json-ld 3.2.3 → 3.2.5

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.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/lib/json/ld/api.rb +807 -764
  4. data/lib/json/ld/compact.rb +304 -304
  5. data/lib/json/ld/conneg.rb +179 -161
  6. data/lib/json/ld/context.rb +2080 -1945
  7. data/lib/json/ld/expand.rb +745 -666
  8. data/lib/json/ld/extensions.rb +14 -13
  9. data/lib/json/ld/flatten.rb +257 -247
  10. data/lib/json/ld/format.rb +202 -194
  11. data/lib/json/ld/frame.rb +525 -502
  12. data/lib/json/ld/from_rdf.rb +224 -166
  13. data/lib/json/ld/html/nokogiri.rb +123 -121
  14. data/lib/json/ld/html/rexml.rb +151 -147
  15. data/lib/json/ld/reader.rb +107 -100
  16. data/lib/json/ld/resource.rb +224 -205
  17. data/lib/json/ld/streaming_reader.rb +574 -507
  18. data/lib/json/ld/streaming_writer.rb +93 -92
  19. data/lib/json/ld/to_rdf.rb +171 -167
  20. data/lib/json/ld/utils.rb +270 -264
  21. data/lib/json/ld/version.rb +24 -14
  22. data/lib/json/ld/writer.rb +334 -311
  23. data/lib/json/ld.rb +103 -96
  24. metadata +78 -209
  25. data/spec/api_spec.rb +0 -132
  26. data/spec/compact_spec.rb +0 -3482
  27. data/spec/conneg_spec.rb +0 -373
  28. data/spec/context_spec.rb +0 -2036
  29. data/spec/expand_spec.rb +0 -4496
  30. data/spec/flatten_spec.rb +0 -1203
  31. data/spec/format_spec.rb +0 -115
  32. data/spec/frame_spec.rb +0 -2498
  33. data/spec/from_rdf_spec.rb +0 -1005
  34. data/spec/matchers.rb +0 -20
  35. data/spec/rdfstar_spec.rb +0 -25
  36. data/spec/reader_spec.rb +0 -883
  37. data/spec/resource_spec.rb +0 -76
  38. data/spec/spec_helper.rb +0 -281
  39. data/spec/streaming_reader_spec.rb +0 -237
  40. data/spec/streaming_writer_spec.rb +0 -145
  41. data/spec/suite_compact_spec.rb +0 -22
  42. data/spec/suite_expand_spec.rb +0 -36
  43. data/spec/suite_flatten_spec.rb +0 -34
  44. data/spec/suite_frame_spec.rb +0 -29
  45. data/spec/suite_from_rdf_spec.rb +0 -22
  46. data/spec/suite_helper.rb +0 -411
  47. data/spec/suite_html_spec.rb +0 -22
  48. data/spec/suite_http_spec.rb +0 -35
  49. data/spec/suite_remote_doc_spec.rb +0 -22
  50. data/spec/suite_to_rdf_spec.rb +0 -30
  51. data/spec/support/extensions.rb +0 -44
  52. data/spec/test-files/test-1-compacted.jsonld +0 -10
  53. data/spec/test-files/test-1-context.jsonld +0 -7
  54. data/spec/test-files/test-1-expanded.jsonld +0 -5
  55. data/spec/test-files/test-1-input.jsonld +0 -10
  56. data/spec/test-files/test-1-rdf.ttl +0 -8
  57. data/spec/test-files/test-2-compacted.jsonld +0 -20
  58. data/spec/test-files/test-2-context.jsonld +0 -7
  59. data/spec/test-files/test-2-expanded.jsonld +0 -16
  60. data/spec/test-files/test-2-input.jsonld +0 -20
  61. data/spec/test-files/test-2-rdf.ttl +0 -14
  62. data/spec/test-files/test-3-compacted.jsonld +0 -11
  63. data/spec/test-files/test-3-context.jsonld +0 -8
  64. data/spec/test-files/test-3-expanded.jsonld +0 -10
  65. data/spec/test-files/test-3-input.jsonld +0 -11
  66. data/spec/test-files/test-3-rdf.ttl +0 -8
  67. data/spec/test-files/test-4-compacted.jsonld +0 -10
  68. data/spec/test-files/test-4-context.jsonld +0 -7
  69. data/spec/test-files/test-4-expanded.jsonld +0 -6
  70. data/spec/test-files/test-4-input.jsonld +0 -10
  71. data/spec/test-files/test-4-rdf.ttl +0 -5
  72. data/spec/test-files/test-5-compacted.jsonld +0 -13
  73. data/spec/test-files/test-5-context.jsonld +0 -7
  74. data/spec/test-files/test-5-expanded.jsonld +0 -9
  75. data/spec/test-files/test-5-input.jsonld +0 -13
  76. data/spec/test-files/test-5-rdf.ttl +0 -7
  77. data/spec/test-files/test-6-compacted.jsonld +0 -10
  78. data/spec/test-files/test-6-context.jsonld +0 -7
  79. data/spec/test-files/test-6-expanded.jsonld +0 -10
  80. data/spec/test-files/test-6-input.jsonld +0 -10
  81. data/spec/test-files/test-6-rdf.ttl +0 -6
  82. data/spec/test-files/test-7-compacted.jsonld +0 -23
  83. data/spec/test-files/test-7-context.jsonld +0 -4
  84. data/spec/test-files/test-7-expanded.jsonld +0 -20
  85. data/spec/test-files/test-7-input.jsonld +0 -23
  86. data/spec/test-files/test-7-rdf.ttl +0 -14
  87. data/spec/test-files/test-8-compacted.jsonld +0 -34
  88. data/spec/test-files/test-8-context.jsonld +0 -11
  89. data/spec/test-files/test-8-expanded.jsonld +0 -24
  90. data/spec/test-files/test-8-frame.jsonld +0 -18
  91. data/spec/test-files/test-8-framed.jsonld +0 -25
  92. data/spec/test-files/test-8-input.jsonld +0 -30
  93. data/spec/test-files/test-8-rdf.ttl +0 -15
  94. data/spec/test-files/test-9-compacted.jsonld +0 -20
  95. data/spec/test-files/test-9-context.jsonld +0 -13
  96. data/spec/test-files/test-9-expanded.jsonld +0 -14
  97. data/spec/test-files/test-9-input.jsonld +0 -12
  98. data/spec/to_rdf_spec.rb +0 -1551
  99. data/spec/writer_spec.rb +0 -427
