activerubic 0.8.0 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,175 @@
1
+ module ActiveRubinstein
2
+ ## A DRb object to jRubinstein#JeanLuc::Picard
3
+ class JenaEndpoint < DRb::DRbObject
4
+
5
+ attr_reader :uri
6
+
7
+ # adds a JenaEndpoint to the server pool.
8
+ def initialize
9
+ # jdrb_servers.each do |uri|
10
+ # STDERR.puts " * jRubinstein client @ " + uri
11
+ # jrubinstein = Rubinstein::JenaEndpoint.new( DRbObject.new_with_uri( uri ) )
12
+ # end
13
+ # return nil
14
+ @uri = ['druby','//' + JDRB_SERVER, JDRB_PORT].join(':')
15
+ begin
16
+ @@log.rubinstein " * initializing JenaEndpoint: " + @uri
17
+ server = DRbObject.new_with_uri( @uri )
18
+ @@log.debug server.inspect
19
+ if server.ping then
20
+ @@log.debug " => reply from server: " + server.hello
21
+ return server
22
+ else
23
+ raise ConnectionFailedError, $!.message
24
+ end
25
+
26
+ rescue
27
+ raise ConnectionFailedError, $!.message
28
+ end
29
+ end
30
+ end
31
+
32
+ #############################################################################
33
+ # JenaQuery translates an ActiveRubic query to JeanLuc::Picard over the DRb via method_missing.
34
+ #
35
+ # execute accepts these actions:
36
+ # - :instances_of
37
+ # :class => getInstances
38
+ # - :parents
39
+ # the same method is used for both instances and classes, but the actual method in Java is different
40
+ # :class || :subject
41
+ # is_class? => getParents
42
+ # is_subject? => getInstanceClass
43
+ # - :ancestors
44
+ # :class => getAncestors
45
+ # - :children
46
+ # :class => getChildren
47
+ # - :descendants
48
+ # :class => getDescendants
49
+ # - :roots
50
+ # :ontology => getRoot
51
+ # - :classes_within
52
+ # :class, :radius => getClassesWithin
53
+ # - :inverse
54
+ # :property => getInverse
55
+ #
56
+ #############################################################################
57
+ class JenaQuery < ActiveRubinstein::Base
58
+
59
+ # allow to set query language
60
+ attr_accessor :language
61
+
62
+ # picks a JenaEndpoint from the server pool.
63
+ def initialize
64
+ server = $serverPool[ :jena ].first
65
+ unless server.ping
66
+ raise ConnectionFailedError, $!.message
67
+ else
68
+ @@jena = server
69
+ @@log.rubinstein "@@jena = #{server.inspect}"
70
+ end
71
+ end
72
+
73
+ class << self
74
+
75
+ public
76
+
77
+ # analyzes the query to find the correct method to execute
78
+ def execute( query, options )
79
+ if query.is_a? Symbol or query.is_a? RDFS::Resource
80
+ case query
81
+ when :instances_of
82
+ subject = options[ :class ]
83
+ if subject
84
+ # 2nd parameter sets the reasoner
85
+ self.getInstances( subject, false )
86
+ end
87
+ when :parents
88
+ # the same method is used for both instances and classes,
89
+ # but the actual method in Java is different
90
+ subject = options[ :subject ]
91
+ if subject.is_class? then
92
+ self.getParents( subject )
93
+ else
94
+ self.getInstanceClass( subject )
95
+ end
96
+ when :ancestors
97
+ subject = options[ :subject ]
98
+ if subject.is_class? then
99
+ self.getAncestors( subject )
100
+ elsif subject.is_a? RDFS::Resource then
101
+ ancestors = Array.new
102
+ subject.parents.each do |parent|
103
+ ancestors << parent
104
+ ancestors << self.getAncestors( parent )
105
+ end
106
+ return ancestors.flatten
107
+ end
108
+ when :children
109
+ subject = options[ :class ]
110
+ if subject
111
+ self.getChildren( subject )
112
+ end
113
+ when :descendants
114
+ subject = options[ :class ]
115
+ if subject
116
+ self.getDescendants( subject )
117
+ end
118
+ when :roots
119
+ ontology = options[ :ontology ]
120
+ if ontology
121
+ self.getRoot( ontology )
122
+ end
123
+ when :classes_within
124
+ subject = options[ :class ]
125
+ radius = options[ :radius ] || 0.2
126
+ if subject
127
+ # 2nd parameter sets the reasoner
128
+ self.getClassesWithin( subject, radius )
129
+ end
130
+ when :properties then
131
+ subject = options[ :subject ]
132
+ if subject
133
+ self.getProperties( subject )
134
+ end
135
+ when :inverse
136
+ property = options[ :property ]
137
+ if property
138
+ self.getInverse( property )
139
+ end
140
+
141
+ else # construct common SPARQL
142
+ sparql = ActiveRubinstein::SparqlFormulator.construct( query, options )
143
+ return self.query( sparql, options ) if sparql
144
+ end
145
+
146
+ elsif query.is_a? Query then
147
+ @@log.query query.to_sp
148
+ return self.query( query, options )
149
+ end
150
+ end
151
+
152
+ # returns the server object
153
+ def server
154
+ @@jena
155
+ end
156
+
157
+ private
158
+
159
+ # sends the request to Rubinstein's DRb server.
160
+ def method_missing(method, *args, &block) # :dodoc:
161
+ @@log.rubinstein "sending the request to DRb server, method #{method}"
162
+ begin
163
+ return @@jena.send( method, *args, &block )
164
+ rescue
165
+ raise ConnectionFailedError, $!.message
166
+ end
167
+ end
168
+
169
+ def do_log(*args)
170
+ super
171
+ end
172
+
173
+ end
174
+ end
175
+ end
@@ -0,0 +1,82 @@
1
+ module ActiveRubinstein
2
+
3
+ #############################################################################
4
+ # Joseki backend
5
+ #
6
+ # Copyright (c) 2007 Savonia University of Applied Sciences
7
+ # Mikael Lammentausta
8
+ #
9
+ #############################################################################
10
+
11
+ # A DRb object to jRubinstein#Joseki
12
+ class ActiveRubinstein::JosekiEndpoint < DRb::DRbObject
13
+
14
+ attr_reader :uri
15
+
16
+ # connects to the Rubinstein server and adds a server to the server pool.
17
+ def initialize
18
+
19
+ # drb_servers.each do |uri|
20
+ # STDERR.puts " * cRubinstein client @ " + uri
21
+ # rubinstein = Rubinstein::SparqlEndpoint.new( DRbObject.new_with_uri( uri ) )
22
+ # end
23
+
24
+ @uri = ['druby','//' + DRB_SERVER, DRB_PORT].join(':')
25
+ @@log.debug " * initializing SparqlEndpoint: " + @uri
26
+ server = DRbObject.new_with_uri( @uri )
27
+ begin
28
+ @@log.debug " => reply from server: " + server.hello
29
+ return server
30
+ rescue
31
+ @@log.error $!
32
+ return nil
33
+ end
34
+ end
35
+ end
36
+
37
+
38
+ # Picks a server from the server pool and opens up the interface for queries.
39
+ class ActiveRubinstein::JosekiQuery < ActiveRubinstein::Base
40
+ def initialize
41
+ server = $serverPool[ :joseki ].first
42
+ @@log.debug $serverPool[ :joseki ].inspect
43
+ if server.nil?
44
+ @@log.error $!.message
45
+ else
46
+ @@joseki = server
47
+ @@log.rubinstein "@@joseki = #{server.inspect}"
48
+ end
49
+ end
50
+
51
+ class << self
52
+
53
+ public
54
+
55
+ # analyzes the query to find the correct method to execute
56
+ def execute( query, options={} )
57
+ # construct common SPARQL
58
+ query = ActiveRubinstein::SparqlFormulator.construct( query, options )
59
+ results = self.query( query, options ) if query
60
+ end
61
+
62
+ # returns the server object
63
+ def server
64
+ @@joseki
65
+ end
66
+
67
+ private
68
+
69
+ # pretty much the most important method of all :)
70
+ # this method sends the request to Rubinstein's DRb server.
71
+ def method_missing(method, *args, &block)
72
+ @@log.rubinstein "sending the request to DRb server, method #{method}"
73
+ return @@joseki.send( method, *args, &block )
74
+ end
75
+
76
+ def do_log(*args)
77
+ super
78
+ end
79
+
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,170 @@
1
+ module ActiveRubinstein
2
+
3
+ #############################################################################
4
+ # Lucene backend queries for ActiveRubinstein
5
+ #
6
+ # NOTE: standard Lucene uses JenaEndPoint, geoLucene GeoLuceneEndpoint
7
+ #
8
+ # Copyright:: 2007 Savonia University of Applied Sciences
9
+ # Author:: Mikael Lammentausta
10
+ #
11
+ #############################################################################
12
+
13
+ ## A DRb object to jRubinstein#JeanLuc::GeoLucene
14
+ class GeoLuceneEndpoint < DRb::DRbObject
15
+
16
+ attr_reader :uri
17
+
18
+ # connects to the Rubinstein server and adds a server to the server pool.
19
+ def initialize
20
+ @uri = ['druby','//' + GEOLUCENE_SERVER, GEOLUCENE_PORT].join(':')
21
+ begin
22
+ @@log.rubinstein " * initializing GeoLuceneEndpoint: " + @uri
23
+ server = DRbObject.new_with_uri( @uri )
24
+ @@log.debug server.inspect
25
+ if server.ping then
26
+ @@log.debug " => reply from server: " + server.hello
27
+ return server
28
+ else
29
+ @@log.error $!.message
30
+ return nil
31
+ end
32
+
33
+ rescue
34
+ @@log.error $!.message
35
+ return nil
36
+ end
37
+ end
38
+ end
39
+
40
+ # A DRb object to jRubinstein#JenaLuc::Lucene or JenaLuc::GeoLucene
41
+ class LuceneSearcher < ActiveRubinstein::Base
42
+
43
+ attr_accessor :language
44
+
45
+ # adds a Lucene engine to the server pool;
46
+ # the Lucene branch can be selected by the option
47
+ # lucene_branch => :standard || :geolucene
48
+ #
49
+ # currently GeoLucene is not used, as it fails to parse fuzzy searches.
50
+ def initialize( lucene_branch = :standard )
51
+ case lucene_branch
52
+
53
+ when :standard
54
+ server = $serverPool[ :jena ].first
55
+ unless server.ping
56
+ @@log.error $!.message
57
+ else
58
+ @@lucene = server
59
+ @@log.rubinstein "@@lucene = #{server.inspect}"
60
+ end
61
+
62
+ when :geolucene
63
+ server = $serverPool[ :geolucene ].first
64
+ unless server.ping
65
+ @@log.error $!.message
66
+ else
67
+ @@geolucene = server
68
+ @@log.rubinstein "@@geolucene = #{server.inspect}"
69
+ end
70
+ end
71
+ end
72
+
73
+ class << self
74
+
75
+ public
76
+
77
+ # analyzes the query to find the correct method to execute. accepts queries of type Symbol, RDFS::Resource and String.
78
+ #
79
+ # Parameters:
80
+ # - 1 query (Symbol, RDFS::Resource or String)
81
+ # - 2 options (Hash; ...)
82
+ def execute( query, options )
83
+
84
+ @lucene = options[ :lucene_branch ] || :standard
85
+
86
+ if query.is_a? Symbol or query.is_a? RDFS::Resource
87
+ case query
88
+
89
+ # look for geographically nearby resources
90
+ when :nearby
91
+ lat = options[ :lat ]
92
+ long = options[ :long ]
93
+ radius = options[ :radius ] || 1000
94
+ resource = options[ :resource ]
95
+
96
+ if resource # quick hack
97
+ resource = RdfAbout.new( resource ) unless resource.is_a? RdfAbout
98
+ lat = resource.lat
99
+ long = resource.long
100
+ end
101
+
102
+ lat = lat.to_f unless lat.is_a? Float
103
+ long = long.to_f unless long.is_a? Float
104
+ radius = radius.to_i unless radius.is_a? Fixnum
105
+
106
+ if lat and long
107
+ return self.getNearbyTargets( lat, long, radius, options )
108
+ end
109
+ end
110
+
111
+ elsif query.is_a? String
112
+ options.update :indices => :full unless options.has_key? :indices
113
+ return self.search( query, options )
114
+
115
+ elsif query.is_a? Query
116
+ @@log.info "Lucene cannot handle SPARQL queries yet."
117
+ return nil
118
+
119
+ else
120
+ @@log.warn "Unfamiliar query (#{query}) to Lucene"
121
+ return nil
122
+ end
123
+ end
124
+
125
+ # def lucene_query( search_string, options={} )
126
+ # begin
127
+ # @@log.rubinstein " => Querying Lucene, search string: #{search_string}"
128
+ # # NOTE: the query actually goes to Lucene on the Rubinstein server,
129
+ # # it's actually somewhat misleading that the variable is @@jena..
130
+ # # return @@jena.searchText( search_string )
131
+ # return @@jena.search( search_string, options={} )
132
+ # rescue
133
+ # Array.new
134
+ # end
135
+ # end
136
+ # alias :query_from_lucene :lucene_query
137
+ # alias :searchText :lucene_query
138
+
139
+ # returns the server object
140
+ def server
141
+ if @@lucene
142
+ return @@lucene
143
+ elsif @@geolucene
144
+ return @@geolucene
145
+ end
146
+ end
147
+
148
+ # pretty much the most important method of all :)
149
+ # this method sends the request to Rubinstein's DRb server.
150
+ def method_missing(method, *args, &block)
151
+ @@log.rubinstein "sending the request to #{@@lucene}, method #{method}"
152
+
153
+ @lucene ||= :standard
154
+ case @lucene
155
+ when :standard
156
+ return @@lucene.send( method, *args, &block )
157
+ when :geolucene
158
+ return @@geolucene.send( method, *args, &block )
159
+ else
160
+ @@log.error "Unknown Lucene branch #{@lucene}"
161
+ return Array.new
162
+ end
163
+ end
164
+
165
+ def do_log(*args) # :nodoc:
166
+ super
167
+ end
168
+ end
169
+ end
170
+ end
@@ -0,0 +1,133 @@
1
+ module ActiveRubinstein
2
+ # constructs SPARQL from abstract ActiveRubic queries
3
+ class SparqlFormulator
4
+
5
+ # Parameters:
6
+ # - 1 action (Symbol; :all, :images_of, :properties etc) -- see RDFS::Resource and the child objects for possible actions.
7
+ # - 2 options (Hash)
8
+ def self.construct( action, options={} )
9
+ @@log.rubinstein "Constructing SPARQL, options: #{options}"
10
+ # todo: insert limit into sparql
11
+ # if limit then
12
+ # BUG: Jena doesn't process .limit in SPARQL
13
+ subject = options[ :subject ]
14
+ predicate = options[ :predicate ] || options[ :property ]
15
+ object = options[ :object ]
16
+ owlclass = options[ :class ]
17
+ @@log.debug " => constructing Query to find #{action}"
18
+
19
+ # subject = RDFS::Resource.new( subject.uri ) if subject.is_a? RdfAbout
20
+ # predicate = RDFS::Resource.new( predicate.uri ) if predicate.is_a? Property or predicate.is_a? RdfAbout
21
+ # object = RDFS::Resource.new( object.uri ) if object.is_a? RdfAbout
22
+ # owlclass = RDFS::Resource.new( owlclass.uri ) if owlclass.is_a? OwlClass
23
+ #
24
+ # subject = RDFS::Resource.new( subject ) if subject.is_a? String
25
+ # predicate = RDFS::Resource.new( predicate ) if predicate.is_a? String
26
+ # object = RDFS::Resource.new( object ) if object.is_a? String
27
+ # owlclass = RDFS::Resource.new( owlclass ) if owlclass.is_a? String
28
+
29
+
30
+ # ActiveRubic::Base.find :images_of, :subject => KUOPIO::kuopion_museo
31
+ if action.is_a? Symbol
32
+ case action
33
+ when :all then # BROKEN
34
+ # query = Query.new.distinct( :resource ).where( :resource, :x, :y )
35
+ q = Query.new.distinct( :image ).where( :image, RDF::type, RDFS::Resource.new("media://image") )
36
+
37
+ when :images_of then
38
+ unless defined? subject
39
+ @@log.error " ! No subject defined for action #{action}, cannot formulate SPARQL"
40
+ else
41
+ @@log.rubinstein "Find images of #{subject}"
42
+ q = Query.new.select( :image ).
43
+ where( :image, RDF::subject, subject ).
44
+ where( :image, RDF::type, RDFS::Resource.new("media://image") )
45
+
46
+ # select by image rating
47
+ if options[ :rating ] # can be only 0 to 5
48
+ q.where( :image, IPTC::Rating, options[ :rating ] )
49
+ end
50
+ end
51
+
52
+ # not used!!!!
53
+ when :random_image_of
54
+ unless subject
55
+ @@log.error " ! No subject defined for query #{action}, cannot formulate SPARQL"
56
+ else
57
+ # FIXME: Randomizing is not handled here, it's hacked into RDFS::Resource
58
+ q = Query.new.select( :image ).
59
+ where( :image, RDF::subject, subject ).
60
+ where( :image, RDF::type, RDFS::Resource.new("media://image") )
61
+
62
+ # select by image rating
63
+ if options[ :rating ] # can be only 0 to 5
64
+ q.where( :image, IPTC::Rating, options[ :rating ] )
65
+ end
66
+ end
67
+
68
+ when :markers
69
+ unless owlclass
70
+ @@log.error " ! No class defined for query #{action}"
71
+ else
72
+ # Query for all instances that belong to this class and have GEO::lat and GEO::long defined
73
+ q = Query.new.select( :markers ). \
74
+ where( :markers, RDF::type, owlclass ). \
75
+ where( :markers, GEO::lat, :lat ).where( :markers, GEO::long, :long )
76
+
77
+ end
78
+
79
+ # property handling moved to jena_query, since the objects should
80
+ # be transformed to OWL::ObjectProperty and generic SPARQL returns
81
+ # only RDFS::Resource objects
82
+ # when :properties then
83
+ # unless defined? subject
84
+ # @@log.error " ! No subject defined for action #{action}, cannot formulate SPARQL"
85
+ # else
86
+ # @@log.deep "Querying for properties of #{subject}"
87
+ # q = Query.new.select( :property ) \
88
+ # .where( :property, :any, OWL::ObjectProperty ) \
89
+ # .where( RDFS::Resource.new( subject ), :property, :within_range )
90
+ # end
91
+
92
+ when :within_range then
93
+ unless subject
94
+ @@log.debug "Subject not defined, using Symbol"
95
+ subject = :subject
96
+ # @@log.error " ! No subject defined for action #{action}, cannot formulate SPARQL"
97
+ end
98
+
99
+ if ! defined? predicate
100
+ @@log.error " ! No predicate defined for action #{action}, cannot formulate SPARQL"
101
+ else
102
+ @@log.deep "Querying for #{subject} #{predicate} ?"
103
+ q = Query.new.select( :within_range ) \
104
+ .where( subject, predicate, :within_range )
105
+ # .where( RDFS::Resource.new( subject ), :property, :within_range )
106
+ end
107
+
108
+ end
109
+
110
+ # insert LIMIT into SPARQL
111
+ limit = options[ :limit ]
112
+ if !limit.nil? and !limit.is_a? Fixnum
113
+ @@log.warn "Limit must be a Fixnum, got #{limit} (#{limit.class})"
114
+ elsif !limit.nil?
115
+ @@log.rubinstein " => Limit: #{limit}"
116
+ q.limit( limit )
117
+ end
118
+
119
+ return q
120
+
121
+ else # expect the action variable is a RDFS::Resource predicate
122
+ unless defined? subject
123
+ @@log.error " ! No subject defined to query #{action}, cannot formulate SPARQL"
124
+ else
125
+ @@log.deep "Constructing SPARQL #{subject} #{action} ?"
126
+ return Query.new.distinct( :object ). \
127
+ where( subject, action, :object )
128
+ end
129
+ end
130
+ end
131
+
132
+ end
133
+ end