File Coverage

blib/lib/Catmandu/Fix/Bind/hashmap.pm
Criterion Covered Total %
statement 44 45 97.7
branch 15 16 93.7
condition 4 5 80.0
subroutine 9 9 100.0
pod 0 1 0.0
total 72 76 94.7


line stmt bran cond sub pod time code
1             package Catmandu::Fix::Bind::hashmap;
2              
3 1     1   6206 use Catmandu::Sane;
  1         3  
  1         12  
4              
5             our $VERSION = '1.2020';
6              
7 1     1   8 use Moo;
  1         2  
  1         14  
8 1     1   545 use Catmandu::Util qw(:is);
  1         3  
  1         232  
9 1     1   8 use namespace::clean;
  1         21  
  1         33  
10 1     1   1181 use Catmandu::Fix::Has;
  1         3  
  1         16  
11              
12             with 'Catmandu::Fix::Bind', 'Catmandu::Fix::Bind::Group';
13              
14             has exporter => (fix_opt => 1);
15             has store => (fix_opt => 1);
16             has uniq => (fix_opt => 1, default => sub {0});
17             has count => (fix_opt => 1);
18             has join => (fix_opt => 1);
19             has extra_args => (fix_opt => 'collect');
20             has hash => (is => 'lazy');
21              
22             sub _build_hash {
23 12     12   138 +{};
24             }
25              
26             sub add_to_hash {
27 9     9 0 19 my ($self, $key, $val) = @_;
28 9 100       36 if ($self->count) {
    100          
29 3         53 $self->hash->{$key} += 1;
30             }
31             elsif ($self->uniq) {
32 3         53 $self->hash->{$key}->{$val} = 1;
33             }
34             else {
35 3         4 push @{$self->hash->{$key}}, $val;
  3         55  
36             }
37             }
38              
39             sub bind {
40             my ($self, $data, $code) = @_;
41              
42             $data = $code->($data);
43              
44             my $key = $data->{key};
45             my $value = $data->{value};
46              
47             if (defined $key) {
48             if (is_string($key)) {
49             $self->add_to_hash($key, $value);
50             }
51             elsif (is_array_ref($key)) {
52             for (@$key) {
53             $self->add_to_hash($_, $value);
54             }
55             }
56             else {
57             warn "$key is not a string or array for $value";
58             }
59             }
60              
61             $data;
62             }
63              
64             sub DESTROY {
65 12     12   2225 my ($self) = @_;
66 12         247 my $h = $self->hash;
67 12         48 my $e;
68 12   50     55 my $args = $self->extra_args // {};
69              
70 12 50       53 if ($self->store) {
    100          
71 0         0 $e = Catmandu->store($self->store, %$args);
72             }
73             elsif ($self->exporter) {
74 3         29 $e = Catmandu->exporter($self->exporter, %$args);
75             }
76             else {
77 9         50 $e = Catmandu->exporter('JSON', line_delimited => 1);
78             }
79              
80 12 100   2   131 my $sorter = $self->count ? sub {$h->{$b} <=> $h->{$a}} : sub {$a cmp $b};
  1         5  
  2         15  
81              
82 12         27 my $id = 0;
83 12         60 for (sort $sorter keys %$h) {
84 6         35 my $v;
85              
86 6 100       70 if ($self->count) {
    100          
87 2         4 $v = $h->{$_};
88             }
89             elsif ($self->uniq) {
90 2         6 $v = [sort keys %{$h->{$_}}];
  2         20  
91             }
92             else {
93 2         7 $v = $h->{$_};
94             }
95              
96 6 100 100     37 if (is_array_ref($v) && $self->join) {
97 2         11 $v = join $self->join, @$v;
98             }
99              
100 6         142 $e->add({_id => $_, value => $v});
101             }
102              
103 12         269 $e->commit;
104             }
105              
106             1;
107              
108             __END__
109              
110             =pod
111              
112             =head1 NAME
113              
114             Catmandu::Fix::Bind::hashmap - a binder to add key/value pairs to an internal hashmap
115              
116             =head1 SYNOPSIS
117              
118             # Find non unique ISBN numbers in the record stream
119             do hashmap(join: ',')
120             copy_field(isbn,key)
121             copy_field(_id,value)
122             end
123              
124             # will export to the JSON exporter a hash map containing all isbn occurrences in the stream
125              
126             { "_id": "9781565920422" , "value": "rec0001,rec0329,rec1032" }
127             { "_id": "9780596004927" , "value": "rec0718" }
128              
129             # Ignore the values. Count the number of ISBN occurrences in a stream
130             # File: count.fix:
131             do hashmap(count: 1)
132             copy_field(isbn,key)
133             end
134              
135             # Use the Null exporter to suppress the normal output
136             $ cat /tmp/data.json | catmandu convert JSON --fix count.fix to Null
137              
138             =head1 DESCRIPTION
139              
140             The hashmap binder will insert all key/value pairs given to a internal hashmap
141             that can be exported using an Catmandu::Exporter.
142              
143             The 'key' fields in the internal hashmap will be exported as '_id' field.
144              
145             If the key in the hashmap Bind is an ARRAY, then multiple key/value pairs will
146             be inserted into the hashmap.
147              
148             By default all the values will be added as an array to the hashmap. Every key
149             will have one or more values. Use the 'join' parameter to create a string
150             out of this array.
151              
152             =head1 CONFIGURATION
153              
154             =head2 exporter: EXPORTER
155              
156             The name of an exporter to send the results to. Default: JSON Extra parameters can be added:
157              
158             do hashmap(exporter: JSON, file:/tmp/data.json, count: 1)
159             ...
160             end
161              
162             =head2 store: STORE
163              
164             Send the output to a store instead of an exporter. Extra parameters can be added:
165              
166             do hashmap(store: MongoDB, database_name: test, bag: data, count: 1)
167             ...
168             end
169              
170             =head2 uniq: 0|1
171              
172             When set to 1, then all values in the key 'value' will be made unique
173              
174             =head2 join: CHAR
175              
176             Join all the values of a key using a delimiter.
177              
178             =head2 count: 0|1
179              
180             Don't store the values only count the number of key occurrences.
181              
182             =head1 SEE ALSO
183              
184             L<Catmandu::Fix::Bind>
185              
186             =cut