@@ -1,356 +1,356 @@
1
- # -*- encoding: utf-8 -*-
2
1
  # frozen_string_literal: true
3
- module JSON::LD
4
- module Compact
5
- include Utils
6
-
7
- # The following constant is used to reduce object allocations in #compact below
8
- CONTAINER_MAPPING_LANGUAGE_INDEX_ID_TYPE = Set.new(%w(@language @index @id @type)).freeze
9
- EXPANDED_PROPERTY_DIRECTION_INDEX_LANGUAGE_VALUE = %w(@direction @index @language @value).freeze
10
-
11
- ##
12
- # This algorithm compacts a JSON-LD document, such that the given context is applied. This must result in shortening any applicable IRIs to terms or compact IRIs, any applicable keywords to keyword aliases, and any applicable JSON-LD values expressed in expanded form to simple values such as strings or numbers.
13
- #
14
- # @param [Array, Hash] element
15
- # @param [String, RDF::URI] base (nil)
16
- # Ensure output objects have keys ordered properly
17
- # @param [String] property (nil)
18
- # Extra validatation
19
- # @return [Array, Hash]
20
- def compact(element,
21
- base: nil,
22
- property: nil,
23
- log_depth: nil)
24
- log_debug("compact", depth: log_depth.to_i) {"element: #{element.inspect}, ec: #{context.inspect}"}
25
-
26
- # If the term definition for active property itself contains a context, use that for compacting values.
27
- input_context = self.context
28
-
29
- case element
30
- when Array
31
- #log_debug("") {"Array #{element.inspect}"}
32
- result = element.map do |item|
33
- compact(item, base: base, property: property, log_depth: log_depth.to_i + 1)
34
- end.compact
35
-
36
- # If element has a single member and the active property has no
37
- # @container mapping to @list or @set, the compacted value is that
38
- # member; otherwise the compacted value is element
39
- if result.length == 1 &&
40
- !context.as_array?(property) && @options[:compactArrays]
41
- log_debug("=> extract single element", depth: log_depth.to_i) {result.first.inspect}
42
- result.first
43
- else
44
- log_debug("=> array result", depth: log_depth.to_i) {result.inspect}
45
- result
46
- end
47
- when Hash
48
- # Otherwise element is a JSON object.
49
2
 
