001package org.andromda.cartridges.spring.metafacades;
002
003import java.util.Collection;
004import java.util.Collections;
005import java.util.HashSet;
006import java.util.Set;
007import org.andromda.cartridges.spring.SpringProfile;
008import org.andromda.metafacades.uml.MetafacadeUtils;
009import org.andromda.metafacades.uml.ParameterFacade;
010import org.andromda.metafacades.uml.UMLProfile;
011import org.andromda.utils.StringUtilsHelper;
012import org.apache.commons.lang.BooleanUtils;
013import org.apache.commons.lang.ObjectUtils;
014import org.apache.commons.lang.StringUtils;
015
016/**
017 * MetafacadeLogic implementation for org.andromda.cartridges.spring.metafacades.SpringServiceOperation.
018 *
019 * @see org.andromda.cartridges.spring.metafacades.SpringServiceOperation
020 */
021public class SpringServiceOperationLogicImpl
022        extends SpringServiceOperationLogic
023{
024    private static final long serialVersionUID = 34L;
025    /**
026     * Public constructor for SpringServiceOperationLogicImpl
027     * @param metaObject
028     * @param context
029     * @see org.andromda.cartridges.spring.metafacades.SpringServiceOperation
030     */
031    public SpringServiceOperationLogicImpl(Object metaObject, String context)
032    {
033        super(metaObject, context);
034    }
035
036    /**
037     * @return hasStereotype(UMLProfile.STEREOTYPE_WEBSERVICE_OPERATION)
038     * @see org.andromda.cartridges.spring.metafacades.SpringServiceOperation#isWebserviceExposed()
039     */
040    protected boolean handleIsWebserviceExposed()
041    {
042        return this.hasStereotype(UMLProfile.STEREOTYPE_WEBSERVICE_OPERATION);
043    }
044
045    /**
046     * @return getImplementationOperationName(StringUtils.capitalize(this.getName()))
047     * or getImplementationOperationName(StringUtils.capitalize(this.getSignature())
048     * @see org.andromda.cartridges.spring.metafacades.SpringServiceOperation#getImplementationName()
049     */
050    protected String handleGetImplementationName()
051    {
052        return this.getImplementationOperationName(StringUtils.capitalize(this.getName()));
053    }
054
055    /**
056     * @return getOutgoingMessageImplementationSignature() or getOutgoingMessageImplementationSignature()
057     * @see org.andromda.cartridges.spring.metafacades.SpringServiceOperation#getImplementationSignature()
058     */
059    protected String handleGetImplementationSignature()
060    {
061        String signature = null;
062        if (this.isIncomingMessageOperation())
063        {
064            signature = this.getIncomingMessageImplementationSignature();
065        }
066        else if (this.isOutgoingMessageOperation())
067        {
068            signature = this.getOutgoingMessageImplementationSignature();
069        }
070        else
071        {
072            signature = this.getImplementationOperationName(StringUtils.capitalize(this.getSignature()));
073        }
074        return signature;
075    }
076
077    /**
078     * @see org.andromda.metafacades.uml.OperationFacade#getCall()
079     *
080     * Overridden to provide the message argument (when necessary)
081     */
082    public String getCall()
083    {
084        String call = null;
085        if (this.isIncomingMessageOperation() && this.getArguments().isEmpty())
086        {
087            call = this.getName() + "(message)";
088        }
089        else
090        {
091            call = super.getCall();
092        }
093        return call;
094    }
095
096    /**
097     * @see org.andromda.cartridges.spring.metafacades.SpringServiceOperation#getSignature(String)
098     *
099     * Overridden to provide the appropriate incoming message (if needed).
100     */
101    public String getSignature(String modifier)
102    {
103        String signature = null;
104        if (this.isIncomingMessageOperation() && this.getArguments().isEmpty())
105        {
106            signature = this.getIncomingMessageSignature(modifier);
107        }
108        else
109        {
110            signature = super.getSignature(modifier);
111        }
112        return signature;
113    }
114
115    /**
116     * @see org.andromda.cartridges.spring.metafacades.SpringServiceOperationLogic#getSignature(boolean)
117     *
118     * Overridden to provide the appropriate incoming message (if needed).
119     */
120    public String getSignature(final boolean withArgumentNames)
121    {
122        String signature = null;
123        if (this.isIncomingMessageOperation() && this.getArguments().isEmpty())
124        {
125            signature = this.getIncomingMessageSignature(null);
126        }
127        else
128        {
129            signature = super.getSignature(withArgumentNames);
130        }
131        return signature;
132    }
133
134    /**
135     *
136     * @see org.andromda.cartridges.spring.metafacades.SpringServiceOperationLogic#getSignature()
137     *
138     * Overridden to provide the appropriate incoming message (if needed).
139     */
140    public String getSignature()
141    {
142        return this.getSignature(true);
143    }
144
145    /**
146     * @return getImplementationOperationName(StringUtils.capitalize(this.getCall()))
147     * @see org.andromda.cartridges.spring.metafacades.SpringServiceOperationLogic#getImplementationCall()
148     */
149    protected String handleGetImplementationCall()
150    {
151        return this.getImplementationOperationName(StringUtils.capitalize(this.getCall()));
152    }
153
154    /**
155     * Retrieves the implementationOperatName by replacing the <code>replacement</code> in the {@link
156     * SpringGlobals#IMPLEMENTATION_OPERATION_NAME_PATTERN}
157     *
158     * @param replacement the replacement string for the pattern.
159     * @return the operation name
160     */
161    private String getImplementationOperationName(String replacement)
162    {
163        return StringUtils.trimToEmpty(String.valueOf(this.getConfiguredProperty(
164                SpringGlobals.IMPLEMENTATION_OPERATION_NAME_PATTERN))).replaceAll("\\{0\\}", replacement);
165    }
166
167    /**
168     * The transaction type for Spring service operations.
169     */
170    private static final String SERVICE_OPERATION_TRANSACTION_TYPE = "serviceOperationTransactionType";
171
172    /**
173     * @return getOwner().findTaggedValue(SpringProfile.TAGGEDVALUE_TRANSACTION_TYPE)
174     * @see org.andromda.cartridges.spring.metafacades.SpringServiceOperationLogic#getTransactionType()
175     */
176    public String handleGetTransactionType()
177    {
178        String transactionType = (String)this.findTaggedValue(SpringProfile.TAGGEDVALUE_TRANSACTION_TYPE);
179        if (StringUtils.isBlank(transactionType))
180        {
181            transactionType = (String)this.getOwner().findTaggedValue(SpringProfile.TAGGEDVALUE_TRANSACTION_TYPE);
182        }
183        if (StringUtils.isBlank(transactionType))
184        {
185            transactionType = String.valueOf(this.getConfiguredProperty(SERVICE_OPERATION_TRANSACTION_TYPE));
186        }
187        return transactionType;
188    }
189
190    /**
191     * The transaction type for EJB wrapped service operations..
192     */
193    private static final String EJB_SERVICE_OPERATION_TRANSACTION_TYPE = "ejbServiceOperationTransactionType";
194
195    /**
196     * @return EjbTransactionType
197     * @see org.andromda.cartridges.spring.metafacades.SpringServiceOperationLogic#getEjbTransactionType()
198     */
199    protected String handleGetEjbTransactionType()
200    {
201        String transactionType = (String)this.findTaggedValue(SpringProfile.TAGGEDVALUE_EJB_TRANSACTION_TYPE);
202        if (StringUtils.isBlank(transactionType))
203        {
204            transactionType = (String)this.getOwner().findTaggedValue(SpringProfile.TAGGEDVALUE_EJB_TRANSACTION_TYPE);
205        }
206        if (StringUtils.isBlank(transactionType))
207        {
208            transactionType = String.valueOf(this.getConfiguredProperty(EJB_SERVICE_OPERATION_TRANSACTION_TYPE));
209        }
210        return transactionType;
211    }
212
213    /**
214     * @return ThrowsClause
215     * @see org.andromda.cartridges.spring.metafacades.SpringServiceOperation#getThrowsClause()
216     */
217    protected String handleGetThrowsClause()
218    {
219        StringBuilder throwsClause = null;
220        if (this.isExceptionsPresent())
221        {
222            throwsClause = new StringBuilder(this.getExceptionList());
223        }
224        if (throwsClause != null)
225        {
226            throwsClause.insert(0, "throws ");
227        }
228        return throwsClause != null ? throwsClause.toString() : null;
229    }
230
231    /**
232     * @param initialExceptions
233     * @return ThrowsClause
234     * @see org.andromda.cartridges.spring.metafacades.SpringServiceOperation#getThrowsClause(String)
235     */
236    protected String handleGetThrowsClause(String initialExceptions)
237    {
238        final StringBuilder throwsClause = new StringBuilder(initialExceptions);
239        if (this.getThrowsClause() != null)
240        {
241            throwsClause.insert(0, ", ");
242            throwsClause.insert(0, this.getThrowsClause());
243        }
244        else
245        {
246            throwsClause.insert(0, "throws ");
247        }
248        return throwsClause.toString();
249    }
250
251    /**
252     * @return getMessageImplementationCall("session")
253     * @see org.andromda.cartridges.spring.metafacades.SpringServiceOperation#getOutgoingMessageImplementationCall()
254     */
255    protected String handleGetOutgoingMessageImplementationCall()
256    {
257        return this.getMessageImplementationCall("session");
258    }
259
260    private String getMessageImplementationCall(String firstArgument)
261    {
262        final StringBuilder buffer = new StringBuilder();
263        buffer.append(StringUtils.capitalize(this.getName()));
264        buffer.append('(');
265        final boolean outgoingMessageOperation = this.isOutgoingMessageOperation();
266        if (outgoingMessageOperation || (this.isIncomingMessageOperation() && this.getArguments().isEmpty()))
267        {
268            buffer.append(firstArgument);
269        }
270        final String argumentNames = this.getArgumentNames();
271        if (outgoingMessageOperation && StringUtils.isNotBlank(argumentNames))
272        {
273            buffer.append(", ");
274        }
275        if (StringUtils.isNotBlank(argumentNames))
276        {
277            buffer.append(argumentNames);
278        }
279        buffer.append(')');
280        return this.getImplementationOperationName(buffer.toString());
281    }
282
283    /**
284     * @return getMessagingImplementationSignature("javax.jms.Session session")
285     * @see org.andromda.cartridges.spring.metafacades.SpringServiceOperation#getOutgoingMessageImplementationSignature()
286     */
287    protected String handleGetOutgoingMessageImplementationSignature()
288    {
289        return this.getMessagingImplementationSignature("javax.jms.Session session");
290    }
291
292    private String getMessagingImplementationSignature(final String firstArgument)
293    {
294        return this.getMessagingOperationSignature(this.getImplementationName(), firstArgument, null);
295    }
296
297    /**
298     * Gets the signature for an incoming message operation.
299     *
300     * @return the signature
301     */
302    private String getIncomingMessageSignature(String modifier)
303    {
304        return this.getMessagingOperationSignature(this.getName(), "javax.jms.Message message", modifier);
305    }
306
307    /**
308     * Constructs the incoming or outgoing messaging operation signature given the <code>operationName</code>
309     * and the <code>firstArgument</code>.
310     *
311     * @param operationName the name of the operation.
312     * @param firstArgument the argument that will be the first argument in the operation signature.
313     * @param modifier the modifier to add to each argument (if null or empty, it isn't added).
314     * @return the signature of the operation.
315     */
316    private String getMessagingOperationSignature(final String operationName, final String firstArgument, final String modifier)
317    {
318        final StringBuilder signature = new StringBuilder(operationName);
319        signature.append('(');
320        if (StringUtils.isNotBlank(modifier))
321        {
322            signature.append(modifier).append(' ');
323        }
324        final Collection<ParameterFacade> arguments = this.getArguments();
325        final boolean outgoingMessageOperation = this.isOutgoingMessageOperation();
326        if (outgoingMessageOperation || (this.isIncomingMessageOperation() && arguments.isEmpty()))
327        {
328            signature.append(firstArgument);
329        }
330        final String argumentList = MetafacadeUtils.getTypedArgumentList(
331            this.getArguments(),
332            true,
333            modifier);
334        if (outgoingMessageOperation && StringUtils.isNotBlank(argumentList))
335        {
336            signature.append(", ");
337        }
338        if (StringUtils.isNotBlank(argumentList))
339        {
340            signature.append(argumentList);
341        }
342        signature.append(')');
343        return signature.toString();
344    }
345
346    /**
347     * @return getMessageImplementationCall("message")
348     * @see org.andromda.cartridges.spring.metafacades.SpringServiceOperation#getIncomingMessageImplementationCall()
349     */
350    protected String handleGetIncomingMessageImplementationCall()
351    {
352        return this.getMessageImplementationCall("message");
353    }
354
355    /**
356     * @return getMessagingImplementationSignature("javax.jms.Message message")
357     * @see org.andromda.cartridges.spring.metafacades.SpringServiceOperation#getIncomingMessageImplementationSignature()
358     */
359    protected String handleGetIncomingMessageImplementationSignature()
360    {
361        return this.getMessagingImplementationSignature("javax.jms.Message message");
362    }
363
364    /**
365     * @return "javax.jms.Message" or getGetterSetterReturnTypeName()
366     * @see org.andromda.cartridges.spring.metafacades.SpringServiceOperation#getImplementationReturnTypeName()
367     */
368    protected String handleGetImplementationReturnTypeName()
369    {
370        String returnTypeName = null;
371        if (this.isOutgoingMessageOperation())
372        {
373            returnTypeName = "javax.jms.Message";
374        }
375        else
376        {
377            returnTypeName = getGetterSetterReturnTypeName();
378        }
379        return returnTypeName;
380    }
381
382    /**
383     * @return FullyQualifiedMessageListenerName
384     * @see org.andromda.cartridges.spring.metafacades.SpringServiceOperation#getFullyQualifiedMessageListenerName()
385     */
386    protected String handleGetFullyQualifiedMessageListenerName()
387    {
388        StringBuilder name = new StringBuilder();
389        final String packageName = this.getPackageName();
390        if (StringUtils.isNotBlank(packageName))
391        {
392            name.append(packageName).append('.');
393        }
394        name.append(this.getMessageListenerName());
395        return name.toString();
396    }
397
398    /**
399     * @return MessageListenerName
400     * @see org.andromda.cartridges.spring.metafacades.SpringServiceOperation#getMessageListenerName()
401     */
402    protected String handleGetMessageListenerName()
403    {
404        return this.getOwner().getName() +
405            StringUtilsHelper.upperCamelCaseName(this.getName());
406    }
407
408    /**
409     * @return StringUtils.uncapitalize(this.getMessageListenerName())
410     * @see org.andromda.cartridges.spring.metafacades.SpringServiceOperation#getMessageListenerBeanName()
411     */
412    protected String handleGetMessageListenerBeanName()
413    {
414        return StringUtils.uncapitalize(this.getMessageListenerName());
415    }
416
417    /**
418     * @return getName() + MESSAGE_LISTENER_CONTAINER_SUFFIX
419     * @see org.andromda.cartridges.spring.metafacades.SpringServiceOperation#getMessageListenerContainerReferenceName()
420     */
421    protected String handleGetMessageListenerContainerReferenceName()
422    {
423        return this.getName() + MESSAGE_LISTENER_CONTAINER_SUFFIX;
424    }
425
426    /**
427     * The suffix for the listener container. "ListenerContainer"
428     */
429    private static final String MESSAGE_LISTENER_CONTAINER_SUFFIX = "ListenerContainer";
430
431    /**
432     * @return getMessageListenerBeanName() + MESSAGE_LISTENER_CONTAINER_SUFFIX
433     * @see org.andromda.cartridges.spring.metafacades.SpringServiceOperation#getMessageListenerContainerBeanName()
434     */
435    protected String handleGetMessageListenerContainerBeanName()
436    {
437        return this.getMessageListenerBeanName() + MESSAGE_LISTENER_CONTAINER_SUFFIX;
438    }
439
440    /**
441     * @return findTaggedValue(SpringProfile.TAGGEDVALUEVALUE_MESSAGING_SESSION_ACKNOWLEDGE_MODE)
442     * @see org.andromda.cartridges.spring.metafacades.SpringServiceOperation#getSessionAcknowledgeMode()
443     */
444    protected String handleGetSessionAcknowledgeMode()
445    {
446        // use the attribute name by default
447        String mode = null;
448
449        // if there is a tagged value, use it instead
450        Object value = findTaggedValue(SpringProfile.TAGGEDVALUEVALUE_MESSAGING_SESSION_ACKNOWLEDGE_MODE);
451        if (value != null)
452        {
453            mode = ObjectUtils.toString(value);
454        }
455
456        return mode;
457    }
458
459    /**
460     * @return findTaggedValue(SpringProfile.TAGGEDVALUEVALUE_ACTIVEMQ_OPTIMIZE_ACKNOWLEDGE)
461     * @see org.andromda.cartridges.spring.metafacades.SpringServiceOperation#isOptimizeAcknowledge()
462     */
463    protected boolean handleIsOptimizeAcknowledge()
464    {
465        return BooleanUtils.toBoolean(ObjectUtils.toString(this.findTaggedValue(SpringProfile.TAGGEDVALUEVALUE_ACTIVEMQ_OPTIMIZE_ACKNOWLEDGE)));
466    }
467
468    /**
469     * @return IsNullMessageConverterRequired
470     * @see org.andromda.cartridges.spring.metafacades.SpringServiceOperation#isNullMessageConverterRequired()
471     */
472    protected boolean handleIsNullMessageConverterRequired()
473    {
474        boolean result = false;
475
476        Collection<ParameterFacade> arguments = getArguments();
477        if (arguments != null && arguments.size() == 1)
478        {
479            ParameterFacade parameter = arguments.iterator().next();
480            String parameterType = parameter.getType().getFullyQualifiedName();
481
482            Set<String> jmsMessageTypes = new HashSet<String>();
483            Collections.addAll(jmsMessageTypes, SpringGlobals.jmsMessageTypes);
484
485            result = jmsMessageTypes.contains(parameterType);
486        }
487
488        return result;
489    }
490
491    /**
492     * {@inheritDoc}
493     */
494    protected boolean handleIsInitMethod()
495    {
496        return hasStereotype(SpringProfile.STEREOTYPE_POST_CONSTRUCT_METHOD);
497    }
498
499    /**
500     * {@inheritDoc}
501     */
502    protected boolean handleIsDestroyMethod()
503    {
504        return hasStereotype(SpringProfile.STEREOTYPE_PRE_DESTROY_METHOD);
505    }
506}