All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nuiton.eugene.java.JavaBuilder Maven / Gradle / Ivy

/*
 * #%L
 * EUGene :: EUGene Core
 * %%
 * Copyright (C) 2004 - 2017 Code Lutin, Ultreia.io
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as 
 * published by the Free Software Foundation, either version 3 of the 
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public 
 * License along with this program.  If not, see
 * .
 * #L%
 */

package org.nuiton.eugene.java;

import com.google.common.base.Preconditions;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.nuiton.eugene.GeneratorUtil;
import org.nuiton.eugene.java.extension.AnnotationsManager;
import org.nuiton.eugene.java.extension.AnnotationsManagerExtension;
import org.nuiton.eugene.java.extension.CodesManager;
import org.nuiton.eugene.java.extension.CodesManagerExtension;
import org.nuiton.eugene.java.extension.ConstantsManagerExtension;
import org.nuiton.eugene.java.extension.ImportsManager;
import org.nuiton.eugene.java.extension.ImportsManagerExtension;
import org.nuiton.eugene.java.extension.ObjectModelAnnotation;
import org.nuiton.eugene.java.extension.ObjectModelAnnotationParameter;
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.ObjectModelJavaModifier;
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.xml.ObjectModelClassImpl;
import org.nuiton.eugene.models.object.xml.ObjectModelOperationImpl;

import javax.lang.model.SourceVersion;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

/**
 * JavaBuilder
 * 
 * Created: 29 oct. 2009
 * 
 * Builder to fill an empty ObjectModel with java specificities
 * (imports, only one inheritance, constructor, ...).
 * 
 * JavaBuilder uses some extensions to manage imports , constants, annotations,
 * ...in the model.
 * 
 * JavaBuilder is also based on ObjectModelBuilder for the simple filling of
 * the model.
 *
 * @author Florian Desbois - [email protected]
 * @author Tony Chemit - [email protected]
 */
public class JavaBuilder extends ObjectModelBuilder {

    private static final Logger log = LogManager.getLogger(JavaBuilder.class);

    /** ObjectModel extension to manage imports : one ImportsManager by classifier */
    protected ImportsManagerExtension importsManagerExtension;

    /** ObjectModel extension to manage imports : one ImportsManager by classifier */
    protected AnnotationsManagerExtension annotationsManagerExtension;

    /** ObjectModel extension to manage constants : one ConstantsManager for all */
    protected ConstantsManagerExtension constantsManagerExtension;

    /** ObjectModel extension to manage operation boby codes */
    protected CodesManagerExtension codesManagerExtension;

    public JavaBuilder(String modelName) {
        super(modelName);

        importsManagerExtension = getModel().getExtension(
                ImportsManagerExtension.OBJECTMODEL_EXTENSION,
                ImportsManagerExtension.class);

        annotationsManagerExtension = getModel().getExtension(
                AnnotationsManagerExtension.OBJECTMODEL_EXTENSION,
                AnnotationsManagerExtension.class);

        constantsManagerExtension = getModel().getExtension(
                ConstantsManagerExtension.OBJECTMODEL_EXTENSION,
                ConstantsManagerExtension.class);

        codesManagerExtension = getModel().getExtension(
                CodesManagerExtension.OBJECTMODEL_EXTENSION,
                CodesManagerExtension.class);
    }

    /**
     * Add an interface to a classifier (interface, class, enum).
     * IMPORTS interfaceQualifiedName.
     *
     * @param classifier             the classifier on which to add the interface
     * @param interfaceQualifiedName fully qualified name of the interface
     */
    @Override
    public void addInterface(ObjectModelClassifier classifier,
                             String interfaceQualifiedName) {
        super.addInterface(classifier, interfaceQualifiedName);
        addImport(classifier, interfaceQualifiedName);
    }

    @Override
    public void addSuperclass(ObjectModelClass clazz, String superclassQualifiedName)
            throws UnsupportedOperationException {
        throw new UnsupportedOperationException("This operation can't be used" +
                                                " to generate Java, use setSuperClass method instead");
    }

