Custom types and custom operations in OCL

We got this Question:

I have an attribute of type TestStruct defined on a class.

TestStruct is defined as follows:

Code Snippet
  1. public struct TestStruct : IComparable
  2. {
  3.   public int Int1 { get; private set; }
  4.   public int Int2 { get; private set; }
  5.  
  6.   public TestStruct(int int1, int int2)
  7.     : this()
  8.   {
  9.     this.Int1 = int1;
  10.     this.Int2 = int2;
  11.   }
  12.  
  13.   public int CompareToX(object obj)
  14.   {
  15.     return CompareTo(obj);
  16.   }
  17.  
  18.   public int CompareToX(TestStruct other)
  19.   {
  20.     return CompareTo(other);
  21.   }
  22.  
  23.   public int CompareTo(TestStruct other)
  24.   {
  25.     return (Int1 + Int2).CompareTo(other.Int1 + other.Int2);
  26.   }
  27.  
  28.   #region IComparable Members
  29.  
  30.   public int CompareTo(object obj)
  31.   {
  32.     return CompareTo((TestStruct)obj);
  33.   }
  34.  
  35.   #endregion
  36. }

 

The following Ocl expression gives an error “Eco.FrameworkImpl.Ocl.EBoldOCLAbort: 31:Undefined operation: CompareTo”

Class1.allInstances.Attribute2.CompareTo(Class1.allInstances->first.Attribute2)

However, the expression

Class1.allInstances.Attribute2.CompareToX(Class1.allInstances->first.Attribute2)

Works OK

Why is this happening?

So there are a couple of things that are interesting in this:

  1. ECO can use any native type you define as a type of an attribute (beware you will need to explain how to persist the type if you want to store it in a database – AbstractSingleColumnAttribute, ISingleColumnAttributemapping, IDefaultReverseMapping)
  2. ECO will pick up on Methods of this native type and make them available in the Object constraint language – OCL – so that you can use the method in OCL and EAL.

So how come CompareToX works but CompareTo does not work?

Answer: CompareTo is common and well-known so we hijack it and map it to the “=”-operator of OCL. You need to go like this:

Class1.allInstances.Attribute2=(Class1.allInstances->first.Attribute2)

But while testing this I was surprised to find that my CompareTo was still not called… It turned out that we in ECO used the Equals operator, so you would need to amend your struct code with something like this: (GetHashCode override is to avoid warning)

  1. public override bool Equals(Object obj)
  2. {
  3.   return CompareTo(obj)==0;
  4. }
  5.  
  6. public override int GetHashCode()
  7. {
  8.   return Int1 ^ Int2;
  9. }

It all seemed a bit complex in the end so new builds of ECO has been changed to call look like this:

  1. if (thisobject is IComparable)
  2.   return ((IComparable)thisobject).CompareTo(elementAsObject)==0;
  3. else
  4.         return object.Equals(GetAsObject(), elementAsObject);

Which in turn means that we from now and on will use IComparable, if implemented,  for checking Equality on attribute types.

This entry was posted in EcoActionLanguage, OCL. Bookmark the permalink.

One Response to Custom types and custom operations in OCL

  1. Efim Mett says:

    While observing the OCL expressions I would expect the both not to work because a collection of TestStruct (Class1.allInstances.Attribute2) is tried to be compared with TestStruct instance. Do I miss something?

Leave a Reply

Your email address will not be published. Required fields are marked *

*