File Coverage

blib/lib/XAO/SimpleHash.pm
Criterion Covered Total %
statement 98 143 68.5
branch 38 62 61.2
condition 15 30 50.0
subroutine 16 21 76.1
pod 0 17 0.0
total 167 273 61.1


line stmt bran cond sub pod time code
1             # Base of all hash-like objects.
2             #
3             package XAO::SimpleHash;
4 5     5   4945 use strict;
  5         12  
  5         144  
5 5     5   25 use Carp;
  5         10  
  5         9693  
6              
7             ###############################################################################
8              
9             #
10             # METHODS
11             #
12              
13             sub new ($;@);
14             sub fill ($@);
15              
16             #
17             # Perl-style API
18             #
19              
20             sub put ($$$); # has URI support
21             sub get ($$); # has URI support
22             sub getref ($$); # has URI support
23             sub delete ($$); # has URI support
24             sub defined ($$); # has URI support
25             sub exists ($$); # has URI support
26             sub keys ($); # has URI support
27             sub values ($); # has URI support
28             sub contains ($$);
29              
30             #
31             # Java style API
32             #
33              
34             sub isSet ($$);
35             sub containsKey ($);
36             sub containsValue ($$);
37             sub remove ($$);
38              
39             ###############################################################################
40             #
41             # Creating object instance and loading initial data.
42             #
43             sub new ($;@) {
44 14     14 0 356 my $proto=shift;
45 14   66     158 my $this = bless {}, ref($proto) || $proto;
46 14 100       139 $this->fill(@_) if @_;
47 14         108 $this;
48             }
49              
50             ###############################################################################
51             #
52             # Filling with values. Values may be given in any of the following
53             # formats:
54             # { key1 => value1,
55             # key2 => value2
56             # }
57             # or
58             # key1 => value1,
59             # key2 => value2
60             # or
61             # [ key1 => value1 ], (deprecated)
62             # [ key2 => value2 ]
63             #
64             sub fill ($@)
65             {
66 14     14 0 28 my $self = shift;
67 14 50       45 return unless @_;
68 14         25 my $args;
69              
70             #print "*** SimpleHash->fill: $self\n";
71              
72             #
73             # We have hash reference?
74             #
75 14 100 66     135 if (@_ == 1 && ref($_[0]))
    100          
    50          
76             {
77 7         26 $args = $_[0];
78             }
79            
80             #
81             # @_ = ['NAME', 'PHONE'], ['John Smith', '(626)555-1212']
82             #
83             elsif(ref($_[0]) eq 'ARRAY')
84             {
85 1         8 my %a=map { ($_->[0], $_->[1]) } @_;
  2         9  
86 1         3 $args=\%a;
87             }
88              
89             #
90             # @_ = 'NAME' => 'John Smith', 'PHONE' => '(626)555-1212'
91             #
92             elsif(int(@_) % 2 == 0)
93             {
94 6         56 my %a=@_;
95 6         30 $args=\%a;
96             }
97             #
98             # Something we do not understand.. yet :)
99             #
100             else
101             {
102 0         0 carp ref($self)."::fill - syntax error in argument passing";
103 0         0 return undef;
104             }
105              
106             #
107             # Putting data in in pretty efficient but hard to read way :)
108             #
109             # @{self}{keys %{$args}} =CORE::values %{$args};
110              
111 14         33 foreach (CORE::keys %{$args}) { $self->{$_} = $args->{$_}; }
  14         65  
  21         127  
112             }
113             ###############################################################################
114             #
115             # Checks does given key contains anything or not.
116             #
117             sub defined ($$)
118             {
119 3     3 0 16 my ($self, $name) = @_;
120              
121 3         9 my @uri = $self->_uri_parser($name);
122              
123 3 100       16 return defined $self->{$uri[0]} unless $#uri > 0;
124              
125 1         1 my $value=$self;
126 1         7 foreach my $key (@uri)
127             {
128 3         9 my $ref = ref($value);
129             return undef unless ($ref eq 'HASH' || $ref eq ref($self))
130 3 100 66     49 && defined $value->{$key};
      66        
131 2         9 $value = $value->{$key};
132             }
133 0         0 1;
134             }
135             ###############################################################################
136             #
137             # The same as defined(), method name compatibility with Java hash.
138             #
139             sub isSet ($$)
140             {
141 0     0 0 0 my $self=shift;
142 0         0 $self->defined(@_);
143             }
144             ###############################################################################
145             #
146             # Putting new value. Fill optimized for name-value pair.
147             #
148             sub put ($$$)
149             {
150 7     7 0 39 my ($self, $name, $new_value) = @_;
151              
152 7         37 my @uri = $self->_uri_parser($name);
153 7         22 my $last_idx = $#uri;
154              
155 7 100       25 unless ($last_idx > 0)
156             {
157 4         21 $self->{$uri[0]} = $new_value;
158 4         16 return $new_value;
159             }
160              
161 3         5 my $i=0;
162 3         8 my $value=$self;
163 3         10 foreach my $key (@uri)
164             {
165 9 100       16 if ($i < $last_idx)
166             {
167 6 100       33 $value->{$key} = {} unless ref($value->{$key}) eq 'HASH';
168 6         10 $value = $value->{$key};
169             }
170             else
171             {
172 3         6 $value->{$key} = $new_value;
173 3         12 return $value->{$key};
174             }
175 6         9 $i++;
176             }
177             }
178             ###############################################################################
179             #
180             # Getting value by name
181             #
182             sub get ($$)
183             {
184 62     62 0 230 my ($self, $name) = @_;
185 62         147 my $ref = $self->getref($name);
186 62 100       628 return ref($ref) ? $$ref : undef;
187             }
188             ###############################################################################
189             #
190             # Returns reference to the value. Suitable for really big or complex
191             # values and to be used on left side of expression.
192             #
193             sub getref ($$)
194             {
195 62     62 0 105 my ($self, $name) = @_;
196 62 100       140 return undef unless $self->exists($name);
197              
198 57         142 my @uri = $self->_uri_parser($name);
199              
200 57 100       163 return \$self->{$uri[0]} unless $#uri > 0;
201              
202 39         93 my $value=$self;
203 39         82 foreach my $key (@uri)
204             {
205 114         189 my $ref = ref($value);
206 114 50 66     319 if ($ref eq 'HASH' || $ref eq ref($self))
207             {
208 114         210 $value = $value->{$key};
209             }
210             else
211             {
212 0         0 return undef;
213             }
214             }
215 39         94 \$value;
216             }
217             ###############################################################################
218             #
219             # Checks whether we contain given key or not.
220             #
221             sub exists ($$) {
222 67     67 0 114 my ($self, $name) = @_;
223              
224 67         102 my $value=$self;
225 67         257 foreach my $key ($self->_uri_parser($name)) {
226 154         298 my $r=ref($value);
227             return undef unless ($r eq 'HASH' || $r eq ref($self)) &&
228 154 100 66     747 CORE::exists $value->{$key};
      66        
229 146         324 $value=$value->{$key};
230             }
231              
232 59         250 1;
233             }
234              
235             ###############################################################################
236             #
237             # The same as exists(), method name compatibility with Java hash.
238             #
239             sub containsKey ($)
240             {
241 0     0 0 0 my $self=shift;
242 0         0 $self->exists(@_);
243             }
244             ###############################################################################
245             #
246             # List of elements in the 'hash'.
247             #
248             sub values ($)
249             {
250 1     1 0 3 my ($self, $key) = @_;
251              
252 1 50       14 return CORE::values %{$self} unless defined($key);
  1         21  
253              
254 0         0 my @uri = $self->_uri_parser($key);
255 0         0 my $last_idx = $#uri;
256              
257 0 0       0 return CORE::values %{$self} unless $uri[0] =~ /\S+/;
  0         0  
258              
259 0         0 my $i=0;
260 0         0 my $value=$self;
261 0         0 foreach my $key (@uri)
262             {
263 0         0 my $ref = ref($value);
264 0 0 0     0 if ($ref eq 'HASH' || $ref eq ref($self))
265             {
266 0         0 $value = $value->{$key};
267             }
268             else
269             {
270 0         0 return undef;
271             }
272 0 0       0 if ($i == $last_idx)
273             {
274 0 0       0 return ref($value) eq 'HASH' ? CORE::values %{$value} : undef;
  0         0  
275             }
276 0         0 $i++;
277             }
278             }
279             ###############################################################################
280             #
281             # The same as values(), method name compatibility with Java hash.
282             #
283             sub elements ($)
284             {
285 0     0 0 0 my $self=shift;
286 0         0 $self->values;
287             }
288             ###############################################################################
289             #
290             # Keys in the 'hash'. In the same order as 'elements'.
291             #
292             sub keys ($)
293             {
294 2     2 0 22 my ($self, $key) = @_;
295              
296 2 50       7 return CORE::keys %{$self} unless defined($key);
  2         15  
297              
298 0         0 my @uri = $self->_uri_parser($key);
299 0         0 my $last_idx = $#uri;
300              
301 0 0       0 return CORE::keys %{$self} unless $uri[0] =~ /\S+/;
  0         0  
302              
303 0         0 my $i=0;
304 0         0 my $value=$self;
305 0         0 foreach my $key (@uri)
306             {
307 0         0 my $ref = ref($value);
308 0 0 0     0 if ($ref eq 'HASH' || $ref eq ref($self))
309             {
310 0         0 $value = $value->{$key};
311             }
312             else
313             {
314 0         0 return undef;
315             }
316 0 0       0 if ($i == $last_idx)
317             {
318 0 0       0 return ref($value) eq 'HASH' ? CORE::keys %{$value} : undef;
  0         0  
319             }
320 0         0 $i++;
321             }
322             }
323              
324             ###############################################################################
325             #
326             # Deleting given key from the 'hash'.
327             #
328             sub delete ($$) {
329 2     2 0 4 my ($self, $key) = @_;
330              
331 2         4 my @uri = $self->_uri_parser($key);
332 2         3 my $last_idx = $#uri;
333              
334 2 100       8 return delete $self->{$uri[0]} unless $last_idx > 0;
335              
336 1         3 my $i=0;
337 1         1 my $value=$self;
338 1         8 foreach my $key (@uri) {
339 2 100       8 if ($i < $last_idx) {
340 1 50       5 return undef unless ref($value->{$key}) eq 'HASH';
341 1         2 $value = $value->{$key};
342             }
343             else {
344             return (ref($value) eq 'HASH' && CORE::exists $value->{$key})
345 1 50 33     16 ? CORE::delete $value->{$key} : undef;
346             }
347 1         3 $i++;
348             }
349              
350 0         0 '';
351             }
352              
353             ###############################################################################
354             #
355             # The same as delete(), method name compatibility with Java hash.
356             #
357             sub remove ($$)
358             {
359 0     0 0 0 my $self=shift;
360 0         0 $self->delete(@_);
361             }
362             ###############################################################################
363             #
364             # Checks if our 'hash' contains specific value and return key or undef.
365             # Case is insignificant.
366             #
367             sub contains ($$)
368             {
369 2     2 0 6 my ($self, $value) = @_;
370 2         3 while(my ($key, $tvalue) = each %{$self})
  8         31  
371             {
372 7 100       20 return $key if uc($tvalue) eq uc($value);
373             }
374 1         4 undef;
375             }
376             ###############################################################################
377             #
378             # The same as contains, method name compatibility with Java hash.
379             #
380             sub containsValue ($$)
381             {
382 0     0 0 0 my $self=shift;
383 0         0 $self->contains(@_);
384             }
385             ###############################################################################
386             sub _uri_parser {
387 136     136   260 my ($self, $uri) = @_;
388 136 50       295 die "No URI passed" unless defined($uri);
389 136         456 $uri =~ s/^\/+//; # get rid of leading slashes
390 136         389 $uri =~ s/\/+$//; # get rid of trailing slashes
391 136         561 split(/\/+/, $uri);
392             }
393              
394             ###############################################################################
395              
396             #XXX This should really be in POD! (AM)
397             #
398             # =item embeddable_methods ()
399             #
400             # Returns a list of methods to be embedded into Configuration. Only used
401             # by XAO::DO::Config object. Currently the list of embeddable methods
402             # include all methods of Perl API.
403             #
404             # =cut
405              
406             sub embeddable_methods () {
407 5     5 0 60 qw(put get getref delete defined exists keys values contains);
408             }
409              
410             ###############################################################################
411             #
412             # That's it
413             #
414 5     5   51 use vars qw($VERSION);
  5         18  
  5         554  
415             $VERSION=(0+sprintf('%u.%03u',(q$Id: SimpleHash.pm,v 2.1 2005/01/13 22:34:34 am Exp $ =~ /\s(\d+)\.(\d+)\s/))) || die "Bad VERSION";
416             1;
417             __END__