rdf 1.0.3 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ YjI3YmJmYTZkOGMwMTc2M2VkYTY4YWFiZGQ2YWRlN2E0NmQ5YzIxOQ==
5
+ data.tar.gz: !binary |-
6
+ NmU0NTA4ODAwNTNkNzJmMWQ1M2U3M2IyODFiNjJkYjRhM2ZiNjM2ZA==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ NTM5MDM3NjEzMWZhZTYwMjg1MGZjOGY5OTY4ODMyNDIxNjZjOTJiYTdiZDhk
10
+ YzAyZGUyYzllYjU1ZWZkMjM4NzEzMWU4NzViNGI0ZGI4YWMzZWEyZWJlZTkz
11
+ MzRjOTgyMzE1ZWZjN2UyYTIwZGM5ZWI4ZDRjYjhmODg0MGY5ZGM=
12
+ data.tar.gz: !binary |-
13
+ ZTA3MDBiYzUyYTBlYjJlNTk1Njg5NDYwNzI5ZTY3MGIzNjU5NmEyMjlkZTVl
14
+ MzQ4MTFjMmQyZTE1NDgwODc0ZTk4YThlYzRmYjJmOTBhYjdlYzQxOGFiZTg1
15
+ Y2MxOTQ4NDBhNzg3YzNmYjIwNWIwNjUyYTNiYzE3MzEzZTAwMzI=
data/README CHANGED
@@ -115,6 +115,23 @@ A specific sub-type of Writer can also be invoked directly:
115
115
 
116
116
  graph.dump(:nquads)
117
117
 
118
+ ## Reader/Writer convenience methods
119
+ {RDF::Enumerable} implements `to_{format}` for each available instance of {RDF::Reader}.
120
+ For example, if `rdf/turtle` is loaded, this allows the following:
121
+
122
+ graph = RDF::Graph.new << [:hello, RDF::DC.title, "Hello, world!"]
123
+ graph.to_ttl
124
+
125
+ Similarly, {RDF::Mutable} implements `from_{format}` for each available instance
126
+ of {RDF::Writer}. For example:
127
+
128
+ graph = RDF::Graph.new
129
+ graph.from_ttl("[ a <http://www.w3.org/1999/02/22-rdf-syntax-ns#Resource>]")
130
+
131
+ Note that no prefixes are loaded automatically, however they can be provided as arguments:
132
+
133
+ graph.from_ttl("[ a rdf:Resource]", :prefixes => {:rdf => RDF.to_uri})
134
+
118
135
  ### Querying RDF data using basic graph patterns (BGPs)
119
136
 
120
137
  require 'rdf/ntriples'
@@ -317,6 +334,7 @@ follows:
317
334
 
318
335
  * Do your best to adhere to the existing coding conventions and idioms.
319
336
  * Don't use hard tabs, and don't leave trailing whitespace on any line.
337
+ Before committing, run `git diff --check` to make sure of this.
320
338
  * Do document every method you add using [YARD][] annotations. Read the
321
339
  [tutorial][YARD-GS] or just look at the existing code for examples.
322
340
  * Don't touch the `.gemspec` or `VERSION` files. If you need to change them,
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.3
1
+ 1.0.4
@@ -181,29 +181,55 @@ module RDF
181
181
  end
182
182
 
183
183
  ##
184
- # Returns the set of format symbols for loaded RDF::Reader subclasses.
184
+ # Returns the set of format symbols for available RDF::Reader subclasses.
185
185
  #
186
186
  # @example
187
187
  #
188
- # formats = RDF::Format.reader_symbols
189
- # format = RDF::Format.for(formats.first)
188
+ # symbols = RDF::Format.reader_symbols
189
+ # format = RDF::Format.for(symbols.first)
190
190
  #
191
191
  # @return [Array<Symbol>]
192
192
  def self.reader_symbols
193
- RDF::Format.each.to_a.map(&:reader).compact.map(&:to_sym).uniq
193
+ @@readers.keys.compact.map(&:to_sym).uniq
194
194
  end
195
195
 
196
196
  ##
197
- # Returns the set of format symbols for loaded RDF::Writer subclasses.
197
+ # Returns the set of content types for available RDF::Reader subclasses.
198
198
  #
199
199
  # @example
200
200
  #
201
- # formats = RDF::Format.writer_symbols
202
- # format = RDF::Format.for(formats.first)
201
+ # content_types = RDF::Format.reader_types
202
+ # format = RDF::Format.for(:content_type => content_types.first)
203
+ #
204
+ # @return [Array<String>]
205
+ def self.reader_types
206
+ reader_symbols.map {|s| RDF::Format.for(s).content_type}.flatten.uniq
207
+ end
208
+
209
+ ##
210
+ # Returns the set of format symbols for available RDF::Writer subclasses.
211
+ #
212
+ # @example
213
+ #
214
+ # symbols = RDF::Format.writer_symbols
215
+ # format = RDF::Format.for(symbols.first)
203
216
  #
204
217
  # @return [Array<Symbol>]
205
218
  def self.writer_symbols
206
- RDF::Format.each.to_a.map(&:writer).compact.map(&:to_sym).uniq
219
+ @@writers.keys.compact.map(&:to_sym).uniq
220
+ end
221
+
222
+ ##
223
+ # Returns the set of content types for available RDF::Writer subclasses.
224
+ #
225
+ # @example
226
+ #
227
+ # content_types = RDF::Format.writer_types
228
+ # format = RDF::Format.for(:content_type => content_types.first)
229
+ #
230
+ # @return [Array<String>]
231
+ def self.writer_types
232
+ writer_symbols.map {|s| RDF::Format.for(s).content_type}.flatten.uniq
207
233
  end
208
234
 
209
235
  ##
@@ -492,7 +492,7 @@ module RDF
492
492
  alias_method :enum_objects, :enum_object
493
493
 
494
494
  ##
495
- # Returns all unique RDF contexts.
495
+ # Returns all unique RDF contexts, other than the default context.
496
496
  #
497
497
  # @param [Hash{Symbol => Boolean}] options
498
498
  # @option options [Boolean] :unique (true)
@@ -510,14 +510,15 @@ module RDF
510
510
  ##
511
511
  # Returns `true` if `self` contains the given RDF context.
512
512
  #
513
- # @param [RDF::Resource] value
513
+ # @param [RDF::Resource, false] value
514
+ # Use value `false` to query for the default context
514
515
  # @return [Boolean]
515
516
  def has_context?(value)
516
517
  enum_context.include?(value)
517
518
  end
518
519
 
519
520
  ##
520
- # Iterates the given block for each unique RDF context.
521
+ # Iterates the given block for each unique RDF context, other than the default context.
521
522
  #
522
523
  # If no block was given, returns an enumerator.
523
524
  #
@@ -664,5 +665,21 @@ module RDF
664
665
  raise RDF::WriterError, "No writer found using #{args.inspect}" unless writer
665
666
  writer.dump(self, nil, options)
666
667
  end
668
+
669
+ ##
670
+ # @overload #to_writer
671
+ # Implements #to_writer for each available instance of {RDF::Writer},
672
+ # based on the writer symbol.
673
+ #
674
+ # @return [String]
675
+ # @see {RDF::Writer.sym}
676
+ def method_missing(meth, *args)
677
+ writer = RDF::Writer.for(meth.to_s[3..-1].to_sym) if meth.to_s[0,3] == "to_"
678
+ if writer
679
+ writer.buffer(:standard_prefixes => true) {|w| w << self}
680
+ else
681
+ super
682
+ end
683
+ end
667
684
  end # Enumerable
668
685
  end # RDF
@@ -152,6 +152,23 @@ module RDF
152
152
 
153
153
  alias_method :clear!, :clear
154
154
 