50
- # @null objects are used in framing
51
- return nil if element.key?('@null')
3
+ module JSON
4
+ module LD
5
+ module Compact
6
+ include Utils
7
+
8
+ # The following constant is used to reduce object allocations in #compact below
9
+ CONTAINER_MAPPING_LANGUAGE_INDEX_ID_TYPE = Set.new(%w[@language @index @id @type]).freeze
10
+ EXPANDED_PROPERTY_DIRECTION_INDEX_LANGUAGE_VALUE = %w[@direction @index @language @value].freeze
11
+
12
+ ##
13
+ # This algorithm compacts a JSON-LD document, such that the given context is applied. This must result in shortening any applicable IRIs to terms or compact IRIs, any applicable keywords to keyword aliases, and any applicable JSON-LD values expressed in expanded form to simple values such as strings or numbers.
14
+ #
15
+ # @param [Array, Hash] element
16
+ # @param [String, RDF::URI] base (nil)
17
+ # Ensure output objects have keys ordered properly
18
+ # @param [String] property (nil)
19
+ # Extra validatation
20
+ # @return [Array, Hash]
21
+ def compact(element,
22
+ base: nil,
23
+ property: nil,
24
+ log_depth: nil)
25
+ # log_debug("compact", depth: log_depth.to_i) {"element: #{element.inspect}, ec: #{context.inspect}"}
26
+
27
+ # If the term definition for active property itself contains a context, use that for compacting values.
28
+ input_context = context
29
+
30
+ case element
31
+ when Array
32
+ # log_debug("") {"Array #{element.inspect}"}
33
+ result = element.map do |item|
34
+ compact(item, base: base, property: property, log_depth: log_depth.to_i + 1)
35
+ end.compact
36
+
37
+ # If element has a single member and the active property has no
38
+ # @container mapping to @list or @set, the compacted value is that
39
+ # member; otherwise the compacted value is element
40
+ if result.length == 1 &&
41
+ !context.as_array?(property) && @options[:compactArrays]
42
+ # log_debug("=> extract single element", depth: log_depth.to_i) {result.first.inspect}
43
+ result.first
44
+ else
45
+ # log_debug("=> array result", depth: log_depth.to_i) {result.inspect}
46
+ result
47
+ end
48
+ when Hash
49
+ # Otherwise element is a JSON object.
52
50
 
53
- # Revert any previously type-scoped (non-preserved) context
54
- if context.previous_context && !element.key?('@value') && element.keys != %w(@id)
55
- log_debug("revert ec", depth: log_depth.to_i) {"previous context: #{context.previous_context.inspect}"}
56
- self.context = context.previous_context
57
- end
51
+ # @null objects are used in framing
52
+ return nil if element.key?('@null')
58
53
 
59
- # Look up term definintions from property using the original type-scoped context, if it exists, but apply them to the now current previous context
60
- td = input_context.term_definitions[property] if property
61
- if td && !td.context.nil?
62
- self.context = context.parse(td.context,
63
- override_protected: true)
64
- log_debug("prop-scoped", depth: log_depth.to_i) {"context: #{self.context.inspect}"}
65
- end
54
+ # Revert any previously type-scoped (non-preserved) context
55
+ if context.previous_context && !element.key?('@value') && element.keys != %w[@id]
56
+ # log_debug("revert ec", depth: log_depth.to_i) {"previous context: #{context.previous_context.inspect}"}
57
+ self.context = context.previous_context
58
+ end
66
59
 
67
- if (element.key?('@id') || element.key?('@value')) && !element.key?('@annotation')
68
- result = context.compact_value(property, element, base: @options[:base])
69
- if !result.is_a?(Hash) || context.coerce(property) == '@json'
70
- log_debug("", depth: log_depth.to_i) {"=> scalar result: #{result.inspect}"}
71
- return result
60
+ # Look up term definintions from property using the original type-scoped context, if it exists, but apply them to the now current previous context
61
+ td = input_context.term_definitions[property] if property
62
+ if td && !td.context.nil?
63
+ self.context = context.parse(td.context,
64
+ override_protected: true)
65
+ # log_debug("prop-scoped", depth: log_depth.to_i) {"context: #{self.context.inspect}"}
72
66
  end
73
- end
74
67
 
75
- # If expanded property is @list and we're contained within a list container, recursively compact this item to an array
76
- if list?(element) && context.container(property).include?('@list')
77
- return compact(element['@list'], base: base,
78
- property: property,
79
- log_depth: log_depth.to_i + 1)
80
- end
68
+ if (element.key?('@id') || element.key?('@value')) && !element.key?('@annotation')
69
+ result = context.compact_value(property, element, base: @options[:base])
70
+ if !result.is_a?(Hash) || context.coerce(property) == '@json'
71
+ # log_debug("", depth: log_depth.to_i) {"=> scalar result: #{result.inspect}"}
72
+ return result
73
+ end
74
+ end
81
75
 
