Add RDF.IRI, use it instead of URI and use the term IRI consistently

Closes #1
This commit is contained in:
Marcel Otto 2017-08-20 22:35:14 +02:00
parent ec67c2379f
commit 5c7efe4cbd
50 changed files with 1109 additions and 718 deletions

View file

@ -5,6 +5,29 @@ This project adheres to [Semantic Versioning](http://semver.org/) and
[Keep a CHANGELOG](http://keepachangelog.com). [Keep a CHANGELOG](http://keepachangelog.com).
## Unreleased
### Added
- `RDF.IRI` as a more suitable URI/IRI representation for RDF, bringing enormous
performance and memory-consumption benefits
### Changed
- use `RDF.IRI` instead of Elixirs `URI` everywhere
- use the term _iri_ instead of _uri_ consistently, leading to the following
function renamings:
- `base_iri` instead of `base_uri` for the definition of `RDF.Vocabulary.Namespace`s
- `__base_iri__` instead of `__base_uri__` in all `RDF.Vocabulary.Namespace`s
- `__iris__` instead of `__uris__` in all `RDF.Vocabulary.Namespace`s
- `RDF.IRI.InvalidError` instead of `RDF.InvalidURIError`
- `RDF.Literal.InvalidError` instead of `RDF.InvalidLiteralError`
- `RDF.Namespace.InvalidVocabBaseIRIError` instead of `RDF.Namespace.InvalidVocabBaseURIError`
[Compare v0.2.0...HEAD](https://github.com/marcelotto/rdf-ex/compare/v0.2.0...HEAD)
## 0.2.0 - 2017-08-12 ## 0.2.0 - 2017-08-12
### Added ### Added

View file

@ -1 +1 @@
0.2.0 0.3.0-dev

File diff suppressed because one or more lines are too long

View file

@ -5,8 +5,7 @@ defmodule RDF do
RDF.ex consists of: RDF.ex consists of:
- modules for the nodes of an RDF graph - modules for the nodes of an RDF graph
- URIs are (currently) represented via Elixirs `URI` struct and should be - `RDF.IRI`
constructed with `RDF.uri/1`
- `RDF.BlankNode` - `RDF.BlankNode`
- `RDF.Literal` - `RDF.Literal`
- a facility for the mapping of URIs of a vocabulary to Elixir modules and - a facility for the mapping of URIs of a vocabulary to Elixir modules and
@ -20,13 +19,15 @@ defmodule RDF do
- `RDF.Graph` - `RDF.Graph`
- `RDF.Dataset` - `RDF.Dataset`
- `RDF.Data` - `RDF.Data`
- `RDF.List`
- the foundations for the definition of RDF serialization formats - the foundations for the definition of RDF serialization formats
- `RDF.Serialization` - `RDF.Serialization`
- `RDF.Serialization.Decoder` - `RDF.Serialization.Decoder`
- `RDF.Serialization.Encoder` - `RDF.Serialization.Encoder`
- and the implementation of two basic RDF serialization formats - and the implementation of various RDF serialization formats
- `RDF.NTriples` - `RDF.NTriples`
- `RDF.NQuads` - `RDF.NQuads`
- `RDF.Turtle`
This top-level module provides shortcut functions for the construction of the This top-level module provides shortcut functions for the construction of the
basic elements and structures of RDF and some general helper functions. basic elements and structures of RDF and some general helper functions.
@ -34,7 +35,7 @@ defmodule RDF do
For a general introduction you may refer to the [README](readme.html). For a general introduction you may refer to the [README](readme.html).
""" """
alias RDF.{Namespace, Literal, BlankNode, Triple, Quad, alias RDF.{IRI, Namespace, Literal, BlankNode, Triple, Quad,
Description, Graph, Dataset} Description, Graph, Dataset}
@doc """ @doc """
@ -42,7 +43,7 @@ defmodule RDF do
## Examples ## Examples
iex> RDF.resource?(RDF.uri("http://example.com/resource")) iex> RDF.resource?(RDF.iri("http://example.com/resource"))
true true
iex> RDF.resource?(EX.resource) iex> RDF.resource?(EX.resource)
true true
@ -52,31 +53,18 @@ defmodule RDF do
false false
""" """
def resource?(value) def resource?(value)
def resource?(%URI{}), do: true def resource?(%IRI{}), do: true
def resource?(atom) when is_atom(atom), do: resource?(Namespace.resolve_term(atom))
def resource?(%BlankNode{}), do: true def resource?(%BlankNode{}), do: true
def resource?(atom) when is_atom(atom), do: resource?(Namespace.resolve_term(atom))
def resource?(_), do: false def resource?(_), do: false
@doc """
Checks if the given value is an URI.
## Examples defdelegate uri?(value), to: IRI, as: :valid?
defdelegate iri?(value), to: IRI, as: :valid?
iex> RDF.uri?("http://www.example.com/foo") defdelegate uri(value), to: IRI, as: :new
true defdelegate iri(value), to: IRI, as: :new
iex> RDF.uri?("not a uri") defdelegate uri!(value), to: IRI, as: :new!
false defdelegate iri!(value), to: IRI, as: :new!
"""
def uri?(some_uri = %URI{}) do
# The following was suggested at http://stackoverflow.com/questions/30696761/check-if-a-url-is-valid-in-elixir
# TODO: Find a better way! Maybe <https://github.com/marcelog/ex_rfc3986>?
case some_uri do
%URI{scheme: nil} -> false
_uri -> true
end
end
def uri?(value) when is_binary(value), do: uri?(URI.parse(value))
def uri?(_), do: false
@doc """ @doc """
Checks if the given value is a blank node. Checks if the given value is a blank node.
@ -85,7 +73,7 @@ defmodule RDF do
iex> RDF.bnode?(RDF.bnode) iex> RDF.bnode?(RDF.bnode)
true true
iex> RDF.bnode?(RDF.uri("http://example.com/resource")) iex> RDF.bnode?(RDF.iri("http://example.com/resource"))
false false
iex> RDF.bnode?(42) iex> RDF.bnode?(42)
false false
@ -93,54 +81,6 @@ defmodule RDF do
def bnode?(%BlankNode{}), do: true def bnode?(%BlankNode{}), do: true
def bnode?(_), do: false def bnode?(_), do: false
@doc """
Generator function for URIs from strings or term atoms of a `RDF.Namespace`.
This function is used for the `~I` sigil.
## Examples
iex> RDF.uri("http://www.example.com/foo")
%URI{authority: "www.example.com", fragment: nil, host: "www.example.com",
path: "/foo", port: 80, query: nil, scheme: "http", userinfo: nil}
iex> RDF.uri(RDF.NS.RDFS.Class)
%URI{authority: "www.w3.org", fragment: "Class", host: "www.w3.org",
path: "/2000/01/rdf-schema", port: 80, query: nil, scheme: "http",
userinfo: nil}
iex> RDF.uri("not a uri")
** (RDF.InvalidURIError) string "not a uri" is not a valid URI
"""
@spec uri(URI.t | binary | atom) :: URI.t
def uri(atom) when is_atom(atom), do: Namespace.resolve_term(atom)
def uri(string) do
with parsed_uri = URI.parse(string) do
if uri?(parsed_uri) do
if is_binary(string) and String.ends_with?(string, "#") do
%URI{parsed_uri | fragment: ""}
else
parsed_uri
end
else
raise RDF.InvalidURIError, ~s(string "#{string}" is not a valid URI)
end
end
end
def list(native_list),
do: RDF.List.from(native_list)
def list(head, %Graph{} = graph),
do: RDF.List.new(head, graph)
def list(native_list, opts),
do: RDF.List.from(native_list, opts)
defdelegate bnode(), to: BlankNode, as: :new defdelegate bnode(), to: BlankNode, as: :new
defdelegate bnode(id), to: BlankNode, as: :new defdelegate bnode(id), to: BlankNode, as: :new
@ -170,6 +110,16 @@ defmodule RDF do
defdelegate list?(resource, graph), to: RDF.List, as: :node? defdelegate list?(resource, graph), to: RDF.List, as: :node?
defdelegate list?(description), to: RDF.List, as: :node? defdelegate list?(description), to: RDF.List, as: :node?
def list(native_list),
do: RDF.List.from(native_list)
def list(head, %Graph{} = graph),
do: RDF.List.new(head, graph)
def list(native_list, opts),
do: RDF.List.from(native_list, opts)
for term <- ~w[type subject predicate object first rest value]a do for term <- ~w[type subject predicate object first rest value]a do
defdelegate unquote(term)(), to: RDF.NS.RDF defdelegate unquote(term)(), to: RDF.NS.RDF
@ -183,5 +133,5 @@ defmodule RDF do
defdelegate langString(), to: RDF.NS.RDF defdelegate langString(), to: RDF.NS.RDF
defdelegate unquote(nil)(), to: RDF.NS.RDF defdelegate unquote(nil)(), to: RDF.NS.RDF
defdelegate __base_uri__(), to: RDF.NS.RDF defdelegate __base_iri__(), to: RDF.NS.RDF
end end

View file

@ -1,6 +1,6 @@
defmodule RDF.BlankNode do defmodule RDF.BlankNode do
@moduledoc """ @moduledoc """
A RDF blank node (aka bnode) is a local node of a graph without an URI. A RDF blank node (aka bnode) is a local node of a graph without an IRI.
see <https://www.w3.org/TR/rdf11-primer/#section-blank-node> see <https://www.w3.org/TR/rdf11-primer/#section-blank-node>
and <https://www.w3.org/TR/rdf11-concepts/#section-blank-nodes> and <https://www.w3.org/TR/rdf11-concepts/#section-blank-nodes>
@ -11,13 +11,13 @@ defmodule RDF.BlankNode do
@type t :: module @type t :: module
@doc """ @doc """
Generator function for `RDF.BlankNode`s. Creates a `RDF.BlankNode` with an arbitrary internal id.
""" """
def new, def new,
do: new(make_ref()) do: new(make_ref())
@doc """ @doc """
Generator function for `RDF.BlankNode`s with a user-defined identity. Creates a `RDF.BlankNode` with a user-defined identity.
## Examples ## Examples
@ -34,10 +34,10 @@ defmodule RDF.BlankNode do
def new(id) when is_atom(id) or is_integer(id), def new(id) when is_atom(id) or is_integer(id),
do: id |> to_string |> new do: id |> to_string |> new
end
defimpl String.Chars, for: RDF.BlankNode do
def to_string(%RDF.BlankNode{id: id}) do defimpl String.Chars do
"_:#{id}" def to_string(%RDF.BlankNode{id: id}), do: "_:#{id}"
end end
end end

View file

@ -63,7 +63,7 @@ defmodule RDF.Dataset do
Creates an empty named `RDF.Dataset`. Creates an empty named `RDF.Dataset`.
""" """
def new(name), def new(name),
do: %RDF.Dataset{name: RDF.uri(name)} do: %RDF.Dataset{name: RDF.iri!(name)}
@doc """ @doc """
Creates a named `RDF.Dataset` with an initial statement. Creates a named `RDF.Dataset` with an initial statement.
@ -561,7 +561,7 @@ defmodule RDF.Dataset do
...> {EX.S2, EX.p2, EX.O2}, ...> {EX.S2, EX.p2, EX.O2},
...> {EX.S1, EX.p2, EX.O3}]) |> ...> {EX.S1, EX.p2, EX.O3}]) |>
...> RDF.Dataset.subjects ...> RDF.Dataset.subjects
MapSet.new([RDF.uri(EX.S1), RDF.uri(EX.S2)]) MapSet.new([RDF.iri(EX.S1), RDF.iri(EX.S2)])
""" """
def subjects(%RDF.Dataset{graphs: graphs}) do def subjects(%RDF.Dataset{graphs: graphs}) do
Enum.reduce graphs, MapSet.new, fn ({_, graph}, subjects) -> Enum.reduce graphs, MapSet.new, fn ({_, graph}, subjects) ->
@ -590,7 +590,7 @@ defmodule RDF.Dataset do
@doc """ @doc """
The set of all resources used in the objects within a `RDF.Dataset`. The set of all resources used in the objects within a `RDF.Dataset`.
Note: This function does collect only URIs and BlankNodes, not Literals. Note: This function does collect only IRIs and BlankNodes, not Literals.
## Examples ## Examples
@ -601,7 +601,7 @@ defmodule RDF.Dataset do
...> {EX.S4, EX.p2, RDF.bnode(:bnode)}, ...> {EX.S4, EX.p2, RDF.bnode(:bnode)},
...> {EX.S5, EX.p3, "foo"} ...> {EX.S5, EX.p3, "foo"}
...> ]) |> RDF.Dataset.objects ...> ]) |> RDF.Dataset.objects
MapSet.new([RDF.uri(EX.O1), RDF.uri(EX.O2), RDF.bnode(:bnode)]) MapSet.new([RDF.iri(EX.O1), RDF.iri(EX.O2), RDF.bnode(:bnode)])
""" """
def objects(%RDF.Dataset{graphs: graphs}) do def objects(%RDF.Dataset{graphs: graphs}) do
Enum.reduce graphs, MapSet.new, fn ({_, graph}, objects) -> Enum.reduce graphs, MapSet.new, fn ({_, graph}, objects) ->
@ -620,8 +620,8 @@ defmodule RDF.Dataset do
...> {EX.S2, EX.p2, RDF.bnode(:bnode)}, ...> {EX.S2, EX.p2, RDF.bnode(:bnode)},
...> {EX.S3, EX.p1, "foo"} ...> {EX.S3, EX.p1, "foo"}
...> ]) |> RDF.Dataset.resources ...> ]) |> RDF.Dataset.resources
MapSet.new([RDF.uri(EX.S1), RDF.uri(EX.S2), RDF.uri(EX.S3), MapSet.new([RDF.iri(EX.S1), RDF.iri(EX.S2), RDF.iri(EX.S3),
RDF.uri(EX.O1), RDF.uri(EX.O2), RDF.bnode(:bnode), EX.p1, EX.p2]) RDF.iri(EX.O1), RDF.iri(EX.O2), RDF.bnode(:bnode), EX.p1, EX.p2])
""" """
def resources(%RDF.Dataset{graphs: graphs}) do def resources(%RDF.Dataset{graphs: graphs}) do
Enum.reduce graphs, MapSet.new, fn ({_, graph}, resources) -> Enum.reduce graphs, MapSet.new, fn ({_, graph}, resources) ->
@ -639,9 +639,9 @@ defmodule RDF.Dataset do
...> {EX.S2, EX.p2, EX.O2}, ...> {EX.S2, EX.p2, EX.O2},
...> {EX.S1, EX.p2, EX.O3}]) |> ...> {EX.S1, EX.p2, EX.O3}]) |>
...> RDF.Dataset.statements ...> RDF.Dataset.statements
[{RDF.uri(EX.S1), RDF.uri(EX.p1), RDF.uri(EX.O1), RDF.uri(EX.Graph)}, [{RDF.iri(EX.S1), RDF.iri(EX.p1), RDF.iri(EX.O1), RDF.iri(EX.Graph)},
{RDF.uri(EX.S1), RDF.uri(EX.p2), RDF.uri(EX.O3)}, {RDF.iri(EX.S1), RDF.iri(EX.p2), RDF.iri(EX.O3)},
{RDF.uri(EX.S2), RDF.uri(EX.p2), RDF.uri(EX.O2)}] {RDF.iri(EX.S2), RDF.iri(EX.p2), RDF.iri(EX.O2)}]
""" """
def statements(%RDF.Dataset{graphs: graphs}) do def statements(%RDF.Dataset{graphs: graphs}) do
Enum.reduce graphs, [], fn ({_, graph}, all_statements) -> Enum.reduce graphs, [], fn ({_, graph}, all_statements) ->
@ -713,7 +713,7 @@ defmodule RDF.Dataset do
...> {EX.S1, EX.p, EX.O, EX.Graph1}, ...> {EX.S1, EX.p, EX.O, EX.Graph1},
...> {EX.S2, EX.p, EX.O, EX.Graph2}]) ...> {EX.S2, EX.p, EX.O, EX.Graph2}])
...> RDF.Dataset.who_describes(dataset, EX.S1) ...> RDF.Dataset.who_describes(dataset, EX.S1)
[nil, RDF.uri(EX.Graph1)] [nil, RDF.iri(EX.Graph1)]
""" """
def who_describes(%RDF.Dataset{graphs: graphs}, subject) do def who_describes(%RDF.Dataset{graphs: graphs}, subject) do
with subject = coerce_subject(subject) do with subject = coerce_subject(subject) do

View file

@ -10,9 +10,9 @@ defmodule RDF.Datatype do
alias RDF.Datatype.NS.XSD alias RDF.Datatype.NS.XSD
@doc """ @doc """
The URI of the datatype. The IRI of the datatype.
""" """
@callback id :: URI.t @callback id :: RDF.IRI.t
@doc """ @doc """
Produces the lexical form of a `RDF.Literal`. Produces the lexical form of a `RDF.Literal`.
@ -57,7 +57,7 @@ defmodule RDF.Datatype do
@callback valid?(literal :: RDF.Literal.t) :: boolean @callback valid?(literal :: RDF.Literal.t) :: boolean
@lang_string RDF.uri("http://www.w3.org/1999/02/22-rdf-syntax-ns#langString") @lang_string RDF.iri("http://www.w3.org/1999/02/22-rdf-syntax-ns#langString")
# TODO: This mapping should be created dynamically and be extendable, to allow user-defined datatypes ... # TODO: This mapping should be created dynamically and be extendable, to allow user-defined datatypes ...
@mapping %{ @mapping %{
@ -72,12 +72,12 @@ defmodule RDF.Datatype do
} }
@doc """ @doc """
The mapping of URIs of datatypes to their `RDF.Datatype`. The mapping of IRIs of datatypes to their `RDF.Datatype`.
""" """
def mapping, do: @mapping def mapping, do: @mapping
@doc """ @doc """
The URIs of all datatypes with a `RDF.Datatype` defined. The IRIs of all datatypes with a `RDF.Datatype` defined.
""" """
def ids, do: Map.keys(@mapping) def ids, do: Map.keys(@mapping)
@ -87,7 +87,7 @@ defmodule RDF.Datatype do
def modules, do: Map.values(@mapping) def modules, do: Map.values(@mapping)
@doc """ @doc """
Returns the `RDF.Datatype` for a directly datatype URI or the datatype URI of a `RDF.Literal`. Returns the `RDF.Datatype` for a directly datatype IRI or the datatype IRI of a `RDF.Literal`.
""" """
def get(%Literal{datatype: id}), do: get(id) def get(%Literal{datatype: id}), do: get(id)
def get(id), do: @mapping[id] def get(id), do: @mapping[id]

View file

@ -9,7 +9,7 @@ defmodule RDF.Datatype.NS do
@vocabdoc false @vocabdoc false
defvocab XSD, defvocab XSD,
base_uri: "http://www.w3.org/2001/XMLSchema#", base_iri: "http://www.w3.org/2001/XMLSchema#",
terms: ~w[ terms: ~w[
string string
normalizedString normalizedString

View file

@ -313,10 +313,10 @@ defmodule RDF.Description do
## Examples ## Examples
iex> RDF.Description.fetch(RDF.Description.new({EX.S, EX.p, EX.O}), EX.p) iex> RDF.Description.fetch(RDF.Description.new({EX.S, EX.p, EX.O}), EX.p)
{:ok, [RDF.uri(EX.O)]} {:ok, [RDF.iri(EX.O)]}
iex> RDF.Description.fetch(RDF.Description.new([{EX.S, EX.P, EX.O1}, iex> RDF.Description.fetch(RDF.Description.new([{EX.S, EX.P, EX.O1},
...> {EX.S, EX.P, EX.O2}]), EX.P) ...> {EX.S, EX.P, EX.O2}]), EX.P)
{:ok, [RDF.uri(EX.O1), RDF.uri(EX.O2)]} {:ok, [RDF.iri(EX.O1), RDF.iri(EX.O2)]}
iex> RDF.Description.fetch(RDF.Description.new(EX.S), EX.foo) iex> RDF.Description.fetch(RDF.Description.new(EX.S), EX.foo)
:error :error
""" """
@ -334,7 +334,7 @@ defmodule RDF.Description do
## Examples ## Examples
iex> RDF.Description.get(RDF.Description.new({EX.S, EX.P, EX.O}), EX.P) iex> RDF.Description.get(RDF.Description.new({EX.S, EX.P, EX.O}), EX.P)
[RDF.uri(EX.O)] [RDF.iri(EX.O)]
iex> RDF.Description.get(RDF.Description.new(EX.S), EX.foo) iex> RDF.Description.get(RDF.Description.new(EX.S), EX.foo)
nil nil
iex> RDF.Description.get(RDF.Description.new(EX.S), EX.foo, :bar) iex> RDF.Description.get(RDF.Description.new(EX.S), EX.foo, :bar)
@ -355,7 +355,7 @@ defmodule RDF.Description do
## Examples ## Examples
iex> RDF.Description.first(RDF.Description.new({EX.S, EX.P, EX.O}), EX.P) iex> RDF.Description.first(RDF.Description.new({EX.S, EX.P, EX.O}), EX.P)
RDF.uri(EX.O) RDF.iri(EX.O)
iex> RDF.Description.first(RDF.Description.new(EX.S), EX.foo) iex> RDF.Description.first(RDF.Description.new(EX.S), EX.foo)
nil nil
""" """
@ -385,10 +385,10 @@ defmodule RDF.Description do
...> RDF.Description.get_and_update(EX.P, fn current_objects -> ...> RDF.Description.get_and_update(EX.P, fn current_objects ->
...> {current_objects, EX.NEW} ...> {current_objects, EX.NEW}
...> end) ...> end)
{[RDF.uri(EX.O)], RDF.Description.new({EX.S, EX.P, EX.NEW})} {[RDF.iri(EX.O)], RDF.Description.new({EX.S, EX.P, EX.NEW})}
iex> RDF.Description.new([{EX.S, EX.P1, EX.O1}, {EX.S, EX.P2, EX.O2}]) |> iex> RDF.Description.new([{EX.S, EX.P1, EX.O1}, {EX.S, EX.P2, EX.O2}]) |>
...> RDF.Description.get_and_update(EX.P1, fn _ -> :pop end) ...> RDF.Description.get_and_update(EX.P1, fn _ -> :pop end)
{[RDF.uri(EX.O1)], RDF.Description.new({EX.S, EX.P2, EX.O2})} {[RDF.iri(EX.O1)], RDF.Description.new({EX.S, EX.P2, EX.O2})}
""" """
def get_and_update(description = %RDF.Description{}, predicate, fun) do def get_and_update(description = %RDF.Description{}, predicate, fun) do
with triple_predicate = coerce_predicate(predicate) do with triple_predicate = coerce_predicate(predicate) do
@ -430,7 +430,7 @@ defmodule RDF.Description do
## Examples ## Examples
iex> RDF.Description.pop(RDF.Description.new({EX.S, EX.P, EX.O}), EX.P) iex> RDF.Description.pop(RDF.Description.new({EX.S, EX.P, EX.O}), EX.P)
{[RDF.uri(EX.O)], RDF.Description.new(EX.S)} {[RDF.iri(EX.O)], RDF.Description.new(EX.S)}
iex> RDF.Description.pop(RDF.Description.new({EX.S, EX.P, EX.O}), EX.Missing) iex> RDF.Description.pop(RDF.Description.new({EX.S, EX.P, EX.O}), EX.Missing)
{nil, RDF.Description.new({EX.S, EX.P, EX.O})} {nil, RDF.Description.new({EX.S, EX.P, EX.O})}
""" """
@ -462,7 +462,7 @@ defmodule RDF.Description do
@doc """ @doc """
The set of all resources used in the objects within a `RDF.Description`. The set of all resources used in the objects within a `RDF.Description`.
Note: This function does collect only URIs and BlankNodes, not Literals. Note: This function does collect only IRIs and BlankNodes, not Literals.
## Examples ## Examples
@ -473,7 +473,7 @@ defmodule RDF.Description do
...> {EX.p4, RDF.bnode(:bnode)}, ...> {EX.p4, RDF.bnode(:bnode)},
...> {EX.p3, "foo"} ...> {EX.p3, "foo"}
...> ]) |> RDF.Description.objects ...> ]) |> RDF.Description.objects
MapSet.new([RDF.uri(EX.O1), RDF.uri(EX.O2), RDF.bnode(:bnode)]) MapSet.new([RDF.iri(EX.O1), RDF.iri(EX.O2), RDF.bnode(:bnode)])
""" """
def objects(%RDF.Description{} = description), def objects(%RDF.Description{} = description),
do: objects(description, &RDF.resource?/1) do: objects(description, &RDF.resource?/1)
@ -503,7 +503,7 @@ defmodule RDF.Description do
...> {EX.p2, RDF.bnode(:bnode)}, ...> {EX.p2, RDF.bnode(:bnode)},
...> {EX.p3, "foo"} ...> {EX.p3, "foo"}
...> ]) |> RDF.Description.resources ...> ]) |> RDF.Description.resources
MapSet.new([RDF.uri(EX.O1), RDF.uri(EX.O2), RDF.bnode(:bnode), EX.p1, EX.p2, EX.p3]) MapSet.new([RDF.iri(EX.O1), RDF.iri(EX.O2), RDF.bnode(:bnode), EX.p1, EX.p2, EX.p3])
""" """
def resources(description) do def resources(description) do
description description

View file

@ -1,8 +1,8 @@
defmodule RDF.InvalidURIError do defmodule RDF.IRI.InvalidError do
defexception [:message] defexception [:message]
end end
defmodule RDF.InvalidLiteralError do defmodule RDF.Literal.InvalidError do
defexception [:message] defexception [:message]
end end
@ -31,7 +31,7 @@ defmodule RDF.Quad.InvalidGraphContextError do
end end
defmodule RDF.Namespace.InvalidVocabBaseURIError do defmodule RDF.Namespace.InvalidVocabBaseIRIError do
defexception [:message] defexception [:message]
end end

View file

