json-ld 0.1.3 → 0.1.4

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.
Files changed (78) hide show
  1. data/History.markdown +3 -0
  2. data/VERSION +1 -1
  3. data/bin/jsonld +134 -0
  4. data/lib/json/ld/api.rb +4 -4
  5. data/lib/json/ld/frame.rb +2 -1
  6. data/lib/json/ld/from_rdf.rb +1 -1
  7. data/spec/api_spec.rb +66 -0
  8. data/spec/compact_spec.rb +420 -0
  9. data/spec/evaluation_context_spec.rb +1039 -0
  10. data/spec/expand_spec.rb +625 -0
  11. data/spec/format_spec.rb +71 -0
  12. data/spec/frame_spec.rb +542 -0
  13. data/spec/from_rdf_spec.rb +316 -0
  14. data/spec/matchers.rb +67 -0
  15. data/spec/reader_spec.rb +79 -0
  16. data/spec/spec_helper.rb +56 -0
  17. data/spec/suite_helper.rb +184 -0
  18. data/spec/suite_spec.rb +104 -0
  19. data/spec/support/extensions.rb +10 -0
  20. data/spec/test-files/test-1-automatic.json +10 -0
  21. data/spec/test-files/test-1-compacted.json +10 -0
  22. data/spec/test-files/test-1-context.json +7 -0
  23. data/spec/test-files/test-1-expanded.json +5 -0
  24. data/spec/test-files/test-1-input.json +10 -0
  25. data/spec/test-files/test-1-normalized.json +8 -0
  26. data/spec/test-files/test-1-rdf.ttl +7 -0
  27. data/spec/test-files/test-2-automatic.json +27 -0
  28. data/spec/test-files/test-2-compacted.json +20 -0
  29. data/spec/test-files/test-2-context.json +7 -0
  30. data/spec/test-files/test-2-expanded.json +16 -0
  31. data/spec/test-files/test-2-input.json +20 -0
  32. data/spec/test-files/test-2-normalized.json +32 -0
  33. data/spec/test-files/test-2-rdf.ttl +14 -0
  34. data/spec/test-files/test-3-compacted.json +11 -0
  35. data/spec/test-files/test-3-context.json +8 -0
  36. data/spec/test-files/test-3-expanded.json +10 -0
  37. data/spec/test-files/test-3-input.json +11 -0
  38. data/spec/test-files/test-3-normalized.json +13 -0
  39. data/spec/test-files/test-3-rdf.ttl +7 -0
  40. data/spec/test-files/test-4-automatic.json +10 -0
  41. data/spec/test-files/test-4-compacted.json +10 -0
  42. data/spec/test-files/test-4-context.json +7 -0
  43. data/spec/test-files/test-4-expanded.json +6 -0
  44. data/spec/test-files/test-4-input.json +10 -0
  45. data/spec/test-files/test-4-rdf.ttl +5 -0
  46. data/spec/test-files/test-5-automatic.json +13 -0
  47. data/spec/test-files/test-5-compacted.json +13 -0
  48. data/spec/test-files/test-5-context.json +7 -0
  49. data/spec/test-files/test-5-expanded.json +9 -0
  50. data/spec/test-files/test-5-input.json +13 -0
  51. data/spec/test-files/test-5-rdf.ttl +6 -0
  52. data/spec/test-files/test-6-automatic.json +10 -0
  53. data/spec/test-files/test-6-compacted.json +10 -0
  54. data/spec/test-files/test-6-context.json +7 -0
  55. data/spec/test-files/test-6-expanded.json +10 -0
  56. data/spec/test-files/test-6-input.json +10 -0
  57. data/spec/test-files/test-6-rdf.ttl +5 -0
  58. data/spec/test-files/test-7-automatic.json +20 -0
  59. data/spec/test-files/test-7-compacted.json +23 -0
  60. data/spec/test-files/test-7-context.json +4 -0
  61. data/spec/test-files/test-7-expanded.json +20 -0
  62. data/spec/test-files/test-7-input.json +23 -0
  63. data/spec/test-files/test-7-rdf.ttl +13 -0
  64. data/spec/test-files/test-8-automatic.json +1 -0
  65. data/spec/test-files/test-8-compacted.json +34 -0
  66. data/spec/test-files/test-8-context.json +11 -0
  67. data/spec/test-files/test-8-expanded.json +24 -0
  68. data/spec/test-files/test-8-frame.json +18 -0
  69. data/spec/test-files/test-8-framed.json +29 -0
  70. data/spec/test-files/test-8-input.json +30 -0
  71. data/spec/test-files/test-8-rdf.ttl +15 -0
  72. data/spec/test-files/test-9-compacted.json +20 -0
  73. data/spec/test-files/test-9-context.json +13 -0
  74. data/spec/test-files/test-9-expanded.json +14 -0
  75. data/spec/test-files/test-9-input.json +12 -0
  76. data/spec/to_rdf_spec.rb +640 -0
  77. data/spec/writer_spec.rb +161 -0
  78. metadata +150 -22