155
+ ##
156
+ # @overload #from_reader
157
+ # Implements #from_reader for each available instance of {RDF::Reader},
158
+ # based on the reader symbol.
159
+ #
160
+ # Arguments are passed to Reader.new.
161
+ #
162
+ # @return [String]
163
+ # @see {RDF::Reader.sym}
164
+ def method_missing(meth, *args)
165
+ reader = RDF::Reader.for(meth.to_s[5..-1].to_sym) if meth.to_s[0,5] == "from_"
166
+ if reader
167
+ self << reader.new(*args)
168
+ else
169
+ super
170
+ end
171
+ end
155
172
  protected
156
173
 
157
174
  ##
@@ -184,8 +201,5 @@ module RDF
184
201
  def delete_statement(statement)
185
202
  raise NotImplementedError.new("#{self.class}#delete_statement")
186
203
  end
187
-
188
- protected :delete_statements
189
- protected :delete_statement
190
204
  end
191
205
  end
@@ -147,10 +147,14 @@ module RDF
147
147
  query(pattern) do |statement|
148
148
  return statement
149
149
  end
150
- return nil
150
+ elsif respond_to?(:each_statement)
151
+ each_statement do |statement|
152
+ return statement
153
+ end
151
154
  else
152
- super()
155
+ return super()
153
156
  end
157
+ nil
154
158
  end
155
159
 
156
160
  ##
@@ -31,15 +31,24 @@ module RDF
31
31
  ##
32
32
  # Returns the options passed to this graph when it was constructed.
33
33
  #
34
+ # @!attribute [r] options
34
35
  # @return [Hash{Symbol => Object}]
35
36
  attr_reader :options
36
37
 
37
38
  ##
39
+ # Name of this graph, if it is part of an {RDF::Repository}
40
+ # @!attribute [rw] context
38
41
  # @return [RDF::Resource]
39
- # @deprecated In the next release, graphs will have no name
42
+ # @note In the next release, only projections from an
43
+ # {RDF::Enumerable} supporting contexts will have a context.
40
44
  attr_accessor :context
41
45
 
46
+ alias_method :name, :context
47
+ alias_method :name=, :context=
48
+
42
49
  ##
50
+ # {RDF::Queryable} backing this graph.
51
+ # @!attribute [rw] data
43
52
  # @return [RDF::Queryable]
44
53
  attr_accessor :data
45
54
 
@@ -72,9 +81,10 @@ module RDF
72
81
  # @param [RDF::Resource] context
73
82
  # The context only provides a context for loading relative documents
74
83
  # @param [Hash{Symbol => Object}] options
75
- # @deprecated Graph context will be removed in the next release.
76
- # This is because context relates to a Named Graph in RDF 1.1
77
- # and a default graph has no context/name.
84
+ # @note contexts are only useful when used as a projection
85
+ # on a `:data` which supports contexts. Otherwise, there is no
86
+ # such thing as a named graph in RDF 1.1, a repository may have
87
+ # graphs which are named, but the name is not a property of the graph.
78
88
  # @overload initialize(options)
79
89
  # @param [Hash{Symbol => Object}] options
80
90
  # @yield [graph]
@@ -139,12 +149,12 @@ module RDF
139
149
  end
140
150
 
141
151
  ##
142
- # Returns `false` to indicate that this graph is not durable
152
+ # A graph is durable if it's underlying data model is durable
143
153
  #
144
154
  # @return [Boolean]
145
155
  # @see RDF::Durable#durable?
146
156
  def durable?
147
- false
157
+ @data.durable?
148
158
  end
149
159
 
150
160
  ##
@@ -156,10 +166,9 @@ module RDF
156
166
  end
157
167
 
158
168
  ##
159
- # Returns the URI representation of this graph.
169
+ # Returns the {RDF::Resource} representation of this graph.
160
170
  #
161
- # @return [RDF::URI]
162
- # @note The next release, graphs will not be named, this will return nil
171
+ # @return [RDF::Resource]
163
172
  def to_uri
164
173
  context
165
174
  end
@@ -169,7 +178,7 @@ module RDF
169
178
  #
170
179
  # @return [String]
171
180
  def to_s
172
- named? ? context.to_s : "<>"
181
+ named? ? context.to_s : "default"
173
182
  end
174
183
 
175
184
  ##
@@ -178,7 +187,7 @@ module RDF
178
187
  # @return [Boolean]
179
188
  # @see RDF::Enumerable#empty?
180
189
  def empty?
181
- @data.empty?
190
+ !@data.has_context?(context || false)
182
191
  end
183
192
 
184
193
  ##
@@ -196,7 +205,7 @@ module RDF
196
205
  # @return [Integer]
197
206
  # @see RDF::Enumerable#count
198
207
  def count
199
- @data.query(:context => context).count
208
+ @data.query(:context => context || false).count
200
209
  end
201
210
 
202
211
  ##
@@ -207,7 +216,7 @@ module RDF
207
216
  # @see RDF::Enumerable#has_statement?
208
217
  def has_statement?(statement)
209
218
  statement = statement.dup
210
- statement.context = context # TODO: going away
219
+ statement.context = context
211
220
  @data.has_statement?(statement)
212
221
  end
213
222
 
@@ -219,7 +228,27 @@ module RDF
219
228
  # @return [Enumerator]
220
229
  # @see RDF::Enumerable#each_statement
221
230
  def each(&block)
222
- @data.query(:context => context).each(&block)
231
+ if @data.respond_to?(:query)
232
+ @data.query(:context => context || false, &block)
233
+ elsif @data.respond_to?(:each)
234
+ @data.each(&block)
235
+ else
236
+ @data.to_a.each(&block)
237
+ end
238
+ end
239
+
240
+ ##
241
+ # Graph equivalence based on the contents of each graph being _exactly_
242
+ # the same. To determine if the have the same _meaning_, consider
243
+ # [rdf-isomorphic](http://rubygems.org/gems/rdf-isomorphic).
244
+ #
245
+ # @param [RDF::Graph] other
246
+ # @return [Boolean]
247
+ # @see http://rubygems.org/gems/rdf-isomorphic
248
+ def ==(other)
249
+ other.is_a?(RDF::Graph) &&
250
+ context == other.context &&
251
+ statements.to_a == other.statements.to_a
223
252
  end
224
253
 
225
254
  ##
@@ -227,7 +256,7 @@ module RDF
227
256
  # @see RDF::Queryable#query
228
257
  def query_pattern(pattern, &block)
229
258
  pattern = pattern.dup
230
- pattern.context = context
259
+ pattern.context = context || false
231
260
  @data.query(pattern, &block)
232
261
  end
233
262
 
@@ -253,7 +282,7 @@ module RDF
253
282
  # @private
254
283
  # @see RDF::Mutable#clear
255
284
  def clear_statements
256
- @data.delete(:context => context)
285
+ @data.delete(:context => context || false)
257
286
  end
258
287
 
259
288
  protected :query_pattern
@@ -343,6 +343,17 @@ module RDF
343
343
  self
344
344
  end
345
345
 
346
+ ##
347
+ # Returns the base representation of this URI.
348
+ #
349
+ # @return [Sring]
350
+ def to_base
351
+ text = %("#{escape(value)}")
352
+ text << "@#{language}" if has_language?
353
+ text << "^^#{datatype.to_base}" if has_datatype?
354
+ text
355
+ end
356
+
346
357
  ##
347
358
  # Returns the value as a string.
348
359
  #
@@ -137,6 +137,14 @@ module RDF
137
137
  end
138
138
  alias_method :===, :==
139
139
 
140
+ ##
141
+ # Returns the base representation of this URI.
142
+ #
143
+ # @return [Sring]
144
+ def to_base
145
+ to_s
146
+ end
147
+
140
148
  ##
141
149
  # Returns a string representation of this blank node.
