Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions fhircraft/fhir/resources/factory/builders/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,7 @@ def resolve_type(
def build_primitive_extension_placeholder(
self,
node: ElementNode,
name: str | None = None,
) -> FieldInformation:
"""
Build a placeholder field information for primitive type extensions.
Expand All @@ -450,14 +451,16 @@ def build_primitive_extension_placeholder(

Args:
node: ElementNode representing the primitive FHIR element for which to create an extension placeholder.
name: When provided, use this name instead of ``node.name``

Returns:
FieldInformation: Field information for the extension placeholder
"""

# Process the name for the placeholder field
original_name = f"_{node.name}"
placeholder_name = f"{node.name}_ext"
name = name if name is not None else node.name
original_name = f"_{name}"
placeholder_name = f"{name}_ext"
safe_placeholder_name, ext_alias = self.handle_python_keyword(placeholder_name)

# Get the appropriate Element type for the placeholder field
Expand All @@ -470,7 +473,7 @@ def build_primitive_extension_placeholder(
default=None,
alias=original_name,
validation_alias=ext_alias,
description=f"Placeholder element for {node.name} extensions",
description=f"Placeholder element for {name} extensions",
)
return info

Expand Down
4 changes: 3 additions & 1 deletion fhircraft/fhir/resources/factory/builders/type_choice.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ def build(self, node: ElementNode, _: DefinitionIndex) -> Build:

# Add primitive extension field if applicable
if field_type_info.requires_primitive_extension:
placeholder = self.build_primitive_extension_placeholder(node)
placeholder = self.build_primitive_extension_placeholder(
node, name=safe_name
)
build.fields.append(placeholder)

# Type-choice validator & property go on the first FieldBuild
Expand Down
49 changes: 46 additions & 3 deletions test/test_fhir_resources_factory_builders_type_choice.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ def test_build__primitive_type_adds_ext_placeholder(builder, index):
node = make_node("value", type_codes=["string"])
result = builder.build(node, index)
names = [f.name for f in result.fields]
assert "value_ext" in names
assert "valueString_ext" in names


def test_build__non_primitive_type_does_not_add_placeholder(builder, index):
Expand All @@ -229,8 +229,51 @@ def test_build__non_primitive_type_does_not_add_placeholder(builder, index):
def test_build__primitive_placeholder_alias_is_underscore_name(builder, index):
node = make_node("value", type_codes=["string"])
result = builder.build(node, index)
placeholder = next(f for f in result.fields if f.name == "value_ext")
assert placeholder.alias == "_value"
placeholder = next(f for f in result.fields if f.name == "valueString_ext")
assert placeholder.alias == "_valueString"


def test_build__primitive_type_ext_placeholder_does_not_use_base_name(builder, index):
"""No base-name _ext placeholder should be emitted for a type-choice element."""
node = make_node("value", type_codes=["string"])
result = builder.build(node, index)
names = [f.name for f in result.fields]
assert "value_ext" not in names


def test_build__primitive_type_ext_placeholder_uses_typed_name(builder, index):
"""Ext placeholder for a type-choice primitive must use the full typed field name."""
node = make_node("value", type_codes=["string"])
result = builder.build(node, index)
names = [f.name for f in result.fields]
assert "valueString_ext" in names


def test_build__primitive_type_ext_placeholder_alias_uses_typed_name(builder, index):
"""Ext placeholder alias must be the underscore-prefixed typed field name."""
node = make_node("value", type_codes=["string"])
result = builder.build(node, index)
placeholder = next(f for f in result.fields if f.name == "valueString_ext")
assert placeholder.alias == "_valueString"


def test_build__two_primitives_ext_placeholders_use_typed_names(builder, index):
"""Each primitive type choice variant gets its own correctly named _ext placeholder."""
node = make_node("value", type_codes=["string", "boolean"])
result = builder.build(node, index)
ext_names = [f.name for f in result.fields if f.name.endswith("_ext")]
assert "valueString_ext" in ext_names
assert "valueBoolean_ext" in ext_names
assert "value_ext" not in ext_names


def test_build__different_base_name_primitive_ext_uses_typed_name(builder, index):
"""The correctly-typed _ext placeholder is generated regardless of the base name."""
node = make_node("effective", type_codes=["dateTime"])
result = builder.build(node, index)
names = [f.name for f in result.fields]
assert "effectiveDateTime_ext" in names
assert "effective_ext" not in names


def test_build__two_types_one_primitive_adds_exactly_one_placeholder(builder, index):
Expand Down
Loading