001: package org.andromda.metafacades.emf.uml2;
002:
003: import java.util.ArrayList;
004: import java.util.Collection;
005: import java.util.Iterator;
006: import java.util.LinkedHashSet;
007:
008: import org.andromda.metafacades.uml.ClassifierFacade;
009: import org.andromda.metafacades.uml.DependencyFacade;
010: import org.andromda.metafacades.uml.ModelElementFacade;
011: import org.andromda.metafacades.uml.NameMasker;
012: import org.andromda.metafacades.uml.ParameterFacade;
013: import org.andromda.metafacades.uml.TypeMappings;
014: import org.andromda.metafacades.uml.UMLMetafacadeProperties;
015: import org.andromda.metafacades.uml.UMLProfile;
016: import org.andromda.metafacades.uml.OperationFacade;
017: import org.andromda.translation.ocl.ExpressionKinds;
018: import org.apache.commons.collections.CollectionUtils;
019: import org.apache.commons.collections.Predicate;
020: import org.apache.commons.collections.Transformer;
021: import org.apache.commons.lang.StringUtils;
022: import org.eclipse.uml2.CallConcurrencyKind;
023: import org.eclipse.uml2.Parameter;
024: import org.eclipse.uml2.ParameterDirectionKind;
025:
026: /**
027: * MetafacadeLogic implementation for
028: * org.andromda.metafacades.uml.OperationFacade.
029: *
030: * @see org.andromda.metafacades.uml.OperationFacade
031: */
032: public class OperationFacadeLogicImpl extends OperationFacadeLogic {
033: public OperationFacadeLogicImpl(
034: final org.eclipse.uml2.Operation metaObject,
035: final String context) {
036: super (metaObject, context);
037: }
038:
039: /**
040: * Overridden to provide name masking.
041: *
042: * @see org.andromda.metafacades.uml.ModelElementFacade#getName()
043: */
044: protected String handleGetName() {
045: final String nameMask = String
046: .valueOf(this
047: .getConfiguredProperty(UMLMetafacadeProperties.OPERATION_NAME_MASK));
048: return NameMasker.mask(super .handleGetName(), nameMask);
049: }
050:
051: /**
052: * @see org.andromda.metafacades.uml.OperationFacade#getSignature()
053: */
054: protected java.lang.String handleGetSignature() {
055: return this .getSignature(true);
056: }
057:
058: /**
059: * @see org.andromda.metafacades.uml.OperationFacade#getCall()
060: */
061: protected java.lang.String handleGetCall() {
062: return this .getCall(this .getName());
063: }
064:
065: /**
066: * Constructs the operation call with the given <code>name</code>
067: *
068: * @param name
069: * the name form which to construct the operation call.
070: * @return the operation call.
071: */
072: private String getCall(final String name) {
073: StringBuffer buffer = new StringBuffer();
074: buffer.append(name);
075: buffer.append("(");
076: buffer.append(this .getArgumentNames());
077: buffer.append(")");
078: return buffer.toString();
079: }
080:
081: /**
082: * @see org.andromda.metafacades.uml.OperationFacade#getTypedArgumentList()
083: */
084: protected java.lang.String handleGetTypedArgumentList() {
085: return this .getTypedArgumentList(true);
086: }
087:
088: private String getTypedArgumentList(final boolean withArgumentNames) {
089: return this .getTypedArgumentList(withArgumentNames, null);
090: }
091:
092: /**
093: * @see org.andromda.metafacades.uml.OperationFacade#isStatic()
094: */
095: protected boolean handleIsStatic() {
096: return this .metaObject.isStatic();
097: }
098:
099: /**
100: * @see org.andromda.metafacades.uml.OperationFacade#isAbstract()
101: */
102: protected boolean handleIsAbstract() {
103: return this .metaObject.isAbstract();
104: }
105:
106: /**
107: * @see org.andromda.metafacades.uml.OperationFacade#getExceptionList()
108: */
109: protected java.lang.String handleGetExceptionList() {
110: return this .getExceptionList(null);
111: }
112:
113: /**
114: * @see org.andromda.metafacades.uml.OperationFacade#getExceptions()
115: */
116: protected Collection handleGetExceptions() {
117: Collection exceptions = new LinkedHashSet();
118:
119: // finds both exceptions and exception references
120: final class ExceptionFilter implements Predicate {
121: public boolean evaluate(Object object) {
122: boolean hasException = object instanceof DependencyFacade;
123: if (hasException) {
124: DependencyFacade dependency = (DependencyFacade) object;
125: // first check for exception references
126: hasException = dependency
127: .hasStereotype(UMLProfile.STEREOTYPE_EXCEPTION_REF);
128:
129: // if there wasn't any exception reference
130: // now check for actual exceptions
131: if (!hasException) {
132: ModelElementFacade targetElement = dependency
133: .getTargetElement();
134: hasException = targetElement != null
135: && targetElement
136: .hasStereotype(UMLProfile.STEREOTYPE_EXCEPTION);
137: }
138: }
139: return hasException;
140: }
141: }
142:
143: // first get any dependencies on this operation's
144: // owner (because these will represent the default exception(s))
145: final Collection ownerDependencies = new ArrayList(this
146: .getOwner().getSourceDependencies());
147: if (ownerDependencies != null && !ownerDependencies.isEmpty()) {
148: CollectionUtils.filter(ownerDependencies,
149: new ExceptionFilter());
150: exceptions.addAll(ownerDependencies);
151: }
152:
153: final Collection operationDependencies = new ArrayList(this
154: .getSourceDependencies());
155: // now get any exceptions directly on the operation
156: if (operationDependencies != null
157: && !operationDependencies.isEmpty()) {
158: CollectionUtils.filter(operationDependencies,
159: new ExceptionFilter());
160: exceptions.addAll(operationDependencies);
161: }
162:
163: // now transform the dependency(s) to the actual exception(s)
164: CollectionUtils.transform(exceptions, new Transformer() {
165: public Object transform(Object object) {
166: return ((DependencyFacade) object).getTargetElement();
167: }
168: });
169:
170: // finally add in any members of the UML2 RaisedException list
171: // (the 'proper' UML2 way of doing exceptions .. or at least one way).
172: Collection raisedExceptions = this .metaObject
173: .getRaisedExceptions();
174: exceptions.addAll(this .shieldedElements(raisedExceptions));
175:
176: return exceptions;
177: }
178:
179: /**
180: * @see org.andromda.metafacades.uml.OperationFacade#isReturnTypePresent()
181: */
182: protected boolean handleIsReturnTypePresent() {
183: boolean hasReturnType = false;
184: if (this .getReturnType() != null) {
185: hasReturnType = !StringUtils.trimToEmpty(
186: this .getReturnType().getFullyQualifiedName(true))
187: .equals(UMLProfile.VOID_TYPE_NAME);
188: }
189: return hasReturnType;
190: }
191:
192: /**
193: * @see org.andromda.metafacades.uml.OperationFacade#isExceptionsPresent()
194: */
195: protected boolean handleIsExceptionsPresent() {
196: return !this .getExceptions().isEmpty();
197: }
198:
199: /**
200: * @see org.andromda.metafacades.uml.OperationFacade#getArgumentNames()
201: */
202: protected java.lang.String handleGetArgumentNames() {
203: StringBuffer buffer = new StringBuffer();
204:
205: Iterator iterator = this .metaObject.getOwnedParameters()
206: .iterator();
207:
208: boolean commaNeeded = false;
209: while (iterator.hasNext()) {
210: Parameter parameter = (Parameter) iterator.next();
211:
212: if (!parameter.getDirection().equals(
213: ParameterDirectionKind.RETURN_LITERAL)) {
214: if (commaNeeded) {
215: buffer.append(", ");
216: }
217: buffer.append(parameter.getName());
218: commaNeeded = true;
219: }
220: }
221: return buffer.toString();
222: }
223:
224: /**
225: * @see org.andromda.metafacades.uml.OperationFacade#getArgumentTypeNames()
226: */
227: protected java.lang.String handleGetArgumentTypeNames() {
228: StringBuffer buffer = new StringBuffer();
229:
230: Iterator iterator = this .metaObject.getOwnedParameters()
231: .iterator();
232:
233: boolean commaNeeded = false;
234: while (iterator.hasNext()) {
235: Parameter parameter = (Parameter) iterator.next();
236:
237: if (!parameter.getDirection().equals(
238: ParameterDirectionKind.RETURN_LITERAL)) {
239: if (commaNeeded) {
240: buffer.append(", ");
241: }
242: ParameterFacade facade = (ParameterFacade) this
243: .shieldedElement(parameter);
244: buffer.append(facade.getType().getFullyQualifiedName());
245: commaNeeded = true;
246: }
247: }
248: return buffer.toString();
249: }
250:
251: /**
252: * @see org.andromda.metafacades.uml.OperationFacade#isQuery()
253: */
254: protected boolean handleIsQuery() {
255: return this .metaObject.isQuery();
256: }
257:
258: /**
259: * @see org.andromda.metafacades.uml.OperationFacade#getConcurrency()
260: */
261: protected java.lang.String handleGetConcurrency() {
262: String concurrency = null;
263:
264: final CallConcurrencyKind concurrencyKind = this .metaObject
265: .getConcurrency();
266: if (concurrencyKind == null
267: || concurrencyKind
268: .equals(CallConcurrencyKind.CONCURRENT_LITERAL)) {
269: concurrency = "concurrent";
270: } else if (concurrencyKind
271: .equals(CallConcurrencyKind.GUARDED_LITERAL)) {
272: concurrency = "guarded";
273: } else// CallConcurrencyKindEnum.CCK_SEQUENTIAL
274: {
275: concurrency = "sequential";
276: }
277:
278: final TypeMappings languageMappings = this
279: .getLanguageMappings();
280: if (languageMappings != null) {
281: concurrency = languageMappings.getTo(concurrency);
282: }
283:
284: return concurrency;
285: }
286:
287: /**
288: * Gets the pattern for constructing the precondition name.
289: *
290: * @return the precondition pattern.
291: */
292: private String getPreconditionPattern() {
293: return String
294: .valueOf(this
295: .getConfiguredProperty(UMLMetafacadeProperties.PRECONDITION_NAME_PATTERN));
296: }
297:
298: /**
299: * Gets the pattern for constructing the postcondition name.
300: *
301: * @return the postcondition pattern.
302: */
303: private String getPostconditionPattern() {
304: return String
305: .valueOf(this
306: .getConfiguredProperty(UMLMetafacadeProperties.POSTCONDITION_NAME_PATTERN));
307: }
308:
309: /**
310: * @see org.andromda.metafacades.uml.OperationFacade#getPreconditionName()
311: */
312: protected java.lang.String handleGetPreconditionName() {
313: return this .getPreconditionPattern().replaceAll("\\{0\\}",
314: this .getName());
315: }
316:
317: /**
318: * @see org.andromda.metafacades.uml.OperationFacade#getPostconditionName()
319: */
320: protected java.lang.String handleGetPostconditionName() {
321: return this .getPostconditionPattern().replaceAll("\\{0\\}",
322: this .getName());
323: }
324:
325: /**
326: * @see org.andromda.metafacades.uml.OperationFacade#getPreconditionSignature()
327: */
328: protected java.lang.String handleGetPreconditionSignature() {
329: return this
330: .getSignature(this .getPreconditionName(), true, null);
331: }
332:
333: /**
334: * @see org.andromda.metafacades.uml.OperationFacade#getPreconditionCall()
335: */
336: protected java.lang.String handleGetPreconditionCall() {
337: return this .getCall(this .getPreconditionName());
338: }
339:
340: /**
341: * @see org.andromda.metafacades.uml.OperationFacade#isPreconditionsPresent()
342: */
343: protected boolean handleIsPreconditionsPresent() {
344: final Collection preconditions = this .getPreconditions();
345: return preconditions != null && !preconditions.isEmpty();
346: }
347:
348: /**
349: * @see org.andromda.metafacades.uml.OperationFacade#isPostconditionsPresent()
350: */
351: protected boolean handleIsPostconditionsPresent() {
352: final Collection postconditions = this .getPostconditions();
353: return postconditions != null && !postconditions.isEmpty();
354: }
355:
356: /**
357: * @see org.andromda.metafacades.uml.OperationFacade#findTaggedValue(java.lang.String,
358: * boolean)
359: */
360: protected java.lang.Object handleFindTaggedValue(
361: java.lang.String name, final boolean follow) {
362: name = StringUtils.trimToEmpty(name);
363: Object value = this .findTaggedValue(name);
364: if (follow) {
365: ClassifierFacade type = this .getReturnType();
366: while (value == null && type != null) {
367: value = type.findTaggedValue(name);
368: type = (ClassifierFacade) type.getGeneralization();
369: }
370: }
371: return value;
372: }
373:
374: /**
375: * @see org.andromda.metafacades.uml.OperationFacade#getExceptionList(java.lang.String)
376: */
377: protected java.lang.String handleGetExceptionList(
378: java.lang.String initialExceptions) {
379: initialExceptions = StringUtils.trimToEmpty(initialExceptions);
380: StringBuffer exceptionList = new StringBuffer(initialExceptions);
381: Collection exceptions = this .getExceptions();
382: if (exceptions != null && !exceptions.isEmpty()) {
383: if (StringUtils.isNotEmpty(initialExceptions)) {
384: exceptionList.append(", ");
385: }
386: Iterator exceptionIt = exceptions.iterator();
387: while (exceptionIt.hasNext()) {
388: ModelElementFacade exception = (ModelElementFacade) exceptionIt
389: .next();
390: exceptionList.append(exception.getFullyQualifiedName());
391: if (exceptionIt.hasNext()) {
392: exceptionList.append(", ");
393: }
394: }
395: }
396:
397: return exceptionList.toString();
398: }
399:
400: /**
401: * @see org.andromda.metafacades.uml.OperationFacade#getSignature(boolean)
402: */
403: protected java.lang.String handleGetSignature(
404: final boolean withArgumentNames) {
405: return this .getSignature(this .getName(), withArgumentNames,
406: null);
407: }
408:
409: /**
410: * @see org.andromda.metafacades.uml.OperationFacade#getSignature(String,
411: * boolean, String)
412: */
413: private String getSignature(final String name,
414: final boolean withArgumentNames,
415: final String argumentModifier) {
416: StringBuffer signature = new StringBuffer(name);
417: signature.append("(");
418: signature.append(this .getTypedArgumentList(withArgumentNames,
419: argumentModifier));
420: signature.append(")");
421: return signature.toString();
422: }
423:
424: /**
425: * @see org.andromda.metafacades.uml.OperationFacade#getTypedArgumentList(boolean,
426: * String)
427: */
428: private String getTypedArgumentList(
429: final boolean withArgumentNames, final String modifier) {
430: StringBuffer buffer = new StringBuffer();
431: Iterator parameterIterator = this .metaObject
432: .getOwnedParameters().iterator();
433:
434: boolean commaNeeded = false;
435: while (parameterIterator.hasNext()) {
436: Parameter paramter = (Parameter) parameterIterator.next();
437:
438: if (paramter.isException()) {
439: continue;
440: }
441:
442: if (!paramter.getDirection().equals(
443: ParameterDirectionKind.RETURN_LITERAL)) {
444: String type = null;
445: if (paramter.getType() == null) {
446: this .logger
447: .error("ERROR! No type specified for parameter --> '"
448: + paramter.getName()
449: + "' on operation --> '"
450: + this .getName()
451: + "', please check your model");
452: } else {
453: ClassifierFacade theType = (ClassifierFacade) this
454: .shieldedElement(paramter.getType());
455: if (paramter.isMultivalued()) {
456: type = theType.getFullyQualifiedName() + "[]";
457: } else {
458: type = theType.getFullyQualifiedName();
459: }
460: }
461:
462: if (commaNeeded) {
463: buffer.append(", ");
464: }
465: if (StringUtils.isNotBlank(modifier)) {
466: buffer.append(modifier);
467: buffer.append(" ");
468: }
469: buffer.append(type);
470: if (withArgumentNames) {
471: buffer.append(" ");
472: buffer.append(paramter.getName());
473: }
474: commaNeeded = true;
475: }
476: }
477: return buffer.toString();
478: }
479:
480: /**
481: * @see org.andromda.metafacades.uml.OperationFacade#getTypedArgumentList(java.lang.String)
482: */
483: protected java.lang.String handleGetTypedArgumentList(
484: final java.lang.String modifier) {
485: return this .getTypedArgumentList(true, modifier);
486: }
487:
488: /**
489: * @see org.andromda.metafacades.uml.OperationFacade#getSignature(java.lang.String)
490: */
491: protected java.lang.String handleGetSignature(
492: final java.lang.String argumentModifier) {
493: return this
494: .getSignature(this .getName(), true, argumentModifier);
495: }
496:
497: /**
498: * @see org.andromda.metafacades.uml.OperationFacade#getOwner()
499: */
500: protected java.lang.Object handleGetOwner() {
501: return this .metaObject.getOwner();
502: }
503:
504: /**
505: * @see org.andromda.metafacades.uml.OperationFacade#getParameters()
506: */
507: protected java.util.Collection handleGetParameters() {
508: final Collection params = new ArrayList(this .metaObject
509: .getOwnedParameters());
510: params.addAll(this .metaObject.getReturnResults());
511: CollectionUtils.filter(params, new Predicate() {
512: public boolean evaluate(final Object object) {
513: return !((Parameter) object).isException();
514: }
515: });
516: return params;
517: }
518:
519: /**
520: * @see org.andromda.metafacades.uml.OperationFacade#getReturnType()
521: */
522: protected java.lang.Object handleGetReturnType() {
523: return this .metaObject.getType();
524: }
525:
526: /**
527: * @see org.andromda.metafacades.uml.OperationFacade#getArguments()
528: */
529: protected java.util.Collection handleGetArguments() {
530: final Collection arguments = new ArrayList(this .metaObject
531: .getOwnedParameters());
532: CollectionUtils.filter(arguments, new Predicate() {
533: public boolean evaluate(final Object object) {
534: Parameter p = (Parameter) object;
535: return !p.getDirection().equals(
536: ParameterDirectionKind.RETURN_LITERAL)
537: && !p.isException();
538: }
539: });
540: return arguments;
541: }
542:
543: /**
544: * @see org.andromda.metafacades.uml.OperationFacade#getPreconditions()
545: */
546: protected java.util.Collection handleGetPreconditions() {
547: return this .getConstraints(ExpressionKinds.PRE);
548: }
549:
550: /**
551: * @see org.andromda.metafacades.uml.OperationFacade#getPostconditions()
552: */
553: protected java.util.Collection handleGetPostconditions() {
554: return this .getConstraints(ExpressionKinds.POST);
555: }
556:
557: /**
558: * @see org.andromda.core.metafacade.MetafacadeBase#getValidationOwner()
559: */
560: public Object getValidationOwner() {
561: return this .getOwner();
562: }
563:
564: /**
565: * @see org.andromda.metafacades.emf.uml2.OperationFacade#findParameter(java.lang.String)
566: */
567: protected ParameterFacade handleFindParameter(final String name) {
568: return (ParameterFacade) this .shieldedElement(this .metaObject
569: .getOwnedParameter(name));
570: }
571:
572: /**
573: * Get the UML upper multiplicity Not implemented for UML1.4
574: */
575: protected int handleGetUpper() {
576: // MD11.5 Exports multiplicity as String
577: return UmlUtilities.parseMultiplicity(this .metaObject
578: .getUpperValue());
579: }
580:
581: /**
582: * Get the UML lower multiplicity Not implemented for UML1.4
583: */
584: protected int handleGetLower() {
585: // MD11.5 Exports multiplicity as String
586: return UmlUtilities.parseMultiplicity(this .metaObject
587: .getLowerValue());
588: }
589:
590: /**
591: * Get the first UML2 ReturnResult parameter. Not implemented for UML1.4
592: */
593: public ParameterFacade handleGetReturnParameter() {
594: Collection returnResults = this .metaObject.getReturnResults();
595: return (ParameterFacade) this .shieldedElement(returnResults
596: .iterator().next());
597: }
598:
599: protected boolean handleIsOverriding() {
600: return this .getOverriddenOperation() != null;
601: }
602:
603: protected Object handleGetOverriddenOperation() {
604: OperationFacade overriddenOperation = null;
605:
606: final String signature = this .getSignature(false);
607:
608: ClassifierFacade ancestor = this .getOwner().getSuperClass();
609: while (overriddenOperation == null && ancestor != null) {
610: for (Iterator operationIterator = ancestor.getOperations()
611: .iterator(); overriddenOperation == null
612: && operationIterator.hasNext();) {
613: final OperationFacade ancestorOperation = (OperationFacade) operationIterator
614: .next();
615: if (signature.equals(ancestorOperation
616: .getSignature(false))) {
617: overriddenOperation = ancestorOperation;
618: }
619: }
620:
621: ancestor = ancestor.getSuperClass();
622: }
623:
624: return overriddenOperation;
625: }
626: }
|