1 17 package org.alfresco.repo.node.db; 18 19 import java.io.Serializable ; 20 import java.util.ArrayList ; 21 import java.util.Collection ; 22 import java.util.Collections ; 23 import java.util.HashMap ; 24 import java.util.HashSet ; 25 import java.util.List ; 26 import java.util.Map ; 27 import java.util.Set ; 28 import java.util.Stack ; 29 30 import org.alfresco.model.ContentModel; 31 import org.alfresco.repo.domain.ChildAssoc; 32 import org.alfresco.repo.domain.Node; 33 import org.alfresco.repo.domain.NodeAssoc; 34 import org.alfresco.repo.domain.NodeKey; 35 import org.alfresco.repo.domain.NodeStatus; 36 import org.alfresco.repo.domain.PropertyValue; 37 import org.alfresco.repo.domain.Store; 38 import org.alfresco.repo.node.AbstractNodeServiceImpl; 39 import org.alfresco.repo.policy.PolicyComponent; 40 import org.alfresco.repo.transaction.AlfrescoTransactionSupport; 41 import org.alfresco.service.cmr.dictionary.AspectDefinition; 42 import org.alfresco.service.cmr.dictionary.ClassDefinition; 43 import org.alfresco.service.cmr.dictionary.DataTypeDefinition; 44 import org.alfresco.service.cmr.dictionary.DictionaryService; 45 import org.alfresco.service.cmr.dictionary.InvalidAspectException; 46 import org.alfresco.service.cmr.dictionary.InvalidTypeException; 47 import org.alfresco.service.cmr.dictionary.PropertyDefinition; 48 import org.alfresco.service.cmr.dictionary.TypeDefinition; 49 import org.alfresco.service.cmr.repository.AssociationExistsException; 50 import org.alfresco.service.cmr.repository.AssociationRef; 51 import org.alfresco.service.cmr.repository.ChildAssociationRef; 52 import org.alfresco.service.cmr.repository.CyclicChildRelationshipException; 53 import org.alfresco.service.cmr.repository.InvalidChildAssociationRefException; 54 import org.alfresco.service.cmr.repository.InvalidNodeRefException; 55 import org.alfresco.service.cmr.repository.InvalidStoreRefException; 56 import org.alfresco.service.cmr.repository.NodeRef; 57 import org.alfresco.service.cmr.repository.Path; 58 import org.alfresco.service.cmr.repository.StoreExistsException; 59 import org.alfresco.service.cmr.repository.StoreRef; 60 import org.alfresco.service.cmr.repository.NodeRef.Status; 61 import org.alfresco.service.namespace.QName; 62 import org.alfresco.service.namespace.QNamePattern; 63 import org.springframework.util.Assert; 64 65 70 public class DbNodeServiceImpl extends AbstractNodeServiceImpl 71 { 72 private final DictionaryService dictionaryService; 73 private final NodeDaoService nodeDaoService; 74 75 public DbNodeServiceImpl( 76 PolicyComponent policyComponent, 77 DictionaryService dictionaryService, 78 NodeDaoService nodeDaoService) 79 { 80 super(policyComponent); 81 82 this.dictionaryService = dictionaryService; 83 this.nodeDaoService = nodeDaoService; 84 } 85 86 93 private Node getNodeNotNull(NodeRef nodeRef) throws InvalidNodeRefException 94 { 95 String protocol = nodeRef.getStoreRef().getProtocol(); 96 String identifier = nodeRef.getStoreRef().getIdentifier(); 97 Node unchecked = nodeDaoService.getNode(protocol, identifier, nodeRef.getId()); 98 if (unchecked == null) 99 { 100 throw new InvalidNodeRefException("Node does not exist: " + nodeRef, nodeRef); 101 } 102 return unchecked; 103 } 104 105 public boolean exists(StoreRef storeRef) 106 { 107 Store store = nodeDaoService.getStore(storeRef.getProtocol(), storeRef.getIdentifier()); 108 boolean exists = (store != null); 109 return exists; 111 } 112 113 public boolean exists(NodeRef nodeRef) 114 { 115 StoreRef storeRef = nodeRef.getStoreRef(); 116 Node node = nodeDaoService.getNode(storeRef.getProtocol(), 117 storeRef.getIdentifier(), 118 nodeRef.getId()); 119 boolean exists = (node != null); 120 return exists; 122 } 123 124 public Status getNodeStatus(NodeRef nodeRef) 125 { 126 NodeStatus nodeStatus = nodeDaoService.getNodeStatus( 127 nodeRef.getStoreRef().getProtocol(), 128 nodeRef.getStoreRef().getIdentifier(), 129 nodeRef.getId()); 130 if (nodeStatus == null) { 132 return null; 133 } 134 else 135 { 136 return new NodeRef.Status( 137 nodeStatus.getChangeTxnId(), 138 nodeStatus.isDeleted()); 139 } 140 } 141 142 145 public List <StoreRef> getStores() 146 { 147 List <Store> stores = nodeDaoService.getStores(); 148 List <StoreRef> storeRefs = new ArrayList <StoreRef>(stores.size()); 149 for (Store store : stores) 150 { 151 storeRefs.add(store.getStoreRef()); 152 } 153 return storeRefs; 155 } 156 157 161 public StoreRef createStore(String protocol, String identifier) 162 { 163 StoreRef storeRef = new StoreRef(protocol, identifier); 164 Store store = nodeDaoService.getStore(protocol, identifier); 166 if (store != null) 167 { 168 throw new StoreExistsException("Unable to create a store that already exists", 169 new StoreRef(protocol, identifier)); 170 } 171 172 invokeBeforeCreateStore(ContentModel.TYPE_STOREROOT, storeRef); 174 175 store = nodeDaoService.createStore(protocol, identifier); 177 Node rootNode = store.getRootNode(); 179 addAspect(rootNode.getNodeRef(), 181 ContentModel.ASPECT_ROOT, 182 Collections.<QName, Serializable >emptyMap()); 183 184 invokeOnCreateStore(rootNode.getNodeRef()); 186 187 if (!store.getStoreRef().equals(storeRef)) 189 { 190 throw new RuntimeException ("Incorrect store reference"); 191 } 192 return storeRef; 193 } 194 195 public NodeRef getRootNode(StoreRef storeRef) throws InvalidStoreRefException 196 { 197 Store store = nodeDaoService.getStore(storeRef.getProtocol(), storeRef.getIdentifier()); 198 if (store == null) 199 { 200 throw new InvalidStoreRefException("Store does not exist", storeRef); 201 } 202 Node node = store.getRootNode(); 204 if (node == null) 205 { 206 throw new InvalidStoreRefException("Store does not have a root node", storeRef); 207 } 208 NodeRef nodeRef = node.getNodeRef(); 209 return nodeRef; 211 } 212 213 216 public ChildAssociationRef createNode( 217 NodeRef parentRef, 218 QName assocTypeQName, 219 QName assocQName, 220 QName nodeTypeQName) 221 { 222 return this.createNode(parentRef, assocTypeQName, assocQName, nodeTypeQName, null); 223 } 224 225 228 public ChildAssociationRef createNode( 229 NodeRef parentRef, 230 QName assocTypeQName, 231 QName assocQName, 232 QName nodeTypeQName, 233 Map <QName, Serializable > properties) 234 { 235 Assert.notNull(parentRef); 236 Assert.notNull(assocTypeQName); 237 Assert.notNull(assocQName); 238 239 if (properties == null) 241 { 242 properties = new HashMap <QName, Serializable >(); 243 } 244 else 245 { 246 properties = new HashMap <QName, Serializable >(properties); 248 } 249 250 invokeBeforeUpdateNode(parentRef); 252 invokeBeforeCreateNode(parentRef, assocTypeQName, assocQName, nodeTypeQName); 253 254 StoreRef storeRef = parentRef.getStoreRef(); 256 Store store = nodeDaoService.getStore(storeRef.getProtocol(), storeRef.getIdentifier()); 257 if (store == null) 258 { 259 throw new RuntimeException ("No store found for parent node: " + parentRef); 260 } 261 262 TypeDefinition nodeTypeDef = dictionaryService.getType(nodeTypeQName); 264 if (nodeTypeDef == null) 265 { 266 throw new InvalidTypeException(nodeTypeQName); 267 } 268 269 String newId = generateGuid(properties); 271 272 Node node = nodeDaoService.newNode(store, newId, nodeTypeQName); 274 275 Node parentNode = getNodeNotNull(parentRef); 277 278 ChildAssoc childAssoc = nodeDaoService.newChildAssoc(parentNode, node, true, assocTypeQName, assocQName); 280 ChildAssociationRef childAssocRef = childAssoc.getChildAssocRef(); 281 282 addDefaultPropertyValues(nodeTypeDef, properties); 284 285 addDefaultAspects(nodeTypeDef, node, childAssocRef.getChildRef(), properties); 287 288 if (properties.size() > 0) 290 { 291 this.setProperties(node.getNodeRef(), properties); 292 } 293 294 invokeOnCreateNode(childAssocRef); 296 invokeOnUpdateNode(parentRef); 297 298 return childAssocRef; 300 } 301 302 307 private void addDefaultAspects(ClassDefinition classDefinition, Node node, NodeRef nodeRef, Map <QName, Serializable > properties) 308 { 309 List <AspectDefinition> defaultAspectDefs = classDefinition.getDefaultAspects(); 311 312 Set <QName> nodeAspects = node.getAspects(); 314 for (AspectDefinition defaultAspectDef : defaultAspectDefs) 315 { 316 invokeBeforeAddAspect(nodeRef, defaultAspectDef.getName()); 317 nodeAspects.add(defaultAspectDef.getName()); 318 addDefaultPropertyValues(defaultAspectDef, properties); 319 invokeOnAddAspect(nodeRef, defaultAspectDef.getName()); 320 321 addDefaultAspects(defaultAspectDef, node, nodeRef, properties); 323 } 324 } 325 326 332 private void addDefaultPropertyValues(ClassDefinition classDefinition, Map <QName, Serializable > properties) 333 { 334 for (Map.Entry <QName, Serializable > entry : classDefinition.getDefaultValues().entrySet()) 335 { 336 if (properties.containsKey(entry.getKey())) 337 { 338 continue; 340 } 341 Serializable value = entry.getValue(); 342 343 PropertyDefinition prop = this.dictionaryService.getProperty(entry.getKey()); 345 if (prop == null) 346 { 347 continue; 349 } 350 351 353 if (DataTypeDefinition.BOOLEAN.equals(prop.getDataType().getName()) == true) 355 { 356 if (value instanceof String ) 357 { 358 if (((String )value).toUpperCase().equals("TRUE") == true) 359 { 360 value = Boolean.TRUE; 361 } 362 else if (((String )value).toUpperCase().equals("FALSE") == true) 363 { 364 value = Boolean.FALSE; 365 } 366 } 367 } 368 369 properties.put(entry.getKey(), value); 371 } 372 } 373 374 377 public ChildAssociationRef moveNode( 378 NodeRef nodeToMoveRef, 379 NodeRef newParentRef, 380 QName assocTypeQName, 381 QName assocQName) 382 throws InvalidNodeRefException 383 { 384 Assert.notNull(nodeToMoveRef); 385 Assert.notNull(newParentRef); 386 Assert.notNull(assocTypeQName); 387 Assert.notNull(assocQName); 388 389 Node nodeToMove = getNodeNotNull(nodeToMoveRef); 391 Node newParentNode = getNodeNotNull(newParentRef); 392 ChildAssoc oldAssoc = nodeDaoService.getPrimaryParentAssoc(nodeToMove); 394 ChildAssociationRef oldAssocRef = oldAssoc.getChildAssocRef(); 395 Node oldParentNode = oldAssoc.getParent(); 397 398 invokeBeforeDeleteChildAssociation(oldAssocRef); 400 invokeBeforeCreateChildAssociation(newParentRef, nodeToMoveRef, assocTypeQName, assocQName); 401 invokeBeforeUpdateNode(oldParentNode.getNodeRef()); invokeBeforeUpdateNode(newParentRef); 404 nodeDaoService.deleteChildAssoc(oldAssoc, false); 407 ChildAssoc newAssoc = nodeDaoService.newChildAssoc(newParentNode, nodeToMove, true, assocTypeQName, assocQName); 409 410 getPaths(nodeToMoveRef, false); 412 413 invokeOnCreateChildAssociation(newAssoc.getChildAssocRef()); 415 invokeOnDeleteChildAssociation(oldAssoc.getChildAssocRef()); 416 invokeOnUpdateNode(oldParentNode.getNodeRef()); 417 invokeOnUpdateNode(newParentRef); 418 419 NodeStatus nodeStatus = nodeToMove.getStatus(); 421 nodeStatus.setChangeTxnId(AlfrescoTransactionSupport.getTransactionId()); 422 423 return newAssoc.getChildAssocRef(); 425 } 426 427 public void setChildAssociationIndex(ChildAssociationRef childAssocRef, int index) 428 { 429 Node parentNode = getNodeNotNull(childAssocRef.getParentRef()); 431 Node childNode = getNodeNotNull(childAssocRef.getChildRef()); 432 433 ChildAssoc assoc = nodeDaoService.getChildAssoc( 434 parentNode, 435 childNode, 436 childAssocRef.getTypeQName(), 437 childAssocRef.getQName()); 438 if (assoc == null) 439 { 440 throw new InvalidChildAssociationRefException("Unable to set child association index: \n" + 441 " assoc: " + childAssocRef + "\n" + 442 " index: " + index, 443 childAssocRef); 444 } 445 assoc.setIndex(index); 447 } 448 449 public QName getType(NodeRef nodeRef) throws InvalidNodeRefException 450 { 451 Node node = getNodeNotNull(nodeRef); 452 return node.getTypeQName(); 453 } 454 455 458 public void setType(NodeRef nodeRef, QName typeQName) throws InvalidNodeRefException 459 { 460 TypeDefinition nodeTypeDef = dictionaryService.getType(typeQName); 462 if (nodeTypeDef == null) 463 { 464 throw new InvalidTypeException(typeQName); 465 } 466 467 invokeBeforeUpdateNode(nodeRef); 469 470 Node node = getNodeNotNull(nodeRef); 472 node.setTypeQName(typeQName); 473 474 Map <QName, Serializable > properties = this.getProperties(nodeRef); 476 addDefaultAspects(nodeTypeDef, node, nodeRef, properties); 477 this.setProperties(nodeRef, properties); 478 479 invokeOnUpdateNode(nodeRef); 481 } 482 483 486 public void addAspect( 487 NodeRef nodeRef, 488 QName aspectTypeQName, 489 Map <QName, Serializable > aspectProperties) 490 throws InvalidNodeRefException, InvalidAspectException 491 { 492 AspectDefinition aspectDef = dictionaryService.getAspect(aspectTypeQName); 494 if (aspectDef == null) 495 { 496 throw new InvalidAspectException("The aspect is invalid: " + aspectTypeQName, aspectTypeQName); 497 } 498 499 invokeBeforeUpdateNode(nodeRef); 501 invokeBeforeAddAspect(nodeRef, aspectTypeQName); 502 503 Node node = getNodeNotNull(nodeRef); 504 505 Map <QName, Serializable > nodeProperties = getProperties(nodeRef); 507 508 if (aspectProperties != null) 509 { 510 nodeProperties.putAll(aspectProperties); 511 } 512 513 addDefaultPropertyValues(aspectDef, nodeProperties); 515 516 addDefaultAspects(aspectDef, node, nodeRef, nodeProperties); 518 519 setProperties(nodeRef, nodeProperties); 521 522 if (node.getAspects().add(aspectTypeQName) == true) 524 { 525 invokeOnUpdateNode(nodeRef); 527 invokeOnAddAspect(nodeRef, aspectTypeQName); 528 529 NodeStatus nodeStatus = node.getStatus(); 531 nodeStatus.setChangeTxnId(AlfrescoTransactionSupport.getTransactionId()); 532 } 533 } 534 535 538 public void removeAspect(NodeRef nodeRef, QName aspectTypeQName) 539 throws InvalidNodeRefException, InvalidAspectException 540 { 541 invokeBeforeUpdateNode(nodeRef); 543 invokeBeforeRemoveAspect(nodeRef, aspectTypeQName); 544 545 AspectDefinition aspectDef = dictionaryService.getAspect(aspectTypeQName); 547 if (aspectDef == null) 548 { 549 throw new InvalidAspectException(aspectTypeQName); 550 } 551 Node node = getNodeNotNull(nodeRef); 553 554 TypeDefinition nodeTypeDef = dictionaryService.getType(node.getTypeQName()); 556 if (nodeTypeDef == null) 557 { 558 throw new InvalidNodeRefException("The node type is no longer valid: " + nodeRef, nodeRef); 559 } 560 List <AspectDefinition> defaultAspects = nodeTypeDef.getDefaultAspects(); 561 if (defaultAspects.contains(aspectDef)) 562 { 563 throw new InvalidAspectException( 564 "The aspect is a default for the node's type and cannot be removed: " + aspectTypeQName, 565 aspectTypeQName); 566 } 567 568 boolean removed = node.getAspects().remove(aspectTypeQName); 570 if (removed) 572 { 573 Map <QName, PropertyValue> nodeProperties = node.getProperties(); 574 Map <QName,PropertyDefinition> propertyDefs = aspectDef.getProperties(); 575 for (QName propertyName : propertyDefs.keySet()) 576 { 577 nodeProperties.remove(propertyName); 578 } 579 580 invokeOnUpdateNode(nodeRef); 582 invokeOnRemoveAspect(nodeRef, aspectTypeQName); 583 584 NodeStatus nodeStatus = node.getStatus(); 586 nodeStatus.setChangeTxnId(AlfrescoTransactionSupport.getTransactionId()); 587 } 588 } 589 590 595 public boolean hasAspect(NodeRef nodeRef, QName aspectRef) throws InvalidNodeRefException, InvalidAspectException 596 { 597 Node node = getNodeNotNull(nodeRef); 598 Set <QName> aspectQNames = node.getAspects(); 599 boolean hasAspect = aspectQNames.contains(aspectRef); 600 return hasAspect; 602 } 603 604 public Set <QName> getAspects(NodeRef nodeRef) throws InvalidNodeRefException 605 { 606 Node node = getNodeNotNull(nodeRef); 607 Set <QName> aspectQNames = node.getAspects(); 608 Set <QName> ret = new HashSet <QName>(aspectQNames.size()); 610 ret.addAll(aspectQNames); 611 return ret; 613 } 614 615 public void deleteNode(NodeRef nodeRef) 616 { 617 invokeBeforeDeleteNode(nodeRef); 619 620 Node node = getNodeNotNull(nodeRef); 622 ChildAssociationRef childAssocRef = getPrimaryParent(nodeRef); 624 QName nodeTypeQName = node.getTypeQName(); 626 Set <QName> nodeAspectQNames = node.getAspects(); 627 nodeDaoService.deleteNode(node, true); 629 630 invokeOnDeleteNode(childAssocRef, nodeTypeQName, nodeAspectQNames); 632 } 633 723 public ChildAssociationRef addChild(NodeRef parentRef, NodeRef childRef, QName assocTypeQName, QName assocQName) 724 { 725 invokeBeforeUpdateNode(parentRef); 727 invokeBeforeCreateChildAssociation(parentRef, childRef, assocTypeQName, assocQName); 728 729 if (!parentRef.getStoreRef().equals(childRef.getStoreRef())) 731 { 732 throw new InvalidNodeRefException("Parent and child nodes must belong to the same store: \n" + 733 " parent: " + parentRef + "\n" + 734 " child: " + childRef, 735 childRef); 736 } 737 738 Node parentNode = getNodeNotNull(parentRef); 740 Node childNode = getNodeNotNull(childRef); 742 ChildAssoc assoc = nodeDaoService.newChildAssoc(parentNode, childNode, false, assocTypeQName, assocQName); 744 ChildAssociationRef assocRef = assoc.getChildAssocRef(); 745 NodeRef childNodeRef = assocRef.getChildRef(); 746 747 getPaths(childNodeRef, false); 750 751 invokeOnCreateChildAssociation(assocRef); 753 invokeOnUpdateNode(parentRef); 754 755 return assoc.getChildAssocRef(); 756 } 757 758 public void removeChild(NodeRef parentRef, NodeRef childRef) throws InvalidNodeRefException 759 { 760 Node parentNode = getNodeNotNull(parentRef); 761 Node childNode = getNodeNotNull(childRef); 762 NodeKey childNodeKey = childNode.getKey(); 763 764 ChildAssociationRef primaryAssocRef = null; 766 Collection <ChildAssoc> assocs = parentNode.getChildAssocs(); 767 assocs = new HashSet <ChildAssoc>(assocs); for (ChildAssoc assoc : assocs) 769 { 770 if (!assoc.getChild().getKey().equals(childNodeKey)) 771 { 772 continue; } 774 ChildAssociationRef assocRef = assoc.getChildAssocRef(); 775 if (assoc.getIsPrimary()) 777 { 778 primaryAssocRef = assocRef; 780 } 781 else 782 { 783 invokeBeforeDeleteChildAssociation(assocRef); 785 nodeDaoService.deleteChildAssoc(assoc, true); invokeOnDeleteChildAssociation(assocRef); 787 } 788 } 789 if (primaryAssocRef != null) 791 { 792 deleteNode(primaryAssocRef.getChildRef()); 793 } 794 795 invokeOnUpdateNode(parentRef); 797 798 } 800 801 public Map <QName, Serializable > getProperties(NodeRef nodeRef) throws InvalidNodeRefException 802 { 803 Node node = getNodeNotNull(nodeRef); 804 Map <QName, PropertyValue> nodeProperties = node.getProperties(); 805 Map <QName, Serializable > ret = new HashMap <QName, Serializable >(nodeProperties.size()); 806 for (Map.Entry <QName, PropertyValue> entry: nodeProperties.entrySet()) 808 { 809 QName propertyQName = entry.getKey(); 810 PropertyValue propertyValue = entry.getValue(); 811 PropertyDefinition propertyDef = dictionaryService.getProperty(propertyQName); 813 Serializable value = makeSerializableValue(propertyDef, propertyValue); 815 ret.put(propertyQName, value); 817 } 818 addReferencableProperties(nodeRef, ret); 820 return ret; 822 } 823 824 public Serializable getProperty(NodeRef nodeRef, QName qname) throws InvalidNodeRefException 825 { 826 if (qname.equals(ContentModel.PROP_STORE_PROTOCOL)) 828 { 829 return nodeRef.getStoreRef().getProtocol(); 830 } 831 else if (qname.equals(ContentModel.PROP_STORE_IDENTIFIER)) 832 { 833 return nodeRef.getStoreRef().getIdentifier(); 834 } 835 else if (qname.equals(ContentModel.PROP_NODE_UUID)) 836 { 837 return nodeRef.getId(); 838 } 839 840 Node node = getNodeNotNull(nodeRef); 842 Map <QName, PropertyValue> properties = node.getProperties(); 843 PropertyValue propertyValue = properties.get(qname); 844 845 PropertyDefinition propertyDef = dictionaryService.getProperty(qname); 847 Serializable value = makeSerializableValue(propertyDef, propertyValue); 849 return value; 851 } 852 853 865 public void setProperties(NodeRef nodeRef, Map <QName, Serializable > properties) throws InvalidNodeRefException 866 { 867 invokeBeforeUpdateNode(nodeRef); 869 870 if (properties == null) 871 { 872 throw new IllegalArgumentException ("Properties may not be null"); 873 } 874 875 removeReferencableProperties(properties); 877 878 Node node = getNodeNotNull(nodeRef); 880 Map <QName, Serializable > propertiesBefore = getProperties(nodeRef); 882 883 Map <QName, PropertyValue> nodeProperties = node.getProperties(); 885 nodeProperties.clear(); 886 887 for (QName propertyQName : properties.keySet()) 889 { 890 PropertyDefinition propertyDef = dictionaryService.getProperty(propertyQName); 891 Serializable value = properties.get(propertyQName); 892 PropertyValue propertyValue = makePropertyValue(propertyDef, value); 894 nodeProperties.put(propertyQName, propertyValue); 895 } 896 897 Map <QName, Serializable > propertiesAfter = Collections.unmodifiableMap(properties); 899 900 invokeOnUpdateNode(nodeRef); 902 invokeOnUpdateProperties(nodeRef, propertiesBefore, propertiesAfter); 903 904 NodeStatus nodeStatus = node.getStatus(); 906 nodeStatus.setChangeTxnId(AlfrescoTransactionSupport.getTransactionId()); 907 } 908 909 915 public void setProperty(NodeRef nodeRef, QName qname, Serializable value) throws InvalidNodeRefException 916 { 917 Assert.notNull(qname); 918 919 invokeBeforeUpdateNode(nodeRef); 921 922 Node node = getNodeNotNull(nodeRef); 924 Map <QName, Serializable > propertiesBefore = getProperties(nodeRef); 926 927 Map <QName, PropertyValue> properties = node.getProperties(); 928 PropertyDefinition propertyDef = dictionaryService.getProperty(qname); 929 PropertyValue propertyValue = makePropertyValue(propertyDef, value); 931 properties.put(qname, propertyValue); 932 933 Map <QName, Serializable > propertiesAfter = getProperties(nodeRef); 935 936 invokeOnUpdateNode(nodeRef); 938 invokeOnUpdateProperties(nodeRef, propertiesBefore, propertiesAfter); 939 940 NodeStatus nodeStatus = node.getStatus(); 942 nodeStatus.setChangeTxnId(AlfrescoTransactionSupport.getTransactionId()); 943 } 944 945 948 public Collection <NodeRef> getParents(NodeRef nodeRef) throws InvalidNodeRefException 949 { 950 Node node = getNodeNotNull(nodeRef); 951 Collection <ChildAssoc> parentAssocs = node.getParentAssocs(); 953 Collection <NodeRef> results = new ArrayList <NodeRef>(parentAssocs.size()); 955 for (ChildAssoc assoc : parentAssocs) 956 { 957 Node parentNode = assoc.getParent(); 959 results.add(parentNode.getNodeRef()); 960 } 961 return results; 963 } 964 965 968 public List <ChildAssociationRef> getParentAssocs(NodeRef nodeRef, QNamePattern typeQNamePattern, QNamePattern qnamePattern) 969 { 970 Node node = getNodeNotNull(nodeRef); 971 Collection <ChildAssoc> parentAssocs = node.getParentAssocs(); 973 if (parentAssocs.size() == 0) 975 { 976 return Collections.emptyList(); 977 } 978 List <ChildAssociationRef> results = new ArrayList <ChildAssociationRef>(parentAssocs.size()); 980 for (ChildAssoc assoc : parentAssocs) 981 { 982 if (!qnamePattern.isMatch(assoc.getQname()) || !typeQNamePattern.isMatch(assoc.getTypeQName())) 984 { 985 continue; 987 } 988 results.add(assoc.getChildAssocRef()); 989 } 990 return results; 992 } 993 994 997 public List <ChildAssociationRef> getChildAssocs(NodeRef nodeRef, QNamePattern typeQNamePattern, QNamePattern qnamePattern) 998 { 999 Node node = getNodeNotNull(nodeRef); 1000 Collection <ChildAssoc> childAssocs = node.getChildAssocs(); 1002 if (childAssocs.size() == 0) 1004 { 1005 return Collections.emptyList(); 1006 } 1007 ArrayList <ChildAssoc> orderedList = new ArrayList <ChildAssoc>(childAssocs); 1009 Collections.sort(orderedList); 1010 1011 List <ChildAssociationRef> results = new ArrayList <ChildAssociationRef>(childAssocs.size()); 1013 int nthSibling = 0; 1014 for (ChildAssoc assoc : orderedList) 1015 { 1016 if (!qnamePattern.isMatch(assoc.getQname()) || !typeQNamePattern.isMatch(assoc.getTypeQName())) 1018 { 1019 continue; 1021 } 1022 ChildAssociationRef assocRef = assoc.getChildAssocRef(); 1023 assocRef.setNthSibling(nthSibling); 1025 nthSibling++; 1026 results.add(assoc.getChildAssocRef()); 1028 } 1029 return results; 1031 } 1032 1033 public ChildAssociationRef getPrimaryParent(NodeRef nodeRef) throws InvalidNodeRefException 1034 { 1035 Node node = getNodeNotNull(nodeRef); 1036 ChildAssoc assoc = nodeDaoService.getPrimaryParentAssoc(node); 1038 1039 ChildAssociationRef assocRef = null; 1041 if (assoc == null) 1042 { 1043 assocRef = new ChildAssociationRef(null, null, null, nodeRef); 1044 } 1045 else 1046 { 1047 assocRef = assoc.getChildAssocRef(); 1048 } 1049 return assocRef; 1050 } 1051 1052 public AssociationRef createAssociation(NodeRef sourceRef, NodeRef targetRef, QName assocTypeQName) 1053 throws InvalidNodeRefException, AssociationExistsException 1054 { 1055 invokeBeforeUpdateNode(sourceRef); 1057 1058 Node sourceNode = getNodeNotNull(sourceRef); 1059 Node targetNode = getNodeNotNull(targetRef); 1060 NodeAssoc assoc = nodeDaoService.getNodeAssoc(sourceNode, targetNode, assocTypeQName); 1062 if (assoc != null) 1063 { 1064 throw new AssociationExistsException(sourceRef, targetRef, assocTypeQName); 1065 } 1066 assoc = nodeDaoService.newNodeAssoc(sourceNode, targetNode, assocTypeQName); 1068 AssociationRef assocRef = assoc.getNodeAssocRef(); 1069 1070 invokeOnUpdateNode(sourceRef); 1072 invokeOnCreateAssociation(assocRef); 1073 1074 return assocRef; 1075 } 1076 1077 public void removeAssociation(NodeRef sourceRef, NodeRef targetRef, QName assocTypeQName) 1078 throws InvalidNodeRefException 1079 { 1080 invokeBeforeUpdateNode(sourceRef); 1082 1083 Node sourceNode = getNodeNotNull(sourceRef); 1084 Node targetNode = getNodeNotNull(targetRef); 1085 NodeAssoc assoc = nodeDaoService.getNodeAssoc(sourceNode, targetNode, assocTypeQName); 1087 AssociationRef assocRef = assoc.getNodeAssocRef(); 1088 nodeDaoService.deleteNodeAssoc(assoc); 1090 1091 invokeOnUpdateNode(sourceRef); 1093 invokeOnDeleteAssociation(assocRef); 1094 } 1095 1096 public List <AssociationRef> getTargetAssocs(NodeRef sourceRef, QNamePattern qnamePattern) 1097 throws InvalidNodeRefException 1098 { 1099 Node sourceNode = getNodeNotNull(sourceRef); 1100 Collection <NodeAssoc> assocs = sourceNode.getTargetNodeAssocs(); 1102 List <AssociationRef> nodeAssocRefs = new ArrayList <AssociationRef>(assocs.size()); 1103 for (NodeAssoc assoc : assocs) 1104 { 1105 if (!qnamePattern.isMatch(assoc.getTypeQName())) 1107 { 1108 continue; } 1110 nodeAssocRefs.add(assoc.getNodeAssocRef()); 1111 } 1112 return nodeAssocRefs; 1114 } 1115 1116 public List <AssociationRef> getSourceAssocs(NodeRef targetRef, QNamePattern qnamePattern) 1117 throws InvalidNodeRefException 1118 { 1119 Node sourceNode = getNodeNotNull(targetRef); 1120 Collection <NodeAssoc> assocs = sourceNode.getSourceNodeAssocs(); 1122 List <AssociationRef> nodeAssocRefs = new ArrayList <AssociationRef>(assocs.size()); 1123 for (NodeAssoc assoc : assocs) 1124 { 1125 if (!qnamePattern.isMatch(assoc.getTypeQName())) 1127 { 1128 continue; } 1130 nodeAssocRefs.add(assoc.getNodeAssocRef()); 1131 } 1132 return nodeAssocRefs; 1134 } 1135 1136 1152 private void prependPaths( 1153 final Node currentNode, 1154 final Path currentPath, 1155 Collection <Path> completedPaths, 1156 Stack <ChildAssoc> assocStack, 1157 boolean primaryOnly) 1158 throws CyclicChildRelationshipException 1159 { 1160 NodeRef currentNodeRef = currentNode.getNodeRef(); 1161 Collection <ChildAssoc> parentAssocs = currentNode.getParentAssocs(); 1163 boolean hasParents = parentAssocs.size() > 0; 1165 boolean isRoot = hasAspect(currentNodeRef, ContentModel.ASPECT_ROOT); 1167 boolean isStoreRoot = currentNode.getTypeQName().equals(ContentModel.TYPE_STOREROOT); 1168 1169 if (isRoot && !(primaryOnly && hasParents)) { 1172 ChildAssociationRef assocRef = new ChildAssociationRef( 1177 null, 1178 null, 1179 null, 1180 getRootNode(currentNode.getNodeRef().getStoreRef())); 1181 Path pathToSave = new Path(); 1183 Path.ChildAssocElement first = null; 1184 for (Path.Element element: currentPath) 1185 { 1186 if (first == null) 1187 { 1188 first = (Path.ChildAssocElement) element; 1189 } 1190 else 1191 { 1192 pathToSave.append(element); 1193 } 1194 } 1195 if (first != null) 1196 { 1197 ChildAssociationRef updateAssocRef = new ChildAssociationRef( 1201 isStoreRoot ? ContentModel.ASSOC_CHILDREN : first.getRef().getTypeQName(), 1202 getRootNode(currentNode.getNodeRef().getStoreRef()), 1203 first.getRef().getQName(), 1204 first.getRef().getChildRef()); 1205 Path.Element newFirst = new Path.ChildAssocElement(updateAssocRef); 1206 pathToSave.prepend(newFirst); 1207 } 1208 1209 Path.Element element = new Path.ChildAssocElement(assocRef); 1210 pathToSave.prepend(element); 1211 1212 completedPaths.add(pathToSave); 1214 } 1215 1216 if (parentAssocs.size() == 0 && !isRoot) 1217 { 1218 throw new RuntimeException ("Node without parents does not have root aspect: " + 1219 currentNodeRef); 1220 } 1221 for (ChildAssoc assoc : parentAssocs) 1223 { 1224 if (assocStack.contains(assoc)) 1226 { 1227 throw new CyclicChildRelationshipException( 1229 "Cyclic parent-child relationship detected: \n" + 1230 " current node: " + currentNode + "\n" + 1231 " current path: " + currentPath + "\n" + 1232 " next assoc: " + assoc, 1233 assoc); 1234 } 1235 if (primaryOnly && !assoc.getIsPrimary()) 1237 { 1238 continue; 1239 } 1240 NodeRef parentRef = assoc.getParent().getNodeRef(); 1242 QName qname = assoc.getQname(); 1243 NodeRef childRef = assoc.getChild().getNodeRef(); 1244 boolean isPrimary = assoc.getIsPrimary(); 1245 ChildAssociationRef assocRef = new ChildAssociationRef(assoc.getTypeQName(), parentRef, qname, childRef, isPrimary, -1); 1247 Path.Element element = new Path.ChildAssocElement(assocRef); 1249 Path path = new Path(); 1251 path.append(currentPath); 1252 path.prepend(element); 1254 Node parentNode = assoc.getParent(); 1256 1257 assocStack.push(assoc); 1259 prependPaths(parentNode, path, completedPaths, assocStack, primaryOnly); 1260 assocStack.pop(); 1261 } 1262 } 1264 1265 1269 public Path getPath(NodeRef nodeRef) throws InvalidNodeRefException 1270 { 1271 List <Path> paths = getPaths(nodeRef, true); if (paths.size() == 1) 1273 { 1274 return paths.get(0); } 1276 throw new RuntimeException ("Primary path count not checked"); } 1278 1279 1284 public List <Path> getPaths(NodeRef nodeRef, boolean primaryOnly) throws InvalidNodeRefException 1285 { 1286 Node node = getNodeNotNull(nodeRef); 1288 List <Path> paths = new ArrayList <Path>(primaryOnly ? 1 : 10); 1290 Path currentPath = new Path(); 1292 Stack <ChildAssoc> assocStack = new Stack <ChildAssoc>(); 1294 prependPaths(node, currentPath, paths, assocStack, primaryOnly); 1296 1297 if (primaryOnly && paths.size() != 1) 1299 { 1300 throw new RuntimeException ("Node has " + paths.size() + " primary paths: " + nodeRef); 1301 } 1302 1303 return paths; 1305 } 1306} 1307 | Popular Tags |