mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Feature/repo 5181 implement child assoc events (#1030)
Co-authored-by: Chris Shields <christopher.shields@alfresco.com> Co-authored-by: Adina Ababei <adina.ababei@ness.com> Co-authored-by: aftene <iulian.aftene@ness.com>
This commit is contained in:
2
pom.xml
2
pom.xml
@@ -70,7 +70,7 @@
|
||||
<dependency.jackson.version>2.11.0</dependency.jackson.version>
|
||||
<dependency.jackson-databind.version>2.10.2</dependency.jackson-databind.version>
|
||||
<dependency.apache.taglibs.version>1.2.5</dependency.apache.taglibs.version>
|
||||
<dependency.acs-event-model.version>0.0.2</dependency.acs-event-model.version>
|
||||
<dependency.acs-event-model.version>0.0.6</dependency.acs-event-model.version>
|
||||
<dependency.awaitility.version>4.0.2</dependency.awaitility.version>
|
||||
</properties>
|
||||
|
||||
|
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2020 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.event2;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
|
||||
import org.alfresco.repo.event.v1.model.ChildAssociationResource;
|
||||
import org.alfresco.repo.event.v1.model.EventData;
|
||||
import org.alfresco.repo.event.v1.model.RepoEvent;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* Encapsulates child association events that occurred in a single transaction.
|
||||
*
|
||||
* @author Chris Shields
|
||||
* @author Sara Aspery
|
||||
*/
|
||||
public class ChildAssociationEventConsolidator implements ChildAssociationEventSupportedPolicies
|
||||
{
|
||||
private final Deque<EventType> eventTypes;
|
||||
|
||||
private final ChildAssociationRef childAssociationRef;
|
||||
private ChildAssociationResource resource;
|
||||
private final QNameHelper helper;
|
||||
|
||||
public ChildAssociationEventConsolidator(ChildAssociationRef childAssociationRef, QNameHelper helper)
|
||||
{
|
||||
this.eventTypes = new ArrayDeque<>();
|
||||
this.childAssociationRef = childAssociationRef;
|
||||
this.helper = helper;
|
||||
this.resource = buildChildAssociationResource(this.childAssociationRef);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and returns the {@link RepoEvent} instance.
|
||||
*
|
||||
* @param eventInfo the object holding the event information
|
||||
* @return the {@link RepoEvent} instance
|
||||
*/
|
||||
public RepoEvent<ChildAssociationResource> getRepoEvent(EventInfo eventInfo)
|
||||
{
|
||||
EventType eventType = getDerivedEvent();
|
||||
|
||||
EventData.Builder<ChildAssociationResource> eventDataBuilder = EventData.<ChildAssociationResource>builder()
|
||||
.setEventGroupId(eventInfo.getTxnId())
|
||||
.setResource(resource);
|
||||
|
||||
EventData<ChildAssociationResource> eventData = eventDataBuilder.build();
|
||||
return RepoEvent.<ChildAssociationResource>builder()
|
||||
.setId(eventInfo.getId())
|
||||
.setSource(eventInfo.getSource())
|
||||
.setTime(eventInfo.getTimestamp())
|
||||
.setType(eventType.getType())
|
||||
.setData(eventData)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add child association created event on create of a child association.
|
||||
*
|
||||
* @param childAssociationRef ChildAssociationRef
|
||||
*/
|
||||
@Override
|
||||
public void onCreateChildAssociation(ChildAssociationRef childAssociationRef, boolean isNewNode)
|
||||
{
|
||||
eventTypes.add(EventType.CHILD_ASSOC_CREATED);
|
||||
resource = buildChildAssociationResource(childAssociationRef);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add child association deleted event on delete of a child association.
|
||||
*
|
||||
* @param childAssociationRef ChildAssociationRef
|
||||
*/
|
||||
@Override
|
||||
public void beforeDeleteChildAssociation(ChildAssociationRef childAssociationRef)
|
||||
{
|
||||
eventTypes.add(EventType.CHILD_ASSOC_DELETED);
|
||||
resource = buildChildAssociationResource(childAssociationRef);
|
||||
}
|
||||
|
||||
private ChildAssociationResource buildChildAssociationResource(ChildAssociationRef childAssociationRef)
|
||||
{
|
||||
String parentId = childAssociationRef.getParentRef().getId();
|
||||
String childId = childAssociationRef.getChildRef().getId();
|
||||
String assocType = helper.getQNamePrefixString(childAssociationRef.getTypeQName());
|
||||
return new ChildAssociationResource(parentId, childId, assocType);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a derived event for a transaction.
|
||||
*/
|
||||
private EventType getDerivedEvent()
|
||||
{
|
||||
if (isTemporaryChildAssociation())
|
||||
{
|
||||
// This event will be filtered out, but we set the correct
|
||||
// event type anyway for debugging purposes
|
||||
return EventType.CHILD_ASSOC_DELETED;
|
||||
}
|
||||
else if (eventTypes.contains(EventType.CHILD_ASSOC_CREATED))
|
||||
{
|
||||
return EventType.CHILD_ASSOC_CREATED;
|
||||
}
|
||||
else if (eventTypes.getLast() == EventType.CHILD_ASSOC_DELETED)
|
||||
{
|
||||
return EventType.CHILD_ASSOC_DELETED;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Default to first event
|
||||
return eventTypes.getFirst();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the child association has been created and then deleted, i.e. a temporary child association.
|
||||
*
|
||||
* @return {@code true} if the child association has been created and then deleted, otherwise false
|
||||
*/
|
||||
public boolean isTemporaryChildAssociation()
|
||||
{
|
||||
return eventTypes.contains(EventType.CHILD_ASSOC_CREATED) && eventTypes.getLast() == EventType.CHILD_ASSOC_DELETED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get child association type.
|
||||
*
|
||||
* @return QName the child association type
|
||||
*/
|
||||
public QName getChildAssocType()
|
||||
{
|
||||
return childAssociationRef.getTypeQName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get event types.
|
||||
*
|
||||
* @return Deque<EventType> queue of event types
|
||||
*/
|
||||
public Deque<EventType> getEventTypes()
|
||||
{
|
||||
return eventTypes;
|
||||
}
|
||||
}
|
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2020 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.event2;
|
||||
|
||||
import org.alfresco.repo.node.NodeServicePolicies;
|
||||
|
||||
/**
|
||||
* Event generator supported policies.
|
||||
*
|
||||
* @author Chris Shields
|
||||
* @author Sara Aspery
|
||||
*/
|
||||
public interface ChildAssociationEventSupportedPolicies extends NodeServicePolicies.OnCreateChildAssociationPolicy,
|
||||
NodeServicePolicies.BeforeDeleteChildAssociationPolicy
|
||||
{
|
||||
}
|
||||
|
@@ -28,6 +28,7 @@ package org.alfresco.repo.event2;
|
||||
import java.io.Serializable;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Deque;
|
||||
@@ -57,8 +58,8 @@ public class EventConsolidator implements EventSupportedPolicies
|
||||
{
|
||||
private final NodeResourceHelper helper;
|
||||
private final Deque<EventType> eventTypes;
|
||||
private final Set<QName> aspectsAdded;
|
||||
private final Set<QName> aspectsRemoved;
|
||||
private final List<QName> aspectsAdded;
|
||||
private final List<QName> aspectsRemoved;
|
||||
|
||||
private NodeResource.Builder resourceBuilder;
|
||||
private Map<QName, Serializable> propertiesBefore;
|
||||
@@ -67,13 +68,14 @@ public class EventConsolidator implements EventSupportedPolicies
|
||||
private QName nodeType;
|
||||
private QName nodeTypeBefore;
|
||||
private List<String> primaryHierarchyBefore;
|
||||
private boolean resourceBeforeAllFieldsNull = true;
|
||||
|
||||
public EventConsolidator(NodeResourceHelper nodeResourceHelper)
|
||||
{
|
||||
this.helper = nodeResourceHelper;
|
||||
this.eventTypes = new ArrayDeque<>();
|
||||
this.aspectsAdded = new HashSet<>();
|
||||
this.aspectsRemoved = new HashSet<>();
|
||||
this.aspectsAdded = new ArrayList<>();
|
||||
this.aspectsRemoved = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -202,18 +204,42 @@ public class EventConsolidator implements EventSupportedPolicies
|
||||
public void onAddAspect(NodeRef nodeRef, QName aspectTypeQName)
|
||||
{
|
||||
eventTypes.add(EventType.NODE_UPDATED);
|
||||
aspectsAdded.add(aspectTypeQName);
|
||||
addAspect(aspectTypeQName);
|
||||
createBuilderIfAbsent(nodeRef);
|
||||
}
|
||||
|
||||
void addAspect(QName aspectTypeQName)
|
||||
{
|
||||
if (aspectsRemoved.contains(aspectTypeQName))
|
||||
{
|
||||
aspectsRemoved.remove(aspectTypeQName);
|
||||
}
|
||||
else
|
||||
{
|
||||
aspectsAdded.add(aspectTypeQName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemoveAspect(NodeRef nodeRef, QName aspectTypeQName)
|
||||
{
|
||||
eventTypes.add(EventType.NODE_UPDATED);
|
||||
aspectsRemoved.add(aspectTypeQName);
|
||||
removeAspect(aspectTypeQName);
|
||||
createBuilderIfAbsent(nodeRef);
|
||||
}
|
||||
|
||||
void removeAspect(QName aspectTypeQName)
|
||||
{
|
||||
if (aspectsAdded.contains(aspectTypeQName))
|
||||
{
|
||||
aspectsAdded.remove(aspectTypeQName);
|
||||
}
|
||||
else
|
||||
{
|
||||
aspectsRemoved.add(aspectTypeQName);
|
||||
}
|
||||
}
|
||||
|
||||
private void setAfterProperties(Map<QName, Serializable> after)
|
||||
{
|
||||
propertiesAfter = after;
|
||||
@@ -265,7 +291,7 @@ public class EventConsolidator implements EventSupportedPolicies
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
Builder builder = NodeResource.builder();
|
||||
|
||||
Map<QName, Serializable> changedPropsBefore = getBeforeMapChanges(propertiesBefore, propertiesAfter);
|
||||
@@ -276,27 +302,33 @@ public class EventConsolidator implements EventSupportedPolicies
|
||||
if (!mappedProps.isEmpty())
|
||||
{
|
||||
builder.setProperties(mappedProps);
|
||||
resourceBeforeAllFieldsNull = false;
|
||||
}
|
||||
String name = (String) changedPropsBefore.get(ContentModel.PROP_NAME);
|
||||
if (name != null)
|
||||
{
|
||||
builder.setName(name);
|
||||
resourceBeforeAllFieldsNull = false;
|
||||
}
|
||||
ContentInfo contentInfo = helper.getContentInfo(changedPropsBefore);
|
||||
if (contentInfo != null)
|
||||
{
|
||||
builder.setContent(contentInfo);
|
||||
resourceBeforeAllFieldsNull = false;
|
||||
}
|
||||
|
||||
UserInfo modifier = helper.getUserInfo((String) changedPropsBefore.get(ContentModel.PROP_MODIFIER));
|
||||
if (modifier != null)
|
||||
{
|
||||
builder.setModifiedByUser(modifier);
|
||||
resourceBeforeAllFieldsNull = false;
|
||||
}
|
||||
ZonedDateTime modifiedAt =
|
||||
helper.getZonedDateTime((Date) changedPropsBefore.get(ContentModel.PROP_MODIFIED));
|
||||
if (modifiedAt != null)
|
||||
{
|
||||
builder.setModifiedAt(modifiedAt);
|
||||
resourceBeforeAllFieldsNull = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -304,22 +336,25 @@ public class EventConsolidator implements EventSupportedPolicies
|
||||
if (!aspectsBefore.isEmpty())
|
||||
{
|
||||
builder.setAspectNames(aspectsBefore);
|
||||
resourceBeforeAllFieldsNull = false;
|
||||
}
|
||||
|
||||
if (primaryHierarchyBefore != null && !primaryHierarchyBefore.isEmpty())
|
||||
{
|
||||
builder.setPrimaryHierarchy(primaryHierarchyBefore);
|
||||
resourceBeforeAllFieldsNull = false;
|
||||
}
|
||||
|
||||
if (nodeTypeBefore != null)
|
||||
{
|
||||
builder.setNodeType(helper.getQNamePrefixString(nodeTypeBefore));
|
||||
resourceBeforeAllFieldsNull = false;
|
||||
}
|
||||
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private Set<String> getMappedAspectsBefore(Set<String> currentAspects)
|
||||
|
||||
Set<String> getMappedAspectsBefore(Set<String> currentAspects)
|
||||
{
|
||||
if (currentAspects == null)
|
||||
{
|
||||
@@ -329,17 +364,21 @@ public class EventConsolidator implements EventSupportedPolicies
|
||||
{
|
||||
Set<String> removed = helper.mapToNodeAspects(aspectsRemoved);
|
||||
Set<String> added = helper.mapToNodeAspects(aspectsAdded);
|
||||
|
||||
Set<String> before = new HashSet<>(currentAspects);
|
||||
if (!removed.isEmpty())
|
||||
|
||||
Set<String> before = new HashSet<>();
|
||||
if (!removed.isEmpty() || !added.isEmpty())
|
||||
{
|
||||
// Add all the removed aspects from the current list
|
||||
before.addAll(removed);
|
||||
}
|
||||
if (!added.isEmpty())
|
||||
{
|
||||
// Remove all the added aspects from the current list
|
||||
before.removeAll(added);
|
||||
before = new HashSet<>(currentAspects);
|
||||
if (!removed.isEmpty())
|
||||
{
|
||||
// Add all the removed aspects from the current list
|
||||
before.addAll(removed);
|
||||
}
|
||||
if (!added.isEmpty())
|
||||
{
|
||||
// Remove all the added aspects from the current list
|
||||
before.removeAll(added);
|
||||
}
|
||||
}
|
||||
return before;
|
||||
}
|
||||
@@ -348,7 +387,12 @@ public class EventConsolidator implements EventSupportedPolicies
|
||||
|
||||
private boolean hasChangedAspect()
|
||||
{
|
||||
return !(aspectsRemoved.isEmpty() && aspectsAdded.isEmpty());
|
||||
if ((aspectsRemoved.isEmpty() && aspectsAdded.isEmpty()) ||
|
||||
org.apache.commons.collections.CollectionUtils.isEqualCollection(aspectsAdded, aspectsRemoved))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private <K, V> Map<K, V> getBeforeMapChanges(Map<K, V> before, Map<K, V> after)
|
||||
@@ -413,4 +457,20 @@ public class EventConsolidator implements EventSupportedPolicies
|
||||
{
|
||||
return eventTypes;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public List<QName> getAspectsAdded()
|
||||
{
|
||||
return aspectsAdded;
|
||||
}
|
||||
|
||||
public List<QName> getAspectsRemoved()
|
||||
{
|
||||
return aspectsRemoved;
|
||||
}
|
||||
|
||||
public boolean isResourceBeforeAllFieldsNull()
|
||||
{
|
||||
return resourceBeforeAllFieldsNull;
|
||||
}
|
||||
}
|
||||
|
@@ -28,16 +28,22 @@ package org.alfresco.repo.event2;
|
||||
import java.io.Serializable;
|
||||
import java.net.URI;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.alfresco.repo.event.v1.model.RepoEvent;
|
||||
import org.alfresco.repo.event2.filter.ChildAssociationTypeFilter;
|
||||
import org.alfresco.repo.event2.filter.EventFilterRegistry;
|
||||
import org.alfresco.repo.event2.filter.EventUserFilter;
|
||||
import org.alfresco.repo.event2.filter.NodeTypeFilter;
|
||||
import org.alfresco.repo.node.NodeServicePolicies.BeforeDeleteAssociationPolicy;
|
||||
import org.alfresco.repo.node.NodeServicePolicies.BeforeDeleteChildAssociationPolicy;
|
||||
import org.alfresco.repo.node.NodeServicePolicies.BeforeDeleteNodePolicy;
|
||||
import org.alfresco.repo.node.NodeServicePolicies.OnAddAspectPolicy;
|
||||
import org.alfresco.repo.node.NodeServicePolicies.OnCreateAssociationPolicy;
|
||||
import org.alfresco.repo.node.NodeServicePolicies.OnCreateChildAssociationPolicy;
|
||||
import org.alfresco.repo.node.NodeServicePolicies.OnCreateNodePolicy;
|
||||
import org.alfresco.repo.node.NodeServicePolicies.OnDownloadNodePolicy;
|
||||
import org.alfresco.repo.node.NodeServicePolicies.OnMoveNodePolicy;
|
||||
@@ -50,6 +56,7 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.repository.AssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
@@ -71,7 +78,9 @@ import org.springframework.extensions.surf.util.AbstractLifecycleBean;
|
||||
*
|
||||
* @author Jamal Kaabi-Mofrad
|
||||
*/
|
||||
public class EventGenerator extends AbstractLifecycleBean implements InitializingBean, EventSupportedPolicies
|
||||
public class EventGenerator extends AbstractLifecycleBean implements InitializingBean, EventSupportedPolicies,
|
||||
ChildAssociationEventSupportedPolicies,
|
||||
PeerAssociationEventSupportedPolicies
|
||||
{
|
||||
private static final Log LOGGER = LogFactory.getLog(EventGenerator.class);
|
||||
|
||||
@@ -86,8 +95,10 @@ public class EventGenerator extends AbstractLifecycleBean implements Initializin
|
||||
private PersonService personService;
|
||||
|
||||
private NodeTypeFilter nodeTypeFilter;
|
||||
private ChildAssociationTypeFilter childAssociationTypeFilter;
|
||||
private EventUserFilter userFilter;
|
||||
private NodeResourceHelper nodeResourceHelper;
|
||||
private QNameHelper qNameHelper;
|
||||
private final EventTransactionListener transactionListener = new EventTransactionListener();
|
||||
|
||||
@Override
|
||||
@@ -104,10 +115,13 @@ public class EventGenerator extends AbstractLifecycleBean implements Initializin
|
||||
PropertyCheck.mandatory(this, "personService", personService);
|
||||
|
||||
this.nodeTypeFilter = eventFilterRegistry.getNodeTypeFilter();
|
||||
this.childAssociationTypeFilter = eventFilterRegistry.getChildAssociationTypeFilter();
|
||||
this.userFilter = eventFilterRegistry.getEventUserFilter();
|
||||
this.nodeResourceHelper = new NodeResourceHelper(nodeService, namespaceService, dictionaryService,
|
||||
personService,
|
||||
eventFilterRegistry);
|
||||
this.qNameHelper = new QNameHelper(namespaceService);
|
||||
this.nodeResourceHelper = new NodeResourceHelper(nodeService, dictionaryService,
|
||||
personService,
|
||||
eventFilterRegistry,
|
||||
qNameHelper);
|
||||
}
|
||||
|
||||
private void bindBehaviours()
|
||||
@@ -128,6 +142,14 @@ public class EventGenerator extends AbstractLifecycleBean implements Initializin
|
||||
new JavaBehaviour(this, "onMoveNode"));
|
||||
policyComponent.bindClassBehaviour(OnDownloadNodePolicy.QNAME, this,
|
||||
new JavaBehaviour(this, "onDownloadNode"));
|
||||
policyComponent.bindAssociationBehaviour(OnCreateChildAssociationPolicy.QNAME, this,
|
||||
new JavaBehaviour(this, "onCreateChildAssociation"));
|
||||
policyComponent.bindAssociationBehaviour(BeforeDeleteChildAssociationPolicy.QNAME, this,
|
||||
new JavaBehaviour(this, "beforeDeleteChildAssociation"));
|
||||
policyComponent.bindAssociationBehaviour(OnCreateAssociationPolicy.QNAME, this,
|
||||
new JavaBehaviour(this, "onCreateAssociation"));
|
||||
policyComponent.bindAssociationBehaviour(BeforeDeleteAssociationPolicy.QNAME, this,
|
||||
new JavaBehaviour(this, "beforeDeleteAssociation"));
|
||||
}
|
||||
|
||||
public void setPolicyComponent(PolicyComponent policyComponent)
|
||||
@@ -204,7 +226,7 @@ public class EventGenerator extends AbstractLifecycleBean implements Initializin
|
||||
{
|
||||
getEventConsolidator(nodeRef).onDownloadNode(nodeRef);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void beforeDeleteNode(NodeRef nodeRef)
|
||||
{
|
||||
@@ -223,13 +245,38 @@ public class EventGenerator extends AbstractLifecycleBean implements Initializin
|
||||
getEventConsolidator(nodeRef).onRemoveAspect(nodeRef, aspectTypeQName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateChildAssociation(ChildAssociationRef childAssociationRef, boolean isNewNode)
|
||||
{
|
||||
getEventConsolidator(childAssociationRef).onCreateChildAssociation(childAssociationRef, isNewNode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeDeleteChildAssociation(ChildAssociationRef childAssociationRef)
|
||||
{
|
||||
getEventConsolidator(childAssociationRef).beforeDeleteChildAssociation(childAssociationRef);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateAssociation(AssociationRef associationRef)
|
||||
{
|
||||
getEventConsolidator(associationRef).onCreateAssociation(associationRef);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeDeleteAssociation(AssociationRef associationRef)
|
||||
{
|
||||
getEventConsolidator(associationRef).beforeDeleteAssociation(associationRef);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link EventConsolidator} for the supplied {@code nodeRef} from
|
||||
* the current transaction context.
|
||||
*/
|
||||
private EventConsolidator getEventConsolidator(NodeRef nodeRef)
|
||||
{
|
||||
Map<NodeRef, EventConsolidator> nodeEvents = getTxnResourceMap(transactionListener);
|
||||
Consolidators consolidators = getTxnConsolidators(transactionListener);
|
||||
Map<NodeRef, EventConsolidator> nodeEvents = consolidators.getNodes();
|
||||
if (nodeEvents.isEmpty())
|
||||
{
|
||||
AlfrescoTransactionSupport.bindListener(transactionListener);
|
||||
@@ -244,15 +291,60 @@ public class EventGenerator extends AbstractLifecycleBean implements Initializin
|
||||
return eventConsolidator;
|
||||
}
|
||||
|
||||
private Map<NodeRef, EventConsolidator> getTxnResourceMap(Object resourceKey)
|
||||
|
||||
private Consolidators getTxnConsolidators(Object resourceKey)
|
||||
{
|
||||
Map<NodeRef, EventConsolidator> map = AlfrescoTransactionSupport.getResource(resourceKey);
|
||||
if (map == null)
|
||||
Consolidators consolidators = AlfrescoTransactionSupport.getResource(resourceKey);
|
||||
if (consolidators == null)
|
||||
{
|
||||
map = new LinkedHashMap<>(29);
|
||||
AlfrescoTransactionSupport.bindResource(resourceKey, map);
|
||||
consolidators = new Consolidators();
|
||||
AlfrescoTransactionSupport.bindResource(resourceKey, consolidators);
|
||||
}
|
||||
return map;
|
||||
return consolidators;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link EventConsolidator} for the supplied {@code childAssociationRef} from
|
||||
* the current transaction context.
|
||||
*/
|
||||
private ChildAssociationEventConsolidator getEventConsolidator(ChildAssociationRef childAssociationRef)
|
||||
{
|
||||
Consolidators consolidators = getTxnConsolidators(transactionListener);
|
||||
Map<ChildAssociationRef, ChildAssociationEventConsolidator> assocEvents = consolidators.getChildAssocs();
|
||||
if (assocEvents.isEmpty())
|
||||
{
|
||||
AlfrescoTransactionSupport.bindListener(transactionListener);
|
||||
}
|
||||
|
||||
ChildAssociationEventConsolidator eventConsolidator = assocEvents.get(childAssociationRef);
|
||||
if (eventConsolidator == null)
|
||||
{
|
||||
eventConsolidator = new ChildAssociationEventConsolidator(childAssociationRef, qNameHelper);
|
||||
assocEvents.put(childAssociationRef, eventConsolidator);
|
||||
}
|
||||
return eventConsolidator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link EventConsolidator} for the supplied {@code peerAssociationRef} from
|
||||
* the current transaction context.
|
||||
*/
|
||||
private PeerAssociationEventConsolidator getEventConsolidator(AssociationRef peerAssociationRef)
|
||||
{
|
||||
Consolidators consolidators = getTxnConsolidators(transactionListener);
|
||||
Map<AssociationRef, PeerAssociationEventConsolidator> assocEvents = consolidators.getPeerAssocs();
|
||||
if (assocEvents.isEmpty())
|
||||
{
|
||||
AlfrescoTransactionSupport.bindListener(transactionListener);
|
||||
}
|
||||
|
||||
PeerAssociationEventConsolidator eventConsolidator = assocEvents.get(peerAssociationRef);
|
||||
if (eventConsolidator == null)
|
||||
{
|
||||
eventConsolidator = new PeerAssociationEventConsolidator(peerAssociationRef, qNameHelper);
|
||||
assocEvents.put(peerAssociationRef, eventConsolidator);
|
||||
}
|
||||
return eventConsolidator;
|
||||
}
|
||||
|
||||
private boolean isFiltered(QName nodeType, String user)
|
||||
@@ -260,6 +352,11 @@ public class EventGenerator extends AbstractLifecycleBean implements Initializin
|
||||
return (nodeTypeFilter.isExcluded(nodeType) || (userFilter.isExcluded(user)));
|
||||
}
|
||||
|
||||
private boolean isFilteredChildAssociation(QName childAssocType, String user)
|
||||
{
|
||||
return (childAssociationTypeFilter.isExcluded(childAssocType) || (userFilter.isExcluded(user)));
|
||||
}
|
||||
|
||||
private EventInfo getEventInfo(String user)
|
||||
{
|
||||
return new EventInfo().setTimestamp(ZonedDateTime.now())
|
||||
@@ -269,47 +366,6 @@ public class EventGenerator extends AbstractLifecycleBean implements Initializin
|
||||
.setSource(URI.create("/" + descriptorService.getCurrentRepositoryDescriptor().getId()));
|
||||
}
|
||||
|
||||
private void sendEvent(NodeRef nodeRef, EventConsolidator consolidator)
|
||||
{
|
||||
if (consolidator.isTemporaryNode())
|
||||
{
|
||||
if (LOGGER.isTraceEnabled())
|
||||
{
|
||||
LOGGER.trace("Ignoring temporary node: " + nodeRef);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
final String user = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
// Get the repo event before the filtering,
|
||||
// so we can take the latest node info into account
|
||||
final RepoEvent<?> event = consolidator.getRepoEvent(getEventInfo(user));
|
||||
|
||||
final QName nodeType = consolidator.getNodeType();
|
||||
if (isFiltered(nodeType, user))
|
||||
{
|
||||
if (LOGGER.isTraceEnabled())
|
||||
{
|
||||
LOGGER.trace("EventFilter - Excluding node: '" + nodeRef + "' of type: '"
|
||||
+ ((nodeType == null) ? "Unknown' " : nodeType.toPrefixString())
|
||||
+ "' created by: " + user);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (LOGGER.isTraceEnabled())
|
||||
{
|
||||
LOGGER.trace("List of Events:" + consolidator.getEventTypes());
|
||||
LOGGER.trace("Sending event:" + event);
|
||||
}
|
||||
// Need to execute this in another read txn because Camel expects it
|
||||
transactionService.getRetryingTransactionHelper().doInTransaction((RetryingTransactionCallback<Void>) () -> {
|
||||
event2MessageProducer.send(event);
|
||||
|
||||
return null;
|
||||
}, true, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBootstrap(ApplicationEvent applicationEvent)
|
||||
{
|
||||
@@ -329,18 +385,184 @@ public class EventGenerator extends AbstractLifecycleBean implements Initializin
|
||||
{
|
||||
try
|
||||
{
|
||||
final Map<NodeRef, EventConsolidator> changedNodes = getTxnResourceMap(this);
|
||||
for (Map.Entry<NodeRef, EventConsolidator> entry : changedNodes.entrySet())
|
||||
final Consolidators consolidators = getTxnConsolidators(this);
|
||||
|
||||
// Node events
|
||||
for (Map.Entry<NodeRef, EventConsolidator> entry : consolidators.getNodes().entrySet())
|
||||
{
|
||||
EventConsolidator eventConsolidator = entry.getValue();
|
||||
sendEvent(entry.getKey(), eventConsolidator);
|
||||
}
|
||||
}
|
||||
|
||||
// Child assoc events
|
||||
for (Map.Entry<ChildAssociationRef, ChildAssociationEventConsolidator> entry : consolidators.getChildAssocs().entrySet())
|
||||
{
|
||||
ChildAssociationEventConsolidator eventConsolidator = entry.getValue();
|
||||
sendEvent(entry.getKey(), eventConsolidator);
|
||||
}
|
||||
|
||||
// Peer assoc events
|
||||
for (Map.Entry<AssociationRef, PeerAssociationEventConsolidator> entry : consolidators.getPeerAssocs().entrySet())
|
||||
{
|
||||
PeerAssociationEventConsolidator eventConsolidator = entry.getValue();
|
||||
sendEvent(entry.getKey(), eventConsolidator);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// Must consume the exception to protect other TransactionListeners
|
||||
LOGGER.error("Unexpected error while sending repository events", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendEvent(NodeRef nodeRef, EventConsolidator consolidator)
|
||||
{
|
||||
if (consolidator.isTemporaryNode())
|
||||
{
|
||||
if (LOGGER.isTraceEnabled())
|
||||
{
|
||||
LOGGER.trace("Ignoring temporary node: " + nodeRef);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
final String user = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
// Get the repo event before the filtering,
|
||||
// so we can take the latest node info into account
|
||||
final RepoEvent<?> event = consolidator.getRepoEvent(getEventInfo(user));
|
||||
|
||||
|
||||
final QName nodeType = consolidator.getNodeType();
|
||||
if (isFiltered(nodeType, user))
|
||||
{
|
||||
if (LOGGER.isTraceEnabled())
|
||||
{
|
||||
LOGGER.trace("EventFilter - Excluding node: '" + nodeRef + "' of type: '"
|
||||
+ ((nodeType == null) ? "Unknown' " : nodeType.toPrefixString())
|
||||
+ "' created by: " + user);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getType().equals(EventType.NODE_UPDATED.getType()) && consolidator.isResourceBeforeAllFieldsNull())
|
||||
{
|
||||
if (LOGGER.isTraceEnabled())
|
||||
{
|
||||
LOGGER.trace("Ignoring node updated event as no fields have been updated: " + nodeRef);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
logAndSendEvent(event, consolidator.getEventTypes());
|
||||
}
|
||||
|
||||
private void sendEvent(ChildAssociationRef childAssociationRef, ChildAssociationEventConsolidator consolidator)
|
||||
{
|
||||
if (consolidator.isTemporaryChildAssociation())
|
||||
{
|
||||
if (LOGGER.isTraceEnabled())
|
||||
{
|
||||
LOGGER.trace("Ignoring temporary child association: " + childAssociationRef);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
final String user = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
// Get the repo event before the filtering,
|
||||
// so we can take the latest association info into account
|
||||
final RepoEvent<?> event = consolidator.getRepoEvent(getEventInfo(user));
|
||||
|
||||
final QName childAssocType = consolidator.getChildAssocType();
|
||||
if (isFilteredChildAssociation(childAssocType, user))
|
||||
{
|
||||
if (LOGGER.isTraceEnabled())
|
||||
{
|
||||
LOGGER.trace("EventFilter - Excluding child association: '" + childAssociationRef + "' of type: '"
|
||||
+ ((childAssocType == null) ? "Unknown' " : childAssocType.toPrefixString())
|
||||
+ "' created by: " + user);
|
||||
}
|
||||
return;
|
||||
} else if (childAssociationRef.isPrimary())
|
||||
{
|
||||
if (LOGGER.isTraceEnabled())
|
||||
{
|
||||
LOGGER.trace("EventFilter - Excluding primary child association: '" + childAssociationRef + "' of type: '"
|
||||
+ ((childAssocType == null) ? "Unknown' " : childAssocType.toPrefixString())
|
||||
+ "' created by: " + user);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
logAndSendEvent(event, consolidator.getEventTypes());
|
||||
}
|
||||
|
||||
private void sendEvent(AssociationRef peerAssociationRef, PeerAssociationEventConsolidator consolidator)
|
||||
{
|
||||
if (consolidator.isTemporaryPeerAssociation())
|
||||
{
|
||||
if (LOGGER.isTraceEnabled())
|
||||
{
|
||||
LOGGER.trace("Ignoring temporary peer association: " + peerAssociationRef);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
final String user = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
// Get the repo event before the filtering,
|
||||
// so we can take the latest association info into account
|
||||
final RepoEvent<?> event = consolidator.getRepoEvent(getEventInfo(user));
|
||||
|
||||
logAndSendEvent(event, consolidator.getEventTypes());
|
||||
}
|
||||
|
||||
private void logAndSendEvent(RepoEvent<?> event, Deque<EventType> listOfEvents)
|
||||
{
|
||||
if (LOGGER.isTraceEnabled())
|
||||
{
|
||||
LOGGER.trace("List of Events:" + listOfEvents);
|
||||
LOGGER.trace("Sending event:" + event);
|
||||
}
|
||||
// Need to execute this in another read txn because Camel expects it
|
||||
transactionService.getRetryingTransactionHelper().doInTransaction((RetryingTransactionCallback<Void>) () -> {
|
||||
event2MessageProducer.send(event);
|
||||
|
||||
return null;
|
||||
}, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class Consolidators
|
||||
{
|
||||
private Map<NodeRef, EventConsolidator> nodes;
|
||||
private Map<ChildAssociationRef, ChildAssociationEventConsolidator> childAssocs;
|
||||
private Map<AssociationRef, PeerAssociationEventConsolidator> peerAssocs;
|
||||
|
||||
public Map<NodeRef, EventConsolidator> getNodes()
|
||||
{
|
||||
if (nodes == null)
|
||||
{
|
||||
nodes = new LinkedHashMap<>(29);
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
public Map<ChildAssociationRef, ChildAssociationEventConsolidator> getChildAssocs()
|
||||
{
|
||||
if (childAssocs == null)
|
||||
{
|
||||
childAssocs = new LinkedHashMap<>(29);
|
||||
}
|
||||
return childAssocs;
|
||||
}
|
||||
|
||||
public Map<AssociationRef, PeerAssociationEventConsolidator> getPeerAssocs()
|
||||
{
|
||||
if (peerAssocs == null)
|
||||
{
|
||||
peerAssocs = new LinkedHashMap<>(29);
|
||||
}
|
||||
return peerAssocs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -32,21 +32,23 @@ package org.alfresco.repo.event2;
|
||||
*/
|
||||
public enum EventType
|
||||
{
|
||||
NODE_CREATED("Created"), NODE_UPDATED("Updated"), NODE_DELETED("Deleted"), NODE_DOWNLOADED("Downloaded");
|
||||
NODE_CREATED(EventTypeConst.CREATED, ContextType.NODE), NODE_UPDATED(EventTypeConst.UPDATED, ContextType.NODE), NODE_DELETED(EventTypeConst.DELETED, ContextType.NODE), NODE_DOWNLOADED("Downloaded", ContextType.NODE),
|
||||
CHILD_ASSOC_CREATED(EventTypeConst.CREATED, ContextType.CHILD_ASSOC), CHILD_ASSOC_DELETED(EventTypeConst.DELETED, ContextType.CHILD_ASSOC),
|
||||
PEER_ASSOC_CREATED(EventTypeConst.CREATED, ContextType.PEER_ASSOC), PEER_ASSOC_DELETED(EventTypeConst.DELETED, ContextType.PEER_ASSOC);
|
||||
|
||||
private static final String PREFIX = "org.alfresco.event.";
|
||||
private static final String CONTEXT = "node.";
|
||||
private String type;
|
||||
private ContextType contextType;
|
||||
|
||||
EventType(String type)
|
||||
EventType(String type, ContextType contextType)
|
||||
{
|
||||
this.type = type;
|
||||
this.contextType = contextType;
|
||||
}
|
||||
|
||||
// Should be overridden if a type requires different context. E.g. auth
|
||||
/* package*/ String getContext()
|
||||
{
|
||||
return CONTEXT;
|
||||
return contextType.getContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -64,5 +66,27 @@ public enum EventType
|
||||
{
|
||||
return toString();
|
||||
}
|
||||
|
||||
private enum ContextType
|
||||
{
|
||||
NODE("node."), CHILD_ASSOC("assoc.child."), PEER_ASSOC("assoc.peer.");
|
||||
private String context;
|
||||
ContextType(String context)
|
||||
{
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
String getContext()
|
||||
{
|
||||
return context;
|
||||
}
|
||||
}
|
||||
|
||||
private static class EventTypeConst
|
||||
{
|
||||
private static final String CREATED = "Created";
|
||||
private static final String UPDATED = "Updated";
|
||||
private static final String DELETED = "Deleted";
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -28,8 +28,7 @@ package org.alfresco.repo.event2;
|
||||
import java.io.Serializable;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@@ -54,8 +53,6 @@ import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.Path;
|
||||
import org.alfresco.service.cmr.security.NoSuchPersonException;
|
||||
import org.alfresco.service.cmr.security.PersonService;
|
||||
import org.alfresco.service.namespace.NamespaceException;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.PathUtil;
|
||||
import org.apache.commons.logging.Log;
|
||||
@@ -71,22 +68,23 @@ public class NodeResourceHelper
|
||||
private static final Log LOGGER = LogFactory.getLog(NodeResourceHelper.class);
|
||||
|
||||
private final NodeService nodeService;
|
||||
private final NamespaceService namespaceService;
|
||||
private final DictionaryService dictionaryService;
|
||||
private final PersonService personService;
|
||||
private final NodeAspectFilter nodeAspectFilter;
|
||||
private final NodePropertyFilter nodePropertyFilter;
|
||||
private final QNameHelper qNameHelper;
|
||||
|
||||
public NodeResourceHelper(NodeService nodeService, NamespaceService namespaceService,
|
||||
public NodeResourceHelper(NodeService nodeService,
|
||||
DictionaryService dictionaryService, PersonService personService,
|
||||
EventFilterRegistry eventFilterRegistry)
|
||||
EventFilterRegistry eventFilterRegistry,
|
||||
QNameHelper qNameHelper)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
this.namespaceService = namespaceService;
|
||||
this.dictionaryService = dictionaryService;
|
||||
this.personService = personService;
|
||||
this.nodeAspectFilter = eventFilterRegistry.getNodeAspectFilter();
|
||||
this.nodePropertyFilter = eventFilterRegistry.getNodePropertyFilter();
|
||||
this.qNameHelper = qNameHelper;
|
||||
}
|
||||
|
||||
public NodeResource.Builder createNodeResourceBuilder(NodeRef nodeRef)
|
||||
@@ -227,19 +225,10 @@ public class NodeResourceHelper
|
||||
// returns it in the form {uri}local.
|
||||
public String getQNamePrefixString(QName k)
|
||||
{
|
||||
String key;
|
||||
try
|
||||
{
|
||||
key = k.toPrefixString(namespaceService);
|
||||
}
|
||||
catch (NamespaceException e)
|
||||
{
|
||||
key = k.toString();
|
||||
}
|
||||
return key;
|
||||
return qNameHelper.getQNamePrefixString(k);
|
||||
}
|
||||
|
||||
public Set<String> mapToNodeAspects(Set<QName> aspects)
|
||||
public Set<String> mapToNodeAspects(Collection<QName> aspects)
|
||||
{
|
||||
Set<String> filteredAspects = new HashSet<>(aspects.size());
|
||||
|
||||
|
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2020 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.event2;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
|
||||
import org.alfresco.repo.event.v1.model.EventData;
|
||||
import org.alfresco.repo.event.v1.model.PeerAssociationResource;
|
||||
import org.alfresco.repo.event.v1.model.RepoEvent;
|
||||
import org.alfresco.service.cmr.repository.AssociationRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* Encapsulates peer association events occurred in a single transaction.
|
||||
*
|
||||
* @author Sara Aspery
|
||||
*/
|
||||
public class PeerAssociationEventConsolidator implements PeerAssociationEventSupportedPolicies
|
||||
{
|
||||
private final Deque<EventType> eventTypes;
|
||||
|
||||
private final AssociationRef associationRef;
|
||||
private PeerAssociationResource resource;
|
||||
private final QNameHelper helper;
|
||||
|
||||
public PeerAssociationEventConsolidator(AssociationRef associationRef, QNameHelper helper)
|
||||
{
|
||||
this.eventTypes = new ArrayDeque<>();
|
||||
this.associationRef = associationRef;
|
||||
this.helper = helper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and returns the {@link RepoEvent} instance.
|
||||
*
|
||||
* @param eventInfo the object holding the event information
|
||||
* @return the {@link RepoEvent} instance
|
||||
*/
|
||||
public RepoEvent<PeerAssociationResource> getRepoEvent(EventInfo eventInfo)
|
||||
{
|
||||
EventType eventType = getDerivedEvent();
|
||||
|
||||
EventData.Builder<PeerAssociationResource> eventDataBuilder = EventData.<PeerAssociationResource>builder()
|
||||
.setEventGroupId(eventInfo.getTxnId())
|
||||
.setResource(resource);
|
||||
|
||||
EventData<PeerAssociationResource> eventData = eventDataBuilder.build();
|
||||
return RepoEvent.<PeerAssociationResource>builder()
|
||||
.setId(eventInfo.getId())
|
||||
.setSource(eventInfo.getSource())
|
||||
.setTime(eventInfo.getTimestamp())
|
||||
.setType(eventType.getType())
|
||||
.setData(eventData)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add peer association created event on create of a peer association.
|
||||
*
|
||||
* @param associationRef AssociationRef
|
||||
*/
|
||||
@Override
|
||||
public void onCreateAssociation(AssociationRef associationRef)
|
||||
{
|
||||
eventTypes.add(EventType.PEER_ASSOC_CREATED);
|
||||
resource = buildPeerAssociationResource(associationRef);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add peer association deleted event on delete of a peer association.
|
||||
*
|
||||
* @param associationRef AssociationRef
|
||||
*/
|
||||
@Override
|
||||
public void beforeDeleteAssociation(AssociationRef associationRef)
|
||||
{
|
||||
eventTypes.add(EventType.PEER_ASSOC_DELETED);
|
||||
resource = buildPeerAssociationResource(associationRef);
|
||||
}
|
||||
|
||||
private PeerAssociationResource buildPeerAssociationResource(AssociationRef associationRef)
|
||||
{
|
||||
String sourceId = associationRef.getSourceRef().getId();
|
||||
String targetId = associationRef.getTargetRef().getId();
|
||||
String assocType = helper.getQNamePrefixString(associationRef.getTypeQName());
|
||||
|
||||
return new PeerAssociationResource(sourceId, targetId, assocType);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a derived event for a transaction.
|
||||
*/
|
||||
private EventType getDerivedEvent()
|
||||
{
|
||||
if (isTemporaryPeerAssociation())
|
||||
{
|
||||
// This event will be filtered out, but we set the correct
|
||||
// event type anyway for debugging purposes
|
||||
return EventType.PEER_ASSOC_DELETED;
|
||||
}
|
||||
else if (eventTypes.contains(EventType.PEER_ASSOC_CREATED))
|
||||
{
|
||||
return EventType.PEER_ASSOC_CREATED;
|
||||
}
|
||||
else if (eventTypes.getLast() == EventType.PEER_ASSOC_DELETED)
|
||||
{
|
||||
return EventType.PEER_ASSOC_DELETED;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Default to first event
|
||||
return eventTypes.getFirst();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the association has been created and then deleted, i.e. a temporary association.
|
||||
*
|
||||
* @return {@code true} if the association has been created and then deleted, otherwise false
|
||||
*/
|
||||
public boolean isTemporaryPeerAssociation()
|
||||
{
|
||||
return eventTypes.contains(EventType.PEER_ASSOC_CREATED) && eventTypes.getLast() == EventType.PEER_ASSOC_DELETED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get peer association type.
|
||||
*
|
||||
* @return QName the peer association type
|
||||
*/
|
||||
public QName getAssocType()
|
||||
{
|
||||
return associationRef.getTypeQName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get event types.
|
||||
*
|
||||
* @return Deque<EventType> queue of event types
|
||||
*/
|
||||
public Deque<EventType> getEventTypes()
|
||||
{
|
||||
return eventTypes;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2020 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.event2;
|
||||
|
||||
import org.alfresco.repo.node.NodeServicePolicies;
|
||||
|
||||
/**
|
||||
* Event generator supported policies for peer associations.
|
||||
*
|
||||
* @author Sara Aspery
|
||||
*/
|
||||
public interface PeerAssociationEventSupportedPolicies extends NodeServicePolicies.OnCreateAssociationPolicy,
|
||||
NodeServicePolicies.BeforeDeleteAssociationPolicy
|
||||
{
|
||||
}
|
66
src/main/java/org/alfresco/repo/event2/QNameHelper.java
Normal file
66
src/main/java/org/alfresco/repo/event2/QNameHelper.java
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2020 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.event2;
|
||||
|
||||
import org.alfresco.service.namespace.NamespaceException;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* Helper for {@link QName} objects.
|
||||
*
|
||||
* @author Sara Aspery
|
||||
*/
|
||||
public class QNameHelper
|
||||
{
|
||||
private final NamespaceService namespaceService;
|
||||
|
||||
public QNameHelper(NamespaceService namespaceService)
|
||||
{
|
||||
this.namespaceService = namespaceService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the QName in the format prefix:local, but in the exceptional case where there is no registered prefix
|
||||
* returns it in the form {uri}local.
|
||||
*
|
||||
* @param k QName
|
||||
* @return a String representing the QName in the format prefix:local or {uri}local.
|
||||
*/
|
||||
public String getQNamePrefixString(QName k)
|
||||
{
|
||||
String key;
|
||||
try
|
||||
{
|
||||
key = k.toPrefixString(namespaceService);
|
||||
}
|
||||
catch (NamespaceException e)
|
||||
{
|
||||
key = k.toString();
|
||||
}
|
||||
return key;
|
||||
}
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2020 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.event2.filter;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* Implementation of the child association types filter.
|
||||
*
|
||||
* @author Sara Aspery
|
||||
*/
|
||||
public class ChildAssociationTypeFilter extends AbstractNodeEventFilter
|
||||
{
|
||||
private final List<String> assocTypesBlackList;
|
||||
|
||||
public ChildAssociationTypeFilter(String filteredChildAssocTypes)
|
||||
{
|
||||
this.assocTypesBlackList = parseFilterList(filteredChildAssocTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see org.alfresco.repo.event2.filter.AbstractNodeEventFilter#getExcludedTypes()
|
||||
*/
|
||||
@Override
|
||||
public Set<QName> getExcludedTypes()
|
||||
{
|
||||
Set<QName> result = new HashSet<>();
|
||||
|
||||
// add child association types defined in repository.properties/alfresco-global.properties
|
||||
assocTypesBlackList.forEach(childAssocType -> result.addAll(expandTypeDef(childAssocType)));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@@ -85,6 +85,11 @@ public class EventFilterRegistry implements BeanFactoryAware
|
||||
return getFilter("event2NodePropertyFilter", NodePropertyFilter.class);
|
||||
}
|
||||
|
||||
public ChildAssociationTypeFilter getChildAssociationTypeFilter()
|
||||
{
|
||||
return getFilter("event2ChildAssociationTypeFilter", ChildAssociationTypeFilter.class);
|
||||
}
|
||||
|
||||
public EventUserFilter getEventUserFilter()
|
||||
{
|
||||
return getFilter("event2UserFilter", EventUserFilter.class);
|
||||
|
@@ -25,6 +25,10 @@
|
||||
<constructor-arg value="${repo.event2.filter.users}"/>
|
||||
<constructor-arg type="boolean" value="${user.name.caseSensitive}" />
|
||||
</bean>
|
||||
|
||||
<bean id="event2ChildAssociationTypeFilter" class="org.alfresco.repo.event2.filter.ChildAssociationTypeFilter" parent="abstractNodeEventFilter">
|
||||
<constructor-arg value="${repo.event2.filter.childAssocTypes}"/>
|
||||
</bean>
|
||||
<!-- End of Event2 Filters -->
|
||||
|
||||
<bean id="eventGeneratorV2" class="org.alfresco.repo.event2.EventGenerator">
|
||||
|
@@ -1314,7 +1314,8 @@ contentPropertyRestrictions.whitelist=
|
||||
# Type and aspect filters which should be excluded
|
||||
# Note: System folders node types are added by default
|
||||
repo.event2.filter.nodeTypes=sys:*, fm:*, cm:thumbnail, cm:failedThumbnail, cm:rating, rma:rmsite include_subtypes
|
||||
repo.event2.filter.nodeAspects=
|
||||
repo.event2.filter.nodeAspects=sys:*
|
||||
repo.event2.filter.childAssocTypes=rn:rendition
|
||||
# Comma separated list of users which should be excluded
|
||||
# Note: username's case-sensitivity depends on the {user.name.caseSensitive} setting
|
||||
repo.event2.filter.users=System, null
|
||||
|
@@ -205,7 +205,8 @@ import org.junit.runners.Suite;
|
||||
org.alfresco.transform.client.registry.TransformServiceRegistryConfigTest.class,
|
||||
|
||||
org.alfresco.repo.event2.EventFilterTest.class,
|
||||
org.alfresco.repo.node.DownloadNotifierServiceImplUnitTest.class
|
||||
org.alfresco.repo.node.DownloadNotifierServiceImplUnitTest.class,
|
||||
org.alfresco.repo.event2.EventConsolidatorUnitTest.class
|
||||
})
|
||||
public class AllUnitTestsSuite
|
||||
{
|
||||
|
@@ -37,8 +37,10 @@ import javax.jms.ConnectionFactory;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.opencmis.CMISConnector;
|
||||
import org.alfresco.repo.event.databind.ObjectMapperFactory;
|
||||
import org.alfresco.repo.event.v1.model.ChildAssociationResource;
|
||||
import org.alfresco.repo.event.v1.model.EventData;
|
||||
import org.alfresco.repo.event.v1.model.NodeResource;
|
||||
import org.alfresco.repo.event.v1.model.PeerAssociationResource;
|
||||
import org.alfresco.repo.event.v1.model.RepoEvent;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
@@ -237,6 +239,28 @@ public abstract class AbstractContextAwareRepoEvent extends BaseSpringTest
|
||||
return resource;
|
||||
}
|
||||
|
||||
protected ChildAssociationResource getChildAssocResource(RepoEvent repoEvent)
|
||||
{
|
||||
assertNotNull(repoEvent);
|
||||
EventData<ChildAssociationResource> eventData = repoEvent.getData();
|
||||
assertNotNull(eventData);
|
||||
ChildAssociationResource resource = eventData.getResource();
|
||||
assertNotNull(resource);
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
protected PeerAssociationResource getPeerAssocResource(RepoEvent repoEvent)
|
||||
{
|
||||
assertNotNull(repoEvent);
|
||||
EventData<PeerAssociationResource> eventData = repoEvent.getData();
|
||||
assertNotNull(eventData);
|
||||
PeerAssociationResource resource = eventData.getResource();
|
||||
assertNotNull(resource);
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
protected NodeResource getNodeResourceBefore(int eventSequenceNumber)
|
||||
{
|
||||
EventData<NodeResource> eventData = getEventData(eventSequenceNumber);
|
||||
@@ -339,6 +363,15 @@ public abstract class AbstractContextAwareRepoEvent extends BaseSpringTest
|
||||
events.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public List<RepoEvent<NodeResource>> getChildAssocEvents(RepoEventContainer repoEventContainer, EventType eventType)
|
||||
{
|
||||
List<RepoEvent<NodeResource>> assocChildCreatedEvents = new ArrayList<>();
|
||||
for (int i = 1; i <= repoEventContainer.getEvents().size(); i++)
|
||||
{
|
||||
if (repoEventContainer.getEvent(i).getType().equals(eventType.getType()))
|
||||
assocChildCreatedEvents.add(repoEventContainer.getEvent(i));
|
||||
}
|
||||
return assocChildCreatedEvents;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@@ -0,0 +1,723 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2020 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.event2;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.event.v1.model.ChildAssociationResource;
|
||||
import org.alfresco.repo.event.v1.model.EventData;
|
||||
import org.alfresco.repo.event.v1.model.NodeResource;
|
||||
import org.alfresco.repo.event.v1.model.RepoEvent;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.GUID;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Adina Ababei
|
||||
* @author Iulian Aftene
|
||||
*/
|
||||
public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
{
|
||||
private RepoEventContainer repoEventsContainer;
|
||||
|
||||
@Before
|
||||
public void initContainer()
|
||||
{
|
||||
repoEventsContainer = getRepoEventsContainer();
|
||||
repoEventsContainer.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddChildAssociation()
|
||||
{
|
||||
final NodeRef parentNodeRef = createNode(ContentModel.TYPE_FOLDER);
|
||||
final NodeRef childNodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
|
||||
checkNumOfEvents(2);
|
||||
|
||||
RepoEvent<NodeResource> resultRepoEvent = repoEventsContainer.getEvent(1);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(),
|
||||
resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(2);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(),
|
||||
resultRepoEvent.getType());
|
||||
|
||||
retryingTransactionHelper.doInTransaction(() ->
|
||||
nodeService.addChild(
|
||||
parentNodeRef,
|
||||
childNodeRef,
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
QName.createQName(TEST_NAMESPACE, GUID.generate())));
|
||||
|
||||
List<ChildAssociationRef> childAssociationRefs = retryingTransactionHelper.doInTransaction(() ->
|
||||
nodeService.getChildAssocs(parentNodeRef));
|
||||
|
||||
assertEquals(1, childAssociationRefs.size());
|
||||
assertFalse(childAssociationRefs.get(0).isPrimary());
|
||||
|
||||
checkNumOfEvents(3);
|
||||
|
||||
final RepoEvent<NodeResource> childAssocRepoEvent = getChildAssocEvents(repoEventsContainer,
|
||||
EventType.CHILD_ASSOC_CREATED).get(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());
|
||||
assertEquals("Repo event source is not available.",
|
||||
"/" + descriptorService.getCurrentRepositoryDescriptor().getId(),
|
||||
childAssocRepoEvent.getSource().toString());
|
||||
assertNotNull("Repo event creation time is not available.", childAssocRepoEvent.getTime());
|
||||
assertEquals("Invalid repo event datacontenttype", "application/json",
|
||||
childAssocRepoEvent.getDatacontenttype());
|
||||
assertEquals(EventData.JSON_SCHEMA, childAssocRepoEvent.getDataschema());
|
||||
|
||||
final EventData<NodeResource> nodeResourceEventData = getEventData(childAssocRepoEvent);
|
||||
// EventData attributes
|
||||
assertNotNull("Event data group ID is not available. ", nodeResourceEventData.getEventGroupId());
|
||||
assertNull("resourceBefore property is not available", nodeResourceEventData.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());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveChildAssociation()
|
||||
{
|
||||
final NodeRef parentNodeRef = createNode(ContentModel.TYPE_FOLDER);
|
||||
final NodeRef childNodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
|
||||
checkNumOfEvents(2);
|
||||
RepoEvent<NodeResource> parentRepoEvent = repoEventsContainer.getEvent(1);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), parentRepoEvent.getType());
|
||||
|
||||
RepoEvent<NodeResource> childRepoEvent = repoEventsContainer.getEvent(2);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), childRepoEvent.getType());
|
||||
|
||||
ChildAssociationRef childAssociationRef = retryingTransactionHelper.doInTransaction(() ->
|
||||
nodeService.addChild(
|
||||
parentNodeRef,
|
||||
childNodeRef,
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
QName.createQName(TEST_NAMESPACE, GUID.generate())));
|
||||
|
||||
List<ChildAssociationRef> childAssociationRefs = retryingTransactionHelper.doInTransaction(() ->
|
||||
nodeService.getChildAssocs(parentNodeRef));
|
||||
|
||||
assertEquals(1, childAssociationRefs.size());
|
||||
assertFalse(childAssociationRefs.get(0).isPrimary());
|
||||
|
||||
checkNumOfEvents(3);
|
||||
|
||||
retryingTransactionHelper.doInTransaction(() ->
|
||||
nodeService.removeChildAssociation(childAssociationRef));
|
||||
|
||||
childAssociationRefs = retryingTransactionHelper.doInTransaction(() ->
|
||||
nodeService.getChildAssocs(parentNodeRef));
|
||||
|
||||
assertEquals(0, childAssociationRefs.size());
|
||||
|
||||
checkNumOfEvents(4);
|
||||
|
||||
final RepoEvent<NodeResource> childAssocRepoEvent = getChildAssocEvents(repoEventsContainer,
|
||||
EventType.CHILD_ASSOC_DELETED).get(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());
|
||||
assertEquals("Repo event source is not available. ",
|
||||
"/" + descriptorService.getCurrentRepositoryDescriptor().getId(),
|
||||
childAssocRepoEvent.getSource().toString());
|
||||
assertNotNull("Repo event creation time is not available. ", childAssocRepoEvent.getTime());
|
||||
assertEquals("Repo event datacontenttype", "application/json", childAssocRepoEvent.getDatacontenttype());
|
||||
assertEquals(EventData.JSON_SCHEMA, childAssocRepoEvent.getDataschema());
|
||||
|
||||
final EventData<NodeResource> nodeResourceEventData = getEventData(childAssocRepoEvent);
|
||||
// EventData attributes
|
||||
assertNotNull("Event data group ID is not available. ", nodeResourceEventData.getEventGroupId());
|
||||
assertNull("resourceBefore property is not available", nodeResourceEventData.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());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOneChildListOfParentsAssociations()
|
||||
{
|
||||
final NodeRef parent1NodeRef = createNode(ContentModel.TYPE_FOLDER);
|
||||
final NodeRef parent2NodeRef = createNode(ContentModel.TYPE_FOLDER);
|
||||
final NodeRef parent3NodeRef = createNode(ContentModel.TYPE_FOLDER);
|
||||
final NodeRef childNodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
|
||||
List<NodeRef> parents = Arrays.asList(parent1NodeRef, parent2NodeRef, parent3NodeRef);
|
||||
|
||||
checkNumOfEvents(4);
|
||||
|
||||
RepoEvent<NodeResource> resultRepoEvent = repoEventsContainer.getEvent(1);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(2);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(3);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(4);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
retryingTransactionHelper.doInTransaction(() ->
|
||||
nodeService.addChild(
|
||||
parents,
|
||||
childNodeRef,
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
QName.createQName(TEST_NAMESPACE, GUID.generate())));
|
||||
|
||||
retryingTransactionHelper.doInTransaction(() -> {
|
||||
List<ChildAssociationRef> childAssocParent1 = nodeService.getChildAssocs(
|
||||
parent1NodeRef);
|
||||
List<ChildAssociationRef> childAssocParent2 = nodeService.getChildAssocs(
|
||||
parent2NodeRef);
|
||||
List<ChildAssociationRef> childAssocParent3 = nodeService.getChildAssocs(
|
||||
parent3NodeRef);
|
||||
|
||||
assertEquals(1, childAssocParent1.size());
|
||||
assertEquals(1, childAssocParent2.size());
|
||||
assertEquals(1, childAssocParent3.size());
|
||||
return null;
|
||||
});
|
||||
|
||||
checkNumOfEvents(7);
|
||||
|
||||
// 3 assoc.child.Created events should be created
|
||||
|
||||
List<RepoEvent<NodeResource>> childAssocEvents = getChildAssocEvents(repoEventsContainer, EventType.CHILD_ASSOC_CREATED);
|
||||
assertEquals("Wrong association events number",3, childAssocEvents.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOneChildMultipleParentsSameTransaction()
|
||||
{
|
||||
final NodeRef parent1NodeRef = createNode(ContentModel.TYPE_FOLDER);
|
||||
final NodeRef parent2NodeRef = createNode(ContentModel.TYPE_FOLDER);
|
||||
final NodeRef parent3NodeRef = createNode(ContentModel.TYPE_FOLDER);
|
||||
final NodeRef childNodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
|
||||
List<NodeRef> parents = Arrays.asList(parent1NodeRef, parent2NodeRef, parent3NodeRef);
|
||||
checkNumOfEvents(4);
|
||||
|
||||
RepoEvent<NodeResource> resultRepoEvent = repoEventsContainer.getEvent(1);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(2);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(3);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(4);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
retryingTransactionHelper.doInTransaction(() -> {
|
||||
for (NodeRef parent : parents)
|
||||
{
|
||||
nodeService.addChild(parent,
|
||||
childNodeRef,
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
QName.createQName(TEST_NAMESPACE, GUID.generate()));
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
retryingTransactionHelper.doInTransaction(() -> {
|
||||
List<ChildAssociationRef> childAssocParent1 = nodeService.getChildAssocs(
|
||||
parent1NodeRef);
|
||||
List<ChildAssociationRef> childAssocParent2 = nodeService.getChildAssocs(
|
||||
parent2NodeRef);
|
||||
List<ChildAssociationRef> childAssocParent3 = nodeService.getChildAssocs(
|
||||
parent3NodeRef);
|
||||
|
||||
assertEquals(1, childAssocParent1.size());
|
||||
assertEquals(1, childAssocParent2.size());
|
||||
assertEquals(1, childAssocParent3.size());
|
||||
return null;
|
||||
});
|
||||
|
||||
// 3 assoc.child.Created events should be created
|
||||
List<RepoEvent<NodeResource>> childAssocEvents = getChildAssocEvents(repoEventsContainer, EventType.CHILD_ASSOC_CREATED);
|
||||
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();
|
||||
String assocEventGroupID2 = getEventData(childAssocEvents.get(1)).getEventGroupId();
|
||||
String assocEventGroupID3 = getEventData(childAssocEvents.get(2)).getEventGroupId();
|
||||
|
||||
assertEquals(assocEventGroupID1, assocEventGroupID2);
|
||||
assertEquals(assocEventGroupID2, assocEventGroupID3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOneChildMultipleParentsDifferentTransaction()
|
||||
{
|
||||
final NodeRef parent1NodeRef = createNode(ContentModel.TYPE_FOLDER);
|
||||
final NodeRef parent2NodeRef = createNode(ContentModel.TYPE_FOLDER);
|
||||
final NodeRef parent3NodeRef = createNode(ContentModel.TYPE_FOLDER);
|
||||
final NodeRef childNodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
|
||||
List<NodeRef> parents = Arrays.asList(parent1NodeRef, parent2NodeRef, parent3NodeRef);
|
||||
|
||||
checkNumOfEvents(4);
|
||||
|
||||
RepoEvent<NodeResource> resultRepoEvent = repoEventsContainer.getEvent(1);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(2);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(3);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(4);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
for (NodeRef parent : parents)
|
||||
{
|
||||
retryingTransactionHelper.doInTransaction(() ->
|
||||
nodeService.addChild(
|
||||
parent,
|
||||
childNodeRef,
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
QName.createQName(TEST_NAMESPACE, GUID.generate())));
|
||||
}
|
||||
|
||||
retryingTransactionHelper.doInTransaction(() -> {
|
||||
List<ChildAssociationRef> childAssocParent1 = nodeService.getChildAssocs(
|
||||
parent1NodeRef);
|
||||
List<ChildAssociationRef> childAssocParent2 = nodeService.getChildAssocs(
|
||||
parent2NodeRef);
|
||||
List<ChildAssociationRef> childAssocParent3 = nodeService.getChildAssocs(
|
||||
parent3NodeRef);
|
||||
|
||||
assertEquals(1, childAssocParent1.size());
|
||||
assertEquals(1, childAssocParent2.size());
|
||||
assertEquals(1, childAssocParent3.size());
|
||||
return null;
|
||||
});
|
||||
|
||||
// 3 assoc.child.Created events should be created
|
||||
List<RepoEvent<NodeResource>> childAssocEvents = getChildAssocEvents(repoEventsContainer, EventType.CHILD_ASSOC_CREATED);
|
||||
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());
|
||||
assertEquals("cm:contains", getChildAssocResource(childAssocEvents.get(0)).getAssocType());
|
||||
|
||||
assertEquals(parent2NodeRef.getId(), getChildAssocResource(childAssocEvents.get(1)).getParent().getId());
|
||||
assertEquals(childNodeRef.getId(), getChildAssocResource(childAssocEvents.get(1)).getChild().getId());
|
||||
assertEquals("cm:contains", getChildAssocResource(childAssocEvents.get(1)).getAssocType());
|
||||
|
||||
assertEquals(parent3NodeRef.getId(), getChildAssocResource(childAssocEvents.get(2)).getParent().getId());
|
||||
assertEquals(childNodeRef.getId(), getChildAssocResource(childAssocEvents.get(2)).getChild().getId());
|
||||
assertEquals("cm:contains", getChildAssocResource(childAssocEvents.get(2)).getAssocType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOneParentMultipleChildrenSameTransaction()
|
||||
{
|
||||
final NodeRef parentNodeRef = createNode(ContentModel.TYPE_FOLDER);
|
||||
final NodeRef child1NodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
final NodeRef child2NodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
final NodeRef child3NodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
|
||||
List<NodeRef> children = Arrays.asList(child1NodeRef, child2NodeRef, child3NodeRef);
|
||||
|
||||
checkNumOfEvents(4);
|
||||
|
||||
RepoEvent<NodeResource> resultRepoEvent = repoEventsContainer.getEvent(1);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(2);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(3);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(4);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
retryingTransactionHelper.doInTransaction(() -> {
|
||||
for (NodeRef child : children)
|
||||
{
|
||||
nodeService.addChild(parentNodeRef, child, ContentModel.ASSOC_CONTAINS,
|
||||
QName.createQName(TEST_NAMESPACE, GUID.generate()));
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
retryingTransactionHelper.doInTransaction(() -> {
|
||||
List<ChildAssociationRef> childAssocParent = nodeService.getChildAssocs(parentNodeRef);
|
||||
|
||||
assertEquals(3, childAssocParent.size());
|
||||
return null;
|
||||
});
|
||||
|
||||
// 3 assoc.child.Created events should be created
|
||||
List<RepoEvent<NodeResource>> childAssocEvents = getChildAssocEvents(repoEventsContainer, EventType.CHILD_ASSOC_CREATED);
|
||||
assertEquals("Wrong association events number",3, childAssocEvents.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOneParentMultipleChildrenDifferentTransaction()
|
||||
{
|
||||
final NodeRef parentNodeRef = createNode(ContentModel.TYPE_FOLDER);
|
||||
final NodeRef child1NodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
final NodeRef child2NodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
final NodeRef child3NodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
|
||||
List<NodeRef> children = Arrays.asList(child1NodeRef, child2NodeRef, child3NodeRef);
|
||||
|
||||
checkNumOfEvents(4);
|
||||
|
||||
RepoEvent<NodeResource> resultRepoEvent = repoEventsContainer.getEvent(1);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(2);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(3);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(4);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
for (NodeRef child : children)
|
||||
{
|
||||
retryingTransactionHelper.doInTransaction(() ->
|
||||
nodeService.addChild(parentNodeRef, child, ContentModel.ASSOC_CONTAINS,
|
||||
QName.createQName(TEST_NAMESPACE, GUID.generate())));
|
||||
}
|
||||
|
||||
retryingTransactionHelper.doInTransaction(() -> {
|
||||
List<ChildAssociationRef> childAssocParent = nodeService.getChildAssocs(parentNodeRef);
|
||||
|
||||
assertEquals(3, childAssocParent.size());
|
||||
return null;
|
||||
});
|
||||
|
||||
// 3 assoc.child.Created events should be created
|
||||
List<RepoEvent<NodeResource>> childAssocEvents = getChildAssocEvents(repoEventsContainer, EventType.CHILD_ASSOC_CREATED);
|
||||
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());
|
||||
assertEquals("cm:contains", getChildAssocResource(childAssocEvents.get(0)).getAssocType());
|
||||
|
||||
assertEquals(parentNodeRef.getId(), getChildAssocResource(childAssocEvents.get(1)).getParent().getId());
|
||||
assertEquals(child2NodeRef.getId(), getChildAssocResource(childAssocEvents.get(1)).getChild().getId());
|
||||
assertEquals("cm:contains", getChildAssocResource(childAssocEvents.get(1)).getAssocType());
|
||||
|
||||
assertEquals(parentNodeRef.getId(), getChildAssocResource(childAssocEvents.get(2)).getParent().getId());
|
||||
assertEquals(child3NodeRef.getId(), getChildAssocResource(childAssocEvents.get(2)).getChild().getId());
|
||||
assertEquals("cm:contains", getChildAssocResource(childAssocEvents.get(2)).getAssocType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteAssociationsOneChildMultipleParentsSameTransaction()
|
||||
{
|
||||
final NodeRef parent1NodeRef = createNode(ContentModel.TYPE_FOLDER);
|
||||
final NodeRef parent2NodeRef = createNode(ContentModel.TYPE_FOLDER);
|
||||
final NodeRef parent3NodeRef = createNode(ContentModel.TYPE_FOLDER);
|
||||
final NodeRef childNodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
|
||||
List<NodeRef> parents = Arrays.asList(parent1NodeRef, parent2NodeRef, parent3NodeRef);
|
||||
|
||||
checkNumOfEvents(4);
|
||||
|
||||
RepoEvent<NodeResource> resultRepoEvent = repoEventsContainer.getEvent(1);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(2);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(3);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(4);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
retryingTransactionHelper.doInTransaction(() ->
|
||||
nodeService.addChild(parents, childNodeRef, ContentModel.ASSOC_CONTAINS,
|
||||
QName.createQName(TEST_NAMESPACE, GUID.generate())));
|
||||
|
||||
List<ChildAssociationRef> listChildAssociationRefs = retryingTransactionHelper.doInTransaction(() -> {
|
||||
List<ChildAssociationRef> childAssocParent1 = nodeService.getChildAssocs(
|
||||
parent1NodeRef);
|
||||
List<ChildAssociationRef> childAssocParent2 = nodeService.getChildAssocs(
|
||||
parent2NodeRef);
|
||||
List<ChildAssociationRef> childAssocParent3 = nodeService.getChildAssocs(
|
||||
parent3NodeRef);
|
||||
|
||||
assertEquals(1, childAssocParent1.size());
|
||||
assertEquals(1, childAssocParent2.size());
|
||||
assertEquals(1, childAssocParent3.size());
|
||||
|
||||
return Arrays.asList(childAssocParent1.get(0), childAssocParent2.get(0), childAssocParent3.get(0));
|
||||
});
|
||||
|
||||
retryingTransactionHelper.doInTransaction(() -> {
|
||||
for (ChildAssociationRef childAssociationRef : listChildAssociationRefs)
|
||||
{
|
||||
nodeService.removeChildAssociation(childAssociationRef);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
checkNumOfEvents(10);
|
||||
|
||||
// 3 assoc.child.Deleted events should be created
|
||||
List<RepoEvent<NodeResource>> childAssocEvents = getChildAssocEvents(repoEventsContainer, EventType.CHILD_ASSOC_DELETED);
|
||||
assertEquals("Wrong association events number",3, childAssocEvents.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteAssociationOneParentMultipleChildrenDifferentTransactions()
|
||||
{
|
||||
final NodeRef parent1NodeRef = createNode(ContentModel.TYPE_FOLDER);
|
||||
final NodeRef parent2NodeRef = createNode(ContentModel.TYPE_FOLDER);
|
||||
final NodeRef parent3NodeRef = createNode(ContentModel.TYPE_FOLDER);
|
||||
final NodeRef childNodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
|
||||
List<NodeRef> parents = Arrays.asList(parent1NodeRef, parent2NodeRef, parent3NodeRef);
|
||||
|
||||
checkNumOfEvents(4);
|
||||
|
||||
RepoEvent<NodeResource> resultRepoEvent = repoEventsContainer.getEvent(1);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(2);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(3);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(4);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
retryingTransactionHelper.doInTransaction(() ->
|
||||
nodeService.addChild(parents, childNodeRef, ContentModel.ASSOC_CONTAINS,
|
||||
QName.createQName(TEST_NAMESPACE, GUID.generate())));
|
||||
|
||||
List<ChildAssociationRef> listChildAssociationRefs = retryingTransactionHelper.doInTransaction(() -> {
|
||||
List<ChildAssociationRef> childAssocParent1 = nodeService.getChildAssocs(
|
||||
parent1NodeRef);
|
||||
List<ChildAssociationRef> childAssocParent2 = nodeService.getChildAssocs(
|
||||
parent2NodeRef);
|
||||
List<ChildAssociationRef> childAssocParent3 = nodeService.getChildAssocs(
|
||||
parent3NodeRef);
|
||||
|
||||
assertEquals(1, childAssocParent1.size());
|
||||
assertEquals(1, childAssocParent2.size());
|
||||
assertEquals(1, childAssocParent3.size());
|
||||
|
||||
return Arrays.asList(childAssocParent1.get(0), childAssocParent2.get(0), childAssocParent3.get(0));
|
||||
});
|
||||
|
||||
for (ChildAssociationRef childAssociationRef : listChildAssociationRefs)
|
||||
{
|
||||
retryingTransactionHelper.doInTransaction(() ->
|
||||
nodeService.removeChildAssociation(childAssociationRef));
|
||||
}
|
||||
|
||||
checkNumOfEvents(10);
|
||||
|
||||
// 3 assoc.child.Deleted events should be created
|
||||
List<RepoEvent<NodeResource>> childAssocEvents = getChildAssocEvents(repoEventsContainer, EventType.CHILD_ASSOC_DELETED);
|
||||
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());
|
||||
assertEquals("cm:contains", getChildAssocResource(childAssocEvents.get(0)).getAssocType());
|
||||
|
||||
assertEquals(parent2NodeRef.getId(), getChildAssocResource(childAssocEvents.get(1)).getParent().getId());
|
||||
assertEquals(childNodeRef.getId(), getChildAssocResource(childAssocEvents.get(1)).getChild().getId());
|
||||
assertEquals("cm:contains", getChildAssocResource(childAssocEvents.get(1)).getAssocType());
|
||||
|
||||
assertEquals(parent3NodeRef.getId(), getChildAssocResource(childAssocEvents.get(2)).getParent().getId());
|
||||
assertEquals(childNodeRef.getId(), getChildAssocResource(childAssocEvents.get(2)).getChild().getId());
|
||||
assertEquals("cm:contains", getChildAssocResource(childAssocEvents.get(2)).getAssocType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteParentWithMultipleChildAssociations()
|
||||
{
|
||||
final NodeRef parentNodeRef = createNode(ContentModel.TYPE_FOLDER);
|
||||
final NodeRef child1NodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
final NodeRef child2NodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
final NodeRef child3NodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
|
||||
List<NodeRef> children = Arrays.asList(child1NodeRef, child2NodeRef, child3NodeRef);
|
||||
|
||||
checkNumOfEvents(4);
|
||||
|
||||
RepoEvent<NodeResource> resultRepoEvent = repoEventsContainer.getEvent(1);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(2);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(3);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(4);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
retryingTransactionHelper.doInTransaction(() -> {
|
||||
for (NodeRef child : children)
|
||||
{
|
||||
nodeService.addChild(parentNodeRef, child, ContentModel.ASSOC_CONTAINS,
|
||||
QName.createQName(TEST_NAMESPACE, GUID.generate()));
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
retryingTransactionHelper.doInTransaction(() -> {
|
||||
List<ChildAssociationRef> childAssocParent = nodeService.getChildAssocs(parentNodeRef);
|
||||
|
||||
assertEquals(3, childAssocParent.size());
|
||||
return null;
|
||||
});
|
||||
|
||||
deleteNode(parentNodeRef);
|
||||
|
||||
checkNumOfEvents(11);
|
||||
|
||||
// 3 assoc.child.Deleted events should be created
|
||||
List<RepoEvent<NodeResource>> childAssocEvents = getChildAssocEvents(repoEventsContainer, EventType.CHILD_ASSOC_DELETED);
|
||||
assertEquals("Wrong association events number",3, childAssocEvents.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteChildWithMultipleParentAssociations()
|
||||
{
|
||||
final NodeRef parent1NodeRef = createNode(ContentModel.TYPE_FOLDER);
|
||||
final NodeRef parent2NodeRef = createNode(ContentModel.TYPE_FOLDER);
|
||||
final NodeRef parent3NodeRef = createNode(ContentModel.TYPE_FOLDER);
|
||||
final NodeRef childNodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
|
||||
List<NodeRef> parents = Arrays.asList(parent1NodeRef, parent2NodeRef, parent3NodeRef);
|
||||
|
||||
checkNumOfEvents(4);
|
||||
|
||||
RepoEvent<NodeResource> resultRepoEvent = repoEventsContainer.getEvent(1);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(2);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(3);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(4);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
retryingTransactionHelper.doInTransaction(() ->
|
||||
nodeService.addChild(parents, childNodeRef, ContentModel.ASSOC_CONTAINS,
|
||||
QName.createQName(TEST_NAMESPACE, GUID.generate())));
|
||||
|
||||
retryingTransactionHelper.doInTransaction(() -> {
|
||||
List<ChildAssociationRef> childAssocParent1 = nodeService.getChildAssocs(
|
||||
parent1NodeRef);
|
||||
List<ChildAssociationRef> childAssocParent2 = nodeService.getChildAssocs(
|
||||
parent2NodeRef);
|
||||
List<ChildAssociationRef> childAssocParent3 = nodeService.getChildAssocs(
|
||||
parent3NodeRef);
|
||||
|
||||
assertEquals(1, childAssocParent1.size());
|
||||
assertEquals(1, childAssocParent2.size());
|
||||
assertEquals(1, childAssocParent3.size());
|
||||
return null;
|
||||
});
|
||||
|
||||
deleteNode(childNodeRef);
|
||||
|
||||
checkNumOfEvents(11);
|
||||
|
||||
// 3 assoc.child.Deleted events should be created
|
||||
List<RepoEvent<NodeResource>> childAssocEvents = getChildAssocEvents(repoEventsContainer, EventType.CHILD_ASSOC_DELETED);
|
||||
assertEquals("Wrong association events number",3, childAssocEvents.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateNodeAddChildAssociationNodeEventsFirst()
|
||||
{
|
||||
final NodeRef parentNodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
final NodeRef childNodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
|
||||
checkNumOfEvents(2);
|
||||
|
||||
RepoEvent<NodeResource> resultRepoEvent = repoEventsContainer.getEvent(1);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(2);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
retryingTransactionHelper.doInTransaction(() ->
|
||||
{
|
||||
nodeService.setType(parentNodeRef, ContentModel.TYPE_FOLDER);
|
||||
|
||||
return nodeService.addChild(
|
||||
parentNodeRef,
|
||||
childNodeRef,
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
QName.createQName(TEST_NAMESPACE, GUID.generate()));
|
||||
});
|
||||
|
||||
List<ChildAssociationRef> childAssociationRefs = retryingTransactionHelper.doInTransaction(() ->
|
||||
nodeService.getChildAssocs(parentNodeRef));
|
||||
|
||||
assertEquals(1, childAssociationRefs.size());
|
||||
assertFalse(childAssociationRefs.get(0).isPrimary());
|
||||
|
||||
checkNumOfEvents(4);
|
||||
|
||||
// Check the node events occur before the child association event
|
||||
List<RepoEvent<NodeResource>> 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.assoc.child.Created", repoEvents.get(3).getType());
|
||||
}
|
||||
}
|
@@ -0,0 +1,296 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2020 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.event2;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.junit.Test;
|
||||
|
||||
public class EventConsolidatorUnitTest
|
||||
{
|
||||
private NodeResourceHelper nodeResourceHelper = mock(NodeResourceHelper.class);
|
||||
|
||||
@Test
|
||||
public void testGetMappedAspectsBeforeRemovedAndAddedEmpty()
|
||||
{
|
||||
EventConsolidator eventConsolidator = new EventConsolidator(nodeResourceHelper);
|
||||
|
||||
Set<String> currentAspects = new HashSet<>();
|
||||
currentAspects.add("cm:geographic");
|
||||
currentAspects.add("cm:auditable");
|
||||
|
||||
Set<String> mappedAspectsBefore = eventConsolidator.getMappedAspectsBefore(currentAspects);
|
||||
|
||||
assertEquals(0, mappedAspectsBefore.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMappedAspectsBefore_AspectRemoved()
|
||||
{
|
||||
EventConsolidator eventConsolidator = new EventConsolidator(nodeResourceHelper);
|
||||
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
|
||||
|
||||
Set<String> currentAspects = new HashSet<>();
|
||||
currentAspects.add("cm:geographic");
|
||||
currentAspects.add("cm:auditable");
|
||||
|
||||
Set<String> removed = new HashSet<>();
|
||||
Set<String> added = new HashSet<>();
|
||||
removed.add("cm:contains");
|
||||
|
||||
when(nodeResourceHelper.mapToNodeAspects(eventConsolidator.getAspectsRemoved())).thenReturn(removed);
|
||||
when(nodeResourceHelper.mapToNodeAspects(eventConsolidator.getAspectsAdded())).thenReturn(added);
|
||||
|
||||
Set<String> mappedAspectsBefore = eventConsolidator.getMappedAspectsBefore(currentAspects);
|
||||
|
||||
assertEquals(3, mappedAspectsBefore.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMappedAspectsBefore_AspectAdded()
|
||||
{
|
||||
EventConsolidator eventConsolidator = new EventConsolidator(nodeResourceHelper);
|
||||
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
|
||||
|
||||
Set<String> currentAspects = new HashSet<>();
|
||||
currentAspects.add("cm:geographic");
|
||||
currentAspects.add("cm:auditable");
|
||||
|
||||
Set<String> removed = new HashSet<>();
|
||||
Set<String> added = new HashSet<>();
|
||||
added.add("cm:auditable");
|
||||
|
||||
when(nodeResourceHelper.mapToNodeAspects(eventConsolidator.getAspectsRemoved())).thenReturn(removed);
|
||||
when(nodeResourceHelper.mapToNodeAspects(eventConsolidator.getAspectsAdded())).thenReturn(added);
|
||||
|
||||
Set<String> mappedAspectsBefore = eventConsolidator.getMappedAspectsBefore(currentAspects);
|
||||
|
||||
assertEquals(1, mappedAspectsBefore.size());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGetMappedAspectsBefore_AspectAddedAndRemoved()
|
||||
{
|
||||
EventConsolidator eventConsolidator = new EventConsolidator(nodeResourceHelper);
|
||||
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
|
||||
|
||||
Set<String> currentAspects = new HashSet<>();
|
||||
currentAspects.add("cm:geographic");
|
||||
currentAspects.add("cm:auditable");
|
||||
|
||||
Set<String> removed = new HashSet<>();
|
||||
removed.add("cm:contains");
|
||||
Set<String> added = new HashSet<>();
|
||||
added.add("cm:contains");
|
||||
|
||||
when(nodeResourceHelper.mapToNodeAspects(eventConsolidator.getAspectsRemoved())).thenReturn(removed);
|
||||
when(nodeResourceHelper.mapToNodeAspects(eventConsolidator.getAspectsAdded())).thenReturn(added);
|
||||
|
||||
Set<String> mappedAspectsBefore = eventConsolidator.getMappedAspectsBefore(currentAspects);
|
||||
|
||||
assertEquals(2, mappedAspectsBefore.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMappedAspectsBefore_AspectRemovedAndAdded()
|
||||
{
|
||||
EventConsolidator eventConsolidator = new EventConsolidator(nodeResourceHelper);
|
||||
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
|
||||
eventConsolidator.removeAspect(ContentModel.ASSOC_CONTAINS);
|
||||
|
||||
Set<String> currentAspects = new HashSet<>();
|
||||
currentAspects.add("cm:geographic");
|
||||
currentAspects.add("cm:auditable");
|
||||
currentAspects.add("cm:contains");
|
||||
|
||||
Set<String> removed = new HashSet<>();
|
||||
removed.add("cm:contains");
|
||||
Set<String> added = new HashSet<>();
|
||||
added.add("cm:contains");
|
||||
|
||||
when(nodeResourceHelper.mapToNodeAspects(eventConsolidator.getAspectsRemoved())).thenReturn(removed);
|
||||
when(nodeResourceHelper.mapToNodeAspects(eventConsolidator.getAspectsAdded())).thenReturn(added);
|
||||
|
||||
Set<String> mappedAspectsBefore = eventConsolidator.getMappedAspectsBefore(currentAspects);
|
||||
|
||||
assertEquals(0, mappedAspectsBefore.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMappedAspectsBefore_AspectAddedTwiceRemovedOnce()
|
||||
{
|
||||
EventConsolidator eventConsolidator = new EventConsolidator(nodeResourceHelper);
|
||||
|
||||
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
|
||||
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
|
||||
|
||||
eventConsolidator.removeAspect(ContentModel.ASSOC_CONTAINS);
|
||||
|
||||
Set<String> currentAspects = new HashSet<>();
|
||||
currentAspects.add("cm:geographic");
|
||||
currentAspects.add("cm:auditable");
|
||||
currentAspects.add("cm:contains");
|
||||
|
||||
Set<String> removed = new HashSet<>();
|
||||
Set<String> added = new HashSet<>();
|
||||
added.add("cm:contains");
|
||||
|
||||
when(nodeResourceHelper.mapToNodeAspects(eventConsolidator.getAspectsRemoved())).thenReturn(removed);
|
||||
when(nodeResourceHelper.mapToNodeAspects(eventConsolidator.getAspectsAdded())).thenReturn(added);
|
||||
|
||||
Set<String> mappedAspectsBefore = eventConsolidator.getMappedAspectsBefore(currentAspects);
|
||||
|
||||
assertEquals(2, mappedAspectsBefore.size());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGetMappedAspectsBefore_AspectRemovedTwiceAddedOnce()
|
||||
{
|
||||
EventConsolidator eventConsolidator = new EventConsolidator(nodeResourceHelper);
|
||||
|
||||
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
|
||||
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
|
||||
|
||||
eventConsolidator.removeAspect(ContentModel.ASSOC_CONTAINS);
|
||||
|
||||
Set<String> currentAspects = new HashSet<>();
|
||||
currentAspects.add("cm:geographic");
|
||||
currentAspects.add("cm:auditable");
|
||||
currentAspects.add("cm:contains");
|
||||
|
||||
Set<String> removed = new HashSet<>();
|
||||
removed.add("cm:contains");
|
||||
Set<String> added = new HashSet<>();
|
||||
added.add("cm:contains");
|
||||
|
||||
when(nodeResourceHelper.mapToNodeAspects(eventConsolidator.getAspectsRemoved())).thenReturn(removed);
|
||||
when(nodeResourceHelper.mapToNodeAspects(eventConsolidator.getAspectsAdded())).thenReturn(added);
|
||||
|
||||
Set<String> mappedAspectsBefore = eventConsolidator.getMappedAspectsBefore(currentAspects);
|
||||
|
||||
assertEquals(2, mappedAspectsBefore.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMappedAspectsBefore_FilteredAspectAdded()
|
||||
{
|
||||
EventConsolidator eventConsolidator = new EventConsolidator(nodeResourceHelper);
|
||||
eventConsolidator.addAspect(ContentModel.ASPECT_COPIEDFROM);
|
||||
|
||||
Set<String> currentAspects = new HashSet<>();
|
||||
currentAspects.add("cm:geographic");
|
||||
currentAspects.add("cm:auditable");
|
||||
|
||||
Set<String> removed = new HashSet<>();
|
||||
Set<String> added = new HashSet<>();
|
||||
|
||||
when(nodeResourceHelper.mapToNodeAspects(eventConsolidator.getAspectsRemoved())).thenReturn(removed);
|
||||
when(nodeResourceHelper.mapToNodeAspects(eventConsolidator.getAspectsAdded())).thenReturn(added);
|
||||
|
||||
Set<String> mappedAspectsBefore = eventConsolidator.getMappedAspectsBefore(currentAspects);
|
||||
|
||||
assertEquals(0, mappedAspectsBefore.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddAspect()
|
||||
{
|
||||
EventConsolidator eventConsolidator = new EventConsolidator(nodeResourceHelper);
|
||||
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
|
||||
|
||||
assertEquals(1, eventConsolidator.getAspectsAdded().size());
|
||||
assertEquals(0, eventConsolidator.getAspectsRemoved().size());
|
||||
assertTrue(eventConsolidator.getAspectsAdded().contains(ContentModel.ASSOC_CONTAINS));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveAspect()
|
||||
{
|
||||
EventConsolidator eventConsolidator = new EventConsolidator(nodeResourceHelper);
|
||||
eventConsolidator.removeAspect(ContentModel.ASSOC_CONTAINS);
|
||||
|
||||
assertEquals(0, eventConsolidator.getAspectsAdded().size());
|
||||
assertEquals(1, eventConsolidator.getAspectsRemoved().size());
|
||||
assertTrue(eventConsolidator.getAspectsRemoved().contains(ContentModel.ASSOC_CONTAINS));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddAspectRemoveAspect()
|
||||
{
|
||||
EventConsolidator eventConsolidator = new EventConsolidator(nodeResourceHelper);
|
||||
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
|
||||
eventConsolidator.removeAspect(ContentModel.ASSOC_CONTAINS);
|
||||
|
||||
assertEquals(0, eventConsolidator.getAspectsAdded().size());
|
||||
assertEquals(0, eventConsolidator.getAspectsRemoved().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveAspectAddAspect()
|
||||
{
|
||||
EventConsolidator eventConsolidator = new EventConsolidator(nodeResourceHelper);
|
||||
eventConsolidator.removeAspect(ContentModel.ASSOC_CONTAINS);
|
||||
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
|
||||
|
||||
assertEquals(0, eventConsolidator.getAspectsAdded().size());
|
||||
assertEquals(0, eventConsolidator.getAspectsRemoved().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddAspectTwiceRemoveAspectOnce()
|
||||
{
|
||||
EventConsolidator eventConsolidator = new EventConsolidator(nodeResourceHelper);
|
||||
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
|
||||
eventConsolidator.removeAspect(ContentModel.ASSOC_CONTAINS);
|
||||
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
|
||||
|
||||
assertEquals(1, eventConsolidator.getAspectsAdded().size());
|
||||
assertEquals(0, eventConsolidator.getAspectsRemoved().size());
|
||||
assertTrue(eventConsolidator.getAspectsAdded().contains(ContentModel.ASSOC_CONTAINS));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddAspectOnceRemoveAspectTwice()
|
||||
{
|
||||
EventConsolidator eventConsolidator = new EventConsolidator(nodeResourceHelper);
|
||||
eventConsolidator.removeAspect(ContentModel.ASSOC_CONTAINS);
|
||||
eventConsolidator.addAspect(ContentModel.ASSOC_CONTAINS);
|
||||
eventConsolidator.removeAspect(ContentModel.ASSOC_CONTAINS);
|
||||
|
||||
assertEquals(0, eventConsolidator.getAspectsAdded().size());
|
||||
assertEquals(1, eventConsolidator.getAspectsRemoved().size());
|
||||
assertTrue(eventConsolidator.getAspectsRemoved().contains(ContentModel.ASSOC_CONTAINS));
|
||||
}
|
||||
}
|
@@ -37,6 +37,8 @@ import java.util.Collections;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.model.ForumModel;
|
||||
import org.alfresco.model.RenditionModel;
|
||||
import org.alfresco.repo.event2.filter.ChildAssociationTypeFilter;
|
||||
import org.alfresco.repo.event2.filter.EventUserFilter;
|
||||
import org.alfresco.repo.event2.filter.NodeAspectFilter;
|
||||
import org.alfresco.repo.event2.filter.NodePropertyFilter;
|
||||
@@ -61,6 +63,7 @@ public class EventFilterTest
|
||||
private static NodePropertyFilter propertyFilter;
|
||||
private static NodeTypeFilter typeFilter;
|
||||
private static NodeAspectFilter aspectFilter;
|
||||
private static ChildAssociationTypeFilter childAssociationTypeFilter;
|
||||
private static EventUserFilter caseInsensitive_userFilter;
|
||||
private static EventUserFilter caseSensitive_userFilter;
|
||||
|
||||
@@ -80,6 +83,8 @@ public class EventFilterTest
|
||||
NamespaceService.CONTENT_MODEL_1_0_URI);
|
||||
namespaceService.registerNamespace(NamespaceService.FORUMS_MODEL_PREFIX,
|
||||
NamespaceService.FORUMS_MODEL_1_0_URI);
|
||||
namespaceService.registerNamespace(NamespaceService.RENDITION_MODEL_PREFIX,
|
||||
NamespaceService.RENDITION_MODEL_1_0_URI);
|
||||
|
||||
propertyFilter = new NodePropertyFilter();
|
||||
propertyFilter.setNamespaceService(namespaceService);
|
||||
@@ -96,6 +101,11 @@ public class EventFilterTest
|
||||
aspectFilter.setDictionaryService(dictionaryService);
|
||||
aspectFilter.init();
|
||||
|
||||
childAssociationTypeFilter = new ChildAssociationTypeFilter("rn:rendition");
|
||||
childAssociationTypeFilter.setNamespaceService(namespaceService);
|
||||
childAssociationTypeFilter.setDictionaryService(dictionaryService);
|
||||
childAssociationTypeFilter.init();
|
||||
|
||||
caseInsensitive_userFilter = new EventUserFilter("System, john.doe, null", false);
|
||||
caseSensitive_userFilter = new EventUserFilter("System, john.doe, null", true);
|
||||
}
|
||||
@@ -139,6 +149,15 @@ public class EventFilterTest
|
||||
assertFalse(aspectFilter.isExcluded(ContentModel.ASPECT_TITLED));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void childAssociationTypeFilter()
|
||||
{
|
||||
assertTrue("Rendition child association type should have been filtered.",
|
||||
childAssociationTypeFilter.isExcluded(RenditionModel.ASSOC_RENDITION));
|
||||
|
||||
assertFalse(childAssociationTypeFilter.isExcluded(ContentModel.ASSOC_CONTAINS));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void userFilter_case_insensitive()
|
||||
{
|
||||
|
@@ -0,0 +1,374 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2020 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.event2;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.event.v1.model.EventData;
|
||||
import org.alfresco.repo.event.v1.model.NodeResource;
|
||||
import org.alfresco.repo.event.v1.model.PeerAssociationResource;
|
||||
import org.alfresco.repo.event.v1.model.RepoEvent;
|
||||
import org.alfresco.service.cmr.repository.AssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Chris Shields
|
||||
*/
|
||||
public class PeerAssociationRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
{
|
||||
private RepoEventContainer repoEventsContainer;
|
||||
|
||||
@Before
|
||||
public void initContainer()
|
||||
{
|
||||
repoEventsContainer = getRepoEventsContainer();
|
||||
repoEventsContainer.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddPeerAssociation()
|
||||
{
|
||||
final NodeRef content1NodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
final NodeRef content2NodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
|
||||
checkNumOfEvents(2);
|
||||
|
||||
RepoEvent<NodeResource> resultRepoEvent = repoEventsContainer.getEvent(1);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(2);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
retryingTransactionHelper.doInTransaction(() ->
|
||||
nodeService.createAssociation(
|
||||
content1NodeRef,
|
||||
content2NodeRef,
|
||||
ContentModel.ASSOC_ORIGINAL));
|
||||
|
||||
List<AssociationRef> peerAssociationRefs = retryingTransactionHelper.doInTransaction(
|
||||
() ->
|
||||
nodeService.getSourceAssocs(content2NodeRef, ContentModel.ASSOC_ORIGINAL));
|
||||
assertEquals(1, peerAssociationRefs.size());
|
||||
|
||||
checkNumOfEvents(4);
|
||||
|
||||
final RepoEvent<NodeResource> peerAssocRepoEvent = getChildAssocEvents(repoEventsContainer,
|
||||
EventType.PEER_ASSOC_CREATED).get(0);
|
||||
|
||||
assertEquals("Wrong repo event type.",
|
||||
EventType.PEER_ASSOC_CREATED.getType(),
|
||||
peerAssocRepoEvent.getType());
|
||||
assertNotNull("Repo event ID is not available. ", peerAssocRepoEvent.getId());
|
||||
assertNotNull("Source is not available", peerAssocRepoEvent.getSource());
|
||||
assertEquals("Repo event source is not available. ",
|
||||
"/" + descriptorService.getCurrentRepositoryDescriptor().getId(),
|
||||
peerAssocRepoEvent.getSource().toString());
|
||||
assertNotNull("Repo event creation time is not available. ", peerAssocRepoEvent.getTime());
|
||||
assertEquals("Repo event datacontenttype", "application/json",
|
||||
peerAssocRepoEvent.getDatacontenttype());
|
||||
assertEquals(EventData.JSON_SCHEMA, peerAssocRepoEvent.getDataschema());
|
||||
|
||||
final EventData<NodeResource> nodeResourceEventData = getEventData(peerAssocRepoEvent);
|
||||
// EventData attributes
|
||||
assertNotNull("Event data group ID is not available. ", nodeResourceEventData.getEventGroupId());
|
||||
assertNull("resourceBefore property is not available", nodeResourceEventData.getResourceBefore());
|
||||
|
||||
final PeerAssociationResource peerAssociationResource = getPeerAssocResource(peerAssocRepoEvent);
|
||||
assertEquals("Wrong source", content1NodeRef.getId(), peerAssociationResource.getSource().getId());
|
||||
assertEquals("Wrong target", content2NodeRef.getId(), peerAssociationResource.getTarget().getId());
|
||||
assertEquals("Wrong assoc type", "cm:original", peerAssociationResource.getAssocType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddMultiplePeerAssociationSameTransaction()
|
||||
{
|
||||
final NodeRef content1NodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
final NodeRef content2NodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
final NodeRef content3NodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
|
||||
checkNumOfEvents(3);
|
||||
|
||||
RepoEvent<NodeResource> resultRepoEvent = repoEventsContainer.getEvent(1);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(2);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(3);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
retryingTransactionHelper.doInTransaction(() -> {
|
||||
nodeService.createAssociation(
|
||||
content1NodeRef,
|
||||
content2NodeRef,
|
||||
ContentModel.ASSOC_ORIGINAL);
|
||||
|
||||
nodeService.createAssociation(
|
||||
content3NodeRef,
|
||||
content2NodeRef,
|
||||
ContentModel.ASSOC_ORIGINAL);
|
||||
return null;
|
||||
});
|
||||
|
||||
|
||||
List<AssociationRef> peerAssociationRefs = retryingTransactionHelper.doInTransaction(() ->
|
||||
nodeService.getSourceAssocs(content2NodeRef, ContentModel.ASSOC_ORIGINAL));
|
||||
|
||||
assertEquals(2, peerAssociationRefs.size());
|
||||
|
||||
checkNumOfEvents(7);
|
||||
|
||||
List<RepoEvent<NodeResource>> peerAssocRepoEvent = getChildAssocEvents(repoEventsContainer, EventType.PEER_ASSOC_CREATED);
|
||||
|
||||
// we should have 2 assoc.peer.Created events
|
||||
assertEquals("Wrong association events number",2, peerAssocRepoEvent.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddMultiplePeerAssociationDifferentTransaction()
|
||||
{
|
||||
final NodeRef content1NodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
final NodeRef content2NodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
final NodeRef content3NodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
|
||||
checkNumOfEvents(3);
|
||||
|
||||
RepoEvent<NodeResource> resultRepoEvent = repoEventsContainer.getEvent(1);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(2);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(3);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
retryingTransactionHelper.doInTransaction(() -> {
|
||||
nodeService.createAssociation(
|
||||
content1NodeRef,
|
||||
content2NodeRef,
|
||||
ContentModel.ASSOC_ORIGINAL);
|
||||
return null;
|
||||
});
|
||||
|
||||
retryingTransactionHelper.doInTransaction(() -> {
|
||||
nodeService.createAssociation(
|
||||
content3NodeRef,
|
||||
content2NodeRef,
|
||||
ContentModel.ASSOC_ORIGINAL);
|
||||
return null;
|
||||
});
|
||||
|
||||
List<AssociationRef> peerAssociationRefs = retryingTransactionHelper.doInTransaction(() ->
|
||||
nodeService.getSourceAssocs(content2NodeRef, ContentModel.ASSOC_ORIGINAL));
|
||||
|
||||
assertEquals(2, peerAssociationRefs.size());
|
||||
|
||||
checkNumOfEvents(7);
|
||||
|
||||
List<RepoEvent<NodeResource>> peerAssocRepoEvent = getChildAssocEvents(repoEventsContainer, EventType.PEER_ASSOC_CREATED);
|
||||
|
||||
// we should have 2 assoc.peer.Created events
|
||||
assertEquals("Wrong association events number",2, peerAssocRepoEvent.size());
|
||||
|
||||
assertEquals("Wrong source",
|
||||
content1NodeRef.getId(),
|
||||
getPeerAssocResource(peerAssocRepoEvent.get(0)).getSource().getId());
|
||||
assertEquals("Wrong target",
|
||||
content2NodeRef.getId(),
|
||||
getPeerAssocResource(peerAssocRepoEvent.get(0)).getTarget().getId());
|
||||
assertEquals("Wrong assoc type",
|
||||
"cm:original",
|
||||
getPeerAssocResource(peerAssocRepoEvent.get(0)).getAssocType());
|
||||
|
||||
assertEquals("Wrong source",
|
||||
content3NodeRef.getId(),
|
||||
getPeerAssocResource(peerAssocRepoEvent.get(1)).getSource().getId());
|
||||
assertEquals("Wrong target",
|
||||
content2NodeRef.getId(),
|
||||
getPeerAssocResource(peerAssocRepoEvent.get(1)).getTarget().getId());
|
||||
assertEquals("Wrong assoc type",
|
||||
"cm:original",
|
||||
getPeerAssocResource(peerAssocRepoEvent.get(1)).getAssocType());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRemovePeerAssociation()
|
||||
{
|
||||
final NodeRef content1NodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
final NodeRef content2NodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
|
||||
checkNumOfEvents(2);
|
||||
|
||||
RepoEvent<NodeResource> resultRepoEvent = repoEventsContainer.getEvent(1);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(2);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
// Create peer association
|
||||
retryingTransactionHelper.doInTransaction(() ->
|
||||
nodeService.createAssociation(
|
||||
content1NodeRef,
|
||||
content2NodeRef,
|
||||
ContentModel.ASSOC_ORIGINAL));
|
||||
|
||||
List<AssociationRef> peerAssociationRefs = retryingTransactionHelper.doInTransaction(
|
||||
() ->
|
||||
nodeService.getSourceAssocs(content2NodeRef, ContentModel.ASSOC_ORIGINAL));
|
||||
assertEquals(1, peerAssociationRefs.size());
|
||||
|
||||
checkNumOfEvents(4);
|
||||
|
||||
// Remove peer association
|
||||
retryingTransactionHelper.doInTransaction(() ->
|
||||
{
|
||||
nodeService.removeAssociation(
|
||||
content1NodeRef,
|
||||
content2NodeRef,
|
||||
ContentModel.ASSOC_ORIGINAL);
|
||||
return null;
|
||||
});
|
||||
|
||||
peerAssociationRefs = retryingTransactionHelper.doInTransaction(
|
||||
() ->
|
||||
nodeService.getSourceAssocs(content2NodeRef, ContentModel.ASSOC_ORIGINAL));
|
||||
assertEquals(0, peerAssociationRefs.size());
|
||||
|
||||
checkNumOfEvents(6);
|
||||
|
||||
// Check the peer assoc created event
|
||||
final RepoEvent<NodeResource> peerAssocRepoEvent = getChildAssocEvents(repoEventsContainer,
|
||||
EventType.PEER_ASSOC_CREATED).get(0);
|
||||
|
||||
assertEquals("Wrong repo event type.",
|
||||
EventType.PEER_ASSOC_CREATED.getType(),
|
||||
peerAssocRepoEvent.getType());
|
||||
assertNotNull("Repo event ID is not available. ", peerAssocRepoEvent.getId());
|
||||
assertNotNull("Source is not available", peerAssocRepoEvent.getSource());
|
||||
assertEquals("Repo event source is not available. ",
|
||||
"/" + descriptorService.getCurrentRepositoryDescriptor().getId(),
|
||||
peerAssocRepoEvent.getSource().toString());
|
||||
assertNotNull("Repo event creation time is not available. ", peerAssocRepoEvent.getTime());
|
||||
assertEquals("Repo event datacontenttype", "application/json",
|
||||
peerAssocRepoEvent.getDatacontenttype());
|
||||
assertEquals(EventData.JSON_SCHEMA, peerAssocRepoEvent.getDataschema());
|
||||
|
||||
final EventData nodeResourceEventData = getEventData(peerAssocRepoEvent);
|
||||
// EventData attributes
|
||||
assertNotNull("Event data group ID is not available. ",
|
||||
nodeResourceEventData.getEventGroupId());
|
||||
assertNull("resourceBefore property is not available",
|
||||
nodeResourceEventData.getResourceBefore());
|
||||
|
||||
final PeerAssociationResource peerAssociationResource = getPeerAssocResource(
|
||||
peerAssocRepoEvent);
|
||||
assertEquals("Wrong source", content1NodeRef.getId(),
|
||||
peerAssociationResource.getSource().getId());
|
||||
assertEquals("Wrong target", content2NodeRef.getId(),
|
||||
peerAssociationResource.getTarget().getId());
|
||||
assertEquals("Wrong assoc type", "cm:original",
|
||||
peerAssociationResource.getAssocType());
|
||||
|
||||
// Check the peer assoc deleted event
|
||||
final RepoEvent<NodeResource> peerAssocRepoEvent2 = getChildAssocEvents(repoEventsContainer,
|
||||
EventType.PEER_ASSOC_DELETED).get(0);
|
||||
|
||||
assertEquals("Wrong repo event type.",
|
||||
EventType.PEER_ASSOC_DELETED.getType(),
|
||||
peerAssocRepoEvent2.getType());
|
||||
assertNotNull("Repo event ID is not available. ", peerAssocRepoEvent2.getId());
|
||||
assertNotNull("Source is not available", peerAssocRepoEvent2.getSource());
|
||||
assertEquals("Repo event source is not available. ",
|
||||
"/" + descriptorService.getCurrentRepositoryDescriptor().getId(),
|
||||
peerAssocRepoEvent2.getSource().toString());
|
||||
assertNotNull("Repo event creation time is not available. ", peerAssocRepoEvent2.getTime());
|
||||
assertEquals("Repo event datacontenttype", "application/json",
|
||||
peerAssocRepoEvent2.getDatacontenttype());
|
||||
assertEquals(EventData.JSON_SCHEMA, peerAssocRepoEvent2.getDataschema());
|
||||
|
||||
final EventData nodeResourceEventData2 = getEventData(peerAssocRepoEvent2);
|
||||
// EventData attributes
|
||||
assertNotNull("Event data group ID is not available. ",
|
||||
nodeResourceEventData2.getEventGroupId());
|
||||
assertNull("resourceBefore property is not available",
|
||||
nodeResourceEventData2.getResourceBefore());
|
||||
|
||||
final PeerAssociationResource peerAssociationResource2 = getPeerAssocResource(
|
||||
peerAssocRepoEvent2);
|
||||
assertEquals("Wrong source", content1NodeRef.getId(),
|
||||
peerAssociationResource2.getSource().getId());
|
||||
assertEquals("Wrong target", content2NodeRef.getId(),
|
||||
peerAssociationResource2.getTarget().getId());
|
||||
assertEquals("Wrong assoc type", "cm:original",
|
||||
peerAssociationResource2.getAssocType());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testAddAndRemovePeerAssociationSameTransaction()
|
||||
{
|
||||
final NodeRef content1NodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
final NodeRef content2NodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
|
||||
checkNumOfEvents(2);
|
||||
|
||||
RepoEvent<NodeResource> resultRepoEvent = repoEventsContainer.getEvent(1);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(),
|
||||
resultRepoEvent.getType());
|
||||
|
||||
resultRepoEvent = repoEventsContainer.getEvent(2);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(),
|
||||
resultRepoEvent.getType());
|
||||
|
||||
// Create peer association
|
||||
retryingTransactionHelper.doInTransaction(() ->
|
||||
|
||||
{
|
||||
nodeService.createAssociation(
|
||||
content1NodeRef,
|
||||
content2NodeRef,
|
||||
ContentModel.ASSOC_ORIGINAL);
|
||||
|
||||
nodeService.removeAssociation(
|
||||
content1NodeRef,
|
||||
content2NodeRef,
|
||||
ContentModel.ASSOC_ORIGINAL);
|
||||
return null;
|
||||
});
|
||||
|
||||
List<AssociationRef> peerAssociationRefs = retryingTransactionHelper.doInTransaction(
|
||||
() ->
|
||||
nodeService.getSourceAssocs(content2NodeRef, ContentModel.ASSOC_ORIGINAL));
|
||||
assertEquals(0, peerAssociationRefs.size());
|
||||
|
||||
checkNumOfEvents(2);
|
||||
}
|
||||
}
|
@@ -33,7 +33,9 @@ import org.junit.runners.Suite.SuiteClasses;
|
||||
@SuiteClasses({ org.alfresco.repo.event2.CreateRepoEventIT.class,
|
||||
org.alfresco.repo.event2.UpdateRepoEventIT.class,
|
||||
org.alfresco.repo.event2.DeleteRepoEventIT.class,
|
||||
org.alfresco.repo.event2.DownloadRepoEventIT.class })
|
||||
org.alfresco.repo.event2.DownloadRepoEventIT.class,
|
||||
org.alfresco.repo.event2.ChildAssociationRepoEventIT.class,
|
||||
org.alfresco.repo.event2.PeerAssociationRepoEventIT.class })
|
||||
public class RepoEvent2ITSuite
|
||||
{
|
||||
}
|
||||
|
@@ -25,6 +25,7 @@
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.event2;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
@@ -76,6 +77,8 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
return null;
|
||||
});
|
||||
|
||||
checkNumOfEvents(2);
|
||||
|
||||
resultRepoEvent = getRepoEvent(2);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_UPDATED.getType(),
|
||||
resultRepoEvent.getType());
|
||||
@@ -152,6 +155,8 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
return null;
|
||||
});
|
||||
|
||||
checkNumOfEvents(2);
|
||||
|
||||
resultRepoEvent = getRepoEvent(2);
|
||||
assertEquals("Wrong repo event type.", EventType.NODE_UPDATED.getType(), resultRepoEvent.getType());
|
||||
|
||||
@@ -608,6 +613,8 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
return null;
|
||||
});
|
||||
|
||||
checkNumOfEvents(4);
|
||||
|
||||
NodeResource resourceBefore = getNodeResourceBefore(4);
|
||||
NodeResource resource = getNodeResource(4);
|
||||
|
||||
@@ -628,7 +635,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
assertNull(resourceBefore.getCreatedAt());
|
||||
assertNull(resourceBefore.getCreatedByUser());
|
||||
assertNull(resourceBefore.getProperties());
|
||||
assertNotNull(resourceBefore.getAspectNames());
|
||||
assertNull(resourceBefore.getAspectNames());
|
||||
assertNotNull(resourceBefore.getPrimaryHierarchy());
|
||||
assertNull("Content should have been null.", resource.getContent());
|
||||
assertNull("Content should have been null.", resourceBefore.getContent());
|
||||
@@ -820,4 +827,62 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
||||
|
||||
assertEquals("Wrong node parent.", folder2ID, moveFileParentAfterMove);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddAspectRemoveAspectFromContentSameTransactionTest()
|
||||
{
|
||||
final NodeRef nodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
NodeResource resource = getNodeResource(1);
|
||||
final Set<String> originalAspects = resource.getAspectNames();
|
||||
assertNotNull(originalAspects);
|
||||
|
||||
|
||||
retryingTransactionHelper.doInTransaction(() -> {
|
||||
// Add cm:geographic aspect with default value
|
||||
nodeService.addAspect(nodeRef, ContentModel.ASPECT_GEOGRAPHIC, null);
|
||||
|
||||
// Remove cm:geographic aspect
|
||||
nodeService.removeAspect(nodeRef, ContentModel.ASPECT_GEOGRAPHIC);
|
||||
return null;
|
||||
});
|
||||
|
||||
checkNumOfEvents(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddAspectRemoveAspectAddAspectFromContentSameTransactionTest()
|
||||
{
|
||||
final NodeRef nodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||
NodeResource resource = getNodeResource(1);
|
||||
final Set<String> originalAspects = resource.getAspectNames();
|
||||
assertNotNull(originalAspects);
|
||||
|
||||
retryingTransactionHelper.doInTransaction(() -> {
|
||||
// Add cm:geographic aspect with default value
|
||||
nodeService.addAspect(nodeRef, ContentModel.ASPECT_GEOGRAPHIC, null);
|
||||
|
||||
// Remove cm:geographic aspect
|
||||
nodeService.removeAspect(nodeRef, ContentModel.ASPECT_GEOGRAPHIC);
|
||||
|
||||
// Add cm:geographic aspect with default value
|
||||
nodeService.addAspect(nodeRef, ContentModel.ASPECT_GEOGRAPHIC, null);
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
checkNumOfEvents(2);
|
||||
|
||||
resource = getNodeResource(2);
|
||||
Set<String> aspectsAfter = resource.getAspectNames();
|
||||
assertNotNull(aspectsAfter);
|
||||
assertEquals(2, aspectsAfter.size());
|
||||
assertTrue(aspectsAfter.contains("cm:auditable"));
|
||||
assertTrue(aspectsAfter.contains("cm:auditable"));
|
||||
|
||||
NodeResource resourceBefore = getNodeResourceBefore(2);
|
||||
Set<String> aspectsBefore = resourceBefore.getAspectNames();
|
||||
assertNotNull(aspectsBefore);
|
||||
assertEquals(1, aspectsBefore.size());
|
||||
assertTrue(aspectsBefore.contains("cm:auditable"));
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user