rdf-trig 1.0.1 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -71,16 +71,19 @@ module RDF::TriG
71
71
  case token.value
72
72
  when 'A', 'a' then input[:resource] = RDF.type
73
73
  when 'true', 'false' then input[:resource] = RDF::Literal::Boolean.new(token.value)
74
- when '@base', '@prefix' then input[:lang] = token.value[1..-1]
74
+ when '.' then input[:terminated] = true
75
75
  else input[:string] = token.value
76
76
  end
77
77
  end
78
78
 
79
+ terminal(:GRAPH, /graph/i) do |prod, token, input|
80
+ input[:string_value] = token.value
81
+ end
79
82
  terminal(:PREFIX, PREFIX) do |prod, token, input|
80
- input[:string_value] = token.value.downcase
83
+ input[:string_value] = token.value
81
84
  end
82
85
  terminal(:BASE, BASE) do |prod, token, input|
83
- input[:string_value] = token.value.downcase
86
+ input[:string_value] = token.value
84
87
  end
85
88
 
86
89
  terminal(:LANGTAG, LANGTAG) do |prod, token, input|
@@ -88,47 +91,72 @@ module RDF::TriG
88
91
  end
89
92
 
90
93
  # Productions
91
- # [3g] graph defines the basic creation of context
92
- start_production(:graph) do |input, current, callback|
94
+ # [2g] block defines the basic creation of context
95
+ start_production(:block) do |input, current, callback|
93
96
  callback.call(:context, "graph", nil)
94
97
  end
95
- production(:graph) do |input, current, callback|
98
+ production(:block) do |input, current, callback|
96
99
  callback.call(:context, "graph", nil)
97
100
  end
98
101
 
99
- # [4g] graphName
100
- # Normally, just returns the resource, but if called from [3g], also
101
- # sets the context for triples defined within that graph
102
- production(:graphName) do |input, current, callback|
102
+ # [7g] labelOrSubject
103
+ # Sets the context for triples defined within that graph
104
+ production(:labelOrSubject) do |input, current, callback|
103
105
  # If input contains set_graph_iri, use the returned value to set @context
104
- debug("graphName") {"Set graph context to #{current[:resource]}"}
105
- callback.call(:context, "graphName", current[:resource])
106
+ debug(":labelOrSubject") {"Set graph context to #{current[:resource]}"}
107
+ callback.call(:context, "labelOrSubject", current[:resource])
108
+ input[:resource] = current[:resource]
106
109
  end
107
110
 
111
+ # _triplesOrGraph_2 ::= predicateObjectList '.'
112
+ start_production(:_triplesOrGraph_2) do |input, current, callback|
113
+ # Default graph after all
114
+ callback.call(:context, "graph", nil)
115
+ debug("_triplesOrGraph_2") {"subject: #{current[:resource]}"}
116
+ current[:subject] = input[:resource]
117
+ end
108
118
 
109
119
  # Productions
110
120
  # [4] prefixID defines a prefix mapping
111
121
  production(:prefixID) do |input, current, callback|
112
122
  prefix = current[:prefix]
113
123
  iri = current[:resource]
124
+ lexical = current[:string_value]
125
+ terminated = current[:terminated]
114
126
  debug("prefixID") {"Defined prefix #{prefix.inspect} mapping to #{iri.inspect}"}
127
+ if lexical.start_with?('@') && lexical != '@prefix'
128
+ error(:prefixID, "should be downcased")
129
+ elsif lexical == '@prefix'
130
+ error(:prefixID, "directive not terminated") unless terminated
131
+ else
132
+ error(:prefixID, "directive should not be terminated") if terminated
133
+ end
115
134
  prefix(prefix, iri)
116
135
  end
117
136
 
118
137
  # [5] base set base_uri
119
138
  production(:base) do |input, current, callback|
120
139
  iri = current[:resource]
140
+ lexical = current[:string_value]
141
+ terminated = current[:terminated]
121
142
  debug("base") {"Defined base as #{iri}"}
143
+ if lexical.start_with?('@') && lexical != '@base'
144
+ error(:base, "should be downcased")
145
+ elsif lexical == '@base'
146
+ error(:base, "directive not terminated") unless terminated
147
+ else
148
+ error(:base, "directive should not be terminated") if terminated
149
+ end
122
150
  options[:base_uri] = iri
123
151
  end
124
152
 
125
- # [6] triples
126
- start_production(:triples) do |input, current, callback|
153
+ # [52s] triplesBlock
154
+ start_production(:triplesBlock) do |input, current, callback|
127
155
  # Note production as triples for blankNodePropertyList
