org.openmicroscopy.shoola.agents.treeviewer.view.TreeViewerFactory.java Source code

Java tutorial

Introduction

Here is the source code for org.openmicroscopy.shoola.agents.treeviewer.view.TreeViewerFactory.java

Source

/*
 * org.openmicroscopy.shoola.agents.treeviewer.view.TreeViewerFactory
 *
 *------------------------------------------------------------------------------
 *  Copyright (C) 2006 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.view;

//Java imports
import java.awt.Rectangle;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import javax.swing.JMenu;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

//Third-party libraries

//Application-internal dependencies
import org.apache.commons.io.FilenameUtils;
import org.openmicroscopy.shoola.agents.events.SaveData;
import org.openmicroscopy.shoola.agents.treeviewer.TreeViewerAgent;
import org.openmicroscopy.shoola.env.Agent;
import org.openmicroscopy.shoola.env.Environment;
import org.openmicroscopy.shoola.env.LookupNames;
import org.openmicroscopy.shoola.env.data.events.SaveEventRequest;
import org.openmicroscopy.shoola.env.data.events.SaveEventResponse;
import org.openmicroscopy.shoola.env.data.model.ApplicationData;
import org.openmicroscopy.shoola.env.event.EventBus;
import org.openmicroscopy.shoola.env.log.LogMessage;
import org.openmicroscopy.shoola.env.ui.TaskBar;
import org.openmicroscopy.shoola.util.StringComparator;

import pojos.DataObject;
import pojos.ExperimenterData;
import pojos.ImageData;

/** 
 * Factory to create {@link TreeViewer} component.
 * This class keeps track of the {@link TreeViewer} instance that has been 
 * created and is not yet in the {@link TreeViewer#DISCARDED} state.
 *
 * @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
 */
public class TreeViewerFactory implements ChangeListener {

    /** Keeps track of viewers used to view archived images. */
    static final String IMAGE_ARCHIVED = "imageNotArchived";//"imageArchived";

    /** Keeps track of viewers used to view images. */
    static final String IMAGE_NOT_ARCHIVED = "imageNotArchived";

    /** The name of the file. */
    private static final String FILE_NAME = "externalApplication.txt";

    /** The name of the windows menu. */
    private static final String MENU_NAME = "Data Manager";

    /** The terms used to separate the file ID from the external application. */
    private static final String SEPARATOR = "=";

    /** The sole instance. */
    private static final TreeViewerFactory singleton = new TreeViewerFactory();

    /**
     * Registers the application.
     * 
     * @param data The application to register.
     * @param mimeType The mimeType of the file.
     */
    static void register(ApplicationData data, String mimeType) {
        if (mimeType == null)
            return;
        List<ApplicationData> list = singleton.applications.get(mimeType);
        if (list == null) {
            list = new ArrayList<ApplicationData>();
            list.add(data);
            singleton.applications.put(mimeType, list);
        } else { //Add the applications if needed.
            String path = data.getApplicationPath();
            Iterator<ApplicationData> i = list.iterator();
            ApplicationData app;
            boolean registered = false;
            while (i.hasNext()) {
                app = i.next();
                if (app.getApplicationPath().equals(path)) {
                    registered = true;
                    break;
                }
            }
            if (!registered) {
                list.add(data);
                Collections.sort(list, singleton.comparator);
            }
        }
    }

    /**
     * Returns the collection of external applications used to 
     * open the document.
     * 
     * @param type The MIME type of the document.
     * @return See above.
     */
    static List<ApplicationData> getApplications(String type) {
        return singleton.applications.get(type);
    }

    //static 
    /** 
     * Returns the <code>window</code> menu. 
     * 
     * @return See above.
     */
    static JMenu getWindowMenu() {
        return singleton.windowMenu;
    }

    /**
     * Returns <code>true</code> is the {@link #windowMenu} is attached 
     * to the <code>TaskBar</code>, <code>false</code> otherwise.
     *
     * @return See above.
     */
    static boolean isWindowMenuAttachedToTaskBar() {
        return singleton.isAttached;
    }

    /** Attaches the {@link #windowMenu} to the <code>TaskBar</code>. */
    static void attachWindowMenuToTaskBar() {
        if (isWindowMenuAttachedToTaskBar())
            return;
        TaskBar tb = TreeViewerAgent.getRegistry().getTaskBar();
        tb.addToMenu(TaskBar.WINDOW_MENU, getWindowMenu());
        singleton.isAttached = true;
    }

    /**
     * Returns the collection of active viewers.
     * 
     * @return See above.
     */
    static Set getViewers() {
        return singleton.viewers;
    }

    /**
     * Returns <code>true</code> if there is only one {@link TreeViewer}
     * available, <code>false</code> otherwise.
     * 
     * @return See above.
     */
    static boolean isLastViewer() {
        return (singleton.viewers.size() <= 1);
    }

