cancel
Showing results for 
Search instead for 
Did you mean: 

Adding children to store root

hsjawanda
Champ in-the-making
Champ in-the-making
Hi,

I have been trying a few things, have been getting unexpected results, and now I am confused.  So here are my questions:

Is there anything special about adding a node (say, a folder) directly as a child of a store root? I have a store with protocol "workspace" – will the following code work for adding a folder directly under the store root:


// this.storeRef points to the store I am interested in.
NodeRef rootNode = nodeService.getRootNode(this.storeRef);

// Creating a folder as a direct child of storeRef
ChildAssociationRef childAssocRef = nodeService.createNode(rootNode,
        ContentModel.PROP_CONTAINS, QName.createQName(
                NamespaceService.CONTENT_MODEL_1_0_URI, folderName),
        ContentModel.TYPE_FOLDER);

Does it matter whether I use ContentModel.PROP_CONTAINS or some other QName as the assocTypeQName when adding a child to a store's root?

What are the differences between creating child associations and creating plain-jane associations (NodeService#createAssociation())? I think one of the differences is that (recursive) searching under a parent node will search those nodes related through child associations, but not those related through plain associations – is this correct?

If I don't put any "PATH:" term in my Lucene search, does the whole store get searched? For example, if I construct a query like this:


String query = "+TYPE:\"" + ContentModel.TYPE_FOLDER.toString() + "\"";

will I get back a list of all the folders in the store being searched?  Will the assocTypeQName I use while adding children make a difference to the results of the above query?

I apologize for asking so many questions in a single post, but I am getting confused by some of the results I am seeing :-).

Thanks.
28 REPLIES 28

kevinr
Star Contributor
Star Contributor
Yes you are quite correct - that should be the searchService.

Thanks for spotting that, we'll change it.

Kevin

soeursourire
Champ in-the-making
Champ in-the-making
Sure:-)

I got into troubles again with a page navigation… I would like to add an action in browse.jsp in order to access the list of people and create a user thus I want to have in the list of action "manage users" and when I click on it I open users.jsp. So I was adding this code as follow in browse.jsp but when I click the page does not open and stay on browse.jsp:

<rSmiley TongueermissionEvaluator value="#{NavigationBean.currentNode}" allow="Write" id="ef_eval1">
     <a:actionLink value="#{Fmsg.manage_users}" image="/images/icons/users.gif" action="manageUsers" styleClass="title" actionListener="#{NewUserWizard.setupUsers}" />
</rSmiley TongueermissionEvaluator>

What is wrong here? And what is the currentNode here?

Thanks in advance

kevinr
Star Contributor
Star Contributor
If you want your view (browse.jsp) to be able to navigate to the users.jsp page then you need to add a navigation handler element to the faces-config-navigation.xml file. This is basic JSF knowledge, you should walk through a few basic JSF tutorials on the web to understand how this works.

To add it, edit the faces-config-navigation.xml file, find this section:

   <navigation-rule>
      <from-view-id>/jsp/browse/browse.jsp</from-view-id>
and add this new navigation case:

      <navigation-case>
         <from-outcome>manageUsers</from-outcome>
         <to-view-id>/jsp/users/users.jsp</to-view-id>
      </navigation-case>

The currentNode object is the current space the user is viewing.

This allows the browse.jsp page to navigate to the users.jsp page.

Kevin

soeursourire
Champ in-the-making
Champ in-the-making
Thanks a lot..actually I was just finding my error :?

soeursourire
Champ in-the-making
Champ in-the-making
I have some problems of configurations:
- I developped a sub-class of UsersBean in the web-client but in this class I need to get storeRef. So when I define my bean in the faces-config.xml I wanted to add this:
<managed-property>
           <property-name>storeUrl</property-name>
          <value>${spaces.store}</value>
      </managed-property>   
But this spaces.store is defined in repository side in repository.properties. So should I add a bean in faces-config to call repository.properties or use directly Workspace\\store…?

soeursourire
Champ in-the-making
Champ in-the-making
Why while doing this in my subclass of UsersBean I have credential problems??

