json-ld 3.1.4 → 3.1.9

Sign up to get free protection for your applications and to get access to all the features.
data/lib/json/ld/frame.rb CHANGED
@@ -52,7 +52,7 @@ module JSON::LD
52
52
  state[:uniqueEmbeds][state[:graph]] ||= {}
53
53
  end
54
54
 
55
- if flags[:embed] == '@link' && link.has_key?(id)
55
+ if flags[:embed] == '@link' && link.key?(id)
56
56
  # add existing linked subject
57
57
  add_frame_output(parent, property, link[id])
58
58
  next
@@ -66,7 +66,7 @@ module JSON::LD
66
66
  warn "[DEPRECATION] #{flags[:embed]} is not a valid value of @embed in 1.1 mode.\n"
67
67
  end
68
68
 
69
- if !state[:embedded] && state[:uniqueEmbeds][state[:graph]].has_key?(id)
69
+ if !state[:embedded] && state[:uniqueEmbeds][state[:graph]].key?(id)
70
70
  # Skip adding this node object to the top-level, as it was included in another node object
71
71
  next
72
72
  elsif state[:embedded] &&
@@ -76,7 +76,7 @@ module JSON::LD
76
76
  next
77
77
  elsif state[:embedded] &&
78
78
  %w(@first @once).include?(flags[:embed]) &&
79
- state[:uniqueEmbeds][state[:graph]].has_key?(id)
79
+ state[:uniqueEmbeds][state[:graph]].key?(id)
80
80
 
81
81
  # if only the first match should be embedded
82
82
  # Embed unless already embedded
@@ -97,7 +97,7 @@ module JSON::LD
97
97
  state[:subjectStack] << {subject: subject, graph: state[:graph]}
98
98
 
99
99
  # Subject is also the name of a graph
100
- if state[:graphMap].has_key?(id)
100
+ if state[:graphMap].key?(id)
101
101
  # check frame's "@graph" to see what to do next
102
102
  # 1. if it doesn't exist and state.graph === "@merged", don't recurse
103
103
  # 2. if it doesn't exist and state.graph !== "@merged", recurse
@@ -105,7 +105,7 @@ module JSON::LD
105
105
  # 4. if "@default" then don't recurse
106
106
  # 5. recurse
107
107
  recurse, subframe = false, nil
108
- if !frame.has_key?('@graph')
108
+ if !frame.key?('@graph')
109
109
  recurse, subframe = (state[:graph] != '@merged'), {}
110
110
  else
111
111
  subframe = frame['@graph'].first
@@ -134,7 +134,7 @@ module JSON::LD
134
134
  end
135
135
 
136
136
  # explicit is on and property isn't in frame, skip processing
137
- next if flags[:explicit] && !frame.has_key?(prop)
137
+ next if flags[:explicit] && !frame.key?(prop)
138
138
 
139
139
  # add objects
140
140
  objects.each do |o|
@@ -267,7 +267,7 @@ module JSON::LD
267
267
  # If, after replacement, an array contains only the value null remove the value, leaving an empty array.
268
268
  input.map {|o| cleanup_preserve(o)}
269
269
  when Hash
270
- if input.has_key?('@preserve')
270
+ if input.key?('@preserve')
271
271
  # Replace with the content of `@preserve`
272
272
  cleanup_preserve(input['@preserve'].first)
273
273
  else
@@ -388,7 +388,7 @@ module JSON::LD
388
388
  is_empty = v.empty?
389
389
  if v = v.first
390
390
  validate_frame(v)
391
- has_default = v.has_key?('@default')
391
+ has_default = v.key?('@default')
392
392
  end
393
393
 
394
394
  # No longer a wildcard pattern if frame has any non-keyword properties
@@ -22,7 +22,6 @@ module JSON::LD
22
22
  referenced_once = {}
23
23
 
24
24
  value = nil
25
- ec = @context
26
25
 
27
26
  # Create an entry for compound-literal node detection
28
27
  compound_literal_subjects = {}
@@ -33,7 +32,7 @@ module JSON::LD
33
32
  dataset.each do |statement|
34
33
  #log_debug("statement") { statement.to_nquads.chomp}
