File Coverage

blib/lib/Lang/Tree/Builder/Class.pm
Criterion Covered Total %
statement 63 89 70.7
branch 19 32 59.3
condition 1 2 50.0
subroutine 17 20 85.0
pod 12 15 80.0
total 112 158 70.8


line stmt bran cond sub pod time code
1             package Lang::Tree::Builder::Class;
2              
3 6     6   24053 use strict;
  6         13  
  6         213  
4 6     6   52 use warnings;
  6         11  
  6         183  
5 6     6   4527 use Lang::Tree::Builder::Scalar;
  6         16  
  6         184  
6 6     6   2945 use Lang::Tree::Builder::Args;
  6         15  
  6         7821  
7              
8             our $VERSION = '0.01';
9              
10              
11             =head1 NAME
12              
13             Lang::Tree::Builder::Data - Tree Data
14              
15             =head1 SYNOPSIS
16              
17             use Lang::Tree::Builder::Parser;
18             my $parser = new Lang::Tree::Builder::Parser();
19             my $data = $parser->parseFile($datafile);
20             foreach my $class ($data->classes()) {
21             my $parent = $class->parent();
22             my @args = $class->args();
23             my $name = $class->name();
24             # etc
25             }
26              
27             This package contains an ever-growing list of accessor methods
28             to make the maintainance and extension of templates easy.
29             See below for the full list.
30              
31             =head1 DESCRIPTION
32              
33             =head2 new
34              
35             my $class = new Lang::Tree::Builder::Class(%params);
36              
37             Creates and returns a new instance of Class. Don't do this, the parser
38             does it for you, however for reference, C<%params> is:
39              
40             =over 4
41              
42             =item class
43              
44             The class name.
45              
46             =item parent
47              
48             The parent class name, if any.
49              
50             =item args
51              
52             The arguments to the constructor,
53             will be passed to L
54              
55             =item abstract
56              
57             True if the class was declared abstract.
58              
59             =back
60              
61             Note that each class is unique, and that additional calls to C
62             may be used to add information to an existing class object which
63             will then be returned. It is an error for new information to conflict
64             with existing information however.
65              
66             =cut
67              
68             {
69             my %symbols;
70              
71             sub new {
72 18     18 1 1519 my ($class, %params) = @_;
73 18 50       51 die "no class specified" unless $params{class};
74 18         27 my $name = $params{class};
75 18 100       47 unless (exists $symbols{$name}) {
76 11 100       32 if ($name eq 'scalar') {
77 1         8 return new Lang::Tree::Builder::Scalar();
78             } else {
79 10         89 $symbols{$name} = bless {
80             _name => $name,
81             _substantial => 0,
82             _abstract => 0,
83             _parent => 0,
84             _children => {},
85             _args => 0,
86             }, $class;
87             }
88             }
89 17         61 my $self = $symbols{$name};
90 17 100       99 $self->{parts} = [ split(/::/, $self->{_name}) ] unless $self->{parts};
91 17 100       48 if ($params{parent}) {
92 2         6 my $parent = $params{parent};
93 2 50       10 if ($self->{_parent}) {
94 0 0       0 die "parent conflict on $name: ",
95             $self->{_parent}->name(),
96             " ne $parent"
97             unless $self->{_parent}->name() eq $parent;
98             } else {
99 2         25 $self->{_parent} = $class->new(class => $parent);
100             }
101 2         10 $self->{_parent}->_acceptChild($self);
102             }
103 17 100       47 if ($params{args}) {
104 2         4 my @args = @{$params{args}};
  2         6  
105 2 50       46 if ($self->{_args}) {
106 0         0 my @argnames = map {$_->name} @{$self->{_args}};
  0         0  
  0         0  
107 0         0 my $l1 = '(' . join(', ', @args) . ')';
108 0         0 my $l2 = '(' . join(', ', @argnames) . ')';
109 0 0       0 die "args conflict on $name: $l1 ne $l2" unless $l1 eq $l2;
110             } else {
111 2         21 $self->{_args} = Lang::Tree::Builder::Args->List($params{args});
112             }
113             }
114 17 50       48 if ($params{abstract}) {
115 0         0 $self->{_abstract} = 1;
116             }
117 17         71 return $self;
118             }
119             }
120              
121             sub _acceptChild {
122 2     2   5 my ($self, $child) = @_;
123 2         9 $self->{_children}{$child->name} = $child;
124             }
125              
126             sub descendants {
127 0     0 0 0 my ($self) = @_;
128 0         0 my @descendants = ();
129 0         0 foreach my $child ( values %{$self->{_children}} ) {
  0         0  
130 0         0 push @descendants, $child;
131 0         0 push @descendants, $child->descendants;
132             }
133 0         0 return sort @descendants;
134             }
135              
136             =head2 name
137              
138             Returns the fully qualified class name, with parts joined by C<::>
139             by default. An alternative join string can be passed as an optional
140             argument.
141              
142             =cut
143              
144             sub name {
145 13     13 1 980 my ($self, $join) = @_;
146 13 50       41 $join = '::' unless defined $join;
147 13         35 return join($join, $self->parts);
148             }
149              
150             =head2 parent
151              
152             Returns the parent class, or false if no parent.
153              
154             =cut
155              
156             sub parent {
157 2     2 1 6 my ($self) = @_;
158 2         9 return $self->{_parent};
159             }
160              
161             =head2 args
162              
163             Returns an array of arguments to the constructor.
164             Each element is a C.
165              
166             =cut
167              
168             sub args {
169 2     2 1 6 my ($self) = @_;
170 2 50       8 return wantarray ? @{$self->{_args}} : $self->{_args};
  2         11  
171             }
172              
173             =head2 numargs
174              
175             Returns the number of args the constructor accepts.
176              
177             =cut
178              
179             sub numargs {
180 0     0 1 0 my ($self) = @_;
181 0         0 return scalar(@{$self->{_args}});
  0         0  
182             }
183              
184             =head2 parts
185              
186             Returns an array or arrayref of the components of the class name.
187             For example C has parts C and C.
188              
189             =cut
190              
191             sub parts {
192 14     14 1 24 my ($self) = @_;
193 14 100       42 return wantarray ? @{$self->{parts}} : $self->{parts};
  13         105  
194             }
195              
196             =head2 lastpart
197              
198             Returns the last component of C above.
199              
200             =cut
201              
202             sub lastpart {
203 7     7 1 12 my ($self) = @_;
204 7         52 return $self->{parts}[-1];
205             }
206              
207             =head2 namespace
208              
209             Returns all but the last component of C, joined with C<::> by default,
210             but an alternative can be supplied as an optional argument.
211              
212             =cut
213              
214             sub namespace {
215 1     1 1 3 my ($self, $join) = @_;
216 1 50       5 $join = '::' unless defined $join;
217 1         2 my @parts = @{$self->{parts}};
  1         4  
218 1         2 pop @parts;
219 1   50     9 return join('::', @parts) || 'main';
220             }
221              
222             =head2 interface
223              
224             Returns an equivalent interface name by prepending a literal C to the
225             last part of the class name.
226              
227             =cut
228              
229             sub interface {
230 0     0 1 0 my ($self, $join) = @_;
231 0 0       0 $join = '::' unless defined $join;
232 0         0 my @parts = @{$self->{parts}};
  0         0  
233 0         0 my $lastpart = pop @parts;
234 0         0 $lastpart = 'i' . $lastpart;
235 0         0 push @parts, $lastpart;
236 0         0 return join($join, @parts);
237             }
238              
239             =head2 is_scalar
240              
241             Returns false
242              
243             =cut
244              
245 1     1 1 6 sub is_scalar { 0 }
246              
247             # internal, sets a flag to say the class has a definition.
248             sub substantiate {
249 3     3 0 9 my ($self) = @_;
250 3         16 $self->{_substantial} = 1;
251             }
252              
253             =head2 is_substantioal
254              
255             Returns true if the class was defined in the config (as opposed to merely
256             being used as an argument type). Not to be confused with C.
257              
258             =cut
259              
260             sub is_substantial {
261 4     4 0 607 my ($self) = @_;
262 4         22 return $self->{_substantial};
263             }
264              
265             =head2 is_abstract
266              
267             Returns true if the class was declared abstract.
268              
269             =cut
270              
271             sub is_abstract {
272 1     1 1 4 my ($self) = @_;
273 1         5 return $self->{_abstract};
274             }
275              
276             =head2 is_concrete
277              
278             Returns true if the class was not declared abstract. N.b. a class is
279             concrete by default, C could still return false for
280             the same class.
281              
282             =cut
283              
284             sub is_concrete {
285 1     1 1 2 my ($self) = @_;
286 1         6 return !$self->{_abstract};
287             }
288              
289             =head1 SEE ALSO
290              
291             L
292              
293             =head1 AUTHOR
294              
295             Bill Hails, Eme@billhails.netE
296              
297             =head1 COPYRIGHT AND LICENSE
298              
299             Copyright (C) 2008 by Bill Hails
300              
301             This library is free software; you can redistribute it and/or modify
302             it under the same terms as Perl itself, either Perl version 5.8.8 or,
303             at your option, any later version of Perl 5 you may have available.
304              
305             =cut
306              
307             1;