File Coverage

blib/lib/Data/BISON/Base.pm
Criterion Covered Total %
statement 47 80 58.7
branch 9 22 40.9
condition 2 6 33.3
subroutine 9 17 52.9
pod 0 1 0.0
total 67 126 53.1


line stmt bran cond sub pod time code
1             package Data::BISON::Base;
2              
3 4     4   25 use warnings;
  4         11  
  4         166  
4 4     4   22 use strict;
  4         10  
  4         210  
5 4     4   24 use Carp;
  4         10  
  4         394  
6 4     4   22 use base qw(Exporter);
  4         52  
  4         1339  
7              
8             our @ISA;
9              
10             sub new {
11 3     3 0 72 my $class = shift;
12 3   33     28 my $self = bless {}, ref $class || $class;
13              
14 3         6 my $args = {};
15 3 50       12 if ( @_ ) {
16 3         7 $args = shift;
17 3 50 33     24 croak "The only argument to new must be a hash reference of options"
18             if @_ || ref $args ne 'HASH';
19             }
20              
21 3         23 $self->_pre_init( $args );
22 3         13 $self->__parse_args( $args );
23 0         0 $self->_initialize( $args );
24              
25 0 0       0 if ( my @extra = sort keys %$args ) {
26 0         0 croak "Illegal option(s): ", join( ', ', @extra );
27             }
28              
29 0         0 return $self;
30             }
31              
32 3     3   4 sub _pre_init { }
33 0     0   0 sub __parse_args { }
34 0     0   0 sub _initialize { }
35              
36             # Generate methods
37             sub import {
38 14     14   3497 my $class = shift;
39 14         29 my $caller = caller;
40              
41 14 100       1269 if ( my $attr_spec = shift ) {
42 4     4   47 no strict 'refs';
  4         9  
  4         2866  
43              
44             my %default = (
45              
46             # Capabilities i=init, s=set
47             can => 'is',
48              
49             # Set the value of an attribute
50             set => sub {
51 0     0   0 my $self = shift;
52 0         0 my $attr = shift;
53 0         0 my $val = shift;
54 0         0 $self->{$attr} = $val;
55             },
56              
57             # Get the value of an attribute
58             get => sub {
59 0     0   0 my $self = shift;
60 0         0 my $attr = shift;
61 0         0 return $self->{$attr};
62             },
63              
64             # Return the default value for an attribute
65             default => sub {
66 0     0   0 my $self = shift;
67 0         0 my $attr = shift;
68 0         0 croak "Option $attr is required";
69             },
70 6         53 );
71              
72 6         33 while ( my ( $attr, $spec ) = each %$attr_spec ) {
73 12         43 while ( my ( $handler, $def ) = each %default ) {
74 48 100       187 $spec->{$handler} = $def unless exists $spec->{$handler};
75             }
76              
77             # Turn keys that map to a value into a sub that returns
78             # that value
79 12         18 for my $handler ( qw( get default ) ) {
80 24 100       83 unless ( ref $spec->{$handler} eq 'CODE' ) {
81 12         16 my $value = $spec->{$handler};
82 12     0   51 $spec->{$handler} = sub { return $value };
  0         0  
83             }
84             }
85              
86             # Getter / setter
87 12         23 my $getter = $spec->{get};
88 12 50       35 if ( $spec->{can} =~ /s/ ) {
89 12         15 my $setter = $spec->{set};
90 12         90 *{ $caller . '::' . $attr } = sub {
91 0     0   0 my $self = shift;
92 0 0       0 return $getter->( $self, $attr ) unless @_;
93 0         0 return $setter->( $self, $attr, @_ );
94 12         36 };
95             }
96             else {
97 0         0 *{ $caller . '::' . $attr } = sub {
98 0     0   0 my $self = shift;
99 0 0       0 return $getter->( $self, $attr ) unless @_;
100 0         0 croak "Attribute $attr is read-only";
101 0         0 };
102             }
103             }
104              
105 6         9623 *{ $caller . '::__parse_args' } = sub {
106 3     3   6 my $self = shift;
107 3         6 my $args = shift;
108              
109             {
110 3         5 local @ISA = @{ $caller . '::ISA' };
  3         6  
  3         1003  
111 0           $self->SUPER::__parse_args( $args );
112             }
113              
114 0           while ( my ( $attr, $spec ) = each %$attr_spec ) {
115 0           my @value;
116 0 0         if ( exists $args->{$attr} ) {
117 0 0         croak "Argument $attr can not be set during initialisation"
118             unless $spec->{can} =~ /i/;
119 0           @value = delete $args->{$attr};
120             }
121             else {
122 0           @value = $spec->{default}->( $self, $attr );
123             }
124 0           $spec->{set}->( $self, $attr, @value );
125             }
126 6         24 };
127             }
128             }
129              
130             1;
131             __END__