when_exe 0.3.4 → 0.3.5

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.
Files changed (168) hide show
  1. data/bin/locales.rb +2 -2
  2. data/bin/when.rb +2 -2
  3. data/lib/when_exe.rb +161 -55
  4. data/lib/when_exe/basictypes.rb +34 -26
  5. data/lib/when_exe/calendarnote.rb +654 -0
  6. data/lib/when_exe/calendartypes.rb +49 -474
  7. data/lib/when_exe/coordinates.rb +141 -34
  8. data/lib/when_exe/core/compatibility.rb +22 -2
  9. data/lib/when_exe/core/extension.rb +47 -3
  10. data/lib/when_exe/ephemeris.rb +82 -109
  11. data/lib/when_exe/googlecalendar.rb +1 -1
  12. data/lib/when_exe/icalendar.rb +26 -14
  13. data/lib/when_exe/inspect.rb +82 -68
  14. data/lib/when_exe/locales/af.rb +1 -1
  15. data/lib/when_exe/locales/ar.rb +1 -1
  16. data/lib/when_exe/locales/az.rb +1 -1
  17. data/lib/when_exe/locales/bg.rb +1 -1
  18. data/lib/when_exe/locales/bn.rb +1 -1
  19. data/lib/when_exe/locales/bs.rb +1 -1
  20. data/lib/when_exe/locales/ca.rb +1 -1
  21. data/lib/when_exe/locales/cs.rb +1 -1
  22. data/lib/when_exe/locales/cy.rb +1 -1
  23. data/lib/when_exe/locales/da.rb +1 -1
  24. data/lib/when_exe/locales/de.rb +1 -1
  25. data/lib/when_exe/locales/de_AT.rb +1 -1
  26. data/lib/when_exe/locales/de_CH.rb +1 -1
  27. data/lib/when_exe/locales/el.rb +1 -1
  28. data/lib/when_exe/locales/en.rb +1 -1
  29. data/lib/when_exe/locales/en_AU.rb +1 -1
  30. data/lib/when_exe/locales/en_CA.rb +1 -1
  31. data/lib/when_exe/locales/en_GB.rb +1 -1
  32. data/lib/when_exe/locales/en_IE.rb +1 -1
  33. data/lib/when_exe/locales/en_IN.rb +1 -1
  34. data/lib/when_exe/locales/en_NZ.rb +1 -1
  35. data/lib/when_exe/locales/en_US.rb +1 -1
  36. data/lib/when_exe/locales/eo.rb +1 -1
  37. data/lib/when_exe/locales/es.rb +1 -1
  38. data/lib/when_exe/locales/es_419.rb +1 -1
  39. data/lib/when_exe/locales/es_AR.rb +1 -1
  40. data/lib/when_exe/locales/es_CL.rb +1 -1
  41. data/lib/when_exe/locales/es_CO.rb +1 -1
  42. data/lib/when_exe/locales/es_CR.rb +1 -1
  43. data/lib/when_exe/locales/es_EC.rb +1 -1
  44. data/lib/when_exe/locales/es_MX.rb +1 -1
  45. data/lib/when_exe/locales/es_PA.rb +1 -1
  46. data/lib/when_exe/locales/es_PE.rb +1 -1
  47. data/lib/when_exe/locales/es_VE.rb +1 -1
  48. data/lib/when_exe/locales/et.rb +1 -1
  49. data/lib/when_exe/locales/eu.rb +1 -1
  50. data/lib/when_exe/locales/fa.rb +1 -1
  51. data/lib/when_exe/locales/fi.rb +1 -1
  52. data/lib/when_exe/locales/fr.rb +1 -1
  53. data/lib/when_exe/locales/fr_CA.rb +1 -1
  54. data/lib/when_exe/locales/fr_CH.rb +1 -1
  55. data/lib/when_exe/locales/gl.rb +1 -1
  56. data/lib/when_exe/locales/he.rb +1 -1
  57. data/lib/when_exe/locales/hi.rb +1 -1
  58. data/lib/when_exe/locales/hi_IN.rb +1 -1
  59. data/lib/when_exe/locales/hr.rb +1 -1
  60. data/lib/when_exe/locales/hu.rb +1 -1
  61. data/lib/when_exe/locales/id.rb +1 -1
  62. data/lib/when_exe/locales/is.rb +1 -1
  63. data/lib/when_exe/locales/it.rb +1 -1
  64. data/lib/when_exe/locales/it_CH.rb +1 -1
  65. data/lib/when_exe/locales/ja.rb +1 -1
  66. data/lib/when_exe/locales/kn.rb +1 -1
  67. data/lib/when_exe/locales/ko.rb +1 -1
  68. data/lib/when_exe/locales/lo.rb +1 -1
  69. data/lib/when_exe/locales/locales.rb +1 -1
  70. data/lib/when_exe/locales/lt.rb +1 -1
  71. data/lib/when_exe/locales/lv.rb +1 -1
  72. data/lib/when_exe/locales/mk.rb +1 -1
  73. data/lib/when_exe/locales/mn.rb +1 -1
  74. data/lib/when_exe/locales/ms.rb +1 -1
  75. data/lib/when_exe/locales/nb.rb +1 -1
  76. data/lib/when_exe/locales/ne.rb +1 -1
  77. data/lib/when_exe/locales/nl.rb +1 -1
  78. data/lib/when_exe/locales/nn.rb +1 -1
  79. data/lib/when_exe/locales/or.rb +1 -1
  80. data/lib/when_exe/locales/pl.rb +1 -1
  81. data/lib/when_exe/locales/pt.rb +1 -1
  82. data/lib/when_exe/locales/pt_BR.rb +1 -1
  83. data/lib/when_exe/locales/rm.rb +1 -1
  84. data/lib/when_exe/locales/ro.rb +1 -1
  85. data/lib/when_exe/locales/ru.rb +1 -1
  86. data/lib/when_exe/locales/sk.rb +1 -1
  87. data/lib/when_exe/locales/sl.rb +1 -1
  88. data/lib/when_exe/locales/sr.rb +1 -1
  89. data/lib/when_exe/locales/sv.rb +1 -1
  90. data/lib/when_exe/locales/sw.rb +1 -1
  91. data/lib/when_exe/locales/th.rb +1 -1
  92. data/lib/when_exe/locales/tl.rb +1 -1
  93. data/lib/when_exe/locales/tr.rb +1 -1
  94. data/lib/when_exe/locales/uk.rb +1 -1
  95. data/lib/when_exe/locales/ur.rb +1 -1
  96. data/lib/when_exe/locales/uz.rb +1 -1
  97. data/lib/when_exe/locales/vi.rb +1 -1
  98. data/lib/when_exe/locales/wo.rb +1 -1
  99. data/lib/when_exe/locales/zh_CN.rb +1 -1
  100. data/lib/when_exe/locales/zh_HK.rb +1 -1
  101. data/lib/when_exe/locales/zh_TW.rb +1 -1
  102. data/lib/when_exe/mini_application.rb +6 -2
  103. data/lib/when_exe/parts/enumerator.rb +13 -8
  104. data/lib/when_exe/parts/geometric_complex.rb +3 -5
  105. data/lib/when_exe/parts/locale.rb +185 -28
  106. data/lib/when_exe/parts/method_cash.rb +20 -10
  107. data/lib/when_exe/parts/resource.rb +154 -76
  108. data/lib/when_exe/parts/timezone.rb +11 -6
  109. data/lib/when_exe/region/bahai.rb +2 -2
  110. data/lib/when_exe/region/balinese.rb +296 -296
  111. data/lib/when_exe/region/chinese.rb +564 -564
  112. data/lib/when_exe/region/chinese_calendar.rb +5 -1
  113. data/lib/when_exe/region/chinese_epoch.rb +47 -102
  114. data/lib/when_exe/region/chinese_twin.rb +798 -0
  115. data/lib/when_exe/region/christian.rb +314 -338
  116. data/lib/when_exe/region/coptic.rb +88 -0
  117. data/lib/when_exe/region/ephemeric_notes.rb +322 -307
  118. data/lib/when_exe/region/french.rb +2 -2
  119. data/lib/when_exe/region/indian.rb +361 -272
  120. data/lib/when_exe/region/iranian.rb +2 -2
  121. data/lib/when_exe/region/islamic.rb +3 -3
  122. data/lib/when_exe/region/japanese.rb +1 -1
  123. data/lib/when_exe/region/japanese_notes.rb +165 -103
  124. data/lib/when_exe/region/japanese_residues.rb +56 -55
  125. data/lib/when_exe/region/japanese_twin.rb +228 -0
  126. data/lib/when_exe/region/javanese.rb +2 -2
  127. data/lib/when_exe/region/jewish.rb +2 -2
  128. data/lib/when_exe/region/korean.rb +4 -4
  129. data/lib/when_exe/region/m17n.rb +19 -19
  130. data/lib/when_exe/region/martian.rb +21 -9
  131. data/lib/when_exe/region/mayan.rb +19 -11
  132. data/lib/when_exe/region/moon.rb +7 -7
  133. data/lib/when_exe/region/nihon_shoki.rb +7 -7
  134. data/lib/when_exe/region/roman.rb +100 -100
  135. data/lib/when_exe/region/shire.rb +130 -147
  136. data/lib/when_exe/region/thai.rb +2 -2
  137. data/lib/when_exe/region/tibetan.rb +2 -2
  138. data/lib/when_exe/region/vietnamese.rb +383 -114
  139. data/lib/when_exe/region/world.rb +112 -129
  140. data/lib/when_exe/timestandard.rb +12 -1
  141. data/lib/when_exe/tmposition.rb +28 -14
  142. data/lib/when_exe/tmreference.rb +96 -93
  143. data/lib/when_exe/version.rb +1 -1
  144. data/test/examples/Terms.m17n +2 -2
  145. data/test/examples/sample.json +16 -0
  146. data/test/examples/sample.xml +1 -1
  147. data/test/test.rb +4 -0
  148. data/test/test/basictypes.rb +2 -2
  149. data/test/test/calendarnote.rb +69 -0
  150. data/test/test/calendartypes.rb +41 -1
  151. data/test/test/coordinates.rb +12 -1
  152. data/test/test/ephemeris.rb +13 -66
  153. data/test/test/icalendar.rb +3 -3
  154. data/test/test/inspect.rb +1 -1
  155. data/test/test/parts.rb +7 -4
  156. data/test/test/region/chinese.rb +45 -0
  157. data/test/test/region/coptic.rb +27 -0
  158. data/test/test/region/indian.rb +1 -1
  159. data/test/test/region/japanese.rb +4 -4
  160. data/test/test/region/jewish.rb +1 -1
  161. data/test/test/region/m17n.rb +7 -5
  162. data/test/test/region/residue.rb +2 -2
  163. data/test/test/region/vietnamese.rb +102 -0
  164. data/test/test/timestandard.rb +81 -0
  165. data/test/test/tmposition.rb +1 -1
  166. data/test/test/tmreference.rb +1 -1
  167. data/when_exe.gemspec +2 -2
  168. metadata +16 -7
