de.loskutov.eclipse.jdepend.views.PackageTreeView.java Source code

Java tutorial

Introduction

Here is the source code for de.loskutov.eclipse.jdepend.views.PackageTreeView.java

Source

/*******************************************************************************
 * Copyright (c) 2010 Andrey Loskutov.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * Contributor:  Andrey Loskutov - initial API and implementation
 *******************************************************************************/

package de.loskutov.eclipse.jdepend.views;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import jdepend.framework.ClassFileParser;
import jdepend.framework.JDepend;
import jdepend.framework.JavaClass;
import jdepend.framework.JavaPackage;
import jdepend.framework.PackageComparator;
import jdepend.framework.PackageFilter;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jdt.ui.actions.OpenJavaPerspectiveAction;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseTrackAdapter;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.console.IConsoleConstants;
import org.eclipse.ui.part.ISetSelectionTarget;
import org.eclipse.ui.part.IShowInSource;
import org.eclipse.ui.part.ShowInContext;
import org.eclipse.ui.part.ViewPart;

import de.loskutov.eclipse.jdepend.JDepend4EclipsePlugin;
import de.loskutov.eclipse.jdepend.JDependConstants;

/**
 *
 */
public class PackageTreeView extends ViewPart implements IShowInSource {
    protected TreeViewer viewer;
    protected ViewContentProvider treeContent;
    protected Action actionOpenJava;
    protected Action actionRefresh;
    protected Action actionConsole;
    protected Action actionSave;
    protected List<JavaPackage> analyzedPackages;
    protected ToolTipHandler tooltip;
    protected TreeSelectionListener treeSelectionHandler;

    /** key is Resource, value is treeObject*/
    protected HashMap<IResource, TreeObject> resourceMap;

    /** The view's identifier */
    public static final String ID = JDepend4EclipsePlugin.ID + ".views.PackageTreeView"; //$NON-NLS-1$

    final class TreeSelectionListener implements ISelectionChangedListener, ISelectionProvider {

        private TreeObject lastSelection;
        private final List<ISelectionChangedListener> listeners;

        public TreeSelectionListener() {
            super();
            listeners = new ArrayList<ISelectionChangedListener>();
        }

        @Override
        public void selectionChanged(SelectionChangedEvent event) {
            IStructuredSelection selection = (IStructuredSelection) event.getSelection();

            ArrayList<IResource> al = new ArrayList<IResource>();
            Iterator<?> iter = selection.iterator();
            IResource[] resources;
            while (iter.hasNext()) {
                TreeObject o = (TreeObject) iter.next();
                if (o.isLeaf()) {
                    TreeLeaf tleaf = (TreeLeaf) o;
                    if (tleaf.getIResource() != null) {
                        al.add(tleaf.getIResource());
                    }
                } else {
                    TreeFolder tfolder = (TreeFolder) o;
                    resources = tfolder.getIResources();
                    for (int i = 0; i < resources.length; i++) {
                        if (!al.contains(resources[i])) {
                            al.add(resources[i]);
                        }
                    }
                }
            }
            resources = al.toArray(new IResource[al.size()]);

            updateDependencyView(analyzedPackages, resources);
            updateMetricsView(analyzedPackages, resources);
            boolean singleSelection = selection.size() == 1;
            actionOpenJava.setEnabled(singleSelection);
            IStatusLineManager manager = getViewSite().getActionBars().getStatusLineManager();
            if (singleSelection) {
                lastSelection = (TreeObject) selection.getFirstElement();
                if (lastSelection.isLeaf()) {
                    manager.setMessage(
                            lastSelection.getName() + " -> " + ((TreeLeaf) lastSelection).getByteCodePath());
                } else {
                    manager.setMessage(lastSelection.getPackageName() + " -> " + lastSelection.getIResource());
                }
            } else {
                lastSelection = null;
                manager.setMessage(selection.size() + " elements selected");
            }
            try {
                // to select this view again, if selection was lost
                getSite().getPage().showView(ID);
            } catch (PartInitException e) {
                JDepend4EclipsePlugin.handle(e);
            }
            fireSelectionChanged();
        }

        public void fireSelectionChanged() {
            ISelection selection = getSelection();
            SelectionChangedEvent event = new SelectionChangedEvent(this, selection);
            for (int i = 0; i < listeners.size(); i++) {
                listeners.get(i).selectionChanged(event);
            }
        }

        @Override
        public void addSelectionChangedListener(ISelectionChangedListener listener) {
            if (listener != null && !listeners.contains(listener)) {
                listeners.add(listener);
            }
        }

