Change RDF.Graph.new to take the graph name as an option

This commit is contained in:
Marcel Otto 2019-03-29 00:34:22 +01:00
parent 6bd42a9c39
commit 1793c842bb
8 changed files with 142 additions and 119 deletions

View file

@ -13,6 +13,11 @@ This project adheres to [Semantic Versioning](http://semver.org/) and
- configurable RDF.default_prefixes - configurable RDF.default_prefixes
### Changed
- `RDF.Graph.new` now takes the graph name as a `name` option
[Compare v0.5.4...HEAD](https://github.com/marcelotto/rdf-ex/compare/v0.5.4...HEAD) [Compare v0.5.4...HEAD](https://github.com/marcelotto/rdf-ex/compare/v0.5.4...HEAD)

View file

@ -1 +1 @@
0.5.4 0.6.0-pre

View file

@ -124,7 +124,7 @@ defmodule RDF.Dataset do
with graph_context = coerce_graph_name(graph_context) do with graph_context = coerce_graph_name(graph_context) do
updated_graphs = updated_graphs =
Map.update(graphs, graph_context, Map.update(graphs, graph_context,
Graph.new(graph_context, {subject, predicate, objects}), Graph.new({subject, predicate, objects}, name: graph_context),
fn graph -> Graph.add(graph, {subject, predicate, objects}) end) fn graph -> Graph.add(graph, {subject, predicate, objects}) end)
%RDF.Dataset{name: name, graphs: updated_graphs} %RDF.Dataset{name: name, graphs: updated_graphs}
end end
@ -140,7 +140,7 @@ defmodule RDF.Dataset do
%Description{} = description, graph_context) do %Description{} = description, graph_context) do
with graph_context = coerce_graph_name(graph_context) do with graph_context = coerce_graph_name(graph_context) do
updated_graph = updated_graph =
Map.get(graphs, graph_context, Graph.new(graph_context)) Map.get(graphs, graph_context, Graph.new(name: graph_context))
|> Graph.add(description) |> Graph.add(description)
%RDF.Dataset{ %RDF.Dataset{
name: name, name: name,
@ -200,7 +200,7 @@ defmodule RDF.Dataset do
graph = %Graph{} -> graph = %Graph{} ->
Graph.put(graph, {subject, predicate, objects}) Graph.put(graph, {subject, predicate, objects})
nil -> nil ->
Graph.new(graph_context, {subject, predicate, objects}) Graph.new({subject, predicate, objects}, name: graph_context)
end end
%RDF.Dataset{name: name, %RDF.Dataset{name: name,
graphs: Map.put(graphs, graph_context, new_graph)} graphs: Map.put(graphs, graph_context, new_graph)}
@ -244,7 +244,7 @@ defmodule RDF.Dataset do
%Description{} = description, graph_context) do %Description{} = description, graph_context) do
with graph_context = coerce_graph_name(graph_context) do with graph_context = coerce_graph_name(graph_context) do
updated_graph = updated_graph =
Map.get(graphs, graph_context, Graph.new(graph_context)) Map.get(graphs, graph_context, Graph.new(name: graph_context))
|> Graph.put(description) |> Graph.put(description)
%RDF.Dataset{ %RDF.Dataset{
name: name, name: name,
@ -284,7 +284,7 @@ defmodule RDF.Dataset do
{subject, graph_context}, predications) {subject, graph_context}, predications)
when is_list(predications) do when is_list(predications) do
with graph_context = coerce_graph_name(graph_context) do with graph_context = coerce_graph_name(graph_context) do
graph = Map.get(graphs, graph_context, Graph.new(graph_context)) graph = Map.get(graphs, graph_context, Graph.new(name: graph_context))
new_graphs = graphs new_graphs = graphs
|> Map.put(graph_context, Graph.put(graph, subject, predications)) |> Map.put(graph_context, Graph.put(graph, subject, predications))
%RDF.Dataset{name: name, graphs: new_graphs} %RDF.Dataset{name: name, graphs: new_graphs}
@ -397,7 +397,7 @@ defmodule RDF.Dataset do
iex> dataset = RDF.Dataset.new([{EX.S1, EX.P1, EX.O1, EX.Graph}, {EX.S2, EX.P2, EX.O2}]) iex> dataset = RDF.Dataset.new([{EX.S1, EX.P1, EX.O1, EX.Graph}, {EX.S2, EX.P2, EX.O2}])
...> RDF.Dataset.fetch(dataset, EX.Graph) ...> RDF.Dataset.fetch(dataset, EX.Graph)
{:ok, RDF.Graph.new(EX.Graph, {EX.S1, EX.P1, EX.O1})} {:ok, RDF.Graph.new({EX.S1, EX.P1, EX.O1}, name: EX.Graph)}
iex> RDF.Dataset.fetch(dataset, nil) iex> RDF.Dataset.fetch(dataset, nil)
{:ok, RDF.Graph.new({EX.S2, EX.P2, EX.O2})} {:ok, RDF.Graph.new({EX.S2, EX.P2, EX.O2})}
iex> RDF.Dataset.fetch(dataset, EX.Foo) iex> RDF.Dataset.fetch(dataset, EX.Foo)
@ -418,7 +418,7 @@ defmodule RDF.Dataset do
iex> dataset = RDF.Dataset.new([{EX.S1, EX.P1, EX.O1, EX.Graph}, {EX.S2, EX.P2, EX.O2}]) iex> dataset = RDF.Dataset.new([{EX.S1, EX.P1, EX.O1, EX.Graph}, {EX.S2, EX.P2, EX.O2}])
...> RDF.Dataset.get(dataset, EX.Graph) ...> RDF.Dataset.get(dataset, EX.Graph)
RDF.Graph.new(EX.Graph, {EX.S1, EX.P1, EX.O1}) RDF.Graph.new({EX.S1, EX.P1, EX.O1}, name: EX.Graph)
iex> RDF.Dataset.get(dataset, nil) iex> RDF.Dataset.get(dataset, nil)
RDF.Graph.new({EX.S2, EX.P2, EX.O2}) RDF.Graph.new({EX.S2, EX.P2, EX.O2})
iex> RDF.Dataset.get(dataset, EX.Foo) iex> RDF.Dataset.get(dataset, EX.Foo)
@ -472,7 +472,7 @@ defmodule RDF.Dataset do
...> RDF.Dataset.get_and_update(dataset, EX.Graph, fn current_graph -> ...> RDF.Dataset.get_and_update(dataset, EX.Graph, fn current_graph ->
...> {current_graph, {EX.S, EX.P, EX.NEW}} ...> {current_graph, {EX.S, EX.P, EX.NEW}}
...> end) ...> end)
{RDF.Graph.new(EX.Graph, {EX.S, EX.P, EX.O}), RDF.Dataset.new({EX.S, EX.P, EX.NEW, EX.Graph})} {RDF.Graph.new({EX.S, EX.P, EX.O}, name: EX.Graph), RDF.Dataset.new({EX.S, EX.P, EX.NEW, EX.Graph})}
""" """
@impl Access @impl Access
def get_and_update(%RDF.Dataset{} = dataset, graph_name, fun) do def get_and_update(%RDF.Dataset{} = dataset, graph_name, fun) do
@ -520,7 +520,7 @@ defmodule RDF.Dataset do
...> {EX.S1, EX.P1, EX.O1, EX.Graph}, ...> {EX.S1, EX.P1, EX.O1, EX.Graph},
...> {EX.S2, EX.P2, EX.O2}]) ...> {EX.S2, EX.P2, EX.O2}])
...> RDF.Dataset.pop(dataset, EX.Graph) ...> RDF.Dataset.pop(dataset, EX.Graph)
{RDF.Graph.new(EX.Graph, {EX.S1, EX.P1, EX.O1}), RDF.Dataset.new({EX.S2, EX.P2, EX.O2})} {RDF.Graph.new({EX.S1, EX.P1, EX.O1}, name: EX.Graph), RDF.Dataset.new({EX.S2, EX.P2, EX.O2})}
iex> RDF.Dataset.pop(dataset, EX.Foo) iex> RDF.Dataset.pop(dataset, EX.Foo)
{nil, dataset} {nil, dataset}
""" """

