001: // ========================================================================
002: // Copyright 2004-2005 Mort Bay Consulting Pty. Ltd.
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: // http://www.apache.org/licenses/LICENSE-2.0
008: // Unless required by applicable law or agreed to in writing, software
009: // distributed under the License is distributed on an "AS IS" BASIS,
010: // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
011: // See the License for the specific language governing permissions and
012: // limitations under the License.
013: // ========================================================================
014:
015: package org.mortbay.util;
016:
017: import java.util.Arrays;
018: import java.util.HashMap;
019: import java.util.Iterator;
020: import java.util.List;
021: import java.util.Map;
022:
023: /* ------------------------------------------------------------ */
024: /** A multi valued Map.
025: * This Map specializes HashMap and provides methods
026: * that operate on multi valued items.
027: * <P>
028: * Implemented as a map of LazyList values
029: *
030: * @see LazyList
031: * @author Greg Wilkins (gregw)
032: */
033: public class MultiMap extends HashMap implements Cloneable {
034: /* ------------------------------------------------------------ */
035: /** Constructor.
036: */
037: public MultiMap() {
038: }
039:
040: /* ------------------------------------------------------------ */
041: /** Constructor.
042: * @param size Capacity of the map
043: */
044: public MultiMap(int size) {
045: super (size);
046: }
047:
048: /* ------------------------------------------------------------ */
049: /** Constructor.
050: * @param map
051: */
052: public MultiMap(Map map) {
053: super ((map.size() * 3) / 2);
054: putAll(map);
055: }
056:
057: /* ------------------------------------------------------------ */
058: /** Get multiple values.
059: * Single valued entries are converted to singleton lists.
060: * @param name The entry key.
061: * @return Unmodifieable List of values.
062: */
063: public List getValues(Object name) {
064: return LazyList.getList(super .get(name), true);
065: }
066:
067: /* ------------------------------------------------------------ */
068: /** Get a value from a multiple value.
069: * If the value is not a multivalue, then index 0 retrieves the
070: * value or null.
071: * @param name The entry key.
072: * @param i Index of element to get.
073: * @return Unmodifieable List of values.
074: */
075: public Object getValue(Object name, int i) {
076: Object l = super .get(name);
077: if (i == 0 && LazyList.size(l) == 0)
078: return null;
079: return LazyList.get(l, i);
080: }
081:
082: /* ------------------------------------------------------------ */
083: /** Get value as String.
084: * Single valued items are converted to a String with the toString()
085: * Object method. Multi valued entries are converted to a comma separated
086: * List. No quoting of commas within values is performed.
087: * @param name The entry key.
088: * @return String value.
089: */
090: public String getString(Object name) {
091: Object l = super .get(name);
092: switch (LazyList.size(l)) {
093: case 0:
094: return null;
095: case 1:
096: Object o = LazyList.get(l, 0);
097: return o == null ? null : o.toString();
098: default:
099: StringBuffer values = new StringBuffer(128);
100: synchronized (values) {
101: for (int i = 0; i < LazyList.size(l); i++) {
102: Object e = LazyList.get(l, i);
103: if (e != null) {
104: if (values.length() > 0)
105: values.append(',');
106: values.append(e.toString());
107: }
108: }
109: return values.toString();
110: }
111: }
112: }
113:
114: /* ------------------------------------------------------------ */
115: public Object get(Object name) {
116: Object l = super .get(name);
117: switch (LazyList.size(l)) {
118: case 0:
119: return null;
120: case 1:
121: Object o = LazyList.get(l, 0);
122: return o;
123: default:
124: return LazyList.getList(l, true);
125: }
126: }
127:
128: /* ------------------------------------------------------------ */
129: /** Put and entry into the map.
130: * @param name The entry key.
131: * @param value The entry value.
132: * @return The previous value or null.
133: */
134: public Object put(Object name, Object value) {
135: return super .put(name, LazyList.add(null, value));
136: }
137:
138: /* ------------------------------------------------------------ */
139: /** Put multi valued entry.
140: * @param name The entry key.
141: * @param values The List of multiple values.
142: * @return The previous value or null.
143: */
144: public Object putValues(Object name, List values) {
145: return super .put(name, values);
146: }
147:
148: /* ------------------------------------------------------------ */
149: /** Put multi valued entry.
150: * @param name The entry key.
151: * @param values The String array of multiple values.
152: * @return The previous value or null.
153: */
154: public Object putValues(Object name, String[] values) {
155: Object list = null;
156: for (int i = 0; i < values.length; i++)
157: list = LazyList.add(list, values[i]);
158: return put(name, list);
159: }
160:
161: /* ------------------------------------------------------------ */
162: /** Add value to multi valued entry.
163: * If the entry is single valued, it is converted to the first
164: * value of a multi valued entry.
165: * @param name The entry key.
166: * @param value The entry value.
167: */
168: public void add(Object name, Object value) {
169: Object lo = super .get(name);
170: Object ln = LazyList.add(lo, value);
171: if (lo != ln)
172: super .put(name, ln);
173: }
174:
175: /* ------------------------------------------------------------ */
176: /** Add values to multi valued entry.
177: * If the entry is single valued, it is converted to the first
178: * value of a multi valued entry.
179: * @param name The entry key.
180: * @param values The List of multiple values.
181: */
182: public void addValues(Object name, List values) {
183: Object lo = super .get(name);
184: Object ln = LazyList.addCollection(lo, values);
185: if (lo != ln)
186: super .put(name, ln);
187: }
188:
189: /* ------------------------------------------------------------ */
190: /** Add values to multi valued entry.
191: * If the entry is single valued, it is converted to the first
192: * value of a multi valued entry.
193: * @param name The entry key.
194: * @param values The String array of multiple values.
195: */
196: public void addValues(Object name, String[] values) {
197: Object lo = super .get(name);
198: Object ln = LazyList.addCollection(lo, Arrays.asList(values));
199: if (lo != ln)
200: super .put(name, ln);
201: }
202:
203: /* ------------------------------------------------------------ */
204: /** Remove value.
205: * @param name The entry key.
206: * @param value The entry value.
207: * @return true if it was removed.
208: */
209: public boolean removeValue(Object name, Object value) {
210: Object lo = super .get(name);
211: Object ln = lo;
212: int s = LazyList.size(lo);
213: if (s > 0) {
214: ln = LazyList.remove(lo, value);
215: if (ln == null)
216: super .remove(name);
217: else
218: super .put(name, ln);
219: }
220: return LazyList.size(ln) != s;
221: }
222:
223: /* ------------------------------------------------------------ */
224: /** Put all contents of map.
225: * @param m Map
226: */
227: public void putAll(Map m) {
228: Iterator i = m.entrySet().iterator();
229: boolean multi = m instanceof MultiMap;
230: while (i.hasNext()) {
231: Map.Entry entry = (Map.Entry) i.next();
232: if (multi)
233: super .put(entry.getKey(), LazyList.clone(entry
234: .getValue()));
235: else
236: put(entry.getKey(), entry.getValue());
237: }
238: }
239:
240: /* ------------------------------------------------------------ */
241: /**
242: * @return Map of String arrays
243: */
244: public Map toStringArrayMap() {
245: HashMap map = new HashMap(size() * 3 / 2);
246:
247: Iterator i = super .entrySet().iterator();
248: while (i.hasNext()) {
249: Map.Entry entry = (Map.Entry) i.next();
250: Object l = entry.getValue();
251: String[] a = LazyList.toStringArray(l);
252: // for (int j=a.length;j-->0;)
253: // if (a[j]==null)
254: // a[j]="";
255: map.put(entry.getKey(), a);
256: }
257: return map;
258: }
259:
260: /* ------------------------------------------------------------ */
261: public Object clone() {
262: MultiMap mm = (MultiMap) super .clone();
263:
264: Iterator iter = mm.entrySet().iterator();
265: while (iter.hasNext()) {
266: Map.Entry entry = (Map.Entry) iter.next();
267: entry.setValue(LazyList.clone(entry.getValue()));
268: }
269:
270: return mm;
271: }
272: }
|