Efficient way to get nodes X level deep - dataset

I have a 4 levels deep node structure, where the top most level is made of 1 root node.
What I want to do is get all nodes in the 4th level for which a certain property(ies) is true, for example:
get all 4th level nodes where nodePropertyX == true.
Now, I could do this with a for-each loop, and iterate all the items in the levels above, but I have the feeling it would be inefficient.
How can I do it in a better more efficient way ? Is there a way to maybe cache my dataset? (I'm returning results as a datatable) ?
What is the preferrable method: using C# control (.ascx) or razor script (.cshtml)?

Depending on what you want to do with those nodes, you may use razor, macros and the built-in caching abilities for macros to cache the output of the macro:
Here's how to get all nodes at the 4th level from the root node having a property nodePropertyX which equals value :
#foreach (var item in #Model.AncestorOrSelf().Descendants()
.Where("Visible")
.Where("level=4")
.Where("nodePropertyX == \"value\""))
{
#item.Name
}
Place this code in a Scripting file (Section Developer, node Scripting Files), create a macro using this scripting file, and insert the macro wherever (on any template) you want to display the list of those nodes.
In order to cache the output of the macro, select the macro and set the appropriate properties (Cache Period, Cache By Page and Cache Personalized).

Related

How to pass a two dimensional list/array between groovy scripts in soap ui?

Problem statement: We need a way to pass a two dimensional list (or array) from one groovy script to other scripts ( to assert values from multiple DB2 tables in other scripts].
Some Background:
Step1: Based on our input xml payload we are capturing the list of nodes (and child elements) in a two dimensional list [][]. [Done]
Step2: Now we want to use the values from each of this list to assert with respect to values in DB2 tables [Also done, however keeping both step1 and step2 in same groovy script].
What we want is to to be able to pass the 2dimensional list from step1 in step2. Specially important since we have multiple tables and we dont want to either add all table steps in one big groovy script Or to duplicate step1 code in each Db2 validataion script.
We read about setting each element value from list at test case level and then reconstructing the array back but we are hesitating to use that method due to (varying &) huge size of list elements (in thousands). Question is: Are there any clean ways to achieve this?
Thanks!
As you are aware of the limitation of the earlier solution, which would only work (sharing of object between the groovy scripts) if the test case is run and does not work if individual steps are run.
Here I want to provide an approach which over comes that by using groovy's meta programming.
In script 1, have the below code:
import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase
WsdlTestCase.metaClass.myList = [1,2,3,4,5]
In script 2, have the below code:
log.info "From script 2: ${context.testCase.myList}"
assert [1,2,3,4,5] == context.testCase.myList
The above even works if individual steps are run.
Hope this is helpful.
EDIT: come to understand that user required to update the list repeatedly and with metaClass user couldn't update the list. Here is the alternative:
import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase
WsdlTestCase.metaClass.myObject = new Expando(myList: [1,2,3,4,5])
log.info "list initialized: ${context.testCase.myObject.myList}"
WsdlTestCase.metaClass.myObject = new Expando(myList: [1,2,3,4,5,6,7])
log.info "list updated: ${context.testCase.myObject.myList}"
You can use context
That's real working Groovy Script steps.
step1:
def array = ['Kyiv', 'Boryspil', 'Kharkiv', "L'Viv", "Odesa"]
context.setProperty('cities', array)
log.info( 'script1: '+array )
step2:
def array = context.getProperty('cities')
log.info( 'script2: '+array )
assert array.size()>0
Note:
If you run just one step, then there will be absolutely
independent context.
But if you run the whole testcase then there will be context shared
for the whole testcase.
You can use Run from here context menu in your test case window to run from exact step.

C: deleting elements mid array and have previous pointers working

