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 6     6   60754 use strict;
  6         11  
  6         302  
14 6     6   6280 use Data::MultiValuedHash;
  6         18261  
  6         165  
15 6     6   3108 use Data::Dumper;
  6         23929  
  6         376  
16 6     6   40 use Carp;
  6         8  
  6         355  
17 6     6   2103 use Clone qw(clone);
  6         11536  
  6         532  
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 6     6   52 use vars qw($VERSION);
  6         13  
  6         16472  
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 25     25 1 1797 my $class = shift;
125 25         41 my $configParam = shift;
126              
127 25         130 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 25 100       74 if (defined($configParam)) {
134 7 50       24 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         172 $self->{config} = clone($configParam);
139             }
140             else {
141             # Start with empty config
142 18         54 $self->{config} = {};
143 18         58 $self->{config}->{uniqueValues} = {};
144 18         56 $self->{config}->{comparator} = {};
145             }
146              
147             # Default value comparison method
148 25 100       117 $self->{config}->{defaultValueComparator} = 'caseInsensitive' unless $self->{config}->{defaultValueComparator};
149              
150             # Default true for uniqueValues flags
151 25 100       141 $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 25         35 my $ignoreCase = 1;
156 25 100       68 $ignoreCase = 0 if $self->{config}->{caseSensitiveNames};
157              
158             # We use Data::MultiValuedHash to handle attribute-value storage
159 25         134 $self->{data} = Data::MultiValuedHash->new($ignoreCase);
160              
161 25         706 bless ($self, $class);
162              
163 25 50       66 carp "Creating $self" if $debug;
164 25         69 return $self;
165             }
166              
167             sub DESTROY {
168 25     25   1487 my $self = shift;
169 25 50       776 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 48     48 1 185 my $self = shift;
203 48         75 my $attrib = shift;
204 48         254 my $values = shift;
205              
206 48 50       117 croak "set requires an attribute name" if (!$attrib);
207              
208             # Lower-case the attribute name if necessary
209 48 50       180 $attrib = "\L$attrib" if (!$self->{config}->{caseSensitiveNames});
210              
211 48 50       107 carp "Data::Template::Entry->set attribute '$attrib'" if $debug;
212              
213             # Delete any existing values
214 48         174 $self->{data}->delete($attrib);
215              
216             # undefined list?
217 48 100       416 return undef if !defined($values);
218              
219 47 50       143 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 47         130 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 89     89 1 4056 my $self = shift;
251 89         119 my $attrib = shift;
252 89         92 my $values = shift;
253              
254 89 50       347 croak "add requires an attribute name" if (!$attrib);
255              
256             # Lower-case the attribute name if necessary
257 89 100       262 $attrib = "\L$attrib" if (!$self->{config}->{caseSensitiveNames});
258              
259 89 50       186 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 89 100       225 return $self->{data}->count($attrib) if !defined($values);
265              
266 88 50       410 carp "Data::Template::Entry->add $attrib: " . ref $values if $debug;
267 88 50       217 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 88 100       336 if (!defined($self->{config}->{comparator}->{$attrib})) {
271 61 50       129 carp "Data::Template::Entry->add setting attribute '$attrib' default comparator" if $debug;
272 61         267 $self->{config}->{comparator}->{$attrib} = $self->{config}->{defaultValueComparator};
273             }
274              
275             # Set the uniqueValues flag if it has not been done already
276 88 100       241 if (!defined($self->{config}->{uniqueValues}->{$attrib})) {
277 62 50       137 carp "Data::Template::Entry->add setting attribute '$attrib' default uniqueValues flag" if $debug;
278 62         166 $self->{config}->{uniqueValues}->{$attrib} = $self->{config}->{defaultUniqueValues};
279             }
280              
281             # If we get this far we should at least create the attribute
282 88         307 $self->{data}->push($attrib);
283              
284             # Add each value from the list
285 88         1276 foreach my $val (@$values) {
286 101         474 $self->addOne( $attrib, $val );
287             }
288              
289             # Return the new number of values
290 88         2239 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 43     43 1 55 my $self = shift;
307 43         46 my $attrib = shift;
308 43         44 my $val1 = shift;
309 43         45 my $val2 = shift;
310              
311 43 50       72 croak "Data::Template::Entry->attrCmp needs an attribute name" if !$attrib;
312              
313             # Lower-case the attribute name if necessary
314 43 100       101 $attrib = "\L$attrib" if (!$self->{config}->{caseSensitiveNames});
315              
316             # Find the comparator for this attribute
317 43         65 my $comparator = $self->{config}->{comparator}->{$attrib};
318 43 50       77 carp "Data::Template::Entry->attrCmp comparator: $comparator" if $debug;
319              
320 43 100       119 if ($comparator eq 'caseSensitive') {
    100          
    100          
    50          
321 6         11 return ($val1 cmp $val2);
322             }
323             elsif ($comparator eq 'caseInsensitive') {
324 27         97 return ("\L$val1" cmp "\L$val2");
325             }
326             elsif ($comparator eq 'integer') {
327 8         16 return ($val1 <=> $val2);
328             }
329             elsif ((ref $comparator) eq 'CODE') {
330 2         6 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 101     101 0 156 my $self = shift;
341 101         123 my $attrib = shift;
342 101         119 my $value = shift;
343              
344 101 50       199 carp "Data::Template::Entry->addOne( $attrib, $value )" if $debug;
345              
346             # Get the current list of values
347 101         446 my @list = $self->{data}->fetch($attrib);
348              
349             # Find the uniqueness flag for this attribute
350 101         1383 my $uniq = $self->{config}->{uniqueValues}->{$attrib};
351 101 50       206 carp "Data::Template::Entry->addOne uniqueValues: $uniq" if $debug;
352              
353             # Work out where to put our new one
354 101         114 my $splicePosition = 0;
355 101         262 while (defined(my $thisVal = $list[$splicePosition])) {
356 38         63 my $cmp = attrCmp( $self, $attrib, $value, $thisVal );
357              
358             # Not there yet
359 38 100       97 next if $cmp > 0;
360              
361             # Duplicate - return now if we are preserving uniqueness
362 12 50 66     36 return if (($cmp == 0) and $uniq);
363              
364             # Insert here
365 12         17 last;
366             }
367             continue {
368 26         62 $splicePosition++;
369             }
370              
371             # Insert the value
372 101         328 $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 97     97 1 11983 my $self = shift;
391 97         131 my $attrib = shift;
392              
393 97 50       191 croak "get requires an attribute name" if (!$attrib);
394              
395             # Lower-case the attribute name if necessary
396 97 100       316 $attrib = "\L$attrib" if (!$self->{config}->{caseSensitiveNames});
397              
398 97 50       197 carp "Data::Template::Entry->get attribute '$attrib'" if $debug;
399 97         286 my $valref = $self->{data}->fetch($attrib);
400 97 100       1239 return undef if !$valref;
401 78         159 my @values = @$valref;
402 78 100       358 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 222 my $self = shift;
449 4         6 my $attrib = shift;
450 4         4 my $list = shift;
451              
452 4 50       9 croak "Data::Template::Entry->attribute_match needs an attribute name" if !$attrib;
453 4 50       8 carp "Data::Template::Entry->attribute_match $attrib" if $debug;
454              
455             # Lower-case the attribute name if necessary
456 4 50       11 $attrib = "\L$attrib" if (!$self->{config}->{caseSensitiveNames});
457              
458             # Undef list of values is equivalent to an empty list
459 4 100       8 $list = [] if !$list;
460 4         8 my @supplied = @$list;
461 4         10 my @mine = $self->{data}->fetch($attrib);
462              
463             # Step through the lists comparing values
464 4         44 my $suppVal = shift @supplied;
465 4         6 my $myVal = shift @mine;
466 4   66     16 while ($suppVal and $myVal) {
467 5 100       14 return 0 if (attrCmp($self, $attrib, $suppVal, $myVal) != 0);
468              
469             # Match so far - get the next pair of values
470 4         5 $suppVal = shift @supplied;
471 4         15 $myVal = shift @mine;
472             }
473             # Match is good if no values left
474 3 50 33     26 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 718 my $self = shift;
509 4         6 my $attrib = shift;
510 4         6 my $uniq = shift;
511              
512 4 50       9 croak "uniqueValues requires an attribute name or hash" if (!$attrib);
513              
514 4 50       10 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       14 $attrib = "\L$attrib" if (!$self->{config}->{caseSensitiveNames});
522              
523              
524 4 100       11 if (!defined($uniq)) {
525 2 50       5 carp "Data::Template::Entry->uniqueValues attribute '$attrib'" if $debug;
526 2         10 return $self->{config}->{uniqueValues}->{$attrib};
527             }
528              
529 2 50       5 carp "Data::Template::Entry->uniqueValues attribute '$attrib': $uniq" if $debug;
530 2         12 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 486 my $self = shift;
568 5         6 my $attrib = shift;
569 5         6 my $comp = shift;
570              
571 5 50       13 croak "comparator requires an attribute name or hash" if (!$attrib);
572              
573 5 50       10 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       15 $attrib = "\L$attrib" if (!$self->{config}->{caseSensitiveNames});
581              
582              
583 5 100       9 if (!defined($comp)) {
584 2 50       5 carp "Data::Template::Entry->comparator attribute '$attrib'" if $debug;
585 2         10 return $self->{config}->{comparator}->{$attrib};
586             }
587              
588 3 100       9 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         6 return $self->{config}->{comparator}->{$attrib} = $comp;
592             }
593              
594 2 50       5 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       6 if ("\L$comp" eq 'casesensitive') {
600 1 50       4 carp "Data::Template::Entry->comparator attribute '$attrib' (caseSensitive)" if $debug;
601 1         43 return $self->{config}->{comparator}->{$attrib} = 'caseSensitive';
602             }
603              
604 1 50       4 if ("\L$comp" eq 'integer') {
605 1 50       2 carp "Data::Template::Entry->comparator attribute '$attrib' (integer)" if $debug;
606 1         6 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 474 my $self = shift;
630 5         8 my $map = shift;
631              
632 5 50       14 croak "map requires a map object" if (!$map);
633 5 50       66 croak "map object must be of type Data::Toolkit::Map" if (!$map->isa('Data::Toolkit::Map'));
634 5 50       31 carp "Data::Template::Entry->map" if $debug;
635              
636             # Create a new entry with the same setup as this one
637 5         20 my $newEntry = Data::Toolkit::Entry->new($self->{config});
638              
639             # Get the list of output attributes from the map
640 5         19 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         12 foreach my $attr (@$mapOutputs) {
646 28         203 my $vals = $map->generate($attr,$self,@_);
647 28 50       294 warn "Data::Template::Entry->map $attr: " . (join ':',@$vals) if $debug;
648 28 100       89 $newEntry->add($attr, $vals) if $vals;
649             }
650              
651 5         51 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 247 my $self = shift;
677 4         6 my $attrib = shift;
678 4         10 my $value = shift;
679              
680 4 50       9 croak "delete requires an attribute name" if (!$attrib);
681              
682             # Lower-case the attribute name if necessary
683 4 50       11 $attrib = "\L$attrib" if (!$self->{config}->{caseSensitiveNames});
684              
685              
686 4 100       8 if (defined($value)) {
687             # We are deleting a single value
688 2 50       5 carp "Data::Template::Entry->delete '$value' from attribute '$attrib'" if $debug;
689 2         5 my $allValues = $self->{data}->fetch($attrib);
690             # Is there anything there at all?
691 2 50 33     27 return undef if (!defined($allValues) or !defined($allValues->[0]));
692             # print "NEED TO DELETE $value\n";
693 2         10 for (my $count=0; defined($allValues->[$count]); $count++) {
694 10 100       25 if ($value eq $allValues->[$count]) {
695 1         9 return $self->{data}->splice($attrib,$count,1);
696             }
697             }
698             # Not found
699 1         4 return undef;
700             }
701             else {
702             # We are deleting the whole attribute
703 2 50       9 carp "Data::Template::Entry->delete attribute '$attrib'" if $debug;
704 2         7 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 866 my $class = shift;
738 4 50       12 if (ref $class) { croak "Class method 'debug' called as object method" }
  0         0  
739             # print "DEBUG: ", (join '/', @_), "\n";
740 4 100       11 $debug = shift if (@_ == 1);
741 4         17 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;