/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package freemarker.ext.jdom;

import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;

import org.jaxen.Context;
import org.jaxen.JaxenException;
import org.jaxen.NamespaceContext;
import org.jaxen.jdom.JDOMXPath;
import org.jdom.Attribute;
import org.jdom.CDATA;
import org.jdom.Comment;
import org.jdom.DocType;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.EntityRef;
import org.jdom.Namespace;
import org.jdom.ProcessingInstruction;
import org.jdom.Text;
import org.jdom.output.XMLOutputter;

import freemarker.template.SimpleScalar;
import freemarker.template.TemplateCollectionModel;
import freemarker.template.TemplateHashModel;
import freemarker.template.TemplateMethodModel;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
import freemarker.template.TemplateModelIterator;
import freemarker.template.TemplateScalarModel;
import freemarker.template.TemplateSequenceModel;

/**
 * Provides a template for wrapping JDOM objects. It is capable of storing not only
 * a single JDOM node, but a list of JDOM nodes at once (hence the name).
 * Each node is an instance of any of the core JDOM node classes (except namespaces,
 * which are not supported at the moment), or String for representing text.
 * See individual method documentation for exact details on how the class works. In
 * short:
 * <ul>
 * <li>{@link #getAsString()} will render all contained nodes as XML fragment,
 * <li>{@link #exec(List)} provides full XPath functionality implemented on top of
 * the <a href="http://www.jaxen.org">Jaxen</a> library,</li>
 * <li>{@link #get(String)} provides node traversal, copying and filtering - somewhat
 * less expressive than XPath, however it does not require the external library and
 * it evaluates somewhat faster</li>
 * <li>being a {@link TemplateCollectionModel} allows to iterate the contained node list, and</li>
 * <li>being a {@link TemplateSequenceModel} allows to access the contained nodes by index and query the node count.</li>
 * </ul>
 * 
 * <p><b>Note:</b> There is a JDOM independent re-implementation of this class:
 *   {@link freemarker.ext.xml.NodeListModel freemarker.ext.xml.NodeListModel}
 * 
 * @deprecated Use {@link freemarker.ext.dom.NodeModel} instead.
 */
