json-ld 1.0.5 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +8 -8
- data/README.md +9 -8
- data/VERSION +1 -1
- data/bin/jsonld +2 -1
- data/lib/json/ld.rb +43 -42
- data/lib/json/ld/api.rb +184 -39
- data/lib/json/ld/compact.rb +1 -1
- data/lib/json/ld/context.rb +88 -58
- data/lib/json/ld/expand.rb +27 -25
- data/lib/json/ld/extensions.rb +0 -23
- data/lib/json/ld/flatten.rb +1 -1
- data/lib/json/ld/reader.rb +2 -2
- data/lib/json/ld/resource.rb +1 -1
- data/spec/api_spec.rb +3 -1
- data/spec/compact_spec.rb +6 -4
- data/spec/context_spec.rb +20 -35
- data/spec/expand_spec.rb +42 -22
- data/spec/frame_spec.rb +1 -1
- data/spec/from_rdf_spec.rb +4 -22
- data/spec/suite_compact_spec.rb +2 -19
- data/spec/suite_error_spec.rb +17 -0
- data/spec/suite_expand_spec.rb +2 -16
- data/spec/suite_flatten_spec.rb +2 -16
- data/spec/suite_frame_spec.rb +2 -16
- data/spec/suite_from_rdf_spec.rb +2 -18
- data/spec/suite_helper.rb +218 -60
- data/spec/suite_remote_doc_spec.rb +17 -0
- data/spec/suite_to_rdf_spec.rb +2 -19
- data/spec/to_rdf_spec.rb +5 -5
- data/spec/writer_spec.rb +3 -3
- metadata +8 -6
- data/spec/suite_error_expand_spec.rb +0 -23
data/lib/json/ld/compact.rb
CHANGED
@@ -133,7 +133,7 @@ module JSON::LD
|
|
133
133
|
compacted_item[key] = expanded_item['@index']
|
134
134
|
end
|
135
135
|
else
|
136
|
-
raise
|
136
|
+
raise JsonLdError::CompactionToListOfLists,
|
137
137
|
"key cannot have more than one list value" if result.has_key?(item_active_property)
|
138
138
|
end
|
139
139
|
end
|
data/lib/json/ld/context.rb
CHANGED
@@ -116,16 +116,19 @@ module JSON::LD
|
|
116
116
|
# @return [Context] A context provided to us that we can use without re-serializing XXX
|
117
117
|
attr_accessor :provided_context
|
118
118
|
|
119
|
-
# @!attribute [r] remote_contexts
|
120
|
-
# @return [Array<String>] The list of remote contexts already processed
|
121
|
-
attr_accessor :remote_contexts
|
122
|
-
|
123
119
|
# @!attribute [r] namer
|
124
120
|
# @return [BlankNodeNamer]
|
125
121
|
attr_accessor :namer
|
126
122
|
|
127
123
|
##
|
128
124
|
# Create new evaluation context
|
125
|
+
# @param [Hash] options
|
126
|
+
# @option options [String, #to_s] :base
|
127
|
+
# The Base IRI to use when expanding the document. This overrides the value of `input` if it is a _IRI_. If not specified and `input` is not an _IRI_, the base IRI defaults to the current document IRI if in a browser context, or the empty string if there is no document context.
|
128
|
+
# @option options [Proc] :documentLoader
|
129
|
+
# The callback of the loader to be used to retrieve remote documents and contexts. If specified, it must be used to retrieve remote documents and contexts; otherwise, if not specified, the processor's built-in loader must be used. See {API.documentLoader} for the method signature.
|
130
|
+
# @option options [Hash{Symbol => String}] :prefixes
|
131
|
+
# See `RDF::Reader#initialize`
|
129
132
|
# @yield [ec]
|
130
133
|
# @yieldparam [Context]
|
131
134
|
# @return [Context]
|
@@ -136,12 +139,12 @@ module JSON::LD
|
|
136
139
|
@doc_base.fragment = nil
|
137
140
|
@doc_base.query = nil
|
138
141
|
end
|
142
|
+
options[:documentLoader] ||= JSON::LD::API.method(:documentLoader)
|
139
143
|
@term_definitions = {}
|
140
144
|
@iri_to_term = {
|
141
145
|
RDF.to_uri.to_s => "rdf",
|
142
146
|
RDF::XSD.to_uri.to_s => "xsd"
|
143
147
|
}
|
144
|
-
@remote_contexts = []
|
145
148
|
@namer = BlankNodeMapper.new("t")
|
146
149
|
|
147
150
|
@options = options
|
@@ -151,7 +154,7 @@ module JSON::LD
|
|
151
154
|
@iri_to_term[v.to_s] = k unless k.nil?
|
152
155
|
end
|
153
156
|
|
154
|
-
debug("init") {"iri_to_term: #{iri_to_term.inspect}"}
|
157
|
+
#debug("init") {"iri_to_term: #{iri_to_term.inspect}"}
|
155
158
|
|
156
159
|
yield(self) if block_given?
|
157
160
|
end
|
@@ -159,12 +162,12 @@ module JSON::LD
|
|
159
162
|
# @param [String] value must be an absolute IRI
|
160
163
|
def base=(value)
|
161
164
|
if value
|
162
|
-
raise
|
165
|
+
raise JsonLdError::InvalidBaseIRI, "@base must be a string: #{value.inspect}" unless value.is_a?(String) || value.is_a?(RDF::URI)
|
163
166
|
@base = RDF::URI(value)
|
164
167
|
@base.canonicalize!
|
165
168
|
@base.fragment = nil
|
166
169
|
@base.query = nil
|
167
|
-
raise
|
170
|
+
raise JsonLdError::InvalidBaseIRI, "@base must be an absolute IRI: #{value.inspect}" unless @base.absolute?
|
168
171
|
@base
|
169
172
|
else
|
170
173
|
@base = nil
|
@@ -175,7 +178,7 @@ module JSON::LD
|
|
175
178
|
# @param [String] value
|
176
179
|
def default_language=(value)
|
177
180
|
@default_language = if value
|
178
|
-
raise
|
181
|
+
raise JsonLdError::InvalidDefaultLanguage, "@language must be a string: #{value.inspect}" unless value.is_a?(String)
|
179
182
|
value.downcase
|
180
183
|
else
|
181
184
|
nil
|
@@ -189,12 +192,12 @@ module JSON::LD
|
|
189
192
|
value
|
190
193
|
when String
|
191
194
|
v = as_resource(value)
|
192
|
-
raise
|
195
|
+
raise JsonLdError::InvalidVocabMapping, "@value must be an absolute IRI: #{value.inspect}" if v.uri? && v.relative?
|
193
196
|
v
|
194
197
|
when nil
|
195
198
|
nil
|
196
199
|
else
|
197
|
-
raise
|
200
|
+
raise JsonLdError::InvalidVocabMapping, "@value must be a string: #{value.inspect}"
|
198
201
|
end
|
199
202
|
end
|
200
203
|
|
@@ -208,7 +211,7 @@ module JSON::LD
|
|
208
211
|
#
|
209
212
|
#
|
210
213
|
# @param [String, #read, Array, Hash, Context] local_context
|
211
|
-
# @raise [
|
214
|
+
# @raise [JsonLdError]
|
212
215
|
# on a remote context load error, syntax error, or a reference to a term which is not defined.
|
213
216
|
# @see http://json-ld.org/spec/latest/json-ld-api/index.html#context-processing-algorithm
|
214
217
|
def parse(local_context, remote_contexts = [])
|
@@ -229,46 +232,57 @@ module JSON::LD
|
|
229
232
|
# Load context document, if it is a string
|
230
233
|
begin
|
231
234
|
ctx = JSON.load(context)
|
232
|
-
raise JSON::LD::
|
235
|
+
raise JSON::LD::JsonLdError::InvalidRemoteContext, "Context missing @context key" if @options[:validate] && ctx['@context'].nil?
|
233
236
|
result = parse(ctx["@context"] ? ctx["@context"].dup : {})
|
234
237
|
result.provided_context = ctx["@context"]
|
235
238
|
result
|
236
239
|
rescue JSON::ParserError => e
|
237
240
|
debug("parse") {"Failed to parse @context from remote document at #{context}: #{e.message}"}
|
238
|
-
raise JSON::LD::
|
241
|
+
raise JSON::LD::JsonLdError::InvalidRemoteContext, "Failed to parse remote context at #{context}: #{e.message}" if @options[:validate]
|
239
242
|
self.dup
|
240
243
|
end
|
241
|
-
when String
|
244
|
+
when String, RDF::URI
|
242
245
|
debug("parse") {"remote: #{context}, base: #{result.context_base || result.base}"}
|
243
246
|
# Load context document, if it is a string
|
244
|
-
|
245
|
-
|
246
|
-
context = RDF::URI(result.context_base || result.base).join(context)
|
247
|
+
# 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].
|
248
|
+
context = RDF::URI(result.context_base || result.base).join(context)
|
247
249
|
|
248
|
-
|
249
|
-
|
250
|
+
raise JsonLdError::RecursiveContextInclusion, "#{context}" if remote_contexts.include?(context.to_s)
|
251
|
+
remote_contexts << context.to_s
|
250
252
|
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
context_no_base.
|
253
|
+
context_no_base = self.dup
|
254
|
+
context_no_base.base = nil
|
255
|
+
unless @options[:processingMode] == "json-ld-1.0"
|
256
|
+
context_no_base.provided_context = context.to_s
|
257
|
+
end
|
258
|
+
context_no_base.context_base = context.to_s
|
255
259
|
|
256
|
-
|
260
|
+
begin
|
261
|
+
@options[:documentLoader].call(context.to_s) do |remote_doc|
|
257
262
|
# 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.
|
258
|
-
jo =
|
259
|
-
|
263
|
+
jo = case remote_doc.document
|
264
|
+
when String then JSON.parse(remote_doc.document)
|
265
|
+
else remote_doc.document
|
266
|
+
end
|
267
|
+
raise JsonLdError::InvalidRemoteContext, "#{context}" unless jo.is_a?(Hash) && jo.has_key?('@context')
|
260
268
|
context = jo['@context']
|
269
|
+
if @options[:processingMode] == "json-ld-1.0"
|
270
|
+
context_no_base.provided_context = context.dup
|
271
|
+
end
|
261
272
|
end
|
262
|
-
|
263
|
-
|
264
|
-
context = context_no_base.parse(context, remote_contexts.dup)
|
265
|
-
context.base = result.base unless result.base.nil?
|
266
|
-
result = context
|
267
|
-
debug("parse") {"=> provided_context: #{context.inspect}"}
|
273
|
+
rescue JsonLdError
|
274
|
+
raise
|
268
275
|
rescue Exception => e
|
269
276
|
debug("parse") {"Failed to retrieve @context from remote document at #{context_no_base.context_base.inspect}: #{e.message}"}
|
270
|
-
raise
|
277
|
+
raise JsonLdError::LoadingRemoteContextFailed, "#{context_no_base.context_base}", e.backtrace if @options[:validate]
|
271
278
|
end
|
279
|
+
|
280
|
+
# 3.2.6) Set context to the result of recursively calling this algorithm, passing context no base for active context, context for local context, and remote contexts.
|
281
|
+
context = context_no_base.parse(context, remote_contexts.dup)
|
282
|
+
context.provided_context = context_no_base.provided_context
|
283
|
+
context.base ||= result.base
|
284
|
+
result = context
|
285
|
+
debug("parse") {"=> provided_context: #{context.inspect}"}
|
272
286
|
when Hash
|
273
287
|
# 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.
|
274
288
|
{
|
@@ -293,7 +307,7 @@ module JSON::LD
|
|
293
307
|
end
|
294
308
|
else
|
295
309
|
# 3.3) If context is not a JSON object, an invalid local context error has been detected and processing is aborted.
|
296
|
-
raise
|
310
|
+
raise JsonLdError::InvalidLocalContext
|
297
311
|
end
|
298
312
|
end
|
299
313
|
end
|
@@ -311,7 +325,7 @@ module JSON::LD
|
|
311
325
|
# @param [Hash] local_context
|
312
326
|
# @param [String] term
|
313
327
|
# @param [Hash] defined
|
314
|
-
# @raise [
|
328
|
+
# @raise [JsonLdError]
|
315
329
|
# Represents a cyclical term dependency
|
316
330
|
# @see http://json-ld.org/spec/latest/json-ld-api/index.html#create-term-definition
|
317
331
|
def create_term_definition(local_context, term, defined)
|
@@ -324,15 +338,15 @@ module JSON::LD
|
|
324
338
|
when nil
|
325
339
|
defined[term] = false
|
326
340
|
else
|
327
|
-
raise
|
341
|
+
raise JsonLdError::CyclicIRIMapping, "Cyclical term dependency found for #{term.inspect}"
|
328
342
|
end
|
329
343
|
|
330
344
|
# Since keywords cannot be overridden, term must not be a keyword. Otherwise, an invalid value has been detected, which is an error.
|
331
345
|
if KEYWORDS.include?(term) && !%w(@vocab @language).include?(term)
|
332
|
-
raise
|
346
|
+
raise JsonLdError::KeywordRedefinition, "term #{term.inspect} must not be a keyword" if
|
333
347
|
@options[:validate]
|
334
348
|
elsif !term_valid?(term) && @options[:validate]
|
335
|
-
raise
|
349
|
+
raise JsonLdError::InvalidTermDefinition, "term #{term.inspect} is invalid"
|
336
350
|
end
|
337
351
|
|
338
352
|
# Remove any existing term definition for term in active context.
|
@@ -356,16 +370,29 @@ module JSON::LD
|
|
356
370
|
if value.has_key?('@type')
|
357
371
|
type = value['@type']
|
358
372
|
# SPEC FIXME: @type may be nil
|
359
|
-
|
360
|
-
|
373
|
+
type = case type
|
374
|
+
when nil
|
375
|
+
type
|
376
|
+
when String
|
377
|
+
begin
|
378
|
+
expand_iri(type, :vocab => true, :documentRelative => false, :local_context => local_context, :defined => defined)
|
379
|
+
rescue JsonLdError::InvalidIRIMapping
|
380
|
+
raise JsonLdError::InvalidTypeMapping, "invalid mapping for '@type' to #{type.inspect}"
|
381
|
+
end
|
382
|
+
else
|
383
|
+
:error
|
384
|
+
end
|
385
|
+
unless %w(@id @vocab).include?(type) || type.is_a?(RDF::URI) && type.absolute?
|
386
|
+
raise JsonLdError::InvalidTypeMapping, "unknown mapping for '@type' to #{type.inspect}"
|
387
|
+
end
|
361
388
|
debug("") {"type_mapping: #{type.inspect}"}
|
362
389
|
definition.type_mapping = type
|
363
390
|
end
|
364
391
|
|
365
392
|
if value.has_key?('@reverse')
|
366
|
-
raise
|
393
|
+
raise JsonLdError::InvalidReverseProperty, "unexpected key in #{value.inspect}" if
|
367
394
|
value.keys.any? {|k| %w(@id).include?(k)}
|
368
|
-
raise
|
395
|
+
raise JsonLdError::InvalidIRIMapping, "expected value of @reverse to be a string" unless
|
369
396
|
value['@reverse'].is_a?(String)
|
370
397
|
|
371
398
|
# Otherwise, set the IRI mapping of definition to the result of using the IRI Expansion algorithm, passing active context, the value associated with the @reverse key for value, true for vocab, true for document relative, local context, and defined. If the result is not an absolute IRI, i.e., it contains no colon (:), an invalid IRI mapping error has been detected and processing is aborted.
|
@@ -374,25 +401,27 @@ module JSON::LD
|
|
374
401
|
:documentRelative => true,
|
375
402
|
:local_context => local_context,
|
376
403
|
:defined => defined)
|
377
|
-
raise
|
378
|
-
definition.id.absolute?
|
404
|
+
raise JsonLdError::InvalidIRIMapping, "non-absolute @reverse IRI: #{definition.id}" unless
|
405
|
+
definition.id.is_a?(RDF::URI) && definition.id.absolute?
|
379
406
|
|
380
407
|
# If value contains an @container member, set the container mapping of definition to its value; if its value is neither @set, nor @index, nor null, an invalid reverse property error has been detected (reverse properties only support set- and index-containers) and processing is aborted.
|
381
408
|
if (container = value['@container'])
|
382
|
-
raise
|
409
|
+
raise JsonLdError::InvalidReverseProperty,
|
383
410
|
"unknown mapping for '@container' to #{container.inspect}" unless
|
384
411
|
['@set', '@index', nil].include?(container)
|
385
412
|
definition.container_mapping = container
|
386
413
|
end
|
387
414
|
definition.reverse_property = true
|
388
415
|
elsif value.has_key?('@id') && value['@id'] != term
|
389
|
-
raise
|
416
|
+
raise JsonLdError::InvalidIRIMapping, "expected value of @id to be a string" unless
|
390
417
|
value['@id'].is_a?(String)
|
391
418
|
definition.id = expand_iri(value['@id'],
|
392
419
|
:vocab => true,
|
393
420
|
:documentRelative => true,
|
394
421
|
:local_context => local_context,
|
395
422
|
:defined => defined)
|
423
|
+
raise JsonLdError::InvalidKeywordAlias, "expected value of @id to not be @context" if
|
424
|
+
definition.id == '@context'
|
396
425
|
elsif term.include?(':')
|
397
426
|
# 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.
|
398
427
|
prefix, suffix = term.split(':')
|
@@ -408,21 +437,21 @@ module JSON::LD
|
|
408
437
|
debug("") {"=> #{definition.id}"}
|
409
438
|
else
|
410
439
|
# 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.
|
411
|
-
raise
|
440
|
+
raise JsonLdError::InvalidIRIMapping, "relative term definition without vocab" unless vocab
|
412
441
|
definition.id = vocab + term
|
413
442
|
debug("") {"=> #{definition.id}"}
|
414
443
|
end
|
415
444
|
|
416
445
|
if value.has_key?('@container')
|
417
446
|
container = value['@container']
|
418
|
-
raise
|
447
|
+
raise JsonLdError::InvalidContainerMapping, "unknown mapping for '@container' to #{container.inspect}" unless %w(@list @set @language @index).include?(container)
|
419
448
|
debug("") {"container_mapping: #{container.inspect}"}
|
420
449
|
definition.container_mapping = container
|
421
450
|
end
|
422
451
|
|
423
452
|
if value.has_key?('@language')
|
424
453
|
language = value['@language']
|
425
|
-
raise
|
454
|
+
raise JsonLdError::InvalidLanguageMapping, "language must be null or a string, was #{language.inspect}}" unless language.nil? || (language || "").is_a?(String)
|
426
455
|
language = language.downcase if language.is_a?(String)
|
427
456
|
debug("") {"language_mapping: #{language.inspect}"}
|
428
457
|
definition.language_mapping = language || false
|
@@ -431,7 +460,7 @@ module JSON::LD
|
|
431
460
|
term_definitions[term] = definition
|
432
461
|
defined[term] = true
|
433
462
|
else
|
434
|
-
raise
|
463
|
+
raise JsonLdError::InvalidTermDefinition, "Term definition for #{term.inspect} is an #{value.class}"
|
435
464
|
end
|
436
465
|
end
|
437
466
|
|
@@ -447,7 +476,7 @@ module JSON::LD
|
|
447
476
|
depth(options) do
|
448
477
|
# FIXME: not setting provided_context now
|
449
478
|
use_context = case provided_context
|
450
|
-
when RDF::URI
|
479
|
+
when String, RDF::URI
|
451
480
|
debug "serlialize: reuse context: #{provided_context.inspect}"
|
452
481
|
provided_context.to_s
|
453
482
|
when Hash, Array
|
@@ -462,7 +491,7 @@ module JSON::LD
|
|
462
491
|
ctx['@vocab'] = vocab.to_s if vocab
|
463
492
|
|
464
493
|
# Term Definitions
|
465
|
-
term_definitions.each do |term, definition|
|
494
|
+
term_definitions.dup.each do |term, definition|
|
466
495
|
ctx[term] = definition.to_context_definition(self)
|
467
496
|
end
|
468
497
|
|
@@ -611,7 +640,7 @@ module JSON::LD
|
|
611
640
|
# Used during Context Processing.
|
612
641
|
# @return [RDF::URI, String]
|
613
642
|
# IRI or String, if it's a keyword
|
614
|
-
# @raise [JSON::LD::
|
643
|
+
# @raise [JSON::LD::JsonLdError::InvalidIRIMapping] if the value cannot be expanded
|
615
644
|
# @see http://json-ld.org/spec/latest/json-ld-api/#iri-expansion
|
616
645
|
def expand_iri(value, options = {})
|
617
646
|
return value unless value.is_a?(String)
|
@@ -668,7 +697,7 @@ module JSON::LD
|
|
668
697
|
RDF::URI(base).join(value)
|
669
698
|
elsif local_context && RDF::URI(value).relative?
|
670
699
|
# If local context is not null and value is not an absolute IRI, an invalid IRI mapping error has been detected and processing is aborted.
|
671
|
-
raise JSON::LD::
|
700
|
+
raise JSON::LD::JsonLdError::InvalidIRIMapping, "not an absolute IRI: #{value}"
|
672
701
|
else
|
673
702
|
RDF::URI(value)
|
674
703
|
end
|
@@ -813,7 +842,7 @@ module JSON::LD
|
|
813
842
|
# try those, and add to mapping
|
814
843
|
if @options[:standard_prefixes]
|
815
844
|
candidates = RDF::Vocabulary.
|
816
|
-
select {|v| iri.start_with?(v.to_uri.to_s)}.
|
845
|
+
select {|v| iri.start_with?(v.to_uri.to_s) && iri != v.to_uri.to_s}.
|
817
846
|
map do |v|
|
818
847
|
prefix = v.__name__.to_s.split('::').last.downcase
|
819
848
|
set_mapping(prefix, v.to_uri.to_s)
|
@@ -854,7 +883,7 @@ module JSON::LD
|
|
854
883
|
# @raise [RDF::ReaderError] if the iri cannot be expanded
|
855
884
|
# @see http://json-ld.org/spec/latest/json-ld-api/#value-expansion
|
856
885
|
def expand_value(property, value, options = {})
|
857
|
-
options = {:useNativeTypes =>
|
886
|
+
options = {:useNativeTypes => false}.merge(options)
|
858
887
|
depth(options) do
|
859
888
|
debug("expand_value") {"property: #{property.inspect}, value: #{value.inspect}"}
|
860
889
|
|
@@ -928,7 +957,7 @@ module JSON::LD
|
|
928
957
|
# @param [Hash{Symbol => Object}] options
|
929
958
|
#
|
930
959
|
# @return [Hash] Object representation of value
|
931
|
-
# @raise [
|
960
|
+
# @raise [JsonLdError] if the iri cannot be expanded
|
932
961
|
# @see http://json-ld.org/spec/latest/json-ld-api/#value-compaction
|
933
962
|
# FIXME: revisit the specification version of this.
|
934
963
|
def compact_value(property, value, options = {})
|
@@ -994,6 +1023,7 @@ module JSON::LD
|
|
994
1023
|
|
995
1024
|
def inspect
|
996
1025
|
v = %w([Context)
|
1026
|
+
v << "base=#{base}" if base
|
997
1027
|
v << "vocab=#{vocab}" if vocab
|
998
1028
|
v << "def_language=#{default_language}" if default_language
|
999
1029
|
v << "term_definitions[#{term_definitions.length}]=#{term_definitions}"
|
data/lib/json/ld/expand.rb
CHANGED
@@ -24,7 +24,7 @@ module JSON::LD
|
|
24
24
|
v = expand(v, active_property, context, options)
|
25
25
|
|
26
26
|
# If the active property is @list or its container mapping is set to @list, the expanded item must not be an array or a list object, otherwise a list of lists error has been detected and processing is aborted.
|
27
|
-
raise
|
27
|
+
raise JsonLdError::ListOfLists,
|
28
28
|
"A list may not contain another list" if
|
29
29
|
is_list && (v.is_a?(Array) || list?(v))
|
30
30
|
v
|
@@ -60,17 +60,17 @@ module JSON::LD
|
|
60
60
|
|
61
61
|
if KEYWORDS.include?(expanded_property)
|
62
62
|
# If active property equals @reverse, an invalid reverse property map error has been detected and processing is aborted.
|
63
|
-
raise
|
63
|
+
raise JsonLdError::InvalidReversePropertyMap,
|
64
64
|
"@reverse not appropriate at this point" if active_property == '@reverse'
|
65
65
|
|
66
66
|
# If result has already an expanded property member, an colliding keywords error has been detected and processing is aborted.
|
67
|
-
raise
|
67
|
+
raise JsonLdError::CollidingKeywords,
|
68
68
|
"#{expanded_property} already exists in result" if output_object.has_key?(expanded_property)
|
69
69
|
|
70
70
|
expanded_value = case expanded_property
|
71
71
|
when '@id'
|
72
72
|
# If expanded property is @id and value is not a string, an invalid @id value error has been detected and processing is aborted
|
73
|
-
raise
|
73
|
+
raise JsonLdError::InvalidIdValue,
|
74
74
|
"value of @id must be a string: #{value.inspect}" unless value.is_a?(String)
|
75
75
|
|
76
76
|
# Otherwise, set expanded value to the result of using the IRI Expansion algorithm, passing active context, value, and true for document relative.
|
@@ -82,7 +82,7 @@ module JSON::LD
|
|
82
82
|
when Array
|
83
83
|
depth do
|
84
84
|
value.map do |v|
|
85
|
-
raise
|
85
|
+
raise JsonLdError::InvalidTypeValue,
|
86
86
|
"@type value must be a string or array of strings: #{v.inspect}" unless v.is_a?(String)
|
87
87
|
context.expand_iri(v, :vocab => true, :documentRelative => true, :quiet => true, :depth => @depth).to_s
|
88
88
|
end
|
@@ -91,11 +91,11 @@ module JSON::LD
|
|
91
91
|
context.expand_iri(value, :vocab => true, :documentRelative => true, :quiet => true, :depth => @depth).to_s
|
92
92
|
when Hash
|
93
93
|
# For framing
|
94
|
-
raise
|
94
|
+
raise JsonLdError::InvalidTypeValue,
|
95
95
|
"@type value must be a an empty object for framing: #{value.inspect}" unless
|
96
96
|
value.empty?
|
97
97
|
else
|
98
|
-
raise
|
98
|
+
raise JsonLdError::InvalidTypeValue,
|
99
99
|
"@type value must be a string or array of strings: #{value.inspect}"
|
100
100
|
end
|
101
101
|
when '@graph'
|
@@ -103,7 +103,7 @@ module JSON::LD
|
|
103
103
|
depth { expand(value, '@graph', context, options) }
|
104
104
|
when '@value'
|
105
105
|
# If expanded property is @value and value is not a scalar or null, an invalid value object value error has been detected and processing is aborted. Otherwise, set expanded value to value. If expanded value is null, set the @value member of result to null and continue with the next key from element. Null values need to be preserved in this case as the meaning of an @type member depends on the existence of an @value member.
|
106
|
-
raise
|
106
|
+
raise JsonLdError::InvalidValueObjectValue,
|
107
107
|
"Value of #{expanded_property} must be a scalar or null: #{value.inspect}" if value.is_a?(Hash) || value.is_a?(Array)
|
108
108
|
if value.nil?
|
109
109
|
output_object['@value'] = nil
|
@@ -112,12 +112,12 @@ module JSON::LD
|
|
112
112
|
value
|
113
113
|
when '@language'
|
114
114
|
# If expanded property is @language and value is not a string, an invalid language-tagged string error has been detected and processing is aborted. Otherwise, set expanded value to lowercased value.
|
115
|
-
raise
|
115
|
+
raise JsonLdError::InvalidLanguageTaggedString,
|
116
116
|
"Value of #{expanded_property} must be a string: #{value.inspect}" unless value.is_a?(String)
|
117
117
|
value.downcase
|
118
118
|
when '@index'
|
119
119
|
# If expanded property is @index and value is not a string, an invalid @index value error has been detected and processing is aborted. Otherwise, set expanded value to value.
|
120
|
-
raise
|
120
|
+
raise JsonLdError::InvalidIndexValue,
|
121
121
|
"Value of @index is not a string: #{value.inspect}" unless value.is_a?(String)
|
122
122
|
value
|
123
123
|
when '@list'
|
@@ -134,7 +134,7 @@ module JSON::LD
|
|
134
134
|
|
135
135
|
# If expanded value is a list object, a list of lists error has been detected and processing is aborted.
|
136
136
|
# Spec FIXME: Also look at each object if result is an array
|
137
|
-
raise
|
137
|
+
raise JsonLdError::ListOfLists,
|
138
138
|
"A list may not contain another list" if value.any? {|v| list?(v)}
|
139
139
|
|
140
140
|
value
|
@@ -143,7 +143,7 @@ module JSON::LD
|
|
143
143
|
depth { expand(value, active_property, context, options) }
|
144
144
|
when '@reverse'
|
145
145
|
# If expanded property is @reverse and value is not a JSON object, an invalid @reverse value error has been detected and processing is aborted.
|
146
|
-
raise
|
146
|
+
raise JsonLdError::InvalidReverseValue,
|
147
147
|
"@reverse value must be an object: #{value.inspect}" unless value.is_a?(Hash)
|
148
148
|
|
149
149
|
# Otherwise
|
@@ -168,8 +168,8 @@ module JSON::LD
|
|
168
168
|
next if property == '@reverse'
|
169
169
|
items.each do |item|
|
170
170
|
if value?(item) || list?(item)
|
171
|
-
raise
|
172
|
-
|
171
|
+
raise JsonLdError::InvalidReversePropertyValue,
|
172
|
+
item.inspect
|
173
173
|
end
|
174
174
|
merge_value(reverse_map, property, item)
|
175
175
|
end
|
@@ -202,7 +202,7 @@ module JSON::LD
|
|
202
202
|
value.keys.sort.each do |k|
|
203
203
|
[value[k]].flatten.each do |item|
|
204
204
|
# item must be a string, otherwise an invalid language map value error has been detected and processing is aborted.
|
205
|
-
raise
|
205
|
+
raise JsonLdError::InvalidLanguageMapValue,
|
206
206
|
"Expected #{item.inspect} to be a string" unless item.is_a?(String)
|
207
207
|
|
208
208
|
# Append a JSON object to expanded value that consists of two key-value pairs: (@value-item) and (@language-lowercased language).
|
@@ -256,8 +256,8 @@ module JSON::LD
|
|
256
256
|
reverse_map = output_object['@reverse'] ||= {}
|
257
257
|
[expanded_value].flatten.each do |item|
|
258
258
|
# If item is a value object or list object, an invalid reverse property value has been detected and processing is aborted.
|
259
|
-
raise
|
260
|
-
|
259
|
+
raise JsonLdError::InvalidReversePropertyValue,
|
260
|
+
item.inspect if value?(item) || list?(item)
|
261
261
|
|
262
262
|
# If reverse map has no expanded property member, create one and initialize its value to an empty array.
|
263
263
|
# Append item to the value of the expanded property member of reverse map.
|
@@ -274,9 +274,10 @@ module JSON::LD
|
|
274
274
|
|
275
275
|
# If result contains the key @value:
|
276
276
|
if value?(output_object)
|
277
|
-
unless (output_object.keys - %w(@value @language @type @index)).empty?
|
277
|
+
unless (output_object.keys - %w(@value @language @type @index)).empty? &&
|
278
|
+
(output_object.keys & %w(@language @type)).length < 2
|
278
279
|
# The result must not contain any keys other than @value, @language, @type, and @index. It must not contain both the @language key and the @type key. Otherwise, an invalid value object error has been detected and processing is aborted.
|
279
|
-
raise
|
280
|
+
raise JsonLdError::InvalidValueObject,
|
280
281
|
"value object has unknown keys: #{output_object.inspect}"
|
281
282
|
end
|
282
283
|
|
@@ -288,12 +289,13 @@ module JSON::LD
|
|
288
289
|
|
289
290
|
if !output_object['@value'].is_a?(String) && output_object.has_key?('@language')
|
290
291
|
# Otherwise, if the value of result's @value member is not a string and result contains the key @language, an invalid language-tagged value error has been detected (only strings can be language-tagged) and processing is aborted.
|
291
|
-
raise
|
292
|
+
raise JsonLdError::InvalidLanguageTaggedValue,
|
292
293
|
"when @language is used, @value must be a string: #{@value.inspect}"
|
293
|
-
elsif !output_object.fetch('@type', "").is_a?(String)
|
294
|
-
|
295
|
-
|
296
|
-
|
294
|
+
elsif !output_object.fetch('@type', "").is_a?(String) ||
|
295
|
+
!context.expand_iri(output_object.fetch('@type', ""), :vocab => true, :depth => @depth).is_a?(RDF::URI)
|
296
|
+
# Otherwise, if the result has a @type member and its value is not an IRI, an invalid typed value error has been detected and processing is aborted.
|
297
|
+
raise JsonLdError::InvalidTypedValue,
|
298
|
+
"value of @type must be an IRI: #{output_object['@type'].inspect}"
|
297
299
|
end
|
298
300
|
elsif !output_object.fetch('@type', []).is_a?(Array)
|
299
301
|
# Otherwise, if result contains the key @type and its associated value is not an array, set it to an array containing only the associated value.
|
@@ -301,7 +303,7 @@ module JSON::LD
|
|
301
303
|
elsif output_object.keys.any? {|k| %w(@set @list).include?(k)}
|
302
304
|
# Otherwise, if result contains the key @set or @list:
|
303
305
|
# The result must contain at most one other key and that key must be @index. Otherwise, an invalid set or list object error has been detected and processing is aborted.
|
304
|
-
raise
|
306
|
+
raise JsonLdError::InvalidSetOrListObject,
|
305
307
|
"@set or @list may only contain @index: #{output_object.keys.inspect}" unless
|
306
308
|
(output_object.keys - %w(@set @list @index)).empty?
|
307
309
|
|