Custom types and custom operations in OCL
No edit summary
No edit summary
Line 1: Line 1:
We received this Question:<blockquote>'''I have an attribute of type TestStruct defined on a class.'''</blockquote>TestStruct is defined as follows:
We received this question:<blockquote>'''I have an attribute of type TestStruct defined on a class.'''</blockquote>TestStruct is defined as follows:


'''Code Snippet'''
'''Code Snippet'''
Line 32: Line 32:
  <nowiki>#</nowiki>endregion
  <nowiki>#</nowiki>endregion
  }
  }
The following OCL expression gives an error: "Eco.FrameworkImpl.Ocl.EBoldOCLAbort: 31:Undefined operation: CompareTo"
The following OCL expression gives an error: "Eco.FrameworkImpl.Ocl.EBoldOCLAbort: 31:Undefined operation: CompareTo"<blockquote>'''''Class1.allInstances.Attribute2.CompareTo(Class1.allInstances-'''''</blockquote><blockquote>'''''>first.Attribute2)'''''</blockquote>However, the expression:<blockquote>'''''Class1.allInstances.Attribute2.CompareToX(Class1.allInstances-'''''</blockquote><blockquote>'''''>first.Attribute2)'''''</blockquote>Works OK.
 
'''''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? ===
=== Why is this happening? ===
Line 50: Line 38:
# 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)
# 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)
# 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.
# 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.
How come CompareToX works but CompareTo does not work?
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 do this:
 
'''''Class1.allInstances.Attribute2=(Class1.allInstances->first.Attribute2)'''''


While testing this, however, I was surprised to find that my CompareTo was still not called… It turned out that, in ECO, we used the Equals operator - you would need to amend your struct code with something like this: (GetHashCode override is to avoid the warning.)
'''Answer''': CompareTo is common and well-known, so we hijack it and map it to the “=” operator of OCL. You need to do this:<blockquote>'''Class1.allInstances.Attribute2=(Class1.allInstances->first.Attribute2)'''</blockquote>While testing this, however, I was surprised that my CompareTo was still not called… It turned out that, in ECO, we used the Equals operator - you would need to amend your struct code with something like this: (GetHashCode override is to avoid the warning.)
  public override bool Equals(Object obj)
  public override bool Equals(Object obj)
  {
  {
Line 65: Line 49:
  return Int1 ^ Int2;
  return Int1 ^ Int2;
  }
  }
It all seemed a bit complex in the end so new builds of ECO have been changed to all look like this:
It all seemed a bit complex in the end, so new builds of ECO have been changed to all look like this:
  if (thisobject is IComparable)
  if (thisobject is IComparable)
   return ((IComparable)thisobject).CompareTo(elementAsObject)==0;
   return ((IComparable)thisobject).CompareTo(elementAsObject)==0;

Revision as of 06:09, 12 September 2023

We received this question:

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

TestStruct is defined as follows:

Code Snippet

public struct TestStruct : IComparable
{
public int Int1 { get; private set; }
public int Int2 { get; private set; }
public TestStruct(int int1, int int2)
: this()
{
this.Int1 = int1;
this.Int2 = int2;
}
public int CompareToX(object obj)
{
return CompareTo(obj);
}
public int CompareToX(TestStruct other)
{
return CompareTo(other);
}
public int CompareTo(TestStruct other)
{
return (Int1 + Int2).CompareTo(other.Int1 + other.Int2);
}

#region IComparable Members
public int CompareTo(object obj)
{
return CompareTo((TestStruct)obj);
}
#endregion
}

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?

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.

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 do this:

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

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

public override bool Equals(Object obj)
{
return CompareTo(obj)==0;
}
public override int GetHashCode()
{
return Int1 ^ Int2;
}

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

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

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

This page was edited 101 days ago on 02/10/2024. What links here