Home > Eclipse development, Software Development, Testing > Writing an Eclipse Plug-in (Part 13): Common Navigator: Adding Tests

Writing an Eclipse Plug-in (Part 13): Common Navigator: Adding Tests


And now it is time for the mundane.

While I firmly believe in test-driven development I do not believe in test-driven learning; that means that while tests are great to insure that your software works as advertised (or at least as much of it as you could think of), testing is not a good way to learn implementation. I know the physicists out there will disagree with me, but learning the black box behavior of a system is quite different than learning how to build the actual clockwork mechanism that makes something go.

With that said, at some point we do need to refactor the code and we can’t safely refactor the code without some tests to prove that our refactoring hasn’t broken anything.

We have been coding without a net in the interest of keeping the learning as noise-free as possible. Now we return to the part of the coding that we would normally do as we developed the code.

In other words, time for code hygiene.

What to do

  1. Create a plug-in test project for the navigator
    1. Enter the following:
      • Project name: customnavigator.test
      • Eclipse version: 3.5
    2. Click Next
    3. Enter the following:
      • Version: 1.0.1.3 [Actually anything you want]
      • Name: Custom Navigator Test
    4. Click Finish
  2. Clean up MANIFEST.MF
    1. Click the MANIFEST.MF tab
    2. Move the cursor to line 1 and Press Ctrl+1
    3. Select Add Missing Packages
    4. Move the cursor to line 3 and Press Ctrl+1
    5. Select Externalize the Bundle-Name header
    6. Save the file
  3. Dependencies tab: Add org.junit4
  4. Dependencies tab: Add org.eclipse.core.resources
  5. Copy easymock.jar to your project. Add a lib folder under your test project folder, copy the easymock.jar file and add it to Runtime –> Classpath
  6. Open the customnavigator.test Properties dialog. In the Project References element put a check mark next to the customnavigator project. Click Finish.
  7. Implement customnavigator.navigator.ContentProviderTest in the customnavigator.test project
    1. Create a new JUnit class named customnavigator.navigator.ContentProviderTest
    2. Test getParent()
    3. Test getChildren()
    4. Test hasChildren()

One of the tests, getChildren(), pointed out a bug: when a project came in, custom or not, it was being wrapped and saved in the _wrapperCache. The only projects that should be in the wrapper cache are projects of type CustomProjectParents. While not fatal, it was still wrong. Not a bad catch.

Here is the corrected code.

ContentProvider.java

    private Object[] createCustomProjectParents(IProject[] projects) {
        Object[] result = null;
        
        List<Object> list = new ArrayList<Object>();
        for (int i = 0; i < projects.length; i++) {
            Object customProjectParent = _wrapperCache.get(projects[i].getName()); 
            if (customProjectParent == null) {
                customProjectParent = createCustomProjectParent(projects[i]);
                if (customProjectParent != null) {
                    _wrapperCache.put(projects[i].getName(), customProjectParent);
                }
            }

            if (customProjectParent != null) {
                list.add(customProjectParent);
            } // else ignore the project
        }
        
        result = new Object[list.size()];
        list.toArray(result);
        
        return result;
    }

That brings the number of test projects up to 2.

Why did we do that?

Just as a review about TDD from my rather narrow/myopic perspective (and not necessarily in this order):

  • Don’t test the platform
  • Don’t test trivial logic (i.e. trivial getters and setters)
  • Test boundary conditions that will cause errors
  • Test success conditions

So, what kinds of tests do we need? Well, the easiest way is to pretend we know how to implement the behavior, but haven’t actually written it yet. That should give us a clarity of purpose known only to those who already know the answer.

What does Eclipse expect the content provider to provide? Well, content. In our case, the content is the custom project in its variations; no other project/content types need apply.

As ContentProvider is just another POJO we can test it in a pretty standalone way. Also, even though our content provider implements an interface that extends an interface that extends an interface, we really only care about the methods we overrode. Of course, when I made the following list to see which methods I care about it turns out I had to override them all:

public class ContentProvider implements ITreeContentProvider, IResourceChangeListener {
    // From ITreeContentProvider
    @Override
    public Object[] getChildren(Object parentElement) {
      ...
    }

    @Override
    public Object getParent(Object element) {
      ...
    }

