1 19 20 package org.netbeans.modules.java.bridge; 21 22 import java.beans.PropertyChangeEvent ; 23 import java.util.*; 24 25 import org.openide.src.MultiPropertyChangeEvent; 26 27 38 public abstract class IndexedPropertyBase extends Object { 39 public static final int SMALL_THRESHOLD = 500; 40 41 private String propertyName; 42 58 59 63 public static class Change { 64 public Collection removed; 66 public int[] removeIndices; 68 public int[] reordered; 71 public Collection inserted; 73 public int[] insertIndices; 75 public Collection replacements; 77 public int[] replaceIndices; 79 public int[] offsets; 83 public int phaseCount; 85 86 public int[] mapping; 87 88 public int sizeDiff; 89 90 public String toString() { 91 StringBuffer sb = new StringBuffer (); 92 if (removed != null) { 93 sb.append("removed(" + removed.size() + ")"); } 95 if (reordered != null) { 96 sb.append(" reordered "); } 98 if (inserted != null) { 99 sb.append("inserted(" + inserted.size() + ")"); } 101 if (replacements != null) { 102 sb.append("replaced(" + replacements.size() + ")"); } 104 sb.append("sizedif=" + sizeDiff); return sb.toString(); 106 } 107 108 public Object clone() { 109 try { 110 return super.clone(); 111 } catch (Exception ex) { 112 } 113 return null; 114 } 115 } 116 117 120 public IndexedPropertyBase(String propName) { 121 this.propertyName = propName; 122 } 123 124 127 public Change computeChanges(Object [] olds, Object [] newValue) { 128 return computeChanges2(olds, newValue, pairItems(olds, newValue)); 129 } 130 131 134 public static Change computeChanges2(Object [] olds, Object [] newValue, int[] mapping) { 135 int[] perm = new int[olds.length]; 136 int matched = 0; 137 int inserted = 0; 138 boolean removed = false; 139 int reordered = 0; 140 int[] insertIndices = null; 141 int removeCount; 142 int[] offsets = null; 143 145 int oldIndex = 0; 148 149 for (int i = 0; i < mapping.length; i++) { 150 if (offsets != null && i - inserted < olds.length) { 151 offsets[i - inserted] = inserted; 152 } 153 if (mapping[i] == -1) { 155 if (insertIndices == null) { 157 offsets = new int[olds.length]; 158 insertIndices = new int[mapping.length]; 159 } 163 insertIndices[inserted] = i; 165 inserted++; 166 } else { 167 perm[mapping[i]] = i + 1; 168 172 matched++; 173 } 174 } 175 if (inserted > 0 && mapping.length < olds.length) { 176 Arrays.fill(offsets, mapping.length, olds.length - 1, inserted); 177 } 178 179 removeCount = perm.length - matched; 180 removed = removeCount > 0; 181 182 Change ch = new Change(); 183 int eventCount = 0; 184 PropertyChangeEvent removeEvent = null, addEvent = null, reorderEvent = null; 185 186 if (removed) { 187 Collection rem = new ArrayList(perm.length - matched); 188 int bias = 0; 189 int reorderIndex = 0; 190 int removedSoFar = 0; 191 int[] indices = new int[removeCount]; 192 int indicePos = 0; 193 int diff = 0; 194 195 if (offsets == null) { 198 offsets = new int[olds.length]; 199 } 201 for (int i = 0; i < perm.length; i++) { 203 if (perm[i] == 0) { 204 bias--; 206 indices[indicePos++] = i; 207 rem.add(olds[i]); 208 removedSoFar++; 209 offsets[i] = -i - 1; 211 } else { 212 offsets[i] += bias; 213 } 215 } 216 ch.removed = rem; 217 ch.removeIndices = indices; 218 eventCount++; 219 } 220 if (true) { 222 int nextInsert; 223 int insertPos = 1; 224 225 if (insertIndices == null) 226 nextInsert = -1; 227 else 228 nextInsert = insertIndices[0]; 229 int pos = 0; 230 231 reordered = 0; 232 int j = 0; 233 234 for (int i = 0; i < perm.length; i++) { 236 if (perm[i] == 0) { 237 perm[i] = -1; 238 continue; 240 } 241 int newPlace = perm[i] - 1; 242 int expectedPlace = i; 243 244 if (offsets != null) 245 expectedPlace += offsets[i]; 246 249 if (newPlace != expectedPlace) { 251 reordered++; 252 perm[i] = newPlace; 254 } else { 255 perm[i] = -1; 257 } 258 277 } 278 if (reordered > 0) { 279 ch.reordered = perm; 280 eventCount++; 281 } 282 } 283 if (inserted > 0) { 284 Collection col = new ArrayList(inserted); 286 int[] indices = new int[inserted]; 287 System.arraycopy(insertIndices, 0, indices, 0, inserted); 288 for (int i = 0; i < indices.length; i++) { 289 col.add(newValue[insertIndices[i]]); 290 } 291 ch.inserted = col; 292 ch.insertIndices = indices; 293 eventCount++; 294 } 295 ch.offsets = offsets; 296 ch.phaseCount = eventCount; 297 ch.sizeDiff = inserted - removeCount; 298 return ch; 299 } 300 301 303 public MultiPropertyChangeEvent createPropertyEvent(Change ch, 304 Object source, Object oldV, Object newV) { 305 if (ch.phaseCount == 0) 306 return null; 307 308 MultiPropertyChangeEvent evt = null; 309 boolean compound = ch.phaseCount > 1; 310 Collection sub = null; 311 312 newV = ((Object [])newV).clone(); 313 if (compound) { 314 sub = new ArrayList(ch.phaseCount); 315 } 316 if (ch.inserted != null) { 317 evt = createInsertionEvent(source, oldV, newV, ch.inserted, 318 ch.insertIndices); 319 if (compound) 320 sub.add(evt); 321 } 322 if (ch.removed != null) { 323 evt = createRemovalEvent(source, oldV, newV, ch.removed, 324 ch.removeIndices); 325 if (compound) 326 sub.add(evt); 327 } 328 if (ch.reordered != null) { 329 evt = createReorderEvent(source, oldV, newV, ch.reordered); 330 if (compound) 331 sub.add(evt); 332 } 333 if (compound) { 334 return createCompoundEvent(source, sub, ch.offsets, oldV, newV); 335 } else { 336 return evt; 337 } 338 } 339 340 public MultiPropertyChangeEvent createChangeEvent(Object source, 341 Object [] olds, Object [] newValue) { 342 Change ch = computeChanges(olds, newValue); 343 return createPropertyEvent(ch, source, olds, newValue); 344 } 345 346 protected MultiPropertyChangeEvent createInsertionEvent(Object source, 347 Object previous, Object now, Collection inserted, 348 int[] indices) { 349 MultiPropertyChangeEvent insertEvent = new MultiPropertyChangeEvent( 350 source, 351 getPropertyName(), previous, now); 352 insertEvent.makeInsertion(inserted, indices); 353 return insertEvent; 354 } 355 356 protected MultiPropertyChangeEvent createRemovalEvent(Object source, 357 Object prev, Object now, Collection removed, int[] indices) { 358 MultiPropertyChangeEvent evt = new MultiPropertyChangeEvent( 359 source, 360 getPropertyName(), prev, now); 361 evt.makeRemoval(removed, indices); 362 return evt; 363 } 364 365 protected MultiPropertyChangeEvent createModifyEvent(Object source, 366 Object prev, Object now, Collection origs, Collection replacements, int[] indices) { 367 MultiPropertyChangeEvent evt = new MultiPropertyChangeEvent( 368 source, 369 getPropertyName(), prev, now); 370 evt.makeReplacement(origs, replacements, indices); 371 return evt; 372 } 373 374 377 protected MultiPropertyChangeEvent createCompoundEvent(Object source, 378 Collection subEvents, int[] offsets, Object old, Object newValue) { 379 MultiPropertyChangeEvent evt = new MultiPropertyChangeEvent(source, 380 getPropertyName(), old, newValue); 381 evt.makeCompound(subEvents, offsets); 382 return evt; 383 } 384 385 393 protected MultiPropertyChangeEvent createReorderEvent(Object source, 394 Object old, Object now, int[] perm) { 395 MultiPropertyChangeEvent evt = new MultiPropertyChangeEvent(source, 396 getPropertyName(), old, now); 397 evt.makeReorder(perm); 398 return evt; 399 } 400 401 406 public int[] pairItems(Object [] o, Object [] n) { 407 int[] map = new int[n.length]; 408 boolean[] used = new boolean[o.length]; 409 410 for (int i = 0; i < n.length; i++) { 411 map[i] = -1; 412 for (int j = 0; j < o.length; j++) { 413 if (used[j]) 414 continue; 415 if (o[j] == n[i] || compareValues(o[j], n[i])) { 416 used[j] = true; 417 map[i] = j; 418 } 419 } 420 } 421 return map; 422 } 423 424 425 protected int[] createIdentityMap(Object [] els, Object [] olds) { 426 int avgOps = els.length * olds.length; 427 428 if (avgOps < SMALL_THRESHOLD) { 429 430 return pairItems(olds, els); 432 } 433 434 Map indexM = new HashMap((int)(olds.length * 1.3)); 435 int[] mapping = new int[els.length]; 436 437 for (int idx = 0; idx < olds.length; idx++) { 438 indexM.put(olds[idx], new Integer (idx)); 439 } 440 441 for (int i = 0; i < els.length; i++) { 442 Integer pos = (Integer )indexM.get(els[i]); 443 mapping[i] = pos == null ? -1 : pos.intValue(); 444 } 445 return mapping; 446 } 447 448 453 protected boolean compareValues(Object o1, Object o2) { 454 return false; 455 } 456 457 459 protected Object getSource(ElementImpl key) { 460 return key.getElement(); 461 } 462 463 protected String getPropertyName() { 466 return propertyName; 467 } 468 } 469 | Popular Tags |