View Javadoc
1   /*
2    * #%L
3    * ToPIA :: Persistence
4    * $Id$
5    * $HeadURL$
6    * %%
7    * Copyright (C) 2004 - 2016 CodeLutin
8    * %%
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU Lesser General Public License as 
11   * published by the Free Software Foundation, either version 3 of the 
12   * License, or (at your option) any later version.
13   * 
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Lesser Public License for more details.
18   * 
19   * You should have received a copy of the GNU General Lesser Public 
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
22   * #L%
23   */
24  
25  package org.nuiton.topia.generator;
26  
27  import org.apache.commons.lang3.StringUtils;
28  import org.apache.commons.logging.Log;
29  import org.apache.commons.logging.LogFactory;
30  import org.codehaus.plexus.component.annotations.Component;
31  import org.nuiton.eugene.GeneratorUtil;
32  import org.nuiton.eugene.Template;
33  import org.nuiton.eugene.java.ObjectModelTransformerToJava;
34  import org.nuiton.eugene.models.object.ObjectModel;
35  import org.nuiton.eugene.models.object.ObjectModelClass;
36  import org.nuiton.eugene.models.object.ObjectModelInterface;
37  import org.nuiton.eugene.models.object.ObjectModelJavaModifier;
38  import org.nuiton.eugene.models.object.ObjectModelModifier;
39  import org.nuiton.eugene.models.object.ObjectModelOperation;
40  import org.nuiton.eugene.models.object.ObjectModelParameter;
41  import org.nuiton.i18n.I18n;
42  import org.nuiton.topia.TopiaContext;
43  import org.nuiton.topia.TopiaException;
44  
45  import java.util.ArrayList;
46  import java.util.LinkedHashMap;
47  import java.util.Map;
48  
49  /*{generator option: parentheses = false}*/
50  
51  /*{generator option: writeString = +}*/
52  
53  /**
54   * This Template is used to create the skeleton of services for a final
55   * application which using Topia. 
56   * <div>
57   * Generation from interfaces with stereotype &lt;&lt;service&gt;&gt; :
58   *  <ul>
59   *    <li>Service : interface of the service defined in model.</li>
60   *    <li><p>ServiceAbstract : abstract class which contains :</p>
61   *        <p>* treateError : abstract method used to catch all exception from a
62   *          service method.</p>
63   *        <p>* closeTransaction : abstract method used to finally the try/catch
64   *          of a service method</p>
65   *        <p>* beginTransaction : abstract method used to start the transaction
66   *          using rootContext.</p>
67   *        <p>* constructor with AppContextImplementor in argument</p>
68   *        <p>* for each method : the implementation of the method (skeleton with
69   *          try/catch and beginTransaction call to open a new TopiaContext from
70   *          AppContextImplementor). Usage of i18n keys for error messages in
71   *          exception.</p>
72   *        <p>* for each method : an abstract method used to execute the business
73   *          code of the method : need to be implemented in subclass.</p>
74   *    </li>
75   *  </ul>
76   * </div>
77   * <div>
78   * Exemple of ServiceImpl utils method implementation. (The AppException
79   * is considered if defined in model tagvalue "exceptionClass") :
80   * <pre>
81   *   public class ServiceImpl implements ServiceAbstract  {
82   *
83   *      // properties for Topia configuration
84   *      protected Properties properties;
85   *      ...
86   * 
87   *      &#64;Override
88   *      public void treateError(TopiaContext transaction, Exception eee,
89   *              String message, Object... args) throws AppException {
90   *
91   *          // Note that the message from service doesn't directly use _() for
92   *          // i18 messages but n_(). In this log, the _() is used to translate
93   *          // correctly the message. But the message must be translate when
94   *          // catching the AppException in UI.
95   *          if (log.isErrorEnabled()) {
96   *              log.error(_(message, args), eee);
97   *          }
98   *
99   *          // rollback of current transaction
100  *          if (transaction != null) {
101  *              try {
102  *                  transaction.rollbackTransaction();
103  *              } catch (TopiaException ex) {
104  *                  if (log.isErrorEnabled()) {
105  *                      log.error(_("app.error.context.rollback"), ex);
106  *                  }
107  *              }
108  *          }
109  *          // wrapping the exception in a AppException with message and
110  *          // arguments for i18n translation
111  *          throw new AppException(eee, message, args);
112  *      }
113  *
114  *      &#64;Override
115  *      public void closeTransaction(TopiaContext transaction) {
116  *          if (transaction != null) {
117  *              try {
118  *                  transaction.closeContext();
119  *              } catch (TopiaException eee) {
120  *                  if (log.isErrorEnabled()) {
121  *                      log.error(_("app.error.context.close"), eee);
122  *                  }
123  *              }
124  *          }
125  *      }
126  *
127  *      &#64;Override
128  *      public TopiaContext beginTransaction() throws TopiaException {
129  *          TopiaContext rootContext = null;
130  *          try {
131  *              // You have to manage the properties using ApplicationConfig
132  *              // or other lib to have configuration for Topia
133  *              rootContext = TopiaContextFactory.getContext(properties);
134  *
135  *              return getTopiaRootContext().beginTransaction();
136  *
137  *          // only catch exception for rootContext
138  *          } catch (TopiaNotFoundException eee) {
139  *              treateError(eee, n_("app.error.context.getTopiaRootContext"));
140  *          }
141  *          return null;
142  *      }
143  *
144  *      // Implementation of abstract method, the interface method is
145  *      // called 'createMyEntity(MyEntity entity)' in this case.
146  *      &#64;Override
147  *      public void executeCreateMyEntity(TopiaContext transaction, 
148  *                      MyEntity entity) throws TopiaException {
149  *
150  *          MyEntityDAO dao = AppDAOHelper.getMyEntityDAO(transaction);
151  *          dao.create(entity);
152  *          // That's it, no need to manage errors or transaction, the abstract
153  *          // service will do this job.
154  *      }
155  * }
156  * </pre>
157  * </div>
158  * <div>
159  * <h2>TAG_TRANSACTION</h2>
160  * <p>Default value : true</p>
161  * <p>You can use the tagValue 'transaction=false' to specify that a method
162  * doesn't need any TopiaContext, so no need to instantiate a new one.
163  * This tagValue can only be put directly in the model and not in properties
164  * file (because of multiple methods with same name problem).</p>
165  * </div>
166  * <div>
167  * <h2>TAG_ERROR_ARGS</h2>
168  * <p>Default value : false</p>
169  * <p>You can use the tagValue 'errorArgs=true' to specify that a method
170  * need arguments for error message. This tagValue can only be put directly
171  * in the model and not in properties file.</p>
172  * </div>
173  * <div>
174  * <h2>TAG_EXCEPTION_CLASS</h2>
175  * <p>Default value : null</p>
176  * <p>You can use the tagValue 'exceptionClass=my.exception.full.qualified.Name'
177  * to specify that all contract methods will throw this exception.</p>
178  * </div>
179  * <p>It is smooth, isn't it :p ?</p>
180  * <p>
181  *
182  * Created: 23 mars 2010
183  *
184  * @author fdesbois &lt;fdesbois@codelutin.com&gt;
185  * @version $Id$
186  * @since 2.3.1
187  */
188 // TODO : may be refactor to integrate JTA or webservice or may be not in this transformer.
189 @Component(role = Template.class, hint = "org.nuiton.topia.generator.ServiceTransformer")
190 public class ServiceTransformer extends ObjectModelTransformerToJava {
191 
192 
193     private static final Log log = LogFactory.getLog(ServiceTransformer.class);
194     protected String modelName;
195 
196     protected String defaultPackageName;
197 
198     protected String exceptionName;
199 
200     private static final String OP_NAME_BEGIN_TRANSACTION = "beginTransaction";
201 
202     private static final String OP_NAME_COMMIT_TRANSACTION = "commitTransaction";
203 
204     private static final String OP_NAME_CLOSE_TRANSACTION = "closeTransaction";
205 
206     private static final String OP_NAME_TREATE_ERROR = "treateError";
207 
208     public static final String PARAMETER_TRANSACTION = "transaction";
209 
210     protected String getServiceAbstractClassName(String serviceName) {
211         return serviceName + "Abstract";
212     }
213 
214     @Override
215     public void transformFromModel(ObjectModel model) {
216         exceptionName =  TopiaGeneratorUtil.getExceptionClassTagValue(model);
217         modelName = model.getName();
218     }
219 
220     @Override
221     public void transformFromInterface(ObjectModelInterface input) {
222         if (!TopiaGeneratorUtil.hasServiceStereotype(input)) {
223             return;
224         }
225 
226         // global transaction needed (if set to false then never use transaction)
227         boolean needTransaction = isTransactionNeeded(input);
228 
229         ObjectModelInterface serviceContract = createServiceContract(input);
230 
231         createServiceAbstract(input,
232                               serviceContract,
233                               needTransaction);
234     }
235 
236     /**
237      * Create the service contract using {@code source} interface defined
238      * in model.
239      *
240      * @param source interface from model
241      * @return the ObjectModelInterface created
242      */
243     protected ObjectModelInterface createServiceContract(
244             ObjectModelInterface source) {
245 
246         ObjectModelInterface serviceContract =
247                 createInterface(source.getName(), source.getPackageName());
248 
249         setDocumentation(serviceContract, source.getDocumentation());
250         for (ObjectModelOperation op : source.getOperations()) {
251             ObjectModelOperation newOp = addOperation(serviceContract,
252                                                       op.getName(),
253                                                       op.getReturnType()
254             );
255             setDocumentation(newOp.getReturnParameter(),
256                              op.getReturnParameter().getDocumentation()
257             );
258             for (ObjectModelParameter param : op.getParameters()) {
259                 ObjectModelParameter newParam = addParameter(newOp,
260                                                              param.getType(),
261                                                              param.getName()
262                 );
263                 setDocumentation(newParam, param.getDocumentation());
264             }
265             for (String ex : op.getExceptions()) {
266                 addException(newOp, ex);
267             }
268             if (exceptionName != null) {
269                 addException(newOp, exceptionName);
270             }
271             setDocumentation(newOp, op.getDocumentation());
272         }
273         return serviceContract;
274     }
275 
276     protected void createBeginTransactionMethod(ObjectModelInterface source,
277                                          ObjectModelInterface serviceContract,
278                                          ObjectModelClass serviceAbstract) {
279         ObjectModelOperation operation =
280                     addOperation(serviceAbstract, OP_NAME_BEGIN_TRANSACTION,
281                                  TopiaContext.class,
282                                  ObjectModelJavaModifier.ABSTRACT,
283                                  ObjectModelJavaModifier.PROTECTED);
284             addException(operation, TopiaException.class);
285     }
286 
287     protected void createCommitTransactionMethod(ObjectModelClass serviceAbstract) {
288         ObjectModelOperation operation =
289                     addOperation(serviceAbstract,
290                                  OP_NAME_COMMIT_TRANSACTION,
291                                  "void",
292                                  ObjectModelJavaModifier.PROTECTED);
293         addParameter(operation, TopiaContext.class, PARAMETER_TRANSACTION);
294         addException(operation, TopiaException.class);
295         setOperationBody(operation,""
296 /*{
297         transaction.commitTransaction();
298 }*/
299         );
300 
301     }
302 
303     protected void createCloseTransactionMethod(ObjectModelInterface source,
304                                          ObjectModelInterface serviceContract,
305                                          ObjectModelClass serviceAbstract) {
306         ObjectModelOperation operation =
307                         addOperation(serviceAbstract,
308                                      OP_NAME_CLOSE_TRANSACTION,
309                                      "void",
310                                      ObjectModelJavaModifier.ABSTRACT,
311                                      ObjectModelJavaModifier.PROTECTED);
312                 addParameter(operation, TopiaContext.class, PARAMETER_TRANSACTION);
313                 addException(operation, TopiaException.class);
314     }
315 
316     protected void createTreateErrorMethod(ObjectModelInterface source,
317                                          ObjectModelInterface serviceContract,
318                                          ObjectModelClass serviceAbstract,
319                                          boolean needTransaction) {
320 
321         ObjectModelOperation treateError1 =
322                 addOperation(serviceAbstract,
323                              OP_NAME_TREATE_ERROR,
324                              "void",
325                              ObjectModelJavaModifier.ABSTRACT,
326                              ObjectModelJavaModifier.PROTECTED);
327         if (needTransaction) {
328             addParameter(treateError1, TopiaContext.class, PARAMETER_TRANSACTION);
329         }
330         addParameter(treateError1, Exception.class, "eee");
331         addParameter(treateError1, String.class, "message");
332         addParameter(treateError1, "Object...", "args");
333         if (exceptionName != null) {
334             addException(treateError1, exceptionName);
335         }
336 
337         if (needTransaction) {
338             ObjectModelOperation treateError2 =
339                     addOperation(serviceAbstract, OP_NAME_TREATE_ERROR, "void",
340                             ObjectModelJavaModifier.PROTECTED);
341             addParameter(treateError2, Exception.class, "eee");
342             addParameter(treateError2, String.class, "message");
343             addParameter(treateError2, "Object...", "args");
344             if (exceptionName != null) {
345                 addException(treateError2, exceptionName);
346             }
347 
348             setOperationBody(treateError2, ""
349         /*{
350             treateError(null, eee, message, args);
351         }*/
352             );
353         }
354     }
355     /**
356      * Create the service abstract for {@code serviceContract}
357      * using {@code source} interface defined
358      * in model.
359      *
360      * @param source interface from model
361      * @param serviceContract to implement
362      * @param needTransaction flag to know if service globally use transaction
363      */
364     protected void createServiceAbstract(ObjectModelInterface source,
365                                          ObjectModelInterface serviceContract,
366                                          boolean needTransaction) {
367 
368         ObjectModelClass serviceAbstract = createAbstractClass(
369                 getServiceAbstractClassName(serviceContract.getName()),
370                         serviceContract.getPackageName());
371 
372         // Imports for implementations
373         if (needTransaction) {
374             addImport(serviceAbstract, TopiaContext.class);
375         }
376         addImport(serviceAbstract, I18n.class);
377 
378         // Implements contract interface
379         addInterface(serviceAbstract, serviceContract.getQualifiedName());
380 
381         // Create abstract methods
382         
383         if (needTransaction) {
384             createBeginTransactionMethod(source,
385                                          serviceContract,
386                                          serviceAbstract);
387 
388             createCommitTransactionMethod(serviceAbstract);
389             
390             createCloseTransactionMethod(source,
391                                          serviceContract,
392                                          serviceAbstract);
393         }
394 
395         createTreateErrorMethod(source,
396                                 serviceContract,
397                                 serviceAbstract,
398                                 needTransaction
399         );
400 
401         // keep execute methods (we want to generate them at the top of the
402         // class since they are all abstract)
403         // Note: using a LinkedHashMap permits to keep incoming order
404         Map<ObjectModelOperation, ObjectModelOperation> abstractExecuteMethods =
405                 new LinkedHashMap<ObjectModelOperation, ObjectModelOperation>();
406 
407         // first generate the abstract execute methods
408         for (ObjectModelOperation operation : source.getOperations()) {
409 
410             ObjectModelOperation executeOp = createOperationExecuteAbstract(
411                     serviceAbstract,
412                     operation,
413                     needTransaction
414             );
415             
416             abstractExecuteMethods.put(operation , executeOp);
417         }
418 
419         // Then generates the real operation which boxes the execute methods
420         for (Map.Entry<ObjectModelOperation, ObjectModelOperation> entry :
421                 abstractExecuteMethods.entrySet()) {
422             ObjectModelOperation operation = entry.getKey();
423             ObjectModelOperation executeOperation = entry.getValue();
424             createOperationImplementation(
425                     serviceAbstract,
426                     executeOperation,
427                     operation,
428                     source.getName(),
429                     needTransaction
430             );
431         }
432     }
433 
434     /**
435      * Create an operation abstract to execute in contract implementation.
436      * You can use tagvalues "errorArgs" (default = false) and "transaction"
437      * (default = true) to generate appropriate parameters. This abstract
438      * method will throw all exceptions (Exception.class). This is the method
439      * which will be implemented by the developper in service implementation
440      * class.
441      *
442      * @param serviceAbstract where the operation will be created
443      * @param source ObjectModelOperation from model
444      * @param needTransaction flag to know if service globally use transaction
445      * @return the abstract operation created
446      * @see #isErrorArgsNeeded(ObjectModelOperation)
447      * @see #isTransactionNeeded(ObjectModelOperation)
448      * @see #isTransactionNeeded(ObjectModelInterface)
449      */
450     protected ObjectModelOperation createOperationExecuteAbstract(
451             ObjectModelClass serviceAbstract,
452             ObjectModelOperation source,
453             boolean needTransaction) {
454         String opName = StringUtils.capitalize(source.getName());
455 
456         // Abstract operation to execute method content
457         ObjectModelOperation executeOperation =
458                 addOperation(serviceAbstract, "execute" + opName,
459                         source.getReturnType(),
460                         ObjectModelJavaModifier.ABSTRACT,
461                         ObjectModelJavaModifier.PROTECTED);
462 
463         // Throw all exception from abstract method
464         // They will be catched by interface method to use treateError
465         addException(executeOperation, Exception.class);
466 
467         if (needTransaction && isTransactionNeeded(source)) {
468             addParameter(executeOperation, TopiaContext.class, PARAMETER_TRANSACTION);
469         }
470 
471         if (isErrorArgsNeeded(source)) {
472             // Add errorArgs to abstract operation
473             addParameter(executeOperation, "java.util.List<Object>", "errorArgs");
474         }
475 
476         // Copy other operation parameters
477         for (ObjectModelParameter param : source.getParameters()) {
478             addParameter(executeOperation, param.getType(), param.getName());
479         }
480         return executeOperation;
481     }
482 
483     /**
484      * Create an operation implementation. This is the skeleton of the operation
485      * defined from model. This will put a try/catch block over an abstract
486      * method {@code abstOp}. You can use tagvalues "errorArgs" and
487      * "transaction" for abstract method parameters to call. If the transaction
488      * is needed, this will use the beginTransaction() and closeTransaction()
489      * methods defined in {@code serviceAbstract} class.
490      *
491      * @param serviceAbstract where the operation will be created
492      * @param abstOp to execute into the implementation body
493      * @param source ObjectModelOperation from model
494      * @param serviceContractName where the signature method is defined
495      * @param needTransaction flag to know if service globally use transaction
496      * @see #isErrorArgsNeeded(ObjectModelOperation)
497      * @see #isTransactionNeeded(ObjectModelInterface)
498      */
499     protected void createOperationImplementation(
500             ObjectModelClass serviceAbstract,
501             ObjectModelOperation abstOp,
502             ObjectModelOperation source,
503             String serviceContractName,
504             boolean needTransaction) {
505 
506         // boolean to specify if the method need a transaction or not
507         // Default set to true but can be override by a tagvalue on the
508         // method
509         needTransaction &= isTransactionNeeded(source);
510 
511         // boolean to specify if the method need error arguments or not
512         // Default set to true but can be override by a tagvalue on the
513         // method
514         boolean needErrorArgs = isErrorArgsNeeded(source);
515 
516         // Implementation of interface operation
517         ObjectModelOperation implOp =
518                 addOperation(serviceAbstract,
519                              source.getName(),
520                              source.getReturnType(),
521                              ObjectModelJavaModifier.PUBLIC);
522 
523         addAnnotation(serviceAbstract, implOp, Override.class.getSimpleName());
524 
525         String toStringAppend = "";
526         String separatorLog = " : ";
527         // Copy operation parameters
528         for (ObjectModelParameter param : source.getParameters()) {
529             String paramName = param.getName();
530             addParameter(implOp, param.getType(), paramName);
531         }
532 
533         // Use buffer for operation body
534         StringBuilder buffer = new StringBuilder();
535 
536         // Abstract operation parameters
537         String abstName = abstOp.getName();
538         String abstParams =
539                 GeneratorUtil.getOperationParametersListName(abstOp);
540         
541         // Abstract operation return managment
542         String abstReturnType = "";
543         String abstReturn = "";
544         String finalReturn = "";
545         String returnType = GeneratorUtil.getSimpleName(abstOp.getReturnType(),
546                                                         true
547         );
548         if (!returnType.equals("void")) {
549             abstReturnType = returnType + " result = ";
550             abstReturn = "return result;";
551             finalReturn = "return " +
552                     getReturnValue(abstOp.getReturnType()) + ";";
553         }
554 
555         // Error key for i18n
556         String contract =
557             GeneratorUtil.toLowerCaseFirstLetter(serviceContractName);
558         String errorKey = StringUtils.lowerCase(modelName) + ".error." +
559                             contract + "." + source.getName();
560 
561         String treateErrorParams = "eee, I18n.n_(\"" + errorKey + "\")";
562 
563         if (needErrorArgs) {
564             addImport(serviceAbstract, ArrayList.class);
565             // Init errorArgs
566             buffer.append(""
567     /*{
568         List<Object> errorArgs = new ArrayList<Object>();
569     }*/             );
570             treateErrorParams += ", errorArgs.toArray()";
571         }
572 
573         if (needTransaction) {
574             // Open the transaction
575             buffer.append(""
576     /*{
577         TopiaContext transaction = null;
578         try {
579             transaction = beginTransaction();
580 
581             try {}*/
582                     );
583             // Add transaction in treateError parameters
584             treateErrorParams = "transaction, " + treateErrorParams;
585         } else {
586             buffer.append(""
587     /*{
588         try {
589     }*/
590                     );
591         }
592         String implName = StringUtils.capitalize(implOp.getName());
593         String first = modelName.substring(0, 1);
594 
595         buffer.append(""
596     /*{
597                 <%=abstReturnType%><%=abstName%>(<%=abstParams%>);}*/);
598 
599         if (needTransaction && isCommit(source, model)) {
600 
601             // add the commit instruction
602             buffer.append(""
603     /*{
604                 commitTransaction(transaction);}*/);
605 
606         }
607         buffer.append(""
608     /*{
609                 <%=abstReturn%>}*/);
610 
611         if (needTransaction) {
612             // Finally block to close transaction
613             buffer.append(""
614     /*{
615             } finally {
616                 closeTransaction(transaction);
617             }
618      }*/
619             );
620 
621         }
622         // Copy exceptions
623         for (String ex : source.getExceptions()) {
624             addException(implOp, ex);
625             // Add catch block for known exceptions we want to throw
626             String exName = GeneratorUtil.getSimpleName(ex);
627             buffer.append(""
628     /*{
629         } catch (<%=exName%> eee) {
630             throw eee; }*/);
631         }
632         if (exceptionName != null) {
633             addException(implOp, exceptionName);
634         }
635 
636         buffer.append(""
637     /*{
638         } catch (Exception eee) {
639             treateError(<%=treateErrorParams%>); }*/);
640 
641 
642         buffer.append(""
643     /*{
644         }
645         <%=finalReturn%>
646     }*/
647                 );
648 
649         setOperationBody(implOp, buffer.toString());
650     }
651 
652     /**
653      * boolean to specify if the method need a transaction or not.
654      * Default set to true but can be override using a tagvalue "transaction"
655      * on the method from model.
656      *
657      * @param op where the tagvalue is set
658      * @return {@code true} if transaction is needed
659      */
660     protected boolean isTransactionNeeded(ObjectModelInterface op) {
661         boolean needTransaction = true;
662 
663         String transactionTag = TopiaGeneratorUtil.getTransactionTagValue(op);
664 
665         if (transactionTag != null) {
666             needTransaction = Boolean.parseBoolean(transactionTag);
667         }
668         return needTransaction;
669     }
670 
671     /**
672      * boolean to specify if the method need a transaction or not.
673      * Default set to true but can be override using a tagvalue "transaction"
674      * on the method from model.
675      *
676      * @param op where the tagvalue is set
677      * @return {@code true} if transaction is needed
678      */
679     protected boolean isTransactionNeeded(ObjectModelOperation op) {
680         boolean needTransaction = true;
681 
682         String transactionTag = TopiaGeneratorUtil.getTransactionTagValue(op);
683 
684         if (transactionTag != null) {
685             needTransaction = Boolean.parseBoolean(transactionTag);
686         }
687         return needTransaction;
688     }
689 
690     /**
691      * boolean to specify if method needs a commit after the executeXXX code invoked.
692      *
693      * @param op model element where the tagvalue is set
694      * @param model  model where to tagvalue can be also set
695      * @return {@code true} if a commit must be generated after the executeXXX invocation
696      * @see TopiaTagValues#TAG_DO_COMMIT
697      * @since 2.5
698      */
699     protected boolean isCommit(ObjectModelOperation op, ObjectModel model) {
700         boolean needCommit = false;
701 
702         String tagValue = TopiaGeneratorUtil.getDoCommitTagValue(
703                 op,
704                 model
705         );
706         if (tagValue != null) {
707             needCommit = Boolean.parseBoolean(tagValue);
708         }
709         if (isVerbose()) {
710             log.info("commit needed for op [" + op.getName() + "] : " + needCommit);
711         }
712         return needCommit;
713     }
714 
715     /**
716      * boolean to specify if the method need error arguments or not
717      * Default set to false but can be override using a tagvalue "errorArgs" on
718      * the method from model.
719      *
720      * @param op where the tagvalue is set
721      * @return true if errorArgs are needed
722      */
723     protected boolean isErrorArgsNeeded(ObjectModelOperation op) {
724         // 
725         boolean needErrorArgs = false;
726 
727         String errorArgsTag = TopiaGeneratorUtil.getErrorArgsTagValue(op);
728 
729         if (errorArgsTag != null) {
730             needErrorArgs = Boolean.parseBoolean(errorArgsTag);
731         }
732         return needErrorArgs;
733     }
734 
735     /**
736      * This method give the return string for an operation {@code returnType}.
737      * This use {@link Primitive} enum to provide default values for primitive
738      * type. For all other object type, this method will return null.
739      *
740      * @param returnType
741      * @return the defaultValue of the returnType
742      */
743     protected String getReturnValue(String returnType) {
744         try {
745             //FIXME-TC20100423 : can not deal with Object types (float != Float)
746             Primitive prim =
747                 Primitive.valueOf(StringUtils.upperCase(returnType));
748             return prim.getValue();
749         // If not defined in Primitive enum, return null
750         } catch (IllegalArgumentException eee) {
751             return null;
752         }
753     }
754 
755     //FIXME-TC20100423 : REMOVE THIS!
756     protected enum Primitive {
757         BYTE("0"),
758         SHORT("0"),
759         INT("0"),
760         LONG("0"),
761         FLOAT("0."),
762         DOUBLE("0."),
763         CHAR("''"),
764         BOOLEAN("false");
765 
766         private String value;
767 
768         Primitive(String value) {
769             this.value = value;
770         }
771 
772         public String getValue() {
773             return value;
774         }
775     }
776 }