View Javadoc
1   package org.andromda.translation.ocl.syntax;
2   
3   import java.util.ArrayList;
4   import java.util.Collection;
5   import java.util.List;
6   import org.andromda.core.common.ExceptionUtils;
7   import org.andromda.core.translation.TranslationUtils;
8   import org.andromda.translation.ocl.node.AActualParameterList;
9   import org.andromda.translation.ocl.node.ACommaExpression;
10  import org.andromda.translation.ocl.node.AFeatureCall;
11  import org.andromda.translation.ocl.node.AFeatureCallParameters;
12  import org.andromda.translation.ocl.node.AOperation;
13  import org.andromda.translation.ocl.node.APropertyCallExpression;
14  import org.andromda.translation.ocl.node.ARelationalExpression;
15  import org.andromda.translation.ocl.node.ARelationalExpressionTail;
16  import org.andromda.translation.ocl.node.AStandardDeclarator;
17  import org.andromda.translation.ocl.node.ATypeDeclaration;
18  import org.andromda.translation.ocl.node.AVariableDeclaration;
19  import org.andromda.translation.ocl.node.AVariableDeclarationList;
20  import org.andromda.translation.ocl.node.AVariableDeclarationListTail;
21  import org.andromda.translation.ocl.node.PActualParameterList;
22  import org.andromda.translation.ocl.node.PEqualExpression;
23  import org.andromda.translation.ocl.node.PFeatureCallParameters;
24  import org.andromda.translation.ocl.node.POperation;
25  import org.andromda.translation.ocl.node.PRelationalExpression;
26  import org.andromda.translation.ocl.node.PVariableDeclaration;
27  import org.andromda.translation.ocl.node.PVariableDeclarationList;
28  import org.andromda.translation.ocl.node.TName;
29  import org.apache.commons.lang.ObjectUtils;
30  import org.apache.commons.lang.StringUtils;
31  import org.apache.log4j.Logger;
32  
33  /**
34   * Contains some utilities for concrete syntax value retrieval.
35   *
36   * @author Chad Brandon
37   */
38  public class ConcreteSyntaxUtils
39  {
40      private static final Logger logger = Logger.getLogger(ConcreteSyntaxUtils.class);
41  
42      /**
43       * Iterates through the passed in list and concatenates all the values of objects toString value to a StringBuffer and
44       * returns the StringBuffer.
45       *
46       * @param list the List of objects to concatenate.
47       * @return StringBuffer the concatenated contents of the list.
48       */
49      public static StringBuffer concatContents(List list)
50      {
51          StringBuffer name = new StringBuffer();
52          if (list != null)
53          {
54              for (Object object : list)
55              {
56                  String value = ObjectUtils.toString(object);
57                  name.append(value);
58              }
59          }
60          return name;
61      }
62  
63      /**
64       * Converts the passed <code>operation</code> to an instance of <code>Operation</code> for the passed in operation.
65       *
66       * @param operation
67       * @return VariableDeclarations
68       */
69      public static OperationDeclaration getOperationDeclaration(POperation operation)
70      {
71          ExceptionUtils.checkNull("operation", operation);
72  
73          OperationDeclaration operationDeclaration = null;
74  
75          AOperation op = (AOperation) operation;
76  
77          ATypeDeclaration typeDeclaration = (ATypeDeclaration) op.getReturnTypeDeclaration();
78          String returnType = null;
79          if (typeDeclaration != null)
80          {
81              returnType = ObjectUtils.toString(typeDeclaration.getType());
82          }
83  
84          operationDeclaration = new OperationDeclarationImpl(ObjectUtils.toString(op.getName()), returnType, ConcreteSyntaxUtils.getVariableDeclarations(
85                  operation));
86          return operationDeclaration;
87      }
88  
89      /**
90       * Retrieves all the variable declarations for the passed in <code>operation</code>.
91       *
92       * @param operation the operation for which to retrieve the variable declarations.
93       * @return VariableDeclaration[]
94       */
95      public static VariableDeclaration[] getVariableDeclarations(POperation operation)
96      {
97          ExceptionUtils.checkNull("operation", operation);
98          return ConcreteSyntaxUtils.getVariableDeclarations(((AOperation) operation).getParameters());
99      }
100 
101     /**
102      * Retrieves all the variable declarations for the passed in <code>standardDeclarator</code>.
103      *
104      * @param standardDeclarator the standard declartor for which to retrieve the VariableDeclaration instances.
105      * @return VariableDeclaration[]
106      */
107     public static VariableDeclaration[] getVariableDeclarations(AStandardDeclarator standardDeclarator)
108     {
109         ExceptionUtils.checkNull("standardDeclarator", standardDeclarator);
110         return ConcreteSyntaxUtils.getVariableDeclarations(standardDeclarator.getVariableDeclarationList());
111     }
112 
113     /**
114      * Creates a new VariableDeclaration from the passed in PVariableDeclaration.
115      *
116      * @param variableDeclaration the PVariableDeclaration that the new VariableDeclaration will be created from.
117      * @param initialValue        the initial value of the variable declaration.
118      * @return VariableDeclaration the new VariableDeclaration
119      */
120     protected static VariableDeclaration newVariableDeclaration(PVariableDeclaration variableDeclaration,
121                                                                 PEqualExpression initialValue)
122     {
123         ExceptionUtils.checkNull("variableDeclaration", variableDeclaration);
124 
125         AVariableDeclaration declaration = (AVariableDeclaration) variableDeclaration;
126         ATypeDeclaration typeDeclaration = (ATypeDeclaration) declaration.getTypeDeclaration();
127         String type = null;
128         String name = ObjectUtils.toString(declaration.getName()).trim();
129         if (typeDeclaration != null)
130         {
131             type = ObjectUtils.toString(typeDeclaration.getType());
132         }
133         return new VariableDeclarationImpl(name, type, ObjectUtils.toString(initialValue).trim());
134     }
135 
136     /**
137      * Creates an array of VariableDeclaration[] from the passed in PVariableDeclarationList.
138      *
139      * @param variableDeclarationList the PVariableDeclarationList that the new VariableDeclaration will be created
140      *                                from.
141      * @return VariableDeclaration[] the new VariableDeclaration array
142      */
143     public static VariableDeclaration[] getVariableDeclarations(PVariableDeclarationList variableDeclarationList)
144     {
145 
146         Collection declarations = new ArrayList();
147 
148         if (variableDeclarationList != null)
149         {
150             AVariableDeclarationList variables = (AVariableDeclarationList) variableDeclarationList;
151 
152             // add the first one
153             declarations.add(ConcreteSyntaxUtils.newVariableDeclaration(variables.getVariableDeclaration(),
154                     variables.getVariableDeclarationValue()));
155 
156             // add the rest
157             List<AVariableDeclarationListTail> variableTails = variables.getVariableDeclarationListTail();
158             if (variableTails != null)
159             {
160                 for (AVariableDeclarationListTail tail : variableTails)
161                 {
162                     declarations.add(
163                             ConcreteSyntaxUtils.newVariableDeclaration(tail.getVariableDeclaration(),
164                                     tail.getVariableDeclarationValue()));
165                 }
166             }
167         }
168         return (VariableDeclaration[]) declarations.toArray(new VariableDeclaration[declarations.size()]);
169     }
170 
171     /**
172      * Gets all the parameters from the <code>featureCall</code> instance.
173      *
174      * @param featureCall the featureCall for which to retrieve the parameters
175      * @return List the list containing any parameters retrieved, or an empty array if none could be retrieved
176      */
177     public static List getParameters(AFeatureCall featureCall)
178     {
179         List parameters = new ArrayList();
180         if (featureCall != null)
181         {
182             parameters = getParameters(featureCall.getFeatureCallParameters());
183         }
184         return parameters;
185     }
186 
187     /**
188      * Gets all the parameters from the <code>featureCall</code> instance as a comma separated String.
189      *
190      * @param featureCall the featureCall from which to retrieve the parameters
191      * @return String the comma separated String
192      */
193     public static String getParametersAsString(AFeatureCall featureCall)
194     {
195         return getParametersAsString(featureCall.getFeatureCallParameters());
196     }
197 
198     /**
199      * Gets all the parameters from the <code>PFeatureCallParameters</code> instance as a comma separated String.
200      *
201      * @param featureCallParameters the featureCallParameters from which to retrieve the parameters
202      * @return String the comma separated String
203      */
204     public static String getParametersAsString(PFeatureCallParameters featureCallParameters)
205     {
206         return StringUtils.join(ConcreteSyntaxUtils.getParameters(featureCallParameters).iterator(), ",");
207     }
208 
209     /**
210      * Gets all the parameters from the <code>callParameters</code> instance.
211      *
212      * @param callParameters the callParameters for which to retrieve the parameters
213      * @return List the list containing any parameters retrieved, or an empty array if none could be retrieved
214      */
215     private static List getParameters(PFeatureCallParameters callParameters)
216     {
217         List parameters = new ArrayList();
218         if (callParameters != null)
219         {
220             PActualParameterList parameterList = ((AFeatureCallParameters) callParameters).getActualParameterList();
221             if (parameterList != null)
222             {
223                 AActualParameterList params = (AActualParameterList) parameterList;
224 
225                 // add the first param if it exists
226                 String firstParam = TranslationUtils.trimToEmpty(params.getExpression());
227                 if (StringUtils.isNotBlank(firstParam))
228                 {
229                     parameters.add(firstParam);
230                 }
231 
232                 // now add the rest of the params which are contained in the
233                 // tail
234                 List<ACommaExpression> restOfParams = params.getCommaExpression();
235                 if (restOfParams != null && !restOfParams.isEmpty())
236                 {
237                     for (ACommaExpression parameterListTail : restOfParams)
238                     {
239                         parameters.add(TranslationUtils.trimToEmpty(parameterListTail.getExpression()));
240                     }
241                 }
242             }
243         }
244         return parameters;
245     }
246 
247     /**
248      * Gets the left and right expressions of a PRelationalExpression and puts then into a List. The left expression
249      * will be the first expression in the list.
250      *
251      * @param relationalExpression
252      * @return the left and right parenthesis in [0] and [1] of the String[]
253      */
254     public static String[] getLeftAndRightExpressions(PRelationalExpression relationalExpression)
255     {
256         String[] expressions = new String[2];
257         ARelationalExpression expression = (ARelationalExpression) relationalExpression;
258 
259         // set the left expression
260         expressions[0] = TranslationUtils.trimToEmpty(expression.getAdditiveExpression());
261 
262         ARelationalExpressionTail expressionTail = (ARelationalExpressionTail) expression.getRelationalExpressionTail();
263 
264         // set the right expression
265         expressions[1] = TranslationUtils.trimToEmpty(expressionTail.getAdditiveExpression());
266 
267         return expressions;
268     }
269 
270     /**
271      * Concatenates the type from the passed in name and pathNameTail.
272      *
273      * @param name         the starting name of the type
274      * @param pathNameTail the tail pieces of the name
275      * @return String the concatenated name.
276      */
277     public static String getType(TName name, List pathNameTail)
278     {
279         StringBuffer type = ConcreteSyntaxUtils.concatContents(pathNameTail);
280         type.insert(0, TranslationUtils.trimToEmpty(name));
281         return StringUtils.deleteWhitespace(type.toString());
282     }
283 
284     /**
285      * Gets the "real" primary expression, as opposed to the primary expression retrieved from the parser syntax (since
286      * it leaves off any navigational relationships).
287      *
288      * @param expression the APosfixExpression instance for which to retrieve the primary expression
289      * @return String the "real" primary expression or the passed in expression.
290      */
291     public static String getPrimaryExpression(APropertyCallExpression expression)
292     {
293         StringBuilder primaryExpression = new StringBuilder();
294         if (expression != null)
295         {
296             // append the first part of the primary expression
297             primaryExpression.append(TranslationUtils.trimToEmpty(expression.getPrimaryExpression()));
298             List expressionTail = expression.getPropertyCallExpressionTail();
299             if (!expressionTail.isEmpty())
300             {
301                 for (Object object : expressionTail)
302                 {
303                     final String tail = TranslationUtils.trimToEmpty(object);
304                     // beak out if we encounter an arrow feature call
305                     if (tail.contains(ARROW_FEATURE_CALL))
306                     {
307                         break;
308                     }
309                     // only append to the expression if not an operation
310                     if (tail.indexOf('(') == -1)
311                     {
312                         primaryExpression.append(tail);
313                     }
314                 }
315             }
316         }
317         return StringUtils.deleteWhitespace(primaryExpression.toString());
318     }
319 
320     /**
321      * Gets all feature calls from the passed in APropertyCallExpression instance.
322      *
323      * @param expression the APosfixExpression instance for which to retrieve the primary expression
324      * @return String the "real" primary expression of the passed in expression.
325      */
326     public static List getFeatureCalls(APropertyCallExpression expression)
327     {
328         final String methodName = "ConcreteSyntaxUtils.getFeatureCalls";
329         if (logger.isDebugEnabled())
330         {
331             logger.debug("performing " + methodName + " with expression --> '" + expression + '\'');
332         }
333         List featureCalls = new ArrayList();
334         if (expression != null)
335         {
336             List tails = expression.getPropertyCallExpressionTail();
337             if (tails != null && !tails.isEmpty())
338             {
339                 for (int ctr = 0; ctr < tails.size(); ctr++)
340                 {
341                     featureCalls.add(TranslationUtils.getProperty(tails.get(ctr), "featureCall"));
342                 }
343             }
344         }
345         return featureCalls;
346     }
347 
348     /**
349      * Indicates an arrow feature call.
350      */
351     private static final String ARROW_FEATURE_CALL = "->";
352 
353     /**
354      * Gets the navigational path from the given <code>expression</code> that occurs after an arrow feature call. If the
355      * the expression contains an arrow feature call, then the navigational expression is any expression navigating on
356      * the result of an arrow feature call (otherwise it's an empty string).
357      *
358      * @param expression the expression from which to retrieve the navigational path.
359      * @return the navigational path.
360      */
361     public static String getArrowFeatureCallResultNavigationalPath(APropertyCallExpression expression)
362     {
363         StringBuilder path = new StringBuilder();
364         if (OCLPatterns.isCollectionOperationResultNavigationalPath(expression))
365         {
366             List featureCalls = getFeatureCalls(expression);
367             int size = featureCalls.size();
368             if (size > 1)
369             {
370                 for (int ctr = 1; ctr < size; ctr++)
371                 {
372                     String featureCall = TranslationUtils.trimToEmpty(featureCalls.get(ctr));
373                     if (featureCall.contains(ARROW_FEATURE_CALL) || featureCall.indexOf('(') != -1)
374                     {
375                         break;
376                     }
377                     path.append(featureCall);
378                     if (ctr != size - 1)
379                     {
380                         path.append('.');
381                     }
382                 }
383             }
384         }
385         return path.toString();
386     }
387 
388     /**
389      * Loads a List of variable declaration names from the <code>variableDeclarations</code>
390      *
391      * @param variableDeclarations an array of VariableDeclaration objects
392      * @return List the list of argument names as Strings/
393      */
394     public static List getArgumentNames(VariableDeclaration[] variableDeclarations)
395     {
396         List names = new ArrayList();
397         for (int ctr = 0; ctr < variableDeclarations.length; ctr++)
398         {
399             names.add(variableDeclarations[ctr].getName());
400         }
401         return names;
402     }
403 }