001: /* Registry.java */
002:
003: package org.quilt.reg;
004:
005: import java.util.*;
006:
007: /**
008: * <p>A registry for storing Quilt run-time options. The registry
009: * stores key-value pairs, where the key takes the form of an array
010: * of Strings. The registry is sorted, but XXX there is currently
011: * no support for sequential access or partial-key access.</p>
012: *
013: * <p>This class is not thread-safe.</p>
014: *
015: * @author <a href="jddixon@users.sourceforge.net">Jim Dixon</a>
016: */
017:
018: public class Registry {
019:
020: // PRIVATE VARIABLES, CLASS, AND CONSTRUCTOR ////////////////////
021:
022: private SortedMap registry = null; // key = String[], value = Object
023:
024: /** Comparator for String arrays. */
025: private class CmpArrays implements Comparator {
026: /**
027: * Compare String arrays. The arrays are compared element
028: * by element starting at [0]. If any such pair differ,
029: * then the result of the String comparison is returned.
030: * If they match up to and including the last element of the
031: * shorter array of the two, then the shorter is deemed to sort
032: * before the longer. The two arrays are equal if and only if
033: * they have the same number of elements and each pair of
034: * elements is equal.
035: *
036: * @param o1 First String array.
037: * @param o2 Second.
038: * @return -1 if o1 < o2, 0 if o1 == o2, 1 if o1 > o2
039: */
040: public int compare(final Object o1, final Object o2) {
041: String str1[] = (String[]) o1;
042: String str2[] = (String[]) o2;
043: int depth1 = str1.length; // number of elements in array
044: int depth2 = str2.length;
045: int depth = (depth1 < depth2) ? depth1 : depth2;
046:
047: int i;
048: for (i = 0; i < depth; i++) {
049: int rel = str1[i].compareTo(str2[i]);
050: if (rel < 0) {
051: return -1;
052: } else if (rel > 0) {
053: return 1;
054: }
055: // otherwise equal, so continue
056: }
057: // the first n == depth strings are the same
058: if (depth1 < depth2) {
059: return -1; // shorter
060: } else if (depth1 > depth2) {
061: return 1; // longer
062: }
063: // depth1 == depth2
064: return 0; // a perfect match
065: }
066: }
067:
068: /** No-arg constructor. */
069: public Registry() {
070: registry = new TreeMap(new CmpArrays());
071: registry.clear(); // should not be necessary, doesn't solve problem
072: }
073:
074: // OTHER METHODS ////////////////////////////////////////////////
075:
076: /** Remove all elements from the registry. */
077: final public void clear() {
078: registry.clear();
079: }
080:
081: /** Return comparator used in sorting keys. */
082: final Comparator comparator() {
083: return new CmpArrays();
084: }
085:
086: /** @return True if there is an item under this key in the registry. */
087: final public boolean containsKey(String[] key) {
088: if (key == null) {
089: throw new IllegalArgumentException("null key");
090: }
091: return registry.containsKey(key);
092: }
093:
094: /**
095: * Get an object from the registry.
096: *
097: * @param key Array of strings, the unique key.
098: * @return value Object stored under the key, or null if none.
099: */
100: final public Object get(String[] key) {
101: if (key == null) {
102: throw new IllegalArgumentException("null key");
103: }
104: if (registry.containsKey(key)) {
105: return registry.get(key);
106: } else {
107: return null;
108: }
109: }
110:
111: /** @return True if there are no elements in the registry. */
112: final public boolean isEmpty() {
113: return registry.isEmpty();
114: }
115:
116: /**
117: * XXX An overly powerful method.
118: * @todo Replace with first/next/last access.
119: * @return The (editable) set of keys.
120: */
121: public Set keySet() {
122: return registry.keySet();
123: }
124:
125: /**
126: * Add an object to the registry, overwriting any existing value.
127: *
128: * @param key Array of Strings, the unique key. Must not be null.
129: * @param value Object to be stored under this key.
130: * @return Old value if there was one, null otherwise.
131: */
132: final public Object put(String[] key, Object value) {
133: if (key == null) {
134: throw new IllegalArgumentException("null key");
135: }
136: // make a copy of the key
137: String keyCopy[] = new String[key.length];
138: for (int i = 0; i < key.length; i++) {
139: keyCopy[i] = key[i];
140: }
141: return registry.put(keyCopy, value);
142: }
143:
144: /**
145: * Remove an item from the registry.
146: *
147: * @param key Array of Strings.
148: * @return The value associated with the key, or null if none.
149: */
150: final public Object remove(String[] key) {
151: if (key == null) {
152: throw new IllegalArgumentException("null key");
153: }
154: return registry.remove(key);
155: }
156:
157: /** @return Number of items in the registry. */
158: final public int size() {
159: return registry.size();
160: }
161:
162: /**
163: * Convert a class or method name into a String array.
164: *
165: * @return A string array containing the fields of the name.
166: */
167: final public String[] splitClassName(String name) {
168: return name.split(".");
169: }
170: }
|