org.openmicroscopy.shoola.agents.treeviewer.browser.BrowserComponent.java Source code

Java tutorial

Introduction

Here is the source code for org.openmicroscopy.shoola.agents.treeviewer.browser.BrowserComponent.java

Source

/*
 * org.openmicroscopy.shoola.agents.treeviewer.browser.BrowserComponent
 *
 *------------------------------------------------------------------------------
 *  Copyright (C) 2006-2014 University of Dundee. All rights reserved.
 *
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 *------------------------------------------------------------------------------
 */

package org.openmicroscopy.shoola.agents.treeviewer.browser;

//Java imports
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JTree;
import javax.swing.tree.TreePath;

//Third-party libraries

import org.apache.commons.collections.CollectionUtils;
//Application-internal dependencies
import org.openmicroscopy.shoola.agents.events.treeviewer.ExperimenterLoadedDataEvent;
import org.openmicroscopy.shoola.agents.treeviewer.IconManager;
import org.openmicroscopy.shoola.agents.treeviewer.RefreshExperimenterDef;
import org.openmicroscopy.shoola.agents.treeviewer.TreeViewerAgent;
import org.openmicroscopy.shoola.agents.treeviewer.cmd.EditVisitor;
import org.openmicroscopy.shoola.agents.treeviewer.cmd.ExperimenterVisitor;
import org.openmicroscopy.shoola.agents.treeviewer.cmd.ParentVisitor;
import org.openmicroscopy.shoola.agents.treeviewer.cmd.RefreshVisitor;
import org.openmicroscopy.shoola.agents.treeviewer.view.TreeViewer;
import org.openmicroscopy.shoola.agents.util.EditorUtil;
import org.openmicroscopy.shoola.agents.util.browser.ContainerFinder;
import org.openmicroscopy.shoola.agents.util.browser.NodeSelectionVisitor;
import org.openmicroscopy.shoola.agents.util.browser.NodesFinder;
import org.openmicroscopy.shoola.agents.util.browser.PartialNameVisitor;
import org.openmicroscopy.shoola.agents.util.browser.SimilarNodesVisitor;
import org.openmicroscopy.shoola.agents.util.browser.TreeFileSet;
import org.openmicroscopy.shoola.agents.util.browser.TreeImageDisplay;
import org.openmicroscopy.shoola.agents.util.browser.TreeImageDisplayVisitor;
import org.openmicroscopy.shoola.agents.util.browser.TreeImageSet;
import org.openmicroscopy.shoola.agents.util.browser.TreeImageTimeSet;
import org.openmicroscopy.shoola.agents.util.browser.TreeViewerTranslator;
import org.openmicroscopy.shoola.agents.util.dnd.DnDTree;
import org.openmicroscopy.shoola.env.data.FSAccessException;
import org.openmicroscopy.shoola.env.data.FSFileSystemView;
import org.openmicroscopy.shoola.env.data.util.SecurityContext;
import org.openmicroscopy.shoola.env.event.EventBus;
import org.openmicroscopy.shoola.env.log.LogMessage;
import org.openmicroscopy.shoola.util.ui.component.AbstractComponent;

import com.google.common.collect.Sets;

import pojos.DataObject;
import pojos.DatasetData;
import pojos.ExperimenterData;
import pojos.FileData;
import pojos.GroupData;
import pojos.ImageData;
import pojos.MultiImageData;
import pojos.PlateData;
import pojos.ProjectData;
import pojos.ScreenData;
import pojos.TagAnnotationData;

/** 
 * Implements the {@link Browser} interface to provide the functionality
 * required of the tree viewer component.
 * This class is the component hub and embeds the component's MVC triad.
 * It manages the component's state machine and fires state change 
 * notifications as appropriate, but delegates actual functionality to the
 * MVC sub-components.
 *
 * @author  Jean-Marie Burel     
 *             <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a>
 * @version 2.2
 * <small>
 * (<b>Internal version:</b> $Revision$ $Date$)
 * </small>
 * @since OME2.2
 */
class BrowserComponent extends AbstractComponent implements Browser {

    /** The Model sub-component. */
    private BrowserModel model;

    /** The View sub-component. */
    private BrowserUI view;

    /** The Controller sub-component. */
    private BrowserControl controller;

    /** The node to select after saving data. */
    private TreeImageDisplay toSelectAfterSave;

    /**
    * Reloads the data for the specified experimenters.
    * 
    * @param ids The id of the experimenters.
    */
    private void refreshExperimenterData(List<Long> ids) {
        RefreshExperimenterDef def;
        RefreshVisitor v = new RefreshVisitor(this);
        TreeImageDisplay root = view.getTreeRoot();
        //root.setToRefresh(false);
        int n = root.getChildCount();
        Map<SecurityContext, RefreshExperimenterDef> m = new HashMap<SecurityContext, RefreshExperimenterDef>(n);
        Collection foundNodes;
        Map topNodes;
        int type = model.getBrowserType();
        Iterator j;
        TreeImageSet expNode, groupNode;
        List children;
        long gid;
        SecurityContext ctx;
        if (model.isSingleGroup()) {
            gid = model.getUserDetails().getDefaultGroup().getId();
            for (int i = 0; i < n; i++) {
                expNode = (TreeImageSet) root.getChildAt(i);
                //if (expNode.isExpanded() && expNode.isChildrenLoaded()) {
                if (ids.contains(expNode.getUserObjectId())) {
                    expNode.accept(v, TreeImageDisplayVisitor.TREEIMAGE_SET_ONLY);
                    foundNodes = v.getFoundNodes();
                    topNodes = v.getExpandedTopNodes();
                    //reset the flag 
                    if (type == Browser.IMAGES_EXPLORER)
                        countExperimenterImages(expNode);
                    def = new RefreshExperimenterDef(expNode, v.getFoundNodes(), v.getExpandedTopNodes());
                    ctx = new SecurityContext(gid);
                    if (model.getDisplayMode() == TreeViewer.EXPERIMENTER_DISPLAY)
                        ctx.setExperimenter((ExperimenterData) expNode.getUserObject());
                    m.put(ctx, def);
                }
            }
        } else {
            for (int i = 0; i < n; i++) {
                groupNode = (TreeImageSet) root.getChildAt(i);
                if (groupNode.isExpanded()) {
                    gid = groupNode.getUserObjectId();
                    children = groupNode.getChildrenDisplay();
                    j = children.iterator();
                    while (j.hasNext()) {
                        expNode = (TreeImageSet) j.next();
                        if (ids.contains(expNode.getUserObjectId())) {
                            expNode.accept(v, TreeImageDisplayVisitor.TREEIMAGE_SET_ONLY);
                            foundNodes = v.getFoundNodes();
                            topNodes = v.getExpandedTopNodes();
                            //reset the flag 
                            if (type == Browser.IMAGES_EXPLORER)
                                countExperimenterImages(expNode);
                            def = new RefreshExperimenterDef(expNode, v.getFoundNodes(), v.getExpandedTopNodes());
                            ctx = new SecurityContext(gid);
                            ctx.setExperimenter((ExperimenterData) expNode.getUserObject());
                            m.put(ctx, def);
                        }
                    }
                }
            }
        }
        model.loadRefreshExperimenterData(m, null, -1, null, null);
        fireStateChange();
    }

    /**
     * Helper method to remove the collection of the specified nodes.
     * 
     * @param nodes The collection of node to remove.
     */
    private void removeNodes(List nodes) {
        TreeImageDisplay parentDisplay;
        if (getLastSelectedDisplay() == null)
            parentDisplay = view.getTreeRoot();
        else {
            parentDisplay = getLastSelectedDisplay().getParentDisplay();
        }
        if (parentDisplay == null)
            parentDisplay = view.getTreeRoot();
        setSelectedDisplay(parentDisplay);
        view.removeNodes(nodes, parentDisplay);
    }

    /**
     * Helper method to create the specified nodes.
     * 
     * @param nodes         The list of nodes to add the specified 
     *                      <code>display</code> node to.
     * @param display       The node to add to.
     * @param parentDisplay The parent of the node.
     */
    private void createNodes(List nodes, TreeImageDisplay display, TreeImageDisplay parentDisplay) {
        setSelectedDisplay(display);
        Object ho = display.getUserObject();
        if ((ho instanceof ProjectData) || (ho instanceof ScreenData))
            display.setChildrenLoaded(Boolean.valueOf(true));
        else if (ho instanceof TagAnnotationData) {
            TagAnnotationData tag = (TagAnnotationData) ho;
            if (TagAnnotationData.INSIGHT_TAGSET_NS.equals(tag.getNameSpace()))
                display.setChildrenLoaded(Boolean.valueOf(true));
            else
                display.setChildrenLoaded(Boolean.valueOf(false));
        } else {
            display.setChildrenLoaded(Boolean.valueOf(false));
        }
        view.createNodes(nodes, display, parentDisplay);
        //Object o = display.getUserObject();
        countItems(null, display);
    }

