json-ld 1.99.2 → 2.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/VERSION +1 -1
- data/lib/json/ld.rb +0 -3
- data/lib/json/ld/api.rb +38 -21
- data/lib/json/ld/compact.rb +24 -24
- data/lib/json/ld/context.rb +80 -79
- data/lib/json/ld/expand.rb +30 -30
- data/lib/json/ld/flatten.rb +2 -2
- data/lib/json/ld/format.rb +126 -1
- data/lib/json/ld/frame.rb +3 -3
- data/lib/json/ld/from_rdf.rb +3 -3
- data/lib/json/ld/reader.rb +15 -5
- data/lib/json/ld/streaming_writer.rb +6 -6
- data/lib/json/ld/to_rdf.rb +75 -85
- data/lib/json/ld/utils.rb +1 -30
- data/lib/json/ld/writer.rb +86 -51
- data/spec/api_spec.rb +8 -8
- data/spec/compact_spec.rb +19 -19
- data/spec/context_spec.rb +76 -96
- data/spec/expand_spec.rb +30 -30
- data/spec/flatten_spec.rb +3 -4
- data/spec/format_spec.rb +43 -0
- data/spec/frame_spec.rb +7 -9
- data/spec/from_rdf_spec.rb +25 -24
- data/spec/reader_spec.rb +4 -1
- data/spec/spec_helper.rb +0 -1
- data/spec/streaming_writer_spec.rb +18 -11
- data/spec/suite_helper.rb +29 -28
- data/spec/suite_to_rdf_spec.rb +0 -2
- data/spec/to_rdf_spec.rb +17 -18
- data/spec/writer_spec.rb +15 -11
- metadata +75 -35
- data/spec/matchers.rb +0 -67
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 41122ee834694585f5bccd788b5310ca40ece180
|
4
|
+
data.tar.gz: 7c6ab81c44cdc21260b6dc0b2c9882c96d3dd0c0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3fecd04504e2bc9b4a7c40cb867c95c8b0aec0afc560e928bf330642ac397571bad7bc6b61cdcd7e1deae115a859346aa27ef07e3aab079c19736e4dbc2a3b96
|
7
|
+
data.tar.gz: 52bb0c863bd72dbd28fa02caa1b2eeb93c263b9310f09a6ca2e9745ad4df3dccb6c013d77255a6d4467ec2a7dcf275297605dd48549bfd7c514ed432507f79b7
|
data/README.md
CHANGED
@@ -274,8 +274,8 @@ Note, the API method signatures differed in versions before 1.0, in that they al
|
|
274
274
|
* {JSON::LD::Writer}
|
275
275
|
|
276
276
|
## Dependencies
|
277
|
-
* [Ruby](http://ruby-lang.org/) (>=
|
278
|
-
* [RDF.rb](http://rubygems.org/gems/rdf) (>=
|
277
|
+
* [Ruby](http://ruby-lang.org/) (>= 2.0)
|
278
|
+
* [RDF.rb](http://rubygems.org/gems/rdf) (>= 2.0)
|
279
279
|
* [JSON](https://rubygems.org/gems/json) (>= 1.5)
|
280
280
|
|
281
281
|
## Installation
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
2.0.0.beta1
|
data/lib/json/ld.rb
CHANGED
data/lib/json/ld/api.rb
CHANGED
@@ -28,6 +28,7 @@ module JSON::LD
|
|
28
28
|
include Flatten
|
29
29
|
include FromRDF
|
30
30
|
include Frame
|
31
|
+
include RDF::Util::Logger
|
31
32
|
|
32
33
|
# Options used for open_file
|
33
34
|
OPEN_OPTS = {
|
@@ -78,7 +79,7 @@ module JSON::LD
|
|
78
79
|
# @option options [Boolean] :rename_bnodes (true)
|
79
80
|
# Rename bnodes as part of expansion, or keep them the same.
|
80
81
|
# @option options [Boolean] :unique_bnodes (false)
|
81
|
-
# Use unique bnode identifiers, defaults to using the identifier which the node was
|
82
|
+
# Use unique bnode identifiers, defaults to using the identifier which the node was originall initialized with (if any).
|
82
83
|
# @option options [Boolean] :simple_compact_iris (false)
|
83
84
|
# When compacting IRIs, do not use terms with expanded term definitions
|
84
85
|
# @option options [Symbol] :adapter used with MultiJson
|
@@ -132,7 +133,7 @@ module JSON::LD
|
|
132
133
|
context ||= (@value['@context'] if @value.is_a?(Hash)) || context_ref
|
133
134
|
@context = Context.new(@options)
|
134
135
|
@context = @context.parse(context) if context
|
135
|
-
|
136
|
+
|
136
137
|
if block_given?
|
137
138
|
case block.arity
|
138
139
|
when 0, -1 then instance_eval(&block)
|
@@ -206,7 +207,7 @@ module JSON::LD
|
|
206
207
|
expanded = options[:expanded] ? input : API.expand(input, options)
|
207
208
|
|
208
209
|
API.new(expanded, context, options) do
|
209
|
-
|
210
|
+
log_debug(".compact") {"expanded input: #{expanded.to_json(JSON_STATE) rescue 'malformed json'}"}
|
210
211
|
result = compact(value, nil)
|
211
212
|
|
212
213
|
# xxx) Add the given context to the output
|
@@ -248,7 +249,7 @@ module JSON::LD
|
|
248
249
|
|
249
250
|
# Initialize input using
|
250
251
|
API.new(expanded_input, context, options) do
|
251
|
-
|
252
|
+
log_debug(".flatten") {"expanded input: #{value.to_json(JSON_STATE) rescue 'malformed json'}"}
|
252
253
|
|
253
254
|
# Initialize node map to a JSON object consisting of a single member whose key is @default and whose value is an empty JSON object.
|
254
255
|
graphs = {'@default' => {}}
|
@@ -269,7 +270,7 @@ module JSON::LD
|
|
269
270
|
|
270
271
|
if context && !flattened.empty?
|
271
272
|
# Otherwise, return the result of compacting flattened according the Compaction algorithm passing context ensuring that the compaction result uses the @graph keyword (or its alias) at the top-level, even if the context is empty or if there is only one element to put in the @graph array. This ensures that the returned document has a deterministic structure.
|
272
|
-
compacted =
|
273
|
+
compacted = log_depth {compact(flattened, nil)}
|
273
274
|
compacted = [compacted] unless compacted.is_a?(Array)
|
274
275
|
kwgraph = self.context.compact_iri('@graph', quiet: true)
|
275
276
|
flattened = self.context.serialize.merge(kwgraph => compacted)
|
@@ -350,30 +351,30 @@ module JSON::LD
|
|
350
351
|
|
351
352
|
# Initialize input using frame as context
|
352
353
|
API.new(expanded_input, nil, options) do
|
353
|
-
#
|
354
|
-
|
354
|
+
#log_debug(".frame") {"context from frame: #{context.inspect}"}
|
355
|
+
log_debug(".frame") {"expanded frame: #{expanded_frame.to_json(JSON_STATE) rescue 'malformed json'}"}
|
355
356
|
|
356
357
|
# Get framing nodes from expanded input, replacing Blank Node identifiers as necessary
|
357
|
-
|
358
|
+
old_logger, @options[:logger] = @options[:logger], []
|
358
359
|
create_node_map(value, framing_state[:graphs], '@merged')
|
359
|
-
@options[:
|
360
|
+
@options[:logger] = old_logger
|
360
361
|
framing_state[:subjects] = framing_state[:graphs]['@merged']
|
361
|
-
|
362
|
+
log_debug(".frame") {"subjects: #{framing_state[:subjects].to_json(JSON_STATE) rescue 'malformed json'}"}
|
362
363
|
|
363
364
|
result = []
|
364
365
|
frame(framing_state, framing_state[:subjects].keys.sort, (expanded_frame.first || {}), options.merge(parent: result))
|
365
|
-
|
366
|
+
log_debug(".frame") {"after frame: #{result.to_json(JSON_STATE) rescue 'malformed json'}"}
|
366
367
|
|
367
368
|
# Initalize context from frame
|
368
|
-
@context =
|
369
|
+
@context = log_depth {@context.parse(frame['@context'])}
|
369
370
|
# Compact result
|
370
|
-
compacted =
|
371
|
+
compacted = log_depth {compact(result, nil)}
|
371
372
|
compacted = [compacted] unless compacted.is_a?(Array)
|
372
373
|
|
373
374
|
# Add the given context to the output
|
374
375
|
kwgraph = context.compact_iri('@graph', quiet: true)
|
375
376
|
result = context.serialize.merge({kwgraph => compacted})
|
376
|
-
|
377
|
+
log_debug(".frame") {"after compact: #{result.to_json(JSON_STATE) rescue 'malformed json'}"}
|
377
378
|
result = cleanup_preserve(result)
|
378
379
|
end
|
379
380
|
|
@@ -411,13 +412,24 @@ module JSON::LD
|
|
411
412
|
API.new(expanded_input, nil, options) do
|
412
413
|
# 1) Perform the Expansion Algorithm on the JSON-LD input.
|
413
414
|
# This removes any existing context to allow the given context to be cleanly applied.
|
414
|
-
|
415
|
+
log_debug(".toRdf") {"expanded input: #{expanded_input.to_json(JSON_STATE) rescue 'malformed json'}"}
|
415
416
|
|
416
|
-
#
|
417
|
-
|
418
|
-
|
417
|
+
# Generate _nodeMap_
|
418
|
+
graphs = {'@default' => {}}
|
419
|
+
create_node_map(expanded_input, graphs)
|
420
|
+
log_debug(".toRdf") {"node map: #{graphs.to_json(JSON_STATE) rescue 'malformed json'}"}
|
421
|
+
|
422
|
+
# Start generating statements
|
423
|
+
graphs.each do |graph_name, graph|
|
424
|
+
context = as_resource(graph_name) unless graph_name == '@default'
|
425
|
+
log_debug(".toRdf") {"graph_name: #{context ? context.to_ntriples : 'null'}"}
|
426
|
+
# Drop results for graphs which are named with relative IRIs
|
427
|
+
if graph_name.is_a?(RDF::URI) && !graph_name.absolute
|
428
|
+
log_debug(".toRdf") {"drop relative graph_name: #{statement.to_ntriples}"}
|
429
|
+
next
|
430
|
+
end
|
431
|
+
graph_to_rdf(graph) do |statement|
|
419
432
|
next if statement.predicate.node? && !options[:produceGeneralizedRdf]
|
420
|
-
|
421
433
|
# Drop results with relative IRIs
|
422
434
|
relative = statement.to_a.any? do |r|
|
423
435
|
case r
|
@@ -430,11 +442,16 @@ module JSON::LD
|
|
430
442
|
end
|
431
443
|
end
|
432
444
|
if relative
|
433
|
-
|
445
|
+
log_debug(".toRdf") {"drop statement with relative IRIs: #{statement.to_ntriples}"}
|
434
446
|
next
|
435
447
|
end
|
436
448
|
|
437
|
-
|
449
|
+
statement.graph_name = context if context
|
450
|
+
if block_given?
|
451
|
+
yield statement
|
452
|
+
else
|
453
|
+
results << statement
|
454
|
+
end
|
438
455
|
end
|
439
456
|
end
|
440
457
|
end
|
data/lib/json/ld/compact.rb
CHANGED
@@ -10,23 +10,23 @@ module JSON::LD
|
|
10
10
|
# @return [Array, Hash]
|
11
11
|
def compact(element, property = nil)
|
12
12
|
if property.nil?
|
13
|
-
|
13
|
+
log_debug("compact") {"element: #{element.inspect}, ec: #{context.inspect}"}
|
14
14
|
else
|
15
|
-
|
15
|
+
log_debug("compact") {"property: #{property.inspect}"}
|
16
16
|
end
|
17
17
|
case element
|
18
18
|
when Array
|
19
|
-
|
20
|
-
result =
|
19
|
+
log_debug("") {"Array #{element.inspect}"}
|
20
|
+
result = log_depth {element.map {|item| compact(item, property)}.compact}
|
21
21
|
|
22
22
|
# If element has a single member and the active property has no
|
23
23
|
# @container mapping to @list or @set, the compacted value is that
|
24
24
|
# member; otherwise the compacted value is element
|
25
25
|
if result.length == 1 && context.container(property).nil? && @options[:compactArrays]
|
26
|
-
|
26
|
+
log_debug("=> extract single element: #{result.first.inspect}")
|
27
27
|
result.first
|
28
28
|
else
|
29
|
-
|
29
|
+
log_debug("=> array result: #{result.inspect}")
|
30
30
|
result
|
31
31
|
end
|
32
32
|
when Hash
|
@@ -36,9 +36,9 @@ module JSON::LD
|
|
36
36
|
return nil if element.has_key?('@null')
|
37
37
|
|
38
38
|
if element.keys.any? {|k| %w(@id @value).include?(k)}
|
39
|
-
result = context.compact_value(property, element,
|
39
|
+
result = context.compact_value(property, element, log_depth: @options[:log_depth])
|
40
40
|
unless result.is_a?(Hash)
|
41
|
-
|
41
|
+
log_debug("") {"=> scalar result: #{result.inspect}"}
|
42
42
|
return result
|
43
43
|
end
|
44
44
|
end
|
@@ -48,28 +48,28 @@ module JSON::LD
|
|
48
48
|
|
49
49
|
element.each_key do |expanded_property|
|
50
50
|
expanded_value = element[expanded_property]
|
51
|
-
|
51
|
+
log_debug("") {"#{expanded_property}: #{expanded_value.inspect}"}
|
52
52
|
|
53
53
|
if %w(@id @type).include?(expanded_property)
|
54
54
|
compacted_value = [expanded_value].flatten.compact.map do |expanded_type|
|
55
|
-
|
55
|
+
log_depth {context.compact_iri(expanded_type, vocab: (expanded_property == '@type'), log_depth: @options[:log_depth])}
|
56
56
|
end
|
57
57
|
compacted_value = compacted_value.first if compacted_value.length == 1
|
58
58
|
|
59
59
|
al = context.compact_iri(expanded_property, vocab: true, quiet: true)
|
60
|
-
|
60
|
+
log_debug(expanded_property) {"result[#{al}] = #{compacted_value.inspect}"}
|
61
61
|
result[al] = compacted_value
|
62
62
|
next
|
63
63
|
end
|
64
64
|
|
65
65
|
if expanded_property == '@reverse'
|
66
|
-
compacted_value =
|
67
|
-
|
66
|
+
compacted_value = log_depth {compact(expanded_value, '@reverse')}
|
67
|
+
log_debug("@reverse") {"compacted_value: #{compacted_value.inspect}"}
|
68
68
|
compacted_value.each do |prop, value|
|
69
69
|
if context.reverse?(prop)
|
70
70
|
value = [value] if !value.is_a?(Array) &&
|
71
71
|
(context.container(prop) == '@set' || !@options[:compactArrays])
|
72
|
-
|
72
|
+
log_debug("") {"merge #{prop} => #{value.inspect}"}
|
73
73
|
merge_compacted_value(result, prop, value)
|
74
74
|
compacted_value.delete(prop)
|
75
75
|
end
|
@@ -77,32 +77,32 @@ module JSON::LD
|
|
77
77
|
|
78
78
|
unless compacted_value.empty?
|
79
79
|
al = context.compact_iri('@reverse', quiet: true)
|
80
|
-
|
80
|
+
log_debug("") {"remainder: #{al} => #{compacted_value.inspect}"}
|
81
81
|
result[al] = compacted_value
|
82
82
|
end
|
83
83
|
next
|
84
84
|
end
|
85
85
|
|
86
86
|
if expanded_property == '@index' && context.container(property) == '@index'
|
87
|
-
|
87
|
+
log_debug("@index") {"drop @index"}
|
88
88
|
next
|
89
89
|
end
|
90
90
|
|
91
91
|
# Otherwise, if expanded property is @index, @value, or @language:
|
92
92
|
if %w(@index @value @language).include?(expanded_property)
|
93
93
|
al = context.compact_iri(expanded_property, vocab: true, quiet: true)
|
94
|
-
|
94
|
+
log_debug(expanded_property) {"#{al} => #{expanded_value.inspect}"}
|
95
95
|
result[al] = expanded_value
|
96
96
|
next
|
97
97
|
end
|
98
98
|
|
99
99
|
if expanded_value == []
|
100
|
-
item_active_property =
|
100
|
+
item_active_property = log_depth do
|
101
101
|
context.compact_iri(expanded_property,
|
102
102
|
value: expanded_value,
|
103
103
|
vocab: true,
|
104
104
|
reverse: inside_reverse,
|
105
|
-
|
105
|
+
log_depth: @options[:log_depth])
|
106
106
|
end
|
107
107
|
|
108
108
|
iap = result[item_active_property] ||= []
|
@@ -111,17 +111,17 @@ module JSON::LD
|
|
111
111
|
|
112
112
|
# At this point, expanded value must be an array due to the Expansion algorithm.
|
113
113
|
expanded_value.each do |expanded_item|
|
114
|
-
item_active_property =
|
114
|
+
item_active_property = log_depth do
|
115
115
|
context.compact_iri(expanded_property,
|
116
116
|
value: expanded_item,
|
117
117
|
vocab: true,
|
118
118
|
reverse: inside_reverse,
|
119
|
-
|
119
|
+
log_depth: @options[:log_depth])
|
120
120
|
end
|
121
121
|
container = context.container(item_active_property)
|
122
122
|
value = list?(expanded_item) ? expanded_item['@list'] : expanded_item
|
123
|
-
compacted_item =
|
124
|
-
|
123
|
+
compacted_item = log_depth {compact(value, item_active_property)}
|
124
|
+
log_debug("") {" => compacted key: #{item_active_property.inspect} for #{compacted_item.inspect}"}
|
125
125
|
|
126
126
|
if list?(expanded_item)
|
127
127
|
compacted_item = [compacted_item] unless compacted_item.is_a?(Array)
|
@@ -159,7 +159,7 @@ module JSON::LD
|
|
159
159
|
result.keys.kw_sort.inject({}) {|map, kk| map[kk] = result[kk]; map}
|
160
160
|
else
|
161
161
|
# For other types, the compacted value is the element value
|
162
|
-
|
162
|
+
log_debug("compact") {element.class.to_s}
|
163
163
|
element
|
164
164
|
end
|
165
165
|
end
|
data/lib/json/ld/context.rb
CHANGED
@@ -4,6 +4,7 @@ require 'bigdecimal'
|
|
4
4
|
module JSON::LD
|
5
5
|
class Context
|
6
6
|
include Utils
|
7
|
+
include RDF::Util::Logger
|
7
8
|
|
8
9
|
# Term Definitions specify how properties and values have to be interpreted as well as the current vocabulary mapping and the default language
|
9
10
|
class TermDefinition
|
@@ -179,7 +180,7 @@ module JSON::LD
|
|
179
180
|
self.vocab = options[:vocab] if options[:vocab]
|
180
181
|
self.default_language = options[:language] if options[:language]
|
181
182
|
|
182
|
-
#
|
183
|
+
#log_debug("init") {"iri_to_term: #{iri_to_term.inspect}"}
|
183
184
|
|
184
185
|
yield(self) if block_given?
|
185
186
|
end
|
@@ -254,30 +255,30 @@ module JSON::LD
|
|
254
255
|
local_context = [local_context] unless local_context.is_a?(Array)
|
255
256
|
|
256
257
|
local_context.each do |context|
|
257
|
-
|
258
|
+
log_depth do
|
258
259
|
case context
|
259
260
|
when nil
|
260
261
|
# 3.1 If niil, set to a new empty context
|
261
262
|
result = Context.new(options)
|
262
263
|
when Context
|
263
|
-
|
264
|
+
log_debug("parse") {"context: #{context.inspect}"}
|
264
265
|
result = context.dup
|
265
266
|
when IO, StringIO
|
266
|
-
|
267
|
+
log_debug("parse") {"io: #{context}"}
|
267
268
|
# Load context document, if it is a string
|
268
269
|
begin
|
269
270
|
ctx = JSON.load(context)
|
270
271
|
raise JSON::LD::JsonLdError::InvalidRemoteContext, "Context missing @context key" if @options[:validate] && ctx['@context'].nil?
|
271
|
-
result =
|
272
|
+
result = parse(ctx["@context"] ? ctx["@context"].dup : {})
|
272
273
|
result.provided_context = ctx["@context"] if [context] == local_context
|
273
274
|
result
|
274
275
|
rescue JSON::ParserError => e
|
275
|
-
|
276
|
+
log_debug("parse") {"Failed to parse @context from remote document at #{context}: #{e.message}"}
|
276
277
|
raise JSON::LD::JsonLdError::InvalidRemoteContext, "Failed to parse remote context at #{context}: #{e.message}" if @options[:validate]
|
277
278
|
self.dup
|
278
279
|
end
|
279
280
|
when String, RDF::URI
|
280
|
-
|
281
|
+
log_debug("parse") {"remote: #{context}, base: #{result.context_base || result.base}"}
|
281
282
|
# Load context document, if it is a string
|
282
283
|
# 3.2.1) Set context to the result of resolving value against the base IRI which is established as specified in section 5.1 Establishing a Base URI of [RFC3986]. Only the basic algorithm in section 5.2 of [RFC3986] is used; neither Syntax-Based Normalization nor Scheme-Based Normalization are performed. Characters additionally allowed in IRI references are treated in the same way that unreserved characters are treated in URI references, per section 6.5 of [RFC3987].
|
283
284
|
context = RDF::URI(result.context_base || result.base).join(context)
|
@@ -285,7 +286,7 @@ module JSON::LD
|
|
285
286
|
raise JsonLdError::RecursiveContextInclusion, "#{context}" if remote_contexts.include?(context.to_s)
|
286
287
|
remote_contexts << context.to_s
|
287
288
|
|
288
|
-
context_no_base =
|
289
|
+
context_no_base = self.dup
|
289
290
|
context_no_base.base = nil
|
290
291
|
context_no_base.context_base = context.to_s
|
291
292
|
|
@@ -305,12 +306,12 @@ module JSON::LD
|
|
305
306
|
end
|
306
307
|
end
|
307
308
|
rescue JsonLdError::LoadingDocumentFailed => e
|
308
|
-
|
309
|
+
log_debug("parse") {"Failed to retrieve @context from remote document at #{context_no_base.context_base.inspect}: #{e.message}"}
|
309
310
|
raise JsonLdError::LoadingRemoteContextFailed, "#{context_no_base.context_base}", e.backtrace
|
310
311
|
rescue JsonLdError
|
311
312
|
raise
|
312
313
|
rescue Exception => e
|
313
|
-
|
314
|
+
log_debug("parse") {"Failed to retrieve @context from remote document at #{context_no_base.context_base.inspect}: #{e.message}"}
|
314
315
|
raise JsonLdError::LoadingRemoteContextFailed, "#{context_no_base.context_base}", e.backtrace
|
315
316
|
end
|
316
317
|
|
@@ -319,7 +320,7 @@ module JSON::LD
|
|
319
320
|
context.provided_context = result.provided_context
|
320
321
|
context.base ||= result.base
|
321
322
|
result = context
|
322
|
-
|
323
|
+
log_debug("parse") {"=> provided_context: #{context.inspect}"}
|
323
324
|
when Hash
|
324
325
|
# If context has a @vocab member: if its value is not a valid absolute IRI or null trigger an INVALID_VOCAB_MAPPING error; otherwise set the active context's vocabulary mapping to its value and remove the @vocab member from context.
|
325
326
|
context = context.dup # keep from modifying a hash passed as a param
|
@@ -331,14 +332,14 @@ module JSON::LD
|
|
331
332
|
v = context.fetch(key, false)
|
332
333
|
unless v == false
|
333
334
|
context.delete(key)
|
334
|
-
|
335
|
+
log_debug("parse") {"Set #{key} to #{v.inspect}"}
|
335
336
|
result.send(setter, v)
|
336
337
|
end
|
337
338
|
end
|
338
339
|
|
339
340
|
defined = {}
|
340
341
|
# For each key-value pair in context invoke the Create Term Definition subalgorithm, passing result for active context, context for local context, key, and defined
|
341
|
-
|
342
|
+
log_depth do
|
342
343
|
context.each_key do |key|
|
343
344
|
result.create_term_definition(context, key, defined)
|
344
345
|
end
|
@@ -394,7 +395,7 @@ module JSON::LD
|
|
394
395
|
# @see http://json-ld.org/spec/latest/json-ld-api/index.html#create-term-definition
|
395
396
|
def create_term_definition(local_context, term, defined)
|
396
397
|
# Expand a string value, unless it matches a keyword
|
397
|
-
|
398
|
+
log_debug("create_term_definition") {"term = #{term.inspect}"}
|
398
399
|
|
399
400
|
# If defined contains the key term, then the associated value must be true, indicating that the term definition has already been created, so return. Otherwise, a cyclical term definition has been detected, which is an error.
|
400
401
|
case defined[term]
|
@@ -424,12 +425,12 @@ module JSON::LD
|
|
424
425
|
case value
|
425
426
|
when nil, {'@id' => nil}
|
426
427
|
# If value equals null or value is a JSON object containing the key-value pair (@id-null), then set the term definition in active context to null, set the value associated with defined's key term to true, and return.
|
427
|
-
|
428
|
+
log_debug("") {"=> nil"}
|
428
429
|
term_definitions[term] = TermDefinition.new(term)
|
429
430
|
defined[term] = true
|
430
431
|
return
|
431
432
|
when Hash
|
432
|
-
|
433
|
+
log_debug("") {"Hash[#{term.inspect}] = #{value.inspect}"}
|
433
434
|
definition = TermDefinition.new(term)
|
434
435
|
definition.simple = simple_term
|
435
436
|
|
@@ -451,7 +452,7 @@ module JSON::LD
|
|
451
452
|
unless %w(@id @vocab).include?(type) || type.is_a?(RDF::URI) && type.absolute?
|
452
453
|
raise JsonLdError::InvalidTypeMapping, "unknown mapping for '@type': #{type.inspect} on term #{term.inspect}"
|
453
454
|
end
|
454
|
-
|
455
|
+
log_debug("") {"type_mapping: #{type.inspect}"}
|
455
456
|
definition.type_mapping = type
|
456
457
|
end
|
457
458
|
|
@@ -491,7 +492,7 @@ module JSON::LD
|
|
491
492
|
elsif term.include?(':')
|
492
493
|
# 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.
|
493
494
|
prefix, suffix = term.split(':')
|
494
|
-
|
495
|
+
log_depth {create_term_definition(local_context, prefix, defined)} if local_context.has_key?(prefix)
|
495
496
|
|
496
497
|
definition.id = if td = term_definitions[prefix]
|
497
498
|
# 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.
|
@@ -500,12 +501,12 @@ module JSON::LD
|
|
500
501
|
# Otherwise, term is an absolute IRI. Set the IRI mapping for definition to term
|
501
502
|
term
|
502
503
|
end
|
503
|
-
|
504
|
+
log_debug("") {"=> #{definition.id}"}
|
504
505
|
else
|
505
506
|
# Otherwise, active context must have a vocabulary mapping, otherwise an invalid value has been detected, which is an error. Set the IRI mapping for definition to the result of concatenating the value associated with the vocabulary mapping and term.
|
506
507
|
raise JsonLdError::InvalidIRIMapping, "relative term definition without vocab: #{term} on term #{term.inspect}" unless vocab
|
507
508
|
definition.id = vocab + term
|
508
|
-
|
509
|
+
log_debug("") {"=> #{definition.id}"}
|
509
510
|
end
|
510
511
|
|
511
512
|
@iri_to_term[definition.id] = term if simple_term && definition.id
|
@@ -513,7 +514,7 @@ module JSON::LD
|
|
513
514
|
if value.has_key?('@container')
|
514
515
|
container = value['@container']
|
515
516
|
raise JsonLdError::InvalidContainerMapping, "unknown mapping for '@container' to #{container.inspect} on term #{term.inspect}" unless %w(@list @set @language @index).include?(container)
|
516
|
-
|
517
|
+
log_debug("") {"container_mapping: #{container.inspect}"}
|
517
518
|
definition.container_mapping = container
|
518
519
|
end
|
519
520
|
|
@@ -521,7 +522,7 @@ module JSON::LD
|
|
521
522
|
language = value['@language']
|
522
523
|
raise JsonLdError::InvalidLanguageMapping, "language must be null or a string, was #{language.inspect}} on term #{term.inspect}" unless language.nil? || (language || "").is_a?(String)
|
523
524
|
language = language.downcase if language.is_a?(String)
|
524
|
-
|
525
|
+
log_debug("") {"language_mapping: #{language.inspect}"}
|
525
526
|
definition.language_mapping = language || false
|
526
527
|
end
|
527
528
|
|
@@ -541,18 +542,18 @@ module JSON::LD
|
|
541
542
|
# @param [Hash{Symbol => Object}] options ({})
|
542
543
|
# @return [Hash]
|
543
544
|
def serialize(options = {})
|
544
|
-
|
545
|
+
log_depth(options) do
|
545
546
|
# FIXME: not setting provided_context now
|
546
547
|
use_context = case provided_context
|
547
548
|
when String, RDF::URI
|
548
|
-
|
549
|
+
log_debug "serlialize: reuse context: #{provided_context.inspect}"
|
549
550
|
provided_context.to_s
|
550
551
|
when Hash, Array
|
551
|
-
|
552
|
+
log_debug "serlialize: reuse context: #{provided_context.inspect}"
|
552
553
|
provided_context
|
553
554
|
else
|
554
|
-
|
555
|
-
|
555
|
+
log_debug("serlialize: generate context")
|
556
|
+
log_debug("") {"=> context: #{inspect}"}
|
556
557
|
ctx = {}
|
557
558
|
ctx['@base'] = base.to_s if base && base != doc_base
|
558
559
|
ctx['@language'] = default_language.to_s if default_language
|
@@ -564,7 +565,7 @@ module JSON::LD
|
|
564
565
|
ctx[term] = defn if defn
|
565
566
|
end
|
566
567
|
|
567
|
-
|
568
|
+
log_debug("") {"start_doc: context=#{ctx.inspect}"}
|
568
569
|
ctx
|
569
570
|
end
|
570
571
|
|
@@ -657,7 +658,7 @@ module JSON::LD
|
|
657
658
|
#
|
658
659
|
# @return [TermDefinition]
|
659
660
|
def set_mapping(term, value)
|
660
|
-
|
661
|
+
log_debug("") {"map #{term.inspect} to #{value.inspect}"}
|
661
662
|
term = term.to_s
|
662
663
|
term_definitions[term] = TermDefinition.new(term, value)
|
663
664
|
term_definitions[term].simple = true
|
@@ -750,26 +751,26 @@ module JSON::LD
|
|
750
751
|
return value unless value.is_a?(String)
|
751
752
|
|
752
753
|
return value if KEYWORDS.include?(value)
|
753
|
-
|
754
|
-
|
754
|
+
log_depth(options) do
|
755
|
+
log_debug("expand_iri") {"value: #{value.inspect}"} unless options[:quiet]
|
755
756
|
local_context = options[:local_context]
|
756
757
|
defined = options.fetch(:defined, {})
|
757
758
|
|
758
759
|
# 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.
|
759
760
|
if local_context && local_context.has_key?(value) && !defined[value]
|
760
|
-
|
761
|
+
log_depth {create_term_definition(local_context, value, defined)}
|
761
762
|
end
|
762
763
|
|
763
764
|
# If vocab is true and the active context has a term definition for value, return the associated IRI mapping.
|
764
765
|
if options[:vocab] && (v_td = term_definitions[value])
|
765
|
-
|
766
|
+
log_debug("") {"match with #{v_td.id}"} unless options[:quiet]
|
766
767
|
return v_td.id
|
767
768
|
end
|
768
769
|
|
769
770
|
# If value contains a colon (:), it is either an absolute IRI or a compact IRI:
|
770
771
|
if value.include?(':')
|
771
772
|
prefix, suffix = value.split(':', 2)
|
772
|
-
|
773
|
+
log_debug("") {"prefix: #{prefix.inspect}, suffix: #{suffix.inspect}, vocab: #{vocab.inspect}"} unless options[:quiet]
|
773
774
|
|
774
775
|
# If prefix is underscore (_) or suffix begins with double-forward-slash (//), return value as it is already an absolute IRI or a blank node identifier.
|
775
776
|
return RDF::Node.new(namer.get_sym(suffix)) if prefix == '_'
|
@@ -788,10 +789,10 @@ module JSON::LD
|
|
788
789
|
RDF::URI(value)
|
789
790
|
end
|
790
791
|
|
791
|
-
|
792
|
+
log_debug("") {"=> #{result.inspect}"} unless options[:quiet]
|
792
793
|
return result
|
793
794
|
end
|
794
|
-
|
795
|
+
log_debug("") {"=> #{result.inspect}"} unless options[:quiet]
|
795
796
|
|
796
797
|
result = if options[:vocab] && vocab
|
797
798
|
# If vocab is true, and active context has a vocabulary mapping, return the result of concatenating the vocabulary mapping with value.
|
@@ -806,7 +807,7 @@ module JSON::LD
|
|
806
807
|
else
|
807
808
|
RDF::URI(value)
|
808
809
|
end
|
809
|
-
|
810
|
+
log_debug("") {"=> #{result}"} unless options[:quiet]
|
810
811
|
result
|
811
812
|
end
|
812
813
|
end
|
@@ -828,13 +829,13 @@ module JSON::LD
|
|
828
829
|
def compact_iri(iri, options = {})
|
829
830
|
return if iri.nil?
|
830
831
|
iri = iri.to_s
|
831
|
-
|
832
|
-
|
832
|
+
log_debug("compact_iri(#{iri.inspect}", options) {options.inspect} unless options[:quiet]
|
833
|
+
log_depth(options) do
|
833
834
|
|
834
835
|
value = options.fetch(:value, nil)
|
835
836
|
|
836
837
|
if options[:vocab] && inverse_context.has_key?(iri)
|
837
|
-
|
838
|
+
log_debug("") {"vocab and key in inverse context"} unless options[:quiet]
|
838
839
|
default_language = self.default_language || @none
|
839
840
|
containers = []
|
840
841
|
tl, tl_value = "@language", "@null"
|
@@ -843,7 +844,7 @@ module JSON::LD
|
|
843
844
|
tl, tl_value = "@type", "@reverse"
|
844
845
|
containers << '@set'
|
845
846
|
elsif list?(value)
|
846
|
-
|
847
|
+
log_debug("") {"list(#{value.inspect})"} unless options[:quiet]
|
847
848
|
# if value is a list object, then set type/language and type/language value to the most specific values that work for all items in the list as follows:
|
848
849
|
containers << "@list" unless index?(value)
|
849
850
|
list = value['@list']
|
@@ -864,25 +865,25 @@ module JSON::LD
|
|
864
865
|
end
|
865
866
|
common_language ||= item_language
|
866
867
|
if item_language != common_language && value?(item)
|
867
|
-
|
868
|
+
log_debug("") {"-- #{item_language} conflicts with #{common_language}, use @none"} unless options[:quiet]
|
868
869
|
common_language = '@none'
|
869
870
|
end
|
870
871
|
common_type ||= item_type
|
871
872
|
if item_type != common_type
|
872
873
|
common_type = '@none'
|
873
|
-
|
874
|
+
log_debug("") {"#{item_type} conflicts with #{common_type}, use @none"} unless options[:quiet]
|
874
875
|
end
|
875
876
|
end
|
876
877
|
|
877
878
|
common_language ||= '@none'
|
878
879
|
common_type ||= '@none'
|
879
|
-
|
880
|
+
log_debug("") {"common type: #{common_type}, common language: #{common_language}"} unless options[:quiet]
|
880
881
|
if common_type != '@none'
|
881
882
|
tl, tl_value = '@type', common_type
|
882
883
|
else
|
883
884
|
tl_value = common_language
|
884
885
|
end
|
885
|
-
|
886
|
+
log_debug("") {"list: containers: #{containers.inspect}, type/language: #{tl.inspect}, type/language value: #{tl_value.inspect}"} unless options[:quiet]
|
886
887
|
else
|
887
888
|
if value?(value)
|
888
889
|
if value.has_key?('@language') && !index?(value)
|
@@ -896,7 +897,7 @@ module JSON::LD
|
|
896
897
|
tl, tl_value = '@type', '@id'
|
897
898
|
end
|
898
899
|
containers << '@set'
|
899
|
-
|
900
|
+
log_debug("") {"value: containers: #{containers.inspect}, type/language: #{tl.inspect}, type/language value: #{tl_value.inspect}"} unless options[:quiet]
|
900
901
|
end
|
901
902
|
|
902
903
|
containers << '@none'
|
@@ -913,9 +914,9 @@ module JSON::LD
|
|
913
914
|
else
|
914
915
|
preferred_values.concat([tl_value, '@none'])
|
915
916
|
end
|
916
|
-
|
917
|
+
log_debug("") {"preferred_values: #{preferred_values.inspect}"} unless options[:quiet]
|
917
918
|
if p_term = select_term(iri, containers, tl, preferred_values)
|
918
|
-
|
919
|
+
log_debug("") {"=> term: #{p_term.inspect}"} unless options[:quiet]
|
919
920
|
return p_term
|
920
921
|
end
|
921
922
|
end
|
@@ -923,7 +924,7 @@ module JSON::LD
|
|
923
924
|
# 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:
|
924
925
|
if options[:vocab] && vocab && iri.start_with?(vocab) && iri.length > vocab.length
|
925
926
|
suffix = iri[vocab.length..-1]
|
926
|
-
|
927
|
+
log_debug("") {"=> vocab suffix: #{suffix.inspect}"} unless options[:quiet]
|
927
928
|
return suffix unless term_definitions.has_key?(suffix)
|
928
929
|
end
|
929
930
|
|
@@ -943,7 +944,7 @@ module JSON::LD
|
|
943
944
|
end
|
944
945
|
|
945
946
|
if !candidates.empty?
|
946
|
-
|
947
|
+
log_debug("") {"=> compact iri: #{candidates.term_sort.first.inspect}"} unless options[:quiet]
|
947
948
|
return candidates.term_sort.first
|
948
949
|
end
|
949
950
|
|
@@ -959,7 +960,7 @@ module JSON::LD
|
|
959
960
|
end
|
960
961
|
|
961
962
|
if !candidates.empty?
|
962
|
-
|
963
|
+
log_debug("") {"=> standard prefies: #{candidates.term_sort.first.inspect}"} unless options[:quiet]
|
963
964
|
return candidates.term_sort.first
|
964
965
|
end
|
965
966
|
end
|
@@ -967,10 +968,10 @@ module JSON::LD
|
|
967
968
|
if !options[:vocab]
|
968
969
|
# transform iri to a relative IRI using the document's base IRI
|
969
970
|
iri = remove_base(iri)
|
970
|
-
|
971
|
+
log_debug("") {"=> relative iri: #{iri.inspect}"} unless options[:quiet]
|
971
972
|
return iri
|
972
973
|
else
|
973
|
-
|
974
|
+
log_debug("") {"=> absolute iri: #{iri.inspect}"} unless options[:quiet]
|
974
975
|
return iri
|
975
976
|
end
|
976
977
|
end
|
@@ -993,18 +994,18 @@ module JSON::LD
|
|
993
994
|
# @see http://json-ld.org/spec/latest/json-ld-api/#value-expansion
|
994
995
|
def expand_value(property, value, options = {})
|
995
996
|
options = {useNativeTypes: false}.merge!(options)
|
996
|
-
|
997
|
-
|
997
|
+
log_depth(options) do
|
998
|
+
log_debug("expand_value") {"property: #{property.inspect}, value: #{value.inspect}"}
|
998
999
|
|
999
1000
|
# If the active property has a type mapping in active context that is @id, return a new JSON object containing a single key-value pair where the key is @id and the value is the result of using the IRI Expansion algorithm, passing active context, value, and true for document relative.
|
1000
1001
|
if (td = term_definitions.fetch(property, TermDefinition.new(property))) && td.type_mapping == '@id'
|
1001
|
-
|
1002
|
+
log_debug("") {"as relative IRI: #{value.inspect}"}
|
1002
1003
|
return {'@id' => expand_iri(value, documentRelative: true).to_s}
|
1003
1004
|
end
|
1004
1005
|
|
1005
1006
|
# If active property has a type mapping in active context that is @vocab, return a new JSON object containing a single key-value pair where the key is @id and the value is the result of using the IRI Expansion algorithm, passing active context, value, true for vocab, and true for document relative.
|
1006
1007
|
if td.type_mapping == '@vocab'
|
1007
|
-
|
1008
|
+
log_debug("") {"as vocab IRI: #{value.inspect}"}
|
1008
1009
|
return {'@id' => expand_iri(value, vocab: true, documentRelative: true).to_s}
|
1009
1010
|
end
|
1010
1011
|
|
@@ -1015,10 +1016,10 @@ module JSON::LD
|
|
1015
1016
|
|
1016
1017
|
result = case value
|
1017
1018
|
when RDF::URI, RDF::Node
|
1018
|
-
|
1019
|
+
log_debug("URI | BNode") { value.to_s }
|
1019
1020
|
{'@id' => value.to_s}
|
1020
1021
|
when RDF::Literal
|
1021
|
-
|
1022
|
+
log_debug("Literal") {"datatype: #{value.datatype.inspect}"}
|
1022
1023
|
res = {}
|
1023
1024
|
if options[:useNativeTypes] && [RDF::XSD.boolean, RDF::XSD.integer, RDF::XSD.double].include?(value.datatype)
|
1024
1025
|
res['@value'] = value.object
|
@@ -1051,7 +1052,7 @@ module JSON::LD
|
|
1051
1052
|
res
|
1052
1053
|
end
|
1053
1054
|
|
1054
|
-
|
1055
|
+
log_debug("") {"=> #{result.inspect}"}
|
1055
1056
|
result
|
1056
1057
|
end
|
1057
1058
|
end
|
@@ -1071,53 +1072,53 @@ module JSON::LD
|
|
1071
1072
|
# FIXME: revisit the specification version of this.
|
1072
1073
|
def compact_value(property, value, options = {})
|
1073
1074
|
|
1074
|
-
|
1075
|
-
|
1075
|
+
log_depth(options) do
|
1076
|
+
log_debug("compact_value") {"property: #{property.inspect}, value: #{value.inspect}"}
|
1076
1077
|
|
1077
1078
|
num_members = value.keys.length
|
1078
1079
|
|
1079
1080
|
num_members -= 1 if index?(value) && container(property) == '@index'
|
1080
1081
|
if num_members > 2
|
1081
|
-
|
1082
|
+
log_debug("") {"can't compact value with # members > 2"}
|
1082
1083
|
return value
|
1083
1084
|
end
|
1084
1085
|
|
1085
1086
|
result = case
|
1086
1087
|
when coerce(property) == '@id' && value.has_key?('@id') && num_members == 1
|
1087
1088
|
# Compact an @id coercion
|
1088
|
-
|
1089
|
+
log_debug("") {" (@id & coerce)"}
|
1089
1090
|
compact_iri(value['@id'])
|
1090
1091
|
when coerce(property) == '@vocab' && value.has_key?('@id') && num_members == 1
|
1091
1092
|
# Compact an @id coercion
|
1092
|
-
|
1093
|
+
log_debug("") {" (@id & coerce & vocab)"}
|
1093
1094
|
compact_iri(value['@id'], vocab: true)
|
1094
1095
|
when value.has_key?('@id')
|
1095
|
-
|
1096
|
+
log_debug("") {" (@id)"}
|
1096
1097
|
# return value as is
|
1097
1098
|
value
|
1098
1099
|
when value['@type'] && expand_iri(value['@type'], vocab: true) == coerce(property)
|
1099
1100
|
# Compact common datatype
|
1100
|
-
|
1101
|
+
log_debug("") {" (@type & coerce) == #{coerce(property)}"}
|
1101
1102
|
value['@value']
|
1102
1103
|
when value['@language'] && (value['@language'] == language(property))
|
1103
1104
|
# Compact language
|
1104
|
-
|
1105
|
+
log_debug("") {" (@language) == #{language(property).inspect}"}
|
1105
1106
|
value['@value']
|
1106
1107
|
when num_members == 1 && !value['@value'].is_a?(String)
|
1107
|
-
|
1108
|
+
log_debug("") {" (native)"}
|
1108
1109
|
value['@value']
|
1109
1110
|
when num_members == 1 && default_language.nil? || language(property) == false
|
1110
|
-
|
1111
|
+
log_debug("") {" (!@language)"}
|
1111
1112
|
value['@value']
|
1112
1113
|
else
|
1113
1114
|
# Otherwise, use original value
|
1114
|
-
|
1115
|
+
log_debug("") {" (no change)"}
|
1115
1116
|
value
|
1116
1117
|
end
|
1117
1118
|
|
1118
1119
|
# If the result is an object, tranform keys using any term keyword aliases
|
1119
1120
|
if result.is_a?(Hash) && result.keys.any? {|k| self.alias(k) != k}
|
1120
|
-
|
1121
|
+
log_debug("") {" (map to key aliases)"}
|
1121
1122
|
new_element = {}
|
1122
1123
|
result.each do |k, v|
|
1123
1124
|
new_element[self.alias(k)] = v
|
@@ -1125,7 +1126,7 @@ module JSON::LD
|
|
1125
1126
|
result = new_element
|
1126
1127
|
end
|
1127
1128
|
|
1128
|
-
|
1129
|
+
log_debug("") {"=> #{result.inspect}"}
|
1129
1130
|
result
|
1130
1131
|
end
|
1131
1132
|
end
|
@@ -1194,7 +1195,7 @@ module JSON::LD
|
|
1194
1195
|
case value.to_s
|
1195
1196
|
when /^_:(.*)$/
|
1196
1197
|
# Map BlankNodes if a namer is given
|
1197
|
-
|
1198
|
+
log_debug "uri(bnode)#{value}: #{$1}"
|
1198
1199
|
bnode(namer.get_sym($1))
|
1199
1200
|
else
|
1200
1201
|
value = RDF::URI.new(value)
|
@@ -1273,26 +1274,26 @@ module JSON::LD
|
|
1273
1274
|
# for the type mapping or language mapping
|
1274
1275
|
# @return [String]
|
1275
1276
|
def select_term(iri, containers, type_language, preferred_values)
|
1276
|
-
|
1277
|
-
|
1277
|
+
log_depth do
|
1278
|
+
log_debug("select_term") {
|
1278
1279
|
"iri: #{iri.inspect}, " +
|
1279
1280
|
"containers: #{containers.inspect}, " +
|
1280
1281
|
"type_language: #{type_language.inspect}, " +
|
1281
1282
|
"preferred_values: #{preferred_values.inspect}"
|
1282
1283
|
}
|
1283
1284
|
container_map = inverse_context[iri]
|
1284
|
-
|
1285
|
+
log_debug(" ") {"container_map: #{container_map.inspect}"}
|
1285
1286
|
containers.each do |container|
|
1286
1287
|
next unless container_map.has_key?(container)
|
1287
1288
|
tl_map = container_map[container]
|
1288
1289
|
value_map = tl_map[type_language]
|
1289
1290
|
preferred_values.each do |item|
|
1290
1291
|
next unless value_map.has_key?(item)
|
1291
|
-
|
1292
|
+
log_debug("=>") {value_map[item].inspect}
|
1292
1293
|
return value_map[item]
|
1293
1294
|
end
|
1294
1295
|
end
|
1295
|
-
|
1296
|
+
log_debug("=>") {"nil"}
|
1296
1297
|
nil
|
1297
1298
|
end
|
1298
1299
|
end
|