activerubic 0.8.0 → 0.8.1

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