1
- // Copyright 2019 - 2021 The Samply Community
1
+ // Copyright 2019 - 2022 The Samply Community
2
2
//
3
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
4
// you may not use this file except in compliance with the License.
@@ -47,7 +47,7 @@ func UnmarshalResource(b []byte) (Resource, error) {
47
47
type ResourceMap = map [string ]map [string ][]byte
48
48
49
49
var licenseComment = Split (Trim (`
50
- Copyright 2019 - 2021 The Samply Community
50
+ Copyright 2019 - 2022 The Samply Community
51
51
52
52
Licensed under the Apache License, Version 2.0 (the "License");
53
53
you may not use this file except in compliance with the License.
@@ -318,7 +318,9 @@ func appendGeneratorComment(file *jen.File) {
318
318
file .Comment ("// THIS FILE IS GENERATED BY https://github.com/samply/golang-fhir-models\n // PLEASE DO NOT EDIT BY HAND\n " )
319
319
}
320
320
321
- func appendFields (resources ResourceMap , requiredTypes map [string ]bool , requiredValueSetBindings map [string ]bool , file * jen.File , fields * jen.Group , parentName string , elementDefinitions []fhir.ElementDefinition , start , level int ) (int , error ) {
321
+ func appendFields (resources ResourceMap , requiredTypes map [string ]bool , requiredValueSetBindings map [string ]bool ,
322
+ file * jen.File , fields * jen.Group , parentName string , elementDefinitions []fhir.ElementDefinition , start ,
323
+ level int ) (int , error ) {
322
324
//fmt.Printf("appendFields parentName=%s, start=%d, level=%d\n", parentName, start, level)
323
325
for i := start ; i < len (elementDefinitions ); i ++ {
324
326
element := elementDefinitions [i ]
@@ -346,88 +348,27 @@ func appendFields(resources ResourceMap, requiredTypes map[string]bool, required
346
348
}
347
349
statement .Id (typeIdentifier ).Tag (map [string ]string {"json" : pathParts [level ] + ",omitempty" , "bson" : pathParts [level ] + ",omitempty" })
348
350
}
349
- // support polymorphic elements later
350
351
case 1 :
351
- statement := fields .Id (name )
352
+ var err error
353
+ i , err = addFieldStatement (resources , requiredTypes , requiredValueSetBindings , file , fields ,
354
+ pathParts [level ], parentName , elementDefinitions , i , level , element .Type [0 ])
352
355
353
- switch element . Type [ 0 ]. Code {
354
- case "code" :
355
- if * element . Max == "*" {
356
- statement . Op ( "[]" )
357
- } else if * element . Min == 0 {
358
- statement . Op ( "*" )
359
- }
356
+ if err != nil {
357
+ return 0 , err
358
+ }
359
+ default : //polymorphic type
360
+ name = Replace ( pathParts [ level ], "[x]" , "" , - 1 )
361
+ for _ , eleType := range element . Type {
362
+ name := name + Title ( eleType . Code )
360
363
361
- if url := requiredValueSetBinding (element ); url != nil {
362
- if bytes := resources ["ValueSet" ][* url ]; bytes != nil {
363
- valueSet , err := fhir .UnmarshalValueSet (bytes )
364
- if err != nil {
365
- return 0 , err
366
- }
367
- if name := valueSet .Name ; name != nil {
368
- if ! namePattern .MatchString (* name ) {
369
- fmt .Printf ("Skip generating an enum for a ValueSet binding to `%s` because the ValueSet has a non-conforming name.\n " , * name )
370
- statement .Id ("string" )
371
- } else if len (valueSet .Compose .Include ) > 1 {
372
- fmt .Printf ("Skip generating an enum for a ValueSet binding to `%s` because the ValueSet includes more than one CodeSystem.\n " , * valueSet .Name )
373
- statement .Id ("string" )
374
- } else if codeSystemUrl := canonical (valueSet .Compose .Include [0 ]); resources ["CodeSystem" ][codeSystemUrl ] == nil {
375
- fmt .Printf ("Skip generating an enum for a ValueSet binding to `%s` because the ValueSet includes the non-existing CodeSystem with canonical URL `%s`.\n " , * valueSet .Name , codeSystemUrl )
376
- statement .Id ("string" )
377
- } else {
378
- requiredValueSetBindings [* url ] = true
379
- statement .Id (* name )
380
- }
381
- } else {
382
- return 0 , fmt .Errorf ("missing name in ValueSet with canonical URL `%s`" , * url )
383
- }
384
- } else {
385
- statement .Id ("string" )
386
- }
387
- } else {
388
- statement .Id ("string" )
389
- }
390
- case "Resource" :
391
- statement .Qual ("encoding/json" , "RawMessage" )
392
- default :
393
- if * element .Max == "*" {
394
- statement .Op ("[]" )
395
- } else if * element .Min == 0 {
396
- statement .Op ("*" )
397
- }
364
+ var err error
365
+ i , err = addFieldStatement (resources , requiredTypes , requiredValueSetBindings , file , fields ,
366
+ name , parentName , elementDefinitions , i , level , eleType )
398
367
399
- var typeIdentifier string
400
- if parentName == "Element" && name == "Id" ||
401
- parentName == "Extension" && name == "Url" {
402
- typeIdentifier = "string"
403
- } else {
404
- typeIdentifier = typeCodeToTypeIdentifier (element .Type [0 ].Code )
405
- }
406
- if typeIdentifier == "Element" || typeIdentifier == "BackboneElement" {
407
- backboneElementName := parentName + name
408
- statement .Id (backboneElementName )
409
- var err error
410
- file .Type ().Id (backboneElementName ).StructFunc (func (childFields * jen.Group ) {
411
- //var err error
412
- i , err = appendFields (resources , requiredTypes , requiredValueSetBindings , file , childFields , backboneElementName , elementDefinitions , i + 1 , level + 1 )
413
- })
414
- if err != nil {
415
- return 0 , err
416
- }
417
- i --
418
- } else {
419
- if unicode .IsUpper (rune (typeIdentifier [0 ])) {
420
- requiredTypes [typeIdentifier ] = true
421
- }
422
- statement .Id (typeIdentifier )
368
+ if err != nil {
369
+ return 0 , err
423
370
}
424
371
}
425
-
426
- if * element .Min == 0 {
427
- statement .Tag (map [string ]string {"json" : pathParts [level ] + ",omitempty" , "bson" : pathParts [level ] + ",omitempty" })
428
- } else {
429
- statement .Tag (map [string ]string {"json" : pathParts [level ], "bson" : pathParts [level ]})
430
- }
431
372
}
432
373
}
433
374
} else {
@@ -438,6 +379,105 @@ func appendFields(resources ResourceMap, requiredTypes map[string]bool, required
438
379
return 0 , nil
439
380
}
440
381
382
+ func addFieldStatement (
383
+ resources ResourceMap ,
384
+ requiredTypes map [string ]bool ,
385
+ requiredValueSetBindings map [string ]bool ,
386
+ file * jen.File ,
387
+ fields * jen.Group ,
388
+ name string ,
389
+ parentName string ,
390
+ elementDefinitions []fhir.ElementDefinition ,
391
+ elementIndex , level int ,
392
+ elementType fhir.ElementDefinitionType ,
393
+ ) (idx int , err error ) {
394
+ fieldName := Title (name )
395
+ element := elementDefinitions [elementIndex ]
396
+ statement := fields .Id (fieldName )
397
+
398
+ switch elementType .Code {
399
+ case "code" :
400
+ if * element .Max == "*" {
401
+ statement .Op ("[]" )
402
+ } else if * element .Min == 0 {
403
+ statement .Op ("*" )
404
+ }
405
+
406
+ if url := requiredValueSetBinding (element ); url != nil {
407
+ if bytes := resources ["ValueSet" ][* url ]; bytes != nil {
408
+ valueSet , err := fhir .UnmarshalValueSet (bytes )
409
+ if err != nil {
410
+ return 0 , err
411
+ }
412
+ if name := valueSet .Name ; name != nil {
413
+ if ! namePattern .MatchString (* name ) {
414
+ fmt .Printf ("Skip generating an enum for a ValueSet binding to `%s` because the ValueSet has a non-conforming name.\n " , * name )
415
+ statement .Id ("string" )
416
+ } else if len (valueSet .Compose .Include ) > 1 {
417
+ fmt .Printf ("Skip generating an enum for a ValueSet binding to `%s` because the ValueSet includes more than one CodeSystem.\n " , * valueSet .Name )
418
+ statement .Id ("string" )
419
+ } else if codeSystemUrl := canonical (valueSet .Compose .Include [0 ]); resources ["CodeSystem" ][codeSystemUrl ] == nil {
420
+ fmt .Printf ("Skip generating an enum for a ValueSet binding to `%s` because the ValueSet includes the non-existing CodeSystem with canonical URL `%s`.\n " , * valueSet .Name , codeSystemUrl )
421
+ statement .Id ("string" )
422
+ } else {
423
+ requiredValueSetBindings [* url ] = true
424
+ statement .Id (* name )
425
+ }
426
+ } else {
427
+ return 0 , fmt .Errorf ("missing name in ValueSet with canonical URL `%s`" , * url )
428
+ }
429
+ } else {
430
+ statement .Id ("string" )
431
+ }
432
+ } else {
433
+ statement .Id ("string" )
434
+ }
435
+ case "Resource" :
436
+ statement .Qual ("encoding/json" , "RawMessage" )
437
+ default :
438
+ if * element .Max == "*" {
439
+ statement .Op ("[]" )
440
+ } else if * element .Min == 0 {
441
+ statement .Op ("*" )
442
+ }
443
+
444
+ var typeIdentifier string
445
+ if parentName == "Element" && fieldName == "Id" ||
446
+ parentName == "Extension" && fieldName == "Url" {
447
+ typeIdentifier = "string"
448
+ } else {
449
+ typeIdentifier = typeCodeToTypeIdentifier (elementType .Code )
450
+ }
451
+ if typeIdentifier == "Element" || typeIdentifier == "BackboneElement" {
452
+ backboneElementName := parentName + fieldName
453
+ statement .Id (backboneElementName )
454
+ var err error
455
+ file .Type ().Id (backboneElementName ).StructFunc (func (childFields * jen.Group ) {
456
+ //var err error
457
+ elementIndex , err = appendFields (resources , requiredTypes , requiredValueSetBindings , file , childFields ,
458
+ backboneElementName , elementDefinitions , elementIndex + 1 , level + 1 )
459
+ })
460
+ if err != nil {
461
+ return 0 , err
462
+ }
463
+ elementIndex --
464
+ } else {
465
+ if unicode .IsUpper (rune (typeIdentifier [0 ])) {
466
+ requiredTypes [typeIdentifier ] = true
467
+ }
468
+ statement .Id (typeIdentifier )
469
+ }
470
+ }
471
+
472
+ if * element .Min == 0 {
473
+ statement .Tag (map [string ]string {"json" : name + ",omitempty" , "bson" : name + ",omitempty" })
474
+ } else {
475
+ statement .Tag (map [string ]string {"json" : name , "bson" : name })
476
+ }
477
+
478
+ return elementIndex , err
479
+ }
480
+
441
481
func requiredValueSetBinding (elementDefinition fhir.ElementDefinition ) * string {
442
482
if elementDefinition .Binding != nil {
443
483
binding := * elementDefinition .Binding
0 commit comments