adaptation 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +1 -0
- data/README +90 -0
- data/bin/about +5 -0
- data/bin/adaptation +19 -0
- data/bin/destroy +5 -0
- data/bin/generate +5 -0
- data/bin/mom +8 -0
- data/bin/subscribe +8 -0
- data/configs/boot.rb +10 -0
- data/configs/databases/mysql.yml +48 -0
- data/configs/empty.log +0 -0
- data/configs/mom.yml +8 -0
- data/dispatches/dispatch.rb +8 -0
- data/dispatches/publish.rb +11 -0
- data/doc/README_FOR_APP +2 -0
- data/fresh_rakefile +10 -0
- data/helpers/publish.rb +24 -0
- data/helpers/test_helper.rb +6 -0
- data/lib/adaptation/adaptor.rb +32 -0
- data/lib/adaptation/base.rb +70 -0
- data/lib/adaptation/message.rb +328 -0
- data/lib/adaptation/mom.rb +70 -0
- data/lib/adaptation/oapdaemon.rb +38 -0
- data/lib/adaptation/test/test_help.rb +282 -0
- data/lib/adaptation/version.rb +9 -0
- data/lib/adaptation.rb +5 -0
- data/lib/commands/about.rb +3 -0
- data/lib/commands/destroy.rb +6 -0
- data/lib/commands/generate.rb +6 -0
- data/lib/commands/mom.rb +8 -0
- data/lib/commands/subscribe.rb +11 -0
- data/lib/commands.rb +17 -0
- data/lib/rails_generator/base.rb +262 -0
- data/lib/rails_generator/commands.rb +582 -0
- data/lib/rails_generator/generated_attribute.rb +42 -0
- data/lib/rails_generator/generators/applications/app/USAGE +13 -0
- data/lib/rails_generator/generators/applications/app/app_generator.rb +133 -0
- data/lib/rails_generator/generators/components/adaptor/USAGE +25 -0
- data/lib/rails_generator/generators/components/adaptor/adaptor_generator.rb +21 -0
- data/lib/rails_generator/generators/components/adaptor/templates/adaptor.rb +6 -0
- data/lib/rails_generator/generators/components/adaptor/templates/functional_test.rb +16 -0
- data/lib/rails_generator/generators/components/message/USAGE +16 -0
- data/lib/rails_generator/generators/components/message/message_generator.rb +28 -0
- data/lib/rails_generator/generators/components/message/templates/fixtures.xml +3 -0
- data/lib/rails_generator/generators/components/message/templates/message.rb +2 -0
- data/lib/rails_generator/generators/components/message/templates/unit_test.rb +25 -0
- data/lib/rails_generator/generators/components/model/USAGE +26 -0
- data/lib/rails_generator/generators/components/model/model_generator.rb +38 -0
- data/lib/rails_generator/generators/components/model/templates/fixtures.yml +11 -0
- data/lib/rails_generator/generators/components/model/templates/migration.rb +13 -0
- data/lib/rails_generator/generators/components/model/templates/model.rb +2 -0
- data/lib/rails_generator/generators/components/model/templates/unit_test.rb +10 -0
- data/lib/rails_generator/lookup.rb +209 -0
- data/lib/rails_generator/manifest.rb +53 -0
- data/lib/rails_generator/options.rb +143 -0
- data/lib/rails_generator/scripts/destroy.rb +7 -0
- data/lib/rails_generator/scripts/generate.rb +7 -0
- data/lib/rails_generator/scripts/update.rb +12 -0
- data/lib/rails_generator/scripts.rb +85 -0
- data/lib/rails_generator/simple_logger.rb +46 -0
- data/lib/rails_generator/spec.rb +44 -0
- data/lib/rails_generator.rb +43 -0
- data/lib/ruby_version_check.rb +17 -0
- metadata +142 -0
@@ -0,0 +1,328 @@
|
|
1
|
+
module Adaptation
|
2
|
+
|
3
|
+
#= Adaptation::Message -- XML to classes mapping.
|
4
|
+
#
|
5
|
+
#Adaptation::Message connects ruby objects and xml data to create a model where
|
6
|
+
#logic and data are presented in one wrapping. It's is inspired on activerecord, and pretends
|
7
|
+
#to solve xml data management problems in a similar way activerecord handles database data
|
8
|
+
#management.
|
9
|
+
#
|
10
|
+
#Adaptation::Message classes describe xml structures, allowing separation of common structures as
|
11
|
+
#standalone classes. It offers a set of macros to specify wich structures are part of a bigger one and
|
12
|
+
#to allow validation of the different parts.
|
13
|
+
#
|
14
|
+
#A summary of the major features and their usage:
|
15
|
+
#
|
16
|
+
#* Automated mapping between classes and xml attributes and elements.
|
17
|
+
#
|
18
|
+
# class Contact < Adaptation::Message
|
19
|
+
# has_one :text, :name
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# ...is automatically mapped to a xml structure with root element named "contact", such as:
|
23
|
+
#
|
24
|
+
# <contact>
|
25
|
+
# <name>Name</name>
|
26
|
+
# </contact>
|
27
|
+
#
|
28
|
+
# ...which gives Contact#name
|
29
|
+
#
|
30
|
+
#
|
31
|
+
#* Associations between objects controlled by simple meta-programming macros.
|
32
|
+
#
|
33
|
+
# class Agenda < Adaptation::Message
|
34
|
+
# has_one :attribute, :type
|
35
|
+
# has_one :text, :owner
|
36
|
+
# has_many :contacts
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# class Contact < Adaptation::Message
|
40
|
+
# belongs_to :contacts
|
41
|
+
# has_one :text, :name
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
# Agenda class would be mapping the following xml structure:
|
45
|
+
#
|
46
|
+
# <agenda type="...">
|
47
|
+
# <owner>...</owner>
|
48
|
+
# <contacts>
|
49
|
+
# <contact>...</contact>
|
50
|
+
# </contacts>
|
51
|
+
# </agenda>
|
52
|
+
#
|
53
|
+
# while the _Contact_ class would map:
|
54
|
+
#
|
55
|
+
# <contact>
|
56
|
+
# <name>...</name>
|
57
|
+
# </contact>
|
58
|
+
#
|
59
|
+
# The Contact class is a partial, a structure included in a bigger structure, so its
|
60
|
+
# file name starts with an underscore: _contact.rb
|
61
|
+
#
|
62
|
+
# We could have wrote Agenda like this, to change the contacts container name:
|
63
|
+
#
|
64
|
+
# class Agenda < Adaptation::Message
|
65
|
+
# has_one :attribute, :type
|
66
|
+
# has_one :text, :owner
|
67
|
+
# has_many :contacts, :in => :contact_list
|
68
|
+
# end
|
69
|
+
#
|
70
|
+
# and Contact like:
|
71
|
+
#
|
72
|
+
# class Contact < Adaptation::Message
|
73
|
+
# belongs_to :contact_list
|
74
|
+
# has_one :text, :name
|
75
|
+
# end
|
76
|
+
#
|
77
|
+
# Then the mapping in Agenda would be:
|
78
|
+
#
|
79
|
+
# <agenda type="...">
|
80
|
+
# <owner>...</owner>
|
81
|
+
# <contact_list>
|
82
|
+
# <contact>...</contact>
|
83
|
+
# </contact_list>
|
84
|
+
# </agenda>
|
85
|
+
#
|
86
|
+
#
|
87
|
+
#* Validation rules.
|
88
|
+
#
|
89
|
+
# class Agenda < Adaptation::Message
|
90
|
+
# has_one :attribute, :type
|
91
|
+
# has_one :text, :owner
|
92
|
+
# validates_presence_of :owner, :type
|
93
|
+
# validates_value :type, "indexed"
|
94
|
+
# end
|
95
|
+
#
|
96
|
+
#
|
97
|
+
class Message
|
98
|
+
|
99
|
+
@@validations = {}
|
100
|
+
@@default_error_messages = {
|
101
|
+
:invalid_value => "Invalid value",
|
102
|
+
:must_be_present => "Must be present"
|
103
|
+
}
|
104
|
+
@@errors = []
|
105
|
+
|
106
|
+
include ROXML
|
107
|
+
|
108
|
+
def self.belongs_to symbol
|
109
|
+
@belongs_to = symbol
|
110
|
+
end
|
111
|
+
|
112
|
+
def self.parent
|
113
|
+
@belongs_to
|
114
|
+
end
|
115
|
+
|
116
|
+
def to_hash
|
117
|
+
s = self.to_yaml
|
118
|
+
h = YAML::load s[4..s.length].downcase.gsub(/\!ruby\/object:.* /,"")
|
119
|
+
end
|
120
|
+
|
121
|
+
def has_son?(son)
|
122
|
+
search_symbol_in_hash self.to_hash, son
|
123
|
+
end
|
124
|
+
|
125
|
+
def search_symbol_in_hash hash, symbol
|
126
|
+
found = false
|
127
|
+
hash.each_pair do |k,v|
|
128
|
+
if (k.to_sym == symbol)
|
129
|
+
found = true
|
130
|
+
break
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
if !found
|
135
|
+
hash.each_pair do |k,v|
|
136
|
+
found = search_symbol_in_hash(v, symbol) if v.is_a?(Hash)
|
137
|
+
break if found
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
found
|
142
|
+
end
|
143
|
+
|
144
|
+
def self.highest_parent
|
145
|
+
parent_class = self
|
146
|
+
while parent_class != nil
|
147
|
+
begin
|
148
|
+
parent_class = get_class_object(parent_class.parent.to_s.capitalize)
|
149
|
+
rescue Exception => e
|
150
|
+
top_parent_class = parent_class.parent.to_s
|
151
|
+
parent_class = nil
|
152
|
+
end
|
153
|
+
end
|
154
|
+
top_parent_class
|
155
|
+
end
|
156
|
+
|
157
|
+
def self.has_one *symbols
|
158
|
+
xml_tag = symbols[0]
|
159
|
+
case xml_tag
|
160
|
+
when :object
|
161
|
+
@objects = [] if @objects.nil?
|
162
|
+
unless @objects.include?(symbols[1])
|
163
|
+
@objects << symbols[1]
|
164
|
+
begin
|
165
|
+
klass = get_class_object(symbols[1].to_s.capitalize)
|
166
|
+
rescue Exception => e
|
167
|
+
require "#{ADAPTOR_ROOT}/app/messages/_#{symbols[1].to_s}.rb"
|
168
|
+
klass = get_class_object(symbols[1].to_s.capitalize)
|
169
|
+
end
|
170
|
+
xml_object symbols[1], klass
|
171
|
+
end
|
172
|
+
when :attribute
|
173
|
+
@attributes = [] if @attributes.nil?
|
174
|
+
unless @attributes.include?(symbols[1])
|
175
|
+
@attributes << symbols[1]
|
176
|
+
s = ""
|
177
|
+
@attributes.each do |a|
|
178
|
+
s << a.to_s
|
179
|
+
end
|
180
|
+
xml_attribute symbols[1]
|
181
|
+
end
|
182
|
+
when :text
|
183
|
+
@texts = [] if @texts.nil?
|
184
|
+
unless @texts.include?(symbols[1])
|
185
|
+
@texts << symbols[1]
|
186
|
+
xml_text symbols[1]
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def self.has_text
|
192
|
+
if @has_text.nil?
|
193
|
+
@has_text = true
|
194
|
+
xml_text :text, nil, ROXML::TEXT_CONTENT
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def self.has_many *options
|
199
|
+
configuration = {}
|
200
|
+
configuration.update(options.pop) if options.last.is_a?(Hash)
|
201
|
+
@has_many = [] if @has_many.nil?
|
202
|
+
unless @has_many.include?(options[0])
|
203
|
+
@has_many << options[0]
|
204
|
+
begin
|
205
|
+
klass = get_class_object(options[0].to_s.capitalize[0..-2]) # TODO: singularize seriously
|
206
|
+
rescue Exception => e
|
207
|
+
require "#{ADAPTOR_ROOT}/app/messages/_#{options[0].to_s[0..-2]}.rb"
|
208
|
+
klass = get_class_object(options[0].to_s.capitalize[0..-2])
|
209
|
+
end
|
210
|
+
|
211
|
+
if configuration[:in]
|
212
|
+
xml_object configuration[:in], klass, ROXML::TAG_ARRAY, configuration[:in].to_s
|
213
|
+
else
|
214
|
+
xml_object options[0], klass, ROXML::TAG_ARRAY, options[0].to_s
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
def self.get_class_object(searched_class)
|
220
|
+
class_object = nil
|
221
|
+
ObjectSpace.each_object(Class){|aClass|
|
222
|
+
class_object = aClass if aClass.to_s == searched_class
|
223
|
+
}
|
224
|
+
if class_object.nil?
|
225
|
+
raise Exception.new("Unknown class #{searched_class}.")
|
226
|
+
else
|
227
|
+
return class_object
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
def self.get_validations_array
|
232
|
+
validations_array = nil
|
233
|
+
if self.highest_parent.empty?
|
234
|
+
validations_array = self.to_s.downcase.to_sym
|
235
|
+
else
|
236
|
+
validations_array = self.highest_parent.to_sym
|
237
|
+
end
|
238
|
+
|
239
|
+
@@validations[validations_array] = [] if @@validations[validations_array].nil?
|
240
|
+
@@validations[validations_array]
|
241
|
+
end
|
242
|
+
|
243
|
+
def self.validates_value(*options)
|
244
|
+
belongs_to = @belongs_to
|
245
|
+
get_validations_array << Proc.new {|message|
|
246
|
+
configuration = {:message => @@default_error_messages[:invalid_value] }
|
247
|
+
if belongs_to.nil?
|
248
|
+
unless (message.send(options[0]) == options[1].to_s)
|
249
|
+
@@errors << [options[0], message.send(options[0]), configuration[:message]]
|
250
|
+
end
|
251
|
+
else
|
252
|
+
found = false
|
253
|
+
message.send(belongs_to).each do |son|
|
254
|
+
if son.send(options[0]) == options[1].to_s
|
255
|
+
found = true
|
256
|
+
break
|
257
|
+
end
|
258
|
+
end
|
259
|
+
unless found
|
260
|
+
@@errors << [options[0], message.send(options[0]), configuration[:message]]
|
261
|
+
end
|
262
|
+
end
|
263
|
+
}
|
264
|
+
end
|
265
|
+
|
266
|
+
def self.validates_presence_of *options
|
267
|
+
belongs_to = @belongs_to
|
268
|
+
get_validations_array << Proc.new {|message|
|
269
|
+
configuration = {:message => @@default_error_messages[:must_be_present]}
|
270
|
+
options.each do |o|
|
271
|
+
if belongs_to.nil?
|
272
|
+
if message.send(o).nil?
|
273
|
+
@@errors << [o, message.send(o), configuration[:message]]
|
274
|
+
end
|
275
|
+
else
|
276
|
+
parent = message.send(belongs_to)
|
277
|
+
if parent.send(o).nil? # this throws a warning if o = :id (but it works)
|
278
|
+
@@errors << [o, message.send(o), configuration[:message]]
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
}
|
283
|
+
end
|
284
|
+
|
285
|
+
def self.validates_uniqueness_of(*options)
|
286
|
+
end
|
287
|
+
|
288
|
+
def self.to_object xml_message
|
289
|
+
parse xml_message
|
290
|
+
end
|
291
|
+
|
292
|
+
def check
|
293
|
+
clear_errors
|
294
|
+
|
295
|
+
@@validations.each_key do |k|
|
296
|
+
if self.has_son? k.to_sym
|
297
|
+
@@validations[k.to_sym].each do |v|
|
298
|
+
v.call(self)
|
299
|
+
end
|
300
|
+
end
|
301
|
+
end
|
302
|
+
@@validations[self.class.to_s.downcase.to_sym].each do |v|
|
303
|
+
v.call(self)
|
304
|
+
end
|
305
|
+
|
306
|
+
unless @@errors.empty?
|
307
|
+
error = "Errors found in XML message:\n"
|
308
|
+
@@errors.each do |e|
|
309
|
+
error << " #{e[0]}: #{e[2]}\n"
|
310
|
+
error << " #{e[1]}\n"
|
311
|
+
end
|
312
|
+
return false
|
313
|
+
end
|
314
|
+
|
315
|
+
return true
|
316
|
+
end
|
317
|
+
|
318
|
+
def get_errors
|
319
|
+
@@errors
|
320
|
+
end
|
321
|
+
|
322
|
+
def clear_errors
|
323
|
+
@@errors = []
|
324
|
+
end
|
325
|
+
|
326
|
+
end
|
327
|
+
|
328
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'drb'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
module Adaptation
|
5
|
+
|
6
|
+
class Mom
|
7
|
+
|
8
|
+
def initialize mom_uri
|
9
|
+
@mom_uri = mom_uri
|
10
|
+
end
|
11
|
+
|
12
|
+
def subscribe drb_uri
|
13
|
+
unless get_subscribers.include?(drb_uri)
|
14
|
+
add_subscriber drb_uri
|
15
|
+
puts "Added new subscriber: #{drb_uri}"
|
16
|
+
oapdaemon = DRbObject.new(nil, drb_uri)
|
17
|
+
oapdaemon.subscription_result true
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def publish message, topic
|
22
|
+
# Tell subscribed hosts to execute their adaptors
|
23
|
+
puts "-----------------------------------"
|
24
|
+
puts "Received message in topic: #{topic}"
|
25
|
+
puts "#{message}"
|
26
|
+
puts "-----------------------------------"
|
27
|
+
get_subscribers.each do |uri|
|
28
|
+
puts "Calling #{uri}"
|
29
|
+
DRb.start_service
|
30
|
+
oapdaemon = DRbObject.new(nil, uri)
|
31
|
+
oapdaemon.call_adaptor message, topic
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def start
|
36
|
+
DRb.start_service(@mom_uri, self)
|
37
|
+
puts "MOM started. Listening at #{@mom_uri}"
|
38
|
+
DRb.thread.join # Don't exit just yet
|
39
|
+
end
|
40
|
+
|
41
|
+
def list
|
42
|
+
puts "MOM subscriptions:"
|
43
|
+
get_subscribers.each do |s|
|
44
|
+
puts " #{s}"
|
45
|
+
end
|
46
|
+
return
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def add_subscriber drb_uri
|
52
|
+
subscribers = get_subscribers
|
53
|
+
subscribers << drb_uri unless subscribers.include?(drb_uri)
|
54
|
+
sf = File.new('subscribers.yml', 'w')
|
55
|
+
sf.write(YAML::dump(subscribers))
|
56
|
+
sf.close
|
57
|
+
end
|
58
|
+
|
59
|
+
def get_subscribers
|
60
|
+
if File.exists?('subscribers.yml')
|
61
|
+
subscribers = YAML::load(File.open('subscribers.yml'))
|
62
|
+
else
|
63
|
+
subscribers = Array.new
|
64
|
+
end
|
65
|
+
subscribers
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'drb'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
module Adaptation
|
5
|
+
|
6
|
+
class Oapdaemon
|
7
|
+
|
8
|
+
def initialize subscriber_uri, mom_uri, topics
|
9
|
+
@subscriber_uri = subscriber_uri
|
10
|
+
@mom_uri = mom_uri
|
11
|
+
@topics = topics
|
12
|
+
end
|
13
|
+
|
14
|
+
def call_adaptor message, topic
|
15
|
+
if ( (@topics.include?(topic)) or (@topics == "all") )
|
16
|
+
system("ruby public/dispatch.rb #{message}")
|
17
|
+
end
|
18
|
+
puts "#{topic} => #{message}"
|
19
|
+
end
|
20
|
+
|
21
|
+
def subscription_result subscribed
|
22
|
+
if subscribed
|
23
|
+
puts "Subscribed to mom (#{@mom_uri}). Listening at #{@subscriber_uri}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def start
|
28
|
+
DRb.start_service(@subscriber_uri, self)
|
29
|
+
|
30
|
+
mom = DRbObject.new(nil, @mom_uri)
|
31
|
+
mom.subscribe @subscriber_uri
|
32
|
+
|
33
|
+
DRb.thread.join # Don't exit just yet!
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,282 @@
|
|
1
|
+
#set environment
|
2
|
+
$environment = "test"
|
3
|
+
if File.exists?("config/settings.yml")
|
4
|
+
$config = YAML::load(File.open("config/settings.yml"))[$environment]
|
5
|
+
end
|
6
|
+
|
7
|
+
# connect to test database
|
8
|
+
require 'active_record'
|
9
|
+
|
10
|
+
if File.exists?("config/database.yml")
|
11
|
+
test_configurations = YAML::load(File.open("config/database.yml"))[$environment]
|
12
|
+
ActiveRecord::Base.configurations.update("test" => test_configurations)
|
13
|
+
ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations[$environment])
|
14
|
+
end
|
15
|
+
|
16
|
+
if File.exists?("log")
|
17
|
+
ActiveRecord::Base.logger = Logger.new("#{ADAPTOR_ROOT}/log/test.log")
|
18
|
+
end
|
19
|
+
|
20
|
+
# load messages
|
21
|
+
Dir["#{ADAPTOR_ROOT}/app/messages/*.rb"].reject{|f| f =~ /\/_/}.each do |f|
|
22
|
+
require f
|
23
|
+
end
|
24
|
+
|
25
|
+
# load models
|
26
|
+
Dir["#{ADAPTOR_ROOT}/app/models/*.rb"].each do |f|
|
27
|
+
require f
|
28
|
+
end
|
29
|
+
|
30
|
+
if File.exists?("config/database.yml")
|
31
|
+
begin
|
32
|
+
require 'active_record/fixtures'
|
33
|
+
rescue Exception => e
|
34
|
+
puts "Problem with database fixtures: #{e}"
|
35
|
+
end
|
36
|
+
Test::Unit::TestCase.fixture_path = 'test/fixtures'
|
37
|
+
end
|
38
|
+
|
39
|
+
class Test::Unit::TestCase
|
40
|
+
|
41
|
+
def assert_parsed message_symbol
|
42
|
+
data, message_object = load_message_fixture message_symbol
|
43
|
+
|
44
|
+
parsed_data = REXML::Document.new data
|
45
|
+
error = build_message error,
|
46
|
+
"? not parsed ok:\n initial: ?\n parsed: ?",
|
47
|
+
message_symbol.to_s,
|
48
|
+
parsed_data.to_s,
|
49
|
+
message_object.to_xml.to_s
|
50
|
+
assert_block error do
|
51
|
+
#message_object.to_xml.to_s == parsed_data.to_s
|
52
|
+
compare_xml_elements parsed_data.root, message_object.to_xml
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def assert_not_parsed message_symbol
|
57
|
+
data, message_object = load_message_fixture message_symbol
|
58
|
+
|
59
|
+
parsed_data = REXML::Document.new data
|
60
|
+
error = build_message error,
|
61
|
+
"? shouldn't be parsed ok:\n data: ?\n real: ?",
|
62
|
+
message_symbol.to_s,
|
63
|
+
parsed_data.to_s,
|
64
|
+
message_object.to_xml.to_s
|
65
|
+
assert_block error do
|
66
|
+
message_object.to_xml.to_s != parsed_data.to_s
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def assert_validates message_symbol
|
71
|
+
data, message_object = load_message_fixture message_symbol
|
72
|
+
error = build_message error,
|
73
|
+
"invalid message ?",
|
74
|
+
message_symbol.to_s
|
75
|
+
message_object.clear_errors
|
76
|
+
assert_block error do
|
77
|
+
message_object.check
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def assert_not_validates message_symbol
|
82
|
+
data, message_object = load_message_fixture message_symbol
|
83
|
+
error = build_message error,
|
84
|
+
"? message shouldn't validate",
|
85
|
+
message_symbol.to_s
|
86
|
+
assert_block error do
|
87
|
+
!message_object.check
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def assert_message_published xml_message
|
92
|
+
# build Message object with xml_data
|
93
|
+
message_type = xml_message[1..(xml_message.index(/(>| )/) - 1)]
|
94
|
+
message_class = get_class_object(message_type.capitalize)
|
95
|
+
message_object = message_class.to_object(xml_message)
|
96
|
+
|
97
|
+
# check for all messages "published" in the mom (that's file /tmp/mom.txt),
|
98
|
+
# if any line corresponds to the message passes as a parameter.
|
99
|
+
message_found = false
|
100
|
+
File.open('/tmp/mom.txt', 'r').each{ |line|
|
101
|
+
mom_message = REXML::Document.new line
|
102
|
+
if mom_message.to_s.chomp == message_object.to_xml.to_s
|
103
|
+
message_found = true
|
104
|
+
break
|
105
|
+
end
|
106
|
+
}
|
107
|
+
|
108
|
+
error = build_message error,
|
109
|
+
"? message not published",
|
110
|
+
message_type
|
111
|
+
assert_block error do
|
112
|
+
message_found
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
def assert_database_present db_settings_hash
|
118
|
+
update_activerecord_test_configuration db_settings_hash
|
119
|
+
|
120
|
+
ActiveRecord::Base.remove_connection
|
121
|
+
|
122
|
+
ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations[$environment])
|
123
|
+
|
124
|
+
database_exists = true
|
125
|
+
begin
|
126
|
+
connection = ActiveRecord::Base.connection
|
127
|
+
rescue Exception => e
|
128
|
+
puts "Database error message: #{e}"
|
129
|
+
database_exists = false
|
130
|
+
end
|
131
|
+
|
132
|
+
error = build_message error,
|
133
|
+
"? database not found",
|
134
|
+
ActiveRecord::Base.configurations[$environment][:database]
|
135
|
+
assert_block error do
|
136
|
+
database_exists
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
|
141
|
+
def assert_database_not_present db_settings_hash
|
142
|
+
update_activerecord_test_configuration db_settings_hash
|
143
|
+
|
144
|
+
ActiveRecord::Base.remove_connection
|
145
|
+
|
146
|
+
ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations[$environment])
|
147
|
+
|
148
|
+
database_exists = true
|
149
|
+
begin
|
150
|
+
connection = ActiveRecord::Base.connection
|
151
|
+
rescue Exception => e
|
152
|
+
puts "Database error message: #{e}"
|
153
|
+
database_exists = false
|
154
|
+
end
|
155
|
+
|
156
|
+
error = build_message error,
|
157
|
+
"? database shouldn't exist",
|
158
|
+
ActiveRecord::Base.configurations[$environment][:database]
|
159
|
+
assert_block error do
|
160
|
+
!database_exists
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|
164
|
+
|
165
|
+
def update_activerecord_test_configuration db_settings_hash
|
166
|
+
unless db_settings_hash.nil?
|
167
|
+
ActiveRecord::Base.configurations.update("test" => db_settings_hash)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def assert_file_present file
|
172
|
+
error = build_message error,
|
173
|
+
"? not found",
|
174
|
+
file
|
175
|
+
assert_block error do
|
176
|
+
File.exists?(file)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def assert_file_not_present file
|
181
|
+
error = build_message error,
|
182
|
+
"? shouldn't exist",
|
183
|
+
file
|
184
|
+
assert_block error do
|
185
|
+
!File.exists?(file)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
def get_message_fixture fixture_name
|
190
|
+
fixture_file = ADAPTOR_ROOT + '/test/fixtures/' + fixture_name + '.xml'
|
191
|
+
fixture_contents = ""
|
192
|
+
File.open(fixture_file).each { |line|
|
193
|
+
unless line =~ /^ {0,}#/
|
194
|
+
fixture_contents << line.strip.chomp
|
195
|
+
end
|
196
|
+
}
|
197
|
+
fixture_contents.chomp
|
198
|
+
end
|
199
|
+
|
200
|
+
def load_message_fixture fixture_symbol
|
201
|
+
data = get_message_fixture(fixture_symbol.to_s)
|
202
|
+
class_name = self.class.to_s.gsub("Test", "")
|
203
|
+
class_name = class_name.gsub("Adaptor", "")
|
204
|
+
message_class = get_class_object(class_name)
|
205
|
+
message_object = message_class.to_object(data)
|
206
|
+
[data, message_object]
|
207
|
+
end
|
208
|
+
|
209
|
+
def get_class_object(searched_class)
|
210
|
+
class_object = nil
|
211
|
+
ObjectSpace.each_object(Class){|aClass|
|
212
|
+
class_object = aClass if aClass.to_s == searched_class
|
213
|
+
}
|
214
|
+
if class_object.nil?
|
215
|
+
raise Exception.new("Unknown class #{searched_class}.")
|
216
|
+
else
|
217
|
+
return class_object
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
def message message_symbol
|
222
|
+
# build a message object from fixture
|
223
|
+
message_xml, message_object = load_message_fixture message_symbol
|
224
|
+
|
225
|
+
# load mock objects
|
226
|
+
Dir["test/mocks/test/*.rb"].each do |f|
|
227
|
+
require f
|
228
|
+
end
|
229
|
+
|
230
|
+
# clean mom (delete mom.txt file)
|
231
|
+
mom_mock_file = 'test/mocks/test/mom.txt'
|
232
|
+
if File.exists? mom_mock_file
|
233
|
+
File.delete mom_mock_file
|
234
|
+
end
|
235
|
+
|
236
|
+
# process message
|
237
|
+
@adaptor.process message_object
|
238
|
+
|
239
|
+
end
|
240
|
+
|
241
|
+
def compare_xml_elements element1, element2
|
242
|
+
if element1.has_attributes?
|
243
|
+
if !elements2.has_attributes?
|
244
|
+
return false
|
245
|
+
end
|
246
|
+
element1.attributes.to_a.each do |a|
|
247
|
+
if !element2.attributes.to_a.include?(a)
|
248
|
+
return false
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
if element1.has_text?
|
253
|
+
if !element2.has_text?
|
254
|
+
return false
|
255
|
+
end
|
256
|
+
if element1.text != element2.text
|
257
|
+
return false
|
258
|
+
end
|
259
|
+
end
|
260
|
+
if element1.has_elements?
|
261
|
+
if !element2.has_elements?
|
262
|
+
return false
|
263
|
+
end
|
264
|
+
element1.elements.to_a.each do |e1|
|
265
|
+
element_exists = false
|
266
|
+
element2.elements.to_a.each do |e2|
|
267
|
+
result = compare_xml_elements e1, e2
|
268
|
+
if result == true
|
269
|
+
element_exists = true
|
270
|
+
break
|
271
|
+
end
|
272
|
+
end
|
273
|
+
if element_exists == false
|
274
|
+
return false
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
return true
|
280
|
+
end
|
281
|
+
|
282
|
+
end
|