File Coverage

blib/lib/Data/Hive.pm
Criterion Covered Total %
statement 64 74 86.4
branch 35 36 97.2
condition 5 5 100.0
subroutine 17 22 77.2
pod 11 12 91.6
total 132 149 88.5


line stmt bran cond sub pod time code
1 4     4   130973 use strict;
  4         36  
  4         111  
2 4     4   19 use warnings;
  4         8  
  4         194  
3             package Data::Hive 1.014;
4             # ABSTRACT: convenient access to hierarchical data
5              
6 4     4   22 use Carp ();
  4         6  
  4         1301  
7              
8             #pod =head1 SYNOPSIS
9             #pod
10             #pod use Data::Hive;
11             #pod
12             #pod my $hive = Data::Hive->NEW(\%arg);
13             #pod
14             #pod $hive->foo->bar->quux->SET(17);
15             #pod
16             #pod print $hive->foo->bar->quux->GET; # 17
17             #pod
18             #pod =head1 DESCRIPTION
19             #pod
20             #pod Data::Hive doesn't do very much. Its main purpose is to provide a simple,
21             #pod consistent interface for accessing simple, nested data dictionaries. The
22             #pod mechanism for storing or consulting these dictionaries is abstract, so it can
23             #pod be replaced without altering any of the code that reads or writes the hive.
24             #pod
25             #pod A hive is like a set of nested hash references, but with a few crucial
26             #pod differences:
27             #pod
28             #pod =begin :list
29             #pod
30             #pod * a hive is always accessed by methods, never by dereferencing with C<< ->{} >>
31             #pod
32             #pod For example, these two lines perform similar tasks:
33             #pod
34             #pod $href->{foo}->{bar}->{baz}
35             #pod
36             #pod $hive->foo->bar->baz->GET
37             #pod
38             #pod * every key may have a value as well as children
39             #pod
40             #pod With nested hashrefs, each entry is either another hashref (representing
41             #pod children in the tree) or a leaf node. With a hive, each entry may be either or
42             #pod both. For example, we can do this:
43             #pod
44             #pod $hive->entry->SET(1);
45             #pod
46             #pod $hive->entry->child->SET(1)
47             #pod
48             #pod This wouldn't be possible with a hashref, because C<< $href->{entry} >> could
49             #pod not hold both another node and a simple value.
50             #pod
51             #pod It also means that along the ways to existing values in a hive, there might be
52             #pod paths with no existing value.
53             #pod
54             #pod $hive->NEW(...); # create a new hive with no entries
55             #pod
56             #pod $hive->foo->bar->baz->SET(1); # set a single value
57             #pod
58             #pod $hive->foo->EXISTS; # false! no value exists here
59             #pod
60             #pod grep { 'foo' eq $_ } $hive->KEYS; # true! we can descent down this path
61             #pod
62             #pod $hive->foo->bar->baz->EXISTS; # true! there is a value here
63             #pod
64             #pod * hives are accessed by path, not by name
65             #pod
66             #pod When you call C<< $hive->foo->bar->baz->GET >>, you're not accessing several
67             #pod substructures. You're accessing I hive. When the C method is
68             #pod reached, the intervening names are converted into an entry path and I is
69             #pod accessed. Paths are made of zero or more non-empty strings. In other words,
70             #pod while this is legal:
71             #pod
72             #pod $href->{foo}->{''}->baz;
73             #pod
74             #pod It is not legal to have an empty part in a hive path.
75             #pod
76             #pod =end :list
77             #pod
78             #pod =head1 WHY??
79             #pod
80             #pod By using method access, the behavior of hives can be augmented as needed during
81             #pod testing or development. Hives can be easily collapsed to single key/value
82             #pod pairs using simple notations whereby C<< $hive->foo->bar->baz->SET(1) >>
83             #pod becomes C<< $storage->{"foo.bar.baz"} = 1 >> or something similar.
84             #pod
85             #pod This, along with the L API makes it very easy to swap out
86             #pod the storage and retrieval mechanism used for keeping hives in persistent
87             #pod storage. It's trivial to persist entire hives into a database, flatfile, CGI
88             #pod query, or many other structures, without using weird tricks beyond the weird
89             #pod trick that is Data::Hive itself.
90             #pod
91             #pod =head1 METHODS
92             #pod
93             #pod =head2 hive path methods
94             #pod
95             #pod All lowercase methods are used to travel down hive paths.
96             #pod
97             #pod When you call C<< $hive->some_name >>, the return value is another Data::Hive
98             #pod object using the same store as C<$hive> but with a starting path of
99             #pod C. With that hive, you can descend to deeper hives or you can get
100             #pod or set its value.
101             #pod
102             #pod Once you've reached the path where you want to perform a lookup or alteration,
103             #pod you call an all-uppercase method. These are detailed below.
104             #pod
105             #pod =head2 hive access methods
106             #pod
107             #pod These methods are thin wrappers around required modules in L
108             #pod subclasses. These methods all basically call a method on the store with the
109             #pod same (but lowercased) name and pass it the hive's path.
110             #pod
111             #pod =head3 NEW
112             #pod
113             #pod This constructs a new hive object. Note that the name is C and not
114             #pod C! The C method is just another method to pick a hive path part.
115             #pod
116             #pod The following are valid arguments for C.
117             #pod
118             #pod =begin :list
119             #pod
120             #pod = store
121             #pod
122             #pod a L object, or one with a compatible interface; this will be
123             #pod used as the hive's backend storage driver; do not supply C or
124             #pod C if C is supplied
125             #pod
126             #pod = store_class
127             #pod
128             #pod This names a class from which to instantiate a storage driver. The classname
129             #pod will have C prepended; to avoid this, prefix it with a '='
130             #pod (C<=My::Store>). A plus sign can be used instead of an equal sign, for
131             #pod historical reasons.
132             #pod
133             #pod = store_args
134             #pod
135             #pod If C has been provided instead of C, this argument may be
136             #pod given as an arrayref of arguments to pass (dereferenced) to the store class's
137             #pod C method.
138             #pod
139             #pod =end :list
140             #pod
141             #pod =cut
142              
143             sub NEW {
144 505     505 1 4860 my ($invocant, $arg) = @_;
145 505   100     899 $arg ||= {};
146              
147 505 100       639 my @path = @{ $arg->{path} || [] };
  505         1372  
148              
149 505 100       1068 my $class = ref $invocant ? ref $invocant : $invocant;
150 505         1185 my $self = bless { path => \@path } => $class;
151              
152 505 100       1120 if ($arg->{store_class}) {
    100          
153             die "don't use 'store' with 'store_class' and 'store_args'"
154 19 100       57 if $arg->{store};
155              
156             $arg->{store_class} = "Data::Hive::Store::$arg->{store_class}"
157 18 100       91 unless $arg->{store_class} =~ s/^[+=]//;
158              
159 18 100       33 $self->{store} = $arg->{store_class}->new(@{ $arg->{store_args} || [] });
  18         110  
160             } elsif ($arg->{store}) {
161 484         752 $self->{store} = $arg->{store};
162             } else {
163 2         275 Carp::croak "can't create a hive with no store";
164             }
165              
166 502         2615 return $self;
167             }
168              
169             #pod =head3 GET
170             #pod
171             #pod my $value = $hive->some->path->GET( $default );
172             #pod
173             #pod The C method gets the hive value. If there is no defined value at the
174             #pod path and a default has been supplied, the default will be returned instead.
175             #pod
176             #pod C<$default> should be a simple scalar or a subroutine. If C<$default> is a
177             #pod subroutine, it will be called to compute the default only if needed. The
178             #pod behavior for other types of defaults is undefined.
179             #pod
180             #pod =head4 overloading
181             #pod
182             #pod Hives are overloaded for stringification and numification so that they behave
183             #pod like their value when used without an explicit C. This behavior is
184             #pod deprecated and will be removed in a future release. Always use C to get
185             #pod the value of a hive.
186             #pod
187             #pod =cut
188              
189             use overload (
190             q{""} => sub {
191 0     0   0 Carp::carp "using hive as string for implicit GET is deprecated";
192 0         0 shift->GET(@_);
193             },
194             q{0+} => sub {
195 0     0   0 Carp::carp "using hive as number for implicit GET is deprecated";
196 0         0 shift->GET(@_);
197             },
198 4         34 fallback => 1,
199 4     4   4597 );
  4         4222  
