defmodule Archeometer.Reports.Section do
@moduledoc """
Represents a Section, which is part of a Page.
"""
require Logger
use Archeometer.Repo
alias Archeometer.Reports.Fragment
defstruct [:id, :desc, fragments: []]
defmodule Definition do
@moduledoc """
Represents the definition of a Section.
"""
defstruct [:id, :desc, fragments: []]
end
def process(%__MODULE__.Definition{} = sdef, bindings, db_name \\ default_db_name()) do
Logger.debug("Processing section #{sdef.id}")
{fragments, _} =
Enum.reduce(sdef.fragments, {[], bindings, []}, fn fdef, acc ->
validate_fragment_input(fdef, acc, db_name)
end)
|> Tuple.delete_at(2)
res = struct(__MODULE__, Map.from_struct(sdef))
%{res | fragments: fragments}
end
defp validate_fragment_input(fdef, {_, _, empty_bindings} = acc, db_name) do
if Enum.member?(empty_bindings, fdef.receives) do
process_empty_fragment(fdef, acc, db_name)
else
process_fragment(fdef, acc, db_name)
end
end
defp process_empty_fragment(fdef, acc, db_name) do
Map.put(fdef, :query_type, :empty_input)
|> process_fragment(acc, db_name)
end
defp process_fragment(
%Fragment.Definition{result_type: :table} = fdef,
{results, bindings, empty_bindings},
db_name
) do
fragment = Fragment.process(fdef, bindings, db_name)
assign_bindings(fragment, fdef, bindings, empty_bindings, results)
end
defp process_fragment(
%Fragment.Definition{} = fdef,
{results, bindings, empty_bindings},
db_name
) do
fragment = Fragment.process(fdef, bindings, db_name)
{results ++ [fragment], bindings, empty_bindings}
end
defp assign_bindings(
%{result: %{values: []}} = fragment,
fdef,
bindings,
empty_bindings,
results
) do
new_bindings = new_bindings(bindings, fdef.result_name, fragment.result)
{results ++ [fragment], new_bindings, [empty_bindings | [fdef.result_name]]}
end
defp assign_bindings(fragment, fdef, bindings, empty_bindings, results) do
new_bindings = new_bindings(bindings, fdef.result_name, fragment.result)
{results ++ [fragment], new_bindings, empty_bindings}
end
defp new_bindings(bindings, :none, _value) do
bindings
end
defp new_bindings(bindings, name, value) do
[{name, to_binding_val(value)} | bindings]
end
defp to_binding_val(table) when is_map(table) do
table.values |> Enum.join(" ")
end
end