1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. *
  5. * Copyright (c) 2002-2004 The Apache Software Foundation. All rights
  6. * 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) 2001, 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.xs;
  58. import java.util.Vector;
  59. import com.sun.org.apache.xerces.internal.xs.StringList;
  60. import com.sun.org.apache.xerces.internal.xs.XSAttributeDeclaration;
  61. import com.sun.org.apache.xerces.internal.xs.XSAttributeGroupDefinition;
  62. import com.sun.org.apache.xerces.internal.xs.XSConstants;
  63. import com.sun.org.apache.xerces.internal.xs.XSElementDeclaration;
  64. import com.sun.org.apache.xerces.internal.xs.XSModel;
  65. import com.sun.org.apache.xerces.internal.xs.XSModelGroupDefinition;
  66. import com.sun.org.apache.xerces.internal.xs.XSNamedMap;
  67. import com.sun.org.apache.xerces.internal.xs.XSNamespaceItemList;
  68. import com.sun.org.apache.xerces.internal.xs.XSNotationDeclaration;
  69. import com.sun.org.apache.xerces.internal.xs.XSObjectList;
  70. import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition;
  71. import com.sun.org.apache.xerces.internal.impl.xs.util.NSItemListImpl;
  72. import com.sun.org.apache.xerces.internal.impl.xs.util.StringListImpl;
  73. import com.sun.org.apache.xerces.internal.impl.xs.util.XSNamedMap4Types;
  74. import com.sun.org.apache.xerces.internal.impl.xs.util.XSNamedMapImpl;
  75. import com.sun.org.apache.xerces.internal.impl.xs.util.XSObjectListImpl;
  76. import com.sun.org.apache.xerces.internal.util.SymbolHash;
  77. import com.sun.org.apache.xerces.internal.util.XMLSymbols;
  78. /**
  79. * @author elitani
  80. *
  81. * To change this generated comment edit the template variable "typecomment":
  82. * Window>Preferences>Java>Templates.
  83. * To enable and disable the creation of type comments go to
  84. * Window>Preferences>Java>Code Generation.
  85. */
  86. /**
  87. * @author elitani
  88. *
  89. * To change this generated comment edit the template variable "typecomment":
  90. * Window>Preferences>Java>Templates.
  91. * To enable and disable the creation of type comments go to
  92. * Window>Preferences>Java>Code Generation.
  93. */
  94. /**
  95. * Implements XSModel: a read-only interface that represents an XML Schema,
  96. * which could be components from different namespaces.
  97. *
  98. * @author Sandy Gao, IBM
  99. *
  100. * @version $Id: XSModelImpl.java,v 1.12 2004/02/03 17:10:38 sandygao Exp $
  101. */
  102. public class XSModelImpl implements XSModel {
  103. // the max index / the max value of XSObject type
  104. private static final short MAX_COMP_IDX = XSTypeDefinition.SIMPLE_TYPE;
  105. private static final boolean[] GLOBAL_COMP = {false, // null
  106. true, // attribute
  107. true, // element
  108. true, // type
  109. false, // attribute use
  110. true, // attribute group
  111. true, // group
  112. false, // model group
  113. false, // particle
  114. false, // wildcard
  115. false, // idc
  116. true, // notation
  117. false, // annotation
  118. false, // facet
  119. false, // multi value facet
  120. true, // complex type
  121. true // simple type
  122. };
  123. // number of grammars/namespaces stored here
  124. private int fGrammarCount;
  125. // all target namespaces
  126. private String[] fNamespaces;
  127. // all schema grammar objects (for each namespace)
  128. private SchemaGrammar[] fGrammarList;
  129. // a map from namespace to schema grammar
  130. private SymbolHash fGrammarMap;
  131. // a map from element declaration to its substitution group
  132. private SymbolHash fSubGroupMap;
  133. // store a certain kind of components from all namespaces
  134. private XSNamedMap[] fGlobalComponents;
  135. // store a certain kind of components from one namespace
  136. private XSNamedMap[][] fNSComponents;
  137. // store all annotations
  138. private XSObjectListImpl fAnnotations = null;
  139. // whether there is any IDC in this XSModel
  140. private boolean fHasIDC = false;
  141. /**
  142. * Construct an XSModelImpl, by storing some grammars and grammars imported
  143. * by them to this object.
  144. *
  145. * @param grammars the array of schema grammars
  146. */
  147. public XSModelImpl(SchemaGrammar[] grammars) {
  148. // copy namespaces/grammars from the array to our arrays
  149. int len = grammars.length;
  150. fNamespaces = new String[Math.max(len+1, 5)];
  151. fGrammarList = new SchemaGrammar[Math.max(len+1, 5)];
  152. boolean hasS4S = false;
  153. for (int i = 0; i < len; i++) {
  154. fNamespaces[i] = grammars[i].getTargetNamespace();
  155. fGrammarList[i] = grammars[i];
  156. if (fNamespaces[i] == SchemaSymbols.URI_SCHEMAFORSCHEMA)
  157. hasS4S = true;
  158. }
  159. // If a schema for the schema namespace isn't included, include it here.
  160. if (!hasS4S) {
  161. fNamespaces[len] = SchemaSymbols.URI_SCHEMAFORSCHEMA;
  162. fGrammarList[len++] = SchemaGrammar.SG_SchemaNS;
  163. }
  164. SchemaGrammar sg1, sg2;
  165. Vector gs;
  166. int i, j, k;
  167. // and recursively get all imported grammars, add them to our arrays
  168. for (i = 0; i < len; i++) {
  169. // get the grammar
  170. sg1 = fGrammarList[i];
  171. gs = sg1.getImportedGrammars();
  172. // for each imported grammar
  173. for (j = gs == null ? -1 : gs.size() - 1; j >= 0; j--) {
  174. sg2 = (SchemaGrammar)gs.elementAt(j);
  175. // check whether this grammar is already in the list
  176. for (k = 0; k < len; k++) {
  177. if (sg2 == fGrammarList[k])
  178. break;
  179. }
  180. // if it's not, add it to the list
  181. if (k == len) {
  182. // ensure the capacity of the arrays
  183. if (len == fGrammarList.length) {
  184. String[] newSA = new String[len*2];
  185. System.arraycopy(fNamespaces, 0, newSA, 0, len);
  186. fNamespaces = newSA;
  187. SchemaGrammar[] newGA = new SchemaGrammar[len*2];
  188. System.arraycopy(fGrammarList, 0, newGA, 0, len);
  189. fGrammarList = newGA;
  190. }
  191. fNamespaces[len] = sg2.getTargetNamespace();
  192. fGrammarList[len] = sg2;
  193. len++;
  194. }
  195. }
  196. }
  197. // establish the mapping from namespace to grammars
  198. fGrammarMap = new SymbolHash(len*2);
  199. for (i = 0; i < len; i++) {
  200. fGrammarMap.put(null2EmptyString(fNamespaces[i]), fGrammarList[i]);
  201. // update the idc field
  202. if (fGrammarList[i].hasIDConstraints())
  203. fHasIDC = true;
  204. }
  205. fGrammarCount = len;
  206. fGlobalComponents = new XSNamedMap[MAX_COMP_IDX+1];
  207. fNSComponents = new XSNamedMap[len][MAX_COMP_IDX+1];
  208. // build substitution groups
  209. buildSubGroups();
  210. }
  211. private void buildSubGroups() {
  212. SubstitutionGroupHandler sgHandler = new SubstitutionGroupHandler(null);
  213. for (int i = 0 ; i < fGrammarCount; i++) {
  214. sgHandler.addSubstitutionGroup(fGrammarList[i].getSubstitutionGroups());
  215. }
  216. XSNamedMap elements = getComponents(XSConstants.ELEMENT_DECLARATION);
  217. int len = elements.getLength();
  218. fSubGroupMap = new SymbolHash(len*2);
  219. XSElementDecl head;
  220. XSElementDeclaration[] subGroup;
  221. for (int i = 0; i < len; i++) {
  222. head = (XSElementDecl)elements.item(i);
  223. subGroup = sgHandler.getSubstitutionGroup(head);
  224. fSubGroupMap.put(head, new XSObjectListImpl(subGroup, subGroup.length));
  225. }
  226. }
  227. /**
  228. * Convenience method. Returns a list of all namespaces that belong to
  229. * this schema.
  230. * @return A list of all namespaces that belong to this schema or
  231. * <code>null</code> if all components don't have a targetNamespace.
  232. */
  233. public StringList getNamespaces() {
  234. // REVISIT: should the type of fNamespace be StringListImpl?
  235. return new StringListImpl(fNamespaces, fGrammarCount);
  236. }
  237. public XSNamespaceItemList getNamespaceItems() {
  238. // REVISIT: should the type of fGrammarList be NSItemListImpl?
  239. return new NSItemListImpl(fGrammarList, fGrammarCount);
  240. }
  241. /**
  242. * Returns a list of top-level components, i.e. element declarations,
  243. * attribute declarations, etc.
  244. * @param objectType The type of the declaration, i.e.
  245. * ELEMENT_DECLARATION, ATTRIBUTE_DECLARATION, etc.
  246. * @return A list of top-level definition of the specified type in
  247. * <code>objectType</code> or <code>null</code>.
  248. */
  249. public synchronized XSNamedMap getComponents(short objectType) {
  250. if (objectType <= 0 || objectType > MAX_COMP_IDX ||
  251. !GLOBAL_COMP[objectType]) {
  252. return null;
  253. }
  254. SymbolHash[] tables = new SymbolHash[fGrammarCount];
  255. // get all hashtables from all namespaces for this type of components
  256. if (fGlobalComponents[objectType] == null) {
  257. for (int i = 0; i < fGrammarCount; i++) {
  258. switch (objectType) {
  259. case XSConstants.TYPE_DEFINITION:
  260. case XSTypeDefinition.COMPLEX_TYPE:
  261. case XSTypeDefinition.SIMPLE_TYPE:
  262. tables[i] = fGrammarList[i].fGlobalTypeDecls;
  263. break;
  264. case XSConstants.ATTRIBUTE_DECLARATION:
  265. tables[i] = fGrammarList[i].fGlobalAttrDecls;
  266. break;
  267. case XSConstants.ELEMENT_DECLARATION:
  268. tables[i] = fGrammarList[i].fGlobalElemDecls;
  269. break;
  270. case XSConstants.ATTRIBUTE_GROUP:
  271. tables[i] = fGrammarList[i].fGlobalAttrGrpDecls;
  272. break;
  273. case XSConstants.MODEL_GROUP_DEFINITION:
  274. tables[i] = fGrammarList[i].fGlobalGroupDecls;
  275. break;
  276. case XSConstants.NOTATION_DECLARATION:
  277. tables[i] = fGrammarList[i].fGlobalNotationDecls;
  278. break;
  279. }
  280. }
  281. // for complex/simple types, create a special implementation,
  282. // which take specific types out of the hash table
  283. if (objectType == XSTypeDefinition.COMPLEX_TYPE ||
  284. objectType == XSTypeDefinition.SIMPLE_TYPE) {
  285. fGlobalComponents[objectType] = new XSNamedMap4Types(fNamespaces, tables, fGrammarCount, objectType);
  286. }
  287. else {
  288. fGlobalComponents[objectType] = new XSNamedMapImpl(fNamespaces, tables, fGrammarCount);
  289. }
  290. }
  291. return fGlobalComponents[objectType];
  292. }
  293. /**
  294. * Convenience method. Returns a list of top-level component declarations
  295. * that are defined within the specified namespace, i.e. element
  296. * declarations, attribute declarations, etc.
  297. * @param objectType The type of the declaration, i.e.
  298. * ELEMENT_DECLARATION, ATTRIBUTE_DECLARATION, etc.
  299. * @param namespace The namespace to which declaration belong or
  300. * <code>null</code> (for components with no targetNamespace).
  301. * @return A list of top-level definition of the specified type in
  302. * <code>objectType</code> and defined in the specified
  303. * <code>namespace</code> or <code>null</code>.
  304. */
  305. public synchronized XSNamedMap getComponentsByNamespace(short objectType,
  306. String namespace) {
  307. if (objectType <= 0 || objectType > MAX_COMP_IDX ||
  308. !GLOBAL_COMP[objectType]) {
  309. return null;
  310. }
  311. // try to find the grammar
  312. int i = 0;
  313. for (; i < fGrammarCount; i++) {
  314. if (fNamespaces[i] == namespace)
  315. break;
  316. }
  317. if (i == fGrammarCount)
  318. return null;
  319. // get the hashtable for this type of components
  320. if (fNSComponents[i][objectType] == null) {
  321. SymbolHash table = null;
  322. switch (objectType) {
  323. case XSConstants.TYPE_DEFINITION:
  324. case XSTypeDefinition.COMPLEX_TYPE:
  325. case XSTypeDefinition.SIMPLE_TYPE:
  326. table = fGrammarList[i].fGlobalTypeDecls;
  327. break;
  328. case XSConstants.ATTRIBUTE_DECLARATION:
  329. table = fGrammarList[i].fGlobalAttrDecls;
  330. break;
  331. case XSConstants.ELEMENT_DECLARATION:
  332. table = fGrammarList[i].fGlobalElemDecls;
  333. break;
  334. case XSConstants.ATTRIBUTE_GROUP:
  335. table = fGrammarList[i].fGlobalAttrGrpDecls;
  336. break;
  337. case XSConstants.MODEL_GROUP_DEFINITION:
  338. table = fGrammarList[i].fGlobalGroupDecls;
  339. break;
  340. case XSConstants.NOTATION_DECLARATION:
  341. table = fGrammarList[i].fGlobalNotationDecls;
  342. break;
  343. }
  344. // for complex/simple types, create a special implementation,
  345. // which take specific types out of the hash table
  346. if (objectType == XSTypeDefinition.COMPLEX_TYPE ||
  347. objectType == XSTypeDefinition.SIMPLE_TYPE) {
  348. fNSComponents[i][objectType] = new XSNamedMap4Types(namespace, table, objectType);
  349. }
  350. else {
  351. fNSComponents[i][objectType] = new XSNamedMapImpl(namespace, table);
  352. }
  353. }
  354. return fNSComponents[i][objectType];
  355. }
  356. /**
  357. * Convenience method. Returns a top-level simple or complex type
  358. * definition.
  359. * @param name The name of the definition.
  360. * @param namespace The namespace of the definition, otherwise null.
  361. * @return An <code>XSTypeDefinition</code> or null if such definition
  362. * does not exist.
  363. */
  364. public XSTypeDefinition getTypeDefinition(String name,
  365. String namespace) {
  366. SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace));
  367. if (sg == null)
  368. return null;
  369. return (XSTypeDefinition)sg.fGlobalTypeDecls.get(name);
  370. }
  371. /**
  372. * Convenience method. Returns a top-level attribute declaration.
  373. * @param name The name of the declaration.
  374. * @param namespace The namespace of the definition, otherwise null.
  375. * @return A top-level attribute declaration or null if such declaration
  376. * does not exist.
  377. */
  378. public XSAttributeDeclaration getAttributeDeclaration(String name,
  379. String namespace) {
  380. SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace));
  381. if (sg == null)
  382. return null;
  383. return (XSAttributeDeclaration)sg.fGlobalAttrDecls.get(name);
  384. }
  385. /**
  386. * Convenience method. Returns a top-level element declaration.
  387. * @param name The name of the declaration.
  388. * @param namespace The namespace of the definition, otherwise null.
  389. * @return A top-level element declaration or null if such declaration
  390. * does not exist.
  391. */
  392. public XSElementDeclaration getElementDeclaration(String name,
  393. String namespace) {
  394. SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace));
  395. if (sg == null)
  396. return null;
  397. return (XSElementDeclaration)sg.fGlobalElemDecls.get(name);
  398. }
  399. /**
  400. * Convenience method. Returns a top-level attribute group definition.
  401. * @param name The name of the definition.
  402. * @param namespace The namespace of the definition, otherwise null.
  403. * @return A top-level attribute group definition or null if such
  404. * definition does not exist.
  405. */
  406. public XSAttributeGroupDefinition getAttributeGroup(String name,
  407. String namespace) {
  408. SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace));
  409. if (sg == null)
  410. return null;
  411. return (XSAttributeGroupDefinition)sg.fGlobalAttrGrpDecls.get(name);
  412. }
  413. /**
  414. * Convenience method. Returns a top-level model group definition.
  415. *
  416. * @param name The name of the definition.
  417. * @param namespace The namespace of the definition, otherwise null.
  418. * @return A top-level model group definition definition or null if such
  419. * definition does not exist.
  420. */
  421. public XSModelGroupDefinition getModelGroupDefinition(String name,
  422. String namespace) {
  423. SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace));
  424. if (sg == null)
  425. return null;
  426. return (XSModelGroupDefinition)sg.fGlobalGroupDecls.get(name);
  427. }
  428. /**
  429. * @see com.sun.org.apache.xerces.internal.xs.XSModel#getNotationDeclaration(String, String)
  430. */
  431. public XSNotationDeclaration getNotationDeclaration(String name,
  432. String namespace) {
  433. SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace));
  434. if (sg == null)
  435. return null;
  436. return (XSNotationDeclaration)sg.fGlobalNotationDecls.get(name);
  437. }
  438. /**
  439. * {annotations} A set of annotations.
  440. */
  441. public synchronized XSObjectList getAnnotations() {
  442. if(fAnnotations != null)
  443. return fAnnotations;
  444. // do this in two passes to avoid inaccurate array size
  445. int totalAnnotations = 0;
  446. for (int i = 0; i < fGrammarCount; i++) {
  447. totalAnnotations += fGrammarList[i].fNumAnnotations;
  448. }
  449. XSAnnotationImpl [] annotations = new XSAnnotationImpl [totalAnnotations];
  450. int currPos = 0;
  451. for (int i = 0; i < fGrammarCount; i++) {
  452. SchemaGrammar currGrammar = fGrammarList[i];
  453. System.arraycopy(currGrammar.fAnnotations, 0, annotations, currPos, currGrammar.fNumAnnotations);
  454. currPos += currGrammar.fNumAnnotations;
  455. }
  456. fAnnotations = new XSObjectListImpl(annotations, annotations.length);
  457. return fAnnotations;
  458. }
  459. private static final String null2EmptyString(String str) {
  460. return str == null ? XMLSymbols.EMPTY_STRING : str;
  461. }
  462. /**
  463. * REVISIT: to expose identity constraints from XSModel.
  464. * For now, we only expose whether there are any IDCs.
  465. * We also need to add these methods to the public
  466. * XSModel interface.
  467. */
  468. public boolean hasIDConstraints() {
  469. return fHasIDC;
  470. }
  471. /**
  472. * REVISIT: to expose substitution group of a given element.
  473. * We need to add this to the XSModel interface.
  474. */
  475. public XSObjectList getSubstitutionGroup(XSElementDeclaration head) {
  476. return (XSObjectList)fSubGroupMap.get(head);
  477. }
  478. } // class XSModelImpl