json-ld 0.3.2 → 0.9.0
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.
- data/README.markdown +2 -2
- data/VERSION +1 -1
- data/lib/json/ld.rb +10 -0
- data/lib/json/ld/api.rb +43 -26
- data/lib/json/ld/compact.rb +119 -17
- data/lib/json/ld/evaluation_context.rb +186 -146
- data/lib/json/ld/expand.rb +192 -86
- data/lib/json/ld/extensions.rb +18 -0
- data/lib/json/ld/flatten.rb +6 -8
- data/lib/json/ld/frame.rb +3 -3
- data/lib/json/ld/to_rdf.rb +4 -6
- data/lib/json/ld/utils.rb +46 -15
- data/spec/compact_spec.rb +130 -113
- data/spec/evaluation_context_spec.rb +230 -43
- data/spec/expand_spec.rb +185 -17
- data/spec/flatten_spec.rb +3 -5
- data/spec/frame_spec.rb +1 -1
- data/spec/suite_compact_spec.rb +4 -1
- data/spec/suite_expand_spec.rb +2 -4
- data/spec/suite_flatten_spec.rb +32 -0
- data/spec/suite_frame_spec.rb +1 -1
- data/spec/suite_helper.rb +0 -3
- data/spec/test-files/test-7-compacted.json +3 -3
- data/spec/test-files/test-7-expanded.json +3 -3
- data/spec/to_rdf_spec.rb +1 -1
- data/spec/writer_spec.rb +1 -1
- metadata +16 -30
data/lib/json/ld/expand.rb
CHANGED
@@ -47,117 +47,194 @@ module JSON::LD
|
|
47
47
|
depth do
|
48
48
|
output_object = Hash.ordered
|
49
49
|
# Then, proceed and process each property and value in element as follows:
|
50
|
-
input.each do |
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
50
|
+
input.keys.kw_sort.each do |property|
|
51
|
+
value = input[property]
|
52
|
+
expanded_property = context.expand_iri(property, :position => :predicate, :quiet => true, :namer => namer)
|
53
|
+
|
54
|
+
if expanded_property.is_a?(Array)
|
55
|
+
# If expanded property is an array, remove every element which is not a absolute IRI.
|
56
|
+
expanded_property = expanded_property.map {|p| p.to_s if p && p.uri? && p.absolute? || p.node?}.compact
|
57
|
+
expanded_property = nil if expanded_property.empty?
|
58
|
+
elsif expanded_property.is_a?(RDF::Resource)
|
59
|
+
expanded_property = expanded_property.to_s
|
60
|
+
end
|
61
|
+
|
62
|
+
debug("expand property") {"ap: #{active_property.inspect}, expanded: #{expanded_property.inspect}, value: #{value.inspect}"}
|
63
|
+
|
64
|
+
# If expanded property is an empty array, or null, continue with the next property from element
|
65
|
+
if expanded_property.nil?
|
66
|
+
debug(" => ") {"skip nil property"}
|
62
67
|
next
|
63
68
|
end
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
69
|
+
expanded_property
|
70
|
+
|
71
|
+
if expanded_property.is_a?(String) && expanded_property[0,1] == '@'
|
72
|
+
expanded_value = case expanded_property
|
73
|
+
when '@id'
|
74
|
+
# If expanded property is @id, value must be a string. Set the @id member in result to the result of expanding value according the IRI Expansion algorithm relative to the document base and re-labeling Blank Nodes.
|
75
|
+
context.expand_iri(value, :position => :subject, :quiet => true, :namer => namer).to_s
|
76
|
+
when '@type'
|
77
|
+
# If expanded property is @type, value must be a string or array of strings. Set the @type member of result to the result of expanding value according the IRI Expansion algorithm relative to the document base and re-labeling Blank Nodes, unless that result is an empty array.
|
78
|
+
debug("@type") {"value: #{value.inspect}"}
|
79
|
+
case value
|
80
|
+
when Array
|
81
|
+
depth do
|
82
|
+
[value].flatten.map do |v|
|
83
|
+
v = v['@id'] if node_reference?(v)
|
84
|
+
raise ProcessingError, "Object value must be a string or a node reference: #{v.inspect}" unless v.is_a?(String)
|
85
|
+
context.expand_iri(v, options.merge(:position => :subject, :quiet => true, :namer => namer)).to_s
|
86
|
+
end
|
87
|
+
end
|
88
|
+
when Hash
|
89
|
+
# Empty object used for @type wildcard or node reference
|
90
|
+
if node_reference?(value)
|
91
|
+
context.expand_iri(value['@id'], options.merge(:position => :property, :quiet => true, :namer => namer)).to_s
|
92
|
+
elsif !value.empty?
|
93
|
+
raise ProcessingError, "Object value of @type must be empty or a node reference: #{value.inspect}"
|
94
|
+
else
|
95
|
+
value
|
82
96
|
end
|
83
|
-
end
|
84
|
-
when Hash
|
85
|
-
# Empty object used for @type wildcard or node reference
|
86
|
-
if node_reference?(value)
|
87
|
-
context.expand_iri(value['@id'], options.merge(:position => :property, :quiet => true)).to_s
|
88
|
-
elsif !value.empty?
|
89
|
-
raise ProcessingError, "Object value of @type must be empty or a node reference: #{value.inspect}"
|
90
97
|
else
|
91
|
-
value
|
98
|
+
context.expand_iri(value, options.merge(:position => :property, :quiet => true, :namer => namer)).to_s
|
99
|
+
end
|
100
|
+
when '@value'
|
101
|
+
# If expanded property is @value, value must be a scalar or null. Set the @value member of result to value.
|
102
|
+
raise ProcessingError::Lossy, "Value of #{expanded_property} must be a string, was #{value.inspect}" if value.is_a?(Hash) || value.is_a?(Array)
|
103
|
+
value
|
104
|
+
when '@language'
|
105
|
+
# If expanded property is @language, value must be a string with the lexical form described in [BCP47] or null. Set the @language member of result to the lowercased value.
|
106
|
+
raise ProcessingError::Lossy, "Value of #{expanded_property} must be a string, was #{value.inspect}" if value.is_a?(Hash) || value.is_a?(Array)
|
107
|
+
value.to_s.downcase
|
108
|
+
when '@annotation'
|
109
|
+
# If expanded property is @annotation value must be a string. Set the @annotation member of result to value.
|
110
|
+
value = value.first if value.is_a?(Array) && value.length == 1
|
111
|
+
raise ProcessingError, "Value of @annotation is not a string: #{value.inspect}" unless value.is_a?(String)
|
112
|
+
value.to_s
|
113
|
+
when '@list', '@set', '@graph'
|
114
|
+
# If expanded property is @set, @list, or @graph, set the expanded property member of result to the result of expanding value by recursively using this algorithm, along with the active context and active property. If expanded property is @list and active property is null or @graph, pass @list as active property instead.
|
115
|
+
value = [value] unless value.is_a?(Array)
|
116
|
+
ap = expanded_property == '@list' && ((active_property || '@graph') == '@graph') ? '@list' : active_property
|
117
|
+
value = depth { expand(value, ap, context, options) }
|
118
|
+
|
119
|
+
# If expanded property is @list, and any expanded value
|
120
|
+
# is an object containing an @list property, throw an exception, as lists of lists are not supported
|
121
|
+
if expanded_property == '@list' && value.any? {|v| v.is_a?(Hash) && v.has_key?('@list')}
|
122
|
+
raise ProcessingError::ListOfLists, "A list may not contain another list"
|
92
123
|
end
|
124
|
+
|
125
|
+
value
|
93
126
|
else
|
94
|
-
|
127
|
+
# Skip unknown keyword
|
128
|
+
next
|
95
129
|
end
|
96
|
-
|
97
|
-
#
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
#
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
#
|
109
|
-
|
110
|
-
|
130
|
+
|
131
|
+
debug("expand #{expanded_property}") { expanded_value.inspect}
|
132
|
+
output_object[expanded_property] = expanded_value
|
133
|
+
next
|
134
|
+
end
|
135
|
+
|
136
|
+
expanded_value = if context.container(property) == '@language' && value.is_a?(Hash)
|
137
|
+
# Otherwise, if value is a JSON object and property is not a keyword and its associated term entry in the active context has a @container key associated with a value of @language, process the associated value as a language map:
|
138
|
+
|
139
|
+
# Set multilingual array to an empty array.
|
140
|
+
language_map_values = []
|
141
|
+
|
142
|
+
# For each key-value in the language map:
|
143
|
+
value.keys.sort.each do |k|
|
144
|
+
[value[k]].flatten.each do |v|
|
145
|
+
# Create a new JSON Object, referred to as an expanded language object.
|
146
|
+
expanded_language_object = Hash.new
|
147
|
+
|
148
|
+
# Add a key-value pair to the expanded language object where the key is @value and the value is the value associated with the key in the language map.
|
149
|
+
raise ProcessingError::LanguageMap, "Expected #{vv.inspect} to be a string" unless v.is_a?(String)
|
150
|
+
expanded_language_object['@value'] = v
|
151
|
+
|
152
|
+
# Add a key-value pair to the expanded language object where the key is @language, and the value is the key in the language map, transformed to lowercase.
|
153
|
+
# FIXME: check for BCP47 conformance
|
154
|
+
expanded_language_object['@language'] = k.downcase
|
155
|
+
# Append the expanded language object to the multilingual array.
|
156
|
+
language_map_values << expanded_language_object
|
157
|
+
end
|
111
158
|
end
|
159
|
+
# Set the value associated with property to the multilingual array.
|
160
|
+
language_map_values
|
161
|
+
elsif context.container(property) == '@annotation' && value.is_a?(Hash)
|
162
|
+
# Otherwise, if value is a JSON object and property is not a keyword and its associated term entry in the active context has a @container key associated with a value of @annotation, process the associated value as a annotation:
|
163
|
+
|
164
|
+
# Set ary to an empty array.
|
165
|
+
annotation_map_values = []
|
112
166
|
|
113
|
-
value
|
167
|
+
# For each key-value in the object:
|
168
|
+
value.keys.sort.each do |k|
|
169
|
+
[value[k]].flatten.each do |v|
|
170
|
+
# Expand the value, adding an '@annotation' key with value equal to the key
|
171
|
+
expanded_value = depth { expand(v, property, context, options) }
|
172
|
+
next unless expanded_value
|
173
|
+
expanded_value['@annotation'] ||= k
|
174
|
+
annotation_map_values << expanded_value
|
175
|
+
end
|
176
|
+
end
|
177
|
+
# Set the value associated with property to the multilingual array.
|
178
|
+
annotation_map_values
|
114
179
|
else
|
115
|
-
# Otherwise, expand value recursively using this algorithm, passing copies of the active context and active property.
|
116
|
-
depth { expand(value,
|
180
|
+
# Otherwise, expand value by recursively using this algorithm, passing copies of the active context and property as active property.
|
181
|
+
depth { expand(value, property, context, options) }
|
117
182
|
end
|
118
183
|
|
119
|
-
#
|
120
|
-
|
121
|
-
# from element.
|
122
|
-
if property != '@value' && expanded_value.nil?
|
184
|
+
# Continue to the next property-value pair from element if value is null.
|
185
|
+
if expanded_value.nil?
|
123
186
|
debug(" => skip nil value")
|
124
187
|
next
|
125
188
|
end
|
126
189
|
|
127
|
-
# If
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
(!expanded_value.is_a?(Hash) || !expanded_value.fetch('@list', false))
|
133
|
-
debug(" => ") { "convert #{expanded_value.inspect} to list"}
|
190
|
+
# If property's container mapping is set to @list and value is not a JSON object or is a JSON object without a @list member, replace value with a JSON object having a @list member whose value is set to value, ensuring that value is an array.
|
191
|
+
if context.container(property) == '@list' &&
|
192
|
+
(!expanded_value.is_a?(Hash) || !expanded_value.fetch('@list', false))
|
193
|
+
|
194
|
+
debug(" => ") { "convert #{expanded_value.inspect} to list"}
|
134
195
|
expanded_value = {'@list' => [expanded_value].flatten}
|
135
196
|
end
|
136
197
|
|
137
|
-
# Convert value to array form
|
138
|
-
|
139
|
-
|
140
|
-
expanded_value = [expanded_value]
|
141
|
-
end
|
198
|
+
# Convert value to array form
|
199
|
+
debug(" => ") {"expanded property: #{expanded_property.inspect}"}
|
200
|
+
expanded_value = [expanded_value] unless expanded_value.is_a?(Array)
|
142
201
|
|
143
|
-
if
|
144
|
-
|
145
|
-
|
202
|
+
if expanded_property.is_a?(Array)
|
203
|
+
label_blanknodes(expanded_value)
|
204
|
+
expanded_property.map(&:to_s).each do |prop|
|
205
|
+
# label all blank nodes in value with blank node identifiers by using the Label Blank Nodes Algorithm.
|
206
|
+
output_object[prop] ||= []
|
207
|
+
output_object[prop] += expanded_value.dup
|
208
|
+
end
|
146
209
|
else
|
147
|
-
|
148
|
-
|
210
|
+
if output_object.has_key?(expanded_property)
|
211
|
+
# If element already contains a expanded_property property, append value to the existing value.
|
212
|
+
output_object[expanded_property] += expanded_value
|
213
|
+
else
|
214
|
+
# Otherwise, create a property property with value as value.
|
215
|
+
output_object[expanded_property] = expanded_value
|
216
|
+
end
|
149
217
|
end
|
150
218
|
debug {" => #{expanded_value.inspect}"}
|
151
219
|
end
|
152
220
|
|
153
221
|
debug("output object") {output_object.inspect}
|
154
222
|
|
223
|
+
# If the active property is null or @graph and element has a @value member without an @annotation member, or element consists of only an @id member, set element to null.
|
224
|
+
debug("output object(ap)") {((active_property || '@graph') == '@graph').inspect}
|
225
|
+
if (active_property || '@graph') == '@graph' &&
|
226
|
+
((output_object.has_key?('@value') && !output_object.has_key?('@annotation')) ||
|
227
|
+
(output_object.keys - %w(@id)).empty?)
|
228
|
+
debug("empty top-level") {output_object.inspect}
|
229
|
+
return nil
|
230
|
+
end
|
231
|
+
|
155
232
|
# If the processed element has an @value property
|
156
233
|
if output_object.has_key?('@value')
|
157
234
|
output_object.delete('@language') if output_object['@language'].to_s.empty?
|
158
235
|
output_object.delete('@type') if output_object['@type'].to_s.empty?
|
159
|
-
if
|
160
|
-
raise ProcessingError, "element must not have more than one other property, which can either be @language or @type with a string value." unless value.is_a?(String)
|
236
|
+
if (%w(@annotation @language @type) - output_object.keys).empty?
|
237
|
+
raise ProcessingError, "element must not have more than one other property other than @annotation, which can either be @language or @type with a string value." unless value.is_a?(String)
|
161
238
|
end
|
162
239
|
|
163
240
|
# if the value of @value equals null, replace element with the value of null.
|
@@ -168,24 +245,53 @@ module JSON::LD
|
|
168
245
|
output_object['@type'] = [output_object['@type']]
|
169
246
|
end
|
170
247
|
|
171
|
-
# If element has an @set or @list property, it must be the only property. Set element to the value of @set;
|
248
|
+
# If element has an @set or @list property, it must be the only property (other tha @annotation). Set element to the value of @set;
|
172
249
|
# leave @list untouched.
|
173
250
|
if !(%w(@set @list) & output_object.keys).empty?
|
174
|
-
|
251
|
+
o_keys = output_object.keys - %w(@set @list @annotation)
|
252
|
+
raise ProcessingError, "element must have only @set or @list: #{output_object.keys.inspect}" if o_keys.length > 1
|
175
253
|
|
176
254
|
output_object = output_object.values.first unless output_object.has_key?('@list')
|
177
255
|
end
|
178
256
|
|
179
|
-
#
|
180
|
-
|
257
|
+
# Re-order result keys
|
258
|
+
if output_object.is_a?(Hash) && output_object.keys == %w(@language)
|
259
|
+
# If element has just a @language property, set element to null.
|
260
|
+
nil
|
261
|
+
elsif output_object.is_a?(Hash)
|
262
|
+
r = Hash.ordered
|
263
|
+
output_object.keys.kw_sort.each {|k| r[k] = output_object[k]}
|
264
|
+
r
|
265
|
+
else
|
266
|
+
output_object
|
267
|
+
end
|
181
268
|
end
|
182
269
|
else
|
183
270
|
# Otherwise, unless the value is a number, expand the value according to the Value Expansion rules, passing active property.
|
184
|
-
context.expand_value(active_property, input,
|
271
|
+
context.expand_value(active_property, input,
|
272
|
+
:position => :subject, :namer => namer, :depth => @depth
|
273
|
+
) unless input.nil? || active_property.nil? || active_property == '@graph'
|
185
274
|
end
|
186
275
|
|
187
276
|
debug {" => #{result.inspect}"}
|
188
277
|
result
|
189
278
|
end
|
279
|
+
|
280
|
+
protected
|
281
|
+
# @param [Array, Hash] input
|
282
|
+
def label_blanknodes(element)
|
283
|
+
if element.is_a?(Array)
|
284
|
+
element.each {|e| label_blanknodes(e)}
|
285
|
+
elsif list?(element)
|
286
|
+
element['@list'].each {|e| label_blanknodes(e)}
|
287
|
+
elsif element.is_a?(Hash)
|
288
|
+
element.keys.sort.each do |k|
|
289
|
+
label_blanknodes(element[k])
|
290
|
+
end
|
291
|
+
if node?(element) and !element.has_key?('@id')
|
292
|
+
element['@id'] = namer.get_name(nil)
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
190
296
|
end
|
191
|
-
end
|
297
|
+
end
|
data/lib/json/ld/extensions.rb
CHANGED
@@ -62,6 +62,24 @@ module RDF
|
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
+
class Array
|
66
|
+
# Sort values, but impose special keyword ordering
|
67
|
+
# @yield a, b
|
68
|
+
# @yieldparam [Object] a
|
69
|
+
# @yieldparam [Object] b
|
70
|
+
# @yieldreturn [Integer]
|
71
|
+
# @return [Array]
|
72
|
+
KW_ORDER = %(@id @value @type @language @vocab @container @graph @list @set)
|
73
|
+
|
74
|
+
def kw_sort
|
75
|
+
self.sort do |a, b|
|
76
|
+
a = "@#{KW_ORDER.index(a)}" if KW_ORDER.include?(a)
|
77
|
+
b = "@#{KW_ORDER.index(b)}" if KW_ORDER.include?(b)
|
78
|
+
a <=> b
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
65
83
|
if RUBY_VERSION < "1.9"
|
66
84
|
class InsertOrderPreservingHash < Hash
|
67
85
|
include Enumerable
|
data/lib/json/ld/flatten.rb
CHANGED
@@ -13,14 +13,13 @@ module JSON::LD
|
|
13
13
|
# Graph name for results
|
14
14
|
# @param [Array] list
|
15
15
|
# List for saving list elements
|
16
|
-
# @param [
|
17
|
-
# @param [String] id
|
16
|
+
# @param [String] id (nil)
|
18
17
|
# Identifier already associated with element
|
19
|
-
def generate_node_map(element, node_map, graph, list
|
18
|
+
def generate_node_map(element, node_map, graph, list = nil, id = nil)
|
20
19
|
depth do
|
21
20
|
debug("nodeMap") {"element: #{element.inspect}, graph: #{graph}"}
|
22
21
|
if element.is_a?(Array)
|
23
|
-
element.map {|o| generate_node_map(o, node_map, graph, list
|
22
|
+
element.map {|o| generate_node_map(o, node_map, graph, list)}
|
24
23
|
elsif !element.is_a?(Hash) || value?(element)
|
25
24
|
list << element if list
|
26
25
|
else
|
@@ -48,7 +47,7 @@ module JSON::LD
|
|
48
47
|
when '@graph'
|
49
48
|
# If property is @graph, recursively call this algorithm passing value for element, nodeMap, nil for list and if graph is @merged use graph, otherwise use id for graph and then continue.
|
50
49
|
graph = graph == '@merged' ? '@merged' : id
|
51
|
-
generate_node_map(value, node_map, graph
|
50
|
+
generate_node_map(value, node_map, graph)
|
52
51
|
when /^@(?!type)/
|
53
52
|
# If property is not @type and is a keyword, merge property and value into node and then continue.
|
54
53
|
debug("nodeMap") {"merge keyword#{prop}: #{value.inspect}"}
|
@@ -75,7 +74,7 @@ module JSON::LD
|
|
75
74
|
}
|
76
75
|
|
77
76
|
# Recursively call this algorithm passing v for value, nodeMap, graph, and nil for list.
|
78
|
-
generate_node_map(v, node_map, graph, nil,
|
77
|
+
generate_node_map(v, node_map, graph, nil, name)
|
79
78
|
elsif list?(v)
|
80
79
|
# Otherwise if v has the property @list then recursively call this algorithm with the value of @list as element, nodeMap, graph, and a new array flattenedList as list.
|
81
80
|
debug("nodeMap") {"list value #{prop}: #{v.inspect}"}
|
@@ -83,8 +82,7 @@ module JSON::LD
|
|
83
82
|
generate_node_map(v['@list'],
|
84
83
|
node_map,
|
85
84
|
graph,
|
86
|
-
flattened_list
|
87
|
-
namer)
|
85
|
+
flattened_list)
|
88
86
|
# Create a new JSON object with the property @list set to flattenedList and add it to node for property.
|
89
87
|
(node[prop] ||= []) << {'@list' => flattened_list}
|
90
88
|
elsif prop == '@type'
|
data/lib/json/ld/frame.rb
CHANGED
@@ -36,7 +36,7 @@ module JSON::LD
|
|
36
36
|
debug("frame") {"embed: #{embed.inspect}, explicit: #{explicit.inspect}"}
|
37
37
|
|
38
38
|
# For each id and node from the set of matched nodes ordered by id
|
39
|
-
matches.keys.
|
39
|
+
matches.keys.kw_sort.each do |id|
|
40
40
|
element = matches[id]
|
41
41
|
# If the active property is null, set the map of embeds in state to an empty map
|
42
42
|
state = state.merge(:embeds => {}) if property.nil?
|
@@ -77,7 +77,7 @@ module JSON::LD
|
|
77
77
|
debug("frame") {"add embedded_node: #{embedded_node.inspect}"}
|
78
78
|
|
79
79
|
# Process each property and value in the matched node as follows
|
80
|
-
element.keys.
|
80
|
+
element.keys.kw_sort.each do |prop|
|
81
81
|
value = element[prop]
|
82
82
|
if prop[0,1] == '@'
|
83
83
|
# If property is a keyword, add property and a copy of value to output and continue with the next property from node
|
@@ -138,7 +138,7 @@ module JSON::LD
|
|
138
138
|
end
|
139
139
|
|
140
140
|
# Process each property and value in frame in lexographical order, where property is not a keyword, as follows:
|
141
|
-
frame.keys.
|
141
|
+
frame.keys.kw_sort.each do |prop|
|
142
142
|
next if prop[0,1] == '@' || output.has_key?(prop)
|
143
143
|
property_frame = frame[prop]
|
144
144
|
debug("frame") {"frame prop: #{prop.inspect}. property_frame: #{property_frame.inspect}"}
|
data/lib/json/ld/to_rdf.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'rdf'
|
1
2
|
require 'rdf/nquads'
|
2
3
|
|
3
4
|
module JSON::LD
|
@@ -21,7 +22,6 @@ module JSON::LD
|
|
21
22
|
# @yieldparam [RDF::Statement] statement
|
22
23
|
def statements(path, element, subject, property, name, &block)
|
23
24
|
debug(path) {"statements: e=#{element.inspect}, s=#{subject.inspect}, p=#{property.inspect}, n=#{name.inspect}"}
|
24
|
-
@node_seq = "t0" unless subject || property
|
25
25
|
|
26
26
|
traverse_result = depth do
|
27
27
|
case element
|
@@ -55,7 +55,7 @@ module JSON::LD
|
|
55
55
|
|
56
56
|
# 1.7) For each key in the JSON object that has not already been processed,
|
57
57
|
# perform the following steps:
|
58
|
-
element.keys.
|
58
|
+
element.keys.kw_sort.each do |key|
|
59
59
|
value = element[key]
|
60
60
|
active_property = case key
|
61
61
|
when '@type'
|
@@ -65,7 +65,7 @@ module JSON::LD
|
|
65
65
|
# Otherwise, if property is @graph, process value algorithm recursively, using active subject
|
66
66
|
# as graph name and null values for active subject and active property and then continue to
|
67
67
|
# next property
|
68
|
-
statements("#{path}[#{key}]", value, nil, nil, active_subject, &block)
|
68
|
+
statements("#{path}[#{key}]", value, nil, nil, (active_subject unless active_subject.node?), &block)
|
69
69
|
next
|
70
70
|
when /^@/
|
71
71
|
# Otherwise, if property is a keyword, skip this step.
|
@@ -154,9 +154,7 @@ module JSON::LD
|
|
154
154
|
##
|
155
155
|
# Create a new named node using the sequence
|
156
156
|
def node
|
157
|
-
|
158
|
-
@node_seq = @node_seq.succ
|
159
|
-
n
|
157
|
+
RDF::Node.new(namer.get_sym)
|
160
158
|
end
|
161
159
|
|
162
160
|
##
|