82
- inside_reverse = property == '@reverse'
83
- result, nest_result = {}, nil
84
-
85
- # Apply any context defined on an alias of @type
86
- # If key is @type and any compacted value is a term having a local context, overlay that context.
87
- Array(element['@type']).
88
- map {|expanded_type| context.compact_iri(expanded_type, vocab: true)}.
89
- sort.
90
- each do |term|
91
- term_context = input_context.term_definitions[term].context if input_context.term_definitions[term]
92
- self.context = context.parse(term_context, propagate: false) unless term_context.nil?
93
- log_debug("type-scoped", depth: log_depth.to_i) {"context: #{self.context.inspect}"}
94
- end
76
+ # If expanded property is @list and we're contained within a list container, recursively compact this item to an array
77
+ if list?(element) && context.container(property).include?('@list')
78
+ return compact(element['@list'], base: base,
79
+ property: property,
80
+ log_depth: log_depth.to_i + 1)
81
+ end
95
82
 
96
- element.keys.opt_sort(ordered: @options[:ordered]).each do |expanded_property|
97
- expanded_value = element[expanded_property]
98
- log_debug("", depth: log_depth.to_i) {"#{expanded_property}: #{expanded_value.inspect}"}
99
-
100
- if expanded_property == '@id'
101
- compacted_value = as_array(expanded_value).map do |expanded_id|
102
- if node?(expanded_id) && @options[:rdfstar]
103
- # This can only really happen for valid RDF-star
104
- compact(expanded_id, base: base,
105
- property: '@id',
106
- log_depth: log_depth.to_i + 1)
107
- else
108
- context.compact_iri(expanded_id, base: @options[:base])
83
+ inside_reverse = property == '@reverse'
84
+ result = {}
85
+ nest_result = nil
86
+
87
+ # Apply any context defined on an alias of @type
88
+ # If key is @type and any compacted value is a term having a local context, overlay that context.
89
+ Array(element['@type'])
90
+ .map { |expanded_type| context.compact_iri(expanded_type, vocab: true) }
91
+ .sort
92
+ .each do |term|
93
+ term_context = input_context.term_definitions[term].context if input_context.term_definitions[term]
94
+ self.context = context.parse(term_context, propagate: false) unless term_context.nil?
95
+ # log_debug("type-scoped", depth: log_depth.to_i) {"context: #{self.context.inspect}"}
96
+ end
97
+
98
+ element.keys.opt_sort(ordered: @options[:ordered]).each do |expanded_property|
99
+ expanded_value = element[expanded_property]
100
+ # log_debug("", depth: log_depth.to_i) {"#{expanded_property}: #{expanded_value.inspect}"}
101
+
102
+ if expanded_property == '@id'
103
+ compacted_value = as_array(expanded_value).map do |expanded_id|
104
+ if node?(expanded_id) && @options[:rdfstar]
105
+ # This can only really happen for valid RDF-star
106
+ compact(expanded_id, base: base,
107
+ property: '@id',
108
+ log_depth: log_depth.to_i + 1)
109
+ else
110
+ context.compact_iri(expanded_id, base: @options[:base])
111
+ end
109
112
  end
113
+
114
+ kw_alias = context.compact_iri('@id', vocab: true)
115
+ as_array = compacted_value.length > 1
116
+ compacted_value = compacted_value.first unless as_array
117
+ result[kw_alias] = compacted_value
118
+ next
110
119
  end
111
120
 
112
- kw_alias = context.compact_iri('@id', vocab: true)
113
- as_array = compacted_value.length > 1
114
- compacted_value = compacted_value.first unless as_array
115
- result[kw_alias] = compacted_value
116
- next
117
- end
121
+ if expanded_property == '@type'
122
+ compacted_value = Array(expanded_value).map do |expanded_type|
123
+ input_context.compact_iri(expanded_type, vocab: true)
124
+ end
118
125
 
119
- if expanded_property == '@type'
120
- compacted_value = Array(expanded_value).map do |expanded_type|
121
- input_context.compact_iri(expanded_type, vocab: true)
126
+ kw_alias = context.compact_iri('@type', vocab: true)
127
+ as_array = compacted_value.length > 1 ||
128
+ (context.as_array?(kw_alias) &&
129
+ !value?(element) &&
130
+ context.processingMode('json-ld-1.1'))
131
+ add_value(result, kw_alias, compacted_value, property_is_array: as_array)
132
+ next
122
133
  end
123
134
 
