Remove coercion on RDF.Literal.Datatype.cast/1
It's not worth the effort and more explicit to do the coercion step manually.
This commit is contained in:
parent
accf66d75f
commit
c1a61c58e8
16 changed files with 27 additions and 169 deletions
|
@ -24,15 +24,17 @@ defmodule RDF.Literal.Datatype do
|
|||
@callback new!(any, Keyword.t()) :: Literal.t()
|
||||
|
||||
@doc """
|
||||
Casts a datatype literal or coercible value of one type into a datatype literal of another type.
|
||||
Casts a datatype literal of one type into a datatype literal of another type.
|
||||
|
||||
If the given literal or value is invalid or can not be converted into this datatype an
|
||||
implementation should return `nil`.
|
||||
This function is called by the auto-generated `cast/1` function on the implementations, which already deals with the basic cases.
|
||||
So, implementations can assume the passed argument is a valid `RDF.Literal.Datatype` struct.
|
||||
|
||||
This function is called by auto-generated `cast/1` function on the implementations,
|
||||
which already deals with basic cases and coercion.
|
||||
If the given literal can not be converted into this datatype an implementation should return `nil`.
|
||||
|
||||
A final catch-all clause should delegate to `super`. For example `RDF.XSD.Datatype`s will handle casting from derived
|
||||
datatypes in the default implementation.
|
||||
"""
|
||||
@callback do_cast(literal | any) :: Literal.t() | nil
|
||||
@callback do_cast(literal) :: Literal.t() | nil
|
||||
|
||||
@doc """
|
||||
Checks if the given `RDF.Literal` has the datatype for which the `RDF.Literal.Datatype` is implemented or is derived from it.
|
||||
|
@ -222,32 +224,33 @@ defmodule RDF.Literal.Datatype do
|
|||
def canonical_lexical(_), do: nil
|
||||
|
||||
@doc """
|
||||
Casts a datatype literal or coercible value of one type into a datatype literal of another type.
|
||||
Casts a datatype literal of one type into a datatype literal of another type.
|
||||
|
||||
Returns `nil` when the given arguments are not comparable as literals of this
|
||||
datatype or when the given argument is an invalid literal.
|
||||
Returns `nil` when the given arguments are not castable into this datatype or when the given argument is an
|
||||
invalid literal.
|
||||
|
||||
Implementations define the casting for a given value with the `c:do_cast/1` callback.
|
||||
"""
|
||||
@spec cast(any) :: Literal.t() | nil
|
||||
@spec cast(Literal.t | Literal.Datatype.literal) :: Literal.t() | nil
|
||||
@dialyzer {:nowarn_function, cast: 1}
|
||||
def cast(literal_or_value)
|
||||
def cast(%Literal{literal: literal}), do: cast(literal)
|
||||
def cast(%__MODULE__{} = datatype_literal),
|
||||
do: if(valid?(datatype_literal), do: literal(datatype_literal))
|
||||
def cast(nil), do: nil
|
||||
def cast(value) do
|
||||
case do_cast(value) do
|
||||
%__MODULE__{} = literal -> if valid?(literal), do: literal(literal)
|
||||
%Literal{literal: %__MODULE__{}} = literal -> if valid?(literal), do: literal
|
||||
_ -> nil
|
||||
def cast(%struct{} = datatype_literal) do
|
||||
if Literal.datatype?(struct) and Literal.Datatype.valid?(datatype_literal) do
|
||||
case do_cast(datatype_literal) do
|
||||
%__MODULE__{} = literal -> if valid?(literal), do: literal(literal)
|
||||
%Literal{literal: %__MODULE__{}} = literal -> if valid?(literal), do: literal
|
||||
_ -> nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def cast(_), do: nil
|
||||
|
||||
@impl unquote(__MODULE__)
|
||||
def do_cast(value) do
|
||||
value |> Literal.coerce() |> cast()
|
||||
end
|
||||
def do_cast(value), do: nil
|
||||
|
||||
@doc """
|
||||
Checks if two datatype literals are equal in terms of the values of their value space.
|
||||
|
|
|
@ -186,20 +186,6 @@ defmodule RDF.XSD.Datatype do
|
|||
literal(%__MODULE__{uncanonical_lexical: init_invalid_lexical(lexical, opts)})
|
||||
end
|
||||
|
||||
def cast(literal_or_value)
|
||||
def cast(%RDF.Literal{literal: literal}), do: cast(literal)
|
||||
# Invalid values can not be casted in general
|
||||
def cast(%{value: @invalid_value}), do: nil
|
||||
def cast(%__MODULE__{} = datatype_literal), do: literal(datatype_literal)
|
||||
def cast(nil), do: nil
|
||||
def cast(value) do
|
||||
case do_cast(value) do
|
||||
%__MODULE__{} = literal -> if valid?(literal), do: literal(literal)
|
||||
%RDF.Literal{literal: %__MODULE__{}} = literal -> if valid?(literal), do: literal
|
||||
_ -> nil
|
||||
end
|
||||
end
|
||||
|
||||
@impl RDF.Literal.Datatype
|
||||
def value(%RDF.Literal{literal: literal}), do: value(literal)
|
||||
def value(%__MODULE__{} = literal), do: literal.value
|
||||
|
|
|
@ -43,12 +43,8 @@ defmodule RDF.XSD.Datatype.Primitive do
|
|||
|
||||
@impl RDF.Literal.Datatype
|
||||
def do_cast(value) do
|
||||
if RDF.Literal.datatype?(value) do
|
||||
if datatype?(value) do
|
||||
build_valid(value.value, value.uncanonical_lexical, [])
|
||||
end
|
||||
else
|
||||
value |> RDF.Literal.coerce() |> cast()
|
||||
if datatype?(value) do # i.e. derived datatype
|
||||
build_valid(value.value, value.uncanonical_lexical, [])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ defmodule RDF.XSD.AnyURI do
|
|||
@impl RDF.XSD.Datatype
|
||||
@spec elixir_mapping(any, Keyword.t()) :: value
|
||||
def elixir_mapping(%URI{} = uri, _), do: uri
|
||||
def elixir_mapping(%IRI{} = iri, _), do: IRI.parse(iri)
|
||||
|
||||
def elixir_mapping(value, _) when maybe_ns_term(value) do
|
||||
case RDF.Namespace.resolve_term(value) do
|
||||
|
@ -33,7 +34,6 @@ defmodule RDF.XSD.AnyURI do
|
|||
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
|
||||
|
|
|
@ -39,8 +39,6 @@ defmodule RDF.XSD.String do
|
|||
@impl RDF.Literal.Datatype
|
||||
def do_cast(value)
|
||||
|
||||
def do_cast(%RDF.IRI{value: value}), do: new(value)
|
||||
|
||||
def do_cast(%RDF.XSD.Decimal{} = xsd_decimal) do
|
||||
try do
|
||||
xsd_decimal.value
|
||||
|
|
|
@ -9,6 +9,8 @@ defmodule RDF.XSD.AnyURITest do
|
|||
{URI.parse("http://example.com/foo"), nil, "http://example.com/foo"},
|
||||
URI.parse("http://example.com/foo") =>
|
||||
{URI.parse("http://example.com/foo"), nil, "http://example.com/foo"},
|
||||
RDF.iri("http://example.com/foo") =>
|
||||
{URI.parse("http://example.com/foo"), nil, "http://example.com/foo"},
|
||||
RDF.List =>
|
||||
{URI.parse("http://www.w3.org/1999/02/22-rdf-syntax-ns#List"), nil, "http://www.w3.org/1999/02/22-rdf-syntax-ns#List"},
|
||||
},
|
||||
|
@ -20,20 +22,5 @@ defmodule RDF.XSD.AnyURITest 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
|
||||
|
|
|
@ -91,20 +91,6 @@ defmodule RDF.XSD.BooleanTest do
|
|||
test "with values of unsupported datatypes" do
|
||||
assert XSD.date("2020-01-01") |> XSD.Boolean.cast() == nil
|
||||
end
|
||||
|
||||
test "with coercible value" do
|
||||
assert XSD.Boolean.cast(0) == XSD.false()
|
||||
assert XSD.Boolean.cast(0.0) == XSD.false()
|
||||
assert XSD.Boolean.cast(42) == XSD.true()
|
||||
assert XSD.Boolean.cast(3.14) == XSD.true()
|
||||
assert XSD.Boolean.cast("true") == XSD.true()
|
||||
assert XSD.Boolean.cast("false") == XSD.false()
|
||||
end
|
||||
|
||||
test "with non-coercible value" do
|
||||
assert XSD.Boolean.cast(:foo) == nil
|
||||
assert XSD.Boolean.cast(make_ref()) == nil
|
||||
end
|
||||
end
|
||||
|
||||
describe "ebv/1" do
|
||||
|
|
|
@ -127,14 +127,5 @@ defmodule RDF.XSD.DateTest do
|
|||
assert XSD.integer(1) |> XSD.Date.cast() == nil
|
||||
assert XSD.decimal(3.14) |> XSD.Date.cast() == nil
|
||||
end
|
||||
|
||||
test "with coercible value" do
|
||||
assert XSD.Date.cast("2010-01-01") == XSD.date("2010-01-01")
|
||||
end
|
||||
|
||||
test "with non-coercible value" do
|
||||
assert XSD.Date.cast(:foo) == nil
|
||||
assert XSD.Date.cast(make_ref()) == nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -113,15 +113,6 @@ defmodule RDF.XSD.DateTimeTest do
|
|||
assert XSD.integer(1) |> XSD.DateTime.cast() == nil
|
||||
assert XSD.decimal(3.14) |> XSD.DateTime.cast() == nil
|
||||
end
|
||||
|
||||
test "with coercible value" do
|
||||
assert XSD.DateTime.cast("2010-01-01T12:34:56") == XSD.datetime("2010-01-01T12:34:56")
|
||||
end
|
||||
|
||||
test "with non-coercible value" do
|
||||
assert XSD.DateTime.cast(:foo) == nil
|
||||
assert XSD.DateTime.cast(make_ref()) == nil
|
||||
end
|
||||
end
|
||||
|
||||
test "now/0" do
|
||||
|
|
|
@ -127,16 +127,6 @@ defmodule RDF.XSD.DecimalTest do
|
|||
test "with literals of unsupported datatypes" do
|
||||
assert XSD.date("2020-01-01") |> XSD.Decimal.cast() == nil
|
||||
end
|
||||
|
||||
test "with coercible value" do
|
||||
assert XSD.Decimal.cast("3.14") == XSD.decimal(3.14)
|
||||
assert XSD.Decimal.cast("42") == XSD.decimal(42.0)
|
||||
end
|
||||
|
||||
test "with non-coercible value" do
|
||||
assert XSD.Decimal.cast(:foo) == nil
|
||||
assert XSD.Decimal.cast(make_ref()) == nil
|
||||
end
|
||||
end
|
||||
|
||||
test "digit_count/1" do
|
||||
|
|
|
@ -68,14 +68,5 @@ defmodule RDF.XSD.DoubleTest do
|
|||
test "with literals of unsupported datatypes" do
|
||||
assert XSD.date("2020-01-01") |> XSD.Double.cast() == nil
|
||||
end
|
||||
|
||||
test "with coercible value" do
|
||||
assert XSD.Double.cast("3.14") == XSD.double(3.14) |> XSD.Double.canonical()
|
||||
end
|
||||
|
||||
test "with non-coercible value" do
|
||||
assert XSD.Double.cast(:foo) == nil
|
||||
assert XSD.Double.cast(make_ref()) == nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -85,18 +85,6 @@ defmodule RDF.XSD.IntegerTest do
|
|||
test "with literals of unsupported datatypes" do
|
||||
assert XSD.date("2020-01-01") |> XSD.Integer.cast() == nil
|
||||
end
|
||||
|
||||
test "with coercible value" do
|
||||
assert XSD.Integer.cast("42") == XSD.integer(42)
|
||||
assert XSD.Integer.cast(3.14) == XSD.integer(3)
|
||||
assert XSD.Integer.cast(true) == XSD.integer(1)
|
||||
assert XSD.Integer.cast(false) == XSD.integer(0)
|
||||
end
|
||||
|
||||
test "with non-coercible value" do
|
||||
assert XSD.Integer.cast(:foo) == nil
|
||||
assert XSD.Integer.cast(make_ref()) == nil
|
||||
end
|
||||
end
|
||||
|
||||
test "digit_count/1" do
|
||||
|
|
|
@ -107,17 +107,5 @@ defmodule RDF.XSD.NonNegativeIntegerTest do
|
|||
test "with literals of unsupported datatypes" do
|
||||
assert XSD.date("2020-01-01") |> XSD.NonNegativeInteger.cast() == nil
|
||||
end
|
||||
|
||||
test "with coercible value" do
|
||||
assert XSD.NonNegativeInteger.cast("42") == XSD.non_negative_integer(42)
|
||||
assert XSD.NonNegativeInteger.cast(3.14) == XSD.non_negative_integer(3)
|
||||
assert XSD.NonNegativeInteger.cast(true) == XSD.non_negative_integer(1)
|
||||
assert XSD.NonNegativeInteger.cast(false) == XSD.non_negative_integer(0)
|
||||
end
|
||||
|
||||
test "with non-coercible value" do
|
||||
assert XSD.NonNegativeInteger.cast(:foo) == nil
|
||||
assert XSD.NonNegativeInteger.cast(make_ref()) == nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -117,17 +117,5 @@ defmodule RDF.XSD.PositiveIntegerTest do
|
|||
test "with literals of unsupported datatypes" do
|
||||
assert XSD.date("2020-01-01") |> XSD.PositiveInteger.cast() == nil
|
||||
end
|
||||
|
||||
test "with coercible value" do
|
||||
assert XSD.PositiveInteger.cast("42") == XSD.positive_integer(42)
|
||||
assert XSD.PositiveInteger.cast(3.14) == XSD.positive_integer(3)
|
||||
assert XSD.PositiveInteger.cast(true) == XSD.positive_integer(1)
|
||||
assert XSD.PositiveInteger.cast(false) == nil
|
||||
end
|
||||
|
||||
test "with non-coercible value" do
|
||||
assert XSD.PositiveInteger.cast(:foo) == nil
|
||||
assert XSD.PositiveInteger.cast(make_ref()) == nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -117,26 +117,10 @@ defmodule RDF.XSD.StringTest do
|
|||
assert XSD.time("00:00:00+01:00") |> XSD.String.cast() == XSD.string("00:00:00+01:00")
|
||||
end
|
||||
|
||||
test "casting an IRI" do
|
||||
assert RDF.iri("http://example.com") |> XSD.String.cast() == XSD.string("http://example.com")
|
||||
end
|
||||
|
||||
test "with invalid literals" do
|
||||
assert XSD.integer(3.14) |> XSD.String.cast() == nil
|
||||
assert XSD.decimal("NAN") |> XSD.String.cast() == nil
|
||||
assert XSD.double(true) |> XSD.String.cast() == nil
|
||||
end
|
||||
|
||||
test "with coercible value" do
|
||||
assert XSD.String.cast(42) == XSD.string("42")
|
||||
assert XSD.String.cast(3.14) == XSD.string("3.14")
|
||||
assert XSD.String.cast(true) == XSD.string("true")
|
||||
assert XSD.String.cast(false) == XSD.string("false")
|
||||
end
|
||||
|
||||
test "with non-coercible value" do
|
||||
assert XSD.String.cast(:foo) == nil
|
||||
assert XSD.String.cast(make_ref()) == nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -138,14 +138,5 @@ defmodule RDF.XSD.TimeTest do
|
|||
assert XSD.integer(1) |> XSD.Time.cast() == nil
|
||||
assert XSD.decimal(3.14) |> XSD.Time.cast() == nil
|
||||
end
|
||||
|
||||
test "with coercible value" do
|
||||
assert XSD.Time.cast("01:00:00") == XSD.time("01:00:00")
|
||||
end
|
||||
|
||||
test "with non-coercible value" do
|
||||
assert XSD.Time.cast(:foo) == nil
|
||||
assert XSD.Time.cast(make_ref()) == nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue