lib/json/ld/compact.rb in json-ld-2.2.1 vs lib/json/ld/compact.rb in json-ld-3.0.0
- old
+ new
@@ -28,11 +28,12 @@
result = element.map {|item| compact(item, property: property)}.compact
# If element has a single member and the active property has no
# @container mapping to @list or @set, the compacted value is that
# member; otherwise the compacted value is element
- if result.length == 1 && !context.as_array?(property) && @options[:compactArrays]
+ if result.length == 1 &&
+ !context.as_array?(property) && @options[:compactArrays]
#log_debug("=> extract single element: #{result.first.inspect}")
result.first
else
#log_debug("=> array result: #{result.inspect}")
result
@@ -49,30 +50,38 @@
#log_debug("") {"=> scalar result: #{result.inspect}"}
return result
end
end
+ # If expanded property is @list and we're contained within a list container, recursively compact this item to an array
+ if list?(element) && context.container(property) == %w(@list)
+ return compact(element['@list'], property: property)
+ end
+
+
inside_reverse = property == '@reverse'
result, nest_result = {}, nil
+ # Apply any context defined on an alias of @type
+ # If key is @type and any compacted value is a term having a local context, overlay that context.
+ Array(element['@type']).
+ map {|expanded_type| context.compact_iri(expanded_type, vocab: true)}.
+ sort.
+ each do |term|
+ term_context = self.context.term_definitions[term].context if context.term_definitions[term]
+ self.context = context.parse(term_context) if term_context
+ end
+
element.keys.sort.each do |expanded_property|
expanded_value = element[expanded_property]
#log_debug("") {"#{expanded_property}: #{expanded_value.inspect}"}
if expanded_property == '@id' || expanded_property == '@type'
- compacted_value = [expanded_value].flatten.compact.map do |expanded_type|
+ compacted_value = Array(expanded_value).map do |expanded_type|
context.compact_iri(expanded_type, vocab: (expanded_property == '@type'), log_depth: @options[:log_depth])
end
- # If key is @type and any compacted value is a term having a local context, overlay that context.
- if expanded_property == '@type'
- compacted_value.each do |term|
- term_context = self.context.term_definitions[term].context if context.term_definitions[term]
- self.context = context.parse(term_context) if term_context
- end
- end
-
compacted_value = compacted_value.first if compacted_value.length == 1
al = context.compact_iri(expanded_property, vocab: true, quiet: true)
#log_debug(expanded_property) {"result[#{al}] = #{compacted_value.inspect}"}
result[al] = compacted_value
@@ -83,15 +92,12 @@
compacted_value = compact(expanded_value, property: '@reverse')
#log_debug("@reverse") {"compacted_value: #{compacted_value.inspect}"}
# handle double-reversed properties
compacted_value.each do |prop, value|
if context.reverse?(prop)
- value = [value] if !value.is_a?(Array) &&
- (context.as_array?(prop) || !@options[:compactArrays])
- #log_debug("") {"merge #{prop} => #{value.inspect}"}
-
- merge_compacted_value(result, prop, value)
+ add_value(result, prop, value,
+ property_is_array: context.as_array?(prop) || !@options[:compactArrays])
compacted_value.delete(prop)
end
end
unless compacted_value.empty?
@@ -134,15 +140,15 @@
reverse: inside_reverse,
log_depth: @options[:log_depth])
if nest_prop = context.nest(item_active_property)
result[nest_prop] ||= {}
- iap = result[result[nest_prop]] ||= []
- result[nest_prop][item_active_property] = [iap] unless iap.is_a?(Array)
+ add_value(result[nest_prop], item_active_property, [],
+ property_is_array: true)
else
- iap = result[item_active_property] ||= []
- result[item_active_property] = [iap] unless iap.is_a?(Array)
+ add_value(result, item_active_property, [],
+ property_is_array: true)
end
end
# At this point, expanded value must be an array due to the Expansion algorithm.
expanded_value.each do |expanded_item|
@@ -160,11 +166,11 @@
else
result
end
container = context.container(item_active_property)
- as_array = context.as_array?(item_active_property)
+ as_array = !@options[:compactArrays] || context.as_array?(item_active_property)
value = case
when list?(expanded_item) then expanded_item['@list']
when graph?(expanded_item) then expanded_item['@graph']
else expanded_item
@@ -173,99 +179,97 @@
compacted_item = compact(value, property: item_active_property)
#log_debug("") {" => compacted key: #{item_active_property.inspect} for #{compacted_item.inspect}"}
# handle @list
if list?(expanded_item)
- compacted_item = [compacted_item] unless compacted_item.is_a?(Array)
+ compacted_item = as_array(compacted_item)
unless container == %w(@list)
al = context.compact_iri('@list', vocab: true, quiet: true)
compacted_item = {al => compacted_item}
if expanded_item.has_key?('@index')
key = context.compact_iri('@index', vocab: true, quiet: true)
compacted_item[key] = expanded_item['@index']
end
else
- raise JsonLdError::CompactionToListOfLists,
- "key cannot have more than one list value" if nest_result.has_key?(item_active_property)
- # Falls through to add list value below
+ add_value(nest_result, item_active_property, compacted_item,
+ value_is_array: true, allow_duplicate: true)
+ next
end
end
# Graph object compaction cases:
if graph?(expanded_item)
- if container.include?('@graph') && container.include?('@id')
+ if container.include?('@graph') &&
+ (container.include?('@id') || container.include?('@index') && simple_graph?(expanded_item))
# container includes @graph and @id
map_object = nest_result[item_active_property] ||= {}
- map_key = expanded_item['@id']
# If there is no @id, create a blank node identifier to use as an index
- map_key = map_key ? context.compact_iri(map_key, quiet: true) : namer.get_name
- merge_compacted_value(map_object, map_key, compacted_item)
- elsif container.include?('@graph') && container.include?('@index') && simple_graph?(expanded_item)
- # container includes @graph and @index and value is a simple graph object
- map_object = nest_result[item_active_property] ||= {}
- # If there is no @index, use @none
- map_key = expanded_item['@index'] || '@none'
- merge_compacted_value(map_object, map_key, compacted_item)
+ map_key = if container.include?('@id') && expanded_item['@id']
+ context.compact_iri(expanded_item['@id'], quiet: true)
+ elsif container.include?('@index') && expanded_item['@index']
+ context.compact_iri(expanded_item['@index'], quiet: true)
+ else
+ context.compact_iri('@none', vocab: true, quiet: true)
+ end
+ add_value(map_object, map_key, compacted_item,
+ property_is_array: as_array)
elsif container.include?('@graph') && simple_graph?(expanded_item)
# container includes @graph but not @id or @index and value is a simple graph object
# Drop through, where compacted_value will be added
- compacted_item = [compacted_item] if
- !compacted_item.is_a?(Array) && (!@options[:compactArrays] || as_array)
- merge_compacted_value(nest_result, item_active_property, compacted_item)
+ add_value(nest_result, item_active_property, compacted_item,
+ property_is_array: as_array)
else
# container does not include @graph or otherwise does not match one of the previous cases, redo compacted_item
- compacted_item = [compacted_item]
al = context.compact_iri('@graph', vocab: true, quiet: true)
compacted_item = {al => compacted_item}
if expanded_item['@id']
al = context.compact_iri('@id', vocab: true, quiet: true)
compacted_item[al] = context.compact_iri(expanded_item['@id'], vocab: false, quiet: true).to_s
end
if expanded_item.has_key?('@index')
key = context.compact_iri('@index', vocab: true, quiet: true)
compacted_item[key] = expanded_item['@index']
end
- compacted_item = [compacted_item] if !@options[:compactArrays] || as_array
- merge_compacted_value(nest_result, item_active_property, compacted_item)
+ add_value(nest_result, item_active_property, compacted_item,
+ property_is_array: as_array)
end
elsif !(container & %w(@language @index @id @type)).empty? && !container.include?('@graph')
map_object = nest_result[item_active_property] ||= {}
+ c = container.first
+ container_key = context.compact_iri(c, vocab: true, quiet: true)
compacted_item = case container
when %w(@id)
- id_prop = context.compact_iri('@id', vocab: true, quiet: true)
- map_key = compacted_item[id_prop]
- map_key = context.compact_iri(map_key, quiet: true)
- compacted_item.delete(id_prop)
+ map_key = compacted_item[container_key]
+ compacted_item.delete(container_key)
compacted_item
when %w(@index)
map_key = expanded_item['@index']
+ compacted_item.delete(container_key) if compacted_item.is_a?(Hash)
compacted_item
when %w(@language)
map_key = expanded_item['@language']
value?(expanded_item) ? expanded_item['@value'] : compacted_item
when %w(@type)
- type_prop = context.compact_iri('@type', vocab: true, quiet: true)
- map_key, *types = Array(compacted_item[type_prop])
- map_key = context.compact_iri(map_key, vocab: true, quiet: true)
+ map_key, *types = Array(compacted_item[container_key])
case types.length
- when 0 then compacted_item.delete(type_prop)
- when 1 then compacted_item[type_prop] = types.first
- else compacted_item[type_prop] = types
+ when 0 then compacted_item.delete(container_key)
+ when 1 then compacted_item[container_key] = types.first
+ else compacted_item[container_key] = types
end
compacted_item
end
- compacted_item = [compacted_item] if as_array && !compacted_item.is_a?(Array)
- merge_compacted_value(map_object, map_key, compacted_item)
+ map_key ||= context.compact_iri('@none', vocab: true, quiet: true)
+ add_value(map_object, map_key, compacted_item,
+ property_is_array: as_array)
else
- compacted_item = [compacted_item] if
- !compacted_item.is_a?(Array) && (!@options[:compactArrays] || as_array)
- merge_compacted_value(nest_result, item_active_property, compacted_item)
+ add_value(nest_result, item_active_property, compacted_item,
+ property_is_array: as_array)
end
end
end
# Re-order result keys
- result.keys.kw_sort.each_with_object({}) {|kk, memo| memo[kk] = result[kk]}
+ result.keys.sort.each_with_object({}) {|kk, memo| memo[kk] = result[kk]}
else
# For other types, the compacted value is the element value
#log_debug("compact") {element.class.to_s}
element
end