Author: echatellier Date: 2011-07-05 16:13:10 +0200 (Tue, 05 Jul 2011) New Revision: 1051 Url: http://nuiton.org/repositories/revision/wikitty/1051 Log: Fix model transformation (to generate new modele instead of java) Modified: trunk/wikitty-generators/src/main/java/org/nuiton/wikitty/generator/WikittyPurifierTransformer.java Modified: trunk/wikitty-generators/src/main/java/org/nuiton/wikitty/generator/WikittyPurifierTransformer.java =================================================================== --- trunk/wikitty-generators/src/main/java/org/nuiton/wikitty/generator/WikittyPurifierTransformer.java 2011-07-05 14:12:19 UTC (rev 1050) +++ trunk/wikitty-generators/src/main/java/org/nuiton/wikitty/generator/WikittyPurifierTransformer.java 2011-07-05 14:13:10 UTC (rev 1051) @@ -5,7 +5,7 @@ * $Id$ * $HeadURL$ * %% - * Copyright (C) 2009 - 2010 CodeLutin, Benjamin Poussin + * Copyright (C) 2009 - 2011 CodeLutin, Benjamin Poussin, Chatellier Eric * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as @@ -25,35 +25,53 @@ package org.nuiton.wikitty.generator; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.nuiton.eugene.java.ObjectModelTransformerToJava; +import org.nuiton.eugene.GeneratorUtil; +import org.nuiton.eugene.Template; import org.nuiton.eugene.models.object.ObjectModel; import org.nuiton.eugene.models.object.ObjectModelAttribute; +import org.nuiton.eugene.models.object.ObjectModelBuilder; import org.nuiton.eugene.models.object.ObjectModelClass; +import org.nuiton.eugene.models.object.ObjectModelClassifier; +import org.nuiton.eugene.models.object.ObjectModelElement; +import org.nuiton.eugene.models.object.ObjectModelEnumeration; +import org.nuiton.eugene.models.object.ObjectModelGenerator; +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.eugene.models.object.ObjectModelTransformer; +import org.nuiton.eugene.models.object.ObjectModelType; /** - * this transformer read the original user model and generate the intermediate - * model needed by generators. + * This transformer read the original user model and generate the intermediate + * model needed by generators. * - * - * + * Currently: + * - manage name collision for attributes or methods inherited from two + * different classes */ -public class WikittyPurifierTransformer extends ObjectModelTransformerToJava { +public class WikittyPurifierTransformer extends ObjectModelTransformer<ObjectModel> { private static final Log log = LogFactory.getLog(WikittyPurifierTransformer.class); /** for a given class, store all the names used by this class and subClasses */ - Map<ObjectModelClass, List<String>> namesUsedByClass = new HashMap<ObjectModelClass, List<String>>(); + protected Map<ObjectModelClass, List<String>> namesUsedByClass = new HashMap<ObjectModelClass, List<String>>(); /** class of the original model that are already processed */ - List<ObjectModelClass> processedClasses = new ArrayList<ObjectModelClass>(); + protected List<ObjectModelClass> processedClasses = new ArrayList<ObjectModelClass>(); + /** Generated model builder. */ + protected ObjectModelBuilder builder; + /** * for a given, class read all attributes name and try to find conflicts * with parent classes attributes names. @@ -129,7 +147,7 @@ // using alternative name lead to a conflict attributeName = null; } else { - addTagValue(attribute, WikittyTransformerUtil.TAG_ALTERNATIVE_NAME, attributeName); + builder.addTagValue(attribute, WikittyTransformerUtil.TAG_ALTERNATIVE_NAME, attributeName); } } @@ -142,8 +160,17 @@ WikittyTransformerUtil.TAG_ALTERNATIVE_NAME + "\" on this attribute"); } else { + + if (isVerbose()) { + if (!attributeName.equals(attribute.getName())) { + log.info("attribute " + attribute.getName() + " purified to " + attributeName); + } + } + allUsedNames.add(attributeName); } + + } // saving all names we used in current class will permit to sub classes @@ -163,4 +190,304 @@ } } } + + @Override + protected Template<ObjectModel> initOutputTemplate() { + return new ObjectModelGenerator(); + } + + /* + * @see org.nuiton.eugene.models.object.ObjectModelTransformer#debugOutputModel() + */ + @Override + protected void debugOutputModel() { + + } + + /* + * @see org.nuiton.eugene.Transformer#initOutputModel() + */ + @Override + protected ObjectModel initOutputModel() { + builder = new ObjectModelBuilder(getModel().getName()); + ObjectModel model = builder.getModel(); + return model; + } + + /** + * creates a clone of the given {@code source} class in the output model + * and clones attributes, inheritance declarations and operations into the + * clone + * + * @param source the class to clone from the source model + * @param cloneDocumentation flag to add documentation if some found in model + * @return the clone of the given class + */ + public ObjectModelClass cloneClass(ObjectModelClass source, + boolean cloneDocumentation) { + ObjectModelClass outputClass = + builder.createClass(source.getName(), source.getPackageName()); + + cloneClassifier(source, outputClass, cloneDocumentation); + + for (ObjectModelClass superClass : source.getSuperclasses()) { + builder.addSuperclass(outputClass, superClass.getQualifiedName()); + } + + if (!CollectionUtils.isEmpty(source.getInnerClassifiers())) { + for (ObjectModelClassifier classifier : source.getInnerClassifiers()) { + ObjectModelClassifier innerClassifierClone = + cloneClassifier(classifier, cloneDocumentation); + builder.addInnerClassifier(outputClass, + ObjectModelType.OBJECT_MODEL_CLASSIFIER, + innerClassifierClone.getName()); + } + } + return outputClass; + } + + /** + * creates a clone of the given {@code source} classifier in the output + * model and clones attributes, inheritance declaration and operations + * + * class-specific, enumeration-specific and interface-specific features + * of the given classifier <strong>will</strong> be present in the clone + * + * @param source the classifier to clone from the source model + * @param cloneDocumentation flag to add documentation if some found in model + * @return the clone of the given classifier + */ + public ObjectModelClassifier cloneClassifier(ObjectModelClassifier source, + boolean cloneDocumentation) { + ObjectModelClassifier clone = null; + if (source.isInterface()) { + clone = cloneInterface((ObjectModelInterface) source, cloneDocumentation); + } else if (source.isClass()) { + clone = cloneClass((ObjectModelClass) source, cloneDocumentation); + } else if (source.isEnum()) { + clone = cloneEnumeration((ObjectModelEnumeration) source, cloneDocumentation); + } else { + // should never occur + log.error("strange classifier " + source); + } + return clone; + } + + /** + * creates a clone of the given {@code source} interface in the output model + * and clones attributes, inheritance declaration and operations into the + * clone + * + * @param source the interface to clone from the source model + * @param cloneDocumentation flag to add documentation if some found in model + * @return the clone of the given interface + */ + public ObjectModelInterface cloneInterface(ObjectModelInterface source, + boolean cloneDocumentation) { + ObjectModelInterface outputInterface = + builder.createInterface(source.getName(), source.getPackageName()); + + cloneClassifier(source, outputInterface, cloneDocumentation); + // nothing more to do. copyClassifier already done the job + + return outputInterface; + } + + /** + * creates a clone of the given {@code source} enumeration in the output + * model and clones attributes, inheritance declaration, operations and + * literals into the clone + * + * @param source the enumeration to clone from the source model + * @param cloneDocumentation flag to add documentation if some found in model + * @return the clone of the given enumeration + */ + public ObjectModelEnumeration cloneEnumeration(ObjectModelEnumeration source, + boolean cloneDocumentation) { + ObjectModelEnumeration outputEnumeration = + builder.createEnumeration(source.getName(), source.getPackageName()); + + cloneClassifier(source, outputEnumeration, cloneDocumentation); + + for (String literal : source.getLiterals()) { + builder.addLiteral(outputEnumeration, literal); + } + + return outputEnumeration; + } + + /** + * copy attributes, interfaces declaration 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 #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 + */ + protected void cloneClassifier(ObjectModelClassifier source, + ObjectModelClassifier destination, + boolean copyDocumentation) { + + cloneTagValues(source, destination); + + cloneStereotypes(source, destination); + + for (ObjectModelAttribute attribute : source.getAttributes()) { + cloneAttribute(attribute, destination, copyDocumentation); + } + + for (ObjectModelInterface interfacez : source.getInterfaces()) { + builder.addInterface(destination, interfacez.getQualifiedName()); + } + + for (ObjectModelOperation operation : source.getOperations()) { + cloneOperation(operation, destination, copyDocumentation); + } + } + + /** + * Clone the {@code source} operation into the {@code destination} classifier. + * whole signature, tagValues and body code will be cloned. You can specify + * {@code modifiers} for the result operation. + * + * @param source operation to clone + * @param destination classifier where result operation will be added + * @param cloneDocumentation flag to add documentation if some found in model + * @param modifiers extra modifiers + * @return the new operation created in destination classifier + */ + public ObjectModelOperation cloneOperation(ObjectModelOperation source, + ObjectModelClassifier destination, + boolean cloneDocumentation, + ObjectModelModifier... modifiers) { + ObjectModelOperation outputOperation = cloneOperationSignature( + source, + destination, + cloneDocumentation, + modifiers + ); + + // add body only if operation is not abstract + boolean opAbstract = false; + for (ObjectModelModifier modifier : modifiers) { + if (modifier == ObjectModelModifier.ABSTRACT) { + opAbstract = true; + break; + } + } + if (!opAbstract) { + builder.setOperationBody(outputOperation, source.getBodyCode()); + } + return outputOperation; + } + + /** + * Copy all tag values for the given {@code source} to the given + * {@code destination}. + * + * @param source the source element + * @param destination the destination element + */ + protected void cloneTagValues(ObjectModelElement source, + ObjectModelElement destination) { + Map<String, String> tags = source.getTagValues(); + for (Map.Entry<String, String> entry : tags.entrySet()) { + builder.addTagValue(destination,entry.getKey(),entry.getValue()); + } + } + + /** + * + * @param source + * @param destination + */ + protected void cloneStereotypes(ObjectModelClassifier source, + ObjectModelClassifier destination) { + + Collection<String> stereotypes = source.getStereotypes(); + for (String stereotype : stereotypes) { + builder.addStereotype(destination,stereotype); + } + } + + /** + * Clone the {@code source} operation into the {@code destination} classifier. + * name, returnType, parameters, exceptions and tagValues will be cloned. + * You can specify {@code modifiers} for the result operation. + * + * @param source operation to clone + * @param destination classifier where result operation will be added + * @param cloneDocumentation flag to add documentation if some found in model + * @param modifiers extra modifiers + * @return the new operation created in destination classifier + */ + public ObjectModelOperation cloneOperationSignature(ObjectModelOperation source, + ObjectModelClassifier destination, + boolean cloneDocumentation, + ObjectModelModifier... modifiers) { + + ObjectModelOperation outputOperation = + builder.addOperation(destination, source.getName(), source.getReturnType(), modifiers); + + if (cloneDocumentation && GeneratorUtil.hasDocumentation(source)) { + builder.setDocumentation(outputOperation, source.getDocumentation()); + } + + for (ObjectModelParameter parameter : source.getParameters()) { + + ObjectModelParameter outputParam = + builder.addParameter(outputOperation, parameter.getType(), parameter.getName()); + + if (cloneDocumentation && GeneratorUtil.hasDocumentation(parameter)) { + builder.setDocumentation(outputParam, parameter.getDocumentation()); + } + } + + for (String exception : source.getExceptions()) { + builder.addException(outputOperation, exception); + } + + cloneTagValues(source, outputOperation); + + return outputOperation; + } + + /** + * clone a given attribute into a classifier of the output model + * + * @param source the original attribute + * @param destination classifier where the clone will be added + * @param cloneDocumentation flag to add documentation if some found in model + * @param modifiers extra modifiers + * @return the clone attribute + */ + protected ObjectModelAttribute cloneAttribute(ObjectModelAttribute source, + ObjectModelClassifier destination, + boolean cloneDocumentation, + ObjectModelModifier... modifiers) { + + ObjectModelAttribute outputAttribute = builder.addAttribute(destination, + source.getName(), source.getType(), + source.getDefaultValue(), modifiers); + + cloneTagValues(source, outputAttribute); + + if (cloneDocumentation) { + builder.setDocumentation(outputAttribute, source.getDocumentation()); + } + + for (String comment : source.getComments()) { + builder.addComment(outputAttribute, comment); + } + + builder.setMinMultiplicity(outputAttribute, source.getMinMultiplicity()); + builder.setMaxMultiplicity(outputAttribute, source.getMaxMultiplicity()); + builder.setNavigable(outputAttribute,source.isNavigable()); + + return outputAttribute; + } }