@@ -257,13 +257,11 @@ module When::Parts
257
257
  when GeometricComplex
258
258
  @node = args[0].node
259
259
  @reverse ^= args[0].reverse
260
- super(self.first, self.last, exclude_end?) if self.first && self.last
261
- return
260
+ return super(self.first||-Float::INFINITY, self.last||+Float::INFINITY, exclude_end?)
262
261
 
263
262
  when Array
264
263
  @node = args[0]
265
- super(self.first, self.last, exclude_end?) if self.first && self.last
266
- return
264
+ return super(self.first||-Float::INFINITY, self.last||+Float::INFINITY, exclude_end?)
267
265
 
268
266
  when Range
269
267
  first = [args[0].first, true]
@@ -288,7 +286,7 @@ module When::Parts
288
286
  @node = []
289
287
  @node << first if first
290
288
  @node << last if last
291
- super(self.first, self.last, exclude_end?) if first && last
289
+ super(self.first||-Float::INFINITY, self.last||+Float::INFINITY, exclude_end?)
292
290
  end
293
291
 
294
292
  private
@@ -54,21 +54,47 @@ module When::Parts
54
54
  "\\," => ","
55
55
  }
56
56
 
57
+ # Wikipedia の URL の正規表現
58
+ # @private
59
+ Ref = /^http:\/\/(.+?)\.wikipedia\.org\/wiki\/([^#]+?)$/
60
+
61
+ # Wikipedia の多言語リンクの正規表現
62
+ # @private
63
+ Link = /<li class="interlanguage-link interwiki-(.+?)"><a href="\/\/(.+?)\.wikipedia\.org\/wiki\/(.+?)" title="(.+?) – /
64
+
57
65
  class << self
58
66
 
67
+ # Wikipedia の連続的な参照を抑制するための遅延時間/秒
68
+ #
69
+ # @return [Numeric]
70
+ #
71
+ attr_accessor :wikipedia_interval
72
+
59
73
  # When::Parts::Locale Module のグローバルな設定を行う
60
74
  #
61
75
  # @param [Hash] options 下記の通り
62
- # @option options [Hash] :alias Locale の読み替えパターンを Hash で指定する。
63
- # @option options [Hash] :unification 漢字の包摂パターンを Hash で指定する。
76
+ # @option options [Hash] :alias Locale の読み替えパターンを Hash で指定する。
77
+ # @option options [Hash] :unification 漢字の包摂パターンを Hash で指定する。
78
+ # @option options [Numeric] :wikipedia_interval Wikipedia の連続的な参照を抑制するための遅延時間/秒
64
79
  #
65
80
  # @note
66
81
  # :alias の指定がない場合、aliases は DefaultAlias(モジュール定数)と解釈する。
67
82
  # :unification の指定がない場合、unifications は DefaultUnification(モジュール定数)と解釈する。
68
83
  #
69
84
  def _setup_(options={})
70
- @aliases = options[:alias] || DefaultAlias
71
- @unifications = options[:unification] || DefaultUnification
85
+ @aliases = options[:alias] || DefaultAlias
86
+ @unifications = options[:unification] || DefaultUnification
87
+ @wikipedia_interval = options[:wikipedia_interval]
88
+ end
89
+
90
+ # 設定情報を取得する
91
+ #
92
+ # @return [Hash] 設定情報
93
+ #
94
+ def _setup_info
95
+ {:alias => _alias,
96
+ :unification => _unification,
97
+ :wikipedia_interval => @wikipedia_interval}
72
98
  end
73
99
 
74
100
  # 特定 locale に対応した文字列の取得
@@ -171,7 +197,7 @@ module When::Parts
171
197
  if v.kind_of?(String)
172
198
  v = v.strip
173
199
  next if (v=~/^#/)
174
- (v =~ /^(\*)?(.*?)(?:\s*=\s*(.+))?$/) ? $~[1..3] : [[nil, '', nil]]
200
+ (v =~ /^(\*)?(.*?)(?:\s*=\s*(.*))?$/) ? $~[1..3] : [[nil, '', nil]]
175
201
  else
176
202
  v
177
203
  end
@@ -212,21 +238,118 @@ module When::Parts
212
238
  def _hash_value(hash, locale, default='')
213
239
  locale = locale.sub(/\..*/, '').sub(/-/,'_')
214
240
  return hash[locale] if (hash[locale])
215
- return _hash_value(hash, _alias[locale], default) if (_alias[locale])
241
+ return _hash_value(hash, _alias[locale], default) if _alias[locale]
216
242
  language = locale.sub(/_.*/, '')
217
243
  return hash[language] if (hash[language])
218
244
  return hash[default]
219
245
  end
220
246
 
247
+ # 漢字の包摂パターン
221
248
  # @private
222
249
  def _unification
223
- @unifications || DefaultUnification
250
+ @unifications ||= DefaultUnification
224
251
  end
225
252
 
253
+ private
254
+
255
+ # Locale の読み替えパターン
226
256
  def _alias
227
- @aliases || DefaultAlias
257
+ @aliases ||= DefaultAlias
258
+ end
259
+
260
+ # wikipedia オブジェクトの生成・参照
261
+ def wikipedia_object(path, options={})
262
+ query = options.delete(:query)
263
+ interval = options.key?(:interval) ? options.delete(:interval) : @wikipedia_interval
264
+ return nil unless Object.const_defined?(:JSON) && path =~ Ref
265
+ _wikipedia_relation(_wikipedia_object(path, $~[1], $~[2], query, interval, options), path, query)
266
+ end
267
+
268
+ # wikipedia の読み込み
269
+ def _wikipedia_object(path, locale, file, query, interval, options)
270
+ # 採取済みデータ
271
+ title = URI.decode(file.gsub('_', ' '))
272
+ mode = "".respond_to?(:force_encoding) ? ':utf-8' : ''
273
+ dir = Resource.root_dir + '/data/wikipedia/' + locale
274
+ FileUtils.mkdir_p(dir) unless FileTest.exist?(dir)
275
+
276
+ open("#{dir}/#{file}.json", 'r'+mode) do |source|
277
+ json = JSON.parse(source.read)
278
+ json.update(Hash[*query.split('&').map {|pair| pair.split('=')}.flatten]) if query
279
+ json.key?('names') ?
280
+ When::BasicTypes::M17n.new(json) :
281
+ When::Coordinates::Spatial.new(json)
282
+ end
283
+
284
+ rescue => no_file_error
285
+ # 新しいデータ
286
+ case interval
287
+ when 0
288
+ raise no_file_error
289
+ when Numeric
290
+ if @wikipedia_last_access
291
+ delay = (@wikipedia_last_access + interval.abs - Time.now.to_f).ceil
292
+ sleep(delay) if delay > 0
293
+ end
294
+ end
295
+ contents = nil
296
+ begin
297
+ OpenURI
298
+ source = open(path, 'r'+mode)
299
+ contents = source.read
300
+ ensure
301
+ @wikipedia_last_access = Time.now.to_f
302
+ source.close if source
303
+ end
304
+
305
+ # wikipedia contents
306
+ raise KeyError, 'Article not found: ' + title if contents =~ /<div class="noarticletext">/
307
+
308
+ # word
309
+ word = {
310
+ :label => title,
311
+ :names => {''=>title, locale=>title},
312
+ :link => {''=>path, locale=>path }
313
+ }
314
+ contents.scan(Link) do |link|
315
+ word[:names][$~[1]] = $~[4]
316
+ word[:link ][$~[1]] = "http://#{$~[1]}.wikipedia.org/wiki/#{$~[3]}"
317
+ end
318
+ object = When::BasicTypes::M17n.new(word)
319
+
320
+ # location
321
+ if contents =~ /tools\.wmflabs\.org\/geohack\/geohack\.php\?.+?params=(.+?[NS])_(.+?[EW])/
322
+ location = {
323
+ :label => object
324
+ }
325
+ location[:lat], location[:long] = $~[1..2].map {|pos|
326
+ pos.gsub(/_(\d)[._]/, '_0\1_').sub('.', '_').sub('_', '.').gsub('_', '')
327
+ }
328
+ object = When::Coordinates::Spatial.new(location)
329
+ end
330
+
331
+ # save data
332
+ open("#{dir}/#{file}.json", 'w'+mode) do |source|
333
+ source.write(JSON.dump(object.to_h({:method=>:to_h}).update(options)))
334
+ end
335
+ query ? _wikipedia_object(path, locale, file, query) : object
336
+ end
337
+
338
+ # wikipedia オブジェクトの関連付け
339
+ def _wikipedia_relation(object, path, query)
340
+ code_space = path.sub(/[^\/]+$/, '')
341
+ if object.kind_of?(When::Coordinates::Spatial)
342
+ object.label._pool['..'] = object
343
+ object._pool[object.label.to_s] = object.label
344
+ object.send(:child=, [object.label])
345
+ object.label.send(:code_space=, code_space)
346
+ else
347
+ object.send(:code_space=, code_space)
348
+ end
349
+ object._pool['..'] = path
350
+ object._pool['..'] += '?' + query if query
351
+ object
228
352
  end
229
- private :_alias
230
353
  end
231
354
 
232
355
  # ローケール指定時の文字列
@@ -343,12 +466,14 @@ module When::Parts
343
466
  (@names.keys + other.names.keys).uniq.each do |key|
344
467
  names[key] = _label_value(key) + other._label_value(key)
345
468
  end
469
+ links = other.link
346
470
  else
347
471
  @names.keys.each do |key|
348
472
  names[key] = _label_value(key) + other.to_s
349
473
  end
474
+ links = {}
350
475
  end
351
- return dup._copy({:names=>names, :label=>to_s + other.to_s})
476
+ return dup._copy({:names=>names, :link=>links.merge(link), :label=>to_s + other.to_s})
352
477
  end
353
478
 
354
479
  # 書式指定による文字列化
@@ -387,11 +512,17 @@ module When::Parts
387
512
  l
388
513
  }
389
514
 
515
+ # link ハッシュ
516
+ links = terms.reverse.inject({}) {|h,t|
517
+ h.update(t.link) if t.kind_of?(Locale)
518
+ h
519
+ }
520
+
390
521
  # 生成
391
- # @private
392
522
  dup._copy({
393
523
  :label => keys.include?('') ? names.delete(nil) : (names[''] = names[keys[0]]),
394
- :names => names
524
+ :names => names,
525
+ :link => links
395
526
  })
396
527
  end
397
528
  alias :% :_printf
@@ -464,25 +595,35 @@ module When::Parts
464
595
 
465
596
  # @private
466
597
  def _copy(options={})
467
- if (options.key?(:names))
468
- @names = options[:names]
598
+ if options.key?('label') # for JSON
599
+ opt = {}
600
+ options.each_pair do |key, value|
601
+ opt[key.to_sym] = value
602
+ end
603
+ else
604
+ opt = options
605
+ end
606
+
607
+ self[0..-1] = opt[:label] if opt[:label]
608
+ if opt[:names]
609
+ @names = opt[:names]
469
610
  @keys = @names.keys.sort
470
611
  @values = @names.values.compact.sort.reverse
471
612
  end
472
- @link = options[:link] if (options.key?(:link))
473
- @code_space = options[:code_space] if (options.key?(:code_space))
474
- @access_key = options[:access_key] if (options.key?(:access_key))
475
- self[0..-1] = options[:label] if (options.key?(:label))
613
+ @label = opt[:label] if opt[:label]
614
+ @link = opt[:link] if opt[:link]
615
+ @access_key = opt[:access_key] if opt[:access_key]
616
+ @code_space = opt[:code_space] if opt[:code_space]
476
617
  return self
477
618
  end
478
619
 
479
620
  # @private
480
621
  def _copy_all(other)
481
- _copy({:names => other.names,
622
+ _copy({:label => other.to_s,
623
+ :names => other.names,
482
624
  :link => other.link,
483
- :code_space => other.code_space,
484
625
  :access_key => other.access_key,
485
- :label => other.to_s
626
+ :code_space => other.code_space
486
627
  })
487
628
  end
488
629
 
@@ -491,9 +632,12 @@ module When::Parts
491
632
  def _label_value(locale)
492
633
  label = Locale._hash_value(@names, locale, nil)
493
634
  return label if label
494
- addition = When::BasicTypes::M17n._get_locale(locale, @access_key)
495
- return @names[''] unless addition
496
- update(addition)
635
+ foreign = When::BasicTypes::M17n._get_locale(locale, @access_key)
636
+ return @names[''] unless foreign
637
+ english = @names['en'] || @names['']
638
+ addition = english.dup.sub!(/^#{When::BasicTypes::M17n._get_locale('en', @access_key)['en']}/, '')
639
+ foreign[locale] += addition if addition
640
+ update(foreign)
497
641
  return Locale._hash_value(@names, locale)
498
642
  end
499
643
 
@@ -505,7 +649,7 @@ module When::Parts
505
649
  @names = {}
506
650
  @link = {}
507
651
 
508
- if (names.kind_of?(String))
652
+ if names.kind_of?(String)
509
653
  unless (names=~/\A\s*\[(.+?)\]\s*\z/m)
510
654
  names = names.strip
511
655
  @names[''] = names
@@ -524,7 +668,7 @@ module When::Parts
524
668
  case v
525
669
  when '', /^#/ ;
526
670
  when /^\/(.+)/; @access_key = $1
527
- when /^(\*)?(?:([^=%]*?)\s*:)?\s*(.+?)\s*(=\s*([^=]+?)?)?$/
671
+ when /^(\*)?(?:([^=%]*?)\s*:)?\s*(.+?)\s*(=\s*([^=]+?(\?.+)?)?)?$/
528
672
  asterisk[0], locale, name, assignment, ref = $~[1..5]
529
673
  asterisk[1], locale, default_ref = default_locale.shift unless locale
530
674
  locale ||= ''
@@ -540,7 +684,19 @@ module When::Parts
540
684
  end
541
685
  ref += '%%<' + name + '>' if (ref =~ /[\/#:]$/)
542
686
  @link[locale] = _encode(ref)
543
- else ; raise ArgumentError, "Irregal locale format"
687
+ else ; raise ArgumentError, "Irregal locale format: " + v
688
+ end
689
+ end
690
+ if Locale.wikipedia_interval && Locale.wikipedia_interval <= 0
691
+ ['en', ''].each do |lc|
692
+ if Locale::Ref =~ @link[lc] && $~[1] == 'en'
693
+ object = Locale.send(:wikipedia_object, @link[lc])
694
+ if object
695
+ @names = object.names.merge(@names)
696
+ @link = object.link.merge(@link)
697
+ end
698
+ break
699
+ end
544
700
  end
545
701
  end
546
702
 
@@ -548,7 +704,8 @@ module When::Parts
548
704
  @keys = @names.keys.sort
549
705
  @values = @names.values.sort.reverse
550
706
 
551
- return @names[mark[0] || mark[1] || mark[2]]
707
+ # 代表名
708
+ @names[mark[0] || mark[1] || mark[2]]
552
709
  end
553
710
 
554
711
  # encode URI from patterns %%(...) or %.(...)
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  =begin
3
- Copyright (C) 2011-2013 Takashi SUGA
3
+ Copyright (C) 2011-2014 Takashi SUGA
4
4
 
5
5
  You may use and/or modify this file according to the license described in the LICENSE.txt file included in this archive.
6
6
  =end
@@ -66,18 +66,20 @@ module When::Parts
66
66
 
67
67
  # When::Parts::MethodCash のグローバルな設定を行う
68
68
  #
69
- # @param [Boolean] direct '_' で終わるメソッドをキャッシュせずに毎回計算する場合 true, キャッシュする場合 false/nil
70
- # @param [Hash{Symbol=>boolean}] escape 毎回 method_missing を発生させるメソッドを true にして指定
71
- # @param [false, nil] escape to_str, to_ary, to_hash のみ毎回 method_missing を発生させる
72
- # @param [true] escape すべて毎回 method_missing を発生させる
69
+ # @param [Hash] options 以下の通り
70
+ # @option options [Boolean] :direct '_' で終わるメソッドをキャッシュせずに毎回計算するか否か
71
+ # @option options [Hash{Symbol=>boolean}] :escape 毎回 method_missing を発生させるメソッドを true にする
72
+ # @option options [false, nil] :escape to_str, to_ary, to_hash のみ毎回 method_missing を発生させる
73
+ # @option options [true] :escape すべて毎回 method_missing を発生させる
73
74
  #
74
75
  # @return [void]
75
76
  #
76
- # @note When::TM::Calendar クラスの一部はキャッシュ使用を前提としているため direct=true では動作しません
77
+ # @note When::TM::Calendar クラスの一部はキャッシュ使用を前提としているため :direct=>true では動作しません
77
78
  #
78
- def _setup_(direct=false, escape=false)
79
- @direct = direct
80
- case escape
79
+ def _setup_(options={})
80
+ @_setup_info = options
81
+ @direct = options[:direct]
82
+ case options[:escape]
81
83
  when true
82
84
  instance_eval %Q{
83
85
  def escape(method)
@@ -85,7 +87,7 @@ module When::Parts
85
87
  end
86
88
  }
87
89
  when Hash
88
- @escape = Escape.merge(escape)
90
+ @escape = Escape.merge(options[:escape])
89
91
  instance_eval %Q{
90
92
  def escape(method)
91
93
  @escape[method]
@@ -100,6 +102,14 @@ module When::Parts
100
102
  end
101
103
  end
102
104
 
105
+ # 設定情報を取得する
106
+ #
107
+ # @return [Hash] 設定情報
108
+ #
109
+ def _setup_info
110
+ @_setup_info ||= {}
111
+ end
112
+
103
113
  # method_missing メソッドを forward するか否か
104
114
  #
105
115
  # @param [Symbol] method メソッドシンボル
@@ -143,7 +143,17 @@ module When::Parts
143
143
  #
144
144
  # @return [String]
145
145
  #
146
- attr_reader :base_uri
146
+ def base_uri
147
+ @base_uri ||= When::SourceURI
148
+ end
149
+
150
+ # Root Directory for When_exe Resources
151
+ #
152
+ # @return [String]
153
+ #
154
+ def root_dir
155
+ @root_dir ||= When::RootDir
156
+ end
147
157
 
148
158
  # @private
149
159
  attr_reader :_prefix, :_prefix_values, :_prefix_index
@@ -151,7 +161,9 @@ module When::Parts
151
161
 
152
162
  # 初期化
153
163
  #
154
- # @param [String] base_uri Base URI for When_exe Resources
164
+ # @param [Hash] options 以下の通り
165
+ # @option options [String] :base_uri Base URI for When_exe Resources (Default When::SourceURI)
166
+ # @option options [String] :root_dir Root Directory for When_exe Resources Cash data (Default When::RootDir)
155
167
  #
156
168
  # @return [void]
157
169
  #
@@ -159,9 +171,10 @@ module When::Parts
159
171
  # 本メソッドでマルチスレッド対応の管理変数の初期化を行っている。
160
172
  # このため、本メソッド自体はスレッドセーフでない。
161
173
  #
162
- def _setup_(base_uri=When::SourceURI)
174
+ def _setup_(options={})
163
175
  super()
164
176
  @_prefix = {
177
+ '_wp' => 'http://en.wikipedia.org/wiki/',
165
178
  '_w' => base_uri + '/',
166
179
  '_p' => base_uri + 'Parts/',
167
180
  '_b' => base_uri + 'BasicTypes/',
@@ -176,14 +189,23 @@ module When::Parts
176
189
  '_t' => base_uri + 'TimeStandard/',
177
190
  '_ep' => base_uri + 'Ephemeris/',
178
191
  '_c' => base_uri + 'CalendarTypes/',
179
- '_n' => base_uri + 'CalendarTypes/CalendarNote/',
192
+ '_n' => base_uri + 'CalendarNote/',
180
193
  '_sc' => base_uri + 'Ephemeris/V50/'
181
194
  }
182
- @base_uri = base_uri
195
+ @base_uri = options[:base_uri] || When::SourceURI
196
+ @root_dir = options[:root_dir] || When::RootDir
183
197
  @_prefix_values = @_prefix.values.sort.reverse
184
198
  @_prefix_index = @_prefix.invert
185
199
  end
186
200
 
201
+ # 設定情報を取得する
202
+ #
203
+ # @return [Hash] 設定情報
204
+ #
205
+ def _setup_info
206
+ {:base_uri => base_uri, :root_dir => root_dir}
207
+ end
208
+
187
209
  # オブジェクト生成&参照
188
210
  #
189
211
  # 指定した iri の When::Parts::Resource オブジェクトを取得する。
@@ -225,13 +247,13 @@ module When::Parts
225
247
  end
226
248
  end
227
249
  case @_pool[iri]
228
- when my_mutex; my_mutex.synchronize {_create_object(iri, path, query) }
229
- when Mutex ; @_pool[iri].synchronize { @_pool[iri] }
250
+ when my_mutex; my_mutex.synchronize {@_pool[iri] = _create_object(iri, path, query) }
251
+ when Mutex ; @_pool[iri].synchronize {@_pool[iri]}
230
252
  else ; @_pool[iri]
231
253
  end
232
254
  else
233
- @_pool ||= {}
234
- @_pool[iri] ? @_pool[iri] : _create_object(iri, path, query)
255
+ @_pool ||= {}
256
+ @_pool[iri] ||= _create_object(iri, path, query)
235
257
  end
236
258
  end
237
259
 
@@ -240,7 +262,11 @@ module When::Parts
240
262
  _setup_ unless @_pool
241
263
  path = obj.kind_of?(Class) ? obj.to_s.sub(/^When::/, base_uri).gsub(/::/, '/') :
242
264
  obj.iri
243
- return path unless simple
265
+ simple ? _simplify_path(path) : path
266
+ end
267
+
268
+ # @private
269
+ def _simplify_path(path)
244
270
  _prefix_values.each do |value|
245
271
  index = path.index(value)
246
272
  return _prefix_index[value] + ':' + path[value.length..-1] if index
@@ -294,10 +320,12 @@ module When::Parts
294
320
  # @private
295
321
  def _replace_tags(source, tags)
296
322
  case source
323
+ when When::BasicTypes::M17n
324
+ source
297
325
  when String
298
326
  target = source.dup
299
327
  tags.each_pair do |key, value|
300
- target.gsub!(/#\{(\?[^=#}]+?=)?#{key}(:.*?)?\}/, '\1' + value) if value.kind_of?(String)
328
+ target.gsub!(/#\{([?&][^=#}]+?=)?#{key}(:.*?)?\}/, '\1' + value) if value.kind_of?(String)
301
329
  end
302
330
  target.gsub(/#\{.+?(:(.*?))?\}/, '\2')
303
331
  when Array
@@ -305,7 +333,7 @@ module When::Parts
305
333
  when Hash
306
334
  target = {}
307
335
  source.each_pair do |key, value|
308
- target[key] = tags[key].kind_of?(Numeric) ? tags[key] : _replace_tags(value, tags)
336
+ target[key] = _replace_tags(tags[key] || value, tags)
309
337
  end
310
338
  target
311
339
  else
@@ -344,9 +372,18 @@ module When::Parts
344
372
  iri
345
373
  end
346
374
 
375
+ # @private
376
+ def _instantiate(resource)
377
+ return resource unless resource.kind_of?(Array)
378
+ return resource[0].new(*resource[1..-1]) if resource[0].kind_of?(Class)
379
+ return resource.map {|rsc| _instantiate(rsc)}
380
+ end
381
+
347
382
  private
348
383
 
384
+ # オブジェクト生成
349
385
  def _create_object(iri, path, query)
386
+ # query analyzation
350
387
  options = {}
351
388
  replace = {}
352
389
  if query
@@ -361,69 +398,48 @@ module When::Parts
361
398
  end
362
399
  options['..'] = iri
363
400
 
364
- obj = nil
365
- list = _class(path)
366
- if list
367
- # direct URI
368
- case list[0]
369
- when Class
370
- obj = list[0].new(options)
371
- when Array
372
- top = list[0][0]
373
- if top.kind_of?(Hash)
374
- top.each_pair do |key, value|
375
- replace.update(value[replace.delete(key)]) if value.kind_of?(Hash) && value.key?(replace[key])
376
- end
377
- list[0] = list[0][1..-1]
378
- list[0] = _replace_tags(list[0], top.merge(replace))
379
- end
380
- if list[0][0].kind_of?(Class)
381
- # 配列の先頭がクラスである場合
382
- klass, *list = list[0]
383
- unless list[-1].kind_of?(Hash)
384
- if list.length == 1
385
- list[0] = {'.'=>Array(list[0])}
386
- else
387
- list << {}
388
- end
389
- end
390
- else
391
- # 配列の先頭がクラスではない場合
392
- klass, *list = [list[1], *list[0]]
393
- list << {} unless list[-1].kind_of?(Hash)
394
- end
395
- list[-1] = list[-1].merge(options)
396
- obj = klass.new(*list)
401
+ # internal Resource
402
+ if path.index(Resource.base_uri) == 0
403
+ list = _class(path)
404
+ if list
405
+ return _internal(list, replace, options)
397
406
  else
398
- obj = list[0]
407
+ raise IOError, 'IRI not found - ' + path
399
408
  end
400
- else
401
- # external Resource
402
- parsed = nil
409
+ end
410
+
411
+ # external Resource
412
+ begin
413
+ object = When::Parts::Locale.send(:wikipedia_object, path, {:query=>query})
414
+ return object if object
403
415
  OpenURI
404
- begin
405
- args = [path, "1".respond_to?(:force_encoding) ? 'r:utf-8' : 'r']
406
- args << {:ssl_verify_mode=>OpenSSL::SSL::VERIFY_NONE} if path =~ /^https:/
407
- open(*args) do |file|
408
- resource = _replace_tags(file.read, replace)
409
- parsed = (resource[0..5]=='BEGIN:') ? _ics(resource.split(/[\n\r]+/)) :
410
- _xml(REXML::Document.new(resource).root)
416
+ args = [path, "1".respond_to?(:force_encoding) ? 'r:utf-8' : 'r']
417
+ args << {:ssl_verify_mode=>OpenSSL::SSL::VERIFY_NONE} if path =~ /^https:/
418
+ open(*args) do |file|
419
+ resource = file.read
420
+ case resource[0..5].upcase
421
+ when 'BEGIN:'
422
+ options['.'] = _ics(_replace_tags(resource, replace).split(/[\n\r]+/))
423
+ options['.'][0].new(options)
424
+ when '<?XML '
425
+ options['.'] = _xml(REXML::Document.new(_replace_tags(resource, replace)).root)
426
+ options['.'][0].new(options)
427
+ else
428
+ raise NoMethodError, 'JSON not supported' unless Object.const_defined?(:JSON)
429
+ _internal(_json([JSON.parse(resource)]), replace, options)
411
430
  end
412
- rescue OpenURI::HTTPError => error
413
- message = error.message + " - #{path}"
414
- error = error.respond_to?(:uri) ?
415
- error.class.new(message, error.io, error.uri) :
416
- error.class.new(message, error.io)
417
- raise error
418
431
  end
419
- options['.'] = parsed
420
- obj = parsed[0].new(options)
432
+ rescue OpenURI::HTTPError => error
433
+ message = error.message + " - #{path}"
434
+ error = error.respond_to?(:uri) ?
435
+ error.class.new(message, error.io, error.uri) :
436
+ error.class.new(message, error.io)
437
+ raise error
421
438
  end
422
- @_pool[iri] = obj
423
439
  end
424
440
 
441
+ # 内部形式定義の取得
425
442
  def _class(path)
426
- return nil unless path.index(Resource.base_uri) == 0
427
443
  list = [When]
428
444
  path[Resource.base_uri.length..-1].split(/\//).each do |mod|
429
445
  if list[0].const_defined?(mod)
@@ -437,6 +453,42 @@ module When::Parts
437
453
  return list
438
454
  end
439
455
 
456
+ # 内部形式定義のオブジェクト化
457
+ def _internal(list, replace, options)
458
+ case list[0]
459
+ when Class
460
+ list[0].new(options)
461
+ when Array
462
+ top = list[0][0]
463
+ if top.kind_of?(Hash)
464
+ top.each_pair do |key, value|
465
+ replace.update(value[replace[key]]) if value.kind_of?(Hash) && value[replace[key]]
466
+ end
467
+ list[0] = list[0][1..-1]
468
+ list[0] = _replace_tags(list[0], top.merge(replace))
469
+ end
470
+ if list[0][0].kind_of?(Class)
471
+ # 配列の先頭がクラスである場合
472
+ klass, *list = list[0]
473
+ unless list[-1].kind_of?(Hash)
474
+ if list.length == 1
475
+ list[0] = {'.'=>Array(list[0])}
476
+ else
477
+ list << {}
478
+ end
479
+ end
480
+ else
481
+ # 配列の先頭がクラスではない場合
482
+ klass, *list = [list[1], *list[0]]
483
+ list << {} unless list[-1].kind_of?(Hash)
484
+ end
485
+ list[-1] = list[-1].merge(options)
486
+ klass.new(*list)
487
+ else
488
+ list[0]
489
+ end
490
+ end
491
+
440
492
  # .xml フォーマットの読み込み
441
493
  def _xml(xml, namespace={})
442
494
  obj = [_class(_extract_prefix(xml.attributes['type'].to_s))[0]]
@@ -497,6 +549,27 @@ module When::Parts
497
549
  end
498
550
  raise ArgumentError, "BEGIN-END mismatch"
499
551
  end
552
+
553
+ # .json フォーマットの読み込み
554
+ def _json(json)
555
+ case json
556
+ when Array
557
+ json.map {|value| _json(value)}
558
+ when Hash
559
+ hash = {}
560
+ json.each_pair {|key, value| hash[key] = _json(value)}
561
+ hash
562
+ when String
563
+ return json unless json =~ /^When::/
564
+ begin
565
+ return json.split('::').inject(Object) {|ns, sym| ns.const_get(sym)}
566
+ rescue
567
+ json
568
+ end
569
+ else
570
+ json
571
+ end
572
+ end
500
573
  end
501
574
 
502
575
  include Synchronize
@@ -508,7 +581,8 @@ module When::Parts
508
581
  #
509
582
  # @return [Array<When::Parts::Resource>]
510
583
  #
511
- attr_reader :child
584
+ attr_accessor :child
585
+ private :child=
512
586
 
513
587
  #
514
588
  # Resource包含階層で使用する namespace
@@ -539,17 +613,21 @@ module When::Parts
539
613
 
540
614
  # オブジェクトの IRI
541
615
  #
542
- # @return [Sring]
616
+ # @param [Boolean] prefix true ならIRI の先頭部分を簡約表現にする
617
+ #
618
+ # @return [Sring]
543
619
  #
544
- def iri
545
- return @iri if @iri
546
- root = @_pool['..']
547
- path = root.instance_of?(String) ? root : label.to_s
548
- if root.respond_to?(:iri)
549
- prefix = root.iri
550
- path = prefix + '::' + path if prefix
620
+ def iri(prefix=false)
621
+ unless @iri
622
+ root = @_pool['..']
623
+ path = root.instance_of?(String) ? root : label.to_s
624
+ if root.respond_to?(:iri)
625
+ root_iri = root.iri
626
+ path = root_iri + '::' + path if root_iri
627
+ end
628
+ @iri = path
551
629
  end
552
- @iri = path
630
+ prefix ? Resource._simplify_path(@iri) : @iri
553
631
  end
554
632
 
555
633
  # IRI または child の番号によるオブジェクト参照