blob: 059811fedd2b70fec32a216c8dd16a594d1a7620 [file] [log] [blame]
import 'ECoreUtil.eol';
context EPackage {
constraint DiagramIsDefined {
check : getDiagramClass().isDefined()
message : 'One class must be specified as gmf.diagram'
}
constraint ContainmentReferencesAreDefined {
guard : self.satisfies('DiagramIsDefined')
check : getDiagramClass().getContainmentReferences().size() > 0
message : 'Diagram class ' + getDiagramClass().name + ' must define '
+ ' at least one containment reference'
}
constraint NodesAreDefined {
guard : self.satisfies('DiagramIsDefined')
check : getNodes().size() > 0
message : 'No nodes (gmf.node) have been defined'
}
critique ReferenceLinksAreDefined {
guard : self.satisfies('DiagramIsDefined')
check : getReferenceLinks().size() > 0 or getLinks().size > 0
message : 'No reference links (gmf.link) have been defined'
}
}
context EClass {
guard : self.isNode()
constraint IsValidSvgNode {
check : (self.getAnnotationValue('gmf.node', 'figure') = "svg") implies
(self.getAnnotationValue('gmf.node', 'svg.uri').isDefined())
message : "No svg.uri provided for SVG figure " + self.name
}
constraint IsValidPolygonNode {
check : (self.getAnnotationValue('gmf.node', 'figure') = "polygon") implies
(
self.getAnnotationValue('gmf.node', 'polygon.x').isDefined() and
self.getAnnotationValue('gmf.node', 'polygon.y').isDefined()
)
message : "No polygon x/y coordinates provided for polygon figure " + self.name
}
constraint NodeLabelIsDefined {
guard : self.getAnnotationValue('gmf.node', 'label.placement') <> "none"
check : self.getAnnotationValue('gmf.node', 'label').isDefined()
message : 'No label defined for class ' + self.name
}
constraint NodeLabelsExist {
guard : self.satisfies('NodeLabelIsDefined')
check {
var missing : Sequence(String);
for (label : String in self.getAnnotationValue('gmf.node', 'label').split(',').collect(s|s.trim())){
if (not self.getAttribute(label).isDefined()) {
missing.add(label);
}
}
return missing.size() = 0;
}
message : 'Label attribute(s) ' + missing.concat(', ')
+ ' do(es) not exist in class ' + self.name
}
}
context EAnnotation {
constraint IsValidCompartment {
guard : self.source = "gmf.compartment"
check : self.eContainer().isTypeOf(EReference) and self.eContainer().containment = true
message : "EReference " + self.eContainer().name + " is not a containment reference"
}
}
/*
* Validation rules for annoations details
*/
context EStringToStringMapEntry {
critique IsValidLinkDecoration {
guard : self.is('gmf.link', 'source.decoration') or
self.is('gmf.link', 'target.decoration')
check {
var values := Sequence{'none', 'arrow', 'rhomb', 'filledrhomb',
'square', 'filledsquare', 'closedarrow', 'filledclosedarrow'};
return self.value.isWithinValuesOrLooksLikeJavaClassName(values);
}
message : 'The value of ' + self.toEmfatic() + ' must be one of: ' + values.concat(', ') +
" or a fully-qualified Java class name"
}
critique IsValidNodeFigure {
guard : self.is('gmf.node', 'figure')
check {
var values := Sequence{'rectangle', 'ellipse', 'rounded', 'svg',
'polygon'};
return self.value.isWithinValuesOrLooksLikeJavaClassName(values);
}
message : 'The value of ' + self.toEmfatic() + ' must be one of: ' + values.concat(', ') +
" or a fully-qualified Java class name"
}
constraint IsValidLabelPlacement {
guard : self.is('gmf.node', 'label.placement')
check {
var values := Sequence{'internal', 'external', 'none'};
return values.includes(self.value);
}
message : 'The value of ' + self.toEmfatic() + ' must be one of: ' + values.concat(', ')
}
constraint IsValidInteger {
guard : self.is('gmf.node', 'border.width') or
self.is('gmf.node', 'margin')
check : self.value.isInteger()
message : 'The value of ' + self.key + " is not a valid integer"
}
constraint IsValidListOfIntegers {
guard : self.is('gmf.node', 'polygon.x') or
self.is('gmf.node', 'polygon.y')
check : self.value.matches("(\\s*\\d+)+")
message : 'The value of ' + self.toEmfatic() + " is not a valid list of integers"
}
constraint IsValidDimension {
guard : self.is('gmf.node', 'size')
check : self.value.matches("\\s*\\d+,\\s*\\d+\\s*")
message : 'The value of ' + self.toEmfatic() + " is not a valid dimension"
}
constraint IsValidRGB {
guard : self.is('gmf.node', 'border.color') or
self.is('gmf.node', 'color') or
self.is('gmf.link', 'color')
check : self.value.matches("\\s*\\d+,\\s*\\d+,\\s*\\d+\\s*")
message : 'The value of ' + self.toEmfatic() + " is not a valid RGB color"
}
constraint IsValidBoolean {
guard : self.is('gmf.diagram', 'rcp') or
self.is('gmf.node', 'label.icon') or
self.is('gmf.node', 'label.readOnly') or
self.is('gmf.node', 'phantom') or
self.is('gmf.node', 'resizable') or
self.is('gmf.compartment', 'collapsible') or
self.is('gmf.label', 'label.readOnly')
check {
var values := Sequence{'true', 'false'};
return values.includes(self.value);
}
message : 'The value of ' + self.toEmfatic() + ' must be one of: ' + values.concat(', ')
}
constraint IsValidLineStyle {
guard : self.is('gmf.node', 'border.style') or
self.is('gmf.link', 'style')
check {
var values := Sequence{'dot', 'dash', 'solid'};
return values.includes(self.value);
}
message : "The value of " + self.toEmfatic() + " must be one of: " + values.concat(', ')
}
constraint IsValidCompartmentLayout {
guard : self.key = 'layout'
check {
var values := Sequence{'list', 'free'};
return values.includes(self.value);
}
message : 'The layout of the ' + self.eContainer().eContainer().name +
' compartment must be one of: ' + values.concat(', ')
}
}
context EClass {
guard : self.isLink()
constraint LinkLabelExists {
guard : self.getAnnotationValue('gmf.link', 'label').isDefined()
check {
var missing : Sequence(String);
for (label : String in self.getAnnotationValue('gmf.link', 'label').split(',').collect(s|s.trim())){
if (not self.getAttribute(label).isDefined()) {
missing.add(label);
}
}
return missing.size() = 0;
}
message : 'Label attribute(s) ' + missing.concat(', ')
+ ' does not exist in link class ' + self.name
}
constraint LinkSourceIsDefined {
check : self.getAnnotationValue('gmf.link', 'source').isDefined()
message : 'No source defined for link class ' + self.name
}
constraint LinkSourceExists {
guard : self.satisfies('LinkSourceIsDefined')
check : self.getReference(self.getAnnotationValue('gmf.link', 'source')).isDefined()
message : 'No reference named ' + self.getAnnotationValue('gmf.link', 'source')
+ ' exists in link class ' + self.name
}
constraint LinkTargetIsDefined {
check : self.getAnnotationValue('gmf.link', 'target').isDefined()
message : 'No target defined for link class ' + self.name
}
constraint LinkTargetExists {
guard : self.satisfies('LinkTargetIsDefined')
check : self.getReference(self.getAnnotationValue('gmf.link', 'target')).isDefined()
message : 'No reference named ' + self.getAnnotationValue('gmf.link', 'target')
+ ' exists in link class ' + self.name
}
constraint LinkTargetAndSourceMustBeDifferent {
guard : self.satisfies('LinkSourceExists') and self.satisfies('LinkTargetExists')
check : self.getAnnotationValue('gmf.link', 'source') <> self.getAnnotationValue('gmf.link', 'target')
message : 'Source and target attributes must be different in link class ' + self.name
}
critique CanBeVisualized {
guard : getDiagramClass().isDefined()
check : getDiagramContainmentReference(self).isDefined()
message : 'Cannot generate link for class ' + self.name +
' because it cannot be contained in any containment reference' +
' of diagram root ' + getDiagramClass().name
}
}
operation String isWithinValuesOrLooksLikeJavaClassName(values : Sequence) {
return values.includes(self) or self.indexOf('.') > -1;
}
operation EStringToStringMapEntry is(annotation : String, key : String) {
return self.eContainer().source = annotation and self.key = key;
}
operation ECore!EClass getAttribute(name : String) {
return self.eAllStructuralFeatures.selectOne(sf:ECore!EAttribute|sf.name = name);
}
operation ECore!EClass getReference(name : String) {
return self.eAllStructuralFeatures.selectOne(sf:ECore!EReference|sf.name = name);
}
operation EStringToStringMapEntry toEmfatic() {
var s = "@" + self.eContainer.source + "(" + self.key + ")";
if (self.eContainer().isKindOf(EStructuralFeature)) {
s = s + " of " + self.eContainer().eContainer().eContainer().name + "." +
self.eContainer().eContainer().name;
}
else {
s = s + " of " + self.eContainer().eContainer().name;
}
return s;
}
operation Any getTopEPackage() {
if (self.eContainer().isDefined()) {
return self.eContainer().getTopEPackage();
}
else {
return self;
}
}