Example usage for org.eclipse.jdt.core.dom.rewrite ASTRewrite create

List of usage examples for org.eclipse.jdt.core.dom.rewrite ASTRewrite create

Introduction

In this page you can find the example usage for org.eclipse.jdt.core.dom.rewrite ASTRewrite create.

Prototype

public static ASTRewrite create(AST ast) 

Source Link

Document

Creates a new instance for describing manipulations of the given AST.

Usage

From source file:ac.at.tuwien.dsg.uml.statemachine.export.transformation.engines.impl.PathWithUncertaintyTestStrategy.java

License:Open Source License

/**
 * Generates a class to be used in executing the test plan.
 * The class is abstract because at this point it is unclear how to assert that a certain state has been reached.
 * Thus, the assertStateReached will be abstract methods.
 * @param stateGraph// w  ww.ja  v a 2 s.  c  o m
 */
public Document generateTestPlan(StateMachineStateGraph stateGraph) {
    Document doc = new Document(
            "public abstract class TestPlanForStateMachine" + stateGraph.getStateMachineName() + " { \n");

    //from here we use the cumbersome and extremely detailed Eclipse recommended DOM/AST library
    ASTParser parser = ASTParser.newParser(AST.JLS8);
    parser.setSource(doc.get().toCharArray());
    CompilationUnit cu = (CompilationUnit) parser.createAST(null);
    cu.recordModifications();
    AST ast = cu.getAST();
    ASTRewrite rewriter = ASTRewrite.create(ast);

    //create method which will contain one test plan (might be cloned and branched for each if-else in the state machine diagram)    
    MethodDeclaration testPlanMethodDeclaration = ast.newMethodDeclaration();
    testPlanMethodDeclaration.modifiers().add(ast.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD));
    testPlanMethodDeclaration.setName(ast.newSimpleName("testPlan"));
    testPlanMethodDeclaration.setReturnType2(ast.newPrimitiveType(PrimitiveType.VOID)); //return true if successful or false otherwise

    //create method body
    Block testPlanMethodBody = ast.newBlock();
    testPlanMethodDeclaration.setBody(testPlanMethodBody);

    //create recursively the test plan by parsing the state graph starting with initial state
    try {
        generatePlanForState(stateGraph.getInitialState(), rewriter, testPlanMethodDeclaration,
                new HashSet<StateMachineStateTransition>());
    } catch (NoSuchStateException e) {
        e.printStackTrace();
    }

    ListRewrite listRewrite = rewriter.getListRewrite(cu, CompilationUnit.TYPES_PROPERTY);

    //add all generated abstract methods
    for (Map.Entry<String, MethodDeclaration> entry : generatedAbstractMethods.entrySet()) {
        listRewrite.insertLast(entry.getValue(), null);
    }

    if (generatedPlans.isEmpty()) {
        notifyUser("No test plans containing uncertainty states could have been generated. "
                + "\n Please ensure selected state machine has at least one state with at least one uncertainty"
                + "\n Please ensure there is at least one InitialState, one FinalState, and one path between Initial and Final states which passes through"
                + "at least one state with at least one uncertainty");
    }

    int index = 1;
    //add generated plan methods
    for (Map.Entry<String, MethodDeclaration> entry : generatedPlans.entrySet()) {
        //rename to PLAN_METHOD_LEADING + plan index from PLAN_METHOD_LEADING + UUID
        MethodDeclaration method = entry.getValue();
        method.setName(ast.newSimpleName(PLAN_METHOD_LEADING + index++));

        listRewrite.insertLast(method, null);
    }

    //add final }
    listRewrite.insertLast(rewriter.createStringPlaceholder("}\n", ASTNode.EMPTY_STATEMENT), null);

    TextEdit edits = rewriter.rewriteAST(doc, null);
    try {
        UndoEdit undo = edits.apply(doc);
    } catch (MalformedTreeException | BadLocationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    System.out.println(doc.get());

    return doc;
}

