json-ld 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
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