File Coverage

blib/lib/Class/Meta/Class.pm
Criterion Covered Total %
statement 106 108 98.1
branch 56 64 87.5
condition 16 21 76.1
subroutine 22 22 100.0
pod 12 12 100.0
total 212 227 93.3


line stmt bran cond sub pod time code
1             package Class::Meta::Class;
2              
3             =head1 NAME
4              
5             Class::Meta::Class - Class::Meta class introspection
6              
7             =head1 SYNOPSIS
8              
9             # Assuming MyApp::Thingy was generated by Class::Meta.
10             my $class = MyApp::Thingy->my_class;
11             my $thingy = MyApp::Thingy->new;
12              
13             print "Examining object of class ", $class->package, $/;
14              
15             print "\nConstructors:\n";
16             for my $ctor ($class->constructors) {
17             print " o ", $ctor->name, $/;
18             }
19              
20             print "\nAttributes:\n";
21             for my $attr ($class->attributes) {
22             print " o ", $attr->name, " => ", $attr->get($thingy) $/;
23             }
24              
25             print "\nMethods:\n";
26             for my $meth ($class->methods) {
27             print " o ", $meth->name, $/;
28             }
29              
30             =head1 DESCRIPTION
31              
32             Object of this class describe classes created by Class::Meta. They contain
33             everything you need to know about a class to be able to put objects of that
34             class to good use. In addition to retrieving meta data about the class itself,
35             you can retrieve objects that describe the constructors, attributes, and
36             methods of the class. See C for a fuller description
37             of the utility of the Class::Meta suite of modules.
38              
39             Class::Meta::Class objects are created by Class::Meta; they are never
40             instantiated directly in client code. To access the class object for a
41             Class::Meta-generated class, simply call its C method.
42              
43             At this point, those attributes tend to be database-specific. Once other types
44             of data stores are added (XML, LDAP, etc.), other attributes may be added to
45             allow their schemas to be built, as well.
46              
47             =cut
48              
49             ##############################################################################
50             # Dependencies #
51             ##############################################################################
52 21     21   28055 use strict;
  21         40  
  21         739  
53 21     21   1016 use Class::ISA ();
  21         3343  
  21         404  
54 21     21   916 use Class::Meta;
  21         79  
  21         502  
55 21     21   33249 use Class::Meta::Attribute;
  21         63  
  21         806  
56 21     21   13818 use Class::Meta::Method;
  21         56  
  21         12069  
57              
58             ##############################################################################
59             # Package Globals #
60             ##############################################################################
61             our $VERSION = '0.66';
62             our @CARP_NOT = qw(Class::Meta);
63              
64             =head1 INTERFACE
65              
66             =head2 Constructors
67              
68             =head3 new
69              
70             A protected method for constructing a Class::Meta::Class object. Do not call
71             this method directly; Call the L|Class::Meta/new"> constructor on a
72             Class::Meta object, instead. A Class::Meta::Class object will be constructed
73             by default, and can always be retrieved via the C method of the
74             class for which it was constructed.
75              
76             =cut
77              
78             ##############################################################################
79              
80             sub new {
81 47     47 1 1870 my ($pkg, $spec) = @_;
82             # Check to make sure that only Class::Meta or a subclass is
83             # constructing a Class::Meta::Class object.
84 47         129 my $caller = caller;
85 47 100 100     446 Class::Meta->handle_error("Package '$caller' cannot create $pkg objects")
86             unless UNIVERSAL::isa($caller, 'Class::Meta')
87             || UNIVERSAL::isa($caller, __PACKAGE__);
88              
89             # Set the name to be the same as the key by default.
90 45   66     342 $spec->{name} ||= join ' ', map { ucfirst } split '_', $spec->{key};
  33         215  
91              
92             # Set the abstract attribute.
93 45 100       195 $spec->{abstract} = $spec->{abstract} ? 1 : 0;
94              
95             # Set the trusted attribute.
96 45 50       242 $spec->{trusted} = exists $spec->{trust}
    100          
97             ? ref $spec->{trust} ? delete $spec->{trust} : [ delete $spec->{trust} ]
98             : [];
99              
100             # Okay, create the class object.
101 45   33     507 my $self = bless $spec, ref $pkg || $pkg;
102             }
103              
104             ##############################################################################
105             # Instance Methods
106             ##############################################################################
107              
108             =head2 Instance Methods
109              
110             =head3 package
111              
112             my $pkg = $class->package;
113              
114             Returns the name of the package that the Class::Meta::Class object describes.
115              
116             =head3 key
117              
118             my $key = $class->key;
119              
120             Returns the key name that uniquely identifies the class across the
121             application. The key name may simply be the same as the package name.
122              
123             =head3 name
124              
125             my $name = $class->name;
126              
127             Returns the name of the the class. This should generally be a descriptive
128             name, rather than a package name.
129              
130             =head3 desc
131              
132             my $desc = $class->desc;
133              
134             Returns a description of the class.
135              
136             =head3 abstract
137              
138             my $abstract = $class->abstract;
139              
140             Returns true if the class is an abstract class, and false if it is not.
141              
142             =head3 default_type
143              
144             my $default_type = $class->default_type;
145              
146             The data type used for attributes of the class that were added with no
147             explicit types.
148              
149             =head3 trusted
150              
151             my @trusted = $class->trusted;
152             my $trusted = $class->trusted;
153              
154             In an array context, returns a list of class names that this class trusts.
155             Returns the same list in an array reference in a scalar context.
156              
157             =cut
158              
159 82     82 1 379 sub package { $_[0]->{package} }
160 6     6 1 49 sub key { $_[0]->{key} }
161 5     5 1 36 sub name { $_[0]->{name} }
162 5     5 1 37 sub desc { $_[0]->{desc} }
163 121     121 1 643 sub abstract { $_[0]->{abstract} }
164 7     7 1 469 sub default_type { $_[0]->{default_type} }
165 6 100   6 1 23 sub trusted { wantarray ? @{ $_[0]->{trusted} } : [ @{ $_[0]->{trusted} } ] }
  1         8  
  5         29  
