File Coverage

blib/lib/Data/Toolkit/Entry.pm
Criterion Covered Total %
statement 180 198 90.9
branch 103 158 65.1
condition 6 12 50.0
subroutine 19 21 90.4
pod 13 14 92.8
total 321 403 79.6


line stmt bran cond sub pod time code
1             #!/usr/bin/perl -w
2             #
3             # Data::Toolkit::Entry
4             #
5             # Andrew Findlay
6             # Nov 2006
7             # andrew.findlay@skills-1st.co.uk
8             #
9             # $Id: Entry.pm 388 2013-08-30 15:19:23Z remotesvn $
10              
11             package Data::Toolkit::Entry;
12              
13 5     5   208813 use strict;
  5         15  
  5         376  
14 5     5   18184 use Data::MultiValuedHash;
  5         44440  
  5         221  
15 5     5   7432 use Data::Dumper;
  5         61313  
  5         780  
16 5     5   44 use Carp;
  5         8  
  5         952  
17 5     5   5878 use Clone qw(clone);
  5         55420  
  5         443  
18              
19             =head1 NAME
20              
21             Data::Toolkit::Entry
22              
23             =head1 DESCRIPTION
24              
25             Data::Toolkit::Entry objects store attribute-value data.
26             Attributes can have zero or more values.
27             By default, attribute names are case-insensitive and are always
28             returned in lower case.
29              
30             Each attribute can have zero or more values.
31             The list of values is kept sorted, and by default only one copy of each value
32             is permitted. The sort order is selectable.
33              
34             Data::Toolkit::Entry objects are ideal for carrying entries in
35             directory synchronisation systems and other data-pump applications.
36              
37             =head1 DEPENDENCIES
38              
39             Carp
40             Clone
41             Data::Dumper
42             Data::MultiValuedHash
43              
44             =head1 SYNOPSIS
45              
46             my $entry = Data::Toolkit::Entry->new();
47              
48             $count = $entry->set("surname", [ "Findlay" ]);
49             $count = $entry->set("cn", [ "Andrew Findlay", "A J Findlay" ]);
50             $count = $entry->set("mobile", []);
51              
52             $count = $entry->add("newAttribute", [ "Apples" ]);
53             $count = $entry->add("newAttribute", [ "Pears", "Oranges" ]);
54              
55             $arrayRef = $entry->get("myAttribute");
56             print (join ":", $arrayref), "\n";
57              
58             $arrayRef = $entry->attributes();
59              
60             $result = $entry->attribute_match( 'attribname', ['value1','value2'] );
61              
62             $newEntry = $entry->map($thisMap);
63             $newEntry = $entry->map($thisMap,$entry2,$entry3,...);
64              
65             $result = $entry->delete('thisAttribute','thisValue');
66              
67             $result = $entry->delete('thisAttribute');
68              
69             my $currentDebugLevel = Data::Toolkit::Entry->debug();
70             my $newDebugLevel = Data::Toolkit::Entry(1);
71              
72             my $string = $entry->dump();
73              
74             =cut
75              
76             ########################################################################
77             # Package globals
78             ########################################################################
79              
80 5     5   42 use vars qw($VERSION);
  5         11  
  5         22680  