View file

@ -23,80 +23,78 @@ defmodule RDF.Graph do
@doc """ @doc """
Creates an empty unnamed `RDF.Graph`. Creates an empty unnamed `RDF.Graph`.
""" """
def new, def new, do: %RDF.Graph{}
do: %RDF.Graph{}
@doc """ @doc """
Creates an unnamed `RDF.Graph` with an initial triple. Creates an `RDF.Graph`.
If a keyword list is given an empty graph is created.
Otherwise an unnamed graph initialized with the given data is created.
See `new/2` for available arguments and the different ways to provide data.
## Examples
RDF.Graph.new({EX.S, EX.p, EX.O})
RDF.Graph.new(name: EX.GraphName)
""" """
def new({_, _, _} = triple), def new(data_or_options)
do: new() |> add(triple)
def new(data_or_options)
when is_list(data_or_options) and length(data_or_options) != 0 do
if Keyword.keyword?(data_or_options) do
new([], data_or_options)
else
new(data_or_options, [])
end
end
def new(data), do: new(data, [])
@doc """ @doc """
Creates an unnamed `RDF.Graph` with initial triples. Creates an `RDF.Graph` initialized with data.
The initial RDF triples can be provided
- as a single statement tuple
- an `RDF.Description`
- an `RDF.Graph`
- or a list with any combination of the former
Available options:
- `name`: the name of the graph to be created
## Examples
RDF.Graph.new({EX.S, EX.p, EX.O})
RDF.Graph.new({EX.S, EX.p, EX.O}, name: EX.GraphName)
RDF.Graph.new({EX.S, EX.p, [EX.O1, EX.O2]})
RDF.Graph.new([{EX.S1, EX.p1, EX.O1}, {EX.S2, EX.p2, EX.O2}])
RDF.Graph.new(RDF.Description.new(EX.S, EX.P, EX.O))
RDF.Graph.new([graph, description, triple])
""" """
def new(triples) when is_list(triples), def new(data, options)
do: new() |> add(triples)
def new(%RDF.Graph{} = graph, options) do
%RDF.Graph{graph | name: options |> Keyword.get(:name) |> coerce_graph_name()}
end
def new(data, options) do
%RDF.Graph{name: options |> Keyword.get(:name) |> coerce_graph_name()}
|> add(data)
end
@doc """ @doc """
Creates an unnamed `RDF.Graph` with a `RDF.Description`. Creates an `RDF.Graph` with initial triples.
"""
def new(%RDF.Description{} = description),
do: new() |> add(description)
@doc """ See `new/2` for available arguments.
Creates an unnamed `RDF.Graph` from another `RDF.Graph`.
""" """
def new(%RDF.Graph{descriptions: descriptions}), def new(subject, predicate, objects, options \\ []),
do: %RDF.Graph{descriptions: descriptions} do: new(options) |> add(subject, predicate, objects)
@doc """
Creates an empty unnamed `RDF.Graph`.
"""
def new(nil),
do: new()
@doc """
Creates an empty named `RDF.Graph`.
"""
def new(name),
do: %RDF.Graph{name: coerce_graph_name(name)}
@doc """
Creates a named `RDF.Graph` with an initial triple.
"""
def new(name, triple = {_, _, _}),
do: new(name) |> add(triple)
@doc """
Creates a named `RDF.Graph` with initial triples.
"""
def new(name, triples) when is_list(triples),
do: new(name) |> add(triples)
@doc """
Creates a named `RDF.Graph` with a `RDF.Description`.
"""
def new(name, %RDF.Description{} = description),
do: new(name) |> add(description)
@doc """
Creates a named `RDF.Graph` from another `RDF.Graph`.
"""
def new(name, %RDF.Graph{descriptions: descriptions}),
do: %RDF.Graph{new(name) | descriptions: descriptions}
@doc """
Creates an unnamed `RDF.Graph` with initial triples.
"""
def new(subject, predicate, objects),
do: new() |> add(subject, predicate, objects)
@doc """
Creates a named `RDF.Graph` with initial triples.
"""
def new(name, subject, predicate, objects),
do: new(name) |> add(subject, predicate, objects)
@doc """ @doc """
@ -105,7 +103,6 @@ defmodule RDF.Graph do
def add(%RDF.Graph{} = graph, subject, predicate, objects), def add(%RDF.Graph{} = graph, subject, predicate, objects),
do: add(graph, {subject, predicate, objects}) do: add(graph, {subject, predicate, objects})
@doc """ @doc """
Adds triples to a `RDF.Graph`. Adds triples to a `RDF.Graph`.
@ -113,6 +110,7 @@ defmodule RDF.Graph do
the graph name must not match graph name of the graph to which the statements the graph name must not match graph name of the graph to which the statements
are added. As opposed to that `RDF.Data.merge/2` will produce a `RDF.Dataset` are added. As opposed to that `RDF.Data.merge/2` will produce a `RDF.Dataset`
containing both graphs. containing both graphs.
""" """
def add(graph, triples) def add(graph, triples)
@ -157,6 +155,7 @@ defmodule RDF.Graph do
iex> RDF.Graph.new([{EX.S1, EX.P1, EX.O1}, {EX.S2, EX.P2, EX.O2}]) |> iex> RDF.Graph.new([{EX.S1, EX.P1, EX.O1}, {EX.S2, EX.P2, EX.O2}]) |>
...> RDF.Graph.put([{EX.S1, EX.P2, EX.O3}, {EX.S2, EX.P2, EX.O3}]) ...> RDF.Graph.put([{EX.S1, EX.P2, EX.O3}, {EX.S2, EX.P2, EX.O3}])
RDF.Graph.new([{EX.S1, EX.P1, EX.O1}, {EX.S1, EX.P2, EX.O3}, {EX.S2, EX.P2, EX.O3}]) RDF.Graph.new([{EX.S1, EX.P1, EX.O1}, {EX.S1, EX.P2, EX.O3}, {EX.S2, EX.P2, EX.O3}])
""" """
def put(graph, statements) def put(graph, statements)
@ -227,6 +226,7 @@ defmodule RDF.Graph do
RDF.Graph.new(EX.S, EX.P, EX.O2) RDF.Graph.new(EX.S, EX.P, EX.O2)
iex> RDF.Graph.new(EX.S, EX.P1, EX.O1) |> RDF.Graph.put(EX.S, EX.P2, EX.O2) iex> RDF.Graph.new(EX.S, EX.P1, EX.O1) |> RDF.Graph.put(EX.S, EX.P2, EX.O2)
RDF.Graph.new([{EX.S, EX.P1, EX.O1}, {EX.S, EX.P2, EX.O2}]) RDF.Graph.new([{EX.S, EX.P1, EX.O1}, {EX.S, EX.P2, EX.O2}])
""" """
def put(%RDF.Graph{} = graph, subject, predicate, objects), def put(%RDF.Graph{} = graph, subject, predicate, objects),
do: put(graph, {subject, predicate, objects}) do: put(graph, {subject, predicate, objects})
@ -245,6 +245,7 @@ defmodule RDF.Graph do
the graph name must not match graph name of the graph from which the statements the graph name must not match graph name of the graph from which the statements
are deleted. If you want to delete only graphs with matching names, you can are deleted. If you want to delete only graphs with matching names, you can
use `RDF.Data.delete/2`. use `RDF.Data.delete/2`.
""" """
def delete(graph, triples) def delete(graph, triples)
@ -318,6 +319,7 @@ defmodule RDF.Graph do
{:ok, RDF.Description.new({EX.S1, EX.P1, EX.O1})} {:ok, RDF.Description.new({EX.S1, EX.P1, EX.O1})}
iex> RDF.Graph.fetch(RDF.Graph.new, EX.foo) iex> RDF.Graph.fetch(RDF.Graph.new, EX.foo)
:error :error
""" """
@impl Access @impl Access
def fetch(%RDF.Graph{descriptions: descriptions}, subject) do def fetch(%RDF.Graph{descriptions: descriptions}, subject) do
@ -338,6 +340,7 @@ defmodule RDF.Graph do
nil nil
iex> RDF.Graph.get(RDF.Graph.new, EX.Foo, :bar) iex> RDF.Graph.get(RDF.Graph.new, EX.Foo, :bar)
:bar :bar
""" """
def get(%RDF.Graph{} = graph, subject, default \\ nil) do def get(%RDF.Graph{} = graph, subject, default \\ nil) do
case fetch(graph, subject) do case fetch(graph, subject) do
@ -380,6 +383,7 @@ defmodule RDF.Graph do
...> {current_description, {EX.P, EX.NEW}} ...> {current_description, {EX.P, EX.NEW}}
...> end) ...> end)
{RDF.Description.new(EX.S, EX.P, EX.O), RDF.Graph.new(EX.S, EX.P, EX.NEW)} {RDF.Description.new(EX.S, EX.P, EX.O), RDF.Graph.new(EX.S, EX.P, EX.NEW)}
""" """
@impl Access @impl Access
def get_and_update(%RDF.Graph{} = graph, subject, fun) do def get_and_update(%RDF.Graph{} = graph, subject, fun) do
@ -427,6 +431,7 @@ defmodule RDF.Graph do
{RDF.Description.new({EX.S1, EX.P1, EX.O1}), RDF.Graph.new({EX.S2, EX.P2, EX.O2})} {RDF.Description.new({EX.S1, EX.P1, EX.O1}), RDF.Graph.new({EX.S2, EX.P2, EX.O2})}
iex> RDF.Graph.pop(RDF.Graph.new({EX.S, EX.P, EX.O}), EX.Missing) iex> RDF.Graph.pop(RDF.Graph.new({EX.S, EX.P, EX.O}), EX.Missing)
{nil, RDF.Graph.new({EX.S, EX.P, EX.O})} {nil, RDF.Graph.new({EX.S, EX.P, EX.O})}
""" """
@impl Access @impl Access
def pop(%RDF.Graph{name: name, descriptions: descriptions} = graph, subject) do def pop(%RDF.Graph{name: name, descriptions: descriptions} = graph, subject) do
@ -450,6 +455,7 @@ defmodule RDF.Graph do
...> {EX.S1, EX.p2, EX.O3}]) |> ...> {EX.S1, EX.p2, EX.O3}]) |>
...> RDF.Graph.subject_count ...> RDF.Graph.subject_count
2 2
""" """
def subject_count(%RDF.Graph{descriptions: descriptions}), def subject_count(%RDF.Graph{descriptions: descriptions}),
do: Enum.count(descriptions) do: Enum.count(descriptions)
@ -465,6 +471,7 @@ defmodule RDF.Graph do
...> {EX.S1, EX.p2, EX.O3}]) |> ...> {EX.S1, EX.p2, EX.O3}]) |>
...> RDF.Graph.triple_count ...> RDF.Graph.triple_count
3 3
""" """
def triple_count(%RDF.Graph{descriptions: descriptions}) do def triple_count(%RDF.Graph{descriptions: descriptions}) do
Enum.reduce descriptions, 0, fn ({_subject, description}, count) -> Enum.reduce descriptions, 0, fn ({_subject, description}, count) ->

