package org.vaadin.mideaas.frontend; import japa.parser.ASTHelper; import japa.parser.JavaParser; import japa.parser.ParseException; import japa.parser.ast.CompilationUnit; import japa.parser.ast.ImportDeclaration; import japa.parser.ast.body.BodyDeclaration; import japa.parser.ast.body.FieldDeclaration; import japa.parser.ast.body.MethodDeclaration; import japa.parser.ast.body.ModifierSet; import japa.parser.ast.body.Parameter; import japa.parser.ast.body.TypeDeclaration; import japa.parser.ast.expr.AnnotationExpr; import japa.parser.ast.expr.AssignExpr; import japa.parser.ast.expr.AssignExpr.Operator; import japa.parser.ast.expr.CastExpr; import japa.parser.ast.expr.FieldAccessExpr; import japa.parser.ast.expr.NameExpr; import japa.parser.ast.expr.ThisExpr; import japa.parser.ast.stmt.BlockStmt; import japa.parser.ast.stmt.ExpressionStmt; import japa.parser.ast.stmt.Statement; import japa.parser.ast.type.ClassOrInterfaceType; import japa.parser.ast.type.ReferenceType; import japa.parser.ast.type.Type; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; import com.vaadin.annotations.AutoGenerated; public class JavaUtil { public static String javaCodeWithRootClass(String java, String rootClass) { try { CompilationUnit cu = getCu(java); changeMethods(cu, rootClass); return cu.toString(); } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } private static CompilationUnit getCu(String java) throws ParseException { InputStream is = new ByteArrayInputStream(java.getBytes()); try { return JavaParser.parse(is); } finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } private static void changeMethods(CompilationUnit cu, String rootClass) { addImport(cu, rootClass); String rootClassShort = rootClass .substring(rootClass.lastIndexOf(".") + 1); List<TypeDeclaration> types = cu.getTypes(); for (TypeDeclaration type : types) { List<BodyDeclaration> members = type.getMembers(); for (BodyDeclaration member : members) { if (member instanceof MethodDeclaration) { MethodDeclaration method = (MethodDeclaration) member; if (isSetRootComponentMethod(method)) { changeSetRootMethod(method, rootClassShort); } } else if (member instanceof FieldDeclaration) { FieldDeclaration field = (FieldDeclaration) member; if (isRootField(field)) { changeRootField(field, rootClassShort); } } } } } private static void changeRootField(FieldDeclaration field, String rootClass) { Type type = new ClassOrInterfaceType(rootClass); field.setType(type); } private static boolean isRootField(FieldDeclaration field) { if (field.getVariables().size() != 1 || !"root" .equals(field.getVariables().get(0).getId().getName())) { return false; } field.getModifiers(); return ModifierSet.hasModifier(field.getModifiers(), ModifierSet.PRIVATE) && hasAnnotation(field, "AutoGenerated"); } @AutoGenerated private static void changeSetRootMethod(MethodDeclaration method, String rootClass) { Type type = new ClassOrInterfaceType(rootClass); // Parameter newArg = ASTHelper.createParameter(type, "root"); // method.setParameters(Collections.singletonList(newArg)); BlockStmt body = method.getBody(); AssignExpr rootAssign = findRootAssignExpr(body); CastExpr ce = new CastExpr(type, new NameExpr("root")); FieldAccessExpr field = new FieldAccessExpr(new ThisExpr(), "root"); if (rootAssign==null) { rootAssign = new AssignExpr(field, ce, Operator.assign); ASTHelper.addStmt(body, rootAssign); } else { rootAssign.setValue(ce); } } private static AssignExpr findRootAssignExpr(BlockStmt body) { if (body.getStmts() != null) { for (Statement s : body.getStmts()) { if (s instanceof ExpressionStmt) { ExpressionStmt est = (ExpressionStmt) s; if (est.getExpression() instanceof AssignExpr) { AssignExpr ass = (AssignExpr) est.getExpression(); if (ass.getTarget() instanceof FieldAccessExpr) { FieldAccessExpr fae = (FieldAccessExpr) ass.getTarget(); if ("root".equals(fae.getField())) { return ass; } } } } } } return null; } private static boolean isSetRootComponentMethod(MethodDeclaration method) { return "setRootComponent".equals(method.getName()) && method.getParameters()!=null && method.getParameters().size() == 1 && isSetRootComponentMethodParameter(method.getParameters().get(0)) && hasAnnotation(method, "AutoGenerated"); } private static boolean isSetRootComponentMethodParameter(Parameter p) { return p.getType() instanceof ReferenceType; // TODO } private static boolean hasAnnotation(BodyDeclaration decl, String anno) { if (decl.getAnnotations() == null) { return false; } for (AnnotationExpr ae : decl.getAnnotations()) { if (anno.equals(ae.getName().toString())) { return true; } } return false; } private static void addImport(CompilationUnit cu, String imp) { for (ImportDeclaration id : cu.getImports()) { if (imp.equals(id.getName().toString())) { return; } } cu.getImports().add( new ImportDeclaration(new NameExpr(imp), false, false)); } public static final Set<String> JAVA_RESERVED_WORDS = new HashSet<String>( Arrays.asList(new String[] { "abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "default", "do", "double", "else", "enum", "extends", "false", "final", "finally", "float", "for", "goto", "if", "implements", "import", "instanceof", "int", "interface", "long", "native", "new", "null", "package", "private", "protected", "public", "return", "short", "static", "strictfp", "super", "switch", "synchronized", "this", "throw", "throws", "transient", "true", "try", "void", "volatile", "while", })); public static boolean isJavaReservedWord(String s) { return JAVA_RESERVED_WORDS.contains(s); } public static List<String> classPathItems(String classPath) { return Arrays.asList(classPath.split(File.pathSeparator)); } public static String generateClass(String fullClass, String baseCls) { String[] cls = splitFullJavaClassName(fullClass); String[] base = baseCls==null ? null : splitFullJavaClassName(baseCls); StringBuilder sb = new StringBuilder("package "+cls[0]+";\n\n"); if (base!=null) { sb.append("import "+baseCls+";\n\n"); } sb.append("public class "+cls[1]+" "); if (base!=null) { sb.append("extends " + base[1]+ " "); } sb.append("{\n\n\n\n}\n"); return sb.toString(); } public static String[] splitFullJavaClassName(String cls) { int i = cls.lastIndexOf('.'); return new String[] { cls.substring(0, i), cls.substring(i+1)}; } }