Added double-checks for associations when a potential failure is detected

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@28974 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2011-07-13 11:44:57 +00:00
parent f12b5edafa
commit 17a5ae11ff
6 changed files with 93 additions and 7 deletions

View File

@@ -167,6 +167,17 @@ public class AssocSourceMultiplicityIntegrityEvent extends AbstractIntegrityEven
if ((mandatory && actualSize == 0) || (!allowMany && actualSize > 1)) if ((mandatory && actualSize == 0) || (!allowMany && actualSize > 1))
{ {
if (actualSize == 0)
{
// Double check that the association source is still present
ClassDefinition classDef = assocDef.getTargetClass();
if (classDef.isAspect() && !nodeService.hasAspect(targetNodeRef, classDef.getName()))
{
// The target is an aspect but the aspect is not present
return;
}
}
String parentOrSourceStr = (assocDef.isChild() ? "parent" : "source"); String parentOrSourceStr = (assocDef.isChild() ? "parent" : "source");
IntegrityRecord result = new IntegrityRecord( IntegrityRecord result = new IntegrityRecord(
"The association " + parentOrSourceStr + " multiplicity has been violated: \n" + "The association " + parentOrSourceStr + " multiplicity has been violated: \n" +

View File

@@ -29,6 +29,7 @@ import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@@ -127,6 +128,24 @@ public class AssocSourceTypeIntegrityEvent extends AbstractIntegrityEvent
} }
if (!found) if (!found)
{ {
// Actually make sure that the association still exists
if (assocDef.isChild())
{
if (nodeService.getChildAssocs(sourceNodeRef, assocDef.getName(), RegexQNamePattern.MATCH_ALL).size() == 0)
{
// The association does not exist any more
return;
}
}
else
{
if (nodeService.getTargetAssocs(sourceNodeRef, assocDef.getName()).size() == 0)
{
// The association does not exist any more
return;
}
}
// The association is still present
IntegrityRecord result = new IntegrityRecord( IntegrityRecord result = new IntegrityRecord(
"The association source is missing the aspect required for this association: \n" + "The association source is missing the aspect required for this association: \n" +
" Source Node: " + sourceNodeRef + "\n" + " Source Node: " + sourceNodeRef + "\n" +

View File

@@ -167,6 +167,17 @@ public class AssocTargetMultiplicityIntegrityEvent extends AbstractIntegrityEven
if ((mandatory && actualSize == 0) || (!allowMany && actualSize > 1)) if ((mandatory && actualSize == 0) || (!allowMany && actualSize > 1))
{ {
if (actualSize == 0)
{
// Double check that the association source is still present
ClassDefinition classDef = assocDef.getSourceClass();
if (classDef.isAspect() && !nodeService.hasAspect(sourceNodeRef, classDef.getName()))
{
// The source is an aspect but the aspect is not present
return;
}
}
String childOrTargetStr = (assocDef.isChild() ? "child" : "target"); String childOrTargetStr = (assocDef.isChild() ? "child" : "target");
IntegrityRecord result = new IntegrityRecord( IntegrityRecord result = new IntegrityRecord(
"The association " + childOrTargetStr + " multiplicity has been violated: \n" + "The association " + childOrTargetStr + " multiplicity has been violated: \n" +

View File

@@ -29,6 +29,7 @@ import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@@ -127,13 +128,34 @@ public class AssocTargetTypeIntegrityEvent extends AbstractIntegrityEvent
} }
if (!found) if (!found)
{ {
IntegrityRecord result = new IntegrityRecord( // Actually make sure that the association still exists
"The association target is missing the aspect required for this association: \n" + if (assocDef.isChild())
" Target Node: " + targetNodeRef + "\n" + {
" Association: " + assocDef + "\n" + if (nodeService.getParentAssocs(targetNodeRef, assocDef.getName(), RegexQNamePattern.MATCH_ALL).size() == 0)
" Required Target Aspect: " + targetDef.getName() + "\n" + {
" Actual Target Aspects: " + targetAspects); // The association does not exist any more
eventResults.add(result); return;
}
}
else
{
if (nodeService.getSourceAssocs(targetNodeRef, assocDef.getName()).size() == 0)
{
// The association does not exist any more
return;
}
}
// The association is still present
if (nodeService.getSourceAssocs(targetNodeRef, assocDef.getName()).size() > 0)
{
IntegrityRecord result = new IntegrityRecord(
"The association target is missing the aspect required for this association: \n" +
" Target Node: " + targetNodeRef + "\n" +
" Association: " + assocDef + "\n" +
" Required Target Aspect: " + targetDef.getName() + "\n" +
" Actual Target Aspects: " + targetAspects);
eventResults.add(result);
}
} }
} }
else else

View File

@@ -73,6 +73,7 @@ public class IntegrityTest extends TestCase
public static final QName TEST_ASSOC_NODE_ZEROMANY_ZEROMANY = QName.createQName(NAMESPACE, "assoc-0to* - 0to*"); public static final QName TEST_ASSOC_NODE_ZEROMANY_ZEROMANY = QName.createQName(NAMESPACE, "assoc-0to* - 0to*");
public static final QName TEST_ASSOC_CHILD_ZEROMANY_ZEROMANY = QName.createQName(NAMESPACE, "child-0to* - 0to*"); public static final QName TEST_ASSOC_CHILD_ZEROMANY_ZEROMANY = QName.createQName(NAMESPACE, "child-0to* - 0to*");
public static final QName TEST_ASSOC_NODE_ONE_ONE = QName.createQName(NAMESPACE, "assoc-1to1 - 1to1"); public static final QName TEST_ASSOC_NODE_ONE_ONE = QName.createQName(NAMESPACE, "assoc-1to1 - 1to1");
public static final QName TEST_ASSOC_NODE_ONE_MANY = QName.createQName(NAMESPACE, "assoc-1to1 - 0to*");
public static final QName TEST_ASSOC_CHILD_ONE_ONE = QName.createQName(NAMESPACE, "child-1to1 - 1to1"); public static final QName TEST_ASSOC_CHILD_ONE_ONE = QName.createQName(NAMESPACE, "child-1to1 - 1to1");
public static final QName TEST_ASSOC_ASPECT_ONE_ONE = QName.createQName(NAMESPACE, "aspect-assoc-1to1 - 1to1"); public static final QName TEST_ASSOC_ASPECT_ONE_ONE = QName.createQName(NAMESPACE, "aspect-assoc-1to1 - 1to1");
public static final QName TEST_ASSOC_CHILD_NON_ENFORCED = QName.createQName(NAMESPACE, "child-non-enforced"); public static final QName TEST_ASSOC_CHILD_NON_ENFORCED = QName.createQName(NAMESPACE, "child-non-enforced");
@@ -436,4 +437,15 @@ public class IntegrityTest extends TestCase
checkIntegrityExpectFailure("Failed to detect excess target cardinality for one-to-one assocs", 3); checkIntegrityExpectFailure("Failed to detect excess target cardinality for one-to-one assocs", 3);
} }
public void testExcessTargetsOfOneToManyAssocs() throws Exception
{
NodeRef source = createNode("abc", TEST_TYPE_WITH_ASSOCS, null);
NodeRef target1 = createNode("target1", TEST_TYPE_WITHOUT_ANYTHING, null);
NodeRef target2 = createNode("target2", TEST_TYPE_WITHOUT_ANYTHING, null);
nodeService.createAssociation(source, target1, TEST_ASSOC_NODE_ONE_MANY);
nodeService.createAssociation(source, target2, TEST_ASSOC_NODE_ONE_MANY);
checkIntegrityExpectFailure("Failed to detect excess source cardinality for one-to-many assocs", 1);
}
} }

View File

@@ -91,6 +91,17 @@
<many>false</many> <many>false</many>
</target> </target>
</association> </association>
<association name="test:assoc-1to1 - 0to*">
<source>
<mandatory>true</mandatory>
<many>false</many>
</source>
<target>
<class>test:typeWithoutAnything</class>
<mandatory>false</mandatory>
<many>true</many>
</target>
</association>
</associations> </associations>
</type> </type>
<!-- Type with child assocs --> <!-- Type with child assocs -->