001: /*
002: * Copyright 2004-2006 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.compass.core.util.config;
018:
019: import java.io.Serializable;
020: import java.util.ArrayList;
021: import java.util.HashMap;
022:
023: import org.compass.core.config.ConfigurationException;
024:
025: /**
026: * This is the default <code>ConfigurationHelper</code> implementation.
027: */
028: public class XmlConfigurationHelper extends AbstractConfigurationHelper
029: implements ConfigurationHelper, Serializable {
030:
031: private static final long serialVersionUID = 3546076943545219376L;
032:
033: /**
034: * An empty (length zero) array of configuration objects.
035: */
036: protected static final ConfigurationHelper[] EMPTY_ARRAY = new ConfigurationHelper[0];
037:
038: private final String m_name;
039:
040: private final String m_location;
041:
042: private final String m_namespace;
043:
044: private final String m_prefix;
045:
046: private HashMap m_attributes;
047:
048: private ArrayList m_children;
049:
050: private String m_value;
051:
052: private boolean m_readOnly;
053:
054: /**
055: * Shallow copy constructor, suitable for craeting a writable clone of a
056: * read-only configuration. To modify children, use <code>getChild()</code>,
057: * <code>removeChild()</code> and <code>addChild()</code>.
058: */
059: public XmlConfigurationHelper(ConfigurationHelper config)
060: throws ConfigurationException {
061: this (
062: config.getName(),
063: config.getLocation(),
064: config.getNamespace(),
065: ((config instanceof AbstractConfigurationHelper) ? ((AbstractConfigurationHelper) config)
066: .getPrefix()
067: : ""));
068: addAll(config);
069: }
070:
071: /**
072: * Create a new <code>DefaultConfiguration</code> instance.
073: */
074: public XmlConfigurationHelper(final String name) {
075: this (name, null, "", "");
076: }
077:
078: /**
079: * Create a new <code>DefaultConfiguration</code> instance.
080: */
081: public XmlConfigurationHelper(final String name,
082: final String location) {
083: this (name, location, "", "");
084: }
085:
086: /**
087: * Create a new <code>DefaultConfiguration</code> instance.
088: */
089: public XmlConfigurationHelper(final String name,
090: final String location, final String ns, final String prefix) {
091: m_name = name;
092: m_location = location;
093: m_namespace = ns;
094: m_prefix = prefix; // only used as a serialization hint. Cannot be null
095: }
096:
097: /**
098: * Returns the name of this configuration element.
099: */
100: public String getName() {
101: return m_name;
102: }
103:
104: /**
105: * Returns the namespace of this configuration element
106: */
107: public String getNamespace() throws ConfigurationException {
108: if (null != m_namespace) {
109: return m_namespace;
110: } else {
111: throw new ConfigurationException(
112: "No namespace (not even default \"\") is associated with the "
113: + "configuration element \"" + getName()
114: + "\" at " + getLocation());
115: }
116: }
117:
118: /**
119: * Returns the prefix of the namespace
120: */
121: protected String getPrefix() throws ConfigurationException {
122: if (null != m_prefix) {
123: return m_prefix;
124: } else {
125: throw new ConfigurationException(
126: "No prefix (not even default \"\") is associated with the "
127: + "configuration element \"" + getName()
128: + "\" at " + getLocation());
129: }
130: }
131:
132: /**
133: * Returns a description of location of element.
134: */
135: public String getLocation() {
136: return m_location;
137: }
138:
139: /**
140: * Returns the value of the configuration element as a <code>String</code>.
141: */
142: public String getValue(final String defaultValue) {
143: if (null != m_value) {
144: return m_value;
145: } else {
146: return defaultValue;
147: }
148: }
149:
150: /**
151: * Returns the value of the configuration element as a <code>String</code>.
152: */
153: public String getValue() throws ConfigurationException {
154: if (null != m_value) {
155: return m_value;
156: } else {
157: throw new ConfigurationException(
158: "No value is associated with the "
159: + "configuration element \"" + getName()
160: + "\" at " + getLocation());
161: }
162: }
163:
164: /**
165: * Return an array of all attribute names.
166: */
167: public String[] getAttributeNames() {
168: if (null == m_attributes) {
169: return new String[0];
170: } else {
171: return (String[]) m_attributes.keySet().toArray(
172: new String[0]);
173: }
174: }
175:
176: /**
177: * Return an array of <code>Configuration</code> elements containing all
178: * node children.
179: */
180: public ConfigurationHelper[] getChildren() {
181: if (null == m_children) {
182: return new ConfigurationHelper[0];
183: } else {
184: return (ConfigurationHelper[]) m_children
185: .toArray(new ConfigurationHelper[0]);
186: }
187: }
188:
189: /**
190: * Returns the value of the attribute specified by its name as a
191: * <code>String</code>.
192: */
193: public String getAttribute(final String name)
194: throws ConfigurationException {
195: final String value = (null != m_attributes) ? (String) m_attributes
196: .get(name)
197: : null;
198: if (null != value) {
199: return value;
200: } else {
201: throw new ConfigurationException("No attribute named \""
202: + name + "\" is "
203: + "associated with the configuration element \""
204: + getName() + "\" at " + getLocation());
205: }
206: }
207:
208: /**
209: * Return the first <code>Configuration</code> object child of this
210: * associated with the given name.
211: */
212: public ConfigurationHelper getChild(final String name,
213: final boolean createNew) {
214: if (null != m_children) {
215: final int size = m_children.size();
216: for (int i = 0; i < size; i++) {
217: final ConfigurationHelper configuration = (ConfigurationHelper) m_children
218: .get(i);
219: if (name.equals(configuration.getName())) {
220: return configuration;
221: }
222: }
223: }
224: if (createNew) {
225: return new XmlConfigurationHelper(name, "<generated>"
226: + getLocation(), m_namespace, m_prefix);
227: } else {
228: return null;
229: }
230: }
231:
232: /**
233: * Return an array of <code>Configuration</code> objects children of this
234: * associated with the given name. <br>
235: * The returned array may be empty but is never <code>null</code>.
236: */
237: public ConfigurationHelper[] getChildren(final String name) {
238: if (null == m_children) {
239: return new ConfigurationHelper[0];
240: } else {
241: final ArrayList children = new ArrayList();
242: final int size = m_children.size();
243: for (int i = 0; i < size; i++) {
244: final ConfigurationHelper configuration = (ConfigurationHelper) m_children
245: .get(i);
246: if (name.equals(configuration.getName())) {
247: children.add(configuration);
248: }
249: }
250: return (ConfigurationHelper[]) children
251: .toArray(new ConfigurationHelper[0]);
252: }
253: }
254:
255: /**
256: * Set the value of this <code>Configuration</code> object to the
257: * specified string.
258: */
259: public void setValue(final String value) {
260: checkWriteable();
261: m_value = value;
262: }
263:
264: /**
265: * Set the value of this <code>Configuration</code> object to the
266: * specified int.
267: */
268: public void setValue(final int value) {
269: setValue(String.valueOf(value));
270: }
271:
272: /**
273: * Set the value of this <code>Configuration</code> object to the
274: * specified long.
275: */
276: public void setValue(final long value) {
277: setValue(String.valueOf(value));
278: }
279:
280: /**
281: * Set the value of this <code>Configuration</code> object to the
282: * specified boolean.
283: */
284: public void setValue(final boolean value) {
285: setValue(String.valueOf(value));
286: }
287:
288: /**
289: * Set the value of this <code>Configuration</code> object to the
290: * specified float.
291: */
292: public void setValue(final float value) {
293: setValue(String.valueOf(value));
294: }
295:
296: /**
297: * Set the value of the specified attribute to the specified string.
298: */
299: public void setAttribute(final String name, final String value) {
300: checkWriteable();
301: if (null != value) {
302: if (null == m_attributes) {
303: m_attributes = new HashMap();
304: }
305: m_attributes.put(name, value);
306: } else {
307: if (null != m_attributes) {
308: m_attributes.remove(name);
309: }
310: }
311: }
312:
313: /**
314: * Set the value of the specified attribute to the specified int.
315: */
316: public void setAttribute(final String name, final int value) {
317: setAttribute(name, String.valueOf(value));
318: }
319:
320: /**
321: * Set the value of the specified attribute to the specified long.
322: */
323: public void setAttribute(final String name, final long value) {
324: setAttribute(name, String.valueOf(value));
325: }
326:
327: /**
328: * Set the value of the specified attribute to the specified boolean.
329: */
330: public void setAttribute(final String name, final boolean value) {
331: setAttribute(name, String.valueOf(value));
332: }
333:
334: /**
335: * Set the value of the specified attribute to the specified float.
336: */
337: public void setAttribute(final String name, final float value) {
338: setAttribute(name, String.valueOf(value));
339: }
340:
341: /**
342: * Add a child <code>Configuration</code> to this configuration element.
343: */
344: public void addChild(final ConfigurationHelper configuration) {
345: checkWriteable();
346: if (null == m_children) {
347: m_children = new ArrayList();
348: }
349: m_children.add(configuration);
350: }
351:
352: /**
353: * Add all the attributes, children and value from specified configuration
354: * element to current configuration element.
355: */
356: public void addAll(final ConfigurationHelper other) {
357: checkWriteable();
358: setValue(other.getValue(null));
359: addAllAttributes(other);
360: addAllChildren(other);
361: }
362:
363: /**
364: * Add all attributes from specified configuration element to current
365: * configuration element.
366: */
367: public void addAllAttributes(final ConfigurationHelper other) {
368: checkWriteable();
369: final String[] attributes = other.getAttributeNames();
370: for (int i = 0; i < attributes.length; i++) {
371: final String name = attributes[i];
372: final String value = other.getAttribute(name, null);
373: setAttribute(name, value);
374: }
375: }
376:
377: /**
378: * Add all child <code>Configuration</code> objects from specified
379: * configuration element to current configuration element.
380: */
381: public void addAllChildren(final ConfigurationHelper other) {
382: checkWriteable();
383: final ConfigurationHelper[] children = other.getChildren();
384: for (int i = 0; i < children.length; i++) {
385: addChild(children[i]);
386: }
387: }
388:
389: /**
390: * Add all child <code>Configuration</code> objects from specified
391: * configuration element to current configuration element.
392: */
393: public void addAllChildrenBefore(final ConfigurationHelper other) {
394: checkWriteable();
395: final ConfigurationHelper[] children = other.getChildren();
396: if (null == m_children) {
397: m_children = new ArrayList();
398: }
399: for (int i = children.length - 1; i >= 0; i--) {
400: m_children.add(0, children[i]);
401: }
402: }
403:
404: /**
405: * Remove a child <code>Configuration</code> to this configuration
406: * element.
407: */
408: public void removeChild(final ConfigurationHelper configuration) {
409: checkWriteable();
410: if (null == m_children) {
411: return;
412: }
413: m_children.remove(configuration);
414: }
415:
416: /**
417: * Return count of children.
418: */
419: public int getChildCount() {
420: if (null == m_children) {
421: return 0;
422: }
423: return m_children.size();
424: }
425:
426: /**
427: * Make this configuration read-only.
428: */
429: public void makeReadOnly() {
430: m_readOnly = true;
431: }
432:
433: /**
434: * heck if this configuration is writeable.
435: */
436: protected final void checkWriteable() throws IllegalStateException {
437: if (m_readOnly) {
438: throw new IllegalStateException(
439: "Configuration is read only and can not be modified");
440: }
441: }
442:
443: /**
444: * Returns true iff this DefaultConfiguration has been made read-only.
445: */
446: protected final boolean isReadOnly() {
447: return m_readOnly;
448: }
449:
450: /**
451: * Compare if this configuration is equal to another.
452: */
453: public boolean equals(Object other) {
454: if (other == null)
455: return false;
456: if (!(other instanceof ConfigurationHelper))
457: return false;
458: return ConfigurationHelperUtil.equals(this ,
459: (ConfigurationHelper) other);
460: }
461:
462: /**
463: * Obtaine the hashcode for this configuration.
464: */
465: public int hashCode() {
466: int hash = m_prefix.hashCode();
467: if (m_name != null)
468: hash ^= m_name.hashCode();
469: hash >>>= 7;
470: if (m_location != null)
471: hash ^= m_location.hashCode();
472: hash >>>= 7;
473: if (m_namespace != null)
474: hash ^= m_namespace.hashCode();
475: hash >>>= 7;
476: if (m_attributes != null)
477: hash ^= m_attributes.hashCode();
478: hash >>>= 7;
479: if (m_children != null)
480: hash ^= m_children.hashCode();
481: hash >>>= 7;
482: if (m_value != null)
483: hash ^= m_value.hashCode();
484: hash >>>= 7;
485: hash ^= (m_readOnly) ? 1 : 3;
486: return hash;
487: }
488: }
|