clickclient 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/History.txt +4 -0
- data/License.txt +57 -0
- data/README.txt +34 -0
- data/example/example_use_localserver.rb +202 -0
- data/lib/clickclient/common.rb +208 -0
- data/lib/clickclient/fx.rb +992 -0
- data/lib/clickclient/version.rb +9 -0
- data/lib/clickclient.rb +4 -0
- data/test/alltests.rb +6 -0
- data/test/connect_test_fx.rb +728 -0
- data/test/test_base.rb +61 -0
- data/test/test_helper.rb +2 -0
- metadata +69 -0
data/History.txt
ADDED
data/License.txt
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.co.jp>.
|
2
|
+
You can redistribute it and/or modify it under either the terms of the GPL,
|
3
|
+
or the conditions below:
|
4
|
+
|
5
|
+
1. You may make and give away verbatim copies of the source form of the
|
6
|
+
software without restriction, provided that you duplicate all of the
|
7
|
+
original copyright notices and associated disclaimers.
|
8
|
+
|
9
|
+
2. You may modify your copy of the software in any way, provided that
|
10
|
+
you do at least ONE of the following:
|
11
|
+
|
12
|
+
a) place your modifications in the Public Domain or otherwise
|
13
|
+
make them Freely Available, such as by posting said
|
14
|
+
modifications to Usenet or an equivalent medium, or by allowing
|
15
|
+
the author to include your modifications in the software.
|
16
|
+
|
17
|
+
b) use the modified software only within your corporation or
|
18
|
+
organization.
|
19
|
+
|
20
|
+
c) rename any non-standard executables so the names do not conflict
|
21
|
+
with standard executables, which must also be provided.
|
22
|
+
|
23
|
+
d) make other distribution arrangements with the author.
|
24
|
+
|
25
|
+
3. You may distribute the software in object code or executable
|
26
|
+
form, provided that you do at least ONE of the following:
|
27
|
+
|
28
|
+
a) distribute the executables and library files of the software,
|
29
|
+
together with instructions (in the manual page or equivalent)
|
30
|
+
on where to get the original distribution.
|
31
|
+
|
32
|
+
b) accompany the distribution with the machine-readable source of
|
33
|
+
the software.
|
34
|
+
|
35
|
+
c) give non-standard executables non-standard names, with
|
36
|
+
instructions on where to get the original software distribution.
|
37
|
+
|
38
|
+
d) make other distribution arrangements with the author.
|
39
|
+
|
40
|
+
4. You may modify and include the part of the software into any other
|
41
|
+
software (possibly commercial). But some files in the distribution
|
42
|
+
are not written by the author, so that they are not under this terms.
|
43
|
+
|
44
|
+
They are gc.c(partly), utils.c(partly), regex.[ch], st.[ch] and some
|
45
|
+
files under the ./missing directory. See each file for the copying
|
46
|
+
condition.
|
47
|
+
|
48
|
+
5. The scripts and library files supplied as input to or produced as
|
49
|
+
output from the software do not automatically fall under the
|
50
|
+
copyright of the software, but belong to whomever generated them,
|
51
|
+
and may be sold commercially, and may be aggregated with this
|
52
|
+
software.
|
53
|
+
|
54
|
+
6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
55
|
+
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
56
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
57
|
+
PURPOSE.
|
data/README.txt
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
= CLICK Client -- CLICK Securities Web Service Client Library for Ruby.
|
2
|
+
|
3
|
+
CLICK Client is a CLICK Securities Web Service Client for Ruby.
|
4
|
+
CLICK Client はクリック証券Webサービスにアクセスするためのクライアントライブラリです。
|
5
|
+
以下の機能を提供します。
|
6
|
+
|
7
|
+
* 外為証拠金取引(FX)取引
|
8
|
+
|
9
|
+
|
10
|
+
== Dounload
|
11
|
+
|
12
|
+
CLICK Clientの最新バージョンは以下のサイトからダウンロードできます。
|
13
|
+
|
14
|
+
* http://rubyforge.org/projects/clickclient
|
15
|
+
|
16
|
+
|
17
|
+
== Installation
|
18
|
+
|
19
|
+
rubygemを使ってインストール可能です。なお、依存もジュールとして「httpclient」も必要となります。
|
20
|
+
以下のコマンドを実行してインストールしてください。
|
21
|
+
|
22
|
+
% [sudo] gem install httpclient --source http://dev.ctor.org/download/
|
23
|
+
% [sudo] gem install clickclient
|
24
|
+
|
25
|
+
|
26
|
+
== License
|
27
|
+
|
28
|
+
Ruby ライセンスに準拠
|
29
|
+
|
30
|
+
|
31
|
+
== Disclaimer
|
32
|
+
* 本ライブラリの利用は自己責任でお願いします。
|
33
|
+
* ライブラリの不備・不具合等によるあらゆる損害について、作成者は責任を負いません。
|
34
|
+
|
@@ -0,0 +1,202 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../lib/clickclient'
|
2
|
+
|
3
|
+
require 'kconv'
|
4
|
+
|
5
|
+
#== 利用サンプル
|
6
|
+
#ローカルサーバーに接続し、結果を表示します。
|
7
|
+
c = ClickClient::Client.new
|
8
|
+
|
9
|
+
# ローカルサーバーへの接続設定
|
10
|
+
c.host_name = "http://localhost:8000"
|
11
|
+
c.fx_path = "/webservice/ws-redirect"
|
12
|
+
c.fx_session( "012345678", "sdfsdf" ) { | fx_session |
|
13
|
+
|
14
|
+
# 通貨ペア一覧取得
|
15
|
+
# 引数で取得する通貨ペアコードを配列で指定
|
16
|
+
# 指定しない場合すべての通貨ペアの情報を取得。
|
17
|
+
puts "\n--- list_currency_pairs"
|
18
|
+
list = fx_session.list_currency_pairs [GMO::FX::USDJPY, GMO::FX::EURJPY]
|
19
|
+
list.each{ |currency_pair_code, value| puts value }
|
20
|
+
|
21
|
+
# レート一覧取得
|
22
|
+
puts "\n--- list_rates"
|
23
|
+
list = fx_session.list_rates
|
24
|
+
list.each{ |currency_pair_code, value| puts value }
|
25
|
+
|
26
|
+
# 成り行き注文
|
27
|
+
puts "\n--- order - buy"
|
28
|
+
puts fx_session.order( GMO::FX::USDJPY, GMO::FX::BUY, 2 )
|
29
|
+
puts "\n--- order - sell"
|
30
|
+
result = fx_session.order( GMO::FX::USDJPY, GMO::FX::SELL, 1, {
|
31
|
+
:slippage=>99,
|
32
|
+
:slippage_base_rate=>list[GMO::FX::USDJPY].bid_rate
|
33
|
+
})
|
34
|
+
puts result
|
35
|
+
|
36
|
+
# 成り行き決済注文
|
37
|
+
puts "\n--- settle"
|
38
|
+
puts fx_session.settle( result.order_no, 1 )
|
39
|
+
puts fx_session.settle( result.order_no, 2, {
|
40
|
+
:slippage=>99,
|
41
|
+
:slippage_base_rate=>list[GMO::FX::USDJPY].bid_rate
|
42
|
+
})
|
43
|
+
|
44
|
+
# 通常注文
|
45
|
+
puts "\n--- order - basic sell"
|
46
|
+
result = fx_session.order( GMO::FX::USDJPY, GMO::FX::SELL, 1, {
|
47
|
+
:rate=>145.19,
|
48
|
+
:execution_expression=>GMO::FX::EXECUTION_EXPRESSION_LIMIT_ORDER,
|
49
|
+
:expiration_type=>GMO::FX::EXPIRATION_TYPE_SPECIFIED,
|
50
|
+
:expiration_date=>DateTime.new( 2007, 11, 5, 0 )
|
51
|
+
})
|
52
|
+
puts result
|
53
|
+
|
54
|
+
# 注文変更
|
55
|
+
puts "\n--- edit_order"
|
56
|
+
fx_session.edit_order( result.order_no, {
|
57
|
+
:rate=>145.19,
|
58
|
+
:expiration_type=>GMO::FX::EXPIRATION_TYPE_TODAY
|
59
|
+
})
|
60
|
+
|
61
|
+
# 注文取消し
|
62
|
+
puts "\n--- cancel_order"
|
63
|
+
fx_session.cancel_order( result.order_no )
|
64
|
+
|
65
|
+
# 通常決済注文
|
66
|
+
puts "\n--- settle - basic"
|
67
|
+
result = fx_session.order( GMO::FX::USDJPY, GMO::FX::SELL, 2, {
|
68
|
+
:rate=>145.19,
|
69
|
+
:execution_expression=>GMO::FX::EXECUTION_EXPRESSION_LIMIT_ORDER,
|
70
|
+
:expiration_type=>GMO::FX::EXPIRATION_TYPE_TODAY
|
71
|
+
})
|
72
|
+
puts fx_session.settle( result.order_no, 2, {
|
73
|
+
:rate=>146.20,
|
74
|
+
:execution_expression=>GMO::FX::EXECUTION_EXPRESSION_LIMIT_ORDER,
|
75
|
+
:expiration_type=>GMO::FX::EXPIRATION_TYPE_SPECIFIED,
|
76
|
+
:expiration_date=>DateTime.new( 2007, 11, 5, 0 )
|
77
|
+
})
|
78
|
+
|
79
|
+
# OCO注文
|
80
|
+
puts "\n--- order - oco"
|
81
|
+
result = fx_session.order( GMO::FX::USDJPY, GMO::FX::SELL, 1, {
|
82
|
+
:rate=>145.19,
|
83
|
+
:stop_order_rate=>144.19,
|
84
|
+
:expiration_type=>GMO::FX::EXPIRATION_TYPE_SPECIFIED,
|
85
|
+
:expiration_date=>DateTime.new( 2007, 11, 5, 0 )
|
86
|
+
})
|
87
|
+
puts result
|
88
|
+
|
89
|
+
# OCO注文変更
|
90
|
+
puts "\n--- edit - oco"
|
91
|
+
fx_session.edit_order( result.limit_order_no, {
|
92
|
+
:stop_order_no=>result.stop_order_no,
|
93
|
+
:rate=>145.29,
|
94
|
+
:stop_order_rate=>144.29,
|
95
|
+
:expiration_type=>GMO::FX::EXPIRATION_TYPE_SPECIFIED,
|
96
|
+
:expiration_date=>DateTime.new( 2007, 11, 6, 0 )
|
97
|
+
})
|
98
|
+
|
99
|
+
# OCO決済注文
|
100
|
+
puts "\n--- settle - oco"
|
101
|
+
puts fx_session.settle( result.limit_order_no, 2, {
|
102
|
+
:rate=>146.20,
|
103
|
+
:stop_order_rate=>144.19,
|
104
|
+
:execution_expression=>GMO::FX::EXECUTION_EXPRESSION_LIMIT_ORDER,
|
105
|
+
:expiration_type=>GMO::FX::EXPIRATION_TYPE_SPECIFIED,
|
106
|
+
:expiration_date=>DateTime.new( 2007, 11, 5, 0 )
|
107
|
+
})
|
108
|
+
|
109
|
+
# IFD取引
|
110
|
+
puts "\n--- order - ifd"
|
111
|
+
result = fx_session.order( GMO::FX::USDJPY, GMO::FX::SELL, 1, {
|
112
|
+
:rate=>145.19,
|
113
|
+
:execution_expression=>GMO::FX::EXECUTION_EXPRESSION_LIMIT_ORDER,
|
114
|
+
:expiration_type=>GMO::FX::EXPIRATION_TYPE_SPECIFIED,
|
115
|
+
:expiration_date=>DateTime.new( 2007, 11, 5, 0 ),
|
116
|
+
:settle=>{
|
117
|
+
:unit=>1,
|
118
|
+
:sell_or_buy=>GMO::FX::BUY,
|
119
|
+
:rate=>145.91,
|
120
|
+
:execution_expression=>GMO::FX::EXECUTION_EXPRESSION_LIMIT_ORDER,
|
121
|
+
:expiration_type=>GMO::FX::EXPIRATION_TYPE_SPECIFIED,
|
122
|
+
:expiration_date=>DateTime.new( 2007, 11, 5, 0 ),
|
123
|
+
}
|
124
|
+
})
|
125
|
+
puts result
|
126
|
+
|
127
|
+
# IFD注文変更
|
128
|
+
puts "\n--- edit - ifd"
|
129
|
+
fx_session.edit_order( result.order_no, {
|
130
|
+
:rate=>145.29,
|
131
|
+
:expiration_type=>GMO::FX::EXPIRATION_TYPE_TODAY,
|
132
|
+
:settle=>{
|
133
|
+
:order_no=>result.settlement_order_no,
|
134
|
+
:rate=>145.91,
|
135
|
+
:expiration_type=>GMO::FX::EXPIRATION_TYPE_SPECIFIED,
|
136
|
+
:expiration_date=>DateTime.new( 2007, 11, 6, 0 ),
|
137
|
+
}
|
138
|
+
})
|
139
|
+
|
140
|
+
# IFD-OCO取引
|
141
|
+
puts "\n--- order - ifd-oco"
|
142
|
+
result = fx_session.order( GMO::FX::USDJPY, GMO::FX::SELL, 1, {
|
143
|
+
:rate=>145.19,
|
144
|
+
:execution_expression=>GMO::FX::EXECUTION_EXPRESSION_LIMIT_ORDER,
|
145
|
+
:expiration_type=>GMO::FX::EXPIRATION_TYPE_TODAY,
|
146
|
+
:settle=>{
|
147
|
+
:unit=>1,
|
148
|
+
:sell_or_buy=>GMO::FX::BUY,
|
149
|
+
:rate=>145.91,
|
150
|
+
:stop_order_rate=>144.15,
|
151
|
+
:execution_expression=>GMO::FX::EXECUTION_EXPRESSION_LIMIT_ORDER,
|
152
|
+
:expiration_type=>GMO::FX::EXPIRATION_TYPE_SPECIFIED,
|
153
|
+
:expiration_date=>DateTime.new( 2007, 11, 5, 0 ),
|
154
|
+
}
|
155
|
+
})
|
156
|
+
puts result
|
157
|
+
|
158
|
+
# IFD-OCO注文変更
|
159
|
+
puts "\n--- edit - ifd-oco"
|
160
|
+
fx_session.edit_order( result.order_no, {
|
161
|
+
:rate=>145.29,
|
162
|
+
:expiration_type=>GMO::FX::EXPIRATION_TYPE_SPECIFIED,
|
163
|
+
:expiration_date=>DateTime.new( 2007, 11, 6, 0 ),
|
164
|
+
:settle=>{
|
165
|
+
:order_no=>result.kessaiSashineChumonBango,
|
166
|
+
:stop_order_no=>result.kessaiGyakusashiChumonBango,
|
167
|
+
:rate=>145.21,
|
168
|
+
:stop_order_rate=>144.15,
|
169
|
+
:expiration_type=>GMO::FX::EXPIRATION_TYPE_SPECIFIED,
|
170
|
+
:expiration_date=>DateTime.new( 2007, 11, 6, 0 ),
|
171
|
+
}
|
172
|
+
})
|
173
|
+
|
174
|
+
# 注文一覧取得
|
175
|
+
# 引数で、注文状態コード(必須)、通貨ペアコード、注文日期間開始日、注文日期間終了日を指定可能。
|
176
|
+
puts "\n--- list_orders"
|
177
|
+
list = fx_session.list_orders GMO::FX::ORDER_CONDITION_ALL, GMO::FX::EURJPY, Date.new( 2007, 10, 1 ), Date.new( 2007, 11, 1 )
|
178
|
+
list.each{ |item| puts item }
|
179
|
+
|
180
|
+
# 建玉一覧取得
|
181
|
+
# 引数で、通貨ペアコードを指定可能。(省略可)
|
182
|
+
puts "\n--- list_open_interests"
|
183
|
+
list = fx_session.list_open_interests( GMO::FX::EURJPY )
|
184
|
+
list.each{ |item| puts item }
|
185
|
+
|
186
|
+
# 約定一覧取得
|
187
|
+
# 引数で、取得期間(開始日,終了日)(必須)、通貨ペアコード、取引タイプ(新規Or決済)を指定可能。
|
188
|
+
puts "\n--- list_execution_results"
|
189
|
+
list = fx_session.list_execution_results( Date.new( 2007, 10, 1 ), Date.new( 2007, 11, 1 ) )
|
190
|
+
list.each{ |item| puts item }
|
191
|
+
list = fx_session.list_execution_results( Date.new( 2007, 10, 1 ), Date.new( 2007, 11, 1 ), GMO::FX::TRADE_TYPE_NEW, GMO::FX::EURJPY )
|
192
|
+
list.each{ |item| puts item }
|
193
|
+
|
194
|
+
# 余力情報の取得
|
195
|
+
puts "\n--- get_margin"
|
196
|
+
puts fx_session.get_margin
|
197
|
+
|
198
|
+
# お知らせ一覧取得
|
199
|
+
puts "\n--- list_messages"
|
200
|
+
list = fx_session.list_messages
|
201
|
+
list.each{ |item| puts item.to_s.tosjis }
|
202
|
+
}
|
@@ -0,0 +1,208 @@
|
|
1
|
+
begin
|
2
|
+
require 'rubygems'
|
3
|
+
rescue LoadError
|
4
|
+
end
|
5
|
+
require 'httpclient'
|
6
|
+
require 'rexml/document'
|
7
|
+
require 'date'
|
8
|
+
|
9
|
+
#
|
10
|
+
#=== クリック証券アクセスクライアント
|
11
|
+
#
|
12
|
+
#*Version*:: 0.0.1
|
13
|
+
#*License*:: Ruby ライセンスに準拠
|
14
|
+
#
|
15
|
+
#クリック証券Webサービスを利用するためのクライアントライブラリです。以下の機能を提供します。
|
16
|
+
#- 外為証拠金取引(FX)取引
|
17
|
+
#
|
18
|
+
#====依存モジュール
|
19
|
+
#「{httpclient}[http://dev.ctor.org/http-access2]」を利用しています。以下のコマンドを実行してインストールしてください。
|
20
|
+
#
|
21
|
+
# gem install httpclient --source http://dev.ctor.org/download/
|
22
|
+
#
|
23
|
+
#====基本的な使い方
|
24
|
+
#
|
25
|
+
# require 'clickclient'
|
26
|
+
#
|
27
|
+
# c = ClickClient::Client.new
|
28
|
+
# # c = ClickClient::Client.new https://<プロキシホスト>:<プロキシポート> # プロキシを利用する場合
|
29
|
+
# c.fx_session( "<ユーザー名>", "<パスワード>" ) { | fx_session |
|
30
|
+
# # 通貨ペア一覧取得
|
31
|
+
# list = fx_session.list_currency_pairs
|
32
|
+
# puts list
|
33
|
+
# }
|
34
|
+
#なお、ご利用にあたっては「{クリック証券Webサービス利用規約}[https://sec.gmo.jp/corp/guide/regulations/pdf/reg_webservice.pdf]
|
35
|
+
#」(PDF)に同意して頂く必要があります。
|
36
|
+
#
|
37
|
+
#====免責
|
38
|
+
#- 本ライブラリの利用は自己責任でお願いします。
|
39
|
+
#- ライブラリの不備・不具合等によるあらゆる損害について、作成者は責任を負いません。
|
40
|
+
#
|
41
|
+
module ClickClient
|
42
|
+
|
43
|
+
# クライアント
|
44
|
+
class Client
|
45
|
+
|
46
|
+
# ホスト名
|
47
|
+
DEFAULT_HOST_NAME = "https://sec-sso.gmo.jp"
|
48
|
+
|
49
|
+
#
|
50
|
+
#===コンストラクタ
|
51
|
+
#
|
52
|
+
#*proxy*:: プロキシホストを利用する場合、そのホスト名とパスを指定します。
|
53
|
+
# 例) https://proxyhost.com:80
|
54
|
+
#
|
55
|
+
def initialize( proxy=nil )
|
56
|
+
@client = HTTPClient.new( proxy, "ClickClientLib")
|
57
|
+
@client.set_cookie_store("cookie.dat")
|
58
|
+
@host_name = DEFAULT_HOST_NAME
|
59
|
+
end
|
60
|
+
|
61
|
+
#ホスト名
|
62
|
+
attr :host_name, true
|
63
|
+
|
64
|
+
private
|
65
|
+
# ログインしてブロックを実行する。ブロックの実行後ログアウトする。
|
66
|
+
def session( uri, userid, password, &block )
|
67
|
+
|
68
|
+
# sequence 1
|
69
|
+
result = @client.post(uri, "u=" << userid )
|
70
|
+
seq2_uri = result.header["Location"].to_s
|
71
|
+
raise "fail session-1.responce=" << result.content if seq2_uri == nil || seq2_uri.length <= 0
|
72
|
+
|
73
|
+
# sequence 2
|
74
|
+
result = @client.get( seq2_uri )
|
75
|
+
doc = REXML::Document.new(result.content)
|
76
|
+
unless ( doc.text( "./loginResponse/responseStatus" ) =~ /OK/ )
|
77
|
+
raise "fail session-2." << doc.text( "./loginResponse/message" )
|
78
|
+
end
|
79
|
+
|
80
|
+
# sequence 3
|
81
|
+
base_uri = File.dirname( seq2_uri )
|
82
|
+
result = @client.post( base_uri + "/ws-login", "j_username=#{userid}&j_password=#{password}" )
|
83
|
+
seq4_uri = result.header["Location"]
|
84
|
+
if ( seq4_uri == nil || seq4_uri.length <= 0 )
|
85
|
+
doc = REXML::Document.new(result.content)
|
86
|
+
raise "fail session-3." << doc.text( "./loginResponse/message" )
|
87
|
+
end
|
88
|
+
|
89
|
+
# sequence 4
|
90
|
+
# responseStatusがOKになるまでリダイレクトが続く。
|
91
|
+
while ( true )
|
92
|
+
result = @client.get( seq4_uri )
|
93
|
+
doc = REXML::Document.new(result.content)
|
94
|
+
if ( doc.text( "./loginResponse/responseStatus" ) =~ /OK/ )
|
95
|
+
break
|
96
|
+
else
|
97
|
+
seq4_uri = result.header["Location"]
|
98
|
+
raise "fail session-4.responce=" << result.content if seq4_uri == nil || seq4_uri.length <= 0
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
begin
|
103
|
+
block.call( @client, base_uri )
|
104
|
+
ensure
|
105
|
+
# logout
|
106
|
+
result = @client.post( base_uri + "/ws-logout" )
|
107
|
+
doc = REXML::Document.new(result.content)
|
108
|
+
unless ( doc.text( "./logoutResponse/responseStatus" ) =~ /OK/ )
|
109
|
+
raise "fail session-5." << doc.text( "./logoutResponse/message" )
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
#
|
119
|
+
#=== 結果オブジェクトの抽象基底クラス。
|
120
|
+
#
|
121
|
+
class Base #:nodoc:
|
122
|
+
def initialize( item )
|
123
|
+
# 属性と子要素の値を、オブジェクトの属性として格納する。
|
124
|
+
item.attributes.each { |name, value|
|
125
|
+
set_attribute(name.to_s ,value)
|
126
|
+
}
|
127
|
+
item.elements.each { |elm|
|
128
|
+
if ( elm.name != "responseStatus" && elm.name != "message" )
|
129
|
+
set_attribute(elm.name.to_s, elm.text)
|
130
|
+
end
|
131
|
+
}
|
132
|
+
end
|
133
|
+
def to_s
|
134
|
+
str = ""
|
135
|
+
instance_variables.each { |name|
|
136
|
+
str += name + "=" + instance_variable_get(name).to_s + ", "
|
137
|
+
}
|
138
|
+
return str.chop.chop
|
139
|
+
end
|
140
|
+
def method_missing( name, *args )
|
141
|
+
if name.to_s =~ /(.*?)=/
|
142
|
+
name = $1
|
143
|
+
setter = true
|
144
|
+
end
|
145
|
+
|
146
|
+
# 同名の属性があればそれのReaderと見なし、属性値を返す。
|
147
|
+
value = instance_variable_get("@" << name.to_s)
|
148
|
+
unless ( value == nil )
|
149
|
+
if setter
|
150
|
+
instance_variable_set( "@" << name, args[0] )
|
151
|
+
else
|
152
|
+
return value
|
153
|
+
end
|
154
|
+
else
|
155
|
+
super(name)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
def hash
|
159
|
+
hash = 0
|
160
|
+
values.each {|v|
|
161
|
+
hash = v.hash + 31 * hash
|
162
|
+
}
|
163
|
+
return hash
|
164
|
+
end
|
165
|
+
def eql?(other)
|
166
|
+
return false if other == nil
|
167
|
+
return false unless other.is_a?( Base )
|
168
|
+
a = values
|
169
|
+
b = other.values
|
170
|
+
return false if a.length != b.length
|
171
|
+
a.length.times{|i|
|
172
|
+
return false unless a[i].eql? b[i]
|
173
|
+
}
|
174
|
+
return true
|
175
|
+
end
|
176
|
+
protected
|
177
|
+
def values
|
178
|
+
values = []
|
179
|
+
instance_variables.each { |name|
|
180
|
+
values << instance_variable_get(name)
|
181
|
+
}
|
182
|
+
return values
|
183
|
+
end
|
184
|
+
private
|
185
|
+
def set_attribute(name ,value)
|
186
|
+
if ( value =~ /^\d+$/)
|
187
|
+
value = value.to_i
|
188
|
+
elsif ( value =~ /^[\d\.]+$/)
|
189
|
+
value = value.to_f
|
190
|
+
elsif ( value =~ /^\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2}$/)
|
191
|
+
value = DateTime.strptime( value, "%Y-%m-%d %H:%M:%S")
|
192
|
+
elsif ( value =~ /^\d{4}-\d{2}-\d{2}$/)
|
193
|
+
value = DateTime.strptime( value, "%Y-%m-%d")
|
194
|
+
end
|
195
|
+
instance_variable_set( "@" << name, value )
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
# 結果を解析し、エラーであれば例外をスローする。
|
200
|
+
def self.parse( content )
|
201
|
+
doc = REXML::Document.new( content )
|
202
|
+
unless ( doc.text( "./*/responseStatus" ) =~ /OK/ )
|
203
|
+
raise "fail." << doc.text( "./*/message" )
|
204
|
+
end
|
205
|
+
return doc
|
206
|
+
end
|
207
|
+
|
208
|
+
end
|