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