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