root/trunk/grails-app/controllers/dbnp/studycapturing/SimpleWizardController.groovy @ 1553

Revision 1553, 25.2 KB (checked in by robert@…, 3 years ago)

First version of a simple wizard

Line 
1/**
2 * SimpleWizardController Controler
3 *
4 * Description of my controller
5 *
6 * @author  your email (+name?)
7 * @since       2010mmdd
8 * @package     ???
9 *
10 * Revision information:
11 * $Rev: 1430 $
12 * $Author: work@osx.eu $
13 * $Date: 2011-01-21 21:05:36 +0100 (Fri, 21 Jan 2011) $
14 */
15package dbnp.studycapturing
16
17import org.dbnp.gdt.*
18import grails.plugins.springsecurity.Secured
19import dbnp.authentication.SecUser
20import dbnp.importer.ImportCell
21import dbnp.importer.ImportRecord
22import dbnp.importer.MappingColumn
23
24@Secured(['IS_AUTHENTICATED_REMEMBERED'])
25class SimpleWizardController extends StudyWizardController {
26        def authenticationService
27        def fileService
28        def importerService
29        def gdtService
30
31        /**
32         * index closure
33         */
34        def index = {
35                redirect( action: "study" );
36        }
37
38        /**
39         * Shows the study page
40         */
41        def study = {
42                // Retrieve the correct study
43                Study study = getStudyInWizard( params );
44
45                // If no study is found in the wizard, this is the entry page of the
46                // wizard. Retrieve the study from request parameters
47                if( !study ) {
48                        study = getStudyFromRequest( params );
49
50                        // Some error might have occurred during the retrieval of the study
51                        if( !study ) {
52                                redirect( controller: 'simpleWizard', action: 'study' );
53                                return;
54                        }
55
56                        session.simpleWizard = [ study: study ]
57                }
58
59                def event = getEvent(params);
60
61                // If any event on this page is triggered, we should save the entered data.
62                // If no event is triggered, the user gets here from another page. In that case,
63                // we don't set the values
64                if( event ) {
65                        // Only continue to the next or previous page if the information entered is correct
66                        if( handleStudy( study, params ) ) {
67                                // Now determine what action to perform
68                                // If the user clicks next, the study should be validated
69                                if( event == "next" && validateObject( study ) ) {
70                                        toPage( "samples" );
71                                        return;
72                                }
73                        }
74                }
75
76                // Give the study to the user
77                [ study: study ]
78        }
79
80        /**
81         * Shows the samples page
82         */
83        def samples = {
84                // Retrieve the correct study
85                study = getStudyInWizard( params );
86                if( !study ) {
87                        redirect( controller: 'simpleWizard', action: 'study' );
88                        return;
89                }
90
91                def event = getEvent(params);
92
93                // If any event on this page is triggered, we should save the entered data.
94                // If no event is triggered, the user gets here from another page. In that case,
95                // we don't set the values
96                if( event ) {
97                        // Now determine what action to perform
98                        if( event == "next" && handleSamples( study, params )) {
99                                // Only continue to the next page if the information entered is correct
100                                toPage( "columns" );
101                                return;
102                        } else if( event == "previous" ) {
103                                // The user may go to the previous page, even if none of the data entered is OK.
104                                toPage( "study" );
105                                return;
106                        } else if( event == "skip" ) {
107                                // The user may skip the complete samples page
108                                toPage( "assays" );
109                                return;
110                        }
111                }
112
113                // Give the study and other data to the user
114                [ study: study, sampleTemplates: Template.findAllByEntity( Sample.class ), encodedEntity: gdtService.encryptEntity( Sample.class.name ), sampleForm: session.simpleWizard.sampleForm ]
115        }
116
117        /**
118         * Shows the columns page
119         */
120        def columns = {
121                // Retrieve the correct study
122                study = getStudyInWizard( params );
123                if( !study ) {
124                        redirect( controller: 'simpleWizard', action: 'study' );
125                        return;
126                }
127
128                def event = getEvent(params);
129
130                // If any event on this page is triggered, we should save the entered data.
131                // If no event is triggered, the user gets here from another page. In that case,
132                // we don't set the values
133                if( event ) {
134                        // Now determine what action to perform
135                        if( event == "next" && handleColumns( study, params ) ) {
136                                // Only continue to the next page if the information entered is correct
137                                if( session.simpleWizard.imported.numInvalidEntities > 0 ) {
138                                        toPage( "missingFields" );
139                                } else {
140                                        toPage( "assays" );
141                                }
142                                return;
143                        } else if( event == "previous" ) {
144                                // THe user may go to the previous page, even if the data is not correct
145                                toPage( "samples" );
146                                return;
147                        }
148                }
149
150                // Give the study and other data to the user
151                [ study: study,
152                                        filename: session.simpleWizard.sampleForm.importFile,
153                                        template: Template.get( session.simpleWizard.sampleForm.templateId ),
154                                        excel: session.simpleWizard.excel]
155        }
156
157        /**
158         * Shows the page where missing fields can be filled in
159         */
160        def missingFields = {
161                // Retrieve the correct study
162                study = getStudyInWizard( params );
163                if( !study ) {
164                        redirect( controller: 'simpleWizard', action: 'study' );
165                        return;
166                }
167
168                def event = getEvent(params);
169
170                // If any event on this page is triggered, we should save the entered data.
171                // If no event is triggered, the user gets here from another page. In that case,
172                // we don't set the values
173                if( event ) {
174                        // Now determine what action to perform
175                        if( event == "next" && handleMissingFields( study, params ) ) {
176                                if( session.simpleWizard.imported.numInvalidEntities == 0 ) {
177                                        // Only continue to the next page if the information entered is correct
178                                        toPage( "assays" );
179                                        return;
180                                }
181                        } else if( event == "previous" ) {
182                                // THe user may go to the previous page, even if the data is not correct
183                                toPage( "columns" );
184                                return;
185                        }
186                }
187
188                // If any errors have occurred during validation, show them to the user. However,
189                // the same error might have occurred for multiple entities. For that reason,
190                // we only show unique errors
191                def rules
192                if( session.simpleWizard.imported.errors ) {
193                        rules = session.simpleWizard.imported.errors*.values().flatten().unique().join( "<br /> \n" );
194                }
195
196                // Give the study and other data to the user
197                [ study: study, imported: session.simpleWizard.imported, rules: rules ]
198        }
199
200        /**
201         * Shows the assay page
202         */
203        def assays = {
204                // Retrieve the correct study
205                Study study = getStudyInWizard( params );
206                if( !study ) {
207                        redirect( controller: 'simpleWizard', action: 'study' );
208                        return;
209                }
210               
211                Assay assay
212                if( study.assays?.size() ) {
213                        assay = study.assays[0];
214                        study.removeFromAssays( assay );
215                } else {
216                        assay = new Assay();
217                }
218                       
219                def event = getEvent(params);
220
221                // If any event on this page is triggered, we should save the entered data.
222                // If no event is triggered, the user gets here from another page. In that case,
223                // we don't set the values
224                if( event ) {
225                        // Only continue to the next or previous page if the information entered is correct
226                        if( event == "skip" ) {
227                                // The user may skip the complete assay page
228                                toPage( "overview" );
229                                return;
230                        } else if( handleAssays( assay, params ) ) {
231                                study.addToAssays( assay );
232                               
233                                // Now determine what action to perform
234                                if( event == "next" && validateObject( study ) ) {
235                                        toPage( "overview" );
236                                        return;
237                                } else if( event == "previous" ) {
238                                        toPage( "samples" )
239                                        return;
240                                }
241                        }
242                }
243
244                // Give the study to the user
245                [ study: study, assay: assay ]
246        }
247       
248        /**
249         * Shows an overview of the entered study
250         */
251        def overview = {
252                // Retrieve the correct study
253                Study study = getStudyInWizard( params );
254                if( !study ) {
255                        redirect( controller: 'simpleWizard', action: 'study' );
256                        return;
257                }
258                       
259                def event = getEvent(params);
260
261                // If any event on this page is triggered, we should save the entered data.
262                // If no event is triggered, the user gets here from another page. In that case,
263                // we don't set the values
264                if( event ) {
265                        // Now determine what action to perform
266                        if( event == "save" ) {
267                                toPage( "save" );
268                                return;
269                        } else if( event == "previous" ) {
270                                toPage( "assay" )
271                                return;
272                        }
273                }
274
275                // Give the study to the user
276                [ study: study ]
277        }
278       
279        def save = {
280                // Retrieve the correct study
281                Study study = getStudyInWizard( params );
282                if( !study ) {
283                        redirect( controller: 'simpleWizard', action: 'study' );
284                        return;
285                }
286               
287                // Make sure all samples are attached to all assays
288                study.assays.each { assay ->
289                        assay.samples?.clear();
290                        study.samples.each { sample ->
291                                assay.addToSamples( sample )
292                        }
293                }
294               
295                // Save the study
296                if( study.save( flush: true ) ) {
297                        // Clear session
298                        session.simpleWizard = null;
299                       
300                        flash.message = "Your study is succesfully saved.";
301                } else {
302                        flash.error = "An error occurred while saving your study";
303                        //validateObject( study );
304                }
305
306                // Give the study to the user
307                [ study: study ]
308        }
309
310        /**
311         * Handles study input
312         * @param study         Study to update
313         * @param params        Request parameter map
314         * @return                      True if everything went OK, false otherwise. An error message is put in flash.error
315         */
316        def handleStudy( study, params ) {
317                // did the study template change?
318                if (params.get('template') && study.template?.name != params.get('template')) {
319                        // set the template
320                        study.template = Template.findByName(params.remove('template'))
321                }
322
323                // does the study have a template set?
324                if (study.template && study.template instanceof Template) {
325                        // yes, iterate through template fields
326                        study.giveFields().each() {
327                                // and set their values
328                                study.setFieldValue(it.name, params.get(it.escapedName()))
329                        }
330                }
331
332                // handle public checkbox
333                if (params.get("publicstudy")) {
334                        study.publicstudy = params.get("publicstudy")
335                }
336
337                // handle publications
338                handleStudyPublications(study, params)
339
340                // handle contacts
341                handleStudyContacts(study, params)
342
343                // handle users (readers, writers)
344                handleStudyUsers(study, params, 'readers')
345                handleStudyUsers(study, params, 'writers')
346               
347                return true
348        }
349
350        /**
351         * Handles the upload of sample data
352         * @param study         Study to update
353         * @param params        Request parameter map
354         * @return                      True if everything went OK, false otherwise. An error message is put in flash.error
355         */
356        def handleSamples( study, params ) {
357                def filename = params.get( 'importfile' );
358
359                // Handle 'existing*' in front of the filename. This is put in front to make a distinction between
360                // an already uploaded file test.txt (maybe moved to some other directory) and a newly uploaded file test.txt
361                // still being in the temporary directory.
362                // This import step doesn't have to make that distinction, since all files remain in the temporary directory.
363                if( filename[0..8] == 'existing*' )
364                        filename = filename[9..-1]
365
366                def templateId  = params.long( 'template_id' )
367                int sheetIndex = (params.int( 'sheetindex' ) ?: 1 )
368                int dataMatrixStart = (params.int( 'datamatrix_start' ) ?: 2 )
369                int headerRow = (params.int( 'headerrow' ) ?: 1 )
370
371                // Save form data in session
372                session.simpleWizard.sampleForm = [
373                                        importFile: filename,
374                                        templateId: templateId,
375                                        sheetIndex: sheetIndex,
376                                        dataMatrixStart: dataMatrixStart,
377                                        headerRow: headerRow
378                                ];
379
380                // Check whether the template exists
381                if (!templateId || !Template.get( templateId ) ){
382                        log.error ".simple study wizard not all fields are filled in"
383                        flash.error = "No template was chosen. Please choose a template for the samples you provided."
384                        return false
385                }
386
387                def importedfile = fileService.get( filename )
388                def workbook
389                if (importedfile.exists()) {
390                        try {
391                                workbook = importerService.getWorkbook(new FileInputStream(importedfile))
392                        } catch (Exception e) {
393                                log.error ".simple study wizard could not load file: " + e
394                                flash.error = "The given file doesn't seem to be an excel file. Please provide an excel file for entering samples.";
395                                return false
396                        }
397                } else {
398                        log.error ".simple study wizard no file given";
399                        flash.error = "No file was given. Please provide an excel file for entering samples.";
400                        return false;
401                }
402
403                if( !workbook ) {
404                        log.error ".simple study wizard could not load file into a workbook"
405                        flash.error = "The given file doesn't seem to be an excel file. Please provide an excel file for entering samples.";
406                        return false
407                }
408
409                def selectedentities = []
410
411                if( !excelChecks( workbook, sheetIndex, headerRow, dataMatrixStart ) )
412                        return false;
413
414                // Get the header from the Excel file using the arguments given in the first step of the wizard
415                def importerHeader;
416                def importerDataMatrix;
417
418                try {
419                        importerHeader = importerService.getHeader(workbook,
420                                        sheetIndex - 1,                 // 0 == first sheet
421                                        headerRow,                              // 1 == first row :s
422                                        dataMatrixStart - 1,    // 0 == first row
423                                        Sample.class)
424
425                        importerDataMatrix = importerService.getDatamatrix(
426                                        workbook,
427                                        importerHeader,
428                                        sheetIndex - 1,                 // 0 == first sheet
429                                        dataMatrixStart - 1,    // 0 == first row
430                                        5)
431                } catch( Exception e ) {
432                        // An error occurred while reading the excel file.
433                        log.error ".simple study wizard error while reading the excel file";
434                        e.printStackTrace();
435
436                        // Show a message to the user
437                        flash.error = "An error occurred while reading the excel file. Have you provided the right sheet number and row numbers. Contact your system administrator if this problem persists.";
438                        return false;
439                }
440
441                // Save read excel data into session
442                session.simpleWizard.excel = [
443                                        workbook: workbook,
444                                        sheetIndex: sheetIndex,
445                                        dataMatrixStart: dataMatrixStart,
446                                        headerRow: headerRow,
447                                        data: [
448                                                header: importerHeader,
449                                                dataMatrix: importerDataMatrix
450                                        ]
451                                ]
452
453                return true
454        }
455
456        /**
457         * Handles the matching of template fields with excel columns by the user
458         * @param study         Study to update
459         * @param params        Request parameter map
460         * @return                      True if everything went OK, false otherwise. An error message is put in flash.error
461         *                                      The field session.simpleWizard.imported.numInvalidEntities reflects the number of
462         *                                      entities that have errors, and should be fixed before saving. The errors for those entities
463         *                                      are saved into session.simpleWizard.imported.errors
464         */
465        def handleColumns( study, params ) {
466                // Find actual Template object from the chosen template name
467                def template = Template.get(session.simpleWizard.sampleForm.templateId)
468                def headers = session.simpleWizard.excel.data.header;
469
470                if( !params.matches ) {
471                        log.error( ".simple study wizard no column matches given" );
472                        flash.error = "No column matches given";
473                        return false;
474                }
475
476                // Retrieve the chosen matches from the request parameters and put them into
477                // the headers-structure, for later reference
478                params.matches.index.each { columnindex, property ->
479                        // Create an actual class instance of the selected entity with the selected template
480                        // This should be inside the closure because in some cases in the advanced importer, the fields can have different target entities
481                        def entityClass = Class.forName( headers[columnindex.toInteger()].entityclass.getName(), true, this.getClass().getClassLoader())
482                        def entityObj = entityClass.newInstance(template: template)
483
484                        // Store the selected property for this column into the column map for the ImporterService
485                        headers[columnindex.toInteger()].property = property
486
487                        // Look up the template field type of the target TemplateField and store it also in the map
488                        headers[columnindex.toInteger()].templatefieldtype = entityObj.giveFieldType(property)
489
490                        // Is a "Don't import" property assigned to the column?
491                        headers[columnindex.toInteger()].dontimport = (property == "dontimport") ? true : false
492
493                        //if it's an identifier set the mapping column true or false
494                        entityObj.giveFields().each {
495                                headers[columnindex.toInteger()].identifier = ( it.preferredIdentifier && (it.name == property) )
496                        }
497                }
498
499                // Import the workbook and store the table with entity records and store the failed cells
500                def (table, failedcells) = importerService.importData(session.simpleWizard.sampleForm.templateId,
501                                session.simpleWizard.excel.workbook,
502                                session.simpleWizard.excel.sheetIndex - 1,
503                                session.simpleWizard.excel.dataMatrixStart - 1,
504                                session.simpleWizard.excel.data.header)
505
506
507
508                session.simpleWizard.imported = [
509                                        data: table,
510                                        failedCells: failedcells
511                                ];
512
513                // loop through all entities to validate them and add them to failedcells if an error occurs
514                def numInvalidEntities = 0;
515                def errors = [];
516
517                // Remove all samples
518                study.samples?.clear();
519
520                table.each { record ->
521                        record.each { entity ->
522                                // Determine entity class and add a parent
523                                entity.parent = study
524                                study.addToSamples( entity );
525
526                                if (!entity.validate()) {
527                                        numInvalidEntities++;
528
529                                        // Add this field to the list of failed cells, in order to give the user feedback
530                                        failedcells = addNonValidatingCells( failedcells, entity )
531
532                                        // Also create a full list of errors
533                                        errors += getHumanReadableErrors( entity );
534                                }
535                        }
536                }
537
538                session.simpleWizard.imported.numInvalidEntities = numInvalidEntities;
539                session.simpleWizard.imported.errors = errors;
540
541                return true
542        }
543       
544        /**
545        * Handles the update of the edited fields by the user
546        * @param study          Study to update
547        * @param params         Request parameter map
548        * @return                       True if everything went OK, false otherwise. An error message is put in flash.error.
549        *                                       The field session.simpleWizard.imported.numInvalidEntities reflects the number of
550        *                                       entities that still have errors, and should be fixed before saving. The errors for those entities
551        *                                       are saved into session.simpleWizard.imported.errors
552        */
553   def handleMissingFields( study, params ) {
554           def numInvalidEntities = 0;
555           def errors = [];
556
557           // Remove all samples before adding them again
558           study.samples?.clear();
559
560           // Check which fields failed previously
561           def failedCells = session.simpleWizard.imported.failedCells
562
563           session.simpleWizard.imported.data.each { table ->
564                   table.each { entity ->
565                           def invalidFields = 0
566
567                           // Set the fields for this entity by retrieving values from the params
568                           entity.giveFields().each { field ->
569                                   def fieldName = importerService.getFieldNameInTableEditor( entity, field );
570
571                                   if( params[ fieldName ] == "#invalidterm" ) {
572                                           // If the value '#invalidterm' is chosen, the user hasn't fixed anything, so this field is still incorrect
573                                           invalidFields++;
574                                   } else {
575                                           if( field.type == org.dbnp.gdt.TemplateFieldType.ONTOLOGYTERM || field.type == org.dbnp.gdt.TemplateFieldType.STRINGLIST ) {
576                                                   // If this field is an ontologyterm field or a stringlist field, the value has changed, so remove the field from
577                                                   // the failedCells list
578                                                   importerService.removeFailedCell( failedCells, entity, field )
579                                           }
580
581                                           // Update the field, regardless of the type of field
582                                           entity.setFieldValue(field.name, params[ fieldName ] )
583                                   }
584                           }
585
586                           // Determine entity class and add a parent
587                           entity.parent = study;
588                           study.addToSamples( entity );
589
590                           // Try to validate the entity now all fields have been set. If it fails, return an error
591                           if (!entity.validate() || invalidFields) {
592                                   numInvalidEntities++;
593
594                                   // Add this field to the list of failed cells, in order to give the user feedback
595                                   failedCells = addNonValidatingCells( failedCells, entity )
596
597                                   // Also create a full list of errors
598                                   errors += getHumanReadableErrors( entity );
599                           } else {
600                                   importerService.removeFailedCell( failedCells, entity )
601                           }
602                   } // end of record
603           } // end of table
604
605           session.simpleWizard.imported.numInvalidEntities = numInvalidEntities;
606           session.simpleWizard.imported.errors = errors;
607
608           return true
609   }
610       
611        /**
612        * Handles assay input
613        * @param study          Study to update
614        * @param params         Request parameter map
615        * @return                       True if everything went OK, false otherwise. An error message is put in flash.error
616        */
617   def handleAssays( assay, params ) {
618           // did the study template change?
619           if (params.get('template') && assay.template?.name != params.get('template')) {
620                   // set the template
621                   assay.template = Template.findByName(params.remove('template'))
622           }
623
624           // does the study have a template set?
625           if (assay.template && assay.template instanceof Template) {
626                   // yes, iterate through template fields
627                   assay.giveFields().each() {
628                           // and set their values
629                           assay.setFieldValue(it.name, params.get(it.escapedName()))
630                   }
631           }
632
633           return true
634   }
635
636   /**
637    * Validates an object and puts human readable errors in validationErrors variable
638    * @param entity             Entity to validate
639    * @return                   True iff the entity validates, false otherwise
640    */
641   protected boolean validateObject( def entity ) {
642           if( !entity.validate() ) {
643                   flash.validationErrors = getHumanReadableErrors( entity )
644                   return false;
645           }
646           return true;
647   }
648   
649   
650        /**
651         * Adds all fields of this entity that have given an error when validating to the failedcells list
652         * @param failedcells   Current list of ImportRecords
653         * @param entity                Entity to check. The entity must have been validated before
654         * @return                              Updated list of ImportRecords
655         */
656        protected def addNonValidatingCells( failedcells, entity ) {
657                // Add this entity and the fields with an error to the failedCells list
658                ImportRecord failedRecord = new ImportRecord();
659
660                entity.getErrors().getFieldErrors().each { error ->
661                        String field = error.getField();
662                        def mc = importerService.findMappingColumn( session.simpleWizard.excel.data.header, field );
663                        def mcInstance = new MappingColumn( name: field, entityClass: Sample.class, index: -1, property: field.toLowerCase(), templateFieldType: entity.giveFieldType( field ) );
664
665                        // Create a clone of the mapping column
666                        if( mc ) {
667                                mcInstance.properties = mc.properties
668                        }
669
670                        failedRecord.addToImportcells( new ImportCell(mappingcolumn: mcInstance, value: error.getRejectedValue(), entityidentifier: importerService.getFieldNameInTableEditor( entity, field ) ) )
671                }
672                failedcells.add( failedRecord );
673
674                return failedcells
675        }
676
677
678
679
680        /**
681         * Checks an excel workbook whether the given sheetindex and rownumbers are correct     
682         * @param workbook                      Excel workbook to read
683         * @param sheetIndex            1-based sheet index for the sheet to read (1=first sheet)
684         * @param headerRow                     1-based row number for the header row (1=first row)
685         * @param dataMatrixStart       1-based row number for the first data row (1=first row)
686         * @return                                      True if the sheet index and row numbers are correct.
687         */
688        protected boolean excelChecks( def workbook, int sheetIndex, int headerRow, int dataMatrixStart ) {
689                // Perform some basic checks on the excel file. These checks should be performed by the importerservice
690                // in a perfect scenario.
691                if( sheetIndex > workbook.getNumberOfSheets() ) {
692                        log.error ".simple study wizard Sheet index is too high: " + sheetIndex + " / " + workbook.getNumberOfSheets();
693                        flash.error = "The sheet number you provided is too high. The provided excel sheet has only " + workbook.getNumberOfSheets() + " sheet(s).";
694                        return false
695                }
696
697                def sheet = workbook.getSheetAt(sheetIndex - 1);
698                def firstRowNum = sheet.getFirstRowNum();
699                def lastRowNum = sheet.getLastRowNum();
700                def numRows = lastRowNum - firstRowNum + 1;
701
702                if( headerRow > numRows  ) {
703                        log.error ".simple study wizard Header row number is incorrect: " + headerRow + " / " + numRows;
704                        flash.error = "The header row number you provided is too high. Please provide a number equal to or below " + numRows;
705                        return false
706                }
707
708                if( dataMatrixStart > numRows  ) {
709                        log.error ".simple study wizard Data row number is incorrect: " + dataMatrixStart + " / " + numRows;
710                        flash.error = "The data row number you provided is too high. Please provide a number equal to or below " + numRows;
711                        return false
712                }
713
714                return true;
715        }
716
717        /**
718         * Redirects the user to the page with the given name
719         * @param action
720         */
721        protected void toPage( String action ) {
722                println "Redirecting to: " + action;
723                redirect( action: action, params: [ "wizard": true ] );
724        }
725
726        /**
727         * Returns the event that is specified by the user form
728         * @param params
729         * @return
730         */
731        protected String getEvent( def params ) {
732                return params.get( 'event' );
733        }
734
735        /**
736         * Retrieves the required study from the database or return an empty Study object if
737         * no id is given
738         *
739         * @param params        Request parameters with params.id being the ID of the study to be retrieved
740         * @return                      A study from the database or an empty study if no id was given
741         */
742        protected Study getStudyFromRequest( def params ) {
743                int id = params.int( "id" );
744
745                if( !id ) {
746                        return new Study( title: "New study", owner: authenticationService.getLoggedInUser() );
747                }
748
749                Study s = Study.get( id );
750
751                if( !s.canWrite( authenticationService.getLoggedInUser() ) ) {
752                        flash.error = "No authorization to edit this study."
753                        return null;
754                }
755
756                return s
757        }
758
759        /**
760         * Retrieves the study that is saved in the wizard,
761         *
762         * @param params        Request parameters
763         * @return                      The found study object, or null if no study object is found
764         */
765        protected Study getStudyInWizard( def params ) {
766                if( params.wizard && session.simpleWizard && session.simpleWizard.study ) {
767                        // The user came here by clicking previous or a link on another page. Use the existing study
768                        return session.simpleWizard.study;
769                } else {
770                        // The user didn't get here from the wizard or no study is found
771                        return null;
772                }
773        }
774
775        /**
776         * transform domain class validation errors into a human readable
777         * linked hash map
778         * @param object validated domain class
779         * @return object  linkedHashMap
780         */
781        def getHumanReadableErrors(object) {
782                def errors = [:]
783                object.errors.getAllErrors().each() { error ->
784                        // error.codes.each() { code -> println code }
785
786                        // generally speaking g.message(...) should work,
787                        // however it fails in some steps of the wizard
788                        // (add event, add assay, etc) so g is not always
789                        // availably. Using our own instance of the
790                        // validationTagLib instead so it is always
791                        // available to us
792                        errors[error.getArguments()[0]] = validationTagLib.message(error: error)
793                }
794
795                return errors
796        }
797
798}
Note: See TracBrowser for help on using the browser.