128
156
  # to set :subject instead of :resource
129
157
  current[:triples] = true
130
158
  end
131
- production(:triples) do |input, current, callback|
159
+ production(:triplesBlock) do |input, current, callback|
132
160
  # Note production as triples for blankNodePropertyList
133
161
  # to set :subject instead of :resource
134
162
  current[:triples] = true
@@ -139,7 +167,7 @@ module RDF::TriG
139
167
  input[:predicate] = current[:resource]
140
168
  end
141
169
 
142
- # [10] subject ::= IRIref | BlankNode | collection
170
+ # [10] subject ::= iri | blank
143
171
  start_production(:subject) do |input, current, callback|
144
172
  current[:triples] = nil
145
173
  end
@@ -0,0 +1,42 @@
1
+ module RDF::TriG
2
+ ##
3
+ # Streaming writer interface
4
+ # @author [Gregg Kellogg](http://greggkellogg.net/)
5
+ module StreamingWriter
6
+ ##
7
+ # Write out a statement, retaining current
8
+ # `subject` and `predicate` to create more compact output
9
+ # @return [void] `self`
10
+ def stream_statement(statement)
11
+ if statement.context != @streaming_context
12
+ stream_epilogue
13
+ if statement.context
14
+ @output.write "#{format_term(statement.context)} {"
15
+ end
16
+ @streaming_context, @streaming_subject, @streaming_predicate = statement.context, statement.subject, statement.predicate
17
+ @output.write "#{format_term(statement.subject)} "
18
+ @output.write "#{format_term(statement.predicate)} "
19
+ elsif statement.subject != @streaming_subject
20
+ @output.write " .\n#{indent(@streaming_subject ? 1 : 0)}"
21
+ @streaming_subject, @streaming_predicate = statement.subject, statement.predicate
22
+ @output.write "#{format_term(statement.subject)} "
23
+ @output.write "#{format_term(statement.predicate)} "
24
+ elsif statement.predicate != @streaming_predicate
25
+ @streaming_predicate = statement.predicate
26
+ @output.write ";\n#{indent(@streaming_subject ? 2 : 1)}#{format_term(statement.predicate)} "
27
+ else
28
+ @output.write ",\n#{indent(@streaming_subject ? 3 : 2)}"
29
+ end
30
+ @output.write("#{format_term(statement.object)}")
31
+ end
32
+
33
+ ##
34
+ # Complete open statements
35
+ # @return [void] `self`
36
+ def stream_epilogue
37
+ @output.puts " }" if @streaming_context
38
+ end
39
+
40
+ private
41
+ end
42
+ end
@@ -1,4 +1,5 @@
1
1
  require 'rdf/turtle'
2
+ require 'rdf/trig/streaming_writer'
2
3
 
3
4
  module RDF::TriG
4
5
  ##
@@ -34,6 +35,13 @@ module RDF::TriG
34
35
  # end
35
36
  # end
36
37
  #
38
+ # @example Serializing RDF statements to a string in streaming mode
39
+ # RDF::TriG::Writer.buffer(:stream => true) do |writer|
40
+ # repo.each_statement do |statement|
41
+ # writer << statement
42
+ # end
43
+ # end
44
+ #
37
45
  # The writer will add prefix definitions, and use them for creating @prefix definitions, and minting QNames
38
46
  #
39
47
  # @example Creating @base and @prefix definitions in output
@@ -48,6 +56,7 @@ module RDF::TriG
48
56
  #
49
57
  # @author [Gregg Kellogg](http://greggkellogg.net/)
50
58
  class Writer < RDF::Turtle::Writer
59
+ include StreamingWriter
51
60
  format RDF::TriG::Format
52
61
 
53
62
  class ContextFilteredRepo
@@ -103,6 +112,8 @@ module RDF::TriG
103
112
  # Maximum depth for recursively defining resources, defaults to 3
104
113
  # @option options [Boolean] :standard_prefixes (false)
105
114
  # Add standard prefixes to @prefixes, if necessary.
115
+ # @option options [Boolean] :stream (false)
116
+ # Do not attempt to optimize graph presentation, suitable for streaming large repositories.
106
117
  # @option options [String] :default_namespace (nil)
107
118
  # URI to use as default namespace, same as `prefixes\[nil\]`
108
119
  # @yield [writer] `self`
@@ -111,6 +122,7 @@ module RDF::TriG
111
122
  # @yield [writer]
