source: trunk/src/groovy/dbnp/query/StudySearch.groovy @ 1524

Last change on this file since 1524 was 1524, checked in by robert@…, 9 years ago

Refactored some of the querying stuff and built in 'check all' checkboxes

  • Property svn:keywords set to Rev Author Date
File size: 6.9 KB
Line 
1/**
2 * StudySearch Domain Class
3 *
4 * This class provides querying capabilities for searching for studies
5 *
6 * @author  Robert Horlings (robert@isdat.nl)
7 * @since       20110118
8 * @package     dbnp.query
9 *
10 * Revision information:
11 * $Rev: 1524 $
12 * $Author: robert@isdat.nl $
13 * $Date: 2011-02-15 14:05:23 +0000 (di, 15 feb 2011) $
14 */
15package dbnp.query
16
17import groovy.lang.Closure;
18
19import java.util.List;
20import java.util.Map;
21
22import dbnp.studycapturing.*
23import org.dbnp.gdt.*
24import org.apache.commons.logging.LogFactory;
25
26class StudySearch extends Search {
27        private static final log = LogFactory.getLog(this);
28
29        public StudySearch() {
30                super();
31                this.entity = "Study";
32        }
33
34        /**
35         * Searches for studies based on the given criteria. All criteria have to be satisfied and
36         * criteria for the different entities are satisfied as follows:
37         *
38         *              Study.title = 'abc'             
39         *                              All returned studies will have title 'abc'
40         *             
41         *              Subject.species = 'human'
42         *                              All returned studies will have one or more subjects with species = 'human' 
43         *
44         *              Sample.name = 'sample 1'
45         *                              All returned studies will have one or more samples with name = 'sample 1'
46         *
47         *              Event.startTime = '0s'
48         *                              All returned studies will have one or more events with start time = '0s' 
49         *
50         *              Assay.module = 'metagenomics'
51         *                              All returned studies will have one or more assays with module = 'metagenomics' 
52         *
53         * When searching the system doesn't look at the connections between different entities. This means,
54         * the system doesn't look for human subjects having a sample with name 'sample 1'. The sample 1 might
55         * as well belong to a mouse subject and still the study satisfies the criteria.
56         *
57         * When searching for more than one criterion per entity, these are taken combined. Searching for
58         *
59         *              Subject.species = 'human'
60         *              Subject.name = 'Jan'
61         *
62         *  will result in all studies having a human subject named 'Jan'. Studies with only a mouse subject
63         *  named 'Jan' or a human subject named 'Kees' won't satisfy the criteria.
64         *     
65         */
66        @Override
67        void executeAnd() {
68                def studies = Study.list().findAll { it.canRead( this.user ) };
69
70                // If no criteria are found, return all studies
71                if( !criteria || criteria.size() == 0 ) {
72                        results = studies;
73                        return;
74                }
75
76                // Perform filters
77                studies = filterOnStudyCriteria( studies );
78                studies = filterOnSubjectCriteria( studies );
79                studies = filterOnSampleCriteria( studies );
80                studies = filterOnEventCriteria( studies );
81                studies = filterOnSamplingEventCriteria( studies );
82                studies = filterOnAssayCriteria( studies );
83
84                studies = filterOnModuleCriteria( studies );
85
86                // Save matches
87                results = studies;
88        }
89
90        /**
91         * Searches for studies based on the given criteria. Only one criteria have to be satisfied and
92         * criteria for the different entities are satisfied as follows:
93         *
94         *              Study.title = 'abc'
95         *                              The returned study will have title 'abc'
96         *
97         *              Subject.species = 'human'
98         *                              The returned study will have one or more subjects with species = 'human'
99         *
100         *              Sample.name = 'sample 1'
101         *                              The returned study will have one or more samples with name = 'sample 1'
102         *
103         *              Event.startTime = '0s'
104         *                              The returned study will have one or more events with start time = '0s'
105         *
106         *              Assay.module = 'metagenomics'
107         *                              The returned study will have one or more assays with module = 'metagenomics'
108         *
109         * When searching the system doesn't look at the connections between different entities. This means,
110         * the system doesn't look for human subjects having a sample with name 'sample 1'. The sample 1 might
111         * as well belong to a mouse subject and still the study satisfies the criteria.
112         *
113         * When searching for more than one criterion per entity, these are taken separately. Searching for
114         *
115         *              Subject.species = 'human'
116         *              Subject.name = 'Jan'
117         *
118         *  will result in all studies having a human subject or a subject named 'Jan'. Studies with only a
119         *  mouse subject named 'Jan' or a human subject named 'Kees' will satisfy the criteria.
120         *
121         */
122        @Override
123        void executeOr() {
124                def allStudies = Study.list().findAll { it.canRead( this.user ) };
125
126                // If no criteria are found, return all studies
127                if( !criteria || criteria.size() == 0 ) {
128                        results = allStudies;
129                        return;
130                }
131
132                // Perform filters
133                def studies = []
134                studies = ( studies + filterOnStudyCriteria( allStudies - studies ) ).unique();
135                studies = ( studies + filterOnSubjectCriteria( allStudies - studies ) ).unique();
136                studies = ( studies + filterOnSampleCriteria( allStudies - studies ) ).unique();
137                studies = ( studies + filterOnEventCriteria( allStudies - studies ) ).unique();
138                studies = ( studies + filterOnSamplingEventCriteria( allStudies - studies ) ).unique();
139                studies = ( studies + filterOnAssayCriteria( allStudies - studies ) ).unique();
140               
141                studies = ( studies + filterOnModuleCriteria( allStudies - studies ) ).unique();
142               
143                // Save matches
144                results = studies;
145        }
146
147        /**
148        * Returns a closure for the given entitytype that determines the value for a criterion
149        * on the given object. The closure receives two parameters: the object and a criterion.
150        *
151        * This method should be implemented by all searches
152        *
153        * For example:
154        *               For a study search, the object given is a study. How to determine the value for that study of
155        *               the criterion field of type sample? This is done by returning the field values for all
156        *               samples in the study
157        *                       { study, criterion -> return study.samples?.collect { criterion.getFieldValue( it ); } }
158        * @return
159        */
160   protected Closure valueCallback( String entity ) {
161           switch( entity ) {
162                   case "Study":
163                           return { study, criterion -> return criterion.getFieldValue( study ) }
164                   case "Subject":
165                           return { study, criterion -> return study.subjects?.collect { criterion.getFieldValue( it ); } }
166                   case "Sample":
167                           return { study, criterion -> return study.samples?.collect { criterion.getFieldValue( it ); } }
168                   case "Event":
169                           return { study, criterion -> return study.events?.collect { criterion.getFieldValue( it ); } }
170                   case "SamplingEvent":
171                           return { study, criterion -> return study.samplingEvents?.collect { criterion.getFieldValue( it ); } }
172                   case "Assay":
173                           return { study, criterion -> return study.assays?.collect { criterion.getFieldValue( it ); } }
174                   default:
175                           return super.valueCallback( entity );
176           }
177   }
178
179        /**
180         * Returns the saved field data that could be shown on screen. This means, the data
181         * is filtered to show only data of the query results. Also, the study title and sample
182         * name are filtered out, in order to be able to show all data on the screen without
183         * checking further
184         *
185         * @return      Map with the entity id as a key, and a field-value map as value
186         */
187        public Map getShowableResultFields() {
188                Map showableFields = super.getShowableResultFields()
189                showableFields.each { sampleElement ->
190                        sampleElement.value = sampleElement.value.findAll { fieldElement ->
191                                fieldElement.key != "Study title" && fieldElement.key != "Subject species"
192                        }
193                }
194                return showableFields
195        }
196}
Note: See TracBrowser for help on using the repository browser.