source: trunk/grails-app/controllers/dbnp/studycapturing/AssayController.groovy @ 1761

Last change on this file since 1761 was 1761, checked in by s.h.sikkema@…, 11 years ago

assay excel export now writes to a temporary file first to prevent memory issues

  • Property svn:keywords set to Rev Author Date
File size: 10.2 KB
Line 
1package dbnp.studycapturing
2
3class AssayController {
4
5        def assayService
6        def authenticationService
7    def fileService
8
9        static allowedMethods = [save: "POST", update: "POST", delete: "POST"]
10
11        def index = {
12                redirect(action: "list", params: params)
13        }
14
15        def list = {
16                params.max = Math.min(params.max ? params.int('max') : 10, 100)
17                [assayInstanceList: Assay.list(params), assayInstanceTotal: Assay.count()]
18        }
19
20        def create = {
21                def assayInstance = new Assay()
22                assayInstance.properties = params
23                return [assayInstance: assayInstance]
24        }
25
26        def save = {
27                def assayInstance = new Assay(params)
28
29                // The following lines deviate from the generate-all generated code.
30                // See http://jira.codehaus.org/browse/GRAILS-3783 for why we have this shameful workaround...
31                def study = assayInstance.parent
32                study.addToAssays(assayInstance)
33
34                if (assayInstance.save(flush: true)) {
35                        flash.message = "${message(code: 'default.created.message', args: [message(code: 'assay.label', default: 'Assay'), assayInstance.id])}"
36                        redirect(action: "show", id: assayInstance.id)
37                }
38                else {
39                        render(view: "create", model: [assayInstance: assayInstance])
40                }
41        }
42
43        def show = {
44                def assayInstance = Assay.get(params.id)
45                if (!assayInstance) {
46                        flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'assay.label', default: 'Assay'), params.id])}"
47                        redirect(action: "list")
48                }
49                else {
50                        [assayInstance: assayInstance]
51                }
52        }
53
54        def showByToken = {
55                def assayInstance = Assay.findByAssayUUID(params.id)
56                if (!assayInstance) {
57                        flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'assay.label', default: 'Assay'), params.id])}"
58                        redirect(action: "list")
59                }
60                else {
61                        redirect(action: "show", id: assayInstance.id)
62                }
63        }
64
65        def edit = {
66                def assayInstance = Assay.get(params.id)
67                if (!assayInstance) {
68                        flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'assay.label', default: 'Assay'), params.id])}"
69                        redirect(action: "list")
70                }
71                else {
72                        return [assayInstance: assayInstance]
73                }
74        }
75
76        def update = {
77                def assayInstance = Assay.get(params.id)
78                if (assayInstance) {
79                        if (params.version) {
80                                def version = params.version.toLong()
81                                if (assayInstance.version > version) {
82
83                                        assayInstance.errors.rejectValue("version", "default.optimistic.locking.failure", [message(code: 'assay.label', default: 'Assay')] as Object[], "Another user has updated this Assay while you were editing")
84                                        render(view: "edit", model: [assayInstance: assayInstance])
85                                        return
86                                }
87                        }
88                        assayInstance.properties = params
89                        if (!assayInstance.hasErrors() && assayInstance.save(flush: true)) {
90                                flash.message = "${message(code: 'default.updated.message', args: [message(code: 'assay.label', default: 'Assay'), assayInstance.id])}"
91                                redirect(action: "show", id: assayInstance.id)
92                        }
93                        else {
94                                render(view: "edit", model: [assayInstance: assayInstance])
95                        }
96                }
97                else {
98                        flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'assay.label', default: 'Assay'), params.id])}"
99                        redirect(action: "list")
100                }
101        }
102
103        def delete = {
104                def assayInstance = Assay.get(params.id)
105                if (assayInstance) {
106                        try {
107                                assayInstance.delete(flush: true)
108                                flash.message = "${message(code: 'default.deleted.message', args: [message(code: 'assay.label', default: 'Assay'), params.id])}"
109                                redirect(action: "list")
110                        }
111                        catch (org.springframework.dao.DataIntegrityViolationException e) {
112                                flash.message = "${message(code: 'default.not.deleted.message', args: [message(code: 'assay.label', default: 'Assay'), params.id])}"
113                                redirect(action: "show", id: params.id)
114                        }
115                }
116                else {
117                        flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'assay.label', default: 'Assay'), params.id])}"
118                        redirect(action: "list")
119                }
120        }
121
122        def excelExportFlow = {
123                entry {
124                        action{
125                                def user            = authenticationService.getLoggedInUser()
126                                flow.userStudies    = Study.giveReadableStudies(user)
127                        }
128                        on("success").to "selectAssay"
129                }
130
131                selectAssay {
132                        on ("submit"){
133                                flow.assay = Assay.get(params.assayId)
134
135                                // check if assay exists
136                                if (!flow.assay) throw new Exception("No assay found with id: ${flow.assay.id}")
137
138                                // obtain fields for each category
139                                flow.fieldMap = assayService.collectAssayTemplateFields(flow.assay)
140
141                                flow.measurementTokens = flow.fieldMap.remove('Module Measurement Data')
142                        }.to "selectFields"
143
144                        on(Exception).to "handleError"
145                }
146
147                selectFields {
148                        on ("submit"){
149                                def fieldMapSelection = [:]
150
151                                flow.fieldMap.eachWithIndex { cat, cat_i ->
152
153                                        if (params."cat_$cat_i" == 'on') {
154                                                fieldMapSelection[cat.key] = []
155
156                                                cat.value.eachWithIndex { field, field_i ->
157
158                                                        if (params."cat_${cat_i}_${field_i}" == 'on')
159                                                                fieldMapSelection[cat.key] += field
160                                                }
161
162                                                if (fieldMapSelection[cat.key] == [])
163                                                        fieldMapSelection.remove(cat.key)
164                                        }
165                                }
166
167                                def measurementTokens = []
168
169                                if (params."cat_4" == 'on') {
170                                        measurementTokens = params.list( "measurementToken" )
171                                }
172
173                                def assayData           = assayService.collectAssayData(flow.assay, fieldMapSelection, measurementTokens)
174                                flow.rowData            = assayService.convertColumnToRowStructure(assayData)
175                                flow.assayDataPreview   = flow.rowData[0..4].collect{ it[0..4] as ArrayList }
176
177                        }.to "compileExportData"
178
179                        on(Exception).to "handleError"
180                }
181
182                compileExportData {
183                        on ("ok"){session.rowData = flow.rowData}.to "export"
184                        on ("cancel").to "selectAssay"
185                }
186
187                export {
188                        redirect(action: 'doExport')
189                }
190
191                handleError() {
192                        render(view: 'errorPage')
193                }
194        }
195
196        def doExport = {
197
198                def filename = 'export.xlsx'
199                response.setHeader("Content-disposition", "attachment;filename=\"${filename}\"")
200                response.setContentType("application/octet-stream")
201                try {
202
203            def file = fileService.get('tempAssayExportFile')
204            def os = file.newOutputStream()
205
206                        assayService.exportRowWiseDataToExcelFile(session.rowData, os)
207                        os.flush()
208
209            response.outputStream << file.newInputStream()
210
211            file.delete()
212
213                } catch (Exception e) {
214
215                        flash.errorMessage = e.message
216                        redirect action: 'errorPage'
217
218                }
219        }
220
221        /**
222         * Method to export one or more assays to excel in separate sheets.
223         *
224         * @param       params.ids              One or more assay IDs to export
225         * @param       params.format   "list" in order to export all assays in one big excel sheet
226         *                                                      "sheets" in order to export every assay on its own sheet (default)
227         */
228        def exportToExcel = {
229                def format = params.get( 'format', 'sheets' );
230                if( format == 'list' ) {
231                        exportToExcelAsList( params );
232                } else {
233                        exportToExcelAsSheets( params );
234                }
235        }
236
237        /**
238         * Method to export one or more assays to excel in separate sheets.
239         *
240         * @param       params.ids              One or more assay IDs to export
241         */
242        def exportToExcelAsSheets = {
243                def ids = params.list( 'ids' ).findAll { it.isLong() }.collect { Long.valueOf( it ) };
244
245                if( !ids ) {
246                        flash.errorMessage = "No assay ids given";
247                        redirect( action: "errorPage" );
248                        return;
249                }
250
251                // Find all assays for the given ids
252                def assays = ids.unique().collect { id -> Assay.get( id ) }.findAll { it }
253
254                // Send headers to the browser so the user can download the file
255                def filename = 'export.xlsx'
256                response.setHeader("Content-disposition", "attachment;filename=\"${filename}\"")
257                response.setContentType("application/octet-stream")
258
259                try {
260                        // Loop through all assays to collect the data
261                        def rowWiseAssayData = [];
262
263                        assays.each { assay ->
264                                // Determine which fields should be exported for this assay
265                                def fieldMap = assayService.collectAssayTemplateFields(assay)
266                                def measurementTokens = fieldMap.remove('Module Measurement Data')
267
268                                // Retrieve row based data for this assay
269                                def assayData = assayService.collectAssayData( assay, fieldMap, measurementTokens );
270                                def rowData   = assayService.convertColumnToRowStructure(assayData)
271
272                                // Put each assay on another sheet
273                                rowWiseAssayData << rowData;
274                        }
275
276                        assayService.exportRowWiseDataForMultipleAssaysToExcelFile( rowWiseAssayData, response.getOutputStream() )
277
278                        response.outputStream.flush()
279
280                } catch (Exception e) {
281                        throw e;
282                }
283        }
284
285        /**
286         * Method to export one or more assays to excel.
287         *
288         * @param       params.ids              One or more assay IDs to export
289         */
290        def exportToExcelAsList = {
291                def ids = params.list( 'ids' ).findAll { it.isLong() }.collect { Long.valueOf( it ) };
292
293                if( !ids ) {
294                        flash.errorMessage = "No assay ids given";
295                        redirect( action: "errorPage" );
296                        return;
297                }
298
299                // If only 1 assay is asked for, don't bother with merging multiple assays.
300                // In that case just use the export method to export one assay per sheet
301                if( ids.size() == 1 )
302                        return exportToExcelAsSheets( params );
303
304                // Find all assays for the given ids
305                def assays = ids.unique().collect { id -> Assay.get( id ) }.findAll { it }
306
307                // Send headers to the browser so the user can download the file
308                def filename = 'export.xlsx'
309                response.setHeader("Content-disposition", "attachment;filename=\"${filename}\"")
310                response.setContentType("application/octet-stream")
311
312                try {
313                        // Loop through all assays to collect the data
314                        def columnWiseAssayData = [];
315
316                        assays.each { assay ->
317                                // Determine which fields should be exported for this assay
318                                def fieldMap = assayService.collectAssayTemplateFields(assay)
319                                def measurementTokens = fieldMap.remove('Module Measurement Data')
320
321                                // Retrieve row based data for this assay
322                                def assayData = assayService.collectAssayData( assay, fieldMap, measurementTokens );
323                               
324                                // Prepend study and assay data to the list
325                                assayData = assayService.prependAssayData( assayData, assay, assay.samples?.size() )
326                                assayData = assayService.prependStudyData( assayData, assay, assay.samples?.size() )
327                               
328                                // Put each assay on another sheet
329                                columnWiseAssayData << assayData;
330                        }
331                       
332                        // Merge data from all assays
333                        def mergedColumnWiseData = assayService.mergeColumnWiseDataOfMultipleStudies( columnWiseAssayData );
334
335                        def rowData   = assayService.convertColumnToRowStructure(mergedColumnWiseData)
336                        assayService.exportRowWiseDataToExcelFile( rowData, response.getOutputStream() )
337
338                        response.outputStream.flush()
339
340                } catch (Exception e) {
341                        throw e;
342                }
343        }
344
345
346        def errorPage = {
347                render(view: 'excelExport/errorPage')
348        }
349}
Note: See TracBrowser for help on using the repository browser.