json-ld 3.1.7 → 3.1.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +16 -3
- data/VERSION +1 -1
- data/bin/jsonld +3 -3
- data/lib/json/ld.rb +3 -1
- data/lib/json/ld/api.rb +22 -14
- data/lib/json/ld/compact.rb +3 -3
- data/lib/json/ld/context.rb +44 -44
- data/lib/json/ld/expand.rb +46 -8
- data/lib/json/ld/extensions.rb +4 -4
- data/lib/json/ld/flatten.rb +92 -9
- data/lib/json/ld/format.rb +1 -1
- data/lib/json/ld/frame.rb +8 -8
- data/lib/json/ld/from_rdf.rb +2 -2
- data/lib/json/ld/reader.rb +1 -0
- data/lib/json/ld/streaming_reader.rb +5 -5
- data/lib/json/ld/streaming_writer.rb +4 -4
- data/lib/json/ld/to_rdf.rb +2 -2
- data/lib/json/ld/utils.rb +13 -13
- data/lib/json/ld/writer.rb +2 -2
- data/spec/api_spec.rb +1 -1
- data/spec/compact_spec.rb +1 -1
- data/spec/expand_spec.rb +384 -1
- data/spec/flatten_spec.rb +517 -1
- data/spec/rdfstar_spec.rb +25 -0
- data/spec/spec_helper.rb +33 -0
- data/spec/suite_flatten_spec.rb +4 -0
- data/spec/suite_frame_spec.rb +7 -0
- data/spec/suite_helper.rb +13 -7
- data/spec/to_rdf_spec.rb +3 -3
- metadata +63 -61
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8fab787ba5efd37b20576d65d5dfe524923f14c7dac53a1d9ed32cb88bd689c8
|
4
|
+
data.tar.gz: 3b8ce473fe9e05302dabedb9a631ca2212aeb03479cc2d282abf8603daeedce2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 47ec226ef3c0d79702d61a7fa81ce2ed3368f64744e2fb29f1b98fdaae2aba7e6af7ed493395031eb43d89e4469c04a24ea38ad836baffb50a46854cf33a75c8
|
7
|
+
data.tar.gz: 579b1794485469d832b29a2f5f5bbf36819627d93289595da6f46e2197829e4e6365a5bbb4c88193f904ad07a21a643821195d22cb3750543e6954e986d809f4
|
data/README.md
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
[![Gem Version](https://badge.fury.io/rb/json-ld.png)](https://rubygems.org/gems/json-ld)
|
6
6
|
[![Build Status](https://secure.travis-ci.org/ruby-rdf/json-ld.png?branch=develop)](https://github.com/ruby-rdf/json-ld/actions?query=workflow%3ACI)
|
7
|
-
[![Coverage Status](https://coveralls.io/repos/ruby-rdf/json-ld/badge.svg)](https://coveralls.io/github/ruby-rdf/json-ld)
|
7
|
+
[![Coverage Status](https://coveralls.io/repos/ruby-rdf/json-ld/badge.svg?branch=develop)](https://coveralls.io/github/ruby-rdf/json-ld?branch=develop)
|
8
8
|
[![Gitter chat](https://badges.gitter.im/ruby-rdf.png)](https://gitter.im/gitterHQ/gitter)
|
9
9
|
|
10
10
|
## Features
|
@@ -17,7 +17,7 @@ JSON::LD can now be used to create a _context_ from an RDFS/OWL definition, and
|
|
17
17
|
* If available, uses [Nokogiri][] and/or [Nokogumbo][] for parsing HTML, falls back to REXML otherwise.
|
18
18
|
* Provisional support for [JSON-LD*][JSON-LD*].
|
19
19
|
|
20
|
-
[Implementation Report](
|
20
|
+
[Implementation Report](https://ruby-rdf.github.io/json-ld/etc/earl.html)
|
21
21
|
|
22
22
|
Install with `gem install json-ld`
|
23
23
|
|
@@ -39,7 +39,7 @@ The [MultiJson](https://rubygems.org/gems/multi_json) gem is used for parsing JS
|
|
39
39
|
|
40
40
|
### JSON-LD* (RDFStar)
|
41
41
|
|
42
|
-
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*].
|
42
|
+
The {JSON::LD::API.expand}, {JSON::LD::API.compact}, {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*].
|
43
43
|
|
44
44
|
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`.
|
45
45
|
|
@@ -55,6 +55,19 @@ In JSON-LD, with the `rdfstar` option set, the value of `@id`, in addition to an
|
|
55
55
|
"ex:certainty": 0.9
|
56
56
|
}
|
57
57
|
|
58
|
+
Additionally, the `@annotation` property (or alias) may be used on a node object or value object to annotate the statement for which the associated node is the object of a triple.
|
59
|
+
|
60
|
+
{
|
61
|
+
"@context": {"foaf": "http://xmlns.com/foaf/0.1/"},
|
62
|
+
"@id": "bob",
|
63
|
+
"foaf:age" 23,
|
64
|
+
"@annotation": {
|
65
|
+
"ex:certainty": 0.9
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
In the first case, the embedded node is not asserted, and only appears as the subject of a triple. In the second case, the triple is asserted and used as the subject in another statement which annotates it.
|
70
|
+
|
58
71
|
**Note: This feature is subject to change or elimination as the standards process progresses.**
|
59
72
|
|
60
73
|
#### Serializing a Graph containing embedded statements
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.1.
|
1
|
+
3.1.8
|
data/bin/jsonld
CHANGED
@@ -24,7 +24,7 @@ def run(input, options, parser_options)
|
|
24
24
|
|
25
25
|
start = Time.new
|
26
26
|
if options[:expand]
|
27
|
-
parser_options = parser_options.merge(expandContext: parser_options.delete(:context)) if parser_options.
|
27
|
+
parser_options = parser_options.merge(expandContext: parser_options.delete(:context)) if parser_options.key?(:context)
|
28
28
|
input = JSON::LD::API.fromRdf(reader) if reader
|
29
29
|
output = JSON::LD::API.expand(input, parser_options)
|
30
30
|
secs = Time.new - start
|
@@ -49,7 +49,7 @@ def run(input, options, parser_options)
|
|
49
49
|
options[:output].puts output.to_json(JSON::LD::JSON_STATE)
|
50
50
|
STDERR.puts "Framed in #{secs} seconds." unless options[:quiet]
|
51
51
|
else
|
52
|
-
parser_options = parser_options.merge(expandContext: parser_options.delete(:context)) if parser_options.
|
52
|
+
parser_options = parser_options.merge(expandContext: parser_options.delete(:context)) if parser_options.key?(:context)
|
53
53
|
parser_options[:standard_prefixes] = true
|
54
54
|
reader ||= JSON::LD::Reader.new(input, parser_options)
|
55
55
|
num = 0
|
@@ -181,7 +181,7 @@ opts.each do |opt, arg|
|
|
181
181
|
end
|
182
182
|
|
183
183
|
# Hack
|
184
|
-
if !(options.keys &
|
184
|
+
if !(options.keys & %i{expand compact flatten frame}).empty? &&
|
185
185
|
(parser_options[:stream] || options[:output_format] != :jsonld)
|
186
186
|
STDERR.puts "Incompatible options"
|
187
187
|
exit(1)
|
data/lib/json/ld.rb
CHANGED
@@ -47,6 +47,7 @@ module JSON
|
|
47
47
|
DEFAULT_CONTEXT = "http://schema.org"
|
48
48
|
|
49
49
|
KEYWORDS = Set.new(%w(
|
50
|
+
@annotation
|
50
51
|
@base
|
51
52
|
@container
|
52
53
|
@context
|
@@ -116,6 +117,7 @@ module JSON
|
|
116
117
|
class CollidingKeywords < JsonLdError; @code = "colliding keywords"; end
|
117
118
|
class ConflictingIndexes < JsonLdError; @code = "conflicting indexes"; end
|
118
119
|
class CyclicIRIMapping < JsonLdError; @code = "cyclic IRI mapping"; end
|
120
|
+
class InvalidAnnotation < JsonLdError; @code = "invalid annotation"; end
|
119
121
|
class InvalidBaseIRI < JsonLdError; @code = "invalid base IRI"; end
|
120
122
|
class InvalidContainerMapping < JsonLdError; @code = "invalid container mapping"; end
|
121
123
|
class InvalidContextEntry < JsonLdError; @code = "invalid context entry"; end
|
@@ -137,7 +139,7 @@ module JSON
|
|
137
139
|
class InvalidNestValue < JsonLdError; @code = "invalid @nest value"; end
|
138
140
|
class InvalidPrefixValue < JsonLdError; @code = "invalid @prefix value"; end
|
139
141
|
class InvalidPropagateValue < JsonLdError; @code = "invalid @propagate value"; end
|
140
|
-
class InvalidEmbeddedNode < JsonLdError; @code = "invalid
|
142
|
+
class InvalidEmbeddedNode < JsonLdError; @code = "invalid embedded node"; end
|
141
143
|
class InvalidRemoteContext < JsonLdError; @code = "invalid remote context"; end
|
142
144
|
class InvalidReverseProperty < JsonLdError; @code = "invalid reverse property"; end
|
143
145
|
class InvalidReversePropertyMap < JsonLdError; @code = "invalid reverse property map"; end
|
data/lib/json/ld/api.rb
CHANGED
@@ -102,13 +102,15 @@ module JSON::LD
|
|
102
102
|
# @yield [api]
|
103
103
|
# @yieldparam [API]
|
104
104
|
# @raise [JsonLdError]
|
105
|
-
def initialize(input, context,
|
105
|
+
def initialize(input, context, **options, &block)
|
106
106
|
@options = {
|
107
107
|
compactArrays: true,
|
108
108
|
ordered: false,
|
109
109
|
extractAllScripts: false,
|
110
|
+
rename_bnodes: true,
|
111
|
+
unique_bnodes: false,
|
110
112
|
}.merge(options)
|
111
|
-
@namer = unique_bnodes ? BlankNodeUniqer.new : (rename_bnodes ? BlankNodeNamer.new("b") : BlankNodeMapper.new)
|
113
|
+
@namer = @options[:unique_bnodes] ? BlankNodeUniqer.new : (@options[:rename_bnodes] ? BlankNodeNamer.new("b") : BlankNodeMapper.new)
|
112
114
|
|
113
115
|
@options[:base] = RDF::URI(@options[:base]) if @options[:base] && !@options[:base].is_a?(RDF::URI)
|
114
116
|
# For context via Link header
|
@@ -202,9 +204,9 @@ module JSON::LD
|
|
202
204
|
# The JSON-LD object to copy and perform the compaction upon.
|
203
205
|
# @param [String, #read, Hash, Array, JSON::LD::Context] context
|
204
206
|
# The base context to use when compacting the input.
|
207
|
+
# @param [Boolean] expanded (false) Input is already expanded
|
205
208
|
# @param [Hash{Symbol => Object}] options
|
206
209
|
# @option options (see #initialize)
|
207
|
-
# @option options [Boolean] :expanded Input is already expanded
|
208
210
|
# @yield jsonld
|
209
211
|
# @yieldparam [Hash] jsonld
|
210
212
|
# The compacted JSON-LD document
|
@@ -248,9 +250,9 @@ module JSON::LD
|
|
248
250
|
# The JSON-LD object or array of JSON-LD objects to flatten or an IRI referencing the JSON-LD document to flatten.
|
249
251
|
# @param [String, #read, Hash, Array, JSON::LD::EvaluationContext] context
|
250
252
|
# An optional external context to use additionally to the context embedded in input when expanding the input.
|
253
|
+
# @param [Boolean] expanded (false) Input is already expanded
|
251
254
|
# @param [Hash{Symbol => Object}] options
|
252
255
|
# @option options (see #initialize)
|
253
|
-
# @option options [Boolean] :expanded Input is already expanded
|
254
256
|
# @yield jsonld
|
255
257
|
# @yieldparam [Hash] jsonld
|
256
258
|
# The flattened JSON-LD document
|
@@ -275,6 +277,9 @@ module JSON::LD
|
|
275
277
|
API.new(expanded_input, context, no_default_base: true, **options) do
|
276
278
|
log_debug(".flatten") {"expanded input: #{value.to_json(JSON_STATE) rescue 'malformed json'}"}
|
277
279
|
|
280
|
+
# Rename blank nodes recusively. Note that this does not create new blank node identifiers where none exist, which is performed in the node map generation algorithm.
|
281
|
+
@value = rename_bnodes(@value) if @options[:rename_bnodes]
|
282
|
+
|
278
283
|
# Initialize node map to a JSON object consisting of a single member whose key is @default and whose value is an empty JSON object.
|
279
284
|
graph_maps = {'@default' => {}}
|
280
285
|
create_node_map(value, graph_maps)
|
@@ -316,6 +321,7 @@ module JSON::LD
|
|
316
321
|
# The JSON-LD object to copy and perform the framing on.
|
317
322
|
# @param [String, #read, Hash, Array] frame
|
318
323
|
# The frame to use when re-arranging the data.
|
324
|
+
# @param [Boolean] expanded (false) Input is already expanded
|
319
325
|
# @option options (see #initialize)
|
320
326
|
# @option options ['@always', '@link', '@once', '@never'] :embed ('@once')
|
321
327
|
# a flag specifying that objects should be directly embedded in the output, instead of being referred to by their IRI.
|
@@ -325,7 +331,6 @@ module JSON::LD
|
|
325
331
|
# A flag specifying that all properties present in the input frame must either have a default value or be present in the JSON-LD input for the frame to match.
|
326
332
|
# @option options [Boolean] :omitDefault (false)
|
327
333
|
# a flag specifying that properties that are missing from the JSON-LD input should be omitted from the output.
|
328
|
-
# @option options [Boolean] :expanded Input is already expanded
|
329
334
|
# @option options [Boolean] :pruneBlankNodeIdentifiers (true) removes blank node identifiers that are only used once.
|
330
335
|
# @option options [Boolean] :omitGraph does not use `@graph` at top level unless necessary to describe multiple objects, defaults to `true` if processingMode is 1.1, otherwise `false`.
|
331
336
|
# @yield jsonld
|
@@ -391,10 +396,13 @@ module JSON::LD
|
|
391
396
|
end
|
392
397
|
|
393
398
|
# Set omitGraph option, if not present, based on processingMode
|
394
|
-
unless options.
|
399
|
+
unless options.key?(:omitGraph)
|
395
400
|
options[:omitGraph] = context.processingMode('json-ld-1.1')
|
396
401
|
end
|
397
402
|
|
403
|
+
# Rename blank nodes recusively. Note that this does not create new blank node identifiers where none exist, which is performed in the node map generation algorithm.
|
404
|
+
@value = rename_bnodes(@value)
|
405
|
+
|
398
406
|
# Get framing nodes from expanded input, replacing Blank Node identifiers as necessary
|
399
407
|
create_node_map(value, framing_state[:graphMap], active_graph: '@default')
|
400
408
|
|
@@ -415,7 +423,7 @@ module JSON::LD
|
|
415
423
|
frame(framing_state, framing_state[:subjects].keys.opt_sort(ordered: @options[:ordered]), (expanded_frame.first || {}), parent: result, **options)
|
416
424
|
|
417
425
|
# Default to based on processinMode
|
418
|
-
if !options.
|
426
|
+
if !options.key?(:pruneBlankNodeIdentifiers)
|
419
427
|
options[:pruneBlankNodeIdentifiers] = context.processingMode('json-ld-1.1')
|
420
428
|
end
|
421
429
|
|
@@ -458,10 +466,10 @@ module JSON::LD
|
|
458
466
|
#
|
459
467
|
# @param [String, #read, Hash, Array] input
|
460
468
|
# The JSON-LD object to process when outputting statements.
|
469
|
+
# @param [Boolean] expanded (false) Input is already expanded
|
461
470
|
# @option options (see #initialize)
|
462
471
|
# @option options [Boolean] :produceGeneralizedRdf (false)
|
463
472
|
# If true, output will include statements having blank node predicates, otherwise they are dropped.
|
464
|
-
# @option options [Boolean] :expanded Input is already expanded
|
465
473
|
# @raise [JsonLdError]
|
466
474
|
# @yield statement
|
467
475
|
# @yieldparam [RDF::Statement] statement
|
@@ -470,7 +478,7 @@ module JSON::LD
|
|
470
478
|
unless block_given?
|
471
479
|
results = []
|
472
480
|
results.extend(RDF::Enumerable)
|
473
|
-
self.toRdf(input, **options) do |stmt|
|
481
|
+
self.toRdf(input, expanded: expanded, **options) do |stmt|
|
474
482
|
results << stmt
|
475
483
|
end
|
476
484
|
return results
|
@@ -480,16 +488,16 @@ module JSON::LD
|
|
480
488
|
extractAllScripts: true,
|
481
489
|
}.merge(options)
|
482
490
|
|
483
|
-
#
|
484
|
-
|
491
|
+
# Flatten input to simplify processing
|
492
|
+
flattened_input = API.flatten(input, nil, expanded: expanded, ordered: false, **options)
|
485
493
|
|
486
|
-
API.new(
|
494
|
+
API.new(flattened_input, nil, **options) do
|
487
495
|
# 1) Perform the Expansion Algorithm on the JSON-LD input.
|
488
496
|
# This removes any existing context to allow the given context to be cleanly applied.
|
489
|
-
log_debug(".toRdf") {"
|
497
|
+
log_debug(".toRdf") {"flattened input: #{flattened_input.to_json(JSON_STATE) rescue 'malformed json'}"}
|
490
498
|
|
491
499
|
# Recurse through input
|
492
|
-
|
500
|
+
flattened_input.each do |node|
|
493
501
|
item_to_rdf(node) do |statement|
|
494
502
|
next if statement.predicate.node? && !options[:produceGeneralizedRdf]
|
495
503
|
|
data/lib/json/ld/compact.rb
CHANGED
@@ -64,7 +64,7 @@ module JSON::LD
|
|
64
64
|
log_debug("prop-scoped", depth: log_depth.to_i) {"context: #{self.context.inspect}"}
|
65
65
|
end
|
66
66
|
|
67
|
-
if element.key?('@id') || element.key?('@value')
|
67
|
+
if (element.key?('@id') || element.key?('@value')) && !element.key?('@annotation')
|
68
68
|
result = context.compact_value(property, element, base: @options[:base])
|
69
69
|
if !result.is_a?(Hash) || context.coerce(property) == '@json'
|
70
70
|
log_debug("", depth: log_depth.to_i) {"=> scalar result: #{result.inspect}"}
|
@@ -231,7 +231,7 @@ module JSON::LD
|
|
231
231
|
unless container.include?('@list')
|
232
232
|
al = context.compact_iri('@list', vocab: true)
|
233
233
|
compacted_item = {al => compacted_item}
|
234
|
-
if expanded_item.
|
234
|
+
if expanded_item.key?('@index')
|
235
235
|
key = context.compact_iri('@index', vocab: true)
|
236
236
|
compacted_item[key] = expanded_item['@index']
|
237
237
|
end
|
@@ -276,7 +276,7 @@ module JSON::LD
|
|
276
276
|
al = context.compact_iri('@id', vocab: true)
|
277
277
|
compacted_item[al] = context.compact_iri(expanded_item['@id'], vocab: false)
|
278
278
|
end
|
279
|
-
if expanded_item.
|
279
|
+
if expanded_item.key?('@index')
|
280
280
|
key = context.compact_iri('@index', vocab: true)
|
281
281
|
compacted_item[key] = expanded_item['@index']
|
282
282
|
end
|
data/lib/json/ld/context.rb
CHANGED
@@ -314,7 +314,7 @@ module JSON::LD
|
|
314
314
|
#context_opts.delete(:headers)
|
315
315
|
JSON::LD::API.loadRemoteDocument(context.to_s, **context_opts) do |remote_doc|
|
316
316
|
# 3.2.5) Dereference context. If the dereferenced document has no top-level JSON object with an @context member, an invalid remote context has been detected and processing is aborted; otherwise, set context to the value of that member.
|
317
|
-
raise JsonLdError::InvalidRemoteContext, "#{context}" unless remote_doc.document.is_a?(Hash) && remote_doc.document.
|
317
|
+
raise JsonLdError::InvalidRemoteContext, "#{context}" unless remote_doc.document.is_a?(Hash) && remote_doc.document.key?('@context')
|
318
318
|
|
319
319
|
# Parse stand-alone
|
320
320
|
ctx = Context.new(unfrozen: true, **options).dup
|
@@ -352,7 +352,7 @@ module JSON::LD
|
|
352
352
|
'@propagate' => :propagate=,
|
353
353
|
'@vocab' => :vocab=,
|
354
354
|
}.each do |key, setter|
|
355
|
-
next unless context.
|
355
|
+
next unless context.key?(key)
|
356
356
|
if key == '@import'
|
357
357
|
# Retrieve remote context and merge the remaining context object into the result.
|
358
358
|
raise JsonLdError::InvalidContextEntry, "@import may only be used in 1.1 mode}" if result.processingMode("json-ld-1.0")
|
@@ -367,11 +367,11 @@ module JSON::LD
|
|
367
367
|
# FIXME: should cache this, but ContextCache is for parsed contexts
|
368
368
|
JSON::LD::API.loadRemoteDocument(import_loc, **context_opts) do |remote_doc|
|
369
369
|
# Dereference import_loc. If the dereferenced document has no top-level JSON object with an @context member, an invalid remote context has been detected and processing is aborted; otherwise, set context to the value of that member.
|
370
|
-
raise JsonLdError::InvalidRemoteContext, "#{import_loc}" unless remote_doc.document.is_a?(Hash) && remote_doc.document.
|
370
|
+
raise JsonLdError::InvalidRemoteContext, "#{import_loc}" unless remote_doc.document.is_a?(Hash) && remote_doc.document.key?('@context')
|
371
371
|
import_context = remote_doc.document['@context']
|
372
372
|
import_context.delete('@base')
|
373
373
|
raise JsonLdError::InvalidRemoteContext, "#{import_context.to_json} must be an object" unless import_context.is_a?(Hash)
|
374
|
-
raise JsonLdError::InvalidContextEntry, "#{import_context.to_json} must not include @import entry" if import_context.
|
374
|
+
raise JsonLdError::InvalidContextEntry, "#{import_context.to_json} must not include @import entry" if import_context.key?('@import')
|
375
375
|
context.delete(key)
|
376
376
|
context = import_context.merge(context)
|
377
377
|
end
|
@@ -542,7 +542,7 @@ module JSON::LD
|
|
542
542
|
# Potentially note that the term is protected
|
543
543
|
definition.protected = value.fetch('@protected', protected)
|
544
544
|
|
545
|
-
if value.
|
545
|
+
if value.key?('@type')
|
546
546
|
type = value['@type']
|
547
547
|
# SPEC FIXME: @type may be nil
|
548
548
|
type = case type
|
@@ -566,7 +566,7 @@ module JSON::LD
|
|
566
566
|
definition.type_mapping = type
|
567
567
|
end
|
568
568
|
|
569
|
-
if value.
|
569
|
+
if value.key?('@reverse')
|
570
570
|
raise JsonLdError::InvalidReverseProperty, "unexpected key in #{value.inspect} on term #{term.inspect}" if
|
571
571
|
value.key?('@id') || value.key?('@nest')
|
572
572
|
raise JsonLdError::InvalidIRIMapping, "expected value of @reverse to be a string: #{value['@reverse'].inspect} on term #{term.inspect}" unless
|
@@ -592,7 +592,7 @@ module JSON::LD
|
|
592
592
|
warn "[DEPRECATION] Blank Node terms deprecated in JSON-LD 1.1." if @options[:validate] && processingMode('json-ld-1.1') && definition.id.to_s.start_with?("_:")
|
593
593
|
|
594
594
|
# If value contains an @container member, set the container mapping of definition to its value; if its value is neither @set, @index, @type, @id, an absolute IRI nor null, an invalid reverse property error has been detected (reverse properties only support set- and index-containers) and processing is aborted.
|
595
|
-
if value.
|
595
|
+
if value.key?('@container')
|
596
596
|
container = value['@container']
|
597
597
|
raise JsonLdError::InvalidReverseProperty,
|
598
598
|
"unknown mapping for '@container' to #{container.inspect} on term #{term.inspect}" unless
|
@@ -600,9 +600,9 @@ module JSON::LD
|
|
600
600
|
definition.container_mapping = check_container(container, local_context, defined, term)
|
601
601
|
end
|
602
602
|
definition.reverse_property = true
|
603
|
-
elsif value.
|
603
|
+
elsif value.key?('@id') && value['@id'].nil?
|
604
604
|
# Allowed to reserve a null term, which may be protected
|
605
|
-
elsif value.
|
605
|
+
elsif value.key?('@id') && value['@id'] != term
|
606
606
|
raise JsonLdError::InvalidIRIMapping, "expected value of @id to be a string: #{value['@id'].inspect} on term #{term.inspect}" unless
|
607
607
|
value['@id'].is_a?(String)
|
608
608
|
|
@@ -637,7 +637,7 @@ module JSON::LD
|
|
637
637
|
elsif term[1..-1].include?(':')
|
638
638
|
# If term is a compact IRI with a prefix that is a key in local context then a dependency has been found. Use this algorithm recursively passing active context, local context, the prefix as term, and defined.
|
639
639
|
prefix, suffix = term.split(':', 2)
|
640
|
-
create_term_definition(local_context, prefix, defined, protected: protected) if local_context.
|
640
|
+
create_term_definition(local_context, prefix, defined, protected: protected) if local_context.key?(prefix)
|
641
641
|
|
642
642
|
definition.id = if td = term_definitions[prefix]
|
643
643
|
# If term's prefix has a term definition in active context, set the IRI mapping for definition to the result of concatenating the value associated with the prefix's IRI mapping and the term's suffix.
|
@@ -664,7 +664,7 @@ module JSON::LD
|
|
664
664
|
|
665
665
|
@iri_to_term[definition.id] = term if simple_term && definition.id
|
666
666
|
|
667
|
-
if value.
|
667
|
+
if value.key?('@container')
|
668
668
|
#log_debug("") {"container_mapping: #{value['@container'].inspect}"}
|
669
669
|
definition.container_mapping = check_container(value['@container'], local_context, defined, term)
|
670
670
|
|
@@ -679,14 +679,14 @@ module JSON::LD
|
|
679
679
|
end
|
680
680
|
end
|
681
681
|
|
682
|
-
if value.
|
682
|
+
if value.key?('@index')
|
683
683
|
# property-based indexing
|
684
684
|
raise JsonLdError::InvalidTermDefinition, "@index without @index in @container: #{value['@index']} on term #{term.inspect}" unless definition.container_mapping.include?('@index')
|
685
685
|
raise JsonLdError::InvalidTermDefinition, "@index must expand to an IRI: #{value['@index']} on term #{term.inspect}" unless value['@index'].is_a?(String) && !value['@index'].start_with?('@')
|
686
686
|
definition.index = value['@index'].to_s
|
687
687
|
end
|
688
688
|
|
689
|
-
if value.
|
689
|
+
if value.key?('@context')
|
690
690
|
begin
|
691
691
|
new_ctx = self.parse(value['@context'],
|
692
692
|
base: base,
|
@@ -704,7 +704,7 @@ module JSON::LD
|
|
704
704
|
end
|
705
705
|
end
|
706
706
|
|
707
|
-
if value.
|
707
|
+
if value.key?('@language')
|
708
708
|
language = value['@language']
|
709
709
|
language = case value['@language']
|
710
710
|
when String
|
@@ -722,14 +722,14 @@ module JSON::LD
|
|
722
722
|
definition.language_mapping = language || false
|
723
723
|
end
|
724
724
|
|
725
|
-
if value.
|
725
|
+
if value.key?('@direction')
|
726
726
|
direction = value['@direction']
|
727
727
|
raise JsonLdError::InvalidBaseDirection, "direction must be null, 'ltr', or 'rtl', was #{language.inspect}} on term #{term.inspect}" unless direction.nil? || %w(ltr rtl).include?(direction)
|
728
728
|
#log_debug("") {"direction_mapping: #{direction.inspect}"}
|
729
729
|
definition.direction_mapping = direction || false
|
730
730
|
end
|
731
731
|
|
732
|
-
if value.
|
732
|
+
if value.key?('@nest')
|
733
733
|
nest = value['@nest']
|
734
734
|
raise JsonLdError::InvalidNestValue, "nest must be a string, was #{nest.inspect}} on term #{term.inspect}" unless nest.is_a?(String)
|
735
735
|
raise JsonLdError::InvalidNestValue, "nest must not be a keyword other than @nest, was #{nest.inspect}} on term #{term.inspect}" if nest.match?(/^@[a-zA-Z]+$/) && nest != '@nest'
|
@@ -737,7 +737,7 @@ module JSON::LD
|
|
737
737
|
definition.nest = nest
|
738
738
|
end
|
739
739
|
|
740
|
-
if value.
|
740
|
+
if value.key?('@prefix')
|
741
741
|
raise JsonLdError::InvalidTermDefinition, "@prefix used on compact or relative IRI term #{term.inspect}" if term.match?(%r{:|/})
|
742
742
|
case pfx = value['@prefix']
|
743
743
|
when TrueClass, FalseClass
|
@@ -1018,7 +1018,7 @@ module JSON::LD
|
|
1018
1018
|
|
1019
1019
|
term_sym = term.empty? ? "" : term.to_sym
|
1020
1020
|
iri_to_term.delete(term_definitions[term].id.to_s) if term_definitions[term].id.is_a?(String)
|
1021
|
-
@options[:prefixes][term_sym] = value if @options.
|
1021
|
+
@options[:prefixes][term_sym] = value if @options.key?(:prefixes)
|
1022
1022
|
iri_to_term[value.to_s] = term
|
1023
1023
|
term_definitions[term]
|
1024
1024
|
end
|
@@ -1134,7 +1134,7 @@ module JSON::LD
|
|
1134
1134
|
# @return [Term] related term definition
|
1135
1135
|
def reverse_term(term)
|
1136
1136
|
# Direct lookup of term
|
1137
|
-
term = term_definitions[term.to_s] if term_definitions.
|
1137
|
+
term = term_definitions[term.to_s] if term_definitions.key?(term.to_s) && !term.is_a?(TermDefinition)
|
1138
1138
|
|
1139
1139
|
# Lookup term, assuming term is an IRI
|
1140
1140
|
unless term.is_a?(TermDefinition)
|
@@ -1182,7 +1182,7 @@ module JSON::LD
|
|
1182
1182
|
defined = defined || {} # if we initialized in the keyword arg we would allocate {} at each invokation, even in the 2 (common) early returns above.
|
1183
1183
|
|
1184
1184
|
# If local context is not null, it contains a key that equals value, and the value associated with the key that equals value in defined is not true, then invoke the Create Term Definition subalgorithm, passing active context, local context, value as term, and defined. This will ensure that a term definition is created for value in active context during Context Processing.
|
1185
|
-
if local_context && local_context.
|
1185
|
+
if local_context && local_context.key?(value) && !defined[value]
|
1186
1186
|
create_term_definition(local_context, value, defined)
|
1187
1187
|
end
|
1188
1188
|
|
@@ -1212,7 +1212,7 @@ module JSON::LD
|
|
1212
1212
|
end
|
1213
1213
|
|
1214
1214
|
# If local context is not null, it contains a key that equals prefix, and the value associated with the key that equals prefix in defined is not true, invoke the Create Term Definition algorithm, passing active context, local context, prefix as term, and defined. This will ensure that a term definition is created for prefix in active context during Context Processing.
|
1215
|
-
if local_context && local_context.
|
1215
|
+
if local_context && local_context.key?(prefix) && !defined[prefix]
|
1216
1216
|
create_term_definition(local_context, prefix, defined)
|
1217
1217
|
end
|
1218
1218
|
|
@@ -1287,7 +1287,7 @@ module JSON::LD
|
|
1287
1287
|
return if iri.nil?
|
1288
1288
|
iri = iri.to_s
|
1289
1289
|
|
1290
|
-
if vocab && inverse_context.
|
1290
|
+
if vocab && inverse_context.key?(iri)
|
1291
1291
|
default_language = if self.default_direction
|
1292
1292
|
"#{self.default_language}_#{self.default_direction}".downcase
|
1293
1293
|
else
|
@@ -1298,7 +1298,7 @@ module JSON::LD
|
|
1298
1298
|
containers.concat(CONTAINERS_INDEX_SET) if index?(value) && !graph?(value)
|
1299
1299
|
|
1300
1300
|
# If the value is a JSON Object with the key @preserve, use the value of @preserve.
|
1301
|
-
value = value['@preserve'].first if value.is_a?(Hash) && value.
|
1301
|
+
value = value['@preserve'].first if value.is_a?(Hash) && value.key?('@preserve')
|
1302
1302
|
|
1303
1303
|
if reverse
|
1304
1304
|
tl, tl_value = "@type", "@reverse"
|
@@ -1312,11 +1312,11 @@ module JSON::LD
|
|
1312
1312
|
list.each do |item|
|
1313
1313
|
item_language, item_type = "@none", "@none"
|
1314
1314
|
if value?(item)
|
1315
|
-
if item.
|
1315
|
+
if item.key?('@direction')
|
1316
1316
|
item_language = "#{item['@language']}_#{item['@direction']}".downcase
|
1317
|
-
elsif item.
|
1317
|
+
elsif item.key?('@language')
|
1318
1318
|
item_language = item['@language'].downcase
|
1319
|
-
elsif item.
|
1319
|
+
elsif item.key?('@type')
|
1320
1320
|
item_type = item['@type']
|
1321
1321
|
else
|
1322
1322
|
item_language = "@null"
|
@@ -1344,14 +1344,14 @@ module JSON::LD
|
|
1344
1344
|
elsif graph?(value)
|
1345
1345
|
# Prefer @index and @id containers, then @graph, then @index
|
1346
1346
|
containers.concat(CONTAINERS_GRAPH_INDEX_INDEX) if index?(value)
|
1347
|
-
containers.concat(CONTAINERS_GRAPH) if value.
|
1347
|
+
containers.concat(CONTAINERS_GRAPH) if value.key?('@id')
|
1348
1348
|
|
1349
1349
|
# Prefer an @graph container next
|
1350
1350
|
containers.concat(CONTAINERS_GRAPH_SET)
|
1351
1351
|
|
1352
1352
|
# Lastly, in 1.1, any graph can be indexed on @index or @id, so add if we haven't already
|
1353
1353
|
containers.concat(CONTAINERS_GRAPH_INDEX) unless index?(value)
|
1354
|
-
containers.concat(CONTAINERS_GRAPH) unless value.
|
1354
|
+
containers.concat(CONTAINERS_GRAPH) unless value.key?('@id')
|
1355
1355
|
containers.concat(CONTAINERS_INDEX_SET) unless index?(value)
|
1356
1356
|
containers << '@set'
|
1357
1357
|
|
@@ -1359,13 +1359,13 @@ module JSON::LD
|
|
1359
1359
|
else
|
1360
1360
|
if value?(value)
|
1361
1361
|
# In 1.1, an language map can be used to index values using @none
|
1362
|
-
if value.
|
1362
|
+
if value.key?('@language') && !index?(value)
|
1363
1363
|
tl_value = value['@language'].downcase
|
1364
1364
|
tl_value += "_#{value['@direction']}" if value['@direction']
|
1365
1365
|
containers.concat(CONTAINERS_LANGUAGE)
|
1366
|
-
elsif value.
|
1366
|
+
elsif value.key?('@direction') && !index?(value)
|
1367
1367
|
tl_value = "_#{value['@direction']}"
|
1368
|
-
elsif value.
|
1368
|
+
elsif value.key?('@type')
|
1369
1369
|
tl_value = value['@type']
|
1370
1370
|
tl = '@type'
|
1371
1371
|
end
|
@@ -1387,7 +1387,7 @@ module JSON::LD
|
|
1387
1387
|
tl_value ||= '@null'
|
1388
1388
|
preferred_values = []
|
1389
1389
|
preferred_values << '@reverse' if tl_value == '@reverse'
|
1390
|
-
if (tl_value == '@id' || tl_value == '@reverse') && value.is_a?(Hash) && value.
|
1390
|
+
if (tl_value == '@id' || tl_value == '@reverse') && value.is_a?(Hash) && value.key?('@id')
|
1391
1391
|
t_iri = compact_iri(value['@id'], vocab: true, base: base)
|
1392
1392
|
if (r_td = term_definitions[t_iri]) && r_td.id == value['@id']
|
1393
1393
|
preferred_values.concat(CONTAINERS_VOCAB_ID)
|
@@ -1413,7 +1413,7 @@ module JSON::LD
|
|
1413
1413
|
# At this point, there is no simple term that iri can be compacted to. If vocab is true and active context has a vocabulary mapping:
|
1414
1414
|
if vocab && self.vocab && iri.start_with?(self.vocab) && iri.length > self.vocab.length
|
1415
1415
|
suffix = iri[self.vocab.length..-1]
|
1416
|
-
return suffix unless term_definitions.
|
1416
|
+
return suffix unless term_definitions.key?(suffix)
|
1417
1417
|
end
|
1418
1418
|
|
1419
1419
|
# The iri could not be compacted using the active context's vocabulary mapping. Try to create a compact IRI, starting by initializing compact IRI to null. This variable will be used to tore the created compact IRI, if any.
|
@@ -1427,7 +1427,7 @@ module JSON::LD
|
|
1427
1427
|
|
1428
1428
|
suffix = iri[td.id.length..-1]
|
1429
1429
|
ciri = "#{term}:#{suffix}"
|
1430
|
-
candidates << ciri unless value && term_definitions.
|
1430
|
+
candidates << ciri unless value && term_definitions.key?(ciri)
|
1431
1431
|
end
|
1432
1432
|
|
1433
1433
|
return candidates.sort.first if !candidates.empty?
|
@@ -1523,16 +1523,16 @@ module JSON::LD
|
|
1523
1523
|
res['@language'] = lang
|
1524
1524
|
end
|
1525
1525
|
res['@direction'] = dir
|
1526
|
-
elsif useNativeTypes && RDF_LITERAL_NATIVE_TYPES.include?(value.datatype)
|
1526
|
+
elsif useNativeTypes && RDF_LITERAL_NATIVE_TYPES.include?(value.datatype) && value.valid?
|
1527
1527
|
res['@type'] = uri(coerce(property)) if coerce(property)
|
1528
1528
|
res['@value'] = value.object
|
1529
1529
|
else
|
1530
|
-
value.canonicalize! if value.datatype == RDF::XSD.double
|
1530
|
+
value.canonicalize! if value.valid? && value.datatype == RDF::XSD.double
|
1531
1531
|
if coerce(property)
|
1532
1532
|
res['@type'] = uri(coerce(property)).to_s
|
1533
|
-
elsif value.
|
1533
|
+
elsif value.datatype?
|
1534
1534
|
res['@type'] = uri(value.datatype).to_s
|
1535
|
-
elsif value.
|
1535
|
+
elsif value.language? || language(property)
|
1536
1536
|
res['@language'] = (value.language || language(property)).to_s
|
1537
1537
|
end
|
1538
1538
|
res['@value'] = value.to_s
|
@@ -1580,15 +1580,15 @@ module JSON::LD
|
|
1580
1580
|
direction = direction(property)
|
1581
1581
|
|
1582
1582
|
result = case
|
1583
|
-
when coerce(property) == '@id' && value.
|
1583
|
+
when coerce(property) == '@id' && value.key?('@id') && (value.keys - %w(@id @index)).empty?
|
1584
1584
|
# Compact an @id coercion
|
1585
1585
|
#log_debug("") {" (@id & coerce)"}
|
1586
1586
|
compact_iri(value['@id'], base: base)
|
1587
|
-
when coerce(property) == '@vocab' && value.
|
1587
|
+
when coerce(property) == '@vocab' && value.key?('@id') && (value.keys - %w(@id @index)).empty?
|
1588
1588
|
# Compact an @id coercion
|
1589
1589
|
#log_debug("") {" (@id & coerce & vocab)"}
|
1590
1590
|
compact_iri(value['@id'], vocab: true)
|
1591
|
-
when value.
|
1591
|
+
when value.key?('@id')
|
1592
1592
|
#log_debug("") {" (@id)"}
|
1593
1593
|
# return value as is
|
1594
1594
|
value
|
@@ -1609,7 +1609,7 @@ module JSON::LD
|
|
1609
1609
|
value
|
1610
1610
|
end
|
1611
1611
|
|
1612
|
-
if result.is_a?(Hash) && result.
|
1612
|
+
if result.is_a?(Hash) && result.key?('@type') && value['@type'] != '@json'
|
1613
1613
|
# Compact values of @type
|
1614
1614
|
c_type = if result['@type'].is_a?(Array)
|
1615
1615
|
result['@type'].map {|t| compact_iri(t, vocab: true)}
|
@@ -1857,11 +1857,11 @@ module JSON::LD
|
|
1857
1857
|
container_map = inverse_context[iri]
|
1858
1858
|
#log_debug(" ") {"container_map: #{container_map.inspect}"}
|
1859
1859
|
containers.each do |container|
|
1860
|
-
next unless container_map.
|
1860
|
+
next unless container_map.key?(container)
|
1861
1861
|
tl_map = container_map[container]
|
1862
1862
|
value_map = tl_map[type_language]
|
1863
1863
|
preferred_values.each do |item|
|
1864
|
-
next unless value_map.
|
1864
|
+
next unless value_map.key?(item)
|
1865
1865
|
#log_debug("=>") {value_map[item].inspect}
|
1866
1866
|
return value_map[item]
|
1867
1867
|
end
|