ECS 0.1.0
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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README +3 -0
- data/lib/ecs.rb +268 -0
- data/lib/ecs/help.rb +282 -0
- data/lib/ecs/help_response_group.rb +67 -0
- data/lib/ecs/operations.rb +39 -0
- data/lib/ecs/response_groups.rb +7 -0
- data/lib/ecs/time_management.rb +58 -0
- data/lib/libxml_additions.rb +51 -0
- data/lib/string_additions.rb +15 -0
- data/test/all_tests.rb +16 -0
- data/test/unit/ecs_test.rb +379 -0
- data/test/unit/libxml_additions_test.rb +121 -0
- data/test/unit/string_additions_test.rb +27 -0
- data/test/unit/unit_test_setup.rb +40 -0
- metadata +67 -0
data/CHANGELOG
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
0.1.0
|
2
|
+
* Initial release
|
3
|
+
* Forces ECS API version 2007-01-17
|
4
|
+
* Requires libxml-ruby (tested with libxml-ruby-0.3.8.4)
|
5
|
+
* The XML returned from ECS, when parsed into an XML::Document or XML::Node object (libxml-ruby-0.3.8.4)
|
6
|
+
breaks the find() method on both classes. If I strip the namespace, it works.
|
7
|
+
ECS.strip_namespace? governs this behavior.
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2007 Zachary Holt
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
data/lib/ecs.rb
ADDED
@@ -0,0 +1,268 @@
|
|
1
|
+
#!/usr/local/bin/ruby
|
2
|
+
|
3
|
+
dir = File::dirname( __FILE__ )
|
4
|
+
|
5
|
+
require 'rubygems'
|
6
|
+
require 'xml/libxml'
|
7
|
+
require 'digest/md5'
|
8
|
+
require 'net/http'
|
9
|
+
require 'erb'
|
10
|
+
|
11
|
+
module ECS
|
12
|
+
Dir[File.join( File.dirname( __FILE__ ), "*.rb" )].each { |f| require f }
|
13
|
+
|
14
|
+
require File.join( File.dirname( __FILE__ ), 'ecs', 'operations' )
|
15
|
+
require File.join( File.dirname( __FILE__ ), 'ecs', 'response_groups' )
|
16
|
+
require File.join( File.dirname( __FILE__ ), 'ecs', 'help' )
|
17
|
+
require File.join( File.dirname( __FILE__ ), 'ecs', 'help_response_group' )
|
18
|
+
require File.join( File.dirname( __FILE__ ), 'ecs', 'time_management' )
|
19
|
+
|
20
|
+
# [ 'help', 'help_response_group', 'operations', 'response_groups', 'time_management' ].each { |f| require( File.join( File.dirname( __FILE__ ), 'ecs', f ) ) }
|
21
|
+
# Dir[File.join( File.join( File.dirname( __FILE__ ), 'ecs' ), "*.rb" )].each { |f| require f }
|
22
|
+
# Dir[File.join( File.join( File.dirname( __FILE__ ), 'ecs', 'operation' ), "*.rb" )].each { |f| require f }
|
23
|
+
# Dir[File.join( File.join( File.dirname( __FILE__ ), 'ecs', 'response_group' ), "*.rb" )].each { |f| require f }
|
24
|
+
|
25
|
+
@@associate_id = 'limn-20'
|
26
|
+
@@access_key_id = ''
|
27
|
+
@@default_default_locale = :us
|
28
|
+
@@default_locale = @@default_default_locale
|
29
|
+
@@cache_directory = ''
|
30
|
+
@@cache = true
|
31
|
+
@@cache_suffix = 'ecs_cache'
|
32
|
+
|
33
|
+
# libxml-ruby is not able to do XML::Document#find or XML::Node#find with xml returned from Amazon.
|
34
|
+
# If you remove the namespace from the xml, it works perfectly
|
35
|
+
@@strip_namespace = true
|
36
|
+
|
37
|
+
def self.method_missing( meth, *args )
|
38
|
+
meth_s = meth.to_s
|
39
|
+
begin
|
40
|
+
klass_name = meth_s.camel_case
|
41
|
+
instance = nil
|
42
|
+
if meth_s =~ /^(.*)_response_group$/
|
43
|
+
instance = self.resolve_response_group_klass( klass_name )
|
44
|
+
else
|
45
|
+
klass = self.resolve_operation_klass( klass_name )
|
46
|
+
|
47
|
+
# string_to_eval = "#{klass_name}.new"
|
48
|
+
# puts "Now going to #{string_to_eval}"
|
49
|
+
instance = klass.new
|
50
|
+
# instance = instance_eval( string_to_eval, __FILE__, __LINE__ )
|
51
|
+
instance.parameters = *args
|
52
|
+
instance.parameters = {} unless instance.parameters.is_a?( Hash )
|
53
|
+
|
54
|
+
# If no ResponsGroup is set, then allow the defaults
|
55
|
+
unless instance.parameters[:ResponseGroup].nil?
|
56
|
+
# Otherwise, be sure :Request is included
|
57
|
+
instance.parameters[:ResponseGroup] = [instance.parameters[:ResponseGroup]] unless instance.parameters[:ResponseGroup].is_a?( Array )
|
58
|
+
instance.parameters[:ResponseGroup] << :Request unless instance.parameters[:ResponseGroup].include?( :Request ) || instance.parameters[:ResponseGroup].include?( 'Request' )
|
59
|
+
end
|
60
|
+
end
|
61
|
+
instance
|
62
|
+
rescue NameError => e
|
63
|
+
raise NameError, "#{e.message}"#Are you sure that ECS::#{klass_name} is defined?"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
def self.associate_id
|
69
|
+
@@associate_id
|
70
|
+
end
|
71
|
+
def self.associate_id=( k )
|
72
|
+
@@associate_id = k.to_s
|
73
|
+
end
|
74
|
+
def self.access_key_id
|
75
|
+
@@access_key_id
|
76
|
+
end
|
77
|
+
def self.access_key_id=( i )
|
78
|
+
@@access_key_id = i.to_s
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.default_locale
|
82
|
+
@@default_locale
|
83
|
+
end
|
84
|
+
def self.default_locale=( loc )
|
85
|
+
@@default_locale = self.resolve_locale( loc )
|
86
|
+
end
|
87
|
+
def self.reset_default_locale
|
88
|
+
@@default_locale = @@default_default_locale
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.cache_directory
|
92
|
+
@@cache_directory
|
93
|
+
end
|
94
|
+
def self.cache_directory=( d='' )
|
95
|
+
directory = File.expand_path( d )
|
96
|
+
Dir.mkdir( directory ) unless File.exist?( directory )
|
97
|
+
raise( EACCESS, "#{directory} is not a suitable cache directory" ) unless File.writable?( directory ) && File.directory?( directory )
|
98
|
+
@@cache_directory = directory
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
def self.available_locales
|
103
|
+
[ :ca, :de, :fr, :jp, :uk, :us ]
|
104
|
+
end
|
105
|
+
|
106
|
+
def self.base_urls
|
107
|
+
{
|
108
|
+
:ca => 'http://webservices.amazon.ca/onca/xml?Service=AWSECommerceService',
|
109
|
+
:de => 'http://webservices.amazon.de/onca/xml?Service=AWSECommerceService',
|
110
|
+
:fr => 'http://webservices.amazon.fr/onca/xml?Service=AWSECommerceService',
|
111
|
+
:jp => 'http://webservices.amazon.co.jp/onca/xml?Service=AWSECommerceService',
|
112
|
+
:uk => 'http://webservices.amazon.co.uk/onca/xml?Service=AWSECommerceService',
|
113
|
+
:us => 'http://webservices.amazon.com/onca/xml?Service=AWSECommerceService'
|
114
|
+
}
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
def self.api_version
|
119
|
+
'2007-02-22'
|
120
|
+
end
|
121
|
+
|
122
|
+
def self.strip_namespace?
|
123
|
+
@@strip_namespace != false
|
124
|
+
end
|
125
|
+
def self.strip_namespace=( s )
|
126
|
+
@@strip_namespace = s != false
|
127
|
+
end
|
128
|
+
|
129
|
+
def self.call_web_service( p={} )
|
130
|
+
parameters = p.is_a?( Hash ) ? p : {}
|
131
|
+
|
132
|
+
locale = self.resolve_locale( parameters[:locale] )
|
133
|
+
parameters.delete( :locale )
|
134
|
+
|
135
|
+
sleep( ECS::TimeManagement.sleep_duration )
|
136
|
+
url = "#{ self.base_urls[locale] }&AWSAccessKeyId=#{self.access_key_id}&Version=#{self.api_version}&AssociateTag=#{self.associate_id}&#{ parameters.keys.map{ |k| "#{ERB::Util.url_encode( k.to_s ) }=#{ERB::Util.url_encode( parameters[k].is_a?( Array ) ? parameters[k].join( ',' ) : parameters[k].to_s )}" }.join( '&' ) }"
|
137
|
+
#puts url
|
138
|
+
r = Net::HTTP.get_response( URI.parse( url ) )
|
139
|
+
r.value # this will raise an error if there was one.
|
140
|
+
@@strip_namespace && r.body =~ /(.*)xmlns\s*=\s*".*?"(.*)/m ? "#{$1}#{$2}" : r.body
|
141
|
+
end
|
142
|
+
|
143
|
+
def self.resolve_locale( l=nil )
|
144
|
+
!l.nil? && self.available_locales.include?( l.to_s.downcase.to_sym ) ? l.to_s.downcase.to_sym : self.default_locale
|
145
|
+
end
|
146
|
+
|
147
|
+
def self.resolve_response_group_klass( name='' )
|
148
|
+
klass_name = ECS::HelpResponseGroup.resolve_response_group_name( name )
|
149
|
+
klass = ECS::ResponseGroups[klass_name]
|
150
|
+
if klass.nil?
|
151
|
+
string_to_eval = "class #{klass_name} < HelpResponseGroup
|
152
|
+
@@response_group_name=nil
|
153
|
+
@@valid_operations=nil
|
154
|
+
@@elements=nil
|
155
|
+
@@help_xml=nil
|
156
|
+
ECS::ResponseGroups['#{klass_name}'] = self
|
157
|
+
end
|
158
|
+
#{klass_name}"
|
159
|
+
#puts string_to_eval
|
160
|
+
klass = instance_eval( string_to_eval, __FILE__, __LINE__ )
|
161
|
+
end
|
162
|
+
klass
|
163
|
+
end
|
164
|
+
def self.resolve_operation_klass( name='' )
|
165
|
+
klass_name = ECS::Help.resolve_operation_name( name )
|
166
|
+
klass = ECS::Operations[klass_name]
|
167
|
+
if klass.nil?
|
168
|
+
string_to_eval = "class #{klass_name} < Help
|
169
|
+
@@operation_name=nil
|
170
|
+
@@help_xml=nil
|
171
|
+
@@required_parameters=nil
|
172
|
+
@@available_parameters=nil
|
173
|
+
@@default_response_groups=nil
|
174
|
+
@@available_response_groups=nil
|
175
|
+
ECS::Operations['#{klass_name}'] = self
|
176
|
+
end
|
177
|
+
#{klass_name}"
|
178
|
+
# puts string_to_eval
|
179
|
+
klass = instance_eval( string_to_eval, __FILE__, __LINE__ )
|
180
|
+
end
|
181
|
+
klass
|
182
|
+
end
|
183
|
+
|
184
|
+
def self.xml_for_parameters( parameters={}, force=false )
|
185
|
+
# if you pass a block to this method, the XML::Document object
|
186
|
+
# will be yielded (if it's not cached) and you will be able to return
|
187
|
+
# true to cache it or false to not cache it. The object is yielded
|
188
|
+
# regardless of the value of ECS.cache?
|
189
|
+
# In other words, ECS.cache? is respected only when there is no block
|
190
|
+
tag = self.resolve_cache_tag( parameters )
|
191
|
+
xml = nil
|
192
|
+
|
193
|
+
xml = self.read_cache( tag ) unless force
|
194
|
+
|
195
|
+
if xml.nil?
|
196
|
+
xml = self.call_web_service( parameters )
|
197
|
+
parser = XML::Parser.new
|
198
|
+
parser.string = xml
|
199
|
+
xml = parser.parse
|
200
|
+
we_should_cache = block_given? ? yield( xml ) : self.cache?
|
201
|
+
self.write_cache( tag, xml.to_s ) if we_should_cache
|
202
|
+
end
|
203
|
+
|
204
|
+
xml
|
205
|
+
end
|
206
|
+
|
207
|
+
def self.read_cache( tag_or_parameters )
|
208
|
+
tag = tag_or_parameters.is_a?( String ) ? tag_or_parameters : self.resolve_cache_tag( tag_or_parameters )
|
209
|
+
XML::Document.file( tag ) if File.exist?( tag )
|
210
|
+
end
|
211
|
+
def self.write_cache( tag_or_parameters, content )
|
212
|
+
tag = tag_or_parameters.is_a?( String ) ? tag_or_parameters : self.resolve_cache_tag( tag_or_parameters )
|
213
|
+
File.open( tag, 'w' ) { |f| f << content }
|
214
|
+
end
|
215
|
+
|
216
|
+
def self.clear_cache( tag=nil )
|
217
|
+
if tag.nil?
|
218
|
+
Dir[File.join( self.cache_directory, "*.#{@@cache_suffix}" )].each { |f| File.unlink( f ) }
|
219
|
+
else
|
220
|
+
File.unlink( tag )
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
def self.cache?
|
225
|
+
@@cache != false
|
226
|
+
end
|
227
|
+
def self.cache=( true_or_false=true )
|
228
|
+
@@cache = true_or_false != false
|
229
|
+
end
|
230
|
+
|
231
|
+
def self.cached?( p={} )
|
232
|
+
File.exist?( p.is_a?( String ) ? p : self.resolve_cache_tag( p ) )
|
233
|
+
end
|
234
|
+
|
235
|
+
|
236
|
+
def self.query_string( p={} )
|
237
|
+
( p.is_a?( Hash ) ? p : {} ).keys.map{ |k| k.to_s }.sort.map{ |k| "#{k}=#{p[k.to_sym]}" }.join( '&' )
|
238
|
+
end
|
239
|
+
|
240
|
+
def self.resolve_cache_tag( p={} )
|
241
|
+
"#{cache_directory}/#{Digest::MD5.hexdigest( p.is_a?( String ) ? p : query_string( p ) )}.#{@@cache_suffix}"
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
##At this point I can do
|
246
|
+
##
|
247
|
+
##b = ECS.browse_node_lookup( :BrowseNodeId => 43242 )
|
248
|
+
##
|
249
|
+
##and b is an object of class ECS::BrowseNodeLookup
|
250
|
+
##
|
251
|
+
##
|
252
|
+
##What I would like to be able to do is say
|
253
|
+
##
|
254
|
+
##1) b.results (or some such)
|
255
|
+
##
|
256
|
+
##and get either one ECS::BroseNodeInfo (which include ECS::ResponseGroup) object
|
257
|
+
##or an array of ECS::BrowseNodeInfo objects
|
258
|
+
##
|
259
|
+
##
|
260
|
+
##This should happen by
|
261
|
+
##
|
262
|
+
##2) Checking a @results instance variable
|
263
|
+
##
|
264
|
+
##3) If @results is null, parse and iterate over the xml, creating a ECS::BrowseNodeInfo object for each <BrowseNodeInfo> element
|
265
|
+
##
|
266
|
+
##4) If the xml is null, check the disk to see whether there is a cached version
|
267
|
+
##
|
268
|
+
##5) If there is no cached version, call the web service and get the xml, caching it when you are done with it
|
data/lib/ecs/help.rb
ADDED
@@ -0,0 +1,282 @@
|
|
1
|
+
#!/usr/local/bin/ruby
|
2
|
+
|
3
|
+
module ECS
|
4
|
+
class Help
|
5
|
+
instance_variable_set( '@operation_name', nil )
|
6
|
+
instance_variable_set( '@help_xml', nil )
|
7
|
+
instance_variable_set( '@required_parameters', nil )
|
8
|
+
instance_variable_set( '@available_parameters', nil )
|
9
|
+
instance_variable_set( '@default_response_groups', nil )
|
10
|
+
instance_variable_set( '@available_response_groups', nil )
|
11
|
+
|
12
|
+
|
13
|
+
@@help_map = {
|
14
|
+
:required_parameters => { :call_path => 'HelpResponse.Information.OperationInformation.RequiredParameters.Parameter' },
|
15
|
+
:available_parameters => { :call_path => 'HelpResponse.Information.OperationInformation.AvailableParameters.Parameter' },
|
16
|
+
:default_response_groups => { :call_path => 'HelpResponse.Information.OperationInformation.DefaultResponseGroups.ResponseGroup' },
|
17
|
+
:available_response_groups => { :call_path => 'HelpResponse.Information.OperationInformation.AvailableResponseGroups.ResponseGroup' }
|
18
|
+
}
|
19
|
+
|
20
|
+
attr_accessor :parameters, :xml
|
21
|
+
ECS::Operations['Help'] = self
|
22
|
+
|
23
|
+
def self.operation_name
|
24
|
+
@operation_name ||= self.resolve_operation_name( self.name )
|
25
|
+
end
|
26
|
+
def self.help_xml( force=false )
|
27
|
+
if force || @help_xml.nil?
|
28
|
+
@help_xml = ECS.help( :HelpType => 'Operation', :About => self.operation_name ) { |x| ECS::Help.valid_aws_response( x ) }.xml
|
29
|
+
end
|
30
|
+
@help_xml
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
def self.valid_aws_response?( x )
|
35
|
+
xml = x
|
36
|
+
unless x.is_a?( XML::Document )
|
37
|
+
p = XML::Parser.new
|
38
|
+
p.string = x
|
39
|
+
xml = p.parse
|
40
|
+
end
|
41
|
+
|
42
|
+
if self.errors_from_aws( xml ).empty?
|
43
|
+
n = xml.find( '//Request/IsValid' ).first
|
44
|
+
n.nil? || n.content.downcase != 'false'
|
45
|
+
else
|
46
|
+
false
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.errors_from_aws( x )
|
51
|
+
xml = x
|
52
|
+
unless x.is_a?( XML::Document )
|
53
|
+
p = XML::Parser.new
|
54
|
+
p.string = x
|
55
|
+
xml = p.parse
|
56
|
+
end
|
57
|
+
|
58
|
+
errors = []
|
59
|
+
xml.find( '//Errors/Error' ).each do |error_node|
|
60
|
+
begin
|
61
|
+
m = error_node.Message.content
|
62
|
+
c = error_node.Code.content.gsub( /[\.:\s,\-_]/, '' )
|
63
|
+
errors << RuntimeError.new( m )
|
64
|
+
rescue Exception => e
|
65
|
+
end
|
66
|
+
end
|
67
|
+
errors
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
def self.required_parameters( force=false )
|
72
|
+
if force || @required_parameters.nil?
|
73
|
+
@required_parameters = []
|
74
|
+
self.help_xml.HelpResponse.Information.OperationInformation.RequiredParameters.Parameter.each do |p|
|
75
|
+
@required_parameters << p.content.to_s.to_sym
|
76
|
+
end
|
77
|
+
end
|
78
|
+
@required_parameters
|
79
|
+
rescue
|
80
|
+
[]
|
81
|
+
end
|
82
|
+
def self.available_parameters( force=false )
|
83
|
+
if force || @available_parameters.nil?
|
84
|
+
@available_parameters = []
|
85
|
+
self.help_xml.HelpResponse.Information.OperationInformation.AvailableParameters.Parameter.each do |p|
|
86
|
+
@available_parameters << p.content.to_s.to_sym
|
87
|
+
end
|
88
|
+
end
|
89
|
+
@available_parameters
|
90
|
+
end
|
91
|
+
def self.optional_parameters( force=false )
|
92
|
+
self.available_parameters( force )
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.default_response_groups( force=false )
|
96
|
+
if force || @default_response_groups.nil?
|
97
|
+
@default_response_groups = []
|
98
|
+
self.help_xml.HelpResponse.Information.OperationInformation.DefaultResponseGroups.ResponseGroup.each do |p|
|
99
|
+
@default_response_groups << ECS.resolve_response_group_klass( "#{p.content.to_s}ResponseGroup" )
|
100
|
+
end
|
101
|
+
end
|
102
|
+
@default_response_groups
|
103
|
+
end
|
104
|
+
def self.available_response_groups( force=false )
|
105
|
+
if force || @available_response_groups.nil?
|
106
|
+
@available_response_groups = []
|
107
|
+
self.help_xml.HelpResponse.Information.OperationInformation.AvailableResponseGroups.ResponseGroup.each do |p|
|
108
|
+
@available_response_groups << ECS.resolve_response_group_klass( "#{p.content.to_s}ResponseGroup" )
|
109
|
+
end
|
110
|
+
end
|
111
|
+
@available_response_groups
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
def self.resolve_operation_name( t )
|
116
|
+
t =~ /::([^:]*)$/ ? $1 : t
|
117
|
+
end
|
118
|
+
|
119
|
+
def operation_name
|
120
|
+
self.class.operation_name
|
121
|
+
end
|
122
|
+
|
123
|
+
def help_xml( force=false )
|
124
|
+
self.class.help_xml( force )
|
125
|
+
end
|
126
|
+
|
127
|
+
def xml( force=false )
|
128
|
+
if force || @xml.nil?
|
129
|
+
self.class.required_parameters.each do |p|
|
130
|
+
raise(
|
131
|
+
ArgumentError,
|
132
|
+
"#{p} is a required parameter for the #{ self.operation_name } operation"
|
133
|
+
) if !self.parameters.keys.include?( p.to_sym ) || self.parameters[p.to_sym].to_s.empty?
|
134
|
+
end
|
135
|
+
|
136
|
+
# Cache the xml only if it's a valid AWS Response
|
137
|
+
@xml = ECS.xml_for_parameters( self.parameters_for_xml ) { |x| ECS::Help.valid_aws_response?( x ) }
|
138
|
+
end
|
139
|
+
@xml
|
140
|
+
end
|
141
|
+
|
142
|
+
def parameters_for_xml
|
143
|
+
self.parameters.merge( :Operation => self.operation_name )
|
144
|
+
end
|
145
|
+
|
146
|
+
def cached?
|
147
|
+
ECS.cached?( self.parameters_for_xml )
|
148
|
+
end
|
149
|
+
|
150
|
+
def cached_content
|
151
|
+
ECS.read_cache( self.parameters_for_xml )
|
152
|
+
end
|
153
|
+
|
154
|
+
def headers( force=false )
|
155
|
+
if force || @headers.nil?
|
156
|
+
@headers = {}
|
157
|
+
self.xml.find( '//OperationRequest/HTTPHeaders/Header' ).each do |header|
|
158
|
+
name = ''
|
159
|
+
value = ''
|
160
|
+
header.each_attr do |attribute|
|
161
|
+
name = attribute.value.to_sym if attribute.name == 'Name'
|
162
|
+
value = attribute.value if attribute.name == 'Value'
|
163
|
+
end
|
164
|
+
@headers[name] = value
|
165
|
+
end
|
166
|
+
end
|
167
|
+
@headers
|
168
|
+
rescue
|
169
|
+
@headers = []
|
170
|
+
end
|
171
|
+
|
172
|
+
def request_id( force=false )
|
173
|
+
if force || @request_id.nil?
|
174
|
+
@request_id = self.xml.find( '//OperationRequest/RequestId' ).first.content
|
175
|
+
end
|
176
|
+
@request_id
|
177
|
+
rescue
|
178
|
+
@request_id = 'Could not determine request_id'
|
179
|
+
end
|
180
|
+
|
181
|
+
def arguments( force=false )
|
182
|
+
if force || @arguments.nil?
|
183
|
+
@arguments = {}
|
184
|
+
self.xml.find( '//OperationRequest/Arguments/Argument' ).each do |argument|
|
185
|
+
name = ''
|
186
|
+
value = ''
|
187
|
+
argument.each_attr do |attribute|
|
188
|
+
name = attribute.value.to_sym if attribute.name == 'Name'
|
189
|
+
value = attribute.value if attribute.name == 'Value'
|
190
|
+
end
|
191
|
+
@arguments[name] = value
|
192
|
+
end
|
193
|
+
end
|
194
|
+
@arguments
|
195
|
+
rescue
|
196
|
+
@arguments = {}
|
197
|
+
end
|
198
|
+
|
199
|
+
def request_processing_time( force=false )
|
200
|
+
if force || @request_processing_time.nil?
|
201
|
+
@request_processing_time = self.xml.find( '//OperationRequest/RequestProcessingTime' ).first.content.to_f
|
202
|
+
end
|
203
|
+
@request_processing_time
|
204
|
+
rescue
|
205
|
+
@request_processing_time = -1.0
|
206
|
+
end
|
207
|
+
|
208
|
+
def response_groups( force=false )
|
209
|
+
#these are the response groups that are included in this instance,
|
210
|
+
#not all those available to the class
|
211
|
+
if force || @response_groups.nil?
|
212
|
+
@response_groups = []
|
213
|
+
|
214
|
+
response_group_names = self.arguments[:ResponseGroup]
|
215
|
+
|
216
|
+
if response_group_names.nil?
|
217
|
+
@response_groups = self.class.default_response_groups
|
218
|
+
else
|
219
|
+
response_group_names.split( ',' ).each do |response_group_name|
|
220
|
+
@response_groups << ECS.resolve_response_group_klass( "#{response_group_name}ResponseGroup" )
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
@response_groups
|
225
|
+
end
|
226
|
+
|
227
|
+
def potential_elements( force=false )
|
228
|
+
if force || @potential_elements.nil?
|
229
|
+
@potential_elements = []
|
230
|
+
self.response_groups.each do |response_group|
|
231
|
+
@potential_elements << response_group.elements
|
232
|
+
end
|
233
|
+
@potential_elements.flatten!.uniq!
|
234
|
+
end
|
235
|
+
@potential_elements
|
236
|
+
end
|
237
|
+
|
238
|
+
def errors( force=false )
|
239
|
+
@errors = self.class.errors_from_aws( self.xml ) if force || @errors.nil?
|
240
|
+
@errors
|
241
|
+
end
|
242
|
+
|
243
|
+
def valid?( force=false )
|
244
|
+
@valid = self.class.valid_aws_response?( self.xml ) if force || @valid.nil?
|
245
|
+
@valid
|
246
|
+
end
|
247
|
+
|
248
|
+
|
249
|
+
def method_missing( meth, *args )
|
250
|
+
method_name = meth.to_s
|
251
|
+
|
252
|
+
# Note that if there is an element in the xml called each_*,
|
253
|
+
# in order to get to it, you can't pass a block
|
254
|
+
if method_name =~ /^each_(.*)$/ && block_given?
|
255
|
+
x = self.send( $1.to_sym, *args )
|
256
|
+
if [ Array, XML::Node::Set].include?( x.class )
|
257
|
+
x.each { |y| yield( y ) }
|
258
|
+
else
|
259
|
+
yield( x )
|
260
|
+
end
|
261
|
+
elsif method_name =~ /^(.*)_count$/
|
262
|
+
# Note that this will return the count for all descendants
|
263
|
+
# Not just children
|
264
|
+
x = self.send( $1.to_sym, *args )
|
265
|
+
x.respond_to?( :size ) ? x.size : 1
|
266
|
+
else
|
267
|
+
instance_variable_name = "@#{method_name}_var"
|
268
|
+
self.instance_eval( "
|
269
|
+
def #{method_name}( force=false )
|
270
|
+
if force || #{instance_variable_name}.nil?
|
271
|
+
#{instance_variable_name} = self.xml.find( '//#{method_name}' )
|
272
|
+
#{instance_variable_name} = #{instance_variable_name}.first if #{instance_variable_name}.size == 1
|
273
|
+
end
|
274
|
+
#{instance_variable_name}
|
275
|
+
end
|
276
|
+
" )
|
277
|
+
|
278
|
+
self.send( meth, *args )
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|