    /**
     * Returns the {@link TreeViewer}.
     * 
     * @param exp The experiment the TreeViewer is for.
     * @return See above.
     */
    public static TreeViewer getTreeViewer(ExperimenterData exp) {
        TreeViewerModel model = new TreeViewerModel(exp);
        return singleton.getTreeViewer(model, null);
    }

    /**
     * Stores the image to copy the rendering settings from.
     * 
     * @param image The image to copy the rendering settings from.
     */
    public static void copyRndSettings(ImageData image) {
        Iterator v = singleton.viewers.iterator();
        TreeViewerComponent comp;
        while (v.hasNext()) {
            comp = (TreeViewerComponent) v.next();
            comp.setRndSettings(image);
        }
    }

    /**
     * Notifies that the rendering settings have been copied.
     * 
     * @param imageIds The collection of updated images
     */
    public static void onRndSettingsCopied(Collection<Long> imageIds) {
        Iterator<TreeViewer> v = singleton.viewers.iterator();
        TreeViewerComponent comp;
        while (v.hasNext()) {
            comp = (TreeViewerComponent) v.next();
            comp.onRndSettingsCopied(imageIds);
        }
    }

    /**
     * Saves the data before closing the application.
     * 
     * @param evt
     * @param agent
     */
    public static void saveOnClose(SaveEventRequest evt, Object agent) {
        //if (!(evt instanceof SaveData)) return;
        Iterator v = singleton.viewers.iterator();
        TreeViewerComponent comp;
        //tmp
        EventBus bus = TreeViewerAgent.getRegistry().getEventBus();
        while (v.hasNext()) {
            comp = (TreeViewerComponent) v.next();
            comp.saveOnClose((SaveData) evt.getAnswer());
            bus.post(new SaveEventResponse(evt, (Agent) agent));
        }
    }

    /**
     * Notifies the model that the user's group has successfully be modified
     * if the passed value is <code>true</code>, unsuccessfully 
     * if <code>false</code>.
     * 
     * @param success    Pass <code>true</code> if successful, <code>false</code>
     *                otherwise.
     */
    public static void onGroupSwitched(boolean success) {
        if (!success)
            return;
        Iterator<TreeViewer> v = singleton.viewers.iterator();
        TreeViewerComponent comp;
        while (v.hasNext()) {
            comp = (TreeViewerComponent) v.next();
            comp.onGroupSwitched(success);
        }
    }

    /**
     * Notifies the model that the user is reconnected.
     * 
     * @return Returns <code>true</code> if some viewers are already stored, 
     *         <code>false</code> otherwise.
     */
    public static boolean onReconnected() {
        Iterator<TreeViewer> v = singleton.viewers.iterator();
        TreeViewerComponent comp;
        while (v.hasNext()) {
            comp = (TreeViewerComponent) v.next();
            comp.onReconnected();
        }
        return singleton.viewers.size() > 0;
    }

    /**
     * Notifies the model that the user has annotated data.
     * 
     * @param containers The objects to handle.
     * @param count A positive value if annotations are added, a negative value
     * if annotations are removed.
     */
    public static void onAnnotated(List<DataObject> containers, int count) {
        Iterator v = singleton.viewers.iterator();
        TreeViewerComponent comp;
        while (v.hasNext()) {
            comp = (TreeViewerComponent) v.next();
            comp.onAnnotated(containers, count);
        }
    }

    /**
     * Returns the {@link TreeViewer}.
     * 
     * @param exp The experiment the TreeViewer is for.
     * @param bounds The bounds of the component invoking a new 
     * {@link TreeViewer}. 
     * @return See above.
     */
    public static TreeViewer getTreeViewer(ExperimenterData exp, Rectangle bounds) {
        TreeViewerModel model = new TreeViewerModel(exp);
        return singleton.getTreeViewer(model, bounds);
    }

    /** Close all the instances.*/
    public static void terminate() {
        singleton.shutDown();
    }

    /** Writes the external applications used to open document. */
    public static void writeExternalApplications() {
        if (singleton.applications == null || singleton.applications.size() == 0)
            return;
        try {
            Environment env = (Environment) TreeViewerAgent.getRegistry().lookup(LookupNames.ENV);
            String name = env.getOmeroHome() + File.separator + FILE_NAME;
            File f = new File(name);
            if (f.exists())
                f.delete();
            BufferedWriter output = new BufferedWriter(new FileWriter(name));
            Entry entry;
            Iterator i = singleton.applications.entrySet().iterator();
            String format;
            List list;
            Iterator j;
            ApplicationData data;
            while (i.hasNext()) {
                entry = (Entry) i.next();
                format = (String) entry.getKey();
                list = (List) entry.getValue();
                if (list != null) {
                    j = list.iterator();
                    while (j.hasNext()) {
                        data = (ApplicationData) j.next();
                        output.write(format + SEPARATOR + data.getApplicationPath());
                        output.newLine();
                    }
                }
            }
            if (output != null)
                output.close();
        } catch (Exception e) {
            LogMessage msg = new LogMessage();
            msg.print("An error occurred while writing the external " + "applications back to the file.");
            msg.print(e);
            TreeViewerAgent.getRegistry().getLogger().error(TreeViewerFactory.class, msg);
        }
    }

