PageRenderTime 34ms CodeModel.GetById 24ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 0ms

/src/org/ooc/middle/structs/MultiMap.java

http://github.com/nddrylliog/ooc
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}