paypal-sdk-core 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/Gemfile +11 -0
- data/README.md +16 -0
- data/Rakefile +5 -0
- data/lib/generators/paypal/sdk/USAGE +3 -0
- data/lib/generators/paypal/sdk/install_generator.rb +17 -0
- data/lib/generators/paypal/sdk/templates/paypal.rb +2 -0
- data/lib/generators/paypal/sdk/templates/paypal.yml +32 -0
- data/lib/paypal-sdk-core.rb +40 -0
- data/lib/paypal-sdk/core/api/base.rb +166 -0
- data/lib/paypal-sdk/core/api/data_types/base.rb +236 -0
- data/lib/paypal-sdk/core/api/data_types/enum.rb +26 -0
- data/lib/paypal-sdk/core/api/data_types/simple_types.rb +47 -0
- data/lib/paypal-sdk/core/api/merchant.rb +122 -0
- data/lib/paypal-sdk/core/api/platform.rb +75 -0
- data/lib/paypal-sdk/core/authentication.rb +79 -0
- data/lib/paypal-sdk/core/config.rb +138 -0
- data/lib/paypal-sdk/core/credential/base.rb +27 -0
- data/lib/paypal-sdk/core/credential/certificate.rb +32 -0
- data/lib/paypal-sdk/core/credential/signature.rb +22 -0
- data/lib/paypal-sdk/core/credential/third_party/subject.rb +25 -0
- data/lib/paypal-sdk/core/credential/third_party/token.rb +39 -0
- data/lib/paypal-sdk/core/logging.rb +43 -0
- data/lib/paypal-sdk/core/util/oauth_signature.rb +64 -0
- data/lib/paypal-sdk/core/version.rb +7 -0
- data/spec/config/cert_key.pem +33 -0
- data/spec/config/paypal.yml +29 -0
- data/spec/core/api/data_type_spec.rb +164 -0
- data/spec/core/api/merchant_spec.rb +114 -0
- data/spec/core/api/platform_spec.rb +107 -0
- data/spec/core/config_spec.rb +48 -0
- data/spec/core/logging_spec.rb +28 -0
- data/spec/log/test.log +84 -0
- data/spec/spec_helper.rb +11 -0
- metadata +109 -0
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# Paypal::Sdk::Core
|
2
|
+
|
3
|
+
Core library for PayPal ruby SDKs.
|
4
|
+
|
5
|
+
SDKs:
|
6
|
+
|
7
|
+
* [paypal-sdk-adaptivepayments](https://github.com/paypal/adaptivepayments-sdk-ruby)
|
8
|
+
* [paypal-sdk-adaptiveaccounts](https://github.com/paypal/adaptiveaccounts-sdk-ruby)
|
9
|
+
* [paypal-sdk-invoice](https://github.com/paypal/invoice-sdk-ruby)
|
10
|
+
* [paypal-sdk-permissions](https://github.com/paypal/permissions-sdk-ruby)
|
11
|
+
* [paypal-sdk-merchant](https://github.com/paypal/merchant-sdk-ruby)
|
12
|
+
* [paypal-sdk-buttonmanager](https://github.com/paypal/buttonmanager-sdk-ruby)
|
13
|
+
|
14
|
+
|
15
|
+
Note: Don't use this library directly
|
16
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module Paypal
|
2
|
+
module Sdk
|
3
|
+
module Generators
|
4
|
+
class InstallGenerator < Rails::Generators::Base
|
5
|
+
source_root File.expand_path('../templates', __FILE__)
|
6
|
+
|
7
|
+
def copy_config_file
|
8
|
+
copy_file "paypal.yml", "config/paypal.yml"
|
9
|
+
end
|
10
|
+
|
11
|
+
def copy_initializer_file
|
12
|
+
copy_file "paypal.rb", "config/initializers/paypal.rb"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
test: &default
|
2
|
+
username: jb-us-seller_api1.paypal.com
|
3
|
+
password: WX4WTU3S8MY44S7F
|
4
|
+
signature: AFcWxV21C7fd0v3bYYYRCpSSRl31A7yDhhsPUU2XhtMoZXsWHFxu-RWy
|
5
|
+
app_id: APP-80W284485P519543T
|
6
|
+
http_timeout: 30
|
7
|
+
mode: sandbox
|
8
|
+
sandbox_email_address: Platform.sdk.seller@gmail.com
|
9
|
+
|
10
|
+
development:
|
11
|
+
<<: *default
|
12
|
+
|
13
|
+
production:
|
14
|
+
<<: *default
|
15
|
+
mode: live
|
16
|
+
|
17
|
+
# with_certificate:
|
18
|
+
# <<: *default
|
19
|
+
# username: platfo_1255170694_biz_api1.gmail.com
|
20
|
+
# password: 2DPPKUPKB7DQLXNR
|
21
|
+
# signature:
|
22
|
+
# cert_path: "config/cert_key.pem"
|
23
|
+
# app_id: APP-80W284485P519543T
|
24
|
+
#
|
25
|
+
# with_oauth_token:
|
26
|
+
# <<: *default
|
27
|
+
# token: ESTy2hio5WJQo1iixkH29I53RJxaS0Gvno1A6.YQXZgktxbY4I2Tdg
|
28
|
+
# token_secret: ZKPhUYuwJwYsfWdzorozWO2U9pI
|
29
|
+
#
|
30
|
+
# with_proxy:
|
31
|
+
# <<: *default
|
32
|
+
# http_proxy: http://proxy-ipaddress:3129/
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require "paypal-sdk/core/version"
|
2
|
+
require "paypal-sdk/core/config"
|
3
|
+
require "paypal-sdk/core/logging"
|
4
|
+
|
5
|
+
module PayPal
|
6
|
+
module SDK
|
7
|
+
module Core
|
8
|
+
|
9
|
+
autoload :Authentication, "paypal-sdk/core/authentication"
|
10
|
+
|
11
|
+
module API
|
12
|
+
autoload :Base, "paypal-sdk/core/api/base"
|
13
|
+
autoload :Merchant, "paypal-sdk/core/api/merchant"
|
14
|
+
autoload :Platform, "paypal-sdk/core/api/platform"
|
15
|
+
|
16
|
+
module DataTypes
|
17
|
+
autoload :Base, "paypal-sdk/core/api/data_types/base"
|
18
|
+
autoload :Enum, "paypal-sdk/core/api/data_types/enum"
|
19
|
+
autoload :SimpleTypes, "paypal-sdk/core/api/data_types/simple_types"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
module Util
|
24
|
+
autoload :OauthSignature, "paypal-sdk/core/util/oauth_signature"
|
25
|
+
end
|
26
|
+
|
27
|
+
module Credential
|
28
|
+
autoload :Base, "paypal-sdk/core/credential/base"
|
29
|
+
autoload :Certificate, "paypal-sdk/core/credential/certificate"
|
30
|
+
autoload :Signature, "paypal-sdk/core/credential/signature"
|
31
|
+
|
32
|
+
module ThirdParty
|
33
|
+
autoload :Token, "paypal-sdk/core/credential/third_party/token"
|
34
|
+
autoload :Subject, "paypal-sdk/core/credential/third_party/subject"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module PayPal::SDK::Core
|
4
|
+
|
5
|
+
module API
|
6
|
+
# API class provide default functionality for accessing the API web services.
|
7
|
+
# == Example
|
8
|
+
# api = API::Base.new("AdaptivePayments")
|
9
|
+
# response = api.request("GetPaymentOptions", "")
|
10
|
+
class Base
|
11
|
+
|
12
|
+
include Configuration
|
13
|
+
include Logging
|
14
|
+
include Authentication
|
15
|
+
|
16
|
+
attr_accessor :http, :uri, :service_name
|
17
|
+
|
18
|
+
DEFAULT_END_POINTS = {
|
19
|
+
:sandbox => {
|
20
|
+
:platform => { # NVP EndPoint
|
21
|
+
:three_token => "https://svcs.sandbox.paypal.com/",
|
22
|
+
:certificate => "https://svcs.sandbox.paypal.com/"
|
23
|
+
},
|
24
|
+
:merchant => { # SOAP EndPoint
|
25
|
+
:three_token => "https://api-3t.sandbox.paypal.com/2.0",
|
26
|
+
:certificate => "https://api.sandbox.paypal.com/2.0"
|
27
|
+
}
|
28
|
+
},
|
29
|
+
:live => {
|
30
|
+
:platform => { # NVP EndPoint
|
31
|
+
:three_token => "https://svcs.paypal.com/",
|
32
|
+
:certificate => "https://svcs.paypal.com/"
|
33
|
+
},
|
34
|
+
:merchant => { # SOAP EndPoint
|
35
|
+
:three_token => "https://api-3t.paypal.com/2.0",
|
36
|
+
:certificate => "https://api.paypal.com/2.0"
|
37
|
+
}
|
38
|
+
}
|
39
|
+
}
|
40
|
+
DEFAULT_HTTP_HEADER = {}
|
41
|
+
|
42
|
+
# Initialize API object
|
43
|
+
# === Argument
|
44
|
+
# * <tt>service_name</tt> -- (Optional) Service name
|
45
|
+
# * <tt>environment</tt> -- (Optional) Configuration environment to load
|
46
|
+
# * <tt>options</tt> -- (Optional) Override configuration.
|
47
|
+
# === Example
|
48
|
+
# new("AdaptivePayments")
|
49
|
+
# new("AdaptivePayments", :development)
|
50
|
+
# new(:wsdl_service) # It load wsdl_service configuration
|
51
|
+
def initialize(service_name = "", environment = nil, options = {})
|
52
|
+
unless service_name.is_a? String
|
53
|
+
environment, options, service_name = service_name, environment || {}, ""
|
54
|
+
end
|
55
|
+
@service_name = service_name
|
56
|
+
set_config(environment, options)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Override set_config method to create http connection on changing the configuration.
|
60
|
+
def set_config(*args)
|
61
|
+
super
|
62
|
+
create_http_connection
|
63
|
+
end
|
64
|
+
|
65
|
+
# Create HTTP connection based on given service name or configured end point
|
66
|
+
def create_http_connection
|
67
|
+
service_path = "#{service_endpoint}/#{service_name}"
|
68
|
+
@uri = URI.parse(service_path)
|
69
|
+
if config.http_proxy
|
70
|
+
proxy = URI.parse(config.http_proxy)
|
71
|
+
@http = Net::HTTP.new(@uri.host, @uri.port, proxy.host, proxy.port, proxy.user, proxy.password)
|
72
|
+
else
|
73
|
+
@http = Net::HTTP.new(@uri.host, @uri.port)
|
74
|
+
end
|
75
|
+
@uri.path = @uri.path.gsub(/\/+/, "/")
|
76
|
+
configure_http_connection
|
77
|
+
end
|
78
|
+
|
79
|
+
# Configure HTTP connection based on configuration.
|
80
|
+
def configure_http_connection
|
81
|
+
http.use_ssl = true
|
82
|
+
http.ca_file = config.ca_file if config.ca_file
|
83
|
+
if config.http_timeout
|
84
|
+
http.open_timeout = config.http_timeout
|
85
|
+
http.read_timeout = config.http_timeout
|
86
|
+
end
|
87
|
+
add_certificate(http)
|
88
|
+
end
|
89
|
+
|
90
|
+
# Get configured API mode( sandbox or live)
|
91
|
+
def api_mode
|
92
|
+
api_modes = DEFAULT_END_POINTS.keys
|
93
|
+
config_mode = ( config.mode || api_modes.first ).to_sym
|
94
|
+
api_modes.include?(config_mode) ? config_mode : api_modes.first
|
95
|
+
end
|
96
|
+
|
97
|
+
# Get default endpoint for the given service name
|
98
|
+
# === Argument
|
99
|
+
# * <tt>name</tt> -- Service name ( platform or merchant)
|
100
|
+
# === Returns
|
101
|
+
# Return service end point based on the configured API mode.
|
102
|
+
def default_end_point(name)
|
103
|
+
default_end_point = DEFAULT_END_POINTS[api_mode][name]
|
104
|
+
if default_end_point
|
105
|
+
config.cert_path ? default_end_point[:certificate] : default_end_point[:three_token]
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Get service end point
|
110
|
+
def service_endpoint
|
111
|
+
config.end_point ? default_end_point(config.end_point.to_sym) : config.end_point
|
112
|
+
end
|
113
|
+
|
114
|
+
# Default Http header
|
115
|
+
def default_http_header
|
116
|
+
DEFAULT_HTTP_HEADER
|
117
|
+
end
|
118
|
+
|
119
|
+
# Generate HTTP request for given action and parameters
|
120
|
+
# === Arguments
|
121
|
+
# * <tt>action</tt> -- Action to perform
|
122
|
+
# * <tt>params</tt> -- (Optional) Parameters for the action
|
123
|
+
# * <tt>initheader</tt> -- (Optional) HTTP header
|
124
|
+
def request(action, params = {}, initheader = {})
|
125
|
+
uri, content, header = format_request(action, params)
|
126
|
+
initheader = default_http_header.merge(header).merge(initheader)
|
127
|
+
initheader.delete_if{|key, val| val.nil? }
|
128
|
+
start_time = Time.now
|
129
|
+
response = @http.post(uri.path, content, initheader)
|
130
|
+
format_response(action, response)
|
131
|
+
rescue Net::HTTPBadGateway, Errno::ECONNRESET, Errno::ECONNABORTED, SocketError => error
|
132
|
+
format_error(error, error.message)
|
133
|
+
ensure
|
134
|
+
log_event("Request: #{action}", start_time)
|
135
|
+
end
|
136
|
+
|
137
|
+
# Format Request data. It will be override by child class
|
138
|
+
# == Arguments
|
139
|
+
# * <tt>action</tt> -- Request action
|
140
|
+
# * <tt>params</tt> -- Request parameters
|
141
|
+
# == Return
|
142
|
+
# * <tt>path</tt> -- Formated request uri object
|
143
|
+
# * <tt>params</tt> -- Formated request Parameters
|
144
|
+
# * <tt>header</tt> -- HTTP Header
|
145
|
+
def format_request(action, params)
|
146
|
+
[ @uri, params, {} ]
|
147
|
+
end
|
148
|
+
|
149
|
+
# Format Response object. It will be override by child class
|
150
|
+
# == Argument
|
151
|
+
# * <tt>action</tt> -- Request action
|
152
|
+
# * <tt>response</tt> -- HTTP response object
|
153
|
+
def format_response(action, response)
|
154
|
+
response
|
155
|
+
end
|
156
|
+
|
157
|
+
# Format Error object. It will be override by child class.
|
158
|
+
# == Arguments
|
159
|
+
# * <tt>exception</tt> -- Exception object.
|
160
|
+
# * <tt>message</tt> -- Readable error message.
|
161
|
+
def format_error(exception, message)
|
162
|
+
raise exception
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
@@ -0,0 +1,236 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
module PayPal::SDK::Core
|
4
|
+
module API
|
5
|
+
|
6
|
+
module DataTypes
|
7
|
+
|
8
|
+
# Create attributes and restrict the object type.
|
9
|
+
# == Example
|
10
|
+
# class ConvertCurrencyRequest < Core::API::DataTypes::Base
|
11
|
+
# object_of :baseAmountList, CurrencyList
|
12
|
+
# object_of :convertToCurrencyList, CurrencyCodeList
|
13
|
+
# object_of :countryCode, String
|
14
|
+
# object_of :conversionType, String
|
15
|
+
# end
|
16
|
+
class Base
|
17
|
+
|
18
|
+
HashOptions = { :attribute => true, :namespace => true, :symbol => true }
|
19
|
+
ContentKey = :value
|
20
|
+
|
21
|
+
include SimpleTypes
|
22
|
+
|
23
|
+
class << self
|
24
|
+
|
25
|
+
# Add attribute
|
26
|
+
# === Arguments
|
27
|
+
# * <tt>name</tt> -- attribute name
|
28
|
+
# * <tt>options</tt> -- options
|
29
|
+
def add_attribute(name, options = {})
|
30
|
+
add_member(name, SimpleTypes::String, options.merge( :attribute => true ))
|
31
|
+
end
|
32
|
+
|
33
|
+
# Fields list for the DataTye
|
34
|
+
def members
|
35
|
+
@members ||=
|
36
|
+
begin
|
37
|
+
parent_members = superclass.instance_variable_get("@members")
|
38
|
+
parent_members ? parent_members.dup : {}
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Add Field to class variable hash and generate methods
|
43
|
+
# === Example
|
44
|
+
# add_member(:errorMessage, String) # Generate Code
|
45
|
+
# # attr_reader :errorMessage
|
46
|
+
# # alias_method :error_message, :errorMessage
|
47
|
+
# # alias_method :error_message=, :errorMessage=
|
48
|
+
def add_member(member_name, klass, options = {})
|
49
|
+
member_name = member_name.to_sym
|
50
|
+
members[member_name] = options.merge( :type => klass )
|
51
|
+
member_variable_name = "@#{member_name}"
|
52
|
+
define_method "#{member_name}=" do |value|
|
53
|
+
object = options[:array] ? convert_array(value, klass) : convert_object(value, klass)
|
54
|
+
instance_variable_set(member_variable_name, object)
|
55
|
+
end
|
56
|
+
default_value = ( options[:array] ? [] : ( klass < Base ? {} : nil ) )
|
57
|
+
define_method member_name do |&block|
|
58
|
+
value = instance_variable_get(member_variable_name) || ( default_value && send("#{member_name}=", default_value) )
|
59
|
+
value.instance_eval(&block) if block
|
60
|
+
value
|
61
|
+
end
|
62
|
+
define_alias_methods(member_name, options)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Define alias methods for getter and setter
|
66
|
+
def define_alias_methods(member_name, options)
|
67
|
+
snakecase_name = snakecase(member_name)
|
68
|
+
alias_method snakecase_name, member_name
|
69
|
+
alias_method "#{snakecase_name}=", "#{member_name}="
|
70
|
+
alias_method "#{options[:namespace]}:#{member_name}=", "#{member_name}=" if options[:namespace]
|
71
|
+
if options[:attribute]
|
72
|
+
alias_method "@#{member_name}=", "#{member_name}="
|
73
|
+
alias_method "@#{options[:namespace]}:#{member_name}=", "#{member_name}=" if options[:namespace]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# define method for given member and the class name
|
78
|
+
# === Example
|
79
|
+
# object_of(:errorMessage, ErrorMessage) # Generate Code
|
80
|
+
# # def errorMessage=(options)
|
81
|
+
# # @errorMessage = ErrorMessage.new(options)
|
82
|
+
# # end
|
83
|
+
# # add_member :errorMessage, ErrorMessage
|
84
|
+
def object_of(key, klass, options = {})
|
85
|
+
add_member(key, klass, options)
|
86
|
+
end
|
87
|
+
|
88
|
+
# define method for given member and the class name
|
89
|
+
# === Example
|
90
|
+
# array_of(:errorMessage, ErrorMessage) # It Generate below code
|
91
|
+
# # def errorMessage=(array)
|
92
|
+
# # @errorMessage = array.map{|options| ErrorMessage.new(options) }
|
93
|
+
# # end
|
94
|
+
# # add_member :errorMessage, ErrorMessage
|
95
|
+
def array_of(key, klass, options = {})
|
96
|
+
add_member(key, klass, options.merge(:array => true))
|
97
|
+
end
|
98
|
+
|
99
|
+
# Generate snakecase string.
|
100
|
+
# === Example
|
101
|
+
# snakecase("errorMessage")
|
102
|
+
# # error_message
|
103
|
+
def snakecase(string)
|
104
|
+
string.to_s.gsub(/([a-z])([A-Z])/, '\1_\2').gsub(/([A-Z])([A-Z][a-z])/, '\1_\2').downcase
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
# Initialize options.
|
110
|
+
def initialize(options = {}, &block)
|
111
|
+
if options.is_a? Hash
|
112
|
+
options.each do |key, value|
|
113
|
+
begin
|
114
|
+
send("#{key}=", value)
|
115
|
+
rescue TypeError, ArgumentError => error
|
116
|
+
raise TypeError, "#{error.message}(#{value.inspect}) for #{self.class.name}.#{key} member"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
elsif members[ContentKey]
|
120
|
+
self.value = options
|
121
|
+
else
|
122
|
+
raise ArgumentError, "invalid data(#{options.inspect}) for #{self.class.name} class"
|
123
|
+
end
|
124
|
+
self.instance_eval(&block) if block
|
125
|
+
end
|
126
|
+
|
127
|
+
# Create Array with default value.
|
128
|
+
class ArrayWithDefault < ::Array
|
129
|
+
def initialize(&block)
|
130
|
+
@block = block
|
131
|
+
super()
|
132
|
+
end
|
133
|
+
|
134
|
+
def [](key)
|
135
|
+
super(key) || send(:"[]=", key, nil)
|
136
|
+
end
|
137
|
+
|
138
|
+
def []=(key, value)
|
139
|
+
super(key, @block ? @block.call(value) : value )
|
140
|
+
end
|
141
|
+
|
142
|
+
def merge!(array)
|
143
|
+
if array.is_a? Array
|
144
|
+
array.each_with_index do |object, index|
|
145
|
+
self[index] = object
|
146
|
+
end
|
147
|
+
elsif array.is_a? Hash and array.keys.first.to_s =~ /^\d+$/
|
148
|
+
array.each do |key, object|
|
149
|
+
self[key.to_i] = object
|
150
|
+
end
|
151
|
+
else
|
152
|
+
self[0] = array
|
153
|
+
end
|
154
|
+
self
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# Create array of objects.
|
159
|
+
# === Example
|
160
|
+
# covert_array([{ :amount => "55", :code => "USD"}], CurrencyType)
|
161
|
+
# covert_array({ "0" => { :amount => "55", :code => "USD"} }, CurrencyType)
|
162
|
+
# covert_array({ :amount => "55", :code => "USD"}, CurrencyType)
|
163
|
+
# # @return
|
164
|
+
# # [ <CurrencyType#object @amount="55" @code="USD" > ]
|
165
|
+
def convert_array(array, klass)
|
166
|
+
default_value = ( klass < Base ? {} : nil )
|
167
|
+
data_type_array = ArrayWithDefault.new{|object| convert_object(object || default_value, klass) }
|
168
|
+
data_type_array.merge!(array)
|
169
|
+
end
|
170
|
+
|
171
|
+
# Create object based on given data.
|
172
|
+
# === Example
|
173
|
+
# covert_object({ :amount => "55", :code => "USD"}, CurrencyType )
|
174
|
+
# # @return
|
175
|
+
# # <CurrencyType#object @amount="55" @code="USD" >
|
176
|
+
def convert_object(object, klass)
|
177
|
+
object.is_a?(klass) ? object : ( ( object.nil? or object == "" ) ? nil : klass.new(object) )
|
178
|
+
end
|
179
|
+
|
180
|
+
# Alias instance method for the class method.
|
181
|
+
def members
|
182
|
+
self.class.members
|
183
|
+
end
|
184
|
+
|
185
|
+
# Get configured member names
|
186
|
+
def member_names
|
187
|
+
members.keys
|
188
|
+
end
|
189
|
+
|
190
|
+
# Create Hash based configured members
|
191
|
+
def to_hash(options = {})
|
192
|
+
options = HashOptions.merge(options)
|
193
|
+
hash = {}
|
194
|
+
member_names.each do |member|
|
195
|
+
value = value_to_hash(instance_variable_get("@#{member}"), options)
|
196
|
+
hash[hash_key(member, options)] = value unless skip_value?(value)
|
197
|
+
end
|
198
|
+
hash
|
199
|
+
end
|
200
|
+
|
201
|
+
# Skip nil, empty array and empty hash.
|
202
|
+
def skip_value?(value)
|
203
|
+
value.nil? || ( ( value.is_a?(Array) || value.is_a?(Hash) ) && value.empty? )
|
204
|
+
end
|
205
|
+
|
206
|
+
# Generate Hash key for given member name based on configuration
|
207
|
+
# === Example
|
208
|
+
# hash_key(:amount) # @return :"ebl:amount"
|
209
|
+
# hash_key(:type) # @return :"@type"
|
210
|
+
def hash_key(key, options = {})
|
211
|
+
unless key == ContentKey
|
212
|
+
member_option = members[key]
|
213
|
+
key = member_option[:name] if member_option.include? :name
|
214
|
+
key = "#{member_option[:namespace]}:#{key}" if member_option[:namespace] and options[:namespace]
|
215
|
+
key = "@#{key}" if member_option[:attribute] and options[:attribute]
|
216
|
+
end
|
217
|
+
options[:symbol] ? key.to_sym : key.to_s
|
218
|
+
end
|
219
|
+
|
220
|
+
# Covert the object to hash based on class.
|
221
|
+
def value_to_hash(value, options = {})
|
222
|
+
case value
|
223
|
+
when Array
|
224
|
+
value = value.map{|object| value_to_hash(object, options) }
|
225
|
+
value.delete_if{|v| skip_value?(v) }
|
226
|
+
value
|
227
|
+
when Base
|
228
|
+
value.to_hash(options)
|
229
|
+
else
|
230
|
+
value
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|