/* *------------------------------------------------------------------------------ * Copyright (C) 2006-2015 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.env.ui; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.swing.JFrame; import javax.swing.JOptionPane; import org.openmicroscopy.shoola.util.CommonsLangUtils; import org.openmicroscopy.shoola.env.Container; import org.openmicroscopy.shoola.env.LookupNames; import org.openmicroscopy.shoola.env.config.Registry; import omero.gateway.SecurityContext; import org.openmicroscopy.shoola.env.event.EventBus; import omero.log.LogMessage; import omero.log.Logger; import org.openmicroscopy.shoola.svc.SvcRegistry; import org.openmicroscopy.shoola.svc.communicator.Communicator; import org.openmicroscopy.shoola.svc.communicator.CommunicatorDescriptor; import org.openmicroscopy.shoola.svc.transport.HttpChannel; import org.openmicroscopy.shoola.util.ui.MessengerDetails; import org.openmicroscopy.shoola.util.ui.MessengerDialog; import org.openmicroscopy.shoola.util.ui.UIUtilities; import omero.gateway.model.ExperimenterData; /** * Acts a controller. Listens to property changes fired by the * <code>MessengerDialog</code>s. * * @author Jean-Marie Burel      * <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a> * @author Donald MacDonald      * <a href="mailto:donald@lifesci.dundee.ac.uk">donald@lifesci.dundee.ac.uk</a> * @version 3.0 * @since OME3.0 */ class UserNotifierManager implements PropertyChangeListener { /** The default message if an error occurred while transferring data. */ private static final String MESSAGE_START = "Sorry, but due to an error " + "we were not able to automatically \n"; /** The default message if an error occurred while transferring data. */ private static final String MESSAGE_END = "\n\n"+ "You can still send us the error message by " + "clicking on the \n" + "error message tab, copying the error " + "message to the clipboard, \n" + "and sending it to "; /** Message if the dialog's type is {@link MessengerDialog#ERROR_TYPE}. */ private static final String ERROR_MSG = "send your debug information."; /** Message if the dialog's type is {@link MessengerDialog#COMMENT_TYPE}. */ private static final String COMMENT_MSG = "send your comment."; /** Reply when sending the comments. */ private static final String COMMENT_REPLY = "Thanks, your comments have " + "been successfully posted."; /** Reply when sending the error message. */ private static final String ERROR_REPLY = "Thanks, the error message " + "has been successfully posted."; /** Default title for the comment dialog. */ private static final String DEFAULT_COMMENT_TITLE = "Comment"; /** Reference to the container. */ private Container container; /** Back pointer to the component. */ private UserNotifier component; /** Map keeping track of the ongoing data loading. */ private Map<String, UserNotifierLoader> loaders; /** The Dialog used to send comments. */ private MessengerDialog commentDialog; /** The dialog keeping track of the activity files. */ private DownloadsDialog activityDialog; /** The collection of running activities. */ private List<ActivityComponent> activities; /** * Returns the invoker depending on which application is running e.g. * insight, importer or editor. * * @param comment Pass <code>true</code> to return the invoker for the * comments, <code>false </code> * * @return */ private String getInvoker(boolean comment) { Registry reg = container.getRegistry(); String master = (String) reg.lookup(LookupNames.MASTER); if (comment) { if (LookupNames.MASTER_IMPORTER.equals(master)) return "importer_comments"; return "insight_comments"; } if (LookupNames.MASTER_IMPORTER.equals(master)) return "importer_bugs"; return "insight_bugs"; } /** * Sends a message. * * @param source The source of the message. * @param details The values to send. */ private void handleSendMessage(MessengerDialog source, MessengerDetails details) { Registry reg = container.getRegistry(); if (details.getObjectToSubmit() != null) { ExperimenterData exp = (ExperimenterData) reg.lookup( LookupNames.CURRENT_USER_DETAILS); SecurityContext ctx = new SecurityContext( exp.getDefaultGroup().getId()); FileUploader loader = new FileUploader(component, container.getRegistry(), ctx, source, details); loader.load(); return; } boolean bug = true; String error = details.getError(); if (CommonsLangUtils.isBlank(error)) bug = false; String url = (String) reg.lookup(LookupNames.TOKEN_URL); String appName; if (bug) appName = (String) reg.lookup(LookupNames.APPLICATION_NAME_BUG); else appName = (String) reg.lookup(LookupNames.APPLICATION_NAME_COMMENT); CommunicatorDescriptor desc = new CommunicatorDescriptor (HttpChannel.CONNECTION_PER_REQUEST, url, -1); Object version = reg.lookup(LookupNames.VERSION); String v = ""; if (version != null && version instanceof String) v = (String) version; try { Communicator c = SvcRegistry.getCommunicator(desc); StringBuilder builder = new StringBuilder(); String reply = ""; String invoker = getInvoker(bug); if (!bug) c.submitComment(invoker, details.getEmail(), details.getComment(), details.getExtra(), appName, v, builder); else c.submitError(invoker, details.getEmail(), details.getComment(), details.getExtra(), error, appName, v, builder); if (!bug) reply = COMMENT_REPLY; else reply = ERROR_REPLY; JOptionPane.showMessageDialog(source, reply); } catch (Exception e) { LogMessage msg = new LogMessage(); msg.println("Failed to send message."); msg.println("Reason: "+e.getMessage()); Logger logger = container.getRegistry().getLogger(); logger.error(this, msg); String s = MESSAGE_START; if (source.getDialogType() == MessengerDialog.ERROR_TYPE) s += ERROR_MSG; else s += COMMENT_MSG; String address = (String) container.getRegistry().lookup(LookupNames.DEBUGGER_ADDRESS); if (address != null && address.trim().length() > 0) { s += MESSAGE_END; s += address; s += "."; } JOptionPane.showMessageDialog(source, s); } source.setVisible(false); source.dispose(); } /** Creates the activity dialog. */ private void createActivity() { if (activityDialog != null) return; Registry reg = getRegistry(); JFrame f = reg.getTaskBar().getFrame(); activityDialog = new DownloadsDialog(f, IconManager.getInstance(reg), DownloadsDialog.ACTIVITY); } /** * Creates a new instance. * * @param component Back pointer to the component. * @param c Reference to the container. */ UserNotifierManager(UserNotifier component, Container c) { container = c; this.component = component; loaders = new HashMap<String, UserNotifierLoader>(); JFrame f = getRegistry().getTaskBar().getFrame(); if (f != null) f.addPropertyChangeListener(TaskBarManager.ACTIVITIES_PROPERTY, this); } /** * Returns the details of the user currently logged in if any. * * @return See above. */ ExperimenterData getExperimenter() { Object exp = container.getRegistry().lookup(LookupNames.CURRENT_USER_DETAILS); if (exp == null) return null; return (ExperimenterData) exp; } /** * Registers the passed activity. * * @param activity The activity to register. * @param uiRegister Pass <code>true</code> to display the activity in the * activity dialog, <code>false</code> otherwise. */ void registerActivity(ActivityComponent activity, boolean uiRegister) { if (activity == null) return; if (uiRegister) { createActivity(); activityDialog.addActivityEntry(activity); showActivity(); } if (activities == null) activities = new ArrayList<ActivityComponent>(); activity.addPropertyChangeListener(this); activities.add(activity); } /** * Returns the version number of the server. * * @return See above. */ String getServerVersion() { if (container == null) return ""; String name = container.getRegistry().getAdminService().getServerName(); if (name == null) name = ""; String version = container.getRegistry().getAdminService().getServerVersion(); if (name == null || name.trim().length() == 0) return ""; if (version == null || version.trim().length() == 0) version = "not available"; return "Server name: "+name+", version: "+version; } /** * Returns the reference to the registry. * * @return See above. */ Registry getRegistry() { return container.getRegistry(); } /** * Creates or recycles the messenger dialog. * * @param frame The owner of the dialog. * @param email The e-mail address. * @return See above. */ MessengerDialog getCommentDialog(JFrame frame, String email) { if (commentDialog != null) return commentDialog; commentDialog = new MessengerDialog(frame, DEFAULT_COMMENT_TITLE, email); commentDialog.setServerVersion(getServerVersion()); commentDialog.addPropertyChangeListener(this); commentDialog.setModal(false); commentDialog.setAlwaysOnTop(false); return commentDialog; } /** Displays the activity window. */ void showActivity() { if (activityDialog == null) createActivity(); if (!activityDialog.isVisible()) UIUtilities.centerAndShow(activityDialog); activityDialog.requestFocusInWindow(); activityDialog.toFront(); } /** * Returns the number of running activities. * * @return See above. */ int getRunningActivitiesCount() { if (activities == null) return 0; return activities.size(); } /** * Removes all activities */ void clearActivities() { if (activities != null) activities.clear(); if (activityDialog != null) { activityDialog.setVisible(false); activityDialog = null; } } /** * Starts the specified activity. * * @param start Pass <code>true</code> to update view, <code>false</code> * otherwise. * @param comp The component to activate. */ void startActivity(boolean start, ActivityComponent comp) { if (comp == null) return; if (start) comp.startActivity(); EventBus bus = getRegistry().getEventBus(); bus.post(new ActivityProcessEvent(comp, false)); UserNotifierLoader loader = comp.createLoader(); if (loader != null) loader.load(); } /** * Returns <code>true</code> if there is an on-going activity of * the specified type, <code>false</code> otherwise. * * @param type The type of activity to handle. * @return See above. */ boolean hasRunningActivityOfType(Class type) { if (type == null || getRunningActivitiesCount() == 0) return false; if (ExportActivity.class.equals(type)) { Iterator<ActivityComponent> i = activities.iterator(); ActivityComponent ac; while (i.hasNext()) { ac = i.next(); if (ExportActivity.class.equals(ac.getClass())) return true; } } return false; } /** * Reacts to property changes fired by dialogs. * @see PropertyChangeListener#propertyChange(PropertyChangeEvent) */ public void propertyChange(PropertyChangeEvent pce) { String name = pce.getPropertyName(); if (MessengerDialog.SEND_PROPERTY.equals(name)) { MessengerDialog source = (MessengerDialog) pce.getSource(); handleSendMessage(source, (MessengerDetails) pce.getNewValue()); } else if (MessengerDialog.CLOSE_MESSENGER_PROPERTY.equals(name)) { commentDialog = null; } else if (OpeningFileDialog.SAVE_TO_DISK_PROPERTY.equals(name)) { /* Object value = pce.getNewValue(); if (value instanceof FileAnnotationData) saveFileToDisk((FileAnnotationData) value); */ } else if (DownloadsDialog.CANCEL_LOADING_PROPERTY.equals(name)) { String fileName = (String) pce.getNewValue(); UserNotifierLoader loader = loaders.get(fileName); if (loader != null) loader.cancel(); } else if (ActivityComponent.UNREGISTER_ACTIVITY_PROPERTY.equals(name)) { ActivityComponent c = (ActivityComponent) pce.getNewValue(); if (c != null) activities.remove(c); //Depending on the activity check if need to do another one. if (c instanceof ExportActivity) { Iterator<ActivityComponent> i = activities.iterator(); ActivityComponent ac; while (i.hasNext()) { ac = i.next(); if (ExportActivity.class.equals(ac.getClass())) { startActivity(true, ac); break; } } } } } }