# Copyright 2011 Amazon.com, Inc. or its affiliates. All Rights Reserved.## Licensed under the Apache License, Version 2.0 (the "License"). You# may not use this file except in compliance with the License. A copy of# the License is located at## http://aws.amazon.com/apache2.0/## or in the "license" file accompanying this file. This file is# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF# ANY KIND, either express or implied. See the License for the specific# language governing permissions and limitations under the License.moduleAWSmoduleCore# @privateclassResourceincludeModelincludeCacheable# @privateclassNotFound<StandardError;enddefinitialize*argssuper# cache static attributes passed into optionsoptions=args.last.is_a?(Hash)?args.last:{}options.each_pairdo|opt_name,opt_value|ifself.class.attributes.has_key?(opt_name)andself.class.attributes[opt_name].static?thenstatic_attributes[opt_name]=opt_valueendendend# @return [String] Returns a simple string representation of this resource.definspectidentifiers=[]resource_identifiers.eachdo|key,value|ifattr=self.class.attributes.values.find{|a|a.get_as==key}identifiers<<"#{attr.name}:#{value}"elseidentifiers<<"#{key}:#{value}"endend"<#{self::class}#{identifiers.join(' ')}>"end# @return [Boolean] Returns true if the objects references the same# AWS resource.def==otherother.kind_of?(self.class)andresource_identifiers==other.resource_identifiersendalias_method:eql?,:==# @privateprotecteddefget_resourceattr_nameraiseNotImplementedErrorend# @privateprotecteddefupdate_resourceattr,valueraiseNotImplementedErrorend# Overide this method is subclasses of Resource. This method should # return an array of identifying key/value pairs.## # @private# protected# def resource_identifiers# [[:user_name, name]]# end# # @privateprotecteddefresource_identifiersraiseNotImplementedErrorend# @protectedprotecteddefresource_options(additional={})Hash[resource_identifiers].merge(additional)end# @privateprotecteddeflocal_cache_keyresource_identifiers.collect{|name,value|value.to_s}.join(":")end# @privateprotecteddefstatic_attributes@static_attributes||={}end# @privateprotecteddefruby_name@ruby_name||=Inflection.ruby_name(self.class.name)end# @privatepublicdefattributes_from_responserespattributes={}self.class.attribute_providers_for(resp.request_type).eachdo|provider|attributes.merge!(provider.attributes_from_response(self,resp))end# cache static attributesattributes.eachdo|attr_name,value|ifself.class.attributes[attr_name].static?static_attributes[attr_name]=valueendendattributes.empty??nil:attributesend# @privateprotecteddefcache_static_attributesrequest_type,resp_objself.class.attribute_providers_for(request_type).eachdo|provider|attributes=provider.attributes_from_response_object(resp_obj)attributes.each_pairdo|attr_name,value|ifself.class.attributes[attr_name].static?static_attributes[attr_name]=valueendendendendclass<<self# @privatedefnew_fromrequest_type,resp_obj,*argsresource=new(*args)resource.send(:cache_static_attributes,request_type,resp_obj)resourceend# @privatedefattributes@attributes||=Hash.newdo|hash,attr_name|raise"uknown attribute #{attr_name}"endend# @privatedefattribute_providers@attribute_providers||=[]end# @privatedefattribute_providers_forrequest_typeattribute_providers.selectdo|provider|provider.request_types.include?(request_type)endend# @privateprotecteddefattributename,options={},&blockattr=Attribute.new(name,options)attr.instance_eval(&block)ifblock_given?define_attribute_getter(attr)define_attribute_setter(attr)ifattr.mutable?attributes[attr.name]=attrend# @privateprotecteddefmutable_attributename,options={},&blockattribute(name,options.merge(:mutable=>true),&block)end# @privateprotecteddefdefine_attribute_getterattributedefine_method(attribute.name)doreturnstatic_attributes[attribute.name]ifstatic_attributes.has_key?(attribute.name)beginretrieve_attribute(attribute){get_resource(attribute)}rescueCacheable::NoData=>ename=ruby_name.tr("_"," ")raiseNotFound,"unable to find the #{name}"endendend# @privateprotecteddefdefine_attribute_setterattributesetter=attribute.name.to_s.sub(/\?/,'')+'='define_method(setter)do|value|translated_value=attribute.translate_input_value(value)update_resource(attribute,translated_value)ifattribute.static?static_attributes[attribute.name]=translated_valueendvalueendend# @privateprotecteddefpopulates_from*request_types,&blockprovider=provider(*request_types)provider.find(&block)provider.provides(*attributes.keys)providerend# @privateprotecteddefprovider*request_types,&blockprovider=AttributeProvider.new(self,request_types)ifblock_given?yield(provider)endattribute_providers<<providerproviderendend# @privateclassAttributedefinitializename,options={}@name=name@options=options@request_types=[]endattr_reader:nameattr_reader:request_typesdefget_as@get_as||=(@options[:get_as]||@options[:as]||name)enddefset_as@set_as||=(@options[:set_as]||@options[:as]||name)enddefmutable?@options[:mutable]==trueenddefstatic?@options[:static]==trueenddeftranslates_input&block@input_translator=blockenddeftranslates_outputoptions={},&block@translates_nil=options[:nil]@output_translator=blockenddeftranslate_input_valuevalue@input_translator?@input_translator.call(value):valueenddeftranslate_output_valuevalue# by default nil values are not translatedreturnnilifvalue.nil?and@translates_nil!=truecasewhen@options[:to_sym]thenvalue.tr('-','_').downcase.to_symwhen@output_translatorthen@output_translator.call(value)elsevalueendendend# @privateclassAttributeProviderdefinitializeklass,request_types@klass=klass@id=klass.attribute_providers.length@request_types=request_types@provides={}endattr_reader:request_typesdeffind&block@klass.send(:define_method,finder_method,&block)enddeffinder_method"find_in_response_#{@id}"end# Indicates that all of the the named attributes can be retrieved# from an appropriate response object.# # @param [Symbol] attr_names A list of attributes provided# @param [Hash] options# @option options [Boolean] :value_wrapped (false) If true, then# the value returned by the response object will also receive# the message :value before it is translated and returned.# @option options [Symbol] :get_as Defaults to the method named# by the attribute. This is useful when you have two providers# for the same attribute but their response object name# them differently.defprovides*attr_namesoptions=attr_names.last.is_a?(Hash)?attr_names.pop:{}attr_names.eachdo|attr_name|attr=@klass.attributes[attr_name]attr.request_types.push(*request_types)@provides[attr_name]=optionsendenddefattributes_from_responseresource,responseifresponse_object=resource.send(finder_method,response)attributes_from_response_object(response_object)else{}endenddefattributes_from_response_objectresp_objattributes={}@provides.eachdo|attr_name,options|attr=@klass.attributes[attr_name]method=options[:get_as]||attr.get_asv=resp_obj.respond_to?(method)?resp_obj.send(method):nilv=v.valueifvandoptions[:value_wrapped]v=attr.translate_output_value(v)attributes[attr_name]=vendattributesendendendendend