rdf 0.1.10 → 0.2.0

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.
@@ -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