File Coverage

blib/lib/Class/Data/TIN.pm
Criterion Covered Total %
statement 152 165 92.1
branch 48 72 66.6
condition 29 38 76.3
subroutine 24 24 100.0
pod 4 5 80.0
total 257 304 84.5


line stmt bran cond sub pod time code
1             package Class::Data::TIN;
2              
3             # ABSTRACT: DEPRECATED - Translucent, Inheritable, Nonpolluting class data
4             our $VERSION = '0.03'; # VERSION
5              
6 1     1   73441 use 5.006;
  1         12  
7 1     1   6 use strict;
  1         1  
  1         21  
8 1     1   4 use warnings;
  1         2  
  1         54  
9              
10             warn __PACKAGE__ .' is DEPRECATED, please do not use this module anymore';
11              
12 1     1   538 use Class::DispatchToAll qw(dispatch_to_all);
  1         536  
  1         62  
13              
14             require Exporter;
15              
16 1     1   7 use Carp;
  1         2  
  1         48  
17 1     1   708 use Data::Dumper;
  1         7308  
  1         595  
18              
19             our @ISA = qw(Exporter);
20             our @EXPORT_OK = ('get_classdata','set_classdata','append_classdata','merge_classdata');
21              
22             our $stop="_tinstop";
23              
24             # not exported, has to be called explicitly with Class::Data::TIN->new()
25             sub new {
26 6     6 1 890 shift; # remove own ClassName 'Class::Data::TIN'
27 6         12 my $org_package=shift; # get name of package to store vars in
28 6         14 my $data=_import_data(@_);
29              
30 6 50 33     30 croak("data structure must be a hashref") if ($data && ref($data) ne "HASH");
31              
32 6         18 my $tin_package=__PACKAGE__."::".$org_package;
33              
34             ### put data into TIN
35             # start eval-string
36 6         10 my $install="package $tin_package;";
37              
38             # add ISA's
39 6         303 my @isa=eval "@".$org_package."::ISA";
40 6         19 my @isa_tin;
41 6         14 foreach (@isa) {
42 5         14 push(@isa_tin,__PACKAGE__."::".$_);
43             }
44 6 100       24 $install.='our @ISA=(qw ('."@isa_tin".'));' if @isa_tin;
45              
46             # $install.='$'.__PACKAGE__.'::_tin=$data;';
47 6         12 $install.='our $_tin=$data;';
48              
49 6         461 eval $install;
50 6 50       24 croak $@ if $@;
51              
52             # generate accessor methods in $tin_package
53 6         22 for my $key (keys %$data) {
54 9         20 _make_accessor($tin_package,$key);
55             }
56              
57             # return empty fake pseudo obj, to make calling get/set/append easier
58             # this is /not/ blessed, in fact, its just an alias to __PACKAGE__
59 6         26 return $org_package;
60             }
61              
62             # not exported
63             sub _import_data {
64 14     14   21 my $data;
65 14 100       35 if (@_ == 1) { # one param passed
66 10         17 my $param=shift;
67 10 50       29 if (ref($param) eq 'HASH') { # is it a HASH ref ?
    0          
68 10         18 $data=$param;
69             } elsif (-e $param) { # or is it a file ?
70 0         0 $data=do $param;
71 0 0       0 unless ($data) {
72 0 0       0 croak("couldn't parse $param: $@") if $@;
73 0 0       0 croak("couldn't do $param: $!") unless defined $data;
74             }
75             } else { # then something is wrong
76 0         0 croak("param is neither HASH REF nor file ...");
77             }
78             } else { # more params passed, treat as HASH
79 4         9 $data={@_};
80             }
81 14         25 return $data;
82             }
83              
84             sub _save_val {
85 52     52   100 my ($pkg,$key,$val,$stopper)=@_;
86              
87             # if (ref($val) eq "ARRAY" && $val->[0] eq $stop) {
88             # $val=$val->[1];
89             # }
90              
91 52 100 100     122 if ($stopper && $stopper>0) {
92 8         18 $val=[$stop,$val];
93             }
94              
95 52         105 my $install='$'.$pkg.'::_tin->{$key}=$val';
96 52         2917 eval $install;
97 52 50       206 croak($@) if $@;
98              
99 52         150 _make_accessor($pkg,$key);
100              
101 52         147 return;
102             }
103              
104             sub _make_accessor {
105 61     61   124 my ($pkg,$key)=@_;
106 1     1   8 no strict "refs";
  1         3  
  1         266  
107 61         134 my $accessor=$pkg."::".$key;
108 61 100       249 return if *$accessor{CODE}; # there is allready an accessor
109              
110 30         1140 my $r_tin=eval '$'."$pkg".'::_tin';
111 30 50       97 croak($@) if $@;
112              
113             *$accessor = sub {
114 288     288   15202 my $self=shift;
115 288 50       601 $r_tin->{$key} = shift if @_;
116 288         672 return $r_tin->{$key};
117 30         183 };
118 30         66 return;
119             }
120              
121             # ueberschreibt den aktuellen Wert in der package mit dem neuen
122             # geht mit einem wert
123             sub set_classdata {
124 18     18 1 1194 my ($self,$key,$val,$stopper)=@_;
125 18   33     52 my $package=ref($self) || $self;
126              
127 18         41 my $tin=__PACKAGE__."::".$package;
128 18         53 _save_val($tin,$key,$val,$stopper);
129 18         57 return $tin->$key();
130             }
131              
132             # haengt daten an die daten in der aktuellen package dran
133             # geht mit einem wert
134             # copy on write
135             sub append_classdata {
136 15     15 1 42 my ($self,$key,$val,$stopper)=@_;
137 15 50       36 return unless $val;
138 15   66     39 my $package=ref($self) || $self;
139              
140             # aktuellen wert hohlen
141 1     1   18 no strict 'refs';
  1         2  
  1         157  
142 15         35 my $tin=__PACKAGE__."::".$package;
143 15         24 my $rtin=$tin."::_tin";
144 15         53 my $oldval=$$rtin->{$key};
145              
146             # neuen wert dranhaengen
147 15 100       36 if ($oldval) {
148 13         30 ($val,$stopper)=_merge($oldval,$val,$stopper);
149             }
150              
151 15         42 _save_val($tin,$key,$val,$stopper);
152 15         38 return;
153             }
154              
155             # wie append, nur mit mehreren vals auf einmal
156             sub merge_classdata {
157 8     8 0 64 my $self=shift;
158 8   66     29 my $package=ref($self) || $self;
159 8         23 my $data=_import_data(@_);
160              
161 1     1   7 no strict 'refs';
  1         4  
  1         564  
162 8         22 my $tin=__PACKAGE__."::".$package;
163 8         16 my $rtin=$tin."::_tin";
164              
165 8         38 while (my ($key,$val)=each %$data) {
166 19         28 my $stopper;
167 19         57 my $oldval=$$rtin->{$key};
168 19 100 66     53 if ($oldval && $val) {
169 4         11 ($val,$stopper)=_merge($oldval,$val);
170             }
171 19         37 _save_val($tin,$key,$val,$stopper);
172             }
173 8         19 return;
174             }
175              
176             sub _merge {
177 17     17   31 my ($oldval,$newval,$stopper)=@_;
178              
179 17         31 my $ref=ref($oldval);
180 17         24 my $refnew=ref($newval);
181              
182 17 100 100     65 if ($ref eq "ARRAY" && $oldval->[0] eq $stop) {
183 4         6 $oldval=$oldval->[1];
184 4         8 $ref=ref($oldval);
185 4         8 $stopper++;
186             }
187              
188 17 100 100     45 if ($refnew eq "ARRAY" && $newval->[0] eq $stop) {
189 1         3 $newval=$newval->[1];
190 1         5 $refnew=ref($newval);
191 1         3 $stopper++;
192             }
193              
194 17 100 66     68 if (!$ref || $ref eq "SCALAR") {
    100          
    50          
    0          
195 4 100       9 if ($refnew eq "SCALAR") {
196 1         3 $oldval=$newval;
197             } else {
198 3 50       7 if ($ref eq "SCALAR") {
199 0         0 my $v=$$oldval;
200 0         0 $v.=$newval;
201 0         0 $oldval=\$v;
202             } else {
203 3         7 $oldval.=$newval;
204             }
205             }
206             } elsif ($ref eq "HASH") {
207 6 50       18 if (!$refnew) {
    50          
208 0         0 $oldval={%$oldval,$newval};
209             } elsif ($refnew eq "HASH") {
210 6         25 $oldval={%$oldval,%$newval};
211             } else {
212 0         0 croak("type mismatch!");
213             }
214             } elsif ($ref eq "ARRAY") {
215 7 50       18 if (!$refnew) {
    50          
216 0         0 push(@$oldval,$newval);
217             } elsif ($refnew eq "ARRAY") {
218 7         16 push(@$oldval,@$newval);
219             } else {
220 0         0 croak("type mismatch!");
221             }
222             } elsif ($ref eq "CODE") {
223 0         0 croak("cannot append/merge code ref");
224             }
225              
226 17         46 return ($oldval,$stopper);
227             }
228              
229              
230             sub get_classdata {
231 84     84 1 1307 my ($self,$key)=@_;
232 84   66     219 my $package=ref($self) || $self;
233 84         160 my $tin=__PACKAGE__."::".$package;
234              
235 84         210 my @vals=dispatch_to_all($tin,$key);
236 84 100       5734 return unless @vals;
237              
238             # peek at first val of @vals to decide data type
239 82         179 my $ref=ref($vals[0]);
240              
241             # check if stoptin caused wrong ref
242 82 100 100     290 if ($ref eq "ARRAY" && $vals[0]->[0] eq $stop) {
243 9         19 $ref=ref($vals[0]->[1]);
244             }
245              
246 82   100     218 $ref||="SCALAR";
247              
248 82         157 my $get='_get_'.$ref;
249 82         126 my $return;
250 1     1   8 no strict 'refs';
  1         2  
  1         323  
251 82         152 foreach my $v (reverse @vals) {
252 270 100       459 next unless $v;
253 269 100 100     632 if (ref($v) eq "ARRAY" && $v->[0] eq $stop) {
254 17         39 $return=$get->(undef,$v->[1]);
255             # my $overwrite=$v->[1];
256             # if ($ref eq "ARRAY") {
257             # $return=[];
258             # push(@$return,@$overwrite);
259             # } else {
260             # $return=$overwrite;
261             # }
262             } else {
263 252         491 $return=$get->($return,$v);
264             }
265             }
266 82         466 return $return;
267             }
268              
269              
270             sub _get_SCALAR {
271 72     72   120 my ($ret,$val)=@_;
272 72         101 my $r=ref($val);
273 72 100       109 if (!$r) {
    50          
274 66         115 $ret.=$val;
275             } elsif ($r eq "SCALAR") {
276 6         10 $ret=$$val;
277             }
278 72         156 return $ret;
279             }
280              
281             sub _get_ARRAY {
282 84     84   134 my ($ret,$val)=@_;
283 84         169 push(@$ret,@$val);
284 84         173 return $ret;
285             }
286              
287             sub _get_HASH {
288 104     104   172 my ($ret,$val)=@_;
289 104 100       185 if (! defined $ret) {
290 36         55 $ret=$val;
291             } else {
292 68         343 $ret={%$ret,%$val};
293             }
294 104         287 return $ret;
295             }
296              
297             sub _get_CODE {
298 9     9   18 my ($ret,$val)=@_;
299 9         18 return $val;
300             }
301              
302             1;
303              
304             __END__