rdf 0.1.10 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,22 +1,19 @@
1
1
  module RDF
2
2
  ##
3
3
  # An RDF resource.
4
- #
5
- # @abstract
6
- class Resource < Value
4
+ module Resource
5
+ include RDF::Value
6
+
7
7
  ##
8
8
  # Instantiates an {RDF::Node} or an {RDF::URI}, depending on the given
9
9
  # argument.
10
10
  #
11
11
  # @return [RDF::Resource]
12
12
  def self.new(*args, &block)
13
- if self == Resource
14
- case arg = args.shift
15
- when /^_:(.*)$/ then Node.new($1, *args, &block)
16
- else URI.new(arg, *args, &block)
17
- end
18
- else
19
- super
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)
20
17
  end
21
18
  end
22
19
 
@@ -18,56 +18,67 @@ module RDF
18
18
  # :object => RDF::URI.new("http://ar.to/#self"),
19
19
  # })
20
20
  #
21
- class Statement < Value
21
+ class Statement
22
+ include RDF::Value
23
+
22
24
  # @return [Object]
23
25
  attr_accessor :id
24
26
 
25
- # @return [Resource]
27
+ # @return [RDF::Resource]
26
28
  attr_accessor :context
27
29
 
28
- # @return [Resource]
30
+ # @return [RDF::Resource]
29
31
  attr_accessor :subject
30
32
 
31
- # @return [URI]
33
+ # @return [RDF::URI]
32
34
  attr_accessor :predicate
33
35
 
34
- # @return [Value]
36
+ # @return [RDF::Value]
35
37
  attr_accessor :object
36
38
 
37
39
  ##
38
40
  # @overload initialize(options = {})
39
41
  # @param [Hash{Symbol => Object}] options
40
- # @option options [Resource] :subject (nil)
41
- # @option options [URI] :predicate (nil)
42
- # @option options [Value] :object (nil)
43
- # @option options [Resource] :context (nil)
42
+ # @option options [RDF::Resource] :subject (nil)
43
+ # @option options [RDF::URI] :predicate (nil)
44
+ # @option options [RDF::Value] :object (nil)
45
+ # @option options [RDF::Resource] :context (nil)
44
46
  #
45
47
  # @overload initialize(subject, predicate, object, options = {})
46
- # @param [Resource] subject
47
- # @param [URI] predicate
48
- # @param [Value] object
48
+ # @param [RDF::Resource] subject
49
+ # @param [RDF::URI] predicate
50
+ # @param [RDF::Value] object
49
51
  # @param [Hash{Symbol => Object}] options
50
- # @option options [Resource] :context (nil)
52
+ # @option options [RDF::Resource] :context (nil)
51
53
  def initialize(subject = nil, predicate = nil, object = nil, options = {})
52
- options = options.dup unless options.empty?
53
54
  case subject
54
55
  when Hash
55
- options = subject.dup
56
- subject = options.delete(:subject)
57
- predicate = options.delete(:predicate)
58
- object = options.delete(:object)
59
- initialize(subject, predicate, object, options)
56
+ @options = subject.dup
57
+ @subject = @options.delete(:subject)
58
+ @predicate = @options.delete(:predicate)
59
+ @object = @options.delete(:object)
60
60
  else
61
- @id = options.delete(:id) if options.has_key?(:id)
62
- @context = options.delete(:context) || options.delete(:graph)
63
- @options = options
61
+ @options = !options.empty? ? options.dup : {}
64
62
  @subject = subject
65
63
  @predicate = predicate
66
- @object = case object
67
- when nil then nil
68
- when RDF::Value then object
69
- else RDF::Literal.new(object)
70
- end
64
+ @object = object
65
+ end
66
+ @id = @options.delete(:id) if @options.has_key?(:id)
67
+ @context = @options.delete(:context) || @options.delete(:graph)
68
+ initialize!
69
+ end
70
+
71
+ ##
72
+ # @private
73
+ def initialize!
74
+ @context = Node.intern(@context) if @context.is_a?(Symbol)
75
+ @subject = Node.intern(@subject) if @subject.is_a?(Symbol)
76
+ @predicate = Node.intern(@predicate) if @predicate.is_a?(Symbol)
77
+ @object = case @object
78
+ when nil then nil
79
+ when Symbol then Node.intern(@object)
80
+ when Value then @object
81
+ else Literal.new(@object)
71
82
  end
72
83
  end
73
84
 
@@ -167,32 +178,39 @@ module RDF
167
178
 
168
179
  ##
169
180
  # @param [Integer] index
