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