    @Override
    public boolean hasChildren(Object element) {
      ...
    }

    // From IStructuredContentProvider
    @Override
    public Object[] getElements(Object inputElement) {
      ...
    }

    // From IContentProvider
    @Override
    public void dispose() {
      ...
    }

    @Override
    public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
      ...
    }

    // From IResourceChangeListener
    @Override
    public void resourceChanged(IResourceChangeEvent event) {
      ...
    }

}

The EasyMock framework will also make these tests a simpler to implement. I am not going to try to convince you one way or another to use EasyMock or any other mock object framework. Every time I use EasyMock my life is easier. If there is a simpler mock object framework let me know, otherwise pick one and get to work.

For example, when I thought about the tests for ContentProvider I wasn’t sure which I should write first so I took the path of least resistence:

  • getParent()
    • Input: IWorkspaceRoot, Output: null
    • Input: IProject, Output: non-null
    • Input: ICustomProjectElement, Output: non-null (could be an IWorkspaceRoot, or one of the CustomProject wrappers)
    • Input: anything else (including null), Output: zero length array
  • getChildren()
    • Input: IWorkspaceRoot, Output: null if no projects exist or if the projects are not of of the Custom Project nature.
    • Input: IWorkspaceRoot, Output: non-null if a Custom Project exists
    • Input: IWorkspaceRoot w/ 3 projects (1 non-custom, 1 custom, 1 non-custom), Output: an array with one custom project
    • Input: IWorkspaceRoot w/ 3 projects (1 custom, 1 non-custom, 1 custom), Output: an array with two custom projects
    • Input: IProject, Output: null (by defintion, if it were a CustomProject it would be wrapped already)
    • Input: ICustomProjectElement, Output: non-null unless if is a leaf child like CustomProjectSchemaFilters
    • Input: anything else (including null), Output: zero length array
  • hasChildren()
    • Input: IWorkspaceRoot, Output: false if the projects no proejcts exist or are not Custom Projects otherwise true
    • Input: ICustomProjectElement, Output: false if it is a leaf child like CustomProjectSchemaFilters, true otherwise
    • Input: anything else (including null), Output: false

Seems like a lot to think about doesn’t it? That is the whole idea. [Programming is no more about typing than writing is; in fact, programming is just as much about thinking as writing is.] Under what conditions can something fail? When it “succeeds” did it succeed properly? Some of the above I normally consider as I write the tests and others happen as I learn about the behavior as I implement. White boards are my friend.

Also, tests, like the ones for ICustomProjectElement, normally help you discover that you need data types like ICustomProjectElement. In this case, we skipped a few steps.

It’s okay; I forgive us.

Finally, I am not testing:

  • getElement(): since this calls getChildren() there is no reason to test this.
  • dispose(): I have no idea how I would do that. Sadly, I do have to make sure that I release any resources for which I am responsible, but I am not sure how I would do that except to simply remember that I need to do that in dispose() (can you say time bomb?). Also, it is trivial enough so I can safely ignore it for now.
  • inputChanged(): having implemented it I can safely say that testing an assignment at this point is…pointless.
  • resourceChanged(): This is purely GUI behavior. I suppose I could test it if the logic were complex, but for now it is not.

Being less than a TDD purist is hard to admit, but what the heck, I am not as much of a TDD purist as I would like folks to believe. Sometimes, I can’t come up with that perfect scenario that will light the way for me to create a host of absolutely incredible tests that will leave my code both bug-free and completely covered.

In any case, I am not going to go over every test or how I agonized over them or how much I drank to get through them. Red Bull is overrated.

In addition, clean up customnavigator.test.Activator:
– comment the empty constructor
– add @Override to start()
– add @Override to stop()

More True Confessions

And this is where we write all kinds of test code for the CustomNavigator; only CustomProjects should appear and their various nodes should stay open if they were open when we changed something or should stay closed when we changed something.

We could test things like:

  • a generic project – assert an empty custom navigator in a fresh workspace
  • a custom project – assert one project in the custom navigator
  • a generic project and a custom project – assert one project in the custom navigator

