Handle derived datatypes on RDF.Literal.Datatype.compare/2 properly

This commit is contained in:
Marcel Otto 2020-05-27 00:56:44 +02:00
parent 162e82ed47
commit 98adbaf878
13 changed files with 154 additions and 153 deletions

View file

@ -130,20 +130,23 @@ defmodule RDF.Literal.Datatype do
@callback do_equal_value_different_datatypes?(literal, literal) :: boolean | nil @callback do_equal_value_different_datatypes?(literal, literal) :: boolean | nil
@doc """ @doc """
Compares two `RDF.Literal`s. Callback for datatype specific `compare/2` comparisons between two `RDF.Literal`s.
Returns `:gt` if value of the first literal is greater than the value of the second in This callback is called by auto-generated `compare/2` function on the implementations, which already deals with the basic cases.
terms of their datatype and `:lt` for vice versa. If the two literals are equal `:eq` is returned. So, implementations can assume the passed arguments are valid `RDF.Literal.Datatype` structs and
For datatypes with only partial ordering `:indeterminate` is returned when the have the same datatypes or are derived from each other.
Should return `:gt` if value of the first literal is greater than the value of the second in
terms of their datatype and `:lt` for vice versa. If the two literals can be considered equal `:eq` should be returned.
For datatypes with only partial ordering `:indeterminate` should be returned when the
order of the given literals is not defined. order of the given literals is not defined.
Returns `nil` when the given arguments are not comparable datatypes or if one `nil` should be returned when the given arguments are not comparable datatypes or if one them is invalid.
them is invalid.
The default implementation of the `_using__` macro of `RDF.XSD.Datatype`s The default implementation of the `_using__` macro of `RDF.Literal.Datatype`s
compares the values of the `canonical/1` forms of the given literals of this datatype. just compares the values of the given literals.
""" """
@callback compare(Literal.t() | literal, Literal.t() | literal) :: comparison_result | :indeterminate | nil @callback do_compare(literal, literal) :: comparison_result | :indeterminate | nil
@doc """ @doc """
Updates the value of a `RDF.Literal` without changing everything else. Updates the value of a `RDF.Literal` without changing everything else.
@ -348,7 +351,37 @@ defmodule RDF.Literal.Datatype do
defp resource?(%RDF.BlankNode{}), do: true defp resource?(%RDF.BlankNode{}), do: true
defp resource?(_), do: false defp resource?(_), do: false
@impl unquote(__MODULE__) # RDF.XSD.Datatypes offers another default implementation, but since it is
# still in a macro implementation defoverridable doesn't work
unless RDF.XSD.Datatype in @behaviour do
def compare(left, right)
def compare(left, %RDF.Literal{literal: right}), do: compare(left, right)
def compare(%RDF.Literal{literal: left}, right), do: compare(left, right)
def compare(left, right) do
if Literal.datatype?(left) and Literal.datatype?(right) and
Literal.Datatype.valid?(left) and Literal.Datatype.valid?(right) do
do_compare(left, right)
end
end
@impl RDF.Literal.Datatype
def do_compare(%datatype{} = left, %datatype{} = right) do
case {datatype.value(left), datatype.value(right)} do
{left_value, right_value} when left_value < right_value -> :lt
{left_value, right_value} when left_value > right_value -> :gt
_ ->
if datatype.equal_value?(left, right), do: :eq
end
end
def do_compare(_, _), do: nil
defoverridable compare: 2,
do_compare: 2
end
@impl unquote(__MODULE__)
def update(literal, fun, opts \\ []) def update(literal, fun, opts \\ [])
def update(%Literal{literal: literal}, fun, opts), do: update(literal, fun, opts) def update(%Literal{literal: literal}, fun, opts), do: update(literal, fun, opts)
def update(%__MODULE__{} = literal, fun, opts) do def update(%__MODULE__{} = literal, fun, opts) do

View file

