Allow contributors to add limited number of a node - jahia

I want to allow my contributors to add a limited number of a node in Edit Mode. Here's what I have right now in my definitions.cnd:
[jnt:parent] > jnt:content, jmix:basicContent, mix:title
- intro (string, richtext)
+ * (jnt:child)
This allows contributors to add as many node child they want. I want to limit that number to 2. I tried + 2 (jnt:child) but that didn't change a thing.
How to achieve my goal?

It's not possible to specify how many child you want to add.
As workaround, it's possible to do that :
[jnt:parent] > jnt:content, jmix:basicContent, mix:title
- intro (string, richtext)
+ firstChild (jnt:child)
+ secondChild (jnt:child)
Here, contributors would only be able to add these 2 node "child", with these names.

That is not possible in cnd. Here is a link to the source docs: https://jackrabbit.apache.org/jcr/node-type-notation.html It's either one or many.
The way I have controled that in the past is to use logic to in the ui to remove the option of adding additional nodes, and logic in the backing handlers to discard any attempts to add nodes.

Related

how to group observations in stata

I'm a beginner with stata so this question might be easy for some of you.
I have a Dataset with Firmspecific data. One variable is Branche which contains the following lines of business: Consumer, Utilities, Food/Beverage, Technology, Logistics/Transportation, Retail, Insurance etc.
Now I want to form groups, for example the group Consumer which should contain Retail, Food/Beverages, Consumer but with the command generate Consumer = Consumer Retail Food/Beverages it doesn't work. Does anyone know what the right command would be? Thanks!
You can use user-written string recode command strrec:
ssc install strrec
strrec Branche ("Consumer" "Retail" "Food/Beverage" = 1 "Consumer"), gen(trunk)
You will need to add additional categories as you see fit. This creates a new variable, trunk, that has labeled integer(s).
You can refer to particular trunks like this:
list if trunk == 1
list if trunk == "Consumer":trunk
The reason I used an integer with value labels rather than a string is that some of the panel data commands do not like string IDs. I am guessing you are headed that route.

Summing XML Data in MSWord Mail Merge