There is only one problem (or perhaps we should consider it an opportunity): that is testing the platform. Making sure that ContentProvider is called with an IWorkspaceRoot was a plugin.xml configuration, not code, so what are we testing anyway? Actually, we would be testing the ContentProvider! Again!

I know we had fun doing it the first time, but I’ll pass on doing it more than once.

I am also not going to write any tests for CustomProjectParent or any of the children that come from it. Why? They are simple. No point wasting time on them until the logic contained by them is complex enough to warrant it.

Kinda makes you wish we had refactored them earlier. No worries; we do that in the next post.

What Just Happened?

Some of you may look at the tests and wonder how does using EasyMock make the job any easier? It is not about EasyMock; it is about testing the expected behavior from the code regardless of what the actual input is.

For example, in testGetChildrenForICustomProjectElementWithNoChildren() and testGetChildrenForICustomProjectElementWithChildren() I tested for an ICustomProjectElement with children and with no children, but I did it without using the CustomProjectParent type or any of its children. The reason for that is both simple and important: I am not testing CustomProjectParent or its children; I am testing ContentProvider. By mixing the testing of ContentProvider and CustomProjectParent (or any of the children) I run the risk of testing something I don’t need to test, or worse, forgetting to test something I should have tested.

Next time: Now that the tests are mostly out of the way it is time to refactor the children.

The cat is tired.

Code

ContentProviderTest.java

/**
 * Coder beware: this code is not warranted to do anything.
 *
 * Copyright Dec 6, 2009 Carlos Valcarcel
 */
package customnavigator.navigator;

import org.easymock.EasyMock;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectNature;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.runtime.CoreException;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;


/**
 * @author carlos
 *
 */
public class ContentProviderTest {
    private static final String CUSTOMPLUGIN_PROJECT_NATURE = "customplugin.projectNature"; //$NON-NLS-1$
    
    private ContentProvider _contentProvider;

    @Test
    public void testGetParentForIWorkspaceRoot() {
        Object actual = null;
        
        IWorkspaceRoot workspaceRoot = EasyMock.createStrictMock(IWorkspaceRoot.class);
        actual = _contentProvider.getParent(workspaceRoot);
        
        Assert.assertNull(actual);
    }
    
    @Test
    public void testGetParentForNull() {
        Object actual = null;
        
        actual = _contentProvider.getParent(null);
        
        Assert.assertNull(actual);
    }
    
    @Test
    public void testGetParentForObject() {
        Object actual = null;
        
        actual = _contentProvider.getParent(new Object());
        
        Assert.assertNull(actual);
    }
    
    @Test
    public void testGetParentForIProject() {
        IWorkspaceRoot workspaceRoot = EasyMock.createStrictMock(IWorkspaceRoot.class);
        IWorkspace workspace = EasyMock.createStrictMock(IWorkspace.class);
        IProject project = EasyMock.createStrictMock(IProject.class);
        project.getWorkspace();
        EasyMock.expectLastCall().andReturn(workspace);
        workspace.getRoot();
        EasyMock.expectLastCall().andReturn(workspaceRoot);
        
        EasyMock.replay(workspaceRoot, workspace, project);
        
        Object actual = _contentProvider.getParent(project);
        Assert.assertNotNull(actual);
        
        EasyMock.verify(workspaceRoot, workspace, project);
    }
    
    @Test
    public void testGetParentForICustomProjectElement() {
        Object parent = EasyMock.createNiceControl();
        ICustomProjectElement customProjectElement = EasyMock.createStrictMock(ICustomProjectElement.class);
        customProjectElement.getParent();
        EasyMock.expectLastCall().andReturn(parent);
        
        EasyMock.replay(customProjectElement);
        
        Object actual = _contentProvider.getParent(customProjectElement);
        Assert.assertNotNull(actual);
        
        EasyMock.verify(customProjectElement);
    }

    @Test
    public void testGetChildrenForIWorkspaceRootWithNoProjects() {
        IProject [] projects = {};
        IWorkspaceRoot workspaceRoot = EasyMock.createStrictMock(IWorkspaceRoot.class);
        workspaceRoot.getProjects();
        EasyMock.expectLastCall().andReturn(projects);
        
        EasyMock.replay(workspaceRoot);
        
        Object [] actual = _contentProvider.getChildren(workspaceRoot);
        Assert.assertNotNull(actual);
        Assert.assertTrue(actual.length == 0);
        
        EasyMock.verify(workspaceRoot);
    }
    
    @Test
    public void testGetChildrenForIWorkspaceRootWithNoCustomProjects() throws CoreException {
        IProject [] projects = new IProject[1];
        IProject project = EasyMock.createStrictMock(IProject.class);
        
        projects[0] = project;
        
        IWorkspaceRoot workspaceRoot = EasyMock.createStrictMock(IWorkspaceRoot.class);
        workspaceRoot.getProjects();
        EasyMock.expectLastCall().andReturn(projects);
        
        project.getName();
        EasyMock.expectLastCall().andReturn("non-custom project"); //$NON-NLS-1$
        
        project.getNature(CUSTOMPLUGIN_PROJECT_NATURE);
        EasyMock.expectLastCall().andReturn(null);
        
        EasyMock.replay(workspaceRoot, project);
        
        Object [] actual = _contentProvider.getChildren(workspaceRoot);
        Assert.assertNotNull(actual);
        Assert.assertTrue(actual.length == 0);
        
        EasyMock.verify(workspaceRoot, project);
    }
    
    @Test
    public void testGetChildrenForIWorkspaceRootWithOneCustomProject() throws CoreException {
        IProject [] projects = new IProject[1];
        IProject project = EasyMock.createStrictMock(IProject.class);
        
        projects[0] = project;
        
        IWorkspaceRoot workspaceRoot = EasyMock.createStrictMock(IWorkspaceRoot.class);
        workspaceRoot.getProjects();
        EasyMock.expectLastCall().andReturn(projects);
        
        String projectName = "custom project"; //$NON-NLS-1$
        project.getName();
        EasyMock.expectLastCall().andReturn(projectName);
        
        project.getNature(CUSTOMPLUGIN_PROJECT_NATURE);
        EasyMock.expectLastCall().andReturn(EasyMock.createMock(IProjectNature.class));

        project.getName();
        EasyMock.expectLastCall().andReturn(projectName);
        
        EasyMock.replay(workspaceRoot, project);
        
        Object [] actual = _contentProvider.getChildren(workspaceRoot);
        Assert.assertNotNull(actual);
        Assert.assertTrue(actual.length == 1);
        Assert.assertEquals(project, ((CustomProjectParent)actual[0]).getProject());
        
        EasyMock.verify(workspaceRoot, project);
    }
    
    @Test
    public void testGetChildrenForIWorkspaceRootWithOneCustomProjectTwoNonCustomProjects() throws CoreException {
        IProject nonCustomProject1 = EasyMock.createStrictMock(IProject.class);
        IProject nonCustomProject2 = EasyMock.createStrictMock(IProject.class);
        IProject customProject = EasyMock.createStrictMock(IProject.class);
        
        IProject[] projects = {
                nonCustomProject1,
                customProject,
                nonCustomProject2
        };
        
        IWorkspaceRoot workspaceRoot = EasyMock.createStrictMock(IWorkspaceRoot.class);
        workspaceRoot.getProjects();
        EasyMock.expectLastCall().andReturn(projects);
        
        String bogusProjectName = "bogus project"; //$NON-NLS-1$
        String customProjectName = "custom project"; //$NON-NLS-1$
        nonCustomProject1.getName();
        EasyMock.expectLastCall().andReturn(bogusProjectName);
        
        nonCustomProject1.getNature(CUSTOMPLUGIN_PROJECT_NATURE);
        EasyMock.expectLastCall().andReturn(null);

        customProject.getName();
        EasyMock.expectLastCall().andReturn(customProjectName);
        
        customProject.getNature(CUSTOMPLUGIN_PROJECT_NATURE);
        EasyMock.expectLastCall().andReturn(EasyMock.createMock(IProjectNature.class));

        customProject.getName();
        EasyMock.expectLastCall().andReturn(customProjectName);
        
        nonCustomProject2.getName();
        EasyMock.expectLastCall().andReturn(bogusProjectName);
        
        nonCustomProject2.getNature(CUSTOMPLUGIN_PROJECT_NATURE);
        EasyMock.expectLastCall().andReturn(null);

        EasyMock.replay(workspaceRoot, nonCustomProject1, customProject, nonCustomProject2);
        
        Object [] actual = _contentProvider.getChildren(workspaceRoot);
        Assert.assertNotNull(actual);
        Assert.assertTrue(actual.length == 1);
        Assert.assertEquals(customProject, ((CustomProjectParent)actual[0]).getProject());
        
        EasyMock.verify(workspaceRoot, nonCustomProject1, nonCustomProject2, customProject);
    }

    @Test
    public void testGetChildrenForIWorkspaceRootWithOneNonCustomProjectTwoCustomProjects() throws CoreException {
        IProject customProject1 = EasyMock.createStrictMock(IProject.class);
        IProject customProject2 = EasyMock.createStrictMock(IProject.class);
        IProject nonCustomProject = EasyMock.createStrictMock(IProject.class);
        
        IProject[] projects = {
                customProject1,
                nonCustomProject,
                customProject2
        };
        
        IWorkspaceRoot workspaceRoot = EasyMock.createStrictMock(IWorkspaceRoot.class);
        workspaceRoot.getProjects();
        EasyMock.expectLastCall().andReturn(projects);
        
        String bogusProjectName = "bogus project"; //$NON-NLS-1$
        String customProjectName1 = "custom project 1"; //$NON-NLS-1$
        String customProjectName2 = "custom project 2"; //$NON-NLS-1$
        customProject1.getName();
        EasyMock.expectLastCall().andReturn(customProjectName1);
        
        customProject1.getNature(CUSTOMPLUGIN_PROJECT_NATURE);
        EasyMock.expectLastCall().andReturn(EasyMock.createMock(IProjectNature.class));

        customProject1.getName();
        EasyMock.expectLastCall().andReturn(customProjectName1);
        
        nonCustomProject.getName();
        EasyMock.expectLastCall().andReturn(bogusProjectName);
        
        nonCustomProject.getNature(CUSTOMPLUGIN_PROJECT_NATURE);
        EasyMock.expectLastCall().andReturn(null);

        customProject2.getName();
        EasyMock.expectLastCall().andReturn(customProjectName2);
        
        customProject2.getNature(CUSTOMPLUGIN_PROJECT_NATURE);
        EasyMock.expectLastCall().andReturn(EasyMock.createMock(IProjectNature.class));

        customProject2.getName();
        EasyMock.expectLastCall().andReturn(customProjectName2);
        
        EasyMock.replay(workspaceRoot, customProject1, nonCustomProject, customProject2);
        
        Object [] actual = _contentProvider.getChildren(workspaceRoot);
        Assert.assertNotNull(actual);
        Assert.assertTrue(actual.length == 2);
        Assert.assertEquals(customProject1, ((CustomProjectParent)actual[0]).getProject());
        Assert.assertEquals(customProject2, ((CustomProjectParent)actual[1]).getProject());
        
        EasyMock.verify(workspaceRoot, customProject1, nonCustomProject, customProject2);
    }

    /**
     * If a resource of type IProject comes in ignore it. If it were
     * a Custom Project it would be wrapped already.
     */
    @Test
    public void testGetChildrenForIProjectNotCustomProject() {
        IProject project = EasyMock.createStrictMock(IProject.class);
        
        Object [] actual = _contentProvider.getChildren(project);
        Assert.assertNotNull(actual);
        Assert.assertTrue(actual.length == 0);
    }
    
    @Test
    public void testGetChildrenForICustomProjectElementWithNoChildren() {
        assertChildrenFromICustomProjectElement(0);
    }

    /**
     * Check that an ICustomProjectElement returns some kids. Send back 5 to prove
     * the right method is called. 
     */
    @Test
    public void testGetChildrenForICustomProjectElementWithChildren() {
        assertChildrenFromICustomProjectElement(5);
    }
    
    @Before
    public void setUp() {
        _contentProvider = new ContentProvider();
    }

    private void assertChildrenFromICustomProjectElement(int childCount) {
        Object [] children = new Object[childCount];
        ICustomProjectElement customProjectElement = EasyMock.createStrictMock(ICustomProjectElement.class);
        
        customProjectElement.getChildren();
        EasyMock.expectLastCall().andReturn(children);

        EasyMock.replay(customProjectElement);
        
        Object [] actual = _contentProvider.getChildren(customProjectElement);
        Assert.assertNotNull(actual);
        Assert.assertTrue(actual.length == childCount);

        EasyMock.verify(customProjectElement);
    }

}

