001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.xerces.impl.xs;
019:
020: import java.util.Hashtable;
021: import java.util.Enumeration;
022: import java.util.Vector;
023:
024: /**
025: * A class used to hold the internal schema grammar set for the current instance
026: *
027: * @xerces.internal
028: *
029: * @author Sandy Gao, IBM
030: * @version $Id: XSGrammarBucket.java 446734 2006-09-15 20:51:23Z mrglavas $
031: */
032: public class XSGrammarBucket {
033:
034: // Data
035:
036: /**
037: * Hashtable that maps between Namespace and a Grammar
038: */
039: Hashtable fGrammarRegistry = new Hashtable();
040: SchemaGrammar fNoNSGrammar = null;
041:
042: /**
043: * Get the schema grammar for the specified namespace
044: *
045: * @param namespace
046: * @return SchemaGrammar associated with the namespace
047: */
048: public SchemaGrammar getGrammar(String namespace) {
049: if (namespace == null)
050: return fNoNSGrammar;
051: return (SchemaGrammar) fGrammarRegistry.get(namespace);
052: }
053:
054: /**
055: * Put a schema grammar into the registry
056: * This method is for internal use only: it assumes that a grammar with
057: * the same target namespace is not already in the bucket.
058: *
059: * @param grammar the grammar to put in the registry
060: */
061: public void putGrammar(SchemaGrammar grammar) {
062: if (grammar.getTargetNamespace() == null)
063: fNoNSGrammar = grammar;
064: else
065: fGrammarRegistry.put(grammar.getTargetNamespace(), grammar);
066: }
067:
068: /**
069: * put a schema grammar and any grammars imported by it (directly or
070: * inderectly) into the registry. when a grammar with the same target
071: * namespace is already in the bucket, and different from the one being
072: * added, it's an error, and no grammar will be added into the bucket.
073: *
074: * @param grammar the grammar to put in the registry
075: * @param deep whether to add imported grammars
076: * @return whether the process succeeded
077: */
078: public boolean putGrammar(SchemaGrammar grammar, boolean deep) {
079: // whether there is one with the same tns
080: SchemaGrammar sg = getGrammar(grammar.fTargetNamespace);
081: if (sg != null) {
082: // if the one we have is different from the one passed, it's an error
083: return sg == grammar;
084: }
085: // not deep import, then just add this one grammar
086: if (!deep) {
087: putGrammar(grammar);
088: return true;
089: }
090:
091: // get all imported grammars, and make a copy of the Vector, so that
092: // we can recursively process the grammars, and add distinct ones
093: // to the same vector
094: Vector currGrammars = (Vector) grammar.getImportedGrammars();
095: if (currGrammars == null) {
096: putGrammar(grammar);
097: return true;
098: }
099:
100: Vector grammars = ((Vector) currGrammars.clone());
101: SchemaGrammar sg1, sg2;
102: Vector gs;
103: // for all (recursively) imported grammars
104: for (int i = 0; i < grammars.size(); i++) {
105: // get the grammar
106: sg1 = (SchemaGrammar) grammars.elementAt(i);
107: // check whether the bucket has one with the same tns
108: sg2 = getGrammar(sg1.fTargetNamespace);
109: if (sg2 == null) {
110: // we need to add grammars imported by sg1 too
111: gs = sg1.getImportedGrammars();
112: // for all grammars imported by sg2, but not in the vector
113: // we add them to the vector
114: if (gs == null)
115: continue;
116: for (int j = gs.size() - 1; j >= 0; j--) {
117: sg2 = (SchemaGrammar) gs.elementAt(j);
118: if (!grammars.contains(sg2))
119: grammars.addElement(sg2);
120: }
121: }
122: // we found one with the same target namespace
123: // if the two grammars are not the same object, then it's an error
124: else if (sg2 != sg1) {
125: return false;
126: }
127: }
128:
129: // now we have all imported grammars stored in the vector. add them
130: putGrammar(grammar);
131: for (int i = grammars.size() - 1; i >= 0; i--)
132: putGrammar((SchemaGrammar) grammars.elementAt(i));
133:
134: return true;
135: }
136:
137: /**
138: * get all grammars in the registry
139: *
140: * @return an array of SchemaGrammars.
141: */
142: public SchemaGrammar[] getGrammars() {
143: // get the number of grammars
144: int count = fGrammarRegistry.size()
145: + (fNoNSGrammar == null ? 0 : 1);
146: SchemaGrammar[] grammars = new SchemaGrammar[count];
147: // get grammars with target namespace
148: Enumeration schemas = fGrammarRegistry.elements();
149: int i = 0;
150: while (schemas.hasMoreElements())
151: grammars[i++] = (SchemaGrammar) schemas.nextElement();
152: // add the grammar without target namespace, if any
153: if (fNoNSGrammar != null)
154: grammars[count - 1] = fNoNSGrammar;
155: return grammars;
156: }
157:
158: /**
159: * Clear the registry.
160: * REVISIT: update to use another XSGrammarBucket
161: */
162: public void reset() {
163: fNoNSGrammar = null;
164: fGrammarRegistry.clear();
165: }
166:
167: } // class XSGrammarBucket
|