Search in sources :

Example 1 with CyclicChildRelationshipException

use of org.alfresco.service.cmr.repository.CyclicChildRelationshipException in project alfresco-repository by Alfresco.

the class BaseNodeServiceTest method testGetPaths.

/**
 * @see #buildNodeGraph()
 */
@Test
public void testGetPaths() throws Exception {
    Map<QName, ChildAssociationRef> assocRefs = buildNodeGraph();
    NodeRef n1Ref = assocRefs.get(QName.createQName(BaseNodeServiceTest.NAMESPACE, "root_p_n1")).getChildRef();
    NodeRef n6Ref = assocRefs.get(QName.createQName(BaseNodeServiceTest.NAMESPACE, "n3_p_n6")).getChildRef();
    NodeRef n8Ref = assocRefs.get(QName.createQName(BaseNodeServiceTest.NAMESPACE, "n6_p_n8")).getChildRef();
    // get all paths for the root node
    Collection<Path> paths = nodeService.getPaths(rootNodeRef, false);
    assertEquals("Root node must have exactly 1 path", 1, paths.size());
    Path rootPath = paths.toArray(new Path[1])[0];
    assertNotNull("Root node path must have 1 element", rootPath.last());
    assertEquals("Root node path must have 1 element", rootPath.first(), rootPath.last());
    // get all paths for n8
    paths = nodeService.getPaths(n8Ref, false);
    // n6 is a root as well
    assertEquals("Incorrect path count", 6, paths.size());
    // check that each path element has parent node ref, qname and child node ref
    for (Path path : paths) {
        // get the path elements
        for (Path.Element element : path) {
            assertTrue("Path element of incorrect type", element instanceof Path.ChildAssocElement);
            Path.ChildAssocElement childAssocElement = (Path.ChildAssocElement) element;
            ChildAssociationRef ref = childAssocElement.getRef();
            if (childAssocElement != path.first()) {
                // for all but the first element, the parent and assoc qname must be set
                assertNotNull("Parent node ref not set", ref.getParentRef());
                assertNotNull("QName not set", ref.getQName());
            }
            // all associations must have a child ref
            assertNotNull("Child node ref not set", ref.getChildRef());
        }
    }
    // get primary path for n8
    paths = nodeService.getPaths(n8Ref, true);
    assertEquals("Incorrect path count", 1, paths.size());
    // check that a cyclic path is detected - make n6_n1
    try {
        nodeService.addChild(n6Ref, n1Ref, ASSOC_TYPE_QNAME_TEST_CHILDREN, QName.createQName("n6_n1"));
        nodeService.getPaths(n6Ref, false);
        fail("Cyclic relationship not detected");
    } catch (CyclicChildRelationshipException e) {
    // expected
    } catch (StackOverflowError e) {
        throw e;
    }
}
Also used : Path(org.alfresco.service.cmr.repository.Path) NodeRef(org.alfresco.service.cmr.repository.NodeRef) QName(org.alfresco.service.namespace.QName) ChildAssociationRef(org.alfresco.service.cmr.repository.ChildAssociationRef) CyclicChildRelationshipException(org.alfresco.service.cmr.repository.CyclicChildRelationshipException) BaseSpringTest(org.alfresco.util.BaseSpringTest) Test(org.junit.Test)

Example 2 with CyclicChildRelationshipException

use of org.alfresco.service.cmr.repository.CyclicChildRelationshipException in project alfresco-repository by Alfresco.

the class BaseNodeServiceTest method testAddChild.

