Module: When::Parts::Resource

Extended by:
Pool
Includes:
Synchronize
Included in:
BasicTypes::M17n, BasicTypes::Object, TM::Position, TM::TemporalPosition
Defined in:
lib/when_exe/parts/resource.rb

Overview

Resource which has 'International Resource Identifier'

Defined Under Namespace

Modules: Pool, Synchronize Classes: ContentLine, Enumerator

Constant Summary collapse

LabelProperty =
nil

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Pool

[]=, _setup_

Methods included from Synchronize

#synchronize

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object (private)

その他のメソッド

When::Parts::Resource 

916
917
918
919
920
921
922
923
924
# File 'lib/when_exe/parts/resource.rb', line 916

def method_missing(name, *args, &block)
  return __method_missing(name, *args, &block) if When::Parts::MethodCash::Escape.key?(name)
  self.class.module_eval %Q{
    def #{name}(*args, &block)
      @child.send("#{name}", *args, &block)
    end
  } unless When::Parts::MethodCash.escape(name)
  @child.send(name, *args, &block)
end

Class Attribute Details

._prefixObject (readonly)


149
150
151
# File 'lib/when_exe/parts/resource.rb', line 149

def _prefix
  @_prefix
end

._prefix_indexObject (readonly)


149
150
151
# File 'lib/when_exe/parts/resource.rb', line 149

def _prefix_index
  @_prefix_index
end

._prefix_valuesObject (readonly)


149
150
151
# File 'lib/when_exe/parts/resource.rb', line 149

def _prefix_values
  @_prefix_values
end

.base_uriString (readonly)

Base URI for When_exe Resources


146
147
148
# File 'lib/when_exe/parts/resource.rb', line 146

def base_uri
  @base_uri
end

Instance Attribute Details

#_poolObject (readonly)


505
506
507
# File 'lib/when_exe/parts/resource.rb', line 505

def _pool
  @_pool
end

#childArray<When::Parts::Resource> (readonly)

self が has-a 関係で包含するオブジェクト


511
512
513
# File 'lib/when_exe/parts/resource.rb', line 511

def child
  @child
end

#keysArray<String> (readonly)

strftime で有効な locale


538
539
540
# File 'lib/when_exe/parts/resource.rb', line 538

def keys
  @keys
end

#localeArray<String> (readonly)

Resource包含階層で使用する locale

When::BasicTypes::M17n 

532
533
534
# File 'lib/when_exe/parts/resource.rb', line 532

def locale
  @locale
end

#namespaceHash (readonly)

Resource包含階層で使用する namespace

When::BasicTypes::M17n 

522
523
524
# File 'lib/when_exe/parts/resource.rb', line 522

def namespace
  @namespace
end

Class Method Details

._decode(iri) ⇒ Object


332
333
334
335
336
337
338
339
340
341
342
343
344
345
# File 'lib/when_exe/parts/resource.rb', line 332

def _decode(iri)
  return iri unless iri =~ /%28/

  iri = iri.dup
  begin
    unless iri.gsub!(/%28.*?%29/) {|token|
      token.gsub(/%([\dA-F]{2})/i) {$1.to_i(16).chr}
    }
      raise ArgumentError, 'Brackets do not correspond: ' + iri 
    end
  end while iri =~ /%28/
  iri = $1 if iri =~ /^\((.*)\)$/
  iri
end

._encode(iri) ⇒ Object


317
318
319
320
321
322
323
324
325
326
327
328
329
# File 'lib/when_exe/parts/resource.rb', line 317

