Add comparable?/2 functions to RDF.Literal and RDF.Literal.Datatypes
This commit is contained in:
parent
66cc9292c9
commit
287839740c
8 changed files with 79 additions and 0 deletions
|
@ -202,6 +202,13 @@ defmodule RDF.Literal do
|
|||
|
||||
def equal_value?(_, _), do: false
|
||||
|
||||
@spec comparable?(t, t) :: boolean
|
||||
def comparable?(%__MODULE__{literal: %datatype{} = left}, right) do
|
||||
Datatype.Registry.rdf_datatype(datatype).comparable?(left, right)
|
||||
end
|
||||
|
||||
def comparable?(_, _), do: false
|
||||
|
||||
@spec compare(t, t) :: Datatype.comparison_result | :indeterminate | nil
|
||||
def compare(%__MODULE__{literal: %datatype{} = left}, right) do
|
||||
Datatype.Registry.rdf_datatype(datatype).compare(left, right)
|
||||
|
|
|
@ -86,6 +86,15 @@ defmodule RDF.Literal.Datatype do
|
|||
"""
|
||||
@callback compare(Literal.t() | literal, Literal.t() | literal) :: comparison_result | :indeterminate | nil
|
||||
|
||||
@doc """
|
||||
Checks if two datatype literals are comparable.
|
||||
|
||||
This basically mimics the comparability check in terms of the `=` operator of the SPARQL
|
||||
which handles equality comparisons between some datatypes as errors, i.e. considering
|
||||
them as incompatible.
|
||||
"""
|
||||
@callback comparable?(Literal.t() | literal, Literal.t() | literal) :: boolean
|
||||
|
||||
@callback update(Literal.t() | literal, fun()) :: Literal.t
|
||||
@callback update(Literal.t() | literal, fun(), keyword) :: Literal.t
|
||||
end
|
||||
|
|
|
@ -89,6 +89,14 @@ defmodule RDF.Literal.Generic do
|
|||
def equal_value?(%Literal{literal: left}, right), do: equal_value?(left, right)
|
||||
def equal_value?(%__MODULE__{} = left, right), do: left == right
|
||||
|
||||
@impl Datatype
|
||||
def comparable?(left, %Literal{literal: right}), do: comparable?(left, right)
|
||||
def comparable?(%Literal{literal: left}, right), do: comparable?(left, right)
|
||||
def comparable?(%__MODULE__{datatype: left_datatype},
|
||||
%__MODULE__{datatype: right_datatype}),
|
||||
do: left_datatype == right_datatype
|
||||
def comparable?(_, _), do: false
|
||||
|
||||
@impl Datatype
|
||||
def compare(left, %Literal{literal: right}), do: compare(left, right)
|
||||
def compare(%Literal{literal: left}, right), do: compare(left, right)
|
||||
|
|
|
@ -95,6 +95,12 @@ defmodule RDF.LangString do
|
|||
def equal_value?(%__MODULE__{} = left, right), do: left == right
|
||||
def equal_value?(_, _), do: false
|
||||
|
||||
@impl Datatype
|
||||
def comparable?(left, %Literal{literal: right}), do: comparable?(left, right)
|
||||
def comparable?(%Literal{literal: left}, right), do: comparable?(left, right)
|
||||
def comparable?(%__MODULE__{}, %__MODULE__{}), do: true
|
||||
def comparable?(_, _), do: false
|
||||
|
||||
@impl Datatype
|
||||
def compare(left, %Literal{literal: right}), do: compare(left, right)
|
||||
def compare(%Literal{literal: left}, right), do: compare(left, right)
|
||||
|
|
|
@ -92,6 +92,14 @@ defmodule RDF.Literal.XSD do
|
|||
end
|
||||
def equal_value?(_, _), do: false
|
||||
|
||||
@impl RDF.Literal.Datatype
|
||||
def comparable?(left, %Literal{literal: right}), do: comparable?(left, right)
|
||||
def comparable?(%Literal{literal: left}, right), do: comparable?(left, right)
|
||||
def comparable?(%unquote(xsd_datatype){} = left, right) do
|
||||
XSD.Literal.comparable?(left, right)
|
||||
end
|
||||
def comparable?(_, _), do: false
|
||||
|
||||
@impl RDF.Literal.Datatype
|
||||
@dialyzer {:nowarn_function, compare: 2} # TODO: Why is this warning raised
|
||||
def compare(left, %Literal{literal: right}), do: compare(left, right)
|
||||
|
|
|
@ -165,6 +165,22 @@ defmodule RDF.Literal.GenericTest do
|
|||
assert Generic.equal_value?(Generic.new("foo", datatype: "foo"), RDF.XSD.String.new("foo")) == false
|
||||
end
|
||||
|
||||
test "comparable?/2" do
|
||||
Enum.each @valid, fn {input, {_, datatype}} ->
|
||||
assert Generic.comparable?(
|
||||
Generic.new(input, datatype: datatype),
|
||||
Generic.new(input, datatype: datatype)) == true
|
||||
end
|
||||
|
||||
assert Generic.comparable?(
|
||||
Generic.new("foo", datatype: "http://example.com/foo"),
|
||||
Generic.new("foo", datatype: "http://example.com/bar")) == false
|
||||
|
||||
assert Generic.comparable?(
|
||||
Generic.new("foo", datatype: "http://example.com/foo"),
|
||||
RDF.string("foo")) == false
|
||||
end
|
||||
|
||||
test "compare/2" do
|
||||
Enum.each @valid, fn {input, {_, datatype}} ->
|
||||
assert Generic.compare(
|
||||
|
|
|
@ -198,6 +198,22 @@ defmodule RDF.LangStringTest do
|
|||
assert LangString.equal_value?(RDF.XSD.String.new("foo"), LangString.new("foo", [])) == false
|
||||
end
|
||||
|
||||
test "comparable?/2" do
|
||||
Enum.each @valid, fn {input, {_, language}} ->
|
||||
assert LangString.comparable?(
|
||||
LangString.new(input, language: language),
|
||||
LangString.new(input, language: language)) == true
|
||||
end
|
||||
|
||||
assert LangString.comparable?(
|
||||
LangString.new("foo", language: "en"),
|
||||
LangString.new("foo", language: "de")) == true # TODO: This is an assumption. Couldn't find anything in the specs yet.
|
||||
|
||||
assert LangString.comparable?(
|
||||
LangString.new("foo", language: "de"),
|
||||
RDF.string("foo")) == false
|
||||
end
|
||||
|
||||
test "compare/2" do
|
||||
Enum.each @valid, fn {input, {_, language}} ->
|
||||
assert LangString.compare(
|
||||
|
|
|
@ -140,6 +140,15 @@ defmodule RDF.Literal.XSDTest do
|
|||
end
|
||||
end)
|
||||
|
||||
Enum.each(@examples, fn {rdf_datatype, xsd_datatype, value_type} ->
|
||||
value = value_type |> value() |> List.first()
|
||||
@tag rdf_datatype: rdf_datatype, xsd_datatype: xsd_datatype, value: value
|
||||
test "#{rdf_datatype}.comparable?/2 (#{inspect value})", %{rdf_datatype: rdf_datatype, value: value} do
|
||||
literal = rdf_datatype.new(value)
|
||||
assert rdf_datatype.comparable?(literal, literal) == true
|
||||
end
|
||||
end)
|
||||
|
||||
describe "cast/1" do
|
||||
test "when given a literal with the same datatype" do
|
||||
assert RDF.XSD.String.new("foo") |> RDF.XSD.String.cast() == RDF.XSD.String.new("foo")
|
||||
|
|
Loading…
Reference in a new issue