    /**
     * Handles the node selection when the user clicks on find next or find 
     * previous.
     * 
     * @param node The newly selected node.
     */
    private void handleNodeDisplay(TreeImageDisplay node) {
        view.selectFoundNode(node);
    }

    /**
     * Controls if the passed node has to be saved before selecting a new node.
     * 
     * @param node The node to check.
     * @return <code>true</code> if we need to save data, <code>false</code>
     *          otherwise.
     */
    private boolean hasDataToSave(TreeImageDisplay node) {
        if (model.getParentModel().hasDataToSave()) {
            //toSelectAfterSave = node;
            model.getParentModel().showPreSavingDialog();
            return false;
        }
        return false;
    }

    /** Counts the tags used but not owned by the user. */
    private void countExperimenterDataInFolders() {
        ContainerFinder finder = new ContainerFinder(ExperimenterData.class);
        accept(finder, TreeImageDisplayVisitor.TREEIMAGE_SET_ONLY);
        Set<TreeImageSet> nodes = finder.getContainerNodes();
        Iterator<TreeImageSet> i = nodes.iterator();
        TreeImageSet node;
        while (i.hasNext()) {
            node = i.next();
            if (node.getUserObject() instanceof ExperimenterData && node.isExpanded())
                countExperimenterImages(node);
        }
    }

    /** 
     * Retrieves the nodes to count the value for.
     *
     * @param rootType The type of node to track.
     * @param node The node to visit.
     */
    private void countItems(List<Class> rootType, TreeImageDisplay node) {
        if (rootType == null) {
            int type = model.getBrowserType();
            if (type == PROJECTS_EXPLORER) {
                rootType = new ArrayList<Class>();
                rootType.add(DatasetData.class);
            } else if (type == TAGS_EXPLORER) {
                rootType = new ArrayList<Class>();
                rootType.add(TagAnnotationData.class);
            } else if (type == ADMIN_EXPLORER) {
                rootType = new ArrayList<Class>();
                rootType.add(GroupData.class);
            }
        }
        if (rootType == null) {
            countExperimenterDataInFolders();
            return;
        }
        ContainerFinder finder = new ContainerFinder(rootType);
        Set<DataObject> items;
        Set<TreeImageSet> nodes;
        if (node != null) {
            node.accept(finder, TreeImageDisplayVisitor.TREEIMAGE_SET_ONLY);
            items = finder.getContainers();
            nodes = finder.getContainerNodes();
            if (items.size() == 0 && nodes.size() == 0)
                return;
            model.fireContainerCountLoading(items, nodes, node);
        } else {
            //
            TreeImageDisplay root = view.getTreeRoot();
            List l = root.getChildrenDisplay();
            Iterator i = l.iterator();
            while (i.hasNext()) {
                countItems(rootType, (TreeImageDisplay) i.next());
            }
        }
    }

    /** 
     * Counts the nodes linked to the specified annotation.
     *
     * @param node The node of reference.
     */
    private void countItemsInAnnotation(TreeImageSet node) {
        if (node == null)
            return;
        Object ho = node.getUserObject();
        List<Class> types = new ArrayList<Class>();
        if (ho instanceof TagAnnotationData) {
            types.add(DatasetData.class);
        }
        if (types.size() == 0)
            return;
        ContainerFinder finder = new ContainerFinder(types);
        node.accept(finder, TreeImageDisplayVisitor.TREEIMAGE_SET_ONLY);
        Set<DataObject> items = finder.getContainers();
        Set<TreeImageSet> nodes = finder.getContainerNodes();
        if (items.size() == 0 && nodes.size() == 0)
            return;
        model.fireContainerCountLoading(items, nodes, node);
    }

    /**
     * Sets the selected node.
     * 
     * @param display The selected value.
     * @param single  Pass <code>true</code> if the method is invoked for
     *                single selection, <code>false</code> for multi-selection.
     */
    private void setSelectedDisplay(TreeImageDisplay display, boolean single) {
        switch (model.getState()) {
        //case LOADING_DATA:
        //case LOADING_LEAVES:
        case DISCARDED:
            throw new IllegalStateException("This method cannot be invoked in the " + "DISCARDED state.");
        }
        hasDataToSave(display);
        TreeImageDisplay oldDisplay = model.getLastSelectedDisplay();
        TreeImageDisplay exp = null;
        Object ho = null;
        if (display != null) {
            ho = display.getUserObject();
            if (ho instanceof ExperimenterData) {
                if (getBrowserType() != ADMIN_EXPLORER) {
                    exp = display;
                    display = null;
                }
            }
        }
        if (exp != null)
            model.setSelectedDisplay(exp, single);
        else
            model.setSelectedDisplay(display, single);
        if (oldDisplay != null && oldDisplay.equals(display)) {
            ho = oldDisplay.getUserObject();
            if (ho instanceof PlateData)
                firePropertyChange(SELECTED_TREE_NODE_DISPLAY_PROPERTY, null, display);
        } else {
            firePropertyChange(SELECTED_TREE_NODE_DISPLAY_PROPERTY, oldDisplay, display);
        }
    }

    /**
     * Creates a new instance.
     * The {@link #initialize() initialize} method should be called straight 
     * after to complete the MVC set up.
     * 
     * @param model The Model sub-component.
     */
    BrowserComponent(BrowserModel model) {
        if (model == null)
            throw new NullPointerException("No model.");
        this.model = model;
        controller = new BrowserControl(this);
        view = new BrowserUI();
    }

    /** 
     * Links up the MVC triad. 
     * 
     * @param exp The logged in experimenter.
     */
    void initialize(ExperimenterData exp) {
        model.initialize(this);
        controller.initialize(view);
        view.initialize(controller, model, exp);
    }

