-
Notifications
You must be signed in to change notification settings - Fork 8
/
primitive.ex
114 lines (88 loc) · 3.18 KB
/
primitive.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
defmodule RDF.XSD.Datatype.Primitive do
@moduledoc """
Macros for the definition of primitive XSD datatypes.
"""
@doc """
Specifies the applicability of the given XSD `facet` on a primitive datatype.
For a facet with the name `example_facet` this requires a function
def example_facet_conform?(example_facet_value, literal_value, lexical) do
end
to be defined on the primitive datatype.
"""
defmacro def_applicable_facet(facet) do
quote do
@applicable_facets unquote(facet)
use unquote(facet)
end
end
defmacro __using__(opts) do
quote do
use RDF.XSD.Datatype, unquote(opts)
import unquote(__MODULE__)
Module.register_attribute(__MODULE__, :applicable_facets, accumulate: true)
@impl RDF.XSD.Datatype
def primitive?, do: true
@impl RDF.XSD.Datatype
def base, do: nil
@impl RDF.XSD.Datatype
def base_primitive, do: __MODULE__
@impl RDF.XSD.Datatype
def derived_from?(_), do: false
@impl RDF.XSD.Datatype
def init_valid_lexical(value, lexical, opts)
def init_valid_lexical(_value, nil, _opts), do: nil
def init_valid_lexical(_value, lexical, _opts), do: lexical
@impl RDF.XSD.Datatype
def init_invalid_lexical(value, _opts), do: to_string(value)
@doc false
# Optimization: facets are generally unconstrained on primitives
def facet_conform?(_, _), do: true
@impl RDF.XSD.Datatype
def canonical_mapping(value), do: to_string(value)
@impl RDF.Literal.Datatype
def do_cast(value) do
# i.e. derived datatype
if datatype?(value) do
build_valid(value.value, value.uncanonical_lexical, [])
end
end
@impl RDF.Literal.Datatype
def do_equal_value_same_or_derived_datatypes?(
%left_datatype{} = left,
%right_datatype{} = right
) do
left_datatype.value(left) == right_datatype.value(right)
end
@impl RDF.Literal.Datatype
def do_equal_value_different_datatypes?(left, right), do: nil
@impl RDF.Literal.Datatype
def do_compare(%left_datatype{} = left, %right_datatype{} = right) do
if left_datatype.datatype?(right_datatype) or right_datatype.datatype?(left_datatype) do
case {left_datatype.value(left), right_datatype.value(right)} do
{left_value, right_value} when left_value < right_value ->
:lt
{left_value, right_value} when left_value > right_value ->
:gt
_ ->
if left_datatype.equal_value?(left, right), do: :eq
end
end
end
def do_compare(_, _), do: nil
defoverridable canonical_mapping: 1,
do_cast: 1,
init_valid_lexical: 3,
init_invalid_lexical: 2,
do_equal_value_same_or_derived_datatypes?: 2,
do_equal_value_different_datatypes?: 2,
do_compare: 2
@before_compile unquote(__MODULE__)
end
end
defmacro __before_compile__(_env) do
quote do
@impl RDF.XSD.Datatype
def applicable_facets, do: @applicable_facets
end
end
end