@ -479,7 +479,7 @@ defmodule RDF.Graph do
...> {EX.S2, EX.p2, EX.O2}, ...> {EX.S2, EX.p2, EX.O2},
...> {EX.S1, EX.p2, EX.O3}]) |> ...> {EX.S1, EX.p2, EX.O3}]) |>
...> RDF.Graph.subjects ...> RDF.Graph.subjects
MapSet.new([RDF.uri(EX.S1), RDF.uri(EX.S2)]) MapSet.new([RDF.iri(EX.S1), RDF.iri(EX.S2)])
""" """
def subjects(%RDF.Graph{descriptions: descriptions}), def subjects(%RDF.Graph{descriptions: descriptions}),
do: descriptions |> Map.keys |> MapSet.new do: descriptions |> Map.keys |> MapSet.new
@ -507,7 +507,7 @@ defmodule RDF.Graph do
@doc """ @doc """
The set of all resources used in the objects within a `RDF.Graph`. The set of all resources used in the objects within a `RDF.Graph`.
Note: This function does collect only URIs and BlankNodes, not Literals. Note: This function does collect only IRIs and BlankNodes, not Literals.
## Examples ## Examples
@ -518,7 +518,7 @@ defmodule RDF.Graph do
...> {EX.S4, EX.p2, RDF.bnode(:bnode)}, ...> {EX.S4, EX.p2, RDF.bnode(:bnode)},
...> {EX.S5, EX.p3, "foo"} ...> {EX.S5, EX.p3, "foo"}
...> ]) |> RDF.Graph.objects ...> ]) |> RDF.Graph.objects
MapSet.new([RDF.uri(EX.O1), RDF.uri(EX.O2), RDF.bnode(:bnode)]) MapSet.new([RDF.iri(EX.O1), RDF.iri(EX.O2), RDF.bnode(:bnode)])
""" """
def objects(%RDF.Graph{descriptions: descriptions}) do def objects(%RDF.Graph{descriptions: descriptions}) do
Enum.reduce descriptions, MapSet.new, fn ({_, description}, acc) -> Enum.reduce descriptions, MapSet.new, fn ({_, description}, acc) ->
@ -539,8 +539,8 @@ defmodule RDF.Graph do
...> {EX.S2, EX.p2, RDF.bnode(:bnode)}, ...> {EX.S2, EX.p2, RDF.bnode(:bnode)},
...> {EX.S3, EX.p1, "foo"} ...> {EX.S3, EX.p1, "foo"}
...> ]) |> RDF.Graph.resources ...> ]) |> RDF.Graph.resources
MapSet.new([RDF.uri(EX.S1), RDF.uri(EX.S2), RDF.uri(EX.S3), MapSet.new([RDF.iri(EX.S1), RDF.iri(EX.S2), RDF.iri(EX.S3),
RDF.uri(EX.O1), RDF.uri(EX.O2), RDF.bnode(:bnode), EX.p1, EX.p2]) RDF.iri(EX.O1), RDF.iri(EX.O2), RDF.bnode(:bnode), EX.p1, EX.p2])
""" """
def resources(graph = %RDF.Graph{descriptions: descriptions}) do def resources(graph = %RDF.Graph{descriptions: descriptions}) do
Enum.reduce(descriptions, MapSet.new, fn ({_, description}, acc) -> Enum.reduce(descriptions, MapSet.new, fn ({_, description}, acc) ->
@ -560,9 +560,9 @@ defmodule RDF.Graph do
...> {EX.S2, EX.p2, EX.O2}, ...> {EX.S2, EX.p2, EX.O2},
...> {EX.S1, EX.p2, EX.O3} ...> {EX.S1, EX.p2, EX.O3}
...> ]) |> RDF.Graph.triples ...> ]) |> RDF.Graph.triples
[{RDF.uri(EX.S1), RDF.uri(EX.p1), RDF.uri(EX.O1)}, [{RDF.iri(EX.S1), RDF.iri(EX.p1), RDF.iri(EX.O1)},
{RDF.uri(EX.S1), RDF.uri(EX.p2), RDF.uri(EX.O3)}, {RDF.iri(EX.S1), RDF.iri(EX.p2), RDF.iri(EX.O3)},
{RDF.uri(EX.S2), RDF.uri(EX.p2), RDF.uri(EX.O2)}] {RDF.iri(EX.S2), RDF.iri(EX.p2), RDF.iri(EX.O2)}]
""" """
def triples(graph = %RDF.Graph{}), do: Enum.to_list(graph) def triples(graph = %RDF.Graph{}), do: Enum.to_list(graph)

View file

@ -3,19 +3,17 @@ defmodule RDF.InspectHelper do
import Inspect.Algebra import Inspect.Algebra
def value_doc(%URI{} = uri, _opts), do: "~I<#{uri}>"
def value_doc(value, opts), do: to_doc(value, opts)
def objects_doc(objects, opts) do def objects_doc(objects, opts) do
objects objects
|> Enum.map(fn {object, _} -> value_doc(object, opts) end) |> Enum.map(fn {object, _} -> to_doc(object, opts) end)
|> fold_doc(fn(object, acc) -> line(object, acc) end) |> fold_doc(fn(object, acc) -> line(object, acc) end)
end end
def predications_doc(predications, opts) do def predications_doc(predications, opts) do
predications predications
|> Enum.map(fn {predicate, objects} -> |> Enum.map(fn {predicate, objects} ->
value_doc(predicate, opts) to_doc(predicate, opts)
|> line(objects_doc(objects, opts)) |> line(objects_doc(objects, opts))
|> nest(4) |> nest(4)
end) end)
@ -27,7 +25,7 @@ defmodule RDF.InspectHelper do
def descriptions_doc(descriptions, opts) do def descriptions_doc(descriptions, opts) do
descriptions descriptions
|> Enum.map(fn {subject, description} -> |> Enum.map(fn {subject, description} ->
value_doc(subject, opts) to_doc(subject, opts)
|> line(predications_doc(description.predications, opts)) |> line(predications_doc(description.predications, opts))
|> nest(4) |> nest(4)
end) end)
@ -37,6 +35,12 @@ defmodule RDF.InspectHelper do
end end
end end
defimpl Inspect, for: RDF.IRI do
def inspect(%RDF.IRI{value: value}, _opts) do
"~I<#{value}>"
end
end
defimpl Inspect, for: RDF.BlankNode do defimpl Inspect, for: RDF.BlankNode do
def inspect(%RDF.BlankNode{id: id}, _opts) do def inspect(%RDF.BlankNode{id: id}, _opts) do
"~B<#{id}>" "~B<#{id}>"
@ -68,7 +72,7 @@ defimpl Inspect, for: RDF.Description do
def inspect(%RDF.Description{subject: subject, predications: predications}, opts) do def inspect(%RDF.Description{subject: subject, predications: predications}, opts) do
doc = doc =
space("subject:", value_doc(subject, opts)) space("subject:", to_doc(subject, opts))
|> line(predications_doc(predications, opts)) |> line(predications_doc(predications, opts))
|> nest(4) |> nest(4)
surround("#RDF.Description{", doc, "}") surround("#RDF.Description{", doc, "}")
@ -81,7 +85,7 @@ defimpl Inspect, for: RDF.Graph do
def inspect(%RDF.Graph{name: name, descriptions: descriptions}, opts) do def inspect(%RDF.Graph{name: name, descriptions: descriptions}, opts) do
doc = doc =
space("name:", value_doc(name, opts)) space("name:", to_doc(name, opts))
|> line(descriptions_doc(descriptions, opts)) |> line(descriptions_doc(descriptions, opts))
|> nest(4) |> nest(4)
surround("#RDF.Graph{", doc, "}") surround("#RDF.Graph{", doc, "}")
@ -94,7 +98,7 @@ defimpl Inspect, for: RDF.Dataset do
def inspect(%RDF.Dataset{name: name} = dataset, opts) do def inspect(%RDF.Dataset{name: name} = dataset, opts) do
doc = doc =
space("name:", value_doc(name, opts)) space("name:", to_doc(name, opts))
|> line(graphs_doc(RDF.Dataset.graphs(dataset), opts)) |> line(graphs_doc(RDF.Dataset.graphs(dataset), opts))
|> nest(4) |> nest(4)
surround("#RDF.Dataset{", doc, "}") surround("#RDF.Dataset{", doc, "}")

183
lib/rdf/iri.ex Normal file
View file

@ -0,0 +1,183 @@
defmodule RDF.IRI do
@moduledoc """
A structure for IRIs.
This structure just wraps a plain IRI string and doesn't bother with the
components of the IRI, since in the context of RDF there are usually very many
IRIs and parsing them isn't needed in most cases. For these reasons we don't
use Elixirs built-in `URI` structure, because it would be unnecessary
expensive in terms of performance and memory.
The component parts can always be retrieved with the `RDF.IRI.parse/1`
function, which returns Elixirs built-in `URI` structure. Note, that `URI`
doesn't escape Unicode characters by default, so it's a suitable structure for
IRIs.
see <https://tools.ietf.org/html/rfc3987>
"""
defstruct [:value]
alias RDF.Namespace
@type t :: module
# see https://tools.ietf.org/html/rfc3986#appendix-B
@scheme_regex Regex.recompile!(~r/^([a-z][a-z0-9\+\-\.]*):/i)
@doc """
Creates a `RDF.IRI`.
"""
def new(iri)
def new(iri) when is_binary(iri), do: %RDF.IRI{value: iri}
def new(qname) when is_atom(qname), do: Namespace.resolve_term(qname)
def new(%URI{} = uri), do: uri |> URI.to_string |> new
def new(%RDF.IRI{} = iri), do: iri
@doc """
Creates a `RDF.IRI`, but checks if the given IRI is valid.
If the given IRI is not valid a `RDF.IRI.InvalidError` is raised.
see `valid?/1`
"""
def new!(iri)
def new!(iri) when is_binary(iri), do: iri |> valid!() |> new()
def new!(qname) when is_atom(qname), do: new(qname) # since terms of a namespace are already validated
def new!(%URI{} = uri), do: uri |> valid!() |> new()
def new!(%RDF.IRI{} = iri), do: valid!(iri)
@doc """
Returns the given value unchanged if it's a valid IRI, otherwise raises an exception.
## Examples
iex> RDF.IRI.valid!("http://www.example.com/foo")
"http://www.example.com/foo"
iex> RDF.IRI.valid!(RDF.IRI.new("http://www.example.com/foo"))
RDF.IRI.new("http://www.example.com/foo")
iex> RDF.IRI.valid!("not an iri")
** (RDF.IRI.InvalidError) Invalid IRI: "not an iri"
"""
def valid!(iri) do
if not valid?(iri), do: raise RDF.IRI.InvalidError, "Invalid IRI: #{inspect iri}"
iri
end
@doc """
Checks if the given IRI is valid.
Note: This currently checks only if the given IRI is absolute.
## Examples
iex> RDF.IRI.valid?("http://www.example.com/foo")
true
iex> RDF.IRI.valid?("not an iri")
false
"""
def valid?(iri), do: absolute?(iri) # TODO: Provide a more elaborate validation
@doc """
Checks if the given value is an absolute IRI.
An absolute IRI is defined in [RFC3987](http://www.ietf.org/rfc/rfc3987.txt)
containing a scheme along with a path and optional query and fragment segments.
"""
def absolute?(iri)
def absolute?(%RDF.IRI{value: value}), do: absolute?(value)
def absolute?(qname) when is_atom(qname), do: Namespace.resolve_term(qname) |> absolute?()
def absolute?(%URI{scheme: nil}), do: false
def absolute?(%URI{scheme: _}), do: true
def absolute?(value), do: not is_nil(scheme(value))
@doc """
Resolves a relative IRI against a base IRI.
as specified in [section 5.1 Establishing a Base URI of RFC3986](http://tools.ietf.org/html/rfc3986#section-5.1).
Only the basic algorithm in [section 5.2 of RFC3986](http://tools.ietf.org/html/rfc3986#section-5.2)
is used; neither Syntax-Based Normalization nor Scheme-Based Normalization are performed.
Characters additionally allowed in IRI references are treated in the same way that unreserved
characters are treated in URI references, per [section 6.5 of RFC3987](http://tools.ietf.org/html/rfc3987#section-6.5)
"""
def absolute(iri, base) do
if absolute?(iri) do
new(iri)
else
merge(base, iri)
end
end
@doc """
Merges two IRIs.
This function merges two IRIs as per
[RFC 3986, section 5.2](https://tools.ietf.org/html/rfc3986#section-5.2).
"""
def merge(base, rel) do
base
|> parse()
|> URI.merge(parse(rel))
|> empty_fragment_shim(rel)
|> new()
end
@doc false
# shim for https://github.com/elixir-lang/elixir/pull/6419
def empty_fragment_shim(_, %URI{} = uri), do: uri
def empty_fragment_shim(uri, %RDF.IRI{value: value}),
do: empty_fragment_shim(uri, value)
def empty_fragment_shim(uri, original) do
if String.ends_with?(original, "#") do
%URI{uri | fragment: ""}
else
uri
end
end
@doc """
Returns the scheme of the given IRI
If the given string is not a valid absolute IRI, `nil` is returned.
## Examples
iex> RDF.IRI.scheme("http://www.example.com/foo")
"http"
iex> RDF.IRI.scheme("not an iri")
nil
"""
def scheme(iri) do
with [_, scheme] <- Regex.run(@scheme_regex, iri) do
scheme
end
end
@doc """
Parses an IRI into its components and returns them as an `URI` struct.
"""
def parse(iri)
def parse(iri) when is_binary(iri), do: URI.parse(iri) |> empty_fragment_shim(iri)
def parse(qname) when is_atom(qname), do: Namespace.resolve_term(qname) |> parse()
def parse(%RDF.IRI{value: value}), do: URI.parse(value) |> empty_fragment_shim(value)
def parse(%URI{} = uri), do: uri
defimpl String.Chars do
def to_string(%RDF.IRI{value: value}) do
value
end
end
end

View file

@ -9,7 +9,9 @@ defmodule RDF.List do
defstruct [:head, :graph] defstruct [:head, :graph]
alias RDF.{Graph, Description, BlankNode} alias RDF.{Graph, Description, IRI, BlankNode}
@type t :: module
@rdf_nil RDF.nil @rdf_nil RDF.nil
@ -27,7 +29,7 @@ defmodule RDF.List do
def new(head, graph) def new(head, graph)
def new(head, graph) when is_atom(head) and not head in ~w[true false nil]a, def new(head, graph) when is_atom(head) and not head in ~w[true false nil]a,
do: new(RDF.uri(head), graph) do: new(RDF.iri(head), graph)
def new(head, graph) do def new(head, graph) do
with list = %RDF.List{head: head, graph: graph} do with list = %RDF.List{head: head, graph: graph} do
@ -77,7 +79,7 @@ defmodule RDF.List do
end end
defp do_from(list, head, graph, opts) when is_atom(head) do defp do_from(list, head, graph, opts) when is_atom(head) do
do_from(list, RDF.uri(head), graph, opts) do_from(list, RDF.iri!(head), graph, opts)
end end
defp do_from([list | rest], head, graph, opts) when is_list(list) do defp do_from([list | rest], head, graph, opts) when is_list(list) do
@ -169,12 +171,12 @@ defmodule RDF.List do
def node?(%BlankNode{} = list_node, graph), def node?(%BlankNode{} = list_node, graph),
do: do_node?(list_node, graph) do: do_node?(list_node, graph)
def node?(%URI{} = list_node, graph), def node?(%IRI{} = list_node, graph),
do: do_node?(list_node, graph) do: do_node?(list_node, graph)
def node?(list_node, graph) def node?(list_node, graph)
when is_atom(list_node) and not list_node in ~w[true false nil]a, when is_atom(list_node) and not list_node in ~w[true false nil]a,
do: do_node?(RDF.uri(list_node), graph) do: do_node?(RDF.iri(list_node), graph)
def node?(_, _), do: false def node?(_, _), do: false
@ -206,7 +208,7 @@ defmodule RDF.List do
def reduce(%RDF.List{head: %BlankNode{}} = list, acc, fun), def reduce(%RDF.List{head: %BlankNode{}} = list, acc, fun),
do: do_reduce(list, acc, fun) do: do_reduce(list, acc, fun)
def reduce(%RDF.List{head: %URI{}} = list, acc, fun), def reduce(%RDF.List{head: %IRI{}} = list, acc, fun),
do: do_reduce(list, acc, fun) do: do_reduce(list, acc, fun)
def reduce(_, _, _), do: {:halted, nil} def reduce(_, _, _), do: {:halted, nil}

View file

@ -11,7 +11,7 @@ defmodule RDF.Literal do
# to be able to pattern-match on plain types # to be able to pattern-match on plain types
@xsd_string XSD.string @xsd_string XSD.string
@lang_string RDF.uri("http://www.w3.org/1999/02/22-rdf-syntax-ns#langString") @lang_string RDF.iri("http://www.w3.org/1999/02/22-rdf-syntax-ns#langString")
@plain_types [@xsd_string, @lang_string] @plain_types [@xsd_string, @lang_string]
@ -56,7 +56,7 @@ defmodule RDF.Literal do
def new(value) do def new(value) do
raise RDF.InvalidLiteralError, "#{inspect value} not convertible to a RDF.Literal" raise RDF.Literal.InvalidError, "#{inspect value} not convertible to a RDF.Literal"
end end
def new(value, opts) when is_list(opts), def new(value, opts) when is_list(opts),
@ -74,7 +74,7 @@ defmodule RDF.Literal do
end end
end end
def new(value, %{datatype: %URI{} = id} = opts) do def new(value, %{datatype: %RDF.IRI{} = id} = opts) do
case RDF.Datatype.get(id) do case RDF.Datatype.get(id) do
nil -> %RDF.Literal{value: value, datatype: id} nil -> %RDF.Literal{value: value, datatype: id}
datatype -> datatype.new(value, opts) datatype -> datatype.new(value, opts)
@ -82,7 +82,7 @@ defmodule RDF.Literal do
end end
def new(value, %{datatype: datatype} = opts), def new(value, %{datatype: datatype} = opts),
do: new(value, %{opts | datatype: RDF.uri(datatype)}) do: new(value, %{opts | datatype: RDF.iri(datatype)})
def new(value, opts) when is_map(opts) and map_size(opts) == 0, def new(value, opts) when is_map(opts) and map_size(opts) == 0,
do: new(value) do: new(value)

View file

@ -1,6 +1,6 @@
defmodule RDF.Namespace do defmodule RDF.Namespace do
@moduledoc """ @moduledoc """
A behaviour for resolvers of module atoms to URIs. A behaviour for resolvers of module atoms to `RDF.IRI`s.
Currently there's only one type of such namespaces: `RDF.Vocabulary.Namespace`, Currently there's only one type of such namespaces: `RDF.Vocabulary.Namespace`,
but other types are thinkable and might be implemented in the future, eg. but other types are thinkable and might be implemented in the future, eg.
@ -8,9 +8,9 @@ defmodule RDF.Namespace do
""" """
@doc """ @doc """
Resolves a term to an URI. Resolves a term to a `RDF.IRI`.
""" """
@callback __resolve_term__(atom) :: URI.t @callback __resolve_term__(atom) :: RDF.IRI.t
@doc """ @doc """
All terms of a `RDF.Namespace`. All terms of a `RDF.Namespace`.
@ -19,7 +19,7 @@ defmodule RDF.Namespace do
@doc """ @doc """
Resolves a qualified term to an URI. Resolves a qualified term to a `RDF.IRI`.
It determines a `RDF.Namespace` from the qualifier of the given term and It determines a `RDF.Namespace` from the qualifier of the given term and
delegates to remaining part of the term to `__resolve_term__/1` of this delegates to remaining part of the term to `__resolve_term__/1` of this
@ -27,7 +27,7 @@ defmodule RDF.Namespace do
""" """
def resolve_term(expr) def resolve_term(expr)
def resolve_term(uri = %URI{}), do: uri def resolve_term(%RDF.IRI{} = iri), do: iri
def resolve_term(namespaced_term) when is_atom(namespaced_term) do def resolve_term(namespaced_term) when is_atom(namespaced_term) do
namespaced_term namespaced_term

View file

