/* * Copyright 2010 Android ORM projects. * * 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. */ package cn.ieclipse.aorm.eclipse.jdt; import java.io.File; import java.io.FileReader; import java.util.Arrays; import java.util.List; import org.eclipse.jdt.core.IBuffer; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.dom.AST; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.ASTParser; import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; import org.eclipse.jdt.core.dom.AnonymousClassDeclaration; import org.eclipse.jdt.core.dom.Assignment; import org.eclipse.jdt.core.dom.Block; import org.eclipse.jdt.core.dom.ClassInstanceCreation; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.FieldDeclaration; import org.eclipse.jdt.core.dom.ImportDeclaration; import org.eclipse.jdt.core.dom.InfixExpression; import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.MethodInvocation; import org.eclipse.jdt.core.dom.Modifier; import org.eclipse.jdt.core.dom.PrimitiveType; import org.eclipse.jdt.core.dom.ReturnStatement; import org.eclipse.jdt.core.dom.SingleVariableDeclaration; import org.eclipse.jdt.core.dom.StringLiteral; import org.eclipse.jdt.core.dom.ThisExpression; import org.eclipse.jdt.core.dom.Type; import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.jdt.core.dom.VariableDeclarationFragment; import org.eclipse.jdt.core.dom.VariableDeclarationStatement; import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; import org.eclipse.jdt.core.dom.rewrite.ImportRewrite; import org.eclipse.jdt.core.dom.rewrite.ListRewrite; import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility; import org.eclipse.text.edits.MultiTextEdit; import org.eclipse.text.edits.TextEdit; /** * @author Jamling * */ public class SourceGenerator { public static void main(String[] args) throws Exception { // ICompilationUnit unit = JavaCore.createCompilationUnitFrom(); File f = new File("ExampleContentProvider.java"); FileReader fr = new FileReader(f); char[] b = new char[1024 * 1024]; int len = fr.read(b); char[] c = new char[len]; System.arraycopy(b, 0, c, 0, len); merge(c, "com.ex", "MyContentProvider", "abc", "person.db", Arrays.asList(new String[] { "create 1", "create 2" })); } public static void merge(char[] source, String pkgName, String typeName, String auth, String dbName, List<String> tableCreators) throws Exception { ASTParser parser = ASTParser.newParser(AST.JLS3); parser.setKind(ASTParser.K_COMPILATION_UNIT); parser.setSource(source); parser.setResolveBindings(true); CompilationUnit unit = (CompilationUnit) parser.createAST(null); // parse merge(unit, pkgName, typeName, auth, dbName, tableCreators); // System.out.println(unit); } private static void merge(CompilationUnit unit, String pkgName, String typeName, String auth, String dbName, List<String> tableCreators) { unit.recordModifications(); AST ast = unit.getAST(); TypeDeclaration type = (TypeDeclaration) unit.types().get(0); ImportDeclaration id = ast.newImportDeclaration(); id.setName(ast.newName("cn.ieclipse.aorm.Session")); unit.imports().add(id); id = ast.newImportDeclaration(); id.setName(ast.newName("android.content.UriMatcher")); unit.imports().add(id); id = ast.newImportDeclaration(); id.setName(ast.newName("android.database.sqlite.SQLiteDatabase")); unit.imports().add(id); id = ast.newImportDeclaration(); id.setName(ast.newName("android.database.sqlite.SQLiteOpenHelper")); unit.imports().add(id); id = ast.newImportDeclaration(); id.setName(ast.newName("java.net.Uri")); unit.imports().add(id); id = ast.newImportDeclaration(); id.setName(ast.newName("android.content.ContentValue")); unit.imports().add(id); VariableDeclarationFragment vdf = ast.newVariableDeclarationFragment(); vdf.setName(ast.newSimpleName("AUTH")); StringLiteral sl = ast.newStringLiteral(); sl.setLiteralValue(auth); vdf.setInitializer(sl); FieldDeclaration fd = ast.newFieldDeclaration(vdf); fd.modifiers() .addAll(ast .newModifiers((Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL))); fd.setType(ast.newSimpleType(ast.newSimpleName("String"))); int i = 0; type.bodyDeclarations().add(i++, fd); // URI = Uri.parse("content://" + AUTH); vdf = ast.newVariableDeclarationFragment(); vdf.setName(ast.newSimpleName("URI")); MethodInvocation mi = ast.newMethodInvocation(); mi.setExpression(ast.newSimpleName("Uri")); mi.setName(ast.newSimpleName("parse")); InfixExpression fix = ast.newInfixExpression(); fix.setOperator(InfixExpression.Operator.PLUS); sl = ast.newStringLiteral(); sl.setLiteralValue("content://"); fix.setLeftOperand(sl); fix.setRightOperand(ast.newSimpleName("AUTH")); mi.arguments().add(fix); vdf.setInitializer(mi); fd = ast.newFieldDeclaration(vdf); fd.modifiers() .addAll(ast .newModifiers((Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL))); fd.setType(ast.newSimpleType(ast.newSimpleName("Uri"))); type.bodyDeclarations().add(i++, fd); // private mOpenHelper; vdf = ast.newVariableDeclarationFragment(); vdf.setName(ast.newSimpleName("mOpenHelper")); fd = ast.newFieldDeclaration(vdf); fd.modifiers().add( ast.newModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD)); fd.setType(ast.newSimpleType(ast.newName("SQLiteOpenHelper"))); type.bodyDeclarations().add(i++, fd); // private static session; vdf = ast.newVariableDeclarationFragment(); vdf.setName(ast.newSimpleName("session")); fd = ast.newFieldDeclaration(vdf); fd.modifiers().addAll( ast.newModifiers((Modifier.PRIVATE | Modifier.STATIC))); fd.setType(ast.newSimpleType(ast.newName("Session"))); type.bodyDeclarations().add(i++, fd); // public static Session getSession(){ // return session; // } MethodDeclaration md = ast.newMethodDeclaration(); md.modifiers().addAll( ast.newModifiers((Modifier.PUBLIC | Modifier.STATIC))); md.setReturnType2(ast.newSimpleType(ast.newName("Session"))); md.setName(ast.newSimpleName("getSession")); Block methodBlock = ast.newBlock(); ReturnStatement returnStmt = ast.newReturnStatement(); returnStmt.setExpression(ast.newSimpleName("session")); methodBlock.statements().add(returnStmt); md.setBody(methodBlock); type.bodyDeclarations().add(i, md); // modify onCreate rewriteOnCreate(unit, dbName, tableCreators); } public static CompilationUnit merge(ICompilationUnit source, String pkgName, String typeName, String auth, String dbName, List<String> tableCreators) throws Exception { ASTParser parser = ASTParser.newParser(AST.JLS3); parser.setKind(ASTParser.K_COMPILATION_UNIT); parser.setSource(source); parser.setResolveBindings(true); CompilationUnit unit = (CompilationUnit) parser.createAST(null); // parse merge(unit, pkgName, typeName, auth, dbName, tableCreators); return unit; } private static void rewriteOnCreate(CompilationUnit unit, String dbName, List<String> tableCreators) { AST ast = unit.getAST(); TypeDeclaration type = (TypeDeclaration) unit.types().get(0); MethodDeclaration onCreate = getMethod(type, ("onCreate"), null); if (onCreate != null) { Block methodBlock = ast.newBlock(); // mOpenHelper = new // InlineOpenHelper(this.getContext(),"person.db",null,1); Assignment a = ast.newAssignment(); a.setOperator(Assignment.Operator.ASSIGN); a.setLeftHandSide(ast.newSimpleName("mOpenHelper")); ClassInstanceCreation cc = ast.newClassInstanceCreation(); cc.setType(ast.newSimpleType(ast.newSimpleName("SQLiteOpenHelper"))); ThisExpression thisExp = ast.newThisExpression(); MethodInvocation mi = ast.newMethodInvocation(); mi.setName(ast.newSimpleName("getContext")); mi.setExpression(thisExp); cc.arguments().add(mi); StringLiteral sl = ast.newStringLiteral(); sl.setLiteralValue(dbName); cc.arguments().add(sl); cc.arguments().add(ast.newNullLiteral()); cc.arguments().add(ast.newNumberLiteral("1")); a.setRightHandSide(cc); methodBlock.statements().add(ast.newExpressionStatement(a)); AnonymousClassDeclaration acd = ast.newAnonymousClassDeclaration(); cc.setAnonymousClassDeclaration(acd); genInnerSQLiteOpenHelper(acd, ast, tableCreators); a = ast.newAssignment(); a.setOperator(Assignment.Operator.ASSIGN); a.setLeftHandSide(ast.newSimpleName("session")); ClassInstanceCreation cic = ast.newClassInstanceCreation(); cic.setType(ast.newSimpleType(ast.newSimpleName("Session"))); // SingleVariableDeclaration svd = // ast.newSingleVariableDeclaration(); // svd.setName(ast.newSimpleName("mOpenHelper")); cic.arguments().add(ast.newSimpleName("mOpenHelper")); // vdf.setInitializer(cic); a.setRightHandSide(cic); // methodBlock.statements().add(vde); methodBlock.statements().add(ast.newExpressionStatement(a)); ReturnStatement returnStmt = ast.newReturnStatement(); returnStmt.setExpression(ast.newBooleanLiteral(true)); methodBlock.statements().add(returnStmt); onCreate.setBody(methodBlock); } } private static void genInnerSQLiteOpenHelper(AnonymousClassDeclaration acd, AST ast, List<String> tableCreators) { MethodDeclaration md = ast.newMethodDeclaration(); md.modifiers().addAll(ast.newModifiers((Modifier.PUBLIC))); md.setReturnType2(ast.newPrimitiveType(PrimitiveType.VOID)); md.setName(ast.newSimpleName("onCreate")); SingleVariableDeclaration svd = ast.newSingleVariableDeclaration(); svd.setName(ast.newSimpleName("db")); svd.setType(ast.newSimpleType(ast.newSimpleName("SQLiteDatabase"))); md.parameters().add(svd); Block innerBlock = ast.newBlock(); md.setBody(innerBlock); VariableDeclarationFragment vdf = ast.newVariableDeclarationFragment(); vdf.setName(ast.newSimpleName("sql")); StringLiteral sl = ast.newStringLiteral(); sl.setLiteralValue(""); vdf.setInitializer(sl); VariableDeclarationStatement vds = ast .newVariableDeclarationStatement(vdf); vds.setType(ast.newSimpleType(ast.newSimpleName("String"))); innerBlock.statements().add(vds); for (String creator : tableCreators) { String[] lines = creator.split(SourceAnalysis.LF); for (String line : lines) { Assignment a = ast.newAssignment(); a.setOperator(Assignment.Operator.PLUS_ASSIGN); a.setLeftHandSide(ast.newSimpleName("sql")); StringLiteral temp = ast.newStringLiteral(); temp.setLiteralValue(line); a.setRightHandSide(temp); innerBlock.statements().add(ast.newExpressionStatement(a)); } MethodInvocation mi = ast.newMethodInvocation(); mi.setName(ast.newSimpleName("execSQL")); mi.setExpression(ast.newSimpleName("db")); mi.arguments().add(ast.newSimpleName("sql")); innerBlock.statements().add(ast.newExpressionStatement(mi)); } acd.bodyDeclarations().add(md); // onUpgrade md = ast.newMethodDeclaration(); md.modifiers().addAll(ast.newModifiers((Modifier.PUBLIC))); md.setReturnType2(ast.newPrimitiveType(PrimitiveType.VOID)); md.setName(ast.newSimpleName("onUpgrade")); svd = ast.newSingleVariableDeclaration(); svd.setName(ast.newSimpleName("db")); svd.setType(ast.newSimpleType(ast.newSimpleName("SQLiteDatabase"))); md.parameters().add(svd); svd = ast.newSingleVariableDeclaration(); svd.setName(ast.newSimpleName("oldVersion")); svd.setType(ast.newPrimitiveType(PrimitiveType.INT)); md.parameters().add(svd); svd = ast.newSingleVariableDeclaration(); svd.setName(ast.newSimpleName("newVersion")); svd.setType(ast.newPrimitiveType(PrimitiveType.INT)); md.parameters().add(svd); innerBlock = ast.newBlock(); md.setBody(innerBlock); acd.bodyDeclarations().add(md); } private static MethodDeclaration getMethod(TypeDeclaration type, String name, Type... types) { MethodDeclaration result = null; MethodDeclaration[] methods = type.getMethods(); for (MethodDeclaration temp : methods) { if (temp.getName().getIdentifier().equals(name)) { List params = temp.typeParameters(); if (params.isEmpty() && types == null) { result = temp; break; } else if (params.size() == types.length) { boolean eq = true; for (int i = 0; i < types.length; i++) { if (!params.get(i).equals(types[i])) { eq = false; break; } } if (eq) { result = temp; break; } } } } return result; } public static void applyChange(ICompilationUnit cu, CompilationUnit unit) { try { ASTRewrite rewrite = ASTRewrite.create(unit.getAST()); ImportRewrite importRewrite = StubUtility.createImportRewrite(unit, false); ASTNode node = unit.findDeclaringNode(cu.getTypes()[0].getKey()); AbstractTypeDeclaration type = ((AbstractTypeDeclaration) node); ListRewrite listRewrite = rewrite.getListRewrite(node, type.getBodyDeclarationsProperty()); MultiTextEdit edit = new MultiTextEdit(); TextEdit sub = importRewrite.rewriteImports(null); edit.addChild(sub); // System.out.println(unit); org.eclipse.jface.text.Document doc = new org.eclipse.jface.text.Document( cu.getSource()); TextEdit te = rewrite.rewriteAST(doc, cu.getJavaProject() .getOptions(true)); te.apply(doc); IBuffer buffer = cu.getBuffer(); buffer.setContents(doc.get()); buffer.save(null, true); // System.out.println(buffer.getContents()); } catch (Exception e) { e.printStackTrace(); } } public static void merge(IType type, String authority, String dbName, List<String> tableCreators) throws Exception { type.createField("public static final String AUTH=\"" + authority + "\";", null, true, null); type.createField( "public static final Uri URI=Uri.parse(\"content://\" + AUTH);", null, true, null); type.createField("private SQLiteOpenHelper mOpenHelper;", null, true, null); type.createField("private static Session session;", null, true, null); type.createMethod("public static Session getSession(){" + "return session;" + "}", null, true, null); IMethod onCreate = type.getMethod("onCreate", null); // String doc = onCreate.getAttachedJavadoc(null); StringBuilder sb = new StringBuilder(onCreate.getSource()); int start = sb.indexOf("{") + 1; int end = sb.indexOf("}"); sb.delete(start, end); StringBuilder sb2 = new StringBuilder(); sb2.append("mOpenHelper=new SQLiteOpenHelper(this.getContext(),\""); sb2.append(dbName); sb2.append("\",null,1){"); sb2.append("public void onCreate(SQLiteDatabase db){"); sb2.append(" String sql=\"\";"); for (String creator : tableCreators) { String[] lines = creator.split(SourceAnalysis.LF); for (int i = 0; i < lines.length; i++) { if (i == 0) { sb2.append("sql=\""); } else { sb2.append("sql+=\""); } sb2.append(lines[i]); sb2.append("\";"); } sb2.append("db.execSQL(sql);"); } sb2.append("}"); sb2.append("public void onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion){"); sb2.append(""); sb2.append("}};"); sb2.append("session = new Session(mOpenHelper, getContext().getContentResolver());"); sb2.append("return true;"); sb.insert(start, sb2); onCreate.delete(true, null); type.createMethod(sb.toString(), null, true, null); } }