source: trunk/grails-app/controllers/dbnp/studycapturing/EventController.groovy @ 959

Last change on this file since 959 was 959, checked in by j.a.m.wesbeek@…, 9 years ago
  • set keyword expansion
  • Property svn:keywords set to Author Date Rev
File size: 20.3 KB
Line 
1package dbnp.studycapturing
2import java.text.SimpleDateFormat
3import dbnp.data.Term
4import dbnp.data.Ontology
5/**
6 * 888       888 888    888 8888888888 8888888b.  8888888888
7 * 888   o   888 888    888 888        888   Y88b 888
8 * 888  d8b  888 888    888 888        888    888 888
9 * 888 d888b 888 8888888888 8888888    888   d88P 8888888
10 * 888d88888b888 888    888 888        8888888P"  888
11 * 88888P Y88888 888    888 888        888 T88b   888
12 * 8888P   Y8888 888    888 888        888  T88b  888
13 * 888P     Y888 888    888 8888888888 888   T88b 8888888888
14 *
15 * 8888888 .d8888b.     88888888888 888    888 8888888888
16 *   888  d88P  Y88b        888     888    888 888
17 *   888  Y88b.             888     888    888 888
18 *   888   "Y888b.          888     8888888888 8888888
19 *   888      "Y88b.        888     888    888 888
20 *   888        "888        888     888    888 888
21 *   888  Y88b  d88P        888     888    888 888
22 * 8888888 "Y8888P"         888     888    888 8888888888
23 *
24 *   888888        d8888 888     888     d8888 8888888b.   .d88888b.   .d8888b.
25 *     "88b       d88888 888     888    d88888 888  "Y88b d88P" "Y88b d88P  Y88b
26 *      888      d88P888 888     888   d88P888 888    888 888     888 888    888
27 *      888     d88P 888 Y88b   d88P  d88P 888 888    888 888     888 888
28 *      888    d88P  888  Y88b d88P  d88P  888 888    888 888     888 888
29 *      888   d88P   888   Y88o88P  d88P   888 888    888 888     888 888    888
30 *      88P  d8888888888    Y888P  d8888888888 888  .d88P Y88b. .d88P Y88b  d88P
31 *      888 d88P     888     Y8P  d88P     888 8888888P"   "Y88888P"   "Y8888P"
32 *    .d88P
33 *  .d88P"
34 * 888P"
35 *
36 *  .d8888b.  888  .d8888b.  888  .d8888b.  888
37 * d88P  Y88b 888 d88P  Y88b 888 d88P  Y88b 888
38 *      .d88P 888      .d88P 888      .d88P 888
39 *    .d88P"  888    .d88P"  888    .d88P"  888
40 *    888"    888    888"    888    888"    888
41 *    888     Y8P    888     Y8P    888     Y8P
42 *             "              "              "
43 *    888     888    888     888    888     888
44 *
45 *
46 * TODO: add PROPER class and method documentation, just like have
47 *       agreed upon hundreds of times!!!!
48 */
49class EventController {
50
51    static allowedMethods = [save: "POST", update: "POST", delete: "POST"]
52
53    def index = {
54        redirect(action: "list", params: params)
55    }
56
57    def list = {
58        params.max = Math.min(params.max ? params.int('max') : 10, 100)
59        [eventInstanceList: Event.list(params), eventInstanceTotal: Event.count()]
60    }
61
62
63    /*def createForEventDescription = {
64        if( params["id"]==null)
65        {
66            def eventInstance = new Event()
67            def sDate = new Date( params["startTime"])
68            def eDate = new Date( params["endTime"])
69            def description = EventDescription.findById((params["eventDescription"])["id"])
70            return [testo:params.clone(), sDate:sDate, eDate:eDate, description:description ]
71        }
72        else
73        {
74            def eventInstance = Event.get(params.id)
75            if (!eventInstance) {
76                flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'event.label', default: 'Event'), params.id])}"
77                redirect(action: "list")
78            }
79            return [testo:params.clone(), sDate:eventInstance.startTime, eDate:eventInstance.endTime, description:eventInstance.eventDescription]
80        }
81    }*/
82
83
84    // Convert date strings to date strings grails can deal with.
85    // Input format:  "01/20/2010 08:45 am"
86    // Output format: "01/20/2010 20:45"
87    // Note: the "am" amd "pm" suffixes are removed.
88    def parseDate = {  st ->
89            def subst = st.substring(0,16)
90            def ampm =  st.substring(17,19)
91            if(ampm=="pm")
92            {
93                 def hours=st.substring(11,13)
94                 hours = hours.toInteger() + 12
95                 st = st.substring(0,11) + hours + st.substring(13,16)
96            }
97            else { st = st.substring(0,16) }
98
99            def sdfh = new SimpleDateFormat("MM/DD/yyyy hh:mm")
100            return sdfh.parse(st)
101    }
102
103
104
105
106    // helper function for save()
107    // parses the params from the edit view
108    // and saves paramters as new entries in the events value lists
109    def parseParamsForParameterValues( params, event ) {
110
111            params.each{ key,value ->
112                 def pattern =/(parameterValue\.)([\d]+)/
113                 def matcher = key=~pattern
114                 if(matcher) {
115                      def id = key.replaceAll(pattern,'$2')
116                      def parameter = ProtocolParameter.get(id)
117
118                      switch(parameter.type)
119                      {
120                            case dbnp.studycapturing.ProtocolParameterType.STRING:
121                                 event.parameterStringValues[parameter.name]=value
122                                 break
123                            case dbnp.studycapturing.ProtocolParameterType.FLOAT:
124                                 event.parameterFloatValues[parameter.name]=value.toFloat()
125                                 break
126                            case dbnp.studycapturing.ProtocolParameterType.INTEGER:
127                                 event.parameterFloatValues[parameter.name]=value.toInteger()
128                                 break
129                            case dbnp.studycapturing.ProtocolParameterType.STRINGLIST:
130                                 def item = ParameterStringListItem.get(value)
131                                 event.parameterStringListValues[''+parameter.id]=item
132                      }
133                 }
134            }
135    }
136
137
138
139    // assuming that an event has a sample
140    // return the first sample's subject
141    def getSubjectForEvent( event ) {
142        def samples =  Sample.getSamplesFor(event)
143        return samples[0].parentSubject
144    }
145
146
147
148
149    // helper function for save()
150    // parse params from the edit view
151    // and save all samples returned as a list
152    def parseParamsForNewSamples( params, event ) {
153
154        def subject = getSubjectForEvent( event )
155
156        def samples=[]
157            params.each{ k,v ->
158                 def pattern = /^(sampleName)([\d]+)/
159                 def matcher =  k=~pattern
160                 if(matcher) {
161                     def id = k.replaceAll(pattern,'$2')
162                     def sample = new Sample()
163                     sample.parentEvent = event
164                     sample.parentSubject = subject
165                     sample.name = v
166                     sample.material= Term.getTerm( params['sampleMaterial'+id] )
167                     saveSample(sample)
168                     samples.push(sample)
169                 }
170            }
171        return samples
172    }
173
174
175
176    // save a samle or handle errors
177    def saveSample(sample) {
178           if (sample.save(flush: true)) {
179                       flash.message = "${message(code: 'default.created.message', args: [message(code: 'event.label', default: 'Sample'), sample.id])}"
180            }
181            else {
182                    sample.errors.each{ println it }
183            }
184    }
185
186
187    // helper function for save()
188    // parse params from the edit view and save changes.
189    // Return all updated samples as a list
190    def parseParamsForOldSamples( params ) {
191        def samples=[]
192            params.each{ k,v ->
193                 def pattern = /^(sampleName_existing_)([\d]+)/
194                 def matcher =  k=~pattern
195                 if(matcher) {
196                     def id = k.replaceAll(pattern,'$2')
197                     def sample = Sample.get(id)
198                     sample.name = v
199                     sample.material= Term.getTerm( params['sampleMaterial_existing_'+id] )
200                     samples.push(sample)
201                     saveSample(sample)
202                 }
203            }
204        return samples
205    }
206
207
208    // helper function for save()
209    // delete a sample removed by the user
210    // Note: we completely delete this sample! It is also removed from the Study and the Assay!
211    def deleteSampelsRemovedByUser( originalSamples, remainingSamples) {
212
213        def toDelete = []
214        originalSamples.each { original ->
215            if( !remainingSamples.contains(original) ) 
216            { 
217                toDelete.push( original )
218            }
219        }
220
221        toDelete.each { 
222            Assay.list().each{ assay ->
223                if( assay.samples.contains((Sample)it) )
224                {
225                    assay.removeFromSamples(it)
226                }
227            }
228            Study.list().each{ study ->
229                if( study.samples.contains((Sample)it) )
230                {
231                    study.removeFromSamples(it)
232                }
233            }
234            ((Sample)it).delete()
235        }
236    }
237
238
239
240
241
242
243    def save = {
244
245        // create a new event from scratch
246
247        if( !(params['id']=~/^[\d]+$/) ) {
248
249            /* Not needed anymore: replace by template check?
250
251            def description = new EventDescription()
252            description.name = (params['name']==null || params['name'].replaceAll(/\S/,'').size()==0 ) ? '[no Name]' : params['name']
253            description.description = (params['description']==null || params['description'].replaceAll(/\w/,'').size()==0 ) ? '[no description]' : params['description']
254            description.protocol = Protocol.get( params['protocol'] )
255            description.isSamplingEvent = params['isSamplingEvent']=='on' ? true : false
256
257            if (description.save(flush: true)) {
258                flash.message = "${message(code: 'default.created.message', args: [message(code: 'description.label', default: 'Event'), description.id])}"
259            }
260            else {
261                description.errors.each{ println it }
262            }*/
263
264            def event = description.isSamplingEvent ? new SamplingEvent() : new Event();
265
266            event.startTime = new Date(params["startTime"])                   // parse the date strings
267            event.endTime = new Date(params["endTime"])                       // parse the date strings
268            event.parameterStringValues = new HashMap()
269            event.parameterFloatValues = new HashMap()
270            event.parameterIntegerValues = new HashMap()
271            event.parameterStringListValues = new HashMap()
272            event.eventDescription = description
273
274
275            if (event.save(flush:true, validate:false)) {
276                flash.message = "${message(code: 'default.created.message', args: [message(code: 'event.label', default: 'Event'), event.id])}"
277            }
278            else {
279                    event.errors.each{ println it }
280            }
281
282            // read params and add parameter values to event.
283            // (such as ParameterStringListValues, etc.
284            parseParamsForParameterValues( params, event )
285
286
287            if (event.save(flush: true)) {
288                flash.message = "${message(code: 'default.created.message', args: [message(code: 'event.label', default: 'Event'), event.id])}"
289            }
290            else {
291                    event.errors.each{ println it }
292            }
293
294
295        }
296
297
298        // modify an existing event
299
300        else { 
301
302            def event = Event.get(params['id'])
303
304            // save basic changes in event and event description
305
306            /* Not needed anymore: replace by template check?
307
308            def description = event.eventDescription
309            def oldProtocol = description.protocol
310
311            def name = params['name']
312            description.name = ( name==null || name.replaceAll(/\S/,'').size()==0 ) ? '[no Name]' : name
313            description.description = (params['description']==null || params['description'].replaceAll(/\w/,'').size()==0 ) ? '[no description]' : params['description']
314            description.isSamplingEvent = params['isSamplingEvent']=='on' ? true : false
315
316            */
317
318            event.startTime = new Date(params["startTime"])
319            event.endTime   = new Date(params["endTime"])
320
321
322            /* Not needed anymore: replace by template check?
323
324
325            // save changed parameters
326            description.protocol = Protocol.get( params['protocol'] )
327
328            // get the protocol
329            if(description.protocol!=oldProtocol)  {          // protocol changed
330
331                // remove all old parameter values
332
333                def removeAll = { values, memberName ->
334                    def list = values.getProperty(memberName)
335                }
336
337                removeAll(event, 'parameterStringValues' )
338                removeAll(event, 'parameterIntegerValues' )
339                removeAll(event, 'parameterFloatValues' )
340                removeAll(event, 'parameterStringListValues')
341
342
343                // add all new parameter values
344                parseParamsForParameterValues( params, event )
345
346
347            }
348
349            */
350
351
352            // update samples
353
354            if( event.isSamplingEvent() ) {
355
356                // remove deleted samples
357                // update existing samples
358
359                // add new samples
360
361                def originalSamples = Sample.getSamplesFor(event)               // samples that have been in this form before the edit
362
363                def newSamples = parseParamsForNewSamples( params, event )       //  get list of new samples as persistent sample objects
364                                                                                 //  also add all the samples to this event already
365                                                                                 //  by assigning event as parentEvent
366
367                def remainingSamples = parseParamsForOldSamples( params )        // samples, that have been in the form, and not deleted by the user
368                                                                                 // remainigSamples is subset of originalSamples
369
370                deleteSampelsRemovedByUser( originalSamples, remainingSamples)   // delete sample and remove it from parentSubject and the
371                                                                                 // associated study.
372
373            }
374
375            //((Event)event).eventDescription=description
376
377
378            if (event.save(flush: true)) {
379                 flash.message = "${message(code: 'default.created.message', args: [message(code: 'event.label', default: 'Event'), event.id])}"
380            }
381            else {
382                 event.errors.each{ println it }
383            }
384
385        }
386
387
388        render(action: "list", total:Event.count() )
389    }
390
391
392
393
394    def show = {
395        def eventInstance = Event.get(params.id)
396        if (!eventInstance) {
397            flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'event.label', default: 'Event'), params.id])}"
398            redirect(action: "list")
399        }
400        else {
401            [eventInstance: eventInstance]
402        }
403    }
404
405
406
407
408
409    def partial = {
410        println "In action: partial"
411        println params
412        def eventDescription = EventDescription.get(params.id)
413        if (!eventDescription) {
414            flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'event.label', default: 'Event'), params.id])}"
415            redirect(action: "list")
416        }
417        else {
418            [eventDescription: event]
419        }
420        redirect(view: 'partial')
421    }
422
423
424
425
426
427    // This action is not complete yet.
428    // (1) Need to include SamplingEvents.
429    // (2) This probably causes orphened PrtocolPrameters that have to be delt with.
430    //     The orphanes have to be managed centrally with the Protocols.
431    // (3) Parts of this might have to be moved into the Domain object's save() method.
432    // (4) The correspoding view's params are bloated and contain redundancy.
433    // (5) The whole thing should be moved to update.
434    // (6) A "create" should be added.
435
436    def edit = {
437
438        // create entirely new Event
439
440        if( params["id"]==null || params['id']=='' )
441        {
442            // New events cannot deal with Samples because there is not subject
443            // to assign samples to. Therefore, samples cannot be added to the a new
444            // Event, event if the user makes it a SamplingEvent by ticking a box.
445            // Therefore, showSample is set to false.
446
447            def eventInstance = new Event()
448            def sDate = new Date()
449            def eDate = new Date()
450            //def description = new EventDescription()
451            return [eventInstance:eventInstance, testo:params.clone(), sDate:sDate, eDate:eDate,
452                    //description:description,
453            showSample:false, samples:null, createNew:true ]
454        }
455
456
457        // edit an existing Event
458
459        else
460        {
461            def eventInstance = Event.get(params.id)
462            if (!eventInstance) {
463                flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'event.label', default: 'Event'), params.id])}"
464                redirect(action: "list")
465            }
466            def samples = []
467            def showSample = false
468            if(eventInstance.isSamplingEvent() ) {
469                samples = ((SamplingEvent) eventInstance).getSamples()
470                if( samples.size() > 0 ) { showSample = true }
471                // later, also check of eventInstance's study contains any subjects, if so, show them as list to chose from
472            }
473
474            return [eventInstance:eventInstance, testo:params.clone(), sDate:eventInstance.startTime, eDate:eventInstance.endTime,
475                    // description:eventInstance.eventDescription,
476            showSample:showSample, samples:samples, createNew:false ]
477        }
478
479    }
480
481
482    def create = {
483        redirect(action:"edit", id:'')
484    }
485
486
487
488
489    def update = {
490        def eventInstance = Event.get(params.id)
491        if (eventInstance) {
492            if (params.version) {
493                def version = params.version.toLong()
494                if (eventInstance.version > version) {
495                   
496                    eventInstance.errors.rejectValue("version", "default.optimistic.locking.failure", [message(code: 'event.label', default: 'Event')] as Object[], "Another user has updated this Event while you were editing")
497                    render(view: "edit", model: [eventInstance: eventInstance])
498                    return
499                }
500            }
501            eventInstance.properties = params
502            if (!eventInstance.hasErrors() && eventInstance.save(flush: true)) {
503                flash.message = "${message(code: 'default.updated.message', args: [message(code: 'event.label', default: 'Event'), eventInstance.id])}"
504                redirect(action: "show", id: eventInstance.id)
505            }
506            else {
507                render(view: "edit", model: [eventInstance: eventInstance])
508            }
509        }
510        else {
511            flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'event.label', default: 'Event'), params.id])}"
512            redirect(action: "list")
513        }
514    }
515
516
517    def delete = {
518        def eventInstance = Event.get(params.id)
519        if (eventInstance) {
520            try {
521                eventInstance.delete(flush: true)
522                flash.message = "${message(code: 'default.deleted.message', args: [message(code: 'event.label', default: 'Event'), params.id])}"
523                redirect(action: "list")
524            }
525            catch (org.springframework.dao.DataIntegrityViolationException e) {
526                flash.message = "${message(code: 'default.not.deleted.message', args: [message(code: 'event.label', default: 'Event'), params.id])}"
527                redirect(action: "show", id: params.id)
528            }
529        }
530        else {
531            flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'event.label', default: 'Event'), params.id])}"
532            redirect(action: "list")
533        }
534    }
535
536
537
538    def showSample = {
539
540          println params
541          println "\n\nin showSample"
542          params.each{ x -> println x}
543          def samples = null
544          def event = Event.get(params.id)
545          if(event!=null)
546          {
547          def wantSample = params['wantSample']
548                                              // user wants this Event to be a SamplingEvent?
549          if( wantSample==null  &&  event.isSamplingEvent() )
550          {
551                println "want sample is null"
552                wantSample = true
553          }     
554          else {  println "want sample is " + params['wantSample']
555                  wantSample = params.wantSample <=>'no'?true:false }
556
557
558
559          if( event.isSamplingEvent() ) {
560              samples = Sample.findAll("from Sample as s where s.parentEvent.id = ${event.id}" )
561              samples.each{ println it.class }
562              samples.collect{ it.name }
563              println "yes ${event.id}"
564          }
565          else    println "no ${event.id}"
566
567
568          render( view:"showSample", model:[samples:samples,wantSample:wantSample,id:event.id] )
569          }
570    }
571
572
573   def deleteSample = {
574          // saves the samples from the page, then repaint the samples
575          println "in deleteSample"
576          println params
577
578          def event = Event.get(params['id'])
579
580          redirect( action:showSample, samples:newSample, wantSample:true,id:params['id'] )
581   }
582
583
584   def showEventDescription = {
585         def event = Event.get( params['id'] )
586         def description = EventDescription.get( params['eventDescriptionId'] )
587         render( view:"showEventDescription", model:[description:description] )
588   }
589
590
591   def deleteAllSamples = {
592        println "in deleteSamples"
593        println params
594        def event = Event.get(params['id'])
595        event.samples.each{ 
596            event.removeFromSamples(it)
597            it.delete(flush:true)
598        }
599
600        redirect( action:showSample, id:params['id'] )
601   }
602
603
604
605   def combobox = {
606        def event = Event.get(1)
607        def parameters = event.parameterStringValues
608        render( view:"combobox", model:[event:event,parameters:parameters] )
609   }
610}
Note: See TracBrowser for help on using the repository browser.