Current section

Files

Jump to
ocpp_model lib ocpp_model.ex
Raw

lib/ocpp_model.ex

defmodule OcppModel do
@moduledoc """
OcppModel Module: Contains helper functions
"""
@spec to_struct(map, atom | struct()) :: struct()
@doc """
Converts a Map into a struct of the given kind
"""
def to_struct(map, kind) when is_map(map) do
struct = struct(kind)
map_to_struct = fn {k, _}, acc ->
case Map.fetch(map, k) do
{:ok, v} -> %{acc | k => v}
:error -> acc
end
end
struct |> Map.to_list() |> Enum.reduce(struct, map_to_struct)
end
@spec to_map!(struct()) :: map()
@doc """
Converts a struct into a map including any nested structs
"""
def to_map!(st, filter_empty \\ true) when is_struct(st) do
struct_to_map = fn {k, v}, acc ->
cond do
is_list(v) -> Map.put_new(acc, k, v |> Enum.map(&to_map!(&1)))
is_struct(v) -> Map.put_new(acc, k, to_map!(v))
is_nil(v) && filter_empty -> acc
true -> Map.put_new(acc, k, v)
end
end
st |> Map.from_struct() |> Enum.reduce(%{}, struct_to_map)
end
@spec to_map(
{{:ok, struct()}, any()}
| {{:error, atom(), String.t()}, any()}
) ::
{{:ok, map()}, any()}
| {{:error, atom(), String.t()}, any()}
@doc """
same as `to_map!()` but takes an `{{:ok, struct()}, state}` and returns an `{{:ok, map()}, state}`
in case of een `{{:error, atom(), String.t()}, state}` argument it will let it pass through
"""
def to_map({{:ok, st}, state}) when is_struct(st), do: {{:ok, to_map!(st)}, state}
def to_map({{:error, error, desc}, state}), do: {{:error, error, desc}, state}
@doc """
Transforms the payload into a struct and calls the implemented behaviour function and returns the response back into a map
the implemented behaviour can alter the state if it wants to
"""
def execute(payload, model, method, state) do
payload
|> to_struct(model)
|> method.(state)
|> to_map()
end
end