35
34
 
36
- name = statement.graph_name ? ec.expand_iri(statement.graph_name, base: @options[:base]).to_s : '@default'
35
+ name = statement.graph_name ? @context.expand_iri(statement.graph_name, base: @options[:base]).to_s : '@default'
37
36
 
38
37
  # Create a graph entry as needed
39
38
  node_map = graph_map[name] ||= {}
@@ -41,17 +40,24 @@ module JSON::LD
41
40
 
42
41
  default_graph[name] ||= {'@id' => name} unless name == '@default'
43
42
 
44
- subject = ec.expand_iri(statement.subject, as_string: true, base: @options[:base])
45
- node = node_map[subject] ||= {'@id' => subject}
43
+ subject = statement.subject.statement? ?
44
+ resource_representation(statement.subject, useNativeTypes)['@id'].to_json_c14n :
45
+ statement.subject.to_s
46
+ node = node_map[subject] ||= resource_representation(statement.subject, useNativeTypes)
46
47
 
47
48
  # If predicate is rdf:datatype, note subject in compound literal subjects map
48
49
  if @options[:rdfDirection] == 'compound-literal' && statement.predicate == RDF.to_uri + 'direction'
49
50
  compound_literal_subjects[name][subject] ||= true
50
51
  end
51
52
 
52
- # If object is an IRI or blank node identifier, and node map does not have an object member, create one and initialize its value to a new JSON object consisting of a single member @id whose value is set to object.
53
- node_map[statement.object.to_s] ||= {'@id' => statement.object.to_s} unless
54
- statement.object.literal?
53
+ # If object is an IRI, blank node identifier, or statement, and node map does not have an object member, create one and initialize its value to a new JSON object consisting of a single member @id whose value is set to object.
54
+ unless statement.object.literal?
55
+ object = statement.object.statement? ?
56
+ resource_representation(statement.object, useNativeTypes)['@id'].to_json_c14n :
57
+ statement.object.to_s
58
+ node_map[object] ||=
59
+ resource_representation(statement.object, useNativeTypes)
60
+ end
55
61
 
56
62
  # If predicate equals rdf:type, and object is an IRI or blank node identifier, append object to the value of the @type member of node. If no such member exists, create one and initialize it to an array whose only item is object. Finally, continue to the next RDF triple.
57
63
  if statement.predicate == RDF.type && statement.object.resource? && !useRdfType
@@ -60,11 +66,7 @@ module JSON::LD
60
66
  end
61
67
 
62
68
  # Set value to the result of using the RDF to Object Conversion algorithm, passing object, rdfDirection, and use native types.
63
- value = ec.expand_value(nil,
64
- statement.object,
65
- rdfDirection: @options[:rdfDirection],
66
- useNativeTypes: useNativeTypes,
67
- base: @options[:base])
69
+ value = resource_representation(statement.object, useNativeTypes)
68
70
 
69
71
  merge_value(node, statement.predicate.to_s, value)
70
72
 
@@ -77,7 +79,7 @@ module JSON::LD
77
79
  property: statement.predicate.to_s,
78
80
  value: value
79
81
  })
80
- elsif referenced_once.has_key?(statement.object.to_s)
82
+ elsif referenced_once.key?(statement.object.to_s)
81
83
  referenced_once[statement.object.to_s] = false
82
84
  elsif statement.object.node?
