XSDAbstractTraverser.java revision 1113:2fdbfbde3bc0
1/* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5/* 6 * Licensed to the Apache Software Foundation (ASF) under one or more 7 * contributor license agreements. See the NOTICE file distributed with 8 * this work for additional information regarding copyright ownership. 9 * The ASF licenses this file to You under the Apache License, Version 2.0 10 * (the "License"); you may not use this file except in compliance with 11 * the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 */ 21 22package com.sun.org.apache.xerces.internal.impl.xs.traversers; 23 24import java.util.Locale; 25import java.util.Vector; 26 27import com.sun.org.apache.xerces.internal.impl.dv.InvalidDatatypeValueException; 28import com.sun.org.apache.xerces.internal.impl.dv.XSFacets; 29import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType; 30import com.sun.org.apache.xerces.internal.impl.validation.ValidationState; 31import com.sun.org.apache.xerces.internal.impl.xs.SchemaGrammar; 32import com.sun.org.apache.xerces.internal.impl.xs.SchemaSymbols; 33import com.sun.org.apache.xerces.internal.impl.xs.XSAnnotationImpl; 34import com.sun.org.apache.xerces.internal.impl.xs.XSAttributeGroupDecl; 35import com.sun.org.apache.xerces.internal.impl.xs.XSAttributeUseImpl; 36import com.sun.org.apache.xerces.internal.impl.xs.XSComplexTypeDecl; 37import com.sun.org.apache.xerces.internal.impl.xs.XSElementDecl; 38import com.sun.org.apache.xerces.internal.impl.xs.XSParticleDecl; 39import com.sun.org.apache.xerces.internal.impl.xs.XSWildcardDecl; 40import com.sun.org.apache.xerces.internal.impl.xs.util.XInt; 41import com.sun.org.apache.xerces.internal.impl.xs.util.XSObjectListImpl; 42import com.sun.org.apache.xerces.internal.util.DOMUtil; 43import com.sun.org.apache.xerces.internal.util.NamespaceSupport; 44import com.sun.org.apache.xerces.internal.util.SymbolTable; 45import com.sun.org.apache.xerces.internal.xni.QName; 46import com.sun.org.apache.xerces.internal.xs.XSAttributeUse; 47import com.sun.org.apache.xerces.internal.xs.XSObjectList; 48import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition; 49import org.w3c.dom.Element; 50 51/** 52 * Class <code>XSDAbstractTraverser</code> serves as the base class for all 53 * other <code>XSD???Traverser</code>s. It holds the common data and provide 54 * a unified way to initialize these data. 55 * 56 * @xerces.internal 57 * 58 * @author Elena Litani, IBM 59 * @author Rahul Srivastava, Sun Microsystems Inc. 60 * @author Neeraj Bajaj, Sun Microsystems Inc. 61 * 62 */ 63abstract 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} 854