170
- # @return [Value]
181
+ # @return [RDF::Value]
171
182
  def [](index)
172
- to_a[index]
183
+ case index
184
+ when 0 then self.subject
185
+ when 1 then self.predicate
186
+ when 2 then self.object
187
+ when 3 then self.context
188
+ else nil
189
+ end
173
190
  end
174
191
 
175
192
  ##
176
- # @param [Integer] index
177
- # @param [Value] value
178
- # @return [Value]
193
+ # @param [Integer] index
194
+ # @param [RDF::Value] value
195
+ # @return [RDF::Value]
179
196
  def []=(index, value)
180
197
  case index
181
- when 0 then subject = value
182
- when 1 then predicate = value
183
- when 2 then object = value
184
- when 3 then context = value
198
+ when 0 then self.subject = value
199
+ when 1 then self.predicate = value
200
+ when 2 then self.object = value
201
+ when 3 then self.context = value
202
+ else nil
185
203
  end
186
204
  end
187
205
 
188
206
  ##
189
- # @return [Array(Value)]
207
+ # @return [Array(RDF::Value)]
190
208
  def to_quad
191
209
  [subject, predicate, object, context]
192
210
  end
193
211
 
194
212
  ##
195
- # @return [Array(Value)]
213
+ # @return [Array(RDF::Value)]
196
214
  def to_triple
197
215
  [subject, predicate, object]
198
216
  end
@@ -206,9 +224,9 @@ module RDF
206
224
  # @param [Symbol] subject_key
207
225
  # @param [Symbol] predicate_key
208
226
  # @param [Symbol] object_key
209
- # @return [Hash{Symbol => Value}]
210
- def to_hash(subject_key = :subject, predicate_key = :predicate, object_key = :object)
211
- {subject_key => subject, predicate_key => predicate, object_key => object}
227
+ # @return [Hash{Symbol => RDF::Value}]
228
+ def to_hash(subject_key = :subject, predicate_key = :predicate, object_key = :object, context_key = :context)
229
+ {subject_key => subject, predicate_key => predicate, object_key => object, context_key => context}
212
230
  end
213
231
 
214
232
  ##
@@ -12,22 +12,61 @@ module RDF
12
12
  # @example Creating a URI reference (2)
13
13
  # uri = RDF::URI.new(:scheme => 'http', :host => 'rdf.rubyforge.org', :path => '/')
14
14
  #
15
+ # @example Creating an interned URI reference
16
+ # uri = RDF::URI.intern("http://rdf.rubyforge.org/")
17
+ #
15
18
  # @example Getting the string representation of a URI
16
19
  # uri.to_s #=> "http://rdf.rubyforge.org/"
17
20
  #
18
21
  # @see http://en.wikipedia.org/wiki/Uniform_Resource_Identifier
19
22
  # @see http://addressable.rubyforge.org/
20
- class URI < Resource
23
+ class URI
24
+ include RDF::Resource
25
+
26
+ ##
27
+ # Defines the maximum number of interned URI references that can be held
28
+ # cached in memory at any one time.
29
+ CACHE_SIZE = -1 # unlimited by default
30
+
31
+ ##
32
+ # @return [RDF::Util::Cache]
33
+ # @private
34
+ def self.cache
35
+ require 'rdf/util/cache' unless defined?(::RDF::Util::Cache)
36
+ @cache ||= RDF::Util::Cache.new(CACHE_SIZE)
37
+ end
38
+
39
+ ##
40
+ # Returns an interned `RDF::URI` instance based on the given `uri`
41
+ # string.
42
+ #
43
+ # The maximum number of cached interned URI references is given by the
44
+ # `CACHE_SIZE` constant. This value is unlimited by default, in which
45
+ # case an interned URI object will be purged only when the last strong
46
+ # reference to it is garbage collection (i.e., when its finalizer runs).
47
+ #
48
+ # Excepting special memory-limited circumstances, it should always be
49
+ # safe and preferred to construct new URI references using
50
+ # `RDF::URI.intern` instead of `RDF::URI.new`, since if an interned
51
+ # object can't be returned for some reason, this method will fall back
52
+ # to returning a freshly-allocated one.
53
+ #
54
+ # @param [String, #to_s] str
55
+ # @return [RDF::URI]
56
+ def self.intern(str)
57
+ cache[str = str.to_s] ||= self.new(str)
58
+ end
59
+
21
60
  ##
22
61
  # Creates a new `RDF::URI` instance based on the given `uri` string.
23
62
  #
