File Coverage

blib/lib/Class/Gomor/Array.pm
Criterion Covered Total %
statement 54 60 90.0
branch 9 10 90.0
condition 6 18 33.3
subroutine 12 13 92.3
pod 5 5 100.0
total 86 106 81.1


line stmt bran cond sub pod time code
1             #
2             # $Id: Array.pm 1633 2009-05-23 13:30:33Z gomor $
3             #
4             package Class::Gomor::Array;
5 6     6   5429 use strict; use warnings;
  6     6   13  
  6         271  
  6         37  
  6         15  
  6         347  
6              
7             our $VERSION = '1.02';
8              
9 6     6   2301 use Class::Gomor;
  6         14  
  6         461  
10 6     6   35 use base qw(Class::Gomor);
  6         12  
  6         541  
11              
12 6     6   4974 use Data::Dumper;
  6         45894  
  6         643  
13              
14 6     6   63 no strict 'refs';
  6         12  
  6         5046  
15              
16             sub new {
17 4     4 1 35 my $self = shift;
18 4   33     25 my $class = ref($self) || $self;
19 4         12 my %h = @_;
20 4 100       22 $class->cgCheckParams(\%h, $class->cgGetAttributes)
21             unless $Class::Gomor::NoCheck;
22 4         9 my @obj;
23 4         10 my $base = $class.'::__';
24 4         14 $obj[${$base.$_}] = $h{$_} for keys %h;
  4         15  
25 4         23 bless(\@obj, $class);
26             }
27              
28             sub cgGetIndice {
29 8     8 1 78 my $self = shift;
30 8   33     12 ${(ref($self) || $self).'::__'.shift()};
  8         64  
31             }
32              
33             sub cgBuildIndices {
34 4     4 1 194 my $self = shift;
35 4         9 my $i = 0;
36 4   33     6 ${(ref($self) || $self).'::__'.$_} = $i++ for @{$self->cgGetAttributes};
  4         49  
  12         117  
37             }
38              
39             sub cgFullClone {
40 11     11 1 18 my $self = shift;
41 11         12 my ($n) = @_;
42 11 100       34 return $self->SUPER::cgFullClone($n) if $n;
43 10   33     21 my $class = ref($self) || $self;
44 10         13 my @new;
45 10         16 for (@$self) {
46 30 50 66     107 (ref($_) && UNIVERSAL::isa($_, 'Class::Gomor'))
47             ? push @new, $_->cgFullClone
48             : push @new, $_;
49             }
50 10         46 bless(\@new, $class);
51             }
52              
53             sub cgDumper {
54 0     0 1 0 my $self = shift;
55 0   0     0 my $class = ref($self) || $self;
56 0         0 my %h = map { $_ => $self->[$self->cgGetIndice($_)] }
  0         0  
57 0         0 @{$class->cgGetAttributes};
58 0         0 Dumper(\%h);
59             }
60              
61             sub _cgAccessorScalar {
62 15     15   25 my $self = shift;
63 15         19 my $a = shift;
64 7         30 @_ ? $self->[${ref($self).'::__'.$a}] = shift
  8         185  
65 15 100       120 : $self->[${ref($self).'::__'.$a}];
66             }
67              
68             sub _cgAccessorArray {
69 6     6   8 my $self = shift;
70 6         11 my $a = shift;
71 2         9 @_ ? $self->[${ref($self).'::__'.$a}] = shift
  4         48  
72 6 100       19 : @{$self->[${ref($self).'::__'.$a}]};
  4         5  
73             }
74              
75             1;
76              
77             =head1 NAME
78              
79             Class::Gomor::Array - class and object builder, array version
80              
81             =head1 SYNPOSIS
82              
83             # Create a base class in BaseClass.pm
84             package My::BaseClass;
85              
86             require Class::Gomor::Array;
87             our @ISA = qw(Class::Gomor::Array);
88              
89             our @AS = qw(attribute1 attribute2);
90             our @AA = qw(attribute3 attribute4);
91             our @AO = qw(other);
92              
93             # You should initialize yourself array attributes
94             sub new { shift->SUPER::new(attribute3 => [], attribute4 => [], @_) }
95              
96             # Create indices and accessors
97             My::BaseClass->cgBuildIndices;
98             My::BaseClass->cgBuildAccessorsScalar(\@AS);
99             My::BaseClass->cgBuildAccessorsArray(\@AA);
100              
101             sub other {
102             my $self = shift;
103             @_ ? $self->[$self->cgGetIndice('other')] = [ split(/\n/, shift) ]
104             : @{$self->[$self->cgGetIndice('other')]};
105             }
106              
107             1;
108              
109             # Create a subclass in SubClass.pm
110             package My::SubClass;
111              
112             require My::BaseClass;
113             our @ISA = qw(My::BaseClass);
114              
115             our @AS = qw(subclassAttribute);
116              
117             My::SubClass->cgBuildIndices;
118             My::SubClass->cgBuildAccessorsScalar(\@AS);
119              
120             sub new {
121             shift->SUPER::new(
122             attribute1 => 'val1',
123             attribute2 => 'val2',
124             attribute3 => [ 'val3', ],
125             attribute4 => [ 'val4', ],
126             other => [ 'none', ],
127             subclassAttribute => 'subVal',
128             );
129             }
130              
131             1;
132              
133             # A program using those classes
134              
135             my $new = My::SubClass->new;
136              
137             my $val1 = $new->attribute1;
138             my @values3 = $new->attribute3;
139             my @otherOld = $new->other;
140              
141             $new->other("str1\nstr2\nstr3");
142             my @otherNew = $new->other;
143             print "@otherNew\n";
144              
145             $new->attribute2('newValue');
146             $new->attribute4([ 'newVal1', 'newVal2', ]);
147              
148             =head1 DESCRIPTION
149              
150             This class is a subclass from B. It implements objects as array references, and inherits methods from B.
151              
152             =head1 GLOBAL VARIABLES
153              
154             See B.
155              
156             =head1 METHODS
157              
158             =over 4
159              
160             =item B (hash)
161              
162             Object constructor. This is where user passed attributes (hash argument) are checked against valid attributes (gathered by B method). Valid attributes are those that exists (doh!), and have not an undef value. The default is to check this, you can avoid it by setting B<$NoCheck> global variable (see perldoc B).
163              
164             =item B
165              
166             You MUST call this method one time at the beginning of your classes, and all subclasses (even if you do not add new attributes). It will build the matching between object attributes and their indices inside the array object. Global variables will be created in your class, with the following format: B<$__attributeName>.
167              
168             =item B (array ref)
169              
170             =item B (array ref)
171              
172             See B.
173              
174             =item B (scalar)
175              
176             Returns the array indice of specified attribute passed as a parameter. You can use it in your programs to avoid calling directly the global variable giving indice information concerning requesting object, thus avoiding using `no strict 'vars';'. This method is usually used when you build your own accessors (those using attributes defined in B<@AO>).
177              
178             =item B [ (scalar) ]
179              
180             You can clone one of your objects by calling this method. An optional parameter may be used to create multiple clones. Cloning will occure only on the first level attributes, that is, if you have attributes containing other objects, they will not be cloned.
181              
182             =item B [ (scalar) ]
183              
184             This method is the same as B, but will clone all attributes recursively, but only if they are subclassed from B. So, objects created with other modules than B or B will not be cloned.
185              
186             Another thing to note, there is no catch for cycling references (when you link two objects with each others). You have been warned.
187              
188             =item B
189              
190             Will return a string as with B Dumper method. This is useful for debugging purposes, because an arrayref object does not include attributes names.
191              
192             =back
193              
194             =head1 SEE ALSO
195              
196             L
197              
198             =head1 AUTHOR
199            
200             Patrice EGomoRE Auffret
201            
202             =head1 COPYRIGHT AND LICENSE
203            
204             Copyright (c) 2004-2009, Patrice EGomoRE Auffret
205              
206             You may distribute this module under the terms of the Artistic license.
207             See LICENSE.Artistic file in the source distribution archive.
208              
209             =cut