83
85
  referenced_once[statement.object.to_s] = {
@@ -114,8 +116,7 @@ module JSON::LD
114
116
  end
115
117
  end
116
118
 
117
- # Skip to next graph, unless this one has lists
118
- next unless nil_var = graph_object[RDF.nil.to_s]
119
+ nil_var = graph_object.fetch(RDF.nil.to_s, {})
119
120
 
120
121
  # For each item usage in the usages member of nil, perform the following steps:
121
122
  nil_var.fetch(:usages, []).each do |usage|
@@ -143,12 +144,15 @@ module JSON::LD
143
144
  head['@list'] = list.reverse
144
145
  list_nodes.each {|node_id| graph_object.delete(node_id)}
145
146
  end
147
+
148
+ # Create annotations on graph object
149
+ create_annotations(graph_object)
146
150
  end
147
151
 
148
152
  result = []
149
153
  default_graph.keys.opt_sort(ordered: @options[:ordered]).each do |subject|
150
154
  node = default_graph[subject]
151
- if graph_map.has_key?(subject)
155
+ if graph_map.key?(subject)
152
156
  node['@graph'] = []
153
157
  graph_map[subject].keys.opt_sort(ordered: @options[:ordered]).each do |s|
154
158
  n = graph_map[subject][s]
@@ -162,5 +166,31 @@ module JSON::LD
162
166
  #log_debug("fromRdf") {result.to_json(JSON_STATE) rescue 'malformed json'}
163
167
  result
164
168
  end
169
+
170
+ private
171
+ def resource_representation(resource, useNativeTypes)
172
+ case resource
173
+ when RDF::Statement
174
+ # Note, if either subject or object are a BNode which is used elsewhere,
175
+ # this might not work will with the BNode accounting from above.
176
+ rep = {'@id' => resource_representation(resource.subject, false)}
177
+ if resource.predicate == RDF.type
178
+ rep['@id'].merge!('@type' => resource.object.to_s)
179
+ else
180
+ rep['@id'].merge!(
181
+ resource.predicate.to_s =>
182
+ as_array(resource_representation(resource.object, useNativeTypes)))
183
+ end
184
+ rep
185
+ when RDF::Literal
186
+ @context.expand_value(nil,
187
+ resource,
188
+ rdfDirection: @options[:rdfDirection],
189
+ useNativeTypes: useNativeTypes,
190
+ base: @options[:base])
191
+ else
192
+ {'@id' => resource.to_s}
193
+ end
194
+ end
165
195
  end
166
196
  end
@@ -20,7 +20,7 @@ module JSON::LD
20
20
  control: :url2,
21
21
  datatype: RDF::URI,
22
22
  on: ["--expand-context CONTEXT"],
23
- description: "Context to use when expanding.") {|arg| RDF::URI(arg)},
23
+ description: "Context to use when expanding.") {|arg| RDF::URI(arg).absolute? ? RDF::URI(arg) : StringIO.new(File.read(arg))},
24
24
  RDF::CLI::Option.new(
25
25
  symbol: :extractAllScripts,
26
26
  datatype: TrueClass,
@@ -68,6 +68,7 @@ module JSON::LD
68
68
  # @raise [RDF::ReaderError] if the JSON document cannot be loaded
69
69
  def initialize(input = $stdin, **options, &block)
70
70
  options[:base_uri] ||= options[:base]
71
+ options[:rename_bnodes] = false unless options.key?(:rename_bnodes)
71
72
  super do
72
73
  @options[:base] ||= base_uri.to_s if base_uri
73
74
  # Trim non-JSON stuff in script.
@@ -136,7 +136,7 @@ module JSON::LD
136
136
  when '@type'
137
137
  # Set the type-scoped context to the context on input, for use later
138
138
  raise JsonLdError::InvalidStreamingKeyOrder,
139
- "found #{key} in state #{state}" unless [:await_context, :await_type].include?(state)
139
+ "found #{key} in state #{state}" unless %i(await_context await_type).include?(state)
140
140
 
141
141
  type_scoped_context = context
142
142
  as_array(value).sort.each do |term|
@@ -159,7 +159,7 @@ module JSON::LD
159
159
  raise JsonLdError::InvalidSetOrListObject,
160
160
  "found #{key} in state #{state}" if is_list_or_set
161
161
  raise JsonLdError::CollidingKeywords,
162
- "found #{key} in state #{state}" unless [:await_context, :await_type, :await_id].include?(state)
162
+ "found #{key} in state #{state}" unless %i(await_context await_type await_id).include?(state)
163
163
 
164
164
  # Set our actual id, and use for replacing any provisional statements using our existing node_id, which is provisional
165
165
  raise JsonLdError::InvalidIdValue,
@@ -209,7 +209,7 @@ module JSON::LD
209
209
  # Expanded values must be node objects
210
210
  have_statements = false
211
211
  parse_object(value, active_property, context) do |st|
212
- have_statements ||= st.has_subject?
212
+ have_statements ||= st.subject?
213
213
  block.call(st)
214
214
  end
215
215
  raise JsonLdError::InvalidIncludedValue, "values of @included must expand to node objects" unless have_statements
@@ -232,7 +232,7 @@ module JSON::LD
232
232
  when '@list'
233
233
  raise JsonLdError::InvalidSetOrListObject,
234
234
  "found #{key} in state #{state}" if
235
- ![:await_context, :await_type, :await_id].include?(state)
235
+ !%i(await_context await_type await_id).include?(state)
236
236
  is_list_or_set = true
237
237
  if subject
238
238
  node_id = parse_list(value, active_property, context, &block)
@@ -277,7 +277,7 @@ module JSON::LD
277
277
  when '@set'
278
278
  raise JsonLdError::InvalidSetOrListObject,
279
279
  "found #{key} in state #{state}" if
280
- ![:await_context, :await_type, :await_id].include?(state)
280
+ !%i(await_context await_type await_id).include?(state)
281
281
  is_list_or_set = true
282
282
  value = as_array(value).compact
283
283
  parse_object(value, active_property, context, subject: subject, predicate: predicate, &block)
@@ -64,8 +64,8 @@ module JSON::LD
64
64
  {"@value" => MultiJson.load(statement.object.to_s), "@type" => "@json"}
65
65
  else
66
66
  lit = {"@value" => statement.object.to_s}
67
- lit["@type"] = statement.object.datatype.to_s if statement.object.has_datatype?
68
- lit["@language"] = statement.object.language.to_s if statement.object.has_language?
67
+ lit["@type"] = statement.object.datatype.to_s if statement.object.datatype?
68
+ lit["@language"] = statement.object.language.to_s if statement.object.language?
69
69
  lit
70
70
  end
71
71
  end
@@ -91,7 +91,7 @@ module JSON::LD
91
91
  def start_graph(resource)
92
92
  #log_debug("start_graph") {"state: #{@state.inspect}, resource: #{resource}"}
93
93
  if resource
94
- @output.puts(",") if [:wrote_node, :wrote_graph].include?(@state)
94
+ @output.puts(",") if %i(wrote_node wrote_graph).include?(@state)
95
95
  @output.puts %({"@id": "#{resource}", "@graph": [)
96
96
  @state = :in_graph
97
97
  end
@@ -109,7 +109,7 @@ module JSON::LD
109
109
 
110
110
  def end_node
111
111
  #log_debug("end_node") {"state: #{@state.inspect}, node: #{@current_node_def.to_json}"}
112
- @output.puts(",") if [:wrote_node, :wrote_graph].include?(@state)
112
+ @output.puts(",") if %i(wrote_node wrote_graph).include?(@state)
113
113
  if @current_node_def
114
114
  node_def = if context
115
115
  compacted = JSON::LD::API.compact(@current_node_def, context, rename_bnodes: false, **@options)
@@ -16,6 +16,8 @@ module JSON::LD
16
16
  # @return RDF::Resource the subject of this item
17
17
  def item_to_rdf(item, graph_name: nil, &block)
18
18
  # Just return value object as Term
19
+ return unless item
20
+
19
21
  if value?(item)
20
22
  value, datatype = item.fetch('@value'), item.fetch('@type', nil)
21
23
 
@@ -46,7 +48,7 @@ module JSON::LD
46
48
  # Only valid for rdf:JSON
47
49
  value = value.to_json_c14n
48
50
  else
49
- if item.has_key?('@direction') && @options[:rdfDirection]
51
+ if item.key?('@direction') && @options[:rdfDirection]
50
52
  # Either serialize using a datatype, or a compound-literal
51
53
  case @options[:rdfDirection]
52
54
  when 'i18n-datatype'
@@ -61,7 +63,7 @@ module JSON::LD
61
63
  end
62
64
 
63
65
  # Otherwise, if datatype is null, set it to xsd:string or xsd:langString, depending on if item has a @language key.
64
- datatype ||= item.has_key?('@language') ? RDF.langString : RDF::XSD.string
66
+ datatype ||= item.key?('@language') ? RDF.langString : RDF::XSD.string
65
67
  if datatype == RDF::URI(RDF.to_uri + "JSON")
66
68
  value = value.to_json_c14n
67
69
  end
@@ -76,11 +78,13 @@ module JSON::LD
76
78
  return parse_list(item['@list'], graph_name: graph_name, &block)
77
79
  end
78
80
 
79
- # Skip if '@id' is nil
80
- subject = if item.has_key?('@id')
81
- item['@id'].nil? ? nil : as_resource(item['@id'])
82
- else
83
- node
81
+ subject = case item['@id']
82
+ when nil then node
83
+ when String then as_resource(item['@id'])
84
+ when Object
85
+ # Embedded statement
86
+ # (No error checking, as this is done in expansion)
87
+ to_enum(:item_to_rdf, item['@id']).to_a.first
84
88
  end
85
89
 
86
90
  #log_debug("item_to_rdf") {"subject: #{subject.to_ntriples rescue 'malformed rdf'}"}
data/lib/json/ld/utils.rb CHANGED
@@ -11,8 +11,8 @@ module JSON::LD
11
11
  # @return [Boolean]
12
12
  def node?(value)
13
13
  value.is_a?(Hash) &&
14
- !(value.has_key?('@value') || value.has_key?('@list') || value.has_key?('@set')) &&
15
- (value.length > 1 || !value.has_key?('@id'))
14
+ !(value.key?('@value') || value.key?('@list') || value.key?('@set')) &&
15
+ (value.length > 1 || !value.key?('@id'))
16
16
  end
17
17
 
18
18
  ##
@@ -29,7 +29,7 @@ module JSON::LD
29
29
  # @return [Boolean]
30
30
  def node_or_ref?(value)
31
31
  value.is_a?(Hash) &&
32
- !(value.has_key?('@value') || value.has_key?('@list') || value.has_key?('@set'))
32
+ !(value.key?('@value') || value.key?('@list') || value.key?('@set'))
33
33
  end
34
34
 
35
35
  ##
@@ -66,7 +66,7 @@ module JSON::LD
66
66
  # @param [Object] value
67
67
  # @return [Boolean]
68
68
  def simple_graph?(value)
69
- graph?(value) && !value.has_key?('@id')
69
+ graph?(value) && !value.key?('@id')
70
70
  end
71
71
 
72
72
  ##
@@ -75,7 +75,7 @@ module JSON::LD
75
75
  # @param [Object] value
76
76
  # @return [Boolean]
77
77
  def list?(value)
78
- value.is_a?(Hash) && value.has_key?('@list')
78
+ value.is_a?(Hash) && value.key?('@list')
79
79
  end
80
80
 
81
81
  ##
@@ -84,7 +84,7 @@ module JSON::LD
84
84
  # @param [Object] value
85
85
  # @return [Boolean]
86
86
  def index?(value)
87
- value.is_a?(Hash) && value.has_key?('@index')
87
+ value.is_a?(Hash) && value.key?('@index')
88
88
  end
89
89
 
90
90
  ##
@@ -93,7 +93,7 @@ module JSON::LD
93
93
  # @param [Object] value
94
94
  # @return [Boolean]
95
95
  def value?(value)
96
- value.is_a?(Hash) && value.has_key?('@value')
96
+ value.is_a?(Hash) && value.key?('@value')
97
97
  end
98
98
 
99
99
  ##
@@ -170,7 +170,7 @@ module JSON::LD
170
170
  end
171
171
  elsif subject[property]
172
172
  # check if subject already has value if duplicates not allowed
173
- _has_value = !allow_duplicate && has_value(subject, property, value)
173
+ _has_value = !allow_duplicate && has_value?(subject, property, value)
174
174
 
175
175
  # make property an array if value not present or always an array
176
176
  if !subject[property].is_a?(Array) && (!_has_value || property_is_array)
@@ -188,7 +188,7 @@ module JSON::LD
188
188
  # @param property the property to look for.
189
189
  #
190
190
  # @return [Boolean] true if the subject has the given property, false if not.
191
- def has_property(subject, property)
191
+ def property?(subject, property)
192
192
  return false unless value = subject[property]
193
193
  !value.is_a?(Array) || !value.empty?
194
194
  end
@@ -200,8 +200,8 @@ module JSON::LD
200
200
  # @param [Object] value the value to check.
201
201
  #
202
202
  # @return [Boolean] true if the value exists, false if not.
203
- def has_value(subject, property, value)
204
- if has_property(subject, property)
203
+ def has_value?(subject, property, value)
204
+ if property?(subject, property)
205
205
  val = subject[property]
206
206
  is_list = list?(val)
207
207
  if val.is_a?(Array) || is_list
@@ -265,7 +265,7 @@ module JSON::LD
265
265
  # @return [String]
266
266
  def get_sym(old = "")
267
267
  old = old.to_s.sub(/_:/, '')
268
- if old && self.has_key?(old)
268
+ if old && self.key?(old)
269
269
  self[old]
270
270
  elsif !old.empty?
271
271
  self[old] = RDF::Node.new.to_unique_base[2..-1]
@@ -289,7 +289,7 @@ module JSON::LD
289
289
  # @return [String]
290
290
  def get_sym(old = "")
291
291
  old = old.to_s.sub(/_:/, '')
292
- if !old.empty? && self.has_key?(old)
292
+ if !old.empty? && self.key?(old)
293
293
  self[old]
294
294
  elsif !old.empty?
295
295
  @num += 1
@@ -93,7 +93,7 @@ module JSON::LD
93
93
  datatype: RDF::URI,
94
94
  control: :url2,
95
95
  on: ["--context CONTEXT"],
96
- description: "Context to use when compacting.") {|arg| RDF::URI(arg)},
96
+ description: "Context to use when compacting.") {|arg| RDF::URI(arg).absolute? ? RDF::URI(arg) : StringIO.new(File.read(arg))},
97
97
  RDF::CLI::Option.new(
98
98
  symbol: :embed,
99
99
  datatype: %w(@always @once @never),
@@ -107,6 +107,13 @@ module JSON::LD
107
107
  control: :checkbox,
108
108
  on: ["--[no-]explicit"],
109
109
  description: "Only include explicitly declared properties in output (false)") {|arg| arg},
110
+ RDF::CLI::Option.new(
111
+ symbol: :frame,
112
+ datatype: RDF::URI,
113
+ control: :url2,
114
+ use: :required,
115
+ on: ["--frame FRAME"],
116
+ description: "Frame to use when serializing.") {|arg| RDF::URI(arg).absolute? ? RDF::URI(arg) : StringIO.new(File.read(arg))},
110
117
  RDF::CLI::Option.new(
111
118
  symbol: :lowercaseLanguage,
112
119
  datatype: TrueClass,
@@ -137,7 +144,7 @@ module JSON::LD
137
144
  default: 'null',
138
145
  control: :select,
139
146
  on: ["--rdf-direction DIR", %w(i18n-datatype compound-literal)],
140
- description: "How to serialize literal direction (i18n-datatype compound-literal)") {|arg| RDF::URI(arg)},
147
+ description: "How to serialize literal direction (i18n-datatype compound-literal)") {|arg| arg},
141
148
  RDF::CLI::Option.new(
142
149
  symbol: :requireAll,
143
150
  datatype: TrueClass,
@@ -202,7 +209,7 @@ module JSON::LD
202
209
  end
203
210
 
204
211
  ##
205
- # Initializes the RDF-LD writer instance.
212
+ # Initializes the JSON-LD writer instance.
206
213
  #
207
214
  # @param [IO, File] output
208
215
  # the output stream
@@ -230,8 +237,8 @@ module JSON::LD
230
237
  # @yield [writer]
231
238
  # @yieldparam [RDF::Writer] writer
232
239
  def initialize(output = $stdout, **options, &block)
233
- options[:base_uri] ||= options[:base] if options.has_key?(:base)
234
- options[:base] ||= options[:base_uri] if options.has_key?(:base_uri)
240
+ options[:base_uri] ||= options[:base] if options.key?(:base)
241
+ options[:base] ||= options[:base_uri] if options.key?(:base_uri)
235
242
  super do
236
243
  @repo = RDF::Repository.new
237
244