Example: Validate an OO model against a DB model with EVL

context OO!Class {
  constraint TableExists {
    // The condition that needs to be satisfied: 
    // For every class X there is a table named T_X
    check : DB!Table.all.select(t|t.name = "T_" + self.name).size() > 0
    // The message that is displayed to the user
    // if the check part returns false
    message : "No table found for class " + self.name
    // This is an optional fix which the user may want to invoke
    // to fix this inconsistency
    fix {
      title : "Add missing table"
      do {
        var table = new DB!Table;
        table.name = "T_" + self.name;
@namespace(uri="OO", prefix="OO")
package OO;

class Model extends Package {

abstract class PackageableElement extends NamedElement {
  ref Package#contents ~package;

abstract class AnnotatedElement {
  val Annotation[*] annotations;

class Annotation {
  attr String key;
  attr String value;

abstract class NamedElement extends AnnotatedElement {
  attr String name;

class Package extends PackageableElement {
  val PackageableElement[*]#~package contents;

abstract class ~Classifier extends PackageableElement {

class ExternalClass extends ~Class {

class ~Class extends ~Classifier {
  ref ~Class#extendedBy ~extends;
  ref ~Class[*]#~extends extendedBy;
  val Feature[*]#owner features;
  attr Boolean isAbstract;

class Datatype extends ~Classifier {

abstract class Feature extends NamedElement {
  ref ~Class#features owner;
  ref ~Classifier type;
  attr VisibilityEnum visibility;

abstract class StructuralFeature extends Feature {
  attr Boolean isMany;

class Operation extends Feature {
  val Parameter[*]#owner parameters;

class Parameter extends NamedElement {
  ref ~Classifier type;
  ref Operation#parameters owner;

class Reference extends StructuralFeature {

class Attribute extends StructuralFeature {

enum VisibilityEnum {
  public = 1;
  private = 2;
@namespace(uri="DB", prefix="DB")
package DB;

abstract class NamedElement {
    attr String name;

class Database {
   val DatabaseElement[*]#database contents;

abstract class DatabaseElement extends NamedElement {
   ref Database#contents database;

class Table extends DatabaseElement {
   val Column[*]#table columns;
   ref Column[*] primaryKeys;

class Column extends DatabaseElement {
   ref Table#columns table;
   attr String type;

class ForeignKey extends DatabaseElement {
   ref Column parent;
   ref Column child;
   attr Boolean isMany;

Clone Epsilon's Git repository and then:

Once you have checked out/imported the code, to run the example you need to go through the following steps:

  1. register all .ecore metamodels in the org.eclipse.epsilon.examples.metamodels project (select all of them and then right click and select Register EPackages)
  2. register any .ecore metamodels in the org.eclipse.epsilon.examples.evl.intermodel project
  3. right click the .launch file in the org.eclipse.epsilon.examples.evl.intermodel project
  4. select Run as... and click the first item in the menu that pops up

What's this?

In this example, we use EVL to expressing inter-model constraints.

What are .emf files?

.emf files are Ecore metamodels expressed using the Emfatic textual syntax.

More examples...

Epsilon Object Language
Epsilon Transformation Language
Epsilon Generation Language
Epsilon Validation Language
Epsilon Merging Language
Epsilon Flock
Epsilon Model Generation Language
Epsilon Pattern Language
Combining the Epsilon Languages

Even more examples...

More examples are available in the examples folder of the Git repository.