Mercurial > pub > Impl
annotate Lib/IMPL/TypeKeyedCollection.pm @ 390:de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
author | cin |
---|---|
date | Wed, 12 Feb 2014 18:02:03 +0400 |
parents | 96a522aeb359 |
children | 69a1f1508696 |
rev | line source |
---|---|
316 | 1 package IMPL::TypeKeyedCollection; |
2 use strict; | |
3 | |
4 use IMPL::Const qw(:prop); | |
5 use IMPL::declare { | |
6 require => { | |
7 ArgException => '-IMPL::InvalidArgumentException' | |
8 }, | |
9 base => [ | |
10 'IMPL::Object' => undef | |
11 ], | |
12 props => [ | |
13 _items => PROP_RW | PROP_DIRECT, | |
390
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
14 _cache => PROP_RW | PROP_DIRECT, |
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
15 _reverse => PROP_RW | PROP_DIRECT |
316 | 16 ] |
17 }; | |
18 | |
19 sub CTOR { | |
390
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
20 my ($this,$items,$reverse) = @_; |
316 | 21 |
22 $items = {} | |
23 unless ref($items) eq 'HASH'; | |
24 | |
25 $this->{$_items} = $items; | |
390
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
26 $this->{$_reverse} = $reverse; |
316 | 27 } |
28 | |
29 sub Get { | |
30 my ($this,$type) = @_; | |
31 | |
317 | 32 die ArgException->new(type => 'Invalid type', $type) |
33 if not $type or ref($type); | |
316 | 34 |
35 if(my $val = $this->{$_cache}{$type}) { | |
36 return $val; | |
37 } else { | |
390
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
38 if ($this->_reverse) { |
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
39 my $val = $this->{$_items}{$type}; |
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
40 |
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
41 unless(defined $val) { |
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
42 my $matching; |
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
43 while ( my ($k,$v) = each %{$this->{$_items}}) { |
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
44 if (isclass($k,$type) && (not($matching) || isclass($k,$matching)) ) { |
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
45 $matching = $k; |
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
46 $val = $v; |
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
47 } |
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
48 } |
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
49 } |
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
50 |
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
51 return $this->{$_cache}{$type} = $val; |
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
52 |
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
53 } else { |
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
54 no strict 'refs'; |
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
55 |
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
56 my @isa = $type; |
316 | 57 |
390
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
58 while (@isa) { |
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
59 my $sclass = shift @isa; |
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
60 |
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
61 $val = $this->{$_items}{$sclass}; |
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
62 |
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
63 return($this->{$_cache}{$type} = $val) |
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
64 if defined $val; # zeroes and empty strings are also valid |
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
65 |
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
66 push @isa, @{"${sclass}::ISA"}; |
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
67 } |
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
68 return; |
de1f875e8875
added reverse matching lookup to TypeKeyedCollection (find closest descendant)
cin
parents:
317
diff
changeset
|
69 } |
316 | 70 } |
71 } | |
72 | |
73 sub Set { | |
74 my ($this,$type,$value) = @_; | |
75 | |
317 | 76 die ArgException->new(type => 'Invalid type', $type) |
77 if not $type or ref($type); | |
316 | 78 |
79 $this->{$_items}{$type} = $value; | |
80 | |
81 delete $this->{$_cache}; | |
82 | |
83 return $value; | |
84 } | |
85 | |
86 sub Delete { | |
87 my ($this,$type) = @_; | |
88 | |
89 if(defined delete $this->{$_items}{$type} ) { | |
90 delete $this->{$_cache}; | |
91 return 1; | |
92 } | |
93 return; | |
94 } | |
95 | |
96 1; | |
97 | |
98 __END__ | |
99 | |
100 =pod | |
101 | |
102 =head1 NAME | |
103 | |
104 C<IMPL::TypeKeyedCollection> - коллекция, ключами которой являются типы. | |
105 | |
106 =head1 SYNOPSIS | |
107 | |
108 =begin code | |
109 | |
110 package Foo; | |
111 | |
112 package Bar; | |
113 our @ISA = qw(Foo); | |
114 | |
115 package Baz; | |
116 our @ISA = qw(Foo); | |
117 | |
118 package main; | |
119 use IMPL::require { | |
120 TypeKeyedCollection => 'IMPL::TypeKeyedCollection' | |
121 }; | |
122 | |
123 my $col = TypeKeyedCollection->new({ | |
124 Foo => 'base', | |
125 Bar => 'BAAAR' | |
126 }); | |
127 | |
128 print $col->Get('Foo'); # 'base' | |
129 print $col->Get('Bar'); # 'BAAAR' | |
130 print $col->Get('Baz'); # 'base' | |
131 | |
132 =end code | |
133 | |
134 =head1 DESCRIPTION | |
135 | |
136 Использует иерархию классов для определения наиболее подходяжего значения в | |
137 коллекции. | |
138 | |
139 =cut |