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).
## 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
### 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:
- modules for the nodes of an RDF graph
- URIs are (currently) represented via Elixirs `URI` struct and should be
constructed with `RDF.uri/1`
- `RDF.IRI`
- `RDF.BlankNode`
- `RDF.Literal`
- a facility for the mapping of URIs of a vocabulary to Elixir modules and
@ -20,13 +19,15 @@ defmodule RDF do
- `RDF.Graph`
- `RDF.Dataset`
- `RDF.Data`
- `RDF.List`
- the foundations for the definition of RDF serialization formats
- `RDF.Serialization`
- `RDF.Serialization.Decoder`
- `RDF.Serialization.Encoder`
- and the implementation of two basic RDF serialization formats
- and the implementation of various RDF serialization formats
- `RDF.NTriples`
- `RDF.NQuads`
- `RDF.Turtle`
This top-level module provides shortcut functions for the construction of the
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).
"""
alias RDF.{Namespace, Literal, BlankNode, Triple, Quad,
alias RDF.{IRI, Namespace, Literal, BlankNode, Triple, Quad,
Description, Graph, Dataset}
@doc """
@ -42,7 +43,7 @@ defmodule RDF do
## Examples
iex> RDF.resource?(RDF.uri("http://example.com/resource"))
iex> RDF.resource?(RDF.iri("http://example.com/resource"))
true
iex> RDF.resource?(EX.resource)
true
@ -52,31 +53,18 @@ defmodule RDF do
false
"""
def resource?(value)
def resource?(%URI{}), do: true
def resource?(%IRI{}), do: true
def resource?(%BlankNode{}), do: true
def resource?(atom) when is_atom(atom), do: resource?(Namespace.resolve_term(atom))
def resource?(%BlankNode{}), do: true
def resource?(_), do: false
def resource?(_), do: false
@doc """
Checks if the given value is an URI.
## Examples
iex> RDF.uri?("http://www.example.com/foo")
true
iex> RDF.uri?("not a uri")
false
"""
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
defdelegate uri?(value), to: IRI, as: :valid?
defdelegate iri?(value), to: IRI, as: :valid?
defdelegate uri(value), to: IRI, as: :new
defdelegate iri(value), to: IRI, as: :new
defdelegate uri!(value), to: IRI, as: :new!
defdelegate iri!(value), to: IRI, as: :new!
@doc """
Checks if the given value is a blank node.
@ -85,7 +73,7 @@ defmodule RDF do
iex> RDF.bnode?(RDF.bnode)
true
iex> RDF.bnode?(RDF.uri("http://example.com/resource"))
iex> RDF.bnode?(RDF.iri("http://example.com/resource"))
false
iex> RDF.bnode?(42)
false
@ -93,54 +81,6 @@ defmodule RDF do
def bnode?(%BlankNode{}), do: true
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(id), to: BlankNode, as: :new
@ -170,6 +110,16 @@ defmodule RDF do
defdelegate list?(resource, graph), 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
defdelegate unquote(term)(), to: RDF.NS.RDF
@ -183,5 +133,5 @@ defmodule RDF do
defdelegate langString(), 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

View file

