diff options
Diffstat (limited to 'graph-inventory/fluent-builder-maven-plugin/src/main/java/org/onap/graphinventory/generate/FluentGenerator.java')
-rw-r--r-- | graph-inventory/fluent-builder-maven-plugin/src/main/java/org/onap/graphinventory/generate/FluentGenerator.java | 324 |
1 files changed, 324 insertions, 0 deletions
diff --git a/graph-inventory/fluent-builder-maven-plugin/src/main/java/org/onap/graphinventory/generate/FluentGenerator.java b/graph-inventory/fluent-builder-maven-plugin/src/main/java/org/onap/graphinventory/generate/FluentGenerator.java new file mode 100644 index 0000000000..f9c664389b --- /dev/null +++ b/graph-inventory/fluent-builder-maven-plugin/src/main/java/org/onap/graphinventory/generate/FluentGenerator.java @@ -0,0 +1,324 @@ +package org.onap.graphinventory.generate; + +import java.io.IOException; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.stream.Collectors; +import javax.lang.model.element.Modifier; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.tuple.Pair; +import org.apache.maven.plugin.logging.Log; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.google.common.base.CaseFormat; +import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.CodeBlock; +import com.squareup.javapoet.FieldSpec; +import com.squareup.javapoet.JavaFile; +import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.ParameterSpec; +import com.squareup.javapoet.ParameterizedTypeName; +import com.squareup.javapoet.TypeSpec; + +public class FluentGenerator { + + private final Map<String, ObjectType> doc; + private final String location; + private final String CLASSPATH; + + private final String singularBuilderClass; + private final String pluralBuilderClass; + private final String topLevelBuilderClass; + private final String baseBuilderClass; + private final String singularClass; + private final String pluralClass; + private final String builderName; + private final String nameClass; + + public FluentGenerator(Log log, String location, String destinationClasspath, String swaggerLocation, + String builderName, String singularBuilderClass, String pluralBuilderClass, String topLevelBuilderClass, + String baseBuilderClass, String singularClass, String pluralClass, String nameClass) + throws JsonProcessingException { + + this.location = location; + this.CLASSPATH = destinationClasspath; + this.builderName = builderName; + this.singularBuilderClass = singularBuilderClass; + this.pluralBuilderClass = pluralBuilderClass; + this.topLevelBuilderClass = topLevelBuilderClass; + this.baseBuilderClass = baseBuilderClass; + this.singularClass = singularClass; + this.pluralClass = pluralClass; + this.nameClass = nameClass; + doc = new SwaggerConverter(log).getDoc(swaggerLocation); + } + + public void run() throws IOException { + List<JavaFile> files = new ArrayList<>(); + for (Entry<String, ObjectType> entry : doc.entrySet()) { + // String key = "routing-instance"; + // ObjectType oType = test; + String key = entry.getKey(); + ObjectType oType = entry.getValue(); + MethodSpec.Builder constructor = MethodSpec.constructorBuilder().addModifiers(Modifier.PROTECTED); + List<ParameterSpec> constructorParams = new ArrayList<>(); + List<FieldSpec> classFields = new ArrayList<>(); + + if (!oType.getType().equals("top level")) { + Pair<String, String> path = splitClasspath(this.baseBuilderClass); + ClassName parameterizedTypeName = ClassName.get(path.getLeft(), path.getRight()); + constructorParams.add(ParameterSpec.builder(parameterizedTypeName, "parentObj").build()); + classFields.add(FieldSpec.builder(parameterizedTypeName, "parentObj") + .addModifiers(Modifier.PRIVATE, Modifier.FINAL).build()); + } + List<ParameterSpec> typeParams = new ArrayList<>(); + + for (ObjectField oF : oType.getFields()) { + if (oF.getType().equals("string")) { + typeParams.add(ParameterSpec.builder(String.class, lowerCamel(makeValidJavaVariable(oF.getName()))) + .build()); + classFields.add(FieldSpec.builder(String.class, lowerCamel(makeValidJavaVariable(oF.getName()))) + .addModifiers(Modifier.PRIVATE, Modifier.FINAL).build()); + } else if (oF.getType().equals("integer")) { + typeParams.add( + ParameterSpec.builder(int.class, lowerCamel(makeValidJavaVariable(oF.getName()))).build()); + classFields.add(FieldSpec.builder(int.class, lowerCamel(makeValidJavaVariable(oF.getName()))) + .addModifiers(Modifier.PRIVATE, Modifier.FINAL).build()); + } + } + constructorParams.addAll(typeParams); + constructor.addParameters(constructorParams); + for (ParameterSpec p : constructorParams) { + constructor.addStatement("this.$L = $L", p.name, p.name); + + } + List<MethodSpec> methods = new ArrayList<>(); + methods.add(constructor.build()); + + methods.addAll(createChildMethods(oType)); + + methods.addAll(createInterfaceMethods(oType, typeParams)); + + ClassName superType = null; + if (oType.getType().equals("top level")) { + Pair<String, String> path = splitClasspath(this.topLevelBuilderClass); + superType = ClassName.get(path.getLeft(), path.getRight()); + } else { + if (oType.getType().equals("singular")) { + Pair<String, String> path = splitClasspath(this.singularBuilderClass); + superType = ClassName.get(path.getLeft(), path.getRight()); + + } else if (oType.getType().equals("plural")) { + Pair<String, String> path = splitClasspath(this.pluralBuilderClass); + superType = ClassName.get(path.getLeft(), path.getRight()); + } + } + + TypeSpec type = TypeSpec.classBuilder(upperCamel(key)).addModifiers(Modifier.PUBLIC, Modifier.FINAL) + .addType(createInnerInfoClass(oType)).addSuperinterface(superType).addFields(classFields) + .addMethods(methods).build(); + + files.add(JavaFile.builder(CLASSPATH, type).build()); + + } + + files.add(createBuilderClass()); + + files.stream().forEach(javaFile -> { + try { + javaFile.writeTo(Paths.get(location, "fluent")); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + + } + + protected List<MethodSpec> createInterfaceMethods(ObjectType oType, List<ParameterSpec> typeParams) { + + List<MethodSpec> methods = new ArrayList<>(); + + CodeBlock.Builder uriTemplateCodeBlock = CodeBlock.builder(); + if (!oType.getType().equals("top level")) { + uriTemplateCodeBlock.add("return this.parentObj.uriTemplate() + Info.partialUri"); + } else { + uriTemplateCodeBlock.add("return Info.partialUri"); + + } + methods.add(MethodSpec.methodBuilder("uriTemplate").returns(String.class).addModifiers(Modifier.PUBLIC) + .addStatement(uriTemplateCodeBlock.build()).addAnnotation(Override.class).build()); + + ClassName arrayUtils = ClassName.get(ArrayUtils.class); + + CodeBlock.Builder valuesReturn = CodeBlock.builder(); + + if (oType.getType().equals("top level")) { + valuesReturn.add("return new Object[0]"); + } else { + if (!typeParams.isEmpty()) { + valuesReturn.add("return $T.addAll(this.parentObj.values(), $L)", arrayUtils, String.join(", ", + typeParams.stream().map(item -> "this." + item.name).collect(Collectors.toList()))); + } else { + valuesReturn.add("return this.parentObj.values()"); + } + } + methods.add(MethodSpec.methodBuilder("values").returns(Object[].class).addModifiers(Modifier.PUBLIC) + .addAnnotation(Override.class).addStatement(valuesReturn.build()).build()); + + if (!oType.getType().equals("top level")) { + ClassName returnType = null; + CodeBlock.Builder block = CodeBlock.builder(); + if (oType.getType().equals("singular")) { + Pair<String, String> path = splitClasspath(this.singularClass); + returnType = ClassName.get(path.getLeft(), path.getRight()); + block.add("return new $T(this.parentObj.uriTemplate(), Info.partialUri, Info.name, false)", returnType); + } else if (oType.getType().equals("plural")) { + Pair<String, String> path = splitClasspath(this.pluralClass); + returnType = ClassName.get(path.getLeft(), path.getRight()); + block.add("return new $T(Info.name, this.parentObj.uriTemplate(), Info.partialUri)", returnType); + } + + methods.add(MethodSpec.methodBuilder("build").returns(returnType).addModifiers(Modifier.PUBLIC) + .addAnnotation(Override.class).addStatement(block.build()).build()); + + } + + return methods; + } + + protected List<MethodSpec> createChildMethods(ObjectType oType) { + List<MethodSpec> methods = new ArrayList<>(); + for (String child : oType.getChildren()) { + methods.add(createAccessMethod(doc.get(child), true, false)); + } + + return methods; + } + + protected MethodSpec createAccessMethod(ObjectType oType, boolean isChild, boolean isStatic) { + + ClassName childClass = ClassName.get(CLASSPATH, upperCamel(oType.getName())); + MethodSpec.Builder b = MethodSpec.methodBuilder(lowerCamel(oType.getName())).returns(childClass); + List<Modifier> modifiers = new ArrayList<>(); + if (isStatic) { + modifiers.add(Modifier.STATIC); + } + modifiers.add(Modifier.PUBLIC); + b.addModifiers(modifiers); + List<ParameterSpec> params = new ArrayList<>(); + for (ObjectField oF : doc.get(oType.getName()).getFields()) { + if (oF.getType().equals("string")) { + params.add( + ParameterSpec.builder(String.class, lowerCamel(makeValidJavaVariable(oF.getName()))).build()); + } else if (oF.getType().equals("integer")) { + params.add(ParameterSpec.builder(int.class, lowerCamel(makeValidJavaVariable(oF.getName()))).build()); + } + } + List<String> paramNames = params.stream().map(item -> item.name).collect(Collectors.toList()); + if (isChild) { + paramNames.add(0, "this"); + } + b.addParameters(params).addStatement("return new $T($L)", childClass, String.join(", ", paramNames)); + + return b.build(); + } + + protected JavaFile createBuilderClass() { + + List<MethodSpec> methods = doc.values().stream().filter(item -> item.getType().equals("top level")) + .map(item -> createAccessMethod(item, false, true)).collect(Collectors.toList()); + + TypeSpec type = TypeSpec.classBuilder(this.builderName).addModifiers(Modifier.PUBLIC, Modifier.FINAL) + .addMethods(methods).addType(createTypes()).build(); + + return JavaFile.builder(CLASSPATH, type).build(); + + } + + protected TypeSpec createTypes() { + Pair<String, String> path = splitClasspath(this.nameClass); + ClassName nameType = ClassName.get(path.getLeft(), path.getRight()); + + List<FieldSpec> params = + doc.values().stream().filter(item -> item.getType().equals("singular")) + .sorted(Comparator + .comparing(item -> item.getName())) + .map(item -> FieldSpec + .builder(nameType, + CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE, item.getName()), + Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) + .initializer("new $T($S)", nameType, item.getName()).build()) + .collect(Collectors.toList()); + + TypeSpec type = TypeSpec.classBuilder("Types").addModifiers(Modifier.PUBLIC, Modifier.FINAL, Modifier.STATIC) + .addFields(params).build(); + + return type; + + } + + protected TypeSpec createInnerInfoClass(ObjectType oType) { + List<FieldSpec> classFields = new ArrayList<>(); + List<MethodSpec> methods = new ArrayList<>(); + + classFields.add(FieldSpec.builder(String.class, "partialUri") + .addModifiers(Modifier.PRIVATE, Modifier.FINAL, Modifier.STATIC) + .initializer("$S", oType.getPartialUri()).build()); + + classFields.add(FieldSpec.builder(ParameterizedTypeName.get(List.class, String.class), "paths") + .addModifiers(Modifier.PRIVATE, Modifier.FINAL, Modifier.STATIC) + .initializer("$T.asList($L)", ClassName.get(Arrays.class), + "\"" + oType.getPaths().stream().collect(Collectors.joining("\", \"")) + "\"") + .build()); + + ClassName superInterface; + if (oType.getType().equals("plural")) { + classFields.add(FieldSpec.builder(String.class, "name") + .addModifiers(Modifier.PRIVATE, Modifier.FINAL, Modifier.STATIC) + .initializer("$S", oType.getAdditionalName()).build()); + superInterface = ClassName.get(this.pluralBuilderClass, "Info"); + } else if (oType.getType().equals("singular")) { + classFields.add(FieldSpec.builder(String.class, "name") + .addModifiers(Modifier.PRIVATE, Modifier.FINAL, Modifier.STATIC).initializer("$S", oType.getName()) + .build()); + superInterface = ClassName.get(this.singularBuilderClass, "Info"); + } else { + superInterface = ClassName.get(this.topLevelBuilderClass, "Info"); + } + methods.add(MethodSpec.methodBuilder("getPaths").returns(ParameterizedTypeName.get(List.class, String.class)) + .addModifiers(Modifier.PUBLIC).addAnnotation(Override.class).addStatement("return Info.paths").build()); + methods.add(MethodSpec.methodBuilder("getPartialUri").returns(String.class).addModifiers(Modifier.PUBLIC) + .addAnnotation(Override.class).addStatement("return Info.partialUri").build()); + if (!oType.getType().equals("top level")) { + methods.add(MethodSpec.methodBuilder("getName").returns(String.class).addModifiers(Modifier.PUBLIC) + .addAnnotation(Override.class).addStatement("return Info.name").build()); + } + return TypeSpec.classBuilder("Info").addModifiers(Modifier.PUBLIC, Modifier.STATIC) + .addSuperinterface(superInterface).addFields(classFields).addMethods(methods).build(); + + } + + protected String makeValidJavaVariable(String name) { + + return name.replace(".", "_"); + } + + protected Pair<String, String> splitClasspath(String path) { + + return Pair.of(path.substring(0, path.lastIndexOf(".")), + path.substring(path.lastIndexOf(".") + 1, path.length())); + } + + protected String lowerCamel(String s) { + return CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL, s); + } + + protected String upperCamel(String s) { + return CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, s); + } + +} |