when_exe 0.3.6 → 0.3.7
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.
- checksums.yaml +7 -0
- data/README.md +171 -0
- data/lib/when_exe.rb +78 -47
- data/lib/when_exe/basictypes.rb +752 -747
- data/lib/when_exe/calendarnote.rb +805 -801
- data/lib/when_exe/calendartypes.rb +1583 -1531
- data/lib/when_exe/coordinates.rb +16 -15
- data/lib/when_exe/core/duration.rb +114 -110
- data/lib/when_exe/core/extension.rb +504 -504
- data/lib/when_exe/ephemeris.rb +1917 -1913
- data/lib/when_exe/ephemeris/moon.rb +333 -333
- data/lib/when_exe/ephemeris/notes.rb +389 -387
- data/lib/when_exe/ephemeris/planets.rb +585 -585
- data/lib/when_exe/ephemeris/sun.rb +214 -214
- data/lib/when_exe/googlecalendar.rb +144 -140
- data/lib/when_exe/icalendar.rb +1636 -1636
- data/lib/when_exe/inspect.rb +46 -22
- data/lib/when_exe/locales/akt.rb +176 -176
- data/lib/when_exe/locales/encoding_conversion.rb +134 -126
- data/lib/when_exe/locales/iast.rb +90 -90
- data/lib/when_exe/locales/locale.rb +750 -746
- data/lib/when_exe/locales/transliteration_table.rb +62 -62
- data/lib/when_exe/mini_application.rb +307 -305
- data/lib/when_exe/parts/enumerator.rb +2 -2
- data/lib/when_exe/parts/geometric_complex.rb +397 -397
- data/lib/when_exe/parts/method_cash.rb +224 -224
- data/lib/when_exe/parts/resource.rb +1069 -1071
- data/lib/when_exe/parts/timezone.rb +240 -230
- data/lib/when_exe/region/armenian.rb +56 -56
- data/lib/when_exe/region/babylonian.rb +405 -0
- data/lib/when_exe/region/bahai.rb +146 -146
- data/lib/when_exe/region/balinese.rb +622 -622
- data/lib/when_exe/region/chinese.rb +95 -25
- data/lib/when_exe/region/chinese/calendars.rb +1016 -1016
- data/lib/when_exe/region/chinese/epochs.rb +1 -1
- data/lib/when_exe/region/chinese/twins.rb +803 -795
- data/lib/when_exe/region/christian.rb +824 -824
- data/lib/when_exe/region/coptic.rb +106 -87
- data/lib/when_exe/region/discordian.rb +225 -225
- data/lib/when_exe/region/far_east.rb +188 -188
- data/lib/when_exe/region/french.rb +56 -56
- data/lib/when_exe/region/geologicalage.rb +639 -639
- data/lib/when_exe/region/goddess.rb +58 -58
- data/lib/when_exe/region/indian.rb +1254 -1251
- data/lib/when_exe/region/iranian.rb +8 -8
- data/lib/when_exe/region/islamic.rb +3 -3
- data/lib/when_exe/region/japanese.rb +93 -99
- data/lib/when_exe/region/japanese/calendars.rb +396 -397
- data/lib/when_exe/region/japanese/epochs.rb +26 -26
- data/lib/when_exe/region/japanese/nihon_shoki.rb +71 -71
- data/lib/when_exe/region/japanese/notes.rb +1383 -1386
- data/lib/when_exe/region/japanese/residues.rb +1306 -1306
- data/lib/when_exe/region/japanese/twins.rb +225 -225
- data/lib/when_exe/region/japanese/weeks.rb +112 -0
- data/lib/when_exe/region/javanese.rb +230 -230
- data/lib/when_exe/region/jewish.rb +126 -126
- data/lib/when_exe/region/korean.rb +378 -378
- data/lib/when_exe/region/m17n.rb +114 -113
- data/lib/when_exe/region/martian.rb +258 -255
- data/lib/when_exe/region/mayan.rb +32 -32
- data/lib/when_exe/region/residue.rb +89 -89
- data/lib/when_exe/region/roman.rb +36 -24
- data/lib/when_exe/region/ryukyu.rb +97 -97
- data/lib/when_exe/region/shire.rb +240 -240
- data/lib/when_exe/region/soviet.rb +209 -0
- data/lib/when_exe/region/symmetry.rb +50 -50
- data/lib/when_exe/region/thai.rb +336 -335
- data/lib/when_exe/region/tibetan.rb +316 -315
- data/lib/when_exe/region/vietnamese.rb +440 -439
- data/lib/when_exe/region/weekdate.rb +80 -80
- data/lib/when_exe/region/world.rb +175 -175
- data/lib/when_exe/region/yerm.rb +14 -14
- data/lib/when_exe/region/zoroastrian.rb +203 -203
- data/lib/when_exe/timestandard.rb +707 -681
- data/lib/when_exe/tmduration.rb +338 -330
- data/lib/when_exe/tmobjects.rb +1346 -1325
- data/lib/when_exe/tmposition.rb +2115 -2072
- data/lib/when_exe/tmreference.rb +1693 -1669
- data/lib/when_exe/version.rb +1 -1
- data/link_to_online_documents +1 -1
- data/test/examples/JapanHolidaysRFC6350.ics +1 -1
- data/test/test.rb +67 -61
- data/test/test/basictypes.rb +409 -409
- data/test/test/calendarnote.rb +86 -69
- data/test/test/calendartypes.rb +97 -97
- data/test/test/coordinates.rb +396 -396
- data/test/test/ephemeris.rb +83 -74
- data/test/test/ephemeris/moon.rb +14 -14
- data/test/test/ephemeris/planets.rb +14 -14
- data/test/test/ephemeris/sun.rb +14 -14
- data/test/test/googlecalendar.rb +194 -176
- data/test/test/icalendar.rb +867 -858
- data/test/test/inspect.rb +117 -117
- data/test/test/parts.rb +487 -487
- data/test/test/region/balinese.rb +34 -0
- data/test/test/region/chinese.rb +218 -206
- data/test/test/region/christian.rb +245 -245
- data/test/test/region/coptic.rb +27 -27
- data/test/test/region/french.rb +33 -33
- data/test/test/region/geologicalage.rb +17 -17
- data/test/test/region/indian.rb +57 -57
- data/test/test/region/iran.rb +54 -54
- data/test/test/region/islamic.rb +18 -18
- data/test/test/region/japanese.rb +237 -219
- data/test/test/region/jewish.rb +61 -61
- data/test/test/region/m17n.rb +184 -184
- data/test/test/region/mayan.rb +195 -195
- data/test/test/region/residue.rb +147 -139
- data/test/test/region/thai.rb +116 -116
- data/test/test/region/tibetan.rb +30 -30
- data/test/test/region/vietnamese.rb +102 -102
- data/test/test/region/yerm.rb +146 -146
- data/test/test/timestandard.rb +81 -81
- data/test/test/tmobjects.rb +328 -328
- data/test/test/tmposition.rb +397 -284
- data/test/test/tmreference.rb +157 -157
- metadata +13 -10
|
@@ -1,224 +1,224 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
=begin
|
|
3
|
-
Copyright (C) 2011-2014 Takashi SUGA
|
|
4
|
-
|
|
5
|
-
You may use and/or modify this file according to the license described in the LICENSE.txt file included in this archive.
|
|
6
|
-
=end
|
|
7
|
-
|
|
8
|
-
module When
|
|
9
|
-
#
|
|
10
|
-
# 本ライブラリのための諸々の部品
|
|
11
|
-
#
|
|
12
|
-
module Parts
|
|
13
|
-
|
|
14
|
-
#
|
|
15
|
-
# == メソッドの実行結果をキャッシュし処理の高速化を行う
|
|
16
|
-
#
|
|
17
|
-
# === fn というメソッドをキャッシュ化
|
|
18
|
-
# * fn ではなく fn_ を定義しておく
|
|
19
|
-
# * fn メソッドが呼ばれると fn_ を実行し、{引数=>戻り値} を Hash に記憶する
|
|
20
|
-
# * 同じ引数で再度 fn メソッドが呼ばれると Hash から戻り値を取り出して返す
|
|
21
|
-
#
|
|
22
|
-
# === a_to_b と b_to_a という互いに逆関数のメソッドをキャッシュ化
|
|
23
|
-
# * a_to_b ではなく a_to_b_ , b_to_a ではなく b_to_a_ を定義しておく
|
|
24
|
-
# * a_to_b メソッドが呼ばれると a_to_b_ を実行し、{引数=>戻り値}, {戻り値=>引数}を Hash に記憶する
|
|
25
|
-
# * 同じ引数で再度 a_to_b メソッドが呼ばれると Hash から戻り値を取り出して返す
|
|
26
|
-
# * b_to_a メソッドが呼ばれ Hash に戻り値があれば Hash から戻り値を取り出して返す
|
|
27
|
-
#
|
|
28
|
-
# == 特記事項
|
|
29
|
-
#
|
|
30
|
-
# === Argument identification
|
|
31
|
-
# The eql? method of When::TM::(Temporal)Position is not overridden.
|
|
32
|
-
# It seems that the cost of identification of the argument exceeds the merit of the method cash.
|
|
33
|
-
# I do not recommend applying the methodcash to the method which takes
|
|
34
|
-
# When::TM::(Temporal)Position as an argument.
|
|
35
|
-
#
|
|
36
|
-
# === Multi-thread critical situation
|
|
37
|
-
# There is a problem in consistency of hash when this function is used in multi-thread environment.
|
|
38
|
-
# If the initialize method sets Mutex in instance variable @_m_cash_lock_,
|
|
39
|
-
# this function gives up use of hash in the critical situation.
|
|
40
|
-
#
|
|
41
|
-
# class Foo
|
|
42
|
-
# include MethodCash
|
|
43
|
-
#
|
|
44
|
-
# def initialize
|
|
45
|
-
# ...
|
|
46
|
-
# @_m_cash_lock_ = Mutex.new
|
|
47
|
-
# ...
|
|
48
|
-
# end
|
|
49
|
-
# end
|
|
50
|
-
#
|
|
51
|
-
# 参考 http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/47663
|
|
52
|
-
#
|
|
53
|
-
module MethodCash
|
|
54
|
-
|
|
55
|
-
# @private
|
|
56
|
-
Escape = {:to_str => true,
|
|
57
|
-
:to_ary => true,
|
|
58
|
-
:to_hash => true}
|
|
59
|
-
|
|
60
|
-
class << self
|
|
61
|
-
|
|
62
|
-
# '_' で終わるメソッドをキャッシュせずに毎回計算するか否か
|
|
63
|
-
#
|
|
64
|
-
# @return [Boolean] キャッシュしない true, キャッシュする false/nil
|
|
65
|
-
#
|
|
66
|
-
attr_accessor :direct
|
|
67
|
-
|
|
68
|
-
# When::Parts::MethodCash のグローバルな設定を行う
|
|
69
|
-
#
|
|
70
|
-
# @param [Hash] options 以下の通り
|
|
71
|
-
# @option options [Boolean] :direct '_' で終わるメソッドをキャッシュせずに毎回計算するか否か
|
|
72
|
-
# @option options [Hash{Symbol=>boolean}] :escape 毎回 method_missing を発生させるメソッドを true にする
|
|
73
|
-
# @option options [false, nil] :escape to_str, to_ary, to_hash のみ毎回 method_missing を発生させる
|
|
74
|
-
# @option options [true] :escape すべて毎回 method_missing を発生させる
|
|
75
|
-
#
|
|
76
|
-
# @return [void]
|
|
77
|
-
#
|
|
78
|
-
# @note When::TM::Calendar クラスの一部はキャッシュ使用を前提としているため :direct=>true では動作しません
|
|
79
|
-
#
|
|
80
|
-
def _setup_(options={})
|
|
81
|
-
@_setup_info = options
|
|
82
|
-
@direct = options[:direct]
|
|
83
|
-
case options[:escape]
|
|
84
|
-
when true
|
|
85
|
-
instance_eval %Q{
|
|
86
|
-
def escape(method)
|
|
87
|
-
true
|
|
88
|
-
end
|
|
89
|
-
}
|
|
90
|
-
when Hash
|
|
91
|
-
@escape = Escape.merge(options[:escape])
|
|
92
|
-
instance_eval %Q{
|
|
93
|
-
def escape(method)
|
|
94
|
-
@escape[method]
|
|
95
|
-
end
|
|
96
|
-
}
|
|
97
|
-
else
|
|
98
|
-
instance_eval %Q{
|
|
99
|
-
def escape(method)
|
|
100
|
-
Escape.key?(method)
|
|
101
|
-
end
|
|
102
|
-
}
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
# 設定情報を取得する
|
|
107
|
-
#
|
|
108
|
-
# @return [Hash] 設定情報
|
|
109
|
-
#
|
|
110
|
-
def _setup_info
|
|
111
|
-
@_setup_info ||= {}
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
# method_missing メソッドを forward するか否か
|
|
115
|
-
#
|
|
116
|
-
# @param [Symbol] method メソッドシンボル
|
|
117
|
-
#
|
|
118
|
-
# @return [boolean] true - しない, false/nil - する
|
|
119
|
-
#
|
|
120
|
-
def escape(method)
|
|
121
|
-
Escape.key?(method)
|
|
122
|
-
end
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
alias :method_missing_ :method_missing
|
|
126
|
-
|
|
127
|
-
#
|
|
128
|
-
# 最初に発生する method_missing で、キャッシュ機能を登録する
|
|
129
|
-
#
|
|
130
|
-
# @param [Symbol] name メソッド名
|
|
131
|
-
# @param [Array] args メソッド引数
|
|
132
|
-
# @param [block] block ブロック(省略可)
|
|
133
|
-
#
|
|
134
|
-
# @return [void]
|
|
135
|
-
#
|
|
136
|
-
def method_missing(name, *args, &block)
|
|
137
|
-
|
|
138
|
-
return method_missing_(name, *args, &block) unless respond_to?("#{name}_", true)
|
|
139
|
-
return send("#{name}_", *args, &block) if MethodCash.direct
|
|
140
|
-
|
|
141
|
-
if ((name.to_s =~
|
|
142
|
-
prefix, from, to = $~[1..3]
|
|
143
|
-
begin
|
|
144
|
-
if (@_m_cash_lock_)
|
|
145
|
-
return send("#{prefix}#{from}_to_#{to}_", *args, &block) unless @_m_cash_lock_.try_lock
|
|
146
|
-
unlock = "ensure ; @_m_cash_lock_.locked? && @_m_cash_lock_.unlock"
|
|
147
|
-
end
|
|
148
|
-
[[from, to],[to, from]].each do |pair|
|
|
149
|
-
a, b = pair
|
|
150
|
-
lock = @_m_cash_lock_ ? " return #{prefix}#{a}_to_#{b}_(*args) unless @_m_cash_lock_.try_lock" : ''
|
|
151
|
-
instance_eval %Q{
|
|
152
|
-
def #{prefix}#{a}_to_#{b}(*args)
|
|
153
|
-
key = _key_simplefy(args)
|
|
154
|
-
inv = @_m_cash_["#{prefix}#{a}_to_#{b}"][key]
|
|
155
|
-
return inv if inv
|
|
156
|
-
begin
|
|
157
|
-
#{lock}
|
|
158
|
-
inv = #{prefix}#{a}_to_#{b}_(*args)
|
|
159
|
-
@_m_cash_["#{prefix}#{b}_to_#{a}"][_key_simplefy(inv)] = args
|
|
160
|
-
@_m_cash_["#{prefix}#{a}_to_#{b}"][key] = inv
|
|
161
|
-
return inv
|
|
162
|
-
#{unlock}
|
|
163
|
-
end
|
|
164
|
-
end
|
|
165
|
-
}
|
|
166
|
-
end
|
|
167
|
-
key = _key_simplefy(args)
|
|
168
|
-
inv = send("#{prefix}#{from}_to_#{to}_", *args)
|
|
169
|
-
@_m_cash_ ||= {}
|
|
170
|
-
@_m_cash_["#{prefix}#{to}_to_#{from}"] ||= {}
|
|
171
|
-
@_m_cash_["#{prefix}#{from}_to_#{to}"] ||= {}
|
|
172
|
-
@_m_cash_["#{prefix}#{to}_to_#{from}"][_key_simplefy(inv)] = args
|
|
173
|
-
@_m_cash_["#{prefix}#{from}_to_#{to}"][key] = inv
|
|
174
|
-
return inv
|
|
175
|
-
ensure
|
|
176
|
-
@_m_cash_lock_ && @_m_cash_lock_.locked? && @_m_cash_lock_.unlock
|
|
177
|
-
end
|
|
178
|
-
|
|
179
|
-
else
|
|
180
|
-
begin
|
|
181
|
-
respond = respond_to?("#{name}_setup", true)
|
|
182
|
-
setup = respond ? "#{name}_setup(key, *args)" :
|
|
183
|
-
"(@_m_cash_[\"#{name}\"][key] = #{name}_(*args))"
|
|
184
|
-
if (@_m_cash_lock_)
|
|
185
|
-
return send("#{name}_", *args, &block) unless @_m_cash_lock_.try_lock
|
|
186
|
-
lock = " return #{name}_(*args) unless @_m_cash_lock_.try_lock"
|
|
187
|
-
unlock = "ensure ; @_m_cash_lock_.locked? && @_m_cash_lock_.unlock"
|
|
188
|
-
end
|
|
189
|
-
instance_eval %Q{
|
|
190
|
-
def #{name}(*args)
|
|
191
|
-
key = _key_simplefy(args)
|
|
192
|
-
ret = @_m_cash_["#{name}"][key]
|
|
193
|
-
return ret if ret
|
|
194
|
-
begin
|
|
195
|
-
#{lock}
|
|
196
|
-
return #{setup}
|
|
197
|
-
#{unlock}
|
|
198
|
-
end
|
|
199
|
-
end
|
|
200
|
-
}
|
|
201
|
-
key = _key_simplefy(args)
|
|
202
|
-
@_m_cash_ ||= {}
|
|
203
|
-
@_m_cash_["#{name}"] ||= {}
|
|
204
|
-
if (respond)
|
|
205
|
-
return send("#{name}_setup", key, *args)
|
|
206
|
-
else
|
|
207
|
-
return(@_m_cash_["#{name}"][key] ||= send("#{name}_", *args))
|
|
208
|
-
end
|
|
209
|
-
ensure
|
|
210
|
-
@_m_cash_lock_ && @_m_cash_lock_.locked? && @_m_cash_lock_.unlock
|
|
211
|
-
end
|
|
212
|
-
end
|
|
213
|
-
end
|
|
214
|
-
|
|
215
|
-
private
|
|
216
|
-
|
|
217
|
-
def _key_simplefy(args)
|
|
218
|
-
key = args.kind_of?(Array) ? args.dup : args
|
|
219
|
-
key = key[0] while key.kind_of?(Array) && key.length<=1
|
|
220
|
-
return key
|
|
221
|
-
end
|
|
222
|
-
end
|
|
223
|
-
end
|
|
224
|
-
end
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
=begin
|
|
3
|
+
Copyright (C) 2011-2014 Takashi SUGA
|
|
4
|
+
|
|
5
|
+
You may use and/or modify this file according to the license described in the LICENSE.txt file included in this archive.
|
|
6
|
+
=end
|
|
7
|
+
|
|
8
|
+
module When
|
|
9
|
+
#
|
|
10
|
+
# 本ライブラリのための諸々の部品
|
|
11
|
+
#
|
|
12
|
+
module Parts
|
|
13
|
+
|
|
14
|
+
#
|
|
15
|
+
# == メソッドの実行結果をキャッシュし処理の高速化を行う
|
|
16
|
+
#
|
|
17
|
+
# === fn というメソッドをキャッシュ化
|
|
18
|
+
# * fn ではなく fn_ を定義しておく
|
|
19
|
+
# * fn メソッドが呼ばれると fn_ を実行し、{引数=>戻り値} を Hash に記憶する
|
|
20
|
+
# * 同じ引数で再度 fn メソッドが呼ばれると Hash から戻り値を取り出して返す
|
|
21
|
+
#
|
|
22
|
+
# === a_to_b と b_to_a という互いに逆関数のメソッドをキャッシュ化
|
|
23
|
+
# * a_to_b ではなく a_to_b_ , b_to_a ではなく b_to_a_ を定義しておく
|
|
24
|
+
# * a_to_b メソッドが呼ばれると a_to_b_ を実行し、{引数=>戻り値}, {戻り値=>引数}を Hash に記憶する
|
|
25
|
+
# * 同じ引数で再度 a_to_b メソッドが呼ばれると Hash から戻り値を取り出して返す
|
|
26
|
+
# * b_to_a メソッドが呼ばれ Hash に戻り値があれば Hash から戻り値を取り出して返す
|
|
27
|
+
#
|
|
28
|
+
# == 特記事項
|
|
29
|
+
#
|
|
30
|
+
# === Argument identification
|
|
31
|
+
# The eql? method of When::TM::(Temporal)Position is not overridden.
|
|
32
|
+
# It seems that the cost of identification of the argument exceeds the merit of the method cash.
|
|
33
|
+
# I do not recommend applying the methodcash to the method which takes
|
|
34
|
+
# When::TM::(Temporal)Position as an argument.
|
|
35
|
+
#
|
|
36
|
+
# === Multi-thread critical situation
|
|
37
|
+
# There is a problem in consistency of hash when this function is used in multi-thread environment.
|
|
38
|
+
# If the initialize method sets Mutex in instance variable @_m_cash_lock_,
|
|
39
|
+
# this function gives up use of hash in the critical situation.
|
|
40
|
+
#
|
|
41
|
+
# class Foo
|
|
42
|
+
# include MethodCash
|
|
43
|
+
#
|
|
44
|
+
# def initialize
|
|
45
|
+
# ...
|
|
46
|
+
# @_m_cash_lock_ = Mutex.new
|
|
47
|
+
# ...
|
|
48
|
+
# end
|
|
49
|
+
# end
|
|
50
|
+
#
|
|
51
|
+
# 参考 http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/47663
|
|
52
|
+
#
|
|
53
|
+
module MethodCash
|
|
54
|
+
|
|
55
|
+
# @private
|
|
56
|
+
Escape = {:to_str => true,
|
|
57
|
+
:to_ary => true,
|
|
58
|
+
:to_hash => true}
|
|
59
|
+
|
|
60
|
+
class << self
|
|
61
|
+
|
|
62
|
+
# '_' で終わるメソッドをキャッシュせずに毎回計算するか否か
|
|
63
|
+
#
|
|
64
|
+
# @return [Boolean] キャッシュしない true, キャッシュする false/nil
|
|
65
|
+
#
|
|
66
|
+
attr_accessor :direct
|
|
67
|
+
|
|
68
|
+
# When::Parts::MethodCash のグローバルな設定を行う
|
|
69
|
+
#
|
|
70
|
+
# @param [Hash] options 以下の通り
|
|
71
|
+
# @option options [Boolean] :direct '_' で終わるメソッドをキャッシュせずに毎回計算するか否か
|
|
72
|
+
# @option options [Hash{Symbol=>boolean}] :escape 毎回 method_missing を発生させるメソッドを true にする
|
|
73
|
+
# @option options [false, nil] :escape to_str, to_ary, to_hash のみ毎回 method_missing を発生させる
|
|
74
|
+
# @option options [true] :escape すべて毎回 method_missing を発生させる
|
|
75
|
+
#
|
|
76
|
+
# @return [void]
|
|
77
|
+
#
|
|
78
|
+
# @note When::TM::Calendar クラスの一部はキャッシュ使用を前提としているため :direct=>true では動作しません
|
|
79
|
+
#
|
|
80
|
+
def _setup_(options={})
|
|
81
|
+
@_setup_info = options
|
|
82
|
+
@direct = options[:direct]
|
|
83
|
+
case options[:escape]
|
|
84
|
+
when true
|
|
85
|
+
instance_eval %Q{
|
|
86
|
+
def escape(method)
|
|
87
|
+
true
|
|
88
|
+
end
|
|
89
|
+
}
|
|
90
|
+
when Hash
|
|
91
|
+
@escape = Escape.merge(options[:escape])
|
|
92
|
+
instance_eval %Q{
|
|
93
|
+
def escape(method)
|
|
94
|
+
@escape[method]
|
|
95
|
+
end
|
|
96
|
+
}
|
|
97
|
+
else
|
|
98
|
+
instance_eval %Q{
|
|
99
|
+
def escape(method)
|
|
100
|
+
Escape.key?(method)
|
|
101
|
+
end
|
|
102
|
+
}
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# 設定情報を取得する
|
|
107
|
+
#
|
|
108
|
+
# @return [Hash] 設定情報
|
|
109
|
+
#
|
|
110
|
+
def _setup_info
|
|
111
|
+
@_setup_info ||= {}
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# method_missing メソッドを forward するか否か
|
|
115
|
+
#
|
|
116
|
+
# @param [Symbol] method メソッドシンボル
|
|
117
|
+
#
|
|
118
|
+
# @return [boolean] true - しない, false/nil - する
|
|
119
|
+
#
|
|
120
|
+
def escape(method)
|
|
121
|
+
Escape.key?(method)
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
alias :method_missing_ :method_missing
|
|
126
|
+
|
|
127
|
+
#
|
|
128
|
+
# 最初に発生する method_missing で、キャッシュ機能を登録する
|
|
129
|
+
#
|
|
130
|
+
# @param [Symbol] name メソッド名
|
|
131
|
+
# @param [Array] args メソッド引数
|
|
132
|
+
# @param [block] block ブロック(省略可)
|
|
133
|
+
#
|
|
134
|
+
# @return [void]
|
|
135
|
+
#
|
|
136
|
+
def method_missing(name, *args, &block)
|
|
137
|
+
|
|
138
|
+
return method_missing_(name, *args, &block) unless respond_to?("#{name}_", true)
|
|
139
|
+
return send("#{name}_", *args, &block) if MethodCash.direct
|
|
140
|
+
|
|
141
|
+
if ((name.to_s =~ /\A(_*)(.+?)_to_(.+)\z/) && respond_to?("#{$1}#{$3}_to_#{$2}_", true))
|
|
142
|
+
prefix, from, to = $~[1..3]
|
|
143
|
+
begin
|
|
144
|
+
if (@_m_cash_lock_)
|
|
145
|
+
return send("#{prefix}#{from}_to_#{to}_", *args, &block) unless @_m_cash_lock_.try_lock
|
|
146
|
+
unlock = "ensure ; @_m_cash_lock_.locked? && @_m_cash_lock_.unlock"
|
|
147
|
+
end
|
|
148
|
+
[[from, to],[to, from]].each do |pair|
|
|
149
|
+
a, b = pair
|
|
150
|
+
lock = @_m_cash_lock_ ? " return #{prefix}#{a}_to_#{b}_(*args) unless @_m_cash_lock_.try_lock" : ''
|
|
151
|
+
instance_eval %Q{
|
|
152
|
+
def #{prefix}#{a}_to_#{b}(*args)
|
|
153
|
+
key = _key_simplefy(args)
|
|
154
|
+
inv = @_m_cash_["#{prefix}#{a}_to_#{b}"][key]
|
|
155
|
+
return inv if inv
|
|
156
|
+
begin
|
|
157
|
+
#{lock}
|
|
158
|
+
inv = #{prefix}#{a}_to_#{b}_(*args)
|
|
159
|
+
@_m_cash_["#{prefix}#{b}_to_#{a}"][_key_simplefy(inv)] = args
|
|
160
|
+
@_m_cash_["#{prefix}#{a}_to_#{b}"][key] = inv
|
|
161
|
+
return inv
|
|
162
|
+
#{unlock}
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
}
|
|
166
|
+
end
|
|
167
|
+
key = _key_simplefy(args)
|
|
168
|
+
inv = send("#{prefix}#{from}_to_#{to}_", *args)
|
|
169
|
+
@_m_cash_ ||= {}
|
|
170
|
+
@_m_cash_["#{prefix}#{to}_to_#{from}"] ||= {}
|
|
171
|
+
@_m_cash_["#{prefix}#{from}_to_#{to}"] ||= {}
|
|
172
|
+
@_m_cash_["#{prefix}#{to}_to_#{from}"][_key_simplefy(inv)] = args
|
|
173
|
+
@_m_cash_["#{prefix}#{from}_to_#{to}"][key] = inv
|
|
174
|
+
return inv
|
|
175
|
+
ensure
|
|
176
|
+
@_m_cash_lock_ && @_m_cash_lock_.locked? && @_m_cash_lock_.unlock
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
else
|
|
180
|
+
begin
|
|
181
|
+
respond = respond_to?("#{name}_setup", true)
|
|
182
|
+
setup = respond ? "#{name}_setup(key, *args)" :
|
|
183
|
+
"(@_m_cash_[\"#{name}\"][key] = #{name}_(*args))"
|
|
184
|
+
if (@_m_cash_lock_)
|
|
185
|
+
return send("#{name}_", *args, &block) unless @_m_cash_lock_.try_lock
|
|
186
|
+
lock = " return #{name}_(*args) unless @_m_cash_lock_.try_lock"
|
|
187
|
+
unlock = "ensure ; @_m_cash_lock_.locked? && @_m_cash_lock_.unlock"
|
|
188
|
+
end
|
|
189
|
+
instance_eval %Q{
|
|
190
|
+
def #{name}(*args)
|
|
191
|
+
key = _key_simplefy(args)
|
|
192
|
+
ret = @_m_cash_["#{name}"][key]
|
|
193
|
+
return ret if ret
|
|
194
|
+
begin
|
|
195
|
+
#{lock}
|
|
196
|
+
return #{setup}
|
|
197
|
+
#{unlock}
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
}
|
|
201
|
+
key = _key_simplefy(args)
|
|
202
|
+
@_m_cash_ ||= {}
|
|
203
|
+
@_m_cash_["#{name}"] ||= {}
|
|
204
|
+
if (respond)
|
|
205
|
+
return send("#{name}_setup", key, *args)
|
|
206
|
+
else
|
|
207
|
+
return(@_m_cash_["#{name}"][key] ||= send("#{name}_", *args))
|
|
208
|
+
end
|
|
209
|
+
ensure
|
|
210
|
+
@_m_cash_lock_ && @_m_cash_lock_.locked? && @_m_cash_lock_.unlock
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
private
|
|
216
|
+
|
|
217
|
+
def _key_simplefy(args)
|
|
218
|
+
key = args.kind_of?(Array) ? args.dup : args
|
|
219
|
+
key = key[0] while key.kind_of?(Array) && key.length<=1
|
|
220
|
+
return key
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
end
|
|
@@ -1,1071 +1,1069 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
=begin
|
|
3
|
-
Copyright (C) 2011-2014 Takashi SUGA
|
|
4
|
-
|
|
5
|
-
You may use and/or modify this file according to the license described in the LICENSE.txt file included in this archive.
|
|
6
|
-
=end
|
|
7
|
-
|
|
8
|
-
#
|
|
9
|
-
# 本ライブラリのための諸々の部品
|
|
10
|
-
#
|
|
11
|
-
module When::Parts
|
|
12
|
-
|
|
13
|
-
#
|
|
14
|
-
# Resource which has 'International Resource Identifier'
|
|
15
|
-
#
|
|
16
|
-
module Resource
|
|
17
|
-
|
|
18
|
-
# @private
|
|
19
|
-
LabelProperty = nil
|
|
20
|
-
|
|
21
|
-
# @private
|
|
22
|
-
ConstTypes = {
|
|
23
|
-
'
|
|
24
|
-
'
|
|
25
|
-
'
|
|
26
|
-
'
|
|
27
|
-
'
|
|
28
|
-
'
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
"^
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
attr_reader :
|
|
58
|
-
attr_accessor :
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
@
|
|
67
|
-
|
|
68
|
-
@
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
#
|
|
78
|
-
#
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
#
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
#
|
|
100
|
-
# @
|
|
101
|
-
#
|
|
102
|
-
#
|
|
103
|
-
#
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
#
|
|
112
|
-
#
|
|
113
|
-
# @
|
|
114
|
-
#
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
#
|
|
132
|
-
#
|
|
133
|
-
#
|
|
134
|
-
#
|
|
135
|
-
#
|
|
136
|
-
# @
|
|
137
|
-
#
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
#
|
|
162
|
-
#
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
#
|
|
170
|
-
#
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
#
|
|
178
|
-
#
|
|
179
|
-
#
|
|
180
|
-
# @
|
|
181
|
-
#
|
|
182
|
-
# @
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
#
|
|
203
|
-
#
|
|
204
|
-
# @
|
|
205
|
-
#
|
|
206
|
-
# @
|
|
207
|
-
#
|
|
208
|
-
# @
|
|
209
|
-
#
|
|
210
|
-
#
|
|
211
|
-
#
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
'
|
|
220
|
-
'
|
|
221
|
-
'
|
|
222
|
-
'
|
|
223
|
-
'
|
|
224
|
-
'
|
|
225
|
-
'
|
|
226
|
-
'
|
|
227
|
-
'
|
|
228
|
-
'
|
|
229
|
-
'
|
|
230
|
-
'
|
|
231
|
-
'
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
#
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
#
|
|
260
|
-
#
|
|
261
|
-
#
|
|
262
|
-
#
|
|
263
|
-
#
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
#
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
#
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
@_pool
|
|
305
|
-
@_pool[iri]
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
when
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
target
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
list[0]
|
|
517
|
-
list
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
end
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
#
|
|
650
|
-
#
|
|
651
|
-
#
|
|
652
|
-
#
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
#
|
|
658
|
-
#
|
|
659
|
-
#
|
|
660
|
-
#
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
#
|
|
664
|
-
#
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
#
|
|
668
|
-
#
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
#
|
|
684
|
-
#
|
|
685
|
-
# @param [
|
|
686
|
-
#
|
|
687
|
-
# @return [
|
|
688
|
-
#
|
|
689
|
-
def
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
#
|
|
744
|
-
#
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
#
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
#
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
#
|
|
777
|
-
#
|
|
778
|
-
#
|
|
779
|
-
#
|
|
780
|
-
def
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
#
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
#
|
|
798
|
-
#
|
|
799
|
-
#
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
#
|
|
818
|
-
#
|
|
819
|
-
# @
|
|
820
|
-
#
|
|
821
|
-
#
|
|
822
|
-
#
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
#
|
|
836
|
-
#
|
|
837
|
-
#
|
|
838
|
-
#
|
|
839
|
-
#
|
|
840
|
-
#
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
#
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
#
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
#
|
|
873
|
-
#
|
|
874
|
-
#
|
|
875
|
-
# @
|
|
876
|
-
#
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
#
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
options
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
end
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
options[
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
options[key] = value
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
end
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
#
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
end
|
|
1071
|
-
end
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
=begin
|
|
3
|
+
Copyright (C) 2011-2014 Takashi SUGA
|
|
4
|
+
|
|
5
|
+
You may use and/or modify this file according to the license described in the LICENSE.txt file included in this archive.
|
|
6
|
+
=end
|
|
7
|
+
|
|
8
|
+
#
|
|
9
|
+
# 本ライブラリのための諸々の部品
|
|
10
|
+
#
|
|
11
|
+
module When::Parts
|
|
12
|
+
|
|
13
|
+
#
|
|
14
|
+
# Resource which has 'International Resource Identifier'
|
|
15
|
+
#
|
|
16
|
+
module Resource
|
|
17
|
+
|
|
18
|
+
# @private
|
|
19
|
+
LabelProperty = nil
|
|
20
|
+
|
|
21
|
+
# @private
|
|
22
|
+
ConstTypes = {
|
|
23
|
+
'SolarTerms' => ['CalendarNote', '%sSolarTerms', '_n:%sSolarTerms%s' ],
|
|
24
|
+
'LunarPhases' => ['LunarPhases', '%sLunarPhases', '_n:%sLunarPhases%s'],
|
|
25
|
+
'Terms' => ['BasicTypes::M17n', '%s', '_m:%s%s' ],
|
|
26
|
+
'Era' => ['TM::CalendarEra', '%s', '_e:%s%s' ],
|
|
27
|
+
'Residue' => ['Coordinates', '%s', '_co:%s%s' ],
|
|
28
|
+
'Week' => ['CalendarNote', '%sWeek', '_n:%sWeek%s' ],
|
|
29
|
+
'Note' => ['CalendarNote', '%s', '_n:%s%s' ],
|
|
30
|
+
'Notes' => ['CalendarNote', '%s', '_n:%s/Notes%s' ],
|
|
31
|
+
nil => ['CalendarTypes', '%s', '_c:%s%s' ]
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
# @private
|
|
35
|
+
ConstList = []
|
|
36
|
+
|
|
37
|
+
# private
|
|
38
|
+
IRIHeader = /\A[_a-z\d]+:[^:]/i
|
|
39
|
+
|
|
40
|
+
# @private
|
|
41
|
+
class ContentLine
|
|
42
|
+
|
|
43
|
+
RFC6350 = {
|
|
44
|
+
"\\\\" => "\\",
|
|
45
|
+
"\\n" => "\n",
|
|
46
|
+
"\\N" => "\n",
|
|
47
|
+
"\\;" => ";",
|
|
48
|
+
"\\:" => ":"
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
RFC6868 = {
|
|
52
|
+
"^n" => "\n",
|
|
53
|
+
"^^" => "^",
|
|
54
|
+
"^'" => '"'
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
attr_reader :predicate
|
|
58
|
+
attr_accessor :object
|
|
59
|
+
attr_reader :attribute
|
|
60
|
+
attr_accessor :namespace
|
|
61
|
+
attr_accessor :same_altid
|
|
62
|
+
attr_reader :marked
|
|
63
|
+
|
|
64
|
+
def initialize(key, object=nil, marked=nil)
|
|
65
|
+
key = key.downcase.gsub(/-/,'_') if (key==key.upcase)
|
|
66
|
+
@predicate, @namespace = key.split(/:/).reverse
|
|
67
|
+
object = object.gsub(/\^./) {|escape| RFC6868[escape] || escape} if object.instance_of?(String)
|
|
68
|
+
@object = object
|
|
69
|
+
@marked = marked
|
|
70
|
+
@attribute = {}
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# @private
|
|
75
|
+
module Synchronize
|
|
76
|
+
|
|
77
|
+
# 排他実行
|
|
78
|
+
#
|
|
79
|
+
# 与えられたブロックを必要なら排他制御をして実行する
|
|
80
|
+
#
|
|
81
|
+
def synchronize
|
|
82
|
+
if @_lock_
|
|
83
|
+
@_lock_.synchronize do
|
|
84
|
+
yield
|
|
85
|
+
end
|
|
86
|
+
else
|
|
87
|
+
yield
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
#
|
|
93
|
+
# Resource の has-a 親子関係を管理する
|
|
94
|
+
#
|
|
95
|
+
module Pool
|
|
96
|
+
|
|
97
|
+
include Synchronize
|
|
98
|
+
|
|
99
|
+
# 初期化
|
|
100
|
+
# @return [void]
|
|
101
|
+
#
|
|
102
|
+
# @note
|
|
103
|
+
# 本メソッドでマルチスレッド対応の管理変数の初期化を行っている。
|
|
104
|
+
# このため、本メソッド自体はスレッドセーフでない。
|
|
105
|
+
#
|
|
106
|
+
def _setup_
|
|
107
|
+
@_lock_ = Mutex.new if When.multi_thread
|
|
108
|
+
@_pool = {}
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# オブジェクト参照
|
|
112
|
+
#
|
|
113
|
+
# @param [String] label
|
|
114
|
+
#
|
|
115
|
+
# @return [When::Parts::Resource] 指定した label で登録した子 Resource を返す
|
|
116
|
+
#
|
|
117
|
+
def [](label)
|
|
118
|
+
|
|
119
|
+
# nil label の場合
|
|
120
|
+
return _pool[label] unless label
|
|
121
|
+
|
|
122
|
+
# 階層がある場合
|
|
123
|
+
terms = Resource._encode(label).split(/::/)
|
|
124
|
+
terms.shift if terms[0] == ''
|
|
125
|
+
return terms.inject(self) {|obj,term| obj = obj[Resource._decode(term)]} if terms.length >= 2
|
|
126
|
+
|
|
127
|
+
# 階層がない場合
|
|
128
|
+
_pool[Resource._decode(Resource._extract_prefix(terms[0]))]
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# オブジェクト登録
|
|
132
|
+
#
|
|
133
|
+
# 指定した label で子 Resource を登録する
|
|
134
|
+
#
|
|
135
|
+
# @param [String] label
|
|
136
|
+
# @param [When::Parts::Resource] obj
|
|
137
|
+
#
|
|
138
|
+
# @return [void]
|
|
139
|
+
#
|
|
140
|
+
def []=(label, obj)
|
|
141
|
+
# raise NameError, "Name duplication" if (@_pool[label])
|
|
142
|
+
_pool[label] = obj
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# @private
|
|
146
|
+
def pool_keys
|
|
147
|
+
_pool.keys
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# @private
|
|
151
|
+
def _pool
|
|
152
|
+
_setup_ unless @_pool
|
|
153
|
+
@_pool
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
class << self
|
|
158
|
+
|
|
159
|
+
include Pool
|
|
160
|
+
|
|
161
|
+
# Base URI for When_exe Resources
|
|
162
|
+
#
|
|
163
|
+
# @return [String]
|
|
164
|
+
#
|
|
165
|
+
def base_uri
|
|
166
|
+
@base_uri ||= When::SourceURI
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Root Directory for When_exe Resources
|
|
170
|
+
#
|
|
171
|
+
# @return [String]
|
|
172
|
+
#
|
|
173
|
+
def root_dir
|
|
174
|
+
@root_dir ||= When::RootDir
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
#
|
|
178
|
+
# 略称を iri に変換する
|
|
179
|
+
#
|
|
180
|
+
# @param [String or Symbol] abbreviation 略称
|
|
181
|
+
#
|
|
182
|
+
# @return [String] iri or nil
|
|
183
|
+
#
|
|
184
|
+
# @private
|
|
185
|
+
def _abbreviation_to_iri(abbreviation, abbreviation_types=ConstTypes)
|
|
186
|
+
abbreviation_types[:pattern] ||= /\A(?=[A-Z])(.*?)(#{abbreviation_types.keys.compact.join('|')})?(\?.+|::.+)?\z/
|
|
187
|
+
abbreviation.to_s =~ abbreviation_types[:pattern]
|
|
188
|
+
return nil unless $1
|
|
189
|
+
klass, name, iri = abbreviation_types[$2]
|
|
190
|
+
key, name, iri = $2, name % $1, iri % [$1,$3]
|
|
191
|
+
if klass.kind_of?(String)
|
|
192
|
+
klass = klass.split('::').inject(When) {|k,n| k.const_get(n)}
|
|
193
|
+
abbreviation_types[key][0] = klass
|
|
194
|
+
end
|
|
195
|
+
klass.const_defined?(name) ? iri : nil
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# @private
|
|
199
|
+
attr_reader :_prefix, :_prefix_values, :_prefix_index
|
|
200
|
+
private :_prefix, :_prefix_values, :_prefix_index
|
|
201
|
+
|
|
202
|
+
# 初期化
|
|
203
|
+
#
|
|
204
|
+
# @param [Hash] options 以下の通り
|
|
205
|
+
# @option options [String] :base_uri Base URI for When_exe Resources (Default When::SourceURI)
|
|
206
|
+
# @option options [Hash<String(namespace)=>String(URI)>] :additional_namespaces User defined namespaces (Default {})
|
|
207
|
+
# @option options [String] :root_dir Root Directory for When_exe Resources Cash data (Default When::RootDir)
|
|
208
|
+
# @option options [Boolean] :leave_const If true, leave Constants of When module defined
|
|
209
|
+
#
|
|
210
|
+
# @return [void]
|
|
211
|
+
#
|
|
212
|
+
# @note
|
|
213
|
+
# 本メソッドでマルチスレッド対応の管理変数の初期化を行っている。
|
|
214
|
+
# このため、本メソッド自体はスレッドセーフでない。
|
|
215
|
+
#
|
|
216
|
+
def _setup_(options={})
|
|
217
|
+
super()
|
|
218
|
+
@_prefix = {
|
|
219
|
+
'_wp' => 'http://en.wikipedia.org/wiki/',
|
|
220
|
+
'_w' => base_uri + '/',
|
|
221
|
+
'_p' => base_uri + 'Parts/',
|
|
222
|
+
'_b' => base_uri + 'BasicTypes/',
|
|
223
|
+
'_m' => base_uri + 'BasicTypes/M17n/',
|
|
224
|
+
'_co' => base_uri + 'Coordinates/',
|
|
225
|
+
'_l' => base_uri + 'Coordinates/Spatial?',
|
|
226
|
+
'_v' => base_uri + 'V/',
|
|
227
|
+
'_rs' => base_uri + 'RS/',
|
|
228
|
+
'_ex' => base_uri + 'EX/',
|
|
229
|
+
'_tm' => base_uri + 'TM/',
|
|
230
|
+
'_e' => base_uri + 'TM/CalendarEra/',
|
|
231
|
+
'_t' => base_uri + 'TimeStandard/',
|
|
232
|
+
'_ep' => base_uri + 'Ephemeris/',
|
|
233
|
+
'_c' => base_uri + 'CalendarTypes/',
|
|
234
|
+
'_n' => base_uri + 'CalendarNote/',
|
|
235
|
+
'_sc' => base_uri + 'Ephemeris/V50/'
|
|
236
|
+
}
|
|
237
|
+
@base_uri = options[:base_uri] || When::SourceURI
|
|
238
|
+
@root_dir = options[:root_dir] || When::RootDir
|
|
239
|
+
@_prefix = options[:additional_namespaces].merge(@_prefix) if options[:additional_namespaces].kind_of?(Hash)
|
|
240
|
+
@_prefix_values = @_prefix.values.sort.reverse
|
|
241
|
+
@_prefix_index = @_prefix.invert
|
|
242
|
+
unless options[:leave_const] || ConstList.empty?
|
|
243
|
+
ConstList.delete_if do |constant|
|
|
244
|
+
When.send(:remove_const, constant) if When.const_defined?(constant)
|
|
245
|
+
true
|
|
246
|
+
end
|
|
247
|
+
When._define_common_calendar_types
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
# 設定情報を取得する
|
|
252
|
+
#
|
|
253
|
+
# @return [Hash] 設定情報
|
|
254
|
+
#
|
|
255
|
+
def _setup_info
|
|
256
|
+
{:base_uri => base_uri, :root_dir => root_dir}
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
# オブジェクト生成&参照
|
|
260
|
+
#
|
|
261
|
+
# 指定した iri の When::Parts::Resource オブジェクトを取得する。
|
|
262
|
+
# 当該オブジェクトが未登録であれば生成する。
|
|
263
|
+
#
|
|
264
|
+
# @param [String] iri International Resource Identifier
|
|
265
|
+
# @param [String] namespace (デフォルトの名前空間, 指定がないときは名前空間を省略しない)
|
|
266
|
+
# @param [Block] block オブジェクトが見つからない場合の代替処理
|
|
267
|
+
#
|
|
268
|
+
# @return [When::Parts::Resource]
|
|
269
|
+
#
|
|
270
|
+
def _instance(iri, namespace=nil, &block)
|
|
271
|
+
_setup_ unless @_pool
|
|
272
|
+
|
|
273
|
+
case iri
|
|
274
|
+
when Array ; return iri.map {|e| _instance(e, namespace)} # 配列は個別に処理
|
|
275
|
+
when Resource ; return iri # 登録済みはそのまま
|
|
276
|
+
when String ; # 解析処理へ
|
|
277
|
+
else ; raise ArgumentError, "can't convert #{iri.class} to String" # 例外
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
# 内部文字列化
|
|
281
|
+
iri = When::EncodingConversion.to_internal_encoding(iri)
|
|
282
|
+
|
|
283
|
+
# 階層がある場合は、階層をたどる
|
|
284
|
+
iri = Resource._decode(iri)
|
|
285
|
+
iri = $1 while iri =~ /\A\((.*)\)\z/
|
|
286
|
+
iri = namespace + iri if namespace && iri !~ IRIHeader
|
|
287
|
+
root, *leaves= Resource._encode(iri).split(/::/)
|
|
288
|
+
if leaves.size > 0
|
|
289
|
+
return leaves.inject(_instance(Resource._decode(root))) {|obj,leaf| obj[Resource._decode(leaf)]}
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
# 登録ずみなら、参照
|
|
293
|
+
iri = _extract_prefix(iri)
|
|
294
|
+
path, query = iri.split(/\?/, 2)
|
|
295
|
+
if When.multi_thread
|
|
296
|
+
my_mutex = nil
|
|
297
|
+
@_lock_.synchronize do
|
|
298
|
+
@_pool ||= {}
|
|
299
|
+
unless @_pool[iri]
|
|
300
|
+
my_mutex = Mutex.new
|
|
301
|
+
@_pool[iri] = my_mutex
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
case @_pool[iri]
|
|
305
|
+
when my_mutex; my_mutex.synchronize {@_pool[iri] = _create_object(iri, path, query, &block) }
|
|
306
|
+
when Mutex ; @_pool[iri].synchronize {@_pool[iri]}
|
|
307
|
+
else ; @_pool[iri]
|
|
308
|
+
end
|
|
309
|
+
else
|
|
310
|
+
@_pool ||= {}
|
|
311
|
+
@_pool[iri] ||= _create_object(iri, path, query, &block)
|
|
312
|
+
end
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
# @private
|
|
316
|
+
def _path_with_prefix(obj, simple=true)
|
|
317
|
+
_setup_ unless @_pool
|
|
318
|
+
path = obj.kind_of?(Class) ? obj.to_s.sub(/\AWhen::/, base_uri).gsub(/::/, '/') :
|
|
319
|
+
obj.iri
|
|
320
|
+
simple ? _simplify_path(path) : path
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
# @private
|
|
324
|
+
def _simplify_path(path)
|
|
325
|
+
_prefix_values.each do |value|
|
|
326
|
+
index = path.index(value)
|
|
327
|
+
return _prefix_index[value] + ':' + path[value.length..-1] if index
|
|
328
|
+
end
|
|
329
|
+
return path
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
# @private
|
|
333
|
+
def _parse(line, type=nil)
|
|
334
|
+
return line unless line.kind_of?(String)
|
|
335
|
+
line.sub!(/\s#.*\z/, '')
|
|
336
|
+
return When::Locale._split($1) if type && /\A#{type}:(.+)\z/i =~ line
|
|
337
|
+
tokens = line.scan(/((?:[^\\:]|\\.)+)(?::(?!\z))?|:/).flatten
|
|
338
|
+
return When::Locale._split(line) unless tokens.size > 1 && /\A(\*)?([A-Z][-A-Z_]{0,255})(?:;(.+))?\z/i =~ tokens[0]
|
|
339
|
+
marked, key, property = $~[1..3]
|
|
340
|
+
values = tokens[1..-1]
|
|
341
|
+
value = values.join(':') unless values == [nil]
|
|
342
|
+
content = ContentLine.new(key, value, marked)
|
|
343
|
+
value ||= ''
|
|
344
|
+
if property
|
|
345
|
+
content.attribute['.'] = property + ':' + value
|
|
346
|
+
property.scan(/((?:[^\\;]|\\.)+)(?:;(?!\z))?|;/).flatten.each do |pr|
|
|
347
|
+
pr ||= ''
|
|
348
|
+
pr.gsub!(/\\./) {|escape| ContentLine::RFC6350[escape] || escape}
|
|
349
|
+
prop = ContentLine.new(*pr.split(/=/, 2))
|
|
350
|
+
content.attribute[prop.predicate] = prop
|
|
351
|
+
end
|
|
352
|
+
else
|
|
353
|
+
content.attribute['.'] = value
|
|
354
|
+
end
|
|
355
|
+
return content
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
# @private
|
|
359
|
+
def _extract_prefix(path, capitalize=false)
|
|
360
|
+
if (path =~ /\A(.+?):+(.+)\z/)
|
|
361
|
+
prefix, klass = $~[1..2]
|
|
362
|
+
if capitalize
|
|
363
|
+
prefix = '_' + prefix.downcase
|
|
364
|
+
klass = klass.capitalize if klass == klass.upcase
|
|
365
|
+
end
|
|
366
|
+
path = _prefix[prefix] + klass if _prefix[prefix]
|
|
367
|
+
elsif capitalize && path =~ /\A(v[^\/]+|daylight$|standard$)/i
|
|
368
|
+
klass = path.sub(/\Av/i, '').capitalize
|
|
369
|
+
path = _prefix['_v'] + klass if When::V.const_defined?(klass) &&
|
|
370
|
+
When::V.const_get(klass).kind_of?(Class)
|
|
371
|
+
end
|
|
372
|
+
return path
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
# @private
|
|
376
|
+
def _replace_tags(source, tags)
|
|
377
|
+
case source
|
|
378
|
+
when When::BasicTypes::M17n
|
|
379
|
+
source
|
|
380
|
+
when String
|
|
381
|
+
target = source.dup
|
|
382
|
+
tags.each_pair do |key, value|
|
|
383
|
+
target.gsub!(/#\{([?&][^=#}]+?=)?#{key}(:.*?)?\}/, '\1' + value) if value.kind_of?(String)
|
|
384
|
+
end
|
|
385
|
+
target.gsub(/#\{.+?(:(.*?))?\}/, '\2')
|
|
386
|
+
when Array
|
|
387
|
+
source.map {|target| _replace_tags(target, tags)}
|
|
388
|
+
when Hash
|
|
389
|
+
target = {}
|
|
390
|
+
source.each_pair do |key, value|
|
|
391
|
+
target[key] = _replace_tags(tags[key] || value, tags)
|
|
392
|
+
end
|
|
393
|
+
target
|
|
394
|
+
else
|
|
395
|
+
source
|
|
396
|
+
end
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
# @private
|
|
400
|
+
def _encode(iri)
|
|
401
|
+
return iri unless iri =~ /\(/
|
|
402
|
+
|
|
403
|
+
iri = iri.dup
|
|
404
|
+
begin
|
|
405
|
+
unless iri.gsub!(/\([^()]*\)/) {|token|
|
|
406
|
+
token.gsub(/[():?&%]/) {|char|'%' + char.ord.to_s(16)}
|
|
407
|
+
}
|
|
408
|
+
raise ArgumentError, 'Brackets do not correspond: ' + iri
|
|
409
|
+
end
|
|
410
|
+
end while iri =~ /\(/
|
|
411
|
+
iri
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
# @private
|
|
415
|
+
def _decode(iri)
|
|
416
|
+
return iri unless iri =~ /%28/
|
|
417
|
+
|
|
418
|
+
iri = iri.dup
|
|
419
|
+
begin
|
|
420
|
+
unless iri.gsub!(/%28.*?%29/) {|token|
|
|
421
|
+
token.gsub(/%([\dA-F]{2})/i) {$1.to_i(16).chr}
|
|
422
|
+
}
|
|
423
|
+
raise ArgumentError, 'Brackets do not correspond: ' + iri
|
|
424
|
+
end
|
|
425
|
+
end while iri =~ /%28/
|
|
426
|
+
iri = $1 if iri =~ /\A\((.*)\)\z/
|
|
427
|
+
iri
|
|
428
|
+
end
|
|
429
|
+
|
|
430
|
+
# @private
|
|
431
|
+
def _instantiate(resource)
|
|
432
|
+
return resource unless resource.kind_of?(Array)
|
|
433
|
+
return resource[0].new(*resource[1..-1]) if resource[0].kind_of?(Class)
|
|
434
|
+
return resource.map {|rsc| _instantiate(rsc)}
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
private
|
|
438
|
+
|
|
439
|
+
# オブジェクト生成
|
|
440
|
+
def _create_object(iri, path, query, &block)
|
|
441
|
+
# query analyzation
|
|
442
|
+
options = {}
|
|
443
|
+
replace = {}
|
|
444
|
+
if query
|
|
445
|
+
options = Hash[*Resource._encode(query).split(/&/).map{|pair|
|
|
446
|
+
key, value = pair.split(/=/, 2)
|
|
447
|
+
[key, Resource._decode(value)]
|
|
448
|
+
}.flatten]
|
|
449
|
+
keys = options.keys
|
|
450
|
+
keys.each do |key|
|
|
451
|
+
replace[$1] = options.delete(key) if key =~ /\A([A-Z].*)/
|
|
452
|
+
end
|
|
453
|
+
end
|
|
454
|
+
options['..'] = iri
|
|
455
|
+
|
|
456
|
+
# internal Resource
|
|
457
|
+
if path.index(Resource.base_uri) == 0
|
|
458
|
+
list = _class(path)
|
|
459
|
+
if list
|
|
460
|
+
return _internal(list, replace, options)
|
|
461
|
+
else
|
|
462
|
+
object = yield(iri) if block_given?
|
|
463
|
+
return object if object
|
|
464
|
+
raise IOError, 'IRI not found - ' + path
|
|
465
|
+
end
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
# external Resource
|
|
469
|
+
begin
|
|
470
|
+
object = When::Locale.send(:wikipedia_object, path, {:query=>query})
|
|
471
|
+
return object if object
|
|
472
|
+
OpenURI
|
|
473
|
+
args = [path, "1".respond_to?(:force_encoding) ? 'r:utf-8' : 'r']
|
|
474
|
+
args << {:ssl_verify_mode=>OpenSSL::SSL::VERIFY_NONE} if path =~ /\Ahttps:/
|
|
475
|
+
open(*args) do |file|
|
|
476
|
+
resource = file.read
|
|
477
|
+
case resource[0..5].upcase
|
|
478
|
+
when 'BEGIN:'
|
|
479
|
+
options['.'] = _ics(_replace_tags(resource, replace).split(/[\n\r]+/))
|
|
480
|
+
options['.'][0].new(options)
|
|
481
|
+
when '<?XML '
|
|
482
|
+
options['.'] = _xml(REXML::Document.new(_replace_tags(resource, replace)).root)
|
|
483
|
+
options['.'][0].new(options)
|
|
484
|
+
else
|
|
485
|
+
raise NoMethodError, 'JSON not supported' unless Object.const_defined?(:JSON)
|
|
486
|
+
_internal(_json([JSON.parse(resource)]), replace, options)
|
|
487
|
+
end
|
|
488
|
+
end
|
|
489
|
+
rescue OpenURI::HTTPError => error
|
|
490
|
+
message = error.message + " - #{path}"
|
|
491
|
+
error = error.respond_to?(:uri) ?
|
|
492
|
+
error.class.new(message, error.io, error.uri) :
|
|
493
|
+
error.class.new(message, error.io)
|
|
494
|
+
raise error
|
|
495
|
+
end
|
|
496
|
+
end
|
|
497
|
+
|
|
498
|
+
# 指定のモジュール/クラスで直接定数が定義されているか
|
|
499
|
+
if method(:const_defined?).arity == 1
|
|
500
|
+
def _directry_defined?(klass, const)
|
|
501
|
+
klass.const_defined?(const)
|
|
502
|
+
end
|
|
503
|
+
else
|
|
504
|
+
def _directry_defined?(klass, const)
|
|
505
|
+
klass.const_defined?(const, false)
|
|
506
|
+
end
|
|
507
|
+
end
|
|
508
|
+
|
|
509
|
+
# 内部形式定義の取得
|
|
510
|
+
def _class(path)
|
|
511
|
+
list = [When]
|
|
512
|
+
path[Resource.base_uri.length..-1].split(/\//).each do |mod|
|
|
513
|
+
if list[0].kind_of?(Module) && _directry_defined?(list[0], mod)
|
|
514
|
+
list.unshift(list[0].const_get(mod))
|
|
515
|
+
else
|
|
516
|
+
return nil unless list[0] == When::V
|
|
517
|
+
list.unshift(When::V::Root)
|
|
518
|
+
return list
|
|
519
|
+
end
|
|
520
|
+
end
|
|
521
|
+
return list
|
|
522
|
+
end
|
|
523
|
+
|
|
524
|
+
# 内部形式定義のオブジェクト化
|
|
525
|
+
def _internal(list, replace, options)
|
|
526
|
+
case list[0]
|
|
527
|
+
when Class
|
|
528
|
+
list[0].new(options)
|
|
529
|
+
when Array
|
|
530
|
+
top = list[0][0]
|
|
531
|
+
if top.kind_of?(Hash)
|
|
532
|
+
top.each_pair do |key, value|
|
|
533
|
+
replace.update(value[replace[key]]) if value.kind_of?(Hash) && value[replace[key]]
|
|
534
|
+
end
|
|
535
|
+
list[0] = list[0][1..-1]
|
|
536
|
+
list[0] = _replace_tags(list[0], top.merge(replace))
|
|
537
|
+
end
|
|
538
|
+
if list[0][0].kind_of?(Class)
|
|
539
|
+
# 配列の先頭がクラスである場合
|
|
540
|
+
klass, *list = list[0]
|
|
541
|
+
unless list[-1].kind_of?(Hash)
|
|
542
|
+
if list.length == 1
|
|
543
|
+
list[0] = {'.'=>Array(list[0])}
|
|
544
|
+
else
|
|
545
|
+
list << {}
|
|
546
|
+
end
|
|
547
|
+
end
|
|
548
|
+
else
|
|
549
|
+
# 配列の先頭がクラスではない場合
|
|
550
|
+
klass, *list = [list[1], *list[0]]
|
|
551
|
+
list << {} unless list[-1].kind_of?(Hash)
|
|
552
|
+
end
|
|
553
|
+
list[-1] = list[-1].merge(options)
|
|
554
|
+
klass.new(*list)
|
|
555
|
+
else
|
|
556
|
+
list[0]
|
|
557
|
+
end
|
|
558
|
+
end
|
|
559
|
+
|
|
560
|
+
# .xml フォーマットの読み込み
|
|
561
|
+
def _xml(xml, namespace={})
|
|
562
|
+
obj = [_class(_extract_prefix(xml.attributes['type'].to_s))[0]]
|
|
563
|
+
xml.attributes.each_pair do |key,value|
|
|
564
|
+
expanded_name = value.expanded_name
|
|
565
|
+
next unless (expanded_name =~ /\Axmlns/)
|
|
566
|
+
key = '' if expanded_name == 'xmlns'
|
|
567
|
+
namespace[key] = value.to_s
|
|
568
|
+
end
|
|
569
|
+
obj << ContentLine.new('xmlns:namespace', namespace) if (namespace.size>0)
|
|
570
|
+
xml.each do |e|
|
|
571
|
+
next unless defined? e.name
|
|
572
|
+
if (e.attributes['type'])
|
|
573
|
+
obj << _xml(e, namespace)
|
|
574
|
+
else
|
|
575
|
+
content = ContentLine.new(e.expanded_name, e.attributes['ref']||e.text)
|
|
576
|
+
e.attributes.each_pair do |key,value|
|
|
577
|
+
attr = ContentLine.new(value.name, value)
|
|
578
|
+
attr.namespace = value.prefix
|
|
579
|
+
content.attribute[key] = attr
|
|
580
|
+
end
|
|
581
|
+
obj << content
|
|
582
|
+
end
|
|
583
|
+
end
|
|
584
|
+
return obj
|
|
585
|
+
end
|
|
586
|
+
|
|
587
|
+
# .ics フォーマットの読み込み
|
|
588
|
+
def _ics(ics, type=nil)
|
|
589
|
+
obj = [type] if type
|
|
590
|
+
indent = nil
|
|
591
|
+
while (line = ics.shift) do
|
|
592
|
+
line.chomp!
|
|
593
|
+
case line
|
|
594
|
+
when /\A\s*BEGIN:(.*)\z/
|
|
595
|
+
if type
|
|
596
|
+
subtype = $1
|
|
597
|
+
obj[-1] = _parse(obj[-1], type) if obj.length > 1
|
|
598
|
+
obj << _ics(ics, subtype)
|
|
599
|
+
else
|
|
600
|
+
type = $1
|
|
601
|
+
obj = [type]
|
|
602
|
+
end
|
|
603
|
+
when /\A\s*END:(.*)\z/
|
|
604
|
+
raise TypeError, "Irregal Type : #{$1}" unless type == $1
|
|
605
|
+
obj[0] = _class(_extract_prefix(type, true))[0]
|
|
606
|
+
obj[-1] = _parse(obj[-1], type)
|
|
607
|
+
return obj
|
|
608
|
+
when /\A\s*#/
|
|
609
|
+
when /\A(\s*)(.*)\z/
|
|
610
|
+
indent = $1 unless indent
|
|
611
|
+
if indent.length < $1.length
|
|
612
|
+
obj[-1] += line[(indent.length+1)..-1] # See RFC5545 3.1 Content Lines
|
|
613
|
+
else
|
|
614
|
+
obj << $2
|
|
615
|
+
obj[-2] = _parse(obj[-2], type)
|
|
616
|
+
end
|
|
617
|
+
end
|
|
618
|
+
end
|
|
619
|
+
raise ArgumentError, "BEGIN-END mismatch"
|
|
620
|
+
end
|
|
621
|
+
|
|
622
|
+
# .json フォーマットの読み込み
|
|
623
|
+
def _json(json)
|
|
624
|
+
case json
|
|
625
|
+
when Array
|
|
626
|
+
json.map {|value| _json(value)}
|
|
627
|
+
when Hash
|
|
628
|
+
hash = {}
|
|
629
|
+
json.each_pair {|key, value| hash[key] = _json(value)}
|
|
630
|
+
hash
|
|
631
|
+
when String
|
|
632
|
+
return json unless json =~ /\AWhen::/
|
|
633
|
+
begin
|
|
634
|
+
return json.split('::').inject(Object) {|ns, sym| ns.const_get(sym)}
|
|
635
|
+
rescue
|
|
636
|
+
json
|
|
637
|
+
end
|
|
638
|
+
else
|
|
639
|
+
json
|
|
640
|
+
end
|
|
641
|
+
end
|
|
642
|
+
end
|
|
643
|
+
|
|
644
|
+
include Synchronize
|
|
645
|
+
|
|
646
|
+
# @private
|
|
647
|
+
attr_reader :_pool
|
|
648
|
+
|
|
649
|
+
# self が has-a 関係で包含するオブジェクト
|
|
650
|
+
#
|
|
651
|
+
# @return [Array<When::Parts::Resource>]
|
|
652
|
+
#
|
|
653
|
+
attr_accessor :child
|
|
654
|
+
private :child=
|
|
655
|
+
|
|
656
|
+
#
|
|
657
|
+
# Resource包含階層で使用する namespace
|
|
658
|
+
#
|
|
659
|
+
# When::BasicTypes::M17n の生成に使用する namespace を定義する。
|
|
660
|
+
# RFC 5545 に対する拡張である。
|
|
661
|
+
# xml で記述する場合には、本ライブラリ以外でも namespace を定義している。
|
|
662
|
+
#
|
|
663
|
+
# @return [Hash] { prefix => prefix文字列 }
|
|
664
|
+
#
|
|
665
|
+
attr_reader :namespace
|
|
666
|
+
|
|
667
|
+
#
|
|
668
|
+
# Resource包含階層で使用する locale
|
|
669
|
+
#
|
|
670
|
+
# When::BasicTypes::M17n の生成に使用する locale を定義する。
|
|
671
|
+
# RFC 5545 に対する拡張である。
|
|
672
|
+
#
|
|
673
|
+
# @return [Array<String>]
|
|
674
|
+
#
|
|
675
|
+
attr_reader :locale
|
|
676
|
+
|
|
677
|
+
# strftime で有効な locale
|
|
678
|
+
#
|
|
679
|
+
# @return [Array<String>]
|
|
680
|
+
#
|
|
681
|
+
attr_reader :keys
|
|
682
|
+
|
|
683
|
+
# オブジェクトの IRI
|
|
684
|
+
#
|
|
685
|
+
# @param [Boolean] prefix true ならIRI の先頭部分を簡約表現にする
|
|
686
|
+
#
|
|
687
|
+
# @return [Sring]
|
|
688
|
+
#
|
|
689
|
+
def iri(prefix=false)
|
|
690
|
+
unless @iri
|
|
691
|
+
root = @_pool['..']
|
|
692
|
+
path = root.instance_of?(String) ? root : label.to_s
|
|
693
|
+
if root.respond_to?(:iri)
|
|
694
|
+
root_iri = root.iri
|
|
695
|
+
path = root_iri + '::' + path if root_iri
|
|
696
|
+
end
|
|
697
|
+
@iri = path
|
|
698
|
+
end
|
|
699
|
+
prefix ? Resource._simplify_path(@iri) : @iri
|
|
700
|
+
end
|
|
701
|
+
|
|
702
|
+
# IRI または child の番号によるオブジェクト参照
|
|
703
|
+
#
|
|
704
|
+
# @param [String] iri オブジェクトの IRI
|
|
705
|
+
# @param [Numeric] iri child の index
|
|
706
|
+
#
|
|
707
|
+
# @return [When::parts::Resource]
|
|
708
|
+
#
|
|
709
|
+
def [](iri)
|
|
710
|
+
case iri
|
|
711
|
+
when Numeric
|
|
712
|
+
return child[iri * 1]
|
|
713
|
+
when String
|
|
714
|
+
obj = self
|
|
715
|
+
Resource._encode(iri).split(/::/).each do |label|
|
|
716
|
+
return obj.child if label == '*'
|
|
717
|
+
if obj == Resource
|
|
718
|
+
obj = Resource._instance(Resource._decode(label))
|
|
719
|
+
else
|
|
720
|
+
case label
|
|
721
|
+
when '' ; obj = Resource
|
|
722
|
+
when '.' # obj = obj
|
|
723
|
+
else ; obj = obj._pool[Resource._decode(label)]
|
|
724
|
+
end
|
|
725
|
+
end
|
|
726
|
+
raise ArgumentError, "IRI not found: #{iri}" unless obj
|
|
727
|
+
end
|
|
728
|
+
return obj
|
|
729
|
+
else
|
|
730
|
+
super(iri)
|
|
731
|
+
#raise ArgumentError, "IRI not found: #{iri}"
|
|
732
|
+
end
|
|
733
|
+
end
|
|
734
|
+
|
|
735
|
+
# self を直接に包含するオブジェクト
|
|
736
|
+
#
|
|
737
|
+
# @return [When::Parts::Resource]
|
|
738
|
+
#
|
|
739
|
+
def parent
|
|
740
|
+
@_pool['..'].kind_of?(Resource) ? @_pool['..'] : nil
|
|
741
|
+
end
|
|
742
|
+
|
|
743
|
+
# self を包含するオブジェクト階層
|
|
744
|
+
#
|
|
745
|
+
# @param [Class] klass 階層を遡るクラス
|
|
746
|
+
#
|
|
747
|
+
# @return [When::Parts::Resource]
|
|
748
|
+
#
|
|
749
|
+
def hierarchy(klass=self.class)
|
|
750
|
+
hierarchy = []
|
|
751
|
+
parent = self
|
|
752
|
+
while parent.kind_of?(klass)
|
|
753
|
+
hierarchy << parent
|
|
754
|
+
parent = parent.parent
|
|
755
|
+
end
|
|
756
|
+
hierarchy.reverse
|
|
757
|
+
end
|
|
758
|
+
|
|
759
|
+
# self が other を包含するか
|
|
760
|
+
#
|
|
761
|
+
# @return [Boolean]
|
|
762
|
+
# [ true - 包含する ]
|
|
763
|
+
# [ false - 包含しない ]
|
|
764
|
+
#
|
|
765
|
+
def include?(other)
|
|
766
|
+
c = other
|
|
767
|
+
while c.kind_of?(Resource)
|
|
768
|
+
return true if c.equal?(self)
|
|
769
|
+
c = c.parent
|
|
770
|
+
end
|
|
771
|
+
return false
|
|
772
|
+
end
|
|
773
|
+
|
|
774
|
+
# other が self を包含するか
|
|
775
|
+
#
|
|
776
|
+
# @return [Boolean]
|
|
777
|
+
# [ true - 包含される ]
|
|
778
|
+
# [ false - 包含されない ]
|
|
779
|
+
#
|
|
780
|
+
def included?(other)
|
|
781
|
+
other.include?(self)
|
|
782
|
+
end
|
|
783
|
+
|
|
784
|
+
# 前のオブジェクト
|
|
785
|
+
#
|
|
786
|
+
# @return [When::Parts::Resource]
|
|
787
|
+
#
|
|
788
|
+
def prev
|
|
789
|
+
c = self
|
|
790
|
+
c = c.child[0] while c.child && c.child.size > 0
|
|
791
|
+
c = c._pool['.<-']
|
|
792
|
+
c = c.child[-1] while c && c.child && c.child.size > 0
|
|
793
|
+
c
|
|
794
|
+
end
|
|
795
|
+
|
|
796
|
+
# 次のオブジェクト
|
|
797
|
+
#
|
|
798
|
+
# @return [When::Parts::Resource]
|
|
799
|
+
#
|
|
800
|
+
def next
|
|
801
|
+
c = self
|
|
802
|
+
c = c.child[0] while c.child && c.child.size > 0
|
|
803
|
+
c._pool['.->']
|
|
804
|
+
end
|
|
805
|
+
alias :succ :next
|
|
806
|
+
|
|
807
|
+
# オブジェクト包含階層の末端か?
|
|
808
|
+
#
|
|
809
|
+
# @return [Boolean]
|
|
810
|
+
# [ true - IRIが付与された他のオブジェクトを包含していない ]
|
|
811
|
+
# [ false - IRIが付与された他のオブジェクトを包含している ]
|
|
812
|
+
#
|
|
813
|
+
def leaf?
|
|
814
|
+
!@child || (@child.length==0)
|
|
815
|
+
end
|
|
816
|
+
|
|
817
|
+
# IRIが付与されているか?
|
|
818
|
+
#
|
|
819
|
+
# @return [Boolean]
|
|
820
|
+
# [ true - IRIが付与されている ]
|
|
821
|
+
# [ false - IRIが付与されていない ]
|
|
822
|
+
#
|
|
823
|
+
def registered?
|
|
824
|
+
leaf = self
|
|
825
|
+
while leaf._pool['..'].respond_to?(:_pool)
|
|
826
|
+
root = leaf._pool['..']
|
|
827
|
+
return false unless leaf.equal?(root._pool[leaf.label])
|
|
828
|
+
leaf = root
|
|
829
|
+
end
|
|
830
|
+
Resource._pool.value?(leaf)
|
|
831
|
+
end
|
|
832
|
+
|
|
833
|
+
# When::BasicTypes::M17n の生成/参照
|
|
834
|
+
#
|
|
835
|
+
# @param [When::BasicTypes::M17n] source 処理を行わず、そのままsourceを返す
|
|
836
|
+
# @param [String] source locale と 文字列の対応
|
|
837
|
+
# @param [Array] source 要素を個別に解釈して生成したオブジェクトのArrayを返す
|
|
838
|
+
# @param [Hash] namespace prefix の指定
|
|
839
|
+
# @param [Array] locale locale の定義順序の指定
|
|
840
|
+
# @param [Hash] options (see {When::BasicTypes::M17n.new}[link:When/BasicTypes/M17n.html#method-c-new])
|
|
841
|
+
#
|
|
842
|
+
# @return [When::BasicTypes::M17n or Array<them>]
|
|
843
|
+
#
|
|
844
|
+
def m17n(source, namespace=nil, locale=nil, options={})
|
|
845
|
+
case source
|
|
846
|
+
when Array ; When::BasicTypes::M17n.new(source, namespace, locale, options)
|
|
847
|
+
when When::BasicTypes::M17n ; source
|
|
848
|
+
when String
|
|
849
|
+
return self[$1] if source =~ /\A\s*\[((\.{1,2}|::)+[^\]]+)\]/
|
|
850
|
+
When::BasicTypes::M17n.new(source, namespace, locale, options)
|
|
851
|
+
else ; raise TypeError, "Invalid Type: #{source.class}"
|
|
852
|
+
end
|
|
853
|
+
end
|
|
854
|
+
|
|
855
|
+
# 子オブジェクトを順に取り出す enumerator
|
|
856
|
+
#
|
|
857
|
+
def enum_for
|
|
858
|
+
@child.enum_for
|
|
859
|
+
end
|
|
860
|
+
alias :to_enum :enum_for
|
|
861
|
+
|
|
862
|
+
# Enumerator 生成のダミー
|
|
863
|
+
#
|
|
864
|
+
# @param [Object] other
|
|
865
|
+
#
|
|
866
|
+
# @return [Enumerator]
|
|
867
|
+
#
|
|
868
|
+
def ^(other)
|
|
869
|
+
return nil
|
|
870
|
+
end
|
|
871
|
+
|
|
872
|
+
# 順次実行
|
|
873
|
+
#
|
|
874
|
+
# @param [Array] args 各サブクラスの enum_for にそのまま渡す
|
|
875
|
+
# @param [Block] block 実行するブロック
|
|
876
|
+
#
|
|
877
|
+
# @return [Enumerator]
|
|
878
|
+
#
|
|
879
|
+
def each(*args, &block)
|
|
880
|
+
enum = enum_for(*args)
|
|
881
|
+
return enum unless block
|
|
882
|
+
enum.each(&block)
|
|
883
|
+
end
|
|
884
|
+
|
|
885
|
+
# map, collect の再定義
|
|
886
|
+
#
|
|
887
|
+
# has-a 関係の子 Resource に対して map/collect を行う
|
|
888
|
+
#
|
|
889
|
+
# @param [Block] block 実行するブロック
|
|
890
|
+
#
|
|
891
|
+
# @return [Array]
|
|
892
|
+
#
|
|
893
|
+
def map(&block)
|
|
894
|
+
@child.map(&block)
|
|
895
|
+
end
|
|
896
|
+
alias :collect :map
|
|
897
|
+
|
|
898
|
+
protected
|
|
899
|
+
|
|
900
|
+
# @private
|
|
901
|
+
def pool_keys
|
|
902
|
+
_pool.keys
|
|
903
|
+
end
|
|
904
|
+
|
|
905
|
+
private
|
|
906
|
+
|
|
907
|
+
# 属性の設定
|
|
908
|
+
def _attributes(args)
|
|
909
|
+
options =_get_options(args)
|
|
910
|
+
_set_variables(options)
|
|
911
|
+
return args, options
|
|
912
|
+
end
|
|
913
|
+
|
|
914
|
+
# option の読み出し
|
|
915
|
+
def _get_options(args)
|
|
916
|
+
options = args[-1].kind_of?(Hash) ? args.pop : {}
|
|
917
|
+
@_pool = {}
|
|
918
|
+
@_pool['..'] = options['..'] if (options['..'])
|
|
919
|
+
|
|
920
|
+
# 配下のオブジェクトの生成と関連付け
|
|
921
|
+
if (options.key?('.'))
|
|
922
|
+
_child(options)
|
|
923
|
+
end
|
|
924
|
+
|
|
925
|
+
options
|
|
926
|
+
end
|
|
927
|
+
|
|
928
|
+
# 変数の設定
|
|
929
|
+
def _set_variables(options)
|
|
930
|
+
@options = options[:options] || {} if options.key?(:options)
|
|
931
|
+
options.each_pair do |key,value|
|
|
932
|
+
unless (key =~ /\Aoptions$|^\.|^[A-Z]/)
|
|
933
|
+
case "#{key}"
|
|
934
|
+
when 'namespace' ; value = When::Locale._namespace(value)
|
|
935
|
+
when 'locale' ; value = When::Locale._locale(value)
|
|
936
|
+
end
|
|
937
|
+
instance_variable_set("@#{key}", value)
|
|
938
|
+
end
|
|
939
|
+
end
|
|
940
|
+
end
|
|
941
|
+
|
|
942
|
+
# 配下のオブジェクトの生成
|
|
943
|
+
def _child(options)
|
|
944
|
+
@child = []
|
|
945
|
+
query = options.dup
|
|
946
|
+
options['..'] = self
|
|
947
|
+
leaves = options.delete('.').map {|leaf| Resource._parse(leaf)}
|
|
948
|
+
key_list = []
|
|
949
|
+
properties = {}
|
|
950
|
+
label_candidates = nil
|
|
951
|
+
|
|
952
|
+
# ContentLine の処理(namespace, locale, altidの前処理)
|
|
953
|
+
leaves.each do |content|
|
|
954
|
+
next unless content.kind_of?(ContentLine)
|
|
955
|
+
key = content.predicate
|
|
956
|
+
value = content.object
|
|
957
|
+
next options.delete(key) unless value
|
|
958
|
+
case key
|
|
959
|
+
when 'namespace'
|
|
960
|
+
options[key] ||= {}
|
|
961
|
+
if content.attribute['altid']
|
|
962
|
+
options[key][content.attribute['prefix'].object] = content.object
|
|
963
|
+
else
|
|
964
|
+
options[key] = options[key].update(When::Locale._namespace(value))
|
|
965
|
+
end
|
|
966
|
+
when 'locale'
|
|
967
|
+
options[key] = When::Locale._locale(value)
|
|
968
|
+
else
|
|
969
|
+
_parse_altid(properties, content)
|
|
970
|
+
key_list << key unless key_list.include?(key)
|
|
971
|
+
end
|
|
972
|
+
end
|
|
973
|
+
|
|
974
|
+
# ContentLine の処理(一般)
|
|
975
|
+
key_list.each do |key|
|
|
976
|
+
content = properties[key][0]
|
|
977
|
+
value = content.same_altid ? When::BasicTypes::M17n.new(content, options['namespace'], []) : content.object
|
|
978
|
+
value = When::BasicTypes::M17n.new(value, nil, nil, options) if value.instance_of?(String) && value =~ /\A\s*\[/
|
|
979
|
+
@_pool[value.to_s] = value if value.kind_of?(When::BasicTypes::M17n)
|
|
980
|
+
if content.marked || key == self.class::LabelProperty
|
|
981
|
+
@label = value
|
|
982
|
+
else
|
|
983
|
+
options[key] = value
|
|
984
|
+
label_candidates ||= value
|
|
985
|
+
end
|
|
986
|
+
end
|
|
987
|
+
|
|
988
|
+
# Array の処理(子オブジェクトの生成)
|
|
989
|
+
leaves.each do |content|
|
|
990
|
+
next unless content.kind_of?(Array)
|
|
991
|
+
if content[0].kind_of?(Class)
|
|
992
|
+
list = []
|
|
993
|
+
content.each do |e|
|
|
994
|
+
if e.kind_of?(Hash)
|
|
995
|
+
list += e.keys.map {|key| Resource::ContentLine.new(key, e[key])}
|
|
996
|
+
else
|
|
997
|
+
list << e
|
|
998
|
+
end
|
|
999
|
+
end
|
|
1000
|
+
options['.'] = list
|
|
1001
|
+
@child << content[0].new(options.dup)
|
|
1002
|
+
else
|
|
1003
|
+
options.delete('.')
|
|
1004
|
+
@child << self.class.new(*(content + [options]))
|
|
1005
|
+
end
|
|
1006
|
+
end
|
|
1007
|
+
|
|
1008
|
+
# 代表ラベルの設定
|
|
1009
|
+
options.update(query)
|
|
1010
|
+
unless @label
|
|
1011
|
+
raise ArgumentError, "label attribute not found: #{options['.']}" unless label_candidates
|
|
1012
|
+
@label = label_candidates
|
|
1013
|
+
end
|
|
1014
|
+
end
|
|
1015
|
+
|
|
1016
|
+
# ALTIDを持つ ContentLine の解析
|
|
1017
|
+
def _parse_altid(properties, content)
|
|
1018
|
+
key = content.predicate
|
|
1019
|
+
properties[key] ||= []
|
|
1020
|
+
if content.attribute['altid']
|
|
1021
|
+
found = false
|
|
1022
|
+
(0...properties[key].length).to_a.each do |i|
|
|
1023
|
+
prev = properties[key][i]
|
|
1024
|
+
if prev.attribute['altid'] && prev.attribute['altid'].object == content.attribute['altid'].object
|
|
1025
|
+
content.same_altid = prev
|
|
1026
|
+
properties[key][i] = content
|
|
1027
|
+
found = true
|
|
1028
|
+
break
|
|
1029
|
+
end
|
|
1030
|
+
end
|
|
1031
|
+
end
|
|
1032
|
+
properties[key] << content unless found
|
|
1033
|
+
end
|
|
1034
|
+
|
|
1035
|
+
# 配下のオブジェクトの前後関係の設定
|
|
1036
|
+
def _sequence
|
|
1037
|
+
return unless @child
|
|
1038
|
+
prev = @_pool['..'].child[-1] if @_pool['..'].respond_to?(:child)
|
|
1039
|
+
@child.each do |v|
|
|
1040
|
+
if prev
|
|
1041
|
+
v._pool['.<-'] = prev
|
|
1042
|
+
prev._pool['.->'] = v
|
|
1043
|
+
while (prev.child && prev.child[-1]) do
|
|
1044
|
+
prev = prev.child[-1]
|
|
1045
|
+
prev._pool['.->'] = v
|
|
1046
|
+
end
|
|
1047
|
+
end
|
|
1048
|
+
@_pool[v.label.to_s] = v
|
|
1049
|
+
prev = v
|
|
1050
|
+
end
|
|
1051
|
+
end
|
|
1052
|
+
|
|
1053
|
+
alias :__method_missing :method_missing
|
|
1054
|
+
|
|
1055
|
+
# その他のメソッド
|
|
1056
|
+
# When::Parts::Resource で定義されていないメソッドは
|
|
1057
|
+
# 処理を @child (type: Array) に委譲する
|
|
1058
|
+
#
|
|
1059
|
+
def method_missing(name, *args, &block)
|
|
1060
|
+
return __method_missing(name, *args, &block) if When::Parts::MethodCash::Escape.key?(name)
|
|
1061
|
+
self.class.module_eval %Q{
|
|
1062
|
+
def #{name}(*args, &block)
|
|
1063
|
+
@child.send("#{name}", *args, &block)
|
|
1064
|
+
end
|
|
1065
|
+
} unless When::Parts::MethodCash.escape(name)
|
|
1066
|
+
@child.send(name, *args, &block)
|
|
1067
|
+
end
|
|
1068
|
+
end
|
|
1069
|
+
end
|