root/trunk/grails-app/controllers/dbnp/studycapturing/StudyWizardController.groovy @ 1715

Revision 1715, 53.8 KB (checked in by work@…, 3 years ago)

- removed debug lines

  • Property svn:keywords set to Rev Author Date
Line 
1package dbnp.studycapturing
2
3import grails.plugins.springsecurity.Secured
4import dbnp.authentication.SecUser
5import org.codehaus.groovy.grails.plugins.web.taglib.ValidationTagLib
6import org.dbnp.gdt.*
7
8/**
9 * ajaxflow Controller
10 *
11 * @author      Jeroen Wesbeek
12 * @since       20101220
13 *
14 * Revision information:
15 * $Rev$
16 * $Author$
17 * $Date$
18 */
19@Secured(['IS_AUTHENTICATED_REMEMBERED'])
20class StudyWizardController {
21        def pluginManager
22        def authenticationService
23        def validationTagLib = new ValidationTagLib()
24
25        /**
26         * index method, redirect to the webflow
27         * @void
28         */
29        def index = {
30                // Grom a development message
31                if (pluginManager.getGrailsPlugin('grom')) "redirecting into the webflow".grom()
32
33                def jump = [:]
34
35                // allow quickjumps to:
36                //      edit a study    : /wizard?jump=edit&id=1
37                //      create a study  : /wizard?jump=create
38                if (params.get('jump')) {
39                        switch (params.get('jump')) {
40                                case 'create':
41                                        jump = [
42                                            action: 'create'
43                                        ]
44                                        break
45                                case 'edit':
46                                        jump = [
47                                            action      : 'edit',
48                                                id              : params.get('id')
49                                        ]
50                                        break
51                                case 'simpleedit':
52                                        jump = [
53                                            action      : 'simpleedit',
54                                                id              : params.get('id')
55                                        ]
56                                        break
57                                default:
58                                        break
59                        }
60                }
61
62                // store in session
63                session.jump = jump
64
65                /**
66                 * Do you believe it in your head?
67                 * I can go with the flow
68                 * Don't say it doesn't matter (with the flow) matter anymore
69                 * I can go with the flow (I can go)
70                 * Do you believe it in your head?
71                 */
72                redirect(action: 'pages')
73        }
74
75        /**
76         * WebFlow definition
77         * @void
78         */
79        def pagesFlow = {
80                // start the flow
81                onStart {
82                        // Grom a development message
83                        if (pluginManager.getGrailsPlugin('grom')) "entering the WebFlow".grom()
84
85                        // define variables in the flow scope which is availabe
86                        // throughout the complete webflow also have a look at
87                        // the Flow Scopes section on http://www.grails.org/WebFlow
88                        //
89                        // The following flow scope variables are used to generate
90                        // wizard tabs. Also see common/_tabs.gsp for more information
91                        // define flow variables
92                        flow.page = 0
93
94                        if (session.jump && session.jump?.action == 'simpleedit') {
95                                flow.pages = [
96                                    [title: 'Start'],
97                                        [title: 'Done']
98                                ]
99                        } else {
100                                flow.pages = [
101                                        //[title: 'Templates'],                 // templates
102                                        [title: 'Start'],                               // load or create a study
103                                        [title: 'Subjects'],                    // subjects
104                                        [title: 'Events'],                              // events and event grouping
105                                        //[title: 'Event Groups'],              // groups
106                                        [title: 'Samples'],                             // samples
107                                        [title: 'Assays'],                              // assays
108                                        //[title: 'Assay Groups'],              // assays
109                                        [title: 'Confirmation'],                // confirmation page
110                                        [title: 'Done']                                 // finish page
111                                ]
112                        }
113                        flow.jump = session.jump
114
115                        success()
116                }
117
118                // render the main wizard page which immediately
119                // triggers the 'next' action (hence, the main
120                // page dynamically renders the study template
121                // and makes the flow jump to the study logic)
122                mainPage {
123                        render(view: "/studyWizard/index")
124                        onRender {
125                                // Grom a development message
126                                if (pluginManager.getGrailsPlugin('grom')) "rendering the main Ajaxflow page (index.gsp)".grom()
127
128                                // let the view know we're in page 1
129                                flow.page = 1
130                                success()
131                        }
132                        on("next").to "handleJump"
133                }
134
135                // handle the jump parameter
136                //
137                // I came to get down [2x]
138                // So get out your seats and jump around
139                // Jump around [3x]
140                // Jump up Jump up and get down
141                // Jump [18x]
142                handleJump {
143                        action {
144                                // Grom a development message
145                                if (pluginManager.getGrailsPlugin('grom')) "entering handleJump".grom()
146
147                                if (flow.jump && flow.jump.action =~ 'edit') {
148                                        if (flow.jump.id) {
149                                                // load study
150                                                if (this.loadStudy(flow, flash, [studyid:flow.jump.id],authenticationService.getLoggedInUser())) {
151                                                        toStudyPage()
152                                                } else {
153                                                        toStartPage()
154                                                }
155                                        } else {
156                                                toModifyPage()
157                                        }
158                                } else if (flow.jump && flow.jump.action == 'create') {
159                                        if (!flow.study) flow.study = new Study()
160                                        toStudyPage()
161                                } else {
162                                        toStartPage()
163                                }
164                        }
165                        on("toStartPage").to "start"
166                        on("toStudyPage").to "study"
167                        on("toModifyPage").to "modify"
168                }
169
170                // create or modify a study
171                start {
172                        render(view: "_start")
173                        onRender {
174                                // Grom a development message
175                                if (pluginManager.getGrailsPlugin('grom')) "rendering the partial: pages/_start.gsp".grom()
176
177                                flow.page = 1
178                                success()
179                        }
180                        on("next") {
181                                // clean the flow scope
182                                flow.remove('study')
183
184                                // create a new study instance
185                                if (!flow.study) flow.study = new Study()
186
187                                // set 'quicksave' variable to false
188                                flow.quickSave = false
189                        }.to "study"
190                        on("modify").to "modify"
191                        on("import").to "redirectToImport"
192                }
193
194                // redirect to the import wizard
195                redirectToImport {
196                        render(view: "_redirect")
197                        onRender {
198                                // Grom a development message
199                                if (pluginManager.getGrailsPlugin('grom')) "rendering the partial: pages/_redirect.gsp".grom()
200
201                                flash.uri = "/importer/index"
202                        }
203                        on("next").to "start"
204                }
205
206                // load a study to modify
207                modify {
208                        render(view: "_modify")
209                        onRender {
210                                // Grom a development message
211                                if (pluginManager.getGrailsPlugin('grom')) "rendering the partial: pages/_modify.gsp".grom()
212
213                                flow.page = 1
214                                flash.showCancel = true
215                                success()
216                        }
217                        on("cancel") {
218                                flow.remove('study')
219
220                                success()
221                        }.to "start"
222                        on("next") {
223                                // load study
224                                if (this.loadStudy(flow, flash, params, authenticationService.getLoggedInUser())) {
225                                        success()
226                                } else {
227                                        error()
228                                }
229                        }.to "study"
230                }
231
232                // render and handle the study page
233                study {
234                        render(view: "_study")
235                        onRender {
236                                // Grom a development message
237                                if (pluginManager.getGrailsPlugin('grom')) "rendering the partial: pages/_study.gsp".grom()
238
239                                flow.page = 1
240
241                                // since this controller was refactored it's technically
242                                // safe to enable quicksave throughout the application.
243                                // However, we must keep an eye on the quality of the
244                                // studies as this change makes it easier to create dummy
245                                // studies which will create garbage in out database.
246                                flow.quickSave = true
247
248                                success()
249                        }
250                        on("refresh") {
251                                // handle form data
252                                studyPage(flow, flash, params)
253
254                                // force refresh of the template
255                                if (flow.study.template && flow.study.template instanceof Template) {
256                                        flow.study.template.refresh()
257                                }
258
259                                // reset errors
260                                flash.wizardErrors = [:]
261                                success()
262                        }.to "study"
263            on("switchTemplate") {
264                                // handle form data
265                                studyPage(flow, flash, params)
266
267                                // reset errors
268                                flash.wizardErrors = [:]
269                                success()
270                        }.to "study"
271                        on("previous") {
272                                // handle form data
273                                studyPage(flow, flash, params)
274
275                                // reset errors
276                                flash.wizardErrors = [:]
277                                success()
278                        }.to "start"
279                        on("next") {
280                                studyPage(flow, flash, params) ? success() : error()
281                        }.to "studyNext"
282                        on("quickSave") {
283                                studyPage(flow, flash, params) ? success() : error()
284                        }.to "save"
285                        on("toPageTwo") {
286                                studyPage(flow, flash, params) ? success() : error()
287                        }.to "studyNext"
288                        on("toPageThree") {
289                                studyPage(flow, flash, params) ? success() : error()
290                        }.to "events"
291                        on("toPageFour") {
292                                studyPage(flow, flash, params) ? success() : error()
293                        }.to "samples"
294                        on("toPageFive") {
295                                studyPage(flow, flash, params) ? success() : error()
296                        }.to "assays"
297                        on("toPageSix") {
298                                studyPage(flow, flash, params) ? success() : error()
299                        }.to "confirm"
300                        on("toPageSeven") {
301                                studyPage(flow, flash, params) ? success() : error()
302                        }.to "save"
303                }
304
305                // handle the second tab click on the study page
306                studyNext {
307                        action {
308                                if (session.jump?.action == 'simpleedit') {
309                                        toSave()
310                                } else {
311                                        toPageTwo()
312                                }
313                        }
314                        on("toSave").to "save"
315                        on("toPageTwo").to "subjects"
316                }
317
318                // render and handle subjects page
319                subjects {
320                        render(view: "_subjects")
321                        onRender {
322                                // Grom a development message
323                                if (pluginManager.getGrailsPlugin('grom')) "rendering the partial: pages/_subjects.gsp".grom()
324
325                                flow.page = 2
326
327                                if (!flash.values || !flash.values.addNumber) flash.values = [addNumber:1]
328
329                                success()
330                        }
331                        on("refresh") {
332                                // remember the params in the flash scope
333                                flash.values = params
334
335                                // handle form data
336                                subjectPage(flow, flash, params)
337
338                                // reset errors
339                                flash.wizardErrors = [:]
340
341                                // refresh templates
342                                if (flow.study.subjects) {
343                                        flow.study.giveSubjectTemplates().each() {
344                                                it.refresh()
345                                        }
346                                }
347
348                                success()
349                        }.to "subjects"
350                        on("add") {
351                                // handle form data
352                                addSubjects(flow, flash, params) ? success() : error()
353                        }.to "subjects"
354                        on("delete") {
355                                // handle form data
356                                subjectPage(flow, flash, params)
357
358                                // reset errors
359                                flash.wizardErrors = [:]
360
361                                // remove subject
362                                def subjectToRemove = flow.study.subjects.find { it.identifier == (params.get('do') as int) }
363                                if (subjectToRemove) {
364                                        flow.study.deleteSubject( subjectToRemove )
365                                }
366                        }.to "subjects"
367                        on("previous") {
368                                // handle form data
369                                subjectPage(flow, flash, params)
370
371                                // reset errors
372                                flash.wizardErrors = [:]
373                                success()
374                        }.to "study"
375                        on("next") {
376                                // handle form data
377                                subjectPage(flow, flash, params) ? success() : error()
378                        }.to "events"
379                        on("quickSave") {
380                                // handle form data
381                                subjectPage(flow, flash, params) ? success() : error()
382                        }.to "save"
383                        on("toPageOne") {
384                                subjectPage(flow, flash, params) ? success() : error()
385                        }.to "study"
386                        on("toPageThree") {
387                                subjectPage(flow, flash, params) ? success() : error()
388                        }.to "events"
389                        on("toPageFour") {
390                                subjectPage(flow, flash, params) ? success() : error()
391                        }.to "samples"
392                        on("toPageFive") {
393                                subjectPage(flow, flash, params) ? success() : error()
394                        }.to "assays"
395                        on("toPageSix") {
396                                subjectPage(flow, flash, params) ? success() : error()
397                        }.to "confirm"
398                        on("toPageSeven") {
399                                subjectPage(flow, flash, params) ? success() : error()
400                        }.to "save"
401                }
402
403                // render events page
404                events {
405                        render(view: "_events")
406                        onRender {
407                                // Grom a development message
408                                if (pluginManager.getGrailsPlugin('grom')) "rendering the partial: pages/_events.gsp".grom()
409
410                                flow.page = 3
411
412                                // add initial eventGroup to study
413                                if (!flow.study.eventGroups?.size()) {
414                                        flow.study.addToEventGroups(
415                                                new EventGroup(name: 'Group 1')
416                                        )
417                                }
418
419                                success()
420                        }
421                        on("clear") {
422                                // remove all events
423                                (flow.study.events + flow.study.samplingEvents).each() { event ->
424                                        if (event instanceof SamplingEvent) {
425                                                flow.study.deleteSamplingEvent( event )
426                                        } else {
427                                                flow.study.deleteEvent( event )
428                                        }
429                                }
430
431                                success()
432                        }.to "events"
433                        on("switchTemplate") {
434                                // handle form data
435                                eventPage(flow, flash, params)
436
437                                // get template
438                                def type        = params.get('eventType')
439                                def template= Template.findByName( params.get( type + 'Template' ) )
440                                if (template) template.refresh()
441
442                                // change template and/or instance?
443                                if (!flow.event || (flow.event instanceof Event && type == "sample") || (flow.event instanceof SamplingEvent && type == "event")) {
444                                        // create new instance
445                                        flow.event = (type == "event") ? new Event(template: template) : new SamplingEvent(template: template)
446                                } else {
447                                        flow.event.template = template
448                                }
449
450                                // reset errors
451                                flash.wizardErrors = [:]
452                                success()
453
454                        }.to "events"
455                        on("refresh") {
456                                // handle form data
457                                eventPage(flow, flash, params)
458
459                                // refresh templates
460                                flow.study.giveEventTemplates().each() {
461                                        it.refresh()
462                                }
463
464                                // refresh event template
465                                if (flow.event?.template) {
466                                        flow.event.template.refresh()
467                                }
468
469                                // reset errors
470                                flash.wizardErrors = [:]
471                                success()
472                        }.to "events"
473                        on("add") {
474                                // handle form data
475                                eventPage(flow, flash, params)
476
477                                // reset errors
478                                flash.wizardErrors = [:]
479
480                                // add event to study
481                                if (flow.event instanceof SamplingEvent) {
482                                        flow.study.addToSamplingEvents( flow.event )
483                                } else {
484                                        flow.study.addToEvents( flow.event )
485                                }
486
487                                // validate event
488                                if (flow.event.validate()) {
489                                        // remove event from the flowscope
490                                        flow.remove('event')
491
492                                        success()
493                                } else {
494                                        // event does not validate
495                                        // remove from study
496                                        if (flow.event instanceof SamplingEvent) {
497                                                flow.study.removeFromSamplingEvents( flow.event )
498                                        } else {
499                                                flow.study.removeFromEvents( flow.event )
500                                        }
501
502                                        // append errors
503                                        this.appendErrors(flow.event, flash.wizardErrors)
504                                        error()
505                                }
506                        }.to "events"
507                        on("deleteEvent") {
508                                // handle form data
509                                eventPage(flow, flash, params)
510
511                                // reset errors
512                                flash.wizardErrors = [:]
513
514                                // find matching (sampling) event
515                                def event                       = flow.study.events.find { it.getIdentifier() == (params.get('do') as int) }
516                                def samplingEvent       = flow.study.samplingEvents.find { it.getIdentifier() == (params.get('do') as int) }
517
518                                // perform delete
519                                if (event) flow.study.deleteEvent( event )
520                                if (samplingEvent) flow.study.deleteSamplingEvent( samplingEvent )
521                        }.to "events"
522                        on("addEventGroup") {
523                                // handle form data
524                                eventPage(flow, flash, params)
525
526                                // set work variables
527                                def groupName = 'Group '
528                                def tempGroupIterator = 1
529                                def tempGroupName = groupName + tempGroupIterator
530
531                                // make sure group name is unique
532                                if (flow.study.eventGroups) {
533                                        while (flow.study.eventGroups.find { it.name == tempGroupName }) {
534                                                tempGroupIterator++
535                                                tempGroupName = groupName + tempGroupIterator
536                                        }
537                                }
538                                groupName = tempGroupName
539
540                                // add a new eventGroup
541                                flow.study.addToEventGroups(
542                                        new EventGroup(
543                                                name    : groupName
544                                        )
545                                )
546
547                                // reset errors
548                                flash.wizardErrors = [:]
549                                success()
550                        }.to "events"
551                        on("deleteEventGroup") {
552                                // handle form data
553                                eventPage(flow, flash, params)
554
555                                // reset errors
556                                flash.wizardErrors = [:]
557
558                                // remove eventGroup
559                                def eventGroupToRemove = flow.study.eventGroups.find { it.getIdentifier() == (params.get('do') as int) }
560                                if (eventGroupToRemove) {
561                                        flow.study.deleteEventGroup( eventGroupToRemove )
562                                }
563                        }.to "events"
564                        on("duplicate") {
565                                // handle form data
566                                eventPage(flow, flash, params)
567
568                                // reset errors
569                                flash.wizardErrors = [:]
570
571                                // clone event
572                                def event = null
573                                (((flow.study.events) ? flow.study.events : []) + ((flow.study.samplingEvents) ? flow.study.samplingEvents : [])).find { it.getIdentifier() == (params.get('do') as int) }.each {
574                                        event = (it instanceof SamplingEvent) ? new SamplingEvent() : new Event()
575
576                                        // set template
577                                        event.template = it.template
578
579                                        // copy data
580                                        it.giveFields().each() { field ->
581                                                event.setFieldValue(
582                                                        field.name,
583                                                        it.getFieldValue(field.name)
584                                                )
585                                        }
586
587                                        // assign duplicate event to study
588                                        if (event instanceof SamplingEvent) {
589                                                flow.study.addToSamplingEvents(event)
590                                        } else {
591                                                flow.study.addToEvents(event)
592                                        }
593                                }
594
595                                success()
596                        }.to "events"
597                        on("previous") {
598                                // handle form data
599                                eventPage(flow, flash, params)
600
601                                // reset errors
602                                flash.wizardErrors = [:]
603                                success()
604                        }.to "subjects"
605                        on("next") {
606                                // handle form data
607                                eventPage(flow, flash, params) ? success() : error()
608                        }.to "eventsNext"
609                        on("quickSave") {
610                                // handle form data
611                                eventPage(flow, flash, params) ? success() : error()
612                        }.to "save"
613                        on("toPageOne") {
614                                eventPage(flow, flash, params) ? success() : error()
615                        }.to "study"
616                        on("toPageTwo") {
617                                eventPage(flow, flash, params) ? success() : error()
618                        }.to "subjects"
619                        on("toPageFour") {
620                                eventPage(flow, flash, params) ? success() : error()
621                        }.to "samples"
622                        on("toPageFive") {
623                                eventPage(flow, flash, params) ? success() : error()
624                        }.to "assays"
625                        on("toPageSix") {
626                                eventPage(flow, flash, params) ? success() : error()
627                        }.to "confirm"
628                        on("toPageSeven") {
629                                eventPage(flow, flash, params) ? success() : error()
630                        }.to "save"
631                }
632
633                // decide to show a warning page or not
634                eventsNext {
635                        action {
636                                // Grom a development message
637                                if (pluginManager.getGrailsPlugin('grom')) ".entering eventsNext".grom()
638
639                                def assigned = false
640
641                                // check if all sampling events are in an eventGroup
642                                flow.study.samplingEvents.each() { samplingEvent ->
643                                        // iterate through eventGroups
644                                        flow.study.eventGroups.each() { eventGroup ->
645                                                if ( eventGroup.samplingEvents.find { it.equals(samplingEvent) } ) {
646                                                        assigned = true
647                                                }
648                                        }
649                                }
650
651                                if (assigned) {
652                                        toGroupsPage()
653                                } else {
654                                        toWarningPage()
655                                }
656                        }
657                        on("toWarningPage").to "unassignedSamplingEventWarning"
658                        on("toGroupsPage").to "groups"
659                }
660
661                // warning page for unassigned samplingEvent
662                unassignedSamplingEventWarning {
663                        render(view: "_unassigned_samplingEvent_warning")
664                        onRender {
665                                // Grom a development message
666                                if (pluginManager.getGrailsPlugin('grom')) "rendering the partial: pages/_unnassigned_samplingEvent_warning.gsp".grom()
667
668                                flow.page = 3
669                                success()
670                        }
671                        on("next").to "groups"
672                        on("previous").to "events"
673                        on("toPageOne") {
674                                eventPage(flow, flash, params) ? success() : error()
675                        }.to "study"
676                        on("toPageTwo") {
677                                eventPage(flow, flash, params) ? success() : error()
678                        }.to "subjects"
679                        on("toPageFour") {
680                                eventPage(flow, flash, params) ? success() : error()
681                        }.to "samples"
682                        on("toPageFive") {
683                                eventPage(flow, flash, params) ? success() : error()
684                        }.to "assays"
685                        on("toPageSix") {
686                                eventPage(flow, flash, params) ? success() : error()
687                        }.to "confirm"
688                        on("toPageSeven") {
689                                eventPage(flow, flash, params) ? success() : error()
690                        }.to "save"
691                }
692
693                // groups page
694                groups {
695                        render(view: "_groups")
696                        onRender {
697                                // Grom a development message
698                                if (pluginManager.getGrailsPlugin('grom')) "rendering the partial: pages/_groups.gsp".grom()
699
700                                flow.page = 3
701                                success()
702                        }
703                        on("previous") {
704                                // handle form data
705                                groupPage(flow, flash, params) ? success() : error()
706                        }.to "events"
707                        on("next") {
708                                // handle form data
709                                groupPage(flow, flash, params) ? success() : error()
710                        }.to "samples"
711                        on("quickSave") {
712                                // handle form data
713                                groupPage(flow, flash, params) ? success() : error()
714                        }.to "save"
715                        on("toPageOne") {
716                                groupPage(flow, flash, params) ? success() : error()
717                        }.to "study"
718                        on("toPageTwo") {
719                                groupPage(flow, flash, params) ? success() : error()
720                        }.to "subjects"
721                        on("toPageFour") {
722                                groupPage(flow, flash, params) ? success() : error()
723                        }.to "samples"
724                        on("toPageFive") {
725                                groupPage(flow, flash, params) ? success() : error()
726                        }.to "assays"
727                        on("toPageSix") {
728                                groupPage(flow, flash, params) ? success() : error()
729                        }.to "confirm"
730                        on("toPageSeven") {
731                                groupPage(flow, flash, params) ? success() : error()
732                        }.to "save"
733                }
734
735                // sample 'previous' page with warning
736                samplePrevious {
737                        render(view: "_samples_previous_warning")
738                        onRender {
739                                // Grom a development message
740                                if (pluginManager.getGrailsPlugin('grom')) "rendering the partial: pages/_samples_previous_warning.gsp".grom()
741
742                                flow.page = 4
743                        }
744                        on("next").to "samples"
745                        on("previous").to "groups"
746                        on("toPageOne").to "study"
747                        on("toPageTwo").to "subjects"
748                        on("toPageThree").to "events"
749                        on("toPageFive").to "assays"
750                        on("toPageSix").to "confirm"
751                        on("toPageSeven").to "save"
752                }
753
754                // samples page
755                samples {
756                        render(view: "_samples")
757                        onRender {
758                                // Grom a development message
759                                if (pluginManager.getGrailsPlugin('grom')) "rendering the partial: pages/_samples.gsp".grom()
760
761                                flow.page = 4
762                                success()
763                        }
764                        on("switchTemplate") {
765                                // handle form data
766                                samplePage(flow, flash, params)
767
768                                // ignore errors
769                                flash.wizardErrors = [:]
770
771                                succes()
772                        }.to "samples"
773                        on("refresh") {
774                                // handle samples
775                                samplePage(flow, flash, params)
776
777                                // refresh all sample templates
778                                flow.study.giveSampleTemplates().each() {
779                                        it.refresh()
780                                }
781
782                                // ignore errors
783                                flash.wizardErrors = [:]
784
785                                success()
786                        }.to "samples"
787                        on("regenerate") {
788                                // handle samples
789                                samplePage(flow, flash, params)
790
791                                // remove all samples from the study
792                                flow.study.samples.findAll{true}.each() { sample ->
793                                        flow.study.deleteSample( sample )
794                                }
795
796                                // ignore errors
797                                flash.wizardErrors = [:]
798
799                                success()
800                        }.to "samples"
801                        on("previous") {
802                                // handle samples
803                                samplePage(flow, flash, params)
804
805                                // ignore errors
806                                flash.wizardErrors = [:]
807
808                                success()
809                        }.to "samplePrevious"
810                        on("next") {
811                                // handle form data
812                                samplePage(flow, flash, params) ? success() : error()
813                        }.to "assays"
814                        on("quickSave") {
815                                // handle form data
816                                samplePage(flow, flash, params) ? success() : error()
817                        }.to "save"
818                        on("toPageOne") {
819                                samplePage(flow, flash, params) ? success() : error()
820                        }.to "study"
821                        on("toPageTwo") {
822                                samplePage(flow, flash, params) ? success() : error()
823                        }.to "subjects"
824                        on("toPageThree") {
825                                samplePage(flow, flash, params) ? success() : error()
826                        }.to "events"
827                        on("toPageFive") {
828                                samplePage(flow, flash, params) ? success() : error()
829                        }.to "assays"
830                        on("toPageSix") {
831                                samplePage(flow, flash, params) ? success() : error()
832                        }.to "confirm"
833                        on("toPageSeven") {
834                                samplePage(flow, flash, params) ? success() : error()
835                        }.to "save"
836                }
837
838                // assays page
839                assays {
840                        render(view: "_assays")
841                        onRender {
842                                // Grom a development message
843                                if (pluginManager.getGrailsPlugin('grom')) "rendering the partial: pages/_assays.gsp".grom()
844
845                                flow.page = 5
846                        }
847                        on("refresh") {
848                                // handle form data
849                                assayPage(flow, flash, params)
850
851                                // force refresh of the template
852                                if (flow.assay && flow.assay.template && flow.assay.template instanceof Template) {
853                                        flow.assay.template.refresh()
854                                }
855
856                                // reset errors
857                                flash.wizardErrors = [:]
858                                success()
859                        }.to "assays"
860            on("switchTemplate") {
861                                // handle form data
862                    assayPage(flow, flash, params)
863
864                    // find assay template
865                    def template = Template.findByName(params.get('template'))
866                    if (flow.assay) {
867                            // set template
868                            flow.assay.template = template
869                    } else {
870                            // create a new assay instance
871                            flow.assay = new Assay(template: template)
872                    }
873
874                                // reset errors
875                                flash.wizardErrors = [:]
876                                success()
877                        }.to "assays"
878                        on("add") {
879                                // handle form data
880                                assayPage(flow, flash, params)
881
882                                // reset errors
883                                flash.wizardErrors = [:]
884
885                                // add assay to study
886                                flow.study.addToAssays( flow.assay )
887
888                                // validate assay
889                                if (flow.assay.validate()) {
890                                        // remove assay from the flowscope
891                                        flow.remove('assay')
892                                        success()
893                                } else {
894                                        // assay does not validate
895                                        // remove from study
896                                        flow.study.deleteAssay( flow.assay )
897
898                                        // append errors
899                                        this.appendErrors(flow.assay, flash.wizardErrors)
900                                        error()
901                                }
902                        }.to "assays"
903                        on("deleteAssay") {
904                                // handle form data
905                                assayPage(flow, flash, params)
906
907                                // reset errors
908                                flash.wizardErrors = [:]
909
910                                // find this assay
911                                def assay = flow.study.assays.find { it.getIdentifier() == (params.get('do') as int) }
912
913                                // perform delete
914                                if (assay) flow.study.deleteAssay( assay )
915                        }.to "assays"
916                        on("previous") {
917                                // handle form data
918                                assayPage(flow, flash, params)
919
920                                // ignore errors
921                                flash.wizardErrors = [:]
922
923                                success()
924                        }.to "samples"
925                        on("next") {
926                                // handle form data
927                                assayPage(flow, flash, params) ? success() : error()
928                        }.to "assayNext"
929                        on("quickSave") {
930                                // handle form data
931                                assayPage(flow, flash, params) ? success() : error()
932                        }.to "save"
933                        on("toPageOne") {
934                                assayPage(flow, flash, params) ? success() : error()
935                        }.to "study"
936                        on("toPageTwo") {
937                                assayPage(flow, flash, params) ? success() : error()
938                        }.to "subjects"
939                        on("toPageThree") {
940                                assayPage(flow, flash, params) ? success() : error()
941                        }.to "events"
942                        on("toPageFour") {
943                                assayPage(flow, flash, params) ? success() : error()
944                        }.to "samples"
945                        on("toPageSix") {
946                                assayPage(flow, flash, params) ? success() : error()
947                        }.to "confirm"
948                        on("toPageSeven") {
949                                assayPage(flow, flash, params) ? success() : error()
950                        }.to "save"
951                }
952
953                // assayNext
954                assayNext {
955                        action {
956                                // Grom a development message
957                                if (pluginManager.getGrailsPlugin('grom')) "entering assayNext".grom()
958
959                                // have we got samples and assays?
960                                if (flow.study.assays && flow.study.samples) {
961                                        // yes, go to the group page
962                                        toAssayGroups()
963                                } else {
964                                        // no need to show the group page as
965                                        // there's nothing to group
966                                        toConfirm()
967                                }
968                        }
969                        on("toAssayGroups").to "assayGroups"
970                        on("toConfirm").to "confirm"
971                }
972
973                // assay grouping page
974                assayGroups {
975                        render(view: "_assay_groups")
976                        onRender {
977                                // Grom a development message
978                                if (pluginManager.getGrailsPlugin('grom')) "rendering the partial: pages/_assay_groups.gsp".grom()
979
980                                flow.page = 5
981                        }
982                        on("previous") {
983                                // handle form data
984                                assayGroupPage(flow, flash, params)
985
986                                // ignore errors
987                                flash.wizardErrors = [:]
988
989                                success()
990                        }.to "assays"
991                        on("next") {
992                                // handle form data
993                                assayGroupPage(flow, flash, params) ? success() : error()
994                        }.to "confirm"
995                        on("quickSave") {
996                                // handle form data
997                                assayGroupPage(flow, flash, params) ? success() : error()
998                        }.to "save"
999                        on("toPageOne") {
1000                                assayGroupPage(flow, flash, params) ? success() : error()
1001                        }.to "study"
1002                        on("toPageTwo") {
1003                                assayGroupPage(flow, flash, params) ? success() : error()
1004                        }.to "subjects"
1005                        on("toPageThree") {
1006                                assayGroupPage(flow, flash, params) ? success() : error()
1007                        }.to "events"
1008                        on("toPageFour") {
1009                                assayGroupPage(flow, flash, params) ? success() : error()
1010                        }.to "samples"
1011                        on("toPageSix") {
1012                                assayGroupPage(flow, flash, params) ? success() : error()
1013                        }.to "confirm"
1014                        on("toPageSeven") {
1015                                assayGroupPage(flow, flash, params) ? success() : error()
1016                        }.to "save"
1017                }
1018
1019                // confirm Previous
1020                confirmPrevious {
1021                        action {
1022                                // Grom a development message
1023                                if (pluginManager.getGrailsPlugin('grom')) "entering confirmPrevious".grom()
1024
1025                                // have we got samples and assays?
1026                                if (flow.study.assays && flow.study.samples) {
1027                                        // yes, go to the group page
1028                                        toAssayGroups()
1029                                } else {
1030                                        // no need to show the group page as
1031                                        // there's nothing to group
1032                                        toAssays()
1033                                }
1034                        }
1035                        on("toAssayGroups").to "assayGroups"
1036                        on("toAssays").to "assays"
1037                }
1038
1039                // confirmation
1040                confirm {
1041                        render(view: "_confirmation")
1042                        onRender {
1043                                // Grom a development message
1044                                if (pluginManager.getGrailsPlugin('grom')) "rendering the partial: pages/_confirmation.gsp".grom()
1045
1046                                flow.page = 6
1047                        }
1048                        on("toStudy").to "study"
1049                        on("toSubjects").to "subjects"
1050                        on("toEvents").to "events"
1051                        on("toGroups").to "groups"
1052                        on("toSamples").to "samples"
1053                        on("toAssays").to "assays"
1054                        on("toAssayGroups").to "assayGroups"
1055                        on("previous").to "confirmPrevious"
1056                        on("next").to "save"
1057                        on("quickSave").to "save"
1058                        on("toPageOne").to "study"
1059                        on("toPageTwo").to "subjects"
1060                        on("toPageThree").to "events"
1061                        on("toPageFour").to "samples"
1062                        on("toPageFive").to "assays"
1063                        on("toPageSeven").to "save"
1064                }
1065
1066                // store all study data
1067                save {
1068                        action {
1069                                // Grom a development message
1070                                if (pluginManager.getGrailsPlugin('grom')) "entering save".grom()
1071
1072                                flow.page = 7
1073                                flash.wizardErrors = [:]
1074
1075                                // persist data to the database
1076                                try {
1077                                        // save study
1078                                        // Grom a development message
1079                                        if (pluginManager.getGrailsPlugin('grom')) "saving study".grom()
1080
1081                                        // Make sure the owner of the study is set right
1082                                        if (!flow.study.owner) {
1083                                                flow.study.owner = authenticationService.getLoggedInUser()
1084                                        }
1085
1086                                        if (!flow.study.save(flush:true)) {
1087                                                this.appendErrors(flow.study, flash.wizardErrors)
1088                                                throw new Exception('error saving study')
1089                                        }
1090                                        log.info ".saved study "+flow.study+" (id: "+flow.study.id+")"
1091
1092                                        success()
1093                                } catch (Exception e) {
1094                                        // rollback
1095                                        this.appendErrorMap(['exception': e.toString() + ', see log for stacktrace' ], flash.wizardErrors)
1096
1097                                        // stacktrace in flash scope
1098                                        flash.debug = e.getStackTrace()
1099
1100                                        error()
1101                                }
1102                        }
1103                        on("error").to "error"
1104                        on(Exception).to "error"
1105                        on("success").to "done"
1106                }
1107
1108                // error storing data
1109                error {
1110                        render(view: "_error")
1111                        onRender {
1112                                // Grom a development message
1113                                if (pluginManager.getGrailsPlugin('grom')) "rendering the partial: pages/_error.gsp".grom()
1114
1115                                flow.page = 6
1116                        }
1117                        on("next").to "save"
1118                        on("previous").to "samples"
1119                        on("toPageOne").to "study"
1120                        on("toPageTwo").to "subjects"
1121                        on("toPageThree").to "events"
1122                        on("toPageFour").to "samples"
1123                        on("toPageFive").to "assays"
1124                        on("toPageSix").to "confirm"
1125                        on("toPageSeven").to "save"
1126                }
1127
1128                // render finish page
1129                done {
1130                        render(view: "_done")
1131                        onRender {
1132                                // Grom a development message
1133                                if (pluginManager.getGrailsPlugin('grom')) "rendering the partial: pages/_done.gsp".grom()
1134
1135                                flow.page = 7
1136                        }
1137                        onEnd {
1138                                // clean flow scope
1139                                flow.clear()
1140                        }
1141                }
1142        }
1143
1144        /**
1145         * load a study
1146         * @param Map LocalAttributeMap (the flow scope)
1147         * @param Map localAttributeMap (the flash scope)
1148         * @param Map GrailsParameterMap (the flow parameters = form data)
1149         * @returns boolean
1150         */
1151        def loadStudy(flow, flash, params, user) {
1152                flash.wizardErrors      = [:]
1153
1154                // load study
1155                try {
1156                        // load study
1157                        def study = (params.studyid) ? Study.findById( params.studyid ) : Study.findByTitle( params.study )
1158
1159                        // Check whether the user is allowed to edit this study. If it is not allowed
1160                        // the used should had never seen a link to this page, so he should never get
1161                        // here. That's why we just return false
1162            if (!study.canWrite(user)){
1163                                return false
1164                        }
1165
1166                        // store study in the flowscope
1167                        flow.study = study
1168
1169                        // set 'quicksave' variable
1170                        flow.quickSave = true
1171
1172                        return true
1173                } catch (Exception e) {
1174                        // rollback
1175                        this.appendErrorMap(['exception': e.getMessage() + ', see log for stacktrace'], flash.wizardErrors)
1176
1177                        return false
1178                }
1179        }
1180
1181        /**
1182         * Handle the wizard study page
1183         *
1184         * @param Map LocalAttributeMap (the flow scope)
1185         * @param Map localAttributeMap (the flash scope)
1186         * @param Map GrailsParameterMap (the flow parameters = form data)
1187         * @returns boolean
1188         */
1189        def studyPage(flow, flash, params) {
1190                flash.values            = params
1191                flash.wizardErrors      = [:]
1192
1193                // instantiate study of it is not yet present
1194                if (!flow.study) flow.study = new Study()
1195
1196                // did the study template change?
1197                if (params.get('template').size() && flow.study.template?.name != params.get('template')) {
1198                        // set the template
1199                        flow.study.template = Template.findByName(params.remove('template'))
1200                }
1201
1202                // does the study have a template set?
1203                if (flow.study.template && flow.study.template instanceof Template) {
1204                        // yes, iterate through template fields
1205                        flow.study.giveFields().each() {
1206                                // and set their values
1207                                flow.study.setFieldValue(it.name, params.get(it.escapedName()))
1208                        }
1209                }
1210
1211                // handle publications
1212                handlePublications(flow, flash, params)
1213
1214                // handle contacts
1215                handleContacts(flow, flash, params)
1216
1217                // handle users (readers, writers)
1218                handleUsers(flow, flash, params, 'readers')
1219                handleUsers(flow, flash, params, 'writers')
1220
1221                // handle public checkbox
1222                flow.study.publicstudy = (params.get("publicstudy") && params.get("publicstudy") == "on") ? true : false
1223
1224                // have we got a template?
1225                if (flow.study.template && flow.study.template instanceof Template) {
1226                        // validate the study
1227                        if (flow.study.validate()) {
1228                                // instance is okay
1229                                return true
1230                        } else {
1231                                // validation failed
1232                                this.appendErrors(flow.study, flash.wizardErrors)
1233                                return false
1234                        }
1235                } else {
1236                        // no, return an error that the template is not set
1237                        this.appendErrorMap(['template': g.message(code: 'select.not.selected.or.add', args: ['template'])], flash.wizardErrors)
1238                        return false
1239                }
1240        }
1241
1242        /**
1243         * re-usable code for handling publications form data in a web flow
1244         * @param Map LocalAttributeMap (the flow scope)
1245         * @param Map localAttributeMap (the flash scope)
1246         * @param Map GrailsParameterMap (the flow parameters = form data)
1247         * @returns boolean
1248         */
1249        def handlePublications(flow, flash, params) {
1250                flash.wizardErrors      = [:]
1251                handleStudyPublications( flow.study, params );
1252        }
1253
1254        /**
1255         * re-usable code for handling contacts form data in a web flow
1256         * @param Map LocalAttributeMap (the flow scope)
1257         * @param Map localAttributeMap (the flash scope)
1258         * @param Map GrailsParameterMap (the flow parameters = form data)
1259         * @return boolean
1260         */
1261        def handleContacts(flow, flash, params) {
1262                flash.wizardErrors      = [:]
1263
1264                handleStudyContacts( flow.study, params );
1265        }
1266
1267        /**
1268         * re-usable code for handling contacts form data in a web flow
1269         * @param Map LocalAttributeMap (the flow scope)
1270         * @param Map localAttributeMap (the flash scope)
1271         * @param Map GrailsParameterMap (the flow parameters = form data)
1272     * @param String    'readers' or 'writers'
1273         * @return boolean
1274         */
1275        def handleUsers(flow, flash, params, type) {
1276                flash.wizardErrors = [:]
1277                handleStudyUsers( flow.study, params, type );
1278        }
1279       
1280    /**
1281        * re-usable code for handling publications form data
1282        * @param study  Study object to update
1283        * @param params GrailsParameterMap (the flow parameters = form data)
1284        * @returns boolean
1285        */
1286   def handleStudyPublications(Study study,  params) {
1287           if (study.publications) study.publications = []
1288
1289           // Check the ids of the pubblications that should be attached
1290           // to this study. If they are already attached, keep 'm. If
1291           // studies are attached that are not in the selected (i.e. the
1292           // user deleted them), remove them
1293           def publicationIDs = params.get('publication_ids')
1294           if (publicationIDs) {
1295                   // Find the individual IDs and make integers
1296                   publicationIDs = publicationIDs.split(',').collect { Integer.parseInt(it, 10) }
1297
1298                   // First remove the publication that are not present in the array
1299                   if( study.publications )
1300                           study.publications.removeAll { publication -> !publicationIDs.find { id -> id == publication.id } }
1301
1302                   // Add those publications not yet present in the database
1303                   publicationIDs.each { id ->
1304                           if (!study.publications.find { publication -> id == publication.id }) {
1305                                   def publication = Publication.get(id)
1306                                   if (publication) {
1307                                           study.addToPublications(publication)
1308                                   } else {
1309                                           log.info('.publication with ID ' + id + ' not found in database.')
1310                                   }
1311                           }
1312                   }
1313
1314           } else {
1315                   log.info('.no publications selected.')
1316                   if( study.publications )
1317                           study.publications.clear()
1318           }
1319   }
1320
1321   /**
1322        * re-usable code for handling contacts form data
1323        * @param study  Study object to update
1324        * @param Map GrailsParameterMap (the flow parameters = form data)
1325        * @return boolean
1326        */
1327   def handleStudyContacts(Study study, params) {
1328           if (!study.persons) study.persons = []
1329
1330           // Check the ids of the contacts that should be attached
1331           // to this study. If they are already attached, keep 'm. If
1332           // studies are attached that are not in the selected (i.e. the
1333           // user deleted them), remove them
1334
1335           // Contacts are saved as [person_id]-[role_id]
1336           def contactIDs = params.get('contacts_ids')
1337           if (contactIDs) {
1338                   // Find the individual IDs and make integers
1339                   contactIDs = contactIDs.split(',').collect {
1340                           def parts = it.split('-')
1341                           return [person: Integer.parseInt(parts[0]), role: Integer.parseInt(parts[1])]
1342                   }
1343
1344                   // First remove the contacts that are not present in the array
1345                   if( study.persons ) {
1346                           study.persons.removeAll {
1347                                   studyperson -> !contactIDs.find { ids -> (ids.person == studyperson.person.id) && (ids.role == studyperson.role.id) }
1348                           }
1349                   }
1350
1351                   // Add those contacts not yet present in the database
1352                   contactIDs.each { ids ->
1353                           if (!study.persons.find { studyperson -> (ids.person == studyperson.person.id) && (ids.role == studyperson.role.id) }) {
1354                                   def person = Person.get(ids.person)
1355                                   def role = PersonRole.get(ids.role)
1356                                   if (person && role) {
1357                                           // Find a studyperson object with these parameters
1358                                           def studyPerson = StudyPerson.findAll().find { studyperson -> studyperson.person.id == person.id && studyperson.role.id == role.id }
1359
1360                                           // If if does not yet exist, save the example
1361                                           if (!studyPerson) {
1362                                                   studyPerson = new StudyPerson(
1363                                                                   person: person,
1364                                                                   role: role
1365                                                                   )
1366                                                   studyPerson.save(flush: true)
1367                                           }
1368
1369                                           study.addToPersons(studyPerson)
1370                                   } else {
1371                                           log.info('.person ' + ids.person + ' or Role ' + ids.role + ' not found in database.')
1372                                   }
1373                           }
1374                   }
1375           } else {
1376                   log.info('.no persons selected.')
1377                   if( study.persons )
1378                           study.persons.clear()
1379           }
1380   }
1381
1382   /**
1383        * re-usable code for handling contacts form data
1384        * @param study  Study object to update
1385        * @param Map GrailsParameterMap (the flow parameters = form data)
1386        * @param String    'readers' or 'writers'
1387        * @return boolean
1388        */
1389   def handleStudyUsers(Study study, params, type) {
1390           def users = []
1391
1392           if (type == "readers" && study.readers ) {
1393                   users += study.readers
1394           } else if (type == "writers" && study.writers ) {
1395                   users += study.writers
1396           }
1397
1398           // Check the ids of the contacts that should be attached
1399           // to this study. If they are already attached, keep 'm. If
1400           // studies are attached that are not in the selected (i.e. the
1401           // user deleted them), remove them
1402
1403           // Users are saved as user_id
1404           def userIDs = params.get(type + '_ids')
1405           
1406           if (userIDs) {
1407                   // Find the individual IDs and make integers
1408                   userIDs = userIDs.split(',').collect { Long.valueOf(it, 10) }
1409                   
1410                   // First remove the publication that are not present in the array
1411                   users.removeAll { user -> !userIDs.find { id -> id == user.id } }
1412
1413                   // Add those publications not yet present in the database
1414                   userIDs.each { id ->
1415                           if (!users.find { user -> id == user.id }) {
1416                                   def user = SecUser.get(id)
1417                                   if (user) {
1418                                           users.add(user)
1419                                   } else {
1420                                           log.info('.user with ID ' + id + ' not found in database.')
1421                                   }
1422                           }
1423                   }
1424                   
1425           } else {
1426                   log.info('.no users selected.')
1427                   users.clear()
1428           }
1429           
1430           if (type == "readers") {
1431                   if (study.readers)
1432                           study.readers.clear()
1433                           
1434                   users.each { study.addToReaders(it) }
1435           } else if (type == "writers") {
1436                   if (study.writers)
1437                           study.writers.clear()
1438
1439                   users.each { study.addToWriters(it) }
1440                   
1441           }
1442   }
1443       
1444       
1445               
1446
1447        /**
1448         * Handle the wizard subject page
1449         *
1450         * @param Map LocalAttributeMap (the flow scope)
1451         * @param Map localAttributeMap (the flash scope)
1452         * @param Map GrailsParameterMap (the flow parameters = form data)
1453         * @returns boolean
1454         */
1455        def subjectPage(flow, flash, params) {
1456                def errors = false
1457                flash.wizardErrors = [:]
1458
1459                // remember the params in the flash scope
1460                flash.values = params
1461
1462                // iterate through subjects
1463                flow.study.subjects.each() { subject ->
1464                        // iterate through (template and domain) fields
1465                        subject.giveFields().each() { field ->
1466                                // set field
1467                                subject.setFieldValue(
1468                                        field.name,
1469                                        params.get('subject_' + subject.getIdentifier() + '_' + field.escapedName())
1470                                )
1471                        }
1472
1473                        // validate subject
1474                        if (!subject.validate()) {
1475                                errors = true
1476                                this.appendErrors(subject, flash.wizardErrors, 'subject_' + subject.getIdentifier() + '_')
1477                        }
1478                }
1479
1480                return !errors
1481        }
1482
1483        /**
1484         * Add a number of subjects to a study
1485         *
1486         * required params entities:
1487         * -addNumber (int)
1488         * -species   (string)
1489         * -template  (string)
1490         *
1491         * @param Map LocalAttributeMap (the flow scope)
1492         * @param Map localAttributeMap (the flash scope)
1493         * @param Map GrailsParameterMap (the flow parameters = form data)
1494         * @returns boolean
1495         */
1496        def addSubjects(flow, flash, params) {
1497                // remember the params in the flash scope
1498                flash.values = params
1499
1500                // handle the subject page
1501                subjectPage(flow, flash, params)
1502
1503                // (re)set error message
1504                flash.wizardErrors = [:]
1505
1506                // set work variables
1507                def errors              = false
1508                def number              = params.get('addNumber') as int
1509                def species             = Term.findByName(params.get('species'))
1510                def template    = Template.findByName(params.get('template'))
1511
1512                // can we add subjects?
1513                if (number > 0 && species && template) {
1514                        // add subjects to study
1515                        number.times {
1516                                // work variables
1517                                def subjectName = 'Subject '
1518                                def subjectIterator = 1
1519                                def tempSubjectName = subjectName + subjectIterator
1520
1521                                // make sure subject name is unique
1522                                if (flow.study.subjects) {
1523                                        while (flow.study.subjects.find { it.name == tempSubjectName }) {
1524                                                subjectIterator++
1525                                                tempSubjectName = subjectName + subjectIterator
1526                                        }
1527                                }
1528                                subjectName = tempSubjectName
1529
1530                                // create a subject instance
1531                                def subject = new Subject(
1532                                        name            : subjectName,
1533                                        species         : species,
1534                                        template        : template
1535                                )
1536
1537                                // add it to the study
1538                                flow.study.addToSubjects( subject )
1539                        }
1540                } else {
1541                        // add feedback
1542                        errors = true
1543                        if (number < 1) this.appendErrorMap(['addNumber': 'Enter a positive number of subjects to add'], flash.wizardErrors)
1544                        if (!species)   this.appendErrorMap(['species': g.message(code: 'select.not.selected.or.add', args: ['species'])], flash.wizardErrors)
1545                        if (!template)  this.appendErrorMap(['template': g.message(code: 'select.not.selected.or.add', args: ['template'])], flash.wizardErrors)
1546                }
1547
1548                return !errors
1549        }
1550
1551        /**
1552         * Handle the wizard event page
1553         *
1554         * @param Map LocalAttributeMap (the flow scope)
1555         * @param Map localAttributeMap (the flash scope)
1556         * @param Map GrailsParameterMap (the flow parameters = form data)
1557         * @returns boolean
1558         */
1559        def eventPage(flow, flash, params) {
1560                def errors = false
1561                flash.wizardErrors = [:]
1562
1563                // remember the params in the flash scope
1564                flash.values = params
1565
1566                // handle the 'add event' form
1567                if (flow.event) {
1568                        flow.event.giveFields().each() { field ->
1569                                // set field
1570                                flow.event.setFieldValue(
1571                                        field.name,
1572                                        params.get(field.escapedName())
1573                                )
1574                        }
1575                }
1576
1577                // handle the eventGroup names and grouping
1578                def name        = ""
1579                def tempName= ""
1580                flow.study.eventGroups.each() { eventGroup ->
1581                        // iterate through templates
1582                        flow.study.giveAllEventTemplates().each() { template ->
1583                                tempName = params.get( 'eventGroup_' + eventGroup.getIdentifier() + '_' + template.getIdentifier() )
1584
1585                                // is the name different?
1586                                if (tempName != eventGroup.name) {
1587                                        name = tempName
1588                                }
1589                        }
1590
1591                        // should the name change?
1592                        if (name) {
1593                                // yes, change it
1594                                eventGroup.name = name
1595                                name = ""
1596                        }
1597
1598                        // handle eventGrouping
1599                        ( ((flow.study.events) ? flow.study.events : []) + ((flow.study.samplingEvents) ? flow.study.samplingEvents : []) ) .each() { event ->
1600                                if (params.get( 'event_' + event.getIdentifier() + '_group_' + eventGroup.getIdentifier() )) {
1601                                        // add to eventGroup
1602                                        if (event instanceof SamplingEvent) {
1603                                                // check if we are already in this eventGroup
1604                                                if (!eventGroup.samplingEvents.find { it.equals(event) }) {
1605                                                        // no, add it
1606                                                        eventGroup.addToSamplingEvents(event)
1607
1608                                                        // iterate through subjects for this eventGroup
1609                                                        eventGroup.subjects.each() { subject ->
1610                                                                // instantiate a sample for this subject / event
1611                                                                def samplingEventName = ucwords(event.template.name)
1612                                                                def eventGroupName = ucwords(eventGroup.name).replaceAll("([ ]{1,})", "")
1613                                                                def sampleName = (ucwords(subject.name) + '_' + samplingEventName + '_' + eventGroupName + '_' + new RelTime(event.startTime).toString()).replaceAll("([ ]{1,})", "")
1614                                                                def tempSampleIterator = 0
1615                                                                def tempSampleName = sampleName
1616
1617                                                                // make sure sampleName is unique
1618                                                                if (flow.study.samples) {
1619                                                                        while (flow.study.samples.find { it.name == tempSampleName }) {
1620                                                                                tempSampleIterator++
1621                                                                                tempSampleName = sampleName + "_" + tempSampleIterator
1622                                                                        }
1623                                                                        sampleName = tempSampleName
1624                                                                }
1625
1626                                                                // instantiate a sample
1627                                                                flow.study.addToSamples(
1628                                                                        new Sample(
1629                                                                                parentSubject   : subject,
1630                                                                                parentEvent             : event,
1631                                                                                parentEventGroup: eventGroup,
1632                                                                                name                    : sampleName,
1633                                                                                template                : (event.sampleTemplate) ? event.sampleTemplate : ''
1634                                                                        )
1635                                                                )
1636                                                        }
1637                                                }
1638                                        } else {
1639                                                eventGroup.addToEvents(event)
1640                                        }
1641                                } else {
1642                                        // remove from eventGroup
1643                                        if (event instanceof SamplingEvent) {
1644                                                // iterate through subjects (if we have them)
1645                                                eventGroup.subjects.each() { subject ->
1646                                                        // find all samples for this subject / event
1647                                                        flow.study.samples.findAll { (it.parentEvent.equals(event) && it.parentSubject.equals(subject) ) }.each() {
1648                                                                // delete this sample
1649                                                                flow.study.deleteSample( it )
1650                                                        }
1651                                                }
1652
1653                                                eventGroup.removeFromSamplingEvents(event)
1654                                        } else {
1655                                                eventGroup.removeFromEvents(event)
1656                                        }
1657                                }
1658                        }
1659                }
1660
1661                // handle the (sampling) events
1662                ( ((flow.study.events) ? flow.study.events : []) + ((flow.study.samplingEvents) ? flow.study.samplingEvents : []) ) .each() { event ->
1663                        event.giveFields().each() { field ->
1664                                event.setFieldValue(
1665                                        field.name,
1666                                        params.get( 'event_' + event.getIdentifier() + '_' + field.escapedName() )
1667                                )
1668                        }
1669
1670                        // validate event
1671                        if (!event.validate()) {
1672                                errors = true
1673                                this.appendErrors(event, flash.wizardErrors)
1674                        }
1675                }
1676
1677                return !errors
1678        }
1679
1680        /**
1681         * Handle the wizard group page
1682         *
1683         * @param Map LocalAttributeMap (the flow scope)
1684         * @param Map localAttributeMap (the flash scope)
1685         * @param Map GrailsParameterMap (the flow parameters = form data)
1686         * @returns boolean
1687         */
1688        def groupPage(flow, flash, params) {
1689                def errors = false
1690                flash.wizardErrors = [:]
1691
1692                // remember the params in the flash scope
1693                flash.values = params
1694
1695                // iterate through groups
1696                flow.study.eventGroups.each() { eventGroup ->
1697                        // iterate through subjects
1698                        flow.study.subjects.each() { subject ->
1699                                if (params.get('subject_' + subject.getIdentifier() + '_group_' + eventGroup.getIdentifier() )) {
1700                                        // check if this subject is already part of this eventGroup
1701                                        if ( !eventGroup.subjects.find { it.equals(subject) } ) {
1702                                                // add to eventGroup
1703                                                eventGroup.addToSubjects(subject)
1704
1705                                                // iterate through samplingEvents
1706                                                eventGroup.samplingEvents.each() { samplingEvent ->
1707                                                        def samplingEventName = ucwords(samplingEvent.template.name)
1708                                                        def eventGroupName = ucwords(eventGroup.name)
1709                                                        def sampleName = (ucwords(subject.name) + '_' + samplingEventName + '_' + eventGroupName + '_' + new RelTime(samplingEvent.startTime).toString()).replaceAll("([ ]{1,})", "")
1710                                                        def tempSampleIterator = 0
1711                                                        def tempSampleName = sampleName
1712
1713                                                        // make sure sampleName is unique
1714                                                        if (flow.study.samples) {
1715                                                                while (flow.study.samples.find { it.name == tempSampleName }) {
1716                                                                        tempSampleIterator++
1717                                                                        tempSampleName = sampleName + "_" + tempSampleIterator
1718                                                                }
1719                                                                sampleName = tempSampleName
1720                                                        }
1721
1722                                                        // instantiate a sample
1723                                                        flow.study.addToSamples(
1724                                                                new Sample(
1725                                                                        parentSubject   : subject,
1726                                                                        parentEvent             : samplingEvent,
1727                                                                        parentEventGroup: eventGroup,
1728                                                                        name                    : sampleName,
1729                                                                        template                : (samplingEvent.sampleTemplate) ? samplingEvent.sampleTemplate : ''
1730                                                                )
1731                                                        )
1732                                                }
1733                                        } else {
1734                                        }
1735                                } else {
1736                                        // check if this subject is a member of this eventGroup
1737                                        if (eventGroup.subjects.find { it.equals(subject) }) {
1738                                                // remove from eventGroup
1739                                                eventGroup.removeFromSubjects(subject)
1740
1741                                                // iterate through samplingEvents
1742                                                eventGroup.samplingEvents.each() { samplingEvent ->
1743                                                        flow.study.samples.findAll { (it.parentEvent.equals(samplingEvent) && it.parentSubject.equals(subject) && it.parentEventGroup.equals(eventGroup)) }.each() {
1744                                                                // delete this sample
1745                                                                flow.study.deleteSample( it )
1746                                                        }
1747                                                }
1748                                        }
1749                                }
1750                        }
1751                }
1752        }
1753
1754        /**
1755         * Handle the wizard samples page
1756         *
1757         * @param Map LocalAttributeMap (the flow scope)
1758         * @param Map localAttributeMap (the flash scope)
1759         * @param Map GrailsParameterMap (the flow parameters = form data)
1760         * @returns boolean
1761         */
1762        def samplePage(flow, flash, params) {
1763                def errors = false
1764                flash.wizardErrors = [:]
1765
1766                // remember the params in the flash scope
1767                flash.values = params
1768
1769                // iterate through samples
1770                flow.study.samples.each() { sample ->
1771                        // iterate through sample fields
1772                        sample.giveFields().each() { field ->
1773                                def value = params.get('sample_'+sample.getIdentifier()+'_'+field.escapedName())
1774
1775                                // set field value
1776                                if (!(field.name == 'name' && !value)) {
1777                                        log.info "setting "+field.name+" to "+value
1778                                        sample.setFieldValue(field.name, value)
1779                                }
1780                        }
1781
1782                        // has the template changed?
1783                        def templateName = params.get('template_' + sample.getIdentifier())
1784                        if (templateName && sample.template?.name != templateName) {
1785                                sample.template = Template.findByName(templateName)
1786                        }
1787
1788                        // validate sample
1789                        if (!sample.validate()) {
1790                                errors = true
1791                                this.appendErrors(sample, flash.wizardErrors, 'sample_' + sample.getIdentifier() + '_' )
1792                                log.info 'error-> sample_'+sample.getIdentifier()
1793                        }
1794                }
1795
1796                return !errors
1797        }
1798
1799        /**
1800         * Handle the wizard assays page
1801         *
1802         * @param Map LocalAttributeMap (the flow scope)
1803         * @param Map localAttributeMap (the flash scope)
1804         * @param Map GrailsParameterMap (the flow parameters = form data)
1805         * @returns boolean
1806         */
1807        def assayPage(flow, flash, params) {
1808                def errors = false
1809                flash.wizardErrors = [:]
1810
1811                // remember the params in the flash scope
1812                flash.values = params
1813
1814                // handle the 'add assay' form
1815                if (flow.assay) {
1816                        flow.assay.giveFields().each() { field ->
1817                                // set field
1818                                flow.assay.setFieldValue(
1819                                        field.name,
1820                                        params.get(field.escapedName())
1821                                )
1822                        }
1823                }
1824
1825                // handle the assay data
1826                flow.study.assays.each() { assay ->
1827                        // set data
1828                        assay.giveFields().each() { field ->
1829                                assay.setFieldValue(
1830                                        field.name,
1831                                        params.get( 'assay_' + assay.getIdentifier() + '_' + field.escapedName() )
1832                                )
1833                        }
1834
1835                        // validate assay
1836                        if (!assay.validate()) {
1837                                errors = true
1838                                this.appendErrors(assay, flash.wizardErrors, 'assay_' + assay.getIdentifier() + '_')
1839                        }
1840                }
1841
1842                return !errors
1843        }
1844
1845        /**
1846         * Handle the wizard assayGroups page
1847         *
1848         * @param Map LocalAttributeMap (the flow scope)
1849         * @param Map localAttributeMap (the flash scope)
1850         * @param Map GrailsParameterMap (the flow parameters = form data)
1851         * @returns boolean
1852         */
1853        def assayGroupPage(flow, flash, params) {
1854                def errors = false
1855                flash.wizardErrors = [:]
1856
1857                // remember the params in the flash scope
1858                flash.values = params
1859
1860                // iterate through samples
1861                flow.study.samples.each() { sample ->
1862                        // iterate through assays
1863                        flow.study.assays.each() { assay ->
1864                                if (params.get( 'sample_' + sample.getIdentifier() + '_assay_' + assay.getIdentifier() )) {
1865                                        // add sample to assay
1866                                        assay.addToSamples( sample )
1867                                } else {
1868                                        // remove sample from assay
1869                                        assay.removeFromSamples( sample )
1870                                }
1871                        }
1872                }
1873
1874                return !errors
1875        }
1876
1877        /**
1878         * groovy / java equivalent of php's ucwords function
1879         *
1880         * Capitalize all first letters of separate words
1881         *
1882         * @param String
1883         * @return String
1884         */
1885        public static ucwords(String text) {
1886                def newText = ''
1887
1888                // change case to lowercase
1889                text = text.toLowerCase()
1890
1891                // iterate through words
1892                text.split(" ").each() {
1893                        newText += it[0].toUpperCase() + it.substring(1) + " "
1894                }
1895
1896                return newText.substring(0, newText.size()-1)
1897        }
1898
1899        /**
1900         * return the object from a map of objects by searching for a name
1901         * @param String name
1902         * @param Map map of objects
1903         * @return Object
1904         */
1905        def getObjectByName(name, map) {
1906                def result = null
1907                map.each() {
1908                        if (it.name == name) {
1909                                result = it
1910                        }
1911                }
1912
1913                return result
1914        }
1915
1916        /**
1917         * transform domain class validation errors into a human readable
1918         * linked hash map
1919         * @param object validated domain class
1920         * @return object  linkedHashMap
1921         */
1922        def getHumanReadableErrors(object) {
1923                def errors = [:]
1924                object.errors.getAllErrors().each() { error ->
1925                        // error.codes.each() { code -> println code }
1926
1927                        // generally speaking g.message(...) should work,
1928                        // however it fails in some steps of the wizard
1929                        // (add event, add assay, etc) so g is not always
1930                        // availably. Using our own instance of the
1931                        // validationTagLib instead so it is always
1932                        // available to us
1933                        errors[ error.getArguments()[0] ] = validationTagLib.message(error: error)
1934                }
1935
1936                return errors
1937        }
1938
1939        /**
1940         * append errors of a particular object to a map
1941         * @param object
1942         * @param map linkedHashMap
1943         * @void
1944         */
1945        def appendErrors(object, map) {
1946                this.appendErrorMap(getHumanReadableErrors(object), map)
1947        }
1948
1949        def appendErrors(object, map, prepend) {
1950                this.appendErrorMap(getHumanReadableErrors(object), map, prepend)
1951        }
1952
1953        /**
1954         * append errors of one map to another map
1955         * @param map linkedHashMap
1956         * @param map linkedHashMap
1957         * @void
1958         */
1959        def appendErrorMap(map, mapToExtend) {
1960                map.each() {key, value ->
1961                        mapToExtend[key] = ['key': key, 'value': value, 'dynamic': false]
1962                }
1963        }
1964
1965        def appendErrorMap(map, mapToExtend, prepend) {
1966                map.each() {key, value ->
1967                        mapToExtend[prepend + key] = ['key': key, 'value': value, 'dynamic': true]
1968                }
1969        }
1970
1971        /**
1972         * Parses a RelTime string and returns a nice human readable string
1973         *
1974         * @return Human Readable string or a HTTP response code 400 on error
1975         */
1976        def ajaxParseRelTime = {
1977                if (params.reltime == null) {
1978                        response.status = 400
1979                        render('reltime parameter is expected')
1980                }
1981
1982                try {
1983                        def reltime = RelTime.parseRelTime(params.reltime)
1984                        render reltime.toPrettyString()
1985                } catch (IllegalArgumentException e) {
1986                        response.status = 400
1987                        render(e.getMessage())
1988                }
1989        }
1990
1991        /**
1992         * Proxy for searching PubMed articles (or other articles from the Entrez DB).
1993         *
1994         * This proxy is needed because it is not allowed to fetch XML directly from a different
1995         * domain using javascript. So we have the javascript call a function on our own domain
1996         * and the proxy will fetch the data from Entrez
1997         *
1998         * @since       20100609
1999         * @param       _utility        The name of the utility, without the complete path. Example: 'esearch.fcgi'
2000         * @return      XML
2001         */
2002        def entrezProxy = {
2003                // Remove unnecessary parameters
2004                params.remove( "action" )
2005                params.remove( "controller" )
2006
2007                def url = "http://eutils.ncbi.nlm.nih.gov/entrez/eutils";
2008                def util = params.remove( "_utility" )
2009               
2010                if( !util ) {
2011                        response.setStatus( 404, "File not found" );
2012                        return;
2013                }
2014       
2015                def paramString = params.collect { k, v -> k + '=' + v.encodeAsURL() }.join( '&' );
2016
2017                def fullUrl = url + '/' + util + '?' + paramString;
2018
2019                // Return the output of the request
2020                response.setContentType("text/xml; charset=UTF-8")
2021
2022                response <<  new URL( fullUrl ).getText()
2023
2024                render ""
2025        }
2026}
Note: See TracBrowser for help on using the browser.