cn.ieclipse.adt.ext.jdt.SourceGenerator.java Source code

Java tutorial

Introduction

Here is the source code for cn.ieclipse.adt.ext.jdt.SourceGenerator.java

Source

/*
 * 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.adt.ext.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,
            List<String> tables) 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);");
        //        }
        for (String table : tables) {
            sb2.append(table);
        }
        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);

    }
}