1 /* 2 * Copyright (c) 2015, 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.dtd; 23 24 import com.sun.org.apache.xerces.internal.impl.dtd.models.CMAny; 25 import com.sun.org.apache.xerces.internal.impl.dtd.models.CMBinOp; 26 import com.sun.org.apache.xerces.internal.impl.dtd.models.CMLeaf; 27 import com.sun.org.apache.xerces.internal.impl.dtd.models.CMNode; 28 import com.sun.org.apache.xerces.internal.impl.dtd.models.CMUniOp; 29 import com.sun.org.apache.xerces.internal.impl.dtd.models.ContentModelValidator; 30 import com.sun.org.apache.xerces.internal.impl.dtd.models.DFAContentModel; 31 import com.sun.org.apache.xerces.internal.impl.dtd.models.MixedContentModel; 32 import com.sun.org.apache.xerces.internal.impl.dtd.models.SimpleContentModel; 33 import com.sun.org.apache.xerces.internal.impl.dv.DatatypeValidator; 34 import com.sun.org.apache.xerces.internal.impl.validation.EntityState; 35 import com.sun.org.apache.xerces.internal.util.SymbolTable; 36 import com.sun.org.apache.xerces.internal.xni.Augmentations; 37 import com.sun.org.apache.xerces.internal.xni.QName; 38 import com.sun.org.apache.xerces.internal.xni.XMLDTDContentModelHandler; 39 import com.sun.org.apache.xerces.internal.xni.XMLDTDHandler; 40 import com.sun.org.apache.xerces.internal.xni.XMLLocator; 41 import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier; 42 import com.sun.org.apache.xerces.internal.xni.XMLString; 43 import com.sun.org.apache.xerces.internal.xni.XNIException; 44 import com.sun.org.apache.xerces.internal.xni.grammars.Grammar; 45 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription; 46 import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDContentModelSource; 47 import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDSource; 48 import java.util.ArrayList; 49 import java.util.HashMap; 50 import java.util.List; 51 import java.util.Map; 52 import java.util.Random; 53 54 /** 55 * A DTD grammar. This class implements the XNI handler interfaces 56 * for DTD information so that it can build the appropriate validation 57 * structures automatically from the callbacks. 58 * 59 * @xerces.internal 60 * 61 * @author Eric Ye, IBM 62 * @author Jeffrey Rodriguez, IBM 63 * @author Andy Clark, IBM 64 * @author Neil Graham, IBM 65 * 66 */ 67 public class DTDGrammar 68 implements XMLDTDHandler, XMLDTDContentModelHandler, EntityState, Grammar { 69 70 // 71 // Constants 72 // 73 74 /** Top level scope (-1). */ 75 public static final int TOP_LEVEL_SCOPE = -1; 76 77 // private 78 79 /** Chunk shift (8). */ 80 private static final int CHUNK_SHIFT = 8; // 2^8 = 256 81 82 /** Chunk size (1 << CHUNK_SHIFT). */ 83 private static final int CHUNK_SIZE = (1 << CHUNK_SHIFT); 84 85 /** Chunk mask (CHUNK_SIZE - 1). */ 86 private static final int CHUNK_MASK = CHUNK_SIZE - 1; 87 88 /** Initial chunk count (1 << (10 - CHUNK_SHIFT)). */ 89 private static final int INITIAL_CHUNK_COUNT = (1 << (10 - CHUNK_SHIFT)); // 2^10 = 1k 90 91 /** List flag (0x80). */ 92 private static final short LIST_FLAG = 0x80; 93 94 /** List mask (~LIST_FLAG). */ 95 private static final short LIST_MASK = ~LIST_FLAG; 96 97 // debugging 98 99 /** Debug DTDGrammar. */ 100 private static final boolean DEBUG = false; 101 102 // 103 // Data 104 // 105 106 protected XMLDTDSource fDTDSource = null; 107 protected XMLDTDContentModelSource fDTDContentModelSource = null; 108 109 /** Current element index. */ 110 protected int fCurrentElementIndex; 111 112 /** Current attribute index. */ 113 protected int fCurrentAttributeIndex; 114 115 /** fReadingExternalDTD */ 116 protected boolean fReadingExternalDTD = false; 117 118 /** Symbol table. */ 119 private SymbolTable fSymbolTable; 120 121 // The XMLDTDDescription with which this Grammar is associated 122 protected XMLDTDDescription fGrammarDescription = null; 123 124 // element declarations 125 126 /** Number of element declarations. */ 127 private int fElementDeclCount = 0; 128 129 /** Element declaration name. */ 130 private QName fElementDeclName[][] = new QName[INITIAL_CHUNK_COUNT][]; 131 132 /** 133 * Element declaration type. 134 * @see XMLElementDecl 135 */ 136 private short fElementDeclType[][] = new short[INITIAL_CHUNK_COUNT][]; 137 138 /** 139 * Element declaration content spec index. This index value is used 140 * to refer to the content spec information tables. 141 */ 142 private int fElementDeclContentSpecIndex[][] = new int[INITIAL_CHUNK_COUNT][]; 143 144 /** 145 * Element declaration content model validator. This validator is 146 * constructed from the content spec nodes. 147 */ 148 private ContentModelValidator fElementDeclContentModelValidator[][] = new ContentModelValidator[INITIAL_CHUNK_COUNT][]; 149 150 /** First attribute declaration of an element declaration. */ 151 private int fElementDeclFirstAttributeDeclIndex[][] = new int[INITIAL_CHUNK_COUNT][]; 152 153 /** Last attribute declaration of an element declaration. */ 154 private int fElementDeclLastAttributeDeclIndex[][] = new int[INITIAL_CHUNK_COUNT][]; 155 156 // attribute declarations 157 158 /** Number of attribute declarations. */ 159 private int fAttributeDeclCount = 0 ; 160 161 /** Attribute declaration name. */ 162 private QName fAttributeDeclName[][] = new QName[INITIAL_CHUNK_COUNT][]; 163 164 // is this grammar immutable? (fully constructed and not changeable) 165 private boolean fIsImmutable = false; 166 167 /** 168 * Attribute declaration type. 169 * @see XMLAttributeDecl 170 */ 171 private short fAttributeDeclType[][] = new short[INITIAL_CHUNK_COUNT][]; 172 173 /** Attribute declaration enumeration values. */ 174 private String[] fAttributeDeclEnumeration[][] = new String[INITIAL_CHUNK_COUNT][][]; 175 private short fAttributeDeclDefaultType[][] = new short[INITIAL_CHUNK_COUNT][]; 176 private DatatypeValidator fAttributeDeclDatatypeValidator[][] = new DatatypeValidator[INITIAL_CHUNK_COUNT][]; 177 private String fAttributeDeclDefaultValue[][] = new String[INITIAL_CHUNK_COUNT][]; 178 private String fAttributeDeclNonNormalizedDefaultValue[][] = new String[INITIAL_CHUNK_COUNT][]; 179 private int fAttributeDeclNextAttributeDeclIndex[][] = new int[INITIAL_CHUNK_COUNT][]; 180 181 // content specs 182 183 // here saves the content spec binary trees for element decls, 184 // each element with a content model will hold a pointer which is 185 // the index of the head node of the content spec tree. 186 187 private int fContentSpecCount = 0; 188 private short fContentSpecType[][] = new short[INITIAL_CHUNK_COUNT][]; 189 private Object fContentSpecValue[][] = new Object[INITIAL_CHUNK_COUNT][]; 190 private Object fContentSpecOtherValue[][] = new Object[INITIAL_CHUNK_COUNT][]; 191 192 // entities 193 194 private int fEntityCount = 0; 195 private String fEntityName[][] = new String[INITIAL_CHUNK_COUNT][]; 196 private String[][] fEntityValue = new String[INITIAL_CHUNK_COUNT][]; 197 private String[][] fEntityPublicId = new String[INITIAL_CHUNK_COUNT][]; 198 private String[][] fEntitySystemId = new String[INITIAL_CHUNK_COUNT][]; 199 private String[][] fEntityBaseSystemId = new String[INITIAL_CHUNK_COUNT][]; 200 private String[][] fEntityNotation = new String[INITIAL_CHUNK_COUNT][]; 201 private byte[][] fEntityIsPE = new byte[INITIAL_CHUNK_COUNT][]; 202 private byte[][] fEntityInExternal = new byte[INITIAL_CHUNK_COUNT][]; 203 204 // notations 205 206 private int fNotationCount = 0; 207 private String fNotationName[][] = new String[INITIAL_CHUNK_COUNT][]; 208 private String[][] fNotationPublicId = new String[INITIAL_CHUNK_COUNT][]; 209 private String[][] fNotationSystemId = new String[INITIAL_CHUNK_COUNT][]; 210 private String[][] fNotationBaseSystemId = new String[INITIAL_CHUNK_COUNT][]; 211 212 // other information 213 214 /** Element index mapping table. */ 215 private final Map<String, Integer> fElementIndexMap = new HashMap<>(); 216 217 /** Entity index mapping table. */ 218 private final Map<String, Integer> fEntityIndexMap = new HashMap<>(); 219 220 /** Notation index mapping table. */ 221 private final Map<String, Integer> fNotationIndexMap = new HashMap<>(); 222 223 // temp variables 224 225 /** Mixed. */ 226 private boolean fMixed; 227 228 /** Temporary qualified name. */ 229 private final QName fQName = new QName(); 230 231 /** Temporary qualified name. */ 232 private final QName fQName2 = new QName(); 233 234 /** Temporary Attribute decl. */ 235 protected final XMLAttributeDecl fAttributeDecl = new XMLAttributeDecl(); 236 237 // for buildSyntaxTree method 238 239 private int fLeafCount = 0; 240 private int fEpsilonIndex = -1; 241 242 /** Element declaration. */ 243 private XMLElementDecl fElementDecl = new XMLElementDecl(); 244 245 /** Entity declaration. */ 246 private XMLEntityDecl fEntityDecl = new XMLEntityDecl(); 247 248 /** Simple type. */ 249 private XMLSimpleType fSimpleType = new XMLSimpleType(); 250 251 /** Content spec node. */ 252 private XMLContentSpec fContentSpec = new XMLContentSpec(); 253 254 /** table of XMLElementDecl */ 255 Map<String, XMLElementDecl> fElementDeclTab = new HashMap<>(); 256 257 /** Children content model operation stack. */ 258 private short[] fOpStack = null; 259 260 /** Children content model index stack. */ 261 private int[] fNodeIndexStack = null; 262 263 /** Children content model previous node index stack. */ 264 private int[] fPrevNodeIndexStack = null; 265 266 /** Stack depth */ 267 private int fDepth = 0; 268 269 /** Entity stack. */ 270 private boolean[] fPEntityStack = new boolean[4]; 271 private int fPEDepth = 0; 272 273 // additional fields(columns) for the element Decl pool in the Grammar 274 275 /** flag if the elementDecl is External. */ 276 private int fElementDeclIsExternal[][] = new int[INITIAL_CHUNK_COUNT][]; 277 278 279 // additional fields(columns) for the attribute Decl pool in the Grammar 280 281 /** flag if the AttributeDecl is External. */ 282 private int fAttributeDeclIsExternal[][] = new int[INITIAL_CHUNK_COUNT][]; 283 284 // for mixedElement method 285 286 int valueIndex = -1; 287 int prevNodeIndex = -1; 288 int nodeIndex = -1; 289 290 // 291 // Constructors 292 // 293 294 /** Default constructor. */ 295 public DTDGrammar(SymbolTable symbolTable, XMLDTDDescription desc) { 296 fSymbolTable = symbolTable; 297 fGrammarDescription = desc; 298 } // <init>(SymbolTable) 299 300 // Grammar methods 301 302 // return the XMLDTDDescription object with which this is associated 303 public XMLGrammarDescription getGrammarDescription() { 304 return fGrammarDescription; 305 } // getGrammarDescription(): XMLGrammarDescription 306 307 // 308 // Public methods 309 // 310 311 /** 312 * Returns true if the specified element declaration is external. 313 * 314 * @param elementDeclIndex The element declaration index. 315 */ 316 public boolean getElementDeclIsExternal(int elementDeclIndex) { 317 318 if (elementDeclIndex < 0) { 319 return false; 320 } 321 322 int chunk = elementDeclIndex >> CHUNK_SHIFT; 323 int index = elementDeclIndex & CHUNK_MASK; 324 return (fElementDeclIsExternal[chunk][index] != 0); 325 326 } // getElementDeclIsExternal(int):boolean 327 328 /** 329 * Returns true if the specified attribute declaration is external. 330 * 331 * @param attributeDeclIndex Attribute declaration index. 332 */ 333 public boolean getAttributeDeclIsExternal(int attributeDeclIndex) { 334 335 if (attributeDeclIndex < 0) { 336 return false; 337 } 338 339 int chunk = attributeDeclIndex >> CHUNK_SHIFT; 340 int index = attributeDeclIndex & CHUNK_MASK; 341 return (fAttributeDeclIsExternal[chunk][index] != 0); 342 } 343 344 public int getAttributeDeclIndex(int elementDeclIndex, String attributeDeclName) { 345 if (elementDeclIndex == -1) { 346 return -1; 347 } 348 int attDefIndex = getFirstAttributeDeclIndex(elementDeclIndex); 349 while (attDefIndex != -1) { 350 getAttributeDecl(attDefIndex, fAttributeDecl); 351 352 if (fAttributeDecl.name.rawname == attributeDeclName 353 || attributeDeclName.equals(fAttributeDecl.name.rawname) ) { 354 return attDefIndex; 355 } 356 attDefIndex = getNextAttributeDeclIndex(attDefIndex); 357 } 358 return -1; 359 } // getAttributeDeclIndex (int,QName) 360 361 // 362 // XMLDTDHandler methods 363 // 364 365 /** 366 * The start of the DTD. 367 * 368 * @param locator The document locator, or null if the document 369 * location cannot be reported during the parsing of 370 * the document DTD. However, it is <em>strongly</em> 371 * recommended that a locator be supplied that can 372 * at least report the base system identifier of the 373 * DTD. 374 * 375 * @param augs Additional information that may include infoset 376 * augmentations. 377 * @throws XNIException Thrown by handler to signal an error. 378 */ 379 public void startDTD(XMLLocator locator, Augmentations augs) throws XNIException { 380 //Initialize stack 381 fOpStack = null; 382 fNodeIndexStack = null; 383 fPrevNodeIndexStack = null; 384 } // startDTD(XMLLocator) 385 386 /** 387 * This method notifies of the start of an entity. The DTD has the 388 * pseudo-name of "[dtd]" and parameter entity names start with '%'. 389 * <p> 390 * <strong>Note:</strong> Since the DTD is an entity, the handler 391 * will be notified of the start of the DTD entity by calling the 392 * startParameterEntity method with the entity name "[dtd]" <em>before</em> calling 393 * the startDTD method. 394 * 395 * @param name The name of the parameter entity. 396 * @param identifier The resource identifier. 397 * @param encoding The auto-detected IANA encoding name of the entity 398 * stream. This value will be null in those situations 399 * where the entity encoding is not auto-detected (e.g. 400 * internal parameter entities). 401 * @param augs Additional information that may include infoset 402 * augmentations. 403 * 404 * @throws XNIException Thrown by handler to signal an error. 405 */ 406 public void startParameterEntity(String name, 407 XMLResourceIdentifier identifier, 408 String encoding, 409 Augmentations augs) throws XNIException { 410 411 // keep track of this entity before fEntityDepth is increased 412 if (fPEDepth == fPEntityStack.length) { 413 boolean[] entityarray = new boolean[fPEntityStack.length * 2]; 414 System.arraycopy(fPEntityStack, 0, entityarray, 0, fPEntityStack.length); 415 fPEntityStack = entityarray; 416 } 417 fPEntityStack[fPEDepth] = fReadingExternalDTD; 418 fPEDepth++; 419 420 } // startParameterEntity(String,XMLResourceIdentifier,String,Augmentations) 421 422 /** 423 * The start of the DTD external subset. 424 * 425 * @param augs Additional information that may include infoset 426 * augmentations. 427 * 428 * @throws XNIException Thrown by handler to signal an error. 429 */ 430 public void startExternalSubset(XMLResourceIdentifier identifier, 431 Augmentations augs) throws XNIException { 432 fReadingExternalDTD = true; 433 } // startExternalSubset(Augmentations) 434 435 /** 436 * This method notifies the end of an entity. The DTD has the pseudo-name 437 * of "[dtd]" and parameter entity names start with '%'. 438 * <p> 439 * <strong>Note:</strong> Since the DTD is an entity, the handler 440 * will be notified of the end of the DTD entity by calling the 441 * endEntity method with the entity name "[dtd]" <em>after</em> calling 442 * the endDTD method. 443 * 444 * @param name The name of the entity. 445 * @param augs Additional information that may include infoset 446 * augmentations. 447 * @throws XNIException Thrown by handler to signal an error. 448 */ 449 public void endParameterEntity(String name, Augmentations augs) throws XNIException { 450 451 fPEDepth--; 452 fReadingExternalDTD = fPEntityStack[fPEDepth]; 453 454 } // endParameterEntity(String,Augmentations) 455 456 /** 457 * The end of the DTD external subset. 458 * 459 * @param augs Additional information that may include infoset 460 * augmentations. 461 * 462 * @throws XNIException Thrown by handler to signal an error. 463 */ 464 public void endExternalSubset(Augmentations augs) throws XNIException { 465 fReadingExternalDTD = false; 466 } // endExternalSubset(Augmentations) 467 468 /** 469 * An element declaration. 470 * 471 * @param name The name of the element. 472 * @param contentModel The element content model. 473 * @param augs Additional information that may include infoset 474 * augmentations. 475 * @throws XNIException Thrown by handler to signal an error. 476 */ 477 public void elementDecl(String name, String contentModel, Augmentations augs) 478 throws XNIException { 479 480 XMLElementDecl tmpElementDecl = fElementDeclTab.get(name) ; 481 482 // check if it is already defined 483 if ( tmpElementDecl != null ) { 484 if (tmpElementDecl.type == -1) { 485 fCurrentElementIndex = getElementDeclIndex(name); 486 } 487 else { 488 // duplicate element, ignored. 489 return; 490 } 491 } 492 else { 493 fCurrentElementIndex = createElementDecl();//create element decl 494 } 495 496 XMLElementDecl elementDecl = new XMLElementDecl(); 497 498 fQName.setValues(null, name, name, null); 499 500 elementDecl.name.setValues(fQName); 501 502 elementDecl.contentModelValidator = null; 503 elementDecl.scope= -1; 504 if (contentModel.equals("EMPTY")) { 505 elementDecl.type = XMLElementDecl.TYPE_EMPTY; 506 } 507 else if (contentModel.equals("ANY")) { 508 elementDecl.type = XMLElementDecl.TYPE_ANY; 509 } 510 else if (contentModel.startsWith("(") ) { 511 if (contentModel.indexOf("#PCDATA") > 0 ) { 512 elementDecl.type = XMLElementDecl.TYPE_MIXED; 513 } 514 else { 515 elementDecl.type = XMLElementDecl.TYPE_CHILDREN; 516 } 517 } 518 519 520 //add(or set) this elementDecl to the local cache 521 this.fElementDeclTab.put(name, elementDecl ); 522 523 fElementDecl = elementDecl; 524 addContentSpecToElement(elementDecl); 525 526 if ( DEBUG ) { 527 System.out.println( "name = " + fElementDecl.name.localpart ); 528 System.out.println( "Type = " + fElementDecl.type ); 529 } 530 531 setElementDecl(fCurrentElementIndex, fElementDecl );//set internal structure 532 533 int chunk = fCurrentElementIndex >> CHUNK_SHIFT; 534 int index = fCurrentElementIndex & CHUNK_MASK; 535 ensureElementDeclCapacity(chunk); 536 fElementDeclIsExternal[chunk][index] = (fReadingExternalDTD || fPEDepth > 0) ? 1 : 0; 537 538 } // elementDecl(String,String) 539 540 /** 541 * An attribute declaration. 542 * 543 * @param elementName The name of the element that this attribute 544 * is associated with. 545 * @param attributeName The name of the attribute. 546 * @param type The attribute type. This value will be one of 547 * the following: "CDATA", "ENTITY", "ENTITIES", 548 * "ENUMERATION", "ID", "IDREF", "IDREFS", 549 * "NMTOKEN", "NMTOKENS", or "NOTATION". 550 * @param enumeration If the type has the value "ENUMERATION", this 551 * array holds the allowed attribute values; 552 * otherwise, this array is null. 553 * @param defaultType The attribute default type. This value will be 554 * one of the following: "#FIXED", "#IMPLIED", 555 * "#REQUIRED", or null. 556 * @param defaultValue The attribute default value, or null if no 557 * default value is specified. 558 * @param nonNormalizedDefaultValue The attribute default value with no normalization 559 * performed, or null if no default value is specified. 560 * 561 * @param augs Additional information that may include infoset 562 * augmentations. 563 * @throws XNIException Thrown by handler to signal an error. 564 */ 565 public void attributeDecl(String elementName, String attributeName, 566 String type, String[] enumeration, 567 String defaultType, XMLString defaultValue, 568 XMLString nonNormalizedDefaultValue, Augmentations augs) throws XNIException { 569 570 if ( this.fElementDeclTab.containsKey(elementName) ) { 571 //if ElementDecl has already being created in the Grammar then remove from table, 572 //this.fElementDeclTab.remove( (String) elementName ); 573 } 574 // then it is forward reference to a element decl, create the elementDecl first. 575 else { 576 fCurrentElementIndex = createElementDecl();//create element decl 577 578 XMLElementDecl elementDecl = new XMLElementDecl(); 579 elementDecl.name.setValues(null, elementName, elementName, null); 580 581 elementDecl.scope= -1; 582 583 //add(or set) this elementDecl to the local cache 584 this.fElementDeclTab.put(elementName, elementDecl ); 585 586 //set internal structure 587 setElementDecl(fCurrentElementIndex, elementDecl ); 588 } 589 590 //Get Grammar index to grammar array 591 int elementIndex = getElementDeclIndex(elementName); 592 593 //return, when more than one definition is provided for the same attribute of given element type 594 //only the first declaration is binding and later declarations are ignored 595 if (getAttributeDeclIndex(elementIndex, attributeName) != -1) { 596 return; 597 } 598 599 fCurrentAttributeIndex = createAttributeDecl();// Create current Attribute Decl 600 601 fSimpleType.clear(); 602 if ( defaultType != null ) { 603 if ( defaultType.equals( "#FIXED") ) { 604 fSimpleType.defaultType = XMLSimpleType.DEFAULT_TYPE_FIXED; 605 } else if ( defaultType.equals( "#IMPLIED") ) { 606 fSimpleType.defaultType = XMLSimpleType.DEFAULT_TYPE_IMPLIED; 607 } else if ( defaultType.equals( "#REQUIRED") ) { 608 fSimpleType.defaultType = XMLSimpleType.DEFAULT_TYPE_REQUIRED; 609 } 610 } 611 if ( DEBUG ) { 612 System.out.println("defaultvalue = " + defaultValue.toString() ); 613 } 614 fSimpleType.defaultValue = defaultValue!=null ? defaultValue.toString() : null; 615 fSimpleType.nonNormalizedDefaultValue = nonNormalizedDefaultValue!=null ? nonNormalizedDefaultValue.toString() : null; 616 fSimpleType.enumeration = enumeration; 617 618 if (type.equals("CDATA")) { 619 fSimpleType.type = XMLSimpleType.TYPE_CDATA; 620 } 621 else if ( type.equals("ID") ) { 622 fSimpleType.type = XMLSimpleType.TYPE_ID; 623 } 624 else if ( type.startsWith("IDREF") ) { 625 fSimpleType.type = XMLSimpleType.TYPE_IDREF; 626 if (type.indexOf("S") > 0) { 627 fSimpleType.list = true; 628 } 629 } 630 else if (type.equals("ENTITIES")) { 631 fSimpleType.type = XMLSimpleType.TYPE_ENTITY; 632 fSimpleType.list = true; 633 } 634 else if (type.equals("ENTITY")) { 635 fSimpleType.type = XMLSimpleType.TYPE_ENTITY; 636 } 637 else if (type.equals("NMTOKENS")) { 638 fSimpleType.type = XMLSimpleType.TYPE_NMTOKEN; 639 fSimpleType.list = true; 640 } 641 else if (type.equals("NMTOKEN")) { 642 fSimpleType.type = XMLSimpleType.TYPE_NMTOKEN; 643 } 644 else if (type.startsWith("NOTATION") ) { 645 fSimpleType.type = XMLSimpleType.TYPE_NOTATION; 646 } 647 else if (type.startsWith("ENUMERATION") ) { 648 fSimpleType.type = XMLSimpleType.TYPE_ENUMERATION; 649 } 650 else { 651 // REVISIT: Report error message. -Ac 652 System.err.println("!!! unknown attribute type "+type); 653 } 654 // REVISIT: The datatype should be stored with the attribute value 655 // and not special-cased in the XMLValidator. -Ac 656 //fSimpleType.datatypeValidator = fDatatypeValidatorFactory.createDatatypeValidator(type, null, facets, fSimpleType.list); 657 658 fQName.setValues(null, attributeName, attributeName, null); 659 fAttributeDecl.setValues( fQName, fSimpleType, false ); 660 661 setAttributeDecl(elementIndex, fCurrentAttributeIndex, fAttributeDecl); 662 663 int chunk = fCurrentAttributeIndex >> CHUNK_SHIFT; 664 int index = fCurrentAttributeIndex & CHUNK_MASK; 665 ensureAttributeDeclCapacity(chunk); 666 fAttributeDeclIsExternal[chunk][index] = (fReadingExternalDTD || fPEDepth > 0) ? 1 : 0; 667 668 } // attributeDecl(String,String,String,String[],String,XMLString,XMLString, Augmentations) 669 670 /** 671 * An internal entity declaration. 672 * 673 * @param name The name of the entity. Parameter entity names start with 674 * '%', whereas the name of a general entity is just the 675 * entity name. 676 * @param text The value of the entity. 677 * @param nonNormalizedText The non-normalized value of the entity. This 678 * value contains the same sequence of characters that was in 679 * the internal entity declaration, without any entity 680 * references expanded. 681 * @param augs Additional information that may include infoset 682 * augmentations. 683 * @throws XNIException Thrown by handler to signal an error. 684 */ 685 public void internalEntityDecl(String name, XMLString text, 686 XMLString nonNormalizedText, 687 Augmentations augs) throws XNIException { 688 689 int entityIndex = getEntityDeclIndex(name); 690 if( entityIndex == -1){ 691 entityIndex = createEntityDecl(); 692 boolean isPE = name.startsWith("%"); 693 boolean inExternal = (fReadingExternalDTD || fPEDepth > 0); 694 XMLEntityDecl entityDecl = new XMLEntityDecl(); 695 entityDecl.setValues(name,null,null, null, null, 696 text.toString(), isPE, inExternal); 697 698 setEntityDecl(entityIndex, entityDecl); 699 } 700 701 } // internalEntityDecl(String,XMLString,XMLString) 702 703 /** 704 * An external entity declaration. 705 * 706 * @param name The name of the entity. Parameter entity names start 707 * with '%', whereas the name of a general entity is just 708 * the entity name. 709 * @param identifier An object containing all location information 710 * pertinent to this external entity declaration. 711 * @param augs Additional information that may include infoset 712 * augmentations. 713 * @throws XNIException Thrown by handler to signal an error. 714 */ 715 public void externalEntityDecl(String name, 716 XMLResourceIdentifier identifier, 717 Augmentations augs) throws XNIException { 718 719 int entityIndex = getEntityDeclIndex(name); 720 if( entityIndex == -1){ 721 entityIndex = createEntityDecl(); 722 boolean isPE = name.startsWith("%"); 723 boolean inExternal = (fReadingExternalDTD || fPEDepth > 0); 724 725 XMLEntityDecl entityDecl = new XMLEntityDecl(); 726 entityDecl.setValues(name, identifier.getPublicId(), identifier.getLiteralSystemId(), 727 identifier.getBaseSystemId(), 728 null, null, isPE, inExternal); 729 730 setEntityDecl(entityIndex, entityDecl); 731 } 732 } // externalEntityDecl(String, XMLResourceIdentifier, Augmentations) 733 734 /** 735 * An unparsed entity declaration. 736 * 737 * @param name The name of the entity. 738 * @param identifier An object containing all location information 739 * pertinent to this entity. 740 * @param notation The name of the notation. 741 * @param augs Additional information that may include infoset 742 * augmentations. 743 * @throws XNIException Thrown by handler to signal an error. 744 */ 745 public void unparsedEntityDecl(String name, XMLResourceIdentifier identifier, 746 String notation, 747 Augmentations augs) throws XNIException { 748 749 XMLEntityDecl entityDecl = new XMLEntityDecl(); 750 boolean isPE = name.startsWith("%"); 751 boolean inExternal = (fReadingExternalDTD || fPEDepth > 0); 752 753 entityDecl.setValues(name,identifier.getPublicId(),identifier.getLiteralSystemId(), 754 identifier.getBaseSystemId(), notation, 755 null, isPE, inExternal); 756 int entityIndex = getEntityDeclIndex(name); 757 if (entityIndex == -1) { 758 entityIndex = createEntityDecl(); 759 setEntityDecl(entityIndex, entityDecl); 760 } 761 762 } // unparsedEntityDecl(String,StringXMLResourceIdentifier,Augmentations) 763 764 /** 765 * A notation declaration 766 * 767 * @param name The name of the notation. 768 * @param identifier An object containing all location information 769 * pertinent to this notation. 770 * @param augs Additional information that may include infoset 771 * augmentations. 772 * @throws XNIException Thrown by handler to signal an error. 773 */ 774 public void notationDecl(String name, XMLResourceIdentifier identifier, 775 Augmentations augs) throws XNIException { 776 777 XMLNotationDecl notationDecl = new XMLNotationDecl(); 778 notationDecl.setValues(name,identifier.getPublicId(),identifier.getLiteralSystemId(), 779 identifier.getBaseSystemId()); 780 int notationIndex = getNotationDeclIndex(name); 781 if (notationIndex == -1) { 782 notationIndex = createNotationDecl(); 783 setNotationDecl(notationIndex, notationDecl); 784 } 785 786 } // notationDecl(String,XMLResourceIdentifier,Augmentations) 787 788 /** 789 * The end of the DTD. 790 * 791 * @param augs Additional information that may include infoset 792 * augmentations. 793 * @throws XNIException Thrown by handler to signal an error. 794 */ 795 public void endDTD(Augmentations augs) throws XNIException { 796 fIsImmutable = true; 797 // make sure our description contains useful stuff... 798 if (fGrammarDescription.getRootName() == null) { 799 // we don't know what the root is; so use possibleRoots... 800 int chunk, index = 0; 801 String currName = null; 802 final int size = fElementDeclCount; 803 List<String> elements = new ArrayList<>(size); 804 for (int i = 0; i < size; ++i) { 805 chunk = i >> CHUNK_SHIFT; 806 index = i & CHUNK_MASK; 807 currName = fElementDeclName[chunk][index].rawname; 808 elements.add(currName); 809 } 810 fGrammarDescription.setPossibleRoots(elements); 811 } 812 } // endDTD() 813 814 // sets the source of this handler 815 public void setDTDSource(XMLDTDSource source) { 816 fDTDSource = source; 817 } // setDTDSource(XMLDTDSource) 818 819 // returns the source of this handler 820 public XMLDTDSource getDTDSource() { 821 return fDTDSource; 822 } // getDTDSource(): XMLDTDSource 823 824 // no-op methods 825 826 /** 827 * Notifies of the presence of a TextDecl line in an entity. If present, 828 * this method will be called immediately following the startEntity call. 829 * <p> 830 * <strong>Note:</strong> This method is only called for external 831 * parameter entities referenced in the DTD. 832 * 833 * @param version The XML version, or null if not specified. 834 * @param encoding The IANA encoding name of the entity. 835 * 836 * @param augs Additional information that may include infoset 837 * augmentations. 838 * @throws XNIException Thrown by handler to signal an error. 839 */ 840 public void textDecl(String version, String encoding, Augmentations augs) 841 throws XNIException {} 842 843 /** 844 * A comment. 845 * 846 * @param text The text in the comment. 847 * @param augs Additional information that may include infoset 848 * augmentations. 849 * @throws XNIException Thrown by application to signal an error. 850 */ 851 public void comment(XMLString text, Augmentations augs) throws XNIException {} 852 853 /** 854 * A processing instruction. Processing instructions consist of a 855 * target name and, optionally, text data. The data is only meaningful 856 * to the application. 857 * <p> 858 * Typically, a processing instruction's data will contain a series 859 * of pseudo-attributes. These pseudo-attributes follow the form of 860 * element attributes but are <strong>not</strong> parsed or presented 861 * to the application as anything other than text. The application is 862 * responsible for parsing the data. 863 * 864 * @param target The target. 865 * @param data The data or null if none specified. 866 * @param augs Additional information that may include infoset 867 * augmentations. 868 * @throws XNIException Thrown by handler to signal an error. 869 */ 870 public void processingInstruction(String target, XMLString data, 871 Augmentations augs) throws XNIException {} 872 873 /** 874 * The start of an attribute list. 875 * 876 * @param elementName The name of the element that this attribute 877 * list is associated with. 878 * @param augs Additional information that may include infoset 879 * augmentations. 880 * @throws XNIException Thrown by handler to signal an error. 881 */ 882 public void startAttlist(String elementName, Augmentations augs) 883 throws XNIException {} 884 885 /** 886 * The end of an attribute list. 887 * @param augs Additional information that may include infoset 888 * augmentations. 889 * @throws XNIException Thrown by handler to signal an error. 890 */ 891 public void endAttlist(Augmentations augs) throws XNIException {} 892 893 /** 894 * The start of a conditional section. 895 * 896 * @param type The type of the conditional section. This value will 897 * either be CONDITIONAL_INCLUDE or CONDITIONAL_IGNORE. 898 * @param augs Additional information that may include infoset 899 * augmentations. 900 * @throws XNIException Thrown by handler to signal an error. 901 * 902 * @see XMLDTDHandler#CONDITIONAL_INCLUDE 903 * @see XMLDTDHandler#CONDITIONAL_IGNORE 904 */ 905 public void startConditional(short type, Augmentations augs) 906 throws XNIException {} 907 908 /** 909 * Characters within an IGNORE conditional section. 910 * 911 * @param text The ignored text. 912 * @param augs Additional information that may include infoset 913 * augmentations. 914 */ 915 public void ignoredCharacters(XMLString text, Augmentations augs) 916 throws XNIException {} 917 918 /** 919 * The end of a conditional section. 920 * @param augs Additional information that may include infoset 921 * augmentations. 922 * @throws XNIException Thrown by handler to signal an error. 923 */ 924 public void endConditional(Augmentations augs) throws XNIException {} 925 926 // 927 // XMLDTDContentModelHandler methods 928 // 929 930 // set content model source 931 public void setDTDContentModelSource(XMLDTDContentModelSource source) { 932 fDTDContentModelSource = source; 933 } 934 935 // get content model source 936 public XMLDTDContentModelSource getDTDContentModelSource() { 937 return fDTDContentModelSource; 938 } 939 940 /** 941 * The start of a content model. Depending on the type of the content 942 * model, specific methods may be called between the call to the 943 * startContentModel method and the call to the endContentModel method. 944 * 945 * @param elementName The name of the element. 946 * @param augs Additional information that may include infoset 947 * augmentations. 948 * @throws XNIException Thrown by handler to signal an error. 949 */ 950 public void startContentModel(String elementName, Augmentations augs) 951 throws XNIException { 952 953 XMLElementDecl elementDecl = this.fElementDeclTab.get(elementName); 954 if ( elementDecl != null ) { 955 fElementDecl = elementDecl; 956 } 957 fDepth = 0; 958 initializeContentModelStack(); 959 960 } // startContentModel(String) 961 962 /** 963 * A start of either a mixed or children content model. A mixed 964 * content model will immediately be followed by a call to the 965 * <code>pcdata()</code> method. A children content model will 966 * contain additional groups and/or elements. 967 * 968 * @param augs Additional information that may include infoset 969 * augmentations. 970 * @throws XNIException Thrown by handler to signal an error. 971 * 972 * @see #any 973 * @see #empty 974 */ 975 public void startGroup(Augmentations augs) throws XNIException { 976 fDepth++; 977 initializeContentModelStack(); 978 fMixed = false; 979 } // startGroup() 980 981 /** 982 * The appearance of "#PCDATA" within a group signifying a 983 * mixed content model. This method will be the first called 984 * following the content model's <code>startGroup()</code>. 985 * 986 *@param augs Additional information that may include infoset 987 * augmentations. 988 * 989 * @throws XNIException Thrown by handler to signal an error. 990 * 991 * @see #startGroup 992 */ 993 public void pcdata(Augmentations augs) throws XNIException { 994 fMixed = true; 995 } // pcdata() 996 997 /** 998 * A referenced element in a mixed or children content model. 999 * 1000 * @param elementName The name of the referenced element. 1001 * @param augs Additional information that may include infoset 1002 * augmentations. 1003 * 1004 * @throws XNIException Thrown by handler to signal an error. 1005 */ 1006 public void element(String elementName, Augmentations augs) throws XNIException { 1007 if (fMixed) { 1008 if (fNodeIndexStack[fDepth] == -1 ) { 1009 fNodeIndexStack[fDepth] = addUniqueLeafNode(elementName); 1010 } 1011 else { 1012 fNodeIndexStack[fDepth] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_CHOICE, 1013 fNodeIndexStack[fDepth], 1014 addUniqueLeafNode(elementName)); 1015 } 1016 } 1017 else { 1018 fNodeIndexStack[fDepth] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_LEAF, elementName); 1019 } 1020 } // element(String) 1021 1022 /** 1023 * The separator between choices or sequences of a mixed or children 1024 * content model. 1025 * 1026 * @param separator The type of children separator. 1027 * @param augs Additional information that may include infoset 1028 * augmentations. 1029 * @throws XNIException Thrown by handler to signal an error. 1030 * 1031 * @see org.apache.xerces.xni.XMLDTDContentModelHandler#SEPARATOR_CHOICE 1032 * @see org.apache.xerces.xni.XMLDTDContentModelHandler#SEPARATOR_SEQUENCE 1033 */ 1034 public void separator(short separator, Augmentations augs) throws XNIException { 1035 1036 if (!fMixed) { 1037 if (fOpStack[fDepth] != XMLContentSpec.CONTENTSPECNODE_SEQ && separator == XMLDTDContentModelHandler.SEPARATOR_CHOICE ) { 1038 if (fPrevNodeIndexStack[fDepth] != -1) { 1039 fNodeIndexStack[fDepth] = addContentSpecNode(fOpStack[fDepth], fPrevNodeIndexStack[fDepth], fNodeIndexStack[fDepth]); 1040 } 1041 fPrevNodeIndexStack[fDepth] = fNodeIndexStack[fDepth]; 1042 fOpStack[fDepth] = XMLContentSpec.CONTENTSPECNODE_CHOICE; 1043 } else if (fOpStack[fDepth] != XMLContentSpec.CONTENTSPECNODE_CHOICE && separator == XMLDTDContentModelHandler.SEPARATOR_SEQUENCE) { 1044 if (fPrevNodeIndexStack[fDepth] != -1) { 1045 fNodeIndexStack[fDepth] = addContentSpecNode(fOpStack[fDepth], fPrevNodeIndexStack[fDepth], fNodeIndexStack[fDepth]); 1046 } 1047 fPrevNodeIndexStack[fDepth] = fNodeIndexStack[fDepth]; 1048 fOpStack[fDepth] = XMLContentSpec.CONTENTSPECNODE_SEQ; 1049 } 1050 } 1051 1052 } // separator(short) 1053 1054 /** 1055 * The occurrence count for a child in a children content model or 1056 * for the mixed content model group. 1057 * 1058 * @param occurrence The occurrence count for the last element 1059 * or group. 1060 * @param augs Additional information that may include infoset 1061 * augmentations. 1062 * @throws XNIException Thrown by handler to signal an error. 1063 * 1064 * @see org.apache.xerces.xni.XMLDTDContentModelHandler#OCCURS_ZERO_OR_ONE 1065 * @see org.apache.xerces.xni.XMLDTDContentModelHandler#OCCURS_ZERO_OR_MORE 1066 * @see org.apache.xerces.xni.XMLDTDContentModelHandler#OCCURS_ONE_OR_MORE 1067 */ 1068 public void occurrence(short occurrence, Augmentations augs) throws XNIException { 1069 1070 if (!fMixed) { 1071 if (occurrence == XMLDTDContentModelHandler.OCCURS_ZERO_OR_ONE ) { 1072 fNodeIndexStack[fDepth] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE, fNodeIndexStack[fDepth], -1); 1073 } else if ( occurrence == XMLDTDContentModelHandler.OCCURS_ZERO_OR_MORE ) { 1074 fNodeIndexStack[fDepth] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE, fNodeIndexStack[fDepth], -1 ); 1075 } else if ( occurrence == XMLDTDContentModelHandler.OCCURS_ONE_OR_MORE) { 1076 fNodeIndexStack[fDepth] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE, fNodeIndexStack[fDepth], -1 ); 1077 } 1078 } 1079 1080 } // occurrence(short) 1081 1082 /** 1083 * The end of a group for mixed or children content models. 1084 * 1085 * @param augs Additional information that may include infoset 1086 * augmentations. 1087 * @throws XNIException Thrown by handler to signal an error. 1088 */ 1089 public void endGroup(Augmentations augs) throws XNIException { 1090 1091 if (!fMixed) { 1092 if (fPrevNodeIndexStack[fDepth] != -1) { 1093 fNodeIndexStack[fDepth] = addContentSpecNode(fOpStack[fDepth], fPrevNodeIndexStack[fDepth], fNodeIndexStack[fDepth]); 1094 } 1095 int nodeIndex = fNodeIndexStack[fDepth--]; 1096 fNodeIndexStack[fDepth] = nodeIndex; 1097 } 1098 1099 } // endGroup() 1100 1101 // no-op methods 1102 1103 /** 1104 * A content model of ANY. 1105 * 1106 * @param augs Additional information that may include infoset 1107 * augmentations. 1108 * @throws XNIException Thrown by handler to signal an error. 1109 * 1110 * @see #empty 1111 * @see #startGroup 1112 */ 1113 public void any(Augmentations augs) throws XNIException {} 1114 1115 /** 1116 * A content model of EMPTY. 1117 * 1118 * @param augs Additional information that may include infoset 1119 * augmentations. 1120 * @throws XNIException Thrown by handler to signal an error. 1121 * 1122 * @see #any 1123 * @see #startGroup 1124 */ 1125 public void empty(Augmentations augs) throws XNIException {} 1126 1127 /** 1128 * The end of a content model. 1129 * @param augs Additional information that may include infoset 1130 * augmentations. 1131 * 1132 * @throws XNIException Thrown by handler to signal an error. 1133 */ 1134 public void endContentModel(Augmentations augs) throws XNIException {} 1135 1136 // 1137 // Grammar methods 1138 // 1139 1140 /** Returns true if this grammar is namespace aware. */ 1141 public boolean isNamespaceAware() { 1142 return false; 1143 } // isNamespaceAware():boolean 1144 1145 /** Returns the symbol table. */ 1146 public SymbolTable getSymbolTable() { 1147 return fSymbolTable; 1148 } // getSymbolTable():SymbolTable 1149 1150 /** 1151 * Returns the index of the first element declaration. This index 1152 * is then used to query more information about the element declaration. 1153 * 1154 * @see #getNextElementDeclIndex 1155 * @see #getElementDecl 1156 */ 1157 public int getFirstElementDeclIndex() { 1158 return fElementDeclCount >= 0 ? 0 : -1; 1159 } // getFirstElementDeclIndex():int 1160 1161 /** 1162 * Returns the next index of the element declaration following the 1163 * specified element declaration. 1164 * 1165 * @param elementDeclIndex The element declaration index. 1166 */ 1167 public int getNextElementDeclIndex(int elementDeclIndex) { 1168 return elementDeclIndex < fElementDeclCount - 1 1169 ? elementDeclIndex + 1 : -1; 1170 } // getNextElementDeclIndex(int):int 1171 1172 /** 1173 * getElementDeclIndex 1174 * 1175 * @param elementDeclName 1176 * 1177 * @return index of the elementDeclName in scope 1178 */ 1179 public int getElementDeclIndex(String elementDeclName) { 1180 Integer mapping = fElementIndexMap.get(elementDeclName); 1181 if (mapping == null) { 1182 mapping = -1; 1183 } 1184 //System.out.println("getElementDeclIndex("+elementDeclName+") -> "+mapping); 1185 return mapping; 1186 } // getElementDeclIndex(String):int 1187 1188 /** Returns the element decl index. 1189 * @param elementDeclQName qualilfied name of the element 1190 */ 1191 public int getElementDeclIndex(QName elementDeclQName) { 1192 return getElementDeclIndex(elementDeclQName.rawname); 1193 } // getElementDeclIndex(QName):int 1194 1195 /** make separate function for getting contentSpecType of element. 1196 * we can avoid setting of the element values. 1197 */ 1198 1199 public short getContentSpecType(int elementIndex){ 1200 if (elementIndex < 0 || elementIndex >= fElementDeclCount) { 1201 return -1 ; 1202 } 1203 1204 int chunk = elementIndex >> CHUNK_SHIFT; 1205 int index = elementIndex & CHUNK_MASK; 1206 1207 if(fElementDeclType[chunk][index] == -1){ 1208 return -1 ; 1209 } 1210 else{ 1211 return (short) (fElementDeclType[chunk][index] & LIST_MASK); 1212 } 1213 1214 }//getContentSpecType 1215 1216 /** 1217 * getElementDecl 1218 * 1219 * @param elementDeclIndex 1220 * @param elementDecl The values of this structure are set by this call. 1221 * 1222 * @return True if find the element, False otherwise. 1223 */ 1224 public boolean getElementDecl(int elementDeclIndex, 1225 XMLElementDecl elementDecl) { 1226 1227 if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) { 1228 return false; 1229 } 1230 1231 int chunk = elementDeclIndex >> CHUNK_SHIFT; 1232 int index = elementDeclIndex & CHUNK_MASK; 1233 1234 elementDecl.name.setValues(fElementDeclName[chunk][index]); 1235 1236 if (fElementDeclType[chunk][index] == -1) { 1237 elementDecl.type = -1; 1238 elementDecl.simpleType.list = false; 1239 } else { 1240 elementDecl.type = (short) (fElementDeclType[chunk][index] & LIST_MASK); 1241 elementDecl.simpleType.list = (fElementDeclType[chunk][index] & LIST_FLAG) != 0; 1242 } 1243 1244 /* Validators are null until we add that code */ 1245 if (elementDecl.type == XMLElementDecl.TYPE_CHILDREN || elementDecl.type == XMLElementDecl.TYPE_MIXED) { 1246 elementDecl.contentModelValidator = getElementContentModelValidator(elementDeclIndex); 1247 } 1248 1249 elementDecl.simpleType.datatypeValidator = null; 1250 elementDecl.simpleType.defaultType = -1; 1251 elementDecl.simpleType.defaultValue = null; 1252 1253 return true; 1254 1255 } // getElementDecl(int,XMLElementDecl):boolean 1256 1257 QName getElementDeclName(int elementDeclIndex) { 1258 if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) { 1259 return null; 1260 } 1261 int chunk = elementDeclIndex >> CHUNK_SHIFT; 1262 int index = elementDeclIndex & CHUNK_MASK; 1263 return fElementDeclName[chunk][index]; 1264 } 1265 1266 // REVISIT: Make this getAttributeDeclCount/getAttributeDeclAt. -Ac 1267 1268 /** 1269 * getFirstAttributeDeclIndex 1270 * 1271 * @param elementDeclIndex 1272 * 1273 * @return index of the first attribute for element declaration elementDeclIndex 1274 */ 1275 public int getFirstAttributeDeclIndex(int elementDeclIndex) { 1276 int chunk = elementDeclIndex >> CHUNK_SHIFT; 1277 int index = elementDeclIndex & CHUNK_MASK; 1278 1279 return fElementDeclFirstAttributeDeclIndex[chunk][index]; 1280 } // getFirstAttributeDeclIndex 1281 1282 /** 1283 * getNextAttributeDeclIndex 1284 * 1285 * @param attributeDeclIndex 1286 * 1287 * @return index of the next attribute of the attribute at attributeDeclIndex 1288 */ 1289 public int getNextAttributeDeclIndex(int attributeDeclIndex) { 1290 int chunk = attributeDeclIndex >> CHUNK_SHIFT; 1291 int index = attributeDeclIndex & CHUNK_MASK; 1292 1293 return fAttributeDeclNextAttributeDeclIndex[chunk][index]; 1294 } // getNextAttributeDeclIndex 1295 1296 /** 1297 * getAttributeDecl 1298 * 1299 * @param attributeDeclIndex 1300 * @param attributeDecl The values of this structure are set by this call. 1301 * 1302 * @return true if getAttributeDecl was able to fill in the value of attributeDecl 1303 */ 1304 public boolean getAttributeDecl(int attributeDeclIndex, XMLAttributeDecl attributeDecl) { 1305 if (attributeDeclIndex < 0 || attributeDeclIndex >= fAttributeDeclCount) { 1306 return false; 1307 } 1308 int chunk = attributeDeclIndex >> CHUNK_SHIFT; 1309 int index = attributeDeclIndex & CHUNK_MASK; 1310 1311 attributeDecl.name.setValues(fAttributeDeclName[chunk][index]); 1312 1313 short attributeType; 1314 boolean isList; 1315 1316 if (fAttributeDeclType[chunk][index] == -1) { 1317 1318 attributeType = -1; 1319 isList = false; 1320 } else { 1321 attributeType = (short) (fAttributeDeclType[chunk][index] & LIST_MASK); 1322 isList = (fAttributeDeclType[chunk][index] & LIST_FLAG) != 0; 1323 } 1324 attributeDecl.simpleType.setValues(attributeType,fAttributeDeclName[chunk][index].localpart, 1325 fAttributeDeclEnumeration[chunk][index], 1326 isList, fAttributeDeclDefaultType[chunk][index], 1327 fAttributeDeclDefaultValue[chunk][index], 1328 fAttributeDeclNonNormalizedDefaultValue[chunk][index], 1329 fAttributeDeclDatatypeValidator[chunk][index]); 1330 return true; 1331 1332 } // getAttributeDecl 1333 1334 1335 /** 1336 * Returns whether the given attribute is of type CDATA or not 1337 * 1338 * @param elName The element name. 1339 * @param atName The attribute name. 1340 * 1341 * @return true if the attribute is of type CDATA 1342 */ 1343 public boolean isCDATAAttribute(QName elName, QName atName) { 1344 int elDeclIdx = getElementDeclIndex(elName); 1345 if (getAttributeDecl(elDeclIdx, fAttributeDecl) 1346 && fAttributeDecl.simpleType.type != XMLSimpleType.TYPE_CDATA){ 1347 return false; 1348 } 1349 return true; 1350 } 1351 1352 /** 1353 * getEntityDeclIndex 1354 * 1355 * @param entityDeclName 1356 * 1357 * @return the index of the EntityDecl 1358 */ 1359 public int getEntityDeclIndex(String entityDeclName) { 1360 if (entityDeclName == null || fEntityIndexMap.get(entityDeclName) == null) { 1361 return -1; 1362 } 1363 1364 return fEntityIndexMap.get(entityDeclName); 1365 } // getEntityDeclIndex 1366 1367 /** 1368 * getEntityDecl 1369 * 1370 * @param entityDeclIndex 1371 * @param entityDecl 1372 * 1373 * @return true if getEntityDecl was able to fill entityDecl with the contents of the entity 1374 * with index entityDeclIndex 1375 */ 1376 public boolean getEntityDecl(int entityDeclIndex, XMLEntityDecl entityDecl) { 1377 if (entityDeclIndex < 0 || entityDeclIndex >= fEntityCount) { 1378 return false; 1379 } 1380 int chunk = entityDeclIndex >> CHUNK_SHIFT; 1381 int index = entityDeclIndex & CHUNK_MASK; 1382 1383 entityDecl.setValues(fEntityName[chunk][index], 1384 fEntityPublicId[chunk][index], 1385 fEntitySystemId[chunk][index], 1386 fEntityBaseSystemId[chunk][index], 1387 fEntityNotation[chunk][index], 1388 fEntityValue[chunk][index], 1389 fEntityIsPE[chunk][index] == 0 ? false : true , 1390 fEntityInExternal[chunk][index] == 0 ? false : true ); 1391 1392 return true; 1393 } // getEntityDecl 1394 1395 /** 1396 * getNotationDeclIndex 1397 * 1398 * @param notationDeclName 1399 * 1400 * @return the index if found a notation with the name, otherwise -1. 1401 */ 1402 public int getNotationDeclIndex(String notationDeclName) { 1403 if (notationDeclName == null || fNotationIndexMap.get(notationDeclName) == null) { 1404 return -1; 1405 } 1406 1407 return fNotationIndexMap.get(notationDeclName); 1408 } // getNotationDeclIndex 1409 1410 /** 1411 * getNotationDecl 1412 * 1413 * @param notationDeclIndex 1414 * @param notationDecl 1415 * 1416 * @return return true of getNotationDecl can fill notationDecl with information about 1417 * the notation at notationDeclIndex. 1418 */ 1419 public boolean getNotationDecl(int notationDeclIndex, XMLNotationDecl notationDecl) { 1420 if (notationDeclIndex < 0 || notationDeclIndex >= fNotationCount) { 1421 return false; 1422 } 1423 int chunk = notationDeclIndex >> CHUNK_SHIFT; 1424 int index = notationDeclIndex & CHUNK_MASK; 1425 1426 notationDecl.setValues(fNotationName[chunk][index], 1427 fNotationPublicId[chunk][index], 1428 fNotationSystemId[chunk][index], 1429 fNotationBaseSystemId[chunk][index]); 1430 1431 return true; 1432 1433 } // getNotationDecl 1434 1435 /** 1436 * getContentSpec 1437 * 1438 * @param contentSpecIndex 1439 * @param contentSpec 1440 * 1441 * @return true if find the requested contentSpec node, false otherwise 1442 */ 1443 public boolean getContentSpec(int contentSpecIndex, XMLContentSpec contentSpec) { 1444 if (contentSpecIndex < 0 || contentSpecIndex >= fContentSpecCount ) 1445 return false; 1446 1447 int chunk = contentSpecIndex >> CHUNK_SHIFT; 1448 int index = contentSpecIndex & CHUNK_MASK; 1449 1450 contentSpec.type = fContentSpecType[chunk][index]; 1451 contentSpec.value = fContentSpecValue[chunk][index]; 1452 contentSpec.otherValue = fContentSpecOtherValue[chunk][index]; 1453 return true; 1454 } 1455 1456 /** 1457 * Returns the index to the content spec for the given element 1458 * declaration, or <code>-1</code> if the element declaration 1459 * index was invalid. 1460 */ 1461 public int getContentSpecIndex(int elementDeclIndex) { 1462 if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) { 1463 return -1; 1464 } 1465 final int chunk = elementDeclIndex >> CHUNK_SHIFT; 1466 final int index = elementDeclIndex & CHUNK_MASK; 1467 return fElementDeclContentSpecIndex[chunk][index]; 1468 } 1469 1470 /** 1471 * getContentSpecAsString 1472 * 1473 * @param elementDeclIndex 1474 * 1475 * @return String 1476 */ 1477 public String getContentSpecAsString(int elementDeclIndex){ 1478 1479 if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) { 1480 return null; 1481 } 1482 1483 int chunk = elementDeclIndex >> CHUNK_SHIFT; 1484 int index = elementDeclIndex & CHUNK_MASK; 1485 1486 int contentSpecIndex = fElementDeclContentSpecIndex[chunk][index]; 1487 1488 // lookup content spec node 1489 XMLContentSpec contentSpec = new XMLContentSpec(); 1490 1491 if (getContentSpec(contentSpecIndex, contentSpec)) { 1492 1493 // build string 1494 StringBuffer str = new StringBuffer(); 1495 int parentContentSpecType = contentSpec.type & 0x0f; 1496 int nextContentSpec; 1497 switch (parentContentSpecType) { 1498 case XMLContentSpec.CONTENTSPECNODE_LEAF: { 1499 str.append('('); 1500 if (contentSpec.value == null && contentSpec.otherValue == null) { 1501 str.append("#PCDATA"); 1502 } 1503 else { 1504 str.append(contentSpec.value); 1505 } 1506 str.append(')'); 1507 break; 1508 } 1509 case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE: { 1510 getContentSpec(((int[])contentSpec.value)[0], contentSpec); 1511 nextContentSpec = contentSpec.type; 1512 1513 if (nextContentSpec == XMLContentSpec.CONTENTSPECNODE_LEAF) { 1514 str.append('('); 1515 str.append(contentSpec.value); 1516 str.append(')'); 1517 } else if( nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE || 1518 nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE || 1519 nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) { 1520 str.append('(' ); 1521 appendContentSpec(contentSpec, str, 1522 true, parentContentSpecType ); 1523 str.append(')'); 1524 } else { 1525 appendContentSpec(contentSpec, str, 1526 true, parentContentSpecType ); 1527 } 1528 str.append('?'); 1529 break; 1530 } 1531 case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE: { 1532 getContentSpec(((int[])contentSpec.value)[0], contentSpec); 1533 nextContentSpec = contentSpec.type; 1534 1535 if ( nextContentSpec == XMLContentSpec.CONTENTSPECNODE_LEAF) { 1536 str.append('('); 1537 if (contentSpec.value == null && contentSpec.otherValue == null) { 1538 str.append("#PCDATA"); 1539 } 1540 else if (contentSpec.otherValue != null) { 1541 str.append("##any:uri=").append(contentSpec.otherValue); 1542 } 1543 else if (contentSpec.value == null) { 1544 str.append("##any"); 1545 } 1546 else { 1547 appendContentSpec(contentSpec, str, 1548 true, parentContentSpecType ); 1549 } 1550 str.append(')'); 1551 } else if( nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE || 1552 nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE || 1553 nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) { 1554 str.append('(' ); 1555 appendContentSpec(contentSpec, str, 1556 true, parentContentSpecType ); 1557 str.append(')'); 1558 } else { 1559 appendContentSpec(contentSpec, str, 1560 true, parentContentSpecType ); 1561 } 1562 str.append('*'); 1563 break; 1564 } 1565 case XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE: { 1566 getContentSpec(((int[])contentSpec.value)[0], contentSpec); 1567 nextContentSpec = contentSpec.type; 1568 1569 if ( nextContentSpec == XMLContentSpec.CONTENTSPECNODE_LEAF) { 1570 str.append('('); 1571 if (contentSpec.value == null && contentSpec.otherValue == null) { 1572 str.append("#PCDATA"); 1573 } 1574 else if (contentSpec.otherValue != null) { 1575 str.append("##any:uri=").append(contentSpec.otherValue); 1576 } 1577 else if (contentSpec.value == null) { 1578 str.append("##any"); 1579 } 1580 else { 1581 str.append(contentSpec.value); 1582 } 1583 str.append(')'); 1584 } else if( nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE || 1585 nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE || 1586 nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) { 1587 str.append('(' ); 1588 appendContentSpec(contentSpec, str, 1589 true, parentContentSpecType ); 1590 str.append(')'); 1591 } else { 1592 appendContentSpec(contentSpec, str, 1593 true, parentContentSpecType); 1594 } 1595 str.append('+'); 1596 break; 1597 } 1598 case XMLContentSpec.CONTENTSPECNODE_CHOICE: 1599 case XMLContentSpec.CONTENTSPECNODE_SEQ: { 1600 appendContentSpec(contentSpec, str, 1601 true, parentContentSpecType ); 1602 break; 1603 } 1604 case XMLContentSpec.CONTENTSPECNODE_ANY: { 1605 str.append("##any"); 1606 if (contentSpec.otherValue != null) { 1607 str.append(":uri="); 1608 str.append(contentSpec.otherValue); 1609 } 1610 break; 1611 } 1612 case XMLContentSpec.CONTENTSPECNODE_ANY_OTHER: { 1613 str.append("##other:uri="); 1614 str.append(contentSpec.otherValue); 1615 break; 1616 } 1617 case XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL: { 1618 str.append("##local"); 1619 break; 1620 } 1621 default: { 1622 str.append("???"); 1623 } 1624 1625 } // switch type 1626 1627 // return string 1628 return str.toString(); 1629 } 1630 1631 // not found 1632 return null; 1633 1634 } // getContentSpecAsString(int):String 1635 1636 // debugging 1637 1638 public void printElements( ) { 1639 int elementDeclIndex = 0; 1640 XMLElementDecl elementDecl = new XMLElementDecl(); 1641 while (getElementDecl(elementDeclIndex++, elementDecl)) { 1642 1643 System.out.println("element decl: "+elementDecl.name+ 1644 ", "+ elementDecl.name.rawname ); 1645 1646 // ", "+ elementDecl.contentModelValidator.toString()); 1647 } 1648 } 1649 1650 public void printAttributes(int elementDeclIndex) { 1651 int attributeDeclIndex = getFirstAttributeDeclIndex(elementDeclIndex); 1652 System.out.print(elementDeclIndex); 1653 System.out.print(" ["); 1654 while (attributeDeclIndex != -1) { 1655 System.out.print(' '); 1656 System.out.print(attributeDeclIndex); 1657 printAttribute(attributeDeclIndex); 1658 attributeDeclIndex = getNextAttributeDeclIndex(attributeDeclIndex); 1659 if (attributeDeclIndex != -1) { 1660 System.out.print(","); 1661 } 1662 } 1663 System.out.println(" ]"); 1664 } 1665 1666 // 1667 // Protected methods 1668 // 1669 1670 /** 1671 * Adds the content spec to the given element declaration. 1672 */ 1673 protected void addContentSpecToElement(XMLElementDecl elementDecl) { 1674 if ((fDepth == 0 || (fDepth == 1 && elementDecl.type == XMLElementDecl.TYPE_MIXED)) && 1675 fNodeIndexStack != null) { 1676 if (elementDecl.type == XMLElementDecl.TYPE_MIXED) { 1677 int pcdata = addUniqueLeafNode(null); 1678 if (fNodeIndexStack[0] == -1) { 1679 fNodeIndexStack[0] = pcdata; 1680 } 1681 else { 1682 fNodeIndexStack[0] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_CHOICE, 1683 pcdata, fNodeIndexStack[0]); 1684 } 1685 } 1686 setContentSpecIndex(fCurrentElementIndex, fNodeIndexStack[fDepth]); 1687 } 1688 } 1689 1690 /** 1691 * getElementContentModelValidator 1692 * 1693 * @param elementDeclIndex 1694 * 1695 * @return its ContentModelValidator if any. 1696 */ 1697 protected ContentModelValidator getElementContentModelValidator(int elementDeclIndex) { 1698 1699 int chunk = elementDeclIndex >> CHUNK_SHIFT; 1700 int index = elementDeclIndex & CHUNK_MASK; 1701 1702 ContentModelValidator contentModel = fElementDeclContentModelValidator[chunk][index]; 1703 1704 // If we have one, just return that. Otherwise, gotta create one 1705 if (contentModel != null) { 1706 return contentModel; 1707 } 1708 1709 int contentType = fElementDeclType[chunk][index]; 1710 if (contentType == XMLElementDecl.TYPE_SIMPLE) { 1711 return null; 1712 } 1713 1714 // Get the type of content this element has 1715 int contentSpecIndex = fElementDeclContentSpecIndex[chunk][index]; 1716 1717 /*** 1718 if ( contentSpecIndex == -1 ) 1719 return null; 1720 /***/ 1721 1722 XMLContentSpec contentSpec = new XMLContentSpec(); 1723 getContentSpec( contentSpecIndex, contentSpec ); 1724 1725 // And create the content model according to the spec type 1726 if ( contentType == XMLElementDecl.TYPE_MIXED ) { 1727 // 1728 // Just create a mixel content model object. This type of 1729 // content model is optimized for mixed content validation. 1730 // 1731 ChildrenList children = new ChildrenList(); 1732 contentSpecTree(contentSpecIndex, contentSpec, children); 1733 contentModel = new MixedContentModel(children.qname, 1734 children.type, 1735 0, children.length, 1736 false); 1737 } else if (contentType == XMLElementDecl.TYPE_CHILDREN) { 1738 // This method will create an optimal model for the complexity 1739 // of the element's defined model. If its simple, it will create 1740 // a SimpleContentModel object. If its a simple list, it will 1741 // create a SimpleListContentModel object. If its complex, it 1742 // will create a DFAContentModel object. 1743 // 1744 contentModel = createChildModel(contentSpecIndex); 1745 } else { 1746 throw new RuntimeException("Unknown content type for a element decl " 1747 + "in getElementContentModelValidator() in AbstractDTDGrammar class"); 1748 } 1749 1750 // Add the new model to the content model for this element 1751 fElementDeclContentModelValidator[chunk][index] = contentModel; 1752 1753 return contentModel; 1754 1755 } // getElementContentModelValidator(int):ContentModelValidator 1756 1757 protected int createElementDecl() { 1758 int chunk = fElementDeclCount >> CHUNK_SHIFT; 1759 int index = fElementDeclCount & CHUNK_MASK; 1760 ensureElementDeclCapacity(chunk); 1761 fElementDeclName[chunk][index] = new QName(); 1762 fElementDeclType[chunk][index] = -1; 1763 fElementDeclContentModelValidator[chunk][index] = null; 1764 fElementDeclFirstAttributeDeclIndex[chunk][index] = -1; 1765 fElementDeclLastAttributeDeclIndex[chunk][index] = -1; 1766 return fElementDeclCount++; 1767 } 1768 1769 protected void setElementDecl(int elementDeclIndex, XMLElementDecl elementDecl) { 1770 if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) { 1771 return; 1772 } 1773 int chunk = elementDeclIndex >> CHUNK_SHIFT; 1774 int index = elementDeclIndex & CHUNK_MASK; 1775 1776 fElementDeclName[chunk][index].setValues(elementDecl.name); 1777 fElementDeclType[chunk][index] = elementDecl.type; 1778 1779 fElementDeclContentModelValidator[chunk][index] = elementDecl.contentModelValidator; 1780 1781 if (elementDecl.simpleType.list == true ) { 1782 fElementDeclType[chunk][index] |= LIST_FLAG; 1783 } 1784 1785 fElementIndexMap.put(elementDecl.name.rawname, elementDeclIndex); 1786 } 1787 1788 1789 1790 1791 protected void putElementNameMapping(QName name, int scope, 1792 int elementDeclIndex) { 1793 } 1794 1795 protected void setFirstAttributeDeclIndex(int elementDeclIndex, int newFirstAttrIndex){ 1796 1797 if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) { 1798 return; 1799 } 1800 1801 int chunk = elementDeclIndex >> CHUNK_SHIFT; 1802 int index = elementDeclIndex & CHUNK_MASK; 1803 1804 fElementDeclFirstAttributeDeclIndex[chunk][index] = newFirstAttrIndex; 1805 } 1806 1807 protected void setContentSpecIndex(int elementDeclIndex, int contentSpecIndex){ 1808 1809 if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) { 1810 return; 1811 } 1812 1813 int chunk = elementDeclIndex >> CHUNK_SHIFT; 1814 int index = elementDeclIndex & CHUNK_MASK; 1815 1816 fElementDeclContentSpecIndex[chunk][index] = contentSpecIndex; 1817 } 1818 1819 1820 protected int createAttributeDecl() { 1821 int chunk = fAttributeDeclCount >> CHUNK_SHIFT; 1822 int index = fAttributeDeclCount & CHUNK_MASK; 1823 1824 ensureAttributeDeclCapacity(chunk); 1825 fAttributeDeclName[chunk][index] = new QName(); 1826 fAttributeDeclType[chunk][index] = -1; 1827 fAttributeDeclDatatypeValidator[chunk][index] = null; 1828 fAttributeDeclEnumeration[chunk][index] = null; 1829 fAttributeDeclDefaultType[chunk][index] = XMLSimpleType.DEFAULT_TYPE_IMPLIED; 1830 fAttributeDeclDefaultValue[chunk][index] = null; 1831 fAttributeDeclNonNormalizedDefaultValue[chunk][index] = null; 1832 fAttributeDeclNextAttributeDeclIndex[chunk][index] = -1; 1833 return fAttributeDeclCount++; 1834 } 1835 1836 1837 protected void setAttributeDecl(int elementDeclIndex, int attributeDeclIndex, 1838 XMLAttributeDecl attributeDecl) { 1839 int attrChunk = attributeDeclIndex >> CHUNK_SHIFT; 1840 int attrIndex = attributeDeclIndex & CHUNK_MASK; 1841 fAttributeDeclName[attrChunk][attrIndex].setValues(attributeDecl.name); 1842 fAttributeDeclType[attrChunk][attrIndex] = attributeDecl.simpleType.type; 1843 1844 if (attributeDecl.simpleType.list) { 1845 fAttributeDeclType[attrChunk][attrIndex] |= LIST_FLAG; 1846 } 1847 fAttributeDeclEnumeration[attrChunk][attrIndex] = attributeDecl.simpleType.enumeration; 1848 fAttributeDeclDefaultType[attrChunk][attrIndex] = attributeDecl.simpleType.defaultType; 1849 fAttributeDeclDatatypeValidator[attrChunk][attrIndex] = attributeDecl.simpleType.datatypeValidator; 1850 1851 fAttributeDeclDefaultValue[attrChunk][attrIndex] = attributeDecl.simpleType.defaultValue; 1852 fAttributeDeclNonNormalizedDefaultValue[attrChunk][attrIndex] = attributeDecl.simpleType.nonNormalizedDefaultValue; 1853 1854 int elemChunk = elementDeclIndex >> CHUNK_SHIFT; 1855 int elemIndex = elementDeclIndex & CHUNK_MASK; 1856 int index = fElementDeclFirstAttributeDeclIndex[elemChunk][elemIndex]; 1857 while (index != -1) { 1858 if (index == attributeDeclIndex) { 1859 break; 1860 } 1861 attrChunk = index >> CHUNK_SHIFT; 1862 attrIndex = index & CHUNK_MASK; 1863 index = fAttributeDeclNextAttributeDeclIndex[attrChunk][attrIndex]; 1864 } 1865 if (index == -1) { 1866 if (fElementDeclFirstAttributeDeclIndex[elemChunk][elemIndex] == -1) { 1867 fElementDeclFirstAttributeDeclIndex[elemChunk][elemIndex] = attributeDeclIndex; 1868 } else { 1869 index = fElementDeclLastAttributeDeclIndex[elemChunk][elemIndex]; 1870 attrChunk = index >> CHUNK_SHIFT; 1871 attrIndex = index & CHUNK_MASK; 1872 fAttributeDeclNextAttributeDeclIndex[attrChunk][attrIndex] = attributeDeclIndex; 1873 } 1874 fElementDeclLastAttributeDeclIndex[elemChunk][elemIndex] = attributeDeclIndex; 1875 } 1876 } 1877 1878 protected int createContentSpec() { 1879 int chunk = fContentSpecCount >> CHUNK_SHIFT; 1880 int index = fContentSpecCount & CHUNK_MASK; 1881 1882 ensureContentSpecCapacity(chunk); 1883 fContentSpecType[chunk][index] = -1; 1884 fContentSpecValue[chunk][index] = null; 1885 fContentSpecOtherValue[chunk][index] = null; 1886 1887 return fContentSpecCount++; 1888 } 1889 1890 protected void setContentSpec(int contentSpecIndex, XMLContentSpec contentSpec) { 1891 int chunk = contentSpecIndex >> CHUNK_SHIFT; 1892 int index = contentSpecIndex & CHUNK_MASK; 1893 1894 fContentSpecType[chunk][index] = contentSpec.type; 1895 fContentSpecValue[chunk][index] = contentSpec.value; 1896 fContentSpecOtherValue[chunk][index] = contentSpec.otherValue; 1897 } 1898 1899 1900 protected int createEntityDecl() { 1901 int chunk = fEntityCount >> CHUNK_SHIFT; 1902 int index = fEntityCount & CHUNK_MASK; 1903 1904 ensureEntityDeclCapacity(chunk); 1905 fEntityIsPE[chunk][index] = 0; 1906 fEntityInExternal[chunk][index] = 0; 1907 1908 return fEntityCount++; 1909 } 1910 1911 protected void setEntityDecl(int entityDeclIndex, XMLEntityDecl entityDecl) { 1912 int chunk = entityDeclIndex >> CHUNK_SHIFT; 1913 int index = entityDeclIndex & CHUNK_MASK; 1914 1915 fEntityName[chunk][index] = entityDecl.name; 1916 fEntityValue[chunk][index] = entityDecl.value; 1917 fEntityPublicId[chunk][index] = entityDecl.publicId; 1918 fEntitySystemId[chunk][index] = entityDecl.systemId; 1919 fEntityBaseSystemId[chunk][index] = entityDecl.baseSystemId; 1920 fEntityNotation[chunk][index] = entityDecl.notation; 1921 fEntityIsPE[chunk][index] = entityDecl.isPE ? (byte)1 : (byte)0; 1922 fEntityInExternal[chunk][index] = entityDecl.inExternal ? (byte)1 : (byte)0; 1923 1924 fEntityIndexMap.put(entityDecl.name, entityDeclIndex); 1925 } 1926 1927 protected int createNotationDecl() { 1928 int chunk = fNotationCount >> CHUNK_SHIFT; 1929 ensureNotationDeclCapacity(chunk); 1930 return fNotationCount++; 1931 } 1932 1933 protected void setNotationDecl(int notationDeclIndex, XMLNotationDecl notationDecl) { 1934 int chunk = notationDeclIndex >> CHUNK_SHIFT; 1935 int index = notationDeclIndex & CHUNK_MASK; 1936 1937 fNotationName[chunk][index] = notationDecl.name; 1938 fNotationPublicId[chunk][index] = notationDecl.publicId; 1939 fNotationSystemId[chunk][index] = notationDecl.systemId; 1940 fNotationBaseSystemId[chunk][index] = notationDecl.baseSystemId; 1941 1942 fNotationIndexMap.put(notationDecl.name, notationDeclIndex); 1943 } 1944 1945 /** 1946 * Create an XMLContentSpec for a single non-leaf 1947 * 1948 * @param nodeType the type of XMLContentSpec to create - from XMLContentSpec.CONTENTSPECNODE_* 1949 * @param nodeValue handle to an XMLContentSpec 1950 * @return handle to the newly create XMLContentSpec 1951 */ 1952 protected int addContentSpecNode(short nodeType, String nodeValue) { 1953 1954 // create content spec node 1955 int contentSpecIndex = createContentSpec(); 1956 1957 // set content spec node values 1958 fContentSpec.setValues(nodeType, nodeValue, null); 1959 setContentSpec(contentSpecIndex, fContentSpec); 1960 1961 // return index 1962 return contentSpecIndex; 1963 1964 } // addContentSpecNode(short,String):int 1965 1966 /** 1967 * create an XMLContentSpec for a leaf 1968 * 1969 * @param elementName the name (Element) for the node 1970 * @return handle to the newly create XMLContentSpec 1971 */ 1972 protected int addUniqueLeafNode(String elementName) { 1973 1974 // create content spec node 1975 int contentSpecIndex = createContentSpec(); 1976 1977 // set content spec node values 1978 fContentSpec.setValues( XMLContentSpec.CONTENTSPECNODE_LEAF, 1979 elementName, null); 1980 setContentSpec(contentSpecIndex, fContentSpec); 1981 1982 // return index 1983 return contentSpecIndex; 1984 1985 } // addUniqueLeafNode(String):int 1986 1987 /** 1988 * Create an XMLContentSpec for a two child leaf 1989 * 1990 * @param nodeType the type of XMLContentSpec to create - from XMLContentSpec.CONTENTSPECNODE_* 1991 * @param leftNodeIndex handle to an XMLContentSpec 1992 * @param rightNodeIndex handle to an XMLContentSpec 1993 * @return handle to the newly create XMLContentSpec 1994 */ 1995 protected int addContentSpecNode(short nodeType, 1996 int leftNodeIndex, int rightNodeIndex) { 1997 1998 // create content spec node 1999 int contentSpecIndex = createContentSpec(); 2000 2001 // set content spec node values 2002 int[] leftIntArray = new int[1]; 2003 int[] rightIntArray = new int[1]; 2004 2005 leftIntArray[0] = leftNodeIndex; 2006 rightIntArray[0] = rightNodeIndex; 2007 fContentSpec.setValues(nodeType, leftIntArray, rightIntArray); 2008 setContentSpec(contentSpecIndex, fContentSpec); 2009 2010 // return index 2011 return contentSpecIndex; 2012 2013 } // addContentSpecNode(short,int,int):int 2014 2015 /** Initialize content model stack. */ 2016 protected void initializeContentModelStack() { 2017 2018 if (fOpStack == null) { 2019 fOpStack = new short[8]; 2020 fNodeIndexStack = new int[8]; 2021 fPrevNodeIndexStack = new int[8]; 2022 } else if (fDepth == fOpStack.length) { 2023 short[] newStack = new short[fDepth * 2]; 2024 System.arraycopy(fOpStack, 0, newStack, 0, fDepth); 2025 fOpStack = newStack; 2026 int[] newIntStack = new int[fDepth * 2]; 2027 System.arraycopy(fNodeIndexStack, 0, newIntStack, 0, fDepth); 2028 fNodeIndexStack = newIntStack; 2029 newIntStack = new int[fDepth * 2]; 2030 System.arraycopy(fPrevNodeIndexStack, 0, newIntStack, 0, fDepth); 2031 fPrevNodeIndexStack = newIntStack; 2032 } 2033 fOpStack[fDepth] = -1; 2034 fNodeIndexStack[fDepth] = -1; 2035 fPrevNodeIndexStack[fDepth] = -1; 2036 2037 } // initializeContentModelStack() 2038 2039 boolean isImmutable() { 2040 return fIsImmutable; 2041 } 2042 2043 // 2044 // Private methods 2045 // 2046 2047 private void appendContentSpec(XMLContentSpec contentSpec, 2048 StringBuffer str, boolean parens, 2049 int parentContentSpecType ) { 2050 2051 int thisContentSpec = contentSpec.type & 0x0f; 2052 switch (thisContentSpec) { 2053 case XMLContentSpec.CONTENTSPECNODE_LEAF: { 2054 if (contentSpec.value == null && contentSpec.otherValue == null) { 2055 str.append("#PCDATA"); 2056 } 2057 else if (contentSpec.value == null && contentSpec.otherValue != null) { 2058 str.append("##any:uri=").append(contentSpec.otherValue); 2059 } 2060 else if (contentSpec.value == null) { 2061 str.append("##any"); 2062 } 2063 else { 2064 str.append(contentSpec.value); 2065 } 2066 break; 2067 } 2068 case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE: { 2069 if (parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE || 2070 parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE || 2071 parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) { 2072 getContentSpec(((int[])contentSpec.value)[0], contentSpec); 2073 str.append('('); 2074 appendContentSpec(contentSpec, str, true, thisContentSpec ); 2075 str.append(')'); 2076 } 2077 else { 2078 getContentSpec(((int[])contentSpec.value)[0], contentSpec); 2079 appendContentSpec( contentSpec, str, true, thisContentSpec ); 2080 } 2081 str.append('?'); 2082 break; 2083 } 2084 case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE: { 2085 if (parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE || 2086 parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE || 2087 parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) { 2088 getContentSpec(((int[])contentSpec.value)[0], contentSpec); 2089 str.append('('); 2090 appendContentSpec(contentSpec, str, true, thisContentSpec); 2091 str.append(')' ); 2092 } 2093 else { 2094 getContentSpec(((int[])contentSpec.value)[0], contentSpec); 2095 appendContentSpec(contentSpec, str, true, thisContentSpec); 2096 } 2097 str.append('*'); 2098 break; 2099 } 2100 case XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE: { 2101 if (parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE || 2102 parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE || 2103 parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) { 2104 2105 str.append('('); 2106 getContentSpec(((int[])contentSpec.value)[0], contentSpec); 2107 appendContentSpec(contentSpec, str, true, thisContentSpec); 2108 str.append(')' ); 2109 } 2110 else { 2111 getContentSpec(((int[])contentSpec.value)[0], contentSpec); 2112 appendContentSpec(contentSpec, str, true, thisContentSpec); 2113 } 2114 str.append('+'); 2115 break; 2116 } 2117 case XMLContentSpec.CONTENTSPECNODE_CHOICE: 2118 case XMLContentSpec.CONTENTSPECNODE_SEQ: { 2119 if (parens) { 2120 str.append('('); 2121 } 2122 int type = contentSpec.type; 2123 int otherValue = ((int[])contentSpec.otherValue)[0]; 2124 getContentSpec(((int[])contentSpec.value)[0], contentSpec); 2125 appendContentSpec(contentSpec, str, contentSpec.type != type, thisContentSpec); 2126 if (type == XMLContentSpec.CONTENTSPECNODE_CHOICE) { 2127 str.append('|'); 2128 } 2129 else { 2130 str.append(','); 2131 } 2132 getContentSpec(otherValue, contentSpec); 2133 appendContentSpec(contentSpec, str, true, thisContentSpec); 2134 if (parens) { 2135 str.append(')'); 2136 } 2137 break; 2138 } 2139 case XMLContentSpec.CONTENTSPECNODE_ANY: { 2140 str.append("##any"); 2141 if (contentSpec.otherValue != null) { 2142 str.append(":uri="); 2143 str.append(contentSpec.otherValue); 2144 } 2145 break; 2146 } 2147 case XMLContentSpec.CONTENTSPECNODE_ANY_OTHER: { 2148 str.append("##other:uri="); 2149 str.append(contentSpec.otherValue); 2150 break; 2151 } 2152 case XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL: { 2153 str.append("##local"); 2154 break; 2155 } 2156 default: { 2157 str.append("???"); 2158 break; 2159 } 2160 2161 } // switch type 2162 2163 } // appendContentSpec(XMLContentSpec.Provider,StringPool,XMLContentSpec,StringBuffer,boolean) 2164 2165 // debugging 2166 2167 private void printAttribute(int attributeDeclIndex) { 2168 2169 XMLAttributeDecl attributeDecl = new XMLAttributeDecl(); 2170 if (getAttributeDecl(attributeDeclIndex, attributeDecl)) { 2171 System.out.print(" { "); 2172 System.out.print(attributeDecl.name.localpart); 2173 System.out.print(" }"); 2174 } 2175 2176 } // printAttribute(int) 2177 2178 // content models 2179 2180 /** 2181 * When the element has a 'CHILDREN' model, this method is called to 2182 * create the content model object. It looks for some special case simple 2183 * models and creates SimpleContentModel objects for those. For the rest 2184 * it creates the standard DFA style model. 2185 */ 2186 private synchronized ContentModelValidator createChildModel(int contentSpecIndex) { 2187 2188 // 2189 // Get the content spec node for the element we are working on. 2190 // This will tell us what kind of node it is, which tells us what 2191 // kind of model we will try to create. 2192 // 2193 XMLContentSpec contentSpec = new XMLContentSpec(); 2194 getContentSpec(contentSpecIndex, contentSpec); 2195 2196 if ((contentSpec.type & 0x0f ) == XMLContentSpec.CONTENTSPECNODE_ANY || 2197 (contentSpec.type & 0x0f ) == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER || 2198 (contentSpec.type & 0x0f ) == XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL) { 2199 // let fall through to build a DFAContentModel 2200 } 2201 2202 else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_LEAF) { 2203 // 2204 // Check that the left value is not -1, since any content model 2205 // with PCDATA should be MIXED, so we should not have gotten here. 2206 // 2207 if (contentSpec.value == null && contentSpec.otherValue == null) 2208 throw new RuntimeException("ImplementationMessages.VAL_NPCD"); 2209 2210 // 2211 // Its a single leaf, so its an 'a' type of content model, i.e. 2212 // just one instance of one element. That one is definitely a 2213 // simple content model. 2214 // 2215 2216 fQName.setValues(null, (String)contentSpec.value, 2217 (String)contentSpec.value, (String)contentSpec.otherValue); 2218 return new SimpleContentModel(contentSpec.type, fQName, null); 2219 } else if ((contentSpec.type == XMLContentSpec.CONTENTSPECNODE_CHOICE) 2220 || (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_SEQ)) { 2221 // 2222 // Lets see if both of the children are leafs. If so, then it 2223 // it has to be a simple content model 2224 // 2225 XMLContentSpec contentSpecLeft = new XMLContentSpec(); 2226 XMLContentSpec contentSpecRight = new XMLContentSpec(); 2227 2228 getContentSpec( ((int[])contentSpec.value)[0], contentSpecLeft); 2229 getContentSpec( ((int[])contentSpec.otherValue)[0], contentSpecRight); 2230 2231 if ((contentSpecLeft.type == XMLContentSpec.CONTENTSPECNODE_LEAF) 2232 && (contentSpecRight.type == XMLContentSpec.CONTENTSPECNODE_LEAF)) { 2233 // 2234 // Its a simple choice or sequence, so we can do a simple 2235 // content model for it. 2236 // 2237 fQName.setValues(null, (String)contentSpecLeft.value, 2238 (String)contentSpecLeft.value, (String)contentSpecLeft.otherValue); 2239 fQName2.setValues(null, (String)contentSpecRight.value, 2240 (String)contentSpecRight.value, (String)contentSpecRight.otherValue); 2241 return new SimpleContentModel(contentSpec.type, fQName, fQName2); 2242 } 2243 } else if ((contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE) 2244 || (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE) 2245 || (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE)) { 2246 // 2247 // Its a repetition, so see if its one child is a leaf. If so 2248 // its a repetition of a single element, so we can do a simple 2249 // content model for that. 2250 // 2251 XMLContentSpec contentSpecLeft = new XMLContentSpec(); 2252 getContentSpec(((int[])contentSpec.value)[0], contentSpecLeft); 2253 2254 if (contentSpecLeft.type == XMLContentSpec.CONTENTSPECNODE_LEAF) { 2255 // 2256 // It is, so we can create a simple content model here that 2257 // will check for this repetition. We pass -1 for the unused 2258 // right node. 2259 // 2260 fQName.setValues(null, (String)contentSpecLeft.value, 2261 (String)contentSpecLeft.value, (String)contentSpecLeft.otherValue); 2262 return new SimpleContentModel(contentSpec.type, fQName, null); 2263 } 2264 } else { 2265 throw new RuntimeException("ImplementationMessages.VAL_CST"); 2266 } 2267 2268 // 2269 // Its not a simple content model, so here we have to create a DFA 2270 // for this element. So we create a DFAContentModel object. He 2271 // encapsulates all of the work to create the DFA. 2272 // 2273 2274 fLeafCount = 0; 2275 //int leafCount = countLeaves(contentSpecIndex); 2276 fLeafCount = 0; 2277 CMNode cmn = buildSyntaxTree(contentSpecIndex, contentSpec); 2278 2279 // REVISIT: has to be fLeafCount because we convert x+ to x,x*, one more leaf 2280 return new DFAContentModel( cmn, fLeafCount, false); 2281 2282 } // createChildModel(int):ContentModelValidator 2283 2284 private final CMNode buildSyntaxTree(int startNode, 2285 XMLContentSpec contentSpec) { 2286 2287 // We will build a node at this level for the new tree 2288 CMNode nodeRet = null; 2289 getContentSpec(startNode, contentSpec); 2290 if ((contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY) { 2291 //nodeRet = new CMAny(contentSpec.type, -1, fLeafCount++); 2292 nodeRet = new CMAny(contentSpec.type, (String)contentSpec.otherValue, fLeafCount++); 2293 } 2294 else if ((contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER) { 2295 nodeRet = new CMAny(contentSpec.type, (String)contentSpec.otherValue, fLeafCount++); 2296 } 2297 else if ((contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL) { 2298 nodeRet = new CMAny(contentSpec.type, null, fLeafCount++); 2299 } 2300 // 2301 // If this node is a leaf, then its an easy one. We just add it 2302 // to the tree. 2303 // 2304 else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_LEAF) { 2305 // 2306 // Create a new leaf node, and pass it the current leaf count, 2307 // which is its DFA state position. Bump the leaf count after 2308 // storing it. This makes the positions zero based since we 2309 // store first and then increment. 2310 // 2311 fQName.setValues(null, (String)contentSpec.value, 2312 (String)contentSpec.value, (String)contentSpec.otherValue); 2313 nodeRet = new CMLeaf(fQName, fLeafCount++); 2314 } 2315 else { 2316 // 2317 // Its not a leaf, so we have to recurse its left and maybe right 2318 // nodes. Save both values before we recurse and trash the node. 2319 final int leftNode = ((int[])contentSpec.value)[0]; 2320 final int rightNode = ((int[])contentSpec.otherValue)[0]; 2321 2322 if ((contentSpec.type == XMLContentSpec.CONTENTSPECNODE_CHOICE) 2323 || (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_SEQ)) { 2324 // 2325 // Recurse on both children, and return a binary op node 2326 // with the two created sub nodes as its children. The node 2327 // type is the same type as the source. 2328 // 2329 2330 nodeRet = new CMBinOp( contentSpec.type, buildSyntaxTree(leftNode, contentSpec) 2331 , buildSyntaxTree(rightNode, contentSpec)); 2332 } 2333 else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE) { 2334 nodeRet = new CMUniOp( contentSpec.type, buildSyntaxTree(leftNode, contentSpec)); 2335 } 2336 else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE 2337 || contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE 2338 || contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE) { 2339 nodeRet = new CMUniOp(contentSpec.type, buildSyntaxTree(leftNode, contentSpec)); 2340 } 2341 else { 2342 throw new RuntimeException("ImplementationMessages.VAL_CST"); 2343 } 2344 } 2345 // And return our new node for this level 2346 return nodeRet; 2347 } 2348 2349 /** 2350 * Build a vector of valid QNames from Content Spec 2351 * table. 2352 * 2353 * @param contentSpecIndex 2354 * Content Spec index 2355 * @param vectorQName 2356 * Array of QName 2357 * @exception RuntimeException 2358 */ 2359 private void contentSpecTree(int contentSpecIndex, 2360 XMLContentSpec contentSpec, 2361 ChildrenList children) { 2362 2363 // Handle any and leaf nodes 2364 getContentSpec( contentSpecIndex, contentSpec); 2365 if ( contentSpec.type == XMLContentSpec.CONTENTSPECNODE_LEAF || 2366 (contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY || 2367 (contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL || 2368 (contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER) { 2369 2370 // resize arrays, if needed 2371 if (children.length == children.qname.length) { 2372 QName[] newQName = new QName[children.length * 2]; 2373 System.arraycopy(children.qname, 0, newQName, 0, children.length); 2374 children.qname = newQName; 2375 int[] newType = new int[children.length * 2]; 2376 System.arraycopy(children.type, 0, newType, 0, children.length); 2377 children.type = newType; 2378 } 2379 2380 // save values and return length 2381 children.qname[children.length] = new QName(null, (String)contentSpec.value, 2382 (String) contentSpec.value, 2383 (String) contentSpec.otherValue); 2384 children.type[children.length] = contentSpec.type; 2385 children.length++; 2386 return; 2387 } 2388 2389 // 2390 // Its not a leaf, so we have to recurse its left and maybe right 2391 // nodes. Save both values before we recurse and trash the node. 2392 // 2393 final int leftNode = contentSpec.value != null 2394 ? ((int[])(contentSpec.value))[0] : -1; 2395 int rightNode = -1 ; 2396 if (contentSpec.otherValue != null ) 2397 rightNode = ((int[])(contentSpec.otherValue))[0]; 2398 else 2399 return; 2400 2401 if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_CHOICE || 2402 contentSpec.type == XMLContentSpec.CONTENTSPECNODE_SEQ) { 2403 contentSpecTree(leftNode, contentSpec, children); 2404 contentSpecTree(rightNode, contentSpec, children); 2405 return; 2406 } 2407 2408 if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE || 2409 contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE || 2410 contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE) { 2411 contentSpecTree(leftNode, contentSpec, children); 2412 return; 2413 } 2414 2415 // error 2416 throw new RuntimeException("Invalid content spec type seen in contentSpecTree() method of AbstractDTDGrammar class : "+contentSpec.type); 2417 2418 } // contentSpecTree(int,XMLContentSpec,ChildrenList) 2419 2420 // ensure capacity 2421 2422 private void ensureElementDeclCapacity(int chunk) { 2423 if (chunk >= fElementDeclName.length) { 2424 fElementDeclIsExternal = resize(fElementDeclIsExternal, 2425 fElementDeclIsExternal.length * 2); 2426 2427 fElementDeclName = resize(fElementDeclName, fElementDeclName.length * 2); 2428 fElementDeclType = resize(fElementDeclType, fElementDeclType.length * 2); 2429 fElementDeclContentModelValidator = resize(fElementDeclContentModelValidator, fElementDeclContentModelValidator.length * 2); 2430 fElementDeclContentSpecIndex = resize(fElementDeclContentSpecIndex,fElementDeclContentSpecIndex.length * 2); 2431 fElementDeclFirstAttributeDeclIndex = resize(fElementDeclFirstAttributeDeclIndex, fElementDeclFirstAttributeDeclIndex.length * 2); 2432 fElementDeclLastAttributeDeclIndex = resize(fElementDeclLastAttributeDeclIndex, fElementDeclLastAttributeDeclIndex.length * 2); 2433 } 2434 else if (fElementDeclName[chunk] != null) { 2435 return; 2436 } 2437 2438 fElementDeclIsExternal[chunk] = new int[CHUNK_SIZE]; 2439 fElementDeclName[chunk] = new QName[CHUNK_SIZE]; 2440 fElementDeclType[chunk] = new short[CHUNK_SIZE]; 2441 fElementDeclContentModelValidator[chunk] = new ContentModelValidator[CHUNK_SIZE]; 2442 fElementDeclContentSpecIndex[chunk] = new int[CHUNK_SIZE]; 2443 fElementDeclFirstAttributeDeclIndex[chunk] = new int[CHUNK_SIZE]; 2444 fElementDeclLastAttributeDeclIndex[chunk] = new int[CHUNK_SIZE]; 2445 return; 2446 } 2447 2448 private void ensureAttributeDeclCapacity(int chunk) { 2449 2450 if (chunk >= fAttributeDeclName.length) { 2451 fAttributeDeclIsExternal = resize(fAttributeDeclIsExternal, 2452 fAttributeDeclIsExternal.length * 2); 2453 fAttributeDeclName = resize(fAttributeDeclName, fAttributeDeclName.length * 2); 2454 fAttributeDeclType = resize(fAttributeDeclType, fAttributeDeclType.length * 2); 2455 fAttributeDeclEnumeration = resize(fAttributeDeclEnumeration, fAttributeDeclEnumeration.length * 2); 2456 fAttributeDeclDefaultType = resize(fAttributeDeclDefaultType, fAttributeDeclDefaultType.length * 2); 2457 fAttributeDeclDatatypeValidator = resize(fAttributeDeclDatatypeValidator, fAttributeDeclDatatypeValidator.length * 2); 2458 fAttributeDeclDefaultValue = resize(fAttributeDeclDefaultValue, fAttributeDeclDefaultValue.length * 2); 2459 fAttributeDeclNonNormalizedDefaultValue = resize(fAttributeDeclNonNormalizedDefaultValue, fAttributeDeclNonNormalizedDefaultValue.length * 2); 2460 fAttributeDeclNextAttributeDeclIndex = resize(fAttributeDeclNextAttributeDeclIndex, fAttributeDeclNextAttributeDeclIndex.length * 2); 2461 } 2462 else if (fAttributeDeclName[chunk] != null) { 2463 return; 2464 } 2465 2466 fAttributeDeclIsExternal[chunk] = new int[CHUNK_SIZE]; 2467 fAttributeDeclName[chunk] = new QName[CHUNK_SIZE]; 2468 fAttributeDeclType[chunk] = new short[CHUNK_SIZE]; 2469 fAttributeDeclEnumeration[chunk] = new String[CHUNK_SIZE][]; 2470 fAttributeDeclDefaultType[chunk] = new short[CHUNK_SIZE]; 2471 fAttributeDeclDatatypeValidator[chunk] = new DatatypeValidator[CHUNK_SIZE]; 2472 fAttributeDeclDefaultValue[chunk] = new String[CHUNK_SIZE]; 2473 fAttributeDeclNonNormalizedDefaultValue[chunk] = new String[CHUNK_SIZE]; 2474 fAttributeDeclNextAttributeDeclIndex[chunk] = new int[CHUNK_SIZE]; 2475 return; 2476 } 2477 2478 private void ensureEntityDeclCapacity(int chunk) { 2479 if (chunk >= fEntityName.length) { 2480 fEntityName = resize(fEntityName, fEntityName.length * 2); 2481 fEntityValue = resize(fEntityValue, fEntityValue.length * 2); 2482 fEntityPublicId = resize(fEntityPublicId, fEntityPublicId.length * 2); 2483 fEntitySystemId = resize(fEntitySystemId, fEntitySystemId.length * 2); 2484 fEntityBaseSystemId = resize(fEntityBaseSystemId, fEntityBaseSystemId.length * 2); 2485 fEntityNotation = resize(fEntityNotation, fEntityNotation.length * 2); 2486 fEntityIsPE = resize(fEntityIsPE, fEntityIsPE.length * 2); 2487 fEntityInExternal = resize(fEntityInExternal, fEntityInExternal.length * 2); 2488 } 2489 else if (fEntityName[chunk] != null) { 2490 return; 2491 } 2492 2493 fEntityName[chunk] = new String[CHUNK_SIZE]; 2494 fEntityValue[chunk] = new String[CHUNK_SIZE]; 2495 fEntityPublicId[chunk] = new String[CHUNK_SIZE]; 2496 fEntitySystemId[chunk] = new String[CHUNK_SIZE]; 2497 fEntityBaseSystemId[chunk] = new String[CHUNK_SIZE]; 2498 fEntityNotation[chunk] = new String[CHUNK_SIZE]; 2499 fEntityIsPE[chunk] = new byte[CHUNK_SIZE]; 2500 fEntityInExternal[chunk] = new byte[CHUNK_SIZE]; 2501 return; 2502 } 2503 2504 private void ensureNotationDeclCapacity(int chunk) { 2505 if (chunk >= fNotationName.length) { 2506 fNotationName = resize(fNotationName, fNotationName.length * 2); 2507 fNotationPublicId = resize(fNotationPublicId, fNotationPublicId.length * 2); 2508 fNotationSystemId = resize(fNotationSystemId, fNotationSystemId.length * 2); 2509 fNotationBaseSystemId = resize(fNotationBaseSystemId, fNotationBaseSystemId.length * 2); 2510 } 2511 else if (fNotationName[chunk] != null) { 2512 return; 2513 } 2514 2515 fNotationName[chunk] = new String[CHUNK_SIZE]; 2516 fNotationPublicId[chunk] = new String[CHUNK_SIZE]; 2517 fNotationSystemId[chunk] = new String[CHUNK_SIZE]; 2518 fNotationBaseSystemId[chunk] = new String[CHUNK_SIZE]; 2519 return; 2520 } 2521 2522 private void ensureContentSpecCapacity(int chunk) { 2523 if (chunk >= fContentSpecType.length) { 2524 fContentSpecType = resize(fContentSpecType, fContentSpecType.length * 2); 2525 fContentSpecValue = resize(fContentSpecValue, fContentSpecValue.length * 2); 2526 fContentSpecOtherValue = resize(fContentSpecOtherValue, fContentSpecOtherValue.length * 2); 2527 } 2528 else if (fContentSpecType[chunk] != null) { 2529 return; 2530 } 2531 2532 fContentSpecType[chunk] = new short[CHUNK_SIZE]; 2533 fContentSpecValue[chunk] = new Object[CHUNK_SIZE]; 2534 fContentSpecOtherValue[chunk] = new Object[CHUNK_SIZE]; 2535 return; 2536 } 2537 2538 // 2539 // Private static methods 2540 // 2541 2542 // resize chunks 2543 2544 private static byte[][] resize(byte array[][], int newsize) { 2545 byte newarray[][] = new byte[newsize][]; 2546 System.arraycopy(array, 0, newarray, 0, array.length); 2547 return newarray; 2548 } 2549 2550 private static short[][] resize(short array[][], int newsize) { 2551 short newarray[][] = new short[newsize][]; 2552 System.arraycopy(array, 0, newarray, 0, array.length); 2553 return newarray; 2554 } 2555 2556 private static int[][] resize(int array[][], int newsize) { 2557 int newarray[][] = new int[newsize][]; 2558 System.arraycopy(array, 0, newarray, 0, array.length); 2559 return newarray; 2560 } 2561 2562 private static DatatypeValidator[][] resize(DatatypeValidator array[][], int newsize) { 2563 DatatypeValidator newarray[][] = new DatatypeValidator[newsize][]; 2564 System.arraycopy(array, 0, newarray, 0, array.length); 2565 return newarray; 2566 } 2567 2568 private static ContentModelValidator[][] resize(ContentModelValidator array[][], int newsize) { 2569 ContentModelValidator newarray[][] = new ContentModelValidator[newsize][]; 2570 System.arraycopy(array, 0, newarray, 0, array.length); 2571 return newarray; 2572 } 2573 2574 private static Object[][] resize(Object array[][], int newsize) { 2575 Object newarray[][] = new Object[newsize][]; 2576 System.arraycopy(array, 0, newarray, 0, array.length); 2577 return newarray; 2578 } 2579 2580 private static QName[][] resize(QName array[][], int newsize) { 2581 QName newarray[][] = new QName[newsize][]; 2582 System.arraycopy(array, 0, newarray, 0, array.length); 2583 return newarray; 2584 } 2585 2586 private static String[][] resize(String array[][], int newsize) { 2587 String newarray[][] = new String[newsize][]; 2588 System.arraycopy(array, 0, newarray, 0, array.length); 2589 return newarray; 2590 } 2591 2592 private static String[][][] resize(String array[][][], int newsize) { 2593 String newarray[][][] = new String[newsize] [][]; 2594 System.arraycopy(array, 0, newarray, 0, array.length); 2595 return newarray; 2596 } 2597 2598 // 2599 // Classes 2600 // 2601 2602 /** 2603 * Children list for <code>contentSpecTree</code> method. 2604 * 2605 * @xerces.internal 2606 * 2607 * @author Eric Ye, IBM 2608 */ 2609 private static class ChildrenList { 2610 2611 // 2612 // Data 2613 // 2614 2615 /** Length. */ 2616 public int length = 0; 2617 2618 // NOTE: The following set of data is mutually exclusive. It is 2619 // written this way because Java doesn't have a native 2620 // union data structure. -Ac 2621 2622 /** Left and right children names. */ 2623 public QName[] qname = new QName[2]; 2624 2625 /** Left and right children types. */ 2626 public int[] type = new int[2]; 2627 2628 // 2629 // Constructors 2630 // 2631 2632 public ChildrenList () {} 2633 2634 } // class ChildrenList 2635 2636 // 2637 // EntityState methods 2638 // 2639 public boolean isEntityDeclared (String name){ 2640 return (getEntityDeclIndex(name)!=-1)?true:false; 2641 } 2642 2643 public boolean isEntityUnparsed (String name){ 2644 int entityIndex = getEntityDeclIndex(name); 2645 if (entityIndex >-1) { 2646 int chunk = entityIndex >> CHUNK_SHIFT; 2647 int index = entityIndex & CHUNK_MASK; 2648 //for unparsed entity notation!=null 2649 return (fEntityNotation[chunk][index]!=null)?true:false; 2650 } 2651 return false; 2652 } 2653 } // class DTDGrammar