/*
* Copyright (C) 2006-2014 University of Dundee & Open Microscopy Environment.
* All rights reserved.
*
* Use is subject to license terms supplied in LICENSE.txt
*/
package ome.logic;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.transaction.annotation.Transactional;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimaps;
import com.google.common.collect.SetMultimap;
import ome.annotations.NotNull;
import ome.annotations.RolesAllowed;
import ome.annotations.Validate;
import ome.api.IContainer;
import ome.api.IMetadata;
import ome.api.ServiceInterface;
import ome.conditions.ApiUsageException;
import ome.model.IAnnotated;
import ome.model.ILink;
import ome.model.IObject;
import ome.model.annotations.DatasetAnnotationLink;
import ome.model.annotations.FileAnnotation;
import ome.model.annotations.ImageAnnotationLink;
import ome.model.annotations.PlateAnnotationLink;
import ome.model.annotations.ProjectAnnotationLink;
import ome.model.annotations.ScreenAnnotationLink;
import ome.model.annotations.TagAnnotation;
import ome.model.acquisition.Arc;
import ome.model.acquisition.Filament;
import ome.model.acquisition.Instrument;
import ome.model.acquisition.Laser;
import ome.model.acquisition.LightEmittingDiode;
import ome.model.acquisition.LightSettings;
import ome.model.acquisition.LightSource;
import ome.model.annotations.Annotation;
import ome.model.containers.Dataset;
import ome.model.containers.Project;
import ome.model.core.Image;
import ome.model.core.LogicalChannel;
import ome.model.core.OriginalFile;
import ome.model.fs.Fileset;
import ome.model.screen.Plate;
import ome.model.screen.PlateAcquisition;
import ome.model.screen.Screen;
import ome.model.screen.Well;
import ome.parameters.Parameters;
import ome.services.query.PojosFindAnnotationsQueryDefinition;
import ome.services.query.Query;
/**
* Implement the {@link IMetadata} 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>
* @since 3.0-Beta4
*/
public class MetadataImpl
extends AbstractLevel2Service
implements IMetadata
{
/** Query to load the original file related to a file annotation. */
private final String LOAD_ORIGINAL_FILE =
"select p from OriginalFile as p left outer join fetch p.hasher where p.id = :id";
/* HQL to translate given image IDs into corresponding fileset IDs */
private static final String LOAD_FILESET_OF_IMAGE =
"SELECT id, fileset.id FROM Image WHERE fileset IS NOT NULL AND id IN (:ids)";
/* HQL to translate given fileset IDs into corresponding import log IDs */
private static final String LOAD_IMPORT_LOGS =
"SELECT fjl.parent.id, o FROM UploadJob u, FilesetJobLink fjl, JobOriginalFileLink jol, OriginalFile o " +
"WHERE fjl.parent.id IN (:ids) AND fjl.child = jol.parent AND jol.child.id = o.id AND fjl.child = u AND " +
"o.mimetype = '" + "application/omero-log-file" /*PublicRepositoryI.IMPORT_LOG_MIMETYPE*/ + "'";
/** Identifies the file annotation class. */
private final String FILE_TYPE = "ome.model.annotations.FileAnnotation";
/** Identifies the tag annotation class. */
private final String TAG_TYPE = "ome.model.annotations.TagAnnotation";
/** Reference to the {@link IContainer} service. */
private IContainer iContainer;
/**
* Builds the <code>StringBuilder</code> corresponding to the passed
* light source.
*
* @param src The light source to handle.
* @param instrument Pass <code>true</code> for clause on id,
* <code>false</code> for clause on instrument
* @return See above.
*/
private StringBuilder createLightQuery(LightSource src, boolean idClause)
{
if (src == null) return null;
StringBuilder sb = new StringBuilder();
if (src instanceof Laser) {
sb.append("select l from Laser as l ");
sb.append("left outer join fetch l.type ");
sb.append("left outer join fetch l.laserMedium ");
sb.append("left outer join fetch l.pulse as pulse ");
//sb.append("left outer join fetch l.pump as pump ");
if (idClause)
sb.append("where l.id = :id");
else sb.append("where l.instrument.id = :instrumentId");
} else if (src instanceof Filament) {
sb.append("select l from Filament as l ");
sb.append("left outer join fetch l.type ");
if (idClause)
sb.append("where l.id = :id");
else sb.append("where l.instrument.id = :instrumentId");
} else if (src instanceof Arc) {
sb.append("select l from Arc as l ");
sb.append("left outer join fetch l.type ");
if (idClause)
sb.append("where l.id = :id");
else sb.append("where l.instrument.id = :instrumentId");
} else sb = null;
return sb;
}
/**
* Retrieves the annotation of the given type.
*
* @param type The type of annotation to retrieve.
* @param include The collection of name spaces to include.
* @param exclude The collection of name spaces to exclude.
* @param rootType The type of objects the annotations are linked to.
* @param rootNodeIds The identifiers of the objects.
* @param options The options if any.
* @return See above.
*/
private List<IObject> getAnnotation(@NotNull Class type,
Set<String> include, Set<String> exclude, Class rootType,
Set<Long> rootNodeIds, Parameters options)
{
StringBuilder sb = new StringBuilder();
if (rootType == null)
sb.append("select ann from Annotation as ann ");
else if (Image.class.getName().equals(rootType.getName()))
sb.append("select l from ImageAnnotationLink as l ");
else if (Dataset.class.getName().equals(rootType.getName()))
sb.append("select l from DatasetAnnotationLink as l ");
else if (Project.class.getName().equals(rootType.getName()))
sb.append("select l from ProjectAnnotationLink as l ");
else if (Screen.class.getName().equals(rootType.getName()))
sb.append("select l from ScreenAnnotationLink as l ");
else if (Plate.class.getName().equals(rootType.getName()))
sb.append("select l from PlateAnnotationLink as l ");
else if (PlateAcquisition.class.getName().equals(rootType.getName()))
sb.append("select l from PlateAcquisitionAnnotationLink as l ");
else if (Well.class.getName().equals(rootType.getName()))
sb.append("select l from WellAnnotationLink as l ");
else if (Fileset.class.getName().equals(rootType.getName()))
sb.append("select l from FilesetAnnotationLink as l ");
if (rootType != null) {
sb.append("left outer join fetch l.parent ");
sb.append("left outer join fetch l.child as ann ");
}
sb.append("left outer join fetch ann.details.creationEvent ");
sb.append("left outer join fetch ann.details.owner ");
sb.append("where ann member of "+type.getName());
Parameters param = new Parameters();
Parameters po = new Parameters(options);
if (po.getExperimenter() != null) {
sb.append(" and ann.details.owner.id = :userId");
param.addLong("userId", po.getExperimenter());
}
if (include != null && include.size() > 0) {
sb.append(" and ann.ns is not null and ann.ns in (:include)");
param.addSet("include", include);
}
if (exclude != null && exclude.size() > 0) {
sb.append(" and (ann.ns is null or ann.ns not in (:exclude))");
param.addSet("exclude", exclude);
}
if (rootNodeIds != null && rootNodeIds.size() > 0) {
sb.append(" and l.parent.id in (:rootNodeIds)");
param.addSet("rootNodeIds", rootNodeIds);
}
return iQuery.findAllByQuery(sb.toString(), param);
}
/**
* Retrieves the annotation of the given type.
*
* @param type The type of annotation to retrieve.
* @param include The collection of name spaces to include.
* @param exclude The collection of name spaces to exclude.
* @param options The options if any.
* @return See above.
*/
private List<IObject> getAnnotation(@NotNull Class type,
Set<String> include, Set<String> exclude, Parameters options)
{
return getAnnotation(type, include, exclude, null, null, options);
}
/**
* Returns the Interface implemented by this class.
*
* @return See above.
*/
public final Class<? extends ServiceInterface> getServiceInterface() {
return IMetadata.class;
}
/**
* IContainer bean injector. For use during configuration. Can only be called
* once.
* @param iContainer The value to set.
*/
public final void setIContainer(IContainer iContainer)
{
getBeanHelper().throwIfAlreadySet(this.iContainer, iContainer);
this.iContainer = iContainer;
}
/**
* Counts the number of <code>IObject</code>s (Project, Dataset or Image)
* linked to the specified tag.
*
* @param tagID The id of the tag.
* @return See above.
*/
private long countTaggedObjects(long tagID)
{
Parameters param = new Parameters();
param.addId(tagID);
StringBuilder sb = new StringBuilder();
sb.append("select img from Image as img ");
sb.append("left outer join fetch img.annotationLinks ail ");
sb.append("where ail.child.id = :id");
List l = iQuery.findAllByQuery(sb.toString(), param);
long n = 0;
if (l != null) n += l.size();
sb = new StringBuilder();
sb.append("select d from Dataset as d ");
sb.append("left outer join fetch d.annotationLinks ail ");
sb.append("where ail.child.id = :id");
l = iQuery.findAllByQuery(sb.toString(), param);
if (l != null) n += l.size();
sb = new StringBuilder();
sb.append("select p from Project as p ");
sb.append("left outer join fetch p.annotationLinks ail ");
sb.append("where ail.child.id = :id");
l = iQuery.findAllByQuery(sb.toString(), param);
if (l != null) n += l.size();
sb = new StringBuilder();
sb.append("select p from Screen as p ");
sb.append("left outer join fetch p.annotationLinks ail ");
sb.append("where ail.child.id = :id");
l = iQuery.findAllByQuery(sb.toString(), param);
if (l != null) n += l.size();
sb = new StringBuilder();
sb.append("select p from Plate as p ");
sb.append("left outer join fetch p.annotationLinks ail ");
sb.append("where ail.child.id = :id");
l = iQuery.findAllByQuery(sb.toString(), param);
if (l != null) n += l.size();
return n;
}
/**
* Loads the objects linked to a tag.
*
* @param id The id of the tag.
* @param options The options.
* @return See above.
*/
private Set<IObject> loadObjects(long id, Parameters options)
{
Parameters param = new Parameters();
param.addId(id);
StringBuilder sb = new StringBuilder();
Set result = new HashSet(); //images linked to it.
sb.append("select img from Image as img ");
sb.append("left outer join fetch "
+ "img.annotationLinksCountPerOwner img_a_c ");
sb.append("left outer join fetch img.annotationLinks ail ");
sb.append("left outer join fetch ail.child child ");
sb.append("left outer join fetch ail.parent parent ");
sb.append("left outer join fetch child.details.owner ownerChild ");
sb.append("left outer join fetch parent.details.owner ownerParent ");
sb.append("left outer join fetch img.pixels as pix ");
sb.append("left outer join fetch pix.pixelsType as pt ");
sb.append("where child.id = :id");
List l = iQuery.findAllByQuery(sb.toString(), param);
if (l != null) result.addAll(l);
sb = new StringBuilder();
sb.append("select d from Dataset as d ");
sb.append("left outer join fetch "
+ "d.annotationLinksCountPerOwner d_a_c ");
sb.append("left outer join fetch d.annotationLinks ail ");
sb.append("left outer join fetch ail.child child ");
sb.append("left outer join fetch ail.parent parent ");
sb.append("left outer join fetch child.details.owner ownerChild ");
sb.append("left outer join fetch parent.details.owner ownerParent ");
sb.append("where child.id = :id");
l = iQuery.findAllByQuery(sb.toString(), param);
if (l != null) result.addAll(l);
sb = new StringBuilder();
sb.append("select pl from Plate as pl ");
sb.append("left outer join fetch "
+ "pl.annotationLinksCountPerOwner pl_a_c ");
sb.append("left outer join fetch pl.annotationLinks ail ");
sb.append("left outer join fetch ail.child child ");
sb.append("left outer join fetch ail.parent parent ");
sb.append("where child.id = :id");
l = iQuery.findAllByQuery(sb.toString(), param);
if (l != null) result.addAll(l);
sb = new StringBuilder();
sb.append("select p from Project as p ");
sb.append("left outer join fetch "
+ "p.annotationLinksCountPerOwner p_a_c ");
sb.append("left outer join fetch p.annotationLinks ail ");
sb.append("left outer join fetch ail.child child ");
sb.append("left outer join fetch ail.parent parent ");
sb.append("left outer join fetch child.details.owner ownerChild ");
sb.append("left outer join fetch parent.details.owner ownerParent ");
sb.append("where child.id = :id");
l = iQuery.findAllByQuery(sb.toString(), param);
if (l != null && l.size() > 0) {
Set<Long> ids = new HashSet<Long>();
Iterator i = l.iterator();
while (i.hasNext()) {
ids.add(((IObject) i.next()).getId());
}
Parameters po = new Parameters(options);
po.noLeaves();
po.noOrphan();
Set p = iContainer.loadContainerHierarchy(Project.class, ids, po);
result.addAll(p);
}
sb = new StringBuilder();
sb.append("select s from Screen as s ");
sb.append("left outer join fetch "
+ "s.annotationLinksCountPerOwner s_a_c ");
sb.append("left outer join fetch s.annotationLinks ail ");
sb.append("left outer join fetch ail.child child ");
sb.append("left outer join fetch ail.parent parent ");
sb.append("left outer join fetch child.details.owner ownerChild ");
sb.append("left outer join fetch parent.details.owner ownerParent ");
sb.append("where child.id = :id");
l = iQuery.findAllByQuery(sb.toString(), param);
if (l != null && l.size() > 0) {
Set<Long> ids = new HashSet<Long>();
Iterator i = l.iterator();
while (i.hasNext()) {
ids.add(((IObject) i.next()).getId());
}
Parameters po = new Parameters(options);
po.noLeaves();
po.noOrphan();
Set p = iContainer.loadContainerHierarchy(Screen.class, ids, po);
result.addAll(p);
}
return result;
}
@Override
@RolesAllowed("user")
@Transactional(readOnly = true)
public Instrument loadInstrument(long id)
{
StringBuilder sb = new StringBuilder();
sb.append("select inst from Instrument as inst ");
sb.append("left outer join fetch inst.microscope as m ");
sb.append("left outer join fetch m.type ");
//objective
sb.append("left outer join fetch inst.objective as o ");
sb.append("left outer join fetch o.immersion ");
sb.append("left outer join fetch o.correction ");
//detector
sb.append("left outer join fetch inst.detector as d ");
sb.append("left outer join fetch d.type ");
//filter
sb.append("left outer join fetch inst.filter as f ");
sb.append("left outer join fetch f.type ");
sb.append("left outer join fetch f.transmittanceRange as trans ");
//filterset
sb.append("left outer join fetch inst.filterSet as fs ");
sb.append("left outer join fetch fs.dichroic as dichroic ");
//dichroic
sb.append("left outer join fetch inst.dichroic as di ");
//OTF
sb.append("left outer join fetch inst.otf as otf ");
sb.append("left outer join fetch otf.pixelsType as type ");
sb.append("left outer join fetch otf.objective as obj ");
sb.append("left outer join fetch obj.immersion ");
sb.append("left outer join fetch obj.correction ");
sb.append("left outer join fetch otf.filterSet ");
//light source
sb.append("left outer join fetch inst.lightSource as ls ");
sb.append("where inst.id = :id ");
Parameters params = new Parameters();
params.addId(id);
Instrument value = iQuery.findByQuery(sb.toString(), params);
if (value == null) return null;
LightSource ls;
Iterator<LightSource> i = value.iterateLightSource();
Laser laser;
if (i != null) {
params = new Parameters();
params.addLong("instrumentId", id);
List<String> names = new ArrayList<String>();
String name;
StringBuilder builder;
List<IObject> list = new ArrayList<IObject>();
while (i.hasNext()) {
ls = i.next();
if (ls instanceof LightEmittingDiode) {
list.add(ls);
} else {
name = ls.getClass().getName();
if (!names.contains(name)) {
names.add(name);
builder = createLightQuery(ls, false);
if (builder != null) {
list.addAll(
iQuery.findAllByQuery(builder.toString(),
params));
}
}
}
}
value.clearLightSource();
Iterator<IObject> j = list.iterator();
while (j.hasNext()) {
value.addLightSource((LightSource) j.next());
}
}
return value;
}
@Override
@RolesAllowed("user")
@Transactional(readOnly = true)
public Set loadChannelAcquisitionData(@NotNull
@Validate(Long.class) Set<Long> ids)
{
StringBuilder sb = new StringBuilder();
sb.append("select channel from LogicalChannel as channel ");
sb.append("left outer join fetch channel.mode as mode ");
sb.append("left outer join fetch channel.illumination as illumination ");
sb.append("left outer join fetch channel.contrastMethod as cm ");
sb.append("left outer join fetch channel.detectorSettings as ds ");
sb.append("left outer join fetch channel.lightSourceSettings as lss ");
sb.append("left outer join fetch lss.microbeamManipulation ");
//
sb.append("left outer join fetch channel.otf as otf ");
sb.append("left outer join fetch otf.pixelsType ");
sb.append("left outer join fetch otf.objective as objective ");
sb.append("left outer join fetch objective.immersion ");
sb.append("left outer join fetch objective.correction ");
sb.append("left outer join fetch otf.filterSet as otffilter ");
sb.append("left outer join fetch otffilter.dichroic as otfdichroic ");
sb.append("left outer join fetch channel.filterSet as filter ");
sb.append("left outer join fetch filter.dichroic as dichroic ");
//emission filters
sb.append("left outer join fetch filter.emissionFilterLink as efl ");
sb.append("left outer join fetch efl.child as ef ");
sb.append("left outer join fetch ef.transmittanceRange as efTrans ");
sb.append("left outer join fetch ef.type as type1 ");
//excitation filters
sb.append("left outer join fetch filter.excitationFilterLink as exfl ");
sb.append("left outer join fetch exfl.child as exf ");
sb.append("left outer join fetch exf.transmittanceRange as exfTrans ");
sb.append("left outer join fetch exf.type as type2 ");
sb.append("left outer join fetch channel.lightPath as lp ");
sb.append("left outer join fetch lp.dichroic as dichroic ");
//emission filters
sb.append("left outer join fetch lp.emissionFilterLink as efLpl ");
sb.append("left outer join fetch efLpl.child as efLp ");
sb.append("left outer join fetch efLp.transmittanceRange as efLpTrans ");
sb.append("left outer join fetch efLp.type as type3 ");
//excitation filters
sb.append("left outer join fetch lp.excitationFilterLink as exfLpl ");
sb.append("left outer join fetch exfLpl.child as exfLp ");
sb.append("left outer join fetch exfLp.transmittanceRange as exfLpTrans ");
sb.append("left outer join fetch exfLp.type as type4 ");
sb.append("left outer join fetch ds.detector as detector ");
sb.append("left outer join fetch detector.type ");
sb.append("left outer join fetch ds.binning as binning ");
sb.append("left outer join fetch lss.lightSource as light ");
sb.append("left outer join fetch light.instrument as instrument ");
sb.append("where channel.id in (:ids)");
List<LogicalChannel> list = iQuery.findAllByQuery(sb.toString(),
new Parameters().addIds(ids));
Iterator<LogicalChannel> i = list.iterator();
LogicalChannel channel;
LightSettings light;
LightSource src, pump;
Parameters params;
Laser laser;
while (i.hasNext()) {
channel = i.next();
light = channel.getLightSourceSettings();
if (light != null) {
src = light.getLightSource();
if (!(src instanceof LightEmittingDiode)) {
sb = createLightQuery(src, true);
if (sb != null) {
params = new Parameters();
params.addId(src.getId());
src = iQuery.findByQuery(sb.toString(), params);
if (src instanceof Laser) {
laser = (Laser) src;
pump = laser.getPump();
if (pump != null &&
!(pump instanceof LightEmittingDiode)) {
params = new Parameters();
params.addId(pump.getId());
sb = createLightQuery(pump, true);
if (sb != null)
laser.setPump((LightSource)
iQuery.findByQuery(sb.toString(),
params));
light.setLightSource(laser);
}
} else light.setLightSource(src);
}
}
}
}
return new HashSet<LogicalChannel>(list);
}
@Override
@RolesAllowed("user")
@Transactional(readOnly = true)
public <T extends IObject, A extends Annotation>
Map<Long, Set<A>> loadAnnotations(
Class<T> rootNodeType, Set<Long> rootNodeIds,
Set<String> annotationTypes, Set<Long> annotatorIds,
Parameters options)
{
Map<Long, Set<A>> map = new HashMap<Long, Set<A>>();
if (rootNodeIds.size() == 0) return map;
if (!IAnnotated.class.isAssignableFrom(rootNodeType)) {
throw new ApiUsageException(
"Class parameter for loadAnnotation() "
+ "must be a subclass of ome.model.IAnnotated");
}
Parameters po = new Parameters();
Query<List<IAnnotated>> q = getQueryFactory().lookup(
PojosFindAnnotationsQueryDefinition.class.getName(),
po.addIds(rootNodeIds).addClass(rootNodeType)
.addSet("annotatorIds", annotatorIds));
List<IAnnotated> l = iQuery.execute(q);
iQuery.clear();
// no count collection
// SORT
Iterator<IAnnotated> i = new HashSet<IAnnotated>(l).iterator();
IAnnotated annotated;
Long id;
Set<A> set;
List<A> list;
List<A> supported;
Iterator<A> j;
A object;
Iterator<A> ann;
OriginalFile of;
FileAnnotation fa;
while (i.hasNext()) {
annotated = i.next();
id = annotated.getId();
set = map.get(id);
if (set == null) {
set = new HashSet<A>();
map.put(id, set);
}
list = (List<A>) annotated.linkedAnnotationList();
supported = new ArrayList<A>();
if (list != null) {
if (annotationTypes != null && annotationTypes.size() > 0) {
j = list.iterator();
while (j.hasNext()) {
object = j.next();
if (annotationTypes.contains(
object.getClass().getName())) {
supported.add(object);
}
}
} else {
supported.addAll(list);
}
} else supported.addAll(list);
ann = supported.iterator();
while (ann.hasNext()) {
object = ann.next();
//load original file.
if (object instanceof FileAnnotation) {
fa = (FileAnnotation) object;
if (fa.getFile() != null) {
of = iQuery.findByQuery(LOAD_ORIGINAL_FILE,
new Parameters().addId(fa.getFile().getId()));
fa.setFile(of);
}
}
}
//Archived if no updated script.
set.addAll(supported);
}
return map;
}
@Override
@RolesAllowed("user")
@Transactional(readOnly = true)
public <A extends Annotation> Set<A> loadSpecifiedAnnotations(
@NotNull Class type, Set<String> include, Set<String> exclude,
Parameters options)
{
List<IObject> list = getAnnotation(type, include, exclude, options);
Iterator<IObject> i;
if (FILE_TYPE.equals(type.getName()) && list != null) {
i = list.iterator();
FileAnnotation fa;
OriginalFile of;
List<Annotation> toRemove = new ArrayList<Annotation>();
while (i.hasNext()) {
fa = (FileAnnotation) i.next();
if (fa.getFile() != null) {
of = iQuery.findByQuery(LOAD_ORIGINAL_FILE,
new Parameters().addId(fa.getFile().getId()));
fa.setFile(of);
} else toRemove.add(fa);
}
if (toRemove.size() > 0) list.removeAll(toRemove);
}
if (list == null) return new HashSet<A>();
Set<A> set = new HashSet<A>(list.size());
i = list.iterator();
while (i.hasNext()) {
set.add((A) i.next());
}
return set;
}
@Override
@RolesAllowed("user")
@Transactional(readOnly = true)
public Long countSpecifiedAnnotations(
@NotNull Class type, Set<String> include, Set<String> exclude,
Parameters options)
{
List list = getAnnotation(type, include, exclude, options);
if (list != null) return new Long(list.size());
return -1L;
}
@Override
@RolesAllowed("user")
@Transactional(readOnly = true)
public <A extends Annotation> Set<A> loadAnnotation(
@NotNull @Validate(Long.class) Set<Long> annotationIds)
{
StringBuilder sb = new StringBuilder();
sb.append("select ann from Annotation as ann ");
sb.append("left outer join fetch ann.details.creationEvent ");
sb.append("left outer join fetch ann.details.owner ");
sb.append("where ann.id in (:ids)");
List<A> list = iQuery.findAllByQuery(sb.toString(),
new Parameters().addIds(annotationIds));
if (list == null) return new HashSet<A>();
Iterator<A> i = list.iterator();
A object;
FileAnnotation fa;
Object of;
while (i.hasNext()) {
object = i.next();
if (object instanceof FileAnnotation) {
fa = (FileAnnotation) object;
if (fa.getFile() != null) {
of = iQuery.findByQuery(LOAD_ORIGINAL_FILE,
new Parameters().addId(fa.getFile().getId()));
fa.setFile((OriginalFile) of);
}
}
}
return new HashSet<A>(list);
}
@Override
@RolesAllowed("user")
@Transactional(readOnly = true)
public Map<Long, Set<IObject>>
loadTagContent(@NotNull @Validate(Long.class) Set<Long> tagIds,
Parameters options)
{
Map<Long, Set<IObject>> m = new HashMap<Long, Set<IObject>>();
Iterator<Long> i = tagIds.iterator();
Long id;
while (i.hasNext()) {
id = i.next();
m.put(id, loadObjects(id, options));
}
return m;
}
@Override
@RolesAllowed("user")
@Transactional(readOnly = true)
public Set<IObject> loadTagSets(Parameters options)
{
Set result = new HashSet();
Parameters po = new Parameters(options);
Parameters param = new Parameters();
StringBuilder sb = new StringBuilder();
param.addString("include", NS_INSIGHT_TAG_SET);
sb.append("select tag from TagAnnotation as tag ");
sb.append("left outer join fetch tag.annotationLinks as l ");
sb.append("left outer join fetch l.parent as parent ");
sb.append("left outer join fetch l.child as child ");
sb.append("left outer join fetch child.details.owner as ownerChild ");
sb.append("left outer join fetch parent.details.owner as ownerParent ");
sb.append("left outer join fetch tag.details.owner as tagOwner ");
sb.append("where tag.ns is not null and tag.ns = :include ");
sb.append("and (l is null or child member of "+TAG_TYPE+")");
if (po.isExperimenter()) {
sb.append(" and tagOwner.id = :userID");
param.addLong("userID", po.getExperimenter());
}
//All the tags
List l = iQuery.findAllByQuery(sb.toString(), param);
if (l != null) result.addAll(l);
//retrieve the orphan tags.
if (po.isOrphan()) {
List<Long> children = new ArrayList<Long>();
if (l != null) {
Iterator j = l.iterator();
TagAnnotation tag;
List list;
Iterator k;
Long id;
while (j.hasNext()) {
tag = (TagAnnotation) j.next();
if (tag.sizeOfAnnotationLinks() > 0) {
list = tag.linkedAnnotationList();
k = list.iterator();
while (k.hasNext()) {
id = ((IObject) k.next()).getId();
if (!children.contains(id))
children.add(id);
}
}
}
}
sb = new StringBuilder();
param = new Parameters();
param.addString("include", NS_INSIGHT_TAG_SET);
sb.append("select ann from TagAnnotation as ann");
//sb.append(" where ann.ns is null");
sb.append(" where ((ann.ns is null) or " +
"(ann.ns is not null and ann.ns != :include)) ");
if (children.size() > 0) {
sb.append(" and ann.id not in (:ids)");
param.addList("ids", children);
}
if (po.isExperimenter()) {
sb.append(" and ann.details.owner.id = :userID");
param.addLong("userID", po.getExperimenter());
}
l = iQuery.findAllByQuery(sb.toString(), param);
if (l != null) {
result.addAll(l);
}
}
return result;
}
@Override
@RolesAllowed("user")
@Transactional(readOnly = true)
public Map getTaggedObjectsCount(@NotNull @Validate(Long.class)
Set<Long> tagIds, Parameters options)
{
Map<Long, Long> counts = new HashMap<Long, Long>();
Iterator<Long> i = tagIds.iterator();
Long id;
while (i.hasNext()) {
id = i.next();
counts.put(id, countTaggedObjects(id));
}
return counts;
}
@Override
@RolesAllowed("user")
@Transactional(readOnly = true)
public Set<IObject> loadAnnotationsUsedNotOwned(@NotNull Class annotationType,
long userID)
{
Set result = new HashSet();
String type = annotationType.getName();
List<Long> ids = new ArrayList<Long>();
Iterator i;
IObject o;
Parameters param = new Parameters();
param.addLong("userID", userID);
List<IObject> l;
StringBuffer sb = new StringBuffer();
sb.append("select link from ImageAnnotationLink as link ");
sb.append("left outer join fetch link.child child ");
sb.append("left outer join fetch child.details.owner as co ");
sb.append("left outer join fetch link.details.owner as lo ");
sb.append("where co.id != :userID and lo.id = :userID " +
"and child member of "+type);
l = iQuery.findAllByQuery(sb.toString(), param);
if (l != null && l.size() > 0) {
i = l.iterator();
ImageAnnotationLink link;
while (i.hasNext()) {
link = (ImageAnnotationLink) i.next();
o = link.getChild();
if (!ids.contains(o.getId())) {
result.add(o);
ids.add(o.getId());
}
}
}
sb = new StringBuffer();
sb.append("select link from DatasetAnnotationLink as link ");
sb.append("left outer join fetch link.child child ");
sb.append("left outer join fetch child.details.owner as co ");
sb.append("left outer join fetch link.details.owner as lo ");
sb.append("where co.id != :userID and lo.id = :userID " +
"and child member of "+type);
l = iQuery.findAllByQuery(sb.toString(), param);
if (l != null && l.size() > 0) {
i = l.iterator();
DatasetAnnotationLink link;
while (i.hasNext()) {
link = (DatasetAnnotationLink) i.next();
o = link.getChild();
if (!ids.contains(o.getId())) {
result.add(o);
ids.add(o.getId());
}
}
}
sb = new StringBuffer();
sb.append("select link from ProjectAnnotationLink as link ");
sb.append("left outer join fetch link.child child ");
sb.append("left outer join fetch child.details.owner as co ");
sb.append("left outer join fetch link.details.owner as lo ");
sb.append("where co.id != :userID and lo.id = :userID " +
"and child member of "+type);
l = iQuery.findAllByQuery(sb.toString(), param);
if (l != null && l.size() > 0) {
i = l.iterator();
ProjectAnnotationLink link;
while (i.hasNext()) {
link = (ProjectAnnotationLink) i.next();
o = link.getChild();
if (!ids.contains(o.getId())) {
result.add(o);
ids.add(o.getId());
}
}
}
sb = new StringBuffer();
sb.append("select link from ScreenAnnotationLink as link ");
sb.append("left outer join fetch link.child child ");
sb.append("left outer join fetch child.details.owner as co ");
sb.append("left outer join fetch link.details.owner as lo ");
sb.append("where co.id != :userID and lo.id = :userID " +
"and child member of "+annotationType.getName());
l = iQuery.findAllByQuery(sb.toString(), param);
if (l != null && l.size() > 0) {
i = l.iterator();
ScreenAnnotationLink link;
while (i.hasNext()) {
link = (ScreenAnnotationLink) i.next();
o = link.getChild();
if (!ids.contains(o.getId())) {
result.add(o);
ids.add(o.getId());
}
}
}
sb = new StringBuffer();
sb.append("select link from PlateAnnotationLink as link ");
sb.append("left outer join fetch link.child child ");
sb.append("left outer join fetch child.details.owner as co ");
sb.append("left outer join fetch link.details.owner as lo ");
sb.append("where co.id != :userID and lo.id = :userID " +
"and child member of "+annotationType.getName());
l = iQuery.findAllByQuery(sb.toString(), param);
if (l != null && l.size() > 0) {
i = l.iterator();
PlateAnnotationLink link;
while (i.hasNext()) {
link = (PlateAnnotationLink) i.next();
o = link.getChild();
if (!ids.contains(o.getId())) {
result.add(o);
ids.add(o.getId());
}
}
}
return result;
}
@Override
@RolesAllowed("user")
@Transactional(readOnly = true)
public Long countAnnotationsUsedNotOwned(@NotNull Class annotationType,
long userID)
{
Set s = loadAnnotationsUsedNotOwned(annotationType, userID);
if (s != null) return new Long(s.size());
return -1L;
}
@Override
@RolesAllowed("user")
@Transactional(readOnly = true)
public <A extends Annotation> Map<Long, Set<A>> loadSpecifiedAnnotationsLinkedTo(
@NotNull Class type, Set<String> include, Set<String> exclude,
@NotNull Class rootNodeType,
@NotNull @Validate(Long.class) Set<Long> rootNodeIds,
Parameters options)
{
//First depending on the class
List<IObject> list = getAnnotation(type, include, exclude, rootNodeType,
rootNodeIds, options);
Map<Long, Set<A>> map = new HashMap<Long, Set<A>>(rootNodeIds.size());
if (list == null) return map;
Iterator<IObject> i = list.iterator();
ILink object;
Set<A> set;
Long parentID;
A ann;
FileAnnotation fa;
OriginalFile of;
while (i.hasNext()) {
object = (ILink) i.next();
parentID = object.getParent().getId();
set = map.get(parentID);
if (set == null) {
set = new HashSet<A>();
map.put(parentID, set);
}
ann = (A) object.getChild();
if (FILE_TYPE.equals(type.getName())) {
fa = (FileAnnotation) ann;
if (fa.getFile() != null) {
of = iQuery.findByQuery(LOAD_ORIGINAL_FILE,
new Parameters().addId(fa.getFile().getId()));
fa.setFile(of);
}
}
set.add(ann);
}
return map;
}
@Override
@RolesAllowed("user")
@Transactional(readOnly = true)
public Map<Long, Set<IObject>> loadLogFiles(
@NotNull Class<? extends IObject> rootNodeType,
@Validate(Long.class) Set<Long> ids) {
final SetMultimap<Long, Long> rootIdByFileset;
if (Image.class.isAssignableFrom(rootNodeType)) {
rootIdByFileset = HashMultimap.create();
if (CollectionUtils.isNotEmpty(ids)) {
for (final Object[] result : iQuery.projection(LOAD_FILESET_OF_IMAGE,
new Parameters().addIds(ids))) {
final Long imageId = (Long) result[0];
final Long filesetId = (Long) result[1];
rootIdByFileset.put(filesetId, imageId);
}
}
} else if (!Fileset.class.isAssignableFrom(rootNodeType)) {
throw new ApiUsageException("can load log files only by Fileset or Image");
} else {
rootIdByFileset = null;
}
final SetMultimap<Long, IObject> map = HashMultimap.create();
final Set<Long> filesetIds = rootIdByFileset == null ? ids : rootIdByFileset.keySet();
if (CollectionUtils.isNotEmpty(filesetIds)) {
for (final Object[] result : iQuery.projection(LOAD_IMPORT_LOGS,
new Parameters().addIds(filesetIds))) {
final Long filesetId = (Long) result[0];
final OriginalFile logFile = (OriginalFile) result[1];
final Set<Long> mapKeys;
if (rootIdByFileset == null) {
mapKeys = Collections.singleton(filesetId);
} else {
mapKeys = rootIdByFileset.get(filesetId);
}
for (final Long mapKey : mapKeys) {
map.put(mapKey, logFile);
}
}
}
/* wrap in a hash map so that ModelMapper may create a new instance */
return new HashMap<Long, Set<IObject>>(Multimaps.asMap(map));
}
}