de.knightsoftnet.gwtp.spring.annotation.processor.AbstractBackofficeCreator Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License. You may obtain a
* copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package de.knightsoftnet.gwtp.spring.annotation.processor;
import de.knightsoftnet.validators.annotation.processor.TypeUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.processing.FilerException;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
/**
* Create class or interface.
*/
public abstract class AbstractBackofficeCreator {
private final List imports;
protected final String suffix;
protected AbstractBackofficeCreator(final String suffix) {
super();
imports = new ArrayList<>();
this.suffix = suffix;
}
public String getSuffix() {
return suffix;
}
/**
* write class or interface.
*
* @param element the element which represents the entity
* @param annotationInterface annotation interface
* @param processingEnv processing environment
*/
public void writeClassOrInterface(final Element element, final T annotationInterface,
final ProcessingEnvironment processingEnv) {
try {
final String serverPackage = processingEnv.getElementUtils()
.getPackageOf(element.getEnclosingElement()).getQualifiedName().toString();
final String entityType = getEntityNameOfElement(element);
final JavaFileObject builderFile =
processingEnv.getFiler().createSourceFile(serverPackage + "." + entityType + suffix);
try (PrintWriter out = new PrintWriter(builderFile.openWriter())) {
out.print("package ");
out.print(serverPackage);
out.println(";");
out.println();
addAdditionalImports(serverPackage, element, annotationInterface);
writeImports(out, serverPackage);
out.println();
writeBody(out, serverPackage, element, annotationInterface, processingEnv);
}
} catch (final FilerException e) {
// happens when trying to recreate an existing interface
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, e.getMessage());
} catch (final IOException e) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, e.getMessage());
e.printStackTrace();
}
}
protected String getPackageOfElement(final Element element) {
final String entityName = element.asType().toString();
final int packagePos = entityName.lastIndexOf('.');
return entityName.substring(0, packagePos);
}
protected String getEntityNameOfElement(final Element element) {
final String entityName = element.asType().toString();
final int packagePos = entityName.lastIndexOf('.');
return entityName.substring(packagePos + 1);
}
/**
* add import line.
*
* @param classWithPaths class including pass to import
*/
protected void addImports(final String... classWithPaths) {
Stream.of(classWithPaths).forEach(this::addImport);
}
/**
* add import line.
*
* @param typeMirrors class including pass to import
*/
protected void addImports(final TypeMirror... typeMirrors) {
Stream.of(typeMirrors).forEach(this::addImport);
}
/**
* add import line.
*
* @param classWithPath class including pass to import
*/
protected void addImport(final String classWithPath) {
imports.add(classWithPath);
}
/**
* add import line.
*
* @param typeMirror type mirror of the class to add
*/
protected void addImport(final TypeMirror typeMirror) {
addImport(typeMirror.toString());
}
/**
* write import lines.
*
* @param out print writer
* @param classPath path of the class (or interface) to crate
*/
protected void writeImports(final PrintWriter out, final String classPath) {
String lastPrefix = firstTwoPartsOfPath(classPath);
imports.sort(new ImportComparator(lastPrefix));
for (final String importValue : imports) {
if (!importValue.startsWith(lastPrefix)) {
out.println();
lastPrefix = firstPartOfPath(importValue);
}
out.print("import ");
out.print(importValue);
out.println(";");
}
}
protected String firstPartOfPath(final String classPath) {
final int pos1 = classPath.indexOf('.');
return classPath.substring(0, pos1);
}
protected String firstTwoPartsOfPath(final String classPath) {
final int pos1 = classPath.indexOf('.');
final int pos2 = classPath.indexOf('.', pos1 + 1);
return classPath.substring(0, pos2);
}
protected List getFields(final Element element) {
return TypeUtils.getFields(element.asType()).stream().sorted((o1, o2) -> {
// sort id on top, keep the rest unchanged
if ("id".equals(o1.getSimpleName().toString())) {
return "id".equals(o2.getSimpleName().toString()) ? 0 : -1;
}
return 0;
}).collect(Collectors.toList());
}
protected boolean hasEnum(final Element element) {
return getFields(element).stream().map(Element::asType).anyMatch(this::isEnum);
}
protected boolean isEnum(final TypeMirror typeMirror) {
return StringUtils.isNoneEmpty(getEnumName(typeMirror));
}
protected String getEnumName(final TypeMirror typeMirror) {
if ("java.lang.Enum".equals(TypeUtils.getClassName(typeMirror))) {
return TypeUtils.getClassName(((DeclaredType) typeMirror).getTypeArguments().get(0));
}
if (typeMirror.getKind() == TypeKind.DECLARED) {
final TypeMirror superclass =
((TypeElement) ((DeclaredType) typeMirror).asElement()).getSuperclass();
if (superclass != null) {
return getEnumName(superclass);
}
}
return null;
}
/**
* write additional imports.
*
* @param element the element which represents the entity
*/
protected abstract void addAdditionalImports(final String serverPackage, final Element element,
final T annotationInterface);
/**
* write class or interface body.
*
* @param out print writer
* @param serverPackage package to generate stuff in
* @param element the element which represents the entity
* @param annotationInterface annotation interface
* @param processingEnv processing environment
*/
protected abstract void writeBody(final PrintWriter out, final String serverPackage,
final Element element, final T annotationInterface, ProcessingEnvironment processingEnv);
}