/*
 * 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.FileReader;
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.SimpleHash;
import freemarker.template.SimpleScalar;
import freemarker.template.Template;
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;
import freemarker.template._ObjectWrappers;

/**
 * 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.
     */
    @Override
    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.
     */
    @Override
    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 {@code _ftype}
     * 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>{@code *} or {@code _children}: all direct element children of current nodes (non-recursive). Applicable
     *  to element and document nodes.</li>
     *    <li>{@code @*} or {@code _attributes}: all attributes of current nodes. Applicable to elements only.</li>
     *    <li>{@code _content} the complete content of current nodes (non-recursive).
     *  Applicable to elements and documents.</li>
     *    <li>{@code _text}: 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>{@code _plaintext}: same as {@code _text}, but does not escape any characters,
     *  and instead of returning a NodeList returns a SimpleScalar.</li>
     *    <li>{@code _name}: 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>{@code _qname}: the qualified names of current nodes in {@code [namespacePrefix:]localName}
     * form, one string per node (non-recursive). Applicable to elements and attributes</li>
     *    <li>{@code _cname}: the canonical names of current nodes (namespace URI + local name),
     * one string per node (non-recursive). Applicable to elements and attributes</li>
     *    <li>{@code _nsprefix}: namespace prefixes of current nodes,
     * one string per node (non-recursive). Applicable to elements and attributes</li>
     *    <li>{@code _nsuri}: namespace URIs of current nodes,
     * one string per node (non-recursive). Applicable to elements and attributes</li>
     *    <li>{@code _parent}: parent elements of current nodes. Applicable to element, attribute, comment,
     *  entity, processing instruction.</li>
     *    <li>{@code _ancestor}: all ancestors up to root element (recursive) of current nodes. Applicable
     *  to same node types as {@code _parent}.</li>
     *    <li>{@code _ancestorOrSelf}: all ancestors of current nodes plus current nodes. Applicable
     *  to same node types as {@code _parent}.</li>
     *    <li>{@code _descendant}: all recursive descendant element children of current nodes. Applicable to
     *  document and element nodes.
     *    <li>{@code _descendantOrSelf}: all recursive descendant element children of current nodes
     *  plus current nodes. Applicable to document and element nodes.
     *    <li>{@code _document}: all documents the current nodes belong to.
     *  Applicable to all nodes except text.
     *    <li>{@code _doctype}: doctypes of the current nodes.
     *  Applicable to document nodes only.
     *    <li>{@code _fname}: 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>{@code _ftype}: 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>{@code _type}: 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>{@code _unique}: 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 {@code _parent},
     *  {@code _ancestor}, {@code _ancestorOrSelf}, and {@code _document}.
     *  I.e. {@code foo._children._parent} 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
     *  {@code foo._children._parent._unique} to eliminate duplicates. Applicable
     *  to all node types.</li>
     *    <li>{@code _copy}: 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>{@code _registerNamespace(prefix, uri)}: 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 {@code nodelist["prefix:localname"]} or
     *  {@code nodelist["@prefix:localname"]} 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>{@code @attributeName}: named attributes of current nodes. Applicable to
     *  elements, doctypes and processing instructions. On doctypes it supports
     *  attributes {@code publicId}, {@code systemId} and {@code elementName}. On processing
     *  instructions, it supports attributes {@code target} and {@code data}, as
     *  well as any other attribute name specified in data as {@code name="value"} pair.
     *  The attribute nodes for doctype and processing instruction are synthetic, and
     *  as such have no parent. Note, however that {@code @*} 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 {@code book.chapter.title} style syntax.
     *  Note that {@code nodeset.childname} is technically equivalent to
     *  {@code nodeset._children._fname("childname")}, 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.
     */
    @Override
    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());
    }

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

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

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

    /**
     * Retrieves the i-th element of the node list.
     */
    @Override
    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());
        }
    }
    
    @Override
    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.
     */
    @Override
    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
     * {@code nodelist["prefix:localname"]} or the
     * {@code nodelist["@prefix:localname"]} 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
     * {@code nodelist._registerNamespace(prefix, uri)} 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 {
        @Override
        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 {
        @Override
        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 {
        @Override
        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 {
        @Override
        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 {
        @Override
        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 {
        @Override
        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 {
        @Override
        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 {
        @Override
        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 {
        @Override
        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 {
        @Override
        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 {
        @Override
        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 {
        @Override
        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 {
        @Override
        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 {
        @Override
        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 {
        @Override
        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 {
        @Override
        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 {
        @Override
        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;
        }

        @Override
        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;
        }

        @Override
        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;
        }

        @Override
        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);
        }
    }

    /**
     * Loads a template from a file passed as the first argument, loads an XML
     * document from the standard input, passes it to the template as variable
     * {@code document} and writes the result of template processing to
     * standard output.
     * 
     * @deprecated Will be removed (main method in a library, often classified as CWE-489 "Leftover Debug Code").
     */
    @Deprecated
    public static void main(String[] args)
    throws Exception {
        org.jdom.input.SAXBuilder builder = new org.jdom.input.SAXBuilder();
        Document document = builder.build(System.in);
        SimpleHash model = new SimpleHash(_ObjectWrappers.SAFE_OBJECT_WRAPPER);
        model.put("document", new NodeListModel(document));
        FileReader fr = new FileReader(args[0]);
        Template template = new Template(args[0], fr);
        Writer w = new java.io.OutputStreamWriter(System.out);
        template.process(model, w);
        w.flush();
        w.close();
    }

    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;
            }
            
            @Override
            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();
                }   
            }
        }
    }
}
