1/* 2 * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. 3 */ 4 5/* 6 * Licensed to the Apache Software Foundation (ASF) under one or more 7 * contributor license agreements. See the NOTICE file distributed with 8 * this work for additional information regarding copyright ownership. 9 * The ASF licenses this file to You under the Apache License, Version 2.0 10 * (the "License"); you may not use this file except in compliance with 11 * the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 */ 21 22package com.sun.xml.internal.stream.dtd.nonvalidating; 23 24import com.sun.org.apache.xerces.internal.util.SymbolTable; 25import com.sun.org.apache.xerces.internal.util.XMLSymbols; 26import com.sun.org.apache.xerces.internal.xni.Augmentations; 27import com.sun.org.apache.xerces.internal.xni.QName; 28import com.sun.org.apache.xerces.internal.xni.XMLLocator; 29import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier; 30import com.sun.org.apache.xerces.internal.xni.XMLString; 31import com.sun.org.apache.xerces.internal.xni.XNIException; 32import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDContentModelSource; 33import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDSource; 34import java.util.ArrayList; 35import java.util.HashMap; 36import java.util.List; 37import java.util.Map; 38 39/** 40 * A DTD grammar. This class implements the XNI handler interfaces 41 * for DTD information so that it can build the approprate validation 42 * structures automatically from the callbacks. 43 * 44 * @author Eric Ye, IBM 45 * @author Jeffrey Rodriguez, IBM 46 * @author Andy Clark, IBM 47 * @author Neil Graham, IBM 48 * 49 */ 50public class DTDGrammar { 51 52 53 /** Top level scope (-1). */ 54 public static final int TOP_LEVEL_SCOPE = -1; 55 56 // private 57 58 /** Chunk shift (8). */ 59 private static final int CHUNK_SHIFT = 8; // 2^8 = 256 60 61 /** Chunk size (1 << CHUNK_SHIFT). */ 62 private static final int CHUNK_SIZE = (1 << CHUNK_SHIFT); 63 64 /** Chunk mask (CHUNK_SIZE - 1). */ 65 private static final int CHUNK_MASK = CHUNK_SIZE - 1; 66 67 /** Initial chunk count (1 << (10 - CHUNK_SHIFT)). */ 68 private static final int INITIAL_CHUNK_COUNT = (1 << (10 - CHUNK_SHIFT)); // 2^10 = 1k 69 70 /** List flag (0x80). */ 71 private static final short LIST_FLAG = 0x80; 72 73 /** List mask (~LIST_FLAG). */ 74 private static final short LIST_MASK = ~LIST_FLAG; 75 76 // debugging 77 78 /** Debug DTDGrammar. */ 79 private static final boolean DEBUG = false; 80 81 // 82 // Data 83 // 84 85 protected XMLDTDSource fDTDSource = null; 86 protected XMLDTDContentModelSource fDTDContentModelSource = null; 87 88 /** Current element index. */ 89 protected int fCurrentElementIndex; 90 91 /** Current attribute index. */ 92 protected int fCurrentAttributeIndex; 93 94 /** fReadingExternalDTD */ 95 protected boolean fReadingExternalDTD = false; 96 97 /** Symbol table. */ 98 private final SymbolTable fSymbolTable; 99 private final ArrayList<XMLNotationDecl> notationDecls = new ArrayList<>(); 100 101 // element declarations 102 103 /** Number of element declarations. */ 104 private int fElementDeclCount = 0; 105 106 /** Element declaration name. */ 107 private QName fElementDeclName[][] = new QName[INITIAL_CHUNK_COUNT][]; 108 109 /** 110 * Element declaration type. 111 * @see XMLElementDecl 112 */ 113 private short fElementDeclType[][] = new short[INITIAL_CHUNK_COUNT][]; 114 115 116 /** First attribute declaration of an element declaration. */ 117 private int fElementDeclFirstAttributeDeclIndex[][] = new int[INITIAL_CHUNK_COUNT][]; 118 119 /** Last attribute declaration of an element declaration. */ 120 private int fElementDeclLastAttributeDeclIndex[][] = new int[INITIAL_CHUNK_COUNT][]; 121 122 // attribute declarations 123 124 /** Number of attribute declarations. */ 125 private int fAttributeDeclCount = 0 ; 126 127 /** Attribute declaration name. */ 128 private QName fAttributeDeclName[][] = new QName[INITIAL_CHUNK_COUNT][]; 129 130 /** 131 * Attribute declaration type. 132 * @see XMLAttributeDecl 133 */ 134 private short fAttributeDeclType[][] = new short[INITIAL_CHUNK_COUNT][]; 135 136 /** Attribute declaration enumeration values. */ 137 private String[] fAttributeDeclEnumeration[][] = new String[INITIAL_CHUNK_COUNT][][]; 138 private short fAttributeDeclDefaultType[][] = new short[INITIAL_CHUNK_COUNT][]; 139 private String fAttributeDeclDefaultValue[][] = new String[INITIAL_CHUNK_COUNT][]; 140 private String fAttributeDeclNonNormalizedDefaultValue[][] = new String[INITIAL_CHUNK_COUNT][]; 141 private int fAttributeDeclNextAttributeDeclIndex[][] = new int[INITIAL_CHUNK_COUNT][]; 142 143 /** Element index mapping table. */ 144 private final Map<String, Integer> fElementIndexMap = new HashMap<>(); 145 146 /** Temporary qualified name. */ 147 private final QName fQName = new QName(); 148 149 /** Temporary Attribute decl. */ 150 protected XMLAttributeDecl fAttributeDecl = new XMLAttributeDecl(); 151 152 /** Element declaration. */ 153 private XMLElementDecl fElementDecl = new XMLElementDecl(); 154 155 /** Simple type. */ 156 private XMLSimpleType fSimpleType = new XMLSimpleType(); 157 158 159 /** table of XMLElementDecl */ 160 Map<String, XMLElementDecl> fElementDeclTab = new HashMap<>(); 161 162 /** Default constructor. */ 163 public DTDGrammar(SymbolTable symbolTable) { 164 fSymbolTable = symbolTable; 165 } 166 167 public int getAttributeDeclIndex(int elementDeclIndex, String attributeDeclName) { 168 if (elementDeclIndex == -1) { 169 return -1; 170 } 171 int attDefIndex = getFirstAttributeDeclIndex(elementDeclIndex); 172 while (attDefIndex != -1) { 173 getAttributeDecl(attDefIndex, fAttributeDecl); 174 175 if (fAttributeDecl.name.rawname == attributeDeclName 176 || attributeDeclName.equals(fAttributeDecl.name.rawname) ) { 177 return attDefIndex; 178 } 179 attDefIndex = getNextAttributeDeclIndex(attDefIndex); 180 } 181 return -1; 182 } 183 184 /** 185 * The start of the DTD. 186 * 187 * @param locator The document locator, or null if the document 188 * location cannot be reported during the parsing of 189 * the document DTD. However, it is <em>strongly</em> 190 * recommended that a locator be supplied that can 191 * at least report the base system identifier of the 192 * DTD. 193 * 194 * @param augs Additional information that may include infoset 195 * augmentations. 196 * @throws XNIException Thrown by handler to signal an error. 197 */ 198 public void startDTD(XMLLocator locator, Augmentations augs) throws XNIException { 199 } // startDTD(XMLLocator) 200 201 // startExternalSubset(Augmentations) 202 203 // endExternalSubset(Augmentations) 204 205 /** 206 * An element declaration. 207 * 208 * @param name The name of the element. 209 * @param contentModel The element content model. 210 * @param augs Additional information that may include infoset 211 * augmentations. 212 * @throws XNIException Thrown by handler to signal an error. 213 */ 214 public void elementDecl(String name, String contentModel, Augmentations augs) 215 throws XNIException { 216 217 XMLElementDecl tmpElementDecl = fElementDeclTab.get(name) ; 218 if ( tmpElementDecl != null ) { 219 if (tmpElementDecl.type == -1) { 220 fCurrentElementIndex = getElementDeclIndex(name); 221 } 222 else { 223 // duplicate element, ignored. 224 return; 225 } 226 } 227 else { 228 fCurrentElementIndex = createElementDecl();//create element decl 229 } 230 231 XMLElementDecl elementDecl = new XMLElementDecl(); 232 QName elementName = new QName(null, name, name, null); 233 234 elementDecl.name.setValues(elementName); 235 elementDecl.scope= -1; 236 if (contentModel.equals("EMPTY")) { 237 elementDecl.type = XMLElementDecl.TYPE_EMPTY; 238 } 239 else if (contentModel.equals("ANY")) { 240 elementDecl.type = XMLElementDecl.TYPE_ANY; 241 } 242 else if (contentModel.startsWith("(") ) { 243 if (contentModel.indexOf("#PCDATA") > 0 ) { 244 elementDecl.type = XMLElementDecl.TYPE_MIXED; 245 } 246 else { 247 elementDecl.type = XMLElementDecl.TYPE_CHILDREN; 248 } 249 } 250 251 252 //add(or set) this elementDecl to the local cache 253 this.fElementDeclTab.put(name, elementDecl ); 254 255 fElementDecl = elementDecl; 256 257 258 if ( DEBUG ) { 259 System.out.println( "name = " + fElementDecl.name.localpart ); 260 System.out.println( "Type = " + fElementDecl.type ); 261 } 262 263 setElementDecl(fCurrentElementIndex, fElementDecl );//set internal structure 264 265 int chunk = fCurrentElementIndex >> CHUNK_SHIFT; 266 ensureElementDeclCapacity(chunk); 267 } 268 269 /** 270 * An attribute declaration. 271 * 272 * @param elementName The name of the element that this attribute 273 * is associated with. 274 * @param attributeName The name of the attribute. 275 * @param type The attribute type. This value will be one of 276 * the following: "CDATA", "ENTITY", "ENTITIES", 277 * "ENUMERATION", "ID", "IDREF", "IDREFS", 278 * "NMTOKEN", "NMTOKENS", or "NOTATION". 279 * @param enumeration If the type has the value "ENUMERATION", this 280 * array holds the allowed attribute values; 281 * otherwise, this array is null. 282 * @param defaultType The attribute default type. This value will be 283 * one of the following: "#FIXED", "#IMPLIED", 284 * "#REQUIRED", or null. 285 * @param defaultValue The attribute default value, or null if no 286 * default value is specified. 287 * @param nonNormalizedDefaultValue The attribute default value with no normalization 288 * performed, or null if no default value is specified. 289 * 290 * @param augs Additional information that may include infoset 291 * augmentations. 292 * @throws XNIException Thrown by handler to signal an error. 293 */ 294 public void attributeDecl(String elementName, String attributeName, 295 String type, String[] enumeration, 296 String defaultType, XMLString defaultValue, 297 XMLString nonNormalizedDefaultValue, Augmentations augs) throws XNIException { 298 299 if (type != XMLSymbols.fCDATASymbol && defaultValue != null) { 300 normalizeDefaultAttrValue(defaultValue); 301 } 302 303 if ( this.fElementDeclTab.containsKey(elementName)) { 304 //if ElementDecl has already being created in the Grammar then remove from table, 305 //this.fElementDeclTab.remove( (String) elementName ); 306 } 307 // then it is forward reference to a element decl, create the elementDecl first. 308 else { 309 fCurrentElementIndex = createElementDecl();//create element decl 310 311 XMLElementDecl elementDecl = new XMLElementDecl(); 312 elementDecl.name.setValues(null, elementName, elementName, null); 313 314 elementDecl.scope= -1; 315 316 //add(or set) this elementDecl to the local cache 317 this.fElementDeclTab.put(elementName, elementDecl ); 318 319 //set internal structure 320 setElementDecl(fCurrentElementIndex, elementDecl ); 321 } 322 323 //Get Grammar index to grammar array 324 int elementIndex = getElementDeclIndex(elementName); 325 326 //return, when more than one definition is provided for the same attribute of given element type 327 //only the first declaration is binding and later declarations are ignored 328 if (getAttributeDeclIndex(elementIndex, attributeName) != -1) { 329 return; 330 } 331 332 fCurrentAttributeIndex = createAttributeDecl();// Create current Attribute Decl 333 334 fSimpleType.clear(); 335 if ( defaultType != null ) { 336 if ( defaultType.equals( "#FIXED") ) { 337 fSimpleType.defaultType = XMLSimpleType.DEFAULT_TYPE_FIXED; 338 } else if ( defaultType.equals( "#IMPLIED") ) { 339 fSimpleType.defaultType = XMLSimpleType.DEFAULT_TYPE_IMPLIED; 340 } else if ( defaultType.equals( "#REQUIRED") ) { 341 fSimpleType.defaultType = XMLSimpleType.DEFAULT_TYPE_REQUIRED; 342 } 343 } 344 if ( DEBUG ) { 345 System.out.println("defaultvalue = " + defaultValue.toString() ); 346 } 347 fSimpleType.defaultValue = defaultValue!=null ? defaultValue.toString() : null; 348 fSimpleType.nonNormalizedDefaultValue = nonNormalizedDefaultValue!=null ? 349 nonNormalizedDefaultValue.toString() : null; 350 fSimpleType.enumeration = enumeration; 351 352 if (type.equals("CDATA")) { 353 fSimpleType.type = XMLSimpleType.TYPE_CDATA; 354 } 355 else if ( type.equals("ID") ) { 356 fSimpleType.type = XMLSimpleType.TYPE_ID; 357 } 358 else if ( type.startsWith("IDREF") ) { 359 fSimpleType.type = XMLSimpleType.TYPE_IDREF; 360 if (type.indexOf("S") > 0) { 361 fSimpleType.list = true; 362 } 363 } 364 else if (type.equals("ENTITIES")) { 365 fSimpleType.type = XMLSimpleType.TYPE_ENTITY; 366 fSimpleType.list = true; 367 } 368 else if (type.equals("ENTITY")) { 369 fSimpleType.type = XMLSimpleType.TYPE_ENTITY; 370 } 371 else if (type.equals("NMTOKENS")) { 372 fSimpleType.type = XMLSimpleType.TYPE_NMTOKEN; 373 fSimpleType.list = true; 374 } 375 else if (type.equals("NMTOKEN")) { 376 fSimpleType.type = XMLSimpleType.TYPE_NMTOKEN; 377 } 378 else if (type.startsWith("NOTATION") ) { 379 fSimpleType.type = XMLSimpleType.TYPE_NOTATION; 380 } 381 else if (type.startsWith("ENUMERATION") ) { 382 fSimpleType.type = XMLSimpleType.TYPE_ENUMERATION; 383 } 384 else { 385 // REVISIT: Report error message. -Ac 386 System.err.println("!!! unknown attribute type "+type); 387 } 388 // REVISIT: The datatype should be stored with the attribute value 389 // and not special-cased in the XMLValidator. -Ac 390 //fSimpleType.datatypeValidator = fDatatypeValidatorFactory.createDatatypeValidator(type, null, facets, fSimpleType.list); 391 392 fQName.setValues(null, attributeName, attributeName, null); 393 fAttributeDecl.setValues( fQName, fSimpleType, false ); 394 395 setAttributeDecl(elementIndex, fCurrentAttributeIndex, fAttributeDecl); 396 397 int chunk = fCurrentAttributeIndex >> CHUNK_SHIFT; 398 ensureAttributeDeclCapacity(chunk); 399 } // attributeDecl(String,String,String,String[],String,XMLString,XMLString, Augmentations) 400 401 /** Returns the symbol table. */ 402 public SymbolTable getSymbolTable() { 403 return fSymbolTable; 404 } // getSymbolTable():SymbolTable 405 406 /** 407 * Returns the index of the first element declaration. This index 408 * is then used to query more information about the element declaration. 409 * 410 * @see #getNextElementDeclIndex 411 * @see #getElementDecl 412 */ 413 public int getFirstElementDeclIndex() { 414 return fElementDeclCount >= 0 ? 0 : -1; 415 } // getFirstElementDeclIndex():int 416 417 /** 418 * Returns the next index of the element declaration following the 419 * specified element declaration. 420 * 421 * @param elementDeclIndex The element declaration index. 422 */ 423 public int getNextElementDeclIndex(int elementDeclIndex) { 424 return elementDeclIndex < fElementDeclCount - 1 425 ? elementDeclIndex + 1 : -1; 426 } // getNextElementDeclIndex(int):int 427 428 /** 429 * getElementDeclIndex 430 * 431 * @param elementDeclName 432 * 433 * @return index of the elementDeclName in scope 434 */ 435 public int getElementDeclIndex(String elementDeclName) { 436 Integer mapping = fElementIndexMap.get(elementDeclName); 437 if (mapping == null) { 438 mapping = -1; 439 } 440 //System.out.println("getElementDeclIndex("+elementDeclName+") -> "+mapping); 441 return mapping; 442 } // getElementDeclIndex(String):int 443 444 /** Returns the element decl index. 445 * @param elementDeclQName qualilfied name of the element 446 */ 447 public int getElementDeclIndex(QName elementDeclQName) { 448 return getElementDeclIndex(elementDeclQName.rawname); 449 } // getElementDeclIndex(QName):int 450 451 /** make separate function for getting contentSpecType of element. 452 * we can avoid setting of the element values. 453 */ 454 455 public short getContentSpecType(int elementIndex){ 456 if (elementIndex < 0 || elementIndex >= fElementDeclCount) { 457 return -1 ; 458 } 459 460 int chunk = elementIndex >> CHUNK_SHIFT; 461 int index = elementIndex & CHUNK_MASK; 462 463 if(fElementDeclType[chunk][index] == -1){ 464 return -1 ; 465 } 466 else{ 467 return (short) (fElementDeclType[chunk][index] & LIST_MASK); 468 } 469 } 470 471 /** 472 * getElementDecl 473 * 474 * @param elementDeclIndex 475 * @param elementDecl The values of this structure are set by this call. 476 * 477 * @return True if find the element, False otherwise. 478 */ 479 public boolean getElementDecl(int elementDeclIndex, 480 XMLElementDecl elementDecl) { 481 482 if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) { 483 return false; 484 } 485 486 int chunk = elementDeclIndex >> CHUNK_SHIFT; 487 int index = elementDeclIndex & CHUNK_MASK; 488 489 elementDecl.name.setValues(fElementDeclName[chunk][index]); 490 491 if (fElementDeclType[chunk][index] == -1) { 492 elementDecl.type = -1; 493 elementDecl.simpleType.list = false; 494 } else { 495 elementDecl.type = (short) (fElementDeclType[chunk][index] & LIST_MASK); 496 elementDecl.simpleType.list = (fElementDeclType[chunk][index] & LIST_FLAG) != 0; 497 } 498 499 elementDecl.simpleType.defaultType = -1; 500 elementDecl.simpleType.defaultValue = null; 501 return true; 502 503 } 504 505 // REVISIT: Make this getAttributeDeclCount/getAttributeDeclAt. -Ac 506 507 /** 508 * getFirstAttributeDeclIndex 509 * 510 * @param elementDeclIndex 511 * 512 * @return index of the first attribute for element declaration elementDeclIndex 513 */ 514 public int getFirstAttributeDeclIndex(int elementDeclIndex) { 515 int chunk = elementDeclIndex >> CHUNK_SHIFT; 516 int index = elementDeclIndex & CHUNK_MASK; 517 518 return fElementDeclFirstAttributeDeclIndex[chunk][index]; 519 } // getFirstAttributeDeclIndex 520 521 /** 522 * getNextAttributeDeclIndex 523 * 524 * @param attributeDeclIndex 525 * 526 * @return index of the next attribute of the attribute at attributeDeclIndex 527 */ 528 public int getNextAttributeDeclIndex(int attributeDeclIndex) { 529 int chunk = attributeDeclIndex >> CHUNK_SHIFT; 530 int index = attributeDeclIndex & CHUNK_MASK; 531 532 return fAttributeDeclNextAttributeDeclIndex[chunk][index]; 533 } 534 535 /** 536 * getAttributeDecl 537 * 538 * @param attributeDeclIndex 539 * @param attributeDecl The values of this structure are set by this call. 540 * 541 * @return true if getAttributeDecl was able to fill in the value of attributeDecl 542 */ 543 public boolean getAttributeDecl(int attributeDeclIndex, XMLAttributeDecl attributeDecl) { 544 if (attributeDeclIndex < 0 || attributeDeclIndex >= fAttributeDeclCount) { 545 return false; 546 } 547 int chunk = attributeDeclIndex >> CHUNK_SHIFT; 548 int index = attributeDeclIndex & CHUNK_MASK; 549 550 attributeDecl.name.setValues(fAttributeDeclName[chunk][index]); 551 552 short attributeType; 553 boolean isList; 554 555 if (fAttributeDeclType[chunk][index] == -1) { 556 557 attributeType = -1; 558 isList = false; 559 } else { 560 attributeType = (short) (fAttributeDeclType[chunk][index] & LIST_MASK); 561 isList = (fAttributeDeclType[chunk][index] & LIST_FLAG) != 0; 562 } 563 attributeDecl.simpleType.setValues(attributeType,fAttributeDeclName[chunk][index].localpart, 564 fAttributeDeclEnumeration[chunk][index], 565 isList, fAttributeDeclDefaultType[chunk][index], 566 fAttributeDeclDefaultValue[chunk][index], 567 fAttributeDeclNonNormalizedDefaultValue[chunk][index]); 568 return true; 569 570 } // getAttributeDecl 571 572 573 /** 574 * Returns whether the given attribute is of type CDATA or not 575 * 576 * @param elName The element name. 577 * @param atName The attribute name. 578 * 579 * @return true if the attribute is of type CDATA 580 */ 581 public boolean isCDATAAttribute(QName elName, QName atName) { 582 int elDeclIdx = getElementDeclIndex(elName); 583 if (getAttributeDecl(elDeclIdx, fAttributeDecl) 584 && fAttributeDecl.simpleType.type != XMLSimpleType.TYPE_CDATA){ 585 return false; 586 } 587 return true; 588 } 589 590 591 592 public void printElements( ) { 593 int elementDeclIndex = 0; 594 XMLElementDecl elementDecl = new XMLElementDecl(); 595 while (getElementDecl(elementDeclIndex++, elementDecl)) { 596 597 System.out.println("element decl: "+elementDecl.name+ 598 ", "+ elementDecl.name.rawname ); 599 600 } 601 } 602 603 public void printAttributes(int elementDeclIndex) { 604 int attributeDeclIndex = getFirstAttributeDeclIndex(elementDeclIndex); 605 System.out.print(elementDeclIndex); 606 System.out.print(" ["); 607 while (attributeDeclIndex != -1) { 608 System.out.print(' '); 609 System.out.print(attributeDeclIndex); 610 printAttribute(attributeDeclIndex); 611 attributeDeclIndex = getNextAttributeDeclIndex(attributeDeclIndex); 612 if (attributeDeclIndex != -1) { 613 System.out.print(","); 614 } 615 } 616 System.out.println(" ]"); 617 } 618 619 620 protected int createElementDecl() { 621 int chunk = fElementDeclCount >> CHUNK_SHIFT; 622 int index = fElementDeclCount & CHUNK_MASK; 623 ensureElementDeclCapacity(chunk); 624 fElementDeclName[chunk][index] = new QName(); 625 fElementDeclType[chunk][index] = -1; 626 fElementDeclFirstAttributeDeclIndex[chunk][index] = -1; 627 fElementDeclLastAttributeDeclIndex[chunk][index] = -1; 628 return fElementDeclCount++; 629 } 630 631 protected void setElementDecl(int elementDeclIndex, XMLElementDecl elementDecl) { 632 if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) { 633 return; 634 } 635 int chunk = elementDeclIndex >> CHUNK_SHIFT; 636 int index = elementDeclIndex & CHUNK_MASK; 637 638 int scope = elementDecl.scope; 639 640 641 fElementDeclName[chunk][index].setValues(elementDecl.name); 642 fElementDeclType[chunk][index] = elementDecl.type; 643 644 645 646 if (elementDecl.simpleType.list == true ) { 647 fElementDeclType[chunk][index] |= LIST_FLAG; 648 } 649 650 fElementIndexMap.put(elementDecl.name.rawname, elementDeclIndex); 651 } 652 653 654 655 656 protected void setFirstAttributeDeclIndex(int elementDeclIndex, int newFirstAttrIndex){ 657 658 if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) { 659 return; 660 } 661 662 int chunk = elementDeclIndex >> CHUNK_SHIFT; 663 int index = elementDeclIndex & CHUNK_MASK; 664 665 fElementDeclFirstAttributeDeclIndex[chunk][index] = newFirstAttrIndex; 666 } 667 668 669 protected int createAttributeDecl() { 670 int chunk = fAttributeDeclCount >> CHUNK_SHIFT; 671 int index = fAttributeDeclCount & CHUNK_MASK; 672 673 ensureAttributeDeclCapacity(chunk); 674 fAttributeDeclName[chunk][index] = new QName(); 675 fAttributeDeclType[chunk][index] = -1; 676 fAttributeDeclEnumeration[chunk][index] = null; 677 fAttributeDeclDefaultType[chunk][index] = XMLSimpleType.DEFAULT_TYPE_IMPLIED; 678 fAttributeDeclDefaultValue[chunk][index] = null; 679 fAttributeDeclNonNormalizedDefaultValue[chunk][index] = null; 680 fAttributeDeclNextAttributeDeclIndex[chunk][index] = -1; 681 return fAttributeDeclCount++; 682 } 683 684 685 protected void setAttributeDecl(int elementDeclIndex, int attributeDeclIndex, 686 XMLAttributeDecl attributeDecl) { 687 int attrChunk = attributeDeclIndex >> CHUNK_SHIFT; 688 int attrIndex = attributeDeclIndex & CHUNK_MASK; 689 fAttributeDeclName[attrChunk][attrIndex].setValues(attributeDecl.name); 690 fAttributeDeclType[attrChunk][attrIndex] = attributeDecl.simpleType.type; 691 692 if (attributeDecl.simpleType.list) { 693 fAttributeDeclType[attrChunk][attrIndex] |= LIST_FLAG; 694 } 695 fAttributeDeclEnumeration[attrChunk][attrIndex] = attributeDecl.simpleType.enumeration; 696 fAttributeDeclDefaultType[attrChunk][attrIndex] = attributeDecl.simpleType.defaultType; 697 698 fAttributeDeclDefaultValue[attrChunk][attrIndex] = attributeDecl.simpleType.defaultValue; 699 fAttributeDeclNonNormalizedDefaultValue[attrChunk][attrIndex] = attributeDecl.simpleType.nonNormalizedDefaultValue; 700 701 int elemChunk = elementDeclIndex >> CHUNK_SHIFT; 702 int elemIndex = elementDeclIndex & CHUNK_MASK; 703 int index = fElementDeclFirstAttributeDeclIndex[elemChunk][elemIndex]; 704 while (index != -1) { 705 if (index == attributeDeclIndex) { 706 break; 707 } 708 attrChunk = index >> CHUNK_SHIFT; 709 attrIndex = index & CHUNK_MASK; 710 index = fAttributeDeclNextAttributeDeclIndex[attrChunk][attrIndex]; 711 } 712 if (index == -1) { 713 if (fElementDeclFirstAttributeDeclIndex[elemChunk][elemIndex] == -1) { 714 fElementDeclFirstAttributeDeclIndex[elemChunk][elemIndex] = attributeDeclIndex; 715 } else { 716 index = fElementDeclLastAttributeDeclIndex[elemChunk][elemIndex]; 717 attrChunk = index >> CHUNK_SHIFT; 718 attrIndex = index & CHUNK_MASK; 719 fAttributeDeclNextAttributeDeclIndex[attrChunk][attrIndex] = attributeDeclIndex; 720 } 721 fElementDeclLastAttributeDeclIndex[elemChunk][elemIndex] = attributeDeclIndex; 722 } 723 } 724 725 public void notationDecl(String name, XMLResourceIdentifier identifier, 726 Augmentations augs) throws XNIException { 727 728 729 XMLNotationDecl notationDecl = new XMLNotationDecl(); 730 notationDecl.setValues(name,identifier.getPublicId(),identifier.getLiteralSystemId(), 731 identifier.getBaseSystemId()); 732 notationDecls.add(notationDecl); 733 } 734 735 public List<XMLNotationDecl> getNotationDecls() { 736 return notationDecls; 737 } 738 739 // 740 // Private methods 741 // 742 private void printAttribute(int attributeDeclIndex) { 743 744 XMLAttributeDecl attributeDecl = new XMLAttributeDecl(); 745 if (getAttributeDecl(attributeDeclIndex, attributeDecl)) { 746 System.out.print(" { "); 747 System.out.print(attributeDecl.name.localpart); 748 System.out.print(" }"); 749 } 750 751 } // printAttribute(int) 752 753 754 755 private void ensureElementDeclCapacity(int chunk) { 756 if (chunk >= fElementDeclName.length) { 757 758 fElementDeclName = resize(fElementDeclName, fElementDeclName.length * 2); 759 fElementDeclType = resize(fElementDeclType, fElementDeclType.length * 2); 760 fElementDeclFirstAttributeDeclIndex = resize(fElementDeclFirstAttributeDeclIndex, fElementDeclFirstAttributeDeclIndex.length * 2); 761 fElementDeclLastAttributeDeclIndex = resize(fElementDeclLastAttributeDeclIndex, fElementDeclLastAttributeDeclIndex.length * 2); 762 } 763 else if (fElementDeclName[chunk] != null) { 764 return; 765 } 766 767 fElementDeclName[chunk] = new QName[CHUNK_SIZE]; 768 fElementDeclType[chunk] = new short[CHUNK_SIZE]; 769 fElementDeclFirstAttributeDeclIndex[chunk] = new int[CHUNK_SIZE]; 770 fElementDeclLastAttributeDeclIndex[chunk] = new int[CHUNK_SIZE]; 771 return; 772 } 773 774 private void ensureAttributeDeclCapacity(int chunk) { 775 776 if (chunk >= fAttributeDeclName.length) { 777 fAttributeDeclName = resize(fAttributeDeclName, fAttributeDeclName.length * 2); 778 fAttributeDeclType = resize(fAttributeDeclType, fAttributeDeclType.length * 2); 779 fAttributeDeclEnumeration = resize(fAttributeDeclEnumeration, fAttributeDeclEnumeration.length * 2); 780 fAttributeDeclDefaultType = resize(fAttributeDeclDefaultType, fAttributeDeclDefaultType.length * 2); 781 fAttributeDeclDefaultValue = resize(fAttributeDeclDefaultValue, fAttributeDeclDefaultValue.length * 2); 782 fAttributeDeclNonNormalizedDefaultValue = resize(fAttributeDeclNonNormalizedDefaultValue, fAttributeDeclNonNormalizedDefaultValue.length * 2); 783 fAttributeDeclNextAttributeDeclIndex = resize(fAttributeDeclNextAttributeDeclIndex, fAttributeDeclNextAttributeDeclIndex.length * 2); 784 } 785 else if (fAttributeDeclName[chunk] != null) { 786 return; 787 } 788 789 fAttributeDeclName[chunk] = new QName[CHUNK_SIZE]; 790 fAttributeDeclType[chunk] = new short[CHUNK_SIZE]; 791 fAttributeDeclEnumeration[chunk] = new String[CHUNK_SIZE][]; 792 fAttributeDeclDefaultType[chunk] = new short[CHUNK_SIZE]; 793 fAttributeDeclDefaultValue[chunk] = new String[CHUNK_SIZE]; 794 fAttributeDeclNonNormalizedDefaultValue[chunk] = new String[CHUNK_SIZE]; 795 fAttributeDeclNextAttributeDeclIndex[chunk] = new int[CHUNK_SIZE]; 796 return; 797 } 798 799 800 // resize chunks 801 802 private static short[][] resize(short array[][], int newsize) { 803 short newarray[][] = new short[newsize][]; 804 System.arraycopy(array, 0, newarray, 0, array.length); 805 return newarray; 806 } 807 808 private static int[][] resize(int array[][], int newsize) { 809 int newarray[][] = new int[newsize][]; 810 System.arraycopy(array, 0, newarray, 0, array.length); 811 return newarray; 812 } 813 814 private static QName[][] resize(QName array[][], int newsize) { 815 QName newarray[][] = new QName[newsize][]; 816 System.arraycopy(array, 0, newarray, 0, array.length); 817 return newarray; 818 } 819 820 private static String[][] resize(String array[][], int newsize) { 821 String newarray[][] = new String[newsize][]; 822 System.arraycopy(array, 0, newarray, 0, array.length); 823 return newarray; 824 } 825 826 private static String[][][] resize(String array[][][], int newsize) { 827 String newarray[][][] = new String[newsize] [][]; 828 System.arraycopy(array, 0, newarray, 0, array.length); 829 return newarray; 830 } 831 832 /** 833 * Normalize the attribute value of a non CDATA default attribute 834 * collapsing sequences of space characters (x20) 835 * 836 * @param value The value to normalize 837 * @return Whether the value was changed or not. 838 */ 839 private boolean normalizeDefaultAttrValue(XMLString value) { 840 841 int oldLength = value.length; 842 843 boolean skipSpace = true; // skip leading spaces 844 int current = value.offset; 845 int end = value.offset + value.length; 846 for (int i = value.offset; i < end; i++) { 847 if (value.ch[i] == ' ') { 848 if (!skipSpace) { 849 // take the first whitespace as a space and skip the others 850 value.ch[current++] = ' '; 851 skipSpace = true; 852 } 853 else { 854 // just skip it. 855 } 856 } 857 else { 858 // simply shift non space chars if needed 859 if (current != i) { 860 value.ch[current] = value.ch[i]; 861 } 862 current++; 863 skipSpace = false; 864 } 865 } 866 if (current != end) { 867 if (skipSpace) { 868 // if we finished on a space trim it 869 current--; 870 } 871 // set the new value length 872 value.length = current - value.offset; 873 return true; 874 } 875 return false; 876 } 877 public void endDTD(Augmentations augs) throws XNIException { 878 879 } 880} 881