package com.lambdaworks.apigenerator; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; import com.github.javaparser.ASTHelper; import com.github.javaparser.JavaParser; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.ImportDeclaration; import com.github.javaparser.ast.PackageDeclaration; import com.github.javaparser.ast.TypeParameter; import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.ast.body.ModifierSet; import com.github.javaparser.ast.body.Parameter; import com.github.javaparser.ast.comments.Comment; import com.github.javaparser.ast.comments.JavadocComment; import com.github.javaparser.ast.expr.NameExpr; import com.github.javaparser.ast.type.Type; import com.github.javaparser.ast.visitor.VoidVisitorAdapter; /** * @author Mark Paluch */ public class CompilationUnitFactory { private File templateFile; private File sources; private File target; private String targetPackage; private String targetName; private Function<String, String> typeDocFunction; private Function<MethodDeclaration, Type> methodReturnTypeFunction; private Predicate<MethodDeclaration> methodFilter; private Supplier<List<String>> importSupplier; private Consumer<ClassOrInterfaceDeclaration> typeMutator; private Function<Comment, Comment> methodCommentMutator; CompilationUnit template; CompilationUnit result = new CompilationUnit(); ClassOrInterfaceDeclaration resultType; public CompilationUnitFactory(File templateFile, File sources, String targetPackage, String targetName, Function<String, String> typeDocFunction, Function<MethodDeclaration, Type> methodReturnTypeFunction, Predicate<MethodDeclaration> methodFilter, Supplier<List<String>> importSupplier, Consumer<ClassOrInterfaceDeclaration> typeMutator, Function<Comment, Comment> methodCommentMutator) { this.templateFile = templateFile; this.sources = sources; this.targetPackage = targetPackage; this.targetName = targetName; this.typeDocFunction = typeDocFunction; this.methodReturnTypeFunction = methodReturnTypeFunction; this.methodFilter = methodFilter; this.importSupplier = importSupplier; this.typeMutator = typeMutator; this.methodCommentMutator = methodCommentMutator; this.target = new File(sources, targetPackage.replace('.', '/') + "/" + targetName + ".java"); } public void createInterface() throws Exception { result.setPackage(new PackageDeclaration(ASTHelper.createNameExpr(targetPackage))); template = JavaParser.parse(templateFile); ClassOrInterfaceDeclaration templateTypeDeclaration = (ClassOrInterfaceDeclaration) template.getTypes().get(0); resultType = new ClassOrInterfaceDeclaration(ModifierSet.PUBLIC, true, targetName); if (templateTypeDeclaration.getExtends() != null) { resultType.setExtends(templateTypeDeclaration.getExtends()); } if (!templateTypeDeclaration.getTypeParameters().isEmpty()) { resultType.setTypeParameters(new ArrayList<>()); for (TypeParameter typeParameter : templateTypeDeclaration.getTypeParameters()) { resultType.getTypeParameters().add(new TypeParameter(typeParameter.getName(), typeParameter.getTypeBound())); } } resultType.setComment(new JavadocComment(typeDocFunction.apply(templateTypeDeclaration.getComment().getContent()))); result.setImports(new ArrayList<>()); ASTHelper.addTypeDeclaration(result, resultType); resultType.setParentNode(result); if (template.getImports() != null) { result.getImports().addAll(template.getImports()); } List<String> importLines = importSupplier.get(); for (String importLine : importLines) { result.getImports().add(new ImportDeclaration(new NameExpr(importLine), false, false)); } new MethodVisitor().visit(template, null); if (typeMutator != null) { typeMutator.accept(resultType); } writeResult(); } protected void writeResult() throws IOException { FileOutputStream fos = new FileOutputStream(target); fos.write(result.toString().getBytes()); fos.close(); } /** * Simple visitor implementation for visiting MethodDeclaration nodes. */ private class MethodVisitor extends VoidVisitorAdapter<Object> { @Override public void visit(MethodDeclaration n, Object arg) { if (!methodFilter.test(n)) { return; } MethodDeclaration method = new MethodDeclaration(n.getModifiers(), methodReturnTypeFunction.apply(n), n.getName()); if (methodCommentMutator != null) { method.setComment(methodCommentMutator.apply(n.getComment())); } else { method.setComment(n.getComment()); } for (Parameter parameter : n.getParameters()) { Parameter param = ASTHelper.createParameter(parameter.getType(), parameter.getId().getName()); param.setVarArgs(parameter.isVarArgs()); ASTHelper.addParameter(method, param); } if (n.getTypeParameters() != null) { method.setTypeParameters(new ArrayList<>()); method.getTypeParameters().addAll(n.getTypeParameters()); } if (n.getAnnotations() != null) { method.setAnnotations(n.getAnnotations()); } ASTHelper.addMember(resultType, method); } } }