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