diff --git a/config/alfresco/public-services-security-context.xml b/config/alfresco/public-services-security-context.xml index e4acc0def2..b793a67300 100644 --- a/config/alfresco/public-services-security-context.xml +++ b/config/alfresco/public-services-security-context.xml @@ -382,7 +382,7 @@ org.alfresco.service.cmr.repository.NodeService.getPaths=ACL_NODE.0.sys:base.ReadProperties org.alfresco.service.cmr.repository.NodeService.getStoreArchiveNode=ACL_NODE.0.sys:base.Read org.alfresco.service.cmr.repository.NodeService.restoreNode=ACL_NODE.0.sys:base.DeleteNode,ACL_NODE.1.sys:base.CreateChildren - org.alfresco.service.cmr.repository.NodeService.getNodesWithoutParentAssocsOfType=ACL_NODE.0.sys:base.ReadProperties,AFTER_ACL_NODE.sys:base.ReadProperties + org.alfresco.service.cmr.repository.NodeService.getChildAssocsWithoutParentAssocsOfType=ACL_NODE.0.sys:base.ReadProperties,AFTER_ACL_NODE.sys:base.ReadProperties diff --git a/source/java/org/alfresco/repo/avm/AVMNodeService.java b/source/java/org/alfresco/repo/avm/AVMNodeService.java index b5b3fd17ff..b606f94e59 100644 --- a/source/java/org/alfresco/repo/avm/AVMNodeService.java +++ b/source/java/org/alfresco/repo/avm/AVMNodeService.java @@ -1885,11 +1885,10 @@ public class AVMNodeService extends AbstractNodeServiceImpl implements NodeServi } /* (non-Javadoc) - * @see org.alfresco.service.cmr.repository.NodeService#getNodesWithoutParentAssocsOfType(org.alfresco.service.cmr.repository.StoreRef, org.alfresco.service.namespace.QName, org.alfresco.service.namespace.QName) + * @see org.alfresco.service.cmr.repository.NodeService#getChildAssocsWithoutParentAssocsOfType(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName) */ - public Collection getNodesWithoutParentAssocsOfType(StoreRef storeRef, QName nodeTypeQName, - QName assocTypeQName) + public Collection getChildAssocsWithoutParentAssocsOfType(NodeRef parent, QName assocTypeQName) { throw new UnsupportedOperationException("AVM does not support this operation."); - } + } } diff --git a/source/java/org/alfresco/repo/domain/hibernate/Node.hbm.xml b/source/java/org/alfresco/repo/domain/hibernate/Node.hbm.xml index 90e82dd1c8..da717f78c7 100644 --- a/source/java/org/alfresco/repo/domain/hibernate/Node.hbm.xml +++ b/source/java/org/alfresco/repo/domain/hibernate/Node.hbm.xml @@ -812,4 +812,42 @@ a.child_node_id IS NULL + + + + + + + + + + + + + + select + z1.id, + z1.type_qname_id, + z1.qname_ns_id, + z1.qname_localname, + z1.child_node_name, + z1.child_node_name_crc, + z1.is_primary, + z1.assoc_index, + n.id, + s.protocol, + s.identifier, + n.uuid + FROM + (alf_node n + JOIN alf_store s ON (s.id = n.store_id) + JOIN alf_child_assoc z1 ON (z1.parent_node_id = :parentId and z1.child_node_id = n.id)) + LEFT OUTER JOIN + (alf_child_assoc a + JOIN alf_child_assoc z2 ON (z2.parent_node_id = :parentId AND z2.child_node_id = a.parent_node_id )) + ON (a.child_node_id = n.id AND a.type_qname_id = :assocTypeQNameID) + WHERE + a.child_node_id IS NULL + + diff --git a/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java b/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java index 6bd2d931c5..52849d9ecc 100644 --- a/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java +++ b/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java @@ -1631,24 +1631,30 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl addMissingAspects(sourceNodePair, assocTypeQName); return assocRef; - } - - public Collection getNodesWithoutParentAssocsOfType(final StoreRef storeRef, final QName nodeTypeQName, - final QName assocTypeQName) + } + + public Collection getChildAssocsWithoutParentAssocsOfType(NodeRef parent, QName assocTypeQName) { - final Collection results = new LinkedList(); + // Get the parent node + Pair nodePair = getNodePairNotNull(parent); + Long parentNodeId = nodePair.getFirst(); - NodeDaoService.NodeRefQueryCallback callback = new NodeDaoService.NodeRefQueryCallback() + final List results = new ArrayList(100); + + NodeDaoService.ChildAssocRefQueryCallback callback = new NodeDaoService.ChildAssocRefQueryCallback() { - public boolean handle(Pair nodePair) + public boolean handle(Pair childAssocPair, Pair parentNodePair, + Pair childNodePair) { - results.add(nodePair.getSecond()); + results.add(childAssocPair.getSecond()); return true; } }; - nodeDaoService.getNodesWithoutParentAssocsOfType(storeRef, nodeTypeQName, assocTypeQName, callback); + // Get the child associations that meet the criteria + nodeDaoService.getChildAssocsWithoutParentAssocsOfType(parentNodeId, assocTypeQName, callback); + // done return results; } diff --git a/source/java/org/alfresco/repo/node/db/NodeDaoService.java b/source/java/org/alfresco/repo/node/db/NodeDaoService.java index 6c30af03da..23d9b8a6e0 100644 --- a/source/java/org/alfresco/repo/node/db/NodeDaoService.java +++ b/source/java/org/alfresco/repo/node/db/NodeDaoService.java @@ -364,21 +364,19 @@ public interface NodeDaoService public void getNodesWithAspect(QName aspectQName, Long minNodeId, int count, NodeRefQueryCallback resultsCallback); /** - * Gets the set of nodes of a certain type without parent associations of a certain type. In effect the 'orphans' - * with respect to a certain association type. + * Gets the set of child associations of a certain parent node without parent associations of a certain type to + * other nodes with the same parent! In effect the 'orphans' with respect to a certain association type. * - * @param storeRef - * the store reference - * @param nodeTypeQName - * the node type QName + * @param parentNodeId + * the parent node ID * @param assocTypeQName * the association type QName * @param resultsCallback - * the node callback + * the callback that will be called with the results */ - @DirtySessionAnnotation(markDirty=false) - public void getNodesWithoutParentAssocsOfType(final StoreRef storeRef, final QName nodeTypeQName, final QName assocTypeQName, - NodeRefQueryCallback resultsCallback); + @DirtySessionAnnotation(markDirty = false) + public void getChildAssocsWithoutParentAssocsOfType(final Long parentNodeId, final QName assocTypeQName, + ChildAssocRefQueryCallback resultsCallback); /** * @return Returns an association matching the given parent, type and child name (cm:name) - or null if not found */ diff --git a/source/java/org/alfresco/repo/node/db/hibernate/HibernateNodeDaoServiceImpl.java b/source/java/org/alfresco/repo/node/db/hibernate/HibernateNodeDaoServiceImpl.java index 2b8187b166..b5893ca20b 100644 --- a/source/java/org/alfresco/repo/node/db/hibernate/HibernateNodeDaoServiceImpl.java +++ b/source/java/org/alfresco/repo/node/db/hibernate/HibernateNodeDaoServiceImpl.java @@ -151,7 +151,7 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements private static final String QUERY_GET_PRIMARY_CHILD_ASSOCS_NOT_IN_SAME_STORE = "node.GetPrimaryChildAssocsNotInSameStore"; private static final String QUERY_GET_NODES_WITH_CHILDREN_IN_DIFFERENT_STORE ="node.GetNodesWithChildrenInDifferentStore"; private static final String QUERY_GET_NODES_WITH_ASPECT ="node.GetNodesWithAspect"; - private static final String QUERY_GET_NODES_WITHOUT_PARENT_ASSOCS_OF_TYPE ="node.GetNodesWithoutParentAssocsOfType"; + private static final String QUERY_GET_CHILD_ASSOCS_WITHOUT_PARENT_ASSOCS_OF_TYPE ="node.GetChildAssocsWithoutParentAssocsOfType"; private static final String QUERY_GET_PARENT_ASSOCS = "node.GetParentAssocs"; private static final String QUERY_GET_NODE_ASSOC = "node.GetNodeAssoc"; private static final String QUERY_GET_NODE_ASSOCS_TO_AND_FROM = "node.GetNodeAssocsToAndFrom"; @@ -2934,19 +2934,19 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements // Done } - public void getNodesWithoutParentAssocsOfType(final StoreRef storeRef, final QName nodeTypeQName, - final QName assocTypeQName, NodeRefQueryCallback resultsCallback) + public void getChildAssocsWithoutParentAssocsOfType(final Long parentNodeId, final QName assocTypeQName, + ChildAssocRefQueryCallback resultsCallback) { + Node parentNode = getNodeNotNull(parentNodeId); HibernateCallback callback = new HibernateCallback() { public Object doInHibernate(Session session) { + Query query = session.getNamedQuery( - HibernateNodeDaoServiceImpl.QUERY_GET_NODES_WITHOUT_PARENT_ASSOCS_OF_TYPE).setString( - "storeProtocol", storeRef.getProtocol()).setString("storeIdentifier", storeRef.getIdentifier()) - .setLong("nodeTypeQNameID", qnameDAO.getOrCreateQName(nodeTypeQName).getFirst()).setLong( - "assocTypeQNameID", qnameDAO.getOrCreateQName(assocTypeQName).getFirst()).setBoolean( - "isDeleted", false); + HibernateNodeDaoServiceImpl.QUERY_GET_CHILD_ASSOCS_WITHOUT_PARENT_ASSOCS_OF_TYPE).setLong( + "parentId", parentNodeId).setLong("assocTypeQNameID", + qnameDAO.getOrCreateQName(assocTypeQName).getFirst()); DirtySessionMethodInterceptor.setQueryFlushMode(session, query); return query.scroll(ScrollMode.FORWARD_ONLY); } @@ -2955,7 +2955,7 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements try { queryResults = (ScrollableResults) getHibernateTemplate().execute(callback); - processNodeResults(queryResults, resultsCallback); + convertToChildAssocRefs(parentNode, queryResults, resultsCallback); } finally { @@ -2964,10 +2964,9 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements queryResults.close(); } } - // Done } - + /** *
             Node ID = (Long) row[0];
diff --git a/source/java/org/alfresco/repo/security/authority/AuthorityDAOImpl.java b/source/java/org/alfresco/repo/security/authority/AuthorityDAOImpl.java
index 644c027415..ebe4ac0960 100644
--- a/source/java/org/alfresco/repo/security/authority/AuthorityDAOImpl.java
+++ b/source/java/org/alfresco/repo/security/authority/AuthorityDAOImpl.java
@@ -25,6 +25,7 @@
 package org.alfresco.repo.security.authority;
 
 import java.io.Serializable;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -42,7 +43,6 @@ import org.alfresco.service.cmr.repository.NodeRef;
 import org.alfresco.service.cmr.repository.NodeService;
 import org.alfresco.service.cmr.repository.StoreRef;
 import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
-import org.alfresco.service.cmr.security.AuthorityService;
 import org.alfresco.service.cmr.security.AuthorityType;
 import org.alfresco.service.cmr.security.PersonService;
 import org.alfresco.service.namespace.NamespacePrefixResolver;
@@ -169,16 +169,7 @@ public class AuthorityDAOImpl implements AuthorityDAO
 
     public Set getAllRootAuthorities(AuthorityType type)
     {
-        if (type != null && type.equals(AuthorityType.USER))
-        {
-            return Collections. emptySet();
-        }
-        Set authorities = new HashSet();
-        for (NodeRef nodeRef : nodeService.getNodesWithoutParentAssocsOfType(this.storeRef, ContentModel.TYPE_AUTHORITY_CONTAINER, ContentModel.ASSOC_MEMBER))
-        {
-            addAuthorityNameIfMatches(authorities, nodeRef, type, null);
-        }
-        return authorities;
+        return getAllRootAuthoritiesUnderContainer(getAuthorityContainer(), type);
     }
 
     public Set getAllAuthorities(AuthorityType type)
@@ -299,12 +290,6 @@ public class AuthorityDAOImpl implements AuthorityDAO
 
     }
 
