View Javadoc

1   /*
2    * Copyright 1999-2006 Faculty of Mathematics, Physics and Informatics, Comenius
3    * University, Bratislava. This file is protected by the Mozilla Public License
4    * version 1.1 (the "License"); you may not use this file except in compliance
5    * with the License. You may obtain a copy of the License at
6    * http://euromath2.sourceforge.net/license.html Unless required by applicable
7    * law or agreed to in writing, software distributed under the License is
8    * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
9    * KIND, either express or implied. See the License for the specific language
10   * governing permissions and limitations under the License.
11   */
12  package sk.uniba.euromath.document.schema;
13  import java.io.IOException;
14  import java.util.ArrayList;
15  import java.util.Collection;
16  import java.util.HashMap;
17  import java.util.Iterator;
18  import java.util.Map;
19  import java.util.Set;
20  import sk.uniba.euromath.document.DomCore;
21  import sk.uniba.euromath.document.schema.plug.ISchema;
22  import sk.uniba.euromath.document.schema.plug.SchemaException;
23  import sk.uniba.euromath.tools.StringTools;
24  /***
25   * <p>
26   * Manages list of <code>Schema</code>s, one for each namespace URI, for a
27   * single document. Thread-safe. Class is not intended for subclassing nor
28   * instantiating by clients.
29   * </p>
30   * @author Martin Vysny
31   */
32  public final class SchemaReferences {
33  	/***
34  	 * Schemas that are loaded for this object. Maps <code>String</code>
35  	 * namespace to <code>Schema</code> instance. This map ensures that the
36  	 * schema doesn't get garbage-collected while document has reference to this
37  	 * object.
38  	 */
39  	private final Map<String, ISchema> schemas = new HashMap<String, ISchema>();
40  	/***
41  	 * The document.
42  	 */
43  	final DomCore doc;
44  	/***
45  	 * Constructor.
46  	 * @param doc the document.
47  	 */
48  	SchemaReferences(DomCore doc) {
49  		super();
50  		this.doc = doc;
51  	}
52  	/***
53  	 * <p>
54  	 * For given namespace URI returns appropriate <code>Schema</code> object,
55  	 * that validates elements with this namespace URI.
56  	 * </p>
57  	 * <p>
58  	 * If no local Schema for given URI exists for given document, then try to
59  	 * get appropriate global Schema (it won't attempt to load the schema if not
60  	 * present).
61  	 * </p>
62  	 * @param namespaceURI namespace URI.
63  	 * @return Schema
64  	 * @throws IllegalStateException if Schema with given URI cannot be found.
65  	 */
66  	public ISchema getSchema(String namespaceURI) {
67  		ISchema result = getSchemaNull(namespaceURI);
68  		if (result == null)
69  			throw new IllegalStateException(
70  					"The global schema is not yet loaded. You forgot to call XMLAccess.loadGlobalSchemas(), didn't you? :-)"); //$NON-NLS-1$
71  		return result;
72  	}
73  	/***
74  	 * <p>
75  	 * For given namespace URI returns appropriate <code>Schema</code> object,
76  	 * that validates elements with this namespace URI.
77  	 * </p>
78  	 * <p>
79  	 * If no local Schema for given URI exists for given document, then try to
80  	 * get appropriate global Schema (it won't attempt to load the schema if not
81  	 * present).
82  	 * </p>
83  	 * @param namespaceURI namespace URI.
84  	 * @return Schema, or <code>null</code> if no such schema has been loaded.
85  	 */
86  	public ISchema getSchemaNull(String namespaceURI) {
87  		namespaceURI = StringTools.nonNullStr(namespaceURI);
88  		// check if there is such local schema.
89  		ISchema result = schemas.get(namespaceURI);
90  		if (result != null)
91  			return result;
92  		// nope, check for global schema.
93  		return SchemaPool.getInstance().getSchemaNull(namespaceURI);
94  	}
95  	/***
96  	 * <p>
97  	 * For given namespace URI returns appropriate <code>Schema</code> object,
98  	 * that validates elements with this namespace URI.
99  	 * </p>
100 	 * <p>
101 	 * If no local Schema for given URI exists for given document, then try to
102 	 * get appropriate global Schema (it won't attempt to load the schema if not
103 	 * present).
104 	 * </p>
105 	 * @param namespaceURI namespace URI.
106 	 * @param localOnly if true then the function returns <code>null</code>
107 	 * even if there is such schema registered in main pool.
108 	 * @return Schema, or <code>null</code> if no such schema has been loaded.
109 	 */
110 	private ISchema getSchemaNull(String namespaceURI, boolean localOnly) {
111 		namespaceURI = StringTools.nonNullStr(namespaceURI);
112 		// check if there is such local schema.
113 		ISchema result = schemas.get(namespaceURI);
114 		if ((result != null) || localOnly)
115 			return result;
116 		// nope, check for global schema.
117 		return SchemaPool.getInstance().getSchemaNull(namespaceURI);
118 	}
119 	/***
120 	 * Loads schemas for all given namespaces. If the schema is already loaded
121 	 * then it is not loaded again. It must be called before the Schema
122 	 * interface is used, to ensure that all schemata are properly loaded.
123 	 * @param namespaces collection of <code>String</code> namespaces.
124 	 * @throws SchemaException if error happens during loading of schemas.
125 	 * @throws IOException if i/o error occurs during the schema files
126 	 * deserialization.
127 	 */
128 	public synchronized void loadSchemata(Collection<String> namespaces)
129 			throws SchemaException, IOException {
130 		for (String namespace : namespaces) {
131 			if (getSchemaNull(namespace, true) == null) {
132 				ISchema schema = getSchemaNull(namespace, false);
133 				if (schema == null) {
134 					// the schema is not yet loaded. Try to load it.
135 					schema = SchemaPool.getInstance().loadSchema(namespace,
136 							this);
137 				}
138 				// register the schema
139 				schemas.put(namespace, schema);
140 			}
141 		}
142 	}
143 	/***
144 	 * Removes the schema from the reference. The schema may be still present,
145 	 * but only in a pool - it is not linked to this document anymore.
146 	 * @param namespaceURI the namespace.
147 	 */
148 	public void unloadSchema(String namespaceURI) {
149 		schemas.remove(StringTools.nonNullStr(namespaceURI));
150 	}
151 	/***
152 	 * Loads schema for given namespace. If the schema is already loaded then it
153 	 * is not loaded again. It must be called before the Schema interface is
154 	 * used, to ensure that all schemata are properly loaded.
155 	 * @param namespaceURI the namespace
156 	 * @throws SchemaException if error happens during loading of schemas.
157 	 * @throws IOException if i/o error occurs during the schema files
158 	 * deserialization.
159 	 */
160 	public synchronized void loadSchema(String namespaceURI)
161 			throws SchemaException, IOException {
162 		Collection<String> list = new ArrayList<String>(1);
163 		list.add(namespaceURI);
164 		loadSchemata(list);
165 	}
166 	/***
167 	 * Determines availability of schema for the namespace.
168 	 * @param namespaceURI the namespace to check
169 	 * @return availability code.
170 	 */
171 	public SchemaAvailabilityEnum getSchemaAvailability(String namespaceURI) {
172 		ISchema result = getSchemaNull(namespaceURI, true);
173 		if (result != null)
174 			return SchemaAvailabilityEnum.BOUND;
175 		if (SchemaPool.getInstance().getSchemaNull(namespaceURI) != null)
176 			return SchemaAvailabilityEnum.LOADED;
177 		if (SchemaPool.getInstance().getKnownNamespaces()
178 				.contains(namespaceURI))
179 			return SchemaAvailabilityEnum.LOADABLE;
180 		return SchemaAvailabilityEnum.UNAVAILABLE;
181 	}
182 	/***
183 	 * Preserves only the schemas contained in the given set, but unregisters
184 	 * all other schemas.
185 	 * @param namespaces set of namespaces that shall be preserved.
186 	 */
187 	public void preserve(Set< ? extends String> namespaces) {
188 		for (Iterator<String> i = schemas.keySet().iterator(); i.hasNext();) {
189 			String ns = i.next();
190 			if (!namespaces.contains(ns))
191 				i.remove();
192 		}
193 	}
194 }