def _encode(iri)
  return iri unless iri =~ /\(/

  iri = iri.dup
  begin
    unless iri.gsub!(/\([^()]*\)/) {|token|
      token.gsub(/[():?&%]/) {|char|'%' + char.ord.to_s(16)}
    }
      raise ArgumentError, 'Brackets do not correspond: ' + iri 
    end
  end while iri =~ /\(/
  iri
end

._extract_prefix(path, capitalize = false) ⇒ Object


278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
# File 'lib/when_exe/parts/resource.rb', line 278

def _extract_prefix(path, capitalize=false)
  if (path =~ /^(.+?):+(.+)$/)
    prefix, klass = $~[1..2]
    if capitalize
      prefix = '_' + prefix.downcase
      klass  = klass.capitalize if klass == klass.upcase
    end
    path = _prefix[prefix] + klass if (_prefix[prefix])
  elsif capitalize && path =~ /^(v[^\/]+|daylight$|standard$)/i
    klass = path.sub(/^v/i, '').capitalize
    path  = _prefix['_v'] + klass if When::V.const_defined?(klass) &&
                                     When::V.const_get(klass).kind_of?(Class)
  end
  return path
end

._instance(iri, namespace = nil) ⇒ When::Parts::Resource

オブジェクト生成&参照

指定した iri の When::Parts::Resource オブジェクトを取得する。 当該オブジェクトが未登録であれば生成する。


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
# File 'lib/when_exe/parts/resource.rb', line 197

def _instance(iri, namespace=nil)
  _setup_ unless @_pool

  # 配列は個別に処理
  return iri.map {|e| _instance(e, namespace)} if iri.kind_of?(Array)

  # 文字列以外はそのまま返す
  return iri unless iri.instance_of?(String)

  # 階層がある場合は、階層をたどる
  iri = Resource._decode(iri)
  iri = $1 while iri =~ /^\((.*)\)$/
  iri = namespace + iri if namespace && iri !~ /^[_a-z\d]+:[^:]/i
  root, *leaves= Resource._encode(iri).split(/::/)
  if leaves.size > 0
    return leaves.inject(_instance(Resource._decode(root))) {|obj,leaf| obj[Resource._decode(leaf)]}
  end

  # 登録ずみなら、参照
  iri = _extract_prefix(iri)
  path, query = iri.split(/\?/, 2)
  if When.multi_thread
    my_mutex = nil
    @_lock_.synchronize do
      @_pool ||= {}
      unless @_pool[iri]
        my_mutex    = Mutex.new
        @_pool[iri] = my_mutex
      end
    end
    case @_pool[iri]
    when my_mutex; my_mutex.synchronize    {_create_object(iri, path, query) }
    when Mutex   ; @_pool[iri].synchronize { @_pool[iri] }
    else         ; @_pool[iri]
    end
  else
    @_pool ||= {}
    @_pool[iri] ? @_pool[iri] : _create_object(iri, path, query)
  end
end

._parse(line, type = nil) ⇒ Object


252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
# File 'lib/when_exe/parts/resource.rb', line 252

def _parse(line, type=nil)
  return line unless line.kind_of?(String)
  line.sub!(/\s#.*$/, '')
  return Locale._split($1) if type && /^#{type}:(.+)$/i =~ line
  tokens = line.scan(/((?:[^\\:]|\\.)+)(?::(?!\z))?|:/).flatten
  return Locale._split(line) unless tokens.size > 1 && /^(\*)?([A-Z][-A-Z_]{0,255})(?:;(.+))?$/i =~ tokens[0]
  marked, key, property = $~[1..3]
  values = tokens[1..-1]
  value  = values.join(':') unless values == [nil]
  content = ContentLine.new(key, value, marked)
  value ||= ''
  if property
    content.attribute['.'] = property + ':' + value
    property.scan(/((?:[^\\;]|\\.)+)(?:;(?!\z))?|;/).flatten.each do |pr|
      pr ||= ''
      pr.gsub!(/\\./) {|escape| ContentLine::RFC6350[escape] || escape}
      prop = ContentLine.new(*pr.split(/=/, 2))
      content.attribute[prop.predicate] = prop
    end
  else
    content.attribute['.'] = value
  end
  return content
end

._path_with_prefix(obj, simple = true) ⇒ Object


239
240
241
242
243
244
245
246
247
248
249
# File 'lib/when_exe/parts/resource.rb', line 239

def _path_with_prefix(obj, simple=true)
  _setup_ unless @_pool
  path = obj.kind_of?(Class) ? obj.to_s.sub(/^When::/, base_uri).gsub(/::/, '/') :
                               obj.iri
  return path unless simple
  _prefix_values.each do |value|
    index = path.index(value)
    return _prefix_index[value] + ':' + path[value.length..-1] if index
  end
  return path
end

._replace_tags(source, tags) ⇒ Object


295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
# File 'lib/when_exe/parts/resource.rb', line 295

def _replace_tags(source, tags)
  case source
  when String
    target = source.dup
    tags.each_pair do |key, value|
      target.gsub!(/#\{(\?[^=#}]+?=)?#{key}(:.*?)?\}/, '\1' + value) if value.kind_of?(String)
    end
    target.gsub(/#\{.+?(:(.*?))?\}/, '\2')
  when Array
    source.map {|target| _replace_tags(target, tags)}
  when Hash
    target = {}
    source.each_pair do |key, value|
      target[key] = tags[key].kind_of?(Numeric) ? tags[key] : _replace_tags(value, tags)
    end
    target
  else
    source
  end
end

._setup_(base_uri = When::SourceURI) ⇒ void

Note:

本メソッドでマルチスレッド対応の管理変数の初期化を行っている。 このため、本メソッド自体はスレッドセーフでない。

This method returns an undefined value.

初期化


162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/when_exe/parts/resource.rb', line 162

def _setup_(base_uri=When::SourceURI)
  super()
  @_prefix = {
    '_w'   => base_uri + '/',
    '_p'   => base_uri + 'Parts/',
    '_b'   => base_uri + 'BasicTypes/',
    '_m'   => base_uri + 'BasicTypes/M17n/',
    '_co'  => base_uri + 'Coordinates/',
    '_l'   => base_uri + 'Coordinates/Spatial?',
    '_v'   => base_uri + 'V/',
    '_rs'  => base_uri + 'RS/',
    '_ex'  => base_uri + 'EX/',
    '_tm'  => base_uri + 'TM/',
    '_e'   => base_uri + 'TM/CalendarEra/',
    '_t'   => base_uri + 'TimeStandard/',
    '_ep'  => base_uri + 'Ephemeris/',
    '_c'   => base_uri + 'CalendarTypes/',
    '_n'   => base_uri + 'CalendarTypes/CalendarNote/',
    '_sc'  => base_uri + 'Ephemeris/V50/'
  }
  @base_uri       = base_uri
  @_prefix_values = @_prefix.values.sort.reverse
  @_prefix_index  = @_prefix.invert
end

Instance Method Details

#[](iri) ⇒ When::parts::Resource

IRI または child の番号によるオブジェクト参照


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
# File 'lib/when_exe/parts/resource.rb', line 562

def [](iri)
  case iri
  when Numeric
    return child[iri * 1]
  when String
    obj = self
    Resource._encode(iri).split(/::/).each do |label|
      return obj.child if label == '*'
      if obj == Resource
        obj = Resource._instance(Resource._decode(label))
      else
        case label
        when ''  ; obj = Resource
        when '.' # obj = obj
        else     ; obj = obj._pool[Resource._decode(label)]
        end
      end
      raise ArgumentError, "IRI not found: #{iri}" unless obj
    end
    return obj
  else
    super(iri)
    #raise ArgumentError, "IRI not found: #{iri}"
  end
end

#^(other) ⇒ Enumerator

Enumerator 生成のダミー


725
726
727
# File 'lib/when_exe/parts/resource.rb', line 725

def ^(other)
  return nil
end

#each(*args, &block) ⇒ Enumerator

順次実行


736
737
738
739
740
# File 'lib/when_exe/parts/resource.rb', line 736

def each(*args, &block)
  enum = enum_for(*args)
  return enum unless block
  enum.each(&block)
end

#enum_for(direction = :forward) ⇒ Object Also known as: to_enum

オブジェクトを順に取り出す enumerator

@param [Symbol] direction 

714
715
716
# File 'lib/when_exe/parts/resource.rb', line 714

def enum_for(direction=:forward)
  Enumerator.new(self, direction)
end

#hierarchy(klass = self.class) ⇒ When::Parts::Resource

self を包含するオブジェクト階層


602
603
604
605
606
607
608
609
610
# File 'lib/when_exe/parts/resource.rb', line 602

def hierarchy(klass=self.class)
  hierarchy = []
  parent    = self
  while parent.kind_of?(klass)
    hierarchy << parent
    parent = parent.parent
  end
  hierarchy.reverse
end

#include?(other) ⇒ Boolean

self が other を包含するか


618
619
620
621
622
623
624
625
# File 'lib/when_exe/parts/resource.rb', line 618

def include?(other)
  c = other
  while c.kind_of?(Resource)
    return true if c.equal?(self)
    c = c.parent
  end
  return false
end

#included?(other) ⇒ Boolean

other が self を包含するか


633
634
635
# File 'lib/when_exe/parts/resource.rb', line 633

def included?(other)
  other.include?(self)
end

#iriObject

オブジェクトの IRI

@return [Sring]

544
545
546
547
548
549
550
551
552
553
# File 'lib/when_exe/parts/resource.rb', line 544

def iri
  return @iri if @iri
  root = @_pool['..']
  path = root.instance_of?(String) ? root : label.to_s
  if root.respond_to?(:iri)
    prefix = root.iri
    path = prefix + '::' + path if prefix
  end
  @iri = path
end

#leaf?Boolean

オブジェクト包含階層の末端か?


666
667
668
# File 'lib/when_exe/parts/resource.rb', line 666

def leaf?
  !@child || (@child.length==0)
end

#m17n(source, namespace = nil, locale = nil, options = {}) ⇒ When::BasicTypes::M17n or Array<them>

When::BasicTypes::M17n の生成/参照


697
698
699
700
701
702
703
704
705
706
# File 'lib/when_exe/parts/resource.rb', line 697

def m17n(source, namespace=nil, locale=nil, options={})
  case source
  when Array                  ; When::BasicTypes::M17n.new(source, namespace, locale, options)
  when When::BasicTypes::M17n ; source
  when String
    return self[$1] if source =~ /^\s*\[((\.{1,2}|::)+[^\]]+)\]/
    When::BasicTypes::M17n.new(source, namespace, locale, options)
  else ; raise TypeError, "Invalid Type: #{source.class}"
  end
end

#map(&block) ⇒ Array Also known as: collect

map, collect の再定義

has-a 関係の子 Resource に対して map/collect を行う


750
751
752
# File 'lib/when_exe/parts/resource.rb', line 750

def map(&block)
  @child.map(&block)
end

#nextWhen::Parts::Resource Also known as: succ

次のオブジェクト


653
654
655
656
657
# File 'lib/when_exe/parts/resource.rb', line 653

def next
  c = self
  c = c.child[0] while c.child && c.child.size > 0
  c._pool['.->']
end

#parentWhen::Parts::Resource

self を直接に包含するオブジェクト


592
593
594
# File 'lib/when_exe/parts/resource.rb', line 592

def parent
  @_pool['..'].kind_of?(Resource) ? @_pool['..'] : nil
end

#prevWhen::Parts::Resource

前のオブジェクト


641
642
643
644
645
646
647
# File 'lib/when_exe/parts/resource.rb', line 641

def prev
  c = self
  c = c.child[0] while c.child && c.child.size > 0
  c = c._pool['.<-']
  c = c.child[-1] while c && c.child && c.child.size > 0
  c
end

#registered?Boolean

IRIが付与されているか?


676
677
678
679
680
681
682
683
684
# File 'lib/when_exe/parts/resource.rb', line 676

def registered?
  leaf = self
  while leaf._pool['..'].respond_to?(:_pool)
    root = leaf._pool['..']
    return false unless leaf.equal?(root._pool[leaf.label])
    leaf = root
  end
  Resource._pool.value?(leaf)
end