Add ordering of descriptions to Turtle encoder
This commit is contained in:
parent
eeffceb16d
commit
75b84254f4
3 changed files with 87 additions and 1 deletions
|
@ -18,6 +18,10 @@ defmodule RDF.Turtle.Encoder do
|
|||
@rdf_type RDF.type
|
||||
@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)
|
||||
|
||||
# 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")]
|
||||
@ordered_properties MapSet.new(@predicate_order)
|
||||
|
||||
|
@ -78,11 +82,52 @@ defmodule RDF.Turtle.Encoder do
|
|||
defp graph_statements(state) do
|
||||
State.data(state)
|
||||
|> RDF.Data.descriptions
|
||||
|> order_descriptions(state)
|
||||
|> Enum.map(&description_statements(&1, state))
|
||||
|> Enum.reject(&is_nil/1)
|
||||
|> Enum.join("\n")
|
||||
end
|
||||
|
||||
defp order_descriptions(descriptions, state) do
|
||||
base_uri = State.base_uri(state)
|
||||
group =
|
||||
Enum.group_by descriptions, fn
|
||||
%Description{subject: ^base_uri} ->
|
||||
:base
|
||||
description ->
|
||||
with types when not is_nil(types) <- description.predications[@rdf_type] do
|
||||
Enum.find @top_classes, :other, fn top_class ->
|
||||
Map.has_key?(types, top_class)
|
||||
end
|
||||
else
|
||||
_ -> :other
|
||||
end
|
||||
end
|
||||
ordered_descriptions = (
|
||||
@top_classes
|
||||
|> Stream.map(fn top_class -> group[top_class] end)
|
||||
|> Stream.reject(&is_nil/1)
|
||||
|> Stream.map(&sort_description_group/1)
|
||||
|> Enum.reduce([], fn class_group, ordered_descriptions ->
|
||||
ordered_descriptions ++ class_group
|
||||
end)
|
||||
) ++ (group |> Map.get(:other, []) |> sort_description_group())
|
||||
|
||||
case group[:base] do
|
||||
[base] -> [base | ordered_descriptions]
|
||||
_ -> ordered_descriptions
|
||||
end
|
||||
end
|
||||
|
||||
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: s1}, %Description{subject: s2} ->
|
||||
to_string(s1) < to_string(s2)
|
||||
end
|
||||
end
|
||||
|
||||
defp description_statements(description, state, nesting \\ 0) do
|
||||
with %BlankNode{} <- description.subject,
|
||||
ref_count when ref_count < 2 <-
|
||||
|
|
|
@ -22,6 +22,14 @@ defmodule RDF.Turtle.Encoder.State do
|
|||
bnode_ref_counter(state) |> Map.get(bnode, 0)
|
||||
end
|
||||
|
||||
def base_uri(state) do
|
||||
with {:ok, base} <- base(state) do
|
||||
RDF.uri(base)
|
||||
else
|
||||
_ -> nil
|
||||
end
|
||||
end
|
||||
|
||||
def list_values(head, state), do: Agent.get(state, &(&1.list_values[head]))
|
||||
|
||||
def preprocess(state) do
|
||||
|
|
|
@ -6,7 +6,7 @@ defmodule RDF.Turtle.EncoderTest do
|
|||
doctest Turtle.Encoder
|
||||
|
||||
alias RDF.Graph
|
||||
alias RDF.NS.XSD
|
||||
alias RDF.NS.{XSD, RDFS, OWL}
|
||||
|
||||
import RDF.Sigils
|
||||
|
||||
|
@ -101,6 +101,39 @@ defmodule RDF.Turtle.EncoderTest do
|
|||
<http://example.org/#p1> _:1, _:bar, _:foo .
|
||||
"""
|
||||
end
|
||||
|
||||
test "ordering of descriptions" do
|
||||
assert Turtle.Encoder.encode!(Graph.new([
|
||||
{EX.__base_uri__, 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__,
|
||||
prefixes: %{
|
||||
rdf: RDF.__base_uri__,
|
||||
rdfs: RDFS.__base_uri__,
|
||||
owl: OWL.__base_uri__,
|
||||
}) ==
|
||||
"""
|
||||
@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__)}> .
|
||||
|
||||
<>
|
||||
a owl:Ontology .
|
||||
|
||||
<S2>
|
||||
a rdfs:Class .
|
||||
|
||||
<S1>
|
||||
a <O> .
|
||||
|
||||
<S3>
|
||||
a rdf:Property .
|
||||
"""
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue