org.gw4e.eclipse.facade.JDTManager.java Source code

Java tutorial

Introduction

Here is the source code for org.gw4e.eclipse.facade.JDTManager.java

Source

package org.gw4e.eclipse.facade;

/*-
 * #%L
 * gw4e
 * $Id:$
 * $HeadURL:$
 * %%
 * Copyright (C) 2017 gw4e-project
 * %%
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 * #L%
 */

import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

import javax.annotation.Generated;

import org.eclipse.core.filebuffers.FileBuffers;
import org.eclipse.core.filebuffers.ITextFileBuffer;
import org.eclipse.core.filebuffers.ITextFileBufferManager;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaModel;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.ISourceRange;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.JavaConventions;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.ToolFactory;
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.ASTVisitor;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.ExpressionStatement;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.IAnnotationBinding;
import org.eclipse.jdt.core.dom.IBinding;
import org.eclipse.jdt.core.dom.IMemberValuePairBinding;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jdt.core.dom.MemberValuePair;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.NormalAnnotation;
import org.eclipse.jdt.core.dom.PackageDeclaration;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.StringLiteral;
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.formatter.CodeFormatter;
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jdt.ui.actions.OrganizeImportsAction;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.search.core.text.TextSearchEngine;
import org.eclipse.search.core.text.TextSearchMatchAccess;
import org.eclipse.search.core.text.TextSearchRequestor;
import org.eclipse.search.ui.text.FileTextSearchScope;
import org.eclipse.swt.widgets.Display;
import org.eclipse.text.edits.MalformedTreeException;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.ui.IPartService;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.IWorkbenchSite;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.wizards.newresource.BasicNewResourceWizard;
import org.graphwalker.core.generator.PathGenerator;
import org.graphwalker.core.generator.PathGeneratorBase;
import org.graphwalker.core.machine.ExecutionContext;
import org.graphwalker.java.annotation.GraphWalker;
import org.graphwalker.java.annotation.Model;
import org.gw4e.eclipse.builder.Location;
import org.gw4e.eclipse.conversion.ClassExtension;
import org.gw4e.eclipse.refactoring.Helper;
import org.gw4e.eclipse.wizard.convert.AbstractPostConversion;

public class JDTManager {

    public static List<IFile> findAvailableExecutionContextAncestors(IFile file) {
        List<IFile> files = new ArrayList<IFile>();

        IResource[] roots = { file.getProject() };
        String[] fileNamePatterns = new String[] { "*.java" };
        FileTextSearchScope scope = FileTextSearchScope.newSearchScope(roots, fileNamePatterns, false);
        IPath path = Helper.buildGeneratedAnnotationValue(file);
        Pattern pattern = Pattern.compile(Helper.getGeneratedAnnotationRegExp(path));
        TextSearchRequestor collector = new TextSearchRequestor() {
            @Override
            public boolean acceptPatternMatch(TextSearchMatchAccess matchAccess) throws CoreException {
                IFile file = matchAccess.getFile();
                files.add(file);
                return true;
            }
        };
        TextSearchEngine.create().search(scope, collector, pattern, new NullProgressMonitor());
        return files;
    }

    /**
     * @param elt
     * @return
     * @throws JavaModelException
     */
    public static String getFullyQualifiedName(IJavaElement elt) throws JavaModelException {
        IPackageFragmentRoot[] roots = elt.getJavaProject().getPackageFragmentRoots();
        for (int i = 0; i < roots.length; i++) {
            if (roots[i].getPath().isPrefixOf(elt.getPath())) {
                IPath p = elt.getPath().makeRelativeTo(roots[i].getPath());
                return p.toString();
            }
        }
        return elt.getElementName();
    }

    public static String getJavaFullyQualifiedName(IJavaElement elt) throws JavaModelException {
        String name = getFullyQualifiedName(elt);
        name = name.split("\\.")[0];
        name = name.replaceAll("\\/", "\\.");
        return name;
    }

    /**
     * Find the path of the graph model file that is the origin of the passed
     * type The one which has been converted ..
     * 
     * @param project
     * @param itype
     * @return
     * @throws JavaModelException
     */
    public static IPath getGraphModelPath(IProject project, IType itype) throws JavaModelException {
        IPath path = findPathInGeneratedAnnotation(project, itype);
        if (path == null) {
            path = findPathInStaticField(project, itype);
        }
        return path;
    }

    /**
     * @param project
     * @param itype
     * @return
     * @throws JavaModelException
     */
    private static IPath findPathInGeneratedAnnotation(IProject project, IType itype) throws JavaModelException {
        ICompilationUnit cu = itype.getCompilationUnit();
        List<IAnnotationBinding> annotations = resolveAnnotation(cu, Generated.class).getAnnotations();
        if ((annotations != null) && (annotations.size() > 0)) {
            IAnnotationBinding ab = annotations.get(0);
            IMemberValuePairBinding[] attributes = ab.getAllMemberValuePairs();
            for (int i = 0; i < attributes.length; i++) {
                IMemberValuePairBinding attribut = attributes[i];
                if (attribut.getName().equalsIgnoreCase("value")) {
                    Object[] o = (Object[]) attribut.getValue();
                    if (o != null && o.length > 0 && String.valueOf(o[0]).trim().length() > 0) {
                        try {
                            IPath p = ResourceManager.find(project, String.valueOf(o[0]).trim());
                            return p;
                        } catch (Exception e) {
                            ResourceManager.logException(e);
                            return null;
                        }
                    }
                }
            }
        }
        return null;
    }

    public static ICompilationUnit[] getOrCreateGeneratedTestInterfaces(IProject project)
            throws CoreException, FileNotFoundException {

        project.refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor());
        IPath folderForMain = project.getFullPath()
                .append(GraphWalkerContextManager.getTargetFolderForTestInterface(project.getName(), true));
        IPath folderForTest = project.getFullPath()
                .append(GraphWalkerContextManager.getTargetFolderForTestInterface(project.getName(), false));
        if (ResourceManager.getResource(folderForMain.toString()) == null
                && ResourceManager.getResource(folderForTest.toString()) == null) {
            throw new IllegalStateException(
                    "No target/generated-sources or target/generated-test-sources folders found");
        }

