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

org.nuiton.jaxx.compiler.java.JavaFile Maven / Gradle / Ivy

The newest version!
/*
 * #%L
 * JAXX :: Compiler
 * %%
 * Copyright (C) 2008 - 2024 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.jaxx.compiler.java;

import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.nuiton.eugene.java.extension.ImportsManager;
import org.nuiton.jaxx.compiler.finalizers.JAXXCompilerFinalizer;
import org.nuiton.jaxx.compiler.types.TypeManager;

import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * A Java source file being generated for output.  Once the class is completely initialized, use the
 * {@link #toString} method to generate source code for it.
 */
public class JavaFile extends JavaElement {

    /** Logger. */
    static final Logger log = LogManager.getLogger(JavaFile.class);

    protected static final String GETTER_PATTERN = "return %1$s;";

    protected static final String BOOLEAN_GETTER_PATTERN = "return %1$s !=null && %1$s;";

    protected static final String SETTER_PATTERN = "%1$s oldValue = this.%2$s;\nthis.%2$s = %2$s;\nfirePropertyChange(%3$s, oldValue, %2$s);";

    private Set imports = new HashSet<>();

    private List fields = new ArrayList<>();

    private List methods = new ArrayList<>();

    private List constructors = new ArrayList<>();

    private final List innerClasses = new ArrayList<>();

    private String superClass;

    private List interfaces;

    private final StringBuilder rawBodyCode = new StringBuilder();

    private boolean superclassIsJAXXObject;

    private boolean abstractClass;

    private String genericType;

    private String superGenericType;

    private final ImportsManager importManager;

    private String simpleName;

    JavaFile(int modifiers, String packageName,String className) {
        super(modifiers, packageName+"."+className);
        importManager = new ImportsManager();
        // add the fqn before all in the import manager to deal with alias classes
        importManager.addImport(packageName+"."+className);
        setSimpleName(className);
    }

    JavaFile(int modifiers, String className) {
        super(modifiers, className);
        importManager = new ImportsManager();
        // add the fqn before all in the import manager to deal with alias classes
        importManager.addImport(className);
    }

    public String getPackageName() {
        String name = getName();

        String packageName;
        if (name.contains(".")) {
            packageName = name.substring(0, name.lastIndexOf("."));
        } else {
            packageName = null;
        }
        return packageName;
    }

    public ImportsManager getImportManager() {
        return importManager;
    }

    public String getImportedType(Class type) {
        return getImportManager().getType(type);
    }

    public String getImportedType(String type) {
        return getImportManager().getType(type);
    }

    public String[] getImports() {
        List result = new ArrayList<>(imports);
        Collections.sort(result);
        return result.toArray(new String[result.size()]);
    }

    public List getImportsList() {
        List result = new ArrayList<>(imports);
        Collections.sort(result);
        return result;
    }

    public String getSuperClass() {
        return superClass;
    }

    public List getInterfaces() {
        if (interfaces == null) {
            interfaces = new ArrayList<>();
        }
        return interfaces;
    }

    public List getMethods() {
        return methods;
    }

    public List getFields() {
        return fields;
    }

    public boolean isAbstractClass() {
        return abstractClass;
    }

    public String getGenericType() {
        return genericType;
    }

    public List getInnerClasses() {
        return innerClasses;
    }

    public StringBuilder getRawBodyCode() {
        return rawBodyCode;
    }

    public String getSuperGenericType() {
        return superGenericType;
    }

    public boolean isSuperclassIsJAXXObject() {
        return superclassIsJAXXObject;
    }

    public String getSimpleName() {
        return simpleName;
    }

    public JavaField getField(String componentId) {
        for (JavaField field : fields) {
            if (componentId.equals(field.getName())) {
                return field;
            }
        }
        return null;
    }

    public void addImport(String importString) {
        try {
            importManager.addImport(importString);
        } catch (Exception e) {
            log.error("Could not determine simple name of import " + importString);
        }
    }

    public void addImport(Class importString) {
        addImport(importString.getName());
    }