@ -92,21 +92,17 @@ defmodule RDF.Literal.Generic do
def do_equal_value_same_or_derived_datatypes?(_, _), do: nil def do_equal_value_same_or_derived_datatypes?(_, _), do: nil
@impl Datatype @impl Datatype
def compare(left, %Literal{literal: right}), do: compare(left, right) def do_compare(%__MODULE__{datatype: datatype} = left_literal,
def compare(%Literal{literal: left}, right), do: compare(left, right) %__MODULE__{datatype: datatype} = right_literal) do
def compare(%__MODULE__{datatype: datatype} = literal1, case {left_literal.value, right_literal.value} do
%__MODULE__{datatype: datatype} = literal2) do {left_value, right_value} when left_value < right_value -> :lt
if valid?(literal1) and valid?(literal2) do {left_value, right_value} when left_value > right_value -> :gt
case {literal1.value, literal2.value} do _ ->
{value1, value2} when value1 < value2 -> :lt if equal_value?(left_literal, right_literal), do: :eq
{value1, value2} when value1 > value2 -> :gt
_ ->
if equal_value?(literal1, literal2), do: :eq
end
end end
end end
def compare(_, _), do: nil def do_compare(_, _), do: nil
@impl Datatype @impl Datatype
def update(literal, fun, opts \\ []) def update(literal, fun, opts \\ [])

View file

@ -78,23 +78,6 @@ defmodule RDF.LangString do
@impl Datatype @impl Datatype
def do_cast(_), do: nil def do_cast(_), do: nil
@impl Datatype
def compare(left, %Literal{literal: right}), do: compare(left, right)
def compare(%Literal{literal: left}, right), do: compare(left, right)
def compare(%__MODULE__{language: language_tag} = literal1,
%__MODULE__{language: language_tag} = literal2) do
if valid?(literal1) and valid?(literal2) do
case {canonical(literal1).literal.value, canonical(literal2).literal.value} do
{value1, value2} when value1 < value2 -> :lt
{value1, value2} when value1 > value2 -> :gt
_ ->
if equal_value?(literal1, literal2), do: :eq
end
end
end
def compare(_, _), do: nil
@impl Datatype @impl Datatype
def update(literal, fun, opts \\ []) def update(literal, fun, opts \\ [])
def update(%Literal{literal: literal}, fun, opts), do: update(literal, fun, opts) def update(%Literal{literal: literal}, fun, opts), do: update(literal, fun, opts)

View file

@ -13,8 +13,6 @@ defmodule RDF.XSD.Datatype do
:uncanonical_lexical => uncanonical_lexical() :uncanonical_lexical => uncanonical_lexical()
} }
@type comparison_result :: :lt | :gt | :eq
import RDF.Utils.Guards import RDF.Utils.Guards
@doc """ @doc """
@ -272,6 +270,17 @@ defmodule RDF.XSD.Datatype do
end end
end end
def compare(left, right)
def compare(left, %RDF.Literal{literal: right}), do: compare(left, right)
def compare(%RDF.Literal{literal: left}, right), do: compare(left, right)
def compare(left, right) do
if RDF.XSD.datatype?(left) and RDF.XSD.datatype?(right) and
RDF.Literal.Datatype.valid?(left) and RDF.Literal.Datatype.valid?(right) do
do_compare(left, right)
end
end
defimpl Inspect do defimpl Inspect do
"Elixir.Inspect." <> datatype_name = to_string(__MODULE__) "Elixir.Inspect." <> datatype_name = to_string(__MODULE__)
@datatype_name datatype_name @datatype_name datatype_name

View file

