rfernandes

Alfresco Parents and Children

Blog Post created by rfernandes on Sep 25, 2013
This post won’t tell you much new if you are already experienced in Alfresco but even then you might found something curious somewhere. So be warned that the audience for this post is mostly the Alfresco newbie that just started playing with this great Open Source ECM platform.



I am often asked about things that are related in a way or another with the parent-child relationship between nodes in Alfresco (folders or documents). Not surprising this is a core concept in Alfresco. So I thought it deserved a dedicated post going through some of the nuances.



 



Javascript API Root Variables 



One of the most common places where a conversation about a node’s parents and children in Alfresco will start is the Alfresco’s server side Javascript API. If we look into it [1]:



 





































Root ObjectType in Script RuntimeDescription
documentorg.alfresco.repo.jscript.ScriptNodeThe current document ScriptNode (if any)
spaceorg.alfresco.repo.jscript.ScriptNodeThe current space ScriptNode (if any). For a script executing from a rule, the space object is the space in which the rule resides. If the rule is inherited, this may not be the expected space.


 



The newbye will naturally assume document always refers to a (content) document and space to a folder. But that’s very far from the truth (although the original root variables names themselves bear a big amount of fault for this). It is in fact better to map it conceptually as following:



 































Root ObjectDescription
documentThe current node ScriptNode.
spaceThe parent node ScriptNode of the current node.


 



If you want to see this in action just create a simple Javascript script as the following:



 

function main() {



     return 'Node: ' + document.name +'\tParent: '+space.name+ '\tDate: ' + new Date().toUTCString();



}



main();


 



Call it as myscript.js (by the way this would be a terrible name for a real production script...) and store it in the Company Home/Data Dictionary/Scripts folder in Alfresco.



This server-side script basically returns a line with the details about the node name and its parent name, besides the date of execution.



So now, if we use the Script Command Processor of Alfresco we can call the script for any node on our repository. We just need to call from our browser an URL like this [2]:



 



http://localhost:8080/alfresco/command/script/execute/workspace/SpacesStore/b9f89106-acb3-458c-9151-0318b1c613dc/workspace/SpacesStore/98ef0384-d882-4839-89d2-40026edd89f9



 



The first uuid belongs to the script’s node reference and the second to the node we want to execute the script against (so you should replace according to your installation and setup). You should get a response similar to this:



Node: test Parent: documentLibrary Date: Wed, 25 Sep 2013 10:10:05 GMT



 



document can be a Space



Just execute the script for a folder in Alfresco and you will see that document will reference the folder’s ScriptNode and less strangely space to its parent folder. This is in fact a very common case with server-side scripting in Alfresco.



 



space can be a Document



This will be most probably more unexpected to some. But if you call the script for an inner child of a document, the space variable will refer to the document and document to the inner child node. And yes, documents can have children in Alfresco and in fact they are very common.



For example when you upload a document in Alfresco Share Document Library you can see with the Node Browser [3] that these documents have children for things like thumbnail, preview and rating. You can use a node reference for one of these child nodes to run the script against and see how your document will be referenced by the space root variable in the Javascript.







The fact that these document children (doclib, webpreview, etc) are not available during normal navigation, be it through Share or file protocols like CIFS, is just because those interfaces were specifically designed (or by their own nature as in case of CIFS wouldn’t adapt to it very easily...) to ignore those objects and corresponding particular kinds of parent-child association used. They just know about the standard parent child association that associates a folder to other children folders or documents.



 



What about rules? (an experiment)



Why rules can’t be defined for documents just like they are for spaces? In fact you can, just configure Share to show the Manage Rules action in a document. If you want to try (you definitely don’t want to do that for real projects) just edit the share-documentlibrary-config.xml and add the corresponding action entry for the action group of document-details. Something like this:



 

<actionGroup id='document-details'>



<action index='100' id='document-download' />



<action index='105' id='folder-manage-rules' />



...


 



When you restart Alfresco you should be able to see now the Manage Rules action on the document details pages. You can create the rule and execute for example a variation [4] (see bellow) of the previously used for any “incoming node inside” your document.



 

var logFile = companyhome.childByNamePath(document.id+'.txt');



if (logFile == null) {



      logFile = companyhome.createFile(document.id+'.txt');



}



if (logFile != null) {



      logFile.content += 'Node: ' + document.name +'\tParent: '+space.name+ '\tDate: ' + new Date().toUTCString() + '\r\n';



}






 



If you execute the rules explicitly from the Manage Rules interface for the document you should see that the script executes as before with the Script Command Processor for each of the document children (doclib, webpreview and rating if there’s one). Except for the rules child itself (created cause of the definition of the document rule), because Alfresco ignores the rules folders as expected (imagine if a rule in a folder was sensitive to the node where it’s defined, it wouldn’t make any sense and that would be definitely unexpected to the end user that don’t see it).



But although this might be fun as an experiment it is not really useful because any rules automation won’t be triggered for non standard folder-document parent child related nodes. So for documents rules will never be triggered for its children (only explicitly as in the experiment we just did). [5]



In any case a script that references a document as space and its inner children as document can still be useful in other contexts.



 



Multiple Parents



