when_exe 0.2.100 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (193) hide show
  1. data/LICENSE.ja.txt +25 -25
  2. data/LICENSE.txt +31 -31
  3. data/bin/irb.rc +5 -0
  4. data/bin/locales.rb +2 -2
  5. data/bin/when.rb +16 -0
  6. data/bin/when.rb.config +7 -0
  7. data/lib/when_exe.rb +616 -14
  8. data/lib/when_exe/basictypes.rb +615 -0
  9. data/lib/when_exe/calendartypes.rb +1700 -0
  10. data/lib/when_exe/coordinates.rb +1936 -0
  11. data/lib/when_exe/core/compatibility.rb +54 -0
  12. data/lib/when_exe/core/duration.rb +72 -72
  13. data/lib/when_exe/core/extension.rb +382 -0
  14. data/lib/when_exe/ephemeris.rb +1845 -0
  15. data/lib/when_exe/googlecalendar.rb +140 -0
  16. data/lib/when_exe/icalendar.rb +1587 -0
  17. data/lib/when_exe/inspect.rb +1237 -0
  18. data/lib/when_exe/locales/af.rb +90 -0
  19. data/lib/when_exe/locales/ar.rb +145 -0
  20. data/lib/when_exe/locales/az.rb +90 -0
  21. data/lib/when_exe/locales/bg.rb +90 -0
  22. data/lib/when_exe/locales/bn.rb +94 -0
  23. data/lib/when_exe/locales/bs.rb +121 -0
  24. data/lib/when_exe/locales/ca.rb +92 -0
  25. data/lib/when_exe/locales/cs.rb +107 -0
  26. data/lib/when_exe/locales/cy.rb +150 -0
  27. data/lib/when_exe/locales/da.rb +84 -0
  28. data/lib/when_exe/locales/de.rb +92 -0
  29. data/lib/when_exe/locales/de_AT.rb +92 -0
  30. data/lib/when_exe/locales/de_CH.rb +92 -0
  31. data/lib/when_exe/locales/el.rb +93 -0
  32. data/lib/when_exe/locales/en.rb +88 -0
  33. data/lib/when_exe/locales/en_AU.rb +88 -0
  34. data/lib/when_exe/locales/en_CA.rb +88 -0
  35. data/lib/when_exe/locales/en_GB.rb +88 -0
  36. data/lib/when_exe/locales/en_IN.rb +88 -0
  37. data/lib/when_exe/locales/en_NZ.rb +88 -0
  38. data/lib/when_exe/locales/eo.rb +89 -0
  39. data/lib/when_exe/locales/es.rb +84 -0
  40. data/lib/when_exe/locales/es_419.rb +84 -0
  41. data/lib/when_exe/locales/es_AR.rb +84 -0
  42. data/lib/when_exe/locales/es_CL.rb +84 -0
  43. data/lib/when_exe/locales/es_CO.rb +84 -0
  44. data/lib/when_exe/locales/es_MX.rb +84 -0
  45. data/lib/when_exe/locales/es_PE.rb +85 -0
  46. data/lib/when_exe/locales/es_VE.rb +84 -0
  47. data/lib/when_exe/locales/et.rb +94 -0
  48. data/lib/when_exe/locales/eu.rb +95 -0
  49. data/lib/when_exe/locales/fa.rb +80 -0
  50. data/lib/when_exe/locales/fi.rb +89 -0
  51. data/lib/when_exe/locales/fr.rb +88 -0
  52. data/lib/when_exe/locales/fr_CA.rb +88 -0
  53. data/lib/when_exe/locales/fr_CH.rb +88 -0
  54. data/lib/when_exe/locales/gl.rb +81 -0
  55. data/lib/when_exe/locales/he.rb +84 -0
  56. data/lib/when_exe/locales/hi.rb +80 -0
  57. data/lib/when_exe/locales/hi_IN.rb +84 -0
  58. data/lib/when_exe/locales/hr.rb +128 -0
  59. data/lib/when_exe/locales/hu.rb +84 -0
  60. data/lib/when_exe/locales/id.rb +89 -0
  61. data/lib/when_exe/locales/is.rb +89 -0
  62. data/lib/when_exe/locales/it.rb +87 -0
  63. data/lib/when_exe/locales/it_CH.rb +87 -0
  64. data/lib/when_exe/locales/ja.rb +78 -0
  65. data/lib/when_exe/locales/kn.rb +86 -0
  66. data/lib/when_exe/locales/ko.rb +78 -0
  67. data/lib/when_exe/locales/links.rb +2342 -0
  68. data/lib/when_exe/locales/lo.rb +123 -0
  69. data/lib/when_exe/locales/locales.rb +91 -0
  70. data/lib/when_exe/locales/lt.rb +111 -0
  71. data/lib/when_exe/locales/lv.rb +118 -0
  72. data/lib/when_exe/locales/mk.rb +93 -0
  73. data/lib/when_exe/locales/mn.rb +80 -0
  74. data/lib/when_exe/locales/nb.rb +81 -0
  75. data/lib/when_exe/locales/ne.rb +81 -0
  76. data/lib/when_exe/locales/nl.rb +92 -0
  77. data/lib/when_exe/locales/nn.rb +73 -0
  78. data/lib/when_exe/locales/or.rb +84 -0
  79. data/lib/when_exe/locales/pl.rb +128 -0
  80. data/lib/when_exe/locales/pt.rb +88 -0
  81. data/lib/when_exe/locales/pt_BR.rb +88 -0
  82. data/lib/when_exe/locales/rm.rb +143 -0
  83. data/lib/when_exe/locales/ro.rb +105 -0
  84. data/lib/when_exe/locales/ru.rb +128 -0
  85. data/lib/when_exe/locales/sk.rb +109 -0
  86. data/lib/when_exe/locales/sl.rb +122 -0
  87. data/lib/when_exe/locales/sr.rb +122 -0
  88. data/lib/when_exe/locales/sv.rb +83 -0
  89. data/lib/when_exe/locales/sw.rb +89 -0
  90. data/lib/when_exe/locales/th.rb +78 -0
  91. data/lib/when_exe/locales/tl.rb +99 -0
  92. data/lib/when_exe/locales/tr.rb +96 -0
  93. data/lib/when_exe/locales/uk.rb +128 -0
  94. data/lib/when_exe/locales/uz.rb +128 -0
  95. data/lib/when_exe/locales/vi.rb +94 -0
  96. data/lib/when_exe/locales/wo.rb +82 -0
  97. data/lib/when_exe/locales/zh_CN.rb +77 -0
  98. data/lib/when_exe/locales/zh_HK.rb +77 -0
  99. data/lib/when_exe/locales/zh_TW.rb +77 -0
  100. data/lib/when_exe/mini_application.rb +252 -0
  101. data/lib/when_exe/parts/enumerator.rb +472 -0
  102. data/lib/when_exe/parts/geometric_complex.rb +379 -0
  103. data/lib/when_exe/parts/locale.rb +513 -0
  104. data/lib/when_exe/parts/method_cash.rb +207 -0
  105. data/lib/when_exe/parts/resource.rb +806 -0
  106. data/lib/when_exe/parts/timezone.rb +182 -0
  107. data/lib/when_exe/region/bahai.rb +145 -0
  108. data/lib/when_exe/region/balinese.rb +627 -0
  109. data/lib/when_exe/region/chinese.rb +896 -0
  110. data/lib/when_exe/region/chinese_calendar.rb +919 -0
  111. data/lib/when_exe/region/chinese_epoch.rb +1245 -0
  112. data/lib/when_exe/region/christian.rb +644 -0
  113. data/lib/when_exe/region/far_east.rb +192 -0
  114. data/lib/when_exe/region/french.rb +66 -0
  115. data/lib/when_exe/region/geologicalage.rb +639 -0
  116. data/lib/when_exe/region/indian.rb +1066 -0
  117. data/lib/when_exe/region/iranian.rb +66 -0
  118. data/lib/when_exe/region/islamic.rb +105 -0
  119. data/lib/when_exe/region/japanese.rb +851 -0
  120. data/lib/when_exe/region/japanese_notes.rb +964 -0
  121. data/lib/when_exe/region/japanese_residues.rb +1149 -0
  122. data/lib/when_exe/region/javanese.rb +228 -0
  123. data/lib/when_exe/region/jewish.rb +127 -0
  124. data/lib/when_exe/region/korean.rb +267 -0
  125. data/lib/when_exe/region/m17n.rb +115 -0
  126. data/lib/when_exe/region/martian.rb +215 -0
  127. data/lib/when_exe/region/mayan.rb +122 -0
  128. data/lib/when_exe/region/moon.rb +333 -0
  129. data/lib/when_exe/region/nihon_shoki.rb +73 -0
  130. data/lib/when_exe/region/planets.rb +585 -0
  131. data/lib/when_exe/region/pope.rb +298 -0
  132. data/lib/when_exe/region/residue.rb +229 -0
  133. data/lib/when_exe/region/roman.rb +325 -0
  134. data/lib/when_exe/region/ryukyu.rb +98 -0
  135. data/lib/when_exe/region/shire.rb +254 -0
  136. data/lib/when_exe/region/sun.rb +210 -0
  137. data/lib/when_exe/region/thai.rb +227 -0
  138. data/lib/when_exe/region/tibetan.rb +233 -0
  139. data/lib/when_exe/region/v50.rb +111 -0
  140. data/lib/when_exe/region/vietnamese.rb +173 -0
  141. data/lib/when_exe/region/world.rb +197 -0
  142. data/lib/when_exe/timestandard.rb +547 -0
  143. data/lib/when_exe/tmduration.rb +330 -330
  144. data/lib/when_exe/tmobjects.rb +1295 -0
  145. data/lib/when_exe/tmposition.rb +1955 -0
  146. data/lib/when_exe/tmreference.rb +1547 -0
  147. data/lib/when_exe/version.rb +10 -3
  148. data/link_to_online_documents +4 -0
  149. data/test/examples/JapanHolidays.ics +456 -0
  150. data/test/examples/Millennium.ics +17 -0
  151. data/test/examples/NewYork.ics +61 -0
  152. data/test/examples/Residue.m17n +135 -0
  153. data/test/examples/Spatial.m17n +179 -0
  154. data/test/examples/Terms.m17n +39 -0
  155. data/test/examples/Test.ics +53 -0
  156. data/test/examples/USA-DST.ics +61 -0
  157. data/test/examples/geometric_complex.rb +41 -0
  158. data/test/examples/sample.xml +14 -0
  159. data/test/examples/today.rb +61 -0
  160. data/test/test.rb +54 -19
  161. data/test/test.rb.config +1 -0
  162. data/test/test/basictypes.rb +368 -0
  163. data/test/test/calendartypes.rb +57 -0
  164. data/test/test/coordinates.rb +380 -0
  165. data/test/test/ephemeris.rb +127 -0
  166. data/test/test/googlecalendar.rb +167 -0
  167. data/test/test/icalendar.rb +848 -0
  168. data/test/test/inspect.rb +115 -0
  169. data/test/test/parts.rb +480 -0
  170. data/test/test/region/chinese.rb +161 -0
  171. data/test/test/region/french.rb +33 -0
  172. data/test/test/region/geologicalage.rb +14 -0
  173. data/test/test/region/indian.rb +55 -0
  174. data/test/test/region/iran.rb +54 -0
  175. data/test/test/region/islamic.rb +18 -0
  176. data/test/test/region/japanese.rb +62 -0
  177. data/test/test/region/jewish.rb +61 -0
  178. data/test/test/region/m17n.rb +181 -0
  179. data/test/test/region/mayan.rb +78 -0
  180. data/test/test/region/moon.rb +14 -0
  181. data/test/test/region/planets.rb +14 -0
  182. data/test/test/region/residue.rb +123 -0
  183. data/test/test/region/sun.rb +14 -0
  184. data/test/test/region/thai.rb +94 -0
  185. data/test/test/region/tibetan.rb +30 -0
  186. data/test/test/tmobjects.rb +356 -57
  187. data/test/test/tmposition.rb +237 -0
  188. data/test/test/tmreference.rb +95 -0
  189. data/when_exe.gemspec +2 -2
  190. metadata +187 -7
  191. data/doc/COPYING +0 -31
  192. data/doc/COPYING.ja +0 -25
  193. data/doc/document_url +0 -1
