core: RDF.Dataset.graph/2 and RDF.Graph.description/2

and other minor refactorings
This commit is contained in:
Marcel Otto 2017-02-19 01:34:01 +01:00
parent e5c8043cc2
commit d2019eef58
2 changed files with 46 additions and 29 deletions

View file

@ -256,6 +256,12 @@ defmodule RDF.Dataset do
end end
end end
@doc """
The graph with given name.
"""
def graph(%RDF.Dataset{graphs: graphs}, graph_name),
do: Map.get(graphs, Quad.convert_graph_context(graph_name))
@doc """ @doc """
The default graph of a `RDF.Dataset`. The default graph of a `RDF.Dataset`.
""" """

View file

@ -94,11 +94,12 @@ defmodule RDF.Graph do
def add(%RDF.Graph{name: name, descriptions: descriptions}, def add(%RDF.Graph{name: name, descriptions: descriptions},
subject, predicate, object) do subject, predicate, object) do
with triple_subject = Triple.convert_subject(subject), with subject = Triple.convert_subject(subject) do
updated_descriptions = Map.update(descriptions, triple_subject, updated_descriptions =
Description.new({triple_subject, predicate, object}), fn description -> Map.update(descriptions, subject,
description |> Description.add({predicate, object}) Description.new({subject, predicate, object}), fn description ->
end) do description |> Description.add({predicate, object})
end)
%RDF.Graph{name: name, descriptions: updated_descriptions} %RDF.Graph{name: name, descriptions: updated_descriptions}
end end
end end
@ -139,13 +140,15 @@ defmodule RDF.Graph do
""" """
def put(%RDF.Graph{name: name, descriptions: descriptions}, def put(%RDF.Graph{name: name, descriptions: descriptions},
subject, predicate, objects) do subject, predicate, objects) do
with triple_subject = Triple.convert_subject(subject) do with subject = Triple.convert_subject(subject) do
new_description = case descriptions[triple_subject] do new_description = case descriptions[subject] do
desc = %Description{} -> Description.put(desc, predicate, objects) %Description{} = description ->
nil -> Description.new(triple_subject, predicate, objects) Description.put(description, predicate, objects)
nil ->
Description.new(subject, predicate, objects)
end end
%RDF.Graph{name: name, %RDF.Graph{name: name,
descriptions: Map.put(descriptions, triple_subject, new_description)} descriptions: Map.put(descriptions, subject, new_description)}
end end
end end
@ -160,7 +163,7 @@ defmodule RDF.Graph do
""" """
def put(graph, statements) def put(graph, statements)
def put(graph = %RDF.Graph{}, {subject, predicate, object}), def put(%RDF.Graph{} = graph, {subject, predicate, object}),
do: put(graph, subject, predicate, object) do: put(graph, subject, predicate, object)
def put(%RDF.Graph{name: name, descriptions: descriptions}, def put(%RDF.Graph{name: name, descriptions: descriptions},
@ -172,27 +175,28 @@ defmodule RDF.Graph do
descriptions: Map.put(descriptions, subject, description)} descriptions: Map.put(descriptions, subject, description)}
end end
def put(graph = %RDF.Graph{}, statements) when is_map(statements) do def put(%RDF.Graph{} = graph, statements) when is_map(statements) do
Enum.reduce statements, graph, fn ({subject, predications}, graph) -> Enum.reduce statements, graph, fn ({subject, predications}, graph) ->
put(graph, subject, predications) put(graph, subject, predications)
end end
end end
def put(graph = %RDF.Graph{}, statements) when is_list(statements) do def put(%RDF.Graph{} = graph, statements) when is_list(statements) do
put(graph, Enum.group_by(statements, &(elem(&1, 0)), fn {_, p, o} -> {p, o} end)) put(graph, Enum.group_by(statements, &(elem(&1, 0)), fn {_, p, o} -> {p, o} end))
end end
def put(%RDF.Graph{name: name, descriptions: descriptions}, subject, predications) def put(%RDF.Graph{name: name, descriptions: descriptions}, subject, predications)
when is_list(predications) do when is_list(predications) do
with subject = Triple.convert_subject(subject) do with subject = Triple.convert_subject(subject) do
description = Map.get(descriptions, subject, Description.new(subject)) description =
new_descriptions = descriptions Map.get(descriptions, subject, Description.new(subject))
|> Map.put(subject, Description.put(description, predications)) new_descriptions =
Map.put(descriptions, subject, Description.put(description, predications))
%RDF.Graph{name: name, descriptions: new_descriptions} %RDF.Graph{name: name, descriptions: new_descriptions}
end end
end end
def put(graph, subject, predications = {_predicate, _objects}), def put(graph, subject, {_predicate, _objects} = predications),
do: put(graph, subject, [predications]) do: put(graph, subject, [predications])
@ -228,13 +232,20 @@ defmodule RDF.Graph do
iex> RDF.Graph.get(RDF.Graph.new, EX.Foo, :bar) iex> RDF.Graph.get(RDF.Graph.new, EX.Foo, :bar)
:bar :bar
""" """
def get(graph = %RDF.Graph{}, subject, default \\ nil) do def get(%RDF.Graph{} = graph, subject, default \\ nil) do
case fetch(graph, subject) do case fetch(graph, subject) do
{:ok, value} -> value {:ok, value} -> value
:error -> default :error -> default
end end
end end
@doc """
The `RDF.Description` of the given subject.
"""
def description(%RDF.Graph{descriptions: descriptions}, subject),
do: Map.get(descriptions, Triple.convert_subject(subject))
@doc """ @doc """
Gets and updates the description of the given subject, in a single pass. Gets and updates the description of the given subject, in a single pass.
@ -257,13 +268,13 @@ defmodule RDF.Graph do
...> end) ...> end)
{RDF.Description.new(EX.S, EX.P, EX.O), RDF.Graph.new(EX.S, EX.P, EX.NEW)} {RDF.Description.new(EX.S, EX.P, EX.O), RDF.Graph.new(EX.S, EX.P, EX.NEW)}
""" """
def get_and_update(graph = %RDF.Graph{}, subject, fun) do def get_and_update(%RDF.Graph{} = graph, subject, fun) do
with triple_subject = Triple.convert_subject(subject) do with subject = Triple.convert_subject(subject) do
case fun.(get(graph, triple_subject)) do case fun.(get(graph, subject)) do
{old_description, new_description} -> {old_description, new_description} ->
{old_description, put(graph, triple_subject, new_description)} {old_description, put(graph, subject, new_description)}
:pop -> :pop ->
pop(graph, triple_subject) pop(graph, subject)
other -> other ->
raise "the given function must return a two-element tuple or :pop, got: #{inspect(other)}" raise "the given function must return a two-element tuple or :pop, got: #{inspect(other)}"
end end
@ -283,7 +294,7 @@ defmodule RDF.Graph do
iex> RDF.Graph.pop(RDF.Graph.new({EX.S, EX.P, EX.O}), EX.Missing) iex> RDF.Graph.pop(RDF.Graph.new({EX.S, EX.P, EX.O}), EX.Missing)
{nil, RDF.Graph.new({EX.S, EX.P, EX.O})} {nil, RDF.Graph.new({EX.S, EX.P, EX.O})}
""" """
def pop(graph = %RDF.Graph{name: name, descriptions: descriptions}, subject) do def pop(%RDF.Graph{name: name, descriptions: descriptions} = graph, subject) do
case Access.pop(descriptions, Triple.convert_subject(subject)) do case Access.pop(descriptions, Triple.convert_subject(subject)) do
{nil, _} -> {nil, _} ->
{nil, graph} {nil, graph}
@ -425,8 +436,8 @@ defmodule RDF.Graph do
def include?(%RDF.Graph{descriptions: descriptions}, def include?(%RDF.Graph{descriptions: descriptions},
triple = {subject, _, _}) do triple = {subject, _, _}) do
with triple_subject = Triple.convert_subject(subject), with subject = Triple.convert_subject(subject),
%Description{} <- description = descriptions[triple_subject] do %Description{} <- description = descriptions[subject] do
Description.include?(description, triple) Description.include?(description, triple)
else else
_ -> false _ -> false
@ -439,18 +450,18 @@ defmodule RDF.Graph do
def reduce(%RDF.Graph{descriptions: descriptions}, {:cont, acc}, _fun) def reduce(%RDF.Graph{descriptions: descriptions}, {:cont, acc}, _fun)
when map_size(descriptions) == 0, do: {:done, acc} when map_size(descriptions) == 0, do: {:done, acc}
def reduce(graph = %RDF.Graph{}, {:cont, acc}, fun) do def reduce(%RDF.Graph{} = graph, {:cont, acc}, fun) do
{triple, rest} = RDF.Graph.pop(graph) {triple, rest} = RDF.Graph.pop(graph)
reduce(rest, fun.(triple, acc), fun) reduce(rest, fun.(triple, acc), fun)
end end
def reduce(_, {:halt, acc}, _fun), do: {:halted, acc} def reduce(_, {:halt, acc}, _fun), do: {:halted, acc}
def reduce(graph = %RDF.Graph{}, {:suspend, acc}, fun) do def reduce(%RDF.Graph{} = graph, {:suspend, acc}, fun) do
{:suspended, acc, &reduce(graph, &1, fun)} {:suspended, acc, &reduce(graph, &1, fun)}
end end
def pop(graph = %RDF.Graph{descriptions: descriptions}) def pop(%RDF.Graph{descriptions: descriptions} = graph)
when descriptions == %{}, do: {nil, graph} when descriptions == %{}, do: {nil, graph}
def pop(%RDF.Graph{name: name, descriptions: descriptions}) do def pop(%RDF.Graph{name: name, descriptions: descriptions}) do