mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-10-15 15:02:20 +00:00
Fix for ACE-4420 SOLR 4 - sharded - rename and move operations will not update descendants and add incorrect nodes to the shard
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@114654 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -373,6 +373,25 @@
|
|||||||
</property>
|
</property>
|
||||||
</properties>
|
</properties>
|
||||||
</aspect>
|
</aspect>
|
||||||
|
|
||||||
|
<!-- Aspect to record the last transaction that requires a cascade update to index children (like move, rename, link and unlink) -->
|
||||||
|
<aspect name="sys:cascadeUpdate">
|
||||||
|
<title>Cascade update</title>
|
||||||
|
<properties>
|
||||||
|
<property name="sys:cascadeCRC">
|
||||||
|
<title>Cascade CRC</title>
|
||||||
|
<type>d:long</type>
|
||||||
|
<mandatory>false</mandatory>
|
||||||
|
<multiple>false</multiple>
|
||||||
|
</property>
|
||||||
|
<property name="sys:cascadeTx">
|
||||||
|
<title>Cascade Tx</title>
|
||||||
|
<type>d:long</type>
|
||||||
|
<mandatory>false</mandatory>
|
||||||
|
<multiple>false</multiple>
|
||||||
|
</property>
|
||||||
|
</properties>
|
||||||
|
</aspect>
|
||||||
</aspects>
|
</aspects>
|
||||||
|
|
||||||
</model>
|
</model>
|
@@ -305,4 +305,12 @@
|
|||||||
<property name="jobLockService" ref="jobLockService"/>
|
<property name="jobLockService" ref="jobLockService"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<!-- The cascade update aspect -->
|
||||||
|
<bean id="cascadeUpdateAspect" class="org.alfresco.repo.node.CascadeUpdateAspect" init-method="init">
|
||||||
|
<property name="nodeService" ref="nodeService"/>
|
||||||
|
<property name="policyComponent" ref="policyComponent"/>
|
||||||
|
<property name="dictionaryService" ref="dictionaryService" />
|
||||||
|
<property name="solrTrackingComponent" ref="solrTrackingComponent" />
|
||||||
|
</bean>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
||||||
|
162
source/java/org/alfresco/repo/node/CascadeUpdateAspect.java
Normal file
162
source/java/org/alfresco/repo/node/CascadeUpdateAspect.java
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2015 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.node;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.node.NodeServicePolicies.OnCreateChildAssociationPolicy;
|
||||||
|
import org.alfresco.repo.node.NodeServicePolicies.OnDeleteChildAssociationPolicy;
|
||||||
|
import org.alfresco.repo.node.NodeServicePolicies.OnMoveNodePolicy;
|
||||||
|
import org.alfresco.repo.node.NodeServicePolicies.OnUpdatePropertiesPolicy;
|
||||||
|
import org.alfresco.repo.policy.Behaviour;
|
||||||
|
import org.alfresco.repo.policy.JavaBehaviour;
|
||||||
|
import org.alfresco.repo.policy.PolicyComponent;
|
||||||
|
import org.alfresco.repo.solr.SOLRTrackingComponent;
|
||||||
|
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
||||||
|
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||||
|
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||||
|
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef.Status;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.alfresco.util.EqualsHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andy
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class CascadeUpdateAspect implements OnCreateChildAssociationPolicy, OnDeleteChildAssociationPolicy, OnMoveNodePolicy
|
||||||
|
{
|
||||||
|
private PolicyComponent policyComponent;
|
||||||
|
private NodeService nodeService;
|
||||||
|
private SOLRTrackingComponent solrTrackingComponent;
|
||||||
|
private DictionaryService dictionaryService;
|
||||||
|
|
||||||
|
|
||||||
|
public void setPolicyComponent(PolicyComponent policyComponent)
|
||||||
|
{
|
||||||
|
this.policyComponent = policyComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNodeService(NodeService nodeService)
|
||||||
|
{
|
||||||
|
this.nodeService = nodeService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSolrTrackingComponent(SOLRTrackingComponent solrTrackingComponent)
|
||||||
|
{
|
||||||
|
this.solrTrackingComponent = solrTrackingComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDictionaryService(DictionaryService dictionaryService)
|
||||||
|
{
|
||||||
|
this.dictionaryService = dictionaryService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise method
|
||||||
|
*/
|
||||||
|
public void init()
|
||||||
|
{
|
||||||
|
// need to listen to:
|
||||||
|
// invokeOnCreateChildAssociation(newParentAssocRef, false);
|
||||||
|
// invokeOnDeleteChildAssociation(oldParentAssocRef);
|
||||||
|
// invokeOnMoveNode(oldParentAssocRef, newParentAssocRef);
|
||||||
|
// categories affect paths via membership (not paths beneath nodes that are categories)
|
||||||
|
// - only changing category structure requires a cascade not changing a node's on a categories
|
||||||
|
|
||||||
|
this.policyComponent.bindAssociationBehaviour(OnCreateChildAssociationPolicy.QNAME,
|
||||||
|
ContentModel.TYPE_BASE,
|
||||||
|
new JavaBehaviour(this, "onCreateChildAssociation", Behaviour.NotificationFrequency.EVERY_EVENT));
|
||||||
|
this.policyComponent.bindAssociationBehaviour(OnDeleteChildAssociationPolicy.QNAME,
|
||||||
|
ContentModel.TYPE_BASE,
|
||||||
|
new JavaBehaviour(this, "onDeleteChildAssociation", Behaviour.NotificationFrequency.EVERY_EVENT));
|
||||||
|
this.policyComponent.bindClassBehaviour(OnMoveNodePolicy.QNAME,
|
||||||
|
ContentModel.TYPE_BASE,
|
||||||
|
new JavaBehaviour(this, "onMoveNode", Behaviour.NotificationFrequency.EVERY_EVENT));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.alfresco.repo.node.NodeServicePolicies.OnMoveNodePolicy#onMoveNode(org.alfresco.service.cmr.repository.ChildAssociationRef, org.alfresco.service.cmr.repository.ChildAssociationRef)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onMoveNode(ChildAssociationRef oldChildAssocRef, ChildAssociationRef newChildAssocRef)
|
||||||
|
{
|
||||||
|
markCascadeUpdate(oldChildAssocRef.getChildRef());
|
||||||
|
markCascadeUpdate(newChildAssocRef.getChildRef());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.alfresco.repo.node.NodeServicePolicies.OnDeleteChildAssociationPolicy#onDeleteChildAssociation(org.alfresco.service.cmr.repository.ChildAssociationRef)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onDeleteChildAssociation(ChildAssociationRef childAssocRef)
|
||||||
|
{
|
||||||
|
markCascadeUpdate(childAssocRef.getChildRef());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.alfresco.repo.node.NodeServicePolicies.OnCreateChildAssociationPolicy#onCreateChildAssociation(org.alfresco.service.cmr.repository.ChildAssociationRef, boolean)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onCreateChildAssociation(ChildAssociationRef childAssocRef, boolean isNewNode)
|
||||||
|
{
|
||||||
|
if(!isNewNode)
|
||||||
|
{
|
||||||
|
markCascadeUpdate(childAssocRef.getChildRef());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void markCascadeUpdate(NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
Status status = nodeService.getNodeStatus(nodeRef);
|
||||||
|
nodeService.setProperty(status.getNodeRef(), ContentModel.PROP_CASCADE_CRC, solrTrackingComponent.getCRC(status.getDbId()));
|
||||||
|
nodeService.setProperty(status.getNodeRef(), ContentModel.PROP_CASCADE_TX, status.getDbTxnId());
|
||||||
|
}
|
||||||
|
// /* (non-Javadoc)
|
||||||
|
// * @see org.alfresco.repo.node.NodeServicePolicies.OnUpdatePropertiesPolicy#onUpdateProperties(org.alfresco.service.cmr.repository.NodeRef, java.util.Map, java.util.Map)
|
||||||
|
// */
|
||||||
|
// @Override
|
||||||
|
// public void onUpdateProperties(NodeRef nodeRef, Map<QName, Serializable> before, Map<QName, Serializable> after)
|
||||||
|
// {
|
||||||
|
// HashSet<QName> combinedPropertyNames = new HashSet<QName>(before.size() + 10);
|
||||||
|
// combinedPropertyNames.addAll(before.keySet());
|
||||||
|
// combinedPropertyNames.addAll(after.keySet());
|
||||||
|
// for(QName propertyQName : combinedPropertyNames)
|
||||||
|
// {
|
||||||
|
// PropertyDefinition propDef = dictionaryService.getProperty(propertyQName);
|
||||||
|
// if((propDef != null) && (propDef.getDataType().getName().equals(DataTypeDefinition.CATEGORY)))
|
||||||
|
// {
|
||||||
|
// Serializable beforeValue = before.get(propDef.getName());
|
||||||
|
// Serializable afterValue = after.get(propDef.getName());
|
||||||
|
// if(false == EqualsHelper.nullSafeEquals(beforeValue, afterValue))
|
||||||
|
// {
|
||||||
|
// markCascadeUpdate(nodeRef);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
}
|
@@ -181,4 +181,12 @@ public interface SOLRTrackingComponent
|
|||||||
* This is an optional feature.
|
* This is an optional feature.
|
||||||
*/
|
*/
|
||||||
public ShardRegistry getShardRegistry();
|
public ShardRegistry getShardRegistry();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the CRC for the parent associations to this node that can cause its PATH to change
|
||||||
|
* - primary & secondary associations and virtual associations from categories.
|
||||||
|
* @param nodeId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public long getCRC(Long nodeId);
|
||||||
}
|
}
|
||||||
|
@@ -650,6 +650,66 @@ public class SOLRTrackingComponentImpl implements SOLRTrackingComponent
|
|||||||
return props;
|
return props;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getCRC(Long nodeId)
|
||||||
|
{
|
||||||
|
Status status = nodeDAO.getNodeIdStatus(nodeId);
|
||||||
|
Set<QName> aspects = getNodeAspects(nodeId);
|
||||||
|
Map<QName, Serializable> props = getProperties(nodeId);
|
||||||
|
|
||||||
|
//Category membership does not cascade to children - only the node needs reindexing, not its children
|
||||||
|
//This was producing cascade updates that were not required
|
||||||
|
////CategoryPaths categoryPaths = new CategoryPaths(new ArrayList<Pair<Path, QName>>(), new ArrayList<ChildAssociationRef>());
|
||||||
|
////categoryPaths = getCategoryPaths(status.getNodeRef(), aspects, props);
|
||||||
|
|
||||||
|
final List<ChildAssociationRef> parentAssocs = new ArrayList<ChildAssociationRef>(100);
|
||||||
|
nodeDAO.getParentAssocs(nodeId, null, null, null, new ChildAssocRefQueryCallback()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public boolean preLoadNodes()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean orderResults()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handle(Pair<Long, ChildAssociationRef> childAssocPair,
|
||||||
|
Pair<Long, NodeRef> parentNodePair, Pair<Long, NodeRef> childNodePair)
|
||||||
|
{
|
||||||
|
parentAssocs.add(tenantService.getBaseName(childAssocPair.getSecond(), true));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void done()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// for(ChildAssociationRef ref : categoryPaths.getCategoryParents())
|
||||||
|
// {
|
||||||
|
// parentAssocs.add(tenantService.getBaseName(ref, true));
|
||||||
|
// }
|
||||||
|
|
||||||
|
CRC32 crc = new CRC32();
|
||||||
|
for(ChildAssociationRef car : parentAssocs)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
crc.update(car.toString().getBytes("UTF-8"));
|
||||||
|
}
|
||||||
|
catch (UnsupportedEncodingException e)
|
||||||
|
{
|
||||||
|
throw new RuntimeException("UTF-8 encoding is not supported");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return crc.getValue();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
|
@@ -980,11 +980,12 @@ public class NodeServiceTest
|
|||||||
props.put(ContentModel.PROP_TITLE, "some title");
|
props.put(ContentModel.PROP_TITLE, "some title");
|
||||||
nodeService.addAspect(nodeRef, ContentModel.ASPECT_TITLED, props);
|
nodeService.addAspect(nodeRef, ContentModel.ASPECT_TITLED, props);
|
||||||
nodeService.setProperty(nodeRef, ContentModel.PROP_DESCRIPTION, "Some description");
|
nodeService.setProperty(nodeRef, ContentModel.PROP_DESCRIPTION, "Some description");
|
||||||
nodeService.addChild(
|
// Adding a child node now triggers behaviour to update a CRC property
|
||||||
Collections.singletonList(workspaceRootNodeRef),
|
// nodeService.addChild(
|
||||||
nodeRef,
|
// Collections.singletonList(workspaceRootNodeRef),
|
||||||
ContentModel.ASSOC_CHILDREN,
|
// nodeRef,
|
||||||
QName.createQName(TEST_PREFIX, "secondary"));
|
// ContentModel.ASSOC_CHILDREN,
|
||||||
|
// QName.createQName(TEST_PREFIX, "secondary"));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1781,4 +1782,118 @@ public class NodeServiceTest
|
|||||||
assertEquals(nodes[1], nodesParentFirst.get(0).sourceAssocs.get(0).getSecond().getSourceRef());
|
assertEquals(nodes[1], nodesParentFirst.get(0).sourceAssocs.get(0).getSecond().getSourceRef());
|
||||||
assertEquals(0, nodesParentFirst.get(1).sourceAssocs.size());
|
assertEquals(0, nodesParentFirst.get(1).sourceAssocs.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test public void testCascadeUpdate()
|
||||||
|
{
|
||||||
|
Map<QName, Serializable> props = new HashMap<QName, Serializable>();
|
||||||
|
NodeRef nodeRef1 = nodeService.createNode(
|
||||||
|
rootNodeRef,
|
||||||
|
ContentModel.ASSOC_CHILDREN,
|
||||||
|
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, this.getClass().getName()),
|
||||||
|
ContentModel.TYPE_CONTAINER).getChildRef();
|
||||||
|
|
||||||
|
assertFalse(nodeService.getAspects(nodeRef1).contains(ContentModel.ASPECT_CASCADE_UPDATE));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Map<QName, Serializable> aspectProps = new HashMap<QName, Serializable>();
|
||||||
|
ArrayList<NodeRef> cats = new ArrayList<NodeRef>();
|
||||||
|
cats.add(nodeRef1);
|
||||||
|
aspectProps.put(ContentModel.PROP_CATEGORIES, cats);
|
||||||
|
nodeService.addAspect(nodeRef1, ContentModel.ASPECT_GEN_CLASSIFIABLE, aspectProps);
|
||||||
|
assertTrue(nodeService.getAspects(nodeRef1).contains(ContentModel.ASPECT_GEN_CLASSIFIABLE));
|
||||||
|
assertFalse(nodeService.getAspects(nodeRef1).contains(ContentModel.ASPECT_CASCADE_UPDATE));
|
||||||
|
|
||||||
|
|
||||||
|
NodeRef nodeRef2 = nodeService.createNode(
|
||||||
|
rootNodeRef,
|
||||||
|
ContentModel.ASSOC_CHILDREN,
|
||||||
|
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, this.getClass().getName()),
|
||||||
|
ContentModel.TYPE_CONTAINER).getChildRef();
|
||||||
|
|
||||||
|
NodeRef nodeRef3 = nodeService.createNode(
|
||||||
|
rootNodeRef,
|
||||||
|
ContentModel.ASSOC_CHILDREN,
|
||||||
|
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, this.getClass().getName()),
|
||||||
|
ContentModel.TYPE_CONTAINER).getChildRef();
|
||||||
|
|
||||||
|
NodeRef nodeRef4 = nodeService.createNode(
|
||||||
|
nodeRef2,
|
||||||
|
ContentModel.ASSOC_CHILDREN,
|
||||||
|
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, this.getClass().getName()),
|
||||||
|
ContentModel.TYPE_CONTAINER).getChildRef();
|
||||||
|
|
||||||
|
assertFalse(nodeService.getAspects(nodeRef2).contains(ContentModel.ASPECT_CASCADE_UPDATE));
|
||||||
|
assertFalse(nodeService.getAspects(nodeRef3).contains(ContentModel.ASPECT_CASCADE_UPDATE));
|
||||||
|
assertFalse(nodeService.getAspects(nodeRef4).contains(ContentModel.ASPECT_CASCADE_UPDATE));
|
||||||
|
|
||||||
|
nodeService.moveNode(nodeRef4, nodeRef3, ContentModel.ASSOC_CHILDREN, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, this.getClass().getName()));
|
||||||
|
|
||||||
|
|
||||||
|
assertFalse(nodeService.getAspects(nodeRef2).contains(ContentModel.ASPECT_CASCADE_UPDATE));
|
||||||
|
assertFalse(nodeService.getAspects(nodeRef3).contains(ContentModel.ASPECT_CASCADE_UPDATE));
|
||||||
|
assertTrue(nodeService.getAspects(nodeRef4).contains(ContentModel.ASPECT_CASCADE_UPDATE));
|
||||||
|
Status status = nodeService.getNodeStatus(nodeRef4);
|
||||||
|
Long lastCascadeTx = (Long)nodeService.getProperty(nodeRef4, ContentModel.PROP_CASCADE_TX);
|
||||||
|
assertTrue(status.getDbTxnId().equals(lastCascadeTx));
|
||||||
|
assertTrue(nodeService.getProperty(nodeRef4, ContentModel.PROP_CASCADE_CRC) != null);
|
||||||
|
Long crcIn3 = (Long)nodeService.getProperty(nodeRef4, ContentModel.PROP_CASCADE_CRC);
|
||||||
|
|
||||||
|
nodeService.moveNode(nodeRef4, nodeRef2, ContentModel.ASSOC_CHILDREN, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, this.getClass().getName()));
|
||||||
|
Long crcIn2 = (Long)nodeService.getProperty(nodeRef4, ContentModel.PROP_CASCADE_CRC);
|
||||||
|
|
||||||
|
assertFalse(crcIn2.equals(crcIn3));
|
||||||
|
|
||||||
|
|
||||||
|
NodeRef nodeRef5 = nodeService.createNode(
|
||||||
|
rootNodeRef,
|
||||||
|
ContentModel.ASSOC_CHILDREN,
|
||||||
|
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "5"),
|
||||||
|
ContentModel.TYPE_CONTAINER).getChildRef();
|
||||||
|
|
||||||
|
NodeRef nodeRef6 = nodeService.createNode(
|
||||||
|
rootNodeRef,
|
||||||
|
ContentModel.ASSOC_CHILDREN,
|
||||||
|
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "6"),
|
||||||
|
ContentModel.TYPE_CONTAINER).getChildRef();
|
||||||
|
|
||||||
|
NodeRef nodeRef7 = nodeService.createNode(
|
||||||
|
nodeRef5,
|
||||||
|
ContentModel.ASSOC_CHILDREN,
|
||||||
|
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "7"),
|
||||||
|
ContentModel.TYPE_CONTAINER).getChildRef();
|
||||||
|
|
||||||
|
NodeRef nodeRef8 = nodeService.createNode(
|
||||||
|
nodeRef5,
|
||||||
|
ContentModel.ASSOC_CHILDREN,
|
||||||
|
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "8"),
|
||||||
|
ContentModel.TYPE_CONTAINER).getChildRef();
|
||||||
|
|
||||||
|
|
||||||
|
assertFalse(nodeService.getAspects(nodeRef5).contains(ContentModel.ASPECT_CASCADE_UPDATE));
|
||||||
|
assertFalse(nodeService.getAspects(nodeRef6).contains(ContentModel.ASPECT_CASCADE_UPDATE));
|
||||||
|
assertFalse(nodeService.getAspects(nodeRef7).contains(ContentModel.ASPECT_CASCADE_UPDATE));
|
||||||
|
assertFalse(nodeService.getAspects(nodeRef8).contains(ContentModel.ASPECT_CASCADE_UPDATE));
|
||||||
|
|
||||||
|
nodeService.addChild(nodeRef6, nodeRef7, ContentModel.ASSOC_CHILDREN, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, this.getClass().getName()));
|
||||||
|
assertFalse(nodeService.getAspects(nodeRef5).contains(ContentModel.ASPECT_CASCADE_UPDATE));
|
||||||
|
assertFalse(nodeService.getAspects(nodeRef6).contains(ContentModel.ASPECT_CASCADE_UPDATE));
|
||||||
|
assertTrue(nodeService.getAspects(nodeRef7).contains(ContentModel.ASPECT_CASCADE_UPDATE));
|
||||||
|
assertFalse(nodeService.getAspects(nodeRef8).contains(ContentModel.ASPECT_CASCADE_UPDATE));
|
||||||
|
|
||||||
|
Long doubleLinkCRC = (Long)nodeService.getProperty(nodeRef7, ContentModel.PROP_CASCADE_CRC);
|
||||||
|
|
||||||
|
nodeService.removeChild(nodeRef6, nodeRef7);
|
||||||
|
Long singleLinkCRC = (Long)nodeService.getProperty(nodeRef7, ContentModel.PROP_CASCADE_CRC);
|
||||||
|
assertFalse(doubleLinkCRC.equals(singleLinkCRC));
|
||||||
|
|
||||||
|
nodeService.addChild(nodeRef6, nodeRef7, ContentModel.ASSOC_CHILDREN, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, this.getClass().getName()));
|
||||||
|
Long doubleLinkCRC2 = (Long)nodeService.getProperty(nodeRef7, ContentModel.PROP_CASCADE_CRC);
|
||||||
|
assertTrue(doubleLinkCRC.equals(doubleLinkCRC2));
|
||||||
|
|
||||||
|
nodeService.removeChild(nodeRef6, nodeRef7);
|
||||||
|
Long singleLinkCRC2 = (Long)nodeService.getProperty(nodeRef7, ContentModel.PROP_CASCADE_CRC);
|
||||||
|
assertTrue(singleLinkCRC2.equals(singleLinkCRC));
|
||||||
|
|
||||||
|
; }
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user