Add valid?/1 on RDF.Triple, RDF.Quad and RDF.Statement

This commit is contained in:
Marcel Otto 2018-11-11 02:30:25 +01:00
parent d1532d7022
commit 036de6e66c
5 changed files with 174 additions and 2 deletions

View file

@ -5,6 +5,18 @@ This project adheres to [Semantic Versioning](http://semver.org/) and
[Keep a CHANGELOG](http://keepachangelog.com).
## Unreleased
### Added
- `RDF.Triple.valid?/1`, `RDF.Quad.valid?/1` and `RDF.Statement.valid?/1`, which
validate if a tuple is a valid RDF triple or RDF quad
[Compare v0.5.2...HEAD](https://github.com/marcelotto/rdf-ex/compare/v0.5.2...HEAD)
## 0.5.2 - 2018-11-04
### Added

View file

@ -6,7 +6,7 @@ defmodule RDF.Quad do
RDF values for subject, predicate, object and a graph context.
"""
alias RDF.{Statement, Term}
alias RDF.Statement
@doc """
Creates a `RDF.Quad` with proper RDF values.
@ -94,4 +94,16 @@ defmodule RDF.Quad do
def values(_, _), do: nil
@doc """
Checks if the given tuple is a valid RDF quad.
The elements of a valid RDF quad must be RDF terms. On the subject
position only IRIs and blank nodes allowed, while on the predicate and graph
context position only IRIs allowed. The object position can be any RDF term.
"""
def valid?(tuple)
def valid?({_, _, _, _} = quad), do: Statement.valid?(quad)
def valid?(_), do: false
end

View file

@ -115,4 +115,40 @@ defmodule RDF.Statement do
def default_term_mapping({:graph_name, nil}), do: nil
def default_term_mapping({_, term}), do: RDF.Term.value(term)
@doc """
Checks if the given tuple is a valid RDF statement, i.e. RDF triple or quad.
The elements of a valid RDF statement must be RDF terms. On the subject
position only IRIs and blank nodes allowed, while on the predicate and graph
context position only IRIs allowed. The object position can be any RDF term.
"""
def valid?(tuple)
def valid?({subject, predicate, object}) do
valid_subject?(subject) && valid_predicate?(predicate) && valid_object?(object)
end
def valid?({subject, predicate, object, graph_name}) do
valid_subject?(subject) && valid_predicate?(predicate) && valid_object?(object) &&
valid_graph_name?(graph_name)
end
def valid?(_), do: false
def valid_subject?(%IRI{}), do: true
def valid_subject?(%BlankNode{}), do: true
def valid_subject?(_), do: false
def valid_predicate?(%IRI{}), do: true
def valid_predicate?(_), do: false
def valid_object?(%IRI{}), do: true
def valid_object?(%BlankNode{}), do: true
def valid_object?(%Literal{}), do: true
def valid_object?(_), do: false
def valid_graph_name?(%IRI{}), do: true
def valid_graph_name?(_), do: false
end

View file

@ -6,7 +6,7 @@ defmodule RDF.Triple do
RDF values for subject, predicate and object.
"""
alias RDF.{Statement, Term}
alias RDF.Statement
@doc """
Creates a `RDF.Triple` with proper RDF values.
@ -87,4 +87,16 @@ defmodule RDF.Triple do
def values(_, _), do: nil
@doc """
Checks if the given tuple is a valid RDF triple.
The elements of a valid RDF triple must be RDF terms. On the subject
position only IRIs and blank nodes allowed, while on the predicate position
only IRIs allowed. The object position can be any RDF term.
"""
def valid?(tuple)
def valid?({_, _, _} = triple), do: Statement.valid?(triple)
def valid?(_), do: false
end

View file

@ -3,4 +3,104 @@ defmodule RDF.StatementTest do
doctest RDF.Statement
describe "valid?/1" do
@iri ~I<http://example.com/Foo>
@bnode ~B<foo>
@valid_literal ~L"foo"
@invalid_literal RDF.integer("foo")
@literal @valid_literal
@valid_triples [
{@iri, @iri, @iri},
{@bnode, @iri, @iri},
{@iri, @iri, @bnode},
{@bnode, @iri, @bnode},
{@iri, @iri, @valid_literal},
{@bnode, @iri, @valid_literal},
{@iri, @iri, @invalid_literal},
{@bnode, @iri, @invalid_literal},
]
@valid_quads [
{@iri, @iri, @iri , @iri},
{@bnode, @iri, @iri , @iri},
{@iri, @iri, @bnode , @iri},
{@bnode, @iri, @bnode , @iri},
{@iri, @iri, @valid_literal , @iri},
{@bnode, @iri, @valid_literal , @iri},
{@iri, @iri, @invalid_literal, @iri},
{@bnode, @iri, @invalid_literal, @iri},
]
test "valid triples" do
Enum.each @valid_triples, fn argument ->
assert RDF.Statement.valid?(argument) == true
assert RDF.Triple.valid?(argument) == true
refute RDF.Quad.valid?(argument)
end
end
test "valid quads" do
Enum.each @valid_quads, fn argument ->
assert RDF.Statement.valid?(argument) == true
assert RDF.Quad.valid?(argument) == true
refute RDF.Triple.valid?(argument)
end
end
test "with invalid triples" do
[
{@iri, @bnode, @iri},
{@valid_literal, @iri, @iri},
{@iri, @valid_literal, @iri},
]
|> Enum.each(fn argument ->
assert RDF.Statement.valid?(argument) == false
assert RDF.Triple.valid?(argument) == false
assert RDF.Quad.valid?(argument) == false
end)
end
test "with invalid quads" do
[
{@iri, @bnode, @iri, @iri},
{@iri, @iri, @iri, @bnode},
{@valid_literal, @iri, @iri, @iri},
{@iri, @valid_literal, @iri, @iri},
{@iri, @iri , @iri, @valid_literal},
]
|> Enum.each(fn argument ->
assert RDF.Statement.valid?(argument) == false
assert RDF.Triple.valid?(argument) == false
assert RDF.Quad.valid?(argument) == false
end)
end
test "with invalid statements by number of elements" do
refute RDF.Statement.valid?({@iri, @iri})
refute RDF.Triple.valid?({@iri, @iri})
refute RDF.Quad.valid?({@iri, @iri})
refute RDF.Statement.valid?({@iri, @iri, @iri, @iri, @iri})
refute RDF.Triple.valid?({@iri, @iri, @iri, @iri, @iri})
refute RDF.Quad.valid?({@iri, @iri, @iri, @iri, @iri})
refute RDF.Triple.valid?({@iri, @iri, @iri, @iri})
refute RDF.Quad.valid?({@iri, @iri, @iri})
end
test "with non-tuples" do
[
42,
"foo",
@iri,
@bnode,
]
|> Enum.each(fn arg ->
refute RDF.Statement.valid?(arg)
refute RDF.Triple.valid?(arg)
refute RDF.Quad.valid?(arg)
end)
end
end
end