    /**
     * Add a new attribute to a classifier.
     * IMPORTS type.
     *
     * @param classifier the classifier on which to add the attribute
     * @param name       name of attribute
     * @param type       type of attribute
     * @param value      initializer value of attribute
     * @param modifiers  modifiers of the attribute
     * @return a new ObjectModelAttribute
     */
    @Override
    public ObjectModelAttribute addAttribute(ObjectModelClassifier classifier,
                                             String name,
                                             String type,
                                             String value,
                                             ObjectModelModifier... modifiers) {
        addImport(classifier, type);
        // ANO#474 FD-20100408 : problem with import from defaultValue, will
        // not be supported from version 2.0.1
        //this.addImport(classifier, value);
        return super.addAttribute(classifier,
                                  name,
                                  type,
                                  value,
                                  modifiers
        );
    }

    /**
     * Add a new attribute to a classifier with no default value.
     * Default visibility is set to PROTECTED.
     * IMPORTS type.
     *
     * @param classifier the classifier on which add the attribute
     * @param name       name of the attribute
     * @param type       type of the attribute
     * @return a new ObjectModelAttribute
     */
    @Override
    public ObjectModelAttribute addAttribute(ObjectModelClassifier classifier,
                                             String name,
                                             String type) {
        return addAttribute(classifier,
                            name,
                            type,
                            "",
                            ObjectModelJavaModifier.PROTECTED
        );
    }

    /**
     * Add a new operation to a classifier.
     *
     * @param classifier the classifier on which to add the operation
     * @param name       the name of the operation
     * @param type       the return type of the operation
     * @param modifiers  the modifiers of the operation
     * @return a new ObjectModelOperation
     */
    @Override
    public ObjectModelOperation addOperation(ObjectModelClassifier classifier,
                                             String name,
                                             String type,
                                             ObjectModelModifier... modifiers) {
        addImport(classifier, type);
        return super.addOperation(classifier, name, type, modifiers);
    }

    /**
     * Add a new parameter to an existing operation.
     *
     * @param operation the operation on which to add a parameter
     * @param type      the type of the parameter
     * @param name      the name of the parameter
     * @return a new ObjectModelParameter
     */
    @Override
    public ObjectModelParameter addParameter(ObjectModelOperation operation,
                                             String type,
                                             String name) {
        addImport((ObjectModelClassifier) operation.getDeclaringElement(),
                  type);
        return super.addParameter(operation, type, name);
    }

    /**
     * Add an exception to an operation.
     *
     * @param operation the operation on which to add a exeception
     * @param exception the exception to add
     */
    @Override
    public void addException(ObjectModelOperation operation, String exception) {
        addImport((ObjectModelClassifier) operation.getDeclaringElement(),
                  exception);
        super.addException(operation, exception);
    }

    /**
     * Set the operation body code.
     *
     * @param operation the operation on which to add the body code
     * @param body      the body code to set on the operation
     * @throws IllegalArgumentException if operation is abstract
     */
    @Override
    public void setOperationBody(ObjectModelOperation operation, String body)
            throws IllegalArgumentException {
        if (operation.isAbstract()) {
            throw new IllegalArgumentException(
                    "Unable to add body for an abstract method");
        }
        super.setOperationBody(operation, body);
    }

    /**
     * Create a new abstract class in the model.
     *
     * @param name        the name of the abstract class to create
     * @param packageName package's name of the class to create
     * @return a new ObjectModelClass
     * @see ObjectModelBuilder#createClass(String, String, ObjectModelModifier...)
     */
    public ObjectModelClass createAbstractClass(String name,
                                                String packageName) {
        return createClass(name, packageName, ObjectModelJavaModifier.ABSTRACT);
    }

