Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » Generating Setters and Getters API for EMF.Edit commands
Generating Setters and Getters API for EMF.Edit commands [message #894886] Tue, 10 July 2012 22:34 Go to next message
Miles Parker is currently offline Miles ParkerFriend
Messages: 1341
Registered: July 2009
Senior Member
As I've tried to indoctrinate people into the EMF religion, one of the biggest -- and most understandable --objections I've run into is the awkward interface for working with models. Here's an idea for addressing that issue that I've been kicking around in my mind. Would love to hear feedback on it..

The idea is to provide an edit aware setter and getter Adapter/Decorator (not sure what pattern applies here exactly) for eObjects.

In Model, you'd add to each MyObject method an:

MyObject eEdit() {
IEditProviderFactory editFactory = [package/resource]getEditFactory();
    if (editFactory != null) {
       return (MyObject) editFactory.getEditDecorator(this);
    }
    return null;
}


And for the package an:

IEditProviderFactory getEditFactory();
void setEditFactory(IEditProviderFactory factory);


Alternatively, you could add this as a method to Resource.

In Edit, you'd generate:

MyPackageEditProviderFactory implements IEditProviderFactory {
IEditingDomain domain;
...
    public getEditDecorator(EObject eObject) {
        ..another gigantic switch statement..
			public Adapter caseMyObject(MyObject object) {
				return new MyObjectEditDecorator(getEditingDomain(), object);
			}
}


Any editors (e.g. MyEditor#createModel) would then call something like the below after the resource is opened/created:

myPackage.setEditorFactory(new MyPackgeEditProviderFactory(editingDomain));


Finally for each EClass you'd generate a:

MyObjectEditDecorator implements MyObject {
    public void setFoo(Bar bar) {
        getEditFactory().getCommandStack().execute(SetCommand.create(getEditingDomain(), this, MyPackage.Literals.MYOBJECT_FOO, bar);
    }
...
    public void addBaz(Baz baz) {
        getEditFactory().getCommandStack().execute(AddCommand.create(getEditingDomain(), this, baz);
    }
....
}


The upshot of all of this of course is that then a consumer of the EMF Model API would only have to do:

myObect.eEdit().setBar(myBar);


!

Whaddya all think, brain storm or brain cramp? Smile
Re: Generating Setters and Getters API for EMF.Edit commands [message #894920 is a reply to message #894886] Wed, 11 July 2012 06:03 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33137
Registered: July 2009
Senior Member
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
Miles,<br>
<br>
Comments below.<br>
<br>
<div class="moz-cite-prefix">On 11/07/2012 12:34 AM, Miles Parker
wrote:<br>
</div>
<blockquote cite="mid:jtial8$28d$1@xxxxxxxxe.org" type="cite">As
I've tried to indoctrinate people into the EMF religion, one of
the biggest -- and most understandable --objections </blockquote>
Interesting that people start with objections.  They seem to seek
them out and in many ways their fundamentally excuses to justify
irrational things.<br>
<blockquote cite="mid:jtial8$28d$1@xxxxxxxxe.org" type="cite">I've
run into is the awkward interface for working with models. Here's
an idea for addressing that issue that I've been kicking around in
my mind. Would love to hear feedback on it..
<br>
<br>
The idea is to provide an edit aware setter and getter
Adapter/Decorator (not sure what pattern applies here exactly) for
eObjects.
<br>
<br>
In Model, you'd add to each MyObject method an:
<br>
<br>
MyObject eEdit() {
<br>
IEditProviderFactory editFactory =
[package/resource]getEditFactory();
<br>
   if (editFactory != null) {
<br>
      return (MyObject) editFactory.getEditDecorator(this);
<br>
   }
<br>
   return null;
<br>
}
<br>
</blockquote>
Sorry, but this is sounding horrible already.  It seems to me if you
want to operate directly on your objects without worrying about
editing and undo, you can do that and use a ChangeCommand.<br>
<blockquote cite="mid:jtial8$28d$1@xxxxxxxxe.org" type="cite">
<br>
And for the package an:
<br>
<br>
IEditProviderFactory getEditFactory();
<br>
void setEditFactory(IEditProviderFactory factory);
<br>
</blockquote>
So not only populate the instance API with edit concerns but pollute
the communal font of data about the instances with one user in the
JVM's particular choice of "edit provider".<br>
<blockquote cite="mid:jtial8$28d$1@xxxxxxxxe.org" type="cite">
<br>
Alternatively, you could add this as a method to Resource.
<br>
<br>
In Edit, you'd generate:
<br>
<br>
MyPackageEditProviderFactory implements IEditProviderFactory {
<br>
IEditingDomain domain;
<br>
..
<br>
   public getEditDecorator(EObject eObject) {
<br>
       ..another gigantic switch statement..
<br>
            public Adapter caseMyObject(MyObject object) {
<br>
                return new
MyObjectEditDecorator(getEditingDomain(), object);
<br>
            }
<br>
}
<br>
</blockquote>
At this point I have to wonder why though, how is it better then
AdapterFactoryEditingDomain.getEditingDomainFor(EObject)?<br>
<blockquote cite="mid:jtial8$28d$1@xxxxxxxxe.org" type="cite">
<br>
<br>
Any editors (e.g. MyEditor#createModel) would then call something
like the below after the resource is opened/created:
<br>
<br>
myPackage.setEditorFactory(new
MyPackgeEditProviderFactory(editingDomain));
<br>
</blockquote>
Clearly this don't work.  The package is shared by all instances but
there isn't just one editor.<br>
<blockquote cite="mid:jtial8$28d$1@xxxxxxxxe.org" type="cite">
<br>
Finally for each EClass you'd generate a:
<br>
<br>
MyObjectEditDecorator implements MyObject {
<br>
   public void setFoo(Bar bar) {
<br>
      
getEditFactory().getCommandStack().execute(SetCommand.create(getEditingDomain(),
this, MyPackage.Literals.MYOBJECT_FOO, bar);
<br>
   }
<br>
..
<br>
   public void addBaz(Baz baz) {
<br>
      
getEditFactory().getCommandStack().execute(AddCommand.create(getEditingDomain(),
this, baz);
<br>
   }
<br>
...
<br>
}
<br>
</blockquote>
And then you never have a course grained undo?  You can never
compose fine grained model updates into a single undo?<br>
<blockquote cite="mid:jtial8$28d$1@xxxxxxxxe.org" type="cite">
<br>
The upshot of all of this of course is that then a consumer of the
EMF Model API would only have to do:
<br>
<br>
<br>
myObect.eEdit().setBar(myBar);
<br>
<br>
<br>
!
<br>
<br>
Whaddya all think, brain storm or brain cramp? :)
<br>
</blockquote>
I think the latter.  If someone wants something totally easy (though
brute force) they can use, a ChangeCommand like this:<br>
<blockquote>  public void testEObject()<br>
  {<br>
    final E e = refFactory.createE();    <br>
    // State 0<br>
    assertTrue(e.getIds().isEmpty());<br>
    <br>
    ChangeCommand changeCommand = new ChangeCommand(e)<br>
    {<br>
      @Override<br>
      protected void doExecute()<br>
      {<br>
        EList&lt;String&gt; ids = e.getIds();<br>
        ids.add("0");<br>
        ids.add("1");<br>
        ids.add("2");        <br>
      }<br>
    }<br>
</blockquote>
No parallel set of relfective-like APIs to learn and generate and
you get the granularity of undo you need.<br>
<br>
<br>
</body>
</html>


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: Generating Setters and Getters API for EMF.Edit commands [message #895102 is a reply to message #894920] Wed, 11 July 2012 17:03 Go to previous messageGo to next message
Miles Parker is currently offline Miles ParkerFriend
Messages: 1341
Registered: July 2009
Senior Member
Right, you'll need to support multiple editing domains for one model instance. Duh. I was thinking to avoid the overhead of AdapterFactoryEditingDomain.getEditingDomainFor(EObject), but using that you could do away with a lot of the model level support. I don't think that this "pollutes" model too much with editing concerns, because you're not providing any implementation; it's simply a hook for arbitrary edit aware interfaces. If you wanted to truly separate concerns at the expense of clarity, you could call the method something like eClient(). Smile

The whole point of this is to make it so that consumers of the tool have *nothing to learn* except for the very simple "it's easy, just append .eClient() to any object modifications".

I think the number one barrier for Ecore/XCore adoption for generic usage is the difficulty/annoyance with grokking the command API. Yes, as EMF users we all understand why this richer way of doing things works, but the more that people can treat an EMF object the way they would treat any other object *and get the benefits of EMF* the more likely they will be to adopt it. So brain cramp or not, it might be worth considering ways to provide a more natural API for that.

With Change Command, granular edit commands are not managed -- that is, forwarded through item providers -- correct? It's that facility that I want to preserve more than the undo stack.

Re: Generating Setters and Getters API for EMF.Edit commands [message #895144 is a reply to message #895102] Wed, 11 July 2012 19:35 Go to previous message
Ed Merks is currently offline Ed MerksFriend
Messages: 33137
Registered: July 2009
Senior Member
Miles,

Comments below.
On 11/07/2012 7:03 PM, Miles Parker wrote:
> Right, you'll need to support multiple editing domains for one model
> instance. Duh. I was thinking to avoid the overhead of
> AdapterFactoryEditingDomain.getEditingDomainFor(EObject), but using
> that you could do away with a lot of the model level support. I don't
> think that this "pollutes" model too much with editing concerns,
> because you're not providing any implementation; it's simply a hook
> for arbitrary edit aware interfaces. If you wanted to truly separate
> concerns at the expense of clarity, you could call the method
> something like eClient(). :)
>
> The whole point of this is to make it so that consumers of the tool
> have *nothing to learn* except for the very simple "it's easy, just
> append .eClient() to any object modifications".
>
> I think the number one barrier for Ecore/XCore adoption for generic
> usage is the difficulty/annoyance with grokking the command API.
Well, there is all the nice Observables stuff. In the end, suppose you
hand wrote and implemented all of your APIs, i.e., the standard
straightforward way of working that doesn't make people blink and eye.
How would one write a UI that supports undo and redo? You'd do that
all by hand as well. Still no blinking of eyes? The alternative to
learning an existing well-tested solution is always do it all by hand
yourself. People are always comfortable with that, even if it's 10
times as much work. It just always sounds good to hard-core
do-it-yourselfers. There's just no appeasing people like that anyway.
I certainly don't intend to add yet more complexity in a (hopeless?
misguided? futile?) bid to make things simpler...
> Yes, as EMF users we all understand why this richer way of doing
> things works, but the more that people can treat an EMF object the way
> they would treat any other object *
Other objects don't support anything like what you're suggesting do they?
> and get the benefits of EMF* the more likely they will be to adopt it.
As far as I'm concern, resistance is futile. People will come around in
the end because things are simpler and richer. Adding yet more
complexity in order to simplify just isn't going to help, in my opinion.
> So brain cramp or not, it might be worth considering ways to provide a
> more natural API for that.
So what is the natural analog to what you're suggesting. Beans don't
have anything like this do they?
>
> With Change Command, granular edit commands are not managed -- that
> is, forwarded through item providers -- correct?
No, only the one command is involved. All changes are recorded in a way
that supports roll back and replay. All changes are done using the
standard simple Bean-like APIs, other than wrapping them much as you'd
do a Runnable...
> It's that facility that I want to preserve more than the undo stack.
What good is an editor that doesn't support undo?
>
>


Ed Merks
Professional Support: https://www.macromodeling.com/
Previous Topic:Efficiently Traversing an Entire EMF Model
Next Topic:[EMF .Edit] Customizing child creation behaviour
Goto Forum:
  


Current Time: Fri Apr 19 06:11:00 GMT 2024

Powered by FUDForum. Page generated in 0.01973 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top