source: trunk/grails-app/controllers/dbnp/studycapturing/StudyController.groovy @ 1752

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

Updated assay export to be able to export multiple assays or studies (in the search results page).
Also changed the assay export such that the assay can still be exported if the module is not reachable (without module measurements but with a message in the excel sheet)

  • Property svn:keywords set to Rev Author Date
File size: 13.5 KB
Line 
1package dbnp.studycapturing
2
3import grails.converters.*
4import grails.plugins.springsecurity.Secured
5import org.dbnp.gdt.TemplateFieldType
6import org.dbnp.gdt.RelTime
7
8
9/**
10 * Controller class for studies
11 */
12class StudyController {
13    def authenticationService
14   
15    //static allowedMethods = [save: "POST", update: "POST", delete: "POST"]
16
17    def index = {
18        redirect(action: "list", params: params)
19    }
20
21    /**
22     * Shows all studies where the user has access to
23     */
24    def list = {
25
26        def user = authenticationService.getLoggedInUser()
27        def max = Math.min(params.max ? params.int('max') : 10, 100)
28                def offset = params.offset ? params.int( 'offset' ) : 0
29        def studies = Study.giveReadableStudies( user, max, offset );
30        [studyInstanceList: studies, studyInstanceTotal: Study.countReadableStudies( user ), loggedInUser: user]
31    }
32
33    /**
34     * Shows studies for which the logged in user is the owner
35     */
36    @Secured(['IS_AUTHENTICATED_REMEMBERED'])
37    def myStudies = {
38        def user = authenticationService.getLoggedInUser()
39        def max = Math.min(params.max ? params.int('max') : 10, 100)
40                def offset = params.offset ? params.int( 'offset' ) : 0
41               
42        def studies = Study.findAllByOwner(user, [max:max,offset: offset]);
43        render( view: "list", model: [studyInstanceList: studies, studyInstanceTotal: Study.countByOwner(user), loggedInUser: user] )
44    }
45
46    /**
47     * Shows a comparison of multiple studies using the show view
48     *
49     */
50    def list_extended = {
51                // If nothing has been selected, redirect the user
52                if( !params.id ) 
53                        redirect( action: 'list' )
54
55                // Check whether one id has been selected or multiple.
56                def ids = params.id
57                if( ids instanceof String )
58                        redirect( action: 'show', id: ids )
59
60                // Parse strings to a long
61                def long_ids = []
62                ids.each { long_ids.add( Long.parseLong( it ) ) }
63
64                println( long_ids )
65
66        def startTime = System.currentTimeMillis()
67                def c = Study.createCriteria()
68
69        def studyList = c {
70                        maxResults( Math.min(params.max ? params.int('max') : 10, 100) )
71                        'in'( "id", long_ids )
72                }
73        render(view:'show',model:[studyList: studyList, studyInstanceTotal: Study.count(), multipleStudies: ( studyList.size() > 1 ) ] )
74    }
75
76    /**
77     * Shows one or more studies
78     */
79    def show = {
80        def startTime = System.currentTimeMillis()
81
82        def studyInstance = Study.get( params.long( "id" ) )
83        if (!studyInstance) {
84            flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'study.label', default: 'Study'), params.id])}"
85            redirect(action: "list")
86        }
87        else {
88            // Check whether the user may see this study
89            def loggedInUser = authenticationService.getLoggedInUser()
90            if( !studyInstance.canRead(loggedInUser) ) {
91                flash.message = "You have no access to this study"
92                redirect(action: "list")
93            }
94
95            // The study instance is packed into an array, to be able to
96            // use the same view for showing the study and comparing multiple
97            // studies
98            [studyList: [ studyInstance ], multipleStudies: false, loggedInUser: loggedInUser, facebookLikeUrl: studyInstance.getFieldValue('published') ? "/study/show/${studyInstance?.id}" : '' ]
99        }
100    }
101
102        /**
103     * Shows the subjects tab of one or more studies. Is called when opening the subjects-tab
104         * on the study overview screen.
105     */
106    def show_subjects = {
107                def studyList = readStudies( params.id );
108
109                if( !studyList )
110                        return
111
112                [studyList: studyList, studyInstanceTotal: Study.count(), multipleStudies: ( studyList.size() > 1 ), loggedInUser: authenticationService.getLoggedInUser() ]
113    }
114
115        /**
116     * Shows the events timeline tab of one or more studies. Is called when opening the events timeline-tab
117         * on the study overview screen.
118     */
119    def show_events_timeline = {
120                def studyList = readStudies( params.id );
121
122                if( !studyList )
123                        return
124
125                [studyList: studyList, studyInstanceTotal: Study.count(), multipleStudies: ( studyList.size() > 1 ), loggedInUser: authenticationService.getLoggedInUser() ]
126    }
127
128        /**
129     * Shows the events table tab of one or more studies. Is called when opening the events table-tab
130         * on the study overview screen.
131     */
132    def show_events_table = {
133                def studyList = readStudies( params.id );
134
135                if( !studyList )
136                        return
137
138                [studyList: studyList, studyInstanceTotal: Study.count(), multipleStudies: ( studyList.size() > 1 ), loggedInUser: authenticationService.getLoggedInUser() ]
139    }
140
141        /**
142     * Shows the assays tab of one or more studies. Is called when opening the assays tab
143         * on the study overview screen.
144     */
145    def show_assays = {
146                def studyList = readStudies( params.id );
147
148                if( !studyList )
149                        return
150
151                [studyList: studyList, studyInstanceTotal: Study.count(), multipleStudies: ( studyList.size() > 1 ), loggedInUser: authenticationService.getLoggedInUser() ]
152    }
153
154        /**
155     * Shows the samples tab of one or more studies. Is called when opening the samples-tab
156         * on the study overview screen.
157     */
158    def show_samples = {
159                def studyList = readStudies( params.id );
160
161                if( !studyList )
162                        return
163
164                [studyList: studyList, studyInstanceTotal: Study.count(), multipleStudies: ( studyList.size() > 1 ), loggedInUser: authenticationService.getLoggedInUser() ]
165    }
166
167        /**
168     * Shows the persons tab of one or more studies. Is called when opening the persons tab
169         * on the study overview screen.
170     */
171    def show_persons = {
172                def studyList = readStudies( params.id );
173
174                if( !studyList )
175                        return
176
177                [studyList: studyList, studyInstanceTotal: Study.count(), multipleStudies: ( studyList.size() > 1 ), loggedInUser: authenticationService.getLoggedInUser() ]
178    }
179
180        /**
181     * Shows the publications tab of one or more studies. Is called when opening the publications tab
182         * on the study overview screen.
183     */
184    def show_publications = {
185                def studyList = readStudies( params.id );
186
187                if( !studyList )
188                        return
189
190                [studyList: studyList, studyInstanceTotal: Study.count(), multipleStudies: ( studyList.size() > 1 ), loggedInUser: authenticationService.getLoggedInUser() ]
191    }
192
193        /**
194         * Creates the javascript for showing the timeline of one or more studies
195         */
196        def createTimelineBandsJs = {
197                def studyList = readStudies( params.id );
198
199                if( !studyList )
200                        return
201
202                [studyList: studyList, studyInstanceTotal: Study.count(), multipleStudies: ( studyList.size() > 1 ) ]
203        }
204
205    /**
206         * Reads one or more studies from the database and checks whether the logged
207         * in user is allowed to access them.
208         *
209         * Is used by several show_-methods
210         *
211         * @return List with Study objects or false if an error occurred.
212         */
213        private def readStudies( id ) {
214                // If nothing has been selected, redirect the user
215                if( !id || !( id instanceof String)) {
216            response.status = 500;
217            render 'No study selected';
218            return false
219                }
220
221                // Check whether one id has been selected or multiple.
222                def ids = URLDecoder.decode( id ).split( "," );
223
224                // Parse strings to a long
225                def long_ids = []
226                ids.each { long_ids.add( Long.parseLong( it ) ) }
227
228                def c = Study.createCriteria()
229
230        def studyList = c {
231                        maxResults( Math.min(params.max ? params.int('max') : 10, 100) )
232                        'in'( "id", long_ids )
233                }
234
235                // Check whether the user may see these studies
236                def studiesAllowed = []
237        def loggedInUser = authenticationService.getLoggedInUser()
238
239                studyList.each { studyInstance ->
240            if( studyInstance.canRead(loggedInUser) ) {
241                                studiesAllowed << studyInstance
242            }
243                }
244
245                // If the user is not allowed to see any of the studies, return 404
246                if( studiesAllowed.size() == 0 ) {
247            response.status = 404;
248            render 'Selected studies not found';
249            return false
250                }
251               
252                return studyList
253        }
254
255    def showByToken = {
256        def studyInstance = Study.findByStudyUUID(params.id)
257        if (!studyInstance) {
258            flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'study.label', default: 'Study'), params.id])}"
259            redirect(action: "list")
260        }
261        else {
262            // Check whether the user may see this study
263            def loggedInUser = authenticationService.getLoggedInUser()
264            if( !studyInstance.canRead(loggedInUser) ) {
265                flash.message = "You have no access to this study"
266                redirect(action: "list")
267            }
268
269            redirect(action: "show", id: studyInstance.id)
270        }
271    }
272
273    /**
274     * Gives the events for one eventgroup in JSON format
275     *
276     */
277    def events = {
278        def eventGroupId = Integer.parseInt( params.id );
279        def studyId      = Integer.parseInt( params.study );
280        def eventGroup;
281
282        // eventGroupId == -1 means that the orphaned events should be given
283        if( eventGroupId == -1 ) {
284            def studyInstance = Study.get( studyId )
285           
286            if (studyInstance == null) {
287                flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'study.label', default: 'Study'), studyId])}"
288                redirect(action: "list");
289                return;
290            }
291
292            events = studyInstance.getOrphanEvents();
293        } else {
294            eventGroup = EventGroup.get(params.id)
295
296            if (eventGroup == null) {
297                flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'eventgroup.label', default: 'Eventgroup'), params.id])}"
298                redirect(action: "list");
299                return;
300            }
301            events = eventGroup?.events + eventGroup?.samplingEvents;
302        }
303
304        // This parameter should give the startdate of the study in milliseconds
305        // since 1-1-1970
306        long startDate  = Long.parseLong( params.startDate )
307
308        // Create JSON object
309        def json = [ 'dateTimeFormat': 'iso8601', events: [] ];
310
311        // Add all other events
312        for( event in events ) {
313            def parameters = []
314            for( templateField in event.giveTemplateFields() ) {
315                def value = event.getFieldValue( templateField.name );
316                                if( value ) {
317                                        if( templateField.type == TemplateFieldType.RELTIME )
318                                                value = new RelTime( value ).toString();
319
320                        def param = templateField.name + " = " + value;
321
322                                        if( templateField.unit )
323                                                param += templateField.unit;
324
325                    parameters << param ;
326                }
327            }
328
329                        def description = parameters.join( '<br />\n' );
330
331                        if( event instanceof SamplingEvent ) {
332                                 json.events << [
333                                        'start':    new Date( startDate + event.startTime * 1000 ),
334                                        'end':      new Date( startDate + event.startTime * 1000 ),
335                                        'durationEvent': false,
336                                        'title': event.template.name,
337                                        'description': description
338                                ]
339                        } else {
340                                 json.events << [
341                                        'start':    new Date( startDate + event.startTime * 1000 ),
342                                        'end':      new Date( startDate + event.endTime * 1000 ),
343                                        'durationEvent': true,
344                                        'title': event.template.name,
345                                        'description': description
346                                ]
347                               
348                        }
349        }
350
351                // set output header to json
352                response.contentType = 'application/json'
353
354        render json as JSON
355    }
356
357    def delete = {
358        def studyInstance = Study.get(params.id)
359        if (studyInstance) {
360            try {
361                studyInstance.delete(flush: true)
362                flash.message = "${message(code: 'default.deleted.message', args: [message(code: 'study.label', default: 'Study'), params.id])}"
363                redirect(action: "list")
364            }
365            catch (org.springframework.dao.DataIntegrityViolationException e) {
366                flash.message = "${message(code: 'default.not.deleted.message', args: [message(code: 'study.label', default: 'Study'), params.id])}"
367                redirect(action: "show", id: params.id)
368            }
369        }
370        else {
371            flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'study.label', default: 'Study'), params.id])}"
372            redirect(action: "list")
373        }
374    }
375
376    /**
377     * Renders assay names and id's as JSON
378     */
379    def ajaxGetAssays = {
380        def study = Study.read(params.id)
381
382                // set output header to json
383                response.contentType = 'application/json'
384
385        render study?.assays?.collect{[name: it.name, id: it.id]} as JSON
386    }
387       
388        /**
389         * Exports all data from the given studies to excel. This is done using a redirect to the
390         * assay controller
391         *
392         * @param       ids                             ids of the studies to export
393         * @param       params.format   "list" in order to export all assays in one big excel sheet
394         *                                                      "sheets" in order to export every assay on its own sheet (default)
395         * @see         AssayController.exportToExcel
396         */
397        def exportToExcel = {
398                def ids = params.list( 'ids' ).findAll { it.isLong() }.collect { Long.valueOf( it ) };
399
400                if( !ids ) {
401                        flash.errorMessage = "No study ids given";
402                        redirect( controller: "assay", action: "errorPage" );
403                        return;
404                }
405               
406                // Find all assay ids for these studies
407                def assayIds = ids.collect { id ->
408                        def study = Study.get( id );
409                        if( study ) {
410                                return study.assays.collect { assay -> assay.id }
411                        } else {
412                                return []
413                        }
414                }.flatten()
415               
416                if( !assayIds ) {
417                        flash.errorMessage = "No assays found for the given studies";
418                        redirect( controller: "assay", action: "errorPage" );
419                        return;
420                }
421               
422                // Create url to redirect to
423                def format = params.get( "format", "sheets" )
424                redirect( controller: "assay", action: "exportToExcel", params: [ "format": format, "ids": assayIds ] );
425        }
426}
Note: See TracBrowser for help on using the repository browser.