142
150
  #
@@ -57,6 +57,7 @@ module RDF
57
57
  # @option options [RDF::URI] :predicate (nil)
58
58
  # @option options [RDF::Term] :object (nil)
59
59
  # @option options [RDF::Resource] :context (nil)
60
+ # Note, in RDF 1.1, a context MUST be an IRI.
60
61
  #
61
62
  # @overload initialize(subject, predicate, object, options = {})
62
63
  # @param [RDF::Resource] subject
@@ -259,25 +260,9 @@ module RDF
259
260
  #
260
261
  # @return [String]
261
262
  def to_s
262
- StringIO.open do |buffer|
263
- buffer << case subject
264
- when RDF::Node then subject.to_s
265
- when RDF::URI then "<#{subject}>"
266
- else subject.inspect
267
- end
268
- buffer << " <#{predicate}> "
269
- buffer << case object
270
- when RDF::Literal then object.to_s
271
- when RDF::Node then object.to_s
272
- when RDF::URI then "<#{object}>"
273
- else object.inspect
274
- end
275
- buffer << case context
276
- when nil then " ."
277
- else " <#{context}> ."
278
- end
279
- buffer.string
280
- end
263
+ (context ? to_quad : to_triple).map do |term|
264
+ term.respond_to?(:to_base) ? term.to_base : term.inspect
265
+ end.join(" ") + " ."
281
266
  end
282
267
 
283
268
  ##
@@ -66,12 +66,36 @@ module RDF
66
66
  end
67
67
 
68
68
  ##
69
- # Returns `true` if this term is variable.
69
+ # Returns a base representation of `self`.
70
70
  #
71
- # @return [Boolean] `true` or `false`
72
- # @see #constant?
73
- def variable?
74
- false
71
+ # @return [RDF::Value]
72
+ def to_base
73
+ self
74
+ end
75
+
76
+ ##
77
+ # Returns `true` if `self` is a {RDF::Term}.
78
+ #
79
+ # @return [Boolean]
80
+ def term?
81
+ true
75
82
  end
83
+
84
+ protected
85
+ ##
86
+ # Escape a term using standard character escapes
87
+ #
88
+ # @param [String] string
89
+ # @return [String]
90
+ def escape(string)
91
+ string.gsub('\\', '\\\\').
92
+ gsub("\b", '\\b').
93
+ gsub("\f", '\\f').
94
+ gsub("\t", '\\t').
95
+ gsub("\n", '\\n').
96
+ gsub("\r", '\\r').
97
+ gsub('"', '\\"')
98
+ end
99
+
76
100
  end # Term
77
101
  end # RDF
@@ -19,6 +19,7 @@ module RDF
19
19
  # @example Getting the string representation of a URI
20
20
  # uri.to_s #=> "http://rdf.rubyforge.org/"
21
21
  #
22
+ # http://en.wikipedia.org/wiki/Internationalized_Resource_Identifier
22
23
  # @see http://en.wikipedia.org/wiki/Uniform_Resource_Identifier
23
24
  # @see http://www.ietf.org/rfc/rfc3986.txt
24
25
  # @see http://www.ietf.org/rfc/rfc3987.txt
@@ -41,54 +42,54 @@ module RDF
41
42
  [\\u{A0000}-\\u{AFFFD}]|[\\u{B0000}-\\u{BFFFD}]|[\\u{C0000}-\\u{CFFFD}]|
42
43
  [\\u{D0000}-\\u{DFFFD}]|[\\u{E0000}-\\u{EFFFD}]
43
44
  EOS
44
- IPRIVATE = Regexp.compile("[\\uE000-\\uF8FF]|[\\u{F0000}-\\u{FFFFD}]|[\\u100000-\\u10FFFD]")
45
+ IPRIVATE = Regexp.compile("[\\uE000-\\uF8FF]|[\\u{F0000}-\\u{FFFFD}]|[\\u100000-\\u10FFFD]").freeze
45
46
  end
46
47
 
47
- SCHEME = Regexp.compile("[A-za-z](?:[A-Za-z0-9+-\.])*")
48
- PORT = Regexp.compile("[0-9]*")
49
- IP_literal = Regexp.compile("\\[[0-9A-Fa-f:\\.]*\\]") # Simplified, no IPvFuture
50
- PCT_ENCODED = Regexp.compile("%[0-9A-Fa-f]{2}")
51
- GEN_DELIMS = Regexp.compile("[:/\\?\\#\\[\\]@]")
52
- SUB_DELIMS = Regexp.compile("[!\\$&'\\(\\)\\*\\+,;=]")
53
- RESERVED = Regexp.compile("(?:#{GEN_DELIMS}|#{SUB_DELIMS})")
54
- UNRESERVED = Regexp.compile("[A-Za-z0-9]|-|\\.|_|~")
48
+ SCHEME = Regexp.compile("[A-za-z](?:[A-Za-z0-9+-\.])*").freeze
49
+ PORT = Regexp.compile("[0-9]*").freeze
50
+ IP_literal = Regexp.compile("\\[[0-9A-Fa-f:\\.]*\\]").freeze # Simplified, no IPvFuture
51
+ PCT_ENCODED = Regexp.compile("%[0-9A-Fa-f]{2}").freeze
52
+ GEN_DELIMS = Regexp.compile("[:/\\?\\#\\[\\]@]").freeze
53
+ SUB_DELIMS = Regexp.compile("[!\\$&'\\(\\)\\*\\+,;=]").freeze
54
+ RESERVED = Regexp.compile("(?:#{GEN_DELIMS}|#{SUB_DELIMS})").freeze
55
+ UNRESERVED = Regexp.compile("[A-Za-z0-9]|-|\\.|_|~").freeze
55
56
 
56
57
  if RUBY_VERSION >= '1.9'
57
- IUNRESERVED = Regexp.compile("[A-Za-z0-9]|-|\\.|_|~|#{UCSCHAR}")
58
+ IUNRESERVED = Regexp.compile("[A-Za-z0-9]|-|\\.|_|~|#{UCSCHAR}").freeze
58
59
  else
59
- IUNRESERVED = Regexp.compile("[A-Za-z0-9]|-|\\.|_|~")
60
+ IUNRESERVED = Regexp.compile("[A-Za-z0-9]|-|\\.|_|~").freeze
60
61
  end
61
62
 
62
- IPCHAR = Regexp.compile("(?:#{IUNRESERVED}|#{PCT_ENCODED}|#{SUB_DELIMS}|:|@)")
63
+ IPCHAR = Regexp.compile("(?:#{IUNRESERVED}|#{PCT_ENCODED}|#{SUB_DELIMS}|:|@)").freeze
63
64
 
64
65
  if RUBY_VERSION >= '1.9'
65
- IQUERY = Regexp.compile("(?:#{IPCHAR}|#{IPRIVATE}|/|\\?)*")
66
+ IQUERY = Regexp.compile("(?:#{IPCHAR}|#{IPRIVATE}|/|\\?)*").freeze
66
67
  else
67
- IQUERY = Regexp.compile("(?:#{IPCHAR}|/|\\?)*")
68
+ IQUERY = Regexp.compile("(?:#{IPCHAR}|/|\\?)*").freeze
68
69
  end
69
70
 
70
- IFRAGMENT = Regexp.compile("(?:#{IPCHAR}|/|\\?)*")
71
+ IFRAGMENT = Regexp.compile("(?:#{IPCHAR}|/|\\?)*").freeze.freeze
71
72
 
