Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion lib/access/access.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,23 @@ defmodule DiffoExample.Access do
Access - example Access domain
"""
use Ash.Domain,
otp_app: :diffo
otp_app: :diffo,
fragments: [Diffo.Provider.DomainFragment]

alias DiffoExample.Access.DslAccess
alias DiffoExample.Access.Shelf
alias DiffoExample.Access.Card
alias DiffoExample.Access.Cable
alias DiffoExample.Access.Path
alias DiffoExample.Access.CableCharacteristic
alias DiffoExample.Access.CardCharacteristic
alias DiffoExample.Access.ShelfCharacteristic
alias DiffoExample.Access.PathCharacteristic
alias DiffoExample.Access.LineCharacteristic
alias DiffoExample.Access.DslamCharacteristic
alias DiffoExample.Access.AggregateCharacteristic
alias DiffoExample.Access.CircuitCharacteristic
alias DiffoExample.Access.ConstraintsCharacteristic

domain do
description "An example showing how TMF Services and Resources for a fictional Access domain can be extended from the Provider domain"
Expand Down Expand Up @@ -59,5 +69,15 @@ defmodule DiffoExample.Access do
define :define_path, action: :define
define :relate_path, action: :relate
end

resource CableCharacteristic
resource CardCharacteristic
resource ShelfCharacteristic
resource PathCharacteristic
resource LineCharacteristic
resource DslamCharacteristic
resource AggregateCharacteristic
resource CircuitCharacteristic
resource ConstraintsCharacteristic
end
end
53 changes: 53 additions & 0 deletions lib/access/characteristic_changes.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# SPDX-FileCopyrightText: 2025 diffo_example contributors <https://github.com/diffo-dev/diffo_example/graphs.contributors>
#
# SPDX-License-Identifier: MIT

defmodule DiffoExample.Access.CharacteristicChanges do
@moduledoc """
Shared changeset helpers for Access characteristic update actions.

Characteristics store nested value structs (units, bandwidth profiles)
as flat attributes. These helpers map the nested argument shape onto
those attributes.
"""

alias Ash.Changeset

@doc """
Splits a `%{amount: a, unit: u}` argument into two attributes.

Returns the changeset unchanged when the argument is nil or not a map
with both keys.
"""
def set_unit(changeset, arg, amount_attr, unit_attr) do
case Changeset.get_argument(changeset, arg) do
%{amount: amount, unit: unit} ->
changeset
|> Changeset.force_change_attribute(amount_attr, amount)
|> Changeset.force_change_attribute(unit_attr, unit)

_ ->
changeset
end
end

@doc """
Splits a `%{downstream: d, upstream: u, units: units}` bandwidth-profile
argument into three attributes.

Returns the changeset unchanged when the argument is nil or not a map
with all three keys.
"""
def set_bandwidth_profile(changeset, arg, downstream_attr, upstream_attr, units_attr) do
case Changeset.get_argument(changeset, arg) do
%{downstream: d, upstream: u, units: units} ->
changeset
|> Changeset.force_change_attribute(downstream_attr, d)
|> Changeset.force_change_attribute(upstream_attr, u)
|> Changeset.force_change_attribute(units_attr, units)

_ ->
changeset
end
end
end
38 changes: 18 additions & 20 deletions lib/access/resources/cable.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@ defmodule DiffoExample.Access.Cable do
"""

alias Diffo.Provider.BaseInstance
alias Diffo.Provider.Instance.Relationship
alias Diffo.Provider.Instance.Characteristic
alias Diffo.Provider.Assigner
alias Diffo.Provider.Assignment

alias DiffoExample.Access
Expand All @@ -26,7 +23,7 @@ defmodule DiffoExample.Access.Cable do
plural_name :Cables
end

structure do
provider do
specification do
id "ce0a567a-6abb-4862-9e33-851fd79fa595"
name "cable"
Expand All @@ -36,14 +33,22 @@ defmodule DiffoExample.Access.Cable do
end

characteristics do
characteristic :cable, DiffoExample.Access.CableValue
characteristic :pairs, Diffo.Provider.AssignableValue
characteristic :cable, DiffoExample.Access.CableCharacteristic
end

pools do
pool :pairs, :pair
end
end

behaviour do
actions do
create :build
relationships do
source :all
target :all
end

behaviour do
actions do
create :build
end
end
end

Expand All @@ -64,11 +69,8 @@ defmodule DiffoExample.Access.Cable do
description "defines the cable"
argument :characteristic_value_updates, {:array, :term}

change after_action(fn changeset, result, _context ->
with {:ok, result} <- Characteristic.update_values(result, changeset),
{:ok, result} <- Access.get_cable_by_id(result.id),
do: {:ok, result}
end)
change set_attribute(:resource_state, :operating)
change DiffoExample.Changes.Define
end

update :relate do
Expand All @@ -86,11 +88,7 @@ defmodule DiffoExample.Access.Cable do
description "relates the cable with an instance by assigning a pair"
argument :assignment, :struct, constraints: [instance_of: Assignment]

