/* Expr.java -- 
   Copyright (C) 2004 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., 59 Temple Place, Suite 330, Boston, MA
02111-1307 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);
  
  /* -- 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)
  {
    Node node = (nodeSet == null || nodeSet.size() == 0) ? context :
      firstNode(nodeSet);
    return node.getLocalName();
  }

  /**
   * 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)
  {
    Node node = (nodeSet == null || nodeSet.size() == 0) ? context :
      firstNode(nodeSet);
    return node.getNamespaceURI();
  }
  
  /**
   * 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)
  {
    Node node = (nodeSet == null || nodeSet.size() == 0) ? context :
      firstNode(nodeSet);
    switch (node.getNodeType())
      {
      case Node.ATTRIBUTE_NODE:
      case Node.ELEMENT_NODE:
      case Node.PROCESSING_INSTRUCTION_NODE:
        return node.getNodeName();
      default:
        return "";
      }
  }

  /**
   * 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)
      {
        return ((Double) object).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 "";
      }
  }

}