    /**
     * Add an import to a classifier. Imports are automatic for lots of
     * JavaBuilder's methods except body code of operations.
     * 
     * You can have some complex imports like :
     * - new java.util.List<org.chorem.bonzoms.Role>()
     *  --> two imports 'java.util.List' and 'org.chorem.bonzoms.Role'
     * - java.util.Collection<T extends org.nuiton.topia.TopiaEntity>
     *  --> two imports 'java.util.Collection' and 'org.nuiton.topia.TopiaEntity'
     * 
* * @param classifier where the imports will be added. * @param imports to add * @see GeneratorUtil#getTypesList(String) */ public void addImport(ObjectModelClassifier classifier, String imports) { if (imports == null) { return; } ImportsManager manager = getImportManager(classifier); imports = imports.trim(); // remove ... operator if (imports.endsWith("...")) { imports = imports.substring(0, imports.length() - 3); } for (String oneType : GeneratorUtil.getTypesList(imports)) { manager.addImport(oneType); if (log.isDebugEnabled()) { log.debug("Add import for : " + classifier.getQualifiedName() + " _ import: " + oneType); } } } public String importAndSimplify(ObjectModelClassifier classifier, String imports) { ImportsManager manager = getImportManager(Objects.requireNonNull(classifier)); imports = Objects.requireNonNull(imports).trim(); // remove ... operator if (imports.endsWith("...")) { imports = imports.substring(0, imports.length() - 3); return importAndSimplify(classifier, imports)+"..."; } Set typesList = GeneratorUtil.getTypesList(imports); if (typesList.size()>1) { // Can't simplify in this case (need to rebuild the hole thing, not now...) typesList.forEach(manager::addImport); return imports; } String oneType = typesList.iterator().next(); return manager.importAndSimplify(oneType); } /** * Add an annotation on an element of a classifier. * * @param classifier where the annotation will be added. * @param element element on which add annotation * @param annotationType type of annotation to add * @return the instanciated annotation */ public ObjectModelAnnotation addAnnotation(ObjectModelClassifier classifier, ObjectModelElement element, String annotationType) { Preconditions.checkNotNull("Can't add a null annotation"); Preconditions.checkArgument( SourceVersion.isName(annotationType), "Annotation type must be a valid type , but was: " + annotationType); AnnotationsManager manager = annotationsManagerExtension.getManager(classifier); ObjectModelAnnotation annotation = new ObjectModelAnnotation(annotationType); manager.addAnnotation(element, annotation); if (log.isDebugEnabled()) { log.debug("Add annotation for <" + classifier.getQualifiedName() + ":" + element.getName() + "> : " + annotation); } return annotation; } public ObjectModelAnnotation addAnnotationParameter(ObjectModelAnnotation annotation, String parameterName, Object parameterValue) { annotation.addParameter(new ObjectModelAnnotationParameter(parameterName, parameterValue)); return annotation; } /** * Set the superclass of an other class. Only one superclass can be set * to the class. * IMPORTS superclassQualifiedName. * * @param classifier the classifier on which to set the super class * @param superclassQualifiedName fully qualified name of the super class */ public void setSuperClass(ObjectModelClass classifier, String superclassQualifiedName) { ObjectModelClassImpl impl = (ObjectModelClassImpl) classifier; // suppress all existing superclass: only one can be set for java impl.clearSuperclasses(); super.addSuperclass(impl, superclassQualifiedName); addImport(classifier, superclassQualifiedName); } /** * Add a new constant to a classifier. A constant is static and final * and have a value. * IMPORTS type, value. * * @param classifier the classifier on which to add the constant field * @param name name of the constant field * @param type type of the constant field * @param value initializer value of the constant field * @param visibility modifier allowed : PUBLIC, PRIVATE, PROTECTED, PACKAGE * @return a new ObjectModelAttribute * @throws IllegalArgumentException if the modifier is not a visibility */ public ObjectModelAttribute addConstant(ObjectModelClassifier classifier, String name, String type, String value, ObjectModelModifier visibility) throws IllegalArgumentException { if (!visibility.isVisibility()) { throw new IllegalArgumentException( "Illegal visibility type : " + visibility.toString() + " for " + classifier.getQualifiedName()); } return addAttribute(classifier, name, type, value, visibility, ObjectModelJavaModifier.STATIC, ObjectModelJavaModifier.FINAL ); } /** * Add a body code to the operation of a classifier. * * @param classifier where the body code will be added. * @param operation operation on which add body code * @param code code to add */ public void addBodyCode(ObjectModelClassifier classifier, ObjectModelOperation operation, String code) { if (code == null) { return; } CodesManager manager = codesManagerExtension.getManager(classifier); code = code.trim(); manager.addCode(operation, code); if (log.isDebugEnabled()) { log.debug("Add code for <" + classifier.getQualifiedName() + ":" + operation.getName() + "> : " + code); } } /** * Converts the given {@code propertyName} to a constant name. * * For example : *
     * "CONSTANT_A" = getConstantName("constantA");
     * 
* * @param propertyName the name of the property to convert * @return the constant name */ public String getConstantName(String propertyName) { String result = constantsManagerExtension.getConstantName(propertyName); if (log.isDebugEnabled()) { log.debug("get constant name for <" + propertyName + "> : " + result); } return result; } /** * Add a new attribute to a classifier from an existing attribute. * IMPORTS attribute.getType() and attribute.getDefaultValue(). * * @param classifier the classifier on which to add the attribute * @param attribute the attribute to add * @return a new ObjectModelAttribute */ public ObjectModelAttribute addAttribute(ObjectModelClassifier classifier, ObjectModelAttribute attribute) { Set modifiers = new HashSet<>(); if (attribute.isStatic()) { modifiers.add(ObjectModelJavaModifier.STATIC); } if (attribute.isFinal()) { modifiers.add(ObjectModelJavaModifier.FINAL); } if (attribute.isTransient()) { modifiers.add(ObjectModelJavaModifier.TRANSIENT); } modifiers.add(ObjectModelJavaModifier.fromVisibility(attribute.getVisibility())); return addAttribute( classifier, attribute.getName(), attribute.getType(), attribute.getDefaultValue(), modifiers.toArray(new ObjectModelModifier[modifiers.size()]) ); } /** * Add a new block to a classifier. * * @param classifier the classifier on which to add the block * @param modifiers the modifiers of the operation * @return a new ObjectModelOperation * @see ObjectModelBuilder#addOperation(ObjectModelClassifier, String, String, ObjectModelModifier...) */ public ObjectModelOperation addBlock(ObjectModelClassifier classifier, ObjectModelModifier... modifiers) { ObjectModelOperationImpl operation = (ObjectModelOperationImpl) addOperation(classifier, null, null, modifiers); if (Arrays.asList(modifiers).contains(ObjectModelJavaModifier.STATIC)) { operation.setStatic(true); } return operation; } /** * Add a constructor to a class. * * @param clazz the classifier on which to add the constructor * @param visibility the visibility of the operation * @return a new ObjectModelOperation * @throws IllegalArgumentException if the modifier is not a visibility */ public ObjectModelOperation addConstructor(ObjectModelClass clazz, ObjectModelModifier visibility) throws IllegalArgumentException { return addConstructorForClassifier(clazz, visibility); } /** * Add a constructor to a enumeration. * * @param enumeration the enumeration on which to add the constructor * @param visibility the visibility of the constructor (should always to private...) * @return the new constructor * @throws IllegalArgumentException if visibility is not ok */ public ObjectModelOperation addConstructor(ObjectModelEnumeration enumeration, ObjectModelModifier visibility) throws IllegalArgumentException { return addConstructorForClassifier(enumeration, visibility); } protected ObjectModelOperation addConstructorForClassifier( ObjectModelClassifier classifier, ObjectModelModifier visibility) { if (!visibility.isVisibility()) { throw new IllegalArgumentException( "Illegal visibility type : " + visibility.toString() + " for " + classifier.getQualifiedName()); } String simpleName = JavaGeneratorUtil.removeAnyGenericDefinition( classifier.getName()); return addOperation(classifier, simpleName, null, visibility); } public ImportsManager getImportManager(ObjectModelClassifier clazz) { return importsManagerExtension.getManager(clazz); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy