ACS-5471: Secondary path support (#2213)

* ACS-5471: Secondary path support

* ACS-5471: Secondary path support

* ACS-5471: Secondary path support

* ACS-5471: Secondary path support

* ACS-5471: Secondary path support

* ACS-5471: Secondary path support

* ACS-5471: Secondary path support

* ACS-5471: Secondary path support
- fixed test method name

* ACS-5471: Secondary path support
- trying to fix failing on CI DispositionScheduleLinkedRecordsTest

* ACS-5471: Secondary path support
- trying to fix failing on CI DispositionScheduleLinkedRecordsTest

* ACS-5471: Secondary path support
- trying to fix failing CI due to DispositionScheduleLinkedRecordsTest

* ACS-5471: Test adjustment to follow same behavior as introduced by ACS-5325

* ACS-5471: Fixing docker issues

---------

Co-authored-by: mpichura <maciej.pichura@hyland.com>
This commit is contained in:
Krystian Dabrowski 2023-10-06 15:36:46 +02:00 committed by GitHub
parent c157780dcb
commit 395d7ded57
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 528 additions and 191 deletions

View File

@ -35,6 +35,7 @@ import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.stream.Stream;
import io.restassured.http.ContentType; import io.restassured.http.ContentType;
import org.alfresco.rest.core.JsonBodyGenerator; import org.alfresco.rest.core.JsonBodyGenerator;
@ -51,9 +52,11 @@ import org.alfresco.rest.model.RestCommentModelsCollection;
import org.alfresco.rest.model.RestNodeAssocTargetModel; import org.alfresco.rest.model.RestNodeAssocTargetModel;
import org.alfresco.rest.model.RestNodeAssociationModel; import org.alfresco.rest.model.RestNodeAssociationModel;
import org.alfresco.rest.model.RestNodeAssociationModelCollection; import org.alfresco.rest.model.RestNodeAssociationModelCollection;
import org.alfresco.rest.model.RestNodeAssociationTypeModel;
import org.alfresco.rest.model.RestNodeBodyModel; import org.alfresco.rest.model.RestNodeBodyModel;
import org.alfresco.rest.model.RestNodeBodyMoveCopyModel; import org.alfresco.rest.model.RestNodeBodyMoveCopyModel;
import org.alfresco.rest.model.RestNodeChildAssocModelCollection; import org.alfresco.rest.model.RestNodeChildAssocModelCollection;
import org.alfresco.rest.model.RestNodeChildAssociationModel;
import org.alfresco.rest.model.RestNodeModel; import org.alfresco.rest.model.RestNodeModel;
import org.alfresco.rest.model.RestNodeModelsCollection; import org.alfresco.rest.model.RestNodeModelsCollection;
import org.alfresco.rest.model.RestRatingModel; import org.alfresco.rest.model.RestRatingModel;
@ -72,6 +75,7 @@ import org.alfresco.rest.model.body.RestNodeLockBodyModel;
import org.alfresco.rest.model.builder.NodesBuilder; import org.alfresco.rest.model.builder.NodesBuilder;
import org.alfresco.utility.Utility; import org.alfresco.utility.Utility;
import org.alfresco.utility.model.RepoTestModel; import org.alfresco.utility.model.RepoTestModel;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.testng.reporters.Files; import org.testng.reporters.Files;
@ -824,25 +828,118 @@ public class Node extends ModelRequest<Node>
} }
/** /**
* Create secondary children association using POST call 'nodes/{nodeId}/secondary-children * Creates a secondary child association using POST call to: 'nodes/{nodeId}/secondary-children'.
* Use a list of secondary children nodes
* *
* @return a collection of nodes * @param secondaryChild - node, which should become a secondary child
* @return a node's parent-child association
*/ */
public RestNodeChildAssocModelCollection createSecondaryChildren(String secondaryChildren) public RestNodeChildAssociationModel addSecondaryChild(RepoTestModel secondaryChild)
{ {
RestRequest request = RestRequest.requestWithBody(HttpMethod.POST, secondaryChildren, "nodes/{nodeId}/secondary-children?{parameters}", repoModel.getNodeRef(), restWrapper.getParameters()); return addSecondaryChild("cm:contains", secondaryChild);
}
/**
* Creates a secondary child association using POST call to: 'nodes/{nodeId}/secondary-children'.
*
* @param associationType - type of secondary parent-child relationship association
* @param secondaryChild - node, which should become a secondary child
* @return a node's parent-child association
*/
public RestNodeChildAssociationModel addSecondaryChild(String associationType, RepoTestModel secondaryChild)
{
return addSecondaryChild(new RestNodeChildAssociationModel(secondaryChild.getNodeRef(), associationType));
}
/**
* Creates a secondary child association using POST call to: 'nodes/{nodeId}/secondary-children'.
*
* @param secondaryChildAssociation - node's secondary parent-child association model
* @return a node's parent-child association
*/
public RestNodeChildAssociationModel addSecondaryChild(RestNodeChildAssociationModel secondaryChildAssociation)
{
RestRequest request = RestRequest.requestWithBody(HttpMethod.POST, secondaryChildAssociation.toJson(), "nodes/{nodeId}/secondary-children?{parameters}", repoModel.getNodeRef(), restWrapper.getParameters());
return restWrapper.processModel(RestNodeChildAssociationModel.class, request);
}
/**
* Creates a secondary children association using POST call to: 'nodes/{nodeId}/secondary-children'.
*
* @param secondaryChildren - nodes, which should become secondary children
* @return a collection of node's parent-child associations
*/
public RestNodeChildAssocModelCollection addSecondaryChildren(RepoTestModel... secondaryChildren)
{
return addSecondaryChildren("cm:contains", secondaryChildren);
}
/**
* Creates a secondary children association using POST call to: 'nodes/{nodeId}/secondary-children'.
*
* @param associationType - type of secondary parent-child relationship association
* @param secondaryChildren - nodes, which should become secondary children
* @return a collection of node's parent-child associations
*/
public RestNodeChildAssocModelCollection addSecondaryChildren(String associationType, RepoTestModel... secondaryChildren)
{
return addSecondaryChildren(Stream.of(secondaryChildren)
.map(child -> new RestNodeChildAssociationModel(child.getNodeRef(), associationType))
.toArray(RestNodeChildAssociationModel[]::new));
}
/**
* Creates a secondary children association using POST call to: 'nodes/{nodeId}/secondary-children'.
*
* @param secondaryChildrenAssociations - node's secondary parent-child association models
* @return a collection of node's parent-child associations
*/
public RestNodeChildAssocModelCollection addSecondaryChildren(RestNodeChildAssociationModel... secondaryChildrenAssociations)
{
String requestBody = arrayToJson(Stream.of(secondaryChildrenAssociations).toList());
RestRequest request = RestRequest.requestWithBody(HttpMethod.POST, requestBody, "nodes/{nodeId}/secondary-children?{parameters}", repoModel.getNodeRef(), restWrapper.getParameters());
return restWrapper.processModels(RestNodeChildAssocModelCollection.class, request); return restWrapper.processModels(RestNodeChildAssocModelCollection.class, request);
} }
/** /**
* Delete secondary children using DELETE call 'nodes/{nodeId}/secondary-children/{childId} * Removes secondary child association using DELETE call 'nodes/{nodeId}/secondary-children/{childId}'.
* *
* @return a collection of nodes * @param secondaryChild - node, which should NOT be a secondary child anymore
*/ */
public void deleteSecondaryChild(RestNodeAssociationModel child) public void removeSecondaryChild(RepoTestModel secondaryChild)
{ {
RestRequest request = RestRequest.simpleRequest(HttpMethod.DELETE, "nodes/{nodeId}/secondary-children/{childId}?{parameters}", repoModel.getNodeRef(), child.getId(), restWrapper.getParameters()); removeSecondaryChild(null, secondaryChild);
}
/**
* Removes secondary child association using DELETE call 'nodes/{nodeId}/secondary-children/{childId}'.
*
* @param associationType - type of secondary parent-child relationship association
* @param secondaryChild - node, which should NOT be a secondary child anymore
*/
public void removeSecondaryChild(String associationType, RepoTestModel secondaryChild)
{
RestNodeAssociationModel associationModel = new RestNodeAssociationModel();
RestNodeAssociationTypeModel associationTypeModel = new RestNodeAssociationTypeModel();
if (associationType != null)
{
associationTypeModel.setAssocType(associationType);
}
associationModel.setAssociation(associationTypeModel);
associationModel.setId(secondaryChild.getNodeRef());
removeSecondaryChild(associationModel);
}
/**
* Removes secondary child association using DELETE call 'nodes/{nodeId}/secondary-children/{childId}'.
*
* @param secondaryChildAssociation - node's secondary parent-child association to remove
*/
public void removeSecondaryChild(RestNodeAssociationModel secondaryChildAssociation)
{
String parameters = StringUtils.isNotEmpty(secondaryChildAssociation.getAssociation().getAssocType()) ?
"assocType=" + secondaryChildAssociation.getAssociation().getAssocType() + "&" + restWrapper.getParameters() :
restWrapper.getParameters();
RestRequest request = RestRequest.simpleRequest(HttpMethod.DELETE, "nodes/{nodeId}/secondary-children/{childId}?{parameters}", repoModel.getNodeRef(), secondaryChildAssociation.getId(), parameters);
restWrapper.processEmptyModel(request); restWrapper.processEmptyModel(request);
} }