    /** The tracked component. */
    //private TreeViewer     viewer;

    /** The tracked components. */
    private Set<TreeViewer> viewers;

    /** The windows menu. */
    private JMenu windowMenu;

    /** 
     * Indicates if the {@link #windowMenu} is attached to the 
     * <code>TaskBar</code>.
     */
    private boolean isAttached;

    /** The external applications used to open file or images. */
    private Map<String, List<ApplicationData>> applications;

    /** The comparator used to sort the applications. */
    private StringComparator comparator;

    /** Creates a new instance. */
    private TreeViewerFactory() {
        //viewer = null;
        applications = null;
        viewers = new HashSet<TreeViewer>();
        isAttached = false;
        windowMenu = new JMenu(MENU_NAME);
        comparator = new StringComparator();
    }

    private void shutDown() {
        Set<TreeViewer> viewers = singleton.viewers;
        Iterator<TreeViewer> i = viewers.iterator();
        TreeViewer viewer;
        while (i.hasNext()) {
            viewer = i.next();
            ((TreeViewerComponent) viewer).shutDown();
            //viewer.removeChangeListener(this);
            //viewer.discard();
        }
        viewers.clear();
    }

    /**
     * Creates or recycles a viewer component for the specified 
     * <code>model</code>.
     * 
     * @param model    The Model.
     * @param bounds   The bounds of the component invoking a new
     *                   {@link TreeViewer}. 
     * @return A {@link TreeViewer}.
     */
    private TreeViewer getTreeViewer(TreeViewerModel model, Rectangle bounds) {
        Iterator v = viewers.iterator();
        TreeViewerComponent comp;
        while (v.hasNext()) {
            comp = (TreeViewerComponent) v.next();
            comp.setRecycled(true);
            return comp;
        }
        //if (viewer != null) return viewer;
        readExternalApplications();
        comp = new TreeViewerComponent(model);
        model.initialize(comp);
        comp.initialize(bounds);
        //viewer = component;
        comp.addChangeListener(this);
        viewers.add(comp);
        return comp;
    }

    /** Reads the file hosting the external applications. */
    private void readExternalApplications() {
        if (applications != null)
            return;
        applications = new HashMap<String, List<ApplicationData>>();

        Environment env = (Environment) TreeViewerAgent.getRegistry().lookup(LookupNames.ENV);
        String name = FilenameUtils.concat(env.getOmeroHome(), FILE_NAME);

        File f = new File(name);
        if (!f.exists())
            return;
        try {
            BufferedReader input = new BufferedReader(new FileReader(f));
            try {
                String line = null;
                String mimeType;
                String[] values;
                int index;
                StringBuffer buffer;
                List<ApplicationData> list;
                while ((line = input.readLine()) != null) {
                    if (line.contains(SEPARATOR)) {
                        values = line.split(SEPARATOR);
                        if (values.length >= 2) {
                            mimeType = values[0];
                            index = 1;
                            buffer = new StringBuffer();
                            for (int i = 1; i < values.length; i++) {
                                buffer.append(values[i]);
                                if (index != values.length - 1)
                                    buffer.append(SEPARATOR);
                                index++;
                            }
                            list = applications.get(mimeType);
                            if (list == null) {
                                list = new ArrayList<ApplicationData>();
                                applications.put(mimeType, list);
                            }
                            File application = new File(buffer.toString());
                            list.add(new ApplicationData(application));
                        }
                    }
                }

                //sort out the list.
                Iterator<String> k = applications.keySet().iterator();
                while (k.hasNext()) {
                    list = applications.get(k.next());
                    Collections.sort(list, singleton.comparator);
                }
            } finally {
                input.close();
            }
        } catch (Exception e) {
            LogMessage msg = new LogMessage();
            msg.print("An error occurred while reading the external " + "applications file.");
            msg.print(e);
            TreeViewerAgent.getRegistry().getLogger().error(TreeViewerFactory.class, msg);
        }

    }

    /**
     * Sets the {@link #viewer} to <code>null</code> when it is
     * {@link TreeViewer#DISCARDED discarded}. 
     * @see ChangeListener#stateChanged(ChangeEvent)
     */
    public void stateChanged(ChangeEvent ce) {
        TreeViewerComponent comp = (TreeViewerComponent) ce.getSource();
        if (comp.getState() == TreeViewer.DISCARDED)
            viewers.remove(comp);
    }

}