Example: Validate an OO model with EVL


  • ValidateOO.evl
  • OO.emf
  • Get it!
context NamedElement {
  
  -- Every NamedElement must define a name
  constraint HasName {
    
    check : self.name <> ''

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

context 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 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;
}

There are two ways to get the code of this example:

  1. download the following zip archive(s), extract them and import them as new Eclipse projects
  2. or 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. right click the .launch file in the org.eclipse.epsilon.examples.validateoo project
  3. select Run as... and click the first item in the menu that pops up