Restore ability to cast RDF.IRIs to XSD.Strings and XSD.AnyURIs
This is needed for SPARQL.
This commit is contained in:
parent
ffebf86505
commit
7daf494fb9
5 changed files with 23 additions and 4 deletions
|
@ -27,14 +27,15 @@ defmodule RDF.Literal.Datatype do
|
||||||
Casts a datatype literal of one type into a datatype literal of another type.
|
Casts a datatype literal of one type into a datatype literal of another type.
|
||||||
|
|
||||||
This function is called by the auto-generated `cast/1` function on the implementations, which already deals with the basic cases.
|
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.
|
So, implementations can assume the passed argument is a valid `RDF.Literal.Datatype` struct,
|
||||||
|
a `RDF.IRI` or a `RDF.BlankNode`.
|
||||||
|
|
||||||
If the given literal can not be converted into this datatype an implementation should return `nil`.
|
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
|
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.
|
datatypes in the default implementation.
|
||||||
"""
|
"""
|
||||||
@callback do_cast(literal) :: Literal.t() | nil
|
@callback do_cast(literal | RDF.IRI.t | RDF.BlankNode.t) :: Literal.t() | nil
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Checks if the given `RDF.Literal` has the datatype for which the `RDF.Literal.Datatype` is implemented or is derived from it.
|
Checks if the given `RDF.Literal` has the datatype for which the `RDF.Literal.Datatype` is implemented or is derived from it.
|
||||||
|
@ -231,14 +232,15 @@ defmodule RDF.Literal.Datatype do
|
||||||
|
|
||||||
Implementations define the casting for a given value with the `c:do_cast/1` callback.
|
Implementations define the casting for a given value with the `c:do_cast/1` callback.
|
||||||
"""
|
"""
|
||||||
@spec cast(Literal.t | Literal.Datatype.literal) :: Literal.t() | nil
|
@spec cast(Literal.Datatype.literal | RDF.Term.t) :: Literal.t() | nil
|
||||||
@dialyzer {:nowarn_function, cast: 1}
|
@dialyzer {:nowarn_function, cast: 1}
|
||||||
def cast(literal_or_value)
|
def cast(literal_or_value)
|
||||||
def cast(%Literal{literal: literal}), do: cast(literal)
|
def cast(%Literal{literal: literal}), do: cast(literal)
|
||||||
def cast(%__MODULE__{} = datatype_literal),
|
def cast(%__MODULE__{} = datatype_literal),
|
||||||
do: if(valid?(datatype_literal), do: literal(datatype_literal))
|
do: if(valid?(datatype_literal), do: literal(datatype_literal))
|
||||||
def cast(%struct{} = datatype_literal) do
|
def cast(%struct{} = datatype_literal) do
|
||||||
if Literal.datatype?(struct) and Literal.Datatype.valid?(datatype_literal) do
|
if (Literal.datatype?(struct) and Literal.Datatype.valid?(datatype_literal)) or
|
||||||
|
struct in [RDF.IRI, RDF.BlankNode] do
|
||||||
case do_cast(datatype_literal) do
|
case do_cast(datatype_literal) do
|
||||||
%__MODULE__{} = literal -> if valid?(literal), do: literal(literal)
|
%__MODULE__{} = literal -> if valid?(literal), do: literal(literal)
|
||||||
%Literal{literal: %__MODULE__{}} = literal -> if valid?(literal), do: literal
|
%Literal{literal: %__MODULE__{}} = literal -> if valid?(literal), do: literal
|
||||||
|
|
|
@ -60,6 +60,10 @@ defmodule RDF.XSD.AnyURI do
|
||||||
|
|
||||||
def elixir_mapping(_, _), do: @invalid_value
|
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
|
@impl RDF.Literal.Datatype
|
||||||
def do_equal_value?(literal1, literal2)
|
def do_equal_value?(literal1, literal2)
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,10 @@ defmodule RDF.XSD.String do
|
||||||
def elixir_mapping(value, _), do: to_string(value)
|
def elixir_mapping(value, _), do: to_string(value)
|
||||||
|
|
||||||
@impl RDF.Literal.Datatype
|
@impl RDF.Literal.Datatype
|
||||||
|
def do_cast(literal_or_iri)
|
||||||
|
|
||||||
|
def do_cast(%RDF.IRI{value: value}), do: new(value)
|
||||||
|
|
||||||
def do_cast(%datatype{} = literal) do
|
def do_cast(%datatype{} = literal) do
|
||||||
cond do
|
cond do
|
||||||
XSD.Decimal.datatype?(literal) ->
|
XSD.Decimal.datatype?(literal) ->
|
||||||
|
|
|
@ -34,5 +34,10 @@ defmodule RDF.XSD.AnyURITest do
|
||||||
assert XSD.anyURI("http://example.com/") |> XSD.AnyURI.cast() ==
|
assert XSD.anyURI("http://example.com/") |> XSD.AnyURI.cast() ==
|
||||||
XSD.anyURI("http://example.com/")
|
XSD.anyURI("http://example.com/")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "casting an RDF.IRI" do
|
||||||
|
assert RDF.iri("http://example.com/") |> XSD.AnyURI.cast() ==
|
||||||
|
XSD.anyURI("http://example.com/")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -127,6 +127,10 @@ defmodule RDF.XSD.StringTest do
|
||||||
assert FloatUnitInterval.new(1.0) |> XSD.String.cast() == XSD.string("1")
|
assert FloatUnitInterval.new(1.0) |> XSD.String.cast() == XSD.string("1")
|
||||||
end
|
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
|
test "with invalid literals" do
|
||||||
assert XSD.integer(3.14) |> XSD.String.cast() == nil
|
assert XSD.integer(3.14) |> XSD.String.cast() == nil
|
||||||
assert XSD.decimal("NAN") |> XSD.String.cast() == nil
|
assert XSD.decimal("NAN") |> XSD.String.cast() == nil
|
||||||
|
|
Loading…
Reference in a new issue