NodeRef rootNodeRef = this.nodeService.getRootNode(Repository.getStoreRef());

soeursourire
Champ in-the-making
Champ in-the-making
Please help…I am blocked with this problem of permissions….
I do not understand why I cannot do this code in my class added to the WebClient:

NodeRef rootNodeRef = nodeService.getRootNode(Repository.getStoreRef());

although I added variable nodeService to my class with setNodeService and I added my class bean in faces-config.xml. I also tried to give permission to the connected user to access the nodeService as follow:
this.permissionService.setPermission(nodeService.getRootNode(Repository.getStoreRef()), connectedUsername, this.permissionService.getAllPermission(), true);

Are operations on nodeService only possible from Repository? I guess not seeing that we have this.nodeService.getRootNode(Repository.getStoreRef()) from the class NewUserWizard. How should I choose where to create my classes (under Repository or WebClient)?

Should we use transaction only from the Repository and thus from classes under the Repository project? I am using 3differents transactions in my function finish() of MyNewUserWizard: one for storing properties in my node function, one in my node link and another one for my node person, is it not good? If I create a class in Repository can I call it from my jsp page?

When should I use or not transaction?

Thanks for help

derek
Star Contributor
Star Contributor
You can use the transactions wherever you need them.  You shouldn't decide whether or not put a transaction around some code - if it performs multiple operations as part of a business process, then it should get a transaction.  They will just propogate.  Usually, you would have a single transaction for everything in the finish() method.  You can have 3 nested transactions within that, but if you have 3 completely separate transactions, then if the 3rd fails, the others will still have been committed.  That can't be right.  Perhaps you could post your finish() code.

Mmm.  I think you need to post the method here - otherwise it is going to be difficult to know what is going on.

Somehow, giving admin rights on the root to whatever user logs in doesn't seem like a good idea.  But post the code and we'll see.

Regards

soeursourire
Champ in-the-making
Champ in-the-making
Thanks a lot for your answer… In my function finish() I was using 3 different transactions because I was getting into troubles while using a single one… Maybe I should do like you said one single transactions including 3others transactions… here is the code of my function finish():