I have several arrays like this (please ignore specific names):
static resource_t coap_cmp_res[MAX_CMPS];
e.g. [cmp1,cmp2,cmp3,cmp4,cmp5,0,0,0]
and a code that uses these elements, for example, coap_cmp_res[4] (cmp5) is associated with a REST resource, call it Res5.
At a certain point in time, I delete an element in that array at position x like this:
rest_deactivate_resource(&coap_cmp_res[x]);
e.g. for x = 2
[cmp1,cmp2,0,cmp4,cmp5,0,0,0]
What I then would like to do is have a single continuous array again like this
e.g. [cmp1,cmp2,cmp4,cmp5,0,0,0,0]
What I do currently is:
for(UInt8 i = x; i < MAX_CMPS; i++){
coap_cmp_res[i] = coap_cmp_res[i+1];
}
which gives [cmp1,cmp2,cmp4,cmp5,cmp5,0,0,0]
then I manually set the last non-zero element to 0.
e.g. [cmp1,cmp2,cmp4,cmp5,0,0,0,0]
So, this looks good, but the problem is that the Res5 is still associated with coap_cmp_res[4] and thus now the value 0, instead of cmp5, which is not what I desire.
I could deactivate and reactivate every resource after x in the array to have the associations working again, but was wondering if there was a more efficient way to go about this.
Hopefully this makes sense.
As the proverb says: "add a level of indirection". An array of resource_t* that point into coap_cmp_res and are stable. Then have Rea5 associated with a pointer, and use the indirection to reach into a valid entry.
static resource_t coap_cmp_res_data[MAX_CMPS];
static resource_t* coap_cmp_res_ptrs[MAX_CMPS]; // points into coap_cmp_res_data
When you remove an element, you update the entries in coap_cmp_res_ptrs, without moving them, and shrink coap_cmp_res_data. Any resource will still refer to the same position in coap_cmp_res_ptrs, and the indirection will take it to the current location of the resource.
An alternative approach, which may prove better in your case (you'd have to profile), is to use node based storage. I.e a linked list.

I have MDLAsset created from an SCNScene. How do I extract MDLMeshs, MDLCamera(s), and MDLLights?

I am struggling trying to traverse an MDLAsset instance created by loading an SCNScene file (.scn).
I want to identify and extract the MDLMeshs as well as camera(s) and lights. I see no direct way to do that.
For example I see this instance method on MDLAsset:
func childObjects(of objectClass: Swift.AnyClass) -> [MDLObject]
Is this what I use?
I have carefully labeled things in the SceneKit modeler. Can I not refer to those which would be ideal. Surely, there is a dictionary of ids/labels that I can get access to. What am I missing here?
UPDATE 0
I had to resort to pouring over the scene graph in the Xcode debugger due to the complete lack of Apple documentation. Sigh ...
A few things. I see the MDLMesh and MDLSubmesh that is what I am after. What is the traversal approach to get it? Similarly for lights, and camera.
I also need to know the layout of the vertex descriptors so I can sync with my shaders. Can I force a specifc vertex layout on the parsed SCNScene?
MDLObject has a name (because of its conformance to the MDLNamed protocol), and also a path, which is the slash-separated concatenation of the names of its ancestors, but unfortunately, these don't contain the names of their SceneKit counterparts.
If you know you need to iterate through the entire hierarchy of an asset, you may be better off explicitly recursing through it yourself (by first iterating over the top-level objects of the asset, then recursively enumerating their children), since using childObjects(of:) repeatedly will wind up internally iterating over the entire hierarchy to collect all the objects of the specified type.
Beware that even though MDLAsset and MDLObjectContainerComponent conform to NSFastEnumeration, enumerating over them in Swift can be a little painful, and you might want to manually extend them to conform to Sequence to make your work a little easier.
To get all cameras,
[asset childObjectsOfClass:[MDLCamera class]]
Similarly, to get all MDLObjects,
[asset childObjectsOfClass:[MDLObjects class]]
Etc.
MDLSubmeshes aren't MDLObjects, so you traverse those on the MDLMesh.
There presently isn't a way to impose a vertex descriptor on MDL objects created from SCN objects, but that would be useful.
One thing you can do is to impose a new vertex descriptor on an existing MDL object by setting a mesh's vertexDescriptor property. See the MDLMesh.h header for some discussion.

Winform treeview sorted property is slow

I have a winforms TreeView control with the Sorted property set to true. I also override the default sorter by assigning and instance of IComparer to the TreeViewNodeSorter property.
Unfortunately adding a few thousand nodes using the AddRange function takes perhaps 10 seconds. If I set Sorted to false the AddRange function is < 1/2 second. (please no discussions about the validity of adding so many nodes)
Aha I hear you say.. there is a problem in my IComparer object. Not according to the profiler. Barely any time is spent in the sorting object and yet the AddRange function is right at the top of the list of slow functions.
The problem is easy to replicate in a test project. Simply create a list of TreeNodes and add it to the an existing expanded tree node using the AddRange function. This will use the default sort on the tree text - again it is disproportionately slow.
To demonstrate how disproportionately slow it is if I disable the Sorted property in the test probject and use the List<T>.Sort function (with a delegate that compares the Text of the nodes) on my list of nodes before adding them to the tree there is virtually no delay.
This leads to the workaround of sorting the nodes manually before using AddRange. That's OK but it means a lot of work to find the correct insertion point when adding nodes to an existing set of child nodes - rather less convenient than simply setting Sorted to true.
Is there anyway to speed up the behaviour?
EDIT - it seems the only way is to sort before adding.. it's a bit of a hassle but I came up with the following extension method:
public static void AddSortedRange(this TreeNodeCollection existingNodes, IList<TreeNode> nodes, TreeView treeView, IComparer sorter)
{
TreeNode[] array = new TreeNode[nodes.Count + existingNodes.Count];
existingNodes.CopyTo(array, 0);
nodes.CopyTo(array, existingNodes.Count);
Array.Sort(array, sorter);
treeView.BeginUpdate();
existingNodes.Clear();
existingNodes.AddRange(array);
treeView.EndUpdate();
}
It is quicker to copy the existing nodes to an array, append the new nodes, sort the array and then replace that trying to manipulate nodes inline in the tree view - the slowest operation in the above code is the existingNodes.Clear() call
The performance problems you have are related to the fact that you are adding items to a sorted TreeView. What happens behind the scenes when you add to a sorted list is that for each item that you are adding, it tries to find it's place, which means that it needs to go through the whole list for each item, now imagine how many iteration that makes for each new item :)
What you can do is this:
TreeView tv = new TreeView(); // Just so I have a TreeView variable
TreeNode[] nodes = ... // Well, your list of nodes that you want to add
tv.SuspendLayout();
tv.Sorted = false;
tv.Nodes.Clear();
tv.Nodes.AddRange( nodes );
tv.Sorted = true;
tv.ResumeLayout();
For performance reasons we are using the SuspendLayout/ResumeLayout methods to disable the painting process used by the TreeView when manipulating it's items, which we would cause by removing the items and then adding them as well, since it would need to repaint to add the new item that you are adding (for each of the items).
Right before we are doing any changes to the Nodes Collection we have to call Sorted = false; to disable the sorting (this is just temporary - the user will not see any changes because of SuspendLayout).
Then just add the items to the collection (since the TreeView is not sorted for the time being it should be really quick).
Then we enable the sorting again by calling Sorted = true; setting the Sorted Property to true will cause for the collection to do a sort.
This way, the sort will be performed only once (and therefore the TreeView will just go once through the items).
One more thing, if you have a custom sorter defined for the ListView (tv.ListViewItemSorter), set it to null before adding the items as well, just temporary of course, re-enable it again before the ResumeLayout call.
I experienced a locking situation using the Sort() method.
It worked fine for weeks, then once, it stucks, stucking my application with 25% CPU in the task manager.
var allTags = _TagEngine.GetTags(1, force);
try
{
TagTree.BeginUpdate();
TagTree.Nodes.Clear();
foreach (var rec in allTags)
{
... adding nodes in the tree
}
TagTree.Sort(); // <= stuck here !
}
finally
{
TagTree.EndUpdate();
}
So I watch inside the Sort() method using a decompiler, and I noticed it handles already the BeginUpdate/EndUpdate feature internally.
Then I moved the TagTree.Sort() outside the BeginUpdate/EndUpdate, and it works fine since.
var allTags = _TagEngine.GetTags(1, force);
try
{
TagTree.BeginUpdate();
TagTree.Nodes.Clear();
foreach (var rec in allTags)
{
... adding nodes in the tree
}
}
finally
{
TagTree.EndUpdate();
}
TagTree.Sort();
I hardly understood what happened here. Why it worked in the past, and suddenly stoped. Frankly, I did not had time enough to dig further and anyway, the most important is here : it works again.
I made a simple extension to the TreeView control. It is very fast. It moves internal storage to a Dictionary which makes a huge difference. In my real world example I have 100000 records that I need to load. It took 37 minutes before, but now it takes 2.2 seconds!!
You can find example and code on CodeProject: http://www.codeproject.com/Articles/679563/Fast-TreeView

Graph-Traversal: How do I query for "friends and friends of friends" using Gremlin

In my graph database I have Branches and Leaves. Branches can "contain" Leaves and Branches can "contain" Branches.
How, using Gremlin, can I find all leaves for a given branch, that are directly or indirectly related to it?
I got this to work in Cypher:
START v=node(1) MATCH v-[:contains*1..2]->i RETURN v,i
Where the *1..2 means "friends and friends of friends".
I thought maybe LoopV was the way forward, but I just get an Exception:
Error reading JArray from JsonReader. Current JsonReader item is not an array: String
You can do the following in Gremlin 1.4+.
g.v(1).out('contains').loop(1){true}{it.out('contains').count() == 0}
This says:
Start at vertex with id 1
Take the outgoing "contains" edges.
Loop over the out('contains') section.
Loop "infinitely" (make sure your tree doesn't have loops in it)
Emit only those vertices touched that don't have more outgoing 'contains'-edges. (i.e. the leaves)
However, looking at what you wanted from Cypher, it looks like you only want 2 steps. Thus, to do that, simply do:
g.v(1).out('contains').loop(1){it.loops < 3}
Perhaps I misunderstood your question --- either way, that should give you enough to play with.

Resources