001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.reef.tang.util; 020 021import java.util.*; 022import java.util.Map.Entry; 023 024public abstract class AbstractMonotonicMultiMap<K, V> implements Collection<Entry<K, V>> { 025 protected Map<K, Set<V>> map; 026 private int size = 0; 027 028 public AbstractMonotonicMultiMap(Map<K, Set<V>> map) { 029 this.map = map; 030 } 031 032 public void put(K key, V v) { 033 Set<V> vals = map.get(key); 034 if (vals == null) { 035 vals = new MonotonicHashSet<V>(); 036 map.put(key, vals); 037 } 038 vals.add(v); 039 size++; 040 } 041 042 public Set<K> keySet() { 043 return map.keySet(); 044 } 045 046 public Set<V> getValuesForKey(K key) { 047 Set<V> ret = map.get(key); 048 if (ret == null) { 049 return new MonotonicHashSet<V>(); 050 } else { 051 return ret; 052 } 053 } 054 055 public boolean contains(K key, V v) { 056 Set<V> vals = map.get(key); 057 if (vals != null) { 058 return vals.contains(v); 059 } 060 return false; 061 } 062 063 @Override 064 public boolean add(Entry<K, V> e) { 065 put(e.getKey(), e.getValue()); 066 return true; 067 } 068 069 @Override 070 public boolean addAll(Collection<? extends Entry<K, V>> c) { 071 boolean ret = false; 072 for (Entry<K, V> e : c) { 073 add(e); 074 ret = true; 075 } 076 return ret; 077 } 078 079 @Override 080 public void clear() { 081 throw new UnsupportedOperationException("MonotonicMultiMap cannot be cleared!"); 082 } 083 084 @SuppressWarnings("unchecked") 085 @Override 086 public boolean contains(Object o) { 087 Entry<?, ?> e = (Entry<?, ?>) o; 088 return contains((K) e.getKey(), (V) e.getValue()); 089 } 090 091 @Override 092 public boolean containsAll(Collection<?> c) { 093 for (Object o : c) { 094 if (!contains(o)) { 095 return false; 096 } 097 } 098 return true; 099 } 100 101 @Override 102 public boolean isEmpty() { 103 return size == 0; 104 } 105 106 @Override 107 public Iterator<Entry<K, V>> iterator() { 108 final Iterator<Entry<K, Set<V>>> it = map.entrySet().iterator(); 109 return new Iterator<Entry<K, V>>() { 110 Iterator<V> cur; 111 K curKey; 112 113 @Override 114 public boolean hasNext() { 115 return it.hasNext() || (cur != null && cur.hasNext()); 116 } 117 118 @Override 119 public Entry<K, V> next() { 120 if (cur == null) { 121 if (it.hasNext()) { 122 Entry<K, Set<V>> e = it.next(); 123 curKey = e.getKey(); 124 cur = e.getValue().iterator(); 125 } 126 } 127 final K k = curKey; 128 final V v = cur.next(); 129 if (!cur.hasNext()) { 130 cur = null; 131 } 132 133 return new Entry<K, V>() { 134 135 @Override 136 public K getKey() { 137 return k; 138 } 139 140 @Override 141 public V getValue() { 142 return v; 143 } 144 145 @Override 146 public V setValue(V value) { 147 throw new UnsupportedOperationException(); 148 } 149 150 }; 151 } 152 153 @Override 154 public void remove() { 155 throw new UnsupportedOperationException(); 156 } 157 158 }; 159 } 160 161 public Set<V> values() { 162 Set<V> s = new HashSet<>(); 163 for (Entry<K, V> e : this) { 164 s.add(e.getValue()); 165 } 166 return s; 167 } 168 169 @Override 170 public boolean remove(Object o) { 171 throw new UnsupportedOperationException("MonotonicMultiMap does not support non-monotonic method remove!"); 172 } 173 174 @Override 175 public boolean removeAll(Collection<?> c) { 176 throw new UnsupportedOperationException("MonotonicMultiMap does not support non-monotonic method removeAll!"); 177 } 178 179 @Override 180 public boolean retainAll(Collection<?> c) { 181 throw new UnsupportedOperationException("MonotonicMultiMap does not support non-monotonic method retainAll!"); 182 } 183 184 @Override 185 public int size() { 186 return size; 187 } 188 189 @Override 190 public Entry<K, V>[] toArray() { 191 throw new UnsupportedOperationException("No toArray() for MonotonicMulitMap (yet)"); 192 } 193 194 @Override 195 public <T> T[] toArray(T[] a) { 196 throw new UnsupportedOperationException("No toArray() for MonotonicMulitMap (yet)"); 197 } 198 199 public boolean containsKey(K k) { 200 if (map.containsKey(k)) { 201 return !getValuesForKey(k).isEmpty(); 202 } else { 203 return false; 204 } 205 } 206}