/src/org/ooc/middle/structs/MultiMap.java
Java | 177 lines | 140 code | 29 blank | 8 comment | 33 complexity | 7fa39faa5d2b9abe528d22a1e51851ee MD5 | raw file
1package org.ooc.middle.structs; 2 3import java.io.IOException; 4import java.util.ArrayList; 5import java.util.Collections; 6import java.util.Iterator; 7import java.util.LinkedHashMap; 8import java.util.List; 9import java.util.Map; 10import java.util.Set; 11 12import org.ooc.frontend.Visitor; 13import org.ooc.frontend.model.Node; 14import org.ooc.frontend.model.tokens.Token; 15 16/** 17 * A MultiMap allows you to store several values for the same 18 * key, in a relatively lightweight fashion (memory-wise) 19 * @author Amos Wenger 20 * 21 * @param <K> the keys type 22 * @param <V> the values type 23 */ 24public class MultiMap<K, V> extends Node { 25 26 final Map<K, Object> map; 27 28 public MultiMap() { 29 super(Token.defaultToken); 30 map = new LinkedHashMap<K, Object>(); 31 } 32 33 public void put(K key, V value) { 34 add(key, value); 35 } 36 37 @SuppressWarnings("unchecked") 38 public void add(K key, V value) { 39 40 Object o = map.get(key); 41 if(o == null) { 42 map.put(key, value); 43 } else { 44 if(o instanceof List<?>) { 45 List<V> list = (List<V>) o; 46 list.add(value); 47 } else { 48 List<V> list = new ArrayList<V>(); 49 list.add((V) o); 50 list.add(value); 51 map.put(key, list); 52 } 53 } 54 55 } 56 57 @SuppressWarnings("unchecked") 58 public Iterable<V> getAll(final K key) { 59 60 final Object o = map.get(key); 61 if(o instanceof List<?>) { 62 List<V> list = (List<V>) o; 63 return list; 64 } else if(o != null) { 65 return new Iterable<V>() { 66 public Iterator<V> iterator() { 67 return new Iterator<V>() { 68 69 boolean hasNext = true; 70 71 public boolean hasNext() { 72 return hasNext; 73 } 74 75 public V next() { 76 hasNext = false; 77 return (V) o; 78 } 79 80 public void remove() { 81 map.remove(key); 82 } 83 }; 84 } 85 }; 86 } else { 87 return Collections.emptySet(); // it's iterable, and empty. what else? (Nespresso) 88 } 89 90 } 91 92 @SuppressWarnings("unchecked") 93 public V get(final K key) { 94 95 final Object o = map.get(key); 96 if(o instanceof List<?>) { 97 List<V> list = (List<V>) o; 98 return list.get(0); 99 } 100 return (V) o; 101 102 } 103 104 @Override 105 public String toString() { 106 return map.toString(); 107 } 108 109 @SuppressWarnings("unchecked") 110 @Override 111 public boolean replace(Node oldie, Node kiddo) { 112 for(Object key: map.keySet()) { 113 final Object o = map.get(key); 114 if(o instanceof List<?>) { 115 List<V> list = (List<V>) o; 116 for(int index = 0; index < list.size(); index++) { 117 V value = list.get(index); 118 if(oldie == value) { 119 list.set(index, (V) kiddo); 120 return true; 121 } 122 } 123 } else if(o != null && o == oldie) { 124 map.put((K) oldie, kiddo); 125 return true; 126 } 127 } 128 return false; 129 } 130 131 public void accept(Visitor visitor) throws IOException { 132 visitor.visit(this); 133 } 134 135 @SuppressWarnings("unchecked") 136 public void acceptChildren(Visitor visitor) throws IOException { 137 for(Object key: map.keySet()) { 138 final Object o = map.get(key); 139 if(o instanceof List<?>) { 140 List<V> list = (List<V>) o; 141 for(V value: list) { 142 ((Node) value).accept(visitor); 143 } 144 } else if(o != null) { 145 ((Node) o).accept(visitor); 146 } 147 } 148 } 149 150 public boolean hasChildren() { 151 return map.size() > 0; 152 } 153 154 public Set<K> keySet() { 155 return map.keySet(); 156 } 157 158 @SuppressWarnings("unchecked") 159 public List<V> values() { 160 ArrayList<V> values = new ArrayList<V>(); 161 162 for(Object key: map.keySet()) { 163 final Object o = map.get(key); 164 if(o instanceof List<?>) { 165 List<V> list = (List<V>) o; 166 for(V value: list) { 167 values.add(value); 168 } 169 } else if(o != null) { 170 values.add((V) o); 171 } 172 } 173 174 return values; 175 } 176 177}