Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » EcoreUtil.EqualityHelper and 'ordered' feature
EcoreUtil.EqualityHelper and 'ordered' feature [message #1647088] Tue, 03 March 2015 08:46 Go to next message
Mark Hoffmann is currently offline Mark HoffmannFriend
Messages: 113
Registered: July 2009
Location: Jena
Senior Member
Hello together,

I noticed that the 'ordered' feature in the ecore has no influence on the code generation process. It is no bigger problem until now. Currently I have a use case where I want to compare to model instance for equality. But there are many-references with content that has not the same order in the list. The order is not important for the equality in this case, but only the content of the objects.

For that I created my own EqualityHelper extending the EcoreUtil.EqualityHelper to support sorting like this:
 protected boolean haveEqualReference(EObject eObject1, EObject eObject2, EReference reference) {
    Object value1 = eObject1.eGet(reference);
    Object value2 = eObject2.eGet(reference);
    
    if (reference.isMany()) {
      List<EObject> list1 = (List<EObject>) value1;
      List<EObject> list2 = (List<EObject>) value2;
      if (reference.isOrdered()) {
        Comparator<EObject> comparator = new EObjectComparator(reference.getEKeys());
        Collections.sort(list1, comparator);
        Collections.sort(list2, comparator);
      }
      return equals(list1, list2);
    } else {
      return equals((EObject)value1, (EObject)value2);
    }
  }


The comparator sorts depending on the keys, if any are given, otherwise it uses toString comparison. The values in the key attributes are checked, if they implement java.lang.Comparable, which works for Numbers, String, Date and Enums

What do you think of this pattern? Is it something to contribute to enhance the EcoreUtil.EqualityHelper? Because this use-case is probalby not the most common one, maybe it should be parameterized.

EcoreUtil.equals(EObject eObject1, EObject eObject2, boolean sort)


By the way my implementation supports ignore-features too, that are ignored during comparison when they are not important for the equality.

Regards,
Mark
Re: EcoreUtil.EqualityHelper and 'ordered' feature [message #1647123 is a reply to message #1647088] Tue, 03 March 2015 09:07 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33140
Registered: July 2009
Senior Member
Mark,

Comments below.

On 03/03/2015 9:46 AM, Mark Hoffmann wrote:
> Hello together,
>
> I noticed that the 'ordered' feature in the ecore has no influence on
> the code generation process. It is no bigger problem until now.
> Currently I have a use case where I want to compare to model instance
> for equality. But there are many-references with content that has not
> the same order in the list. The order is not important for the
> equality in this case, but only the content of the objects.
>
> For that I created my own EqualityHelper extending the
> EcoreUtil.EqualityHelper to support sorting like this:
>
> protected boolean haveEqualReference(EObject eObject1, EObject
> eObject2, EReference reference) {
> Object value1 = eObject1.eGet(reference);
> Object value2 = eObject2.eGet(reference);
> if (reference.isMany()) {
> List<EObject> list1 = (List<EObject>) value1;
> List<EObject> list2 = (List<EObject>) value2;
> if (reference.isOrdered()) {
> Comparator<EObject> comparator = new
> EObjectComparator(reference.getEKeys());
> Collections.sort(list1, comparator);
> Collections.sort(list2, comparator);
This actually modifies the state of the model as part of equality
testing... That seems not so ideal...
> }
> return equals(list1, list2);
> } else {
> return equals((EObject)value1, (EObject)value2);
> }
> }
>
>
> The comparator sorts depending on the keys, if any are given,
> otherwise it uses toString comparison. The values in the key
> attributes are checked, if they implement java.lang.Comparable, which
> works for Numbers, String, Date and Enums
>
> What do you think of this pattern? Is it something to contribute to
> enhance the EcoreUtil.EqualityHelper? Because this use-case is
> probalby not the most common one, maybe it should be parameterized.
> EcoreUtil.equals(EObject eObject1, EObject eObject2, boolean sort)
It seems odd to me that an equality tester should modify the state of
the model. One generally expects a tester to be side-effect free...
>
> By the way my implementation supports ignore-features too, that are
> ignored during comparison when they are not important for the equality.
>
> Regards,
> Mark


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: EcoreUtil.EqualityHelper and 'ordered' feature [message #1647219 is a reply to message #1647088] Tue, 03 March 2015 10:08 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi

Perhaps I misunderstand, but it seems you have an ordered collection
whose order you are unhappy with.

Surely the solution is either to make the collection unordered, or to
fix-up your assignment algorithm so that it is sensibly ordered?

EMF unordered collections are realised by ELists so that they do
actually have an order that can be inconvenient if you use something
like org.eclipse.xtext.util.EmfFormatter as the basis for a
JUnit-friendly model comparison. For that purpose, I use a hierarchy of
Normalizer classes, so that a first traversal pass over the model
gathers all the normalizations that are necessary, then the
normalizations can be performed in a second 'pass' without corrupting an
iterator domain. Once normalized, 'equivalent' models can be compared
for exact equality. But as EdM observed, modifying models is dubious. It
is often tolerable at the end of JUnit tests., however where
intolerable, the Normalizers support an inverse denormalization
operation so that the normalization can be reverted.

Your Comparator assumes that getEKeys() is the basis for an ordering.
There are many different comparisons, so hardwiring one doesn't seem
helpful.

An idea! Rather than a disruptive normalizer, why not provide an Guava
Iterable that presents a normalized view of your collection? An
EStructuralFeature to NormalizedIteratableFactory registry could provide
something extensible and neutral.

Regards

Ed Willink


On 03/03/2015 08:46, Mark Hoffmann wrote:
> Hello together,
>
> I noticed that the 'ordered' feature in the ecore has no influence on
> the code generation process. It is no bigger problem until now.
> Currently I have a use case where I want to compare to model instance
> for equality. But there are many-references with content that has not
> the same order in the list. The order is not important for the
> equality in this case, but only the content of the objects.
>
> For that I created my own EqualityHelper extending the
> EcoreUtil.EqualityHelper to support sorting like this:
>
> protected boolean haveEqualReference(EObject eObject1, EObject
> eObject2, EReference reference) {
> Object value1 = eObject1.eGet(reference);
> Object value2 = eObject2.eGet(reference);
> if (reference.isMany()) {
> List<EObject> list1 = (List<EObject>) value1;
> List<EObject> list2 = (List<EObject>) value2;
> if (reference.isOrdered()) {
> Comparator<EObject> comparator = new
> EObjectComparator(reference.getEKeys());
> Collections.sort(list1, comparator);
> Collections.sort(list2, comparator);
> }
> return equals(list1, list2);
> } else {
> return equals((EObject)value1, (EObject)value2);
> }
> }
>
>
> The comparator sorts depending on the keys, if any are given,
> otherwise it uses toString comparison. The values in the key
> attributes are checked, if they implement java.lang.Comparable, which
> works for Numbers, String, Date and Enums
>
> What do you think of this pattern? Is it something to contribute to
> enhance the EcoreUtil.EqualityHelper? Because this use-case is
> probalby not the most common one, maybe it should be parameterized.
> EcoreUtil.equals(EObject eObject1, EObject eObject2, boolean sort)
>
> By the way my implementation supports ignore-features too, that are
> ignored during comparison when they are not important for the equality.
>
> Regards,
> Mark
Re: EcoreUtil.EqualityHelper and 'ordered' feature [message #1647228 is a reply to message #1647123] Tue, 03 March 2015 10:12 Go to previous messageGo to next message
Mark Hoffmann is currently offline Mark HoffmannFriend
Messages: 113
Registered: July 2009
Location: Jena
Senior Member
Hi Ed,

Touche Smile.

I agree completely. Some modifications can avoid the modification:

protected boolean haveEqualReference(EObject eObject1, EObject eObject2, EReference reference) {
    Object value1 = eObject1.eGet(reference);
    Object value2 = eObject2.eGet(reference);
    
    if (reference.isMany()) {
      List<EObject> list1 = (List<EObject>) value1;
      List<EObject> list2 = (List<EObject>) value2;
      if (reference.isOrdered() && reference.getEKeys().size() > 0) {
        Comparator<EObject> comparator = new EObjectComparator(reference.getEKeys());
        list1 = new ArrayList<EObject>(list1);
        list2 = new ArrayList<EObject>(list2);
        Collections.sort(list1, comparator);
        Collections.sort(list2, comparator);
      }
      return equals(list1, list2);
    } else {
      return equals((EObject)value1, (EObject)value2);
    }
  }


The question is, do you think it is useful for EcoreUtil.EqualityHelper?

Mark
Re: EcoreUtil.EqualityHelper and 'ordered' feature [message #1647258 is a reply to message #1647219] Tue, 03 March 2015 10:31 Go to previous messageGo to next message
Mark Hoffmann is currently offline Mark HoffmannFriend
Messages: 113
Registered: July 2009
Location: Jena
Senior Member
Hi Ed,

Thank you for you response.

I already had something like your normalizer in mind.
The two pass step is an good idea. Because I often make use of the EKeys, I can use the comparator for a default implementation of an normalizer.

Thank you,
Mark

Ed Willink wrote on Tue, 03 March 2015 11:08
Hi

Perhaps I misunderstand, but it seems you have an ordered collection
whose order you are unhappy with.

Surely the solution is either to make the collection unordered, or to
fix-up your assignment algorithm so that it is sensibly ordered?

EMF unordered collections are realised by ELists so that they do
actually have an order that can be inconvenient if you use something
like org.eclipse.xtext.util.EmfFormatter as the basis for a
JUnit-friendly model comparison. For that purpose, I use a hierarchy of
Normalizer classes, so that a first traversal pass over the model
gathers all the normalizations that are necessary, then the
normalizations can be performed in a second 'pass' without corrupting an
iterator domain. Once normalized, 'equivalent' models can be compared
for exact equality. But as EdM observed, modifying models is dubious. It
is often tolerable at the end of JUnit tests., however where
intolerable, the Normalizers support an inverse denormalization
operation so that the normalization can be reverted.

Your Comparator assumes that getEKeys() is the basis for an ordering.
There are many different comparisons, so hardwiring one doesn't seem
helpful.

An idea! Rather than a disruptive normalizer, why not provide an Guava
Iterable that presents a normalized view of your collection? An
EStructuralFeature to NormalizedIteratableFactory registry could provide
something extensible and neutral.

Regards

Ed Willink


On 03/03/2015 08:46, Mark Hoffmann wrote:
> Hello together,
>
> I noticed that the 'ordered' feature in the ecore has no influence on
> the code generation process. It is no bigger problem until now.
> Currently I have a use case where I want to compare to model instance
> for equality. But there are many-references with content that has not
> the same order in the list. The order is not important for the
> equality in this case, but only the content of the objects.
>
> For that I created my own EqualityHelper extending the
> EcoreUtil.EqualityHelper to support sorting like this:
>
> protected boolean haveEqualReference(EObject eObject1, EObject
> eObject2, EReference reference) {
> Object value1 = eObject1.eGet(reference);
> Object value2 = eObject2.eGet(reference);
> if (reference.isMany()) {
> List<EObject> list1 = (List<EObject>) value1;
> List<EObject> list2 = (List<EObject>) value2;
> if (reference.isOrdered()) {
> Comparator<EObject> comparator = new
> EObjectComparator(reference.getEKeys());
> Collections.sort(list1, comparator);
> Collections.sort(list2, comparator);
> }
> return equals(list1, list2);
> } else {
> return equals((EObject)value1, (EObject)value2);
> }
> }
>
>
> The comparator sorts depending on the keys, if any are given,
> otherwise it uses toString comparison. The values in the key
> attributes are checked, if they implement java.lang.Comparable, which
> works for Numbers, String, Date and Enums
>
> What do you think of this pattern? Is it something to contribute to
> enhance the EcoreUtil.EqualityHelper? Because this use-case is
> probalby not the most common one, maybe it should be parameterized.
> EcoreUtil.equals(EObject eObject1, EObject eObject2, boolean sort)
>
> By the way my implementation supports ignore-features too, that are
> ignored during comparison when they are not important for the equality.
>
> Regards,
> Mark

Re: EcoreUtil.EqualityHelper and 'ordered' feature [message #1647267 is a reply to message #1647228] Tue, 03 March 2015 10:35 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33140
Registered: July 2009
Senior Member
Mark,

Comments below.


On 03/03/2015 11:12 AM, Mark Hoffmann wrote:
> Hi Ed,
>
> Touche :).
> I agree completely. Some modifications can avoid the modification:
>
>
> protected boolean haveEqualReference(EObject eObject1, EObject
> eObject2, EReference reference) {
> Object value1 = eObject1.eGet(reference);
> Object value2 = eObject2.eGet(reference);
> if (reference.isMany()) {
> List<EObject> list1 = (List<EObject>) value1;
> List<EObject> list2 = (List<EObject>) value2;
> if (reference.isOrdered() && reference.getEKeys().size() > 0) {
> Comparator<EObject> comparator = new
> EObjectComparator(reference.getEKeys());
> list1 = new ArrayList<EObject>(list1);
> list2 = new ArrayList<EObject>(list2);
> Collections.sort(list1, comparator);
> Collections.sort(list2, comparator);
> }
> return equals(list1, list2);
> } else {
> return equals((EObject)value1, (EObject)value2);
> }
> }
>
>
> The question is, do you think it is useful for EcoreUtil.EqualityHelper?
It hard codes quite specific details that I'm not sure are so generally
applicable. What Ed W suggests, i.e., a normalization traversal, seems
more natural, but of course that doesn't deal with your desire to ignore
some features as well. Certainly the Copier and EqualityHelper are
designed to be subclassed quite easily, so additional refactoring to
make that easier (i.e., less need to duplicate significantly large
methods in order to specialize behavior) seems a more palatable (as was
done with the Copier during the previous release)...
>
> Mark


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: EcoreUtil.EqualityHelper and 'ordered' feature [message #1647290 is a reply to message #1647267] Tue, 03 March 2015 10:51 Go to previous messageGo to next message
Mark Hoffmann is currently offline Mark HoffmannFriend
Messages: 113
Registered: July 2009
Location: Jena
Senior Member
Ed,

Thank you, I will follow the normalizer idea. I think that makes even more sense in my system.

Regards,
Mark
Re: EcoreUtil.EqualityHelper and 'ordered' feature [message #1647338 is a reply to message #1647290] Tue, 03 March 2015 11:23 Go to previous message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi

org.eclipse.ocl.examples.xtext.tests. Normalizer and its derived
implementations might give you some inspiration.

Regards

Ed Willink

On 03/03/2015 10:51, Mark Hoffmann wrote:
> Ed,
>
> Thank you, I will follow the normalizer idea. I think that makes even
> more sense in my system.
>
> Regards,
> Mark
Previous Topic:Clarification on EditingDomainViewerDropAdapter.getDragSource(...) method
Next Topic:EMF Resource load from InputStream taking too long
Goto Forum:
  


Current Time: Wed Apr 24 23:11:20 GMT 2024

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

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

Back to the top