View File

@ -125,11 +125,10 @@ public class NodesParentChildrenTests extends RestTest
RestNodeChildAssociationModel childAssoc1 = new RestNodeChildAssociationModel(nodesBuilder.getNode("f1").getId(), "cm:contains"); RestNodeChildAssociationModel childAssoc1 = new RestNodeChildAssociationModel(nodesBuilder.getNode("f1").getId(), "cm:contains");
RestNodeChildAssociationModel childAssoc2 = new RestNodeChildAssociationModel(nodesBuilder.getNode("f2").getId(), "cm:contains"); RestNodeChildAssociationModel childAssoc2 = new RestNodeChildAssociationModel(nodesBuilder.getNode("f2").getId(), "cm:contains");
RestNodeChildAssociationModel childAssoc3 = new RestNodeChildAssociationModel(nodesBuilder.getNode("f3").getId(), "cm:preferenceImage"); RestNodeChildAssociationModel childAssoc3 = new RestNodeChildAssociationModel(nodesBuilder.getNode("f3").getId(), "cm:preferenceImage");
String secondaryChildrenBody = "[" + childAssoc1.toJson() + "," + childAssoc2.toJson() + "," + childAssoc3.toJson() + "]";
STEP("3. Create secondary child associations using POST /nodes/{nodeId}/secondary-children"); STEP("3. Create secondary child associations using POST /nodes/{nodeId}/secondary-children");
RestNodeChildAssocModelCollection secondaryChildAssoc = restClient.withCoreAPI().usingNode(nodesBuilder.getNode("F1").toContentModel()) RestNodeChildAssocModelCollection secondaryChildAssoc = restClient.withCoreAPI().usingNode(nodesBuilder.getNode("F1").toContentModel())
.createSecondaryChildren(secondaryChildrenBody); .addSecondaryChildren(childAssoc1, childAssoc2, childAssoc3);
restClient.assertStatusCodeIs(HttpStatus.CREATED); restClient.assertStatusCodeIs(HttpStatus.CREATED);
secondaryChildAssoc.getEntryByIndex(0).assertThat().field("childId").is(childAssoc1.getChildId()); secondaryChildAssoc.getEntryByIndex(0).assertThat().field("childId").is(childAssoc1.getChildId());
secondaryChildAssoc.getEntryByIndex(1).assertThat().field("childId").is(childAssoc2.getChildId()); secondaryChildAssoc.getEntryByIndex(1).assertThat().field("childId").is(childAssoc2.getChildId());
@ -142,7 +141,7 @@ public class NodesParentChildrenTests extends RestTest
secondaryChildren.assertThat().entriesListCountIs(2); secondaryChildren.assertThat().entriesListCountIs(2);
STEP("5. Check using DELETE /nodes/{nodeId}/secondary-children/{childId} that a secondary child can be deleted"); STEP("5. Check using DELETE /nodes/{nodeId}/secondary-children/{childId} that a secondary child can be deleted");
restClient.withCoreAPI().usingNode(nodesBuilder.getNode("F1").toContentModel()).deleteSecondaryChild(secondaryChildren.getEntryByIndex(0)); restClient.withCoreAPI().usingNode(nodesBuilder.getNode("F1").toContentModel()).removeSecondaryChild(secondaryChildren.getEntryByIndex(0));
restClient.assertStatusCodeIs(HttpStatus.NO_CONTENT); restClient.assertStatusCodeIs(HttpStatus.NO_CONTENT);
STEP("6. Check using GET /nodes/{nodeId}/secondary-children that a secondary child association was deleted"); STEP("6. Check using GET /nodes/{nodeId}/secondary-children that a secondary child association was deleted");
@ -182,7 +181,7 @@ public class NodesParentChildrenTests extends RestTest
STEP("2. Create secondary child associations using POST /nodes/{nodeId}/secondary-children"); STEP("2. Create secondary child associations using POST /nodes/{nodeId}/secondary-children");
RestNodeChildAssociationModel childAssoc = new RestNodeChildAssociationModel(nodesBuilder.getNode("f1").getId(), "cm:contains"); RestNodeChildAssociationModel childAssoc = new RestNodeChildAssociationModel(nodesBuilder.getNode("f1").getId(), "cm:contains");
restClient.withCoreAPI().usingNode(nodesBuilder.getNode("F1").toContentModel()).createSecondaryChildren(childAssoc.toJson()); restClient.withCoreAPI().usingNode(nodesBuilder.getNode("F1").toContentModel()).addSecondaryChild(childAssoc);
restClient.assertStatusCodeIs(HttpStatus.CREATED); restClient.assertStatusCodeIs(HttpStatus.CREATED);
STEP("3. Get all parents for file 'f1' - both primary and secondary"); STEP("3. Get all parents for file 'f1' - both primary and secondary");

View File

@ -54,7 +54,7 @@
<dependency.alfresco-transform-core.version>5.0.0-A3</dependency.alfresco-transform-core.version> <dependency.alfresco-transform-core.version>5.0.0-A3</dependency.alfresco-transform-core.version>
<dependency.alfresco-transform-service.version>4.0.0-A3</dependency.alfresco-transform-service.version> <dependency.alfresco-transform-service.version>4.0.0-A3</dependency.alfresco-transform-service.version>
<dependency.alfresco-greenmail.version>7.0</dependency.alfresco-greenmail.version> <dependency.alfresco-greenmail.version>7.0</dependency.alfresco-greenmail.version>
<dependency.acs-event-model.version>0.0.23</dependency.acs-event-model.version> <dependency.acs-event-model.version>0.0.24</dependency.acs-event-model.version>
<dependency.aspectj.version>1.9.20.1</dependency.aspectj.version> <dependency.aspectj.version>1.9.20.1</dependency.aspectj.version>
<dependency.spring.version>6.0.12</dependency.spring.version> <dependency.spring.version>6.0.12</dependency.spring.version>

View File

