Changeset 1608 for trunk/grails-app
- Timestamp:
- Mar 9, 2011, 3:56:26 PM (10 years ago)
- Location:
- trunk/grails-app
- Files:
-
- 11 added
- 11 deleted
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/grails-app/controllers/dbnp/studycapturing/SimpleWizardController.groovy
r1591 r1608 15 15 package dbnp.studycapturing 16 16 17 import org.apache.poi.ss.usermodel.DataFormatter 17 18 import org.dbnp.gdt.* 18 19 import grails.plugins.springsecurity.Secured … … 27 28 def fileService 28 29 def importerService 29 def gdtService 30 def gdtService = new GdtService() 30 31 31 32 /** … … 33 34 */ 34 35 def index = { 35 redirect( action: "study" ); 36 if( params.id ) 37 redirect( action: "simpleWizard", id: params.id ); 38 else 39 redirect( action: "simpleWizard" ); 36 40 } 37 41 38 /** 39 * Shows the study page 40 */ 41 def study = { 42 // Retrieve the correct study 43 Study study = getStudyInWizard( params ); 44 45 // If no study is found in the wizard, this is the entry page of the 46 // wizard. Retrieve the study from request parameters 47 if( !study ) { 48 study = getStudyFromRequest( params ); 49 50 // Some error might have occurred during the retrieval of the study 51 if( !study ) { 52 redirect( controller: 'simpleWizard', action: 'study' ); 53 return; 54 } 55 56 session.simpleWizard = [ study: study ] 57 } 58 59 def event = getEvent(params); 60 61 // If any event on this page is triggered, we should save the entered data. 62 // If no event is triggered, the user gets here from another page. In that case, 63 // we don't set the values 64 if( event ) { 65 // Only continue to the next or previous page if the information entered is correct 66 if( handleStudy( study, params ) ) { 67 // Now determine what action to perform 68 // If the user clicks next, the study should be validated 69 if( event == "next" && validateObject( study ) ) { 70 if( study.samples?.size() ) { 71 // This wizard can only handle simple studies. If the 72 // study is too complex, this wizard doesn't provide the 73 // possibility to edit samples/subjects etc. 74 if( checkStudySimplicity( study ) ) { 75 toPage( "existingSamples" ); 76 } else { 77 toPage( "complexStudy" ); 78 } 79 } else { 80 toPage( "samples" ); 81 } 82 83 return; 84 } 85 } 86 } 87 88 // Give the study to the user 89 [ study: study ] 90 } 91 92 /** 93 * Shows a page to mention that the study being edited is too complex 94 */ 95 def complexStudy = { 96 // Retrieve the correct study 97 study = getStudyInWizard( params ); 98 if( !study ) { 99 redirect( controller: 'simpleWizard', action: 'study' ); 100 return; 101 } 102 103 def event = getEvent(params); 104 105 // If any event on this page is triggered 106 if( event ) { 107 // Now determine what action to perform 108 if( event == "save" ) { 109 toPage( "save" ); 110 return; 111 } else if( event == "previous" ) { 112 toPage( "study" ); 113 return; 114 } 115 } 116 117 // Give the study and other data to the user 118 [ study: study ] 119 } 120 121 /** 122 * Shows the samples page 123 */ 124 def existingSamples = { 125 // Retrieve the correct study 126 study = getStudyInWizard( params ); 127 if( !study ) { 128 redirect( controller: 'simpleWizard', action: 'study' ); 129 return; 130 } 131 132 def event = getEvent(params); 133 134 // If any event on this page is triggered, we should save the entered data. 135 // If no event is triggered, the user gets here from another page. In that case, 136 // we don't set the values 137 if( event ) { 138 // Now determine what action to perform 139 if( event == "next" && handleExistingSamples( study, params )) { 42 def simpleWizardFlow = { 43 entry { 44 action{ 45 flow.study = getStudyFromRequest( params ) 46 if (!flow.study) retrievalError() 47 } 48 on("retrievalError").to "handleError" 49 on("success").to "study" 50 } 51 52 study { 53 on("next") { 54 handleStudy( flow.study, params ) 55 if( !validateObject( flow.study ) ) 56 error() 57 }.to "decisionState" 58 on("refresh") { handleStudy( flow.study, params ); }.to "study" 59 on( "success" ) { handleStudy( flow.study, params ) }.to "study" 60 } 61 62 decisionState { 63 action { 64 // Create data in the flow 65 flow.templates = [ 66 'Sample': Template.findAllByEntity( Sample.class ), 67 'Subject': Template.findAllByEntity( Subject.class ), 68 'Event': Template.findAllByEntity( Event.class ), 69 'SamplingEvent': Template.findAllByEntity( SamplingEvent.class ) 70 ]; 71 flow.encodedEntity = [ 72 'Sample': gdtService.encryptEntity( Sample.class.name ), 73 'Subject': gdtService.encryptEntity( Subject.class.name ), 74 'Event': gdtService.encryptEntity( Event.class.name ), 75 'SamplingEvent': gdtService.encryptEntity( SamplingEvent.class.name ) 76 ] 77 78 if (flow.study.samples) 79 checkStudySimplicity(flow.study) ? existingSamples() : complexStudy() 80 else 81 samples() 82 } 83 on ("existingSamples").to "startExistingSamples" 84 on ("complexStudy").to "complexStudy" 85 on ("samples").to "samples" 86 } 87 88 startExistingSamples { 89 action { 90 def records = importerService.getRecords( flow.study ); 91 flow.records = records 92 flow.templateCombinations = records.templateCombination.unique() 93 success(); 94 } 95 on( "success" ).to "existingSamples" 96 } 97 98 existingSamples { 99 on("next") { 100 handleExistingSamples( flow.study, params, flow ) ? success() : error() 101 }.to "startAssays" 102 on("previous").to "study" 103 on("update") { 104 handleExistingSamples( flow.study, params, flow ) ? success() : error() 105 }.to "samples" 106 107 on("skip").to "startAssays" 108 } 109 110 complexStudy { 111 on("save").to "save" 112 on("previous").to "study" 113 } 114 115 samples { 116 on("next") { 117 handleSamples( flow.study, params, flow ) ? success() : error () 118 119 // Add domain fields for all entities 120 flow.domainFields = [:] 121 122 flow.templates.each { 123 if( it.value ) { 124 flow.domainFields[ it.key ] = it.value[0].entity.giveDomainFields(); 125 } 126 } 127 128 }.to "columns" 129 on("previous").to "returnFromSamples" 130 on("study").to "study" 131 on("skip").to "startAssays" 132 } 133 134 returnFromSamples { 135 action { 136 flow.study.samples ? existingSamples() : study(); 137 } 138 on( "existingSamples" ).to "startExistingSamples" 139 on( "study" ).to "study" 140 } 141 142 columns { 143 on( "next" ) { 144 handleColumns( flow.study, params, flow ) ? success() : error() 145 }.to "checkImportedEntities" 146 on( "previous" ).to "samples" 147 } 148 149 checkImportedEntities { 150 action { 140 151 // Only continue to the next page if the information entered is correct 141 toPage( "assays" ); 142 return; 143 } else if( event == "previous" ) { 144 // The user may go to the previous page, even if none of the data entered is OK. 145 toPage( "study" ); 146 return; 147 } else if( event == "update" && handleExistingSamples( study, params ) ) { 148 // The user may update the samples using excel. Before that, the sample date should be saved 149 toPage( "samples" ); 150 return; 151 } else if( event == "skip" ) { 152 // The user may skip the complete samples page 153 toPage( "assays" ); 154 return; 155 } 156 } 157 158 // Give the study and other data to the user 159 def records = importerService.getRecords( study ); 160 161 [ study: study, 162 records: records, 163 templateCombinations: records.templateCombination.unique(), 164 templates: [ 165 'Sample': Template.findAllByEntity( Sample.class ), 166 'Subject': Template.findAllByEntity( Subject.class ), 167 'Event': Template.findAllByEntity( Event.class ), 168 'SamplingEvent': Template.findAllByEntity( SamplingEvent.class ) 169 ], 170 encodedEntity: [ 171 'Sample': gdtService.encryptEntity( Sample.class.name ), 172 'Subject': gdtService.encryptEntity( Subject.class.name ), 173 'Event': gdtService.encryptEntity( Event.class.name ), 174 'SamplingEvent': gdtService.encryptEntity( SamplingEvent.class.name ) 175 ], 176 existingSampleForm: session.simpleWizard.existingSampleForm 177 ] 178 } 179 180 /** 181 * Shows the samples page 182 */ 183 def samples = { 184 // Retrieve the correct study 185 study = getStudyInWizard( params ); 186 if( !study ) { 187 redirect( controller: 'simpleWizard', action: 'study' ); 188 return; 189 } 190 191 def event = getEvent(params); 192 193 // If any event on this page is triggered, we should save the entered data. 194 // If no event is triggered, the user gets here from another page. In that case, 195 // we don't set the values 196 if( event ) { 197 // Now determine what action to perform 198 if( event == "next" && handleSamples( study, params )) { 199 // Only continue to the next page if the information entered is correct 200 toPage( "columns" ); 201 return; 202 } else if( event == "previous" ) { 203 // The user may go to the previous page, even if none of the data entered is OK. 204 if( study.samples?.size() ) 205 toPage( "existingSamples" ); 206 else 207 toPage( "study" ); 208 209 return; 210 } else if( event == "skip" ) { 211 // The user may skip the complete samples page 212 toPage( "assays" ); 213 return; 214 } 215 } 216 217 // Give the study and other data to the user 218 [ study: study, 219 templates: [ 220 'Sample': Template.findAllByEntity( Sample.class ), 221 'Subject': Template.findAllByEntity( Subject.class ), 222 'Event': Template.findAllByEntity( Event.class ), 223 'SamplingEvent': Template.findAllByEntity( SamplingEvent.class ) 224 ], 225 encodedEntity: [ 226 'Sample': gdtService.encryptEntity( Sample.class.name ), 227 'Subject': gdtService.encryptEntity( Subject.class.name ), 228 'Event': gdtService.encryptEntity( Event.class.name ), 229 'SamplingEvent': gdtService.encryptEntity( SamplingEvent.class.name ) 230 ], 231 sampleForm: session.simpleWizard.sampleForm ] 232 } 233 234 /** 235 * Shows the columns page 236 */ 237 def columns = { 238 // Retrieve the correct study 239 study = getStudyInWizard( params ); 240 if( !study ) { 241 redirect( controller: 'simpleWizard', action: 'study' ); 242 return; 243 } 244 245 def event = getEvent(params); 246 247 // If any event on this page is triggered, we should save the entered data. 248 // If no event is triggered, the user gets here from another page. In that case, 249 // we don't set the values 250 if( event ) { 251 // Now determine what action to perform 252 if( event == "next" && handleColumns( study, params ) ) { 253 254 // Only continue to the next page if the information entered is correct 255 if( session.simpleWizard.imported.numInvalidEntities > 0 ) { 256 toPage( "missingFields" ); 152 if( flow.imported.numInvalidEntities > 0 ) { 153 missingFields(); 257 154 } else { 258 155 // The import of the excel file has finished. Now delete the excelfile 259 if( session.simpleWizard.sampleForm.importFile ) 260 fileService.delete( session.simpleWizard.sampleForm.importFile ); 261 262 session.simpleWizard.sampleForm = null 263 264 toPage( "assays" ); 265 } 266 return; 267 } else if( event == "previous" ) { 268 // The user may go to the previous page, even if the data is not correct 269 toPage( "samples" ); 270 return; 271 } 272 } 273 274 def templates = [:]; 275 def domainFields = [:] 276 277 session.simpleWizard.sampleForm.templateId.each { 278 templates[ it.key ] = it.value ? Template.get( it.value ) : null; 279 if( it.value ) { 280 domainFields[ it.key ] = templates[ it.key ].entity.giveDomainFields(); 281 } 282 } 283 284 // Give the study and other data to the user 285 [ study: study, 286 filename: session.simpleWizard.sampleForm.importFile, 287 templates: templates, 288 domainFields: domainFields, 289 excel: session.simpleWizard.excel] 156 if( flow.excel.filename ) 157 fileService.delete( flow.excel.filename ); 158 159 flow.sampleForm = null 160 161 assays(); 162 } 163 } 164 on( "missingFields" ).to "missingFields" 165 on( "assays" ).to "startAssays" 166 } 167 168 missingFields { 169 on( "next" ) { 170 if( !handleMissingFields( flow.study, params, flow ) ) { 171 return error(); 172 } 173 174 // The import of the excel file has finished. Now delete the excelfile 175 if( flow.excel.filename ) 176 fileService.delete( flow.excel.filename ); 177 178 flow.sampleForm = null 179 180 success(); 181 }.to "startAssays" 182 on( "previous" ) { 183 // The user goes back to the previous page, so the already imported entities 184 // (of which some gave an error) should be removed again. 185 // Add all samples 186 flow.imported.data.each { record -> 187 record.each { entity -> 188 if( entity ) { 189 switch( entity.class ) { 190 case Sample: flow.study.removeFromSamples( entity ); break; 191 case Subject: flow.study.removeFromSubjects( entity ); break; 192 case Event: flow.study.removeFromEvents( entity ); break; 193 case SamplingEvent: flow.study.removeFromSamplingEvents( entity ); break; 194 } 195 } 196 } 197 } 198 199 success(); 200 }.to "columns" 201 } 202 203 startAssays { 204 action { 205 if( !flow.assay ) 206 flow.assay = new Assay( parent: flow.study ); 207 208 success(); 209 } 210 on( "success" ).to "assays" 211 } 212 213 assays { 214 on( "next" ) { 215 handleAssays( flow.assay, params, flow ); 216 if( !validateObject( flow.assay ) ) 217 error(); 218 }.to "overview" 219 on( "skip" ) { 220 // In case the user has created an assay before he clicked 'skip', it should only be kept if it 221 // existed before this step 222 if( flow.assay != null && !flow.assay.id ) { 223 flow.remove( "assay" ) 224 } 225 226 }.to "overview" 227 on( "previous" ).to "returnFromAssays" 228 on("refresh") { handleAssays( flow.assay, params, flow ); success() }.to "assays" 229 } 230 231 returnFromAssays { 232 action { 233 flow.study.samples ? existingSamples() : samples(); 234 } 235 on( "existingSamples" ).to "existingSamples" 236 on( "samples" ).to "samples" 237 } 238 239 overview { 240 on( "save" ).to "saveStudy" 241 on( "previous" ).to "startAssays" 242 } 243 244 saveStudy { 245 action { 246 if( flow.assay && !flow.study.assays?.contains( flow.assay ) ) { 247 flow.study.addToAssays( flow.assay ); 248 } 249 250 if( flow.study.save( flush: true ) ) { 251 // Make sure all samples are attached to all assays 252 flow.study.assays.each { assay -> 253 def l = []+ assay.samples; 254 l.each { sample -> 255 if( sample ) 256 assay.removeFromSamples( sample ); 257 } 258 assay.samples?.clear(); 259 260 flow.study.samples.each { sample -> 261 assay.addToSamples( sample ) 262 } 263 } 264 265 flash.message = "Your study is succesfully saved."; 266 267 finish(); 268 } else { 269 flash.error = "An error occurred while saving your study: <br />" 270 flow.study.getErrors().each { flash.error += it.toString() + "<br />"} 271 272 // Remove the assay from the study again, since it is still available 273 // in the session 274 if( flow.assay ) { 275 flow.study.removeFromAssays( flow.assay ); 276 flow.assay.parent = flow.study; 277 } 278 279 overview(); 280 } 281 } 282 on( "finish" ).to "finish" 283 on( "overview" ).to "overview" 284 } 285 286 finish() 287 288 handleError{ 289 redirect action: "errorPage" 290 } 290 291 } 291 292 292 293 /** 293 * Shows the page where missing fields can be filled in 294 * Retrieves the required study from the database or return an empty Study object if 295 * no id is given 296 * 297 * @param params Request parameters with params.id being the ID of the study to be retrieved 298 * @return A study from the database or an empty study if no id was given 294 299 */ 295 def missingFields = { 296 // Retrieve the correct study 297 study = getStudyInWizard( params ); 298 if( !study ) { 299 redirect( controller: 'simpleWizard', action: 'study' ); 300 return; 301 } 302 303 def event = getEvent(params); 304 305 // If any event on this page is triggered, we should save the entered data. 306 // If no event is triggered, the user gets here from another page. In that case, 307 // we don't set the values 308 if( event ) { 309 // Now determine what action to perform 310 if( event == "next" && handleMissingFields( study, params ) ) { 311 if( session.simpleWizard.imported.numInvalidEntities == 0 ) { 312 // Only continue to the next page if the information entered is correct 313 314 // The import of the excel file has finished. Now delete the excelfile 315 if( session.simpleWizard.sampleForm.importFile ) { 316 fileService.delete( session.simpleWizard.sampleForm.importFile ); 317 } 318 session.simpleWizard.sampleForm = null 319 320 toPage( "assays" ); 321 return; 322 } 323 } else if( event == "previous" ) { 324 // THe user may go to the previous page, even if the data is not correct 325 toPage( "columns" ); 326 return; 327 } 328 } 329 330 // If any errors have occurred during validation, show them to the user. However, 331 // the same error might have occurred for multiple entities. For that reason, 332 // we only show unique errors 333 def rules 334 if( session.simpleWizard.imported.errors ) { 335 rules = session.simpleWizard.imported.errors*.values().flatten().unique().join( "<br /> \n" ); 336 } 337 338 // Create the right format for showing the data 339 def records = []; 340 session.simpleWizard.imported.data.each { row -> 341 def record = [:]; 342 row.each { object -> 343 // Attach template to session 344 if( object.template ) 345 attachTemplate( object.template ); 346 347 def entityName = object.class.name[ object.class.name.lastIndexOf( '.' ) + 1 .. -1 ] 348 record[ entityName ] = object; 349 } 350 records << record; 351 } 352 353 // Give the study and other data to the user 354 println "Imported: " + session.simpleWizard.imported.failedCells; 355 356 [ study: study, imported: session.simpleWizard.imported, records: records, rules: rules ] 300 protected Study getStudyFromRequest( def params ) { 301 int id = params.int( "id" ); 302 303 if( !id ) { 304 return new Study( title: "New study", owner: authenticationService.getLoggedInUser() ); 305 } 306 307 Study s = Study.get( id ); 308 309 if( !s ) { 310 flash.error = "No study found with given id"; 311 return null; 312 } 313 if( !s.canWrite( authenticationService.getLoggedInUser() ) ) { 314 flash.error = "No authorization to edit this study." 315 return null; 316 } 317 318 return s 357 319 } 358 320 359 321 /** 360 * Shows the assay page361 */362 def assays = {363 // Retrieve the correct study364 Study study = getStudyInWizard( params );365 if( !study ) {366 redirect( controller: 'simpleWizard', action: 'study' );367 return;368 }369 370 Assay assay = getAssayInWizard( study );371 372 def event = getEvent(params);373 374 // If any event on this page is triggered, we should save the entered data.375 // If no event is triggered, the user gets here from another page. In that case,376 // we don't set the values377 if( event ) {378 // Only continue to the next or previous page if the information entered is correct379 if( event == "skip" ) {380 // The user may skip the complete assay page381 382 // In case the user has created an assay before, it should only be kept if it383 // existed before this step384 if( session.simpleWizard.assay != null && !session.simpleWizard.assay.id ) {385 session.simpleWizard.remove( "assay" )386 }387 388 toPage( "overview" );389 return;390 } else if( handleAssays( assay, params ) ) {391 // Now determine what action to perform392 if( event == "next" && validateObject( assay ) ) {393 toPage( "overview" );394 return;395 } else if( event == "previous" ) {396 if( study.samples?.size() )397 toPage( "existingSamples" )398 else399 toPage( "samples" );400 401 return;402 }403 }404 }405 406 // Give the study to the user407 [ study: study, wizardAssay: assay ]408 }409 410 /**411 * Shows an overview of the entered study412 */413 def overview = {414 // Retrieve the correct study415 Study study = getStudyInWizard( params );416 if( !study ) {417 redirect( controller: 'simpleWizard', action: 'study' );418 return;419 }420 421 Assay assay = getAssayInWizard();422 423 def event = getEvent(params);424 425 // If any event on this page is triggered, we should save the entered data.426 // If no event is triggered, the user gets here from another page. In that case,427 // we don't set the values428 if( event ) {429 // Now determine what action to perform430 if( event == "save" ) {431 toPage( "save" );432 return;433 } else if( event == "previous" ) {434 toPage( "assays" )435 return;436 }437 }438 439 // Give the study to the user440 [ study: study, wizardAssay: assay ]441 }442 443 def save = {444 // Retrieve the correct study445 Study study = getStudyInWizard( params );446 if( !study ) {447 redirect( controller: 'simpleWizard', action: 'study' );448 return;449 }450 451 def event = getEvent(params);452 453 if( event && event == "previous" ) {454 toPage( "assays" );455 return;456 }457 458 Assay newAssay = getAssayInWizard();459 460 if( newAssay && !study.assays?.contains( newAssay ) ) {461 study.addToAssays( newAssay );462 }463 464 //attachAndValidateEntities( study );465 466 // Save the study. The study must be merged if it is loaded from467 // the database before, since otherwise it will raise 'lazy initialization' errors468 // The validation is done in the other steps, so it is skipped here.469 def success470 471 if(472 study.id ?473 study.merge( validate: false, flush: true ) :474 study.save( flush: true )475 ) {476 // Make sure all samples are attached to all assays477 study.assays.each { assay ->478 def l = []+ assay.samples;479 l.each { sample ->480 if( sample )481 assay.removeFromSamples( sample );482 }483 assay.samples?.clear();484 485 study.samples.each { sample ->486 assay.addToSamples( sample )487 }488 }489 490 // Clear session491 session.simpleWizard = null;492 493 flash.message = "Your study is succesfully saved.";494 success = true495 } else {496 flash.error = "An error occurred while saving your study";497 498 study.getErrors().each { println it }499 500 // Remove the assay from the study again, since it is still available501 // in the session502 if( newAssay ) {503 study.removeFromAssays( newAssay );504 newAssay.parent = study;505 }506 507 //validateObject( study );508 success = false509 }510 511 // Give the study to the user512 [ study: study, success: success ]513 }514 515 /**516 322 * Handles study input 517 323 * @param study Study to update … … 552 358 return true 553 359 } 554 555 /** 556 * Handles the editing of existing samples 557 * @param study Study to update 558 * @param params Request parameter map 559 * @return True if everything went OK, false otherwise. An error message is put in flash.error 560 */ 561 def handleExistingSamples( study, params ) { 562 session.simpleWizard.existingSampleForm = params 563 flash.validationErrors = [:]; 564 565 def errors = false; 566 567 // iterate through objects; set field values and validate the object 568 def eventgroups = study.samples.parentEventGroup.findAll { it } 569 def events; 570 if( !eventgroups ) 571 events = [] 572 else 573 events = eventgroups.events?.getAt(0); 574 575 def objects = [ 576 'Sample': study.samples, 577 'Subject': study.samples.parentSubject.findAll { it }, 578 'SamplingEvent': study.samples.parentEvent.findAll { it }, 579 'Event': events.flatten().findAll { it } 580 ]; 581 objects.each { 582 def type = it.key; 583 def entities = it.value; 584 585 entities.each { entity -> 586 // iterate through entity fields 587 entity.giveFields().each() { field -> 588 def value = params.get( type.toLowerCase() + '_' + entity.getIdentifier() + '_' + field.escapedName()) 589 590 // set field value; name cannot be set to an empty value 591 if (field.name != 'name' || value) { 592 log.info "setting "+field.name+" to "+value 593 entity.setFieldValue(field.name, value) 594 } 595 } 596 597 // has the template changed? 598 def templateName = params.get(type.toLowerCase() + '_' + entity.getIdentifier() + '_template') 599 if (templateName && entity.template?.name != templateName) { 600 entity.template = Template.findByName(templateName) 601 } 602 603 // validate sample 604 if (!entity.validate()) { 605 errors = true; 606 flash.validationErrors << getHumanReadableErrors( entity ) 607 } 608 } 609 } 610 611 return !errors 612 } 360 361 /** 362 * Handles the editing of existing samples 363 * @param study Study to update 364 * @param params Request parameter map 365 * @return True if everything went OK, false otherwise. An error message is put in flash.error 366 */ 367 def handleExistingSamples( study, params, flow ) { 368 flash.validationErrors = []; 369 370 def errors = false; 371 372 // iterate through objects; set field values and validate the object 373 def eventgroups = study.samples.parentEventGroup.findAll { it } 374 def events; 375 if( !eventgroups ) 376 events = [] 377 else 378 events = eventgroups.events?.getAt(0); 379 380 def objects = [ 381 'Sample': study.samples, 382 'Subject': study.samples.parentSubject.findAll { it }, 383 'SamplingEvent': study.samples.parentEvent.findAll { it }, 384 'Event': events.flatten().findAll { it } 385 ]; 386 objects.each { 387 def type = it.key; 388 def entities = it.value; 389 390 entities.each { entity -> 391 // iterate through entity fields 392 entity.giveFields().each() { field -> 393 def value = params.get( type.toLowerCase() + '_' + entity.getIdentifier() + '_' + field.escapedName()) 394 395 // set field value; name cannot be set to an empty value 396 if (field.name != 'name' || value) { 397 log.info "setting "+field.name+" to "+value 398 entity.setFieldValue(field.name, value) 399 } 400 } 401 402 // has the template changed? 403 def templateName = params.get(type.toLowerCase() + '_' + entity.getIdentifier() + '_template') 404 if (templateName && entity.template?.name != templateName) { 405 entity.template = Template.findByName(templateName) 406 } 407 408 // validate sample 409 if (!entity.validate()) { 410 errors = true; 411 412 def entityName = entity.class.name[ entity.class.name.lastIndexOf( "." ) + 1 .. -1 ] 413 getHumanReadableErrors( entity ).each { 414 flash.validationErrors << [ key: it.key, value: "(" + entityName + ") " + it.value ]; 415 } 416 } 417 } 418 } 419 420 return !errors 421 } 613 422 614 423 /** … … 618 427 * @return True if everything went OK, false otherwise. An error message is put in flash.error 619 428 */ 620 def handleSamples( study, params ) {429 def handleSamples( study, params, flow ) { 621 430 def filename = params.get( 'importfile' ); 622 431 … … 629 438 else if( filename[0..8] == 'existing*' ) 630 439 filename = filename[9..-1] 631 440 632 441 def sampleTemplateId = params.long( 'sample_template_id' ) 633 442 def subjectTemplateId = params.long( 'subject_template_id' ) 634 443 def eventTemplateId = params.long( 'event_template_id' ) 635 444 def samplingEventTemplateId = params.long( 'samplingEvent_template_id' ) 636 445 637 446 // These fields have been removed from the form, so will always contain 638 447 // their default value. The code however remains like this for future use. … … 642 451 643 452 // Save form data in session 644 session.simpleWizard.sampleForm = [453 flow.sampleForm = [ 645 454 importFile: filename, 646 templateId: [ 455 templateId: [ 647 456 'Sample': sampleTemplateId, 648 457 'Subject': subjectTemplateId, … … 650 459 'SampingEvent': samplingEventTemplateId 651 460 ], 461 template: [ 462 'Sample': sampleTemplateId ? Template.get( sampleTemplateId ) : null, 463 'Subject': subjectTemplateId ? Template.get( subjectTemplateId ) : null, 464 'Event': eventTemplateId ? Template.get( eventTemplateId ) : null, 465 'SampingEvent': samplingEventTemplateId ? Template.get( samplingEventTemplateId ) : null 466 ], 652 467 sheetIndex: sheetIndex, 653 468 dataMatrixStart: dataMatrixStart, … … 661 476 return false 662 477 } 663 478 664 479 def importedfile = fileService.get( filename ) 665 480 def workbook … … 693 508 def importerDataMatrix; 694 509 695 try { 510 try { 696 511 importerHeader = importerService.getHeader(workbook, 697 512 sheetIndex - 1, // 0 == first sheet … … 699 514 dataMatrixStart - 1, // 0 == first row 700 515 Sample.class) 701 516 702 517 importerDataMatrix = importerService.getDatamatrix( 703 518 workbook, … … 716 531 } 717 532 533 // Match excel columns with template fields 534 def fieldNames = []; 535 flow.sampleForm.template.each { template -> 536 if( template.value ) { 537 def fields = template.value.entity.giveDomainFields() + template.value.getFields(); 538 fields.each { field -> 539 if( !field.entity ) 540 field.entity = template.value.entity 541 542 fieldNames << field 543 } 544 } 545 } 546 importerHeader.each { mc -> 547 def bestfit = importerService.mostSimilar( mc.name, fieldNames, 0.8); 548 if( bestfit ) { 549 // Remove this fit from the list 550 fieldNames.remove( bestfit ); 551 552 mc.entityclass = bestfit.entity 553 mc.property = bestfit.name 554 } 555 } 556 718 557 // Save read excel data into session 719 session.simpleWizard.excel = [ 720 workbook: workbook, 558 def dataMatrix = []; 559 def df = new DataFormatter(); 560 importerDataMatrix.each { 561 dataMatrix << it.collect{ it ? df.formatCellValue(it) : "" } 562 } 563 564 flow.excel = [ 565 filename: filename, 721 566 sheetIndex: sheetIndex, 722 567 dataMatrixStart: dataMatrixStart, … … 724 569 data: [ 725 570 header: importerHeader, 726 dataMatrix: importerDataMatrix571 dataMatrix: dataMatrix 727 572 ] 728 573 ] … … 731 576 } 732 577 578 733 579 /** 734 580 * Handles the matching of template fields with excel columns by the user … … 736 582 * @param params Request parameter map 737 583 * @return True if everything went OK, false otherwise. An error message is put in flash.error 738 * The field session.simpleWizard.imported.numInvalidEntities reflects the number of 584 * The field session.simpleWizard.imported.numInvalidEntities reflects the number of 739 585 * entities that have errors, and should be fixed before saving. The errors for those entities 740 586 * are saved into session.simpleWizard.imported.errors 741 587 */ 742 def handleColumns( study, params ) {588 def handleColumns( study, params, flow ) { 743 589 // Find actual Template object from the chosen template name 744 590 def templates = [:]; 745 session.simpleWizard.sampleForm.templateId.each {591 flow.sampleForm.templateId.each { 746 592 templates[ it.key ] = it.value ? Template.get( it.value ) : null; 747 593 } 748 594 749 def headers = session.simpleWizard.excel.data.header;595 def headers = flow.excel.data.header; 750 596 751 597 if( !params.matches ) { … … 796 642 println "Importing samples for study " + study + " (" + study.id + ")"; 797 643 644 def importedfile = fileService.get( flow.excel.filename ) 645 def workbook 646 if (importedfile.exists()) { 647 try { 648 workbook = importerService.getWorkbook(new FileInputStream(importedfile)) 649 } catch (Exception e) { 650 log.error ".simple study wizard could not load file: " + e 651 flash.error = "The given file doesn't seem to be an excel file. Please provide an excel file for entering samples."; 652 return false 653 } 654 } else { 655 log.error ".simple study wizard no file given"; 656 flash.error = "No file was given. Please provide an excel file for entering samples."; 657 return false; 658 } 659 660 if( !workbook ) { 661 log.error ".simple study wizard could not load file into a workbook" 662 flash.error = "The given file doesn't seem to be an excel file. Please provide an excel file for entering samples."; 663 return false 664 } 665 666 798 667 def imported = importerService.importOrUpdateDataBySampleIdentifier(templates, 799 session.simpleWizard.excel.workbook,800 session.simpleWizard.excel.sheetIndex - 1,801 session.simpleWizard.excel.dataMatrixStart - 1,802 session.simpleWizard.excel.data.header,803 study,804 true // Also create entities for which no data is imported but where templates were chosen 668 workbook, 669 flow.excel.sheetIndex - 1, 670 flow.excel.dataMatrixStart - 1, 671 flow.excel.data.header, 672 flow.study, 673 true // Also create entities for which no data is imported but where templates were chosen 805 674 ); 806 675 … … 808 677 def failedcells = imported.failedCells 809 678 810 session.simpleWizard.imported = [679 flow.imported = [ 811 680 data: table, 812 681 failedCells: failedcells 813 682 ]; 814 683 815 684 // loop through all entities to validate them and add them to failedcells if an error occurs 816 685 def numInvalidEntities = 0; … … 821 690 record.each { entity -> 822 691 if( entity ) { 823 // Determine entity class and add a parent 692 // Determine entity class and add a parent. Add the entity to the study 824 693 def preferredIdentifier = importerService.givePreferredIdentifier( entity.class ); 825 694 def equalClosure = { it.getFieldValue( preferredIdentifier.name ) == entity.getFieldValue( preferredIdentifier.name ) } 826 695 def entityName = entity.class.name[ entity.class.name.lastIndexOf( "." ) + 1 .. -1 ] 696 827 697 entity.parent = study 828 698 … … 854 724 855 725 // Add this field to the list of failed cells, in order to give the user feedback 856 failedcells = addNonValidatingCells( failedcells, entity )726 failedcells = addNonValidatingCells( failedcells, entity, flow ) 857 727 858 728 // Also create a full list of errors 859 errors += getHumanReadableErrors( entity ); 860 } 861 } 862 } 863 } 864 865 session.simpleWizard.imported.numInvalidEntities = numInvalidEntities + failedcells?.size(); 866 session.simpleWizard.imported.errors = errors; 729 def currentErrors = getHumanReadableErrors( entity ) 730 if( currentErrors ) { 731 currentErrors.each { 732 errors += "(" + entityName + ") " + it.value; 733 } 734 } 735 } 736 } 737 } 738 } 739 740 flow.imported.numInvalidEntities = numInvalidEntities + failedcells?.size(); 741 flow.imported.errors = errors; 867 742 868 743 return true 869 744 } 870 745 871 746 /** 872 747 * Handles the update of the edited fields by the user … … 878 753 * are saved into session.simpleWizard.imported.errors 879 754 */ 880 def handleMissingFields( study, params ) {755 def handleMissingFields( study, params, flow ) { 881 756 def numInvalidEntities = 0; 882 757 def errors = []; 883 758 884 759 // Check which fields failed previously 885 def failedCells = session.simpleWizard.imported.failedCells 886 887 session.simpleWizard.imported.data.each { table -> 760 def failedCells = flow.imported.failedCells 761 def newFailedCells = []; 762 763 flow.imported.data.each { table -> 888 764 table.each { entity -> 889 765 def invalidFields = 0 766 def failed = new ImportRecord(); 767 def entityName = entity.class.name[ entity.class.name.lastIndexOf( "." ) + 1 .. -1 ] 768 890 769 891 770 // Set the fields for this entity by retrieving values from the params … … 896 775 // If the value '#invalidterm' is chosen, the user hasn't fixed anything, so this field is still incorrect 897 776 invalidFields++; 777 778 // store the mapping column and value which failed 779 def identifier = entityName.toLowerCase() + "_" + entity.getIdentifier() + "_" + fieldName 780 def mcInstance = new MappingColumn() 781 failed.addToImportcells(new ImportCell(mappingcolumn: mcInstance, value: params[ fieldName ], entityidentifier: identifier)) 898 782 } else { 899 783 if( field.type == org.dbnp.gdt.TemplateFieldType.ONTOLOGYTERM || field.type == org.dbnp.gdt.TemplateFieldType.STRINGLIST ) { … … 907 791 } 908 792 } 909 910 // Determine entity class and add a parent 911 entity.parent = study; 912 793 913 794 // Try to validate the entity now all fields have been set. If it fails, return an error 914 795 if (!entity.validate() || invalidFields) { … … 916 797 917 798 // Add this field to the list of failed cells, in order to give the user feedback 918 failedCells = addNonValidatingCells ( failedCells, entity)799 failedCells = addNonValidatingCellsToImportRecord( failed, entity, flow ) 919 800 920 801 // Also create a full list of errors 921 errors += getHumanReadableErrors( entity ); 802 def currentErrors = getHumanReadableErrors( entity ) 803 if( currentErrors ) { 804 currentErrors.each { 805 errors += "(" + entityName + ") " + it.value; 806 } 807 } 808 809 newFailedCells << failed; 922 810 } else { 923 811 importerService.removeFailedCell( failedCells, entity ) … … 926 814 } // end of table 927 815 928 session.simpleWizard.imported.numInvalidEntities = numInvalidEntities; 929 session.simpleWizard.imported.errors = errors; 930 931 return true 816 flow.imported.failedCells = newFailedCells 817 flow.imported.numInvalidEntities = numInvalidEntities; 818 flow.imported.errors = errors; 819 820 return numInvalidEntities == 0 932 821 } 933 934 /** 935 * Handles assay input 936 * @param study Study to update 937 * @param params Request parameter map 938 * @return True if everything went OK, false otherwise. An error message is put in flash.error 939 */ 940 def handleAssays( assay, params ) { 941 // did the study template change? 942 if (params.get('template') && assay.template?.name != params.get('template')) { 943 // set the template 944 assay.template = Template.findByName(params.remove('template')) 945 } 946 947 // does the study have a template set? 948 if (assay.template && assay.template instanceof Template) { 949 // yes, iterate through template fields 950 assay.giveFields().each() { 951 // and set their values 952 assay.setFieldValue(it.name, params.get(it.escapedName())) 953 } 954 } 955 956 // Save the assay in session 957 session.simpleWizard.assay = assay; 958 959 return true 960 } 822 823 /** 824 * Handles assay input 825 * @param study Study to update 826 * @param params Request parameter map 827 * @return True if everything went OK, false otherwise. An error message is put in flash.error 828 */ 829 def handleAssays( assay, params, flow ) { 830 // did the study template change? 831 if (params.get('template') && assay.template?.name != params.get('template')) { 832 // set the template 833 assay.template = Template.findByName(params.remove('template')) 834 } 835 836 // does the study have a template set? 837 if (assay.template && assay.template instanceof Template) { 838 // yes, iterate through template fields 839 assay.giveFields().each() { 840 // and set their values 841 assay.setFieldValue(it.name, params.get(it.escapedName())) 842 } 843 } 844 845 return true 846 } 847 961 848 962 849 /** 963 850 * Checks whether the given study is simple enough to be edited using this controller. 964 * 965 * The study is simple enough if the samples, subjects, events and samplingEvents can be 966 * edited as a flat table. That is: 851 * 852 * The study is simple enough if the samples, subjects, events and samplingEvents can be 853 * edited as a flat table. That is: 967 854 * - Every subject belongs to 0 or 1 eventgroup 968 855 * - Every eventgroup belongs to 0 or 1 sample 969 856 * - Every eventgroup has 0 or 1 subjects, 0 or 1 event and 0 or 1 samplingEvents 970 857 * - If a sample belongs to an eventgroup: 971 * - If that eventgroup has a samplingEvent, that same samplingEvent must also be 858 * - If that eventgroup has a samplingEvent, that same samplingEvent must also be 972 859 * the sampling event that generated this sample 973 860 * - If that eventgroup has a subject, that same subject must also be the subject 974 861 * from whom the sample was taken 975 * 862 * 976 863 * @param study Study to check 977 864 * @return True if the study can be edited by this controller, false otherwise … … 979 866 def checkStudySimplicity( study ) { 980 867 def simplicity = true; 981 868 982 869 if( !study ) 983 870 return false … … 990 877 simplicity = false; 991 878 } 992 879 993 880 // Check whether this eventgroup only belongs to (max) 1 sample 994 881 def numSamples = 0; 995 882 study.samples.each { sample -> 996 // If no id is given for the eventGroup, it has been entered in this wizard, but 883 // If no id is given for the eventGroup, it has been entered in this wizard, but 997 884 // not yet saved. In that case, it is always OK 998 885 if( eventGroup.id && sample.parentEventGroup?.id == eventGroup.id ) 999 886 numSamples++; 1000 887 } 1001 1002 if( numSamples > 1 ) { 888 889 if( numSamples > 1 ) { 1003 890 flash.message = "One or more eventgroups belong to multiple samples." 1004 891 simplicity = false; 1005 892 } 1006 893 } 1007 894 1008 895 if( !simplicity ) return false; 1009 896 … … 1018 905 numEventGroups++ 1019 906 } 1020 907 1021 908 if( numEventGroups > 1 ) { 1022 909 flash.message = "One or more subjects belong to multiple eventgroups." … … 1027 914 1028 915 if( !simplicity ) return false; 1029 916 1030 917 // Check whether the samples that belong to an eventgroup have the right parentObjects 1031 918 study.samples.each { sample -> … … 1039 926 } 1040 927 } 1041 928 1042 929 // If no id is given for the sampling event, it has been entered in this wizard, but 1043 930 // not yet saved. In that case, it is always OK … … 1050 937 } 1051 938 } 1052 939 1053 940 if( !simplicity ) return false; 1054 941 } 1055 942 1056 943 return simplicity; 1057 944 } 1058 945 1059 def attachAndValidateEntities( def study ) { 1060 if( !session.simpleWizard?.imported?.data ) 1061 return 1062 1063 def table = session.simpleWizard.imported.data 1064 def numInvalidEntities = 0; 1065 1066 // Add all samples 1067 table.each { record -> 1068 println record*.class 1069 record.each { entity -> 1070 if( entity ) { 1071 if( entity.validate() ) { 1072 println "Saving: " + entity + " (" + entity.class.name + ")" 1073 println study.samples; 1074 println study.subjects; 1075 1076 // Determine entity class and add a parent 1077 def preferredIdentifier = importerService.givePreferredIdentifier( entity.class ); 1078 def equalClosure = { it.getFieldValue( preferredIdentifier.name ) == entity.getFieldValue( preferredIdentifier.name ) } 1079 1080 //entity.parent = study 1081 switch( entity.class ) { 1082 case Sample: 1083 if( preferredIdentifier && !study.samples?.find( equalClosure ) ) { 1084 study.addToSamples( entity ); 1085 } 1086 break; 1087 case Subject: 1088 if( preferredIdentifier && !study.subjects?.find( equalClosure ) ) { 1089 study.addToSubjects( entity ); 1090 } 1091 break; 1092 case Event: 1093 if( preferredIdentifier && !study.events?.find( equalClosure ) ) { 1094 study.addToEvents( entity ); 1095 } 1096 break; 1097 case SamplingEvent: 1098 if( preferredIdentifier && !study.samplingEvents?.find( equalClosure ) ) { 1099 study.addToSamplingEvents( entity ); 1100 } 1101 break; 1102 } 1103 1104 entity.save(); 1105 1106 } else { 1107 numInvalidEntities++; 1108 } 1109 } 1110 } 1111 } 1112 1113 return numInvalidEntities == 0; 946 947 /** 948 * Adds all fields of this entity that have given an error when validating to the failedcells list 949 * @param failedcells Current list of ImportRecords 950 * @param entity Entity to check. The entity must have been validated before 951 * @return Updated list of ImportRecords 952 */ 953 protected def addNonValidatingCells( failedcells, entity, flow ) { 954 // Add this entity and the fields with an error to the failedCells list 955 ImportRecord failedRecord = addNonValidatingCellsToImportRecord( new ImportRecord(), entity, flow ); 956 957 failedcells.add( failedRecord ); 958 959 return failedcells 1114 960 } 1115 961 962 /** 963 * Adds all fields of this entity that have given an error when validating to the failedcells list 964 * @param failedcells Current list of ImportRecords 965 * @param entity Entity to check. The entity must have been validated before 966 * @return Updated list of ImportRecords 967 */ 968 protected def addNonValidatingCellsToImportRecord( failedRecord, entity, flow ) { 969 entity.getErrors().getFieldErrors().each { error -> 970 String field = error.getField(); 971 972 def mc = importerService.findMappingColumn( flow.excel.data.header, field ); 973 def mcInstance = new MappingColumn( name: field, entityClass: Sample.class, index: -1, property: field.toLowerCase(), templateFieldType: entity.giveFieldType( field ) ); 974 975 // Create a clone of the mapping column 976 if( mc ) { 977 mcInstance.properties = mc.properties 978 } 979 980 failedRecord.addToImportcells( new ImportCell(mappingcolumn: mcInstance, value: error.getRejectedValue(), entityidentifier: importerService.getFieldNameInTableEditor( entity, field ) ) ) 981 } 982 983 return failedRecord 984 } 985 986 987 /** 988 * Checks an excel workbook whether the given sheetindex and rownumbers are correct 989 * @param workbook Excel workbook to read 990 * @param sheetIndex 1-based sheet index for the sheet to read (1=first sheet) 991 * @param headerRow 1-based row number for the header row (1=first row) 992 * @param dataMatrixStart 1-based row number for the first data row (1=first row) 993 * @return True if the sheet index and row numbers are correct. 994 */ 995 protected boolean excelChecks( def workbook, int sheetIndex, int headerRow, int dataMatrixStart ) { 996 // Perform some basic checks on the excel file. These checks should be performed by the importerservice 997 // in a perfect scenario. 998 if( sheetIndex > workbook.getNumberOfSheets() ) { 999 log.error ".simple study wizard Sheet index is too high: " + sheetIndex + " / " + workbook.getNumberOfSheets(); 1000 flash.error = "Your excel sheet contains too few excel sheets. The provided excel sheet has only " + workbook.getNumberOfSheets() + " sheet(s)."; 1001 return false 1002 } 1003 1004 def sheet = workbook.getSheetAt(sheetIndex - 1); 1005 def firstRowNum = sheet.getFirstRowNum(); 1006 def lastRowNum = sheet.getLastRowNum(); 1007 def numRows = lastRowNum - firstRowNum + 1; 1008 1009 if( headerRow > numRows ) { 1010 log.error ".simple study wizard Header row number is incorrect: " + headerRow + " / " + numRows; 1011 flash.error = "Your excel sheet doesn't contain enough rows (" + numRows + "). Please provide an excel sheet with one header row and data below"; 1012 return false 1013 } 1014 1015 if( dataMatrixStart > numRows ) { 1016 log.error ".simple study wizard Data row number is incorrect: " + dataMatrixStart + " / " + numRows; 1017 flash.error = "Your excel sheet doesn't contain enough rows (" + numRows + "). Please provide an excel sheet with one header row and data below"; 1018 return false 1019 } 1020 1021 return true; 1022 } 1023 1116 1024 /** 1117 1025 * Validates an object and puts human readable errors in validationErrors variable … … 1125 1033 } 1126 1034 return true; 1127 }1128 1129 /**1130 * Adds all fields of this entity that have given an error when validating to the failedcells list1131 * @param failedcells Current list of ImportRecords1132 * @param entity Entity to check. The entity must have been validated before1133 * @return Updated list of ImportRecords1134 */1135 protected def addNonValidatingCells( failedcells, entity ) {1136 // Add this entity and the fields with an error to the failedCells list1137 ImportRecord failedRecord = new ImportRecord();1138 1139 entity.getErrors().getFieldErrors().each { error ->1140 String field = error.getField();1141 1142 def mc = importerService.findMappingColumn( session.simpleWizard.excel.data.header, field );1143 def mcInstance = new MappingColumn( name: field, entityClass: Sample.class, index: -1, property: field.toLowerCase(), templateFieldType: entity.giveFieldType( field ) );1144 1145 // Create a clone of the mapping column1146 if( mc ) {1147 mcInstance.properties = mc.properties1148 }1149 1150 failedRecord.addToImportcells( new ImportCell(mappingcolumn: mcInstance, value: error.getRejectedValue(), entityidentifier: importerService.getFieldNameInTableEditor( entity, field ) ) )1151 }1152 failedcells.add( failedRecord );1153 1154 return failedcells1155 }1156 1157 1158 /**1159 * Checks an excel workbook whether the given sheetindex and rownumbers are correct1160 * @param workbook Excel workbook to read1161 * @param sheetIndex 1-based sheet index for the sheet to read (1=first sheet)1162 * @param headerRow 1-based row number for the header row (1=first row)1163 * @param dataMatrixStart 1-based row number for the first data row (1=first row)1164 * @return True if the sheet index and row numbers are correct.1165 */1166 protected boolean excelChecks( def workbook, int sheetIndex, int headerRow, int dataMatrixStart ) {1167 // Perform some basic checks on the excel file. These checks should be performed by the importerservice1168 // in a perfect scenario.1169 if( sheetIndex > workbook.getNumberOfSheets() ) {1170 log.error ".simple study wizard Sheet index is too high: " + sheetIndex + " / " + workbook.getNumberOfSheets();1171 flash.error = "Your excel sheet contains too few excel sheets. The provided excel sheet has only " + workbook.getNumberOfSheets() + " sheet(s).";1172 return false1173 }1174 1175 def sheet = workbook.getSheetAt(sheetIndex - 1);1176 def firstRowNum = sheet.getFirstRowNum();1177 def lastRowNum = sheet.getLastRowNum();1178 def numRows = lastRowNum - firstRowNum + 1;1179 1180 if( headerRow > numRows ) {1181 log.error ".simple study wizard Header row number is incorrect: " + headerRow + " / " + numRows;1182 flash.error = "Your excel sheet doesn't contain enough rows (" + numRows + "). Please provide an excel sheet with one header row and data below";1183 return false1184 }1185 1186 if( dataMatrixStart > numRows ) {1187 log.error ".simple study wizard Data row number is incorrect: " + dataMatrixStart + " / " + numRows;1188 flash.error = "Your excel sheet doesn't contain enough rows (" + numRows + "). Please provide an excel sheet with one header row and data below";1189 return false1190 }1191 1192 return true;1193 }1194 1195 /**1196 * Redirects the user to the page with the given name1197 * @param action1198 */1199 protected void toPage( String action ) {1200 println "Redirecting to: " + action;1201 redirect( action: action, params: [ "wizard": true ] );1202 }1203 1204 /**1205 * Returns the event that is specified by the user form1206 * @param params1207 * @return1208 */1209 protected String getEvent( def params ) {1210 return params.get( 'event' );1211 }1212 1213 /**1214 * Retrieves the required study from the database or return an empty Study object if1215 * no id is given1216 *1217 * @param params Request parameters with params.id being the ID of the study to be retrieved1218 * @return A study from the database or an empty study if no id was given1219 */1220 protected Study getStudyFromRequest( def params ) {1221 int id = params.int( "id" );1222 1223 if( !id ) {1224 return new Study( title: "New study", owner: authenticationService.getLoggedInUser() );1225 }1226 1227 Study s = Study.get( id );1228 1229 if( !s ) {1230 flash.error = "No study found with given id";1231 return null;1232 }1233 if( !s.canWrite( authenticationService.getLoggedInUser() ) ) {1234 flash.error = "No authorization to edit this study."1235 return null;1236 }1237 1238 return s1239 }1240 1241 /**1242 * Attach a template to the session1243 * @param t1244 * @return1245 */1246 protected attachTemplate( Template t ) {1247 if( t && !t.isAttached() ) {1248 t.attach();1249 1250 t.fields.each { field ->1251 if( field && !field.isAttached() )1252 field.attach();1253 1254 field.listEntries?.each { entry ->1255 if( entry && !entry.isAttached() )1256 entry.attach();1257 }1258 field.ontologies?.each { entry ->1259 if( entry && !entry.isAttached() )1260 entry.attach();1261 }1262 }1263 }1264 }1265 1266 /**1267 * Retrieves the study that is saved in the wizard,1268 *1269 * @param params Request parameters1270 * @return The found study object, or null if no study object is found1271 */1272 protected Study getStudyInWizard( def params ) {1273 if( params.wizard && session.simpleWizard && session.simpleWizard.study ) {1274 // The user came here by clicking previous or a link on another page. Use the existing study1275 Study s = session.simpleWizard.study;1276 1277 if( s.id && !s.isAttached() ) {1278 s.attach();1279 }1280 1281 s.samples?.each {1282 if( it && it.id && !it.isAttached() )1283 it.attach();1284 1285 attachTemplate( it.template )1286 }1287 s.subjects?.each {1288 if( it && it.id && !it.isAttached() )1289 it.attach();1290 1291 attachTemplate( it.template )1292 }1293 s.events?.each {1294 if( it && it.id && !it.isAttached() )1295 it.attach();1296 1297 attachTemplate( it.template )1298 }1299 1300 s.samplingEvents?.each {1301 if( it && it.id && !it.isAttached() )1302 it.attach();1303 1304 attachTemplate( it.template )1305 }1306 s.assays?.each {1307 if( it && it.id && !it.isAttached() )1308 it.attach();1309 1310 attachTemplate( it.template )1311 }1312 1313 return s;1314 } else {1315 // The user didn't get here from the wizard or no study is found1316 return null;1317 }1318 }1319 1320 /**1321 * Retrieves the assay to edit in the wizard1322 * @param s Study that the assay will be in1323 * @return Assay object (may be empty)1324 */1325 protected Assay getAssayInWizard( Study study = null ) {1326 if( session.simpleWizard && session.simpleWizard.assay ) {1327 Assay a = session.simpleWizard.assay;1328 1329 if( a.id && !a.isAttached() ) {1330 a.attach();1331 1332 attachTemplate( a.template );1333 }1334 1335 return a;1336 } else if( study ) {1337 // The user came on the assay page for the first time1338 if( study.assays?.size() ) {1339 def assay = study.assays[0];1340 1341 return assay;1342 } else {1343 return new Assay( parent: study );1344 }1345 } else {1346 return null;1347 }1348 1035 } 1349 1036 -
trunk/grails-app/services/dbnp/importer/ImporterService.groovy
r1603 r1608 23 23 def authenticationService 24 24 25 static transactional = true25 static transactional = false 26 26 27 27 /** … … 339 339 importedEntities = importedRows.flatten().findAll { it.class == dbnp.studycapturing.Sample }.unique(); 340 340 341 def importedSample = findEntityInImportedEntities( dbnp.studycapturing.Sample, excelRow, mcmap, importedEntities, df )342 def imported = retrieveEntitiesBySample( importedSample );341 def importedSample = null // findEntityInImportedEntities( dbnp.studycapturing.Sample, excelRow, mcmap, importedEntities, df ) 342 def imported = [] // retrieveEntitiesBySample( importedSample ); 343 343 344 344 for( entity in entities ) { … … 675 675 * Retrieves a mapping column from a list based on the given fieldname 676 676 * @param mappingColumns List of mapping columns 677 * @param fieldName Field name to find678 * @return Mapping column if a column is found, null otherwise677 * @param fieldName Field name to find 678 * @return Mapping column if a column is found, null otherwise 679 679 */ 680 680 def findMappingColumn( mappingColumns, String fieldName ) {
Note: See TracChangeset
for help on using the changeset viewer.