72
- ISEGMENT = Regexp.compile("(?:#{IPCHAR})*")
73
- ISEGMENT_NZ = Regexp.compile("(?:#{IPCHAR})+")
74
- ISEGMENT_NZ_NC = Regexp.compile("(?:(?:#{IUNRESERVED})|(?:#{PCT_ENCODED})|(?:#{SUB_DELIMS})|@)+")
73
+ ISEGMENT = Regexp.compile("(?:#{IPCHAR})*").freeze
74
+ ISEGMENT_NZ = Regexp.compile("(?:#{IPCHAR})+").freeze
75
+ ISEGMENT_NZ_NC = Regexp.compile("(?:(?:#{IUNRESERVED})|(?:#{PCT_ENCODED})|(?:#{SUB_DELIMS})|@)+").freeze
75
76
 
76
- IPATH_ABEMPTY = Regexp.compile("(?:/#{ISEGMENT})*")
77
- IPATH_ABSOLUTE = Regexp.compile("/(?:(?:#{ISEGMENT_NZ})(/#{ISEGMENT})*)?")
78
- IPATH_NOSCHEME = Regexp.compile("(?:#{ISEGMENT_NZ_NC})(?:/#{ISEGMENT})*")
79
- IPATH_ROOTLESS = Regexp.compile("(?:#{ISEGMENT_NZ})(?:/#{ISEGMENT})*")
80
- IPATH_EMPTY = Regexp.compile("")
77
+ IPATH_ABEMPTY = Regexp.compile("(?:/#{ISEGMENT})*").freeze
78
+ IPATH_ABSOLUTE = Regexp.compile("/(?:(?:#{ISEGMENT_NZ})(/#{ISEGMENT})*)?").freeze
79
+ IPATH_NOSCHEME = Regexp.compile("(?:#{ISEGMENT_NZ_NC})(?:/#{ISEGMENT})*").freeze
80
+ IPATH_ROOTLESS = Regexp.compile("(?:#{ISEGMENT_NZ})(?:/#{ISEGMENT})*").freeze
81
+ IPATH_EMPTY = Regexp.compile("").freeze
81
82
 
82
- IREG_NAME = Regexp.compile("(?:(?:#{IUNRESERVED})|(?:#{PCT_ENCODED})|(?:#{SUB_DELIMS}))*")
83
- IHOST = Regexp.compile("(?:#{IP_literal})|(?:#{IREG_NAME})")
84
- IUSERINFO = Regexp.compile("(?:(?:#{IUNRESERVED})|(?:#{PCT_ENCODED})|(?:#{SUB_DELIMS})|:)*")
85
- IAUTHORITY = Regexp.compile("(?:#{IUSERINFO}@)?#{IHOST}(?::#{PORT})?")
83
+ IREG_NAME = Regexp.compile("(?:(?:#{IUNRESERVED})|(?:#{PCT_ENCODED})|(?:#{SUB_DELIMS}))*").freeze
84
+ IHOST = Regexp.compile("(?:#{IP_literal})|(?:#{IREG_NAME})").freeze
85
+ IUSERINFO = Regexp.compile("(?:(?:#{IUNRESERVED})|(?:#{PCT_ENCODED})|(?:#{SUB_DELIMS})|:)*").freeze
86
+ IAUTHORITY = Regexp.compile("(?:#{IUSERINFO}@)?#{IHOST}(?::#{PORT})?").freeze
86
87
 
87
- IRELATIVE_PART = Regexp.compile("(?:(?://#{IAUTHORITY}(?:#{IPATH_ABEMPTY}))|(?:#{IPATH_ABSOLUTE})|(?:#{IPATH_NOSCHEME})|(?:#{IPATH_EMPTY}))")
88
- IRELATIVE_REF = Regexp.compile("^#{IRELATIVE_PART}(?:\\?#{IQUERY})?(?:\\##{IFRAGMENT})?$")
88
+ IRELATIVE_PART = Regexp.compile("(?:(?://#{IAUTHORITY}(?:#{IPATH_ABEMPTY}))|(?:#{IPATH_ABSOLUTE})|(?:#{IPATH_NOSCHEME})|(?:#{IPATH_EMPTY}))").freeze
89
+ IRELATIVE_REF = Regexp.compile("^#{IRELATIVE_PART}(?:\\?#{IQUERY})?(?:\\##{IFRAGMENT})?$").freeze
89
90
 
90
- IHIER_PART = Regexp.compile("(?:(?://#{IAUTHORITY}#{IPATH_ABEMPTY})|(?:#{IPATH_ABSOLUTE})|(?:#{IPATH_ROOTLESS})|(?:#{IPATH_EMPTY}))")
91
- IRI = Regexp.compile("^#{SCHEME}:(?:#{IHIER_PART})(?:\\?#{IQUERY})?(?:\\##{IFRAGMENT})?$")
91
+ IHIER_PART = Regexp.compile("(?:(?://#{IAUTHORITY}#{IPATH_ABEMPTY})|(?:#{IPATH_ABSOLUTE})|(?:#{IPATH_ROOTLESS})|(?:#{IPATH_EMPTY}))").freeze
92
+ IRI = Regexp.compile("^#{SCHEME}:(?:#{IHIER_PART})(?:\\?#{IQUERY})?(?:\\##{IFRAGMENT})?$").freeze
92
93
 
93
94
  ##
94
95
  # @return [RDF::Util::Cache]
@@ -148,14 +149,6 @@ module RDF
148
149
  end
149
150
  end
150
151
 
151
- ##
152
- # Returns `false`.
153
- #
154
- # @return [Boolean] `true` or `false`
155
- def anonymous?
156
- false
157
- end
158
-
159
152
  ##
160
153
  # Returns `true`.
161
154
  #
@@ -592,6 +585,14 @@ module RDF
592
585
  self
593
586
  end
594
587
 
588
+ ##
589
+ # Returns the base representation of this URI.
590
+ #
591
+ # @return [Sring]
592
+ def to_base
593
+ "<#{escape(@uri.to_s)}>"
594
+ end
595
+
595
596
  ##
596
597
  # Returns the string representation of this URI.
597
598
  #
@@ -641,4 +642,7 @@ module RDF
641
642
  end
642
643
  end
643
644
  end # URI
645
+
646
+ # RDF::IRI is a synonym for RDF::URI
647
+ IRI = URI
644
648
  end # RDF
@@ -4,7 +4,8 @@ module RDF
4
4
  #
5
5
  # This is the basis for the RDF.rb class hierarchy. Anything that can be a
6
6
  # term of {RDF::Statement RDF statements} should directly or indirectly
7
- # include this module.
7
+ # include this module, but it does not define classes that can be included
8
+ # within a {RDF::Statement}, for this see {RDF::Term}.
8
9
  #
9
10
  # @example Checking if a value is a resource (blank node or URI reference)
10
11
  # value.resource?
@@ -19,15 +20,16 @@ module RDF
19
20
  # @example Checking if a value is a literal
20
21
  # value.literal?
21
22
  #
22
- # @see RDF::Graph
23
23
  # @see RDF::Literal
24
24
  # @see RDF::Node
25
25
  # @see RDF::Resource
26
- # @see RDF::Statement
27
26
  # @see RDF::URI
27
+ # @see RDF::Graph
28
+ # @see RDF::List
29
+ # @see RDF::Statement
28
30
  module Value
29
31
  ##
30
- # Returns `true` if `self` is a graph.
32
+ # Returns `true` if `self` is a {RDF::Graph}.
31
33
  #
32
34
  # @return [Boolean]
33
35
  def graph?
@@ -35,23 +37,31 @@ module RDF
35
37
  end
36
38
 
37
39
  ##
38
- # Returns `true` if `self` is a literal.
40
+ # Returns `true` if `self` is a {RDF::Statement}.
39
41
  #
40
42
  # @return [Boolean]
41
- def literal?
43
+ def statement?
42
44
  false
43
45
  end
44
46
 
45
47
  ##
46
- # Returns `true` if `self` is a blank node.
48
+ # Returns `true` if `self` is a {RDF::List}.
47
49
  #