@Test
public void testAddChild() throws Exception {
    NodeRef childNodeRef1 = nodeService.createNode(rootNodeRef, ASSOC_TYPE_QNAME_TEST_CHILDREN, QName.createQName("C1"), ContentModel.TYPE_CONTAINER).getChildRef();
    int count = countChildrenOfNode(rootNodeRef);
    assertEquals("Root children count incorrect", 1, count);
    NodeRef childNodeRef2 = nodeService.createNode(childNodeRef1, ASSOC_TYPE_QNAME_TEST_CHILDREN, QName.createQName("C2"), ContentModel.TYPE_CONTAINER).getChildRef();
    count = countChildrenOfNode(rootNodeRef);
    assertEquals("Root children count incorrect", 1, count);
    // associate the two nodes
    nodeService.addChild(rootNodeRef, childNodeRef2, ASSOC_TYPE_QNAME_TEST_CHILDREN, QName.createQName("pathB"));
    // there should now be 2 child assocs on the root
    int countAfter = countChildrenOfNode(rootNodeRef);
    assertEquals("Root children count incorrect", 2, countAfter);
    // now attempt to create a cyclical relationship
    try {
        nodeService.addChild(childNodeRef1, rootNodeRef, ASSOC_TYPE_QNAME_TEST_CHILDREN, QName.createQName("backToRoot"));
        fail("Failed to detect cyclic child relationship during addition of child");
    } catch (CyclicChildRelationshipException e) {
    // expected
    }
}
Also used : NodeRef(org.alfresco.service.cmr.repository.NodeRef) CyclicChildRelationshipException(org.alfresco.service.cmr.repository.CyclicChildRelationshipException) BaseSpringTest(org.alfresco.util.BaseSpringTest) Test(org.junit.Test)

Example 3 with CyclicChildRelationshipException

use of org.alfresco.service.cmr.repository.CyclicChildRelationshipException in project alfresco-repository by Alfresco.

the class AbstractNodeDAOImpl method prependPaths.

/**
 * Build the paths for a node
 *
 * @param currentNodePair       the leave or child node to start with
 * @param currentRootNodePair   pass in <tt>null</tt> only
 * @param currentPath           an empty {@link Path}
 * @param completedPaths        completed paths i.e. the result
 * @param assocIdStack          a stack to detected cyclic relationships
 * @param primaryOnly           <tt>true</tt> to follow only primary parent associations
 * @throws CyclicChildRelationshipException
 */
