Author: tchemit Date: 2010-11-27 16:55:17 +0100 (Sat, 27 Nov 2010) New Revision: 1002 Url: http://nuiton.org/repositories/revision/eugene/1002 Log: - Anomalie #1105: Clone classifier is not correct and can't work... - Anomalie #1106: Transformer api is not correct (can not use the previous transformer in the applyTemplate method) - Evolution #1107: Improve MetaTransformer api - improve @author on my files Modified: trunk/eugene/src/main/java/org/nuiton/eugene/AbstractMetaTransformer.java trunk/eugene/src/main/java/org/nuiton/eugene/Transformer.java trunk/eugene/src/main/java/org/nuiton/eugene/java/AnnotationsManager.java trunk/eugene/src/main/java/org/nuiton/eugene/java/AnnotationsManagerExtension.java trunk/eugene/src/main/java/org/nuiton/eugene/java/ObjectModelTransformerToJava.java trunk/eugene/src/main/java/org/nuiton/eugene/models/object/ObjectModelBuilder.java trunk/eugene/src/main/java/org/nuiton/eugene/writer/ChainedFileWriterEntry.java trunk/eugene/src/main/java/org/nuiton/eugene/writer/ChainedWriterEngine.java trunk/eugene/src/main/java/org/nuiton/eugene/writer/DefaultChainedWriterEngine.java trunk/maven-eugene-plugin/src/it/smart-generate/generators/src/main/java/org/nuiton/eugene/test/generator/BeanGenerator.java Modified: trunk/eugene/src/main/java/org/nuiton/eugene/AbstractMetaTransformer.java =================================================================== --- trunk/eugene/src/main/java/org/nuiton/eugene/AbstractMetaTransformer.java 2010-11-26 17:24:18 UTC (rev 1001) +++ trunk/eugene/src/main/java/org/nuiton/eugene/AbstractMetaTransformer.java 2010-11-27 15:55:17 UTC (rev 1002) @@ -25,26 +25,25 @@ package org.nuiton.eugene; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.nuiton.eugene.models.Model; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; /** * Abstract meta transformer which contains some templates to apply to an * incoming model. - * + * <p/> * Using the {@link #getExcludeTemplates()} to restrict use of some templates. - * + * <p/> * Created: 20 déc. 2009 * + * @author tchemit <chemit@codelutin.com> * @param <M> type of Model - * - * @author Tony Chemit <chemit@codelutin.com> * @since 2.0.0 */ public abstract class AbstractMetaTransformer<M extends Model> extends AbstractGenerator<M> { @@ -52,30 +51,132 @@ private static final Log log = LogFactory.getLog(AbstractMetaTransformer.class); - private final Class<? extends Template<M>>[] transformers; + /** + * Transformers to apply before using templates. + * <p/> + * It will replace each time the input model by the generated output model. + * + * @since 2.2.1 + */ + protected Class<? extends Transformer<M, M>>[] transformerTypes; + /** + * Templates to apply to the model. + * + * @since 2.2.1, replace the old transformers field. + */ + protected Class<? extends Template<M>>[] templateTypes; + + protected AbstractMetaTransformer() { + } + + /** + * @param templateTypes templates to apply on model + * @deprecated since 2.2.1, prefer use the default constructor, the invoke + * setters {@link #setTemplateTypes(Class[])} and + * {@link #setTransformerTypes(Class[])}. + */ + @Deprecated public AbstractMetaTransformer( - Class<? extends Template<M>>... transformers) { - this.transformers = transformers; + Class<? extends Template<M>>... templateTypes) { + this.templateTypes = templateTypes; } + /** + * Validates the incoming given {@code model}. + * + * <b>Note :</b> If model is not valid, then nothing will be apply on the model + * (no transformer nor templates) in the {@link #applyTemplate(Model, File)}. + * + * @param model the incoming model to validate + * @return {@code true} if model is valid, {@code false} otherwise. + */ protected abstract boolean validateModel(M model); + public Class<? extends Transformer<M, M>>[] getTransformerTypes() { + return transformerTypes; + } + + public Class<? extends Template<M>>[] getTemplateTypes() { + return templateTypes; + } + + public void setTransformerTypes(Class<? extends Transformer<M, M>>... transformerTypes) { + this.transformerTypes = transformerTypes; + } + + public void setTemplateTypes(Class<? extends Template<M>>... templateTypes) { + this.templateTypes = templateTypes; + } + @Override public void applyTemplate(M model, File destDir) throws IOException { boolean isValid = validateModel(model); if (!isValid) { - //On n'empeche pas la génération si le modèle n'est pas valide - + // Can not generate is model is not valid return; } - List<Template<M>> templates = getTemplates(); + // obtain transformers instances + List<Transformer<M, M>> transformers = + getInstances(getTransformerTypes()); + // transforme model to obtain the final model used by templates + M currentModel = applyTransformers(model, transformers); + + // obtains templates instances + List<Template<M>> templates = getInstances(getTemplateTypes()); + + // apply templates to model + applyTemplates(currentModel, templates, destDir); + } + + /** + * given an incoming {@code model}, chain transformations of the mode + * using the given {@code transformers}. + * + * Will aplly the transformers in the order given by the list, using as + * incoming model to a transformer the last (or incoming for the first transformer) + * model. + * + * @param model incoming model to transform + * @param transformers list of transformers to apply to the model + * @return the final transformed model + * @since 2.2.1 + */ + protected M applyTransformers(M model, + List<? extends Transformer<M, M>> transformers) { + M currentModel = model; + for (Transformer<M, M> template : transformers) { + if (log.isDebugEnabled()) { + log.debug("call transformer : " + + template.getClass().getSimpleName()); + } + // transform from the current model + template.transform(currentModel); + + // current model become the transformed model + currentModel = template.getOutputModel(); + } + return currentModel; + } + + /** + * Generates to the given {@code destination directory} using the given + * templates on the incoming given {@code model}. + * + * @param model the incoming model to be used by templates + * @param templates templates to apply the incoming model + * @param destDir the destination directory where to generate + * @throws IOException if any IO errors while generating files + * @since 2.2.1 + */ + protected void applyTemplates(M model, + List<? extends Template<M>> templates, + File destDir) throws IOException { for (Template<M> template : templates) { - // log if (log.isDebugEnabled()) { log.debug("call template : " + template.getClass().getSimpleName()); @@ -84,9 +185,57 @@ } } + protected <T extends Template<M>> List<T> getInstances(Class<? extends T>[] types) { + List<T> result = new ArrayList<T>(); + if (types != null) { + for (Class<? extends T> generatorClass : types) { + T generator; + if (getExcludeTemplates().contains(generatorClass.getName())) { + + // exclude generator + if (log.isInfoEnabled()) { + log.info("exclude generator " + generatorClass); + } + continue; + } + + // instanciate the template + try { + generator = generatorClass.newInstance(); + + // init template + generator.setConfiguration(getConfiguration()); + + if (generator instanceof AbstractGenerator) { + ((AbstractGenerator) generator).setParent(this); + } +// if (generator instanceof Transformer) { +// generator.setProperties(properties); +// } + + // will use it + result.add(generator); + } catch (Exception e) { + + if (log.isErrorEnabled()) { + log.error("Could not instanciate template " + + generatorClass, e); + } + throw new RuntimeException(e); + } + } + } + return result; + } + + /** + * @return the instances of templates to apply to the model. + * @deprecated since 2.2.1, prefer use the {@link #getInstances(Class[])} + */ + @Deprecated protected List<Template<M>> getTemplates() { List<Template<M>> result = new ArrayList<Template<M>>(); - for (Class<? extends Template<M>> generatorClass : getTransformers()) { + for (Class<? extends Template<M>> generatorClass : templateTypes) { Template<M> generator; if (getExcludeTemplates().contains(generatorClass.getName())) { // exclude generator @@ -101,7 +250,7 @@ // init template generator.setConfiguration(getConfiguration()); - + if (generator instanceof AbstractGenerator) { ((AbstractGenerator<M>) generator).setParent(this); } @@ -122,7 +271,12 @@ return result; } + /** + * @return the template types to apply + * @deprecated since 2.2.1, use the method {@link #getTemplateTypes()} instead. + */ + @Deprecated public Class<? extends Template<M>>[] getTransformers() { - return transformers; + return templateTypes; } } Modified: trunk/eugene/src/main/java/org/nuiton/eugene/Transformer.java =================================================================== --- trunk/eugene/src/main/java/org/nuiton/eugene/Transformer.java 2010-11-26 17:24:18 UTC (rev 1001) +++ trunk/eugene/src/main/java/org/nuiton/eugene/Transformer.java 2010-11-27 15:55:17 UTC (rev 1002) @@ -28,6 +28,9 @@ import java.io.File; import java.io.IOException; import java.util.Properties; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.nuiton.eugene.models.Model; /** @@ -42,6 +45,9 @@ public abstract class Transformer<I extends Model, O extends Model> extends Template<I> { + /** Logger */ + private static final Log log = LogFactory.getLog(Transformer.class); + /** * Output generator, to generate files from Output model. * @@ -80,7 +86,10 @@ */ protected void init(I model) { this.model = model; - previousTransformer = initPreviousTransformer(); + // tchemit 2010-11-26 : this is not the good place to init a previous + // transformer : once coming here, we lost our chance to use the previousTransformer +// previousTransformer = initPreviousTransformer(); + outputTemplate = initOutputTemplate(); // build output template configuration @@ -92,7 +101,7 @@ new DefaultTemplateConfiguration(properties); // push back to outputPropertie the all configuration - //FIXME tchemit 20100516 Should rethink this... + //FIXME tchemit 2010-05-16 Should rethink this... outputProperties = properties; outputTemplate.setConfiguration(outconfig); @@ -168,16 +177,27 @@ */ @Override public void applyTemplate(I model, File destDir) throws IOException { - // previous transformation + + // init previous transformer + previousTransformer = initPreviousTransformer(); + + // previous transformation if (previousTransformer != null) { + + if (isVerbose()) { + log.info("Use previousTransformer " + previousTransformer); + } // transformation only, no application of next template previousTransformer.transform(model); - // current transformation + + // current transformation from the ouput model of previous transformer transform(previousTransformer.getOutputModel()); } else { - // current transformation + + // current transformation directly from the incoming model transform(model); } + // after template application getOutputTemplate().applyTemplate(getOutputModel(), destDir); } Modified: trunk/eugene/src/main/java/org/nuiton/eugene/java/AnnotationsManager.java =================================================================== --- trunk/eugene/src/main/java/org/nuiton/eugene/java/AnnotationsManager.java 2010-11-26 17:24:18 UTC (rev 1001) +++ trunk/eugene/src/main/java/org/nuiton/eugene/java/AnnotationsManager.java 2010-11-27 15:55:17 UTC (rev 1002) @@ -37,7 +37,7 @@ * <p/> * Created: 17 déc. 2009 * - * @author Tony Chemit <chemit@codelutin.com> Copyright Code Lutin + * @author tchemit <chemit@codelutin.com> * @version $Revision$ * <p/> * Mise a jour: $Date$ par : Modified: trunk/eugene/src/main/java/org/nuiton/eugene/java/AnnotationsManagerExtension.java =================================================================== --- trunk/eugene/src/main/java/org/nuiton/eugene/java/AnnotationsManagerExtension.java 2010-11-26 17:24:18 UTC (rev 1001) +++ trunk/eugene/src/main/java/org/nuiton/eugene/java/AnnotationsManagerExtension.java 2010-11-27 15:55:17 UTC (rev 1002) @@ -36,7 +36,7 @@ /** * Created: 17 déc. 2009 * - * @author Tony Chemit <chemit@codelutin.com> Copyright Code Lutin + * @author tchemit <chemit@codelutin.com> * @version $Revision$ * <p/> * Mise a jour: $Date$ par : Modified: trunk/eugene/src/main/java/org/nuiton/eugene/java/ObjectModelTransformerToJava.java =================================================================== --- trunk/eugene/src/main/java/org/nuiton/eugene/java/ObjectModelTransformerToJava.java 2010-11-26 17:24:18 UTC (rev 1001) +++ trunk/eugene/src/main/java/org/nuiton/eugene/java/ObjectModelTransformerToJava.java 2010-11-27 15:55:17 UTC (rev 1002) @@ -25,6 +25,7 @@ package org.nuiton.eugene.java; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -369,6 +370,17 @@ } /** + * Adds a navigable flag to the given {@code attribute}. + * + * @param attribute the attribute on which the navigable flag will be setted + * @param navigable the navigable flag to set + * @since 2.2.1 + */ + public void setNavigable(ObjectModelAttribute attribute, boolean navigable) { + builder.setNavigable(attribute, navigable); + } + + /** * Adds a comment to the given {@code element}. * * @param element the element on which the comment will be added. @@ -451,9 +463,7 @@ addException(outputOperation, exception); } - for (Map.Entry<String, String> tagValue : source.getTagValues().entrySet()) { - addTagValue(destination, tagValue.getKey(), tagValue.getValue()); - } + cloneTagValues(source, outputOperation); return outputOperation; } @@ -474,7 +484,13 @@ ObjectModelClassifier destination, boolean cloneDocumentation, ObjectModelModifier... modifiers) { - ObjectModelOperation outputOperation = cloneOperationSignature(source, destination, cloneDocumentation, modifiers); + ObjectModelOperation outputOperation = cloneOperationSignature( + source, + destination, + cloneDocumentation, + modifiers + ); + setOperationBody(outputOperation, source.getBodyCode()); return outputOperation; } @@ -498,9 +514,7 @@ source.getName(), source.getType(), source.getDefaultValue(), modifiers); - for (Map.Entry<String, String> tagValue : source.getTagValues().entrySet()) { - addTagValue(outputAttribute, tagValue.getKey(), tagValue.getValue()); - } + cloneTagValues(source, outputAttribute); if (cloneDocumentation) { setDocumentation(outputAttribute, source.getDocumentation()); @@ -512,9 +526,41 @@ setMinMultiplicity(outputAttribute, source.getMinMultiplicity()); setMaxMultiplicity(outputAttribute, source.getMaxMultiplicity()); + setNavigable(outputAttribute,source.isNavigable()); return outputAttribute; } + + /** + * Copy all tag values fro the given {@code source} to the given + * {@code destination}. + * + * @param source the source element + * @param destination the destination element + * @since 2.2.1 + */ + protected void cloneTagValues(ObjectModelElement source, + ObjectModelElement destination) { + Map<String, String> tags = source.getTagValues(); + for (Map.Entry<String, String> entry : tags.entrySet()) { + addTagValue(destination,entry.getKey(),entry.getValue()); + } + } + + /** + * + * @param source + * @param destination + * @since 2.2.1 + */ + protected void cloneStereotypes(ObjectModelClassifier source, + ObjectModelClassifier destination) { + + Collection<String> stereotypes = source.getStereotypes(); + for (String stereotype : stereotypes) { + addStereotype(destination,stereotype); + } + } /** * copy attributes, interfaces declartion and operation of a given classifier @@ -526,14 +572,41 @@ * @link {@link #cloneClassifier(ObjectModelClassifier, boolean)} * * @param source the classifier to clone from the source model - * @param destination + * @param destination where to clone the given source one * @param copyDocumentation flag to add documentation if some found in model * @since 2.1.2 + * @deprecated since 2.2.1, prefer use the {@link #cloneClass(ObjectModelClass, boolean)} method */ + @Deprecated protected void copyClassifier(ObjectModelClassifier source, ObjectModelClassifier destination, boolean copyDocumentation) { - + + cloneClassifier(source, destination, copyDocumentation); + } + + /** + * copy attributes, interfaces declartion and operation of a given classifier + * into another classifier. + * + * class-specific, enumeration-specific and interface-specific features + * of the given classifier <strong>will not</strong> be present in the clone. + * To copy those specific elements, use + * @link {@link #cloneClassifier(ObjectModelClassifier, boolean)} + * + * @param source the classifier to clone from the source model + * @param destination where to clone the given source one + * @param copyDocumentation flag to add documentation if some found in model + * @since 2.2.1 + */ + protected void cloneClassifier(ObjectModelClassifier source, + ObjectModelClassifier destination, + boolean copyDocumentation) { + + cloneTagValues(source, destination); + + cloneStereotypes(source, destination); + for (ObjectModelAttribute attribute : source.getAttributes()) { cloneAttribute(attribute, destination, copyDocumentation); } @@ -547,6 +620,7 @@ } } + /** * creates a clone of the given {@code source} class in the output model * and clones attributes, inheritence declarations and operations into the @@ -559,9 +633,10 @@ */ public ObjectModelClass cloneClass(ObjectModelClass source, boolean cloneDocumentation) { - ObjectModelClass outputClass = createClass(source.getName(), - source.getPackageName()); - copyClassifier(source, outputClass, cloneDocumentation); + ObjectModelClass outputClass = + createClass(source.getName(), source.getPackageName()); + + cloneClassifier(source, outputClass, cloneDocumentation); if (source.getSuperclasses().size() > 1) { log.warn(source.getQualifiedName() + " has multiple inheritence, some of them will be ignored"); @@ -573,13 +648,15 @@ // TODO 20100812 bleny is there something to do with discriminator for superClass ? } - for (ObjectModelClassifier innerClassifier : source.getInnerClassifiers()) { - ObjectModelClassifier innerClassifierClone = cloneClassifier(innerClassifier, cloneDocumentation); - addInnerClassifier(outputClass, - ObjectModelType.OBJECT_MODEL_CLASSIFIER, - innerClassifierClone.getName()); + if (!CollectionUtils.isEmpty(source.getInnerClassifiers())) { + for (ObjectModelClassifier classifier : source.getInnerClassifiers()) { + ObjectModelClassifier innerClassifierClone = + cloneClassifier(classifier, cloneDocumentation); + addInnerClassifier(outputClass, + ObjectModelType.OBJECT_MODEL_CLASSIFIER, + innerClassifierClone.getName()); + } } - return outputClass; } @@ -595,9 +672,10 @@ */ public ObjectModelInterface cloneInterface(ObjectModelInterface source, boolean cloneDocumentation) { - ObjectModelInterface outputInterface = createInterface(source.getName(), source.getPackageName()); + ObjectModelInterface outputInterface = + createInterface(source.getName(), source.getPackageName()); - copyClassifier(source, outputInterface, cloneDocumentation); + cloneClassifier(source, outputInterface, cloneDocumentation); // nothing more to do. copyClassifier already done the job return outputInterface; @@ -618,7 +696,7 @@ ObjectModelEnumeration outputEnumeration = createEnumeration(source.getName(), source.getPackageName()); - copyClassifier(source, outputEnumeration, cloneDocumentation); + cloneClassifier(source, outputEnumeration, cloneDocumentation); for (String literal : source.getLiterals()) { addLiteral(outputEnumeration, literal); @@ -759,7 +837,7 @@ addI18n(buffer, i18nPrefix, Introspector.decapitalize(input.getName())); boolean useI18n = false; for (ObjectModelAttribute attr : input.getAttributes()) { - //TC-20100225 only treate navigable relations + //tchemit-20100225 only treate navigable relations if (attr.isNavigable()) { useI18n=true; addI18n(buffer, Modified: trunk/eugene/src/main/java/org/nuiton/eugene/models/object/ObjectModelBuilder.java =================================================================== --- trunk/eugene/src/main/java/org/nuiton/eugene/models/object/ObjectModelBuilder.java 2010-11-26 17:24:18 UTC (rev 1001) +++ trunk/eugene/src/main/java/org/nuiton/eugene/models/object/ObjectModelBuilder.java 2010-11-27 15:55:17 UTC (rev 1002) @@ -686,4 +686,17 @@ impl.setMaxMultiplicity(multiplicity); } + + /** + * Set the navigable flag of an attribute in the model. + * + * @param attribute where the navigable flag will be setted + * @param navigable navigable flag value to set + * @since 2.2.1 + */ + public void setNavigable(ObjectModelAttribute attribute, + boolean navigable) { + ObjectModelAttributeImpl impl = (ObjectModelAttributeImpl) attribute; + impl.setNavigable(navigable); + } } Modified: trunk/eugene/src/main/java/org/nuiton/eugene/writer/ChainedFileWriterEntry.java =================================================================== --- trunk/eugene/src/main/java/org/nuiton/eugene/writer/ChainedFileWriterEntry.java 2010-11-26 17:24:18 UTC (rev 1001) +++ trunk/eugene/src/main/java/org/nuiton/eugene/writer/ChainedFileWriterEntry.java 2010-11-27 15:55:17 UTC (rev 1002) @@ -32,7 +32,7 @@ * <p/> * Created: 04 mars. 2010 * - * @author Tony Chemit <chemit@codelutin.com> Copyright Code Lutin + * @author tchemit <chemit@codelutin.com> * @version $Revision$ * @since 2.0.0 */ Modified: trunk/eugene/src/main/java/org/nuiton/eugene/writer/ChainedWriterEngine.java =================================================================== --- trunk/eugene/src/main/java/org/nuiton/eugene/writer/ChainedWriterEngine.java 2010-11-26 17:24:18 UTC (rev 1001) +++ trunk/eugene/src/main/java/org/nuiton/eugene/writer/ChainedWriterEngine.java 2010-11-27 15:55:17 UTC (rev 1002) @@ -40,7 +40,7 @@ * <p/> * Created: 17 déc. 2009 * - * @author Tony Chemit <chemit@codelutin.com> Copyright Code Lutin + * @author tchemit <chemit@codelutin.com> * @version $Revision$ * @since 2.0.0 */ Modified: trunk/eugene/src/main/java/org/nuiton/eugene/writer/DefaultChainedWriterEngine.java =================================================================== --- trunk/eugene/src/main/java/org/nuiton/eugene/writer/DefaultChainedWriterEngine.java 2010-11-26 17:24:18 UTC (rev 1001) +++ trunk/eugene/src/main/java/org/nuiton/eugene/writer/DefaultChainedWriterEngine.java 2010-11-27 15:55:17 UTC (rev 1002) @@ -48,7 +48,7 @@ * <p/> * Created: 17 déc. 2009 * - * @author Tony Chemit <chemit@codelutin.com> Copyright Code Lutin + * @author tchemit <chemit@codelutin.com> * @version $Id$ * @plexus.component role="org.nuiton.eugene.writer.ChainedWriterEngine" role-hint="default" * @since 2.0.0 Modified: trunk/maven-eugene-plugin/src/it/smart-generate/generators/src/main/java/org/nuiton/eugene/test/generator/BeanGenerator.java =================================================================== --- trunk/maven-eugene-plugin/src/it/smart-generate/generators/src/main/java/org/nuiton/eugene/test/generator/BeanGenerator.java 2010-11-26 17:24:18 UTC (rev 1001) +++ trunk/maven-eugene-plugin/src/it/smart-generate/generators/src/main/java/org/nuiton/eugene/test/generator/BeanGenerator.java 2010-11-27 15:55:17 UTC (rev 1002) @@ -46,7 +46,7 @@ * * Created: 17 avril 2009 * -* @author tony Chemit <chemit@codelutin.com> +* @author tchemit <chemit@codelutin.com> * @version $Revision$ * * Mise a jour: $Date$