View Javadoc
1 /* 2 * Copyright (c) 2003, Henri Yandell 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or 6 * without modification, are permitted provided that the 7 * following conditions are met: 8 * 9 * + Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * 12 * + Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * + Neither the name of Genjava-Core nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 package com.generationjava.collections; 33 34 import java.util.Collection; 35 import java.util.HashMap; 36 import java.util.Iterator; 37 import java.util.LinkedList; 38 import java.util.Map; 39 import java.util.Set; 40 import java.util.HashSet; 41 42 import com.generationjava.patterns.Null; 43 44 /*** 45 * A Map in which multiple keys are used, ie) an Object array 46 * of keys. 47 * 48 * @author bayard@generationjava.com 49 * @date 2001-12-19 50 */ 51 /// Pass in: { "key1", "key2", "key3" } and a value. 52 public class MultiKeyedMap implements Map { 53 54 // this is not lazy instantiation. One MUST be 55 // constructed in a constructor. 56 private Map myMap = null; 57 58 public MultiKeyedMap(Map m) { 59 myMap = m; 60 } 61 62 public MultiKeyedMap() { 63 this(new HashMap()); 64 } 65 66 /* map interface */ 67 68 // Removes all mappings from this map (optional operation) {. 69 public void clear() { 70 myMap.clear(); 71 } 72 73 // Returns true if this map contains a mapping for the specified key. 74 public boolean containsKey(Object key) { 75 return get(key) != null; 76 } 77 78 // Returns true if this map maps one or more keys to the specified value. 79 public boolean containsValue(Object value) { 80 return this.containsValue(this.myMap, value); 81 } 82 83 private boolean containsValue(Map map, Object value) { 84 Iterator values = map.values().iterator(); 85 while(values.hasNext()) { 86 Object obj = values.next(); 87 if(obj instanceof Map) { 88 if(containsValue((Map)obj, value) ) { 89 return true; 90 } 91 } 92 if(value == obj) { 93 return true; 94 } 95 if(value.equals(obj)) { 96 return true; 97 } 98 } 99 100 return false; 101 } 102 103 // Returns a set view of the mappings contained in this map. 104 public Set entrySet() { 105 // FIX : Make this actually work. 106 return myMap.entrySet(); 107 } 108 109 // Compares the specified object with this map for equality. 110 public boolean equals(Object o) { 111 return myMap.equals(o); 112 } 113 114 // Returns the value to which this map maps the specified key. 115 public Object get(Object key) { 116 if(key instanceof Object[]) { 117 Object[] keys = (Object[])key; 118 Map map = this.myMap; 119 int szLessOne = keys.length - 1; 120 for(int i=0; i<szLessOne; i++) { 121 Object value = map.get(keys[i]); 122 if(value instanceof Map) { 123 map = (Map)value; 124 } else { 125 return null; 126 } 127 } 128 return map.get(keys[szLessOne]); 129 } else { 130 return this.myMap.get(key); 131 } 132 } 133 134 // Returns the hash code value for this map. 135 public int hashCode() { 136 return myMap.hashCode(); 137 } 138 139 // Returns true if this map contains no key-value mappings. 140 public boolean isEmpty() { 141 return myMap.isEmpty(); 142 } 143 144 // Returns a set view of the keys contained in this map. 145 /// NOTE: If fred:foo is added, it will return that key as 146 /// the array [fred]. Arrays are the correct way to talk 147 /// to this class. 148 public Set keySet() { 149 Set set = new HashSet(); 150 keySetRecurse(this.myMap, set, new LinkedList()); 151 return set; 152 } 153 154 // SLOW :( 155 private void keySetRecurse(Map map, Set set, LinkedList head) { 156 Iterator keys = map.keySet().iterator(); 157 while(keys.hasNext()) { 158 Object key = keys.next(); 159 head.add(key); 160 Object value = map.get(key); 161 if(value instanceof Map) { 162 keySetRecurse((Map)value, set, head); 163 } else { 164 set.add(head.toArray()); 165 } 166 head.removeLast(); 167 } 168 } 169 170 // Put a value into the specified map (optional operation) 171 public Object put(Object key, Object value) { 172 if(key instanceof Object[]) { 173 Object[] keys = (Object[])key; 174 int szLessOne = keys.length-1; 175 Map map = this.myMap; 176 for(int i=0; i<szLessOne; i++) { 177 Object obj = map.get(keys[i]); 178 if(obj instanceof Map) { 179 map = (Map)obj; 180 } else { 181 Map oldmap = map; 182 map = CollectionsW.cloneNewEmptyMap(map); 183 oldmap.put(keys[i], map); 184 } 185 } 186 return map.put(keys[szLessOne], value); 187 } else { 188 return this.myMap.put(key, value); 189 } 190 } 191 192 // Copies all of the mappings from the specified map to this map (optional operation) 193 public void putAll(Map t) { 194 if(t != null) { 195 Set set = t.keySet(); 196 if(set != null) { 197 Iterator iterator = set.iterator(); 198 while(iterator.hasNext()) { 199 Object key = iterator.next(); 200 put(key,t.get(key)); 201 } 202 } 203 } 204 } 205 206 // Removes the mapping for this key from this map if present (optional operation) 207 public Object remove(Object key) { 208 if(key instanceof Object[]) { 209 Object[] keys = (Object[])key; 210 int szLessOne = keys.length-1; 211 Map map = this.myMap; 212 for(int i=0; i<szLessOne; i++) { 213 Object obj = map.get(keys[i]); 214 if(obj instanceof Map) { 215 map = (Map)obj; 216 } else { 217 return null; 218 } 219 } 220 return map.remove(keys[szLessOne]); 221 } else { 222 return this.myMap.remove(key); 223 } 224 } 225 226 // Returns the number of key-value mappings in this map. 227 public int size() { 228 // QUERY: This is okay I think. Should it return size of flattened??? 229 return values().size(); 230 } 231 232 // Returns a collection view of the values contained in this map. 233 public Collection values() { 234 Collection list = new LinkedList(); 235 valuesRecurse( this.myMap, list ); 236 return list; 237 } 238 239 private void valuesRecurse(Map map, Collection list) { 240 Iterator iterator = map.keySet().iterator(); 241 while(iterator.hasNext()) { 242 Object key = iterator.next(); 243 Object value = map.get(key); 244 if(value instanceof Map) { 245 valuesRecurse((Map)value, list); 246 } else { 247 list.add(value); 248 } 249 } 250 } 251 252 public String toString() { 253 return myMap.toString(); 254 } 255 256 }

This page was automatically generated by Maven