Best practice for EMF Notification propagation [message #630645] |
Mon, 04 October 2010 13:28 |
|
Howdy,
My question feels rather... basic, yet I couldn't find a proper answer online (nor in the EMF-Book, or maybe I missed it):
My problem: I would like to be notified if attributes of a referenced object change. But I do not want to register a listener in the object's implementation. In other words, I'd like to realize this with the ItemProviders.
Some background: I am working on a project where I am using the data model from a different project. Requesting changes in the data model is kind of a last resort. Besides, intuitively it feels like that this should be doable with the ItemProviders.
I set up a tiny project to demonstrate the issue (I just hacked the AdapterFactory in for testing, sorry):
public void testNotificationsShirt() {
getFixture().eAdapters().add(new AdapterImpl() {
@Override
public void notifyChanged(Notification msg) {
System.out.println(" >> " + msg);
super.notifyChanged(msg);
}
});
EmftestItemProviderAdapterFactory factory = new EmftestItemProviderAdapterFactory();
getFixture().eAdapters().add(factory.createBagAdapter());
System.out.println("Creating shirt...");
Shirt shirt = EmftestFactory.eINSTANCE.createShirt();
shirt.eAdapters().add(factory.createShirtAdapter());
System.out.println("Adding shirt...");
getFixture().setShirt(shirt);
System.out.println("Updating shirt...");
shirt.setColor("red");
}
As Expected, I got the following output:
Creating shirt...
Adding shirt...
>> org.eclipse.emf.ecore.impl.ENotificationImpl@1d256fa ...
Updating shirt...
But I am trying to get a notification on Bag when I update the Shirt's color.
I managed to realize this by changing ShirtItemProvider.notifyChanged(), but the result feels messy:
public void notifyChanged(Notification notification) {
updateChildren(notification);
switch (notification.getFeatureID(Shirt.class)) {
case EmftestPackage.SHIRT__COLOR:
fireNotifyChanged(new ViewerNotification(notification,
notification.getNotifier(), false, true));
Bag bag = (Bag) ((EObject) notification.getNotifier()).eContainer();
if (bag != null) {
bag.eNotify(new ENotificationImpl((InternalEObject) bag,
ENotificationImpl.SET, EmftestPackage.BAG__SHIRT,
notification.getNotifier(), notification.getNotifier()));
}
return;
}
super.notifyChanged(notification);
}
Is this the right way? Is there a better way?
thanks,
- Michael
|
|
|
Re: Best practice for EMF Notification propagation [message #630659 is a reply to message #630645] |
Mon, 04 October 2010 13:48 |
Ed Merks Messages: 33140 Registered: July 2009 |
Senior Member |
|
|
Michael,
Comments below.
Michael Jastram wrote:
> Howdy,
>
> My question feels rather... basic, yet I couldn't find a proper answer
> online (nor in the EMF-Book, or maybe I missed it):
>
> My problem: I would like to be notified if attributes of a referenced
> object change. But I do not want to register a listener in the
> object's implementation. In other words, I'd like to realize this
> with the ItemProviders.
ItemProviders are listeners too.
>
> Some background: I am working on a project where I am using the data
> model from a different project. Requesting changes in the data model
> is kind of a last resort. Besides, intuitively it feels like that
> this should be doable with the ItemProviders.
>
> I set up a tiny project to demonstrate the issue (I just hacked the
> AdapterFactory in for testing, sorry):
>
> public void testNotificationsShirt() {
> getFixture().eAdapters().add(new AdapterImpl() {
> @Override
> public void notifyChanged(Notification msg) {
> System.out.println(" >> " + msg);
> super.notifyChanged(msg);
> }
> });
>
> EmftestItemProviderAdapterFactory factory = new
> EmftestItemProviderAdapterFactory();
> getFixture().eAdapters().add(factory.createBagAdapter());
> System.out.println("Creating shirt...");
> Shirt shirt = EmftestFactory.eINSTANCE.createShirt();
> shirt.eAdapters().add(factory.createShirtAdapter());
> System.out.println("Adding shirt...");
> getFixture().setShirt(shirt);
> System.out.println("Updating shirt...");
> shirt.setColor("red");
> }
>
>
> As Expected, I got the following output:
>
> Creating shirt...
> Adding shirt...
> >> org.eclipse.emf.ecore.impl.ENotificationImpl@1d256fa ...
> Updating shirt...
>
> But I am trying to get a notification on Bag when I update the Shirt's
> color.
>
> I managed to realize this by changing
> ShirtItemProvider.notifyChanged(), but the result feels messy:
>
>
> public void notifyChanged(Notification notification) {
> updateChildren(notification);
>
> switch (notification.getFeatureID(Shirt.class)) {
> case EmftestPackage.SHIRT__COLOR:
> fireNotifyChanged(new ViewerNotification(notification,
> notification.getNotifier(), false, true));
>
> Bag bag = (Bag) ((EObject)
> notification.getNotifier()).eContainer();
> if (bag != null) {
> bag.eNotify(new ENotificationImpl((InternalEObject) bag,
> ENotificationImpl.SET, EmftestPackage.BAG__SHIRT,
> notification.getNotifier(),
> notification.getNotifier()));
> }
> return;
> }
> super.notifyChanged(notification);
> }
>
>
> Is this the right way?
It's not totally bad.
> Is there a better way?
The only way is to add listeners so in this case you're exploiting the
fact that the contained child has a listener and you're propagating a
notification. EGenericTypeItemProvider does something similar...
>
> thanks,
>
> - Michael
>
Ed Merks
Professional Support: https://www.macromodeling.com/
|
|
|
Powered by
FUDForum. Page generated in 0.03450 seconds