rdf-ex/lib/rdf/term.ex
2018-10-05 01:15:36 +02:00

215 lines
6.4 KiB
Elixir

defprotocol RDF.Term do
@moduledoc """
Shared behaviour for all RDF terms.
A `RDF.Term` is anything which can be an element of RDF statements of a RDF graph:
- `RDF.IRI`s
- `RDF.BlankNode`s
- `RDF.Literal`s
see <https://www.w3.org/TR/sparql11-query/#defn_RDFTerm>
"""
@type t :: RDF.IRI.t | RDF.BlankNode.t | RDF.Literal.t
@doc """
Checks if the given value is a RDF term.
Note: As opposed to `RDF.term?` this function returns false on atoms and does
not try resolves those to IRIs.
## Examples
iex> RDF.Term.term?(RDF.iri("http://example.com/resource"))
true
iex> RDF.Term.term?(EX.Resource)
false
iex> RDF.Term.term?(RDF.bnode)
true
iex> RDF.Term.term?(RDF.integer(42))
true
iex> RDF.Term.term?(42)
false
"""
def term?(value)
@doc """
Tests for term equality.
see <http://www.w3.org/TR/rdf-sparql-query/#func-sameTerm>
"""
@fallback_to_any true
def equal?(term1, term2)
@doc """
Tests for equality of values.
Non-RDF terms are tried to be coerced via `RDF.Term.coerce/1` before comparison.
Returns `nil` if the given terms are not comparable.
see <http://www.w3.org/TR/rdf-sparql-query/#func-RDFterm-equal>
and the value equality semantics of the different literal datatypes here:
<https://www.w3.org/TR/sparql11-query/#OperatorMapping>
"""
@fallback_to_any true
def equal_value?(term1, term2)
@doc """
Converts a given value into a RDF term.
Returns `nil` if the given value is not convertible into any valid RDF.Term.
## Examples
iex> RDF.Term.coerce("foo")
~L"foo"
iex> RDF.Term.coerce(42)
RDF.integer(42)
"""
def coerce(value)
@doc """
Returns the native Elixir value of a RDF term.
Returns `nil` if the given value is not a a valid RDF term or a value convertible to a RDF term.
## Examples
iex> RDF.Term.value(~I<http://example.com/>)
"http://example.com/"
iex> RDF.Term.value(~L"foo")
"foo"
iex> RDF.integer(42) |> RDF.Term.value()
42
"""
def value(term)
end
defimpl RDF.Term, for: RDF.IRI do
def equal?(term1, term2), do: term1 == term2
def equal_value?(term1, term2), do: RDF.IRI.equal_value?(term1, term2)
def coerce(term), do: term
def value(term), do: term.value
def term?(_), do: true
end
defimpl RDF.Term, for: RDF.BlankNode do
def equal?(term1, term2), do: term1 == term2
def equal_value?(term1, term2), do: RDF.BlankNode.equal_value?(term1, term2)
def coerce(term), do: term
def value(term), do: to_string(term)
def term?(_), do: true
end
defimpl RDF.Term, for: Reference do
def equal?(term1, term2), do: term1 == term2
def equal_value?(term1, term2), do: RDF.Term.equal_value?(coerce(term1), term2)
def coerce(term), do: RDF.BlankNode.new(term)
def value(term), do: term
def term?(_), do: false
end
defimpl RDF.Term, for: RDF.Literal do
def equal?(term1, term2), do: term1 == term2
def equal_value?(term1, term2), do: RDF.Literal.equal_value?(term1, term2)
def coerce(term), do: term
def value(term), do: term.value || RDF.Literal.lexical(term)
def term?(_), do: true
end
defimpl RDF.Term, for: Atom do
def equal?(term1, term2), do: term1 == term2
def equal_value?(nil, _), do: nil
def equal_value?(term1, term2), do: RDF.Term.equal_value?(coerce(term1), term2)
def coerce(true), do: RDF.true
def coerce(false), do: RDF.false
def coerce(_), do: nil
def value(true), do: true
def value(false), do: false
def value(_), do: nil
def term?(_), do: false
end
defimpl RDF.Term, for: BitString do
def equal?(term1, term2), do: term1 == term2
def equal_value?(term1, term2), do: RDF.Term.equal_value?(coerce(term1), term2)
def coerce(term), do: RDF.String.new(term)
def value(term), do: term
def term?(_), do: false
end
defimpl RDF.Term, for: Integer do
def equal?(term1, term2), do: term1 == term2
def equal_value?(term1, term2), do: RDF.Term.equal_value?(coerce(term1), term2)
def coerce(term), do: RDF.Integer.new(term)
def value(term), do: term
def term?(_), do: false
end
defimpl RDF.Term, for: Float do
def equal?(term1, term2), do: term1 == term2
def equal_value?(term1, term2), do: RDF.Term.equal_value?(coerce(term1), term2)
def coerce(term), do: RDF.Double.new(term)
def value(term), do: term
def term?(_), do: false
end
defimpl RDF.Term, for: Decimal do
def equal?(term1, term2), do: term1 == term2
def equal_value?(term1, term2), do: RDF.Term.equal_value?(coerce(term1), term2)
def coerce(term), do: RDF.Decimal.new(term)
def value(term), do: term
def term?(_), do: false
end
defimpl RDF.Term, for: DateTime do
def equal?(term1, term2), do: term1 == term2
def equal_value?(term1, term2), do: RDF.Term.equal_value?(coerce(term1), term2)
def coerce(term), do: RDF.DateTime.new(term)
def value(term), do: term
def term?(_), do: false
end
defimpl RDF.Term, for: NaiveDateTime do
def equal?(term1, term2), do: term1 == term2
def equal_value?(term1, term2), do: RDF.Term.equal_value?(coerce(term1), term2)
def coerce(term), do: RDF.DateTime.new(term)
def value(term), do: term
def term?(_), do: false
end
defimpl RDF.Term, for: Date do
def equal?(term1, term2), do: term1 == term2
def equal_value?(term1, term2), do: RDF.Term.equal_value?(coerce(term1), term2)
def coerce(term), do: RDF.Date.new(term)
def value(term), do: term
def term?(_), do: false
end
defimpl RDF.Term, for: Time do
def equal?(term1, term2), do: term1 == term2
def equal_value?(term1, term2), do: RDF.Term.equal_value?(coerce(term1), term2)
def coerce(term), do: RDF.Time.new(term)
def value(term), do: term
def term?(_), do: false
end
defimpl RDF.Term, for: Any do
def equal?(term1, term2), do: term1 == term2
def equal_value?(_, _), do: nil
def coerce(_), do: nil
def value(_), do: nil
def term?(_), do: false
end