-    private void addAuthorityNameIfMatches(Set authorities, NodeRef nodeRef, AuthorityType type, Pattern pattern)
-    {
-        addAuthorityNameIfMatches(authorities, DefaultTypeConverter.INSTANCE.convert(String.class, nodeService.getProperty(nodeRef, ContentModel.PROP_AUTHORITY_NAME)), type,
-                pattern);
-    }
-
     private void addAuthorityNameIfMatches(Set authorities, String authorityName, AuthorityType type, Pattern pattern)
     {
         if (type == null || AuthorityType.getAuthorityType(authorityName).equals(type))
@@ -693,9 +678,22 @@ public class AuthorityDAOImpl implements AuthorityDAO
 
     public Set getAllRootAuthoritiesInZone(String zoneName, AuthorityType type)
     {
-        Set roots = getAllRootAuthorities(type);
-        Set inZone = getAllAuthoritiesInZone(zoneName, type);
-        roots.retainAll(inZone);
-        return roots;
+        NodeRef zone = getZone(zoneName);
+        return zone == null ? Collections. emptySet() : getAllRootAuthoritiesUnderContainer(zone, type);
+    }
+    
+    private Set getAllRootAuthoritiesUnderContainer(NodeRef container, AuthorityType type)
+    {
+        if (type != null && type.equals(AuthorityType.USER))
+        {
+            return Collections. emptySet();
+        }        
+        Collection childRefs = nodeService.getChildAssocsWithoutParentAssocsOfType(container, ContentModel.ASSOC_MEMBER);
+        Set authorities = new HashSet(childRefs.size() * 2);
+        for (ChildAssociationRef childRef : childRefs)
+        {
+            addAuthorityNameIfMatches(authorities, childRef.getQName().getLocalName(), type, null);
+        }
+        return authorities;        
     }
 }
