1 | |
|
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | |
|
18 | |
|
19 | |
|
20 | |
|
21 | |
|
22 | |
|
23 | |
|
24 | |
|
25 | |
|
26 | |
|
27 | |
|
28 | |
|
29 | |
|
30 | |
|
31 | |
|
32 | |
|
33 | |
|
34 | |
|
35 | |
|
36 | |
|
37 | |
|
38 | |
|
39 | |
package org.argouml.model.mdr; |
40 | |
|
41 | |
import java.beans.PropertyChangeListener; |
42 | |
import java.util.ArrayList; |
43 | |
import java.util.Collection; |
44 | |
import java.util.Collections; |
45 | |
import java.util.HashMap; |
46 | |
import java.util.HashSet; |
47 | |
import java.util.Iterator; |
48 | |
import java.util.List; |
49 | |
import java.util.Map; |
50 | |
import java.util.Set; |
51 | |
|
52 | |
import javax.jmi.model.Association; |
53 | |
import javax.jmi.model.AssociationEnd; |
54 | |
import javax.jmi.model.Attribute; |
55 | |
import javax.jmi.model.GeneralizableElement; |
56 | |
import javax.jmi.model.ModelElement; |
57 | |
import javax.jmi.model.ModelPackage; |
58 | |
import javax.jmi.model.MofClass; |
59 | |
import javax.jmi.model.NameNotFoundException; |
60 | |
import javax.jmi.model.Reference; |
61 | |
import javax.jmi.reflect.InvalidObjectException; |
62 | |
import javax.jmi.reflect.RefAssociation; |
63 | |
import javax.jmi.reflect.RefBaseObject; |
64 | |
import javax.jmi.reflect.RefObject; |
65 | |
|
66 | |
import org.apache.log4j.Logger; |
67 | |
import org.argouml.model.AbstractModelEventPump; |
68 | |
import org.argouml.model.AddAssociationEvent; |
69 | |
import org.argouml.model.AttributeChangeEvent; |
70 | |
import org.argouml.model.DeleteInstanceEvent; |
71 | |
import org.argouml.model.InvalidElementException; |
72 | |
import org.argouml.model.Model; |
73 | |
import org.argouml.model.RemoveAssociationEvent; |
74 | |
import org.argouml.model.UmlChangeEvent; |
75 | |
import org.netbeans.api.mdr.MDRManager; |
76 | |
import org.netbeans.api.mdr.MDRepository; |
77 | |
import org.netbeans.api.mdr.events.AssociationEvent; |
78 | |
import org.netbeans.api.mdr.events.AttributeEvent; |
79 | |
import org.netbeans.api.mdr.events.InstanceEvent; |
80 | |
import org.netbeans.api.mdr.events.MDRChangeEvent; |
81 | |
import org.netbeans.api.mdr.events.MDRPreChangeListener; |
82 | |
import org.netbeans.api.mdr.events.TransactionEvent; |
83 | |
import org.netbeans.api.mdr.events.VetoChangeException; |
84 | |
|
85 | |
|
86 | |
|
87 | |
|
88 | |
|
89 | |
|
90 | |
|
91 | |
|
92 | |
|
93 | |
|
94 | |
|
95 | |
|
96 | |
|
97 | |
|
98 | |
class ModelEventPumpMDRImpl extends AbstractModelEventPump implements |
99 | |
MDRPreChangeListener { |
100 | |
|
101 | |
|
102 | |
|
103 | |
|
104 | 900 | private static final Logger LOG = |
105 | |
Logger.getLogger(ModelEventPumpMDRImpl.class); |
106 | |
|
107 | |
private static final boolean VETO_READONLY_CHANGES = true; |
108 | |
|
109 | |
private MDRModelImplementation modelImpl; |
110 | |
|
111 | 900 | private Object registrationMutex = new Byte[0]; |
112 | |
|
113 | |
private MDRepository repository; |
114 | |
|
115 | 900 | private Boolean eventCountMutex = new Boolean(false); |
116 | 900 | private int pendingEvents = 0; |
117 | |
|
118 | |
private Thread eventThread; |
119 | |
|
120 | |
|
121 | |
|
122 | |
|
123 | 900 | private Registry<PropertyChangeListener> elements = |
124 | |
new Registry<PropertyChangeListener>(); |
125 | |
|
126 | |
|
127 | |
|
128 | |
|
129 | 900 | private Registry<PropertyChangeListener> listenedClasses = |
130 | |
new Registry<PropertyChangeListener>(); |
131 | |
|
132 | |
|
133 | |
|
134 | |
|
135 | |
private Map<String, Collection<String>> subtypeMap; |
136 | |
|
137 | |
|
138 | |
|
139 | |
|
140 | |
|
141 | |
private Map<String, Collection<String>> propertyNameMap; |
142 | |
|
143 | |
|
144 | |
|
145 | |
|
146 | |
|
147 | |
|
148 | |
public ModelEventPumpMDRImpl(MDRModelImplementation implementation) { |
149 | 0 | this(implementation, MDRManager.getDefault().getDefaultRepository()); |
150 | 0 | } |
151 | |
|
152 | |
|
153 | |
|
154 | |
|
155 | |
|
156 | |
|
157 | |
|
158 | |
public ModelEventPumpMDRImpl(MDRModelImplementation implementation, |
159 | |
MDRepository repo) { |
160 | 900 | super(); |
161 | 900 | modelImpl = implementation; |
162 | 900 | repository = repo; |
163 | 900 | subtypeMap = buildTypeMap(modelImpl.getModelPackage()); |
164 | 900 | propertyNameMap = buildPropertyNameMap(modelImpl.getModelPackage()); |
165 | 900 | } |
166 | |
|
167 | |
|
168 | |
|
169 | |
|
170 | |
|
171 | |
public void addModelEventListener(PropertyChangeListener listener, |
172 | |
Object modelElement, String[] propertyNames) { |
173 | 2174 | if (listener == null) { |
174 | 0 | throw new IllegalArgumentException("A listener must be supplied"); |
175 | |
} |
176 | |
|
177 | 2174 | if (modelElement == null) { |
178 | 0 | throw new IllegalArgumentException( |
179 | |
"A model element must be supplied"); |
180 | |
} |
181 | |
|
182 | 2174 | registerModelEvent(listener, modelElement, propertyNames); |
183 | 2174 | } |
184 | |
|
185 | |
|
186 | |
|
187 | |
|
188 | |
|
189 | |
public void addModelEventListener(PropertyChangeListener listener, |
190 | |
Object modelElement) { |
191 | 900 | if (listener == null) { |
192 | 0 | throw new IllegalArgumentException("A listener must be supplied"); |
193 | |
} |
194 | |
|
195 | 900 | if (modelElement == null) { |
196 | 0 | throw new IllegalArgumentException( |
197 | |
"A model element must be supplied"); |
198 | |
} |
199 | |
|
200 | 900 | registerModelEvent(listener, modelElement, null); |
201 | 900 | } |
202 | |
|
203 | |
|
204 | |
|
205 | |
|
206 | |
|
207 | |
public void removeModelEventListener(PropertyChangeListener listener, |
208 | |
Object modelelement, String[] propertyNames) { |
209 | 1 | unregisterModelEvent(listener, modelelement, propertyNames); |
210 | 1 | } |
211 | |
|
212 | |
|
213 | |
|
214 | |
|
215 | |
|
216 | |
public void removeModelEventListener(PropertyChangeListener listener, |
217 | |
Object modelelement) { |
218 | 0 | unregisterModelEvent(listener, modelelement, null); |
219 | 0 | } |
220 | |
|
221 | |
|
222 | |
|
223 | |
|
224 | |
|
225 | |
public void addClassModelEventListener(PropertyChangeListener listener, |
226 | |
Object modelClass, String[] propertyNames) { |
227 | 900 | registerClassEvent(listener, modelClass, propertyNames); |
228 | 900 | } |
229 | |
|
230 | |
|
231 | |
|
232 | |
|
233 | |
|
234 | |
public void removeClassModelEventListener(PropertyChangeListener listener, |
235 | |
Object modelClass, String[] propertyNames) { |
236 | 0 | unregisterClassEvent(listener, modelClass, propertyNames); |
237 | 0 | } |
238 | |
|
239 | |
|
240 | |
|
241 | |
|
242 | |
|
243 | |
|
244 | |
|
245 | |
|
246 | |
|
247 | |
|
248 | |
|
249 | |
|
250 | |
|
251 | |
|
252 | |
|
253 | |
|
254 | |
|
255 | |
|
256 | |
|
257 | |
|
258 | |
|
259 | |
public void change(MDRChangeEvent mdrEvent) { |
260 | |
|
261 | 6985 | if (eventThread == null) { |
262 | 900 | eventThread = Thread.currentThread(); |
263 | |
} |
264 | |
|
265 | |
|
266 | |
|
267 | 6985 | decrementEvents(); |
268 | |
|
269 | |
|
270 | |
|
271 | 6985 | if (mdrEvent instanceof TransactionEvent) { |
272 | 4604 | return; |
273 | |
} |
274 | |
|
275 | 2381 | List<UmlChangeEvent> events = new ArrayList<UmlChangeEvent>(); |
276 | |
|
277 | 2381 | if (mdrEvent instanceof AttributeEvent) { |
278 | 996 | AttributeEvent ae = (AttributeEvent) mdrEvent; |
279 | 996 | events.add(new AttributeChangeEvent(ae.getSource(), |
280 | |
ae.getAttributeName(), ae.getOldElement(), |
281 | |
ae.getNewElement(), mdrEvent)); |
282 | 996 | } else if (mdrEvent instanceof InstanceEvent |
283 | |
&& mdrEvent.isOfType(InstanceEvent.EVENT_INSTANCE_DELETE)) { |
284 | 2 | InstanceEvent ie = (InstanceEvent) mdrEvent; |
285 | 2 | events.add(new DeleteInstanceEvent(ie.getSource(), |
286 | |
"remove", null, null, mdrEvent)); |
287 | |
|
288 | 2 | String mofid = ((InstanceEvent)mdrEvent).getInstance().refMofId(); |
289 | 2 | modelImpl.removeElement(mofid); |
290 | 2 | } else if (mdrEvent instanceof AssociationEvent) { |
291 | 329 | AssociationEvent ae = (AssociationEvent) mdrEvent; |
292 | 329 | if (ae.isOfType(AssociationEvent.EVENT_ASSOCIATION_ADD)) { |
293 | 250 | events.add(new AddAssociationEvent( |
294 | |
ae.getNewElement(), |
295 | |
mapPropertyName(ae.getEndName()), |
296 | |
ae.getOldElement(), |
297 | |
ae.getFixedElement(), |
298 | |
ae.getFixedElement(), |
299 | |
mdrEvent)); |
300 | |
|
301 | 250 | events.add(new AttributeChangeEvent( |
302 | |
ae.getNewElement(), |
303 | |
mapPropertyName(ae.getEndName()), |
304 | |
ae.getOldElement(), |
305 | |
ae.getFixedElement(), |
306 | |
mdrEvent)); |
307 | |
|
308 | 250 | events.add(new AddAssociationEvent( |
309 | |
ae.getFixedElement(), |
310 | |
otherAssocEnd(ae), |
311 | |
ae.getOldElement(), |
312 | |
ae.getNewElement(), |
313 | |
ae.getNewElement(), |
314 | |
mdrEvent)); |
315 | |
|
316 | 250 | events.add(new AttributeChangeEvent( |
317 | |
ae.getFixedElement(), |
318 | |
otherAssocEnd(ae), |
319 | |
ae.getOldElement(), |
320 | |
ae.getNewElement(), |
321 | |
mdrEvent)); |
322 | 79 | } else if (ae.isOfType(AssociationEvent.EVENT_ASSOCIATION_REMOVE)) { |
323 | 79 | events.add(new RemoveAssociationEvent( |
324 | |
ae.getOldElement(), |
325 | |
mapPropertyName(ae.getEndName()), |
326 | |
ae.getFixedElement(), |
327 | |
ae.getNewElement(), |
328 | |
ae.getFixedElement(), |
329 | |
mdrEvent)); |
330 | |
|
331 | 79 | events.add(new AttributeChangeEvent( |
332 | |
ae.getOldElement(), |
333 | |
mapPropertyName(ae.getEndName()), |
334 | |
ae.getFixedElement(), |
335 | |
ae.getNewElement(), |
336 | |
mdrEvent)); |
337 | |
|
338 | 79 | events.add(new RemoveAssociationEvent( |
339 | |
ae.getFixedElement(), |
340 | |
otherAssocEnd(ae), |
341 | |
ae.getOldElement(), |
342 | |
ae.getNewElement(), |
343 | |
ae.getOldElement(), |
344 | |
mdrEvent)); |
345 | |
|
346 | 79 | events.add(new AttributeChangeEvent( |
347 | |
ae.getFixedElement(), |
348 | |
otherAssocEnd(ae), |
349 | |
ae.getOldElement(), |
350 | |
ae.getNewElement(), |
351 | |
mdrEvent)); |
352 | 0 | } else if (ae.isOfType(AssociationEvent.EVENT_ASSOCIATION_SET)) { |
353 | 0 | LOG.error("Unexpected EVENT_ASSOCIATION_SET received"); |
354 | |
} else { |
355 | 0 | LOG.error("Unknown association event type " + ae.getType()); |
356 | |
} |
357 | 329 | } else { |
358 | 1054 | if (LOG.isDebugEnabled()) { |
359 | 0 | String name = mdrEvent.getClass().getName(); |
360 | |
|
361 | 0 | if (!name.endsWith("CreateInstanceEvent")) { |
362 | 0 | LOG.debug("Ignoring MDR event " + mdrEvent); |
363 | |
} |
364 | |
} |
365 | |
} |
366 | |
|
367 | 2381 | for (UmlChangeEvent event : events) { |
368 | 2314 | fire(event); |
369 | |
|
370 | 2314 | if (event instanceof DeleteInstanceEvent) { |
371 | 2 | elements.unregister(null, ((RefBaseObject) event.getSource()) |
372 | |
.refMofId(), null); |
373 | |
} |
374 | |
} |
375 | 2381 | } |
376 | |
|
377 | |
private boolean isReadOnly(RefBaseObject object) { |
378 | 2052 | return modelImpl.isReadOnly(object.refOutermostPackage()); |
379 | |
} |
380 | |
|
381 | |
|
382 | |
|
383 | |
|
384 | |
|
385 | |
public void plannedChange(MDRChangeEvent e) { |
386 | |
|
387 | |
if (VETO_READONLY_CHANGES) { |
388 | 6985 | if (e instanceof InstanceEvent) { |
389 | 1056 | if (e.isOfType(InstanceEvent.EVENT_INSTANCE_CREATE)) { |
390 | 1054 | RefBaseObject element = (RefBaseObject) ((InstanceEvent) e) |
391 | |
.getSource(); |
392 | 1054 | if (isReadOnly(element)) { |
393 | 0 | throw new VetoChangeException(e.getSource(), null); |
394 | |
} |
395 | 1054 | } else { |
396 | 2 | RefObject element = ((InstanceEvent) e).getInstance(); |
397 | 2 | if (isReadOnly(element)) { |
398 | 0 | throw new VetoChangeException(e.getSource(), element); |
399 | |
} |
400 | 2 | } |
401 | 5929 | } else if (e instanceof AssociationEvent) { |
402 | |
|
403 | |
|
404 | |
|
405 | |
|
406 | |
|
407 | |
|
408 | |
|
409 | 5600 | } else if (e instanceof AttributeEvent) { |
410 | 996 | RefObject element = (RefObject) ((AttributeEvent) e) |
411 | |
.getSource(); |
412 | 996 | if (isReadOnly(element)) { |
413 | 0 | throw new VetoChangeException(element, element); |
414 | |
} |
415 | |
} |
416 | |
} |
417 | |
|
418 | 6985 | synchronized (eventCountMutex) { |
419 | 6985 | pendingEvents++; |
420 | 6985 | } |
421 | |
|
422 | |
|
423 | |
|
424 | |
|
425 | |
|
426 | |
|
427 | |
|
428 | |
|
429 | |
|
430 | |
|
431 | |
|
432 | |
|
433 | 6985 | } |
434 | |
|
435 | |
|
436 | |
|
437 | |
|
438 | |
|
439 | |
|
440 | |
|
441 | |
public void changeCancelled(MDRChangeEvent e) { |
442 | 0 | decrementEvents(); |
443 | 0 | } |
444 | |
|
445 | |
|
446 | |
|
447 | |
|
448 | |
|
449 | |
private void decrementEvents() { |
450 | |
|
451 | 6985 | synchronized (eventCountMutex) { |
452 | 6985 | pendingEvents--; |
453 | 6985 | if (pendingEvents <= 0) { |
454 | 2077 | eventCountMutex.notifyAll(); |
455 | |
} |
456 | 6985 | } |
457 | 6985 | } |
458 | |
|
459 | |
|
460 | |
|
461 | |
|
462 | |
private void fire(UmlChangeEvent event) { |
463 | 2314 | String mofId = ((RefBaseObject) event.getSource()).refMofId(); |
464 | 2314 | String className = getClassName(event.getSource()); |
465 | |
|
466 | |
|
467 | |
|
468 | 2314 | Set<PropertyChangeListener> listeners = |
469 | |
new HashSet<PropertyChangeListener>(); |
470 | 2314 | synchronized (registrationMutex) { |
471 | 2314 | listeners.addAll(elements.getMatches(mofId, event |
472 | |
.getPropertyName())); |
473 | |
|
474 | |
|
475 | 2314 | listeners.addAll(listenedClasses.getMatches(className, event |
476 | |
.getPropertyName())); |
477 | 2314 | } |
478 | |
|
479 | 2314 | if (LOG.isDebugEnabled()) { |
480 | 0 | LOG.debug("Firing " |
481 | |
+ modelImpl.getMetaTypes().getName(event) |
482 | |
+ " source " |
483 | |
+ modelImpl.getMetaTypes().getName( |
484 | |
event.getSource()) |
485 | |
+ " [" + ((RefBaseObject) event.getSource()).refMofId() |
486 | |
+ "]." + event.getPropertyName() |
487 | |
+ "," + formatElement(event.getOldValue()) |
488 | |
+ "->" + formatElement(event.getNewValue())); |
489 | |
} |
490 | |
|
491 | 2314 | if (!listeners.isEmpty()) { |
492 | 2314 | for (PropertyChangeListener pcl : listeners) { |
493 | |
if (false ) { |
494 | |
LOG.debug("Firing event on " + pcl.getClass().getName() |
495 | |
+ "[" + pcl + "]"); |
496 | |
} |
497 | 2547 | pcl.propertyChange(event); |
498 | |
} |
499 | |
} else { |
500 | |
|
501 | |
|
502 | |
if (false) { |
503 | |
LOG.debug("No listener for " |
504 | |
+ modelImpl.getMetaTypes().getName(event) |
505 | |
+ " source " |
506 | |
+ modelImpl.getMetaTypes().getName( |
507 | |
event.getSource()) |
508 | |
+ " [" |
509 | |
+ ((RefBaseObject) event.getSource()).refMofId() + "]." |
510 | |
+ event.getPropertyName() + "," + event.getOldValue() |
511 | |
+ "->" + event.getNewValue()); |
512 | |
} |
513 | |
} |
514 | 2314 | } |
515 | |
|
516 | |
|
517 | |
|
518 | |
|
519 | |
|
520 | |
|
521 | |
private void registerModelEvent(PropertyChangeListener listener, |
522 | |
Object modelElement, String[] propertyNames) { |
523 | 3074 | if (listener == null || modelElement == null) { |
524 | 0 | throw new IllegalArgumentException("Neither listener (" + listener |
525 | |
+ ") or modelElement (" + modelElement |
526 | |
+ ") can be null! [Property names: " + propertyNames + "]"); |
527 | |
} |
528 | |
|
529 | |
|
530 | 3074 | String mofId = ((RefBaseObject) modelElement).refMofId(); |
531 | |
try { |
532 | 3074 | verifyAttributeNames(((RefBaseObject) modelElement).refMetaObject(), |
533 | |
propertyNames); |
534 | 0 | } catch (InvalidObjectException e) { |
535 | 0 | throw new InvalidElementException(e); |
536 | 3074 | } |
537 | 3074 | if (LOG.isDebugEnabled()) { |
538 | 0 | LOG.debug("Register [" |
539 | |
+ " element:" + formatElement(modelElement) |
540 | |
+ ", properties:" + formatArray(propertyNames) |
541 | |
+ ", listener:" + listener |
542 | |
+ "]"); |
543 | |
} |
544 | 3074 | synchronized (registrationMutex) { |
545 | 3074 | elements.register(listener, mofId, propertyNames); |
546 | 3074 | } |
547 | 3074 | } |
548 | |
|
549 | |
|
550 | |
|
551 | |
|
552 | |
private void unregisterModelEvent(PropertyChangeListener listener, |
553 | |
Object modelElement, String[] propertyNames) { |
554 | 1 | if (listener == null || modelElement == null) { |
555 | 0 | LOG.error("Attempt to unregister null listener(" + listener |
556 | |
+ ") or modelElement (" + modelElement |
557 | |
+ ")! [Property names: " + propertyNames + "]"); |
558 | 0 | return; |
559 | |
} |
560 | 1 | if (!(modelElement instanceof RefBaseObject)) { |
561 | 0 | LOG.error("Ignoring non-RefBaseObject received by " |
562 | |
+ "unregisterModelEvent - " + modelElement); |
563 | 0 | return; |
564 | |
} |
565 | 1 | String mofId = ((RefBaseObject) modelElement).refMofId(); |
566 | 1 | if (LOG.isDebugEnabled()) { |
567 | 0 | LOG.debug("Unregister [" |
568 | |
+ " element:" + formatElement(modelElement) |
569 | |
+ ", properties:" + formatArray(propertyNames) |
570 | |
+ ", listener:" + listener |
571 | |
+ "]"); |
572 | |
} |
573 | 1 | synchronized (registrationMutex) { |
574 | 1 | elements.unregister(listener, mofId, propertyNames); |
575 | 1 | } |
576 | 1 | } |
577 | |
|
578 | |
|
579 | |
|
580 | |
|
581 | |
|
582 | |
|
583 | |
|
584 | |
|
585 | |
|
586 | |
private void registerClassEvent(PropertyChangeListener listener, |
587 | |
Object modelClass, String[] propertyNames) { |
588 | |
|
589 | 900 | if (modelClass instanceof Class) { |
590 | 900 | String className = getClassName(modelClass); |
591 | 900 | if (LOG.isDebugEnabled()) { |
592 | 0 | LOG.debug("Register class [" |
593 | |
+ modelImpl.getMetaTypes().getName(modelClass) |
594 | |
+ "properties:" + formatArray(propertyNames) |
595 | |
+ ", listener:" + listener + "]"); |
596 | |
} |
597 | 900 | Collection<String> subtypes = subtypeMap.get(className); |
598 | 900 | verifyAttributeNames(className, propertyNames); |
599 | 900 | synchronized (registrationMutex) { |
600 | 900 | listenedClasses.register(listener, className, propertyNames); |
601 | 900 | for (String subtype : subtypes) { |
602 | 90900 | listenedClasses.register(listener, subtype, propertyNames); |
603 | |
} |
604 | 900 | } |
605 | 900 | return; |
606 | |
} |
607 | 0 | throw new IllegalArgumentException( |
608 | |
"Don't know how to register class event for object " |
609 | |
+ modelClass); |
610 | |
} |
611 | |
|
612 | |
|
613 | |
|
614 | |
|
615 | |
|
616 | |
private void unregisterClassEvent(PropertyChangeListener listener, |
617 | |
Object modelClass, String[] propertyNames) { |
618 | 0 | if (modelClass instanceof Class) { |
619 | 0 | String className = getClassName(modelClass); |
620 | 0 | if (LOG.isDebugEnabled()) { |
621 | 0 | LOG.debug("Unregister class [" + className |
622 | |
+ ", properties:" + formatArray(propertyNames) |
623 | |
+ ", listener:" + listener + "]"); |
624 | |
} |
625 | 0 | Collection<String> subtypes = subtypeMap.get(className); |
626 | 0 | synchronized (registrationMutex) { |
627 | 0 | listenedClasses.unregister(listener, className, propertyNames); |
628 | 0 | for (String subtype : subtypes) { |
629 | 0 | listenedClasses.unregister(listener, subtype, |
630 | |
propertyNames); |
631 | |
} |
632 | 0 | } |
633 | 0 | return; |
634 | |
} |
635 | 0 | throw new IllegalArgumentException( |
636 | |
"Don't know how to unregister class event for object " |
637 | |
+ modelClass); |
638 | |
} |
639 | |
|
640 | |
private String getClassName(Object elementOrClass) { |
641 | 3214 | return modelImpl.getMetaTypes().getName(elementOrClass); |
642 | |
} |
643 | |
|
644 | |
|
645 | |
|
646 | |
|
647 | |
public void startPumpingEvents() { |
648 | 2836 | LOG.debug("Start pumping events"); |
649 | 2836 | repository.addListener(this); |
650 | 2836 | } |
651 | |
|
652 | |
|
653 | |
|
654 | |
|
655 | |
public void stopPumpingEvents() { |
656 | 1946 | LOG.debug("Stop pumping events"); |
657 | 1946 | repository.removeListener(this); |
658 | 1946 | } |
659 | |
|
660 | |
|
661 | |
|
662 | |
|
663 | |
public void flushModelEvents() { |
664 | |
while (true) { |
665 | 156 | synchronized (eventCountMutex) { |
666 | 156 | if (pendingEvents <= 0 |
667 | |
|
668 | |
|
669 | |
|| Thread.currentThread().equals(eventThread)) { |
670 | 156 | return; |
671 | |
} |
672 | |
try { |
673 | 0 | eventCountMutex.wait(); |
674 | 0 | } catch (InterruptedException e) { |
675 | 0 | LOG.error("Interrupted while waiting in flushModelEvents"); |
676 | 0 | } |
677 | 0 | } |
678 | |
} |
679 | |
|
680 | |
} |
681 | |
|
682 | |
|
683 | |
|
684 | |
|
685 | |
|
686 | |
private String otherAssocEnd(AssociationEvent ae) { |
687 | 658 | RefAssociation ra = (RefAssociation) ae.getSource(); |
688 | 658 | Association a = (Association) ra.refMetaObject(); |
689 | 658 | AssociationEnd aend = null; |
690 | |
try { |
691 | 658 | aend = (AssociationEnd) a.lookupElementExtended(ae.getEndName()); |
692 | 0 | } catch (NameNotFoundException e) { |
693 | 0 | LOG.error("Failed to find other end of association : " |
694 | |
+ ae.getSource() + " -> " + ae.getEndName()); |
695 | 0 | return null; |
696 | 658 | } |
697 | 658 | return aend.otherEnd().getName(); |
698 | |
} |
699 | |
|
700 | |
|
701 | |
|
702 | |
|
703 | |
|
704 | |
|
705 | |
|
706 | |
|
707 | |
|
708 | |
|
709 | |
private static String mapPropertyName(String name) { |
710 | |
|
711 | |
|
712 | |
|
713 | 658 | if ("typedParameter".equals(name)) { |
714 | 0 | return "parameter"; |
715 | |
} |
716 | 658 | if ("typedFeature".equals(name)) { |
717 | 0 | return "feature"; |
718 | |
} |
719 | 658 | return name; |
720 | |
} |
721 | |
|
722 | |
|
723 | |
|
724 | |
|
725 | |
private String formatArray(String[] array) { |
726 | 0 | if (array == null) { |
727 | 0 | return null; |
728 | |
} |
729 | 0 | String result = "["; |
730 | 0 | for (int i = 0; i < array.length; i++) { |
731 | 0 | result = result + array[i] + ", "; |
732 | |
} |
733 | 0 | return result.substring(0, result.length() - 2) + "]"; |
734 | |
} |
735 | |
|
736 | |
private String formatElement(Object element) { |
737 | |
try { |
738 | 0 | if (element instanceof RefBaseObject) { |
739 | 0 | return modelImpl.getMetaTypes().getName(element) |
740 | |
+ "<" + ((RefBaseObject) element).refMofId() + ">"; |
741 | 0 | } else if (element != null) { |
742 | 0 | return element.toString(); |
743 | |
} |
744 | 0 | } catch (InvalidObjectException e) { |
745 | 0 | return modelImpl.getMetaTypes().getName(element) |
746 | |
+ "<deleted>"; |
747 | 0 | } |
748 | 0 | return null; |
749 | |
} |
750 | |
|
751 | |
|
752 | |
|
753 | |
|
754 | |
|
755 | |
private Map<String, Collection<String>> buildTypeMap(ModelPackage extent) { |
756 | 900 | Map<String, Collection<String>> names = |
757 | |
new HashMap<String, Collection<String>>(); |
758 | 900 | for (Object metaclass : extent.getMofClass().refAllOfClass()) { |
759 | 108000 | ModelElement element = (ModelElement) metaclass; |
760 | 108000 | String name = element.getName(); |
761 | 108000 | if (names.containsKey(name)) { |
762 | 0 | LOG.error("Found duplicate class '" + name + "' in metamodel"); |
763 | |
} else { |
764 | 108000 | names.put(name, getSubtypes(extent, element)); |
765 | |
|
766 | |
|
767 | |
} |
768 | 108000 | } |
769 | 900 | return names; |
770 | |
} |
771 | |
|
772 | |
|
773 | |
|
774 | |
|
775 | |
|
776 | |
|
777 | |
private Collection<String> getSubtypes(ModelPackage extent, |
778 | |
ModelElement me) { |
779 | 485100 | Collection<String> allSubtypes = new HashSet<String>(); |
780 | 485100 | if (me instanceof GeneralizableElement) { |
781 | 485100 | GeneralizableElement ge = (GeneralizableElement) me; |
782 | 485100 | Collection<ModelElement> subtypes = extent.getGeneralizes() |
783 | |
.getSubtype(ge); |
784 | 485100 | for (ModelElement st : subtypes) { |
785 | 377100 | allSubtypes.add(st.getName()); |
786 | 377100 | allSubtypes.addAll(getSubtypes(extent, st)); |
787 | |
} |
788 | |
} |
789 | 485100 | return allSubtypes; |
790 | |
} |
791 | |
|
792 | |
|
793 | |
|
794 | |
|
795 | |
|
796 | |
private Map<String, Collection<String>> buildPropertyNameMap( |
797 | |
ModelPackage extent) { |
798 | 900 | Map<String, Collection<String>> names = |
799 | |
new HashMap<String, Collection<String>>(); |
800 | 900 | for (Reference reference : (Collection<Reference>) extent |
801 | |
.getReference().refAllOfClass()) { |
802 | 148500 | mapAssociationEnd(names, reference.getExposedEnd()); |
803 | 148500 | mapAssociationEnd(names, reference.getReferencedEnd()); |
804 | |
} |
805 | 900 | for (Attribute attribute : (Collection<Attribute>) extent |
806 | |
.getAttribute().refAllOfClass()) { |
807 | 67500 | mapPropertyName(names, attribute.getContainer(), |
808 | |
attribute.getName()); |
809 | |
} |
810 | 900 | return names; |
811 | |
} |
812 | |
|
813 | |
private void mapAssociationEnd(Map<String, Collection<String>> names, |
814 | |
AssociationEnd end) { |
815 | 297000 | ModelElement type = end.otherEnd().getType(); |
816 | 297000 | mapPropertyName(names, type, end.getName()); |
817 | 297000 | } |
818 | |
|
819 | |
private boolean mapPropertyName(Map<String, Collection<String>> names, |
820 | |
ModelElement type, String propertyName) { |
821 | 364500 | String typeName = type.getName(); |
822 | 364500 | boolean added = mapPropertyName(names, typeName, propertyName); |
823 | |
|
824 | 364500 | Collection<String> subtypes = subtypeMap.get(typeName); |
825 | 364500 | if (subtypes != null) { |
826 | 364500 | for (String subtype : subtypes) { |
827 | 3826800 | added &= mapPropertyName(names, subtype, propertyName); |
828 | |
} |
829 | |
} |
830 | |
|
831 | 364500 | return added; |
832 | |
} |
833 | |
|
834 | |
private boolean mapPropertyName(Map<String, Collection<String>> names, |
835 | |
String typeName, String propertyName) { |
836 | 4191300 | if (!names.containsKey(typeName)) { |
837 | 107100 | names.put(typeName, new HashSet<String>()); |
838 | |
} |
839 | 4191300 | boolean added = names.get(typeName).add(propertyName); |
840 | 4191300 | if (LOG.isDebugEnabled()) { |
841 | 0 | if (!added) { |
842 | |
|
843 | |
|
844 | |
|
845 | |
|
846 | |
} else { |
847 | 0 | LOG.debug("Added property name - " + typeName + ":" |
848 | |
+ propertyName); |
849 | |
} |
850 | |
} |
851 | 4191300 | return added; |
852 | |
} |
853 | |
|
854 | |
|
855 | |
|
856 | |
|
857 | |
|
858 | |
private void verifyAttributeNames(String className, String[] attributes) { |
859 | |
|
860 | 900 | RefObject ro = null; |
861 | 900 | verifyAttributeNames(ro, attributes); |
862 | 900 | } |
863 | |
|
864 | |
|
865 | |
|
866 | |
|
867 | |
|
868 | |
private void verifyAttributeNames(RefObject metaobject, |
869 | |
String[] attributes) { |
870 | |
|
871 | |
|
872 | 3974 | if (LOG.isDebugEnabled()) { |
873 | 0 | if (metaobject == null || attributes == null) { |
874 | 0 | return; |
875 | |
} |
876 | |
|
877 | |
|
878 | 0 | if (!(metaobject instanceof MofClass)) { |
879 | 0 | metaobject = metaobject.refMetaObject(); |
880 | |
} |
881 | |
|
882 | |
|
883 | 0 | if (!(metaobject instanceof MofClass)) { |
884 | 0 | throw new IllegalArgumentException( |
885 | |
"Argument must be MofClass or instance of MofClass"); |
886 | |
} |
887 | |
|
888 | 0 | MofClass metaclass = (MofClass) metaobject; |
889 | 0 | Collection<String> names = propertyNameMap.get(metaclass.getName()); |
890 | 0 | if (names == null) { |
891 | 0 | names = Collections.emptySet(); |
892 | |
} |
893 | |
|
894 | 0 | for (String attribute : attributes) { |
895 | 0 | if (!names.contains(attribute) |
896 | |
&& !"remove".equals(attribute)) { |
897 | |
|
898 | |
|
899 | |
|
900 | 0 | LOG.error("Property '" + attribute |
901 | |
+ "' for class '" |
902 | |
+ metaclass.getName() |
903 | |
+ "' doesn't exist in metamodel"); |
904 | |
|
905 | |
|
906 | |
} |
907 | |
} |
908 | |
} |
909 | 3974 | } |
910 | |
|
911 | |
|
912 | |
@SuppressWarnings("unchecked") |
913 | |
public List getDebugInfo() { |
914 | 0 | List info = new ArrayList(); |
915 | 0 | info.add("Event Listeners"); |
916 | 0 | for (Iterator it = elements.registry.entrySet().iterator(); |
917 | 0 | it.hasNext(); ) { |
918 | 0 | Map.Entry entry = (Map.Entry) it.next(); |
919 | 0 | String item = entry.getKey().toString(); |
920 | 0 | List modelElementNode = newDebugNode(getDebugDescription(item)); |
921 | 0 | info.add(modelElementNode); |
922 | 0 | Map propertyMap = (Map) entry.getValue(); |
923 | 0 | for (Iterator propertyIterator = propertyMap.entrySet().iterator(); |
924 | 0 | propertyIterator.hasNext();) { |
925 | 0 | Map.Entry propertyEntry = (Map.Entry) propertyIterator.next(); |
926 | 0 | List propertyNode = |
927 | |
newDebugNode(propertyEntry.getKey().toString()); |
928 | 0 | modelElementNode.add(propertyNode); |
929 | |
|
930 | 0 | List listenerList = (List) propertyEntry.getValue(); |
931 | 0 | for (Iterator listIt = listenerList.iterator(); |
932 | 0 | listIt.hasNext(); ) { |
933 | 0 | Object listener = listIt.next(); |
934 | 0 | List listenerNode = |
935 | |
newDebugNode( |
936 | |
listener.getClass().getName()); |
937 | 0 | propertyNode.add(listenerNode); |
938 | 0 | } |
939 | 0 | } |
940 | 0 | } |
941 | |
|
942 | 0 | return info; |
943 | |
} |
944 | |
|
945 | |
private List<String> newDebugNode(String name) { |
946 | 0 | List<String> list = new ArrayList<String>(); |
947 | 0 | list.add(name); |
948 | 0 | return list; |
949 | |
} |
950 | |
|
951 | |
private String getDebugDescription(String mofId) { |
952 | 0 | Object modelElement = repository.getByMofId(mofId); |
953 | 0 | String name = Model.getFacade().getName(modelElement); |
954 | 0 | if (name != null && name.trim().length() != 0) { |
955 | 0 | return "\"" + name + "\" - " + modelElement.toString(); |
956 | |
} else { |
957 | 0 | return modelElement.toString(); |
958 | |
} |
959 | |
} |
960 | |
|
961 | |
} |
962 | |
|
963 | |
|
964 | |
|
965 | |
|
966 | |
|
967 | |
|
968 | |
|
969 | |
|
970 | |
class Registry<T> { |
971 | |
|
972 | 900 | private static final Logger LOG = Logger.getLogger(Registry.class); |
973 | |
|
974 | |
Map<String, Map<String, List<T>>> registry; |
975 | |
|
976 | |
|
977 | |
|
978 | |
|
979 | 1800 | Registry() { |
980 | 1800 | registry = Collections |
981 | |
.synchronizedMap(new HashMap<String, Map<String, List<T>>>()); |
982 | 1800 | } |
983 | |
|
984 | |
|
985 | |
|
986 | |
|
987 | |
|
988 | |
|
989 | |
|
990 | |
|
991 | |
|
992 | |
|
993 | |
|
994 | |
|
995 | |
|
996 | |
|
997 | |
void register(T item, String key, |
998 | |
String[] subkeys) { |
999 | |
|
1000 | |
|
1001 | 94874 | Map<String, List<T>> entry = registry.get(key); |
1002 | 94874 | if (entry == null) { |
1003 | 92864 | entry = new HashMap<String, List<T>>(); |
1004 | 92864 | registry.put(key, entry); |
1005 | |
} |
1006 | |
|
1007 | |
|
1008 | |
|
1009 | 94874 | if (subkeys == null || subkeys.length < 1) { |
1010 | 92700 | subkeys = |
1011 | |
new String[] { |
1012 | |
"", |
1013 | |
}; |
1014 | |
} |
1015 | |
|
1016 | 189806 | for (int i = 0; i < subkeys.length; i++) { |
1017 | 94932 | List<T> list = entry.get(subkeys[i]); |
1018 | 94932 | if (list == null) { |
1019 | 93822 | list = new ArrayList<T>(); |
1020 | 93822 | entry.put(subkeys[i], list); |
1021 | |
} |
1022 | 94932 | if (!list.contains(item)) { |
1023 | 94932 | list.add(item); |
1024 | |
} else { |
1025 | 0 | if (LOG.isDebugEnabled()) { |
1026 | 0 | LOG.debug("Duplicate registration attempt for " + key + ":" |
1027 | |
+ subkeys + " Listener: " + item); |
1028 | |
} |
1029 | |
} |
1030 | |
} |
1031 | 94874 | } |
1032 | |
|
1033 | |
|
1034 | |
|
1035 | |
|
1036 | |
|
1037 | |
|
1038 | |
|
1039 | |
|
1040 | |
|
1041 | |
|
1042 | |
void unregister(T item, String key, String[] subkeys) { |
1043 | 3 | Map<String, List<T>> entry = registry.get(key); |
1044 | 3 | if (entry == null) { |
1045 | 1 | return; |
1046 | |
} |
1047 | |
|
1048 | 2 | if (subkeys != null && subkeys.length > 0) { |
1049 | 3 | for (int i = 0; i < subkeys.length; i++) { |
1050 | 2 | lookupRemoveItem(entry, subkeys[i], item); |
1051 | |
} |
1052 | |
} else { |
1053 | 1 | if (item == null) { |
1054 | 1 | registry.remove(key); |
1055 | |
} else { |
1056 | 0 | lookupRemoveItem(entry, "", item); |
1057 | |
} |
1058 | |
} |
1059 | 2 | } |
1060 | |
|
1061 | |
private void lookupRemoveItem(Map<String, List<T>> map, String key, |
1062 | |
T item) { |
1063 | 2 | List<T> list = map.get(key); |
1064 | 2 | if (list == null) { |
1065 | 0 | return; |
1066 | |
} |
1067 | 2 | if (item == null) { |
1068 | 0 | map.remove(key); |
1069 | 0 | return; |
1070 | |
} |
1071 | 2 | if (LOG.isDebugEnabled()) { |
1072 | 0 | if (!list.contains(item)) { |
1073 | 0 | LOG.debug("Attempt to unregister non-existant registration" |
1074 | |
+ key + " Listener: " + item); |
1075 | |
} |
1076 | |
} |
1077 | 4 | while (list.contains(item)) { |
1078 | 2 | list.remove(item); |
1079 | |
} |
1080 | 2 | if (list.isEmpty()) { |
1081 | 2 | map.remove(key); |
1082 | |
} |
1083 | 2 | } |
1084 | |
|
1085 | |
|
1086 | |
|
1087 | |
|
1088 | |
|
1089 | |
|
1090 | |
|
1091 | |
|
1092 | |
|
1093 | |
Collection<T> getMatches(String key, String subkey) { |
1094 | 4628 | List<T> results = new ArrayList<T>(); |
1095 | 4628 | Map<String, List<T>> entry = registry.get(key); |
1096 | 4628 | if (entry != null) { |
1097 | 2551 | if (entry.containsKey(subkey)) { |
1098 | 1 | results.addAll(entry.get(subkey)); |
1099 | |
} |
1100 | 2551 | if (entry.containsKey("")) { |
1101 | 2546 | results.addAll(entry.get("")); |
1102 | |
} |
1103 | |
} |
1104 | 4628 | return results; |
1105 | |
} |
1106 | |
|
1107 | |
} |