| /* |
| * generated by Xtext 2.10.0 |
| */ |
| package org.eclipse.emf.henshin.text.validation |
| |
| import com.google.common.collect.Iterables |
| import com.google.inject.Inject |
| import java.lang.reflect.Field |
| import java.lang.reflect.Method |
| import java.util.ArrayList |
| import java.util.List |
| import org.eclipse.emf.ecore.EClass |
| import org.eclipse.emf.ecore.EObject |
| import org.eclipse.emf.ecore.EReference |
| import org.eclipse.emf.henshin.text.henshin_text.AndExpression |
| import org.eclipse.emf.henshin.text.henshin_text.Attribute |
| import org.eclipse.emf.henshin.text.henshin_text.Call |
| import org.eclipse.emf.henshin.text.henshin_text.ComparisonExpression |
| import org.eclipse.emf.henshin.text.henshin_text.ConditionEdge |
| import org.eclipse.emf.henshin.text.henshin_text.ConditionGraph |
| import org.eclipse.emf.henshin.text.henshin_text.ConditionGraphRef |
| import org.eclipse.emf.henshin.text.henshin_text.ConditionNode |
| import org.eclipse.emf.henshin.text.henshin_text.ConditionReuseNode |
| import org.eclipse.emf.henshin.text.henshin_text.ConditionalUnit |
| import org.eclipse.emf.henshin.text.henshin_text.EPackageImport |
| import org.eclipse.emf.henshin.text.henshin_text.Edge |
| import org.eclipse.emf.henshin.text.henshin_text.Edges |
| import org.eclipse.emf.henshin.text.henshin_text.EqualityExpression |
| import org.eclipse.emf.henshin.text.henshin_text.Expression |
| import org.eclipse.emf.henshin.text.henshin_text.Formula |
| import org.eclipse.emf.henshin.text.henshin_text.Graph |
| import org.eclipse.emf.henshin.text.henshin_text.Henshin_textPackage |
| import org.eclipse.emf.henshin.text.henshin_text.IndependentUnit |
| import org.eclipse.emf.henshin.text.henshin_text.IntegerValue |
| import org.eclipse.emf.henshin.text.henshin_text.IteratedUnit |
| import org.eclipse.emf.henshin.text.henshin_text.JavaAttributeValue |
| import org.eclipse.emf.henshin.text.henshin_text.JavaClassValue |
| import org.eclipse.emf.henshin.text.henshin_text.JavaImport |
| import org.eclipse.emf.henshin.text.henshin_text.Logic |
| import org.eclipse.emf.henshin.text.henshin_text.LoopUnit |
| import org.eclipse.emf.henshin.text.henshin_text.Match |
| import org.eclipse.emf.henshin.text.henshin_text.MinusExpression |
| import org.eclipse.emf.henshin.text.henshin_text.Model |
| import org.eclipse.emf.henshin.text.henshin_text.MulOrDivExpression |
| import org.eclipse.emf.henshin.text.henshin_text.MultiRule |
| import org.eclipse.emf.henshin.text.henshin_text.MultiRuleReuseNode |
| import org.eclipse.emf.henshin.text.henshin_text.Node |
| import org.eclipse.emf.henshin.text.henshin_text.NotExpression |
| import org.eclipse.emf.henshin.text.henshin_text.NumberValue |
| import org.eclipse.emf.henshin.text.henshin_text.OrExpression |
| import org.eclipse.emf.henshin.text.henshin_text.Parameter |
| import org.eclipse.emf.henshin.text.henshin_text.ParameterKind |
| import org.eclipse.emf.henshin.text.henshin_text.ParameterValue |
| import org.eclipse.emf.henshin.text.henshin_text.PlusExpression |
| import org.eclipse.emf.henshin.text.henshin_text.PriorityUnit |
| import org.eclipse.emf.henshin.text.henshin_text.Rule |
| import org.eclipse.emf.henshin.text.henshin_text.Unit |
| import org.eclipse.emf.henshin.text.henshin_text.UnitElement |
| import org.eclipse.emf.henshin.text.henshin_text.impl.ANDImpl |
| import org.eclipse.emf.henshin.text.henshin_text.impl.CheckDanglingImpl |
| import org.eclipse.emf.henshin.text.henshin_text.impl.ConditionsImpl |
| import org.eclipse.emf.henshin.text.henshin_text.impl.GraphImpl |
| import org.eclipse.emf.henshin.text.henshin_text.impl.InjectiveMatchingImpl |
| import org.eclipse.emf.henshin.text.henshin_text.impl.JavaImportImpl |
| import org.eclipse.emf.henshin.text.henshin_text.impl.NotImpl |
| import org.eclipse.emf.henshin.text.henshin_text.impl.ORorXORImpl |
| import org.eclipse.emf.henshin.text.henshin_text.impl.RollbackImpl |
| import org.eclipse.emf.henshin.text.henshin_text.impl.StrictImpl |
| import org.eclipse.emf.henshin.text.typesystem.Henshin_textType |
| import org.eclipse.emf.henshin.text.typesystem.Henshin_textTypeProvider |
| import org.eclipse.xtext.validation.Check |
| |
| /** |
| * This class contains custom validation rules. |
| * |
| * See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#validation |
| */ |
| class Henshin_textValidator extends AbstractHenshin_textValidator { |
| |
| @Inject extension Henshin_textTypeProvider |
| |
| /** |
| * Check that the number and type of parameters match in a unit or rule call |
| * This ignores VAR variables in the to-be-called unit / rule (call.elementCall) as they denote local variables |
| * |
| * @param call to-be-checked call |
| */ |
| @Check |
| def checkCallParameter(Call call){ |
| if(call.elementCall.parameters.filter[kind != ParameterKind.VAR].size!=call.parameters.size){ |
| error("Bad Parameter Count.'", Henshin_textPackage::eINSTANCE.call_ElementCall) |
| }else{ |
| for(var i=0;i<call.elementCall.parameters.filter[kind != ParameterKind.VAR].size;i++){ |
| val param = call.elementCall.parameters.get(i) |
| if(typeFor(param.type)!=typeFor(call.parameters.get(i).type)){ |
| error("Call expected " +typeFor(param.type).toString+ " type, but was " +typeFor(call.parameters.get(i).type).toString+".'",call, Henshin_textPackage::eINSTANCE.call_Parameters) |
| } |
| } |
| } |
| } |
| |
| |
| /** |
| * Warning if a parameter has the parameter kind UNKNOWN which is deprecated. |
| * |
| * @param param to be checked parameter |
| */ |
| @Check |
| def checkParameterKind(Parameter param) |
| { |
| if (param.kind == ParameterKind.UNKNOWN) |
| { |
| warning("Parameter " + param.name + " should have a parameter kind of IN, INOUT, OUR or VAR. Specifying no parameter kind is deprecated.", param, Henshin_textPackage.Literals.PARAMETER__KIND) |
| } |
| } |
| |
| |
| |
| //-------------------------------------------------------------------------- |
| //Rule |
| //-------------------------------------------------------------------------- |
| /** |
| * Fehler wenn eine Kante definiert wurde, die im ecore-Modell nicht existiert |
| * |
| * @param edge Zu überprüfende Kante |
| */ |
| @Check |
| def ckeckExistingEdge(Edge edge){ |
| var EClass sourceType |
| var EClass targetType |
| if(edge.source!=null){ |
| if(edge.source instanceof Node){ |
| sourceType=(edge.source as Node).nodetype |
| }else{ |
| try{ |
| sourceType=(edge.source as MultiRuleReuseNode).name.nodetype |
| }catch(ClassCastException e){ |
| sourceType=null |
| } |
| } |
| } |
| if(edge.target!=null){ |
| if(edge.target instanceof Node){ |
| targetType=(edge.target as Node).nodetype |
| }else{ |
| try{ |
| targetType=(edge.target as MultiRuleReuseNode).name.nodetype |
| }catch(ClassCastException e){ |
| targetType=null |
| } |
| } |
| } |
| if((sourceType!=null)&&(targetType!=null)){ |
| var wrongType=true |
| var EClass referenceType |
| for(reference:sourceType.EAllReferences){ |
| if(edge.type.name==reference.name){ |
| wrongType=false |
| referenceType=reference.EReferenceType |
| } |
| } |
| if(wrongType){ |
| error("Edgetype "+edge.type.name+" does not exist.'",edge, Henshin_textPackage::eINSTANCE.edge_Type) |
| } |
| if(referenceType!=targetType){ |
| error("Edge "+sourceType.name+"->"+targetType.name+":"+edge.type.name+" does not exist.'",edge, Henshin_textPackage::eINSTANCE.edge_Type) |
| } |
| } |
| } |
| |
| /** |
| * Fehler wenn ein Knotentyp verwendet wurde, der nicht importiert wurde |
| * |
| * @param node Zu überprüfender Knoten |
| */ |
| @Check |
| def checkNodeType(Node node){ |
| var isImported=false |
| for(ePackage:getEPackageImports(node)){ |
| if(ePackage.ref.EClassifiers.contains(node.nodetype)){ |
| isImported=true |
| } |
| } |
| if(!isImported){ |
| error("Nodetype "+node.nodetype.name+" is not imported.'",node, Henshin_textPackage::eINSTANCE.node_Nodetype) |
| } |
| } |
| |
| /** |
| * Holt alle importierten EPackages anhand eines beliebigen Objekts |
| */ |
| private def getEPackageImports(EObject startObject){ |
| var List<EPackageImport> listOfEPackageImport=new ArrayList |
| var EObject container=startObject.eContainer() |
| while(!(container instanceof Model)){ |
| container=container.eContainer() |
| } |
| if(container instanceof Model){ |
| listOfEPackageImport.addAll((container as Model).EPackageimports) |
| } |
| return listOfEPackageImport |
| |
| } |
| |
| /** |
| * Fehler wenn ein Attribut in einem Knoten definiert wurde das so nicht im ecore-Modell existiert |
| * |
| * @param node Zu überprüfender Knoten |
| */ |
| @Check |
| def checkNodeAttribute(Node node){ |
| for(attribute:node.attribute){ |
| var superTypeAttribute=false |
| if(!node.nodetype.EAttributes.contains(attribute.name)){ |
| for(supertype:node.nodetype.EAllSuperTypes){ |
| if(supertype.EAttributes.contains(attribute.name)){ |
| superTypeAttribute=true |
| } |
| } |
| if(!superTypeAttribute){ |
| error(node.nodetype.name+" has no attribute '"+attribute.name.name+"'.'",attribute, Henshin_textPackage::eINSTANCE.attribute_Name) |
| } |
| } |
| } |
| } |
| |
| /** |
| * Fehler wenn in einem Knoten das selbe Attribut mehrfach definiert wird |
| * |
| * @param node Zu überprüfender Knoten |
| */ |
| @Check |
| def checkattributeOnlyOnce(Node node){ |
| for(var i=0;i<node.attribute.size;i++){ |
| var attribute=node.attribute.get(i) |
| for(var j=i+1;j<node.attribute.size;j++){ |
| if((attribute.name==node.attribute.get(j).name)&&(attribute.update==node.attribute.get(j).update)){ |
| error("'"+attribute.name.name+"' can only be used once.'",node.attribute.get(j), Henshin_textPackage::eINSTANCE.attribute_Name) |
| } |
| } |
| } |
| } |
| |
| /** |
| * Fehler wenn der Typ eines create Knoten abstrakt ist |
| * |
| * @param node Zu überprüfender Knoten |
| */ |
| @Check |
| def checkAbstractNode(Node node){ |
| if(node.getNodetype().isAbstract()&&(node.actiontype=="create")){ |
| error("Node of abstract type cannot be created.'", node, Henshin_textPackage::eINSTANCE.node_Nodetype) |
| } |
| } |
| |
| /** |
| * Fehler wenn mehrere set-Attribute für ein Match-Attribut dfiniert wurden |
| * |
| * @param node Knoten dessen Attribute überprüft werden |
| */ |
| @Check |
| def checkSetAttribute(Node node){ |
| if((node.actiontype=="preserve")||(node.actiontype==null)){ |
| for(attribute:node.attribute){ |
| if(attribute.update!=null){ |
| for(checkAttribute:node.attribute){ |
| if((checkAttribute!=attribute)&&(attribute.name==checkAttribute.name)&&((checkAttribute.update!=null)||(checkAttribute.actiontype=="create"))){ |
| error("Duplicate update.'", attribute, Henshin_textPackage::eINSTANCE.attribute_Update) |
| error("Duplicate update.'", checkAttribute, Henshin_textPackage::eINSTANCE.attribute_Actiontype) |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * Fehler wenn für ein set-Attribut kein Match-Attribut definiert wurde |
| * |
| * @param node Knotendessen Attribute überprüft werden |
| */ |
| @Check |
| def checkSetandMatchAttribute(Node node){ |
| if((node.actiontype=="preserve")||(node.actiontype==null)){ |
| for(attribute:node.attribute){ |
| if(attribute.update!=null){ |
| var matchExist=false |
| for(checkAttribute:node.attribute){ |
| if((checkAttribute!=attribute)&&(attribute.name==checkAttribute.name)&&((checkAttribute.actiontype=="preserve")||((checkAttribute.actiontype==null)&&((node.actiontype=="preserve")||(node.actiontype==null))))){ |
| matchExist=true |
| } |
| } |
| if(!matchExist){ |
| error("Preserve-attribute "+attribute.name.name+" needed.'", attribute, Henshin_textPackage::eINSTANCE.attribute_Update) |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * Fehler wenn der ActionType eines Attributes nicht zu dem ActionType des Knoten passt |
| * |
| * @param node Zu überprüfender Knoten |
| */ |
| @Check |
| def checkNodeAttributeAction(Node node){ |
| if(node.actiontype=="create"){ |
| for(attribute:node.attribute){ |
| if(((attribute.actiontype=="preserve")&&(attribute.update==null))||(attribute.actiontype=="delete")|| |
| (attribute.actiontype=="forbid")||(attribute.actiontype=="require") |
| ){ |
| error(attribute.actiontype+"-attributes are not allowed in "+node.actiontype+"-nodes.'", attribute, Henshin_textPackage::eINSTANCE.attribute_Actiontype) |
| } |
| if(attribute.update!=null){ |
| error("set-attributes are not allowed in "+node.actiontype+"-nodes. '", attribute, Henshin_textPackage::eINSTANCE.attribute_Update) |
| } |
| } |
| }else if(node.actiontype=="delete"){ |
| for(attribute:node.attribute){ |
| if(((attribute.actiontype=="preserve")&&(attribute.update==null))||(attribute.actiontype=="create")){ |
| error(attribute.actiontype+"-attributes are not allowed in "+node.actiontype+"-nodes.'", attribute, Henshin_textPackage::eINSTANCE.attribute_Actiontype) |
| } |
| if(attribute.update!=null){ |
| error("set-attributes are not allowed in "+node.actiontype+"-nodes.'", attribute, Henshin_textPackage::eINSTANCE.attribute_Update) |
| } |
| } |
| }else if(node.actiontype=="forbid"){ |
| for(attribute:node.attribute){ |
| if(((attribute.actiontype=="preserve")&&(attribute.update==null))||(attribute.actiontype=="delete")||(attribute.actiontype=="create")||(attribute.actiontype=="require")){ |
| error(attribute.actiontype+"-attributes are not allowed in "+node.actiontype+"-nodes.'", attribute, Henshin_textPackage::eINSTANCE.attribute_Actiontype) |
| } |
| if(attribute.update!=null){ |
| error("set-attributes are not allowed in "+node.actiontype+"-nodes.'", attribute, Henshin_textPackage::eINSTANCE.attribute_Update) |
| } |
| } |
| }else if(node.actiontype=="require"){ |
| for(attribute:node.attribute){ |
| if(((attribute.actiontype=="preserve")&&(attribute.update==null))||(attribute.actiontype=="delete")||(attribute.actiontype=="create")||(attribute.actiontype=="forbid")){ |
| error(attribute.actiontype+"-attributes are not allowed in "+node.actiontype+"-nodes.'", attribute, Henshin_textPackage::eINSTANCE.attribute_Actiontype) |
| } |
| if(attribute.update!=null){ |
| error("set-attributes are not allowed in "+node.actiontype+"-nodes.'", attribute, Henshin_textPackage::eINSTANCE.attribute_Update) |
| } |
| } |
| } |
| } |
| |
| /** |
| * Fehler wenn der ActionType der Kante nicht zu dem ActionType der Knoten passt |
| * |
| * @param edge Zu überprüfende Kante |
| * |
| */ |
| @Check |
| def checkNodeEdgeAction(Edge edge){ |
| var Node source |
| var Node target |
| if(edge.source instanceof Node){ |
| source=(edge.source as Node) |
| }else{ |
| try{ |
| source=(edge.source as MultiRuleReuseNode).name |
| }catch(ClassCastException e){ |
| target=null |
| } |
| } |
| if(edge.target instanceof Node){ |
| target=(edge.target as Node) |
| }else{ |
| try{ |
| target=(edge.target as MultiRuleReuseNode).name |
| }catch(ClassCastException e){ |
| target=null |
| } |
| } |
| if(target!=null&&source!=null){ |
| var edgetype=edge.actiontype |
| if(edgetype==null){ |
| edgetype="preserve" |
| } |
| var sourcetype=source.actiontype |
| if(sourcetype==null){ |
| sourcetype="preserve" |
| } |
| var tagettype=target.actiontype |
| if(tagettype==null){ |
| tagettype="preserve" |
| } |
| if((edge.actiontype=="preserve")||(edge.actiontype==null)){ |
| if(((source.actiontype=="preserve")||(source.actiontype==null))&&((target.actiontype!="preserve")&&(target.actiontype!=null))){ |
| error("A "+edgetype+"-edge is not allowed between a "+sourcetype+"-node and a "+tagettype+"-node.'", edge, Henshin_textPackage::eINSTANCE.edge_Actiontype) |
| }else if((source.actiontype!="preserve")&&(source.actiontype!=null)){ |
| error("A "+edgetype+"-edge is not allowed between a "+sourcetype+"-node and a "+tagettype+"-node.'", edge, Henshin_textPackage::eINSTANCE.edge_Actiontype) |
| } |
| }else if(edge.actiontype=="create"){ |
| if(((source.actiontype==null)||(source.actiontype=="preserve")||(source.actiontype=="create"))&& |
| ((target.actiontype!=null)&&(target.actiontype!="preserve")&&(target.actiontype!="create")) |
| ){ |
| error("A "+edgetype+"-edge is not allowed between a "+sourcetype+"-node and a "+tagettype+"-node.'", edge, Henshin_textPackage::eINSTANCE.edge_Actiontype) |
| }else if((source.actiontype!=null)&&(source.actiontype!="preserve")&&(source.actiontype!="create")){ |
| error("A "+edgetype+"-edge is not allowed between a "+sourcetype+"-node and a "+tagettype+"-node.'", edge, Henshin_textPackage::eINSTANCE.edge_Actiontype) |
| } |
| }else if(edge.actiontype=="delete"){ |
| if(((source.actiontype==null)||(source.actiontype=="preserve")||(source.actiontype=="delete"))&& |
| ((target.actiontype!=null)&&(target.actiontype!="preserve")&&(target.actiontype!="delete")) |
| ){ |
| error("A "+edgetype+"-edge is not allowed between a "+sourcetype+"-node and a "+tagettype+"-node.'", edge, Henshin_textPackage::eINSTANCE.edge_Actiontype) |
| }else if((source.actiontype!=null)&&(source.actiontype!="preserve")&&(source.actiontype!="delete")){ |
| error("A "+edgetype+"-edge is not allowed between a "+sourcetype+"-node and a "+tagettype+"-node.'", edge, Henshin_textPackage::eINSTANCE.edge_Actiontype) |
| } |
| }else if(edge.actiontype=="forbid"){ |
| if(((source.actiontype==null)||(source.actiontype=="preserve")||(source.actiontype=="delete")||(source.actiontype=="forbid"))&& |
| ((target.actiontype=="create")||(target.actiontype=="require")) |
| ){ |
| error("A "+edgetype+"-edge is not allowed between a "+sourcetype+"-node and a "+tagettype+"-node.'", edge, Henshin_textPackage::eINSTANCE.edge_Actiontype) |
| }else if((source.actiontype=="create")||(source.actiontype=="require")){ |
| error("A "+edgetype+"-edge is not allowed between a "+sourcetype+"-node and a "+tagettype+"-node.'", edge, Henshin_textPackage::eINSTANCE.edge_Actiontype) |
| } |
| }else if(edge.actiontype=="require"){ |
| if(((source.actiontype==null)||(source.actiontype=="preserve")||(source.actiontype=="delete")||(source.actiontype=="require"))&& |
| ((target.actiontype=="create")||(target.actiontype=="forbid")) |
| ){ |
| error("A "+edgetype+"-edge is not allowed between a "+sourcetype+"-node and a "+tagettype+"-node.'", edge, Henshin_textPackage::eINSTANCE.edge_Actiontype) |
| }else if((source.actiontype=="create")||(source.actiontype=="forbid")){ |
| error("A "+edgetype+"-edge is not allowed between a "+sourcetype+"-node and a "+tagettype+"-node.'", edge, Henshin_textPackage::eINSTANCE.edge_Actiontype) |
| } |
| } |
| } |
| } |
| |
| /** |
| * Fehler wenn nicht genau ein Graph in einer Regel definiert wurde |
| * |
| * @param rule Zu überprüfende Regel |
| */ |
| @Check |
| def checkCountGraph(Rule rule){ |
| var iterableOfGraphImpl = Iterables.filter(rule.ruleElements,typeof(GraphImpl)) |
| if(iterableOfGraphImpl.size>1){ |
| for(graph:iterableOfGraphImpl){ |
| error("Multiple graphs in rule "+rule.getName+".'", graph, Henshin_textPackage.Literals.GRAPH__GRAPH_ELEMENTS) |
| } |
| }else if(iterableOfGraphImpl.size==0){ |
| error("No graph in rule "+rule.getName+".'", rule, Henshin_textPackage::eINSTANCE.rule_RuleElements) |
| } |
| } |
| |
| /** |
| * Fehler wenn mehr als ein CheckDangling-Element in einer Regel definiert wurde |
| * |
| * @param rule Zu überprüfende Regel |
| */ |
| @Check |
| def checkCountCheckDangling(Rule rule){ |
| var iterableOfCheckDanglingImpl = Iterables.filter(rule.ruleElements,typeof(CheckDanglingImpl)) |
| if(iterableOfCheckDanglingImpl.size>1){ |
| for(checkDangling:iterableOfCheckDanglingImpl){ |
| error("CheckDangling can only be used once.'", checkDangling, Henshin_textPackage.Literals.CHECK_DANGLING__CHECK_DANGLING) |
| } |
| } |
| } |
| |
| |
| /** |
| * Fehler wenn mehr als ein InjectiveMatching-Element in einer Regel definiert wurde |
| * |
| * @param rule Zu überprüfende Regel |
| */ |
| @Check |
| def checkCountInjectiveMatching(Rule rule){ |
| var iterableOfInjectiveMatchingImpl = Iterables.filter(rule.ruleElements,typeof(InjectiveMatchingImpl)) |
| if(iterableOfInjectiveMatchingImpl.size>1){ |
| for(injectiveMatching:iterableOfInjectiveMatchingImpl){ |
| error("InjectiveMatching can only be used once.'", injectiveMatching, Henshin_textPackage.Literals.INJECTIVE_MATCHING__INJECTIVE_MATCHING) |
| } |
| } |
| } |
| |
| |
| /** |
| * Fehler wenn mehr als ein Conditions-Element in einer Regel definiert wurde |
| * |
| * @param rule Zu überprüfende Regel |
| */ |
| @Check |
| def checkCountCondition(Rule rule){ |
| var iterableOfConditionsImpl = Iterables.filter(rule.ruleElements,typeof(ConditionsImpl)) |
| if(iterableOfConditionsImpl.size>1){ |
| for(conditions:iterableOfConditionsImpl){ |
| error("Conditions can only be used once.'", conditions, Henshin_textPackage.Literals.CONDITIONS__ATTRIBUTE_CONDITIONS) |
| } |
| } |
| } |
| |
| /** |
| * Fehler wenn das in eine Regel importierte Java-Package nicht existiert |
| * |
| * @param rule Zu überprüfende Regel |
| */ |
| @Check |
| def checkJavaImport(Rule rule){ |
| var iterableOfJavaImportImpl= Iterables.filter(rule.ruleElements,typeof(JavaImportImpl)) |
| for(javaImport:iterableOfJavaImportImpl){ |
| if(Package.getPackage(javaImport.packagename)==null){ |
| error("Package "+javaImport.packagename+" doesn't exist.'",javaImport, Henshin_textPackage.Literals.JAVA_IMPORT__PACKAGENAME ) |
| } |
| } |
| } |
| |
| |
| /** |
| * Warnt wenn Java-Packages mehrfach in Regel importiert wurden |
| * |
| * @param rule Zu überprüfende Regel |
| */ |
| @Check |
| def checkMultiJavaImport(Rule rule){ |
| var iterableOfJavaImportImpl= Iterables.filter(rule.ruleElements,typeof(JavaImportImpl)) |
| for(var i=0;i<iterableOfJavaImportImpl.size;i++){ |
| var javaImport=iterableOfJavaImportImpl.get(i) |
| for(var j=i+1;j<iterableOfJavaImportImpl.size;j++){ |
| if(iterableOfJavaImportImpl.get(j).packagename==javaImport.packagename){ |
| warning("Package "+javaImport.packagename+" is already imported.'",iterableOfJavaImportImpl.get(j), Henshin_textPackage.Literals.JAVA_IMPORT__PACKAGENAME ) |
| } |
| } |
| } |
| } |
| |
| |
| //-------------------------------------------------------------------------- |
| //MultiRule |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * Fehler wenn das in eine MultiRegel importierte Java-Package nicht existiert |
| * |
| * @param rule Zu überprüfende MultiRegel |
| */ |
| @Check |
| def checkJavaImport(MultiRule rule){ |
| var iterableOfJavaImportImpl= Iterables.filter(rule.multiruleElements,typeof(JavaImportImpl)) |
| for(javaImport:iterableOfJavaImportImpl){ |
| if(Package.getPackage(javaImport.packagename)==null){ |
| error("Package "+javaImport.packagename+" doesn't exist.'",javaImport, Henshin_textPackage.Literals.JAVA_IMPORT__PACKAGENAME ) |
| } |
| } |
| } |
| |
| /** |
| * Warnt wenn Java-Packages mehrfach in MultiRegel importiert wurden |
| * |
| * @param rule Zu überprüfende MultiRegel |
| */ |
| @Check |
| def checkMultiJavaImport(MultiRule rule){ |
| var iterableOfJavaImportImpl= Iterables.filter(rule.multiruleElements,typeof(JavaImportImpl)) |
| for(var i=0;i<iterableOfJavaImportImpl.size;i++){ |
| var javaImport=iterableOfJavaImportImpl.get(i) |
| for(var j=i+1;j<iterableOfJavaImportImpl.size;j++){ |
| if(iterableOfJavaImportImpl.get(j).packagename==javaImport.packagename){ |
| warning("Package "+javaImport.packagename+" is already imported.'",iterableOfJavaImportImpl.get(j), Henshin_textPackage.Literals.JAVA_IMPORT__PACKAGENAME ) |
| } |
| } |
| } |
| } |
| |
| |
| /** |
| * Fehler wenn mehr als ein Conditions-Element in einer MultiRegel definiert wurde |
| * |
| * @param rule Zu überprüfende MultiRegel |
| */ |
| @Check |
| def checkCountCondition(MultiRule rule){ |
| var iterableOfConditionsImpl = Iterables.filter(rule.multiruleElements,typeof(ConditionsImpl)) |
| if(iterableOfConditionsImpl.size>1){ |
| for(conditions:iterableOfConditionsImpl){ |
| error("Conditions can only be used once.'", conditions, Henshin_textPackage.Literals.CONDITIONS__ATTRIBUTE_CONDITIONS) |
| } |
| } |
| } |
| |
| |
| |
| /** |
| * Fehler wenn mehr als ein InjectiveMatching-Element in einer MultiRegel definiert wurde |
| * |
| * @param rule Zu überprüfende MultiRegel |
| */ |
| @Check |
| def checkCountInjectiveMatching(MultiRule rule){ |
| var iterableOfInjectiveMatchingImpl = Iterables.filter(rule.multiruleElements,typeof(InjectiveMatchingImpl)) |
| if(iterableOfInjectiveMatchingImpl.size>1){ |
| for(injectiveMatching:iterableOfInjectiveMatchingImpl){ |
| error("InjectiveMatching can only be used once.'", injectiveMatching, Henshin_textPackage.Literals.INJECTIVE_MATCHING__INJECTIVE_MATCHING) |
| } |
| } |
| } |
| |
| |
| /** |
| * Fehler wenn mehr als ein CheckDangling-Element in einer MultiRegel definiert wurde |
| * |
| * @param rule Zu überprüfende MultiRegel |
| */ |
| @Check |
| def checkCountCheckDangling(MultiRule rule){ |
| var iterableOfCheckDanglingImpl = Iterables.filter(rule.multiruleElements,typeof(CheckDanglingImpl)) |
| if(iterableOfCheckDanglingImpl.size>1){ |
| for(checkDangling:iterableOfCheckDanglingImpl){ |
| error("CheckDangling can only be used once.'", checkDangling, Henshin_textPackage.Literals.CHECK_DANGLING__CHECK_DANGLING) |
| } |
| } |
| } |
| |
| |
| /** |
| * Fehler wenn mehr als ein Graph in einer MultiRegel definiert wurde |
| * |
| * @param rule Zu überprüfende MultiRegel |
| */ |
| @Check |
| def checkCountGraph(MultiRule rule){ |
| var iterableOfGraphImpl = Iterables.filter(rule.multiruleElements,typeof(GraphImpl)) |
| if(iterableOfGraphImpl.size>1){ |
| for(graph:iterableOfGraphImpl){ |
| error("Multiple graphs in rule "+rule.getName+".'", graph, Henshin_textPackage.Literals.GRAPH__GRAPH_ELEMENTS) |
| } |
| } |
| } |
| |
| /** |
| * Fehler wenn ein Attribut in einem reuse-Knoten definiert wurde das so nicht im ecore-Modell existiert |
| * |
| * @param node Zu überprüfender reuse-Knoten |
| */ |
| @Check |
| def checkNodeAttribute(MultiRuleReuseNode node){ |
| for(attribute:node.attribute){ |
| var superTypeAttribute=false |
| if(!node.name.nodetype.EAttributes.contains(attribute.name)){ |
| for(supertype:node.name.nodetype.EAllSuperTypes){ |
| if(supertype.EAttributes.contains(attribute.name)){ |
| superTypeAttribute=true |
| } |
| } |
| if(!superTypeAttribute){ |
| error(node.name.nodetype.name+" has no attribute '"+attribute.name.name+"'.'",attribute, Henshin_textPackage::eINSTANCE.attribute_Name) |
| } |
| } |
| } |
| } |
| |
| /** |
| * Fehler wenn in einem reuse-Knoten das selbe Attribut mehrfach definiert wird |
| * |
| * @param node Zu überprüfender reuse-Knoten |
| */ |
| @Check |
| def checkattributeOnlyOnce(MultiRuleReuseNode node){ |
| for(var i=0;i<node.attribute.size;i++){ |
| var attribute=node.attribute.get(i) |
| for(var j=i+1;j<node.attribute.size;j++){ |
| if((attribute.name==node.attribute.get(j).name)&&(attribute.update==node.attribute.get(j).update)){ |
| error("'"+attribute.name.name+"' can only be used once.'",node.attribute.get(j), Henshin_textPackage::eINSTANCE.attribute_Name) |
| } |
| } |
| } |
| } |
| |
| /** |
| * Fehler wenn ein forbid- oder require-Knoten in einer Kanten einer MultiRegel wiederverwendet werden soll |
| * |
| * @param conNodes Liste von forbid- und require-Knoten von darüberliegenden Graphen |
| * @param graph Zu überprüfender Graph |
| */ |
| private def void checkEdgesInMultiRuleRekursive(List<Node> conNodes,Graph graph){ |
| for(edges:Iterables.filter(graph.graphElements,typeof(Edges))){ |
| for(edge:edges.edges){ |
| var Node testNode |
| if(edge.source!=null){ |
| if(edge.source instanceof Node){ |
| testNode=(edge.source as Node) |
| }else{ |
| try{ |
| testNode=(edge.source as MultiRuleReuseNode).name |
| }catch(ClassCastException e){ |
| testNode=null |
| } |
| } |
| } |
| for(conNode:conNodes){ |
| if(conNode.name==testNode.name){ |
| error(testNode.actiontype+"-nodes are not allowed to be reused in edges in MultiRuleReuseNodes.'",edge, Henshin_textPackage::eINSTANCE.edge_Source) |
| } |
| } |
| if(edge.target!=null){ |
| if(edge.target instanceof Node){ |
| testNode=(edge.target as Node) |
| }else{ |
| testNode=(edge.target as MultiRuleReuseNode).name |
| } |
| } |
| for(conNode:conNodes){ |
| if(conNode.name==testNode.name){ |
| error(testNode.actiontype+"-nodes are not allowed to be reused in edges in MultiRuleReuseNodes.'",edge, Henshin_textPackage::eINSTANCE.edge_Target) |
| } |
| } |
| } |
| } |
| var multiRules=Iterables.filter(graph.graphElements,typeof(MultiRule)) |
| if(multiRules.size>0){ |
| for(node:Iterables.filter(graph.graphElements,typeof(Node))){ |
| if((node.actiontype=="forbid")||(node.actiontype=="require")){ |
| conNodes.add(node) |
| } |
| } |
| for(multiRule:multiRules){ |
| checkEdgesInMultiRuleRekursive(conNodes,Iterables.filter(multiRule.multiruleElements,typeof(Graph)).get(0)) |
| } |
| } |
| } |
| |
| |
| /** |
| * Fehler wenn ein forbid- oder require-Knoten in einer Kanten einer MultiRegel wiederverwendet werden soll |
| * |
| * @paran rule Zu überprüfende Regel |
| */ |
| @Check |
| def checkEdgesInMultiRule(Rule rule){ |
| var graph=Iterables.filter(rule.ruleElements,typeof(Graph)) |
| if(graph.size>0){ |
| var List<Node> conNodes=new ArrayList<Node> |
| for(node:Iterables.filter(graph.get(0).graphElements,typeof(Node))){ |
| if((node.actiontype=="forbid")||(node.actiontype=="require")){ |
| conNodes.add(node) |
| } |
| } |
| for(multiRule:Iterables.filter(graph.get(0).graphElements,typeof(MultiRule))){ |
| if(Iterables.filter(multiRule.multiruleElements,typeof(Graph)).size>0){ |
| checkEdgesInMultiRuleRekursive(conNodes,Iterables.filter(multiRule.multiruleElements,typeof(Graph)).get(0)) |
| } |
| } |
| } |
| } |
| |
| /** |
| * Fehler wenn ein Knoten mit ActionType require oder forbid reused wird |
| * |
| * @parameter multiReuseNode Zu überprüfender reuse-Node |
| */ |
| @Check |
| def checkMultiRuleReuseNodeActionType(MultiRuleReuseNode multiReuseNode){ |
| if((multiReuseNode.name.actiontype=="require")||(multiReuseNode.name.actiontype=="forbid")){ |
| error(multiReuseNode.name.actiontype+"-Node '"+multiReuseNode.name.name+"' is not allowed in MultiRules.'",multiReuseNode, Henshin_textPackage::eINSTANCE.multiRuleReuseNode_Name) |
| } |
| } |
| |
| |
| /** |
| * Fehler wenn in einem reuse-Node ein set-Attribut definiert wurde |
| * |
| * @param reuseNode Zu überprüfender reuse-Node |
| */ |
| @Check |
| def checkMultiRuleReuseNodAttributeSet(MultiRuleReuseNode reuseNode){ |
| for(attribute:reuseNode.attribute){ |
| if(attribute.update!=null){ |
| error("Set-attributes are not allowed in MultiRuleReuseNodes.'", attribute, Henshin_textPackage::eINSTANCE.attribute_Actiontype) |
| } |
| } |
| } |
| |
| |
| /** |
| * Fehler wenn der ActionType der Attribute eines reuse-Nodes nicht zum ActionType des orginal Knoten passen |
| * |
| * @param reuseNode Zu überprüfender reuse-Node |
| */ |
| @Check |
| def checkMultiRuleReuseNodAttributeAction(MultiRuleReuseNode reuseNode){ |
| var reuseNodeType=reuseNode.name.actiontype |
| if(reuseNodeType==null){ |
| reuseNodeType="preserve" |
| } |
| if(reuseNode.name.actiontype=="create"){ |
| for(attribute:reuseNode.attribute){ |
| if((attribute.actiontype!="create")&&(attribute.actiontype!=null)){ |
| error(attribute.actiontype+"-attributes are not allowed in "+reuseNodeType+"-reuseNodes. '", attribute, Henshin_textPackage::eINSTANCE.attribute_Actiontype) |
| } |
| } |
| }else if(reuseNode.name.actiontype=="delete"){ |
| for(attribute:reuseNode.attribute){ |
| if((attribute.actiontype!="delete")&&(attribute.actiontype!=null)){ |
| error(attribute.actiontype+"-attributes are not allowed in "+reuseNodeType+"-reuseNodes. '", attribute, Henshin_textPackage::eINSTANCE.attribute_Actiontype) |
| } |
| } |
| }else if((reuseNode.name.actiontype=="preserve")||(reuseNode.name.actiontype==null)){ |
| for(attribute:reuseNode.attribute){ |
| if((attribute.actiontype=="forbid")||(attribute.actiontype=="require")){ |
| error(attribute.actiontype+"-attributes are not allowed in "+reuseNodeType+"-reuseNodes. '", attribute, Henshin_textPackage::eINSTANCE.attribute_Actiontype) |
| } |
| } |
| } |
| } |
| |
| |
| /** |
| * Fehler wenn ein Graph der nicht zu einer MultiRegel gehört einen Knoten reused |
| * |
| * @param rule Zu überprüfende Regel |
| */ |
| @Check |
| def checkRuleReuseNodes(Rule rule){ |
| var graph=Iterables.filter(rule.ruleElements,typeof(Graph)) |
| if(graph.size>0){ |
| var reuseNodes=Iterables.filter(graph.get(0).graphElements,typeof(MultiRuleReuseNode)) |
| for(node:reuseNodes){ |
| error("Reuse-Nodes are only allowed in multiRules.''", node, Henshin_textPackage::eINSTANCE.multiRuleReuseNode_Name) |
| } |
| } |
| } |
| |
| |
| /** |
| * Fehler wenn ein Knoten wie ein MultiRuleReuseNode benannt wurde |
| * |
| * @param graph Zu überprüfender Graph |
| */ |
| @Check |
| def checkMultiRuleGraphNodes(Graph graph){ |
| for(reuse:Iterables.filter(graph.graphElements,typeof(MultiRuleReuseNode))){ |
| for(node:Iterables.filter( graph.graphElements,typeof(Node))){ |
| if(reuse.name.name==node.name){ |
| error("Graph cannot reuse its own nodes.'", reuse, Henshin_textPackage::eINSTANCE.multiRuleReuseNode_Name) |
| } |
| } |
| } |
| } |
| |
| /** |
| * Fehler wenn ein Knoten mehrfach reused wird in einem Graphen |
| * |
| * @param graph Zu überprüfender Graph |
| */ |
| @Check |
| def checkGraphMultiReuse(Graph graph){ |
| var reuseNodes=Iterables.filter(graph.graphElements,typeof(MultiRuleReuseNode)) |
| for(var i=0;i<reuseNodes.size;i++){ |
| for(var j=i+1;j<reuseNodes.size;j++){ |
| if(reuseNodes.get(i).name.name==reuseNodes.get(j).name.name){ |
| error(reuseNodes.get(j).name.name+" is already reused.'",reuseNodes.get(j), Henshin_textPackage::eINSTANCE.multiRuleReuseNode_Name) |
| } |
| } |
| } |
| } |
| |
| |
| /** |
| * Fehler wenn ein Graph einer MultiRegel einen Knoten eines darüberliegenden Graphen überschreibt |
| * |
| * @param graph Graph der rekursiv durchsucht wird |
| */ |
| @Check |
| def checkOverrideNodeNamesinMultiRuleGraph(Graph graph){ |
| var multiRules=Iterables.filter(graph.graphElements,typeof(MultiRule)) |
| var List<Node> topNodes=new ArrayList(); |
| for(rule:multiRules){ |
| for(multiGraph:Iterables.filter(rule.multiruleElements,typeof(Graph))){ |
| for(multiNode:Iterables.filter(multiGraph.graphElements,typeof(Node))){ |
| for(node:Iterables.filter(graph.graphElements,typeof(Node))){ |
| topNodes.add(node) |
| if(multiNode.name==node.name){ |
| error("Duplicate Node '"+multiNode.name+"'.'",multiNode, Henshin_textPackage::eINSTANCE.node_Nodetype) |
| } |
| } |
| } |
| if(Iterables.filter(multiGraph.graphElements,typeof(MultiRule)).size>0){ |
| checkRekursiveOverrideNodeNamesinMultiRuleGraph(topNodes,multiGraph) |
| } |
| } |
| } |
| } |
| |
| |
| /** |
| * Fehler wenn ein Graph einer MultiRegel einen Knoten eines darüberliegenden Graphen überschreibt |
| * |
| * @param topNodes Liste der darüberliegenden Graphknoten |
| * @param graph Zu überprüfender Graph |
| * |
| */ |
| private def void checkRekursiveOverrideNodeNamesinMultiRuleGraph(List<Node> topNodes,Graph graph){ |
| var multiRules=Iterables.filter(graph.graphElements,typeof(MultiRule)) |
| for(rule:multiRules){ |
| for(multiGraph:Iterables.filter(rule.multiruleElements,typeof(Graph))){ |
| for(multiNode:Iterables.filter(multiGraph.graphElements,typeof(Node))){ |
| for(node:topNodes){ |
| if(multiNode.name==node.name){ |
| error("Duplicate Node '"+multiNode.name+"'.'",multiNode, Henshin_textPackage::eINSTANCE.node_Nodetype) |
| } |
| } |
| for(node:Iterables.filter(graph.graphElements,typeof(Node))){ |
| topNodes.add(node) |
| if(multiNode.name==node.name){ |
| error("Duplicate Node '"+multiNode.name+"'.'",multiNode, Henshin_textPackage::eINSTANCE.node_Nodetype) |
| } |
| } |
| } |
| if(Iterables.filter(multiGraph.graphElements,typeof(MultiRule)).size>0){ |
| checkRekursiveOverrideNodeNamesinMultiRuleGraph(topNodes,multiGraph) |
| } |
| } |
| } |
| } |
| |
| //-------------------------------------------------------------------------- |
| //Formula |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * Fehler wenn eine Kante in einem ConditionGraph definiert wurde, die nicht im ecore-Modell existiert |
| * |
| * @param edge Zu überprüfende Kante |
| */ |
| @Check |
| def ckeckExistingEdge(ConditionEdge edge){ |
| var EClass sourceType |
| var EClass targetType |
| if(edge.source instanceof Node){ |
| sourceType=(edge.source as Node).nodetype |
| }else{ |
| try{ |
| sourceType=(edge.source as ConditionNode).type |
| }catch(ClassCastException e){ |
| sourceType=null |
| } |
| } |
| if(edge.target instanceof Node){ |
| targetType=(edge.target as Node).nodetype |
| }else{ |
| try{ |
| targetType=(edge.target as ConditionNode).type |
| }catch(ClassCastException e){ |
| targetType=null |
| } |
| } |
| if((sourceType!=null)&&(targetType!=null)){ |
| var wrongType=true |
| var EClass referenceType |
| for(reference:sourceType.EAllReferences){ |
| if(edge.type.name==reference.name){ |
| wrongType=false |
| referenceType=reference.EReferenceType |
| } |
| } |
| if(wrongType){ |
| error("Edgetype "+edge.type.name+" does not exist.'",edge, Henshin_textPackage::eINSTANCE.conditionEdge_Type) |
| } |
| if(referenceType!=targetType){ |
| error("Edge "+sourceType.name+"->"+targetType.name+":"+edge.type.name+" does not exist.'",edge, Henshin_textPackage::eINSTANCE.conditionEdge_Type) |
| } |
| } |
| } |
| |
| /** |
| * Fehler wenn ein Attribut in einem Knoten eines ConditionGraphen definiert wurde das so nicht im ecore-Modell existiert |
| * |
| * @param node Zu überprüfender Knoten eines ConditionGraphen |
| */ |
| @Check |
| def checkNodeAttribute(ConditionNode node){ |
| for(attribute:node.attribute){ |
| var superTypeAttribute=false |
| if(!node.type.EAttributes.contains(attribute.name)){ |
| for(supertype:node.type.EAllSuperTypes){ |
| if(supertype.EAttributes.contains(attribute.name)){ |
| superTypeAttribute=true |
| } |
| } |
| if(!superTypeAttribute){ |
| error(node.type.name+" has no attribute '"+attribute.name.name+"'.'",attribute, Henshin_textPackage::eINSTANCE.match_Name) |
| } |
| } |
| } |
| } |
| |
| /** |
| * Fehler wenn ein Knotentyp verwendet wurde, der nicht importiert wurde |
| * |
| * @param node Zu überprüfender Knoten |
| */ |
| @Check |
| def checkConditionNodeType(ConditionNode node){ |
| var isImported=false |
| for(ePackage:getEPackageImports(node)){ |
| if(ePackage.ref.EClassifiers.contains(node.type)){ |
| isImported=true |
| } |
| } |
| if(!isImported){ |
| error("Nodetype "+node.type.name+" is not imported.'",node, Henshin_textPackage::eINSTANCE.conditionNode_Type) |
| } |
| } |
| |
| /** |
| * Fehler wenn ein Attribut in einem reuse-Knoten eines ConditionGraphen definiert wurde das so nicht im ecore-Modell existiert |
| * |
| * @param node Zu überprüfender reuse-Knoten eines ConditionGraphen |
| */ |
| @Check |
| def checkNodeAttribute(ConditionReuseNode node){ |
| var EClass nodeType |
| if(node.name instanceof Node){ |
| nodeType=(node.name as Node).nodetype |
| }else{ |
| try { |
| nodeType=(node.name as ConditionNode).type |
| }catch(ClassCastException e){ |
| nodeType=null |
| } |
| } |
| if(nodeType!=null){ |
| for(attribute:node.attribute){ |
| var superTypeAttribute=false |
| if(!nodeType.EAttributes.contains(attribute.name)){ |
| for(supertype:nodeType.EAllSuperTypes){ |
| if(supertype.EAttributes.contains(attribute.name)){ |
| superTypeAttribute=true |
| } |
| } |
| if(!superTypeAttribute){ |
| error(nodeType.name+" has no attribute '"+attribute.name.name+"'.'",attribute, Henshin_textPackage::eINSTANCE.match_Name) |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * Fehler wenn in einem Knoten eines ConditionGraphen das selbe Attribut mehrfach definiert wird |
| * |
| * @param node Zu überprüfender Knoten |
| */ |
| @Check |
| def checkattributeOnlyOnce(ConditionNode node){ |
| for(var i=0;i<node.attribute.size;i++){ |
| var match=node.attribute.get(i) |
| for(var j=i+1;j<node.attribute.size;j++){ |
| if((match.name==node.attribute.get(j).name)){ |
| error("'"+match.name.name+"' can only be used once.'",node.attribute.get(j), Henshin_textPackage::eINSTANCE.match_Name) |
| } |
| } |
| } |
| } |
| |
| /** |
| * Fehler wenn in einem reuse-Knoten eines ConditionGraphen das selbe Attribut mehrfach definiert wird |
| * |
| * @param node Zu überprüfender Knoten |
| */ |
| @Check |
| def checkattributeOnlyOnce(ConditionReuseNode node){ |
| for(var i=0;i<node.attribute.size;i++){ |
| var match=node.attribute.get(i) |
| for(var j=i+1;j<node.attribute.size;j++){ |
| if((match.name==node.attribute.get(j).name)){ |
| error("'"+match.name.name+"' can only be used once.'",node.attribute.get(j), Henshin_textPackage::eINSTANCE.match_Name) |
| } |
| } |
| } |
| } |
| |
| /** |
| * Fehler wenn ein Knoten in einem ConditionGraphen reused wird der nicht zur LHS gehört |
| * |
| *@param conReuseNode Zu überprüfender reuse-Node |
| */ |
| @Check |
| def checkConditionReuseNodeInLHS(ConditionReuseNode conReuseNode){ |
| if(conReuseNode.name instanceof Node){ |
| if(((conReuseNode.name as Node).actiontype!=null)&&((conReuseNode.name as Node).actiontype!="preserve")&&((conReuseNode.name as Node).actiontype!="delete")){ |
| error("Node '"+(conReuseNode.name as Node).name+"' is not in LHS.'",conReuseNode, Henshin_textPackage::eINSTANCE.conditionReuseNode_Name) |
| } |
| } |
| } |
| |
| |
| /** |
| * Fehler wenn ein Knoten in einer Kante im ConditionGraph wiederverwendet wird der nicht zur LHS gehört |
| * |
| * @param conEdge zu überprüfende Kante |
| */ |
| @Check |
| def checkConditionEdgeInLHS(ConditionEdge conEdge){ |
| if(conEdge.source instanceof Node){ |
| if(((conEdge.source as Node).actiontype!=null)&&((conEdge.source as Node).actiontype!="preserve")&&((conEdge.source as Node).actiontype!="delete")){ |
| error("Node '"+(conEdge.source as Node).name+"' is not in LHS.'",conEdge, Henshin_textPackage::eINSTANCE.conditionEdge_Source) |
| } |
| } |
| if(conEdge.target instanceof Node){ |
| if(((conEdge.target as Node).actiontype!=null)&&((conEdge.target as Node).actiontype!="preserve")&&((conEdge.target as Node).actiontype!="delete")){ |
| error("Node '"+(conEdge.target as Node).name+"' is not in LHS.'",conEdge, Henshin_textPackage::eINSTANCE.conditionEdge_Target) |
| } |
| } |
| } |
| |
| |
| /** |
| * Fehler wenn in einem Graph mehrere matchingFormula-Elemente definiert wurden |
| * |
| * @param graph Zu überprüfender Graph |
| */ |
| @Check |
| def matchingFormulaOnce(Graph graph){ |
| var formulaList=Iterables.filter(graph.graphElements,typeof(Formula)) |
| if(formulaList.size>1){ |
| for(formula:formulaList){ |
| error("matchingFormula can only use once.'",formula, Henshin_textPackage.Literals.FORMULA__FORMULA) |
| } |
| } |
| } |
| |
| |
| /** |
| * Fehler wenn in einem ConditionGraph mehrere matchingFormula-Elemente definiert wurden |
| * |
| * @param graph Zu überprüfender ConditionGraph |
| */ |
| @Check |
| def matchingFormulaOnce(ConditionGraph graph){ |
| var formulaList=Iterables.filter(graph.conditionGraphElements,typeof(Formula)) |
| if(formulaList.size>1){ |
| for(formula:formulaList){ |
| error("matchingFormula can only use once.'",formula, Henshin_textPackage.Literals.FORMULA__FORMULA) |
| } |
| } |
| } |
| |
| |
| /** |
| * Fehler wenn ein ConditionGraph einen Knoten eines darüberliegenden Graphen überschreibt |
| * |
| * @param graph Graph der rekursiv durchsucht wird |
| */ |
| @Check |
| def checkOverrideNodeNamesinConditionGraph(Graph graph){ |
| var formula=Iterables.filter(graph.graphElements,typeof(Formula)) |
| var List<ConditionNode> topConNodes=new ArrayList(); |
| if(formula.size>0){ |
| for(conGraph:formula.get(0).conditionGraphs){ |
| for(conNode:Iterables.filter(conGraph.conditionGraphElements,typeof(ConditionNode))){ |
| for(node:Iterables.filter(graph.graphElements,typeof(Node))){ |
| if(conNode.name==node.name){ |
| error("Duplicate Node '"+conNode.name+"'.'",conNode, Henshin_textPackage::eINSTANCE.conditionNode_Type) |
| } |
| } |
| topConNodes.add(conNode) |
| } |
| if(Iterables.filter(conGraph.conditionGraphElements,typeof(Formula)).size>0){ |
| checkRekursiveOverrideNodeNamesinConditionGraph(Iterables.filter(graph.graphElements,typeof(Node)),topConNodes,conGraph) |
| } |
| } |
| } |
| } |
| |
| |
| /** |
| * Fehler wenn ein ConditionGraph einen Knoten eines darüberliegenden Graphen überschreibt |
| * |
| * @param topNodes Liste der darüberliegenden Graphknoten |
| * @param topConNodes Liste der darüberliegenden ConditionGraphknoten |
| * @param graph Zu überprüfender Graph |
| * |
| */ |
| private def void checkRekursiveOverrideNodeNamesinConditionGraph(Iterable<Node> topNodes,List<ConditionNode> topConNodes,ConditionGraph graph){ |
| var formula=Iterables.filter(graph.conditionGraphElements,typeof(Formula)) |
| if(formula.size>0){ |
| for(conGraph:formula.get(0).conditionGraphs){ |
| for(conNode:Iterables.filter(conGraph.conditionGraphElements,typeof(ConditionNode))){ |
| for(node:Iterables.filter(graph.conditionGraphElements,typeof(ConditionNode))){ |
| if(conNode.name==node.name){ |
| error("Duplicate Node '"+conNode.name+"'.'",conNode, Henshin_textPackage::eINSTANCE.conditionNode_Type) |
| } |
| } |
| for(node:topNodes){ |
| if(conNode.name==node.name){ |
| error("Duplicate Node '"+conNode.name+"'.'",conNode, Henshin_textPackage::eINSTANCE.conditionNode_Type) |
| } |
| } |
| for(node:topConNodes){ |
| if(conNode.name==node.name){ |
| error("Duplicate Node '"+conNode.name+"'.'",conNode, Henshin_textPackage::eINSTANCE.conditionNode_Type) |
| } |
| } |
| topConNodes.add(conNode); |
| } |
| if(Iterables.filter(conGraph.conditionGraphElements,typeof(Formula)).size>0){ |
| checkRekursiveOverrideNodeNamesinConditionGraph(topNodes,topConNodes,conGraph) |
| } |
| } |
| } |
| } |
| |
| |
| /** |
| * Fehler wenn eine Formula auf einen übergeordneten ConditionGraph verweist |
| * |
| * @param formula Zu überprüfende Formula |
| */ |
| @Check |
| def checkFormulaConditionGraphLevel(Formula formula){ |
| var ArrayList<ConditionGraph> formulaGraphs=findDuplicate(formula.formula, new ArrayList<ConditionGraph>) |
| for(graph:formulaGraphs){ |
| if(!formula.conditionGraphs.contains(graph)){ |
| error("ConditionGraph '"+graph.name+"' does not exist.'",formula, Henshin_textPackage.Literals.FORMULA__FORMULA) |
| } |
| } |
| } |
| |
| /** |
| * Durchsucht Formula nach ihren ConditionGraphen |
| * |
| * @param formula Zu durchsuchende Formula |
| */ |
| @Check |
| def checkConditionFormula(Formula formula){ |
| var ArrayList<ConditionGraph> conditionGraphs=new ArrayList<ConditionGraph> |
| if(formula.formula instanceof ANDImpl){ |
| conditionGraphs.addAll(findDuplicate((formula.formula as ANDImpl).left,conditionGraphs)) |
| conditionGraphs.addAll(findDuplicate((formula.formula as ANDImpl).right,conditionGraphs)) |
| }else if(formula.formula instanceof ORorXORImpl){ |
| conditionGraphs.addAll(findDuplicate((formula.formula as ORorXORImpl).left,conditionGraphs)) |
| conditionGraphs.addAll(findDuplicate((formula.formula as ORorXORImpl).right,conditionGraphs)) |
| }else if(formula.formula instanceof NotImpl){ |
| conditionGraphs.addAll(findDuplicate((formula.formula as NotImpl).negation,conditionGraphs)) |
| } |
| } |
| |
| /** |
| * Fehler wenn ein ConditionGraph mehrfach verwendet wurde |
| * |
| * @param logic Zu untersuchender logischer Ausdruck |
| * @param conditionGraphs List der bereits gefundenen ConditionGraphen |
| * @return List der bereits gefundenen ConditionGraphen |
| * |
| */ |
| private def ArrayList<ConditionGraph> findDuplicate(Logic logic,ArrayList<ConditionGraph> conditionGraphs){ |
| if(logic instanceof ANDImpl){ |
| conditionGraphs.addAll(findDuplicate((logic as ANDImpl).left,conditionGraphs)) |
| conditionGraphs.addAll(findDuplicate((logic as ANDImpl).right,conditionGraphs)) |
| }else if(logic instanceof ORorXORImpl){ |
| conditionGraphs.addAll(findDuplicate((logic as ORorXORImpl).left,conditionGraphs)) |
| conditionGraphs.addAll(findDuplicate((logic as ORorXORImpl).right,conditionGraphs)) |
| }else if(logic instanceof NotImpl){ |
| conditionGraphs.addAll(findDuplicate((logic as NotImpl).negation,conditionGraphs)) |
| }else if(logic instanceof ConditionGraphRef){ |
| if(conditionGraphs.contains((logic as ConditionGraphRef).conditionGraphRef)){ |
| error("Duplicate ConditionGraph '"+(logic as ConditionGraphRef).conditionGraphRef.name+"'.'",(logic as ConditionGraphRef), Henshin_textPackage::eINSTANCE.conditionGraphRef_ConditionGraphRef) |
| }else{ |
| conditionGraphs.add((logic as ConditionGraphRef).conditionGraphRef) |
| } |
| } |
| return conditionGraphs |
| } |
| |
| /** |
| * Fehler wenn ein ConditionNode wie ein ConditionReuseNode benannt wurde |
| * |
| * @param graph Zu überprüfender ConditionGraph |
| */ |
| @Check |
| def checkConditionGraphReuseOwnNodes(ConditionGraph graph){ |
| for(reuse:Iterables.filter(graph.conditionGraphElements,typeof(ConditionReuseNode))){ |
| for(node:Iterables.filter( graph.conditionGraphElements,typeof(ConditionNode))){ |
| if(reuse.name.name==node.name){ |
| error("ConditionGraph cannot reuse its own nodes.'", reuse, Henshin_textPackage::eINSTANCE.conditionReuseNode_Name) |
| } |
| } |
| } |
| } |
| |
| |
| /** |
| * Fehler wenn ein Knoten mehrfach reused wird in einem Graphen |
| * |
| * @param graph Zu überprüfender ConditionGraph |
| */ |
| @Check |
| def checkConditionGraphMultiReuse(ConditionGraph graph){ |
| var reuseNodes=Iterables.filter(graph.conditionGraphElements,typeof(ConditionReuseNode)) |
| for(var i=0;i<reuseNodes.size;i++){ |
| for(var j=i+1;j<reuseNodes.size;j++){ |
| if(reuseNodes.get(i).name.name==reuseNodes.get(j).name.name){ |
| error(reuseNodes.get(j).name.name+" is already reused in ConditionGraph "+graph.name+".'",reuseNodes.get(j), Henshin_textPackage::eINSTANCE.conditionReuseNode_Name) |
| } |
| } |
| } |
| } |
| |
| |
| //-------------------------------------------------------------------------- |
| //Units |
| //-------------------------------------------------------------------------- |
| /** |
| * Fehler bei einer negativen Anzahl an Iterationen |
| * |
| * @param unit IteratedUnit die überprüft werden soll |
| * |
| */ |
| @Check |
| def checkIterationUnitIterationsNegative(IteratedUnit unit){ |
| if(unit.iterations instanceof NumberValue){ |
| if((unit.iterations as NumberValue).value.contains("-")){ |
| error("Negative values are not allowed.'",unit, Henshin_textPackage::eINSTANCE.iteratedUnit_Iterations) |
| } |
| }else if(unit.iterations instanceof IntegerValue){ |
| if((unit.iterations as IntegerValue).value.contains("-")){ |
| error("Negative values are not allowed.'",unit, Henshin_textPackage::eINSTANCE.iteratedUnit_Iterations) |
| } |
| } |
| } |
| |
| /** |
| * Fehler bei einem nicht-numerischen Parametertyp für Iterationen |
| * |
| * @param unit IteratedUnit die überprüft werden soll |
| * |
| */ |
| @Check |
| def checkIterationUnitIterationsType(IteratedUnit unit){ |
| if(unit.iterations!=null){ |
| if(typeFor(unit.iterations).toString!="number"){ |
| error("IteratedUnit expected number type, but was " +typeFor(unit.iterations)+".'",unit, Henshin_textPackage::eINSTANCE.iteratedUnit_Iterations) |
| } |
| } |
| } |
| |
| |
| /** |
| * Fehler wenn mehr als ein Strict-Element in einer Unit-Definition definiert wurde |
| * |
| * @param unit Zu überprüfende Unit |
| */ |
| @Check |
| def checkCountStrict(Unit unit){ |
| var iterableOfStrictImpl= Iterables.filter(unit.unitElements,typeof(StrictImpl)) |
| if(iterableOfStrictImpl.size>1){ |
| for(strict:iterableOfStrictImpl){ |
| error("Strict can only be used once.'", strict, Henshin_textPackage.Literals.STRICT__STRICT) |
| } |
| } |
| } |
| |
| /** |
| * Fehler wenn mehr als ein Strict-Element in einer SubSequenz definiert wurde |
| * |
| * @param unit Zu überprüfende SubSequenz |
| */ |
| @Check |
| def checkCountStrictSubSequence(UnitElement unit){ |
| var iterableOfStrictImpl= Iterables.filter(unit.subSequence,typeof(StrictImpl)) |
| if(iterableOfStrictImpl.size>1){ |
| for(strict:iterableOfStrictImpl){ |
| error("Strict can only be used once.'", strict, Henshin_textPackage.Literals.STRICT__STRICT) |
| } |
| } |
| } |
| |
| |
| /** |
| * Fehler wenn mehr als ein Strict-Element in einer IndependentUnit definiert wurde |
| * |
| * @param unit Zu überprüfende IndependentUnit |
| */ |
| @Check |
| def checkCountStrictIndependentUnit(IndependentUnit unit){ |
| for(e:unit.listOfLists){ |
| var iterableOfStrictImpl= Iterables.filter(e.subElements,typeof(StrictImpl)) |
| if(iterableOfStrictImpl.size>1){ |
| for(strict:iterableOfStrictImpl){ |
| error("Strict can only be used once.'", strict, Henshin_textPackage.Literals.STRICT__STRICT) |
| } |
| } |
| } |
| } |
| |
| |
| /** |
| * Fehler wenn mehr als ein Strict-Element in einer ConditionalUnit definiert wurde |
| * |
| * @param unit Zu überprüfende ConditionalUnit |
| */ |
| @Check |
| def checkCountStrictConditionalUnit(ConditionalUnit unit){ |
| var iterableOfStrictImplIF= Iterables.filter(unit.getIf,typeof(StrictImpl)) |
| var iterableOfStrictImplTHEN= Iterables.filter(unit.then,typeof(StrictImpl)) |
| var iterableOfStrictImplELSE= Iterables.filter(unit.getElse,typeof(StrictImpl)) |
| if(iterableOfStrictImplIF.size>1){ |
| for(strict:iterableOfStrictImplIF){ |
| error("Strict can only be used once.'", strict, Henshin_textPackage.Literals.STRICT__STRICT) |
| } |
| } |
| if(iterableOfStrictImplTHEN.size>1){ |
| for(strict:iterableOfStrictImplTHEN){ |
| error("Strict can only be used once.'", strict, Henshin_textPackage.Literals.STRICT__STRICT) |
| } |
| } |
| if(iterableOfStrictImplELSE.size>1){ |
| for(strict:iterableOfStrictImplELSE){ |
| error("Strict can only be used once.'", strict, Henshin_textPackage.Literals.STRICT__STRICT) |
| } |
| } |
| } |
| |
| |
| /** |
| * Fehler wenn mehr als ein Strict-Element in einer PriorityUnit definiert wurde |
| * |
| * @param unit Zu überprüfende PriorityUnit |
| */ |
| @Check |
| def checkCountStrictPriorityUnit(PriorityUnit unit){ |
| for(e:unit.listOfLists){ |
| var iterableOfStrictImpl= Iterables.filter(e.subElements,typeof(StrictImpl)) |
| if(iterableOfStrictImpl.size>1){ |
| for(strict:iterableOfStrictImpl){ |
| error("Strict can only be used once.'", strict, Henshin_textPackage.Literals.STRICT__STRICT) |
| } |
| } |
| } |
| } |
| |
| /** |
| * Fehler wenn mehr als ein Strict-Element in einer IteratedUnit definiert wurde |
| * |
| * @param unit Zu überprüfende IteratedUnit |
| */ |
| @Check |
| def checkCountStrictIteratedUnit(IteratedUnit unit){ |
| var iterableOfStrictImpl= Iterables.filter(unit.subElement,typeof(StrictImpl)) |
| if(iterableOfStrictImpl.size>1){ |
| for(strict:iterableOfStrictImpl){ |
| error("Strict can only be used once.'", strict, Henshin_textPackage.Literals.STRICT__STRICT) |
| } |
| } |
| } |
| |
| /** |
| * Fehler wenn mehr als ein Strict-Element in einer LoopUnit definiert wurde |
| * |
| * @param unit Zu überprüfende LoopUnit |
| */ |
| @Check |
| def checkCountStrictLoopUnit(LoopUnit unit){ |
| var iterableOfStrictImpl= Iterables.filter(unit.subElement,typeof(StrictImpl)) |
| if(iterableOfStrictImpl.size>1){ |
| for(strict:iterableOfStrictImpl){ |
| error("Strict can only be used once.'", strict, Henshin_textPackage.Literals.STRICT__STRICT) |
| } |
| } |
| } |
| |
| /** |
| * Fehler wenn mehr als ein Rollback-Element in einer Unit-Definition definiert wurde |
| * |
| * @param unit Zu überprüfende Unit |
| */ |
| @Check |
| def checkCountRollback(Unit unit){ |
| var iterableOfRollbackImpl= Iterables.filter(unit.unitElements,typeof(RollbackImpl)) |
| if(iterableOfRollbackImpl.size>1){ |
| for(rollback:iterableOfRollbackImpl){ |
| error("Rollback can only be used once.'", rollback, Henshin_textPackage.Literals.ROLLBACK__ROLLBACK) |
| } |
| } |
| } |
| |
| /** |
| * Fehler wenn mehr als ein Rollback-Element in einer SubSequenz definiert wurde |
| * |
| * @param unit Zu überprüfende SupSequenz |
| */ |
| @Check |
| def checkCountRollbackSubSequence(UnitElement unit){ |
| var iterableOfRollbackImpl= Iterables.filter(unit.subSequence,typeof(RollbackImpl)) |
| if(iterableOfRollbackImpl.size>1){ |
| for(rollback:iterableOfRollbackImpl){ |
| error("Rollback can only be used once.'", rollback, Henshin_textPackage.Literals.ROLLBACK__ROLLBACK) |
| } |
| } |
| } |
| |
| /** |
| * Fehler wenn mehr als ein Rollback-Element in einer IndependentUnit definiert wurde |
| * |
| * @param unit Zu überprüfende IndependentUnit |
| */ |
| @Check |
| def checkCountRollbackIndependentUnit(IndependentUnit unit){ |
| for(e:unit.listOfLists){ |
| var iterableOfRollbackImpl= Iterables.filter(e.subElements,typeof(RollbackImpl)) |
| if(iterableOfRollbackImpl.size>1){ |
| for(rollback:iterableOfRollbackImpl){ |
| error("Rollback can only be used once.'", rollback, Henshin_textPackage.Literals.ROLLBACK__ROLLBACK) |
| } |
| } |
| } |
| } |
| |
| /** |
| * Fehler wenn mehr als ein Rollback-Element in einer ConditionalUnit definiert wurde |
| * |
| * @param unit Zu überprüfende ConditionalUnit |
| */ |
| @Check |
| def checkCountRollbackConditionalUnit(ConditionalUnit unit){ |
| var iterableOfRollbackImplIF= Iterables.filter(unit.getIf,typeof(RollbackImpl)) |
| var iterableOfRollbackImplTHEN= Iterables.filter(unit.then,typeof(RollbackImpl)) |
| var iterableOfRollbackImplELSE= Iterables.filter(unit.getElse,typeof(RollbackImpl)) |
| if(iterableOfRollbackImplIF.size>1){ |
| for(rollback:iterableOfRollbackImplIF){ |
| error("Strict can only be used once.'", rollback, Henshin_textPackage.Literals.ROLLBACK__ROLLBACK) |
| } |
| } |
| if(iterableOfRollbackImplTHEN.size>1){ |
| for(rollback:iterableOfRollbackImplTHEN){ |
| error("Strict can only be used once.'", rollback, Henshin_textPackage.Literals.ROLLBACK__ROLLBACK) |
| } |
| } |
| if(iterableOfRollbackImplELSE.size>1){ |
| for(rollback:iterableOfRollbackImplELSE){ |
| error("Strict can only be used once.'", rollback, Henshin_textPackage.Literals.ROLLBACK__ROLLBACK) |
| } |
| } |
| } |
| |
| /** |
| * Fehler wenn mehr als ein Rollback-Element in einer PriorityUnit definiert wurde |
| * |
| * @param unit Zu überprüfende PriorityUnit |
| */ |
| @Check |
| def checkCountRollbackPriorityUnit(PriorityUnit unit){ |
| for(e:unit.listOfLists){ |
| var iterableOfRollbackImpl= Iterables.filter(e.subElements,typeof(RollbackImpl)) |
| if(iterableOfRollbackImpl.size>1){ |
| for(rollback:iterableOfRollbackImpl){ |
| error("Rollback can only be used once.'", rollback, Henshin_textPackage.Literals.ROLLBACK__ROLLBACK) |
| } |
| } |
| } |
| } |
| |
| |
| /** |
| * Fehler wenn mehr als ein Rollback-Element in einer IteratedUnit definiert wurde |
| * |
| * @param unit Zu überprüfende IteratedUnit |
| */ |
| @Check |
| def checkCountRollbackIteratedUnit(IteratedUnit unit){ |
| var iterableOfRollbackImpl= Iterables.filter(unit.subElement,typeof(RollbackImpl)) |
| if(iterableOfRollbackImpl.size>1){ |
| for(rollback:iterableOfRollbackImpl){ |
| error("Rollback can only be used once.'", rollback, Henshin_textPackage.Literals.ROLLBACK__ROLLBACK) |
| } |
| } |
| } |
| |
| /** |
| * Fehler wenn mehr als ein Rollback-Element in einer LoopUnit definiert wurde |
| * |
| * @param unit Zu überprüfende LoopUnit |
| */ |
| @Check |
| def checkCountRollbackLoopUnit(LoopUnit unit){ |
| var iterableOfRollbackImpl= Iterables.filter(unit.subElement,typeof(RollbackImpl)) |
| if(iterableOfRollbackImpl.size>1){ |
| for(rollback:iterableOfRollbackImpl){ |
| error("Rollback can only be used once.'", rollback, Henshin_textPackage.Literals.ROLLBACK__ROLLBACK) |
| } |
| } |
| } |
| |
| //-------------------------------------------------------------------------- |
| //Typesystem |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * Fehler wenn NOT auf einen anderen Wert als vom Typ Boolean angewendet wird |
| * |
| * @param not Zu überprüfender NOT-Ausdruck |
| */ |
| @Check |
| def checkTypeNot(NotExpression not) { |
| checkExpectedType(not.expression, Henshin_textTypeProvider.boolType, Henshin_textPackage.Literals.NOT_EXPRESSION__EXPRESSION) |
| } |
| |
| /** |
| * Fehler wenn keine Zahlenwerte in einem Multiplikations-/Divisions-Ausdruck verwendet werden |
| * |
| * @param plus Zu überprüfender Multiplikations-/Divisions-Ausdruck |
| */ |
| @Check |
| def checkTypeMulOrDiv(MulOrDivExpression mulOrDiv) { |
| checkExpectedType(mulOrDiv.left, Henshin_textTypeProvider.numberType, Henshin_textPackage.Literals.MUL_OR_DIV_EXPRESSION__LEFT) |
| checkExpectedType(mulOrDiv.right, Henshin_textTypeProvider.numberType, Henshin_textPackage.Literals.MUL_OR_DIV_EXPRESSION__RIGHT) |
| } |
| |
| /** |
| * Fehler wenn keine Zahlenwerte in einem Subtraktions-Ausdruck verwendet werden |
| * |
| * @param plus Zu überprüfender Subtraktions-Ausdruck |
| */ |
| @Check |
| def checkTypeMinus(MinusExpression minus) { |
| checkExpectedType(minus.left, Henshin_textTypeProvider.numberType, Henshin_textPackage.Literals.MINUS_EXPRESSION__LEFT) |
| checkExpectedType(minus.right, Henshin_textTypeProvider.numberType, Henshin_textPackage.Literals.MINUS_EXPRESSION__RIGHT) |
| } |
| |
| /** |
| * Fehler wenn keine Zahlenwerte miteinander addiert werden sollen |
| * |
| * @param plus Zu überprüfender Additions-Ausdruck |
| */ |
| @Check |
| def checkTypePlus(PlusExpression plus) { |
| checkExpectedType(plus.left, Henshin_textTypeProvider.numberType, Henshin_textPackage.Literals.PLUS_EXPRESSION__LEFT) |
| checkExpectedType(plus.right, Henshin_textTypeProvider.numberType, Henshin_textPackage.Literals.PLUS_EXPRESSION__RIGHT) |
| } |
| |
| |
| /** |
| * Fehler wenn keine Boolean-Werte in einem AND-Ausdruck verwendet werden |
| * |
| * @param and Zu überprüfender AND-Ausdruck |
| */ |
| @Check |
| def checkTypeAnd(AndExpression and) { |
| checkExpectedType(and.left, Henshin_textTypeProvider.boolType, Henshin_textPackage.Literals.AND_EXPRESSION__LEFT) |
| checkExpectedType(and.right, Henshin_textTypeProvider.boolType, Henshin_textPackage.Literals.AND_EXPRESSION__RIGHT) |
| } |
| |
| |
| /** |
| * Fehler wenn keine Boolean-Werte in einem OR-Ausdruck verwendet werden |
| * |
| * @param or Zu überprüfender OR-Ausdruck |
| */ |
| @Check |
| def checkTypeOr(OrExpression or) { |
| checkExpectedType(or.left, Henshin_textTypeProvider.boolType, Henshin_textPackage.Literals.OR_EXPRESSION__LEFT) |
| checkExpectedType(or.right, Henshin_textTypeProvider.boolType, Henshin_textPackage.Literals.OR_EXPRESSION__RIGHT) |
| } |
| |
| |
| /** |
| * Fehler wenn Werte unterschiedlicher Typen auf Un-/Gleichheit geprüft werden |
| * |
| * @param equality Zu überprüfender Un-/Gleichheits-Ausdruck |
| * |
| */ |
| @Check |
| def checkTypeEquality(EqualityExpression equality) { |
| val leftType = getTypeAndCheckNotNull(equality.left, Henshin_textPackage.Literals.EQUALITY_EXPRESSION__LEFT) |
| val rightType = getTypeAndCheckNotNull(equality.right, Henshin_textPackage.Literals.EQUALITY_EXPRESSION__RIGHT) |
| if((leftType!=rightType)&&(leftType!=null)&&(rightType!=null)){ |
| error("Expression expected the same type, but was " + leftType + " and " +rightType+".'",Henshin_textPackage.Literals.EQUALITY_EXPRESSION.getEIDAttribute(),"") |
| } |
| } |
| |
| |
| /** |
| * Fehler wenn bei einem Verleich unterschiedliche Typen oder Boolean-Werte miteinander verglichen werden |
| * |
| * @param comparison Zu überprüfender Vergleichs-Ausdruck |
| */ |
| @Check |
| def checkTypeComparison(ComparisonExpression comparison) { |
| val leftType = getTypeAndCheckNotNull(comparison.left, Henshin_textPackage.Literals.COMPARISON_EXPRESSION__LEFT) |
| val rightType = getTypeAndCheckNotNull(comparison.right, Henshin_textPackage.Literals.COMPARISON_EXPRESSION__RIGHT) |
| if((leftType!=rightType)&&(leftType!=null)&&(rightType!=null)){ |
| error("Expression expected the same type, but was " + leftType + " and " +rightType+".'",Henshin_textPackage.Literals.COMPARISON_EXPRESSION.getEIDAttribute(),"") |
| } |
| if ((leftType==Henshin_textTypeProvider.boolType)||(leftType==Henshin_textTypeProvider.complexType)){ |
| error("Value cannot be compared.'", Henshin_textPackage.Literals.COMPARISON_EXPRESSION__LEFT,"") |
| } |
| if ((rightType==Henshin_textTypeProvider.boolType)||(leftType==Henshin_textTypeProvider.complexType)){ |
| error("Value cannot be compared.'", Henshin_textPackage.Literals.COMPARISON_EXPRESSION__RIGHT,"") |
| } |
| } |
| |
| |
| /** |
| * Fehler wenn der tatsächliche Typ eines Ausdrucks nicht zur erwarteten Typart passt. |
| * |
| * @param expression Zu überprüfender Ausdruck |
| * @param expectedType Erwarteter Typ |
| * @param reference Referenz zum zu überprüfenden Ausdrucks |
| * |
| */ |
| def private checkExpectedType(Expression expression, Henshin_textType expectedType, EReference reference) { |
| val actualType=getTypeAndCheckNotNull(expression, reference) |
| if (actualType!=expectedType){ |
| error("Expression expected " + expectedType + " type, but was " + actualType+".'", reference, "") |
| } |
| } |
| |
| |
| /** |
| * Liefert die Typart eines Ausdrucks zurück. Fehler wenn keine passende Typart gefunden wurde. |
| * |
| * @param expression Zu überprüfender Ausdruck |
| * @param refrence Referenz zum zu überprüfenden Ausdrucks |
| * |
| * @return Typart des Ausdrucks |
| * |
| */ |
| def private Henshin_textType getTypeAndCheckNotNull(Expression expression,EReference reference){ |
| var Henshin_textType type |
| if(expression!=null){ |
| type=typeFor(expression) |
| } |
| if (type==null){ |
| error("Null type.'",reference, "") |
| } |
| return type; |
| } |
| |
| /** |
| * Fehler wenn ein Ausdruck einem Attribut zugewiesen wird der den falschen Typ hat |
| * |
| * @param attribute Zu überprüfendes Attribut |
| * |
| */ |
| @Check |
| def checkAttributeType(Attribute attribute){ |
| if(attribute.value instanceof ParameterValue){ |
| if(((attribute.value as ParameterValue).value.type.type!=null)&&(attribute.name.EAttributeType.name!=(attribute.value as ParameterValue).value.type.type.name)){ |
| error("Attribute expected " + attribute.name.EAttributeType.name + " type, but was " + (attribute.value as ParameterValue).value.type.type.name+".'", attribute,Henshin_textPackage::eINSTANCE.attribute_Value) |
| }else if((typeFor(attribute.name.EAttributeType.name).toString!="string")&&(typeFor(attribute.name.EAttributeType.name)!=typeFor((attribute.value as ParameterValue).value.type.enumType.literal))){ |
| error("Attribute expected " + attribute.name.EAttributeType.name + " type, but was " + (attribute.value as ParameterValue).value.type.enumType.literal+".'", attribute,Henshin_textPackage::eINSTANCE.attribute_Value) |
| } |
| }else{ |
| if((typeFor(attribute.name.EAttributeType.name).toString!="string")&&(typeFor(attribute.name.EAttributeType.name)!=typeFor(attribute.value))){ |
| error("Attribute expected " + attribute.name.EAttributeType.name + " type, but was "+typeFor(attribute.value)+".'", attribute,Henshin_textPackage::eINSTANCE.attribute_Value) |
| } |
| } |
| } |
| |
| /** |
| * Fehler wenn ein Ausdruck einem Match zugewiesen wird der den falschen Typ hat |
| * |
| * @param match Zu überprüfender Match-Ausdruck |
| * |
| */ |
| @Check |
| def checkMatchType(Match match){ |
| if(match.value instanceof ParameterValue){ |
| if(((match.value as ParameterValue).value.type.type!=null)&&(match.name.EAttributeType.name!=(match.value as ParameterValue).value.type.type.name)){ |
| error("Attribute expected " + match.name.EAttributeType.name + " type, but was " + (match.value as ParameterValue).value.type.type.name+".'",match,Henshin_textPackage::eINSTANCE.match_Value) |
| }else if((typeFor(match.name.EAttributeType.name).toString!="string")&&(typeFor(match.name.EAttributeType.name)!=typeFor((match.value as ParameterValue).value.type.enumType.literal))){ |
| error("Attribute expected " + match.name.EAttributeType.name + " type, but was " +(match.value as ParameterValue).value.type.enumType.literal+".'", match,Henshin_textPackage::eINSTANCE.match_Value) |
| } |
| }else{ |
| if((typeFor(match.name.EAttributeType.name).toString!="string")&&(typeFor(match.name.EAttributeType.name)!=typeFor(match.value))){ |
| error("Attribute expected " + match.name.EAttributeType.name + " type, but was "+typeFor(match.value)+".'",match,Henshin_textPackage::eINSTANCE.match_Value) |
| } |
| } |
| } |
| |
| /** |
| * Fehler wenn das Java-Attribut nicht existiert |
| * |
| * @param attribute Zu überprüfenders Java-Attribute |
| */ |
| @Check |
| def checkJavaAttribute(JavaAttributeValue attribute){ |
| var Iterable<JavaImport> iterableOfJavaImportImpl=getImportList(attribute) |
| var Field javaAttribute |
| for(imports:iterableOfJavaImportImpl){ |
| try{ |
| var calledClass=Class.forName(imports.packagename+"."+attribute.value.split("\\.").get(0)) |
| for(atrib:calledClass.declaredFields){ |
| if(atrib.name==attribute.value.split("\\.").get(1)){ |
| javaAttribute=atrib |
| } |
| } |
| }catch(ClassNotFoundException e){} |
| } |
| if(javaAttribute==null){ |
| error(attribute.value+" doesn't exist.'",attribute,Henshin_textPackage::eINSTANCE.javaAttributeValue_Value) |
| } |
| } |
| |
| |
| /** |
| * Fehler wenn die aufgerufene Java-Methode nicht existiert oder der Aufruf fehlerhaft ist |
| * |
| * @param classCall Javamethodenaufruf der überprüft werden soll |
| * |
| */ |
| @Check |
| def checkJavaCall(JavaClassValue classCall){ |
| var Iterable<JavaImport> iterableOfJavaImportImpl=getImportList(classCall) |
| var List<Method> methods=new ArrayList<Method> |
| for(imports:iterableOfJavaImportImpl){ |
| try{ |
| var calledClass=Class.forName(imports.packagename+"."+classCall.value.split("\\.").get(0)) |
| for(method:calledClass.getMethods()){ |
| if(method.name==classCall.value.split("\\.").get(1)){ |
| methods.add(method) |
| } |
| } |
| }catch(ClassNotFoundException e){} |
| } |
| if(methods.size<=0){ |
| error(classCall.value+" doesn't exist.'",classCall,Henshin_textPackage::eINSTANCE.javaClassValue_Value) |
| }else{ |
| var badParametercount=true |
| var wrongParameterType=false |
| var methodExist=false |
| for(method:methods){ |
| if(!methodExist){ |
| if(method.parameterTypes.size==classCall.getJavaParameter.size){ |
| badParametercount=false |
| for(var i=0;i<classCall.javaParameter.size;i++){ |
| if(typeFor(classCall.javaParameter.get(i))!=typeForJavaType(method.parameterTypes.get(i).name)){ |
| wrongParameterType=true |
| } |
| } |
| } |
| if(!badParametercount&&!wrongParameterType){ |
| methodExist=true |
| }else{ |
| badParametercount=true |
| wrongParameterType=false |
| } |
| } |
| } |
| if(!methodExist){ |
| if(methods.get(0).parameterTypes.size!=classCall.getJavaParameter.size){ |
| error("Bad Parameter Count.'",classCall,Henshin_textPackage::eINSTANCE.javaClassValue_Value) |
| }else{ |
| for(var i=0;i<classCall.javaParameter.size;i++){ |
| if(typeFor(classCall.javaParameter.get(i))!=typeForJavaType(methods.get(0).parameterTypes.get(i).name)){ |
| error("Methode expected " + methods.get(0).parameterTypes.get(i).name + " type, but was "+typeFor(classCall.javaParameter.get(i))+".'",classCall.javaParameter.get(i),Henshin_textPackage::eINSTANCE.javaClassValue_JavaParameter) |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| /** |
| * Liefert Liste der importierten JavaPackages oberhalb des übergebenen Objekts |
| * |
| * @param startObject Object für das alle JavaPackages gefunden werden soll |
| * |
| * @return List<JavaImport> Liste der importierten JavaPackages |
| * |
| */ |
| private def List<JavaImport> getImportList(EObject startObject){ |
| var List<JavaImport> iterableOfJavaImportImpl=new ArrayList |
| var EObject container=startObject.eContainer() |
| while(!(container instanceof Rule)&&!(container instanceof MultiRule)){ |
| container=container.eContainer() |
| } |
| if(container instanceof Rule){ |
| iterableOfJavaImportImpl.addAll(Iterables.filter((container as Rule).ruleElements,typeof(JavaImport))) |
| }else{ |
| iterableOfJavaImportImpl.addAll(Iterables.filter((container as MultiRule).multiruleElements,typeof(JavaImport))) |
| } |
| if(!(container.eContainer instanceof Model)){ |
| iterableOfJavaImportImpl.addAll(getImportList(container)) |
| } |
| return iterableOfJavaImportImpl |
| } |
| |
| } |