Author: fdesbois
Date: 2010-03-31 10:27:58 +0200 (Wed, 31 Mar 2010)
New Revision: 1862
Log:
- Evo #412 : rename BusinessTransformer to ServiceTransformer + improve html javadoc
- Evo #430 : use 1.2 version of i18n
Added:
trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/ServiceTransformer.java
Removed:
trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/BusinessTransformer.java
Modified:
trunk/pom.xml
Modified: trunk/pom.xml
===================================================================
--- trunk/pom.xml 2010-03-30 20:51:55 UTC (rev 1861)
+++ trunk/pom.xml 2010-03-31 08:27:58 UTC (rev 1862)
@@ -190,7 +190,7 @@
<eugene.version>2.0</eugene.version>
<lutinutil.version>1.2</lutinutil.version>
<processor.version>1.0.3</processor.version>
- <i18n.version>1.1</i18n.version>
+ <i18n.version>1.2</i18n.version>
<xmlrpc.version>3.1.2</xmlrpc.version>
<hibernate.version>3.3.2.GA</hibernate.version>
Deleted: trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/BusinessTransformer.java
===================================================================
--- trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/BusinessTransformer.java 2010-03-30 20:51:55 UTC (rev 1861)
+++ trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/BusinessTransformer.java 2010-03-31 08:27:58 UTC (rev 1862)
@@ -1,592 +0,0 @@
-
-package org.nuiton.topia.generator;
-
-import java.util.ArrayList;
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.nuiton.eugene.GeneratorUtil;
-import org.nuiton.eugene.Template;
-import org.nuiton.eugene.java.ObjectModelTransformerToJava;
-import org.nuiton.eugene.models.object.ObjectModel;
-import org.nuiton.eugene.models.object.ObjectModelClass;
-import org.nuiton.eugene.models.object.ObjectModelInterface;
-import org.nuiton.eugene.models.object.ObjectModelModifier;
-import org.nuiton.eugene.models.object.ObjectModelOperation;
-import org.nuiton.eugene.models.object.ObjectModelParameter;
-import org.nuiton.i18n.I18n;
-import org.nuiton.topia.TopiaContext;
-import org.nuiton.topia.TopiaException;
-
-/*{generator option: parentheses = false}*/
-
-/*{generator option: writeString = +}*/
-
-/**
- * This Template is used to create the skeleton of services for a final
- * application which using Topia.
- * <pre>
- * Generation from a model named 'App' :
- *
- * - AppContext : empty super interface to used in application UI. Can
- * be override in model if put in defaultPackage (ex : org.chorem.app) set
- * in maven-eugene-plugin configuration.
- *
- * - AppContextImplementor : interface which extends AppContext to add
- * technical methods for the application. Generation of methods :
- * * doCatch : used to catch all exception from a service method.
- * * doFinally : used to finally the try/catch of a service method
- * * beginTransaction : start the transaction using rootContext.
- * These three methods have to be implemented in a class which implements
- * AppContextImplementor (ex : AppContextImpl). You can also add others
- * methods to AppContextImplementor in the same way as AppContext.
- *
- * - AppException : exception class which extends RuntimeException for all
- * technical exceptions which appears in service method. If you want to
- * manage some specific exceptions, you have to managed them in doCatch
- * implementation.
- *
- * Generation from interfaces with stereotype <<service>> :
- *
- * - Service : interface of the service defined in model.
- *
- * - ServiceAbstract : abstract class which contains :
- * * constructor with AppContextImplementor in argument
- * * for each method : the implementation of the method (skeleton with
- * try/catch and beginTransaction call to open a new TopiaContext from
- * AppContextImplementor). Usage of i18n keys for error messages in
- * exception.
- * * for each method : an abstract method used to execute the business
- * code of the method : need to be implemented in subclass.
- *
- * Exemple of AppContextImpl :
- *
- * public class AppContextImpl implements AppContextImplementor {
- *
- * // properties for Topia configuration
- * protected Properties properties;
- * ...
- *
- * @Override
- * public void doCatch(TopiaContext transaction, Exception eee,
- * String message, Object... args) throws AppException {
- *
- * // Note that the message from service doesn't directly use _() for
- * // i18 messages but n_(). In this log, the _() is used to translate
- * // correctly the message. But the message must be translate when
- * // catching the AppException in UI.
- * if (log.isErrorEnabled()) {
- * log.error(_(message, args), eee);
- * }
- *
- * // rollback of current transaction
- * if (transaction != null) {
- * try {
- * transaction.rollbackTransaction();
- * } catch (TopiaException ex) {
- * if (log.isErrorEnabled()) {
- * log.error(_("app.error.context.rollback"), ex);
- * }
- * }
- * }
- * // wrapping the exception in a AppException with message and
- * // arguments for i18n translation
- * throw new AppException(eee, message, args);
- * }
- *
- * @Override
- * public void doFinally(TopiaContext transaction) {
- * if (transaction != null) {
- * try {
- * transaction.closeContext();
- * } catch (TopiaException eee) {
- * if (log.isErrorEnabled()) {
- * log.error(_("app.error.context.close"), eee);
- * }
- * }
- * }
- * }
- *
- * @Override
- * public TopiaContext beginTransaction() throws TopiaException {
- * TopiaContext rootContext = null;
- * try {
- * // You have to manage the properties using ApplicationConfig
- * // or other lib to have configuration for Topia
- * rootContext = TopiaContextFactory.getContext(properties);
- *
- * return getTopiaRootContext().beginTransaction();
- *
- * // only catch exception for rootContext
- * } catch (TopiaNotFoundException eee) {
- * doCatch(eee, n_("app.error.context.getTopiaRootContext"));
- * }
- * return null;
- * }
- * ...
- * }
- *
- * Exemple of ServiceImpl :
- *
- * public class ServiceImpl extends ServiceAbstract {
- *
- * public ServiceImpl(AppContextImplementor context) {
- * super(context);
- * }
- *
- * // Implementation of abstract method, the interface method is
- * // called 'createMyEntity(MyEntity entity)' in this case.
- * @Override
- * public void executeCreateMyEntity(TopiaContext transaction,
- * MyEntity entity) throws TopiaException {
- *
- * MyEntityDAO dao = AppDAOHelper.getMyEntityDAO(transaction);
- * dao.create(entity);
- * // That's it, no need to manage errors or transaction, the abstract
- * // service will do this job.
- * }
- * }
- *
- * TAG_TRANSACTION
- * ---------------
- *
- * You can use the tagValue 'transaction=false' to specify that a method doesn't
- * need any TopiaContext, so no need to instantiate a new one. This tagValue
- * can only be put directly in the model and not in properties file (because
- * of multiple methods with same name problem).
- *
- * TAG_ERROR_ARGS
- * --------------
- *
- * You can use the tagValue 'errorArgs=false' to specify that a method doesn't
- * need any arguments for error message. This tagValue can only be put directly
- * in the model and not in properties file.
- *
- * It is smooth, isn't it :p ?
- *
- * TODO : may be refactor to integrate JTA or webservice or may be not in this
- * transformer.
- *
- * TODO : find a good way to change log level
- *
- * </pre>
- *
- * Created: 23 mars 2010
- *
- * @author fdesbois
- * @version $Revision$
- *
- * Mise a jour: $Date$
- * par : $Author$
- */
-public class BusinessTransformer extends ObjectModelTransformerToJava {
-
- protected String modelName;
-
- protected String defaultPackageName;
-
- protected String getContextInterfaceName() {
- return modelName + "Context";
- }
-
- protected String getContextImplementorInterfaceName() {
- return getContextInterfaceName() + "Implementor";
- }
-
- protected String getExceptionClassName() {
- return modelName + "Exception";
- }
-
- protected String getServiceAbstractClassName(String serviceName) {
- return serviceName + "Abstract";
- }
-
- @Override
- public void transformFromModel(ObjectModel model) {
- modelName = model.getName();
- defaultPackageName = getOutputProperties().
- getProperty(Template.PROP_DEFAULT_PACKAGE);
-
- ObjectModelInterface contextImplementor =
- model.getInterface(defaultPackageName + "." +
- getContextImplementorInterfaceName());
-
- ObjectModelInterface context =
- model.getInterface(defaultPackageName + "." +
- getContextInterfaceName());
-
- ObjectModelClass exception = createExceptionClass();
-
- ObjectModelInterface newContextImplementor =
- this.createInterface(getContextImplementorInterfaceName(),
- defaultPackageName);
- ObjectModelInterface newContext =
- this.createInterface(getContextInterfaceName(),
- defaultPackageName);
-
- this.addInterface(newContextImplementor,
- newContext.getQualifiedName());
-
- if (contextImplementor != null) {
- // Copy of defined operations
- // interfaces of contextImplementor are not copied
- copyInterfaceOperations(contextImplementor, newContextImplementor);
- }
-
- if (context != null) {
- // Copy of defined operations
- // interfaces of context are not copied
- copyInterfaceOperations(context, newContext);
- }
-
- ObjectModelOperation beginTransaction =
- this.addOperation(newContextImplementor,
- "beginTransaction", TopiaContext.class);
- this.addException(beginTransaction, TopiaException.class);
-
- ObjectModelOperation doCatch1 =
- this.addOperation(newContextImplementor, "doCatch", "void");
- this.addParameter(doCatch1, Exception.class, "eee");
- this.addParameter(doCatch1, String.class, "message");
- this.addParameter(doCatch1, "Object...", "args");
- this.addException(doCatch1, exception.getQualifiedName());
-
- ObjectModelOperation doCatch2 =
- this.addOperation(newContextImplementor, "doCatch", "void");
- this.addParameter(doCatch2, TopiaContext.class, "transaction");
- this.addParameter(doCatch2, Exception.class, "eee");
- this.addParameter(doCatch2, String.class, "message");
- this.addParameter(doCatch2, "Object...", "args");
- this.addException(doCatch2, exception.getQualifiedName());
-
- ObjectModelOperation doFinally =
- this.addOperation(newContextImplementor, "doFinally", "void");
- this.addParameter(doFinally, TopiaContext.class, "transaction");
- }
-
- protected ObjectModelClass createExceptionClass() {
-
- ObjectModelClass exception =
- this.createClass(getExceptionClassName(), defaultPackageName);
-
- this.setSuperClass(exception, RuntimeException.class);
- this.addAttribute(exception, "args", "Object[]", null,
- ObjectModelModifier.PROTECTED);
-
- ObjectModelOperation constructor =
- this.addConstructor(exception, ObjectModelModifier.PUBLIC);
-
- this.addParameter(constructor, Throwable.class, "eee");
- this.addParameter(constructor, String.class, "message");
- this.addParameter(constructor, "Object...", "args");
-
- setOperationBody(constructor, ""
- /*{
- super(message, eee);
- this.args = args;
- }*/
- );
-
- ObjectModelOperation getArgs =
- this.addOperation(exception, "getArgs", "Object[]",
- ObjectModelModifier.PUBLIC);
-
- setOperationBody(getArgs, ""
- /*{
- return args;
- }*/
- );
-
- ObjectModelOperation hasArgs =
- this.addOperation(exception, "hasArgs", "boolean",
- ObjectModelModifier.PUBLIC);
-
- setOperationBody(hasArgs, ""
- /*{
- return args.length > 0;
- }*/
- );
-
- return exception;
- }
-
- /**
- * Used to simply copy the {@code source} interface signature to the
- * {@code dest} interface.
- *
- * @param source interface
- * @param dest interface
- */
- protected void copyInterfaceOperations(ObjectModelInterface source,
- ObjectModelInterface dest) {
- for (ObjectModelOperation op : source.getOperations()) {
- ObjectModelOperation newOp =
- this.addOperation(dest,
- op.getName(), op.getReturnType());
- setDocumentation(newOp.getReturnParameter(),
- op.getReturnParameter().getDocumentation());
- for (ObjectModelParameter param : op.getParameters()) {
- ObjectModelParameter newParam =
- this.addParameter(newOp, param.getType(),
- param.getName());
- setDocumentation(newParam, param.getDocumentation());
- }
- for (String ex : op.getExceptions()) {
- this.addException(newOp, ex);
- }
- setDocumentation(newOp, op.getDocumentation());
- }
- }
-
- @Override
- public void transformFromInterface(ObjectModelInterface interfacez) {
- // skip ContextImplementor and Context interfaces
- if (!interfacez.hasStereotype(TopiaGeneratorUtil.STEREOTYPE_SERVICE)) {
- return;
- }
-
- // Create INTERFACE
- ObjectModelInterface serviceInterface =
- this.createInterface(interfacez.getName(),
- interfacez.getPackageName());
-
- copyInterfaceOperations(interfacez, serviceInterface);
-
-
- // Create ABSTRACT CLASS
- ObjectModelClass service = this.createAbstractClass(
- getServiceAbstractClassName(interfacez.getName()),
- interfacez.getPackageName());
-
- this.addInterface(service, serviceInterface.getQualifiedName());
-
- // Add Logger
- // FIXME in EUGene, we want the default value not to be managed
- // for import.
-// this.addAttribute(service, "log",
-// Log.class,
-// "LogFactory.getLog(" + interfacez.getName() + ".class)",
-// ObjectModelModifier.PRIVATE,
-// ObjectModelModifier.STATIC,
-// ObjectModelModifier.FINAL);
- this.addAttribute(service, "log",
- Log.class, null,
- ObjectModelModifier.PRIVATE,
- ObjectModelModifier.FINAL);
-
- this.addImport(service, Log.class);
- this.addImport(service, LogFactory.class);
-
- String contextFqn = defaultPackageName + "." +
- getContextImplementorInterfaceName();
-
- // Add Context Attribute + constructor
- this.addAttribute(service, "context", contextFqn, null,
- ObjectModelModifier.PROTECTED);
-
- // Constructor
- ObjectModelOperation constructor =
- this.addConstructor(service, ObjectModelModifier.PUBLIC);
- //this.addParameter(constructor, contextFqn, "context");
- setOperationBody(constructor, ""
- /*{
- //this.context = context;
- // FIXME : must be fixed attribute value in EUGene
- this.log = LogFactory.getLog(<%=interfacez.getName()%>.class);
- }*/
- );
-
- ObjectModelOperation setContext =
- this.addOperation(service, "setContext", "void",
- ObjectModelModifier.PUBLIC);
- this.addParameter(setContext, contextFqn, "context");
- setOperationBody(setContext, ""
- /*{
- this.context = context;
- }*/
- );
-
- // Prepare operation generations
- String first = modelName.substring(0, 1);
- String serviceName =
- GeneratorUtil.toLowerCaseFirstLetter(interfacez.getName());
-
- this.addImport(service, TopiaContext.class);
- this.addImport(service, I18n.class);
- this.addImport(service, ArrayList.class);
-
- for (ObjectModelOperation op : interfacez.getOperations()) {
-
- // boolean to specify if the method need a transaction or not
- // Default set to true but can be override by a tagvalue on the
- // method
- boolean needTransaction = true;
-
- String transactionTag =
- op.getTagValue(TopiaGeneratorUtil.TAG_TRANSACTION);
-
- if (transactionTag != null) {
- needTransaction = Boolean.parseBoolean(transactionTag);
- }
-
- // boolean to specify if the method need error arguments or not
- // Default set to true but can be override by a tagvalue on the
- // method
- boolean needErrorArgs = true;
-
- String errorArgsTag =
- op.getTagValue(TopiaGeneratorUtil.TAG_ERROR_ARGS);
-
- if (errorArgsTag != null) {
- needErrorArgs = Boolean.parseBoolean(errorArgsTag);
- }
-
- // Implementation of interface operation
- ObjectModelOperation implOp =
- this.addOperation(service,
- op.getName(), op.getReturnType(),
- ObjectModelModifier.PUBLIC);
- this.addAnnotation(service, implOp, Override.class.getSimpleName());
-
- String opName = StringUtils.capitalize(op.getName());
-
- // Abstract operation to execute method content
- ObjectModelOperation abstOp =
- this.addOperation(service, "execute" + opName,
- op.getReturnType(),
- ObjectModelModifier.ABSTRACT,
- ObjectModelModifier.PROTECTED);
-
- // Throw all exception from abstract method
- // They will be catched by interface method to use doCatch
- this.addException(abstOp, Exception.class);
-
- if (needTransaction) {
- this.addParameter(abstOp, TopiaContext.class, "transaction");
- this.addException(abstOp, TopiaException.class);
- }
-
- String toStringAppend = "";
- String separatorLog = " : ";
- // Prepare operation parameters
- String opParams = "";
- String separatorParams = "";
- if (needErrorArgs) {
- opParams += "errorArgs";
- separatorParams = ", ";
- // Add errorArgs to abstract operation
- this.addParameter(abstOp,
- "java.util.List<Object>", "errorArgs");
- }
-
- // Copy other operation parameters
- for (ObjectModelParameter param : op.getParameters()) {
- String paramName = param.getName();
- this.addParameter(implOp, param.getType(), param.getName());
- this.addParameter(abstOp, param.getType(), param.getName());
-
- // Prepare Log
- toStringAppend +=
- "\n\t\t\t.append(\"" + separatorLog + paramName + " = \")" +
- ".append(" + paramName + ")";
- separatorLog = " _ ";
-
- // Prepare Abstract method params
- opParams += separatorParams + param.getName();
- separatorParams = ", ";
- }
-
- // Use buffer for operation body
- StringBuilder buffer = new StringBuilder();
-
- // Error key for i18n
- String errorKey = StringUtils.lowerCase(modelName) + ".error." +
- serviceName + "." + op.getName();
-
- String doCatchParams = "eee, I18n.n_(\"" + errorKey + "\")";
- doCatchParams += needErrorArgs ? ", errorArgs.toArray()" : "";
-
- // Return managment
- String opReturn = "";
- String finalReturn = "";
- if (!op.getReturnType().equals("void")) {
- opReturn = "return ";
- finalReturn = "return null;";
- }
-
- if (needErrorArgs) {
- // Init errorArgs
- buffer.append(""
- /*{
- List<Object> errorArgs = new ArrayList<Object>();
- }*/ );
- }
-
- if (needTransaction) {
- // Open the transaction
- buffer.append(""
- /*{
- TopiaContext transaction = null;
- try {
- transaction = context.beginTransaction();
- }*/
- );
- // Add transaction in the execute operation parameters
- // and doCatch parameters
- opParams = "transaction, " + opParams;
- doCatchParams = "transaction, " + doCatchParams;
- } else {
- buffer.append(""
- /*{
- try {
- }*/
- );
- }
-
- buffer.append(""
- /*{
- if (log.isDebugEnabled()) {
- String message = new StringBuilder("<%=first%>:[ <%=opName%> ]")<%=toStringAppend%>.
- toString();
- log.debug(message);
- }
-
- <%=opReturn%>execute<%=opName%>(<%=opParams%>); }*/);
-
- // Copy exceptions
- for (String ex : op.getExceptions()) {
- this.addException(implOp, ex);
- this.addException(abstOp, ex);
- // Add catch block for known exceptions we want to throw
- String exName = GeneratorUtil.getSimpleName(ex);
- buffer.append(""
- /*{
- } catch (<%=exName%> eee) {
- throw eee; }*/);
- }
-
- buffer.append(""
- /*{
- } catch (Exception eee) {
- context.doCatch(<%=doCatchParams%>); }*/);
-
- if (needTransaction) {
- // Finally block to close transaction
- buffer.append(""
- /*{
- } finally {
- context.doFinally(transaction); }*/);
- }
-
- buffer.append(""
- /*{
- }
- <%=finalReturn%>
- }*/
- );
-
- this.setOperationBody(implOp, buffer.toString());
- }
-
- }
-}
Copied: trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/ServiceTransformer.java (from rev 1860, trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/BusinessTransformer.java)
===================================================================
--- trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/ServiceTransformer.java (rev 0)
+++ trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/ServiceTransformer.java 2010-03-31 08:27:58 UTC (rev 1862)
@@ -0,0 +1,594 @@
+
+package org.nuiton.topia.generator;
+
+import java.util.ArrayList;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.nuiton.eugene.GeneratorUtil;
+import org.nuiton.eugene.Template;
+import org.nuiton.eugene.java.ObjectModelTransformerToJava;
+import org.nuiton.eugene.models.object.ObjectModel;
+import org.nuiton.eugene.models.object.ObjectModelClass;
+import org.nuiton.eugene.models.object.ObjectModelInterface;
+import org.nuiton.eugene.models.object.ObjectModelModifier;
+import org.nuiton.eugene.models.object.ObjectModelOperation;
+import org.nuiton.eugene.models.object.ObjectModelParameter;
+import org.nuiton.i18n.I18n;
+import org.nuiton.topia.TopiaContext;
+import org.nuiton.topia.TopiaException;
+
+/*{generator option: parentheses = false}*/
+
+/*{generator option: writeString = +}*/
+
+/**
+ * This Template is used to create the skeleton of services for a final
+ * application which using Topia.
+ * <div>
+ * Generation from a model named 'App' :
+ * <ul>
+ * <li>AppContext : empty super interface to used in application UI. Can
+ * be override in model if put in defaultPackage (ex : org.chorem.app) set
+ * in maven-eugene-plugin configuration.
+ * </li>
+ * <li><p>AppContextImplementor : interface which extends AppContext to add
+ * technical methods for the application. Generation of methods :</p>
+ * <p>* doCatch : used to catch all exception from a service method.</p>
+ * <p>* doFinally : used to finally the try/catch of a service method</p>
+ * <p>* beginTransaction : start the transaction using rootContext.</p>
+ * <p>These three methods have to be implemented in a class which implements
+ * AppContextImplementor (ex : AppContextImpl). You can also add others
+ * methods to AppContextImplementor in the same way as AppContext.</p>
+ * </li>
+ * <li>AppException : exception class which extends RuntimeException for all
+ * technical exceptions which appears in service method. If you want to
+ * manage some specific exceptions, you have to managed them in doCatch
+ * implementation.
+ * </li>
+ * </ul>
+ * </div>
+ * <div>
+ * Generation from interfaces with stereotype <<service>> :
+ * <ul>
+ * <li>Service : interface of the service defined in model.</li>
+ * <li><p>ServiceAbstract : abstract class which contains :</p>
+ * <p>* constructor with AppContextImplementor in argument</p>
+ * <p>* for each method : the implementation of the method (skeleton with
+ * try/catch and beginTransaction call to open a new TopiaContext from
+ * AppContextImplementor). Usage of i18n keys for error messages in
+ * exception.</p>
+ * <p>* for each method : an abstract method used to execute the business
+ * code of the method : need to be implemented in subclass.</p>
+ * </li>
+ * </ul>
+ * </div>
+ * <div>
+ * Exemple of AppContextImpl :<br />
+ * <pre>
+ * public class AppContextImpl implements AppContextImplementor {
+ *
+ * // properties for Topia configuration
+ * protected Properties properties;
+ * ...
+ *
+ * @Override
+ * public void doCatch(TopiaContext transaction, Exception eee,
+ * String message, Object... args) throws AppException {
+ *
+ * // Note that the message from service doesn't directly use _() for
+ * // i18 messages but n_(). In this log, the _() is used to translate
+ * // correctly the message. But the message must be translate when
+ * // catching the AppException in UI.
+ * if (log.isErrorEnabled()) {
+ * log.error(_(message, args), eee);
+ * }
+ *
+ * // rollback of current transaction
+ * if (transaction != null) {
+ * try {
+ * transaction.rollbackTransaction();
+ * } catch (TopiaException ex) {
+ * if (log.isErrorEnabled()) {
+ * log.error(_("app.error.context.rollback"), ex);
+ * }
+ * }
+ * }
+ * // wrapping the exception in a AppException with message and
+ * // arguments for i18n translation
+ * throw new AppException(eee, message, args);
+ * }
+ *
+ * @Override
+ * public void doFinally(TopiaContext transaction) {
+ * if (transaction != null) {
+ * try {
+ * transaction.closeContext();
+ * } catch (TopiaException eee) {
+ * if (log.isErrorEnabled()) {
+ * log.error(_("app.error.context.close"), eee);
+ * }
+ * }
+ * }
+ * }
+ *
+ * @Override
+ * public TopiaContext beginTransaction() throws TopiaException {
+ * TopiaContext rootContext = null;
+ * try {
+ * // You have to manage the properties using ApplicationConfig
+ * // or other lib to have configuration for Topia
+ * rootContext = TopiaContextFactory.getContext(properties);
+ *
+ * return getTopiaRootContext().beginTransaction();
+ *
+ * // only catch exception for rootContext
+ * } catch (TopiaNotFoundException eee) {
+ * doCatch(eee, n_("app.error.context.getTopiaRootContext"));
+ * }
+ * return null;
+ * }
+ * ...
+ * }
+ * </pre>
+ * </div>
+ * <div>
+ * Exemple of ServiceImpl :<br />
+ * <pre>
+ * public class ServiceImpl extends ServiceAbstract {
+ *
+ * public ServiceImpl(AppContextImplementor context) {
+ * super(context);
+ * }
+ *
+ * // Implementation of abstract method, the interface method is
+ * // called 'createMyEntity(MyEntity entity)' in this case.
+ * @Override
+ * public void executeCreateMyEntity(TopiaContext transaction,
+ * MyEntity entity) throws TopiaException {
+ *
+ * MyEntityDAO dao = AppDAOHelper.getMyEntityDAO(transaction);
+ * dao.create(entity);
+ * // That's it, no need to manage errors or transaction, the abstract
+ * // service will do this job.
+ * }
+ * }
+ * </pre>
+ * <div>
+ * <h2>TAG_TRANSACTION</h2>
+ * <p>You can use the tagValue 'transaction=false' to specify that a method
+ * doesn't need any TopiaContext, so no need to instantiate a new one.
+ * This tagValue can only be put directly in the model and not in properties
+ * file (because of multiple methods with same name problem).</p>
+ * </div>
+ * <div>
+ * <h2>TAG_ERROR_ARGS</h2>
+ * <p>You can use the tagValue 'errorArgs=false' to specify that a method doesn't
+ * need any arguments for error message. This tagValue can only be put directly
+ * in the model and not in properties file.</p>
+ * </div>
+ * <p>It is smooth, isn't it :p ?</p>
+ * <p>TODO : may be refactor to integrate JTA or webservice or may be not in this
+ * transformer.</p>
+ * <p>TODO : find a good way to change log level</p>
+ *
+ * Created: 23 mars 2010
+ *
+ * @author fdesbois
+ * @version $Revision$
+ *
+ * Mise a jour: $Date$
+ * par : $Author$
+ */
+public class ServiceTransformer extends ObjectModelTransformerToJava {
+
+ protected String modelName;
+
+ protected String defaultPackageName;
+
+ protected String getContextInterfaceName() {
+ return modelName + "Context";
+ }
+
+ protected String getContextImplementorInterfaceName() {
+ return getContextInterfaceName() + "Implementor";
+ }
+
+ protected String getExceptionClassName() {
+ return modelName + "Exception";
+ }
+
+ protected String getServiceAbstractClassName(String serviceName) {
+ return serviceName + "Abstract";
+ }
+
+ @Override
+ public void transformFromModel(ObjectModel model) {
+ modelName = model.getName();
+ defaultPackageName = getOutputProperties().
+ getProperty(Template.PROP_DEFAULT_PACKAGE);
+
+ ObjectModelInterface contextImplementor =
+ model.getInterface(defaultPackageName + "." +
+ getContextImplementorInterfaceName());
+
+ ObjectModelInterface context =
+ model.getInterface(defaultPackageName + "." +
+ getContextInterfaceName());
+
+ ObjectModelClass exception = createExceptionClass();
+
+ ObjectModelInterface newContextImplementor =
+ this.createInterface(getContextImplementorInterfaceName(),
+ defaultPackageName);
+ ObjectModelInterface newContext =
+ this.createInterface(getContextInterfaceName(),
+ defaultPackageName);
+
+ this.addInterface(newContextImplementor,
+ newContext.getQualifiedName());
+
+ if (contextImplementor != null) {
+ // Copy of defined operations
+ // interfaces of contextImplementor are not copied
+ copyInterfaceOperations(contextImplementor, newContextImplementor);
+ }
+
+ if (context != null) {
+ // Copy of defined operations
+ // interfaces of context are not copied
+ copyInterfaceOperations(context, newContext);
+ }
+
+ ObjectModelOperation beginTransaction =
+ this.addOperation(newContextImplementor,
+ "beginTransaction", TopiaContext.class);
+ this.addException(beginTransaction, TopiaException.class);
+
+ ObjectModelOperation doCatch1 =
+ this.addOperation(newContextImplementor, "doCatch", "void");
+ this.addParameter(doCatch1, Exception.class, "eee");
+ this.addParameter(doCatch1, String.class, "message");
+ this.addParameter(doCatch1, "Object...", "args");
+ this.addException(doCatch1, exception.getQualifiedName());
+
+ ObjectModelOperation doCatch2 =
+ this.addOperation(newContextImplementor, "doCatch", "void");
+ this.addParameter(doCatch2, TopiaContext.class, "transaction");
+ this.addParameter(doCatch2, Exception.class, "eee");
+ this.addParameter(doCatch2, String.class, "message");
+ this.addParameter(doCatch2, "Object...", "args");
+ this.addException(doCatch2, exception.getQualifiedName());
+
+ ObjectModelOperation doFinally =
+ this.addOperation(newContextImplementor, "doFinally", "void");
+ this.addParameter(doFinally, TopiaContext.class, "transaction");
+ }
+
+ protected ObjectModelClass createExceptionClass() {
+
+ ObjectModelClass exception =
+ this.createClass(getExceptionClassName(), defaultPackageName);
+
+ this.setSuperClass(exception, RuntimeException.class);
+ this.addAttribute(exception, "args", "Object[]", null,
+ ObjectModelModifier.PROTECTED);
+
+ ObjectModelOperation constructor =
+ this.addConstructor(exception, ObjectModelModifier.PUBLIC);
+
+ this.addParameter(constructor, Throwable.class, "eee");
+ this.addParameter(constructor, String.class, "message");
+ this.addParameter(constructor, "Object...", "args");
+
+ setOperationBody(constructor, ""
+ /*{
+ super(message, eee);
+ this.args = args;
+ }*/
+ );
+
+ ObjectModelOperation getArgs =
+ this.addOperation(exception, "getArgs", "Object[]",
+ ObjectModelModifier.PUBLIC);
+
+ setOperationBody(getArgs, ""
+ /*{
+ return args;
+ }*/
+ );
+
+ ObjectModelOperation hasArgs =
+ this.addOperation(exception, "hasArgs", "boolean",
+ ObjectModelModifier.PUBLIC);
+
+ setOperationBody(hasArgs, ""
+ /*{
+ return args.length > 0;
+ }*/
+ );
+
+ return exception;
+ }
+
+ /**
+ * Used to simply copy the {@code source} interface signature to the
+ * {@code dest} interface.
+ *
+ * @param source interface
+ * @param dest interface
+ */
+ protected void copyInterfaceOperations(ObjectModelInterface source,
+ ObjectModelInterface dest) {
+ setDocumentation(dest, source.getDocumentation());
+ for (ObjectModelOperation op : source.getOperations()) {
+ ObjectModelOperation newOp =
+ this.addOperation(dest,
+ op.getName(), op.getReturnType());
+ setDocumentation(newOp.getReturnParameter(),
+ op.getReturnParameter().getDocumentation());
+ for (ObjectModelParameter param : op.getParameters()) {
+ ObjectModelParameter newParam =
+ this.addParameter(newOp, param.getType(),
+ param.getName());
+ setDocumentation(newParam, param.getDocumentation());
+ }
+ for (String ex : op.getExceptions()) {
+ this.addException(newOp, ex);
+ }
+ setDocumentation(newOp, op.getDocumentation());
+ }
+ }
+
+ @Override
+ public void transformFromInterface(ObjectModelInterface interfacez) {
+ // skip ContextImplementor and Context interfaces
+ if (!interfacez.hasStereotype(TopiaGeneratorUtil.STEREOTYPE_SERVICE)) {
+ return;
+ }
+
+ // Create INTERFACE
+ ObjectModelInterface serviceInterface =
+ this.createInterface(interfacez.getName(),
+ interfacez.getPackageName());
+
+ copyInterfaceOperations(interfacez, serviceInterface);
+
+
+ // Create ABSTRACT CLASS
+ ObjectModelClass service = this.createAbstractClass(
+ getServiceAbstractClassName(interfacez.getName()),
+ interfacez.getPackageName());
+
+ this.addInterface(service, serviceInterface.getQualifiedName());
+
+ // Add Logger
+ // FIXME in EUGene, we want the default value not to be managed
+ // for import.
+// this.addAttribute(service, "log",
+// Log.class,
+// "LogFactory.getLog(" + interfacez.getName() + ".class)",
+// ObjectModelModifier.PRIVATE,
+// ObjectModelModifier.STATIC,
+// ObjectModelModifier.FINAL);
+ this.addAttribute(service, "log",
+ Log.class, null,
+ ObjectModelModifier.PRIVATE,
+ ObjectModelModifier.FINAL);
+
+ this.addImport(service, Log.class);
+ this.addImport(service, LogFactory.class);
+
+ String contextFqn = defaultPackageName + "." +
+ getContextImplementorInterfaceName();
+
+ // Add Context Attribute + constructor
+ this.addAttribute(service, "context", contextFqn, null,
+ ObjectModelModifier.PROTECTED);
+
+ // Constructor
+ ObjectModelOperation constructor =
+ this.addConstructor(service, ObjectModelModifier.PUBLIC);
+ //this.addParameter(constructor, contextFqn, "context");
+ setOperationBody(constructor, ""
+ /*{
+ //this.context = context;
+ // FIXME : must be fixed attribute value in EUGene
+ this.log = LogFactory.getLog(<%=interfacez.getName()%>.class);
+ }*/
+ );
+
+ ObjectModelOperation setContext =
+ this.addOperation(service, "setContext", "void",
+ ObjectModelModifier.PUBLIC);
+ this.addParameter(setContext, contextFqn, "context");
+ setOperationBody(setContext, ""
+ /*{
+ this.context = context;
+ }*/
+ );
+
+ // Prepare operation generations
+ String first = modelName.substring(0, 1);
+ String serviceName =
+ GeneratorUtil.toLowerCaseFirstLetter(interfacez.getName());
+
+ this.addImport(service, TopiaContext.class);
+ this.addImport(service, I18n.class);
+ this.addImport(service, ArrayList.class);
+
+ for (ObjectModelOperation op : interfacez.getOperations()) {
+
+ // boolean to specify if the method need a transaction or not
+ // Default set to true but can be override by a tagvalue on the
+ // method
+ boolean needTransaction = true;
+
+ String transactionTag =
+ op.getTagValue(TopiaGeneratorUtil.TAG_TRANSACTION);
+
+ if (transactionTag != null) {
+ needTransaction = Boolean.parseBoolean(transactionTag);
+ }
+
+ // boolean to specify if the method need error arguments or not
+ // Default set to true but can be override by a tagvalue on the
+ // method
+ boolean needErrorArgs = true;
+
+ String errorArgsTag =
+ op.getTagValue(TopiaGeneratorUtil.TAG_ERROR_ARGS);
+
+ if (errorArgsTag != null) {
+ needErrorArgs = Boolean.parseBoolean(errorArgsTag);
+ }
+
+ // Implementation of interface operation
+ ObjectModelOperation implOp =
+ this.addOperation(service,
+ op.getName(), op.getReturnType(),
+ ObjectModelModifier.PUBLIC);
+ this.addAnnotation(service, implOp, Override.class.getSimpleName());
+
+ String opName = StringUtils.capitalize(op.getName());
+
+ // Abstract operation to execute method content
+ ObjectModelOperation abstOp =
+ this.addOperation(service, "execute" + opName,
+ op.getReturnType(),
+ ObjectModelModifier.ABSTRACT,
+ ObjectModelModifier.PROTECTED);
+
+ // Throw all exception from abstract method
+ // They will be catched by interface method to use doCatch
+ this.addException(abstOp, Exception.class);
+
+ if (needTransaction) {
+ this.addParameter(abstOp, TopiaContext.class, "transaction");
+ this.addException(abstOp, TopiaException.class);
+ }
+
+ String toStringAppend = "";
+ String separatorLog = " : ";
+ // Prepare operation parameters
+ String opParams = "";
+ String separatorParams = "";
+ if (needErrorArgs) {
+ opParams += "errorArgs";
+ separatorParams = ", ";
+ // Add errorArgs to abstract operation
+ this.addParameter(abstOp,
+ "java.util.List<Object>", "errorArgs");
+ }
+
+ // Copy other operation parameters
+ for (ObjectModelParameter param : op.getParameters()) {
+ String paramName = param.getName();
+ this.addParameter(implOp, param.getType(), param.getName());
+ this.addParameter(abstOp, param.getType(), param.getName());
+
+ // Prepare Log
+ toStringAppend +=
+ "\n\t\t\t.append(\"" + separatorLog + paramName + " = \")" +
+ ".append(" + paramName + ")";
+ separatorLog = " _ ";
+
+ // Prepare Abstract method params
+ opParams += separatorParams + param.getName();
+ separatorParams = ", ";
+ }
+
+ // Use buffer for operation body
+ StringBuilder buffer = new StringBuilder();
+
+ // Error key for i18n
+ String errorKey = StringUtils.lowerCase(modelName) + ".error." +
+ serviceName + "." + op.getName();
+
+ String doCatchParams = "eee, I18n.n_(\"" + errorKey + "\")";
+ doCatchParams += needErrorArgs ? ", errorArgs.toArray()" : "";
+
+ // Return managment
+ String opReturn = "";
+ String finalReturn = "";
+ if (!op.getReturnType().equals("void")) {
+ opReturn = "return ";
+ finalReturn = "return null;";
+ }
+
+ if (needErrorArgs) {
+ // Init errorArgs
+ buffer.append(""
+ /*{
+ List<Object> errorArgs = new ArrayList<Object>();
+ }*/ );
+ }
+
+ if (needTransaction) {
+ // Open the transaction
+ buffer.append(""
+ /*{
+ TopiaContext transaction = null;
+ try {
+ transaction = context.beginTransaction();
+ }*/
+ );
+ // Add transaction in the execute operation parameters
+ // and doCatch parameters
+ opParams = "transaction, " + opParams;
+ doCatchParams = "transaction, " + doCatchParams;
+ } else {
+ buffer.append(""
+ /*{
+ try {
+ }*/
+ );
+ }
+
+ buffer.append(""
+ /*{
+ if (log.isDebugEnabled()) {
+ String message = new StringBuilder("<%=first%>:[ <%=opName%> ]")<%=toStringAppend%>.
+ toString();
+ log.debug(message);
+ }
+
+ <%=opReturn%>execute<%=opName%>(<%=opParams%>); }*/);
+
+ // Copy exceptions
+ for (String ex : op.getExceptions()) {
+ this.addException(implOp, ex);
+ this.addException(abstOp, ex);
+ // Add catch block for known exceptions we want to throw
+ String exName = GeneratorUtil.getSimpleName(ex);
+ buffer.append(""
+ /*{
+ } catch (<%=exName%> eee) {
+ throw eee; }*/);
+ }
+
+ buffer.append(""
+ /*{
+ } catch (Exception eee) {
+ context.doCatch(<%=doCatchParams%>); }*/);
+
+ if (needTransaction) {
+ // Finally block to close transaction
+ buffer.append(""
+ /*{
+ } finally {
+ context.doFinally(transaction); }*/);
+ }
+
+ buffer.append(""
+ /*{
+ }
+ <%=finalReturn%>
+ }*/
+ );
+
+ this.setOperationBody(implOp, buffer.toString());
+ }
+
+ }
+}
Property changes on: trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/ServiceTransformer.java
___________________________________________________________________
Added: svn:keywords
+ "Author Date Id Revision HeadURL"
Added: svn:mergeinfo
+