@ -1,6 +1,6 @@
defmodule RDF.BlankNode do
@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>
and <https://www.w3.org/TR/rdf11-concepts/#section-blank-nodes>
@ -11,13 +11,13 @@ defmodule RDF.BlankNode do
@type t :: module
@doc """
Generator function for `RDF.BlankNode`s.
Creates a `RDF.BlankNode` with an arbitrary internal id.
"""
def new,
do: new(make_ref())
@doc """
Generator function for `RDF.BlankNode`s with a user-defined identity.
Creates a `RDF.BlankNode` with a user-defined identity.
## Examples
@ -34,10 +34,10 @@ defmodule RDF.BlankNode do
def new(id) when is_atom(id) or is_integer(id),
do: id |> to_string |> new
end
defimpl String.Chars, for: RDF.BlankNode do
def to_string(%RDF.BlankNode{id: id}) do
"_:#{id}"
defimpl String.Chars do
def to_string(%RDF.BlankNode{id: id}), do: "_:#{id}"
end
end

View file

@ -63,7 +63,7 @@ defmodule RDF.Dataset do
Creates an empty named `RDF.Dataset`.
"""
def new(name),
do: %RDF.Dataset{name: RDF.uri(name)}
do: %RDF.Dataset{name: RDF.iri!(name)}
@doc """
Creates a named `RDF.Dataset` with an initial statement.
@ -561,7 +561,7 @@ defmodule RDF.Dataset do
...> {EX.S2, EX.p2, EX.O2},
...> {EX.S1, EX.p2, EX.O3}]) |>
...> 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
Enum.reduce graphs, MapSet.new, fn ({_, graph}, subjects) ->
@ -590,7 +590,7 @@ defmodule RDF.Dataset do
@doc """
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
@ -601,7 +601,7 @@ defmodule RDF.Dataset do
...> {EX.S4, EX.p2, RDF.bnode(:bnode)},
...> {EX.S5, EX.p3, "foo"}
...> ]) |> 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
Enum.reduce graphs, MapSet.new, fn ({_, graph}, objects) ->
@ -620,8 +620,8 @@ defmodule RDF.Dataset do
...> {EX.S2, EX.p2, RDF.bnode(:bnode)},
...> {EX.S3, EX.p1, "foo"}
...> ]) |> RDF.Dataset.resources
MapSet.new([RDF.uri(EX.S1), RDF.uri(EX.S2), RDF.uri(EX.S3),
RDF.uri(EX.O1), RDF.uri(EX.O2), RDF.bnode(:bnode), EX.p1, EX.p2])
MapSet.new([RDF.iri(EX.S1), RDF.iri(EX.S2), RDF.iri(EX.S3),
RDF.iri(EX.O1), RDF.iri(EX.O2), RDF.bnode(:bnode), EX.p1, EX.p2])
"""
def resources(%RDF.Dataset{graphs: graphs}) do
Enum.reduce graphs, MapSet.new, fn ({_, graph}, resources) ->
@ -639,9 +639,9 @@ defmodule RDF.Dataset do
...> {EX.S2, EX.p2, EX.O2},
...> {EX.S1, EX.p2, EX.O3}]) |>
...> RDF.Dataset.statements
[{RDF.uri(EX.S1), RDF.uri(EX.p1), RDF.uri(EX.O1), RDF.uri(EX.Graph)},
{RDF.uri(EX.S1), RDF.uri(EX.p2), RDF.uri(EX.O3)},
{RDF.uri(EX.S2), RDF.uri(EX.p2), RDF.uri(EX.O2)}]
[{RDF.iri(EX.S1), RDF.iri(EX.p1), RDF.iri(EX.O1), RDF.iri(EX.Graph)},
{RDF.iri(EX.S1), RDF.iri(EX.p2), RDF.iri(EX.O3)},
{RDF.iri(EX.S2), RDF.iri(EX.p2), RDF.iri(EX.O2)}]
"""
def statements(%RDF.Dataset{graphs: graphs}) do
Enum.reduce graphs, [], fn ({_, graph}, all_statements) ->
@ -713,7 +713,7 @@ defmodule RDF.Dataset do
...> {EX.S1, EX.p, EX.O, EX.Graph1},
...> {EX.S2, EX.p, EX.O, EX.Graph2}])
...> 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
with subject = coerce_subject(subject) do

View file

@ -10,9 +10,9 @@ defmodule RDF.Datatype do
alias RDF.Datatype.NS.XSD
@doc """
The URI of the datatype.
The IRI of the datatype.
"""
@callback id :: URI.t
@callback id :: RDF.IRI.t
@doc """
Produces the lexical form of a `RDF.Literal`.
@ -57,7 +57,7 @@ defmodule RDF.Datatype do
@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 ...
@mapping %{
@ -72,12 +72,12 @@ defmodule RDF.Datatype do
}
@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
@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)
@ -87,7 +87,7 @@ defmodule RDF.Datatype do
def modules, do: Map.values(@mapping)
@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(id), do: @mapping[id]

View file

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

View file

@ -313,10 +313,10 @@ defmodule RDF.Description do
## Examples
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},
...> {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)
:error
"""
@ -334,7 +334,7 @@ defmodule RDF.Description do
## Examples
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)
nil
iex> RDF.Description.get(RDF.Description.new(EX.S), EX.foo, :bar)
@ -355,7 +355,7 @@ defmodule RDF.Description do
## Examples
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)
nil
"""
@ -385,10 +385,10 @@ defmodule RDF.Description do
...> RDF.Description.get_and_update(EX.P, fn current_objects ->
...> {current_objects, EX.NEW}
...> 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}]) |>
...> 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
with triple_predicate = coerce_predicate(predicate) do
@ -430,7 +430,7 @@ defmodule RDF.Description do
## Examples
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)
{nil, RDF.Description.new({EX.S, EX.P, EX.O})}
"""
@ -462,7 +462,7 @@ defmodule RDF.Description do
@doc """
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
@ -473,7 +473,7 @@ defmodule RDF.Description do
...> {EX.p4, RDF.bnode(:bnode)},
...> {EX.p3, "foo"}
...> ]) |> 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),
do: objects(description, &RDF.resource?/1)
@ -503,7 +503,7 @@ defmodule RDF.Description do
...> {EX.p2, RDF.bnode(:bnode)},
...> {EX.p3, "foo"}
...> ]) |> 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
description

View file

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

View file

@ -479,7 +479,7 @@ defmodule RDF.Graph do
...> {EX.S2, EX.p2, EX.O2},
...> {EX.S1, EX.p2, EX.O3}]) |>
...> 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}),
do: descriptions |> Map.keys |> MapSet.new
@ -507,7 +507,7 @@ defmodule RDF.Graph do
@doc """
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
@ -518,7 +518,7 @@ defmodule RDF.Graph do
...> {EX.S4, EX.p2, RDF.bnode(:bnode)},
...> {EX.S5, EX.p3, "foo"}
...> ]) |> 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
Enum.reduce descriptions, MapSet.new, fn ({_, description}, acc) ->
@ -539,8 +539,8 @@ defmodule RDF.Graph do
...> {EX.S2, EX.p2, RDF.bnode(:bnode)},
...> {EX.S3, EX.p1, "foo"}
...> ]) |> RDF.Graph.resources
MapSet.new([RDF.uri(EX.S1), RDF.uri(EX.S2), RDF.uri(EX.S3),
RDF.uri(EX.O1), RDF.uri(EX.O2), RDF.bnode(:bnode), EX.p1, EX.p2])
MapSet.new([RDF.iri(EX.S1), RDF.iri(EX.S2), RDF.iri(EX.S3),
RDF.iri(EX.O1), RDF.iri(EX.O2), RDF.bnode(:bnode), EX.p1, EX.p2])
"""
def resources(graph = %RDF.Graph{descriptions: descriptions}) do
Enum.reduce(descriptions, MapSet.new, fn ({_, description}, acc) ->
@ -560,9 +560,9 @@ defmodule RDF.Graph do
...> {EX.S2, EX.p2, EX.O2},
...> {EX.S1, EX.p2, EX.O3}
...> ]) |> RDF.Graph.triples
[{RDF.uri(EX.S1), RDF.uri(EX.p1), RDF.uri(EX.O1)},
{RDF.uri(EX.S1), RDF.uri(EX.p2), RDF.uri(EX.O3)},
{RDF.uri(EX.S2), RDF.uri(EX.p2), RDF.uri(EX.O2)}]
[{RDF.iri(EX.S1), RDF.iri(EX.p1), RDF.iri(EX.O1)},
{RDF.iri(EX.S1), RDF.iri(EX.p2), RDF.iri(EX.O3)},
{RDF.iri(EX.S2), RDF.iri(EX.p2), RDF.iri(EX.O2)}]
"""
def triples(graph = %RDF.Graph{}), do: Enum.to_list(graph)