@Deprecated
public class NodeListModel
implements
    TemplateHashModel,
    TemplateMethodModel,
    TemplateCollectionModel,
    TemplateSequenceModel,
    TemplateScalarModel {
    private static final AttributeXMLOutputter OUTPUT = new AttributeXMLOutputter();
    // A convenience singleton for representing a node list without nodes.
    private static final NodeListModel EMPTY = new NodeListModel(null, false);

    // Cache of already parsed XPath expressions
    private static final Map XPATH_CACHE = new WeakHashMap();

    private static final NamedNodeOperator NAMED_CHILDREN_OP = new NamedChildrenOp();
    private static final NamedNodeOperator NAMED_ATTRIBUTE_OP = new NamedAttributeOp();
    private static final NodeOperator ALL_ATTRIBUTES_OP = new AllAttributesOp();
    private static final NodeOperator ALL_CHILDREN_OP = new AllChildrenOp();
    private static final Map OPERATIONS = createOperations();
    private static final Map SPECIAL_OPERATIONS = createSpecialOperations();
    private static final int SPECIAL_OPERATION_COPY = 0;
    private static final int SPECIAL_OPERATION_UNIQUE = 1;
    private static final int SPECIAL_OPERATION_FILTER_NAME = 2;
    private static final int SPECIAL_OPERATION_FILTER_TYPE = 3;
    private static final int SPECIAL_OPERATION_QUERY_TYPE = 4;
    private static final int SPECIAL_OPERATION_REGISTER_NAMESPACE = 5;
    private static final int SPECIAL_OPERATION_PLAINTEXT = 6;

    // The contained nodes
    private final List nodes;
    private final Map namespaces;

    /**
     * Creates a node list that holds a single {@link Document} node.
     */
    public NodeListModel(Document document) {
        nodes = document == null ? Collections.EMPTY_LIST : Collections.singletonList(document);
        namespaces = new HashMap();
    }

    /**
     * Creates a node list that holds a single {@link Element} node.
     */
    public NodeListModel(Element element) {
        nodes = element == null ? Collections.EMPTY_LIST : Collections.singletonList(element);
        namespaces = new HashMap();
    }

    private NodeListModel(Object object, Map namespaces) {
        nodes = object == null ? Collections.EMPTY_LIST : Collections.singletonList(object);
        this.namespaces = namespaces;
    }

    /**
     * Creates a node list that holds a list of nodes.
     * @param nodes the list of nodes this template should hold. The created template
     * will copy the passed nodes list, so changes to the passed list will not affect
     * the model.
     */
    public NodeListModel(List nodes) {
        this(nodes, true);
    }

    /**
     * Creates a node list that holds a list of nodes.
     * @param nodes the list of nodes this template should hold.
     * @param copy if true, the created template will copy the passed nodes list,
     * so changes to the passed list will not affect the model. If false, the model
     * will reference the passed list and will sense changes in it, although no
     * operations on the list will be synchronized.
     */
    public NodeListModel(List nodes, boolean copy) {
        this.nodes = copy && nodes != null ? new ArrayList(nodes) : (nodes == null ? Collections.EMPTY_LIST : nodes);
        namespaces = new HashMap();
    }

    private NodeListModel(List nodes, Map namespaces) {
        this.nodes = nodes == null ? Collections.EMPTY_LIST : nodes;
        this.namespaces = namespaces;
    }

    private static final NodeListModel createNodeListModel(List list, Map namespaces) {
        if (list == null || list.isEmpty()) {
            if (namespaces.isEmpty()) {
                return EMPTY;
            } else {
                return new NodeListModel(Collections.EMPTY_LIST, namespaces);
            }
        }
        if (list.size() == 1) return new NodeListModel(list.get(0), namespaces);
        return new NodeListModel(list, namespaces);
    }

    /**
     * Returns true if this model contains no nodes.
     */
    public boolean isEmpty() {
        return nodes.isEmpty();
    }

    /**
     * This method returns the string resulting from concatenation
     * of string representations of its nodes. Each node is rendered using its XML
     * serialization format, while text (String) is rendered as itself. This greatly
     * simplifies creating XML-transformation templates, as to output a node contained
     * in variable x as XML fragment, you simply write ${x} in the template.
     */
    public String getAsString()
    throws TemplateModelException {
        if (isEmpty())
            return "";

        java.io.StringWriter sw = new java.io.StringWriter(nodes.size() * 128);
        try {
            for (Iterator i = nodes.iterator(); i.hasNext(); ) {
                Object node = i.next();
                if (node instanceof Element)
                    OUTPUT.output((Element) node, sw);
                else if (node instanceof Attribute)
                    OUTPUT.output((Attribute) node, sw);
                else if (node instanceof String)
                    sw.write(OUTPUT.escapeElementEntities(node.toString()));
                else if (node instanceof Text)
                    OUTPUT.output((Text) node, sw);
                else if (node instanceof Document)
                    OUTPUT.output((Document) node, sw);
                else if (node instanceof ProcessingInstruction)
                    OUTPUT.output((ProcessingInstruction) node, sw);
                else if (node instanceof Comment)
                    OUTPUT.output((Comment) node, sw);
                else if (node instanceof CDATA)
                    OUTPUT.output((CDATA) node, sw);
                else if (node instanceof DocType)
                    OUTPUT.output((DocType) node, sw);
                else if (node instanceof EntityRef)
                    OUTPUT.output((EntityRef) node, sw);
                else
                    throw new TemplateModelException(node.getClass().getName() + " is not a core JDOM class");
            }
        } catch (IOException e) {
            throw new TemplateModelException(e.getMessage());
        }
        return sw.toString();
    }


    /**
     * Provides node list traversal as well as special functions: filtering by name,
     * filtering by node type, shallow-copying, and duplicate removal.
     * While not as powerful as the full XPath support built into the
     * {@link #exec(List)} method, it does not require the external Jaxen
     * library to be present at run time. Below are listed the recognized keys.
     * In key descriptions, "applicable to this-and-that node type" means that if
     * a key is applied to a node list that contains a node of non-applicable type
     * a TemplateMethodModel will be thrown. However, you can use <tt>_ftype</tt>
     * key to explicitly filter out undesired node types prior to applying the
     * restricted-applicability key. Also "current nodes" means nodes contained in this
     * set.
     * <ul>
     *    <li><tt>*</tt> or <tt>_children</tt>: all direct element children of current nodes (non-recursive). Applicable
     *  to element and document nodes.</li>
     *    <li><tt>@*</tt> or <tt>_attributes</tt>: all attributes of current nodes. Applicable to elements only.</li>
     *    <li><tt>_content</tt> the complete content of current nodes (non-recursive).
     *  Applicable to elements and documents.</li>
     *    <li><tt>_text</tt>: the text of current nodes, one string per node (non-recursive).
     *  Applicable to elements, attributes, comments, processing instructions (returns its data)
     *  and CDATA sections. The reserved XML characters ('&lt;' and '&amp;') are escaped.</li>
     *    <li><tt>_plaintext</tt>: same as <tt>_text</tt>, but does not escape any characters,
     *  and instead of returning a NodeList returns a SimpleScalar.</li>
     *    <li><tt>_name</tt>: the names of current nodes, one string per node (non-recursive).
     *  Applicable to elements and attributes (returns their local name), 
     *  entities, processing instructions (returns its target), doctypes 
     * (returns its public ID)</li>
     *    <li><tt>_qname</tt>: the qualified names of current nodes in <tt>[namespacePrefix:]localName</tt>
     * form, one string per node (non-recursive). Applicable to elements and attributes</li>
     *    <li><tt>_cname</tt>: the canonical names of current nodes (namespace URI + local name),
     * one string per node (non-recursive). Applicable to elements and attributes</li>
     *    <li><tt>_nsprefix</tt>: namespace prefixes of current nodes,
     * one string per node (non-recursive). Applicable to elements and attributes</li>
     *    <li><tt>_nsuri</tt>: namespace URIs of current nodes,
     * one string per node (non-recursive). Applicable to elements and attributes</li>
     *    <li><tt>_parent</tt>: parent elements of current nodes. Applicable to element, attribute, comment,
     *  entity, processing instruction.</li>
     *    <li><tt>_ancestor</tt>: all ancestors up to root element (recursive) of current nodes. Applicable
     *  to same node types as <tt>_parent</tt>.</li>
     *    <li><tt>_ancestorOrSelf</tt>: all ancestors of current nodes plus current nodes. Applicable
     *  to same node types as <tt>_parent</tt>.</li>
     *    <li><tt>_descendant</tt>: all recursive descendant element children of current nodes. Applicable to
     *  document and element nodes.
     *    <li><tt>_descendantOrSelf</tt>: all recursive descendant element children of current nodes
     *  plus current nodes. Applicable to document and element nodes.
     *    <li><tt>_document</tt>: all documents the current nodes belong to.
     *  Applicable to all nodes except text.
     *    <li><tt>_doctype</tt>: doctypes of the current nodes.
     *  Applicable to document nodes only.
     *    <li><tt>_fname</tt>: is a filter-by-name template method model. When called,
     *  it will yield a node list that contains only those current nodes whose name
     *  matches one of names passed as argument. Attribute names should NOT be prefixed with the
     *  at sign (@). Applicable on all node types, however has no effect on unnamed nodes.</li>
     *    <li><tt>_ftype</tt>: is a filter-by-type template method model. When called,
     *  it will yield a node list that contains only those current nodes whose type matches one
     *  of types passed as argument. You should pass a single string to this method
     *  containing the characters of all types to keep. Valid characters are:
     *  e (Element), a (Attribute), n (Entity), d (Document), t (DocType),
     *  c (Comment), p (ProcessingInstruction), x (text). If the string anywhere contains
     *  the exclamation mark (!), the filter's effect is inverted.</li>
     *    <li><tt>_type</tt>: Returns a one-character String SimpleScalar containing
     *    the typecode of the first node in the node list. Valid characters are:
     *  e (Element), a (Attribute), n (Entity), d (Document), t (DocType),
     *  c (Comment), p (ProcessingInstruction), x (text). If the type of the node
     *  is unknown, returns '?'. If the node list is empty, returns an empty string scalar.</li>
     *    <li><tt>_unique</tt>: a copy of the current nodes that keeps only the
     *  first occurrence of every node, eliminating duplicates. Duplicates can
     *  occur in the node list by applying uptree-traversals <tt>_parent</tt>,
     *  <tt>_ancestor</tt>, <tt>_ancestorOrSelf</tt>, and <tt>_document</tt>.
     *  I.e. <tt>foo._children._parent</tt> will return a node list that has
     *  duplicates of nodes in foo - each node will have the number of occurrences
     *  equal to the number of its children. In these cases, use
     *  <tt>foo._children._parent._unique</tt> to eliminate duplicates. Applicable
     *  to all node types.</li>
     *    <li><tt>_copy</tt>: a copy of the current node list. It is a shallow copy that
     *  shares the underlying node list with this node list, however it has a
     *  separate namespace registry, so it can be used to guarantee that subsequent
     *  changes to the set of registered namespaces does not affect the node lists
     *  that were used to create this node list. Applicable to all node types.</li>
     *    <li><tt>_registerNamespace(prefix, uri)</tt>: register a XML namespace
     *  with the specified prefix and URI for the current node list and all node
     *  lists that are derived from the current node list. After registering,
     *  you can use the <tt>nodelist["prefix:localname"]</tt> or
     *  <tt>nodelist["@prefix:localname"]</tt> syntaxes to reach elements and
     *  attributes whose names are namespace-scoped. Note that the namespace
     *  prefix need not match the actual prefix used by the XML document itself
     *  since namespaces are compared solely by their URI. You can also register
     *  namespaces from Java code using the
     *  {@link #registerNamespace(String, String)} method.
     * </li>
     *    <li><tt>@attributeName</tt>: named attributes of current nodes. Applicable to
     *  elements, doctypes and processing instructions. On doctypes it supports
     *  attributes <tt>publicId</tt>, <tt>systemId</tt> and <tt>elementName</tt>. On processing
     *  instructions, it supports attributes <tt>target</tt> and <tt>data</tt>, as
     *  well as any other attribute name specified in data as <tt>name="value"</tt> pair.
     *  The attribute nodes for doctype and processing instruction are synthetic, and
     *  as such have no parent. Note, however that <tt>@*</tt> does NOT operate on
     *  doctypes or processing instructions.</li>
     *    <li>any other key: element children of current nodes with name matching the key.
     *  This allows for convenience child traversal in <tt>book.chapter.title</tt> style syntax.
     *  Note that <tt>nodeset.childname</tt> is technically equivalent to
     *  <tt>nodeset._children._fname("childname")</tt>, but is both shorter to write
     *  and evaluates faster. Applicable to document and element nodes.</li>
     * </ul>
     * The order of nodes in the resulting set is the order of evaluation of the key
     * on each node in this set from left to right. Evaluation of the key on a single
     * node always yields the results in "natural" order (that of the document preorder
     * traversal), even for uptree traversals. As a consequence, if this node list's nodes
     * are listed in natural order, applying any of the keys will produce a node list that
     * is also naturally ordered. As a special case, all node lists that are directly or
     * indirectly generated from a single Document or Element node through repeated
     * invocations of this method will be naturally ordered.
     * @param key a key that identifies a required set of nodes
     * @return a new NodeListModel that represents the requested set of nodes.
     */
    public TemplateModel get(String key)
    throws TemplateModelException {
        if (isEmpty())
            return EMPTY;

        if (key == null || key.length() == 0)
            throw new TemplateModelException("Invalid key [" + key + "]");

        NodeOperator op = null;
        NamedNodeOperator nop = null;
        String name = null;

        switch (key.charAt(0)) {
            case '@':
                {
                    if (key.length() != 2 || key.charAt(1) != '*') {
                        // Generic attribute key
                        nop = NAMED_ATTRIBUTE_OP;
                        name = key.substring(1);
                    } else
                        // It is @*
                        op = ALL_ATTRIBUTES_OP;

                    break;
                }
            case '*':
                {
                    if (key.length() == 1)
                        op = ALL_CHILDREN_OP;
                    else
                        // Explicitly disallow any other identifier starting with asterisk
                        throw new TemplateModelException("Invalid key [" + key + "]");

                    break;
                }
            case 'x':
            case '_':
                {
                    op = (NodeOperator) OPERATIONS.get(key);
                    if (op == null) {
                        // Some special operation?
                        Integer specop = (Integer) SPECIAL_OPERATIONS.get(key);
                        if (specop != null) {
                            switch (specop.intValue()) {
                                case SPECIAL_OPERATION_COPY:
                                {
                                    synchronized (namespaces) {
                                        return new NodeListModel(nodes, (Map) ((HashMap) namespaces).clone());
                                    }
                                }
                                case SPECIAL_OPERATION_UNIQUE:
                                    return new NodeListModel(removeDuplicates(nodes), namespaces);
                                case SPECIAL_OPERATION_FILTER_NAME:
                                    return new NameFilter();
                                case SPECIAL_OPERATION_FILTER_TYPE:
                                    return new TypeFilter();
                                case SPECIAL_OPERATION_QUERY_TYPE:
                                    return getType();
                                case SPECIAL_OPERATION_REGISTER_NAMESPACE:
                                    return new RegisterNamespace();
                                case SPECIAL_OPERATION_PLAINTEXT:
                                    return getPlainText();
                            }
                        }
                    }
                    break;
                }
        }

        if (op == null && nop == null) {
            nop = NAMED_CHILDREN_OP;
            name = key;
        }

        List list = null;
        if (op != null)
            list = evaluateElementOperation(op, nodes);
        else {
            String localName = name;
            Namespace namespace = Namespace.NO_NAMESPACE;
            int colon = name.indexOf(':');
            if (colon != -1) {
                localName = name.substring(colon + 1);
                String nsPrefix = name.substring(0, colon);
                synchronized (namespaces) {
                    namespace = (Namespace) namespaces.get(nsPrefix);
                }
                if (namespace == null) {
                    if (nsPrefix.equals("xml"))
                        namespace = Namespace.XML_NAMESPACE;
                    else
                        throw new TemplateModelException("Unregistered namespace prefix '" + nsPrefix + "'");
                }
            }

            list = evaluateNamedElementOperation(nop, localName, namespace, nodes);
        }
        return createNodeListModel(list, namespaces);
    }

    private TemplateModel getType() {
        if (nodes.size() == 0)
            return new SimpleScalar("");
        Object firstNode = nodes.get(0);
        char code;
        if (firstNode instanceof Element)
            code = 'e';
        else if (firstNode instanceof Text || firstNode instanceof String)
            code = 'x';
        else if (firstNode instanceof Attribute)
            code = 'a';
        else if (firstNode instanceof EntityRef)
            code = 'n';
        else if (firstNode instanceof Document)
            code = 'd';
        else if (firstNode instanceof DocType)
            code = 't';
        else if (firstNode instanceof Comment)
            code = 'c';
        else if (firstNode instanceof ProcessingInstruction)
            code = 'p';
        else
            code = '?';
        return new SimpleScalar(new String(new char[] { code}));
    }

    private SimpleScalar getPlainText()
    throws TemplateModelException {
        List list = evaluateElementOperation((TextOp) OPERATIONS.get("_text"), nodes);
        StringBuilder buf = new StringBuilder();
        for (Iterator it = list.iterator(); it.hasNext(); ) {
            buf.append(it.next());
        }
        return new SimpleScalar(buf.toString());
    }

    public TemplateModelIterator iterator() {
        return new TemplateModelIterator()
        {
            private final Iterator it = nodes.iterator();

            public TemplateModel next() {
                return it.hasNext() ? new NodeListModel(it.next(), namespaces) : null;
            }

            public boolean hasNext() {
                return it.hasNext();
            }
        };
    }

    /**
     * Retrieves the i-th element of the node list.
     */
    public TemplateModel get(int i)
    throws TemplateModelException {
        try {
            return new NodeListModel(nodes.get(i), namespaces);
        } catch (IndexOutOfBoundsException e) {
            throw new TemplateModelException("Index out of bounds: " + e.getMessage());
        }
    }
    
    public int size() {
        return nodes.size();
    }

    /**
     * Applies an XPath expression to the node list and returns the resulting node list.
     * In order for this method to work, your application must have access
     * <a href="http://www.jaxen.org">Jaxen</a> library classes. The
     * implementation does cache the parsed format of XPath expressions in a weak hash
     * map, keyed by the string representation of the XPath expression. As the string
     * object passed as the argument is usually kept in the parsed FreeMarker template,
     * this ensures that each XPath expression is parsed only once during the lifetime
     * of the FreeMarker template that contains it.
     * @param arguments the list of arguments. Must contain exactly one string that is
     * the XPath expression you wish to apply. The XPath expression can use any namespace
     * prefixes that were defined using the {@link #registerNamespace(String, String)}
     * method or the <code>nodelist._registerNamespace(prefix, uri)</code> expression in the
     * template.
     * @return a NodeListModel representing the nodes that are the result of application
     * of the XPath to the current node list.
     */
    public Object exec(List arguments)
    throws TemplateModelException {
        if (arguments == null || arguments.size() != 1)
            throw new TemplateModelException("Exactly one argument required for execute() on NodeTemplate");

        String xpathString = (String) arguments.get(0);
        JDOMXPathEx xpath = null;
        try {
            synchronized (XPATH_CACHE) {
                xpath = (JDOMXPathEx) XPATH_CACHE.get(xpathString);
                if (xpath == null) {
                    xpath = new JDOMXPathEx(xpathString);
                    XPATH_CACHE.put(xpathString, xpath);
                }
            }
            return createNodeListModel(xpath.selectNodes(nodes, namespaces), namespaces);
        } catch (Exception e) {
            throw new TemplateModelException("Could not evaulate XPath expression " + xpathString, e);
        }
    }

    /**
     * Registers an XML namespace with this node list. Once registered, you can
     * refer to the registered namespace using its prefix in the
     * {@link #get(String)} method from this node list and all other
     * node lists that are derived from this node list. Use the
     * <tt>nodelist["prefix:localname"]</tt> or the
     * <tt>nodelist["@prefix:localname"]</tt> syntax to reach elements and
     *  attributes whose names are namespace-scoped. Note that the namespace
     * prefix need not match the actual prefix used by the XML document itself
     * since namespaces are compared solely by their URI. You can also register
     * namespaces during template evaluation using the
     * <tt>nodelist._registerNamespace(prefix, uri)</tt> syntax in the template.
     * This mechanism is completely independent from the namespace declarations
     * in the XML document itself; its purpose is to give you an easy way
     * to refer to namespace-scoped elements in {@link #get(String)} and
     * in XPath expressions passed to {@link #exec(List)}. Note also that
     * the namespace prefix registry is shared among all node lists that
     * are created from a single node list - modifying the registry in one
     * affects all others as well. If you want to obtain a namespace 
     * "detached" copy of the node list, use the <code>_copy</code> key on
     * it (or call <code>nodeList.get("_copy")</code> directly from your
     * Java code. The returned node list has all the namespaces that the
     * original node list has, but they can be manipulated independently
     * thereon.
     */
    public void registerNamespace(String prefix, String uri) {
        synchronized (namespaces) {
            namespaces.put(prefix, Namespace.getNamespace(prefix, uri));
        }
    }

    private interface NodeOperator {
        List operate(Object node)
        throws TemplateModelException;
    }

    private interface NamedNodeOperator {
        List operate(Object node, String localName, Namespace namespace)
        throws TemplateModelException;
    }

    private static final class AllChildrenOp implements NodeOperator {
        public List operate(Object node) {
            if (node instanceof Element)
                return((Element) node).getChildren();
            else if (node instanceof Document) {
                Element root = ((Document) node).getRootElement();
                return root == null ? Collections.EMPTY_LIST : Collections.singletonList(root);
            } 
 // With 2.1 semantics it  makes more sense to just return a null and let the core 
 // throw an InvalidReferenceException and the template writer can use ?exists etcetera. (JR)
            return null;
/*            
            else
                throw new TemplateModelException("_allChildren can not be applied on " + node.getClass());
*/                
        }
    }

    private static final class NamedChildrenOp implements NamedNodeOperator {
        public List operate(Object node, String localName, Namespace namespace) {
            if (node instanceof Element) {
                return((Element) node).getChildren(localName, namespace);
            } else if (node instanceof Document) {
                Element root = ((Document) node).getRootElement();
                if (root != null &&
                    root.getName().equals(localName) &&
                    root.getNamespaceURI().equals(namespace.getURI())) {
                    return Collections.singletonList(root);
                } else
                    return Collections.EMPTY_LIST;
            } 
 // With 2.1 semantics it  makes more sense to just return a null and let the core 
 // throw an InvalidReferenceException and the template writer can use ?exists etcetera. (JR)
            return null;
 /*           
            else
                throw new TemplateModelException("_namedChildren can not be applied on " + node.getClass());
*/                
        }
    }

    private static final class AllAttributesOp implements NodeOperator {
        public List operate(Object node) {
 // With 2.1 semantics it  makes more sense to just return a null and let the core 
 // throw an InvalidReferenceException and the template writer can use ?exists etcetera. (JR)
            if (!(node instanceof Element)) {
                return null;
            }
            return ((Element) node).getAttributes();
/*
            else
                throw new TemplateModelException("_allAttributes can not be applied on " + node.getClass());
*/                
        }
    }

    private static final class NamedAttributeOp implements NamedNodeOperator {
        public List operate(Object node, String localName, Namespace namespace) {
            Attribute attr = null;
            if (node instanceof Element) {
                Element element = (Element) node;
                attr = element.getAttribute(localName, namespace);
            } else if (node instanceof ProcessingInstruction) {
                ProcessingInstruction pi = (ProcessingInstruction) node;
                if ("target".equals(localName))
                    attr = new Attribute("target", pi.getTarget());
                else if ("data".equals(localName))
                    attr = new Attribute("data", pi.getData());
                else
                    attr = new Attribute(localName, pi.getValue(localName));
            } else if (node instanceof DocType) {
                DocType doctype = (DocType) node;
                if ("publicId".equals(localName))
                    attr = new Attribute("publicId", doctype.getPublicID());
                else if ("systemId".equals(localName))
                    attr = new Attribute("systemId", doctype.getSystemID());
                else if ("elementName".equals(localName))
                    attr = new Attribute("elementName", doctype.getElementName());
            } 
            // With 2.1 semantics it  makes more sense to just return a null and let the core 
            // throw an InvalidReferenceException and the template writer can use ?exists etcetera. (JR)
            else {
                return null;
            }
/*            
            else
                throw new TemplateModelException("_allAttributes can not be applied on " + node.getClass());
*/
            return attr == null ? Collections.EMPTY_LIST : Collections.singletonList(attr);
        }
    }

    private static final class NameOp implements NodeOperator {
        public List operate(Object node) {
            if (node instanceof Element)
                return Collections.singletonList(((Element) node).getName());
            else if (node instanceof Attribute)
                return Collections.singletonList(((Attribute) node).getName());
            else if (node instanceof EntityRef)
                return Collections.singletonList(((EntityRef) node).getName());
            else if (node instanceof ProcessingInstruction)
                return Collections.singletonList(((ProcessingInstruction) node).getTarget());
            else if (node instanceof DocType)
                return Collections.singletonList(((DocType) node).getPublicID());
            else
                return null;
            // With 2.1 semantics it  makes more sense to just return a null and let the core 
            // throw an InvalidReferenceException and the template writer can use ?exists etcetera. (JR)
//                throw new TemplateModelException("_name can not be applied on " + node.getClass());
        }
    }

    private static final class QNameOp implements NodeOperator {
        public List operate(Object node) {
            if (node instanceof Element)
                return Collections.singletonList(((Element) node).getQualifiedName());
            else if (node instanceof Attribute)
                return Collections.singletonList(((Attribute) node).getQualifiedName());
            // With 2.1 semantics it  makes more sense to just return a null and let the core 
            // throw an InvalidReferenceException and the template writer can use ?exists etcetera. (JR)
            return null;
//            throw new TemplateModelException("_qname can not be applied on " + node.getClass());
        }
    }

    private static final class NamespaceUriOp implements NodeOperator {
        public List operate(Object node) {
            if (node instanceof Element)
                return Collections.singletonList(((Element) node).getNamespace().getURI());
            else if (node instanceof Attribute)
                return Collections.singletonList(((Attribute) node).getNamespace().getURI());
            // With 2.1 semantics it  makes more sense to just return a null and let the core 
            // throw an InvalidReferenceException and the template writer can use ?exists etcetera. (JR)
            return null;
//            throw new TemplateModelException("_nsuri can not be applied on " + node.getClass());
        }
    }

    private static final class NamespacePrefixOp implements NodeOperator {
        public List operate(Object node) {
            if (node instanceof Element)
                return Collections.singletonList(((Element) node).getNamespace().getPrefix());
            else if (node instanceof Attribute)
                return Collections.singletonList(((Attribute) node).getNamespace().getPrefix());
            // With 2.1 semantics it  makes more sense to just return a null and let the core 
            // throw an InvalidReferenceException and the template writer can use ?exists etcetera. (JR)
            return null;
//            throw new TemplateModelException("_nsprefix can not be applied on " + node.getClass());
        }
    }

    private static final class CanonicalNameOp implements NodeOperator {
        public List operate(Object node) {
            if (node instanceof Element) {
                Element element = (Element) node;
                return Collections.singletonList(element.getNamespace().getURI() + element.getName());
            } else if (node instanceof Attribute) {
                Attribute attribute = (Attribute) node;
                return Collections.singletonList(attribute.getNamespace().getURI() + attribute.getName());
            }
            // With 2.1 semantics it  makes more sense to just return a null and let the core 
            // throw an InvalidReferenceException and the template writer can use ?exists etcetera. (JR)
            return null;
//            throw new TemplateModelException("_cname can not be applied on " + node.getClass());
        }
    }


    private static final Element getParent(Object node) {
        if (node instanceof Element)
            return((Element) node).getParent();
        else if (node instanceof Attribute)
            return((Attribute) node).getParent();
        else if (node instanceof Text)
            return((Text) node).getParent();
        else if (node instanceof ProcessingInstruction)
            return((ProcessingInstruction) node).getParent();
        else if (node instanceof Comment)
            return((Comment) node).getParent();
        else if (node instanceof EntityRef)
            return((EntityRef) node).getParent();
        else
            // With 2.1 semantics it  makes more sense to just return a null and let the core 
            // throw an InvalidReferenceException and the template writer can use ?exists etcetera. (JR)
            return null;
//            throw new TemplateModelException("_parent can not be applied on " + node.getClass());
    }

    private static final class ParentOp implements NodeOperator {
        public List operate(Object node) {
            Element parent = getParent(node);
            return parent == null ? Collections.EMPTY_LIST : Collections.singletonList(parent);
        }
    }

    private static final class AncestorOp implements NodeOperator {
        public List operate(Object node) {
            Element parent = getParent(node);
            if (parent == null) return Collections.EMPTY_LIST;
            LinkedList list = new LinkedList();
            do {
                list.addFirst(parent);
                parent = parent.getParent();
            } while (parent != null);
            return list;
        }
    }

    private static final class AncestorOrSelfOp implements NodeOperator {
        public List operate(Object node) {
            Element parent = getParent(node);
            if (parent == null) return Collections.singletonList(node);
            LinkedList list = new LinkedList();
            list.addFirst(node);
            do {
                list.addFirst(parent);
                parent = parent.getParent();
            } while (parent != null);
            return list;
        }
    }

    private static class DescendantOp implements NodeOperator {
        public List operate(Object node) {
            LinkedList list = new LinkedList();
            if (node instanceof Element) {
                addChildren((Element) node, list);
            } else if (node instanceof Document) {
                Element root = ((Document) node).getRootElement();
                list.add(root);
                addChildren(root, list);
            } else
                // With 2.1 semantics it  makes more sense to just return a null and let the core 
                // throw an InvalidReferenceException and the template writer can use ?exists etcetera. (JR)
                return null;
//                throw new TemplateModelException("_descendant can not be applied on " + node.getClass());

            return list;
        }

        private void addChildren(Element element, List list) {
            List children = element.getChildren();
            Iterator it = children.iterator();
            while (it.hasNext()) {
                Element child = (Element) it.next();
                list.add(child);
                addChildren(child, list);
            }
        }
    }

    private static final class DescendantOrSelfOp extends DescendantOp {
        @Override
        public List operate(Object node) {
            LinkedList list = (LinkedList) super.operate(node);
            list.addFirst(node);
            return list;
        }
    }

    private static final class DocumentOp implements NodeOperator {
        public List operate(Object node) {
            Document doc = null;
            if (node instanceof Element)
                doc = ((Element) node).getDocument();
            else if (node instanceof Attribute) {
                Element parent = ((Attribute) node).getParent();
                doc = parent == null ? null : parent.getDocument();
            } else if (node instanceof Text) {
                Element parent = ((Text) node).getParent();
                doc = parent == null ? null : parent.getDocument();
            } else if (node instanceof Document)
                doc = (Document) node;
            else if (node instanceof ProcessingInstruction)
                doc = ((ProcessingInstruction) node).getDocument();
            else if (node instanceof EntityRef)
                doc = ((EntityRef) node).getDocument();
            else if (node instanceof Comment)
                doc = ((Comment) node).getDocument();
            else
                // With 2.1 semantics it  makes more sense to just return a null and let the core 
                // throw an InvalidReferenceException and the template writer can use ?exists etcetera. (JR)
                return null;
//                throw new TemplateModelException("_document can not be applied on " + node.getClass());

            return doc == null ? Collections.EMPTY_LIST : Collections.singletonList(doc);
        }
    }

    private static final class DocTypeOp implements NodeOperator {
        public List operate(Object node) {
            if (node instanceof Document) {
                DocType doctype = ((Document) node).getDocType();
                return doctype == null ? Collections.EMPTY_LIST : Collections.singletonList(doctype);
            } else
                // With 2.1 semantics it  makes more sense to just return a null and let the core 
                // throw an InvalidReferenceException and the template writer can use ?exists etcetera. (JR)
                return null;
//                throw new TemplateModelException("_doctype can not be applied on " + node.getClass());
        }
    }

    private static final class ContentOp implements NodeOperator {
        public List operate(Object node) {
            if (node instanceof Element)
                return((Element) node).getContent();
            else if (node instanceof Document)
                return((Document) node).getContent();
            // With 2.1 semantics it  makes more sense to just return a null and let the core 
            // throw an InvalidReferenceException and the template writer can use ?exists etcetera. (JR)
            return null;
//            throw new TemplateModelException("_content can not be applied on " + node.getClass());
        }
    }

    private static final class TextOp implements NodeOperator {
        public List operate(Object node) {
            if (node instanceof Element)
                return Collections.singletonList(((Element) node).getTextTrim());
            if (node instanceof Attribute)
                return Collections.singletonList(((Attribute) node).getValue());
            if (node instanceof CDATA)
                return Collections.singletonList(((CDATA) node).getText());
            if (node instanceof Comment)
                return Collections.singletonList(((Comment) node).getText());
            if (node instanceof ProcessingInstruction)
                return Collections.singletonList(((ProcessingInstruction) node).getData());
            // With 2.1 semantics it  makes more sense to just return a null and let the core 
            // throw an InvalidReferenceException and the template writer can use ?exists etcetera. (JR)
            return null;
//            throw new TemplateModelException("_text can not be applied on " + node.getClass());
        }
    }

    private static final List evaluateElementOperation(NodeOperator op, List nodes)
    throws TemplateModelException {
        int s = nodes.size();
        List[] lists = new List[s];
        int l = 0;
        {
            int i = 0;
            Iterator it = nodes.iterator();
            while (it.hasNext()) {
                List list = op.operate(it.next());
                if (list != null) {
                    lists[i++] = list;
                    l += list.size();
                }
            }
        }
        List retval = new ArrayList(l);
        for (int i = 0; i < s; ++i) {
            if (lists[i] != null) {
                retval.addAll(lists[i]);
            }
        }
        return retval;
    }

    private static final List evaluateNamedElementOperation(NamedNodeOperator op, String localName, Namespace namespace, List nodes)
    throws TemplateModelException {
        int s = nodes.size();
        List[] lists = new List[s];
        int l = 0;
        {
            int i = 0;
            Iterator it = nodes.iterator();
            while (it.hasNext()) {
                List list = op.operate(it.next(), localName, namespace);
                lists[i++] = list;
                l += list.size();
            }
        }
        List retval = new ArrayList(l);
        for (int i = 0; i < s; ++i)
            retval.addAll(lists[i]);
        return retval;
    }

    private static final List removeDuplicates(List list) {
        int s = list.size();
        ArrayList ulist = new ArrayList(s);
        Set set = new HashSet(s * 4 / 3, .75f);
        Iterator it = list.iterator();
        while (it.hasNext()) {
            Object o = it.next();
            if (set.add(o))
                ulist.add(o);
        }
        ulist.trimToSize();
        return ulist;
    }

    private static final Map createOperations() {
        Map map = new HashMap();

        map.put("_ancestor", new AncestorOp());
        map.put("_ancestorOrSelf", new AncestorOrSelfOp());
        map.put("_attributes", ALL_ATTRIBUTES_OP);
        map.put("_children", ALL_CHILDREN_OP);
        map.put("_cname", new CanonicalNameOp());
        map.put("_content", new ContentOp());
        map.put("_descendant", new DescendantOp());
        map.put("_descendantOrSelf", new DescendantOrSelfOp());
        map.put("_document", new DocumentOp());
        map.put("_doctype", new DocTypeOp());
        map.put("_name", new NameOp());
        map.put("_nsprefix", new NamespacePrefixOp());
        map.put("_nsuri", new NamespaceUriOp());
        map.put("_parent", new ParentOp());
        map.put("_qname", new QNameOp());
        map.put("_text", new TextOp());

        return map;
    }

    private static final Map createSpecialOperations() {
        Map map = new HashMap();

        Integer copy = Integer.valueOf(SPECIAL_OPERATION_COPY);
        Integer unique = Integer.valueOf(SPECIAL_OPERATION_UNIQUE);
        Integer fname = Integer.valueOf(SPECIAL_OPERATION_FILTER_NAME);
        Integer ftype = Integer.valueOf(SPECIAL_OPERATION_FILTER_TYPE);
        Integer type = Integer.valueOf(SPECIAL_OPERATION_QUERY_TYPE);
        Integer regns = Integer.valueOf(SPECIAL_OPERATION_REGISTER_NAMESPACE);
        Integer plaintext = Integer.valueOf(SPECIAL_OPERATION_PLAINTEXT);

        map.put("_copy", copy);
        map.put("_unique", unique);
        map.put("_fname", fname);
        map.put("_ftype", ftype);
        map.put("_type", type);
        map.put("_registerNamespace", regns);
        map.put("_plaintext", plaintext);

        // These are in for backward compatibility
        map.put("x_copy", copy);
        map.put("x_unique", unique);
        map.put("x_fname", fname);
        map.put("x_ftype", ftype);
        map.put("x_type", type);

        return map;
    }

    private final class RegisterNamespace implements TemplateMethodModel {
        public boolean isEmpty() {
            return false;
        }

        public Object exec(List arguments)
        throws TemplateModelException {
            if (arguments.size() != 2)
                throw new TemplateModelException("_registerNamespace(prefix, uri) requires two arguments");

            registerNamespace((String) arguments.get(0), (String) arguments.get(1));

            return TemplateScalarModel.EMPTY_STRING;
        }
    }

    private final class NameFilter implements TemplateMethodModel {
        public boolean isEmpty() {
            return false;
        }

        public Object exec(List arguments) {
            Set names = new HashSet(arguments);
            List list = new LinkedList(nodes);
            Iterator it = list.iterator();
            while (it.hasNext()) {
                Object node = it.next();
                String name = null;
                if (node instanceof Element)
                    name = ((Element) node).getName();
                else if (node instanceof Attribute)
                    name = ((Attribute) node).getName();
                else if (node instanceof ProcessingInstruction)
                    name = ((ProcessingInstruction) node).getTarget();
                else if (node instanceof EntityRef)
                    name = ((EntityRef) node).getName();
                else if (node instanceof DocType)
                    name = ((DocType) node).getPublicID();

                if (name == null || !names.contains(name))
                    it.remove();
            }
            return createNodeListModel(list, namespaces);
        }
    }

    private final class TypeFilter implements TemplateMethodModel {
        public boolean isEmpty() {
            return false;
        }

        public Object exec(List arguments)
        throws TemplateModelException {
            if (arguments == null || arguments.size() == 0)
                throw new TemplateModelException("_type expects exactly one argument");
            String arg = (String) arguments.get(0);
            boolean invert = arg.indexOf('!') != -1;
            // NOTE: true in each of these variables means 'remove', not 'keep'
            // This is so we don't invert their values in the loop. So,
            // a is true <--> (a is not present in the string) xor invert.
            boolean a = invert != (arg.indexOf('a') == -1);
            boolean c = invert != (arg.indexOf('c') == -1);
            boolean d = invert != (arg.indexOf('d') == -1);
            boolean e = invert != (arg.indexOf('e') == -1);
            boolean n = invert != (arg.indexOf('n') == -1);
            boolean p = invert != (arg.indexOf('p') == -1);
            boolean t = invert != (arg.indexOf('t') == -1);
            boolean x = invert != (arg.indexOf('x') == -1);

            LinkedList list = new LinkedList(nodes);
            Iterator it = list.iterator();
            while (it.hasNext()) {
                Object node = it.next();
                if ((node instanceof Element && e)
                    || (node instanceof Attribute && a)
                    || (node instanceof String && x)
                    || (node instanceof Text && x)
                    || (node instanceof ProcessingInstruction && p)
                    || (node instanceof Comment && c)
                    || (node instanceof EntityRef && n)
                    || (node instanceof Document && d)
                    || (node instanceof DocType && t))
                    it.remove();
            }
            return createNodeListModel(list, namespaces);
        }
    }

    private static final class AttributeXMLOutputter extends XMLOutputter {
        public void output(Attribute attribute, Writer out)
        throws IOException {
            out.write(" ");
            out.write(attribute.getQualifiedName());
            out.write("=");

            out.write("\"");
            out.write(escapeAttributeEntities(attribute.getValue()));
            out.write("\"");
        }
    }

    private static final class JDOMXPathEx
    extends
        JDOMXPath {
        JDOMXPathEx(String path)
        throws JaxenException {
            super(path);
        }

        public List selectNodes(Object object, Map namespaces)
        throws JaxenException {
            Context context = getContext(object);
            context.getContextSupport().setNamespaceContext(new NamespaceContextImpl(namespaces));
            return selectNodesForContext(context);
        } 

        private static final class NamespaceContextImpl
        implements
            NamespaceContext {
            private final Map namespaces;
            
            NamespaceContextImpl(Map namespaces) {
                this.namespaces = namespaces;
            }
            
            public String translateNamespacePrefixToUri(String prefix) {
                // Empty prefix always maps to empty URL in XPath
                if (prefix.length() == 0) {
                    return prefix;
                }
                synchronized (namespaces) {
                    Namespace ns = (Namespace) namespaces.get(prefix);
                    return ns == null ? null : ns.getURI();
                }   
            }
        }
    }
}
