Interop between RDF.IRI and XSD.AnyURI in terms of cast and equal_value?

This commit is contained in:
Marcel Otto 2020-05-06 16:48:31 +02:00
parent 6057749d2a
commit 00a6103e56
5 changed files with 66 additions and 16 deletions

View file

@ -49,11 +49,11 @@ defmodule RDF.IRI do
"""
@spec new(coercible) :: t
def new(iri)
def new(iri) when is_binary(iri), do: %RDF.IRI{value: iri}
def new(iri) when is_binary(iri), do: %__MODULE__{value: iri}
def new(qname) when is_atom(qname) and qname not in [nil, true, false],
do: Namespace.resolve_term(qname)
def new(%URI{} = uri), do: uri |> URI.to_string |> new
def new(%RDF.IRI{} = iri), do: iri
def new(%__MODULE__{} = iri), do: iri
@doc """
Creates a `RDF.IRI`, but checks if the given IRI is valid.
@ -68,7 +68,7 @@ defmodule RDF.IRI do
def new!(qname) when is_atom(qname) and qname not in [nil, true, false],
do: new(qname) # since terms of a namespace are already validated
def new!(%URI{} = uri), do: uri |> valid!() |> new()
def new!(%RDF.IRI{} = iri), do: valid!(iri)
def new!(%__MODULE__{} = iri), do: valid!(iri)
@doc """
@ -136,7 +136,7 @@ defmodule RDF.IRI do
def absolute?(iri)
def absolute?(value) when is_binary(value), do: not is_nil(scheme(value))
def absolute?(%RDF.IRI{value: value}), do: absolute?(value)
def absolute?(%__MODULE__{value: value}), do: absolute?(value)
def absolute?(%URI{scheme: nil}), do: false
def absolute?(%URI{scheme: _}), do: true
def absolute?(qname) when is_atom(qname) and qname not in [nil, true, false] do
@ -198,7 +198,7 @@ defmodule RDF.IRI do
"""
@spec scheme(coercible) :: String.t | nil
def scheme(iri)
def scheme(%RDF.IRI{value: value}), do: scheme(value)
def scheme(%__MODULE__{value: value}), do: scheme(value)
def scheme(%URI{scheme: scheme}), do: scheme
def scheme(qname) when is_atom(qname), do: Namespace.resolve_term(qname) |> scheme()
def scheme(iri) when is_binary(iri) do
@ -216,7 +216,7 @@ defmodule RDF.IRI do
def parse(iri) when is_binary(iri), do: URI.parse(iri)
def parse(qname) when is_atom(qname) and qname not in [nil, true, false],
do: Namespace.resolve_term(qname) |> parse()
def parse(%RDF.IRI{value: value}), do: URI.parse(value)
def parse(%__MODULE__{value: value}), do: URI.parse(value)
def parse(%URI{} = uri), do: uri
@ -230,9 +230,14 @@ defmodule RDF.IRI do
@spec equal_value?(t | RDF.Literal.t, t | RDF.Literal.t) :: boolean | nil
def equal_value?(left, right)
def equal_value?(%RDF.IRI{value: left}, %RDF.IRI{value: right}),
def equal_value?(%__MODULE__{value: left}, %__MODULE__{value: right}),
do: left == right
def equal_value?(%__MODULE__{} = left, %RDF.Literal{} = right),
do: RDF.Literal.equal_value?(right, left)
def equal_value?(%__MODULE__{value: left}, %URI{} = right),
do: left == URI.to_string(right)
def equal_value?(_, _),
do: nil
@ -256,7 +261,7 @@ defmodule RDF.IRI do
@spec to_string(t | module) :: String.t
def to_string(iri)
def to_string(%RDF.IRI{value: value}),
def to_string(%__MODULE__{value: value}),
do: value
def to_string(qname) when is_atom(qname),

View file

@ -214,8 +214,8 @@ defmodule RDF.Literal.Datatype do
def equal_value?(_, nil), do: nil
def equal_value?(left, right) do
cond do
not RDF.literal?(right) -> equal_value?(left, Literal.coerce(right))
not RDF.literal?(left) -> equal_value?(Literal.coerce(left), right)
not RDF.literal?(right) and not RDF.term?(right) -> equal_value?(left, Literal.coerce(right))
not RDF.literal?(left) and not RDF.term?(left) -> equal_value?(Literal.coerce(left), right)
true -> do_equal_value?(left, right)
end
end

