use of org.alfresco.traitextender.Extend in project alfresco-repository by Alfresco.
the class DbNodeServiceImpl method removeSecondaryChildAssociation.
@Override
@Extend(traitAPI = NodeServiceTrait.class, extensionAPI = NodeServiceExtension.class)
public boolean removeSecondaryChildAssociation(ChildAssociationRef childAssocRef) {
// The node(s) involved may not be pending deletion
checkPendingDelete(childAssocRef.getParentRef());
checkPendingDelete(childAssocRef.getChildRef());
Long parentNodeId = getNodePairNotNull(childAssocRef.getParentRef()).getFirst();
Long childNodeId = getNodePairNotNull(childAssocRef.getChildRef()).getFirst();
QName assocTypeQName = childAssocRef.getTypeQName();
QName assocQName = childAssocRef.getQName();
Pair<Long, ChildAssociationRef> assocPair = nodeDAO.getChildAssoc(parentNodeId, childNodeId, assocTypeQName, assocQName);
if (assocPair == null) {
// No association exists
return false;
}
Long assocId = assocPair.getFirst();
ChildAssociationRef assocRef = assocPair.getSecond();
if (assocRef.isPrimary()) {
throw new IllegalArgumentException("removeSeconaryChildAssociation can not be applied to a primary association: \n" + " Child Assoc: " + assocRef);
}
// Delete the secondary association
invokeBeforeDeleteChildAssociation(childAssocRef);
nodeDAO.deleteChildAssoc(assocId);
invokeOnDeleteChildAssociation(childAssocRef);
// Done
return true;
}
use of org.alfresco.traitextender.Extend in project alfresco-repository by Alfresco.
the class DbNodeServiceImpl method removeAspect.
@Override
@Extend(traitAPI = NodeServiceTrait.class, extensionAPI = NodeServiceExtension.class)
public void removeAspect(NodeRef nodeRef, QName aspectTypeQName) throws InvalidNodeRefException, InvalidAspectException {
// Don't allow spoofed aspect(s) to be removed
if (aspectTypeQName.equals(ContentModel.ASPECT_PENDING_DELETE)) {
throw new IllegalArgumentException("The aspect is reserved for system use: " + aspectTypeQName);
}
/*
* Note: Aspect and property removal is resilient to missing dictionary definitions
*/
// get the node
final Pair<Long, NodeRef> nodePair = getNodePairNotNull(nodeRef);
final Long nodeId = nodePair.getFirst();
boolean hadAspect = nodeDAO.hasNodeAspect(nodeId, aspectTypeQName);
// Invoke policy behaviours
invokeBeforeUpdateNode(nodeRef);
if (hadAspect) {
invokeBeforeRemoveAspect(nodeRef, aspectTypeQName);
nodeDAO.removeNodeAspects(nodeId, Collections.singleton(aspectTypeQName));
}
AspectDefinition aspectDef = dictionaryService.getAspect(aspectTypeQName);
boolean updated = false;
if (aspectDef != null) {
// Remove default properties
Map<QName, PropertyDefinition> propertyDefs = aspectDef.getProperties();
Set<QName> propertyToRemoveQNames = propertyDefs.keySet();
nodeDAO.removeNodeProperties(nodeId, propertyToRemoveQNames);
// Remove child associations
// We have to iterate over the associations and remove all those between the parent and child
final List<Pair<Long, ChildAssociationRef>> assocsToDelete = new ArrayList<Pair<Long, ChildAssociationRef>>(5);
final List<Pair<Long, NodeRef>> nodesToDelete = new ArrayList<Pair<Long, NodeRef>>(5);
NodeDAO.ChildAssocRefQueryCallback callback = new NodeDAO.ChildAssocRefQueryCallback() {
public boolean preLoadNodes() {
return true;
}
@Override
public boolean orderResults() {
return false;
}
public boolean handle(Pair<Long, ChildAssociationRef> childAssocPair, Pair<Long, NodeRef> parentNodePair, Pair<Long, NodeRef> childNodePair) {
if (isPendingDelete(parentNodePair.getSecond()) || isPendingDelete(childNodePair.getSecond())) {
if (logger.isTraceEnabled()) {
logger.trace("Aspect-triggered association removal: " + "Ignoring child associations where one of the nodes is pending delete: " + childAssocPair);
}
return true;
}
// have to delete the child node directly and with full archival.
if (childAssocPair.getSecond().isPrimary()) {
nodesToDelete.add(childNodePair);
} else {
assocsToDelete.add(childAssocPair);
}
// More results
return true;
}
public void done() {
}
};
// Get all the QNames to remove
Set<QName> assocTypeQNamesToRemove = new HashSet<QName>(aspectDef.getChildAssociations().keySet());
nodeDAO.getChildAssocs(nodeId, assocTypeQNamesToRemove, callback);
// Delete all the collected associations
for (Pair<Long, ChildAssociationRef> assocPair : assocsToDelete) {
updated = true;
Long assocId = assocPair.getFirst();
ChildAssociationRef assocRef = assocPair.getSecond();
// delete the association instance - it is not primary
invokeBeforeDeleteChildAssociation(assocRef);
nodeDAO.deleteChildAssoc(assocId);
invokeOnDeleteChildAssociation(assocRef);
}
// Cascade-delete any nodes that were attached to primary associations
for (Pair<Long, NodeRef> childNodePair : nodesToDelete) {
NodeRef childNodeRef = childNodePair.getSecond();
this.deleteNode(childNodeRef);
}
// Gather peer associations to delete
Map<QName, AssociationDefinition> nodeAssocDefs = aspectDef.getAssociations();
List<Long> nodeAssocIdsToRemove = new ArrayList<Long>(13);
List<AssociationRef> assocRefsRemoved = new ArrayList<AssociationRef>(13);
for (Map.Entry<QName, AssociationDefinition> entry : nodeAssocDefs.entrySet()) {
if (isPendingDelete(nodeRef)) {
if (logger.isTraceEnabled()) {
logger.trace("Aspect-triggered association removal: " + "Ignoring peer associations where one of the nodes is pending delete: " + nodeRef);
}
continue;
}
if (entry.getValue().isChild()) {
// Not interested in child assocs
continue;
}
QName assocTypeQName = entry.getKey();
Collection<Pair<Long, AssociationRef>> targetAssocRefs = nodeDAO.getTargetNodeAssocs(nodeId, assocTypeQName);
for (Pair<Long, AssociationRef> assocPair : targetAssocRefs) {
if (isPendingDelete(assocPair.getSecond().getTargetRef())) {
if (logger.isTraceEnabled()) {
logger.trace("Aspect-triggered association removal: " + "Ignoring peer associations where one of the nodes is pending delete: " + assocPair);
}
continue;
}
nodeAssocIdsToRemove.add(assocPair.getFirst());
assocRefsRemoved.add(assocPair.getSecond());
}
// MNT-9580: Daisy chained cm:original associations are cascade-deleted when the first original is deleted
// As a side-effect of the investigation of MNT-9446, it was dicovered that inbound associations (ones pointing *to* this aspect)
// were also being removed. This is incorrect because the aspect being removed here has no say over who points at it.
// Therefore, do not remove inbound associations because we only define outbound associations on types and aspects.
// Integrity checking will ensure that the correct behaviours are in place to maintain model integrity.
}
// Now delete peer associations
int assocsDeleted = nodeDAO.removeNodeAssocs(nodeAssocIdsToRemove);
for (AssociationRef assocRefRemoved : assocRefsRemoved) {
invokeOnDeleteAssociation(assocRefRemoved);
}
updated = updated || assocsDeleted > 0;
}
// Invoke policy behaviours
if (updated) {
invokeOnUpdateNode(nodeRef);
}
if (hadAspect) {
invokeOnRemoveAspect(nodeRef, aspectTypeQName);
}
}
use of org.alfresco.traitextender.Extend in project alfresco-repository by Alfresco.
the class DbNodeServiceImpl method getParentAssocs.
/**
* Filters out any associations if their qname is not a match to the given pattern.
*/
@Extend(traitAPI = NodeServiceTrait.class, extensionAPI = NodeServiceExtension.class)
public List<ChildAssociationRef> getParentAssocs(final NodeRef nodeRef, final QNamePattern typeQNamePattern, final QNamePattern qnamePattern) {
// Get the node
Pair<Long, NodeRef> nodePair = getNodePairNotNull(nodeRef);
Long nodeId = nodePair.getFirst();
final List<ChildAssociationRef> results = new ArrayList<ChildAssociationRef>(10);
// We have a callback handler to filter results
ChildAssocRefQueryCallback callback = new ChildAssocRefQueryCallback() {
public boolean preLoadNodes() {
return false;
}
@Override
public boolean orderResults() {
return false;
}
public boolean handle(Pair<Long, ChildAssociationRef> childAssocPair, Pair<Long, NodeRef> parentNodePair, Pair<Long, NodeRef> childNodePair) {
if (!typeQNamePattern.isMatch(childAssocPair.getSecond().getTypeQName())) {
return true;
}
if (!qnamePattern.isMatch(childAssocPair.getSecond().getQName())) {
return true;
}
results.add(childAssocPair.getSecond());
return true;
}
public void done() {
}
};
// Get the assocs pointing to it
QName typeQName = (typeQNamePattern instanceof QName) ? (QName) typeQNamePattern : null;
QName qname = (qnamePattern instanceof QName) ? (QName) qnamePattern : null;
nodeDAO.getParentAssocs(nodeId, typeQName, qname, null, callback);
// done
return results;
}
use of org.alfresco.traitextender.Extend in project alfresco-repository by Alfresco.
the class DbNodeServiceImpl method getChildAssocs.
/**
* Fetches the first n child associations in an efficient manner
*/
@Extend(traitAPI = NodeServiceTrait.class, extensionAPI = NodeServiceExtension.class)
public List<ChildAssociationRef> getChildAssocs(NodeRef nodeRef, final QNamePattern typeQNamePattern, final QNamePattern qnamePattern, final int maxResults, final boolean preload) {
// Get the node
Pair<Long, NodeRef> nodePair = getNodePairNotNull(nodeRef);
// We have a callback handler to filter results
final List<ChildAssociationRef> results = new ArrayList<ChildAssociationRef>(10);
ChildAssocRefQueryCallback callback = new ChildAssocRefQueryCallback() {
public boolean preLoadNodes() {
return preload;
}
@Override
public boolean orderResults() {
return true;
}
public boolean handle(Pair<Long, ChildAssociationRef> childAssocPair, Pair<Long, NodeRef> parentNodePair, Pair<Long, NodeRef> childNodePair) {
if (typeQNamePattern != null && !typeQNamePattern.isMatch(childAssocPair.getSecond().getTypeQName())) {
return true;
}
if (qnamePattern != null && !qnamePattern.isMatch(childAssocPair.getSecond().getQName())) {
return true;
}
results.add(childAssocPair.getSecond());
return true;
}
public void done() {
}
};
// Get the assocs pointing to it
QName typeQName = (typeQNamePattern instanceof QName) ? (QName) typeQNamePattern : null;
QName qname = (qnamePattern instanceof QName) ? (QName) qnamePattern : null;
nodeDAO.getChildAssocs(nodePair.getFirst(), typeQName, qname, maxResults, callback);
// Done
return results;
}
use of org.alfresco.traitextender.Extend in project alfresco-repository by Alfresco.
the class DbNodeServiceImpl method getChildrenByName.
@Extend(traitAPI = NodeServiceTrait.class, extensionAPI = NodeServiceExtension.class)
public List<ChildAssociationRef> getChildrenByName(NodeRef nodeRef, QName assocTypeQName, Collection<String> childNames) {
// Get the node
Pair<Long, NodeRef> nodePair = getNodePairNotNull(nodeRef);
Long nodeId = nodePair.getFirst();
final List<ChildAssociationRef> results = new ArrayList<ChildAssociationRef>(100);
NodeDAO.ChildAssocRefQueryCallback callback = new NodeDAO.ChildAssocRefQueryCallback() {
public boolean preLoadNodes() {
return true;
}
@Override
public boolean orderResults() {
return true;
}
public boolean handle(Pair<Long, ChildAssociationRef> childAssocPair, Pair<Long, NodeRef> parentNodePair, Pair<Long, NodeRef> childNodePair) {
results.add(childAssocPair.getSecond());
// More results
return true;
}
public void done() {
}
};
// Get all child associations with the specific qualified name
nodeDAO.getChildAssocs(nodeId, assocTypeQName, childNames, callback);
// Done
return results;
}
Aggregations