File Coverage

blib/lib/Class/DBI/ColumnGrouper.pm
Criterion Covered Total %
statement 53 56 94.6
branch 17 22 77.2
condition 11 15 73.3
subroutine 17 17 100.0
pod 11 11 100.0
total 109 121 90.0


line stmt bran cond sub pod time code
1             package Class::DBI::ColumnGrouper;
2              
3             =head1 NAME
4              
5             Class::DBI::ColumnGrouper - Columns and Column Groups
6              
7             =head1 SYNOPSIS
8              
9             my $colg = Class::DBI::ColumnGrouper->new;
10             $colg->add_group(People => qw/star director producer/);
11              
12             my @cols = $colg->group_cols($group);
13              
14             my @all = $colg->all_columns;
15             my @pri_col = $colg->primary;
16             my @essential_cols = $colg->essential;
17              
18             =head1 DESCRIPTION
19              
20             Each Class::DBI class maintains a list of its columns as class data.
21             This provides an interface to that. You probably don't want to be dealing
22             with this directly.
23              
24             =head1 METHODS
25              
26             =cut
27              
28 4     4   23 use strict;
  4         8  
  4         137  
29              
30 4     4   23 use Carp;
  4         7  
  4         673  
31 4     4   5028 use Storable 'dclone';
  4         17507  
  4         370  
32 4     4   3001 use Class::DBI::Column;
  4         11  
  4         39  
33              
34             sub _unique {
35 1     1   2 my %seen;
36 1 100       3 map { $seen{$_}++ ? () : $_ } @_;
  3         23  
37             }
38              
39             sub _uniq {
40 12     12   18 my %tmp;
41 12         45 return grep !$tmp{$_}++, @_;
42             }
43              
44             =head2 new
45              
46             my $colg = Class::DBI::ColumnGrouper->new;
47              
48             A new blank ColumnnGrouper object.
49              
50             =head2 clone
51              
52             my $colg2 = $colg->clone;
53              
54             Clone an existing ColumnGrouper.
55              
56             =cut
57              
58             sub new {
59 4     4 1 9 my $class = shift;
60 4         32 bless {
61             _groups => {},
62             _cols => {},
63             }, $class;
64             }
65              
66             sub clone {
67 15     15 1 180 my ($class, $prev) = @_;
68 15         1782 return dclone $prev;
69             }
70              
71             =head2 add_column / find_column
72              
73             $colg->add_column($name);
74             my Class::DBI::Column $col = $colg->find_column($name);
75              
76             Add or return a Column object for the given column name.
77              
78             =cut
79              
80             sub add_column {
81 36     36 1 162 my ($self, $col) = @_;
82              
83             # TODO remove this
84 36 50       143 croak "Need a Column, got $col" unless $col->isa("Class::DBI::Column");
85 36   66     123 $self->{_allcol}->{ $col->name_lc } ||= $col;
86             }
87              
88             sub find_column {
89 8     8 1 61 my ($self, $name) = @_;
90 8 50       24 return $name if ref $name;
91 8 100       42 return unless $self->{_allcol}->{ lc $name };
92             }
93              
94             =head2 add_group
95              
96             $colg->add_group(People => qw/star director producer/);
97              
98             This adds a list of columns as a column group.
99              
100             =cut
101              
102             sub add_group {
103 19     19 1 46 my ($self, $group, @names) = @_;
104 19 100 100     131 $self->add_group(Primary => $names[0])
      100        
105             if ($group eq "All" or $group eq "Essential")
106             and not $self->group_cols('Primary');
107 19 50 66     80 $self->add_group(Essential => @names)
108             if $group eq "All"
109             and !$self->essential;
110 19 100       57 @names = _unique($self->primary, @names) if $group eq "Essential";
111              
112 19         66 my @cols = map $self->add_column($_), @names;
113 19         222 $_->add_group($group) foreach @cols;
114 19         55 $self->{_groups}->{$group} = \@cols;
115 19         256 return $self;
116             }
117              
118             =head2 group_cols / groups_for
119              
120             my @colg = $cols->group_cols($group);
121             my @groups = $cols->groups_for(@cols);
122              
123             This returns a list of all columns which are in the given group, or the
124             groups a given column is in.
125              
126             =cut
127              
128             sub group_cols {
129 44     44 1 71 my ($self, $group) = @_;
130 44 50       202 return $self->all_columns if $group eq "All";
131 44 100       53 @{ $self->{_groups}->{$group} || [] };
  44         275  
132             }
133              
134             sub groups_for {
135 2     2 1 1585 my ($self, @cols) = @_;
136 2         25 return _uniq(map $_->groups, @cols);
137             }
138              
139             =head2 columns_in
140              
141             my @cols = $colg->columns_in(@groups);
142              
143             This returns a list of all columns which are in the given groups.
144              
145             =cut
146              
147             sub columns_in {
148 11     11 1 22 my ($self, @groups) = @_;
149 11         34 return _uniq(map $self->group_cols($_), @groups);
150             }
151              
152             =head2 all_columns
153              
154             my @all = $colg->all_columns;
155              
156             This returns a list of all the real columns.
157              
158             =head2 primary
159              
160             my $pri_col = $colg->primary;
161              
162             This returns a list of the columns in the Primary group.
163              
164             =head2 essential
165              
166             my @essential_cols = $colg->essential;
167              
168             This returns a list of the columns in the Essential group.
169              
170             =cut
171              
172             sub all_columns {
173 10     10 1 80 my $self = shift;
174 10         16 return grep $_->in_database, values %{ $self->{_allcol} };
  10         53  
175             }
176              
177             sub primary {
178 24     24 1 150 my @cols = shift->group_cols('Primary');
179 24 50 33     78 if (!wantarray && @cols > 1) {
180 0         0 local ($Carp::CarpLevel) = 1;
181 0         0 confess(
182             "Multiple columns in Primary group (@cols) but primary called in scalar context"
183             );
184 0         0 return $cols[0];
185             }
186 24         63 return @cols;
187             }
188              
189             sub essential {
190 11     11 1 45 my $self = shift;
191 11         30 my @cols = $self->columns_in('Essential');
192 11 100       55 @cols = $self->primary unless @cols;
193 11         55 return @cols;
194             }
195              
196             1;