View file

@ -48,7 +48,7 @@ defmodule RDF.Test.Case do
def unnamed_graph, do: Graph.new def unnamed_graph, do: Graph.new
def named_graph(name \\ EX.GraphName), do: Graph.new(name) def named_graph(name \\ EX.GraphName), do: Graph.new(name: name)
def unnamed_graph?(%Graph{name: nil}), do: true def unnamed_graph?(%Graph{name: nil}), do: true
def unnamed_graph?(_), do: false def unnamed_graph?(_), do: false
@ -69,7 +69,7 @@ defmodule RDF.Test.Case do
############################### ###############################
# RDF.Graph # RDF.Dataset
def dataset, do: unnamed_dataset() def dataset, do: unnamed_dataset()

View file

@ -19,7 +19,7 @@ defmodule RDF.DataTest do
Dataset.new Dataset.new
|> Dataset.add(graph) |> Dataset.add(graph)
|> Dataset.add( |> Dataset.add(
Graph.new(EX.NamedGraph) Graph.new(name: EX.NamedGraph)
|> Graph.add(description) |> Graph.add(description)
|> Graph.add({EX.S3, EX.p3, EX.O5}) |> Graph.add({EX.S3, EX.p3, EX.O5})
|> Graph.add({EX.S, EX.p3, EX.O5})) |> Graph.add({EX.S, EX.p3, EX.O5}))
@ -206,7 +206,7 @@ defmodule RDF.DataTest do
test "merge of a dataset", %{dataset: dataset} do test "merge of a dataset", %{dataset: dataset} do
assert RDF.Data.merge(Graph.new({EX.Other, EX.p1, EX.O3}), dataset) == assert RDF.Data.merge(Graph.new({EX.Other, EX.p1, EX.O3}), dataset) ==
Dataset.add(dataset, {EX.Other, EX.p1, EX.O3}) Dataset.add(dataset, {EX.Other, EX.p1, EX.O3})
assert RDF.Data.merge(Graph.new(EX.NamedGraph, {EX.Other, EX.p1, EX.O3}), dataset) == assert RDF.Data.merge(Graph.new({EX.Other, EX.p1, EX.O3}, name: EX.NamedGraph), dataset) ==
Dataset.add(dataset, {EX.Other, EX.p1, EX.O3, EX.NamedGraph}) Dataset.add(dataset, {EX.Other, EX.p1, EX.O3, EX.NamedGraph})
end end
@ -328,7 +328,7 @@ defmodule RDF.DataTest do
test "merge of a graph", %{dataset: dataset} do test "merge of a graph", %{dataset: dataset} do
assert RDF.Data.merge(dataset, Graph.new({EX.Other, EX.p1, EX.O3})) == assert RDF.Data.merge(dataset, Graph.new({EX.Other, EX.p1, EX.O3})) ==
Dataset.add(dataset, {EX.Other, EX.p1, EX.O3}) Dataset.add(dataset, {EX.Other, EX.p1, EX.O3})
assert RDF.Data.merge(dataset, Graph.new(EX.NamedGraph, {EX.Other, EX.p1, EX.O3})) == assert RDF.Data.merge(dataset, Graph.new({EX.Other, EX.p1, EX.O3}, name: EX.NamedGraph)) ==
Dataset.add(dataset, {EX.Other, EX.p1, EX.O3, EX.NamedGraph}) Dataset.add(dataset, {EX.Other, EX.p1, EX.O3, EX.NamedGraph})
end end

