Fix some issues with RDF.Term coercion in various contexts

This commit is contained in:
Marcel Otto 2018-09-16 22:21:53 +02:00
parent 1cd3a0c342
commit f4877bbc65
5 changed files with 73 additions and 15 deletions

View file

@ -216,7 +216,7 @@ defmodule RDF.Datatype do
end
def equal_value?(%RDF.Literal{} = left, right) when not is_nil(right) do
unless RDF.term?(right) do
unless RDF.Term.term?(right) do
equal_value?(left, RDF.Term.coerce(right))
end
end

View file

@ -79,7 +79,7 @@ defmodule RDF.Numeric do
end
def equal_value?(%RDF.Literal{} = left, right) when not is_nil(right) do
unless RDF.term?(right) do
unless RDF.Term.term?(right) do
equal_value?(left, RDF.Term.coerce(right))
end
end
@ -269,7 +269,7 @@ defmodule RDF.Numeric do
end
def abs(value) do
unless RDF.term?(value) do
if not is_nil(value) and not RDF.Term.term?(value) do
value
|> RDF.Term.coerce()
|> abs()
@ -331,7 +331,7 @@ defmodule RDF.Numeric do
end
def round(value, precision) do
unless RDF.term?(value) do
if not is_nil(value) and not RDF.Term.term?(value) do
value
|> RDF.Term.coerce()
|> round(precision)
@ -383,7 +383,7 @@ defmodule RDF.Numeric do
end
def ceil(value) do
unless RDF.term?(value) do
if not is_nil(value) and not RDF.Term.term?(value) do
value
|> RDF.Term.coerce()
|> ceil()
@ -430,7 +430,7 @@ defmodule RDF.Numeric do
end
def floor(value) do
unless RDF.term?(value) do
if not is_nil(value) and not RDF.Term.term?(value) do
value
|> RDF.Term.coerce()
|> floor()
@ -450,14 +450,24 @@ defmodule RDF.Numeric do
end
end
defp arithmetic_operation(op, %Literal{} = arg1, arg2, fun),
do: arithmetic_operation(op, arg1, RDF.Term.coerce(arg2), fun)
defp arithmetic_operation(op, %Literal{} = arg1, arg2, fun) do
if not is_nil(arg2) and not RDF.Term.term?(arg2) do
arithmetic_operation(op, arg1, RDF.Term.coerce(arg2), fun)
end
end
defp arithmetic_operation(op, arg1, %Literal{} = arg2, fun),
do: arithmetic_operation(op, RDF.Term.coerce(arg1), arg2, fun)
defp arithmetic_operation(op, arg1, %Literal{} = arg2, fun) do
if not is_nil(arg1) and not RDF.Term.term?(arg1) do
arithmetic_operation(op, RDF.Term.coerce(arg1), arg2, fun)
end
end
defp arithmetic_operation(op, arg1, arg2, fun),
do: arithmetic_operation(op, RDF.Term.coerce(arg1), RDF.Term.coerce(arg2), fun)
defp arithmetic_operation(op, arg1, arg2, fun) do
if not is_nil(arg1) and not RDF.Term.term?(arg1) and
not is_nil(arg2) and not RDF.Term.term?(arg2) do
arithmetic_operation(op, RDF.Term.coerce(arg1), RDF.Term.coerce(arg2), fun)
end
end
defp type_conversion(%Literal{datatype: datatype} = arg1,

View file

@ -251,7 +251,7 @@ defmodule RDF.Literal do
do: RDF.IRI.equal_value?(left, right)
def equal_value?(%RDF.Literal{} = left, right) when not is_nil(right) do
unless RDF.term?(right) do
unless RDF.Term.term?(right) do
equal_value?(left, RDF.Term.coerce(right))
end
end

View file

@ -15,6 +15,27 @@ defprotocol RDF.Term do
@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.
@ -51,24 +72,28 @@ 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 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 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 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 term?(_), do: true
end
defimpl RDF.Term, for: Atom do
@ -80,58 +105,69 @@ defimpl RDF.Term, for: Atom do
def coerce(true), do: RDF.true
def coerce(false), do: RDF.false
def coerce(_), 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 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 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 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 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 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 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 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 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 term?(_), do: false
end

View file

@ -104,6 +104,10 @@ defmodule RDF.NumericTest do
assert Numeric.add(3.14, 42) == RDF.double(45.14)
assert RDF.decimal(3.14) |> Numeric.add(42) == RDF.decimal(45.14)
assert Numeric.add(42, RDF.decimal(3.14)) == RDF.decimal(45.14)
assert Numeric.add(42, ~B"foo") == nil
assert Numeric.add(42, :foo) == nil
assert Numeric.add(:foo, 42) == nil
assert Numeric.add(:foo, :bar) == nil
end
end
@ -337,8 +341,11 @@ defmodule RDF.NumericTest do
assert RDF.decimal(4) |> Numeric.divide(2) == RDF.decimal(2.0)
assert Numeric.divide(4, RDF.decimal(2.0)) == RDF.decimal(2.0)
assert Numeric.divide("foo", "bar") == nil
assert Numeric.divide(4, "bar") == nil
assert Numeric.divide("foo", 2) == nil
assert Numeric.divide(4, "bar") == nil
assert Numeric.divide("foo", 2) == nil
assert Numeric.divide(42, :bar) == nil
assert Numeric.divide(:foo, 42) == nil
assert Numeric.divide(:foo, :bar) == nil
end
end
@ -383,6 +390,7 @@ defmodule RDF.NumericTest do
assert Numeric.abs(-3.14) == RDF.double(3.14)
assert Numeric.abs(D.new(-3.14)) == RDF.decimal(3.14)
assert Numeric.abs("foo") == nil
assert Numeric.abs(:foo) == nil
end
end
@ -419,6 +427,7 @@ defmodule RDF.NumericTest do
assert Numeric.round(-3.14) == RDF.double(-3.0)
assert Numeric.round(D.new(3.14)) == RDF.decimal("3")
assert Numeric.round("foo") == nil
assert Numeric.round(:foo) == nil
end
end
@ -459,6 +468,7 @@ defmodule RDF.NumericTest do
assert Numeric.round(-3.14, 1) == RDF.double(-3.1)
assert Numeric.round(D.new(3.14), 1) == RDF.decimal("3.1")
assert Numeric.round("foo", 1) == nil
assert Numeric.round(:foo, 1) == nil
end
end
@ -493,6 +503,7 @@ defmodule RDF.NumericTest do
assert Numeric.ceil(-3.14) == RDF.double("-3")
assert Numeric.ceil(D.new(3.14)) == RDF.decimal("4")
assert Numeric.ceil("foo") == nil
assert Numeric.ceil(:foo) == nil
end
end
@ -527,6 +538,7 @@ defmodule RDF.NumericTest do
assert Numeric.floor(-3.14) == RDF.double("-4")
assert Numeric.floor(D.new(3.14)) == RDF.decimal("3")
assert Numeric.floor("foo") == nil
assert Numeric.floor(:foo) == nil
end
end