@ -56,24 +56,19 @@ defmodule RDF.XSD.Datatype.Primitive do
@impl RDF.Literal.Datatype @impl RDF.Literal.Datatype
def do_equal_value_different_datatypes?(left, right), do: nil def do_equal_value_different_datatypes?(left, right), do: nil
@impl RDF.Literal.Datatype @impl RDF.Literal.Datatype
def compare(left, right) def do_compare(%left_datatype{} = left, %right_datatype{} = right) do
def compare(left, %RDF.Literal{literal: right}), do: compare(left, right) if left_datatype.datatype?(right_datatype) or right_datatype.datatype?(left_datatype) do
def compare(%RDF.Literal{literal: left}, right), do: compare(left, right) case {left_datatype.value(left), right_datatype.value(right)} do
{left_value, right_value} when left_value < right_value -> :lt
def compare( {left_value, right_value} when left_value > right_value -> :gt
%__MODULE__{value: left_value} = left, _ ->
%__MODULE__{value: right_value} = right if left_datatype.equal_value?(left, right), do: :eq
) end
when not (is_nil(left_value) or is_nil(right_value)) do
case {left |> canonical() |> value(), right |> canonical() |> value()} do
{value1, value2} when value1 < value2 -> :lt
{value1, value2} when value1 > value2 -> :gt
_ -> if equal_value?(left, right), do: :eq
end end
end end
def compare(_, _), do: nil def do_compare(_, _), do: nil
defoverridable canonical_mapping: 1, defoverridable canonical_mapping: 1,
do_cast: 1, do_cast: 1,
@ -81,7 +76,7 @@ defmodule RDF.XSD.Datatype.Primitive do
init_invalid_lexical: 2, init_invalid_lexical: 2,
do_equal_value_same_or_derived_datatypes?: 2, do_equal_value_same_or_derived_datatypes?: 2,
do_equal_value_different_datatypes?: 2, do_equal_value_different_datatypes?: 2,
compare: 2 do_compare: 2
@before_compile unquote(__MODULE__) @before_compile unquote(__MODULE__)
end end

View file

@ -86,14 +86,14 @@ defmodule RDF.XSD.Datatype.Restriction do
end end
@impl RDF.Literal.Datatype @impl RDF.Literal.Datatype
def compare(left, right), do: @base.compare(left, right) def do_compare(left, right), do: @base.do_compare(left, right)
defoverridable canonical_mapping: 1, defoverridable canonical_mapping: 1,
do_cast: 1, do_cast: 1,
equal_value?: 2, equal_value?: 2,
do_equal_value_same_or_derived_datatypes?: 2, do_equal_value_same_or_derived_datatypes?: 2,
do_equal_value_different_datatypes?: 2, do_equal_value_different_datatypes?: 2,
compare: 2 do_compare: 2
Module.register_attribute(__MODULE__, :facets, accumulate: true) Module.register_attribute(__MODULE__, :facets, accumulate: true)

View file