View file

@ -81,13 +81,13 @@ defmodule RDF.DatasetTest do
assert dataset_includes_statement?(ds, {EX.Subject, EX.predicate, EX.Object}) assert dataset_includes_statement?(ds, {EX.Subject, EX.predicate, EX.Object})
end end
test "creating a named dataset with an inital graph" do test "creating a named dataset with an initial graph" do
ds = Dataset.new(EX.DatasetName, Graph.new({EX.Subject, EX.predicate, EX.Object})) ds = Dataset.new(EX.DatasetName, Graph.new({EX.Subject, EX.predicate, EX.Object}))
assert named_dataset?(ds, iri(EX.DatasetName)) assert named_dataset?(ds, iri(EX.DatasetName))
assert unnamed_graph?(Dataset.default_graph(ds)) assert unnamed_graph?(Dataset.default_graph(ds))
assert dataset_includes_statement?(ds, {EX.Subject, EX.predicate, EX.Object}) assert dataset_includes_statement?(ds, {EX.Subject, EX.predicate, EX.Object})
ds = Dataset.new(EX.DatasetName, Graph.new(EX.GraphName, {EX.Subject, EX.predicate, EX.Object})) ds = Dataset.new(EX.DatasetName, Graph.new({EX.Subject, EX.predicate, EX.Object}, name: EX.GraphName))
assert named_dataset?(ds, iri(EX.DatasetName)) assert named_dataset?(ds, iri(EX.DatasetName))
assert unnamed_graph?(Dataset.default_graph(ds)) assert unnamed_graph?(Dataset.default_graph(ds))
assert named_graph?(Dataset.graph(ds, EX.GraphName), iri(EX.GraphName)) assert named_graph?(Dataset.graph(ds, EX.GraphName), iri(EX.GraphName))
@ -100,7 +100,7 @@ defmodule RDF.DatasetTest do
assert unnamed_graph?(Dataset.default_graph(ds)) assert unnamed_graph?(Dataset.default_graph(ds))
assert dataset_includes_statement?(ds, {EX.Subject, EX.predicate, EX.Object}) assert dataset_includes_statement?(ds, {EX.Subject, EX.predicate, EX.Object})
ds = Dataset.new(Graph.new(EX.GraphName, {EX.Subject, EX.predicate, EX.Object})) ds = Dataset.new(Graph.new({EX.Subject, EX.predicate, EX.Object}, name: EX.GraphName))
assert unnamed_dataset?(ds) assert unnamed_dataset?(ds)
assert unnamed_graph?(Dataset.default_graph(ds)) assert unnamed_graph?(Dataset.default_graph(ds))
assert named_graph?(Dataset.graph(ds, EX.GraphName), iri(EX.GraphName)) assert named_graph?(Dataset.graph(ds, EX.GraphName), iri(EX.GraphName))
@ -293,17 +293,17 @@ defmodule RDF.DatasetTest do
end end
test "a named Graph without specification of the default context" do test "a named Graph without specification of the default context" do
ds = Dataset.add(dataset(), Graph.new(EX.Graph1, [ ds = Dataset.add(dataset(), Graph.new([
{EX.Subject1, EX.predicate1, EX.Object1}, {EX.Subject1, EX.predicate1, EX.Object1},
{EX.Subject1, EX.predicate2, EX.Object2}, {EX.Subject1, EX.predicate2, EX.Object2},
])) ], name: EX.Graph1))
assert Dataset.graph(ds, EX.Graph1) assert Dataset.graph(ds, EX.Graph1)
assert named_graph?(Dataset.graph(ds, EX.Graph1), iri(EX.Graph1)) assert named_graph?(Dataset.graph(ds, EX.Graph1), iri(EX.Graph1))
assert unnamed_graph?(Dataset.default_graph(ds)) assert unnamed_graph?(Dataset.default_graph(ds))
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate1, EX.Object1, EX.Graph1}) assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate1, EX.Object1, EX.Graph1})
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate2, EX.Object2, EX.Graph1}) assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate2, EX.Object2, EX.Graph1})
ds = Dataset.add(ds, Graph.new(EX.Graph2, {EX.Subject1, EX.predicate2, EX.Object3})) ds = Dataset.add(ds, Graph.new({EX.Subject1, EX.predicate2, EX.Object3}, name: EX.Graph2))
assert Dataset.graph(ds, EX.Graph2) assert Dataset.graph(ds, EX.Graph2)
assert named_graph?(Dataset.graph(ds, EX.Graph2), iri(EX.Graph2)) assert named_graph?(Dataset.graph(ds, EX.Graph2), iri(EX.Graph2))
assert unnamed_graph?(Dataset.default_graph(ds)) assert unnamed_graph?(Dataset.default_graph(ds))
@ -314,16 +314,16 @@ defmodule RDF.DatasetTest do
end end
test "a named Graph with specification of the default context" do test "a named Graph with specification of the default context" do
ds = Dataset.add(dataset(), Graph.new(EX.Graph1, [ ds = Dataset.add(dataset(), Graph.new([
{EX.Subject1, EX.predicate1, EX.Object1}, {EX.Subject1, EX.predicate1, EX.Object1},
{EX.Subject1, EX.predicate2, EX.Object2}, {EX.Subject1, EX.predicate2, EX.Object2},
]), nil) ], name: EX.Graph1), nil)
refute Dataset.graph(ds, EX.Graph1) refute Dataset.graph(ds, EX.Graph1)
assert unnamed_graph?(Dataset.default_graph(ds)) assert unnamed_graph?(Dataset.default_graph(ds))
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate1, EX.Object1}) assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate1, EX.Object1})
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate2, EX.Object2}) assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate2, EX.Object2})
ds = Dataset.add(ds, Graph.new(EX.Graph2, {EX.Subject1, EX.predicate2, EX.Object3}), nil) ds = Dataset.add(ds, Graph.new({EX.Subject1, EX.predicate2, EX.Object3}, name: EX.Graph2), nil)
refute Dataset.graph(ds, EX.Graph2) refute Dataset.graph(ds, EX.Graph2)
assert unnamed_graph?(Dataset.default_graph(ds)) assert unnamed_graph?(Dataset.default_graph(ds))
assert Enum.count(ds) == 3 assert Enum.count(ds) == 3
@ -331,7 +331,7 @@ defmodule RDF.DatasetTest do
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate2, EX.Object2}) assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate2, EX.Object2})
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate2, EX.Object3}) assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate2, EX.Object3})
ds = Dataset.add(ds, Graph.new(EX.Graph3, {EX.Subject1, EX.predicate2, EX.Object3}), EX.Graph) ds = Dataset.add(ds, Graph.new({EX.Subject1, EX.predicate2, EX.Object3}, name: EX.Graph3), EX.Graph)
assert named_graph?(Dataset.graph(ds, EX.Graph), iri(EX.Graph)) assert named_graph?(Dataset.graph(ds, EX.Graph), iri(EX.Graph))
assert Enum.count(ds) == 4 assert Enum.count(ds) == 4
assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate1, EX.Object1}) assert dataset_includes_statement?(ds, {EX.Subject1, EX.predicate1, EX.Object1})
@ -409,8 +409,8 @@ defmodule RDF.DatasetTest do
ds = Dataset.new([{EX.S1, EX.P1, EX.O1}, {EX.S2, EX.P2, EX.O2}]) ds = Dataset.new([{EX.S1, EX.P1, EX.O1}, {EX.S2, EX.P2, EX.O2}])
|> RDF.Dataset.add([ |> RDF.Dataset.add([
Graph.new([{EX.S1, EX.P1, EX.O1}, {EX.S1, EX.P2, bnode(:foo)}]), Graph.new([{EX.S1, EX.P1, EX.O1}, {EX.S1, EX.P2, bnode(:foo)}]),
Graph.new(nil, {EX.S1, EX.P2, EX.O3}), Graph.new({EX.S1, EX.P2, EX.O3}),
Graph.new(EX.Graph, [{EX.S1, EX.P2, EX.O2}, {EX.S2, EX.P2, EX.O2}]) Graph.new([{EX.S1, EX.P2, EX.O2}, {EX.S2, EX.P2, EX.O2}], name: EX.Graph)
]) ])
assert Enum.count(ds) == 6 assert Enum.count(ds) == 6
@ -513,7 +513,7 @@ defmodule RDF.DatasetTest do
test "a named Graph" do test "a named Graph" do
ds = Dataset.new( ds = Dataset.new(
Graph.new(EX.GraphName, [{EX.S1, EX.P1, EX.O1}, {EX.S2, EX.P2, EX.O2}, {EX.S1, EX.P3, EX.O3}])) Graph.new([{EX.S1, EX.P1, EX.O1}, {EX.S2, EX.P2, EX.O2}, {EX.S1, EX.P3, EX.O3}], name: EX.GraphName))
|> RDF.Dataset.put( |> RDF.Dataset.put(
Graph.new([{EX.S1, EX.P3, EX.O4}, {EX.S1, EX.P2, bnode(:foo)}]), EX.GraphName) Graph.new([{EX.S1, EX.P3, EX.O4}, {EX.S1, EX.P2, bnode(:foo)}]), EX.GraphName)
@ -602,8 +602,8 @@ defmodule RDF.DatasetTest do
assert Dataset.delete(dataset1, Graph.new({EX.S1, EX.p1, EX.O1})) == Dataset.new assert Dataset.delete(dataset1, Graph.new({EX.S1, EX.p1, EX.O1})) == Dataset.new
assert Dataset.delete(dataset2, Graph.new({EX.S1, EX.p1, EX.O1})) == assert Dataset.delete(dataset2, Graph.new({EX.S1, EX.p1, EX.O1})) ==
Dataset.new({EX.S2, EX.p2, EX.O2, EX.Graph}) Dataset.new({EX.S2, EX.p2, EX.O2, EX.Graph})
assert Dataset.delete(dataset2, Graph.new(EX.Graph, {EX.S2, EX.p2, EX.O2})) == dataset1 assert Dataset.delete(dataset2, Graph.new({EX.S2, EX.p2, EX.O2}, name: EX.Graph)) == dataset1
assert Dataset.delete(dataset2, Graph.new(EX.Graph, {EX.S2, EX.p2, EX.O2})) == dataset1 assert Dataset.delete(dataset2, Graph.new({EX.S2, EX.p2, EX.O2}, name: EX.Graph)) == dataset1
assert Dataset.delete(dataset2, Graph.new({EX.S2, EX.p2, EX.O2}), EX.Graph) == dataset1 assert Dataset.delete(dataset2, Graph.new({EX.S2, EX.p2, EX.O2}), EX.Graph) == dataset1
assert Dataset.delete(dataset2, Graph.new({EX.S2, EX.p2, EX.O2}), EX.Graph) == dataset1 assert Dataset.delete(dataset2, Graph.new({EX.S2, EX.p2, EX.O2}), EX.Graph) == dataset1
assert Dataset.delete(dataset3, Graph.new([ assert Dataset.delete(dataset3, Graph.new([
@ -614,11 +614,11 @@ defmodule RDF.DatasetTest do
{EX.S2, EX.p2, [EX.O1, EX.O2], EX.Graph1}, {EX.S2, EX.p2, [EX.O1, EX.O2], EX.Graph1},
{EX.S3, EX.p3, [~B<foo>, ~L"bar"], EX.Graph2}, {EX.S3, EX.p3, [~B<foo>, ~L"bar"], EX.Graph2},
]) ])
assert Dataset.delete(dataset3, Graph.new(EX.Graph2, [ assert Dataset.delete(dataset3, Graph.new([
{EX.S1, EX.p1, [EX.O1, EX.O2]}, {EX.S1, EX.p1, [EX.O1, EX.O2]},
{EX.S2, EX.p2, EX.O3}, {EX.S2, EX.p2, EX.O3},
{EX.S3, EX.p3, ~B<foo>}, {EX.S3, EX.p3, ~B<foo>},
])) == Dataset.new([ ], name: EX.Graph2)) == Dataset.new([
{EX.S1, EX.p1, EX.O1}, {EX.S1, EX.p1, EX.O1},
{EX.S2, EX.p2, [EX.O1, EX.O2], EX.Graph1}, {EX.S2, EX.p2, [EX.O1, EX.O2], EX.Graph1},
{EX.S3, EX.p3, [~L"bar"], EX.Graph2}, {EX.S3, EX.p3, [~L"bar"], EX.Graph2},
@ -805,7 +805,7 @@ defmodule RDF.DatasetTest do
test "access with the [] operator" do test "access with the [] operator" do
assert Dataset.new[EX.Graph] == nil assert Dataset.new[EX.Graph] == nil
assert Dataset.new({EX.S, EX.p, EX.O, EX.Graph})[EX.Graph] == assert Dataset.new({EX.S, EX.p, EX.O, EX.Graph})[EX.Graph] ==
Graph.new(EX.Graph, {EX.S, EX.p, EX.O}) Graph.new({EX.S, EX.p, EX.O}, name: EX.Graph)
end end
end end

View file

@ -36,11 +36,11 @@ defmodule RDF.GraphTest do
end end
test "creating a named graph with an initial triple" do test "creating a named graph with an initial triple" do
g = Graph.new(EX.GraphName, {EX.Subject, EX.predicate, EX.Object}) g = Graph.new({EX.Subject, EX.predicate, EX.Object}, name: EX.GraphName)
assert named_graph?(g, iri(EX.GraphName)) assert named_graph?(g, iri(EX.GraphName))
assert graph_includes_statement?(g, {EX.Subject, EX.predicate, EX.Object}) assert graph_includes_statement?(g, {EX.Subject, EX.predicate, EX.Object})
g = Graph.new(EX.GraphName, EX.Subject, EX.predicate, EX.Object) g = Graph.new(EX.Subject, EX.predicate, EX.Object, name: EX.GraphName)
assert named_graph?(g, iri(EX.GraphName)) assert named_graph?(g, iri(EX.GraphName))
assert graph_includes_statement?(g, {EX.Subject, EX.predicate, EX.Object}) assert graph_includes_statement?(g, {EX.Subject, EX.predicate, EX.Object})
end end
@ -59,20 +59,23 @@ defmodule RDF.GraphTest do
end end
test "creating a named graph with a list of initial triples" do test "creating a named graph with a list of initial triples" do
g = Graph.new(EX.GraphName, [{EX.Subject, EX.predicate1, EX.Object1}, g = Graph.new([{EX.Subject, EX.predicate1, EX.Object1},
{EX.Subject, EX.predicate2, EX.Object2}]) {EX.Subject, EX.predicate2, EX.Object2}],
name: EX.GraphName)
assert named_graph?(g, iri(EX.GraphName)) assert named_graph?(g, iri(EX.GraphName))
assert graph_includes_statement?(g, {EX.Subject, EX.predicate1, EX.Object1}) assert graph_includes_statement?(g, {EX.Subject, EX.predicate1, EX.Object1})
assert graph_includes_statement?(g, {EX.Subject, EX.predicate2, EX.Object2}) assert graph_includes_statement?(g, {EX.Subject, EX.predicate2, EX.Object2})
g = Graph.new(EX.GraphName, EX.Subject, EX.predicate, [EX.Object1, EX.Object2]) g = Graph.new(EX.Subject, EX.predicate, [EX.Object1, EX.Object2],
name: EX.GraphName)
assert named_graph?(g, iri(EX.GraphName)) assert named_graph?(g, iri(EX.GraphName))
assert graph_includes_statement?(g, {EX.Subject, EX.predicate, EX.Object1}) assert graph_includes_statement?(g, {EX.Subject, EX.predicate, EX.Object1})
assert graph_includes_statement?(g, {EX.Subject, EX.predicate, EX.Object2}) assert graph_includes_statement?(g, {EX.Subject, EX.predicate, EX.Object2})
end end
test "creating a named graph with an initial description" do test "creating a named graph with an initial description" do
g = Graph.new(EX.GraphName, Description.new({EX.Subject, EX.predicate, EX.Object})) g = Graph.new(Description.new({EX.Subject, EX.predicate, EX.Object}),
name: EX.GraphName)
assert named_graph?(g, iri(EX.GraphName)) assert named_graph?(g, iri(EX.GraphName))
assert graph_includes_statement?(g, {EX.Subject, EX.predicate, EX.Object}) assert graph_includes_statement?(g, {EX.Subject, EX.predicate, EX.Object})
end end
@ -84,11 +87,13 @@ defmodule RDF.GraphTest do
end end
test "creating a named graph from another graph" do test "creating a named graph from another graph" do
g = Graph.new(EX.GraphName, Graph.new({EX.Subject, EX.predicate, EX.Object})) g = Graph.new(Graph.new({EX.Subject, EX.predicate, EX.Object}),
name: EX.GraphName)
assert named_graph?(g, iri(EX.GraphName)) assert named_graph?(g, iri(EX.GraphName))
assert graph_includes_statement?(g, {EX.Subject, EX.predicate, EX.Object}) assert graph_includes_statement?(g, {EX.Subject, EX.predicate, EX.Object})
g = Graph.new(EX.GraphName, Graph.new(EX.OtherGraphName, {EX.Subject, EX.predicate, EX.Object})) g = Graph.new(Graph.new({EX.Subject, EX.predicate, EX.Object}, name: EX.OtherGraphName),
name: EX.GraphName)
assert named_graph?(g, iri(EX.GraphName)) assert named_graph?(g, iri(EX.GraphName))
assert graph_includes_statement?(g, {EX.Subject, EX.predicate, EX.Object}) assert graph_includes_statement?(g, {EX.Subject, EX.predicate, EX.Object})
end end
@ -98,10 +103,15 @@ defmodule RDF.GraphTest do
assert unnamed_graph?(g) assert unnamed_graph?(g)
assert graph_includes_statement?(g, {EX.Subject, EX.predicate, EX.Object}) assert graph_includes_statement?(g, {EX.Subject, EX.predicate, EX.Object})
g = Graph.new(Graph.new(EX.OtherGraphName, {EX.Subject, EX.predicate, EX.Object})) g = Graph.new(Graph.new({EX.Subject, EX.predicate, EX.Object}, name: EX.OtherGraphName))
assert unnamed_graph?(g) assert unnamed_graph?(g)
assert graph_includes_statement?(g, {EX.Subject, EX.predicate, EX.Object}) assert graph_includes_statement?(g, {EX.Subject, EX.predicate, EX.Object})
end end
@tag skip: "TODO: "
test "with prefixes" do
# assert Graph.new prefixes
end
end end
describe "add" do describe "add" do
@ -251,7 +261,7 @@ defmodule RDF.GraphTest do
setup do setup do
{:ok, {:ok,
graph1: Graph.new({EX.S, EX.p, EX.O}), graph1: Graph.new({EX.S, EX.p, EX.O}),
graph2: Graph.new(EX.Graph, {EX.S, EX.p, [EX.O1, EX.O2]}), graph2: Graph.new({EX.S, EX.p, [EX.O1, EX.O2]}, name: EX.Graph),
graph3: Graph.new([ graph3: Graph.new([
{EX.S1, EX.p1, [EX.O1, EX.O2]}, {EX.S1, EX.p1, [EX.O1, EX.O2]},
{EX.S2, EX.p2, EX.O3}, {EX.S2, EX.p2, EX.O3},
@ -265,16 +275,16 @@ defmodule RDF.GraphTest do
assert Graph.delete(Graph.new, {EX.S, EX.p, EX.O}) == Graph.new assert Graph.delete(Graph.new, {EX.S, EX.p, EX.O}) == Graph.new
assert Graph.delete(graph1, {EX.S, EX.p, EX.O}) == Graph.new assert Graph.delete(graph1, {EX.S, EX.p, EX.O}) == Graph.new
assert Graph.delete(graph2, {EX.S, EX.p, EX.O1}) == assert Graph.delete(graph2, {EX.S, EX.p, EX.O1}) ==
Graph.new(EX.Graph, {EX.S, EX.p, EX.O2}) Graph.new({EX.S, EX.p, EX.O2}, name: EX.Graph)
assert Graph.delete(graph2, {EX.S, EX.p, EX.O1}) == assert Graph.delete(graph2, {EX.S, EX.p, EX.O1}) ==
Graph.new(EX.Graph, {EX.S, EX.p, EX.O2}) Graph.new({EX.S, EX.p, EX.O2}, name: EX.Graph)
end end
test "multiple statements with a triple with multiple objects", test "multiple statements with a triple with multiple objects",
%{graph1: graph1, graph2: graph2} do %{graph1: graph1, graph2: graph2} do
assert Graph.delete(Graph.new, {EX.S, EX.p, [EX.O1, EX.O2]}) == Graph.new assert Graph.delete(Graph.new, {EX.S, EX.p, [EX.O1, EX.O2]}) == Graph.new
assert Graph.delete(graph1, {EX.S, EX.p, [EX.O, EX.O2]}) == Graph.new assert Graph.delete(graph1, {EX.S, EX.p, [EX.O, EX.O2]}) == Graph.new
assert Graph.delete(graph2, {EX.S, EX.p, [EX.O1, EX.O2]}) == Graph.new(EX.Graph) assert Graph.delete(graph2, {EX.S, EX.p, [EX.O1, EX.O2]}) == Graph.new(name: EX.Graph)
end end
test "multiple statements with a list of triples", test "multiple statements with a list of triples",
@ -282,7 +292,7 @@ defmodule RDF.GraphTest do
assert Graph.delete(graph1, [{EX.S, EX.p, EX.O}, assert Graph.delete(graph1, [{EX.S, EX.p, EX.O},
{EX.S, EX.p, EX.O2}]) == Graph.new {EX.S, EX.p, EX.O2}]) == Graph.new
assert Graph.delete(graph2, [{EX.S, EX.p, EX.O1}, assert Graph.delete(graph2, [{EX.S, EX.p, EX.O1},
{EX.S, EX.p, EX.O2}]) == Graph.new(EX.Graph) {EX.S, EX.p, EX.O2}]) == Graph.new(name: EX.Graph)
assert Graph.delete(graph3, [ assert Graph.delete(graph3, [
{EX.S1, EX.p1, [EX.O1, EX.O2]}, {EX.S1, EX.p1, [EX.O1, EX.O2]},
{EX.S2, EX.p2, EX.O3}, {EX.S2, EX.p2, EX.O3},
@ -294,7 +304,7 @@ defmodule RDF.GraphTest do
assert Graph.delete(graph1, Description.new(EX.S, assert Graph.delete(graph1, Description.new(EX.S,
[{EX.p, EX.O}, {EX.p2, EX.O2}])) == Graph.new [{EX.p, EX.O}, {EX.p2, EX.O2}])) == Graph.new
assert Graph.delete(graph2, Description.new(EX.S, EX.p, [EX.O1, EX.O2])) == assert Graph.delete(graph2, Description.new(EX.S, EX.p, [EX.O1, EX.O2])) ==
Graph.new(EX.Graph) Graph.new(name: EX.Graph)
assert Graph.delete(graph3, Description.new(EX.S3, EX.p3, ~B<foo>)) == assert Graph.delete(graph3, Description.new(EX.S3, EX.p3, ~B<foo>)) ==
Graph.new([ Graph.new([
{EX.S1, EX.p1, [EX.O1, EX.O2]}, {EX.S1, EX.p1, [EX.O1, EX.O2]},
@ -307,8 +317,9 @@ defmodule RDF.GraphTest do
%{graph1: graph1, graph2: graph2, graph3: graph3} do %{graph1: graph1, graph2: graph2, graph3: graph3} do
assert Graph.delete(graph1, graph2) == graph1 assert Graph.delete(graph1, graph2) == graph1
assert Graph.delete(graph1, graph1) == Graph.new assert Graph.delete(graph1, graph1) == Graph.new
assert Graph.delete(graph2, Graph.new(EX.Graph, {EX.S, EX.p, [EX.O1, EX.O3]})) == assert Graph.delete(graph2, Graph.new({EX.S, EX.p, [EX.O1, EX.O3]},
Graph.new(EX.Graph, {EX.S, EX.p, EX.O2}) name: EX.Graph)) ==
Graph.new({EX.S, EX.p, EX.O2}, name: EX.Graph)
assert Graph.delete(graph3, Graph.new([ assert Graph.delete(graph3, Graph.new([
{EX.S1, EX.p1, [EX.O1, EX.O2]}, {EX.S1, EX.p1, [EX.O1, EX.O2]},
{EX.S2, EX.p2, EX.O3}, {EX.S2, EX.p2, EX.O3},
@ -322,7 +333,7 @@ defmodule RDF.GraphTest do
describe "delete_subjects" do describe "delete_subjects" do
setup do setup do
{:ok, {:ok,
graph1: Graph.new(EX.Graph, {EX.S, EX.p, [EX.O1, EX.O2]}), graph1: Graph.new({EX.S, EX.p, [EX.O1, EX.O2]}, name: EX.Graph),
graph2: Graph.new([ graph2: Graph.new([
{EX.S1, EX.p1, [EX.O1, EX.O2]}, {EX.S1, EX.p1, [EX.O1, EX.O2]},
{EX.S2, EX.p2, EX.O3}, {EX.S2, EX.p2, EX.O3},
@ -333,11 +344,11 @@ defmodule RDF.GraphTest do
test "a single subject", %{graph1: graph1} do test "a single subject", %{graph1: graph1} do
assert Graph.delete_subjects(graph1, EX.Other) == graph1 assert Graph.delete_subjects(graph1, EX.Other) == graph1
assert Graph.delete_subjects(graph1, EX.S) == Graph.new(EX.Graph) assert Graph.delete_subjects(graph1, EX.S) == Graph.new(name: EX.Graph)
end end
test "a list of subjects", %{graph1: graph1, graph2: graph2} do test "a list of subjects", %{graph1: graph1, graph2: graph2} do
assert Graph.delete_subjects(graph1, [EX.S, EX.Other]) == Graph.new(EX.Graph) assert Graph.delete_subjects(graph1, [EX.S, EX.Other]) == Graph.new(name: EX.Graph)
assert Graph.delete_subjects(graph2, [EX.S1, EX.S2, EX.S3]) == Graph.new assert Graph.delete_subjects(graph2, [EX.S1, EX.S2, EX.S3]) == Graph.new
end end
end end
@ -394,7 +405,7 @@ defmodule RDF.GraphTest do
describe "Enumerable protocol" do describe "Enumerable protocol" do
test "Enum.count" do test "Enum.count" do
assert Enum.count(Graph.new EX.foo) == 0 assert Enum.count(Graph.new(name: EX.foo)) == 0
assert Enum.count(Graph.new {EX.S, EX.p, EX.O}) == 1 assert Enum.count(Graph.new {EX.S, EX.p, EX.O}) == 1
assert Enum.count(Graph.new [{EX.S, EX.p, EX.O1}, {EX.S, EX.p, EX.O2}]) == 2 assert Enum.count(Graph.new [{EX.S, EX.p, EX.O1}, {EX.S, EX.p, EX.O2}]) == 2