001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.xerces.xpointer;
018:
019: import org.apache.xerces.impl.Constants;
020: import org.apache.xerces.impl.dv.XSSimpleType;
021: import org.apache.xerces.util.SymbolTable;
022: import org.apache.xerces.xni.Augmentations;
023: import org.apache.xerces.xni.QName;
024: import org.apache.xerces.xni.XMLAttributes;
025: import org.apache.xerces.xni.XNIException;
026: import org.apache.xerces.xs.AttributePSVI;
027: import org.apache.xerces.xs.XSTypeDefinition;
028:
029: /**
030: * <p>
031: * Implements the XPointerPart interface and handles processing of
032: * ShortHand Pointers. It identifies at most one element in the
033: * resource's information set; specifically, the first one (if any)
034: * in document order that has a matching NCName as an identifier.
035: * </p>
036: *
037: * @version $Id: ShortHandPointer.java 447248 2006-09-18 05:25:21Z mrglavas $
038: *
039: */
040: class ShortHandPointer implements XPointerPart {
041:
042: // The name of the ShortHand pointer
043: private String fShortHandPointer;
044:
045: // The name of the ShortHand pointer
046: private boolean fIsFragmentResolved = false;
047:
048: // SymbolTable
049: private SymbolTable fSymbolTable;
050:
051: //
052: // Constructors
053: //
054: public ShortHandPointer() {
055: }
056:
057: public ShortHandPointer(SymbolTable symbolTable) {
058: fSymbolTable = symbolTable;
059: }
060:
061: /**
062: * The XPointerProcessor takes care of this. Simply set the ShortHand Pointer here.
063: *
064: * @see org.apache.xerces.xpointer.XPointerPart#parseXPointer(java.lang.String)
065: */
066: public void parseXPointer(String part) throws XNIException {
067: fShortHandPointer = part;
068: // reset fIsFragmentResolved
069: fIsFragmentResolved = false;
070: }
071:
072: /**
073: * Resolves the XPointer ShortHand pointer based on the rules defined in
074: * Section 3.2 of the XPointer Framework Recommendation.
075: * Note that in the current implementation only supports DTD determined ID's.
076: *
077: * @see org.apache.xerces.xpointer.XPointerPart#resolveXPointer(org.apache.xerces.xni.QName, org.apache.xerces.xni.XMLAttributes, org.apache.xerces.xni.Augmentations, int event)
078: */
079: int fMatchingChildCount = 0;
080:
081: public boolean resolveXPointer(QName element,
082: XMLAttributes attributes, Augmentations augs, int event)
083: throws XNIException {
084:
085: // reset fIsFragmentResolved
086: if (fMatchingChildCount == 0) {
087: fIsFragmentResolved = false;
088: }
089:
090: // On startElement or emptyElement, if no matching elements or parent
091: // elements were found, check for a matching idenfitier.
092: if (event == XPointerPart.EVENT_ELEMENT_START) {
093: if (fMatchingChildCount == 0) {
094: fIsFragmentResolved = hasMatchingIdentifier(element,
095: attributes, augs, event);
096: }
097: if (fIsFragmentResolved) {
098: fMatchingChildCount++;
099: }
100: } else if (event == XPointerPart.EVENT_ELEMENT_EMPTY) {
101: if (fMatchingChildCount == 0) {
102: fIsFragmentResolved = hasMatchingIdentifier(element,
103: attributes, augs, event);
104: }
105: } else {
106: // On endElement, decrease the matching child count if the child or
107: // its parent was resolved.
108: if (fIsFragmentResolved) {
109: fMatchingChildCount--;
110: }
111: }
112:
113: return fIsFragmentResolved;
114: }
115:
116: /**
117: *
118: * @param element
119: * @param attributes
120: * @param augs
121: * @param event
122: * @return
123: * @throws XNIException
124: */
125: private boolean hasMatchingIdentifier(QName element,
126: XMLAttributes attributes, Augmentations augs, int event)
127: throws XNIException {
128: String normalizedValue = null;
129:
130: // The identifiers of an element are determined by the
131: // ShortHand Pointer as follows:
132:
133: if (attributes != null) {
134: for (int i = 0; i < attributes.getLength(); i++) {
135:
136: // 1. If an element information item has an attribute information item
137: // among its [attributes] that is a schema-determined ID, then it is
138: // identified by the value of that attribute information item's
139: // [schema normalized value] property;
140: normalizedValue = getSchemaDeterminedID(attributes, i);
141: if (normalizedValue != null) {
142: break;
143: }
144:
145: // 2. If an element information item has an element information item among
146: // its [children] that is a schema-determined ID, then it is identified by
147: // the value of that element information item's [schema normalized value] property;
148: // ???
149: normalizedValue = getChildrenSchemaDeterminedID(
150: attributes, i);
151: if (normalizedValue != null) {
152: break;
153: }
154:
155: // 3. If an element information item has an attribute information item among
156: // its [attributes] that is a DTD-determined ID, then it is identified by the
157: // value of that attribute information item's [normalized value] property.
158: // An attribute information item is a DTD-determined ID if and only if it has
159: // a [type definition] property whose value is equal to ID.
160: normalizedValue = getDTDDeterminedID(attributes, i);
161: if (normalizedValue != null) {
162: break;
163: }
164: // 4. No externally determined ID's
165: }
166: }
167:
168: if (normalizedValue != null
169: && normalizedValue.equals(fShortHandPointer)) {
170: return true;
171: }
172:
173: return false;
174: }
175:
176: /**
177: * Rerturns the DTD determine-ID
178: *
179: * @param attributes
180: * @param index
181: * @return String
182: * @throws XNIException
183: */
184: public String getDTDDeterminedID(XMLAttributes attributes, int index)
185: throws XNIException {
186:
187: if (attributes.getType(index).equals("ID")) {
188: return attributes.getValue(index);
189: }
190: return null;
191: }
192:
193: /**
194: * Returns the schema-determined-ID.
195: *
196: *
197: * @param attributes
198: * @param index
199: * @return A String containing the schema-determined ID.
200: * @throws XNIException
201: */
202: public String getSchemaDeterminedID(XMLAttributes attributes,
203: int index) throws XNIException {
204: Augmentations augs = attributes.getAugmentations(index);
205: AttributePSVI attrPSVI = (AttributePSVI) augs
206: .getItem(Constants.ATTRIBUTE_PSVI);
207:
208: if (attrPSVI != null) {
209: // An element or attribute information item is a schema-determined
210: // ID if and only if one of the following is true:]
211:
212: // 1. It has a [member type definition] or [type definition] property
213: // whose value in turn has [name] equal to ID and [target namespace]
214: // equal to http://www.w3.org/2001/XMLSchema;
215:
216: // 2. It has a [base type definition] whose value has that [name] and [target namespace];
217:
218: // 3. It has a [base type definition] whose value has a [base type definition]
219: // whose value has that [name] and [target namespace], and so on following
220: // the [base type definition] property recursively;
221:
222: XSTypeDefinition typeDef = attrPSVI
223: .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(
248: XMLAttributes attributes, int index) throws XNIException {
249: return null;
250: }
251:
252: /**
253: *
254: * @see org.apache.xerces.xpointer.XPointerPart#isFragmentResolved()
255: */
256: public boolean isFragmentResolved() {
257: return fIsFragmentResolved;
258: }
259:
260: /**
261: *
262: * @see org.apache.xerces.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 org.apache.xerces.xpointer.XPointerPart#getSchemeName()
272: */
273: public String getSchemeName() {
274: return fShortHandPointer;
275: }
276:
277: /**
278: * @see org.apache.xerces.xpointer.XPointerPart#getSchemeData()
279: */
280: public String getSchemeData() {
281: return null;
282: }
283:
284: /**
285: * @see org.apache.xerces.xpointer.XPointerPart#setSchemeName(java.lang.String)
286: */
287: public void setSchemeName(String schemeName) {
288: fShortHandPointer = schemeName;
289: }
290:
291: /**
292: * @see org.apache.xerces.xpointer.XPointerPart#setSchemeData(java.lang.String)
293: */
294: public void setSchemeData(String schemeData) {
295: // NA
296: }
297: }
|