json-ld 1.0.1.1 → 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +14 -6
- data/README.md +2 -2
- data/VERSION +1 -1
- data/lib/json/ld/api.rb +8 -5
- data/lib/json/ld/compact.rb +2 -1
- data/lib/json/ld/context.rb +44 -33
- data/lib/json/ld/expand.rb +1 -1
- data/lib/json/ld/flatten.rb +9 -11
- data/lib/json/ld/from_rdf.rb +48 -45
- data/lib/json/ld/reader.rb +5 -0
- data/lib/json/ld/to_rdf.rb +5 -23
- data/lib/json/ld/utils.rb +9 -2
- data/spec/api_spec.rb +1 -1
- data/spec/compact_spec.rb +1 -2
- data/spec/flatten_spec.rb +3 -20
- data/spec/from_rdf_spec.rb +16 -29
- data/spec/matchers.rb +3 -3
- data/spec/reader_spec.rb +4 -4
- data/spec/suite_compact_spec.rb +0 -4
- data/spec/suite_to_rdf_spec.rb +2 -2
- data/spec/test-files/test-1-rdf.ttl +3 -3
- data/spec/test-files/test-3-rdf.ttl +1 -1
- data/spec/test-files/test-5-rdf.ttl +2 -2
- data/spec/test-files/test-6-rdf.ttl +2 -2
- data/spec/test-files/test-7-rdf.ttl +6 -6
- data/spec/to_rdf_spec.rb +32 -18
- data/spec/writer_spec.rb +0 -2
- metadata +33 -33
checksums.yaml
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
NzllY2IzN2M4MjQ5MGUxMWQ0M2NhYTliZWFmMzUyYzZmMDYwODIxOQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
OGM3NmQ5YTVhMDk3ZTE3NGZjNmM4MTc2NWQ0Y2NiNzhlZjllOWMxYw==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
ZjkxY2E1ZGZiZDM2M2EyMDUwMTFmZGIwNmI2YTYyMGRkYzI5YzQ4OTRkMTFm
|
10
|
+
N2VlZjE5OGEzN2FiMTcyY2U4MGVkOGMzN2RhOWIyZmQ2MTczMDNhMjI5NDli
|
11
|
+
MTBmZTJkOWEzZWYzZjE0Mjk5Mjc1YzgwOTA3YzFlZGZmZWVmYTI=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
NzNmZTU0YTA3OGQ0MmRjZjNlNzhlNzlkNzFlNDQ2OWY4YWM5MTIyNjA1MzFl
|
14
|
+
MTYxNjZiMzFhZWIzNWNhM2I1YjE3ZDA4NDc4M2EwOGI0YjJkYzNkOTJlNDk0
|
15
|
+
ZTliMTMwNDk5MWZmOGU2NjQ3NDFmYjkyMTE3NTRhN2NkYzVkYzk=
|
data/README.md
CHANGED
@@ -184,7 +184,7 @@ Install with `gem install json-ld`
|
|
184
184
|
}
|
185
185
|
}
|
186
186
|
|
187
|
-
JSON::LD::fromRDF(input, context) =>
|
187
|
+
JSON::LD::API::fromRDF(input, context) =>
|
188
188
|
{
|
189
189
|
"@context": {
|
190
190
|
"": "http://manu.sporny.org/",
|
@@ -206,7 +206,7 @@ Install with `gem install json-ld`
|
|
206
206
|
graph.dump(:jsonld, :standard_prefixes => true)
|
207
207
|
|
208
208
|
## Documentation
|
209
|
-
Full documentation available on [RubyDoc](http://rubydoc.info/gems/json-ld/file/README.
|
209
|
+
Full documentation available on [RubyDoc](http://rubydoc.info/gems/json-ld/file/README.md)
|
210
210
|
|
211
211
|
## Differences from [JSON-LD API][]
|
212
212
|
The specified JSON-LD API is based on a WebIDL definition intended for use within the browser.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.3
|
data/lib/json/ld/api.rb
CHANGED
@@ -26,7 +26,7 @@ module JSON::LD
|
|
26
26
|
|
27
27
|
# Options used for open_file
|
28
28
|
OPEN_OPTS = {
|
29
|
-
:headers =>
|
29
|
+
:headers => {"Accept" => "application/ld+json, application/json"}
|
30
30
|
}
|
31
31
|
|
32
32
|
# Current input
|
@@ -212,11 +212,11 @@ module JSON::LD
|
|
212
212
|
entry = default_graph[graph_name] ||= {'@id' => graph_name}
|
213
213
|
nodes = entry['@graph'] ||= []
|
214
214
|
graph.keys.kw_sort.each do |id|
|
215
|
-
nodes << graph[id]
|
215
|
+
nodes << graph[id] unless node_reference?(graph[id])
|
216
216
|
end
|
217
217
|
end
|
218
218
|
default_graph.keys.kw_sort.each do |id|
|
219
|
-
flattened << default_graph[id]
|
219
|
+
flattened << default_graph[id] unless node_reference?(default_graph[id])
|
220
220
|
end
|
221
221
|
|
222
222
|
if context && !flattened.empty?
|
@@ -302,10 +302,10 @@ module JSON::LD
|
|
302
302
|
all_nodes = Hash.ordered
|
303
303
|
old_dbg, @options[:debug] = @options[:debug], nil
|
304
304
|
depth do
|
305
|
-
generate_node_map(value, all_nodes
|
305
|
+
generate_node_map(value, all_nodes)
|
306
306
|
end
|
307
307
|
@options[:debug] = old_dbg
|
308
|
-
@node_map = all_nodes['@
|
308
|
+
@node_map = all_nodes['@default']
|
309
309
|
debug(".frame") {"node_map: #{@node_map.to_json(JSON_STATE)}"}
|
310
310
|
|
311
311
|
result = []
|
@@ -339,6 +339,8 @@ module JSON::LD
|
|
339
339
|
# @param [{Symbol,String => Object}] options
|
340
340
|
# See options in {JSON::LD::API#initialize}
|
341
341
|
# Options passed to {JSON::LD::API.expand}
|
342
|
+
# @option options [Boolean] :produceGeneralizedRDF (false)
|
343
|
+
# If true, output will include statements having blank node predicates, otherwise they are dropped.
|
342
344
|
# @raise [InvalidContext]
|
343
345
|
# @return [Array<RDF::Statement>] if no block given
|
344
346
|
# @yield statement
|
@@ -366,6 +368,7 @@ module JSON::LD
|
|
366
368
|
context = as_resource(graph_name) unless graph_name == '@default'
|
367
369
|
debug(".toRDF") {"context: #{context ? context.to_ntriples : 'null'}"}
|
368
370
|
graph_to_rdf(graph).each do |statement|
|
371
|
+
next if statement.predicate.node? && !options[:produceGeneralizedRDF]
|
369
372
|
statement.context = context if context
|
370
373
|
if block_given?
|
371
374
|
yield statement
|
data/lib/json/ld/compact.rb
CHANGED
@@ -67,7 +67,8 @@ module JSON::LD
|
|
67
67
|
debug("@reverse") {"compacted_value: #{compacted_value.inspect}"}
|
68
68
|
compacted_value.each do |prop, value|
|
69
69
|
if context.reverse?(prop)
|
70
|
-
value = [value]
|
70
|
+
value = [value] if !value.is_a?(Array) &&
|
71
|
+
(context.container(prop) == '@set' || !@options[:compactArrays])
|
71
72
|
debug("") {"merge #{prop} => #{value.inspect}"}
|
72
73
|
merge_compacted_value(result, prop, value)
|
73
74
|
compacted_value.delete(prop)
|
data/lib/json/ld/context.rb
CHANGED
@@ -46,7 +46,7 @@ module JSON::LD
|
|
46
46
|
cid = context.compact_iri(id)
|
47
47
|
cid == term ? id : cid
|
48
48
|
else
|
49
|
-
defn =
|
49
|
+
defn = {}
|
50
50
|
cid = context.compact_iri(id)
|
51
51
|
defn[reverse_property ? '@reverse' : '@id'] = cid unless cid == term && !reverse_property
|
52
52
|
if type_mapping
|
@@ -76,9 +76,14 @@ module JSON::LD
|
|
76
76
|
|
77
77
|
# The base.
|
78
78
|
#
|
79
|
-
# @return [RDF::URI]
|
79
|
+
# @return [RDF::URI] Current base IRI, used for expanding relative IRIs.
|
80
80
|
attr_reader :base
|
81
81
|
|
82
|
+
# The base.
|
83
|
+
#
|
84
|
+
# @return [RDF::URI] Document base IRI, to initialize `base`.
|
85
|
+
attr_reader :doc_base
|
86
|
+
|
82
87
|
# @return [RDF::URI] base IRI of the context, if loaded remotely. XXX
|
83
88
|
attr_accessor :context_base
|
84
89
|
|
@@ -126,7 +131,7 @@ module JSON::LD
|
|
126
131
|
# @return [Context]
|
127
132
|
def initialize(options = {})
|
128
133
|
if options[:base]
|
129
|
-
@doc_base = RDF::URI(options[:base])
|
134
|
+
@base = @doc_base = RDF::URI(options[:base])
|
130
135
|
@doc_base.canonicalize!
|
131
136
|
@doc_base.fragment = nil
|
132
137
|
@doc_base.query = nil
|
@@ -179,13 +184,17 @@ module JSON::LD
|
|
179
184
|
|
180
185
|
# @param [String] value must be an absolute IRI
|
181
186
|
def vocab=(value)
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
+
@vocab = case value
|
188
|
+
when /_:/
|
189
|
+
value
|
190
|
+
when String
|
191
|
+
v = as_resource(value)
|
192
|
+
raise InvalidContext::InvalidVocabMapping, "@value must be an absolute IRI: #{value.inspect}" if v.uri? && v.relative?
|
193
|
+
v
|
194
|
+
when nil
|
195
|
+
nil
|
187
196
|
else
|
188
|
-
@
|
197
|
+
raise InvalidContext::InvalidVocabMapping, "@value must be a string: #{value.inspect}"
|
189
198
|
end
|
190
199
|
end
|
191
200
|
|
@@ -234,7 +243,7 @@ module JSON::LD
|
|
234
243
|
# Load context document, if it is a string
|
235
244
|
begin
|
236
245
|
# 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].
|
237
|
-
context = RDF::URI(result.context_base || result.base
|
246
|
+
context = RDF::URI(result.context_base || result.base).join(context)
|
238
247
|
|
239
248
|
raise InvalidContext::RecursiveContextInclusion, "#{context}" if remote_contexts.include?(context)
|
240
249
|
@remote_contexts = @remote_contexts + [context]
|
@@ -344,9 +353,18 @@ module JSON::LD
|
|
344
353
|
debug("") {"Hash[#{term.inspect}] = #{value.inspect}"}
|
345
354
|
definition = TermDefinition.new(term)
|
346
355
|
|
356
|
+
if value.has_key?('@type')
|
357
|
+
type = value['@type']
|
358
|
+
# SPEC FIXME: @type may be nil
|
359
|
+
raise InvalidContext::InvalidTypeMapping, "unknown mapping for '@type' to #{type.inspect}" unless type.is_a?(String) || type.nil?
|
360
|
+
type = expand_iri(type, :vocab => true, :documentRelative => true, :local_context => local_context, :defined => defined) if type.is_a?(String)
|
361
|
+
debug("") {"type_mapping: #{type.inspect}"}
|
362
|
+
definition.type_mapping = type
|
363
|
+
end
|
364
|
+
|
347
365
|
if value.has_key?('@reverse')
|
348
366
|
raise InvalidContext::InvalidReverseProperty, "unexpected key in #{value.inspect}" if
|
349
|
-
value.keys.any? {|k|
|
367
|
+
value.keys.any? {|k| %w(@id).include?(k)}
|
350
368
|
raise InvalidContext::InvalidIRIMapping, "expected value of @reverse to be a string" unless
|
351
369
|
value['@reverse'].is_a?(String)
|
352
370
|
|
@@ -358,11 +376,13 @@ module JSON::LD
|
|
358
376
|
:defined => defined)
|
359
377
|
raise InvalidContext::InvalidIRImapping, "non-absolute @reverse IRI: #{definition.id}" unless
|
360
378
|
definition.id.absolute?
|
361
|
-
definition.type_mapping = '@id'
|
362
379
|
|
363
|
-
# If value contains an @container member, set the container mapping of definition to
|
364
|
-
if (container = value['@container'])
|
365
|
-
raise InvalidContext::InvalidReverseProperty,
|
380
|
+
# 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
|
+
if (container = value['@container'])
|
382
|
+
raise InvalidContext::InvalidReverseProperty,
|
383
|
+
"unknown mapping for '@container' to #{container.inspect}" unless
|
384
|
+
['@set', '@index', nil].include?(container)
|
385
|
+
definition.container_mapping = container
|
366
386
|
end
|
367
387
|
definition.reverse_property = true
|
368
388
|
elsif value.has_key?('@id') && value['@id'] != term
|
@@ -393,15 +413,6 @@ module JSON::LD
|
|
393
413
|
debug("") {"=> #{definition.id}"}
|
394
414
|
end
|
395
415
|
|
396
|
-
if value.has_key?('@type')
|
397
|
-
type = value['@type']
|
398
|
-
# SPEC FIXME: @type may be nil
|
399
|
-
raise InvalidContext::InvalidTypeMapping, "unknown mapping for '@type' to #{type.inspect}" unless type.is_a?(String) || type.nil?
|
400
|
-
type = expand_iri(type, :vocab => true, :documentRelative => true, :local_context => local_context, :defined => defined) if type.is_a?(String)
|
401
|
-
debug("") {"type_mapping: #{type.inspect}"}
|
402
|
-
definition.type_mapping = type
|
403
|
-
end
|
404
|
-
|
405
416
|
if value.has_key?('@container')
|
406
417
|
container = value['@container']
|
407
418
|
raise InvalidContext::InvalidContainerMapping, "unknown mapping for '@container' to #{container.inspect}" unless %w(@list @set @language @index).include?(container)
|
@@ -445,8 +456,8 @@ module JSON::LD
|
|
445
456
|
else
|
446
457
|
debug("serlialize: generate context")
|
447
458
|
debug("") {"=> context: #{inspect}"}
|
448
|
-
ctx =
|
449
|
-
ctx['@base'] = base.to_s if base
|
459
|
+
ctx = {}
|
460
|
+
ctx['@base'] = base.to_s if base && base != doc_base
|
450
461
|
ctx['@language'] = default_language.to_s if default_language
|
451
462
|
ctx['@vocab'] = vocab.to_s if vocab
|
452
463
|
|
@@ -460,7 +471,7 @@ module JSON::LD
|
|
460
471
|
end
|
461
472
|
|
462
473
|
# Return hash with @context, or empty
|
463
|
-
r =
|
474
|
+
r = {}
|
464
475
|
r['@context'] = use_context unless use_context.nil? || use_context.empty?
|
465
476
|
r
|
466
477
|
end
|
@@ -652,9 +663,9 @@ module JSON::LD
|
|
652
663
|
result = if options[:vocab] && vocab
|
653
664
|
# If vocab is true, and active context has a vocabulary mapping, return the result of concatenating the vocabulary mapping with value.
|
654
665
|
vocab + value
|
655
|
-
elsif options[:documentRelative] && base = options.fetch(:base, self.base
|
666
|
+
elsif options[:documentRelative] && base = options.fetch(:base, self.base)
|
656
667
|
# Otherwise, if document relative is true, set value to the result of resolving value against the base IRI. 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].
|
657
|
-
RDF::URI(base).join(value)
|
668
|
+
RDF::URI(base).join(value)
|
658
669
|
elsif local_context && RDF::URI(value).relative?
|
659
670
|
# 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.
|
660
671
|
raise JSON::LD::InvalidContext::InvalidIRIMapping, "not an absolute IRI: #{value}"
|
@@ -870,7 +881,7 @@ module JSON::LD
|
|
870
881
|
{'@id' => value.to_s}
|
871
882
|
when RDF::Literal
|
872
883
|
debug("Literal") {"datatype: #{value.datatype.inspect}"}
|
873
|
-
res =
|
884
|
+
res = {}
|
874
885
|
if options[:useNativeTypes] && [RDF::XSD.boolean, RDF::XSD.integer, RDF::XSD.double].include?(value.datatype)
|
875
886
|
res['@value'] = value.object
|
876
887
|
res['@type'] = uri(coerce(property)) if coerce(property)
|
@@ -1116,14 +1127,14 @@ module JSON::LD
|
|
1116
1127
|
# @return [String]
|
1117
1128
|
# the relative IRI if relative to base, otherwise the absolute IRI.
|
1118
1129
|
def remove_base(iri)
|
1119
|
-
return iri unless base
|
1130
|
+
return iri unless base
|
1120
1131
|
@base_and_parents ||= begin
|
1121
|
-
u = base
|
1132
|
+
u = base
|
1122
1133
|
iri_set = u.to_s.end_with?('/') ? [u.to_s] : []
|
1123
1134
|
iri_set << u.to_s while (u = u.parent)
|
1124
1135
|
iri_set
|
1125
1136
|
end
|
1126
|
-
b =
|
1137
|
+
b = base.to_s
|
1127
1138
|
return iri[b.length..-1] if iri.start_with?(b) && %w(? #).include?(iri[b.length, 1])
|
1128
1139
|
|
1129
1140
|
@base_and_parents.each_with_index do |b, index|
|
data/lib/json/ld/expand.rb
CHANGED
@@ -81,7 +81,7 @@ module JSON::LD
|
|
81
81
|
case value
|
82
82
|
when Array
|
83
83
|
depth do
|
84
|
-
|
84
|
+
value.map do |v|
|
85
85
|
raise ProcessingError::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
|
data/lib/json/ld/flatten.rb
CHANGED
@@ -10,11 +10,13 @@ module JSON::LD
|
|
10
10
|
# @param [Hash{String => Hash}] node_map
|
11
11
|
# map of nodes
|
12
12
|
# @param [String] active_graph
|
13
|
-
#
|
13
|
+
# The name of the currently active graph that the processor should use when processing.
|
14
|
+
# @param [String] active_subject
|
15
|
+
# The currently active subject that the processor should use when processing.
|
16
|
+
# @param [String] active_property
|
17
|
+
# The currently active property or keyword that the processor should use when processing.
|
14
18
|
# @param [Array] list
|
15
19
|
# List for saving list elements
|
16
|
-
# @param [String] id (nil)
|
17
|
-
# Identifier already associated with element
|
18
20
|
def generate_node_map(element,
|
19
21
|
node_map,
|
20
22
|
active_graph = '@default',
|
@@ -42,13 +44,9 @@ module JSON::LD
|
|
42
44
|
|
43
45
|
# If element has an @type member, perform for each item the following steps:
|
44
46
|
if element.has_key?('@type')
|
45
|
-
types =
|
47
|
+
types = Array(element['@type']).map do |item|
|
46
48
|
# If item is a blank node identifier, replace it with a newly generated blank node identifier passing item for identifier.
|
47
|
-
item
|
48
|
-
|
49
|
-
# If graph has no member item, create it and initialize its value to a JSON object consisting of a single member @id with the value item.
|
50
|
-
graph[item] ||= {'@id' => item}
|
51
|
-
item
|
49
|
+
blank_node?(item) ? namer.get_name(item) : item
|
52
50
|
end
|
53
51
|
|
54
52
|
element['@type'] = element['@type'].is_a?(Array) ? types : types.first
|
@@ -81,7 +79,7 @@ module JSON::LD
|
|
81
79
|
merge_value(node, active_property, result)
|
82
80
|
else
|
83
81
|
# Otherwise element is a node object, perform the following steps:
|
84
|
-
|
82
|
+
|
85
83
|
# If element has an @id member, set id to its value and remove the member from element. If id is a blank node identifier, replace it with a newly generated blank node identifier passing id for identifier.
|
86
84
|
# Otherwise, set id to the result of the Generate Blank Node Identifier algorithm passing null for identifier.
|
87
85
|
id = element.delete('@id')
|
@@ -109,7 +107,7 @@ module JSON::LD
|
|
109
107
|
|
110
108
|
# If element has an @type key, append each item of its associated array to the array associated with the @type key of node unless it is already in that array. Finally remove the @type member from element.
|
111
109
|
if element.has_key?('@type')
|
112
|
-
|
110
|
+
Array(element.delete('@type')).each do |t|
|
113
111
|
merge_value(node, '@type', t)
|
114
112
|
end
|
115
113
|
end
|
data/lib/json/ld/from_rdf.rb
CHANGED
@@ -32,9 +32,9 @@ module JSON::LD
|
|
32
32
|
subject = ec.expand_iri(statement.subject).to_s
|
33
33
|
node = node_map[subject] ||= {'@id' => subject}
|
34
34
|
|
35
|
-
# If object is an IRI or blank node identifier,
|
35
|
+
# If object is an IRI or blank node identifier, and node map does not have an object member, create one and initialize its value to a new JSON object consisting of a single member @id whose value is set to object.
|
36
36
|
node_map[statement.object.to_s] ||= {'@id' => statement.object.to_s} unless
|
37
|
-
|
37
|
+
statement.object.literal?
|
38
38
|
|
39
39
|
# If predicate equals rdf:type, and object is an IRI or blank node identifier, append object to the value of the @type member of node. If no such member exists, create one and initialize it to an array whose only item is object. Finally, continue to the next RDF triple.
|
40
40
|
if statement.predicate == RDF.type && statement.object.resource?
|
@@ -42,61 +42,64 @@ module JSON::LD
|
|
42
42
|
next
|
43
43
|
end
|
44
44
|
|
45
|
-
#
|
46
|
-
value =
|
47
|
-
{'@list' => []}
|
48
|
-
else
|
49
|
-
ec.expand_value(nil, statement.object, @options)
|
50
|
-
end
|
45
|
+
# Set value to the result of using the RDF to Object Conversion algorithm, passing object and use native types.
|
46
|
+
value = ec.expand_value(nil, statement.object, @options)
|
51
47
|
|
52
48
|
merge_value(node, statement.predicate.to_s, value)
|
53
49
|
|
54
|
-
# If object is a blank node identifier
|
55
|
-
if statement.object.
|
56
|
-
|
50
|
+
# If object is a blank node identifier or IRI, it might represent the a list node:
|
51
|
+
if statement.object.resource?
|
52
|
+
# Append a new JSON object consisting of three members, node, property, and value to the usages array. The node member is set to a reference to node, property to predicate, and value to a reference to value.
|
53
|
+
merge_value(node_map[statement.object.to_s], :usages, {
|
54
|
+
:node => node,
|
55
|
+
:property => statement.predicate.to_s,
|
56
|
+
:value => value})
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
60
|
# For each name and graph object in graph map:
|
61
61
|
graph_map.each do |name, graph_object|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
while
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
62
|
+
next unless nil_var = graph_object[RDF.nil.to_s]
|
63
|
+
|
64
|
+
# For each item usage in the usages member of nil, perform the following steps:
|
65
|
+
nil_var[:usages].each do |usage|
|
66
|
+
node, property, head = usage[:node], usage[:property], usage[:value]
|
67
|
+
list, list_nodes = [], []
|
68
|
+
|
69
|
+
# If property equals rdf:rest, the value associated to the usages member of node has exactly 1 entry, node has a rdf:first and rdf:rest property, both of which have as value an array consisting of a single element, and node has no other members apart from an optional @type member whose value is an array with a single item equal to rdf:List, node represents a well-formed list node. Continue with the following steps:
|
70
|
+
debug("list element?") {node.to_json(JSON_STATE)}
|
71
|
+
while property == RDF.rest.to_s &&
|
72
|
+
blank_node?(node) &&
|
73
|
+
node.keys.none? {|k| !["@id", '@type', :usages, RDF.first.to_s, RDF.rest.to_s].include?(k)} &&
|
74
|
+
Array(node[:usages]).length == 1 &&
|
75
|
+
(f = node[RDF.first.to_s]).is_a?(Array) && f.length == 1 &&
|
76
|
+
(r = node[RDF.rest.to_s]).is_a?(Array) && r.length == 1 &&
|
77
|
+
((t = node['@type']).nil? || t == [RDF.List.to_s])
|
78
|
+
list << Array(node[RDF.first.to_s]).first
|
79
|
+
list_nodes << node['@id']
|
80
|
+
node_usage = Array(node[:usages]).first
|
81
|
+
node, property, head = node_usage[:node], node_usage[:property], node_usage[:value]
|
82
|
+
end
|
83
|
+
|
84
|
+
# If property equals rdf:first, i.e., the detected list is nested inside another list
|
85
|
+
if property == RDF.first.to_s
|
86
|
+
# and the value of the @id of node equals rdf:nil, i.e., the detected list is empty, continue with the next usage item. The rdf:nil node cannot be converted to a list object as it would result in a list of lists, which isn't supported.
|
87
|
+
next if node['@id'] == RDF.nil.to_s
|
88
|
+
|
89
|
+
# Otherwise, the list consists of at least one item. We preserve the head node and transform the rest of the linked list to a list object
|
90
|
+
head_id = head['@id']
|
91
|
+
head = graph_object[head_id]
|
92
|
+
head = Array(head[RDF.rest.to_s]).first
|
93
|
+
list.pop; list_nodes.pop
|
89
94
|
end
|
90
95
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
list_nodes.each {|s| graph_object.delete(s)}
|
96
|
+
head.delete('@id')
|
97
|
+
head['@list'] = list.reverse
|
98
|
+
list_nodes.each {|node_id| graph_object.delete(node_id)}
|
95
99
|
end
|
96
100
|
end
|
97
101
|
|
98
102
|
result = []
|
99
|
-
debug("graph_map") {graph_map.to_json(JSON_STATE)}
|
100
103
|
default_graph.keys.sort.each do |subject|
|
101
104
|
node = default_graph[subject]
|
102
105
|
if graph_map.has_key?(subject)
|
@@ -104,11 +107,11 @@ module JSON::LD
|
|
104
107
|
graph_map[subject].keys.sort.each do |s|
|
105
108
|
n = graph_map[subject][s]
|
106
109
|
n.delete(:usages)
|
107
|
-
node['@graph'] << n
|
110
|
+
node['@graph'] << n unless node_reference?(n)
|
108
111
|
end
|
109
112
|
end
|
110
113
|
node.delete(:usages)
|
111
|
-
result << node
|
114
|
+
result << node unless node_reference?(node)
|
112
115
|
end
|
113
116
|
debug("fromRDF") {result.to_json(JSON_STATE)}
|
114
117
|
result
|