From source file:ac.at.tuwien.dsg.uml.statemachine.export.transformation.engines.impl.TransitionCorrectnessTestStrategy.java

License:Open Source License

/**
 * Generates a class to be used in executing the test plan.
 * The class is abstract because at this point it is unclear how to assert that a certain state has been reached.
 * Thus, the assertStateReached will be abstract methods.
 * @param stateGraph//from   w ww. j  av  a2 s  .  com
 */
public Document generateTestPlan(StateMachineStateGraph stateGraph) {
    Document doc = new Document(
            "public abstract class TestPlanForStateMachine" + stateGraph.getStateMachineName() + " { \n");

    //from here we use the cumbersome and extremely detailed Eclipse recommended DOM/AST library
    ASTParser parser = ASTParser.newParser(AST.JLS8);
    parser.setSource(doc.get().toCharArray());
    CompilationUnit cu = (CompilationUnit) parser.createAST(null);
    cu.recordModifications();
    AST ast = cu.getAST();
    ASTRewrite rewriter = ASTRewrite.create(ast);

    //create method which will contain one test plan (might be cloned and branched for each if-else in the state machine diagram)    
    MethodDeclaration testPlanMethodDeclaration = ast.newMethodDeclaration();
    testPlanMethodDeclaration.modifiers().add(ast.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD));
    testPlanMethodDeclaration.setName(ast.newSimpleName("testPlan"));
    testPlanMethodDeclaration.setReturnType2(ast.newPrimitiveType(PrimitiveType.VOID)); //return true if successful or false otherwise

    //create method body
    Block testPlanMethodBody = ast.newBlock();
    testPlanMethodDeclaration.setBody(testPlanMethodBody);

    //create recursively the test plan by parsing the state graph starting with initial state
    try {
        generatePlanForState(stateGraph.getInitialState(), rewriter, testPlanMethodDeclaration,
                new HashSet<StateMachineStateTransition>());
    } catch (NoSuchStateException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }

    ListRewrite listRewrite = rewriter.getListRewrite(cu, CompilationUnit.TYPES_PROPERTY);

    //add all generated abstract methods
    for (Map.Entry<String, MethodDeclaration> entry : generatedAbstractMethods.entrySet()) {
        listRewrite.insertLast(entry.getValue(), null);
    }

    int index = 1;
    //add generated plan methods

    if (generatedPlans.isEmpty()) {
        notifyUser("No test plans could have been generated. "
                + "\n Please ensure selected state machine has at least one complete path from  initial to final state."
                + "\n Please ensure there is at least one InitialState, one FinalState, and one path between Initial and Final states");
    }

    for (Map.Entry<String, MethodDeclaration> entry : generatedPlans.entrySet()) {
        //rename to PLAN_METHOD_LEADING + plan index from PLAN_METHOD_LEADING + UUID
        MethodDeclaration method = entry.getValue();
        method.setName(ast.newSimpleName(PLAN_METHOD_LEADING + index++));

        listRewrite.insertLast(method, null);
    }

    //add final }
    listRewrite.insertLast(rewriter.createStringPlaceholder("}\n", ASTNode.EMPTY_STATEMENT), null);

    TextEdit edits = rewriter.rewriteAST(doc, null);
    try {
        UndoEdit undo = edits.apply(doc);
    } catch (MalformedTreeException | BadLocationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    System.out.println(doc.get());

    return doc;
}

From source file:ac.at.tuwien.dsg.utest.transformation.umlclassdiagram2javadb.id.rules.UMLClassDiagram2JavaDBTransformationRule.java

License:Open Source License