This fact is many times ignored by new comers to Alfresco platform, but Alfresco does not limit the number of parents a node may have. Although parents of a node are not completely equivalent between themselves. There’s always one considered to be the primary parent while the others if any are considered to be the secondary parents. The difference between a primary parent and the other secondary parents, is that if a primary parent is deleted the child node is deleted with it while for secondary parents this cascading deletion does not happen.



If you want to see multiple parents in action just save the following javascript as a new script (same as before but with a different name) [6]:



 

var childNodeRef = 'workspace://SpacesStore/08bba651-81d6-4f17-bf8b-06def398b7b8';  



var childNode = search.findNode(childNodeRef); 



document.addNode(childNode); 


 



Replace on the script before the value for node reference by one of a document in your repository.



This script adds your document as a child to any folder you run the script against it, so that the folder becomes a secondary parent of your document.



Execute the script against a folder that is not the actual parent of the document from which you copied the node reference inside the script. You should then see that the same document (it could also be a folder) shows up besides in its original location also as a child of the new folder. This is not a copy but exactly the same document as you can confirm by editing it (and seeing same changes on metadata or content reflected on both places) or just by checking its node reference [7].



And from the node browser you can check that the document has in fact two parents now (one, the first one, which is the primary).







On the Alfresco Share UI you will notice on the head breadcrumb of the document’s page details that, doesn’t matter how you navigate till it (from the primary or secondary parent), the path shown is always the one from the primary parent (which not necessarily may always be ideal but it’s consistent with Share URL’s addressability).



 



An example: Link to Rule Set 



When in Share you Link to Rule Set [8] (in place of creating local rules) Alfresco is in fact leveraging multiple parents for making the ‘hidden’ rule folder of the first folder to gain a new secondary folder parent. You can confirm that again by navigating through the node browser.



 



Javascript Add Node Extension



By the way the javascript API out of the box is limited to what concerns creating parent child associations that not the standard one (as we did before in our script with the addNode method). To have that would be useful in the case we wanted to link a rule set by ourselves through some automated script for example. But Alfresco allows us to extend its Javascript server side API fairly easily with some coding. [9]



You can check this project for an example on how to extend the API for allowing that: https://code.google.com/p/rules-scriptnode-extension-demo/



This extension once applied to Alfresco allows you to use a new root variable called extScriptNode and its method linkRuleSet to do that, or if you wanted to add another specific custom parent child association of your own the method addNode of the new root variable could be leveraged. [10]



Another example: In Situ Records



With Alfresco Enterprise 4.2 and Alfresco Records Management 2.1 we offer the capability to declare in situ records. So that the records can be declared without leaving the original edition collaboration context. This is great of course and make records management so much more useful for the generic end business user. And by the way it’s in fact implemented leveraging multiple parents.



The collaboration document after declared as record gains a new parent (belonging to the RM site) which becomes in fact its primary parent, and the original parent collaboration folder his secondary parent. Also the new option available for hiding a record (available on the original collaboration context after the record declaration) what in fact does is to remove the secondary parent-child association of the record, so that the record can now only be discovered on the Records Manager site.



Back to Javascript API



Now back to our Javascript server side API of Alfresco we are in conditions to refine the initial conceptual description/mapping of those two root variables to:



 































Root ObjectDescription
documentThe current node ScriptNode.
spaceThe primary parent node ScriptNode of the current node.


 



I hope it was useful (or at least relatively fun) this ‘small’ walkthrough by some details around Alfresco’s parents and children nodes.

______________________________________

1. Source: http://docs.alfresco.com/4.1/index.jsp?topic=%2Fcom.alfresco.enterprise.doc%2Freferences%2FAPI-JS-rootscoped.html



2. In general for creating a custom REST HTTP API you should leverage the Alfresco Web Scripts framework



http://docs.alfresco.com/4.1/index.jsp?topic=%2Fcom.alfresco.enterprise.doc%2Fconcepts%2Fws-architecture.html



But for our purposes the Script Command Processor is very handy and does in fact what we want it to do: execute scripts against specific nodes.



3. http://docs.alfresco.com/4.1/index.jsp?topic=%2Fcom.alfresco.enterprise.doc%2Ftasks%2Fadminconsole-nodebrowser.html



4. The script now is writing the same line as before to a document in the repository (with name equal to id of the corresponding node). It it will create the document before writing or append it if already existing. This way we have a “registry” of the script execution.



5. For cases like this you might need to leverage the powerful policies capability of Alfresco:



http://wiki.alfresco.com/wiki/Policy_Component



6. By the way you can notice how in this sample script the variable document is actually referencing a folder.



7. A copy of a node generates another different node, that can be acted separately (for editing, deleting, etc), even if the binary content path for the copied node points to the same location (till an update in one of the nodes happens, branching the content between the nodes).



8. http://docs.alfresco.com/4.1/index.jsp?topic=%2Fcom.alfresco.enterprise.doc%2Ftasks%2Flibrary-folder-rules-manage.html



9. Check http://wiki.alfresco.com/wiki/4.0_JavaScript_API#Adding_Custom_Script_APIs



10. Check the class code for details:



https://code.google.com/p/rules-scriptnode-extension-demo/source/browse/src/main/java/demo/rf/alfresco/script/node/extension/ExtScriptNode.java .

Attachments

Outcomes