124
- kw_alias = context.compact_iri('@type', vocab: true)
125
- as_array = compacted_value.length > 1 ||
126
- (context.as_array?(kw_alias) &&
127
- !value?(element) &&
128
- context.processingMode('json-ld-1.1'))
129
- add_value(result, kw_alias, compacted_value, property_is_array: as_array)
130
- next
131
- end
135
+ if expanded_property == '@reverse'
136
+ compacted_value = compact(expanded_value, base: base,
137
+ property: '@reverse',
138
+ log_depth: log_depth.to_i + 1)
139
+ # log_debug("@reverse", depth: log_depth.to_i) {"compacted_value: #{compacted_value.inspect}"}
140
+ # handle double-reversed properties
141
+ compacted_value.each do |prop, value|
142
+ next unless context.reverse?(prop)
132
143
 
133
- if expanded_property == '@reverse'
134
- compacted_value = compact(expanded_value, base: base,
135
- property: '@reverse',
136
- log_depth: log_depth.to_i + 1)
137
- log_debug("@reverse", depth: log_depth.to_i) {"compacted_value: #{compacted_value.inspect}"}
138
- # handle double-reversed properties
139
- compacted_value.each do |prop, value|
140
- if context.reverse?(prop)
141
144
  add_value(result, prop, value,
142
145
  property_is_array: context.as_array?(prop) || !@options[:compactArrays])
143
146
  compacted_value.delete(prop)
144
147
  end
145
- end
146
148
 
147
- unless compacted_value.empty?
148
- al = context.compact_iri('@reverse', vocab: true)
149
- log_debug("", depth: log_depth.to_i) {"remainder: #{al} => #{compacted_value.inspect}"}
150
- result[al] = compacted_value
149
+ unless compacted_value.empty?
150
+ al = context.compact_iri('@reverse', vocab: true)
151
+ # log_debug("", depth: log_depth.to_i) {"remainder: #{al} => #{compacted_value.inspect}"}
152
+ result[al] = compacted_value
153
+ end
154
+ next
151
155
  end
152
- next
153
- end
154
156
 
155
- if expanded_property == '@preserve'
156
- # Compact using `property`
157
- compacted_value = compact(expanded_value, base: base,
158
- property: property,
159
- log_depth: log_depth.to_i + 1)
160
- log_debug("@preserve", depth: log_depth.to_i) {"compacted_value: #{compacted_value.inspect}"}
157
+ if expanded_property == '@preserve'
158
+ # Compact using `property`
159
+ compacted_value = compact(expanded_value, base: base,
160
+ property: property,
161
+ log_depth: log_depth.to_i + 1)
162
+ # log_debug("@preserve", depth: log_depth.to_i) {"compacted_value: #{compacted_value.inspect}"}
161
163
 
162
- unless compacted_value.is_a?(Array) && compacted_value.empty?
163
- result['@preserve'] = compacted_value
164
+ result['@preserve'] = compacted_value unless compacted_value.is_a?(Array) && compacted_value.empty?
165
+ next
164
166
  end
165
- next
166
- end
167
-
168
- if expanded_property == '@index' && context.container(property).include?('@index')
169
- log_debug("@index", depth: log_depth.to_i) {"drop @index"}
170
- next
171
- end
172
-
173
- # Otherwise, if expanded property is @direction, @index, @value, or @language:
174
- if EXPANDED_PROPERTY_DIRECTION_INDEX_LANGUAGE_VALUE.include?(expanded_property)
175
- al = context.compact_iri(expanded_property, vocab: true)
176
- log_debug(expanded_property, depth: log_depth.to_i) {"#{al} => #{expanded_value.inspect}"}
177
- result[al] = expanded_value
178
- next
179
- end
180
167
 
181
- if expanded_value.empty?
182
- item_active_property =
183
- context.compact_iri(expanded_property,
184
- value: expanded_value,
185
- vocab: true,
186
- reverse: inside_reverse)
187
-
188
- if nest_prop = context.nest(item_active_property)
189
- result[nest_prop] ||= {}
190
- add_value(result[nest_prop], item_active_property, [],
191
- property_is_array: true)
192
- else
193
- add_value(result, item_active_property, [],
194
- property_is_array: true)
168
+ if expanded_property == '@index' && context.container(property).include?('@index')
169
+ # log_debug("@index", depth: log_depth.to_i) {"drop @index"}
170
+ next
195
171
  end
196
- end
197
-
198
- # At this point, expanded value must be an array due to the Expansion algorithm.
199
- expanded_value.each do |expanded_item|
200
- item_active_property =
201
- context.compact_iri(expanded_property,
202
- value: expanded_item,
203
- vocab: true,
204
- reverse: inside_reverse)
205
172
 
173
+ # Otherwise, if expanded property is @direction, @index, @value, or @language:
174
+ if EXPANDED_PROPERTY_DIRECTION_INDEX_LANGUAGE_VALUE.include?(expanded_property)
175
+ al = context.compact_iri(expanded_property, vocab: true)
176
+ # log_debug(expanded_property, depth: log_depth.to_i) {"#{al} => #{expanded_value.inspect}"}
177
+ result[al] = expanded_value
178
+ next
179
+ end
206
180
 
