rdf-ex/lib/rdf/term.ex

230 lines
6.4 KiB
Elixir
Raw Permalink Normal View History

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>
"""
2022-02-25 16:18:03 +00:00
@type t :: RDF.Resource.t() | RDF.Literal.t()
2018-09-02 03:25:20 +00:00
@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 to resolve them 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.
2018-09-16 02:02:53 +00:00
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)
2018-09-16 02:02:53 +00:00
@doc """
Converts a given value into a RDF term.
Returns `nil` if the given value is not convertible into any valid RDF.Term.
2018-10-04 22:58:34 +00:00
## Examples
iex> RDF.Term.coerce("foo")
~L"foo"
iex> RDF.Term.coerce(42)
RDF.XSD.integer(42)
2018-10-04 22:58:34 +00:00
2018-09-16 02:02:53 +00:00
"""
def coerce(value)
2018-10-04 22:58:34 +00:00
@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()
2018-10-04 22:58:34 +00:00
42
"""
def value(term)
end
defimpl RDF.Term, for: RDF.IRI do
2020-06-29 08:37:42 +00:00
def equal?(term1, term2), do: term1 == term2
def equal_value?(term1, term2), do: RDF.IRI.equal_value?(term1, term2)
2020-06-29 08:37:42 +00:00
def coerce(term), do: term
def value(term), do: term.value
def term?(_), do: true
end
defimpl RDF.Term, for: RDF.BlankNode do
2020-06-29 08:37:42 +00:00
def equal?(term1, term2), do: term1 == term2
def equal_value?(term1, term2), do: RDF.BlankNode.equal_value?(term1, term2)
2020-06-29 08:37:42 +00:00
def coerce(term), do: term
def value(term), do: to_string(term)
def term?(_), do: true
2018-09-16 02:02:53 +00:00
end
defimpl RDF.Term, for: Reference do
2020-03-02 01:07:31 +00:00
@dialyzer {:nowarn_function, equal_value?: 2}
@dialyzer {:nowarn_function, coerce: 1}
2020-06-29 08:37:42 +00:00
def equal?(term1, term2), do: term1 == term2
2018-09-16 02:02:53 +00:00
def equal_value?(term1, term2), do: RDF.Term.equal_value?(coerce(term1), term2)
2020-06-29 08:37:42 +00:00
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
2020-06-29 08:37:42 +00:00
def equal?(term1, term2), do: RDF.Literal.equal?(term1, term2)
def equal_value?(term1, term2), do: RDF.Literal.equal_value?(term1, term2)
2020-06-29 08:37:42 +00:00
def coerce(term), do: term
def value(term), do: RDF.Literal.value(term) || RDF.Literal.lexical(term)
def term?(_), do: true
2018-09-16 02:02:53 +00:00
end
defimpl RDF.Term, for: Atom do
def equal?(term1, term2), do: term1 == term2
2020-06-29 08:37:42 +00:00
def equal_value?(nil, _), do: nil
2018-09-16 02:02:53 +00:00
def equal_value?(term1, term2), do: RDF.Term.equal_value?(coerce(term1), term2)
2020-06-29 08:37:42 +00:00
def coerce(true), do: RDF.XSD.true()
def coerce(false), do: RDF.XSD.false()
def coerce(nil), do: nil
def coerce(term) do
case RDF.Namespace.resolve_term(term) do
{:ok, iri} -> iri
_ -> nil
end
end
2020-06-29 08:37:42 +00:00
def value(true), do: true
2018-10-04 22:58:34 +00:00
def value(false), do: false
2020-06-29 08:37:42 +00:00
def value(nil), do: nil
def value(term), do: RDF.Term.value(coerce(term))
2018-10-04 22:58:34 +00:00
def term?(_), do: false
2018-09-16 02:02:53 +00:00
end
defimpl RDF.Term, for: BitString do
2020-06-29 08:37:42 +00:00
def equal?(term1, term2), do: term1 == term2
2018-09-16 02:02:53 +00:00
def equal_value?(term1, term2), do: RDF.Term.equal_value?(coerce(term1), term2)
2020-06-29 08:37:42 +00:00
def coerce(term), do: RDF.XSD.String.new(term)
def value(term), do: term
def term?(_), do: false
2018-09-16 02:02:53 +00:00
end
defimpl RDF.Term, for: Integer do
2020-06-29 08:37:42 +00:00
def equal?(term1, term2), do: term1 == term2
2018-09-16 02:02:53 +00:00
def equal_value?(term1, term2), do: RDF.Term.equal_value?(coerce(term1), term2)
2020-06-29 08:37:42 +00:00
def coerce(term), do: RDF.XSD.Integer.new(term)
def value(term), do: term
def term?(_), do: false
2018-09-16 02:02:53 +00:00
end
defimpl RDF.Term, for: Float do
2020-06-29 08:37:42 +00:00
def equal?(term1, term2), do: term1 == term2
2018-09-16 02:02:53 +00:00
def equal_value?(term1, term2), do: RDF.Term.equal_value?(coerce(term1), term2)
2020-06-29 08:37:42 +00:00
def coerce(term), do: RDF.XSD.Double.new(term)
def value(term), do: term
def term?(_), do: false
2018-09-16 02:02:53 +00:00
end
defimpl RDF.Term, for: Decimal do
2020-06-29 08:37:42 +00:00
def equal?(term1, term2), do: term1 == term2
def equal_value?(term1, term2), do: RDF.Term.equal_value?(coerce(term1), term2)
2020-06-29 08:37:42 +00:00
def coerce(term), do: RDF.XSD.Decimal.new(term)
def value(term), do: term
def term?(_), do: false
end
2018-09-16 02:02:53 +00:00
defimpl RDF.Term, for: DateTime do
2020-06-29 08:37:42 +00:00
def equal?(term1, term2), do: term1 == term2
2018-09-16 02:02:53 +00:00
def equal_value?(term1, term2), do: RDF.Term.equal_value?(coerce(term1), term2)
2020-06-29 08:37:42 +00:00
def coerce(term), do: RDF.XSD.DateTime.new(term)
def value(term), do: term
def term?(_), do: false
2018-09-16 02:02:53 +00:00
end
defimpl RDF.Term, for: NaiveDateTime do
2020-06-29 08:37:42 +00:00
def equal?(term1, term2), do: term1 == term2
2018-09-16 02:02:53 +00:00
def equal_value?(term1, term2), do: RDF.Term.equal_value?(coerce(term1), term2)
2020-06-29 08:37:42 +00:00
def coerce(term), do: RDF.XSD.DateTime.new(term)
def value(term), do: term
def term?(_), do: false
2018-09-16 02:02:53 +00:00
end
defimpl RDF.Term, for: Date do
2020-06-29 08:37:42 +00:00
def equal?(term1, term2), do: term1 == term2
2018-09-16 02:02:53 +00:00
def equal_value?(term1, term2), do: RDF.Term.equal_value?(coerce(term1), term2)
2020-06-29 08:37:42 +00:00
def coerce(term), do: RDF.XSD.Date.new(term)
def value(term), do: term
def term?(_), do: false
2018-09-16 02:02:53 +00:00
end
defimpl RDF.Term, for: Time do
2020-06-29 08:37:42 +00:00
def equal?(term1, term2), do: term1 == term2
2018-09-16 02:02:53 +00:00
def equal_value?(term1, term2), do: RDF.Term.equal_value?(coerce(term1), term2)
2020-06-29 08:37:42 +00:00
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
2020-06-29 08:37:42 +00:00
def equal?(term1, term2), do: term1 == term2
def equal_value?(term1, term2), do: RDF.Term.equal_value?(coerce(term1), term2)
2020-06-29 08:37:42 +00:00
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
2020-06-29 08:37:42 +00:00
def equal_value?(_, _), do: nil
def coerce(_), do: nil
def value(_), do: nil
def term?(_), do: false
end