    public void setImports(Collection imports) {
        this.imports = new HashSet<>(imports);
    }

    public void setGenericType(String genericType) {
        this.genericType = genericType;
    }

    public void setSuperClass(String superClass) {
        this.superClass = superClass;
    }

    public void addInterface(String... canonicalNames) {
        if (canonicalNames == null) {
            return;
        }
        for (String canonicalName : canonicalNames) {
            if (interfaces == null || !interfaces.contains(canonicalName)) {
                getInterfaces().add(canonicalName);
            }
        }
    }

    public void setInterfaces(List interfaces) {
        List simpleInterfaces = new ArrayList<>();
        for (String anInterface : interfaces) {
            try {
                anInterface = importManager.getType(anInterface);
            } catch (Exception e) {
                log.error("Could not determine simple name of interface " +
                                  anInterface);
            }
            simpleInterfaces.add(anInterface);
        }
        this.interfaces = simpleInterfaces;
    }

    public void addConstructor(JavaConstructor constructor) {
        constructors.add(constructor);
    }

    public void addMethod(JavaMethod method) {
        String returnType = method.getReturnType();
        try {
            String type = importManager.getReturnType(returnType);
            method.setReturnType(type);
        } catch (Exception e) {
            log.error("Could not determine simple name of return type " +
                              returnType + " for method " + method.getName());
        }
        for (JavaArgument argument : method.getArguments()) {
            String argumentType = argument.getType();
            try {
                String type = importManager.getType(argumentType);
                argument.setType(type);
            } catch (Exception e) {
                log.error("Could not determine simple name of argument type " +
                                  argumentType + " of argument " + argument.getName() +
                                  " for method " + method.getName());
            }
        }

        String[] exceptions = method.getExceptions();
        for (int i = 0, length = exceptions.length; i < length; i++) {
            String exception = exceptions[i];
            try {
                String exceptionSimple = importManager.getType(exception);
                exceptions[i] = exceptionSimple;
            } catch (Exception e) {
                log.error("Could not determine simple name of exception " +
                                  exception + " for method " + method.getName());
            }

        }

        // this is a mreal method
        methods.add(method);
    }

    public void addField(JavaField field) {

        addField(field, false);
    }

    public JavaMethod addGetterMethod(String id,
                                      int modifiers,
                                      String type,
                                      boolean override,
                                      boolean useOverride) {

        String capitalizedName = StringUtils.capitalize(id);
        String methodName = "get" + capitalizedName;
        String bodyCode;
        if (useOverride) {
            bodyCode = "super." + methodName + "()";
        } else {
            bodyCode = id;
        }
        String content = String.format(GETTER_PATTERN, bodyCode);
        JavaMethod method = JavaElementFactory.newMethod(modifiers,
                                                         type,
                                                         methodName,
                                                         content,
                                                         override
        );
        addMethod(method);
        return method;
    }

    public JavaMethod addAbstractGetterMethod(String id,
                                              int modifiers,
                                              String type,
                                              boolean override) {
        String capitalizedName = StringUtils.capitalize(id);
        String methodName = "get" + capitalizedName;
        JavaMethod method = JavaElementFactory.newMethod(modifiers | Modifier.ABSTRACT,
                                                         type,
                                                         methodName,
                                                         null,
                                                         override
        );
        addMethod(method);
        return method;
    }

    public JavaMethod addOverrideGetterMethod(String id,
                                              int modifiers,
                                              String type,
                                              boolean override) {

        String capitalizedName = StringUtils.capitalize(id);
        String methodName = "get" + capitalizedName;
        String bodyCode;
        if (override) {
            bodyCode = "super." + methodName + "()";
        } else {
            bodyCode = id;
        }
        bodyCode = "(" + type + ") " + bodyCode;
        String content = String.format(GETTER_PATTERN, bodyCode);
        JavaMethod method = JavaElementFactory.newMethod(modifiers,
                                                         type,
                                                         methodName,
                                                         content,
                                                         override
        );
        addMethod(method);
        return method;
    }

