1 salcianu 1.1.2.1 // AbstrRelation.java, created Thu Jun 29 19:13:12 2000 by salcianu 2 cananian 1.1.2.5 // Copyright (C) 2000 Alexandru SALCIANU <salcianu@retezat.lcs.mit.edu> 3 salcianu 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 salcianu 1.1.2.1 package harpoon.Util.DataStructs; 5 salcianu 1.1.2.1 6 salcianu 1.1.2.1 import java.util.Collection; 7 salcianu 1.1.2.1 import java.util.Iterator; 8 salcianu 1.1.2.1 import java.util.LinkedList; 9 salcianu 1.1.2.1 import java.util.Vector; 10 salcianu 1.1.2.1 import java.util.HashSet; 11 salcianu 1.1.2.1 import java.util.Set; 12 salcianu 1.3 import java.util.Map; 13 salcianu 1.1.2.1 14 salcianu 1.1.2.1 import harpoon.Util.PredicateWrapper; 15 salcianu 1.1.2.1 import harpoon.Analysis.PointerAnalysis.Debug; 16 salcianu 1.1.2.1 17 salcianu 1.1.2.1 /** 18 salcianu 1.1.2.1 * <code>AbstrRelation</code> 19 salcianu 1.1.2.1 * 20 cananian 1.1.2.5 * @author Alexandru SALCIANU <salcianu@retezat.lcs.mit.edu> 21 salcianu 1.4 * @version $Id: AbstrRelation.java,v 1.4 2003/06/04 16:06:31 salcianu Exp $ 22 salcianu 1.1.2.1 */ 23 salcianu 1.1.2.1 public abstract class AbstrRelation implements Relation, Cloneable, 24 salcianu 1.1.2.1 java.io.Serializable { 25 salcianu 1.1.2.1 26 salcianu 1.1.2.2 /** Optimizes the .hashCode() method by caching the hash code. 27 salcianu 1.1.2.2 The cached value is invalidated after each update. */ 28 salcianu 1.1.2.2 public static final boolean OPTIMIZE_HASH_CODE = true; 29 salcianu 1.1.2.2 30 salcianu 1.1.2.1 protected Relation getEmptyRelation() { 31 salcianu 1.1.2.1 throw new UnsupportedOperationException(); 32 salcianu 1.1.2.1 } 33 salcianu 1.1.2.1 34 salcianu 1.1.2.1 35 salcianu 1.1.2.1 public boolean add(Object key, Object value) { 36 salcianu 1.1.2.1 throw new UnsupportedOperationException(); 37 salcianu 1.1.2.1 } 38 salcianu 1.1.2.1 39 salcianu 1.1.2.1 // functional but inefficient implementation 40 salcianu 1.1.2.1 public boolean addAll(Object key, Collection values) { 41 salcianu 1.1.2.1 hashCode = 0; 42 salcianu 1.1.2.1 boolean retval = false; 43 salcianu 1.1.2.1 for(Iterator it = values.iterator(); it.hasNext(); ) 44 salcianu 1.1.2.1 if(add(key, it.next())) 45 salcianu 1.1.2.1 retval = true; 46 salcianu 1.1.2.1 return retval; 47 salcianu 1.1.2.1 } 48 salcianu 1.1.2.1 49 salcianu 1.1.2.1 50 salcianu 1.1.2.1 public void remove(Object key, Object value) { 51 salcianu 1.1.2.3 Set vals = getValues2(key); 52 salcianu 1.1.2.1 if(vals == null) return; 53 salcianu 1.1.2.1 54 salcianu 1.1.2.1 hashCode = 0; 55 salcianu 1.1.2.1 vals.remove(value); 56 salcianu 1.1.2.1 if(vals.isEmpty()) 57 salcianu 1.1.2.1 removeKey(key); 58 salcianu 1.1.2.4 } 59 salcianu 1.1.2.4 60 salcianu 1.3 public Relation revert(final Relation result) { 61 salcianu 1.1.2.4 forAllEntries(new RelationEntryVisitor() { 62 salcianu 1.1.2.4 public void visit(Object key, Object value) { 63 salcianu 1.1.2.4 result.add(value, key); 64 salcianu 1.1.2.4 } 65 salcianu 1.1.2.4 }); 66 salcianu 1.3 return result; 67 salcianu 1.1.2.3 } 68 salcianu 1.1.2.3 69 salcianu 1.1.2.3 70 salcianu 1.1.2.3 protected Set getValues2(Object key) { 71 salcianu 1.1.2.3 throw new UnsupportedOperationException(); 72 salcianu 1.1.2.1 } 73 salcianu 1.1.2.1 74 salcianu 1.1.2.1 75 salcianu 1.1.2.1 // functional but inefficient implementation 76 salcianu 1.1.2.1 public void removeAll(Object key, Collection values) { 77 salcianu 1.1.2.1 for(Iterator it = values.iterator(); it.hasNext(); ) 78 salcianu 1.1.2.1 remove(key, it.next()); 79 salcianu 1.1.2.1 } 80 salcianu 1.1.2.1 81 salcianu 1.1.2.1 82 salcianu 1.1.2.1 public void removeKey(Object key) { 83 salcianu 1.1.2.1 throw new UnsupportedOperationException(); 84 salcianu 1.1.2.1 } 85 salcianu 1.1.2.1 86 salcianu 1.1.2.1 87 salcianu 1.1.2.1 public void removeKeys(PredicateWrapper predicate) { 88 salcianu 1.1.2.1 hashCode = 0; 89 salcianu 1.1.2.1 // 1. put all the keys that satisfy predicate in keysToRemove 90 salcianu 1.1.2.1 Collection keysToRemove = new Vector(); 91 salcianu 1.1.2.1 for(Iterator it = keys().iterator(); it.hasNext(); ) { 92 salcianu 1.1.2.1 Object key = it.next(); 93 salcianu 1.1.2.1 if(predicate.check(key)) 94 salcianu 1.1.2.1 keysToRemove.add(key); 95 salcianu 1.1.2.1 } 96 salcianu 1.1.2.1 // 2. actually do the removal 97 salcianu 1.1.2.1 for(Iterator it = keysToRemove.iterator(); it.hasNext(); ) 98 salcianu 1.1.2.1 removeKey(it.next()); 99 salcianu 1.1.2.1 } 100 salcianu 1.1.2.1 101 salcianu 1.1.2.1 102 salcianu 1.1.2.1 public void removeValues(PredicateWrapper predicate) { 103 salcianu 1.1.2.1 hashCode = 0; 104 salcianu 1.1.2.1 105 salcianu 1.1.2.1 Collection keysToRemove = new Vector(); 106 salcianu 1.1.2.1 for(Iterator itk = keys().iterator(); itk.hasNext(); ) { 107 salcianu 1.1.2.1 Object key = itk.next(); 108 salcianu 1.1.2.1 Set vals = getValues(key); 109 salcianu 1.1.2.1 for(Iterator itv = vals.iterator(); itv.hasNext(); ) { 110 salcianu 1.1.2.1 Object value = itv.next(); 111 salcianu 1.1.2.1 if(predicate.check(value)) 112 salcianu 1.1.2.1 itv.remove(); 113 salcianu 1.1.2.1 } 114 salcianu 1.1.2.1 if(vals.isEmpty()) 115 salcianu 1.1.2.1 keysToRemove.add(key); 116 salcianu 1.1.2.1 } 117 salcianu 1.1.2.1 118 salcianu 1.1.2.1 for(Iterator itk = keysToRemove.iterator(); itk.hasNext(); ) 119 salcianu 1.1.2.1 removeKey(itk.next()); 120 salcianu 1.1.2.1 } 121 salcianu 1.1.2.1 122 salcianu 1.1.2.1 123 salcianu 1.1.2.1 public void removeObjects(PredicateWrapper predicate) { 124 salcianu 1.1.2.1 removeKeys(predicate); 125 salcianu 1.1.2.1 removeValues(predicate); 126 salcianu 1.1.2.1 } 127 salcianu 1.1.2.1 128 salcianu 1.1.2.1 129 salcianu 1.1.2.1 public boolean contains(Object key, Object value) { 130 salcianu 1.1.2.1 Set vals = getValues(key); 131 salcianu 1.1.2.1 return (vals != null) && vals.contains(value); 132 salcianu 1.1.2.1 } 133 salcianu 1.1.2.1 134 salcianu 1.1.2.1 135 salcianu 1.1.2.1 public boolean containsKey(Object key) { 136 salcianu 1.1.2.1 Set vals = getValues(key); 137 salcianu 1.1.2.1 return (vals != null) && !vals.isEmpty(); 138 salcianu 1.1.2.1 } 139 salcianu 1.1.2.1 140 salcianu 1.1.2.1 141 salcianu 1.1.2.1 public boolean isEmpty() { 142 salcianu 1.1.2.1 return keys().isEmpty(); 143 salcianu 1.1.2.1 } 144 salcianu 1.1.2.1 145 salcianu 1.1.2.1 146 salcianu 1.1.2.1 public Set getValues(Object key) { 147 salcianu 1.1.2.1 throw new UnsupportedOperationException(); 148 salcianu 1.1.2.1 } 149 salcianu 1.1.2.1 150 salcianu 1.1.2.1 151 salcianu 1.1.2.1 public Set keys() { 152 salcianu 1.1.2.1 throw new UnsupportedOperationException(); 153 salcianu 1.1.2.1 } 154 salcianu 1.1.2.1 155 salcianu 1.1.2.1 156 salcianu 1.1.2.1 public Set values() { 157 salcianu 1.1.2.1 Set vals = new HashSet(); 158 salcianu 1.1.2.1 for(Iterator it = keys().iterator(); it.hasNext(); ) 159 salcianu 1.1.2.1 vals.addAll(getValues(it.next())); 160 salcianu 1.1.2.1 return vals; 161 salcianu 1.1.2.1 } 162 salcianu 1.1.2.1 163 salcianu 1.1.2.1 164 salcianu 1.4 public boolean union(Relation rel) { 165 salcianu 1.4 boolean changed = false; 166 salcianu 1.1.2.1 for(Iterator itk = rel.keys().iterator(); itk.hasNext(); ) { 167 salcianu 1.1.2.1 Object key = itk.next(); 168 salcianu 1.4 if(addAll(key, rel.getValues(key))) 169 salcianu 1.4 changed = true; 170 salcianu 1.1.2.1 } 171 salcianu 1.4 return changed; 172 salcianu 1.1.2.1 } 173 salcianu 1.1.2.1 174 salcianu 1.1.2.1 175 salcianu 1.1.2.1 public boolean equals(Object o) { 176 salcianu 1.1.2.2 if((o == null) || !(o instanceof Relation)) 177 salcianu 1.1.2.1 return false; 178 salcianu 1.1.2.1 Relation rel2 = (Relation) o; 179 salcianu 1.1.2.1 180 salcianu 1.1.2.1 Set ks = keys(); 181 salcianu 1.1.2.1 Set ks2 = rel2.keys(); 182 salcianu 1.1.2.1 183 salcianu 1.1.2.2 if(!equal_sets(ks, ks2)) 184 salcianu 1.1.2.1 return false; 185 salcianu 1.1.2.1 186 salcianu 1.1.2.1 for(Iterator it = ks.iterator(); it.hasNext(); ){ 187 salcianu 1.1.2.1 Object key = it.next(); 188 salcianu 1.1.2.1 Set vs = getValues(key); 189 salcianu 1.1.2.1 Set vs2 = rel2.getValues(key); 190 salcianu 1.1.2.2 if(!equal_sets(vs, vs2)) 191 salcianu 1.1.2.1 return false; 192 salcianu 1.1.2.1 } 193 salcianu 1.1.2.1 194 salcianu 1.1.2.1 return true; 195 salcianu 1.1.2.1 } 196 salcianu 1.1.2.1 197 salcianu 1.1.2.1 198 salcianu 1.1.2.1 public int hashCode() { 199 salcianu 1.1.2.2 if((hashCode == 0) || !OPTIMIZE_HASH_CODE) { 200 salcianu 1.1.2.2 hashCode = 0; 201 salcianu 1.1.2.1 for(Iterator itk = keys().iterator(); itk.hasNext(); ) { 202 salcianu 1.1.2.1 Object key = itk.next(); 203 salcianu 1.1.2.1 hashCode += key.hashCode(); 204 salcianu 1.1.2.1 for(Iterator itv = getValues(key).iterator(); itv.hasNext(); ){ 205 salcianu 1.1.2.1 Object value = itv.next(); 206 salcianu 1.1.2.1 hashCode += value.hashCode(); 207 salcianu 1.1.2.1 } 208 salcianu 1.1.2.1 } 209 salcianu 1.1.2.2 } 210 salcianu 1.1.2.1 return hashCode; 211 salcianu 1.1.2.1 } 212 salcianu 1.1.2.1 protected int hashCode = 0; 213 salcianu 1.1.2.1 214 salcianu 1.1.2.1 215 salcianu 1.1.2.1 // Test whether c1 and c2 contain the same elements. 216 salcianu 1.1.2.1 // Precondition: c1 and c2 don't contain duplicates. 217 salcianu 1.1.2.1 // So, we can say that c1 and c2 are equal if they have the same number 218 salcianu 1.1.2.1 // of elements and each element of c1 is also in c2. 219 salcianu 1.1.2.1 private boolean equal_sets(Collection c1, Collection c2) { 220 salcianu 1.1.2.1 if((c1 == null) || (c2 == null)) 221 salcianu 1.1.2.1 return c1 == c2; 222 salcianu 1.1.2.1 223 salcianu 1.1.2.2 if(c1.size() != c2.size()) 224 salcianu 1.1.2.1 return false; 225 salcianu 1.1.2.1 226 salcianu 1.1.2.1 for(Iterator it = c1.iterator(); it.hasNext(); ) { 227 salcianu 1.1.2.1 Object obj = it.next(); 228 salcianu 1.1.2.2 if(!c2.contains(obj)) 229 salcianu 1.1.2.1 return false; 230 salcianu 1.1.2.1 } 231 salcianu 1.1.2.1 232 salcianu 1.1.2.1 return true; 233 salcianu 1.1.2.1 } 234 salcianu 1.1.2.1 235 salcianu 1.1.2.1 236 salcianu 1.1.2.1 public Relation select(Collection selected_keys) { 237 salcianu 1.1.2.1 Relation retval = getEmptyRelation(); 238 salcianu 1.1.2.1 239 salcianu 1.1.2.1 for(Iterator it = selected_keys.iterator(); it.hasNext(); ) { 240 salcianu 1.1.2.1 Object key = it.next(); 241 salcianu 1.1.2.1 retval.addAll(key, getValues(key)); 242 salcianu 1.1.2.1 } 243 salcianu 1.1.2.1 244 salcianu 1.1.2.1 return retval; 245 salcianu 1.1.2.1 } 246 salcianu 1.1.2.1 247 salcianu 1.1.2.1 248 salcianu 1.1.2.1 public void forAllEntries(RelationEntryVisitor visitor) { 249 salcianu 1.1.2.1 for(Iterator itk = keys().iterator(); itk.hasNext(); ) { 250 salcianu 1.1.2.1 Object key = itk.next(); 251 salcianu 1.1.2.1 for(Iterator itv = getValues(key).iterator(); itv.hasNext(); ) 252 salcianu 1.1.2.1 visitor.visit(key, itv.next()); 253 salcianu 1.1.2.1 } 254 salcianu 1.1.2.1 } 255 salcianu 1.1.2.1 256 salcianu 1.1.2.1 257 salcianu 1.1.2.1 public String toString() { 258 salcianu 1.1.2.1 StringBuffer buffer = new StringBuffer(); 259 salcianu 1.1.2.1 260 salcianu 1.1.2.1 buffer.append("{"); 261 salcianu 1.1.2.1 262 salcianu 1.1.2.1 Object[] ks = Debug.sortedCollection(keys()); 263 salcianu 1.1.2.1 for(int i = 0 ; i < ks.length ; i++ ){ 264 salcianu 1.1.2.1 Object key = ks[i]; 265 salcianu 1.1.2.1 buffer.append("\n "); 266 salcianu 1.1.2.1 buffer.append(key); 267 salcianu 1.1.2.1 buffer.append(" -> "); 268 salcianu 1.1.2.1 buffer.append(Debug.stringImg(getValues(key))); 269 salcianu 1.1.2.1 } 270 salcianu 1.1.2.1 271 salcianu 1.1.2.1 buffer.append("\n }\n"); 272 salcianu 1.1.2.1 273 salcianu 1.1.2.1 return buffer.toString(); 274 salcianu 1.1.2.1 } 275 salcianu 1.1.2.1 276 salcianu 1.1.2.1 277 salcianu 1.1.2.1 public Object clone() { 278 salcianu 1.1.2.1 try{ 279 salcianu 1.1.2.1 return super.clone(); 280 salcianu 1.1.2.1 } catch(CloneNotSupportedException e) { 281 salcianu 1.1.2.1 throw new InternalError(); 282 salcianu 1.1.2.1 } 283 salcianu 1.3 } 284 salcianu 1.3 285 salcianu 1.3 public Relation convert(final Map map, final Relation result) { 286 salcianu 1.3 forAllEntries(new RelationEntryVisitor() { 287 salcianu 1.3 public void visit(Object key, Object value) { 288 salcianu 1.3 Object keyp = map.get(key); 289 salcianu 1.3 if(keyp == null) keyp = key; 290 salcianu 1.3 Object valuep = map.get(value); 291 salcianu 1.3 if(valuep == null) valuep = value; 292 salcianu 1.3 result.add(keyp, valuep); 293 salcianu 1.3 } 294 salcianu 1.3 }); 295 salcianu 1.3 return result; 296 salcianu 1.1.2.1 } 297 salcianu 1.1.2.1 298 cananian 1.2 }