json-ld 1.0.1.1 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 97a3575f2cb93a3349fbf649fbe3f6e2bc76f309
4
- data.tar.gz: 03bd6138b0f58510bf04e80cd0b303c0672ac30e
5
- SHA512:
6
- metadata.gz: 31a098c284a903bcc42447954a9989e3d775d10c88dd91abdfd02c6c04e8714e6e0d81ac9daa01db96abb58b3acadc185da3331fee040aad9055c11e2d25b8f4
7
- data.tar.gz: 5aa36012fdc65dce8d9129cff315b6ed828e3a8be3af7c4d093fe5becc100360c90ad0bd8e9bc1b30230c5ece62952dc339541485403a705cfaf071f7926b543
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NzllY2IzN2M4MjQ5MGUxMWQ0M2NhYTliZWFmMzUyYzZmMDYwODIxOQ==
5
+ data.tar.gz: !binary |-
6
+ OGM3NmQ5YTVhMDk3ZTE3NGZjNmM4MTc2NWQ0Y2NiNzhlZjllOWMxYw==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ ZjkxY2E1ZGZiZDM2M2EyMDUwMTFmZGIwNmI2YTYyMGRkYzI5YzQ4OTRkMTFm
10
+ N2VlZjE5OGEzN2FiMTcyY2U4MGVkOGMzN2RhOWIyZmQ2MTczMDNhMjI5NDli
11
+ MTBmZTJkOWEzZWYzZjE0Mjk5Mjc1YzgwOTA3YzFlZGZmZWVmYTI=
12
+ data.tar.gz: !binary |-
13
+ NzNmZTU0YTA3OGQ0MmRjZjNlNzhlNzlkNzFlNDQ2OWY4YWM5MTIyNjA1MzFl
14
+ MTYxNjZiMzFhZWIzNWNhM2I1YjE3ZDA4NDc4M2EwOGI0YjJkYzNkOTJlNDk0
15
+ ZTliMTMwNDk5MWZmOGU2NjQ3NDFmYjkyMTE3NTRhN2NkYzVkYzk=
data/README.md CHANGED
@@ -184,7 +184,7 @@ Install with `gem install json-ld`
184
184
  }
185
185
  }
186
186
 
