/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

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