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

Last change on this file since 349 was 288, checked in by jahn, 13 years ago

Event's create and edit action have been tested and are now working.

Also, the old problem of adding Samples has been addressed. When a new event is created as a SamplingEvent?, no new samples can be added directly. The reason for this is, that the event is not yet assigned to any Subject, and thus the non nullable subject field of a new sample (belonging to the new event) cannot be filled.
Similarly, when a SamplingEvent? event is edited, new samples can only be added, if the event already is assigned to belong to a subject. New samples are always added to the same subject as the first (random) sample belonging to the SamplingEvent?.

However, there are still open questions:

(1) Should the sample also be assigned to the samples of its subject's Study?

(2) Should a sample also be assigned, if there are no samples assigned yet, but there is a subject assigned to this event?

(3) Should the user be allowed to chose to assign a subject if the event is assigned to a Study that contains multiple subjects?

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