207
- nest_result = if nest_prop = context.nest(item_active_property)
208
- # FIXME??: It's possible that nest_prop will be used both for nesting, and for values of @nest
209
- result[nest_prop] ||= {}
210
- else
211
- result
181
+ if expanded_value.empty?
182
+ item_active_property =
183
+ context.compact_iri(expanded_property,
184
+ value: expanded_value,
185
+ vocab: true,
186
+ reverse: inside_reverse)
187
+
188
+ if (nest_prop = context.nest(item_active_property))
189
+ result[nest_prop] ||= {}
190
+ add_value(result[nest_prop], item_active_property, [],
191
+ property_is_array: true)
192
+ else
193
+ add_value(result, item_active_property, [],
194
+ property_is_array: true)
195
+ end
212
196
  end
213
197
 
214
- container = context.container(item_active_property)
215
- as_array = !@options[:compactArrays] || context.as_array?(item_active_property)
198
+ # At this point, expanded value must be an array due to the Expansion algorithm.
199
+ expanded_value.each do |expanded_item|
200
+ item_active_property =
201
+ context.compact_iri(expanded_property,
202
+ value: expanded_item,
203
+ vocab: true,
204
+ reverse: inside_reverse)
205
+
206
+ nest_result = if (nest_prop = context.nest(item_active_property))
207
+ # FIXME??: It's possible that nest_prop will be used both for nesting, and for values of @nest
208
+ result[nest_prop] ||= {}
209
+ else
210
+ result
211
+ end
216
212
 
217
- value = case
218
- when list?(expanded_item) then expanded_item['@list']
219
- when graph?(expanded_item) then expanded_item['@graph']
220
- else expanded_item
221
- end
213
+ container = context.container(item_active_property)
214
+ as_array = !@options[:compactArrays] || context.as_array?(item_active_property)
222
215
 
223
- compacted_item = compact(value, base: base,
224
- property: item_active_property,
225
- log_depth: log_depth.to_i + 1)
226
- log_debug("", depth: log_depth.to_i) {" => compacted key: #{item_active_property.inspect} for #{compacted_item.inspect}"}
227
-
228
- # handle @list
229
- if list?(expanded_item)
230
- compacted_item = as_array(compacted_item)
231
- unless container.include?('@list')
232
- al = context.compact_iri('@list', vocab: true)
233
- compacted_item = {al => compacted_item}
234
- if expanded_item.key?('@index')
235
- key = context.compact_iri('@index', vocab: true)
236
- compacted_item[key] = expanded_item['@index']
237
- end
216
+ value = if list?(expanded_item)
217
+ expanded_item['@list']
218
+ elsif graph?(expanded_item)
219
+ expanded_item['@graph']
238
220
  else
239
- add_value(nest_result, item_active_property, compacted_item,
240
- value_is_array: true, allow_duplicate: true)
241
- next
221
+ expanded_item
242
222
  end
243
- end
244
223
 
245
- # Graph object compaction cases:
246
- if graph?(expanded_item)
247
- if container.include?('@graph') &&
248
- (container.include?('@id') || container.include?('@index') && simple_graph?(expanded_item))
249
- # container includes @graph and @id
250
- map_object = nest_result[item_active_property] ||= {}
251
- # If there is no @id, create a blank node identifier to use as an index
252
- map_key = if container.include?('@id') && expanded_item['@id']
253
- context.compact_iri(expanded_item['@id'], base: @options[:base])
254
- elsif container.include?('@index') && expanded_item['@index']
255
- context.compact_iri(expanded_item['@index'], vocab: true)
224
+ compacted_item = compact(value, base: base,
225
+ property: item_active_property,
226
+ log_depth: log_depth.to_i + 1)
227
+ # log_debug("", depth: log_depth.to_i) {" => compacted key: #{item_active_property.inspect} for #{compacted_item.inspect}"}
228
+
229
+ # handle @list
230
+ if list?(expanded_item)
231
+ compacted_item = as_array(compacted_item)
232
+ if container.include?('@list')
233
+ add_value(nest_result, item_active_property, compacted_item,
234
+ value_is_array: true, allow_duplicate: true)
235
+ next
256
236
  else
