defmodule UsCongress.BillDtd.Shape do @doc """ `&combine/2` is used to combine a sequence of nodes, once `end_element` is found. """ def combine( %{scheme: "enum", body: enum} = former, %{label: "header", measure: [header], params: %{}} = current ), do: %{scheme: "header", enum: former.body, body: header} def combine( %{measure: measure} = former, %{scheme: s, body: b} = current ), do: former |> Map.put(:measure, [current | measure]) def combine( %{scheme: a_scheme, body: a_body}, %{scheme: b_scheme, body: b_body} = b ), do: b |> Map.put(a_scheme, a_body) def combine( %{measure: measure} = basis, %{measure: _measure} = current ) do current = Map.put(current, :measure, current.measure |> Enum.reverse) basis |> Map.put(:measure, [current | measure]) end @doc """ `&merge/2` is used to merge a sequence of nodes, before `end_element` is found. In practice this only seems to apply on the `characters` event. """ def merge(%{measure: measure} = prior, current) when is_bitstring(current) do prior |> Map.put(:measure, [current | measure]) end @doc """ """ def scheme(%{ label: name, measure: [body], params: params}) do %{ scheme: name, body: body } end def reshape(label) when is_atom(label), do: Atom.to_string(label) def reshape(label) when is_binary(label), do: label def reshape(l) when is_list(l), do: l |> Enum.map(&reshape/1) def reshape(record) when is_map(record) do record = if Map.has_key?(record, :params) and Map.size(record.params) == 0, do: Map.delete(record, :params), else: record record = if Map.has_key?(record, :measure) do if length(record.measure) == 0, do: Map.delete(record, :measure), else: Map.put(record, :measure, record.measure |> Enum.reverse) else record end record |> Map.new(fn {l, n} -> { reshape(l), reshape(n) } end) end end