File Coverage

lib/Class/Dot/Registry.pm
Criterion Covered Total %
statement 86 95 90.5
branch 29 40 72.5
condition 6 6 100.0
subroutine 23 24 95.8
pod 12 12 100.0
total 156 177 88.1


line stmt bran cond sub pod time code
1             # $Id$
2             # $Source$
3             # $Author$
4             # $HeadURL$
5             # $Revision$
6             # $Date$
7             package Class::Dot::Registry;
8              
9 16     16   83 use strict;
  16         52  
  16         538  
10 16     16   84 use warnings;
  16         27  
  16         452  
11 16     16   79 use version;
  16         71  
  16         96  
12 16     16   1150 use 5.00600;
  16         55  
  16         1297  
13              
14             our $VERSION = qv('2.0.0_15');
15             our $AUTHORITY = 'cpan:ASKSH';
16              
17 16     16   110 use Carp qw(croak);
  16         43  
  16         823  
18 16     16   105 use Class::Plugin::Util qw(require_class);
  16         38  
  16         99  
19              
20             my $DEFAULT_METACLASS = 'Class::Dot::Meta::Class';
21              
22             STATE: {
23             my $THE_REGISTRY; # << This is a singleton object.
24              
25             my $scalar_ref = do { my $scalar; \$scalar };
26              
27             sub new {
28 77     77 1 197 my ($class) = @_;
29              
30 77 100       318 if (! defined $THE_REGISTRY) {
31 16         66 $THE_REGISTRY = bless $scalar_ref, $class;
32             }
33              
34 77         233 return $THE_REGISTRY;
35             }
36             }
37              
38             PRIVATE: {
39             my %METACLASS_FOR;
40             my %IS_FINALIZED;
41             my %ISA_CACHE_FOR;
42             my %CLASS_META_FOR;
43             my %OPTIONS_FOR;
44             my %REGISTERED_CLASSES;
45              
46             sub _get_metaclasses {
47 371     371   604 return \%METACLASS_FOR;
48             }
49              
50             sub _get_finalized {
51 75     75   271 return \%IS_FINALIZED;
52             }
53              
54             sub _get_isa_cache {
55 118     118   274 return \%ISA_CACHE_FOR;
56             }
57              
58             sub _get_class_meta {
59 303     303   502 return \%CLASS_META_FOR;
60             }
61              
62             sub _get_options {
63 158     158   280 return \%OPTIONS_FOR;
64             }
65              
66             sub _get_registered_classes {
67 34     34   88 return \%REGISTERED_CLASSES;
68             }
69             }
70              
71             sub register_class {
72 32     32 1 62 my ($self, $the_class) = @_;
73 32 50       114 my $class = ref $the_class ? ref $the_class
74             : $the_class;
75              
76 32         92 my $class_register = _get_registered_classes();
77 32         104 $class_register->{$class} = 1;
78 32         82 return;
79             }
80              
81             sub is_class_registered {
82 2     2 1 408 my ($self, $the_class) = @_;
83 2 100       8 my $class = ref $the_class ? ref $the_class
84             : $the_class;
85              
86 2         6 return _get_registered_classes()->{$class};
87             }
88              
89             sub finalize_class {
90 3     3 1 7 my ($self, $the_class, $isa_cache) = @_;
91 3 100       8 my $class = ref $the_class ? ref $the_class
92             : $the_class;
93 3 50       9 return if not defined $class;
94              
95 3         8 my $is_finalized = _get_finalized();
96              
97 3 100       18 return 1 if $is_finalized->{$class};
98              
99 2 50       6 if ($isa_cache) {
100 2         6 $self->update_isa_cache_for($class, $isa_cache);
101             }
102              
103 2         15 $is_finalized->{$class} = 1;
104              
105 2         10 return 1;
106             }
107              
108             sub is_finalized {
109 72     72 1 100 my ($self, $the_class) = @_;
110 72 100       173 my $class = ref $the_class ? ref $the_class
111             : $the_class;
112              
113 72 100       130 return _get_finalized()->{$class} ? 1 : 0;
114             }
115              
116             sub get_isa_cache_for {
117 116     116 1 178 my ($self, $the_class) = @_;
118 116 100       235 my $class = ref $the_class ? ref $the_class
119             : $the_class;
120 116         227 my $isa_cache_for = _get_isa_cache();
121 116 100       437 return if not exists $isa_cache_for->{$class};
122              
123             # Can be undef. If it is, the class is probably not finalized.
124 5         15 return $isa_cache_for->{$class};
125             }
126              
127             sub update_isa_cache_for {
128 2     2 1 6 my ($self, $class, $isa_cache) = @_;
129              
130 2         5 my $isa_cache_for = _get_isa_cache();
131 2         6 $isa_cache_for->{$class} = $isa_cache;
132 2         5 return;
133             }
134              
135             sub get_meta_for {
136 303     303 1 441 my ($self, $class) = @_;
137 303         611 my $class_meta_for = _get_class_meta();
138              
139 303   100     938 $class_meta_for->{$class} ||= { };
140 303         711 return $class_meta_for->{$class};
141             }
142              
143             sub get_options_for {
144 158     158 1 2582 my ($self, $the_class, $initial_options) = @_;
145 158 100       349 my $class = ref $the_class ? ref $the_class
146             : $the_class;
147 158         325 my $options_for = _get_options();
148            
149 158   100     665 $initial_options ||= { };
150              
151             # Must be a copy of the options because it probably
152             # comes from %Class::Dot::Policy::DEFAULT_OPTIONS, so if we
153             # just use that reference all class options will be
154             # the same as the last class initialized.
155 158   100     437 $options_for->{$class} ||= { %{$initial_options} };
  32         231  
156              
157 158         5774 return $options_for->{$class};
158             }
159              
160             sub set_options_for {
161 0     0 1 0 my ($self, $class, $options_ref) = @_;
162 0 0       0 return if not ref $options_ref;
163 0 0       0 return if not ref $options_ref eq 'HASH';
164 0         0 my $options_for = _get_options();
165              
166 0         0 $options_for->{$class} = $options_ref;
167 0         0 return;
168             }
169              
170             sub get_metaclass_for {
171 339     339 1 496 my ($self, $the_class) = @_;
172 339 100       763 my $class = ref $the_class ? ref $the_class
173             : $the_class;
174 339         559 my $metaclass_for = _get_metaclasses();
175              
176 339 50       951 if (! exists $metaclass_for->{$class}) {
177 0         0 $self->init_metaclass_for($class);
178             }
179              
180 339         1078 return $metaclass_for->{$class};
181             }
182              
183             sub init_metaclass_for {
184 32     32 1 74 my ($self, $the_class, $metaclass, $options_ref) = @_;
185 32 50       97 my $class = ref $the_class ? ref $the_class
186             : $the_class;
187 32         94 my $metaclass_for = _get_metaclasses();
188              
189 32 50       102 if (not defined $metaclass) {
190 0         0 $metaclass = $DEFAULT_METACLASS;
191             }
192              
193 32 50       144 if (! require_class($metaclass)) {
194 0         0 croak "!!! COULD NOT LOAD METACLASS $metaclass FOR CLASS $class !!!";
195             }
196              
197             # -override gets priority over -optimized.
198 32 100       914 if ($options_ref->{'-override'}) {
199 2         5 $options_ref->{'-optimized'} = 0;
200             };
201              
202 32         50 my %metaclass_options = %{ $options_ref };
  32         182  
203 32         87 $metaclass_options{for_class} = $class;
204            
205 32         218 my $metaclass_instance = $metaclass->new(\%metaclass_options);
206 32         81 $metaclass_for->{$class} = $metaclass_instance;
207              
208 32         164 return $metaclass_instance;
209             }
210              
211             1;
212              
213             __END__