@ -19,7 +19,7 @@ defmodule RDF.NS do
See <https://www.w3.org/TR/xmlschema11-2/> See <https://www.w3.org/TR/xmlschema11-2/>
""" """
defvocab XSD, defvocab XSD,
base_uri: "http://www.w3.org/2001/XMLSchema#", base_iri: "http://www.w3.org/2001/XMLSchema#",
terms: RDF.Datatype.NS.XSD.__terms__ terms: RDF.Datatype.NS.XSD.__terms__
@vocabdoc """ @vocabdoc """
@ -28,7 +28,7 @@ defmodule RDF.NS do
See <https://www.w3.org/TR/rdf11-concepts/> See <https://www.w3.org/TR/rdf11-concepts/>
""" """
defvocab RDF, defvocab RDF,
base_uri: "http://www.w3.org/1999/02/22-rdf-syntax-ns#", base_iri: "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
file: "rdf.ttl", file: "rdf.ttl",
alias: [ alias: [
Nil: "nil", Nil: "nil",
@ -41,7 +41,7 @@ defmodule RDF.NS do
See <https://www.w3.org/TR/rdf-schema/> See <https://www.w3.org/TR/rdf-schema/>
""" """
defvocab RDFS, defvocab RDFS,
base_uri: "http://www.w3.org/2000/01/rdf-schema#", base_iri: "http://www.w3.org/2000/01/rdf-schema#",
file: "rdfs.ttl" file: "rdfs.ttl"
@vocabdoc """ @vocabdoc """
@ -50,7 +50,7 @@ defmodule RDF.NS do
See <https://www.w3.org/TR/owl-overview/> See <https://www.w3.org/TR/owl-overview/>
""" """
defvocab OWL, defvocab OWL,
base_uri: "http://www.w3.org/2002/07/owl#", base_iri: "http://www.w3.org/2002/07/owl#",
file: "owl.ttl" file: "owl.ttl"
@vocabdoc """ @vocabdoc """
@ -59,7 +59,7 @@ defmodule RDF.NS do
See <http://www.w3.org/TR/skos-reference/> See <http://www.w3.org/TR/skos-reference/>
""" """
defvocab SKOS, defvocab SKOS,
base_uri: "http://www.w3.org/2004/02/skos/core#", base_iri: "http://www.w3.org/2004/02/skos/core#",
file: "skos.ttl" file: "skos.ttl"
end end

View file

@ -20,7 +20,7 @@ defmodule RDF.Quad do
iex> RDF.Quad.new("http://example.com/S", "http://example.com/p", 42, "http://example.com/Graph") iex> RDF.Quad.new("http://example.com/S", "http://example.com/p", 42, "http://example.com/Graph")
{~I<http://example.com/S>, ~I<http://example.com/p>, RDF.literal(42), ~I<http://example.com/Graph>} {~I<http://example.com/S>, ~I<http://example.com/p>, RDF.literal(42), ~I<http://example.com/Graph>}
iex> RDF.Quad.new(EX.S, EX.p, 42, EX.Graph) iex> RDF.Quad.new(EX.S, EX.p, 42, EX.Graph)
{RDF.uri("http://example.com/S"), RDF.uri("http://example.com/p"), RDF.literal(42), RDF.uri("http://example.com/Graph")} {RDF.iri("http://example.com/S"), RDF.iri("http://example.com/p"), RDF.literal(42), RDF.iri("http://example.com/Graph")}
""" """
def new(subject, predicate, object, graph_context) do def new(subject, predicate, object, graph_context) do
{ {
@ -43,7 +43,7 @@ defmodule RDF.Quad do
iex> RDF.Quad.new {"http://example.com/S", "http://example.com/p", 42, "http://example.com/Graph"} iex> RDF.Quad.new {"http://example.com/S", "http://example.com/p", 42, "http://example.com/Graph"}
{~I<http://example.com/S>, ~I<http://example.com/p>, RDF.literal(42), ~I<http://example.com/Graph>} {~I<http://example.com/S>, ~I<http://example.com/p>, RDF.literal(42), ~I<http://example.com/Graph>}
iex> RDF.Quad.new {EX.S, EX.p, 42, EX.Graph} iex> RDF.Quad.new {EX.S, EX.p, 42, EX.Graph}
{RDF.uri("http://example.com/S"), RDF.uri("http://example.com/p"), RDF.literal(42), RDF.uri("http://example.com/Graph")} {RDF.iri("http://example.com/S"), RDF.iri("http://example.com/p"), RDF.literal(42), RDF.iri("http://example.com/Graph")}
""" """
def new({subject, predicate, object, graph_context}), def new({subject, predicate, object, graph_context}),
do: new(subject, predicate, object, graph_context) do: new(subject, predicate, object, graph_context)

View file

@ -27,9 +27,9 @@ defmodule RDF.Serialization do
""" """
@doc """ @doc """
An URI of the serialization format. An IRI of the serialization format.
""" """
@callback id :: URI.t @callback id :: RDF.IRI.t
@doc """ @doc """
The usual file extension for the serialization format. The usual file extension for the serialization format.

View file

@ -1,37 +1,32 @@
defmodule RDF.Serialization.ParseHelper do defmodule RDF.Serialization.ParseHelper do
@moduledoc false @moduledoc false
alias RDF.IRI
alias RDF.Datatype.NS.XSD alias RDF.Datatype.NS.XSD
@rdf_type RDF.uri("http://www.w3.org/1999/02/22-rdf-syntax-ns#type") @rdf_type RDF.iri("http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
def rdf_type, do: @rdf_type def rdf_type, do: @rdf_type
def to_uri_string({:iriref, _line, value}), do: value |> iri_unescape def to_iri_string({:iriref, _line, value}), do: value |> iri_unescape
def to_uri({:iriref, line, value}) do def to_iri({:iriref, line, value}) do
case URI.parse(iri_unescape(value)) do with iri = RDF.iri(iri_unescape(value)) do
%URI{scheme: nil} -> if IRI.valid?(iri) do
{:error, line, "#{value} is not a valid URI"} {:ok, iri}
parsed_uri ->
if String.ends_with?(value, "#") do
{:ok, %URI{parsed_uri | fragment: ""}}
else else
{:ok, parsed_uri} {:error, line, "#{value} is not a valid IRI"}
end end
end end
end end
def to_absolute_or_relative_uri({:iriref, _line, value}) do def to_absolute_or_relative_iri({:iriref, _line, value}) do
case URI.parse(iri_unescape(value)) do with iri = RDF.iri(iri_unescape(value)) do
uri = %URI{scheme: scheme} when not is_nil(scheme) -> if IRI.absolute?(iri) do
if String.ends_with?(value, "#") do iri
%URI{uri | fragment: ""}
else else
uri {:relative_iri, value}
end end
_ ->
{:relative_uri, value}
end end
end end
@ -47,7 +42,7 @@ defmodule RDF.Serialization.ParseHelper do
def to_literal({:boolean, _line, value}), do: RDF.literal(value) def to_literal({:boolean, _line, value}), do: RDF.literal(value)
def to_literal({:string_literal_quote, _line, value}, {:language, language}), def to_literal({:string_literal_quote, _line, value}, {:language, language}),
do: RDF.literal(value, language: language) do: RDF.literal(value, language: language)
def to_literal({:string_literal_quote, _line, value}, {:datatype, %URI{} = type}), def to_literal({:string_literal_quote, _line, value}, {:datatype, %IRI{} = type}),
do: value |> string_unescape |> RDF.literal(datatype: type) do: value |> string_unescape |> RDF.literal(datatype: type)
def to_literal(string_literal_quote_ast, type), def to_literal(string_literal_quote_ast, type),
do: {string_literal_quote_ast, type} do: {string_literal_quote_ast, type}

View file

@ -3,7 +3,7 @@ defmodule RDF.NTriples.Encoder do
use RDF.Serialization.Encoder use RDF.Serialization.Encoder
alias RDF.{Literal, BlankNode} alias RDF.{IRI, Literal, BlankNode}
@xsd_string RDF.Datatype.NS.XSD.string @xsd_string RDF.Datatype.NS.XSD.string
@ -22,8 +22,8 @@ defmodule RDF.NTriples.Encoder do
"#{term(subject)} #{term(predicate)} #{term(object)} ." "#{term(subject)} #{term(predicate)} #{term(object)} ."
end end
def term(%URI{} = uri) do def term(%IRI{} = iri) do
"<#{to_string(uri)}>" "<#{to_string(iri)}>"
end end
def term(%Literal{value: value, language: language}) when not is_nil(language) do def term(%Literal{value: value, language: language}) when not is_nil(language) do

View file

@ -3,8 +3,10 @@ defmodule RDF.Turtle.Decoder do
use RDF.Serialization.Decoder use RDF.Serialization.Decoder
alias RDF.IRI
defmodule State do defmodule State do
defstruct base_uri: nil, namespaces: %{}, bnode_counter: 0 defstruct base_iri: nil, namespaces: %{}, bnode_counter: 0
def add_namespace(%State{namespaces: namespaces} = state, ns, iri) do def add_namespace(%State{namespaces: namespaces} = state, ns, iri) do
%State{state | namespaces: Map.put(namespaces, ns, iri)} %State{state | namespaces: Map.put(namespaces, ns, iri)}
@ -29,7 +31,7 @@ defmodule RDF.Turtle.Decoder do
with {:ok, tokens, _} <- tokenize(content), with {:ok, tokens, _} <- tokenize(content),
{:ok, ast} <- parse(tokens), {:ok, ast} <- parse(tokens),
base = Map.get(opts, :base) do base = Map.get(opts, :base) do
build_graph(ast, base && RDF.uri(base)) build_graph(ast, base && RDF.iri(base))
else else
{:error, {error_line, :turtle_lexer, error_descriptor}, _error_line_again} -> {:error, {error_line, :turtle_lexer, error_descriptor}, _error_line_again} ->
{:error, "Turtle scanner error on line #{error_line}: #{inspect error_descriptor}"} {:error, "Turtle scanner error on line #{error_line}: #{inspect error_descriptor}"}
@ -46,7 +48,7 @@ defmodule RDF.Turtle.Decoder do
defp build_graph(ast, base) do defp build_graph(ast, base) do
try do try do
{graph, _} = {graph, _} =
Enum.reduce ast, {RDF.Graph.new, %State{base_uri: base}}, fn Enum.reduce ast, {RDF.Graph.new, %State{base_iri: base}}, fn
{:triples, triples_ast}, {graph, state} -> {:triples, triples_ast}, {graph, state} ->
with {statements, state} = triples(triples_ast, state) do with {statements, state} = triples(triples_ast, state) do
{RDF.Graph.add(graph, statements), state} {RDF.Graph.add(graph, statements), state}
@ -63,25 +65,25 @@ defmodule RDF.Turtle.Decoder do
end end
defp directive({:prefix, {:prefix_ns, _, ns}, iri}, state) do defp directive({:prefix, {:prefix_ns, _, ns}, iri}, state) do
if RDF.URI.Helper.absolute_iri?(iri) do if IRI.absolute?(iri) do
State.add_namespace(state, ns, iri) State.add_namespace(state, ns, iri)
else else
with absolute_uri = RDF.URI.Helper.absolute_iri(iri, state.base_uri) do with absolute_iri = IRI.absolute(iri, state.base_iri) do
State.add_namespace(state, ns, URI.to_string(absolute_uri)) State.add_namespace(state, ns, to_string(absolute_iri))
end end
end end
end end
defp directive({:base, uri}, %State{base_uri: base_uri} = state) do defp directive({:base, iri}, %State{base_iri: base_iri} = state) do
cond do cond do
RDF.URI.Helper.absolute_iri?(uri) -> IRI.absolute?(iri) ->
%State{state | base_uri: RDF.uri(uri)} %State{state | base_iri: RDF.iri(iri)}
base_uri != nil -> base_iri != nil ->
with absolute_uri = RDF.URI.Helper.absolute_iri(uri, base_uri) do with absolute_iri = IRI.absolute(iri, base_iri) do
%State{state | base_uri: absolute_uri} %State{state | base_iri: absolute_iri}
end end
true -> true ->
raise "Could not resolve resolve relative IRI '#{uri}', no base uri provided" raise "Could not resolve resolve relative IRI '#{iri}', no base iri provided"
end end
end end
@ -108,7 +110,7 @@ defmodule RDF.Turtle.Decoder do
defp resolve_node({:prefix_ln, line_number, {prefix, name}}, statements, state) do defp resolve_node({:prefix_ln, line_number, {prefix, name}}, statements, state) do
if ns = State.ns(state, prefix) do if ns = State.ns(state, prefix) do
{RDF.uri(ns <> local_name_unescape(name)), statements, state} {RDF.iri(ns <> local_name_unescape(name)), statements, state}
else else
raise "line #{line_number}: undefined prefix #{inspect prefix}" raise "line #{line_number}: undefined prefix #{inspect prefix}"
end end
@ -116,18 +118,18 @@ defmodule RDF.Turtle.Decoder do
defp resolve_node({:prefix_ns, line_number, prefix}, statements, state) do defp resolve_node({:prefix_ns, line_number, prefix}, statements, state) do
if ns = State.ns(state, prefix) do if ns = State.ns(state, prefix) do
{RDF.uri(ns), statements, state} {RDF.iri(ns), statements, state}
else else
raise "line #{line_number}: undefined prefix #{inspect prefix}" raise "line #{line_number}: undefined prefix #{inspect prefix}"
end end
end end
defp resolve_node({:relative_uri, relative_uri}, _, %State{base_uri: nil}) do defp resolve_node({:relative_iri, relative_iri}, _, %State{base_iri: nil}) do
raise "Could not resolve resolve relative IRI '#{relative_uri}', no base uri provided" raise "Could not resolve resolve relative IRI '#{relative_iri}', no base iri provided"
end end
defp resolve_node({:relative_uri, relative_uri}, statements, state) do defp resolve_node({:relative_iri, relative_iri}, statements, state) do
{RDF.URI.Helper.absolute_iri(relative_uri, state.base_uri), statements, state} {IRI.absolute(relative_iri, state.base_iri), statements, state}
end end
defp resolve_node({:anon}, statements, state) do defp resolve_node({:anon}, statements, state) do

View file

@ -4,7 +4,7 @@ defmodule RDF.Turtle.Encoder do
use RDF.Serialization.Encoder use RDF.Serialization.Encoder
alias RDF.Turtle.Encoder.State alias RDF.Turtle.Encoder.State
alias RDF.{Literal, BlankNode, Description} alias RDF.{IRI, Literal, BlankNode, Description}
@indentation_char " " @indentation_char " "
@indentation 4 @indentation 4
@ -19,10 +19,10 @@ defmodule RDF.Turtle.Encoder do
@rdf_nil RDF.nil @rdf_nil RDF.nil
# Defines rdf:type of subjects to be serialized at the beginning of the encoded graph # Defines rdf:type of subjects to be serialized at the beginning of the encoded graph
@top_classes [RDF.NS.RDFS.Class] |> Enum.map(&RDF.uri/1) @top_classes [RDF.NS.RDFS.Class] |> Enum.map(&RDF.iri/1)
# Defines order of predicates at the beginning of a resource description # Defines order of predicates at the beginning of a resource description
@predicate_order [RDF.type, RDF.NS.RDFS.label, RDF.uri("http://purl.org/dc/terms/title")] @predicate_order [RDF.type, RDF.NS.RDFS.label, RDF.iri("http://purl.org/dc/terms/title")]
@ordered_properties MapSet.new(@predicate_order) @ordered_properties MapSet.new(@predicate_order)
@ -60,8 +60,8 @@ defmodule RDF.Turtle.Encoder do
defp init_prefixes(nil), do: %{} defp init_prefixes(nil), do: %{}
defp init_prefixes(prefixes) do defp init_prefixes(prefixes) do
Enum.reduce prefixes, %{}, fn {prefix, uri}, reverse -> Enum.reduce prefixes, %{}, fn {prefix, iri}, reverse ->
Map.put(reverse, RDF.uri(uri), to_string(prefix)) Map.put(reverse, RDF.iri(iri), to_string(prefix))
end end
end end
@ -89,10 +89,10 @@ defmodule RDF.Turtle.Encoder do
end end
defp order_descriptions(descriptions, state) do defp order_descriptions(descriptions, state) do
base_uri = State.base_uri(state) base_iri = State.base_iri(state)
group = group =
Enum.group_by descriptions, fn Enum.group_by descriptions, fn
%Description{subject: ^base_uri} -> %Description{subject: ^base_iri} ->
:base :base
description -> description ->
with types when not is_nil(types) <- description.predications[@rdf_type] do with types when not is_nil(types) <- description.predications[@rdf_type] do
@ -121,8 +121,8 @@ defmodule RDF.Turtle.Encoder do
defp sort_description_group(descriptions) do defp sort_description_group(descriptions) do
Enum.sort descriptions, fn Enum.sort descriptions, fn
%Description{subject: %URI{}}, %Description{subject: %BlankNode{}} -> true %Description{subject: %IRI{}}, %Description{subject: %BlankNode{}} -> true
%Description{subject: %BlankNode{}}, %Description{subject: %URI{}} -> false %Description{subject: %BlankNode{}}, %Description{subject: %IRI{}} -> false
%Description{subject: s1}, %Description{subject: s2} -> %Description{subject: s1}, %Description{subject: s2} ->
to_string(s1) < to_string(s2) to_string(s1) < to_string(s2)
end end
@ -254,10 +254,10 @@ defmodule RDF.Turtle.Encoder do
defp term(@rdf_type, _, :predicate, _), do: "a" defp term(@rdf_type, _, :predicate, _), do: "a"
defp term(@rdf_nil, _, _, _), do: "()" defp term(@rdf_nil, _, _, _), do: "()"
defp term(%URI{} = uri, state, _, _) do defp term(%IRI{} = iri, state, _, _) do
based_name(uri, State.base(state)) || based_name(iri, State.base(state)) ||
prefixed_name(uri, State.prefixes(state)) || prefixed_name(iri, State.prefixes(state)) ||
"<#{to_string(uri)}>" "<#{to_string(iri)}>"
end end
defp term(%BlankNode{} = bnode, state, position, nesting) defp term(%BlankNode{} = bnode, state, position, nesting)
@ -303,10 +303,10 @@ defmodule RDF.Turtle.Encoder do
")" ")"
end end
defp based_name(%URI{} = uri, base), do: based_name(URI.to_string(uri), base) defp based_name(%IRI{} = iri, base), do: based_name(to_string(iri), base)
defp based_name(uri, {:ok, base}) do defp based_name(iri, {:ok, base}) do
if String.starts_with?(uri, base) do if String.starts_with?(iri, base) do
"<#{String.slice(uri, String.length(base)..-1)}>" "<#{String.slice(iri, String.length(base)..-1)}>"
end end
end end
@ -317,8 +317,8 @@ defmodule RDF.Turtle.Encoder do
do: ~s["#{Literal.lexical(literal)}"^^#{term(datatype, state, :datatype, nesting)}] do: ~s["#{Literal.lexical(literal)}"^^#{term(datatype, state, :datatype, nesting)}]
def prefixed_name(uri, prefixes) do def prefixed_name(iri, prefixes) do
with {ns, name} <- split_uri(uri) do with {ns, name} <- split_iri(iri) do
case prefixes[ns] do case prefixes[ns] do
nil -> nil nil -> nil
prefix -> prefix <> ":" <> name prefix -> prefix <> ":" <> name
@ -326,17 +326,19 @@ defmodule RDF.Turtle.Encoder do
end end
end end
defp split_iri(%IRI{} = iri),
do: iri |> IRI.parse |> split_iri()
defp split_uri(%URI{fragment: fragment} = uri) when not is_nil(fragment), defp split_iri(%URI{fragment: fragment} = uri) when not is_nil(fragment),
do: {%URI{uri | fragment: ""}, fragment} do: {RDF.iri(%URI{uri | fragment: ""}), fragment}
defp split_uri(%URI{path: nil}), defp split_iri(%URI{path: nil}),
do: nil do: nil
defp split_uri(%URI{path: path} = uri) do defp split_iri(%URI{path: path} = uri) do
with [{pos, _}] = Regex.run(~r"[^/]*$"u, path, return: :index), with [{pos, _}] = Regex.run(~r"[^/]*$"u, path, return: :index),
{ns_path, name} = String.split_at(path, pos) do {ns_path, name} = String.split_at(path, pos) do
{%URI{uri | path: ns_path}, name} {RDF.iri(%URI{uri | path: ns_path}), name}
end end
end end

View file

@ -22,9 +22,9 @@ defmodule RDF.Turtle.Encoder.State do
bnode_ref_counter(state) |> Map.get(bnode, 0) bnode_ref_counter(state) |> Map.get(bnode, 0)
end end
def base_uri(state) do def base_iri(state) do
with {:ok, base} <- base(state) do with {:ok, base} <- base(state) do
RDF.uri(base) RDF.iri(base)
else else
_ -> nil _ -> nil
end end

View file

@ -7,17 +7,17 @@ defmodule RDF.Sigils do
@doc ~S""" @doc ~S"""
Handles the sigil `~I` for IRIs. Handles the sigil `~I` for IRIs.
Note: The given IRI string is precompiled into an IRI struct. Note: The given IRI string is precompiled into an `RDF.IRI` struct.
## Examples ## Examples
iex> import RDF.Sigils iex> import RDF.Sigils
iex> ~I<http://example.com> iex> ~I<http://example.com>
RDF.uri("http://example.com") RDF.iri("http://example.com")
""" """
defmacro sigil_I({:<<>>, _, [iri]}, []) when is_binary(iri) do defmacro sigil_I({:<<>>, _, [iri]}, []) when is_binary(iri) do
Macro.escape(RDF.uri(iri)) Macro.escape(RDF.iri!(iri))
end end
@doc ~S""" @doc ~S"""

View file

@ -5,12 +5,12 @@ defmodule RDF.Statement do
A RDF statement is either a `RDF.Triple` or a `RDF.Quad`. A RDF statement is either a `RDF.Triple` or a `RDF.Quad`.
""" """
alias RDF.{Triple, Quad, BlankNode, Literal} alias RDF.{Triple, Quad, IRI, BlankNode, Literal}
@type subject :: URI.t | BlankNode.t @type subject :: IRI.t | BlankNode.t
@type predicate :: URI.t @type predicate :: IRI.t
@type object :: URI.t | BlankNode.t | Literal.t @type object :: IRI.t | BlankNode.t | Literal.t
@type graph_name :: URI.t | BlankNode.t @type graph_name :: IRI.t | BlankNode.t
@type coercible_subject :: subject | atom | String.t @type coercible_subject :: subject | atom | String.t
@type coercible_predicate :: predicate | atom | String.t @type coercible_predicate :: predicate | atom | String.t
@ -35,40 +35,39 @@ defmodule RDF.Statement do
def coerce({_, _, _, _} = quad), do: Quad.new(quad) def coerce({_, _, _, _} = quad), do: Quad.new(quad)
@doc false @doc false
def coerce_subject(uri) def coerce_subject(iri)
def coerce_subject(uri = %URI{}), do: uri def coerce_subject(iri = %IRI{}), do: iri
def coerce_subject(bnode = %BlankNode{}), do: bnode def coerce_subject(bnode = %BlankNode{}), do: bnode
def coerce_subject("_:" <> identifier), do: RDF.bnode(identifier) def coerce_subject("_:" <> identifier), do: RDF.bnode(identifier)
def coerce_subject(uri) when is_atom(uri) or is_binary(uri), do: RDF.uri(uri) def coerce_subject(iri) when is_atom(iri) or is_binary(iri), do: RDF.iri!(iri)
def coerce_subject(arg), do: raise RDF.Triple.InvalidSubjectError, subject: arg def coerce_subject(arg), do: raise RDF.Triple.InvalidSubjectError, subject: arg
@doc false @doc false
def coerce_predicate(uri) def coerce_predicate(iri)
def coerce_predicate(uri = %URI{}), do: uri def coerce_predicate(iri = %IRI{}), do: iri
# Note: Although, RDF does not allow blank nodes for properties, JSON-LD allows # Note: Although, RDF does not allow blank nodes for properties, JSON-LD allows
# them, by introducing the notion of "generalized RDF". # them, by introducing the notion of "generalized RDF".
# TODO: Support an option `:strict_rdf` to explicitly disallow them or produce warnings or ... # TODO: Support an option `:strict_rdf` to explicitly disallow them or produce warnings or ...
def coerce_predicate(bnode = %BlankNode{}), do: bnode def coerce_predicate(bnode = %BlankNode{}), do: bnode
def coerce_predicate(uri) when is_atom(uri) or is_binary(uri), do: RDF.uri(uri) def coerce_predicate(iri) when is_atom(iri) or is_binary(iri), do: RDF.iri!(iri)
def coerce_predicate(arg), do: raise RDF.Triple.InvalidPredicateError, predicate: arg def coerce_predicate(arg), do: raise RDF.Triple.InvalidPredicateError, predicate: arg
@doc false @doc false
def coerce_object(uri) def coerce_object(iri)
def coerce_object(uri = %URI{}), do: uri def coerce_object(iri = %IRI{}), do: iri
def coerce_object(literal = %Literal{}), do: literal def coerce_object(literal = %Literal{}), do: literal
def coerce_object(bnode = %BlankNode{}), do: bnode def coerce_object(bnode = %BlankNode{}), do: bnode
def coerce_object(bool) when is_boolean(bool), do: Literal.new(bool) def coerce_object(bool) when is_boolean(bool), do: Literal.new(bool)
def coerce_object(atom) when is_atom(atom), do: RDF.uri(atom) def coerce_object(atom) when is_atom(atom), do: RDF.iri(atom)
def coerce_object(arg), do: Literal.new(arg) def coerce_object(arg), do: Literal.new(arg)
@doc false @doc false
def coerce_graph_name(uri) def coerce_graph_name(iri)
def coerce_graph_name(nil), do: nil def coerce_graph_name(nil), do: nil
def coerce_graph_name(uri = %URI{}), do: uri def coerce_graph_name(iri = %IRI{}), do: iri
def coerce_graph_name(bnode = %BlankNode{}), do: bnode def coerce_graph_name(bnode = %BlankNode{}), do: bnode
def coerce_graph_name("_:" <> identifier), do: RDF.bnode(identifier) def coerce_graph_name("_:" <> identifier), do: RDF.bnode(identifier)
def coerce_graph_name(uri) when is_atom(uri) or is_binary(uri), def coerce_graph_name(iri) when is_atom(iri) or is_binary(iri), do: RDF.iri!(iri)
do: RDF.uri(uri)
def coerce_graph_name(arg), def coerce_graph_name(arg),
do: raise RDF.Quad.InvalidGraphContextError, graph_context: arg do: raise RDF.Quad.InvalidGraphContextError, graph_context: arg

View file

@ -20,7 +20,7 @@ defmodule RDF.Triple do
iex> RDF.Triple.new("http://example.com/S", "http://example.com/p", 42) iex> RDF.Triple.new("http://example.com/S", "http://example.com/p", 42)
{~I<http://example.com/S>, ~I<http://example.com/p>, RDF.literal(42)} {~I<http://example.com/S>, ~I<http://example.com/p>, RDF.literal(42)}
iex> RDF.Triple.new(EX.S, EX.p, 42) iex> RDF.Triple.new(EX.S, EX.p, 42)
{RDF.uri("http://example.com/S"), RDF.uri("http://example.com/p"), RDF.literal(42)} {RDF.iri("http://example.com/S"), RDF.iri("http://example.com/p"), RDF.literal(42)}
""" """
def new(subject, predicate, object) do def new(subject, predicate, object) do
{ {
@ -42,7 +42,7 @@ defmodule RDF.Triple do
iex> RDF.Triple.new {"http://example.com/S", "http://example.com/p", 42} iex> RDF.Triple.new {"http://example.com/S", "http://example.com/p", 42}
{~I<http://example.com/S>, ~I<http://example.com/p>, RDF.literal(42)} {~I<http://example.com/S>, ~I<http://example.com/p>, RDF.literal(42)}
iex> RDF.Triple.new {EX.S, EX.p, 42} iex> RDF.Triple.new {EX.S, EX.p, 42}
{RDF.uri("http://example.com/S"), RDF.uri("http://example.com/p"), RDF.literal(42)} {RDF.iri("http://example.com/S"), RDF.iri("http://example.com/p"), RDF.literal(42)}
""" """
def new({subject, predicate, object}), do: new(subject, predicate, object) def new({subject, predicate, object}), do: new(subject, predicate, object)

View file

@ -1,45 +0,0 @@
defmodule RDF.URI.Helper do
@moduledoc """
Some helpers functions for working with URIs.
These functions should be part of a dedicated RDF.IRI implementation.
"""
@doc """
Resolves a relative IRI against a base IRI.
as specified in [section 5.1 Establishing a Base URI of RFC3986](http://tools.ietf.org/html/rfc3986#section-5.1).
Only the basic algorithm in [section 5.2 of RFC3986](http://tools.ietf.org/html/rfc3986#section-5.2)
is used; neither Syntax-Based Normalization nor Scheme-Based Normalization are performed.
Characters additionally allowed in IRI references are treated in the same way that unreserved
characters are treated in URI references, per [section 6.5 of RFC3987](http://tools.ietf.org/html/rfc3987#section-6.5)
"""
def absolute_iri(value, base_iri) do
uri =
case URI.parse(value) do
# absolute?
uri = %URI{scheme: scheme} when not is_nil(scheme) -> uri
# relative
_ when is_nil(base_iri) -> nil
_ -> URI.merge(base_iri, value)
end
if String.ends_with?(value, "#") do
%URI{uri | fragment: ""}
else
uri
end
end
@doc """
Checks if the given value is an absolute IRI.
An absolute IRI is defined in [RFC3987](http://www.ietf.org/rfc/rfc3987.txt)
containing a scheme along with a path and optional query and fragment segments.
see <https://www.w3.org/TR/json-ld-api/#dfn-absolute-iri>
"""
def absolute_iri?(value), do: RDF.uri?(value)
end

View file

@ -3,7 +3,7 @@ defmodule RDF.Utils.ResourceClassifier do
alias RDF.Description alias RDF.Description
@rdf_type RDF.uri("http://www.w3.org/1999/02/22-rdf-syntax-ns#type") @rdf_type RDF.iri("http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
@doc """ @doc """
Determines if the given resource is RDF property by Determines if the given resource is RDF property by
@ -25,7 +25,7 @@ defmodule RDF.Utils.ResourceClassifier do
http://www.w3.org/2002/07/owl#inverseOf http://www.w3.org/2002/07/owl#inverseOf
http://www.w3.org/2002/07/owl#propertyDisjointWith http://www.w3.org/2002/07/owl#propertyDisjointWith
] ]
|> Enum.map(&RDF.uri/1) |> Enum.map(&RDF.iri/1)
|> MapSet.new |> MapSet.new
defp property_by_domain?(description) do defp property_by_domain?(description) do
@ -50,7 +50,7 @@ defmodule RDF.Utils.ResourceClassifier do
http://www.w3.org/2002/07/owl#TransitiveProperty http://www.w3.org/2002/07/owl#TransitiveProperty
http://www.w3.org/2002/07/owl#DeprecatedProperty http://www.w3.org/2002/07/owl#DeprecatedProperty
] ]
|> Enum.map(&RDF.uri/1) |> Enum.map(&RDF.iri/1)
|> MapSet.new |> MapSet.new
defp property_by_rdf_type?(nil), do: nil defp property_by_rdf_type?(nil), do: nil

View file

@ -27,16 +27,16 @@ defmodule RDF.Vocabulary.Namespace do
""" """
defmacro defvocab(name, opts) do defmacro defvocab(name, opts) do
strict = strict?(opts) strict = strict?(opts)
base_uri = base_uri!(opts) base_iri = base_iri!(opts)
file = filename!(opts) file = filename!(opts)
{terms, data} = {terms, data} =
case source!(opts) do case source!(opts) do
{:terms, terms} -> {terms, nil} {:terms, terms} -> {terms, nil}
{:data, data} -> {rdf_data_vocab_terms(data, base_uri), data} {:data, data} -> {rdf_data_vocab_terms(data, base_iri), data}
end end
if data && RDF.Data.subject_count(data) > @big_vocab_threshold do if data && RDF.Data.subject_count(data) > @big_vocab_threshold do
IO.puts("Compiling vocabulary namespace for #{base_uri} may take some time") IO.puts("Compiling vocabulary namespace for #{base_iri} may take some time")
end end
ignored_terms = ignored_terms!(opts) ignored_terms = ignored_terms!(opts)
@ -46,7 +46,7 @@ defmodule RDF.Vocabulary.Namespace do
|> Map.drop(MapSet.to_list(ignored_terms)) |> Map.drop(MapSet.to_list(ignored_terms))
|> validate_terms! |> validate_terms!
|> validate_characters!(opts) |> validate_characters!(opts)
|> validate_case!(data, base_uri, opts) |> validate_case!(data, base_iri, opts)
case_separated_terms = group_terms_by_case(terms) case_separated_terms = group_terms_by_case(terms)
lowercased_terms = Map.get(case_separated_terms, :lowercased, %{}) lowercased_terms = Map.get(case_separated_terms, :lowercased, %{})
@ -62,8 +62,8 @@ defmodule RDF.Vocabulary.Namespace do
@external_resource unquote(file) @external_resource unquote(file)
end end
@base_uri unquote(base_uri) @base_iri unquote(base_iri)
def __base_uri__, do: @base_uri def __base_iri__, do: @base_iri
@strict unquote(strict) @strict unquote(strict)
def __strict__, do: @strict def __strict__, do: @strict
@ -74,18 +74,18 @@ defmodule RDF.Vocabulary.Namespace do
@ignored_terms unquote(Macro.escape(ignored_terms)) @ignored_terms unquote(Macro.escape(ignored_terms))
@doc """ @doc """
Returns all known URIs of the vocabulary. Returns all known IRIs of the vocabulary.
""" """
def __uris__ do def __iris__ do
@terms @terms
|> Enum.map(fn |> Enum.map(fn
{term, true} -> term_to_uri(@base_uri, term) {term, true} -> term_to_iri(@base_iri, term)
{_alias, term} -> term_to_uri(@base_uri, term) {_alias, term} -> term_to_iri(@base_iri, term)
end) end)
|> Enum.uniq |> Enum.uniq
end end
define_vocab_terms unquote(lowercased_terms), unquote(base_uri) define_vocab_terms unquote(lowercased_terms), unquote(base_iri)
def __resolve_term__(term) do def __resolve_term__(term) do
case @terms[term] do case @terms[term] do
@ -95,12 +95,12 @@ defmodule RDF.Vocabulary.Namespace do
raise RDF.Namespace.UndefinedTermError, raise RDF.Namespace.UndefinedTermError,
"undefined term #{term} in strict vocabulary #{__MODULE__}" "undefined term #{term} in strict vocabulary #{__MODULE__}"
else else
term_to_uri(@base_uri, term) term_to_iri(@base_iri, term)
end end
true -> true ->
term_to_uri(@base_uri, term) term_to_iri(@base_iri, term)
original_term -> original_term ->
term_to_uri(@base_uri, original_term) term_to_iri(@base_iri, original_term)
end end
end end
@ -109,7 +109,7 @@ defmodule RDF.Vocabulary.Namespace do
if MapSet.member?(@ignored_terms, term) do if MapSet.member?(@ignored_terms, term) do
raise UndefinedFunctionError raise UndefinedFunctionError
else else
term_to_uri(@base_uri, term) term_to_iri(@base_iri, term)
end end
end end
@ -117,7 +117,7 @@ defmodule RDF.Vocabulary.Namespace do
if MapSet.member?(@ignored_terms, term) do if MapSet.member?(@ignored_terms, term) do
raise UndefinedFunctionError raise UndefinedFunctionError
else else
RDF.Description.new(subject, term_to_uri(@base_uri, term), objects) RDF.Description.new(subject, term_to_iri(@base_iri, term), objects)
end end
end end
end end
@ -126,7 +126,7 @@ defmodule RDF.Vocabulary.Namespace do
end end
@doc false @doc false
defmacro define_vocab_terms(terms, base_uri) do defmacro define_vocab_terms(terms, base_iri) do
terms terms
|> Stream.filter(fn |> Stream.filter(fn
{term, true} -> valid_term?(term) {term, true} -> valid_term?(term)
@ -136,15 +136,15 @@ defmodule RDF.Vocabulary.Namespace do
{term, true} -> {term, term} {term, true} -> {term, term}
{term, original_term} -> {term, original_term} {term, original_term} -> {term, original_term}
end) end)
|> Enum.map(fn {term, uri_suffix} -> |> Enum.map(fn {term, iri_suffix} ->
uri = term_to_uri(base_uri, uri_suffix) iri = term_to_iri(base_iri, iri_suffix)
quote do quote do
@doc "<#{unquote(to_string(uri))}>" @doc "<#{unquote(to_string(iri))}>"
def unquote(term)(), do: unquote(Macro.escape(uri)) def unquote(term)(), do: unquote(Macro.escape(iri))
@doc "`RDF.Description` builder for `#{unquote(term)}/0`" @doc "`RDF.Description` builder for `#{unquote(term)}/0`"
def unquote(term)(subject, object) do def unquote(term)(subject, object) do
RDF.Description.new(subject, unquote(Macro.escape(uri)), object) RDF.Description.new(subject, unquote(Macro.escape(iri)), object)
end end
# Is there a better way to support multiple objects via arguments? # Is there a better way to support multiple objects via arguments?
@ -167,13 +167,13 @@ defmodule RDF.Vocabulary.Namespace do
defp strict?(opts), defp strict?(opts),
do: Keyword.get(opts, :strict, true) do: Keyword.get(opts, :strict, true)
defp base_uri!(opts) do defp base_iri!(opts) do
base_uri = Keyword.fetch!(opts, :base_uri) base_iri = Keyword.fetch!(opts, :base_iri)
unless is_binary(base_uri) and String.ends_with?(base_uri, ["/", "#"]) do unless is_binary(base_iri) and String.ends_with?(base_iri, ["/", "#"]) do
raise RDF.Namespace.InvalidVocabBaseURIError, raise RDF.Namespace.InvalidVocabBaseIRIError,
"a base_uri without a trailing '/' or '#' is invalid" "a base_iri without a trailing '/' or '#' is invalid"
else else
base_uri base_iri
end end
end end
@ -365,18 +365,18 @@ defmodule RDF.Vocabulary.Namespace do
do: Regex.match?(~r/^[a-zA-Z_]\w*$/, term) do: Regex.match?(~r/^[a-zA-Z_]\w*$/, term)
defp validate_case!(terms, nil, _, _), do: terms defp validate_case!(terms, nil, _, _), do: terms
defp validate_case!(terms, data, base_uri, opts) do defp validate_case!(terms, data, base_iri, opts) do
if (handling = Keyword.get(opts, :case_violations, :warn)) == :ignore do if (handling = Keyword.get(opts, :case_violations, :warn)) == :ignore do
terms terms
else else
terms terms
|> detect_case_violations(data, base_uri) |> detect_case_violations(data, base_iri)
|> group_case_violations |> group_case_violations
|> handle_case_violations(handling, terms, base_uri, opts) |> handle_case_violations(handling, terms, base_iri, opts)
end end
end end
defp detect_case_violations(terms, data, base_uri) do defp detect_case_violations(terms, data, base_iri) do
aliased_terms = aliased_terms(terms) aliased_terms = aliased_terms(terms)
terms terms
|> Enum.filter(fn {term, _} -> |> Enum.filter(fn {term, _} ->
@ -385,15 +385,15 @@ defmodule RDF.Vocabulary.Namespace do
|> Enum.filter(fn |> Enum.filter(fn
{term, true} -> {term, true} ->
if not term in aliased_terms do if not term in aliased_terms do
proper_case?(term, base_uri, Atom.to_string(term), data) proper_case?(term, base_iri, Atom.to_string(term), data)
end end
{term, original_term} -> {term, original_term} ->
proper_case?(term, base_uri, original_term, data) proper_case?(term, base_iri, original_term, data)
end) end)
end end
defp proper_case?(term, base_uri, uri_suffix, data) do defp proper_case?(term, base_iri, iri_suffix, data) do
case ResourceClassifier.property?(term_to_uri(base_uri, uri_suffix), data) do case ResourceClassifier.property?(term_to_iri(base_iri, iri_suffix), data) do
true -> not lowercase?(term) true -> not lowercase?(term)
false -> lowercase?(term) false -> lowercase?(term)
nil -> lowercase?(term) nil -> lowercase?(term)
@ -417,17 +417,17 @@ defmodule RDF.Vocabulary.Namespace do
defp handle_case_violations(%{} = violations, _, terms, _, _) when map_size(violations) == 0, defp handle_case_violations(%{} = violations, _, terms, _, _) when map_size(violations) == 0,
do: terms do: terms
defp handle_case_violations(violations, :fail, _, base_uri, _) do defp handle_case_violations(violations, :fail, _, base_iri, _) do
resource_name_violations = fn violations -> resource_name_violations = fn violations ->
violations violations
|> Enum.map(fn {term, true} -> term_to_uri(base_uri, term) end) |> Enum.map(fn {term, true} -> term_to_iri(base_iri, term) end)
|> Enum.map(&to_string/1) |> Enum.map(&to_string/1)
|> Enum.join("\n- ") |> Enum.join("\n- ")
end end
alias_violations = fn violations -> alias_violations = fn violations ->
violations violations
|> Enum.map(fn {term, original} -> |> Enum.map(fn {term, original} ->
"alias #{term} for #{term_to_uri(base_uri, original)}" "alias #{term} for #{term_to_iri(base_iri, original)}"
end) end)
|> Enum.join("\n- ") |> Enum.join("\n- ")
end end
@ -484,20 +484,20 @@ defmodule RDF.Vocabulary.Namespace do
end end
defp handle_case_violations(violations, :warn, terms, base_uri, _) do defp handle_case_violations(violations, :warn, terms, base_iri, _) do
for {type, violations} <- violations, for {type, violations} <- violations,
{term, original} <- violations do {term, original} <- violations do
case_violation_warning(type, term, original, base_uri) case_violation_warning(type, term, original, base_iri)
end end
terms terms
end end
defp case_violation_warning(:capitalized_term, term, _, base_uri) do defp case_violation_warning(:capitalized_term, term, _, base_iri) do
IO.warn "'#{term_to_uri(base_uri, term)}' is a capitalized property" IO.warn "'#{term_to_iri(base_iri, term)}' is a capitalized property"
end end
defp case_violation_warning(:lowercased_term, term, _, base_uri) do defp case_violation_warning(:lowercased_term, term, _, base_iri) do
IO.warn "'#{term_to_uri(base_uri, term)}' is a lowercased non-property resource" IO.warn "'#{term_to_iri(base_iri, term)}' is a lowercased non-property resource"
end end
defp case_violation_warning(:capitalized_alias, term, _, _) do defp case_violation_warning(:capitalized_alias, term, _, _) do
@ -539,16 +539,15 @@ defmodule RDF.Vocabulary.Namespace do
__ENV__ __ENV__
end end
defp rdf_data_vocab_terms(data, base_uri) do defp rdf_data_vocab_terms(data, base_iri) do
data data
|> RDF.Data.resources |> RDF.Data.resources
# filter URIs
|> Stream.filter(fn |> Stream.filter(fn
%URI{} -> true %RDF.IRI{} -> true
_ -> false _ -> false
end) end)
|> Stream.map(&URI.to_string/1) |> Stream.map(&to_string/1)
|> Stream.map(&(strip_base_uri(&1, base_uri))) |> Stream.map(&(strip_base_iri(&1, base_iri)))
|> Stream.filter(&vocab_term?/1) |> Stream.filter(&vocab_term?/1)
|> Enum.map(&String.to_atom/1) |> Enum.map(&String.to_atom/1)
end end
@ -570,9 +569,9 @@ defmodule RDF.Vocabulary.Namespace do
defp lowercase?(term), defp lowercase?(term),
do: term =~ ~r/^(_|\p{Ll})/u do: term =~ ~r/^(_|\p{Ll})/u
defp strip_base_uri(uri, base_uri) do defp strip_base_iri(iri, base_iri) do
if String.starts_with?(uri, base_uri) do if String.starts_with?(iri, base_iri) do
String.replace_prefix(uri, base_uri, "") String.replace_prefix(iri, base_iri, "")
end end
end end
@ -583,9 +582,9 @@ defmodule RDF.Vocabulary.Namespace do
defp vocab_term?(_), do: false defp vocab_term?(_), do: false
@doc false @doc false
def term_to_uri(base_uri, term) when is_atom(term), def term_to_iri(base_iri, term) when is_atom(term),
do: term_to_uri(base_uri, Atom.to_string(term)) do: term_to_iri(base_iri, Atom.to_string(term))
def term_to_uri(base_uri, term), def term_to_iri(base_iri, term),
do: URI.parse(base_uri <> term) do: RDF.iri(base_iri <> term)
end end

View file

@ -23,24 +23,24 @@ nonEmptyNquadsDoc -> statement : [ '$1' ].
statement -> subject predicate object graphLabel '.' : { '$1', '$2', '$3', '$4'}. statement -> subject predicate object graphLabel '.' : { '$1', '$2', '$3', '$4'}.
statement -> subject predicate object '.' : { '$1', '$2', '$3' }. statement -> subject predicate object '.' : { '$1', '$2', '$3' }.
subject -> iriref : to_uri('$1'). subject -> iriref : to_iri('$1').
subject -> blank_node_label : to_bnode('$1'). subject -> blank_node_label : to_bnode('$1').
predicate -> iriref : to_uri('$1'). predicate -> iriref : to_iri('$1').
object -> iriref : to_uri('$1'). object -> iriref : to_iri('$1').
object -> blank_node_label : to_bnode('$1'). object -> blank_node_label : to_bnode('$1').
object -> literal : '$1'. object -> literal : '$1'.
graphLabel -> iriref : to_uri('$1'). graphLabel -> iriref : to_iri('$1').
graphLabel -> blank_node_label : to_bnode('$1'). graphLabel -> blank_node_label : to_bnode('$1').
literal -> string_literal_quote '^^' iriref : to_literal('$1', {datatype, to_uri('$3')}). literal -> string_literal_quote '^^' iriref : to_literal('$1', {datatype, to_iri('$3')}).
literal -> string_literal_quote langtag : to_literal('$1', {language, to_langtag('$2')}). literal -> string_literal_quote langtag : to_literal('$1', {language, to_langtag('$2')}).
literal -> string_literal_quote : to_literal('$1'). literal -> string_literal_quote : to_literal('$1').
Erlang code. Erlang code.
to_uri(IRIREF) -> to_iri(IRIREF) ->
case 'Elixir.RDF.Serialization.ParseHelper':to_uri(IRIREF) of case 'Elixir.RDF.Serialization.ParseHelper':to_iri(IRIREF) of
{ok, URI} -> URI; {ok, URI} -> URI;
{error, ErrorLine, Message} -> return_error(ErrorLine, Message) {error, ErrorLine, Message} -> return_error(ErrorLine, Message)
end. end.

View file

@ -22,22 +22,22 @@ nonEmptyNtriplesDoc -> triple : [ '$1' ].
triple -> subject predicate object '.' : { '$1', '$2', '$3' }. triple -> subject predicate object '.' : { '$1', '$2', '$3' }.
subject -> iriref : to_uri('$1'). subject -> iriref : to_iri('$1').
subject -> blank_node_label : to_bnode('$1'). subject -> blank_node_label : to_bnode('$1').
predicate -> iriref : to_uri('$1'). predicate -> iriref : to_iri('$1').
object -> iriref : to_uri('$1'). object -> iriref : to_iri('$1').
object -> blank_node_label : to_bnode('$1'). object -> blank_node_label : to_bnode('$1').
object -> literal : '$1'. object -> literal : '$1'.
literal -> string_literal_quote '^^' iriref : to_literal('$1', {datatype, to_uri('$3')}). literal -> string_literal_quote '^^' iriref : to_literal('$1', {datatype, to_iri('$3')}).
literal -> string_literal_quote langtag : to_literal('$1', {language, to_langtag('$2')}). literal -> string_literal_quote langtag : to_literal('$1', {language, to_langtag('$2')}).
literal -> string_literal_quote : to_literal('$1'). literal -> string_literal_quote : to_literal('$1').
Erlang code. Erlang code.
to_uri(IRIREF) -> to_iri(IRIREF) ->
case 'Elixir.RDF.Serialization.ParseHelper':to_uri(IRIREF) of case 'Elixir.RDF.Serialization.ParseHelper':to_iri(IRIREF) of
{ok, URI} -> URI; {ok, URI} -> URI;
{error, ErrorLine, Message} -> return_error(ErrorLine, Message) {error, ErrorLine, Message} -> return_error(ErrorLine, Message)
end. end.

View file

@ -23,10 +23,10 @@ directive -> sparqlPrefix : '$1' .
directive -> base : '$1' . directive -> base : '$1' .
directive -> sparqlBase : '$1' . directive -> sparqlBase : '$1' .
prefixID -> '@prefix' prefix_ns iriref '.' : {prefix, '$2', to_uri_string('$3')} . prefixID -> '@prefix' prefix_ns iriref '.' : {prefix, '$2', to_iri_string('$3')} .
sparqlPrefix -> 'PREFIX' prefix_ns iriref : {prefix, '$2', to_uri_string('$3')} . sparqlPrefix -> 'PREFIX' prefix_ns iriref : {prefix, '$2', to_iri_string('$3')} .
sparqlBase -> 'BASE' iriref : {base, to_uri_string('$2')} . sparqlBase -> 'BASE' iriref : {base, to_iri_string('$2')} .
base -> '@base' iriref '.' : {base, to_uri_string('$2')} . base -> '@base' iriref '.' : {base, to_iri_string('$2')} .
triples -> subject predicateObjectList : { '$1', '$2' }. triples -> subject predicateObjectList : { '$1', '$2' }.
triples -> blankNodePropertyList predicateObjectList : { '$1', '$2' }. triples -> blankNodePropertyList predicateObjectList : { '$1', '$2' }.
@ -77,7 +77,7 @@ numericLiteral -> decimal : to_literal('$1') .
numericLiteral -> double : to_literal('$1') . numericLiteral -> double : to_literal('$1') .
booleanLiteral -> boolean : to_literal('$1') . booleanLiteral -> boolean : to_literal('$1') .
iri -> iriref : to_uri('$1') . iri -> iriref : to_iri('$1') .
iri -> prefixedName : '$1' . iri -> prefixedName : '$1' .
blankNode -> blank_node_label : to_bnode('$1') . blankNode -> blank_node_label : to_bnode('$1') .
@ -86,8 +86,8 @@ blankNode -> anon : {anon} .
Erlang code. Erlang code.
to_uri_string(IRIREF) -> 'Elixir.RDF.Serialization.ParseHelper':to_uri_string(IRIREF) . to_iri_string(IRIREF) -> 'Elixir.RDF.Serialization.ParseHelper':to_iri_string(IRIREF) .
to_uri(IRIREF) -> 'Elixir.RDF.Serialization.ParseHelper':to_absolute_or_relative_uri(IRIREF) . to_iri(IRIREF) -> 'Elixir.RDF.Serialization.ParseHelper':to_absolute_or_relative_iri(IRIREF) .
to_bnode(BLANK_NODE) -> 'Elixir.RDF.Serialization.ParseHelper':to_bnode(BLANK_NODE). to_bnode(BLANK_NODE) -> 'Elixir.RDF.Serialization.ParseHelper':to_bnode(BLANK_NODE).
to_literal(STRING_LITERAL_QUOTE) -> 'Elixir.RDF.Serialization.ParseHelper':to_literal(STRING_LITERAL_QUOTE). to_literal(STRING_LITERAL_QUOTE) -> 'Elixir.RDF.Serialization.ParseHelper':to_literal(STRING_LITERAL_QUOTE).
to_literal(STRING_LITERAL_QUOTE, Type) -> 'Elixir.RDF.Serialization.ParseHelper':to_literal(STRING_LITERAL_QUOTE, Type). to_literal(STRING_LITERAL_QUOTE, Type) -> 'Elixir.RDF.Serialization.ParseHelper':to_literal(STRING_LITERAL_QUOTE, Type).

View file

@ -3,18 +3,18 @@ defmodule RDF.Test.Case do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab EX, defvocab EX,
base_uri: "http://example.com/", base_iri: "http://example.com/",
terms: [], strict: false terms: [], strict: false
alias RDF.{Dataset, Graph, Description} alias RDF.{Dataset, Graph, Description, IRI}
import RDF, only: [uri: 1] import RDF, only: [iri: 1]
using do using do
quote do quote do
alias RDF.{Dataset, Graph, Description} alias RDF.{Dataset, Graph, Description, IRI}
alias unquote(__MODULE__).EX alias unquote(__MODULE__).EX
import RDF, only: [uri: 1, literal: 1, bnode: 1] import RDF, only: [iri: 1, literal: 1, bnode: 1]
import unquote(__MODULE__) import unquote(__MODULE__)
import RDF.Sigils import RDF.Sigils
@ -53,7 +53,7 @@ defmodule RDF.Test.Case do
def unnamed_graph?(%Graph{name: nil}), do: true def unnamed_graph?(%Graph{name: nil}), do: true
def unnamed_graph?(_), do: false def unnamed_graph?(_), do: false
def named_graph?(%Graph{name: %URI{}}), do: true def named_graph?(%Graph{name: %IRI{}}), do: true
def named_graph?(_), do: false def named_graph?(_), do: false
def named_graph?(%Graph{name: name}, name), do: true def named_graph?(%Graph{name: name}, name), do: true
def named_graph?(_, _), do: false def named_graph?(_, _), do: false
@ -63,7 +63,7 @@ defmodule RDF.Test.Case do
def graph_includes_statement?(graph, {subject, _, _} = statement) do def graph_includes_statement?(graph, {subject, _, _} = statement) do
graph.descriptions graph.descriptions
|> Map.get(uri(subject), %{}) |> Map.get(iri(subject), %{})
|> Enum.member?(statement) |> Enum.member?(statement)
end end
@ -80,7 +80,7 @@ defmodule RDF.Test.Case do
def unnamed_dataset?(%Dataset{name: nil}), do: true def unnamed_dataset?(%Dataset{name: nil}), do: true
def unnamed_dataset?(_), do: false def unnamed_dataset?(_), do: false
def named_dataset?(%Dataset{name: %URI{}}), do: true def named_dataset?(%Dataset{name: %IRI{}}), do: true
def named_dataset?(_), do: false def named_dataset?(_), do: false
def named_dataset?(%Dataset{name: name}, name), do: true def named_dataset?(%Dataset{name: name}, name), do: true
def named_dataset?(_, _), do: false def named_dataset?(_, _), do: false
@ -99,7 +99,7 @@ defmodule RDF.Test.Case do
def dataset_includes_statement?(dataset, def dataset_includes_statement?(dataset,
{subject, predicate, objects, graph_context}) do {subject, predicate, objects, graph_context}) do
dataset.graphs dataset.graphs
|> Map.get(uri(graph_context), named_graph(graph_context)) |> Map.get(iri(graph_context), named_graph(graph_context))
|> graph_includes_statement?({subject, predicate, objects}) |> graph_includes_statement?({subject, predicate, objects})
end end

View file

@ -3,7 +3,7 @@ defmodule RDF.Datatype.Test.Case do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab EX, defvocab EX,
base_uri: "http://example.com/", base_iri: "http://example.com/",
terms: [], strict: false terms: [], strict: false
alias RDF.{Literal, Datatype} alias RDF.{Literal, Datatype}

View file

@ -4,11 +4,11 @@ defmodule RDF.TestSuite do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab MF, defvocab MF,
base_uri: "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#", base_iri: "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#",
terms: [], strict: false terms: [], strict: false
defvocab RDFT, defvocab RDFT,
base_uri: "http://www.w3.org/ns/rdftest#", base_iri: "http://www.w3.org/ns/rdftest#",
terms: ~w[ terms: ~w[
TestTurtleEval TestTurtleEval
TestTurtlePositiveSyntax TestTurtlePositiveSyntax
@ -21,7 +21,7 @@ defmodule RDF.TestSuite do
alias RDF.NS.RDFS alias RDF.NS.RDFS
alias NS.MF alias NS.MF
alias RDF.{Turtle, Graph, Description} alias RDF.{Turtle, Graph, Description, IRI}
def dir(format), do: Path.join(RDF.TestData.dir, String.upcase(format) <> "-TESTS") def dir(format), do: Path.join(RDF.TestData.dir, String.upcase(format) <> "-TESTS")
@ -39,7 +39,7 @@ defmodule RDF.TestSuite do
|> manifest_graph(opts) |> manifest_graph(opts)
|> Graph.descriptions |> Graph.descriptions
|> Enum.filter(fn description -> |> Enum.filter(fn description ->
RDF.uri(test_type) in Description.get(description, RDF.type, []) RDF.iri(test_type) in Description.get(description, RDF.type, [])
end) end)
end end
@ -51,13 +51,17 @@ defmodule RDF.TestSuite do
# do: test_name(test_case) <> ": " <> value(test_case, RDFS.comment) # do: test_name(test_case) <> ": " <> value(test_case, RDFS.comment)
do: test_name(test_case) do: test_name(test_case)
def test_input_file(test_case), do: Description.first(test_case, MF.action) def test_input_file(test_case),
do: test_case |> Description.first(MF.action) |> IRI.parse
def test_output_file(test_case),
do: test_case |> Description.first(MF.result) |> IRI.parse
def test_input_file_path(test_case, format), def test_input_file_path(test_case, format),
do: test_input_file(test_case).path |> Path.basename |> file(format) do: test_input_file(test_case).path |> Path.basename |> file(format)
def test_result_file_path(test_case, format), def test_result_file_path(test_case, format),
do: Description.first(test_case, MF.result).path |> Path.basename |> file(format) do: test_output_file(test_case).path |> Path.basename |> file(format)
defp value(description, property), defp value(description, property),

View file

@ -14,7 +14,7 @@ defmodule RDF.DataTest do
EX.S2 EX.S2
|> EX.p2(EX.O3, EX.O4) |> EX.p2(EX.O3, EX.O4)
) )
named_graph = %Graph{graph | name: uri(EX.NamedGraph)} named_graph = %Graph{graph | name: iri(EX.NamedGraph)}
dataset = dataset =
Dataset.new Dataset.new
|> Dataset.add(graph) |> Dataset.add(graph)
@ -105,7 +105,7 @@ defmodule RDF.DataTest do
test "description when the requested subject does not match the Description.subject", test "description when the requested subject does not match the Description.subject",
%{description: description} do %{description: description} do
assert RDF.Data.description(description, uri(EX.Other)) == Description.new(EX.Other) assert RDF.Data.description(description, iri(EX.Other)) == Description.new(EX.Other)
end end
test "descriptions", %{description: description} do test "descriptions", %{description: description} do
@ -117,7 +117,7 @@ defmodule RDF.DataTest do
end end
test "subjects", %{description: description} do test "subjects", %{description: description} do
assert RDF.Data.subjects(description) == MapSet.new([uri(EX.S)]) assert RDF.Data.subjects(description) == MapSet.new([iri(EX.S)])
end end
test "predicates", %{description: description} do test "predicates", %{description: description} do
@ -126,12 +126,12 @@ defmodule RDF.DataTest do
test "objects", %{description: description} do test "objects", %{description: description} do
assert RDF.Data.objects(description) == assert RDF.Data.objects(description) ==
MapSet.new([uri(EX.O1), uri(EX.O2), uri(EX.O3), ~B<foo>]) MapSet.new([iri(EX.O1), iri(EX.O2), iri(EX.O3), ~B<foo>])
end end
test "resources", %{description: description} do test "resources", %{description: description} do
assert RDF.Data.resources(description) == assert RDF.Data.resources(description) ==
MapSet.new([uri(EX.S), EX.p1, EX.p2, EX.p3, uri(EX.O1), uri(EX.O2), uri(EX.O3), ~B<foo>]) MapSet.new([iri(EX.S), EX.p1, EX.p2, EX.p3, iri(EX.O1), iri(EX.O2), iri(EX.O3), ~B<foo>])
end end
test "subject_count", %{description: description} do test "subject_count", %{description: description} do
@ -228,12 +228,12 @@ defmodule RDF.DataTest do
test "description when a description is present", test "description when a description is present",
%{graph: graph, description: description} do %{graph: graph, description: description} do
assert RDF.Data.description(graph, uri(EX.S)) == description assert RDF.Data.description(graph, iri(EX.S)) == description
assert RDF.Data.description(graph, EX.S) == description assert RDF.Data.description(graph, EX.S) == description
end end
test "description when a description is not present", %{graph: graph} do test "description when a description is not present", %{graph: graph} do
assert RDF.Data.description(graph, uri(EX.Other)) == Description.new(EX.Other) assert RDF.Data.description(graph, iri(EX.Other)) == Description.new(EX.Other)
end end
test "descriptions", %{graph: graph, description: description} do test "descriptions", %{graph: graph, description: description} do
@ -246,7 +246,7 @@ defmodule RDF.DataTest do
end end
test "subjects", %{graph: graph} do test "subjects", %{graph: graph} do
assert RDF.Data.subjects(graph) == MapSet.new([uri(EX.S), uri(EX.S2)]) assert RDF.Data.subjects(graph) == MapSet.new([iri(EX.S), iri(EX.S2)])
end end
test "predicates", %{graph: graph} do test "predicates", %{graph: graph} do
@ -255,13 +255,13 @@ defmodule RDF.DataTest do
test "objects", %{graph: graph} do test "objects", %{graph: graph} do
assert RDF.Data.objects(graph) == assert RDF.Data.objects(graph) ==
MapSet.new([uri(EX.O1), uri(EX.O2), uri(EX.O3), uri(EX.O4), ~B<foo>]) MapSet.new([iri(EX.O1), iri(EX.O2), iri(EX.O3), iri(EX.O4), ~B<foo>])
end end
test "resources", %{graph: graph} do test "resources", %{graph: graph} do
assert RDF.Data.resources(graph) == MapSet.new([ assert RDF.Data.resources(graph) == MapSet.new([
uri(EX.S), uri(EX.S2), EX.p1, EX.p2, EX.p3, iri(EX.S), iri(EX.S2), EX.p1, EX.p2, EX.p3,
uri(EX.O1), uri(EX.O2), uri(EX.O3), uri(EX.O4), ~B<foo> iri(EX.O1), iri(EX.O2), iri(EX.O3), iri(EX.O4), ~B<foo>
]) ])
end end
@ -342,12 +342,12 @@ defmodule RDF.DataTest do
test "description when a description is present", test "description when a description is present",
%{dataset: dataset, description: description} do %{dataset: dataset, description: description} do
description_aggregate = Description.add(description, {EX.S, EX.p3, EX.O5}) description_aggregate = Description.add(description, {EX.S, EX.p3, EX.O5})
assert RDF.Data.description(dataset, uri(EX.S)) == description_aggregate assert RDF.Data.description(dataset, iri(EX.S)) == description_aggregate
assert RDF.Data.description(dataset, EX.S) == description_aggregate assert RDF.Data.description(dataset, EX.S) == description_aggregate
end end
test "description when a description is not present", %{dataset: dataset} do test "description when a description is not present", %{dataset: dataset} do
assert RDF.Data.description(dataset, uri(EX.Other)) == Description.new(EX.Other) assert RDF.Data.description(dataset, iri(EX.Other)) == Description.new(EX.Other)
end end
test "descriptions", %{dataset: dataset, description: description} do test "descriptions", %{dataset: dataset, description: description} do
@ -364,7 +364,7 @@ defmodule RDF.DataTest do
end end
test "subjects", %{dataset: dataset} do test "subjects", %{dataset: dataset} do
assert RDF.Data.subjects(dataset) == MapSet.new([uri(EX.S), uri(EX.S2), uri(EX.S3)]) assert RDF.Data.subjects(dataset) == MapSet.new([iri(EX.S), iri(EX.S2), iri(EX.S3)])
end end
test "predicates", %{dataset: dataset} do test "predicates", %{dataset: dataset} do
@ -373,13 +373,13 @@ defmodule RDF.DataTest do
test "objects", %{dataset: dataset} do test "objects", %{dataset: dataset} do
assert RDF.Data.objects(dataset) == assert RDF.Data.objects(dataset) ==
MapSet.new([uri(EX.O1), uri(EX.O2), uri(EX.O3), uri(EX.O4), uri(EX.O5), ~B<foo>]) MapSet.new([iri(EX.O1), iri(EX.O2), iri(EX.O3), iri(EX.O4), iri(EX.O5), ~B<foo>])
end end
test "resources", %{dataset: dataset} do test "resources", %{dataset: dataset} do
assert RDF.Data.resources(dataset) == MapSet.new([ assert RDF.Data.resources(dataset) == MapSet.new([
uri(EX.S), uri(EX.S2), uri(EX.S3), EX.p1, EX.p2, EX.p3, iri(EX.S), iri(EX.S2), iri(EX.S3), EX.p1, EX.p2, EX.p3,
uri(EX.O1), uri(EX.O2), uri(EX.O3), uri(EX.O4), uri(EX.O5), ~B<foo> iri(EX.O1), iri(EX.O2), iri(EX.O3), iri(EX.O4), iri(EX.O5), ~B<foo>
]) ])
end end

View file

@ -16,8 +16,8 @@ defmodule RDF.DatasetTest do
test "creating an empty dataset with a coercible dataset name" do test "creating an empty dataset with a coercible dataset name" do
assert named_dataset("http://example.com/DatasetName") assert named_dataset("http://example.com/DatasetName")
|> named_dataset?(uri("http://example.com/DatasetName")) |> named_dataset?(iri("http://example.com/DatasetName"))
assert named_dataset(EX.Foo) |> named_dataset?(uri(EX.Foo)) assert named_dataset(EX.Foo) |> named_dataset?(iri(EX.Foo))
end end
test "creating an unnamed dataset with an initial triple" do test "creating an unnamed dataset with an initial triple" do
@ -35,13 +35,13 @@ defmodule RDF.DatasetTest do
test "creating a named dataset with an initial triple" do test "creating a named dataset with an initial triple" do
ds = Dataset.new(EX.DatasetName, {EX.Subject, EX.predicate, EX.Object}) ds = Dataset.new(EX.DatasetName, {EX.Subject, EX.predicate, EX.Object})
assert named_dataset?(ds, uri(EX.DatasetName)) assert named_dataset?(ds, iri(EX.DatasetName))
assert dataset_includes_statement?(ds, {EX.Subject, EX.predicate, EX.Object}) assert dataset_includes_statement?(ds, {EX.Subject, EX.predicate, EX.Object})
end end
test "creating a named dataset with an initial quad" do test "creating a named dataset with an initial quad" do
ds = Dataset.new(EX.DatasetName, {EX.Subject, EX.predicate, EX.Object, EX.GraphName}) ds = Dataset.new(EX.DatasetName, {EX.Subject, EX.predicate, EX.Object, EX.GraphName})
assert named_dataset?(ds, uri(EX.DatasetName)) assert named_dataset?(ds, iri(EX.DatasetName))
assert dataset_includes_statement?(ds, {EX.Subject, EX.predicate, EX.Object, EX.GraphName}) assert dataset_includes_statement?(ds, {EX.Subject, EX.predicate, EX.Object, EX.GraphName})
end end
@ -63,7 +63,7 @@ defmodule RDF.DatasetTest do
{EX.Subject, EX.predicate2, EX.Object2, EX.GraphName}, {EX.Subject, EX.predicate2, EX.Object2, EX.GraphName},
{EX.Subject, EX.predicate3, EX.Object3, nil} {EX.Subject, EX.predicate3, EX.Object3, nil}
]) ])
assert named_dataset?(ds, uri(EX.DatasetName)) assert named_dataset?(ds, iri(EX.DatasetName))
assert dataset_includes_statement?(ds, {EX.Subject, EX.predicate1, EX.Object1, nil}) assert dataset_includes_statement?(ds, {EX.Subject, EX.predicate1, EX.Object1, nil})
assert dataset_includes_statement?(ds, {EX.Subject, EX.predicate2, EX.Object2, EX.GraphName}) assert dataset_includes_statement?(ds, {EX.Subject, EX.predicate2, EX.Object2, EX.GraphName})
assert dataset_includes_statement?(ds, {EX.Subject, EX.predicate3, EX.Object3, nil}) assert dataset_includes_statement?(ds, {EX.Subject, EX.predicate3, EX.Object3, nil})
@ -71,7 +71,7 @@ defmodule RDF.DatasetTest do
test "creating a named dataset with an initial description" do test "creating a named dataset with an initial description" do
ds = Dataset.new(EX.DatasetName, Description.new({EX.Subject, EX.predicate, EX.Object})) ds = Dataset.new(EX.DatasetName, Description.new({EX.Subject, EX.predicate, EX.Object}))
assert named_dataset?(ds, uri(EX.DatasetName)) assert named_dataset?(ds, iri(EX.DatasetName))
assert dataset_includes_statement?(ds, {EX.Subject, EX.predicate, EX.Object}) assert dataset_includes_statement?(ds, {EX.Subject, EX.predicate, EX.Object})
end end
@ -83,14 +83,14 @@ defmodule RDF.DatasetTest do
test "creating a named dataset with an inital graph" do test "creating a named dataset with an inital graph" do
ds = Dataset.new(EX.DatasetName, Graph.new({EX.Subject, EX.predicate, EX.Object})) ds = Dataset.new(EX.DatasetName, Graph.new({EX.Subject, EX.predicate, EX.Object}))
assert named_dataset?(ds, uri(EX.DatasetName)) assert named_dataset?(ds, iri(EX.DatasetName))
assert unnamed_graph?(Dataset.default_graph(ds)) assert unnamed_graph?(Dataset.default_graph(ds))
assert dataset_includes_statement?(ds, {EX.Subject, EX.predicate, EX.Object}) assert dataset_includes_statement?(ds, {EX.Subject, EX.predicate, EX.Object})
ds = Dataset.new(EX.DatasetName, Graph.new(EX.GraphName, {EX.Subject, EX.predicate, EX.Object})) ds = Dataset.new(EX.DatasetName, Graph.new(EX.GraphName, {EX.Subject, EX.predicate, EX.Object}))
assert named_dataset?(ds, uri(EX.DatasetName)) assert named_dataset?(ds, iri(EX.DatasetName))
assert unnamed_graph?(Dataset.default_graph(ds)) assert unnamed_graph?(Dataset.default_graph(ds))
assert named_graph?(Dataset.graph(ds, EX.GraphName), uri(EX.GraphName)) assert named_graph?(Dataset.graph(ds, EX.GraphName), iri(EX.GraphName))
assert dataset_includes_statement?(ds, {EX.Subject, EX.predicate, EX.Object, EX.GraphName}) assert dataset_includes_statement?(ds, {EX.Subject, EX.predicate, EX.Object, EX.GraphName})
end end
@ -103,24 +103,24 @@ defmodule RDF.DatasetTest do
ds = Dataset.new(Graph.new(EX.GraphName, {EX.Subject, EX.predicate, EX.Object})) ds = Dataset.new(Graph.new(EX.GraphName, {EX.Subject, EX.predicate, EX.Object}))
assert unnamed_dataset?(ds) assert unnamed_dataset?(ds)
assert unnamed_graph?(Dataset.default_graph(ds)) assert unnamed_graph?(Dataset.default_graph(ds))
assert named_graph?(Dataset.graph(ds, EX.GraphName), uri(EX.GraphName)) assert named_graph?(Dataset.graph(ds, EX.GraphName), iri(EX.GraphName))
assert dataset_includes_statement?(ds, {EX.Subject, EX.predicate, EX.Object, EX.GraphName}) assert dataset_includes_statement?(ds, {EX.Subject, EX.predicate, EX.Object, EX.GraphName})
end end
end end
describe "add" do describe "add" do
test "a proper triple is added to the default graph" do test "a proper triple is added to the default graph" do
assert Dataset.add(dataset(), {uri(EX.Subject), EX.predicate, uri(EX.Object)}) assert Dataset.add(dataset(), {iri(EX.Subject), EX.predicate, iri(EX.Object)})
|> dataset_includes_statement?({EX.Subject, EX.predicate, EX.Object}) |> dataset_includes_statement?({EX.Subject, EX.predicate, EX.Object})
end end
test "a proper quad is added to the specified graph" do test "a proper quad is added to the specified graph" do
ds = Dataset.add(dataset(), {uri(EX.Subject), EX.predicate, uri(EX.Object), uri(EX.Graph)}) ds = Dataset.add(dataset(), {iri(EX.Subject), EX.predicate, iri(EX.Object), iri(EX.Graph)})
assert dataset_includes_statement?(ds, {EX.Subject, EX.predicate, EX.Object, uri(EX.Graph)}) assert dataset_includes_statement?(ds, {EX.Subject, EX.predicate, EX.Object, iri(EX.Graph)})
end end
test "a proper quad with nil context is added to the default graph" do test "a proper quad with nil context is added to the default graph" do
ds = Dataset.add(dataset(), {uri(EX.Subject), EX.predicate, uri(EX.Object), nil}) ds = Dataset.add(dataset(), {iri(EX.Subject), EX.predicate, iri(EX.Object), nil})
assert dataset_includes_statement?(ds, {EX.Subject, EX.predicate, EX.Object}) assert dataset_includes_statement?(ds, {EX.Subject, EX.predicate, EX.Object})
end end
@ -284,7 +284,7 @@ defmodule RDF.DatasetTest do
ds = Dataset.add(ds, Graph.new({EX.Subject1, EX.predicate2, EX.Object3}), EX.Graph) ds = Dataset.add(ds, Graph.new({EX.Subject1, EX.predicate2, EX.Object3}), EX.Graph)
assert unnamed_graph?(Dataset.default_graph(ds)) assert unnamed_graph?(Dataset.default_graph(ds))
assert named_graph?(Dataset.graph(ds, EX.Graph), uri(EX.Graph)) assert named_graph?(Dataset.graph(ds, EX.Graph), iri(EX.Graph))
assert Enum.count(ds) == 4 assert Enum.count(ds) == 4
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate1, EX.Object1}) assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate1, EX.Object1})
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate2, EX.Object2}) assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate2, EX.Object2})
@ -298,14 +298,14 @@ defmodule RDF.DatasetTest do
{EX.Subject1, EX.predicate2, EX.Object2}, {EX.Subject1, EX.predicate2, EX.Object2},
])) ]))
assert Dataset.graph(ds, EX.Graph1) assert Dataset.graph(ds, EX.Graph1)
assert named_graph?(Dataset.graph(ds, EX.Graph1), uri(EX.Graph1)) assert named_graph?(Dataset.graph(ds, EX.Graph1), iri(EX.Graph1))
assert unnamed_graph?(Dataset.default_graph(ds)) assert unnamed_graph?(Dataset.default_graph(ds))
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate1, EX.Object1, EX.Graph1}) assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate1, EX.Object1, EX.Graph1})
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate2, EX.Object2, EX.Graph1}) assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate2, EX.Object2, EX.Graph1})
ds = Dataset.add(ds, Graph.new(EX.Graph2, {EX.Subject1, EX.predicate2, EX.Object3})) ds = Dataset.add(ds, Graph.new(EX.Graph2, {EX.Subject1, EX.predicate2, EX.Object3}))
assert Dataset.graph(ds, EX.Graph2) assert Dataset.graph(ds, EX.Graph2)
assert named_graph?(Dataset.graph(ds, EX.Graph2), uri(EX.Graph2)) assert named_graph?(Dataset.graph(ds, EX.Graph2), iri(EX.Graph2))
assert unnamed_graph?(Dataset.default_graph(ds)) assert unnamed_graph?(Dataset.default_graph(ds))
assert Enum.count(ds) == 3 assert Enum.count(ds) == 3
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate1, EX.Object1, EX.Graph1}) assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate1, EX.Object1, EX.Graph1})
@ -332,7 +332,7 @@ defmodule RDF.DatasetTest do
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate2, EX.Object3}) assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate2, EX.Object3})
ds = Dataset.add(ds, Graph.new(EX.Graph3, {EX.Subject1, EX.predicate2, EX.Object3}), EX.Graph) ds = Dataset.add(ds, Graph.new(EX.Graph3, {EX.Subject1, EX.predicate2, EX.Object3}), EX.Graph)
assert named_graph?(Dataset.graph(ds, EX.Graph), uri(EX.Graph)) assert named_graph?(Dataset.graph(ds, EX.Graph), iri(EX.Graph))
assert Enum.count(ds) == 4 assert Enum.count(ds) == 4
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate1, EX.Object1}) assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate1, EX.Object1})
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate2, EX.Object2}) assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate2, EX.Object2})
@ -366,14 +366,14 @@ defmodule RDF.DatasetTest do
{EX.Subject1, EX.predicate1, EX.Object1}, {EX.Subject1, EX.predicate1, EX.Object1},
{EX.Subject1, EX.predicate2, EX.Object2}, {EX.Subject1, EX.predicate2, EX.Object2},
])) ]))
assert ds.name == uri(EX.DatasetName) assert ds.name == iri(EX.DatasetName)
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate1, EX.Object1}) assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate1, EX.Object1})
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate2, EX.Object2}) assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate2, EX.Object2})
ds = Dataset.add(ds, Dataset.new(EX.DS2, {EX.Subject1, EX.predicate2, EX.Object3})) ds = Dataset.add(ds, Dataset.new(EX.DS2, {EX.Subject1, EX.predicate2, EX.Object3}))
ds = Dataset.add(ds, Dataset.new(EX.DS2, {EX.Subject1, EX.predicate2, EX.Object3, EX.Graph})) ds = Dataset.add(ds, Dataset.new(EX.DS2, {EX.Subject1, EX.predicate2, EX.Object3, EX.Graph}))
ds = Dataset.add(ds, Dataset.new(EX.DS2, {EX.Subject1, EX.predicate2, EX.Object4}), EX.Graph) ds = Dataset.add(ds, Dataset.new(EX.DS2, {EX.Subject1, EX.predicate2, EX.Object4}), EX.Graph)
assert ds.name == uri(EX.DatasetName) assert ds.name == iri(EX.DatasetName)
assert Enum.count(ds) == 5 assert Enum.count(ds) == 5
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate1, EX.Object1}) assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate1, EX.Object1})
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate2, EX.Object2}) assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate2, EX.Object2})
@ -428,14 +428,14 @@ defmodule RDF.DatasetTest do
end end
test "non-coercible statements elements are causing an error" do test "non-coercible statements elements are causing an error" do
assert_raise RDF.InvalidURIError, fn -> assert_raise RDF.IRI.InvalidError, fn ->
Dataset.add(dataset(), {"not a URI", EX.predicate, uri(EX.Object), uri(EX.GraphName)}) Dataset.add(dataset(), {"not a IRI", EX.predicate, iri(EX.Object), iri(EX.GraphName)})
end end
assert_raise RDF.InvalidLiteralError, fn -> assert_raise RDF.Literal.InvalidError, fn ->
Dataset.add(dataset(), {EX.Subject, EX.prop, self(), nil}) Dataset.add(dataset(), {EX.Subject, EX.prop, self(), nil})
end end
assert_raise RDF.InvalidURIError, fn -> assert_raise RDF.IRI.InvalidError, fn ->
Dataset.add(dataset(), {uri(EX.Subject), EX.predicate, uri(EX.Object), "not a URI"}) Dataset.add(dataset(), {iri(EX.Subject), EX.predicate, iri(EX.Object), "not a IRI"})
end end
end end
end end
@ -683,20 +683,20 @@ defmodule RDF.DatasetTest do
assert Dataset.pop(Dataset.new) == {nil, Dataset.new} assert Dataset.pop(Dataset.new) == {nil, Dataset.new}
{quad, dataset} = Dataset.new({EX.S, EX.p, EX.O, EX.Graph}) |> Dataset.pop {quad, dataset} = Dataset.new({EX.S, EX.p, EX.O, EX.Graph}) |> Dataset.pop
assert quad == {uri(EX.S), uri(EX.p), uri(EX.O), uri(EX.Graph)} assert quad == {iri(EX.S), iri(EX.p), iri(EX.O), iri(EX.Graph)}
assert Enum.count(dataset.graphs) == 0 assert Enum.count(dataset.graphs) == 0
{{subject, predicate, object, _}, dataset} = {{subject, predicate, object, _}, dataset} =
Dataset.new([{EX.S, EX.p, EX.O, EX.Graph}, {EX.S, EX.p, EX.O}]) Dataset.new([{EX.S, EX.p, EX.O, EX.Graph}, {EX.S, EX.p, EX.O}])
|> Dataset.pop |> Dataset.pop
assert {subject, predicate, object} == {uri(EX.S), uri(EX.p), uri(EX.O)} assert {subject, predicate, object} == {iri(EX.S), iri(EX.p), iri(EX.O)}
assert Enum.count(dataset.graphs) == 1 assert Enum.count(dataset.graphs) == 1
{{subject, _, _, graph_context}, dataset} = {{subject, _, _, graph_context}, dataset} =
Dataset.new([{EX.S, EX.p, EX.O1, EX.Graph}, {EX.S, EX.p, EX.O2, EX.Graph}]) Dataset.new([{EX.S, EX.p, EX.O1, EX.Graph}, {EX.S, EX.p, EX.O2, EX.Graph}])
|> Dataset.pop |> Dataset.pop
assert subject == uri(EX.S) assert subject == iri(EX.S)
assert graph_context == uri(EX.Graph) assert graph_context == iri(EX.Graph)
assert Enum.count(dataset.graphs) == 1 assert Enum.count(dataset.graphs) == 1
end end
@ -716,7 +716,7 @@ defmodule RDF.DatasetTest do
end end
test "Enum.member?" do test "Enum.member?" do
refute Enum.member?(Dataset.new, {uri(EX.S), EX.p, uri(EX.O), uri(EX.Graph)}) refute Enum.member?(Dataset.new, {iri(EX.S), EX.p, iri(EX.O), iri(EX.Graph)})
assert Enum.member?(Dataset.new({EX.S, EX.p, EX.O, EX.Graph}), assert Enum.member?(Dataset.new({EX.S, EX.p, EX.O, EX.Graph}),
{EX.S, EX.p, EX.O, EX.Graph}) {EX.S, EX.p, EX.O, EX.Graph})

