/*
*------------------------------------------------------------------------------
* Copyright (C) 2006-2015 University of Dundee. All rights reserved.
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*------------------------------------------------------------------------------
*/
package org.openmicroscopy.shoola.env.data;
import java.io.File;
import java.sql.Timestamp;
import java.util.ArrayList;
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 omero.cmd.Request;
import omero.cmd.graphs.ChildOption;
import omero.model.Annotation;
import omero.model.AnnotationAnnotationLink;
import omero.model.Dataset;
import omero.model.DatasetAnnotationLink;
import omero.model.DatasetImageLink;
import omero.model.Event;
import omero.model.Experimenter;
import omero.model.ExperimenterI;
import omero.model.FileAnnotation;
import omero.model.IObject;
import omero.model.Image;
import omero.model.ImageAnnotationLink;
import omero.model.Plate;
import omero.model.PlateAnnotationLink;
import omero.model.Project;
import omero.model.ProjectAnnotationLink;
import omero.model.ProjectDatasetLink;
import omero.model.Screen;
import omero.model.ScreenAnnotationLink;
import omero.model.ScreenPlateLink;
import omero.model.TagAnnotation;
import omero.sys.Parameters;
import omero.sys.ParametersI;
import org.apache.commons.collections.CollectionUtils;
import org.openmicroscopy.shoola.env.LookupNames;
import org.openmicroscopy.shoola.env.config.AgentInfo;
import org.openmicroscopy.shoola.env.config.Registry;
import org.openmicroscopy.shoola.env.data.login.UserCredentials;
import org.openmicroscopy.shoola.env.data.model.DeletableObject;
import org.openmicroscopy.shoola.env.data.util.ModelMapper;
import omero.gateway.util.PojoMapper;
import org.openmicroscopy.shoola.env.data.util.SearchDataContext;
import omero.gateway.SecurityContext;
import omero.gateway.exception.DSAccessException;
import omero.gateway.exception.DSOutOfServiceException;
import omero.gateway.model.SearchResult;
import omero.gateway.model.SearchResultCollection;
import omero.gateway.model.SearchParameters;
import omero.gateway.util.Requests;
import omero.log.LogMessage;
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.PermissionData;
import omero.gateway.model.PlateAcquisitionData;
import omero.gateway.model.PlateData;
import omero.gateway.model.ProjectData;
import omero.gateway.model.ScreenData;
import omero.gateway.model.TagAnnotationData;
import omero.gateway.model.WellData;
import omero.gateway.model.WellSampleData;
import omero.api.StatefulServiceInterfacePrx;
/**
* Implementation of the {@link OmeroDataService} I/F.
*
* @author Jean-Marie Burel
* <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a>
* @version 2.2
* @since OME2.2
*/
class OmeroDataServiceImpl
implements OmeroDataService
{
/** 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;
/**
* Unlinks the collection of children from the specified parent.
*
* @param ctx The security context.
* @param parent The parent of the children.
* @param children The children to unlink
* @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 cut(SecurityContext ctx, DataObject parent, Set children)
throws DSOutOfServiceException, DSAccessException
{
IObject mParent = parent.asIObject();
Iterator i = children.iterator();
List<Long> ids = new ArrayList<Long>(children.size());
while (i.hasNext()) {
ids.add(Long.valueOf(((DataObject) i.next()).getId()));
}
List links = gateway.findLinks(ctx, mParent, ids);
if (links != null)
gateway.deleteObjects(ctx, links);
}
/**
* Deletes the tag set.
*
* @param ctx The security context.
* @param id The identifier of the set.
* @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<DataObject> deleteTagSet(SecurityContext ctx, long id)
throws DSOutOfServiceException, DSAccessException
{
List l = gateway.findAnnotationLinks(ctx, Annotation.class,
id, null);
List<Long> tagIds = new ArrayList<Long>();
List<DataObject> tags = new ArrayList<DataObject>();
Iterator i = l.iterator();
AnnotationAnnotationLink link;
long tagID;
while (i.hasNext()) {
link = (AnnotationAnnotationLink) i.next();
tagID = link.getChild().getId().getValue();
if (!tagIds.contains(tagID)) {
tagIds.add(tagID);
tags.add(PojoMapper.asDataObject(link.getChild()));
}
}
//delete the links
gateway.deleteObjects(ctx, l);
return tags;
}
/**
* Returns the user name or <code>null</code> if the passed user is
* the user currently logged in.
*
* @param user The user to handle.
* @return See above.
*/
private String getUserName(ExperimenterData user)
{
ExperimenterData loggedIn = context.getAdminService().getUserDetails();
if (user != null && user.getId() != loggedIn.getId())
return user.getUserName();
return null;
}
/**
* 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>.
*/
OmeroDataServiceImpl(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 OmeroDataService#loadContainerHierarchy(SecurityContext, Class, List, boolean, long)
*/
public Set loadContainerHierarchy(SecurityContext ctx,
Class rootNodeType, List rootNodeIDs, boolean withLeaves,
long userID)
throws DSOutOfServiceException, DSAccessException
{
ParametersI param = new ParametersI();
if (rootNodeIDs == null) {
if (userID >= 0) param.exp(omero.rtypes.rlong(userID));
}
if (withLeaves) param.leaves();
else param.noLeaves();
if (rootNodeIDs == null || rootNodeIDs.size() == 0) {
if (ProjectData.class.equals(rootNodeType) ||
ScreenData.class.equals(rootNodeType))
param.orphan();
}
return gateway.loadContainerHierarchy(ctx, rootNodeType, rootNodeIDs,
param);
}
/**
* Implemented as specified by {@link OmeroDataService}.
* @see OmeroDataService#loadTopContainerHierarchy(SecurityContext, Class, long)
*/
public Set loadTopContainerHierarchy(SecurityContext ctx,
Class rootNodeType, long userID)
throws DSOutOfServiceException, DSAccessException
{
ParametersI param = new ParametersI();
param.exp(omero.rtypes.rlong(userID));
return gateway.loadContainerHierarchy(ctx, rootNodeType, null, param);
}
/**
* Implemented as specified by {@link OmeroDataService}.
* @see OmeroDataService#findContainerHierarchy(SecurityContext, Class, List, long)
*/
public Set findContainerHierarchy(SecurityContext ctx, Class rootNodeType,
List leavesIDs, long userID)
throws DSOutOfServiceException, DSAccessException
{
ParametersI po = new ParametersI();
po.leaves();
po.exp(omero.rtypes.rlong(userID));
return gateway.findContainerHierarchy(ctx, rootNodeType, leavesIDs, po);
}
/**
* Implemented as specified by {@link OmeroDataService}.
* @see OmeroDataService#getImages(SecurityContext, Class, List, long)
*/
public Set getImages(SecurityContext ctx, Class nodeType, List nodeIDs,
long userID)
throws DSOutOfServiceException, DSAccessException
{
if (nodeType == null)
throw new IllegalArgumentException("No type specified.");
ParametersI po = new ParametersI();
if (userID >= 0) po.exp(omero.rtypes.rlong(userID));
return gateway.getContainerImages(ctx, nodeType, nodeIDs, po);
}
/**
* Implemented as specified by {@link OmeroDataService}.
* @see OmeroDataService#getExperimenterImages(SecurityContext, long,
* boolean)
*/
public Collection<ImageData> getExperimenterImages(SecurityContext ctx, long userID, boolean
orphan)
throws DSOutOfServiceException, DSAccessException
{
return gateway.getUserImages(ctx, userID, orphan);
}
/**
* Implemented as specified by {@link OmeroDataService}.
* @see OmeroDataService#getCollectionCount(SecurityContext, Class, String, List)
*/
public Map getCollectionCount(SecurityContext ctx, Class rootNodeType,
String property, List rootNodeIDs)
throws DSOutOfServiceException, DSAccessException
{
if (!(property.equals(IMAGES_PROPERTY)))
throw new IllegalArgumentException("Property not supported.");
//if (rootNodeType.equals(TagAnnotationData.class))
//return gateway.getDataObjectsTaggedCount(rootNodeIDs);
return gateway.getCollectionCount(ctx, rootNodeType, property,
rootNodeIDs, new Parameters());
}
/**
* Implemented as specified by {@link OmeroDataService}.
* @see OmeroDataService#createDataObject(SecurityContext, DataObject,
* DataObject, Collection)
*/
public DataObject createDataObject(SecurityContext ctx, DataObject child,
DataObject parent, Collection children)
throws DSOutOfServiceException, DSAccessException
{
if (child == null)
throw new IllegalArgumentException("The child cannot be null.");
//Make sure parent is current
String userName = getUserName(ctx.getExperimenterData());
IObject obj = ModelMapper.createIObject(child, parent);
if (obj == null)
throw new NullPointerException("Cannot convert the object.");
IObject created = gateway.createObject(ctx, obj, userName);
IObject link;
if (parent != null) {
link = ModelMapper.linkParentToChild(created, parent.asIObject());
if ((child instanceof TagAnnotationData) && link != null) {
gateway.createObject(ctx, link, userName);
}
}
if (children != null && children.size() > 0) {
Iterator i = children.iterator();
Object node;
List<IObject> links = new ArrayList<IObject>();
while (i.hasNext()) {
node = i.next();
if (node instanceof DataObject)
links.add(ModelMapper.linkParentToChild(
((DataObject) node).asIObject(), created));
}
if (links.size() > 0)
gateway.createObjects(ctx, links);
}
return PojoMapper.asDataObject(created);
}
/**
* Implemented as specified by {@link OmeroDataService}.
* @see OmeroDataService#updateDataObject(SecurityContext, DataObject)
*/
public DataObject updateDataObject(SecurityContext ctx, DataObject object)
throws DSOutOfServiceException, DSAccessException
{
if (object == null)
throw new DSAccessException("No object to update.");
if (!object.isDirty()) return object;
ctx = gateway.checkContext(ctx, object);
if (object instanceof ExperimenterData)
return updateExperimenter(ctx, (ExperimenterData) object, null);
if (!object.isLoaded()) return object;
IObject ho = null;
IObject oldObject = null;
oldObject = object.asIObject();
ho = gateway.findIObject(ctx, oldObject);
if (ho == null) return null;
ModelMapper.fillIObject(oldObject, ho);
ModelMapper.unloadCollections(ho);
IObject updated = gateway.updateObject(ctx, ho, new Parameters());
return PojoMapper.asDataObject(updated);
}
/**
* Implemented as specified by {@link OmeroDataService}.
* @see OmeroDataService#addExistingObjects(SecurityContext, DataObject, Collection)
*/
public void addExistingObjects(SecurityContext ctx, DataObject parent,
Collection children)
throws DSOutOfServiceException, DSAccessException
{
ctx = gateway.checkContext(ctx, parent);
if (parent instanceof ProjectData) {
try {
children.toArray(new DatasetData[] {});
} catch (ArrayStoreException ase) {
throw new IllegalArgumentException(
"items can only be datasets.");
}
} else if (parent instanceof GroupData) {
try {
ExperimenterData[] exp =
(ExperimenterData[])
children.toArray(new ExperimenterData[] {});
List<ExperimenterData> list = new ArrayList<ExperimenterData>();
for (int i = 0; i < exp.length; i++) {
list.add(exp[i]);
}
context.getAdminService().addExperimenters(ctx,
(GroupData) parent, list);
return;
} catch (ArrayStoreException ase) {
throw new IllegalArgumentException(
"items can only be experimenters.");
}
} else if (parent instanceof DatasetData) {
try {
children.toArray(new ImageData[] {});
} catch (ArrayStoreException ase) {
throw new IllegalArgumentException(
"items can only be images.");
}
} else if (parent instanceof ScreenData) {
try {
children.toArray(new PlateData[] {});
} catch (ArrayStoreException ase) {
throw new IllegalArgumentException(
"items can only be plate.");
}
} else if (parent instanceof TagAnnotationData) {
TagAnnotationData tagSet = (TagAnnotationData) parent;
if (!TagAnnotationData.INSIGHT_TAGSET_NS.equals(
tagSet.getNameSpace()))
throw new IllegalArgumentException("Parent not supported");
Iterator i = children.iterator();
TagAnnotationData tag;
Object object;
while (i.hasNext()) {
object = i.next();
if (!(object instanceof TagAnnotationData))
throw new IllegalArgumentException(
"items can only be Tag.");
tag = (TagAnnotationData) object;
if (tag.getNameSpace() != null)
throw new IllegalArgumentException(
"items can only be Tag.");
}
} else
throw new IllegalArgumentException("Parent not supported");
List<IObject> objects = new ArrayList<IObject>();
IObject ioParent = parent.asIObject();
IObject ioChild;
Iterator i = children.iterator();
DataObject child;
while (i.hasNext()) {
child = (DataObject) i.next();
if (child.getGroupId() == ctx.getGroupID()) {
ioChild = child.asIObject();
//First make sure that the child is not linked to the parent.
if (gateway.findLink(ctx, ioParent, ioChild) == null)
objects.add(
ModelMapper.linkParentToChild(ioChild, ioParent));
}
}
if (objects.size() != 0)
gateway.createObjects(ctx, objects);
}
/**
* Implemented as specified by {@link OmeroDataService}.
* @see OmeroDataService#cutAndPaste(SecurityContext, Map, Map)
*/
public void cutAndPaste(SecurityContext ctx, Map toPaste, Map toCut)
throws DSOutOfServiceException, DSAccessException
{
if (toPaste == null) toPaste = new HashMap();
if (toCut == null) toCut = new HashMap();
Iterator i;
Object parent;
i = toCut.entrySet().iterator();
Entry entry;
while (i.hasNext()) {
entry = (Entry) i.next();
parent = entry.getKey();
if (parent instanceof DataObject) //b/c of orphaned container
cut(ctx, (DataObject) parent, (Set) entry.getValue());
}
i = toPaste.entrySet().iterator();
while (i.hasNext()) {
entry = (Entry) i.next();
parent = entry.getKey();
if (parent instanceof DataObject)
addExistingObjects(ctx, (DataObject) parent,
(Set) entry.getValue());
}
}
/**
* Implemented as specified by {@link OmeroDataService}.
* @see OmeroDataService#getArchivedFiles(SecurityContext, File, long, boolean)
*/
public Map<Boolean, Object> getArchivedImage(SecurityContext ctx,
File file, long imageID, boolean keepOriginalPath)
throws DSOutOfServiceException, DSAccessException
{
context.getLogger().debug(this, file.getAbsolutePath());
//Check the image is archived.
ImageData image = gateway.getImage(ctx, imageID, null);
return gateway.getArchivedFiles(ctx, file, image, keepOriginalPath);
}
/**
* Implemented as specified by {@link OmeroDataService}.
* @see OmeroDataService#updateExperimenter(SecurityContext, ExperimenterData, GroupData)
*/
public ExperimenterData updateExperimenter(SecurityContext ctx,
ExperimenterData exp, GroupData group)
throws DSOutOfServiceException, DSAccessException
{
if (exp == null)
throw new DSAccessException("No object to update.");
ctx = gateway.checkContext(ctx, exp);
UserCredentials uc = (UserCredentials)
context.lookup(LookupNames.USER_CREDENTIALS);
ExperimenterData user =
(ExperimenterData) context.lookup(
LookupNames.CURRENT_USER_DETAILS);
gateway.updateExperimenter(ctx, exp.asExperimenter(), user.getId());
ExperimenterData data;
if (group != null && exp.getDefaultGroup().getId() != group.getId())
gateway.changeCurrentGroup(ctx, exp, group.getId());
data = gateway.getUserDetails(ctx, uc.getUserName(), true);
context.bind(LookupNames.CURRENT_USER_DETAILS, data);
// Bind user details to all agents' registry.
List agents = (List) context.lookup(LookupNames.AGENTS);
Iterator i = agents.iterator();
AgentInfo agentInfo;
while (i.hasNext()) {
agentInfo = (AgentInfo) i.next();
agentInfo.getRegistry().bind(
LookupNames.CURRENT_USER_DETAILS, data);
}
return data;
}
/**
* Implemented as specified by {@link OmeroDataService}.
* @see OmeroDataService#getImagesPeriod(SecurityContext, Timestamp, Timestamp, long, boolean)
*/
public Collection getImagesPeriod(SecurityContext ctx, Timestamp startTime,
Timestamp endTime, long userID, boolean asDataObject)
throws DSOutOfServiceException, DSAccessException
{
if (startTime == null && endTime == null)
throw new NullPointerException("Time not specified.");
ParametersI po = new ParametersI();
po.leaves();
if (userID >= 0) po.exp(omero.rtypes.rlong(userID));
if (startTime != null)
po.startTime(omero.rtypes.rtime(startTime.getTime()));
if (endTime != null)
po.endTime(omero.rtypes.rtime(endTime.getTime()));
return gateway.getImages(ctx, po, asDataObject);
}
/**
* Implemented as specified by {@link OmeroDataService}.
* @see OmeroDataService#getImagesAllPeriodCount(SecurityContext, Timestamp, Timestamp, long)
*/
public List getImagesAllPeriodCount(SecurityContext ctx,
Timestamp startTime, Timestamp endTime, long userID)
throws DSOutOfServiceException, DSAccessException
{
if (startTime == null || endTime == null)
throw new NullPointerException("Time not specified.");
Collection imgs = getImagesPeriod(ctx, startTime, endTime, userID,
false);
Iterator i = imgs.iterator();
Image object;
List<Timestamp> times = new ArrayList<Timestamp>(imgs.size());
Event evt;
while (i.hasNext()) {
object = (Image) i.next();
evt = object.getDetails().getCreationEvent();
if (evt != null)
times.add(new Timestamp(evt.getTime().getValue()));
}
return times;
}
/**
* Implemented as specified by {@link OmeroDataService}.
* @see OmeroDataService#advancedSearchFor(List, SearchDataContext)
*/
public SearchResultCollection search(SecurityContext ctx,
SearchParameters context)
throws DSOutOfServiceException, DSAccessException
{
if (ctx == null)
throw new IllegalArgumentException("No security context defined.");
if (context == null)
throw new IllegalArgumentException("No search context defined.");
if (!context.isValid())
throw new IllegalArgumentException("Search context not valid.");
SearchResultCollection results = new SearchResultCollection();
// If terms contain ids only, just add them as potential result to the results,
// findByIds() will remove them if they can't be found
long[] ids = convertSearchTermsToIds(context.getQuery());
if(ids!=null) {
for(long id: ids) {
List<Class<? extends DataObject>> types = new ArrayList<Class<? extends DataObject>>();
if(context.getTypes().isEmpty()) {
types.add(ImageData.class);
types.add(DatasetData.class);
types.add(ProjectData.class);
types.add(ScreenData.class);
types.add(PlateData.class);
}
else {
types = context.getTypes();
}
for(Class<? extends DataObject> type : types) {
SearchResult res = new SearchResult();
res.setObjectId(id);
res.setType(type);
res.setIdMatch(true);
results.add(res);
}
}
}
// search by ID:
if(!results.isEmpty())
findByIds(ctx, results, true);
// search by text:
SearchResultCollection searchResults = gateway.search(ctx, context);
results.addAll(searchResults);
if (searchResults.isError())
results.setError(searchResults.getError());
// loads the images PixelsData (needed for thumbnail request)
initializeImages(results);
return results;
}
/**
* Tries to find and load the Objects in results; removes them from results
* if they can't be found.
* @param ctx
* @param results
* @param allGroups
*/
private void findByIds(SecurityContext ctx, SearchResultCollection results, boolean allGroups) throws DSOutOfServiceException{
Iterator<SearchResult> it = results.iterator();
while (it.hasNext()) {
SearchResult r = it.next();
IObject obj = null;
try {
String type = PojoMapper.convertTypeForSearchByQuery(r.getType());
String query = "select x from "+type+" x join fetch x.details.creationEvent where x.id="+r.getObjectId();
obj = gateway.findIObjectByQuery(ctx, query, true);
} catch (DSAccessException e) {
// Object can't be found/loaded; just skip it
// and remove the regarding search result
}
if (obj == null)
it.remove();
else {
r.setObject(PojoMapper.asDataObject(obj));
}
}
}
/**
* Skims through the results and loads all images via the Containerservice.
* This is necessary to load the image's PixelsData.
* @param results
*/
private void initializeImages(SearchResultCollection results) {
Map<Long, List<SearchResult>> byGroup = results
.getByGroup(ImageData.class);
for (long groupId : byGroup.keySet()) {
List<Long> ids = new ArrayList<Long>();
for (SearchResult r : byGroup.get(groupId)) {
ids.add(r.getObjectId());
}
SecurityContext ctx = new SecurityContext(groupId);
try {
Set tmp = gateway.getContainerImages(ctx, ImageData.class, ids,
new Parameters());
for(Object obj : tmp) {
ImageData img = (ImageData) obj;
for(SearchResult r : byGroup.get(groupId)) {
if(r.getObjectId()==img.getId()) {
r.setObject(img);
break;
}
}
}
} catch (Exception e) {
}
}
}
/**
* Tries to convert all search terms into ids;
* @param terms
* @return The ids or null if one or multiple terms contain non numeric characters
*/
private long[] convertSearchTermsToIds(String query) {
// split by commas and spaces
String[] tmp = query.split("\\s|\\s*,\\s*");
long[] result = new long[tmp.length];
try {
for (int i = 0; i < tmp.length; i++) {
result[i] = Long.parseLong(tmp[i]);
}
} catch (NumberFormatException e) {
// hit a term with non numeric characters
return null;
}
return result;
}
/**
* Implemented as specified by {@link OmeroDataService}.
* @see OmeroDataService#findContainerPaths(SecurityContext, Class, long,
* long)
*/
public Collection findContainerPaths(SecurityContext ctx,
Class type, long id, long userID)
throws DSOutOfServiceException, DSAccessException
{
try {
Class parentClass = PojoMapper.getModelType(type);
if (DatasetData.class.equals(type))
parentClass = Project.class;
else if (ImageData.class.equals(type))
parentClass = Dataset.class;
else if (PlateData.class.equals(type))
parentClass = Screen.class;
else if (TagAnnotationData.class.equals(type))
parentClass = TagAnnotation.class;
else if (FileAnnotationData.class.equals(type))
parentClass = FileAnnotation.class;
else if (WellSampleData.class.equals(type) ||
WellData.class.equals(type))
parentClass = Plate.class;
else if (PlateAcquisitionData.class.equals(type))
parentClass = Plate.class;
if (parentClass == null) return new HashSet();
List links = gateway.findLinks(ctx, parentClass, id, userID);
if (ImageData.class.equals(type) && (links == null ||
links.size() == 0)) {
return gateway.findPlateFromImage(ctx, id, userID);
}
if (PlateAcquisitionData.class.equals(type) && (links == null ||
links.size() == 0)) {
return gateway.findPlateFromRun(ctx, id, userID);
}
if (links == null) return new HashSet();
Iterator i = links.iterator();
Set<DataObject> nodes = new HashSet<DataObject>();
IObject object, parent = null;
DataObject data;
List<Long> ids = new ArrayList<Long>();
long parentId;
IObject link;
while (i.hasNext()) {
if (parentClass.equals(Project.class))
parent = ((ProjectDatasetLink) i.next()).getParent();
else if (parentClass.equals(Dataset.class))
parent = ((DatasetImageLink) i.next()).getParent();
else if (parentClass.equals(Screen.class))
parent = ((ScreenPlateLink) i.next()).getParent();
else if (parentClass.equals(TagAnnotation.class))
parent = ((AnnotationAnnotationLink) i.next()).getParent();
else if (parentClass.equals(FileAnnotation.class)) {
link = (IObject) i.next();
if (link instanceof ProjectAnnotationLink)
parent = ((ProjectAnnotationLink) link).getParent();
else if (link instanceof DatasetAnnotationLink)
parent = ((DatasetAnnotationLink) link).getParent();
else if (link instanceof ImageAnnotationLink)
parent = ((ImageAnnotationLink) link).getParent();
else if (link instanceof PlateAnnotationLink)
parent = ((PlateAnnotationLink) link).getParent();
else if (link instanceof ScreenAnnotationLink)
parent = ((ScreenAnnotationLink) link).getParent();
}
parentId = parent.getId().getValue();
if (!ids.contains(parentId)) {
object = gateway.findIObject(ctx,
parent.getClass().getName(),
parent.getId().getValue());
data = PojoMapper.asDataObject(object);
if (TagAnnotation.class.equals(parentClass)) {
if (data instanceof TagAnnotationData) {
TagAnnotationData tag = (TagAnnotationData) data;
if (TagAnnotationData.INSIGHT_TAGSET_NS.equals(
tag.getNameSpace())) {
nodes.add(data);
}
}
} else nodes.add(data);
ids.add(parentId);
}
}
return nodes;
} catch (Exception e) {
throw new DSAccessException(e.getMessage());
}
}
/**
* Implemented as specified by {@link OmeroDataService}.
* @see OmeroDataService#getOriginalFiles(SecurityContext, long)
*/
public Collection getOriginalFiles(SecurityContext ctx, long pixelsID)
throws DSOutOfServiceException, DSAccessException
{
if (pixelsID < 0)
throw new IllegalArgumentException("Pixels set ID not valid.");
return gateway.getOriginalFiles(ctx, pixelsID);
}
/**
* Implemented as specified by {@link OmeroDataService}.
* @see OmeroDataService#loadPlateWells(SecurityContext, long, long, long)
*/
public Collection loadPlateWells(SecurityContext ctx,
long plateID, long acquisitionID, long userID)
throws DSOutOfServiceException, DSAccessException
{
return gateway.loadPlateWells(ctx, plateID, acquisitionID);
}
/**
* Implemented as specified by {@link OmeroDataService}.
*
* @see OmeroDataService#delete(SecurityContext, Collection)
*/
public RequestCallback delete(SecurityContext ctx,
Collection<DeletableObject> objects)
throws DSOutOfServiceException, DSAccessException, ProcessException {
if (CollectionUtils.isEmpty(objects) || ctx == null)
return null;
Iterator<DeletableObject> it = objects.iterator();
DeletableObject object;
while (it.hasNext()) {
object = it.next();
if (object.getGroupId() != ctx.getGroupID()) {
it.remove();
}
}
if (objects.size() == 0)
return null;
Map<String, List<Long>> toDelete = new HashMap<String, List<Long>>();
Map<String, List<ChildOption>> options = new HashMap<String, List<ChildOption>>();
for (DeletableObject delo : objects) {
List<ChildOption> opts = new ArrayList<ChildOption>();
DataObject data = delo.getObjectToDelete();
if (!CollectionUtils.isEmpty(delo.getAnnotations())) {
opts.add(Requests.option(null,
PojoMapper.getGraphType(AnnotationData.class)));
}
if (!delo.deleteContent()) {
if (data instanceof DatasetData) {
opts.add(Requests.option(null,
PojoMapper.getGraphType(ImageData.class)));
} else if (data instanceof ProjectData) {
opts.add(Requests.option(null,
PojoMapper.getGraphType(DatasetData.class)));
opts.add(Requests.option(null,
PojoMapper.getGraphType(ImageData.class)));
} else if (data instanceof ScreenData) {
opts.add(Requests.option(null,
PojoMapper.getGraphType(PlateData.class)));
opts.add(Requests.option(null,
PojoMapper.getGraphType(WellData.class)));
opts.add(Requests.option(null,
PojoMapper.getGraphType(PlateAcquisitionData.class)));
opts.add(Requests.option(null,
PojoMapper.getGraphType(ImageData.class)));
} else if (data instanceof PlateData) {
opts.add(Requests.option(null,
PojoMapper.getGraphType(PlateAcquisitionData.class)));
opts.add(Requests.option(null,
PojoMapper.getGraphType(ImageData.class)));
} else if (data instanceof PlateAcquisitionData) {
opts.add(Requests.option(null,
PojoMapper.getGraphType(ImageData.class)));
}
else if (data instanceof TagAnnotationData) {
String ns = ((TagAnnotationData) data).getNameSpace();
if (TagAnnotationData.INSIGHT_TAGSET_NS.equals(ns)) {
deleteTagSet(ctx, data.getId());
}
}
}
String type = PojoMapper.getGraphType(data.getClass());
List<Long> ids = toDelete.get(type);
if (ids == null) {
ids = new ArrayList<Long>();
toDelete.put(type, ids);
}
ids.add(delo.getObjectToDelete().getId());
options.put(type, opts);
}
List<Request> cmds = new ArrayList<Request>();
for (String type : toDelete.keySet()) {
cmds.add(Requests.delete(type, toDelete.get(type),
options.get(type)));
}
return gateway.submit(cmds, ctx);
}
/**
* Implemented as specified by {@link OmeroDataService}.
* @see OmeroDataService#getFSRepositories(SecurityContext, long)
*/
public FSFileSystemView getFSRepositories(SecurityContext ctx, long userID)
throws DSOutOfServiceException, DSAccessException
{
return gateway.getFSRepositories(ctx, userID);
}
/**
* Implemented as specified by {@link OmeroDataService}.
* @see OmeroDataService#transfer(SecurityContext, SecurityContext, List,
* List)
*/
public RequestCallback transfer(SecurityContext ctx,
SecurityContext target, List<DataObject> targetNodes,
List<DataObject> objects)
throws DSOutOfServiceException, DSAccessException, ProcessException
{
if (target == null)
throw new IllegalArgumentException("No target specified.");
if (objects == null || objects.size() == 0)
throw new IllegalArgumentException("No object to move.");
Iterator<DataObject> i = objects.iterator();
Map<DataObject, List<IObject>> map =
new HashMap<DataObject, List<IObject>>();
DataObject data;
List<IObject> l;
Iterator<DataObject> j;
DataObject object;
IObject link;
String userName = getUserName(ctx.getExperimenterData());
ExperimenterData exp = context.getAdminService().getUserDetails();
ExperimenterData owner;
Experimenter o = null;
IObject newObject;
PermissionData perms;
List<IObject> targets = new ArrayList<IObject>();
while (i.hasNext()) {
data = i.next();
owner = data.getOwner();
perms = data.getPermissions();
if (owner.getId() != exp.getId() &&
perms.getPermissionsLevel() == GroupData.PERMISSIONS_PRIVATE) {
o = new ExperimenterI(owner.getId(), false);
break;
}
}
if (!CollectionUtils.isEmpty(targetNodes)) {
List<IObject> toCreate = new ArrayList<IObject>();
j = targetNodes.iterator();
while (j.hasNext()) {
object = j.next();
if (object != null) {
if (object.getId() < 0) {
newObject = object.asIObject();
if (newObject != null && o != null) {
newObject.getDetails().setOwner(o);
}
toCreate.add(newObject);
} else targets.add(object.asIObject());
}
}
if (toCreate.size() > 0) {
toCreate = gateway.saveAndReturnObject(target, toCreate,
new HashMap<Object, Object>(), userName);
targets.addAll(toCreate);
}
}
i = objects.iterator();
Iterator<IObject> k;
boolean notEmpty = !CollectionUtils.isEmpty(targets);
while (i.hasNext()) {
data = i.next();
owner = data.getOwner();
perms = data.getPermissions();
l = new ArrayList<IObject>();
if (notEmpty) {
k = targets.iterator();
while (k.hasNext()) {
newObject = k.next();
if (newObject != null) {
//due to move all option when moving mif
//the following scenario could happen
//select a dataset to move to a Project
//missing image from mif will be added to the queue
//(Move all) The image cannot be linked to the target
//i.e. project so an exception is thrown
try {
link = ModelMapper.linkParentToChild(
data.asIObject(), newObject);
if (link != null) {
if (o != null) link.getDetails().setOwner(o);
l.add(link);
}
} catch (Exception e) {
StringBuffer buffer = new StringBuffer();
buffer.append("Cannot link ");
buffer.append(data.getClass());
buffer.append(" to ");
buffer.append(newObject.getClass());
buffer.append(" ");
LogMessage msg = new LogMessage();
msg.print(buffer.toString());
msg.print(e);
context.getLogger().debug(this, msg);
}
}
}
}
map.put(data, l);
}
Map<String, String> options = new HashMap<String, String>();
return gateway.transfer(ctx, target, map, options);
}
/**
* Implemented as specified by {@link OmeroDataService}.
* @see OmeroDataService#loadPlateFromImage(SecurityContext, Collection)
*/
public Map<Long, PlateData> loadPlateFromImage(SecurityContext ctx,
Collection<Long> ids)
throws DSOutOfServiceException, DSAccessException
{
if (CollectionUtils.isEmpty(ids))
throw new IllegalArgumentException("No images specified.");
Map<Long, PlateData> r = new HashMap<Long, PlateData>();
Iterator<Long> i = ids.iterator();
Long id;
while (i.hasNext()) {
id = i.next();
r.put(id, gateway.getImportedPlate(ctx, id));
}
return r;
}
/**
* Implemented as specified by {@link OmeroDataService}.
* @see OmeroDataService#closeService(SecurityContext,
* StatefulServiceInterfacePrx)
*/
public void closeService(SecurityContext ctx,
StatefulServiceInterfacePrx svc)
{
if (ctx == null || svc == null) return;
gateway.closeService(ctx, svc);
}
/**
* Implemented as specified by {@link OmeroDataService}.
* @see OmeroDataService#getImagesBySplitFilesets(SecurityContext, Class,
* List)
*/
public Map<Long, Map<Boolean, List<ImageData>>> getImagesBySplitFilesets(
SecurityContext ctx, Class<?> rootType, List<Long> rootIDs)
throws DSOutOfServiceException, DSAccessException
{
if (CollectionUtils.isEmpty(rootIDs) || rootType == null)
throw new IllegalArgumentException("No objects specified.");
ParametersI param = new ParametersI();
Map<Long, Map<Boolean, List<Long>>> m =
gateway.getImagesBySplitFilesets(ctx, rootType, rootIDs, param);
Map<Long, Map<Boolean, List<ImageData>>>
r = new HashMap<Long, Map<Boolean, List<ImageData>>>();
if (m == null || m.size() == 0) return r;
List<Long> ids = new ArrayList<Long>();
Iterator<Map<Boolean, List<Long>>> i = m.values().iterator();
while (i.hasNext()) {
Map<Boolean, List<Long>> map = i.next();
Iterator<List<Long>> j = map.values().iterator();
while (j.hasNext()) {
ids.addAll(j.next());
}
}
Set<ImageData> imgs = getImages(ctx, ImageData.class, ids, -1);
Map<Long, ImageData> idMap = new HashMap<Long, ImageData>(imgs.size());
Iterator<ImageData> k = imgs.iterator();
ImageData img;
while (k.hasNext()) {
img = k.next();
idMap.put(img.getId(), img);
}
Entry<Long, Map<Boolean, List<Long>>> e;
Iterator<Entry<Long, Map<Boolean, List<Long>>>> ii =
m.entrySet().iterator();
List<Long> l;
Entry<Boolean, List<Long>> entry;
Iterator<Entry<Boolean, List<Long>>> j;
while (ii.hasNext()) {
e = ii.next();
j = e.getValue().entrySet().iterator();
Map<Boolean, List<ImageData>> converted =
new HashMap<Boolean, List<ImageData>>();
while (j.hasNext()) {
entry = j.next();
l = entry.getValue();
Iterator<Long> kk = l.iterator();
List<ImageData> convertedList = new ArrayList<ImageData>();
while (kk.hasNext()) {
convertedList.add(idMap.get(kk.next()));
}
converted.put(entry.getKey(), convertedList);
}
r.put(e.getKey(), converted);
}
return r;
}
/**
* Implemented as specified by {@link OmeroDataService}.
* @see OmeroDataService#findDatasetsByImageId(SecurityContext ctx, imgId)
*/
public Map<Long, List<DatasetData>> findDatasetsByImageId(SecurityContext ctx, List<Long> imgIds) throws DSOutOfServiceException, DSAccessException
{
Map<Long, List<DatasetData>> result = new HashMap<Long, List<DatasetData>>();
List queryResult = gateway.findDatasetLinks(ctx, imgIds, -1);
for(Object tmp : queryResult) {
if(tmp instanceof DatasetImageLink) {
DatasetImageLink dl = ((DatasetImageLink) tmp);
DatasetData dsd = (DatasetData) PojoMapper.asDataObject(dl.getParent());
long imgId = dl.getChild().getId().getValue();
List<DatasetData> sets = result.get(imgId);
if(sets == null) {
sets = new ArrayList<DatasetData>();
result.put(imgId, sets);
}
sets.add(dsd);
}
}
return result;
}
}