257
- context.compact_iri('@none', vocab: true)
258
- end
259
- add_value(map_object, map_key, compacted_item,
260
- property_is_array: as_array)
261
- elsif container.include?('@graph') && simple_graph?(expanded_item)
262
- # container includes @graph but not @id or @index and value is a simple graph object
263
- if compacted_item.is_a?(Array) && compacted_item.length > 1
264
- # Mutple objects in the same graph can't be represented directly, as they would be interpreted as two different graphs. Need to wrap in @included.
265
- included_key = context.compact_iri('@included', vocab: true)
266
- compacted_item = {included_key => compacted_item}
267
- end
268
- # Drop through, where compacted_item will be added
269
- add_value(nest_result, item_active_property, compacted_item,
270
- property_is_array: as_array)
271
- else
272
- # container does not include @graph or otherwise does not match one of the previous cases, redo compacted_item
273
- al = context.compact_iri('@graph', vocab: true)
274
- compacted_item = {al => compacted_item}
275
- if expanded_item['@id']
276
- al = context.compact_iri('@id', vocab: true)
277
- compacted_item[al] = context.compact_iri(expanded_item['@id'], vocab: false)
278
- end
279
- if expanded_item.key?('@index')
280
- key = context.compact_iri('@index', vocab: true)
281
- compacted_item[key] = expanded_item['@index']
237
+ al = context.compact_iri('@list', vocab: true)
238
+ compacted_item = { al => compacted_item }
239
+ if expanded_item.key?('@index')
240
+ key = context.compact_iri('@index', vocab: true)
241
+ compacted_item[key] = expanded_item['@index']
242
+ end
282
243
  end
283
- add_value(nest_result, item_active_property, compacted_item,
284
- property_is_array: as_array)
285
244
  end
286
- elsif container.intersect?(CONTAINER_MAPPING_LANGUAGE_INDEX_ID_TYPE) && !container.include?('@graph')
287
- map_object = nest_result[item_active_property] ||= {}
288
- c = container.first
289
- container_key = context.compact_iri(c, vocab: true)
290
- compacted_item = case
291
- when container.include?('@id')
292
- map_key = compacted_item[container_key]
293
- compacted_item.delete(container_key)
294
- compacted_item
295
- when container.include?('@index')
296
- index_key = context.term_definitions[item_active_property].index || '@index'
297
- if index_key == '@index'
298
- map_key = expanded_item['@index']
299
- else
300
- index_key = context.expand_iri(index_key, vocab: true)
301
- container_key = context.compact_iri(index_key, vocab: true)
302
- map_key, *others = Array(compacted_item[container_key])
303
- if map_key.is_a?(String)
304
- case others.length
305
- when 0 then compacted_item.delete(container_key)
306
- when 1 then compacted_item[container_key] = others.first
307
- else compacted_item[container_key] = others
308
- end
245
+
246
+ # Graph object compaction cases:
247
+ if graph?(expanded_item)
248
+ if container.include?('@graph') &&
249
+ (container.include?('@id') || (container.include?('@index') && simple_graph?(expanded_item)))
250
+ # container includes @graph and @id
251
+ map_object = nest_result[item_active_property] ||= {}
252
+ # If there is no @id, create a blank node identifier to use as an index
253
+ map_key = if container.include?('@id') && expanded_item['@id']
254
+ context.compact_iri(expanded_item['@id'], base: @options[:base])
255
+ elsif container.include?('@index') && expanded_item['@index']
256
+ context.compact_iri(expanded_item['@index'], vocab: true)
309
257
  else
310
- map_key = context.compact_iri('@none', vocab: true)
258
+ context.compact_iri('@none', vocab: true)
311
259
  end
260
+ add_value(map_object, map_key, compacted_item,
261
+ property_is_array: as_array)
262
+ elsif container.include?('@graph') && simple_graph?(expanded_item)
263
+ # container includes @graph but not @id or @index and value is a simple graph object
264
+ if compacted_item.is_a?(Array) && compacted_item.length > 1
265
+ # Mutple objects in the same graph can't be represented directly, as they would be interpreted as two different graphs. Need to wrap in @included.
266
+ included_key = context.compact_iri('@included', vocab: true)
267
+ compacted_item = { included_key => compacted_item }
268
+ end
269
+ # Drop through, where compacted_item will be added
270
+ add_value(nest_result, item_active_property, compacted_item,
271
+ property_is_array: as_array)
272
+ else
273
+ # container does not include @graph or otherwise does not match one of the previous cases, redo compacted_item
274
+ al = context.compact_iri('@graph', vocab: true)
275
+ compacted_item = { al => compacted_item }
276
+ if expanded_item['@id']
277
+ al = context.compact_iri('@id', vocab: true)
278
+ compacted_item[al] = context.compact_iri(expanded_item['@id'], vocab: false)
279
+ end
280
+ if expanded_item.key?('@index')
281
+ key = context.compact_iri('@index', vocab: true)
282
+ compacted_item[key] = expanded_item['@index']
283
+ end
284
+ add_value(nest_result, item_active_property, compacted_item,
285
+ property_is_array: as_array)
312
286
  end
