OSDN Git Service

Implement (but @hide) java.text.Normalizer from Java 6.
[android-x86/dalvik.git] / libcore / xml / src / main / java / org / apache / harmony / xml / dom / DOMConfigurationImpl.java
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.apache.harmony.xml.dom;
18
19 import org.w3c.dom.DOMConfiguration;
20 import org.w3c.dom.DOMErrorHandler;
21 import org.w3c.dom.DOMException;
22 import org.w3c.dom.DOMStringList;
23
24 import java.util.Map;
25 import java.util.TreeMap;
26
27 /**
28  * A minimal implementation of DOMConfiguration. This implementation uses inner
29  * parameter instances to centralize each parameter's behaviour.
30  */
31 public final class DOMConfigurationImpl implements DOMConfiguration {
32
33     private static final Map<String, Parameter> PARAMETERS
34             = new TreeMap<String, Parameter>(String.CASE_INSENSITIVE_ORDER);
35
36     static {
37         /*
38          * True to canonicalize the document (unsupported). This includes
39          * removing DocumentType nodes from the tree and removing unused
40          * namespace declarations. Setting this to true also sets these
41          * parameters:
42          *   entities = false
43          *   normalize-characters = false
44          *   cdata-sections = false
45          *   namespaces = true
46          *   namespace-declarations = true
47          *   well-formed = true
48          *   element-content-whitespace = true
49          * Setting these parameters to another value shall revert the canonical
50          * form to false.
51          */
52         PARAMETERS.put("canonical-form", new FixedParameter(false));
53
54         /*
55          * True to keep existing CDATA nodes; false to replace them/merge them
56          * into adjacent text nodes.
57          */
58         PARAMETERS.put("cdata-sections", new BooleanParameter() {
59             public Object get(DOMConfigurationImpl config) {
60                 return config.cdataSections;
61             }
62             public void set(DOMConfigurationImpl config, Object value) {
63                 config.cdataSections = (Boolean) value;
64             }
65         });
66
67         /*
68          * True to check character normalization (unsupported).
69          */
70         PARAMETERS.put("check-character-normalization", new FixedParameter(false));
71
72         /*
73          * True to keep comments in the document; false to discard them.
74          */
75         PARAMETERS.put("comments", new BooleanParameter() {
76             public Object get(DOMConfigurationImpl config) {
77                 return config.comments;
78             }
79             public void set(DOMConfigurationImpl config, Object value) {
80                 config.comments = (Boolean) value;
81             }
82         });
83
84         /*
85          * True to expose schema normalized values. Setting this to true sets
86          * the validate parameter to true. Has no effect when validate is false.
87          */
88         PARAMETERS.put("datatype-normalization", new BooleanParameter() {
89             public Object get(DOMConfigurationImpl config) {
90                 return config.datatypeNormalization;
91             }
92             public void set(DOMConfigurationImpl config, Object value) {
93                 if ((Boolean) value) {
94                     config.datatypeNormalization = true;
95                     config.validate = true;
96                 } else {
97                     config.datatypeNormalization = false;
98                 }
99             }
100         });
101
102         /*
103          * True to keep whitespace elements in the document; false to discard
104          * them (unsupported).
105          */
106         PARAMETERS.put("element-content-whitespace", new FixedParameter(true));
107
108         /*
109          * True to keep entity references in the document; false to expand them.
110          */
111         PARAMETERS.put("entities", new BooleanParameter() {
112             public Object get(DOMConfigurationImpl config) {
113                 return config.entities;
114             }
115             public void set(DOMConfigurationImpl config, Object value) {
116                 config.entities = (Boolean) value;
117             }
118         });
119
120         /*
121          * Handler to be invoked when errors are encountered.
122          */
123         PARAMETERS.put("error-handler", new Parameter() {
124             public Object get(DOMConfigurationImpl config) {
125                 return config.errorHandler;
126             }
127             public void set(DOMConfigurationImpl config, Object value) {
128                 config.errorHandler = (DOMErrorHandler) value;
129             }
130             public boolean canSet(DOMConfigurationImpl config, Object value) {
131                 return value == null || value instanceof DOMErrorHandler;
132             }
133         });
134
135         /*
136          * Bulk alias to set the following parameter values:
137          *   validate-if-schema = false
138          *   entities = false
139          *   datatype-normalization = false
140          *   cdata-sections = false
141          *   namespace-declarations = true
142          *   well-formed = true
143          *   element-content-whitespace = true
144          *   comments = true
145          *   namespaces = true.
146          * Querying this returns true if all of the above parameters have the
147          * listed values; false otherwise.
148          */
149         PARAMETERS.put("infoset", new BooleanParameter() {
150             public Object get(DOMConfigurationImpl config) {
151                 // validate-if-schema is always false
152                 // element-content-whitespace is always true
153                 // namespace-declarations is always true
154                 return !config.entities
155                         && !config.datatypeNormalization
156                         && !config.cdataSections
157                         && config.wellFormed
158                         && config.comments
159                         && config.namespaces;
160             }
161             public void set(DOMConfigurationImpl config, Object value) {
162                 if ((Boolean) value) {
163                     // validate-if-schema is always false
164                     // element-content-whitespace is always true
165                     // namespace-declarations is always true
166                     config.entities = false;
167                     config.datatypeNormalization = false;
168                     config.cdataSections = false;
169                     config.wellFormed = true;
170                     config.comments = true;
171                     config.namespaces = true;
172                 }
173             }
174         });
175
176         /*
177          * True to perform namespace processing; false for none.
178          */
179         PARAMETERS.put("namespaces", new BooleanParameter() {
180             public Object get(DOMConfigurationImpl config) {
181                 return config.namespaces;
182             }
183             public void set(DOMConfigurationImpl config, Object value) {
184                 config.namespaces = (Boolean) value;
185             }
186         });
187
188         /**
189          * True to include namespace declarations; false to discard them
190          * (unsupported). Even when namespace declarations are discarded,
191          * prefixes are retained.
192          *
193          * Has no effect if namespaces is false.
194          */
195         PARAMETERS.put("namespace-declarations", new FixedParameter(true));
196
197         /*
198          * True to fully normalize characters (unsupported).
199          */
200         PARAMETERS.put("normalize-characters", new FixedParameter(false));
201
202         /*
203          * A list of whitespace-separated URIs representing the schemas to validate
204          * against. Has no effect if schema-type is null.
205          */
206         PARAMETERS.put("schema-location", new Parameter() {
207             public Object get(DOMConfigurationImpl config) {
208                 return config.schemaLocation;
209             }
210             public void set(DOMConfigurationImpl config, Object value) {
211                 config.schemaLocation = (String) value;
212             }
213             public boolean canSet(DOMConfigurationImpl config, Object value) {
214                 return value == null || value instanceof String;
215             }
216         });
217
218         /*
219          * URI representing the type of schema language, such as
220          * "http://www.w3.org/2001/XMLSchema" or "http://www.w3.org/TR/REC-xml".
221          */
222         PARAMETERS.put("schema-type", new Parameter() {
223             public Object get(DOMConfigurationImpl config) {
224                 return config.schemaType;
225             }
226             public void set(DOMConfigurationImpl config, Object value) {
227                 config.schemaType = (String) value;
228             }
229             public boolean canSet(DOMConfigurationImpl config, Object value) {
230                 return value == null || value instanceof String;
231             }
232         });
233
234         /*
235          * True to split CDATA sections containing "]]>"; false to signal an
236          * error instead.
237          */
238         PARAMETERS.put("split-cdata-sections", new BooleanParameter() {
239             public Object get(DOMConfigurationImpl config) {
240                 return config.splitCdataSections;
241             }
242             public void set(DOMConfigurationImpl config, Object value) {
243                 config.splitCdataSections = (Boolean) value;
244             }
245         });
246
247         /*
248          * True to require validation against a schema or DTD. Validation will
249          * recompute element content whitespace, ID and schema type data.
250          *
251          * Setting this unsets validate-if-schema.
252          */
253         PARAMETERS.put("validate", new BooleanParameter() {
254             public Object get(DOMConfigurationImpl config) {
255                 return config.validate;
256             }
257             public void set(DOMConfigurationImpl config, Object value) {
258                 // validate-if-schema is always false
259                 config.validate = (Boolean) value;
260             }
261         });
262
263         /*
264          * True to validate if a schema was declared (unsupported). Setting this
265          * unsets validate.
266          */
267         PARAMETERS.put("validate-if-schema", new FixedParameter(false));
268
269         /*
270          * True to report invalid characters in node names, attributes, elements,
271          * comments, text, CDATA sections and processing instructions.
272          */
273         PARAMETERS.put("well-formed", new BooleanParameter() {
274             public Object get(DOMConfigurationImpl config) {
275                 return config.wellFormed;
276             }
277             public void set(DOMConfigurationImpl config, Object value) {
278                 config.wellFormed = (Boolean) value;
279             }
280         });
281
282         // TODO add "resource-resolver" property for use with LS feature...
283     }
284
285     private boolean cdataSections = true;
286     private boolean comments = true;
287     private boolean datatypeNormalization = false;
288     private boolean entities = true;
289     private DOMErrorHandler errorHandler;
290     private boolean namespaces = true;
291     private String schemaLocation;
292     private String schemaType;
293     private boolean splitCdataSections = true;
294     private boolean validate = false;
295     private boolean wellFormed = true;
296
297     interface Parameter {
298         Object get(DOMConfigurationImpl config);
299         void set(DOMConfigurationImpl config, Object value);
300         boolean canSet(DOMConfigurationImpl config, Object value);
301     }
302
303     static class FixedParameter implements Parameter {
304         final Object onlyValue;
305         FixedParameter(Object onlyValue) {
306             this.onlyValue = onlyValue;
307         }
308         public Object get(DOMConfigurationImpl config) {
309             return onlyValue;
310         }
311         public void set(DOMConfigurationImpl config, Object value) {
312             if (!onlyValue.equals(value)) {
313                 throw new DOMException(DOMException.NOT_SUPPORTED_ERR,
314                         "Unsupported value: " + value);
315             }
316         }
317         public boolean canSet(DOMConfigurationImpl config, Object value) {
318             return onlyValue.equals(value);
319         }
320     }
321
322     static abstract class BooleanParameter implements Parameter {
323         public boolean canSet(DOMConfigurationImpl config, Object value) {
324             return value instanceof Boolean;
325         }
326     }
327
328     public boolean canSetParameter(String name, Object value) {
329         Parameter parameter = PARAMETERS.get(name);
330         return parameter != null && parameter.canSet(this, value);
331     }
332
333     public void setParameter(String name, Object value) throws DOMException {
334         Parameter parameter = PARAMETERS.get(name);
335         if (parameter == null) {
336             throw new DOMException(DOMException.NOT_FOUND_ERR, "No such parameter: " + name);
337         }
338         try {
339             parameter.set(this, value);
340         } catch (NullPointerException e) {
341             throw new DOMException(DOMException.TYPE_MISMATCH_ERR,
342                     "Null not allowed for " + name);
343         } catch (ClassCastException e) {
344             throw new DOMException(DOMException.TYPE_MISMATCH_ERR,
345                     "Invalid type for " + name + ": " + value.getClass());
346         }
347     }
348
349     public Object getParameter(String name) throws DOMException {
350         Parameter parameter = PARAMETERS.get(name);
351         if (parameter == null) {
352             throw new DOMException(DOMException.NOT_FOUND_ERR, "No such parameter: " + name);
353         }
354         return parameter.get(this);
355     }
356
357     public DOMStringList getParameterNames() {
358         final String[] result = PARAMETERS.keySet().toArray(new String[PARAMETERS.size()]);
359         return new DOMStringList() {
360             public String item(int index) {
361                 return index < result.length ? result[index] : null;
362             }
363             public int getLength() {
364                 return result.length;
365             }
366             public boolean contains(String str) {
367                 return PARAMETERS.containsKey(str); // case-insensitive.
368             }
369         };
370     }
371 }