View file

@ -3,19 +3,17 @@ defmodule RDF.InspectHelper do
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
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)
end
def predications_doc(predications, opts) do
predications
|> Enum.map(fn {predicate, objects} ->
value_doc(predicate, opts)
to_doc(predicate, opts)
|> line(objects_doc(objects, opts))
|> nest(4)
end)
@ -27,7 +25,7 @@ defmodule RDF.InspectHelper do
def descriptions_doc(descriptions, opts) do
descriptions
|> Enum.map(fn {subject, description} ->
value_doc(subject, opts)
to_doc(subject, opts)
|> line(predications_doc(description.predications, opts))
|> nest(4)
end)
@ -37,6 +35,12 @@ defmodule RDF.InspectHelper do
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
def inspect(%RDF.BlankNode{id: id}, _opts) do
"~B<#{id}>"
@ -68,7 +72,7 @@ defimpl Inspect, for: RDF.Description do
def inspect(%RDF.Description{subject: subject, predications: predications}, opts) do
doc =
space("subject:", value_doc(subject, opts))
space("subject:", to_doc(subject, opts))
|> line(predications_doc(predications, opts))
|> nest(4)
surround("#RDF.Description{", doc, "}")
@ -81,7 +85,7 @@ defimpl Inspect, for: RDF.Graph do
def inspect(%RDF.Graph{name: name, descriptions: descriptions}, opts) do
doc =
space("name:", value_doc(name, opts))
space("name:", to_doc(name, opts))
|> line(descriptions_doc(descriptions, opts))
|> nest(4)
surround("#RDF.Graph{", doc, "}")
@ -94,7 +98,7 @@ defimpl Inspect, for: RDF.Dataset do
def inspect(%RDF.Dataset{name: name} = dataset, opts) do
doc =
space("name:", value_doc(name, opts))
space("name:", to_doc(name, opts))
|> line(graphs_doc(RDF.Dataset.graphs(dataset), opts))
|> nest(4)
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]
alias RDF.{Graph, Description, BlankNode}
alias RDF.{Graph, Description, IRI, BlankNode}
@type t :: module
@rdf_nil RDF.nil
@ -27,7 +29,7 @@ defmodule RDF.List do
def new(head, graph)
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
with list = %RDF.List{head: head, graph: graph} do
@ -77,7 +79,7 @@ defmodule RDF.List do
end
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
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),
do: do_node?(list_node, graph)
def node?(%URI{} = list_node, graph),
def node?(%IRI{} = list_node, graph),
do: do_node?(list_node, graph)
def node?(list_node, graph)
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
@ -206,7 +208,7 @@ defmodule RDF.List do
def reduce(%RDF.List{head: %BlankNode{}} = 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)
def reduce(_, _, _), do: {:halted, nil}

View file

@ -11,7 +11,7 @@ defmodule RDF.Literal do
# to be able to pattern-match on plain types
@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]
@ -56,7 +56,7 @@ defmodule RDF.Literal 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
def new(value, opts) when is_list(opts),
@ -74,7 +74,7 @@ defmodule RDF.Literal do
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
nil -> %RDF.Literal{value: value, datatype: id}
datatype -> datatype.new(value, opts)
@ -82,7 +82,7 @@ defmodule RDF.Literal do
end
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,
do: new(value)

