Changeset 487
- Timestamp:
- May 27, 2010, 4:03:31 PM (14 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 6 deleted
- 4 edited
- 5 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/grails-app/domain/dbnp/studycapturing/TemplateEntity.groovy
r453 r487 21 21 Map templateDoubleFields = [:] 22 22 Map templateDateFields = [:] 23 Map templateRelTimeFields = [:] // Contains relative times in seconds 23 24 Map templateTermFields = [:] 24 25 … … 32 33 templateDateFields: Date, 33 34 templateTermFields: Term, 35 templateRelTimeFields: long, 34 36 systemFields: TemplateField 35 37 ] … … 200 202 return (!error) 201 203 }) 204 templateRelTimeFields(validator: { fields, obj, errors -> 205 def error = false 206 fields.each { key, value -> 207 if ( value && value.class != long ) { 208 try { 209 fields[key] = (value as long) 210 } catch (Exception e) { 211 error = true 212 errors.rejectValue( 213 'templateRelTimeFields', 214 'templateEntity.typeMismatch.reltime', 215 [key, value.class] as Object[], 216 'Property {0} must be of type long and is currently of type {1}' 217 ) 218 } 219 } 220 } 221 return (!error) 222 }) 202 223 templateTermFields(validator: { fields, obj, errors -> 203 224 def error = false … … 228 249 * @throws NoSuchFieldException 229 250 */ 230 p rivateMap getStore(TemplateFieldType fieldType) {251 public Map getStore(TemplateFieldType fieldType) { 231 252 switch(fieldType) { 232 253 case TemplateFieldType.STRING: … … 240 261 case TemplateFieldType.DATE: 241 262 return templateDateFields 263 case TemplateFieldType.RELTIME: 264 return templateRelTimeFields 242 265 case TemplateFieldType.FLOAT: 243 266 return templateFloatFields … … 353 376 } 354 377 378 // Magic setter for relative times: handle string values for relTime fields 379 // 380 // The relative time may be set as a string, using the following format 381 // 382 // #w #d #h #m #s 383 // 384 // Where w = weeks, d = days, h = hours, m = minutes, s = seconds 385 // 386 // The spaces between the values are optional. Every timespan 387 // (w, d, h, m, s) must appear at most once. You can also omit 388 // timespans if needed or use a different order. 389 // Other characters are disregarded, allthough results may not 390 // always be as expected. 391 // 392 // If an incorrect format is used, which can't be parsed 393 // an IllegalArgumentException is thrown. 394 // 395 // An empty span is treated as zero seconds. 396 // 397 // Examples: 398 // --------- 399 // 5d 3h 20m // 5 days, 3 hours and 20 minutes 400 // 6h 2d // 2 days, 6 hours 401 // 10m 200s // 13 minutes, 20 seconds (200s == 3m + 20s) 402 // 5w4h15m // 5 weeks, 4 hours, 15 minutes 403 // 404 // 16x14w10d // Incorrect. 16x is disregarded, so the 405 // // result is 15 weeks, 3 days 406 // 13days // Incorrect: days should be d, but this is 407 // // parsed as 13d, 0 seconds 408 // 409 if (field.type == TemplateFieldType.RELTIME && value.class == String) { 410 // A string was given, attempt to transform it into a timespan 411 412 // An empty string should be parsed as 0 413 if( value.trim() == "" ) { 414 value = 0; 415 } else { 416 // Find all parts that contain numbers with 417 // a character w, d, h, m or s after it 418 def periodMatch = value =~ /([0-9]+)([wdhms])/ 419 if (periodMatch.size() > 0 ) { 420 def seconds = 0L; 421 422 // Now check if every part contains data for 423 // the time interval 424 periodMatch.each { 425 def partValue 426 427 println it 428 429 if( it[1].isLong() ) { 430 partValue = Long.parseLong( it[1] ); 431 } else { 432 partValue = 0; 433 } 434 435 switch( it[ 2 ] ) { 436 case 'w': 437 seconds += 7L * 24 * 60 * 60 * partValue; 438 break; 439 case 'd': 440 seconds += 24L * 60 * 60 * partValue; 441 break; 442 case 'h': 443 seconds += 60L * 60 * partValue; 444 break; 445 case 'm': 446 seconds += 60L * partValue; 447 break; 448 case 's': 449 seconds += partValue; 450 break; 451 default: 452 adf.error.warn( 'Parsing relative time: ' + it[0] + it[1] + ' is not understood and disregarded' ); 453 break; 454 } 455 } 456 457 // Continue with the computed value 458 value = seconds; 459 } else { 460 throw new IllegalArgumentException( "String " + value + " cannot be parsed as a relative time. Use format #w #d #h #m #s." ); 461 } 462 } 463 } 464 355 465 // Magic setter for ontology terms: handle string values 356 466 if (field.type == TemplateFieldType.ONTOLOGYTERM && value && value.class == String) { … … 384 494 // If that is ever changed, the results are pretty much unpredictable (random Java object pointers?)! 385 495 def store = getStore(field.type) 386 if (!value && store[fieldName]) { 387 println ".unsetting [" + ((super) ? super.class : '??') + "] template field: [" + fieldName + "]" 388 389 // remove the item from the Map (if present) 390 store.remove(fieldName) 391 } else if (value) { 392 println ".setting [" + ((super) ? super.class : '??') + "] template field: [" + fieldName + "] ([" + value.toString() + "] of type [" + value.class + "])" 393 394 // set value 395 store[fieldName] = value 396 } 496 497 // If some value is entered (or 0), then save the value 498 // otherwise, it should not be present in the store, so 499 // it is unset if it is. 500 if ( value || value == 0 ) { 501 println ".setting [" + ((super) ? super.class : '??') + "] template field: [" + fieldName + "] ([" + value.toString() + "] of type [" + value.class + "])" 502 503 // set value 504 store[fieldName] = value 505 } else if ( store[fieldName] ) { 506 println ".unsetting [" + ((super) ? super.class : '??') + "] template field: [" + fieldName + "]" 507 508 // remove the item from the Map (if present) 509 store.remove(fieldName) 510 } 397 511 } 398 512 … … 420 534 /** 421 535 * Return all fields defined in the underlying template and the built-in 422 * domain fields of this entity536 * domain fields of this entity 423 537 */ 424 538 def List<TemplateField> giveFields() { -
trunk/grails-app/domain/dbnp/studycapturing/TemplateFieldType.groovy
r482 r487 17 17 ONTOLOGYTERM('Ontology Reference'), 18 18 DATE('Date'), 19 RELDATE('Relative date') // relative date, e.g. days since start of study19 RELTIME('Relative time') // relative date, e.g. days since start of study 20 20 21 21 String name … … 26 26 27 27 static list() { 28 [STRING, TEXT, INTEGER, FLOAT, DOUBLE, STRINGLIST, ONTOLOGYTERM, DATE, REL DATE]28 [STRING, TEXT, INTEGER, FLOAT, DOUBLE, STRINGLIST, ONTOLOGYTERM, DATE, RELTIME] 29 29 } 30 30 … … 45 45 case DATE: 46 46 return null 47 case RELDATE:48 return null47 case RELTIME: 48 return null 49 49 default: 50 50 throw new NoSuchFieldException("Field type ${fieldType} not recognized") -
trunk/test/integration/gscf/StudyTests.groovy
r412 r487 23 23 final Date testStudyStartDate = Date.parse('yyyy-MM-dd','2007-12-11') 24 24 final Date testStudyStartDate2 = Date.parse('yyyy-MM-dd','2008-05-11') 25 final String testStudyStartDateString2 = "11-5-20 10"25 final String testStudyStartDateString2 = "11-5-2008" 26 26 // The following dates do net yet work: 27 27 //final String testStudyStartDateString2 = "11-05-2010" -
trunk/test/unit/dbnp/data/OntologyControllerTests.groovy
r448 r487 1 package dbnp.data 2 1 3 import grails.test.* 2 4 -
trunk/test/unit/dbnp/data/TermControllerTests.groovy
r448 r487 1 package dbnp.data 2 1 3 import grails.test.* 2 4 -
trunk/test/unit/dbnp/importer/ImporterTagLibTests.groovy
r448 r487 1 package importer1 package dbnp.importer 2 2 3 3 import grails.test.* -
trunk/test/unit/dbnp/query/QueryControllerTests.groovy
r448 r487 1 package dbnp.query 1 2 import grails.test.* 2 3 -
trunk/test/unit/dbnp/studycapturing/StudyControllerTests.groovy
r448 r487 1 package dbnp.studycapturing 1 2 import grails.test.* 2 3 -
trunk/test/unit/dbnp/studycapturing/TemplateFieldTests.groovy
r84 r487 4 4 5 5 class TemplateFieldTests extends GrailsUnitTestCase { 6 def testEvent; 6 7 protected void setUp() { 7 8 super.setUp() 9 10 // Create the template itself 11 def testTemplate = new Template( 12 name: 'Template for testing relative date fields', 13 entity: dbnp.studycapturing.Event, 14 fields: [ 15 new TemplateField( 16 name: 'testStartDate', 17 type: TemplateFieldType.DATE 18 ), 19 new TemplateField( 20 name: 'testRelTime', 21 type: TemplateFieldType.RELTIME 22 ) 23 ] 24 ); 25 26 this.testEvent = new Event( 27 template: testTemplate, 28 startTime: Date.parse('yyyy-MM-dd','2008-01-02'), 29 endTime: Date.parse('yyyy-MM-dd','2008-01-05') 30 ) 8 31 } 9 32 … … 12 35 } 13 36 14 void testSomething() { 37 void testRelTimeFieldCreation() { 38 def RelTimeField = new TemplateField( 39 name: 'RelTime', 40 type: TemplateFieldType.RELTIME 41 ); 42 } 43 44 void testRelTimeSetValue() { 45 // Check whether the field exists 46 assert this.testEvent.fieldExists( 'testRelTime' ); 47 48 // See that it is not a domain field 49 assert !this.testEvent.isDomainField( 'testRelTime' ); 50 println( this.testEvent.getStore( TemplateFieldType.RELTIME ) ); 51 52 this.testEvent.setFieldValue( 'testRelTime', 10 ); 53 assert this.testEvent.getFieldValue( 'testRelTime' ) == 10; 54 55 this.testEvent.setFieldValue( 'testRelTime', 0 ); 56 assert this.testEvent.getFieldValue( 'testRelTime' ) == 0; 57 58 this.testEvent.setFieldValue( 'testRelTime', -130 ); 59 assert this.testEvent.getFieldValue( 'testRelTime' ) == -130; 60 61 // RelTime must be able to handle 100 years 62 long hundredYears = 100L * 365 * 24 * 3600; 63 this.testEvent.setFieldValue( 'testRelTime', hundredYears ); 64 assert this.testEvent.getFieldValue( 'testRelTime' ) == hundredYears; 65 } 66 67 // Tests the parsing of a string for relative dates 68 // @see TemplateEntity.setFieldValue 69 // 70 // The relative date may be set as a string, using the following format 71 // 72 // #w #d #h #m #s 73 // 74 // Where w = weeks, d = days, h = hours, m = minutes, s = seconds 75 // 76 // The spaces between the values are optional. Every timespan 77 // (w, d, h, m, s) must appear at most once. You can also omit 78 // timespans if needed or use a different order. 79 // Other characters are disregarded, allthough results may not 80 // always be as expected. 81 // 82 // If an incorrect format is used, which can't be parsed 83 // an IllegalFormatException is thrown. 84 // 85 // An empty span is treated as zero seconds. 86 // 87 // Examples: 88 // --------- 89 // 5d 3h 20m // 5 days, 3 hours and 20 minutes 90 // 6h 2d // 2 days, 6 hours 91 // 10m 200s // 13 minutes, 20 seconds (200s == 3m + 20s) 92 // 5w4h15m // 5 weeks, 4 hours, 15 minutes 93 // 94 // 16x14w10d // Incorrect. 16x is disregarded, so the 95 // // result is 15 weeks, 3 days 96 // 13days // Incorrect: days should be d, but this is 97 // // parsed as 13d, 0 seconds 98 // 99 void testRelTimeParser() { 100 def s = 1L; 101 def m = 60L * s; 102 def h = 60L * m; 103 def d = 24L * h; 104 def w = 7L * d; 105 106 this.testEvent.setFieldValue( 'testRelTime', '' ); 107 assert this.testEvent.getFieldValue( 'testRelTime' ) == 0; 108 109 this.testEvent.setFieldValue( 'testRelTime', ' ' ); 110 assert this.testEvent.getFieldValue( 'testRelTime' ) == 0; 111 112 this.testEvent.setFieldValue( 'testRelTime', '5d 3h 20m' ); 113 assert this.testEvent.getFieldValue( 'testRelTime' ) == 5 * d + 3 * h + 20 * m; 114 115 this.testEvent.setFieldValue( 'testRelTime', '6h 2d' ); 116 assert this.testEvent.getFieldValue( 'testRelTime' ) == 2 * d + 6 * h; 117 118 this.testEvent.setFieldValue( 'testRelTime', '10m 200s' ); 119 assert this.testEvent.getFieldValue( 'testRelTime' ) == 10 * m + 200 * s; 120 121 this.testEvent.setFieldValue( 'testRelTime', '5w4h15m' ); 122 assert this.testEvent.getFieldValue( 'testRelTime' ) == 5 * w + 4 * h + 15 * m; 123 124 // Should parse correctly, allthough it is not completely correct 125 this.testEvent.setFieldValue( 'testRelTime', '16x14w10d' ); 126 assert this.testEvent.getFieldValue( 'testRelTime' ) == 14 * w + 10 * d; 127 128 this.testEvent.setFieldValue( 'testRelTime', '13days' ); 129 assert this.testEvent.getFieldValue( 'testRelTime' ) == 13 * d; 130 131 // Test whether an IllegalFormatException is thrown 132 try { 133 this.testEvent.setFieldValue( 'testRelTime', 'nonexistent relative date' ); 134 fail(); 135 } catch(IllegalArgumentException ex) { 136 } catch( Exception ex ) { 137 fail(); 138 } 15 139 16 140 }
Note: See TracChangeset
for help on using the changeset viewer.