Skip to content

Commit 8acef8d

Browse files
IGNT-7 Add serializers for resources
1 parent 24c7407 commit 8acef8d

File tree

687 files changed

+47030
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

687 files changed

+47030
-0
lines changed

src/fhir/generator/generate_classes.py

+17
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ def main() -> int:
5454
data_dir: Path = Path(__file__).parent.joinpath("./")
5555
fhir_dir = Path(__file__).parent.joinpath("../")
5656
classes_dir: Path = fhir_dir.joinpath("classes/4_0_0/")
57+
serializers_dir: Path = fhir_dir.joinpath("serializers/4_0_0")
5758

5859
# clean out old stuff
5960
classes_resources_folder = classes_dir.joinpath("resources")
@@ -70,6 +71,22 @@ def main() -> int:
7071
if os.path.exists(classes_backbone_elements_folder):
7172
shutil.rmtree(classes_backbone_elements_folder)
7273
os.mkdir(classes_backbone_elements_folder)
74+
75+
# clean out old stuff for serializers
76+
serializers_resources_folder = serializers_dir.joinpath("resources")
77+
if os.path.exists(serializers_resources_folder):
78+
shutil.rmtree(serializers_resources_folder)
79+
os.mkdir(serializers_resources_folder)
80+
81+
serializers_complex_types_folder = serializers_dir.joinpath("complex_types")
82+
if os.path.exists(serializers_complex_types_folder):
83+
shutil.rmtree(serializers_complex_types_folder)
84+
os.mkdir(serializers_complex_types_folder)
85+
86+
serializers_backbone_elements_folder = serializers_dir.joinpath("backbone_elements")
87+
if os.path.exists(serializers_backbone_elements_folder):
88+
shutil.rmtree(serializers_backbone_elements_folder)
89+
os.mkdir(serializers_backbone_elements_folder)
7390

