Packages
hl7v2
0.5.0
3.10.1
3.9.0
3.8.0
3.7.0
3.6.0
3.5.0
3.4.0
3.3.6
3.3.5
3.3.4
3.3.3
3.3.2
3.3.1
3.3.0
3.2.0
3.1.1
3.1.0
3.0.2
3.0.1
3.0.0
2.11.0
2.10.0
2.9.1
2.9.0
2.8.2
2.8.1
2.8.0
2.7.1
2.7.0
2.6.0
2.5.0
2.4.0
2.3.0
2.2.0
2.1.3
2.1.2
2.1.1
2.1.0
1.4.6
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.0
1.2.0
1.1.0
1.0.0
0.6.0
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.1.0
Pure Elixir HL7 v2.x toolkit — schema-driven parsing, typed segments, message builder, MLLP transport
Current section
Files
Jump to
Current section
Files
lib/hl7v2/validation/field_rules.ex
defmodule HL7v2.Validation.FieldRules do
@moduledoc """
Field-level validation rules for HL7v2 typed segments.
For each typed segment struct, checks:
- Required fields (`:r` optionality) are not nil
- Repeating fields with bounded `max_reps` do not exceed the limit
"""
@doc """
Returns a list of field-level validation errors/warnings for a single segment.
Skips validation for:
- `HL7v2.Segment.ZXX` (site-defined, no typed fields)
- Raw tuples `{name, fields}` (not typed)
"""
@spec check(struct() | {binary(), list()}) :: [map()]
def check(%HL7v2.Segment.ZXX{}), do: []
def check({name, _fields}) when is_binary(name), do: []
def check(%{__struct__: module} = segment) do
location = module.segment_id()
field_defs = module.fields()
Enum.flat_map(field_defs, fn {_seq, name, _type, optionality, max_reps} ->
value = Map.get(segment, name)
required_errors(location, name, optionality, value) ++
max_reps_warnings(location, name, max_reps, value)
end)
end
defp required_errors(location, name, :r, value) do
if semantic_blank?(value) do
[
%{
level: :error,
location: location,
field: name,
message: "required field #{name} is missing"
}
]
else
[]
end
end
defp required_errors(_location, _name, _optionality, _value), do: []
# A value is semantically blank if it's nil, an empty list, or a struct
# where every field is nil (e.g., %XPN{} with all nil fields).
defp semantic_blank?(nil), do: true
defp semantic_blank?([]), do: true
defp semantic_blank?(list) when is_list(list) do
Enum.all?(list, &semantic_blank?/1)
end
defp semantic_blank?(struct) when is_struct(struct) do
struct
|> Map.from_struct()
|> Map.values()
|> Enum.all?(&is_nil/1)
end
defp semantic_blank?(_), do: false
defp max_reps_warnings(location, name, max_reps, value)
when is_integer(max_reps) and max_reps > 1 and is_list(value) do
if length(value) > max_reps do
[
%{
level: :warning,
location: location,
field: name,
message: "field #{name} has #{length(value)} repetitions, max allowed is #{max_reps}"
}
]
else
[]
end
end
defp max_reps_warnings(_location, _name, _max_reps, _value), do: []
end