001/* 002 * Copyright 2010 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.plugins.repository.metadata.jcr; 017 018import java.util.ArrayList; 019import java.util.Collection; 020import java.util.Date; 021import java.util.GregorianCalendar; 022import java.util.HashSet; 023import java.util.List; 024import java.util.Locale; 025import java.util.Set; 026import java.util.regex.Pattern; 027 028import javax.jcr.Node; 029import javax.jcr.NodeIterator; 030import javax.jcr.PathNotFoundException; 031import javax.jcr.Property; 032import javax.jcr.PropertyIterator; 033import javax.jcr.PropertyType; 034import javax.jcr.RepositoryException; 035import javax.jcr.Value; 036import javax.jcr.lock.Lock; 037import javax.jcr.lock.LockManager; 038 039import org.apache.commons.lang3.LocaleUtils; 040 041import org.ametys.core.user.UserIdentity; 042import org.ametys.plugins.repository.AmetysObjectResolver; 043import org.ametys.plugins.repository.AmetysRepositoryException; 044import org.ametys.plugins.repository.ModifiableTraversableAmetysObject; 045import org.ametys.plugins.repository.RepositoryConstants; 046import org.ametys.plugins.repository.data.repositorydata.impl.JCRRepositoryData; 047import org.ametys.plugins.repository.jcr.NodeTypeHelper; 048import org.ametys.plugins.repository.metadata.CommentableCompositeMetadata; 049import org.ametys.plugins.repository.metadata.MetadataComment; 050import org.ametys.plugins.repository.metadata.ModifiableBinaryMetadata; 051import org.ametys.plugins.repository.metadata.ModifiableCompositeMetadata; 052import org.ametys.plugins.repository.metadata.ModifiableFile; 053import org.ametys.plugins.repository.metadata.ModifiableFolder; 054import org.ametys.plugins.repository.metadata.ModifiableResource; 055import org.ametys.plugins.repository.metadata.ModifiableRichText; 056import org.ametys.plugins.repository.metadata.MultilingualString; 057import org.ametys.plugins.repository.metadata.UnknownMetadataException; 058 059/** 060 * JCR implementation of a CompositeMetadata.<br> 061 * This implementation is based on a child node of the Node supporting the actual content. 062 * @deprecated Use {@link JCRRepositoryData} instead 063 */ 064@Deprecated 065public class JCRCompositeMetadata implements ModifiableCompositeMetadata, CommentableCompositeMetadata 066{ 067 /** Prefix for jcr properties and nodes names */ 068 public static final String METADATA_PREFIX = RepositoryConstants.NAMESPACE_PREFIX + ':'; 069 070 /** Comments metadata suffix */ 071 public static final String METADATA_COMMENTS_SUFFIX = "_comments"; 072 073 /** The JCR nodetype of object collection metadata. */ 074 public static final String OBJECT_COLLECTION_METADATA_NODETYPE = METADATA_PREFIX + "objectCollectionMetadata"; 075 076 /** The JCR nodetype of multilingual metadata. */ 077 public static final String MULTILINGUAL_STRING_METADATA_NODETYPE = METADATA_PREFIX + "multilingualString"; 078 079 private static Pattern __metadataNamePattern; 080 081 private Node _node; 082 private boolean _lockAlreadyChecked; 083 private AmetysObjectResolver _resolver; 084 085 /** 086 * Constructor 087 * @param metadataNode the Node supporting this composite metadata 088 * @param resolver The resolver, used to resolve object collections. 089 */ 090 public JCRCompositeMetadata(Node metadataNode, AmetysObjectResolver resolver) 091 { 092 _node = metadataNode; 093 _resolver = resolver; 094 } 095 096 /** 097 * Retrieves the underlying node. 098 * @return the underlying node. 099 */ 100 public Node getNode() 101 { 102 return _node; 103 } 104 105 public boolean hasMetadata(String metadataName) throws AmetysRepositoryException 106 { 107 try 108 { 109 // TODO filter sub-nodes by type (like in getMetadataNames). 110 return _node.hasProperty(METADATA_PREFIX + metadataName) || _node.hasNode(METADATA_PREFIX + metadataName); 111 } 112 catch (RepositoryException e) 113 { 114 throw new AmetysRepositoryException(e); 115 } 116 } 117 118 @Override 119 public void rename(String newName) throws AmetysRepositoryException 120 { 121 try 122 { 123 getNode().getSession().move(getNode().getPath(), getNode().getParent().getPath() + "/" + newName); 124 } 125 catch (RepositoryException e) 126 { 127 throw new AmetysRepositoryException(e); 128 } 129 } 130 131 public void removeMetadata(String metadataName) throws AmetysRepositoryException 132 { 133 try 134 { 135 _checkLock(); 136 String realMetadataName = METADATA_PREFIX + metadataName; 137 138 if (_node.hasProperty(realMetadataName)) 139 { 140 _node.getProperty(realMetadataName).remove(); 141 } 142 else if (_node.hasNode(realMetadataName)) 143 { 144 // Remove all existing nodes 145 NodeIterator it = _node.getNodes(realMetadataName); 146 while (it.hasNext()) 147 { 148 Node next = it.nextNode(); 149 next.remove(); 150 } 151 } 152 else 153 { 154 throw new UnknownMetadataException("No metadata for name: " + metadataName); 155 } 156 } 157 catch (RepositoryException e) 158 { 159 throw new AmetysRepositoryException("Unable to remove metadata " + metadataName, e); 160 } 161 } 162 163 @Override 164 public void copyTo(ModifiableCompositeMetadata metadata) throws AmetysRepositoryException 165 { 166 String[] metadataNames = getMetadataNames(); 167 for (String metadataName : metadataNames) 168 { 169 if (hasMetadata(metadataName)) 170 { 171 MetadataType type = getType(metadataName); 172 173 boolean multiple = isMultiple(metadataName); 174 switch (type) 175 { 176 case COMPOSITE: 177 ModifiableCompositeMetadata compositeMetadata = metadata.getCompositeMetadata(metadataName, true); 178 getCompositeMetadata(metadataName).copyTo(compositeMetadata); 179 break; 180 case USER: 181 if (multiple) 182 { 183 metadata.setMetadata(metadataName, getUserArray(metadataName)); 184 } 185 else 186 { 187 metadata.setMetadata(metadataName, getUser(metadataName)); 188 } 189 break; 190 case BOOLEAN: 191 if (multiple) 192 { 193 metadata.setMetadata(metadataName, getBooleanArray(metadataName)); 194 } 195 else 196 { 197 metadata.setMetadata(metadataName, getBoolean(metadataName)); 198 } 199 break; 200 case DATE: 201 if (multiple) 202 { 203 metadata.setMetadata(metadataName, getDateArray(metadataName)); 204 } 205 else 206 { 207 metadata.setMetadata(metadataName, getDate(metadataName)); 208 } 209 break; 210 case DOUBLE: 211 if (multiple) 212 { 213 metadata.setMetadata(metadataName, getDoubleArray(metadataName)); 214 } 215 else 216 { 217 metadata.setMetadata(metadataName, getDouble(metadataName)); 218 } 219 break; 220 case LONG: 221 if (multiple) 222 { 223 metadata.setMetadata(metadataName, getLongArray(metadataName)); 224 } 225 else 226 { 227 metadata.setMetadata(metadataName, getLong(metadataName)); 228 } 229 break; 230 case BINARY: 231 ModifiableBinaryMetadata binaryMetadata = metadata.getBinaryMetadata(metadataName, true); 232 ModifiableBinaryMetadata srcBinary = getBinaryMetadata(metadataName); 233 234 binaryMetadata.setFilename(srcBinary.getFilename()); 235 binaryMetadata.setMimeType(srcBinary.getMimeType()); 236 binaryMetadata.setLastModified(srcBinary.getLastModified()); 237 binaryMetadata.setEncoding(srcBinary.getEncoding()); 238 binaryMetadata.setInputStream(srcBinary.getInputStream()); 239 break; 240 case RICHTEXT: 241 ModifiableRichText richText = metadata.getRichText(metadataName, true); 242 ModifiableRichText srcRichText = getRichText(metadataName); 243 244 richText.setInputStream(srcRichText.getInputStream()); 245 richText.setEncoding(srcRichText.getEncoding()); 246 richText.setLastModified(srcRichText.getLastModified()); 247 richText.setMimeType(srcRichText.getMimeType()); 248 249 // Copy additional data 250 _copyDataFolder (srcRichText.getAdditionalDataFolder(), richText.getAdditionalDataFolder()); 251 break; 252 case MULTILINGUAL_STRING: 253 MultilingualString srcMultilingualString = getMultilingualString(metadataName); 254 metadata.setMetadata(metadataName, srcMultilingualString); 255 break; 256 default: 257 if (multiple) 258 { 259 metadata.setMetadata(metadataName, getStringArray(metadataName)); 260 } 261 else 262 { 263 metadata.setMetadata(metadataName, getString(metadataName)); 264 } 265 break; 266 } 267 } 268 } 269 } 270 271 private void _copyDataFolder (ModifiableFolder srcDataFolder, ModifiableFolder targetDataFolder) 272 { 273 // Copy folders 274 Collection<ModifiableFolder> folders = srcDataFolder.getFolders(); 275 for (ModifiableFolder srcSubfolder : folders) 276 { 277 ModifiableFolder targetSubFolder = targetDataFolder.addFolder(srcSubfolder.getName()); 278 _copyDataFolder (srcSubfolder, targetSubFolder); 279 } 280 281 // Copy files 282 Collection<ModifiableFile> files = srcDataFolder.getFiles(); 283 for (ModifiableFile srcFile : files) 284 { 285 _copyFile (srcFile, targetDataFolder); 286 } 287 } 288 289 private void _copyFile (ModifiableFile srcFile, ModifiableFolder targetDataFolder) 290 { 291 ModifiableResource srcResource = srcFile.getResource(); 292 293 ModifiableFile targetFile = targetDataFolder.addFile(srcFile.getName()); 294 ModifiableResource targetResource = targetFile.getResource(); 295 296 targetResource.setLastModified(srcResource.getLastModified()); 297 targetResource.setMimeType(srcResource.getMimeType()); 298 targetResource.setEncoding(srcResource.getEncoding()); 299 targetResource.setInputStream(srcResource.getInputStream()); 300 } 301 302 public MetadataType getType(String metadataName) throws AmetysRepositoryException 303 { 304 try 305 { 306 String realMetadataName = METADATA_PREFIX + metadataName; 307 308 if (_node.hasNode(realMetadataName)) 309 { 310 Node node = _node.getNode(realMetadataName); 311 String type = node.getPrimaryNodeType().getName(); 312 if ("nt:frozenNode".equals(_node.getPrimaryNodeType().getName())) 313 { 314 // on version history 315 type = node.getProperty("jcr:frozenPrimaryType").getString(); 316 } 317 318 if (type.equals(OBJECT_COLLECTION_METADATA_NODETYPE)) 319 { 320 return MetadataType.OBJECT_COLLECTION; 321 } 322 else if (type.equals(RepositoryConstants.BINARY_NODETYPE)) 323 { 324 return MetadataType.BINARY; 325 } 326 else if (type.equals(METADATA_PREFIX + "richText")) 327 { 328 return MetadataType.RICHTEXT; 329 } 330 else if (type.equals(METADATA_PREFIX + "user")) 331 { 332 return MetadataType.USER; 333 } 334 else if (type.equals(MULTILINGUAL_STRING_METADATA_NODETYPE)) 335 { 336 return MetadataType.MULTILINGUAL_STRING; 337 } 338 else 339 { 340 return MetadataType.COMPOSITE; 341 } 342 } 343 344 if (_node.hasProperty(realMetadataName)) 345 { 346 Property property = _node.getProperty(realMetadataName); 347 int type = property.getType(); 348 349 switch (type) 350 { 351 case PropertyType.STRING: 352 return MetadataType.STRING; 353 case PropertyType.BOOLEAN: 354 return MetadataType.BOOLEAN; 355 case PropertyType.DATE: 356 return MetadataType.DATE; 357 case PropertyType.DOUBLE: 358 return MetadataType.DOUBLE; 359 case PropertyType.LONG: 360 return MetadataType.LONG; 361 default: 362 throw new AmetysRepositoryException("Unhandled JCR property type : " + PropertyType.nameFromValue(type)); 363 } 364 } 365 366 throw new UnknownMetadataException("No metadata for name: " + metadataName); 367 } 368 catch (RepositoryException e) 369 { 370 throw new AmetysRepositoryException("Unable to get property type", e); 371 } 372 } 373 374 public String getString(String metadataName) 375 { 376 return _getString(metadataName, null, true); 377 } 378 379 @Override 380 public String getString(String metadataName, String defaultValue) 381 { 382 return _getString(metadataName, defaultValue, false); 383 } 384 385 private String _getString(String metadataName, String defaultValue, boolean failIfNotExist) 386 { 387 try 388 { 389 Property property = _node.getProperty(METADATA_PREFIX + metadataName); 390 391 if (property.getDefinition().isMultiple()) 392 { 393 Value[] values = property.getValues(); 394 395 if (values.length > 0) 396 { 397 return values[0].getString(); 398 } 399 else 400 { 401 throw new AmetysRepositoryException("Cannot get a String from an empty array"); 402 } 403 } 404 405 return property.getString(); 406 } 407 catch (PathNotFoundException e) 408 { 409 if (failIfNotExist) 410 { 411 throw new UnknownMetadataException("Unknown metadata " + METADATA_PREFIX + metadataName + " of " + _node, e); 412 } 413 else 414 { 415 return defaultValue; 416 } 417 } 418 catch (RepositoryException e) 419 { 420 throw new AmetysRepositoryException("Unable to get String property", e); 421 } 422 } 423 424 public String[] getStringArray(String metadataName) throws AmetysRepositoryException 425 { 426 return _getStringArray(metadataName, null, true); 427 } 428 429 public String[] getStringArray(String metadataName, String[] defaultValues) 430 { 431 return _getStringArray(metadataName, defaultValues, false); 432 } 433 434 private String[] _getStringArray(String metadataName, String[] defaultValues, boolean failIfNotExist) 435 { 436 try 437 { 438 Property property = _node.getProperty(METADATA_PREFIX + metadataName); 439 440 if (property.getDefinition().isMultiple()) 441 { 442 Value[] values = property.getValues(); 443 444 String[] results = new String[values.length]; 445 for (int i = 0; i < values.length; i++) 446 { 447 Value value = values[i]; 448 results[i] = value.getString(); 449 } 450 451 return results; 452 } 453 454 Value value = property.getValue(); 455 return new String[] {value.getString()}; 456 } 457 catch (PathNotFoundException e) 458 { 459 if (failIfNotExist) 460 { 461 throw new UnknownMetadataException("Unknown metadata " + METADATA_PREFIX + metadataName + " of " + _node, e); 462 } 463 else 464 { 465 return defaultValues; 466 } 467 } 468 catch (RepositoryException e) 469 { 470 throw new AmetysRepositoryException("Unable to get String array property", e); 471 } 472 } 473 474 @Override 475 public String getLocalizedString(String metadataName, Locale locale) throws UnknownMetadataException, AmetysRepositoryException 476 { 477 return _getString(metadataName, locale, null, true); 478 } 479 480 @Override 481 public String getLocalizedString(String metadataName, Locale locale, String defaultValue) throws AmetysRepositoryException 482 { 483 return _getString(metadataName, locale, defaultValue, false); 484 } 485 486 @Override 487 public MultilingualString getMultilingualString(String metadataName) throws AmetysRepositoryException 488 { 489 try 490 { 491 if (_node.hasNode(METADATA_PREFIX + metadataName)) 492 { 493 Node node = _node.getNode(METADATA_PREFIX + metadataName); 494 495 MultilingualString values = new MultilingualString(); 496 497 PropertyIterator properties = node.getProperties(METADATA_PREFIX + "*"); 498 while (properties.hasNext()) 499 { 500 Property property = properties.nextProperty(); 501 String name = property.getName().substring(METADATA_PREFIX.length()); 502 503 try 504 { 505 Locale locale = LocaleUtils.toLocale(name); 506 values.add(locale, property.getString()); 507 } 508 catch (IllegalArgumentException e) 509 { 510 // Property is not a valid locale, ignore it. 511 } 512 } 513 514 return values; 515 } 516 else 517 { 518 throw new UnknownMetadataException("No multilingual String named " + metadataName); 519 } 520 } 521 catch (RepositoryException e) 522 { 523 throw new AmetysRepositoryException("Unable to get multilingual String property", e); 524 } 525 } 526 527 private String _getString(String metadataName, Locale locale, String defaultValue, boolean failIfNotExist) 528 { 529 try 530 { 531 Node node = _node.getNode(METADATA_PREFIX + metadataName); 532 533 Property property = node.getProperty(METADATA_PREFIX + locale.toString()); 534 return property.getString(); 535 } 536 catch (PathNotFoundException e) 537 { 538 if (failIfNotExist) 539 { 540 throw new UnknownMetadataException("Unknown metadata " + METADATA_PREFIX + metadataName + " of " + _node, e); 541 } 542 else 543 { 544 return defaultValue; 545 } 546 } 547 catch (RepositoryException e) 548 { 549 throw new AmetysRepositoryException("Unable to get String property", e); 550 } 551 } 552 553 public boolean getBoolean(String metadataName) throws UnknownMetadataException, AmetysRepositoryException 554 { 555 return _getBoolean(metadataName, null, true); 556 } 557 558 public boolean getBoolean(String metadataName, boolean defaultValue) throws AmetysRepositoryException 559 { 560 return _getBoolean(metadataName, defaultValue, false); 561 } 562 563 private boolean _getBoolean(String metadataName, Boolean defaultValue, boolean failIfNotExist) 564 { 565 try 566 { 567 Property property = _node.getProperty(METADATA_PREFIX + metadataName); 568 569 if (property.getDefinition().isMultiple()) 570 { 571 Value[] values = property.getValues(); 572 573 if (values.length > 0) 574 { 575 return values[0].getBoolean(); 576 } 577 else 578 { 579 throw new AmetysRepositoryException("Cannot get a boolean from an empty array"); 580 } 581 } 582 583 return property.getBoolean(); 584 } 585 catch (PathNotFoundException e) 586 { 587 if (failIfNotExist) 588 { 589 throw new UnknownMetadataException("Unknown metadata " + METADATA_PREFIX + metadataName + " of " + _node, e); 590 } 591 else 592 { 593 return defaultValue; 594 } 595 } 596 catch (RepositoryException e) 597 { 598 throw new AmetysRepositoryException("Unable to get boolean property", e); 599 } 600 } 601 602 public boolean[] getBooleanArray(String metadataName) throws AmetysRepositoryException 603 { 604 return _getBooleanArray(metadataName, null, true); 605 } 606 607 public boolean[] getBooleanArray(String metadataName, boolean[] defaultValues) 608 { 609 return _getBooleanArray(metadataName, defaultValues, false); 610 } 611 612 private boolean[] _getBooleanArray(String metadataName, boolean[] defaultValues, boolean failIfNotExist) 613 { 614 try 615 { 616 Property property = _node.getProperty(METADATA_PREFIX + metadataName); 617 618 if (property.getDefinition().isMultiple()) 619 { 620 Value[] values = property.getValues(); 621 622 boolean[] results = new boolean[values.length]; 623 for (int i = 0; i < values.length; i++) 624 { 625 Value value = values[i]; 626 results[i] = value.getBoolean(); 627 } 628 629 return results; 630 } 631 632 Value value = property.getValue(); 633 return new boolean[] {value.getBoolean()}; 634 } 635 catch (PathNotFoundException e) 636 { 637 if (failIfNotExist) 638 { 639 throw new UnknownMetadataException("Unknown metadata " + METADATA_PREFIX + metadataName + " of " + _node, e); 640 } 641 else 642 { 643 return defaultValues; 644 } 645 } 646 catch (RepositoryException e) 647 { 648 throw new AmetysRepositoryException("Unable to get boolean array property", e); 649 } 650 } 651 652 public Date getDate(String metadataName) throws AmetysRepositoryException 653 { 654 return _getDate(metadataName, null, true); 655 } 656 657 public Date getDate(String metadataName, Date defaultValue) throws AmetysRepositoryException 658 { 659 return _getDate(metadataName, defaultValue, false); 660 } 661 662 private Date _getDate(String metadataName, Date defaultValue, boolean failIfNotExist) 663 { 664 try 665 { 666 Property property = _node.getProperty(METADATA_PREFIX + metadataName); 667 668 if (property.getDefinition().isMultiple()) 669 { 670 Value[] values = property.getValues(); 671 672 if (values.length > 0) 673 { 674 return values[0].getDate().getTime(); 675 } 676 else 677 { 678 throw new AmetysRepositoryException("Cannot get a date from an empty array"); 679 } 680 } 681 682 return property.getDate().getTime(); 683 } 684 catch (PathNotFoundException e) 685 { 686 if (failIfNotExist) 687 { 688 throw new UnknownMetadataException("Unknown metadata " + METADATA_PREFIX + metadataName + " of " + _node, e); 689 } 690 else 691 { 692 return defaultValue; 693 } 694 } 695 catch (RepositoryException e) 696 { 697 throw new AmetysRepositoryException("Unable to get date property", e); 698 } 699 } 700 701 public Date[] getDateArray(String metadataName) throws AmetysRepositoryException 702 { 703 return _getDateArray(metadataName, null, true); 704 } 705 706 public Date[] getDateArray(String metadataName, Date[] defaultValues) 707 { 708 return _getDateArray(metadataName, defaultValues, false); 709 } 710 711 private Date[] _getDateArray(String metadataName, Date[] defaultValues, boolean failIfNotExist) 712 { 713 try 714 { 715 Property property = _node.getProperty(METADATA_PREFIX + metadataName); 716 717 if (property.getDefinition().isMultiple()) 718 { 719 Value[] values = property.getValues(); 720 721 Date[] results = new Date[values.length]; 722 for (int i = 0; i < values.length; i++) 723 { 724 Value value = values[i]; 725 results[i] = value.getDate().getTime(); 726 } 727 728 return results; 729 } 730 731 Value value = property.getValue(); 732 return new Date[] {value.getDate().getTime()}; 733 } 734 catch (PathNotFoundException e) 735 { 736 if (failIfNotExist) 737 { 738 throw new UnknownMetadataException("Unknown metadata " + METADATA_PREFIX + metadataName + " of " + _node, e); 739 } 740 else 741 { 742 return defaultValues; 743 } 744 } 745 catch (RepositoryException e) 746 { 747 throw new AmetysRepositoryException("Unable to get date array property", e); 748 } 749 } 750 751 public long getLong(String metadataName) throws AmetysRepositoryException 752 { 753 return _getLong(metadataName, null, true); 754 } 755 756 public long getLong(String metadataName, long defaultValue) throws AmetysRepositoryException 757 { 758 return _getLong(metadataName, defaultValue, false); 759 } 760 761 private long _getLong(String metadataName, Long defaultValue, boolean failIfNotExist) 762 { 763 try 764 { 765 Property property = _node.getProperty(METADATA_PREFIX + metadataName); 766 767 if (property.getDefinition().isMultiple()) 768 { 769 Value[] values = property.getValues(); 770 771 if (values.length > 0) 772 { 773 return values[0].getLong(); 774 } 775 else 776 { 777 throw new AmetysRepositoryException("Cannot get a long from an empty array"); 778 } 779 } 780 781 return property.getLong(); 782 } 783 catch (PathNotFoundException e) 784 { 785 if (failIfNotExist) 786 { 787 throw new UnknownMetadataException("Unknown metadata " + METADATA_PREFIX + metadataName + " of " + _node, e); 788 } 789 else 790 { 791 return defaultValue; 792 } 793 } 794 catch (RepositoryException e) 795 { 796 throw new AmetysRepositoryException("Unable to get long property", e); 797 } 798 } 799 800 public long[] getLongArray(String metadataName) throws AmetysRepositoryException 801 { 802 return _getLongArray(metadataName, null, true); 803 } 804 805 public long[] getLongArray(String metadataName, long[] defaultValues) 806 { 807 return _getLongArray(metadataName, defaultValues, false); 808 } 809 810 private long[] _getLongArray(String metadataName, long[] defaultValues, boolean failIfNotExist) 811 { 812 try 813 { 814 Property property = _node.getProperty(METADATA_PREFIX + metadataName); 815 816 if (property.getDefinition().isMultiple()) 817 { 818 Value[] values = property.getValues(); 819 820 long[] results = new long[values.length]; 821 for (int i = 0; i < values.length; i++) 822 { 823 Value value = values[i]; 824 results[i] = value.getLong(); 825 } 826 827 return results; 828 } 829 830 Value value = property.getValue(); 831 return new long[] {value.getLong()}; 832 } 833 catch (PathNotFoundException e) 834 { 835 if (failIfNotExist) 836 { 837 throw new UnknownMetadataException("Unknown metadata " + METADATA_PREFIX + metadataName + " of " + _node, e); 838 } 839 else 840 { 841 return defaultValues; 842 } 843 } 844 catch (RepositoryException e) 845 { 846 throw new AmetysRepositoryException("Unable to get long array property", e); 847 } 848 } 849 850 public double getDouble(String metadataName) throws AmetysRepositoryException 851 { 852 return _getDouble(metadataName, null, true); 853 } 854 855 public double getDouble(String metadataName, double defaultValue) throws AmetysRepositoryException 856 { 857 return _getDouble(metadataName, defaultValue, false); 858 } 859 860 private double _getDouble(String metadataName, Double defaultValue, boolean failIfNotExist) 861 { 862 try 863 { 864 Property property = _node.getProperty(METADATA_PREFIX + metadataName); 865 866 if (property.getDefinition().isMultiple()) 867 { 868 Value[] values = property.getValues(); 869 870 if (values.length > 0) 871 { 872 return values[0].getDouble(); 873 } 874 else 875 { 876 throw new AmetysRepositoryException("Cannot get a double from an empty array"); 877 } 878 } 879 880 return property.getDouble(); 881 } 882 catch (PathNotFoundException e) 883 { 884 if (failIfNotExist) 885 { 886 throw new UnknownMetadataException("Unknown metadata " + METADATA_PREFIX + metadataName + " of " + _node, e); 887 } 888 else 889 { 890 return defaultValue; 891 } 892 } 893 catch (RepositoryException e) 894 { 895 throw new AmetysRepositoryException("Unable to get double property", e); 896 } 897 } 898 899 public double[] getDoubleArray(String metadataName) throws AmetysRepositoryException 900 { 901 return _getDoubleArray(metadataName, null, true); 902 } 903 904 public double[] getDoubleArray(String metadataName, double[] defaultValues) 905 { 906 return _getDoubleArray(metadataName, defaultValues, false); 907 } 908 909 private double[] _getDoubleArray(String metadataName, double[] defaultValues, boolean failIfNotExist) 910 { 911 try 912 { 913 Property property = _node.getProperty(METADATA_PREFIX + metadataName); 914 915 if (property.getDefinition().isMultiple()) 916 { 917 Value[] values = property.getValues(); 918 919 double[] results = new double[values.length]; 920 for (int i = 0; i < values.length; i++) 921 { 922 Value value = values[i]; 923 results[i] = value.getDouble(); 924 } 925 926 return results; 927 } 928 929 Value value = property.getValue(); 930 return new double[] {value.getDouble()}; 931 } 932 catch (PathNotFoundException e) 933 { 934 if (failIfNotExist) 935 { 936 throw new UnknownMetadataException("Unknown metadata " + METADATA_PREFIX + metadataName + " of " + _node, e); 937 } 938 else 939 { 940 return defaultValues; 941 } 942 } 943 catch (RepositoryException e) 944 { 945 throw new AmetysRepositoryException("Unable to get double array property", e); 946 } 947 } 948 949 public UserIdentity getUser(String metadataName) throws AmetysRepositoryException 950 { 951 return _getUser(metadataName, null, true); 952 } 953 954 public UserIdentity getUser(String metadataName, UserIdentity defaultValue) throws AmetysRepositoryException 955 { 956 return _getUser(metadataName, defaultValue, false); 957 } 958 959 private UserIdentity _getUser(String metadataName, UserIdentity defaultValue, boolean failIfNotExist) throws AmetysRepositoryException 960 { 961 try 962 { 963 Node userNode = _node.getNode(METADATA_PREFIX + metadataName); 964 return new UserIdentity(userNode.getProperty("ametys:login").getString(), userNode.getProperty("ametys:population").getString()); 965 } 966 catch (PathNotFoundException e) 967 { 968 if (failIfNotExist) 969 { 970 throw new UnknownMetadataException("Unknown metadata " + METADATA_PREFIX + metadataName + " of " + _node, e); 971 } 972 else 973 { 974 return defaultValue; 975 } 976 } 977 catch (RepositoryException e) 978 { 979 throw new AmetysRepositoryException("Unable to get User metadata", e); 980 } 981 } 982 983 @Override 984 public UserIdentity[] getUserArray(String metadataName) throws AmetysRepositoryException 985 { 986 return _getUserArray(metadataName, null, true); 987 } 988 989 @Override 990 public UserIdentity[] getUserArray(String metadataName, UserIdentity[] defaultValues) throws AmetysRepositoryException 991 { 992 return _getUserArray(metadataName, defaultValues, false); 993 } 994 995 private UserIdentity[] _getUserArray(String metadataName, UserIdentity[] defaultValues, boolean failIfNotExist) throws AmetysRepositoryException 996 { 997 try 998 { 999 if (_node.hasNode(METADATA_PREFIX + metadataName)) 1000 { 1001 List<UserIdentity> results = new ArrayList<>(); 1002 1003 NodeIterator it = _node.getNodes(METADATA_PREFIX + metadataName); 1004 while (it.hasNext()) 1005 { 1006 Node next = (Node) it.next(); 1007 results.add(new UserIdentity(next.getProperty("ametys:login").getString(), next.getProperty("ametys:population").getString())); 1008 } 1009 1010 return results.toArray(new UserIdentity[results.size()]); 1011 } 1012 else if (failIfNotExist) 1013 { 1014 throw new UnknownMetadataException("The metadata '" + metadataName + "' does not exist"); 1015 } 1016 else 1017 { 1018 return defaultValues; 1019 } 1020 } 1021 catch (RepositoryException e) 1022 { 1023 throw new AmetysRepositoryException("Unable to get User array metadata", e); 1024 } 1025 } 1026 1027 @Override 1028 public void setMetadata(String metadataName, String value) throws AmetysRepositoryException 1029 { 1030 if (value == null) 1031 { 1032 throw new NullPointerException("metadata value cannot be null"); 1033 } 1034 1035 _checkMetadataName(metadataName); 1036 1037 try 1038 { 1039 _checkLock(); 1040 _node.setProperty(METADATA_PREFIX + metadataName, value); 1041 } 1042 catch (RepositoryException e) 1043 { 1044 throw new AmetysRepositoryException("Unable to set property", e); 1045 } 1046 } 1047 1048 @Override 1049 public void setMetadata(String metadataName, String[] value) throws AmetysRepositoryException 1050 { 1051 if (value == null) 1052 { 1053 throw new NullPointerException("metadata value cannot be null"); 1054 } 1055 1056 _checkMetadataName(metadataName); 1057 1058 try 1059 { 1060 _checkLock(); 1061 _node.setProperty(METADATA_PREFIX + metadataName, value); 1062 } 1063 catch (RepositoryException e) 1064 { 1065 throw new AmetysRepositoryException("Unable to set property", e); 1066 } 1067 } 1068 1069 @Override 1070 public void setMetadata(String metadataName, String value, Locale locale) throws AmetysRepositoryException 1071 { 1072 if (value == null) 1073 { 1074 throw new NullPointerException("metadata value cannot be null"); 1075 } 1076 1077 _checkMetadataName(metadataName); 1078 1079 try 1080 { 1081 _checkLock(); 1082 1083 Node node = null; 1084 if (_node.hasNode(METADATA_PREFIX + metadataName)) 1085 { 1086 node = _node.getNode(METADATA_PREFIX + metadataName); 1087 } 1088 else 1089 { 1090 node = _node.addNode(METADATA_PREFIX + metadataName, MULTILINGUAL_STRING_METADATA_NODETYPE); 1091 } 1092 1093 node.setProperty(METADATA_PREFIX + locale.toString(), value); 1094 } 1095 catch (RepositoryException e) 1096 { 1097 throw new AmetysRepositoryException("Unable to set property", e); 1098 } 1099 } 1100 1101 @Override 1102 public void setMetadata(String metadataName, Date value) throws AmetysRepositoryException 1103 { 1104 if (value == null) 1105 { 1106 throw new NullPointerException("metadata value cannot be null"); 1107 } 1108 1109 GregorianCalendar calendar = new GregorianCalendar(); 1110 calendar.setTime(value); 1111 1112 _checkMetadataName(metadataName); 1113 1114 try 1115 { 1116 _checkLock(); 1117 _node.setProperty(METADATA_PREFIX + metadataName, calendar); 1118 } 1119 catch (RepositoryException e) 1120 { 1121 throw new AmetysRepositoryException("Unable to set property", e); 1122 } 1123 } 1124 1125 @Override 1126 public void setMetadata(String metadataName, Date[] values) throws AmetysRepositoryException 1127 { 1128 if (values == null) 1129 { 1130 throw new NullPointerException("metadata value cannot be null"); 1131 } 1132 1133 _checkMetadataName(metadataName); 1134 1135 try 1136 { 1137 _checkLock(); 1138 Value[] jcrValues = new Value[values.length]; 1139 1140 for (int i = 0; i < values.length; i++) 1141 { 1142 Date value = values[i]; 1143 1144 GregorianCalendar calendar = new GregorianCalendar(); 1145 calendar.setTime(value); 1146 1147 jcrValues[i] = _node.getSession().getValueFactory().createValue(calendar); 1148 } 1149 1150 _node.setProperty(METADATA_PREFIX + metadataName, jcrValues); 1151 } 1152 catch (RepositoryException e) 1153 { 1154 throw new AmetysRepositoryException("Unable to set property", e); 1155 } 1156 } 1157 1158 @Override 1159 public void setMetadata(String metadataName, long value) throws AmetysRepositoryException 1160 { 1161 _checkMetadataName(metadataName); 1162 1163 try 1164 { 1165 _checkLock(); 1166 _node.setProperty(METADATA_PREFIX + metadataName, value); 1167 } 1168 catch (RepositoryException e) 1169 { 1170 throw new AmetysRepositoryException("Unable to set property", e); 1171 } 1172 } 1173 1174 @Override 1175 public void setMetadata(String metadataName, double value) throws AmetysRepositoryException 1176 { 1177 _checkMetadataName(metadataName); 1178 1179 try 1180 { 1181 _checkLock(); 1182 _node.setProperty(METADATA_PREFIX + metadataName, value); 1183 } 1184 catch (RepositoryException e) 1185 { 1186 throw new AmetysRepositoryException("Unable to set property", e); 1187 } 1188 } 1189 1190 @Override 1191 public void setMetadata(String metadataName, long[] values) throws AmetysRepositoryException 1192 { 1193 if (values == null) 1194 { 1195 throw new NullPointerException("metadata value cannot be null"); 1196 } 1197 1198 _checkMetadataName(metadataName); 1199 1200 try 1201 { 1202 _checkLock(); 1203 Value[] jcrValues = new Value[values.length]; 1204 1205 for (int i = 0; i < values.length; i++) 1206 { 1207 long value = values[i]; 1208 jcrValues[i] = _node.getSession().getValueFactory().createValue(value); 1209 } 1210 1211 _node.setProperty(METADATA_PREFIX + metadataName, jcrValues); 1212 } 1213 catch (RepositoryException e) 1214 { 1215 throw new AmetysRepositoryException("Unable to set property", e); 1216 } 1217 } 1218 1219 @Override 1220 public void setMetadata(String metadataName, double[] values) throws AmetysRepositoryException 1221 { 1222 if (values == null) 1223 { 1224 throw new NullPointerException("metadata value cannot be null"); 1225 } 1226 1227 _checkMetadataName(metadataName); 1228 1229 try 1230 { 1231 _checkLock(); 1232 Value[] jcrValues = new Value[values.length]; 1233 1234 for (int i = 0; i < values.length; i++) 1235 { 1236 double value = values[i]; 1237 jcrValues[i] = _node.getSession().getValueFactory().createValue(value); 1238 } 1239 1240 _node.setProperty(METADATA_PREFIX + metadataName, jcrValues); 1241 } 1242 catch (RepositoryException e) 1243 { 1244 throw new AmetysRepositoryException("Unable to set property", e); 1245 } 1246 } 1247 1248 @Override 1249 public void setMetadata(String metadataName, boolean value) throws AmetysRepositoryException 1250 { 1251 _checkMetadataName(metadataName); 1252 1253 try 1254 { 1255 _checkLock(); 1256 _node.setProperty(METADATA_PREFIX + metadataName, value); 1257 } 1258 catch (RepositoryException e) 1259 { 1260 throw new AmetysRepositoryException("Unable to set property", e); 1261 } 1262 } 1263 1264 @Override 1265 public void setMetadata(String metadataName, boolean[] values) throws AmetysRepositoryException 1266 { 1267 if (values == null) 1268 { 1269 throw new NullPointerException("metadata value cannot be null"); 1270 } 1271 1272 _checkMetadataName(metadataName); 1273 1274 try 1275 { 1276 _checkLock(); 1277 Value[] jcrValues = new Value[values.length]; 1278 1279 for (int i = 0; i < values.length; i++) 1280 { 1281 boolean value = values[i]; 1282 jcrValues[i] = _node.getSession().getValueFactory().createValue(value); 1283 } 1284 1285 _node.setProperty(METADATA_PREFIX + metadataName, jcrValues); 1286 } 1287 catch (RepositoryException e) 1288 { 1289 throw new AmetysRepositoryException("Unable to set property", e); 1290 } 1291 } 1292 1293 @Override 1294 public void setMetadata(String metadataName, UserIdentity value) throws AmetysRepositoryException 1295 { 1296 _checkMetadataName(metadataName); 1297 1298 try 1299 { 1300 _checkLock(); 1301 1302 Node userNode = null; 1303 if (_node.hasNode(METADATA_PREFIX + metadataName)) 1304 { 1305 userNode = _node.getNode(METADATA_PREFIX + metadataName); 1306 } 1307 else 1308 { 1309 userNode = _node.addNode(METADATA_PREFIX + metadataName, RepositoryConstants.USER_NODETYPE); 1310 } 1311 userNode.setProperty(METADATA_PREFIX + "login", value.getLogin()); 1312 userNode.setProperty(METADATA_PREFIX + "population", value.getPopulationId()); 1313 } 1314 catch (RepositoryException e) 1315 { 1316 throw new AmetysRepositoryException("Unable to set property", e); 1317 } 1318 } 1319 1320 @Override 1321 public void setMetadata(String metadataName, UserIdentity[] values) throws AmetysRepositoryException 1322 { 1323 if (values == null) 1324 { 1325 throw new NullPointerException("metadata value cannot be null"); 1326 } 1327 1328 _checkMetadataName(metadataName); 1329 1330 try 1331 { 1332 _checkLock(); 1333 1334 NodeIterator it = _node.getNodes(METADATA_PREFIX + metadataName); 1335 while (it.hasNext()) 1336 { 1337 Node next = (Node) it.next(); 1338 next.remove(); 1339 } 1340 1341 for (UserIdentity value : values) 1342 { 1343 Node userNode = _node.addNode(METADATA_PREFIX + metadataName, RepositoryConstants.USER_NODETYPE); 1344 userNode.setProperty(METADATA_PREFIX + "login", value.getLogin()); 1345 userNode.setProperty(METADATA_PREFIX + "population", value.getPopulationId()); 1346 } 1347 } 1348 catch (RepositoryException e) 1349 { 1350 throw new AmetysRepositoryException("Unable to set property", e); 1351 } 1352 } 1353 1354 @Override 1355 public void setMetadata(String metadataName, MultilingualString value) throws AmetysRepositoryException 1356 { 1357 if (value == null) 1358 { 1359 throw new NullPointerException("metadata value cannot be null"); 1360 } 1361 1362 _checkMetadataName(metadataName); 1363 1364 try 1365 { 1366 _checkLock(); 1367 1368 NodeIterator it = _node.getNodes(METADATA_PREFIX + metadataName); 1369 while (it.hasNext()) 1370 { 1371 Node next = (Node) it.next(); 1372 next.remove(); 1373 } 1374 1375 Node node = null; 1376 if (_node.hasNode(METADATA_PREFIX + metadataName)) 1377 { 1378 node = _node.getNode(METADATA_PREFIX + metadataName); 1379 } 1380 else 1381 { 1382 node = _node.addNode(METADATA_PREFIX + metadataName, MULTILINGUAL_STRING_METADATA_NODETYPE); 1383 } 1384 1385 for (Locale locale : value.getLocales()) 1386 { 1387 node.setProperty(METADATA_PREFIX + locale.toString(), value.getValue(locale)); 1388 } 1389 } 1390 catch (RepositoryException e) 1391 { 1392 throw new AmetysRepositoryException("Unable to set property", e); 1393 } 1394 } 1395 1396 public String[] getMetadataNames() throws AmetysRepositoryException 1397 { 1398 try 1399 { 1400 PropertyIterator itProp = _node.getProperties(METADATA_PREFIX + "*"); 1401 NodeIterator itNode = _node.getNodes(METADATA_PREFIX + "*"); 1402 1403 Set<String> names = new HashSet<>(); 1404 1405 while (itProp.hasNext()) 1406 { 1407 Property property = itProp.nextProperty(); 1408 names.add(property.getName().substring(METADATA_PREFIX.length())); 1409 } 1410 1411 while (itNode.hasNext()) 1412 { 1413 Node node = itNode.nextNode(); 1414 1415 // Filtering out AmetysObjects: they're not metadata (except object collections and users). 1416 if (!NodeTypeHelper.isNodeType(node, AmetysObjectResolver.OBJECT_TYPE) || NodeTypeHelper.isNodeType(node, OBJECT_COLLECTION_METADATA_NODETYPE) || NodeTypeHelper.isNodeType(node, RepositoryConstants.USER_NODETYPE) || NodeTypeHelper.isNodeType(node, MULTILINGUAL_STRING_METADATA_NODETYPE)) 1417 { 1418 names.add(node.getName().substring(METADATA_PREFIX.length())); 1419 } 1420 } 1421 1422 String[] result = new String[names.size()]; 1423 names.toArray(result); 1424 1425 return result; 1426 } 1427 catch (RepositoryException e) 1428 { 1429 throw new AmetysRepositoryException("Unable to get metadata names", e); 1430 } 1431 } 1432 1433 public boolean isMultiple(String metadataName) throws AmetysRepositoryException 1434 { 1435 try 1436 { 1437 String realMetadataName = METADATA_PREFIX + metadataName; 1438 1439 if (_node.hasProperty(realMetadataName)) 1440 { 1441 Property property = _node.getProperty(realMetadataName); 1442 1443 if (property.getDefinition().isMultiple()) 1444 { 1445 return true; 1446 } 1447 1448 return false; 1449 } 1450 1451 if (_node.hasNode(realMetadataName)) 1452 { 1453 String nodeType = NodeTypeHelper.getNodeTypeName(_node.getNode(realMetadataName)); 1454 1455 // Object collection is multi-valued. 1456 if (OBJECT_COLLECTION_METADATA_NODETYPE.equals(nodeType)) 1457 { 1458 return true; 1459 } 1460 1461 // User metadata 1462 if (nodeType.equals(METADATA_PREFIX + "user")) 1463 { 1464 return _node.getNodes(realMetadataName).getSize() > 1; 1465 } 1466 1467 // All other complex metadata are single valued. 1468 return false; 1469 } 1470 1471 throw new UnknownMetadataException("No metadata for name: " + metadataName); 1472 } 1473 catch (RepositoryException e) 1474 { 1475 throw new AmetysRepositoryException("Unable to determine if metadata " + metadataName + " is multiple", e); 1476 } 1477 } 1478 1479 /** 1480 * Check if the metadata name is valid. 1481 * @param metadataName The metadata name to check. 1482 * @throws AmetysRepositoryException If the metadata name is invalid. 1483 */ 1484 protected void _checkMetadataName(String metadataName) throws AmetysRepositoryException 1485 { 1486 // Id null 1487 if (metadataName == null) 1488 { 1489 throw new AmetysRepositoryException("Invalid metadata name (null)"); 1490 } 1491 1492 // Id valide 1493 if (!_getMetadataNamePattern().matcher(metadataName).matches()) 1494 { 1495 throw new AmetysRepositoryException("Invalid metadata name '" + metadataName + "'. This value is not permitted: only [a-zA-Z][a-zA-Z0-9-_]* are allowed."); 1496 } 1497 } 1498 1499 /** 1500 * Get the metadata name pattern to test validity. 1501 * @return The metadata name pattern. 1502 */ 1503 protected static Pattern _getMetadataNamePattern() 1504 { 1505 if (__metadataNamePattern == null) 1506 { 1507 // [a-zA-Z][a-zA-Z0-9_]* 1508 __metadataNamePattern = Pattern.compile("[a-z][a-z0-9-_]*", Pattern.CASE_INSENSITIVE); 1509 } 1510 1511 return __metadataNamePattern; 1512 } 1513 1514 public ModifiableBinaryMetadata getBinaryMetadata(String metadataName) throws AmetysRepositoryException 1515 { 1516 return getBinaryMetadata(metadataName, false); 1517 } 1518 1519 public ModifiableBinaryMetadata getBinaryMetadata(String metadataName, boolean createNew) throws AmetysRepositoryException 1520 { 1521 try 1522 { 1523 if (_node.hasNode(METADATA_PREFIX + metadataName)) 1524 { 1525 Node node = _node.getNode(METADATA_PREFIX + metadataName); 1526 return new JCRBinaryMetadata(node); 1527 } 1528 else if (createNew) 1529 { 1530 _checkLock(); 1531 Node node = _node.addNode(METADATA_PREFIX + metadataName, RepositoryConstants.BINARY_NODETYPE); 1532 return new JCRBinaryMetadata(node); 1533 } 1534 else 1535 { 1536 throw new UnknownMetadataException("No BinaryMetadata named " + metadataName); 1537 } 1538 } 1539 catch (RepositoryException e) 1540 { 1541 throw new AmetysRepositoryException(e); 1542 } 1543 } 1544 1545 public ModifiableCompositeMetadata getCompositeMetadata(String metadataName) throws AmetysRepositoryException 1546 { 1547 return getCompositeMetadata(metadataName, false); 1548 } 1549 1550 public ModifiableCompositeMetadata getCompositeMetadata(String metadataName, boolean createNew) throws AmetysRepositoryException 1551 { 1552 try 1553 { 1554 if (_node.hasNode(METADATA_PREFIX + metadataName)) 1555 { 1556 Node node = _node.getNode(METADATA_PREFIX + metadataName); 1557 return new JCRCompositeMetadata(node, _resolver); 1558 } 1559 else if (createNew) 1560 { 1561 _checkLock(); 1562 Node node = _node.addNode(METADATA_PREFIX + metadataName, "ametys:compositeMetadata"); 1563 return new JCRCompositeMetadata(node, _resolver); 1564 } 1565 else 1566 { 1567 throw new UnknownMetadataException("No CompositeMetadata named " + metadataName); 1568 } 1569 } 1570 catch (RepositoryException e) 1571 { 1572 throw new AmetysRepositoryException(e); 1573 } 1574 } 1575 1576 public ModifiableRichText getRichText(String metadataName) throws UnknownMetadataException, AmetysRepositoryException 1577 { 1578 return getRichText(metadataName, false); 1579 } 1580 1581 public ModifiableRichText getRichText(String metadataName, boolean createNew) throws UnknownMetadataException, AmetysRepositoryException 1582 { 1583 try 1584 { 1585 if (_node.hasNode(METADATA_PREFIX + metadataName)) 1586 { 1587 Node node = _node.getNode(METADATA_PREFIX + metadataName); 1588 return new JCRRichText(node, _resolver); 1589 } 1590 else if (createNew) 1591 { 1592 _checkLock(); 1593 Node node = _node.addNode(METADATA_PREFIX + metadataName, METADATA_PREFIX + "richText"); 1594 return new JCRRichText(node, _resolver); 1595 } 1596 else 1597 { 1598 throw new UnknownMetadataException("No RichText named " + metadataName); 1599 } 1600 } 1601 catch (RepositoryException e) 1602 { 1603 throw new AmetysRepositoryException(e); 1604 } 1605 } 1606 1607 public ModifiableTraversableAmetysObject getObjectCollection(String metadataName) throws AmetysRepositoryException 1608 { 1609 return getObjectCollection(metadataName, false); 1610 } 1611 1612 public ModifiableTraversableAmetysObject getObjectCollection(String metadataName, boolean createNew) throws AmetysRepositoryException 1613 { 1614 try 1615 { 1616 if (_node.hasNode(METADATA_PREFIX + metadataName)) 1617 { 1618 Node node = _node.getNode(METADATA_PREFIX + metadataName); 1619 return _resolver.resolve(node, false); 1620 } 1621 else if (createNew) 1622 { 1623 _checkLock(); 1624 Node node = _node.addNode(METADATA_PREFIX + metadataName, OBJECT_COLLECTION_METADATA_NODETYPE); 1625 return _resolver.resolve(node, false); 1626 } 1627 else 1628 { 1629 throw new UnknownMetadataException("No object collection metadata named " + metadataName); 1630 } 1631 } 1632 catch (RepositoryException e) 1633 { 1634 throw new AmetysRepositoryException(e); 1635 } 1636 } 1637 1638 @Override 1639 public List<MetadataComment> getComments(String metadataName) 1640 { 1641 List<MetadataComment> comments = new ArrayList<>(); 1642 String commentsNodeName = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ':' + metadataName + METADATA_COMMENTS_SUFFIX; 1643 1644 try 1645 { 1646 if (_node.hasNode(commentsNodeName)) 1647 { 1648 Node commentsNode = _node.getNode(commentsNodeName); 1649 NodeIterator iterator = commentsNode.getNodes(); 1650 1651 while (iterator.hasNext()) 1652 { 1653 Node node = iterator.nextNode(); 1654 1655 String text = node.getProperty(METADATA_PREFIX + "comment").getString(); 1656 Date date = node.getProperty(METADATA_PREFIX + "date").getDate().getTime(); 1657 String author = node.getProperty(METADATA_PREFIX + "author").getString(); 1658 1659 comments.add(new MetadataComment(text, date, author)); 1660 } 1661 } 1662 1663 return comments; 1664 } 1665 catch (RepositoryException e) 1666 { 1667 throw new AmetysRepositoryException("Unable to retrieves the comments for metadata : " + metadataName, e); 1668 } 1669 } 1670 1671 @Override 1672 public boolean hasComments(String metadataName) 1673 { 1674 String commentsNodeName = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ':' + metadataName + METADATA_COMMENTS_SUFFIX; 1675 1676 try 1677 { 1678 if (_node.hasNode(commentsNodeName)) 1679 { 1680 Node commentsNode = _node.getNode(commentsNodeName); 1681 return commentsNode.getNodes().hasNext(); 1682 } 1683 1684 return false; 1685 } 1686 catch (RepositoryException e) 1687 { 1688 throw new AmetysRepositoryException("Unable to determine if this node has at least one comment for metadata : " + metadataName, e); 1689 } 1690 } 1691 1692 @Override 1693 public boolean hasComment(String metadataName, int index) 1694 { 1695 String name = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ':' + metadataName + METADATA_COMMENTS_SUFFIX + '/' + RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ':' + index; 1696 try 1697 { 1698 return _node.hasNode(name); 1699 } 1700 catch (RepositoryException e) 1701 { 1702 throw new AmetysRepositoryException("Unable to determine if this node has a comment for metadata : " + metadataName, e); 1703 } 1704 } 1705 1706 @Override 1707 public void addComment(String metadataName, String text, String author, Date date) 1708 { 1709 if (text == null) 1710 { 1711 throw new NullPointerException("text of the comment cannot be null"); 1712 } 1713 1714 String commentsNodeName = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ':' + metadataName + METADATA_COMMENTS_SUFFIX; 1715 1716 try 1717 { 1718 _checkLock(); 1719 if (!_node.hasNode(commentsNodeName)) 1720 { 1721 _node.addNode(commentsNodeName, "ametys:compositeMetadata"); 1722 } 1723 1724 Node commentsNode = _node.getNode(commentsNodeName); 1725 String nodeName = null; 1726 int i = 0; 1727 1728 // Loop over existing comments 1729 do 1730 { 1731 nodeName = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ':' + ++i; 1732 } while (commentsNode.hasNode(nodeName)); 1733 1734 // Add the new comment node at the end 1735 Node commentNode = commentsNode.addNode(nodeName, "ametys:compositeMetadata"); 1736 1737 GregorianCalendar calendar = new GregorianCalendar(); 1738 if (date != null) 1739 { 1740 calendar.setTime(date); 1741 } 1742 1743 commentNode.setProperty(METADATA_PREFIX + "comment", text); 1744 commentNode.setProperty(METADATA_PREFIX + "date", calendar); 1745 commentNode.setProperty(METADATA_PREFIX + "author", author); 1746 } 1747 catch (RepositoryException e) 1748 { 1749 throw new AmetysRepositoryException("Unable to add a comment for metadata : " + metadataName, e); 1750 } 1751 } 1752 1753 @Override 1754 public void editComment(String metadataName, int index, String text, String author, Date date) 1755 { 1756 if (text == null) 1757 { 1758 throw new NullPointerException("text of the comment cannot be null"); 1759 } 1760 1761 String commentNodeName = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ':' + metadataName + METADATA_COMMENTS_SUFFIX + '/' + RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ':' + index; 1762 1763 try 1764 { 1765 _checkLock(); 1766 Node commentNode = _node.getNode(commentNodeName); 1767 1768 GregorianCalendar calendar = new GregorianCalendar(); 1769 if (date != null) 1770 { 1771 calendar.setTime(date); 1772 } 1773 1774 commentNode.setProperty(METADATA_PREFIX + "comment", text); 1775 commentNode.setProperty(METADATA_PREFIX + "date", calendar); 1776 commentNode.setProperty(METADATA_PREFIX + "author", author); 1777 } 1778 catch (RepositoryException e) 1779 { 1780 throw new AmetysRepositoryException("Unable to edit the comment at index +" + index + " for metadata : " + metadataName, e); 1781 } 1782 } 1783 1784 @Override 1785 public void deleteComment(String metadataName, int index) 1786 { 1787 String commentNodeName = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ':' + metadataName + METADATA_COMMENTS_SUFFIX + '/' + RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ':' + index; 1788 1789 try 1790 { 1791 _checkLock(); 1792 _node.getNode(commentNodeName).remove(); 1793 } 1794 catch (RepositoryException e) 1795 { 1796 throw new AmetysRepositoryException("Unable to remove the comment at index +" + index + " for metadata : " + metadataName, e); 1797 } 1798 } 1799 1800 private void _checkLock() throws RepositoryException 1801 { 1802 if (!_lockAlreadyChecked && _node.isLocked()) 1803 { 1804 LockManager lockManager = _node.getSession().getWorkspace().getLockManager(); 1805 1806 Lock lock = lockManager.getLock(_node.getPath()); 1807 Node lockHolder = lock.getNode(); 1808 1809 lockManager.addLockToken(lockHolder.getProperty(RepositoryConstants.METADATA_LOCKTOKEN).getString()); 1810 _lockAlreadyChecked = true; 1811 } 1812 } 1813}