rdf-ex/lib/rdf/blank_node/generator.ex
2018-08-29 21:26:13 +02:00

87 lines
2.5 KiB
Elixir

defmodule RDF.BlankNode.Generator do
@moduledoc """
A GenServer generates `RDF.BlankNode`s using a `RDF.BlankNode.Generator.Algorithm`.
"""
use GenServer
# Client API ###############################################################
@doc """
Starts a blank node generator linked to the current process.
The state will be initialized according to the given `RDF.BlankNode.Generator.Algorithm`.
"""
def start_link(generation_mod, init_opts \\ %{}) do
GenServer.start_link(__MODULE__, {generation_mod, convert_opts(init_opts)})
end
@doc """
Starts a blank node generator process without links (outside of a supervision tree).
The state will be initialized according to the given `RDF.BlankNode.Generator.Algorithm`.
"""
def start(generation_mod, init_opts \\ %{}) do
GenServer.start(__MODULE__, {generation_mod, convert_opts(init_opts)})
end
defp convert_opts(nil), do: %{}
defp convert_opts(opts) when is_list(opts), do: Map.new(opts)
defp convert_opts(opts) when is_map(opts), do: opts
@doc """
Synchronously stops the blank node generator with the given `reason`.
It returns `:ok` if the agent terminates with the given reason. If the agent
terminates with another reason, the call will exit.
This function keeps OTP semantics regarding error reporting.
If the reason is any other than `:normal`, `:shutdown` or `{:shutdown, _}`, an
error report will be logged.
"""
def stop(pid, reason \\ :normal, timeout \\ :infinity) do
GenServer.stop(pid, reason, timeout)
end
@doc """
Generates a new blank node according to the `RDF.BlankNode.Generator.Algorithm` set up.
"""
def generate(pid) do
GenServer.call(pid, :generate)
end
@doc """
Generates a blank node for a given value according to the `RDF.BlankNode.Generator.Algorithm` set up.
"""
def generate_for(pid, value) do
GenServer.call(pid, {:generate_for, value})
end
# Server Callbacks #########################################################
@impl GenServer
def init({generation_mod, init_opts}) do
{:ok, {generation_mod, generation_mod.init(init_opts)}}
end
@impl GenServer
def handle_call(:generate, _from, {generation_mod, state}) do
with {bnode, new_state} = generation_mod.generate(state) do
{:reply, bnode, {generation_mod, new_state}}
end
end
@impl GenServer
def handle_call({:generate_for, string}, _from, {generation_mod, state}) do
with {bnode, new_state} = generation_mod.generate_for(string, state) do
{:reply, bnode, {generation_mod, new_state}}
end
end
end