NodeLinkAware.java

  1. /*
  2.  * Copyright (C) 2003-2009 eXo Platform SAS.
  3.  *
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU Affero General Public License
  6.  * as published by the Free Software Foundation; either version 3
  7.  * of the License, or (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, see<http://www.gnu.org/licenses/>.
  16.  */
  17. package org.exoplatform.services.cms.link;

  18. import java.io.InputStream;
  19. import java.security.AccessControlException;
  20. import java.util.Calendar;
  21. import java.util.Map;

  22. import javax.jcr.AccessDeniedException;
  23. import javax.jcr.InvalidItemStateException;
  24. import javax.jcr.Item;
  25. import javax.jcr.ItemExistsException;
  26. import javax.jcr.ItemNotFoundException;
  27. import javax.jcr.MergeException;
  28. import javax.jcr.NoSuchWorkspaceException;
  29. import javax.jcr.Node;
  30. import javax.jcr.NodeIterator;
  31. import javax.jcr.PathNotFoundException;
  32. import javax.jcr.Property;
  33. import javax.jcr.PropertyIterator;
  34. import javax.jcr.ReferentialIntegrityException;
  35. import javax.jcr.RepositoryException;
  36. import javax.jcr.Session;
  37. import javax.jcr.UnsupportedRepositoryOperationException;
  38. import javax.jcr.Value;
  39. import javax.jcr.ValueFormatException;
  40. import javax.jcr.lock.Lock;
  41. import javax.jcr.lock.LockException;
  42. import javax.jcr.nodetype.ConstraintViolationException;
  43. import javax.jcr.nodetype.NoSuchNodeTypeException;
  44. import javax.jcr.nodetype.NodeDefinition;
  45. import javax.jcr.nodetype.NodeType;
  46. import javax.jcr.version.Version;
  47. import javax.jcr.version.VersionException;
  48. import javax.jcr.version.VersionHistory;

  49. import org.exoplatform.services.jcr.access.AccessControlList;
  50. import org.exoplatform.services.jcr.core.ExtendedNode;
  51. import org.exoplatform.services.jcr.datamodel.InternalQName;
  52. import org.exoplatform.services.log.ExoLogger;
  53. import org.exoplatform.services.log.Log;
  54. import org.exoplatform.services.wcm.core.NodeLocation;

  55. /**
  56.  * Created by The eXo Platform SAS Author : eXoPlatform
  57.  * nicolas.filotto@exoplatform.com 31 mars 2009
  58.  */
  59. public class NodeLinkAware extends ItemLinkAware implements ExtendedNode {

  60.   final static public String    EXO_RESTORE_LOCATION = "exo:restoreLocation";

  61.   /**
  62.    * Logger.
  63.    */
  64.   private static final Log LOG = ExoLogger.getLogger(NodeLinkAware.class.getName());

  65.   private final NodeLocation    nodeLocation;

  66.   private volatile NodeLocation targetNodeLocation;

  67.   public NodeLinkAware(String originalWorkspace, String virtualPath, Node node) {
  68.     super(originalWorkspace, virtualPath, node);
  69.     this.nodeLocation = NodeLocation.getNodeLocationByNode(node);
  70.   }

  71.   public String getRealPath() {
  72.     return nodeLocation.getPath();
  73.   }

  74.   public Node getRealNode() {
  75.     return NodeLocation.getNodeByLocation(nodeLocation);
  76.   }

  77.   public NodeLinkAware getTargetNode() throws RepositoryException {
  78.     return new NodeLinkAware(originalWorkspaceName, virtualPath, getTarget());
  79.   }

  80.   public Session getNodeSession() throws RepositoryException {
  81.     return getRealNode().getSession();
  82.   }

  83.   Node getTarget() throws RepositoryException {
  84.     Node targetNode = null;
  85.     if (targetNodeLocation == null) {
  86.       synchronized (this) {
  87.         if (targetNodeLocation == null) {
  88.           LinkManager linkManager = LinkUtils.getLinkManager();
  89.           Node node = getRealNode();
  90.           if (linkManager.isLink(node)) {
  91.             targetNode = linkManager.getTarget(node);
  92.           } else {
  93.             targetNode = node;
  94.           }
  95.         }
  96.       }
  97.     }
  98.     return targetNode;
  99.   }

  100.   private Node getTargetReachable() throws RepositoryException {
  101.     try {
  102.       return getTarget();
  103.     } catch (AccessDeniedException e) {
  104.       if (LOG.isWarnEnabled()) {
  105.         LOG.warn("Cannot access to the target of the node " + nodeLocation.getPath());
  106.       }
  107.     } catch (ItemNotFoundException e) {
  108.       if (LOG.isWarnEnabled()) {
  109.         LOG.warn("The target of the node " + nodeLocation.getPath() + " doesn't exist anymore");
  110.       }
  111.     }
  112.     return null;
  113.   }

  114.   private ExtendedNode getExtendedTarget() throws RepositoryException {
  115.     return (ExtendedNode) getTarget();
  116.   }

  117.   private ExtendedNode getExtendedRealNode() {
  118.     return (ExtendedNode) getRealNode();
  119.   }

  120.   private String getVirtualPath(String relativePath) {
  121.     return LinkUtils.createPath(virtualPath, relativePath);
  122.   }

  123.   /**
  124.    * {@inheritDoc}
  125.    */
  126.   public void addMixin(String mixinName) throws NoSuchNodeTypeException, VersionException,
  127.       ConstraintViolationException, LockException, RepositoryException {
  128.     getTarget().addMixin(mixinName);
  129.   }

  130.   /**
  131.    * {@inheritDoc}
  132.    */
  133.   public Node addNode(String relPath) throws ItemExistsException, PathNotFoundException,
  134.       VersionException, ConstraintViolationException, LockException, RepositoryException {
  135.     return new NodeLinkAware(originalWorkspaceName, getVirtualPath(relPath), getTarget().addNode(
  136.         relPath));
  137.   }

  138.   /**
  139.    * {@inheritDoc}
  140.    */
  141.   public Node addNode(String relPath, String primaryNodeTypeName) throws ItemExistsException,
  142.       PathNotFoundException, NoSuchNodeTypeException, LockException, VersionException,
  143.       ConstraintViolationException, RepositoryException {
  144.     return new NodeLinkAware(originalWorkspaceName, getVirtualPath(relPath), getTarget().addNode(
  145.         relPath, primaryNodeTypeName));
  146.   }

  147.   /**
  148.    * {@inheritDoc}
  149.    */
  150.   public boolean canAddMixin(String mixinName) throws NoSuchNodeTypeException, RepositoryException {
  151.     return getTarget().canAddMixin(mixinName);
  152.   }

  153.   /**
  154.    * {@inheritDoc}
  155.    */
  156.   public void cancelMerge(Version version) throws VersionException, InvalidItemStateException,
  157.       UnsupportedRepositoryOperationException, RepositoryException {
  158.     getTarget().cancelMerge(version);
  159.   }

  160.   /**
  161.    * {@inheritDoc}
  162.    */
  163.   public Version checkin() throws VersionException, UnsupportedRepositoryOperationException,
  164.       InvalidItemStateException, LockException, RepositoryException {
  165.     return getTarget().checkin();
  166.   }

  167.   /**
  168.    * {@inheritDoc}
  169.    */
  170.   public void checkout() throws UnsupportedRepositoryOperationException, LockException,
  171.       RepositoryException {
  172.     getTarget().checkout();
  173.   }

  174.   /**
  175.    * {@inheritDoc}
  176.    */
  177.   public void doneMerge(Version version) throws VersionException, InvalidItemStateException,
  178.       UnsupportedRepositoryOperationException, RepositoryException {
  179.     getTarget().doneMerge(version);
  180.   }

  181.   /**
  182.    * {@inheritDoc}
  183.    */
  184.   public Version getBaseVersion() throws UnsupportedRepositoryOperationException,
  185.       RepositoryException {
  186.     return getTarget().getBaseVersion();
  187.   }

  188.   /**
  189.    * {@inheritDoc}
  190.    */
  191.   public String getCorrespondingNodePath(String workspaceName) throws ItemNotFoundException,
  192.       NoSuchWorkspaceException, AccessDeniedException, RepositoryException {
  193.     return getTarget().getCorrespondingNodePath(workspaceName);
  194.   }

  195.   /**
  196.    * {@inheritDoc}
  197.    */
  198.   public NodeDefinition getDefinition() throws RepositoryException {
  199.     return getTarget().getDefinition();
  200.   }

  201.   /**
  202.    * {@inheritDoc}
  203.    */
  204.   public int getIndex() throws RepositoryException {
  205.     return getRealNode().getIndex();
  206.   }

  207.   /**
  208.    * {@inheritDoc}
  209.    */
  210.   public Lock getLock() throws UnsupportedRepositoryOperationException, LockException,
  211.       AccessDeniedException, RepositoryException {
  212.     return getTarget().getLock();
  213.   }

  214.   /**
  215.    * {@inheritDoc}
  216.    */
  217.   public NodeType[] getMixinNodeTypes() throws RepositoryException {
  218.     return getTarget().getMixinNodeTypes();
  219.   }

  220.   /**
  221.    * {@inheritDoc}
  222.    */
  223.   public Node getNode(String relPath) throws PathNotFoundException, RepositoryException {
  224.     return new NodeLinkAware(originalWorkspaceName, getVirtualPath(relPath), (Node) LinkUtils
  225.         .getNodeFinder().getItem(getNodeSession(), getVirtualPath(relPath)));
  226.   }

  227.   /**
  228.    * {@inheritDoc}
  229.    */
  230.   public NodeIterator getNodes() throws RepositoryException {
  231.     return new NodeIteratorLinkAware(originalWorkspaceName, virtualPath, getTarget().getNodes());
  232.   }

  233.   /**
  234.    * {@inheritDoc}
  235.    */
  236.   public NodeIterator getNodes(String namePattern) throws RepositoryException {
  237.     return new NodeIteratorLinkAware(originalWorkspaceName, virtualPath, getTarget().getNodes(
  238.         namePattern));
  239.   }

  240.   /**
  241.    * {@inheritDoc}
  242.    */
  243.   public Item getPrimaryItem() throws ItemNotFoundException, RepositoryException {
  244.     return ItemLinkAware.newInstance(originalWorkspaceName, getVirtualPath(super.getName()),
  245.         getTarget().getPrimaryItem());
  246.   }

  247.   /**
  248.    * {@inheritDoc}
  249.    */
  250.   public NodeType getPrimaryNodeType() throws RepositoryException {
  251.     return new NodeTypeLinkAware(this);
  252.   }

  253.   /**
  254.    * {@inheritDoc}
  255.    */
  256.   public PropertyIterator getProperties() throws RepositoryException {
  257.     return new PropertyIteratorLinkAware(originalWorkspaceName, virtualPath, getTarget()
  258.         .getProperties());
  259.   }

  260.   /**
  261.    * {@inheritDoc}
  262.    */
  263.   public PropertyIterator getProperties(String namePattern) throws RepositoryException {
  264.     return new PropertyIteratorLinkAware(originalWorkspaceName, virtualPath, getTarget()
  265.         .getProperties(namePattern));
  266.   }

  267.   /**
  268.    * {@inheritDoc}
  269.    */
  270.   public Property getProperty(String relPath) throws PathNotFoundException, RepositoryException {
  271.     String path = getVirtualPath(relPath);
  272.     return new PropertyLinkAware(originalWorkspaceName, path, (Property) LinkUtils.getNodeFinder()
  273.         .getItem(getOriginalSession(), path));
  274.   }

  275.   /**
  276.    * {@inheritDoc}
  277.    */
  278.   public PropertyIterator getReferences() throws RepositoryException {
  279.     return getTarget().getReferences();
  280.   }

  281.   /**
  282.    * {@inheritDoc}
  283.    */
  284.   public String getUUID() throws UnsupportedRepositoryOperationException, RepositoryException {
  285.     return getTarget().getUUID();
  286.   }

  287.   /**
  288.    * {@inheritDoc}
  289.    */
  290.   public VersionHistory getVersionHistory() throws UnsupportedRepositoryOperationException,
  291.       RepositoryException {
  292.     return getTarget().getVersionHistory();
  293.   }

  294.   /**
  295.    * {@inheritDoc}
  296.    */
  297.   public boolean hasNode(String relPath) throws RepositoryException {
  298.     try {
  299.       return LinkUtils.getNodeFinder().getItem(getOriginalSession(), getVirtualPath(relPath)) instanceof Node;
  300.     } catch (PathNotFoundException e) {
  301.       return false;
  302.     }
  303.   }

  304.   /**
  305.    * {@inheritDoc}
  306.    */
  307.   public boolean hasNodes() throws RepositoryException {
  308.     return getTarget().hasNodes();
  309.   }

  310.   /**
  311.    * {@inheritDoc}
  312.    */
  313.   public boolean hasProperties() throws RepositoryException {
  314.     return getTarget().hasProperties();
  315.   }

  316.   /**
  317.    * {@inheritDoc}
  318.    */
  319.   public boolean hasProperty(String relPath) throws RepositoryException {
  320.     try {
  321.       return LinkUtils.getNodeFinder().getItem(getOriginalSession(), getVirtualPath(relPath)) instanceof Property;
  322.     } catch (PathNotFoundException e) {
  323.       return false;
  324.     }
  325.   }

  326.   /**
  327.    * {@inheritDoc}
  328.    */
  329.   public boolean holdsLock() throws RepositoryException {
  330.     Node node = getTargetReachable();
  331.     return node == null ? false : node.holdsLock();
  332.   }

  333.   /**
  334.    * {@inheritDoc}
  335.    */
  336.   public boolean isCheckedOut() throws RepositoryException {
  337.     Node node = getTargetReachable();
  338.     return node == null ? false : node.isCheckedOut();
  339.   }

  340.   /**
  341.    * {@inheritDoc}
  342.    */
  343.   public boolean isLocked() throws RepositoryException {
  344.     Node node = getTargetReachable();
  345.     return node == null ? false : node.isLocked();
  346.   }

  347.   /**
  348.    * {@inheritDoc}
  349.    */
  350.   public boolean isNodeType(String nodeTypeName) throws RepositoryException {
  351.     if (EXO_RESTORE_LOCATION.equals(nodeTypeName))
  352.       return this.getRealNode().isNodeType(nodeTypeName);
  353.     Node node = getTargetReachable();
  354.     return node == null ? false : node.isNodeType(nodeTypeName);
  355.   }

  356.   /**
  357.    * {@inheritDoc}
  358.    */
  359.   public Lock lock(boolean isDeep, boolean isSessionScoped)
  360.       throws UnsupportedRepositoryOperationException, LockException, AccessDeniedException,
  361.       InvalidItemStateException, RepositoryException {
  362.     return getTarget().lock(isDeep, isSessionScoped);
  363.   }

  364.   /**
  365.    * {@inheritDoc}
  366.    */
  367.   public NodeIterator merge(String srcWorkspace, boolean bestEffort)
  368.       throws NoSuchWorkspaceException, AccessDeniedException, MergeException, LockException,
  369.       InvalidItemStateException, RepositoryException {
  370.     return getTarget().merge(srcWorkspace, bestEffort);
  371.   }

  372.   /**
  373.    * {@inheritDoc}
  374.    */
  375.   public void orderBefore(String srcChildRelPath, String destChildRelPath)
  376.       throws UnsupportedRepositoryOperationException, VersionException,
  377.       ConstraintViolationException, ItemNotFoundException, LockException, RepositoryException {
  378.     getTarget().orderBefore(srcChildRelPath, destChildRelPath);
  379.   }

  380.   /**
  381.    * {@inheritDoc}
  382.    */
  383.   public void removeMixin(String mixinName) throws NoSuchNodeTypeException, VersionException,
  384.       ConstraintViolationException, LockException, RepositoryException {
  385.     getTarget().removeMixin(mixinName);
  386.   }

  387.   /**
  388.    * {@inheritDoc}
  389.    */
  390.   public void restore(String versionName, boolean removeExisting) throws VersionException,
  391.       ItemExistsException, UnsupportedRepositoryOperationException, LockException,
  392.       InvalidItemStateException, RepositoryException {
  393.     getTarget().restore(versionName, removeExisting);
  394.   }

  395.   /**
  396.    * {@inheritDoc}
  397.    */
  398.   public void restore(Version version, boolean removeExisting) throws VersionException,
  399.       ItemExistsException, UnsupportedRepositoryOperationException, LockException,
  400.       RepositoryException {
  401.     getTarget().restore(version, removeExisting);
  402.   }

  403.   /**
  404.    * {@inheritDoc}
  405.    */
  406.   public void restore(Version version, String relPath, boolean removeExisting)
  407.       throws PathNotFoundException, ItemExistsException, VersionException,
  408.       ConstraintViolationException, UnsupportedRepositoryOperationException, LockException,
  409.       InvalidItemStateException, RepositoryException {
  410.     getTarget().restore(version, relPath, removeExisting);
  411.   }

  412.   /**
  413.    * {@inheritDoc}
  414.    */
  415.   public void restoreByLabel(String versionLabel, boolean removeExisting) throws VersionException,
  416.       ItemExistsException, UnsupportedRepositoryOperationException, LockException,
  417.       InvalidItemStateException, RepositoryException {
  418.     getTarget().restoreByLabel(versionLabel, removeExisting);
  419.   }

  420.   /**
  421.    * {@inheritDoc}
  422.    */
  423.   public Property setProperty(String name, Value value) throws ValueFormatException,
  424.       VersionException, LockException, ConstraintViolationException, RepositoryException {
  425.     return getTarget().setProperty(name, value);
  426.   }

  427.   /**
  428.    * {@inheritDoc}
  429.    */
  430.   public Property setProperty(String name, Value[] values) throws ValueFormatException,
  431.       VersionException, LockException, ConstraintViolationException, RepositoryException {
  432.     return getTarget().setProperty(name, values);
  433.   }

  434.   /**
  435.    * {@inheritDoc}
  436.    */
  437.   public Property setProperty(String name, String[] values) throws ValueFormatException,
  438.       VersionException, LockException, ConstraintViolationException, RepositoryException {
  439.     return getTarget().setProperty(name, values);
  440.   }

  441.   /**
  442.    * {@inheritDoc}
  443.    */
  444.   public Property setProperty(String name, String value) throws ValueFormatException,
  445.       VersionException, LockException, ConstraintViolationException, RepositoryException {
  446.     return getTarget().setProperty(name, value);
  447.   }

  448.   /**
  449.    * {@inheritDoc}
  450.    */
  451.   public Property setProperty(String name, InputStream value) throws ValueFormatException,
  452.       VersionException, LockException, ConstraintViolationException, RepositoryException {
  453.     return getTarget().setProperty(name, value);
  454.   }

  455.   /**
  456.    * {@inheritDoc}
  457.    */
  458.   public Property setProperty(String name, boolean value) throws ValueFormatException,
  459.       VersionException, LockException, ConstraintViolationException, RepositoryException {
  460.     return getTarget().setProperty(name, value);
  461.   }

  462.   /**
  463.    * {@inheritDoc}
  464.    */
  465.   public Property setProperty(String name, double value) throws ValueFormatException,
  466.       VersionException, LockException, ConstraintViolationException, RepositoryException {
  467.     return getTarget().setProperty(name, value);
  468.   }

  469.   /**
  470.    * {@inheritDoc}
  471.    */
  472.   public Property setProperty(String name, long value) throws ValueFormatException,
  473.       VersionException, LockException, ConstraintViolationException, RepositoryException {
  474.     return getTarget().setProperty(name, value);
  475.   }

  476.   /**
  477.    * {@inheritDoc}
  478.    */
  479.   public Property setProperty(String name, Calendar value) throws ValueFormatException,
  480.       VersionException, LockException, ConstraintViolationException, RepositoryException {
  481.     return getTarget().setProperty(name, value);
  482.   }

  483.   /**
  484.    * {@inheritDoc}
  485.    */
  486.   public Property setProperty(String name, Node value) throws ValueFormatException,
  487.       VersionException, LockException, ConstraintViolationException, RepositoryException {
  488.     return getTarget().setProperty(name, value);
  489.   }

  490.   /**
  491.    * {@inheritDoc}
  492.    */
  493.   public Property setProperty(String name, Value value, int type) throws ValueFormatException,
  494.       VersionException, LockException, ConstraintViolationException, RepositoryException {
  495.     return getTarget().setProperty(name, value, type);
  496.   }

  497.   /**
  498.    * {@inheritDoc}
  499.    */
  500.   public Property setProperty(String name, Value[] values, int type) throws ValueFormatException,
  501.       VersionException, LockException, ConstraintViolationException, RepositoryException {
  502.     return getTarget().setProperty(name, values, type);
  503.   }

  504.   /**
  505.    * {@inheritDoc}
  506.    */
  507.   public Property setProperty(String name, String[] values, int type) throws ValueFormatException,
  508.       VersionException, LockException, ConstraintViolationException, RepositoryException {
  509.     return getTarget().setProperty(name, values, type);
  510.   }

  511.   /**
  512.    * {@inheritDoc}
  513.    */
  514.   public Property setProperty(String name, String value, int type) throws ValueFormatException,
  515.       VersionException, LockException, ConstraintViolationException, RepositoryException {
  516.     return getTarget().setProperty(name, value, type);
  517.   }

  518.   /**
  519.    * {@inheritDoc}
  520.    */
  521.   public void unlock() throws UnsupportedRepositoryOperationException, LockException,
  522.       AccessDeniedException, InvalidItemStateException, RepositoryException {
  523.     getTarget().unlock();
  524.   }

  525.   /**
  526.    * {@inheritDoc}
  527.    */
  528.   public void update(String srcWorkspaceName) throws NoSuchWorkspaceException,
  529.       AccessDeniedException, LockException, InvalidItemStateException, RepositoryException {
  530.     getTarget().update(srcWorkspaceName);
  531.   }

  532.   /**
  533.    * {@inheritDoc}
  534.    */
  535.   public void save() throws AccessDeniedException, ItemExistsException,
  536.       ConstraintViolationException, InvalidItemStateException, ReferentialIntegrityException,
  537.       VersionException, LockException, NoSuchNodeTypeException, RepositoryException {
  538.     getTarget().save();
  539.   }

  540.   /**
  541.    * {@inheritDoc}
  542.    */
  543.   public void checkPermission(String actions) throws AccessControlException, RepositoryException {
  544.     getExtendedRealNode().checkPermission(actions);
  545.   }

  546.   /**
  547.    * {@inheritDoc}
  548.    */
  549.   public void clearACL() throws RepositoryException, AccessControlException {
  550.     getExtendedRealNode().clearACL();
  551.   }

  552.   /**
  553.    * {@inheritDoc}
  554.    */
  555.   public AccessControlList getACL() throws RepositoryException {
  556.     return getExtendedRealNode().getACL();
  557.   }

  558.   /**
  559.    * {@inheritDoc}
  560.    */
  561.   public boolean isNodeType(InternalQName name) throws RepositoryException {
  562.     ExtendedNode node = (ExtendedNode) getTargetReachable();
  563.     return node == null ? false : node.isNodeType(name);
  564.   }

  565.   /**
  566.    * {@inheritDoc}
  567.    */
  568.   public Lock lock(boolean isDeep, long timeOut) throws UnsupportedRepositoryOperationException,
  569.       LockException, AccessDeniedException, InvalidItemStateException, RepositoryException {
  570.     return getExtendedTarget().lock(isDeep, timeOut);
  571.   }

  572.   /**
  573.    * {@inheritDoc}
  574.    */
  575.   public void removePermission(String identity) throws RepositoryException, AccessControlException {
  576.     getExtendedRealNode().removePermission(identity);
  577.   }

  578.   /**
  579.    * {@inheritDoc}
  580.    */
  581.   public void removePermission(String identity, String permission) throws RepositoryException,
  582.       AccessControlException {
  583.     getExtendedRealNode().removePermission(identity, permission);
  584.   }

  585.   /**
  586.    * {@inheritDoc}
  587.    */
  588.   public void setPermission(String identity, String[] permission) throws RepositoryException,
  589.       AccessControlException {
  590.     getExtendedRealNode().setPermission(identity, permission);
  591.   }

  592.   /**
  593.    * {@inheritDoc}
  594.    */
  595.   public void setPermissions(Map<String, String[]> permissions) throws RepositoryException,
  596.       AccessControlException {
  597.     getExtendedRealNode().setPermissions(permissions);
  598.   }

  599.   /**
  600.    * {@inheritDoc}
  601.    */
  602.   public String getIdentifier() throws RepositoryException {
  603.     ExtendedNode node = (ExtendedNode) getTarget();
  604.     return node.getIdentifier();
  605.   }

  606.   /**
  607.    * {@inheritDoc}
  608.    */
  609.   public NodeIterator getNodesLazily() throws RepositoryException {
  610.     ExtendedNode node = (ExtendedNode) getTarget();
  611.     return node.getNodesLazily();
  612.   }

  613.   @Override
  614.   public NodeIterator getNodesLazily(int pageSize) throws RepositoryException {
  615.     ExtendedNode node = (ExtendedNode) getTarget();
  616.     return node.getNodesLazily(pageSize);
  617.   }

  618.   @Override
  619.   public long getNodesCount() throws RepositoryException {
  620.     ExtendedNode node = (ExtendedNode) getTarget();
  621.     return node.getNodesCount();
  622.   }
  623. }