112
123
  # @yieldparam [RDF::Writer] writer
113
124
  def initialize(output = $stdout, options = {}, &block)
125
+ reset
114
126
  super do
115
127
  # Set both @repo and @graph to a new repository.
116
128
  # When serializing a context, @graph is changed
@@ -125,45 +137,74 @@ module RDF::TriG
125
137
  end
126
138
  end
127
139
 
140
+
141
+ ##
142
+ # Adds a statement to be serialized
143
+ # @param [RDF::Statement] statement
144
+ # @return [void]
145
+ def write_statement(statement)
146
+ case
147
+ when @options[:stream]
148
+ stream_statement(statement)
149
+ else
150
+ super
151
+ end
152
+ end
153
+
154
+ ##
155
+ # Write out declarations
156
+ # @return [void] `self`
157
+ def write_prologue
158
+ case
159
+ when @options[:stream]
160
+ stream_prologue
161
+ else
162
+ super
163
+ end
164
+ end
165
+
128
166
  ##
129
167
  # Outputs the TriG representation of all stored triples.
130
168
  #
131
169
  # @return [void]
132
170
  # @see #write_triple
133
171
  def write_epilogue
134
- @max_depth = @options[:max_depth] || 3
135
- @base_uri = RDF::URI(@options[:base_uri])
172
+ case
173
+ when @options[:stream]
174
+ stream_epilogue
175
+ else
176
+ @max_depth = @options[:max_depth] || 3
177
+ @base_uri = RDF::URI(@options[:base_uri])
136
178
 
137
- reset
179
+ reset
138
180
 
139
- debug {"\nserialize: repo: #{@repo.size}"}
181
+ debug {"\nserialize: repo: #{@repo.size}"}
140
182
 
141
- preprocess
142
- start_document
183
+ preprocess
184
+ start_document
143
185
 
144
- order_contexts.each do |ctx|
145
- debug {"context: #{ctx.inspect}"}
146
- reset
147
- @depth = 2
186
+ order_contexts.each do |ctx|
187
+ debug {"context: #{ctx.inspect}"}
188
+ reset
189
+ @depth = 2
148
190
 
149
- if ctx
150
- @output.write("\n#{format_value(ctx)} {")
151
- else
152
- @output.write("\n{")
153
- end
191
+ if ctx
192
+ @output.write("\n#{format_value(ctx)} {")
193
+ end
154
194
 
155
- # Restrict view to the particular context
156
- @graph = ContextFilteredRepo.new(@repo, ctx)
195
+ # Restrict view to the particular context
196
+ @graph = ContextFilteredRepo.new(@repo, ctx)
157
197
 
158
- # Pre-process statements again, but in the specified context
159
- @graph.each {|st| preprocess_statement(st)}
160
- order_subjects.each do |subject|
161
- unless is_done?(subject)
162
- statement(subject)
198
+ # Pre-process statements again, but in the specified context
199
+ @graph.each {|st| preprocess_statement(st)}
200
+ order_subjects.each do |subject|
201
+ unless is_done?(subject)
202
+ statement(subject)
203
+ end
163
204
  end
164
- end
165
205
 
166
- @output.puts("}")
206
+ @output.puts("}") if ctx
207
+ end
167
208
  end
168
209
  end
169
210
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rdf-trig
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gregg Kellogg
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-05-30 00:00:00.000000000 Z
11
+ date: 2013-09-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rdf
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - ! '>='
46
46
  - !ruby/object:Gem::Version
47
- version: 1.0.7
47
+ version: 1.0.9
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ! '>='
53
53
  - !ruby/object:Gem::Version
54
- version: 1.0.7
54
+ version: 1.0.9
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: open-uri-cached
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -164,6 +164,7 @@ files:
164
164
  - lib/rdf/trig/format.rb
165
165
  - lib/rdf/trig/meta.rb
166
166
  - lib/rdf/trig/reader.rb
167
+ - lib/rdf/trig/streaming_writer.rb
167
168
  - lib/rdf/trig/version.rb
168
169
  - lib/rdf/trig/writer.rb
169
170
  - lib/rdf/trig.rb
@@ -187,7 +188,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
187
188
  version: '0'
188
189
  requirements: []
189
190
  rubyforge_project: rdf-trig
190
- rubygems_version: 2.0.3
191
+ rubygems_version: 2.0.5
191
192
  signing_key:
192
193
  specification_version: 4
193
194
  summary: TriG reader/writer for Ruby.