Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [eclipse-incubator-e4-dev] YAMI (Yet Another Model Interface)

Hi Ed,

I look forward to meet you at the summit...

Comments below...

Ed Merks wrote:
> have you looked at the openArchitectureWare MetaModel [1][2]? It is similar
 > to IObservableModel [3] but it seems to be more complete. It is
 > missing notifications though.

I think the intent is a quite a different though...

This is a good point! There are clearly different uses of meta-models.
Maybe we should differentiate between the uses.

In modeling you need a metamodel that is a model as well, especially,
you need a modifiable metamodel to build your metamodel. EMF is very
good for that and I think that was its primary intend of use.

There are cases when you need meta information about the objects
at hand. In that case the metamodel is essentially read-only (at
least for the consumer). Often additional meta information about
the meta-model artifacts might be useful. Those are often a kind of
annotations. But annotations can come from anywhere. If you look
at persistence systems like Hibernate and EclipseLink, the "annotations"
can either come from the metamodel directly or from an external XML
file that associates the annotations with the model. Ideally, the
annotation itself has a metamodel.....

Typical examples for the need of read-only metamodels
- database persistence
- data-binding
- annotation driven UI
- model validation
- serialization
- scripting language binding (expose java objects to the scripting language)
- access to objects from scripting languages (access scripting objects in java)

Ok, here's an example where you need a modifiable metamodel:
ad-hoc data-structures like IMemento. But with something like
my MagicInterfaces or generated code, the user is not exposed
too the fact that the metamodel is modifiable.

I think in the realm of UI there is a lot you can do if you have
a strong metamodel. The EMF tools show quite nicely what you can do
with a good metamodel.

But unfortunately, EMF is viral like GPL. If you want to use it you
have to make your objects EObject. The oaw metamodel is similar
to ecore but it is not viral (because you can use it for non
openArchitectureWare and non EMF objects).


 >
 > - it does the indirection (model.value(object, attrId))
 > - it is tuned for model access
 > - there are implementations for EMF, java beans, JDT etc

I'm not sure of the specifics, but I expect the need for it is much like in JET where you want to write templates that traverse a data string in a uniform way. I.e., it's effectively a requirement to write scripts against arbitrary data structures all of which you want to view as being typed objects with properties...

It is used for more I think -- (I don't know the oaw code in detail).
But the metamodel is also used in the editors for code completion and
validation. The oaw language family (xTend, xPand etc) is strongly
typed and they rely on a strong metamodel. I don't know about their
dynamic UI. I don't know they are using EMF (that would prove the
viral nature of EMF ;-) or if they base it on their metamodel.

 > This would then have the benefits of the IObservableModel and
 > openArchitectureWare metamodel with the power of EMF....

Again, I think the intent is a little different and I'm not sure those differences unimportant.

 >
 >
 > interface IObservableModel {
 >    // ask an object for what type it is
 >    EClassifier getClassifier(Object obj);
 >    EClass getClass(Object obj);
 >    EDataType getDataType(Object obj);

Note that in general, given a Java object, there isn't necessarily only one EDataType to represent that type of object.

true!


 >    // setting attributes
 >    void set(Object obj, EStructuralFeature feature, Object value);
 >    void unset(Object obj, EStructuralFeature feature);

This is where I think one of the big differences lie. When seen as a way of inducing/deducing a view from an underlying model, many if not all of the properties are likely to be derived and hence not editable.

and therefore there is EStructuralFeature.isChangeable()

Imagine the label of the tree node for a person being the first name and the last name without there being a full name feature in the model... In that sense, the "model" of the view, is very different from the underlying data model itself. Things like fonts and colors typically have no meaning in a data model.

... and with a flexible metamodel it should be possible to add
"volatile" attributes. The openArchitectureWare metamodel adds
some artificial attributes to all objects. At the moment, there
is no way in EMF to access volatile attributes for dynamic models.
For example, you have to write your own helper to interpret CQL
statements that are associated with volatile attributes (at least
that is what I remember you told me at eclipsecon). But like
in openArchitectureWare it should be possible to allow extensions
to weave in additional attributes. Code that might get generated
but is not available in dynamic models. Like the OAW team, and
many others, I have created my own engine to deal with dynamically
calculated attributes. I wish there was a general mechanism...

This weaving could either be done by a dynamic IAdaptable mechanism
or in a aspect oriented way by changing the metamodel...

But having a strong annotation model would be key here. As I
said before annotations don't have to be "physical" annotations
associated directly with the source of the metamodel. There could
be an extension point to contribute "annotations" like hybernate
and eclipselink allow the meta information to come from
different sources.

Here again, the annotations could also be accessed in the eclipse
adpter way:
   AdapterManager.adapt(eStructuralFeature, MyAnnotation.class);



 >    boolean isSet(Object obj, EStructuralFeature feature);

If data binding an things like the properties view considered this aspect a little better, stuff like the restore button in the properties view could be disabled when the feature is already in the unset/default state...

... in my annotation driven UI the EMF implementation of default values
annoyed me, because unsetting a value does not get back the default
value (or something strange like this).

> > // some convenience methods using strings instead of features
 >    Object value(Object obj, String feature);
 >    void set(Object obj, String feature,Object value);
 >    void unset(Object obj, String feature);
 >    boolean isSet(Object obj, String feature);

Yes, looking up the feature by name. I can also imagine useful coercions being involved, must like the SDOUtil help methods that would let you set an integer property from a string value...

Yes, and I created my own utility class, like everybody does.

> > // methods to needed to create objects
 >    EClass getClassByName(String name);

Often many different models will use the same name...

I did not specify how the name looks like ;-) Could be
a full uri... Or there might be multiple IObservableModel
"Realms" with different name resolutions.


 >    EDataType getDataTypeByName(String name);
 >    Object createInstance(EClassifier cl);

