1
2
3
4
5
6
7
8
9
10
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? :-)");
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
89 ISchema result = schemas.get(namespaceURI);
90 if (result != null)
91 return result;
92
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
113 ISchema result = schemas.get(namespaceURI);
114 if ((result != null) || localOnly)
115 return result;
116
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
135 schema = SchemaPool.getInstance().loadSchema(namespace,
136 this);
137 }
138
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 }