lib/json/ld/compact.rb in json-ld-2.1.2 vs lib/json/ld/compact.rb in json-ld-2.1.3

- old
+ new

@@ -14,10 +14,16 @@ #if property.nil? # log_debug("compact") {"element: #{element.inspect}, ec: #{context.inspect}"} #else # log_debug("compact") {"property: #{property.inspect}"} #end + + # If the term definition for active property itself contains a context, use that for compacting values. + input_context = self.context + td = self.context.term_definitions[property] if property + self.context = (td && td.context && self.context.parse(td.context)) || input_context + case element when Array #log_debug("") {"Array #{element.inspect}"} result = element.map {|item| compact(item, property: property)}.compact @@ -44,20 +50,29 @@ return result end end inside_reverse = property == '@reverse' - result = {} + result, nest_result = {}, nil - element.each_key do |expanded_property| + element.keys.sort.each do |expanded_property| expanded_value = element[expanded_property] #log_debug("") {"#{expanded_property}: #{expanded_value.inspect}"} if %w(@id @type).include?(expanded_property) compacted_value = [expanded_value].flatten.compact.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 @@ -70,10 +85,11 @@ compacted_value.each do |prop, value| if context.reverse?(prop) value = [value] if !value.is_a?(Array) && (context.container(prop) == '@set' || !@options[:compactArrays]) #log_debug("") {"merge #{prop} => #{value.inspect}"} + merge_compacted_value(result, prop, value) compacted_value.delete(prop) end end @@ -104,12 +120,18 @@ value: expanded_value, vocab: true, reverse: inside_reverse, log_depth: @options[:log_depth]) - iap = result[item_active_property] ||= [] - result[item_active_property] = [iap] unless iap.is_a?(Array) + 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) + else + iap = result[item_active_property] ||= [] + result[item_active_property] = [iap] unless iap.is_a?(Array) + end end # At this point, expanded value must be an array due to the Expansion algorithm. expanded_value.each do |expanded_item| item_active_property = @@ -117,10 +139,18 @@ value: expanded_item, vocab: true, reverse: inside_reverse, log_depth: @options[:log_depth]) + + nest_result = if nest_prop = context.nest(item_active_property) + # FIXME??: It's possible that nest_prop will be used both for nesting, and for values of @nest + result[nest_prop] ||= {} + else + result + end + container = context.container(item_active_property) value = list?(expanded_item) ? expanded_item['@list'] : expanded_item compacted_item = compact(value, property: item_active_property) #log_debug("") {" => compacted key: #{item_active_property.inspect} for #{compacted_item.inspect}"} @@ -133,27 +163,49 @@ 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 result.has_key?(item_active_property) + "key cannot have more than one list value" if nest_result.has_key?(item_active_property) end end - if %w(@language @index).include?(container) - map_object = result[item_active_property] ||= {} - compacted_item = compacted_item['@value'] if container == '@language' && value?(compacted_item) - map_key = expanded_item[container] + if %w(@language @index @id @type).include?(container) + map_object = nest_result[item_active_property] ||= {} + compacted_item = case container + when '@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) + compacted_item + when '@index' + map_key = expanded_item[container] + compacted_item + when '@language' + map_key = expanded_item[container] + value?(expanded_item) ? expanded_item['@value'] : compacted_item + when '@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) + 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 + end + compacted_item + end merge_compacted_value(map_object, map_key, compacted_item) else compacted_item = [compacted_item] if !compacted_item.is_a?(Array) && ( !@options[:compactArrays] || %w(@set @list).include?(container) || %w(@list @graph).include?(expanded_property) ) - merge_compacted_value(result, item_active_property, compacted_item) + merge_compacted_value(nest_result, item_active_property, compacted_item) end end end # Re-order result keys @@ -161,8 +213,11 @@ else # For other types, the compacted value is the element value #log_debug("compact") {element.class.to_s} element end + + ensure + self.context = input_context end end end