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

org.nuiton.jaxx.compiler.java.JavaFileGenerator 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.collections4.CollectionUtils;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.nuiton.jaxx.compiler.JAXXCompiler;

import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumMap;
import java.util.List;
import java.util.Map.Entry;

/**
 * Java file generator.
 *
 * @author Tony Chemit - [email protected]
 * @since 2.0.0
 */
public class JavaFileGenerator {

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

    public static String getHeader(String header) {
        String all = "/*-----------------------------------------------------------------------*/";
        int size = header.length();
        if (size % 2 == 0) {
            size++;
            header = header + " ";
        }
        int semi = (all.length() - size) / 2 - 5;
        char[] prefix = new char[semi];
        Arrays.fill(prefix, '-');

        String eol = JAXXCompiler.getLineSeparator();

        return all + eol + "/*--" + new String(prefix) +
                " " + header + " " + new String(prefix) + "--*/" + eol + all +
                eol;
    }

    /** End of line */
    protected final String eol;

    /** verbose flag when generates */
    protected final boolean verbose;

    /** current prefix indent size */
    protected int indentationLevel;

    public JavaFileGenerator(String eol, boolean verbose) {
        this.eol = eol;
        this.verbose = verbose && log.isDebugEnabled();
    }

    public static String addDebugLoggerInvocation(JAXXCompiler compiler,
                                                  String call) {
        String eol = JAXXCompiler.getLineSeparator();
        StringBuilder builder = new StringBuilder();
        if (!compiler.getConfiguration().isAddLogger()) {
            return "";
        } else {
            builder.append("if (log.isDebugEnabled()) {");
            builder.append(eol);
            builder.append("    log.debug(").append(call).append(");");
            builder.append(eol);
            builder.append("}");
            builder.append(eol);
        }
        return builder.toString();
    }

    public String generateImport(String anImport) {
        return "import " + anImport + ';' + eol;
    }

    public void generateFile(JavaFile f, PrintWriter result) {
        String name = f.getName();
        if (verbose) {
            log.info(name);
        }
        indentationLevel = 0;
        String packageName = f.getPackageName();
//        if (name.contains(".")) {
        if (packageName != null) {
//            packageName = name.substring(0, name.lastIndexOf("."));
            result.append("package ");
            result.append(packageName);
            result.append(";");
            result.append(eol).append(eol);
        }

        generateImports(f, result);

        result.append(generateClass(f));
    }

    public void generateImports(JavaFile f, PrintWriter result) {

        List imports = f.getImportsList();

        boolean addImports = CollectionUtils.isNotEmpty(imports);
        for (String anImport : imports) {
            result.append(generateImport(anImport));
        }

        if (addImports) {
            result.append(eol);
        }
    }

    public String generateClass(JavaFile f) {
        if (verbose) {
            log.info(f.getName());
        }

        StringBuilder result = new StringBuilder();
        String genericType = f.getGenericType();

        result.append(f.getModifiersText());
        if (f.isAbstractClass()) {
            result.append("abstract ");
        }
        result.append("class ");
        result.append(f.getName().substring(f.getName().lastIndexOf(".") + 1));
        if (genericType != null) {
            result.append('<').append(genericType).append('>');
        }
        result.append(" extends ");
        result.append(f.getSuperClass());
        if (f.getSuperGenericType() != null) {
            result.append('<').append(f.getSuperGenericType()).append('>');
        }
        List interfaces = f.getInterfaces();

        if (interfaces != null && !interfaces.isEmpty()) {
            result.append(" implements ").append(interfaces.get(0));
            for (int i = 1; i < interfaces.size(); i++) {
                result.append(", ").append(interfaces.get(i));
            }
        }
        result.append(" {").append(eol);

        // generate fields

        List fields = f.getFields();

        if (!fields.isEmpty()) {

            EnumMap> map =
                    JavaField.getSortedFields(fields);
            for (Entry> entry :
                    map.entrySet()) {

                List list = entry.getValue();

                // sort fields
                Collections.sort(list);

                if (!list.isEmpty()) {

                    // add field group header
                    result.append(eol);
                    result.append(
                            addIndentation(entry.getKey().getHeader(), 4, eol));
                    result.append(eol);
                    result.append(eol);

                    // add all fields of group
                    for (JavaField method : list) {
                        String txt = generateField(method);
                        result.append(addIndentation(txt, 4, eol)).append(eol);
                    }
                }
                list.clear();
            }
            map.clear();
            result.append(eol);
        }

        // generate raw body

        StringBuilder rawBodyCode = f.getRawBodyCode();

        if (rawBodyCode.length() > 0) {
            result.append(addIndentation(
                    getHeader("Raw body code from script"), 4, eol));
            result.append(eol);
            String s = rawBodyCode.toString();
            if (!s.startsWith(eol)) {
                result.append(eol);
            }
            result.append(addIndentation(s, 4, eol)).append(eol).append(eol);
        }

        // generate inner classes

        List innerClasses = f.getInnerClasses();
        for (JavaFile innerClass : innerClasses) {
            indentationLevel += 4;
            try {
                String txt = generateClass(innerClass);
                result.append(addIndentation(txt, 4, eol));
                result.append(eol);
                result.append(eol);
            } finally {
                indentationLevel -= 4;
            }
        }


        // add constructors :

        result.append(addIndentation(JavaMethod.MethodOrder.constructors.getHeader(), 4, eol));
        result.append(eol);
        result.append(eol);

        // add all constructors
        for (JavaConstructor method : f.getConstructors()) {
            String txt = generateConstructor(method);
            result.append(addIndentation(txt, 4, eol));
            result.append(eol);
            result.append(eol);
        }

        // generate methods
        EnumMap> map =
                JavaMethod.getSortedMethods(f.getMethods());

        for (Entry> entry : map.entrySet()) {
            List list = entry.getValue();
            if (!list.isEmpty()) {

                // sort methods
                Collections.sort(list);

                // add method group header
                result.append(addIndentation(entry.getKey().getHeader(), 4, eol));
                result.append(eol);
                result.append(eol);

                // add all methods of group
                for (JavaMethod method : list) {
                    String txt = generateMethod(method);
                    result.append(addIndentation(txt, 4, eol));
                    result.append(eol);
                    result.append(eol);
                }
            }
            list.clear();
        }
        map.clear();
        result.append("}");
        return result.toString();
    }

    public String generateField(JavaField f) {
        if (verbose) {
            if (log.isDebugEnabled()) {
                log.debug(f.getName());
            }
        }
        StringBuilder result = new StringBuilder();
        generateAnnotations(f, result, eol);
        result.append(f.getModifiersText());
        result.append(f.getType()).append(' ').append(f.getName());
        if (f.getInitializer() != null) {
            result.append(" = ").append(f.getInitializer());
        }
        result.append(';').append(eol);
        return result.toString();
    }

    protected void generateAnnotations(JavaElement element,
                                       StringBuilder result,
                                       String separator) {
        if (element.hasAnnotations()) {
            for (String annotation : element.getAnnotations()) {
                if (!annotation.startsWith("@")) {
                    result.append("@");
                }
                result.append(annotation).append(separator);
            }
        }
    }

    public String generateConstructor(JavaConstructor m) {
        if (verbose) {
            log.info(m.getName());
        }

        StringBuilder result = new StringBuilder();

        generateAnnotations(m, result, eol);
        result.append(m.getModifiersText());
        result.append(m.getName());
        result.append('(');
        JavaArgument[] arguments = m.getArguments();

        // adding arguments

        if (arguments != null && arguments.length > 0) {
            result.append(generateArgument(arguments[0]));
            for (int i = 1; i < arguments.length; i++) {
                result.append(", ").append(generateArgument(arguments[i]));
            }
        }
        result.append(")");

        // adding exceptions

        String[] exceptions = m.getExceptions();
        if (exceptions != null && exceptions.length > 0) {
            result.append(" throws ").append(exceptions[0]);
            for (int i = 1; i < exceptions.length; i++) {
                result.append(", ").append(exceptions[i]);
            }
        }
        result.append(" {");
        result.append(eol);

        // adding body

        String body = m.getBody();

        if (body != null) {
            String formattedBodyCode = addIndentation(body.trim(), 4, eol);
            if (formattedBodyCode.length() > 0) {
                result.append(formattedBodyCode).append(eol);
            }
        }
        result.append("}");
        return result.toString();

    }

    public String generateMethod(JavaMethod m) {
        if (verbose) {
            log.info(m.getName());
        }

        StringBuilder result = new StringBuilder();
        if (m.isOverride()) {
            m.addAnnotation(Override.class.getSimpleName());
        }
        generateAnnotations(m, result, eol);
        result.append(m.getModifiersText());
        if (m.getReturnType() != null) {
            result.append(m.getReturnType());
            result.append(' ');
        }
        result.append(m.getName());
        result.append('(');
        JavaArgument[] arguments = m.getArguments();

        // adding arguments

        if (arguments != null && arguments.length > 0) {
            result.append(generateArgument(arguments[0]));
            for (int i = 1; i < arguments.length; i++) {
                result.append(", ").append(generateArgument(arguments[i]));
            }
        }
        result.append(")");

        // adding exceptions

        String[] exceptions = m.getExceptions();
        if (exceptions != null && exceptions.length > 0) {
            result.append(" throws ").append(exceptions[0]);
            for (int i = 1; i < exceptions.length; i++) {
                result.append(", ").append(exceptions[i]);
            }
        }

        if (m.isAbstract()) {
            result.append(";");
        } else {
            result.append(" {");
            result.append(eol);

            // adding body

            String body = m.getBody();

            if (body != null) {
                String formattedBodyCode = addIndentation(body.trim(), 4, eol);
                if (formattedBodyCode.length() > 0) {
                    result.append(formattedBodyCode).append(eol);
                }
            }
            result.append("}");
        }
        return result.toString();

    }

    public String generateArgument(JavaArgument argument) {
        String result = argument.getType() + ' ' + argument.getName();
        return argument.isFinal() ? "final " + result : result;
    }

    public String addIndentation(String source,
                                 int indentation,
                                 String lineSeparator) {
        return indent(source,
                      indentationLevel + indentation,
                      false,
                      lineSeparator
        );
    }

    public static String indent(String source,
                                int indentation,
                                boolean trim,
                                String lineSeparator) {
        if (trim) {
            source = source.trim();
        }
        char[] spaces = new char[indentation];
        Arrays.fill(spaces, ' ');
        StringBuilder result = new StringBuilder();
        String[] lines = source.split(lineSeparator + "|\n");
        for (int i = 0; i < lines.length; i++) {
            if (i > 0) {
                result.append(lineSeparator);
            }
            result.append(spaces);
            result.append(trim ? lines[i].trim() : lines[i]);
        }
        return result.toString();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy