/* * Copyright (c) 1998-2011 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * Free SoftwareFoundation, Inc. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA * * @author Scott Ferguson */ package com.caucho.xpath.pattern; import com.caucho.xpath.ExprEnvironment; import com.caucho.xpath.XPathException; import org.w3c.dom.Document; import org.w3c.dom.Node; /** * Matches a node without checking the name. e.g. * or @* */ public class NodeTypePattern extends AbstractPattern { public final static int NODE = -2; public final static int ANY = -1; private AbstractPattern _match; private int _nodeType; private NodeTypePattern(AbstractPattern parent, int nodeType) { super(parent); _nodeType = nodeType; } public static AbstractPattern create(AbstractPattern parent, int nodeType) { if (nodeType == NODE && parent instanceof FromParent && parent._parent instanceof FromContext) { FromContext context = (FromContext) parent._parent; return new FromContext(context.getCount() + 1); } else return new NodeTypePattern(parent, nodeType); } /** * The node-type priority is less than nodes. */ public double getPriority() { if (_parent instanceof Axis && _parent.getParent() != null && ! (_parent.getParent() instanceof FromRoot) && ! (_parent.getParent() instanceof FromAny)) return 0.5; else return -0.5; } /** * Returns the name of the matching node or '*' if many nodes match. * * <p>The Xsl package uses this to speed template matching. */ public String getNodeName() { switch (_nodeType) { case Node.TEXT_NODE: // cdata, too? return "#text"; case Node.DOCUMENT_NODE: return "#document"; case Node.COMMENT_NODE: return "#comment"; default: return "*"; } } /** * Returns the matching node type. */ public int getNodeType() { return _nodeType; } /** * Returns true if the pattern is strictly ascending. */ public boolean isStrictlyAscending() { if (_parent != null) return _parent.isStrictlyAscending(); else return true; } /** * Matches if the node type matches. * * @param node the current node * @param env the variable environment * * @return true if the node matches the node type */ public boolean match(Node node, ExprEnvironment env) throws XPathException { if (node == null) return false; if (_nodeType == Node.ATTRIBUTE_NODE) { if (node.getNodeType() != Node.ATTRIBUTE_NODE) return false; else if (XMLNS.equals(node.getNamespaceURI())) return false; } else if (node.getNodeType() == _nodeType) { } else if (_nodeType == ANY) { } else if (_nodeType == NODE && ! (node instanceof Document)) { } else return false; return _parent == null || _parent.match(node, env); } /** * Copies the node matching portion of the pattern, i.e. the section * only applying to the current axis. */ public AbstractPattern copyPosition() { if (_match == null) { AbstractPattern parent = null; if (_parent != null) parent = _parent.copyPosition(); _match = new NodeTypePattern(parent, _nodeType); } return _match; } /** * Returns true if the two patterns are equal. */ public boolean equals(Object b) { if (! (b instanceof NodeTypePattern)) return false; NodeTypePattern bPattern = (NodeTypePattern) b; return (_nodeType == bPattern._nodeType && (_parent == bPattern._parent || (_parent != null && _parent.equals(bPattern._parent)))); } /** * Returns the printable representation of the pattern. */ public String toString() { String prefix; if (_parent == null) prefix = ""; else if (_parent instanceof FromChildren) prefix = _parent.getPrefix(); else prefix = _parent.toString(); switch (_nodeType) { case ANY: if (! (_parent instanceof FromSelf)) return prefix + "node()"; else if (_parent._parent == null) return "."; else return _parent.getPrefix() + "."; case NODE: return prefix + "node()"; case Node.PROCESSING_INSTRUCTION_NODE: return prefix + "pi()"; case Node.ATTRIBUTE_NODE: return prefix + "*"; case Node.ELEMENT_NODE: return prefix + "*"; case Node.COMMENT_NODE: return prefix + "comment()"; case Node.TEXT_NODE: return prefix + "text()"; case Node.ENTITY_REFERENCE_NODE: return prefix + "er()"; default: return super.toString(); } } }