Changeset 1609
- Timestamp:
- Mar 9, 2011, 5:28:45 PM (10 years ago)
- Location:
- trunk/grails-app
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/grails-app/controllers/dbnp/studycapturing/SimpleWizardController.groovy
r1608 r1609 115 115 samples { 116 116 on("next") { 117 handleSamples( flow.study, params, flow ) ? success() : error () 117 if( !handleSamples( flow.study, params, flow ) ) 118 return error(); 118 119 119 120 // Add domain fields for all entities … … 125 126 } 126 127 } 127 128 129 println flow.sampleForm.template 128 130 }.to "columns" 131 on("refresh") { 132 def filename = params.get( 'importfile' ); 133 134 // Handle 'existing*' in front of the filename. This is put in front to make a distinction between 135 // an already uploaded file test.txt (maybe moved to some other directory) and a newly uploaded file test.txt 136 // still being in the temporary directory. 137 // This import step doesn't have to make that distinction, since all files remain in the temporary directory. 138 if( filename == 'existing*' ) 139 filename = ''; 140 else if( filename[0..8] == 'existing*' ) 141 filename = filename[9..-1] 142 143 // Refresh the templates, since the template editor has been opened 144 flow.templates = [ 145 'Sample': Template.findAllByEntity( Sample.class ), 146 'Subject': Template.findAllByEntity( Subject.class ), 147 'Event': Template.findAllByEntity( Event.class ), 148 'SamplingEvent': Template.findAllByEntity( SamplingEvent.class ) 149 ]; 150 151 flow.sampleForm = [ importFile: filename ] 152 }.to "samples" 129 153 on("previous").to "returnFromSamples" 130 154 on("study").to "study" … … 457 481 'Subject': subjectTemplateId, 458 482 'Event': eventTemplateId, 459 'Samp ingEvent': samplingEventTemplateId483 'SamplingEvent': samplingEventTemplateId 460 484 ], 461 485 template: [ … … 463 487 'Subject': subjectTemplateId ? Template.get( subjectTemplateId ) : null, 464 488 'Event': eventTemplateId ? Template.get( eventTemplateId ) : null, 465 'Samp ingEvent': samplingEventTemplateId ? Template.get( samplingEventTemplateId ) : null489 'SamplingEvent': samplingEventTemplateId ? Template.get( samplingEventTemplateId ) : null 466 490 ], 467 491 sheetIndex: sheetIndex, … … 663 687 return false 664 688 } 665 666 689 667 690 def imported = importerService.importOrUpdateDataBySampleIdentifier(templates, 668 691 workbook, … … 699 722 switch( entity.class ) { 700 723 case Sample: 701 if( preferredIdentifier &&!study.samples?.find( equalClosure ) ) {724 if( !preferredIdentifier || !study.samples?.find( equalClosure ) ) { 702 725 study.addToSamples( entity ); 703 726 } 704 727 break; 705 728 case Subject: 706 if( preferredIdentifier &&!study.subjects?.find( equalClosure ) ) {729 if( !preferredIdentifier || !study.subjects?.find( equalClosure ) ) { 707 730 study.addToSubjects( entity ); 708 731 } 709 732 break; 710 733 case Event: 711 if( preferredIdentifier &&!study.events?.find( equalClosure ) ) {734 if( !preferredIdentifier || !study.events?.find( equalClosure ) ) { 712 735 study.addToEvents( entity ); 713 736 } 714 737 break; 715 738 case SamplingEvent: 716 if( preferredIdentifier &&!study.samplingEvents?.find( equalClosure ) ) {739 if( !preferredIdentifier || !study.samplingEvents?.find( equalClosure ) ) { 717 740 study.addToSamplingEvents( entity ); 718 741 } -
trunk/grails-app/services/dbnp/importer/ImporterService.groovy
r1608 r1609 69 69 try { 70 70 formatValue(datamatrix_celldata, TemplateFieldType.DOUBLE) 71 } catch (NumberFormatException nfe) { doubleBoolean = false } 71 } catch (NumberFormatException nfe) { 72 doubleBoolean = false 73 } 72 74 finally { 73 75 if (doubleBoolean) fieldtype = TemplateFieldType.DOUBLE … … 89 91 try { 90 92 Long.valueOf(datamatrix_celldata) 91 } catch (NumberFormatException nfe) { longBoolean = false } 93 } catch (NumberFormatException nfe) { 94 longBoolean = false 95 } 92 96 finally { 93 97 if (longBoolean) fieldtype = TemplateFieldType.LONG … … 98 102 try { 99 103 formatValue(datamatrix_celldata, TemplateFieldType.DOUBLE) 100 } catch (NumberFormatException nfe) { doubleBoolean = false } 104 } catch (NumberFormatException nfe) { 105 doubleBoolean = false 106 } 101 107 finally { 102 108 if (doubleBoolean) fieldtype = TemplateFieldType.DOUBLE … … 187 193 } 188 194 189 195 190 196 /** 191 197 * Retrieves records with sample, subject, samplingevent etc. from a study … … 195 201 protected def getRecords( Study s ) { 196 202 def records = []; 197 203 198 204 s.samples?.each { 199 205 def record = [ 'objects': retrieveEntitiesBySample( it ) ]; 200 206 201 207 def templates = [:] 202 208 def templateCombination = []; … … 206 212 templateCombination << entity.key + ": " + entity.value?.template?.name; 207 213 } 208 214 209 215 record.templates = templates; 210 216 record.templateCombination = templateCombination.join( ', ' ) 211 217 212 218 records << record 213 219 } 214 220 215 221 return records; 216 222 } 217 223 218 224 /** 219 225 * Returns a subject, event and samplingEvent that belong to this sample … … 229 235 ] 230 236 } 231 237 232 238 /** 233 239 * Imports data from a workbook into a list of ImportRecords. If some entities are already in the database, … … 252 258 if( !mcmap ) 253 259 return; 254 260 255 261 // Check whether the rows should be imported in one or more entities 256 262 def entities … … 260 266 entities = mcmap.findAll{ !it.dontimport }.entityclass.unique(); 261 267 } 262 268 263 269 def sheet = wb.getSheetAt(sheetindex) 264 270 def table = [] 265 271 def failedcells = [] // list of cells that have failed to import 266 267 272 // First check for each record whether an entity in the database should be updated, 268 273 // or a new entity should be added. This is done before any new object is created, since … … 274 279 existingEntities[i] = findExistingEntities( entities, sheet.getRow(i), mcmap, parent ); 275 280 } 276 281 277 282 // walk through all rows and fill the table with records 278 283 for( int i = rowindex; i <= sheet.getLastRowNum(); i++ ) { 279 284 // Create an entity record based on a row read from Excel and store the cells which failed to be mapped 280 285 def (record, failed) = importOrUpdateRecord( templates, entities, sheet.getRow(i), mcmap, parent, table, existingEntities[i] ); 281 286 282 287 // Setup the relationships between the imported entities 283 288 relateEntities( record ); 284 289 285 290 // Add record with entities and its values to the table 286 291 table.add(record) … … 289 294 if (failed?.importcells?.size() > 0) failedcells.add(failed) 290 295 } 291 296 292 297 return [ "table": table, "failedCells": failedcells ] 293 298 } 294 299 295 300 /** 296 * Checks whether entities in the given row already exist in the database297 * they are updated.298 *299 * @param entities Entities that have to be imported for this row300 * @param excelRow Excel row to import into this record301 * @param mcmap Hashmap of mappingcolumns, with the first entry in the hashmap containing information about the first column, etc.302 * @return Map Map with entities that have been found for this row. The key for the entities is the entity name (e.g.: [Sample: null, Subject: <subject object>]303 */304 305 306 307 308 309 310 311 301 * Checks whether entities in the given row already exist in the database 302 * they are updated. 303 * 304 * @param entities Entities that have to be imported for this row 305 * @param excelRow Excel row to import into this record 306 * @param mcmap Hashmap of mappingcolumns, with the first entry in the hashmap containing information about the first column, etc. 307 * @return Map Map with entities that have been found for this row. The key for the entities is the entity name (e.g.: [Sample: null, Subject: <subject object>] 308 */ 309 def findExistingEntities(def entities, Row excelRow, mcmap, parent ) { 310 DataFormatter df = new DataFormatter(); 311 312 // Find entities based on sample identifier 313 def sample = findEntityByRow( dbnp.studycapturing.Sample, excelRow, mcmap, parent, [], df ); 314 return retrieveEntitiesBySample( sample ); 315 } 316 312 317 /** 313 318 * Imports a records from the excelsheet into the database. If the entities are already in the database … … 332 337 def record = [] // list of entities and the read values 333 338 def failed = new ImportRecord() // map with entity identifier and failed mappingcolumn 334 339 335 340 // Check whether this record mentions a sample that has been imported before. In that case, 336 341 // we update that record, in order to prevent importing the same sample multiple times … … 341 346 def importedSample = null // findEntityInImportedEntities( dbnp.studycapturing.Sample, excelRow, mcmap, importedEntities, df ) 342 347 def imported = [] // retrieveEntitiesBySample( importedSample ); 343 344 348 for( entity in entities ) { 345 349 // Check whether this entity should be added or updated … … 348 352 def entityName = entity.name[ entity.name.lastIndexOf( '.' ) + 1..-1]; 349 353 def template = templates[ entityName ]; 350 354 351 355 // If no template is specified for this entity, continue with the next 352 356 if( !template ) 353 357 continue; 354 358 355 359 // Check whether the object exists in the list of already imported entities 356 360 def entityObject = imported[ entityName ] 357 361 358 362 // If it doesn't, search for the entity in the database 359 363 if( !entityObject && existingEntities ) 360 364 entityObject = existingEntities[ entityName ]; 361 365 362 366 // Otherwise, create a new object 363 367 if( !entityObject ) 364 368 entityObject = entity.newInstance(); 365 369 366 370 // Update the template 367 371 entityObject.template = template; 368 372 369 373 // Go through the Excel row cell by cell 370 374 for (Cell cell: excelRow) { … … 372 376 def mc = mcmap[cell.getColumnIndex()] 373 377 def value 374 378 375 379 // Check if column must be imported 376 380 if (mc != null && !mc.dontimport && mc.entityclass == entity) { … … 380 384 value = "" 381 385 } 382 386 383 387 try { 384 388 entityObject.setFieldValue(mc.property, value) … … 388 392 // store the mapping column and value which failed 389 393 def identifier = entityName.toLowerCase() + "_" + entityObject.getIdentifier() + "_" + mc.property 390 394 391 395 def mcInstance = new MappingColumn() 392 396 mcInstance.properties = mc.properties … … 395 399 } // end if 396 400 } // end for 397 401 398 402 // If a Study is entered, use it as a 'parent' for other entities 399 403 if( entity == Study ) 400 404 parent = entityObject; 401 405 402 406 record << entityObject; 403 407 } 404 408 405 409 // a failed column means that using the entity.setFieldValue() threw an exception 406 410 return [record, failed] 407 411 } 408 412 409 413 /** 410 414 * Looks into the database to find an object of the given entity that should be updated, given the excel row. … … 424 428 if( df == null ) 425 429 df = new DataFormatter(); 426 430 427 431 def identifierField = givePreferredIdentifier( entity ); 428 432 429 433 if( identifierField ) { 430 434 // Check whether the identifierField is chosen in the column matching 431 435 def identifierColumn = mcmap.find { it.entityclass == entity && it.property == identifierField.name }; 432 436 433 437 // If it is, find the identifier and look it up in the database 434 438 if( identifierColumn ) { … … 440 444 identifier = null 441 445 } 442 446 443 447 // Search for an existing object with the same identifier. 444 448 if( identifier ) { … … 449 453 return imported; 450 454 } 451 455 452 456 def c = entity.createCriteria(); 453 457 454 458 // If the entity has a field 'parent', the search should be limited to 455 459 // objects with the same parent. The method entity.hasProperty( "parent" ) doesn't … … 458 462 // If the entity requires a parent, but none is given, no 459 463 // results are given from the database. This prevents the user 460 // of changing data in another study 464 // of changing data in another study 461 465 if( parent && parent.id ) { 462 466 println "Searching (with parent ) for " + entity.name + " with " + identifierField.name + " = " + identifier … … 475 479 } 476 480 } 477 481 478 482 // No object is found 479 483 return null; 480 484 } 481 482 /** 483 * Looks into the list of already imported entities to find an object of the given entity that should be484 * updated, given the excel row. This is done by looking at the 'preferredIdentifier' field of the object.485 * If it exists in the row, and the list of imported entities contains an object with the same486 * identifier, the existing object is returned. Otherwise, null is returned487 *488 * @param entity Entity to search489 * @param excelRow Excelrow to search for490 * @param mcmap Map with MappingColumns491 * @param importedRows List of entities that have been imported before. The function will first look through this list to find492 * a matching entity.493 * @return An entity that has the same identifier as entered in the excelRow. The entity is first sought in the importedRows. If it494 * is not found there, the database is queried. If no entity is found at all, null is returned.495 */496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 485 486 /** 487 * Looks into the list of already imported entities to find an object of the given entity that should be 488 * updated, given the excel row. This is done by looking at the 'preferredIdentifier' field of the object. 489 * If it exists in the row, and the list of imported entities contains an object with the same 490 * identifier, the existing object is returned. Otherwise, null is returned 491 * 492 * @param entity Entity to search 493 * @param excelRow Excelrow to search for 494 * @param mcmap Map with MappingColumns 495 * @param importedRows List of entities that have been imported before. The function will first look through this list to find 496 * a matching entity. 497 * @return An entity that has the same identifier as entered in the excelRow. The entity is first sought in the importedRows. If it 498 * is not found there, the database is queried. If no entity is found at all, null is returned. 499 */ 500 def findEntityInImportedEntities( Class entity, Row excelRow, def mcmap, List importedEntities = [], DataFormatter df = null ) { 501 if( df == null ) 502 df = new DataFormatter(); 503 504 def allFields = entity.giveDomainFields(); 505 def identifierField = allFields.find { it.preferredIdentifier } 506 507 if( identifierField ) { 508 // Check whether the identifierField is chosen in the column matching 509 def identifierColumn = mcmap.find { it.entityclass == entity && it.property == identifierField.name }; 510 511 // If it is, find the identifier and look it up in the database 512 if( identifierColumn ) { 513 def identifierCell = excelRow.getCell( identifierColumn.index ); 514 def identifier; 515 try { 516 identifier = formatValue(df.formatCellValue(identifierCell), identifierColumn.templatefieldtype) 517 } catch (NumberFormatException nfe) { 518 identifier = null 519 } 520 521 // Search for an existing object with the same identifier. 522 if( identifier ) { 519 523 // First search the already imported rows 520 524 if( importedEntities ) { … … 526 530 else 527 531 return fieldValue == identifier 528 529 532 }; 530 531 532 533 534 535 536 537 538 539 540 541 533 if( imported ) 534 return imported; 535 } 536 } 537 } 538 } 539 540 // No object is found 541 return null; 542 } 543 544 542 545 /** 543 546 * Creates relation between multiple entities that have been imported. The entities are … … 551 554 def samplingEvent = entities.find { it instanceof SamplingEvent } 552 555 def assay = entities.find { it instanceof Assay } 553 556 554 557 // A study object is found in the entity list 555 558 if( study ) { … … 563 566 } 564 567 if( event ) { 565 event.parent = study 568 event.parent = study 566 569 study.addToEvents( event ); 567 570 } … … 584 587 if( subject ) evGroup.addToSubjects( subject ); 585 588 if( samplingEvent ) evGroup.addToSamplingEvents( samplingEvent ); 586 589 587 590 sample.parentEventGroup = evGroup; 588 591 } 589 592 590 593 if( assay ) assay.addToSamples( sample ); 591 594 } … … 610 613 def table = [] 611 614 def failedcells = [] // list of records 612 613 615 // walk through all rows and fill the table with records 614 616 (rowindex..sheet.getLastRowNum()).each { i -> … … 665 667 def getFieldNameInTableEditor(entity, field) { 666 668 def entityName = entity?.class.name[ entity?.class.name.lastIndexOf(".") + 1..-1] 667 669 668 670 if( field instanceof TemplateField ) 669 671 field = field.escapedName(); 670 672 671 return entityName.toLowerCase() + "_" + entity.getIdentifier() + "_" + field 673 return entityName.toLowerCase() + "_" + entity.getIdentifier() + "_" + field.toLowerCase() 672 674 } 673 675 … … 928 930 // store the mapping column and value which failed 929 931 def identifier 930 932 def fieldName = mc.property?.toLowerCase() 933 931 934 switch (mc.entityclass) { 932 case Study: identifier = "entity_" + study.getIdentifier() + "_" + mc.property933 break 934 case Subject: identifier = "entity_" + subject.getIdentifier() + "_" + mc.property935 break 936 case SamplingEvent: identifier = "entity_" + samplingEvent.getIdentifier() + "_" + mc.property937 break 938 case Event: identifier = "entity_" + event.getIdentifier() + "_" + mc.property939 break 940 case Sample: identifier = "entity_" + sample.getIdentifier() + "_" + mc.property935 case Study: identifier = "entity_" + study.getIdentifier() + "_" + fieldName 936 break 937 case Subject: identifier = "entity_" + subject.getIdentifier() + "_" + fieldName 938 break 939 case SamplingEvent: identifier = "entity_" + samplingEvent.getIdentifier() + "_" + fieldName 940 break 941 case Event: identifier = "entity_" + event.getIdentifier() + "_" + fieldName 942 break 943 case Sample: identifier = "entity_" + sample.getIdentifier() + "_" + fieldName 941 944 break 942 945 case Object: // don't import … … 972 975 } 973 976 } 974 977 975 978 /** 976 979 * Returns the preferred identifier field for a given entity or -
trunk/grails-app/views/common/_topnav.gsp
r1512 r1609 14 14 <li><g:link controller="studyWizard" action="index" params="[jump:'create']">Create a new study</g:link></li> 15 15 <li><g:link controller="studyWizard" action="index" params="[jump:'edit']">Edit a study</g:link></li> 16 <li><g:link controller="simpleWizard" action="index">Simple wizard</g:link></li> 16 17 <li><g:link controller="importer" action="index">Import study data</g:link></li> 17 18 <li><g:link controller="simpleQuery" action="index">Search study data</g:link></li> -
trunk/grails-app/views/simpleWizard/simpleWizard/columns.gsp
r1608 r1609 59 59 %> 60 60 <g:each in="${allFields}" var="field"> 61 <% 62 def value = entityTemplates.key + "||" + field.name 63 def selected = ( value == selectedValue ); 64 %> 65 <option value="${value}" <g:if test="${selected}">selected="selected"</g:if>> 66 ${field.name} <g:if test="${field.preferredIdentifier}">[identifier]</g:if> 61 <g:if test="${field}"> 62 <% 63 def value = entityTemplates.key + "||" + field.name 64 def selected = ( value == selectedValue ); 65 %> 66 <option value="${value}" <g:if test="${selected}">selected="selected"</g:if>> 67 ${field.name} <g:if test="${field.preferredIdentifier}">[identifier]</g:if> 68 </option> 69 </g:if> 67 70 68 71 </g:each> -
trunk/grails-app/views/simpleWizard/simpleWizard/missingFields.gsp
r1608 r1609 31 31 <g:if test="${imported.errors}"> 32 32 <br /><br />The following errors occurred:<br /> 33 <g:each in="${imported.errors }" var="err">33 <g:each in="${imported.errors.unique()}" var="err"> 34 34 ${err}<br /> 35 35 </g:each> -
trunk/grails-app/views/simpleWizard/simpleWizard/samples.gsp
r1608 r1609 48 48 </td> 49 49 <td> 50 <g:select rel="template" entity="${encodedEntity.Sample}" name="sample_template_id" optionKey="id" optionValue="name" from="${templates.Sample}" />50 <g:select rel="template" entity="${encodedEntity.Sample}" name="sample_template_id" optionKey="id" optionValue="name" from="${templates.Sample}" value="${sampleForm?.templateId?.Sample}"/> 51 51 </td> 52 52 </tr> … … 56 56 </td> 57 57 <td> 58 <g:select rel="template" entity="${encodedEntity.Subject}" name="subject_template_id" optionKey="id" optionValue="name" from="${templates.Subject}"/>58 <g:select rel="template" entity="${encodedEntity.Subject}" name="subject_template_id" noSelection="${[null: '- no subject template -']}" optionKey="id" optionValue="name" from="${templates.Subject}" value="${sampleForm?.templateId?.Subject}" /> 59 59 </td> 60 </tr> 60 </tr> 61 62 <tr> 63 <td> 64 <div id="datatemplate">Choose type of sampling event template:</div> 65 </td> 66 <td> 67 <g:select rel="template" entity="${encodedEntity.SamplingEvent}" name="samplingEvent_template_id" noSelection="${[null: '- no sampling event template -']}" optionKey="id" optionValue="name" from="${templates.SamplingEvent}" value="${sampleForm?.templateId?.SamplingEvent}" /> 68 </td> 69 </tr> 61 70 </table> 62 71 </div> -
trunk/grails-app/views/study/list.gsp
r1494 r1609 20 20 <thead> 21 21 <tr> 22 <th colspan=" 3"></th>22 <th colspan="4"></th> 23 23 <g:sortableColumn property="code" title="${message(code: 'study.code.label', default: 'Code')}"/> 24 24 <th>Title</th> … … 33 33 34 34 <td><input type="checkbox" name="id" value="${studyInstance.id}" id="${studyInstance.title}"></td> 35 <td><g:link action="show" id="${studyInstance?.id}"><img src='${fam.icon(name: 'application_form_magnify')}' border="0" alt="view study" /></g:link></td> 36 <td><g:if test="${studyInstance.canWrite(loggedInUser)}"><g:link class="edit" controller="studyWizard" params="[jump:'edit']" id="${studyInstance?.id}"><img src='${fam.icon(name: 'application_form_edit')}' border="0" alt="edit study" /></g:link></g:if><g:else><img src='${fam.icon(name: 'lock')}' border="0" alt="you have no write access to shis study" /></g:else> </td> 35 <td><g:link action="show" title="View study" id="${studyInstance?.id}"><img src='${fam.icon(name: 'application_form_magnify')}' border="0" alt="view study" /></g:link></td> 36 <td><g:if test="${studyInstance.canWrite(loggedInUser)}"> 37 <g:link class="edit" title="Edit study using simple wizard" controller="simpleWizard" action="index" id="${studyInstance?.id}"> 38 <img src='${fam.icon(name: 'pencil')}' border="0" alt="edit study" /></g:link> 39 </g:if><g:else><img src='${fam.icon(name: 'lock')}' border="0" alt="you have no write access to shis study" /></g:else> 40 </td> 41 <td><g:if test="${studyInstance.canWrite(loggedInUser)}"> 42 <g:link class="edit" title="Edit study" controller="studyWizard" params="[jump:'edit']" id="${studyInstance?.id}"> 43 <img src='${fam.icon(name: 'application_form_edit')}' border="0" alt="edit study" /></g:link> 44 </g:if><g:else><img src='${fam.icon(name: 'lock')}' border="0" alt="you have no write access to shis study" /></g:else> 45 </td> 37 46 <td>${fieldValue(bean: studyInstance, field: "code")}</td> 38 47 <td> -
trunk/grails-app/views/study/show.gsp
r1461 r1609 215 215 <g:hiddenField name="id" value="${studyInstance?.id}"/> 216 216 <g:if test="${studyInstance.canWrite(loggedInUser)}"> 217 <span class="button"><g:link class="edit" controller="simpleWizard" action="index" id="${studyInstance?.id}">Simple edit</g:link></span> 217 218 <span class="button"><g:link class="edit" controller="studyWizard" params="[jump:'edit']" id="${studyInstance?.id}">${message(code: 'default.button.edit.label', default: 'Edit')}</g:link></span> 218 219 </g:if>
Note: See TracChangeset
for help on using the changeset viewer.