7491
fhir_entities: List[FhirEntity] = FhirXmlSchemaParser.generate_classes()
7592

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# This file implements the code generator for generating schema and resolvers for FHIR
2+
# It reads the FHIR XML schema and generates resolvers in the resolvers folder and schema in the schema folder
3+
4+
import os
5+
import shutil
6+
from os import path
7+
from pathlib import Path
8+
from typing import Union, List, Dict, Any
9+
10+
from fhir_xml_schema_parser import FhirXmlSchemaParser
11+
from search_parameters import search_parameter_queries
12+
from fhir_xml_schema_parser import FhirEntity
13+
14+
15+
def my_copytree(
16+
src: Union[Path, str],
17+
dst: Union[Path, str],
18+
symlinks: bool = False,
19+
# ignore: Union[
20+
# None,
21+
# Callable[[str, List[str]], Iterable[str]],
22+
# Callable[[Union[str, os.PathLike[str]], List[str]], Iterable[str]],
23+
# ] = None,
24+
) -> None:
25+
for item in os.listdir(src):
26+
s = os.path.join(src, item)
27+
d = os.path.join(dst, item)
28+
if os.path.isdir(s):
29+
shutil.copytree(s, d, symlinks)
30+
else:
31+
shutil.copy2(s, d)
32+
33+
34+
def clean_duplicate_lines(file_path: Union[Path, str]) -> None:
35+
print(f"Removing duplicate lines from {file_path}")
36+
with open(file_path, "r") as file:
37+
lines: List[str] = file.readlines()
38+
new_lines: List[str] = []
39+
for line in lines:
40+
if (
41+
not line.strip()
42+
or not line.lstrip().startswith("from")
43+
or (
44+
line not in new_lines
45+
and line.lstrip() not in [c.lstrip() for c in new_lines]
46+
)
47+
):
48+
new_lines.append(line)
49+
with open(file_path, "w") as file:
50+
file.writelines(new_lines)
51+
52+
53+
def main() -> int:
54+
data_dir: Path = Path(__file__).parent.joinpath("./")
55+
fhir_dir = Path(__file__).parent.joinpath("../")
56+
serializers_dir: Path = fhir_dir.joinpath("serializers/4_0_0/")
57+
template_name = 'template.javascript.class_serializer.index.jinja2'
58+
59+
# clean out old stuff
60+
serializers_resources_folder = serializers_dir.joinpath("resources")
61+
indexFilePath = serializers_resources_folder.joinpath("index.js")
62+
if os.path.exists(indexFilePath):
63+
os.remove(indexFilePath)
64+
65+
serializers_complex_types_folder = serializers_dir.joinpath("complex_types")
66+
complexTypeIndexFilePath = serializers_complex_types_folder.joinpath("index.js")
67+
if os.path.exists(complexTypeIndexFilePath):
68+
os.remove(complexTypeIndexFilePath)
69+
70+
fhir_entities: List[FhirEntity] = [f for f in FhirXmlSchemaParser.generate_classes() if f.is_resource]
71+
72+
with open(data_dir.joinpath(template_name), "r") as file:
73+
template_contents = file.read()
74+
from jinja2 import Template
75+
76+
file_path = indexFilePath
77+
template = Template(
78+
template_contents, trim_blocks=True, lstrip_blocks=True
79+
)
80+
result = template.render(
81+
fhir_entities=fhir_entities,
82+
)
83+
if not path.exists(file_path):
84+
with open(file_path, "w") as file2:
85+
file2.write(result)
86+
87+
fhir_entities: List[FhirEntity] = [f for f in FhirXmlSchemaParser.generate_classes()
88+
if f.type_ == "Element" and f.cleaned_name != "Resource"]
89+
90+
with open(data_dir.joinpath(template_name), "r") as file:
91+
template_contents = file.read()
92+
from jinja2 import Template
93+
94+
file_path = complexTypeIndexFilePath
95+
template = Template(
96+
template_contents, trim_blocks=True, lstrip_blocks=True
97+
)
98+
result = template.render(
99+
fhir_entities=fhir_entities,
100+
)
101+
if not path.exists(file_path):
102+
with open(file_path, "w") as file2:
103+
file2.write(result)
104+
105+
return 0
106+
107+
108+
if __name__ == "__main__":
109+
exit(main())
+225
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
# This file implements the code generator for generating schema and resolvers for FHIR
2+
# It reads the FHIR XML schema and generates resolvers in the resolvers folder and schema in the schema folder
3+
4+
import os
5+
import shutil
6+
from os import path
7+
from pathlib import Path
8+
from typing import Union, List, Dict, Any
9+
10+
from fhir_xml_schema_parser import FhirXmlSchemaParser
11+
from search_parameters import search_parameter_queries
12+
from fhir_xml_schema_parser import FhirEntity
13+
14+
15+
def my_copytree(
16+
src: Union[Path, str],
17+
dst: Union[Path, str],
18+
symlinks: bool = False,
19+
# ignore: Union[
20+
# None,
21+
# Callable[[str, List[str]], Iterable[str]],
22+
# Callable[[Union[str, os.PathLike[str]], List[str]], Iterable[str]],
23+
# ] = None,
24+
) -> None:
25+
for item in os.listdir(src):
26+
s = os.path.join(src, item)
27+
d = os.path.join(dst, item)
28+
if os.path.isdir(s):
29+
shutil.copytree(s, d, symlinks)
30+
else:
31+
shutil.copy2(s, d)
32+
33+
34+
def clean_duplicate_lines(file_path: Union[Path, str]) -> None:
35+
print(f"Removing duplicate lines from {file_path}")
36+
with open(file_path, "r") as file:
37+
lines: List[str] = file.readlines()
38+
new_lines: List[str] = []
39+
for line in lines:
40+
if (
41+
not line.strip()
42+
or not line.lstrip().startswith("from")
43+
or (
44+
line not in new_lines
45+
and line.lstrip() not in [c.lstrip() for c in new_lines]
46+
)
47+
):
48+
new_lines.append(line)
49+
with open(file_path, "w") as file:
50+
file.writelines(new_lines)
51+
52+
53+
def main() -> int:
54+
data_dir: Path = Path(__file__).parent.joinpath("./")
55+
fhir_dir = Path(__file__).parent.joinpath("../")
56+
serializers_dir: Path = fhir_dir.joinpath("serializers/4_0_0/")
57+
serializer_template_file_name = 'template.javascript.class_serializer.jinja2'
58+
59+
# clean out old stuff for serializers
60+
serializers_resources_folder = serializers_dir.joinpath("resources")
61+
if os.path.exists(serializers_resources_folder):
62+
shutil.rmtree(serializers_resources_folder)
63+
os.mkdir(serializers_resources_folder)
64+
65+
serializers_complex_types_folder = serializers_dir.joinpath("complex_types")
66+
if os.path.exists(serializers_complex_types_folder):
67+
shutil.rmtree(serializers_complex_types_folder)
68+
os.mkdir(serializers_complex_types_folder)
69+
70+
serializers_backbone_elements_folder = serializers_dir.joinpath("backbone_elements")
71+
if os.path.exists(serializers_backbone_elements_folder):
72+
shutil.rmtree(serializers_backbone_elements_folder)
73+
os.mkdir(serializers_backbone_elements_folder)
74+
75+
fhir_entities: List[FhirEntity] = FhirXmlSchemaParser.generate_classes()
76+
77+
# now print the result
78+
for fhir_entity in fhir_entities:
79+
# use template to generate new code files
80+
resource_name: str = fhir_entity.cleaned_name
81+
entity_file_name = fhir_entity.name_snake_case
82+
if fhir_entity.is_value_set: # valueset
83+
pass
84+
85+
elif fhir_entity.is_resource:
86+
search_parameters_for_all_resources: Dict[str, Dict[str, Any]] = (
87+
search_parameter_queries.get("Resource", {}) if fhir_entity.fhir_name != "Resource" else {}
88+
)
89+
search_parameters_for_current_resource: Dict[str, Dict[str, Any]] = (
90+
search_parameter_queries.get(fhir_entity.fhir_name, {})
91+
)
92+
# write Javascript classes
93+
with open(data_dir.joinpath(serializer_template_file_name), "r") as file:
94+
template_contents = file.read()
95+
from jinja2 import Template
96+
97+
file_path = serializers_resources_folder.joinpath(f"{entity_file_name}.js")
98+
print(f"Writing domain resource: {entity_file_name} to {file_path}...")
99+
template = Template(
100+
template_contents, trim_blocks=True, lstrip_blocks=True
101+
)
102+
result = template.render(
103+
fhir_entity=fhir_entity,
104+
search_parameters_for_all_resources=search_parameters_for_all_resources,
105+
search_parameters_for_current_resource=search_parameters_for_current_resource,
106+
extra_properties=[
107+
{
108+
"name": "_access",
109+
"type": "Object"
110+
},
111+
{
112+
"name": "_sourceAssigningAuthority",
113+
"type": "string"
114+
},
115+
{
116+
"name": "_uuid",
117+
"type": "string"
118+
},
119+
{
120+
"name": "_sourceId",
121+
"type": "string"
122+
}
123+
]
124+
)
125+
if not path.exists(file_path):
126+
with open(file_path, "w") as file2:
127+
file2.write(result)
128+
elif fhir_entity.type_ == "BackboneElement" or fhir_entity.is_back_bone_element:
129+
with open(data_dir.joinpath(serializer_template_file_name), "r") as file:
130+
template_contents = file.read()
131+
from jinja2 import Template
132+
133+
file_path = serializers_backbone_elements_folder.joinpath(f"{entity_file_name}.js")
134+
print(f"Writing back bone class: {entity_file_name} to {file_path}...")
135+
template = Template(
136+
template_contents, trim_blocks=True, lstrip_blocks=True
137+
)
138+
result = template.render(
139+
fhir_entity=fhir_entity,
140+
)
141+
if not path.exists(file_path):
142+
with open(file_path, "w") as file2:
143+
file2.write(result)
144+
elif fhir_entity.is_extension: # valueset
145+
# write Javascript classes
146+
with open(data_dir.joinpath(serializer_template_file_name), "r") as file:
147+
template_contents = file.read()
148+
from jinja2 import Template
149+
150+
file_path = serializers_complex_types_folder.joinpath(f"{entity_file_name}.js")
151+
print(f"Writing extension as complex type: {entity_file_name} to {file_path}...")
152+
template = Template(
153+
template_contents, trim_blocks=True, lstrip_blocks=True
154+
)
155+
result = template.render(
156+
fhir_entity=fhir_entity
157+
)
158+
if not path.exists(file_path):
159+
with open(file_path, "w") as file2:
160+
file2.write(result)
161+
elif fhir_entity.type_ == "Element": # valueset
162+
# write Javascript classes
163+
with open(data_dir.joinpath(serializer_template_file_name), "r") as file:
164+
template_contents = file.read()
165+
from jinja2 import Template
166+
167+
file_path = serializers_complex_types_folder.joinpath(f"{entity_file_name}.js")
168+
print(f"Writing complex type: {entity_file_name} to {file_path}...")
169+
template = Template(
170+
template_contents, trim_blocks=True, lstrip_blocks=True
171+
)
172+
extra_properties = [
173+
{
174+
"name": "_file_id",
175+
"type": "string"
176+
}
177+
] if entity_file_name == "attachment" else []
178+
result = template.render(
179+
fhir_entity=fhir_entity,
180+
extra_properties_for_reference=[
181+
{
182+
"name": "_sourceAssigningAuthority",
183+
"type": "string"
184+
},
185+
{
186+
"name": "_uuid",
187+
"type": "string"
188+
},
189+
{
190+
"name": "_sourceId",
191+
"type": "string"
192+
}
193+
],
194+
extra_properties=extra_properties,
195+
extra_properties_for_json=extra_properties
196+
)
197+
if not path.exists(file_path):
198+
with open(file_path, "w") as file2:
199+
file2.write(result)
200+
elif fhir_entity.type_ in ["Quantity"]: # valueset
201+
with open(data_dir.joinpath(serializer_template_file_name), "r") as file:
202+
template_contents = file.read()
203+
from jinja2 import Template
204+
205+
file_path = serializers_complex_types_folder.joinpath(f"{entity_file_name}.js")
206+
print(f"Writing complex_type: {entity_file_name} to {file_path}...")
207+
template = Template(
208+
template_contents, trim_blocks=True, lstrip_blocks=True
209+
)
210+
result = template.render(
211+
fhir_entity=fhir_entity,
212+
)
213+
214+
if not path.exists(file_path):
215+
with open(file_path, "w") as file2:
216+
file2.write(result)
217+
else:
218+
print(f"{resource_name}: {fhir_entity.type_} is not supported")
219+
# print(result)
220+
221+
return 0
222+
223+
224+
if __name__ == "__main__":
225+
exit(main())
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// This file is auto-generated by generate_classes so do not edit manually
2+
{% macro lower_case_first_letter(text) %}
3+
{{- text[0]|lower }}{{ text[1:] -}}
4+
{% endmacro %}
5+
{% macro upper_case_first_letter(text) %}
6+
{{- text[0]|upper }}{{ text[1:] -}}
7+
{% endmacro %}
8+
9+
{% for fhir_entity in fhir_entities %}
10+
const {{ fhir_entity.cleaned_name | lower }}Serializer = require('./{{ lower_case_first_letter(fhir_entity.cleaned_name) }}');
11+
{% endfor %}
12+
13+
module.exports = {
14+
{% for fhir_entity in fhir_entities %}
15+
{{ fhir_entity.cleaned_name | lower }}Serializer,
16+
{% endfor %}
17+
};
18+
19+

0 commit comments

Comments
 (0)