    /**
     * Returns the Model sub-component.
     * 
     * @return See above.
     */
    BrowserModel getModel() {
        return model;
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#getState()
     */
    public int getState() {
        return model.getState();
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#activate()
     */
    public void activate() {
        int state = model.getState();
        switch (state) {
        case NEW:
            if (model.getBrowserType() == ADMIN_EXPLORER) {
                model.fireExperimenterDataLoading(null);
                return;
            }
            TreeImageDisplay node;
            switch (model.getDisplayMode()) {
            case TreeViewer.GROUP_DISPLAY:
                node = getDefaultGroupNode();
                if (node != null) {
                    view.expandNode(node, true);
                }
                break;
            case TreeViewer.EXPERIMENTER_DISPLAY:
            default:
                node = getLoggedExperimenterNode();
                if (node != null) {
                    if (!model.isSingleGroup()) {
                        TreeImageDisplay p = node.getParentDisplay();
                        if (p != null)
                            p.setExpanded(true);
                    }
                    view.expandNode(node, true);
                }
            }

            break;
        case READY:
            refreshBrowser(); //do we want to automatically refresh?
            break;
        case DISCARDED:
            throw new IllegalStateException("This method can't be invoked in the DISCARDED state.");
        default:
            break;
        }
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#discard()
     */
    public void discard() {
        if (model.getState() != DISCARDED) {
            model.discard();
            fireStateChange();
        }
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#getUI()
     */
    public JComponent getUI() {
        if (model.getState() == DISCARDED)
            throw new IllegalStateException("This method cannot be invoked in the DISCARDED state.");
        return view;
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#getBrowserType()
     */
    public int getBrowserType() {
        return model.getBrowserType();
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#cancel()
     */
    public void cancel() {
        int state = model.getState();
        if ((state == LOADING_DATA) || (state == LOADING_LEAVES)) {
            model.cancel();
            view.cancel(model.getLastSelectedDisplay());
            fireStateChange();
        }
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#loadFilteredImagesForHierarchy()
     */
    public void loadFilteredImagesForHierarchy() {
        int state = model.getState();
        if ((state == DISCARDED) || (state == LOADING_LEAVES))
            throw new IllegalStateException(
                    "This method cannot be invoked in the DISCARDED or" + "LOADING_LEAVES state.");
        //Check the filterType and editorType.
        if (model.getBrowserType() != Browser.IMAGES_EXPLORER)
            throw new IllegalArgumentException("Method should only be invoked" + " by the Images Explorer.");
        //if (model.getFilterType() == NO_IMAGES_FILTER) 
        view.loadAction(view.getTreeRoot());
        //model.fireFilterDataLoading();
        model.getParentModel().setStatus(true, TreeViewer.LOADING_TITLE, false);
        fireStateChange();
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#setLeaves(Set, TreeImageSet, TreeImageSet)
     */
    public void setLeaves(Collection leaves, TreeImageSet parent, TreeImageSet expNode) {
        if (model.getState() != LOADING_LEAVES)
            return;
        if (leaves == null)
            throw new NullPointerException("No leaves.");
        Object ho = expNode.getUserObject();
        if (!(ho instanceof ExperimenterData || ho instanceof GroupData))
            throw new IllegalArgumentException("Node not valid");
        if (model.getBrowserType() == FILE_SYSTEM_EXPLORER) {
            model.getParentModel().setLeaves(parent, leaves);
            model.setState(READY);
            fireStateChange();
            return;
        }

        Set visLeaves = TreeViewerTranslator.transformHierarchy(leaves);
        view.setLeavesViews(visLeaves, parent);

        model.setState(READY);
        if (parent != null && parent.getUserObject() instanceof TagAnnotationData)
            //countItems(TagAnnotationData.class);
            countItemsInAnnotation(parent);
        if (model.getBrowserType() == TAGS_EXPLORER && parent instanceof TreeFileSet) {
            List<Class> types = new ArrayList<Class>();
            types.add(TagAnnotationData.class);
            countItems(types, expNode);
        }
        Object p = null;
        if (parent != null && parent.getUserObject() instanceof PlateData) {
            p = parent.getUserObject();
        }
        if (!(p instanceof PlateData))
            model.getParentModel().setLeaves(parent, leaves);
        model.getParentModel().setStatus(false, "", true);
        fireStateChange();
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#setSelectedDisplay(TreeImageDisplay)
     */
    public void setSelectedDisplay(TreeImageDisplay display) {
        setSelectedDisplay(display, true);
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#showPopupMenu(int)
     */
    public void showPopupMenu(int index) {
        switch (model.getState()) {
        case LOADING_DATA:
        case LOADING_LEAVES:
        case DISCARDED:
            return;
        /*
         throw new IllegalStateException(
                 "This method cannot be invoked in the LOADING_DATA, "+
                 " LOADING_LEAVES or DISCARDED state.");
                 */
        }
        switch (index) {
        case TreeViewer.FULL_POP_UP_MENU:
        case TreeViewer.PARTIAL_POP_UP_MENU:
        case TreeViewer.ADMIN_MENU:
        case TreeViewer.CREATE_MENU_ADMIN:
            break;
        default:
            throw new IllegalArgumentException("Menu not supported:" + " " + index);
        }
        firePropertyChange(POPUP_MENU_PROPERTY, Integer.valueOf(-1), Integer.valueOf(index));
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#getClickPoint()
     */
    public Point getClickPoint() {
        return model.getClickPoint();
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#getLastSelectedDisplay()
     */
    public TreeImageDisplay getLastSelectedDisplay() {
        return model.getLastSelectedDisplay();
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#close()
     */
    public void close() {
        switch (model.getState()) {
        case LOADING_DATA:
        case LOADING_LEAVES:
        case DISCARDED:
            throw new IllegalStateException("This method can only be invoked in the LOADING_DATA, "
                    + " LOADING_LEAVES or DISCARDED state.");
        }
        firePropertyChange(CLOSE_PROPERTY, null, this);
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#collapse(TreeImageDisplay)
     */
    public void collapse(TreeImageDisplay node) {
        if (node == null)
            return;
        view.collapsePath(node);
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#expand(TreeImageDisplay)
     */
    public void expand(TreeImageDisplay node) {
        if (node == null)
            return;
        view.expandNode(node);
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#accept(TreeImageDisplayVisitor)
     */
    public void accept(TreeImageDisplayVisitor visitor) {
        accept(visitor, TreeImageDisplayVisitor.ALL_NODES);
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#accept(TreeImageDisplayVisitor, int)
     */
    public void accept(TreeImageDisplayVisitor visitor, int algoType) {
        view.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        view.getTreeRoot().accept(visitor, algoType);
        view.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#getTitle()
     */
    public String getTitle() {
        return view.getBrowserTitle();
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#getIcon()
     */
    public Icon getIcon() {
        IconManager im = IconManager.getInstance();
        switch (model.getBrowserType()) {
        case PROJECTS_EXPLORER:
            return im.getIcon(IconManager.PROJECT);//HIERARCHY_EXPLORER);
        case TAGS_EXPLORER:
            return im.getIcon(IconManager.TAG);//TAGS_EXPLORER);
        case IMAGES_EXPLORER:
            return im.getIcon(IconManager.DATE);//IMAGES_EXPLORER);
        case SCREENS_EXPLORER:
            return im.getIcon(IconManager.SCREEN);//SCREENS_EXPLORER);
        case FILES_EXPLORER:
            return im.getIcon(IconManager.FILES_EXPLORER);
        case FILE_SYSTEM_EXPLORER:
            return im.getIcon(IconManager.FILE_SYSTEM_EXPLORER);
        case ADMIN_EXPLORER:
            return im.getIcon(IconManager.ADMIN);
        }
        return null;
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#sortTreeNodes(int)
     */
    public void sortTreeNodes(int sortType) {
        switch (model.getState()) {
        //case COUNTING_ITEMS:
        case LOADING_DATA:
        case LOADING_LEAVES:
        case DISCARDED:
            throw new IllegalStateException(
                    "This method cannot be invoked in the LOADING_DATA, " + " LOADING_LEAVES or DISCARDED state.");
        }
        switch (sortType) {
        case SORT_NODES_BY_DATE:
        case SORT_NODES_BY_NAME:
            break;
        default:
            throw new IllegalArgumentException("SortType not supported.");
        }
        view.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        view.sortNodes(sortType);
        view.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#setContainerCountValue(int, long, Set)
     */
    public void setContainerCountValue(long containerID, long value, Set<TreeImageSet> nodes) {
        int state = model.getState();
        if (state == DISCARDED)
            return;
        boolean b = model.setContainerCountValue(view.getTreeDisplay(), containerID, value, nodes);
        if (b) {
            view.getTreeDisplay().repaint();
        }
        model.getParentModel().setStatus(false, "", true);
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#setFoundInBrowser(Set)
     */
    public void setFoundInBrowser(Set nodes) {
        if (nodes == null || nodes.size() == 0) {
            model.setFoundNodes(null); // reset default value.
            model.setFoundNodeIndex(-1); // reset default value.
            view.getTreeDisplay().repaint();
            return;
        }
        List<Object> list = new ArrayList<Object>(nodes.size());
        Iterator i = nodes.iterator();

        final JTree tree = view.getTreeDisplay();
        while (i.hasNext())
            list.add(i.next());
        Comparator c = new Comparator() {
            public int compare(Object o1, Object o2) {
                TreeImageDisplay node1 = (TreeImageDisplay) o1;
                TreeImageDisplay node2 = (TreeImageDisplay) o2;
                int i1 = tree.getRowForPath(new TreePath(node1.getPath()));
                int i2 = tree.getRowForPath(new TreePath(node2.getPath()));
                return (i1 - i2);
            }
        };
        Collections.sort(list, c);
        model.setFoundNodes(list);
        model.setFoundNodeIndex(0);
        handleNodeDisplay((TreeImageDisplay) list.get(0));
        tree.repaint();
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#findNext()
     */
    public void findNext() {
        List l = model.getFoundNodes();
        if (l == null || l.size() == 0)
            return;
        int index = model.getFoundNodeIndex();
        int n = l.size() - 1;
        if (index < n)
            index++; //not last element
        else if (index == n)
            index = 0;
        model.setFoundNodeIndex(index);
        handleNodeDisplay((TreeImageDisplay) l.get(index));
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#findPrevious()
     */
    public void findPrevious() {
        List l = model.getFoundNodes();
        if (l == null || l.size() == 0)
            return;
        int index = model.getFoundNodeIndex();
        if (index > 0)
            index--; //not last element
        else if (index == 0)
            index = l.size() - 1;
        model.setFoundNodeIndex(index);
        handleNodeDisplay((TreeImageDisplay) l.get(index));
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#setSelected(boolean)
     */
    public void setSelected(boolean b) {
        switch (model.getState()) {
        //case LOADING_DATA:
        //case LOADING_LEAVES:
        //case COUNTING_ITEMS:
        //    return;
        case DISCARDED:
            throw new IllegalStateException("This method can only be invoked in the " + "NEW or READY state.");
        }
        boolean old = model.isSelected();
        if (old == b)
            return;
        model.setSelected(b);
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#refreshEdition(DataObject, int)
     */
    public void refreshEdition(DataObject object, DataObject parent, int op) {
        switch (model.getState()) {
        case NEW:
        case READY:
            break;
        default:
            throw new IllegalStateException("This method can only " + "be invoked in the NEW or READY state.");
        }
        Object o = object;
        List nodes = null;
        TreeImageDisplay parentDisplay = null;
        TreeImageDisplay loggedUser = getLoggedExperimenterNode();
        if (op == TreeViewer.CREATE_OBJECT) {
            TreeImageDisplay node = getLastSelectedDisplay();
            if ((object instanceof ProjectData) || (object instanceof ScreenData)
                    || ((object instanceof DatasetData) && parent == null)
                    || ((object instanceof TagAnnotationData) && parent == null)) {
                nodes = new ArrayList(1);
                nodes.add(loggedUser);
                parentDisplay = loggedUser;
                //nodes.add(view.getTreeRoot());
                //parentDisplay = view.getTreeRoot();
            } else if (parent != null)
                o = node.getUserObject();
        }
        if (nodes == null && parent == null) {
            EditVisitor visitor = new EditVisitor(this, o, null);
            //accept(visitor, TreeImageDisplayVisitor.ALL_NODES);
            loggedUser.accept(visitor, TreeImageDisplayVisitor.ALL_NODES);
            nodes = visitor.getFoundNodes();
        }
        if (parent != null) {
            EditVisitor visitor = new EditVisitor(this, null, parent);
            loggedUser.accept(visitor, TreeImageDisplayVisitor.ALL_NODES);
            nodes = visitor.getParentNodes();
        }

        if (op == TreeViewer.UPDATE_OBJECT)
            view.updateNodes(nodes, object);
        else if (op == TreeViewer.REMOVE_OBJECT)
            removeNodes(nodes);
        else if (op == TreeViewer.CREATE_OBJECT) {
            //Get the user node.
            if (parentDisplay == null)
                parentDisplay = getLastSelectedDisplay();
            TreeImageDisplay newNode = TreeViewerTranslator.transformDataObject(object);

            createNodes(nodes, newNode, parentDisplay);
        }
        setSelectedNode();
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#onOrphanDataObjectCreated(DataObject)
     */
    public void onOrphanDataObjectCreated(DataObject data) {
        int type = model.getBrowserType();
        if (data instanceof DatasetData) {
            if (type != PROJECTS_EXPLORER)
                return;
        } else if (data instanceof TagAnnotationData) {
            if (type != TAGS_EXPLORER)
                return;
        }
        TreeImageDisplay loggedUser = getLoggedExperimenterNode();
        List<TreeImageDisplay> nodes = new ArrayList<TreeImageDisplay>(1);
        nodes.add(loggedUser);
        //long model.get
        createNodes(nodes, TreeViewerTranslator.transformDataObject(data), loggedUser);
        setSelectedNode();
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#getSelectedDisplays()
     */
    public TreeImageDisplay[] getSelectedDisplays() {
        return model.getSelectedDisplays();
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#getSelectedDataObjects()
     */
    public List getSelectedDataObjects() {
        TreeImageDisplay[] nodes = getSelectedDisplays();
        if (nodes == null || nodes.length == 0)
            return null;
        List<DataObject> objects = new ArrayList<DataObject>();
        Object uo;
        for (int i = 0; i < nodes.length; i++) {
            uo = nodes[i].getUserObject();
            if (uo instanceof DataObject) {
                objects.add((DataObject) uo);
            }
        }
        return objects;
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#setSelectedDisplays(TreeImageDisplay[], boolean)
     */
    public void setSelectedDisplays(TreeImageDisplay[] nodes, boolean expandParent) {
        if (nodes.length == 0)
            return;
        TreeImageDisplay[] oldNodes = model.getSelectedDisplays();
        boolean b = true;
        if (oldNodes != null && oldNodes.length > 1)
            b = false;
        if (nodes.length == 1 && b) {
            setSelectedDisplay(nodes[0], true);
            if (expandParent) {
                TreeImageDisplay parent = nodes[0].getParentDisplay();
                if (parent.getUserObject() instanceof ExperimenterData)
                    parent = nodes[0];
                view.expandNode(parent);
                view.setFoundNode(nodes);
            }
            return;
        }
        boolean flush = false;
        if (oldNodes.length >= nodes.length)
            flush = true;
        int n = nodes.length;
        TreeImageDisplay parent = null;
        for (int i = 0; i < n; i++) {
            if (nodes[i] != null) {
                parent = nodes[i].getParentDisplay();
                if (parent != null && parent.getUserObject() instanceof ExperimenterData)
                    parent = nodes[i];
                if (i == 0)
                    model.setSelectedDisplay(nodes[i], flush);
                else
                    model.setSelectedDisplay(nodes[i], false);
            }
        }
        if (parent != null && expandParent) {
            view.setFoundNode(nodes);
            view.expandNode(parent);
        }
        firePropertyChange(SELECTED_TREE_NODE_DISPLAY_PROPERTY, null, nodes[n - 1]);
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#onComponentStateChange(boolean)
     */
    public void onComponentStateChange(boolean b) {
        view.onComponentStateChange(b);
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#isDisplayed()
     */
    public boolean isDisplayed() {
        return model.isDisplayed();
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#setDisplayed(boolean)
     */
    public void setDisplayed(boolean displayed) {
        if (model.getState() == DISCARDED)
            throw new IllegalStateException("This method cannot be invoked " + "in the DISCARDED state.");
        model.setDisplayed(displayed);
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#setRefreshedHierarchy(Map, Map)
     */
    public void setRefreshedHierarchy(Map nodes, Map expandedTopNodes) {
        if (model.getState() != LOADING_DATA)
            throw new IllegalStateException("This method cannot be invoked " + "in the LOADING_DATA state.");
        //long userID = model.getUserID();
        //long groupID = model.getUserGroupID();
        //view.setViews(TreeViewerTranslator.refreshHierarchy(nodes,
        //            expandedTopNodes, userID, groupID)); 
        countItems(null, null);
        model.getParentModel().setStatus(false, "", true);
        PartialNameVisitor v = new PartialNameVisitor(view.isPartialName());
        accept(v, TreeImageDisplayVisitor.TREEIMAGE_NODE_ONLY);
        fireStateChange();
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#displaysImagesName()
     */
    public void displaysImagesName() {
        if (model.getState() == DISCARDED)
            throw new IllegalStateException("This method cannot be invoked " + "in the DISCARDED state.");
        PartialNameVisitor v = new PartialNameVisitor(view.isPartialName());
        accept(v, TreeImageDisplayVisitor.TREEIMAGE_NODE_ONLY);
        view.repaint();
    }

    /**
      * Implemented as specified by the {@link Browser} interface.
      * @see Browser#loadExperimenterData(TreeImageDisplay, TreeImageDisplay)
      */
    public void loadExperimenterData(TreeImageDisplay exp, TreeImageDisplay n) {
        if (exp == null)
            throw new IllegalArgumentException("Node not valid.");
        Object uo = exp.getUserObject();
        if (!(uo instanceof ExperimenterData || uo instanceof GroupData))
            throw new IllegalArgumentException("Node not valid.");
        switch (model.getState()) {
        case DISCARDED:
        case LOADING_LEAVES:
            return;
        }
        if (n == null)
            model.fireExperimenterDataLoading((TreeImageSet) exp);
        else {
            n.setToRefresh(false);
            if (model.getBrowserType() == FILE_SYSTEM_EXPLORER) {
                uo = n.getUserObject();
                TreeImageDisplay expNode = BrowserFactory.getDataOwner(n);
                if (expNode == null)
                    return;
                Object ho = expNode.getUserObject();
                if (!(ho instanceof ExperimenterData))
                    return;
                if (uo instanceof MultiImageData) {
                    MultiImageData mi = (MultiImageData) uo;
                    model.setState(LOADING_LEAVES);
                    setLeaves(mi.getComponents(), (TreeImageSet) n, (TreeImageSet) exp);
                } else if (uo instanceof FileData) {
                    FileData dir = (FileData) uo;
                    if (dir.isHidden())
                        return;
                    if (dir.isDirectory()) {
                        //Check if data loaded
                        List<DataObject> list = new ArrayList<DataObject>();
                        if (n.isChildrenLoaded()) {
                            List children = n.getChildrenDisplay();
                            Iterator k = children.iterator();
                            TreeImageDisplay d;
                            Object o;
                            while (k.hasNext()) {
                                d = (TreeImageDisplay) k.next();
                                o = d.getUserObject();
                                if (o instanceof DataObject) {
                                    list.add((DataObject) o);
                                }
                            }
                        } else {
                            long expID = ((ExperimenterData) ho).getId();
                            DataObject[] files = model.getFilesData(expID, dir);
                            if (files != null) {
                                for (int i = 0; i < files.length; i++)
                                    list.add(files[i]);
                            }
                        }
                        if (list.size() > 0) {
                            model.setState(LOADING_LEAVES);
                            setLeaves(list, (TreeImageSet) n, (TreeImageSet) exp);
                        }
                    }
                    return;
                }
            } else
                model.fireLeavesLoading(exp, n);
        }
        model.getParentModel().setStatus(true, TreeViewer.LOADING_TITLE, false);
        fireStateChange();
    }

    /**
      * Implemented as specified by the {@link Browser} interface.
      * @see Browser#setExperimenterData(TreeImageDisplay, Collection)
      */
    public void setExperimenterData(TreeImageDisplay expNode, Collection nodes) {
        int state = model.getState();
        if (state != LOADING_DATA)
            return;
        if (nodes == null)
            throw new NullPointerException("No nodes.");

        if (expNode == null)
            throw new IllegalArgumentException("Node not valid.");
        Object uo = expNode.getUserObject();
        if (!(uo instanceof ExperimenterData || uo instanceof GroupData))
            throw new IllegalArgumentException("Node not valid.");
        Set convertedNodes = TreeViewerTranslator.transformHierarchy(nodes);
        view.setExperimenterData(convertedNodes, expNode);
        model.setState(READY);

        countItems(null, expNode);
        countExperimenterDataInFolders();
        model.getParentModel().setStatus(false, "", true);
        //Visit the tree and
        switch (model.getBrowserType()) {
        case Browser.PROJECTS_EXPLORER:
        case Browser.SCREENS_EXPLORER:
            //TODO: review that code to indicate the context.
            ParentVisitor visitor = new ParentVisitor();
            accept(visitor, ParentVisitor.TREEIMAGE_SET_ONLY);
            EventBus bus = TreeViewerAgent.getRegistry().getEventBus();
            bus.post(new ExperimenterLoadedDataEvent(visitor.getData()));
        }
        fireStateChange();
    }

    /**
      * Implemented as specified by the {@link Browser} interface.
      * @see Browser#addExperimenter(ExperimenterData, long)
      */
    public void addExperimenter(ExperimenterData experimenter, long groupID) {
        if (experimenter == null)
            throw new IllegalArgumentException("Experimenter cannot be null.");
        if (model.getBrowserType() == ADMIN_EXPLORER)
            return;
        TreeImageDisplay node = model.getLastSelectedDisplay();
        boolean reload = false;
        if (model.isSingleGroup()) {
            node = view.getTreeRoot();
            reload = node.getChildCount() == 0;
        } else {
            //Find the group
            ExperimenterVisitor v = new ExperimenterVisitor(this, groupID);
            accept(v, TreeImageDisplayVisitor.TREEIMAGE_SET_ONLY);
            List<TreeImageDisplay> list = v.getNodes();
            if (list.size() == 0)
                return;
            node = list.get(0);
        }

        //Make sure the user is not already display
        List<TreeImageDisplay> nodes = new ArrayList<TreeImageDisplay>(1);
        nodes.add(new TreeImageSet(experimenter));
        SimilarNodesVisitor visitor = new SimilarNodesVisitor(nodes);
        node.accept(visitor, TreeImageDisplayVisitor.TREEIMAGE_SET_ONLY);

        if (visitor.getFoundNodes().size() > 0)
            return;
        setSelectedDisplay(null);
        view.addExperimenter(experimenter, node);
        if (reload)
            view.reloadNode(node);
    }

    /**
      * Implemented as specified by the {@link Browser} interface.
      * @see Browser#removeExperimenter(ExperimenterData, GroupData)
      */
    public void removeExperimenter(ExperimenterData exp, long groupID) {
        if (exp == null)
            throw new IllegalArgumentException("Experimenter cannot be null.");
        TreeImageDisplay node = null;
        if (groupID >= 0) {
            ExperimenterVisitor v = new ExperimenterVisitor(this, groupID);
            accept(v);
            List<TreeImageDisplay> nodes = v.getNodes();
            if (nodes.size() == 1)
                node = nodes.get(0);
        }

        view.removeExperimenter(exp, node);
    }

    /**
      * Implemented as specified by the {@link Browser} interface.
      * @see Browser#refreshExperimenterData()
      */
    public void refreshExperimenterData() {
        switch (model.getState()) {
        case LOADING_DATA:
        case LOADING_LEAVES:
            model.cancel();
            break;
        case DISCARDED:
            //ignore
            return;
        }
        TreeImageDisplay display;
        RefreshVisitor v = new RefreshVisitor(this);
        if (model.getBrowserType() == ADMIN_EXPLORER) {
            display = view.getTreeRoot();
            //review for admin.
            display.accept(v, TreeImageDisplayVisitor.TREEIMAGE_SET_ONLY);
            RefreshExperimenterDef def = new RefreshExperimenterDef((TreeImageSet) display, v.getFoundNodes(),
                    v.getExpandedTopNodes());
            Map<SecurityContext, RefreshExperimenterDef> m = new HashMap<SecurityContext, RefreshExperimenterDef>(
                    1);
            SecurityContext ctx = TreeViewerAgent.getAdminContext();
            if (ctx == null)
                ctx = model.getSecurityContext(null);
            m.put(ctx, def);
            model.loadRefreshExperimenterData(m, null, -1, null, null);
            fireStateChange();
        } else {
            display = model.getLastSelectedDisplay();
            if (display == null)
                return;
            Object ho = display.getUserObject();
            if (!(ho instanceof ExperimenterData))
                return;
            refreshExperimenterData(Arrays.asList(display.getUserObjectId()));
        }
    }

    /**
      * Implemented as specified by the {@link Browser} interface.
      * @see Browser#getLoggedExperimenterNode()
      */
    public TreeImageDisplay getLoggedExperimenterNode() {
        SecurityContext ctx = model.getSecurityContext(null);
        long id = ctx.getGroupID();
        if (model.isSingleGroup())
            id = -1;
        ExperimenterVisitor visitor = new ExperimenterVisitor(this, model.getUserID(), id);
        accept(visitor, TreeImageDisplayVisitor.TREEIMAGE_SET_ONLY);
        List<TreeImageDisplay> nodes = visitor.getNodes();
        if (nodes.size() != 1)
            return null;
        return nodes.get(0);
    }

    /**
      * Implemented as specified by the {@link Browser} interface.
      * @see Browser#refreshLoggedExperimenterData()
      */
    public void refreshLoggedExperimenterData() {
        switch (model.getState()) {
        case LOADING_DATA:
        case LOADING_LEAVES:
            model.cancel();
            break;
        case DISCARDED:
            //ignore
            return;
        }
        TreeImageDisplay node = getLoggedExperimenterNode();
        if (node == null)
            return;
        Object ho = node.getUserObject();
        if (!(ho instanceof ExperimenterData))
            return;
        refreshExperimenterData(Arrays.asList(node.getUserObjectId()));
        fireStateChange();
    }

    /**
      * Implemented as specified by the {@link Browser} interface.
      * @see Browser#refreshTree(Object, DataObject)
      */
    public void refreshTree(Object refNode, DataObject toBrowse) {
        switch (model.getState()) {
        case LOADING_DATA:
        case LOADING_LEAVES:
            model.cancel();
            break;
        case DISCARDED:
            //ignore
            return;
        }

        if (model.getBrowserType() == FILE_SYSTEM_EXPLORER) {
            //view.loadFileSystem(true);
            return;
        }
        if (model.getBrowserType() == ADMIN_EXPLORER) {
            refreshExperimenterData();
            return;
        }
        addComponent(null);
        TreeImageDisplay root = view.getTreeRoot();
        //root.setToRefresh(false);

        RefreshExperimenterDef def;
        RefreshVisitor v;
        int n = root.getChildCount();
        Map<SecurityContext, RefreshExperimenterDef> m = new HashMap<SecurityContext, RefreshExperimenterDef>(n);
        int type = model.getBrowserType();
        Iterator j;
        TreeImageSet expNode, groupNode;
        List children;
        long gid;
        SecurityContext ctx;
        switch (model.getDisplayMode()) {
        case TreeViewer.EXPERIMENTER_DISPLAY:
            if (model.isSingleGroup()) {
                gid = model.getUserDetails().getDefaultGroup().getId();
                for (int i = 0; i < n; i++) {
                    expNode = (TreeImageSet) root.getChildAt(i);
                    if (expNode.isExpanded() && expNode.isChildrenLoaded()) {
                        v = new RefreshVisitor(this);
                        expNode.accept(v);
                        //reset the flag 
                        if (type == Browser.IMAGES_EXPLORER)
                            countExperimenterImages(expNode);
                        def = new RefreshExperimenterDef(expNode, v.getFoundNodes(), v.getExpandedTopNodes());
                        ctx = new SecurityContext(gid);
                        if (model.getDisplayMode() == TreeViewer.EXPERIMENTER_DISPLAY)
                            ctx.setExperimenter((ExperimenterData) expNode.getUserObject());
                        m.put(ctx, def);
                    } else {
                        expNode.setChildrenLoaded(Boolean.FALSE);
                    }
                }
            } else {
                for (int i = 0; i < n; i++) {
                    groupNode = (TreeImageSet) root.getChildAt(i);
                    if (groupNode.isExpanded()) {
                        v = new RefreshVisitor(this);
                        gid = groupNode.getUserObjectId();
                        children = groupNode.getChildrenDisplay();
                        j = children.iterator();
                        while (j.hasNext()) {
                            expNode = (TreeImageSet) j.next();
                            if (expNode.isChildrenLoaded() && expNode.isExpanded()) {
                                v = new RefreshVisitor(this);
                                expNode.accept(v);
                                //reset the flag 
                                if (type == Browser.IMAGES_EXPLORER)
                                    countExperimenterImages(expNode);
                                def = new RefreshExperimenterDef(expNode, v.getFoundNodes(),
                                        v.getExpandedTopNodes());
                                ctx = new SecurityContext(gid);
                                ctx.setExperimenter((ExperimenterData) expNode.getUserObject());
                                m.put(ctx, def);
                            } else {
                                expNode.setChildrenLoaded(Boolean.FALSE);
                            }
                        }
                    }
                }
            }
            break;
        case TreeViewer.GROUP_DISPLAY:
            for (int i = 0; i < n; i++) {
                groupNode = (TreeImageSet) root.getChildAt(i);
                if (groupNode.isExpanded() && groupNode.isChildrenLoaded()) {
                    v = new RefreshVisitor(this);
                    groupNode.accept(v);
                    gid = groupNode.getUserObjectId();
                    //reset the flag 
                    if (type == Browser.IMAGES_EXPLORER)
                        countExperimenterImages(groupNode);
                    def = new RefreshExperimenterDef(groupNode, v.getFoundNodes(), v.getExpandedTopNodes());
                    m.put(new SecurityContext(gid), def);
                } else {
                    groupNode.setChildrenLoaded(Boolean.FALSE);
                }
            }
        }

        if (m.size() == 0) { //for new data the first time.
            TreeImageDisplay node = null;
            switch (model.getDisplayMode()) {
            case TreeViewer.GROUP_DISPLAY:
                node = getDefaultGroupNode();
            case TreeViewer.EXPERIMENTER_DISPLAY:
            default:
                node = getLoggedExperimenterNode();
            }
            if (node != null)
                loadExperimenterData(node, null);
            return;
        }
        model.loadRefreshExperimenterData(m, null, -1, refNode, toBrowse);
        fireStateChange();
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#setRefreshExperimenterData(Map, Class, long)
     */
    public void setRefreshExperimenterData(Map<SecurityContext, RefreshExperimenterDef> nodes, Class type,
            long id) {
        //TODO: Should reselect the node previously selected.
        if (nodes == null || nodes.size() == 0) {
            model.setSelectedDisplay(null, true);
            model.setState(READY);
            countItems(null, null);
            if (model.getBrowserType() == TAGS_EXPLORER)
                countExperimenterDataInFolders();
            model.getParentModel().setStatus(false, "", true);
            return;
        }
        Iterator<Entry<SecurityContext, RefreshExperimenterDef>> i = nodes.entrySet().iterator();
        RefreshExperimenterDef node;
        TreeImageSet expNode;
        Set convertedNodes;
        Entry<SecurityContext, RefreshExperimenterDef> entry;
        int browserType = model.getBrowserType();
        Map<Integer, Set> results;
        while (i.hasNext()) {
            entry = i.next();
            //userId = (Long)
            node = (RefreshExperimenterDef) entry.getValue();
            expNode = node.getExperimenterNode();
            if (browserType == IMAGES_EXPLORER || browserType == FILES_EXPLORER) {
                results = TreeViewerTranslator.refreshFolderHierarchy((Map) node.getResults());
                view.refreshFolder(expNode, results);
            } else {
                convertedNodes = TreeViewerTranslator.refreshHierarchy((Map) node.getResults(),
                        node.getExpandedTopNodes());
                view.setExperimenterData(convertedNodes, expNode);
            }
        }

        //expand the nodes.
        i = nodes.entrySet().iterator();
        Map m;
        Iterator j;
        Entry e;
        NodesFinder finder;
        if (type == null) {
            List l;
            Iterator<TreeImageDisplay> k;
            Set<TreeImageDisplay> found;
            while (i.hasNext()) {
                entry = i.next();
                node = (RefreshExperimenterDef) entry.getValue();
                expNode = node.getExperimenterNode();
                if (expNode.isExpanded()) {
                    m = node.getExpandedTopNodes();
                    List expandedNodes = node.getExpandedNodes();
                    boolean b = expandedNodes.size() == 0;
                    if (model.getBrowserType() == TAGS_EXPLORER)
                        b = expandedNodes.size() > 0;
                    if (m != null && m.size() > 0 && b) {
                        j = m.entrySet().iterator();
                        while (j.hasNext()) {
                            e = (Entry) j.next();
                            finder = new NodesFinder((Class) e.getKey(), (List) e.getValue());
                            accept(finder);
                            found = finder.getNodes();
                            if (found.size() > 0) {
                                k = found.iterator();
                                TreeImageDisplay n, c;
                                while (k.hasNext()) {
                                    n = k.next();
                                    if (n.isExpanded())
                                        view.expandNode(n);
                                    if (n.getUserObject() instanceof ProjectData) {
                                        List ll = n.getChildrenDisplay();
                                        if (!CollectionUtils.isEmpty(ll)) {
                                            Iterator w = ll.iterator();
                                            while (w.hasNext()) {
                                                c = (TreeImageDisplay) w.next();
                                                if (c.isExpanded())
                                                    view.expandNode(c);
                                            }
                                        }

                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        model.setSelectedDisplay(null, true);
        model.setState(READY);
        switch (model.getBrowserType()) {
        case TAGS_EXPLORER:
            List<Class> types = new ArrayList<Class>();
            types.add(TagAnnotationData.class);
            types.add(DatasetData.class);
            countItems(types, null);
            countExperimenterDataInFolders();
            break;
        case ADMIN_EXPLORER:
            countItems(null, null);
            break;
        default:
            TreeImageDisplay root = view.getTreeRoot();
            TreeImageSet groupNode;
            for (int k = 0; k < root.getChildCount(); k++) {
                groupNode = (TreeImageSet) root.getChildAt(k);
                if (groupNode.isExpanded()) {
                    countItems(null, groupNode);
                }
            }
        }
        model.getParentModel().setStatus(false, "", true);
        PartialNameVisitor v = new PartialNameVisitor(view.isPartialName());
        accept(v, TreeImageDisplayVisitor.TREEIMAGE_NODE_ONLY);
        if (ProjectData.class.equals(type) || DatasetData.class.equals(type) || ScreenData.class.equals(type)) {
            finder = new NodesFinder(type, id);
            accept(finder);
            Set<TreeImageDisplay> found = finder.getNodes();
            if (found.size() > 0) {
                Iterator<TreeImageDisplay> n = found.iterator();
                TreeImageDisplay display;
                if (DatasetData.class.equals(type)) {
                    while (n.hasNext()) {
                        display = n.next();
                        setSelectedDisplay(display);
                        view.expandNode(display, true);
                    }
                } else {
                    while (n.hasNext()) {
                        setSelectedDisplay(n.next());
                    }
                }
            }
        }
        switch (model.getBrowserType()) {
        case Browser.PROJECTS_EXPLORER:
        case Browser.SCREENS_EXPLORER:
            ParentVisitor visitor = new ParentVisitor();
            accept(visitor, ParentVisitor.TREEIMAGE_SET_ONLY);
            EventBus bus = TreeViewerAgent.getRegistry().getEventBus();
            bus.post(new ExperimenterLoadedDataEvent(visitor.getData()));
        }
        fireStateChange();
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#countExperimenterImages(TreeImageDisplay)
     */
    public void countExperimenterImages(TreeImageDisplay expNode) {
        if (expNode == null)
            throw new IllegalArgumentException("Node not valid.");
        Object ho = expNode.getUserObject();
        if (!(ho instanceof ExperimenterData || ho instanceof GroupData))
            throw new IllegalArgumentException("Node not valid.");
        switch (model.getState()) {
        case DISCARDED:
        case LOADING_LEAVES:
            throw new IllegalStateException(
                    "This method cannot be invoked in the DISCARDED or" + "LOADING_LEAVES state.");
        }
        int browserType = model.getBrowserType();
        if (!(browserType == IMAGES_EXPLORER || browserType == FILES_EXPLORER || browserType == TAGS_EXPLORER))
            return;
        model.fireCountExperimenterImages((TreeImageSet) expNode);
        model.getParentModel().setStatus(true, TreeViewer.LOADING_TITLE, false);
        fireStateChange();
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#setExperimenterCount(TreeImageSet, int, int)
     */
    public void setExperimenterCount(TreeImageSet expNode, int index, Object v) {
        if (expNode == null)
            throw new IllegalArgumentException("Node not valid.");
        Object ho = expNode.getUserObject();
        if (!(ho instanceof ExperimenterData || ho instanceof GroupData))
            throw new IllegalArgumentException("Node not valid.");
        int browserType = model.getBrowserType();
        if (!(browserType == IMAGES_EXPLORER || browserType == FILES_EXPLORER || browserType == TAGS_EXPLORER))
            return;
        boolean b = model.setExperimenterCount(expNode, index);
        if (index != -1 && v != null) {
            view.setCountValues(expNode, index, v);
        }
        if (b)
            view.getTreeDisplay().repaint();
        model.getParentModel().setStatus(false, "", true);
        fireStateChange();
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#getNodeOwner(TreeImageDisplay)
     */
    public ExperimenterData getNodeOwner(TreeImageDisplay node) {
        if (node == null)
            throw new IllegalArgumentException("No node specified.");
        TreeImageDisplay n = BrowserFactory.getDataOwner(node);
        if (n == null)
            return model.getUserDetails();
        return (ExperimenterData) n.getUserObject();
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#getNodeGroup(TreeImageDisplay)
     */
    public GroupData getNodeGroup(TreeImageDisplay node) {
        if (node == null)
            throw new IllegalArgumentException("No node specified.");
        TreeImageDisplay n = EditorUtil.getDataGroup(node);
        if (n == null)
            return model.getUserDetails().getDefaultGroup();
        return (GroupData) n.getUserObject();
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#getSecurityContext(TreeImageDisplay)
     */
    public SecurityContext getSecurityContext(TreeImageDisplay node) {
        return model.getSecurityContext(node);
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#getClickComponent()
     */
    public JComponent getClickComponent() {
        if (model.getState() == DISCARDED)
            throw new IllegalStateException("This method cannot be invoked " + "in the DISCARDED state.");
        return view.getTreeDisplay();
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#setSelected(boolean)
     */
    public void setSelectedNode() {
        if (toSelectAfterSave == null)
            return;
        setSelectedDisplay(toSelectAfterSave);
        toSelectAfterSave = null;
    }

    /**
    * Implemented as specified by the {@link Browser} interface.
    * @see Browser#refreshAdmin(Object)
    */
    public void refreshAdmin(Object data) {
        if (model.getState() == DISCARDED)
            return;
        if (model.getBrowserType() == ADMIN_EXPLORER && model.isSelected()) {
            //visit the browser
            TreeImageDisplay node = model.getLastSelectedDisplay();
            refreshBrowser();
            setSelectedDisplay(node, true);
            return;
        }
        if (data instanceof ExperimenterData || data instanceof GroupData) {
            ExperimenterVisitor v;
            GroupData g = null;
            if (data instanceof ExperimenterData) {
                ExperimenterData exp = (ExperimenterData) data;
                v = new ExperimenterVisitor(this, exp.getId(), -1);
            } else {
                g = (GroupData) data;
                v = new ExperimenterVisitor(this, g.getId());
            }
            accept(v, TreeImageDisplayVisitor.TREEIMAGE_SET_ONLY);
            List<TreeImageDisplay> l = v.getNodes();
            Iterator<TreeImageDisplay> i = l.iterator();
            TreeImageDisplay n;
            if (data instanceof ExperimenterData) {
                while (i.hasNext()) {
                    n = i.next();
                    n.setUserObject(model.getUserDetails());
                    view.reloadNode(n);
                }
            } else {
                while (i.hasNext()) {
                    n = i.next();
                    n.setUserObject(g);
                    view.reloadNode(n);
                    l = n.getChildrenDisplay();
                    i = l.iterator();
                    while (i.hasNext()) {
                        n = i.next();
                        if (n.isExpanded())
                            view.expandNode(n);
                    }
                }
            }
        }
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#browse(TreeImageDisplay, DataObject, boolean)
     */
    public void browse(TreeImageDisplay node, DataObject data, boolean withThumbnails) {
        //if (node == null) return;
        model.getParentModel().browse(node, data, withThumbnails);
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#onSelectedNode(Object, Object, Boolean)
     */
    public void onSelectedNode(Object parent, Object selected, Boolean multiSelection) {
        TreeImageDisplay foundNode;
        if (selected instanceof DataObject) {
            NodeSelectionVisitor visitor = new NodeSelectionVisitor(parent, (DataObject) selected);
            accept(visitor);
            foundNode = visitor.getSelectedNode();
            if (foundNode != null) {
                if (multiSelection)
                    model.addFoundNode(foundNode);
                else
                    model.setSelectedDisplay(foundNode, true);
                view.setFoundNode(model.getSelectedDisplays());
            } else
                view.setFoundNode(null);
        } else if (selected instanceof TreeImageDisplay) {
            foundNode = (TreeImageDisplay) selected;
            if (multiSelection)
                model.addFoundNode(foundNode);
            else
                model.setSelectedDisplay(foundNode, true);
            view.setFoundNode(model.getSelectedDisplays());
        } else if (selected instanceof List) {
            NodeSelectionVisitor visitor = new NodeSelectionVisitor(parent, (List<DataObject>) selected);
            accept(visitor);
            List<TreeImageDisplay> nodes = visitor.getSelectedNodes();
            if (nodes.size() == 0) {
                view.setFoundNode(null);
            } else if (nodes.size() == 1) {
                model.setSelectedDisplay(nodes.get(0), true);
                view.setFoundNode(model.getSelectedDisplays());
            } else {
                model.setSelectedDisplay(null, true);
                Iterator<TreeImageDisplay> i = nodes.iterator();
                while (i.hasNext())
                    model.addFoundNode(i.next());
                view.setFoundNode(model.getSelectedDisplays());
            }
        }
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#onDeselectedNode(Object, Object, Boolean)
     */
    public void onDeselectedNode(Object parent, Object selected, Boolean multiSelection) {
        if (selected instanceof DataObject) {
            NodeSelectionVisitor visitor = new NodeSelectionVisitor(parent, (DataObject) selected);
            accept(visitor);
            TreeImageDisplay foundNode = visitor.getSelectedNode();
            if (foundNode != null) {
                model.removeDisplay(foundNode);
                view.setFoundNode(model.getSelectedDisplays());
            } else
                view.setFoundNode(null);
        }

    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#setTimeIntervalImages(Set, TreeImageTimeSet)
     */
    public void setTimeIntervalImages(Set set, TreeImageTimeSet node) {
        model.getParentModel().browseTimeInterval(node, set);
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#onImportFinished(List)
     */
    public void onImportFinished(List<TreeImageDisplay> nodes) {
        if (model.getState() == DISCARDED)
            return;
        if (nodes == null)
            return;
        //reload the node.

        Iterator<TreeImageDisplay> i;
        TreeImageDisplay n;
        Object ho;

        switch (model.getBrowserType()) {
        case PROJECTS_EXPLORER:
            SimilarNodesVisitor v = new SimilarNodesVisitor(nodes);
            accept(v, TreeImageDisplayVisitor.TREEIMAGE_SET_ONLY);
            nodes = v.getFoundNodes();
            i = nodes.iterator();
            while (i.hasNext()) {
                n = i.next();
                ho = n.getUserObject();
                if (ho instanceof DatasetData) {
                    view.reloadContainer(n);
                }
            }
            break;
        }
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#setImportedFile(ImageData)
     */
    public void setImportedFile(ImageData image) {
        if (model.getState() == DISCARDED)
            return;
        if (image == null)
            return;
        model.addImportedImage(image);
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#isFileImported(String)
     */
    public boolean isFileImported(String path) {
        if (model.getState() == DISCARDED)
            return false;
        return model.isFileImported(path);
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#deleteObjects(List)
     */
    public void deleteObjects(List nodes) {
        model.getParentModel().deleteObjects(nodes);
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#showMenu(int, Component, Point)
     */
    public void showMenu(int index, Component invoker, Point loc) {
        model.getParentModel().showMenu(index, invoker, loc);
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#refreshBrowser()
     */
    public void refreshBrowser() {
        model.getParentModel().refreshTree();
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#removeTreeNodes(Collection)
     */
    public void removeTreeNodes(Collection<TreeImageDisplay> nodes) {
        if (nodes == null)
            return;
        Iterator<TreeImageDisplay> i = nodes.iterator();
        TreeImageDisplay node;
        TreeImageDisplay parent;
        while (i.hasNext()) {
            node = i.next();
            parent = node.getParentDisplay();
            if (parent != null) {
                parent.removeChildDisplay(node);
                node.removeFromParent();
                view.reloadNode(parent);
            }
        }
        /* ensure that the selected displays do not include any removed nodes */
        final Set<TreeImageDisplay> oldSelected = Sets.newHashSet(getSelectedDisplays());
        final Set<TreeImageDisplay> newSelected = Sets.newHashSet(oldSelected);
        newSelected.removeAll(nodes);
        if (!newSelected.equals(oldSelected)) {
            setSelectedDisplay(null);
            setSelectedDisplays(newSelected.toArray(new TreeImageDisplay[newSelected.size()]), false);
        }
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#reActivate()
     */
    public void reActivate() {
        model.setSelectedDisplay(null, true);
        view.reActivate();
        if (model.isSelected() && model.getBrowserType() == Browser.ADMIN_EXPLORER) {
            model.setState(NEW);
            activate();
        }
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#setRepositories(TreeImageDisplay, FSFileSystemView)
     */
    public void setRepositories(TreeImageDisplay expNode, FSFileSystemView systemView) {
        int state = model.getState();
        if (state != LOADING_DATA)
            throw new IllegalStateException("This method can only be invoked in the LOADING_DATA " + "state.");
        if (model.getBrowserType() != FILE_SYSTEM_EXPLORER)
            return;
        if (systemView == null)
            throw new NullPointerException("No File System.");

        if (expNode == null)
            throw new IllegalArgumentException("Experimenter node not valid.");
        Object uo = expNode.getUserObject();
        if (!(uo instanceof ExperimenterData))
            throw new IllegalArgumentException("Experimenter node not valid.");
        model.setRepositories(systemView);
        view.loadFileSystem(expNode);
        countItems(null, expNode);
        model.getParentModel().setStatus(false, "", true);
        fireStateChange();
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#setGroups(Set, List)
     */
    public void setGroups(Collection groups, List expanded) {
        int state = model.getState();
        if (state != LOADING_DATA)
            return;
        /*
        throw new IllegalStateException(
                "This method can only be invoked in the LOADING_DATA "+
                "state.");
                */
        if (model.getBrowserType() != ADMIN_EXPLORER)
            return;
        Set nodes = TreeViewerTranslator.transformGroups(groups);
        view.setGroups(nodes, expanded);
        model.setState(READY);
        countItems(null, null);
        model.getParentModel().setStatus(false, "", true);
        fireStateChange();
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#register(DataObject)
     */
    public boolean register(DataObject file) {
        if (file == null)
            throw new IllegalArgumentException("No file to register.");
        if (model.getBrowserType() != FILE_SYSTEM_EXPLORER)
            return false;
        if (!(file instanceof FileData || file instanceof ImageData))
            return false;
        if (file.getId() > 0)
            return false;
        try {
            TreeImageDisplay d = model.getLastSelectedDisplay();
            TreeImageDisplay exp = BrowserFactory.getDataOwner(d);
            if (exp == null)
                return false;
            Object ho = exp.getUserObject();
            if (!(ho instanceof ExperimenterData))
                return false;
            long id = ((ExperimenterData) ho).getId();
            if (file instanceof ImageData) {
                ImageData img = (ImageData) file;
                if (img.getIndex() >= 0) {
                    TreeImageDisplay pd = d.getParentDisplay();
                    if (pd == null)
                        return false;
                    if (!(pd.getUserObject() instanceof MultiImageData))
                        return false;
                    file = (DataObject) pd.getUserObject();
                }
            }
            DataObject o = model.getRepositories(id).register(file);
            if (o == null)
                return false;
        } catch (FSAccessException e) {
            LogMessage msg = new LogMessage();
            msg.print("Cannot register the object.");
            msg.print(e);
            TreeViewerAgent.getRegistry().getLogger().error(this, msg);
            return false;
        }
        view.repaint();
        return true;
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#setExperimenters(TreeImageSet, Collection)
     */
    public void setExperimenters(TreeImageSet node, List result) {
        if (result.size() != 1)
            return;
        Object ho = result.get(0);
        node.setUserObject(ho);
        GroupData g = (GroupData) ho;
        Set nodes = TreeViewerTranslator.transformExperimenters(g.getExperimenters());
        view.setLeavesViews(nodes, node);
        model.setState(READY);
        model.getParentModel().setLeaves(node, g.getExperimenters());
        model.getParentModel().setStatus(false, "", true);
        fireStateChange();
    }

    /**
     * Implemented as specified by the {@link TreeViewer} interface.
     * @see Browser#canEdit(Object)
     */
    public boolean canEdit(Object ho) {
        return model.getParentModel().canEdit(ho);
    }

    /**
     * Implemented as specified by the {@link TreeViewer} interface.
     * @see Browser#canAnnotate(Object)
     */
    public boolean canAnnotate(Object ho) {
        return model.getParentModel().canAnnotate(ho);
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#expandUser()
     */
    public void expandUser() {
        if (model.getState() == DISCARDED)
            return;
        SecurityContext ctx = model.getSecurityContext(model.getLastSelectedDisplay());
        long id = model.getUserID();
        ExperimenterVisitor v = new ExperimenterVisitor(this, id, ctx.getGroupID());
        accept(v, TreeImageDisplayVisitor.TREEIMAGE_SET_ONLY);
        List<TreeImageDisplay> values = v.getNodes();
        if (values.size() != 1)
            return;
        TreeImageDisplay n = values.get(0);
        if (!n.isExpanded())
            view.expandNode(n);
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#expandUser()
     */
    public void resetPassword(String value) {
        if (model.getState() == DISCARDED)
            return;
        model.getParentModel().resetPassword(value);
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#refreshBrowser(Class, long)
     */
    public void refreshBrowser(Class type, long id) {
        if (ProjectData.class.equals(type) || DatasetData.class.equals(type) || ScreenData.class.equals(type)) {
            ExperimenterVisitor visitor = new ExperimenterVisitor(this, -1, -1);
            accept(visitor, TreeImageDisplayVisitor.TREEIMAGE_SET_ONLY);
            List<TreeImageDisplay> nodes = visitor.getNodes();
            if (nodes.size() == 0)
                return;
            Iterator<TreeImageDisplay> i = nodes.iterator();
            List<Long> ids = new ArrayList<Long>(nodes.size());
            while (i.hasNext()) {
                ids.add(i.next().getUserObjectId());
            }
            refreshExperimenterData(ids);
        }
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#addComponent(JComponent)
     */
    public void addComponent(JComponent component) {
        if (getBrowserType() != SCREENS_EXPLORER)
            return;
        view.addComponent(component);
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#loadDirectory(TreeImageDisplay)
     */
    public void loadDirectory(TreeImageDisplay display) {
        if (display == null)
            return;
        Object ho = display.getUserObject();
        if (!(ho instanceof FileData))
            return;
        FileData f = (FileData) ho;
        if (f.isDirectory()) {
            if (!display.isChildrenLoaded())
                view.loadFile(display);
            //model.getParentModel().browse(display, true);
        }
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#getNodesForUser(long, TreeImageDisplay)
     */
    public List<TreeImageDisplay> getNodesForUser(long userID, TreeImageDisplay node) {
        if (model.getState() == DISCARDED)
            return null;
        if (userID < 0)
            return null;
        SecurityContext context = model.getSecurityContext(node);
        ExperimenterVisitor v = new ExperimenterVisitor(this, userID, context.getGroupID());
        accept(v, TreeImageDisplayVisitor.TREEIMAGE_SET_ONLY);
        List<TreeImageDisplay> nodes = v.getNodes();
        if (nodes.size() != 1)
            return new ArrayList<TreeImageDisplay>();
        TreeImageDisplay n = nodes.get(0);
        return n.getChildrenDisplay();
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#rejectTransfer()
     */
    public void rejectTransfer() {
        JTree tree = view.getTreeDisplay();
        if (tree instanceof DnDTree) {
            ((DnDTree) tree).reset();
        }
    }

    /**
      * Implemented as specified by the {@link Browser} interface.
      * @see Browser#setUserGroup(GroupData)
      */
    public void setUserGroup(GroupData group) {
        if (group == null)
            throw new IllegalArgumentException("Group cannot be null.");
        view.setUserGroup(Arrays.asList(group));
    }

    /**
      * Implemented as specified by the {@link Browser} interface.
      * @see Browser#removeGroup(GroupData)
      */
    public void removeGroup(GroupData group) {
        if (group == null)
            return;
        view.removeGroup(group);
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#canLink(Object)
     */
    public boolean canLink(Object ho) {
        return model.getParentModel().canLink(ho);
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#getDataToCopy()
     */
    public List<DataObject> getDataToCopy() {
        return model.getParentModel().getDataToCopy();
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#paste(TreeImageDisplay[])
     */
    public void paste(TreeImageDisplay[] parents) {
        model.getParentModel().paste(parents);
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#setNodesToCopy(TreeImageDisplay[], int)
     */
    public void setNodesToCopy(TreeImageDisplay[] nodes, int index) {
        model.getParentModel().setNodesToCopy(nodes, index);
    }

    /**
      * Implemented as specified by the {@link Browser} interface.
      * @see Browser#getLoggedExperimenterNode()
      */
    public TreeImageDisplay getDefaultGroupNode() {
        SecurityContext ctx = model.getSecurityContext(null);
        long id = ctx.getGroupID();
        ExperimenterVisitor visitor = new ExperimenterVisitor(this, id);
        accept(visitor, TreeImageDisplayVisitor.TREEIMAGE_SET_ONLY);
        List<TreeImageDisplay> nodes = visitor.getNodes();
        if (nodes.size() != 1)
            return null;
        return nodes.get(0);
    }

    /**
      * Implemented as specified by the {@link Browser} interface.
      * @see Browser#getDisplayMode()
      */
    public int getDisplayMode() {
        return model.getDisplayMode();
    }

    /**
     * Implemented as specified by the {@link Browser} interface.
     * @see Browser#changeDisplayMode()
     */
    public void changeDisplayMode() {
        if (model.getBrowserType() == Browser.ADMIN_EXPLORER)
            return;
        model.setSelectedDisplay(null, true);
        //view.changeDisplayMode();
        ExperimenterVisitor v = new ExperimenterVisitor(this, -1);
        accept(v, ExperimenterVisitor.TREEIMAGE_SET_ONLY);
        List<TreeImageDisplay> nodes = v.getNodes();

        //Check the group already display
        //Was in group mode
        view.clear();
        List<GroupData> groups = new ArrayList<GroupData>(nodes.size());
        Iterator<TreeImageDisplay> i = nodes.iterator();
        while (i.hasNext()) {
            groups.add((GroupData) i.next().getUserObject());
        }
        if (model.isSingleGroup())
            view.reActivate();
        else
            view.setUserGroup(groups);
    }

}