1 19 package org.netbeans.mdr.util; 20 21 import java.util.Map ; 22 import org.netbeans.api.mdr.events.*; 23 import org.netbeans.mdr.handlers.BaseObjectHandler; 24 import org.netbeans.mdr.storagemodel.CompositeCollection; 25 import java.util.*; 26 import javax.jmi.reflect.*; 27 28 36 public final class EventNotifier { 37 38 39 40 41 42 44 public static final int EVENTMASK_BY_ASSOCIATION = MDRChangeEvent.EVENTMASK_ON_ASSOCIATION; 45 47 public static final int EVENTMASK_BY_INSTANCE = EVENTMASK_BY_ASSOCIATION | MDRChangeEvent.EVENTMASK_ON_INSTANCE; 48 50 public static final int EVENTMASK_BY_CLASS = EVENTMASK_BY_INSTANCE | MDRChangeEvent.EVENTMASK_ON_CLASS; 51 53 public static final int EVENTMASK_BY_PACKAGE = EVENTMASK_BY_CLASS | MDRChangeEvent.EVENTMASK_ON_PACKAGE; 54 56 public static final int EVENTMASK_BY_REPOSITORY = EVENTMASK_BY_CLASS | MDRChangeEvent.EVENTMASK_ON_REPOSITORY; 57 58 59 60 61 62 68 public static String prettyPrintType(MDRChangeEvent e) { 69 if (e.isOfType(AttributeEvent.EVENT_ATTRIBUTE_ADD)) return "EVENT_ATTRIBUTE_ADD"; 70 else if (e.isOfType(AttributeEvent.EVENT_ATTRIBUTE_REMOVE)) return "EVENT_ATTRIBUTE_REMOVE"; 71 else if (e.isOfType(AttributeEvent.EVENT_ATTRIBUTE_SET)) return "EVENT_ATTRIBUTE_SET"; 72 else if (e.isOfType(AttributeEvent.EVENT_CLASSATTR_ADD)) return "EVENT_CLASSATTR_ADD"; 73 else if (e.isOfType(AttributeEvent.EVENT_CLASSATTR_REMOVE)) return "EVENT_CLASSATTR_REMOVE"; 74 else if (e.isOfType(AttributeEvent.EVENT_CLASSATTR_SET)) return "EVENT_CLASSATTR_SET"; 75 else if (e.isOfType(InstanceEvent.EVENT_INSTANCE_CREATE)) return "EVENT_INSTANCE_CREATE"; 76 else if (e.isOfType(InstanceEvent.EVENT_INSTANCE_DELETE)) return "EVENT_INSTANCE_DELETE"; 77 else if (e.isOfType(AssociationEvent.EVENT_ASSOCIATION_ADD)) return "EVENT_ASSOCIATION_ADD"; 78 else if (e.isOfType(AssociationEvent.EVENT_ASSOCIATION_REMOVE)) return "EVENT_ASSOCIATION_REMOVE"; 79 else if (e.isOfType(AssociationEvent.EVENT_ASSOCIATION_SET)) return "EVENT_ASSOCIATION_SET"; 80 else if (e.isOfType(ExtentEvent.EVENT_EXTENT_CREATE)) return "EVENT_EXTENT_CREATE"; 81 else if (e.isOfType(ExtentEvent.EVENT_EXTENT_DELETE)) return "EVENT_EXTENT_DELETE"; 82 else if (e.isOfType(TransactionEvent.EVENT_TRANSACTION_END)) return "EVENT_TRANSACTION_END"; 83 else if (e.isOfType(TransactionEvent.EVENT_TRANSACTION_START)) return "EVENT_TRANSACTION_START"; 84 else return "<UNKNOWN>"; 85 } 86 92 public static String prettyPrintMask(int mask) { 93 StringBuffer buf = new StringBuffer (); 94 if ( (mask & AttributeEvent.EVENT_ATTRIBUTE_ADD) == AttributeEvent.EVENT_ATTRIBUTE_ADD ) buf.append("IAA "); 95 if ( (mask & AttributeEvent.EVENT_ATTRIBUTE_REMOVE) == AttributeEvent.EVENT_ATTRIBUTE_REMOVE ) buf.append("IAR "); 96 if ( (mask & AttributeEvent.EVENT_ATTRIBUTE_SET) == AttributeEvent.EVENT_ATTRIBUTE_SET ) buf.append("IAS "); 97 if ( (mask & AttributeEvent.EVENT_CLASSATTR_ADD) == AttributeEvent.EVENT_CLASSATTR_ADD ) buf.append("CAA "); 98 if ( (mask & AttributeEvent.EVENT_CLASSATTR_REMOVE) == AttributeEvent.EVENT_CLASSATTR_REMOVE ) buf.append("CAR "); 99 if ( (mask & AttributeEvent.EVENT_CLASSATTR_SET) == AttributeEvent.EVENT_CLASSATTR_SET ) buf.append("CAS "); 100 if ( (mask & InstanceEvent.EVENT_INSTANCE_CREATE) == InstanceEvent.EVENT_INSTANCE_CREATE ) buf.append("IC "); 101 if ( (mask & InstanceEvent.EVENT_INSTANCE_DELETE) == InstanceEvent.EVENT_INSTANCE_DELETE ) buf.append("ID "); 102 if ( (mask & AssociationEvent.EVENT_ASSOCIATION_ADD) == AssociationEvent.EVENT_ASSOCIATION_ADD ) buf.append("AA "); 103 if ( (mask & AssociationEvent.EVENT_ASSOCIATION_REMOVE) == AssociationEvent.EVENT_ASSOCIATION_REMOVE ) buf.append("AR "); 104 if ( (mask & AssociationEvent.EVENT_ASSOCIATION_SET) == AssociationEvent.EVENT_ASSOCIATION_SET ) buf.append("AS "); 105 if ( (mask & ExtentEvent.EVENT_EXTENT_CREATE) == ExtentEvent.EVENT_EXTENT_CREATE ) buf.append("EC "); 106 if ( (mask & ExtentEvent.EVENT_EXTENT_DELETE) == ExtentEvent.EVENT_EXTENT_DELETE ) buf.append("ED "); 107 if ( (mask & TransactionEvent.EVENT_TRANSACTION_END) == TransactionEvent.EVENT_TRANSACTION_END ) buf.append("TE "); 108 if ( (mask & TransactionEvent.EVENT_TRANSACTION_START) == TransactionEvent.EVENT_TRANSACTION_START ) buf.append("TS "); 109 if ( buf.length() > 0 ) buf.deleteCharAt(buf.length()-1); 110 return buf.toString(); 111 } 112 113 114 115 116 117 public final Association ASSOCIATION = new Association(); 118 public final Clazz CLASS = new Clazz(); 119 public final Instance INSTANCE = new Instance(); 120 public final Package PACKAGE = new Package (); 121 public final Repository REPOSITORY = new Repository(); 122 123 124 125 126 127 130 private final Thread dispatcher = new Thread (new EventsDelivery(), "MDR event dispatcher"); 131 132 135 private final HashMap preChangeListeners = new HashMap(); 136 137 140 private final Hashtable changeListeners = new Hashtable(); 141 142 147 private final LinkedList localQueue = new LinkedList(); 148 149 153 private final LinkedList globalQueue = new LinkedList(); 154 155 158 private boolean shuttingDown = false; 159 160 161 162 163 164 167 public EventNotifier() { 168 dispatcher.setDaemon(true); 169 dispatcher.start(); 170 } 171 172 173 174 175 176 181 public void fireCancelled(MDRChangeEvent event) { 182 localQueue.remove(event); 183 Set collected = (Set) preChangeListeners.remove(event); 184 changeListeners.remove(event); 185 if (collected == null) { 186 Logger.getDefault().notify(Logger.INFORMATIONAL, new DebugException("Change cancelled event not corresponding to any planned change event.")); 187 return; 188 } 189 for (Iterator it = collected.iterator(); it.hasNext();) { 191 try { 192 ((MDRPreChangeListener) it.next()).changeCancelled(event); 193 } catch (RuntimeException e) { 194 Logger.getDefault().notify(Logger.INFORMATIONAL, e); 196 } 197 } 198 } 199 200 205 public void fireCancelled() { 206 while (!localQueue.isEmpty()) { 207 MDRChangeEvent event = (MDRChangeEvent) localQueue.getFirst(); 208 fireCancelled(event); 209 } 210 } 211 212 216 public void fireChanged() { 217 preChangeListeners.clear(); 218 synchronized (globalQueue) { 219 globalQueue.addAll(localQueue); 220 globalQueue.notify(); 221 } 222 localQueue.clear(); 223 } 224 225 227 public void shutdown() { 228 synchronized (globalQueue) { 229 shuttingDown = true; 230 globalQueue.notify(); 231 } 232 } 233 234 235 236 237 238 246 private class EventsDelivery implements Runnable { 247 250 public void run() { 251 Collection collected; 252 MDRChangeEvent event; 253 254 while (true) { 255 synchronized (globalQueue) { 256 for (;;) { 257 if (!globalQueue.isEmpty()) 258 break; 259 else if (shuttingDown) 260 return; 261 262 try { 263 globalQueue.wait(); 264 } catch (InterruptedException e) { 265 Logger.getDefault().notify(Logger.INFORMATIONAL, e); 266 } 267 } 268 collected = (Collection) changeListeners.remove(event = (MDRChangeEvent) globalQueue.removeFirst()); 269 } 270 if (collected == null) { 271 Logger.getDefault().notify(Logger.INFORMATIONAL, new DebugException("Change event not corresponding to any planned change event.")); 272 return; 273 } 274 for (Iterator it = collected.iterator(); it.hasNext();) { 275 try { 276 ((MDRChangeListener) it.next()).change(event); 277 } catch (RuntimeException e) { 278 Logger.getDefault().notify(Logger.INFORMATIONAL, e); 279 } 280 } 281 } 282 } 283 } 284 285 286 287 288 289 293 public abstract class Abstract { 294 297 private final Map registeredListenerSets = new Map () { 298 public Set keySet() { throw new UnsupportedOperationException (); } 299 public Set entrySet() { throw new UnsupportedOperationException (); } 300 public void putAll(Map t) { throw new UnsupportedOperationException (); } 301 public boolean isEmpty() { throw new UnsupportedOperationException (); } 302 public boolean containsKey(Object key) { throw new UnsupportedOperationException (); } 303 public boolean containsValue(Object value) { throw new UnsupportedOperationException (); } 304 public Collection values() { throw new UnsupportedOperationException (); } 305 public void clear() { throw new UnsupportedOperationException (); } 306 public int size() { throw new UnsupportedOperationException (); } 307 308 private final Map inner = new HashMap(); 309 310 private Object extractKey(Object key) { 311 if (key instanceof BaseObjectHandler) { 312 try { 313 key = ((BaseObjectHandler) key)._getMofId(); 314 } catch (InvalidObjectException e) { 315 return null; 317 } 318 } 319 return key; 320 } 321 322 public Object put(Object key, Object value) { 323 key = extractKey(key); 324 if (key != null) { 325 return inner.put(key, value); 326 } else { 327 return null; 328 } 329 } 330 331 public Object get(Object key) { 332 key = extractKey(key); 333 if (key != null) { 334 return inner.get(key); 335 } else { 336 return null; 337 } 338 } 339 340 public Object remove(Object key) { 341 key = extractKey(key); 342 if (key != null) { 343 return inner.remove(key); 344 } else { 345 return null; 346 } 347 } 348 }; 349 350 354 public void addListener(MDRChangeListener listener, int mask, Object source) { 355 if ( (listener == null) || (mask == 0) ) return; 356 357 synchronized (registeredListenerSets) { 358 RegisteredListenerSet value = (RegisteredListenerSet) registeredListenerSets.get(source); 359 if ( value == null ) { 360 value = new RegisteredListenerSet(); 361 registeredListenerSets.put(source, value); 362 } 363 value.addListener(listener, mask); 364 } 365 } 366 367 370 public void removeListener(MDRChangeListener listener, Object source) { 371 if ( listener == null ) return; 372 373 synchronized (registeredListenerSets) { 374 RegisteredListenerSet value = (RegisteredListenerSet) registeredListenerSets.get(source); 375 if ( value != null ) { 376 value.removeListener(listener); 377 if ( value.isEmpty() ) { 378 registeredListenerSets.remove(source); 379 } 380 } 381 } 382 } 383 384 388 public void removeListener(MDRChangeListener listener, int mask, Object source) { 389 if ( (listener == null) || (mask == 0) ) return; 390 391 synchronized (registeredListenerSets) { 392 RegisteredListenerSet value = (RegisteredListenerSet) registeredListenerSets.get(source); 393 if ( value != null ) { 394 value.removeListener(listener, mask); 395 if ( value.isEmpty() ) { 396 registeredListenerSets.remove(source); 397 } 398 } 399 } 400 } 401 402 411 public void firePlannedChange(Object current, MDRChangeEvent event) { 412 HashSet preChange = new HashSet(); 413 HashSet postChange = new HashSet(); 414 collectListeners(current, event, preChange, postChange); 416 if (!(preChange.isEmpty() && postChange.isEmpty())) { 417 localQueue.addLast(event); 418 for (Iterator it = preChange.iterator(); it.hasNext();) { 419 try { 420 ((MDRPreChangeListener) it.next()).plannedChange(event); 421 } catch (RuntimeException e) { 422 if (e instanceof VetoChangeException) { 423 throw e; 424 } 425 Logger.getDefault().notify(Logger.INFORMATIONAL, e); 426 } 427 } 428 if (preChangeListeners.put(event, preChange) != null) { 429 throw new DebugException("Same event fired twice."); 430 } 431 CompositeCollection all = new CompositeCollection(); 432 all.addCollection(preChange); 433 all.addCollection(postChange); 434 if (changeListeners.put(event, all) != null) { 435 throw new DebugException("Same event fired twice."); 436 } 437 } 438 } 439 440 456 protected void collectListeners(Object current, MDRChangeEvent event, Set preChange, Set postChange) { 457 synchronized (registeredListenerSets) { 459 RegisteredListenerSet value = (RegisteredListenerSet) registeredListenerSets.get(current); 460 if (value != null) { 461 value.collectListeners(event, preChange, postChange); 462 } 463 } 464 } 465 466 public Collection getListeners(Object source) { 467 synchronized (registeredListenerSets) { 468 RegisteredListenerSet value = (RegisteredListenerSet) registeredListenerSets.get(source); 469 if (value != null) { 470 return new ArrayList(value.map.keySet()); 471 } else { 472 return Collections.EMPTY_LIST; 473 } 474 } 475 } 476 } 477 478 479 480 481 482 485 public final class Association extends Abstract { 486 private Association() { 487 super(); 488 } 489 490 public void addListener(MDRChangeListener listener, int mask, Object source) { 491 super.addListener(listener, mask & EventNotifier.EVENTMASK_BY_ASSOCIATION, source); 492 } 493 public void removeListener(MDRChangeListener listener, int mask, Object source) { 494 super.removeListener(listener, mask & EventNotifier.EVENTMASK_BY_ASSOCIATION, source); 495 } 496 497 501 protected void collectListeners(Object current, MDRChangeEvent event, Set preChange, Set postChange) { 502 super.collectListeners(current, event, preChange, postChange); 503 504 if (event instanceof AssociationEvent) { 506 AssociationEvent assocEvent = (AssociationEvent) event; 507 if (assocEvent.getFixedElement() != null) INSTANCE.collectListeners(assocEvent.getFixedElement(), event, preChange, postChange); 508 if (assocEvent.getOldElement() != null) INSTANCE.collectListeners(assocEvent.getOldElement(), event, preChange, postChange); 509 if (assocEvent.getNewElement() != null) INSTANCE.collectListeners(assocEvent.getNewElement(), event, preChange, postChange); 510 } 511 512 PACKAGE.collectListeners(((RefAssociation) current).refImmediatePackage(), event, preChange, postChange); 514 } 515 } 516 517 518 519 520 521 524 public final class Clazz extends Abstract { 525 private Clazz() { 526 super(); 527 } 528 529 public void addListener(MDRChangeListener listener, int mask, Object source) { 530 super.addListener(listener, mask & EventNotifier.EVENTMASK_BY_CLASS, source); 531 } 532 public void removeListener(MDRChangeListener listener, int mask, Object source) { 533 super.removeListener(listener, mask & EventNotifier.EVENTMASK_BY_CLASS, source); 534 } 535 536 539 protected void collectListeners(Object current, MDRChangeEvent event, Set preChange, Set postChange) { 540 super.collectListeners(current, event, preChange, postChange); 541 PACKAGE.collectListeners(((RefClass) current).refImmediatePackage(), event, preChange, postChange); 542 } 543 } 544 545 546 547 548 549 552 public final class Instance extends Abstract { 553 private Instance() { 554 super(); 555 } 556 557 public void addListener(MDRChangeListener listener, int mask, Object source) { 558 super.addListener(listener, mask & EventNotifier.EVENTMASK_BY_INSTANCE, source); 559 } 560 public void removeListener(MDRChangeListener listener, int mask, Object source) { 561 super.removeListener(listener, mask & EventNotifier.EVENTMASK_BY_INSTANCE, source); 562 } 563 564 567 protected void collectListeners(Object current, MDRChangeEvent event, Set preChange, Set postChange) { 568 super.collectListeners(current, event, preChange, postChange); 569 CLASS.collectListeners(((RefObject) current).refClass(), event, preChange, postChange); 570 } 571 } 572 573 574 575 576 577 580 public final class Package extends Abstract { 581 private Package() { 582 super(); 583 } 584 585 public void addListener(MDRChangeListener listener, int mask, Object source) { 586 super.addListener(listener, mask & EventNotifier.EVENTMASK_BY_PACKAGE, source); 587 } 588 public void removeListener(MDRChangeListener listener, int mask, Object source) { 589 super.removeListener(listener, mask & EventNotifier.EVENTMASK_BY_PACKAGE, source); 590 } 591 592 596 protected void collectListeners(Object current, MDRChangeEvent event, Set preChange, Set postChange) { 597 super.collectListeners(current, event, preChange, postChange); 598 RefPackage immediate = ((RefPackage) current).refImmediatePackage(); 599 if (immediate != null) { 600 collectListeners(immediate, event, preChange, postChange); 601 } else { 602 REPOSITORY.collectListeners(((BaseObjectHandler) current)._getDelegate().getMdrStorage(), event, preChange, postChange); 603 } 604 } 605 } 606 607 608 609 610 611 614 public final class Repository extends Abstract { 615 private Repository() { 616 super(); 617 } 618 619 public void addListener(MDRChangeListener listener, int mask, Object source) { 620 super.addListener(listener, mask & EventNotifier.EVENTMASK_BY_REPOSITORY, source); 621 } 622 public void removeListener(MDRChangeListener listener, int mask, Object source) { 623 super.removeListener(listener, mask & EventNotifier.EVENTMASK_BY_REPOSITORY, source); 624 } 625 } 626 627 628 629 630 631 632 633 634 635 636 657 static class RegisteredListenerSet { 658 659 662 HashMap map = new HashMap(); 663 664 667 void addListener(MDRChangeListener listener, int mask) { 668 Integer value = (Integer ) map.get(listener); 669 if ( value != null ) { 670 int currentMask = value.intValue(); 672 mask |= currentMask; 673 if ( (mask ^ currentMask) == 0 ) { 674 return; 676 } 677 } 678 map.put(listener, new Integer (mask)); 679 } 680 681 684 void removeListener(MDRChangeListener listener) { 685 map.remove(listener); 686 } 687 688 691 void removeListener(MDRChangeListener listener, int mask) { 692 Object value = map.get(listener); 693 if ( value != null ) { 694 int currentMask = ((Integer ) value).intValue(); 696 mask = currentMask & (~mask); 697 if (mask == 0) { 698 removeListener(listener); 700 } else { 701 map.put(listener, new Integer (mask)); 703 } 704 } 705 } 706 707 715 void collectListeners(MDRChangeEvent event, Set preChange, Set postChange) { 716 Iterator it = map.entrySet().iterator(); 717 718 while ( it.hasNext() ) { 719 Map.Entry entry = (Map.Entry ) it.next(); 720 if ( event.isOfType(((Integer )entry.getValue()).intValue()) ) { 721 Object key = entry.getKey(); 722 if ( key instanceof MDRPreChangeListener ) { 723 preChange.add(key); 724 } else { 725 postChange.add(key); 726 } 727 } 728 } 729 } 730 731 735 boolean isEmpty() { 736 return map.isEmpty(); 737 } 738 } 739 } 740 | Popular Tags |