defmodule Sorcery.Src.Utils do use Norm alias Sorcery.Specs.Primative, as: T @contract remove_dels_from_db(T.db(), coll_of({T.tk(), T.id()})) :: T.db() def remove_dels_from_db(db, dels) do Enum.reduce(dels, db, fn {tk, id}, acc -> case Map.get(acc, tk) do nil -> acc table -> table = Map.delete(table, id) Map.put(acc, tk, table) end end) end @contract all_ids(T.src(), T.tk()) :: coll_of(T.id()) def all_ids(%{original_db: db1, changes_db: db2, deletes: dels}, tk) do db1 = remove_dels_from_db(db1, dels) db2 = remove_dels_from_db(db2, dels) table1 = Map.get(db1, tk, %{}) table2 = Map.get(db2, tk, %{}) ids1 = Map.keys(table1) |> MapSet.new() ids2 = Map.keys(table2) |> MapSet.new() MapSet.union(ids1, ids2) |> MapSet.to_list() end @contract entities_set(T.src()) :: coll_of({T.tk(), T.id()}) def entities_set(%{original_db: og, changes_db: ch, deletes: del}) do delset = MapSet.new(del) oset = Enum.reduce(og, MapSet.new(), fn {tk, table}, acc -> ids = Map.keys(table) Enum.reduce(ids, acc, fn id, acc -> MapSet.put(acc, {tk, id}) end) end) Enum.reduce(ch, oset, fn {tk, table}, acc -> ids = Map.keys(table) Enum.reduce(ids, acc, fn id, acc -> MapSet.put(acc, {tk, id}) end) end) |> MapSet.difference(delset) end end