/* NodeNumberNode.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.transform;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import javax.xml.transform.TransformerException;
import org.w3c.dom.Node;
import gnu.xml.xpath.Expr;
import gnu.xml.xpath.Pattern;
import gnu.xml.xpath.Selector;
import gnu.xml.xpath.UnionExpr;

/**
 * A template node representing the XSL <code>number</code> instruction
 * with no <code>value</code> expression, i.e. the value is computed from
 * the document position of the context node.
 *
 * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
 */
final class NodeNumberNode
  extends AbstractNumberNode
{

  static final int SINGLE = 0;
  static final int MULTIPLE = 1;
  static final int ANY = 2;

  final int level;
  final Pattern count;
  final Pattern from;

  NodeNumberNode(TemplateNode children, TemplateNode next,
                 int level, Pattern count, Pattern from,
                 TemplateNode format, String lang,
                 int letterValue, String groupingSeparator, int groupingSize)
  {
    super(children, next, format, lang, letterValue, groupingSeparator,
          groupingSize);
    this.level = level;
    this.count = count;
    this.from = from;
  }

  TemplateNode clone(Stylesheet stylesheet)
  {
    return new NodeNumberNode((children == null) ? null :
                              children.clone(stylesheet),
                              (next == null) ? null :
                              next.clone(stylesheet),
                              level,
                              (count == null) ? null :
                              (Pattern) count.clone(stylesheet),
                              (from == null) ? from :
                              (Pattern) from.clone(stylesheet),
                              format, lang, letterValue,
                              groupingSeparator, groupingSize);
  }

  int[] compute(Stylesheet stylesheet, Node context, int pos, int len)
    throws TransformerException
  {
    /*if (from != null)
      {
        Object ret = from.evaluate(context, pos, len);
        if (ret instanceof Collection)
          {
            Collection ns = (Collection) ret;
            if (ns.size() > 0)
              {
                List list = new ArrayList(ns);
                Collections.sort(list, documentOrderComparator);
                context = (Node) list.get(0);
              }
            else
              {
                return new int[0];
              }
          }
        else
          {
            return new int[0];
          }
      }*/
    Node current = context;
    switch (level)
      {
      case SINGLE:
        if (from == null)
          {
            while (context != null && !countMatches(current, context))
              {
                context = context.getParentNode();
              }
          }
        else
          {
            while (context != null && !countMatches(current, context) &&
                   !fromMatches(context))
              {
                context = context.getParentNode();
              }
          }
        return (context == null) ? new int[0] :
          new int[] { (context == current) ? pos : getIndex(current, context) };
      case MULTIPLE:
        List ancestors = new ArrayList();
        while (context != null)
          {
            if (countMatches(current, context))
              {
                if (from == null || fromMatches(context))
                  {
                    ancestors.add(context);
                  }
              }
            context = context.getParentNode();
          }
        Collections.sort(ancestors, documentOrderComparator);
        int[] ret = new int[ancestors.size()];
        for (int i = 0; i < ret.length; i++)
          {
            ret[i] = getIndex(current, (Node) ancestors.get(i));
          }
        return ret;
      case ANY:
        Expr preceding = new Selector(Selector.PRECEDING,
                                      Collections.EMPTY_LIST);
        Expr ancestorOrSelf = new Selector(Selector.ANCESTOR_OR_SELF,
                                           Collections.EMPTY_LIST);
        Expr any = new UnionExpr(preceding, ancestorOrSelf);
        Object eval = any.evaluate(context, pos, len);
        if (eval instanceof Collection)
          {
            Collection ns = (Collection) eval;
            List candidates = new ArrayList();
            for (Iterator i = ns.iterator(); i.hasNext(); )
              {
                Node candidate = (Node) i.next();
                if (countMatches(current, candidate))
                  {
                    candidates.add(candidate);
                    if (from != null && from.matches(candidate))
                      {
                        break;
                      }
                  }
              }
            return new int[] { candidates.size() };
          }
        return new int[0];
      default:
        throw new TransformerException("invalid level");
      }
  }

  boolean countMatches(Node current, Node node)
  {
    if (count == null)
      {
        int cnt = current.getNodeType();
        int nnt = node.getNodeType();
        if (cnt != nnt)
          {
            return false;
          }
        if (nnt == Node.ELEMENT_NODE || nnt == Node.ATTRIBUTE_NODE)
          {
            String curi = current.getNamespaceURI();
            String nuri = node.getNamespaceURI();
            if ((curi == null && nuri != null) ||
                (curi != null && !curi.equals(nuri)))
              {
                return false;
              }
            String cn = current.getLocalName();
            String nn = current.getLocalName();
            if (!cn.equals(nn))
              {
                return false;
              }
          }
        return true;
      }
    else
      {
        return count.matches(node);
      }
  }

  boolean fromMatches(Node node)
  {
    for (Node ctx = node.getParentNode(); ctx != null;
         ctx = ctx.getParentNode())
      {
        if (from.matches(ctx))
          {
            return true;
          }
      }
    return false;
  }

  int getIndex(Node current, Node node)
  {
    int index = 0;
    do
      {
        do
          {
            node = node.getPreviousSibling();
          }
        while (node != null && !countMatches(current, node));
        index++;
      }
    while (node != null);
    return index;
  }
  
}