        @Override
        public ISelection getSelection() {
            if (lastSelection == null) {
                return StructuredSelection.EMPTY;
            }
            Object selectedObj;
            if (lastSelection.isLeaf()) {
                TreeLeaf child = (TreeLeaf) lastSelection;
                selectedObj = child.getIJavaElement();
            } else {
                TreeFolder folder = (TreeFolder) lastSelection;
                selectedObj = folder.getIJavaElement();
            }
            if (selectedObj == null) {
                return StructuredSelection.EMPTY;
            }
            return new StructuredSelection(selectedObj);
        }

        @Override
        public void removeSelectionChangedListener(ISelectionChangedListener listener) {
            listeners.remove(listener);
        }

        @Override
        public void setSelection(ISelection selection) {
            // noop
        }
    }

    private TreeFolder getRoot() {
        return (TreeFolder) viewer.getInput();
    }

    private void setRoot(TreeFolder root) {
        viewer.setInput(root);
    }

    final class ViewContentProvider implements IStructuredContentProvider, ITreeContentProvider {

        @Override
        public void inputChanged(Viewer v, Object oldInput, Object newInput) {
            // ignored
        }

        @Override
        public void dispose() {
            // ignored
        }

        @Override
        public Object[] getElements(Object parent) {
            if (getRoot() == parent) {
                return getChildren(getRoot());
            }
            return getChildren(parent);
        }

        @Override
        public Object getParent(Object child) {
            if (child instanceof TreeObject) {
                return ((TreeObject) child).getParent();
            }
            return null;
        }

        @Override
        public Object[] getChildren(Object parent) {
            if (parent instanceof TreeFolder) {
                return ((TreeFolder) parent).getChildren();
            }
            return new Object[0];
        }

        @Override
        public boolean hasChildren(Object parent) {
            if (parent instanceof TreeFolder) {
                return ((TreeFolder) parent).hasChildren();
            }
            return false;
        }

        /**
         * @return result of JDepend run, never null
         */
        public List<JavaPackage> analyze(TreeFolder newRoot, IResource[] resource) {
            resourceMap.clear();
            if (resource == null) {
                return new ArrayList<JavaPackage>();
            }

            JDepend jdepend = JDepend4EclipsePlugin.getJDependInstance();
            PackageFilter filter = jdepend.getFilter();

            for (int i = 0; i < resource.length; i++) {
                TreeFolder[] tp = createTree(resource[i], filter);
                for (int j = 0; j < tp.length; j++) {
                    // tree object check if child is exist
                    if (tp[j].hasChildren()) {
                        newRoot.addChild(tp[j]);
                    }
                }
            }
            List<JavaPackage> packages = runJDepend(jdepend, newRoot.getChildren());
            // update cycle info
            // set cycle to true, if one of packages is under the founded tree root
            for (int j = 0; j < packages.size(); j++) {
                JavaPackage jp = packages.get(j);
                boolean cycle = jp.containsCycle();
                if (cycle) {
                    if (jp.getName().length() == 0) {
                        newRoot.setContainsCycle(cycle);
                        continue;
                    }
                    TreeObject child = newRoot.findChild(jp);
                    if (child != null && !child.isLeaf()) {
                        ((TreeFolder) child).setContainsCycle(cycle);
                    }
                }
            }
            return packages;
        }