48
50
  # @return [Boolean]
49
- def node?
51
+ def list?
50
52
  false
51
53
  end
52
54
 
53
55
  ##
54
- # Returns `true` if `self` is a resource.
56
+ # Returns `true` if `self` is a {RDF::Term}.
57
+ #
58
+ # @return [Boolean]
59
+ def term?
60
+ false
61
+ end
62
+
63
+ ##
64
+ # Returns `true` if `self` is a {RDF::Resource}.
55
65
  #
56
66
  # @return [Boolean]
57
67
  def resource?
@@ -59,10 +69,18 @@ module RDF
59
69
  end
60
70
 
61
71
  ##
62
- # Returns `true` if `self` is a statement.
72
+ # Returns `true` if `self` is a {RDF::Literal}.
63
73
  #
64
74
  # @return [Boolean]
65
- def statement?
75
+ def literal?
76
+ false
77
+ end
78
+
79
+ ##
80
+ # Returns `true` if `self` is a {RDF::Node}.
81
+ #
82
+ # @return [Boolean]
83
+ def node?
66
84
  false
67
85
  end
68
86
 
@@ -77,7 +95,7 @@ module RDF
77
95
  end
78
96
 
79
97
  ##
80
- # Returns `true` if `self` is a URI reference.
98
+ # Returns `true` if `self` is a {RDF::URI}.
81
99
  #
82
100
  # @return [Boolean]
83
101
  def uri?
@@ -85,7 +103,7 @@ module RDF
85
103
  end
86
104
 
87
105
  ##
88
- # Returns `true` if `self` is a query variable.
106
+ # Returns `true` if `self` is a {RDF::Query::Variable}.
89
107
  #
90
108
  # @return [Boolean]
91
109
  # @since 0.1.7
@@ -93,6 +111,14 @@ module RDF
93
111
  false
94
112
  end
95
113
 
114
+ ##
115
+ # Is this an anonymous value?
116
+ #
117
+ # @return [Boolean] `true` or `false`
118
+ def anonymous?
119
+ false
120
+ end
121
+
96
122
  ##
97
123
  # Returns `true` if the value has a valid representation
98
124
  #
@@ -14,12 +14,13 @@ module RDF
14
14
  # RDF::Format.for("etc/doap.nq")
15
15
  # RDF::Format.for(:file_name => "etc/doap.nq")
16
16
  # RDF::Format.for(:file_extension => "nq")
17
+ # RDF::Format.for(:content_type => "application/n-quads")
17
18
  # RDF::Format.for(:content_type => "text/x-nquads")
18
19
  #
19
20
  # @see http://sw.deri.org/2008/07/n-quads/#mediatype
20
21
  # @since 0.4.0
21
22
  class Format < RDF::Format
22
- content_type 'text/x-nquads', :extension => :nq
23
+ content_type 'application/n-quads', :extension => :nq, :alias => ['text/x-nquads']
23
24
  content_encoding 'utf-8'
24
25
 
25
26
  reader { RDF::NQuads::Reader }
@@ -78,6 +79,9 @@ module RDF
78
79
  predicate = read_uriref(:intern => true) || fail_predicate
79
80
  object = read_uriref || read_node || read_literal || fail_object
80
81
  context = read_uriref || read_node || read_literal
82
+ if validate? && !read_eos
83
+ raise RDF::ReaderError, "expected end of statement in line #{lineno}: #{current_line.inspect}"
84
+ end
81
85
  return [subject, predicate, object, {:context => context}]
82
86
  end
83
87
  rescue RDF::ReaderError => e
@@ -28,20 +28,6 @@ module RDF::NTriples
28
28
  class Reader < RDF::Reader
29
29
  format RDF::NTriples::Format
30
30
 
