DOMConfigurationImpl.java revision 21d27c095fee51fd6eac6a68d50b79df4dc97d85
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 17package org.apache.harmony.xml.dom; 18 19import org.w3c.dom.DOMConfiguration; 20import org.w3c.dom.DOMErrorHandler; 21import org.w3c.dom.DOMException; 22import org.w3c.dom.DOMStringList; 23 24import java.util.Map; 25import 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 */ 31public 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} 372