Current section
Files
Jump to
Current section
Files
lib/tungsten/payload_transformer.ex
defmodule Tungsten.PayloadTransformer do
@moduledoc """
Transforms payloads from and into Tungsten maps
"""
alias Tungsten.Codegen.{Property, Type}
@spec from_cdp([Property.t(), ...], map()) :: map()
def from_cdp(properties, payload) do
payload
|> Enum.map(fn {key, value} ->
property = Enum.find(properties, fn property -> property.name == key end)
case property do
nil ->
{key, value}
%Property{tungsten_name: key, type: type} ->
{key, transform_value_from_cdp(type, value)}
end
end)
|> Enum.into(%{})
end
@spec transform_value_from_cdp(Type.t(), any()) :: any()
def transform_value_from_cdp(type, value)
def transform_value_from_cdp(%Type{type: :array, item_type: %Type{} = type}, value)
when is_list(value) do
Enum.map(value, &transform_value_from_cdp(type, &1))
end
def transform_value_from_cdp(%Type{type: :object, properties: properties}, value)
when is_list(properties) and is_map(value),
do: from_cdp(properties, value)
def transform_value_from_cdp(%Type{type: :string, enum: enum_mappings}, value)
when is_list(enum_mappings) do
case Enum.find(enum_mappings, fn {cdp, _tungsten} -> cdp == value end) do
nil -> value
{_cdp, tungsten} -> tungsten
end
end
def transform_value_from_cdp(%Type{type: :reference, refers_to: {_scope, mod, fun}}, value),
do: transform_value_from_cdp(apply(mod, fun, []), value)
def transform_value_from_cdp(%Type{type: :any}, value), do: value
def transform_value_from_cdp(%Type{type: :number}, value), do: value
def transform_value_from_cdp(%Type{type: :integer}, value), do: value
def transform_value_from_cdp(%Type{type: :boolean}, value), do: value
def transform_value_from_cdp(%Type{type: :string, enum: nil}, value), do: "#{value}"
def transform_value_from_cdp(%Type{type: :array}, value), do: value
def transform_value_from_cdp(%Type{type: :object, properties: nil}, value), do: value
@spec from_tungsten([Property.t(), ...], map()) :: map()
def from_tungsten(properties, payload) do
payload
|> Enum.map(fn {key, value} ->
property = Enum.find(properties, fn property -> property.tungsten_name == key end)
case property do
nil ->
{key, value}
%Property{name: key, type: type} ->
{key, transform_value_from_tungsten(type, value)}
end
end)
|> Enum.into(%{})
end
@spec transform_value_from_tungsten(Type.t(), any()) :: any()
def transform_value_from_tungsten(type, value)
def transform_value_from_tungsten(
%Type{type: :reference, refers_to: {_scope, mod, fun}},
value
) do
transform_value_from_tungsten(apply(mod, fun, []), value)
end
def transform_value_from_tungsten(%Type{type: :array, item_type: %Type{} = type}, value)
when is_list(value) do
Enum.map(value, &transform_value_from_tungsten(type, &1))
end
def transform_value_from_tungsten(%Type{type: :object, properties: properties}, value)
when is_list(properties) and is_map(value),
do: from_tungsten(properties, value)
def transform_value_from_tungsten(%Type{type: :string, enum: enum_mappings}, value)
when is_list(enum_mappings) do
case Enum.find(enum_mappings, fn {_cdp, tungsten} -> tungsten == value end) do
nil -> value
{cdp, _tungsten} -> cdp
end
end
def transform_value_from_tungsten(%Type{type: :any}, value), do: value
def transform_value_from_tungsten(%Type{type: :number}, value), do: value
def transform_value_from_tungsten(%Type{type: :integer}, value), do: value
def transform_value_from_tungsten(%Type{type: :boolean}, value), do: value
def transform_value_from_tungsten(%Type{type: :string, enum: nil}, value), do: value
def transform_value_from_tungsten(%Type{type: :array}, value), do: value
def transform_value_from_tungsten(%Type{type: :object, properties: nil}, value), do: value
end