81             $VERSION = '1.0';
82              
83             # Set this non-zero for debug logging
84             #
85             my $debug = 0;
86              
87             ########################################################################
88             # Constructors and destructors
89             ########################################################################
90              
91             =head1 Constructor
92              
93             =head2 new
94              
95             my $entry = Data::Toolkit::Entry->new();
96             my $entry = Data::Toolkit::Entry->new( {configAttrib => value, ....} );
97              
98             Creates an object of type Data::Toolkit::Entry
99              
100             Optionally accepts a hash of configuration items chosen from this list:
101              
102             =over
103              
104             =item caseSensitiveNames
105              
106             If this is defined with a true value then attribute names are case-sensitive.
107             By default they are not, so "Surname", "surname", and "SurName" are all the same attribute.
108              
109             =item defaultValueComparator
110              
111             If this is defined its value sets the default method of comparing values
112             in all attributes. See I below for details.
113              
114             =item defaultUniqueValues
115              
116             If this is defined its value is the default for each new attribute's
117             uniqueValues flag.
118              
119             =back
120              
121             =cut
122              
123             sub new {
124 16     16 1 5185 my $class = shift;
125 16         31 my $configParam = shift;
126              
127 16         31 my $self = {};
128              
129             # Take a copy of the config hash
130             # - we don't want to store a ref to the one we were given
131             # in case it is part of another object
132             #
133 16 100       51 if (defined($configParam)) {
134 7 50       33 if ((ref $configParam) ne 'HASH') {
135 0         0 croak "Data::Toolkit::Entry->new expects a hash ref but was given something else"
136             }
137              
138 7         248 $self->{config} = clone($configParam);
139             }
140             else {
141             # Start with empty config
142 9         27 $self->{config} = {};
143 9         31 $self->{config}->{uniqueValues} = {};
144 9         27 $self->{config}->{comparator} = {};
145             }
146              
147             # Default value comparison method
148 16 100       88 $self->{config}->{defaultValueComparator} = 'caseInsensitive' unless $self->{config}->{defaultValueComparator};
149              
150             # Default true for uniqueValues flags
151 16 100       69 $self->{config}->{defaultUniqueValues} = 1 unless $self->{config}->{defaultUniqueValues};
152              
153             # Attribute names are not case-sensitive by default.
154             # Check to see whether this should be changed.
155 16         38 my $ignoreCase = 1;
156 16 100       59 $ignoreCase = 0 if $self->{config}->{caseSensitiveNames};
157              
158             # We use Data::MultiValuedHash to handle attribute-value storage
159 16         95 $self->{data} = Data::MultiValuedHash->new($ignoreCase);
160              
161 16         562 bless ($self, $class);
162              
163 16 50       48 carp "Creating $self" if $debug;
164 16         41 return $self;
165             }
166              
167             sub DESTROY {
168 16     16   1167 my $self = shift;
169 16 50       369 carp "Destroying $self" if $debug;
170             }
171              
172             ########################################################################
173             # Methods
174             ########################################################################
175              
176             =head1 Methods
177              
178             =cut
179              
180             ########################################
181              
182             =head2 set
183              
184             Set the value of an attribute, overriding what was there before.
185             Creates the attribute if necessary.
186              
187             Passing an empty list of values creates an empty attribute
188             (this is different from the attribute not existing at all).
189              
190             Passing an undef list of values deletes the attribute and returns undef.
191              
192             $count = $entry->set("surname", [ "Findlay" ]);
193             $count = $entry->set("cn", [ "Andrew Findlay", "A J Findlay" ]);
194             $count = $entry->set("mobile", []);
195              
196             The method returns the number of values that the attribute has, so in the
197             examples above, $count would be 1, 2, and 0 respectively.
198              
199             =cut
200              
201             sub set {
202 25     25 1 111 my $self = shift;
203 25         39 my $attrib = shift;
204 25         32 my $values = shift;
205              
206 25 50       61 croak "set requires an attribute name" if (!$attrib);
207              
208             # Lower-case the attribute name if necessary
209 25 50       105 $attrib = "\L$attrib" if (!$self->{config}->{caseSensitiveNames});
210              
211 25 50       55 carp "Data::Template::Entry->set attribute '$attrib'" if $debug;
212              
213             # Delete any existing values
214 25         97 $self->{data}->delete($attrib);
215              
216             # undefined list?
217 25 100       220 return undef if !defined($values);
218              
219 24 50       91 croak "Second parameter to Data::Template::Entry->set must be an array" if ((ref $values) ne "ARRAY");
220              
221             # Pass the rest of the job to the add method
222 24         65 return $self->add($attrib, $values);
223             }
224              
225              
226             ########################################
227              
228             =head2 add
229              
230             Add one or more values to an attribute.
231             Creates the attribute if necessary.
232              
233             Passing an undef list of values does nothing.
234              
235             Passing an empty list of values creates an empty attribute
236             or leaves an existing one unchanged.
237              
238             $count = $entry->add("newAttribute", [ "Apples" ]);
239             $count = $entry->add("newAttribute", [ "Pears", "Oranges" ]);
240             $count = $entry->add("anotherAttribute", []);
241             $count = $entry->add("anotherAttribute", undef);
242              
243             The method returns the number of values that the attribute has after
244             the add operation has completed. If an undef list is added to a
245             non-existant attribute then the return will be undef.
246              
247             =cut
248              
249             sub add {
250 62     62 1 11925 my $self = shift;
251 62         93 my $attrib = shift;
252 62         75 my $values = shift;
253              
254 62 50       147 croak "add requires an attribute name" if (!$attrib);
255              
256             # Lower-case the attribute name if necessary
257 62 100       205 $attrib = "\L$attrib" if (!$self->{config}->{caseSensitiveNames});
258              
259 62 50       170 carp "Data::Template::Entry->add attribute '$attrib'" if $debug;
260              
261             # If we were given an undef value list then
262             # we dont want to modify the entry at all.
263             #
264 62 100       139 return $self->{data}->count($attrib) if !defined($values);
265              
266 61 50       124 carp "Data::Template::Entry->add $attrib: " . ref $values if $debug;
267 61 50       164 croak "Second parameter to Data::Template::Entry->add must be an array ref" if ((ref $values) ne "ARRAY");
268              
269             # Set the comparator type if it has not been done already
270 61 100       205 if (!defined($self->{config}->{comparator}->{$attrib})) {
271 39 50       1013 carp "Data::Template::Entry->add setting attribute '$attrib' default comparator" if $debug;
272 39         148 $self->{config}->{comparator}->{$attrib} = $self->{config}->{defaultValueComparator};
273             }
274              
275             # Set the uniqueValues flag if it has not been done already
276 61 100       188 if (!defined($self->{config}->{uniqueValues}->{$attrib})) {
277 40 50       90 carp "Data::Template::Entry->add setting attribute '$attrib' default uniqueValues flag" if $debug;
278 40         131 $self->{config}->{uniqueValues}->{$attrib} = $self->{config}->{defaultUniqueValues};
279             }
280              
281             # If we get this far we should at least create the attribute
282 61         259 $self->{data}->push($attrib);
283              
284             # Add each value from the list
285 61         977 foreach my $val (@$values) {
286 74         957 $self->addOne( $attrib, $val );
287             }
288              
289             # Return the new number of values
290 61         1223 return $self->{data}->count($attrib);
291             }
292              
293              
294             ########################################
295              
296             =head2 attrCmp
297              
298             Compare two values of a specific attribute using the defined comparator for that attribute.
299             Returns negative, zero, or positive.
300              
301             $result = $entry->attrCmp( 'attributename', 'value1', 'value2' );
302              
303             =cut
304              
305             sub attrCmp {
306 41     41 1 48 my $self = shift;
307 41         61 my $attrib = shift;
308 41         53 my $val1 = shift;
309 41         54 my $val2 = shift;
310              
311 41 50       102 croak "Data::Template::Entry->attrCmp needs an attribute name" if !$attrib;
312              
313             # Lower-case the attribute name if necessary
314 41 100       119 $attrib = "\L$attrib" if (!$self->{config}->{caseSensitiveNames});
315              
316             # Find the comparator for this attribute
317 41         809 my $comparator = $self->{config}->{comparator}->{$attrib};
318 41 50       88 carp "Data::Template::Entry->attrCmp comparator: $comparator" if $debug;
319              
320 41 100       700 if ($comparator eq 'caseSensitive') {
    100          
    100          
    50          
321 6         15 return ($val1 cmp $val2);
322             }
323             elsif ($comparator eq 'caseInsensitive') {
324 25         97 return ("\L$val1" cmp "\L$val2");
325             }
326             elsif ($comparator eq 'integer') {
327 8         17 return ($val1 <=> $val2);
328             }
329             elsif ((ref $comparator) eq 'CODE') {
330 2         10 return (&$comparator($val1, $val2));
331             }
332             else {
333 0         0 croak "comparator $comparator not implemented";
334             }
335             }
336              
337             # Internal method: add one value to an attribute, preserving the sort order and uniqueness
338             #
339             sub addOne {
340 74     74 0 162 my $self = shift;
341 74         105 my $attrib = shift;
342 74         99 my $value = shift;
343              
344 74 50       184 carp "Data::Template::Entry->addOne( $attrib, $value )" if $debug;
345              
346             # Get the current list of values
347 74         236 my @list = $self->{data}->fetch($attrib);
348              
349             # Find the uniqueness flag for this attribute
350 74         2306 my $uniq = $self->{config}->{uniqueValues}->{$attrib};
351 74 50       171 carp "Data::Template::Entry->addOne uniqueValues: $uniq" if $debug;
352              
353             # Work out where to put our new one
354 74         81 my $splicePosition = 0;
355 74         217 while (defined(my $thisVal = $list[$splicePosition])) {
356 36         87 my $cmp = attrCmp( $self, $attrib, $value, $thisVal );
357              
358             # Not there yet
359 36 100       288 next if $cmp > 0;
360              
361             # Duplicate - return now if we are preserving uniqueness
362 11 50 66     43 return if (($cmp == 0) and $uniq);
363              
364             # Insert here
365 11         17 last;
366             }
367             continue {
368 25         72 $splicePosition++;
369             }
370              
371             # Insert the value
372 74         430 $self->{data}->splice($attrib,$splicePosition,0,$value);
373             }
374              
375             ########################################
376              
377             =head2 get
378              
379             Get the list of values for an attribute.
380              
381             Returns an empty list if the attribute exists but has no values.
382              
383             Returns undef if the attribute does not exist.
384              
385             $arrayRef = $entry->get("myAttribute");
386              
387             =cut
388              
389             sub get {
390 80     80 1 37529 my $self = shift;
391 80         116 my $attrib = shift;
392              
393 80 50       478 croak "get requires an attribute name" if (!$attrib);
394              
395             # Lower-case the attribute name if necessary
396 80 100       251 $attrib = "\L$attrib" if (!$self->{config}->{caseSensitiveNames});
397              
398 80 50       188 carp "Data::Template::Entry->get attribute '$attrib'" if $debug;
399 80         509 my $valref = $self->{data}->fetch($attrib);
400 80 100       4291 return undef if !$valref;
401 61         143 my @values = @$valref;
402 61 100       322 return ( wantarray ? @values : \@values );
403             }
404              
405             ########################################
406              
407             =head2 attributes
408              
409             Get the list of attributes in an entry.
410              
411             Returns an empty list if there are no attributes.
412              
413             Note that attributes can exist but not have values.
414              
415             $arrayRef = $entry->attributes();
416              
417             =cut
418              
419             sub attributes {
420 0     0 1 0 my $self = shift;
421              
422 0         0 my @attrs = $self->{data}->keys();
423 0 0       0 carp "Data::Template::Entry->attributes are: " . (join ',',@attrs) if $debug;
424 0 0       0 return ( wantarray ? @attrs : \@attrs );
425             }
426              
427              
428             ########################################
429              
430             =head2 attribute_match
431              
432             Return true or false depending on whether the named attribute contains
433             a list of values exactly matching the one supplied.
434              
435             $result = $entry->attribute_match( 'attribname', ['value1','value2'] );
436              
437             The supplied list must be sorted into the same order that Data::Toolkit::Entry uses.
438             This will automatically be done in the common case of comparing an attribute
439             in two entries:
440              
441             $result = $entry->attribute_match( 'name', $secondEntry->get('name') );
442              
443             An undef list is treated as if it were an empty list.
444              
445             =cut
446              
447             sub attribute_match {
448 4     4 1 514 my $self = shift;
449 4         5 my $attrib = shift;
450 4         4 my $list = shift;
451              
452 4 50       12 croak "Data::Template::Entry->attribute_match needs an attribute name" if !$attrib;
453 4 50       11 carp "Data::Template::Entry->attribute_match $attrib" if $debug;
454              
455             # Lower-case the attribute name if necessary
456 4 50       13 $attrib = "\L$attrib" if (!$self->{config}->{caseSensitiveNames});
457              
458             # Undef list of values is equivalent to an empty list
459 4 100       10 $list = [] if !$list;
460 4         8 my @supplied = @$list;
461 4         15 my @mine = $self->{data}->fetch($attrib);
462              
463             # Step through the lists comparing values
464 4         45 my $suppVal = shift @supplied;
465 4         7 my $myVal = shift @mine;
466 4   66     17 while ($suppVal and $myVal) {
467 5 100       18 return 0 if (attrCmp($self, $attrib, $suppVal, $myVal) != 0);
468              
469             # Match so far - get the next pair of values
470 4         6 $suppVal = shift @supplied;
471 4         17 $myVal = shift @mine;
472             }
473             # Match is good if no values left
474 3 50 33     43 return 1 if (!$suppVal and !$myVal);
475             # One list still has a value so match is not made
476 0         0 return 0;
477             }
478              
479             ########################################
480              
481             =head2 uniqueValues
482              
483             Define whether an attribute should have unique values.
484              
485             By default, values are unique: an attribute will not store more than one copy
486             of a given value, which is compared using the I method set for the
487             attribute.
488              
489             $uniqVal = $entry->uniqueValues( 'attributeName', 1 );
490             $uniqVal = $entry->uniqueValues( 'attributeName', 0 );
491             $uniqVal = $entry->uniqueValues( 'attributeName' );
492              
493             Setting an undefined value has no effect other than to return the current setting.
494              
495             Returns the setting of the uniqueValues flag.
496              
497             Note that changing this flag on an attribute which already has values
498             does I affect those values.
499              
500             Passing a hash reference causes all existing uniqueValues flags to be replaced
501             by the values specified in the hash:
502              
503             $hashRef = $entry->uniqueValues( \%mySettings );
504              
505             =cut
506              
507             sub uniqueValues {
508 4     4 1 540 my $self = shift;
509 4         7 my $attrib = shift;
510 4         6 my $uniq = shift;
511              
512 4 50       13 croak "uniqueValues requires an attribute name or hash" if (!$attrib);
513              
514 4 50       9 if ((ref $attrib) eq 'HASH') {
515             # we have been given a complete config to override what we had before
516 0         0 my %newUV = %$attrib;
517 0         0 $self->{config}->{uniqueValues} = \%newUV;
518             }
519              
520             # Lower-case the attribute name if necessary
521 4 50       15 $attrib = "\L$attrib" if (!$self->{config}->{caseSensitiveNames});
522              
523              
524 4 100       9 if (!defined($uniq)) {
525 2 50       5 carp "Data::Template::Entry->uniqueValues attribute '$attrib'" if $debug;
526 2         12 return $self->{config}->{uniqueValues}->{$attrib};
527             }
528              
529 2 50       6 carp "Data::Template::Entry->uniqueValues attribute '$attrib': $uniq" if $debug;
530 2         11 return $self->{config}->{uniqueValues}->{$attrib} = $uniq;
531             }
532              
533             ########################################
534              
535             =head2 comparator
536              
537             Define how values should be compared for a particular attribute.
538              
539             By default, values are treated as case-insensitive text strings.
540              
541             $func = $entry->comparator( 'attributeName', 'caseIgnore' );
542             $func = $entry->comparator( 'attributeName', 'caseSensitive' );
543             $func = $entry->comparator( 'attributeName', 'integer' );
544             $func = $entry->comparator( 'attributeName', \&myComparatorFunction );
545             $func = $entry->comparator( 'attributeName' );
546              
547             If supplying a function of your own, it should be suitable for use in
548             Perl's "sort" operation: it should return an integer less than, equal to,
549             or greater than zero depending on whether its first argument is less than, equal to,
550             or greater than its second argument. Note that sort's $a,$b convention
551             should I be used.
552              
553             Returns the name of the comparison method or a reference to a function
554             as appropriate.
555              
556             Note that changing this flag on an attribute which already has values
557             does I affect those values.
558              
559             Passing a hash reference causes all existing comparator flags to be replaced
560             by the values specified in the hash:
561              
562             $hashRef = $entry->comparator( \%myHash );
563              
564             =cut
565              
566             sub comparator {
567 5     5 1 1489 my $self = shift;
568 5         8 my $attrib = shift;
569 5         8 my $comp = shift;
570              
571 5 50       15 croak "comparator requires an attribute name or hash" if (!$attrib);
572              
573 5 50       15 if ((ref $attrib) eq 'HASH') {
574             # we have been given a complete config to override what we had before
575 0         0 my %newCMP = %$attrib;
576 0         0 $self->{config}->{comparator} = \%newCMP;
577             }
578              
579             # Lower-case the attribute name if necessary
580 5 50       23 $attrib = "\L$attrib" if (!$self->{config}->{caseSensitiveNames});
581              
582              
583 5 100       10 if (!defined($comp)) {
584 2 50       6 carp "Data::Template::Entry->comparator attribute '$attrib'" if $debug;
585 2         12 return $self->{config}->{comparator}->{$attrib};
586             }
587              
588 3 100       13 if ((ref $comp) eq 'CODE') {
589             # We have a procedure to register
590 1 50       5 carp "Data::Template::Entry->comparator attribute '$attrib' (CODE)" if $debug;
591 1         7 return $self->{config}->{comparator}->{$attrib} = $comp;
592             }
593              
594 2 50       8 if ("\L$comp" eq 'caseignore') {
595 0 0       0 carp "Data::Template::Entry->comparator attribute '$attrib' (caseIgnore)" if $debug;
596 0         0 return $self->{config}->{comparator}->{$attrib} = 'caseIgnore';
597             }
598              
599 2 100       10 if ("\L$comp" eq 'casesensitive') {
600 1 50       5 carp "Data::Template::Entry->comparator attribute '$attrib' (caseSensitive)" if $debug;
601 1         63 return $self->{config}->{comparator}->{$attrib} = 'caseSensitive';
602             }
603              
604 1 50       5 if ("\L$comp" eq 'integer') {
605 1 50       4 carp "Data::Template::Entry->comparator attribute '$attrib' (integer)" if $debug;
606 1         9 return $self->{config}->{comparator}->{$attrib} = 'integer';
607             }
608              
609             # Hmm - something odd here
610 0         0 croak "Unknown comparator type";
611             }
612              
613             ########################################
614              
615             =head2 map
616              
617             Create a new entry object by applying a map to the current one.
618             Further entries can also be specified. They will be passed to the Data::Toolkit::Map
619             generate method.
620              
621             $newEntry = $entry->map($thisMap);
622             $newEntry = $entry->map($thisMap,$entry2,$entry3,...);
623              
624             The map is a Data::Toolkit::Map object.
625              
626             =cut
627              
628             sub map {
629 5     5 1 259 my $self = shift;
630 5         10 my $map = shift;
631              
632 5 50       16 croak "map requires a map object" if (!$map);
633 5 50       157 croak "map object must be of type Data::Toolkit::Map" if (!$map->isa('Data::Toolkit::Map'));
634 5 50       27 carp "Data::Template::Entry->map" if $debug;
635              
636             # Create a new entry with the same setup as this one
637 5         24 my $newEntry = Data::Toolkit::Entry->new($self->{config});
638              
639             # Get the list of output attributes from the map
640 5         26 my $mapOutputs = $map->outputs();
641              
642             # Step through that list creating attributes in the new entry
643             # Do not create an attribute if given an undef arrayref
644             #
645 5         14 foreach my $attr (@$mapOutputs) {
646 28         234 my $vals = $map->generate($attr,$self,@_);
647 28 50       126 warn "Data::Template::Entry->map $attr: " . (join ':',@$vals) if $debug;
648 28 100       115 $newEntry->add($attr, $vals) if $vals;
649             }
650              
651 5         65 return $newEntry;
652             }
653              
654              
655             ########################################
656              
657             =head2 delete
658              
659             Delete a value from an attribute:
660              
661             $result = $entry->delete('thisAttribute','thisValue');
662              
663             Delete an attribute and all its values:
664              
665             $result = $entry->delete('thisAttribute');
666              
667             In both cases, returns a list containing any values that it deleted.
668             If nothing was deleted, returns false.
669              
670             Note that deleting an attribute does not delete setting such as the
671             comparator for that attribute.
672              
673             =cut
674              
675             sub delete {
676 4     4 1 6561 my $self = shift;
677 4         8 my $attrib = shift;
678 4         7 my $value = shift;
679              
680 4 50       34 croak "delete requires an attribute name" if (!$attrib);
681              
682             # Lower-case the attribute name if necessary
683 4 50       22 $attrib = "\L$attrib" if (!$self->{config}->{caseSensitiveNames});
684              
685              
686 4 100       13 if (defined($value)) {
687             # We are deleting a single value
688 2 50       9 carp "Data::Template::Entry->delete '$value' from attribute '$attrib'" if $debug;
689 2         15 my $allValues = $self->{data}->fetch($attrib);
690             # Is there anything there at all?
691 2 50 33     51 return undef if (!defined($allValues) or !defined($allValues->[0]));
692             # print "NEED TO DELETE $value\n";
693 2         18 for (my $count=0; defined($allValues->[$count]); $count++) {
694 10 100       36 if ($value eq $allValues->[$count]) {
695 1         23 return $self->{data}->splice($attrib,$count,1);
696             }
697             }
698             # Not found
699 1         10 return undef;
700             }
701             else {
702             # We are deleting the whole attribute
703 2 50       16 carp "Data::Template::Entry->delete attribute '$attrib'" if $debug;
704 2         15 return $self->{data}->delete($attrib);
705             }
706             }
707              
708              
709             ########################################################################
710             # Debugging methods
711             ########################################################################
712              
713             =head1 Debugging methods
714              
715             =head2 debug
716              
717             Set and/or get the debug level for Data::Toolkit::Entry
718              
719             my $currentDebugLevel = Data::Toolkit::Entry->debug();
720             my $newDebugLevel = Data::Toolkit::Entry(1);
721              
722             Any non-zero debug level causes the module to print copious debugging information.
723              
724             Note that this is a package method, not an object method. It should always be
725             called exactly as shown above.
726              
727             All debug information is reported using "carp" from the Carp module, so if
728             you want a full stack backtrace included you can run your program like this:
729              
730             perl -MCarp=verbose myProg
731              
732             =cut
733              
734             # Class method to set and/or get debug level
735             #
736             sub debug {
737 4     4 1 1380 my $class = shift;
738 4 50       17 if (ref $class) { croak "Class method 'debug' called as object method" }
  0         0  
739             # print "DEBUG: ", (join '/', @_), "\n";
740 4 100       14 $debug = shift if (@_ == 1);
741 4         20 return $debug
742             }
743              
744             ########################################
745              
746             =head2 dump
747              
748             Returns a text representation of the entry.
749              
750             my $string = $entry->dump();
751              
752             =cut
753              
754              
755             sub dump {
756 0     0 1   my $self = shift;
757              
758 0           my %hash = $self->{data}->fetch_all();
759 0           return Dumper(\%hash);
760             }
761              
762             ########################################################################
763             ########################################################################
764              
765             =head1 Error handling
766              
767             If you miss out an essential parameter, the module will throw an exception
768             using "croak" from the Carp module. These exceptions represent programming
769             errors in most cases so there is little point in trapping them with "eval".
770              
771             =head1 Author
772              
773             Andrew Findlay
774              
775             Skills 1st Ltd
776              
777             andrew.findlay@skills-1st.co.uk
778              
779             http://www.skills-1st.co.uk/
780              
781             =cut
782              
783             ########################################################################
784             ########################################################################
785             1;