activerdf 1.2 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -30,7 +30,7 @@ desc 'test and package gem'
30
30
  task :default => :install
31
31
 
32
32
  # get ActiveRdfVersion from commandline
33
- ActiveRdfVersion = '1.2'
33
+ ActiveRdfVersion = '1.2.1'
34
34
  NAME="activerdf"
35
35
  GEMNAME="#{NAME}-#{ActiveRdfVersion}.gem"
36
36
 
@@ -23,6 +23,7 @@ module RDFS
23
23
  def initialize uri
24
24
  raise ActiveRdfError, "creating resource <#{uri}>" unless uri.is_a?(String)
25
25
  @uri = uri
26
+ @predicates = Hash.new
26
27
  end
27
28
 
28
29
  # setting our own class uri to rdfs:resource
@@ -144,6 +145,10 @@ module RDFS
144
145
  # 4. eyal.age is a custom-written method in class Person
145
146
  # evidence: eyal type ?c, ?c.methods includes age
146
147
  # action: inject age into eyal and invoke
148
+ #
149
+ # 5. eyal.age is registered abbreviation
150
+ # evidence: age in @predicates
151
+ # action: return object from triple (eyal, @predicates[age], ?o)
147
152
 
148
153
  # maybe change order in which to check these, checking (4) is probably
149
154
  # cheaper than (1)-(2) but (1) and (2) are probably more probable (getting
@@ -151,8 +156,8 @@ module RDFS
151
156
 
152
157
  $activerdflog.debug "RDFS::Resource: method_missing on instance: called with method name #{method}"
153
158
 
154
- # are we doing an update or not?
155
- # checking if method ends with '='
159
+ # are we doing an update or not?
160
+ # checking if method ends with '='
156
161
 
157
162
  if method.to_s[-1..-1] == '='
158
163
  methodname = method.to_s[0..-2]
@@ -162,161 +167,175 @@ module RDFS
162
167
  update = false
163
168
  end
164
169
 
170
+ # check possibility (5)
171
+ if @predicates.include?(methodname)
172
+ return predicate_invocation(@predicates[methodname], args, update)
173
+ end
174
+
165
175
  candidates = if update
166
176
  (class_level_predicates + direct_predicates).compact.uniq
167
177
  else
168
178
  direct_predicates
169
179
  end
170
-
171
- # checking possibility (1) and (3)
172
- candidates.each do |pred|
173
- if Namespace.localname(pred) == methodname
174
- # found a property invocation of eyal: option 1) or 2)
175
- # query execution will return either the value for the predicate (1)
176
- # or nil (2)
177
- if update
178
- # TODO: delete old value if overwriting
179
- # FederiationManager.delete(self, pred, nil)
180
-
181
- # handling eyal.friends = [armin, andreas] --> expand array values
182
- args.each do |value|
183
- FederationManager.add(self, pred, value)
184
- end
185
- return args
186
- else
187
- # look into args, if it contains a hash with {:array => true} then
188
- # we should not flatten the query results
189
- return get_property_value(pred, args)
190
- end
191
- end
192
- end
193
-
194
- raise ActiveRdfError, "could not set #{methodname} to #{args}: no suitable
195
- predicate found. Maybe you are missing some schema information?" if update
196
-
197
- # get/set attribute value did not succeed, so checking option (2) and (4)
198
-
199
- # checking possibility (2), it is not handled correctly above since we use
200
- # direct_predicates instead of class_level_predicates. If we didn't find
201
- # anything with direct_predicates, we need to try the
202
- # class_level_predicates. Only if we don't find either, we
203
- # throw "method_missing"
204
- candidates = class_level_predicates
205
-
206
- # if any of the class_level candidates fits the sought method, then we
207
- # found situation (2), so we return nil or [] depending on the {:array =>
208
- # true} value
209
- if candidates.any?{|c| Namespace.localname(c) == methodname}
210
- return_ary = args[0][:array] if args[0].is_a? Hash
211
- if return_ary
212
- return []
213
- else
214
- return nil
215
180
 
