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