Skip to content

Commit

Permalink
Update link to JSON-LD* and consolidate rdfstar mode.
Browse files Browse the repository at this point in the history
  • Loading branch information
gkellogg committed Dec 12, 2020
1 parent 0f71200 commit 40655ec
Show file tree
Hide file tree
Showing 7 changed files with 24 additions and 107 deletions.
17 changes: 5 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ JSON::LD can now be used to create a _context_ from an RDFS/OWL definition, and

* If the [jsonlint][] gem is installed, it will be used when validating an input document.
* If available, uses [Nokogiri][] and/or [Nokogumbo][] for parsing HTML, falls back to REXML otherwise.
* Provisional support for [JSON-LD*][RDF*].
* Provisional support for [JSON-LD*][JSON-LD*].

[Implementation Report](file.earl.html)

Expand All @@ -38,7 +38,7 @@ The [MultiJson](https://rubygems.org/gems/multi_json) gem is used for parsing JS

### JSON-LD* (RDFStar)

The {JSON::LD::API.toRdf} and {JSON::LD::API.fromRdf} API methods, along with the {JSON::LD::Reader} and {JSON::LD::Writer}, include provisional support for [JSON-LD*][RDF*].
The {JSON::LD::API.toRdf} and {JSON::LD::API.fromRdf} API methods, along with the {JSON::LD::Reader} and {JSON::LD::Writer}, include provisional support for [JSON-LD*][JSON-LD*].

Internally, an `RDF::Statement` is treated as another resource, along with `RDF::URI` and `RDF::Node`, which allows an `RDF::Statement` to have a `#subject` or `#object` which is also an `RDF::Statement`.

Expand Down Expand Up @@ -82,17 +82,10 @@ By default, {JSON::LD::API.toRdf} (and {JSON::LD::Reader}) will reject a documen
graph = RDF::Graph.new << JSON::LD::API.toRdf(input)
# => JSON::LD::JsonLdError::InvalidIdValue

{JSON::LD::API.toRdf} (and {JSON::LD::Reader}) support a `rdfstar` option with either `:PG` (Property Graph) or `:SA` (Separate Assertions) modes. In `:PG` mode, statements that are used in the subject or object positions are also implicitly added to the graph:
{JSON::LD::API.toRdf} (and {JSON::LD::Reader}) support a boolean valued `rdfstar` option; only one statement is asserted, although the reified statement is contained within the graph.

graph = RDF::Graph.new do |graph|
JSON::LD::Reader.new(jsonld, rdfstar: :PG) {|reader| graph << reader}
end
graph.count #=> 2

When using the `:SA` mode, only one statement is asserted, although the reified statement is contained within the graph.

graph = RDF::Graph.new do |graph|
JSON::LD::Reader.new(jsonld, rdfstar: :PG) {|reader| graph << reader}
JSON::LD::Reader.new(jsonld, rdfstar: true) {|reader| graph << reader}
end
graph.count #=> 1

Expand Down Expand Up @@ -629,7 +622,7 @@ see <https://unlicense.org/> or the accompanying {file:UNLICENSE} file.
[YARD-GS]: https://rubydoc.info/docs/yard/file/docs/GettingStarted.md
[PDD]: https://unlicense.org/#unlicensing-contributions
[RDF.rb]: https://rubygems.org/gems/rdf
[RDF*]: https://lists.w3.org/Archives/Public/public-rdf-star/
[JSON-LD*]: https://json-ld.github.io/json-ld-star/
[Rack::LinkedData]: https://rubygems.org/gems/rack-linkeddata
[Backports]: https://rubygems.org/gems/backports
[JSON-LD]: https://www.w3.org/TR/json-ld11/ "JSON-LD 1.1"
Expand Down
9 changes: 1 addition & 8 deletions lib/json/ld/api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,8 @@ class API
# @option options [String] :processingMode
# Processing mode, json-ld-1.0 or json-ld-1.1.
# If `processingMode` is not specified, a mode of `json-ld-1.0` or `json-ld-1.1` is set, the context used for `expansion` or `compaction`.
# @option options [:PG, :SA] rdfstar (nil)
# @option options [Boolean] rdfstar (false)
# support parsing JSON-LD* statement resources.
# If `:PG`, referenced statements are also emitted (toRdf).
# If `:SA`, referenced statements are not emitted.
# @option options [Boolean] :rename_bnodes (true)
# Rename bnodes as part of expansion, or keep them the same.
# @option options [Boolean] :unique_bnodes (false)
Expand Down Expand Up @@ -502,11 +500,6 @@ def self.toRdf(input, expanded: false, **options, &block)
end

yield statement

# If in Property Graph mode for RDF* and statement has an embedded triple, yield those embedded triples as well.
if options[:rdfstar] == :PG && statement.to_a.any?(&:statement?)
each_pg_statement(statement, &block)
end
end
end
end
Expand Down
2 changes: 0 additions & 2 deletions lib/json/ld/expand.rb
Original file line number Diff line number Diff line change
Expand Up @@ -281,9 +281,7 @@ def expand_object(input, active_property, context, output_object,
elsif @options[:rdfstar]
# Result must have just a single statement
rei_node = expand(value, active_property, context, log_depth: log_depth.to_i + 1)
old_star, @options[:rdfstar] = @options[:rdfstar], :SA
statements = to_enum(:item_to_rdf, rei_node)
@options[:rdfstar] = old_star # :PG would emit too many statements
raise JsonLdError::InvalidEmbeddedNode,
"Embedded node with #{statements.size} statements" unless
statements.count == 1
Expand Down
16 changes: 0 additions & 16 deletions lib/json/ld/to_rdf.rb
Original file line number Diff line number Diff line change
Expand Up @@ -182,22 +182,6 @@ def parse_list(list, graph_name: nil, &block)
result
end

##
# Recursively emit embedded statements in Property Graph mode
#
# @param [RDF::Statement] statement
def each_pg_statement(statement, &block)
if statement.subject.statement?
block.call(statement.subject)
each_pg_statement(statement.subject, &block)
end

if statement.object.statement?
block.call(statement.object)
each_pg_statement(statement.object, &block)
end
end

##
# Create a new named node using the sequence
def node
Expand Down
6 changes: 2 additions & 4 deletions script/parse
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ OPT_ARGS = [
["--output", "-o", GetoptLong::REQUIRED_ARGUMENT, "Where to store output (default STDOUT)"],
["--profile", GetoptLong::NO_ARGUMENT, "Run profiler with output to doc/profiles/"],
["--quiet", GetoptLong::NO_ARGUMENT, "Reduce output"],
["--rdfstar", GetoptLong::REQUIRED_ARGUMENT, "RDF* mode, SA or PG"],
["--rdfstar", GetoptLong::NO_ARGUMENT, "RDF* mode"],
["--stream", GetoptLong::NO_ARGUMENT, "Streaming reader/writer"],
["--uri", GetoptLong::REQUIRED_ARGUMENT, "Run with argument value as base"],
["--validate", GetoptLong::NO_ARGUMENT, "Validate input"],
Expand Down Expand Up @@ -157,9 +157,7 @@ opts.each do |opt, arg|
when '--quiet'
options[:quiet] = true
logger.level = Logger::FATAL
when '--rdfstar'
parser_options[:rdfstar] = arg.to_sym
usage unless [:PG, :SA].include?(parser_options[:rdfstar])
when '--rdfstar' then parser_options[:rdfstar] = true
when '--stream' then parser_options[:stream] = true
when '--uri' then parser_options[:base] = arg
when '--validate' then parser_options[:validate] = true
Expand Down
2 changes: 1 addition & 1 deletion spec/expand_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3620,7 +3620,7 @@
}])
},
}.each do |title, params|
it(title) {run_expand params.merge(rdfstar: :SA)}
it(title) {run_expand params.merge(rdfstar: true)}
end
end

