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