@@ -0,0 +1,379 @@
1
+ # -*- coding: utf-8 -*-
2
+ =begin
3
+ Copyright (C) 2011-2013 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
+ # 任意個の端点から構成する [Range] の subclass
15
+ #
16
+ class GeometricComplex < Range
17
+
18
+ include Comparable
19
+
20
+ # 範囲の反転
21
+ # @return [Boolean]
22
+ # [ true - 反転する ]
23
+ # [ false - 反転しない ]
24
+ #
25
+ # @note
26
+ # 無限の過去(-Infinity)を範囲に含むか否かと同値である
27
+ #
28
+ attr_reader :reverse
29
+
30
+ #
31
+ # When::Parts::GeometricComplex を構成する端点の Array
32
+ #
33
+ # @return [Array<Array<Comparable, Boolean>>]
34
+ # - Comparable - 端点
35
+ # - Boolean
36
+ # @reverse == true の場合
37
+ # true - 範囲に含まない
38
+ # false - 範囲に含む
39
+ # @reverse == false の場合
40
+ # true - 範囲に含む
41
+ # false - 範囲に含まない
42
+ #
43
+ # @example +[[3,true],[4,false]] は Range(3+...4)に対応する
44
+ #
45
+ attr_reader :node
46
+
47
+ # 最小の端点
48
+ #
49
+ # @param [Comparable] default 端点が-∞の場合に返すべき値(指定がなければ nil)
50
+ #
51
+ # @return [Comparable] 最小の端点
52
+ #
53
+ # @note
54
+ # 含むか否かに関わらず、最小の端点を返す。
55
+ # default が指定されているが有効な区間がない場合、nil を返す。
56
+ #
57
+ def first(default=nil)
58
+ return (@node.length==0) ? nil : @node[0][0] unless default # 互換性
59
+ if reverse
60
+ return default
61
+ else
62
+ (@node.length==0) ? nil : @node[0][0]
63
+ end
64
+ end
65
+ alias :begin :first
66
+
67
+ # 最大の端点
68
+ #
69
+ # @param [Comparable] default 端点が+∞場合に返すべき値(指定がなければ nil)
70
+ #
71
+ # @return [Comparable] 最大の端点
72
+ #
73
+ # @note
74
+ # 含むか否かに関わらず、最大の端点を返す
75
+ # default が指定されているが有効な区間がない場合、nil を返す
76
+ #
77
+ def last(default=nil)
78
+ return (@node.length==0) ? nil : @node[-1][0] unless default # 互換性
79
+ if reverse
80
+ return (@node.length[0]==0) ? default : @node[-1][0]
81
+ else
82
+ return nil if (@node.length==0)
83
+ return (@node.length[0]==1) ? default : @node[-1][0]
84
+ end
85
+ end
86
+ alias :end :last
87
+
88
+ # 端点が範囲に含まれるか?
89
+ #
90
+ # @param [Integer] index 端点の番号(デフォルト : -1 - 最大の端点)
91
+ #
92
+ # @return [Boolean]
93
+ # [ true - 含まれる ]
94
+ # [ false - 含まれない ]
95
+ #
96
+ def exclude_end?(index=-1)
97
+ (@node.length==0) ? nil : !@node[index][1] ^ @reverse
98
+ end
99
+
100
+ # 分解能
101
+ #
102
+ # @return [Integer] 最小の端点の分解能を返す
103
+ #
104
+ # @note
105
+ # 分解能がない場合は、When::SYSTEM を返す
106
+ #
107
+ def precision
108
+ @node[0] && @node[0][0].respond_to?(:precision) ? @node[0][0].precision : Coordinates::SYSTEM
109
+ end
110
+
111
+ # 範囲を反転する
112
+ #
113
+ # @return [When::Parts::GeometricComplex]
114
+ #
115
+ def -@
116
+ GeometricComplex.new(self, true)
117
+ end
118
+
119
+ # 最小の端点と other を比較する
120
+ #
121
+ # @param [Comparable] other 比較対象
122
+ #
123
+ # @return [Integer] 比較結果を 負, 0, 正の値で返す
124
+ #
125
+ def <=>(other)
126
+ first <=> other
127
+ end
128
+
129
+ # 和集合
130
+ #
131
+ # @param [Range, When::Parts::GeometricComplex] other
132
+ #
133
+ # @return [When::Parts::GeometricComplex] self と other の和集合を返す
134
+ #
135
+ def |(other)
136
+ other = GeometricComplex.new(other) unless other.kind_of?(GeometricComplex)
137
+ return self if self.reverse && self.node.length==0
138
+ return other | self if !self.reverse && other.reverse
139
+ copy = self.node.dup
140
+ ref = other.node.dup
141
+ max = _max(copy.shift.dup, ref.shift.dup) if (other.reverse)
142
+ rev = max ? false : @reverse
143
+ while (ref.length > 0) do
144
+ first, last, *ref = ref
145
+ updated = _upper(copy, first, rev)
146
+ updated += _lower(copy, last, rev) if last
147
+ copy = updated
148
+ end
149
+ copy = _lower(copy, max, true) if max
150
+ return GeometricComplex.new(copy, self.reverse)
151
+ end
152
+
153
+ # ISO19108 の TM オブジェクトに変換する
154
+ #
155
+ # @param [Hash] options When::TM::TemporalPosition の生成を行う場合に使用する
156
+ # (see {When::TM::TemporalPosition._instance})
157
+ #
158
+ # @return [When::TM::Node, When::TM::Edge, When::TM::TopologicalComplex]
159
+ #
160
+ def to_tm_object(options={})
161
+ return nil unless !@reverse && @node.length>0 && @node.length[0]==0
162
+ objects = []
163
+ primitives = @node.dup
164
+ while (primitives) do
165
+ first, last, primitives = primitives
166
+ if (first[0].eql?(last[0]))
167
+ objects = When::TM::Node.new(When::TM::Instant.new(When.when?(first[0],options)))
168
+ else
169
+ objects = When::TM::Edge.new(When::TM::Node.new(When::TM::Instant.new(When.when?(first[0],options))),
170
+ When::TM::Node.new(When::TM::Instant.new(When.when?(last[0],options))))
171
+ end
172
+ end
173
+ return objects[0] if objects.length==1
174
+ return When::TM::TopologicalComplex.new(objects)
175
+ end
176
+
177
+ # 範囲に含まれるか?
178
+ #
179
+ # @param [Comparable] other 判断する Comparable
180
+ #
181
+ # @return [Boolean]
182
+ # [ true - 範囲に含まれる ]
183
+ # [ false - 範囲に含まれない ]
184
+ #
185
+ # @note 制限事項
186
+ # When::TM::TopologicalComplex どうしの包含判定は、和集合がもとの範囲と等しいか
187
+ # で判断している。分解能が When::SYSTEM でない場合、論理的には等しいものが、
188
+ # 内部表現が異なるために等しくないとみなされる事があり、その場合 true であるべき
189
+ # ものを false と誤判断する。実行速度上の制約もあり、現時点では対策しない。
190
+ #
191
+ def include?(other)
192
+ if (other.kind_of?(Comparable) && !other.kind_of?(GeometricComplex))
193
+ return (_include_point?(other) != false)
194
+ else
195
+ other = GeometricComplex.new(other) unless other.kind_of?(GeometricComplex)
196
+ return _include_range?(other)
197
+ end
198
+ end
199
+ alias :=== :include?
200
+
201
+ # Enumerator._exclude 専用
202
+ # @private
203
+ def _include?(other)
204
+ if (other.kind_of?(Comparable) && !other.kind_of?(GeometricComplex))
205
+ return _include_point?(other)
206
+ else
207
+ other = GeometricComplex.new(other) unless other.kind_of?(GeometricComplex)
208
+ return _include_range?(other) && _include_point?(other.first)
209
+ end
210
+ end
211
+
212
+ # オブジェクトの生成
213
+ #
214
+ # @overload initialize(range, reverse=false)
215
+ # @param [Range] range
216
+ #
217
+ # @overload initialize(point, reverse=false)
218
+ # range = Range(point..point) と同じ
219
+ # @param [Comparable] point
220
+ #
221
+ # @overload initialize(first, last, reverse=false)
222
+ # range = Range(first...last) と同じ
223
+ # @param [Comparable] first
224
+ # @param [Comparable] last
225
+ #
226
+ # @overload initialize(first, duration, reverse=false)
227
+ # range = Range(first...(first+duration)) と同じ
228
+ # @param [Comparable] first
229
+ # @param [When::TM::Duration] duration
230
+ #
231
+ # @overload initialize(other, reverse=false)
232
+ # もとの When::Parts::GeometricComplex のコピー
233
+ # @param [When::Parts::GeometricComplex] other
234
+ #
235
+ # @overload initialize(node, reverse=false)
236
+ # 指定した node 構造の When::Parts::GeometricComplex を生成
237
+ # @param [Array<Array<Comparable, Boolean>>] note
238
+ # - Comparable - 端点
239
+ # - Boolean
240
+ # @reverse == true の場合
241
+ # true - 範囲に含まない
242
+ # false - 範囲に含む
243
+ # @reverse == false の場合
244
+ # true - 範囲に含む
245
+ # false - 範囲に含まない
246
+ # @note
247
+ # すべての呼び出しパターンに共通の最終引数 reverse を付けることができる
248
+ # reverse [Boolean]
249
+ # true - 反転する
250
+ # false - 反転しない
251
+ #
252
+ def initialize(*args)
253
+
254
+ @reverse = (args[-1]==true || args[-1]==false) ? args.pop : false
255
+
256
+ case args[0]
257
+ when GeometricComplex
258
+ @node = args[0].node
259
+ @reverse ^= args[0].reverse
260
+ super(self.first, self.last, exclude_end?) if self.first && self.last
261
+ return
262
+
263
+ when Array
264
+ @node = args[0]
265
+ super(self.first, self.last, exclude_end?) if self.first && self.last
266
+ return
267
+
268
+ when Range
269
+ first = [args[0].first, true]
270
+ last = [args[0].last, !args[0].exclude_end?]
271
+
272
+ when Comparable
273
+ first, last, rest = args
274
+ raise ArgumentError, "Too many argument: #{rest}" if rest
275
+ first = [first, true]
276
+ case last
277
+ when Comparable ; last = [last, false]
278
+ when When::TM::Duration ; last = [first[0] + last, false]
279
+ when nil ; last = first
280
+ else ; raise TypeError, "Irregal GeometricComplex Type for last element: #{last.class}"
281
+ end
282
+
283
+ when nil ;
284
+ else ; raise TypeError, "Irregal GeometricComplex Type: #{first.class}"
285
+ end
286
+
287
+ first, last = last, first if (first && last && first[0] > last[0])
288
+ @node = []
289
+ @node << first if first
290
+ @node << last if last
291
+ super(self.first, self.last, exclude_end?) if first && last
292
+ end
293
+
294
+ private
295
+
296
+ def _include_range?(other)
297
+ union = self | other
298
+ return false unless self.node == union.node
299
+ return self.reverse == union.reverse
300
+ end
301
+
302
+ def _include_point?(other)
303
+ @node.each_index do |i|
304
+ current = @node[i]
305
+ verify = other <=> current[0]
306
+ if (verify < 0)
307
+ return false if ((i[0]==0) ^ @reverse)
308
+ return @node[[0,i-1].max][0]
309
+ elsif (verify == 0)
310
+ return false unless (@reverse ^ current[1])
311
+ return current[0]
312
+ end
313
+ end
314
+ return (@reverse ? nil : false) if @node.length==0
315
+ return false if ((@node.length[0]==0) ^ @reverse)
316
+ return @node[-1][0]
317
+ end
318
+
319
+ def _upper(node, point, reverse)
320
+ node = node.dup
321
+ point = point.dup
322
+ point[1] = !point[1] if reverse
323
+ node.each_index do |i|
324
+ if (_verify(point, node[i], reverse) <= 0)
325
+ node[i..-1] = ((i[0]==0) ^ reverse) ? [point] : []
326
+ return node
327
+ end
328
+ end
329
+ node.push(point) if (node.length[0]==0) ^ @everse
330
+ return node
331
+ end
332
+
333
+ def _lower(node, point, reverse)
334
+ node = node.dup
335
+ point = point.dup
336
+ point[1] = !point[1] if reverse
337
+ (node.length-1).downto(0) do |i|
338
+ if (_verify(point, node[i], reverse) >= 0)
339
+ node[0..i] = ((i[0]==1) ^ reverse) ? [point] : []
340
+ return node
341
+ end
342
+ end
343
+ node.unshift(point) if (node.length[0]==0) ^ reverse
344
+ return node
345
+ end
346
+
347
+ def _verify(point, node, reverse)
348
+ verify = point[0] <=> node[0]
349
+ return verify unless verify == 0
350
+ if point[0].respond_to?(:precision) && node[0].respond_to?(:precision)
351
+ point[0] = node[0] if point[0].precision >= node[0].precision
352
+ end
353
+ if reverse
354
+ point[1] &= node[1]
355
+ else
356
+ point[1] |= node[1]
357
+ end
358
+ return verify
359
+ end
360
+
361
+ def _max(p1, p2)
362
+ p1[1] = !p1[1]
363
+ p2[1] = !p2[1]
364
+ verify = p1[0] <=> p2[0]
365
+ return p1 if (verify>0)
366
+ return p2 if (verify<0)
367
+ p1[1] |= p2[1]
368
+ return p1
369
+ end
370
+
371
+ # その他のメソッド
372
+ # When::Parts::GeometricComplex で定義されていないメソッドは
373
+ # 処理を first (type: When::TM::(Temporal)Position) に委譲する
374
+ #
375
+ def method_missing(name, *args, &block)
376
+ first.send(name.to_sym, *args, &block)
377
+ end
378
+ end
379
+ end
@@ -0,0 +1,513 @@
1
+ # -*- coding: utf-8 -*-
2
+ =begin
3
+ Copyright (C) 2011-2012 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
+ # Multilingualization(M17n) 対応モジュール
15
+ #
16
+ # When::BasicTypes::M17n の実装のうち When::BasicTypes 内部で
17
+ # 定義すべきでない部分を切り出してモジュールとしている
18
+ #
19
+ module Locale
20
+
21
+ # Locale 読み替えの初期設定
22
+ Alias = {'alias'=>'ja', '日本語'=>'ja', '英語'=>'en'}
23
+
24
+ # 漢字の包摂
25
+ DefaultUnification = {
26
+ '煕' => '熙',
27
+ '廣' => '広',
28
+ '寶' => '宝',
29
+ '國' => '国',
30
+ '應' => '応',
31
+ '觀' => '観',
32
+ '龜' => '亀',
33
+ '齊' => '斉',
34
+ '靈' => '霊',
35
+ '攝' => '摂',
36
+ '壽' => '寿',
37
+ '萬' => '万',
38
+ '廢' => '廃',
39
+ '顯' => '顕',
40
+ '會' => '会',
41
+ '聰' => '聡',
42
+ '總' => '総',
43
+ '證' => '証',
44
+ '禮' => '礼',
45
+ '竜' => '龍',
46
+ }
47
+
48
+ # @private
49
+ Escape = '__!_ESCAPE_%2C_!__'
50
+
51
+ class << self
52
+
53
+ # When::Parts::Locale Module のグローバルな設定を行う
54
+ #
55
+ # @param [Hash] aliases
56
+ # Locale の読み替えパターンを Hash で指定する。
57
+ # aliases の指定がない場合、aliases は Alias(モジュール定数)と解釈する。
58
+ #
59
+ def _setup_(aliases=nil)
60
+ @aliases = aliases || Alias
61
+ end
62
+
63
+ # 特定 locale に対応した文字列の取得
64
+ #
65
+ # @param [String] source もとにする String または M17n
66
+ #
67
+ # @param[String] loc locale の指定 ( lang[-|_]country.encode )
68
+ # [ lang - 言語 ]
69
+ # [ country - 国(省略可) ]
70
+ # [ encode - 文字コード(省略可) ]
71
+ #
72
+ # @return [String] loc に対応した文字列
73
+ #
74
+ # @note source が Hash や Array の場合、その構成要素を変換して返す
75
+ #
76
+ def translate(source, loc='')
77
+ return source unless loc
78
+ case source
79
+ when Hash
80
+ result = {}
81
+ source.each_pair do |key, value|
82
+ result[translate(key, loc)] = translate(value, loc)
83
+ end
84
+ return result
85
+ when Array
86
+ return source.map {|value| translate(value, loc)}
87
+ when Locale
88
+ return source.translate(loc)
89
+ when String
90
+ return source.encode($1) if loc =~ /\.(.+)$/
91
+ end
92
+ source
93
+ end
94
+
95
+ # 包摂リストに登録されている文字を包摂する
96
+ #
97
+ # @param [When::Parts::Locale] source 文字を包摂しようとする国際化文字列
98
+ # @param [String] source 文字を包摂しようとする文字列
99
+ # @param [Regexp] source 文字を包摂しようとする正規表現
100
+ # @param [Hash] pattern 包摂ルール
101
+ #
102
+ # @return [When::Parts::Locale] 文字を包摂した国際化文字列
103
+ # @return [String] 文字を包摂した文字列
104
+ # @return [Regexp] 文字を包摂した正規表現
105
+ #
106
+ def ideographic_unification(source, pattern=DefaultUnification)
107
+ case source
108
+ when When::Parts::Locale
109
+ source.ideographic_unification(pattern)
110
+ when Regexp
111
+ Regexp.compile(ideographic_unification(source.source.encode('UTF-8'), pattern), source.options)
112
+ when String
113
+ source.gsub(/./) do |c|
114
+ pattern[c] ? pattern[c] : c
115
+ end
116
+ else
117
+ source
118
+ end
119
+ end
120
+
121
+ # 文字列で表現された namespace 指定を Hash に変換する
122
+ # @private
123
+ def _namespace(source=nil)
124
+ case source
125
+ when Hash ; return source
126
+ when nil ; return {}
127
+ when String
128
+ namespace = {}
129
+ source = $1 if (source=~/\A\s*\[?(.+?)\]?\s*\z/m)
130
+ source.split(/[\n\r,]+/).each do |v|
131
+ v.strip!
132
+ next if (v=~/^#/)
133
+ pair = [''] + v.split(/\s*=\s*/, 2)
134
+ namespace[pair[-2]] = pair[-1]
135
+ end
136
+ return namespace
137
+ else ; raise TypeError, "Irregal Namespace Type"
138
+ end
139
+ end
140
+
141
+ # locale 指定を Array に変換する
142
+ # @private
143
+ def _locale(source=nil)
144
+ # default の Locale
145
+ return [[nil, '', nil]] unless source
146
+
147
+ # source の配列化
148
+ if source.kind_of?(String)
149
+ source = $1 if (source=~/\A\s*\[?(.+?)\]?\s*\z/m)
150
+ source = source.split(/[\n\r,]+/)
151
+ end
152
+
153
+ # 各Localeの展開
154
+ source.map {|v|
155
+ if v.kind_of?(String)
156
+ v = v.strip
157
+ next if (v=~/^#/)
158
+ (v =~ /^(\*)?(.*?)(?:\s*=\s*(.+))?$/) ? $~[1..3] : [[nil, '', nil]]
159
+ else
160
+ v
161
+ end
162
+ }.compact
163
+ end
164
+
165
+ # 文字列 [.., .., ..] を分割する
166
+ # @private
167
+ def _split(line)
168
+ line = line.dup
169
+ b = d = s = 0
170
+ (line.length-1).downto(0) do |i|
171
+ bs = 0
172
+ (i-1).downto(0) do |k|
173
+ break unless (line[k,1] == '\\')
174
+ bs += 1
175
+ end
176
+ next if (bs[0] == 1)
177
+ case line[i,1]
178
+ when "'" ; s = 1-s if (d == 0)
179
+ when '"' ; d = 1-d if (s == 0)
180
+ when ']' ; b += 1 if (d+s == 0)
181
+ when '[' ; b -= 1 if (d+s == 0 && b > 0)
182
+ when ',' ; line[i,1] = Escape if (b+d+s == 0)
183
+ end
184
+ end
185
+ return (line =='') ? [''] : line.split(Escape, -1)
186
+ end
187
+
188
+ # locale 指定を解析して Hash の値を取り出す
189
+ # @private
190
+ def _hash_value(hash, locale, default='')
191
+ locale = locale.sub(/\..*/, '').sub(/-/,'_')
192
+ return hash[locale] if (hash[locale])
193
+ return _hash_value(hash, _alias[locale], default) if (_alias[locale])
194
+ language = locale.sub(/_.*/, '')
195
+ return hash[language] if (hash[language])
196
+ return hash[default]
197
+ end
198
+
199
+ private
200
+
201
+ def _alias
202
+ @aliases || Alias
203
+ end
204
+ end
205
+
206
+ # ローケール指定時の文字列
207
+ #
208
+ # @return [Hash]
209
+ attr_reader :names
210
+
211
+ # 有効なローケール指定
212
+ #
213
+ # @return [Array<String>]
214
+ attr_reader :keys
215
+
216
+ # 有効な文字列 - additional attribute
217
+ #
218
+ # @return [Array<String>]
219
+ attr_reader :values
220
+
221
+ # 文字列の説明 - additional attribute
222
+ #
223
+ # @return [Hash] { anyURI }
224
+ attr_reader :link
225
+
226
+ # Rails 用 I18n 定義へのアクセス・キー
227
+ #
228
+ # @return [String]
229
+ attr_reader :access_key
230
+ protected :access_key
231
+
232
+ # 特定 locale に対応した文字列の取得
233
+ #
234
+ # @param [String] loc locale の指定 ( lang[-|_]country.encode )
235
+ # [ lang - 言語 ]
236
+ # [ country - 国(省略可) ]
237
+ # [ encode - 文字コード(省略可) ]
238
+ #
239
+ # @return [String] loc に対応した文字列
240
+ #
241
+ def translate(loc='')
242
+ return to_s unless loc
243
+ lang, code = loc.split(/\./)
244
+ result = _label_value(loc)
245
+ return result if !code || @names.member?(loc)
246
+ return result.encode(code)
247
+ end
248
+ alias :/ :translate
249
+
250
+ # 特定 locale に対応した reference URI の取得
251
+ #
252
+ # @param [String] loc locale の指定
253
+ #
254
+ # @return [String] loc に対応した reference URI
255
+ #
256
+ def reference(loc='')
257
+ loc ||= ''
258
+ return Locale._hash_value(@link, loc)
259
+ end
260
+
261
+ # 部分文字列
262
+ #
263
+ # @param [Range] range String#[] と同様の指定方法で範囲を指定する
264
+ #
265
+ # @return [When::Parts::Locale] 指定範囲に対応した部分文字列
266
+ #
267
+ def [](range)
268
+ dup._copy({
269
+ :label => to_s[range],
270
+ :names => @names.keys.inject({}) {|l,k|
271
+ l[k] = @names[k][range]
272
+ l
273
+ }
274
+ })
275
+ end
276
+
277
+ # 文字列の一致
278
+ #
279
+ # @param [String, Regexp] regexp マッチする正規表現
280
+ #
281
+ # @return [Integer] マッチした位置のindex(いずれかの locale でマッチが成功した場合)
282
+ # @return [nil] すべての locale でマッチに失敗した場合
283
+ #
284
+ def =~(regexp)
285
+ @keys.each do |key|
286
+ index = (@names[key] =~ regexp)
287
+ return index if index
288
+ end
289
+ return nil
290
+ end
291
+
292
+ # 文字列の連結
293
+ #
294
+ # @param [String, When::Toos::Locale] other 連結する文字列
295
+ #
296
+ # @return [When::Toos::Locale] 連結された文字列
297
+ #
298
+ def +(other)
299
+ names = {}
300
+ case other
301
+ when Locale
302
+ (@names.keys + other.names.keys).uniq.each do |key|
303
+ names[key] = _label_value(key) + other._label_value(key)
304
+ end
305
+ else
306
+ @names.keys.each do |key|
307
+ names[key] = _label_value(key) + other.to_s
308
+ end
309
+ end
310
+ return dup._copy({:names=>names, :label=>to_s + other.to_s})
311
+ end
312
+
313
+ # 書式指定による文字列化
314
+ #
315
+ # @param [Array<Object>] other 文字列化する Object の Array
316
+ # @param [Array<String>] locale 文字列化を行う locale の指定(デフォルト : すべて)
317
+ #
318
+ # @return [When::Toos::Locale] 文字列化された Object
319
+ #
320
+ def _printf(other, locale=nil)
321
+ # 処理する配列
322
+ terms = other.kind_of?(Array) ? [self] + other : [self, other]
323
+
324
+ # locale key の配列
325
+ if locale == []
326
+ keys = []
327
+ else
328
+ keys = terms.inject([]) {|k,t|
329
+ k += t.keys if t.kind_of?(Locale)
330
+ k
331
+ }.uniq
332
+ if locale
333
+ locale = [locale] unless locale.kind_of?(Array)
334
+ keys = locale | (locale & keys)
335
+ end
336
+ end
337
+ keys << nil if keys.include?('')
338
+
339
+ # names ハッシュ
340
+ names = keys.inject({}) {|l,k|
341
+ l[k] = When::Coordinates::Pair._format(
342
+ (block_given? ? yield(k, *terms) : terms).map {|t|
343
+ t.kind_of?(Locale) ? t.translate(k) : t
344
+ }
345
+ )
346
+ l
347
+ }
348
+
349
+ # 生成
350
+ # @private
351
+ dup._copy({
352
+ :label => keys.include?('') ? names.delete(nil) : (names[''] = names[keys[0]]),
353
+ :names => names
354
+ })
355
+ end
356
+ alias :% :_printf
357
+
358
+ # ローケールの更新
359
+ #
360
+ # @param [Hash] options 下記の通り
361
+ # @option options [String] カントリーコード 表現文字列
362
+ # @option options [Hash] :link { カントリーコード => 参照URL文字列 }
363
+ # @option options [String] :code_space 規格や辞書を特定するコードスペースのURL文字列
364
+ # @option options [String] :label 代表文字列
365
+ # @note Hashキーはすべて Optional で、存在するもののみ更新します
366
+ #
367
+ # @return [self] 更新された Object
368
+ #
369
+ def update(options={})
370
+ options = options.dup
371
+ @link.update(options.delete(:link)) if (options.key?(:link))
372
+ @code_space = options.delete(:code_space) if (options.key?(:code_space))
373
+ self[0..-1] = options.delete(:label) if (options.key?(:label))
374
+ unless (options.empty?)
375
+ @names.update(options)
376
+ @keys = @names.keys.sort
377
+ @values = @names.values.sort.reverse
378
+ end
379
+ return self
380
+ end
381
+
382
+ # 包摂リストに登録されている文字を包摂する(自己破壊)
383
+ #
384
+ # @param [Hash] pattern 包摂ルール
385
+ #
386
+ # @return [When::Parts::Locale] self
387
+ # @private
388
+ def ideographic_unification!(pattern=DefaultUnification)
389
+ names = {}
390
+ @names.each_pair do |key, value|
391
+ names[key] = Locale.ideographic_unification(value, pattern)
392
+ end
393
+ @names = names
394
+ @values = @names.values.sort.reverse
395
+ self[0..-1] = Locale.ideographic_unification(self.to_s[0..-1], pattern)
396
+ return self
397
+ end
398
+ protected :ideographic_unification!
399
+
400
+ # 包摂リストに登録されている文字を包摂する(自己保存)
401
+ #
402
+ # @param [Hash] pattern 包摂ルール
403
+ #
404
+ # @return [When::Parts::Locale] 包摂結果
405
+ #
406
+ def ideographic_unification(pattern=DefaultUnification)
407
+ dup.ideographic_unification!(pattern)
408
+ end
409
+
410
+ # 閏の表記を扱うための書式付整形
411
+ # @private
412
+ def prefix(other, locale=nil)
413
+ return self.dup unless other
414
+ other = m17n(other) unless other.kind_of?(Locale)
415
+ other._printf(self, locale) do |k, *t|
416
+ t[0] = t[0].translate(k)
417
+ t[0] += "%s" unless t[0] =~ /%[-+]?[.\d]*s/
418
+ t
419
+ end
420
+ end
421
+
422
+ protected
423
+
424
+ # @private
425
+ def _copy(options={})
426
+ if (options.key?(:names))
427
+ @names = options[:names]
428
+ @keys = @names.keys.sort
429
+ @values = @names.values.compact.sort.reverse
430
+ end
431
+ @link = options[:link] if (options.key?(:link))
432
+ @code_space = options[:code_space] if (options.key?(:code_space))
433
+ @access_key = options[:access_key] if (options.key?(:access_key))
434
+ self[0..-1] = options[:label] if (options.key?(:label))
435
+ return self
436
+ end
437
+
438
+ # @private
439
+ def _copy_all(other)
440
+ _copy({:names => other.names,
441
+ :link => other.link,
442
+ :code_space => other.code_space,
443
+ :access_key => other.access_key,
444
+ :label => other.to_s
445
+ })
446
+ end
447
+
448
+ # locale 指定を解析して @names の値を取り出す
449
+ # @private
450
+ def _label_value(locale)
451
+ label = Locale._hash_value(@names, locale, nil)
452
+ return label if label
453
+ addition = When::BasicTypes::M17n._get_locale(locale, @access_key)
454
+ return @names[''] unless addition
455
+ update(addition)
456
+ return Locale._hash_value(@names, locale)
457
+ end
458
+
459
+ private
460
+
461
+ def _names(names, namespace, default_locale)
462
+
463
+ # names, link の組み立て
464
+ @names = {}
465
+ @link = {}
466
+
467
+ if (names.kind_of?(String))
468
+ unless (names=~/\A\s*\[(.+?)\]\s*\z/m)
469
+ names = names.strip
470
+ @names[''] = names
471
+ @keys = ['']
472
+ @values = [names]
473
+ return names
474
+ end
475
+ names = $1.split(/[\n\r,]+/)
476
+ end
477
+
478
+ mark = []
479
+ asterisk = []
480
+ default_locale = default_locale.dup
481
+ names.each do |v|
482
+ v.strip!
483
+ case v
484
+ when '', /^#/ ;
485
+ when /^\/(.+)/; @access_key = $1
486
+ when /^(\*)?(?:([^=%]*?)\s*:)?\s*(.+?)\s*(=\s*(.+?)?)?$/
487
+ asterisk[0], locale, name, assignment, ref = $~[1..5]
488
+ asterisk[1], locale, default_ref = default_locale.shift unless locale
489
+ locale ||= ''
490
+ ref ||= default_ref unless (assignment)
491
+ ref ||= ''
492
+ mark[0] = locale if asterisk[0]
493
+ mark[1] = locale if asterisk[1]
494
+ mark[2] = locale unless mark[2]
495
+ @names[locale] = name
496
+ if (ref =~ /^(.+):/)
497
+ prefix = namespace[$1]
498
+ ref.sub!(/^.+:/, prefix) if (prefix)
499
+ end
500
+ ref += URI.encode(name) if (ref =~ /[\/#:]$/)
501
+ @link[locale] = ref
502
+ else ; raise ArgumentError, "Irregal locale format"
503
+ end
504
+ end
505
+
506
+ # keys, values の準備
507
+ @keys = @names.keys.sort
508
+ @values = @names.values.sort.reverse
509
+
510
+ return @names[mark[0] || mark[1] || mark[2]]
511
+ end
512
+ end
513
+ end