12005
|
1 |
/*
|
|
2 |
* reserved comment block
|
|
3 |
* DO NOT REMOVE OR ALTER!
|
|
4 |
*/
|
|
5 |
/*
|
|
6 |
* Copyright 2001-2004 The Apache Software Foundation.
|
|
7 |
*
|
|
8 |
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
9 |
* you may not use this file except in compliance with the License.
|
|
10 |
* You may obtain a copy of the License at
|
|
11 |
*
|
|
12 |
* http://www.apache.org/licenses/LICENSE-2.0
|
|
13 |
*
|
|
14 |
* Unless required by applicable law or agreed to in writing, software
|
|
15 |
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
16 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
17 |
* See the License for the specific language governing permissions and
|
|
18 |
* limitations under the License.
|
|
19 |
*/
|
|
20 |
|
|
21 |
package com.sun.org.apache.xerces.internal.impl.xs.traversers;
|
|
22 |
|
|
23 |
import java.util.Locale;
|
|
24 |
import java.util.Vector;
|
|
25 |
|
|
26 |
import com.sun.org.apache.xerces.internal.impl.dv.InvalidDatatypeValueException;
|
|
27 |
import com.sun.org.apache.xerces.internal.impl.dv.XSFacets;
|
|
28 |
import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType;
|
|
29 |
import com.sun.org.apache.xerces.internal.impl.validation.ValidationState;
|
|
30 |
import com.sun.org.apache.xerces.internal.impl.xs.SchemaGrammar;
|
|
31 |
import com.sun.org.apache.xerces.internal.impl.xs.SchemaSymbols;
|
|
32 |
import com.sun.org.apache.xerces.internal.impl.xs.XSAnnotationImpl;
|
|
33 |
import com.sun.org.apache.xerces.internal.impl.xs.XSAttributeGroupDecl;
|
|
34 |
import com.sun.org.apache.xerces.internal.impl.xs.XSAttributeUseImpl;
|
|
35 |
import com.sun.org.apache.xerces.internal.impl.xs.XSComplexTypeDecl;
|
|
36 |
import com.sun.org.apache.xerces.internal.impl.xs.XSElementDecl;
|
|
37 |
import com.sun.org.apache.xerces.internal.impl.xs.XSParticleDecl;
|
|
38 |
import com.sun.org.apache.xerces.internal.impl.xs.XSWildcardDecl;
|
|
39 |
import com.sun.org.apache.xerces.internal.impl.xs.util.XInt;
|
|
40 |
import com.sun.org.apache.xerces.internal.impl.xs.util.XSObjectListImpl;
|
|
41 |
import com.sun.org.apache.xerces.internal.util.DOMUtil;
|
|
42 |
import com.sun.org.apache.xerces.internal.util.NamespaceSupport;
|
|
43 |
import com.sun.org.apache.xerces.internal.util.SymbolTable;
|
|
44 |
import com.sun.org.apache.xerces.internal.xni.QName;
|
|
45 |
import com.sun.org.apache.xerces.internal.xs.XSAttributeUse;
|
|
46 |
import com.sun.org.apache.xerces.internal.xs.XSObjectList;
|
|
47 |
import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition;
|
|
48 |
import org.w3c.dom.Element;
|
|
49 |
|
|
50 |
/**
|
|
51 |
* Class <code>XSDAbstractTraverser</code> serves as the base class for all
|
|
52 |
* other <code>XSD???Traverser</code>s. It holds the common data and provide
|
|
53 |
* a unified way to initialize these data.
|
|
54 |
*
|
|
55 |
* @xerces.internal
|
|
56 |
*
|
|
57 |
* @author Elena Litani, IBM
|
|
58 |
* @author Rahul Srivastava, Sun Microsystems Inc.
|
|
59 |
* @author Neeraj Bajaj, Sun Microsystems Inc.
|
|
60 |
*
|
|
61 |
* @version $Id: XSDAbstractTraverser.java,v 1.8 2010-11-01 04:40:02 joehw Exp $
|
|
62 |
*/
|
|
63 |
abstract class XSDAbstractTraverser {
|
|
64 |
|
|
65 |
protected static final String NO_NAME = "(no name)";
|
|
66 |
|
|
67 |
// Flags for checkOccurrences to indicate any special
|
|
68 |
// restrictions on minOccurs and maxOccurs relating to "all".
|
|
69 |
// NOT_ALL_CONTEXT - not processing an <all>
|
|
70 |
// PROCESSING_ALL_EL - processing an <element> in an <all>
|
|
71 |
// GROUP_REF_WITH_ALL - processing <group> reference that contained <all>
|
|
72 |
// CHILD_OF_GROUP - processing a child of a model group definition
|
|
73 |
// PROCESSING_ALL_GP - processing an <all> group itself
|
|
74 |
|
|
75 |
protected static final int NOT_ALL_CONTEXT = 0;
|
|
76 |
protected static final int PROCESSING_ALL_EL = 1;
|
|
77 |
protected static final int GROUP_REF_WITH_ALL = 2;
|
|
78 |
protected static final int CHILD_OF_GROUP = 4;
|
|
79 |
protected static final int PROCESSING_ALL_GP = 8;
|
|
80 |
|
|
81 |
//Shared data
|
|
82 |
protected XSDHandler fSchemaHandler = null;
|
|
83 |
protected SymbolTable fSymbolTable = null;
|
|
84 |
protected XSAttributeChecker fAttrChecker = null;
|
|
85 |
protected boolean fValidateAnnotations = false;
|
|
86 |
|
|
87 |
// used to validate default/fixed attribute values
|
|
88 |
ValidationState fValidationState = new ValidationState();
|
|
89 |
|
|
90 |
XSDAbstractTraverser (XSDHandler handler,
|
|
91 |
XSAttributeChecker attrChecker) {
|
|
92 |
fSchemaHandler = handler;
|
|
93 |
fAttrChecker = attrChecker;
|
|
94 |
}
|
|
95 |
|
|
96 |
void reset(SymbolTable symbolTable, boolean validateAnnotations, Locale locale) {
|
|
97 |
fSymbolTable = symbolTable;
|
|
98 |
fValidateAnnotations = validateAnnotations;
|
|
99 |
fValidationState.setExtraChecking(false);
|
|
100 |
fValidationState.setSymbolTable(symbolTable);
|
|
101 |
fValidationState.setLocale(locale);
|
|
102 |
}
|
|
103 |
|
|
104 |
// traverse the annotation declaration
|
|
105 |
// REVISIT: how to pass the parentAttrs? as DOM attributes?
|
|
106 |
// as name/value pairs (string)? in parsed form?
|
|
107 |
// @return XSAnnotationImpl object
|
|
108 |
XSAnnotationImpl traverseAnnotationDecl(Element annotationDecl, Object[] parentAttrs,
|
|
109 |
boolean isGlobal, XSDocumentInfo schemaDoc) {
|
|
110 |
// General Attribute Checking
|
|
111 |
Object[] attrValues = fAttrChecker.checkAttributes(annotationDecl, isGlobal, schemaDoc);
|
|
112 |
fAttrChecker.returnAttrArray(attrValues, schemaDoc);
|
|
113 |
|
|
114 |
String contents = DOMUtil.getAnnotation(annotationDecl);
|
|
115 |
Element child = DOMUtil.getFirstChildElement(annotationDecl);
|
|
116 |
if (child != null) {
|
|
117 |
do {
|
|
118 |
String name = DOMUtil.getLocalName(child);
|
|
119 |
|
|
120 |
// the only valid children of "annotation" are
|
|
121 |
// "appinfo" and "documentation"
|
|
122 |
if (!((name.equals(SchemaSymbols.ELT_APPINFO)) ||
|
|
123 |
(name.equals(SchemaSymbols.ELT_DOCUMENTATION)))) {
|
|
124 |
reportSchemaError("src-annotation", new Object[]{name}, child);
|
|
125 |
}
|
|
126 |
else {
|
|
127 |
// General Attribute Checking
|
|
128 |
// There is no difference between global or local appinfo/documentation,
|
|
129 |
// so we assume it's always global.
|
|
130 |
attrValues = fAttrChecker.checkAttributes(child, true, schemaDoc);
|
|
131 |
fAttrChecker.returnAttrArray(attrValues, schemaDoc);
|
|
132 |
}
|
|
133 |
|
|
134 |
child = DOMUtil.getNextSiblingElement(child);
|
|
135 |
}
|
|
136 |
while (child != null);
|
|
137 |
}
|
|
138 |
// if contents was null, must have been some kind of error;
|
|
139 |
// nothing to contribute to PSVI
|
|
140 |
if (contents == null) return null;
|
|
141 |
|
|
142 |
// find the grammar; fSchemaHandler must be known!
|
|
143 |
SchemaGrammar grammar = fSchemaHandler.getGrammar(schemaDoc.fTargetNamespace);
|
|
144 |
// fish out local attributes passed from parent
|
|
145 |
Vector annotationLocalAttrs = (Vector)parentAttrs[XSAttributeChecker.ATTIDX_NONSCHEMA];
|
|
146 |
// optimize for case where there are no local attributes
|
|
147 |
if(annotationLocalAttrs != null && !annotationLocalAttrs.isEmpty()) {
|
|
148 |
StringBuffer localStrBuffer = new StringBuffer(64);
|
|
149 |
localStrBuffer.append(" ");
|
|
150 |
// Vector should contain rawname value pairs
|
|
151 |
int i = 0;
|
|
152 |
while (i < annotationLocalAttrs.size()) {
|
|
153 |
String rawname = (String)annotationLocalAttrs.elementAt(i++);
|
|
154 |
int colonIndex = rawname.indexOf(':');
|
|
155 |
String prefix, localpart;
|
|
156 |
if (colonIndex == -1) {
|
|
157 |
prefix = "";
|
|
158 |
localpart = rawname;
|
|
159 |
}
|
|
160 |
else {
|
|
161 |
prefix = rawname.substring(0,colonIndex);
|
|
162 |
localpart = rawname.substring(colonIndex+1);
|
|
163 |
}
|
|
164 |
String uri = schemaDoc.fNamespaceSupport.getURI(fSymbolTable.addSymbol(prefix));
|
|
165 |
if (annotationDecl.getAttributeNS(uri, localpart).length() != 0) {
|
|
166 |
i++; // skip the next value, too
|
|
167 |
continue;
|
|
168 |
}
|
|
169 |
localStrBuffer.append(rawname)
|
|
170 |
.append("=\"");
|
|
171 |
String value = (String)annotationLocalAttrs.elementAt(i++);
|
|
172 |
// search for pesky "s and <s within attr value:
|
|
173 |
value = processAttValue(value);
|
|
174 |
localStrBuffer.append(value)
|
|
175 |
.append("\" ");
|
|
176 |
}
|
|
177 |
// and now splice it into place; immediately after the annotation token, for simplicity's sake
|
|
178 |
StringBuffer contentBuffer = new StringBuffer(contents.length() + localStrBuffer.length());
|
|
179 |
int annotationTokenEnd = contents.indexOf(SchemaSymbols.ELT_ANNOTATION);
|
|
180 |
// annotation must occur somewhere or we're in big trouble...
|
|
181 |
if(annotationTokenEnd == -1) return null;
|
|
182 |
annotationTokenEnd += SchemaSymbols.ELT_ANNOTATION.length();
|
|
183 |
contentBuffer.append(contents.substring(0,annotationTokenEnd));
|
|
184 |
contentBuffer.append(localStrBuffer.toString());
|
|
185 |
contentBuffer.append(contents.substring(annotationTokenEnd, contents.length()));
|
|
186 |
final String annotation = contentBuffer.toString();
|
|
187 |
if (fValidateAnnotations) {
|
|
188 |
schemaDoc.addAnnotation(new XSAnnotationInfo(annotation, annotationDecl));
|
|
189 |
}
|
|
190 |
return new XSAnnotationImpl(annotation, grammar);
|
|
191 |
} else {
|
|
192 |
if (fValidateAnnotations) {
|
|
193 |
schemaDoc.addAnnotation(new XSAnnotationInfo(contents, annotationDecl));
|
|
194 |
}
|
|
195 |
return new XSAnnotationImpl(contents, grammar);
|
|
196 |
}
|
|
197 |
|
|
198 |
}
|
|
199 |
|
|
200 |
XSAnnotationImpl traverseSyntheticAnnotation(Element annotationParent, String initialContent,
|
|
201 |
Object[] parentAttrs, boolean isGlobal, XSDocumentInfo schemaDoc) {
|
|
202 |
|
|
203 |
String contents = initialContent;
|
|
204 |
|
|
205 |
// find the grammar; fSchemaHandler must be known!
|
|
206 |
SchemaGrammar grammar = fSchemaHandler.getGrammar(schemaDoc.fTargetNamespace);
|
|
207 |
// fish out local attributes passed from parent
|
|
208 |
Vector annotationLocalAttrs = (Vector)parentAttrs[XSAttributeChecker.ATTIDX_NONSCHEMA];
|
|
209 |
// optimize for case where there are no local attributes
|
|
210 |
if (annotationLocalAttrs != null && !annotationLocalAttrs.isEmpty()) {
|
|
211 |
StringBuffer localStrBuffer = new StringBuffer(64);
|
|
212 |
localStrBuffer.append(" ");
|
|
213 |
// Vector should contain rawname value pairs
|
|
214 |
int i = 0;
|
|
215 |
while (i < annotationLocalAttrs.size()) {
|
|
216 |
String rawname = (String)annotationLocalAttrs.elementAt(i++);
|
|
217 |
int colonIndex = rawname.indexOf(':');
|
|
218 |
String prefix, localpart;
|
|
219 |
if (colonIndex == -1) {
|
|
220 |
prefix = "";
|
|
221 |
localpart = rawname;
|
|
222 |
}
|
|
223 |
else {
|
|
224 |
prefix = rawname.substring(0,colonIndex);
|
|
225 |
localpart = rawname.substring(colonIndex+1);
|
|
226 |
}
|
|
227 |
String uri = schemaDoc.fNamespaceSupport.getURI(fSymbolTable.addSymbol(prefix));
|
|
228 |
localStrBuffer.append(rawname)
|
|
229 |
.append("=\"");
|
|
230 |
String value = (String)annotationLocalAttrs.elementAt(i++);
|
|
231 |
// search for pesky "s and <s within attr value:
|
|
232 |
value = processAttValue(value);
|
|
233 |
localStrBuffer.append(value)
|
|
234 |
.append("\" ");
|
|
235 |
}
|
|
236 |
// and now splice it into place; immediately after the annotation token, for simplicity's sake
|
|
237 |
StringBuffer contentBuffer = new StringBuffer(contents.length() + localStrBuffer.length());
|
|
238 |
int annotationTokenEnd = contents.indexOf(SchemaSymbols.ELT_ANNOTATION);
|
|
239 |
// annotation must occur somewhere or we're in big trouble...
|
|
240 |
if(annotationTokenEnd == -1) return null;
|
|
241 |
annotationTokenEnd += SchemaSymbols.ELT_ANNOTATION.length();
|
|
242 |
contentBuffer.append(contents.substring(0,annotationTokenEnd));
|
|
243 |
contentBuffer.append(localStrBuffer.toString());
|
|
244 |
contentBuffer.append(contents.substring(annotationTokenEnd, contents.length()));
|
|
245 |
final String annotation = contentBuffer.toString();
|
|
246 |
if (fValidateAnnotations) {
|
|
247 |
schemaDoc.addAnnotation(new XSAnnotationInfo(annotation, annotationParent));
|
|
248 |
}
|
|
249 |
return new XSAnnotationImpl(annotation, grammar);
|
|
250 |
} else {
|
|
251 |
if (fValidateAnnotations) {
|
|
252 |
schemaDoc.addAnnotation(new XSAnnotationInfo(contents, annotationParent));
|
|
253 |
}
|
|
254 |
return new XSAnnotationImpl(contents, grammar);
|
|
255 |
}
|
|
256 |
}
|
|
257 |
|
|
258 |
// the QName simple type used to resolve qnames
|
|
259 |
private static final XSSimpleType fQNameDV = (XSSimpleType)SchemaGrammar.SG_SchemaNS.getGlobalTypeDecl(SchemaSymbols.ATTVAL_QNAME);
|
|
260 |
// Temp data structures to be re-used in traversing facets
|
|
261 |
private StringBuffer fPattern = new StringBuffer();
|
|
262 |
private final XSFacets xsFacets = new XSFacets();
|
|
263 |
|
|
264 |
static final class FacetInfo {
|
|
265 |
|
|
266 |
final XSFacets facetdata;
|
|
267 |
final Element nodeAfterFacets;
|
|
268 |
final short fPresentFacets;
|
|
269 |
final short fFixedFacets;
|
|
270 |
|
|
271 |
FacetInfo(XSFacets facets, Element nodeAfterFacets, short presentFacets, short fixedFacets) {
|
|
272 |
facetdata = facets;
|
|
273 |
this.nodeAfterFacets = nodeAfterFacets;
|
|
274 |
fPresentFacets = presentFacets;
|
|
275 |
fFixedFacets = fixedFacets;
|
|
276 |
}
|
|
277 |
}
|
|
278 |
|
|
279 |
FacetInfo traverseFacets(Element content,
|
|
280 |
XSSimpleType baseValidator,
|
|
281 |
XSDocumentInfo schemaDoc) {
|
|
282 |
|
|
283 |
short facetsPresent = 0 ;
|
|
284 |
short facetsFixed = 0; // facets that have fixed="true"
|
|
285 |
String facet;
|
|
286 |
boolean hasQName = containsQName(baseValidator);
|
|
287 |
Vector enumData = null;
|
|
288 |
XSObjectListImpl enumAnnotations = null;
|
|
289 |
XSObjectListImpl patternAnnotations = null;
|
|
290 |
Vector enumNSDecls = hasQName ? new Vector() : null;
|
|
291 |
int currentFacet = 0;
|
|
292 |
xsFacets.reset();
|
|
293 |
while (content != null) {
|
|
294 |
// General Attribute Checking
|
|
295 |
Object[] attrs = null;
|
|
296 |
facet = DOMUtil.getLocalName(content);
|
|
297 |
if (facet.equals(SchemaSymbols.ELT_ENUMERATION)) {
|
|
298 |
attrs = fAttrChecker.checkAttributes(content, false, schemaDoc, hasQName);
|
|
299 |
String enumVal = (String)attrs[XSAttributeChecker.ATTIDX_VALUE];
|
|
300 |
// The facet can't be used if the value is missing. Ignore
|
|
301 |
// this facet element.
|
|
302 |
if (enumVal == null) {
|
|
303 |
reportSchemaError("s4s-att-must-appear", new Object[]{SchemaSymbols.ELT_ENUMERATION, SchemaSymbols.ATT_VALUE}, content);
|
|
304 |
fAttrChecker.returnAttrArray (attrs, schemaDoc);
|
|
305 |
content = DOMUtil.getNextSiblingElement(content);
|
|
306 |
continue;
|
|
307 |
}
|
|
308 |
|
|
309 |
NamespaceSupport nsDecls = (NamespaceSupport)attrs[XSAttributeChecker.ATTIDX_ENUMNSDECLS];
|
|
310 |
|
|
311 |
// for NOTATION types, need to check whether there is a notation
|
|
312 |
// declared with the same name as the enumeration value.
|
|
313 |
if (baseValidator.getVariety() == XSSimpleType.VARIETY_ATOMIC &&
|
|
314 |
baseValidator.getPrimitiveKind() == XSSimpleType.PRIMITIVE_NOTATION) {
|
|
315 |
// need to use the namespace context returned from checkAttributes
|
|
316 |
schemaDoc.fValidationContext.setNamespaceSupport(nsDecls);
|
|
317 |
Object notation = null;
|
|
318 |
try{
|
|
319 |
QName temp = (QName)fQNameDV.validate(enumVal, schemaDoc.fValidationContext, null);
|
|
320 |
// try to get the notation decl. if failed, getGlobalDecl
|
|
321 |
// reports an error, so we don't need to report one again.
|
|
322 |
notation = fSchemaHandler.getGlobalDecl(schemaDoc, XSDHandler.NOTATION_TYPE, temp, content);
|
|
323 |
}catch(InvalidDatatypeValueException ex){
|
|
324 |
reportSchemaError(ex.getKey(), ex.getArgs(), content);
|
|
325 |
}
|
|
326 |
if (notation == null) {
|
|
327 |
// Either the QName value is invalid, or it doens't
|
|
328 |
// resolve to a notation declaration.
|
|
329 |
// Ignore this facet, to avoid instance validation problems
|
|
330 |
fAttrChecker.returnAttrArray (attrs, schemaDoc);
|
|
331 |
content = DOMUtil.getNextSiblingElement(content);
|
|
332 |
continue;
|
|
333 |
}
|
|
334 |
// restore to the normal namespace context
|
|
335 |
schemaDoc.fValidationContext.setNamespaceSupport(schemaDoc.fNamespaceSupport);
|
|
336 |
}
|
|
337 |
if (enumData == null){
|
|
338 |
enumData = new Vector();
|
|
339 |
enumAnnotations = new XSObjectListImpl();
|
|
340 |
}
|
|
341 |
enumData.addElement(enumVal);
|
|
342 |
enumAnnotations.addXSObject(null);
|
|
343 |
if (hasQName)
|
|
344 |
enumNSDecls.addElement(nsDecls);
|
|
345 |
Element child = DOMUtil.getFirstChildElement( content );
|
|
346 |
|
|
347 |
if (child != null &&
|
|
348 |
DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION)) {
|
|
349 |
// traverse annotation if any
|
|
350 |
enumAnnotations.addXSObject(enumAnnotations.getLength()-1,traverseAnnotationDecl(child, attrs, false, schemaDoc));
|
|
351 |
child = DOMUtil.getNextSiblingElement(child);
|
|
352 |
}
|
|
353 |
else {
|
|
354 |
String text = DOMUtil.getSyntheticAnnotation(content);
|
|
355 |
if (text != null) {
|
|
356 |
enumAnnotations.addXSObject(enumAnnotations.getLength()-1, traverseSyntheticAnnotation(content, text, attrs, false, schemaDoc));
|
|
357 |
}
|
|
358 |
}
|
|
359 |
if (child !=null) {
|
|
360 |
reportSchemaError("s4s-elt-must-match.1", new Object[]{"enumeration", "(annotation?)", DOMUtil.getLocalName(child)}, child);
|
|
361 |
}
|
|
362 |
}
|
|
363 |
else if (facet.equals(SchemaSymbols.ELT_PATTERN)) {
|
|
364 |
facetsPresent |= XSSimpleType.FACET_PATTERN;
|
|
365 |
attrs = fAttrChecker.checkAttributes(content, false, schemaDoc);
|
|
366 |
String patternVal = (String)attrs[XSAttributeChecker.ATTIDX_VALUE];
|
|
367 |
// The facet can't be used if the value is missing. Ignore
|
|
368 |
// this facet element.
|
|
369 |
if (patternVal == null) {
|
|
370 |
reportSchemaError("s4s-att-must-appear", new Object[]{SchemaSymbols.ELT_PATTERN, SchemaSymbols.ATT_VALUE}, content);
|
|
371 |
fAttrChecker.returnAttrArray (attrs, schemaDoc);
|
|
372 |
content = DOMUtil.getNextSiblingElement(content);
|
|
373 |
continue;
|
|
374 |
}
|
|
375 |
|
|
376 |
if (fPattern.length() == 0) {
|
|
377 |
fPattern.append(patternVal);
|
|
378 |
} else {
|
|
379 |
// ---------------------------------------------
|
|
380 |
//datatypes: 5.2.4 pattern: src-multiple-pattern
|
|
381 |
// ---------------------------------------------
|
|
382 |
fPattern.append("|");
|
|
383 |
fPattern.append(patternVal);
|
|
384 |
}
|
|
385 |
Element child = DOMUtil.getFirstChildElement( content );
|
|
386 |
if (child != null &&
|
|
387 |
DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION)) {
|
|
388 |
// traverse annotation if any
|
|
389 |
if (patternAnnotations == null){
|
|
390 |
patternAnnotations = new XSObjectListImpl();
|
|
391 |
}
|
|
392 |
patternAnnotations.addXSObject(traverseAnnotationDecl(child, attrs, false, schemaDoc));
|
|
393 |
child = DOMUtil.getNextSiblingElement(child);
|
|
394 |
}
|
|
395 |
else {
|
|
396 |
String text = DOMUtil.getSyntheticAnnotation(content);
|
|
397 |
if (text != null) {
|
|
398 |
if (patternAnnotations == null){
|
|
399 |
patternAnnotations = new XSObjectListImpl();
|
|
400 |
}
|
|
401 |
patternAnnotations.addXSObject(traverseSyntheticAnnotation(content, text, attrs, false, schemaDoc));
|
|
402 |
}
|
|
403 |
}
|
|
404 |
if (child !=null) {
|
|
405 |
reportSchemaError("s4s-elt-must-match.1", new Object[]{"pattern", "(annotation?)", DOMUtil.getLocalName(child)}, child);
|
|
406 |
}
|
|
407 |
}
|
|
408 |
else {
|
|
409 |
if (facet.equals(SchemaSymbols.ELT_MINLENGTH)) {
|
|
410 |
currentFacet = XSSimpleType.FACET_MINLENGTH;
|
|
411 |
}
|
|
412 |
else if (facet.equals(SchemaSymbols.ELT_MAXLENGTH)) {
|
|
413 |
currentFacet = XSSimpleType.FACET_MAXLENGTH;
|
|
414 |
}
|
|
415 |
else if (facet.equals(SchemaSymbols.ELT_MAXEXCLUSIVE)) {
|
|
416 |
currentFacet = XSSimpleType.FACET_MAXEXCLUSIVE;
|
|
417 |
}
|
|
418 |
else if (facet.equals(SchemaSymbols.ELT_MAXINCLUSIVE)) {
|
|
419 |
currentFacet = XSSimpleType.FACET_MAXINCLUSIVE;
|
|
420 |
}
|
|
421 |
else if (facet.equals(SchemaSymbols.ELT_MINEXCLUSIVE)) {
|
|
422 |
currentFacet = XSSimpleType.FACET_MINEXCLUSIVE;
|
|
423 |
}
|
|
424 |
else if (facet.equals(SchemaSymbols.ELT_MININCLUSIVE)) {
|
|
425 |
currentFacet = XSSimpleType.FACET_MININCLUSIVE;
|
|
426 |
}
|
|
427 |
else if (facet.equals(SchemaSymbols.ELT_TOTALDIGITS)) {
|
|
428 |
currentFacet = XSSimpleType.FACET_TOTALDIGITS;
|
|
429 |
}
|
|
430 |
else if (facet.equals(SchemaSymbols.ELT_FRACTIONDIGITS)) {
|
|
431 |
currentFacet = XSSimpleType.FACET_FRACTIONDIGITS;
|
|
432 |
}
|
|
433 |
else if (facet.equals(SchemaSymbols.ELT_WHITESPACE)) {
|
|
434 |
currentFacet = XSSimpleType.FACET_WHITESPACE;
|
|
435 |
}
|
|
436 |
else if (facet.equals(SchemaSymbols.ELT_LENGTH)) {
|
|
437 |
currentFacet = XSSimpleType.FACET_LENGTH;
|
|
438 |
}
|
|
439 |
else {
|
|
440 |
break; // a non-facet
|
|
441 |
}
|
|
442 |
|
|
443 |
attrs = fAttrChecker.checkAttributes(content, false, schemaDoc);
|
|
444 |
|
|
445 |
// check for duplicate facets
|
|
446 |
if ((facetsPresent & currentFacet) != 0) {
|
|
447 |
// Ignore this facet, to avoid corrupting the previous facet
|
|
448 |
reportSchemaError("src-single-facet-value", new Object[]{facet}, content);
|
|
449 |
fAttrChecker.returnAttrArray (attrs, schemaDoc);
|
|
450 |
content = DOMUtil.getNextSiblingElement(content);
|
|
451 |
continue;
|
|
452 |
}
|
|
453 |
|
|
454 |
// The facet can't be used if the value is missing. Ignore
|
|
455 |
// this facet element.
|
|
456 |
if (attrs[XSAttributeChecker.ATTIDX_VALUE] == null) {
|
|
457 |
// Report an error if the "value" attribute is missing.
|
|
458 |
// If it's not missing, then its value is invalid, and an
|
|
459 |
// error should have already been reported by the
|
|
460 |
// attribute checker.
|
|
461 |
if (content.getAttributeNodeNS(null, "value") == null) {
|
|
462 |
reportSchemaError("s4s-att-must-appear", new Object[]{content.getLocalName(), SchemaSymbols.ATT_VALUE}, content);
|
|
463 |
}
|
|
464 |
fAttrChecker.returnAttrArray (attrs, schemaDoc);
|
|
465 |
content = DOMUtil.getNextSiblingElement(content);
|
|
466 |
continue;
|
|
467 |
}
|
|
468 |
|
|
469 |
facetsPresent |= currentFacet;
|
|
470 |
// check for fixed facet
|
|
471 |
if (((Boolean)attrs[XSAttributeChecker.ATTIDX_FIXED]).booleanValue()) {
|
|
472 |
facetsFixed |= currentFacet;
|
|
473 |
}
|
|
474 |
switch (currentFacet) {
|
|
475 |
case XSSimpleType.FACET_MINLENGTH:
|
|
476 |
xsFacets.minLength = ((XInt)attrs[XSAttributeChecker.ATTIDX_VALUE]).intValue();
|
|
477 |
break;
|
|
478 |
case XSSimpleType.FACET_MAXLENGTH:
|
|
479 |
xsFacets.maxLength = ((XInt)attrs[XSAttributeChecker.ATTIDX_VALUE]).intValue();
|
|
480 |
break;
|
|
481 |
case XSSimpleType.FACET_MAXEXCLUSIVE:
|
|
482 |
xsFacets.maxExclusive = (String)attrs[XSAttributeChecker.ATTIDX_VALUE];
|
|
483 |
break;
|
|
484 |
case XSSimpleType.FACET_MAXINCLUSIVE:
|
|
485 |
xsFacets.maxInclusive = (String)attrs[XSAttributeChecker.ATTIDX_VALUE];
|
|
486 |
break;
|
|
487 |
case XSSimpleType.FACET_MINEXCLUSIVE:
|
|
488 |
xsFacets.minExclusive = (String)attrs[XSAttributeChecker.ATTIDX_VALUE];
|
|
489 |
break;
|
|
490 |
case XSSimpleType.FACET_MININCLUSIVE:
|
|
491 |
xsFacets.minInclusive = (String)attrs[XSAttributeChecker.ATTIDX_VALUE];
|
|
492 |
break;
|
|
493 |
case XSSimpleType.FACET_TOTALDIGITS:
|
|
494 |
xsFacets.totalDigits = ((XInt)attrs[XSAttributeChecker.ATTIDX_VALUE]).intValue();
|
|
495 |
break;
|
|
496 |
case XSSimpleType.FACET_FRACTIONDIGITS:
|
|
497 |
xsFacets.fractionDigits = ((XInt)attrs[XSAttributeChecker.ATTIDX_VALUE]).intValue();
|
|
498 |
break;
|
|
499 |
case XSSimpleType.FACET_WHITESPACE:
|
|
500 |
xsFacets.whiteSpace = ((XInt)attrs[XSAttributeChecker.ATTIDX_VALUE]).shortValue();
|
|
501 |
break;
|
|
502 |
case XSSimpleType.FACET_LENGTH:
|
|
503 |
xsFacets.length = ((XInt)attrs[XSAttributeChecker.ATTIDX_VALUE]).intValue();
|
|
504 |
break;
|
|
505 |
}
|
|
506 |
|
|
507 |
Element child = DOMUtil.getFirstChildElement( content );
|
|
508 |
XSAnnotationImpl annotation = null;
|
|
509 |
if (child != null &&
|
|
510 |
DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION)) {
|
|
511 |
// traverse annotation if any
|
|
512 |
annotation = traverseAnnotationDecl(child, attrs, false, schemaDoc);
|
|
513 |
child = DOMUtil.getNextSiblingElement(child);
|
|
514 |
}
|
|
515 |
else {
|
|
516 |
String text = DOMUtil.getSyntheticAnnotation(content);
|
|
517 |
if (text != null) {
|
|
518 |
annotation = traverseSyntheticAnnotation(content, text, attrs, false, schemaDoc);
|
|
519 |
}
|
|
520 |
}
|
|
521 |
switch (currentFacet) {
|
|
522 |
case XSSimpleType.FACET_MINLENGTH:
|
|
523 |
xsFacets.minLengthAnnotation = annotation;
|
|
524 |
break;
|
|
525 |
case XSSimpleType.FACET_MAXLENGTH:
|
|
526 |
xsFacets.maxLengthAnnotation = annotation;
|
|
527 |
break;
|
|
528 |
case XSSimpleType.FACET_MAXEXCLUSIVE:
|
|
529 |
xsFacets.maxExclusiveAnnotation = annotation;
|
|
530 |
break;
|
|
531 |
case XSSimpleType.FACET_MAXINCLUSIVE:
|
|
532 |
xsFacets.maxInclusiveAnnotation = annotation;
|
|
533 |
break;
|
|
534 |
case XSSimpleType.FACET_MINEXCLUSIVE:
|
|
535 |
xsFacets.minExclusiveAnnotation = annotation;
|
|
536 |
break;
|
|
537 |
case XSSimpleType.FACET_MININCLUSIVE:
|
|
538 |
xsFacets.minInclusiveAnnotation = annotation;
|
|
539 |
break;
|
|
540 |
case XSSimpleType.FACET_TOTALDIGITS:
|
|
541 |
xsFacets.totalDigitsAnnotation = annotation;
|
|
542 |
break;
|
|
543 |
case XSSimpleType.FACET_FRACTIONDIGITS:
|
|
544 |
xsFacets.fractionDigitsAnnotation = annotation;
|
|
545 |
break;
|
|
546 |
case XSSimpleType.FACET_WHITESPACE:
|
|
547 |
xsFacets.whiteSpaceAnnotation = annotation;
|
|
548 |
break;
|
|
549 |
case XSSimpleType.FACET_LENGTH:
|
|
550 |
xsFacets.lengthAnnotation = annotation;
|
|
551 |
break;
|
|
552 |
}
|
|
553 |
if (child != null) {
|
|
554 |
reportSchemaError("s4s-elt-must-match.1", new Object[]{facet, "(annotation?)", DOMUtil.getLocalName(child)}, child);
|
|
555 |
}
|
|
556 |
}
|
|
557 |
fAttrChecker.returnAttrArray (attrs, schemaDoc);
|
|
558 |
content = DOMUtil.getNextSiblingElement(content);
|
|
559 |
}
|
|
560 |
if (enumData !=null) {
|
|
561 |
facetsPresent |= XSSimpleType.FACET_ENUMERATION;
|
|
562 |
xsFacets.enumeration = enumData;
|
|
563 |
xsFacets.enumNSDecls = enumNSDecls;
|
|
564 |
xsFacets.enumAnnotations = enumAnnotations;
|
|
565 |
}
|
|
566 |
if ((facetsPresent & XSSimpleType.FACET_PATTERN) != 0) {
|
|
567 |
xsFacets.pattern = fPattern.toString();
|
|
568 |
xsFacets.patternAnnotations = patternAnnotations;
|
|
569 |
}
|
|
570 |
|
|
571 |
fPattern.setLength(0);
|
|
572 |
|
|
573 |
return new FacetInfo(xsFacets, content, facetsPresent, facetsFixed);
|
|
574 |
}
|
|
575 |
|
|
576 |
|
|
577 |
// return whether QName/NOTATION is part of the given type
|
|
578 |
private boolean containsQName(XSSimpleType type) {
|
|
579 |
if (type.getVariety() == XSSimpleType.VARIETY_ATOMIC) {
|
|
580 |
short primitive = type.getPrimitiveKind();
|
|
581 |
return (primitive == XSSimpleType.PRIMITIVE_QNAME ||
|
|
582 |
primitive == XSSimpleType.PRIMITIVE_NOTATION);
|
|
583 |
}
|
|
584 |
else if (type.getVariety() == XSSimpleType.VARIETY_LIST) {
|
|
585 |
return containsQName((XSSimpleType)type.getItemType());
|
|
586 |
}
|
|
587 |
else if (type.getVariety() == XSSimpleType.VARIETY_UNION) {
|
|
588 |
XSObjectList members = type.getMemberTypes();
|
|
589 |
for (int i = 0; i < members.getLength(); i++) {
|
|
590 |
if (containsQName((XSSimpleType)members.item(i)))
|
|
591 |
return true;
|
|
592 |
}
|
|
593 |
}
|
|
594 |
return false;
|
|
595 |
}
|
|
596 |
|
|
597 |
//
|
|
598 |
// Traverse a set of attribute and attribute group elements
|
|
599 |
// Needed by complexType and attributeGroup traversal
|
|
600 |
// This method will return the first non-attribute/attrgrp found
|
|
601 |
//
|
|
602 |
Element traverseAttrsAndAttrGrps(Element firstAttr, XSAttributeGroupDecl attrGrp,
|
|
603 |
XSDocumentInfo schemaDoc, SchemaGrammar grammar,
|
|
604 |
XSComplexTypeDecl enclosingCT) {
|
|
605 |
|
|
606 |
Element child=null;
|
|
607 |
XSAttributeGroupDecl tempAttrGrp = null;
|
|
608 |
XSAttributeUseImpl tempAttrUse = null;
|
|
609 |
XSAttributeUse otherUse = null;
|
|
610 |
String childName;
|
|
611 |
|
|
612 |
for (child=firstAttr; child!=null; child=DOMUtil.getNextSiblingElement(child)) {
|
|
613 |
childName = DOMUtil.getLocalName(child);
|
|
614 |
if (childName.equals(SchemaSymbols.ELT_ATTRIBUTE)) {
|
|
615 |
tempAttrUse = fSchemaHandler.fAttributeTraverser.traverseLocal(child,
|
|
616 |
schemaDoc,
|
|
617 |
grammar,
|
|
618 |
enclosingCT);
|
|
619 |
if (tempAttrUse == null) continue;
|
|
620 |
if (tempAttrUse.fUse == SchemaSymbols.USE_PROHIBITED) {
|
|
621 |
attrGrp.addAttributeUse(tempAttrUse);
|
|
622 |
continue;
|
|
623 |
}
|
|
624 |
otherUse = attrGrp.getAttributeUseNoProhibited(
|
|
625 |
tempAttrUse.fAttrDecl.getNamespace(),
|
|
626 |
tempAttrUse.fAttrDecl.getName());
|
|
627 |
if (otherUse==null) {
|
|
628 |
String idName = attrGrp.addAttributeUse(tempAttrUse);
|
|
629 |
if (idName != null) {
|
|
630 |
String code = (enclosingCT == null) ? "ag-props-correct.3" : "ct-props-correct.5";
|
|
631 |
String name = (enclosingCT == null) ? attrGrp.fName : enclosingCT.getName();
|
|
632 |
reportSchemaError(code, new Object[]{name, tempAttrUse.fAttrDecl.getName(), idName}, child);
|
|
633 |
}
|
|
634 |
}
|
|
635 |
else if (otherUse != tempAttrUse) {
|
|
636 |
String code = (enclosingCT == null) ? "ag-props-correct.2" : "ct-props-correct.4";
|
|
637 |
String name = (enclosingCT == null) ? attrGrp.fName : enclosingCT.getName();
|
|
638 |
reportSchemaError(code, new Object[]{name, tempAttrUse.fAttrDecl.getName()}, child);
|
|
639 |
}
|
|
640 |
}
|
|
641 |
else if (childName.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) {
|
|
642 |
//REVISIT: do we need to save some state at this point??
|
|
643 |
tempAttrGrp = fSchemaHandler.fAttributeGroupTraverser.traverseLocal(
|
|
644 |
child, schemaDoc, grammar);
|
|
645 |
if(tempAttrGrp == null ) continue;
|
|
646 |
XSObjectList attrUseS = tempAttrGrp.getAttributeUses();
|
|
647 |
XSAttributeUseImpl oneAttrUse;
|
|
648 |
int attrCount = attrUseS.getLength();
|
|
649 |
for (int i=0; i<attrCount; i++) {
|
|
650 |
oneAttrUse = (XSAttributeUseImpl)attrUseS.item(i);
|
|
651 |
if (oneAttrUse.fUse == SchemaSymbols.USE_PROHIBITED) {
|
|
652 |
attrGrp.addAttributeUse(oneAttrUse);
|
|
653 |
continue;
|
|
654 |
}
|
|
655 |
otherUse = attrGrp.getAttributeUseNoProhibited(
|
|
656 |
oneAttrUse.fAttrDecl.getNamespace(),
|
|
657 |
oneAttrUse.fAttrDecl.getName());
|
|
658 |
if (otherUse==null) {
|
|
659 |
String idName = attrGrp.addAttributeUse(oneAttrUse);
|
|
660 |
if (idName != null) {
|
|
661 |
String code = (enclosingCT == null) ? "ag-props-correct.3" : "ct-props-correct.5";
|
|
662 |
String name = (enclosingCT == null) ? attrGrp.fName : enclosingCT.getName();
|
|
663 |
reportSchemaError(code, new Object[]{name, oneAttrUse.fAttrDecl.getName(), idName}, child);
|
|
664 |
}
|
|
665 |
}
|
|
666 |
else if (oneAttrUse != otherUse) {
|
|
667 |
String code = (enclosingCT == null) ? "ag-props-correct.2" : "ct-props-correct.4";
|
|
668 |
String name = (enclosingCT == null) ? attrGrp.fName : enclosingCT.getName();
|
|
669 |
reportSchemaError(code, new Object[]{name, oneAttrUse.fAttrDecl.getName()}, child);
|
|
670 |
}
|
|
671 |
}
|
|
672 |
|
|
673 |
if (tempAttrGrp.fAttributeWC != null) {
|
|
674 |
if (attrGrp.fAttributeWC == null) {
|
|
675 |
attrGrp.fAttributeWC = tempAttrGrp.fAttributeWC;
|
|
676 |
}
|
|
677 |
// perform intersection of attribute wildcard
|
|
678 |
else {
|
|
679 |
attrGrp.fAttributeWC = attrGrp.fAttributeWC.
|
|
680 |
performIntersectionWith(tempAttrGrp.fAttributeWC, attrGrp.fAttributeWC.fProcessContents);
|
|
681 |
if (attrGrp.fAttributeWC == null) {
|
|
682 |
String code = (enclosingCT == null) ? "src-attribute_group.2" : "src-ct.4";
|
|
683 |
String name = (enclosingCT == null) ? attrGrp.fName : enclosingCT.getName();
|
|
684 |
reportSchemaError(code, new Object[]{name}, child);
|
|
685 |
}
|
|
686 |
}
|
|
687 |
}
|
|
688 |
}
|
|
689 |
else
|
|
690 |
break;
|
|
691 |
} // for
|
|
692 |
|
|
693 |
if (child != null) {
|
|
694 |
childName = DOMUtil.getLocalName(child);
|
|
695 |
if (childName.equals(SchemaSymbols.ELT_ANYATTRIBUTE)) {
|
|
696 |
XSWildcardDecl tempAttrWC = fSchemaHandler.fWildCardTraverser.
|
|
697 |
traverseAnyAttribute(child, schemaDoc, grammar);
|
|
698 |
if (attrGrp.fAttributeWC == null) {
|
|
699 |
attrGrp.fAttributeWC = tempAttrWC;
|
|
700 |
}
|
|
701 |
// perform intersection of attribute wildcard
|
|
702 |
else {
|
|
703 |
attrGrp.fAttributeWC = tempAttrWC.
|
|
704 |
performIntersectionWith(attrGrp.fAttributeWC, tempAttrWC.fProcessContents);
|
|
705 |
if (attrGrp.fAttributeWC == null) {
|
|
706 |
String code = (enclosingCT == null) ? "src-attribute_group.2" : "src-ct.4";
|
|
707 |
String name = (enclosingCT == null) ? attrGrp.fName : enclosingCT.getName();
|
|
708 |
reportSchemaError(code, new Object[]{name}, child);
|
|
709 |
}
|
|
710 |
}
|
|
711 |
child = DOMUtil.getNextSiblingElement(child);
|
|
712 |
}
|
|
713 |
}
|
|
714 |
|
|
715 |
// Success
|
|
716 |
return child;
|
|
717 |
|
|
718 |
}
|
|
719 |
|
|
720 |
void reportSchemaError (String key, Object[] args, Element ele) {
|
|
721 |
fSchemaHandler.reportSchemaError(key, args, ele);
|
|
722 |
}
|
|
723 |
|
|
724 |
/**
|
|
725 |
* Element/Attribute traversers call this method to check whether
|
|
726 |
* the type is NOTATION without enumeration facet
|
|
727 |
*/
|
|
728 |
void checkNotationType(String refName, XSTypeDefinition typeDecl, Element elem) {
|
|
729 |
if (typeDecl.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE &&
|
|
730 |
((XSSimpleType)typeDecl).getVariety() == XSSimpleType.VARIETY_ATOMIC &&
|
|
731 |
((XSSimpleType)typeDecl).getPrimitiveKind() == XSSimpleType.PRIMITIVE_NOTATION) {
|
|
732 |
if ((((XSSimpleType)typeDecl).getDefinedFacets() & XSSimpleType.FACET_ENUMERATION) == 0) {
|
|
733 |
reportSchemaError("enumeration-required-notation", new Object[]{typeDecl.getName(), refName, DOMUtil.getLocalName(elem)}, elem);
|
|
734 |
}
|
|
735 |
}
|
|
736 |
}
|
|
737 |
|
|
738 |
// Checks constraints for minOccurs, maxOccurs
|
|
739 |
protected XSParticleDecl checkOccurrences(XSParticleDecl particle,
|
|
740 |
String particleName, Element parent,
|
|
741 |
int allContextFlags,
|
|
742 |
long defaultVals) {
|
|
743 |
|
|
744 |
int min = particle.fMinOccurs;
|
|
745 |
int max = particle.fMaxOccurs;
|
|
746 |
boolean defaultMin = (defaultVals & (1 << XSAttributeChecker.ATTIDX_MINOCCURS)) != 0;
|
|
747 |
boolean defaultMax = (defaultVals & (1 << XSAttributeChecker.ATTIDX_MAXOCCURS)) != 0;
|
|
748 |
|
|
749 |
boolean processingAllEl = ((allContextFlags & PROCESSING_ALL_EL) != 0);
|
|
750 |
boolean processingAllGP = ((allContextFlags & PROCESSING_ALL_GP) != 0);
|
|
751 |
boolean groupRefWithAll = ((allContextFlags & GROUP_REF_WITH_ALL) != 0);
|
|
752 |
boolean isGroupChild = ((allContextFlags & CHILD_OF_GROUP) != 0);
|
|
753 |
|
|
754 |
// Neither minOccurs nor maxOccurs may be specified
|
|
755 |
// for the child of a model group definition.
|
|
756 |
if (isGroupChild) {
|
|
757 |
if (!defaultMin) {
|
|
758 |
Object[] args = new Object[]{particleName, "minOccurs"};
|
|
759 |
reportSchemaError("s4s-att-not-allowed", args, parent);
|
|
760 |
min = 1;
|
|
761 |
}
|
|
762 |
if (!defaultMax) {
|
|
763 |
Object[] args = new Object[]{particleName, "maxOccurs"};
|
|
764 |
reportSchemaError("s4s-att-not-allowed", args, parent);
|
|
765 |
max = 1;
|
|
766 |
}
|
|
767 |
}
|
|
768 |
|
|
769 |
// If minOccurs=maxOccurs=0, no component is specified
|
|
770 |
if (min == 0 && max== 0) {
|
|
771 |
particle.fType = XSParticleDecl.PARTICLE_EMPTY;
|
|
772 |
return null;
|
|
773 |
}
|
|
774 |
|
|
775 |
// For the elements referenced in an <all>, minOccurs attribute
|
|
776 |
// must be zero or one, and maxOccurs attribute must be one.
|
|
777 |
// For a complex type definition that contains an <all> or a
|
|
778 |
// reference a <group> whose model group is an all model group,
|
|
779 |
// minOccurs and maxOccurs must be one.
|
|
780 |
if (processingAllEl) {
|
|
781 |
if (max != 1) {
|
|
782 |
reportSchemaError("cos-all-limited.2", new Object[]{
|
|
783 |
(max == SchemaSymbols.OCCURRENCE_UNBOUNDED) ? SchemaSymbols.ATTVAL_UNBOUNDED : Integer.toString(max),
|
|
784 |
((XSElementDecl)particle.fValue).getName()}, parent);
|
|
785 |
max = 1;
|
|
786 |
if (min > 1)
|
|
787 |
min = 1;
|
|
788 |
}
|
|
789 |
}
|
|
790 |
else if (processingAllGP || groupRefWithAll) {
|
|
791 |
if (max != 1) {
|
|
792 |
reportSchemaError("cos-all-limited.1.2", null, parent);
|
|
793 |
if (min > 1)
|
|
794 |
min = 1;
|
|
795 |
max = 1;
|
|
796 |
}
|
|
797 |
}
|
|
798 |
|
|
799 |
particle.fMinOccurs = min;
|
|
800 |
particle.fMaxOccurs = max;
|
|
801 |
|
|
802 |
return particle;
|
|
803 |
}
|
|
804 |
|
|
805 |
private static String processAttValue(String original) {
|
|
806 |
final int length = original.length();
|
|
807 |
// normally, nothing will happen
|
|
808 |
for (int i = 0; i < length; ++i) {
|
|
809 |
char currChar = original.charAt(i);
|
|
810 |
if (currChar == '"' || currChar == '<' || currChar == '&' ||
|
|
811 |
currChar == 0x09 || currChar == 0x0A || currChar == 0x0D) {
|
|
812 |
return escapeAttValue(original, i);
|
|
813 |
}
|
|
814 |
}
|
|
815 |
return original;
|
|
816 |
}
|
|
817 |
|
|
818 |
// this is not terribly performant!
|
|
819 |
private static String escapeAttValue(String original, int from) {
|
|
820 |
int i;
|
|
821 |
final int length = original.length();
|
|
822 |
StringBuffer newVal = new StringBuffer(length);
|
|
823 |
newVal.append(original.substring(0, from));
|
|
824 |
for (i = from; i < length; ++i) {
|
|
825 |
char currChar = original.charAt(i);
|
|
826 |
if (currChar == '"') {
|
|
827 |
newVal.append(""");
|
|
828 |
}
|
|
829 |
else if (currChar == '<') {
|
|
830 |
newVal.append("<");
|
|
831 |
}
|
|
832 |
else if (currChar == '&') {
|
|
833 |
newVal.append("&");
|
|
834 |
}
|
|
835 |
// Must escape 0x09, 0x0A and 0x0D if they appear in attribute
|
|
836 |
// value so that they may be round-tripped. They would otherwise
|
|
837 |
// be transformed to a 0x20 during attribute value normalization.
|
|
838 |
else if (currChar == 0x09) {
|
|
839 |
newVal.append("	");
|
|
840 |
}
|
|
841 |
else if (currChar == 0x0A) {
|
|
842 |
newVal.append("
");
|
|
843 |
}
|
|
844 |
else if (currChar == 0x0D) {
|
|
845 |
newVal.append("
");
|
|
846 |
}
|
|
847 |
else {
|
|
848 |
newVal.append(currChar);
|
|
849 |
}
|
|
850 |
}
|
|
851 |
return newVal.toString();
|
|
852 |
}
|
|
853 |
}
|