Typically data type values are not created in this way. For example, you couldn't just create java.lang.String this way since you can't change it once it exists.

yes therefore there is the EFactory.createFromString(EDataType eDataType, String literalValue);
method:
   Object createInstance(EClassifier eDataType, String literalValue);

> > Object callWithException(Object obj, EOperation operation,
 > Object[] args) throws Exception;

Ooo. Like the eInvoke I've always wanted but have never had time to support. It would be so cool if models could describe behavior in any extensible scripting language...

...which goes back to the dynamic weaving of features into objects.

 >
 >    Object call(Object obj, EOperation operation, Object[] args);
> > // borrowed from IObservableModel
 >     /** Returns the length of the given array */
 >    int length(Object array);
 >
 >    /** Returns the element at the given index of
 >    the given array */
 >    Object element(Object array, int index);

I never did quite understand these... Multi-vaued features in EMF are lists and can be manipulated directly. Of course that doesn't fit well with this design where observable model controls all data access.

This is a tricky business. And I just copied it from Boris model.


 >
 >    // TODO some way to manipulate arrays/lists and maps
> > /** Adds a listener */
 >    void addModelChangeListener(IModelChangeListener listener);
 >
 >    /** Removes a listener */
 >    void removeModelChangeListener(IModelChangeListener listener);
 > }
 >
 > Essentially, this class should cover the self manipulation methods
 > of EObject (including EList and EMap).

You'd have to add effectively the full set of methods you can use with lists, like add, remove, contains...

yes....

 >  But it would allow to have
 > models that do not have a IsA relationship to EObject. As Ed points
 > out all the time: we will end up with a metamodel like ecore anyway.
 > So, why not starting with ecore as metamodel (instead of Attr)....

Hehehehe. I don't see what Boris is proposing as a general purpose meta model for general purpose data models though... It's easy to see it that way though...

Neither am I proposing a general purpose metamodel. All I want is a
unified metamodel that can be used for
- databinding
- scripting
- validation
- "annotation driven" UI

If you look at the example, I don't think it is impossible
to come up with a good practical solution. The same way
EMF is a good practical solution for modeling (I am sure
theoreticians don't like it).

 >
 > Obviously, modifications of the ecore (meta)model cannot supported for
 > all underlying type systems. I'd like to have a clear separation
 > between accessing a metamodel (a kind of read-only access) and
 > metamodel manipulation (read-write access). But maybe that's my
 > personal opinion (I also hate that there are no interfaces for
 > read-only collections, and that java supports them by decorating
 > them and then throwing runtime exceptions.....).

Architecture always seems to be a comprimise... Imagine the impact on the class hiearchies to have such a split...

yes that is true... In C++ you can declare methods as const and if
you get a const object you can only access const methods. This
essentially splits a class into a read-only and a modifiable
interface. This has advantages, if you want to maintain integrity
of objects you give to clients. In java you have to either decorate
the objects (like the java.util.Collections.unmodifiableXXX methods
which do a runtime protection of your classes but do not help
at compile time) or you create two interfaces (one for modifications
and one for read-only access). But creating those two interfaces is
pretty tricky (especially in java 1.4). In java 5 you can override
return types:

   public interface UnmodifiableIterator<E> {
        boolean hasNext();
        E next();
        // no remove method
    }
    interface UnmodifiableCollection<E> {
        int size();
        // the client cannot remove anything from the list!
        UnmodifiableIterator<E> iterator();
    }
    interface Iterator<E> extends UnmodifiableIterator<E> {
        // this modifies the inderlyinglist
        void remove();
    }
    interface Collection<E> extends UnmodifiableCollection<E> {
        boolean add(E o);
        boolean remove(Object o);
        // and a modifiable list overrides the iterator
        // returning a modifiable iterator
        Iterator<E> iterator();
    }

This is actually better than the C++ solution, because depending
on the kind of collection you get, the unmodifiable list or
the unmodifiable list. To be really on the safe side, you'd
still have to use unmodifiable decorators, because else a
user could cast you class
    UnmodifiableCollection ucoll=...;
    if(ucoll instanceof Collection)
         Collection coll=(Collection)ucoll;

 >
 > In a world like this it also makes no sense that the ecore classes
 > (EModelElement, EClass, EFeature etc) extend EObject.... If you
 > want to introspect EClass you'd use IObservableModel...

An Ecore model is just a model as well as being the meta model for other models. so a world where it's not sensible is an odd world for me.

...well because in your world *everything* is a model. I mean
it *IsA* model (the GPL like viral aspect). In my
world it can be seen as a model even it it is not a EMF model....
I am a big fan of minimal interfaces. Don't expose implementation
details to your client. Making models IsA EObject exposes
implementation details to the client that are really hard
to change later. And for most clients it does not matter if
the object IsA EObject. The users of a ecore metamodel don't
need to know that it IsA EObject. Like what is the meaning
of eResource() in case of a java-reflection based metamodel?


Michael


Back to the top