166              
167             ##############################################################################
168              
169             =head3 is_a
170              
171             if ($class->is_a('MyApp::Base')) {
172             print "All your base are belong to us\n";
173             }
174              
175             This method returns true if the object or package name passed as an argument
176             is an instance of the class described by the Class::Meta::Class object or one
177             of its subclasses. Functionally equivalent to
178             C<< $class->package->isa($pkg) >>, but more efficient.
179              
180             =cut
181              
182 8     8 1 87 sub is_a { UNIVERSAL::isa($_[0]->{package}, $_[1]) }
183              
184             ##############################################################################
185             # Accessors to get at the constructor, attribute, and method objects.
186             ##############################################################################
187              
188             =head3 constructors
189              
190             my @constructors = $class->constructors;
191             my $ctor = $class->constructors($ctor_name);
192             @constructors = $class->constructors(@ctor_names);
193              
194             Provides access to the Class::Meta::Constructor objects that describe the
195             constructors for the class. When called with no arguments, it returns all of
196             the constructor objects. When called with a single argument, it returns the
197             constructor object for the constructor with the specified name. When called
198             with a list of arguments, returns all of the constructor objects with the
199             specified names.
200              
201             =cut
202              
203             ##############################################################################
204              
205             =head3 attributes
206              
207             my @attributes = $class->attributes;
208             my $attr = $class->attributes($attr_name);
209             @attributes = $class->attributes(@attr_names);
210              
211             Provides access to the Class::Meta::Attribute objects that describe the
212             attributes for the class. When called with no arguments, it returns all of the
213             attribute objects. When called with a single argument, it returns the
214             attribute object for the attribute with the specified name. When called with a
215             list of arguments, returns all of the attribute objects with the specified
216             names.
217              
218             =cut
219              
220             ##############################################################################
221              
222             =head3 methods
223              
224             my @methods = $class->methods;
225             my $meth = $class->methods($meth_name);
226             @methods = $class->methods(@meth_names);
227              
228             Provides access to the Class::Meta::Method objects that describe the methods
229             for the class. When called with no arguments, it returns all of the method
230             objects. When called with a single argument, it returns the method object for
231             the method with the specified name. When called with a list of arguments,
232             returns all of the method objects with the specified names.
233              
234             =cut
235              
236             for ([qw(attributes attr)], [qw(methods meth)], [qw(constructors ctor)]) {
237             my ($meth, $key) = @$_;
238 21     21   128 no strict 'refs';
  21         46  
  21         29029  
239             *{$meth} = sub {
240 118     118   64763 my $self = shift;
        52      
241 118         446 my $objs = $self->{"${key}s"};
242             # Who's talking to us?
243 118         283 my $caller = caller;
244 118         1425 for (my $i = 1; UNIVERSAL::isa($caller, __PACKAGE__); $i++) {
245 0         0 $caller = caller($i);
246             }
247             # XXX Do we want to make these additive instead of discreet, so that
248             # a class can get both protected and trusted attributes, for example?
249 118         188 my $list = do {
250 118 100       689 if (@_) {
    100          
    50          
    100          
251             # Explicit list requested.
252 98         456 \@_;
253             } elsif ($caller eq $self->{package}) {
254             # List of protected interface objects.
255 8 50       53 $self->{"priv_$key\_ord"} || [];
256             } elsif (UNIVERSAL::isa($caller, $self->{package})) {
257             # List of protected interface objects.
258 0 0       0 $self->{"prot_$key\_ord"} || [];
259             } elsif (_trusted($self, $caller)) {
260             # List of trusted interface objects.
261 7 50       41 $self->{"trst_$key\_ord"} || [];
262             } else {
263             # List of public interface objects.
264 5 50       35 $self->{"$key\_ord"} || [];
265             }
266             };
267 118 100       1045 return @$list == 1 ? $objs->{$list->[0]} : @{$objs}{@$list};
  21         155  
268             };
269             }
270              
271             ##############################################################################
272              
273             =head3 parents
274              
275             my @parents = $class->parents;
276              
277             Returns a list of Class::Meta::Class objects representing all of the
278             Class::Meta-built parent classes of a class.
279              
280             =cut
281              
282             sub parents {
283 2     2 1 6 my $self = shift;
284 2         11 return map { $_->my_class } grep { UNIVERSAL::can($_, 'my_class') }
  1         6  
  1         48  
285             Class::ISA::super_path($self->package);
286             }
287              
288             ##############################################################################
289              
290             =head3 handle_error
291              
292             $class->handle_error($error)
293              
294             Handles Class::Meta-related errors using either the error handler specified
295             when the Class::Meta::Class object was created or the default error handler at
296             the time the Class::Meta::Class object was created.
297              
298             =cut
299              
300             sub handle_error {
301 265     265 1 819 my $code = shift->{error_handler};
302 265         1362 $code->(join '', @_)
303             }
304              
305             ##############################################################################
306              
307             =head3 build
308              
309             $class->build($classes);
310              
311             This is a protected method, designed to be called only by the Class::Meta
312             class or a subclass of Class::Meta. It copies the attribute, constructor, and
313             method objects from all of the parent classes of the class object so that they
314             will be readily available from the C, C, and
315             C methods. Its sole argument is a reference to the hash of all
316             Class::Meta::Class objects (keyed off their package names) stored by
317             Class::Meta.
318              
319             Although you should never call this method directly, subclasses of
320             Class::Meta::Class may need to override its behavior.
321              
322             =cut
323              
324             sub build {
325 32     32 1 64 my ($self, $classes) = @_;
326              
327             # Check to make sure that only Class::Meta or a subclass is building
328             # attribute accessors.
329 32         86 my $caller = caller;
330 32 100 66     1455 $self->handle_error("Package '$caller' cannot call " . ref($self)
331             . "->build")
332             unless UNIVERSAL::isa($caller, 'Class::Meta')
333             || UNIVERSAL::isa($caller, __PACKAGE__);
334              
335             # Copy attributes again to make sure that overridden attributes
336             # truly override.
337 30         120 $self->_inherit($classes, qw(ctor meth attr));
338             }
339              
340             ##############################################################################
341             # Private Methods.
342             ##############################################################################
343              
344             sub _inherit {
345 74     74   191 my $self = shift;
346 74         118 my $classes = shift;
347              
348             # Get a list of all of the parent classes.
349 74         298 my $package = $self->package;
350 74         296 my @classes = reverse Class::ISA::self_and_super_path($package);
351              
352             # Hrm, how can I avoid iterating over the classes a second time?
353 74         1567 my @trusted;
354 74         161 for my $super (@classes) {
355 87 100       329 push @trusted, @{$classes->{$super}{trusted}}
  82         365  
356             if $classes->{$super}{trusted};
357             }
358 74 100       245 $self->{trusted} = \@trusted if @trusted;
359              
360             # For each metadata class, copy the parents' objects.
361 74         172 for my $key (@_) {
362 134         214 my (@lookup, @all, @ord, @prot, @trst, @priv, %sall, %sord, %sprot, %strst);
363 134         222 for my $super (@classes) {
364 155         256 my $class = $classes->{$super};
365 155 100       653 if (my $things = $class->{$key . 's'}) {
366 88         108 push @lookup, %{ $things };
  88         316  
367              
368 88 100       349 if (my $ord = $class->{"$key\_ord"}) {
369 64         85 push @ord, grep { not $sord{$_}++ } @{ $ord} ;
  127         461  
  64         117  
370             }
371              
372 88 100       327 if (my $prot = $class->{"prot_$key\_ord"}) {
373 64         102 push @prot, grep { not $sprot{$_}++ } @{ $prot };
  142         583  
  64         102  
374             }
375              
376 88 100       302 if (my $trust = $class->{"trst_$key\_ord"}) {
377 64         240 push @trst, grep { not $strst{$_}++ } @{ $trust };
  142         379  
  64         111  
378             }
379              
380 88 100       327 if (my $all = $class->{"all_$key\_ord"}) {
381 64         77 for my $name (@{ $all }) {
  64         125  
382 172 100       546 next if $sall{$name}++;
383 155         221 push @all, $name;
384 155         471 my $view = $things->{$name}->view;
385 155 100 100     865 push @priv, $name if $super eq $package
      100        
      66        
386             || $view == Class::Meta::PUBLIC
387             || $view == Class::Meta::PROTECTED
388             || _trusted($class, $package);
389             }
390             }
391             }
392             }
393              
394 134 100       520 $self->{"${key}s"} = { @lookup } if @lookup;
395 134 100       504 $self->{"$key\_ord"} = \@ord if @ord;
396 134 100       399 $self->{"all_$key\_ord"} = \@all if @all;
397 134 100       732 $self->{"prot_$key\_ord"} = \@prot if @prot;
398 134 100       377 $self->{"trst_$key\_ord"} = \@trst if @trst;
399 134 100       761 $self->{"priv_$key\_ord"} = \@priv if @priv;
400             }
401              
402              
403 74         249 return $self;
404             }
405              
406             sub _trusted {
407 26     26   52 my ($self, $caller) = @_;
408 26 50       89 my $trusted = $self->{trusted} or return;
409 26         40 for my $pkg (@{$trusted}) {
  26         61  
410 21 100       187 return 1 if UNIVERSAL::isa($caller, $pkg);
411             }
412 19         94 return;
413             }
414              
415             1;
416             __END__