public String finish()
   {
      String outcome = FINISH_OUTCOME;
     
      //****************************************************************
      // TODO: implement create new Person object from specified details
      //****************************************************************
     
      UserTransaction tx = null;

      try
      {
         FacesContext context = FacesContext.getCurrentInstance();
         tx = Repository.getUserTransaction(context);
         tx.begin();

         if (this.getEditMode())
         {
            // update the existing node in the repository
            NodeRef nodeRef = this.getPerson().getNodeRef();
           
            Map<QName, Serializable> props = this.nodeService.getProperties(nodeRef);
            props.put(EF_ContentModel.PROP_USERNAME, this.getUserName());
            props.put(EF_ContentModel.PROP_FIRSTNAME, this.getFirstName());
            props.put(EF_ContentModel.PROP_LASTNAME, this.getLastName());
           
            // calculate whether we need to move the old home space or create new
            NodeRef newHomeFolderRef;
            NodeRef oldHomeFolderRef = (NodeRef)this.nodeService.getProperty(nodeRef, EF_ContentModel.PROP_HOMEFOLDER);
            boolean moveHomeSpace = false;
            boolean renameHomeSpace = false;
            if (oldHomeFolderRef != null && this.nodeService.exists(oldHomeFolderRef) == true)
            {
               // the original home folder ref exists so may need moving if it has been changed
               ChildAssociationRef childAssocRef = this.nodeService.getPrimaryParent(oldHomeFolderRef);
               NodeRef currentHomeSpaceLocation = childAssocRef.getParentRef();
               if (this.getHomeSpaceName().length() != 0)
               {
                  if (currentHomeSpaceLocation.equals(this.getHomeSpaceLocation()) == false &&
                      oldHomeFolderRef.equals(this.getHomeSpaceLocation()) == false &&
                      currentHomeSpaceLocation.equals(getCompanyHomeSpace()) == false)
                  {
                     moveHomeSpace = true;
                  }
                 
                  String oldHomeSpaceName = Repository.getNameForNode(nodeService, oldHomeFolderRef);
                  if (oldHomeSpaceName.equals(this.getHomeSpaceName()) == false &&
                      oldHomeFolderRef.equals(this.getHomeSpaceLocation()) == false)
                  {
                     renameHomeSpace = true;
                  }
               }
            }
           
            if (logger.isDebugEnabled())
               logger.debug("Moving space: " + moveHomeSpace + "  and renaming space: " + renameHomeSpace);
           
            if (moveHomeSpace == false && renameHomeSpace == false)
            {
               if (this.getHomeSpaceLocation() != null && this.getHomeSpaceName().length() != 0)
               {
                  newHomeFolderRef = createHomeSpace(this.getHomeSpaceLocation().getId(), this.getHomeSpaceName(), false);
               }
               else if (this.getHomeSpaceLocation() != null)
               {
                  // location selected but no home space name entered,
                  // so the home ref should be set to the newly selected space
                  newHomeFolderRef = this.getHomeSpaceLocation();
                 
                  // set the permissions for this space so the user can access it
                 
               }
               else
               {
                  // nothing selected - use Company Home by default
                  newHomeFolderRef = getCompanyHomeSpace();
               }
            }
            else
            {
               // either move, rename or both required
               if (moveHomeSpace == true)
               {
                  this.nodeService.moveNode(
                        oldHomeFolderRef,
                        this.getHomeSpaceLocation(),
                        EF_ContentModel.ASSOC_CONTAINS,
                        this.nodeService.getPrimaryParent(oldHomeFolderRef).getQName());
               }
               newHomeFolderRef = oldHomeFolderRef;   // ref ID doesn't change
              
               if (renameHomeSpace == true)
               {
                  // change HomeSpace node name
                  this.nodeService.setProperty(newHomeFolderRef, EF_ContentModel.PROP_NAME, this.getHomeSpaceName());
               }
            }
           
            props.put(EF_ContentModel.PROP_HOMEFOLDER, newHomeFolderRef);
            props.put(EF_ContentModel.PROP_EMAIL, this.getEmail());
            props.put(EF_ContentModel.PROP_ORGID, this.getCompanyId());
                       
            this.nodeService.setProperties(nodeRef, props);
           
            try {
               BufferedWriter out = new BufferedWriter(new FileWriter("NodeRefEdit.txt"));
                 out.write("—Noderef—\n");
                   out.write("uuid= ");
                   String uuid = nodeRef.getId();
                   out.write(uuid);
                   out.write("\n");
                   out.close();
             } catch (IOException ioe) {
               System.out.println(ioe.toString());
             }
                       
            // TODO: RESET HomeSpace Ref found in top-level navigation bar!
            // NOTE: not need cos only admin can do this?
         }
         else
         {
            if (this.getPassword().equals(this.getConfirm()))
            {
               if (!this.personService.getUserNamesAreCaseSensitive())
               {
                  this.setUserName (this.getUserName().toLowerCase());
               }
               
               // create properties for Person type from submitted Form data
               Map<QName, Serializable> props = new HashMap<QName, Serializable>(7, 1.0f);
               props.put(EF_ContentModel.PROP_USERNAME, this.getUserName());
               props.put(EF_ContentModel.PROP_FIRSTNAME, this.getFirstName());
               props.put(EF_ContentModel.PROP_LASTNAME, this.getLastName());
               NodeRef homeSpaceNodeRef;
               if (this.getHomeSpaceLocation() != null && this.getHomeSpaceName().length() != 0)
               {
                  // create new
                  homeSpaceNodeRef = createHomeSpace(this.getHomeSpaceLocation().getId(), this.getHomeSpaceName(), true);
               }
               else if (this.getHomeSpaceLocation() != null)
               {
                  // set to existing
                  homeSpaceNodeRef = this.getHomeSpaceLocation();
                  setupHomeSpacePermissions(homeSpaceNodeRef);
               }
               else
               {
                  // default to Company Home
                  homeSpaceNodeRef = getCompanyHomeSpace();
               }
               props.put(EF_ContentModel.PROP_HOMEFOLDER, homeSpaceNodeRef);
               props.put(EF_ContentModel.PROP_EMAIL, this.getEmail());
               props.put(EF_ContentModel.PROP_ORGID, this.getCompanyId());
              
               // create the node to represent the Person
               String assocName = QName.createValidLocalName(this.getUserName());
               NodeRef newPerson = this.personService.createPerson(props);
               
               try {
                   BufferedWriter out = new BufferedWriter(new FileWriter("NodeRef.txt"));
                     out.write("—Noderef New person—\n");
                       out.write("uuid= ");
                       String uuid = newPerson.getId();
                       out.write(uuid);
                       out.write("\n");
                    out.close();
                 } catch (IOException ioe) {
                  System.out.println(ioe.toString());
                }
               
               // ensure the user can access their own Person object
               this.permissionService.setPermission(newPerson, this.getUserName(), this.permissionService.getAllPermission(), true);
              
               if (logger.isDebugEnabled()) logger.debug("Created Person node for username: " + this.getUserName());
              
               // create the ACEGI Authentication instance for the new user
               this.authenticationService.createAuthentication(this.getUserName(), this.getPassword().toCharArray());
              
               if (logger.isDebugEnabled()) logger.debug("Created User Authentication instance for username: " + this.getUserName());
            }
            else
            {
               outcome = null;
               Utils.addErrorMessage(Application.getMessage(context, UsersBean.ERROR_PASSWORD_MATCH));
            }
         }
        
         // commit the transaction
         tx.commit();
        
         // reset the richlist component so it rebinds to the users list
         invalidateUserList();
      }
      catch (Exception e)
      {
         // rollback the transaction
         try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
         Utils.addErrorMessage(MessageFormat.format(Application.getMessage(FacesContext.getCurrentInstance(), ERROR), e
               .getMessage()), e);
         outcome = null;
      }

      //*********************************************************************
      //    TODO: implement create new Function object from specified details
      //*********************************************************************
     
      UserTransaction txFN = null;

      try
      {
         FacesContext context = FacesContext.getCurrentInstance();
         txFN = Repository.getUserTransaction(context);
         txFN.begin();

         if (this.getEditMode())
         {
            // update the existing node in the repository
            NodeRef nodeRefFN = this.getFunction().getNodeRef();
             
            Map<QName, Serializable> propsFN = this.nodeService.getProperties(nodeRefFN);
            propsFN.put(EF_ContentModel.PROP_FN_ID, this.functionId);
            propsFN.put(EF_ContentModel.PROP_FN_DIMTRADE, this.fn_trade);
 
            this.nodeService.setProperties(nodeRefFN, propsFN);
           
            try {
               BufferedWriter out = new BufferedWriter(new FileWriter("NodeRefFNEdit.txt"));
                   out.write("—NodeRefFN —");
                   String uuid2 = nodeRefFN.getId();
                   out.write(uuid2);
                   out.write("\n");
                out.close();
             } catch (IOException ioe) {
               System.out.println(ioe.toString());
             }
         }
         else   //not edit mode.. creation mode
         {
            if (this.getPassword().equals(this.getConfirm()))
            {
               if (!this.personService.getUserNamesAreCaseSensitive())
               {
                  this.setUserName (this.getUserName().toLowerCase());
               }
              
               // Create the node to represent the function
   
               Map<QName, Serializable> propsFN = new HashMap<QName, Serializable>(2);
               propsFN.put(EFContentModel.PROP_FN_ID, this.functionId);
               NodeRef newFunction = this.getFunctionService().createFunction(propsFN);
              
               this.functionId = newFunction.getId();
               propsFN.put(EF_ContentModel.PROP_FN_ID, this.functionId);
               propsFN.put(EF_ContentModel.PROP_FN_DIMTRADE, this.fn_trade);
               String assocNameFN = QName.createValidLocalName(this.functionId);
              
               this.nodeService.setProperties(newFunction,propsFN);
                            
            }
            else
            {
               outcome = null;
               Utils.addErrorMessage(Application.getMessage(context, UsersBean.ERROR_PASSWORD_MATCH));
            }
         }
        
         // commit the transaction
         txFN.commit();
        
         // reset the richlist component so it rebinds to the users list
         invalidateUserList();
      }
      catch (Exception e)
      {
         // rollback the transaction
         try { if (txFN != null) {txFN.rollback();} } catch (Exception tex) {}
         Utils.addErrorMessage(MessageFormat.format(Application.getMessage(FacesContext.getCurrentInstance(), ERROR), e
               .getMessage()), e);
         outcome = null;
      }
     
//    *********************************************************************
      //    TODO: implement create new LinkFunctionPerson object from specified details
      //*********************************************************************
     
      UserTransaction txLINK = null;

      try
      {
         FacesContext context = FacesContext.getCurrentInstance();
         txLINK = Repository.getUserTransaction(context);
         txLINK.begin();

         if (this.getEditMode())
         {
            // update the existing node in the repository
            NodeRef nodeRefLINK = this.getLink().getNodeRef();
             
            Map<QName, Serializable> propsLINK = this.nodeService.getProperties(nodeRefLINK);
            propsLINK.put(EF_ContentModel.PROP_LINK_ID, this.linkId);
            propsLINK.put(EF_ContentModel.PROP_LINK_USERNAME, this.getUserName());
            propsLINK.put(EF_ContentModel.PROP_LINK_FUNCTIONID, this.getFunctionId());
           
            this.nodeService.setProperties(nodeRefLINK, propsLINK);
           
            try {
               BufferedWriter out = new BufferedWriter(new FileWriter("NodeRefLINKEdit.txt"));
                   out.write("—NodeRefLINK —");
                   String uuid2 = nodeRefLINK.getId();
                   out.write(uuid2);
                   out.write("\n");
                out.close();
             } catch (IOException ioe) {
               System.out.println(ioe.toString());
             }
         }
         else   //not edit mode.. creation mode
         {
            if (this.getPassword().equals(this.getConfirm()))
            {
               if (!this.personService.getUserNamesAreCaseSensitive())
               {
                  this.setUserName (this.getUserName().toLowerCase());
               }
              
               // Create the node to represent the function
               //linkId++;   //prendre le uuid du noeud!
              
               Map<QName, Serializable> propsLINK = new HashMap<QName, Serializable>(10);
               propsLINK.put(EF_ContentModel.PROP_LINK_ID, this.linkId);
              
               NodeRef newLink = this.linkService.createLinkFunctionPerson(propsLINK);
              
               this.linkId = newLink.getId();
               // choose that the id of the link will be equal to the node uuid
               propsLINK.put(EF_ContentModel.PROP_LINK_ID, this.linkId);
               propsLINK.put(EF_ContentModel.PROP_LINK_USERNAME, this.getUserName());
               propsLINK.put(EF_ContentModel.PROP_LINK_FUNCTIONID, this.getFunctionId());
               String assocNameLINK = QName.createValidLocalName(this.linkId);
               this.nodeService.setProperties(newLink, propsLINK);
              
               try {
                   BufferedWriter out = new BufferedWriter(new FileWriter("NodeRefLINK.txt"));
                       out.write("—NodeRefLINK NewFunction—");
                       String uuid2 = newLink.getId();
                       out.write(uuid2);
                       out.write("\n");
                       out.write("—FunctionId—");
                       String uuid = this.getFunctionId();
                       out.write(uuid);
                       out.write("\n");
                    out.close();
                 } catch (IOException ioe) {
                   System.out.println(ioe.toString());
               }
              
            }
            else
            {
               outcome = null;
               Utils.addErrorMessage(Application.getMessage(context, UsersBean.ERROR_PASSWORD_MATCH));
            }
         }
        
         // commit the transaction
         txLINK.commit();
        
         // reset the richlist component so it rebinds to the users list
         invalidateUserList();
      }
      catch (Exception e)
      {
         // rollback the transaction
         try { if (txLINK != null) {txLINK.rollback();} } catch (Exception tex) {}
         Utils.addErrorMessage(MessageFormat.format(Application.getMessage(FacesContext.getCurrentInstance(), ERROR), e
               .getMessage()), e);
         outcome = null;
      }
     
     
      return outcome;
   }