public Object createTarget(ITransformContext context) {

    ClassImpl source = (ClassImpl) context.getSource();

    Document document = new Document("@NodeType \n public class " + source.getName() + "{ \n");

    //below helper classes toi generate our desired .java file
    ASTParser parser = ASTParser.newParser(AST.JLS8);
    parser.setSource(document.get().toCharArray());
    CompilationUnit cu = (CompilationUnit) parser.createAST(null);
    cu.recordModifications();/*from   w  w  w . ja  v  a 2 s.  c  om*/
    AST ast = cu.getAST();

    ASTRewrite rewriter = ASTRewrite.create(ast);

    ListRewrite listRewrite = rewriter.getListRewrite(cu, CompilationUnit.TYPES_PROPERTY);

    //TODO: here we take each property introduced by each Stereotype

    for (Stereotype stereotype : source.getAppliedStereotypes()) {

        //get all properties
        for (Property attribute : stereotype.getAllAttributes()) {

            //todo
        }
    }

    for (Property property : source.getAllAttributes()) {
        System.out.println(property.getName());

        Association assoc = property.getAssociation();

        if (assoc == null) {
            System.out.format("this is simple %s \n", property.getName());

            VariableDeclarationFragment varDecl = ast.newVariableDeclarationFragment();
            varDecl.setName(ast.newSimpleName(property.getName()));

            FieldDeclaration propertyField = ast.newFieldDeclaration(varDecl);
            propertyField.setType(ast.newSimpleType(ast.newName(property.getType().getName())));

            final SingleMemberAnnotation annot = ast.newSingleMemberAnnotation();
            annot.setTypeName(ast.newName("Property"));

            StringLiteral st = ast.newStringLiteral();
            st.setLiteralValue("type=\"variable\"");

            annot.setValue(st);

            listRewrite.insertLast(annot, null);
            listRewrite.insertLast(propertyField, null);

        } else {
            System.out.format("this is complex %s \n", property.getName());
            Type type = assoc.getEndTypes().stream().filter(a -> !a.equals(source)).findFirst().get();
            System.out.format("Association end is   %s \n", type.getName());

            AggregationKind kind = property.getAggregation();
            if (kind.equals(AggregationKind.COMPOSITE)) {
                System.out.format("Composition \n");
            } else if (kind.equals(AggregationKind.SHARED)) {
                System.out.format("Aggregation \n");
            } else if (kind.equals(AggregationKind.NONE)) {
                System.out.format("Association \n");
            }

        }

    }

    TextEdit edits = rewriter.rewriteAST(document, null);
    try {
        UndoEdit undo = edits.apply(document);
    } catch (MalformedTreeException | BadLocationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    System.out.println(document.get());

    return null;
}

From source file:ch.acanda.eclipse.pmd.java.resolution.ASTRewriteQuickFix.java

License:Open Source License

@Override
protected boolean fixMarker(final T node, final IDocument document, final Map<?, ?> options)
        throws JavaModelException {
    final ASTRewrite rewrite = ASTRewrite.create(node.getAST());
    final boolean isSuccessful = rewrite(node, rewrite);
    if (isSuccessful) {
        rootTextEdit.addChild(rewrite.rewriteAST(document, options));
    }//from w  w  w  .  j a  v a 2 s. c  om
    return isSuccessful;
}

From source file:ch.acanda.eclipse.pmd.java.resolution.TextEditQuickFixTestCase.java

License:Open Source License

@Test
public void apply() throws MalformedTreeException, BadLocationException, JavaModelException {
    final ASTRewriteQuickFix<ASTNode> quickFix = getQuickFix();
    final org.eclipse.jface.text.Document document = new org.eclipse.jface.text.Document(params.source);
    final CompilationUnit ast = createAST(document);
    final ASTNode node = findNode(params, ast, quickFix);

    final ASTRewrite rewrite = ASTRewrite.create(node.getAST());
    final boolean isSuccessful = quickFix.rewrite(node, rewrite);
    assertTrue("The quick fix should be able to successfully rewrite", isSuccessful);

    rewrite.rewriteAST(document, getOptions()).apply(document);
    final String actual = document.get();
    assertEquals("Result of applying the quick fix " + quickFix.getClass().getSimpleName() + " to the test "
            + params.name, params.expectedSource, actual);
}

From source file:cn.ieclipse.adt.ext.jdt.SourceGenerator.java

License:Apache License

public static void applyChange(ICompilationUnit cu, CompilationUnit unit) {
    try {// w  w  w  .j av  a2  s .  com
        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();
    }
}

From source file:com.android.ide.eclipse.adt.internal.lint.AddSuppressAnnotation.java

License:Open Source License

@SuppressWarnings({ "rawtypes" }) // Java AST API has raw types
private MultiTextEdit addSuppressAnnotation(IDocument document, ICompilationUnit compilationUnit,
        BodyDeclaration declaration) throws CoreException {
    List modifiers = declaration.modifiers();
    SingleMemberAnnotation existing = null;
    for (Object o : modifiers) {
        if (o instanceof SingleMemberAnnotation) {
            SingleMemberAnnotation annotation = (SingleMemberAnnotation) o;
            String type = annotation.getTypeName().getFullyQualifiedName();
            if (type.equals(FQCN_SUPPRESS_LINT) || type.endsWith(SUPPRESS_LINT)) {
                existing = annotation;//from w  w w.  j av  a 2s  .  c  o m
                break;
            }
        }
    }

    ImportRewrite importRewrite = ImportRewrite.create(compilationUnit, true);
    String local = importRewrite.addImport(FQCN_SUPPRESS_LINT);
    AST ast = declaration.getAST();
    ASTRewrite rewriter = ASTRewrite.create(ast);
    if (existing == null) {
        SingleMemberAnnotation newAnnotation = ast.newSingleMemberAnnotation();
        newAnnotation.setTypeName(ast.newSimpleName(local));
        StringLiteral value = ast.newStringLiteral();
        value.setLiteralValue(mId);
        newAnnotation.setValue(value);
        ListRewrite listRewrite = rewriter.getListRewrite(declaration, declaration.getModifiersProperty());
        listRewrite.insertFirst(newAnnotation, null);
    } else {
        Expression existingValue = existing.getValue();
        if (existingValue instanceof StringLiteral) {
            StringLiteral stringLiteral = (StringLiteral) existingValue;
            if (mId.equals(stringLiteral.getLiteralValue())) {
                // Already contains the id
                return null;
            }
            // Create a new array initializer holding the old string plus the new id
            ArrayInitializer array = ast.newArrayInitializer();
            StringLiteral old = ast.newStringLiteral();
            old.setLiteralValue(stringLiteral.getLiteralValue());
            array.expressions().add(old);
            StringLiteral value = ast.newStringLiteral();
            value.setLiteralValue(mId);
            array.expressions().add(value);
            rewriter.set(existing, VALUE_PROPERTY, array, null);
        } else if (existingValue instanceof ArrayInitializer) {
            // Existing array: just append the new string
            ArrayInitializer array = (ArrayInitializer) existingValue;
            List expressions = array.expressions();
            if (expressions != null) {
                for (Object o : expressions) {
                    if (o instanceof StringLiteral) {
                        if (mId.equals(((StringLiteral) o).getLiteralValue())) {
                            // Already contains the id
                            return null;
                        }
                    }
                }
            }
            StringLiteral value = ast.newStringLiteral();
            value.setLiteralValue(mId);
            ListRewrite listRewrite = rewriter.getListRewrite(array, EXPRESSIONS_PROPERTY);
            listRewrite.insertLast(value, null);
        } else {
            assert false : existingValue;
            return null;
        }
    }

    TextEdit importEdits = importRewrite.rewriteImports(new NullProgressMonitor());
    TextEdit annotationEdits = rewriter.rewriteAST(document, null);

    // Apply to the document
    MultiTextEdit edit = new MultiTextEdit();
    // Create the edit to change the imports, only if
    // anything changed
    if (importEdits.hasChildren()) {
        edit.addChild(importEdits);
    }
    edit.addChild(annotationEdits);

    return edit;
}

From source file:com.android.ide.eclipse.adt.internal.lint.AddSuppressAnnotation.java

License:Open Source License

@SuppressWarnings({ "rawtypes" }) // Java AST API has raw types
private MultiTextEdit addTargetApiAnnotation(IDocument document, ICompilationUnit compilationUnit,
        BodyDeclaration declaration) throws CoreException {
    List modifiers = declaration.modifiers();
    SingleMemberAnnotation existing = null;
    for (Object o : modifiers) {
        if (o instanceof SingleMemberAnnotation) {
            SingleMemberAnnotation annotation = (SingleMemberAnnotation) o;
            String type = annotation.getTypeName().getFullyQualifiedName();
            if (type.equals(FQCN_TARGET_API) || type.endsWith(TARGET_API)) {
                existing = annotation;//from   w ww.  j av a  2 s .  com
                break;
            }
        }
    }

    ImportRewrite importRewrite = ImportRewrite.create(compilationUnit, true);
    importRewrite.addImport("android.os.Build"); //$NON-NLS-1$
    String local = importRewrite.addImport(FQCN_TARGET_API);
    AST ast = declaration.getAST();
    ASTRewrite rewriter = ASTRewrite.create(ast);
    if (existing == null) {
        SingleMemberAnnotation newAnnotation = ast.newSingleMemberAnnotation();
        newAnnotation.setTypeName(ast.newSimpleName(local));
        Expression value = createLiteral(ast);
        newAnnotation.setValue(value);
        ListRewrite listRewrite = rewriter.getListRewrite(declaration, declaration.getModifiersProperty());
        listRewrite.insertFirst(newAnnotation, null);
    } else {
        Expression value = createLiteral(ast);
        rewriter.set(existing, VALUE_PROPERTY, value, null);
    }

    TextEdit importEdits = importRewrite.rewriteImports(new NullProgressMonitor());
    TextEdit annotationEdits = rewriter.rewriteAST(document, null);
    MultiTextEdit edit = new MultiTextEdit();
    if (importEdits.hasChildren()) {
        edit.addChild(importEdits);
    }
    edit.addChild(annotationEdits);

    return edit;
}

From source file:com.android.ide.eclipse.adt.internal.refactorings.extractstring.ExtractStringRefactoring.java

License:Open Source License

/**
 * Computes the changes to be made to Java file(s) and returns a list of {@link Change}.
 * <p/>//  w ww .ja va  2 s.c om
 * This function scans a Java compilation unit using {@link ReplaceStringsVisitor}, looking
 * for a string literal equals to <code>tokenString</code>.
 * If found, a change is made to replace each occurrence of <code>tokenString</code> by
 * a piece of Java code that somehow accesses R.string.<code>xmlStringId</code>.
 *
 * @param unit The compilated unit to process. Must not be null.
 * @param tokenString The string to find. Must not be null or empty.
 * @param status Status used to report fatal errors.
 * @param monitor Used to log progress.
 */
private List<Change> computeJavaChanges(ICompilationUnit unit, String xmlStringId, String tokenString,
        RefactoringStatus status, SubMonitor monitor) {

    // We shouldn't be trying to replace a null or empty string.
    assert tokenString != null && tokenString.length() > 0;
    if (tokenString == null || tokenString.length() == 0) {
        return null;
    }

    // Get the Android package name from the Android Manifest. We need it to create
    // the FQCN of the R class.
    String packageName = null;
    String error = null;
    IResource manifestFile = mProject.findMember(SdkConstants.FN_ANDROID_MANIFEST_XML);
    if (manifestFile == null || manifestFile.getType() != IResource.FILE) {
        error = "File not found";
    } else {
        ManifestData manifestData = AndroidManifestHelper.parseForData((IFile) manifestFile);
        if (manifestData == null) {
            error = "Invalid content";
        } else {
            packageName = manifestData.getPackage();
            if (packageName == null) {
                error = "Missing package definition";
            }
        }
    }

    if (error != null) {
        status.addFatalError(String.format("Failed to parse file %1$s: %2$s.",
                manifestFile == null ? "" : manifestFile.getFullPath(), //$NON-NLS-1$
                error));
        return null;
    }

    // Right now the changes array will contain one TextFileChange at most.
    ArrayList<Change> changes = new ArrayList<Change>();

    // This is the unit that will be modified.
    TextFileChange change = new TextFileChange(getName(), (IFile) unit.getResource());
    change.setTextType("java"); //$NON-NLS-1$

    // Create an AST for this compilation unit
    ASTParser parser = ASTParser.newParser(AST.JLS3);
    parser.setProject(unit.getJavaProject());
    parser.setSource(unit);
    parser.setResolveBindings(true);
    ASTNode node = parser.createAST(monitor.newChild(1));

    // The ASTNode must be a CompilationUnit, by design
    if (!(node instanceof CompilationUnit)) {
        status.addFatalError(String.format("Internal error: ASTNode class %s", //$NON-NLS-1$
                node.getClass()));
        return null;
    }

    // ImportRewrite will allow us to add the new type to the imports and will resolve
    // what the Java source must reference, e.g. the FQCN or just the simple name.
    ImportRewrite importRewrite = ImportRewrite.create((CompilationUnit) node, true);
    String Rqualifier = packageName + ".R"; //$NON-NLS-1$
    Rqualifier = importRewrite.addImport(Rqualifier);

    // Rewrite the AST itself via an ASTVisitor
    AST ast = node.getAST();
    ASTRewrite astRewrite = ASTRewrite.create(ast);
    ArrayList<TextEditGroup> astEditGroups = new ArrayList<TextEditGroup>();
    ReplaceStringsVisitor visitor = new ReplaceStringsVisitor(ast, astRewrite, astEditGroups, tokenString,
            Rqualifier, xmlStringId);
    node.accept(visitor);

    // Finally prepare the change set
    try {
        MultiTextEdit edit = new MultiTextEdit();

        // Create the edit to change the imports, only if anything changed
        TextEdit subEdit = importRewrite.rewriteImports(monitor.newChild(1));
        if (subEdit.hasChildren()) {
            edit.addChild(subEdit);
        }

        // Create the edit to change the Java source, only if anything changed
        subEdit = astRewrite.rewriteAST();
        if (subEdit.hasChildren()) {
            edit.addChild(subEdit);
        }

        // Only create a change set if any edit was collected
        if (edit.hasChildren()) {
            change.setEdit(edit);

            // Create TextEditChangeGroups which let the user turn changes on or off
            // individually. This must be done after the change.setEdit() call above.
            for (TextEditGroup editGroup : astEditGroups) {
                TextEditChangeGroup group = new TextEditChangeGroup(change, editGroup);
                if (editGroup instanceof EnabledTextEditGroup) {
                    group.setEnabled(((EnabledTextEditGroup) editGroup).isEnabled());
                }
                change.addTextEditChangeGroup(group);
            }

            changes.add(change);
        }

        monitor.worked(1);

        if (changes.size() > 0) {
            return changes;
        }

    } catch (CoreException e) {
        // ImportRewrite.rewriteImports failed.
        status.addFatalError(e.getMessage());
    }
    return null;
}

From source file:com.android.ide.eclipse.adt.refactorings.extractstring.ExtractStringRefactoring.java

License:Open Source License

/**
 * Computes the changes to be made to Java file(s) and returns a list of {@link Change}.
 *///  w w  w. j  av a2s . com
private List<Change> computeJavaChanges(ICompilationUnit unit, String xmlStringId, String tokenString,
        RefactoringStatus status, SubMonitor subMonitor) {

    // Get the Android package name from the Android Manifest. We need it to create
    // the FQCN of the R class.
    String packageName = null;
    String error = null;
    IResource manifestFile = mProject.findMember(AndroidConstants.FN_ANDROID_MANIFEST);
    if (manifestFile == null || manifestFile.getType() != IResource.FILE) {
        error = "File not found";
    } else {
        try {
            AndroidManifestParser manifest = AndroidManifestParser.parseForData((IFile) manifestFile);
            if (manifest == null) {
                error = "Invalid content";
            } else {
                packageName = manifest.getPackage();
                if (packageName == null) {
                    error = "Missing package definition";
                }
            }
        } catch (CoreException e) {
            error = e.getLocalizedMessage();
        }
    }

    if (error != null) {
        status.addFatalError(
                String.format("Failed to parse file %1$s: %2$s.", manifestFile.getFullPath(), error));
        return null;
    }

    // TODO in a future version we might want to collect various Java files that
    // need to be updated in the same project and process them all together.
    // To do that we need to use an ASTRequestor and parser.createASTs, kind of
    // like this:
    //
    // ASTRequestor requestor = new ASTRequestor() {
    //    @Override
    //    public void acceptAST(ICompilationUnit sourceUnit, CompilationUnit astNode) {
    //        super.acceptAST(sourceUnit, astNode);
    //        // TODO process astNode
    //    }  
    // };
    // ...
    // parser.createASTs(compilationUnits, bindingKeys, requestor, monitor)
    // 
    // and then add multiple TextFileChange to the changes arraylist.

    // Right now the changes array will contain one TextFileChange at most.
    ArrayList<Change> changes = new ArrayList<Change>();

    // This is the unit that will be modified.
    TextFileChange change = new TextFileChange(getName(), (IFile) unit.getResource());
    change.setTextType("java"); //$NON-NLS-1$

    // Create an AST for this compilation unit
    ASTParser parser = ASTParser.newParser(AST.JLS3);
    parser.setProject(unit.getJavaProject());
    parser.setSource(unit);
    parser.setResolveBindings(true);
    ASTNode node = parser.createAST(subMonitor.newChild(1));

    // The ASTNode must be a CompilationUnit, by design
    if (!(node instanceof CompilationUnit)) {
        status.addFatalError(String.format("Internal error: ASTNode class %s", //$NON-NLS-1$
                node.getClass()));
        return null;
    }

    // ImportRewrite will allow us to add the new type to the imports and will resolve
    // what the Java source must reference, e.g. the FQCN or just the simple name.
    ImportRewrite importRewrite = ImportRewrite.create((CompilationUnit) node, true);
    String Rqualifier = packageName + ".R"; //$NON-NLS-1$
    Rqualifier = importRewrite.addImport(Rqualifier);

    // Rewrite the AST itself via an ASTVisitor
    AST ast = node.getAST();
    ASTRewrite astRewrite = ASTRewrite.create(ast);
    ArrayList<TextEditGroup> astEditGroups = new ArrayList<TextEditGroup>();
    ReplaceStringsVisitor visitor = new ReplaceStringsVisitor(ast, astRewrite, astEditGroups, tokenString,
            Rqualifier, xmlStringId);
    node.accept(visitor);

    // Finally prepare the change set
    try {
        MultiTextEdit edit = new MultiTextEdit();

        // Create the edit to change the imports, only if anything changed
        TextEdit subEdit = importRewrite.rewriteImports(subMonitor.newChild(1));
        if (subEdit.hasChildren()) {
            edit.addChild(subEdit);
        }

        // Create the edit to change the Java source, only if anything changed
        subEdit = astRewrite.rewriteAST();
        if (subEdit.hasChildren()) {
            edit.addChild(subEdit);
        }

        // Only create a change set if any edit was collected
        if (edit.hasChildren()) {
            change.setEdit(edit);

            // Create TextEditChangeGroups which let the user turn changes on or off
            // individually. This must be done after the change.setEdit() call above.
            for (TextEditGroup editGroup : astEditGroups) {
                change.addTextEditChangeGroup(new TextEditChangeGroup(change, editGroup));
            }

            changes.add(change);
        }

        // TODO to modify another Java source, loop back to the creation of the
        // TextFileChange and accumulate in changes. Right now only one source is
        // modified.

        if (changes.size() > 0) {
            return changes;
        }

        subMonitor.worked(1);

    } catch (CoreException e) {
        // ImportRewrite.rewriteImports failed.
        status.addFatalError(e.getMessage());
    }
    return null;
}