@ -183,21 +183,7 @@ defmodule RDF.XSD.Date do
end end
@impl RDF.Literal.Datatype @impl RDF.Literal.Datatype
def compare(left, right) def do_compare(%{value: value1}, %{value: value2}) do
def compare(left, %RDF.Literal{literal: right}), do: compare(left, right)
def compare(%RDF.Literal{literal: left}, right), do: compare(left, right)
def compare(
%__MODULE__{value: value1},
%__MODULE__{value: value2}
)
when is_nil(value1) or is_nil(value2),
do: nil
def compare(
%__MODULE__{value: value1},
%__MODULE__{value: value2}
) do
XSD.DateTime.compare( XSD.DateTime.compare(
comparison_normalization(value1), comparison_normalization(value1),
comparison_normalization(value2) comparison_normalization(value2)
@ -209,27 +195,27 @@ defmodule RDF.XSD.Date do
# ordering comparisons in the date-3 test. The following implementation would allow # ordering comparisons in the date-3 test. The following implementation would allow
# an ordering comparisons between date and datetimes. # an ordering comparisons between date and datetimes.
# #
# def compare( # def do_compare(
# %__MODULE__{value: date_value}, # %__MODULE__{value: date_value},
# %XSD.DateTime{} = datetime_literal # %XSD.DateTime{} = datetime_literal
# ) do # ) do
# XSD.DateTime.compare( # XSD.DateTime.compare(
# comparison_normalization(date_value), # comparison_normalization(date_value).literal,
# datetime_literal # datetime_literal
# ) # )
# end # end
# #
# def compare( # def do_compare(
# %XSD.DateTime{} = datetime_literal, # %XSD.DateTime{} = datetime_literal,
# %__MODULE__{value: date_value} # %__MODULE__{value: date_value}
# ) do # ) do
# XSD.DateTime.compare( # XSD.DateTime.do_compare(
# datetime_literal, # datetime_literal,
# comparison_normalization(date_value) # comparison_normalization(date_value).literal
# ) # )
# end # end
def compare(_, _), do: nil def do_compare(_, _), do: nil
defp comparison_normalization({date, tz}) do defp comparison_normalization({date, tz}) do
(Date.to_iso8601(date) <> "T00:00:00" <> tz) (Date.to_iso8601(date) <> "T00:00:00" <> tz)

View file

@ -185,15 +185,10 @@ defmodule RDF.XSD.DateTime do
end end
end end
@impl RDF.Literal.Datatype @impl RDF.Literal.Datatype
def compare(left, right) def do_compare(left, right)
def compare(left, %RDF.Literal{literal: right}), do: compare(left, right)
def compare(%RDF.Literal{literal: left}, right), do: compare(left, right)
def compare( def do_compare(%{value: %type{} = value1}, %{value: %type{} = value2}) do
%__MODULE__{value: %type{} = value1},
%__MODULE__{value: %type{} = value2}
) do
type.compare(value1, value2) type.compare(value1, value2)
end end
@ -202,37 +197,31 @@ defmodule RDF.XSD.DateTime do
# ordering comparisons in the date-3 test. The following implementation would allow # ordering comparisons in the date-3 test. The following implementation would allow
# an ordering comparisons between date and datetimes. # an ordering comparisons between date and datetimes.
# #
# def compare(%__MODULE__{} = literal1, %XSD.Date{} = literal2) do # def do_compare(%__MODULE__{} = literal1, %XSD.Date{} = literal2) do
# XSD.Date.compare(literal1, literal2) # XSD.Date.do_compare(literal1, literal2)
# end # end
# #
# def compare(%XSD.Date{} = literal1, %__MODULE__{} = literal2) do # def do_compare(%XSD.Date{} = literal1, %__MODULE__{} = literal2) do
# XSD.Date.compare(literal1, literal2) # XSD.Date.do_compare(literal1, literal2)
# end # end
def compare( def do_compare(%{value: %DateTime{}} = left, %{value: %NaiveDateTime{} = right_value}) do
%__MODULE__{value: %DateTime{}} = left,
%__MODULE__{value: %NaiveDateTime{} = right_value}
) do
cond do cond do
compare(left, new(to_datetime(right_value, "+"))) == :lt -> :lt do_compare(left, new(to_datetime(right_value, "+")).literal) == :lt -> :lt
compare(left, new(to_datetime(right_value, "-"))) == :gt -> :gt do_compare(left, new(to_datetime(right_value, "-")).literal) == :gt -> :gt
true -> :indeterminate true -> :indeterminate
end end
end end
def compare( def do_compare(%{value: %NaiveDateTime{} = left}, %{value: %DateTime{}} = right_literal) do
%__MODULE__{value: %NaiveDateTime{} = left},
%__MODULE__{value: %DateTime{}} = right_literal
) do
cond do cond do
compare(new(to_datetime(left, "-")), right_literal) == :lt -> :lt do_compare(new(to_datetime(left, "-")).literal, right_literal) == :lt -> :lt
compare(new(to_datetime(left, "+")), right_literal) == :gt -> :gt do_compare(new(to_datetime(left, "+")).literal, right_literal) == :gt -> :gt
true -> :indeterminate true -> :indeterminate
end end
end end
def compare(_, _), do: nil def do_compare(_, _), do: nil
defp to_datetime(naive_datetime, offset) do defp to_datetime(naive_datetime, offset) do
(NaiveDateTime.to_iso8601(naive_datetime) <> offset <> "14:00") (NaiveDateTime.to_iso8601(naive_datetime) <> offset <> "14:00")

View file

@ -153,14 +153,14 @@ defmodule RDF.XSD.Decimal do
@impl RDF.Literal.Datatype @impl RDF.Literal.Datatype
def do_equal_value_same_or_derived_datatypes?(left, right), do: XSD.Numeric.equal_value?(left, right) def do_equal_value_same_or_derived_datatypes?(left, right), do: XSD.Numeric.do_equal_value?(left, right)
@impl RDF.Literal.Datatype @impl RDF.Literal.Datatype
def do_equal_value_different_datatypes?(left, right), do: XSD.Numeric.equal_value?(left, right) def do_equal_value_different_datatypes?(left, right), do: XSD.Numeric.do_equal_value?(left, right)
@impl RDF.Literal.Datatype @impl RDF.Literal.Datatype
def compare(left, right), do: XSD.Numeric.compare(left, right) def do_compare(left, right), do: XSD.Numeric.do_compare(left, right)
@doc """ @doc """
The number of digits in the XML Schema canonical form of the literal value. The number of digits in the XML Schema canonical form of the literal value.

View file

@ -161,12 +161,12 @@ defmodule RDF.XSD.Double do
@impl RDF.Literal.Datatype @impl RDF.Literal.Datatype
def do_equal_value_same_or_derived_datatypes?(left, right), do: XSD.Numeric.equal_value?(left, right) def do_equal_value_same_or_derived_datatypes?(left, right), do: XSD.Numeric.do_equal_value?(left, right)
@impl RDF.Literal.Datatype @impl RDF.Literal.Datatype
def do_equal_value_different_datatypes?(left, right), do: XSD.Numeric.equal_value?(left, right) def do_equal_value_different_datatypes?(left, right), do: XSD.Numeric.do_equal_value?(left, right)
@impl RDF.Literal.Datatype @impl RDF.Literal.Datatype
def compare(left, right), do: XSD.Numeric.compare(left, right) def do_compare(left, right), do: XSD.Numeric.do_compare(left, right)
end end

View file

@ -100,13 +100,13 @@ defmodule RDF.XSD.Integer do
end end
@impl RDF.Literal.Datatype @impl RDF.Literal.Datatype
def do_equal_value_same_or_derived_datatypes?(left, right), do: XSD.Numeric.equal_value?(left, right) def do_equal_value_same_or_derived_datatypes?(left, right), do: XSD.Numeric.do_equal_value?(left, right)
@impl RDF.Literal.Datatype @impl RDF.Literal.Datatype
def do_equal_value_different_datatypes?(left, right), do: XSD.Numeric.equal_value?(left, right) def do_equal_value_different_datatypes?(left, right), do: XSD.Numeric.do_equal_value?(left, right)
@impl RDF.Literal.Datatype @impl RDF.Literal.Datatype
def compare(left, right), do: XSD.Numeric.compare(left, right) def do_compare(left, right), do: XSD.Numeric.do_compare(left, right)
@doc """ @doc """
The number of digits in the XML Schema canonical form of the literal value. The number of digits in the XML Schema canonical form of the literal value.

View file

@ -20,10 +20,10 @@ defmodule RDF.XSD.Numeric do
- <https://www.w3.org/TR/sparql11-query/#OperatorMapping> - <https://www.w3.org/TR/sparql11-query/#OperatorMapping>
- <https://www.w3.org/TR/xpath-functions/#func-numeric-equal> - <https://www.w3.org/TR/xpath-functions/#func-numeric-equal>
""" """
@spec equal_value?(t() | any, t() | any) :: boolean @spec do_equal_value?(t() | any, t() | any) :: boolean
def equal_value?(left, right) def do_equal_value?(left, right)
def equal_value?(%left_datatype{value: left}, %right_datatype{value: right}) do def do_equal_value?(%left_datatype{value: left}, %right_datatype{value: right}) do
cond do cond do
XSD.Decimal.datatype?(left_datatype) or XSD.Decimal.datatype?(right_datatype) -> XSD.Decimal.datatype?(left_datatype) or XSD.Decimal.datatype?(right_datatype) ->
equal_decimal_value?(left, right) equal_decimal_value?(left, right)
@ -36,7 +36,7 @@ defmodule RDF.XSD.Numeric do
end end
end end
def equal_value?(_, _), do: nil def do_equal_value?(_, _), do: nil
defp equal_decimal_value?(%D{} = left, %D{} = right), do: D.equal?(left, right) defp equal_decimal_value?(%D{} = left, %D{} = right), do: D.equal?(left, right)
@ -51,7 +51,7 @@ defmodule RDF.XSD.Numeric do
defp new_decimal(value) when is_float(value), do: D.from_float(value) defp new_decimal(value) when is_float(value), do: D.from_float(value)
defp new_decimal(value), do: D.new(value) defp new_decimal(value), do: D.new(value)
@doc """ @doc !"""
Compares two numeric XSD literals. Compares two numeric XSD literals.
Returns `:gt` if first literal is greater than the second and `:lt` for vice Returns `:gt` if first literal is greater than the second and `:lt` for vice
@ -60,36 +60,14 @@ defmodule RDF.XSD.Numeric do
Returns `nil` when the given arguments are not comparable datatypes. Returns `nil` when the given arguments are not comparable datatypes.
""" """
@spec compare(Literal.t | t, Literal.t | t) :: XSD.Datatype.comparison_result() | nil @spec do_compare(t, t) :: Literal.Datatype.comparison_result() | nil
def compare(left, right) def do_compare(left, right)
def compare(left, %Literal{literal: right}), do: compare(left, right)
def compare(%Literal{literal: left}, right), do: compare(left, right)
def compare( def do_compare(%left_datatype{value: left}, %right_datatype{value: right}) do
%XSD.Decimal{value: left},
%right_datatype{value: right}
) do
if datatype?(right_datatype) do
compare_decimal_value(left, right)
end
end
def compare(
%left_datatype{value: left},
%XSD.Decimal{value: right}
) do
if datatype?(left_datatype) do
compare_decimal_value(left, right)
end
end
def compare(
%left_datatype{value: left},
%right_datatype{value: right}
)
when not (is_nil(left) or is_nil(right)) do
if datatype?(left_datatype) and datatype?(right_datatype) do if datatype?(left_datatype) and datatype?(right_datatype) do
cond do cond do
XSD.Decimal.datatype?(left_datatype) or XSD.Decimal.datatype?(right_datatype) ->
compare_decimal_value(left, right)
left < right -> :lt left < right -> :lt
left > right -> :gt left > right -> :gt
true -> :eq true -> :eq
@ -97,7 +75,7 @@ defmodule RDF.XSD.Numeric do
end end
end end
def compare(_, _), do: nil def do_compare(_, _), do: nil
defp compare_decimal_value(%D{} = left, %D{} = right), do: D.cmp(left, right) defp compare_decimal_value(%D{} = left, %D{} = right), do: D.cmp(left, right)

View file

@ -2,6 +2,7 @@ defmodule RDF.XSD.ComparisonTest do
use ExUnit.Case use ExUnit.Case
alias RDF.XSD alias RDF.XSD
alias RDF.TestDatatypes.{Initials, Age, DecimalUnitInterval, CustomTime, DateWithoutTz, DateTimeWithTz}
describe "XSD.String" do describe "XSD.String" do
@ordered_strings [ @ordered_strings [
@ -17,6 +18,13 @@ defmodule RDF.XSD.ComparisonTest do
assert_equal({XSD.string("foo"), XSD.string("foo")}) assert_equal({XSD.string("foo"), XSD.string("foo")})
end end
test "valid comparisons between derived string literals" do
assert_equal({Initials.new("fo"), XSD.string("fo")})
assert_order({Initials.new("ba"), Initials.new("fo")})
assert_order({Initials.new("ba"), XSD.string("foo")})
assert_order({XSD.string("bar"), Initials.new("fo")})
end
test "invalid comparison between string and langString literals" do test "invalid comparison between string and langString literals" do
assert_incomparable({XSD.string("foo"), RDF.langString("foo", :en)}) assert_incomparable({XSD.string("foo"), RDF.langString("foo", :en)})
end end
@ -50,7 +58,14 @@ defmodule RDF.XSD.ComparisonTest do
{XSD.non_negative_integer(0), XSD.integer(1)}, {XSD.non_negative_integer(0), XSD.integer(1)},
{XSD.integer(0), XSD.positive_integer(1)}, {XSD.integer(0), XSD.positive_integer(1)},
{XSD.non_negative_integer(0), XSD.positive_integer(1)}, {XSD.non_negative_integer(0), XSD.positive_integer(1)},
{XSD.positive_integer(1), XSD.non_negative_integer(2)} {XSD.positive_integer(1), XSD.non_negative_integer(2)},
{XSD.positive_integer(1), XSD.non_negative_integer(2)},
{Age.new(1), Age.new(2)},
{Age.new(1), XSD.integer(2)},
{XSD.non_negative_integer(1), Age.new(2)},
{Age.new(1), XSD.decimal(2.1)},
{XSD.decimal(0.1), DecimalUnitInterval.new(0.2)},
{DecimalUnitInterval.new(0.3), Age.new(2)},
], ],
&assert_order/1 &assert_order/1
) )
@ -89,6 +104,7 @@ defmodule RDF.XSD.ComparisonTest do
) )
assert_order({XSD.datetime("2000-01-15T12:00:00"), XSD.datetime("2000-01-16T12:00:00Z")}) assert_order({XSD.datetime("2000-01-15T12:00:00"), XSD.datetime("2000-01-16T12:00:00Z")})
assert_order({XSD.datetime("2000-01-15T12:00:00"), DateTimeWithTz.new("2000-01-16T12:00:00Z")})
end end
test "when unequal due to missing time zone" do test "when unequal due to missing time zone" do
@ -110,6 +126,10 @@ defmodule RDF.XSD.ComparisonTest do
{XSD.datetime("2002-04-02T23:00:00-04:00"), XSD.datetime("2002-04-03T02:00:00-01:00")} {XSD.datetime("2002-04-02T23:00:00-04:00"), XSD.datetime("2002-04-03T02:00:00-01:00")}
) )
assert_equal(
{DateTimeWithTz.new("2002-04-02T23:00:00-04:00"), XSD.datetime("2002-04-03T02:00:00-01:00")}
)
assert_equal({XSD.datetime("1999-12-31T24:00:00"), XSD.datetime("2000-01-01T00:00:00")}) assert_equal({XSD.datetime("1999-12-31T24:00:00"), XSD.datetime("2000-01-01T00:00:00")})
# TODO: Assume that the dynamic context provides an implicit timezone value of -05:00 # TODO: Assume that the dynamic context provides an implicit timezone value of -05:00
# assert_equal {XSD.datetime("2002-04-02T12:00:00"), XSD.datetime("2002-04-02T23:00:00+06:00")} # assert_equal {XSD.datetime("2002-04-02T12:00:00"), XSD.datetime("2002-04-02T23:00:00+06:00")}
@ -127,6 +147,10 @@ defmodule RDF.XSD.ComparisonTest do
assert_indeterminate( assert_indeterminate(
{XSD.datetime("2000-01-16T00:00:00"), XSD.datetime("2000-01-16T12:00:00Z")} {XSD.datetime("2000-01-16T00:00:00"), XSD.datetime("2000-01-16T12:00:00Z")}
) )
assert_indeterminate(
{XSD.datetime("2000-01-16T00:00:00"), DateTimeWithTz.new("2000-01-16T12:00:00Z")}
)
end end
end end
@ -135,6 +159,8 @@ defmodule RDF.XSD.ComparisonTest do
assert_order({XSD.date("2002-04-02"), XSD.date("2002-04-03")}) assert_order({XSD.date("2002-04-02"), XSD.date("2002-04-03")})
assert_order({XSD.date("2002-04-02+01:00"), XSD.date("2002-04-03+00:00")}) assert_order({XSD.date("2002-04-02+01:00"), XSD.date("2002-04-03+00:00")})
assert_order({XSD.date("2002-04-02"), XSD.date("2002-04-03Z")}) assert_order({XSD.date("2002-04-02"), XSD.date("2002-04-03Z")})
assert_order({DateWithoutTz.new("2002-04-02"), XSD.date("2002-04-03Z")})
assert_order({DateWithoutTz.new("2002-04-02"), DateWithoutTz.new("2002-04-03")})
end end
test "when equal" do test "when equal" do
@ -143,12 +169,14 @@ defmodule RDF.XSD.ComparisonTest do
assert_equal({XSD.date("2002-04-02-00:00"), XSD.date("2002-04-02+00:00")}) assert_equal({XSD.date("2002-04-02-00:00"), XSD.date("2002-04-02+00:00")})
assert_equal({XSD.date("2002-04-02Z"), XSD.date("2002-04-02+00:00")}) assert_equal({XSD.date("2002-04-02Z"), XSD.date("2002-04-02+00:00")})
assert_equal({XSD.date("2002-04-02Z"), XSD.date("2002-04-02-00:00")}) assert_equal({XSD.date("2002-04-02Z"), XSD.date("2002-04-02-00:00")})
assert_equal({XSD.date("2002-04-02"), DateWithoutTz.new("2002-04-02")})
end end
test "when indeterminate" do test "when indeterminate" do
assert_indeterminate({XSD.date("2002-04-02Z"), XSD.date("2002-04-02")}) assert_indeterminate({XSD.date("2002-04-02Z"), XSD.date("2002-04-02")})
assert_indeterminate({XSD.date("2002-04-02+00:00"), XSD.date("2002-04-02")}) assert_indeterminate({XSD.date("2002-04-02+00:00"), XSD.date("2002-04-02")})
assert_indeterminate({XSD.date("2002-04-02-00:00"), XSD.date("2002-04-02")}) assert_indeterminate({XSD.date("2002-04-02-00:00"), XSD.date("2002-04-02")})
assert_indeterminate({XSD.date("2002-04-02Z"), DateWithoutTz.new("2002-04-02")})
end end
end end
@ -187,18 +215,21 @@ defmodule RDF.XSD.ComparisonTest do
test "when unequal" do test "when unequal" do
assert_order({XSD.time("12:00:00+01:00"), XSD.time("13:00:00+01:00")}) assert_order({XSD.time("12:00:00+01:00"), XSD.time("13:00:00+01:00")})
assert_order({XSD.time("12:00:00"), XSD.time("13:00:00")}) assert_order({XSD.time("12:00:00"), XSD.time("13:00:00")})
assert_order({CustomTime.new("12:00:00"), CustomTime.new("13:00:00")})
end end
test "when equal" do test "when equal" do
assert_equal({XSD.time("12:00:00+01:00"), XSD.time("12:00:00+01:00")}) assert_equal({XSD.time("12:00:00+01:00"), XSD.time("12:00:00+01:00")})
assert_equal({XSD.time("12:00:00"), XSD.time("12:00:00")}) assert_equal({XSD.time("12:00:00"), XSD.time("12:00:00")})
assert_equal({CustomTime.new("12:00:00+01:00"), XSD.time("12:00:00+01:00")})
end end
test "when indeterminate" do # TODO:
assert_indeterminate({XSD.date("2002-04-02Z"), XSD.date("2002-04-02")}) # test "when indeterminate" do
assert_indeterminate({XSD.date("2002-04-02+00:00"), XSD.date("2002-04-02")}) # assert_indeterminate({XSD.time("12:00:00Z"), XSD.time("12:00:00")})
assert_indeterminate({XSD.date("2002-04-02-00:00"), XSD.date("2002-04-02")}) # assert_indeterminate({XSD.time("12:00:00+00:00"), XSD.time("12:00:00")})
end # assert_indeterminate({XSD.time("12:00:00-00:00"), XSD.time("12:00:00")})
# end
end end
describe "incomparable" do describe "incomparable" do
@ -231,6 +262,7 @@ defmodule RDF.XSD.ComparisonTest do
Enum.each( Enum.each(
[ [
{XSD.true(), XSD.boolean(42)}, {XSD.true(), XSD.boolean(42)},
{XSD.false(), Age.new(242)},
{XSD.datetime("2002-04-02T12:00:00"), XSD.datetime("2002.04.02 12:00")}, {XSD.datetime("2002-04-02T12:00:00"), XSD.datetime("2002.04.02 12:00")},
{XSD.date("2002-04-02"), XSD.date("2002.04.02")}, {XSD.date("2002-04-02"), XSD.date("2002.04.02")},
{XSD.time("12:00:00"), XSD.time("12-00-00")} {XSD.time("12:00:00"), XSD.time("12-00-00")}