Author: tchemit Date: 2010-11-17 08:01:36 +0100 (Wed, 17 Nov 2010) New Revision: 2136 Url: http://nuiton.org/repositories/revision/topia/2136 Log: Evolution #1052: Improve ServiceTransformer code Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/ServiceTransformer.java Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/ServiceTransformer.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/ServiceTransformer.java 2010-11-16 15:38:19 UTC (rev 2135) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/ServiceTransformer.java 2010-11-17 07:01:36 UTC (rev 2136) @@ -27,7 +27,10 @@ import java.util.ArrayList; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; +import java.util.TreeMap; + import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.time.DurationFormatUtils; import org.apache.commons.logging.Log; @@ -266,46 +269,33 @@ return serviceContract; } - /** - * Create the service abstract for {@code serviceContract} - * using {@code source} interface defined - * in model. - * - * @param source interface from model - * @param serviceContract to implement - * @param needTransaction flag to know if service globally use transaction - */ - protected void createServiceAbstract(ObjectModelInterface source, + protected void createBeginTransactionMethod(ObjectModelInterface source, ObjectModelInterface serviceContract, - boolean needTransaction) { - - ObjectModelClass serviceAbstract = createAbstractClass( - getServiceAbstractClassName(serviceContract.getName()), - serviceContract.getPackageName()); - - // Implements contract interface - addInterface(serviceAbstract, serviceContract.getQualifiedName()); - - // Add Logger attribute - addAttribute(serviceAbstract, "log", - Log.class, - "LogFactory.getLog(" + source.getName() + ".class)", - ObjectModelModifier.PRIVATE, - ObjectModelModifier.STATIC, - ObjectModelModifier.FINAL); - - addImport(serviceAbstract, Log.class); - addImport(serviceAbstract, LogFactory.class); - - // Create abstract methods - if (needTransaction) { - ObjectModelOperation beginTransaction = + ObjectModelClass serviceAbstract) { + ObjectModelOperation beginTransaction = addOperation(serviceAbstract, OP_NAME_BEGIN_TRANSACTION, TopiaContext.class, ObjectModelModifier.ABSTRACT, ObjectModelModifier.PROTECTED); addException(beginTransaction, TopiaException.class); - } + } + + protected void createCloseTransactionMethod(ObjectModelInterface source, + ObjectModelInterface serviceContract, + ObjectModelClass serviceAbstract) { + ObjectModelOperation closeTransaction = + addOperation(serviceAbstract, OP_NAME_CLOSE_TRANSACTION, "void", + ObjectModelModifier.ABSTRACT, + ObjectModelModifier.PROTECTED); + addParameter(closeTransaction, TopiaContext.class, "transaction"); + addException(closeTransaction, TopiaException.class); + } + + protected void createTreateErrorMethod(ObjectModelInterface source, + ObjectModelInterface serviceContract, + ObjectModelClass serviceAbstract, + boolean needTransaction) { + ObjectModelOperation treateError1 = addOperation(serviceAbstract, OP_NAME_TREATE_ERROR, "void", ObjectModelModifier.ABSTRACT, @@ -321,29 +311,6 @@ } if (needTransaction) { - ObjectModelOperation closeTransaction = - addOperation(serviceAbstract, OP_NAME_CLOSE_TRANSACTION, "void", - ObjectModelModifier.ABSTRACT, - ObjectModelModifier.PROTECTED); - addParameter(closeTransaction, TopiaContext.class, "transaction"); - addException(closeTransaction, TopiaException.class); - } - // Create abstract execute methods - Map<String, ObjectModelOperation> abstOps = - new HashMap<String, ObjectModelOperation>(); - - // Use source interfacez to have tagvalues from model - for (ObjectModelOperation op : source.getOperations()) { - ObjectModelOperation abstOp = createOperationExecuteAbstract( - serviceAbstract, - op, - needTransaction - ); - // Keep abstract methods to use them in operationImplementation - // generation - abstOps.put(getAbstractOperationKeyMap(op), abstOp); - } - if (needTransaction) { ObjectModelOperation treateError2 = addOperation(serviceAbstract, OP_NAME_TREATE_ERROR, "void", ObjectModelModifier.PROTECTED); @@ -360,6 +327,24 @@ }*/ ); } + } + /** + * Create the service abstract for {@code serviceContract} + * using {@code source} interface defined + * in model. + * + * @param source interface from model + * @param serviceContract to implement + * @param needTransaction flag to know if service globally use transaction + */ + protected void createServiceAbstract(ObjectModelInterface source, + ObjectModelInterface serviceContract, + boolean needTransaction) { + + ObjectModelClass serviceAbstract = createAbstractClass( + getServiceAbstractClassName(serviceContract.getName()), + serviceContract.getPackageName()); + // Imports for implementations if (needTransaction) { addImport(serviceAbstract, TopiaContext.class); @@ -367,13 +352,66 @@ addImport(serviceAbstract, I18n.class); addImport(serviceAbstract, ArrayList.class); addImport(serviceAbstract, DurationFormatUtils.class); + + // Implements contract interface + addInterface(serviceAbstract, serviceContract.getQualifiedName()); - // Create abstract execute methods - for (ObjectModelOperation op : source.getOperations()) { + // Add Logger attribute + addAttribute(serviceAbstract, "log", + Log.class, + "LogFactory.getLog(" + source.getName() + ".class)", + ObjectModelModifier.PRIVATE, + ObjectModelModifier.STATIC, + ObjectModelModifier.FINAL); + + addImport(serviceAbstract, Log.class); + addImport(serviceAbstract, LogFactory.class); + + // Create abstract methods + + if (needTransaction) { + createBeginTransactionMethod(source, + serviceContract, + serviceAbstract); + + createCloseTransactionMethod(source, + serviceContract, + serviceAbstract); + } + + createTreateErrorMethod(source, + serviceContract, + serviceAbstract, + needTransaction + ); + + // keep execute methods (we want to generate them at the top of the + // class since they are all abstract) + // Note: using a LinkedHashMap permits to keep incoming order + Map<ObjectModelOperation, ObjectModelOperation> abstractExecuteMethods = + new LinkedHashMap<ObjectModelOperation, ObjectModelOperation>(); + + // first generate the abstract execute methods + for (ObjectModelOperation operation : source.getOperations()) { + + ObjectModelOperation executeOp = createOperationExecuteAbstract( + serviceAbstract, + operation, + needTransaction + ); + + abstractExecuteMethods.put(operation , executeOp); + } + + // Then generates the real operation which boxes the execute methods + for (Map.Entry<ObjectModelOperation, ObjectModelOperation> entry : + abstractExecuteMethods.entrySet()) { + ObjectModelOperation operation = entry.getKey(); + ObjectModelOperation executeOperation = entry.getValue(); createOperationImplementation( serviceAbstract, - abstOps.get(getAbstractOperationKeyMap(op)), - op, + executeOperation, + operation, source.getName(), needTransaction ); @@ -381,19 +419,6 @@ } /** - * Create a key for the abstractOperations map from {@code op}. Concat - * opName + params as String. - * - * @param op used as reference to construct the keyMap - * @return the keyMap - */ - protected String getAbstractOperationKeyMap(ObjectModelOperation op) { - String key = op.getName() + - GeneratorUtil.getOperationParametersListName(op); - return key; - } - - /** * Create an operation abstract to execute in contract implementation. * You can use tagvalues "errorArgs" (default = false) and "transaction" * (default = true) to generate appropriate parameters. This abstract