Package com.caucho.xpath

Source Code of com.caucho.xpath.XPath

/*
* Copyright (c) 1998-2011 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Resin Open Source is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
* of NON-INFRINGEMENT.  See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
*   Free SoftwareFoundation, Inc.
*   59 Temple Place, Suite 330
*   Boston, MA 02111-1307  USA
*
* @author Scott Ferguson
*/

package com.caucho.xpath;

import com.caucho.loader.EnvironmentLocal;
import com.caucho.util.LruCache;
import com.caucho.xpath.pattern.AbstractPattern;
import com.caucho.xpath.pattern.FromContext;

import org.w3c.dom.Node;

import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* Public facade for selecting nodes and creating match patterns.
*
* <p>Applications can select nodes directly from the XPath facade. 
* For example,
* <code><pre>
* Node verse = XPath.find("chapter/verse", node);
* </pre></code>
*
* <p>For greater efficiency, applications can also precompile the
* match patterns.
* <code><pre>
* Pattern pattern = XPath.parseSelect("chapter/verse");
* Node verse = pattern.find(node);
* </pre></code>
*
* <p>XPath can also return values based on XPath expressions, following
* the XPath expression syntax.  Applications can use the expressions for
* the equivalent of xsl:value-of
* <code><pre>
* Expr expr = XPath.parseExpr("chapter/verse/@id + 1");
* double value = expr.evalNumber(node);
* </pre></code>
*
* <p>To support the XPath pattern variables, XPath uses an environment
* object.  Most applications will not need to use it.
*/
public class XPath {
  private static final Logger log
    = Logger.getLogger(XPath.class.getName());

  private static EnvironmentLocal<LruCache<String,Pattern>> _matchCache
    = new EnvironmentLocal<LruCache<String,Pattern>>();
 
  private static EnvironmentLocal<LruCache<String,Pattern>> _selectCache
    = new EnvironmentLocal<LruCache<String,Pattern>>();
 
  private static EnvironmentLocal<LruCache<String,Expr>> _exprCache
    = new EnvironmentLocal<LruCache<String,Expr>>();

  private XPath()
  {
  }

  /**
   * Finds a node based on an XPath pattern.  The pattern is relative
   * to the node so <code>XPath.find("child", node)</code> will find children,
   * not grandchildren.
   *
   * @param query XPath select pattern.
   * @param node XML node to start searching from.
   * @return The first matching node in document order.
   */
  public static Node find(String query, Node node)
    throws XPathException
  {
    Pattern pattern = parseSelect(query);

    return (Node) pattern.find(node);
  }

  /**
   * Selects all node matching an XPath pattern
   *
   * @param query XPath select pattern.
   * @param node XML node to start searching from.
   * @return An iterator of nodes matching the pattern.
   */
  public static Iterator select(String query, Node node)
    throws XPathException
  {
    Pattern pattern = parseSelect(query);

    return pattern.select(node);
  }

  /**
   * Create a node selection pattern.  The pattern matches relative
   * to the current node.
   *
   * @param query XPath select pattern.
   * @return a pattern that can later select nodes.
   */
  public static Pattern parseSelect(String query)
    throws XPathParseException
  {
    LruCache<String,Pattern> cache = _selectCache.get();
    if (cache == null)
      cache = new LruCache<String,Pattern>(128);
   
    Pattern pattern = cache.get(query);

    if (pattern == null) {
      pattern = parseSelect(query, null);
      cache.put(query, pattern);
    }

    return pattern;
  }

  /**
   * Create a node selection pattern.  The pattern matches relative
   * to the current node.
   *
   * <p>XSLT uses this version of parseSelect for proper namespace
   * matching.
   *
   * @param query XPath select pattern.
   * @param namespace the appropriate namespace mappings
   *
   * @return a pattern that can later select nodes.
   */
  public static Pattern parseSelect(String query, NamespaceContext namespace)
    throws XPathParseException
  {
    XPathParser parser = new XPathParser(query, namespace);

    AbstractPattern pattern = parser.parseSelect();

    if (log.isLoggable(Level.FINER))
      log.finest("select: " + pattern);

    return new Pattern(pattern);
  }

  /**
   * Create a node match pattern.  Match patterns are intended to test
   * if a node matches the pattern.  They do not work well for finding or
   * selecting patterns.  Essentially, a match pattern of 'foo[@bar]' is
   * equivalent to a select pattern of '//foo[@bar]', but with less overhead.
   *
   * @param query XPath match pattern.
   * @return a pattern that can later be used for isMatch.
   */
  public static Pattern parseMatch(String query)
    throws XPathParseException
  {
    LruCache<String,Pattern> cache = _matchCache.get();
    if (cache == null)
      cache = new LruCache<String,Pattern>(128);
   
    Pattern pattern = cache.get(query);

    if (pattern == null) {
      pattern = parseMatch(query, null);
      cache.put(query, pattern);
    }

    return pattern;
  }