private void prependPaths(Pair<Long, NodeRef> currentNodePair, Pair<StoreRef, NodeRef> currentRootNodePair, Path currentPath, Collection<Path> completedPaths, Stack<Long> assocIdStack, boolean primaryOnly) throws CyclicChildRelationshipException {
    if (isDebugEnabled) {
        logger.debug("\n" + "Prepending paths: \n" + "   Current node: " + currentNodePair + "\n" + "   Current root: " + currentRootNodePair + "\n" + "   Current path: " + currentPath);
    }
    Long currentNodeId = currentNodePair.getFirst();
    NodeRef currentNodeRef = currentNodePair.getSecond();
    // Check if we have changed root nodes
    StoreRef currentStoreRef = currentNodeRef.getStoreRef();
    if (currentRootNodePair == null || !currentStoreRef.equals(currentRootNodePair.getFirst())) {
        // We've changed stores
        Pair<Long, NodeRef> rootNodePair = getRootNode(currentStoreRef);
        currentRootNodePair = new Pair<StoreRef, NodeRef>(currentStoreRef, rootNodePair.getSecond());
    }
    // get the parent associations of the given node
    // note: currently may throw NotLiveNodeException
    ParentAssocsInfo parentAssocInfo = getParentAssocsCached(currentNodeId);
    // bulk load parents as we are certain to hit them in the next call
    ArrayList<Long> toLoad = new ArrayList<Long>(parentAssocInfo.getParentAssocs().size());
    for (Map.Entry<Long, ChildAssocEntity> entry : parentAssocInfo.getParentAssocs().entrySet()) {
        toLoad.add(entry.getValue().getParentNode().getId());
    }
    cacheNodesById(toLoad);
    // does the node have parents
    boolean hasParents = parentAssocInfo.getParentAssocs().size() > 0;
    // look for a root. If we only want the primary root, then ignore all but the top-level root.
    if (// exclude primary search with parents present
    !(primaryOnly && hasParents) && parentAssocInfo.isRoot()) {
        // create a one-sided assoc ref for the root node and prepend to the stack
        // this effectively spoofs the fact that the current node is not below the root
        // - we put this assoc in as the first assoc in the path must be a one-sided
        // reference pointing to the root node
        ChildAssociationRef assocRef = new ChildAssociationRef(null, null, null, currentRootNodePair.getSecond());
        // create a path to save and add the 'root' assoc
        Path pathToSave = new Path();
        Path.ChildAssocElement first = null;
        for (Path.Element element : currentPath) {
            if (first == null) {
                first = (Path.ChildAssocElement) element;
            } else {
                pathToSave.append(element);
            }
        }
        if (first != null) {
            // mimic an association that would appear if the current node was below the root node
            // or if first beneath the root node it will make the real thing
            ChildAssociationRef updateAssocRef = new ChildAssociationRef(parentAssocInfo.isStoreRoot() ? ContentModel.ASSOC_CHILDREN : first.getRef().getTypeQName(), currentRootNodePair.getSecond(), first.getRef().getQName(), first.getRef().getChildRef());
            Path.Element newFirst = new Path.ChildAssocElement(updateAssocRef);
            pathToSave.prepend(newFirst);
        }
        Path.Element element = new Path.ChildAssocElement(assocRef);
        pathToSave.prepend(element);
        // store the path just built
        completedPaths.add(pathToSave);
    }
    // walk up each parent association
    for (Map.Entry<Long, ChildAssocEntity> entry : parentAssocInfo.getParentAssocs().entrySet()) {
        Long assocId = entry.getKey();
        ChildAssocEntity assoc = entry.getValue();
        ChildAssociationRef assocRef = assoc.getRef(qnameDAO);
        // do we consider only primary assocs?
        if (primaryOnly && !assocRef.isPrimary()) {
            continue;
        }
        // Ordering is meaningless here as we are constructing a path upwards
        // and have no idea where the node comes in the sibling order or even
        // if there are like-pathed siblings.
        assocRef.setNthSibling(-1);
        // build a path element
        Path.Element element = new Path.ChildAssocElement(assocRef);
        // create a new path that builds on the current path
        Path path = new Path();
        path.append(currentPath);
        // prepend element
        path.prepend(element);
        // get parent node pair
        Pair<Long, NodeRef> parentNodePair = new Pair<Long, NodeRef>(assoc.getParentNode().getId(), assocRef.getParentRef());
        // does the association already exist in the stack
        if (assocIdStack.contains(assocId)) {
            // the association was present already
            logger.error("Cyclic parent-child relationship detected: \n" + "   current node: " + currentNodeId + "\n" + "   current path: " + currentPath + "\n" + "   next assoc: " + assocId);
            throw new CyclicChildRelationshipException("Node has been pasted into its own tree.", assocRef);
        }
        if (isDebugEnabled) {
            logger.debug("\n" + "   Prepending path parent: \n" + "      Parent node: " + parentNodePair);
        }
        // push the assoc stack, recurse and pop
        assocIdStack.push(assocId);
        prependPaths(parentNodePair, currentRootNodePair, path, completedPaths, assocIdStack, primaryOnly);
        assocIdStack.pop();
    }
// done
}
Also used : Path(org.alfresco.service.cmr.repository.Path) StoreRef(org.alfresco.service.cmr.repository.StoreRef) ArrayList(java.util.ArrayList) ChildAssociationRef(org.alfresco.service.cmr.repository.ChildAssociationRef) CyclicChildRelationshipException(org.alfresco.service.cmr.repository.CyclicChildRelationshipException) NodeRef(org.alfresco.service.cmr.repository.NodeRef) ValueProtectingMap(org.alfresco.util.ValueProtectingMap) Map(java.util.Map) HashMap(java.util.HashMap) Pair(org.alfresco.util.Pair)

Example 4 with CyclicChildRelationshipException

use of org.alfresco.service.cmr.repository.CyclicChildRelationshipException in project alfresco-repository by Alfresco.

the class RuleServiceImplTest method testCyclicGraphWithInheritedRules.

/**
 * Ensure that the rule store can cope with a cyclic node graph
 *
 * @throws Exception
 */
