001: package org.andromda.translation.ocl.syntax;
002:
003: import org.andromda.core.common.ExceptionUtils;
004: import org.andromda.core.translation.TranslationUtils;
005: import org.andromda.translation.ocl.node.AActualParameterList;
006: import org.andromda.translation.ocl.node.ACommaExpression;
007: import org.andromda.translation.ocl.node.AFeatureCall;
008: import org.andromda.translation.ocl.node.AFeatureCallParameters;
009: import org.andromda.translation.ocl.node.AOperation;
010: import org.andromda.translation.ocl.node.APropertyCallExpression;
011: import org.andromda.translation.ocl.node.ARelationalExpression;
012: import org.andromda.translation.ocl.node.ARelationalExpressionTail;
013: import org.andromda.translation.ocl.node.AStandardDeclarator;
014: import org.andromda.translation.ocl.node.ATypeDeclaration;
015: import org.andromda.translation.ocl.node.AVariableDeclaration;
016: import org.andromda.translation.ocl.node.AVariableDeclarationList;
017: import org.andromda.translation.ocl.node.AVariableDeclarationListTail;
018: import org.andromda.translation.ocl.node.PActualParameterList;
019: import org.andromda.translation.ocl.node.PEqualExpression;
020: import org.andromda.translation.ocl.node.PFeatureCallParameters;
021: import org.andromda.translation.ocl.node.POperation;
022: import org.andromda.translation.ocl.node.PRelationalExpression;
023: import org.andromda.translation.ocl.node.PVariableDeclaration;
024: import org.andromda.translation.ocl.node.PVariableDeclarationList;
025: import org.andromda.translation.ocl.node.TName;
026: import org.apache.commons.lang.ObjectUtils;
027: import org.apache.commons.lang.StringUtils;
028: import org.apache.log4j.Logger;
029:
030: import java.util.ArrayList;
031: import java.util.Collection;
032: import java.util.Iterator;
033: import java.util.List;
034:
035: /**
036: * Contains some utilities for concrete syntax value retrieval.
037: *
038: * @author Chad Brandon
039: */
040: public class ConcreteSyntaxUtils {
041:
042: private static final Logger logger = Logger
043: .getLogger(ConcreteSyntaxUtils.class);
044:
045: /**
046: * Iterates through the passed in list and concates all the values of objects toString value to a StringBuffer and
047: * returns the StringBuffer.
048: *
049: * @param list the List of objects to concatinate.
050: * @return StringBuffer the concatinated contents of the list.
051: */
052: public static StringBuffer concatContents(List list) {
053: StringBuffer name = new StringBuffer();
054: if (list != null) {
055: Iterator iterator = list.iterator();
056: while (iterator.hasNext()) {
057: String value = ObjectUtils.toString(iterator.next());
058: name.append(value);
059: }
060: }
061: return name;
062: }
063:
064: /**
065: * Converts the passed <code>operation</code> to an instance of <code>Operation</code> for the passed in operation.
066: *
067: * @param operation
068: * @return VariableDeclarations
069: */
070: public static OperationDeclaration getOperationDeclaration(
071: POperation operation) {
072: ExceptionUtils.checkNull("operation", operation);
073:
074: OperationDeclaration operationDeclaration = null;
075:
076: AOperation op = (AOperation) operation;
077:
078: ATypeDeclaration typeDeclaration = (ATypeDeclaration) op
079: .getReturnTypeDeclaration();
080: String returnType = null;
081: if (typeDeclaration != null) {
082: returnType = ObjectUtils
083: .toString(typeDeclaration.getType());
084: }
085:
086: operationDeclaration = new OperationDeclarationImpl(ObjectUtils
087: .toString(op.getName()), returnType,
088: ConcreteSyntaxUtils.getVariableDeclarations(operation));
089: return operationDeclaration;
090: }
091:
092: /**
093: * Retrieves all the variable declarations for the passed in <code>operation</code>.
094: *
095: * @param operation the operation for which to retrieve the variable declarations.
096: * @return VariableDeclaration[]
097: */
098: public static VariableDeclaration[] getVariableDeclarations(
099: POperation operation) {
100: ExceptionUtils.checkNull("operation", operation);
101: return ConcreteSyntaxUtils
102: .getVariableDeclarations(((AOperation) operation)
103: .getParameters());
104: }
105:
106: /**
107: * Retrieves all the variable declarations for the passed in <code>standardDeclarator</code>.
108: *
109: * @param standardDeclarator the standard declartor for which to retrieve the VariableDeclaration instances.
110: * @return VariableDeclaration[]
111: */
112: public static VariableDeclaration[] getVariableDeclarations(
113: AStandardDeclarator standardDeclarator) {
114: ExceptionUtils.checkNull("standardDeclarator",
115: standardDeclarator);
116: return ConcreteSyntaxUtils
117: .getVariableDeclarations(standardDeclarator
118: .getVariableDeclarationList());
119: }
120:
121: /**
122: * Creates a new VariableDeclaration from the passed in PVariableDeclaration.
123: *
124: * @param variableDeclaration the PVariableDeclaration that the new VariableDeclaration will be created from.
125: * @param initialValue the initial value of the variable declaration.
126: * @return VariableDeclaration the new VariableDeclaration
127: */
128: protected static VariableDeclaration newVariableDeclaration(
129: PVariableDeclaration variableDeclaration,
130: PEqualExpression initialValue) {
131: ExceptionUtils.checkNull("variableDeclaration",
132: variableDeclaration);
133:
134: AVariableDeclaration declaration = (AVariableDeclaration) variableDeclaration;
135: ATypeDeclaration typeDeclaration = (ATypeDeclaration) declaration
136: .getTypeDeclaration();
137: String type = null;
138: String name = ObjectUtils.toString(declaration.getName())
139: .trim();
140: if (typeDeclaration != null) {
141: type = ObjectUtils.toString(typeDeclaration.getType());
142: }
143: return new VariableDeclarationImpl(name, type, ObjectUtils
144: .toString(initialValue).trim());
145: }
146:
147: /**
148: * Creates an array of VariableDeclaration[] from the passed in PVariableDeclarationList.
149: *
150: * @param variableDeclarationList the PVariableDeclarationList that the new VariableDeclaration will be created
151: * from.
152: * @return VariableDeclaration[] the new VariableDeclaration array
153: */
154: public static VariableDeclaration[] getVariableDeclarations(
155: PVariableDeclarationList variableDeclarationList) {
156:
157: Collection declarations = new ArrayList();
158:
159: if (variableDeclarationList != null) {
160: AVariableDeclarationList variables = (AVariableDeclarationList) variableDeclarationList;
161:
162: if (variables != null) {
163: // add the first one
164: declarations.add(ConcreteSyntaxUtils
165: .newVariableDeclaration(variables
166: .getVariableDeclaration(), variables
167: .getVariableDeclarationValue()));
168:
169: // add the rest
170: List variableTails = variables
171: .getVariableDeclarationListTail();
172: if (variableTails != null) {
173: Iterator variableTailIt = variableTails.iterator();
174: while (variableTailIt.hasNext()) {
175: AVariableDeclarationListTail tail = (AVariableDeclarationListTail) variableTailIt
176: .next();
177: declarations
178: .add(ConcreteSyntaxUtils
179: .newVariableDeclaration(
180: tail
181: .getVariableDeclaration(),
182: tail
183: .getVariableDeclarationValue()));
184: }
185: }
186: }
187: }
188: return (VariableDeclaration[]) declarations
189: .toArray(new VariableDeclaration[0]);
190: }
191:
192: /**
193: * Gets all the parameters from the <code>featureCall</code> instance.
194: *
195: * @param featureCall the featureCall for which to retrieve the parameters
196: * @return List the list containing any parameters retrieved, or an empty array if none could be retrieved
197: */
198: public static List getParameters(AFeatureCall featureCall) {
199: List parameters = new ArrayList();
200: if (featureCall != null) {
201: parameters = getParameters(featureCall
202: .getFeatureCallParameters());
203: }
204: return parameters;
205: }
206:
207: /**
208: * Gets all the parameters from the <code>featureCall</code> instance as a comma seperated String.
209: *
210: * @param featureCall the featureCall from which to retrieve the parameters
211: * @return String the comma seperated String
212: */
213: public static String getParametersAsString(AFeatureCall featureCall) {
214: return getParametersAsString(featureCall
215: .getFeatureCallParameters());
216: }
217:
218: /**
219: * Gets all the parameters from the <code>PFeatureCallParameters</code> instance as a comma seperated String.
220: *
221: * @param featureCallParameters the featureCallParameters from which to retrieve the parameters
222: * @return String the comma seperated String
223: */
224: public static String getParametersAsString(
225: PFeatureCallParameters featureCallParameters) {
226: return StringUtils.join(ConcreteSyntaxUtils.getParameters(
227: featureCallParameters).iterator(), ",");
228: }
229:
230: /**
231: * Gets all the parameters from the <code>callParameters</code> instance.
232: *
233: * @param callParameters the callParameters for which to retrieve the parameters
234: * @return List the list containing any parameters retrieved, or an empty array if none could be retrieved
235: */
236: private static List getParameters(
237: PFeatureCallParameters callParameters) {
238: List parameters = new ArrayList();
239: if (callParameters != null) {
240: PActualParameterList parameterList = ((AFeatureCallParameters) callParameters)
241: .getActualParameterList();
242: if (parameterList != null) {
243: AActualParameterList params = (AActualParameterList) parameterList;
244:
245: // add the first param if it exists
246: String firstParam = TranslationUtils.trimToEmpty(params
247: .getExpression());
248: if (StringUtils.isNotEmpty(firstParam)) {
249: parameters.add(firstParam);
250: }
251:
252: // now add the rest of the params which are contained in the
253: // tail
254: List restOfParams = params.getCommaExpression();
255: if (restOfParams != null && !restOfParams.isEmpty()) {
256: Iterator paramIt = restOfParams.iterator();
257: while (paramIt.hasNext()) {
258: ACommaExpression parameterListTail = (ACommaExpression) paramIt
259: .next();
260: parameters.add(TranslationUtils
261: .trimToEmpty(parameterListTail
262: .getExpression()));
263: }
264: }
265: }
266: }
267: return parameters;
268: }
269:
270: /**
271: * Gets the left and right expressions of a PRelationalExpression and puts then into a List. The left expression
272: * will be the first expression in the list.
273: *
274: * @param relationalExpression
275: * @return the left and right parenthesis in [0] and [1] of the String[]
276: */
277: public static String[] getLeftAndRightExpressions(
278: PRelationalExpression relationalExpression) {
279: String[] expressions = new String[2];
280: ARelationalExpression expression = (ARelationalExpression) relationalExpression;
281:
282: // set the left expression
283: expressions[0] = TranslationUtils.trimToEmpty(expression
284: .getAdditiveExpression());
285:
286: ARelationalExpressionTail expressionTail = (ARelationalExpressionTail) expression
287: .getRelationalExpressionTail();
288:
289: // set the right expression
290: expressions[1] = TranslationUtils.trimToEmpty(expressionTail
291: .getAdditiveExpression());
292:
293: return expressions;
294: }
295:
296: /**
297: * Concatinates the type from the passed in name and pathNameTail.
298: *
299: * @param name the starting name of the type
300: * @param pathNameTail the tail pieces of the name
301: * @return String the concatinated name.
302: */
303: public static String getType(TName name, List pathNameTail) {
304: StringBuffer type = ConcreteSyntaxUtils
305: .concatContents(pathNameTail);
306: type.insert(0, TranslationUtils.trimToEmpty(name));
307: return StringUtils.deleteWhitespace(type.toString());
308: }
309:
310: /**
311: * Gets the "real" primary expression, as opposed to the primary expression retrieved from the parser syntax (since
312: * it leaves off any navigational relationships).
313: *
314: * @param expression the APosfixExpression instance for which to retrieve the primary expression
315: * @return String the "real" primary expression or the passed in expression.
316: */
317: public static String getPrimaryExpression(
318: APropertyCallExpression expression) {
319: StringBuffer primaryExpression = new StringBuffer();
320: if (expression != null) {
321: // append the first part of the primary expression
322: primaryExpression.append(TranslationUtils
323: .trimToEmpty(expression.getPrimaryExpression()));
324: List expressionTail = expression
325: .getPropertyCallExpressionTail();
326: if (expressionTail.size() > 0) {
327: Iterator expressionTailIt = expressionTail.iterator();
328: while (expressionTailIt.hasNext()) {
329: final String tail = TranslationUtils
330: .trimToEmpty(expressionTailIt.next());
331: // beak out if we encounter an arrow feature call
332: if (tail.indexOf(ARROW_FEATURE_CALL) != -1) {
333: break;
334: }
335: // only append to the expression if not an operation
336: if (tail.indexOf('(') == -1) {
337: primaryExpression.append(tail);
338: }
339: }
340: }
341: }
342: return StringUtils.deleteWhitespace(primaryExpression
343: .toString());
344: }
345:
346: /**
347: * Gets all feature calls from the passed in APropertyCallExpression instance.
348: *
349: * @param expression the APosfixExpression instance for which to retrieve the primary expression
350: * @return String the "real" primary expression of the passed in expression.
351: */
352: public static List getFeatureCalls(
353: APropertyCallExpression expression) {
354: final String methodName = "ConcreteSyntaxUtils.getFeatureCalls";
355: if (logger.isDebugEnabled()) {
356: logger.debug("performing " + methodName
357: + " with expression --> '" + expression + "'");
358: }
359: List featureCalls = new ArrayList();
360: if (expression != null) {
361: List tails = expression.getPropertyCallExpressionTail();
362: if (tails != null && !tails.isEmpty()) {
363: for (int ctr = 0; ctr < tails.size(); ctr++) {
364: featureCalls.add(TranslationUtils.getProperty(tails
365: .get(ctr), "featureCall"));
366: }
367: }
368: }
369: return featureCalls;
370: }
371:
372: /**
373: * Indicates an arrow feature call.
374: */
375: private static final String ARROW_FEATURE_CALL = "->";
376:
377: /**
378: * Gets the navigational path from the given <code>expression</code> that occurs after an arrow feature call. If the
379: * the expression contains an arrow feature call, then the navigational expression is any expression navigating on
380: * the result of an arrow feature call (otherwise it's an empty string).
381: *
382: * @param expression the expression from which to retrieve the navigational path.
383: * @return the navigational path.
384: */
385: public static String getArrowFeatureCallResultNavigationalPath(
386: APropertyCallExpression expression) {
387: StringBuffer path = new StringBuffer();
388: if (OCLPatterns
389: .isCollectionOperationResultNavigationalPath(expression)) {
390: List featureCalls = getFeatureCalls(expression);
391: int size = featureCalls.size();
392: if (size > 1) {
393: for (int ctr = 1; ctr < size; ctr++) {
394: String featureCall = TranslationUtils
395: .trimToEmpty(featureCalls.get(ctr));
396: if (featureCall.indexOf(ARROW_FEATURE_CALL) != -1
397: || featureCall.indexOf('(') != -1) {
398: break;
399: }
400: path.append(featureCall);
401: if (ctr != size - 1) {
402: path.append('.');
403: }
404: }
405: }
406: }
407: return path.toString();
408: }
409:
410: /**
411: * Loads a List of variable declaration names from the <code>variableDeclarations</code>
412: *
413: * @param variableDeclarations an array of VariableDeclaration objects
414: * @return List the list of argument names as Strings/
415: */
416: public static List getArgumentNames(
417: VariableDeclaration[] variableDeclarations) {
418: List names = new ArrayList();
419: for (int ctr = 0; ctr < variableDeclarations.length; ctr++) {
420: names.add(variableDeclarations[ctr].getName());
421: }
422: return names;
423: }
424: }
|