187
- JSON::LD::fromRDF(input, context) =>
187
+ JSON::LD::API::fromRDF(input, context) =>
188
188
  {
189
189
  "@context": {
190
190
  "": "http://manu.sporny.org/",
@@ -206,7 +206,7 @@ Install with `gem install json-ld`
206
206
  graph.dump(:jsonld, :standard_prefixes => true)
207
207
 
208
208
  ## Documentation
209
- Full documentation available on [RubyDoc](http://rubydoc.info/gems/json-ld/file/README.markdown)
209
+ Full documentation available on [RubyDoc](http://rubydoc.info/gems/json-ld/file/README.md)
210
210
 
211
211
  ## Differences from [JSON-LD API][]
212
212
  The specified JSON-LD API is based on a WebIDL definition intended for use within the browser.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.1.1
1
+ 1.0.3
@@ -26,7 +26,7 @@ module JSON::LD
26
26
 
27
27
  # Options used for open_file
28
28
  OPEN_OPTS = {
29
- :headers => %w(Accept: application/ld+json, application/json)
29
+ :headers => {"Accept" => "application/ld+json, application/json"}
30
30
  }
31
31
 
32
32
  # Current input
@@ -212,11 +212,11 @@ module JSON::LD
212
212
  entry = default_graph[graph_name] ||= {'@id' => graph_name}
213
213
  nodes = entry['@graph'] ||= []
214
214
  graph.keys.kw_sort.each do |id|
215
- nodes << graph[id]
215
+ nodes << graph[id] unless node_reference?(graph[id])
216
216
  end
217
217
  end
218
218
  default_graph.keys.kw_sort.each do |id|
219
- flattened << default_graph[id]
219
+ flattened << default_graph[id] unless node_reference?(default_graph[id])
220
220
  end
221
221
 
222
222
  if context && !flattened.empty?
@@ -302,10 +302,10 @@ module JSON::LD
302
302
  all_nodes = Hash.ordered
303
303
  old_dbg, @options[:debug] = @options[:debug], nil
304
304
  depth do
305
- generate_node_map(value, all_nodes, '@merged')
305
+ generate_node_map(value, all_nodes)
306
306
  end
307
307
  @options[:debug] = old_dbg
308
- @node_map = all_nodes['@merged']
308
+ @node_map = all_nodes['@default']
309
309
  debug(".frame") {"node_map: #{@node_map.to_json(JSON_STATE)}"}
310
310
 
311
311
  result = []
@@ -339,6 +339,8 @@ module JSON::LD
339
339
  # @param [{Symbol,String => Object}] options
340
340
  # See options in {JSON::LD::API#initialize}
341
341
  # Options passed to {JSON::LD::API.expand}
342
+ # @option options [Boolean] :produceGeneralizedRDF (false)
343
+ # If true, output will include statements having blank node predicates, otherwise they are dropped.
342
344
  # @raise [InvalidContext]
343
345
  # @return [Array<RDF::Statement>] if no block given
344
346
  # @yield statement
@@ -366,6 +368,7 @@ module JSON::LD
366
368
  context = as_resource(graph_name) unless graph_name == '@default'
367
369
  debug(".toRDF") {"context: #{context ? context.to_ntriples : 'null'}"}
368
370
  graph_to_rdf(graph).each do |statement|
371
+ next if statement.predicate.node? && !options[:produceGeneralizedRDF]
369
372
  statement.context = context if context
370
373
  if block_given?
371
374
  yield statement
@@ -67,7 +67,8 @@ module JSON::LD
67
67
  debug("@reverse") {"compacted_value: #{compacted_value.inspect}"}
68
68
  compacted_value.each do |prop, value|
69
69
  if context.reverse?(prop)
70
- value = [value] unless value.is_a?(Array) || @options[:compactArrays]
70
+ value = [value] if !value.is_a?(Array) &&
71
+ (context.container(prop) == '@set' || !@options[:compactArrays])
71
72
  debug("") {"merge #{prop} => #{value.inspect}"}
72
73
  merge_compacted_value(result, prop, value)
73
74
  compacted_value.delete(prop)
@@ -46,7 +46,7 @@ module JSON::LD
46
46
  cid = context.compact_iri(id)
47
47
  cid == term ? id : cid
48
48
  else
49
- defn = Hash.ordered
49
+ defn = {}
50
50
  cid = context.compact_iri(id)
51
51
  defn[reverse_property ? '@reverse' : '@id'] = cid unless cid == term && !reverse_property
52
52
  if type_mapping
@@ -76,9 +76,14 @@ module JSON::LD
76
76
 
77
77
  # The base.
78
78
  #
79
- # @return [RDF::URI] Document base IRI, used for expanding relative IRIs.
79
+ # @return [RDF::URI] Current base IRI, used for expanding relative IRIs.
80
80
  attr_reader :base
81
81
 
82
+ # The base.
83
+ #
84
+ # @return [RDF::URI] Document base IRI, to initialize `base`.
85
+ attr_reader :doc_base
86
+
82
87
  # @return [RDF::URI] base IRI of the context, if loaded remotely. XXX
83
88
  attr_accessor :context_base
84
89
 
@@ -126,7 +131,7 @@ module JSON::LD
126
131
  # @return [Context]
127
132
  def initialize(options = {})
128
133
  if options[:base]
129
- @doc_base = RDF::URI(options[:base])
134
+ @base = @doc_base = RDF::URI(options[:base])
130
135
  @doc_base.canonicalize!
131
136
  @doc_base.fragment = nil
132
137
  @doc_base.query = nil
@@ -179,13 +184,17 @@ module JSON::LD
179
184
 
180
185
  # @param [String] value must be an absolute IRI
181
186
  def vocab=(value)
182
- if value
183
- raise InvalidContext::InvalidVocabMapping, "@value must be a string: #{value.inspect}" unless value.is_a?(String)
184
- @vocab = RDF::URI(value)
185
- raise InvalidContext::InvalidVocabMapping, "@value must be an absolute IRI: #{value.inspect}" unless @vocab.absolute?
186
- @vocab
187
+ @vocab = case value
188
+ when /_:/
189
+ value
190
+ when String
191
+ v = as_resource(value)
192
+ raise InvalidContext::InvalidVocabMapping, "@value must be an absolute IRI: #{value.inspect}" if v.uri? && v.relative?
193
+ v
194
+ when nil
195
+ nil
187
196
  else
188
- @vocab = nil
197
+ raise InvalidContext::InvalidVocabMapping, "@value must be a string: #{value.inspect}"
189
198
  end
190
199
  end
191
200
 
@@ -234,7 +243,7 @@ module JSON::LD
234
243
  # Load context document, if it is a string
235
244
  begin
236
245
  # 3.2.1) Set context to the result of resolving value against the base IRI which is established as specified in section 5.1 Establishing a Base URI of [RFC3986]. Only the basic algorithm in section 5.2 of [RFC3986] is used; neither Syntax-Based Normalization nor Scheme-Based Normalization are performed. Characters additionally allowed in IRI references are treated in the same way that unreserved characters are treated in URI references, per section 6.5 of [RFC3987].
237
- context = RDF::URI(result.context_base || result.base || @doc_base).join(context)
246
+ context = RDF::URI(result.context_base || result.base).join(context)
238
247
 
239
248
  raise InvalidContext::RecursiveContextInclusion, "#{context}" if remote_contexts.include?(context)
240
249
  @remote_contexts = @remote_contexts + [context]
@@ -344,9 +353,18 @@ module JSON::LD
344
353
  debug("") {"Hash[#{term.inspect}] = #{value.inspect}"}
345
354
  definition = TermDefinition.new(term)
346
355
 
356
+ if value.has_key?('@type')
357
+ type = value['@type']
358
+ # SPEC FIXME: @type may be nil
359
+ raise InvalidContext::InvalidTypeMapping, "unknown mapping for '@type' to #{type.inspect}" unless type.is_a?(String) || type.nil?
360
+ type = expand_iri(type, :vocab => true, :documentRelative => true, :local_context => local_context, :defined => defined) if type.is_a?(String)
361
+ debug("") {"type_mapping: #{type.inspect}"}
362
+ definition.type_mapping = type
363
+ end
364
+
347
365
  if value.has_key?('@reverse')
348
366
  raise InvalidContext::InvalidReverseProperty, "unexpected key in #{value.inspect}" if
349
- value.keys.any? {|k| ['@id', '@type', '@language'].include?(k)}
367
+ value.keys.any? {|k| %w(@id).include?(k)}
350
368
  raise InvalidContext::InvalidIRIMapping, "expected value of @reverse to be a string" unless
351
369
  value['@reverse'].is_a?(String)
352
370
 
@@ -358,11 +376,13 @@ module JSON::LD
358
376
  :defined => defined)
359
377
  raise InvalidContext::InvalidIRImapping, "non-absolute @reverse IRI: #{definition.id}" unless
360
378
  definition.id.absolute?
361
- definition.type_mapping = '@id'
362
379
 
363
- # If value contains an @container member, set the container mapping of definition to @index if that is the value of the @container member; otherwise an invalid reverse property error has been detected (reverse properties only support index-containers) and processing is aborted.
364
- if (container = value['@container']) && container != '@index'
365
- raise InvalidContext::InvalidReverseProperty, "unknown mapping for '@container' to #{container.inspect}"
380
+ # If value contains an @container member, set the container mapping of definition to its value; if its value is neither @set, nor @index, nor null, an invalid reverse property error has been detected (reverse properties only support set- and index-containers) and processing is aborted.
381
+ if (container = value['@container'])
382
+ raise InvalidContext::InvalidReverseProperty,
383
+ "unknown mapping for '@container' to #{container.inspect}" unless
384
+ ['@set', '@index', nil].include?(container)
385
+ definition.container_mapping = container
366
386
  end
367
387
  definition.reverse_property = true
368
388
  elsif value.has_key?('@id') && value['@id'] != term
@@ -393,15 +413,6 @@ module JSON::LD
393
413
  debug("") {"=> #{definition.id}"}
394
414
  end
395
415
 
396
- if value.has_key?('@type')
397
- type = value['@type']
398
- # SPEC FIXME: @type may be nil
399
- raise InvalidContext::InvalidTypeMapping, "unknown mapping for '@type' to #{type.inspect}" unless type.is_a?(String) || type.nil?
400
- type = expand_iri(type, :vocab => true, :documentRelative => true, :local_context => local_context, :defined => defined) if type.is_a?(String)
401
- debug("") {"type_mapping: #{type.inspect}"}
402
- definition.type_mapping = type
403
- end
404
-
405
416
  if value.has_key?('@container')
406
417
  container = value['@container']
407
418
  raise InvalidContext::InvalidContainerMapping, "unknown mapping for '@container' to #{container.inspect}" unless %w(@list @set @language @index).include?(container)
@@ -445,8 +456,8 @@ module JSON::LD
445
456
  else
446
457
  debug("serlialize: generate context")
447
458
  debug("") {"=> context: #{inspect}"}
448
- ctx = Hash.ordered
449
- ctx['@base'] = base.to_s if base
459
+ ctx = {}
460
+ ctx['@base'] = base.to_s if base && base != doc_base
450
461
  ctx['@language'] = default_language.to_s if default_language
451
462
  ctx['@vocab'] = vocab.to_s if vocab
452
463
 
@@ -460,7 +471,7 @@ module JSON::LD
460
471
  end
461
472
 
462
473
  # Return hash with @context, or empty
463
- r = Hash.ordered
474
+ r = {}
464
475
  r['@context'] = use_context unless use_context.nil? || use_context.empty?
465
476
  r
466
477
  end
@@ -652,9 +663,9 @@ module JSON::LD
652
663
  result = if options[:vocab] && vocab
653
664
  # If vocab is true, and active context has a vocabulary mapping, return the result of concatenating the vocabulary mapping with value.
654
665
  vocab + value
655
- elsif options[:documentRelative] && base = options.fetch(:base, self.base || @doc_base)
666
+ elsif options[:documentRelative] && base = options.fetch(:base, self.base)
656
667
  # Otherwise, if document relative is true, set value to the result of resolving value against the base IRI. Only the basic algorithm in section 5.2 of [RFC3986] is used; neither Syntax-Based Normalization nor Scheme-Based Normalization are performed. Characters additionally allowed in IRI references are treated in the same way that unreserved characters are treated in URI references, per section 6.5 of [RFC3987].
657
- RDF::URI(base).join(value).to_s
668
+ RDF::URI(base).join(value)
658
669
  elsif local_context && RDF::URI(value).relative?
659
670
  # If local context is not null and value is not an absolute IRI, an invalid IRI mapping error has been detected and processing is aborted.
660
671
  raise JSON::LD::InvalidContext::InvalidIRIMapping, "not an absolute IRI: #{value}"
@@ -870,7 +881,7 @@ module JSON::LD
870
881
  {'@id' => value.to_s}
871
882
  when RDF::Literal
872
883
  debug("Literal") {"datatype: #{value.datatype.inspect}"}
873
- res = Hash.ordered
884
+ res = {}
874
885
  if options[:useNativeTypes] && [RDF::XSD.boolean, RDF::XSD.integer, RDF::XSD.double].include?(value.datatype)
875
886
  res['@value'] = value.object
876
887
  res['@type'] = uri(coerce(property)) if coerce(property)
@@ -1116,14 +1127,14 @@ module JSON::LD
1116
1127
  # @return [String]
1117
1128
  # the relative IRI if relative to base, otherwise the absolute IRI.
1118
1129
  def remove_base(iri)
1119
- return iri unless base || @doc_base
1130
+ return iri unless base
1120
1131
  @base_and_parents ||= begin
1121
- u = base || @doc_base
1132
+ u = base
1122
1133
  iri_set = u.to_s.end_with?('/') ? [u.to_s] : []
1123
1134
  iri_set << u.to_s while (u = u.parent)
1124
1135
  iri_set
1125
1136
  end
1126
- b = (base || @doc_base).to_s
1137
+ b = base.to_s
1127
1138
  return iri[b.length..-1] if iri.start_with?(b) && %w(? #).include?(iri[b.length, 1])
1128
1139
 
1129
1140
  @base_and_parents.each_with_index do |b, index|
@@ -81,7 +81,7 @@ module JSON::LD
81
81
  case value
82
82
  when Array
83
83
  depth do
84
- [value].flatten.map do |v|
84
+ value.map do |v|
85
85
  raise ProcessingError::InvalidTypeValue,
86
86
  "@type value must be a string or array of strings: #{v.inspect}" unless v.is_a?(String)
87
87
  context.expand_iri(v, :vocab => true, :documentRelative => true, :quiet => true, :depth => @depth).to_s
@@ -10,11 +10,13 @@ module JSON::LD
10
10
  # @param [Hash{String => Hash}] node_map
11
11
  # map of nodes
12
12
  # @param [String] active_graph
13
- # Graph name for results
13
+ # The name of the currently active graph that the processor should use when processing.
14
+ # @param [String] active_subject
15
+ # The currently active subject that the processor should use when processing.
16
+ # @param [String] active_property
17
+ # The currently active property or keyword that the processor should use when processing.
14
18
  # @param [Array] list
15
19
  # List for saving list elements
16
- # @param [String] id (nil)
17
- # Identifier already associated with element
18
20
  def generate_node_map(element,
19
21
  node_map,
20
22
  active_graph = '@default',
@@ -42,13 +44,9 @@ module JSON::LD
42
44
 
43
45
  # If element has an @type member, perform for each item the following steps:
44
46
  if element.has_key?('@type')
45
- types = [element['@type']].flatten.map do |item|
47
+ types = Array(element['@type']).map do |item|
46
48
  # If item is a blank node identifier, replace it with a newly generated blank node identifier passing item for identifier.
47
- item = namer.get_name(item) if blank_node?(item)
48
-
49
- # If graph has no member item, create it and initialize its value to a JSON object consisting of a single member @id with the value item.
50
- graph[item] ||= {'@id' => item}
51
- item
49
+ blank_node?(item) ? namer.get_name(item) : item
52
50
  end
53
51
 
54
52
  element['@type'] = element['@type'].is_a?(Array) ? types : types.first
@@ -81,7 +79,7 @@ module JSON::LD
81
79
  merge_value(node, active_property, result)
82
80
  else
83
81
  # Otherwise element is a node object, perform the following steps:
84
-
82
+
85
83
  # If element has an @id member, set id to its value and remove the member from element. If id is a blank node identifier, replace it with a newly generated blank node identifier passing id for identifier.
86
84
  # Otherwise, set id to the result of the Generate Blank Node Identifier algorithm passing null for identifier.
87
85
  id = element.delete('@id')
@@ -109,7 +107,7 @@ module JSON::LD
109
107
 
110
108
  # If element has an @type key, append each item of its associated array to the array associated with the @type key of node unless it is already in that array. Finally remove the @type member from element.
111
109
  if element.has_key?('@type')
112
- [element.delete('@type')].flatten.each do |t|
110
+ Array(element.delete('@type')).each do |t|
113
111
  merge_value(node, '@type', t)
114
112
  end
115
113
  end
@@ -32,9 +32,9 @@ module JSON::LD
32
32
  subject = ec.expand_iri(statement.subject).to_s
33
33
  node = node_map[subject] ||= {'@id' => subject}
34
34
 
35
- # If object is an IRI or blank node identifier, does not equal rdf:nil, and node map does not have an object member, create one and initialize its value to a new JSON object consisting of a single member @id whose value is set to object.
35
+ # If object is an IRI or blank node identifier, and node map does not have an object member, create one and initialize its value to a new JSON object consisting of a single member @id whose value is set to object.
36
36
  node_map[statement.object.to_s] ||= {'@id' => statement.object.to_s} unless
37
- statement.object.literal? || statement.object == RDF.nil
37
+ statement.object.literal?
38
38
 
39
39
  # If predicate equals rdf:type, and object is an IRI or blank node identifier, append object to the value of the @type member of node. If no such member exists, create one and initialize it to an array whose only item is object. Finally, continue to the next RDF triple.
40
40
  if statement.predicate == RDF.type && statement.object.resource?
@@ -42,61 +42,64 @@ module JSON::LD
42
42
  next
43
43
  end
44
44
 
45
- # If object equals rdf:nil and predicate does not equal rdf:rest, set value to a new JSON object consisting of a single member @list whose value is set to an empty array.
46
- value = if statement.object == RDF.nil && statement.predicate != RDF.rest
47
- {'@list' => []}
48
- else
49
- ec.expand_value(nil, statement.object, @options)
50
- end
45
+ # Set value to the result of using the RDF to Object Conversion algorithm, passing object and use native types.
46
+ value = ec.expand_value(nil, statement.object, @options)
51
47
 
52
48
  merge_value(node, statement.predicate.to_s, value)
53
49
 
54
- # If object is a blank node identifier and predicate equals neither rdf:first nor rdf:rest, it might represent the head of a RDF list:
55
- if statement.object.node? && ![RDF.first, RDF.rest].include?(statement.predicate)
56
- merge_value(node_map[statement.object.to_s], :usages, value)
50
+ # If object is a blank node identifier or IRI, it might represent the a list node:
51
+ if statement.object.resource?
52
+ # Append a new JSON object consisting of three members, node, property, and value to the usages array. The node member is set to a reference to node, property to predicate, and value to a reference to value.
53
+ merge_value(node_map[statement.object.to_s], :usages, {
54
+ :node => node,
55
+ :property => statement.predicate.to_s,
56
+ :value => value})
57
57
  end
58
58
  end
59
59
 
60
60
  # For each name and graph object in graph map:
61
61
  graph_map.each do |name, graph_object|
62
- subjects = graph_object.keys
63
- subjects.each do |subj|
64
- next unless graph_object.has_key?(subj)
65
- node = graph_object[subj]
66
- next unless node[:usages].is_a?(Array) && node[:usages].length == 1
67
- debug("list head") {node.to_json(JSON_STATE)}
68
- value = node[:usages].first
69
- list, list_nodes, subject = [], [], subj
70
-
71
- while subject != RDF.nil.to_s && list
72
- if node.nil? ||
73
- !blank_node?(node) ||
74
- node.keys.any? {|k| !["@id", :usages, RDF.first.to_s, RDF.rest.to_s].include?(k)} ||
75
- !(f = node[RDF.first.to_s]).is_a?(Array) || f.length != 1 ||
76
- !(r = node[RDF.rest.to_s]).is_a?(Array) || r.length != 1 || !node_reference?(r.first) ||
77
- list_nodes.include?(subject)
78
-
79
- debug("list") {"not valid list element: #{node.to_json(JSON_STATE)}"}
80
- list = nil
81
- else
82
- list << f.first
83
- list_nodes << node['@id']
84
- subject = r.first['@id']
85
- node = graph_object[subject]
86
- debug("list") {"rest: #{node.to_json(JSON_STATE)}"}
87
- list = nil if list_nodes.include?(subject)
88
- end
62
+ next unless nil_var = graph_object[RDF.nil.to_s]
63
+
64
+ # For each item usage in the usages member of nil, perform the following steps:
65
+ nil_var[:usages].each do |usage|
66
+ node, property, head = usage[:node], usage[:property], usage[:value]
67
+ list, list_nodes = [], []
68
+
69
+ # If property equals rdf:rest, the value associated to the usages member of node has exactly 1 entry, node has a rdf:first and rdf:rest property, both of which have as value an array consisting of a single element, and node has no other members apart from an optional @type member whose value is an array with a single item equal to rdf:List, node represents a well-formed list node. Continue with the following steps:
70
+ debug("list element?") {node.to_json(JSON_STATE)}
71
+ while property == RDF.rest.to_s &&
72
+ blank_node?(node) &&
73
+ node.keys.none? {|k| !["@id", '@type', :usages, RDF.first.to_s, RDF.rest.to_s].include?(k)} &&
74
+ Array(node[:usages]).length == 1 &&
75
+ (f = node[RDF.first.to_s]).is_a?(Array) && f.length == 1 &&
76
+ (r = node[RDF.rest.to_s]).is_a?(Array) && r.length == 1 &&
77
+ ((t = node['@type']).nil? || t == [RDF.List.to_s])
78
+ list << Array(node[RDF.first.to_s]).first
79
+ list_nodes << node['@id']
80
+ node_usage = Array(node[:usages]).first
81
+ node, property, head = node_usage[:node], node_usage[:property], node_usage[:value]
82
+ end
83
+
84
+ # If property equals rdf:first, i.e., the detected list is nested inside another list
85
+ if property == RDF.first.to_s
86
+ # and the value of the @id of node equals rdf:nil, i.e., the detected list is empty, continue with the next usage item. The rdf:nil node cannot be converted to a list object as it would result in a list of lists, which isn't supported.
87
+ next if node['@id'] == RDF.nil.to_s
88
+
89
+ # Otherwise, the list consists of at least one item. We preserve the head node and transform the rest of the linked list to a list object
90
+ head_id = head['@id']
91
+ head = graph_object[head_id]
92
+ head = Array(head[RDF.rest.to_s]).first
93
+ list.pop; list_nodes.pop
89
94
  end
90
95
 
91
- next if list.nil?
92
- value.delete('@id')
93
- value['@list'] = list
94
- list_nodes.each {|s| graph_object.delete(s)}
96
+ head.delete('@id')
97
+ head['@list'] = list.reverse
98
+ list_nodes.each {|node_id| graph_object.delete(node_id)}
95
99
  end
96
100
  end
97
101
 
98
102
  result = []
99
- debug("graph_map") {graph_map.to_json(JSON_STATE)}
100
103
  default_graph.keys.sort.each do |subject|
101
104
  node = default_graph[subject]
102
105
  if graph_map.has_key?(subject)
@@ -104,11 +107,11 @@ module JSON::LD
104
107
  graph_map[subject].keys.sort.each do |s|
105
108
  n = graph_map[subject][s]
106
109
  n.delete(:usages)
107
- node['@graph'] << n
110
+ node['@graph'] << n unless node_reference?(n)
108
111
  end
109
112
  end
110
113
  node.delete(:usages)
111
- result << node
114
+ result << node unless node_reference?(node)
112
115
  end
113
116
  debug("fromRDF") {result.to_json(JSON_STATE)}
114
117
  result