5819eec0cf
It turned out that the costs of separating the XSD datatypes are too high and probably not worth the effort, since with its limited scope probably nobody would want to use XSD.ex outside of the RDF.ex context anyway.
224 lines
6.9 KiB
Elixir
224 lines
6.9 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.XSD.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.XSD.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.XSD.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
|
|
@dialyzer {:nowarn_function, equal_value?: 2}
|
|
@dialyzer {:nowarn_function, coerce: 1}
|
|
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: RDF.Literal.equal?(term1, term2)
|
|
def equal_value?(term1, term2), do: RDF.Literal.equal_value?(term1, term2)
|
|
def coerce(term), do: term
|
|
def value(term), do: RDF.Literal.value(term) || 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.XSD.true
|
|
def coerce(false), do: RDF.XSD.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.XSD.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.XSD.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.XSD.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.XSD.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.XSD.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.XSD.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.XSD.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.XSD.Time.new(term)
|
|
def value(term), do: term
|
|
def term?(_), do: false
|
|
end
|
|
|
|
defimpl RDF.Term, for: URI 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.XSD.AnyURI.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
|