Add totalDigits and fractionDigits XSD datatype facets

This commit is contained in:
Marcel Otto 2020-05-21 22:57:03 +02:00
parent 0a27c3a928
commit 486a64b4d7
18 changed files with 89 additions and 31 deletions

View file

@ -17,6 +17,8 @@ defmodule RDF.XSD.Decimal do
def_applicable_facet XSD.Facets.MaxInclusive
def_applicable_facet XSD.Facets.MinExclusive
def_applicable_facet XSD.Facets.MaxExclusive
def_applicable_facet XSD.Facets.TotalDigits
def_applicable_facet XSD.Facets.FractionDigits
def_applicable_facet XSD.Facets.Pattern
@doc false
@ -39,6 +41,16 @@ defmodule RDF.XSD.Decimal do
D.cmp(value, D.new(max_exclusive)) == :lt
end
@doc false
def total_digits_conform?(total_digits, value, _lexical) do
do_digit_count(to_string(value)) <= total_digits
end
@doc false
def fraction_digits_conform?(fraction_digits, value, _lexical) do
do_fraction_digit_count(to_string(value)) <= fraction_digits
end
@doc false
def pattern_conform?(pattern, _value, lexical) do
XSD.Facets.Pattern.conform?(pattern, lexical)
@ -149,50 +161,52 @@ defmodule RDF.XSD.Decimal do
The number of digits in the XML Schema canonical form of the literal value.
"""
@spec digit_count(RDF.Literal.t()) :: non_neg_integer | nil
def digit_count(%__MODULE__{} = literal), do: do_digit_count(literal)
def digit_count(literal)
def digit_count(%RDF.Literal{literal: datatype_literal}), do: digit_count(datatype_literal)
def digit_count(literal) do
def digit_count(%datatype{} = literal) do
cond do
XSD.Integer.datatype?(literal) -> XSD.Integer.digit_count(literal)
datatype?(literal) -> do_digit_count(literal)
XSD.Integer.datatype?(datatype) ->
XSD.Integer.digit_count(literal)
datatype?(datatype) and datatype.valid?(literal) ->
literal
|> datatype.canonical_lexical()
|> do_digit_count()
true -> nil
end
end
defp do_digit_count(%datatype{} = literal) do
if datatype.valid?(literal) do
literal
|> datatype.canonical()
|> datatype.lexical()
|> String.replace(".", "")
|> String.replace("-", "")
|> String.length()
end
@doc false
def do_digit_count(decimal_string) do
decimal_string
|> String.replace(".", "")
|> String.replace("-", "")
|> String.length()
end
@doc """
The number of digits to the right of the decimal point in the XML Schema canonical form of the literal value.
"""
@spec fraction_digit_count(RDF.Literal.t()) :: non_neg_integer | nil
def fraction_digit_count(%__MODULE__{} = literal), do: do_fraction_digit_count(literal)
def fraction_digit_count(%RDF.Literal{literal: datatype_literal}), do: fraction_digit_count(datatype_literal)
def fraction_digit_count(literal) do
def fraction_digit_count(%datatype{} = literal) do
cond do
XSD.Integer.datatype?(literal) -> 0
datatype?(literal) -> do_fraction_digit_count(literal)
datatype?(literal) and datatype.valid?(literal) ->
literal
|> datatype.canonical_lexical()
|> do_fraction_digit_count()
true -> nil
end
end
defp do_fraction_digit_count(%datatype{} = literal) do
if datatype.valid?(literal) do
[_, fraction] =
literal
|> datatype.canonical()
|> datatype.lexical()
|> String.split(".")
String.length(fraction)
end
@doc false
def do_fraction_digit_count(decimal_string) do
[_, fraction] = String.split(decimal_string, ".")
String.length(fraction)
end
end

View file

@ -19,6 +19,7 @@ defmodule RDF.XSD.Integer do
def_applicable_facet XSD.Facets.MaxInclusive
def_applicable_facet XSD.Facets.MinExclusive
def_applicable_facet XSD.Facets.MaxExclusive
def_applicable_facet XSD.Facets.TotalDigits
def_applicable_facet XSD.Facets.Pattern
@doc false
@ -41,6 +42,11 @@ defmodule RDF.XSD.Integer do
value < max_exclusive
end
@doc false
def total_digits_conform?(total_digits, value, _lexical) do
digit_count(value) <= total_digits
end
@doc false
def pattern_conform?(pattern, _value, lexical) do
XSD.Facets.Pattern.conform?(pattern, lexical)
@ -101,14 +107,16 @@ defmodule RDF.XSD.Integer do
@doc """
The number of digits in the XML Schema canonical form of the literal value.
"""
@spec digit_count(RDF.Literal.t()) :: non_neg_integer | nil
@spec digit_count(RDF.Literal.t() | integer) :: non_neg_integer | nil
def digit_count(%datatype{} = literal) do
if datatype?(literal) and datatype.valid?(literal) do
literal
|> datatype.canonical()
|> datatype.lexical()
|> String.replace("-", "")
|> String.length()
|> datatype.value()
|> digit_count()
end
end
def digit_count(integer) when is_integer(integer) do
integer |> Integer.digits() |> length()
end
end

View file

@ -0,0 +1,3 @@
defmodule RDF.XSD.Facets.FractionDigits do
use RDF.XSD.Facet, name: :fraction_digits, type: non_neg_integer
end

View file

@ -0,0 +1,3 @@
defmodule RDF.XSD.Facets.TotalDigits do
use RDF.XSD.Facet, name: :total_digits, type: pos_integer
end

View file

@ -10,6 +10,7 @@ defmodule RDF.XSD.ByteTest do
RDF.XSD.Facets.MaxInclusive,
RDF.XSD.Facets.MinExclusive,
RDF.XSD.Facets.MaxExclusive,
RDF.XSD.Facets.TotalDigits,
RDF.XSD.Facets.Pattern
],
facets: %{
@ -17,6 +18,7 @@ defmodule RDF.XSD.ByteTest do
max_inclusive: 127,
min_exclusive: nil,
max_exclusive: nil,
total_digits: nil,
pattern: nil
},
valid: RDF.XSD.TestData.valid_bytes(),

View file

@ -11,6 +11,8 @@ defmodule RDF.XSD.DecimalTest do
RDF.XSD.Facets.MaxInclusive,
RDF.XSD.Facets.MinExclusive,
RDF.XSD.Facets.MaxExclusive,
RDF.XSD.Facets.TotalDigits,
RDF.XSD.Facets.FractionDigits,
RDF.XSD.Facets.Pattern
],
facets: %{
@ -18,6 +20,8 @@ defmodule RDF.XSD.DecimalTest do
max_inclusive: nil,
min_exclusive: nil,
max_exclusive: nil,
total_digits: nil,
fraction_digits: nil,
pattern: nil
},
valid: %{

View file

@ -10,6 +10,7 @@ defmodule RDF.XSD.IntTest do
RDF.XSD.Facets.MaxInclusive,
RDF.XSD.Facets.MinExclusive,
RDF.XSD.Facets.MaxExclusive,
RDF.XSD.Facets.TotalDigits,
RDF.XSD.Facets.Pattern
],
facets: %{
@ -17,6 +18,7 @@ defmodule RDF.XSD.IntTest do
max_inclusive: 2_147_483_647,
min_exclusive: nil,
max_exclusive: nil,
total_digits: nil,
pattern: nil
},
valid: RDF.XSD.TestData.valid_ints(),

View file

@ -9,6 +9,7 @@ defmodule RDF.XSD.IntegerTest do
RDF.XSD.Facets.MaxInclusive,
RDF.XSD.Facets.MinExclusive,
RDF.XSD.Facets.MaxExclusive,
RDF.XSD.Facets.TotalDigits,
RDF.XSD.Facets.Pattern
],
facets: %{
@ -16,6 +17,7 @@ defmodule RDF.XSD.IntegerTest do
max_inclusive: nil,
min_exclusive: nil,
max_exclusive: nil,
total_digits: nil,
pattern: nil
},
valid: RDF.XSD.TestData.valid_integers(),

View file

@ -10,6 +10,7 @@ defmodule RDF.XSD.LongTest do
RDF.XSD.Facets.MaxInclusive,
RDF.XSD.Facets.MinExclusive,
RDF.XSD.Facets.MaxExclusive,
RDF.XSD.Facets.TotalDigits,
RDF.XSD.Facets.Pattern
],
facets: %{
@ -17,6 +18,7 @@ defmodule RDF.XSD.LongTest do
max_inclusive: 9_223_372_036_854_775_807,
min_exclusive: nil,
max_exclusive: nil,
total_digits: nil,
pattern: nil
},
valid: RDF.XSD.TestData.valid_longs(),

View file

@ -10,6 +10,7 @@ defmodule RDF.XSD.NegativeIntegerTest do
RDF.XSD.Facets.MaxInclusive,
RDF.XSD.Facets.MinExclusive,
RDF.XSD.Facets.MaxExclusive,
RDF.XSD.Facets.TotalDigits,
RDF.XSD.Facets.Pattern
],
facets: %{
@ -17,6 +18,7 @@ defmodule RDF.XSD.NegativeIntegerTest do
max_inclusive: -1,
min_exclusive: nil,
max_exclusive: nil,
total_digits: nil,
pattern: nil
},
valid: RDF.XSD.TestData.valid_negative_integers(),

View file

@ -10,6 +10,7 @@ defmodule RDF.XSD.NonNegativeIntegerTest do
RDF.XSD.Facets.MaxInclusive,
RDF.XSD.Facets.MinExclusive,
RDF.XSD.Facets.MaxExclusive,
RDF.XSD.Facets.TotalDigits,
RDF.XSD.Facets.Pattern
],
facets: %{
@ -17,6 +18,7 @@ defmodule RDF.XSD.NonNegativeIntegerTest do
max_inclusive: nil,
min_exclusive: nil,
max_exclusive: nil,
total_digits: nil,
pattern: nil
},
valid: RDF.XSD.TestData.valid_non_negative_integers(),

View file

@ -10,6 +10,7 @@ defmodule RDF.XSD.NonPositiveIntegerTest do
RDF.XSD.Facets.MaxInclusive,
RDF.XSD.Facets.MinExclusive,
RDF.XSD.Facets.MaxExclusive,
RDF.XSD.Facets.TotalDigits,
RDF.XSD.Facets.Pattern
],
facets: %{
@ -17,6 +18,7 @@ defmodule RDF.XSD.NonPositiveIntegerTest do
max_inclusive: 0,
min_exclusive: nil,
max_exclusive: nil,
total_digits: nil,
pattern: nil
},
valid: RDF.XSD.TestData.valid_non_positive_integers(),

View file

@ -10,6 +10,7 @@ defmodule RDF.XSD.PositiveIntegerTest do
RDF.XSD.Facets.MaxInclusive,
RDF.XSD.Facets.MinExclusive,
RDF.XSD.Facets.MaxExclusive,
RDF.XSD.Facets.TotalDigits,
RDF.XSD.Facets.Pattern
],
facets: %{
@ -17,6 +18,7 @@ defmodule RDF.XSD.PositiveIntegerTest do
max_inclusive: nil,
min_exclusive: nil,
max_exclusive: nil,
total_digits: nil,
pattern: nil
},
valid: RDF.XSD.TestData.valid_positive_integers(),

View file

@ -10,6 +10,7 @@ defmodule RDF.XSD.ShortTest do
RDF.XSD.Facets.MaxInclusive,
RDF.XSD.Facets.MinExclusive,
RDF.XSD.Facets.MaxExclusive,
RDF.XSD.Facets.TotalDigits,
RDF.XSD.Facets.Pattern
],
facets: %{
@ -17,6 +18,7 @@ defmodule RDF.XSD.ShortTest do
max_inclusive: 32767,
min_exclusive: nil,
max_exclusive: nil,
total_digits: nil,
pattern: nil
},
valid: RDF.XSD.TestData.valid_shorts(),

View file

@ -10,6 +10,7 @@ defmodule RDF.XSD.UnsignedByteTest do
RDF.XSD.Facets.MaxInclusive,
RDF.XSD.Facets.MinExclusive,
RDF.XSD.Facets.MaxExclusive,
RDF.XSD.Facets.TotalDigits,
RDF.XSD.Facets.Pattern
],
facets: %{
@ -17,6 +18,7 @@ defmodule RDF.XSD.UnsignedByteTest do
max_inclusive: 255,
min_exclusive: nil,
max_exclusive: nil,
total_digits: nil,
pattern: nil
},
valid: RDF.XSD.TestData.valid_unsigned_bytes(),

View file

@ -10,6 +10,7 @@ defmodule RDF.XSD.UnsignedIntTest do
RDF.XSD.Facets.MaxInclusive,
RDF.XSD.Facets.MinExclusive,
RDF.XSD.Facets.MaxExclusive,
RDF.XSD.Facets.TotalDigits,
RDF.XSD.Facets.Pattern
],
facets: %{
@ -17,6 +18,7 @@ defmodule RDF.XSD.UnsignedIntTest do
max_inclusive: 4_294_967_295,
min_exclusive: nil,
max_exclusive: nil,
total_digits: nil,
pattern: nil
},
valid: RDF.XSD.TestData.valid_unsigned_ints(),

View file

@ -10,6 +10,7 @@ defmodule RDF.XSD.UnsignedLongTest do
RDF.XSD.Facets.MaxInclusive,
RDF.XSD.Facets.MinExclusive,
RDF.XSD.Facets.MaxExclusive,
RDF.XSD.Facets.TotalDigits,
RDF.XSD.Facets.Pattern
],
facets: %{
@ -17,6 +18,7 @@ defmodule RDF.XSD.UnsignedLongTest do
max_inclusive: 18_446_744_073_709_551_615,
min_exclusive: nil,
max_exclusive: nil,
total_digits: nil,
pattern: nil
},
valid: RDF.XSD.TestData.valid_unsigned_longs(),

View file

@ -10,6 +10,7 @@ defmodule RDF.XSD.UnsignedShortTest do
RDF.XSD.Facets.MaxInclusive,
RDF.XSD.Facets.MinExclusive,
RDF.XSD.Facets.MaxExclusive,
RDF.XSD.Facets.TotalDigits,
RDF.XSD.Facets.Pattern
],
facets: %{
@ -17,6 +18,7 @@ defmodule RDF.XSD.UnsignedShortTest do
max_inclusive: 65535,
min_exclusive: nil,
max_exclusive: nil,
total_digits: nil,
pattern: nil
},
valid: RDF.XSD.TestData.valid_unsigned_shorts(),