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();
}
}