24
63
  # This is just an alias for {#initialize RDF::URI.new} for compatibity
25
64
  # with `Addressable::URI.parse`.
26
65
  #
27
- # @param [String] uri
28
- # @return [URI]
29
- def self.parse(uri)
30
- self.new(uri)
66
+ # @param [String, #to_s] str
67
+ # @return [RDF::URI]
68
+ def self.parse(str)
69
+ self.new(str)
31
70
  end
32
71
 
33
72
  ##
@@ -47,20 +86,41 @@ module RDF
47
86
  end
48
87
  end
49
88
 
89
+ ##
90
+ # Returns `false`.
91
+ #
92
+ # @return [Boolean]
93
+ def anonymous?
94
+ false
95
+ end
96
+
50
97
  ##
51
98
  # Returns `true`.
52
99
  #
53
100
  # @return [Boolean]
101
+ # @see http://en.wikipedia.org/wiki/Uniform_Resource_Identifier
54
102
  def uri?
55
103
  true
56
104
  end
57
105
 
58
106
  ##
59
- # Returns `false`.
107
+ # Returns `true` if this URI is a URN.
60
108
  #
61
109
  # @return [Boolean]
62
- def anonymous?
63
- false
110
+ # @see http://en.wikipedia.org/wiki/Uniform_Resource_Name
111
+ # @since 0.2.0
112
+ def urn?
113
+ to_s.index('urn:') == 0
114
+ end
115
+
116
+ ##
117
+ # Returns `true` if this URI is a URL.
118
+ #
119
+ # @return [Boolean]
120
+ # @see http://en.wikipedia.org/wiki/Uniform_Resource_Locator
121
+ # @since 0.2.0
122
+ def url?
123
+ !urn?
64
124
  end
65
125
 
66
126
  ##
@@ -2,9 +2,9 @@ module RDF
2
2
  ##
3
3
  # An RDF value.
4
4
  #
5
- # This is the base class for the RDF.rb class hierarchy. The class of
6
- # every object that can be a term of {RDF::Statement statements} is a
7
- # subclass of this class.
5
+ # This is the basis for the RDF.rb class hierarchy. Anything that can be a
6
+ # term of {RDF::Statement RDF statements} should directly or indirectly
7
+ # include this module.
8
8
  #
9
9
  # @example Checking if a value is a resource (blank node or URI reference)
10
10
  # value.resource?
@@ -19,18 +19,17 @@ module RDF
19
19
  # @example Checking if a value is a literal
20
20
  # value.literal?
21
21
  #
22
- # @abstract
23
22
  # @see RDF::Graph
24
23
  # @see RDF::Literal
25
24
  # @see RDF::Node
26
25
  # @see RDF::Resource
27
26
  # @see RDF::Statement
28
27
  # @see RDF::URI
29
- class Value
28
+ module Value
30
29
  include Comparable
31
30
 
32
31
  ##
33
- # Returns `true` if this value is a graph.
32
+ # Returns `true` if `self` is a graph.
34
33
  #
35
34
  # @return [Boolean]
36
35
  def graph?
@@ -38,7 +37,7 @@ module RDF
38
37
  end
39
38
 
40
39
  ##
41
- # Returns `true` if this value is a literal.
40
+ # Returns `true` if `self` is a literal.
42
41
  #
43
42
  # @return [Boolean]
44
43
  def literal?
@@ -46,7 +45,7 @@ module RDF
46
45
  end
47
46
 
48
47
  ##
49
- # Returns `true` if this value is a blank node.
48
+ # Returns `true` if `self` is a blank node.
50
49
  #
51
50
  # @return [Boolean]
52
51
  def node?
@@ -54,7 +53,7 @@ module RDF
54
53
  end
55
54
 
56
55
  ##
57
- # Returns `true` if this value is a resource.
56
+ # Returns `true` if `self` is a resource.
58
57
  #
59
58
  # @return [Boolean]
60
59
  def resource?
@@ -62,7 +61,7 @@ module RDF
62
61
  end
63
62
 
64
63
  ##
65
- # Returns `true` if this value is a statement.
64
+ # Returns `true` if `self` is a statement.
66
65
  #
67
66
  # @return [Boolean]
68
67
  def statement?
@@ -70,17 +69,25 @@ module RDF
70
69
  end
71
70
 
72
71
  ##
73
- # Returns `true` if this value is a URI reference.
72
+ # Returns `true` if `self` is an IRI reference.
73
+ #
74
+ # By default this is simply an alias for {#uri?}.
75
+ #
76
+ # @return [Boolean]
77
+ def iri?
78
+ uri?
79
+ end
80
+
81
+ ##
82
+ # Returns `true` if `self` is a URI reference.
74
83
  #