View file

@ -7,6 +7,8 @@ defmodule RDF.XSD.AnyURI do
@type valid_value :: URI.t()
alias RDF.IRI
use RDF.XSD.Datatype.Primitive,
name: "anyURI",
id: RDF.Utils.Bootstrapping.xsd_iri("anyURI")
@ -19,4 +21,19 @@ defmodule RDF.XSD.AnyURI do
@spec elixir_mapping(any, Keyword.t()) :: value
def elixir_mapping(%URI{} = uri, _), do: uri
def elixir_mapping(_, _), do: @invalid_value
@impl RDF.Literal.Datatype
def do_cast(%IRI{} = iri), do: new(iri.value)
def do_cast(value), do: super(value)
@impl RDF.Literal.Datatype
def do_equal_value?(literal1, literal2)
def do_equal_value?(%IRI{} = iri, %__MODULE__{} = any_uri),
do: do_equal_value?(any_uri, iri)
def do_equal_value?(%__MODULE__{} = any_uri, %IRI{value: iri}),
do: lexical(any_uri) == iri
def do_equal_value?(literal1, literal2), do: super(literal1, literal2)
end

View file

@ -3,28 +3,33 @@ defmodule RDF.EqualityTest do
alias RDF.XSD
describe "RDF.IRI" do
describe "RDF.IRI and XSD.AnyURI" do
@term_equal_iris [
{RDF.iri("http://example.com/"), RDF.iri("http://example.com/")},
{XSD.anyURI("http://example.com/"), XSD.anyURI("http://example.com/")},
]
@value_equal_iris [
{RDF.iri("http://example.com/"), XSD.anyURI("http://example.com/")},
{XSD.anyURI("http://example.com/"), XSD.anyURI("http://example.com/")},
]
@unequal_iris [
{RDF.iri("http://example.com/foo"), RDF.iri("http://example.com/bar")},
{RDF.iri("http://example.com/foo"), XSD.anyURI("http://example.com/bar")},
]
@equal_iris_by_coercion []
@unequal_iris_by_coercion []
@equal_iris_by_coercion [
{RDF.iri("http://example.com/"), URI.parse("http://example.com/")},
{XSD.anyURI("http://example.com/"), URI.parse("http://example.com/")},
]
@unequal_iris_by_coercion [
{RDF.iri("http://example.com/foo"), URI.parse("http://example.com/bar")},
{XSD.anyURI("http://example.com/foo"), URI.parse("http://example.com/bar")},
]
@incomparable_iris [
{RDF.iri("http://example.com/"), XSD.string("http://example.com/")},
{XSD.anyURI("http://example.com/"), XSD.string("http://example.com/")},
]
test "term equality", do: assert_term_equal(@term_equal_iris)
@tag skip: "TODO: finish value equality of XSD.AnyURI"
test "value equality", do: assert_value_equal(@value_equal_iris)
@tag skip: "TODO: finish value equality of XSD.AnyURI"
test "inequality", do: assert_unequal(@unequal_iris)
test "coerced value equality", do: assert_coerced_equal(@equal_iris_by_coercion)
test "coerced value inequality", do: assert_coerced_unequal(@unequal_iris_by_coercion)

View file

@ -11,4 +11,27 @@ defmodule RDF.XSD.AnyURITest do
{URI.parse("http://example.com/foo"), nil, "http://example.com/foo"}
},
invalid: [42, 3.14, true, false]
describe "cast/1" do
test "casting an anyURI returns the input as it is" do
assert XSD.anyURI("http://example.com/") |> XSD.AnyURI.cast() ==
XSD.anyURI("http://example.com/")
end
test "casting an RDF.IRI" do
assert RDF.iri("http://example.com/") |> XSD.AnyURI.cast() ==
XSD.anyURI("http://example.com/")
end
test "with coercible value" do
assert URI.parse("http://example.com/") |> XSD.AnyURI.cast() ==
XSD.anyURI("http://example.com/")
end
test "with non-coercible value" do
assert XSD.string("http://example.com/") |> XSD.AnyURI.cast() == nil
assert XSD.AnyURI.cast(make_ref()) == nil
end
end
end