        /**
         * Create object tree and initialize map with new IResource->TreeObject
         * pairs.
         * @param resource
         * @return TreeParent
         */
        private TreeFolder[] createTree(IResource resource, PackageFilter filter) {
            if (resource.getType() != IResource.FOLDER) {
                return new TreeFolder[0];
            }
            IContainer folder = (IContainer) resource;

            IResource[] resources = null;

            try {
                resources = folder.members();
            } catch (CoreException e) {
                JDepend4EclipsePlugin.handle(e);
            }

            if (resources == null || resources.length == 0) {
                return new TreeFolder[0];
            }

            boolean isPackageRoot = false;
            IJavaElement javaElement = JavaCore.create(folder);

            if (javaElement != null) {
                try {
                    isPackageRoot = TreeObject.isPackageRoot(javaElement.getJavaProject(), folder);
                } catch (JavaModelException e) {
                    // too many errors on 3.3...
                    //                    JDepend4EclipsePlugin.handle(e);
                }
            } else {
                isPackageRoot = false;
            }

            if (!isPackageRoot && resourceMap.containsKey(folder)) {
                // @todo System.out.println("OOOO!! map contains: " + folder);
                return new TreeFolder[0];
            }

            TreeFolder tree = (TreeFolder) resourceMap.get(folder);
            ArrayList<TreeFolder> treeRoots = null;
            //add parent package, if not exist
            if (tree == null) {
                tree = new TreeFolder(javaElement);
                if (filter.accept(tree.getPackageName())) {
                    treeRoots = new ArrayList<TreeFolder>();
                    treeRoots.add(tree);
                    resourceMap.put(folder, tree);
                } else {
                    return new TreeFolder[0];
                }
            }
            if (treeRoots == null) {
                return new TreeFolder[0];
            }
            TreeFolder[] results;
            TreeLeaf tleaf;
            IJavaElement javaChild;
            String tname;
            for (int i = 0; i < resources.length; i++) {
                if (resources[i].getType() == IResource.FOLDER) {
                    results = createTree(resources[i], filter);
                    for (int j = 0; j < results.length; j++) {
                        if (!treeRoots.contains(results[j])) {
                            treeRoots.add(results[j]);
                        }
                    }
                } else {
                    tname = resources[i].getName();
                    if (tname.endsWith(".java")) { //$NON-NLS-1$
                        javaChild = JavaCore.create(resources[i]);
                        if (javaChild == null) {
                            continue;
                        }
                        tleaf = new TreeLeaf(javaChild);
                        resourceMap.put(resources[i], tleaf);
                        tree.addChild(tleaf);
                    } else if (tname.endsWith(".class")) { //$NON-NLS-1$
                        tleaf = new TreeLeaf(resources[i]);
                        resourceMap.put(resources[i], tleaf);
                        tree.addChild(tleaf);
                    }
                }
            }

            return treeRoots.toArray(new TreeFolder[treeRoots.size()]);
        }

    }

    static final class ViewLabelProvider extends LabelProvider {

        @Override
        public String getText(Object obj) {
            return obj.toString();
        }

