/* 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 gnu.java.lang.CPStringBuilder;

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<? extends Test> 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;
  }


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

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

  /**
   * Filter the given list of candidates according to the node tests.
   */
  List<Node> filterCandidates(List<Node> 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<Node> successful = new ArrayList<Node>(len);
            for (int i = 0; i < len; i++)
              {
                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<Node> 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<Node> 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<Node> 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<Node> 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<Node> 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<Node> 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<Node> 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<Test> tests2 = new ArrayList<Test>(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()
  {
    CPStringBuilder buf = new CPStringBuilder();
    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();
  }

}
