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.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/lib/json/ld/api.rb +807 -764
- data/lib/json/ld/compact.rb +304 -304
- data/lib/json/ld/conneg.rb +179 -161
- data/lib/json/ld/context.rb +2080 -1945
- data/lib/json/ld/expand.rb +745 -666
- data/lib/json/ld/extensions.rb +14 -13
- data/lib/json/ld/flatten.rb +257 -247
- data/lib/json/ld/format.rb +202 -194
- data/lib/json/ld/frame.rb +525 -502
- data/lib/json/ld/from_rdf.rb +224 -166
- data/lib/json/ld/html/nokogiri.rb +123 -121
- data/lib/json/ld/html/rexml.rb +151 -147
- data/lib/json/ld/reader.rb +107 -100
- data/lib/json/ld/resource.rb +224 -205
- data/lib/json/ld/streaming_reader.rb +574 -507
- data/lib/json/ld/streaming_writer.rb +93 -92
- data/lib/json/ld/to_rdf.rb +171 -167
- data/lib/json/ld/utils.rb +270 -264
- data/lib/json/ld/version.rb +24 -14
- data/lib/json/ld/writer.rb +334 -311
- data/lib/json/ld.rb +103 -96
- metadata +78 -209
- data/spec/api_spec.rb +0 -132
- data/spec/compact_spec.rb +0 -3482
- data/spec/conneg_spec.rb +0 -373
- data/spec/context_spec.rb +0 -2036
- data/spec/expand_spec.rb +0 -4496
- data/spec/flatten_spec.rb +0 -1203
- data/spec/format_spec.rb +0 -115
- data/spec/frame_spec.rb +0 -2498
- data/spec/from_rdf_spec.rb +0 -1005
- data/spec/matchers.rb +0 -20
- data/spec/rdfstar_spec.rb +0 -25
- data/spec/reader_spec.rb +0 -883
- data/spec/resource_spec.rb +0 -76
- data/spec/spec_helper.rb +0 -281
- data/spec/streaming_reader_spec.rb +0 -237
- data/spec/streaming_writer_spec.rb +0 -145
- data/spec/suite_compact_spec.rb +0 -22
- data/spec/suite_expand_spec.rb +0 -36
- data/spec/suite_flatten_spec.rb +0 -34
- data/spec/suite_frame_spec.rb +0 -29
- data/spec/suite_from_rdf_spec.rb +0 -22
- data/spec/suite_helper.rb +0 -411
- data/spec/suite_html_spec.rb +0 -22
- data/spec/suite_http_spec.rb +0 -35
- data/spec/suite_remote_doc_spec.rb +0 -22
- data/spec/suite_to_rdf_spec.rb +0 -30
- data/spec/support/extensions.rb +0 -44
- data/spec/test-files/test-1-compacted.jsonld +0 -10
- data/spec/test-files/test-1-context.jsonld +0 -7
- data/spec/test-files/test-1-expanded.jsonld +0 -5
- data/spec/test-files/test-1-input.jsonld +0 -10
- data/spec/test-files/test-1-rdf.ttl +0 -8
- data/spec/test-files/test-2-compacted.jsonld +0 -20
- data/spec/test-files/test-2-context.jsonld +0 -7
- data/spec/test-files/test-2-expanded.jsonld +0 -16
- data/spec/test-files/test-2-input.jsonld +0 -20
- data/spec/test-files/test-2-rdf.ttl +0 -14
- data/spec/test-files/test-3-compacted.jsonld +0 -11
- data/spec/test-files/test-3-context.jsonld +0 -8
- data/spec/test-files/test-3-expanded.jsonld +0 -10
- data/spec/test-files/test-3-input.jsonld +0 -11
- data/spec/test-files/test-3-rdf.ttl +0 -8
- data/spec/test-files/test-4-compacted.jsonld +0 -10
- data/spec/test-files/test-4-context.jsonld +0 -7
- data/spec/test-files/test-4-expanded.jsonld +0 -6
- data/spec/test-files/test-4-input.jsonld +0 -10
- data/spec/test-files/test-4-rdf.ttl +0 -5
- data/spec/test-files/test-5-compacted.jsonld +0 -13
- data/spec/test-files/test-5-context.jsonld +0 -7
- data/spec/test-files/test-5-expanded.jsonld +0 -9
- data/spec/test-files/test-5-input.jsonld +0 -13
- data/spec/test-files/test-5-rdf.ttl +0 -7
- data/spec/test-files/test-6-compacted.jsonld +0 -10
- data/spec/test-files/test-6-context.jsonld +0 -7
- data/spec/test-files/test-6-expanded.jsonld +0 -10
- data/spec/test-files/test-6-input.jsonld +0 -10
- data/spec/test-files/test-6-rdf.ttl +0 -6
- data/spec/test-files/test-7-compacted.jsonld +0 -23
- data/spec/test-files/test-7-context.jsonld +0 -4
- data/spec/test-files/test-7-expanded.jsonld +0 -20
- data/spec/test-files/test-7-input.jsonld +0 -23
- data/spec/test-files/test-7-rdf.ttl +0 -14
- data/spec/test-files/test-8-compacted.jsonld +0 -34
- data/spec/test-files/test-8-context.jsonld +0 -11
- data/spec/test-files/test-8-expanded.jsonld +0 -24
- data/spec/test-files/test-8-frame.jsonld +0 -18
- data/spec/test-files/test-8-framed.jsonld +0 -25
- data/spec/test-files/test-8-input.jsonld +0 -30
- data/spec/test-files/test-8-rdf.ttl +0 -15
- data/spec/test-files/test-9-compacted.jsonld +0 -20
- data/spec/test-files/test-9-context.jsonld +0 -13
- data/spec/test-files/test-9-expanded.jsonld +0 -14
- data/spec/test-files/test-9-input.jsonld +0 -12
- data/spec/to_rdf_spec.rb +0 -1551
- data/spec/writer_spec.rb +0 -427
data/lib/json/ld/compact.rb
CHANGED
@@ -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
|
-
|
51
|
-
|
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
|
-
|
54
|
-
|
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
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
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
|
-
|
68
|
-
|
69
|
-
if !
|
70
|
-
|
71
|
-
|
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
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
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
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
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
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
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
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
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
|
-
|
120
|
-
|
121
|
-
|
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
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
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
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
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
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
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
|
-
|
163
|
-
|
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
|
-
|
182
|
-
|
183
|
-
|
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
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
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
|
-
|
215
|
-
|
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
|
-
|
218
|
-
|
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
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
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
|
-
|
240
|
-
value_is_array: true, allow_duplicate: true)
|
241
|
-
next
|
221
|
+
expanded_item
|
242
222
|
end
|
243
|
-
end
|
244
223
|
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
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('@
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
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
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
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
|
-
|
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
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
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
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
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
|
-
|
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
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
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
|