View file

@ -1,6 +1,6 @@
defmodule RDF.Namespace do
@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`,
but other types are thinkable and might be implemented in the future, eg.
@ -8,9 +8,9 @@ defmodule RDF.Namespace do
"""
@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 """
All terms of a `RDF.Namespace`.
@ -19,7 +19,7 @@ defmodule RDF.Namespace do
@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
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(uri = %URI{}), do: uri
def resolve_term(%RDF.IRI{} = iri), do: iri
def resolve_term(namespaced_term) when is_atom(namespaced_term) do
namespaced_term

View file

@ -19,7 +19,7 @@ defmodule RDF.NS do
See <https://www.w3.org/TR/xmlschema11-2/>
"""
defvocab XSD,
base_uri: "http://www.w3.org/2001/XMLSchema#",
base_iri: "http://www.w3.org/2001/XMLSchema#",
terms: RDF.Datatype.NS.XSD.__terms__
@vocabdoc """
@ -28,7 +28,7 @@ defmodule RDF.NS do
See <https://www.w3.org/TR/rdf11-concepts/>
"""
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",
alias: [
Nil: "nil",
@ -41,7 +41,7 @@ defmodule RDF.NS do
See <https://www.w3.org/TR/rdf-schema/>
"""
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"
@vocabdoc """
@ -50,7 +50,7 @@ defmodule RDF.NS do
See <https://www.w3.org/TR/owl-overview/>
"""
defvocab OWL,
base_uri: "http://www.w3.org/2002/07/owl#",
base_iri: "http://www.w3.org/2002/07/owl#",
file: "owl.ttl"
@vocabdoc """
@ -59,7 +59,7 @@ defmodule RDF.NS do
See <http://www.w3.org/TR/skos-reference/>
"""
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"
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")
{~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)
{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
{
@ -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"}
{~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}
{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: new(subject, predicate, object, graph_context)

View file

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

View file

@ -1,37 +1,32 @@
defmodule RDF.Serialization.ParseHelper do
@moduledoc false
alias RDF.IRI
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 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
case URI.parse(iri_unescape(value)) do
%URI{scheme: nil} ->
{:error, line, "#{value} is not a valid URI"}
parsed_uri ->
if String.ends_with?(value, "#") do
{:ok, %URI{parsed_uri | fragment: ""}}
else
{:ok, parsed_uri}
end
def to_iri({:iriref, line, value}) do
with iri = RDF.iri(iri_unescape(value)) do
if IRI.valid?(iri) do
{:ok, iri}
else
{:error, line, "#{value} is not a valid IRI"}
end
end
end
def to_absolute_or_relative_uri({:iriref, _line, value}) do
case URI.parse(iri_unescape(value)) do
uri = %URI{scheme: scheme} when not is_nil(scheme) ->
if String.ends_with?(value, "#") do
%URI{uri | fragment: ""}
else
uri
end
_ ->
{:relative_uri, value}
def to_absolute_or_relative_iri({:iriref, _line, value}) do
with iri = RDF.iri(iri_unescape(value)) do
if IRI.absolute?(iri) do
iri
else
{:relative_iri, value}
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({:string_literal_quote, _line, 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)
def to_literal(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
alias RDF.{Literal, BlankNode}
alias RDF.{IRI, Literal, BlankNode}
@xsd_string RDF.Datatype.NS.XSD.string
@ -22,8 +22,8 @@ defmodule RDF.NTriples.Encoder do
"#{term(subject)} #{term(predicate)} #{term(object)} ."
end
def term(%URI{} = uri) do
"<#{to_string(uri)}>"
def term(%IRI{} = iri) do
"<#{to_string(iri)}>"
end
def term(%Literal{value: value, language: language}) when not is_nil(language) do

View file

@ -2,9 +2,11 @@ defmodule RDF.Turtle.Decoder do
@moduledoc false
use RDF.Serialization.Decoder
alias RDF.IRI
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
%State{state | namespaces: Map.put(namespaces, ns, iri)}
@ -29,7 +31,7 @@ defmodule RDF.Turtle.Decoder do
with {:ok, tokens, _} <- tokenize(content),
{:ok, ast} <- parse(tokens),
base = Map.get(opts, :base) do
build_graph(ast, base && RDF.uri(base))
build_graph(ast, base && RDF.iri(base))
else
{:error, {error_line, :turtle_lexer, error_descriptor}, _error_line_again} ->
{: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
try do
{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} ->
with {statements, state} = triples(triples_ast, state) do
{RDF.Graph.add(graph, statements), state}
@ -63,25 +65,25 @@ defmodule RDF.Turtle.Decoder do
end
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)
else
with absolute_uri = RDF.URI.Helper.absolute_iri(iri, state.base_uri) do
State.add_namespace(state, ns, URI.to_string(absolute_uri))
with absolute_iri = IRI.absolute(iri, state.base_iri) do
State.add_namespace(state, ns, to_string(absolute_iri))
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
RDF.URI.Helper.absolute_iri?(uri) ->
%State{state | base_uri: RDF.uri(uri)}
base_uri != nil ->
with absolute_uri = RDF.URI.Helper.absolute_iri(uri, base_uri) do
%State{state | base_uri: absolute_uri}
IRI.absolute?(iri) ->
%State{state | base_iri: RDF.iri(iri)}
base_iri != nil ->
with absolute_iri = IRI.absolute(iri, base_iri) do
%State{state | base_iri: absolute_iri}
end
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
@ -108,7 +110,7 @@ defmodule RDF.Turtle.Decoder do
defp resolve_node({:prefix_ln, line_number, {prefix, name}}, statements, state) 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
raise "line #{line_number}: undefined prefix #{inspect prefix}"
end
@ -116,18 +118,18 @@ defmodule RDF.Turtle.Decoder do
defp resolve_node({:prefix_ns, line_number, prefix}, statements, state) do
if ns = State.ns(state, prefix) do
{RDF.uri(ns), statements, state}
{RDF.iri(ns), statements, state}
else
raise "line #{line_number}: undefined prefix #{inspect prefix}"
end
end
defp resolve_node({:relative_uri, relative_uri}, _, %State{base_uri: nil}) do
raise "Could not resolve resolve relative IRI '#{relative_uri}', no base uri provided"
defp resolve_node({:relative_iri, relative_iri}, _, %State{base_iri: nil}) do
raise "Could not resolve resolve relative IRI '#{relative_iri}', no base iri provided"
end
defp resolve_node({:relative_uri, relative_uri}, statements, state) do
{RDF.URI.Helper.absolute_iri(relative_uri, state.base_uri), statements, state}
defp resolve_node({:relative_iri, relative_iri}, statements, state) do
{IRI.absolute(relative_iri, state.base_iri), statements, state}
end
defp resolve_node({:anon}, statements, state) do

View file

@ -4,7 +4,7 @@ defmodule RDF.Turtle.Encoder do
use RDF.Serialization.Encoder
alias RDF.Turtle.Encoder.State
alias RDF.{Literal, BlankNode, Description}
alias RDF.{IRI, Literal, BlankNode, Description}
@indentation_char " "
@indentation 4
@ -19,10 +19,10 @@ defmodule RDF.Turtle.Encoder do
@rdf_nil RDF.nil
# 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
@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)
@ -60,8 +60,8 @@ defmodule RDF.Turtle.Encoder do
defp init_prefixes(nil), do: %{}
defp init_prefixes(prefixes) do
Enum.reduce prefixes, %{}, fn {prefix, uri}, reverse ->
Map.put(reverse, RDF.uri(uri), to_string(prefix))
Enum.reduce prefixes, %{}, fn {prefix, iri}, reverse ->
Map.put(reverse, RDF.iri(iri), to_string(prefix))
end
end
@ -89,10 +89,10 @@ defmodule RDF.Turtle.Encoder do
end
defp order_descriptions(descriptions, state) do
base_uri = State.base_uri(state)
base_iri = State.base_iri(state)
group =
Enum.group_by descriptions, fn
%Description{subject: ^base_uri} ->
%Description{subject: ^base_iri} ->
:base
description ->
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
Enum.sort descriptions, fn
%Description{subject: %URI{}}, %Description{subject: %BlankNode{}} -> true
%Description{subject: %BlankNode{}}, %Description{subject: %URI{}} -> false
%Description{subject: %IRI{}}, %Description{subject: %BlankNode{}} -> true
%Description{subject: %BlankNode{}}, %Description{subject: %IRI{}} -> false
%Description{subject: s1}, %Description{subject: s2} ->
to_string(s1) < to_string(s2)
end
@ -254,10 +254,10 @@ defmodule RDF.Turtle.Encoder do
defp term(@rdf_type, _, :predicate, _), do: "a"
defp term(@rdf_nil, _, _, _), do: "()"
defp term(%URI{} = uri, state, _, _) do
based_name(uri, State.base(state)) ||
prefixed_name(uri, State.prefixes(state)) ||
"<#{to_string(uri)}>"
defp term(%IRI{} = iri, state, _, _) do
based_name(iri, State.base(state)) ||
prefixed_name(iri, State.prefixes(state)) ||
"<#{to_string(iri)}>"
end
defp term(%BlankNode{} = bnode, state, position, nesting)
@ -303,10 +303,10 @@ defmodule RDF.Turtle.Encoder do
")"
end
defp based_name(%URI{} = uri, base), do: based_name(URI.to_string(uri), base)
defp based_name(uri, {:ok, base}) do
if String.starts_with?(uri, base) do
"<#{String.slice(uri, String.length(base)..-1)}>"
defp based_name(%IRI{} = iri, base), do: based_name(to_string(iri), base)
defp based_name(iri, {:ok, base}) do
if String.starts_with?(iri, base) do
"<#{String.slice(iri, String.length(base)..-1)}>"
end
end
@ -317,8 +317,8 @@ defmodule RDF.Turtle.Encoder do
do: ~s["#{Literal.lexical(literal)}"^^#{term(datatype, state, :datatype, nesting)}]
def prefixed_name(uri, prefixes) do
with {ns, name} <- split_uri(uri) do
def prefixed_name(iri, prefixes) do
with {ns, name} <- split_iri(iri) do
case prefixes[ns] do
nil -> nil
prefix -> prefix <> ":" <> name
@ -326,17 +326,19 @@ defmodule RDF.Turtle.Encoder do
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),
do: {%URI{uri | fragment: ""}, fragment}
defp split_iri(%URI{fragment: fragment} = uri) when not is_nil(fragment),
do: {RDF.iri(%URI{uri | fragment: ""}), fragment}
defp split_uri(%URI{path: nil}),
defp split_iri(%URI{path: 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),
{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

View file

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

View file

@ -7,17 +7,17 @@ defmodule RDF.Sigils do
@doc ~S"""
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
iex> import RDF.Sigils
iex> ~I<http://example.com>
RDF.uri("http://example.com")
RDF.iri("http://example.com")
"""
defmacro sigil_I({:<<>>, _, [iri]}, []) when is_binary(iri) do
Macro.escape(RDF.uri(iri))
Macro.escape(RDF.iri!(iri))
end
@doc ~S"""

View file

@ -5,12 +5,12 @@ defmodule RDF.Statement do
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 predicate :: URI.t
@type object :: URI.t | BlankNode.t | Literal.t
@type graph_name :: URI.t | BlankNode.t
@type subject :: IRI.t | BlankNode.t
@type predicate :: IRI.t
@type object :: IRI.t | BlankNode.t | Literal.t
@type graph_name :: IRI.t | BlankNode.t
@type coercible_subject :: subject | 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)
@doc false
def coerce_subject(uri)
def coerce_subject(uri = %URI{}), do: uri
def coerce_subject(iri)
def coerce_subject(iri = %IRI{}), do: iri
def coerce_subject(bnode = %BlankNode{}), do: bnode
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
@doc false
def coerce_predicate(uri)
def coerce_predicate(uri = %URI{}), do: uri
def coerce_predicate(iri)
def coerce_predicate(iri = %IRI{}), do: iri
# Note: Although, RDF does not allow blank nodes for properties, JSON-LD allows
# them, by introducing the notion of "generalized RDF".
# TODO: Support an option `:strict_rdf` to explicitly disallow them or produce warnings or ...
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
@doc false
def coerce_object(uri)
def coerce_object(uri = %URI{}), do: uri
def coerce_object(iri)
def coerce_object(iri = %IRI{}), do: iri
def coerce_object(literal = %Literal{}), do: literal
def coerce_object(bnode = %BlankNode{}), do: bnode
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)
@doc false
def coerce_graph_name(uri)
def coerce_graph_name(iri)
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("_:" <> identifier), do: RDF.bnode(identifier)
def coerce_graph_name(uri) when is_atom(uri) or is_binary(uri),
do: RDF.uri(uri)
def coerce_graph_name(iri) when is_atom(iri) or is_binary(iri), do: RDF.iri!(iri)
def coerce_graph_name(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)
{~I<http://example.com/S>, ~I<http://example.com/p>, RDF.literal(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
{
@ -42,7 +42,7 @@ defmodule RDF.Triple do
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)}
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)

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
@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 """
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#propertyDisjointWith
]
|> Enum.map(&RDF.uri/1)
|> Enum.map(&RDF.iri/1)
|> MapSet.new
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#DeprecatedProperty
]
|> Enum.map(&RDF.uri/1)
|> Enum.map(&RDF.iri/1)
|> MapSet.new
defp property_by_rdf_type?(nil), do: nil

View file

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

View file

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

View file

@ -22,22 +22,22 @@ nonEmptyNtriplesDoc -> triple : [ '$1' ].
triple -> subject predicate object '.' : { '$1', '$2', '$3' }.
subject -> iriref : to_uri('$1').
subject -> iriref : to_iri('$1').
subject -> blank_node_label : to_bnode('$1').
predicate -> iriref : to_uri('$1').
object -> iriref : to_uri('$1').
predicate -> iriref : to_iri('$1').
object -> iriref : to_iri('$1').
object -> blank_node_label : to_bnode('$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 : to_literal('$1').
Erlang code.
to_uri(IRIREF) ->
case 'Elixir.RDF.Serialization.ParseHelper':to_uri(IRIREF) of
to_iri(IRIREF) ->
case 'Elixir.RDF.Serialization.ParseHelper':to_iri(IRIREF) of
{ok, URI} -> URI;
{error, ErrorLine, Message} -> return_error(ErrorLine, Message)
end.

View file

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

View file

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

View file

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

View file

@ -4,11 +4,11 @@ defmodule RDF.TestSuite do
use RDF.Vocabulary.Namespace
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
defvocab RDFT,
base_uri: "http://www.w3.org/ns/rdftest#",
base_iri: "http://www.w3.org/ns/rdftest#",
terms: ~w[
TestTurtleEval
TestTurtlePositiveSyntax
@ -21,7 +21,7 @@ defmodule RDF.TestSuite do
alias RDF.NS.RDFS
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")
@ -39,7 +39,7 @@ defmodule RDF.TestSuite do
|> manifest_graph(opts)
|> Graph.descriptions
|> 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
@ -51,13 +51,17 @@ defmodule RDF.TestSuite do
# do: test_name(test_case) <> ": " <> value(test_case, RDFS.comment)
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),
do: test_input_file(test_case).path |> Path.basename |> file(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),

View file

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

View file

@ -16,8 +16,8 @@ defmodule RDF.DatasetTest do
test "creating an empty dataset with a coercible dataset name" do
assert named_dataset("http://example.com/DatasetName")
|> named_dataset?(uri("http://example.com/DatasetName"))
assert named_dataset(EX.Foo) |> named_dataset?(uri(EX.Foo))
|> named_dataset?(iri("http://example.com/DatasetName"))
assert named_dataset(EX.Foo) |> named_dataset?(iri(EX.Foo))
end
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
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})
end
test "creating a named dataset with an initial quad" do
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})
end
@ -63,7 +63,7 @@ defmodule RDF.DatasetTest do
{EX.Subject, EX.predicate2, EX.Object2, EX.GraphName},
{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.predicate2, EX.Object2, EX.GraphName})
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
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})
end
@ -83,14 +83,14 @@ defmodule RDF.DatasetTest do
test "creating a named dataset with an inital graph" do
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 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}))
assert named_dataset?(ds, uri(EX.DatasetName))
assert named_dataset?(ds, iri(EX.DatasetName))
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})
end
@ -103,24 +103,24 @@ defmodule RDF.DatasetTest do
ds = Dataset.new(Graph.new(EX.GraphName, {EX.Subject, EX.predicate, EX.Object}))
assert unnamed_dataset?(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})
end
end
describe "add" 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})
end
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)})
assert dataset_includes_statement?(ds, {EX.Subject, EX.predicate, 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, iri(EX.Graph)})
end
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})
end
@ -284,7 +284,7 @@ defmodule RDF.DatasetTest do
ds = Dataset.add(ds, Graph.new({EX.Subject1, EX.predicate2, EX.Object3}), EX.Graph)
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 dataset_includes_statement?(ds, {EX.Subject1, EX.predicate1, EX.Object1})
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},
]))
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 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})
ds = Dataset.add(ds, Graph.new(EX.Graph2, {EX.Subject1, EX.predicate2, EX.Object3}))
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 Enum.count(ds) == 3
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})
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 dataset_includes_statement?(ds, {EX.Subject1, EX.predicate1, EX.Object1})
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.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.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, 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 dataset_includes_statement?(ds, {EX.Subject1, EX.predicate1, EX.Object1})
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate2, EX.Object2})
@ -428,14 +428,14 @@ defmodule RDF.DatasetTest do
end
test "non-coercible statements elements are causing an error" do
assert_raise RDF.InvalidURIError, fn ->
Dataset.add(dataset(), {"not a URI", EX.predicate, uri(EX.Object), uri(EX.GraphName)})
assert_raise RDF.IRI.InvalidError, fn ->
Dataset.add(dataset(), {"not a IRI", EX.predicate, iri(EX.Object), iri(EX.GraphName)})
end
assert_raise RDF.InvalidLiteralError, fn ->
assert_raise RDF.Literal.InvalidError, fn ->
Dataset.add(dataset(), {EX.Subject, EX.prop, self(), nil})
end
assert_raise RDF.InvalidURIError, fn ->
Dataset.add(dataset(), {uri(EX.Subject), EX.predicate, uri(EX.Object), "not a URI"})
assert_raise RDF.IRI.InvalidError, fn ->
Dataset.add(dataset(), {iri(EX.Subject), EX.predicate, iri(EX.Object), "not a IRI"})
end
end
end
@ -683,20 +683,20 @@ defmodule RDF.DatasetTest do
assert Dataset.pop(Dataset.new) == {nil, Dataset.new}
{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
{{subject, predicate, object, _}, dataset} =
Dataset.new([{EX.S, EX.p, EX.O, EX.Graph}, {EX.S, EX.p, EX.O}])
|> 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
{{subject, _, _, graph_context}, dataset} =
Dataset.new([{EX.S, EX.p, EX.O1, EX.Graph}, {EX.S, EX.p, EX.O2, EX.Graph}])
|> Dataset.pop
assert subject == uri(EX.S)
assert graph_context == uri(EX.Graph)
assert subject == iri(EX.S)
assert graph_context == iri(EX.Graph)
assert Enum.count(dataset.graphs) == 1
end
@ -716,7 +716,7 @@ defmodule RDF.DatasetTest do
end
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}),
{EX.S, EX.p, EX.O, EX.Graph})

View file

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

View file

@ -21,8 +21,8 @@ defmodule RDF.GraphTest do
test "creating an empty graph with a coercible graph name" do
assert named_graph("http://example.com/graph/GraphName")
|> named_graph?(uri("http://example.com/graph/GraphName"))
assert named_graph(EX.Foo) |> named_graph?(uri(EX.Foo))
|> named_graph?(iri("http://example.com/graph/GraphName"))
assert named_graph(EX.Foo) |> named_graph?(iri(EX.Foo))
end
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
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})
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})
end
@ -61,19 +61,19 @@ defmodule RDF.GraphTest do
test "creating a named graph with a list of initial triples" do
g = Graph.new(EX.GraphName, [{EX.Subject, EX.predicate1, EX.Object1},
{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.predicate2, 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.Object2})
end
test "creating a named graph with an initial description" do
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})
end
@ -85,11 +85,11 @@ defmodule RDF.GraphTest do
test "creating a named graph from another graph" do
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})
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})
end
@ -106,9 +106,9 @@ defmodule RDF.GraphTest do
describe "add" 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})
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})
end
@ -190,10 +190,10 @@ defmodule RDF.GraphTest do
end
test "non-coercible Triple elements are causing an error" do
assert_raise RDF.InvalidURIError, fn ->
Graph.add(graph(), {"not a URI", EX.predicate, uri(EX.Object)})
assert_raise RDF.IRI.InvalidError, fn ->
Graph.add(graph(), {"not a IRI", EX.predicate, iri(EX.Object)})
end
assert_raise RDF.InvalidLiteralError, fn ->
assert_raise RDF.Literal.InvalidError, fn ->
Graph.add(graph(), {EX.Subject, EX.prop, self()})
end
end
@ -347,19 +347,19 @@ defmodule RDF.GraphTest do
assert Graph.pop(Graph.new) == {nil, Graph.new}
{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
{{subject, predicate, _}, graph} =
Graph.new([{EX.S, EX.p, EX.O1}, {EX.S, EX.p, EX.O2}])
|> 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
{{subject, _, _}, graph} =
Graph.new([{EX.S, EX.p1, EX.O1}, {EX.S, EX.p2, EX.O2}])
|> Graph.pop
assert subject == uri(EX.S)
assert subject == iri(EX.S)
assert Enum.count(graph.descriptions) == 1
end
@ -378,7 +378,7 @@ defmodule RDF.GraphTest do
end
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})
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
alias RDF.{BlankNode, Literal, Graph}
alias RDF.{IRI, BlankNode, Literal, Graph}
use RDF.Vocabulary.Namespace
defvocab EX,
base_uri: "http://example.org/#",
base_iri: "http://example.org/#",
terms: [], strict: false
setup do
@ -49,7 +49,7 @@ defmodule RDF.ListTest do
|> RDF.first(1)
|> RDF.rest(RDF.nil))
assert %RDF.List{} = list = RDF.List.new(EX.Foo, graph)
assert list.head == RDF.uri(EX.Foo)
assert list.head == iri(EX.Foo)
end
test "with other properties on its nodes" do
@ -165,7 +165,7 @@ defmodule RDF.ListTest do
end
%{
"URI" => RDF.uri(EX.Foo),
"IRI" => iri(EX.Foo),
"blank node" => ~B<Foo>,
"literal" => ~L<Foo>,
"string" => "Foo",
@ -219,7 +219,7 @@ defmodule RDF.ListTest do
assert RDF.nil ==
Enum.reduce list, bnode, fn element, list_node ->
case element do
%URI{} ->
%IRI{} ->
assert get_in(graph_with_list, [list_node, RDF.first]) == [element]
%BlankNode{} ->
assert get_in(graph_with_list, [list_node, RDF.first]) == [element]
@ -228,7 +228,7 @@ defmodule RDF.ListTest do
element when is_boolean(element) ->
assert get_in(graph_with_list, [list_node, RDF.first]) == [RDF.Literal.new(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)]
end
@ -247,7 +247,7 @@ defmodule RDF.ListTest do
end
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

View file

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

View file

@ -13,7 +13,7 @@ defmodule RDF.NQuads.EncoderTest do
use RDF.Vocabulary.Namespace
defvocab EX,
base_uri: "http://example.org/#",
base_iri: "http://example.org/#",
terms: [], strict: false
@ -22,7 +22,7 @@ defmodule RDF.NQuads.EncoderTest do
assert NQuads.Encoder.encode!(Graph.new) == ""
end
test "statements with URIs only" do
test "statements with IRIs only" do
assert NQuads.Encoder.encode!(Graph.new [
{EX.S1, EX.p1, EX.O1},
{EX.S1, EX.p1, EX.O2},
@ -71,7 +71,7 @@ defmodule RDF.NQuads.EncoderTest do
assert NQuads.Encoder.encode!(Dataset.new) == ""
end
test "statements with URIs only" do
test "statements with IRIs only" do
assert NQuads.Encoder.encode!(Dataset.new [
{EX.S1, EX.p1, EX.O1, 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
defvocab EX,
base_uri: "http://example.org/#",
base_iri: "http://example.org/#",
terms: [], strict: false
defvocab P,
base_uri: "http://www.perceive.net/schemas/relationship/",
base_iri: "http://www.perceive.net/schemas/relationship/",
terms: [], strict: false
@ -76,7 +76,7 @@ defmodule RDF.NTriples.DecoderTest do
])
end
test "decoding a single triple with uris" do
test "decoding a single triple with iris" do
assert RDF.NTriples.Decoder.decode!("""
<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})

View file

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

View file

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

View file

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

View file

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

View file

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