openlogic-rdf 0.3.6
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.
- data/AUTHORS +3 -0
- data/CREDITS +9 -0
- data/README +361 -0
- data/UNLICENSE +24 -0
- data/VERSION +1 -0
- data/bin/rdf +18 -0
- data/etc/doap.nt +62 -0
- data/lib/df.rb +1 -0
- data/lib/rdf/cli.rb +200 -0
- data/lib/rdf/format.rb +383 -0
- data/lib/rdf/mixin/countable.rb +39 -0
- data/lib/rdf/mixin/durable.rb +31 -0
- data/lib/rdf/mixin/enumerable.rb +637 -0
- data/lib/rdf/mixin/indexable.rb +26 -0
- data/lib/rdf/mixin/inferable.rb +5 -0
- data/lib/rdf/mixin/mutable.rb +191 -0
- data/lib/rdf/mixin/queryable.rb +265 -0
- data/lib/rdf/mixin/readable.rb +15 -0
- data/lib/rdf/mixin/type_check.rb +21 -0
- data/lib/rdf/mixin/writable.rb +152 -0
- data/lib/rdf/model/graph.rb +263 -0
- data/lib/rdf/model/list.rb +731 -0
- data/lib/rdf/model/literal/boolean.rb +121 -0
- data/lib/rdf/model/literal/date.rb +73 -0
- data/lib/rdf/model/literal/datetime.rb +72 -0
- data/lib/rdf/model/literal/decimal.rb +86 -0
- data/lib/rdf/model/literal/double.rb +189 -0
- data/lib/rdf/model/literal/integer.rb +126 -0
- data/lib/rdf/model/literal/numeric.rb +184 -0
- data/lib/rdf/model/literal/time.rb +87 -0
- data/lib/rdf/model/literal/token.rb +47 -0
- data/lib/rdf/model/literal/xml.rb +39 -0
- data/lib/rdf/model/literal.rb +373 -0
- data/lib/rdf/model/node.rb +156 -0
- data/lib/rdf/model/resource.rb +28 -0
- data/lib/rdf/model/statement.rb +296 -0
- data/lib/rdf/model/term.rb +77 -0
- data/lib/rdf/model/uri.rb +570 -0
- data/lib/rdf/model/value.rb +133 -0
- data/lib/rdf/nquads.rb +152 -0
- data/lib/rdf/ntriples/format.rb +48 -0
- data/lib/rdf/ntriples/reader.rb +239 -0
- data/lib/rdf/ntriples/writer.rb +219 -0
- data/lib/rdf/ntriples.rb +104 -0
- data/lib/rdf/query/pattern.rb +329 -0
- data/lib/rdf/query/solution.rb +252 -0
- data/lib/rdf/query/solutions.rb +237 -0
- data/lib/rdf/query/variable.rb +221 -0
- data/lib/rdf/query.rb +404 -0
- data/lib/rdf/reader.rb +511 -0
- data/lib/rdf/repository.rb +389 -0
- data/lib/rdf/transaction.rb +161 -0
- data/lib/rdf/util/aliasing.rb +63 -0
- data/lib/rdf/util/cache.rb +139 -0
- data/lib/rdf/util/file.rb +38 -0
- data/lib/rdf/util/uuid.rb +36 -0
- data/lib/rdf/util.rb +6 -0
- data/lib/rdf/version.rb +19 -0
- data/lib/rdf/vocab/cc.rb +18 -0
- data/lib/rdf/vocab/cert.rb +13 -0
- data/lib/rdf/vocab/dc.rb +63 -0
- data/lib/rdf/vocab/dc11.rb +23 -0
- data/lib/rdf/vocab/doap.rb +45 -0
- data/lib/rdf/vocab/exif.rb +168 -0
- data/lib/rdf/vocab/foaf.rb +69 -0
- data/lib/rdf/vocab/geo.rb +13 -0
- data/lib/rdf/vocab/http.rb +26 -0
- data/lib/rdf/vocab/owl.rb +59 -0
- data/lib/rdf/vocab/rdfs.rb +17 -0
- data/lib/rdf/vocab/rsa.rb +12 -0
- data/lib/rdf/vocab/rss.rb +14 -0
- data/lib/rdf/vocab/sioc.rb +93 -0
- data/lib/rdf/vocab/skos.rb +36 -0
- data/lib/rdf/vocab/wot.rb +21 -0
- data/lib/rdf/vocab/xhtml.rb +9 -0
- data/lib/rdf/vocab/xsd.rb +58 -0
- data/lib/rdf/vocab.rb +215 -0
- data/lib/rdf/writer.rb +475 -0
- data/lib/rdf.rb +192 -0
- metadata +173 -0
@@ -0,0 +1,373 @@
|
|
1
|
+
module RDF
|
2
|
+
##
|
3
|
+
# An RDF literal.
|
4
|
+
#
|
5
|
+
# Subclasses of {RDF::Literal} should define DATATYPE and GRAMMAR constants, which are used
|
6
|
+
# for identifying the appropriate class to use for a datatype URI and to perform lexical
|
7
|
+
# matching on the value.
|
8
|
+
#
|
9
|
+
# Literal comparison with other {RDF::Value} instances call {RDF::Value#type_error},
|
10
|
+
# which, returns false. Implementations wishing to have {RDF::TypeError} raised
|
11
|
+
# should mix-in {RDF::TypeCheck}. This is required for strict SPARQL conformance.
|
12
|
+
#
|
13
|
+
# Specific typed literals may have behavior different from the default implementation. See
|
14
|
+
# the following defined sub-classes for specific documentation. Additional sub-classes may
|
15
|
+
# be defined, and will interoperate by defining `DATATYPE` and `GRAMMAR` constants, in addition
|
16
|
+
# other required overrides of RDF::Literal behavior.
|
17
|
+
#
|
18
|
+
# * {RDF::Literal::Boolean}
|
19
|
+
# * {RDF::Literal::Date}
|
20
|
+
# * {RDF::Literal::DateTime}
|
21
|
+
# * {RDF::Literal::Decimal}
|
22
|
+
# * {RDF::Literal::Double}
|
23
|
+
# * {RDF::Literal::Integer}
|
24
|
+
# * {RDF::Literal::Time}
|
25
|
+
#
|
26
|
+
# @example Creating a plain literal
|
27
|
+
# value = RDF::Literal.new("Hello, world!")
|
28
|
+
# value.plain? #=> true`
|
29
|
+
#
|
30
|
+
# @example Creating a language-tagged literal (1)
|
31
|
+
# value = RDF::Literal.new("Hello!", :language => :en)
|
32
|
+
# value.has_language? #=> true
|
33
|
+
# value.language #=> :en
|
34
|
+
#
|
35
|
+
# @example Creating a language-tagged literal (2)
|
36
|
+
# RDF::Literal.new("Wazup?", :language => :"en-US")
|
37
|
+
# RDF::Literal.new("Hej!", :language => :sv)
|
38
|
+
# RDF::Literal.new("¡Hola!", :language => :es)
|
39
|
+
#
|
40
|
+
# @example Creating an explicitly datatyped literal
|
41
|
+
# value = RDF::Literal.new("2009-12-31", :datatype => RDF::XSD.date)
|
42
|
+
# value.has_datatype? #=> true
|
43
|
+
# value.datatype #=> RDF::XSD.date
|
44
|
+
#
|
45
|
+
# @example Creating an implicitly datatyped literal
|
46
|
+
# value = RDF::Literal.new(Date.today)
|
47
|
+
# value.has_datatype? #=> true
|
48
|
+
# value.datatype #=> RDF::XSD.date
|
49
|
+
#
|
50
|
+
# @example Creating implicitly datatyped literals
|
51
|
+
# RDF::Literal.new(false).datatype #=> XSD.boolean
|
52
|
+
# RDF::Literal.new(true).datatype #=> XSD.boolean
|
53
|
+
# RDF::Literal.new(123).datatype #=> XSD.integer
|
54
|
+
# RDF::Literal.new(9223372036854775807).datatype #=> XSD.integer
|
55
|
+
# RDF::Literal.new(3.1415).datatype #=> XSD.double
|
56
|
+
# RDF::Literal.new(Time.now).datatype #=> XSD.dateTime
|
57
|
+
# RDF::Literal.new(Date.new(2010)).datatype #=> XSD.date
|
58
|
+
# RDF::Literal.new(DateTime.new(2010)).datatype #=> XSD.dateTime
|
59
|
+
#
|
60
|
+
# @see http://www.w3.org/TR/rdf-concepts/#section-Literals
|
61
|
+
# @see http://www.w3.org/TR/rdf-concepts/#section-Datatypes-intro
|
62
|
+
class Literal
|
63
|
+
|
64
|
+
private
|
65
|
+
@@subclasses = [] # @private
|
66
|
+
|
67
|
+
##
|
68
|
+
# @private
|
69
|
+
# @return [void]
|
70
|
+
def self.inherited(child)
|
71
|
+
@@subclasses << child
|
72
|
+
super
|
73
|
+
end
|
74
|
+
|
75
|
+
public
|
76
|
+
|
77
|
+
require 'rdf/model/literal/numeric'
|
78
|
+
require 'rdf/model/literal/boolean'
|
79
|
+
require 'rdf/model/literal/decimal'
|
80
|
+
require 'rdf/model/literal/integer'
|
81
|
+
require 'rdf/model/literal/double'
|
82
|
+
require 'rdf/model/literal/date'
|
83
|
+
require 'rdf/model/literal/datetime'
|
84
|
+
require 'rdf/model/literal/time'
|
85
|
+
require 'rdf/model/literal/token'
|
86
|
+
require 'rdf/model/literal/xml'
|
87
|
+
|
88
|
+
include RDF::Term
|
89
|
+
|
90
|
+
##
|
91
|
+
# @private
|
92
|
+
# Return datatype class for uri, or nil if none is found
|
93
|
+
def self.datatyped_class(uri)
|
94
|
+
@@subclasses.detect {|klass| klass.const_defined?(:DATATYPE) && klass.const_get(:DATATYPE) == uri}
|
95
|
+
end
|
96
|
+
|
97
|
+
##
|
98
|
+
# @private
|
99
|
+
def self.new(value, options = {})
|
100
|
+
klass = case
|
101
|
+
when !self.equal?(RDF::Literal)
|
102
|
+
self # subclasses can be directly constructed without type dispatch
|
103
|
+
when typed_literal = datatyped_class(RDF::URI(options[:datatype]))
|
104
|
+
typed_literal
|
105
|
+
else case value
|
106
|
+
when ::TrueClass then RDF::Literal::Boolean
|
107
|
+
when ::FalseClass then RDF::Literal::Boolean
|
108
|
+
when ::Integer then RDF::Literal::Integer
|
109
|
+
when ::Float then RDF::Literal::Double
|
110
|
+
when ::BigDecimal then RDF::Literal::Decimal
|
111
|
+
when ::DateTime then RDF::Literal::DateTime
|
112
|
+
when ::Date then RDF::Literal::Date
|
113
|
+
when ::Time then RDF::Literal::Time # FIXME: Ruby's Time class can represent datetimes as well
|
114
|
+
when ::Symbol then RDF::Literal::Token
|
115
|
+
else self
|
116
|
+
end
|
117
|
+
end
|
118
|
+
literal = klass.allocate
|
119
|
+
literal.send(:initialize, value, options)
|
120
|
+
literal.validate! if options[:validate]
|
121
|
+
literal.canonicalize! if options[:canonicalize]
|
122
|
+
literal
|
123
|
+
end
|
124
|
+
|
125
|
+
TRUE = RDF::Literal.new(true).freeze
|
126
|
+
FALSE = RDF::Literal.new(false).freeze
|
127
|
+
ZERO = RDF::Literal.new(0).freeze
|
128
|
+
|
129
|
+
# @return [Symbol] The language tag (optional).
|
130
|
+
attr_accessor :language
|
131
|
+
|
132
|
+
# @return [URI] The XML Schema datatype URI (optional).
|
133
|
+
attr_accessor :datatype
|
134
|
+
|
135
|
+
##
|
136
|
+
# @param [Object] value
|
137
|
+
# @option options [Symbol] :language (nil)
|
138
|
+
# @option options [URI] :datatype (nil)
|
139
|
+
def initialize(value, options = {})
|
140
|
+
@object = value
|
141
|
+
@string = options[:lexical] if options[:lexical]
|
142
|
+
@string = value if !defined?(@string) && value.is_a?(String)
|
143
|
+
@language = options[:language].to_s.to_sym if options[:language]
|
144
|
+
@datatype = RDF::URI(options[:datatype]) if options[:datatype]
|
145
|
+
@datatype ||= self.class.const_get(:DATATYPE) if self.class.const_defined?(:DATATYPE)
|
146
|
+
end
|
147
|
+
|
148
|
+
##
|
149
|
+
# Returns the value as a string.
|
150
|
+
#
|
151
|
+
# @return [String]
|
152
|
+
def value
|
153
|
+
@string || to_s
|
154
|
+
end
|
155
|
+
|
156
|
+
##
|
157
|
+
# @return [Object]
|
158
|
+
def object
|
159
|
+
defined?(@object) ? @object : value
|
160
|
+
end
|
161
|
+
|
162
|
+
##
|
163
|
+
# Returns `true`.
|
164
|
+
#
|
165
|
+
# @return [Boolean] `true` or `false`
|
166
|
+
def literal?
|
167
|
+
true
|
168
|
+
end
|
169
|
+
|
170
|
+
##
|
171
|
+
# Returns `false`.
|
172
|
+
#
|
173
|
+
# @return [Boolean] `true` or `false`
|
174
|
+
def anonymous?
|
175
|
+
false
|
176
|
+
end
|
177
|
+
|
178
|
+
##
|
179
|
+
# Returns a hash code for this literal.
|
180
|
+
#
|
181
|
+
# @return [Fixnum]
|
182
|
+
def hash
|
183
|
+
to_s.hash
|
184
|
+
end
|
185
|
+
|
186
|
+
##
|
187
|
+
# Determins if `self` is the same term as `other`.
|
188
|
+
#
|
189
|
+
# @example
|
190
|
+
# RDF::Literal(1).eql?(RDF::Literal(1.0)) #=> false
|
191
|
+
#
|
192
|
+
# @param [Object] other
|
193
|
+
# @return [Boolean] `true` or `false`
|
194
|
+
def eql?(other)
|
195
|
+
self.equal?(other) ||
|
196
|
+
(self.class.eql?(other.class) &&
|
197
|
+
self.value.eql?(other.value) &&
|
198
|
+
self.language.to_s.downcase.eql?(other.language.to_s.downcase) &&
|
199
|
+
self.datatype.eql?(other.datatype))
|
200
|
+
end
|
201
|
+
|
202
|
+
##
|
203
|
+
# Returns `true` if this literal is equivalent to `other` (with type check).
|
204
|
+
#
|
205
|
+
# @example
|
206
|
+
# RDF::Literal(1) == RDF::Literal(1.0) #=> true
|
207
|
+
#
|
208
|
+
# @param [Object] other
|
209
|
+
# @return [Boolean] `true` or `false`
|
210
|
+
#
|
211
|
+
# @see http://www.w3.org/TR/rdf-sparql-query/#func-RDFterm-equal
|
212
|
+
# @see http://www.w3.org/TR/rdf-concepts/#section-Literal-Equality
|
213
|
+
def ==(other)
|
214
|
+
case other
|
215
|
+
when Literal
|
216
|
+
case
|
217
|
+
when self.eql?(other)
|
218
|
+
true
|
219
|
+
when self.has_language? && self.language.to_s.downcase == other.language.to_s.downcase
|
220
|
+
# Literals with languages can compare if languages are identical
|
221
|
+
self.value == other.value
|
222
|
+
when (self.simple? || self.datatype == XSD.string) && (other.simple? || other.datatype == XSD.string)
|
223
|
+
self.value == other.value
|
224
|
+
when other.comperable_datatype?(self) || self.comperable_datatype?(other)
|
225
|
+
# Comoparing plain with undefined datatypes does not generate an error, but returns false
|
226
|
+
# From data-r2/expr-equal/eq-2-2.
|
227
|
+
false
|
228
|
+
else
|
229
|
+
type_error("unable to determine whether #{self.inspect} and #{other.inspect} are equivalent")
|
230
|
+
end
|
231
|
+
when String
|
232
|
+
self.plain? && self.value.eql?(other)
|
233
|
+
else false
|
234
|
+
end
|
235
|
+
end
|
236
|
+
alias_method :===, :==
|
237
|
+
|
238
|
+
##
|
239
|
+
# Returns `true` if this is a plain literal.
|
240
|
+
#
|
241
|
+
# @return [Boolean] `true` or `false`
|
242
|
+
# @see http://www.w3.org/TR/rdf-concepts/#dfn-plain-literal
|
243
|
+
def plain?
|
244
|
+
language.nil? && datatype.nil?
|
245
|
+
end
|
246
|
+
alias_method :simple?, :plain?
|
247
|
+
|
248
|
+
##
|
249
|
+
# Returns `true` if this is a language-tagged literal.
|
250
|
+
#
|
251
|
+
# @return [Boolean] `true` or `false`
|
252
|
+
# @see http://www.w3.org/TR/rdf-concepts/#dfn-plain-literal
|
253
|
+
def has_language?
|
254
|
+
!language.nil?
|
255
|
+
end
|
256
|
+
alias_method :language?, :has_language?
|
257
|
+
|
258
|
+
##
|
259
|
+
# Returns `true` if this is a datatyped literal.
|
260
|
+
#
|
261
|
+
# @return [Boolean] `true` or `false`
|
262
|
+
# @see http://www.w3.org/TR/rdf-concepts/#dfn-typed-literal
|
263
|
+
def has_datatype?
|
264
|
+
!datatype.nil?
|
265
|
+
end
|
266
|
+
alias_method :datatype?, :has_datatype?
|
267
|
+
alias_method :typed?, :has_datatype?
|
268
|
+
alias_method :datatyped?, :has_datatype?
|
269
|
+
|
270
|
+
##
|
271
|
+
# Returns `true` if the value adheres to the defined grammar of the
|
272
|
+
# datatype.
|
273
|
+
#
|
274
|
+
# @return [Boolean] `true` or `false`
|
275
|
+
# @since 0.2.1
|
276
|
+
def valid?
|
277
|
+
grammar = self.class.const_get(:GRAMMAR) rescue nil
|
278
|
+
grammar.nil? || !!(value =~ grammar)
|
279
|
+
end
|
280
|
+
|
281
|
+
##
|
282
|
+
# Returns `true` if the value does not adhere to the defined grammar of
|
283
|
+
# the datatype.
|
284
|
+
#
|
285
|
+
# @return [Boolean] `true` or `false`
|
286
|
+
# @since 0.2.1
|
287
|
+
def invalid?
|
288
|
+
!valid?
|
289
|
+
end
|
290
|
+
|
291
|
+
##
|
292
|
+
# Returns `true` if the literal has a datatype and the comparison should
|
293
|
+
# return false instead of raise a type error.
|
294
|
+
#
|
295
|
+
# This behavior is intuited from SPARQL data-r2/expr-equal/eq-2-2
|
296
|
+
# @return [Boolean]
|
297
|
+
def comperable_datatype?(other)
|
298
|
+
return false unless self.plain? || self.has_language?
|
299
|
+
|
300
|
+
case other
|
301
|
+
when RDF::Literal::Numeric, RDF::Literal::Boolean,
|
302
|
+
RDF::Literal::Date, RDF::Literal::Time, RDF::Literal::DateTime
|
303
|
+
# Invald types can be compared without raising a TypeError if literal has a language (open-eq-08)
|
304
|
+
!other.valid? && self.has_language?
|
305
|
+
else
|
306
|
+
case other.datatype
|
307
|
+
when XSD.string
|
308
|
+
true
|
309
|
+
when nil
|
310
|
+
# A different language will not generate a type error
|
311
|
+
other.has_language?
|
312
|
+
else
|
313
|
+
# An unknown datatype may not be used for comparison, unless it has a language? (open-eq-8)
|
314
|
+
self.has_language?
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
##
|
320
|
+
# Validates the value using {#valid?}, raising an error if the value is
|
321
|
+
# invalid.
|
322
|
+
#
|
323
|
+
# @return [RDF::Literal] `self`
|
324
|
+
# @raise [ArgumentError] if the value is invalid
|
325
|
+
# @since 0.2.1
|
326
|
+
def validate!
|
327
|
+
raise ArgumentError, "#{to_s.inspect} is not a valid <#{datatype.to_s}> literal" if invalid?
|
328
|
+
self
|
329
|
+
end
|
330
|
+
alias_method :validate, :validate!
|
331
|
+
|
332
|
+
##
|
333
|
+
# Returns a copy of this literal converted into its canonical lexical
|
334
|
+
# representation.
|
335
|
+
#
|
336
|
+
# Subclasses should override `#canonicalize!` as needed and appropriate,
|
337
|
+
# not this method.
|
338
|
+
#
|
339
|
+
# @return [RDF::Literal]
|
340
|
+
# @since 0.2.1
|
341
|
+
def canonicalize
|
342
|
+
self.dup.canonicalize!
|
343
|
+
end
|
344
|
+
|
345
|
+
##
|
346
|
+
# Converts this literal into its canonical lexical representation.
|
347
|
+
#
|
348
|
+
# Subclasses should override this as needed and appropriate.
|
349
|
+
#
|
350
|
+
# @return [RDF::Literal] `self`
|
351
|
+
# @since 0.3.0
|
352
|
+
def canonicalize!
|
353
|
+
@language = @language.to_s.downcase.to_sym if @language
|
354
|
+
self
|
355
|
+
end
|
356
|
+
|
357
|
+
##
|
358
|
+
# Returns the value as a string.
|
359
|
+
#
|
360
|
+
# @return [String]
|
361
|
+
def to_s
|
362
|
+
@object.to_s
|
363
|
+
end
|
364
|
+
|
365
|
+
##
|
366
|
+
# Returns a developer-friendly representation of `self`.
|
367
|
+
#
|
368
|
+
# @return [String]
|
369
|
+
def inspect
|
370
|
+
sprintf("#<%s:%#0x(%s)>", self.class.name, __id__, RDF::NTriples.serialize(self))
|
371
|
+
end
|
372
|
+
end # Literal
|
373
|
+
end # RDF
|
@@ -0,0 +1,156 @@
|
|
1
|
+
module RDF
|
2
|
+
##
|
3
|
+
# An RDF blank node, also known as an anonymous or unlabeled node.
|
4
|
+
#
|
5
|
+
# @example Creating a blank node with an implicit identifier
|
6
|
+
# bnode = RDF::Node.new
|
7
|
+
#
|
8
|
+
# @example Creating a blank node with an UUID identifier
|
9
|
+
# bnode = RDF::Node.uuid
|
10
|
+
# bnode.to_s #=> "_:504c0a30-0d11-012d-3f50-001b63cac539"
|
11
|
+
#
|
12
|
+
class Node
|
13
|
+
include RDF::Resource
|
14
|
+
|
15
|
+
##
|
16
|
+
# Returns a blank node with a random UUID-based identifier.
|
17
|
+
#
|
18
|
+
# @param [Hash{Symbol => Object}] options
|
19
|
+
# @option options [Regexp] :grammar (nil)
|
20
|
+
# a grammar specification that the generated UUID must match
|
21
|
+
# @return [RDF::Node]
|
22
|
+
def self.uuid(options = {})
|
23
|
+
case
|
24
|
+
when options[:grammar]
|
25
|
+
# The UUID is generated such that its initial part is guaranteed
|
26
|
+
# to match the given `grammar`, e.g. `/^[A-Za-z][A-Za-z0-9]*/`.
|
27
|
+
# Some RDF storage systems (e.g. AllegroGraph) require this.
|
28
|
+
# @see http://github.com/bendiken/rdf/pull/43
|
29
|
+
uuid = RDF::Util::UUID.generate(options) until uuid =~ options[:grammar]
|
30
|
+
else
|
31
|
+
uuid = RDF::Util::UUID.generate(options)
|
32
|
+
end
|
33
|
+
self.new(uuid)
|
34
|
+
end
|
35
|
+
|
36
|
+
##
|
37
|
+
# Alias for `RDF::Node.new`, at the moment.
|
38
|
+
#
|
39
|
+
# @private
|
40
|
+
# @param [#to_s] id
|
41
|
+
# @return [RDF::Node]
|
42
|
+
# @since 0.2.0
|
43
|
+
def self.intern(id)
|
44
|
+
self.new(id)
|
45
|
+
end
|
46
|
+
|
47
|
+
##
|
48
|
+
# Override #dup to remember original object.
|
49
|
+
# This allows .eql? to determine that two nodes
|
50
|
+
# are the same thing, and not different nodes
|
51
|
+
# instantiated with the same identifier.
|
52
|
+
# @return [RDF::Node]
|
53
|
+
def dup
|
54
|
+
node = super
|
55
|
+
node.original = self.original || self
|
56
|
+
node
|
57
|
+
end
|
58
|
+
|
59
|
+
##
|
60
|
+
# Originally instantiated node, if any
|
61
|
+
# @return [RDF::Node]
|
62
|
+
attr_accessor :original
|
63
|
+
|
64
|
+
# @return [String]
|
65
|
+
attr_accessor :id
|
66
|
+
|
67
|
+
##
|
68
|
+
# @param [#to_s] id
|
69
|
+
def initialize(id = nil)
|
70
|
+
@id = (id || "g#{__id__.to_i.abs}").to_s
|
71
|
+
end
|
72
|
+
|
73
|
+
##
|
74
|
+
# Returns `true`.
|
75
|
+
#
|
76
|
+
# @return [Boolean]
|
77
|
+
def node?
|
78
|
+
true
|
79
|
+
end
|
80
|
+
|
81
|
+
##
|
82
|
+
# Returns `true`.
|
83
|
+
#
|
84
|
+
# @return [Boolean]
|
85
|
+
def anonymous?
|
86
|
+
true
|
87
|
+
end
|
88
|
+
|
89
|
+
alias_method :unlabeled?, :anonymous?
|
90
|
+
|
91
|
+
##
|
92
|
+
# Returns `false`.
|
93
|
+
#
|
94
|
+
# @return [Boolean]
|
95
|
+
def labeled?
|
96
|
+
!unlabeled?
|
97
|
+
end
|
98
|
+
|
99
|
+
##
|
100
|
+
# Returns a hash code for this blank node.
|
101
|
+
#
|
102
|
+
# @return [Fixnum]
|
103
|
+
def hash
|
104
|
+
@id.hash
|
105
|
+
end
|
106
|
+
|
107
|
+
##
|
108
|
+
# Determins if `self` is the same term as `other`.
|
109
|
+
#
|
110
|
+
# In this case, nodes must be the same object
|
111
|
+
#
|
112
|
+
# @param [Node] other
|
113
|
+
# @return [Boolean]
|
114
|
+
def eql?(other)
|
115
|
+
other.is_a?(RDF::Node) && (self.original || self).equal?(other.original || other)
|
116
|
+
end
|
117
|
+
|
118
|
+
##
|
119
|
+
# Checks whether this blank node is equal to `other` (type checking).
|
120
|
+
#
|
121
|
+
# In this case, different nodes having the same id are considered the same.
|
122
|
+
#
|
123
|
+
# Per SPARQL data-r2/expr-equal/eq-2-2, numeric can't be compared with other types
|
124
|
+
#
|
125
|
+
# @param [Object] other
|
126
|
+
# @return [Boolean]
|
127
|
+
# @see http://www.w3.org/TR/rdf-sparql-query/#func-RDFterm-equal
|
128
|
+
def ==(other)
|
129
|
+
case other
|
130
|
+
when Literal
|
131
|
+
# If other is a Literal, reverse test to consolodate complex type checking logic
|
132
|
+
other == self
|
133
|
+
else
|
134
|
+
other.respond_to?(:node?) && other.node? && other.respond_to?(:id) && @id == other.id
|
135
|
+
end
|
136
|
+
end
|
137
|
+
alias_method :===, :==
|
138
|
+
|
139
|
+
##
|
140
|
+
# Returns a string representation of this blank node.
|
141
|
+
#
|
142
|
+
# @return [String]
|
143
|
+
def to_s
|
144
|
+
"_:%s" % @id.to_s
|
145
|
+
end
|
146
|
+
|
147
|
+
##
|
148
|
+
# Returns a symbol representation of this blank node.
|
149
|
+
#
|
150
|
+
# @return [Symbol]
|
151
|
+
# @since 0.2.0
|
152
|
+
def to_sym
|
153
|
+
@id.to_s.to_sym
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module RDF
|
2
|
+
##
|
3
|
+
# An RDF resource.
|
4
|
+
module Resource
|
5
|
+
include RDF::Term
|
6
|
+
|
7
|
+
##
|
8
|
+
# Instantiates an {RDF::Node} or an {RDF::URI}, depending on the given
|
9
|
+
# argument.
|
10
|
+
#
|
11
|
+
# @return [RDF::Resource]
|
12
|
+
def self.new(*args, &block)
|
13
|
+
case arg = args.shift
|
14
|
+
when Symbol then Node.intern(arg, *args, &block)
|
15
|
+
when /^_:(.*)$/ then Node.new($1, *args, &block)
|
16
|
+
else URI.new(arg, *args, &block)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
##
|
21
|
+
# Returns `true` to indicate that this value is a resource.
|
22
|
+
#
|
23
|
+
# @return [Boolean]
|
24
|
+
def resource?
|
25
|
+
true
|
26
|
+
end
|
27
|
+
end # Resource
|
28
|
+
end # RDF
|