    public void addField(JavaField field, boolean javaBean) {
        addSimpleField(field);
        String id = field.getName();
        String capitalizedName = StringUtils.capitalize(id);

        // add accessor method
        int modifiers = Modifier.isProtected(field.getModifiers()) ?
                Modifier.PUBLIC : Modifier.PROTECTED;

        addGetterMethod(id,
                        modifiers,
                        field.getType(),
                        field.isOverride(),
                        false
        );

        if (javaBean) {
            // add full javabean support accessor + mutator + constant with
            // name of property to make it easier to use
            // compute the property constant
            String constantId = TypeManager.convertVariableNameToConstantName(
                    "property" + capitalizedName);
            addSimpleField(JavaElementFactory.newField(
                    Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL,
                    JAXXCompilerFinalizer.TYPE_STRING,
                    constantId, false, "\"" + id + "\"")
            );

            if (Boolean.class.getSimpleName().equals(field.getType())) {
                String content = String.format(BOOLEAN_GETTER_PATTERN, id);
                JavaMethod method = JavaElementFactory.newMethod(
                        Modifier.PUBLIC,
                        field.getType(),
                        "is" + capitalizedName,
                        content,
                        field.isOverride()
                );
                addMethod(method);
            }
            String content = String.format(SETTER_PATTERN,
                                           field.getType(),
                                           id,
                                           constantId
            );
            JavaArgument arg = JavaElementFactory.newArgument(field.getType(),
                                                              id);
            JavaMethod method = JavaElementFactory.newMethod(
                    Modifier.PUBLIC,
                    JAXXCompilerFinalizer.TYPE_VOID,
                    "set" + capitalizedName,
                    content,
                    field.isOverride(),
                    arg);
            addMethod(method);
        }
    }

    public void addSimpleField(JavaField field) {
        if (log.isDebugEnabled()) {
            log.debug("[" + getName() + "] Add field " + field.getName());
        }
        String fieldType = field.getType();
        try {
            String type = importManager.getType(fieldType);
            field.setType(type);
        } catch (Exception e) {
            log.error("Could not determine simple name of field [" +
                              field.getName() + "] type " + fieldType);
        }
        if (field.hasInitializerTypes()) {
            String code = simplifyCode(field.getInitializer(),
                                       field.getInitializerTypes());
            if (log.isDebugEnabled()) {
                log.debug("Use simplify text : " + code);
            }
            field.setInitializer(code);
        }
        fields.add(field);
    }

    public void setSuperclassIsJAXXObject(boolean superclassIsJAXXObject) {
        this.superclassIsJAXXObject = superclassIsJAXXObject;
    }

    public void setAbstractClass(boolean abstractClass) {
        this.abstractClass = abstractClass;
    }

    public void setSuperGenericType(String superGenericType) {
        this.superGenericType = superGenericType;
    }

    public void addBodyCode(String bodyCode) {
        rawBodyCode.append(bodyCode);
    }

    /**
     * Try to use a simple type fro the given {@code type} and apply it on the
     * given {@code pattern}.
     * 

* Example : *

     * type = java.io.File, pattern = new %s("");
     * returns : new File("") or new java.io.File("") if importManager can
     * not import java.io.File
     * 
* * @param types the types to simplify * @param pattern the pattern where to apply simple types * @return the input pattern with most simplest types * @since 2.4 */ public String simplifyCode(String pattern, String... types) { String[] simpleTypes = new String[types.length]; for (int i = 0; i < types.length; i++) { String type = types[i]; String simpleType = importManager.getType(type); simpleTypes[i] = simpleType; } return String.format(pattern, (Object[]) simpleTypes); } public void clear() { importManager.clearImports(); if (interfaces != null) { interfaces.clear(); interfaces = null; } if (methods != null) { methods.clear(); methods = null; } if (constructors != null) { constructors.clear(); constructors = null; } if (fields != null) { fields.clear(); fields = null; } if (imports != null) { imports.clear(); } } public List getConstructors() { return constructors; } public void setSimpleName(String simpleName) { this.simpleName = simpleName; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy