Skip to content

Commit 9ab5746

Browse files
committed
Update flatten based on pyLd implementation.
1 parent c76a7eb commit 9ab5746

File tree

5 files changed

+441
-391
lines changed

5 files changed

+441
-391
lines changed

lib/json/ld/api.rb

Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ def self.expand(input, options = {})
188188
# @param [Hash{Symbol => Object}] options
189189
# See options in {JSON::LD::API#initialize}
190190
# Other options passed to {JSON::LD::API.expand}
191+
# @option options [Boolean] :expanded Input is already expanded
191192
# @yield jsonld
192193
# @yieldparam [Hash] jsonld
193194
# The compacted JSON-LD document
@@ -201,7 +202,7 @@ def self.compact(input, context, options = {})
201202

202203
# 1) Perform the Expansion Algorithm on the JSON-LD input.
203204
# This removes any existing context to allow the given context to be cleanly applied.
204-
expanded = API.expand(input, options)
205+
expanded = options[:expanded] ? input : API.expand(input, options)
205206

206207
API.new(expanded, context, options) do
207208
debug(".compact") {"expanded input: #{expanded.to_json(JSON_STATE) rescue 'malformed json'}"}
@@ -230,6 +231,7 @@ def self.compact(input, context, options = {})
230231
# @param [Hash{Symbol => Object}] options
231232
# See options in {JSON::LD::API#initialize}
232233
# Other options passed to {JSON::LD::API.expand}
234+
# @option options [Boolean] :expanded Input is already expanded
233235
# @yield jsonld
234236
# @yieldparam [Hash] jsonld
235237
# The framed JSON-LD document
@@ -242,19 +244,19 @@ def self.flatten(input, context, options = {})
242244
flattened = []
243245

244246
# Expand input to simplify processing
245-
expanded_input = API.expand(input, options)
247+
expanded_input = options[:expanded] ? input : API.expand(input, options)
246248

247249
# Initialize input using frame as context
248250
API.new(expanded_input, context, options) do
249251
debug(".flatten") {"expanded input: #{value.to_json(JSON_STATE) rescue 'malformed json'}"}
250252

251253
# Initialize node map to a JSON object consisting of a single member whose key is @default and whose value is an empty JSON object.
252-
node_map = {'@default' => {}}
253-
self.generate_node_map(value, node_map)
254+
graphs = {'@default' => {}}
255+
self.create_node_map(value, graphs)
254256

255-
default_graph = node_map['@default']
256-
node_map.keys.kw_sort.reject {|k| k == '@default'}.each do |graph_name|
257-
graph = node_map[graph_name]
257+
default_graph = graphs['@default']
258+
graphs.keys.kw_sort.reject {|k| k == '@default'}.each do |graph_name|
259+
graph = graphs[graph_name]
258260
entry = default_graph[graph_name] ||= {'@id' => graph_name}
259261
nodes = entry['@graph'] ||= []
260262
graph.keys.kw_sort.each do |id|
@@ -291,15 +293,17 @@ def self.flatten(input, context, options = {})
291293
# @param [Hash{Symbol => Object}] options
292294
# See options in {JSON::LD::API#initialize}
293295
# Other options passed to {JSON::LD::API.expand}
294-
# @option options [Boolean] :embed (true)
296+
# @option options ['@last', '@always', '@never', '@link'] :embed ('@link')
295297
# a flag specifying that objects should be directly embedded in the output,
296298
# instead of being referred to by their IRI.
297299
# @option options [Boolean] :explicit (false)
298300
# a flag specifying that for properties to be included in the output,
299301
# they must be explicitly declared in the framing context.
302+
# @option options [Boolean] :requireAll (true)
300303
# @option options [Boolean] :omitDefault (false)
301304
# a flag specifying that properties that are missing from the JSON-LD
302305
# input should be omitted from the output.
306+
# @option options [Boolean] :expanded Input is already expanded
303307
# @yield jsonld
304308
# @yieldparam [Hash] jsonld
305309
# The framed JSON-LD document
@@ -310,16 +314,22 @@ def self.flatten(input, context, options = {})
310314
# @see http://json-ld.org/spec/latest/json-ld-api/#framing-algorithm
311315
def self.frame(input, frame, options = {})
312316
result = nil
317+
options = {
318+
base: input.is_a?(String) ? input : '',
319+
compactArrays: true,
320+
embed: '@last',
321+
explicit: false,
322+
requireAll: true,
323+
omitDefault: false,
324+
documentLoader: method(:documentLoader)
325+
}.merge(options)
326+
313327
framing_state = {
314-
embed: true,
315-
explicit: false,
316-
omitDefault: false,
317-
embeds: nil,
328+
options: options,
329+
graphs: {'@default' => {}, '@merged' => {}},
330+
subjectStack: [],
331+
link: {},
318332
}
319-
framing_state[:embed] = options[:embed] if options.has_key?(:embed)
320-
framing_state[:explicit] = options[:explicit] if options.has_key?(:explicit)
321-
framing_state[:omitDefault] = options[:omitDefault] if options.has_key?(:omitDefault)
322-
options[:documentLoader] ||= method(:documentLoader)
323333

324334
# de-reference frame to create the framing object
325335
frame = case frame
@@ -334,30 +344,25 @@ def self.frame(input, frame, options = {})
334344
end
335345

336346
# Expand input to simplify processing
337-
expanded_input = API.expand(input, options)
347+
expanded_input = options[:expanded] ? input : API.expand(input, options)
338348

339349
# Expand frame to simplify processing
340350
expanded_frame = API.expand(frame, options)
341351

342352
# Initialize input using frame as context
343353
API.new(expanded_input, nil, options) do
344354
#debug(".frame") {"context from frame: #{context.inspect}"}
345-
debug(".frame") {"raw frame: #{frame.to_json(JSON_STATE) rescue 'malformed json'}"}
346355
debug(".frame") {"expanded frame: #{expanded_frame.to_json(JSON_STATE) rescue 'malformed json'}"}
347-
debug(".frame") {"expanded input: #{value.to_json(JSON_STATE) rescue 'malformed json'}"}
348356

349357
# Get framing nodes from expanded input, replacing Blank Node identifiers as necessary
350-
all_nodes = {}
351358
old_dbg, @options[:debug] = @options[:debug], nil
352-
depth do
353-
generate_node_map(value, all_nodes)
354-
end
359+
create_node_map(value, framing_state[:graphs], '@merged')
355360
@options[:debug] = old_dbg
356-
@node_map = all_nodes['@default']
357-
debug(".frame") {"node_map: #{@node_map.to_json(JSON_STATE) rescue 'malformed json'}"}
361+
framing_state[:subjects] = framing_state[:graphs]['@merged']
362+
debug(".frame") {"subjects: #{framing_state[:subjects].to_json(JSON_STATE) rescue 'malformed json'}"}
358363

359364
result = []
360-
frame(framing_state, @node_map, (expanded_frame.first || {}), parent: result)
365+
frame(framing_state, framing_state[:subjects], (expanded_frame.first || {}), parent: result)
361366
debug(".frame") {"after frame: #{result.to_json(JSON_STATE) rescue 'malformed json'}"}
362367

363368
# Initalize context from frame
@@ -386,6 +391,7 @@ def self.frame(input, frame, options = {})
386391
# Options passed to {JSON::LD::API.expand}
387392
# @option options [Boolean] :produceGeneralizedRdf (false)
388393
# If true, output will include statements having blank node predicates, otherwise they are dropped.
394+
# @option options [Boolean] :expanded Input is already expanded
389395
# @raise [JsonLdError]
390396
# @yield statement
391397
# @yieldparam [RDF::Statement] statement
@@ -401,20 +407,20 @@ def self.toRdf(input, options = {}, &block)
401407
end
402408

403409
# Expand input to simplify processing
404-
expanded_input = API.expand(input, options.merge(ordered: false))
410+
expanded_input = options[:expanded] ? input : API.expand(input, options.merge(ordered: false))
405411

406412
API.new(expanded_input, nil, options) do
407413
# 1) Perform the Expansion Algorithm on the JSON-LD input.
408414
# This removes any existing context to allow the given context to be cleanly applied.
409415
debug(".toRdf") {"expanded input: #{expanded_input.to_json(JSON_STATE) rescue 'malformed json'}"}
410416

411417
# Generate _nodeMap_
412-
node_map = {'@default' => {}}
413-
generate_node_map(expanded_input, node_map)
414-
debug(".toRdf") {"node map: #{node_map.to_json(JSON_STATE) rescue 'malformed json'}"}
418+
graphs = {'@default' => {}}
419+
create_node_map(expanded_input, graphs)
420+
debug(".toRdf") {"node map: #{graphs.to_json(JSON_STATE) rescue 'malformed json'}"}
415421

416422
# Start generating statements
417-
node_map.each do |graph_name, graph|
423+
graphs.each do |graph_name, graph|
418424
context = as_resource(graph_name) unless graph_name == '@default'
419425
debug(".toRdf") {"context: #{context ? context.to_ntriples : 'null'}"}
420426
# Drop results for graphs which are named with relative IRIs

lib/json/ld/expand.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ def expand(input, active_property, context, options = {})
182182

183183
# Continue with the next key from element
184184
next
185-
when '@explicit', '@default', '@embed', '@embedChildren', '@omitDefault'
185+
when '@explicit', '@default', '@embed', '@explicit', '@omitDefault', '@preserve', '@requireAll'
186186
# Framing keywords
187187
depth { [expand(value, expanded_property, context, options)].flatten }
188188
else

0 commit comments

Comments
 (0)