@ -311,12 +311,24 @@ public class EventGenerator extends AbstractLifecycleBean implements Initializin
public void onCreateChildAssociation(ChildAssociationRef childAssociationRef, boolean isNewNode) public void onCreateChildAssociation(ChildAssociationRef childAssociationRef, boolean isNewNode)
{ {
getEventConsolidator(childAssociationRef).onCreateChildAssociation(childAssociationRef, isNewNode); getEventConsolidator(childAssociationRef).onCreateChildAssociation(childAssociationRef, isNewNode);
if (!childAssociationRef.isPrimary())
{
// if this is a secondary relationship simulate node move event to store state of previous secondary parents
ChildAssociationRef oldChildAssociationRef = childAssociationWithoutParentOf(childAssociationRef);
getEventConsolidator(childAssociationRef.getChildRef()).onMoveNode(oldChildAssociationRef, childAssociationRef);
}
} }
@Override @Override
public void beforeDeleteChildAssociation(ChildAssociationRef childAssociationRef) public void beforeDeleteChildAssociation(ChildAssociationRef childAssociationRef)
{ {
getEventConsolidator(childAssociationRef).beforeDeleteChildAssociation(childAssociationRef); getEventConsolidator(childAssociationRef).beforeDeleteChildAssociation(childAssociationRef);
if (!childAssociationRef.isPrimary())
{
// if this is a secondary relationship simulate node move event to store state of previous secondary parents
ChildAssociationRef newChildAssociationRef = childAssociationWithoutParentOf(childAssociationRef);
getEventConsolidator(childAssociationRef.getChildRef()).onMoveNode(childAssociationRef, newChildAssociationRef);
}
} }
@Override @Override
@ -503,6 +515,18 @@ public class EventGenerator extends AbstractLifecycleBean implements Initializin
return ZonedDateTime.ofInstant(commitTimeMs, ZoneOffset.UTC); return ZonedDateTime.ofInstant(commitTimeMs, ZoneOffset.UTC);
} }
private static ChildAssociationRef childAssociationWithoutParentOf(ChildAssociationRef childAssociationRef)
{
return new ChildAssociationRef(
null,
null,
childAssociationRef.getQName(),
childAssociationRef.getChildRef(),
childAssociationRef.isPrimary(),
childAssociationRef.getNthSibling()
);
}
@Override @Override
protected void onBootstrap(ApplicationEvent applicationEvent) protected void onBootstrap(ApplicationEvent applicationEvent)
{ {

View File

@ -65,6 +65,7 @@ public class NodeEventConsolidator extends EventConsolidator<NodeRef, NodeResour
private QName nodeType; private QName nodeType;
private QName nodeTypeBefore; private QName nodeTypeBefore;
private List<String> primaryHierarchyBefore; private List<String> primaryHierarchyBefore;
private List<String> secondaryParentsBefore;
private boolean resourceBeforeAllFieldsNull = true; private boolean resourceBeforeAllFieldsNull = true;
public NodeEventConsolidator(NodeResourceHelper nodeResourceHelper) public NodeEventConsolidator(NodeResourceHelper nodeResourceHelper)
@ -144,8 +145,26 @@ public class NodeEventConsolidator extends EventConsolidator<NodeRef, NodeResour
eventTypes.add(EventType.NODE_UPDATED); eventTypes.add(EventType.NODE_UPDATED);
createBuilderIfAbsent(newChildAssocRef.getChildRef()); createBuilderIfAbsent(newChildAssocRef.getChildRef());
if (newChildAssocRef.isPrimary())
{
setBeforePrimaryHierarchy(helper.getPrimaryHierarchy(oldChildAssocRef.getParentRef(), true)); setBeforePrimaryHierarchy(helper.getPrimaryHierarchy(oldChildAssocRef.getParentRef(), true));
} }
else
{
List<String> secondaryParents = helper.getSecondaryParents(newChildAssocRef.getChildRef());
if (newChildAssocRef.getParentRef() != null)
{
// on create secondary child association event takes place - recreate secondary parents previous state
secondaryParents.remove(newChildAssocRef.getParentRef().getId());
}
else if(oldChildAssocRef.getParentRef() != null && !secondaryParents.contains(oldChildAssocRef.getParentRef().getId()))
{
// before remove secondary child association event takes place - recreate secondary parents previous state
secondaryParents.add(oldChildAssocRef.getParentRef().getId());
}
setSecondaryParentsBefore(secondaryParents);
}
}
@Override @Override
public void onSetNodeType(NodeRef nodeRef, QName before, QName after) public void onSetNodeType(NodeRef nodeRef, QName before, QName after)
@ -174,7 +193,7 @@ public class NodeEventConsolidator extends EventConsolidator<NodeRef, NodeResour
public void beforeDeleteNode(NodeRef nodeRef) public void beforeDeleteNode(NodeRef nodeRef)
{ {
eventTypes.add(EventType.NODE_DELETED); eventTypes.add(EventType.NODE_DELETED);
createBuilderIfAbsent(nodeRef, false); createBuilderIfAbsent(nodeRef);
} }
@Override @Override
@ -240,6 +259,19 @@ public class NodeEventConsolidator extends EventConsolidator<NodeRef, NodeResour
} }
} }
private void setSecondaryParentsBefore(List<String> secondaryParents)
{
if (this.secondaryParentsBefore == null)
{
this.secondaryParentsBefore = secondaryParents;
}
}
List<String> getSecondaryParentsBefore()
{
return secondaryParentsBefore;
}
private NodeResource buildNodeResource() private NodeResource buildNodeResource()
{ {
if (resourceBuilder == null) if (resourceBuilder == null)
@ -283,7 +315,7 @@ public class NodeEventConsolidator extends EventConsolidator<NodeRef, NodeResour
resourceBeforeAllFieldsNull = false; resourceBeforeAllFieldsNull = false;
} }
Map<String, Map<String, String>> localizedProps =helper.getLocalizedPropertiesBefore(changedPropsBefore, after); Map<String, Map<String, String>> localizedProps = helper.getLocalizedPropertiesBefore(changedPropsBefore, after);
if (!localizedProps.isEmpty()) if (!localizedProps.isEmpty())
{ {
builder.setLocalizedProperties(localizedProps); builder.setLocalizedProperties(localizedProps);
@ -309,8 +341,7 @@ public class NodeEventConsolidator extends EventConsolidator<NodeRef, NodeResour
builder.setModifiedByUser(modifier); builder.setModifiedByUser(modifier);
resourceBeforeAllFieldsNull = false; resourceBeforeAllFieldsNull = false;
} }
modifiedAt = modifiedAt = helper.getZonedDateTime((Date) changedPropsBefore.get(ContentModel.PROP_MODIFIED));
helper.getZonedDateTime((Date) changedPropsBefore.get(ContentModel.PROP_MODIFIED));
} }
// Handle case where the content does not exist on the propertiesBefore // Handle case where the content does not exist on the propertiesBefore
@ -334,6 +365,12 @@ public class NodeEventConsolidator extends EventConsolidator<NodeRef, NodeResour
resourceBeforeAllFieldsNull = false; resourceBeforeAllFieldsNull = false;
} }
if (secondaryParentsBefore != null)
{
builder.setSecondaryParents(secondaryParentsBefore);
resourceBeforeAllFieldsNull = false;
}
if (nodeTypeBefore != null) if (nodeTypeBefore != null)
{ {
builder.setNodeType(helper.getQNamePrefixString(nodeTypeBefore)); builder.setNodeType(helper.getQNamePrefixString(nodeTypeBefore));

View File

@ -26,6 +26,7 @@
package org.alfresco.repo.event2; package org.alfresco.repo.event2;
import static java.util.Optional.ofNullable; import static java.util.Optional.ofNullable;
import static java.util.function.Predicate.not;
import java.io.Serializable; import java.io.Serializable;
import java.time.ZoneId; import java.time.ZoneId;
@ -38,6 +39,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
@ -145,7 +147,8 @@ public class NodeResourceHelper implements InitializingBean
// minor: save one lookup if creator & modifier are the same // minor: save one lookup if creator & modifier are the same
Map<String, UserInfo> mapUserCache = new HashMap<>(2); Map<String, UserInfo> mapUserCache = new HashMap<>(2);
return NodeResource.builder().setId(nodeRef.getId()) return NodeResource.builder()
.setId(nodeRef.getId())
.setName((String) properties.get(ContentModel.PROP_NAME)) .setName((String) properties.get(ContentModel.PROP_NAME))
.setNodeType(getQNamePrefixString(type)) .setNodeType(getQNamePrefixString(type))
.setIsFile(isSubClass(type, ContentModel.TYPE_CONTENT)) .setIsFile(isSubClass(type, ContentModel.TYPE_CONTENT))
@ -159,7 +162,8 @@ public class NodeResourceHelper implements InitializingBean
.setPrimaryHierarchy(PathUtil.getNodeIdsInReverse(path, false)) .setPrimaryHierarchy(PathUtil.getNodeIdsInReverse(path, false))
.setProperties(mapToNodeProperties(properties)) .setProperties(mapToNodeProperties(properties))
.setLocalizedProperties(mapToNodeLocalizedProperties(properties)) .setLocalizedProperties(mapToNodeLocalizedProperties(properties))
.setAspectNames(getMappedAspects(nodeRef)); .setAspectNames(getMappedAspects(nodeRef))
.setSecondaryParents(getSecondaryParents(nodeRef));
} }
private boolean isSubClass(QName className, QName ofClassQName) private boolean isSubClass(QName className, QName ofClassQName)
@ -413,6 +417,21 @@ public class NodeResourceHelper implements InitializingBean
return PathUtil.getNodeIdsInReverse(path, showLeaf); return PathUtil.getNodeIdsInReverse(path, showLeaf);
} }
/**
* Gathers node's secondary parents.
*
* @param nodeRef - node reference
* @return a list of node's secondary parents.
*/
public List<String> getSecondaryParents(final NodeRef nodeRef)
{
return nodeService.getParentAssocs(nodeRef).stream()
.filter(not(ChildAssociationRef::isPrimary))
.map(ChildAssociationRef::getParentRef)
.map(NodeRef::getId)
.collect(Collectors.toList());
}
public PermissionService getPermissionService() public PermissionService getPermissionService()
{ {
return permissionService; return permissionService;

View File

@ -1231,6 +1231,7 @@ repo.event2.filter.users=
repo.event2.topic.endpoint=amqp:topic:alfresco.repo.event2 repo.event2.topic.endpoint=amqp:topic:alfresco.repo.event2
# Specifies if messages should be enqueued in in-memory queue or sent directly to the topic # Specifies if messages should be enqueued in in-memory queue or sent directly to the topic
repo.event2.queue.skip=false repo.event2.queue.skip=false
#repo.event2.topic.endpoint=amqp:topic:VirtualTopic.alfresco.repo.event2
# Thread pool for async enqueue of repo events # Thread pool for async enqueue of repo events
repo.event2.queue.enqueueThreadPool.priority=1 repo.event2.queue.enqueueThreadPool.priority=1
repo.event2.queue.enqueueThreadPool.coreSize=8 repo.event2.queue.enqueueThreadPool.coreSize=8

View File

@ -28,6 +28,7 @@ package org.alfresco.repo.event2;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.stream.IntStream;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.repo.event.v1.model.ChildAssociationResource; import org.alfresco.repo.event.v1.model.ChildAssociationResource;
@ -64,8 +65,7 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(),
resultRepoEvent.getType()); resultRepoEvent.getType());
retryingTransactionHelper.doInTransaction(() -> retryingTransactionHelper.doInTransaction(() -> nodeService.addChild(
nodeService.addChild(
parentNodeRef, parentNodeRef,
childNodeRef, childNodeRef,
ContentModel.ASSOC_CONTAINS, ContentModel.ASSOC_CONTAINS,
@ -79,8 +79,30 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
checkNumOfEvents(4); checkNumOfEvents(4);
final RepoEvent<EventData<ChildAssociationResource>> childAssocRepoEvent = getFilteredEvent(EventType.CHILD_ASSOC_CREATED, 0); // node event
final RepoEvent<EventData<NodeResource>> nodeRepoEvent = getRepoEventWithoutWait(3);
assertEquals("Wrong repo event type.", EventType.NODE_UPDATED.getType(), nodeRepoEvent.getType());
assertNotNull("Repo event ID is not available.", nodeRepoEvent.getId());
assertNotNull("Source is not available", nodeRepoEvent.getSource());
assertEquals("Repo event source is not available.",
"/" + descriptorService.getCurrentRepositoryDescriptor().getId(),
nodeRepoEvent.getSource().toString());
assertNotNull("Repo event creation time is not available.", nodeRepoEvent.getTime());
assertEquals("Invalid repo event datacontenttype", "application/json",
nodeRepoEvent.getDatacontenttype());
assertNotNull(nodeRepoEvent.getDataschema());
assertEquals(EventJSONSchema.NODE_UPDATED_V1.getSchema(), nodeRepoEvent.getDataschema());
final EventData<NodeResource> nodeResourceEventData = getEventData(nodeRepoEvent);
assertNotNull("Event data group ID is not available. ", nodeResourceEventData.getEventGroupId());
assertNotNull("resourceBefore property is not available", nodeResourceEventData.getResourceBefore());
final NodeResource nodeResource = getNodeResource(nodeRepoEvent);
final NodeResource nodeResourceBefore = getNodeResourceBefore(nodeRepoEvent);
assertNotSame("Secondary parents actual and earlier state should differ", nodeResource.getSecondaryParents(), nodeResourceBefore.getSecondaryParents());
// child association event
final RepoEvent<EventData<ChildAssociationResource>> childAssocRepoEvent = getFilteredEvent(EventType.CHILD_ASSOC_CREATED, 0);
assertEquals("Wrong repo event type.", EventType.CHILD_ASSOC_CREATED.getType(), childAssocRepoEvent.getType()); assertEquals("Wrong repo event type.", EventType.CHILD_ASSOC_CREATED.getType(), childAssocRepoEvent.getType());
assertNotNull("Repo event ID is not available.", childAssocRepoEvent.getId()); assertNotNull("Repo event ID is not available.", childAssocRepoEvent.getId());
assertNotNull("Source is not available", childAssocRepoEvent.getSource()); assertNotNull("Source is not available", childAssocRepoEvent.getSource());
@ -93,16 +115,18 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
assertNotNull(childAssocRepoEvent.getDataschema()); assertNotNull(childAssocRepoEvent.getDataschema());
assertEquals(EventJSONSchema.CHILD_ASSOC_CREATED_V1.getSchema(), childAssocRepoEvent.getDataschema()); assertEquals(EventJSONSchema.CHILD_ASSOC_CREATED_V1.getSchema(), childAssocRepoEvent.getDataschema());
final EventData<ChildAssociationResource> nodeResourceEventData = getEventData(childAssocRepoEvent); final EventData<ChildAssociationResource> childAssocResourceEventData = getEventData(childAssocRepoEvent);
// EventData attributes assertNotNull("Event data group ID is not available. ", childAssocResourceEventData.getEventGroupId());
assertNotNull("Event data group ID is not available. ", nodeResourceEventData.getEventGroupId()); assertNull("resourceBefore property is not available", childAssocResourceEventData.getResourceBefore());
assertNull("resourceBefore property is not available", nodeResourceEventData.getResourceBefore());
final ChildAssociationResource childAssociationResource = getChildAssocResource(childAssocRepoEvent); final ChildAssociationResource childAssociationResource = getChildAssocResource(childAssocRepoEvent);
assertEquals("Wrong parent", parentNodeRef.getId(), childAssociationResource.getParent().getId()); assertEquals("Wrong parent", parentNodeRef.getId(), childAssociationResource.getParent().getId());
assertEquals("Wrong child", childNodeRef.getId(), childAssociationResource.getChild().getId()); assertEquals("Wrong child", childNodeRef.getId(), childAssociationResource.getChild().getId());
assertEquals("Wrong assoc type", "cm:contains", childAssociationResource.getAssocType()); assertEquals("Wrong assoc type", "cm:contains", childAssociationResource.getAssocType());
assertEquals("Wrong assoc name", "ce:" + assocLocalName, childAssociationResource.getAssocQName()); assertEquals("Wrong assoc name", "ce:" + assocLocalName, childAssociationResource.getAssocQName());
assertEquals("Node and child association events should have same eventGroupId", nodeResourceEventData.getEventGroupId(), childAssocResourceEventData.getEventGroupId());
assertTrue("Wrong node's secondary parents", nodeResource.getSecondaryParents().contains(childAssociationResource.getParent().getId()));
} }
@Test @Test
@ -143,8 +167,30 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
checkNumOfEvents(6); checkNumOfEvents(6);
final RepoEvent<EventData<ChildAssociationResource>> childAssocRepoEvent = getFilteredEvent(EventType.CHILD_ASSOC_DELETED, 0); // node repo event
final RepoEvent<EventData<NodeResource>> nodeRepoEvent = getRepoEventWithoutWait(5);
assertEquals("Wrong repo event type.", EventType.NODE_UPDATED.getType(), nodeRepoEvent.getType());
assertNotNull("Repo event ID is not available.", nodeRepoEvent.getId());
assertNotNull("Source is not available", nodeRepoEvent.getSource());
assertEquals("Repo event source is not available.",
"/" + descriptorService.getCurrentRepositoryDescriptor().getId(),
nodeRepoEvent.getSource().toString());
assertNotNull("Repo event creation time is not available.", nodeRepoEvent.getTime());
assertEquals("Invalid repo event datacontenttype", "application/json",
nodeRepoEvent.getDatacontenttype());
assertNotNull(nodeRepoEvent.getDataschema());
assertEquals(EventJSONSchema.NODE_UPDATED_V1.getSchema(), nodeRepoEvent.getDataschema());
final EventData<NodeResource> nodeResourceEventData = getEventData(nodeRepoEvent);
assertNotNull("Event data group ID is not available. ", nodeResourceEventData.getEventGroupId());
assertNotNull("resourceBefore property is not available", nodeResourceEventData.getResourceBefore());
final NodeResource nodeResource = getNodeResource(nodeRepoEvent);
final NodeResource nodeResourceBefore = getNodeResourceBefore(nodeRepoEvent);
assertNotSame("Secondary parents actual and earlier state should differ", nodeResource.getSecondaryParents(), nodeResourceBefore.getSecondaryParents());
// child association repo event
final RepoEvent<EventData<ChildAssociationResource>> childAssocRepoEvent = getFilteredEvent(EventType.CHILD_ASSOC_DELETED, 0);
assertEquals("Wrong repo event type.", EventType.CHILD_ASSOC_DELETED.getType(), childAssocRepoEvent.getType()); assertEquals("Wrong repo event type.", EventType.CHILD_ASSOC_DELETED.getType(), childAssocRepoEvent.getType());
assertNotNull("Repo event ID is not available. ", childAssocRepoEvent.getId()); assertNotNull("Repo event ID is not available. ", childAssocRepoEvent.getId());
assertNotNull("Source is not available", childAssocRepoEvent.getSource()); assertNotNull("Source is not available", childAssocRepoEvent.getSource());
@ -156,15 +202,17 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
assertNotNull(childAssocRepoEvent.getDataschema()); assertNotNull(childAssocRepoEvent.getDataschema());
assertEquals(EventJSONSchema.CHILD_ASSOC_DELETED_V1.getSchema(), childAssocRepoEvent.getDataschema()); assertEquals(EventJSONSchema.CHILD_ASSOC_DELETED_V1.getSchema(), childAssocRepoEvent.getDataschema());
final EventData<ChildAssociationResource> nodeResourceEventData = getEventData(childAssocRepoEvent); final EventData<ChildAssociationResource> childAssocResourceEventData = getEventData(childAssocRepoEvent);
// EventData attributes assertNotNull("Event data group ID is not available. ", childAssocResourceEventData.getEventGroupId());
assertNotNull("Event data group ID is not available. ", nodeResourceEventData.getEventGroupId()); assertNull("resourceBefore property is not available", childAssocResourceEventData.getResourceBefore());
assertNull("resourceBefore property is not available", nodeResourceEventData.getResourceBefore());
final ChildAssociationResource childAssociationResource = getChildAssocResource(childAssocRepoEvent); final ChildAssociationResource childAssociationResource = getChildAssocResource(childAssocRepoEvent);
assertEquals("Wrong parent", parentNodeRef.getId(), childAssociationResource.getParent().getId()); assertEquals("Wrong parent", parentNodeRef.getId(), childAssociationResource.getParent().getId());
assertEquals("Wrong child", childNodeRef.getId(), childAssociationResource.getChild().getId()); assertEquals("Wrong child", childNodeRef.getId(), childAssociationResource.getChild().getId());
assertEquals("Wrong assoc type", "cm:contains", childAssociationResource.getAssocType()); assertEquals("Wrong assoc type", "cm:contains", childAssociationResource.getAssocType());
assertEquals("Node and child association events should have same eventGroupId", nodeResourceEventData.getEventGroupId(), childAssocResourceEventData.getEventGroupId());
assertTrue("Wrong node's secondary parents", nodeResourceBefore.getSecondaryParents().contains(childAssociationResource.getParent().getId()));
} }
@Test @Test
@ -179,17 +227,10 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
checkNumOfEvents(4); checkNumOfEvents(4);
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(1); IntStream.of(1, 2, 3, 4).forEach(i -> {
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType()); RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(i);
resultRepoEvent = getRepoEventWithoutWait(2);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
resultRepoEvent = getRepoEventWithoutWait(3);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
resultRepoEvent = getRepoEventWithoutWait(4);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType()); assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
});
retryingTransactionHelper.doInTransaction(() -> retryingTransactionHelper.doInTransaction(() ->
nodeService.addChild( nodeService.addChild(
@ -214,10 +255,13 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
checkNumOfEvents(8); checkNumOfEvents(8);
// 3 assoc.child.Created events should be created // 1 node.Updated events should be created
List<RepoEvent<EventData<NodeResource>>> nodeUpdateEvent = getFilteredEvents(EventType.NODE_UPDATED);
assertEquals("Wrong association events number", 1, nodeUpdateEvent.size());
// 3 assoc.child.Created events should be created
List<RepoEvent<EventData<ChildAssociationResource>>> childAssocEvents = getFilteredEvents(EventType.CHILD_ASSOC_CREATED); List<RepoEvent<EventData<ChildAssociationResource>>> childAssocEvents = getFilteredEvents(EventType.CHILD_ASSOC_CREATED);
assertEquals("Wrong association events number",3, childAssocEvents.size()); assertEquals("Wrong association events number", 3, childAssocEvents.size());
} }
@Test @Test
@ -231,17 +275,10 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
List<NodeRef> parents = Arrays.asList(parent1NodeRef, parent2NodeRef, parent3NodeRef); List<NodeRef> parents = Arrays.asList(parent1NodeRef, parent2NodeRef, parent3NodeRef);
checkNumOfEvents(4); checkNumOfEvents(4);
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(1); IntStream.of(1, 2, 3, 4).forEach(i -> {
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType()); RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(i);
resultRepoEvent = getRepoEventWithoutWait(1);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
resultRepoEvent = getRepoEventWithoutWait(1);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
resultRepoEvent = getRepoEventWithoutWait(1);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType()); assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
});
retryingTransactionHelper.doInTransaction(() -> { retryingTransactionHelper.doInTransaction(() -> {
for (NodeRef parent : parents) for (NodeRef parent : parents)
@ -269,9 +306,13 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
}); });
checkNumOfEvents(8); checkNumOfEvents(8);
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(5);
assertEquals("Wrong repo event type.", EventType.NODE_UPDATED.getType(), resultRepoEvent.getType());
// 3 assoc.child.Created events should be created // 3 assoc.child.Created events should be created
List<RepoEvent<EventData<ChildAssociationResource>>> childAssocEvents = getFilteredEvents(EventType.CHILD_ASSOC_CREATED); List<RepoEvent<EventData<ChildAssociationResource>>> childAssocEvents = getFilteredEvents(EventType.CHILD_ASSOC_CREATED);
assertEquals("Wrong association events number",3, childAssocEvents.size()); assertEquals("Wrong association events number", 3, childAssocEvents.size());
// All events in the transaction should have the same eventGroupId // All events in the transaction should have the same eventGroupId
String assocEventGroupID1 = getEventData(childAssocEvents.get(0)).getEventGroupId(); String assocEventGroupID1 = getEventData(childAssocEvents.get(0)).getEventGroupId();
@ -294,17 +335,10 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
checkNumOfEvents(4); checkNumOfEvents(4);
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(1); IntStream.of(1, 2, 3, 4).forEach(i -> {
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType()); RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(i);
resultRepoEvent = getRepoEventWithoutWait(2);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
resultRepoEvent = getRepoEventWithoutWait(3);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
resultRepoEvent = getRepoEventWithoutWait(4);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType()); assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
});
for (NodeRef parent : parents) for (NodeRef parent : parents)
{ {
@ -331,9 +365,14 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
}); });
checkNumOfEvents(10); checkNumOfEvents(10);
// 3 node.Updated events should be created
List<RepoEvent<EventData<ChildAssociationResource>>> nodeUpdateEvents = getFilteredEvents(EventType.NODE_UPDATED);
assertEquals("Wrong node update events number", 3, nodeUpdateEvents.size());
// 3 assoc.child.Created events should be created // 3 assoc.child.Created events should be created
List<RepoEvent<EventData<ChildAssociationResource>>> childAssocEvents = getFilteredEvents(EventType.CHILD_ASSOC_CREATED); List<RepoEvent<EventData<ChildAssociationResource>>> childAssocEvents = getFilteredEvents(EventType.CHILD_ASSOC_CREATED);
assertEquals("Wrong association events number",3, childAssocEvents.size()); assertEquals("Wrong association events number", 3, childAssocEvents.size());
assertEquals(parent1NodeRef.getId(), getChildAssocResource(childAssocEvents.get(0)).getParent().getId()); assertEquals(parent1NodeRef.getId(), getChildAssocResource(childAssocEvents.get(0)).getParent().getId());
assertEquals(childNodeRef.getId(), getChildAssocResource(childAssocEvents.get(0)).getChild().getId()); assertEquals(childNodeRef.getId(), getChildAssocResource(childAssocEvents.get(0)).getChild().getId());
@ -360,17 +399,10 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
checkNumOfEvents(4); checkNumOfEvents(4);
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(1); IntStream.of(1, 2, 3, 4).forEach(i -> {
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType()); RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(i);
resultRepoEvent = getRepoEventWithoutWait(2);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
resultRepoEvent = getRepoEventWithoutWait(3);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
resultRepoEvent = getRepoEventWithoutWait(4);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType()); assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
});
retryingTransactionHelper.doInTransaction(() -> { retryingTransactionHelper.doInTransaction(() -> {
for (NodeRef child : children) for (NodeRef child : children)
@ -389,9 +421,14 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
}); });
checkNumOfEvents(10); checkNumOfEvents(10);
// 3 node.Updated events should be created
List<RepoEvent<EventData<ChildAssociationResource>>> nodeUpdateEvents = getFilteredEvents(EventType.NODE_UPDATED);
assertEquals("Wrong node update events number", 3, nodeUpdateEvents.size());
// 3 assoc.child.Created events should be created // 3 assoc.child.Created events should be created
List<RepoEvent<EventData<ChildAssociationResource>>> childAssocEvents = getFilteredEvents(EventType.CHILD_ASSOC_CREATED); List<RepoEvent<EventData<ChildAssociationResource>>> childAssocEvents = getFilteredEvents(EventType.CHILD_ASSOC_CREATED);
assertEquals("Wrong association events number",3, childAssocEvents.size()); assertEquals("Wrong association events number", 3, childAssocEvents.size());
} }
@Test @Test
@ -406,17 +443,10 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
checkNumOfEvents(4); checkNumOfEvents(4);
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(1); IntStream.of(1, 2, 3, 4).forEach(i -> {
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType()); RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(i);
resultRepoEvent = getRepoEventWithoutWait(2);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
resultRepoEvent = getRepoEventWithoutWait(3);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
resultRepoEvent = getRepoEventWithoutWait(4);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType()); assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
});
for (NodeRef child : children) for (NodeRef child : children)
{ {
@ -433,9 +463,14 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
}); });
checkNumOfEvents(10); checkNumOfEvents(10);
// 3 node.Updated events should be created
List<RepoEvent<EventData<ChildAssociationResource>>> nodeUpdateEvents = getFilteredEvents(EventType.NODE_UPDATED);
assertEquals("Wrong node update events number", 3, nodeUpdateEvents.size());
// 3 assoc.child.Created events should be created // 3 assoc.child.Created events should be created
List<RepoEvent<EventData<ChildAssociationResource>>> childAssocEvents = getFilteredEvents(EventType.CHILD_ASSOC_CREATED); List<RepoEvent<EventData<ChildAssociationResource>>> childAssocEvents = getFilteredEvents(EventType.CHILD_ASSOC_CREATED);
assertEquals("Wrong association events number",3, childAssocEvents.size()); assertEquals("Wrong association events number", 3, childAssocEvents.size());
assertEquals(parentNodeRef.getId(), getChildAssocResource(childAssocEvents.get(0)).getParent().getId()); assertEquals(parentNodeRef.getId(), getChildAssocResource(childAssocEvents.get(0)).getParent().getId());
assertEquals(child1NodeRef.getId(), getChildAssocResource(childAssocEvents.get(0)).getChild().getId()); assertEquals(child1NodeRef.getId(), getChildAssocResource(childAssocEvents.get(0)).getChild().getId());
@ -462,17 +497,10 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
checkNumOfEvents(4); checkNumOfEvents(4);
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(1); IntStream.of(1, 2, 3, 4).forEach(i -> {
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType()); RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(i);
resultRepoEvent = getRepoEventWithoutWait(2);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
resultRepoEvent = getRepoEventWithoutWait(3);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
resultRepoEvent = getRepoEventWithoutWait(4);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType()); assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
});
retryingTransactionHelper.doInTransaction(() -> retryingTransactionHelper.doInTransaction(() ->
nodeService.addChild(parents, childNodeRef, ContentModel.ASSOC_CONTAINS, nodeService.addChild(parents, childNodeRef, ContentModel.ASSOC_CONTAINS,
@ -503,13 +531,17 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
checkNumOfEvents(12); checkNumOfEvents(12);
// 2 node.Updated events should be created
List<RepoEvent<EventData<ChildAssociationResource>>> nodeUpdateEvents = getFilteredEvents(EventType.NODE_UPDATED);
assertEquals("Wrong node update events number", 2, nodeUpdateEvents.size());
// 3 assoc.child.Deleted events should be created // 3 assoc.child.Deleted events should be created
List<RepoEvent<EventData<ChildAssociationResource>>> childAssocEvents = getFilteredEvents(EventType.CHILD_ASSOC_DELETED); List<RepoEvent<EventData<ChildAssociationResource>>> childAssocEvents = getFilteredEvents(EventType.CHILD_ASSOC_DELETED);
assertEquals("Wrong association events number",3, childAssocEvents.size()); assertEquals("Wrong association events number", 3, childAssocEvents.size());
} }
@Test @Test
public void testDeleteAssociationOneParentMultipleChildrenDifferentTransactions() public void testDeleteAssociationMultipleParentOneChildrenDifferentTransactions()
{ {
final NodeRef parent1NodeRef = createNode(ContentModel.TYPE_FOLDER); final NodeRef parent1NodeRef = createNode(ContentModel.TYPE_FOLDER);
final NodeRef parent2NodeRef = createNode(ContentModel.TYPE_FOLDER); final NodeRef parent2NodeRef = createNode(ContentModel.TYPE_FOLDER);
@ -520,17 +552,10 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
checkNumOfEvents(4); checkNumOfEvents(4);
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(1); IntStream.of(1, 2, 3, 4).forEach(i -> {
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType()); RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(i);
resultRepoEvent = getRepoEventWithoutWait(2);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
resultRepoEvent = getRepoEventWithoutWait(3);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
resultRepoEvent = getRepoEventWithoutWait(4);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType()); assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
});
retryingTransactionHelper.doInTransaction(() -> retryingTransactionHelper.doInTransaction(() ->
nodeService.addChild(parents, childNodeRef, ContentModel.ASSOC_CONTAINS, nodeService.addChild(parents, childNodeRef, ContentModel.ASSOC_CONTAINS,
@ -588,17 +613,10 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
checkNumOfEvents(4); checkNumOfEvents(4);
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(1); IntStream.of(1, 2, 3, 4).forEach(i -> {
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType()); RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(i);
resultRepoEvent = getRepoEventWithoutWait(2);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
resultRepoEvent = getRepoEventWithoutWait(3);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
resultRepoEvent = getRepoEventWithoutWait(4);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType()); assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
});
retryingTransactionHelper.doInTransaction(() -> { retryingTransactionHelper.doInTransaction(() -> {
for (NodeRef child : children) for (NodeRef child : children)
@ -621,9 +639,13 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
checkNumOfEvents(17); checkNumOfEvents(17);
// 6 node.Updated events should be created
List<RepoEvent<EventData<ChildAssociationResource>>> nodeUpdateEvents = getFilteredEvents(EventType.NODE_UPDATED);
assertEquals("Wrong node update events number", 6, nodeUpdateEvents.size());
// 3 assoc.child.Deleted events should be created // 3 assoc.child.Deleted events should be created
List<RepoEvent<EventData<ChildAssociationResource>>> childAssocEvents = getFilteredEvents(EventType.CHILD_ASSOC_DELETED); List<RepoEvent<EventData<ChildAssociationResource>>> childAssocEvents = getFilteredEvents(EventType.CHILD_ASSOC_DELETED);
assertEquals("Wrong association events number",3, childAssocEvents.size()); assertEquals("Wrong association events number", 3, childAssocEvents.size());
} }
@Test @Test
@ -638,17 +660,10 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
checkNumOfEvents(4); checkNumOfEvents(4);
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(1); IntStream.of(1, 2, 3, 4).forEach(i -> {
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType()); RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(i);
resultRepoEvent = getRepoEventWithoutWait(2);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
resultRepoEvent = getRepoEventWithoutWait(3);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
resultRepoEvent = getRepoEventWithoutWait(4);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType()); assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
});
retryingTransactionHelper.doInTransaction(() -> retryingTransactionHelper.doInTransaction(() ->
nodeService.addChild(parents, childNodeRef, ContentModel.ASSOC_CONTAINS, nodeService.addChild(parents, childNodeRef, ContentModel.ASSOC_CONTAINS,
@ -672,9 +687,13 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
checkNumOfEvents(12); checkNumOfEvents(12);
// 2 node.Updated events should be created
List<RepoEvent<EventData<ChildAssociationResource>>> nodeUpdateEvents = getFilteredEvents(EventType.NODE_UPDATED);
assertEquals("Wrong node update events number", 2, nodeUpdateEvents.size());
// 3 assoc.child.Deleted events should be created // 3 assoc.child.Deleted events should be created
List<RepoEvent<EventData<ChildAssociationResource>>> childAssocEvents = getFilteredEvents(EventType.CHILD_ASSOC_DELETED); List<RepoEvent<EventData<ChildAssociationResource>>> childAssocEvents = getFilteredEvents(EventType.CHILD_ASSOC_DELETED);
assertEquals("Wrong association events number",3, childAssocEvents.size()); assertEquals("Wrong association events number", 3, childAssocEvents.size());
} }
@Test @Test
@ -685,11 +704,10 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
checkNumOfEvents(2); checkNumOfEvents(2);
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(1); IntStream.of(1, 2).forEach(i -> {
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType()); RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(i);
resultRepoEvent = getRepoEventWithoutWait(2);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType()); assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
});
retryingTransactionHelper.doInTransaction(() -> retryingTransactionHelper.doInTransaction(() ->
{ {
@ -712,10 +730,10 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
// Check the node events occur before the child association event // Check the node events occur before the child association event
List<RepoEvent<?>> repoEvents = getRepoEventsContainer().getEvents(); List<RepoEvent<?>> repoEvents = getRepoEventsContainer().getEvents();
assertEquals("org.alfresco.event.node.Created", repoEvents.get(0).getType()); assertEquals(EventType.NODE_CREATED.getType(), repoEvents.get(0).getType());
assertEquals("org.alfresco.event.node.Created", repoEvents.get(1).getType()); assertEquals(EventType.NODE_CREATED.getType(), repoEvents.get(1).getType());
assertEquals("org.alfresco.event.node.Updated", repoEvents.get(2).getType()); assertEquals(EventType.NODE_UPDATED.getType(), repoEvents.get(2).getType());
assertEquals("org.alfresco.event.node.Updated", repoEvents.get(3).getType()); assertEquals(EventType.NODE_UPDATED.getType(), repoEvents.get(3).getType());
assertEquals("org.alfresco.event.assoc.child.Created", repoEvents.get(4).getType()); assertEquals(EventType.CHILD_ASSOC_CREATED.getType(), repoEvents.get(4).getType());
} }
} }

View File

@ -27,24 +27,38 @@ package org.alfresco.repo.event2;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Set; import java.util.Set;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.repo.event.v1.model.EventType;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
public class EventConsolidatorUnitTest public class EventConsolidatorUnitTest
{ {
private NodeResourceHelper nodeResourceHelper = mock(NodeResourceHelper.class); private final NodeResourceHelper nodeResourceHelper = mock(NodeResourceHelper.class);
private NodeEventConsolidator eventConsolidator;
@Before
public void setUp() throws Exception
{
eventConsolidator = new NodeEventConsolidator(nodeResourceHelper);
}
@Test @Test
public void testGetMappedAspectsBeforeRemovedAndAddedEmpty() public void testGetMappedAspectsBeforeRemovedAndAddedEmpty()
{ {
NodeEventConsolidator eventConsolidator = new NodeEventConsolidator(nodeResourceHelper);
Set<String> currentAspects = new HashSet<>(); Set<String> currentAspects = new HashSet<>();
currentAspects.add("cm:geographic"); currentAspects.add("cm:geographic");
currentAspects.add("cm:auditable"); currentAspects.add("cm:auditable");
@ -57,7 +71,6 @@ public class EventConsolidatorUnitTest
@Test @Test
public void testGetMappedAspectsBefore_AspectRemoved() public void testGetMappedAspectsBefore_AspectRemoved()
{ {
NodeEventConsolidator eventConsolidator = new NodeEventConsolidator(nodeResourceHelper);
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS); eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
Set<String> currentAspects = new HashSet<>(); Set<String> currentAspects = new HashSet<>();
@ -79,7 +92,6 @@ public class EventConsolidatorUnitTest
@Test @Test
public void testGetMappedAspectsBefore_AspectAdded() public void testGetMappedAspectsBefore_AspectAdded()
{ {
NodeEventConsolidator eventConsolidator = new NodeEventConsolidator(nodeResourceHelper);
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS); eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
Set<String> currentAspects = new HashSet<>(); Set<String> currentAspects = new HashSet<>();
@ -102,7 +114,6 @@ public class EventConsolidatorUnitTest
@Test @Test
public void testGetMappedAspectsBefore_AspectAddedAndRemoved() public void testGetMappedAspectsBefore_AspectAddedAndRemoved()
{ {
NodeEventConsolidator eventConsolidator = new NodeEventConsolidator(nodeResourceHelper);
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS); eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
Set<String> currentAspects = new HashSet<>(); Set<String> currentAspects = new HashSet<>();
@ -125,7 +136,6 @@ public class EventConsolidatorUnitTest
@Test @Test
public void testGetMappedAspectsBefore_AspectRemovedAndAdded() public void testGetMappedAspectsBefore_AspectRemovedAndAdded()
{ {
NodeEventConsolidator eventConsolidator = new NodeEventConsolidator(nodeResourceHelper);
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS); eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
eventConsolidator.removeAspect(ContentModel.ASSOC_CONTAINS); eventConsolidator.removeAspect(ContentModel.ASSOC_CONTAINS);
@ -150,8 +160,6 @@ public class EventConsolidatorUnitTest
@Test @Test
public void testGetMappedAspectsBefore_AspectAddedTwiceRemovedOnce() public void testGetMappedAspectsBefore_AspectAddedTwiceRemovedOnce()
{ {
NodeEventConsolidator eventConsolidator = new NodeEventConsolidator(nodeResourceHelper);
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS); eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS); eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
@ -178,8 +186,6 @@ public class EventConsolidatorUnitTest
@Test @Test
public void testGetMappedAspectsBefore_AspectRemovedTwiceAddedOnce() public void testGetMappedAspectsBefore_AspectRemovedTwiceAddedOnce()
{ {
NodeEventConsolidator eventConsolidator = new NodeEventConsolidator(nodeResourceHelper);
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS); eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS); eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
@ -206,7 +212,6 @@ public class EventConsolidatorUnitTest
@Test @Test
public void testGetMappedAspectsBefore_FilteredAspectAdded() public void testGetMappedAspectsBefore_FilteredAspectAdded()
{ {
NodeEventConsolidator eventConsolidator = new NodeEventConsolidator(nodeResourceHelper);
eventConsolidator.addAspect(ContentModel.ASPECT_COPIEDFROM); eventConsolidator.addAspect(ContentModel.ASPECT_COPIEDFROM);
Set<String> currentAspects = new HashSet<>(); Set<String> currentAspects = new HashSet<>();
@ -227,7 +232,6 @@ public class EventConsolidatorUnitTest
@Test @Test
public void testAddAspect() public void testAddAspect()
{ {
NodeEventConsolidator eventConsolidator = new NodeEventConsolidator(nodeResourceHelper);
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS); eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
assertEquals(1, eventConsolidator.getAspectsAdded().size()); assertEquals(1, eventConsolidator.getAspectsAdded().size());
@ -238,7 +242,6 @@ public class EventConsolidatorUnitTest
@Test @Test
public void testRemoveAspect() public void testRemoveAspect()
{ {
NodeEventConsolidator eventConsolidator = new NodeEventConsolidator(nodeResourceHelper);
eventConsolidator.removeAspect(ContentModel.ASSOC_CONTAINS); eventConsolidator.removeAspect(ContentModel.ASSOC_CONTAINS);
assertEquals(0, eventConsolidator.getAspectsAdded().size()); assertEquals(0, eventConsolidator.getAspectsAdded().size());
@ -249,7 +252,6 @@ public class EventConsolidatorUnitTest
@Test @Test
public void testAddAspectRemoveAspect() public void testAddAspectRemoveAspect()
{ {
NodeEventConsolidator eventConsolidator = new NodeEventConsolidator(nodeResourceHelper);
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS); eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
eventConsolidator.removeAspect(ContentModel.ASSOC_CONTAINS); eventConsolidator.removeAspect(ContentModel.ASSOC_CONTAINS);
@ -260,7 +262,6 @@ public class EventConsolidatorUnitTest
@Test @Test
public void testRemoveAspectAddAspect() public void testRemoveAspectAddAspect()
{ {
NodeEventConsolidator eventConsolidator = new NodeEventConsolidator(nodeResourceHelper);
eventConsolidator.removeAspect(ContentModel.ASSOC_CONTAINS); eventConsolidator.removeAspect(ContentModel.ASSOC_CONTAINS);
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS); eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
@ -271,7 +272,6 @@ public class EventConsolidatorUnitTest
@Test @Test
public void testAddAspectTwiceRemoveAspectOnce() public void testAddAspectTwiceRemoveAspectOnce()
{ {
NodeEventConsolidator eventConsolidator = new NodeEventConsolidator(nodeResourceHelper);
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS); eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
eventConsolidator.removeAspect(ContentModel.ASSOC_CONTAINS); eventConsolidator.removeAspect(ContentModel.ASSOC_CONTAINS);
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS); eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
@ -284,7 +284,6 @@ public class EventConsolidatorUnitTest
@Test @Test
public void testAddAspectOnceRemoveAspectTwice() public void testAddAspectOnceRemoveAspectTwice()
{ {
NodeEventConsolidator eventConsolidator = new NodeEventConsolidator(nodeResourceHelper);
eventConsolidator.removeAspect(ContentModel.ASSOC_CONTAINS); eventConsolidator.removeAspect(ContentModel.ASSOC_CONTAINS);
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS); eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
eventConsolidator.removeAspect(ContentModel.ASSOC_CONTAINS); eventConsolidator.removeAspect(ContentModel.ASSOC_CONTAINS);
@ -293,4 +292,83 @@ public class EventConsolidatorUnitTest
assertEquals(1, eventConsolidator.getAspectsRemoved().size()); assertEquals(1, eventConsolidator.getAspectsRemoved().size());
assertTrue(eventConsolidator.getAspectsRemoved().contains(ContentModel.ASSOC_CONTAINS)); assertTrue(eventConsolidator.getAspectsRemoved().contains(ContentModel.ASSOC_CONTAINS));
} }
@Test
public void testOnMoveNodeWithPrimaryParent()
{
ChildAssociationRef oldAssociationMock = mock(ChildAssociationRef.class);
ChildAssociationRef newAssociationMock = mock(ChildAssociationRef.class);
NodeRef parentRefMock = mock(NodeRef.class);
given(newAssociationMock.isPrimary()).willReturn(true);
given(oldAssociationMock.getParentRef()).willReturn(parentRefMock);
eventConsolidator.onMoveNode(oldAssociationMock, newAssociationMock);
then(newAssociationMock).should().getChildRef();
then(newAssociationMock).should().isPrimary();
then(newAssociationMock).shouldHaveNoMoreInteractions();
then(nodeResourceHelper).should().getPrimaryHierarchy(parentRefMock, true);
assertTrue("Node event consolidator should contain event type: UPDATED", eventConsolidator.getEventTypes().contains(EventType.NODE_UPDATED));
}
@Test
public void testOnMoveNodeAfterSecondaryParentAdded()
{
ChildAssociationRef oldAssociationMock = mock(ChildAssociationRef.class);
ChildAssociationRef newAssociationMock = mock(ChildAssociationRef.class);
NodeRef nodeRefMock = mock(NodeRef.class);
NodeRef parentRefMock = mock(NodeRef.class);
List<String> secondaryParentsMock = mock(List.class);
given(newAssociationMock.isPrimary()).willReturn(false);
given(newAssociationMock.getChildRef()).willReturn(nodeRefMock);
given(newAssociationMock.getParentRef()).willReturn(parentRefMock);
given(parentRefMock.getId()).willReturn("parent-id");
given(nodeResourceHelper.getSecondaryParents(any(NodeRef.class))).willReturn(secondaryParentsMock);
// when
eventConsolidator.onMoveNode(oldAssociationMock, newAssociationMock);
then(newAssociationMock).should().isPrimary();
then(newAssociationMock).should(times(2)).getChildRef();
then(newAssociationMock).should(times(2)).getParentRef();
then(newAssociationMock).shouldHaveNoMoreInteractions();
then(oldAssociationMock).shouldHaveNoInteractions();
then(nodeResourceHelper).should().getSecondaryParents(nodeRefMock);
then(secondaryParentsMock).should().remove("parent-id");
then(secondaryParentsMock).shouldHaveNoMoreInteractions();
assertTrue("Node event consolidator should contain event type: UPDATED", eventConsolidator.getEventTypes().contains(EventType.NODE_UPDATED));
assertEquals(secondaryParentsMock, eventConsolidator.getSecondaryParentsBefore());
}
@Test
public void testOnMoveNodeBeforeSecondaryParentRemoved()
{
ChildAssociationRef oldAssociationMock = mock(ChildAssociationRef.class);
ChildAssociationRef newAssociationMock = mock(ChildAssociationRef.class);
NodeRef nodeRefMock = mock(NodeRef.class);
NodeRef parentRefMock = mock(NodeRef.class);
List<String> secondaryParentsMock = mock(List.class);
given(newAssociationMock.isPrimary()).willReturn(false);
given(newAssociationMock.getChildRef()).willReturn(nodeRefMock);
given(oldAssociationMock.getParentRef()).willReturn(parentRefMock);
given(parentRefMock.getId()).willReturn("parent-id");
given(nodeResourceHelper.getSecondaryParents(any(NodeRef.class))).willReturn(secondaryParentsMock);
// when
eventConsolidator.onMoveNode(oldAssociationMock, newAssociationMock);
then(newAssociationMock).should().isPrimary();
then(newAssociationMock).should(times(2)).getChildRef();
then(newAssociationMock).should().getParentRef();
then(newAssociationMock).shouldHaveNoMoreInteractions();
then(oldAssociationMock).should(times(3)).getParentRef();
then(oldAssociationMock).shouldHaveNoMoreInteractions();
then(nodeResourceHelper).should().getSecondaryParents(nodeRefMock);
then(secondaryParentsMock).should().contains("parent-id");
then(secondaryParentsMock).should().add("parent-id");
then(secondaryParentsMock).shouldHaveNoMoreInteractions();
assertTrue("Node event consolidator should contain event type: NODE_UPDATED", eventConsolidator.getEventTypes().contains(EventType.NODE_UPDATED));
assertEquals(secondaryParentsMock, eventConsolidator.getSecondaryParentsBefore());
}
} }

View File

@ -28,14 +28,43 @@ package org.alfresco.repo.event2;
import static org.alfresco.repo.event2.NodeResourceHelper.getLocalizedPropertiesBefore; import static org.alfresco.repo.event2.NodeResourceHelper.getLocalizedPropertiesBefore;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import static org.mockito.Mockito.mock;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class NodeResourceHelperUnitTest public class NodeResourceHelperUnitTest
{ {
@Mock
private NodeService nodeServiceMock;
@InjectMocks
private NodeResourceHelper nodeResourceHelper;
@Before
public void setUp() throws Exception
{
MockitoAnnotations.openMocks(this);
}
@Test @Test
public void shouldExtractOnlyRelevantPropertiesForBeforeNode() public void shouldExtractOnlyRelevantPropertiesForBeforeNode()
{ {
@ -111,4 +140,39 @@ public class NodeResourceHelperUnitTest
return this; return this;
} }
} }
@Test
public void testGetSecondaryParents()
{
NodeRef nodeRefMock = mock(NodeRef.class);
NodeRef parentRefMock = mock(NodeRef.class);
ChildAssociationRef secondaryParentMock = mock(ChildAssociationRef.class);
given(nodeServiceMock.getParentAssocs(any(NodeRef.class))).willReturn(List.of(secondaryParentMock));
given(secondaryParentMock.isPrimary()).willReturn(false);
given(secondaryParentMock.getParentRef()).willReturn(parentRefMock);
// when
List<String> secondaryParents = nodeResourceHelper.getSecondaryParents(nodeRefMock);
then(nodeServiceMock).should().getParentAssocs(nodeRefMock);
then(nodeServiceMock).shouldHaveNoMoreInteractions();
then(secondaryParentMock).should().isPrimary();
then(secondaryParentMock).should().getParentRef();
then(secondaryParentMock).shouldHaveNoMoreInteractions();
then(parentRefMock).should().getId();
then(parentRefMock).shouldHaveNoMoreInteractions();
assertNotNull(secondaryParents);
}
@Test
public void testGetNoneSecondaryParents()
{
NodeRef nodeRefMock = mock(NodeRef.class);
// when
List<String> secondaryParents = nodeResourceHelper.getSecondaryParents(nodeRefMock);
assertNotNull(secondaryParents);
assertTrue(secondaryParents.isEmpty());
}
} }