        // In main resource folder
        ICompilationUnit[] inMain = getExistingGeneratedTestInterfaces(project, true);
        // In test resource folder
        ICompilationUnit[] inTest = getExistingGeneratedTestInterfaces(project, false);
        ICompilationUnit[] ret = new ICompilationUnit[inMain.length + inTest.length];
        System.arraycopy(inMain, 0, ret, 0, inMain.length);
        System.arraycopy(inTest, 0, ret, inMain.length, inTest.length);
        return ret;
    }

    public static IPath guessPackageRootFragment(IProject project, boolean main)
            throws CoreException, FileNotFoundException {
        IPath folder = project.getFullPath()
                .append(GraphWalkerContextManager.getTargetFolderForTestInterface(project.getName(), main));

        IResource interfaceFolder = ResourceManager.toResource(folder);
        List<IPath> paths = new ArrayList<IPath>();
        if (interfaceFolder != null) {
            interfaceFolder.accept(new IResourceVisitor() {
                @Override
                public boolean visit(IResource resource) throws CoreException {
                    IJavaElement element = JavaCore.create(resource);
                    if (element != null && element instanceof ICompilationUnit) {
                        try {
                            ICompilationUnit cu = (ICompilationUnit) element;
                            CompilationUnit ast = parse(cu);
                            ast.accept(new ASTVisitor() {
                                public boolean visit(PackageDeclaration node) {
                                    PackageDeclaration decl = (PackageDeclaration) node;
                                    String pkgname = decl.getName().getFullyQualifiedName();
                                    int sizePath = pkgname.split("\\.").length;
                                    paths.add(resource.getParent().getFullPath().removeLastSegments(sizePath));
                                    return false;
                                }
                            });
                        } catch (Exception e) {
                            ResourceManager.logException(e);
                        }
                    }
                    return true;
                }
            });
        }
        if (paths.size() == 0)
            return null;
        return paths.get(0);
    }

    /**
     * @param project
     * @return
     * @throws CoreException
     * @throws FileNotFoundException
     */
    public static ICompilationUnit[] getExistingGeneratedTestInterfaces(IProject project, boolean main)
            throws CoreException, FileNotFoundException {
        IPath folder = project.getFullPath()
                .append(GraphWalkerContextManager.getTargetFolderForTestInterface(project.getName(), main));
        List<ICompilationUnit> units = new ArrayList<ICompilationUnit>();
        IResource interfaceFolder = ResourceManager.toResource(folder);
        if (interfaceFolder != null) {
            interfaceFolder.accept(new IResourceVisitor() {
                @Override
                public boolean visit(IResource resource) throws CoreException {
                    IJavaElement element = JavaCore.create(resource);
                    if (element != null && element instanceof ICompilationUnit) {
                        try {
                            ICompilationUnit cu = (ICompilationUnit) element;
                            IType interf = cu.findPrimaryType();
                            if (interf != null && interf.isInterface()) {
                                units.add(cu);
                            }
                        } catch (Exception e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                    return true;
                }
            });
        }
        ICompilationUnit[] ret = new ICompilationUnit[units.size()];
        units.toArray(ret);
        return ret;
    }

    /**
     * @param project
     * @param itype
     * @return
     * @throws JavaModelException
     */
    public static IPath findPathInModelAnnotation(IProject project, IType itype) throws JavaModelException {
        ICompilationUnit cu = itype.getCompilationUnit();
        List<IAnnotationBinding> annotations = resolveAnnotation(cu, Model.class).getAnnotations();
        if ((annotations != null) && (annotations.size() > 0)) {
            IAnnotationBinding ab = annotations.get(0);
            IMemberValuePairBinding[] attributes = ab.getAllMemberValuePairs();
            for (int i = 0; i < attributes.length; i++) {
                IMemberValuePairBinding attribut = attributes[i];
                if (attribut.getName().equalsIgnoreCase("value")) {
                    Object[] o = (Object[]) attribut.getValue();
                    if (o != null && o.length > 0 && String.valueOf(o[0]).trim().length() > 0) {
                        try {
                            IPath p = ResourceManager.find(project, String.valueOf(o[0]).trim());
                            return p;
                        } catch (Exception e) {
                            ResourceManager.logException(e);
                            return null;
                        }
                    }
                }
            }
        }
        return null;
    }

    private static boolean isContext(ITypeBinding tbinding) {
        String executionContextClass = org.graphwalker.core.machine.ExecutionContext.class.getName();
        String contextClass = org.graphwalker.core.machine.Context.class.getName();
        while (tbinding != null) {
            String clazz = tbinding.getQualifiedName();
            if (executionContextClass.equals(clazz))
                return true;
            if (contextClass.equals(clazz))
                return true;
            ITypeBinding[] interfaces = tbinding.getInterfaces();
            for (int i = 0; i < interfaces.length; i++) {
                ITypeBinding interf = interfaces[i];
                if (contextClass.equals(interf.getQualifiedName()))
                    return true;
            }
            tbinding = tbinding.getSuperclass();
        }
        return false;

    }

    public static AnnotationParsing findAnnotationParsingInGeneratedAnnotation(ICompilationUnit cu,
            String attribut) {
        AnnotationParsing annoParsing = resolveAnnotation(cu, Generated.class, attribut);
        return annoParsing;
    }

    /**
     * @param cu
     * @return
     * @throws JavaModelException
     */
    public static AnnotationParsing findAnnotationParsingInGraphWalkerAnnotation(ICompilationUnit cu,
            String attribut) {
        AnnotationParsing annoParsing = resolveAnnotation(cu, GraphWalker.class, attribut);
        return annoParsing;
    }

    public static AnnotationParsing findAnnotationParsingInModelAnnotation(ICompilationUnit cu, String attribut) {
        AnnotationParsing annoParsing = resolveAnnotation(cu, Model.class, attribut);
        return annoParsing;
    }

    /**
     * @param cu
     * @return
     */
    public static String findPathGeneratorInGraphWalkerAnnotation(ICompilationUnit cu) {
        CompilationUnit ast = parse(cu);
        Map<String, String> ret = new HashMap<String, String>();
        ast.accept(new ASTVisitor() {
            public boolean visit(MemberValuePair node) {
                String name = node.getName().getFullyQualifiedName();
                if ("value".equals(name) && node.getParent() != null
                        && node.getParent() instanceof NormalAnnotation) {
                    IAnnotationBinding annoBinding = ((NormalAnnotation) node.getParent())
                            .resolveAnnotationBinding();
                    String qname = annoBinding.getAnnotationType().getQualifiedName();
                    if (GraphWalker.class.getName().equals(qname)) {
                        StringLiteral sl = (StringLiteral) node.getValue();
                        ret.put("ret", sl.getLiteralValue());
                    }
                }
                return true;
            }
        });
        return ret.get("ret");
    }

    /**
     * @param project
     * @param itype
     * @return
     */
    public static Set<String> findPathGeneratorClassInstanceCreation(IJavaProject project, IType itype) {
        Set<String> ret = new HashSet<String>();
        ICompilationUnit cu = itype.getCompilationUnit();
        CompilationUnit ast = parse(cu);

        ast.accept(new ASTVisitor() {
            public boolean visit(ClassInstanceCreation node) {
                Type createdType = node.getType();
                ITypeBinding binding = createdType.resolveBinding();
                IType boundType = (IType) binding.getJavaElement();
                try {
                    IType execContextType = project.findType(PathGeneratorBase.class.getName());
                    ITypeHierarchy th = boundType.newTypeHierarchy(null);
                    if (th.contains(execContextType)) {
                        int start = node.getStartPosition();
                        int end = node.getLength();
                        try {
                            String code = cu.getSource().substring(start, start + end);
                            ret.add(code);
                        } catch (JavaModelException e) {
                            ResourceManager.logException(e);
                        }
                    }
                    ;
                } catch (JavaModelException e) {
                    ResourceManager.logException(e);
                }
                return true;
            }
        });
        return ret;
    }

    /**
     * @param project
     * @param itype
     * @return
     * @throws JavaModelException
     */
    public static Map<String, List<String>> findSetPathGeneratorInvocation(IProject project, IType itype)
            throws JavaModelException {
        Map<String, List<String>> ret = new HashMap<String, List<String>>();
        ICompilationUnit cu = itype.getCompilationUnit();
        CompilationUnit ast = parse(cu);

        ast.accept(new ASTVisitor() {
            public boolean visit(MethodDeclaration node) {
                List<?> modifiers = (List<?>) node.getStructuralProperty(MethodDeclaration.MODIFIERS2_PROPERTY);
                for (Object modifier : modifiers) {
                    if (modifier instanceof org.eclipse.jdt.core.dom.Annotation) {
                        IAnnotationBinding annotationBinding = ((org.eclipse.jdt.core.dom.Annotation) modifier)
                                .resolveAnnotationBinding();
                        if (annotationBinding != null) {

                            final String qualifiedName = annotationBinding.getAnnotationType().getQualifiedName();

                            if ("org.junit.Test".equalsIgnoreCase(qualifiedName)) {
                                Map<String, String> variables = new HashMap<String, String>();
                                node.accept(new ASTVisitor() {
                                    public boolean visit(VariableDeclarationStatement node) {
                                        for (int i = 0; i < node.fragments().size(); ++i) {
                                            VariableDeclarationFragment frag = (VariableDeclarationFragment) node
                                                    .fragments().get(i);
                                            if (isContext(node.getType().resolveBinding())) {
                                                Expression initializer = frag.getInitializer();
                                                JDTManager.ExpressionVisitor ev = new ExpressionVisitor(variables);
                                                initializer.accept(ev);
                                                if (ev.getValue() != null) {
                                                    variables.put(frag.getName().getFullyQualifiedName(),
                                                            ev.getValue());
                                                }
                                            }
                                        }
                                        return true;
                                    }

                                    public boolean visit(MethodInvocation node) {
                                        SimpleName simpleName = node.getName();

                                        IBinding bding = simpleName.resolveBinding();

                                        if (bding instanceof IMethodBinding) {
                                            IMethodBinding imb = (IMethodBinding) bding;
                                            if ("setPathGenerator".equalsIgnoreCase(imb.getName())) {
                                                ITypeBinding[] arguments = imb.getParameterTypes();
                                                if (arguments.length == 1) {
                                                    if (isContext(imb.getDeclaringClass())
                                                            && PathGenerator.class.getName()
                                                                    .equals(arguments[0].getQualifiedName())
                                                            && isContext(imb.getReturnType())) {
                                                        int start = node.getStartPosition();
                                                        int end = node.getLength();
                                                        try {
                                                            String code = cu.getSource().substring(start,
                                                                    start + end);
                                                            // System.out.println(code);
                                                        } catch (JavaModelException e) {
                                                            ResourceManager.logException(e);
                                                        }
                                                        List args = node.arguments();
                                                        Expression argumentExpression = (Expression) args.get(0);
                                                        ITypeBinding typeBinding = argumentExpression
                                                                .resolveTypeBinding();
                                                        String parameterName = "";
                                                        if (typeBinding != null) {
                                                            parameterName = argumentExpression.toString();
                                                            JDTManager.ExpressionVisitor ev = new ExpressionVisitor(
                                                                    variables);
                                                            Expression expression = node.getExpression();
                                                            expression.accept(ev);
                                                            if (ev.getValue() != null) {
                                                                String contextClass = ev.getValue();
                                                                List<String> generators = ret.get(contextClass);
                                                                if (generators == null) {
                                                                    generators = new ArrayList<String>();
                                                                    ret.put(contextClass, generators);
                                                                }

                                                                if (!"null".equals(parameterName)
                                                                        && !generators.contains(parameterName)) {
                                                                    generators.add(parameterName);
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                        return true;
                                    }
                                });
                            }
                        }
                    }
                }
                return true;
            }
        });
        return ret;
    }

    static class ExpressionVisitor extends ASTVisitor {
        String value;
        Map<String, String> variables;

        ExpressionVisitor(Map<String, String> variables) {
            this.variables = variables;
        }

        public String getValue() {
            return value;
        }

        public boolean visit(ClassInstanceCreation cic) {
            try {
                this.value = cic.getType().resolveBinding().getQualifiedName().toString();
            } catch (Throwable e) {
            }
            return false;
        }

        public boolean visit(MethodInvocation node) {
            try {
                SimpleName simpleName = node.getName();
                IBinding bding = simpleName.resolveBinding();
                if (bding instanceof IMethodBinding) {
                    IMethodBinding imb = (IMethodBinding) bding;
                    if (isContext(imb.getReturnType())) {
                        this.value = imb.getReturnType().getQualifiedName().toString();
                    }
                }
            } catch (Throwable e) {
            }
            return false;
        }

        public boolean visit(SimpleName node) {
            try {
                this.value = variables.get(node.getFullyQualifiedName());
            } catch (Throwable e) {
            }
            return true;
        }

    }

    public static Set<String> findGeneratorFactoryParseInvocation(IProject project, IType itype)
            throws JavaModelException {
        Set<String> ret = new HashSet<String>();
        ICompilationUnit cu = itype.getCompilationUnit();
        CompilationUnit ast = parse(cu);

        ast.accept(new ASTVisitor() {
            public boolean visit(MethodInvocation node) {
                SimpleName simpleName = node.getName();
                IBinding bding = simpleName.resolveBinding();
                if (bding instanceof IMethodBinding) {
                    IMethodBinding imb = (IMethodBinding) bding;
                    if ("parse".equalsIgnoreCase(imb.getName())) {
                        ITypeBinding[] arguments = imb.getParameterTypes();
                        if (arguments.length == 1) {
                            if (String.class.getName().equals(arguments[0].getQualifiedName())
                                    && PathGenerator.class.getName()
                                            .equals(imb.getReturnType().getQualifiedName())) {
                                int start = node.getStartPosition();
                                int end = node.getLength();
                                try {
                                    String code = cu.getSource().substring(start, start + end);
                                    // System.out.println(code);
                                } catch (JavaModelException e) {
                                    ResourceManager.logException(e);
                                }
                                List args = node.arguments();
                                Expression argumentExpression = (Expression) args.get(0);
                                ITypeBinding typeBinding = argumentExpression.resolveTypeBinding();
                                if (typeBinding != null) {
                                    if (argumentExpression instanceof StringLiteral) {
                                        StringLiteral sl = (StringLiteral) argumentExpression;
                                        String lv = sl.getLiteralValue();
                                        ret.add(lv);
                                    }
                                }
                            }
                        }
                    }
                }

                return true;
            }
        });
        return ret;
    }

    /**
     * @param project
     * @param itype
     * @return
     * @throws JavaModelException
     */
    private static IPath findPathInStaticField(IProject project, IType itype) throws JavaModelException {
        List<IPath> wrapper = new ArrayList<IPath>();
        ICompilationUnit cu = itype.getCompilationUnit();
        CompilationUnit ast = parse(cu);
        ast.accept(new ASTVisitor() {
            public boolean visit(VariableDeclarationFragment node) {
                SimpleName simpleName = node.getName();
                IBinding bding = simpleName.resolveBinding();
                if (bding instanceof IVariableBinding) {
                    IVariableBinding binding = (IVariableBinding) bding;
                    String type = binding.getType().getBinaryName(); //
                    String name = simpleName.getFullyQualifiedName();
                    if ("MODEL_PATH".equals(name) && "java.nio.file.Path".equals(type)) {
                        Expression expression = node.getInitializer();
                        if (expression instanceof MethodInvocation) {
                            MethodInvocation mi = (MethodInvocation) expression;
                            if ("get".equals(mi.resolveMethodBinding().getName())
                                    && "java.nio.file.Path".equals(mi.resolveTypeBinding().getBinaryName())) {
                                StringLiteral sl = (StringLiteral) mi.arguments().get(0);
                                String argument = sl.getLiteralValue();
                                try {
                                    IPath p = ResourceManager.find(project, argument);
                                    wrapper.add(p);
                                } catch (CoreException e) {
                                    ResourceManager.logException(e);
                                }
                            }
                        }
                    }
                }
                return true;
            }
        });
        if (wrapper.size() > 0)
            return wrapper.get(0);
        return null;
    }

    private static IType getClassesWithAnnotation(ICompilationUnit compilationUnit, Class annotationClass,
            String attributName, boolean valued) throws JavaModelException {
        List<IAnnotationBinding> annotations = resolveAnnotation(compilationUnit, annotationClass).getAnnotations();
        if ((annotations != null) && (annotations.size() > 0)) {
            IAnnotationBinding ab = annotations.get(0);
            IMemberValuePairBinding[] attributes = ab.getAllMemberValuePairs();
            for (int i = 0; i < attributes.length; i++) {
                IMemberValuePairBinding attribut = attributes[i];
                if (attribut.getName().equalsIgnoreCase(attributName)) {
                    if (valued) {
                        if (String.valueOf(attribut.getValue()).trim().length() > 0) {
                            return compilationUnit.findPrimaryType();
                        }
                    } else {
                        if (String.valueOf(attribut.getValue()).trim().length() == 0) {
                            return compilationUnit.findPrimaryType();
                        }
                    }
                }
            }
        }
        return null;
    }

    /**
     * @param projectName
     * @return
     * @throws JavaModelException
     */
    private static List<IType> findClassesWithAnnotation(String projectName, Class annotationClass,
            String attributName, boolean valued) throws JavaModelException {
        List<IType> classList = new ArrayList<IType>();
        IProject project = ResourceManager.getProject(projectName);
        IJavaProject javaProject = JavaCore.create(project);
        IPackageFragment[] packages = javaProject.getPackageFragments();
        for (IPackageFragment packageFragment : packages) {
            for (final ICompilationUnit compilationUnit : packageFragment.getCompilationUnits()) {
                if (compilationUnit.exists()) {
                    IType type = getClassesWithAnnotation(compilationUnit, annotationClass, attributName, valued);
                    if (type != null)
                        classList.add(type);
                }
            }
        }
        return classList;
    }

    /**
     * @param compilationUnit
     * @param progressMonitor
     * @return
     * @throws JavaModelException
     */

    public static CompilationUnit parse(final ICompilationUnit cu) {
        ASTParser parser = ASTParser.newParser(AST.JLS8);
        parser.setKind(ASTParser.K_COMPILATION_UNIT);
        parser.setSource(cu);
        parser.setResolveBindings(true);
        parser.setEnvironment(null, null, null, true);
        parser.setBindingsRecovery(true);
        final CompilationUnit ast = (CompilationUnit) parser.createAST(new NullProgressMonitor());

        return ast;
    }

    public static boolean hasStartableGraphWalkerAnnotation(Object receiver) {
        ICompilationUnit cu = null;
        if (receiver instanceof ICompilationUnit) {
            cu = (ICompilationUnit) receiver;
            List<IAnnotationBinding> annotations = resolveAnnotation(cu, GraphWalker.class).getAnnotations();
            if ((annotations != null) && annotations.size() > 0) {
                IAnnotationBinding ab = annotations.get(0);
                IMemberValuePairBinding[] attributes = ab.getAllMemberValuePairs();
                for (int i = 0; i < attributes.length; i++) {
                    IMemberValuePairBinding attribut = attributes[i];
                    if (attribut.getName().toLowerCase().equalsIgnoreCase("start")) {

                        if (attribut.getValue() != null
                                && String.valueOf(attribut.getValue()).trim().length() > 0) {
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }

    /**
     * @param testInterface
     * @return
     * @throws JavaModelException
     */
    public static boolean isGraphWalkerExecutionContextClass(ICompilationUnit unit) throws JavaModelException {
        IType[] types = unit.getAllTypes();

        if (types == null || types.length == 0) {
            ResourceManager.logInfo(unit.getJavaProject().getProject().getName(),
                    "getAllTypes return null" + unit.getPath());
            return false;
        }
        IType execContextType = unit.getJavaProject().findType(ExecutionContext.class.getName());

        for (int i = 0; i < types.length; i++) {
            IType type = types[i];
            String typeNname = type.getFullyQualifiedName();
            String compilationUnitName = JDTManager.getJavaFullyQualifiedName(unit);
            if (typeNname.equals(compilationUnitName)) {
                try {
                    ITypeHierarchy th = types[0].newTypeHierarchy(new NullProgressMonitor());
                    return th.contains(execContextType);
                } catch (Exception e) {
                    ResourceManager.logException(e);
                }
            }
        }
        return false;
    }

    /**
     * @param receiver
     * @return
     * @throws JavaModelException
     */
    public static String getGW4EGeneratedAnnotationValue(Object receiver, String attribut) {
        ICompilationUnit cu = null;
        if (receiver instanceof ICompilationUnit) {
            cu = (ICompilationUnit) receiver;
            List<IAnnotationBinding> annotations = resolveAnnotation(cu, Generated.class).getAnnotations();
            if ((annotations != null) && annotations.size() > 0) {
                IAnnotationBinding generated = annotations.get(0);
                IMemberValuePairBinding[] vpb = generated.getAllMemberValuePairs();
                for (int i = 0; i < vpb.length; i++) {
                    IMemberValuePairBinding pair = vpb[i];
                    if (attribut.equals(pair.getName())) {
                        Object[] value = (Object[]) pair.getValue();
                        if (value == null || value.length == 0)
                            return null;
                        return String.valueOf(value[0]);
                    }
                }
            }
        }
        return null;
    }

    /**
     * @param receiver
     * @return
     * @throws JavaModelException
     */
    public static boolean hasGraphWalkerAnnotation(Object receiver) {
        ICompilationUnit cu = null;
        if (receiver instanceof ICompilationUnit) {
            cu = (ICompilationUnit) receiver;
            List<IAnnotationBinding> annotations = resolveAnnotation(cu, GraphWalker.class).getAnnotations();
            return ((annotations != null) && annotations.size() > 0);
        }
        return false;
    }

    public static AnnotationParsing resolveAnnotation(ICompilationUnit cu, Class inputClass) {
        return resolveAnnotation(cu, inputClass, "value");
    }

    /**
     * @param cu
     * @param annotationName
     * @return
     * @throws JavaModelException
     */
    public static AnnotationParsing resolveAnnotation(ICompilationUnit cu, Class inputClass,
            final String attribut) {

        CompilationUnit ast = parse(cu);
        AnnotationParsing ret = new AnnotationParsing();
        String annotationName = inputClass.getName();
        ast.accept(new ASTVisitor() {
            public boolean visit(MemberValuePair node) {
                String name = node.getName().getFullyQualifiedName();
                if (attribut.equals(name) && node.getParent() != null
                        && node.getParent() instanceof NormalAnnotation) {
                    IAnnotationBinding annoBinding = ((NormalAnnotation) node.getParent())
                            .resolveAnnotationBinding();
                    String qname = annoBinding.getAnnotationType().getQualifiedName();
                    if (inputClass.getName().equals(qname)) {
                        int start = node.getStartPosition();
                        int end = start + node.getLength();
                        int lineNumber = ast.getLineNumber(start);
                        Location location = new Location(lineNumber, start, end);
                        ret.setLocation(location);
                    }
                }
                return true;
            }

            public final boolean visit(final TypeDeclaration node) {
                List<?> modifiers = (List<?>) node.getStructuralProperty(TypeDeclaration.MODIFIERS2_PROPERTY);
                for (Object modifier : modifiers) {
                    if (modifier instanceof org.eclipse.jdt.core.dom.Annotation) {
                        IAnnotationBinding annotationBinding = ((org.eclipse.jdt.core.dom.Annotation) modifier)
                                .resolveAnnotationBinding();

                        if (annotationBinding != null) {
                            final String qualifiedName = annotationBinding.getAnnotationType().getQualifiedName();
                            if (annotationName.equalsIgnoreCase(qualifiedName))
                                ret.add(annotationBinding);

                        }
                    }
                }
                return true;
            }
        });
        return ret;
    }

    /**
     * @param projectName
     * @return
     * @throws JavaModelException
     */
    public static List<IType> getStartableGraphWalkerClasses(String projectName) {
        try {

            return findClassesWithAnnotation(projectName, GraphWalker.class, "start", true);
        } catch (Exception e) {
            ResourceManager.logException(e);
            return new ArrayList<IType>();
        }
    }

    /**
     * @param projectName
     * @return
     */
    public static List<IType> getOrphanGraphWalkerClasses(IType type, boolean hint) {
        try {
            IProject project = ResourceManager.getResource(type.getPath().toString()).getProject();
            String projectName = project.getName();

            List<IType> all = findClassesWithAnnotation(projectName, GraphWalker.class, "value", true);
            if (hint) {
                all = GraphWalkerFacade.getSharedContexts(project, type, all);
                all.remove(type);
            }

            Collections.sort(all, new Comparator() {
                @Override
                public int compare(Object o1, Object o2) {
                    IType type1 = (IType) o1;
                    IType type2 = (IType) o2;
                    return type1.getFullyQualifiedName().compareTo(type2.getFullyQualifiedName());
                }
            });
            return all;
        } catch (Exception e) {
            ResourceManager.logException(e);
            return new ArrayList<IType>();
        }
    }

    /**
     * Generate a test implementation if it does not exist
     * 
     * @param implementationFolder
     * @param implementationFragmentRoot
     * @param targetPkg
     * @param interfaceCompUnit
     * @param monitor
     * @throws CoreException
     */
    public static IFile generateTestImplementation(TestResourceGeneration provider, IProgressMonitor monitor)
            throws Exception {

        IFile ifile = provider.toIFile();

        if (ifile.exists()) {
            JDTManager.rename(ifile, monitor);
            ifile.delete(true, monitor);
        }
        if (ifile.exists())
            return null;

        NewExecutionContextClassWizardPageRunner execRunner = new NewExecutionContextClassWizardPageRunner(provider,
                monitor);
        Display.getDefault().syncExec(execRunner);
        IPath path = execRunner.getType().getPath();
        IFile createdFile = (IFile) ResourceManager.getResource(path.toString());
        return createdFile;
    }

    /**
     * Save the AST int he Compilation Unit
     * 
     * @param testInterface
     * @param rewrite
     * @throws CoreException
     */
    public static void save(CompilationUnit unit, ASTRewrite rewrite) throws CoreException {

        ITextFileBufferManager bufferManager = FileBuffers.getTextFileBufferManager();
        IPath path = unit.getJavaElement().getPath();
        try {
            bufferManager.connect(path, null);
            ITextFileBuffer textFileBuffer = bufferManager.getTextFileBuffer(path);
            IDocument document = textFileBuffer.getDocument();
            TextEdit edit = rewrite.rewriteAST(document, null);
            edit.apply(document);
            textFileBuffer.commit(null /* ProgressMonitor */, true /* Overwrite */);
        } catch (Exception e) {
            ResourceManager.logException(e);
        } finally {
            // disconnect the path
            bufferManager.disconnect(path, null);
        }
    }

    /**
     * @param cu
     * @param rewrite
     * @param ast
     * @param pkgDeclaration
     */
    private static void addPackageDeclaration(CompilationUnit cu, ASTRewrite rewrite, AST ast,
            String[] pkgDeclaration) {
        PackageDeclaration packageDeclaration = ast.newPackageDeclaration();
        Name name = ast.newName(pkgDeclaration);
        packageDeclaration.setName(name);
        rewrite.set(cu, CompilationUnit.PACKAGE_PROPERTY, packageDeclaration, null);

    }

    /**
     * @param file
     * @param cu
     * @param rewrite
     * @param ast
     * @throws JavaModelException
     */
    private static void addPackageDeclarationIfNeeded(IFile file, CompilationUnit cu, ASTRewrite rewrite, AST ast)
            throws JavaModelException {
        IJavaProject javaProject = JavaCore.create(file.getProject());
        IClasspathEntry[] entries = javaProject.getRawClasspath();
        for (int i = 0; i < entries.length; i++) {
            IClasspathEntry entry = entries[i];
            if (IClasspathEntry.CPE_SOURCE == entry.getEntryKind()) {
                if (entry.getPath().isPrefixOf(file.getFullPath())) {
                    IPath path = file.getFullPath().makeRelativeTo(entry.getPath());
                    path = path.removeLastSegments(1); // remove the file
                    // name from the
                    // path
                    if (path.segmentCount() == 0)
                        return; // no package declaration needs to be done
                    int length = path.segmentCount();
                    String[] pkgDeclaration = new String[length];
                    for (int j = 0; j < length; j++) {
                        pkgDeclaration[j] = path.segment(j);
                    }
                    addPackageDeclaration(cu, rewrite, ast, pkgDeclaration);
                    return;
                }
            }

        }
    }

    /**
     * Rename a class name into another name
     * 
     * @param file
     * @param oldClassname
     * @param newName
     * @param monitor
     * @return
     * @throws MalformedTreeException
     * @throws BadLocationException
     * @throws CoreException
     */
    public static IFile renameClass(IFile file, String oldClassname, String newName, IProgressMonitor monitor)
            throws MalformedTreeException, BadLocationException, CoreException {
        Display.getDefault().syncExec(new Runnable() {

            @Override
            public void run() {
                try {

                    ICompilationUnit unit = JavaCore.createCompilationUnitFrom(file);
                    CompilationUnit cu = parse(unit);
                    AST ast = cu.getAST();
                    ASTRewrite rewrite = ASTRewrite.create(ast);

                    String classname = file.getName();
                    classname = classname.substring(0, classname.indexOf("."));
                    final String clazz = classname;
                    ASTVisitor visitor = new ASTVisitor() {
                        public boolean visit(SimpleName node) {
                            String s = node.getIdentifier();
                            if (oldClassname.equalsIgnoreCase(s)) {
                                rewrite.replace(node, ast.newSimpleName(newName), null);
                            }
                            return true;
                        }
                    };
                    cu.accept(visitor);

                    addPackageDeclarationIfNeeded(file, cu, rewrite, ast);
                    file.refreshLocal(IResource.DEPTH_ZERO, monitor);
                    cu = parse(JavaCore.createCompilationUnitFrom(file));
                    save(cu, rewrite);
                } catch (Exception e) {
                    ResourceManager.logException(e);
                }
            }
        });
        return file;
    }

    /**
     * @param ifile
     * @param monitor
     * @throws JavaModelException
     */
    public static void rename(IFile ifile, IProgressMonitor monitor) throws JavaModelException {
        if (!ifile.getName().endsWith(".java"))
            return;
        ICompilationUnit unit = JavaCore.createCompilationUnitFrom(ifile);
        String name = ifile.getName();
        String[] segments = name.split("\\.");

        name = segments[0] + System.currentTimeMillis() + "." + segments[1];
        unit.rename(name, false, monitor);
        unit.close();
    }

    /**
     * @param file
     * @param info
     * @param monitor
     * @throws MalformedTreeException
     * @throws BadLocationException
     * @throws CoreException
     */
    @SuppressWarnings("deprecation")
    public static void enrichClass(IFile file, TestResourceGeneration info, IProgressMonitor monitor)
            throws MalformedTreeException, BadLocationException, CoreException {
        ICompilationUnit compilationUnit = JavaCore.createCompilationUnitFrom(file);
        try {

            String source = compilationUnit.getSource();

            Document document = new Document(source);
            compilationUnit.becomeWorkingCopy(new SubProgressMonitor(monitor, 1));
            ASTParser parser = ASTParser.newParser(AST.JLS8);
            parser.setSource(compilationUnit);
            parser.setResolveBindings(true);
            CompilationUnit astRoot = (CompilationUnit) parser.createAST(new SubProgressMonitor(monitor, 1));
            astRoot.recordModifications();
            final AST ast = astRoot.getAST();

            boolean[] hasGraphWalkerAnnotation = new boolean[1];
            boolean[] hasGeneratedAnnotation = new boolean[1];
            boolean[] hasStaticField = new boolean[1];
            // Add a System.out.println("xxx") statement to the methods
            astRoot.accept(new ASTVisitor() {
                @SuppressWarnings("unchecked")
                @Override
                public boolean visit(MethodDeclaration node) {
                    if (info.isAppendSource())
                        return false; // dont touch the existing code if we are
                                      // appending new source code.
                    ExpressionStatement md = info.getClassExtension().getBodyMethod(node.getName().toString());
                    ASTNode copiedNode = ASTNode.copySubtree(node.getAST(), md);
                    node.setBody(ast.newBlock());
                    node.getBody().statements().add(copiedNode);
                    return false;
                }

                @Override
                public boolean visit(NormalAnnotation node) {
                    if (!hasGeneratedAnnotation[0])
                        hasGeneratedAnnotation[0] = (node.getTypeName().getFullyQualifiedName()
                                .indexOf(Generated.class.getSimpleName()) != -1);
                    if (!hasGraphWalkerAnnotation[0])
                        hasGraphWalkerAnnotation[0] = (node.getTypeName().getFullyQualifiedName()
                                .indexOf(GraphWalker.class.getSimpleName()) != -1);
                    return true;
                }

                @Override
                public boolean visit(FieldDeclaration node) {
                    if (!hasStaticField[0]) {
                        VariableDeclarationFragment fragment = (VariableDeclarationFragment) node.fragments()
                                .get(0);
                        hasStaticField[0] = fragment.getName().toString()
                                .equals(ClassExtension.getStaticVariableName());
                    }
                    return true;
                }

            });

            final ImportRewrite importRewrite = ImportRewrite.create(astRoot, true);

            astRoot.accept(new ASTVisitor() {
                @SuppressWarnings("unchecked")
                @Override
                public boolean visit(TypeDeclaration node) {
                    ITypeBinding binding = node.resolveBinding();

                    // Add import for class annotation
                    String[] imports = info.getClassExtension().getImports();
                    List<String> allImports = new ArrayList<String>();
                    for (int i = 0; i < imports.length; i++) {
                        if (allImports.contains(imports[i]))
                            continue;
                        allImports.add(imports[i]);
                    }
                    // Add import for methods annotation & code
                    for (int i = 0; i < info.getMethods().length; i++) {
                        imports = info.getMethods()[i].getImports();
                        for (int j = 0; j < imports.length; j++) {
                            if (allImports.contains(imports[j]))
                                continue;
                            allImports.add(imports[j]);
                        }
                    }
                    // Add import for methods annotation & code
                    for (int i = 0; i < info.getMethods().length; i++) {
                        imports = info.getMethods()[i].getStaticImports();
                        for (int j = 0; j < imports.length; j++) {
                            if (allImports.contains(imports[j]))
                                continue;
                            allImports.add(imports[j]);
                        }
                    }

                    ASTNode copiedNode = null;
                    Collections.sort(allImports);
                    Iterator<String> iterator = allImports.iterator();
                    while (iterator.hasNext()) {
                        String imp = (String) iterator.next();
                        importRewrite.addImport(imp);
                    }
                    // Add Generated annotation
                    if (!hasGeneratedAnnotation[0]) {
                        NormalAnnotation annotation = info.getClassExtension().getGeneratedClassAnnotation();
                        if (annotation != null) {
                            copiedNode = ASTNode.copySubtree(node.getAST(), annotation);
                            node.modifiers().add(0, copiedNode);
                        }
                    }
                    // Add graphwalker annotation
                    if (!hasGraphWalkerAnnotation[0]) {
                        NormalAnnotation annotation = info.getClassExtension().getGraphWalkerClassAnnotation();
                        if (annotation != null) {
                            copiedNode = ASTNode.copySubtree(node.getAST(), annotation);
                            node.modifiers().add(1, copiedNode);
                        }
                    }

                    if (!hasStaticField[0]) {
                        FieldDeclaration field = info.getClassExtension().getField();
                        if (field != null) {
                            copiedNode = ASTNode.copySubtree(node.getAST(), field);
                            node.bodyDeclarations().add(0, copiedNode);
                        }
                    }

                    List<IFile> additionals = info.getAdditionalContexts();
                    List<String> temp = new ArrayList<String>();
                    for (IFile iFile : additionals) {
                        try {
                            AbstractPostConversion converter = GraphWalkerContextManager
                                    .getDefaultGraphConversion(iFile, false);
                            temp.add(converter.getQualifiedNameForImplementation());

                        } catch (CoreException e) {
                            ResourceManager.logException(e);
                        }
                    }
                    String[] adds = new String[temp.size()];
                    temp.toArray(adds);
                    // add helper hook & test methods
                    for (int i = 0; i < info.getMethods().length; i++) {
                        try {
                            MethodDeclaration methodDeclaration = info.getMethods()[i].getMethodDeclaration(adds,
                                    node.getName().toString());
                            if (methodDeclaration == null)
                                continue;

                            copiedNode = ASTNode.copySubtree(node.getAST(), methodDeclaration);
                            node.bodyDeclarations().add(copiedNode);
                        } catch (Exception e) {
                            ResourceManager.logException(e);
                        }
                    }

                    return super.visit(node);
                }
            });

            TextEdit rewrite = astRoot.rewrite(document, compilationUnit.getJavaProject().getOptions(true));
            rewrite.apply(document);

            TextEdit rewriteImports = importRewrite.rewriteImports(new SubProgressMonitor(monitor, 1));
            rewriteImports.apply(document);

            String newSource = document.get();

            compilationUnit.getBuffer().setContents(newSource);

            compilationUnit.reconcile(ICompilationUnit.NO_AST, false, null, new SubProgressMonitor(monitor, 1));
            compilationUnit.commitWorkingCopy(false, new SubProgressMonitor(monitor, 1));
        } finally {
            compilationUnit.discardWorkingCopy();
            monitor.done();
        }

    }

    /**
     * @param file
     * @param info
     * @param monitor
     * @throws MalformedTreeException
     * @throws BadLocationException
     * @throws CoreException
     */
    @SuppressWarnings("deprecation")
    public static void addGeneratedAnnotation(IFile file, IFile graphFile, IProgressMonitor monitor)
            throws MalformedTreeException, BadLocationException, CoreException {
        ICompilationUnit compilationUnit = JavaCore.createCompilationUnitFrom(file);
        try {

            String source = compilationUnit.getSource();
            Document document = new Document(source);
            compilationUnit.becomeWorkingCopy(new SubProgressMonitor(monitor, 1));
            ASTParser parser = ASTParser.newParser(AST.JLS8);
            parser.setSource(compilationUnit);
            parser.setResolveBindings(true);
            CompilationUnit astRoot = (CompilationUnit) parser.createAST(new SubProgressMonitor(monitor, 1));
            astRoot.recordModifications();

            final ImportRewrite importRewrite = ImportRewrite.create(astRoot, true);
            importRewrite.addImport("javax.annotation.Generated");

            astRoot.accept(new ASTVisitor() {
                @SuppressWarnings("unchecked")
                @Override
                public boolean visit(TypeDeclaration node) {
                    ASTNode copiedNode = null;
                    // Add Generated annotation
                    ClassExtension ce;
                    try {
                        ce = new ClassExtension(false, false, false, false, false, false, "", "", null, false,
                                false, "", "", "", graphFile);
                        NormalAnnotation annotation = ce.getGeneratedClassAnnotation();
                        if (annotation != null) {
                            copiedNode = ASTNode.copySubtree(node.getAST(), annotation);
                            node.modifiers().add(0, copiedNode);
                        }
                    } catch (JavaModelException e) {
                        ResourceManager.logException(e);
                    }

                    return super.visit(node);
                }
            });

            TextEdit rewrite = astRoot.rewrite(document, compilationUnit.getJavaProject().getOptions(true));
            rewrite.apply(document);

            TextEdit rewriteImports = importRewrite.rewriteImports(new SubProgressMonitor(monitor, 1));
            rewriteImports.apply(document);

            String newSource = document.get();
            compilationUnit.getBuffer().setContents(newSource);

            compilationUnit.reconcile(ICompilationUnit.NO_AST, false, null, new SubProgressMonitor(monitor, 1));
            compilationUnit.commitWorkingCopy(false, new SubProgressMonitor(monitor, 1));
        } finally {
            compilationUnit.discardWorkingCopy();
            monitor.done();
        }
        // WorkbenchFacade.JDTManager.reorganizeImport(compilationUnit);
    }

    /**
     * @param project
     * @param targetSite
     * @throws CoreException
     */
    private static void organizeImports(final ICompilationUnit cu, final IWorkbenchSite targetSite)
            throws CoreException {
        Runnable job = new Runnable() {
            @Override
            public void run() {
                OrganizeImportsAction org = new OrganizeImportsAction(targetSite);
                org.run(cu);
                try {
                    if (cu.isWorkingCopy())
                        cu.commitWorkingCopy(true, new NullProgressMonitor());
                } catch (JavaModelException e) {
                    ResourceManager.logException(e);
                }
                try {
                    cu.getCorrespondingResource().refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor());
                } catch (Exception e) {
                }
            }
        };
        Display.getDefault().syncExec(job);
    }

    /**
     * @param project
     */
    public static void reorganizeImport(final ICompilationUnit cu) {

        Display.getDefault().syncExec(() -> {
            try {
                IWorkbenchWindow iww = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
                if (iww == null)
                    return;
                IPartService partService = iww.getPartService();
                if (partService == null)
                    return;
                IWorkbenchPart wp = partService.getActivePart();
                if (wp == null)
                    return;
                IWorkbenchPartSite targetSite = wp.getSite();
                if (targetSite == null)
                    return;
                organizeImports(cu, targetSite);
            } catch (Exception e) {
                ResourceManager.logException(e);
            }
        });
    }

    /**
     * Format a Unit Source Code
     * 
     * @param testInterface
     * @param monitor
     * @throws CoreException 
     */
    @SuppressWarnings("unchecked")
    public static void formatUnitSourceCode(IFile file, IProgressMonitor monitor) throws CoreException {
        @SuppressWarnings("rawtypes")
        SubMonitor subMonitor = SubMonitor.convert(monitor, 100);
        ICompilationUnit unit = JavaCore.createCompilationUnitFrom(file);
        subMonitor.split(50);
        ICompilationUnit workingCopy = unit.getWorkingCopy(monitor);

        Map options = DefaultCodeFormatterConstants.getEclipseDefaultSettings();

        options.put(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_7);
        options.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_7);
        options.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_7);

        options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_ENUM_CONSTANTS,
                DefaultCodeFormatterConstants.createAlignmentValue(true,
                        DefaultCodeFormatterConstants.WRAP_ONE_PER_LINE,
                        DefaultCodeFormatterConstants.INDENT_ON_COLUMN));

        final CodeFormatter codeFormatter = ToolFactory.createCodeFormatter(options);
        ISourceRange range = unit.getSourceRange();
        TextEdit formatEdit = codeFormatter.format(CodeFormatter.K_COMPILATION_UNIT, unit.getSource(),
                range.getOffset(), range.getLength(), 0, null);
        subMonitor.split(30);
        if (formatEdit != null /* && formatEdit.hasChildren()*/) {
            workingCopy.applyTextEdit(formatEdit, monitor);
            workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
            workingCopy.commitWorkingCopy(true, null);
            workingCopy.discardWorkingCopy();
        }
        file.refreshLocal(IResource.DEPTH_INFINITE, subMonitor);
        subMonitor.split(20);
    }

    /**
     * Return a java model
     * 
     * @return
     */
    public static IJavaModel getJavaModel() {
        return JavaCore.create(ResourceManager.getWorkspaceRoot());
    }

    /**
     * 
     * Open a default editor
     * 
     * @param resource
     * @throws FileNotFoundException
     */
    public static void openDefaultEditor(final IResource resource) {
        openEditor(resource, "org.eclipse.ui.DefaultTextEditor", null);
    }

    /**
     * 
     * Open an editor
     * 
     * @param resource
     * @throws FileNotFoundException
     */
    public static void openEditor(final IResource resource, IWorkbenchWindow aww) {
        openEditor(resource, null, aww);
    }

    /**
     * Open an editor
     * 
     * @param resource
     * @param editorId
     */
    public static void openEditor(final IResource resource, String editorId, IWorkbenchWindow aww) {
        openFileEditor(resource, editorId, aww);
    }

    /**
     * Open an editor
     * 
     * @param resource
     * @param extension
     * @param editor
     * @throws FileNotFoundException
     */
    public static void openFileEditor(final IResource resource, String editorId, IWorkbenchWindow window) {
        try {
            Display.getDefault().syncExec(() -> {
                IWorkbenchWindow[] ww = new IWorkbenchWindow[] { window };
                if (resource == null)
                    return;
                if (resource.getType() != IResource.FILE) {
                    return;
                }
                IFile file = (IFile) resource;
                if (!file.exists())
                    return;
                if (ww[0] == null) {
                    ww[0] = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
                }

                if (ww[0] == null) {
                    return;
                }
                final IWorkbenchPage activePage = ww[0].getActivePage();
                try {
                    if (editorId == null) {
                        if (file.getFileExtension().equals("java")) {
                            IDE.openEditor(activePage, file, JavaUI.ID_CU_EDITOR, true);
                        } else {
                            IDE.openEditor(activePage, file, "org.eclipse.ui.DefaultTextEditor", true);
                        }
                    } else {
                        IDE.openEditor(activePage, file, editorId, true);
                    }
                } catch (Throwable e) {
                    ResourceManager.logException(e);
                }
                BasicNewResourceWizard.selectAndReveal(resource, activePage.getWorkbenchWindow());
            });
        } catch (Exception e) {
            ResourceManager.logException(e);
        }
    }

    /**
     * Adapt the passed object to an IProject
     * 
     * @param receiver
     * @return
     */
    public static IProject toJavaProject(Object receiver) {
        IProject project = null;
        if (receiver instanceof IProject) {
            project = (IProject) receiver;
        }
        if (receiver instanceof IJavaProject) {
            project = ((IJavaProject) receiver).getProject();
        } else if (receiver instanceof IAdaptable) {
            project = (IProject) ((IAdaptable) receiver).getAdapter(IProject.class);
        }
        return project;
    }

    public static IPackageFragment getPackageFragment(IFile file) throws JavaModelException {
        IPackageFragmentRoot root1 = JDTManager.findPackageFragmentRoot(file.getProject(), file.getFullPath());
        IPath path = file.getParent().getFullPath().makeRelativeTo(root1.getPath());
        IPackageFragment pf = root1.getPackageFragment(path.toString().replace("/", "."));
        return pf;
    }

    /**
     * Return a package fragment with the passed path
     * 
     * @param project
     * @param path
     * @return
     * @throws JavaModelException
     */
    public static IPackageFragmentRoot getPackageFragmentRoot(IProject project, IPath path)
            throws JavaModelException {
        IJavaProject javaProject = JavaCore.create(project);
        IPackageFragmentRoot[] roots = javaProject.getPackageFragmentRoots();
        for (int i = 0; i < roots.length; i++) {
            if (roots[i].getPath().equals(path))
                return roots[i];
        }
        return null;
    }

    public static IPackageFragmentRoot findPackageFragmentRoot(IProject project, IPath path)
            throws JavaModelException {
        IJavaProject javaProject = JavaCore.create(project);
        IPackageFragmentRoot[] roots = javaProject.getPackageFragmentRoots();
        for (int i = 0; i < roots.length; i++) {
            if (roots[i].getPath().isPrefixOf(path))
                return roots[i];
        }
        return null;
    }

    public static IPath removePackageFragmentRoot(IProject project, IPath path) throws JavaModelException {
        IJavaProject javaProject = JavaCore.create(project);
        IPackageFragmentRoot[] roots = javaProject.getPackageFragmentRoots();
        for (int i = 0; i < roots.length; i++) {
            if (roots[i].getPath().isPrefixOf(path))
                return path.makeRelativeTo(roots[i].getPath());
        }
        return null;
    }

    public static boolean validateClassName(String name) {
        String temp = name + ".java";
        IStatus status = JavaConventions.validateCompilationUnitName(temp, JavaCore.VERSION_1_8,
                JavaCore.VERSION_1_8);
        boolean b = (status.getCode() == IStatus.OK);
        return b;
    }
}