change after_action(fn changeset, result, _context ->
with {:ok, result} <- Assigner.assign(result, changeset, :pairs, :pair),
{:ok, result} <- Access.get_cable_by_id(result.id),
do: {:ok, result}
end)
change {DiffoExample.Changes.Assign, pool: :pairs}
end
end
end
44 changes: 19 additions & 25 deletions lib/access/resources/card.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@ defmodule DiffoExample.Access.Card do
"""

alias Diffo.Provider.BaseInstance
alias Diffo.Provider.Instance.Relationship
alias Diffo.Provider.Instance.Characteristic
alias Diffo.Provider.Assigner
alias Diffo.Provider.Assignment

alias DiffoExample.Access
Expand All @@ -26,7 +23,7 @@ defmodule DiffoExample.Access.Card do
plural_name :Cards
end

structure do
provider do
specification do
id "cd29956f-6c68-44cc-bf54-705eb8d2f754"
name "card"
Expand All @@ -36,14 +33,22 @@ defmodule DiffoExample.Access.Card do
end

characteristics do
characteristic :card, DiffoExample.Access.CardValue
characteristic :ports, Diffo.Provider.AssignableValue
characteristic :card, DiffoExample.Access.CardCharacteristic
end

pools do
pool :ports, :port
end

relationships do
source :all
target :all
end
end

behaviour do
actions do
create :build
behaviour do
actions do
create :build
end
end
end

Expand All @@ -64,33 +69,22 @@ defmodule DiffoExample.Access.Card do
description "defines the card"
argument :characteristic_value_updates, {:array, :term}

change after_action(fn changeset, result, _context ->
with {:ok, result} <- Characteristic.update_values(result, changeset),
{:ok, result} <- Access.get_card_by_id(result.id),
do: {:ok, result}
end)
change set_attribute(:resource_state, :operating)
change DiffoExample.Changes.Define
end

update :relate do
description "relates the card with other instances"
argument :relationships, {:array, :struct}

change after_action(fn changeset, result, _context ->
with {:ok, result} <- Relationship.relate_instance(result, changeset),
{:ok, result} <- Access.get_card_by_id(result.id),
do: {:ok, result}
end)
change DiffoExample.Changes.Relate
end

update :assign_port do
description "relates the card with an instance by assigning a port"
argument :assignment, :struct, constraints: [instance_of: Assignment]

change after_action(fn changeset, result, _context ->
with {:ok, result} <- Assigner.assign(result, changeset, :ports, :port),
{:ok, result} <- Access.get_card_by_id(result.id),
do: {:ok, result}
end)
change {DiffoExample.Changes.Assign, pool: :ports}
end
end
end
119 changes: 119 additions & 0 deletions lib/access/resources/characteristic_values/cable_characteristic.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# SPDX-FileCopyrightText: 2025 diffo_example contributors <https://github.com/diffo-dev/diffo_example/graphs.contributors>
#
# SPDX-License-Identifier: MIT

defmodule DiffoExample.Access.CableCharacteristic do
@moduledoc "Typed characteristic for a Cable's physical properties."
use Ash.Resource,
fragments: [Diffo.Provider.BaseCharacteristic],
domain: DiffoExample.Access

alias DiffoExample.Access.CharacteristicChanges

resource do
description "Typed characteristic carrying cable physical property fields"
plural_name :cable_characteristics
end

actions do
create :create do
accept [:name, :pairs, :length_amount, :length_unit, :loss_amount, :loss_unit, :technology]
argument :instance_id, :uuid
argument :feature_id, :uuid
change manage_relationship(:instance_id, :instance, type: :append)
change manage_relationship(:feature_id, :feature, type: :append)
end

update :update do
accept [:pairs, :technology, :length_amount, :length_unit, :loss_amount, :loss_unit]
argument :length, :term, allow_nil?: true
argument :loss, :term, allow_nil?: true

change fn changeset, _ ->
changeset
|> CharacteristicChanges.set_unit(:length, :length_amount, :length_unit)
|> CharacteristicChanges.set_unit(:loss, :loss_amount, :loss_unit)
end
end
end

attributes do
attribute :pairs, :integer, public?: true
attribute :length_amount, :integer, public?: true
attribute :length_unit, :atom, public?: true
attribute :loss_amount, :float, public?: true
attribute :loss_unit, :atom, public?: true
attribute :technology, :atom, public?: true
end

calculations do
calculate :value,
Diffo.Type.CharacteristicValue,
DiffoExample.Access.CableCharacteristic.ValueCalculation do
public? true
end
end

preparations do
prepare build(load: [:value])
end

jason do
pick [:name, :value]
compact true
end
end

defmodule DiffoExample.Access.CableCharacteristic.Value do
@moduledoc false
use Ash.TypedStruct, extensions: [AshJason.TypedStruct, AshOutstanding.TypedStruct]

alias DiffoExample.Access.IntegerUnit
alias DiffoExample.Access.FloatUnit

jason do
pick [:pairs, :length, :loss, :technology]
compact true
end

outstanding do
expect [:pairs, :loss]
end

typed_struct do
field :pairs, :integer
field :length, IntegerUnit
field :loss, FloatUnit
field :technology, :atom
end
end

defmodule DiffoExample.Access.CableCharacteristic.ValueCalculation do
@moduledoc false
use Ash.Resource.Calculation

alias DiffoExample.Access.IntegerUnit
alias DiffoExample.Access.FloatUnit
alias DiffoExample.Access.CableCharacteristic

@impl true
def load(_, _, _), do: []

@impl true
def calculate(records, _, _) do
Enum.map(records, fn r ->
%CableCharacteristic.Value{
pairs: r.pairs,
length:
if r.length_amount do
%IntegerUnit{amount: r.length_amount, unit: r.length_unit}
end,
loss:
if r.loss_amount do
%FloatUnit{amount: r.loss_amount, unit: r.loss_unit}
end,
technology: r.technology
}
end)
end
end
Loading
Loading