-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #28 from halprin/polymorphism
Polymorphism
Showing
28 changed files
with
468 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
package context | ||
|
||
import ( | ||
_ "embed" | ||
"encoding/json" | ||
) | ||
|
||
//go:generate go run generate.go | ||
|
||
type Definition struct { | ||
Version string `json:"version"` | ||
Resources map[string]ResourceTypeDefinition `json:"resources"` | ||
} | ||
|
||
type ResourceTypeDefinition struct { | ||
Name string `json:"name"` | ||
Fields map[string]FieldTypes | ||
} | ||
|
||
type FieldTypes struct { | ||
Name string `json:"name"` | ||
Types []string `json:"types"` | ||
} | ||
|
||
//go:embed R5.json | ||
var r5json string | ||
|
||
//go:embed R4B.json | ||
var r4bjson string | ||
|
||
//go:embed R4.json | ||
var r4json string | ||
|
||
//go:embed STU3.json | ||
var stu3json string | ||
|
||
//go:embed DSTU2.json | ||
var dstu2json string | ||
|
||
var r5 Definition | ||
var r4b Definition | ||
var r4 Definition | ||
var stu3 Definition | ||
var dstu2 Definition | ||
|
||
func init() { | ||
|
||
if len(r5json) == 0 { | ||
return | ||
} | ||
|
||
err := json.Unmarshal([]byte(r5json), &r5) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
if len(r4bjson) == 0 { | ||
return | ||
} | ||
|
||
err = json.Unmarshal([]byte(r4bjson), &r4b) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
if len(r4json) == 0 { | ||
return | ||
} | ||
|
||
err = json.Unmarshal([]byte(r4json), &r4) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
if len(stu3json) == 0 { | ||
return | ||
} | ||
|
||
err = json.Unmarshal([]byte(stu3json), &stu3) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
if len(dstu2json) == 0 { | ||
return | ||
} | ||
|
||
err = json.Unmarshal([]byte(dstu2json), &dstu2) | ||
if err != nil { | ||
panic(err) | ||
} | ||
} | ||
|
||
func R5() Definition { | ||
return r5 | ||
} | ||
|
||
func R4B() Definition { | ||
return r4b | ||
} | ||
|
||
func R4() Definition { | ||
return r4 | ||
} | ||
|
||
func STU3() Definition { | ||
return stu3 | ||
} | ||
|
||
func DSTU2() Definition { | ||
return dstu2 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
//go:build ignore | ||
|
||
package main | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"github.com/halprin/fhirpath/context" | ||
"golang.org/x/net/html" | ||
"io" | ||
"log" | ||
"net/http" | ||
"os" | ||
) | ||
|
||
type structureDefinition struct { | ||
Name string `json:"name"` | ||
Snapshot struct { | ||
Element []struct { | ||
Path string `json:"path"` | ||
Type []struct { | ||
Code string `json:"code"` | ||
} `json:"type"` | ||
} `json:"element"` | ||
} `json:"snapshot"` | ||
} | ||
|
||
func main() { | ||
|
||
fhirVersions := []string{ | ||
"R5", | ||
"R4B", | ||
"R4", | ||
"STU3", | ||
"DSTU2", | ||
} | ||
|
||
for _, version := range fhirVersions { | ||
err := constructTypesForFhirVersion(version) | ||
if err != nil { | ||
log.Fatalf("Error occured during construction of context definitions: %s", err.Error()) | ||
} | ||
} | ||
} | ||
|
||
func constructTypesForFhirVersion(fhirVersion string) error { | ||
log.Printf("Constructing types for FHIR version %s\n", fhirVersion) | ||
|
||
resources, err := getResourcesForVersion(fhirVersion) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
resourceDefinitions := make([]structureDefinition, 0, len(resources)) | ||
|
||
for _, resource := range resources { | ||
resourceDefinition, err := fetchStructureDefinition(fhirVersion, resource) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
resourceDefinitions = append(resourceDefinitions, resourceDefinition) | ||
} | ||
|
||
log.Printf("Converting structure definitions to our definitions for FHIR version %s\n", fhirVersion) | ||
|
||
types := context.Definition{ | ||
Version: fhirVersion, | ||
Resources: map[string]context.ResourceTypeDefinition{}, | ||
} | ||
|
||
for _, resourceDefinition := range resourceDefinitions { | ||
resource := context.ResourceTypeDefinition{ | ||
Name: resourceDefinition.Name, | ||
Fields: map[string]context.FieldTypes{}, | ||
} | ||
|
||
for _, elem := range resourceDefinition.Snapshot.Element { | ||
field := context.FieldTypes{Name: elem.Path} | ||
for _, currentType := range elem.Type { | ||
field.Types = append(field.Types, currentType.Code) | ||
} | ||
resource.Fields[field.Name] = field | ||
} | ||
|
||
types.Resources[resource.Name] = resource | ||
} | ||
|
||
log.Printf("Marshalling our definitions into JSON for FHIR version %s\n", fhirVersion) | ||
|
||
jsonData, err := json.Marshal(types) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
path := fmt.Sprintf("%s.json", fhirVersion) | ||
|
||
log.Printf("Writing JSON data to file %s for FHIR version %s\n", path, fhirVersion) | ||
|
||
err = os.WriteFile(path, jsonData, 0644) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func getResourcesForVersion(fhirVersion string) ([]string, error) { | ||
log.Printf("Downloading FHIR resource list for version %s\n", fhirVersion) | ||
|
||
url := fmt.Sprintf("https://hl7.org/fhir/%s/resourcelist.html", fhirVersion) | ||
|
||
response, err := http.Get(url) | ||
if err != nil { | ||
return nil, err | ||
} | ||
defer response.Body.Close() | ||
|
||
resources := make([]string, 0) | ||
|
||
log.Printf("Parsing FHIR resources for FHIR version %s\n", fhirVersion) | ||
|
||
tokenizer := html.NewTokenizer(response.Body) | ||
|
||
var isInAlphabeticalDivTag bool | ||
var isInResourceATag bool | ||
|
||
for { | ||
tokenType := tokenizer.Next() | ||
|
||
switch { | ||
case tokenType == html.ErrorToken: | ||
return resources, nil | ||
case tokenType == html.StartTagToken: | ||
token := tokenizer.Token() | ||
if isInAlphabeticalDivTag && token.Data == "a" { | ||
for _, attribute := range token.Attr { | ||
if attribute.Key == "title" && attribute.Val != "Maturity Level" && attribute.Val != "Normative Content" { | ||
isInResourceATag = true | ||
} | ||
} | ||
} | ||
if token.Data == "div" { | ||
for _, attribute := range token.Attr { | ||
if attribute.Key == "id" && attribute.Val == "tabs-2" { // tab-2 is the alphabetical listing of resources | ||
isInAlphabeticalDivTag = true | ||
} | ||
} | ||
} | ||
case tokenType == html.EndTagToken: | ||
token := tokenizer.Token() | ||
if isInAlphabeticalDivTag && token.Data == "div" { | ||
isInAlphabeticalDivTag = false | ||
} | ||
if isInResourceATag && token.Data == "a" { | ||
isInResourceATag = false | ||
} | ||
case tokenType == html.TextToken: | ||
if isInResourceATag { | ||
token := tokenizer.Token() | ||
resources = append(resources, token.Data) | ||
} | ||
} | ||
} | ||
} | ||
|
||
func fetchStructureDefinition(fhirVersion string, resource string) (structureDefinition, error) { | ||
log.Printf("Fetching structure definition for FHIR version %s, resource %s\n", fhirVersion, resource) | ||
|
||
url := fmt.Sprintf("https://hl7.org/fhir/%s/%s.profile.json", fhirVersion, resource) | ||
|
||
response, err := http.Get(url) | ||
if err != nil { | ||
return structureDefinition{}, err | ||
} | ||
defer response.Body.Close() | ||
|
||
responseBody, err := io.ReadAll(response.Body) | ||
if err != nil { | ||
return structureDefinition{}, err | ||
} | ||
|
||
log.Printf("Parsing structure definition for FHIR version %s, resource %s\n", fhirVersion, resource) | ||
|
||
var resourceDefinition structureDefinition | ||
err = json.Unmarshal(responseBody, &resourceDefinition) | ||
if err != nil { | ||
return structureDefinition{}, err | ||
} | ||
|
||
return resourceDefinition, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.