2016-10-15 16:26:56 +00:00
|
|
|
defmodule RDF.Triple do
|
|
|
|
@moduledoc """
|
|
|
|
Defines a RDF Triple.
|
|
|
|
|
|
|
|
A Triple is a plain Elixir tuple consisting of three valid RDF values for
|
|
|
|
subject, predicate and object.
|
|
|
|
"""
|
|
|
|
|
|
|
|
alias RDF.{BlankNode, Literal}
|
|
|
|
|
|
|
|
@type subject :: URI.t | BlankNode.t
|
|
|
|
@type predicate :: URI.t
|
|
|
|
@type object :: URI.t | BlankNode.t | Literal.t
|
|
|
|
|
|
|
|
@type convertible_subject :: subject | atom | String.t
|
|
|
|
@type convertible_predicate :: predicate | atom | String.t
|
|
|
|
@type convertible_object :: object | atom | String.t # TODO: all basic Elixir types convertible to Literals
|
|
|
|
|
|
|
|
@doc """
|
|
|
|
Creates a `RDF.Triple` with proper RDF values.
|
|
|
|
|
|
|
|
An error is raised when the given elements are not convertible to RDF values.
|
|
|
|
|
|
|
|
Note: The `RDF.triple` function is a shortcut to this function.
|
|
|
|
|
|
|
|
# Examples
|
|
|
|
|
|
|
|
iex> RDF.Triple.new("http://example.com/S", "http://example.com/p", 42)
|
2017-04-10 01:06:20 +00:00
|
|
|
{~I<http://example.com/S>, ~I<http://example.com/p>, RDF.literal(42)}
|
2016-10-15 16:26:56 +00:00
|
|
|
"""
|
|
|
|
def new(subject, predicate, object) do
|
|
|
|
{
|
|
|
|
convert_subject(subject),
|
|
|
|
convert_predicate(predicate),
|
|
|
|
convert_object(object)
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
@doc """
|
|
|
|
Creates a `RDF.Triple` with proper RDF values.
|
|
|
|
|
|
|
|
An error is raised when the given elements are not convertible to RDF values.
|
|
|
|
|
|
|
|
Note: The `RDF.triple` function is a shortcut to this function.
|
|
|
|
|
|
|
|
# Examples
|
|
|
|
|
|
|
|
iex> RDF.Triple.new {"http://example.com/S", "http://example.com/p", 42}
|
2017-04-10 01:06:20 +00:00
|
|
|
{~I<http://example.com/S>, ~I<http://example.com/p>, RDF.literal(42)}
|
2016-10-15 16:26:56 +00:00
|
|
|
"""
|
|
|
|
def new({subject, predicate, object}), do: new(subject, predicate, object)
|
|
|
|
|
|
|
|
|
|
|
|
@doc false
|
|
|
|
def convert_subject(uri)
|
|
|
|
def convert_subject(uri = %URI{}), do: uri
|
|
|
|
def convert_subject(bnode = %BlankNode{}), do: bnode
|
|
|
|
def convert_subject(uri) when is_atom(uri) or is_binary(uri), do: RDF.uri(uri)
|
2016-11-04 21:13:06 +00:00
|
|
|
def convert_subject(arg), do: raise RDF.Triple.InvalidSubjectError, subject: arg
|
2016-10-15 16:26:56 +00:00
|
|
|
|
|
|
|
@doc false
|
|
|
|
def convert_predicate(uri)
|
|
|
|
def convert_predicate(uri = %URI{}), do: uri
|
2017-04-07 13:44:36 +00:00
|
|
|
# Note: Although, RDF does not allow blank nodes for properties, JSON-LD allows
|
|
|
|
# them, by introducing the notion of "generalized RDF".
|
|
|
|
# TODO: Support an option `:strict_rdf` to explicitly disallow them or produce warnings or ...
|
|
|
|
def convert_predicate(bnode = %BlankNode{}), do: bnode
|
2016-10-15 16:26:56 +00:00
|
|
|
def convert_predicate(uri) when is_atom(uri) or is_binary(uri), do: RDF.uri(uri)
|
2016-11-04 21:13:06 +00:00
|
|
|
def convert_predicate(arg), do: raise RDF.Triple.InvalidPredicateError, predicate: arg
|
2016-10-15 16:26:56 +00:00
|
|
|
|
|
|
|
@doc false
|
|
|
|
def convert_object(uri)
|
|
|
|
def convert_object(uri = %URI{}), do: uri
|
|
|
|
def convert_object(literal = %Literal{}), do: literal
|
|
|
|
def convert_object(bnode = %BlankNode{}), do: bnode
|
|
|
|
def convert_object(atom) when is_atom(atom), do: RDF.uri(atom)
|
|
|
|
def convert_object(arg), do: Literal.new(arg)
|
|
|
|
|
|
|
|
end
|