1 package org.andromda.translation.ocl.testsuite;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import org.andromda.core.common.ExceptionUtils;
6 import org.andromda.core.metafacade.ModelAccessFacade;
7 import org.andromda.core.translation.Expression;
8 import org.andromda.metafacades.uml.ClassifierFacade;
9 import org.andromda.metafacades.uml.ModelElementFacade;
10 import org.andromda.metafacades.uml.OperationFacade;
11 import org.andromda.metafacades.uml.ParameterFacade;
12 import org.andromda.translation.ocl.BaseTranslator;
13 import org.andromda.translation.ocl.node.AOperationContextDeclaration;
14 import org.andromda.translation.ocl.node.POperation;
15 import org.andromda.translation.ocl.syntax.ConcreteSyntaxUtils;
16 import org.andromda.translation.ocl.syntax.OperationDeclaration;
17 import org.andromda.translation.ocl.syntax.VariableDeclaration;
18 import org.apache.commons.collections.CollectionUtils;
19 import org.apache.commons.collections.Predicate;
20 import org.apache.commons.lang.StringUtils;
21
22
23
24
25
26
27 public class ContextElementFinder
28 extends BaseTranslator
29 {
30 private ModelAccessFacade model;
31
32
33
34
35
36
37
38 public ContextElementFinder(ModelAccessFacade model)
39 {
40 ExceptionUtils.checkNull("model", model);
41 this.model = model;
42 }
43
44
45
46
47 @SuppressWarnings("unused")
48 private ContextElementFinder()
49 {
50 }
51
52
53
54
55 protected OperationDeclaration operation = null;
56
57
58
59
60 private Object contextElement = null;
61
62
63
64
65
66 public void inAOperationContextDeclaration(AOperationContextDeclaration declaration)
67 {
68 super.inAOperationContextDeclaration(declaration);
69 if (declaration != null)
70 {
71 operation = ConcreteSyntaxUtils.getOperationDeclaration(declaration.getOperation());
72 }
73 }
74
75
76
77
78
79
80
81 @Override
82 public void postProcess()
83 {
84 Expression expression = this.getExpression();
85 if (expression != null)
86 {
87 String contextElementName = expression.getContextElement();
88 this.contextElement = this.findModelElement(contextElementName.replaceAll("::", "\\."));
89 if (this.contextElement != null)
90 {
91 logger.info("found context element --> '" + contextElementName + '\'');
92 } else
93 {
94 logger.info("Could not find model element --> '" + contextElementName + '\'');
95 }
96
97 if (this.contextElement != null && this.operation != null &&
98 ClassifierFacade.class.isAssignableFrom(contextElement.getClass()))
99 {
100 ClassifierFacade type = (ClassifierFacade) this.contextElement;
101 Collection operations = type.getOperations();
102 this.contextElement = CollectionUtils.find(operations, new OperationFinder());
103 if (this.contextElement == null)
104 {
105 throw new ContextElementFinderException("No operation matching '" + operation +
106 "' could be found on element --> '" + contextElementName + "', please check your model");
107 }
108
109
110
111
112
113 if (operations.size() == 1)
114 {
115 this.contextElement = operations.iterator().next();
116 } else
117 {
118
119
120 }
121 }
122 }
123 }
124
125 private final class OperationFinder
126 implements Predicate
127 {
128 public boolean evaluate(Object object)
129 {
130
131 OperationFacade facadeOperation = (OperationFacade) object;
132 boolean valid = StringUtils.trimToEmpty(facadeOperation.getName()).equals(
133 StringUtils.trimToEmpty(operation.getName()));
134
135
136 if (valid)
137 {
138 valid = argumentsMatch(operation, facadeOperation);
139 }
140 return valid;
141 }
142 }
143
144
145
146
147
148
149
150
151
152 protected boolean argumentsMatch(OperationDeclaration oclOperation, OperationFacade facadeOperation)
153 {
154 boolean argumentsMatch = this.argumentCountsMatch(oclOperation, facadeOperation);
155 if (argumentsMatch)
156 {
157 argumentsMatch = this.argumentNamesMatch(oclOperation, facadeOperation);
158 }
159 return argumentsMatch;
160 }
161
162
163
164
165
166
167
168
169
170 private boolean argumentCountsMatch(OperationDeclaration oclOperation, OperationFacade facadeOperation)
171 {
172 ExceptionUtils.checkNull("oclOperation", oclOperation);
173 ExceptionUtils.checkNull("facadeOperation", facadeOperation);
174 VariableDeclaration[] expressionOpArgs = oclOperation.getArguments();
175 Collection facadeOpArgs = facadeOperation.getArguments();
176 boolean countsMatch = (expressionOpArgs == null || expressionOpArgs.length == 0) &&
177 (facadeOpArgs == null || facadeOpArgs.isEmpty());
178 if (!countsMatch)
179 {
180 countsMatch = expressionOpArgs != null && facadeOpArgs != null &&
181 expressionOpArgs.length == facadeOpArgs.size();
182 }
183 return countsMatch;
184 }
185
186
187
188
189
190
191
192
193
194 private boolean argumentNamesMatch(OperationDeclaration oclOperation, OperationFacade facadeOperation)
195 {
196 ExceptionUtils.checkNull("oclOperation", oclOperation);
197 ExceptionUtils.checkNull("facadeOperation", facadeOperation);
198
199 Collection<ParameterFacade> facadeOpArguments = facadeOperation.getArguments();
200 VariableDeclaration[] expressionOpArgs = oclOperation.getArguments();
201 Collection<String> expressionArgNames = new ArrayList<String>();
202 if (expressionOpArgs != null)
203 {
204 for (VariableDeclaration expressionOpArg : expressionOpArgs)
205 {
206 expressionArgNames.add(expressionOpArg.getName());
207 }
208 }
209 Collection<String> facadeArgNames = new ArrayList<String>();
210 if (facadeOpArguments != null)
211 {
212 for (ParameterFacade facadeArg : facadeOpArguments)
213 {
214 facadeArgNames.add(facadeArg.getName());
215 }
216 }
217 return CollectionUtils.isEqualCollection(expressionArgNames, facadeArgNames);
218 }
219
220
221
222
223
224
225
226
227 private Object findModelElement(final String modelElementName)
228 {
229 Object modelElement = null;
230 Collection modelElements = this.model.getModelElements();
231 CollectionUtils.filter(modelElements, new Predicate()
232 {
233 public boolean evaluate(Object object)
234 {
235 boolean valid = false;
236 if (ModelElementFacade.class.isAssignableFrom(object.getClass()))
237 {
238 ModelElementFacade modelElement = (ModelElementFacade) object;
239 String elementName = StringUtils.trimToEmpty(modelElement.getName());
240 String name = StringUtils.trimToEmpty(modelElementName);
241 valid = elementName.equals(name);
242 if (!valid)
243 {
244 elementName = StringUtils.trimToEmpty(modelElement.getFullyQualifiedName());
245 valid = elementName.equals(name);
246 }
247 }
248 return valid;
249 }
250 });
251 if (modelElements.size() > 1)
252 {
253 throw new ContextElementFinderException("More than one element named '" + modelElementName +
254 "' was found within your model," + " please give the fully qualified name");
255 } else if (modelElements.size() == 1)
256 {
257 modelElement = modelElements.iterator().next();
258 }
259 return modelElement;
260 }
261
262
263
264
265
266
267 public Object getContextElement()
268 {
269 return this.contextElement;
270 }
271
272 }