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