Current section

Files

Jump to
diffo lib diffo provider components characteristic.ex
Raw

lib/diffo/provider/components/characteristic.ex

# SPDX-FileCopyrightText: 2025 diffo contributors <https://github.com/diffo-dev/diffo/graphs.contributors>
#
# SPDX-License-Identifier: MIT
defmodule Diffo.Provider.Characteristic do
@moduledoc """
Ash Resource for a TMF Characteristic
"""
use Ash.Resource,
otp_app: :diffo,
domain: Diffo.Provider,
data_layer: AshNeo4j.DataLayer,
extensions: [
AshOutstanding.Resource,
AshJason.Resource,
Diffo.Provider.Characteristic.Extension
]
resource do
description "An Ash Resource for a TMF Characteristic"
plural_name :characteristics
end
neo4j do
relate [
{:instance, :HAS, :incoming, :Instance},
{:feature, :HAS, :incoming, :Feature},
{:relationship, :HAS, :incoming, :Relationship}
]
guard [
{:HAS, :incoming, :Instance},
{:HAS, :incoming, :Feature},
{:HAS, :incoming, :Relationship}
]
end
jason do
pick [:name, :value, :values]
compact true
end
outstanding do
expect [:name]
customize fn outstanding, expected, actual ->
key = if expected.is_array, do: :values, else: :value
expected_val = Map.get(expected, key)
val_out =
if actual == nil do
expected_val
else
Outstanding.outstanding(expected_val, Map.get(actual, key))
end
cond do
val_out == nil ->
outstanding
outstanding == nil ->
%{key => val_out}
|> Outstand.map_to_struct(Diffo.Provider.Characteristic)
|> Ash.Test.strip_metadata()
true ->
Map.put(outstanding, key, val_out)
end
end
end
actions do
defaults [:destroy]
create :create do
description "creates a characteristic"
accept [:name, :value, :values, :is_array, :type]
end
read :read do
primary? true
end
read :find_by_name do
description "finds characteristics by name"
get? false
argument :query, :ci_string do
description "Return only characteristics with names including the given value."
end
filter expr(contains(name, ^arg(:query)))
end
read :list do
description "lists all characteristics"
end
update :update do
primary? true
description "updates the characteristic value or instance, feature or relationship"
accept [:value, :values, :is_array]
argument :instance_id, :uuid
argument :feature_id, :uuid
argument :relationship_id, :uuid
change manage_relationship(:instance_id, :instance, type: :append_and_remove)
change manage_relationship(:feature_id, :feature, type: :append_and_remove)
change manage_relationship(:relationship_id, :relationship, type: :append_and_remove)
end
end
attributes do
uuid_primary_key :id do
description "a uuid4, unique to this characteristic, generated by default"
public? false
end
attribute :name, :atom do
description "the name of this characteristic"
allow_nil? false
public? true
end
attribute :value, Diffo.Type.Value do
description "the value of the characteristic"
constraints Diffo.Type.Value.subtype_constraints()
allow_nil? true
public? true
end
attribute :values, {:array, Diffo.Type.Value} do
description "the array of values of the characteristic"
constraints items: Diffo.Type.Value.subtype_constraints()
allow_nil? true
public? true
end
attribute :is_array, :boolean do
description "true when this characteristic holds an array of values; defaults false"
default false
allow_nil? false
public? true
end
attribute :type, :atom do
description "the type of the characteristic"
allow_nil? false
public? true
constraints one_of: [:instance, :feature, :relationship]
end
create_timestamp :created_at
update_timestamp :updated_at
end
relationships do
belongs_to :instance, Diffo.Provider.Instance do
description "the instance the characteristic defines"
allow_nil? true
public? true
end
belongs_to :feature, Diffo.Provider.Feature do
description "the feature the characteristic defines"
allow_nil? true
public? true
end
belongs_to :relationship, Diffo.Provider.Relationship do
description "the relationship the characteristic defines"
allow_nil? true
public? true
end
end
identities do
identity :feature_characteristic_uniqueness, [:feature_id, :name] do
message "feature has duplicate characteristic"
pre_check? true
end
identity :instance_characteristic_uniqueness, [:instance_id, :name] do
message "instance has duplicate characteristic"
pre_check? true
end
identity :relationship_characteristic_uniqueness, [:relationship_id, :name] do
message "relationship has duplicate characteristic"
pre_check? true
end
end
validations do
validate present([:instance_id, :feature_id, :relationship_id], at_most: 1) do
message "characteristic must be related to at most one of an instance, feature or relationship"
end
validate present([:value, :values], at_most: 1) do
message "characteristic must have at most one of value or values"
end
end
preparations do
prepare build(sort: [name: :asc])
end
defimpl Diffo.Unwrap do
def unwrap(%{values: values}) when is_list(values), do: Diffo.Unwrap.unwrap(values)
def unwrap(%{value: value}), do: Diffo.Unwrap.unwrap(value)
end
end