  /**
   * Create a node match pattern.  Match patterns are intended to test
   * if a node matches the pattern.  They do not work well for finding or
   * selecting patterns.  Essentially, a match pattern of 'foo[@bar]' is
   * equivalent to a select pattern of '//foo[@bar]', but with less overhead.
   *
   * @param query XPath match pattern.
   * @param namespace the appropriate namespace mappings.
   *
   * @return a pattern that can later be used for isMatch.
   */
  public static Pattern parseMatch(String query, NamespaceContext namespace)
    throws XPathParseException
  {
    XPathParser parser = new XPathParser(query, namespace);

    AbstractPattern pattern = parser.parseMatch();

    if (log.isLoggable(Level.FINER))
      log.finest("match: " + pattern);

    return new Pattern(pattern);
  }

  /**
   * Evaluates an XPath expression, returning a string.  evalString works
   * like the XSL <code>value-of</code> element.
   *
   * <p>For example, to get the value of an attribute use:
   *
   * <code><pre>
   * String value = XPath.evalString("@id", node);
   * </pre></code>
   *
   * @param query XPath expression
   * @param node the node context
   *
   * @return the string result of the expression.
   */
  public static String evalString(String query, Node node)
    throws XPathException
  {
    Expr expr = parseExpr(query);

    return expr.evalString(node);
  }

  /**
   * Evaluates an XPath expression, returning a double.
   *
   * @param query XPath expression
   * @param node the node context
   *
   * @return the number result of the expression.
   */
  public static double evalNumber(String query, Node node)
    throws XPathException
  {
    Expr expr = parseExpr(query);

    return expr.evalNumber(node);
  }

  /**
   * Evaluates an XPath expression, returning a boolean.
   *
   * @param query XPath expression
   * @param node the node context
   *
   * @return the boolean result of the expression.
   */
  public static boolean evalBoolean(String query, Node node)
    throws XPathException
  {
    Expr expr = parseExpr(query);

    return expr.evalBoolean(node);
  }

  /**
   * Evaluates an XPath expression, returning an object
   *
   * @param query XPath expression
   * @param node the node context
   *
   * @return the result of the expression.
   */
  public static Object evalObject(String query, Node node)
    throws XPathException
  {
    Expr expr = parseExpr(query);

    return expr.evalObject(node);
  }

  /**
   * Parses an XPath expression for later evaluation.
   *
   * @param query XPath expression
   * @return the result of the expression.
   */
  public static Expr parseExpr(String query)
    throws XPathParseException
  {
    LruCache<String,Expr> cache = _exprCache.get();
    if (cache == null) {
      cache = new LruCache<String,Expr>(128);
      _exprCache.set(cache);
    }
   
    Expr expr = cache.get(query);

    if (expr == null) {
      expr = parseExpr(query, null);
      cache.put(query, expr);
    }

    return expr;
  }

  /**
   * Parses an XPath expression for later evaluation.
   *
   * @param query XPath expression
   * @param namespace namespace context
   *
   * @return the compiled expression
   */
  public static Expr parseExpr(String query, NamespaceContext namespace)
    throws XPathParseException
  {
    XPathParser parser = new XPathParser(query, namespace);

    Expr expr = parser.parseExpr();

    if (log.isLoggable(Level.FINER))
      log.finest("expr: " + expr);

    return expr;
  }

  /**
   * Parses an XPath expression for later evaluation.
   *
   * @param query XPath expression
   * @param namespace namespace context
   * @param nodeList containing nodeList pattern
   *
   * @return the compiled expression
   */
  public static Expr parseExpr(String query, NamespaceContext namespace,
                               AbstractPattern nodeList)
    throws XPathParseException
  {
    XPathParser parser = new XPathParser(query, namespace);

    Expr expr = parser.parseExpr(new FromContext(), nodeList);

    if (expr != null)
      expr.setListContext(nodeList);

    if (log.isLoggable(Level.FINER))
      log.finest("expr: " + expr);

    return expr;
  }

  /**
   * Creates a new variable environment.
   */
  public static Env createEnv()
  {
    return Env.create();
  }

  /**
   * Creates a new variable environment based on an old environment.
   *
   * <p>This lets environments share globals even through function calls.
   */
  public static Env createEnv(Env global)
  {
    Env env = Env.create();

    env.init(global);

    return env;
  }

  /**
   * Creates a new variable environment based on an old environment.
   *
   * <p>This lets environments share globals even through function calls.
   */
  public static Env createCall(Env parent)
  {
    Env env = Env.create();

    env.initMacro(parent);

    return env;
  }

  /**
   * Free an environment.
   */
  public static void freeEnv(Env env)
  {
    // env.free();
  }
}
TOP

Related Classes of com.caucho.xpath.XPath

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.