| \begin{lstlisting}[basicstyle=\small,caption=EVL Module for Validating Singletons, label=lst:CaseStudy, language=EVL] | |
| context Singleton { | |
| guard : self.stereotype->exists(s|s.name = "singleton") | |
| constraint DefinesGetInstance { | |
| check : self.getGetInstanceOperation().isDefined() | |
| message : "Singleton " + self.name + | |
| " must define a getInstance() operation" | |
| fix { | |
| title : "Add a getInstance() operation to " + self.name | |
| do { | |
| // Create the getInstance operation | |
| var op : new Operation; | |
| op.name = "getInstance"; | |
| op.owner = self; | |
| op.ownerScope = ScopeKind#sk_classifier; | |
| // Create the return parameter | |
| var returnParameter : new Parameter; | |
| returnParameter.type = self; | |
| op.parameter = Sequence{returnParameter}; | |
| returnParameter.kind = ParameterDirectionKind#pdk_return; | |
| } | |
| } | |
| } | |
| constraint GetInstanceIsStatic { | |
| guard : self.satisfies("DefinesGetInstance") | |
| check : self.getGetInstanceOperation().ownerScope = | |
| ScopeKind#sk_classifier | |
| message : " The getInstance() operation of singleton " | |
| + self.name + " must be static" | |
| fix { | |
| title : "Change to static" | |
| do { | |
| self.getGetInstanceOperation.ownerScope | |
| = ScopeKind#sk_classifier; | |
| } | |
| } | |
| } | |
| constraint GetInstanceReturnsSame { | |
| guard : self.satisfies("DefinesGetInstance") | |
| check { | |
| var returnParameter : Parameter; | |
| returnParameter = self.getReturnParameter(); | |
| return (returnParameter->isDefined() | |
| and returnParameter.type = self); | |
| } | |
| message : " The getInstance() operation of singleton " | |
| + self.name + " must return " + self.name | |
| fix { | |
| title : "Change return type to " + self.name | |
| do { | |
| var returnParameter : Parameter; | |
| returnParameter = self.getReturnParameter(); | |
| // If the operation does not have a return parameter | |
| // create one | |
| if (not returnParameter.isDefined()){ | |
| returnParameter = Parameter.newInstance(); | |
| returnParameter.kind = ParameterDirectionKind#pdk_return; | |
| returnParameter.behavioralFeature = | |
| self.getInstanceOperation(); | |
| } | |
| // Set the correct return type | |
| returnParameter.type = self; | |
| } | |
| } | |
| } | |
| } | |
| operation Class getGetInstanceOperation() : Operation { | |
| return self.feature. | |
| select(o:Operation|o.name = "getInstance").first(); | |
| } | |
| operation Operation getReturnParameter() : Parameter { | |
| return self.parameter. | |
| select(p:Parameter|p.kind = | |
| ParameterDirectionKind#pdk_return).first(); | |
| } | |
| \end{lstlisting} |