package com.github.kklisura.cdt.definition.builder.support.java.builder.impl; /*- * #%L * cdt-java-protocol-builder * %% * Copyright (C) 2018 Kenan Klisura * %% * Licensed 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. * #L% */ import static com.github.kklisura.cdt.definition.builder.support.java.builder.utils.JavadocUtils.INDENTATION_NO_INDENTATION; import static com.github.kklisura.cdt.definition.builder.support.java.builder.utils.JavadocUtils.INDENTATION_TAB; import com.github.javaparser.ast.ImportDeclaration; import com.github.javaparser.ast.Modifier; import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; import com.github.javaparser.ast.body.FieldDeclaration; import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.ast.expr.MarkerAnnotationExpr; import com.github.javaparser.ast.expr.Name; import com.github.kklisura.cdt.definition.builder.support.java.builder.JavaClassBuilder; import com.github.kklisura.cdt.definition.builder.support.java.builder.impl.utils.CompilationUnitUtils; import com.github.kklisura.cdt.definition.builder.support.java.builder.utils.JavadocUtils; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Java class generator. * * @author Kenan Klisura */ public class JavaClassBuilderImpl extends BaseBuilder implements JavaClassBuilder { public static final Logger LOGGER = LoggerFactory.getLogger(JavaClassBuilderImpl.class); private static final String DEPRECATED_ANNOTATION = "Deprecated"; private static final Map<String, String> KEYWORD_TO_FIELD_MAPPING = new HashMap<>(); // Registers a keyword mapping. static { registerKeyword("this", "that"); } private String name; private ClassOrInterfaceDeclaration declaration; private String annotationsPackage; private Map<String, String> fieldDescriptions = new HashMap<>(); /** * Instantiates a new class builder implementation. * * @param packageName Package name. * @param name Class name. * @param annotationsPackage Package where support annotations are located (Optional, * Experimental...) */ public JavaClassBuilderImpl(String packageName, String name, String annotationsPackage) { super(packageName); this.name = name; this.declaration = getCompilationUnit().addClass(name); this.annotationsPackage = annotationsPackage; } /** * Returns a class name. * * @return Class name. */ @Override public String getName() { return name; } /** * Sets the java doc for this class. * * @param comment Comment. */ @Override public void setJavaDoc(String comment) { if (StringUtils.isNotEmpty(comment)) { declaration.setJavadocComment( JavadocUtils.createJavadocComment(comment, INDENTATION_NO_INDENTATION)); } } /** * Adds the private field of a given type to this class. * * @param name Field name. * @param type Field type. */ @Override public void addPrivateField(String name, String type, String description) { String fieldName = getFieldName(name); declaration.addField(type, fieldName, Modifier.PRIVATE); fieldDescriptions.put(fieldName, description); } /** * Adds annotation to field. * * @param name Field name. Could not be in correct format. * @param annotationName Annotation name. */ @Override public void addFieldAnnotation(String name, String annotationName) { Optional<FieldDeclaration> fieldDeclaration = declaration.getFieldByName(getFieldName(name)); if (fieldDeclaration.isPresent()) { MarkerAnnotationExpr annotationExpr = new MarkerAnnotationExpr(); annotationExpr.setName(annotationName); fieldDeclaration.get().addAnnotation(annotationExpr); importAnnotation(annotationName); } else { throw new RuntimeException("Field " + name + " is not present in current class."); } } @Override public void addAnnotation(String annotationName) { MarkerAnnotationExpr annotationExpr = new MarkerAnnotationExpr(); annotationExpr.setName(annotationName); declaration.addAnnotation(annotationExpr); importAnnotation(annotationName); } @Override public void generateGettersAndSetters() { List<FieldDeclaration> fields = declaration.getFields(); for (FieldDeclaration fieldDeclaration : fields) { String fieldName = fieldDeclaration.getVariables().get(0).getNameAsString(); setMethodJavadoc(fieldName, fieldDeclaration.createGetter()); setMethodJavadoc(fieldName, fieldDeclaration.createSetter()); } } @Override public void addImport(String packageName, String object) { Name name = new Name(); name.setQualifier(new Name(packageName)); name.setIdentifier(object); if (!getPackageName().equalsIgnoreCase(packageName) && !CompilationUnitUtils.isImported(getCompilationUnit(), name)) { getCompilationUnit().addImport(new ImportDeclaration(name, false, false)); } } private void setMethodJavadoc(String fieldName, MethodDeclaration methodDeclaration) { String description = fieldDescriptions.get(fieldName); if (StringUtils.isNotEmpty(description)) { methodDeclaration.setJavadocComment( JavadocUtils.createJavadocComment(description, INDENTATION_TAB)); } } private void importAnnotation(String annotationName) { if (!DEPRECATED_ANNOTATION.equals(annotationName)) { addImport(annotationsPackage, annotationName); } } /** * Returns a field name given an input. This is used to rename field names that are keyword names. * * @param input Input field name. * @return Field name. */ private static String getFieldName(String input) { return KEYWORD_TO_FIELD_MAPPING.getOrDefault(input, input); } /** * Registers keyword mapping. This is used to rename a field that belongs to a keyword to some * other name (mapping). * * @param keyword Keyword to be renamed. * @param mapping Mapping to be renamed into. */ private static void registerKeyword(String keyword, String mapping) { KEYWORD_TO_FIELD_MAPPING.put(keyword, mapping); } }