ContentProvider.java

/**
 * Coder beware: this code is not warranted to do anything.
 * Copyright Oct 17, 2009 Carlos Valcarcel
 */
package customnavigator.navigator;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.TreePath;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;

import customplugin.natures.ProjectNature;

/**
 * @author carlos
 */
public class ContentProvider implements ITreeContentProvider, IResourceChangeListener {

    private static final Object[]   NO_CHILDREN = {};
    private Map<String, Object> _wrapperCache = new HashMap<String, Object>();
    private Viewer _viewer;

    public ContentProvider() {
        ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE);
    }

    /*
     * (non-Javadoc)
     * @see
     * org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)
     */
    @Override
    public Object[] getChildren(Object parentElement) {
        Object[] children = null;
        if (IWorkspaceRoot.class.isInstance(parentElement)) {
            IProject[] projects = ((IWorkspaceRoot)parentElement).getProjects(); 
            children = createCustomProjectParents(projects);
        } else if (ICustomProjectElement.class.isInstance(parentElement)) {
            children = ((ICustomProjectElement) parentElement).getChildren();
        } else {
            children = NO_CHILDREN;
        }

        return children;
    }

    /*
     * (non-Javadoc)
     * @see
     * org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object)
     */
    @Override
    public Object getParent(Object element) {
        Object parent = null;
            
        if (IProject.class.isInstance(element)) {
            parent = ((IProject)element).getWorkspace().getRoot();
        } else if (ICustomProjectElement.class.isInstance(element)) {
            parent = ((ICustomProjectElement)element).getParent();
        } // else parent = null if IWorkspaceRoot or anything else
        
        return parent;
    }

    /*
     * (non-Javadoc)
     * @see
     * org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object)
     */
    @Override
    public boolean hasChildren(Object element) {
        boolean hasChildren = false;

        if (IWorkspaceRoot.class.isInstance(element)) {
            hasChildren = ((IWorkspaceRoot)element).getProjects().length > 0;
        } else if (ICustomProjectElement.class.isInstance(element)) {
            hasChildren = ((ICustomProjectElement)element).hasChildren();
        }
        // else it is not one of these so return false
        
        return hasChildren;
    }

    /*
     * (non-Javadoc)
     * @see
     * org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
     */
    @Override
    public Object[] getElements(Object inputElement) {
        // This is the same as getChildren() so we will call that instead
        return getChildren(inputElement);
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.jface.viewers.IContentProvider#dispose()
     */
    @Override
    public void dispose() {
        ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
    }

    /*
     * (non-Javadoc)
     * @see
     * org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
     */
    @Override
    public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
        _viewer = viewer;
    }

    @Override
    public void resourceChanged(IResourceChangeEvent event) {
        TreeViewer viewer = (TreeViewer) _viewer;
        TreePath[] treePaths = viewer.getExpandedTreePaths();
        viewer.refresh();
        viewer.setExpandedTreePaths(treePaths); 
    }

    private Object createCustomProjectParent(IProject parentElement) {

        Object result = null;
        try {
            if (parentElement.getNature(ProjectNature.NATURE_ID) != null) {
                result = new CustomProjectParent(parentElement);
            }
        } catch (CoreException e) {
            // Go to the next IProject
        }

        return result;
    }

    private Object[] createCustomProjectParents(IProject[] projects) {
        Object[] result = null;
        
        List<Object> list = new ArrayList<Object>();
        for (int i = 0; i < projects.length; i++) {
            Object customProjectParent = _wrapperCache.get(projects[i].getName()); 
            if (customProjectParent == null) {
                customProjectParent = createCustomProjectParent(projects[i]);
                if (customProjectParent != null) {
                    _wrapperCache.put(projects[i].getName(), customProjectParent);
                }
            }

            if (customProjectParent != null) {
                list.add(customProjectParent);
            } // else ignore the project
        }
        
        result = new Object[list.size()];
        list.toArray(result);
        
        return result;
    }

}
Advertisements
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: