defmodule HL7.Path do
defstruct segment: nil,
segment_number: nil,
field: nil,
repetition: nil,
component: nil,
subcomponent: nil,
truncate: false,
data: nil,
path: nil
@type level() :: :segment | :field | :repetition | :component | :subcomponent
@type t() :: %__MODULE__{}
@doc ~S"""
Generates an `~p` sigil data structure at runtime.
## Examples
iex> HL7.Examples.wikipedia_sample_hl7()
...> |> HL7.new!()
...> |> HL7.get(HL7.Path.new("OBX-5"))
"1.80"
"""
def new(path) do
import HL7.PathParser
{:ok, data, _, _, _, _} = parse(path)
path_map =
%__MODULE__{}
|> Map.merge(Map.new(data, fn {k, v} -> {k, List.first(v)} end))
|> apply_default_repetition()
|> apply_default_segment_number()
%__MODULE__{
path_map
| path: path,
data: get_data(path, path_map)
}
end
defp apply_default_segment_number(%__MODULE__{segment: nil} = path_map) do
path_map
end
defp apply_default_segment_number(%__MODULE__{segment_number: nil} = path_map) do
Map.put(path_map, :segment_number, 1)
end
defp apply_default_segment_number(%__MODULE__{} = path_map) do
path_map
end
defp apply_default_repetition(%__MODULE__{field: nil, repetition: r} = path_map) do
if is_nil(r) do
path_map
else
raise ArgumentError,
"HL7.Path cannot contain a repetition without a field or segment number with a segment"
end
end
defp apply_default_repetition(%__MODULE__{repetition: nil} = path_map) do
Map.put(path_map, :repetition, 1)
end
defp apply_default_repetition(%__MODULE__{} = path_map) do
path_map
end
# temporary backwards compatibility data for `HL7.Query` paths, to be deprecated in the future
defp get_data(path, %__MODULE__{} = path_map) do
repetition =
cond do
String.contains?(path, "[") and is_integer(path_map.repetition) -> path_map.repetition - 1
path_map.component || path_map.subcomponent -> 0
true -> nil
end
m = %__MODULE__{path_map | repetition: repetition}
indices =
cond do
m.subcomponent -> [m.field, m.repetition, m.component - 1, m.subcomponent - 1]
m.component -> [m.field, m.repetition, m.component - 1]
m.repetition -> [m.field, m.repetition]
m.field -> [m.field]
true -> []
end
if m.segment, do: {m.segment, indices}, else: indices
end
end
defimpl Inspect, for: HL7.Path do
def inspect(%HL7.Path{path: path}, _opts) do
"~p[" <> path <> "]"
end
end