Also for my problem of permission, I created a class on WebClient side in order to display all person who has a trade < to the trade of the connected user but I get into troubles to access the root node. Here is my code:

public List<Node> getSubPersons()
   {
      List<NodeRef> personNodesRef = null;
      List<Node> personNodes =  new ArrayList<Node>();
      
     String connectedUsername = this.getAuthenticationService().getCurrentUserName();
     
      if(connectedUsername.compareTo("admin")==0)
      {
             personNodes = Repository.getUsers(FacesContext.getCurrentInstance(), this.getNodeService(),
                         this.getSearchService());
       }
       else
       {
            UserTransaction tx = null;
            try
            {
               tx = Repository.getUserTransaction(FacesContext.getCurrentInstance(), true);
               tx.begin();
              
              FacesContext context = FacesContext.getCurrentInstance();
              EF_LinksFunctionPersonBeanService linksFunctionPersonBeanService = (EF_LinksFunctionPersonBeanService)FacesContextUtils.getRequiredWebApplicationContext(context).getBean("linksFunctionPersonBeanService");
              EF_FunctionsBeanService functionsBeanService = (EF_FunctionsBeanService)FacesContextUtils.getRequiredWebApplicationContext(context).getBean("functionsBeanService");
              
                //get functionIds of the functions that the connected user has
               List<SelectItem> functionIds = linksFunctionPersonBeanService.getFunctionIdsWithUsername(connectedUsername);
              //get higher function properties levels between these functions (with functionId)
              int higherTradeLevel = functionsBeanService.getHigherTradeLevelFrom(functionIds);
              //get the functionIds of the person that have lower level for all their function properties
      List<SelectItem> personFunctionIds = functionsBeanService.getSubPersonFunctionIds(higherTradeLevel);
                 
             //get all usernames linked to these functionIds
      List<SelectItem> usernames = linksFunctionPersonBeanService.getUsernamesFrom(personFunctionIds);
                    
          //change the permission of the nodeService for the username ???
         //this.permissionService.setPermission(nodeService.getRootNode(Repository.getStoreRef()), connectedUsername, this.permissionService.getAllPermission(), true);

      MethodSecurityInterceptor nodeSecurity = (MethodSecurityInterceptor)FacesContextUtils.getRequiredWebApplicationContext(context).getBean("NodeService_security");
      NodeRef rootNodeRef = this.getNodeService().getRootNode(Repository.getStoreRef()); //PROBLEM HERE

      for(SelectItem username : usernames)
           {
                  //definition of "username" conversion into ef variable
                  QueryParameterDefinition[] defs = new QueryParameterDefinition[1];
                  DataTypeDefinition typeText = this.getDictionaryService().getDataType(DataTypeDefinition.TEXT);
                  defs[0] = new QueryParameterDefImpl(QName.createQName("ef", "var", this.getNamespacePrefixResolver()), typeText, true,
                       username.getLabel());
              
                  //all node Link that have a link_functionId = fnId.getLabel()
                  //should be only one node! 1 id only for 1 function to do that choose only the first node found
                  personNodesRef = this.getSearchService().selectNodes(rootNodeRef, PEOPLE_FOLDER
                       + "/ef:EF_person[@cm:userName = $ef:var]", defs, this.getNamespacePrefixResolver(), false);
                 
                  //redundancy removed here
                  MapNode node = new MapNode(personNodesRef.get(0));
                 personNodes.add(node);
           }
          
           // commit the transaction
            tx.commit();

         }
         catch (InvalidNodeRefException refErr)
         {
            Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
                  FacesContext.getCurrentInstance(), Repository.ERROR_NODEREF), new Object[] {"root"}) );
            personNodes = Collections.<Node>emptyList();
            try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
         }
         catch (Exception err)
         {
            Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
                  FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err );
            personNodes = Collections.<Node>emptyList();
            try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
         }
       }
     
      return personNodes;
   }