/**
   * Returns the relative path to the document directory in the request environment. If the document
   * or one of it's parent sections aren't found in the request environment, null is returned. The
   * path is relative to the request URL and may be empty if the request environment points to the
   * document. Otherwise the path ends with an "/" character.
   *
   * @param content the content document
   * @return the relative path to the document directory, or null if not in the request environment
   */
  private String getDocEnvPath(Content content) {
    RequestEnvironment env = context.getRequest().getEnvironment();
    ContentSection section = env.getSection();
    ContentDocument doc = env.getDocument();
    String path = "";

    if (doc != null) {
      if (doc.getId() == content.getId()) {
        return "";
      }
    } else if (section != null) {
      while (content != null) {
        if (section.getId() == content.getId()) {
          return path;
        }
        path = content.getName() + "/" + path;
        try {
          content = content.getParent();
        } catch (ContentException e) {
          LOG.error(e.getMessage());
          return null;
        }
      }
    }
    return null;
  }
  /** subclasses may envelope to monitor child property changes. */
  public void propertyChange(PropertyChangeEvent pce) {
    String propertyName = pce.getPropertyName();
    Object source = pce.getSource();

    synchronized (children) {
      if ("beanContext".equals(propertyName)
          && containsKey(source)
          && ((BCSChild) children.get(source)).isRemovePending()) {
        BeanContext bc = getBeanContextPeer();

        if (bc.equals(pce.getOldValue()) && !bc.equals(pce.getNewValue())) {
          remove(source, false);
        } else {
          ((BCSChild) children.get(source)).setRemovePending(false);
        }
      }
    }
  }
 public Node getNode() {
   if (node == null) {
     node = context.getAttribute("currentNode", Node.class);
     if (node == null) {
       node = getResource().getNode();
     }
   }
   return node;
 }
 /**
  * Returns a relative link to an object. If the specified path starts with '/' it is assumed to be
  * relative to the site root directory and will be modified to a page relative link. If the link
  * starts with a protocol (for example "http:") it is considered absolute and will not be
  * modified. Otherwise it is assumed to be relative to the document and may be modified to point
  * to the document directory.
  *
  * @param link the link URL
  * @return the resolved URL link
  */
 public String linkTo(String link) {
   if (link.indexOf(":") >= 0) {
     return link;
   } else if (link.startsWith("/")) {
     return context.getSitePath() + link.substring(1);
   } else if (link.startsWith("#")) {
     return link;
   } else {
     return docPath + link;
   }
 }
  /**
   * Returns the relative path to the document directory. The path is relative to the request URL
   * and may be empty if the request refers to an object in the document directory. Otherwise the
   * path ends with an "/" character.
   *
   * @param document the content document, or null
   * @return the relative path to the document directory
   */
  private String getDocPath(ContentDocument document) {
    String path;

    if (document == null) {
      return "";
    } else {
      path = getDocEnvPath(document);
      if (path == null) {
        path = context.getSitePath() + "liquidsite/content/" + document.getId() + "/";
      }
      return path;
    }
  }
 /**
  * Creates a new section template bean based upon the request environment section.
  *
  * @param context the bean context
  */
 SectionBean(BeanContext context) {
   this(context, context.getRequest().getEnvironment().getSection());
 }
  /**
   * The instantiateChild method is a convenience hook in BeanContext to simplify the task of
   * instantiating a Bean, nested, into a <tt>BeanContext</tt>.
   *
   * <p>The semantics of the beanName parameter are defined by java.beans.Beans.instantate.
   *
   * @param beanName the name of the Bean to instantiate within this BeanContext
   * @throws IOException if there is an I/O error when the bean is being deserialized
   * @throws ClassNotFoundException if the class identified by the beanName parameter is not found
   * @return the new object
   */
  public Object instantiateChild(String beanName) throws IOException, ClassNotFoundException {
    BeanContext bc = getBeanContextPeer();

    return Beans.instantiate(bc.getClass().getClassLoader(), beanName, bc);
  }
 /**
  * Uses the contexts 'resource' attribute for initialization (content.getResource()).
  *
  * @param context the scripting context (e.g. a JSP PageContext or a Groovy scripting context)
  */
 public void initialize(BeanContext context) {
   initialize(context, context.getResource());
 }
 /** Returns the handle to the 'Sling world' and all available services. */
 public SlingScriptHelper getSling() {
   if (sling == null) {
     sling = context.getAttribute("sling", SlingScriptHelper.class);
   }
   return sling;
 }