/* *------------------------------------------------------------------------------ * 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.agents.metadata.view; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Map.Entry; import org.apache.commons.collections.CollectionUtils; import org.openmicroscopy.shoola.agents.metadata.AdminEditor; import org.openmicroscopy.shoola.agents.metadata.DataBatchSaver; import org.openmicroscopy.shoola.agents.metadata.DataSaver; import org.openmicroscopy.shoola.agents.metadata.ExperimenterEditor; import org.openmicroscopy.shoola.agents.metadata.GroupEditor; import org.openmicroscopy.shoola.agents.metadata.MetadataLoader; import org.openmicroscopy.shoola.agents.metadata.ContainersLoader; import org.openmicroscopy.shoola.agents.metadata.MetadataViewerAgent; import org.openmicroscopy.shoola.agents.metadata.RenderingSettingsLoader; import org.openmicroscopy.shoola.agents.metadata.StructuredDataLoader; import org.openmicroscopy.shoola.agents.metadata.ThumbnailLoader; import org.openmicroscopy.shoola.agents.metadata.browser.Browser; import org.openmicroscopy.shoola.agents.metadata.browser.BrowserFactory; import org.openmicroscopy.shoola.agents.metadata.browser.TreeBrowserSet; import org.openmicroscopy.shoola.agents.metadata.editor.Editor; import org.openmicroscopy.shoola.agents.metadata.editor.EditorFactory; import org.openmicroscopy.shoola.agents.metadata.rnd.Renderer; import org.openmicroscopy.shoola.agents.metadata.util.DataToSave; import org.openmicroscopy.shoola.agents.util.EditorUtil; import org.openmicroscopy.shoola.env.data.OmeroMetadataService; import org.openmicroscopy.shoola.env.data.model.AdminObject; import org.openmicroscopy.shoola.env.data.model.MovieExportParam; import omero.gateway.SecurityContext; import org.openmicroscopy.shoola.env.data.util.StructuredDataResults; import org.openmicroscopy.shoola.env.rnd.RndProxyDef; import omero.gateway.exception.DSAccessException; import omero.gateway.exception.DSOutOfServiceException; import omero.gateway.model.AnnotationData; import omero.gateway.model.DataObject; import omero.gateway.model.DatasetData; import omero.gateway.model.ExperimenterData; import omero.gateway.model.FileAnnotationData; import omero.gateway.model.GroupData; import omero.gateway.model.ImageData; import omero.gateway.model.PlateAcquisitionData; import omero.gateway.model.PlateData; import omero.gateway.model.ProjectData; import omero.gateway.model.ScreenData; import omero.gateway.model.WellSampleData; /** * The Model component in the <code>MetadataViewer</code> MVC triad. * This class tracks the <code>MetadataViewer</code>'s state and knows how to * initiate data retrievals. It also knows how to store and manipulate * the results. This class provides a suitable data loader. * The {@link MetadataViewerComponent} intercepts the results of data loadings, * feeds them back to this class and fires state transitions as appropriate. * * @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 MetadataViewerModel { /** Holds one of the state flags defined by {@link MetadataViewer}. */ private int state; /** Reference to the component that embeds this model. */ private MetadataViewer component; /** The object of reference for the viewer i.e. the root. */ private Object refObject; /** The object of reference for the viewer i.e. the root. */ private Object parentRefObject; /** The object of reference for the viewer i.e. the root. */ private Object grandParent; /** The object hosting the various annotations linked to an object. */ private Map<DataObject, StructuredDataResults> data; /** The object hosting the various annotations linked to an object. */ private StructuredDataResults parentData; /** Reference to the browser. */ private Browser browser; /** Reference to the editor. */ private Editor editor; /** Use to load annotations when multiple objects are selected.*/ private StructuredDataLoader multiDataLoader; /** Only used when it is a batch call. */ private Class dataType; /** * Flag indicating the selection mode, <code>true</code> * if single selection, <code>false</code> otherwise. */ private boolean singleMode; /** Collection of nodes related to the node of reference. */ private List<DataObject> relatedNodes; /** * One of the Rendering constants defined by the * <code>MetadataViewer</code> interface. */ private int index; /** * The id of the possible owner, this should only be used * to handle unregistered objects. */ private long userID; /** The collection of rendering settings related to the image. */ private Map viewedBy; /** The security context.*/ private SecurityContext ctx; /** The number of loader used.*/ private int loaderID; /** The active loaders.*/ private Map<Integer, MetadataLoader> loaders; /** The alternative rendering settings.*/ private RndProxyDef def; /** The selected rendering settings in "User Settings".*/ private long selectedViewedByDef; /** * Creates a new context if <code>null</code>. * * @param ho The node to handle. * @return See above. */ private SecurityContext retrieveContext(DataObject ho) { if (ho == null && ctx != null) return ctx; return new SecurityContext(ho.getGroupId()); } /** * Returns the loader's ID if any corresponding to the class. * * @param refClass The class of reference. * @return See above. */ private Integer getLoaderID(Class refClass) { Entry<Integer, MetadataLoader> e; Iterator<Entry<Integer, MetadataLoader>> i = loaders.entrySet().iterator(); while (i.hasNext()) { e = i.next(); if (e.getValue().getClass().equals(refClass)) return e.getKey(); } return null; } /** * Returns the collection of the attachments linked to the * <code>DataObject</code>. * * @return See above. */ private List<FileAnnotationData> getTabularData() { StructuredDataResults data = getStructuredData(); List<FileAnnotationData> l = new ArrayList<FileAnnotationData>(); if (data == null) return l; Collection<FileAnnotationData> attachments = data.getAttachments(); if (attachments == null) return l; Iterator<FileAnnotationData> i = attachments.iterator(); FileAnnotationData f; String ns; while (i.hasNext()) { f = i.next(); ns = f.getNameSpace(); if (FileAnnotationData.BULK_ANNOTATIONS_NS.equals(ns)) { l.add(f); } } return l; } /** * Creates a new object and sets its state to {@link MetadataViewer#NEW}. * * @param refObject The reference object. * @param index One of the rendering constants defined by the * <code>MetadataViewer</code> I/F. * @param def The alternative settings if any. * @param selectedViewedByDef The selected viewed elements. */ MetadataViewerModel(Object refObject, int index, RndProxyDef def, long selectedViewedByDef) { state = MetadataViewer.NEW; this.selectedViewedByDef = selectedViewedByDef; switch (index) { case MetadataViewer.RND_GENERAL: case MetadataViewer.RND_SPECIFIC: this.index = index; break; default: this.index = MetadataViewer.RND_GENERAL; } this.def = def; this.refObject = refObject; loaderID = 0; loaders = new HashMap<Integer, MetadataLoader>(); data = null; dataType = null; singleMode = true; userID = MetadataViewerAgent.getUserDetails().getId(); } /** * Returns the selected viewed by def. * * @return See above. */ long getSelectedViewedByDef() { return selectedViewedByDef; } /** * Called by the <code>MetadataViewer</code> after creation to allow this * object to store a back reference to the embedding component. * * @param component The embedding component. */ void initialize(MetadataViewer component) { this.component = component; browser = BrowserFactory.createBrowser(component, refObject); editor = EditorFactory.createEditor(component, refObject, browser); } /** * Returns the id of the user. Only use to handle <code>FileData</code> * objects. * * @return See above. */ long getUserID() { return userID; } /** * Sets the data type, this value is only used for batch annotation. * * @param dataType The value to set. */ void setDataType(Class dataType) { this.dataType = dataType; } /** * Returns the current state. * * @return One of the flags defined by the {@link MetadataViewer} interface. */ int getState() { return state; } /** * Sets the object in the {@link MetadataViewer#DISCARDED} state. * Any ongoing data loading will be cancelled. */ void discard() { state = MetadataViewer.DISCARDED; loaders.entrySet().iterator(); Iterator<Entry<Integer, MetadataLoader>> i = loaders.entrySet().iterator(); MetadataLoader loader; while (i.hasNext()) { loader = i.next().getValue(); if (loader != null) loader.cancel(); } loaders.clear(); if (multiDataLoader != null) multiDataLoader.cancel(); } /** * Sets the object of reference. * * @param refObject The value to set. * @param ctx The security context. */ void setRootObject(Object refObject, SecurityContext ctx) { this.refObject = refObject; this.ctx = ctx; if (ctx == null && refObject instanceof DataObject) { DataObject data = (DataObject) refObject; if (data.getId() >= 0) this.ctx = new SecurityContext(data.getGroupId()); } browser.setRootObject(refObject); editor.setRootObject(refObject); data = null; if (!(refObject instanceof WellSampleData) && parentData != null) { parentData = null; } parentRefObject = null; viewedBy = null; } /** * Sets the parent of the object of reference. * * @param parentRefObject The value to set. * @param grandParent The value to set. */ void setParentRootObject(Object parentRefObject, Object grandParent) { this.parentRefObject = parentRefObject; this.grandParent = grandParent; editor.setParentRootObject(parentRefObject, grandParent); } /** * Returns the parent of the reference object. * * @return See above. */ Object getParentRefObject() { return parentRefObject; } /** * Returns the object of reference. * * @return See above. */ Object getRefObject() { if (data == null) return refObject; return refObject; } /** * Returns the image or <code>null</code> if the primary select * node is an image or a well. * * @return See above. */ ImageData getImage() { ImageData img = null; if (refObject instanceof WellSampleData) img = ((WellSampleData) refObject).getImage(); if (refObject instanceof ImageData) img = (ImageData) refObject; return img; } /** * Returns the <code>Browser</code> displaying the metadata. * * @return See above. */ Browser getBrowser() { return browser; } /** * Returns the <code>Editor</code> displaying the metadata. * * @return See above. */ Editor getEditor() { return editor; } /** * Cancels any ongoing data loading. * * @param loaderID The identifier of the loader. */ void cancel(int loaderID) { MetadataLoader loader = loaders.get(loaderID); if (loader != null) { loader.cancel(); loaders.remove(loaderID); } } /** * Starts the asynchronous retrieval of the attachments related * to the parent node. * * @param refNode The menu node of reference. * @param rootType The type of reference. */ void fireParentLoading(TreeBrowserSet refNode) { Integer id = getLoaderID(ContainersLoader.class); if (id != null) cancel(id); Object ho = refNode.getUserObject(); if (ho instanceof DataObject) { loaderID++; ctx = retrieveContext((DataObject) ho); ContainersLoader loader = new ContainersLoader( component, ctx, refNode, ho.getClass(), ((DataObject) ho).getId(), loaderID); loaders.put(loaderID, loader); loader.load(); } } /** * Starts the asynchronous retrieval of the structured data related * to the passed node. * * @param node The node to handle. */ void fireStructuredDataLoading(Object node) { if (!(node instanceof DataObject)) return; if (node instanceof ExperimenterData) return; if (node instanceof DataObject) { Integer id = getLoaderID(StructuredDataLoader.class); if (id != null) cancel(id); loaderID++; if (node instanceof WellSampleData) { node = ((WellSampleData) node).getImage(); } ctx = retrieveContext((DataObject) node); StructuredDataLoader loader = new StructuredDataLoader(component, ctx, Arrays.asList((DataObject) node), loaderID); loaders.put(loaderID, loader); loader.load(); state = MetadataViewer.LOADING_METADATA; } } /** * Returns <code>true</code> if the passed object is the reference object, * <code>false</code> otherwise. * * @param uo The object to compare. * @param ref The object of reference. * @return See above. */ boolean isSameObject(DataObject uo, Object ref) { if (uo == null || !(ref instanceof DataObject)) return false; Class<?> klass = ref.getClass(); DataObject object; if (ref instanceof WellSampleData) { klass = ((WellSampleData) ref).getImage().getClass(); object = ((WellSampleData) ref).getImage(); } else object = (DataObject) ref; Class<?> hoKlass = uo.getClass(); if (uo instanceof WellSampleData) { hoKlass = ((WellSampleData) uo).getImage().getClass(); uo = ((WellSampleData) uo).getImage(); } if (!hoKlass.equals(klass)) return false; return uo.getId() == object.getId(); } /** * Returns <code>true</code> if the passed object is the reference object, * <code>false</code> otherwise. * * @param uo The object to compare. * @return See above. */ boolean isSameObject(Object uo) { if (uo instanceof DataObject) return isSameObject((DataObject) uo, refObject); return false; } /** * Returns the object path i.e. if a dataset is selected, * the name of the project_name of the dataset. * * @return See above. */ String getRefObjectPath() { return getRefObjectName(); } /** * Returns the name of the object if any. * * @return See above. */ String getRefObjectName() { Object ref = getRefObject(); if (ref instanceof ImageData) return ((ImageData) ref).getName(); else if (ref instanceof DatasetData) return ((DatasetData) ref).getName(); else if (ref instanceof ProjectData) return ((ProjectData) ref).getName(); else if (ref instanceof PlateData) return ((PlateData) ref).getName(); else if (ref instanceof ScreenData) return ((ScreenData) ref).getName(); else if (ref instanceof ExperimenterData) return EditorUtil.formatExperimenter((ExperimenterData) ref); else if (ref instanceof GroupData) return ((GroupData) ref).getName(); return ""; } /** * Returns the text indicating what to save. * * @return See above. */ String getInstanceToSave() { Object ref = getRefObject(); String v = ""; if (ref instanceof ImageData) { v = "Image's Data: "; v += EditorUtil.truncate(((ImageData) ref).getName()); } else if (ref instanceof DatasetData) { v = "Dataset's Data: "; v += EditorUtil.truncate(((DatasetData) ref).getName()); } else if (ref instanceof ProjectData) { v = "Project's Data: "; v += EditorUtil.truncate(((ProjectData) ref).getName()); } else if (ref instanceof PlateData) { v = "Plate's Data: "; v += EditorUtil.truncate(((PlateData) ref).getName()); } else if (ref instanceof PlateAcquisitionData) { v = "Run's Data: "; v += EditorUtil.truncate( ((PlateAcquisitionData) ref).getLabel()); } else if (ref instanceof ScreenData) { v = "Screen's Data: "; v += EditorUtil.truncate(((ScreenData) ref).getName()); } else if (ref instanceof ExperimenterData) { v = EditorUtil.formatExperimenter((ExperimenterData) ref); v += "'s details"; } if (ref instanceof GroupData) { v = ((GroupData) ref).getName(); v += "'s details"; } return v; } /** * Fires an asynchronous call to save the data, add (resp. remove) * annotations to (resp. from) the object. * * @param object * The annotation/link to add or remove. * @param metadata * The acquisition metadata to save. * @param data * The object to update. * @param asynch * Pass <code>true</code> to save data asynchronously, * <code>false</code> otherwise. */ void fireSaving(DataToSave object, List<Object> metadata, Collection<DataObject> data, boolean asynch) { List<AnnotationData> toAdd = null; List<Object> toRemove = null; if (object != null) { toAdd = object.getToAdd(); toRemove = object.getToRemove(); } if (asynch) { DataSaver loader = new DataSaver(component, ctx, data, toAdd, toRemove, metadata, loaderID); loaderID++; loaders.put(loaderID, loader); loader.load(); state = MetadataViewer.SAVING; } else { OmeroMetadataService os = MetadataViewerAgent.getRegistry() .getMetadataService(); if (metadata != null) { Iterator<Object> i = metadata.iterator(); while (i.hasNext()) { try { os.saveAcquisitionData(ctx, i.next()); } catch (DSOutOfServiceException e) { handleException(e); } catch (DSAccessException e) { handleException(e); } } } try { os.saveBatchData(ctx, data, toAdd, toRemove, userID); } catch (DSOutOfServiceException e) { handleException(e); } catch (DSAccessException e) { handleException(e); } } } /** * Notifies the user about the exception */ private void handleException(Exception e) { MetadataViewerAgent .getRegistry() .getUserNotifier() .notifyError("Could not save metadata", "Could not save metadata before closing application.", e); } /** * Fires an asynchronous call to update the passed experimenter. * * @param data The object to update. * @param asynch Pass <code>true</code> to save data asynchronously, * <code>false</code> otherwise. */ void fireExperimenterSaving(ExperimenterData data, boolean async) { loaderID++; ctx = retrieveContext(data); ExperimenterEditor loader = new ExperimenterEditor(component, ctx, data, loaderID); loaders.put(loaderID, loader); loader.load(); state = MetadataViewer.SAVING; } /** * Fires an asynchronous call to modify the default group of the * logged in experimenter. * * @param group */ void fireChangeGroup(GroupData group) { SecurityContext c = ctx; if (MetadataViewerAgent.isAdministrator()) c = getAdminContext(); MetadataLoader loader = new GroupEditor(component, c, group, loaderID, GroupEditor.CHANGE); loader.load(); } /** * Fires an asynchronous call to update the passed group. * * @param data The object to update. * @param asynch Pass <code>true</code> to save data asynchronously, * <code>false</code> otherwise. */ void fireAdminSaving(AdminObject data, boolean asynch) { SecurityContext c = ctx; if (MetadataViewerAgent.isAdministrator()) c = getAdminContext(); MetadataLoader loader; GroupData group = data.getGroup(); switch (data.getIndex()) { case AdminObject.UPDATE_GROUP: loaderID++; loader = new GroupEditor(component, c, group, data.getPermissions(), loaderID, GroupEditor.UPDATE); loaders.put(loaderID, loader); loader.load(); state = MetadataViewer.SAVING; break; case AdminObject.UPDATE_EXPERIMENTER: loaderID++; loader = new AdminEditor(component, c, data.getGroup(), data.getExperimenters(), loaderID); loaders.put(loaderID, loader); loader.load(); state = MetadataViewer.SAVING; } } /** * Sets the structured data. * * @param data The value to set. * @param loaderID The identifier of the loader */ void setStructuredDataResults(Map<DataObject, StructuredDataResults> data, int loaderID) { loaders.remove(loaderID); this.data = data; state = MetadataViewer.READY; } /** * Sets the structured data of the parent. * * @param parentData The value to set. * @param refNode The node of reference. */ void setParentDataResults(StructuredDataResults parentData, DataObject node, int loaderID) { loaders.remove(loaderID); this.parentData = parentData; state = MetadataViewer.READY; } /** * Returns the structured data. * * @return See above. */ StructuredDataResults getStructuredData() { return getStructuredData(refObject); } /** * Returns the structured data. * * @param object The object to * @return See above. */ StructuredDataResults getStructuredData(Object object) { if (data == null) return null; if (object instanceof DataObject) { if (object instanceof WellSampleData) object = ((WellSampleData) object).getImage(); return data.get((DataObject) object); } return null; } /** * Returns the structured data. * * @return See above. */ StructuredDataResults getParentStructuredData() { return parentData; } /** * Returns <code>true</code> if the imported set of pixels has been * archived, <code>false</code> otherwise. * * @return See above. */ boolean isArchived() { if (!(refObject instanceof ImageData)) return false; ImageData img = (ImageData) refObject; return img.isArchived(); } /** * Fires an asynchronous call to save the objects contained * in the passed <code>DataObject</code> to save, add (resp. remove) * annotations to (resp. from) the object. * * @param toAdd Collection of annotations to add. * @param toRemove Collection of annotations to remove. * @param toSave Collection of data objects to handle. */ void fireBatchSaving(List<AnnotationData> toAdd, List<Object> toRemove, Collection<DataObject> toSave) { DataBatchSaver loader = new DataBatchSaver(component, ctx, toSave, toAdd, toRemove, loaderID); loader.load(); loaderID++; state = MetadataViewer.BATCH_SAVING; } /** * Sets to <code>true</code> if the model is in single mode, * to <code>false</code> otherwise. * * @param singleMode The value to set. */ void setSelectionMode(boolean singleMode) { this.singleMode = singleMode; if (singleMode) relatedNodes = null; } /** * Returns <code>true</code> if the model is in single mode, * <code>false</code> otherwise. * * @return See above. */ boolean isSingleMode() { return singleMode; } /** * Sets the nodes related to the object of reference. * * @param relatedNodes The value to set. */ void setRelatedNodes(List<DataObject> relatedNodes) { this.relatedNodes = relatedNodes; if (CollectionUtils.isEmpty(relatedNodes)) return; DataObject ho = relatedNodes.get(0); List<DataObject> l = new ArrayList<DataObject>(); if (ho instanceof WellSampleData) { Iterator<DataObject> i = relatedNodes.iterator(); while (i.hasNext()) { l.add(((WellSampleData) i.next()).getImage()); } } else l.addAll(relatedNodes); loaderID++; ctx = retrieveContext(ho); StructuredDataLoader loader = new StructuredDataLoader(component, ctx, l, loaderID); loaders.put(loaderID, loader); loader.load(); state = MetadataViewer.LOADING_METADATA; } /** * Returns the nodes related to the object of reference. * * @return See above. */ List<DataObject> getRelatedNodes() { return relatedNodes; } /** * Sets the state. * * @param state The value to set. */ void setState(int state) { this.state = state; } /** * Starts an asynchronous retrieval of the containers hosting the * currently edited object. * * @param type The type of the edited object. * @param id The id of the currently edited object. */ void loadParents(Class type, long id) { loaderID++; ContainersLoader loader = new ContainersLoader(component, ctx, type, id, loaderID); loaders.put(loaderID, loader); loader.load(); } /** * Starts an asynchronous call to create a movie. * * @param parameters The movie parameters. */ void createMovie(MovieExportParam parameters) { if (parameters == null) return; if (!(refObject instanceof ImageData)) return; } /** * Returns the rendering index. * * @return See above. */ int getIndex() { return index; } /** * Returns the instrument transfer function linked to the edited object. * * @return See above */ FileAnnotationData getIRF() { if (!(refObject instanceof ImageData)) return null; if (data == null) return null; Collection<FileAnnotationData> l = getStructuredData().getAttachments(); if (l == null || l.size() == 0) return null; Iterator<FileAnnotationData> i = l.iterator(); FileAnnotationData fa; while (i.hasNext()) { fa = i.next(); if (fa.getFileName().contains("irf")) return fa; } return null; } /** * Returns <code>true</code> if it is an image with a lot of channels. * <code>false</code> otherwise. * * @return See above. */ boolean isNumerousChannel() { if (!(refObject instanceof ImageData)) return false; ImageData img = (ImageData) refObject; return img.getDefaultPixels().getSizeC() >= Renderer.MAX_CHANNELS; } /** * Sets the id of the possible owner. This should only be used for * unregistered objects. * * @param userID The value to set. */ void setUserID(long userID) { this.userID = userID; } /** * Returns the rendering settings associated to the image. * * @return See above. */ Map getViewedBy() { return viewedBy; } /** * Sets the rendering settings associated to the image. * * @param viewedBy The value to set. */ void setViewedBy(Map viewedBy) { Map m = new LinkedHashMap(); if (viewedBy != null) { long id = MetadataViewerAgent.getUserDetails().getId(); Entry entry; Iterator i = viewedBy.entrySet().iterator(); ExperimenterData exp; while (i.hasNext()) { entry = (Entry) i.next(); exp = (ExperimenterData) entry.getKey(); if (exp.getId() == id) { m.put(exp, entry.getValue()); } } i = viewedBy.entrySet().iterator(); while (i.hasNext()) { entry = (Entry) i.next(); exp = (ExperimenterData) entry.getKey(); if (exp.getId() != id) { m.put(exp, entry.getValue()); } } } this.viewedBy = m; } /** * Starts an asynchronous call to load all rendering settings * associated to the image and triggers the viewedby items creation */ void fireViewedByLoading() { ImageData img = null; if (refObject instanceof ImageData) img = (ImageData) refObject; else if (refObject instanceof WellSampleData) img = ((WellSampleData) refObject).getImage(); if (img == null) return; Renderer rnd = getEditor().getRenderer(); if (rnd == null) { // nothing to do if the renderer has not been set yet return; } getEditor().getRenderer().loadRndSettings(false, null); loaderID++; ctx = retrieveContext(img); RenderingSettingsLoader loader = new RenderingSettingsLoader(component, ctx, img.getDefaultPixels().getId(), loaderID, RenderingSettingsLoader.TASK_VIEWEDBY); loaders.put(loaderID, loader); loader.load(); } /** * Starts an asynchronous call to load the rendering settings of * an image to copy the settings from, and applies the settings to * the renderer (does not save them). * See also {@link #setCopyRenderingSettingsFrom(ImageData)} */ void fireLoadRndSettings() { if(!hasRndSettingsCopied()) return; ImageData copyRenderingSettingsFrom = MetadataViewerFactory.getCopyRenderingSettingsFrom(); RndProxyDef copiedRndSettings = MetadataViewerFactory.getCopiedRndSettings(); if (copiedRndSettings != null) { applyRenderingSettings(copiedRndSettings); return; } if(copyRenderingSettingsFrom==null) return; if(ctx==null) ctx = retrieveContext((DataObject)refObject); RenderingSettingsLoader loader = new RenderingSettingsLoader(component, ctx, copyRenderingSettingsFrom.getDefaultPixels().getId(), loaderID, RenderingSettingsLoader.TASK_COPY_PASTE); loaders.put(loaderID, loader); loader.load(); } /** Starts an asynchronous retrieval of the thumbnails. */ void fireThumbnailsLoading() { if (viewedBy == null) return; ImageData image = null; if (refObject instanceof ImageData) image = (ImageData) refObject; else if (refObject instanceof WellSampleData) image = ((WellSampleData) refObject).getImage(); if (image == null) return; Set experimenters = viewedBy.keySet(); Set<Long> ids = new HashSet<Long>(); Iterator i = experimenters.iterator(); while (i.hasNext()) { ids.add(((ExperimenterData) i.next()).getId()); } if (ids.size() == 0) return; loaderID++; ctx = retrieveContext(image); ThumbnailLoader loader = new ThumbnailLoader(component, ctx, image, ids, loaderID); loaders.put(loaderID, loader); loader.load(); } /** * Applies the specified rendering settings. * * @param rndDef The rendering settings to apply. */ void applyRenderingSettings(RndProxyDef rndDef) { Renderer rnd = getEditor().getRenderer(); if (rnd != null) { rnd.resetSettings(rndDef, true); } } /** * Returns <code>true</code> if the object can be edited, * <code>false</code> otherwise. * * @return See above. */ boolean canEdit() { if (editor == null) return false; return editor.canEdit(); } /** * Returns <code>true</code> if the object can be annotated, * <code>false</code> otherwise. * * @return See above. */ boolean canAnnotate() { if (editor == null) return false; return editor.canAnnotate(); } /** * Returns <code>true</code> if the object can be hard linked, * i.e. image added to dataset, <code>false</code> otherwise. * * @return See above. */ boolean canLink() { if (editor == null) return false; return editor.canLink(); } /** * Returns the security context. * * @return See above. */ SecurityContext getSecurityContext() { return ctx; } /** * Returns the security context. * * @return See above. */ SecurityContext getAdminContext() { if (MetadataViewerAgent.isAdministrator()) return MetadataViewerAgent.getAdminContext(); return null; } /** * Returns the structured data. * * @return See above. */ Map<DataObject, StructuredDataResults> getAllStructuredData() { return data; } /** * Returns <code>true</code> if the collection of specified objects * corresponding to the list of related nodes, <code>false</code> * otherwise. * * @param keys The nodes to handle. * @return See above. */ boolean isSameSelection(Collection<DataObject> keys) { if (keys == null) return false; List<DataObject> nodes = getRelatedNodes(); if (nodes == null) return false; //Check that the selection is still the same. int count = 0; DataObject o; Iterator<DataObject> j = keys.iterator(), k; while (j.hasNext()) { o = j.next(); k = nodes.iterator(); while (k.hasNext()) { if (isSameObject(o, k.next())) { count++; } } } return count == nodes.size() && count == keys.size(); } /** * Returns the user currently logged in. * * @return See above. */ ExperimenterData getCurrentUser() { return MetadataViewerAgent.getUserDetails(); } /** Loads the rendering engine.*/ void loadRnd() { editor.loadRnd(); } /** * Returns if there are copied rendering settings which could be pasted. * * @return See above */ boolean hasRndSettingsCopied() { Renderer rnd = component.getRenderer(); ImageData img = getImage(); ImageData copyRenderingSettingsFrom = MetadataViewerFactory.getCopyRenderingSettingsFrom(); RndProxyDef copiedRndSettings = MetadataViewerFactory.getCopiedRndSettings(); return (copiedRndSettings != null && rnd != null && !rnd.isSameSettings(copiedRndSettings, false)) || (copyRenderingSettingsFrom != null && img != null && copyRenderingSettingsFrom.getId() != img.getId()); } /** * Returns the alternative rendering settings. * * @return See above. */ RndProxyDef getAlternativeRenderingSettings() { return def; } }