1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /* 6 * Licensed to the Apache Software Foundation (ASF) under one or more 7 * contributor license agreements. See the NOTICE file distributed with 8 * this work for additional information regarding copyright ownership. 9 * The ASF licenses this file to You under the Apache License, Version 2.0 10 * (the "License"); you may not use this file except in compliance with 11 * the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 */ 21 22 package com.sun.org.apache.xerces.internal.xpointer; 23 24 import com.sun.org.apache.xerces.internal.impl.Constants; 25 import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType; 26 import com.sun.org.apache.xerces.internal.util.SymbolTable; 27 import com.sun.org.apache.xerces.internal.xni.Augmentations; 28 import com.sun.org.apache.xerces.internal.xni.QName; 29 import com.sun.org.apache.xerces.internal.xni.XMLAttributes; 30 import com.sun.org.apache.xerces.internal.xni.XNIException; 31 import com.sun.org.apache.xerces.internal.xs.AttributePSVI; 32 import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition; 33 34 /** 35 * <p> 36 * Implements the XPointerPart interface and handles processing of 37 * ShortHand Pointers. It identifies at most one element in the 38 * resource's information set; specifically, the first one (if any) 39 * in document order that has a matching NCName as an identifier. 40 * </p> 41 * 42 */ 43 final class ShortHandPointer implements XPointerPart { 44 45 // The name of the ShortHand pointer 46 private String fShortHandPointer; 47 48 // The name of the ShortHand pointer 49 private boolean fIsFragmentResolved = false; 50 51 // SymbolTable 52 private SymbolTable fSymbolTable; 53 54 // 55 // Constructors 56 // 57 public ShortHandPointer() { 58 } 59 60 public ShortHandPointer(SymbolTable symbolTable) { 61 fSymbolTable = symbolTable; 62 } 63 64 /** 65 * The XPointerProcessor takes care of this. Simply set the ShortHand Pointer here. 66 * 67 * @see com.sun.org.apache.xerces.internal.xpointer.XPointerPart#parseXPointer(java.lang.String) 68 */ 69 public void parseXPointer(String part) throws XNIException { 70 fShortHandPointer = part; 71 // reset fIsFragmentResolved 72 fIsFragmentResolved = false; 73 } 74 75 /** 76 * Resolves the XPointer ShortHand pointer based on the rules defined in 77 * Section 3.2 of the XPointer Framework Recommendation. 78 * Note that in the current implementation only supports DTD determined ID's. 79 * 80 * @see com.sun.org.apache.xerces.internal.xpointer.XPointerPart#resolveXPointer(com.sun.org.apache.xerces.internal.xni.QName, com.sun.org.apache.xerces.internal.xni.XMLAttributes, com.sun.org.apache.xerces.internal.xni.Augmentations, int event) 81 */ 82 int fMatchingChildCount = 0; 83 public boolean resolveXPointer(QName element, XMLAttributes attributes, 84 Augmentations augs, int event) throws XNIException { 85 86 // reset fIsFragmentResolved 87 if (fMatchingChildCount == 0) { 88 fIsFragmentResolved = false; 89 } 90 91 // On startElement or emptyElement, if no matching elements or parent 92 // elements were found, check for a matching idenfitier. 93 if (event == XPointerPart.EVENT_ELEMENT_START) { 94 if (fMatchingChildCount == 0) { 95 fIsFragmentResolved = hasMatchingIdentifier(element, attributes, augs, 96 event); 97 } 98 if (fIsFragmentResolved) { 99 fMatchingChildCount++; 100 } 101 } else if (event == XPointerPart.EVENT_ELEMENT_EMPTY) { 102 if (fMatchingChildCount == 0) { 103 fIsFragmentResolved = hasMatchingIdentifier(element, attributes, augs, 104 event); 105 } 106 } 107 else { 108 // On endElement, decrease the matching child count if the child or 109 // its parent was resolved. 110 if (fIsFragmentResolved) { 111 fMatchingChildCount--; 112 } 113 } 114 115 return fIsFragmentResolved ; 116 } 117 118 /** 119 * 120 * @param element 121 * @param attributes 122 * @param augs 123 * @param event 124 * @return 125 * @throws XNIException 126 */ 127 private boolean hasMatchingIdentifier(QName element, 128 XMLAttributes attributes, Augmentations augs, int event) 129 throws XNIException { 130 String normalizedValue = null; 131 132 // The identifiers of an element are determined by the 133 // ShortHand Pointer as follows: 134 135 if (attributes != null) { 136 for (int i = 0; i < attributes.getLength(); i++) { 137 138 // 1. If an element information item has an attribute information item 139 // among its [attributes] that is a schema-determined ID, then it is 140 // identified by the value of that attribute information item's 141 // [schema normalized value] property; 142 normalizedValue = getSchemaDeterminedID(attributes, i); 143 if (normalizedValue != null) { 144 break; 145 } 146 147 // 2. If an element information item has an element information item among 148 // its [children] that is a schema-determined ID, then it is identified by 149 // the value of that element information item's [schema normalized value] property; 150 // ??? 151 normalizedValue = getChildrenSchemaDeterminedID(attributes, i); 152 if (normalizedValue != null) { 153 break; 154 } 155 156 // 3. If an element information item has an attribute information item among 157 // its [attributes] that is a DTD-determined ID, then it is identified by the 158 // value of that attribute information item's [normalized value] property. 159 // An attribute information item is a DTD-determined ID if and only if it has 160 // a [type definition] property whose value is equal to ID. 161 normalizedValue = getDTDDeterminedID(attributes, i); 162 if (normalizedValue != null) { 163 break; 164 } 165 // 4. No externally determined ID's 166 } 167 } 168 169 if (normalizedValue != null 170 && normalizedValue.equals(fShortHandPointer)) { 171 return true; 172 } 173 174 return false; 175 } 176 177 /** 178 * Rerturns the DTD determine-ID 179 * 180 * @param attributes 181 * @param index 182 * @return String 183 * @throws XNIException 184 */ 185 public String getDTDDeterminedID(XMLAttributes attributes, int index) 186 throws XNIException { 187 188 if (attributes.getType(index).equals("ID")) { 189 return attributes.getValue(index); 190 } 191 return null; 192 } 193 194 /** 195 * Returns the schema-determined-ID. 196 * 197 * 198 * @param attributes 199 * @param index 200 * @return A String containing the schema-determined ID. 201 * @throws XNIException 202 */ 203 public String getSchemaDeterminedID(XMLAttributes attributes, int index) 204 throws XNIException { 205 Augmentations augs = attributes.getAugmentations(index); 206 AttributePSVI attrPSVI = (AttributePSVI) augs 207 .getItem(Constants.ATTRIBUTE_PSVI); 208 209 if (attrPSVI != null) { 210 // An element or attribute information item is a schema-determined 211 // ID if and only if one of the following is true:] 212 213 // 1. It has a [member type definition] or [type definition] property 214 // whose value in turn has [name] equal to ID and [target namespace] 215 // equal to http://www.w3.org/2001/XMLSchema; 216 217 // 2. It has a [base type definition] whose value has that [name] and [target namespace]; 218 219 // 3. It has a [base type definition] whose value has a [base type definition] 220 // whose value has that [name] and [target namespace], and so on following 221 // the [base type definition] property recursively; 222 223 XSTypeDefinition typeDef = attrPSVI.getMemberTypeDefinition(); 224 if (typeDef != null) { 225 typeDef = attrPSVI.getTypeDefinition(); 226 } 227 228 // 229 if (typeDef != null && ((XSSimpleType) typeDef).isIDType()) { 230 return attrPSVI.getSchemaNormalizedValue(); 231 } 232 233 // 4 & 5 NA 234 } 235 236 return null; 237 } 238 239 /** 240 * Not quite sure how this can be correctly implemented. 241 * 242 * @param attributes 243 * @param index 244 * @return String - We return null since we currenly do not supprt this. 245 * @throws XNIException 246 */ 247 public String getChildrenSchemaDeterminedID(XMLAttributes attributes, 248 int index) throws XNIException { 249 return null; 250 } 251 252 /** 253 * 254 * @see com.sun.org.apache.xerces.internal.xpointer.XPointerPart#isFragmentResolved() 255 */ 256 public boolean isFragmentResolved() { 257 return fIsFragmentResolved; 258 } 259 260 /** 261 * 262 * @see com.sun.org.apache.xerces.internal.xpointer.XPointerPart#isChildFragmentResolved() 263 */ 264 public boolean isChildFragmentResolved() { 265 return fIsFragmentResolved && ( fMatchingChildCount > 0); 266 } 267 268 /** 269 * Returns the name of the ShortHand pointer 270 * 271 * @see com.sun.org.apache.xerces.internal.xpointer.XPointerPart#getSchemeName() 272 */ 273 public String getSchemeName() { 274 return fShortHandPointer; 275 } 276 277 /** 278 * @see com.sun.org.apache.xerces.internal.xpointer.XPointerPart#getSchemeData() 279 */ 280 public String getSchemeData() { 281 return null; 282 } 283 284 /** 285 * @see com.sun.org.apache.xerces.internal.xpointer.XPointerPart#setSchemeName(java.lang.String) 286 */ 287 public void setSchemeName(String schemeName) { 288 fShortHandPointer = schemeName; 289 } 290 291 /** 292 * @see com.sun.org.apache.xerces.internal.xpointer.XPointerPart#setSchemeData(java.lang.String) 293 */ 294 public void setSchemeData(String schemeData) { 295 // NA 296 } 297 }