@Test
public void testCyclicGraphWithInheritedRules() throws Exception {
    NodeRef nodeRef1 = createNewNode(this.rootNodeRef);
    NodeRef nodeRef2 = createNewNode(nodeRef1);
    NodeRef nodeRef3 = createNewNode(nodeRef2);
    try {
        this.nodeService.addChild(nodeRef3, nodeRef1, ContentModel.ASSOC_CHILDREN, QName.createQName("{test}loop"));
        fail("Expected detection of cyclic relationship");
    } catch (CyclicChildRelationshipException e) {
    // expected
    // the node will still have been created in the current transaction, although the txn will be rollback-only
    }
    Rule rule1 = createTestRule(true);
    this.ruleService.saveRule(nodeRef1, rule1);
    Rule rule2 = createTestRule(true);
    this.ruleService.saveRule(nodeRef2, rule2);
    Rule rule3 = createTestRule(true);
    this.ruleService.saveRule(nodeRef3, rule3);
    List<? extends Rule> allRules1 = this.ruleService.getRules(nodeRef1, true);
    assertNotNull(allRules1);
    assertEquals(3, allRules1.size());
    assertTrue(allRules1.contains(rule1));
    assertTrue(allRules1.contains(rule2));
    assertTrue(allRules1.contains(rule3));
    List<? extends Rule> allRules2 = this.ruleService.getRules(nodeRef2, true);
    assertNotNull(allRules2);
    assertEquals(3, allRules2.size());
    assertTrue(allRules2.contains(rule1));
    assertTrue(allRules2.contains(rule2));
    assertTrue(allRules2.contains(rule3));
    List<? extends Rule> allRules3 = this.ruleService.getRules(nodeRef3, true);
    assertNotNull(allRules3);
    assertEquals(3, allRules3.size());
    assertTrue(allRules3.contains(rule1));
    assertTrue(allRules3.contains(rule2));
    assertTrue(allRules3.contains(rule3));
}
Also used : NodeRef(org.alfresco.service.cmr.repository.NodeRef) Rule(org.alfresco.service.cmr.rule.Rule) CyclicChildRelationshipException(org.alfresco.service.cmr.repository.CyclicChildRelationshipException) Test(org.junit.Test) AbstractContentTransformerTest(org.alfresco.repo.content.transform.AbstractContentTransformerTest)

Example 5 with CyclicChildRelationshipException

use of org.alfresco.service.cmr.repository.CyclicChildRelationshipException in project alfresco-repository by Alfresco.

the class FileFolderServiceImplTest method testETHREEOH_3088_MoveIntoSelf.

public void testETHREEOH_3088_MoveIntoSelf() throws Exception {
    FileInfo folderInfo = fileFolderService.create(workingRootNodeRef, "NotGood.txt", ContentModel.TYPE_FOLDER);
    NodeRef folderNodeRef = folderInfo.getNodeRef();
    // Move into self
    try {
        fileFolderService.move(folderNodeRef, folderNodeRef, null);
        fail("Failed to detect cyclic relationship");
    } catch (CyclicChildRelationshipException e) {
    // Expected
    }
}
Also used : NodeRef(org.alfresco.service.cmr.repository.NodeRef) FileInfo(org.alfresco.service.cmr.model.FileInfo) CyclicChildRelationshipException(org.alfresco.service.cmr.repository.CyclicChildRelationshipException)

Aggregations

CyclicChildRelationshipException (org.alfresco.service.cmr.repository.CyclicChildRelationshipException)6 NodeRef (org.alfresco.service.cmr.repository.NodeRef)6 Test (org.junit.Test)4 ChildAssociationRef (org.alfresco.service.cmr.repository.ChildAssociationRef)3 BaseSpringTest (org.alfresco.util.BaseSpringTest)3 Path (org.alfresco.service.cmr.repository.Path)2 QName (org.alfresco.service.namespace.QName)2 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 Map (java.util.Map)1 AbstractContentTransformerTest (org.alfresco.repo.content.transform.AbstractContentTransformerTest)1 JavaBehaviour (org.alfresco.repo.policy.JavaBehaviour)1 FileInfo (org.alfresco.service.cmr.model.FileInfo)1 StoreRef (org.alfresco.service.cmr.repository.StoreRef)1 Rule (org.alfresco.service.cmr.rule.Rule)1 Pair (org.alfresco.util.Pair)1 ValueProtectingMap (org.alfresco.util.ValueProtectingMap)1