rdf-mapper 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,281 @@
1
+ module RDFMapper
2
+ module Scope
3
+ ##
4
+ # [-]
5
+ ##
6
+ class Query
7
+
8
+ include RDFMapper::Logger
9
+
10
+ attr_reader :cls
11
+ attr_reader :conditions
12
+ attr_reader :sql # Remaining unparsed conditions
13
+
14
+ def initialize(cls, options = {})
15
+ @options = options
16
+ @conditions = []
17
+ @options[:include] ||= []
18
+ @cls = cls
19
+ @modifier = :and
20
+
21
+ case @options[:conditions]
22
+ when Hash then parse_hash
23
+ when Array then parse_array
24
+ end
25
+
26
+ end
27
+
28
+ ##
29
+ # [-]
30
+ ##
31
+ def modifier
32
+ @modifier.to_s.upcase
33
+ end
34
+
35
+ ##
36
+ # [-]
37
+ ##
38
+ def strict?
39
+ @modifier == :and
40
+ end
41
+
42
+ ##
43
+ # [-]
44
+ ##
45
+ def offset
46
+ @options[:offset] || 0
47
+ end
48
+
49
+ ##
50
+ # [-]
51
+ ##
52
+ def limit
53
+ @options[:limit]
54
+ end
55
+
56
+ ##
57
+ # [-]
58
+ ##
59
+ def include
60
+ @options[:include]
61
+ end
62
+
63
+ ##
64
+ # [-]
65
+ ##
66
+ def include!(name)
67
+ @options[:include] << name
68
+ end
69
+
70
+ ##
71
+ # @todo. Not implemented
72
+ ##
73
+ def order
74
+ nil
75
+ end
76
+
77
+ ##
78
+ # [-]
79
+ ##
80
+ def [](name)
81
+ @conditions.select do |condition|
82
+ condition.name == name
83
+ end.map do |condition|
84
+ condition.value
85
+ end.first
86
+ end
87
+
88
+ ##
89
+ # Follows the same logic as `to_a` method and returns a Hash instead
90
+ # of an Array (:name => { :eq => value, :value => value }).
91
+ #
92
+ # @see to_a
93
+ #
94
+ # @param [Array<Symbol>] required association attributes that should be preloaded
95
+ # @return [Hash]
96
+ ##
97
+ def to_hash(required = [])
98
+ Hash[to_a(required).map do |name, eq, value|
99
+ [name, { :eq => eq, :value => value }]
100
+ end]
101
+ end
102
+
103
+ ##
104
+ # Returns an Array of search conditions. Will preload any associated
105
+ # models if their properties are undefined (e.g. in case of REST and
106
+ # SPARQL models are required to have `id` as RDF::URI, and `rails_id`
107
+ # in case of Rails).
108
+ #
109
+ # Note that any foreign-key associations will be renamed. For instance:
110
+ # :employee_id => #<RDF::URI(http://example.org/people/1354534)>
111
+ # is transformed into
112
+ # :employee => #<RDFMapper::Model:217132856>
113
+ #
114
+ # @param [Array<Symbol>] required association attributes that should be preloaded
115
+ # @return [Array<Condition>]
116
+ ##
117
+ def to_a(required = [])
118
+ unless required.kind_of? Array
119
+ required = [required]
120
+ end
121
+ @conditions.each do |condition|
122
+ condition.check(required)
123
+ end
124
+ end
125
+
126
+ ##
127
+ # [-]
128
+ ##
129
+ def to_triples
130
+ to_statements.map do |statement|
131
+ [ statement[:subject], statement[:predicate], statement[:object] ]
132
+ end
133
+ end
134
+
135
+ ##
136
+ # [-]
137
+ ##
138
+ def to_statements
139
+ target = if self[:id].nil?
140
+ RDF::Query::Variable.new
141
+ else
142
+ RDF::URI.new(self[:id].to_s)
143
+ end
144
+ [{ :subject => target,
145
+ :predicate => RDF.type,
146
+ :object => @cls.type
147
+ }] + to_a(:id).map do |condition|
148
+ condition.to_statements(target)
149
+ end.flatten.compact
150
+ end
151
+
152
+ ##
153
+ # [-]
154
+ ##
155
+ def flatten(required = [])
156
+ to_a(required).map do |condition|
157
+ (condition.class == self.class) ? condition.flatten(required) : condition
158
+ end.flatten
159
+ end
160
+
161
+ alias_method :check, :to_a
162
+
163
+ ##
164
+ # Developer-friendly representation of the instance
165
+ #
166
+ # @return [String]
167
+ ##
168
+ def inspect #nodoc
169
+ "#<Query%s>" % to_a.map do |condition|
170
+ condition.inspect
171
+ end.inspect
172
+ end
173
+
174
+
175
+ private
176
+
177
+ def add_condition(name, value, eq = '=') #nodoc
178
+ if value.kind_of? Array and value.empty?
179
+ raise RuntimeError, 'No value assigned to `%s`' % name
180
+ end
181
+ @conditions << RDFMapper::Scope::Condition.new(@cls, name, value, eq)
182
+ end
183
+
184
+ ##
185
+ # [-]
186
+ ##
187
+ def parse_array #nodoc
188
+ @ary = @options[:conditions][1,255]
189
+ while (read_subquery || read_collection || read_value || read_modifier); end
190
+ end
191
+
192
+ ##
193
+ # [-]
194
+ ##
195
+ def read_collection #nodoc
196
+ full, name = match(/([^\s]+)[\s]*IN[\s]+\(\?\)[\s]*/)
197
+ return nil if full.nil?
198
+ add_condition(name, @ary.shift)
199
+ end
200
+
201
+ ##
202
+ # [-]
203
+ ##
204
+ def read_modifier #nodoc
205
+ full, modifier = match(/[\s]*(AND|OR)/)
206
+ return nil if full.nil?
207
+ @modifier = (modifier == 'OR') ? :or : :and
208
+ end
209
+
210
+ ##
211
+ # [-]
212
+ ##
213
+ def read_value #nodoc
214
+ full, name, eq, value, literal, digit = match(/([^\s]+)[\s]*([=><]+)\s*("([\s\w]*)"|([\d\.]+))/)
215
+ return nil if full.nil?
216
+ value = literal.nil? ? digit.to_f : literal.to_s
217
+ add_condition(name, value, eq)
218
+ end
219
+
220
+ ##
221
+ # [-]
222
+ ##
223
+ def read_subquery #nodoc
224
+ read_subquery_start || read_subquery_end
225
+ end
226
+
227
+ ##
228
+ # [-]
229
+ ##
230
+ def read_subquery_start #nodoc
231
+ return nil if match(/\(/).nil?
232
+ sub = Query.new(@cls, :conditions => [@sql] + @ary)
233
+ @sql = sub.sql[1, sub.sql.length]
234
+ @conditions << sub
235
+ end
236
+
237
+ ##
238
+ # [-]
239
+ ##
240
+ def read_subquery_end #nodoc
241
+ return nil if match(/\)/).nil?
242
+ @sql = "|" + @sql
243
+ end
244
+
245
+ ##
246
+ # Returns a match array
247
+ ##
248
+ def match(pattern)
249
+ if @sql.nil?
250
+ @sql = @options[:conditions].first
251
+ end
252
+ if (@sql =~ pattern) == 0
253
+ @sql = $'.lstrip
254
+ Regexp.last_match.to_a
255
+ end
256
+ end
257
+
258
+ ##
259
+ # Parses all user-specified `options[:conditions]`
260
+ ##
261
+ def parse_hash #nodoc
262
+ @options[:conditions].map do |att, value|
263
+ parse_hash_item(att, value)
264
+ end.flatten
265
+ end
266
+
267
+ ##
268
+ # Parses a single `option`
269
+ ##
270
+ def parse_hash_item(att, value) #nodoc
271
+ if value.kind_of? Array
272
+ return value.map do |item|
273
+ parse_hash_item(att, item)
274
+ end
275
+ end
276
+ add_condition(att, value)
277
+ end
278
+
279
+ end # Query
280
+ end # Scope
281
+ end # RDFMapper
@@ -0,0 +1,66 @@
1
+ module RDFMapper
2
+ ##
3
+ # Basic HTTP interface, built on top of Patron[http://github.com/toland/patron]
4
+ # library. Used by RDFMapper adapters for communication with external data sources.
5
+ #
6
+ # Patron automatically handles cookies, redirects, timeouts. Can be substituted
7
+ # by any other library as long as HTTP class implements `get` and `post` methods.
8
+ ##
9
+ class HTTP
10
+
11
+ require 'patron'
12
+
13
+ class << self
14
+
15
+ ##
16
+ # Performs a `GET` request and returns received data
17
+ #
18
+ # @param [String, RDF::URI] url
19
+ # @param [Hash] options for Patron constructor
20
+ # @return [String]
21
+ ##
22
+ def get(url, options = {})
23
+ self.new(options).get(url.to_s)
24
+ end
25
+
26
+ ##
27
+ # Performs a `POST` request and returns received data
28
+ #
29
+ # @param [String, RDF::URI] url
30
+ # @param [String] data
31
+ # @param [Hash] options for Patron constructor
32
+ # @return [String]
33
+ ##
34
+ def post(url, data, options = {})
35
+ self.new(options).post(url.to_s, data)
36
+ end
37
+
38
+ end
39
+
40
+ ##
41
+ # @return [self]
42
+ ##
43
+ def initialize(options = {})
44
+ @session = Patron::Session.new
45
+ @session.handle_cookies
46
+ @session.timeout = 10
47
+ @session.headers['User-Agent'] = 'Mozilla / RDFMapper'
48
+ @options = options
49
+ end
50
+
51
+ def get(url)
52
+ @session.get(url, headers).body
53
+ end
54
+
55
+ def post(url, data)
56
+ @session.post(url, data, headers).body
57
+ end
58
+
59
+ private
60
+
61
+ def headers
62
+ @options[:headers] || {}
63
+ end
64
+
65
+ end # HTTP
66
+ end # RDFMapper
@@ -0,0 +1,68 @@
1
+ module RDFMapper
2
+ ##
3
+ # A convenience wrapper around Ruby's standard Logger object.
4
+ ##
5
+ module Logger
6
+ module Configuration
7
+ class << self
8
+
9
+ def to(target, level = 4, name = nil)
10
+ io = case target
11
+ when :stdout then $stdout
12
+ when :file then File.open(name, 'a+')
13
+ else String
14
+ end
15
+ @target = ::Logger.new(io)
16
+ end
17
+
18
+ def target
19
+ @target || to(:stdout)
20
+ end
21
+
22
+ end
23
+ end
24
+
25
+ ##
26
+ # Logs a fatal error using RDFMapper::Logger
27
+ #
28
+ # @return[true]
29
+ ##
30
+ def fatal(message)
31
+ log(4, message)
32
+ end
33
+
34
+ ##
35
+ # Logs a warning message using RDFMapper::Logger
36
+ #
37
+ # @return[true]
38
+ ##
39
+ def warn(message)
40
+ log(2, message)
41
+ end
42
+
43
+ ##
44
+ # Logs a debug message using RDFMapper::Logger
45
+ #
46
+ # @return[true]
47
+ ##
48
+ def debug(message)
49
+ log(0, message)
50
+ end
51
+
52
+ private
53
+
54
+ ##
55
+ # Logs a message using RDFMapper::Logger
56
+ #
57
+ # @param [Integer] severity from 0 to 5 (see Logger::Severity)
58
+ # @param [String] message
59
+ # @return[true]
60
+ ##
61
+ def log(severity, message)
62
+ timestamp = Time.now.strftime('%m-%d %H:%M:%S')
63
+ formatted = "[%s] %s | %s" % [timestamp, self.class.name, message]
64
+ RDFMapper::Logger::Configuration.target.add(severity, formatted)
65
+ end
66
+
67
+ end
68
+ end
data/lib/rdf-mapper.rb ADDED
@@ -0,0 +1,15 @@
1
+ module RDFMapper
2
+
3
+ require 'rdf-xml'
4
+ require 'rdf-sparql'
5
+
6
+ autoload :Model, 'lib/model/base'
7
+ autoload :Scope, 'lib/scope/model'
8
+ autoload :Associations, 'lib/associations/base'
9
+ autoload :Adapters, 'lib/adapters/base'
10
+ autoload :HTTP, 'lib/util/http'
11
+ autoload :Logger, 'lib/util/logger'
12
+
13
+ end
14
+
15
+
metadata ADDED
@@ -0,0 +1,141 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rdf-mapper
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Alex Serebryakov
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-04-27 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rspec
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 1
29
+ - 3
30
+ - 0
31
+ version: 1.3.0
32
+ type: :development
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: rdf
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ - 1
44
+ - 1
45
+ version: 0.1.1
46
+ type: :runtime
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: rdf-xml
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ segments:
56
+ - 0
57
+ - 0
58
+ - 1
59
+ version: 0.0.1
60
+ type: :runtime
61
+ version_requirements: *id003
62
+ - !ruby/object:Gem::Dependency
63
+ name: patron
64
+ prerelease: false
65
+ requirement: &id004 !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ segments:
70
+ - 0
71
+ - 4
72
+ - 6
73
+ version: 0.4.6
74
+ type: :runtime
75
+ version_requirements: *id004
76
+ description: RDFMapper is a lightweight Ruby ORM that works with RDF data in a Rails-like fashion. Is supports XML, N-Triples, JSON formats, SPARQL and ActiveRecord as data sources.
77
+ email: serebryakov@gmail.com
78
+ executables: []
79
+
80
+ extensions: []
81
+
82
+ extra_rdoc_files: []
83
+
84
+ files:
85
+ - README.rdoc
86
+ - UNLICENSE
87
+ - VERSION
88
+ - lib/lib/adapters/base.rb
89
+ - lib/lib/adapters/rails.rb
90
+ - lib/lib/adapters/rest.rb
91
+ - lib/lib/adapters/sparql.rb
92
+ - lib/lib/associations/base.rb
93
+ - lib/lib/associations/belongs_to.rb
94
+ - lib/lib/associations/has_and_belongs.rb
95
+ - lib/lib/associations/has_many.rb
96
+ - lib/lib/associations/has_one.rb
97
+ - lib/lib/model/association.rb
98
+ - lib/lib/model/attribute.rb
99
+ - lib/lib/model/base.rb
100
+ - lib/lib/model/output.rb
101
+ - lib/lib/model/property.rb
102
+ - lib/lib/scope/collection.rb
103
+ - lib/lib/scope/condition.rb
104
+ - lib/lib/scope/loader.rb
105
+ - lib/lib/scope/model.rb
106
+ - lib/lib/scope/query.rb
107
+ - lib/lib/util/http.rb
108
+ - lib/lib/util/logger.rb
109
+ - lib/rdf-mapper.rb
110
+ has_rdoc: true
111
+ homepage: http://github.com/42cities/rdf-mapper/
112
+ licenses: []
113
+
114
+ post_install_message:
115
+ rdoc_options: []
116
+
117
+ require_paths:
118
+ - lib
119
+ required_ruby_version: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ segments:
124
+ - 0
125
+ version: "0"
126
+ required_rubygems_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ segments:
131
+ - 0
132
+ version: "0"
133
+ requirements: []
134
+
135
+ rubyforge_project: rdf-mapper
136
+ rubygems_version: 1.3.6
137
+ signing_key:
138
+ specification_version: 3
139
+ summary: A Ruby ORM that is designed to play nicely with RDF data.
140
+ test_files: []
141
+