It is alive!

In one of my earlier blog posts, I have outlined the basic ideas and transformation patterns that accomplish a translation of (a subset of) OCL expressions into graph patterns. The theory was illustrated by running examples from the school case study, where the purpose of querying was to find classmates with the same name. The good news is that I have managed creating an experimental implementation of this translation that maps OCL expressions to equivalent graph patterns.

If you recall, the original OCL expression detecting such name conflicts was expressed in context of a SchoolClass as follows:

self.students->collect(s1 | self.students->select(s2 | s2.name = s1.name and s1 <> s2)->
      collect(s2 | Tuple{student1 = s1, student2 = s2, name = s1.name}))

The following graph patterns was given originally as its translation:

pattern nameConflicts(clazz: SchoolClass, student1: Student, student2: Student, name: EString) = {
  SchoolClass.students(clazz, student1);
  SchoolClass.students(clazz, student2);
  student1 != student2;
  Student.name(student1, name);
  Student.name(student2, name);
}

My tool can currently generate this from the OCL expression as input:

pattern translated(
    self : SchoolClass,
    student2 : Student,
    student1 : Student,
    name : EString
) {
    SchoolClass.students(self, student);
    s1 == student;
    eInt == count find translated_0(s2,s1);
    eBoolean == eval(eInt > 0);
    eInt_0 == count find translated_1(s2,s1);
    eBoolean_0 == eval(eInt_0 > 0);
    boolean_0 == eval((eBoolean as boolean) && (eBoolean_0 as boolean));
    true == boolean_0;
    SchoolClass.students(self, student_0);
    s2 == student_0;
    s2_0 == s2;
    Student.name(s1, eString_1);
    student1 == s1;
    student2 == s2_0;
    name == eString_1;
}

pattern translated_0(
    s2 : Student,
    s1 : Student
) {
    Student.name(s2, eString);
    Student.name(s1, eString_0);
    eString == eString_0;
}

pattern translated_1(
    s2 : Student,
    s1 : Student
) {
    s1 != s2;
}

Admittedly, it is not nearly as nice as the original solution, as some of the solutions I have implemented are quite simple and stupid right now, not as elegant and clever as they could eventually be. In some cases - such as the many EMF-IncQuery variables unnecessarily equated to each other - this is purely a matter of aesthetics. In others, such as pattern translated_1, it actually hurts query evaluation efficiency. However, these generated patterns do the job and deliver correct results.

Furthermore, the tool does not handle yet all OCL language elements for which the translation was shown to be possible, including some things seen in this former blog post.

The experimental implementation was realized as an Eclipse plug-in. The source code project is available at github. Use it in the following way:

        EClass context= MyMetaModelPackage.eINSTANCE; /* reference your Ecore package here*/
        String oclCode = "self.whatever"; /* insert OCL code here */
        OCLExpression exp = new OCLParseControl().parse(context, oclCode);
        String patternCode = new OCL2IQ(context, exp, "translated").gen().toString();

 

This research was supported by the European Union and the State of Hungary, co-financed by the European Social Fund in the framework of TÁMOP 4.2.4. A/1-11-1-2012-0001 'National Excellence Program'.