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

@ -98,4 +98,4 @@ EXPOSE 10001
# For remote debug
EXPOSE 8000
USER ${IMAGEUSERNAME}
USER ${IMAGEUSERNAME}

View File

@ -35,6 +35,7 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
import java.util.stream.Stream;
import io.restassured.http.ContentType;
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.RestNodeAssociationModel;
import org.alfresco.rest.model.RestNodeAssociationModelCollection;
import org.alfresco.rest.model.RestNodeAssociationTypeModel;
import org.alfresco.rest.model.RestNodeBodyModel;
import org.alfresco.rest.model.RestNodeBodyMoveCopyModel;
import org.alfresco.rest.model.RestNodeChildAssocModelCollection;
import org.alfresco.rest.model.RestNodeChildAssociationModel;
import org.alfresco.rest.model.RestNodeModel;
import org.alfresco.rest.model.RestNodeModelsCollection;
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.utility.Utility;
import org.alfresco.utility.model.RepoTestModel;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
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
* Use a list of secondary children nodes
* Creates a secondary child association using POST call to: 'nodes/{nodeId}/secondary-children'.
*
* @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);
}
/**
* 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);
}

View File

@ -125,11 +125,10 @@ public class NodesParentChildrenTests extends RestTest
RestNodeChildAssociationModel childAssoc1 = new RestNodeChildAssociationModel(nodesBuilder.getNode("f1").getId(), "cm:contains");
RestNodeChildAssociationModel childAssoc2 = new RestNodeChildAssociationModel(nodesBuilder.getNode("f2").getId(), "cm:contains");
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");
RestNodeChildAssocModelCollection secondaryChildAssoc = restClient.withCoreAPI().usingNode(nodesBuilder.getNode("F1").toContentModel())
.createSecondaryChildren(secondaryChildrenBody);
.addSecondaryChildren(childAssoc1, childAssoc2, childAssoc3);
restClient.assertStatusCodeIs(HttpStatus.CREATED);
secondaryChildAssoc.getEntryByIndex(0).assertThat().field("childId").is(childAssoc1.getChildId());
secondaryChildAssoc.getEntryByIndex(1).assertThat().field("childId").is(childAssoc2.getChildId());
@ -142,7 +141,7 @@ public class NodesParentChildrenTests extends RestTest
secondaryChildren.assertThat().entriesListCountIs(2);
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);
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");
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);
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-service.version>4.0.0-A3</dependency.alfresco-transform-service.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.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)
{
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
public void beforeDeleteChildAssociation(ChildAssociationRef 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
@ -503,6 +515,18 @@ public class EventGenerator extends AbstractLifecycleBean implements Initializin
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
protected void onBootstrap(ApplicationEvent applicationEvent)
{

View File

@ -65,6 +65,7 @@ public class NodeEventConsolidator extends EventConsolidator<NodeRef, NodeResour
private QName nodeType;
private QName nodeTypeBefore;
private List<String> primaryHierarchyBefore;
private List<String> secondaryParentsBefore;
private boolean resourceBeforeAllFieldsNull = true;
public NodeEventConsolidator(NodeResourceHelper nodeResourceHelper)
@ -144,7 +145,25 @@ public class NodeEventConsolidator extends EventConsolidator<NodeRef, NodeResour
eventTypes.add(EventType.NODE_UPDATED);
createBuilderIfAbsent(newChildAssocRef.getChildRef());
setBeforePrimaryHierarchy(helper.getPrimaryHierarchy(oldChildAssocRef.getParentRef(), true));
if (newChildAssocRef.isPrimary())
{
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
@ -174,7 +193,7 @@ public class NodeEventConsolidator extends EventConsolidator<NodeRef, NodeResour
public void beforeDeleteNode(NodeRef nodeRef)
{
eventTypes.add(EventType.NODE_DELETED);
createBuilderIfAbsent(nodeRef, false);
createBuilderIfAbsent(nodeRef);
}
@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()
{
if (resourceBuilder == null)
@ -283,7 +315,7 @@ public class NodeEventConsolidator extends EventConsolidator<NodeRef, NodeResour
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())
{
builder.setLocalizedProperties(localizedProps);
@ -309,8 +341,7 @@ public class NodeEventConsolidator extends EventConsolidator<NodeRef, NodeResour
builder.setModifiedByUser(modifier);
resourceBeforeAllFieldsNull = false;
}
modifiedAt =
helper.getZonedDateTime((Date) changedPropsBefore.get(ContentModel.PROP_MODIFIED));
modifiedAt = helper.getZonedDateTime((Date) changedPropsBefore.get(ContentModel.PROP_MODIFIED));
}
// Handle case where the content does not exist on the propertiesBefore
@ -334,6 +365,12 @@ public class NodeEventConsolidator extends EventConsolidator<NodeRef, NodeResour
resourceBeforeAllFieldsNull = false;
}
if (secondaryParentsBefore != null)
{
builder.setSecondaryParents(secondaryParentsBefore);
resourceBeforeAllFieldsNull = false;
}
if (nodeTypeBefore != null)
{
builder.setNodeType(helper.getQNamePrefixString(nodeTypeBefore));

View File

@ -26,6 +26,7 @@
package org.alfresco.repo.event2;
import static java.util.Optional.ofNullable;
import static java.util.function.Predicate.not;
import java.io.Serializable;
import java.time.ZoneId;
@ -38,6 +39,7 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import com.google.common.collect.Sets;
@ -145,21 +147,23 @@ public class NodeResourceHelper implements InitializingBean
// minor: save one lookup if creator & modifier are the same
Map<String, UserInfo> mapUserCache = new HashMap<>(2);
return NodeResource.builder().setId(nodeRef.getId())
.setName((String) properties.get(ContentModel.PROP_NAME))
.setNodeType(getQNamePrefixString(type))
.setIsFile(isSubClass(type, ContentModel.TYPE_CONTENT))
.setIsFolder(isSubClass(type, ContentModel.TYPE_FOLDER))
.setCreatedByUser(getUserInfo((String) properties.get(ContentModel.PROP_CREATOR), mapUserCache))
.setCreatedAt(getZonedDateTime((Date)properties.get(ContentModel.PROP_CREATED)))
.setModifiedByUser(getUserInfo((String) properties.get(ContentModel.PROP_MODIFIER), mapUserCache))
.setModifiedAt(getZonedDateTime((Date)properties.get(ContentModel.PROP_MODIFIED)))
.setContent(getContentInfo(properties))
.setPrimaryAssocQName(getPrimaryAssocQName(nodeRef))
.setPrimaryHierarchy(PathUtil.getNodeIdsInReverse(path, false))
.setProperties(mapToNodeProperties(properties))
.setLocalizedProperties(mapToNodeLocalizedProperties(properties))
.setAspectNames(getMappedAspects(nodeRef));
return NodeResource.builder()
.setId(nodeRef.getId())
.setName((String) properties.get(ContentModel.PROP_NAME))
.setNodeType(getQNamePrefixString(type))
.setIsFile(isSubClass(type, ContentModel.TYPE_CONTENT))
.setIsFolder(isSubClass(type, ContentModel.TYPE_FOLDER))
.setCreatedByUser(getUserInfo((String) properties.get(ContentModel.PROP_CREATOR), mapUserCache))
.setCreatedAt(getZonedDateTime((Date)properties.get(ContentModel.PROP_CREATED)))
.setModifiedByUser(getUserInfo((String) properties.get(ContentModel.PROP_MODIFIER), mapUserCache))
.setModifiedAt(getZonedDateTime((Date)properties.get(ContentModel.PROP_MODIFIED)))
.setContent(getContentInfo(properties))
.setPrimaryAssocQName(getPrimaryAssocQName(nodeRef))
.setPrimaryHierarchy(PathUtil.getNodeIdsInReverse(path, false))
.setProperties(mapToNodeProperties(properties))
.setLocalizedProperties(mapToNodeLocalizedProperties(properties))
.setAspectNames(getMappedAspects(nodeRef))
.setSecondaryParents(getSecondaryParents(nodeRef));
}
private boolean isSubClass(QName className, QName ofClassQName)
@ -413,6 +417,21 @@ public class NodeResourceHelper implements InitializingBean
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()
{
return permissionService;

View File

@ -1231,6 +1231,7 @@ repo.event2.filter.users=
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
repo.event2.queue.skip=false
#repo.event2.topic.endpoint=amqp:topic:VirtualTopic.alfresco.repo.event2
# Thread pool for async enqueue of repo events
repo.event2.queue.enqueueThreadPool.priority=1
repo.event2.queue.enqueueThreadPool.coreSize=8

View File

@ -28,6 +28,7 @@ package org.alfresco.repo.event2;
import java.util.Arrays;
import java.util.List;
import java.util.stream.IntStream;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.event.v1.model.ChildAssociationResource;
@ -64,12 +65,11 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(),
resultRepoEvent.getType());
retryingTransactionHelper.doInTransaction(() ->
nodeService.addChild(
parentNodeRef,
childNodeRef,
ContentModel.ASSOC_CONTAINS,
QName.createQName(TEST_NAMESPACE, assocLocalName)));
retryingTransactionHelper.doInTransaction(() -> nodeService.addChild(
parentNodeRef,
childNodeRef,
ContentModel.ASSOC_CONTAINS,
QName.createQName(TEST_NAMESPACE, assocLocalName)));
List<ChildAssociationRef> childAssociationRefs = retryingTransactionHelper.doInTransaction(() ->
nodeService.getChildAssocs(parentNodeRef));
@ -79,8 +79,30 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
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());
assertNotNull("Repo event ID is not available.", childAssocRepoEvent.getId());
assertNotNull("Source is not available", childAssocRepoEvent.getSource());
@ -93,16 +115,18 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
assertNotNull(childAssocRepoEvent.getDataschema());
assertEquals(EventJSONSchema.CHILD_ASSOC_CREATED_V1.getSchema(), childAssocRepoEvent.getDataschema());
final EventData<ChildAssociationResource> nodeResourceEventData = getEventData(childAssocRepoEvent);
// EventData attributes
assertNotNull("Event data group ID is not available. ", nodeResourceEventData.getEventGroupId());
assertNull("resourceBefore property is not available", nodeResourceEventData.getResourceBefore());
final EventData<ChildAssociationResource> childAssocResourceEventData = getEventData(childAssocRepoEvent);
assertNotNull("Event data group ID is not available. ", childAssocResourceEventData.getEventGroupId());
assertNull("resourceBefore property is not available", childAssocResourceEventData.getResourceBefore());
final ChildAssociationResource childAssociationResource = getChildAssocResource(childAssocRepoEvent);
assertEquals("Wrong parent", parentNodeRef.getId(), childAssociationResource.getParent().getId());
assertEquals("Wrong child", childNodeRef.getId(), childAssociationResource.getChild().getId());
assertEquals("Wrong assoc type", "cm:contains", childAssociationResource.getAssocType());
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
@ -143,8 +167,30 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
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());
assertNotNull("Repo event ID is not available. ", childAssocRepoEvent.getId());
assertNotNull("Source is not available", childAssocRepoEvent.getSource());
@ -156,15 +202,17 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
assertNotNull(childAssocRepoEvent.getDataschema());
assertEquals(EventJSONSchema.CHILD_ASSOC_DELETED_V1.getSchema(), childAssocRepoEvent.getDataschema());
final EventData<ChildAssociationResource> nodeResourceEventData = getEventData(childAssocRepoEvent);
// EventData attributes
assertNotNull("Event data group ID is not available. ", nodeResourceEventData.getEventGroupId());
assertNull("resourceBefore property is not available", nodeResourceEventData.getResourceBefore());
final EventData<ChildAssociationResource> childAssocResourceEventData = getEventData(childAssocRepoEvent);
assertNotNull("Event data group ID is not available. ", childAssocResourceEventData.getEventGroupId());
assertNull("resourceBefore property is not available", childAssocResourceEventData.getResourceBefore());
final ChildAssociationResource childAssociationResource = getChildAssocResource(childAssocRepoEvent);
assertEquals("Wrong parent", parentNodeRef.getId(), childAssociationResource.getParent().getId());
assertEquals("Wrong child", childNodeRef.getId(), childAssociationResource.getChild().getId());
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
@ -179,17 +227,10 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
checkNumOfEvents(4);
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(1);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
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());
IntStream.of(1, 2, 3, 4).forEach(i -> {
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(i);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
});
retryingTransactionHelper.doInTransaction(() ->
nodeService.addChild(
@ -213,11 +254,14 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
});
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);
assertEquals("Wrong association events number",3, childAssocEvents.size());
assertEquals("Wrong association events number", 3, childAssocEvents.size());
}
@Test
@ -231,17 +275,10 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
List<NodeRef> parents = Arrays.asList(parent1NodeRef, parent2NodeRef, parent3NodeRef);
checkNumOfEvents(4);
RepoEvent<EventData<NodeResource>> 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());
resultRepoEvent = getRepoEventWithoutWait(1);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
IntStream.of(1, 2, 3, 4).forEach(i -> {
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(i);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
});
retryingTransactionHelper.doInTransaction(() -> {
for (NodeRef parent : parents)
@ -269,9 +306,13 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
});
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
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
String assocEventGroupID1 = getEventData(childAssocEvents.get(0)).getEventGroupId();
@ -294,17 +335,10 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
checkNumOfEvents(4);
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(1);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
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());
IntStream.of(1, 2, 3, 4).forEach(i -> {
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(i);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
});
for (NodeRef parent : parents)
{
@ -331,9 +365,14 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
});
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
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(childNodeRef.getId(), getChildAssocResource(childAssocEvents.get(0)).getChild().getId());
@ -360,17 +399,10 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
checkNumOfEvents(4);
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(1);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
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());
IntStream.of(1, 2, 3, 4).forEach(i -> {
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(i);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
});
retryingTransactionHelper.doInTransaction(() -> {
for (NodeRef child : children)
@ -389,9 +421,14 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
});
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
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
@ -406,17 +443,10 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
checkNumOfEvents(4);
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(1);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
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());
IntStream.of(1, 2, 3, 4).forEach(i -> {
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(i);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
});
for (NodeRef child : children)
{
@ -433,9 +463,14 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
});
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
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(child1NodeRef.getId(), getChildAssocResource(childAssocEvents.get(0)).getChild().getId());
@ -462,17 +497,10 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
checkNumOfEvents(4);
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(1);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
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());
IntStream.of(1, 2, 3, 4).forEach(i -> {
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(i);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
});
retryingTransactionHelper.doInTransaction(() ->
nodeService.addChild(parents, childNodeRef, ContentModel.ASSOC_CONTAINS,
@ -503,13 +531,17 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
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
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
public void testDeleteAssociationOneParentMultipleChildrenDifferentTransactions()
public void testDeleteAssociationMultipleParentOneChildrenDifferentTransactions()
{
final NodeRef parent1NodeRef = createNode(ContentModel.TYPE_FOLDER);
final NodeRef parent2NodeRef = createNode(ContentModel.TYPE_FOLDER);
@ -520,17 +552,10 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
checkNumOfEvents(4);
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(1);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
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());
IntStream.of(1, 2, 3, 4).forEach(i -> {
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(i);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
});
retryingTransactionHelper.doInTransaction(() ->
nodeService.addChild(parents, childNodeRef, ContentModel.ASSOC_CONTAINS,
@ -588,17 +613,10 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
checkNumOfEvents(4);
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(1);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
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());
IntStream.of(1, 2, 3, 4).forEach(i -> {
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(i);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
});
retryingTransactionHelper.doInTransaction(() -> {
for (NodeRef child : children)
@ -621,9 +639,13 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
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
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
@ -638,17 +660,10 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
checkNumOfEvents(4);
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(1);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
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());
IntStream.of(1, 2, 3, 4).forEach(i -> {
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(i);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
});
retryingTransactionHelper.doInTransaction(() ->
nodeService.addChild(parents, childNodeRef, ContentModel.ASSOC_CONTAINS,
@ -672,9 +687,13 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
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
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
@ -685,11 +704,10 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
checkNumOfEvents(2);
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(1);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
resultRepoEvent = getRepoEventWithoutWait(2);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
IntStream.of(1, 2).forEach(i -> {
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEventWithoutWait(i);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
});
retryingTransactionHelper.doInTransaction(() ->
{
@ -712,10 +730,10 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
// Check the node events occur before the child association event
List<RepoEvent<?>> repoEvents = getRepoEventsContainer().getEvents();
assertEquals("org.alfresco.event.node.Created", repoEvents.get(0).getType());
assertEquals("org.alfresco.event.node.Created", repoEvents.get(1).getType());
assertEquals("org.alfresco.event.node.Updated", repoEvents.get(2).getType());
assertEquals("org.alfresco.event.node.Updated", repoEvents.get(3).getType());
assertEquals("org.alfresco.event.assoc.child.Created", repoEvents.get(4).getType());
assertEquals(EventType.NODE_CREATED.getType(), repoEvents.get(0).getType());
assertEquals(EventType.NODE_CREATED.getType(), repoEvents.get(1).getType());
assertEquals(EventType.NODE_UPDATED.getType(), repoEvents.get(2).getType());
assertEquals(EventType.NODE_UPDATED.getType(), repoEvents.get(3).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.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.times;
import static org.mockito.Mockito.when;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
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;
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
public void testGetMappedAspectsBeforeRemovedAndAddedEmpty()
{
NodeEventConsolidator eventConsolidator = new NodeEventConsolidator(nodeResourceHelper);
Set<String> currentAspects = new HashSet<>();
currentAspects.add("cm:geographic");
currentAspects.add("cm:auditable");
@ -57,7 +71,6 @@ public class EventConsolidatorUnitTest
@Test
public void testGetMappedAspectsBefore_AspectRemoved()
{
NodeEventConsolidator eventConsolidator = new NodeEventConsolidator(nodeResourceHelper);
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
Set<String> currentAspects = new HashSet<>();
@ -79,7 +92,6 @@ public class EventConsolidatorUnitTest
@Test
public void testGetMappedAspectsBefore_AspectAdded()
{
NodeEventConsolidator eventConsolidator = new NodeEventConsolidator(nodeResourceHelper);
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
Set<String> currentAspects = new HashSet<>();
@ -102,7 +114,6 @@ public class EventConsolidatorUnitTest
@Test
public void testGetMappedAspectsBefore_AspectAddedAndRemoved()
{
NodeEventConsolidator eventConsolidator = new NodeEventConsolidator(nodeResourceHelper);
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
Set<String> currentAspects = new HashSet<>();
@ -125,7 +136,6 @@ public class EventConsolidatorUnitTest
@Test
public void testGetMappedAspectsBefore_AspectRemovedAndAdded()
{
NodeEventConsolidator eventConsolidator = new NodeEventConsolidator(nodeResourceHelper);
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
eventConsolidator.removeAspect(ContentModel.ASSOC_CONTAINS);
@ -150,8 +160,6 @@ public class EventConsolidatorUnitTest
@Test
public void testGetMappedAspectsBefore_AspectAddedTwiceRemovedOnce()
{
NodeEventConsolidator eventConsolidator = new NodeEventConsolidator(nodeResourceHelper);
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
@ -178,8 +186,6 @@ public class EventConsolidatorUnitTest
@Test
public void testGetMappedAspectsBefore_AspectRemovedTwiceAddedOnce()
{
NodeEventConsolidator eventConsolidator = new NodeEventConsolidator(nodeResourceHelper);
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
@ -206,7 +212,6 @@ public class EventConsolidatorUnitTest
@Test
public void testGetMappedAspectsBefore_FilteredAspectAdded()
{
NodeEventConsolidator eventConsolidator = new NodeEventConsolidator(nodeResourceHelper);
eventConsolidator.addAspect(ContentModel.ASPECT_COPIEDFROM);
Set<String> currentAspects = new HashSet<>();
@ -227,7 +232,6 @@ public class EventConsolidatorUnitTest
@Test
public void testAddAspect()
{
NodeEventConsolidator eventConsolidator = new NodeEventConsolidator(nodeResourceHelper);
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
assertEquals(1, eventConsolidator.getAspectsAdded().size());
@ -238,7 +242,6 @@ public class EventConsolidatorUnitTest
@Test
public void testRemoveAspect()
{
NodeEventConsolidator eventConsolidator = new NodeEventConsolidator(nodeResourceHelper);
eventConsolidator.removeAspect(ContentModel.ASSOC_CONTAINS);
assertEquals(0, eventConsolidator.getAspectsAdded().size());
@ -249,7 +252,6 @@ public class EventConsolidatorUnitTest
@Test
public void testAddAspectRemoveAspect()
{
NodeEventConsolidator eventConsolidator = new NodeEventConsolidator(nodeResourceHelper);
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
eventConsolidator.removeAspect(ContentModel.ASSOC_CONTAINS);
@ -260,7 +262,6 @@ public class EventConsolidatorUnitTest
@Test
public void testRemoveAspectAddAspect()
{
NodeEventConsolidator eventConsolidator = new NodeEventConsolidator(nodeResourceHelper);
eventConsolidator.removeAspect(ContentModel.ASSOC_CONTAINS);
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
@ -271,7 +272,6 @@ public class EventConsolidatorUnitTest
@Test
public void testAddAspectTwiceRemoveAspectOnce()
{
NodeEventConsolidator eventConsolidator = new NodeEventConsolidator(nodeResourceHelper);
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
eventConsolidator.removeAspect(ContentModel.ASSOC_CONTAINS);
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
@ -284,7 +284,6 @@ public class EventConsolidatorUnitTest
@Test
public void testAddAspectOnceRemoveAspectTwice()
{
NodeEventConsolidator eventConsolidator = new NodeEventConsolidator(nodeResourceHelper);
eventConsolidator.removeAspect(ContentModel.ASSOC_CONTAINS);
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
eventConsolidator.removeAspect(ContentModel.ASSOC_CONTAINS);
@ -293,4 +292,83 @@ public class EventConsolidatorUnitTest
assertEquals(1, eventConsolidator.getAspectsRemoved().size());
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.junit.Assert.assertEquals;
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.List;
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.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
{
@Mock
private NodeService nodeServiceMock;
@InjectMocks
private NodeResourceHelper nodeResourceHelper;
@Before
public void setUp() throws Exception
{
MockitoAnnotations.openMocks(this);
}
@Test
public void shouldExtractOnlyRelevantPropertiesForBeforeNode()
{
@ -111,4 +140,39 @@ public class NodeResourceHelperUnitTest
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());
}
}

View File

@ -56,4 +56,4 @@ services:
CLIENT_SSL_TRUST_STORE: "file:/tengineAIO.truststore"
CLIENT_SSL_TRUST_STORE_PASSWORD: "password"
CLIENT_SSL_TRUST_STORE_TYPE: "JCEKS"
CLIENT_SSL_TRUST_STORE_TYPE: "JCEKS"