Expand Down
79 changes: 15 additions & 64 deletions spec/to_rdf_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1199,13 +1199,9 @@
},
"ex:prop": "value2"
}),
sa: %(
expected: %(
<<_:b0 <ex:prop> "value">> <ex:prop> "value2" .
),
pg: %(
<<_:b0 <ex:prop> "value">> <ex:prop> "value2" .
_:b0 <ex:prop> "value" .
),
},
"node with embedded subject having IRI @id": {
input: %({
Expand All @@ -1215,12 +1211,8 @@
},
"ex:prop": "value2"
}),
sa: %(
<<<ex:rei> <ex:prop> "value">> <ex:prop> "value2" .
),
pg: %(
expected: %(
<<<ex:rei> <ex:prop> "value">> <ex:prop> "value2" .
<ex:rei> <ex:prop> "value" .
),
},
"node with embedded subject having BNode @id": {
Expand All @@ -1231,12 +1223,8 @@
},
"ex:prop": "value2"
}),
sa: %(
<<_:b0 <ex:prop> "value">> <ex:prop> "value2" .
),
pg: %(
expected: %(
<<_:b0 <ex:prop> "value">> <ex:prop> "value2" .
_:b0 <ex:prop> "value" .
),
},
"node with embedded subject having a type": {
Expand All @@ -1247,13 +1235,9 @@
},
"ex:prop": "value2"
}),
sa: %(
expected: %(
<<<ex:rei> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex:Type>>> <ex:prop> "value2" .
),
pg: %(
<<<ex:rei> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex:Type>>> <ex:prop> "value2" .
<ex:rei> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex:Type> .
),
},
"node with embedded subject having an IRI value": {
input: %({
Expand All @@ -1263,12 +1247,8 @@
},
"ex:prop": "value2"
}),
sa: %(
<<<ex:rei> <ex:prop> <ex:value>>> <ex:prop> "value2" .
),
pg: %(
expected: %(
<<<ex:rei> <ex:prop> <ex:value>>> <ex:prop> "value2" .
<ex:rei> <ex:prop> <ex:value> .
),
},
"node with embedded subject having an BNode value": {
Expand All @@ -1279,12 +1259,8 @@
},
"ex:prop": "value2"
}),
sa: %(
<<<ex:rei> <ex:prop> _:b0>> <ex:prop> "value2" .
),
pg: %(
expected: %(
<<<ex:rei> <ex:prop> _:b0>> <ex:prop> "value2" .
<ex:rei> <ex:prop> _:b0 .
),
},
"node with recursive embedded subject": {
Expand All @@ -1298,14 +1274,9 @@
},
"ex:prop": "value2"
}),
sa: %(
expected: %(
<<<<<ex:rei> <ex:prop> "value3">> <ex:prop> "value">> <ex:prop> "value2" .
),
pg: %(
<<<<<ex:rei> <ex:prop> "value3">> <ex:prop> "value">> <ex:prop> "value2" .
<<<ex:rei> <ex:prop> "value3">> <ex:prop> "value" .
<ex:rei> <ex:prop> "value3" .
),
},
"illegal node with subject having no property": {
input: %({
Expand Down Expand Up @@ -1357,12 +1328,8 @@
}
}
}),
sa: %(
<ex:subj> <ex:value> <<<ex:rei> <ex:prop> "value">> .
),
pg: %(
expected: %(
<ex:subj> <ex:value> <<<ex:rei> <ex:prop> "value">> .
<ex:rei> <ex:prop> "value" .
),
},
"node with embedded object having properties": {
Expand All @@ -1376,15 +1343,10 @@
"ex:prop": "value2"
}
}),
sa: %(
expected: %(
<ex:subj> <ex:value> <<<ex:rei> <ex:prop> "value">> .
<<<ex:rei> <ex:prop> "value">> <ex:prop> "value2" .
),
pg: %(
<ex:subj> <ex:value> <<<ex:rei> <ex:prop> "value">> .
<<<ex:rei> <ex:prop> "value">> <ex:prop> "value2" .
<ex:rei> <ex:prop> "value" .
),
},
"node with recursive embedded object": {
input: %({
Expand All @@ -1400,31 +1362,20 @@
"ex:prop": "value2"
}
}),
sa: %(
expected: %(
<ex:subj> <ex:value> <<<<<ex:rei> <ex:prop> "value3">> <ex:prop> "value">> .
<<<<<ex:rei> <ex:prop> "value3">> <ex:prop> "value">> <ex:prop> "value2" .
),
pg: %(
<ex:subj> <ex:value> <<<<<ex:rei> <ex:prop> "value3">> <ex:prop> "value">> .
<<<ex:rei> <ex:prop> "value3">> <ex:prop> "value" .
<ex:rei> <ex:prop> "value3" .
<<<<<ex:rei> <ex:prop> "value3">> <ex:prop> "value">> <ex:prop> "value2" .
),
},
}.each do |title, params|
context(title) do
it "Separate Assertions" do
output_graph = RDF::Graph.new {|g| g << RDF::NTriples::Reader.new(params[:sa], rdfstar: :SA)}
run_to_rdf params.merge(rdfstar: :SA, output: output_graph)
end if params[:sa]

it "Property Graph" do
output_graph = RDF::Graph.new {|g| g << RDF::NTriples::Reader.new(params[:pg], rdfstar: :SA)}
run_to_rdf params.merge(rdfstar: :PG, output: output_graph)
end if params[:pg]
it "Generates statements" do
output_graph = RDF::Graph.new {|g| g << RDF::NTriples::Reader.new(params[:expected], rdfstar: true)}
run_to_rdf params.merge(rdfstar: true, output: output_graph)
end if params[:expected]

it "Exception" do
run_to_rdf params.merge(rdfstar: :SA)
run_to_rdf params.merge(rdfstar: true)
end if params[:exception]
end
end
Expand Down

0 comments on commit 40655ec

Please sign in to comment.