001: /*
002: * <copyright>
003: *
004: * Copyright 1997-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026:
027: package org.cougaar.util;
028:
029: import java.io.Serializable;
030: import java.util.ArrayList;
031: import java.util.Collection;
032: import java.util.List;
033: import java.util.Map;
034:
035: /**
036: * A PropertyTree is an <code>ArrayMap</code> that limits it's keys to
037: * <code>String</code>s and it's values to:<ol>
038: * <li>null</li>
039: * <li>String</li>
040: * <li>wrapped Java primitive (Integer, Boolean, etc)</li>
041: * <li>another PropertyTree</li>
042: * <li>a Serializable Collection of elements, each element matching
043: * one of the above criterion</li>
044: * </ol>.
045: *
046: * An ArrayMap is a <code>java.util.Map</code>, and can be used exactly
047: * like a typical Map. The most significant differences are that<ol>
048: * <li>The elements are kept in the order that they are added.</li>
049: * <li>One can restrict the (key, value) types.</li>
050: * <li>There are index-based "getters", such as <tt>getKey(int)</tt>.
051: * </ol>
052: *
053: * @see ArrayMap
054: */
055: public class PropertyTree extends ArrayMap {
056:
057: //
058: // constructors
059: //
060:
061: public PropertyTree(int initialCapacity) {
062: super (initialCapacity);
063: }
064:
065: public PropertyTree() {
066: super (10);
067: }
068:
069: public PropertyTree(Map t) {
070: super (t);
071: }
072:
073: //
074: // maybe add some new "NS"-like directory methods
075: //
076:
077: //
078: // keep all the Map methods
079: //
080:
081: /**
082: * Override entries to be <code>PropertyTree.PropertyTreeEntry</code>.
083: *
084: * @see PropertyTree.PropertyTreeEntry
085: */
086: protected Map.Entry createEntry(final Object key, final Object value) {
087: return new PropertyTreeEntry(key, value);
088: }
089:
090: /**
091: * Force keys to be non-null <code>String</code>s
092: * and values to be one of:<ol>
093: * <li>null</li>
094: * <li>String</li>
095: * <li>wrapped Java primitive (Integer, Boolean, etc)</li>
096: * <li>another PropertyTree</li>
097: * <li>a Serializable Collection of elements, each element matching
098: * one of the above criterion</li>
099: * </ol>.
100: */
101: protected static class PropertyTreeEntry extends
102: ArrayMap.ArrayEntry {
103:
104: public PropertyTreeEntry(final Object key, final Object value) {
105: super (key, value);
106: assertIsValidKey(key);
107: assertIsValidValue(value);
108: }
109:
110: public Object setValue(final Object newValue) {
111: assertIsValidValue(newValue);
112: return super .setValue(newValue);
113: }
114:
115: /**
116: * Valid PropertyTree "keys" must be non-null Strings.
117: *
118: * @throws IllegalArgumentException
119: */
120: private static final void assertIsValidKey(final Object key) {
121: if (key instanceof String) {
122: // valid
123: } else {
124: throw new IllegalArgumentException(
125: "PropertyTree \"key\" must be a non-null String, not "
126: + ((key != null) ? key.getClass()
127: .getName() : "null"));
128: }
129: }
130:
131: /**
132: * Valid PropertyTree "values" are:<ol>
133: * <li>null</li>
134: * <li>String</li>
135: * <li>wrapped Java primitive (Integer, Boolean, etc)</li>
136: * <li>another PropertyTree</li>
137: * <li>a Serializable Collection of elements, each element matching
138: * one of the above criterion</li>
139: * </ol>.
140: *
141: * @throws IllegalArgumentException if not <tt>isValidValue(value)</tt>.
142: */
143: private static final void assertIsValidValue(final Object value) {
144: if ((value == null)
145: || (value instanceof String)
146: || (value instanceof PropertyTree)
147: || ((value instanceof Collection) && (value instanceof Serializable))
148: || (ArrayMap.isWrappedPrimitive(value))) {
149: // valid
150: } else {
151: throw new IllegalArgumentException(
152: "PropertyTree \"value\" of illegal type: "
153: + value.getClass().getName());
154: }
155: }
156:
157: }
158:
159: private static final long serialVersionUID = 182883718294610011L;
160: }
|