1 /* 2 * $Header: /cvsroot/jaxen/jaxen/src/java/main/org/jaxen/expr/DefaultNameStep.java,v 1.23 2002/04/26 17:17:34 jstrachan Exp $ 3 * $Revision: 1.23 $ 4 * $Date: 2002/04/26 17:17:34 $ 5 * 6 * ==================================================================== 7 * 8 * Copyright (C) 2000-2002 bob mcwhirter & James Strachan. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions, and the following disclaimer. 17 * 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions, and the disclaimer that follows 20 * these conditions in the documentation and/or other materials 21 * provided with the distribution. 22 * 23 * 3. The name "Jaxen" must not be used to endorse or promote products 24 * derived from this software without prior written permission. For 25 * written permission, please contact license@jaxen.org. 26 * 27 * 4. Products derived from this software may not be called "Jaxen", nor 28 * may "Jaxen" appear in their name, without prior written permission 29 * from the Jaxen Project Management (pm@jaxen.org). 30 * 31 * In addition, we request (but do not require) that you include in the 32 * end-user documentation provided with the redistribution and/or in the 33 * software itself an acknowledgement equivalent to the following: 34 * "This product includes software developed by the 35 * Jaxen Project (http://www.jaxen.org/)." 36 * Alternatively, the acknowledgment may be graphical using the logos 37 * available at http://www.jaxen.org/ 38 * 39 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 40 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 41 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 42 * DISCLAIMED. IN NO EVENT SHALL THE Jaxen AUTHORS OR THE PROJECT 43 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 45 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 46 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 47 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 48 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 49 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 50 * SUCH DAMAGE. 51 * 52 * ==================================================================== 53 * This software consists of voluntary contributions made by many 54 * individuals on behalf of the Jaxen Project and was originally 55 * created by bob mcwhirter <bob@werken.com> and 56 * James Strachan <jstrachan@apache.org>. For more information on the 57 * Jaxen Project, please see <http://www.jaxen.org/>. 58 * 59 * $Id: DefaultNameStep.java,v 1.23 2002/04/26 17:17:34 jstrachan Exp $ 60 */ 61 62 63 64 package org.jaxen.expr; 65 66 import org.jaxen.ContextSupport; 67 import org.jaxen.Navigator; 68 69 import org.jaxen.expr.iter.IterableAxis; 70 71 72 /** Expression object that represents any flavor 73 * of name-test steps within an XPath. 74 * 75 * <p> 76 * This includes simple steps, such as "foo", 77 * non-default-axis steps, such as "following-sibling::foo" 78 * or "@foo", and namespace-aware steps, such 79 * as "foo:bar". 80 * </p> 81 * 82 * @author bob mcwhirter (bob@werken.com) 83 */ 84 public class DefaultNameStep extends DefaultStep 85 { 86 /** Our prefix, bound through the current Context. 87 * The empty-string ("") if no prefix was specified. 88 * Decidedly NOT-NULL, due to SAXPath constraints. 89 */ 90 private String prefix; 91 92 /** Our local-name.*/ 93 private String localName; 94 95 /** Quick flag denoting if the localname was '*' */ 96 private boolean matchesAnyName; 97 DefaultNameStep(IterableAxis axis, String prefix, String localName)98 public DefaultNameStep(IterableAxis axis, 99 String prefix, 100 String localName) 101 { 102 super( axis ); 103 104 this.prefix = prefix; 105 this.localName = localName; 106 this.matchesAnyName = "*".equals( localName ); 107 } 108 getPrefix()109 public String getPrefix() 110 { 111 return this.prefix; 112 } 113 getLocalName()114 public String getLocalName() 115 { 116 return this.localName; 117 } 118 isMatchesAnyName()119 public boolean isMatchesAnyName() 120 { 121 return matchesAnyName; 122 } 123 getText()124 public String getText() 125 { 126 if ( ( getPrefix() != null ) 127 && 128 ( ! getPrefix().equals("") ) ) 129 { 130 return getAxisName() + "::" + getPrefix() + ":" + getLocalName() + super.getText(); 131 } 132 133 return getAxisName() 134 + "::" + getLocalName() 135 + super.getText(); 136 } 137 toString()138 public String toString() 139 { 140 return "[(DefaultNameStep): " + getPrefix() + ":" + getLocalName() + "[" + super.toString() + "]]"; 141 } 142 matches(Object node, ContextSupport contextSupport)143 public boolean matches(Object node, 144 ContextSupport contextSupport) 145 { 146 //System.err.println( "DefaultNameStep.matches(" + node + ")" ); 147 148 Navigator nav = contextSupport.getNavigator(); 149 150 String myPrefix = getPrefix(); 151 String myUri = null; 152 boolean hasPrefix = ( myPrefix != null ) && (! ( "".equals( myPrefix ) ) ); 153 154 String nodeUri = null; 155 String nodeName = null; 156 157 if ( nav.isElement( node ) ) 158 { 159 nodeUri = nav.getElementNamespaceUri( node ); 160 nodeName = nav.getElementName( node ); 161 } 162 else if ( nav.isAttribute( node ) ) 163 { 164 nodeUri = nav.getAttributeNamespaceUri( node ); 165 nodeName = nav.getAttributeName( node ); 166 } 167 else if ( nav.isDocument( node ) ) 168 { 169 return ( ! hasPrefix ) && matchesAnyName; 170 } 171 else if ( nav.isNamespace( node ) ) 172 { 173 nodeUri = null; 174 nodeName = nav.getNamespacePrefix( node ); 175 } 176 else 177 { 178 // * will only match elements on most axis 179 return false; 180 } 181 182 // System.out.println( "Matching nodeURI: " + nodeUri + " name: " + nodeName ); 183 184 185 if ( hasPrefix ) 186 { 187 myUri = contextSupport.translateNamespacePrefixToUri( myPrefix ); 188 } 189 else if ( matchesAnyName ) 190 { 191 return true; 192 } 193 194 // If we have a prefix that does not map to no namespace, 195 // but the node doesn't have *any* namespace-uri, then we fast-fail. 196 197 if ( ( myUri != null && !"".equals( myUri ) ) 198 && 199 ( nodeUri == null || "".equals( nodeUri ) ) ) 200 { 201 return false; 202 } 203 204 // If we don't have a prefix, but the node does 205 // have any namespace-uri, then we fast-fail. 206 207 if ( ! hasPrefix 208 && 209 ( nodeUri != null 210 && 211 ! "".equals( nodeUri ) ) ) 212 { 213 return false; 214 } 215 216 // To fail-fast, we check the equality of 217 // local-names first. Shorter strings compare 218 // quicker. 219 220 if ( getLocalName().equals( nodeName ) 221 || 222 matchesAnyName ) 223 { 224 if ( ! hasPrefix ) 225 { 226 return true; 227 } 228 229 return matchesNamespaceURIs( myUri, 230 nodeUri ); 231 } 232 233 return false; 234 } 235 236 /** @return true if the two namespace URIs are equal 237 * Note that we may wish to consider null being equal to "" 238 */ matchesNamespaceURIs( String u1, String u2 )239 protected boolean matchesNamespaceURIs( String u1, String u2 ) { 240 //System.out.println( "Comparing URI: " + u1 + " against URI: " + u2 ); 241 242 if ( u1 == u2 ) { 243 return true; 244 } 245 if ( u1 == null ) 246 { 247 u1 = ""; 248 } 249 if ( u2 == null ) 250 { 251 u2 = ""; 252 } 253 return u1.equals( u2 ); 254 } 255 256 } 257