json-ld 3.2.3 → 3.2.5

Sign up to get free protection for your applications and to get access to all the features.
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