I have a report card written in Word that uses an XML file for its input. In the XML file, if a student remains in the same section all three trimesters there will be one node for that class; if they change sections at the trimester they'll have one node for each section. The nodes look something like this (greatly simplified):
<ReportCardSectionFB Abs1="2" Abs2="11" CourseID="ELMATH1" CourseTitle="Math" PeriodStart="3" TeacherName="Jones, Jennifer" TermCode="Year" SectionID="ELMATH1-4" />
<ReportCardSectionFB Abs1="1.50" Abs2="6" CourseID="ELMATH1" CourseTitle="Math" PeriodStart="3" TeacherName="Smith, Tina" TermCode="Year" SectionID="ELMATH1-3" />
There is no indicator within the XML as to which trimester the node belongs to.
In the Word document, we're pulling the absence data with the following mail merge command:
{MERGEFIELD "ReportCardSectionFB[#PeriodStart='3']/ #Abs1" \# 0.# \* MERGEFORMAT }
That's not working in this situation: it only gets the absence data from the first node it comes across, i.e.: 2.0. Is there a way to get the sum of #Abs1 for all period 3 classes, i.e.: 3.5? If not, is there a way to only get the last #Abs1 for period 3, i.e.: 1.5?
I recommend you to use this 3rd party product, which can use xml as input and is capable of merging it with MS Word template. I is also much more powerful than the built-in Word's mail merge. You can see some examples here.
You could also try summing the absences in Synergy - there's a new checkbox under AttDef1, 2, etc. that adds up all the absences for the data range - Include all day data for the entire date range regardless of section enrollment or section timeframe. That way the absences should be the same for each section, if that works for your district.
You can also try the SET function in Word to nest the MERGEFIELDS as bookmarks and use the Word operator functions to then add the bookmarks.

What's the right way to expand filtered nodes in ivh-treeview?

Per the discussion here, currently the ivh-treeview Angular library does not expand collapsed nodes when the tree is filtered and a leaf node matches the filter.
Would the right way to implement this behavior be to add an ng-change handler to the input element used for the filter text and then query the tree in the containing controller (thus, doing it manually)?
There doesn't appear to be any other mechanism by which to detect if the filter is changed.
BTW, there exists no ivh-treeview tag so I can't really tag this properly. Apologies if I've hijacked someone else's tag. That said it appears to be the tag used for other ivh-treeview related questions.
There's really no way to do this elegantly I'm afraid. The best you can do is expand the entire tree (with expandRecursive) when you detect the filter is non-empty (or past some threshold). By completely expanding the tree you get to "show filtered nodes" by virtue of the fact that everything else is hidden by ivhTreeview. That's the easy part. The hard part is when there's no longer a filter how do you restore the tree to it's previous partially-expanded state.
If I had to do it I'd probably end up walking the tree to grab the expanded state from each node before the recursive expand then restore that state when the filter is removed. This would clobber collapse/expand actions while there was a filter in play... you could handle that too but things start to get hairy very quickly. E.g.:
var isExpanded = ivhTreeviewOpts().expandedAttribute
// When the filter becomes non-empty
ivhTreeviewBfs(myTree, function(node) {
node.savedExpandedState = n[isExpanded]
})
ivhTreeviewMgr.expandRecursive(tree)
// When the filter becomes empty
ivhTreeviewBfs(myTree, function(node) {
node[isexpanded] = node.savedExpandedState
})
Here's a rough demo: http://jsbin.com/jijoma/3/edit?html,js,output
Hope that helps!

Query multiple elements without specifying the element name

This may be a silly question, but is it possible to make a query using XPath without specifying the element name?
Normally I would write something like
//ElementName[#id = "some_id"]
But the thing is I have many (about 40) different element types with an id attribute and I want to be able to return any of them if the id fits. But I don't want to make this call for each type individually. Is it possible to search all of them at once, regardless of the name?
I am using this in an XQuery script, if that offers any help.
use * instead of name //*[#id = "some_id"]
It might be more efficient to look directly at the #id elements - //* will work, but will initially return every node in the document and then filter!
That may not matter in a small document, of course. but here's an alternative:
//#id[.="some_id"]/..

What's the standard algorithm for syncing two lists of related objects?

I'm pretty sure this must be in some kind of text book (or more likely in all of them) but I seem to be using the wrong keywords to search for it... :(
A recurring task I'm facing while programming is that I am dealing with lists of objects from different sources which I need to keep in sync somehow. Typically there's some sort of "master list" e.g. returned by some external API and then a list of objects I create myself each of which corresponds to an object in the master list (think "wrappers" or "adapters" - they typically contain extended information about the external objects specific to my application and/or they simplify access to the external objects).
Hard characteristics of all instances of the problem:
the implementation of the master list is hidden from me; its interface is fixed
the elements in the two lists are not assignment-compatible
I have full control over the implementation of the slave list
I cannot control the order of elements in the master list (i.e. it's not sortable)
the master list does either not provide notification about added or removed elements at all or notification is unreliable, i.e. the sync can only happen on-demand, not live
simply clearing and rebuilding the slave list from scratch whenever it's needed is not an option:
initializing the wrapper objects should be considered expensive
other objects will hold references to the wrappers
Additional characteristics in some instances of the problem:
elements in the master list can only be identified by reading their properties rather than accessing them directly by index or memory address:
after a refresh, the master list might return a completely new set of instances even though they still represent the same information
the only interface for accessing elements in the master list might be a sequential enumerator
most of the time, the order of elements in the master list is stable, i.e. new elements are always added either at the beginning or at the end, never in the middle; however, deletion can usually occur at any position
So how would I typically tackle this? What's the name of the algorithm I should google for?
In the past I have implemented this in various ways (see below for an example) but it always felt like there should be a cleaner and more efficient way, especially one that did not require two iterations (one over each list).
Here's an example approach:
Iterate over the master list
Look up each item in the "slave list"
Add items that do not yet exist
Somehow keep track of items that already exist in both lists (e.g. by tagging them or keeping yet another list)
When done, iterate over the slave list and remove all objects that have not been tagged (see 4.) and clear the tag again from all others
Update 1
Thanks for all your responses so far! I will need some time to look at the links.
[...] (text moved to main body of question)
Update 2
Restructered the middle-paragraph into a (hopefully) more easily parseable bullet lists and incorporated details added later in the first update.
The 2 typical solutions are:
1. Copy the master list to the sync list.
2. Do an O(N*N) comparison between all element pairs.
You've excluded the smart options already: shared identity, sorting and change notifications.
Note that it's not relevant whether the lists can be sorted in a meaningful way, or even completely. For instance, when comparing two string lists, it would be ideal to sort alphabetically. But the list comparison would still be more efficient if you'd sort both lists by string length! You'd still have to do a full pairwise comparison of strings of the same length, but that will probably be a much smaller nummber of pairs.
This looks like the set reconciliation problem i.e. the problem of synchronizing unordered data. A question on SO was asked on this: Implementation of set reconciliation algorithm.
Most of the references on google are to technical paper abstracts.
Often the best solution to such problems is to not solve them directly.
IF you really can't use a sorted binary searchable container in your part of the code (like a set or even a sorted vector) then...
Are you very memory bound? If not then I'd just create a dictionary (an std::set for example) containing the contents of one of the lists and then just iterate over the second which I want o sync with the first.
This way you're doing nlogn to create the dictionary (or nX for a hash dictionary depending on which will be more efficient) + mlogn operations to go over the second list and sync it (or just MY) - hard to beat if you really have to use lists in the first place - it's also good you do it only once when and if you need it and it's way better then keeping the lists sorted all the time which would be a n^2 task for both of them.
It looks like a fellow named Michael Heyeck has a good, O(n) solution to this problem. Check out that blog post for an explanation and some code.
Essentially, the solution tracks both the master and slave lists in a single pass, tracking indices into each. Two data structures are then managed: a list of insertions to be replayed on the slave list, and a list of deletions.
It looks straightforward and also has the benefit of a proof of minimalism, which Heyeck followed up with in a subsequent post. The code snippet in this post is more compact, as well:
def sync_ordered_list(a, b):
x = 0; y = 0; i = []; d = []
while (x < len(a)) or (y < len(b)):
if y >= len(b): d.append(x); x += 1
elif x >= len(a): i.append((y, b[y])); y += 1
elif a[x] < b[y]: d.append(x); x += 1
elif a[x] > b[y]: i.append((y, b[y])); y += 1
else: x += 1; y += 1
return (i,d)
Again, credit to Michael Heyeck.
In the C++ STL the algorithm is called set_union. Also, implementing the algorithm is likely to be a lot simpler if you do the union into a 3rd list.
I had such problem in one project in the past.
That project had one master data source and several clients that update the data independently and in the end all of them have to have the latest and unified set of data that is the sum of them.
What I did was building something similar to the SVN protocol, in which every time I wanted to update the master database (which was accessible through a web service) I got the revision number. Updated my local data store to that revision and then commited the entities that aren't covered by any revision number to the database.
Every client has the ability to update it's local data store to the latest revision.
Here is a Javascript version of Michael Heyek's python code.
var b= [1,3,8,12,16,19,22,24,26]; // new situation
var a = [1,2,8,9,19,22,23,26]; // previous situation
var result = sync_ordered_lists(a,b);
console.log(result);
function sync_ordered_lists(a,b){
// by Michael Heyeck see http://www.mlsite.net/blog/?p=2250
// a is the subject list
// b is the target list
// x is the "current position" in the subject list
// y is the "current position" in the target list
// i is the list of inserts
// d is the list of deletes
var x = 0;
var y = 0;
var i = [];
var d = [];
var acc = {}; // object containing inserts and deletes arrays
while (x < a.length || y < b.length) {
if (y >= b.length){
d.push(x);
x++;
} else if (x >= a.length){
i.push([y, b[y]]);
y++;
} else if (a[x] < b[y]){
d.push(x);
x++;
} else if (a[x] > b[y]){
i.push([y, b[y]]);
y++;
} else {
x++; y++;
}
}
acc.inserts = i;
acc.deletes = d;
return acc;
}
Very brute-force and pure technical approach:
Inherit from your List class (sorry don't know what is your language). Override add/remove methods in your child list class. Use your class instead of the base one. Now you can track changes with your own methods and synchronize lists on-line.

Resources