data/History.markdown CHANGED
@@ -1,3 +1,6 @@
1
+ === 0.1.4
2
+ * Added bin/jsonld for command-line manipulation of JSON-LD files and to perform RDF transformations.
3
+
1
4
  === 0.1.3
2
5
  * Progress release syncing with the spec. Most expansion and compaction tests pass. RDF is okay, framing has many issues.
3
6
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.3
1
+ 0.1.4
data/bin/jsonld ADDED
@@ -0,0 +1,134 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", 'lib')))
4
+ begin
5
+ require 'linkeddata'
6
+ rescue LoadError
7
+ end
8
+ require 'json/ld'
9
+ require 'getoptlong'
10
+ require 'open-uri'
11
+
12
+ def run(input, options)
13
+ reader_class = RDF::Reader.for(options[:input_format].to_sym)
14
+ raise "Reader not found for #{options[:input_format]}" unless reader_class
15
+
16
+ # Override default (or specified) output format when framing
17
+ options[:format] = :jsonld if options[:compact] || options[:frame]
18
+
19
+ # If input format is not JSON-LD, transform input to JSON-LD first
20
+ if options[:format] == :jsonld && options[:input_format] != :jsonld
21
+ r = reader_class.new(input, options[:parser_options])
22
+ g = RDF::Repository.new << r
23
+ input = JSON::LD::API.fromRDF(g)
24
+ end
25
+
26
+ prefixes = {}
27
+ start = Time.new
28
+ if options[:expand]
29
+ output = JSON::LD::API.expand(input, options[:context], nil, options)
30
+ secs = Time.new - start
31
+ options[:output].puts output.to_json(JSON::LD::JSON_STATE)
32
+ STDERR.puts "Expanded in #{secs} seconds." unless options[:quiet]
33
+ elsif options[:compact]
34
+ output = JSON::LD::API.compact(input, options[:context], nil, options)
35
+ secs = Time.new - start
36
+ options[:output].puts output.to_json(JSON::LD::JSON_STATE)
37
+ STDERR.puts "Compacted in #{secs} seconds." unless options[:quiet]
38
+ elsif options[:frame]
39
+ output = JSON::LD::API.frame(input, options[:frame], nil, options)
40
+ secs = Time.new - start
41
+ options[:output].puts output.to_json(JSON::LD::JSON_STATE)
42
+ STDERR.puts "Framed in #{secs} seconds." unless options[:quiet]
43
+ else
44
+ r = reader_class.new(input, options[:parser_options])
45
+ g = RDF::Repository.new << r
46
+ secs = Time.new - start
47
+ num = g.count
48
+ parser_options = options[:parser_options].merge(:prefixes => r.prefixes, :standard_prefixes => true)
49
+ options[:output].puts g.dump(options[:output_format], parser_options)
50
+ STDERR.puts "\nParsed #{num} statements in #{secs} seconds @ #{num/secs} statements/second." unless options[:quiet]
51
+ end
52
+ rescue
53
+ fname = input.respond_to?(:path) ? input.path : "-stdin-"
54
+ STDERR.puts("Error in #{fname}")
55
+ raise
56
+ end
57
+
58
+ parser_options = {
59
+ :base => "",
60
+ :progress => false,
61
+ :validate => false,
62
+ :strict => false,
63
+ }
64
+
65
+ options = {
66
+ :parser_options => parser_options,
67
+ :output => STDOUT,
68
+ :output_format => :turtle,
69
+ :input_format => :jsonld,
70
+ }
71
+ input = nil
72
+
73
+ OPT_ARGS = [
74
+ ["--dbg", GetoptLong::NO_ARGUMENT, "Turn on verbose debugging"],
75
+ ["--compact", GetoptLong::NO_ARGUMENT, "Compact document, using --context"],
76
+ ["--context", GetoptLong::REQUIRED_ARGUMENT,"Context to apply for expand, compact and converting from RDF"],
77
+ ["--evaluate","-e", GetoptLong::REQUIRED_ARGUMENT,"Evaluate argument as a JSON-LD document"],
78
+ ["--expand", GetoptLong::NO_ARGUMENT, "Expand document, using an optional --context"],
79
+ ["--format", GetoptLong::REQUIRED_ARGUMENT,"Specify output format when converting to RDF"],
80
+ ["--frame", GetoptLong::REQUIRED_ARGUMENT,"Frame document, using the file or URL as a frame specification"],
81
+ ["--input-format", GetoptLong::REQUIRED_ARGUMENT,"Format of the input document, when converting from RDF."],
82
+ ["--output", "-o", GetoptLong::REQUIRED_ARGUMENT,"Output to the specified file path"],
83
+ ["--parse-only", GetoptLong::NO_ARGUMENT, "Parse the document for well-formedness only"],
84
+ ["--quiet", GetoptLong::NO_ARGUMENT, "Supress most output other than progress indicators"],
85
+ ["--uri", GetoptLong::REQUIRED_ARGUMENT,"URI to be used as the document base"],
86
+ ["--verbose", GetoptLong::NO_ARGUMENT, "Detail on execution"],
87
+ ["--help", "-?", GetoptLong::NO_ARGUMENT, "This message"]
88
+ ]
89
+ def usage
90
+ STDERR.puts %{Usage: #{$0} [options] file ...}
91
+ width = OPT_ARGS.map do |o|
92
+ l = o.first.length
93
+ l += o[1].length + 2 if o[1].is_a?(String)
94
+ l
95
+ end.max
96
+ OPT_ARGS.each do |o|
97
+ s = " %-*s " % [width, (o[1].is_a?(String) ? "#{o[0,2].join(', ')}" : o[0])]
98
+ s += o.last
99
+ STDERR.puts s
100
+ end
101
+ exit(1)
102
+ end
103
+
104
+
105
+ opts = GetoptLong.new(*OPT_ARGS.map {|o| o[0..-2]})
106
+
107
+ opts.each do |opt, arg|
108
+ case opt
109
+ when '--dbg' then parser_options[:debug] = ::JSON::LD::debug = true
110
+ when '--compact' then options[:compact] = true
111
+ when '--context' then options[:context] = arg
112
+ when '--execute' then input = arg
113
+ when '--expand' then options[:expand] = true
114
+ when '--format' then options[:output_format] = arg.to_sym
115
+ when '--frame' then options[:frame] = arg
116
+ when '--input-format' then options[:input_format] = arg.to_sym
117
+ when '--output' then options[:output] = File.open(arg, "w")
118
+ when '--parse-only' then options[:parse_only] = true
119
+ when '--quiet' then options[:quiet] = true
120
+ when '--uri' then parser_options[:base] = arg
121
+ when '--verbose' then $verbose = true
122
+ when '--help' then usage
123
+ end
124
+ end
125
+
126
+ if ARGV.empty?
127
+ s = input ? input : $stdin.read
128
+ run(StringIO.new(s), options)
129
+ else
130
+ ARGV.each do |file|
131
+ run(Kernel.open(file), options)
132
+ end
133
+ end
134
+ puts
data/lib/json/ld/api.rb CHANGED
@@ -129,7 +129,7 @@ module JSON::LD
129
129
 
130
130
  # 1) Perform the Expansion Algorithm on the JSON-LD input.
131
131
  # This removes any existing context to allow the given context to be cleanly applied.
132
- expanded = API.expand(input, nil, nil, options)
132
+ expanded = API.expand(input, nil, nil, options.merge(:debug => nil))
133
133
 
134
134
  API.new(expanded, context, options) do
135
135
  debug(".compact") {"expanded input: #{expanded.to_json(JSON_STATE)}"}
@@ -215,9 +215,9 @@ module JSON::LD
215
215
 
216
216
  # Initialize input using frame as context
217
217
  API.new(expanded_input, nil, options) do
218
- debug(".frame") {"context from frame: #{context.inspect}"}
219
- debug(".frame") {"expanded frame: #{expanded_frame.to_json(JSON_STATE)}"}
220
- debug(".frame") {"expanded input: #{value.to_json(JSON_STATE)}"}
218
+ #debug(".frame") {"context from frame: #{context.inspect}"}
219
+ #debug(".frame") {"expanded frame: #{expanded_frame.to_json(JSON_STATE)}"}
220
+ #debug(".frame") {"expanded input: #{value.to_json(JSON_STATE)}"}
221
221
 
222
222
  # Get framing subjects from expanded input, replacing Blank Node identifiers as necessary
223
223
  @subjects = Hash.ordered
data/lib/json/ld/frame.rb CHANGED
@@ -343,7 +343,8 @@ module JSON::LD
343
343
 
344
344
  # Return value of @name in frame, or default from state if it doesn't exist
345
345
  def get_frame_flag(state, frame, name)
346
- !!(frame.fetch("@#{name}", [state[name.to_sym]]).first)
346
+ value = frame.fetch("@#{name}", [state[name.to_sym]]).first
347
+ !!(value?(value) ? value['@value'] : value)
347
348
  end
348
349
 
349
350
  ##
@@ -8,7 +8,7 @@ module JSON::LD
8
8
  # Generate a JSON-LD array representation from an array of `RDF::Statement`.
9
9
  # Representation is in expanded form
10
10
  #
11
- # @param [Array<RDF::Statement>] input
11
+ # @param [Array<RDF::Statement>, RDF::Enumerable] input
12
12
  # @return [Array<Hash>] the JSON-LD document in normalized form
13
13
  def from_statements(input)
14
14
  defaultGraph = {:subjects => {}, :listMap => {}, :name => ''}
data/spec/api_spec.rb ADDED
@@ -0,0 +1,66 @@
1
+ # coding: utf-8
2
+ $:.unshift "."
3
+ require 'spec_helper'
4
+
5
+ describe JSON::LD::API do
6
+ before(:each) { @debug = []}
7
+
8
+ context "callbacks" do
9
+ describe ".compact" do
10
+ it "needs to be implemented"
11
+ end
12
+
13
+ describe ".expand" do
14
+ it "needs to be implemented"
15
+ end
16
+
17
+ describe ".frame" do
18
+ it "needs to be implemented"
19
+ end
20
+
21
+ describe ".fromRDF" do
22
+ it "needs to be implemented"
23
+ end
24
+
25
+ describe ".toRDF" do
26
+ it "needs to be implemented"
27
+ end
28
+ end
29
+
30
+ context "Test Files" do
31
+ Dir.glob(File.expand_path(File.join(File.dirname(__FILE__), 'test-files/*-input.*'))) do |filename|
32
+ test = File.basename(filename).sub(/-input\..*$/, '')
33
+ frame = filename.sub(/-input\..*$/, '-frame.json')
34
+ framed = filename.sub(/-input\..*$/, '-framed.json')
35
+ compacted = filename.sub(/-input\..*$/, '-compacted.json')
36
+ context = filename.sub(/-input\..*$/, '-context.json')
37
+ expanded = filename.sub(/-input\..*$/, '-expanded.json')
38
+ automatic = filename.sub(/-input\..*$/, '-automatic.json')
39
+ ttl = filename.sub(/-input\..*$/, '-rdf.ttl')
40
+
41
+ context test do
42
+ before(:all) do
43
+ end
44
+
45
+ it "expands" do
46
+ jld = JSON::LD::API.expand(File.open(filename), (File.open(context) if context), nil, :debug => @debug)
47
+ jld.should produce(JSON.load(File.open(expanded)), @debug)
48
+ end if File.exist?(expanded)
49
+
50
+ it "compacts" do
51
+ jld = JSON::LD::API.compact(File.open(filename), File.open(context), nil, :debug => @debug)
52
+ jld.should produce(JSON.load(File.open(compacted)), @debug)
53
+ end if File.exist?(compacted) && File.exist?(context)
54
+
55
+ it "frame" do
56
+ jld = JSON::LD::API.frame(File.open(filename), File.open(frame), nil, :debug => @debug)
57
+ jld.should produce(JSON.load(File.open(framed)), @debug)
58
+ end if File.exist?(framed) && File.exist?(frame)
59
+
60
+ it "toRDF" do
61
+ RDF::Graph.load(filename, :debug => @debug).should be_equivalent_graph(RDF::Graph.load(ttl), :trace => @debug)
62
+ end if File.exist?(ttl)
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,420 @@
1
+ # coding: utf-8
2
+ $:.unshift "."
3
+ require 'spec_helper'
4
+
5
+ describe JSON::LD::API do
6
+ before(:each) { @debug = []}
7
+
8
+ describe ".compact" do
9
+ {
10
+ "prefix" => {
11
+ :input => {
12
+ "@id" => "http://example.com/a",
13
+ "http://example.com/b" => {"@id" => "http://example.com/c"}
14
+ },
15
+ :context => {"ex" => "http://example.com/"},
16
+ :output => {
17
+ "@context" => {"ex" => "http://example.com/"},
18
+ "@id" => "ex:a",
19
+ "ex:b" => {"@id" => "ex:c"}
20
+ }
21
+ },
22
+ "term" => {
23
+ :input => {
24
+ "@id" => "http://example.com/a",
25
+ "http://example.com/b" => {"@id" => "http://example.com/c"}
26
+ },
27
+ :context => {"b" => "http://example.com/b"},
28
+ :output => {
29
+ "@context" => {"b" => "http://example.com/b"},
30
+ "@id" => "http://example.com/a",
31
+ "b" => {"@id" => "http://example.com/c"}
32
+ }
33
+ },
34
+ "integer value" => {
35
+ :input => {
36
+ "@id" => "http://example.com/a",
37
+ "http://example.com/b" => {"@value" => 1}
38
+ },
39
+ :context => {"b" => "http://example.com/b"},
40
+ :output => {
41
+ "@context" => {"b" => "http://example.com/b"},
42
+ "@id" => "http://example.com/a",
43
+ "b" => 1
44
+ }
45
+ },
46
+ "boolean value" => {
47
+ :input => {
48
+ "@id" => "http://example.com/a",
49
+ "http://example.com/b" => {"@value" => true}
50
+ },
51
+ :context => {"b" => "http://example.com/b"},
52
+ :output => {
53
+ "@context" => {"b" => "http://example.com/b"},
54
+ "@id" => "http://example.com/a",
55
+ "b" => true
56
+ }
57
+ },
58
+ "@id" => {
59
+ :input => {"@id" => "http://example.org/test#example"},
60
+ :context => {},
61
+ :output => {"@id" => "http://example.org/test#example"}
62
+ },
63
+ "@id coercion" => {
64
+ :input => {
65
+ "@id" => "http://example.com/a",
66
+ "http://example.com/b" => {"@id" => "http://example.com/c"}
67
+ },
68
+ :context => {"b" => {"@id" => "http://example.com/b", "@type" => "@id"}},
69
+ :output => {
70
+ "@context" => {"b" => {"@id" => "http://example.com/b", "@type" => "@id"}},
71
+ "@id" => "http://example.com/a",
72
+ "b" => "http://example.com/c"
73
+ }
74
+ },
75
+ "xsd:date coercion" => {
76
+ :input => {
77
+ "http://example.com/b" => {"@value" => "2012-01-04", "@type" => RDF::XSD.date.to_s}
78
+ },
79
+ :context => {
80
+ "xsd" => RDF::XSD.to_s,
81
+ "b" => {"@id" => "http://example.com/b", "@type" => "xsd:date"}
82
+ },
83
+ :output => {
84
+ "@context" => {
85
+ "xsd" => RDF::XSD.to_s,
86
+ "b" => {"@id" => "http://example.com/b", "@type" => "xsd:date"}
87
+ },
88
+ "b" => "2012-01-04"
89
+ }
90
+ },
91
+ "@list coercion" => {
92
+ :input => {
93
+ "http://example.com/b" => {"@list" => ["c", "d"]}
94
+ },
95
+ :context => {"b" => {"@id" => "http://example.com/b", "@container" => "@list"}},
96
+ :output => {
97
+ "@context" => {"b" => {"@id" => "http://example.com/b", "@container" => "@list"}},
98
+ "b" => ["c", "d"]
99
+ }
100
+ },
101
+ "@list coercion (integer)" => {
102
+ :input => {
103
+ "http://example.com/term" => [
104
+ {"@list" => [1]},
105
+ ]
106
+ },
107
+ :context => {
108
+ "term4" => {"@id" => "http://example.com/term", "@container" => "@list"},
109
+ "@language" => "de"
110
+ },
111
+ :output => {
112
+ "@context" => {
113
+ "term4" => {"@id" => "http://example.com/term", "@container" => "@list"},
114
+ "@language" => "de"
115
+ },
116
+ "term4" => [1],
117
+ }
118
+ },
119
+ "@set coercion" => {
120
+ :input => {
121
+ "http://example.com/b" => {"@set" => ["c"]}
122
+ },
123
+ :context => {"b" => {"@id" => "http://example.com/b", "@container" => "@set"}},
124
+ :output => {
125
+ "@context" => {"b" => {"@id" => "http://example.com/b", "@container" => "@set"}},
126
+ "b" => ["c"]
127
+ }
128
+ },
129
+ "empty @set coercion" => {
130
+ :input => {
131
+ "http://example.com/b" => []
132
+ },
133
+ :context => {"b" => {"@id" => "http://example.com/b", "@container" => "@set"}},
134
+ :output => {
135
+ "@context" => {"b" => {"@id" => "http://example.com/b", "@container" => "@set"}},
136
+ "b" => []
137
+ }
138
+ },
139
+ "empty term" => {
140
+ :input => {
141
+ "@id" => "http://example.com/",
142
+ "@type" => "#{RDF::RDFS.Resource}"
143
+ },
144
+ :context => {"" => "http://example.com/"},
145
+ :output => {
146
+ "@context" => {"" => "http://example.com/"},
147
+ "@id" => "",
148
+ "@type" => "#{RDF::RDFS.Resource}"
149
+ },
150
+ },
151
+ "@type with string @id" => {
152
+ :input => {
153
+ "@id" => "http://example.com/",
154
+ "@type" => "#{RDF::RDFS.Resource}"
155
+ },
156
+ :context => {},
157
+ :output => {
158
+ "@id" => "http://example.com/",
159
+ "@type" => "#{RDF::RDFS.Resource}"
160
+ },
161
+ },
162
+ "@type with array @id" => {
163
+ :input => {
164
+ "@id" => "http://example.com/",
165
+ "@type" => ["#{RDF::RDFS.Resource}"]
166
+ },
167
+ :context => {},
168
+ :output => {
169
+ "@id" => "http://example.com/",
170
+ "@type" => "#{RDF::RDFS.Resource}"
171
+ },
172
+ },
173
+ "default language" => {
174
+ :input => {
175
+ "http://example.com/term" => [
176
+ "v5",
177
+ {"@value" => "plain literal"}
178
+ ]
179
+ },
180
+ :context => {
181
+ "term5" => {"@id" => "http://example.com/term", "@language" => nil},
182
+ "@language" => "de"
183
+ },
184
+ :output => {
185
+ "@context" => {
186
+ "term5" => {"@id" => "http://example.com/term", "@language" => nil},
187
+ "@language" => "de"
188
+ },
189
+ "term5" => [ "v5", "plain literal" ]
190
+ }
191
+ },
192
+ }.each_pair do |title, params|
193
+ it title do
194
+ jld = JSON::LD::API.compact(params[:input], params[:context], nil, :debug => @debug)
195
+ jld.should produce(params[:output], @debug)
196
+ end
197
+ end
198
+
199
+ context "keyword aliasing" do
200
+ {
201
+ "@id" => {
202
+ :input => {
203
+ "@id" => "",
204
+ "@type" => "#{RDF::RDFS.Resource}"
205
+ },
206
+ :context => {"id" => "@id"},
207
+ :output => {
208
+ "@context" => {"id" => "@id"},
209
+ "id" => "",
210
+ "@type" => "#{RDF::RDFS.Resource}"
211
+ }
212
+ },
213
+ "@type" => {
214
+ :input => {
215
+ "@type" => RDF::RDFS.Resource.to_s,
216
+ "http://example.org/foo" => {"@value" => "bar", "@type" => "http://example.com/type"}
217
+ },
218
+ :context => {"type" => "@type"},
219
+ :output => {
220
+ "@context" => {"type" => "@type"},
221
+ "type" => RDF::RDFS.Resource.to_s,
222
+ "http://example.org/foo" => {"@value" => "bar", "type" => "http://example.com/type"}
223
+ }
224
+ },
225
+ "@language" => {
226
+ :input => {
227
+ "http://example.org/foo" => {"@value" => "bar", "@language" => "baz"}
228
+ },
229
+ :context => {"language" => "@language"},
230
+ :output => {
231
+ "@context" => {"language" => "@language"},
232
+ "http://example.org/foo" => {"@value" => "bar", "language" => "baz"}
233
+ }
234
+ },
235
+ "@value" => {
236
+ :input => {
237
+ "http://example.org/foo" => {"@value" => "bar", "@language" => "baz"}
238
+ },
239
+ :context => {"literal" => "@value"},
240
+ :output => {
241
+ "@context" => {"literal" => "@value"},
242
+ "http://example.org/foo" => {"literal" => "bar", "@language" => "baz"}
243
+ }
244
+ },
245
+ "@list" => {
246
+ :input => {
247
+ "http://example.org/foo" => {"@list" => ["bar"]}
248
+ },
249
+ :context => {"list" => "@list"},
250
+ :output => {
251
+ "@context" => {"list" => "@list"},
252
+ "http://example.org/foo" => {"list" => ["bar"]}
253
+ }
254
+ },
255
+ }.each do |title, params|
256
+ it title do
257
+ jld = JSON::LD::API.compact(params[:input], params[:context], nil, :debug => @debug)
258
+ jld.should produce(params[:output], @debug)
259
+ end
260
+ end
261
+ end
262
+
263
+ context "term selection" do
264
+ {
265
+ #"Uses term with nil language when two terms conflict on language" => {
266
+ # :input => [{
267
+ # "http://example.com/term" => {"@value" => "v1", "@language" => nil}
268
+ # }],
269
+ # :context => {
270
+ # "term5" => {"@id" => "http://example.com/term","@language" => nil},
271
+ # "@language" => "de"
272
+ # },
273
+ # :output => {
274
+ # "@context" => {
275
+ # "term5" => {"@id" => "http://example.com/term","@language" => nil},
276
+ # "@language" => "de"
277
+ # },
278
+ # "term5" => "v1",
279
+ # }
280
+ #},
281
+ "Uses subject alias" => {
282
+ :input => [{
283
+ "@id" => "http://example.com/id1"
284
+ }],
285
+ :context => {
286
+ "id1" => "http://example.com/id1",
287
+ "@language" => "de"
288
+ },
289
+ :output => {
290
+ "@context" => {
291
+ "id1" => "http://example.com/id1",
292
+ "@language" => "de"
293
+ },
294
+ "@id" => "id1",
295
+ }
296
+ },
297
+ "Allows IRI to be aliased to null, but still output term using IRI" => {
298
+ :context => {
299
+ "http://example.com/comment" => nil,
300
+ "comment_en" => {"@id" => "http://example.com/comment", "@language" => "en"}
301
+ },
302
+ :input => [{
303
+ "http://example.com/comment" => [
304
+ {"@value" => "comment in english", "@language" => "en"},
305
+ {"@value" => "commentar auf deutsch", "@language" => "de"},
306
+ {"@value" => "日本語でのコメント", "@language" => "ja"},
307
+ ]
308
+ }],
309
+ :output => {
310
+ "@context" => {
311
+ "http://example.com/comment" => nil,
312
+ "comment_en" => {"@id" => "http://example.com/comment", "@language" => "en"}
313
+ },
314
+ "comment_en" => "comment in english",
315
+ }
316
+ },
317
+ }.each_pair do |title, params|
318
+ it title do
319
+ jld = JSON::LD::API.compact(params[:input], params[:context], nil, :debug => @debug)
320
+ jld.should produce(params[:output], @debug)
321
+ end
322
+ end
323
+ end
324
+
325
+ context "context as value" do
326
+ it "includes the context in the output document" do
327
+ ctx = {
328
+ "foo" => "http://example.com/"
329
+ }
330
+ input = {
331
+ "http://example.com/" => "bar"
332
+ }
333
+ expected = {
334
+ "@context" => {
335
+ "foo" => "http://example.com/"
336
+ },
337
+ "foo" => "bar"
338
+ }
339
+ jld = JSON::LD::API.compact(input, ctx, nil, :debug => @debug, :validate => true)
340
+ jld.should produce(expected, @debug)
341
+ end
342
+ end
343
+
344
+ context "context as reference" do
345
+ it "uses referenced context" do
346
+ ctx = StringIO.new(%q({"@context": {"b": "http://example.com/b"}}))
347
+ input = {
348
+ "http://example.com/b" => "c"
349
+ }
350
+ expected = {
351
+ "@context" => "http://example.com/context",
352
+ "b" => "c"
353
+ }
354
+ RDF::Util::File.stub(:open_file).with("http://example.com/context").and_yield(ctx)
355
+ jld = JSON::LD::API.compact(input, "http://example.com/context", nil, :debug => @debug, :validate => true)
356
+ jld.should produce(expected, @debug)
357
+ end
358
+ end
359
+
360
+ context "@graph" do
361
+ {
362
+ "Uses @graph given mutliple inputs" => {
363
+ :input => [
364
+ {"http://example.com/foo" => ["foo"]},
365
+ {"http://example.com/bar" => ["bar"]}
366
+ ],
367
+ :context => {"ex" => "http://example.com/"},
368
+ :output => {
369
+ "@context" => {"ex" => "http://example.com/"},
370
+ "@graph" => [
371
+ {"ex:foo" => "foo"},
372
+ {"ex:bar" => "bar"}
373
+ ]
374
+ }
375
+ },
376
+ "Uses expanded subject definitions for subject references" => {
377
+ :input => [
378
+ {"@id" => "http://example.com/foo"},
379
+ {"@id" => "http://example.com/bar"}
380
+ ],
381
+ :context => {"ex" => "http://example.com/"},
382
+ :output => {
383
+ "@context" => {"ex" => "http://example.com/"},
384
+ "@graph" => [
385
+ {"@id" => "ex:foo"},
386
+ {"@id" => "ex:bar"}
387
+ ]
388
+ }
389
+ },
390
+ }.each_pair do |title, params|
391
+ it title do
392
+ jld = JSON::LD::API.compact(params[:input], params[:context], nil, :debug => @debug)
393
+ jld.should produce(params[:output], @debug)
394
+ end
395
+ end
396
+ end
397
+
398
+ context "exceptions" do
399
+ {
400
+ "@list containing @list" => {
401
+ :input => {
402
+ "http://example.org/foo" => {"@list" => [{"@list" => ["baz"]}]}
403
+ },
404
+ :exception => JSON::LD::ProcessingError::ListOfLists
405
+ },
406
+ "@list containing @list (with coercion)" => {
407
+ :input => {
408
+ "@context" => {"http://example.org/foo" => {"@container" => "@list"}},
409
+ "http://example.org/foo" => [{"@list" => ["baz"]}]
410
+ },
411
+ :exception => JSON::LD::ProcessingError::ListOfLists
412
+ },
413
+ }.each do |title, params|
414
+ it title do
415
+ lambda {JSON::LD::API.compact(params[:input], {}, nil)}.should raise_error(params[:exception])
416
+ end
417
+ end
418
+ end
419
+ end
420
+ end