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