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; 23 24 import com.sun.org.apache.xerces.internal.impl.Constants; 25 import com.sun.org.apache.xerces.internal.impl.xs.util.StringListImpl; 26 import com.sun.org.apache.xerces.internal.impl.xs.util.XSNamedMap4Types; 27 import com.sun.org.apache.xerces.internal.impl.xs.util.XSNamedMapImpl; 28 import com.sun.org.apache.xerces.internal.impl.xs.util.XSObjectListImpl; 29 import com.sun.org.apache.xerces.internal.util.SymbolHash; 30 import com.sun.org.apache.xerces.internal.util.XMLSymbols; 31 import com.sun.org.apache.xerces.internal.xs.StringList; 32 import com.sun.org.apache.xerces.internal.xs.XSAttributeDeclaration; 33 import com.sun.org.apache.xerces.internal.xs.XSAttributeGroupDefinition; 34 import com.sun.org.apache.xerces.internal.xs.XSConstants; 35 import com.sun.org.apache.xerces.internal.xs.XSElementDeclaration; 36 import com.sun.org.apache.xerces.internal.xs.XSIDCDefinition; 37 import com.sun.org.apache.xerces.internal.xs.XSModel; 38 import com.sun.org.apache.xerces.internal.xs.XSModelGroupDefinition; 39 import com.sun.org.apache.xerces.internal.xs.XSNamedMap; 40 import com.sun.org.apache.xerces.internal.xs.XSNamespaceItem; 41 import com.sun.org.apache.xerces.internal.xs.XSNamespaceItemList; 42 import com.sun.org.apache.xerces.internal.xs.XSNotationDeclaration; 43 import com.sun.org.apache.xerces.internal.xs.XSObject; 44 import com.sun.org.apache.xerces.internal.xs.XSObjectList; 45 import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition; 46 import java.lang.reflect.Array; 47 import java.util.AbstractList; 48 import java.util.Iterator; 49 import java.util.List; 50 import java.util.ListIterator; 51 import java.util.NoSuchElementException; 52 53 /** 54 * Implements XSModel: a read-only interface that represents an XML Schema, 55 * which could be components from different namespaces. 56 * 57 * @xerces.internal 58 * 59 * @author Sandy Gao, IBM 60 * 61 */ 62 @SuppressWarnings("unchecked") // method <T>toArray(T[]) 63 public final class XSModelImpl extends AbstractList<XSNamespaceItem> implements XSModel, XSNamespaceItemList { 64 65 // the max index / the max value of XSObject type 66 private static final short MAX_COMP_IDX = XSTypeDefinition.SIMPLE_TYPE; 67 private static final boolean[] GLOBAL_COMP = {false, // null 68 true, // attribute 69 true, // element 70 true, // type 71 false, // attribute use 72 true, // attribute group 73 true, // group 74 false, // model group 75 false, // particle 76 false, // wildcard 77 true, // idc 78 true, // notation 79 false, // annotation 80 false, // facet 81 false, // multi value facet 82 true, // complex type 83 true // simple type 84 }; 85 86 // number of grammars/namespaces stored here 87 private final int fGrammarCount; 88 // all target namespaces 89 private final String[] fNamespaces; 90 // all schema grammar objects (for each namespace) 91 private final SchemaGrammar[] fGrammarList; 92 // a map from namespace to schema grammar 93 private final SymbolHash fGrammarMap; 94 // a map from element declaration to its substitution group 95 private final SymbolHash fSubGroupMap; 96 97 // store a certain kind of components from all namespaces 98 private final XSNamedMap[] fGlobalComponents; 99 // store a certain kind of components from one namespace 100 private final XSNamedMap[][] fNSComponents; 101 102 // a string list of all the target namespaces. 103 private final StringList fNamespacesList; 104 // store all annotations 105 private XSObjectList fAnnotations = null; 106 107 // whether there is any IDC in this XSModel 108 private final boolean fHasIDC; 109 110 /** 111 * Construct an XSModelImpl, by storing some grammars and grammars imported 112 * by them to this object. 113 * 114 * @param grammars the array of schema grammars 115 */ 116 public XSModelImpl(SchemaGrammar[] grammars) { 117 this(grammars, Constants.SCHEMA_VERSION_1_0); 118 } 119 120 public XSModelImpl(SchemaGrammar[] grammars, short s4sVersion) { 121 // copy namespaces/grammars from the array to our arrays 122 int len = grammars.length; 123 final int initialSize = Math.max(len+1, 5); 124 String[] namespaces = new String[initialSize]; 125 SchemaGrammar[] grammarList = new SchemaGrammar[initialSize]; 126 boolean hasS4S = false; 127 for (int i = 0; i < len; i++) { 128 final SchemaGrammar sg = grammars[i]; 129 final String tns = sg.getTargetNamespace(); 130 namespaces[i] = tns; 131 grammarList[i] = sg; 132 if (tns == SchemaSymbols.URI_SCHEMAFORSCHEMA) { 133 hasS4S = true; 134 } 135 } 136 // If a schema for the schema namespace isn't included, include it here. 137 if (!hasS4S) { 138 namespaces[len] = SchemaSymbols.URI_SCHEMAFORSCHEMA; 139 grammarList[len++] = SchemaGrammar.getS4SGrammar(s4sVersion); 140 } 141 142 SchemaGrammar sg1, sg2; 143 List<SchemaGrammar> gs; 144 int i, j, k; 145 // and recursively get all imported grammars, add them to our arrays 146 for (i = 0; i < len; i++) { 147 // get the grammar 148 sg1 = grammarList[i]; 149 gs = sg1.getImportedGrammars(); 150 // for each imported grammar 151 for (j = gs == null ? -1 : gs.size() - 1; j >= 0; j--) { 152 sg2 = gs.get(j); 153 // check whether this grammar is already in the list 154 for (k = 0; k < len; k++) { 155 if (sg2 == grammarList[k]) { 156 break; 157 } 158 } 159 // if it's not, add it to the list 160 if (k == len) { 161 // ensure the capacity of the arrays 162 if (len == grammarList.length) { 163 String[] newSA = new String[len*2]; 164 System.arraycopy(namespaces, 0, newSA, 0, len); 165 namespaces = newSA; 166 SchemaGrammar[] newGA = new SchemaGrammar[len*2]; 167 System.arraycopy(grammarList, 0, newGA, 0, len); 168 grammarList = newGA; 169 } 170 namespaces[len] = sg2.getTargetNamespace(); 171 grammarList[len] = sg2; 172 len++; 173 } 174 } 175 } 176 177 fNamespaces = namespaces; 178 fGrammarList = grammarList; 179 180 boolean hasIDC = false; 181 // establish the mapping from namespace to grammars 182 fGrammarMap = new SymbolHash(len*2); 183 for (i = 0; i < len; i++) { 184 fGrammarMap.put(null2EmptyString(fNamespaces[i]), fGrammarList[i]); 185 // update the idc field 186 if (fGrammarList[i].hasIDConstraints()) { 187 hasIDC = true; 188 } 189 } 190 191 fHasIDC = hasIDC; 192 fGrammarCount = len; 193 fGlobalComponents = new XSNamedMap[MAX_COMP_IDX+1]; 194 fNSComponents = new XSNamedMap[len][MAX_COMP_IDX+1]; 195 fNamespacesList = new StringListImpl(fNamespaces, fGrammarCount); 196 197 // build substitution groups 198 fSubGroupMap = buildSubGroups(); 199 } 200 201 private SymbolHash buildSubGroups_Org() { 202 SubstitutionGroupHandler sgHandler = new SubstitutionGroupHandler(null); 203 for (int i = 0 ; i < fGrammarCount; i++) { 204 sgHandler.addSubstitutionGroup(fGrammarList[i].getSubstitutionGroups()); 205 } 206 207 final XSNamedMap elements = getComponents(XSConstants.ELEMENT_DECLARATION); 208 final int len = elements.getLength(); 209 final SymbolHash subGroupMap = new SymbolHash(len*2); 210 XSElementDecl head; 211 XSElementDeclaration[] subGroup; 212 for (int i = 0; i < len; i++) { 213 head = (XSElementDecl)elements.item(i); 214 subGroup = sgHandler.getSubstitutionGroup(head); 215 subGroupMap.put(head, subGroup.length > 0 ? 216 new XSObjectListImpl(subGroup, subGroup.length) : XSObjectListImpl.EMPTY_LIST); 217 } 218 return subGroupMap; 219 } 220 221 private SymbolHash buildSubGroups() { 222 SubstitutionGroupHandler sgHandler = new SubstitutionGroupHandler(null); 223 for (int i = 0 ; i < fGrammarCount; i++) { 224 sgHandler.addSubstitutionGroup(fGrammarList[i].getSubstitutionGroups()); 225 } 226 227 final XSObjectListImpl elements = getGlobalElements(); 228 final int len = elements.getLength(); 229 final SymbolHash subGroupMap = new SymbolHash(len*2); 230 XSElementDecl head; 231 XSElementDeclaration[] subGroup; 232 for (int i = 0; i < len; i++) { 233 head = (XSElementDecl)elements.item(i); 234 subGroup = sgHandler.getSubstitutionGroup(head); 235 subGroupMap.put(head, subGroup.length > 0 ? 236 new XSObjectListImpl(subGroup, subGroup.length) : XSObjectListImpl.EMPTY_LIST); 237 } 238 return subGroupMap; 239 } 240 241 private XSObjectListImpl getGlobalElements() { 242 final SymbolHash[] tables = new SymbolHash[fGrammarCount]; 243 int length = 0; 244 245 for (int i = 0; i < fGrammarCount; i++) { 246 tables[i] = fGrammarList[i].fAllGlobalElemDecls; 247 length += tables[i].getLength(); 248 } 249 250 if (length == 0) { 251 return XSObjectListImpl.EMPTY_LIST; 252 } 253 254 final XSObject[] components = new XSObject[length]; 255 256 int start = 0; 257 for (int i = 0; i < fGrammarCount; i++) { 258 tables[i].getValues(components, start); 259 start += tables[i].getLength(); 260 } 261 262 return new XSObjectListImpl(components, length); 263 } 264 265 /** 266 * Convenience method. Returns a list of all namespaces that belong to 267 * this schema. 268 * @return A list of all namespaces that belong to this schema or 269 * <code>null</code> if all components don't have a targetNamespace. 270 */ 271 public StringList getNamespaces() { 272 return fNamespacesList; 273 } 274 275 /** 276 * A set of namespace schema information information items (of type 277 * <code>XSNamespaceItem</code>), one for each namespace name which 278 * appears as the target namespace of any schema component in the schema 279 * used for that assessment, and one for absent if any schema component 280 * in the schema had no target namespace. For more information see 281 * schema information. 282 */ 283 public XSNamespaceItemList getNamespaceItems() { 284 return this; 285 } 286 287 /** 288 * Returns a list of top-level components, i.e. element declarations, 289 * attribute declarations, etc. 290 * @param objectType The type of the declaration, i.e. 291 * <code>ELEMENT_DECLARATION</code>. Note that 292 * <code>XSTypeDefinition.SIMPLE_TYPE</code> and 293 * <code>XSTypeDefinition.COMPLEX_TYPE</code> can also be used as the 294 * <code>objectType</code> to retrieve only complex types or simple 295 * types, instead of all types. 296 * @return A list of top-level definitions of the specified type in 297 * <code>objectType</code> or an empty <code>XSNamedMap</code> if no 298 * such definitions exist. 299 */ 300 public synchronized XSNamedMap getComponents(short objectType) { 301 if (objectType <= 0 || objectType > MAX_COMP_IDX || 302 !GLOBAL_COMP[objectType]) { 303 return XSNamedMapImpl.EMPTY_MAP; 304 } 305 306 SymbolHash[] tables = new SymbolHash[fGrammarCount]; 307 // get all hashtables from all namespaces for this type of components 308 if (fGlobalComponents[objectType] == null) { 309 for (int i = 0; i < fGrammarCount; i++) { 310 switch (objectType) { 311 case XSConstants.TYPE_DEFINITION: 312 case XSTypeDefinition.COMPLEX_TYPE: 313 case XSTypeDefinition.SIMPLE_TYPE: 314 tables[i] = fGrammarList[i].fGlobalTypeDecls; 315 break; 316 case XSConstants.ATTRIBUTE_DECLARATION: 317 tables[i] = fGrammarList[i].fGlobalAttrDecls; 318 break; 319 case XSConstants.ELEMENT_DECLARATION: 320 tables[i] = fGrammarList[i].fGlobalElemDecls; 321 break; 322 case XSConstants.ATTRIBUTE_GROUP: 323 tables[i] = fGrammarList[i].fGlobalAttrGrpDecls; 324 break; 325 case XSConstants.MODEL_GROUP_DEFINITION: 326 tables[i] = fGrammarList[i].fGlobalGroupDecls; 327 break; 328 case XSConstants.NOTATION_DECLARATION: 329 tables[i] = fGrammarList[i].fGlobalNotationDecls; 330 break; 331 case XSConstants.IDENTITY_CONSTRAINT: 332 tables[i] = fGrammarList[i].fGlobalIDConstraintDecls; 333 break; 334 } 335 } 336 // for complex/simple types, create a special implementation, 337 // which take specific types out of the hash table 338 if (objectType == XSTypeDefinition.COMPLEX_TYPE || 339 objectType == XSTypeDefinition.SIMPLE_TYPE) { 340 fGlobalComponents[objectType] = new XSNamedMap4Types(fNamespaces, tables, fGrammarCount, objectType); 341 } 342 else { 343 fGlobalComponents[objectType] = new XSNamedMapImpl(fNamespaces, tables, fGrammarCount); 344 } 345 } 346 347 return fGlobalComponents[objectType]; 348 } 349 350 /** 351 * Convenience method. Returns a list of top-level component declarations 352 * that are defined within the specified namespace, i.e. element 353 * declarations, attribute declarations, etc. 354 * @param objectType The type of the declaration, i.e. 355 * <code>ELEMENT_DECLARATION</code>. 356 * @param namespace The namespace to which the declaration belongs or 357 * <code>null</code> (for components with no target namespace). 358 * @return A list of top-level definitions of the specified type in 359 * <code>objectType</code> and defined in the specified 360 * <code>namespace</code> or an empty <code>XSNamedMap</code>. 361 */ 362 public synchronized XSNamedMap getComponentsByNamespace(short objectType, 363 String namespace) { 364 if (objectType <= 0 || objectType > MAX_COMP_IDX || 365 !GLOBAL_COMP[objectType]) { 366 return XSNamedMapImpl.EMPTY_MAP; 367 } 368 369 // try to find the grammar 370 int i = 0; 371 if (namespace != null) { 372 for (; i < fGrammarCount; ++i) { 373 if (namespace.equals(fNamespaces[i])) { 374 break; 375 } 376 } 377 } 378 else { 379 for (; i < fGrammarCount; ++i) { 380 if (fNamespaces[i] == null) { 381 break; 382 } 383 } 384 } 385 if (i == fGrammarCount) { 386 return XSNamedMapImpl.EMPTY_MAP; 387 } 388 389 // get the hashtable for this type of components 390 if (fNSComponents[i][objectType] == null) { 391 SymbolHash table = null; 392 switch (objectType) { 393 case XSConstants.TYPE_DEFINITION: 394 case XSTypeDefinition.COMPLEX_TYPE: 395 case XSTypeDefinition.SIMPLE_TYPE: 396 table = fGrammarList[i].fGlobalTypeDecls; 397 break; 398 case XSConstants.ATTRIBUTE_DECLARATION: 399 table = fGrammarList[i].fGlobalAttrDecls; 400 break; 401 case XSConstants.ELEMENT_DECLARATION: 402 table = fGrammarList[i].fGlobalElemDecls; 403 break; 404 case XSConstants.ATTRIBUTE_GROUP: 405 table = fGrammarList[i].fGlobalAttrGrpDecls; 406 break; 407 case XSConstants.MODEL_GROUP_DEFINITION: 408 table = fGrammarList[i].fGlobalGroupDecls; 409 break; 410 case XSConstants.NOTATION_DECLARATION: 411 table = fGrammarList[i].fGlobalNotationDecls; 412 break; 413 case XSConstants.IDENTITY_CONSTRAINT: 414 table = fGrammarList[i].fGlobalIDConstraintDecls; 415 break; 416 } 417 418 // for complex/simple types, create a special implementation, 419 // which take specific types out of the hash table 420 if (objectType == XSTypeDefinition.COMPLEX_TYPE || 421 objectType == XSTypeDefinition.SIMPLE_TYPE) { 422 fNSComponents[i][objectType] = new XSNamedMap4Types(namespace, table, objectType); 423 } 424 else { 425 fNSComponents[i][objectType] = new XSNamedMapImpl(namespace, table); 426 } 427 } 428 429 return fNSComponents[i][objectType]; 430 } 431 432 /** 433 * Convenience method. Returns a top-level simple or complex type 434 * definition. 435 * @param name The name of the definition. 436 * @param namespace The namespace of the definition, otherwise null. 437 * @return An <code>XSTypeDefinition</code> or null if such definition 438 * does not exist. 439 */ 440 public XSTypeDefinition getTypeDefinition(String name, 441 String namespace) { 442 SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace)); 443 if (sg == null) { 444 return null; 445 } 446 return (XSTypeDefinition)sg.fGlobalTypeDecls.get(name); 447 } 448 449 /** 450 * Convenience method. Returns a top-level simple or complex type 451 * definition. 452 * @param name The name of the definition. 453 * @param namespace The namespace of the definition, otherwise null. 454 * @param loc The schema location where the component was defined 455 * @return An <code>XSTypeDefinition</code> or null if such definition 456 * does not exist. 457 */ 458 public XSTypeDefinition getTypeDefinition(String name, 459 String namespace, 460 String loc) { 461 SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace)); 462 if (sg == null) { 463 return null; 464 } 465 return sg.getGlobalTypeDecl(name, loc); 466 } 467 468 /** 469 * Convenience method. Returns a top-level attribute declaration. 470 * @param name The name of the declaration. 471 * @param namespace The namespace of the definition, otherwise null. 472 * @return A top-level attribute declaration or null if such declaration 473 * does not exist. 474 */ 475 public XSAttributeDeclaration getAttributeDeclaration(String name, 476 String namespace) { 477 SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace)); 478 if (sg == null) { 479 return null; 480 } 481 return (XSAttributeDeclaration)sg.fGlobalAttrDecls.get(name); 482 } 483 484 /** 485 * Convenience method. Returns a top-level attribute declaration. 486 * @param name The name of the declaration. 487 * @param namespace The namespace of the definition, otherwise null. 488 * @param loc The schema location where the component was defined 489 * @return A top-level attribute declaration or null if such declaration 490 * does not exist. 491 */ 492 public XSAttributeDeclaration getAttributeDeclaration(String name, 493 String namespace, 494 String loc) { 495 SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace)); 496 if (sg == null) { 497 return null; 498 } 499 return sg.getGlobalAttributeDecl(name, loc); 500 } 501 502 /** 503 * Convenience method. Returns a top-level element declaration. 504 * @param name The name of the declaration. 505 * @param namespace The namespace of the definition, otherwise null. 506 * @return A top-level element declaration or null if such declaration 507 * does not exist. 508 */ 509 public XSElementDeclaration getElementDeclaration(String name, 510 String namespace) { 511 SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace)); 512 if (sg == null) { 513 return null; 514 } 515 return (XSElementDeclaration)sg.fGlobalElemDecls.get(name); 516 } 517 518 /** 519 * Convenience method. Returns a top-level element declaration. 520 * @param name The name of the declaration. 521 * @param namespace The namespace of the definition, otherwise null. 522 * @param loc The schema location where the component was defined 523 * @return A top-level element declaration or null if such declaration 524 * does not exist. 525 */ 526 public XSElementDeclaration getElementDeclaration(String name, 527 String namespace, 528 String loc) { 529 SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace)); 530 if (sg == null) { 531 return null; 532 } 533 return sg.getGlobalElementDecl(name, loc); 534 } 535 536 /** 537 * Convenience method. Returns a top-level attribute group definition. 538 * @param name The name of the definition. 539 * @param namespace The namespace of the definition, otherwise null. 540 * @return A top-level attribute group definition or null if such 541 * definition does not exist. 542 */ 543 public XSAttributeGroupDefinition getAttributeGroup(String name, 544 String namespace) { 545 SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace)); 546 if (sg == null) { 547 return null; 548 } 549 return (XSAttributeGroupDefinition)sg.fGlobalAttrGrpDecls.get(name); 550 } 551 552 /** 553 * Convenience method. Returns a top-level attribute group definition. 554 * @param name The name of the definition. 555 * @param namespace The namespace of the definition, otherwise null. 556 * @param loc The schema location where the component was defined 557 * @return A top-level attribute group definition or null if such 558 * definition does not exist. 559 */ 560 public XSAttributeGroupDefinition getAttributeGroup(String name, 561 String namespace, 562 String loc) { 563 SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace)); 564 if (sg == null) { 565 return null; 566 } 567 return sg.getGlobalAttributeGroupDecl(name, loc); 568 } 569 570 /** 571 * Convenience method. Returns a top-level model group definition. 572 * 573 * @param name The name of the definition. 574 * @param namespace The namespace of the definition, otherwise null. 575 * @return A top-level model group definition definition or null if such 576 * definition does not exist. 577 */ 578 public XSModelGroupDefinition getModelGroupDefinition(String name, 579 String namespace) { 580 SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace)); 581 if (sg == null) { 582 return null; 583 } 584 return (XSModelGroupDefinition)sg.fGlobalGroupDecls.get(name); 585 } 586 587 /** 588 * Convenience method. Returns a top-level model group definition. 589 * 590 * @param name The name of the definition. 591 * @param namespace The namespace of the definition, otherwise null. 592 * @param loc The schema location where the component was defined 593 * @return A top-level model group definition definition or null if such 594 * definition does not exist. 595 */ 596 public XSModelGroupDefinition getModelGroupDefinition(String name, 597 String namespace, 598 String loc) { 599 SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace)); 600 if (sg == null) { 601 return null; 602 } 603 return sg.getGlobalGroupDecl(name, loc); 604 } 605 606 /** 607 * Convenience method. Returns a top-level model group definition. 608 * 609 * @param name The name of the definition. 610 * @param namespace The namespace of the definition, otherwise null. 611 * @return A top-level model group definition definition or null if such 612 * definition does not exist. 613 */ 614 public XSIDCDefinition getIDCDefinition(String name, String namespace) { 615 SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace)); 616 if (sg == null) { 617 return null; 618 } 619 return (XSIDCDefinition)sg.fGlobalIDConstraintDecls.get(name); 620 } 621 622 /** 623 * Convenience method. Returns a top-level model group definition. 624 * 625 * @param name The name of the definition. 626 * @param namespace The namespace of the definition, otherwise null. 627 * @param loc The schema location where the component was defined 628 * @return A top-level model group definition definition or null if such 629 * definition does not exist. 630 */ 631 public XSIDCDefinition getIDCDefinition(String name, String namespace, 632 String loc) { 633 SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace)); 634 if (sg == null) { 635 return null; 636 } 637 return sg.getIDConstraintDecl(name, loc); 638 } 639 640 641 /** 642 * @see org.apache.xerces.xs.XSModel#getNotationDeclaration(String, String) 643 */ 644 public XSNotationDeclaration getNotationDeclaration(String name, 645 String namespace) { 646 SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace)); 647 if (sg == null) { 648 return null; 649 } 650 return (XSNotationDeclaration)sg.fGlobalNotationDecls.get(name); 651 } 652 653 public XSNotationDeclaration getNotationDeclaration(String name, 654 String namespace, 655 String loc) { 656 SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace)); 657 if (sg == null) { 658 return null; 659 } 660 return sg.getGlobalNotationDecl(name, loc); 661 } 662 663 /** 664 * [annotations]: a set of annotations if it exists, otherwise an empty 665 * <code>XSObjectList</code>. 666 */ 667 public synchronized XSObjectList getAnnotations() { 668 if (fAnnotations != null) { 669 return fAnnotations; 670 } 671 672 // do this in two passes to avoid inaccurate array size 673 int totalAnnotations = 0; 674 for (int i = 0; i < fGrammarCount; i++) { 675 totalAnnotations += fGrammarList[i].fNumAnnotations; 676 } 677 if (totalAnnotations == 0) { 678 fAnnotations = XSObjectListImpl.EMPTY_LIST; 679 return fAnnotations; 680 } 681 XSAnnotationImpl [] annotations = new XSAnnotationImpl [totalAnnotations]; 682 int currPos = 0; 683 for (int i = 0; i < fGrammarCount; i++) { 684 SchemaGrammar currGrammar = fGrammarList[i]; 685 if (currGrammar.fNumAnnotations > 0) { 686 System.arraycopy(currGrammar.fAnnotations, 0, annotations, currPos, currGrammar.fNumAnnotations); 687 currPos += currGrammar.fNumAnnotations; 688 } 689 } 690 fAnnotations = new XSObjectListImpl(annotations, annotations.length); 691 return fAnnotations; 692 } 693 694 private static final String null2EmptyString(String str) { 695 return str == null ? XMLSymbols.EMPTY_STRING : str; 696 } 697 698 /** 699 * REVISIT: to expose identity constraints from XSModel. 700 * For now, we only expose whether there are any IDCs. 701 * We also need to add these methods to the public 702 * XSModel interface. 703 */ 704 public boolean hasIDConstraints() { 705 return fHasIDC; 706 } 707 708 /** 709 * Convenience method. Returns a list containing the members of the 710 * substitution group for the given <code>XSElementDeclaration</code> 711 * or an empty <code>XSObjectList</code> if the substitution group 712 * contains no members. 713 * @param head The substitution group head. 714 * @return A list containing the members of the substitution group 715 * for the given <code>XSElementDeclaration</code> or an empty 716 * <code>XSObjectList</code> if the substitution group contains 717 * no members. 718 */ 719 public XSObjectList getSubstitutionGroup(XSElementDeclaration head) { 720 return (XSObjectList)fSubGroupMap.get(head); 721 } 722 723 // 724 // XSNamespaceItemList methods 725 // 726 727 /** 728 * The number of <code>XSNamespaceItem</code>s in the list. The range of 729 * valid child object indices is 0 to <code>length-1</code> inclusive. 730 */ 731 public int getLength() { 732 return fGrammarCount; 733 } 734 735 /** 736 * Returns the <code>index</code>th item in the collection or 737 * <code>null</code> if <code>index</code> is greater than or equal to 738 * the number of objects in the list. The index starts at 0. 739 * @param index index into the collection. 740 * @return The <code>XSNamespaceItem</code> at the <code>index</code>th 741 * position in the <code>XSNamespaceItemList</code>, or 742 * <code>null</code> if the index specified is not valid. 743 */ 744 public XSNamespaceItem item(int index) { 745 if (index < 0 || index >= fGrammarCount) { 746 return null; 747 } 748 return fGrammarList[index]; 749 } 750 751 // 752 // java.util.List methods 753 // 754 755 public XSNamespaceItem get(int index) { 756 if (index >= 0 && index < fGrammarCount) { 757 return fGrammarList[index]; 758 } 759 throw new IndexOutOfBoundsException("Index: " + index); 760 } 761 762 public int size() { 763 return getLength(); 764 } 765 766 public Iterator<XSNamespaceItem> iterator() { 767 return listIterator0(0); 768 } 769 770 public ListIterator<XSNamespaceItem> listIterator() { 771 return listIterator0(0); 772 } 773 774 public ListIterator<XSNamespaceItem> listIterator(int index) { 775 if (index >= 0 && index < fGrammarCount) { 776 return listIterator0(index); 777 } 778 throw new IndexOutOfBoundsException("Index: " + index); 779 } 780 781 private ListIterator<XSNamespaceItem> listIterator0(int index) { 782 return new XSNamespaceItemListIterator(index); 783 } 784 785 public Object[] toArray() { 786 Object[] a = new Object[fGrammarCount]; 787 toArray0(a); 788 return a; 789 } 790 791 public Object[] toArray(Object[] a) { 792 if (a.length < fGrammarCount) { 793 Class<?> arrayClass = a.getClass(); 794 Class<?> componentType = arrayClass.getComponentType(); 795 a = (Object[]) Array.newInstance(componentType, fGrammarCount); 796 } 797 toArray0(a); 798 if (a.length > fGrammarCount) { 799 a[fGrammarCount] = null; 800 } 801 return a; 802 } 803 804 private void toArray0(Object[] a) { 805 if (fGrammarCount > 0) { 806 System.arraycopy(fGrammarList, 0, a, 0, fGrammarCount); 807 } 808 } 809 810 private final class XSNamespaceItemListIterator implements ListIterator<XSNamespaceItem> { 811 private int index; 812 public XSNamespaceItemListIterator(int index) { 813 this.index = index; 814 } 815 public boolean hasNext() { 816 return (index < fGrammarCount); 817 } 818 public XSNamespaceItem next() { 819 if (index < fGrammarCount) { 820 return fGrammarList[index++]; 821 } 822 throw new NoSuchElementException(); 823 } 824 public boolean hasPrevious() { 825 return (index > 0); 826 } 827 public XSNamespaceItem previous() { 828 if (index > 0) { 829 return fGrammarList[--index]; 830 } 831 throw new NoSuchElementException(); 832 } 833 public int nextIndex() { 834 return index; 835 } 836 public int previousIndex() { 837 return index - 1; 838 } 839 public void remove() { 840 throw new UnsupportedOperationException(); 841 } 842 public void set(XSNamespaceItem o) { 843 throw new UnsupportedOperationException(); 844 } 845 public void add(XSNamespaceItem o) { 846 throw new UnsupportedOperationException(); 847 } 848 } 849 850 } // class XSModelImpl