/* Expr.java -- 
   Copyright (C) 2004,2006 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath 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, or (at your option)
any later version.

GNU Classpath 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.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */

package gnu.xml.xpath;

import java.io.IOException;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.StringTokenizer;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * An XPath expression.
 * This can be evaluated in the context of a node to produce a result.
 *
 * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
 */
public abstract class Expr
  implements XPathExpression
{

  protected static final Comparator documentOrderComparator =
    new DocumentOrderComparator();

  protected static final DecimalFormat decimalFormat =
    new DecimalFormat("####################################################" +
                      ".####################################################",
                      new DecimalFormatSymbols(Locale.US));

  public Object evaluate(Object item, QName returnType)
    throws XPathExpressionException
  {
    Object ret = null;
    Node context = null;
    if (item instanceof Node)
      {
        context = (Node) item;
        ret = evaluate(context, 1, 1);
        if (XPathConstants.STRING == returnType &&
            !(ret instanceof String))
          {
            ret = _string(context, ret);
          }
        else if (XPathConstants.NUMBER == returnType &&
                 !(ret instanceof Double))
          {
            ret = new Double(_number(context, ret));
          }
        else if (XPathConstants.BOOLEAN == returnType &&
                 !(ret instanceof Boolean))
          {
            ret = _boolean(context, ret) ? Boolean.TRUE : Boolean.FALSE;
          }
        else if (XPathConstants.NODE == returnType)
          {
            if (ret instanceof Collection)
              {
                Collection ns = (Collection) ret;
                switch (ns.size())
                  {
                  case 0:
                    ret = null;
                    break;
                  case 1:
                    ret = (Node) ns.iterator().next();
                    break;
                  default:
                    throw new XPathExpressionException("multiple nodes in node-set");
                  }
              }
            else if (ret != null)
              {
                throw new XPathExpressionException("return value is not a node-set");
              }
          }
        else if (XPathConstants.NODESET == returnType)
          {
            if (ret != null && !(ret instanceof Collection))
              {
                throw new XPathExpressionException("return value is not a node-set");
              }
          }
      }
    return ret;
  }

  public String evaluate(Object item)
    throws XPathExpressionException
  {
    return (String) evaluate(item, XPathConstants.STRING); 
  }

  public Object evaluate(InputSource source, QName returnType)
    throws XPathExpressionException
  {
    try
      {
        DocumentBuilderFactory factory =
          new gnu.xml.dom.JAXPFactory();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document doc = builder.parse(source);
        return evaluate(doc, returnType);
      }
    catch (ParserConfigurationException e)
      {
        throw new XPathExpressionException(e); 
      }
    catch (SAXException e)
      {
        throw new XPathExpressionException(e); 
      }
    catch (IOException e)
      {
        throw new XPathExpressionException(e); 
      }
  }

  public String evaluate(InputSource source)
    throws XPathExpressionException
  {
    return (String) evaluate(source, XPathConstants.STRING);
  }

  public abstract Object evaluate(Node context, int pos, int len);

  public abstract Expr clone(Object context);

  public abstract boolean references(QName var);
  
  /* -- 4.1 Node Set Functions -- */

  /**
   * The id function selects elements by their unique ID.
   * When the argument to id is of type node-set, then the result is
   * the union of the result of applying id to the string-value of each of
   * the nodes in the argument node-set. When the argument to id is of any
   * other type, the argument is converted to a string as if by a call to
   * the string function; the string is split into a whitespace-separated
   * list of tokens (whitespace is any sequence of characters matching the
   * production S); the result is a node-set containing the elements in the
   * same document as the context node that have a unique ID equal to any of
   * the tokens in the list.
   */
  public static Collection _id(Node context, Object object)
  {
    Set ret = new HashSet();
    if (object instanceof Collection)
      {
        Collection nodeSet = (Collection) object;
        for (Iterator i = nodeSet.iterator(); i.hasNext(); )
          {
            String string = stringValue((Node) i.next());
            ret.addAll(_id (context, string));
          }
      }
    else
      {
        Document doc = (context instanceof Document) ? (Document) context :
          context.getOwnerDocument();
        String string = _string(context, object);
        StringTokenizer st = new StringTokenizer(string, " \t\r\n");
        while (st.hasMoreTokens())
          {
            Node element = doc.getElementById(st.nextToken());
            if (element != null)
              {
                ret.add(element);
              }
          }
      }
    return ret;
  }

  /**
   * The local-name function returns the local part of the expanded-name of
   * the node in the argument node-set that is first in document order. If
   * the argument node-set is empty or the first node has no expanded-name,
   * an empty string is returned. If the argument is omitted, it defaults to
   * a node-set with the context node as its only member.
   */
  public static String _local_name(Node context, Collection nodeSet)
  {
    if (nodeSet == null || nodeSet.isEmpty())
      return "";
    Node node = firstNode(nodeSet);
    String ret = node.getLocalName();
    return (ret == null) ? "" : ret;
  }

  /**
   * The namespace-uri function returns the namespace URI of the
   * expanded-name of the node in the argument node-set that is first in
   * document order. If the argument node-set is empty, the first node has
   * no expanded-name, or the namespace URI of the expanded-name is null, an
   * empty string is returned. If the argument is omitted, it defaults to a
   * node-set with the context node as its only member.
   */
  public static String _namespace_uri(Node context, Collection nodeSet)
  {
    if (nodeSet == null || nodeSet.isEmpty())
      return "";
    Node node = firstNode(nodeSet);
    String ret = node.getNamespaceURI();
    return (ret == null) ? "" : ret;
  }
  
  /**
   * The name function returns a string containing a QName representing the
   * expanded-name of the node in the argument node-set that is first in
   * document order. The QName must represent the expanded-name with respect
   * to the namespace declarations in effect on the node whose expanded-name
   * is being represented. Typically, this will be the QName that occurred
   * in the XML source. This need not be the case if there are namespace
   * declarations in effect on the node that associate multiple prefixes
   * with the same namespace. However, an implementation may include
   * information about the original prefix in its representation of nodes;
   * in this case, an implementation can ensure that the returned string is
   * always the same as the QName used in the XML source. If the argument
   * node-set is empty or the first node has no expanded-name, an empty
   * string is returned. If the argument it omitted, it defaults to a
   * node-set with the context node as its only member.
   */
  public static String _name(Node context, Collection nodeSet)
  {
    if (nodeSet == null || nodeSet.isEmpty())
      return "";
    Node node = firstNode(nodeSet);
    String ret = null;
    switch (node.getNodeType())
      {
      case Node.ATTRIBUTE_NODE:
      case Node.ELEMENT_NODE:
      case Node.PROCESSING_INSTRUCTION_NODE:
        ret = node.getNodeName();
      }
    return (ret == null) ? "" : ret;
  }

  /**
   * Returns the first node in the set in document order.
   */
  static Node firstNode(Collection nodeSet)
  {
    List list = new ArrayList(nodeSet);
    Collections.sort(list, documentOrderComparator);
    return (Node) list.get(0);
  }

  /* -- 4.2 String Functions -- */

  /**
   * Implementation of the XPath <code>string</code> function.
   */
  public static String _string(Node context, Object object)
  {
    if (object == null)
      {
        return stringValue(context);
      }
    if (object instanceof String)
      {
        return (String) object;
      }
    if (object instanceof Boolean)
      {
        return object.toString();
      }
    if (object instanceof Double)
      {
        double d = ((Double) object).doubleValue();
        if (Double.isNaN(d))
          {
            return "NaN";
          }
        else if (d == 0.0d)
          {
            return "0";
          }
        else if (Double.isInfinite(d))
          {
            if (d < 0)
              {
                return "-Infinity";
              }
            else
              {
                return "Infinity";
              }
          }
        else
          {
            String ret = decimalFormat.format(d);
            if (ret.endsWith (".0"))
              { 
                ret = ret.substring(0, ret.length() - 2);
              }
            return ret;
          }
      }
    if (object instanceof Collection)
      {
        Collection nodeSet = (Collection) object;
        if (nodeSet.isEmpty())
          {
            return "";
          }
        Node node = firstNode(nodeSet);
        return stringValue(node);
      }
    throw new IllegalArgumentException(object.toString());
  }

  /* -- 4.3 Boolean Functions -- */
  
  /**
   * Implementation of the XPath <code>boolean</code> function.
   */
  public static boolean _boolean(Node context, Object object)
  {
    if (object instanceof Boolean)
      {
        return ((Boolean) object).booleanValue();
      }
    if (object instanceof Double)
      {
        Double value = (Double) object;
        if (value.isNaN())
          return false;
        return value.doubleValue() != 0.0;
      }
    if (object instanceof String)
      {
        return ((String) object).length() != 0;
      }
    if (object instanceof Collection)
      {
        return ((Collection) object).size() != 0;
      }
    return false; // TODO user defined types
  }

  /* -- 4.4 Number Functions -- */

  /**
   * Implementation of the XPath <code>number</code> function.
   */
  public static double _number(Node context, Object object)
  {
    if (object == null)
      {
        object = Collections.singleton(context);
      }
    if (object instanceof Double)
      {
        return ((Double) object).doubleValue();
      }
    if (object instanceof Boolean)
      {
        return ((Boolean) object).booleanValue() ? 1.0 : 0.0;
      }
    if (object instanceof Collection)
      {
        // Convert node-set to string
        object = stringValue((Collection) object);
      }
    if (object instanceof String)
      {
        String string = ((String) object).trim();
        try
          {
            return Double.parseDouble(string);
          }
        catch (NumberFormatException e)
          {
            return Double.NaN;
          }
      }
    return Double.NaN; // TODO user-defined types
  }

  /**
   * Computes the XPath string-value of the specified node-set.
   */
  public static String stringValue(Collection nodeSet)
  {
    StringBuffer buf = new StringBuffer();
    for (Iterator i = nodeSet.iterator(); i.hasNext(); )
      {
        buf.append(stringValue((Node) i.next()));
      }
    return buf.toString();
  }

  /**
   * Computes the XPath string-value of the specified node.
   */
  public static String stringValue(Node node)
  {
    return stringValue(node, false);
  }
  
  static String stringValue(Node node, boolean elementMode)
  {
    switch (node.getNodeType())
      {
      case Node.DOCUMENT_NODE: // 5.1 Root Node
      case Node.DOCUMENT_FRAGMENT_NODE:
      case Node.ELEMENT_NODE: // 5.2 Element Nodes
        StringBuffer buf = new StringBuffer();
        for (Node ctx = node.getFirstChild(); ctx != null;
             ctx = ctx.getNextSibling())
          {
            buf.append(stringValue(ctx, true));
          }
        return buf.toString();
      case Node.TEXT_NODE: // 5.7 Text Nodes
      case Node.CDATA_SECTION_NODE:
        return node.getNodeValue();
      case Node.ATTRIBUTE_NODE: // 5.3 Attribute Nodes
      case Node.PROCESSING_INSTRUCTION_NODE: // 5.5 Processing Instruction
      case Node.COMMENT_NODE: // 5.6 Comment Nodes
        if (!elementMode)
          {
            return node.getNodeValue();
          }
      default:
        return "";
      }
  }

  static int intValue(Object val)
  {
    if (val instanceof Double)
      {
        Double d = (Double) val;
        return d.isNaN() ? 0 : d.intValue();
      }
    else
      return (int) Math.ceil(_number(null, val));
  }

}
