json-ld 0.0.7 → 0.0.8

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.
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.