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

Last change on this file since 411 was 397, checked in by duh, 9 years ago
  • reformatted source code
  • added mega huge big ASCII comments to UNDOCUMMENTED of not properly DOCUMENTED classess... we have agreed many many MANY times that everyone should document their code according to JavaDoc? style... but why does nobody do it, or just keep SLACKING! /annoyed modus
  • Property svn:keywords set to Date Author 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.