/** * SampleSearch Domain Class * * This class provides querying capabilities for searching for samples * * @author Robert Horlings (robert@isdat.nl) * @since 20110118 * @package dbnp.query * * Revision information: * $Rev: 1436 $ * $Author: robert@isdat.nl $ * $Date: 2011-01-24 14:48:46 +0000 (ma, 24 jan 2011) $ */ package dbnp.query import java.util.List import dbnp.studycapturing.* import nl.grails.plugins.gdt.* class SampleSearch extends Search { public SampleSearch() { this.entity = "Sample"; } /** * Searches for samples based on the given criteria. All criteria have to be satisfied and * criteria for the different entities are satisfied as follows: * * Sample.title = 'abc' * Only samples are returned from studies with title 'abc' * * Subject.species = 'human' * Only samples are returned from subjects with species = 'human' * * Sample.name = 'sample 1' * Only samples are returned with name = 'sample 1' * * Event.startTime = '0s' * Only samples are returned from subjects that have had an event with start time = '0s' * * SamplingEvent.startTime = '0s' * Only samples are returned that have originated from a sampling event with start time = '0s' * * Assay.module = 'metagenomics' * Only samples are returned that have been processed in an assay with module = metagenomics * * When searching for more than one criterion per entity, these are taken combined. Searching for * * Subject.species = 'human' * Subject.name = 'Jan' * * will result in all samples from a human subject named 'Jan'. Samples from a mouse subject * named 'Jan' or a human subject named 'Kees' won't satisfy the criteria. * */ @Override void execute() { // TODO: check for authorization for these studies? // If no criteria are found, return all samples if( !criteria || criteria.size() == 0 ) { results = Sample.list(); return; } // We expect the sample criteria to be the most discriminative, and discard // the most samples. (e.g. by searching on sample title of sample type). For // that reason we first look through the list of studies. However, when the // user didn't enter any sample criteria, this will be an extra step, but doesn't // cost much time to process. def samples = [] if( getEntityCriteria( 'Study' ).size() > 0 ) { def studies = Study.findAll(); studies = filterOnStudyCriteria( studies ); if( studies.size() == 0 ) { results = []; return; } def c = Sample.createCriteria() samples = c.list { 'in'( 'parent', studies ) } } else { samples = Sample.findAll() } samples = filterOnSubjectCriteria( samples ); samples = filterOnSampleCriteria( samples ); samples = filterOnEventCriteria( samples ); samples = filterOnSamplingEventCriteria( samples ); samples = filterOnAssayCriteria( samples ); // Save matches results = samples; } /** * Filters the given list of samples on the sample criteria * @param samples Original list of samples * @return List with all samples that match the Sample-criteria */ protected List filterOnStudyCriteria( List studies ) { return filterEntityList( studies, getEntityCriteria( 'Study' ), { study, criterion -> return criterion.matchOne( study ); }); } /** * Filters the given list of samples on the subject criteria * @param samples Original list of samples * @return List with all samples that match the Subject-criteria */ protected List filterOnSubjectCriteria( List samples ) { return filterEntityList( samples, getEntityCriteria( 'Subject' ), { sample, criterion -> if( !sample.parentSubject ) return false return criterion.matchOne( sample.parentSubject ); }); } /** * Filters the given list of samples on the sample criteria * @param samples Original list of samples * @return List with all samples that match the sample-criteria */ protected List filterOnSampleCriteria( List samples ) { return filterEntityList( samples, getEntit