104 lines
2.5 KiB
Elixir
104 lines
2.5 KiB
Elixir
defmodule Kindling.Schema.Resource do
|
|
alias Kindling.Config
|
|
|
|
@empty_properties %{array: [], const: [], has_one: [], has_many: [], enum: [], value: []}
|
|
|
|
def properties(df) do
|
|
df["properties"]
|
|
end
|
|
|
|
def grouped_properties(df) do
|
|
properties =
|
|
(df["properties"] || %{})
|
|
|> Map.delete("id")
|
|
|> Enum.reject(&is_element/1)
|
|
|> Enum.map(fn {key, value} -> {key, value, property_type(value)} end)
|
|
|> Enum.group_by(fn {_key, _value, type} ->
|
|
type
|
|
end)
|
|
|
|
Map.merge(@empty_properties, properties)
|
|
end
|
|
|
|
def all_fields(df) do
|
|
(df["properties"] || %{})
|
|
|> Enum.filter(fn {_name, definition} ->
|
|
property_type(definition) in [:array, :enum, :value]
|
|
end)
|
|
|> Enum.map(fn {name, _} -> name end)
|
|
end
|
|
|
|
def required_fields(df) do
|
|
df
|
|
|> required()
|
|
|> Enum.filter(fn {_name, definition} ->
|
|
property_type(definition) in [:array, :enum, :value]
|
|
end)
|
|
|> Enum.map(fn {name, _} -> name end)
|
|
end
|
|
|
|
def required(df) do
|
|
Map.take(df["properties"] || %{}, df["required"] || [])
|
|
end
|
|
|
|
def required?(df, key) do
|
|
key in df["required"]
|
|
end
|
|
|
|
def property_type(%{"const" => _}), do: :const
|
|
|
|
for embed <- Config.embedded_resources() do
|
|
dbg(embed)
|
|
|
|
def property_type(%{"$ref" => "#/definitions/" <> unquote(embed)}), do: :embed_one
|
|
|
|
def property_type(%{"items" => %{"$ref" => "#/definitions/" <> unquote(embed)}}) do
|
|
:embed_many
|
|
end
|
|
end
|
|
|
|
def property_type(%{"$ref" => "#/definitions/" <> name}) do
|
|
if is_class_name(name) do
|
|
:has_one
|
|
else
|
|
:value
|
|
end
|
|
end
|
|
|
|
def property_type(%{"items" => %{"$ref" => "#/definitions/" <> name}}) do
|
|
if is_class_name(name) do
|
|
:has_many
|
|
else
|
|
:array
|
|
end
|
|
end
|
|
|
|
def property_type(%{"items" => %{"enum" => _}}), do: :array
|
|
def property_type(%{"enum" => _}), do: :enum
|
|
def property_type(_), do: :value
|
|
|
|
def refs(df) do
|
|
(df["properties"] || %{})
|
|
|> Enum.map(fn
|
|
{_, %{"$ref" => "#/definitions/" <> name}} ->
|
|
name
|
|
|
|
{_, %{"items" => %{"$ref" => "#/definitions/" <> name}}} ->
|
|
name
|
|
|
|
_other ->
|
|
nil
|
|
end)
|
|
|> Enum.reject(&is_nil/1)
|
|
|> Enum.filter(&is_class_name/1)
|
|
|> MapSet.new()
|
|
end
|
|
|
|
def is_class_name(name) do
|
|
!(name in Config.embedded_resources()) && Regex.match?(~r/^[A-Z]/, name)
|
|
end
|
|
|
|
def is_element({_name, %{"$ref" => "#/definitions/Element"}}), do: true
|
|
def is_element({name, %{"items" => items}}), do: is_element({name, items})
|
|
def is_element(_), do: false
|
|
end
|