31
- # @see http://www.w3.org/TR/rdf-testcases/#ntrip_grammar
32
- COMMENT = /^#\s*(.*)$/.freeze
33
- NODEID = /^_:([A-Za-z][A-Za-z0-9\-_]*)/.freeze
34
- URIREF = /^<([^>]+)>/.freeze
35
- LITERAL_PLAIN = /^"((?:\\"|[^"])*)"/.freeze
36
- LITERAL_WITH_LANGUAGE = /^"((?:\\"|[^"])*)"@([a-z]+[\-A-Za-z0-9]*)/.freeze
37
- LITERAL_WITH_DATATYPE = /^"((?:\\"|[^"])*)"\^\^<([^>]+)>/.freeze
38
- LANGUAGE_TAG = /^@([a-z]+[\-A-Za-z0-9]*)/.freeze
39
- DATATYPE_URI = /^\^\^<([^>]+)>/.freeze
40
- LITERAL = Regexp.union(LITERAL_WITH_LANGUAGE, LITERAL_WITH_DATATYPE, LITERAL_PLAIN).freeze
41
- SUBJECT = Regexp.union(URIREF, NODEID).freeze
42
- PREDICATE = Regexp.union(URIREF).freeze
43
- OBJECT = Regexp.union(URIREF, NODEID, LITERAL).freeze
44
-
45
31
  # @see http://www.w3.org/TR/rdf-testcases/#ntrip_strings
46
32
  ESCAPE_CHARS = ["\b", "\f", "\t", "\n", "\r", "\"", "\\"].freeze
47
33
  ESCAPE_CHAR4 = /\\u([0-9A-Fa-f]{4,4})/.freeze
@@ -51,6 +37,97 @@ module RDF::NTriples
51
37
  ESCAPE_SURROGATE1 = (0xD800..0xDBFF).freeze
52
38
  ESCAPE_SURROGATE2 = (0xDC00..0xDFFF).freeze
53
39
 
40
+
41
+ # Terminals from rdf-turtle.
42
+ #
43
+ # @see http://www.w3.org/TR/n-triples/
44
+ # @see http://www.w3.org/TR/turtle/
45
+ if RUBY_VERSION >= '1.9'
46
+ ##
47
+ # Unicode regular expressions for Ruby 1.9+ with the Oniguruma engine.
48
+ U_CHARS1 = Regexp.compile(<<-EOS.gsub(/\s+/, ''))
49
+ [\\u00C0-\\u00D6]|[\\u00D8-\\u00F6]|[\\u00F8-\\u02FF]|
50
+ [\\u0370-\\u037D]|[\\u037F-\\u1FFF]|[\\u200C-\\u200D]|
51
+ [\\u2070-\\u218F]|[\\u2C00-\\u2FEF]|[\\u3001-\\uD7FF]|
52
+ [\\uF900-\\uFDCF]|[\\uFDF0-\\uFFFD]|[\\u{10000}-\\u{EFFFF}]
53
+ EOS
54
+ U_CHARS2 = Regexp.compile("\\u00B7|[\\u0300-\\u036F]|[\\u203F-\\u2040]").freeze
55
+ IRI_RANGE = Regexp.compile("[[^<>\"{}|^`\\\\]&&[^\\x00-\\x20]]").freeze
56
+ else
57
+ ##
58
+ # UTF-8 regular expressions for Ruby 1.8.x.
59
+ U_CHARS1 = Regexp.compile(<<-EOS.gsub(/\s+/, ''))
60
+ \\xC3[\\x80-\\x96]| (?# [\\u00C0-\\u00D6]|)
61
+ \\xC3[\\x98-\\xB6]| (?# [\\u00D8-\\u00F6]|)
62
+ \\xC3[\\xB8-\\xBF]|[\\xC4-\\xCB][\\x80-\\xBF]| (?# [\\u00F8-\\u02FF]|)
63
+ \\xCD[\\xB0-\\xBD]| (?# [\\u0370-\\u037D]|)
64
+ \\xCD\\xBF|[\\xCE-\\xDF][\\x80-\\xBF]| (?# [\\u037F-\\u1FFF]|)
65
+ \\xE0[\\xA0-\\xBF][\\x80-\\xBF]| (?# ...)
66
+ \\xE1[\\x80-\\xBF][\\x80-\\xBF]| (?# ...)
67
+ \\xE2\\x80[\\x8C-\\x8D]| (?# [\\u200C-\\u200D]|)
68
+ \\xE2\\x81[\\xB0-\\xBF]| (?# [\\u2070-\\u218F]|)
69
+ \\xE2[\\x82-\\x85][\\x80-\\xBF]| (?# ...)
70
+ \\xE2\\x86[\\x80-\\x8F]| (?# ...)
71
+ \\xE2[\\xB0-\\xBE][\\x80-\\xBF]| (?# [\\u2C00-\\u2FEF]|)
72
+ \\xE2\\xBF[\\x80-\\xAF]| (?# ...)
73
+ \\xE3\\x80[\\x81-\\xBF]| (?# [\\u3001-\\uD7FF]|)
74
+ \\xE3[\\x81-\\xBF][\\x80-\\xBF]| (?# ...)
75
+ [\\xE4-\\xEC][\\x80-\\xBF][\\x80-\\xBF]| (?# ...)
76
+ \\xED[\\x80-\\x9F][\\x80-\\xBF]| (?# ...)
77
+ \\xEF[\\xA4-\\xB6][\\x80-\\xBF]| (?# [\\uF900-\\uFDCF]|)
78
+ \\xEF\\xB7[\\x80-\\x8F]| (?# ...)
79
+ \\xEF\\xB7[\\xB0-\\xBF]| (?# [\\uFDF0-\\uFFFD]|)
80
+ \\xEF[\\xB8-\\xBE][\\x80-\\xBF]| (?# ...)
81
+ \\xEF\\xBF[\\x80-\\xBD]| (?# ...)
82
+ \\xF0[\\x90-\\xBF][\\x80-\\xBF][\\x80-\\xBF]| (?# [\\u{10000}-\\u{EFFFF}])
83
+ [\\xF1-\\xF2][\\x80-\\xBF][\\x80-\\xBF][\\x80-\\xBF]|
84
+ \\xF3[\\x80-\\xAF][\\x80-\\xBF][\\x80-\\xBF] (?# ...)
85
+ EOS
86
+ U_CHARS2 = Regexp.compile(<<-EOS.gsub(/\s+/, ''))
87
+ \\xC2\\xB7| (?# \\u00B7|)
88
+ \\xCC[\\x80-\\xBF]|\\xCD[\\x80-\\xAF]| (?# [\\u0300-\\u036F]|)
89
+ \\xE2\\x80\\xBF|\\xE2\\x81\\x80 (?# [\\u203F-\\u2040])
90
+ EOS
91
+ IRI_RANGE = Regexp.compile(<<-EOS.gsub(/\s+/, ''))
92
+ \\x21| (?# ")
93
+ [\\x23-\\x3b]|\\x3d| (?# < & >)
94
+ [\\x3f-\\x5b]|\\x5d|\\x5f| (?# \ ^ `)
95
+ [\\x61-\\x7a]| (?# { } |)
96
+ [\\x7e-\\xff]
97
+ EOS
98
+ end
99
+
100
+ # 163s
101
+ PN_CHARS_BASE = /[A-Z]|[a-z]|#{U_CHARS1}/.freeze
102
+ # 164s
103
+ PN_CHARS_U = /_|#{PN_CHARS_BASE}/.freeze
104
+ # 166s
105
+ PN_CHARS = /-|[0-9]|#{PN_CHARS_U}|#{U_CHARS2}/.freeze
106
+ # 159s
107
+ ECHAR = /\\[tbnrf\\"']/.freeze
108
+ # 18
109
+ IRIREF = /<((?:#{IRI_RANGE}|#{ESCAPE_CHAR})*)>/.freeze
110
+ # 141s
111
+ BLANK_NODE_LABEL = /_:((?:[0-9]|#{PN_CHARS_U})(?:(?:#{PN_CHARS}|\.)*#{PN_CHARS})?)/.freeze
112
+ # 144s
113
+ LANGTAG = /@([a-zA-Z]+(?:-[a-zA-Z0-9]+)*)/.freeze
114
+ # 22
115
+ STRING_LITERAL_QUOTE = /"((?:[^\"\\\n\r]|#{ECHAR}|#{ESCAPE_CHAR})*)"/.freeze
116
+
117
+ # @see http://www.w3.org/TR/rdf-testcases/#ntrip_grammar
118
+ COMMENT = /^#\s*(.*)$/.freeze
119
+ NODEID = /^#{BLANK_NODE_LABEL}/.freeze
120
+ URIREF = /^#{IRIREF}/.freeze
121
+ LITERAL_PLAIN = /^#{STRING_LITERAL_QUOTE}/.freeze
122
+ LITERAL_WITH_LANGUAGE = /^#{STRING_LITERAL_QUOTE}#{LANGTAG}/.freeze
123
+ LITERAL_WITH_DATATYPE = /^#{STRING_LITERAL_QUOTE}\^\^#{IRIREF}/.freeze
124
+ DATATYPE_URI = /^\^\^#{IRIREF}/.freeze
125
+ LITERAL = Regexp.union(LITERAL_WITH_LANGUAGE, LITERAL_WITH_DATATYPE, LITERAL_PLAIN).freeze
126
+ SUBJECT = Regexp.union(URIREF, NODEID).freeze
127
+ PREDICATE = Regexp.union(URIREF).freeze
128
+ OBJECT = Regexp.union(URIREF, NODEID, LITERAL).freeze
129
+ END_OF_STATEMENT = /^\s*\.\s*$/.freeze
130
+
54
131
  ##
55
132
  # Reconstructs an RDF value from its serialized N-Triples
56
133
  # representation.
@@ -124,6 +201,7 @@ module RDF::NTriples
124
201
  # @see http://blog.grayproductions.net/articles/understanding_m17n
125
202
  # @see http://yehudakatz.com/2010/05/17/encodings-unabridged/
126
203
  def self.unescape(string)
204
+ string = string.to_s
127
205
  string = string.dup.force_encoding(Encoding::ASCII_8BIT) if string.respond_to?(:force_encoding)
128
206
 
129
207
  # Decode \t|\n|\r|\"|\\ character escapes:
@@ -135,8 +213,10 @@ module RDF::NTriples
135
213
  if ESCAPE_SURROGATE1.include?($1.hex) && ESCAPE_SURROGATE2.include?($2.hex)
136
214
  s = [$1, $2].pack('H*H*')
137
215
  s = s.respond_to?(:force_encoding) ?
138
- s.force_encoding(Encoding::UTF_16BE).encode!(Encoding::UTF_8) : # for Ruby 1.9+
139
- Iconv.conv('UTF-8', 'UTF-16BE', s) # for Ruby 1.8.x
216
+ # for Ruby 1.9+
217
+ s.force_encoding(Encoding::UTF_16BE).encode!(Encoding::UTF_8) :
218
+ # for Ruby 1.8.x
219
+ Iconv.conv('UTF-8', 'UTF-16BE', s)
140
220
  else
141
221
  s = [$1.hex].pack('U*') << '\u' << $2
142
222
  end
@@ -159,7 +239,7 @@ module RDF::NTriples
159
239
  def read_value
160
240
  begin
161
241
  read_statement
162
- rescue RDF::ReaderError => e
242
+ rescue RDF::ReaderError
163
243
  read_uriref || read_node || read_literal
164
244
  end
165
245
  end
@@ -177,6 +257,9 @@ module RDF::NTriples
177
257
  subject = read_uriref || read_node || fail_subject
178
258
  predicate = read_uriref(:intern => true) || fail_predicate
179
259
  object = read_uriref || read_node || read_literal || fail_object
260
+ if validate? && !read_eos
261
+ raise RDF::ReaderError, "expected end of statement in line #{lineno}: #{current_line.inspect}"
262
+ end
180
263
  return [subject, predicate, object]
181
264
  end
182
265
  rescue RDF::ReaderError => e
@@ -201,6 +284,7 @@ module RDF::NTriples
201
284
  uri_str = self.class.unescape(uri_str)
202
285
  uri = RDF::URI.send(intern? && options[:intern] ? :intern : :new, uri_str)
203
286
  uri.validate! if validate?
287
+ raise RDF::ReaderError, "uri not absolute" if validate? && !uri.absolute?
204
288
  uri.canonicalize! if canonicalize?
205
289
  uri
206
290
  end
@@ -210,7 +294,7 @@ module RDF::NTriples
210
294
  # @return [RDF::Node]
211
295
  # @see http://www.w3.org/TR/rdf-testcases/#ntrip_grammar (nodeID)
212
296
  def read_node
213
- if node_id = match(NODEID)
297
+ if node_id = match(NODEID)
214
298
  @nodes ||= {}
215
299
  @nodes[node_id] ||= RDF::Node.new(node_id)
216
300
  end
@@ -223,7 +307,7 @@ module RDF::NTriples
223
307
  if literal_str = match(LITERAL_PLAIN)
224
308
  literal_str = self.class.unescape(literal_str)
225
309
  literal = case
226
- when language = match(LANGUAGE_TAG)
310
+ when language = match(LANGTAG)
227
311
  RDF::Literal.new(literal_str, :language => language)
228
312
  when datatype = match(/^(\^\^)/) # FIXME
229
313
  RDF::Literal.new(literal_str, :datatype => read_uriref || fail_object)
@@ -235,5 +319,12 @@ module RDF::NTriples
235
319
  literal
236
320
  end
237
321
  end
322
+
323
+ ##
324
+ # @return [Boolean]
325
+ # @see http://www.w3.org/TR/rdf-testcases/#ntrip_grammar (triple)
326
+ def read_eos
327
+ match(END_OF_STATEMENT)
328
+ end
238
329
  end # Reader
239
330
  end # RDF::NTriples
@@ -209,7 +209,7 @@ module RDF::NTriples
209
209
  # @param [Hash{Symbol => Object}] options
210
210
  # @return [String]
211
211
  def format_node(node, options = {})
212
- "_:%s" % node.id
212
+ node.to_base
213
213
  end
214
214
 
215
215
  ##
@@ -219,7 +219,7 @@ module RDF::NTriples
219
219
  # @param [Hash{Symbol => Object}] options
220
220
  # @return [String]
221
221
  def format_uri(uri, options = {})
222
- "<%s>" % escaped(uri_for(uri))
222
+ uri.to_base
223
223
  end
224
224
 
225
225
  ##
@@ -231,6 +231,7 @@ module RDF::NTriples
231
231
  def format_literal(literal, options = {})
232
232
  case literal
233
233
  when RDF::Literal
234
+ # Note, escaping here is more robust than in Term
234
235
  text = quoted(escaped(literal.value))
235
236
  text << "@#{literal.language}" if literal.has_language?
236
237
  text << "^^<#{uri_for(literal.datatype)}>" if literal.has_datatype?
@@ -129,10 +129,12 @@ module RDF
129
129
  # @option options [RDF::Resource, RDF::Query::Variable, false] :context (nil)
130
130
  # Default context for matching against queryable.
131
131
  # Named queries either match against a specifically named
132
- # contexts if the name is an {RDF::Resource} or bound {RDF::Query::Variable}.
133
- # Names that are against unbound variables match either detault
134
- # or named contexts.
132
+ # graphs if the name is an {RDF::Resource} or bound {RDF::Query::Variable}.
133
+ # Names that are against unbound variables match either default
134
+ # or named graphs.
135
135
  # The name of `false` will only match against the default context.
136
+ # @option options [RDF::Resource, RDF::Query::Variable, false] :name (nil)
137
+ # Alias for `:context`.
136
138
  # @yield [query]
137
139
  # @yieldparam [RDF::Query] query
138
140
  # @yieldreturn [void] ignored
@@ -146,9 +148,11 @@ module RDF
146
148
  # @option options [RDF::Resource, RDF::Query::Variable, false] :context (nil)
147
149
  # Default context for matching against queryable.
148
150
  # Named queries either match against a specifically named
149
- # contexts if the name is an {RDF::Resource} or bound {RDF::Query::Variable}.
150
- # Names that are against unbound variables match either detault
151
- # or named contexts.
151
+ # graphs if the name is an {RDF::Resource} or bound {RDF::Query::Variable}.
152
+ # Names that are against unbound variables match either default
153
+ # or named graphs.
154
+ # @option options [RDF::Resource, RDF::Query::Variable, false] :name (nil)
155
+ # Alias for `:context`.
152
156
  # @yield [query]
153
157
  # @yieldparam [RDF::Query] query
154
158
  # @yieldreturn [void] ignored
@@ -157,7 +161,9 @@ module RDF
157
161
  patterns << @options if patterns.empty?
158
162
  @variables = {}
159
163
  @solutions = @options.delete(:solutions) || Solutions.new
160
- context = @options.delete(:context)
164
+ context = @options.fetch(:context, @options.fetch(:name, nil))
165
+ @options.delete(:context)
166
+ @options.delete(:name)
161
167
 
162
168
  @patterns = case patterns.first
163
169
  when Hash then compile_hash_patterns(HashPatternNormalizer.normalize!(patterns.first.dup, @options))
@@ -246,6 +252,8 @@ module RDF
246
252
  # @option options [RDF::Resource, RDF::Query::Variable, false] context (nil)
247
253
  # Specific context for matching against queryable;
248
254
  # overrides default context defined on query.
255
+ # @option options [RDF::Resource, RDF::Query::Variable, false] name (nil)
256
+ # Alias for `:context`.
249
257
  # @option options [Hash{Symbol => RDF::Term}] solutions
250
258
  # optional initial solutions for chained queries
251
259
  # @return [RDF::Query::Solutions]
@@ -264,7 +272,7 @@ module RDF
264
272
  @solutions = options[:solutions] || (Solutions.new << RDF::Query::Solution.new({}))
265
273
 
266
274
  patterns = @patterns
267
- context = options.fetch(:context, self.context)
275
+ context = options.fetch(:context, options.fetch(:name, self.context))
268
276
 
269
277
  # Add context to pattern, if necessary
270
278
  unless context.nil?
@@ -349,27 +357,34 @@ module RDF
349
357
  Query.new(self.patterns + other.patterns)
350
358
  end
351
359
 
352
- # Is this is a named query?
360
+ # Is this query scoped to a named graph?
353
361
  # @return [Boolean]
354
362
  def named?
355
363
  !!options[:context]
356
364
  end
357
365
 
358
- # Is this is an unamed query?
366
+ # Is this query scoped to the default graph?
367
+ # @return [Boolean]
368
+ def default?
369
+ options[:context] == false
370
+ end
371
+
372
+ # Is this query unscoped? This indicates that it can return results from
373
+ # either a named graph or the default graph.
359
374
  # @return [Boolean]
360
375
  def unnamed?
361
- !named?
376
+ options[:context].nil?
362
377
  end
363
378
 
364
- # Add name to query
365
- # @param [RDF::Value] value
366
- # @return [RDF::Value]
379
+ # Scope the query to named graphs matching value
380
+ # @param [RDF::IRI, RDF::Query::Variable] value
381
+ # @return [RDF::IRI, RDF::Query::Variable]
367
382
  def context=(value)
368
383
  options[:context] = value
369
384
  end
370
385
 
371
- # Name of this query, if any
372
- # @return [RDF::Value]
386
+ # Scope of this query, if any
387
+ # @return [RDF::IRI, RDF::Query::Variable]
373
388
  def context
374
389
  options[:context]
375
390
  end
@@ -22,9 +22,11 @@ class RDF::Query
22
22
  #
23
23
  class Solution
24
24
  # Undefine all superfluous instance methods:
25
- undef_method(*(instance_methods.map(&:to_sym) - [:__id__, :__send__, :__class__, :__eval__,
26
- :object_id, :dup, :instance_eval, :inspect, :to_s,
27
- :class, :is_a?, :respond_to?, :respond_to_missing?]))
25
+ undef_method(*instance_methods.
26
+ map(&:to_s).
27
+ select {|m| m =~ /^\w+$/}.
28
+ reject {|m| %w(object_id dup instance_eval inspect to_s class).include?(m) || m[0,2] == '__'}.
29
+ map(&:to_sym))
28
30
 
29
31
  include Enumerable
30
32
 
@@ -29,17 +29,17 @@ module RDF; module Util
29
29
  # to override this implementation to provide more control over HTTP
30
30
  # headers and redirect following.
31
31
  # @option options [Array, String] :headers
32
- # HTTP Request headers, passed to Kernel.open.
32
+ # HTTP Request headers, passed to Kernel.open. (Ruby >= 1.9 only)
33
33
  # @return [IO] File stream
34
34
  # @yield [IO] File stream
35
35
  # @note HTTP headers not passed to `Kernel.open` for Ruby versions < 1.9.
36
36
  def self.open_file(filename_or_url, options = {}, &block)
37
37
  filename_or_url = $1 if filename_or_url.to_s.match(/^file:(.*)$/)
38
- options[:headers] ||= {}
39
- options[:headers]['Accept'] ||= RDF::Reader.map {|r| r.format.content_type}.uniq.join(", ")
40
38
  if RUBY_VERSION < "1.9"
41
39
  Kernel.open(filename_or_url.to_s, &block)
42
40
  else
41
+ options[:headers] ||= {}
42
+ options[:headers]['Accept'] ||= (RDF::Format.reader_types + %w(*/*;q=0.1)).join(", ")
43
43
  Kernel.open(filename_or_url.to_s, options[:headers], &block)
44
44
  end
45
45
  end
@@ -129,7 +129,11 @@ module RDF
129
129
  end
130
130
 
131
131
  # Undefine all superfluous instance methods:
132
- undef_method(*(instance_methods.map(&:to_sym) - [:__id__, :__send__, :__class__, :__eval__, :object_id, :instance_eval, :inspect, :class, :is_a?]))
132
+ undef_method(*instance_methods.
133
+ map(&:to_s).
134
+ select {|m| m =~ /^\w+$/}.
135
+ reject {|m| %w(object_id dup instance_eval inspect to_s class).include?(m) || m[0,2] == '__'}.
136
+ map(&:to_sym))
133
137
 
134
138
  ##
135
139
  # @param [RDF::URI, String, #to_s] uri
@@ -466,8 +466,13 @@ module RDF
466
466
  # @param [String] string
467
467
  # @return [String]
468
468
  def escaped(string)
469
- string.gsub('\\', '\\\\').gsub("\t", '\\t').
470
- gsub("\n", '\\n').gsub("\r", '\\r').gsub('"', '\\"')
469
+ string.gsub('\\', '\\\\').
470
+ gsub("\b", '\\b').
471
+ gsub("\f", '\\f').
472
+ gsub("\t", '\\t').
473
+ gsub("\n", '\\n').
474
+ gsub("\r", '\\r').
475
+ gsub('"', '\\"')
471
476
  end
472
477
 
473
478
  ##
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rdf
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
5
- prerelease:
4
+ version: 1.0.4
6
5
  platform: ruby
7
6
  authors:
8
7
  - Arto Bendiken
@@ -11,12 +10,11 @@ authors:
11
10
  autorequire:
12
11
  bindir: bin
13
12
  cert_chain: []
14
- date: 2013-02-26 00:00:00.000000000 Z
13
+ date: 2013-03-23 00:00:00.000000000 Z
15
14
  dependencies:
16
15
  - !ruby/object:Gem::Dependency
17
16
  name: addressable
18
17
  requirement: !ruby/object:Gem::Requirement
19
- none: false
20
18
  requirements:
21
19
  - - ! '>='
22
20
  - !ruby/object:Gem::Version
@@ -24,7 +22,6 @@ dependencies:
24
22
  type: :runtime
25
23
  prerelease: false
26
24
  version_requirements: !ruby/object:Gem::Requirement
27
- none: false
28
25
  requirements:
29
26
  - - ! '>='
30
27
  - !ruby/object:Gem::Version
@@ -32,7 +29,6 @@ dependencies:
32
29
  - !ruby/object:Gem::Dependency
33
30
  name: rdf-spec
34
31
  requirement: !ruby/object:Gem::Requirement
35
- none: false
36
32
  requirements:
37
33
  - - ~>
38
34
  - !ruby/object:Gem::Version
@@ -40,7 +36,6 @@ dependencies:
40
36
  type: :development
41
37
  prerelease: false
42
38
  version_requirements: !ruby/object:Gem::Requirement
43
- none: false
44
39
  requirements:
45
40
  - - ~>
46
41
  - !ruby/object:Gem::Version
@@ -48,7 +43,6 @@ dependencies:
48
43
  - !ruby/object:Gem::Dependency
49
44
  name: rspec
50
45
  requirement: !ruby/object:Gem::Requirement
51
- none: false
52
46
  requirements:
53
47
  - - ! '>='
54
48
  - !ruby/object:Gem::Version
@@ -56,7 +50,6 @@ dependencies:
56
50
  type: :development
57
51
  prerelease: false
58
52
  version_requirements: !ruby/object:Gem::Requirement
59
- none: false
60
53
  requirements:
61
54
  - - ! '>='
62
55
  - !ruby/object:Gem::Version
@@ -64,7 +57,6 @@ dependencies:
64
57
  - !ruby/object:Gem::Dependency
65
58
  name: yard
66
59
  requirement: !ruby/object:Gem::Requirement
67
- none: false
68
60
  requirements:
69
61
  - - ! '>='
70
62
  - !ruby/object:Gem::Version
@@ -72,7 +64,6 @@ dependencies:
72
64
  type: :development
73
65
  prerelease: false
74
66
  version_requirements: !ruby/object:Gem::Requirement
75
- none: false
76
67
  requirements:
77
68
  - - ! '>='
78
69
  - !ruby/object:Gem::Version
@@ -170,30 +161,26 @@ files:
170
161
  homepage: http://ruby-rdf.github.com/
171
162
  licenses:
172
163
  - Public Domain
164
+ metadata: {}
173
165
  post_install_message:
174
166
  rdoc_options: []
175
167
  require_paths:
176
168
  - lib
177
169
  required_ruby_version: !ruby/object:Gem::Requirement
178
- none: false
179
170
  requirements:
180
171
  - - ! '>='
181
172
  - !ruby/object:Gem::Version
182
173
  version: 1.8.1
183
174
  required_rubygems_version: !ruby/object:Gem::Requirement
184
- none: false
185
175
  requirements:
186
176
  - - ! '>='
187
177
  - !ruby/object:Gem::Version
188
178
  version: '0'
189
- segments:
190
- - 0
191
- hash: -2150851322746438702
192
179
  requirements: []
193
180
  rubyforge_project: rdf
194
- rubygems_version: 1.8.25
181
+ rubygems_version: 2.0.3
195
182
  signing_key:
196
- specification_version: 3
183
+ specification_version: 4
197
184
  summary: A Ruby library for working with Resource Description Framework (RDF) data.
198
185
  test_files: []
199
186
  has_rdoc: false