json-ld 1.0.1.1 → 1.0.3
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 +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
|