Example: Validate an OO model with EVL

context OO!NamedElement {
  
  // Every NamedElement must define a name
  constraint HasName {
    
    check : self.name <> ""

    message : "Element " + self + " must define a name"
    
  }
} 

context OO!Feature {
  
  // The name of a feature (attribute,referecne,parameter)
  // should start with a lower case letter
  critique NameMustStartWithLowerCase {
    
    guard : self.satisfies("HasName")
    
    check : self.name.substring(0,1) = 
      self.name.substring(0,1).toLowerCase()
    
  }
}

context OO!Class {
  
  // The name of a class should start with
  // an upper case letter
  critique NameShouldStartWithUpperCase {
    
    guard : self.satisfies("HasName")
    
    check : self.name.substring(0,1) = 
      self.name.substring(0,1).toUpperCase()
    
    message : "The name of class " + self.name + 
      " should start with an upper-case letter"
  
    fix {
      title : "Rename class " + self.name + " to " + 
        self.name.firstToUpperCase()
      
      do {
        self.name = self.name.firstToUpperCase();}
    }
  }
  
  // A class must not directly or indirectly
  // inherit from itself
  constraint MustNotInheritItself {
    
    check : not self.inherits(self)
    
    message : "Class " + self.name + " inherits itself"
    
  }
  
  // A class is unused when it is not the type of a feature
  // or a parameter and is not extended by another class
  critique UnusedClass {
    
    check : Parameter.allInstances.exists(p|p.type = self) or 
      Feature.allInstances.exists(f|f.type = self) or
      Class.allInstances.exists(c|c.`extends` = self)
    
    message : "Unused class " + self.name
    
    fix {
      title : "Delete class " + self.name
      
      do {
        delete self;
      }
    }
  }
}

// Returns if a class directly or indirectly
// inherits from another class
operation Class inherits(c : Class) : Boolean {
  
  if (self.`extends`.isDefined()) {
    return self.`extends` = c or self.`extends`.inherits(c);
  }
  else {
    return false;
  }
}
@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;
}

Check out the code from the SVN:

  • go to the SVN repository
  • navigate to trunk/examples
  • check out the org.eclipse.epsilon.examples.metamodels project
  • check out the org.eclipse.epsilon.examples.validateoo project

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.validateoo project
  3. right click the .launch file in the org.eclipse.epsilon.examples.validateoo 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 express constraints for models that conform to an Object-Oriented metamodel.

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
Combining the Epsilon Languages
EuGENia
EUnit

Even more examples...

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