200              
201             sub GET {
202 87     87 1 176 my ($self, $default) = @_;
203 87         166 my $value = $self->STORE->get($self->{path});
204 86 100       715 return defined $value ? $value
    100          
    100          
205             : ! defined $default ? undef
206             : ref $default ? scalar $default->()
207             : $default;
208             }
209              
210             #pod =head3 SET
211             #pod
212             #pod $hive->some->path->SET(10);
213             #pod
214             #pod This method sets (replacing, if necessary) the hive value.
215             #pod
216             #pod Data::Hive was built to store simple scalars as values. Although it
217             #pod I works just fine with references in the hive, it has not been
218             #pod tested for such use, and there may be bugs lurking in there.
219             #pod
220             #pod C's return value is not defined.
221             #pod
222             #pod =cut
223              
224             sub SET {
225 69     69 1 104 my $self = shift;
226 69         170 return $self->STORE->set($self->{path}, @_);
227             }
228              
229             #pod =head3 EXISTS
230             #pod
231             #pod if ($hive->foo->bar->EXISTS) { ... }
232             #pod
233             #pod This method tests whether a value (even an undefined one) exists for the hive.
234             #pod
235             #pod =cut
236              
237             sub EXISTS {
238 86     86   128 my $self = shift;
239 86         150 return $self->STORE->exists($self->{path});
240             }
241              
242             #pod =head3 DELETE
243             #pod
244             #pod $hive->foo->bar->DELETE;
245             #pod
246             #pod This method deletes the hive's value. The deleted value is returned. If no
247             #pod value had existed, C is returned.
248             #pod
249             #pod =cut
250              
251             sub DELETE {
252 10     10   22 my $self = shift;
253 10         25 return $self->STORE->delete($self->{path});
254             }
255              
256             #pod =head3 DELETE_ALL
257             #pod
258             #pod This method behaves like C, but all values for paths below the current
259             #pod one will also be deleted.
260             #pod
261             #pod =cut
262              
263             sub DELETE_ALL {
264 3     3 1 9 my $self = shift;
265 3         11 return $self->STORE->delete_all($self->{path});
266             }
267              
268             #pod =head3 KEYS
269             #pod
270             #pod my @keys = $hive->KEYS;
271             #pod
272             #pod This returns a list of next-level path elements that exist. For example, given
273             #pod a hive with values for the following paths:
274             #pod
275             #pod foo
276             #pod foo/bar
277             #pod foo/bar/baz
278             #pod foo/xyz/abc
279             #pod foo/xyz/def
280             #pod foo/123
281             #pod
282             #pod This shows the expected results:
283             #pod
284             #pod keys of | returns
285             #pod -------------+------------
286             #pod foo | bar, xyz, 123
287             #pod foo/bar | baz
288             #pod foo/bar/baz |
289             #pod foo/xyz | abc, def
290             #pod foo/123 |
291             #pod
292             #pod =cut
293              
294             sub KEYS {
295 47     47 1 99 my ($self) = @_;
296 47         107 return $self->STORE->keys($self->{path});
297             }
298              
299             #pod =head3 COPY_ONTO
300             #pod
301             #pod $hive->foo->COPY_ONTO( $another_hive->bar );
302             #pod
303             #pod This method copies all the existing values found at or under the current path
304             #pod to another Data::Hive, using either the same or a different store.
305             #pod
306             #pod Currently, this will set each found value individually. In the future, store
307             #pod classes should have the ability to receive a bulk-set message to operate in a
308             #pod transaction, if appropriate.
309             #pod
310             #pod =cut
311              
312             sub COPY_ONTO {
313 24     24 1 47 my ($self, $target) = @_;
314              
315 24 100       47 $target->SET( $self->GET ) if $self->EXISTS;
316              
317 24         60 for my $key ($self->KEYS) {
318 21         74 $self->HIVE($key)->COPY_ONTO( $target->HIVE($key) );
319             }
320             }
321              
322             #pod =head3 HIVE
323             #pod
324             #pod $hive->HIVE('foo'); # equivalent to $hive->foo
325             #pod
326             #pod $hive->HIVE('foo', 'bar'); # equivalent to $hive->foo->bar
327             #pod
328             #pod This method returns a subhive of the current hive. In most cases, it is
329             #pod simpler to use the lowercase hive access method. This method is useful when
330             #pod you must, for some reason, access an entry whose name is not a valid Perl
331             #pod method name.
332             #pod
333             #pod It is also needed if you must access a path with the same name as a method in
334             #pod C. In general, only C, C, and C should fall into
335             #pod this category, but some libraries unfortunately add methods to C.
336             #pod Common offenders include C, C, C.
337             #pod
338             #pod This method should be needed fairly rarely. It may also be called as C
339             #pod for historical reasons.
340             #pod
341             #pod =cut
342              
343             sub ITEM {
344 0     0 0 0 my ($self, @rest) = @_;
345 0         0 return $self->HIVE(@rest);
346             }
347              
348             sub HIVE {
349 479     479 1 1038 my ($self, @keys) = @_;
350              
351 3 100       14 my @illegal = map { $_ = '(undef)' if ! defined }
352 479 100 100     770 grep { ! defined or ! length or ref } @keys;
  479         2572  
353              
354 479 100       1088 Carp::croak "illegal hive path parts: @illegal" if @illegal;
355              
356             return $self->NEW({
357             %$self,
358 476         1045 path => [ @{$self->{path}}, @keys ],
  476         1738  
359             });
360             }
361              
362             #pod =head3 NAME
363             #pod
364             #pod This method returns a name that can be used to represent the hive's path. This
365             #pod name is B, and should not be relied upon if the store may
366             #pod change. It is provided primarily for debugging.
367             #pod
368             #pod =cut
369              
370             sub NAME {
371 1     1 1 2 my $self = shift;
372 1         4 return $self->STORE->name($self->{path});
373             }
374              
375             #pod =head3 ROOT
376             #pod
377             #pod This returns a Data::Hive object for the root of the hive.
378             #pod
379             #pod =cut
380              
381             sub ROOT {
382 3     3 1 6 my $self = shift;
383              
384 3         16 return $self->NEW({
385             %$self,
386             path => [ ],
387             });
388             }
389              
390             #pod =head3 SAVE
391             #pod
392             #pod This method tells the hive store to save the value (or lack thereof) for the
393             #pod current path. For many stores, this does nothing. For hive stores that are
394             #pod written out only on demand, this method must be called.
395             #pod
396             #pod =cut
397              
398             sub SAVE {
399 0     0 1 0 my ($self) = @_;
400              
401 0         0 $self->STORE->save($self->{path});
402             }
403              
404             #pod =head3 SAVE_ALL
405             #pod
406             #pod This method tells the hive store to save the value (or lack thereof) for the
407             #pod current path and all paths beneath it. For many stores, this does nothing.
408             #pod For hive stores that are written out only on demand, this method must be
409             #pod called.
410             #pod
411             #pod =cut
412              
413             sub SAVE_ALL {
414 0     0 1 0 my ($self) = @_;
415              
416 0         0 $self->STORE->save_all($self->{path});
417             }
418              
419             #pod =head3 STORE
420             #pod
421             #pod This method returns the storage driver being used by the hive.
422             #pod
423             #pod =cut
424              
425             sub STORE {
426             return $_[0]->{store}
427 329     329   1122 }
428              
429             sub AUTOLOAD {
430 935     935   20832 my $self = shift;
431 935         1044 our $AUTOLOAD;
432              
433 935         3298 (my $method = $AUTOLOAD) =~ s/.*:://;
434 935 50       2027 die "AUTOLOAD for '$method' called on non-object" unless ref $self;
435              
436 935 100       3906 return if $method eq 'DESTROY';
437              
438 430 100       974 if ($method =~ /^[A-Z_]+$/) {
439 1         96 Carp::croak("all-caps method names are reserved: '$method'");
440             }
441              
442 429 100       872 Carp::cluck("arguments passed to autoloaded Data::Hive descender") if @_;
443              
444 429         821 return $self->HIVE($method);
445             }
446              
447             1;
448              
449             __END__