/* Selector.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.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import org.w3c.dom.Attr;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

/**
 * A single component of a location path.
 *
 * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
 */
public final class Selector
  extends Path
{

  public static final int ANCESTOR = 0;
  public static final int ANCESTOR_OR_SELF = 1;
  public static final int ATTRIBUTE = 2;
  public static final int CHILD = 3;
  public static final int DESCENDANT = 4;
  public static final int DESCENDANT_OR_SELF = 5;
  public static final int FOLLOWING = 6;
  public static final int FOLLOWING_SIBLING = 7;
  public static final int NAMESPACE = 8;
  public static final int PARENT = 9;
  public static final int PRECEDING = 10;
  public static final int PRECEDING_SIBLING = 11;
  public static final int SELF = 12;

  /**
   * Axis to select nodes in.
   */
  final int axis;

  /**
   * List of tests to perform on candidates.
   */
  final Test[] tests;

  public Selector(int axis, List tests)
  {
    this.axis = axis;
    int len = tests.size();
    this.tests = new Test[(len == 0) ? 1 : len];
    if (len > 0)
      tests.toArray(this.tests);
    else
      this.tests[0] = new NodeTypeTest((short) 0);
    if (axis == NAMESPACE && this.tests[0] instanceof NameTest)
      {
        NameTest nt = (NameTest) this.tests[0];
        this.tests[0] = new NamespaceTest(nt.qName, nt.anyLocalName, nt.any);
      }
  }

  /**
   * Returns the list of tests to perform on candidates.
   */
  public Test[] getTests()
  {
    return tests;
  }

  public boolean matches(Node context)
  {
    // If called directly, selector is the top level of the path
    return matches(context,
                   getContextPosition(context),
                   getContextSize(context));
  }
  
  boolean matches(Node context, int pos, int len)
  {
    short nodeType = context.getNodeType();
    switch (axis)
      {
      case CHILD:
        if (nodeType == Node.ATTRIBUTE_NODE)
          return false;
        break;
      case ATTRIBUTE:
      case NAMESPACE:
        if (nodeType != Node.ATTRIBUTE_NODE)
          return false;
        break;
      case DESCENDANT_OR_SELF:
        return true;
      default:
        return false;
      }
    for (int j = 0; j < tests.length && len > 0; j++)
      {
        Test test = tests[j];
        if (!test.matches(context, pos, len))
          return false;
      }
    return true;
  }

  private int getContextPosition(Node ctx)
  {
    int pos = 1;
    for (ctx = ctx.getPreviousSibling(); ctx != null;
         ctx = ctx.getPreviousSibling())
      {
        if (tests[0].matches(ctx, 1, 1))
          pos++;
      }
    return pos;
  }

  private int getContextSize(Node ctx)
  {
    if (ctx.getNodeType() == Node.ATTRIBUTE_NODE)
      {
        Node owner = ((Attr) ctx).getOwnerElement();
        return owner.getAttributes().getLength();
      }
    int count = 1;
    Node sib = ctx.getPreviousSibling();
    for (; sib != null; sib = sib.getPreviousSibling())
      {
        if (tests[0].matches(ctx, 1, 1))
          count++;
      }
    sib = ctx.getNextSibling();
    for (; sib != null; sib = sib.getNextSibling())
      {
        if (tests[0].matches(ctx, 1, 1))
          count++;
      }
    return count;
  }

  public Object evaluate(Node context, int pos, int len)
  {
    Set acc = new LinkedHashSet();
    addCandidates(context, acc);
    List candidates = new ArrayList(acc);
    List ret = filterCandidates(candidates, false);
    return ret;
  }

  Collection evaluate(Node context, Collection ns)
  {
    Set acc = new LinkedHashSet();
    for (Iterator i = ns.iterator(); i.hasNext(); )
      addCandidates((Node) i.next(), acc);
    List candidates = new ArrayList(acc);
    List ret = filterCandidates(candidates, true);
    return ret;
  }

  /**
   * Filter the given list of candidates according to the node tests.
   */
  List filterCandidates(List candidates, boolean cascade)
  {
    int len = candidates.size();
    int tlen = tests.length;
    if (tlen > 0 && len > 0)
      {
        // Present the result of each successful generation to the next test
        for (int j = 0; j < tlen && len > 0; j++)
          {
            Test test = tests[j];
            List successful = new ArrayList(len);
            for (int i = 0; i < len; i++)
              {
                Node node = (Node) candidates.get(i);
                if (cascade)
                  {
                    // Documents and DocumentFragments should be considered
                    // if part of a location path where the axis involves
                    // the SELF concept
                    short nodeType = node.getNodeType();
                    if ((nodeType == Node.DOCUMENT_NODE ||
                         nodeType == Node.DOCUMENT_FRAGMENT_NODE) &&
                        (axis == DESCENDANT_OR_SELF ||
                         axis == ANCESTOR_OR_SELF ||
                         axis == SELF) &&
                        (tests.length == 1 &&
                         tests[0] instanceof NodeTypeTest &&
                         ((NodeTypeTest) tests[0]).type == (short) 0))
                      {
                        successful.add(node);
                        continue;
                      }
                  }
                if (test.matches(node, i + 1, len))
                  successful.add(node);
              }
            candidates = successful;
            len = candidates.size();
          }
      }
    return candidates;
  }

  void addCandidates(Node context, Collection candidates)
  {
    // Build list of candidates
    switch (axis)
      {
      case CHILD:
        addChildNodes(context, candidates, false);
        break;
      case DESCENDANT:
        addChildNodes(context, candidates, true);
        break;
      case DESCENDANT_OR_SELF:
        candidates.add (context);
        addChildNodes(context, candidates, true);
        break;
      case PARENT:
        addParentNode(context, candidates, false);
        break;
      case ANCESTOR:
        addParentNode(context, candidates, true);
        break;
      case ANCESTOR_OR_SELF:
        candidates.add(context);
        addParentNode(context, candidates, true);
        break;
      case FOLLOWING_SIBLING:
        addFollowingNodes(context, candidates, false);
        break;
      case PRECEDING_SIBLING:
        addPrecedingNodes(context, candidates, false);
        break;
      case FOLLOWING:
        addFollowingNodes(context, candidates, true);
        break;
      case PRECEDING:
        addPrecedingNodes(context, candidates, true);
        break;
      case ATTRIBUTE:
        addAttributes(context, candidates);
        break;
      case NAMESPACE:
        addNamespaceAttributes(context, candidates);
        break;
      case SELF:
        candidates.add(context);
        break;
      }
  }

  void addChildNodes(Node context, Collection acc, boolean recurse)
  {
    Node child = context.getFirstChild();
    while (child != null)
      {
        acc.add(child);
        if (recurse)
          addChildNodes(child, acc, recurse);
        child = child.getNextSibling();
      }
  }

  void addParentNode(Node context, Collection acc, boolean recurse)
  {
    Node parent = (context.getNodeType() == Node.ATTRIBUTE_NODE) ?
      ((Attr) context).getOwnerElement() : context.getParentNode();
    if (parent != null)
      {
        acc.add(parent);
        if (recurse)
          addParentNode(parent, acc, recurse);
      }
  }

  void addFollowingNodes(Node context, Collection acc, boolean recurse)
  {
    if (context != null && recurse)
      addChildNodes(context, acc, true);
    Node cur = (context.getNodeType() == Node.ATTRIBUTE_NODE) ? null :
      context.getNextSibling();
    while (cur != null)
      {
        acc.add(cur);
        if (recurse)
          addChildNodes(cur, acc, true);
        cur = cur.getNextSibling();
      }
    if (recurse)
      {
        while (context != null)
          {
            context = (context.getNodeType() == Node.ATTRIBUTE_NODE) ?
              ((Attr) context).getOwnerElement() : context.getParentNode();
            if (context != null)
              {
                cur = context.getNextSibling();
                while (cur != null)
                  {
                    acc.add(cur);
                    if (recurse)
                      addChildNodes(cur, acc, true);
                    cur = cur.getNextSibling();
                  }
              }
          }
      }
  }

  void addPrecedingNodes(Node context, Collection acc, boolean recurse)
  {
    Node cur = (context.getNodeType() == Node.ATTRIBUTE_NODE) ? null :
      context.getPreviousSibling();
    while (cur != null)
      {
        acc.add(cur);
        if (recurse)
          addChildNodes(cur, acc, true);
        cur = cur.getPreviousSibling();
      }
    if (recurse)
      {
        cur = context;
        cur = (cur.getNodeType() == Node.ATTRIBUTE_NODE) ?
          ((Attr) cur).getOwnerElement() : cur.getParentNode();
        if (cur != null)
          addPrecedingNodes(cur, acc, recurse);
      }
  }

  void addAttributes(Node context, Collection acc)
  {
    NamedNodeMap attrs = context.getAttributes();
    if (attrs != null)
      {
        int attrLen = attrs.getLength();
        for (int i = 0; i < attrLen; i++)
          {
            Node attr = attrs.item(i);
            if (!isNamespaceAttribute(attr))
              {
                acc.add(attr);
              }
          }
      }
  }

  void addNamespaceAttributes(Node context, Collection acc)
  {
    NamedNodeMap attrs = context.getAttributes();
    if (attrs != null)
      {
        int attrLen = attrs.getLength();
        for (int i = 0; i < attrLen; i++)
          {
            Node attr = attrs.item(i);
            if (isNamespaceAttribute(attr))
              acc.add(attr);
          }
      }
  }

  final boolean isNamespaceAttribute(Node node)
  {
    String uri = node.getNamespaceURI();
    return (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(uri) ||
            XMLConstants.XMLNS_ATTRIBUTE.equals(node.getPrefix()) ||
            XMLConstants.XMLNS_ATTRIBUTE.equals(node.getNodeName()));
  }

  public Expr clone(Object context)
  {
    int len = tests.length;
    List tests2 = new ArrayList(len);
    for (int i = 0; i < len; i++)
      tests2.add(tests[i].clone(context));
    return new Selector(axis, tests2);
  }

  public boolean references(QName var)
  {
    for (int i = 0; i < tests.length; i++)
      {
        if (tests[i].references(var))
          return true;
      }
    return false;
  }

  public String toString()
  {
    StringBuffer buf = new StringBuffer();
    switch (axis)
      {
      case ANCESTOR:
        buf.append("ancestor::");
        break;
      case ANCESTOR_OR_SELF:
        buf.append("ancestor-or-self::");
        break;
      case ATTRIBUTE:
        if (tests.length == 0 ||
            (tests[0] instanceof NameTest))
          buf.append('@');
        else
          buf.append("attribute::");
        break;
      case CHILD:
        //buf.append("child::");
        break;
      case DESCENDANT:
        buf.append("descendant::");
        break;
      case DESCENDANT_OR_SELF:
        buf.append("descendant-or-self::");
        break;
      case FOLLOWING:
        buf.append("following::");
        break;
      case FOLLOWING_SIBLING:
        buf.append("following-sibling::");
        break;
      case NAMESPACE:
        buf.append("namespace::");
        break;
      case PARENT:
        if (tests.length == 0 ||
            (tests[0] instanceof NodeTypeTest &&
             ((NodeTypeTest) tests[0]).type == 0))
          return "..";
        buf.append("parent::");
        break;
      case PRECEDING:
        buf.append("preceding::");
        break;
      case PRECEDING_SIBLING:
        buf.append("preceding-sibling::");
        break;
      case SELF:
        if (tests.length == 0 ||
            (tests[0] instanceof NodeTypeTest &&
             ((NodeTypeTest) tests[0]).type == 0))
          return ".";
        buf.append("self::");
        break;
      }
    if (tests.length == 0)
      buf.append("[error]");
    else
      {
        for (int i = 0; i < tests.length; i++)
          buf.append(tests[i]);
      }
    return buf.toString();
  }
  
}