View file

@ -5,18 +5,18 @@ defmodule RDF.DescriptionTest do
describe "new" do describe "new" do
test "with a subject URI" do test "with a subject IRI" do
assert description_of_subject(Description.new(URI.parse("http://example.com/description/subject")), assert description_of_subject(Description.new(~I<http://example.com/description/subject>),
URI.parse("http://example.com/description/subject")) ~I<http://example.com/description/subject>)
end end
test "with a raw subject URI string" do test "with a raw subject IRI string" do
assert description_of_subject(Description.new("http://example.com/description/subject"), assert description_of_subject(Description.new("http://example.com/description/subject"),
URI.parse("http://example.com/description/subject")) ~I<http://example.com/description/subject>)
end end
test "with an unresolved subject URI term atom" do test "with an unresolved subject IRI term atom" do
assert description_of_subject(Description.new(EX.Bar), uri(EX.Bar)) assert description_of_subject(Description.new(EX.Bar), iri(EX.Bar))
end end
test "with a BlankNode subject" do test "with a BlankNode subject" do
@ -25,24 +25,24 @@ defmodule RDF.DescriptionTest do
test "with a single initial triple" do test "with a single initial triple" do
desc = Description.new({EX.Subject, EX.predicate, EX.Object}) desc = Description.new({EX.Subject, EX.predicate, EX.Object})
assert description_of_subject(desc, uri(EX.Subject)) assert description_of_subject(desc, iri(EX.Subject))
assert description_includes_predication(desc, {EX.predicate, uri(EX.Object)}) assert description_includes_predication(desc, {EX.predicate, iri(EX.Object)})
desc = Description.new(EX.Subject, EX.predicate, 42) desc = Description.new(EX.Subject, EX.predicate, 42)
assert description_of_subject(desc, uri(EX.Subject)) assert description_of_subject(desc, iri(EX.Subject))
assert description_includes_predication(desc, {EX.predicate, literal(42)}) assert description_includes_predication(desc, {EX.predicate, literal(42)})
end end
test "with a list of initial triples" do test "with a list of initial triples" do
desc = Description.new([{EX.Subject, EX.predicate1, EX.Object1}, desc = Description.new([{EX.Subject, EX.predicate1, EX.Object1},
{EX.Subject, EX.predicate2, EX.Object2}]) {EX.Subject, EX.predicate2, EX.Object2}])
assert description_of_subject(desc, uri(EX.Subject)) assert description_of_subject(desc, iri(EX.Subject))
assert description_includes_predication(desc, {EX.predicate1, uri(EX.Object1)}) assert description_includes_predication(desc, {EX.predicate1, iri(EX.Object1)})
assert description_includes_predication(desc, {EX.predicate2, uri(EX.Object2)}) assert description_includes_predication(desc, {EX.predicate2, iri(EX.Object2)})
desc = Description.new(EX.Subject, EX.predicate, [EX.Object, bnode(:foo), "bar"]) desc = Description.new(EX.Subject, EX.predicate, [EX.Object, bnode(:foo), "bar"])
assert description_of_subject(desc, uri(EX.Subject)) assert description_of_subject(desc, iri(EX.Subject))
assert description_includes_predication(desc, {EX.predicate, uri(EX.Object)}) assert description_includes_predication(desc, {EX.predicate, iri(EX.Object)})
assert description_includes_predication(desc, {EX.predicate, bnode(:foo)}) assert description_includes_predication(desc, {EX.predicate, bnode(:foo)})
assert description_includes_predication(desc, {EX.predicate, literal("bar")}) assert description_includes_predication(desc, {EX.predicate, literal("bar")})
end end
@ -50,14 +50,14 @@ defmodule RDF.DescriptionTest do
test "from another description" do test "from another description" do
desc1 = Description.new({EX.Other, EX.predicate, EX.Object}) desc1 = Description.new({EX.Other, EX.predicate, EX.Object})
desc2 = Description.new(EX.Subject, desc1) desc2 = Description.new(EX.Subject, desc1)
assert description_of_subject(desc2, uri(EX.Subject)) assert description_of_subject(desc2, iri(EX.Subject))
assert description_includes_predication(desc2, {EX.predicate, uri(EX.Object)}) assert description_includes_predication(desc2, {EX.predicate, iri(EX.Object)})
end end
test "from a map with coercible RDF term" do test "from a map with coercible RDF term" do
desc = Description.new(EX.Subject, %{EX.Predicate => EX.Object}) desc = Description.new(EX.Subject, %{EX.Predicate => EX.Object})
assert description_of_subject(desc, uri(EX.Subject)) assert description_of_subject(desc, iri(EX.Subject))
assert description_includes_predication(desc, {uri(EX.Predicate), uri(EX.Object)}) assert description_includes_predication(desc, {iri(EX.Predicate), iri(EX.Object)})
end end
test "with another description as subject, it performs and add " do test "with another description as subject, it performs and add " do
@ -73,16 +73,16 @@ defmodule RDF.DescriptionTest do
describe "add" do describe "add" do
test "a predicate-object-pair of proper RDF terms" do test "a predicate-object-pair of proper RDF terms" do
assert Description.add(description(), EX.predicate, uri(EX.Object)) assert Description.add(description(), EX.predicate, iri(EX.Object))
|> description_includes_predication({EX.predicate, uri(EX.Object)}) |> description_includes_predication({EX.predicate, iri(EX.Object)})
assert Description.add(description(), {EX.predicate, uri(EX.Object)}) assert Description.add(description(), {EX.predicate, iri(EX.Object)})
|> description_includes_predication({EX.predicate, uri(EX.Object)}) |> description_includes_predication({EX.predicate, iri(EX.Object)})
end end
test "a predicate-object-pair of coercible RDF terms" do test "a predicate-object-pair of coercible RDF terms" do
assert Description.add(description(), assert Description.add(description(),
"http://example.com/predicate", uri(EX.Object)) "http://example.com/predicate", iri(EX.Object))
|> description_includes_predication({EX.predicate, uri(EX.Object)}) |> description_includes_predication({EX.predicate, iri(EX.Object)})
assert Description.add(description(), assert Description.add(description(),
{"http://example.com/predicate", 42}) {"http://example.com/predicate", 42})
@ -99,28 +99,28 @@ defmodule RDF.DescriptionTest do
test "a proper triple" do test "a proper triple" do
assert Description.add(description(), assert Description.add(description(),
{uri(EX.Subject), EX.predicate, uri(EX.Object)}) {iri(EX.Subject), EX.predicate, iri(EX.Object)})
|> description_includes_predication({EX.predicate, uri(EX.Object)}) |> description_includes_predication({EX.predicate, iri(EX.Object)})
assert Description.add(description(), assert Description.add(description(),
{uri(EX.Subject), EX.predicate, literal(42)}) {iri(EX.Subject), EX.predicate, literal(42)})
|> description_includes_predication({EX.predicate, literal(42)}) |> description_includes_predication({EX.predicate, literal(42)})
assert Description.add(description(), assert Description.add(description(),
{uri(EX.Subject), EX.predicate, bnode(:foo)}) {iri(EX.Subject), EX.predicate, bnode(:foo)})
|> description_includes_predication({EX.predicate, bnode(:foo)}) |> description_includes_predication({EX.predicate, bnode(:foo)})
end end
test "add ignores triples not about the subject of the Description struct" do test "add ignores triples not about the subject of the Description struct" do
assert empty_description( assert empty_description(
Description.add(description(), {EX.Other, EX.predicate, uri(EX.Object)})) Description.add(description(), {EX.Other, EX.predicate, iri(EX.Object)}))
end end
test "a list of predicate-object-pairs" do test "a list of predicate-object-pairs" do
desc = Description.add(description(), desc = Description.add(description(),
[{EX.predicate, EX.Object1}, {EX.predicate, EX.Object2}]) [{EX.predicate, EX.Object1}, {EX.predicate, EX.Object2}])
assert description_includes_predication(desc, {EX.predicate, uri(EX.Object1)}) assert description_includes_predication(desc, {EX.predicate, iri(EX.Object1)})
assert description_includes_predication(desc, {EX.predicate, uri(EX.Object2)}) assert description_includes_predication(desc, {EX.predicate, iri(EX.Object2)})
end end
test "a list of triples" do test "a list of triples" do
@ -128,8 +128,8 @@ defmodule RDF.DescriptionTest do
{EX.Subject, EX.predicate1, EX.Object1}, {EX.Subject, EX.predicate1, EX.Object1},
{EX.Subject, EX.predicate2, EX.Object2} {EX.Subject, EX.predicate2, EX.Object2}
]) ])
assert description_includes_predication(desc, {EX.predicate1, uri(EX.Object1)}) assert description_includes_predication(desc, {EX.predicate1, iri(EX.Object1)})
assert description_includes_predication(desc, {EX.predicate2, uri(EX.Object2)}) assert description_includes_predication(desc, {EX.predicate2, iri(EX.Object2)})
end end
test "a list of mixed triples and predicate-object-pairs" do test "a list of mixed triples and predicate-object-pairs" do
@ -138,10 +138,10 @@ defmodule RDF.DescriptionTest do
{EX.Subject, EX.predicate, EX.Object2}, {EX.Subject, EX.predicate, EX.Object2},
{EX.Other, EX.predicate, EX.Object3} {EX.Other, EX.predicate, EX.Object3}
]) ])
assert description_of_subject(desc, uri(EX.Subject)) assert description_of_subject(desc, iri(EX.Subject))
assert description_includes_predication(desc, {EX.predicate, uri(EX.Object1)}) assert description_includes_predication(desc, {EX.predicate, iri(EX.Object1)})
assert description_includes_predication(desc, {EX.predicate, uri(EX.Object2)}) assert description_includes_predication(desc, {EX.predicate, iri(EX.Object2)})
refute description_includes_predication(desc, {EX.predicate, uri(EX.Object3)}) refute description_includes_predication(desc, {EX.predicate, iri(EX.Object3)})
end end
@ -149,44 +149,44 @@ defmodule RDF.DescriptionTest do
desc = description([{EX.predicate1, EX.Object1}, {EX.predicate2, EX.Object2}]) desc = description([{EX.predicate1, EX.Object1}, {EX.predicate2, EX.Object2}])
|> Description.add(Description.new({EX.Other, EX.predicate3, EX.Object3})) |> Description.add(Description.new({EX.Other, EX.predicate3, EX.Object3}))
assert description_of_subject(desc, uri(EX.Subject)) assert description_of_subject(desc, iri(EX.Subject))
assert description_includes_predication(desc, {EX.predicate1, uri(EX.Object1)}) assert description_includes_predication(desc, {EX.predicate1, iri(EX.Object1)})
assert description_includes_predication(desc, {EX.predicate2, uri(EX.Object2)}) assert description_includes_predication(desc, {EX.predicate2, iri(EX.Object2)})
assert description_includes_predication(desc, {EX.predicate3, uri(EX.Object3)}) assert description_includes_predication(desc, {EX.predicate3, iri(EX.Object3)})
desc = Description.add(desc, Description.new({EX.Other, EX.predicate1, EX.Object4})) desc = Description.add(desc, Description.new({EX.Other, EX.predicate1, EX.Object4}))
assert description_includes_predication(desc, {EX.predicate1, uri(EX.Object1)}) assert description_includes_predication(desc, {EX.predicate1, iri(EX.Object1)})
assert description_includes_predication(desc, {EX.predicate2, uri(EX.Object2)}) assert description_includes_predication(desc, {EX.predicate2, iri(EX.Object2)})
assert description_includes_predication(desc, {EX.predicate3, uri(EX.Object3)}) assert description_includes_predication(desc, {EX.predicate3, iri(EX.Object3)})
assert description_includes_predication(desc, {EX.predicate1, uri(EX.Object4)}) assert description_includes_predication(desc, {EX.predicate1, iri(EX.Object4)})
end end
test "a map of predications with coercible RDF terms" do test "a map of predications with coercible RDF terms" do
desc = description([{EX.predicate1, EX.Object1}, {EX.predicate2, EX.Object2}]) desc = description([{EX.predicate1, EX.Object1}, {EX.predicate2, EX.Object2}])
|> Description.add(%{EX.predicate3 => EX.Object3}) |> Description.add(%{EX.predicate3 => EX.Object3})
assert description_of_subject(desc, uri(EX.Subject)) assert description_of_subject(desc, iri(EX.Subject))
assert description_includes_predication(desc, {EX.predicate1, uri(EX.Object1)}) assert description_includes_predication(desc, {EX.predicate1, iri(EX.Object1)})
assert description_includes_predication(desc, {EX.predicate2, uri(EX.Object2)}) assert description_includes_predication(desc, {EX.predicate2, iri(EX.Object2)})
assert description_includes_predication(desc, {EX.predicate3, uri(EX.Object3)}) assert description_includes_predication(desc, {EX.predicate3, iri(EX.Object3)})
desc = Description.add(desc, %{EX.predicate1 => EX.Object1, desc = Description.add(desc, %{EX.predicate1 => EX.Object1,
EX.predicate2 => [EX.Object2, 42], EX.predicate2 => [EX.Object2, 42],
EX.predicate3 => [bnode(:foo)]}) EX.predicate3 => [bnode(:foo)]})
assert Description.count(desc) == 5 assert Description.count(desc) == 5
assert description_includes_predication(desc, {EX.predicate1, uri(EX.Object1)}) assert description_includes_predication(desc, {EX.predicate1, iri(EX.Object1)})
assert description_includes_predication(desc, {EX.predicate2, uri(EX.Object2)}) assert description_includes_predication(desc, {EX.predicate2, iri(EX.Object2)})
assert description_includes_predication(desc, {EX.predicate2, literal(42)}) assert description_includes_predication(desc, {EX.predicate2, literal(42)})
assert description_includes_predication(desc, {EX.predicate3, uri(EX.Object3)}) assert description_includes_predication(desc, {EX.predicate3, iri(EX.Object3)})
assert description_includes_predication(desc, {EX.predicate3, bnode(:foo)}) assert description_includes_predication(desc, {EX.predicate3, bnode(:foo)})
end end
test "a map of predications with non-coercible RDF terms" do test "a map of predications with non-coercible RDF terms" do
assert_raise RDF.InvalidURIError, fn -> assert_raise RDF.IRI.InvalidError, fn ->
Description.add(description(), %{"not a URI" => uri(EX.Object)}) Description.add(description(), %{"not a IRI" => iri(EX.Object)})
end end
assert_raise RDF.InvalidLiteralError, fn -> assert_raise RDF.Literal.InvalidError, fn ->
Description.add(description(), %{EX.prop => self()}) Description.add(description(), %{EX.prop => self()})
end end
end end
@ -201,11 +201,11 @@ defmodule RDF.DescriptionTest do
end end
test "non-coercible Triple elements are causing an error" do test "non-coercible Triple elements are causing an error" do
assert_raise RDF.InvalidURIError, fn -> assert_raise RDF.IRI.InvalidError, fn ->
Description.add(description(), {"not a URI", uri(EX.Object)}) Description.add(description(), {"not a IRI", iri(EX.Object)})
end end
assert_raise RDF.InvalidLiteralError, fn -> assert_raise RDF.Literal.InvalidError, fn ->
Description.add(description(), {EX.prop, self()}) Description.add(description(), {EX.prop, self()})
end end
end end
@ -323,19 +323,19 @@ defmodule RDF.DescriptionTest do
assert Description.pop(Description.new(EX.S)) == {nil, Description.new(EX.S)} assert Description.pop(Description.new(EX.S)) == {nil, Description.new(EX.S)}
{triple, desc} = Description.new({EX.S, EX.p, EX.O}) |> Description.pop {triple, desc} = Description.new({EX.S, EX.p, EX.O}) |> Description.pop
assert {uri(EX.S), uri(EX.p), uri(EX.O)} == triple assert {iri(EX.S), iri(EX.p), iri(EX.O)} == triple
assert Enum.count(desc.predications) == 0 assert Enum.count(desc.predications) == 0
{{subject, predicate, _}, desc} = {{subject, predicate, _}, desc} =
Description.new([{EX.S, EX.p, EX.O1}, {EX.S, EX.p, EX.O2}]) Description.new([{EX.S, EX.p, EX.O1}, {EX.S, EX.p, EX.O2}])
|> Description.pop |> Description.pop
assert {subject, predicate} == {uri(EX.S), uri(EX.p)} assert {subject, predicate} == {iri(EX.S), iri(EX.p)}
assert Enum.count(desc.predications) == 1 assert Enum.count(desc.predications) == 1
{{subject, _, _}, desc} = {{subject, _, _}, desc} =
Description.new([{EX.S, EX.p1, EX.O1}, {EX.S, EX.p2, EX.O2}]) Description.new([{EX.S, EX.p1, EX.O1}, {EX.S, EX.p2, EX.O2}])
|> Description.pop |> Description.pop
assert subject == uri(EX.S) assert subject == iri(EX.S)
assert Enum.count(desc.predications) == 1 assert Enum.count(desc.predications) == 1
end end
@ -347,7 +347,7 @@ defmodule RDF.DescriptionTest do
end end
test "Enum.member?" do test "Enum.member?" do
refute Enum.member?(Description.new(EX.S), {uri(EX.S), EX.p, uri(EX.O)}) refute Enum.member?(Description.new(EX.S), {iri(EX.S), EX.p, iri(EX.O)})
assert Enum.member?(Description.new({EX.S, EX.p, EX.O}), {EX.S, EX.p, EX.O}) assert Enum.member?(Description.new({EX.S, EX.p, EX.O}), {EX.S, EX.p, EX.O})
desc = Description.new([ desc = Description.new([
@ -373,13 +373,13 @@ defmodule RDF.DescriptionTest do
describe "Access behaviour" do describe "Access behaviour" do
test "access with the [] operator" do test "access with the [] operator" do
assert Description.new(EX.Subject)[EX.predicate] == nil assert Description.new(EX.Subject)[EX.predicate] == nil
assert Description.new(EX.Subject, EX.predicate, EX.Object)[EX.predicate] == [uri(EX.Object)] assert Description.new(EX.Subject, EX.predicate, EX.Object)[EX.predicate] == [iri(EX.Object)]
assert Description.new(EX.Subject, EX.Predicate, EX.Object)[EX.Predicate] == [uri(EX.Object)] assert Description.new(EX.Subject, EX.Predicate, EX.Object)[EX.Predicate] == [iri(EX.Object)]
assert Description.new(EX.Subject, EX.predicate, EX.Object)["http://example.com/predicate"] == [uri(EX.Object)] assert Description.new(EX.Subject, EX.predicate, EX.Object)["http://example.com/predicate"] == [iri(EX.Object)]
assert Description.new([{EX.Subject, EX.predicate1, EX.Object1}, assert Description.new([{EX.Subject, EX.predicate1, EX.Object1},
{EX.Subject, EX.predicate1, EX.Object2}, {EX.Subject, EX.predicate1, EX.Object2},
{EX.Subject, EX.predicate2, EX.Object3}])[EX.predicate1] == {EX.Subject, EX.predicate2, EX.Object3}])[EX.predicate1] ==
[uri(EX.Object1), uri(EX.Object2)] [iri(EX.Object1), iri(EX.Object2)]
end end
end end

View file

@ -21,8 +21,8 @@ defmodule RDF.GraphTest do
test "creating an empty graph with a coercible graph name" do test "creating an empty graph with a coercible graph name" do
assert named_graph("http://example.com/graph/GraphName") assert named_graph("http://example.com/graph/GraphName")
|> named_graph?(uri("http://example.com/graph/GraphName")) |> named_graph?(iri("http://example.com/graph/GraphName"))
assert named_graph(EX.Foo) |> named_graph?(uri(EX.Foo)) assert named_graph(EX.Foo) |> named_graph?(iri(EX.Foo))
end end
test "creating an unnamed graph with an initial triple" do test "creating an unnamed graph with an initial triple" do
@ -37,11 +37,11 @@ defmodule RDF.GraphTest do
test "creating a named graph with an initial triple" do test "creating a named graph with an initial triple" do
g = Graph.new(EX.GraphName, {EX.Subject, EX.predicate, EX.Object}) g = Graph.new(EX.GraphName, {EX.Subject, EX.predicate, EX.Object})
assert named_graph?(g, uri(EX.GraphName)) assert named_graph?(g, iri(EX.GraphName))
assert graph_includes_statement?(g, {EX.Subject, EX.predicate, EX.Object}) assert graph_includes_statement?(g, {EX.Subject, EX.predicate, EX.Object})
g = Graph.new(EX.GraphName, EX.Subject, EX.predicate, EX.Object) g = Graph.new(EX.GraphName, EX.Subject, EX.predicate, EX.Object)
assert named_graph?(g, uri(EX.GraphName)) assert named_graph?(g, iri(EX.GraphName))
assert graph_includes_statement?(g, {EX.Subject, EX.predicate, EX.Object}) assert graph_includes_statement?(g, {EX.Subject, EX.predicate, EX.Object})
end end
@ -61,19 +61,19 @@ defmodule RDF.GraphTest do
test "creating a named graph with a list of initial triples" do test "creating a named graph with a list of initial triples" do
g = Graph.new(EX.GraphName, [{EX.Subject, EX.predicate1, EX.Object1}, g = Graph.new(EX.GraphName, [{EX.Subject, EX.predicate1, EX.Object1},
{EX.Subject, EX.predicate2, EX.Object2}]) {EX.Subject, EX.predicate2, EX.Object2}])
assert named_graph?(g, uri(EX.GraphName)) assert named_graph?(g, iri(EX.GraphName))
assert graph_includes_statement?(g, {EX.Subject, EX.predicate1, EX.Object1}) assert graph_includes_statement?(g, {EX.Subject, EX.predicate1, EX.Object1})
assert graph_includes_statement?(g, {EX.Subject, EX.predicate2, EX.Object2}) assert graph_includes_statement?(g, {EX.Subject, EX.predicate2, EX.Object2})
g = Graph.new(EX.GraphName, EX.Subject, EX.predicate, [EX.Object1, EX.Object2]) g = Graph.new(EX.GraphName, EX.Subject, EX.predicate, [EX.Object1, EX.Object2])
assert named_graph?(g, uri(EX.GraphName)) assert named_graph?(g, iri(EX.GraphName))
assert graph_includes_statement?(g, {EX.Subject, EX.predicate, EX.Object1}) assert graph_includes_statement?(g, {EX.Subject, EX.predicate, EX.Object1})
assert graph_includes_statement?(g, {EX.Subject, EX.predicate, EX.Object2}) assert graph_includes_statement?(g, {EX.Subject, EX.predicate, EX.Object2})
end end
test "creating a named graph with an initial description" do test "creating a named graph with an initial description" do
g = Graph.new(EX.GraphName, Description.new({EX.Subject, EX.predicate, EX.Object})) g = Graph.new(EX.GraphName, Description.new({EX.Subject, EX.predicate, EX.Object}))
assert named_graph?(g, uri(EX.GraphName)) assert named_graph?(g, iri(EX.GraphName))
assert graph_includes_statement?(g, {EX.Subject, EX.predicate, EX.Object}) assert graph_includes_statement?(g, {EX.Subject, EX.predicate, EX.Object})
end end
@ -85,11 +85,11 @@ defmodule RDF.GraphTest do
test "creating a named graph from another graph" do test "creating a named graph from another graph" do
g = Graph.new(EX.GraphName, Graph.new({EX.Subject, EX.predicate, EX.Object})) g = Graph.new(EX.GraphName, Graph.new({EX.Subject, EX.predicate, EX.Object}))
assert named_graph?(g, uri(EX.GraphName)) assert named_graph?(g, iri(EX.GraphName))
assert graph_includes_statement?(g, {EX.Subject, EX.predicate, EX.Object}) assert graph_includes_statement?(g, {EX.Subject, EX.predicate, EX.Object})
g = Graph.new(EX.GraphName, Graph.new(EX.OtherGraphName, {EX.Subject, EX.predicate, EX.Object})) g = Graph.new(EX.GraphName, Graph.new(EX.OtherGraphName, {EX.Subject, EX.predicate, EX.Object}))
assert named_graph?(g, uri(EX.GraphName)) assert named_graph?(g, iri(EX.GraphName))
assert graph_includes_statement?(g, {EX.Subject, EX.predicate, EX.Object}) assert graph_includes_statement?(g, {EX.Subject, EX.predicate, EX.Object})
end end
@ -106,9 +106,9 @@ defmodule RDF.GraphTest do
describe "add" do describe "add" do
test "a proper triple" do test "a proper triple" do
assert Graph.add(graph(), uri(EX.Subject), EX.predicate, uri(EX.Object)) assert Graph.add(graph(), iri(EX.Subject), EX.predicate, iri(EX.Object))
|> graph_includes_statement?({EX.Subject, EX.predicate, EX.Object}) |> graph_includes_statement?({EX.Subject, EX.predicate, EX.Object})
assert Graph.add(graph(), {uri(EX.Subject), EX.predicate, uri(EX.Object)}) assert Graph.add(graph(), {iri(EX.Subject), EX.predicate, iri(EX.Object)})
|> graph_includes_statement?({EX.Subject, EX.predicate, EX.Object}) |> graph_includes_statement?({EX.Subject, EX.predicate, EX.Object})
end end
@ -190,10 +190,10 @@ defmodule RDF.GraphTest do
end end
test "non-coercible Triple elements are causing an error" do test "non-coercible Triple elements are causing an error" do
assert_raise RDF.InvalidURIError, fn -> assert_raise RDF.IRI.InvalidError, fn ->
Graph.add(graph(), {"not a URI", EX.predicate, uri(EX.Object)}) Graph.add(graph(), {"not a IRI", EX.predicate, iri(EX.Object)})
end end
assert_raise RDF.InvalidLiteralError, fn -> assert_raise RDF.Literal.InvalidError, fn ->
Graph.add(graph(), {EX.Subject, EX.prop, self()}) Graph.add(graph(), {EX.Subject, EX.prop, self()})
end end
end end
@ -347,19 +347,19 @@ defmodule RDF.GraphTest do
assert Graph.pop(Graph.new) == {nil, Graph.new} assert Graph.pop(Graph.new) == {nil, Graph.new}
{triple, graph} = Graph.new({EX.S, EX.p, EX.O}) |> Graph.pop {triple, graph} = Graph.new({EX.S, EX.p, EX.O}) |> Graph.pop
assert {uri(EX.S), uri(EX.p), uri(EX.O)} == triple assert {iri(EX.S), iri(EX.p), iri(EX.O)} == triple
assert Enum.count(graph.descriptions) == 0 assert Enum.count(graph.descriptions) == 0
{{subject, predicate, _}, graph} = {{subject, predicate, _}, graph} =
Graph.new([{EX.S, EX.p, EX.O1}, {EX.S, EX.p, EX.O2}]) Graph.new([{EX.S, EX.p, EX.O1}, {EX.S, EX.p, EX.O2}])
|> Graph.pop |> Graph.pop
assert {subject, predicate} == {uri(EX.S), uri(EX.p)} assert {subject, predicate} == {iri(EX.S), iri(EX.p)}
assert Enum.count(graph.descriptions) == 1 assert Enum.count(graph.descriptions) == 1
{{subject, _, _}, graph} = {{subject, _, _}, graph} =
Graph.new([{EX.S, EX.p1, EX.O1}, {EX.S, EX.p2, EX.O2}]) Graph.new([{EX.S, EX.p1, EX.O1}, {EX.S, EX.p2, EX.O2}])
|> Graph.pop |> Graph.pop
assert subject == uri(EX.S) assert subject == iri(EX.S)
assert Enum.count(graph.descriptions) == 1 assert Enum.count(graph.descriptions) == 1
end end
@ -378,7 +378,7 @@ defmodule RDF.GraphTest do
end end
test "Enum.member?" do test "Enum.member?" do
refute Enum.member?(Graph.new, {uri(EX.S), EX.p, uri(EX.O)}) refute Enum.member?(Graph.new, {iri(EX.S), EX.p, iri(EX.O)})
assert Enum.member?(Graph.new({EX.S, EX.p, EX.O}), {EX.S, EX.p, EX.O}) assert Enum.member?(Graph.new({EX.S, EX.p, EX.O}), {EX.S, EX.p, EX.O})
g = Graph.add(graph(), [ g = Graph.add(graph(), [

273
test/unit/iri_test.exs Normal file
View file

@ -0,0 +1,273 @@
defmodule RDF.IRITest do
use RDF.Test.Case
use RDF.Vocabulary.Namespace
defvocab EX,
base_iri: "http://example.com/#",
terms: [], strict: false
doctest RDF.IRI
alias RDF.IRI
@absolute_iris [
"http://www.example.com/foo/",
%IRI{value: "http://www.example.com/foo/"},
URI.parse("http://www.example.com/foo/"),
"http://www.example.com/foo#",
%IRI{value: "http://www.example.com/foo#"},
URI.parse("http://www.example.com/foo#") |> IRI.empty_fragment_shim("#"),
"https://en.wiktionary.org/wiki/Ῥόδος",
%IRI{value: "https://en.wiktionary.org/wiki/Ῥόδος"},
URI.parse("https://en.wiktionary.org/wiki/Ῥόδος"),
]
@relative_iris [
"/relative/",
%IRI{value: "/relative/"},
URI.parse("/relative/"),
"/Ῥόδος/",
%IRI{value: "/Ῥόδος/"},
URI.parse("/Ῥόδος/"),
]
def absolute_iris, do: @absolute_iris
def relative_iris, do: @relative_iris
def valid_iris, do: @absolute_iris
def invalid_iris, do: nil # TODO:
describe "new/1" do
test "with a string" do
assert IRI.new("http://example.com/") == %IRI{value: "http://example.com/"}
end
test "with a RDF.IRI" do
assert IRI.new(IRI.new("http://example.com/")) == %IRI{value: "http://example.com/"}
end
test "with a URI" do
assert IRI.new(URI.parse("http://example.com/")) == %IRI{value: "http://example.com/"}
end
test "with a resolvable atom" do
assert IRI.new(EX.Foo) == %IRI{value: "http://example.com/#Foo"}
end
end
describe "new!/1" do
test "with valid iris" do
Enum.each(valid_iris(), fn valid_iri ->
assert IRI.new!(valid_iri) == IRI.new(valid_iri)
end)
end
test "with a resolvable atom" do
assert IRI.new!(EX.Foo) == %IRI{value: "http://example.com/#Foo"}
end
test "with relative iris" do
Enum.each(relative_iris(), fn relative_iri ->
assert_raise RDF.IRI.InvalidError, fn ->
IRI.new!(relative_iri)
end
end)
end
@tag skip: "TODO: proper validation"
test "with invalid iris" do
Enum.each(invalid_iris(), fn invalid_iri ->
assert_raise RDF.IRI.InvalidError, fn ->
IRI.new!(invalid_iri)
end
end)
end
end
describe "valid!/1" do
test "with valid iris" do
Enum.each(valid_iris(), fn valid_iri ->
assert IRI.valid!(valid_iri) == valid_iri
end)
end
test "with a resolvable atom" do
assert IRI.valid!(EX.Foo) == EX.Foo
end
test "with relative iris" do
Enum.each(relative_iris(), fn relative_iri ->
assert_raise RDF.IRI.InvalidError, fn ->
IRI.valid!(relative_iri)
end
end)
end
@tag skip: "TODO: proper validation"
test "with invalid iris" do
Enum.each(invalid_iris(), fn invalid_iri ->
assert_raise RDF.IRI.InvalidError, fn ->
IRI.valid!(invalid_iri)
end
end)
end
end
describe "valid?/1" do
test "with valid iris" do
Enum.each(valid_iris(), fn valid_iri ->
assert IRI.valid?(valid_iri) == true
end)
end
test "with a resolvable atom" do
assert IRI.valid?(EX.Foo) == true
end
test "with relative iris" do
Enum.each(relative_iris(), fn relative_iri ->
assert IRI.valid?(relative_iri) == false
end)
end
@tag skip: "TODO: proper validation"
test "with invalid iris" do
Enum.each(relative_iris(), fn relative_iri ->
assert IRI.valid?(relative_iri) == false
end)
end
end
describe "absolute?/1" do
test "with absolute iris" do
Enum.each(absolute_iris(), fn absolute_iri ->
assert IRI.absolute?(absolute_iri) == true
end)
end
test "with a resolvable atom" do
assert IRI.absolute?(EX.Foo) == true
end
test "with relative iris" do
Enum.each(relative_iris(), fn relative_iri ->
assert IRI.absolute?(relative_iri) == false
end)
end
@tag skip: "TODO: proper validation"
test "with invalid iris" do
Enum.each(invalid_iris(), fn relative_iri ->
assert IRI.absolute?(relative_iri) == false
end)
end
end
describe "absolute/2" do
test "with an already absolute iri" do
for absolute_iri <- absolute_iris(),
base_iri <- absolute_iris() ++ relative_iris() do
assert IRI.absolute(absolute_iri, base_iri) == IRI.new(absolute_iri)
end
end
test "with a relative iri" do
for relative_iri <- relative_iris(), base_iri <- absolute_iris() do
assert IRI.absolute(relative_iri, base_iri) ==
IRI.merge(base_iri, relative_iri)
end
end
end
describe "merge/2" do
test "with a valid absolute base iri and a valid relative iri" do
for base_iri <- absolute_iris(), relative_iri <- relative_iris() do
assert IRI.merge(base_iri, relative_iri) == (
base_iri
|> to_string
|> URI.merge(to_string(relative_iri))
|> IRI.empty_fragment_shim(relative_iri)
|> IRI.new
)
end
end
test "with a valid absolute base iri and a valid absolute iri" do
for base_iri <- absolute_iris(), absolute_iri <- absolute_iris() do
assert IRI.merge(base_iri, absolute_iri) == (
base_iri
|> to_string
|> URI.merge(to_string(absolute_iri))
|> IRI.empty_fragment_shim(absolute_iri)
|> IRI.new
)
end
end
test "with a relative base iri" do
for base_iri <- relative_iris(), iri <- absolute_iris() ++ relative_iris() do
assert_raise ArgumentError, fn ->
IRI.merge(base_iri, iri)
end
end
end
test "with empty fragments" do
assert IRI.merge("http://example.com/","foo#") == IRI.new("http://example.com/foo#")
end
@tag skip: "TODO: proper validation"
test "with invalid iris" do
Enum.each(invalid_iris(), fn invalid_iri ->
refute IRI.merge(invalid_iri, "foo")
end)
end
end
describe "parse/1" do
test "with absolute and relative iris" do
Enum.each(absolute_iris() ++ relative_iris(), fn iri ->
assert IRI.parse(iri) == (
iri
|> IRI.new
|> to_string()
|> URI.parse
|> IRI.empty_fragment_shim(iri)
)
end)
end
test "with a resolvable atom" do
assert IRI.parse(EX.Foo) == (EX.Foo |> IRI.new |> IRI.parse)
end
test "with empty fragments" do
assert IRI.parse("http://example.com/foo#") |> to_string == "http://example.com/foo#"
end
@tag skip: "TODO: proper validation"
test "with invalid iris" do
Enum.each(invalid_iris(), fn invalid_iri ->
refute IRI.parse(invalid_iri)
end)
end
end
test "to_string/1" do
assert to_string(IRI.new("http://example.com/")) == "http://example.com/"
end
test "inspect/1" do
assert inspect(IRI.new("http://example.com/")) == "~I<http://example.com/>"
end
end

View file

@ -5,12 +5,12 @@ defmodule RDF.ListTest do
import RDF.Sigils import RDF.Sigils
alias RDF.{BlankNode, Literal, Graph} alias RDF.{IRI, BlankNode, Literal, Graph}
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab EX, defvocab EX,
base_uri: "http://example.org/#", base_iri: "http://example.org/#",
terms: [], strict: false terms: [], strict: false
setup do setup do
@ -49,7 +49,7 @@ defmodule RDF.ListTest do
|> RDF.first(1) |> RDF.first(1)
|> RDF.rest(RDF.nil)) |> RDF.rest(RDF.nil))
assert %RDF.List{} = list = RDF.List.new(EX.Foo, graph) assert %RDF.List{} = list = RDF.List.new(EX.Foo, graph)
assert list.head == RDF.uri(EX.Foo) assert list.head == iri(EX.Foo)
end end
test "with other properties on its nodes" do test "with other properties on its nodes" do
@ -165,7 +165,7 @@ defmodule RDF.ListTest do
end end
%{ %{
"URI" => RDF.uri(EX.Foo), "IRI" => iri(EX.Foo),
"blank node" => ~B<Foo>, "blank node" => ~B<Foo>,
"literal" => ~L<Foo>, "literal" => ~L<Foo>,
"string" => "Foo", "string" => "Foo",
@ -219,7 +219,7 @@ defmodule RDF.ListTest do
assert RDF.nil == assert RDF.nil ==
Enum.reduce list, bnode, fn element, list_node -> Enum.reduce list, bnode, fn element, list_node ->
case element do case element do
%URI{} -> %IRI{} ->
assert get_in(graph_with_list, [list_node, RDF.first]) == [element] assert get_in(graph_with_list, [list_node, RDF.first]) == [element]
%BlankNode{} -> %BlankNode{} ->
assert get_in(graph_with_list, [list_node, RDF.first]) == [element] assert get_in(graph_with_list, [list_node, RDF.first]) == [element]
@ -228,7 +228,7 @@ defmodule RDF.ListTest do
element when is_boolean(element) -> element when is_boolean(element) ->
assert get_in(graph_with_list, [list_node, RDF.first]) == [RDF.Literal.new(element)] assert get_in(graph_with_list, [list_node, RDF.first]) == [RDF.Literal.new(element)]
element when is_atom(element) -> element when is_atom(element) ->
assert get_in(graph_with_list, [list_node, RDF.first]) == [RDF.uri(element)] assert get_in(graph_with_list, [list_node, RDF.first]) == [RDF.iri(element)]
_ -> _ ->
assert get_in(graph_with_list, [list_node, RDF.first]) == [RDF.Literal.new(element)] assert get_in(graph_with_list, [list_node, RDF.first]) == [RDF.Literal.new(element)]
end end
@ -247,7 +247,7 @@ defmodule RDF.ListTest do
end end
test "head option with unresolved namespace-qualified name" do test "head option with unresolved namespace-qualified name" do
assert RDF.List.from([42], head: EX.Foo).head == RDF.uri(EX.Foo) assert RDF.List.from([42], head: EX.Foo).head == iri(EX.Foo)
end end
end end

View file

@ -11,11 +11,11 @@ defmodule RDF.NQuads.DecoderTest do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab EX, defvocab EX,
base_uri: "http://example.org/#", base_iri: "http://example.org/#",
terms: [], strict: false terms: [], strict: false
defvocab P, defvocab P,
base_uri: "http://www.perceive.net/schemas/relationship/", base_iri: "http://www.perceive.net/schemas/relationship/",
terms: [], strict: false terms: [], strict: false
@ -78,7 +78,7 @@ defmodule RDF.NQuads.DecoderTest do
]) ])
end end
test "decoding a single statement with uris" do test "decoding a single statement with iris" do
assert RDF.NQuads.Decoder.decode!(""" assert RDF.NQuads.Decoder.decode!("""
<http://example.org/#spiderman> <http://www.perceive.net/schemas/relationship/enemyOf> <http://example.org/#green_goblin> . <http://example.org/#spiderman> <http://www.perceive.net/schemas/relationship/enemyOf> <http://example.org/#green_goblin> .
""") == Dataset.new({EX.spiderman, P.enemyOf, EX.green_goblin}) """) == Dataset.new({EX.spiderman, P.enemyOf, EX.green_goblin})

View file

@ -13,7 +13,7 @@ defmodule RDF.NQuads.EncoderTest do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab EX, defvocab EX,
base_uri: "http://example.org/#", base_iri: "http://example.org/#",
terms: [], strict: false terms: [], strict: false
@ -22,7 +22,7 @@ defmodule RDF.NQuads.EncoderTest do
assert NQuads.Encoder.encode!(Graph.new) == "" assert NQuads.Encoder.encode!(Graph.new) == ""
end end
test "statements with URIs only" do test "statements with IRIs only" do
assert NQuads.Encoder.encode!(Graph.new [ assert NQuads.Encoder.encode!(Graph.new [
{EX.S1, EX.p1, EX.O1}, {EX.S1, EX.p1, EX.O1},
{EX.S1, EX.p1, EX.O2}, {EX.S1, EX.p1, EX.O2},
@ -71,7 +71,7 @@ defmodule RDF.NQuads.EncoderTest do
assert NQuads.Encoder.encode!(Dataset.new) == "" assert NQuads.Encoder.encode!(Dataset.new) == ""
end end
test "statements with URIs only" do test "statements with IRIs only" do
assert NQuads.Encoder.encode!(Dataset.new [ assert NQuads.Encoder.encode!(Dataset.new [
{EX.S1, EX.p1, EX.O1, EX.G}, {EX.S1, EX.p1, EX.O1, EX.G},
{EX.S1, EX.p1, EX.O2, EX.G}, {EX.S1, EX.p1, EX.O2, EX.G},

View file

@ -9,11 +9,11 @@ defmodule RDF.NTriples.DecoderTest do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab EX, defvocab EX,
base_uri: "http://example.org/#", base_iri: "http://example.org/#",
terms: [], strict: false terms: [], strict: false
defvocab P, defvocab P,
base_uri: "http://www.perceive.net/schemas/relationship/", base_iri: "http://www.perceive.net/schemas/relationship/",
terms: [], strict: false terms: [], strict: false
@ -76,7 +76,7 @@ defmodule RDF.NTriples.DecoderTest do
]) ])
end end
test "decoding a single triple with uris" do test "decoding a single triple with iris" do
assert RDF.NTriples.Decoder.decode!(""" assert RDF.NTriples.Decoder.decode!("""
<http://example.org/#spiderman> <http://www.perceive.net/schemas/relationship/enemyOf> <http://example.org/#green_goblin> . <http://example.org/#spiderman> <http://www.perceive.net/schemas/relationship/enemyOf> <http://example.org/#green_goblin> .
""") == Graph.new({EX.spiderman, P.enemyOf, EX.green_goblin}) """) == Graph.new({EX.spiderman, P.enemyOf, EX.green_goblin})

View file

@ -13,7 +13,7 @@ defmodule RDF.NTriples.EncoderTest do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab EX, defvocab EX,
base_uri: "http://example.org/#", base_iri: "http://example.org/#",
terms: [], strict: false terms: [], strict: false
@ -22,7 +22,7 @@ defmodule RDF.NTriples.EncoderTest do
assert NTriples.Encoder.encode!(Graph.new) == "" assert NTriples.Encoder.encode!(Graph.new) == ""
end end
test "statements with URIs only" do test "statements with IRIs only" do
assert NTriples.Encoder.encode!(Graph.new [ assert NTriples.Encoder.encode!(Graph.new [
{EX.S1, EX.p1, EX.O1}, {EX.S1, EX.p1, EX.O1},
{EX.S1, EX.p1, EX.O2}, {EX.S1, EX.p1, EX.O2},

View file

@ -6,8 +6,8 @@ defmodule RDF.SigilsTest do
doctest RDF.Sigils doctest RDF.Sigils
describe "IRI sigil without interpolation" do describe "IRI sigil without interpolation" do
test "creating an URI" do test "creating an IRI" do
assert ~I<http://example.com> == RDF.uri("http://example.com") assert ~I<http://example.com> == RDF.iri("http://example.com")
end end
end end

View file

@ -12,11 +12,11 @@ defmodule RDF.Turtle.DecoderTest do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab EX, defvocab EX,
base_uri: "http://example.org/#", base_iri: "http://example.org/#",
terms: [], strict: false terms: [], strict: false
defvocab P, defvocab P,
base_uri: "http://www.perceive.net/schemas/relationship/", base_iri: "http://www.perceive.net/schemas/relationship/",
terms: [], strict: false terms: [], strict: false
@ -393,7 +393,7 @@ defmodule RDF.Turtle.DecoderTest do
<#Aaron> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <#Person> . <#Aaron> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <#Person> .
""") """)
end end
assert_raise RDF.InvalidURIError, fn -> assert_raise RuntimeError, fn ->
Turtle.Decoder.decode!( Turtle.Decoder.decode!(
"<#Aaron> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <#Person> .", "<#Aaron> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <#Person> .",
base: "foo") base: "foo")

View file

@ -13,7 +13,7 @@ defmodule RDF.Turtle.EncoderTest do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab EX, defvocab EX,
base_uri: "http://example.org/#", base_iri: "http://example.org/#",
terms: [], strict: false terms: [], strict: false
@ -22,7 +22,7 @@ defmodule RDF.Turtle.EncoderTest do
assert Turtle.Encoder.encode!(Graph.new) == "" assert Turtle.Encoder.encode!(Graph.new) == ""
end end
test "statements with URIs only" do test "statements with IRIs only" do
assert Turtle.Encoder.encode!(Graph.new [ assert Turtle.Encoder.encode!(Graph.new [
{EX.S1, EX.p1, EX.O1}, {EX.S1, EX.p1, EX.O1},
{EX.S1, EX.p1, EX.O2}, {EX.S1, EX.p1, EX.O2},
@ -46,11 +46,11 @@ defmodule RDF.Turtle.EncoderTest do
{EX.S1, EX.p2, EX.O3}, {EX.S1, EX.p2, EX.O3},
{EX.S2, EX.p3, EX.O4}, {EX.S2, EX.p3, EX.O4},
]), prefixes: %{ ]), prefixes: %{
ex: EX.__base_uri__, ex: EX. __base_iri__,
xsd: XSD.__base_uri__ xsd: XSD. __base_iri__
}) == }) ==
""" """
@prefix ex: <#{to_string(EX.__base_uri__)}> . @prefix ex: <#{to_string(EX. __base_iri__)}> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
ex:S1 ex:S1
@ -64,9 +64,9 @@ defmodule RDF.Turtle.EncoderTest do
test "statements with empty prefixed names" do test "statements with empty prefixed names" do
assert Turtle.Encoder.encode!(Graph.new({EX.S, EX.p, EX.O}), assert Turtle.Encoder.encode!(Graph.new({EX.S, EX.p, EX.O}),
prefixes: %{"" => EX.__base_uri__}) == prefixes: %{"" => EX. __base_iri__}) ==
""" """
@prefix : <#{to_string(EX.__base_uri__)}> . @prefix : <#{to_string(EX. __base_iri__)}> .
:S :S
:p :O . :p :O .
@ -104,22 +104,22 @@ defmodule RDF.Turtle.EncoderTest do
test "ordering of descriptions" do test "ordering of descriptions" do
assert Turtle.Encoder.encode!(Graph.new([ assert Turtle.Encoder.encode!(Graph.new([
{EX.__base_uri__, RDF.type, OWL.Ontology}, {EX. __base_iri__, RDF.type, OWL.Ontology},
{EX.S1, RDF.type, EX.O}, {EX.S1, RDF.type, EX.O},
{EX.S2, RDF.type, RDFS.Class}, {EX.S2, RDF.type, RDFS.Class},
{EX.S3, RDF.type, RDF.Property}, {EX.S3, RDF.type, RDF.Property},
]), ]),
base: EX.__base_uri__, base: EX. __base_iri__,
prefixes: %{ prefixes: %{
rdf: RDF.__base_uri__, rdf: RDF. __base_iri__,
rdfs: RDFS.__base_uri__, rdfs: RDFS. __base_iri__,
owl: OWL.__base_uri__, owl: OWL. __base_iri__,
}) == }) ==
""" """
@base <#{to_string(EX.__base_uri__)}> . @base <#{to_string(EX. __base_iri__)}> .
@prefix rdf: <#{to_string(RDF.__base_uri__)}> . @prefix rdf: <#{to_string(RDF. __base_iri__)}> .
@prefix rdfs: <#{to_string(RDFS.__base_uri__)}> . @prefix rdfs: <#{to_string(RDFS. __base_iri__)}> .
@prefix owl: <#{to_string(OWL.__base_uri__)}> . @prefix owl: <#{to_string(OWL. __base_iri__)}> .
<> <>
a owl:Ontology . a owl:Ontology .
@ -141,53 +141,53 @@ defmodule RDF.Turtle.EncoderTest do
setup do setup do
{:ok, {:ok,
prefixes: %{ prefixes: %{
RDF.uri(EX.__base_uri__) => "ex", RDF.iri(EX. __base_iri__) => "ex",
~I<http://example.org/> => "ex2" ~I<http://example.org/> => "ex2"
} }
} }
end end
test "hash uri with existing prefix", %{prefixes: prefixes} do test "hash iri with existing prefix", %{prefixes: prefixes} do
assert Turtle.Encoder.prefixed_name(EX.foo, prefixes) == assert Turtle.Encoder.prefixed_name(EX.foo, prefixes) ==
"ex:foo" "ex:foo"
end end
test "hash uri namespace without name", %{prefixes: prefixes} do test "hash iri namespace without name", %{prefixes: prefixes} do
assert Turtle.Encoder.prefixed_name(RDF.uri(EX.__base_uri__), prefixes) == assert Turtle.Encoder.prefixed_name(RDF.iri(EX. __base_iri__), prefixes) ==
"ex:" "ex:"
end end
test "hash uri with non-existing prefix" do test "hash iri with non-existing prefix" do
refute Turtle.Encoder.prefixed_name(EX.foo, %{}) refute Turtle.Encoder.prefixed_name(EX.foo, %{})
end end
test "slash uri with existing prefix", %{prefixes: prefixes} do test "slash iri with existing prefix", %{prefixes: prefixes} do
assert Turtle.Encoder.prefixed_name(~I<http://example.org/foo>, prefixes) == assert Turtle.Encoder.prefixed_name(~I<http://example.org/foo>, prefixes) ==
"ex2:foo" "ex2:foo"
end end
test "slash uri namespace without name", %{prefixes: prefixes} do test "slash iri namespace without name", %{prefixes: prefixes} do
assert Turtle.Encoder.prefixed_name(~I<http://example.org/>, prefixes) == assert Turtle.Encoder.prefixed_name(~I<http://example.org/>, prefixes) ==
"ex2:" "ex2:"
end end
test "slash uri with non-existing prefix" do test "slash iri with non-existing prefix" do
refute Turtle.Encoder.prefixed_name(~I<http://example.org/foo>, %{}) refute Turtle.Encoder.prefixed_name(~I<http://example.org/foo>, %{})
end end
end end
%{ %{
"full URIs without base" => %{ "full IRIs without base" => %{
input: "<http://a/b> <http://a/c> <http://a/d> .", input: "<http://a/b> <http://a/c> <http://a/d> .",
matches: [~r(<http://a/b>\s+<http://a/c>\s+<http://a/d>\s+\.)], matches: [~r(<http://a/b>\s+<http://a/c>\s+<http://a/d>\s+\.)],
}, },
"relative URIs with base" => %{ "relative IRIs with base" => %{
input: "<http://a/b> <http://a/c> <http://a/d> .", input: "<http://a/b> <http://a/c> <http://a/d> .",
matches: [ ~r(@base\s+<http://a/>\s+\.), ~r(<b>\s+<c>\s+<d>\s+\.)m], matches: [ ~r(@base\s+<http://a/>\s+\.), ~r(<b>\s+<c>\s+<d>\s+\.)m],
base: "http://a/" base: "http://a/"
}, },
"pname URIs with prefix" => %{ "pname IRIs with prefix" => %{
input: "<http://example.com/b> <http://example.com/c> <http://example.com/d> .", input: "<http://example.com/b> <http://example.com/c> <http://example.com/d> .",
matches: [ matches: [
~r(@prefix\s+ex:\s+<http://example.com/>\s+\.), ~r(@prefix\s+ex:\s+<http://example.com/>\s+\.),
@ -195,7 +195,7 @@ defmodule RDF.Turtle.EncoderTest do
], ],
prefixes: %{ex: "http://example.com/"} prefixes: %{ex: "http://example.com/"}
}, },
"pname URIs with empty prefix" => %{ "pname IRIs with empty prefix" => %{
input: "<http://example.com/b> <http://example.com/c> <http://example.com/d> .", input: "<http://example.com/b> <http://example.com/c> <http://example.com/d> .",
matches: [ matches: [
~r(@prefix\s+:\s+<http://example.com/>\s+\.), ~r(@prefix\s+:\s+<http://example.com/>\s+\.),
@ -396,9 +396,9 @@ defmodule RDF.Turtle.EncoderTest do
# |> assert_serialization( # |> assert_serialization(
# prefixes: %{ # prefixes: %{
# ex: ~I<http://example.com/>, # ex: ~I<http://example.com/>,
# rdf: RDF.NS.RDF.__base_uri__, # rdf: RDF.NS.RDF. __base_iri__,
# rdfs: RDFS.__base_uri__, # rdfs: RDFS. __base_iri__,
# owl: OWL.__base_uri__, # owl: OWL. __base_iri__,
# }, # },
# matches: [ # matches: [
# {~r[ex:a\s+rdfs:domain \[\s+a owl:Class;\s+owl:unionOf\s+\(ex:b\s+ex:c\)\s*\]\s*\.], # {~r[ex:a\s+rdfs:domain \[\s+a owl:Class;\s+owl:unionOf\s+\(ex:b\s+ex:c\)\s*\]\s*\.],
@ -419,7 +419,7 @@ defmodule RDF.Turtle.EncoderTest do
|> RDF.rest(RDF.nil)) |> RDF.rest(RDF.nil))
|> Graph.add({EX.Baz, EX.quux, ~B<Bar>}) |> Graph.add({EX.Baz, EX.quux, ~B<Bar>})
|> assert_serialization( |> assert_serialization(
prefixes: %{ex: EX.__base_uri__}, prefixes: %{ex: EX. __base_iri__},
# TODO: provide a positive match # TODO: provide a positive match
neg_matches: [ neg_matches: [
{~r[\(\s*ex:Foo\s+ex:Bar\s*\)], "does include the list as a Turtle list"} {~r[\(\s*ex:Foo\s+ex:Bar\s*\)], "does include the list as a Turtle list"}
@ -491,7 +491,7 @@ defmodule RDF.Turtle.EncoderTest do
~r[@prefix xsd: <http://www.w3.org/2001/XMLSchema#> \.], ~r[@prefix xsd: <http://www.w3.org/2001/XMLSchema#> \.],
~r["http://foo/"\^\^xsd:anyURI \.] ~r["http://foo/"\^\^xsd:anyURI \.]
], ],
prefixes: %{xsd: XSD.__base_uri__} prefixes: %{xsd: XSD. __base_iri__}
) )
end end

View file

@ -12,50 +12,50 @@ defmodule RDF.Vocabulary.NamespaceTest do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab EX, defvocab EX,
base_uri: "http://example.com/", base_iri: "http://example.com/",
terms: ~w[], strict: false terms: ~w[], strict: false
defvocab EXS, defvocab EXS,
base_uri: "http://example.com/strict#", base_iri: "http://example.com/strict#",
terms: ~w[foo bar] terms: ~w[foo bar]
defvocab ExampleFromGraph, defvocab ExampleFromGraph,
base_uri: "http://example.com/from_graph#", base_iri: "http://example.com/from_graph#",
data: RDF.Graph.new([ data: RDF.Graph.new([
{~I<http://example.com/from_graph#foo>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property>}, {~I<http://example.com/from_graph#foo>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property>},
{~I<http://example.com/from_graph#Bar>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/2000/01/rdf-schema#Resource>} {~I<http://example.com/from_graph#Bar>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/2000/01/rdf-schema#Resource>}
]) ])
defvocab ExampleFromDataset, defvocab ExampleFromDataset,
base_uri: "http://example.com/from_dataset#", base_iri: "http://example.com/from_dataset#",
data: RDF.Dataset.new([ data: RDF.Dataset.new([
{~I<http://example.com/from_dataset#foo>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property>}, {~I<http://example.com/from_dataset#foo>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property>},
{~I<http://example.com/from_dataset#Bar>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/2000/01/rdf-schema#Resource>, ~I<http://example.com/from_dataset#Graph>} {~I<http://example.com/from_dataset#Bar>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/2000/01/rdf-schema#Resource>, ~I<http://example.com/from_dataset#Graph>}
]) ])
defvocab ExampleFromNTriplesFile, defvocab ExampleFromNTriplesFile,
base_uri: "http://example.com/from_ntriples/", base_iri: "http://example.com/from_ntriples/",
file: "test/data/vocab_ns_example.nt" file: "test/data/vocab_ns_example.nt"
defvocab ExampleFromNQuadsFile, defvocab ExampleFromNQuadsFile,
base_uri: "http://example.com/from_nquads/", base_iri: "http://example.com/from_nquads/",
file: "test/data/vocab_ns_example.nq" file: "test/data/vocab_ns_example.nq"
defvocab ExampleFromTurtleFile, defvocab ExampleFromTurtleFile,
base_uri: "http://example.com/from_turtle/", base_iri: "http://example.com/from_turtle/",
file: "test/data/vocab_ns_example.ttl" file: "test/data/vocab_ns_example.ttl"
defvocab StrictExampleFromTerms, defvocab StrictExampleFromTerms,
base_uri: "http://example.com/strict_from_terms#", base_iri: "http://example.com/strict_from_terms#",
terms: ~w[foo Bar] terms: ~w[foo Bar]
defvocab NonStrictExampleFromTerms, defvocab NonStrictExampleFromTerms,
base_uri: "http://example.com/non_strict_from_terms#", base_iri: "http://example.com/non_strict_from_terms#",
terms: ~w[foo Bar], terms: ~w[foo Bar],
strict: false strict: false
defvocab StrictExampleFromAliasedTerms, defvocab StrictExampleFromAliasedTerms,
base_uri: "http://example.com/strict_from_aliased_terms#", base_iri: "http://example.com/strict_from_aliased_terms#",
terms: ~w[term1 Term2 Term-3 term-4], terms: ~w[term1 Term2 Term-3 term-4],
alias: [ alias: [
Term1: "term1", Term1: "term1",
@ -65,7 +65,7 @@ defmodule RDF.Vocabulary.NamespaceTest do
] ]
defvocab NonStrictExampleFromAliasedTerms, defvocab NonStrictExampleFromAliasedTerms,
base_uri: "http://example.com/non_strict_from_aliased_terms#", base_iri: "http://example.com/non_strict_from_aliased_terms#",
terms: ~w[], terms: ~w[],
alias: [ alias: [
Term1: "term1", Term1: "term1",
@ -76,7 +76,7 @@ defmodule RDF.Vocabulary.NamespaceTest do
strict: false strict: false
defvocab ExampleWithSynonymAliases, defvocab ExampleWithSynonymAliases,
base_uri: "http://example.com/ex#", base_iri: "http://example.com/ex#",
terms: ~w[bar Bar], terms: ~w[bar Bar],
alias: [foo: "bar", baz: "bar", alias: [foo: "bar", baz: "bar",
Foo: "Bar", Baz: "Bar"] Foo: "Bar", Baz: "Bar"]
@ -84,10 +84,10 @@ defmodule RDF.Vocabulary.NamespaceTest do
end end
describe "defvocab with bad base uri" do describe "defvocab with bad base iri" do
test "without a base_uri, an error is raised" do test "without a base_iri, an error is raised" do
assert_raise KeyError, fn -> assert_raise KeyError, fn ->
defmodule NSWithoutBaseURI do defmodule NSWithoutBaseIRI do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab Example, terms: [] defvocab Example, terms: []
@ -95,34 +95,34 @@ defmodule RDF.Vocabulary.NamespaceTest do
end end
end end
test "when the base_uri doesn't end with '/' or '#', an error is raised" do test "when the base_iri doesn't end with '/' or '#', an error is raised" do
assert_raise RDF.Namespace.InvalidVocabBaseURIError, fn -> assert_raise RDF.Namespace.InvalidVocabBaseIRIError, fn ->
defmodule NSWithInvalidBaseURI1 do defmodule NSWithInvalidBaseIRI1 do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab Example, defvocab Example,
base_uri: "http://example.com/base_uri4", base_iri: "http://example.com/base_iri4",
terms: [] terms: []
end end
end end
end end
test "when the base_uri isn't a valid URI, an error is raised" do test "when the base_iri isn't a valid IRI, an error is raised" do
assert_raise RDF.Namespace.InvalidVocabBaseURIError, fn -> assert_raise RDF.Namespace.InvalidVocabBaseIRIError, fn ->
defmodule NSWithInvalidBaseURI2 do defmodule NSWithInvalidBaseIRI2 do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab Example, defvocab Example,
base_uri: "invalid", base_iri: "invalid",
terms: [] terms: []
end end
end end
assert_raise RDF.Namespace.InvalidVocabBaseURIError, fn -> assert_raise RDF.Namespace.InvalidVocabBaseIRIError, fn ->
defmodule NSWithInvalidBaseURI3 do defmodule NSWithInvalidBaseIRI3 do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab Example, defvocab Example,
base_uri: :foo, base_iri: :foo,
terms: [] terms: []
end end
end end
@ -137,7 +137,7 @@ defmodule RDF.Vocabulary.NamespaceTest do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab Example, defvocab Example,
base_uri: "http://example.com/ex#", base_iri: "http://example.com/ex#",
file: "something.nt" file: "something.nt"
end end
end end
@ -152,7 +152,7 @@ defmodule RDF.Vocabulary.NamespaceTest do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab Example, defvocab Example,
base_uri: "http://example.com/ex#", base_iri: "http://example.com/ex#",
terms: ~w[foo], terms: ~w[foo],
alias: ["foo-bar": "foo"] alias: ["foo-bar": "foo"]
end end
@ -165,7 +165,7 @@ defmodule RDF.Vocabulary.NamespaceTest do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab Example, defvocab Example,
base_uri: "http://example.com/ex#", base_iri: "http://example.com/ex#",
terms: ~w[foo bar], terms: ~w[foo bar],
alias: [foo: "bar"] alias: [foo: "bar"]
end end
@ -178,7 +178,7 @@ defmodule RDF.Vocabulary.NamespaceTest do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab Example, defvocab Example,
base_uri: "http://example.com/ex#", base_iri: "http://example.com/ex#",
terms: ~w[], terms: ~w[],
alias: [foo: "bar"] alias: [foo: "bar"]
end end
@ -191,7 +191,7 @@ defmodule RDF.Vocabulary.NamespaceTest do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab Example, defvocab Example,
base_uri: "http://example.com/ex#", base_iri: "http://example.com/ex#",
terms: ~w[bar], terms: ~w[bar],
alias: [foo: "bar", baz: "foo"] alias: [foo: "bar", baz: "foo"]
end end
@ -205,7 +205,7 @@ defmodule RDF.Vocabulary.NamespaceTest do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab Example, defvocab Example,
base_uri: "http://example.com/ex#", base_iri: "http://example.com/ex#",
terms: ~w[ terms: ~w[
nil nil
true true
@ -281,7 +281,7 @@ defmodule RDF.Vocabulary.NamespaceTest do
defmodule NSWithElixirTerms do defmodule NSWithElixirTerms do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab Example, defvocab Example,
base_uri: "http://example.com/example#", base_iri: "http://example.com/example#",
terms: RDF.Vocabulary.Namespace.invalid_terms terms: RDF.Vocabulary.Namespace.invalid_terms
end end
end end
@ -292,7 +292,7 @@ defmodule RDF.Vocabulary.NamespaceTest do
defmodule NSWithElixirAliasTerms do defmodule NSWithElixirAliasTerms do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab Example, defvocab Example,
base_uri: "http://example.com/example#", base_iri: "http://example.com/example#",
terms: ~w[foo], terms: ~w[foo],
alias: [ alias: [
and: "foo", and: "foo",
@ -323,7 +323,7 @@ defmodule RDF.Vocabulary.NamespaceTest do
defmodule NSWithIgnoredElixirTerms do defmodule NSWithIgnoredElixirTerms do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab Example, defvocab Example,
base_uri: "http://example.com/example#", base_iri: "http://example.com/example#",
terms: RDF.Vocabulary.Namespace.invalid_terms, terms: RDF.Vocabulary.Namespace.invalid_terms,
ignore: RDF.Vocabulary.Namespace.invalid_terms ignore: RDF.Vocabulary.Namespace.invalid_terms
end end
@ -333,7 +333,7 @@ defmodule RDF.Vocabulary.NamespaceTest do
defmodule NSWithAliasesForElixirTerms do defmodule NSWithAliasesForElixirTerms do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab Example, defvocab Example,
base_uri: "http://example.com/example#", base_iri: "http://example.com/example#",
terms: RDF.Vocabulary.Namespace.invalid_terms, terms: RDF.Vocabulary.Namespace.invalid_terms,
alias: [ alias: [
and_: "and", and_: "and",
@ -387,7 +387,7 @@ defmodule RDF.Vocabulary.NamespaceTest do
defmodule NSWithInvalidTerms1 do defmodule NSWithInvalidTerms1 do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab Example, defvocab Example,
base_uri: "http://example.com/example#", base_iri: "http://example.com/example#",
terms: ~w[Foo-bar foo-bar] terms: ~w[Foo-bar foo-bar]
end end
end end
@ -397,7 +397,7 @@ defmodule RDF.Vocabulary.NamespaceTest do
defmodule NSWithInvalidTerms2 do defmodule NSWithInvalidTerms2 do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab Example, defvocab Example,
base_uri: "http://example.com/example#", base_iri: "http://example.com/example#",
terms: ~w[Foo-bar foo-bar], terms: ~w[Foo-bar foo-bar],
invalid_characters: :ignore invalid_characters: :ignore
end end
@ -411,7 +411,7 @@ defmodule RDF.Vocabulary.NamespaceTest do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab Example, defvocab Example,
base_uri: "http://example.com/ex#", base_iri: "http://example.com/ex#",
case_violations: :fail, case_violations: :fail,
data: RDF.Graph.new([ data: RDF.Graph.new([
{~I<http://example.com/ex#Foo>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property>}, {~I<http://example.com/ex#Foo>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property>},
@ -429,7 +429,7 @@ defmodule RDF.Vocabulary.NamespaceTest do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab Example, defvocab Example,
base_uri: "http://example.com/ex#", base_iri: "http://example.com/ex#",
case_violations: :ignore, case_violations: :ignore,
data: RDF.Graph.new([ data: RDF.Graph.new([
{~I<http://example.com/ex#Foo>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property>}, {~I<http://example.com/ex#Foo>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property>},
@ -448,7 +448,7 @@ defmodule RDF.Vocabulary.NamespaceTest do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab Example, defvocab Example,
base_uri: "http://example.com/ex#", base_iri: "http://example.com/ex#",
case_violations: :fail, case_violations: :fail,
data: RDF.Graph.new([ data: RDF.Graph.new([
{~I<http://example.com/ex#Foo>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property>}, {~I<http://example.com/ex#Foo>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property>},
@ -463,7 +463,7 @@ defmodule RDF.Vocabulary.NamespaceTest do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab Example, defvocab Example,
base_uri: "http://example.com/ex#", base_iri: "http://example.com/ex#",
case_violations: :fail, case_violations: :fail,
data: RDF.Graph.new([ data: RDF.Graph.new([
{~I<http://example.com/ex#bar>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/2000/01/rdf-schema#Resource>} {~I<http://example.com/ex#bar>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/2000/01/rdf-schema#Resource>}
@ -479,7 +479,7 @@ defmodule RDF.Vocabulary.NamespaceTest do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab Example, defvocab Example,
base_uri: "http://example.com/ex#", base_iri: "http://example.com/ex#",
case_violations: :fail, case_violations: :fail,
data: RDF.Graph.new([ data: RDF.Graph.new([
{~I<http://example.com/ex#foo>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property>}, {~I<http://example.com/ex#foo>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property>},
@ -495,7 +495,7 @@ defmodule RDF.Vocabulary.NamespaceTest do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab Example, defvocab Example,
base_uri: "http://example.com/ex#", base_iri: "http://example.com/ex#",
case_violations: :fail, case_violations: :fail,
data: RDF.Graph.new([ data: RDF.Graph.new([
{~I<http://example.com/ex#Bar>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/2000/01/rdf-schema#Resource>} {~I<http://example.com/ex#Bar>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/2000/01/rdf-schema#Resource>}
@ -510,7 +510,7 @@ defmodule RDF.Vocabulary.NamespaceTest do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab Example, defvocab Example,
base_uri: "http://example.com/ex#", base_iri: "http://example.com/ex#",
case_violations: :fail, case_violations: :fail,
data: RDF.Graph.new([ data: RDF.Graph.new([
{~I<http://example.com/ex#_Foo>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property>}, {~I<http://example.com/ex#_Foo>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property>},
@ -526,7 +526,7 @@ defmodule RDF.Vocabulary.NamespaceTest do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab ExampleIgnoredLowercasedTerm, defvocab ExampleIgnoredLowercasedTerm,
base_uri: "http://example.com/", base_iri: "http://example.com/",
data: RDF.Graph.new([ data: RDF.Graph.new([
{~I<http://example.com/foo>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property>}, {~I<http://example.com/foo>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property>},
{~I<http://example.com/Bar>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/2000/01/rdf-schema#Resource>} {~I<http://example.com/Bar>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/2000/01/rdf-schema#Resource>}
@ -534,7 +534,7 @@ defmodule RDF.Vocabulary.NamespaceTest do
ignore: ["foo"] ignore: ["foo"]
defvocab ExampleIgnoredCapitalizedTerm, defvocab ExampleIgnoredCapitalizedTerm,
base_uri: "http://example.com/", base_iri: "http://example.com/",
data: RDF.Dataset.new([ data: RDF.Dataset.new([
{~I<http://example.com/foo>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property>}, {~I<http://example.com/foo>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property>},
{~I<http://example.com/Bar>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/2000/01/rdf-schema#Resource>, ~I<http://example.com/from_dataset#Graph>} {~I<http://example.com/Bar>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/2000/01/rdf-schema#Resource>, ~I<http://example.com/from_dataset#Graph>}
@ -542,37 +542,37 @@ defmodule RDF.Vocabulary.NamespaceTest do
ignore: ~w[Bar] ignore: ~w[Bar]
defvocab ExampleIgnoredLowercasedTermWithAlias, defvocab ExampleIgnoredLowercasedTermWithAlias,
base_uri: "http://example.com/", base_iri: "http://example.com/",
terms: ~w[foo Bar], terms: ~w[foo Bar],
alias: [Foo: "foo"], alias: [Foo: "foo"],
ignore: ~w[foo]a ignore: ~w[foo]a
defvocab ExampleIgnoredCapitalizedTermWithAlias, defvocab ExampleIgnoredCapitalizedTermWithAlias,
base_uri: "http://example.com/", base_iri: "http://example.com/",
terms: ~w[foo Bar], terms: ~w[foo Bar],
alias: [bar: "Bar"], alias: [bar: "Bar"],
ignore: ~w[Bar]a ignore: ~w[Bar]a
defvocab ExampleIgnoredLowercasedAlias, defvocab ExampleIgnoredLowercasedAlias,
base_uri: "http://example.com/", base_iri: "http://example.com/",
terms: ~w[foo Bar], terms: ~w[foo Bar],
alias: [bar: "Bar"], alias: [bar: "Bar"],
ignore: ~w[bar]a ignore: ~w[bar]a
defvocab ExampleIgnoredCapitalizedAlias, defvocab ExampleIgnoredCapitalizedAlias,
base_uri: "http://example.com/", base_iri: "http://example.com/",
terms: ~w[foo Bar], terms: ~w[foo Bar],
alias: [Foo: "foo"], alias: [Foo: "foo"],
ignore: ~w[Foo]a ignore: ~w[Foo]a
defvocab ExampleIgnoredNonStrictLowercasedTerm, defvocab ExampleIgnoredNonStrictLowercasedTerm,
base_uri: "http://example.com/", base_iri: "http://example.com/",
terms: ~w[], terms: ~w[],
strict: false, strict: false,
ignore: ~w[foo]a ignore: ~w[foo]a
defvocab ExampleIgnoredNonStrictCapitalizedTerm, defvocab ExampleIgnoredNonStrictCapitalizedTerm,
base_uri: "http://example.com/", base_iri: "http://example.com/",
terms: ~w[], terms: ~w[],
strict: false, strict: false,
ignore: ~w[Bar]a ignore: ~w[Bar]a
@ -589,7 +589,7 @@ defmodule RDF.Vocabulary.NamespaceTest do
alias NSWithIgnoredTerms.ExampleIgnoredCapitalizedTerm alias NSWithIgnoredTerms.ExampleIgnoredCapitalizedTerm
assert ExampleIgnoredCapitalizedTerm.__terms__ == [:foo] assert ExampleIgnoredCapitalizedTerm.__terms__ == [:foo]
assert_raise RDF.Namespace.UndefinedTermError, fn -> assert_raise RDF.Namespace.UndefinedTermError, fn ->
RDF.uri(ExampleIgnoredCapitalizedTerm.Bar) RDF.iri(ExampleIgnoredCapitalizedTerm.Bar)
end end
end end
@ -597,33 +597,33 @@ defmodule RDF.Vocabulary.NamespaceTest do
alias NSWithIgnoredTerms.ExampleIgnoredLowercasedTermWithAlias alias NSWithIgnoredTerms.ExampleIgnoredLowercasedTermWithAlias
assert ExampleIgnoredLowercasedTermWithAlias.__terms__ == [:Bar, :Foo] assert ExampleIgnoredLowercasedTermWithAlias.__terms__ == [:Bar, :Foo]
assert_raise UndefinedFunctionError, fn -> ExampleIgnoredLowercasedTermWithAlias.foo end assert_raise UndefinedFunctionError, fn -> ExampleIgnoredLowercasedTermWithAlias.foo end
assert RDF.uri(ExampleIgnoredLowercasedTermWithAlias.Foo) == ~I<http://example.com/foo> assert RDF.iri(ExampleIgnoredLowercasedTermWithAlias.Foo) == ~I<http://example.com/foo>
end end
test "resolution of ignored capitalized term with alias on a strict vocab fails" do test "resolution of ignored capitalized term with alias on a strict vocab fails" do
alias NSWithIgnoredTerms.ExampleIgnoredCapitalizedTermWithAlias alias NSWithIgnoredTerms.ExampleIgnoredCapitalizedTermWithAlias
assert ExampleIgnoredCapitalizedTermWithAlias.__terms__ == [:bar, :foo] assert ExampleIgnoredCapitalizedTermWithAlias.__terms__ == [:bar, :foo]
assert_raise RDF.Namespace.UndefinedTermError, fn -> assert_raise RDF.Namespace.UndefinedTermError, fn ->
RDF.uri(ExampleIgnoredCapitalizedTermWithAlias.Bar) RDF.iri(ExampleIgnoredCapitalizedTermWithAlias.Bar)
end end
assert RDF.uri(ExampleIgnoredCapitalizedTermWithAlias.bar) == ~I<http://example.com/Bar> assert RDF.iri(ExampleIgnoredCapitalizedTermWithAlias.bar) == ~I<http://example.com/Bar>
end end
test "resolution of ignored lowercased alias on a strict vocab fails" do test "resolution of ignored lowercased alias on a strict vocab fails" do
alias NSWithIgnoredTerms.ExampleIgnoredLowercasedAlias alias NSWithIgnoredTerms.ExampleIgnoredLowercasedAlias
assert ExampleIgnoredLowercasedAlias.__terms__ == [:Bar, :foo] assert ExampleIgnoredLowercasedAlias.__terms__ == [:Bar, :foo]
assert RDF.uri(ExampleIgnoredLowercasedAlias.Bar) == ~I<http://example.com/Bar> assert RDF.iri(ExampleIgnoredLowercasedAlias.Bar) == ~I<http://example.com/Bar>
assert_raise UndefinedFunctionError, fn -> assert_raise UndefinedFunctionError, fn ->
RDF.uri(ExampleIgnoredLowercasedAlias.bar) RDF.iri(ExampleIgnoredLowercasedAlias.bar)
end end
end end
test "resolution of ignored capitalized alias on a strict vocab fails" do test "resolution of ignored capitalized alias on a strict vocab fails" do
alias NSWithIgnoredTerms.ExampleIgnoredCapitalizedAlias alias NSWithIgnoredTerms.ExampleIgnoredCapitalizedAlias
assert ExampleIgnoredCapitalizedAlias.__terms__ == [:Bar, :foo] assert ExampleIgnoredCapitalizedAlias.__terms__ == [:Bar, :foo]
assert RDF.uri(ExampleIgnoredCapitalizedAlias.foo) == ~I<http://example.com/foo> assert RDF.iri(ExampleIgnoredCapitalizedAlias.foo) == ~I<http://example.com/foo>
assert_raise RDF.Namespace.UndefinedTermError, fn -> assert_raise RDF.Namespace.UndefinedTermError, fn ->
RDF.uri(ExampleIgnoredCapitalizedAlias.Foo) RDF.iri(ExampleIgnoredCapitalizedAlias.Foo)
end end
end end
@ -637,7 +637,7 @@ defmodule RDF.Vocabulary.NamespaceTest do
test "resolution of ignored capitalized term on a non-strict vocab fails" do test "resolution of ignored capitalized term on a non-strict vocab fails" do
alias NSWithIgnoredTerms.ExampleIgnoredNonStrictCapitalizedTerm alias NSWithIgnoredTerms.ExampleIgnoredNonStrictCapitalizedTerm
assert_raise RDF.Namespace.UndefinedTermError, fn -> assert_raise RDF.Namespace.UndefinedTermError, fn ->
RDF.uri(ExampleIgnoredNonStrictCapitalizedTerm.Bar) RDF.iri(ExampleIgnoredNonStrictCapitalizedTerm.Bar)
end end
end end
@ -645,7 +645,7 @@ defmodule RDF.Vocabulary.NamespaceTest do
defmodule IgnoredTermWithInvalidCharacters do defmodule IgnoredTermWithInvalidCharacters do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab Example, defvocab Example,
base_uri: "http://example.com/", base_iri: "http://example.com/",
terms: ~w[foo-bar], terms: ~w[foo-bar],
ignore: ~w[foo-bar]a ignore: ~w[foo-bar]a
end end
@ -655,7 +655,7 @@ defmodule RDF.Vocabulary.NamespaceTest do
defmodule IgnoredTermWithCaseViolations do defmodule IgnoredTermWithCaseViolations do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab Example, defvocab Example,
base_uri: "http://example.com/", base_iri: "http://example.com/",
data: RDF.Dataset.new([ data: RDF.Dataset.new([
{~I<http://example.com/Foo>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property>}, {~I<http://example.com/Foo>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property>},
{~I<http://example.com/bar>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/2000/01/rdf-schema#Resource>, ~I<http://example.com/from_dataset#Graph>} {~I<http://example.com/bar>, ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ~I<http://www.w3.org/2000/01/rdf-schema#Resource>, ~I<http://example.com/from_dataset#Graph>}
@ -667,42 +667,42 @@ defmodule RDF.Vocabulary.NamespaceTest do
end end
test "__base_uri__ returns the base_uri" do test " __base_iri__ returns the base_iri" do
alias TestNS.ExampleFromGraph, as: HashVocab alias TestNS.ExampleFromGraph, as: HashVocab
alias TestNS.ExampleFromNTriplesFile, as: SlashVocab alias TestNS.ExampleFromNTriplesFile, as: SlashVocab
assert HashVocab.__base_uri__ == "http://example.com/from_graph#" assert HashVocab. __base_iri__ == "http://example.com/from_graph#"
assert SlashVocab.__base_uri__ == "http://example.com/from_ntriples/" assert SlashVocab. __base_iri__ == "http://example.com/from_ntriples/"
end end
test "__uris__ returns all URIs of the vocabulary" do test "__iris__ returns all IRIs of the vocabulary" do
alias TestNS.ExampleFromGraph, as: Example1 alias TestNS.ExampleFromGraph, as: Example1
assert length(Example1.__uris__) == 2 assert length(Example1.__iris__) == 2
assert RDF.uri(Example1.foo) in Example1.__uris__ assert RDF.iri(Example1.foo) in Example1.__iris__
assert RDF.uri(Example1.Bar) in Example1.__uris__ assert RDF.iri(Example1.Bar) in Example1.__iris__
alias TestNS.ExampleFromNTriplesFile, as: Example2 alias TestNS.ExampleFromNTriplesFile, as: Example2
assert length(Example2.__uris__) == 2 assert length(Example2.__iris__) == 2
assert RDF.uri(Example2.foo) in Example2.__uris__ assert RDF.iri(Example2.foo) in Example2.__iris__
assert RDF.uri(Example2.Bar) in Example2.__uris__ assert RDF.iri(Example2.Bar) in Example2.__iris__
alias TestNS.ExampleFromNQuadsFile, as: Example3 alias TestNS.ExampleFromNQuadsFile, as: Example3
assert length(Example3.__uris__) == 2 assert length(Example3.__iris__) == 2
assert RDF.uri(Example3.foo) in Example3.__uris__ assert RDF.iri(Example3.foo) in Example3.__iris__
assert RDF.uri(Example3.Bar) in Example3.__uris__ assert RDF.iri(Example3.Bar) in Example3.__iris__
alias TestNS.ExampleFromTurtleFile, as: Example4 alias TestNS.ExampleFromTurtleFile, as: Example4
assert length(Example4.__uris__) == 2 assert length(Example4.__iris__) == 2
assert RDF.uri(Example4.foo) in Example4.__uris__ assert RDF.iri(Example4.foo) in Example4.__iris__
assert RDF.uri(Example4.Bar) in Example4.__uris__ assert RDF.iri(Example4.Bar) in Example4.__iris__
alias TestNS.StrictExampleFromAliasedTerms, as: Example4 alias TestNS.StrictExampleFromAliasedTerms, as: Example4
assert length(Example4.__uris__) == 4 assert length(Example4.__iris__) == 4
assert RDF.uri(Example4.Term1) in Example4.__uris__ assert RDF.iri(Example4.Term1) in Example4.__iris__
assert RDF.uri(Example4.term2) in Example4.__uris__ assert RDF.iri(Example4.term2) in Example4.__iris__
assert RDF.uri(Example4.Term3) in Example4.__uris__ assert RDF.iri(Example4.Term3) in Example4.__iris__
assert RDF.uri(Example4.term4) in Example4.__uris__ assert RDF.iri(Example4.term4) in Example4.__iris__
end end
@ -731,11 +731,11 @@ defmodule RDF.Vocabulary.NamespaceTest do
test "resolving an unqualified term raises an error" do test "resolving an unqualified term raises an error" do
assert_raise RDF.Namespace.UndefinedTermError, fn -> RDF.uri(:foo) end assert_raise RDF.Namespace.UndefinedTermError, fn -> RDF.iri(:foo) end
end end
test "resolving an non-RDF.Namespace module" do test "resolving an non-RDF.Namespace module" do
assert_raise RDF.Namespace.UndefinedTermError, fn -> RDF.uri(ExUnit.Test) end assert_raise RDF.Namespace.UndefinedTermError, fn -> RDF.iri(ExUnit.Test) end
end end
@ -765,20 +765,20 @@ defmodule RDF.Vocabulary.NamespaceTest do
end end
test "lowercased terms" do test "lowercased terms" do
assert ExampleFromGraph.foo == URI.parse("http://example.com/from_graph#foo") assert ExampleFromGraph.foo == ~I<http://example.com/from_graph#foo>
assert RDF.uri(ExampleFromGraph.foo) == URI.parse("http://example.com/from_graph#foo") assert RDF.iri(ExampleFromGraph.foo) == ~I<http://example.com/from_graph#foo>
assert ExampleFromNTriplesFile.foo == URI.parse("http://example.com/from_ntriples/foo") assert ExampleFromNTriplesFile.foo == ~I<http://example.com/from_ntriples/foo>
assert RDF.uri(ExampleFromNTriplesFile.foo) == URI.parse("http://example.com/from_ntriples/foo") assert RDF.iri(ExampleFromNTriplesFile.foo) == ~I<http://example.com/from_ntriples/foo>
assert StrictExampleFromTerms.foo == URI.parse("http://example.com/strict_from_terms#foo") assert StrictExampleFromTerms.foo == ~I<http://example.com/strict_from_terms#foo>
assert RDF.uri(StrictExampleFromTerms.foo) == URI.parse("http://example.com/strict_from_terms#foo") assert RDF.iri(StrictExampleFromTerms.foo) == ~I<http://example.com/strict_from_terms#foo>
end end
test "capitalized terms" do test "capitalized terms" do
assert RDF.uri(ExampleFromGraph.Bar) == URI.parse("http://example.com/from_graph#Bar") assert RDF.iri(ExampleFromGraph.Bar) == ~I<http://example.com/from_graph#Bar>
assert RDF.uri(ExampleFromNTriplesFile.Bar) == URI.parse("http://example.com/from_ntriples/Bar") assert RDF.iri(ExampleFromNTriplesFile.Bar) == ~I<http://example.com/from_ntriples/Bar>
assert RDF.uri(StrictExampleFromTerms.Bar) == URI.parse("http://example.com/strict_from_terms#Bar") assert RDF.iri(StrictExampleFromTerms.Bar) == ~I<http://example.com/strict_from_terms#Bar>
end end
test "terms starting with an underscore" do test "terms starting with an underscore" do
@ -786,7 +786,7 @@ defmodule RDF.Vocabulary.NamespaceTest do
use RDF.Vocabulary.Namespace use RDF.Vocabulary.Namespace
defvocab Example, defvocab Example,
base_uri: "http://example.com/ex#", base_iri: "http://example.com/ex#",
terms: ~w[_foo] terms: ~w[_foo]
end end
alias NSwithUnderscoreTerms.Example alias NSwithUnderscoreTerms.Example
@ -801,23 +801,23 @@ defmodule RDF.Vocabulary.NamespaceTest do
describe "term resolution in a non-strict vocab namespace" do describe "term resolution in a non-strict vocab namespace" do
alias TestNS.NonStrictExampleFromTerms alias TestNS.NonStrictExampleFromTerms
test "undefined lowercased terms" do test "undefined lowercased terms" do
assert NonStrictExampleFromTerms.random == URI.parse("http://example.com/non_strict_from_terms#random") assert NonStrictExampleFromTerms.random == ~I<http://example.com/non_strict_from_terms#random>
end end
test "undefined capitalized terms" do test "undefined capitalized terms" do
assert RDF.uri(NonStrictExampleFromTerms.Random) == URI.parse("http://example.com/non_strict_from_terms#Random") assert RDF.iri(NonStrictExampleFromTerms.Random) == ~I<http://example.com/non_strict_from_terms#Random>
end end
test "undefined terms starting with an underscore" do test "undefined terms starting with an underscore" do
assert NonStrictExampleFromTerms._random == URI.parse("http://example.com/non_strict_from_terms#_random") assert NonStrictExampleFromTerms._random == ~I<http://example.com/non_strict_from_terms#_random>
end end
test "defined lowercase terms" do test "defined lowercase terms" do
assert NonStrictExampleFromTerms.foo == URI.parse("http://example.com/non_strict_from_terms#foo") assert NonStrictExampleFromTerms.foo == ~I<http://example.com/non_strict_from_terms#foo>
end end
test "defined capitalized terms" do test "defined capitalized terms" do
assert RDF.uri(NonStrictExampleFromTerms.Bar) == URI.parse("http://example.com/non_strict_from_terms#Bar") assert RDF.iri(NonStrictExampleFromTerms.Bar) == ~I<http://example.com/non_strict_from_terms#Bar>
end end
end end
@ -825,38 +825,38 @@ defmodule RDF.Vocabulary.NamespaceTest do
describe "term resolution of aliases on a strict vocabulary" do describe "term resolution of aliases on a strict vocabulary" do
alias TestNS.StrictExampleFromAliasedTerms, as: Example alias TestNS.StrictExampleFromAliasedTerms, as: Example
test "the alias resolves to the correct URI" do test "the alias resolves to the correct IRI" do
assert RDF.uri(Example.Term1) == URI.parse("http://example.com/strict_from_aliased_terms#term1") assert RDF.iri(Example.Term1) == ~I<http://example.com/strict_from_aliased_terms#term1>
assert RDF.uri(Example.term2) == URI.parse("http://example.com/strict_from_aliased_terms#Term2") assert RDF.iri(Example.term2) == ~I<http://example.com/strict_from_aliased_terms#Term2>
assert RDF.uri(Example.Term3) == URI.parse("http://example.com/strict_from_aliased_terms#Term-3") assert RDF.iri(Example.Term3) == ~I<http://example.com/strict_from_aliased_terms#Term-3>
assert RDF.uri(Example.term4) == URI.parse("http://example.com/strict_from_aliased_terms#term-4") assert RDF.iri(Example.term4) == ~I<http://example.com/strict_from_aliased_terms#term-4>
end end
test "the old term remains resolvable" do test "the old term remains resolvable" do
assert RDF.uri(Example.term1) == URI.parse("http://example.com/strict_from_aliased_terms#term1") assert RDF.iri(Example.term1) == ~I<http://example.com/strict_from_aliased_terms#term1>
assert RDF.uri(Example.Term2) == URI.parse("http://example.com/strict_from_aliased_terms#Term2") assert RDF.iri(Example.Term2) == ~I<http://example.com/strict_from_aliased_terms#Term2>
end end
test "defining multiple aliases for a term" do test "defining multiple aliases for a term" do
alias TestNS.ExampleWithSynonymAliases, as: Example alias TestNS.ExampleWithSynonymAliases, as: Example
assert Example.foo == Example.baz assert Example.foo == Example.baz
assert RDF.uri(Example.foo) == RDF.uri(Example.baz) assert RDF.iri(Example.foo) == RDF.iri(Example.baz)
end end
end end
describe "term resolution of aliases on a non-strict vocabulary" do describe "term resolution of aliases on a non-strict vocabulary" do
alias TestNS.NonStrictExampleFromAliasedTerms, as: Example alias TestNS.NonStrictExampleFromAliasedTerms, as: Example
test "the alias resolves to the correct URI" do test "the alias resolves to the correct IRI" do
assert RDF.uri(Example.Term1) == URI.parse("http://example.com/non_strict_from_aliased_terms#term1") assert RDF.iri(Example.Term1) == ~I<http://example.com/non_strict_from_aliased_terms#term1>
assert RDF.uri(Example.term2) == URI.parse("http://example.com/non_strict_from_aliased_terms#Term2") assert RDF.iri(Example.term2) == ~I<http://example.com/non_strict_from_aliased_terms#Term2>
assert RDF.uri(Example.Term3) == URI.parse("http://example.com/non_strict_from_aliased_terms#Term-3") assert RDF.iri(Example.Term3) == ~I<http://example.com/non_strict_from_aliased_terms#Term-3>
assert RDF.uri(Example.term4) == URI.parse("http://example.com/non_strict_from_aliased_terms#term-4") assert RDF.iri(Example.term4) == ~I<http://example.com/non_strict_from_aliased_terms#term-4>
end end
test "the old term remains resolvable" do test "the old term remains resolvable" do
assert RDF.uri(Example.term1) == URI.parse("http://example.com/non_strict_from_aliased_terms#term1") assert RDF.iri(Example.term1) == ~I<http://example.com/non_strict_from_aliased_terms#term1>
assert RDF.uri(Example.Term2) == URI.parse("http://example.com/non_strict_from_aliased_terms#Term2") assert RDF.iri(Example.Term2) == ~I<http://example.com/non_strict_from_aliased_terms#Term2>
end end
end end
@ -945,31 +945,31 @@ defmodule RDF.Vocabulary.NamespaceTest do
describe "term resolution on the top-level RDF module" do describe "term resolution on the top-level RDF module" do
test "capitalized terms" do test "capitalized terms" do
assert RDF.uri(RDF.Property) == URI.parse("http://www.w3.org/1999/02/22-rdf-syntax-ns#Property") assert RDF.iri(RDF.Property) == ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property>
assert RDF.uri(RDF.Statement) == URI.parse("http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement") assert RDF.iri(RDF.Statement) == ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement>
assert RDF.uri(RDF.List) == URI.parse("http://www.w3.org/1999/02/22-rdf-syntax-ns#List") assert RDF.iri(RDF.List) == ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#List>
assert RDF.uri(RDF.Nil) == URI.parse("http://www.w3.org/1999/02/22-rdf-syntax-ns#nil") assert RDF.iri(RDF.Nil) == ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#nil>
assert RDF.uri(RDF.Seq) == URI.parse("http://www.w3.org/1999/02/22-rdf-syntax-ns#Seq") assert RDF.iri(RDF.Seq) == ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#Seq>
assert RDF.uri(RDF.Bag) == URI.parse("http://www.w3.org/1999/02/22-rdf-syntax-ns#Bag") assert RDF.iri(RDF.Bag) == ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#Bag>
assert RDF.uri(RDF.Alt) == URI.parse("http://www.w3.org/1999/02/22-rdf-syntax-ns#Alt") assert RDF.iri(RDF.Alt) == ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#Alt>
assert RDF.uri(RDF.LangString) == URI.parse("http://www.w3.org/1999/02/22-rdf-syntax-ns#langString") assert RDF.iri(RDF.LangString) == ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#langString>
assert RDF.uri(RDF.PlainLiteral) == URI.parse("http://www.w3.org/1999/02/22-rdf-syntax-ns#PlainLiteral") assert RDF.iri(RDF.PlainLiteral) == ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#PlainLiteral>
assert RDF.uri(RDF.XMLLiteral) == URI.parse("http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral") assert RDF.iri(RDF.XMLLiteral) == ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral>
assert RDF.uri(RDF.HTML) == URI.parse("http://www.w3.org/1999/02/22-rdf-syntax-ns#HTML") assert RDF.iri(RDF.HTML) == ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#HTML>
assert RDF.uri(RDF.Property) == URI.parse("http://www.w3.org/1999/02/22-rdf-syntax-ns#Property") assert RDF.iri(RDF.Property) == ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property>
end end
test "lowercase terms" do test "lowercase terms" do
assert RDF.type == URI.parse("http://www.w3.org/1999/02/22-rdf-syntax-ns#type") assert RDF.type == ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>
assert RDF.subject == URI.parse("http://www.w3.org/1999/02/22-rdf-syntax-ns#subject") assert RDF.subject == ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#subject>
assert RDF.predicate == URI.parse("http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate") assert RDF.predicate == ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate>
assert RDF.object == URI.parse("http://www.w3.org/1999/02/22-rdf-syntax-ns#object") assert RDF.object == ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#object>
assert RDF.first == URI.parse("http://www.w3.org/1999/02/22-rdf-syntax-ns#first") assert RDF.first == ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#first>
assert RDF.rest == URI.parse("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest") assert RDF.rest == ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#rest>
assert RDF.value == URI.parse("http://www.w3.org/1999/02/22-rdf-syntax-ns#value") assert RDF.value == ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#value>
assert RDF.langString == URI.parse("http://www.w3.org/1999/02/22-rdf-syntax-ns#langString") assert RDF.langString == ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#langString>
assert RDF.nil == URI.parse("http://www.w3.org/1999/02/22-rdf-syntax-ns#nil") assert RDF.nil == ~I<http://www.w3.org/1999/02/22-rdf-syntax-ns#nil>
end end
test "description DSL" do test "description DSL" do