json-ld 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -24,7 +24,7 @@ Full documentation available on [RubyDoc](http://rubydoc.info/gems/json-ld/0.0.4
24
24
 
25
25
  ##Dependencies
26
26
  * [Ruby](http://ruby-lang.org/) (>= 1.8.7) or (>= 1.8.1 with [Backports][])
27
- * [RDF.rb](http://rubygems.org/gems/rdf) (>= 0.3.3)
27
+ * [RDF.rb](http://rubygems.org/gems/rdf) (>= 0.3.4)
28
28
  * [JSON](https://rubygems.org/gems/json) (>= 1.5.1)
29
29
 
30
30
  ## Installation
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.7
1
+ 0.0.8
@@ -23,35 +23,24 @@ module JSON
23
23
  require 'json'
24
24
  require 'json/ld/extensions'
25
25
  require 'json/ld/format'
26
- autoload :Reader, 'json/ld/reader'
27
- autoload :VERSION, 'json/ld/version'
28
- autoload :Writer, 'json/ld/writer'
29
-
30
- # Keywords
31
- BASE = '@base'.freeze
32
- COERCE = '@coerce'.freeze
33
- CONTEXT = '@context'.freeze
34
- DATATYPE = '@datatype'.freeze
35
- IRI = '@iri'.freeze
36
- LANGUAGE = '@language'.freeze
37
- LITERAL = '@literal'.freeze
38
- SUBJECT = '@subject'.freeze
39
- TYPE = '@type'.freeze
40
- VOCAB = '@vocab'.freeze
26
+ autoload :Normalize, 'json/ld/normalize'
27
+ autoload :Reader, 'json/ld/reader'
28
+ autoload :VERSION, 'json/ld/version'
29
+ autoload :Writer, 'json/ld/writer'
41
30
 
42
31
  # Default context
43
32
  # @see http://json-ld.org/spec/ED/20110507/#the-default-context
44
33
  DEFAULT_CONTEXT = {
45
34
  '@coerce' => {
46
- IRI => [TYPE]
35
+ '@iri' => ['@type']
47
36
  }
48
37
  }.freeze
49
38
 
50
39
  # Default type coercion, in property => datatype order
51
40
  DEFAULT_COERCE = {
52
- TYPE => IRI,
41
+ '@type' => '@iri',
53
42
  RDF.first.to_s => false, # Make sure @coerce isn't generated for this
54
- RDF.rest.to_s => IRI,
43
+ RDF.rest.to_s => '@iri',
55
44
  }.freeze
56
45
 
57
46
  def self.debug?; @debug; end
@@ -21,13 +21,32 @@ module JSON::LD
21
21
  #
22
22
  # @see http://www.w3.org/TR/rdf-testcases/#ntriples
23
23
  class Format < RDF::Format
24
- content_type 'application/ld+json', :extension => :json
25
- content_type 'application/ld+json', :extension => :ld
26
- content_type 'application/x-ld+json'
24
+ content_type 'application/ld+json',
25
+ :extensions => [:jsonld, :json, :ld],
26
+ :alias => 'application/x-ld+json'
27
27
  content_encoding 'utf-8'
28
28
 
29
29
  reader { JSON::LD::Reader }
30
30
  writer { JSON::LD::Writer }
31
+
32
+ ##
33
+ # Sample detection to see if it matches JSON-LD
34
+ #
35
+ # Use a text sample to detect the format of an input file. Sub-classes implement
36
+ # a matcher sufficient to detect probably format matches, including disambiguating
37
+ # between other similar formats.
38
+ #
39
+ # @param [String] sample Beginning several bytes (~ 1K) of input.
40
+ # @return [Boolean]
41
+ def self.detect(sample)
42
+ !!sample.match(/\{\s*"@(subject|context|type|iri)"/m)
43
+ end
44
+
45
+ ##
46
+ # Override normal symbol generation
47
+ def self.to_sym
48
+ :jsonld
49
+ end
31
50
  end
32
51
 
33
52
  # Alias for JSON-LD format
@@ -39,7 +58,6 @@ module JSON::LD
39
58
  # RDF::Format.for(:jsonld).reader #=> JSON::LD::Reader
40
59
  # RDF::Format.for(:jsonld).writer #=> JSON::LD::Writer
41
60
  class JSONLD < RDF::Format
42
- content_type 'application/ld+json', :extension => :jsonld
43
61
  content_encoding 'utf-8'
44
62
 
45
63
  reader { JSON::LD::Reader }
@@ -0,0 +1,120 @@
1
+ module JSON::LD
2
+ ##
3
+ # Normalize Nodes in a graph. Uses [Normalization Algorithm](http://json-ld.org/spec/latest/#normalization-1)
4
+ # from [JSON-LD specification](http://json-ld.org/spec/latest/).
5
+ #
6
+ # This module takes a graph and returns a new graph, with BNode names normalized to allow
7
+ # for a canonical ordering of all statements within a graph.
8
+ #
9
+ # @example Normalize a graph
10
+ # JSON::LD::normalize(graph) => graph
11
+ #
12
+ # @see http://json-ld.org/spec/latest
13
+ # @see http://json-ld.org/spec/latest/#normalization-1
14
+ # @author [Gregg Kellogg](http://greggkellogg.net/)
15
+ class Normalize
16
+ ##
17
+ # Create a new normalization instance
18
+ # @param [RDF::Enumerable] graph
19
+ def initialize(graph)
20
+ @graph = graph
21
+ end
22
+
23
+ ##
24
+ # Perform normalization, and return a new graph with node identifiers normalized
25
+ # @return [RDF::Graph]
26
+ def normalize
27
+ # Create an empty list of expanded nodes and recursively process every object in the expanded input that is not an
28
+ # expanded IRI, typed literal or language literal
29
+ nodes = graph.subjects.select {|s| s.node?}
30
+
31
+ forward_mapping = {}
32
+ reverse_mapping = {}
33
+ @node_properties = {}
34
+ graph.each_statment do |st|
35
+ # Create a forward mapping that relates graph nodes to the IRIs of the targets nodes that they reference. For example,
36
+ # if a node alpha refers to a node beta via a property, the key in the forward mapping is the subject IRI of alpha and
37
+ # the value is an array containing at least the subject IRI of beta.
38
+ if st.subject.node? && st.object.uri?
39
+ forward_mapping[st.subject] ||= {}
40
+ forward_mapping[st.subject] << st.object
41
+ end
42
+
43
+ # Create a reverse mapping that relates graph nodes to every other node that refers to them in the graph. For example,
44
+ # if a node alpha refers to a node beta via a property, the key in the reverse mapping is the subject IRI for beta and
45
+ # the value is an array containing at least the IRI for alpha.
46
+ if st.object.node? && st.subject.uri?
47
+ reverse_mapping[st.object] ||= {}
48
+ reverse_mapping[st.object] << st.subject
49
+ end
50
+
51
+ # For node comparisons, keep track of properties of each node
52
+ if st.subject.node?
53
+ @node_properties[st.subject] ||= {}
54
+ @node_properties[st.subject][st.predicate] ||= []
55
+ @node_properties[st.subject][st.predicate] << st.object
56
+ end
57
+ end
58
+
59
+ # Label every unlabeled node according to the Label Generation Algorithm in descending order using the Deep
60
+ # Comparison Algorithm to determine the sort order.
61
+ node_mapping = {}
62
+ gen = "c14n_1"
63
+ nodes.sort {|a, b| deep_comparison(a) <=> deep_comparison(b) }.each do |node|
64
+ # name with Label Generation Algorithm and create mapping from original node to new name
65
+ node_mapping[node] = RDF::Node.new(gen)
66
+ gen = gen.succ
67
+ end
68
+
69
+ # Add statements to new graph using new node names
70
+ graph = RDF::Graph.new
71
+
72
+ @graph.each_statement do |st|
73
+ if st.subject.node? || st.object.node?
74
+ st = st.dup
75
+ st.subject = node_mapping.fetch(st.subject, st.subject)
76
+ st.object = node_mapping.fetch(st.object, st.object)
77
+ end
78
+ graph << st
79
+ end
80
+
81
+ # Return new graph
82
+ graph
83
+ end
84
+
85
+ private
86
+ def shallow_comparison(a, b)
87
+ # 1. Compare the total number of node properties. The node with fewer properties is first.
88
+ prop_count_a = @node_properties[a].keys.length
89
+ prop_count_b = @node_properties[b].keys.length
90
+ return prop_count_a <=> prop_count_b unless prop_count_a == prop_count_b
91
+
92
+ # 2. Lexicographically sort the property IRIs for each node and compare the sorted lists. If an IRI is found to be
93
+ # lexicographically smaller, the node containing that IRI is first.
94
+ p_iri_a = @node_properties[a].keys.map(&:to_s).sort.first
95
+ p_iri_b = @node_properties[a].keys.map(&:to_s).sort.first
96
+ return p_iri_a <=> p_iri_b unless p_iri_a == p_iri_b
97
+
98
+ # 3. Compare the property values against one another:
99
+ @node_properties
100
+ alpha_list
101
+ end
102
+
103
+ def deep_comparison(a, b)
104
+ comp = shallow_comparison(a, b)
105
+ if comp == 0
106
+ end
107
+ comp
108
+ end
109
+ end
110
+
111
+ ##
112
+ # Normalize a graph, returning a new graph with node names normalized
113
+ def normalize(graph)
114
+ norm = Normalize.new
115
+ norm.normalize
116
+ end
117
+ module_meathod :normalize
118
+
119
+ end
120
+
@@ -38,7 +38,7 @@ module JSON::LD
38
38
 
39
39
  # A list of current, in-scope URI mappings.
40
40
  #
41
- # @attr [Hash{Symbol => String}]
41
+ # @attr [Hash{String => String}]
42
42
  attr :mappings, true
43
43
 
44
44
  # The default vocabulary
@@ -60,8 +60,15 @@ module JSON::LD
60
60
  #
61
61
  # As the value may be an array, this is maintained as a reverse mapping of `property` => `type`.
62
62
  #
63
- # @attr [Hash{RDF::URI => RDF::URI}]
64
- attr :coerce, true
63
+ # @attr [Hash{String => String}]
64
+ attr :coerce
65
+
66
+ # List coercion
67
+ #
68
+ # The @list keyword is used to specify that properties having an array value are to be treated
69
+ # as an ordered list, rather than a normal unordered list
70
+ # @attr [Array<String>]
71
+ attr :list
65
72
 
66
73
  ##
67
74
  # Create new evaluation context
@@ -73,6 +80,7 @@ module JSON::LD
73
80
  @mappings = {}
74
81
  @vocab = nil
75
82
  @coerce = {}
83
+ @list = []
76
84
  yield(self) if block_given?
77
85
  end
78
86
 
@@ -80,6 +88,7 @@ module JSON::LD
80
88
  v = %w([EvaluationContext) + %w(base vocab).map {|a| "#{a}='#{self.send(a).inspect}'"}
81
89
  v << "mappings[#{mappings.keys.length}]=#{mappings}"
82
90
  v << "coerce[#{coerce.keys.length}]=#{coerce}"
91
+ v << "list[#{list.length}]=#{list}"
83
92
  v.join(", ") + "]"
84
93
  end
85
94
  end
@@ -100,7 +109,8 @@ module JSON::LD
100
109
  begin
101
110
  @doc = JSON.load(input)
102
111
  rescue JSON::ParserError => e
103
- raise RDF::ReaderError, "Failed to parse input document: #{e.message}"
112
+ raise RDF::ReaderError, "Failed to parse input document: #{e.message}" if validate?
113
+ @doc = JSON.parse("{}")
104
114
  end
105
115
 
106
116
  if block_given?
@@ -119,9 +129,9 @@ module JSON::LD
119
129
  @callback = block
120
130
 
121
131
  # initialize the evaluation context with the appropriate base
122
- ec = EvaluationContext.new do |ec|
123
- ec.base = @base_uri if @base_uri
124
- parse_context(ec, DEFAULT_CONTEXT)
132
+ ec = EvaluationContext.new do |e|
133
+ e.base = @base_uri if @base_uri
134
+ parse_context(e, DEFAULT_CONTEXT)
125
135
  end
126
136
 
127
137
  traverse("", @doc, nil, nil, ec)
@@ -150,7 +160,7 @@ module JSON::LD
150
160
  # @param [EvaluationContext] ec
151
161
  # The active context
152
162
  def traverse(path, element, subject, property, ec)
153
- add_debug(path, "traverse: s=#{subject.inspect}, p=#{property.inspect}, e=#{ec.inspect}")
163
+ add_debug(path) {"traverse: s=#{subject.inspect}, p=#{property.inspect}, e=#{ec.inspect}"}
154
164
  object = nil
155
165
 
156
166
  case element
@@ -161,119 +171,105 @@ module JSON::LD
161
171
 
162
172
  # 2.1) If a @context keyword is found, the processor merges each key-value pair in
163
173
  # the local context into the active context ...
164
- if element[CONTEXT]
174
+ if element['@context']
165
175
  # Merge context
166
- ec = parse_context(ec.dup, element[CONTEXT])
176
+ ec = parse_context(ec.dup, element['@context'])
167
177
  prefixes.merge!(ec.mappings) # Update parsed prefixes
168
178
  end
169
179
 
170
180
  # 2.2) Create a new associative array by mapping the keys from the current associative array ...
171
181
  new_element = {}
172
182
  element.each do |k, v|
173
- k = ec.mappings[k.to_sym] while ec.mappings.has_key?(k.to_sym)
183
+ k = ec.mappings[k.to_s] while ec.mappings.has_key?(k.to_s)
174
184
  new_element[k] = v
175
185
  end
176
186
  unless element == new_element
177
- add_debug(path, "traverse: keys after map: #{new_element.keys.inspect}")
187
+ add_debug(path) {"traverse: keys after map: #{new_element.keys.inspect}"}
178
188
  element = new_element
179
189
  end
180
190
 
181
191
  # Other shortcuts to allow use of this method for terminal associative arrays
182
- if element[IRI].is_a?(String)
183
- # Return the IRI found from the value
184
- object = expand_term(element[IRI], ec.base, ec)
192
+ if element['@iri'].is_a?(String)
193
+ # 2.3 Return the IRI found from the value
194
+ object = expand_term(element['@iri'], ec.base, ec)
185
195
  add_triple(path, subject, property, object) if subject && property
186
196
  return
187
- elsif element[LITERAL]
197
+ elsif element['@literal']
198
+ # 2.4
188
199
  literal_opts = {}
189
- literal_opts[:datatype] = expand_term(element[DATATYPE], ec.vocab.to_s, ec) if element[DATATYPE]
190
- literal_opts[:language] = element[LANGUAGE].to_sym if element[LANGUAGE]
191
- object = RDF::Literal.new(element[LITERAL], literal_opts)
200
+ literal_opts[:datatype] = expand_term(element['@datatype'], ec.vocab.to_s, ec) if element['@datatype']
201
+ literal_opts[:language] = element['@language'].to_sym if element['@language']
202
+ object = RDF::Literal.new(element['@literal'], literal_opts)
192
203
  add_triple(path, subject, property, object) if subject && property
193
204
  return
194
- end
195
-
196
- # 2.3) ... Otherwise, if the local context is known perform the following steps:
197
- # 2.3.1) If a @ key is found, the processor sets the active subject to the
198
- # value after Object Processing has been performed.
199
- if element[SUBJECT].is_a?(String)
200
- active_subject = expand_term(element[SUBJECT], ec.base, ec)
201
- elsif element[SUBJECT]
202
- # Recursively process hash or Array values
203
- traverse("#{path}[#{SUBJECT}]", element[SUBJECT], subject, property, ec)
205
+ elsif element['@list']
206
+ # 2.4a (Lists)
207
+ parse_list("#{path}[#{'@list'}]", element['@list'], subject, property, ec)
208
+ return
209
+ elsif element['@subject'].is_a?(String)
210
+ # 2.5 Subject
211
+ # 2.5.1 Set active object (subject)
212
+ active_subject = expand_term(element['@subject'], ec.base, ec)
213
+ elsif element['@subject']
214
+ # 2.5.2 Recursively process hash or Array values
215
+ traverse("#{path}[#{'@subject'}]", element['@subject'], subject, property, ec)
204
216
  else
205
- # 2.3.7) If the end of the associative array is detected, and a active subject
206
- # was not discovered, then:
207
- # 2.3.7.1) Generate a blank node identifier and set it as the active subject.
217
+ # 2.6) Generate a blank node identifier and set it as the active subject.
208
218
  active_subject = RDF::Node.new
209
219
  end
210
-
211
- # 2.3.1.1) If the inherited subject and inherited property values are
212
- # specified, generate a triple using the inherited subject for the
213
- # subject, the inherited property for the property, and the active
214
- # subject for the object.
215
- # 2.3.7.2) Complete any previously incomplete triples by running all substeps of Step 2.2.1.
220
+
216
221
  add_triple(path, subject, property, active_subject) if subject && property
217
222
  subject = active_subject
218
223
 
219
224
  element.each do |key, value|
220
- # 2.3.3) If a key that is not @context, @subject, or @type, set the active property by
225
+ # 2.7) If a key that is not @context, @subject, or @type, set the active property by
221
226
  # performing Property Processing on the key.
222
227
  property = case key
223
- when TYPE then TYPE
224
- when /^@/ then nil
228
+ when '@type' then '@type'
229
+ when /^@/ then next
225
230
  else expand_term(key, ec.vocab, ec)
226
231
  end
227
232
 
228
- traverse("#{path}[#{key}]", value, subject, property, ec) if property
233
+ # 2.7.3
234
+ if ec.list.include?(property.to_s) && value.is_a?(Array)
235
+ # 2.7.3.1 (Lists) If the active property is the target of a @list coercion, and the value is an array,
236
+ # process the value as a list starting at Step 3a.
237
+ parse_list("#{path}[#{key}]", value, subject, property, ec)
238
+ else
239
+ traverse("#{path}[#{key}]", value, subject, property, ec)
240
+ end
229
241
  end
230
242
  when Array
231
243
  # 3) If a regular array is detected, process each value in the array by doing the following:
232
244
  element.each_with_index do |v, i|
233
- case v
234
- when Hash, String
235
- traverse("#{path}[#{i}]", v, subject, property, ec)
236
- when Array
237
- # 3.3) If the value is a regular array, should we support RDF List/Sequence Processing?
238
- last = v.pop
239
- first_bnode = last ? RDF::Node.new : RDF.nil
240
- add_triple("#{path}[#{i}][]", subject, property, first_bnode)
241
-
242
- v.each do |list_item|
243
- traverse("#{path}[#{i}][]", list_item, first_bnode, RDF.first, ec)
244
- rest_bnode = RDF::Node.new
245
- add_triple("#{path}[#{i}][]", first_bnode, RDF.rest, rest_bnode)
246
- first_bnode = rest_bnode
247
- end
248
- if last
249
- traverse("#{path}[#{i}][]", last, first_bnode, RDF.first, ec)
250
- add_triple("#{path}[#{i}][]", first_bnode, RDF.rest, RDF.nil)
251
- end
252
- end
245
+ traverse("#{path}[#{i}]", v, subject, property, ec)
253
246
  end
254
247
  when String
255
248
  # Perform coersion of the value, or generate a literal
256
- add_debug(path, "traverse(#{element}): coerce?(#{property.inspect}) == #{ec.coerce[property.to_s].inspect}, ec=#{ec.coerce.inspect}")
257
- object = if ec.coerce[property.to_s] == IRI
249
+ add_debug(path) do
250
+ "traverse(#{element}): coerce?(#{property.inspect}) == #{ec.coerce[property.to_s].inspect}, " +
251
+ "ec=#{ec.coerce.inspect}"
252
+ end
253
+ object = if ec.coerce[property.to_s] == '@iri'
258
254
  expand_term(element, ec.base, ec)
259
255
  elsif ec.coerce[property.to_s]
260
256
  RDF::Literal.new(element, :datatype => ec.coerce[property.to_s])
261
257
  else
262
258
  RDF::Literal.new(element)
263
259
  end
264
- property = RDF.type if property == TYPE
260
+ property = RDF.type if property == '@type'
265
261
  add_triple(path, subject, property, object) if subject && property
266
262
  when Float
267
263
  object = RDF::Literal::Double.new(element)
268
- add_debug(path, "traverse(#{element}): native: #{object.inspect}")
264
+ add_debug(path) {"traverse(#{element}): native: #{object.inspect}"}
269
265
  add_triple(path, subject, property, object) if subject && property
270
266
  when Fixnum
271
267
  object = RDF::Literal.new(element)
272
- add_debug(path, "traverse(#{element}): native: #{object.inspect}")
268
+ add_debug(path) {"traverse(#{element}): native: #{object.inspect}"}
273
269
  add_triple(path, subject, property, object) if subject && property
274
270
  when TrueClass, FalseClass
275
271
  object = RDF::Literal::Boolean.new(element)
276
- add_debug(path, "traverse(#{element}): native: #{object.inspect}")
272
+ add_debug(path) {"traverse(#{element}): native: #{object.inspect}"}
277
273
  add_triple(path, subject, property, object) if subject && property
278
274
  else
279
275
  raise RDF::ReaderError, "Traverse to unknown element: #{element.inspect} of type #{element.class}"
@@ -291,7 +287,7 @@ module JSON::LD
291
287
  # @raise [ReaderError] Checks parameter types and raises if they are incorrect if parsing mode is _validate_.
292
288
  def add_triple(path, subject, predicate, object)
293
289
  statement = RDF::Statement.new(subject, predicate, object)
294
- add_debug(path, "statement: #{statement.to_ntriples}")
290
+ add_debug(path) {"statement: #{statement.to_ntriples}"}
295
291
  @callback.call(statement)
296
292
  end
297
293
 
@@ -299,8 +295,11 @@ module JSON::LD
299
295
  # Add debug event to debug array, if specified
300
296
  #
301
297
  # @param [XML Node, any] node:: XML Node or string for showing context
302
- # @param [String] message::
303
- def add_debug(node, message)
298
+ # @param [String] message
299
+ # @yieldreturn [String] appended to message, to allow for lazy-evaulation of message
300
+ def add_debug(node, message = "")
301
+ return unless ::JSON::LD.debug? || @options[:debug]
302
+ message = message + yield if block_given?
304
303
  puts "#{node}: #{message}" if JSON::LD::debug?
305
304
  @options[:debug] << "#{node}: #{message}" if @options[:debug].is_a?(Array)
306
305
  end
@@ -323,39 +322,77 @@ module JSON::LD
323
322
  end
324
323
 
325
324
  context.each do |key, value|
326
- add_debug("parse_context(#{key})", value.inspect)
325
+ add_debug("parse_context(#{key})") {value.inspect}
327
326
  case key
328
- when VOCAB then ec.vocab = value
329
- when BASE then ec.base = uri(value)
330
- when COERCE
327
+ when '@vocab' then ec.vocab = value
328
+ when '@base' then ec.base = uri(value)
329
+ when '@coerce'
331
330
  # Process after prefix mapping
332
331
  else
333
332
  # Spec confusion: The text indicates to merge each key-value pair into the active context. Is any
334
333
  # processing performed on the values. For instance, could a value be a CURIE, or {"@iri": <value>}?
335
334
  # Examples indicate that there is no such processing, and each value should be an absolute IRI. The
336
335
  # wording makes this unclear.
337
- ec.mappings[key.to_sym] = value
336
+ ec.mappings[key.to_s] = value
338
337
  end
339
338
  end
340
339
 
341
- if context[COERCE]
340
+ if context['@coerce']
342
341
  # Spec confusion: doc says to merge each key-value mapping to the local context's @coerce mapping,
343
342
  # overwriting duplicate values. In the case where a mapping is indicated to a list of properties
344
343
  # (e.g., { "@iri": ["foaf:homepage", "foaf:member"] }, does this overwrite a previous mapping
345
344
  # of { "@iri": "foaf:knows" }, or add to it.
346
- add_error RDF::ReaderError, "Expected @coerce to reference an associative array" unless context[COERCE].is_a?(Hash)
347
- context[COERCE].each do |type, property|
345
+ add_error RDF::ReaderError, "Expected @coerce to reference an associative array" unless context['@coerce'].is_a?(Hash)
346
+ context['@coerce'].each do |type, property|
347
+ add_debug("parse_context: @coerce") {"type=#{type}, prop=#{property}"}
348
348
  type_uri = expand_term(type, ec.vocab, ec).to_s
349
349
  [property].flatten.compact.each do |prop|
350
350
  p = expand_term(prop, ec.vocab, ec).to_s
351
- ec.coerce[p] = type_uri
351
+ if type == '@list'
352
+ # List is managed separate from types, as it is maintained in normal form.
353
+ ec.list << p unless ec.list.include?(p)
354
+ else
355
+ ec.coerce[p] = type_uri
356
+ end
352
357
  end
353
358
  end
354
359
  end
355
360
 
356
361
  ec
357
362
  end
358
-
363
+
364
+ ##
365
+ # Parse a List
366
+ #
367
+ # @param [String] path
368
+ # location within JSON hash
369
+ # @param [Array] list
370
+ # The Array to serialize as a list
371
+ # @param [RDF::URI] subject
372
+ # Inherited subject
373
+ # @param [RDF::URI] property
374
+ # Inherited property
375
+ # @param [EvaluationContext] ec
376
+ # The active context
377
+ def parse_list(path, list, subject, property, ec)
378
+ add_debug(path) {"list: #{list.inspect}, s=#{subject.inspect}, p=#{property.inspect}, e=#{ec.inspect}"}
379
+
380
+ last = list.pop
381
+ first_bnode = last ? RDF::Node.new : RDF.nil
382
+ add_triple("#{path}", subject, property, first_bnode)
383
+
384
+ list.each do |list_item|
385
+ traverse("#{path}", list_item, first_bnode, RDF.first, ec)
386
+ rest_bnode = RDF::Node.new
387
+ add_triple("#{path}", first_bnode, RDF.rest, rest_bnode)
388
+ first_bnode = rest_bnode
389
+ end
390
+ if last
391
+ traverse("#{path}", last, first_bnode, RDF.first, ec)
392
+ add_triple("#{path}", first_bnode, RDF.rest, RDF.nil)
393
+ end
394
+ end
395
+
359
396
  ##
360
397
  # Expand a term using the specified context
361
398
  #
@@ -367,11 +404,9 @@ module JSON::LD
367
404
  # @raise [RDF::ReaderError] if the term cannot be expanded
368
405
  # @see http://json-ld.org/spec/ED/20110507/#markup-of-rdf-concepts
369
406
  def expand_term(term, base, ec)
370
- #add_debug("expand_term", "term=#{term.inspect}, base=#{base.inspect}, ec=#{ec.inspect}")
407
+ #add_debug("expand_term", {"term=#{term.inspect}, base=#{base.inspect}, ec=#{ec.inspect}"}
371
408
  prefix, suffix = term.split(":", 2)
372
- prefix = prefix.to_sym if prefix
373
- return if prefix == '_'
374
- if prefix == :_
409
+ if prefix == '_'
375
410
  bnode(suffix)
376
411
  elsif ec.mappings.has_key?(prefix)
377
412
  uri(ec.mappings[prefix] + suffix.to_s)
@@ -392,9 +427,12 @@ module JSON::LD
392
427
  end
393
428
 
394
429
  # Keep track of allocated BNodes
430
+ #
431
+ # Don't actually use the name provided, to prevent name alias issues.
432
+ # @return [RDF::Node]
395
433
  def bnode(value = nil)
396
434
  @bnode_cache ||= {}
397
- @bnode_cache[value.to_s] ||= RDF::Node.new(value)
435
+ @bnode_cache[value.to_s] ||= RDF::Node.new
398
436
  end
399
437
  end
400
438
  end
@@ -1,4 +1,4 @@
1
- module RDF::N3::VERSION
1
+ module JSON::LD::VERSION
2
2
  VERSION_FILE = File.join(File.expand_path(File.dirname(__FILE__)), "..", "..", "..", "VERSION")
3
3
  MAJOR, MINOR, TINY, EXTRA = File.read(VERSION_FILE).chop.split(".")
4
4
 
@@ -7,7 +7,7 @@ module JSON::LD
7
7
  # and then serialize the graph.
8
8
  #
9
9
  # @example Obtaining a JSON-LD writer class
10
- # RDF::Writer.for(:jsonld) #=> RDF::N3::Writer
10
+ # RDF::Writer.for(:jsonld) #=> JSON::LD::Writer
11
11
  # RDF::Writer.for("etc/test.json")
12
12
  # RDF::Writer.for(:file_name => "etc/test.json")
13
13
  # RDF::Writer.for(:file_extension => "json")
@@ -47,7 +47,7 @@ module JSON::LD
47
47
  # end
48
48
  # end
49
49
  #
50
- # Select the :canonicalize option to output JSON-LD in canonical form
50
+ # Select the :normalize option to output JSON-LD in canonical form
51
51
  #
52
52
  # @see http://json-ld.org/spec/ED/20110507/
53
53
  # @see http://json-ld.org/spec/ED/20110507/#the-normalization-algorithm
@@ -69,6 +69,10 @@ module JSON::LD
69
69
  # @attr [Hash{String => String}]
70
70
  attr :coerce, true
71
71
 
72
+ ##
73
+ # Local implementation of ruby Hash class to allow for ordering in 1.8.x implementations.
74
+ #
75
+ # @return [Hash, InsertOrderPreservingHash]
72
76
  def self.new_hash
73
77
  if RUBY_VERSION < "1.9"
74
78
  InsertOrderPreservingHash.new
@@ -99,6 +103,8 @@ module JSON::LD
99
103
  # the encoding to use on the output stream (Ruby 1.9+)
100
104
  # @option options [Boolean] :canonicalize (false)
101
105
  # whether to canonicalize literals when serializing
106
+ # @option options [Boolean] :normalize (false)
107
+ # Output document in [normalized form](http://json-ld.org/spec/latest/#normalization-1)
102
108
  # @option options [Hash] :prefixes (Hash.new)
103
109
  # the prefix mappings to use (not supported by all writers)
104
110
  # @option options [#to_s] :base_uri (nil)
@@ -115,7 +121,7 @@ module JSON::LD
115
121
  def initialize(output = $stdout, options = {}, &block)
116
122
  super do
117
123
  @graph = RDF::Graph.new
118
- @iri_to_prefix = DEFAULT_CONTEXT.dup.delete_if {|k,v| k == COERCE}.invert
124
+ @iri_to_prefix = DEFAULT_CONTEXT.dup.delete_if {|k,v| k == '@coerce'}.invert
119
125
  @coerce = DEFAULT_COERCE.merge(options[:coerce] || {})
120
126
  if block_given?
121
127
  case block.arity
@@ -132,7 +138,7 @@ module JSON::LD
132
138
  # @param [Graph] graph
133
139
  # @return [void]
134
140
  def write_graph(graph)
135
- add_debug "Add graph #{graph.inspect}"
141
+ add_debug {"Add graph #{graph.inspect}"}
136
142
  @graph = graph
137
143
  end
138
144
 
@@ -162,18 +168,18 @@ module JSON::LD
162
168
  # @return [void]
163
169
  # @see #write_triple
164
170
  def write_epilogue
165
- @base_uri = RDF::URI(@options[:base_uri]) if @options[:base_uri] && !@options[:canonicalize]
166
- @vocab = @options[:vocab] unless @options[:canonicalize]
171
+ @base_uri = RDF::URI(@options[:base_uri]) if @options[:base_uri] && !@options[:normalize]
172
+ @vocab = @options[:vocab] unless @options[:normalize]
167
173
  @debug = @options[:debug]
168
174
 
169
175
  reset
170
176
 
171
- add_debug "\nserialize: graph: #{@graph.size}"
177
+ add_debug {"\nserialize: graph: #{@graph.size}"}
172
178
 
173
179
  preprocess
174
180
 
175
181
  # Don't generate context for canonical output
176
- json_hash = @options[:canonicalize] ? new_hash : start_document
182
+ json_hash = @options[:normalize] ? new_hash : start_document
177
183
 
178
184
  elements = []
179
185
  order_subjects.each do |subject|
@@ -187,13 +193,13 @@ module JSON::LD
187
193
  if elements.length == 1 && elements.first.is_a?(Hash)
188
194
  json_hash.merge!(elements.first)
189
195
  else
190
- json_hash[SUBJECT] = elements
196
+ json_hash['@subject'] = elements
191
197
  end
192
198
 
193
199
  if @output.is_a?(Hash)
194
200
  @output.merge!(json_hash)
195
201
  else
196
- json_state = if @options[:canonicalize]
202
+ json_state = if @options[:normalize]
197
203
  JSON::State.new(
198
204
  :indent => "",
199
205
  :space => "",
@@ -235,17 +241,17 @@ module JSON::LD
235
241
  short == value.to_s ? (get_curie(value) || value.to_s) : short
236
242
  when :predicate
237
243
  # attempt vocab replacement
238
- short = TYPE if value == RDF.type
244
+ short = '@type' if value == RDF.type
239
245
  short ||= value.to_s.sub(@vocab.to_s, "")
240
246
  short == value.to_s ? (get_curie(value) || value.to_s) : short
241
247
  else
242
248
  # Encode like a subject
243
249
  iri_range?(options[:property]) ?
244
250
  format_uri(value, :position => :subject) :
245
- {IRI => format_uri(value, :position => :subject)}
251
+ {'@iri' => format_uri(value, :position => :subject)}
246
252
  end
247
253
 
248
- add_debug("format_uri(#{options.inspect}, #{value.inspect}) => #{result.inspect}")
254
+ add_debug {"format_uri(#{options.inspect}, #{value.inspect}) => #{result.inspect}"}
249
255
  result
250
256
  end
251
257
 
@@ -268,11 +274,11 @@ module JSON::LD
268
274
  # Property referencing literal for type coercion
269
275
  # @return [Object]
270
276
  def format_literal(literal, options = {})
271
- if options[:canonical] || @options[:canonicalize]
277
+ if options[:normal] || @options[:normalize]
272
278
  ret = new_hash
273
- ret[LITERAL] = literal.value
274
- ret[DATATYPE] = format_uri(literal.datatype, :position => :subject)if literal.has_datatype?
275
- ret[LANGUAGE] = literal.language.to_s if literal.has_language?
279
+ ret['@literal'] = literal.value
280
+ ret['@datatype'] = format_uri(literal.datatype, :position => :subject) if literal.has_datatype?
281
+ ret['@language'] = literal.language.to_s if literal.has_language?
276
282
  return ret.delete_if {|k,v| v.nil?}
277
283
  end
278
284
 
@@ -284,7 +290,7 @@ module JSON::LD
284
290
  # Datatype coercion where literal has the same datatype
285
291
  literal.value
286
292
  else
287
- format_literal(literal, :canonical => true)
293
+ format_literal(literal, :normal => true)
288
294
  end
289
295
  end
290
296
  end
@@ -295,12 +301,12 @@ module JSON::LD
295
301
  # @param [Hash{Symbol => Object}] options
296
302
  # @option options [RDF::URI] property
297
303
  # Property referencing literal for type coercion
298
- # @return [Array<Array<Object>>]
304
+ # @return [Hash{"@list" => Array<Object>}]
299
305
  def format_list(object, options = {})
300
306
  predicate = options[:property]
301
307
  list = []
302
308
 
303
- add_debug "format_list(#{object}, #{predicate})"
309
+ add_debug {"format_list(#{object}, #{predicate})"}
304
310
 
305
311
  @depth += 1
306
312
  while object do
@@ -308,7 +314,7 @@ module JSON::LD
308
314
  p = @graph.properties(object)
309
315
  item = p.fetch(RDF.first.to_s, []).first
310
316
  if item
311
- add_debug "format_list serialize #{item.inspect}"
317
+ add_debug {"format_list serialize #{item.inspect}"}
312
318
  list << if predicate || item.literal?
313
319
  property(predicate, item)
314
320
  else
@@ -320,8 +326,8 @@ module JSON::LD
320
326
  @depth -= 1
321
327
 
322
328
  # Returns
323
- add_debug "format_list => #{[list].inspect}"
324
- [list]
329
+ add_debug {"format_list => #{{'@list' => list}.inspect}"}
330
+ {'@list' => list}
325
331
  end
326
332
 
327
333
  private
@@ -330,26 +336,26 @@ module JSON::LD
330
336
  # @return [Hash]
331
337
  def start_document
332
338
  ctx = new_hash
333
- ctx[BASE] = base_uri.to_s if base_uri
334
- ctx[VOCAB] = vocab.to_s if vocab
339
+ ctx['@base'] = base_uri.to_s if base_uri
340
+ ctx['@vocab'] = vocab.to_s if vocab
335
341
 
336
342
  # Prefixes
337
343
  prefixes.keys.sort {|a,b| a.to_s <=> b.to_s}.each do |k|
338
344
  next if DEFAULT_CONTEXT.has_key?(k.to_s)
339
- add_debug "prefix[#{k}] => #{prefixes[k]}"
345
+ add_debug {"prefix[#{k}] => #{prefixes[k]}"}
340
346
  ctx[k.to_s] = prefixes[k].to_s
341
347
  end
342
348
 
343
349
  # Coerce
344
- add_debug "start_doc: coerce= #{coerce.inspect}"
350
+ add_debug {"start_doc: coerce= #{coerce.inspect}"}
345
351
  unless coerce == DEFAULT_COERCE
346
352
  c_h = new_hash
347
353
  coerce.keys.sort.each do |k|
348
- next if [TYPE, RDF.type.to_s].include?(k.to_s)
354
+ next if ['@type', RDF.type.to_s].include?(k.to_s)
349
355
  next if [DEFAULT_COERCE[k], false, RDF::XSD.integer.to_s, RDF::XSD.boolean.to_s].include?(coerce[k])
350
- k_iri = k == IRI ? IRI : format_uri(k, :position => :predicate)
356
+ k_iri = k == '@iri' ? '@iri' : format_uri(k, :position => :predicate)
351
357
  d_iri = format_uri(coerce[k], :position => :subject)
352
- add_debug "coerce[#{k_iri}] => #{d_iri}, k=#{k.inspect}"
358
+ add_debug {"coerce[#{k_iri}] => #{d_iri}, k=#{k.inspect}"}
353
359
  case c_h[d_iri]
354
360
  when nil
355
361
  c_h[d_iri] = k_iri
@@ -360,14 +366,14 @@ module JSON::LD
360
366
  end
361
367
  end
362
368
 
363
- ctx[COERCE] = c_h unless c_h.empty?
369
+ ctx['@coerce'] = c_h unless c_h.empty?
364
370
  end
365
371
 
366
- add_debug "start_doc: context=#{ctx.inspect}"
372
+ add_debug {"start_doc: context=#{ctx.inspect}"}
367
373
 
368
374
  # Return hash with @context, or empty
369
375
  r = new_hash
370
- r[CONTEXT] = ctx unless ctx.empty?
376
+ r['@context'] = ctx unless ctx.empty?
371
377
  r
372
378
  end
373
379
 
@@ -386,7 +392,7 @@ module JSON::LD
386
392
  # prefixes.
387
393
  # @param [Statement] statement
388
394
  def preprocess_statement(statement)
389
- add_debug "preprocess: #{statement.inspect}"
395
+ add_debug {"preprocess: #{statement.inspect}"}
390
396
  references = ref_count(statement.object) + 1
391
397
  @references[statement.object] = references
392
398
  @subjects[statement.subject] = true
@@ -414,35 +420,35 @@ module JSON::LD
414
420
 
415
421
  subject_done(subject)
416
422
  properties = @graph.properties(subject)
417
- add_debug "subject: #{subject.inspect}, props: #{properties.inspect}"
423
+ add_debug {"subject: #{subject.inspect}, props: #{properties.inspect}"}
418
424
 
419
425
  @graph.query(:subject => subject).each do |st|
420
426
  raise RDF::WriterError, "Illegal use of predicate #{st.predicate.inspect}, not supported in RDF/XML" unless st.predicate.uri?
421
427
  end
422
428
 
423
- if subject.node? && ref_count(subject) > (options[:property] ? 1 : 0) && options[:canonicalize]
429
+ if subject.node? && ref_count(subject) > (options[:property] ? 1 : 0) && options[:normalize]
424
430
  raise RDF::WriterError, "Can't serialize named node when normalizing"
425
431
  end
426
432
 
427
433
  # Subject may be a list
428
434
  if is_valid_list?(subject)
429
435
  add_debug "subject is a list"
430
- defn[SUBJECT] = format_list(subject)
436
+ defn['@subject'] = format_list(subject)
431
437
  properties.delete(RDF.first.to_s)
432
438
  properties.delete(RDF.rest.to_s)
433
439
 
434
440
  # Special case, if there are no properties, then we can just serialize the list itself
435
- return defn[SUBJECT].first if properties.empty?
441
+ return defn if properties.empty?
436
442
  elsif subject.uri? || ref_count(subject) > 1
437
443
  add_debug "subject is a uri"
438
444
  # Don't need to set subject if it's a Node without references
439
- defn[SUBJECT] = format_uri(subject, :position => :subject)
445
+ defn['@subject'] = format_uri(subject, :position => :subject)
440
446
  else
441
447
  add_debug "subject is an unreferenced BNode"
442
448
  end
443
449
 
444
450
  prop_list = order_properties(properties)
445
- #add_debug "=> property order: #{prop_list.to_sentence}"
451
+ #add_debug {"=> property order: #{prop_list.to_sentence}"}
446
452
 
447
453
  prop_list.each do |prop|
448
454
  predicate = RDF::URI.intern(prop)
@@ -450,11 +456,11 @@ module JSON::LD
450
456
  p_iri = format_uri(predicate, :position => :predicate)
451
457
  @depth += 1
452
458
  defn[p_iri] = property(predicate, properties[prop])
453
- add_debug "prop(#{p_iri}) => #{properties[prop]} => #{defn[p_iri].inspect}"
459
+ add_debug {"prop(#{p_iri}) => #{properties[prop]} => #{defn[p_iri].inspect}"}
454
460
  @depth -= 1
455
461
  end
456
462
 
457
- add_debug "subject: #{subject} has defn: #{defn.inspect}"
463
+ add_debug {"subject: #{subject} has defn: #{defn.inspect}"}
458
464
  defn
459
465
  end
460
466
 
@@ -490,7 +496,7 @@ module JSON::LD
490
496
  # @param [RDF::Resource] resource
491
497
  # @return [String, nil] value to use to identify IRI
492
498
  def get_curie(resource)
493
- add_debug "get_curie(#{resource.inspect})"
499
+ add_debug {"get_curie(#{resource.inspect})"}
494
500
  case resource
495
501
  when RDF::Node
496
502
  return resource.to_s
@@ -500,7 +506,7 @@ module JSON::LD
500
506
  return nil unless resource.absolute?
501
507
  when RDF::URI
502
508
  iri = resource.to_s
503
- return iri if options[:canonicalize]
509
+ return iri if options[:normalize]
504
510
  else
505
511
  return nil
506
512
  end
@@ -555,7 +561,7 @@ module JSON::LD
555
561
 
556
562
  return @subjects.keys.sort do |a,b|
557
563
  format_iri(a, :position => :subject) <=> format_iri(b, :position => :subject)
558
- end if @options[:canonicalize]
564
+ end if @options[:normalize]
559
565
 
560
566
  # Start with base_uri
561
567
  if base_uri && @subjects.keys.include?(base_uri)
@@ -583,16 +589,16 @@ module JSON::LD
583
589
  # @param [RDF::URI] predicate
584
590
  # @return [Boolean]
585
591
  def iri_range?(predicate)
586
- return false if predicate.nil? || @options[:canonicalize]
592
+ return false if predicate.nil? || @options[:normalize]
587
593
 
588
594
  unless coerce.has_key?(predicate.to_s)
589
595
  # objects of all statements with the predicate may not be literal
590
596
  coerce[predicate.to_s] = @graph.query(:predicate => predicate).to_a.any? {|st| st.object.literal?} ?
591
- false : IRI
597
+ false : '@iri'
592
598
  end
593
599
 
594
- add_debug "iri_range(#{predicate}) = #{coerce[predicate.to_s].inspect}"
595
- coerce[predicate.to_s] == IRI
600
+ add_debug {"iri_range(#{predicate}) = #{coerce[predicate.to_s].inspect}"}
601
+ coerce[predicate.to_s] == '@iri'
596
602
  end
597
603
 
598
604
  ##
@@ -612,7 +618,7 @@ module JSON::LD
612
618
  dt = false
613
619
  end
614
620
  end
615
- add_debug "range(#{predicate}) = #{dt.inspect}"
621
+ add_debug {"range(#{predicate}) = #{dt.inspect}"}
616
622
  coerce[predicate.to_s] = dt
617
623
  end
618
624
 
@@ -630,8 +636,11 @@ module JSON::LD
630
636
 
631
637
  # Add debug event to debug array, if specified
632
638
  #
633
- # @param [String] message::
634
- def add_debug(message)
639
+ # @param [String] message
640
+ # @yieldreturn [String] appended to message, to allow for lazy-evaulation of message
641
+ def add_debug(message = "")
642
+ return unless ::JSON::LD.debug? || @options[:debug]
643
+ message = message + yield if block_given?
635
644
  msg = "#{" " * @depth * 2}#{message}"
636
645
  STDERR.puts msg if ::JSON::LD::debug?
637
646
  @debug << msg if @debug.is_a?(Array)
@@ -641,26 +650,26 @@ module JSON::LD
641
650
  def is_valid_list?(l)
642
651
  props = @graph.properties(l)
643
652
  unless l.node? && props.has_key?(RDF.first.to_s) || l == RDF.nil
644
- add_debug "is_valid_list: false, #{l.inspect}: #{props.inspect}"
653
+ add_debug {"is_valid_list: false, #{l.inspect}: #{props.inspect}"}
645
654
  return false
646
655
  end
647
656
 
648
657
  while l && l != RDF.nil do
649
- #add_debug "is_valid_list(length): #{props.length}"
658
+ #add_debug {"is_valid_list(length): #{props.length}"}
650
659
  return false unless props.has_key?(RDF.first.to_s) && props.has_key?(RDF.rest.to_s)
651
660
  n = props[RDF.rest.to_s]
652
661
  unless n.is_a?(Array) && n.length == 1
653
- add_debug "is_valid_list: false, #{n.inspect}"
662
+ add_debug {"is_valid_list: false, #{n.inspect}"}
654
663
  return false
655
664
  end
656
665
  l = n.first
657
666
  unless l.node? || l == RDF.nil
658
- add_debug "is_valid_list: false, #{l.inspect}"
667
+ add_debug {"is_valid_list: false, #{l.inspect}"}
659
668
  return false
660
669
  end
661
670
  props = @graph.properties(l)
662
671
  end
663
- add_debug "is_valid_list: valid"
672
+ add_debug {"is_valid_list: valid"}
664
673
  true
665
674
  end
666
675
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: json-ld
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,23 +9,22 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-08-05 00:00:00.000000000 -07:00
13
- default_executable:
12
+ date: 2011-09-15 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
15
  name: rdf
17
- requirement: &2168459600 !ruby/object:Gem::Requirement
16
+ requirement: &2169730540 !ruby/object:Gem::Requirement
18
17
  none: false
19
18
  requirements:
20
19
  - - ! '>='
21
20
  - !ruby/object:Gem::Version
22
- version: 0.3.3
21
+ version: 0.3.4
23
22
  type: :runtime
24
23
  prerelease: false
25
- version_requirements: *2168459600
24
+ version_requirements: *2169730540
26
25
  - !ruby/object:Gem::Dependency
27
26
  name: json
28
- requirement: &2168459140 !ruby/object:Gem::Requirement
27
+ requirement: &2169729780 !ruby/object:Gem::Requirement
29
28
  none: false
30
29
  requirements:
31
30
  - - ! '>='
@@ -33,10 +32,10 @@ dependencies:
33
32
  version: 1.5.1
34
33
  type: :runtime
35
34
  prerelease: false
36
- version_requirements: *2168459140
35
+ version_requirements: *2169729780
37
36
  - !ruby/object:Gem::Dependency
38
37
  name: yard
39
- requirement: &2168458680 !ruby/object:Gem::Requirement
38
+ requirement: &2169728940 !ruby/object:Gem::Requirement
40
39
  none: false
41
40
  requirements:
42
41
  - - ! '>='
@@ -44,10 +43,10 @@ dependencies:
44
43
  version: 0.6.0
45
44
  type: :development
46
45
  prerelease: false
47
- version_requirements: *2168458680
46
+ version_requirements: *2169728940
48
47
  - !ruby/object:Gem::Dependency
49
48
  name: rspec
50
- requirement: &2168458220 !ruby/object:Gem::Requirement
49
+ requirement: &2169727620 !ruby/object:Gem::Requirement
51
50
  none: false
52
51
  requirements:
53
52
  - - ! '>='
@@ -55,21 +54,21 @@ dependencies:
55
54
  version: 2.5.0
56
55
  type: :development
57
56
  prerelease: false
58
- version_requirements: *2168458220
57
+ version_requirements: *2169727620
59
58
  - !ruby/object:Gem::Dependency
60
59
  name: rdf-spec
61
- requirement: &2168457760 !ruby/object:Gem::Requirement
60
+ requirement: &2169703000 !ruby/object:Gem::Requirement
62
61
  none: false
63
62
  requirements:
64
63
  - - ! '>='
65
64
  - !ruby/object:Gem::Version
66
- version: 0.3.2
65
+ version: 0.3.4
67
66
  type: :development
68
67
  prerelease: false
69
- version_requirements: *2168457760
68
+ version_requirements: *2169703000
70
69
  - !ruby/object:Gem::Dependency
71
70
  name: rdf-n3
72
- requirement: &2168487740 !ruby/object:Gem::Requirement
71
+ requirement: &2169702100 !ruby/object:Gem::Requirement
73
72
  none: false
74
73
  requirements:
75
74
  - - ! '>='
@@ -77,10 +76,10 @@ dependencies:
77
76
  version: 0.3.3
78
77
  type: :development
79
78
  prerelease: false
80
- version_requirements: *2168487740
79
+ version_requirements: *2169702100
81
80
  - !ruby/object:Gem::Dependency
82
81
  name: rdf-isomorphic
83
- requirement: &2168487280 !ruby/object:Gem::Requirement
82
+ requirement: &2169700640 !ruby/object:Gem::Requirement
84
83
  none: false
85
84
  requirements:
86
85
  - - ! '>='
@@ -88,10 +87,10 @@ dependencies:
88
87
  version: 0.3.4
89
88
  type: :development
90
89
  prerelease: false
91
- version_requirements: *2168487280
90
+ version_requirements: *2169700640
92
91
  - !ruby/object:Gem::Dependency
93
92
  name: sxp
94
- requirement: &2168486820 !ruby/object:Gem::Requirement
93
+ requirement: &2169698280 !ruby/object:Gem::Requirement
95
94
  none: false
96
95
  requirements:
97
96
  - - ! '>='
@@ -99,10 +98,10 @@ dependencies:
99
98
  version: '0'
100
99
  type: :development
101
100
  prerelease: false
102
- version_requirements: *2168486820
101
+ version_requirements: *2169698280
103
102
  - !ruby/object:Gem::Dependency
104
103
  name: sparql-algebra
105
- requirement: &2168486360 !ruby/object:Gem::Requirement
104
+ requirement: &2169697020 !ruby/object:Gem::Requirement
106
105
  none: false
107
106
  requirements:
108
107
  - - ! '>='
@@ -110,10 +109,10 @@ dependencies:
110
109
  version: '0'
111
110
  type: :development
112
111
  prerelease: false
113
- version_requirements: *2168486360
112
+ version_requirements: *2169697020
114
113
  - !ruby/object:Gem::Dependency
115
114
  name: sparql-grammar
116
- requirement: &2168485900 !ruby/object:Gem::Requirement
115
+ requirement: &2169695840 !ruby/object:Gem::Requirement
117
116
  none: false
118
117
  requirements:
119
118
  - - ! '>='
@@ -121,7 +120,7 @@ dependencies:
121
120
  version: '0'
122
121
  type: :development
123
122
  prerelease: false
124
- version_requirements: *2168485900
123
+ version_requirements: *2169695840
125
124
  description: JSON-LD reader/writer for Ruby.
126
125
  email: public-rdf-ruby@w3.org
127
126
  executables: []
@@ -134,11 +133,11 @@ files:
134
133
  - VERSION
135
134
  - lib/json/ld/extensions.rb
136
135
  - lib/json/ld/format.rb
136
+ - lib/json/ld/normalize.rb
137
137
  - lib/json/ld/reader.rb
138
138
  - lib/json/ld/version.rb
139
139
  - lib/json/ld/writer.rb
140
140
  - lib/json/ld.rb
141
- has_rdoc: false
142
141
  homepage: http://github.com/gkellogg/json-ld
143
142
  licenses:
144
143
  - Public Domain
@@ -160,7 +159,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
160
159
  version: '0'
161
160
  requirements: []
162
161
  rubyforge_project: json-ld
163
- rubygems_version: 1.6.2
162
+ rubygems_version: 1.8.10
164
163
  signing_key:
165
164
  specification_version: 3
166
165
  summary: JSON-LD reader/writer for Ruby.