        @Override
        public Image getImage(Object obj) {
            String imageKey = org.eclipse.jdt.ui.ISharedImages.IMG_OBJS_CLASS;
            if (obj instanceof TreeFolder) {
                TreeFolder tp = (TreeFolder) obj;
                if (tp.hasCycle()) {
                    return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJS_WARN_TSK);
                }
                imageKey = org.eclipse.jdt.ui.ISharedImages.IMG_OBJS_PACKAGE;
            }
            return JavaUI.getSharedImages().getImage(imageKey);
        }
    }

    static final class NameSorter extends ViewerSorter {
        // exist here because in 2.x Eclipse the parent class is abstract
    }

    /**
     * Emulated tooltip handler
     * Notice that we could display anything in a tooltip besides text and images.
     */
    private final class ToolTipHandler {
        protected Shell tipShell;
        protected Label tipLabelImage, tipLabelText;
        protected Point tipPosition; // the position being hovered over

        /**
         * Creates a new tooltip handler
         *
         * @param parent the parent Shell
         */
        public ToolTipHandler(Shell parent) {
            final Display display = parent.getDisplay();

            tipShell = new Shell(parent, SWT.ON_TOP);
            GridLayout gridLayout = new GridLayout();
            gridLayout.numColumns = 2;
            gridLayout.marginWidth = 2;
            gridLayout.marginHeight = 2;
            tipShell.setLayout(gridLayout);

            tipShell.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));

            tipLabelImage = new Label(tipShell, SWT.NONE);
            tipLabelImage.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND));
            tipLabelImage.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
            tipLabelImage.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_CENTER));

            tipLabelText = new Label(tipShell, SWT.NONE);
            tipLabelText.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND));
            tipLabelText.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
            tipLabelText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_CENTER));
        }

        void dispose() {
            if (tipShell != null) {
                tipShell.dispose();
                tipShell = null;
            }
        }

        /**
         * Enables customized hover help for a specified control
         *
         * @control the control on which to enable hoverhelp
         */
        public void activateHoverHelp(final Control control) {
            /*
             * Get out of the way if we attempt to activate the control underneath the tooltip
             */
            control.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseDown(MouseEvent e) {
                    if (tipShell.isVisible()) {
                        tipShell.setVisible(false);
                    }
                }
            });

            /*
             * Trap hover events to pop-up tooltip
             */
            control.addMouseTrackListener(new MouseTrackAdapter() {
                @Override
                public void mouseExit(MouseEvent e) {
                    if (tipShell.isVisible()) {
                        tipShell.setVisible(false);
                    }
                }

                @Override
                public void mouseHover(MouseEvent event) {
                    Point pt = new Point(event.x, event.y);

                    TreeItem ti = viewer.getTree().getItem(pt);

                    StringBuffer sb = new StringBuffer();
                    if (ti == null || ti.getText() == null) {
                        if (analyzedPackages.isEmpty()) {
                            sb.append(JDepend4EclipsePlugin.getResourceString("EmptyToolTipHint"));
                        } else {
                            return;
                        }
                    }

                    getTreeText(sb, ti);

                    if (sb.length() == 0) {
                        tipShell.setVisible(false);
                        return;
                    }

                    tipPosition = control.toDisplay(pt);

                    tipLabelText.setText(sb.toString());
                    //tipLabelImage.setImage(image); // accepts null
                    tipShell.pack();
                    setHoverLocation(tipShell, tipPosition);
                    tipShell.setVisible(true);
                }

                private void getTreeText(StringBuffer sb, TreeItem ti) {
                    if (ti == null || ti.getData() == null) {
                        return;
                    }
                    sb.append(ti.getText());
                    TreeObject to = (TreeObject) ti.getData();

                    if (!to.isLeaf()) {
                        try {
                            ArrayList<String> paths = ((TreeFolder) to).getClassesLocation();
                            for (int i = 0; i < paths.size(); i++) {
                                sb.append('\n').append(paths.get(i));
                            }
                        } catch (JavaModelException e) {
                            JDepend4EclipsePlugin.handle(e);
                        }
                    } else {
                        sb.append('\n').append(((TreeLeaf) to).getByteCodePath());
                    }
                }
            });

        }

        /**
         * Sets the location for a hovering shell
         * @param shell the object that is to hover
         * @param position the position of a widget to hover over
         */
        protected void setHoverLocation(Shell shell, Point position) {
            Rectangle displayBounds = shell.getDisplay().getBounds();
            Rectangle shellBounds = shell.getBounds();
            shellBounds.x = Math.max(Math.min(position.x + 8, displayBounds.width - shellBounds.width), 0);
            shellBounds.y = Math.max(Math.min(position.y + 16, displayBounds.height - shellBounds.height), 0);
            shell.setBounds(shellBounds);
        }
    }

    /**
     * The constructor.
     */
    public PackageTreeView() {
        super();
        resourceMap = new HashMap<IResource, TreeObject>(29);
        analyzedPackages = new ArrayList<JavaPackage>();
    }

    /**
     * @param treeObjects not null
     * @return non null list
     */
    protected List<JavaPackage> runJDepend(JDepend jdepend, TreeObject[] treeObjects) {
        for (int i = 0; i < treeObjects.length; i++) {
            try {
                if (!treeObjects[i].isLeaf()) {
                    TreeFolder folder = (TreeFolder) treeObjects[i];
                    // add roots
                    ArrayList<String> dirs = folder.getClassesLocation();
                    for (int j = 0; j < dirs.size(); j++) {
                        jdepend.addDirectory("" + dirs.get(j)); //$NON-NLS-1$
                    }
                }
            } catch (Exception e) {
                // if directory doesn't exist, may be project need to be rebuild
                JDepend4EclipsePlugin.handle(e);
            }
        }

        final List<?> packages = new ArrayList<Object>(jdepend.analyze());
        List<JavaPackage> filteredPackages = filterPackages(packages, jdepend);
        Collections.sort(filteredPackages, new PackageComparator(PackageComparator.byName()));
        return filteredPackages;
    }

    public void updateUI(TreeFolder newRoot, IResource[] folder, List<JavaPackage> packages) {
        analyzedPackages = packages;
        boolean hasContent = !packages.isEmpty();
        actionSave.setEnabled(hasContent);
        actionConsole.setEnabled(hasContent);
        actionOpenJava.setEnabled(hasContent);
        actionRefresh.setEnabled(hasContent);
        viewer.setInput(newRoot);
        // actualize tree
        // should select elements
        viewer.setSelection(new StructuredSelection(getRoot().getChildren()), true);
        JDependConsole.showConsole(packages);
        updateDependencyView(packages, folder);
        updateMetricsView(packages, folder);
    }

    protected void updateMetricsView(List<JavaPackage> packages, IResource[] folder) {
        if (packages == null) {
            return;
        }
        JavaPackage tempPack1;
        List<JavaPackage> selPackages = new ArrayList<JavaPackage>();
        // find corresponding packages
        for (int i = 0; i < folder.length; i++) {
            TreeObject to = resourceMap.get(folder[i]);
            if (to == null) {
                continue;
            }
            if (!to.isLeaf()) {
                // find packages, matching to folder
                String tempFolderName = to.getPackageName();
                for (int j = 0; j < packages.size(); j++) {
                    tempPack1 = packages.get(j);
                    if (tempFolderName.equals(tempPack1.getName())
                            || tempFolderName.endsWith("." + tempPack1.getName())) { //$NON-NLS-1$

                        selPackages.add(tempPack1);
                    }
                }
            }
        }
        if (folder.length > 0 && selPackages.isEmpty() && folder[0] instanceof IFolder) {
            selPackages = packages;
        }

        MetricsView metricsView = (MetricsView) getView(MetricsView.ID);
        if (metricsView != null) {
            metricsView.setInput(selPackages.toArray(new JavaPackage[0]));
        }
    }

    private static List<JavaPackage> filterPackages(List<?> packages, JDepend jdepend) {
        ArrayList<JavaPackage> filteredPackages = new ArrayList<JavaPackage>();
        PackageFilter filter = jdepend.getFilter();
        for (int i = 0; i < packages.size(); i++) {
            JavaPackage tempPackage = (JavaPackage) packages.get(i);
            if (filter.accept(tempPackage.getName())) {
                filteredPackages.add(tempPackage);
            }
        }
        return filteredPackages;
    }

    protected List<JavaPackage> updateDependencyView(List<JavaPackage> packages, IResource[] folder) {

        TreeObject to = null;
        List<JavaClass> selClasses = new ArrayList<JavaClass>();
        ClassFileParser classParser = JDepend4EclipsePlugin.getJDependClassFileParserInstance();

        JDepend jdepend = JDepend4EclipsePlugin.getJDependInstance();
        PackageFilter filter = jdepend.getFilter();
        JavaPackage root = new JavaPackage("root"); //$NON-NLS-1$
        List<JavaPackage> selPackages = new ArrayList<JavaPackage>();

        JavaPackage tempPack1;
        JavaPackage tempPack2;

        String tempName;
        JavaClass tempClass = null;
        // find corresponding packages
        for (int i = 0; i < folder.length; i++) {
            to = resourceMap.get(folder[i]);
            if (to == null) {
                continue;
            }
            if (!to.isLeaf()) {
                // find packages, matching to folder
                String tempFolderName = to.getPackageName();
                for (int j = 0; j < packages.size(); j++) {
                    tempPack1 = packages.get(j);
                    if (tempFolderName.equals(tempPack1.getName())
                            || tempFolderName.endsWith("." + tempPack1.getName())) { //$NON-NLS-1$
                        selPackages.add(tempPack1);
                    }
                }
            } else {
                try {
                    tempName = ((TreeLeaf) to).getByteCodePath();
                    tempClass = classParser.parse(new File(tempName));
                    if (tempClass != null) {
                        selClasses.add(tempClass);
                    }
                } catch (IOException e) {
                    // exception: if class file doesn't exist, may be project must be rebuilded!
                    JDepend4EclipsePlugin.handle(e);
                }
            }
        }

        List<?> aff;
        List<?> eff;

        if (folder.length > 0 && selPackages.isEmpty() && folder[0] instanceof IFolder) {
            selPackages = packages;
        }

        for (int i = 0; i < selPackages.size(); i++) {
            tempPack1 = selPackages.get(i);

            aff = tempPack1.getAfferents();
            for (int j = 0; j < aff.size(); j++) {
                tempPack2 = (JavaPackage) aff.get(j);
                if (filter.accept(tempPack2.getName())) {
                    root.addAfferent(tempPack2);
                }
            }

            eff = tempPack1.getEfferents();
            for (int j = 0; j < eff.size(); j++) {
                tempPack2 = (JavaPackage) eff.get(j);
                if (filter.accept(tempPack2.getName())) {
                    root.addEfferent(tempPack2);
                }
            }
        }

        ArrayList<JavaPackage> imported = new ArrayList<JavaPackage>();
        for (int i = 0; i < selClasses.size(); i++) {
            tempClass = selClasses.get(i);

            List<?> effP = new ArrayList<Object>(tempClass.getImportedPackages());
            for (int j = 0; j < effP.size(); j++) {
                tempPack2 = (JavaPackage) effP.get(j);
                if (!imported.contains(tempPack2) && filter.accept(tempPack2.getName())) {
                    imported.add(tempPack2);
                }
            }
        }

        if (selClasses.size() > 0) {
            for (int j = 0; j < imported.size(); j++) {
                tempName = imported.get(j).getName();
                for (int i = 0; i < packages.size(); i++) {
                    tempPack1 = packages.get(i);
                    if (tempPack1.getName().equals(tempName)) {
                        //System.out.println("add efferent from class:" + tempPack1.getName());
                        root.addEfferent(tempPack1);
                        break;
                    }
                }
            }
        }

        ArrayList<Object> cl = new ArrayList<Object>();

        IPreferenceStore settings = JDepend4EclipsePlugin.getDefault().getPreferenceStore();
        if (settings.getBoolean(JDependConstants.PREF_USE_ALL_CYCLES_SEARCH)) {
            root.collectAllCycles(cl);
        } else {
            root.collectCycle(cl);
        }

        // root is fiction
        if (cl.contains(root)) {
            cl.remove(root);
            if (cl.contains(root)) {
                cl.remove(root);
            }
        }

        aff = root.getAfferents();
        eff = root.getEfferents();

        PackageComparator pc = new PackageComparator(PackageComparator.byName());
        Collections.sort(aff, pc);
        Collections.sort(eff, pc);
        Collections.sort(cl, pc);

        // clear multiple packages in cycle list
        ArrayList<Object> cl2 = new ArrayList<Object>();
        Object tempObj;
        for (int i = 0; i < cl.size(); i++) {
            tempObj = cl.get(i);
            if (!cl2.contains(tempObj)) {
                cl2.add(tempObj);
            }
        }
        cl.clear();
        cl = cl2;

        DependencyView dependView = (DependencyView) getView(DependencyView.ID);
        if (dependView != null) {
            if (analyzedPackages.isEmpty()) {
                dependView.setTooltipText(JDepend4EclipsePlugin.getResourceString("EmptyToolTipHint"));
            } else {
                dependView.setTooltipText(null);
            }
            dependView.getAffViewer().setInput(aff.toArray(new JavaPackage[0]));
            dependView.getEffViewer().setInput(eff.toArray(new JavaPackage[0]));
            dependView.getCycleViewer().setInput(cl.toArray(new JavaPackage[0]));
            dependView.getSelViewer().setInput(selPackages.toArray(new JavaPackage[0]));
        }
        return selPackages;
    }

    private IViewPart getView(String id) {
        IViewPart part = getSite().getPage().findView(id);
        if (part == null) {
            try {
                part = getSite().getPage().showView(id);
            } catch (PartInitException e) {
                JDepend4EclipsePlugin.handle(e);
            }
        }
        return part;
    }

    /**
     * This is a callback that will allow us
     * to create the viewer and initialize it.
     */
    @Override
    public void createPartControl(Composite parent) {

        tooltip = new ToolTipHandler(parent.getShell());
        viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
        treeContent = new ViewContentProvider();
        viewer.setContentProvider(treeContent);
        viewer.setLabelProvider(new ViewLabelProvider());
        viewer.setSorter(new NameSorter());
        setRoot(new TreeFolder());
        treeSelectionHandler = new TreeSelectionListener();
        viewer.addSelectionChangedListener(treeSelectionHandler);
        getSite().setSelectionProvider(treeSelectionHandler);

        makeActions();
        hookContextMenu();
        hookDoubleClickAction();
        contributeToActionBars();
        tooltip.activateHoverHelp(viewer.getTree());
        PlatformUI.getWorkbench().getHelpSystem().setHelp(viewer.getControl(),
                "de.loskutov.eclipse.jdepend.jdepend"); //$NON-NLS-1$
    }

    private void hookContextMenu() {
        MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$
        menuMgr.setRemoveAllWhenShown(true);
        menuMgr.addMenuListener(new IMenuListener() {
            @Override
            public void menuAboutToShow(IMenuManager manager) {
                fillContextMenu(manager);
            }
        });
        Menu menu = menuMgr.createContextMenu(viewer.getControl());
        viewer.getControl().setMenu(menu);
        getSite().registerContextMenu(menuMgr, viewer);
    }

    private void contributeToActionBars() {
        IActionBars bars = getViewSite().getActionBars();
        fillLocalPullDown(bars.getMenuManager());
        fillLocalToolBar(bars.getToolBarManager());
    }

    private void fillLocalPullDown(IMenuManager manager) {
        manager.add(actionRefresh);
        manager.add(new Separator());
        manager.add(actionConsole);
        manager.add(actionSave);
    }

    protected void fillContextMenu(IMenuManager manager) {
        if (getSelection().size() == 1) {
            manager.add(actionOpenJava);
        }
        // Other plug-ins can contribute there actions here
        manager.add(new Separator("additions")); //$NON-NLS-1$
    }

    private void fillLocalToolBar(IToolBarManager manager) {
        manager.add(actionRefresh);
        manager.add(actionOpenJava);
        manager.add(new Separator());
        manager.add(actionConsole);
        manager.add(actionSave);
    }

    private void makeActions() {
        final IPreferenceStore prefs = JDepend4EclipsePlugin.getDefault().getPreferenceStore();
        actionOpenJava = new Action() {
            @Override
            public void run() {

                TreeObject to = getSelectedElement();
                if (to == null) {
                    return;
                }

                if (!to.isLeaf()) {
                    IJavaElement[] javaElements = ((TreeFolder) to).getIJavaElements().toArray(new IJavaElement[0]);
                    Action oa = new OpenJavaPerspectiveAction();
                    oa.run();

                    IViewPart part = getView(JavaUI.ID_PACKAGES);
                    if (part instanceof ISetSelectionTarget) {
                        ISetSelectionTarget target = (ISetSelectionTarget) part;
                        target.selectReveal(new StructuredSelection(javaElements));
                    }
                    return;
                }
                IJavaElement javaElement = ((TreeLeaf) to).getIJavaElement();
                if (javaElement == null) {
                    return;
                }
                IEditorPart javaEditor = null;
                try {
                    Action oa = new OpenJavaPerspectiveAction();
                    oa.run();
                    javaEditor = JavaUI.openInEditor(javaElement);
                    JavaUI.revealInEditor(javaEditor, javaElement);
                } catch (PartInitException e) {
                    JDepend4EclipsePlugin.handle(e);
                } catch (JavaModelException e) {
                    JDepend4EclipsePlugin.handle(e);
                }
            }
        };
        actionOpenJava.setText(JDepend4EclipsePlugin.getResourceString("PackageTreeView.Switch_to_package_view")); //$NON-NLS-1$
        actionOpenJava.setToolTipText(
                JDepend4EclipsePlugin.getResourceString("PackageTreeView.Change_to_Java_Perspective")); //$NON-NLS-1$
        actionOpenJava.setImageDescriptor(
                JavaUI.getSharedImages().getImageDescriptor(org.eclipse.jdt.ui.ISharedImages.IMG_OBJS_PACKAGE));
        actionOpenJava.setEnabled(false);

        actionRefresh = new Action() {
            @Override
            public void run() {
                TreeObject[] childs = getRoot().getChildren();
                ArrayList<IResource> al = new ArrayList<IResource>();
                IResource[] roots;
                for (int i = 0; i < childs.length; i++) {
                    if (childs[i].isLeaf()) {
                        al.add(((TreeLeaf) childs[i]).getIResource());
                    } else {
                        roots = ((TreeFolder) childs[i]).getIResources();
                        for (int j = 0; j < roots.length; j++) {
                            if (!al.contains(roots[j])) {
                                al.add(roots[j]);
                            }
                        }
                    }
                }
                IResource[] dirs = al.toArray(new IResource[al.size()]);
                runJDependJob(dirs);
            }
        };
        actionRefresh.setText(JDepend4EclipsePlugin.getResourceString("PackageTreeView.Refresh_view")); //$NON-NLS-1$
        actionRefresh.setToolTipText(JDepend4EclipsePlugin.getResourceString("PackageTreeView.Run_JDepend_again")); //$NON-NLS-1$
        actionRefresh.setImageDescriptor(
                JDepend4EclipsePlugin.getDefault().getImageDescriptor(JDepend4EclipsePlugin.IMG_REFRESH));
        actionRefresh.setEnabled(false);

        actionConsole = new Action("Show JDepend output", IAction.AS_CHECK_BOX) {
            @Override
            public void run() {
                if (isChecked()) {
                    prefs.setValue(JDependConstants.PREF_OUTPUT_NIX, false);
                    JDependConsole.showConsole(analyzedPackages);
                } else {
                    prefs.setValue(JDependConstants.PREF_OUTPUT_NIX, true);
                    IViewPart part = getSite().getPage().findView(IConsoleConstants.ID_CONSOLE_VIEW);
                    if (part != null) {
                        getSite().getPage().hideView(part);
                    }
                }
            }
        };
        actionConsole.setToolTipText("Show JDepend output"); //$NON-NLS-1$
        actionConsole.setImageDescriptor(JDepend4EclipsePlugin.getDefault().getImageDescriptor("console.gif"));
        actionConsole.setEnabled(false);
        actionConsole.setChecked(!prefs.getBoolean(JDependConstants.PREF_OUTPUT_NIX));

        actionSave = new SaveToFileAction("Save JDepend output") {
            @Override
            protected void write(FileWriter fw) {
                boolean asXml = prefs.getBoolean(JDependConstants.SAVE_AS_XML);
                jdepend.textui.JDepend jdep;
                if (asXml) {
                    jdep = new jdepend.xmlui.JDepend(new PrintWriter(fw)) {
                        @Override
                        protected ArrayList<JavaPackage> getPackagesList() {
                            return (ArrayList<JavaPackage>) analyzedPackages;
                        }
                    };
                } else {
                    jdep = new jdepend.textui.JDepend(new PrintWriter(fw)) {
                        @Override
                        protected ArrayList<JavaPackage> getPackagesList() {
                            return (ArrayList<JavaPackage>) analyzedPackages;
                        }
                    };
                }
                jdep.analyze();
            }
        };
        actionSave.setToolTipText("Save JDepend output"); //$NON-NLS-1$
        actionSave.setImageDescriptor(JDepend4EclipsePlugin.getDefault().getImageDescriptor("saveToFile.gif"));
        actionSave.setEnabled(false);
    }

    protected TreeObject getSelectedElement() {
        ISelection selection = viewer.getSelection();
        Object obj = ((IStructuredSelection) selection).getFirstElement();
        if (!(obj instanceof TreeObject)) {
            return null;
        }
        return (TreeObject) obj;
    }

    private void hookDoubleClickAction() {
        viewer.addDoubleClickListener(new IDoubleClickListener() {
            @Override
            public void doubleClick(DoubleClickEvent event) {
                actionOpenJava.run();
            }
        });
    }

    @Override
    public void dispose() {
        getSite().setSelectionProvider(null);
        tooltip.dispose();
        viewer.getTree().dispose();
        viewer = null;
        analyzedPackages = null;
        resourceMap = null;
        super.dispose();
    }

    /**
     * Passing the focus request to the viewer's control.
     */
    @Override
    public void setFocus() {
        viewer.getControl().setFocus();
    }

    /** Makes the view visible in the active perspective. If there
     * isn't a view registered <code>null</code> is returned.
     * Otherwise the opened view part is returned.
     */
    public static PackageTreeView openInActivePerspective() {
        try {
            return (PackageTreeView) JDepend4EclipsePlugin.getActivePage().showView(PackageTreeView.ID);
        } catch (Exception pe) {
            return null;
        }
    }

    @Override
    public ShowInContext getShowInContext() {
        IStructuredSelection selection = getSelection();
        if (selection.size() != 1) {
            return null;
        }
        TreeObject firstElement = (TreeObject) selection.getFirstElement();
        if (firstElement.getIResource() != null) {
            return new ShowInContext(null, new StructuredSelection(firstElement.getIResource()));
        }
        return null;
    }

    @Override
    public Object getAdapter(Class adapter) {
        if (adapter.equals(ISelectionProvider.class)) {
            return treeSelectionHandler;
        }
        if (adapter == IShowInSource.class) {
            return this;
        }
        return super.getAdapter(adapter);
    }

    private IStructuredSelection getSelection() {
        return ((IStructuredSelection) viewer.getSelection());
    }

    /**
     * Convenience method for running an operation with progress and
     * error feedback.
     */
    public final void runJDependJob(final IResource[] resources) {
        Job job = new Job("JDepend analysis") {
            @Override
            protected IStatus run(IProgressMonitor monitor) {
                try {
                    final TreeFolder newRoot = new TreeFolder();
                    final List<JavaPackage> packages = treeContent.analyze(newRoot, resources);
                    PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
                        @Override
                        public void run() {
                            updateUI(newRoot, resources, packages);

                        }
                    });
                } catch (Exception e) {
                    JDepend4EclipsePlugin.handle(e);
                    monitor.setCanceled(true);
                }
                return monitor.isCanceled() ? Status.CANCEL_STATUS : Status.OK_STATUS;
            }
        };
        job.setUser(true);
        job.setPriority(Job.INTERACTIVE);
        job.schedule();
    }
}