File Coverage

blib/lib/Orignal.pm
Criterion Covered Total %
statement 176 184 95.6
branch 23 36 63.8
condition 16 27 59.2
subroutine 20 20 100.0
pod 2 2 100.0
total 237 269 88.1


line stmt bran cond sub pod time code
1             require 5.006_001;
2             BEGIN {
3 7     7   276399 $Orignal::VERSION = "0.04";
4             }
5             package Orignal;
6 7     7   75 use Carp();
  7         17  
  7         122  
7 7     7   35 use Exporter ();
  7         17  
  7         353  
8             BEGIN {
9 7     7   132 @ISA = qw(Exporter);
10 7         17 @EXPORT = ();
11 7         136 @EXPORT_OK = qw(%Orignal);
12             }
13 7     7   40 use strict;
  7         13  
  7         309  
14 7     7   39 use warnings;
  7         12  
  7         4526  
15             sub attributes {
16 9     9 1 4665 my $class = shift;
17            
18            
19             # Make sure it is not called out of a 'modual' context;
20 9 50       48 Carp::croak("ERROR: Orignal::$class->attributes, Somehow you managed to call this outside a modual!") if (ref($class));
21 9         25 my $self = {};
22 9   33     204 bless( $self, ( ref($class) || $class ) );
23 9         25 my ($attributes) = @_;
24             # Check $attributes
25 9 50       68 ref($attributes) eq 'HASH' || Carp::croak("ERROR: Orignal::$class->attributes, argument must be a 'HASH' reference.");
26 9 50 66     80 if (!exists($attributes->{SCALARS}) and
      66        
      66        
27             !exists($attributes->{HASHES}) and
28             !exists($attributes->{ARRAYS}) and
29             !exists($attributes->{ORDERED_HASHES})){
30 0         0 Carp::croak("ERROR: Orignal::$class->attributes, argument 'HASH' reference must has at least one key of 'SCALARS','HASHES' or 'ARRAYS'.");
31             }
32 9 50 66     79 if ( exists($attributes->{SCALARS}) and ref($attributes->{SCALARS}) ne 'ARRAY') {
33 0         0 Carp::croak("ERROR: Orignal::$class->attributes 'SCALARS', must be an 'ARRAY' reference.");
34             }
35 9 50 66     70 if ( exists($attributes->{HASHES}) and ref($attributes->{HASHES}) ne 'ARRAY') {
36 0         0 Carp::croak("ERROR: Orignal::$class->attributes 'HASHES', must be an 'ARRAY' reference.");
37             }
38 9 50 66     122 if ( exists($attributes->{ORDERED_HASHES}) and ref($attributes->{ORDERED_HASHES}) ne 'ARRAY') {
39 0         0 Carp::croak("ERROR: Orignal::$class->attributes 'ORDERED_HASHES', must be an 'ARRAY' reference.");
40             }
41 9 50 66     72 if ( exists($attributes->{ARRAYS}) and ref($attributes->{ARRAYS}) ne 'ARRAY') {
42 0         0 Carp::croak("ERROR: Orignal::$class->attributes 'ARRAYS', must be an 'ARRAY' reference.");
43             }
44            
45 9         70 $self->_install_perlish($class,$attributes);
46 9         123 return;
47             }
48             sub new {
49 9     9 1 246 my $class = shift;
50 9         23 my $self = {};
51 9   33     524 bless( $self, ( ref($class) || $class ) );
52 9         64 $self->_initialize(@_);
53 9         330 return( $self );
54             }
55             sub _attr_to_string {
56 9     9   23 my $self = shift;
57 9         19 my ($attributes) = @_;
58 9         15 my $return;
59 9         30 foreach my $type (keys(%{$attributes})) {
  9         58  
60 24         53 $return.= $type."=>[";
61 24         58 foreach my $attr (@{$attributes->{$type}}){
  24         69  
62 95         333 $return.="'$attr',";
63             }
64 24         65 $return.='],';
65             }
66 9         50 return $return;
67             }
68             sub _install_perlish {
69 9     9   22 my $self = shift;
70 9         24 my ($imp_class,$attributes) = @_;
71            
72             # set the my_attributes first;
73            
74 9 50       10705 if (!$self->can('my_attributes')){
75 9         39 my $attributes_method= "$imp_class\::my_attributes";
76 9         85 my $attributes_code = "sub {
77             return {".$self->_attr_to_string($attributes)."};
78             };";
79             {
80 7     7   50 no strict qw(refs);
  7         14  
  7         3612  
  9         19  
81 9     2   1494 my $attributes_ref = eval qq{ #line 1 "$imp_class $attributes_method "\n$attributes_code};
  2         52  
82 9         54 *$attributes_method = $attributes_ref;
83             }
84             }
85             #do the scalars next
86 9         20 my %fields;
87 9         18 foreach my $field (@{$attributes->{SCALARS}}) {
  9         37  
88 24         58 $fields{$field} = 'SCALARS';
89 24         53 my $set_method= "$imp_class\::$field";
90 24         79 my $set_code = "sub {
91             my \$self = shift;
92             if (\@_) {
93             \$self->validate_$field(\@_)
94             if \$self->can('validate_$field');
95             \$self->{$field} = shift;
96             return 1;
97             }
98             return \$self->{$field};
99             };";
100             {
101 7     7   44 no strict qw(refs);
  7         15  
  7         3638  
  24         32  
102 24         6911 my $set_code_ref = eval qq{#line 1 "$imp_class $set_method "\n$set_code};
103 24         470 *$set_method = $set_code_ref;
104             }
105             }
106 9 100       47 if (exists($attributes->{HASHES})) {
107 6         52 $self->_install_hashes($imp_class,$attributes->{HASHES},\%fields);
108             }
109 9 100       56 if (exists($attributes->{ORDERED_HASHES})) {
110 6         56 $self->_install_ordered_hashes($imp_class,$attributes->{ORDERED_HASHES},\%fields);
111             }
112 9 100       58 if (exists($attributes->{ARRAYS})) {
113 6         61 $self->_install_arrays($imp_class,$attributes->{ARRAYS},\%fields);
114             }
115 9         113 $self->{attributes} = $attributes;
116 9         71 return;
117             }
118             sub _install_hashes {
119             #do the hashes next
120 6     6   13 my $self = shift;
121 6         17 my ($imp_class,$attributes,$fields) = @_;
122 6         11 foreach my $field (@{$attributes}) {
  6         19  
123 23 50       92 if ($fields->{$field}){
124 0         0 Carp::croak("ERROR: Orignal::$imp_class->attributes, argument 'HASHES' field '$field' is also a SCALARS field!");
125             }
126 23         565 $fields->{$field} = 'HASHES';
127 23         60 my $set_get_method = "$imp_class\::$field";
128 23         49 my $delete_method = "$imp_class\::delete_$field";
129 23         42 my $keys_method = "$imp_class\::keys_$field";
130 23         48 my $values_method = "$imp_class\::values_$field";
131 23         45 my $exists_method = "$imp_class\::exists_$field";
132 23         156 my $set_get_code = "sub {
133             my \$self = shift;
134             my (\$index) = \@_;
135             unless (\$index) {
136             if (\$self->{$field}{HASH}){
137             return(wantarray ? \%{\$self->{$field}{HASH}}:scalar(\%{\$self->{$field}{HASH}}));
138             }
139            
140             }
141             if (ref(\$index) eq 'HASH') {
142             unless (scalar(\%{\$index})){
143             \$self->{$field}{HASH}={};
144             }
145             else {
146             \$self->validate_$field(\$index)
147             if \$self->can('validate_$field');
148             if (\$self->{$field}{HASH}){
149             \$self->{$field}{HASH}={\%{\$self->{$field}{HASH}},\%{\$index}};
150             }
151             else {
152             \$self->{$field}{HASH}= \$index;
153             }
154             }
155             return(wantarray ? \%{\$self->{$field}{HASH}}:scalar(\%{\$self->{$field}{HASH}}));
156             }
157             if (scalar(\@_)){
158             my \%ret=();
159             foreach my \$key (\@_){
160             last if(!\$key);
161             next if (!exists(\$self->{$field}{HASH}{\$key} ) );
162             \$ret{\$key} = \$self->{$field}{HASH}{\$key};
163             }
164             return(wantarray ? \%ret : scalar(\%ret));
165             }
166             };";
167 23         58 my $keys_code = "sub {
168             my \$self = shift;
169             return(wantarray ? keys(\%{\$self->{$field}{HASH}}):scalar(keys(\%{\$self->{$field}{HASH}})));
170             };";
171 23         49 my $values_code = "sub {
172             my \$self = shift;
173             return(wantarray ? values(\%{\$self->{$field}{HASH}}):scalar(values(\%{\$self->{$field}{HASH}})));
174             };";
175 23         64 my $delete_code = "sub {
176             my \$self = shift;
177             my \@ret_val =();
178             foreach my \$val (\@_) {
179             next if (!exists( \$self->{$field}{HASH}{\$val}));
180             push(\@ret_val,\$self->{$field}{HASH}{\$val});
181             delete(\$self->{$field}{HASH}{\$val});
182             }
183             return wantarray ? \@ret_val : pop(\@ret_val);
184             };";
185 23         40 my $exists_code = "sub {
186             my \$self = shift;
187             my \$count = 0;
188             foreach my \$val (\@_) {
189             \$count += exists( \$self->{$field}{HASH}{\$val});
190             }
191             return(\$count);
192             };";
193             {
194 7     7   46 no strict qw(refs);
  7         13  
  7         5571  
  23         36  
195 23         13158 my $set_get_code_ref = eval qq{#line 1 "$imp_class $set_get_method "\n$set_get_code};
196 23         8188 my $delete_code_ref = eval qq{#line 1 "$imp_class $delete_method "\n$delete_code};
197 23         6968 my $keys_code_ref = eval qq{#line 1 "$imp_class $keys_method "\n$keys_code};
198 23         10563 my $values_code_ref = eval qq{#line 1 "$imp_class $values_method "\n$values_code};
199 23         20133 my $exists_code_ref = eval qq{#line 1 "$imp_class $exists_method "\n$exists_code};
200 23         411 *$exists_method = $exists_code_ref;
201 23         97 *$set_get_method = $set_get_code_ref;
202 23         109 *$delete_method = $delete_code_ref;
203 23         117 *$keys_method = $keys_code_ref;
204 23         177 *$values_method = $values_code_ref;
205             }
206             }
207             }
208             sub _install_ordered_hashes {
209             #do the hashes next
210 6     6   16 my $self = shift;
211 6         20 my ($imp_class,$attributes,$fields) = @_;
212 6         13 foreach my $field (@{$attributes}) {
  6         21  
213 24 50       104 if ($fields->{$field}){
214 0         0 Carp::croak("ERROR: Orignal::$imp_class->attributes, argument 'ORDERED_HASHES' field '$field' is also a $fields->{$field} field!");
215             }
216 24         124 $fields->{$field} = 'ORDERED_HASHES';
217 24         62 my $set_get_method = "$imp_class\::$field";
218 24         50 my $delete_method = "$imp_class\::delete_$field";
219 24         50 my $keys_method = "$imp_class\::keys_$field";
220 24         46 my $values_method = "$imp_class\::values_$field";
221 24         49 my $exists_method = "$imp_class\::exists_$field";
222 24         154 my $set_get_code = "sub {
223             my \$self = shift;
224             my (\$index) = \@_;
225             unless (\$index) {
226             if(\$self->{$field}{HASH}){
227             return(wantarray ? \%{\$self->{$field}{HASH}} : scalar(\%{\$self->{$field}{HASH}}));
228             }
229             }
230            
231             if (ref(\$index) eq 'HASH') {
232             unless (scalar(\%{\$index})){
233             \$self->{$field}{HASH} ={};
234             \$self->{$field}{ARRAY}=[];
235             }
236             else {
237             \$self->validate_$field(\$index)
238             if \$self->can('validate_$field');
239             foreach my \$key (keys(\%\$index)){
240             push(\@{\$self->{$field}{ARRAY}},\$key)
241             unless (exists(\$self->{$field}{HASH}{\$key}));
242             \$self->{$field}{HASH}{\$key} = \$index->{\$key};
243             }
244             }
245             return(wantarray ? \%{\$self->{$field}{HASH}} : scalar(\%{\$self->{$field}{HASH}}));
246             }
247             if (scalar(\@_)){
248             my \%ret=();
249             foreach my \$key (\@_){
250             last if (!\$key);
251             next if (!exists(\$self->{$field}{HASH}{\$key} ) );
252             \$ret{\$key} = \$self->{$field}{HASH}{\$key};
253             }
254             if (scalar(\@_) == 1 and \$_[0]){
255             return(wantarray ? \%ret : \$ret{\$_[0]});
256             }
257             return(wantarray ? \%ret : scalar(\%ret));
258             }
259             };";
260 24         53 my $keys_code = "sub {
261             my \$self = shift;
262             return(wantarray ? \@{\$self->{$field}{ARRAY}}:scalar(\@{\$self->{$field}{ARRAY}}));
263             };";
264 24         135 my $values_code = "sub {
265             my \$self = shift;
266             my \@ret = ();
267             foreach my \$key (\@{\$self->{$field}{ARRAY}}){
268             push(\@ret,\$self->{$field}{HASH}{\$key});
269             }
270             return(wantarray ? \@ret : scalar(\@ret));
271             };";
272 24         79 my $delete_code = "sub {
273             my \$self = shift;
274             my \@ret_val =();
275             my \$del_index = 0;
276             foreach my \$val (\@_) {
277             \$del_index = 0;
278             foreach my \$item (\@{\$self->{$field}{ARRAY}}){
279             next if (!exists( \$self->{$field}{HASH}{\$val}));
280             if (\$item eq \$val){
281             push(\@ret_val,\$self->{$field}{HASH}{\$val});
282             splice( \@{\$self->{$field}{ARRAY}},\$del_index,1);
283             delete(\$self->{$field}{HASH}{\$val});
284             }
285             \$del_index++;
286             }
287             }
288             return wantarray ? \@ret_val : pop(\@ret_val);
289             };";
290 24         49 my $exists_code = "sub {
291             my \$self = shift;
292             my \$count = 0;
293             foreach my \$val (\@_) {
294             \$count += exists( \$self->{$field}{HASH}{\$val});
295             }
296             return(\$count);
297             };";
298             {
299 7     7   49 no strict qw(refs);
  7         15  
  7         3609  
  24         32  
300 24         15358 my $set_get_code_ref = eval qq{#line 1 "$imp_class $set_get_method "\n$set_get_code};
301 24         10249 my $delete_code_ref = eval qq{#line 1 "$imp_class $delete_method "\n$delete_code};
302 24         7583 my $keys_code_ref = eval qq{#line 1 "$imp_class $keys_method "\n$keys_code};
303 24         26011 my $values_code_ref = eval qq{#line 1 "$imp_class $values_method "\n$values_code};
304 24         9716 my $exists_code_ref = eval qq{#line 1 "$imp_class $exists_method "\n$exists_code};
305 24         404 *$exists_method = $exists_code_ref;
306 24         102 *$set_get_method = $set_get_code_ref;
307 24         114 *$delete_method = $delete_code_ref;
308 24         99 *$keys_method = $keys_code_ref;
309 24         292 *$values_method = $values_code_ref;
310             }
311             }
312             }
313             sub _install_arrays {
314 6     6   24 my $self = shift;
315 6         18 my ($imp_class,$attributes,$fields) = @_;
316             #do the arrays next
317 6         12 foreach my $field (@{$attributes}) {
  6         19  
318 24 50       110 if ($fields->{$field}){
319 0         0 Carp::croak("ERROR: Orignal::$imp_class->attributes, argument 'ARRAYS' field '$field' is also a $fields->{$field} field!");
320             }
321 24         63 my $pop_method = "$imp_class\::pop_$field";
322 24         55 my $push_method = "$imp_class\::push_$field";
323 24         52 my $shift_method = "$imp_class\::shift_$field";
324 24         52 my $unshift_method = "$imp_class\::unshift_$field";
325 24         47 my $set_get_method = "$imp_class\::$field";
326 24         135 my $set_get_code = "sub {
327             my \$self = shift;
328             my (\$index) = \@_;
329            
330             if (ref(\$index) eq 'ARRAY') {
331             unless (scalar(\@{\$index})){
332             \$self->{$field}{ARRAY}=[];
333             }
334             else {
335             \$self->validate_$field(\$index)
336             if \$self->can('validate_$field');
337             push(\@{\$self->{$field}{ARRAY}},\@{\$index});
338             }
339             return(wantarray ? \@{\$self->{$field}{ARRAY}} : scalar(\@{\$self->{$field}{ARRAY}}));
340             }
341             if (!\$index){
342             if (\$self->{$field}{ARRAY}){
343             return(wantarray ? \@{\$self->{$field}{ARRAY}} : scalar(\@{\$self->{$field}{ARRAY}}));
344             }
345             else {
346             return(wantarray ? () : 0);
347            
348             }
349             }
350             else {
351             my \@ret=();
352             foreach my \$index (\@_){
353             push(\@ret,\$self->{$field}{ARRAY}[\$index]);
354             }
355             return(wantarray ? \@ret : scalar(\@ret));
356             }
357            
358             };";
359 24         58 my $pop_code = "sub {
360             my \$self = shift;
361             return(pop( \@{ \$self->{$field}{ARRAY} } ));
362             };";
363 24         132 my $push_code = "sub {
364             my \$self = shift;
365             my (\$index) = \@_;
366             my \$return_count = 0;
367             if (ref(\$index) eq 'ARRAY') {
368             \$self->validate_$field(\$index)
369             if \$self->can('validate_$field');
370             \$return_count = push( \@{ \$self->{$field}{ARRAY}}, \@{\$index} );
371             }
372             else {
373             foreach my \$val (\@_) {
374             \$self->validate_$field(\$val)
375             if \$self->can('validate_$field');
376             \$return_count = push( \@{ \$self->{$field}{ARRAY}}, \$val );
377             }
378             }
379             return(\$return_count);
380             };";
381 24         54 my $shift_code = "sub {
382             my \$self = shift;
383             my \$index;
384             return(shift( \@{ \$self->{$field}{ARRAY}} ));
385             };";
386 24         70 my $unshift_code = "sub {
387             my \$self = shift;
388             my (\$index) = \@_;
389             my \$return_count = 0;
390             if (ref(\$index) eq 'ARRAY') {
391             \$self->validate_$field(\$index)
392             if \$self->can('validate_$field');
393             \$return_count = unshift( \@{ \$self->{$field}{ARRAY}}, \@{\$index} );
394             }
395             else {
396             foreach my \$val (\@_) {
397             \$return_count = unshift( \@{ \$self->{$field}{ARRAY}}, \$val );
398             }
399             }
400             return(\$return_count);
401             };";
402             {
403 7     7   47 no strict qw(refs);
  7         13  
  7         2557  
  24         45  
404 24         6115 my $pop_code_ref = eval qq{#line 1 "$imp_class $pop_method "\n$pop_code};
405 24         17546 my $push_code_ref = eval qq{#line 1 "$imp_class $push_method "\n$push_code};
406 24         6720 my $shift_code_ref = eval qq{#line 1 "$imp_class $shift_method "\n$shift_code};
407 24         9027 my $unshift_code_ref = eval qq{#line 1 "$imp_class $unshift_method "\n$unshift_code};
408 24         13125 my $set_get_code_ref = eval qq{#line 1 "$imp_class $set_get_method "\n$set_get_code};
409 24         429 *$unshift_method = $unshift_code_ref;
410 24         119 *$pop_method = $pop_code_ref;
411 24         106 *$push_method = $push_code_ref;
412 24         124 *$shift_method = $shift_code_ref;
413 24         180 *$set_get_method = $set_get_code_ref;
414             }
415             }
416             }
417             sub _initialize {
418 9     9   19 my $self = shift;
419 9 100       39 my $opt = defined($_[0]) ? shift : {};
420             # Check $opt
421 9 50       41 ref($opt) eq 'HASH' || Carp::croak("ERROR: Orignal::$self, first argument must be 'HASH' reference.");
422 9         17 foreach my $field (keys(%{$opt})) {
  9         48  
423 65 50       1577 if ($self->can($field)){
424 65         117 my $validate = 'validate_'.$field;
425 65 100       484 if ($self->can($validate)){
426 1         6 $self->$validate($opt->{$field});
427             }
428 65         313 $self->$field($opt->{$field});
429             }
430             # else {
431             # Carp::croak("ERROR: Orignal::".ref($self)."::new, Field $field not defined!");
432             # }
433             }
434             }
435            
436             1;
437             __END__