diff --git a/source/java/org/alfresco/repo/version/NodeServiceImpl.java b/source/java/org/alfresco/repo/version/NodeServiceImpl.java
index 6bd663c356..7139c57d4c 100644
--- a/source/java/org/alfresco/repo/version/NodeServiceImpl.java
+++ b/source/java/org/alfresco/repo/version/NodeServiceImpl.java
@@ -663,9 +663,8 @@ public class NodeServiceImpl implements NodeService, VersionModel
     /**
      * @throws UnsupportedOperationException always
      */
-    public Collection getNodesWithoutParentAssocsOfType(StoreRef storeRef, QName nodeTypeQName,
-            QName assocTypeQName)
+    public Collection getChildAssocsWithoutParentAssocsOfType(NodeRef parent, QName assocTypeQName)
     {
         throw new UnsupportedOperationException(MSG_UNSUPPORTED);
-    }
+    }        
 }
diff --git a/source/java/org/alfresco/service/cmr/repository/NodeService.java b/source/java/org/alfresco/service/cmr/repository/NodeService.java
index 05dd045add..d22704a3a0 100644
--- a/source/java/org/alfresco/service/cmr/repository/NodeService.java
+++ b/source/java/org/alfresco/service/cmr/repository/NodeService.java
@@ -560,21 +560,19 @@ public interface NodeService
     public ChildAssociationRef getPrimaryParent(NodeRef nodeRef) throws InvalidNodeRefException;
     
     /**
-     * Gets the set of nodes of a certain type without parent associations of a certain type. In effect the 'orphans'
-     * with respect to a certain association type.
+     * Gets the set of child associations of a certain parent node without parent associations of a certain type to
+     * other nodes with the same parent! In effect the 'orphans' with respect to a certain association type.
      * 
-     * @param storeRef
-     *            the store reference
-     * @param nodeTypeQName
-     *            the node type QName
+     * @param parent
+     *            the parent node reference
      * @param assocTypeQName
      *            the association type QName
-     * @return the set of nodes of the required type without parent associations of the required type
+     * @return a set of child associations
      */
-    @Auditable(key = Auditable.Key.ARG_0 ,parameters = {"storeRef", "nodeTypeQName", "assocTypeQName"})
-    public Collection getNodesWithoutParentAssocsOfType(final StoreRef storeRef, final QName nodeTypeQName,
+    @Auditable(key = Auditable.Key.ARG_0 ,parameters = {"parent", "assocTypeQName"})
+    public Collection getChildAssocsWithoutParentAssocsOfType(final NodeRef parent,
             final QName assocTypeQName);
-    
+
     /**
      * 
      * @param sourceRef a reference to a real node