216
- end
217
- end
181
+ # checking possibility (1) and (3)
182
+ candidates.each do |pred|
183
+ if Namespace.localname(pred) == methodname
184
+ return predicate_invocation(pred, args, update)
185
+ end
186
+ end
187
+
188
+ raise ActiveRdfError, "could not set #{methodname} to #{args}: no suitable
189
+ predicate found. Maybe you are missing some schema information?" if update
190
+
191
+ # get/set attribute value did not succeed, so checking option (2) and (4)
192
+
193
+ # checking possibility (2), it is not handled correctly above since we use
194
+ # direct_predicates instead of class_level_predicates. If we didn't find
195
+ # anything with direct_predicates, we need to try the
196
+ # class_level_predicates. Only if we don't find either, we
197
+ # throw "method_missing"
198
+ candidates = class_level_predicates
199
+
200
+ # if any of the class_level candidates fits the sought method, then we
201
+ # found situation (2), so we return nil or [] depending on the {:array =>
202
+ # true} value
203
+ if candidates.any?{|c| Namespace.localname(c) == methodname}
204
+ return_ary = args[0][:array] if args[0].is_a? Hash
205
+ if return_ary
206
+ return []
207
+ else
208
+ return nil
209
+ end
210
+ end
211
+
212
+ # checking possibility (4)
213
+ # TODO: implement search strategy to select in which class to invoke
214
+ # e.g. if to_s defined in Resource and in Person we should use Person
215
+ $activerdflog.debug "RDFS::Resource: method_missing option 4: custom class method"
216
+ self.type.each do |klass|
217
+ if klass.instance_methods.include?(method.to_s)
218
+ _dup = klass.new(uri)
219
+ return _dup.send(method,*args)
220
+ end
221
+ end
222
+
223
+ # if none of the three possibilities work out, we don't know this method
224
+ # invocation, but we don't want to throw NoMethodError, instead we return
225
+ # nil, so that eyal.age does not raise error, but returns nil. (in RDFS,
226
+ # we are never sure that eyal cannot have an age, we just dont know the
227
+ # age right now)
228
+ nil
229
+ end
218
230
 
219
- # checking possibility (4)
220
- # TODO: implement search strategy to select in which class to invoke
221
- # e.g. if to_s defined in Resource and in Person we should use Person
222
- $activerdflog.debug "RDFS::Resource: method_missing option 4: custom class method"
223
- self.type.each do |klass|
224
- if klass.instance_methods.include?(method.to_s)
225
- _dup = klass.new(uri)
226
- return _dup.send(method,*args)
227
- end
228
- end
231
+ # saves instance into datastore
232
+ def save
233
+ db = ConnectionPool.write_adapter
234
+ rdftype = Namespace.lookup(:rdf, :type)
235
+ types.each do |t|
236
+ db.add(self, rdftype, t)
237
+ end
238
+
239
+ Query.new.distinct(:p,:o).where(self, :p, :o).execute do |p, o|
240
+ db.add(self, p, o)
241
+ end
242
+ end
229
243
 
230
- # if none of the three possibilities work out, we don't know this method
231
- # invocation, but we don't want to throw NoMethodError, instead we return
232
- # nil, so that eyal.age does not raise error, but returns nil. (in RDFS,
233
- # we are never sure that eyal cannot have an age, we just dont know the
234
- # age right now)
235
- nil
236
- end
237
-
238
- # saves instance into datastore
239
- def save
240
- db = ConnectionPool.write_adapter
241
- rdftype = Namespace.lookup(:rdf, :type)
242
- types.each do |t|
243
- db.add(self, rdftype, t)
244
+ def type
245
+ types.collect do |type|
246
+ ObjectManager.construct_class(type)
247
+ end
244
248
  end
245
249
 
246
- Query.new.distinct(:p,:o).where(self, :p, :o).execute do |p, o|
247
- db.add(self, p, o)
250
+ def add_predicate localname, fulluri
251
+ localname = localname.to_s
252
+ fulluri = RDFS::Resource.new(fulluri) if fulluri.is_a? String
253
+
254
+ # predicates is a hash from abbreviation string to full uri resource
255
+ @predicates[localname] = fulluri
248
256
  end
249
- end
250
257
 
251
- def type
252
- types.collect do |type|
253
- ObjectManager.construct_class(type)
254
- end
255
- end
256
-
257
- # overrides built-in instance_of? to use rdf:type definitions
258
- def instance_of?(klass)
259
- self.type.include?(klass)
260
- end
261
-
262
- # returns all predicates that fall into the domain of the rdf:type of this
263
- # resource
264
- def class_level_predicates
265
- type = Namespace.lookup(:rdf, 'type')
266
- domain = Namespace.lookup(:rdfs, 'domain')
267
- Query.new.distinct(:p).where(self,type,:t).where(:p, domain, :t).execute || []
268
- end
269
-
270
- # returns all predicates that are directly defined for this resource
271
- def direct_predicates(distinct = true)
272
- if distinct
273
- q = Query.new.distinct(:p)
274
- else
275
- q = Query.new.select(:p)
276
- end
277
- q.where(self,:p, :o).execute
278
- end
279
-
280
- def property_accessors
281
- direct_predicates.collect {|pred| Namespace.localname(pred) }
282
- end
283
-
284
- # alias include? to ==, so that you can do paper.creator.include?(eyal)
285
- # without worrying whether paper.creator is single- or multi-valued
286
- alias include? ==
287
-
288
- # returns uri of resource, can be overridden in subclasses
289
- def to_s
290
- "<#{uri}>"
291
- end
292
-
293
- # # label of resource (rdfs:label if available, uri otherwise)
294
- # def label
295
- # get_property_value(Namespace.lookup(:rdfs,:label)) || uri
296
- # end
297
-
298
- private
299
- def get_property_value(predicate, args=[])
300
- return_ary = args[0][:array] if args[0].is_a?(Hash)
301
- flatten_results = !return_ary
302
- query = Query.new.distinct(:o).where(self, predicate, :o)
303
- query.execute(:flatten => flatten_results)
304
- end
305
-
306
- # returns all rdf:types of this resource
307
- def types
308
- type = Namespace.lookup(:rdf, :type)
309
-
310
- # we lookup the type in the database
311
- types = Query.new.distinct(:t).where(self,type,:t).execute
312
-
313
- # we are also always of type rdfs:resource and of our own class (e.g. foaf:Person)
314
- defaults = []
315
- defaults << Namespace.lookup(:rdfs,:Resource)
316
- defaults << self.class.class_uri
317
-
318
- (types + defaults).uniq
319
- end
320
258
 
321
- end
259
+ # overrides built-in instance_of? to use rdf:type definitions
260
+ def instance_of?(klass)
261
+ self.type.include?(klass)
262
+ end
263
+
264
+ # returns all predicates that fall into the domain of the rdf:type of this
265
+ # resource
266
+ def class_level_predicates
267
+ type = Namespace.lookup(:rdf, 'type')
268
+ domain = Namespace.lookup(:rdfs, 'domain')
269
+ Query.new.distinct(:p).where(self,type,:t).where(:p, domain, :t).execute || []
270
+ end
271
+
272
+ # returns all predicates that are directly defined for this resource
273
+ def direct_predicates(distinct = true)
274
+ if distinct
275
+ q = Query.new.distinct(:p)
276
+ else
277
+ q = Query.new.select(:p)
278
+ end
279
+ direct = q.where(self,:p, :o).execute
280
+ return (direct + direct.collect {|d| ancestors(d)}).flatten.uniq
281
+ end
282
+
283
+ def property_accessors
284
+ direct_predicates.collect {|pred| Namespace.localname(pred) }
285
+ end
286
+
287
+ # alias include? to ==, so that you can do paper.creator.include?(eyal)
288
+ # without worrying whether paper.creator is single- or multi-valued
289
+ alias include? ==
290
+
291
+ # returns uri of resource, can be overridden in subclasses
292
+ def to_s
293
+ "<#{uri}>"
294
+ end
295
+
296
+ # # label of resource (rdfs:label if available, uri otherwise)
297
+ # def label
298
+ # get_property_value(Namespace.lookup(:rdfs,:label)) || uri
299
+ # end
300
+
301
+ private
302
+
303
+ def ancestors(predicate)
304
+ subproperty = Namespace.lookup(:rdfs,:subPropertyOf)
305
+ Query.new.distinct(:p).where(predicate, subproperty, :p).execute
306
+ end
307
+
308
+ def predicate_invocation(predicate, args, update)
309
+ if update
310
+ args.each do |value|
311
+ FederationManager.add(self, predicate, value)
312
+ end
313
+ args
314
+ else
315
+ get_property_value(predicate, args)
316
+ end
317
+ end
318
+
319
+ def get_property_value(predicate, args=[])
320
+ return_ary = args[0][:array] if args[0].is_a?(Hash)
321
+ flatten_results = !return_ary
322
+ query = Query.new.distinct(:o).where(self, predicate, :o)
323
+ query.execute(:flatten => flatten_results)
324
+ end
325
+
326
+ # returns all rdf:types of this resource
327
+ def types
328
+ type = Namespace.lookup(:rdf, :type)
329
+
330
+ # we lookup the type in the database
331
+ types = Query.new.distinct(:t).where(self,type,:t).execute
332
+
333
+ # we are also always of type rdfs:resource and of our own class (e.g. foaf:Person)
334
+ defaults = []
335
+ defaults << Namespace.lookup(:rdfs,:Resource)
336
+ defaults << self.class.class_uri
337
+
338
+ (types + defaults).uniq
339
+ end
340
+ end
322
341
  end