313
- # Note, if compacted_item is a node reference and key is @id-valued, then this could be compacted further.
314
- compacted_item
315
- when container.include?('@language')
316
- map_key = expanded_item['@language']
317
- value?(expanded_item) ? expanded_item['@value'] : compacted_item
318
- when container.include?('@type')
319
- map_key, *types = Array(compacted_item[container_key])
320
- case types.length
321
- when 0 then compacted_item.delete(container_key)
322
- when 1 then compacted_item[container_key] = types.first
323
- else compacted_item[container_key] = types
324
- end
287
+ elsif container.intersect?(CONTAINER_MAPPING_LANGUAGE_INDEX_ID_TYPE) && !container.include?('@graph')
288
+ map_object = nest_result[item_active_property] ||= {}
289
+ c = container.first
290
+ container_key = context.compact_iri(c, vocab: true)
291
+ compacted_item = if container.include?('@id')
292
+ map_key = compacted_item[container_key]
293
+ compacted_item.delete(container_key)
294
+ compacted_item
295
+ elsif container.include?('@index')
296
+ index_key = context.term_definitions[item_active_property].index || '@index'
297
+ if index_key == '@index'
298
+ map_key = expanded_item['@index']
299
+ else
300
+ index_key = context.expand_iri(index_key, vocab: true)
301
+ container_key = context.compact_iri(index_key, vocab: true)
302
+ map_key, *others = Array(compacted_item[container_key])
303
+ if map_key.is_a?(String)
304
+ case others.length
305
+ when 0 then compacted_item.delete(container_key)
306
+ when 1 then compacted_item[container_key] = others.first
307
+ else compacted_item[container_key] = others
308
+ end
309
+ else
310
+ map_key = context.compact_iri('@none', vocab: true)
311
+ end
312
+ end
313
+ # Note, if compacted_item is a node reference and key is @id-valued, then this could be compacted further.
314
+ compacted_item
315
+ elsif container.include?('@language')
316
+ map_key = expanded_item['@language']
317
+ value?(expanded_item) ? expanded_item['@value'] : compacted_item
318
+ elsif container.include?('@type')
319
+ map_key, *types = Array(compacted_item[container_key])
320
+ case types.length
321
+ when 0 then compacted_item.delete(container_key)
322
+ when 1 then compacted_item[container_key] = types.first
323
+ else compacted_item[container_key] = types
324
+ end
325
325
 
326
- # if compacted_item contains a single entry who's key maps to @id, then recompact the item without @type
327
- if compacted_item.keys.length == 1 && expanded_item.keys.include?('@id')
328
- compacted_item = compact({'@id' => expanded_item['@id']},
329
- base: base,
330
- property: item_active_property,
331
- log_depth: log_depth.to_i + 1)
326
+ # if compacted_item contains a single entry who's key maps to @id, then recompact the item without @type
327
+ if compacted_item.keys.length == 1 && expanded_item.key?('@id')
328
+ compacted_item = compact({ '@id' => expanded_item['@id'] },
329
+ base: base,
330
+ property: item_active_property,
331
+ log_depth: log_depth.to_i + 1)
332
+ end
333
+ compacted_item
332
334
  end
333
- compacted_item
335
+ map_key ||= context.compact_iri('@none', vocab: true)
336
+ add_value(map_object, map_key, compacted_item,
337
+ property_is_array: as_array)
338
+ else
339
+ add_value(nest_result, item_active_property, compacted_item,
340
+ property_is_array: as_array)
334
341
  end
335
- map_key ||= context.compact_iri('@none', vocab: true)
336
- add_value(map_object, map_key, compacted_item,
337
- property_is_array: as_array)
338
- else
339
- add_value(nest_result, item_active_property, compacted_item,
340
- property_is_array: as_array)
341
342
  end
342
343
  end
343
- end
344
344
 
345
- result
346
- else
347
- # For other types, the compacted value is the element value
348
- log_debug("compact", depth: log_depth.to_i) {element.class.to_s}
349
- element
345
+ result
346
+ else
347
+ # For other types, the compacted value is the element value
348
+ # log_debug("compact", depth: log_depth.to_i) {element.class.to_s}
349
+ element
350
+ end
351
+ ensure
352
+ self.context = input_context
350
353
  end
351
-
352
- ensure
353
- self.context = input_context
354
354
  end
355
355
  end
356
356
  end