diff --git a/lib/rdf/datatype.ex b/lib/rdf/datatype.ex index f3ba9cb..e3c6eab 100644 --- a/lib/rdf/datatype.ex +++ b/lib/rdf/datatype.ex @@ -1,16 +1,41 @@ defmodule RDF.Datatype do + @moduledoc """ + A behaviour for natively supported literal datatypes. + + A `RDF.Datatype` implements the foundational functions for the lexical form, + the validation, conversion and canonicalization of typed `RDF.Literal`s. + """ + alias RDF.Literal alias RDF.Datatype.NS.XSD + @doc """ + The URI of the datatype. + """ @callback id :: URI.t - @callback lexical(RDF.Literal.t) :: any + @doc """ + Produces the lexical form of a `RDF.Literal`. + """ + @callback lexical(literal :: RDF.Literal.t) :: any + @doc """ + Produces the lexical form of a value. + """ @callback canonical_lexical(any) :: binary + @doc """ + Produces the lexical form of an invalid value of a typed Literal. + + The default implementation of the `_using__` macro just returns `to_string` + representation of the value. + """ @callback invalid_lexical(any) :: binary - @callback canonical(RDF.Literal.t) :: RDF.Literal.t + @doc """ + Produces the canonical form of a `RDF.Literal`. + """ + @callback canonical(literal :: RDF.Literal.t) :: RDF.Literal.t @doc """ Converts a value into a proper native value. @@ -26,11 +51,10 @@ defmodule RDF.Datatype do """ @callback convert(any, keyword) :: any - @callback valid?(RDF.Literal.t) :: boolean - - @callback build_literal_by_value(binary, keyword) :: RDF.Literal.t - @callback build_literal_by_lexical(binary, keyword) :: RDF.Literal.t - @callback build_literal(any, binary, keyword) :: RDF.Literal.t + @doc """ + Determines if the value of a `RDF.Literal` is a member of lexical value space of its datatype. + """ + @callback valid?(literal :: RDF.Literal.t) :: boolean # TODO: This mapping should be created dynamically and be extendable, to allow user-defined datatypes ... @@ -45,10 +69,24 @@ defmodule RDF.Datatype do XSD.dateTime => RDF.DateTime, } + @doc """ + The mapping of URIs of datatypes to their `RDF.Datatype`. + """ def mapping, do: @mapping + + @doc """ + The URIs of all datatypes with a `RDF.Datatype` defined. + """ def ids, do: Map.keys(@mapping) + + @doc """ + All defined `RDF.Datatype` modules. + """ def modules, do: Map.values(@mapping) + @doc """ + Returns the `RDF.Datatype` for a directly datatype URI or the datatype URI of a `RDF.Literal`. + """ def get(%Literal{datatype: id}), do: get(id) def get(id), do: @mapping[id] diff --git a/lib/rdf/datatypes/boolean.ex b/lib/rdf/datatypes/boolean.ex index 07cf344..8dec650 100644 --- a/lib/rdf/datatypes/boolean.ex +++ b/lib/rdf/datatypes/boolean.ex @@ -1,4 +1,8 @@ defmodule RDF.Boolean do + @moduledoc """ + `RDF.Datatype` for XSD boolean. + """ + use RDF.Datatype, id: RDF.Datatype.NS.XSD.boolean diff --git a/lib/rdf/datatypes/date.ex b/lib/rdf/datatypes/date.ex index c06938e..005d5ee 100644 --- a/lib/rdf/datatypes/date.ex +++ b/lib/rdf/datatypes/date.ex @@ -1,4 +1,8 @@ defmodule RDF.Date do + @moduledoc """ + `RDF.Datatype` for XSD date. + """ + use RDF.Datatype, id: RDF.Datatype.NS.XSD.date @grammar ~r/\A(-?\d{4}-\d{2}-\d{2})((?:[\+\-]\d{2}:\d{2})|UTC|GMT|Z)?\Z/ diff --git a/lib/rdf/datatypes/date_time.ex b/lib/rdf/datatypes/date_time.ex index dac1051..6aae0db 100644 --- a/lib/rdf/datatypes/date_time.ex +++ b/lib/rdf/datatypes/date_time.ex @@ -1,4 +1,8 @@ defmodule RDF.DateTime do + @moduledoc """ + `RDF.Datatype` for XSD dateTime. + """ + use RDF.Datatype, id: RDF.Datatype.NS.XSD.dateTime diff --git a/lib/rdf/datatypes/double.ex b/lib/rdf/datatypes/double.ex index 1ef5db9..eac4f84 100644 --- a/lib/rdf/datatypes/double.ex +++ b/lib/rdf/datatypes/double.ex @@ -1,4 +1,8 @@ defmodule RDF.Double do + @moduledoc """ + `RDF.Datatype` for XSD double. + """ + use RDF.Datatype, id: RDF.Datatype.NS.XSD.double diff --git a/lib/rdf/datatypes/integer.ex b/lib/rdf/datatypes/integer.ex index f62e95b..ea88288 100644 --- a/lib/rdf/datatypes/integer.ex +++ b/lib/rdf/datatypes/integer.ex @@ -1,4 +1,8 @@ defmodule RDF.Integer do + @moduledoc """ + `RDF.Datatype` for XSD integer. + """ + use RDF.Datatype, id: RDF.Datatype.NS.XSD.integer diff --git a/lib/rdf/datatypes/lang_string.ex b/lib/rdf/datatypes/lang_string.ex index 4e5a89a..7bd6dc4 100644 --- a/lib/rdf/datatypes/lang_string.ex +++ b/lib/rdf/datatypes/lang_string.ex @@ -1,4 +1,8 @@ defmodule RDF.LangString do + @moduledoc """ + `RDF.Datatype` for RDF langString. + """ + use RDF.Datatype, id: RDF.langString diff --git a/lib/rdf/datatypes/string.ex b/lib/rdf/datatypes/string.ex index 4787f8f..c9a7c3f 100644 --- a/lib/rdf/datatypes/string.ex +++ b/lib/rdf/datatypes/string.ex @@ -1,4 +1,8 @@ defmodule RDF.String do + @moduledoc """ + `RDF.Datatype` for XSD string. + """ + use RDF.Datatype, id: RDF.Datatype.NS.XSD.string diff --git a/lib/rdf/datatypes/time.ex b/lib/rdf/datatypes/time.ex index 96eae4c..e7f6aae 100644 --- a/lib/rdf/datatypes/time.ex +++ b/lib/rdf/datatypes/time.ex @@ -1,4 +1,8 @@ defmodule RDF.Time do + @moduledoc """ + `RDF.Datatype` for XSD time. + """ + use RDF.Datatype, id: RDF.Datatype.NS.XSD.time @grammar ~r/\A(\d{2}:\d{2}:\d{2}(?:\.\d+)?)((?:[\+\-]\d{2}:\d{2})|UTC|GMT|Z)?\Z/ diff --git a/lib/rdf/literal.ex b/lib/rdf/literal.ex index 1c0fbac..37b5dea 100644 --- a/lib/rdf/literal.ex +++ b/lib/rdf/literal.ex @@ -2,6 +2,7 @@ defmodule RDF.Literal do @moduledoc """ RDF literals are leaf nodes of a RDF graph containing raw data, like strings and numbers. """ + defstruct [:value, :uncanonical_lexical, :datatype, :language] @type t :: module @@ -21,16 +22,16 @@ defmodule RDF.Literal do The following mapping of Elixir types to XSD datatypes is applied: - | Elixir type | XSD datatype | - | :-------------- | :----------- | - | `string` | `string` | - | `boolean` | `boolean` | - | `integer` | `integer` | - | `float` | `double` | - | `Time` | `time` | - | `Date` | `date` | - | `DateTime` | `dateTime` | - | `NaiveDateTime` | `dateTime` | + | Elixir datatype | XSD datatype | + | :-------------- | :------------- | + | `string` | `xsd:string` | + | `boolean` | `xsd:boolean` | + | `integer` | `xsd:integer` | + | `float` | `xsd:double` | + | `Time` | `xsd:time` | + | `Date` | `xsd:date` | + | `DateTime` | `xsd:dateTime` | + | `NaiveDateTime` | `xsd:dateTime` | # Examples @@ -85,6 +86,9 @@ defmodule RDF.Literal do do: new(value) + @doc """ + Returns the given literal with the canonical lexical representation according to its datatype. + """ def lexical(%RDF.Literal{value: value, uncanonical_lexical: nil, datatype: id} = literal) do case RDF.Datatype.get(id) do nil -> to_string(value) @@ -94,7 +98,9 @@ defmodule RDF.Literal do def lexical(%RDF.Literal{uncanonical_lexical: lexical}), do: lexical - + @doc """ + Returns the given literal in its canonical lexical representation. + """ def canonical(%RDF.Literal{uncanonical_lexical: nil} = literal), do: literal def canonical(%RDF.Literal{datatype: id} = literal) do case RDF.Datatype.get(id) do @@ -104,10 +110,16 @@ defmodule RDF.Literal do end + @doc """ + Returns if the given literal is in its canonical lexical representation. + """ def canonical?(%RDF.Literal{uncanonical_lexical: nil}), do: true def canonical?(_), do: false + @doc """ + Returns if the value of the given literal is a valid according to its datatype. + """ def valid?(%RDF.Literal{datatype: id} = literal) do case RDF.Datatype.get(id) do nil -> true @@ -117,7 +129,7 @@ defmodule RDF.Literal do @doc """ - Checks if a literal is a simple literal. + Returns if a literal is a simple literal. A simple literal has no datatype or language. @@ -128,7 +140,7 @@ defmodule RDF.Literal do @doc """ - Checks if a literal is a language-tagged literal. + Returns if a literal is a language-tagged literal. see """ @@ -137,7 +149,7 @@ defmodule RDF.Literal do @doc """ - Checks if a literal is a datatyped literal. + Returns if a literal is a datatyped literal. For historical reasons, this excludes `xsd:string` and `rdf:langString`. @@ -149,7 +161,7 @@ defmodule RDF.Literal do @doc """ - Checks if a literal is a plain literal. + Returns if a literal is a plain literal. A plain literal may have a language, but may not have a datatype. For all practical purposes, this includes `xsd:string` literals too.