/* *------------------------------------------------------------------------------ * Copyright (C) 2006-2016 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.data; import java.io.File; import java.sql.Timestamp; 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.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import ome.formats.model.UnitsFactory; import omero.model.PlateAnnotationLink; import ome.model.units.BigResult; import omero.cmd.OriginalMetadataRequest; import omero.cmd.Request; import omero.model.Annotation; import omero.model.AnnotationAnnotationLink; import omero.model.BooleanAnnotation; import omero.model.Channel; import omero.model.DatasetAnnotationLink; import omero.model.DoubleAnnotation; import omero.model.FileAnnotation; import omero.model.FileAnnotationI; import omero.model.IObject; import omero.model.Image; import omero.model.ImageAnnotationLink; import omero.model.ImagingEnvironment; import omero.model.ImagingEnvironmentI; import omero.model.Length; import omero.model.LogicalChannel; import omero.model.LongAnnotation; import omero.model.MapAnnotation; import omero.model.Medium; import omero.model.NamedValue; import omero.model.Objective; import omero.model.ObjectiveSettings; import omero.model.ObjectiveSettingsI; import omero.model.OriginalFile; import omero.model.Pixels; import omero.model.PlateAcquisitionAnnotationLink; import omero.model.Pressure; import omero.model.ProjectAnnotationLink; import omero.model.ScreenAnnotationLink; import omero.model.StageLabel; import omero.model.StageLabelI; import omero.model.TagAnnotation; import omero.model.TagAnnotationI; import omero.model.Temperature; import omero.model.TermAnnotation; import omero.model.WellAnnotationLink; import omero.model.XmlAnnotation; import omero.sys.Parameters; import omero.sys.ParametersI; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.ListUtils; import org.openmicroscopy.shoola.env.LookupNames; import org.openmicroscopy.shoola.env.config.Registry; import org.openmicroscopy.shoola.env.data.model.AnnotationLinkData; import org.openmicroscopy.shoola.env.data.model.TableParameters; import org.openmicroscopy.shoola.env.data.model.TimeRefObject; import org.openmicroscopy.shoola.env.data.util.FilterContext; import org.openmicroscopy.shoola.env.data.util.ModelMapper; import omero.gateway.util.PojoMapper; import omero.gateway.SecurityContext; import omero.gateway.exception.DSAccessException; import omero.gateway.exception.DSOutOfServiceException; import omero.gateway.model.ROIResult; import omero.gateway.model.TableResult; import org.openmicroscopy.shoola.env.data.util.StructuredDataResults; import omero.gateway.model.AnnotationData; import omero.gateway.model.BooleanAnnotationData; import omero.gateway.model.ChannelAcquisitionData; import omero.gateway.model.ChannelData; import omero.gateway.model.DataObject; import omero.gateway.model.DatasetData; import omero.gateway.model.DoubleAnnotationData; import omero.gateway.model.ExperimenterData; import omero.gateway.model.FileAnnotationData; import omero.gateway.model.FilesetData; import omero.gateway.model.ImageAcquisitionData; import omero.gateway.model.ImageData; import omero.gateway.model.LongAnnotationData; import omero.gateway.model.MapAnnotationData; import omero.gateway.model.PlateData; import omero.gateway.model.ProjectData; import omero.gateway.model.ROIData; import omero.gateway.model.RatingAnnotationData; import omero.gateway.model.TagAnnotationData; import omero.gateway.model.TermAnnotationData; import omero.gateway.model.TextualAnnotationData; import omero.gateway.model.XMLAnnotationData; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; /** * Implementation of the {@link OmeroMetadataService} I/F. * * @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 OmeroMetadataServiceImpl implements OmeroMetadataService { /** Uses it to gain access to the container's services. */ private Registry context; /** Reference to the entry point to access the <i>OMERO</i> services. */ private OMEROGateway gateway; /** * Updates the loaded channels. * * @param ref The modified channels. * @param list The channels to update. */ private void updateChannels(List<ChannelData> ref, List<Channel> list) { Iterator<Channel> i = list.iterator(); Channel channel; ChannelData data; int index = 0; int n = ref.size(); while (i.hasNext()) { channel = i.next(); if (index == n) break; data = ref.get(index); channel.getLogicalChannel().setName(omero.rtypes.rstring( data.getName())); index++; } } /** * Returns <code>true</code> if the value contains the terms specified, * <code>false</code> otherwise. * * @param terms The terms to check. * @param value The value to handle. * @return See above. */ private boolean containTerms(List<String> terms, String value) { if (terms == null || terms.size() == 0 || value == null) return false; Iterator<String> i = terms.iterator(); while (i.hasNext()) { if (value.contains(i.next())) return true; } return false; } /** * Returns <code>true</code> if the annotation is shared, * <code>false</code> otherwise. * * @param ctx The security context. * @param annotation The annotation to handle. * @param object The object to handle. * @return See above. * @throws DSOutOfServiceException If the connection is broken, or logged * in. * @throws DSAccessException If an error occurred while trying to * retrieve data from OMEDS service. */ private boolean isAnnotationShared(SecurityContext ctx, AnnotationData annotation, DataObject object) throws DSOutOfServiceException, DSAccessException { List<Long> ids = new ArrayList<Long>(); ids.add(annotation.getId()); List l = gateway.findAnnotationLinks(ctx, object.getClass(), -1, ids); if (l == null) return false; return l.size() > 0; } /** * Removes the specified annotation from the object. * Returns the updated object. * * @param ctx The security context. * @param annotation The annotation to create. * Mustn't be <code>null</code>. * @param object The object to handle. Mustn't be <code>null</code>. * @return See above. * @throws DSOutOfServiceException If the connection is broken, or logged * in. * @throws DSAccessException If an error occurred while trying to * retrieve data from OMEDS service. */ private void removeAnnotation(SecurityContext ctx, Object annotation, DataObject object) throws DSOutOfServiceException, DSAccessException { if (annotation == null || object == null || (!(annotation instanceof IObject || annotation instanceof DataObject))) return; IObject o = null; if (annotation instanceof IObject) o = (IObject) annotation; else o = ((DataObject) annotation).asIObject(); IObject ho = gateway.findIObject(ctx, o); if (ho == null) return; long id = -1;//getUserDetails().getId(); if (ho instanceof Annotation) { List links = gateway.findAnnotationLinks(ctx, object.getClass(), object.getId(), Arrays.asList(ho.getId().getValue()), id); Iterator i = links.iterator(); IObject link; while (i.hasNext()) { link = (IObject) i.next(); if (link != null && gateway.canDelete(link)) { try { gateway.deleteObject(ctx, link); } catch (Exception e) { } } } } else { if (gateway.canDelete(o)) { try { gateway.deleteObject(ctx, ho); } catch (Exception e) { } } } } /** * Saves the logical channel. * * @param ctx The security context. * @param data The data to save * @throws DSOutOfServiceException If the connection is broken, or logged in * @throws DSAccessException If an error occurred while trying to * retrieve data from OMEDS service. * @throws DSAccessException */ private void saveChannelData(SecurityContext ctx, ChannelData data) throws DSOutOfServiceException, DSAccessException { LogicalChannel lc = data.asChannel().getLogicalChannel(); ModelMapper.unloadCollections(lc); gateway.saveAndReturnObject(ctx, lc, null); } /** * Saves the metadata linked to a logical channel. * * @param ctx The security context. * @param data The data to save * @throws DSOutOfServiceException If the connection is broken, or logged in * @throws DSAccessException If an error occurred while trying to * retrieve data from OMEDS service. * @throws DSAccessException */ private void saveChannelAcquisitionData(SecurityContext ctx, ChannelAcquisitionData data) { //LogicalChannel lc = (LogicalChannel) data.asIObject(); } /** * Saves the metadata linked to an image. * * @param ctx The security context. * @param data The data to save * @throws DSOutOfServiceException If the connection is broken, or logged in * @throws DSAccessException If an error occurred while trying to * retrieve data from OMEDS service. * @throws DSAccessException */ private void saveImageAcquisitionData(SecurityContext ctx, ImageAcquisitionData data) throws DSOutOfServiceException, DSAccessException { Image image = data.asImage(); long id; IObject object; //stage Label List<IObject> toCreate = new ArrayList<IObject>(); List<IObject> toUpdate = new ArrayList<IObject>(); if (data.isStageLabelDirty()) { StageLabel label; id = data.getStageLabelId(); if (id < 0) { //create a new one. label = new StageLabelI(); toCreate.add(label); } else { label = (StageLabel) gateway.findIObject(ctx, StageLabel.class.getName(), id); toUpdate.add(label); } label.setName(omero.rtypes.rstring(data.getLabelName())); Length o = null; try { o = data.getPositionX(UnitsFactory.StageLabel_X); } catch (BigResult e) { context.getLogger().warn( this, "Could not get X position in " + UnitsFactory.StageLabel_X); } if (o != null) label.setPositionX(o); try { o = data.getPositionY(UnitsFactory.StageLabel_Y); } catch (BigResult e) { context.getLogger().warn( this, "Could not get Y position in " + UnitsFactory.StageLabel_Y); } if (o != null) label.setPositionY(o); try { o = data.getPositionZ(UnitsFactory.StageLabel_Z); } catch (BigResult e) { context.getLogger().warn( this, "Could not get Z position in " + UnitsFactory.StageLabel_Z); } if (o != null) label.setPositionZ(o); } //Environment if (data.isImagingEnvironmentDirty()) { id = data.getImagingEnvironmentId(); ImagingEnvironment condition; if (id < 0) { condition = new ImagingEnvironmentI(); toCreate.add(condition); } else { condition = (ImagingEnvironment) gateway.findIObject(ctx, ImagingEnvironment.class.getName(), id); toUpdate.add(condition); } try { Pressure press = data .getAirPressure(UnitsFactory.ImagingEnvironment_AirPressure); if (press != null) condition.setAirPressure(press); } catch (BigResult e) { context.getLogger().warn( this, "Could not get pressure in " + UnitsFactory.ImagingEnvironment_AirPressure); } condition.setHumidity(omero.rtypes.rdouble( data.getHumidity())); try { Temperature o = data .getTemperature(UnitsFactory.ImagingEnvironment_Temperature); if (o != null) condition.setTemperature(o); } catch (BigResult e) { context.getLogger().warn( this, "Could not get temperature in " + UnitsFactory.ImagingEnvironment_Temperature); } condition.setCo2percent(omero.rtypes.rdouble( data.getCo2Percent())); } if (data.isObjectiveSettingsDirty()) { id = data.getObjectiveSettingsId(); ObjectiveSettings settings; if (id < 0) { settings = new ObjectiveSettingsI(); toCreate.add(settings); } else { settings = (ObjectiveSettings) gateway.findIObject(ctx, ObjectiveSettings.class.getName(), id); toUpdate.add(settings); } settings.setCorrectionCollar( omero.rtypes.rdouble(data.getCorrectionCollar())); settings.setRefractiveIndex( omero.rtypes.rdouble(data.getRefractiveIndex())); object = data.getMediumAsEnum(); if (object != null) settings.setMedium((Medium) object); } long objectiveSettingsID = data.getObjectiveSettingsId(); if (toUpdate.size() > 0) { gateway.updateObjects(ctx, toUpdate, new Parameters()); } Iterator<IObject> i; if (toCreate.size() > 0) { List<IObject> l = gateway.createObjects(ctx, toCreate); i = l.iterator(); image = (Image) gateway.findIObject(ctx, data.asIObject()); while (i.hasNext()) { object = i.next(); if (object instanceof StageLabel) image.setStageLabel((StageLabel) object); else if (object instanceof ImagingEnvironment) image.setImagingEnvironment((ImagingEnvironment) object); else if (object instanceof ObjectiveSettings) { objectiveSettingsID = object.getId().getValue(); image.setObjectiveSettings((ObjectiveSettings) object); } } ModelMapper.unloadCollections(image); gateway.updateObject(ctx, image, new Parameters()); } toUpdate.clear(); toCreate.clear(); //Now we can deal with the objective. //objective settings exist if (toUpdate.size() > 0) { gateway.updateObjects(ctx, toUpdate, new Parameters()); } else { //create the object and link it to the objective settings. //and link it to an instrument. List<IObject> l = gateway.createObjects(ctx, toCreate); i = l.iterator(); ObjectiveSettings settings = (ObjectiveSettings) gateway.findIObject(ctx, ObjectiveSettings.class.getName(), objectiveSettingsID); while (i.hasNext()) { object = i.next(); if (object instanceof Objective) settings.setObjective((Objective) object); } ModelMapper.unloadCollections(settings); gateway.updateObject(ctx, settings, new Parameters()); } } /** * Returns the current user's details. * * @return See above. */ private ExperimenterData getUserDetails() { return (ExperimenterData) context.lookup( LookupNames.CURRENT_USER_DETAILS); } /** * Prepares the annotation to add. * * @param ctx The security context. * @param toAdd The collection of annotation to prepare. * @return See above. * @throws DSOutOfServiceException If the connection is broken, or logged in * @throws DSAccessException If an error occurred while trying to * retrieve data from OMEDS service. */ private List<AnnotationData> prepareAnnotationToAdd(SecurityContext ctx, List<AnnotationData> toAdd) throws DSOutOfServiceException, DSAccessException { List<AnnotationData> annotations = new ArrayList<AnnotationData>(); Iterator i; if (toAdd == null || toAdd.size() == 0) return annotations; i = toAdd.iterator(); AnnotationData ann; Annotation iobject = null; FileAnnotationData fileAnn; FileAnnotation fa; OriginalFile of; List<IObject> toCreate = new ArrayList<IObject>(); //TextualAnnotationData desc; AnnotationData tag; //IObject link = null; //DataObject data; while (i.hasNext()) { ann = (AnnotationData) i.next(); if (ann.getId() < 0) { if (ann instanceof FileAnnotationData) { fileAnn = (FileAnnotationData) ann; of = gateway.uploadFile(ctx, fileAnn.getAttachedFile(), fileAnn.getServerFileMimetype(), -1); fa = new FileAnnotationI(); fa.setFile(of); iobject = fa; } else { iobject = ModelMapper.createAnnotation(ann); } if (iobject != null) { boolean added = false; //Check for tagset - tag link if (ann instanceof TagAnnotationData) { TagAnnotationData t = (TagAnnotationData) ann; Set<DataObject> parents = t.getDataObjects(); if (CollectionUtils.isNotEmpty(parents)) { Iterator<DataObject> j = parents.iterator(); DataObject d; IObject link; while (j.hasNext()) { d = j.next(); if (d instanceof TagAnnotationData) { link = ModelMapper.linkParentToChild( t.asIObject(), d.asIObject()); if (link != null) { toCreate.add(link); added = true; } } } } } if (!added) { toCreate.add(iobject); } } } else { if (ann instanceof TagAnnotationData || ann instanceof TermAnnotationData || ann instanceof XMLAnnotationData || ann instanceof MapAnnotationData) { //update description tag = (AnnotationData) ann; ann = (AnnotationData) updateAnnotationData(ctx, tag); } annotations.add(ann); } } if (toCreate.size() > 0) { i = toCreate.iterator(); List<IObject> l = new ArrayList<IObject>(toCreate.size()); while (i.hasNext()) l.add((IObject) i.next()); List<IObject> r = gateway.createObjects(ctx, l); toCreate.clear(); i = r.iterator(); while (i.hasNext()) { Object object = i.next(); if (object instanceof AnnotationAnnotationLink) { AnnotationAnnotationLink link = (AnnotationAnnotationLink) object; annotations.add((AnnotationData) PojoMapper.asDataObject(link.getChild())); } } annotations.addAll(PojoMapper.asDataObjects(r)); } return annotations; } /** * Links the annotation and the data object. * * @param ctx The security context. * @param data The data object to annotate. * @param annotation The annotation to link. * @throws DSOutOfServiceException If the connection is broken, or logged in * @throws DSAccessException If an error occurred while trying to * retrieve data from OMEDS service. */ private synchronized void linkAnnotation(SecurityContext ctx, DataObject data, AnnotationData annotation) throws DSOutOfServiceException, DSAccessException { String ioType = PojoMapper.getModelType(data.getClass()).getName(); IObject ho = gateway.findIObject(ctx, ioType, data.getId()); if (ho == null) return; ModelMapper.unloadCollections(ho); IObject link = null; boolean exist = false; Annotation an = annotation.asAnnotation(); long[] expIds = new long[] { data.getOwner().getId(), getUserDetails().getId() }; if (annotation instanceof TagAnnotationData) { TagAnnotationData tag = (TagAnnotationData) annotation; //tag a tag. if (TagAnnotationData.class.equals(data.getClass())) { link = findAnnotationLink(ctx, AnnotationData.class, tag.getId(), ho.getId().getValue(), expIds); if (link == null) link = ModelMapper.linkAnnotation(an, (Annotation) ho); else exist = true; } else { link = findAnnotationLink(ctx, ho.getClass(), ho.getId().getValue(), tag.getId(), expIds); if (link == null) link = ModelMapper.linkAnnotation(ho, an); else { updateAnnotationData(ctx, tag); exist = true; } } } else if (annotation instanceof MapAnnotationData) { MapAnnotationData map = (MapAnnotationData) annotation; link = findAnnotationLink(ctx, ho.getClass(), ho.getId().getValue(), map.getId(), expIds); if (link == null) link = ModelMapper.linkAnnotation(ho, an); else { updateAnnotationData(ctx, map); exist = true; } } else if (annotation instanceof RatingAnnotationData) { clearAnnotation(ctx, data.getClass(), data.getId(), RatingAnnotationData.class); link = ModelMapper.linkAnnotation(ho, an); } else { link = ModelMapper.linkAnnotation(ho, an); } if (link != null && !exist) gateway.createObject(ctx, link); } /** * Calls {@link OMEROGateway#findAnnotationLink(SecurityContext, Class, long, long, long)} * for multiple {@link ExperimenterData} ids. * @param ctx The {@link SecurityContext} * @param type The class * @param parentID The parent Id * @param childID The child Id * @param userIDs Array of {@link ExperimenterData} ids * @return The link (if found, <code>null</code> otherwise) * @throws DSOutOfServiceException * @throws DSAccessException */ private IObject findAnnotationLink(SecurityContext ctx, Class type, long parentID, long childID, long[] userIDs) throws DSOutOfServiceException, DSAccessException { for (long userID : userIDs) { IObject obj = gateway.findAnnotationLink(ctx, type, parentID, childID, userID); if (obj != null) return obj; } return null; } /** * Updates the passed annotation. * * @param ctx The security context. * @param ann The annotation to update. * @throws DSOutOfServiceException If the connection is broken, or logged in * @throws DSAccessException If an error occurred while trying to * retrieve data from OMEDS service. */ private DataObject updateAnnotationData(SecurityContext ctx, DataObject ann) throws DSOutOfServiceException, DSAccessException { long id; String ioType; if (ann instanceof TagAnnotationData && ann.isDirty()) { TagAnnotationData tag = (TagAnnotationData) ann; id = tag.getId(); ioType = PojoMapper.getModelType(TagAnnotationData.class).getName(); TagAnnotation ho = (TagAnnotation) gateway.findIObject(ctx, ioType, id); ho.setTextValue(omero.rtypes.rstring(tag.getTagValue())); ho.setDescription(omero.rtypes.rstring(tag.getTagDescription())); IObject object = gateway.updateObject(ctx, ho, new Parameters()); return PojoMapper.asDataObject(object); } else if (ann instanceof TermAnnotationData && ann.isDirty()) { TermAnnotationData tag = (TermAnnotationData) ann; id = tag.getId(); ioType = PojoMapper.getModelType(TermAnnotationData.class).getName(); TermAnnotation ho = (TermAnnotation) gateway.findIObject(ctx, ioType, id); ho.setTermValue(omero.rtypes.rstring(tag.getTerm())); ho.setDescription(omero.rtypes.rstring(tag.getTermDescription())); IObject object = gateway.updateObject(ctx, ho, new Parameters()); return PojoMapper.asDataObject(object); } else if (ann instanceof XMLAnnotationData && ann.isDirty()) { XMLAnnotationData tag = (XMLAnnotationData) ann; id = tag.getId(); ioType = PojoMapper.getModelType(XMLAnnotationData.class).getName(); XmlAnnotation ho = (XmlAnnotation) gateway.findIObject(ctx, ioType, id); ho.setTextValue(omero.rtypes.rstring(tag.getText())); ho.setDescription(omero.rtypes.rstring(tag.getDescription())); IObject object = gateway.updateObject(ctx, ho, new Parameters()); return PojoMapper.asDataObject(object); } else if (ann instanceof LongAnnotationData && ann.isDirty()) { LongAnnotationData tag = (LongAnnotationData) ann; id = tag.getId(); ioType = PojoMapper.getModelType(LongAnnotationData.class).getName(); LongAnnotation ho = (LongAnnotation) gateway.findIObject(ctx, ioType, id); ho.setLongValue(omero.rtypes.rlong(tag.getDataValue())); IObject object = gateway.updateObject(ctx, ho, new Parameters()); return PojoMapper.asDataObject(object); } else if (ann instanceof DoubleAnnotationData && ann.isDirty()) { DoubleAnnotationData tag = (DoubleAnnotationData) ann; id = tag.getId(); ioType = PojoMapper.getModelType(DoubleAnnotationData.class).getName(); DoubleAnnotation ho = (DoubleAnnotation) gateway.findIObject(ctx, ioType, id); ho.setDoubleValue(omero.rtypes.rdouble(tag.getDataValue())); IObject object = gateway.updateObject(ctx, ho, new Parameters()); return PojoMapper.asDataObject(object); } else if (ann instanceof BooleanAnnotationData && ann.isDirty()) { BooleanAnnotationData tag = (BooleanAnnotationData) ann; id = tag.getId(); ioType = PojoMapper.getModelType(BooleanAnnotationData.class).getName(); BooleanAnnotation ho = (BooleanAnnotation) gateway.findIObject(ctx, ioType, id); ho.setBoolValue(omero.rtypes.rbool(tag.getValue())); IObject object = gateway.updateObject(ctx, ho, new Parameters()); return PojoMapper.asDataObject(object); } else if (ann instanceof MapAnnotationData && ann.isDirty()) { MapAnnotationData map = (MapAnnotationData) ann; id = map.getId(); ioType = PojoMapper.getModelType(MapAnnotationData.class).getName(); MapAnnotation m = (MapAnnotation) gateway.findIObject(ctx, ioType, id); m.setMapValue((List<NamedValue>) map.getContent()); IObject object = gateway.updateObject(ctx, m, new Parameters()); return PojoMapper.asDataObject(object); } return ann; } /** * Converts the element of the second collection into their corresponding * <code>DataObject</code>s. * * @param all The list hosting the converted object. * @param l The collection of elements to convert. */ private void convert(List<DataObject> all, Collection l) { Iterator i; if (l == null || l.size() == 0) return; i = l.iterator(); IObject object; while (i.hasNext()) { object = (IObject) i.next(); if (object instanceof ProjectAnnotationLink) { all.add(PojoMapper.asDataObject( ((ProjectAnnotationLink) object).getChild())); } else if (object instanceof DatasetAnnotationLink) { all.add(PojoMapper.asDataObject( ((DatasetAnnotationLink) object).getChild())); } else if (object instanceof ImageAnnotationLink) { all.add(PojoMapper.asDataObject( ((ImageAnnotationLink) object).getChild())); } } } /** * Loads the attachments. * * @param ctx The security context. * @param type The type of object the attachment is related to. * @param userID The id of the user. * @return See above. * @throws DSOutOfServiceException If the connection is broken, or logged * in. * @throws DSAccessException If an error occurred while trying to * retrieve data from OMEDS service. */ private Collection loadAllAttachments(SecurityContext ctx, Class type, long userID) throws DSOutOfServiceException, DSAccessException { List<DataObject> all = new ArrayList<DataObject>(); if (type == null) { //retrieve attachment to P/D and I Collection l; l = gateway.findAllAnnotations(ctx, ProjectData.class, userID); if (l != null && l.size() > 0) convert(all, l); l = gateway.findAllAnnotations(ctx, DatasetData.class, userID); if (l != null && l.size() > 0) convert(all, l); l = gateway.findAllAnnotations(ctx, ImageData.class, userID); if (l != null && l.size() > 0) convert(all, l); return getFileAnnotations(ctx, all); } convert(all, gateway.findAllAnnotations(ctx, type, userID)); return getFileAnnotations(ctx, all); } /** * Returns the file annotations. * * @param ctx The security context. * @param annotations The collection to handle. * @return See above. * @throws DSOutOfServiceException * @throws DSAccessException */ private List<AnnotationData> getFileAnnotations(SecurityContext ctx, Collection annotations) throws DSOutOfServiceException, DSAccessException { List<AnnotationData> result = new ArrayList<AnnotationData>(); if (annotations == null || annotations.size() == 0) return result; Iterator i = annotations.iterator(); AnnotationData data; FileAnnotation fa; long fileID; OriginalFile of; while (i.hasNext()) { data = (AnnotationData) i.next(); if (data instanceof FileAnnotationData) { fa = (FileAnnotation) data.asAnnotation(); fileID = fa.getFile().getId().getValue(); of = gateway.getOriginalFile(ctx, fileID); if (of != null) ((FileAnnotationData) data).setContent(of); result.add(data); } } return result; } /** * Creates a new instance. * * @param gateway Reference to the OMERO entry point. * Mustn't be <code>null</code>. * @param registry Reference to the registry. Mustn't be <code>null</code>. */ OmeroMetadataServiceImpl(OMEROGateway gateway, Registry registry) { if (registry == null) throw new IllegalArgumentException("No registry."); if (gateway == null) throw new IllegalArgumentException("No gateway."); context = registry; this.gateway = gateway; } /** * Implemented as specified by {@link OmeroDataService}. * @see OmeroMetadataService#loadRatings(SecurityContext, Class, long, long) */ public Collection loadRatings(SecurityContext ctx, Class type, long id, long userID) throws DSOutOfServiceException, DSAccessException { List<Long> ids = null; if (userID != -1) { ids = new ArrayList<Long>(1); ids.add(userID); } List<Long> nodeIds = new ArrayList<Long>(1); nodeIds.add(id); List<Class> types = new ArrayList<Class>(); types.add(RatingAnnotationData.class); Map map = gateway.loadAnnotations(ctx, type, nodeIds, types, ids, new Parameters()); if (map == null || map.size() == 0) return new ArrayList(); return (Collection) map.get(id); } /** * Organizes the results and load more annotation is required. * * @param ctx The security context. * @param userID The user of reference. * @param annotations The collections of annotations for that object. * @param results Placeholder for the results. * @throws DSOutOfServiceException * @throws DSAccessException */ private void loadStructuredData(SecurityContext ctx, long userID, Collection annotations, StructuredDataResults results, boolean loadLinks) throws DSOutOfServiceException, DSAccessException { Object object = results.getRelatedObject(); if (CollectionUtils.isNotEmpty(annotations)) { List<TextualAnnotationData> texts = new ArrayList<TextualAnnotationData>(); List<TagAnnotationData> tags = new ArrayList<TagAnnotationData>(); List<TermAnnotationData> terms = new ArrayList<TermAnnotationData>(); List<FileAnnotationData> attachments = new ArrayList<FileAnnotationData>(); List<RatingAnnotationData> ratings = new ArrayList<RatingAnnotationData>(); List<XMLAnnotationData> xml = new ArrayList<XMLAnnotationData>(); List<MapAnnotationData> maps = new ArrayList<MapAnnotationData>(); List<AnnotationData> other = new ArrayList<AnnotationData>(); Iterator i = annotations.iterator(); AnnotationData data; BooleanAnnotationData b; Map<Long, AnnotationData> map = new HashMap<Long, AnnotationData>(); //Check link when not owner List<Long> annotationIds = new ArrayList<Long>(); while (i.hasNext()) { data = (AnnotationData) i.next(); if (data instanceof TermAnnotationData) { annotationIds.add(data.getId()); terms.add((TermAnnotationData) data); } else if (data instanceof TextualAnnotationData) texts.add((TextualAnnotationData) data); else if (data instanceof TagAnnotationData) { annotationIds.add(data.getId()); map.put(data.getId(), data); tags.add((TagAnnotationData) data); } else if (data instanceof RatingAnnotationData) ratings.add((RatingAnnotationData) data); else if (data instanceof FileAnnotationData) { annotationIds.add(data.getId()); map.put(data.getId(), data); attachments.add((FileAnnotationData) data); } else if (data instanceof XMLAnnotationData) { annotationIds.add(data.getId()); xml.add((XMLAnnotationData) data); } else if (data instanceof MapAnnotationData) { annotationIds.add(data.getId()); maps.add((MapAnnotationData) data); } else { annotationIds.add(data.getId()); other.add(data); } } //load the links tags and attachments if (loadLinks && annotationIds.size() > 0 && !(object instanceof TagAnnotationData || object instanceof FileAnnotationData)) { List links = gateway.findAnnotationLinks(ctx, object.getClass(), results.getObjectId(), annotationIds, -1); formatAnnotationLinks(links, results); } results.setOtherAnnotation(other); results.setXMLAnnotations(xml); results.setTextualAnnotations(texts); results.setTerms(terms); results.setTags(tags); results.setRatings(ratings); results.setAttachments(attachments); results.setMapAnnotations(maps); } } /** * Implemented as specified by {@link OmeroDataService}. * @see OmeroMetadataService#loadStructuredData(SecurityContext, DataObject, long, boolean) */ public StructuredDataResults loadStructuredData(SecurityContext ctx, Object object, long userID, boolean viewed) throws DSOutOfServiceException, DSAccessException { if (object == null) throw new IllegalArgumentException("Object not valid."); StructuredDataResults results = null; DataObject r = null; if (object instanceof File) { File f = (File) object; DataObject fd = gateway.loadFolder(f.getAbsolutePath()); //load the data object if any. return new StructuredDataResults(fd); } else if (object instanceof DataObject) { r = (DataObject) object; results = new StructuredDataResults(r); } if (r == null) throw new IllegalArgumentException("Data Object not initialized."); Collection annotations = loadStructuredAnnotations(ctx, object.getClass(), r.getId(), userID); loadStructuredData(ctx, userID, annotations, results, true); //in-place import check if (object instanceof ImageData) { ImageData img = (ImageData) object; long fID = img.getFilesetId(); if (fID >=0) { Map<Long, Collection<AnnotationData>> map = loadAnnotations(ctx, FilesetData.class, Arrays.asList(fID), TextualAnnotationData.class, Arrays.asList(AnnotationData.FILE_TRANSFER_NS), null); results.setTransferlinks(map.get(fID)); } } return results; } /** * Implemented as specified by {@link OmeroDataService}. * @see OmeroMetadataService#loadStructuredData(SecurityContext, List, long, boolean) */ public Map<DataObject, StructuredDataResults> loadStructuredData(SecurityContext ctx, List<DataObject> data, long userID, boolean viewed) throws DSOutOfServiceException, DSAccessException { if (data == null) throw new IllegalArgumentException("Object not valid."); Map<DataObject, StructuredDataResults> results = new HashMap<DataObject, StructuredDataResults>(); Iterator<DataObject> i = data.iterator(); DataObject n; List<Long> ids = new ArrayList<Long>(); Class<?> klass = null; List<Long> fids = new ArrayList<Long>(); ImageData img; Multimap<Class<?>, Long> mm = ArrayListMultimap.create(); while (i.hasNext()) { n = i.next(); if (n != null) { ids.add(n.getId()); mm.put(n.getClass(), n.getId()); if (n instanceof ImageData) { img = (ImageData) n; long fID = img.getFilesetId(); if (fID >=0 && !fids.contains(fID)) { fids.add(fID); } } } } Map<Long, Collection<AnnotationData>> filesetMap = new HashMap<Long, Collection<AnnotationData>>(); if (!fids.isEmpty()) { filesetMap = loadAnnotations(ctx, FilesetData.class, fids, TextualAnnotationData.class, Arrays.asList(AnnotationData.FILE_TRANSFER_NS), null); } //load all the annotations List<Long> usersIDs = null; if (userID != -1) { usersIDs = new ArrayList<Long>(1); usersIDs.add(userID); } //Load annotations for (Class<?> k : mm.keySet()) { loadAnnotations(ctx, k, (List) mm.get(k), userID, data, filesetMap, results); } return results; } private void loadAnnotations(SecurityContext ctx, Class<?> klass, List<Long> ids, long userID, List<DataObject> data, Map<Long, Collection<AnnotationData>> filesetMap, Map<DataObject, StructuredDataResults> results) throws DSOutOfServiceException, DSAccessException { List<Long> usersIDs = null; if (userID != -1) { usersIDs = new ArrayList<Long>(1); usersIDs.add(userID); } Map map = gateway.loadAnnotations(ctx, klass, ids, null, usersIDs, new Parameters()); Multimap<Long, IObject> linkMap = ArrayListMultimap.create(); if (!(klass.equals(TagAnnotationData.class) || klass.equals(FileAnnotationData.class))) { Collection values = map.values(); Iterator k = values.iterator(); List<Long> annotationIds = new ArrayList<Long>(); while (k.hasNext()) { Collection l = (Collection) k.next(); Iterator j = l.iterator(); while (j.hasNext()) { AnnotationData object = (AnnotationData) j.next(); if (!annotationIds.contains(object.getId())) annotationIds.add(object.getId()); } } if (CollectionUtils.isNotEmpty(annotationIds)) { linkMap = gateway.findAnnotationLinks(ctx, klass, ids, annotationIds, userID); } } //format the results Iterator<DataObject> i = data.iterator(); StructuredDataResults r; List<IObject> links; DataObject n; while (i.hasNext()) { n = i.next(); if (n != null && ids.contains(n.getId())) { r = new StructuredDataResults(n); loadStructuredData(ctx, userID, (Collection) map.get(n.getId()), r, false); results.put(n, r); if (n instanceof ImageData) { ImageData img = (ImageData) n; r.setTransferlinks(filesetMap.get(img.getFilesetId())); } formatAnnotationLinks(linkMap.get(n.getId()), r); } } } /** * Formats the annotation links. * * @param links The links to handle. * @param results The placeholder for result. */ private void formatAnnotationLinks(Collection<IObject> links, StructuredDataResults results) { if (CollectionUtils.isEmpty(links)) return; Map<DataObject, ExperimenterData> m = new HashMap<DataObject, ExperimenterData>(); Iterator j = links.iterator(); IObject link; DataObject d; List<AnnotationLinkData> l = new ArrayList<AnnotationLinkData>(); IObject ho; while (j.hasNext()) { link = (IObject) j.next(); ho = ModelMapper.getChildFromLink(link); d = PojoMapper.asDataObject(ho); l.add(new AnnotationLinkData(link, d, PojoMapper.asDataObject( ModelMapper.getParentFromLink(link)))); if (d != null) m.put(d, (ExperimenterData) PojoMapper.asDataObject( link.getDetails().getOwner())); } results.setLinks(m); results.setAnnotationLinks(l); } /** * Implemented as specified by {@link OmeroDataService}. * @see OmeroMetadataService#annotate(SecurityContext, DataObject, AnnotationData) */ public DataObject annotate(SecurityContext ctx, DataObject toAnnotate, AnnotationData annotation) throws DSOutOfServiceException, DSAccessException { if (toAnnotate == null) throw new IllegalArgumentException("DataObject cannot be null"); ctx = gateway.checkContext(ctx, toAnnotate); return annotate(ctx, toAnnotate.getClass(), toAnnotate.getId(), annotation); } /** * Implemented as specified by {@link OmeroDataService}. * @see OmeroMetadataService#annotate(SecurityContext, Class, long, AnnotationData) */ public DataObject annotate(SecurityContext ctx, Class type, long id, AnnotationData annotation) throws DSOutOfServiceException, DSAccessException { if (annotation == null) throw new IllegalArgumentException("DataObject cannot be null"); String ioType = PojoMapper.getModelType(type).getName(); IObject ho = gateway.findIObject(ctx, ioType, id); ModelMapper.unloadCollections(ho); IObject link = null; boolean exist = false; IObject annObject; ExperimenterData exp = getUserDetails(); if (annotation instanceof TagAnnotationData) { TagAnnotationData tag = (TagAnnotationData) annotation; //tag a tag if (TagAnnotationData.class.equals(type)) { if (tag.getId() <= 0) { TagAnnotation ann = new TagAnnotationI(); ann.setTextValue( omero.rtypes.rstring(tag.getContentAsString())); ann.setDescription( omero.rtypes.rstring(tag.getTagDescription())); link = ModelMapper.linkAnnotation(ann, (Annotation) ho); } else { annObject = tag.asIObject(); ModelMapper.unloadCollections(annObject); link = gateway.findAnnotationLink(ctx, AnnotationData.class, tag.getId(), ho.getId().getValue(), exp.getId()); if (link == null) link = ModelMapper.linkAnnotation(annObject, (Annotation) ho); } } else { if (tag.getId() <= 0) link = ModelMapper.createAnnotationAndLink(ho, annotation); else { annObject = tag.asIObject(); ModelMapper.unloadCollections(annObject); link = gateway.findAnnotationLink(ctx, ho.getClass(), ho.getId().getValue(), tag.getId(), exp.getId()); if (link == null) link = ModelMapper.linkAnnotation(ho, (Annotation) annObject); else exist = true; } } } else if (annotation instanceof RatingAnnotationData) { //only one annotation of type rating. //Remove the previous ones. clearAnnotation(ctx, type, id, RatingAnnotationData.class); link = ModelMapper.createAnnotationAndLink(ho, annotation); } else if (annotation instanceof FileAnnotationData) { FileAnnotationData ann = (FileAnnotationData) annotation; if (ann.getId() < 0) { OriginalFile of = gateway.uploadFile(ctx, ann.getAttachedFile(), ann.getServerFileMimetype(), -1); FileAnnotation fa = new FileAnnotationI(); fa.setFile(of); link = ModelMapper.linkAnnotation(ho, fa); } else { annObject = ann.asIObject(); ModelMapper.unloadCollections(annObject); OriginalFile of = ((FileAnnotation) annObject).getFile(); link = ModelMapper.linkAnnotation(ho, (Annotation) annObject); } } else link = ModelMapper.createAnnotationAndLink(ho, annotation); if (link != null) { IObject object; if (exist) object = link; else object = gateway.createObject(ctx, link); return PojoMapper.asDataObject( ModelMapper.getAnnotatedObject(object)); } return null; } /** * Implemented as specified by {@link OmeroDataService}. * @see OmeroMetadataService#clearAnnotation(SecurityContext, Class, long, Class) */ public void clearAnnotation(SecurityContext ctx, Class type, long id, Class annotationType) throws DSOutOfServiceException, DSAccessException { if (type == null) throw new IllegalArgumentException("No object specified."); long userID = getUserDetails().getId(); Collection annotations = loadStructuredAnnotations(ctx, type, id, userID); if (annotations == null || annotations.size() == 0) return; List<IObject> toRemove = new ArrayList<IObject>(); List<Long> ids = new ArrayList<Long>(); Iterator i = annotations.iterator(); AnnotationData data; while (i.hasNext()) { data = (AnnotationData) i.next(); if (annotationType == null || data.getClass().equals(annotationType)) { toRemove.add(data.asIObject()); ids.add(data.getId()); } } List l = null; Class klass = PojoMapper.getModelType(type); if (ids.size() != 0) l = gateway.findAnnotationLinks(ctx, klass, id, ids); if (l != null) { i = l.iterator(); IObject o; while (i.hasNext()) { o = (IObject) i.next(); if (gateway.canDelete(o)) gateway.deleteObject(ctx, o); } //Need to check if the object is not linked to other object. i = toRemove.iterator(); IObject obj; while (i.hasNext()) { obj = (IObject) i.next(); ids = new ArrayList<Long>(); ids.add(obj.getId().getValue()); l = gateway.findAnnotationLinks(ctx, klass, -1, ids); if (l == null || l.size() == 0) { if (gateway.canDelete(obj)) gateway.deleteObject(ctx, obj); } } } } /** * Implemented as specified by {@link OmeroDataService}. * @see OmeroMetadataService#clearAnnotation(SecurityContext, DataObject, Class) */ public void clearAnnotation(SecurityContext ctx, DataObject object, Class annotationType) throws DSOutOfServiceException, DSAccessException { if (object == null) throw new IllegalArgumentException("No object specified."); ctx = gateway.checkContext(ctx, object); clearAnnotation(ctx, object.getClass(), object.getId(), annotationType); } /** * Implemented as specified by {@link OmeroDataService}. * @see OmeroMetadataService#clearAnnotation(SecurityContext, DataObject) */ public void clearAnnotation(SecurityContext ctx, DataObject object) throws DSOutOfServiceException, DSAccessException { if (object == null) throw new IllegalArgumentException("No object specified."); ctx = gateway.checkContext(ctx, object); clearAnnotation(ctx, object.getClass(), object.getId(), null); } /** * Implemented as specified by {@link OmeroDataService}. * @see OmeroMetadataService#loadStructuredAnnotations(SecurityContext, Class, long, long) */ public Collection loadStructuredAnnotations(SecurityContext ctx, Class type, long id, long userID) throws DSOutOfServiceException, DSAccessException { if (id < 0) new ArrayList<Long>(); if (type == null) throw new IllegalArgumentException("No type specified."); List<Long> ids = null; if (userID != -1) { ids = new ArrayList<Long>(1); ids.add(userID); } List<Long> objects = new ArrayList<Long>(1); objects.add(id); Map map = gateway.loadAnnotations(ctx, type, objects, null, ids, new Parameters()); return (Collection) map.get(id); } /** * Implemented as specified by {@link OmeroDataService}. * @see OmeroMetadataService#loadAnnotations(SecurityContext, Class, String, long) */ public Collection loadAnnotations(SecurityContext ctx, Class annotationType, String nameSpace, long userID) throws DSOutOfServiceException, DSAccessException { ParametersI po = new ParametersI(); if (userID >= 0) po.exp(omero.rtypes.rlong(userID)); List<String> toInclude = new ArrayList<String>(); List<String> toExclude = new ArrayList<String>(); if (nameSpace != null) toInclude.add(nameSpace); if (TagAnnotationData.class.equals(annotationType)) { po.orphan(); return gateway.loadTagSets(ctx, po); } if (FileAnnotationData.class.equals(annotationType)) { if (!FileAnnotationData.COMPANION_FILE_NS.equals(nameSpace)) toExclude.add(FileAnnotationData.COMPANION_FILE_NS); if (!FileAnnotationData.MEASUREMENT_NS.equals(nameSpace)) toExclude.add(FileAnnotationData.MEASUREMENT_NS); if (!FileAnnotationData.FLIM_NS.equals(nameSpace)) toExclude.add(FileAnnotationData.FLIM_NS); if (!FileAnnotationData.EXPERIMENTER_PHOTO_NS.equals(nameSpace)) toExclude.add(FileAnnotationData.EXPERIMENTER_PHOTO_NS); if (!FileAnnotationData.LOG_FILE_NS.equals(nameSpace)) toExclude.add(FileAnnotationData.LOG_FILE_NS); } return gateway.loadSpecificAnnotation(ctx, annotationType, toInclude, toExclude, po); } /** * Implemented as specified by {@link OmeroDataService}. * @see OmeroMetadataService#saveData(SecurityContext, Collection, List, List, long) */ public Object saveData(SecurityContext ctx, Collection<DataObject> data, List<AnnotationData> toAdd, List<Object> toRemove, long userID) throws DSOutOfServiceException, DSAccessException { if (data == null) throw new IllegalArgumentException("No data to save"); Iterator<DataObject> j = data.iterator(); DataObject object; OmeroDataService service = context.getDataService(); List<AnnotationData> annotations = prepareAnnotationToAdd(ctx, toAdd); Iterator i; j = data.iterator(); //First create the new annotations AnnotationData ann; List<DataObject> updated = new ArrayList<DataObject>(); List<Long> ids = new ArrayList<Long>(); while (j.hasNext()) { object = j.next(); if (!ids.contains(object.getId())) { ids.add(object.getId()); if (object instanceof AnnotationData) { updateAnnotationData(ctx, object); } else { if (object.isLoaded() && object.isDirty()) updated.add(service.updateDataObject(ctx, object)); else updated.add(object); } if (annotations.size() > 0) { i = annotations.iterator(); while (i.hasNext()) { ann = (AnnotationData) i.next(); if (ann != null) linkAnnotation(ctx, object, ann); } } if (toRemove != null) { Iterator<Object> k = toRemove.iterator(); List<IObject> toDelete = new ArrayList<IObject>(); Object o; while (k.hasNext()) { o = k.next(); if (o != null) { removeAnnotation(ctx, o, object); if (o instanceof TextualAnnotationData) { ann = (AnnotationData) o; if (!isAnnotationShared(ctx, ann, object)) { toDelete.add(ann.asIObject()); } } } } if (toDelete.size() > 0) { gateway.deleteObjects(ctx, toDelete); } } } } return updated;//data; } /** * Implemented as specified by {@link OmeroDataService}. * @see OmeroMetadataService#saveBatchData(SecurityContext, Collection, List, List, long) */ public Object saveBatchData(SecurityContext ctx, Collection<DataObject> data, List<AnnotationData> toAdd, List<Object> toRemove, long userID) throws DSOutOfServiceException, DSAccessException { if (data == null) throw new IllegalArgumentException("No data to save"); OmeroDataService service = context.getDataService(); Iterator i; Iterator<DataObject> j = data.iterator(); DataObject object, child; List<Long> ids; Set images = null; Parameters po = new Parameters(); Iterator k; List result = null; //First create the new annotations List<AnnotationData> annotations = prepareAnnotationToAdd(ctx, toAdd); List<Long> childrenIds = new ArrayList<Long>(); while (j.hasNext()) { object = j.next(); if (result == null) result = new ArrayList(); //Need code for tag if (object instanceof DatasetData) { //retrieve all images in the dataset. //Tmp solution, this code should be pushed server side. ids = new ArrayList<Long>(1); ids.add(object.getId()); images = gateway.getContainerImages(ctx, DatasetData.class, ids, po); if (images != null) { k = images.iterator(); while (k.hasNext()) { child = (DataObject) k.next(); if (!childrenIds.contains(child.getId())) { result.add(child); childrenIds.add(child.getId()); if (annotations != null) { i = annotations.iterator(); while (i.hasNext()) linkAnnotation(ctx, child, (AnnotationData) i.next()); } if (toRemove != null) { i = toRemove.iterator(); while (i.hasNext()) removeAnnotation(ctx, i.next(), child); } } } } } else if (object instanceof PlateData) { //Load all the wells images = gateway.loadPlateWells(ctx, object.getId(), -1); if (images != null) { k = images.iterator(); while (k.hasNext()) { child = (DataObject) k.next(); if (!childrenIds.contains(child.getId())) { result.add(child); childrenIds.add(child.getId()); if (annotations != null) { i = annotations.iterator(); while (i.hasNext()) linkAnnotation(ctx, child, (AnnotationData) i.next()); } if (toRemove != null) { i = toRemove.iterator(); while (i.hasNext()) removeAnnotation(ctx, (AnnotationData) i.next(), child); } } } } } else if (object instanceof ImageData) { service.updateDataObject(ctx, object); if (annotations != null) { i = annotations.iterator(); while (i.hasNext()) linkAnnotation(ctx, object, (AnnotationData) i.next()); //annotate(object, (AnnotationData) i.next()); } if (toRemove != null) { i = toRemove.iterator(); while (i.hasNext()) removeAnnotation(ctx, (AnnotationData) i.next(), object); } } } if (result == null) return data; return result; } /** * Implemented as specified by {@link OmeroDataService}. * @see OmeroMetadataService#saveBatchData(SecurityContext, TimeRefObject, List, List, long) */ public Object saveBatchData(SecurityContext ctx, TimeRefObject data, List<AnnotationData> toAdd, List<Object> toRemove, long userID) throws DSOutOfServiceException, DSAccessException { if (data == null) throw new IllegalArgumentException("No data to save"); OmeroDataService service = context.getDataService(); Collection images = service.getImagesPeriod(ctx, data.getStartTime(), data.getEndTime(), userID, true); List r = new ArrayList(); if (images == null) return r; Iterator i = images.iterator(); DataObject child; Iterator j; //First create the new annotations List<AnnotationData> annotations = prepareAnnotationToAdd(ctx, toAdd); while (i.hasNext()) { child = (DataObject) i.next(); r.add(child); if (annotations != null) { j = annotations.iterator(); while (j.hasNext()) linkAnnotation(ctx, child, (AnnotationData) i.next()); } if (toRemove != null) { j = toRemove.iterator(); while (j.hasNext()) removeAnnotation(ctx, j.next(), child); } } return r; } /** * Implemented as specified by {@link OmeroDataService}. * @see OmeroMetadataService#downloadFile(SecurityContext, String, int) */ public File downloadFile(SecurityContext ctx, File file, long fileID) throws DSOutOfServiceException, DSAccessException { if (fileID < 0) throw new IllegalArgumentException("File ID not valid"); if (file == null) throw new IllegalArgumentException("File path not valid"); return gateway.downloadFile(ctx, file, fileID); } /** * Implemented as specified by {@link OmeroDataService}. * @see OmeroMetadataService#loadRatings(SecurityContext, Class, List, long) */ public Map<Long, Collection> loadRatings(SecurityContext ctx, Class nodeType, List<Long> nodeIds, long userID) throws DSOutOfServiceException, DSAccessException { List<Long> ids = null; if (userID != -1) { ids = new ArrayList<Long>(1); ids.add(userID); } List<Class> types = new ArrayList<Class>(); types.add(RatingAnnotationData.class); Map map = gateway.loadAnnotations(ctx, nodeType, nodeIds, types, ids, new Parameters()); Map<Long, Collection> results = new HashMap<Long, Collection>(); if (map == null) return results; Entry entry; Iterator i = map.entrySet().iterator(); Long id; AnnotationData data; Iterator j; List<AnnotationData> result; Collection l; while (i.hasNext()) { entry = (Entry) i.next(); id = (Long) entry.getKey(); l = (Collection) entry.getValue(); result = new ArrayList<AnnotationData>(); j = l.iterator(); while (j.hasNext()) { data = (AnnotationData) j.next(); if (data instanceof RatingAnnotationData) result.add(data); } if (result.size() > 0) results.put(id, result); } return results; } /** * Implemented as specified by {@link OmeroDataService}. * @see OmeroMetadataService#filterByAnnotation(SecurityContext, * Class, List, Class, List, long) */ public Collection filterByAnnotation(SecurityContext ctx, Class nodeType, List<Long> nodeIds, Class annotationType, List<String> terms, long userID) throws DSOutOfServiceException, DSAccessException { Set<Long> results = new HashSet<Long>(); List<Long> ids = null; if (userID != -1) { ids = new ArrayList<Long>(1); ids.add(userID); } List<Class> types = new ArrayList<Class>(); types.add(annotationType); Map map = gateway.loadAnnotations(ctx, nodeType, nodeIds, types, ids, new Parameters()); if (map == null || map.size() == 0) return results; long id; Collection l; AnnotationData data; Iterator i, j; Entry entry; Map<Long, List<Long>> m = new HashMap<Long, List<Long>>(); List<Long> nodes; if (terms != null && terms.size() > 0) { //retrieve the annotations corresponding to the specified terms. //List annotations = gateway.filterBy(annotationType, terms, // null, null, exp); i = map.entrySet().iterator(); while (i.hasNext()) { entry = (Entry) i.next(); id = (Long) entry.getKey(); l = (Collection) entry.getValue(); j = l.iterator(); while (j.hasNext()) { data = (AnnotationData) j.next(); if (annotationType.equals(TagAnnotationData.class)) { if (data instanceof TagAnnotationData) { if (terms.contains( ((TagAnnotationData) data).getTagValue())) { nodes = m.get(data.getId()); if (nodes == null) { nodes = new ArrayList<Long>(); nodes.add(id); } if (!nodes.contains(id)) nodes.add(id); m.put(data.getId(), nodes); } } } else if (annotationType.equals( TextualAnnotationData.class)) { if (data instanceof TextualAnnotationData) { if (containTerms(terms, ((TextualAnnotationData) data).getText())) { nodes = m.get(data.getId()); if (nodes == null) { nodes = new ArrayList<Long>(); nodes.add(id); } if (!nodes.contains(id)) nodes.add(id); m.put(data.getId(), nodes); } } } } } } else return filterByAnnotated(ctx, nodeType, nodeIds, annotationType, true, userID); i = m.entrySet().iterator(); while (i.hasNext()) { entry = (Entry) i.next(); id = (Long) entry.getKey(); nodes = (List) entry.getValue(); //if (results.size() == 0) results.addAll(nodes); //else results = ListUtils.intersection(results, nodes); results.addAll(nodes); } return results; } /** * Implemented as specified by {@link OmeroDataService}. * @see OmeroMetadataService#filterByAnnotated(SecurityContext, * Class, List, Class, boolean, long) */ public Collection filterByAnnotated(SecurityContext ctx, Class nodeType, List<Long> nodeIds, Class annotationType, boolean annotated, long userID) throws DSOutOfServiceException, DSAccessException { List<Long> results = new ArrayList<Long>(); List<Long> ids = null; if (userID != -1) { ids = new ArrayList<Long>(1); ids.add(userID); } List<Class> types = new ArrayList<Class>(); types.add(annotationType); Map map = gateway.loadAnnotations(ctx, nodeType, nodeIds, types, ids, new Parameters()); if (map == null || map.size() == 0) return results; long id; Collection l; AnnotationData data; Iterator i, j; Entry entry; i = map.entrySet().iterator(); if (annotated) { while (i.hasNext()) { entry = (Entry) i.next(); id = (Long) entry.getKey(); l = (Collection) entry.getValue(); j = l.iterator(); while (j.hasNext()) { data = (AnnotationData) j.next(); if (annotationType.equals(TagAnnotationData.class)) { if (data instanceof TagAnnotationData) { if (!results.contains(id)) { results.add(id); } } } else if (annotationType.equals( TextualAnnotationData.class)) { if (!(data instanceof TagAnnotationData)) { if (!results.contains(id)) { results.add(id); } } } } } } else { List<Long> toExclude = new ArrayList<Long>(); results.addAll(nodeIds); while (i.hasNext()) { entry = (Entry) i.next(); id = (Long) entry.getKey(); l = (Collection) entry.getValue(); j = l.iterator(); while (j.hasNext()) { data = (AnnotationData) j.next(); if (annotationType.equals(TagAnnotationData.class)) { if (data instanceof TagAnnotationData) { if (!toExclude.contains(id)) { toExclude.add(id); } } } else if (annotationType.equals( TextualAnnotationData.class)) { if (!(data instanceof TagAnnotationData)) { if (!toExclude.contains(id)) { toExclude.add(id); } } } } } results.removeAll(toExclude); } return results; } /** * Implemented as specified by {@link OmeroDataService}. * @see OmeroMetadataService#filterByAnnotation(SecurityContext, Class, * List, FilterContext, long) */ public Collection filterByAnnotation(SecurityContext ctx, Class nodeType, List<Long> ids, FilterContext filter, long userID) throws DSOutOfServiceException, DSAccessException { if (filter == null) throw new IllegalArgumentException("No filtering context."); int rateIndex = filter.getRateIndex(); int roiIndex = filter.getRoiIndex(); List<Long> filteredNodes = new ArrayList<Long>(); List<Long> userIDs = null; if (userID != -1) { userIDs = new ArrayList<Long>(1); userIDs.add(userID); } List<Class> annotationTypes = new ArrayList<Class>(); //types.add(annotationType); Map map = gateway.loadAnnotations(ctx, nodeType, ids, annotationTypes, userIDs, new Parameters()); if (map == null || map.size() == 0) { if (rateIndex == FilterContext.EQUAL && filter.getRate() == 0) return ids; } //TODO: retrieve the experimenter corresponding to the passed id. ExperimenterData exp = getUserDetails(); Timestamp start = filter.getFromDate(); Timestamp end = filter.getToDate(); Set<Long> annotationsIds = new HashSet<Long>(); Iterator i, j, k; Long id; Collection l; List annotations; int resultType = filter.getResultType(); Map<Class, List<String>> types = filter.getAnnotationType(); Map<Class, List<Long>> r = new HashMap<Class, List<Long>>(); List<Long> found; Class type; Entry entry; if (types != null && types.size() > 0) { i = types.entrySet().iterator(); Map<Long, List<Long>> m = new HashMap<Long, List<Long>>(); List<Long> nodes; AnnotationData data; if (resultType == FilterContext.INTERSECTION) { while (i.hasNext()) { entry = (Entry) i.next(); type = (Class) entry.getKey(); found = new ArrayList<Long>(); annotations = gateway.filterBy(ctx, type, (List<String>) entry.getValue(), start, end, exp); j = annotations.iterator(); while (j.hasNext()) annotationsIds.add((Long) j.next()); j = map.entrySet().iterator(); while (j.hasNext()) { entry = (Entry) j.next(); id = (Long) entry.getKey(); l = (Collection) entry.getValue(); if (l.size() >= annotations.size()) { k = l.iterator(); while (k.hasNext()) { data = (AnnotationData) k.next(); if (annotations.contains(data.getId())) { nodes = m.get(data.getId()); if (nodes == null) { nodes = new ArrayList<Long>(); nodes.add(id); } if (!nodes.contains(id)) nodes.add(id); m.put(data.getId(), nodes); } } } } j = m.entrySet().iterator(); while (j.hasNext()) { entry = (Entry) j.next(); id = (Long) entry.getKey(); nodes = (List) entry.getValue(); if (found.size() == 0) found.addAll(nodes); else found = ListUtils.intersection(found, nodes); } r.put(type, found); } } else if (resultType == FilterContext.UNION) { while (i.hasNext()) { type = (Class) i.next(); annotations = gateway.filterBy(ctx, type, types.get(type), start, end, exp); i = annotations.iterator(); while (i.hasNext()) annotationsIds.add((Long) i.next()); } i = map.entrySet().iterator(); while (i.hasNext()) { entry = (Entry) i.next(); id = (Long) entry.getKey(); l = (Collection) entry.getValue(); j = l.iterator(); while (j.hasNext()) { data = (AnnotationData) j.next(); if (annotationsIds.contains(data.getId())) filteredNodes.add(id); } } } } if(roiIndex != -1) { found = new ArrayList<Long>(); for (long imgId : ids) { List<ROIResult> roiResults = gateway.loadROI(ctx, imgId, null, userID); List rois = new ArrayList(); for (ROIResult tmp : roiResults) { rois.addAll(tmp.getROIs()); } int numberOfRois = filter.getROIs(); switch (roiIndex) { case FilterContext.EQUAL: if (rois.size() == numberOfRois) { found.add(imgId); } break; case FilterContext.LOWER_EQUAL: if (rois.size() <= numberOfRois) { found.add(imgId); } break; case FilterContext.GREATER_EQUAL: if (rois.size() >= numberOfRois) { found.add(imgId); } break; } } if (resultType == FilterContext.UNION) filteredNodes.addAll(found); else if (resultType == FilterContext.INTERSECTION) r.put(ROIData.class, found); } if (rateIndex != -1) { int rate = filter.getRate(); int value; i = map.keySet().iterator(); AnnotationData data; found = new ArrayList<Long>(); switch (rateIndex) { case FilterContext.EQUAL: if (rate == 0) { //unrated element. found.addAll(ids); while (i.hasNext()) found.remove(i.next()); } else { while (i.hasNext()) { id = (Long) i.next(); l = (Collection) map.get(id); j = l.iterator(); while (j.hasNext()) { data = (AnnotationData) j.next(); if (data instanceof RatingAnnotationData) { value = ((RatingAnnotationData) data).getRating(); if (rate == value) found.add(id); } } } } break; case FilterContext.LOWER_EQUAL: if (rate == 0) { //unrated element. found.addAll(ids); while (i.hasNext()) found.remove(i.next()); } else { while (i.hasNext()) { id = (Long) i.next(); l = (Collection) map.get(id); j = l.iterator(); while (j.hasNext()) { data = (AnnotationData) j.next(); if (data instanceof RatingAnnotationData) { value = ((RatingAnnotationData) data).getRating(); if (value <= rate) found.add(id); } } } } break; case FilterContext.GREATER_EQUAL: while (i.hasNext()) { id = (Long) i.next(); l = (Collection) map.get(id); j = l.iterator(); while (j.hasNext()) { data = (AnnotationData) j.next(); if (data instanceof RatingAnnotationData) { value = ((RatingAnnotationData) data).getRating(); if (value >= rate) found.add(id); } } } } if (resultType == FilterContext.UNION) filteredNodes.addAll(found); else if (resultType == FilterContext.INTERSECTION) r.put(RatingAnnotationData.class, found); } if (resultType == FilterContext.UNION) return filteredNodes; //Intersection. filteredNodes.clear(); if (r.size() == 0) return filteredNodes; int index = 0; type = null; /* while (i.hasNext()) { type = (Class) i.next(); if (index == 0) { filteredNodes.addAll(r.get(type)); break; } index++; } r.remove(type); */ i = r.values().iterator(); if(!i.hasNext()) { return filteredNodes; } found = (List)i.next(); filteredNodes.addAll(found); while (i.hasNext()) { found = (List)i.next(); filteredNodes = ListUtils.intersection(filteredNodes, found); } return filteredNodes; } /** * Implemented as specified by {@link OmeroDataService}. * @see OmeroMetadataService#getEnumeration(SecurityContext, String) */ public Collection getEnumeration(SecurityContext ctx, String type) throws DSOutOfServiceException, DSAccessException { return gateway.getEnumerations(ctx, type); } /** * Implemented as specified by {@link OmeroImageService}. * @see OmeroMetadataService#loadAcquisitionData(SecurityContext, Object) */ public Object loadAcquisitionData(SecurityContext ctx, Object refObject) throws DSOutOfServiceException, DSAccessException { if (refObject instanceof ImageData) { ctx = gateway.checkContext(ctx, (ImageData) refObject); return gateway.loadImageAcquisitionData(ctx, ((ImageData) refObject).getId()); } else if (refObject instanceof ChannelData) { ctx = gateway.checkContext(ctx, (ChannelData) refObject); Channel c = ((ChannelData) refObject).asChannel(); if (c.getLogicalChannel() == null) return null; long id = c.getLogicalChannel().getId().getValue(); return gateway.loadChannelAcquisitionData(ctx, id); } return null; } /** * Implemented as specified by {@link OmeroImageService}. * @see OmeroMetadataService#loadInstrument(SecurityContext, long) */ public Object loadInstrument(SecurityContext ctx, long instrumentID) throws DSOutOfServiceException, DSAccessException { if (instrumentID <= 0) return null; return gateway.loadInstrument(ctx, instrumentID); } /** * Implemented as specified by {@link OmeroImageService}. * @see OmeroMetadataService#saveAcquisitionData(SecurityContext, Object) */ public Object saveAcquisitionData(SecurityContext ctx, Object refObject) throws DSOutOfServiceException, DSAccessException { if (refObject instanceof ImageAcquisitionData) { ImageAcquisitionData data = (ImageAcquisitionData) refObject; ctx = gateway.checkContext(ctx, data); saveImageAcquisitionData(ctx, data); return null;//loadAcquisitionData(data.asImage()); } else if (refObject instanceof ChannelData) { ChannelData data = (ChannelData) refObject; ctx = gateway.checkContext(ctx, data); saveChannelData(ctx, data); } else if (refObject instanceof ChannelAcquisitionData) { ChannelAcquisitionData data = (ChannelAcquisitionData) refObject; ctx = gateway.checkContext(ctx, data); saveChannelAcquisitionData(ctx, data); } return null; } /** * Implemented as specified by {@link OmeroImageService}. * @see OmeroMetadataService#archivedFile(SecurityContext ctx, * FileAnnotationData, File, int, DataObject) */ public Object archivedFile(SecurityContext ctx, FileAnnotationData fileAnnotation, File file, int index, DataObject linkTo) throws DSOutOfServiceException, DSAccessException { if (file == null) throw new IllegalArgumentException("No file to save."); if (fileAnnotation == null) return null; ctx = gateway.checkContext(ctx, fileAnnotation); //Upload the file back to the server long id = fileAnnotation.getId(); long originalID = fileAnnotation.getFileID(); OriginalFile of = gateway.uploadFile(ctx, file, fileAnnotation.getServerFileMimetype(), originalID); //Need to relink and delete the previous one. FileAnnotation fa; String desc = fileAnnotation.getDescription(); if (id < 0) { fa = new FileAnnotationI(); fa.setFile(of); if (desc != null) fa.setDescription(omero.rtypes.rstring(desc)); IObject object = gateway.createObject(ctx, fa); id = object.getId().getValue(); } else { fa = (FileAnnotation) gateway.findIObject(ctx, FileAnnotation.class.getName(), id); fa.setFile(of); if (desc != null) fa.setDescription(omero.rtypes.rstring(desc)); gateway.updateObject(ctx, fa, new Parameters()); } fa = (FileAnnotation) gateway.findIObject(ctx, FileAnnotation.class.getName(), id); FileAnnotationData data = (FileAnnotationData) PojoMapper.asDataObject(fa); if (of != null) { data.setContent(of); } if (linkTo != null) { if (linkTo.getId() > 0) { annotate(ctx, linkTo, data); } } return data; } /** * Implemented as specified by {@link OmeroImageService}. * @see OmeroMetadataService#loadTags(SecurityContext, Long, * boolean, long, long) */ public Collection loadTags(SecurityContext ctx, Long id, boolean topLevel, long userID, long groupID) throws DSOutOfServiceException, DSAccessException { ParametersI po = new ParametersI(); if (userID >= 0) po.exp(omero.rtypes.rlong(userID)); if (groupID >= 0) po.grp(omero.rtypes.rlong(groupID)); if (topLevel) { po.orphan(); return gateway.loadTagSets(ctx, po); } return gateway.loadTags(ctx, id, po); } /** * Implemented as specified by {@link OmeroImageService}. * @see OmeroMetadataService#countFileType(SecurityContext, long, int) */ public long countFileType(SecurityContext ctx, long userID, int fileType) throws DSOutOfServiceException, DSAccessException { List<String> include = new ArrayList<String>(); List<String> exclude = new ArrayList<String>(); switch (fileType) { case MOVIE: include.add(FileAnnotationData.MOVIE_NS); break; case TAG_NOT_OWNED: return gateway.countAnnotationsUsedNotOwned(ctx, TagAnnotationData.class, userID); case OTHER: default: exclude.add(FileAnnotationData.MOVIE_NS); exclude.add(FileAnnotationData.COMPANION_FILE_NS); exclude.add(FileAnnotationData.MEASUREMENT_NS); exclude.add(FileAnnotationData.FLIM_NS); exclude.add(FileAnnotationData.EXPERIMENTER_PHOTO_NS); exclude.add(FileAnnotationData.LOG_FILE_NS); } ParametersI po = new ParametersI(); if (userID >= 0) po.exp(omero.rtypes.rlong(userID)); return gateway.countSpecificAnnotation(ctx, FileAnnotationData.class, include, exclude, po); } /** * Implemented as specified by {@link OmeroImageService}. * @see OmeroMetadataService#loadFiles(SecurityContext, int, long) */ public Collection loadFiles(SecurityContext ctx, int fileType, long userID) throws DSOutOfServiceException, DSAccessException { List<String> include = new ArrayList<String>(); List<String> exclude = new ArrayList<String>(); ParametersI po = new ParametersI(); if (userID >= 0) po.exp(omero.rtypes.rlong(userID)); switch (fileType) { case MOVIE: include.add(FileAnnotationData.MOVIE_NS); break; case TAG_NOT_OWNED: return gateway.loadAnnotationsUsedNotOwned(ctx, TagAnnotationData.class, userID); case OTHER: default: exclude.add(FileAnnotationData.MOVIE_NS); exclude.add(FileAnnotationData.COMPANION_FILE_NS); exclude.add(FileAnnotationData.MEASUREMENT_NS); exclude.add(FileAnnotationData.FLIM_NS); exclude.add(FileAnnotationData.EXPERIMENTER_PHOTO_NS); exclude.add(FileAnnotationData.LOG_FILE_NS); } return gateway.loadSpecificAnnotation(ctx, FileAnnotationData.class, include, exclude, po); } /** * Implemented as specified by {@link OmeroImageService}. * @see OmeroMetadataService#loadAnnotation(SecurityContext, long) */ public DataObject loadAnnotation(SecurityContext ctx, long annotationID) throws DSOutOfServiceException, DSAccessException { //Tmp code Set<DataObject> set = gateway.loadAnnotation(ctx, Arrays.asList(annotationID)); if (set.size() != 1) return null; Iterator<DataObject> i = set.iterator(); while (i.hasNext()) { return i.next(); } return null; } /** * Implemented as specified by {@link OmeroImageService}. * @see OmeroMetadataService#loadTabularData(SecurityContext ctx, * TableParameters, long) */ public List<TableResult> loadTabularData(SecurityContext ctx, TableParameters parameters, long userID) throws DSOutOfServiceException, DSAccessException { if (parameters == null) throw new IllegalArgumentException("No parameters specified."); return gateway.loadTabularData(ctx, parameters, userID); } /** * Implemented as specified by {@link OmeroImageService}. * * @see OmeroMetadataService#loadParentsOfAnnotations(SecurityContext, long) */ public List<DataObject> loadParentsOfAnnotations(SecurityContext ctx, long annotationId) throws DSOutOfServiceException, DSAccessException { ExperimenterData exp = (ExperimenterData) context .lookup(LookupNames.CURRENT_USER_DETAILS); long userId = exp.getId(); return loadParentsOfAnnotations(ctx, annotationId, userId); } /** * Implemented as specified by {@link OmeroImageService}. * @see OmeroMetadataService#loadParentsOfAnnotations(SecurityContext, long, long) */ public List<DataObject> loadParentsOfAnnotations(SecurityContext ctx, long annotationId, long userId) throws DSOutOfServiceException, DSAccessException { if (annotationId < 0) throw new IllegalArgumentException("Annotation id not valid."); //Check possible links List links = gateway.findLinks(ctx, FileAnnotation.class, annotationId, userId); List<DataObject> nodes = new ArrayList<DataObject>(); if (links != null) { Iterator j = links.iterator(); Object o; while (j.hasNext()) { o = j.next(); if (o instanceof ProjectAnnotationLink) { nodes.add(PojoMapper.asDataObject( ((ProjectAnnotationLink) o).getParent())); } else if (o instanceof DatasetAnnotationLink) { nodes.add(PojoMapper.asDataObject( ((DatasetAnnotationLink) o).getParent())); } else if (o instanceof ImageAnnotationLink) { nodes.add(PojoMapper.asDataObject( ((ImageAnnotationLink) o).getParent())); } else if (o instanceof PlateAnnotationLink) { nodes.add(PojoMapper.asDataObject( ((PlateAnnotationLink) o).getParent())); } else if (o instanceof ScreenAnnotationLink) { nodes.add(PojoMapper.asDataObject( ((ScreenAnnotationLink) o).getParent())); } else if (o instanceof WellAnnotationLink) { nodes.add(PojoMapper.asDataObject( ((WellAnnotationLink) o).getParent())); } else if (o instanceof PlateAcquisitionAnnotationLink) { nodes.add(PojoMapper.asDataObject( ((PlateAcquisitionAnnotationLink) o).getParent())); } } } return nodes; } /** * Implemented as specified by {@link OmeroImageService}. * @see OmeroMetadataService#saveChannelData(SecurityContext, List, List) */ public List<Long> saveChannelData(SecurityContext ctx, List<ChannelData> channels, List<DataObject> objects) throws DSOutOfServiceException, DSAccessException { List<Long> images = new ArrayList<Long>(); if (channels == null || channels.size() == 0) return images; //Update the channels only if (objects == null || objects.size() == 0) return images; List<IObject> pixels = gateway.getPixels(ctx, objects); if (pixels == null) return images; Iterator<IObject> i = pixels.iterator(); Pixels p; int sizeC; int n = channels.size(); List<IObject> toUpdate = new ArrayList<IObject>(); List<Channel> l; while (i.hasNext()) { p = (Pixels) i.next(); sizeC = p.getSizeC().getValue(); if (sizeC == n) { l = p.copyChannels(); updateChannels(channels, l); toUpdate.addAll(l); images.add(p.getImage().getId().getValue()); } } //Update the channels now gateway.saveAndReturnObject(ctx, toUpdate, null, null); return images; } /** * Implemented as specified by {@link OmeroDataService}. * @see OmeroDataService#getChannelsMetadata(SecurityContext, long) */ public List<ChannelData> getChannelsMetadata(SecurityContext ctx, long pixelsID) throws DSOutOfServiceException, DSAccessException { Pixels pixels = gateway.getPixels(ctx, pixelsID); if (pixels == null) return new ArrayList<ChannelData>(); Collection l = pixels.copyChannels(); if (l == null) return new ArrayList<ChannelData>(); Iterator i = l.iterator(); List<ChannelData> m = new ArrayList<ChannelData>(l.size()); int index = 0; while (i.hasNext()) { m.add(new ChannelData(index, (Channel) i.next())); index++; } return m; } /** * Implemented as specified by {@link OmeroDataService}. * @see OmeroMetadataService#loadAnnotations(SecurityContext, Class, List, * Class, List, List) */ public Map<Long, Collection<AnnotationData>> loadAnnotations(SecurityContext ctx, Class<?> rootType, List<Long> rootIDs, Class<?> annotationType, List<String> nsInclude, List<String> nsExclude) throws DSOutOfServiceException, DSAccessException { if (rootType == null || CollectionUtils.isEmpty(rootIDs)) throw new IllegalArgumentException("No node specified"); if (annotationType == null) throw new IllegalArgumentException("No annotation type specified"); //always exclude the log file if (nsExclude == null) nsExclude = new ArrayList<String>(); nsExclude.add(FileAnnotationData.LOG_FILE_NS); return gateway.loadSpecifiedAnnotationsLinkedTo(ctx, rootType, rootIDs, annotationType, nsInclude, nsExclude, new Parameters()); } /** * Implemented as specified by {@link OmeroDataService}. * @see OmeroDataService#downloadMetadataFile(SecurityContext, File, long) */ public RequestCallback downloadMetadataFile(SecurityContext ctx, File file, long id) throws DSOutOfServiceException, DSAccessException, ProcessException { //Get the file annotation if (id < 0) return null; OriginalMetadataRequest cmd = new OriginalMetadataRequest(); cmd.imageId = id; return gateway.submit(Arrays.<Request>asList(cmd), ctx); } /** * Implemented as specified by {@link OmeroDataService}. * @see OmeroDataService#loadLogFiles(SecurityContext, Class, List) */ public Map<Long, List<IObject>> loadLogFiles(SecurityContext ctx, Class<?> rootType, List<Long> rootIDs) throws DSOutOfServiceException, DSAccessException { if (rootType == null || CollectionUtils.isEmpty(rootIDs)) throw new IllegalArgumentException("No node specified"); return gateway.loadLogFiles(ctx, rootType, rootIDs); } /** * Implemented as specified by {@link OmeroDataService}. * @see OmeroMetadataService#saveData(SecurityContext, Map, Map, long) */ public void saveAnnotationData(SecurityContext ctx, Map<DataObject, List<AnnotationData>> toAdd, Map<DataObject, List<AnnotationData>> toRemove, long userID) throws DSOutOfServiceException, DSAccessException { Entry<DataObject, List<AnnotationData>> e; Iterator<Entry<DataObject, List<AnnotationData>>> j; List<AnnotationData> annotations; Iterator<AnnotationData> i; AnnotationData ann; if (toAdd != null && toAdd.size() > 0) { j = toAdd.entrySet().iterator(); while (j.hasNext()) { e = j.next(); annotations = prepareAnnotationToAdd(ctx, e.getValue()); if (annotations.size() > 0) { i = annotations.iterator(); while (i.hasNext()) { ann = i.next(); if (ann != null) { linkAnnotation(ctx, e.getKey(), ann); } } } } } if (toRemove != null && toRemove.size() > 0) { j = toRemove.entrySet().iterator(); while (j.hasNext()) { e = j.next(); annotations = e.getValue(); i = annotations.iterator(); while (i.hasNext()) { ann = i.next(); if (ann != null) { removeAnnotation(ctx, ann, e.getKey()); } } } } } }