rdf-mapper 0.0.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,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
+