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