75
84
  # @return [Boolean]
76
85
  def uri?
77
86
  false
78
87
  end
79
88
 
80
- alias_method :iri?, :uri?
81
-
82
89
  ##
83
- # Returns `true` if this value is a query variable.
90
+ # Returns `true` if `self` is a query variable.
84
91
  #
85
92
  # @return [Boolean]
86
93
  # @since 0.1.7
@@ -89,7 +96,7 @@ module RDF
89
96
  end
90
97
 
91
98
  ##
92
- # Compares this value to `other` for sorting purposes.
99
+ # Compares `self` to `other` for sorting purposes.
93
100
  #
94
101
  # Subclasses should override this to provide a more meaningful
95
102
  # implementation than the default which simply performs a string
@@ -103,15 +110,15 @@ module RDF
103
110
  end
104
111
 
105
112
  ##
106
- # Returns an RDF::Value representation of this object.
113
+ # Returns an `RDF::Value` representation of `self`.
107
114
  #
108
- # @return [Value]
115
+ # @return [RDF::Value]
109
116
  def to_rdf
110
117
  self
111
118
  end
112
119
 
113
120
  ##
114
- # Returns a developer-friendly representation of this value.
121
+ # Returns a developer-friendly representation of `self`.
115
122
  #
116
123
  # The result will be of the format `#<RDF::Value::0x12345678(...)>`,
117
124
  # where `...` is the string returned by `#to_s`.
@@ -122,23 +129,11 @@ module RDF
122
129
  end
123
130
 
124
131
  ##
125
- # Outputs a developer-friendly representation of this value to `stderr`.
132
+ # Outputs a developer-friendly representation of `self` to `stderr`.
126
133
  #
127
134
  # @return [void]
128
135
  def inspect!
129
136
  warn(inspect)
130
137
  end
131
-
132
- private
133
-
134
- # Prevent the instantiation of this class:
135
- private_class_method :new
136
-
137
- def self.inherited(child) # @private
138
- # Enable the instantiation of any subclasses:
139
- child.send(:public_class_method, :new)
140
- super
141
- end
142
-
143
138
  end
144
139
  end
@@ -75,7 +75,7 @@ module RDF::NTriples
75
75
  # @param [String] input
76
76
  # @return [RDF::URI]
77
77
  def self.parse_predicate(input)
78
- parse_uri(input)
78
+ parse_uri(input, :intern => true)
79
79
  end
80
80
 
81
81
  ##
@@ -97,9 +97,9 @@ module RDF::NTriples
97
97
  ##
98
98
  # @param [String] input
99
99
  # @return [RDF::URI]
100
- def self.parse_uri(input)
100
+ def self.parse_uri(input, options = {})
101
101
  if input =~ URIREF
102
- RDF::URI.new($1)
102
+ RDF::URI.send(options[:intern] ? :intern : :new, $1)
103
103
  end
104
104
  end
105
105
 
@@ -122,6 +122,7 @@ module RDF::NTriples
122
122
  # @return [String]
123
123
  # @see http://www.w3.org/TR/rdf-testcases/#ntrip_strings
124
124
  # @see http://blog.grayproductions.net/articles/understanding_m17n
125
+ # @see http://yehudakatz.com/2010/05/17/encodings-unabridged/
125
126
  def self.unescape(string)
126
127
  string.force_encoding(Encoding::ASCII_8BIT) if string.respond_to?(:force_encoding)
127
128
 
@@ -174,7 +175,7 @@ module RDF::NTriples
174
175
  begin
175
176
  unless blank? || read_comment
176
177
  subject = read_uriref || read_node || fail_subject
177
- predicate = read_uriref || fail_predicate
178
+ predicate = read_uriref(:intern => true) || fail_predicate
178
179
  object = read_uriref || read_node || read_literal || fail_object
179
180
  return [subject, predicate, object]
180
181
  end
@@ -195,9 +196,9 @@ module RDF::NTriples
195
196
  ##
196
197
  # @return [RDF::URI]
197
198
  # @see http://www.w3.org/TR/rdf-testcases/#ntrip_grammar (uriref)
198
- def read_uriref
199
+ def read_uriref(options = {})
199
200
  if uri = match(URIREF)
200
- RDF::URI.new(uri)
201
+ RDF::URI.send(options[:intern] ? :intern : :new, uri)
201
202
  end
202
203
  end
203
204