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

de.knightsoftnet.gwtp.spring.annotation.processor.AbstractBackofficeCreator Maven / Gradle / Ivy

There is a newer version: 2.2.2
Show newest version
/*
 * 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);
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy