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.web.repository.page.jcr; 017 018import java.util.ArrayList; 019import java.util.Collections; 020import java.util.HashMap; 021import java.util.HashSet; 022import java.util.List; 023import java.util.Map; 024import java.util.Set; 025 026import javax.jcr.ItemExistsException; 027import javax.jcr.Node; 028import javax.jcr.RepositoryException; 029import javax.jcr.Value; 030 031import org.apache.commons.lang.StringUtils; 032 033import org.ametys.plugins.explorer.resources.ResourceCollection; 034import org.ametys.plugins.explorer.resources.jcr.JCRResourcesCollectionFactory; 035import org.ametys.plugins.repository.AmetysObject; 036import org.ametys.plugins.repository.AmetysObjectIterable; 037import org.ametys.plugins.repository.AmetysRepositoryException; 038import org.ametys.plugins.repository.CopiableAmetysObject; 039import org.ametys.plugins.repository.ModifiableTraversableAmetysObject; 040import org.ametys.plugins.repository.RepositoryConstants; 041import org.ametys.plugins.repository.RepositoryIntegrityViolationException; 042import org.ametys.plugins.repository.data.holder.ModifiableDataHolder; 043import org.ametys.plugins.repository.data.holder.impl.DataHolderHelper; 044import org.ametys.plugins.repository.jcr.SimpleAmetysObject; 045import org.ametys.plugins.repository.tag.TaggableAmetysObjectHelper; 046import org.ametys.runtime.model.exception.BadItemTypeException; 047import org.ametys.runtime.model.exception.NotUniqueTypeException; 048import org.ametys.runtime.model.exception.UndefinedItemPathException; 049import org.ametys.runtime.model.exception.UnknownTypeException; 050import org.ametys.runtime.model.type.DataContext; 051import org.ametys.runtime.model.type.ModelItemTypeConstants; 052import org.ametys.web.parameters.view.ViewParametersManager; 053import org.ametys.web.repository.page.LockablePage; 054import org.ametys.web.repository.page.ModifiableZone; 055import org.ametys.web.repository.page.MoveablePage; 056import org.ametys.web.repository.page.Page; 057import org.ametys.web.repository.page.PageDAO; 058import org.ametys.web.repository.page.SitemapElement; 059import org.ametys.web.repository.site.Site; 060import org.ametys.web.repository.sitemap.Sitemap; 061 062/** 063 * {@link Page} implementation stored into a JCR node using 064 * <code>ametys:defaultPage</code> node type. 065 * 066 * @param <F> the actual type of factory. 067 */ 068public class DefaultPage<F extends DefaultPageFactory> extends AbstractSitemapElement<F> implements LockablePage, CopiableAmetysObject, MoveablePage 069{ 070 /** Constant for template metadata. */ 071 public static final String METADATA_TEMPLATE = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":template"; 072 073 /** Constant for title metadata. */ 074 public static final String METADATA_TITLE = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":title"; 075 076 /** Constant for the initial title metadata. */ 077 public static final String METADATA_INITIAL_TITLE = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":title-initial"; 078 079 /** Constant for long title metadata. */ 080 public static final String METADATA_LONG_TITLE = "long-title"; 081 082 /** Constant for title metadata. */ 083 public static final String METADATA_TYPE = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":type"; 084 085 /** Constant for title metadata. */ 086 public static final String METADATA_URL = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":url"; 087 088 /** Constant for title metadata. */ 089 public static final String METADATA_URLTYPE = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":url-type"; 090 091 /** Constant for referers metadata. */ 092 public static final String METADATA_REFERERS = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":referers"; 093 094 /** Constant for the visible attribute. */ 095 public static final String METADATA_VISIBLE = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":visible"; 096 097 /** Constant for the locked attribute. */ 098 public static final String METADATA_LOCKED = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":locked"; 099 100 /** Constant for robots metadata. */ 101 public static final String METADATA_ROBOTS_DISALLOW = "robots-disallow"; 102 103 /** Constant for the attachment node name. */ 104 public static final String ATTACHMENTS_NODE_NAME = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":attachments"; 105 106 /** Constants for sitemap Metadata* */ 107 public static final String METADATA_SITEMAP = "sitemap"; 108 109 /** Constant for publication start date metadata. */ 110 public static final String METADATA_PUBLICATION_START_DATE = "publicationStartDate"; 111 112 /** Constant for publication end date metadata. */ 113 public static final String METADATA_PUBLICATION_END_DATE = "publicationEndDate"; 114 115 /** 116 * Creates a {@link DefaultPage}. 117 * 118 * @param node the node backing this {@link AmetysObject}. 119 * @param parentPath the parent path in the Ametys hierarchy. 120 * @param factory the {@link DefaultPageFactory} which creates the 121 * AmetysObject. 122 */ 123 public DefaultPage(Node node, String parentPath, F factory) 124 { 125 super(node, parentPath, factory); 126 } 127 128 @Override 129 public String getTemplate() throws AmetysRepositoryException 130 { 131 if (getType() != PageType.CONTAINER) 132 { 133 return null; 134 } 135 136 try 137 { 138 Node node = getNode(); 139 140 if (node.hasProperty(METADATA_TEMPLATE)) 141 { 142 return node.getProperty(METADATA_TEMPLATE).getString(); 143 } 144 else 145 { 146 return null; 147 } 148 } 149 catch (RepositoryException e) 150 { 151 throw new AmetysRepositoryException("Unable to get template property", e); 152 } 153 } 154 155 @Override 156 public void setTemplate(String template) throws AmetysRepositoryException 157 { 158 try 159 { 160 getNode().setProperty(METADATA_TEMPLATE, template); 161 } 162 catch (RepositoryException e) 163 { 164 throw new AmetysRepositoryException("Unable to set template property", e); 165 } 166 } 167 168 @Override 169 public Set<String> getTags() throws AmetysRepositoryException 170 { 171 return TaggableAmetysObjectHelper.getTags(this); 172 } 173 174 @Override 175 public void tag(String tag) throws AmetysRepositoryException 176 { 177 TaggableAmetysObjectHelper.tag(this, tag); 178 } 179 180 @Override 181 public void untag(String tag) throws AmetysRepositoryException 182 { 183 TaggableAmetysObjectHelper.untag(this, tag); 184 } 185 186 @Override 187 public String getTitle() throws AmetysRepositoryException 188 { 189 try 190 { 191 return getNode().getProperty(METADATA_TITLE).getString(); 192 } 193 catch (RepositoryException e) 194 { 195 throw new AmetysRepositoryException("Unable to get title property", e); 196 } 197 } 198 199 @Override 200 public void setTitle(String title) throws AmetysRepositoryException 201 { 202 try 203 { 204 getNode().setProperty(METADATA_TITLE, title); 205 } 206 catch (RepositoryException e) 207 { 208 throw new AmetysRepositoryException("Unable to set title property", e); 209 } 210 setInitialTitle(title); 211 } 212 213 /** 214 * Get the title that was set by the user (and not set by a copy adding a number after) 215 * @return The initial title 216 * @throws AmetysRepositoryException if an error occurs 217 */ 218 public String getInitialTitle() throws AmetysRepositoryException 219 { 220 try 221 { 222 if (getNode().hasProperty(METADATA_INITIAL_TITLE)) 223 { 224 return getNode().getProperty(METADATA_INITIAL_TITLE).getString(); 225 } 226 else 227 { 228 return getTitle(); 229 } 230 } 231 catch (RepositoryException e) 232 { 233 throw new AmetysRepositoryException("Unable to get initial title property", e); 234 } 235 } 236 237 /** 238 * Set the title that was set by the user (and not set by a copy adding a number after) 239 * @param initialTitle The initial title to set 240 * @throws AmetysRepositoryException if an error occurs 241 */ 242 public void setInitialTitle(String initialTitle) throws AmetysRepositoryException 243 { 244 try 245 { 246 getNode().setProperty(METADATA_INITIAL_TITLE, initialTitle); 247 } 248 catch (RepositoryException e) 249 { 250 throw new AmetysRepositoryException("Unable to set initial title property", e); 251 } 252 } 253 254 @Override 255 public String getLongTitle() throws AmetysRepositoryException 256 { 257 String longTitle = getValue(METADATA_LONG_TITLE); 258 if (StringUtils.isNotBlank(longTitle)) 259 { 260 return longTitle; 261 } 262 else 263 { 264 return this.getTitle(); 265 } 266 } 267 268 @Override 269 public void setLongTitle(String title) throws AmetysRepositoryException 270 { 271 String newTitle = StringUtils.trimToNull(title); 272 setValue(METADATA_LONG_TITLE, newTitle, ModelItemTypeConstants.STRING_TYPE_ID); 273 } 274 275 @Override 276 public Sitemap getSitemap() throws AmetysRepositoryException 277 { 278 try 279 { 280 Node node = getNode(); 281 282 do 283 { 284 node = node.getParent(); 285 } 286 while (!node.getPrimaryNodeType().getName().equals(Sitemap.NODE_TYPE)); 287 288 return _getFactory().resolveAmetysObject(node); 289 } 290 catch (RepositoryException e) 291 { 292 throw new AmetysRepositoryException("Unable to get sitemap", e); 293 } 294 } 295 296 @Override 297 public int getDepth() throws AmetysRepositoryException 298 { 299 try 300 { 301 int depth = 1; 302 Node node = getNode().getParent(); 303 while (!node.getPrimaryNodeType().getName().equals(Sitemap.NODE_TYPE)) 304 { 305 depth++; 306 node = node.getParent(); 307 } 308 309 return depth; 310 } 311 catch (RepositoryException e) 312 { 313 throw new AmetysRepositoryException("Unable to get depth", e); 314 } 315 } 316 317 @Override 318 public Site getSite() throws AmetysRepositoryException 319 { 320 return getSitemap().getSite(); 321 } 322 323 @Override 324 public String getSiteName() 325 { 326 return getValue(METADATA_SITE); 327 } 328 329 @Override 330 public void setSiteName(String siteName) 331 { 332 setValue(METADATA_SITE, siteName); 333 } 334 335 @Override 336 public String getSitemapName() throws AmetysRepositoryException 337 { 338 return getValue(METADATA_SITEMAP); 339 } 340 341 @Override 342 public void setSitemapName(String sitemapName) throws AmetysRepositoryException 343 { 344 setValue(METADATA_SITEMAP, sitemapName); 345 } 346 347 @Override 348 public String getPathInSitemap() throws AmetysRepositoryException 349 { 350 String nodePath = getPath(); 351 String sitemapPath = getSitemap().getPath(); 352 return nodePath.substring(sitemapPath.length() + 1); 353 } 354 355 @Override 356 public PageType getType() throws AmetysRepositoryException 357 { 358 try 359 { 360 return PageType.valueOf(getNode().getProperty(METADATA_TYPE).getString()); 361 } 362 catch (RepositoryException e) 363 { 364 throw new AmetysRepositoryException("Unable to get type property", e); 365 } 366 } 367 368 @Override 369 public void setType(PageType type) throws AmetysRepositoryException 370 { 371 try 372 { 373 getNode().setProperty(METADATA_TYPE, type.name()); 374 } 375 catch (RepositoryException e) 376 { 377 throw new AmetysRepositoryException("Unable to set type property", e); 378 } 379 } 380 381 @Override 382 public String getURL() throws AmetysRepositoryException 383 { 384 try 385 { 386 return getNode().getProperty(METADATA_URL).getString(); 387 } 388 catch (RepositoryException e) 389 { 390 throw new AmetysRepositoryException("Unable to get url property", e); 391 } 392 } 393 394 @Override 395 public LinkType getURLType() throws AmetysRepositoryException 396 { 397 try 398 { 399 return LinkType.valueOf(getNode().getProperty(METADATA_URLTYPE).getString()); 400 } 401 catch (RepositoryException e) 402 { 403 throw new AmetysRepositoryException("Unable to get url type property", e); 404 } 405 } 406 407 @Override 408 public void setURL(LinkType type, String url) throws AmetysRepositoryException 409 { 410 try 411 { 412 getNode().setProperty(METADATA_URLTYPE, type.toString()); 413 getNode().setProperty(METADATA_URL, url); 414 } 415 catch (RepositoryException e) 416 { 417 throw new AmetysRepositoryException("Unable to set url property", e); 418 } 419 } 420 421 @Override 422 public ResourceCollection getRootAttachments() throws AmetysRepositoryException 423 { 424 ResourceCollection attachments; 425 if (hasChild(ATTACHMENTS_NODE_NAME)) 426 { 427 attachments = getChild(ATTACHMENTS_NODE_NAME); 428 } 429 else 430 { 431 attachments = createChild(ATTACHMENTS_NODE_NAME, JCRResourcesCollectionFactory.RESOURCESCOLLECTION_NODETYPE); 432 433 try 434 { 435 getNode().getSession().save(); 436 } 437 catch (RepositoryException e) 438 { 439 throw new AmetysRepositoryException("Unable to save session", e); 440 } 441 } 442 443 return attachments; 444 } 445 446 @Override 447 public Set<String> getReferers() throws AmetysRepositoryException 448 { 449 try 450 { 451 Node node = getNode(); 452 453 if (!node.hasProperty(METADATA_REFERERS)) 454 { 455 return Collections.emptySet(); 456 } 457 458 Value[] values = getNode().getProperty(METADATA_REFERERS).getValues(); 459 Set<String> ids = new HashSet<>(values.length); 460 461 for (Value value : values) 462 { 463 ids.add(value.getString()); 464 } 465 466 return ids; 467 } 468 catch (RepositoryException e) 469 { 470 throw new AmetysRepositoryException("Unable to get referers property", e); 471 } 472 } 473 474 @Override 475 public void addReferer(String ametysObjectId) throws AmetysRepositoryException 476 { 477 try 478 { 479 Set<String> ids = null; 480 Node node = getNode(); 481 482 if (!node.hasProperty(METADATA_REFERERS)) 483 { 484 ids = Collections.singleton(ametysObjectId); 485 } 486 else 487 { 488 Value[] values = getNode().getProperty(METADATA_REFERERS).getValues(); 489 ids = new HashSet<>(values.length + 1); 490 491 for (Value value : values) 492 { 493 ids.add(value.getString()); 494 } 495 496 ids.add(ametysObjectId); 497 } 498 499 node.setProperty(METADATA_REFERERS, ids.toArray(new String[ids.size()])); 500 } 501 catch (RepositoryException e) 502 { 503 throw new AmetysRepositoryException("Unable to add an id into referers property", e); 504 } 505 } 506 507 @Override 508 public void removeReferer(String ametysObjectId) throws AmetysRepositoryException 509 { 510 try 511 { 512 Node node = getNode(); 513 514 if (node.hasProperty(METADATA_REFERERS)) 515 { 516 Value[] values = getNode().getProperty(METADATA_REFERERS).getValues(); 517 Set<String> ids = new HashSet<>(values.length + 1); 518 519 for (Value value : values) 520 { 521 ids.add(value.getString()); 522 } 523 524 ids.remove(ametysObjectId); 525 node.setProperty(METADATA_REFERERS, ids.toArray(new String[ids.size()])); 526 } 527 } 528 catch (RepositoryException e) 529 { 530 throw new AmetysRepositoryException("Unable to remove an id from referers property", e); 531 } 532 } 533 534 @Override 535 public DefaultPage copyTo(ModifiableTraversableAmetysObject parent, String name, List<String> restrictTo) throws AmetysRepositoryException 536 { 537 try 538 { 539 String pageName = PageDAO.findFreePageName(parent, name != null ? name : getName()); 540 541 DefaultPage cPage = parent.createChild(pageName, "ametys:defaultPage"); 542 cPage.setType(getType()); 543 cPage.setTitle(getTitle()); 544 cPage.setInitialTitle(getInitialTitle()); 545 546 if (PageType.CONTAINER.equals(getType())) 547 { 548 cPage.setTemplate(getTemplate()); 549 } 550 else if (PageType.LINK.equals(getType())) 551 { 552 cPage.setURL(getURLType(), getURL()); 553 } 554 555 // Copy metadata 556 copyTo(cPage); 557 558 // Copy view parameters 559 getTemplateParametersHolder().copyTo(cPage.getTemplateParametersHolder()); 560 561 // Copy zones 562 for (ModifiableZone zone : getZones()) 563 { 564 if (zone instanceof CopiableAmetysObject) 565 { 566 ((CopiableAmetysObject) zone).copyTo(cPage, null); 567 } 568 } 569 570 // Copy tags 571 Set<String> tags = getTags(); 572 for (String tag : tags) 573 { 574 cPage.tag(tag); 575 } 576 577 // Update sitemap name 578 if (parent instanceof SitemapElement) 579 { 580 cPage.setSitemapName(((SitemapElement) parent).getSitemapName()); 581 } 582 583 parent.saveChanges(); 584 585 // Copy attachments 586 ResourceCollection rootAttachments = getRootAttachments(); 587 if (rootAttachments instanceof SimpleAmetysObject) 588 { 589 Node resourcesNode = ((SimpleAmetysObject) rootAttachments).getNode(); 590 getNode().getSession().getWorkspace().copy(resourcesNode.getPath(), cPage.getNode().getPath() + "/" + resourcesNode.getName()); 591 } 592 593 // Copy sub-pages 594 AmetysObjectIterable< ? extends Page> childrenPages = getChildrenPages(); 595 for (Page page : childrenPages) 596 { 597 // Avoid infinite loop : do not copy the page itself 598 if (page instanceof CopiableAmetysObject && restrictTo.contains(page.getId())) 599 { 600 ((CopiableAmetysObject) page).copyTo(cPage, null, restrictTo); 601 } 602 } 603 604 return cPage; 605 } 606 catch (RepositoryException e) 607 { 608 throw new AmetysRepositoryException(e); 609 } 610 } 611 612 @Override 613 public DefaultPage copyTo(ModifiableTraversableAmetysObject parent, String name) throws AmetysRepositoryException 614 { 615 return copyTo (parent, name, new ArrayList<>()); 616 } 617 618 public void copyTo(ModifiableDataHolder dataHolder) throws UndefinedItemPathException, BadItemTypeException, UnknownTypeException, NotUniqueTypeException 619 { 620 for (String name : getDataNames()) 621 { 622 if (!_getExcludedDataFromCopy().contains(name)) 623 { 624 DataHolderHelper.copyTo(getDataHolder(), dataHolder, name, DataContext.newInstance()); 625 } 626 } 627 } 628 629 /** 630 * Get the set of data name to exclude from the copy 631 * @return the set of data name to exclude from the copy 632 */ 633 protected Set<String> _getExcludedDataFromCopy() 634 { 635 return Set.of( 636 ViewParametersManager.VIEW_PARAMETERS_COMPOSITE_NAME, 637 METADATA_PUBLICATION_START_DATE, 638 METADATA_PUBLICATION_END_DATE 639 ); 640 } 641 642 @Override 643 public void moveTo(AmetysObject newParent, boolean renameIfExist) throws AmetysRepositoryException, RepositoryIntegrityViolationException 644 { 645 Node node = getNode(); 646 647 try 648 { 649 if (getParent().equals(newParent)) 650 { 651 // Just order current node to the end 652 node.getParent().orderBefore(node.getName(), null); 653 } 654 else 655 { 656 if (!canMoveTo(newParent)) 657 { 658 throw new AmetysRepositoryException("DefaultPage " + toString() + " can only be moved to a CompositePages and "); 659 } 660 SitemapElement newParentPage = (SitemapElement) newParent; 661 662 String sitemapNodePath = getSitemap().getNode().getPath(); 663 String newPath = sitemapNodePath + (newParentPage instanceof Sitemap ? "" : '/' + newParentPage.getPathInSitemap()); 664 665 String name = node.getName(); 666 667 if (renameIfExist) 668 { 669 // Find unused name on new parent node 670 int index = 1; 671 while (node.getSession().getRootNode().hasNode(newPath.substring(1) + "/" + name)) 672 { 673 name = name + "-" + index++; 674 } 675 } 676 677 try 678 { 679 // Move node 680 node.getSession().move(node.getPath(), newPath + "/" + name); 681 } 682 catch (ItemExistsException e) 683 { 684 throw new AmetysRepositoryException(String.format("A page already exists for in parent path '%s'", newPath), e); 685 } 686 687 // recompute name in case it has changed 688 _invalidateName(); 689 690 // Invalidate parent path as the parent path has changed 691 _invalidateParentPath(); 692 } 693 } 694 catch (RepositoryException e) 695 { 696 throw new AmetysRepositoryException(String.format("Unable to move page '%s' to node '%s'", this, newParent.getId()), e); 697 } 698 } 699 700 @Override 701 public boolean canMoveTo(AmetysObject newParent) throws AmetysRepositoryException 702 { 703 return newParent instanceof SitemapElement && ((SitemapElement) newParent).getSitemap().equals(getSitemap()); 704 } 705 706 @Override 707 public void orderBefore(AmetysObject siblingNode) throws AmetysRepositoryException 708 { 709 Node node = getNode(); 710 try 711 { 712 node.getParent().orderBefore(node.getName(), siblingNode != null ? siblingNode.getName() : null); 713 } 714 catch (RepositoryException e) 715 { 716 throw new AmetysRepositoryException(String.format("Unable to order page '%s' before sibling '%s'", this, siblingNode != null ? siblingNode.getName() : ""), e); 717 } 718 } 719 720 @Override 721 public boolean isVisible() throws AmetysRepositoryException 722 { 723 try 724 { 725 if (getNode().hasProperty(METADATA_VISIBLE)) 726 { 727 return getNode().getProperty(METADATA_VISIBLE).getBoolean(); 728 } 729 else 730 { 731 return true; 732 } 733 } 734 catch (RepositoryException e) 735 { 736 throw new AmetysRepositoryException("Unable to get visible property", e); 737 } 738 } 739 740 @Override 741 public void setVisible(boolean isVisible) throws AmetysRepositoryException 742 { 743 try 744 { 745 getNode().setProperty(METADATA_VISIBLE, isVisible); 746 } 747 catch (RepositoryException e) 748 { 749 throw new AmetysRepositoryException("Unable to set visible property", e); 750 } 751 } 752 753 public Map<String, Object> dataToJSON(DataContext context) throws UnknownTypeException, NotUniqueTypeException 754 { 755 Map<String, Object> result = new HashMap<>(); 756 for (String dataName : getDataNames()) 757 { 758 DataContext newContext = context.cloneContext().addSegmentToDataPath(dataName); 759 result.put(dataName, dataToJSON(dataName, newContext)); 760 } 761 762 return result; 763 } 764 765 public Object dataToJSON(String dataPath, DataContext context) 766 { 767 // Do not convert view parameters 768 return !ViewParametersManager.VIEW_PARAMETERS_COMPOSITE_NAME.equals(dataPath) 769 ? LockablePage.super.dataToJSON(dataPath, context) 770 : null; 771 } 772 773 public boolean isLocked() throws AmetysRepositoryException 774 { 775 try 776 { 777 if (getNode().hasProperty(METADATA_LOCKED)) 778 { 779 return getNode().getProperty(METADATA_LOCKED).getBoolean(); 780 } 781 else 782 { 783 return false; 784 } 785 } 786 catch (RepositoryException e) 787 { 788 throw new AmetysRepositoryException("Unable to get locked property", e); 789 } 790 } 791 792 public void lock() throws AmetysRepositoryException 793 { 794 try 795 { 796 getNode().setProperty(METADATA_LOCKED, true); 797 } 798 catch (RepositoryException e) 799 { 800 throw new AmetysRepositoryException("Unable to set locked property", e); 801 } 802 } 803 804 public void unlock() throws AmetysRepositoryException 805 { 806 try 807 { 808 getNode().setProperty(METADATA_LOCKED, false); 809 } 810 catch (RepositoryException e) 811 { 812 throw new AmetysRepositoryException("Unable to set locked property", e); 813 } 814 } 815}