data/lib/active_rdf.rb CHANGED
@@ -27,20 +27,20 @@ def load_adapter s
27
27
  end
28
28
 
29
29
  require 'rubygems'
30
- #determine if we are installed as a gem right now:
31
- if Gem::cache().search("activerdf").empty?
32
- #we are not running as a gem
33
- $activerdflog.info 'ActiveRDF is NOT installed as a Gem'
34
- load_adapter this_dir + '/../activerdf-rdflite/lib/activerdf_rdflite/rdflite'
35
- load_adapter this_dir + '/../activerdf-rdflite/lib/activerdf_rdflite/fetching'
36
- load_adapter this_dir + '/../activerdf-rdflite/lib/activerdf_rdflite/suggesting'
37
- load_adapter this_dir + '/../activerdf-redland/lib/activerdf_redland/redland'
38
- load_adapter this_dir + '/../activerdf-sparql/lib/activerdf_sparql/sparql'
39
- load_adapter this_dir + '/../activerdf-yars/lib/activerdf_yars/jars2'
30
+ # determine whether activerdf is installed as a gem:
31
+ if Gem::cache.search(/^activerdf$/).empty?
32
+ # we are not running as a gem
33
+ $activerdflog.info 'ActiveRDF is NOT installed as a Gem'
34
+ load_adapter this_dir + '/../activerdf-rdflite/lib/activerdf_rdflite/rdflite'
35
+ load_adapter this_dir + '/../activerdf-rdflite/lib/activerdf_rdflite/fetching'
36
+ load_adapter this_dir + '/../activerdf-rdflite/lib/activerdf_rdflite/suggesting'
37
+ load_adapter this_dir + '/../activerdf-redland/lib/activerdf_redland/redland'
38
+ load_adapter this_dir + '/../activerdf-sparql/lib/activerdf_sparql/sparql'
39
+ load_adapter this_dir + '/../activerdf-yars/lib/activerdf_yars/jars2'
40
40
  else
41
- #we are indeed running as a gem
42
- require 'gem_plugin'
43
- $activerdflog.info 'ActiveRDF is installed as a Gem'
44
- GemPlugin::Manager.instance.load "activerdf" => GemPlugin::INCLUDE
41
+ # we are running as a gem
42
+ require 'gem_plugin'
43
+ $activerdflog.info 'ActiveRDF is installed as a Gem'
44
+ GemPlugin::Manager.instance.load "activerdf" => GemPlugin::INCLUDE
45
45
  end
46
46
 
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
3
3
  specification_version: 1
4
4
  name: activerdf
5
5
  version: !ruby/object:Gem::Version
6
- version: "1.2"
7
- date: 2006-12-21 00:00:00 +01:00
6
+ version: 1.2.1
7
+ date: 2007-01-30 00:00:00 +00:00
8
8
  summary: Offers object-oriented access to RDF (with adapters to several datastores).
9
9
  require_paths:
10
10
  - lib