nodePair = getNodePairNotNull(nodeRef);
-
- // Invoke policy behaviour
- invokeBeforeUpdateNode(nodeRef);
-
- // cm:name special handling
- setPropertiesCommonWork(
- nodePair,
- Collections.singletonMap(qname, value));
-
- // Add the property and all required defaults
- boolean changed = addAspectsAndProperties(
- nodePair, null,
- null, null,
- null, Collections.singletonMap(qname, value), false);
-
- if (changed)
- {
- // Invoke policy behaviour
- invokeOnUpdateNode(nodeRef);
- }
- }
-
- /**
- * Ensures that all required properties are present on the node and copies the
- * property values to the Node
.
- *
- * To remove a property, remove it from the map before calling this method.
- * Null-valued properties are allowed.
- *
- * If any of the values are null, a marker object is put in to mimic nulls. They will be turned back into
- * a real nulls when the properties are requested again.
- *
- */
- @Extend(traitAPI=NodeServiceTrait.class,extensionAPI=NodeServiceExtension.class)
- public void setProperties(NodeRef nodeRef, Map properties) throws InvalidNodeRefException
- {
- Pair nodePair = getNodePairNotNull(nodeRef);
-
- // Invoke policy behaviours
- invokeBeforeUpdateNode(nodeRef);
-
- // SetProperties common tasks
- setPropertiesCommonWork(nodePair, properties);
-
- // Set properties and defaults, overwriting the existing properties
- boolean changed = addAspectsAndProperties(nodePair, null, null, null, null, properties, true);
-
- if (changed)
- {
- // Invoke policy behaviours
- invokeOnUpdateNode(nodeRef);
- }
- }
-
- @Extend(traitAPI=NodeServiceTrait.class,extensionAPI=NodeServiceExtension.class)
- public void addProperties(NodeRef nodeRef, Map properties) throws InvalidNodeRefException
- {
- Pair nodePair = getNodePairNotNull(nodeRef);
-
- // Invoke policy behaviours
- invokeBeforeUpdateNode(nodeRef);
-
- // cm:name special handling
- setPropertiesCommonWork(nodePair, properties);
-
- // Add properties and defaults
- boolean changed = addAspectsAndProperties(nodePair, null, null, null, null, properties, false);
-
- if (changed)
- {
- // Invoke policy behaviours
- invokeOnUpdateNode(nodeRef);
- }
- }
-
- @Extend(traitAPI=NodeServiceTrait.class,extensionAPI=NodeServiceExtension.class)
- public void removeProperty(NodeRef nodeRef, QName qname) throws InvalidNodeRefException
- {
- // Get the node
- Pair nodePair = getNodePairNotNull(nodeRef);
- Long nodeId = nodePair.getFirst();
-
- // Invoke policy behaviours
- invokeBeforeUpdateNode(nodeRef);
-
- // Get the values before
- Map propertiesBefore = getPropertiesImpl(nodePair);
-
- // cm:name special handling
- if (qname.equals(ContentModel.PROP_NAME))
- {
- String oldName = extractNameProperty(nodeDAO.getNodeProperties(nodeId));
- String newName = null;
- setChildNameUnique(nodePair, newName, oldName);
- }
-
- // Remove
- nodeDAO.removeNodeProperties(nodeId, Collections.singleton(qname));
-
- // Invoke policy behaviours
- Map propertiesAfter = getPropertiesImpl(nodePair);
- invokeOnUpdateNode(nodeRef);
- invokeOnUpdateProperties(nodeRef, propertiesBefore, propertiesAfter);
- }
-
- public Collection getParents(NodeRef nodeRef) throws InvalidNodeRefException
- {
- List parentAssocs = getParentAssocs(
- nodeRef,
- RegexQNamePattern.MATCH_ALL,
- RegexQNamePattern.MATCH_ALL);
-
- // Copy into the set to avoid duplicates
- Set parentNodeRefs = new HashSet(parentAssocs.size());
- for (ChildAssociationRef parentAssoc : parentAssocs)
- {
- NodeRef parentNodeRef = parentAssoc.getParentRef();
- parentNodeRefs.add(parentNodeRef);
- }
- // Done
- return new ArrayList(parentNodeRefs);
- }
-
- /**
- * Filters out any associations if their qname is not a match to the given pattern.
- */
- @Extend(traitAPI=NodeServiceTrait.class,extensionAPI=NodeServiceExtension.class)
- public List getParentAssocs(
- final NodeRef nodeRef,
- final QNamePattern typeQNamePattern,
- final QNamePattern qnamePattern)
- {
- // Get the node
- Pair nodePair = getNodePairNotNull(nodeRef);
- Long nodeId = nodePair.getFirst();
-
- final List results = new ArrayList(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 childAssocPair,
- Pair parentNodePair,
- Pair 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;
- }
-
- @Override
- @Extend(traitAPI=NodeServiceTrait.class,extensionAPI=NodeServiceExtension.class)
- public List getParentAssocs(NodeRef nodeRef) throws InvalidNodeRefException
- {
- return super.getParentAssocs(nodeRef);
- }
-
- /**
- * Filters out any associations if their qname is not a match to the given pattern.
- */
- @Extend(traitAPI=NodeServiceTrait.class,extensionAPI=NodeServiceExtension.class)
- public List getChildAssocs(NodeRef nodeRef, final QNamePattern typeQNamePattern, final QNamePattern qnamePattern)
- {
- return getChildAssocs(nodeRef, typeQNamePattern, qnamePattern, true) ;
- }
-
- /**
- * Filters out any associations if their qname is not a match to the given pattern.
- */
- @Extend(traitAPI=NodeServiceTrait.class,extensionAPI=NodeServiceExtension.class)
- public List getChildAssocs(
- NodeRef nodeRef,
- final QNamePattern typeQNamePattern,
- final QNamePattern qnamePattern,
- final boolean preload)
- {
- return getChildAssocs(nodeRef, typeQNamePattern, qnamePattern, Integer.MAX_VALUE, preload);
- }
-
- /**
- * Fetches the first n child associations in an efficient manner
- */
- @Extend(traitAPI=NodeServiceTrait.class,extensionAPI=NodeServiceExtension.class)
- public List getChildAssocs(
- NodeRef nodeRef,
- final QNamePattern typeQNamePattern,
- final QNamePattern qnamePattern,
- final int maxResults,
- final boolean preload)
- {
- // Get the node
- Pair nodePair = getNodePairNotNull(nodeRef);
-
- // We have a callback handler to filter results
- final List results = new ArrayList(10);
- ChildAssocRefQueryCallback callback = new ChildAssocRefQueryCallback()
- {
- public boolean preLoadNodes()
- {
- return preload;
- }
-
- @Override
- public boolean orderResults()
- {
- return true;
- }
-
- public boolean handle(
- Pair childAssocPair,
- Pair parentNodePair,
- Pair 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;
- }
-
- @Extend(traitAPI=NodeServiceTrait.class,extensionAPI=NodeServiceExtension.class)
- public List getChildAssocs(NodeRef nodeRef, Set childNodeTypeQNames)
- {
- // Get the node
- Pair nodePair = getNodePairNotNull(nodeRef);
- Long nodeId = nodePair.getFirst();
-
- final List results = new ArrayList(100);
-
- NodeDAO.ChildAssocRefQueryCallback callback = new NodeDAO.ChildAssocRefQueryCallback()
- {
- public boolean preLoadNodes()
- {
- return true;
- }
-
- @Override
- public boolean orderResults()
- {
- return true;
- }
-
- public boolean handle(
- Pair childAssocPair,
- Pair parentNodePair,
- Pair childNodePair)
- {
- results.add(childAssocPair.getSecond());
- // More results
- return true;
- }
-
- public void done()
- {
- }
- };
- // Get all child associations with the specific qualified name
- nodeDAO.getChildAssocsByChildTypes(nodeId, childNodeTypeQNames, callback);
- // Done
- return results;
- }
-
- @Extend(traitAPI=NodeServiceTrait.class,extensionAPI=NodeServiceExtension.class)
- public NodeRef getChildByName(NodeRef nodeRef, QName assocTypeQName, String childName)
- {
- ParameterCheck.mandatory("childName", childName);
- ParameterCheck.mandatory("nodeRef", nodeRef);
- ParameterCheck.mandatory("assocTypeQName", assocTypeQName);
-
- // Get the node
- Pair nodePair = getNodePairNotNull(nodeRef);
- Long nodeId = nodePair.getFirst();
-
- Pair childAssocPair = nodeDAO.getChildAssoc(nodeId, assocTypeQName, childName);
- if (childAssocPair != null)
- {
- return childAssocPair.getSecond().getChildRef();
- }
- else
- {
- return null;
- }
- }
-
- @Extend(traitAPI=NodeServiceTrait.class,extensionAPI=NodeServiceExtension.class)
- public List getChildrenByName(NodeRef nodeRef, QName assocTypeQName, Collection childNames)
- {
- // Get the node
- Pair nodePair = getNodePairNotNull(nodeRef);
- Long nodeId = nodePair.getFirst();
-
- final List results = new ArrayList(100);
-
- NodeDAO.ChildAssocRefQueryCallback callback = new NodeDAO.ChildAssocRefQueryCallback()
- {
- public boolean preLoadNodes()
- {
- return true;
- }
-
- @Override
- public boolean orderResults()
- {
- return true;
- }
-
- public boolean handle(
- Pair childAssocPair,
- Pair parentNodePair,
- Pair 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;
- }
-
- @Extend(traitAPI=NodeServiceTrait.class,extensionAPI=NodeServiceExtension.class)
- public ChildAssociationRef getPrimaryParent(NodeRef nodeRef) throws InvalidNodeRefException
- {
- // Get the node
- Pair nodePair = getNodePairNotNull(nodeRef);
- Long nodeId = nodePair.getFirst();
-
- // get the primary parent assoc
- Pair assocPair = nodeDAO.getPrimaryParentAssoc(nodeId);
-
- // done - the assoc may be null for a root node
- ChildAssociationRef assocRef = null;
- if (assocPair == null)
- {
- assocRef = new ChildAssociationRef(null, null, null, nodeRef);
- }
- else
- {
- assocRef = assocPair.getSecond();
- }
- return assocRef;
- }
-
- @Override
- @Extend(traitAPI=NodeServiceTrait.class,extensionAPI=NodeServiceExtension.class)
- public AssociationRef createAssociation(NodeRef sourceRef, NodeRef targetRef, QName assocTypeQName)
- throws InvalidNodeRefException, AssociationExistsException
- {
- // The node(s) involved may not be pending deletion
- checkPendingDelete(sourceRef);
- checkPendingDelete(targetRef);
-
- Pair sourceNodePair = getNodePairNotNull(sourceRef);
- long sourceNodeId = sourceNodePair.getFirst();
- Pair targetNodePair = getNodePairNotNull(targetRef);
- long targetNodeId = targetNodePair.getFirst();
-
- // we are sure that the association doesn't exist - make it
- Long assocId = nodeDAO.newNodeAssoc(sourceNodeId, targetNodeId, assocTypeQName, -1);
- AssociationRef assocRef = new AssociationRef(assocId, sourceRef, assocTypeQName, targetRef);
-
- // Invoke policy behaviours
- invokeOnCreateAssociation(assocRef);
-
- // Add missing aspects
- addAspectsAndPropertiesAssoc(sourceNodePair, assocTypeQName, null, null, null, null, false);
-
- return assocRef;
- }
-
- @Override
- @Extend(traitAPI=NodeServiceTrait.class,extensionAPI=NodeServiceExtension.class)
- public void setAssociations(NodeRef sourceRef, QName assocTypeQName, List targetRefs)
- {
- // The node(s) involved may not be pending deletion
- checkPendingDelete(sourceRef);
-
- Pair sourceNodePair = getNodePairNotNull(sourceRef);
- Long sourceNodeId = sourceNodePair.getFirst();
- // First get the existing associations
- Collection> assocsBefore = nodeDAO.getTargetNodeAssocs(sourceNodeId, assocTypeQName);
- Map targetRefsBefore = new HashMap(assocsBefore.size());
- Map toRemoveMap = new HashMap(assocsBefore.size());
- for (Pair assocBeforePair : assocsBefore)
- {
- Long id = assocBeforePair.getFirst();
- NodeRef nodeRef = assocBeforePair.getSecond().getTargetRef();
- targetRefsBefore.put(nodeRef, id);
- toRemoveMap.put(nodeRef, id);
- }
- // Work out which associations need to be removed
- toRemoveMap.keySet().removeAll(targetRefs);
- // Fire policies for redundant assocs
- for (NodeRef targetRef : toRemoveMap.keySet())
- {
- AssociationRef assocRef = new AssociationRef(sourceRef, assocTypeQName, targetRef);
- invokeBeforeDeleteAssociation(assocRef);
- }
- // Remove reduncant assocs
- List toRemoveIds = new ArrayList(toRemoveMap.values());
- nodeDAO.removeNodeAssocs(toRemoveIds);
-
- // Work out which associations need to be added
- Set toAdd = new HashSet(targetRefs);
- toAdd.removeAll(targetRefsBefore.keySet());
-
- // Iterate over the desired result and create new or reset indexes
- int assocIndex = 1;
- for (NodeRef targetNodeRef : targetRefs)
- {
- // The node(s) involved may not be pending deletion
- checkPendingDelete(targetNodeRef);
-
- Long id = targetRefsBefore.get(targetNodeRef);
- // Is this an existing assoc?
- if (id != null)
- {
- // Update it
- nodeDAO.setNodeAssocIndex(id, assocIndex);
- }
- else
- {
- Long targetNodeId = getNodePairNotNull(targetNodeRef).getFirst();
- nodeDAO.newNodeAssoc(sourceNodeId, targetNodeId, assocTypeQName, assocIndex);
- }
- assocIndex++;
- }
-
- // Invoke policy behaviours
- for (NodeRef targetNodeRef : toAdd)
- {
- AssociationRef assocRef = new AssociationRef(sourceRef, assocTypeQName, targetNodeRef);
- invokeOnCreateAssociation(assocRef);
- }
- }
-
- @Extend(traitAPI=NodeServiceTrait.class,extensionAPI=NodeServiceExtension.class)
- public Collection getChildAssocsWithoutParentAssocsOfType(NodeRef parent, QName assocTypeQName)
- {
- // Get the parent node
- Pair nodePair = getNodePairNotNull(parent);
- Long parentNodeId = nodePair.getFirst();
-
- final List results = new ArrayList(100);
-
- NodeDAO.ChildAssocRefQueryCallback callback = new NodeDAO.ChildAssocRefQueryCallback()
- {
- public boolean preLoadNodes()
- {
- return false;
- }
-
- @Override
- public boolean orderResults()
- {
- return false;
- }
-
- public boolean handle(Pair childAssocPair, Pair parentNodePair,
- Pair childNodePair)
- {
- results.add(childAssocPair.getSecond());
- // More results
- return true;
- }
-
- public void done()
- {
- }
- };
- // Get the child associations that meet the criteria
- nodeDAO.getChildAssocsWithoutParentAssocsOfType(parentNodeId, assocTypeQName, callback);
- // done
- return results;
- }
-
- @Extend(traitAPI=NodeServiceTrait.class,extensionAPI=NodeServiceExtension.class)
- public List findAssocsNotLinkedByTwoOtherAssocs(NodeRef parent)
- {
- // Get the parent node
- Pair nodePair = getNodePairNotNull(parent);
- Long parentNodeId = nodePair.getFirst();
-
- return nodeDAO.selectAssocsNotLinkedByTwoOtherAssocs(parentNodeId);
- }
- /**
- * Specific properties not supported by {@link #getChildAssocsByPropertyValue(NodeRef, QName, Serializable)}
- */
- private static List getChildAssocsByPropertyValueBannedProps = new ArrayList();
- static
- {
- getChildAssocsByPropertyValueBannedProps.add(ContentModel.PROP_NODE_DBID);
- getChildAssocsByPropertyValueBannedProps.add(ContentModel.PROP_NODE_UUID);
- getChildAssocsByPropertyValueBannedProps.add(ContentModel.PROP_NAME);
- getChildAssocsByPropertyValueBannedProps.add(ContentModel.PROP_MODIFIED);
- getChildAssocsByPropertyValueBannedProps.add(ContentModel.PROP_MODIFIER);
- getChildAssocsByPropertyValueBannedProps.add(ContentModel.PROP_CREATED);
- getChildAssocsByPropertyValueBannedProps.add(ContentModel.PROP_CREATOR);
- }
-
- @Override
- @Extend(traitAPI=NodeServiceTrait.class,extensionAPI=NodeServiceExtension.class)
- public List getChildAssocsByPropertyValue(
- NodeRef nodeRef,
- QName propertyQName,
- Serializable value)
- {
- // Get the node
- Pair nodePair = getNodePairNotNull(nodeRef);
- Long nodeId = nodePair.getFirst();
-
- // Check the QName is not one of the "special" system maintained ones.
-
- if (getChildAssocsByPropertyValueBannedProps.contains(propertyQName))
- {
- throw new IllegalArgumentException(
- "getChildAssocsByPropertyValue does not allow search of system maintained properties: " + propertyQName);
- }
-
- final List results = new ArrayList(10);
- // We have a callback handler to filter results
- ChildAssocRefQueryCallback callback = new ChildAssocRefQueryCallback()
- {
- public boolean preLoadNodes()
- {
- return false;
- }
-
- @Override
- public boolean orderResults()
- {
- return true;
- }
-
- public boolean handle(
- Pair childAssocPair,
- Pair parentNodePair,
- Pair childNodePair)
- {
- results.add(childAssocPair.getSecond());
- return true;
- }
-
- public void done()
- {
- }
- };
- // Get the assocs pointing to it
- nodeDAO.getChildAssocsByPropertyValue(nodeId, propertyQName, value, callback);
- // Done
- return results;
- }
-
- @Extend(traitAPI=NodeServiceTrait.class,extensionAPI=NodeServiceExtension.class)
- public void removeAssociation(NodeRef sourceRef, NodeRef targetRef, QName assocTypeQName)
- throws InvalidNodeRefException
- {
- // The node(s) involved may not be pending deletion
- checkPendingDelete(sourceRef);
- checkPendingDelete(targetRef);
-
- Pair sourceNodePair = getNodePairNotNull(sourceRef);
- Long sourceNodeId = sourceNodePair.getFirst();
- Pair targetNodePair = getNodePairNotNull(targetRef);
- Long targetNodeId = targetNodePair.getFirst();
-
- AssociationRef assocRef = new AssociationRef(sourceRef, assocTypeQName, targetRef);
- // Invoke policy behaviours
- invokeBeforeDeleteAssociation(assocRef);
-
- // delete it
- int assocsDeleted = nodeDAO.removeNodeAssoc(sourceNodeId, targetNodeId, assocTypeQName);
-
- if (assocsDeleted > 0)
- {
- // Invoke policy behaviours
- invokeOnDeleteAssociation(assocRef);
- }
- }
-
- @Override
- @Extend(traitAPI=NodeServiceTrait.class,extensionAPI=NodeServiceExtension.class)
- public AssociationRef getAssoc(Long id)
- {
- Pair nodeAssocPair = nodeDAO.getNodeAssocOrNull(id);
- return nodeAssocPair == null ? null : nodeAssocPair.getSecond();
- }
-
- @Extend(traitAPI=NodeServiceTrait.class,extensionAPI=NodeServiceExtension.class)
- public List getTargetAssocs(NodeRef sourceRef, QNamePattern qnamePattern)
- {
- Pair sourceNodePair = getNodePairNotNull(sourceRef);
- Long sourceNodeId = sourceNodePair.getFirst();
-
- QName qnameFilter = null;
- if (qnamePattern instanceof QName)
- {
- qnameFilter = (QName) qnamePattern;
- }
- Collection> assocPairs = nodeDAO.getTargetNodeAssocs(sourceNodeId, qnameFilter);
- List nodeAssocRefs = new ArrayList(assocPairs.size());
- for (Pair assocPair : assocPairs)
- {
- AssociationRef assocRef = assocPair.getSecond();
- // check qname pattern, if not already filtered
- if (qnameFilter == null && !qnamePattern.isMatch(assocRef.getTypeQName()))
- {
- continue; // the assoc name doesn't match the pattern given
- }
- nodeAssocRefs.add(assocRef);
- }
- // done
- return nodeAssocRefs;
- }
-
- @Override
- @Extend(traitAPI=NodeServiceTrait.class,extensionAPI=NodeServiceExtension.class)
- public List getTargetAssocsByPropertyValue(NodeRef sourceRef, QNamePattern qnamePattern, QName propertyQName, Serializable propertyValue)
- {
- Pair sourceNodePair = getNodePairNotNull(sourceRef);
- Long sourceNodeId = sourceNodePair.getFirst();
-
- QName qnameFilter = null;
- if (qnamePattern instanceof QName)
- {
- qnameFilter = (QName) qnamePattern;
- }
-
- // Check the QName is not one of the "special" system maintained ones.
- if (getChildAssocsByPropertyValueBannedProps.contains(propertyQName))
- {
- throw new IllegalArgumentException(
- "getTargetAssocsByPropertyValue does not allow search of system maintained properties: " + propertyQName);
- }
-
- Collection> assocPairs = nodeDAO.getTargetAssocsByPropertyValue(sourceNodeId, qnameFilter, propertyQName, propertyValue);
- List nodeAssocRefs = new ArrayList