File Coverage

blib/lib/DBD/Sys/PluginManager.pm
Criterion Covered Total %
statement 58 64 90.6
branch 12 16 75.0
condition n/a
subroutine 11 13 84.6
pod 5 5 100.0
total 86 98 87.7


line stmt bran cond sub pod time code
1             package DBD::Sys::PluginManager;
2              
3 4     4   20 use strict;
  4         7  
  4         117  
4 4     4   18 use warnings;
  4         7  
  4         115  
5              
6             =head1 NAME
7              
8             DBD::Sys::Plugin - embed own tables to DBD::Sys
9              
10             =head1 SYNOPSIS
11              
12             my $dbh = DBI->connect( "DBI:Sys:", undef, undef, {
13             sys_pluginmgr_class => "DBD::Sys::PluginManager", }
14             ) or die $DBI:errstr;
15              
16             =cut
17              
18 4     4   20 use vars qw($VERSION);
  4         7  
  4         224  
19              
20             require DBD::Sys::Plugin;
21             require DBD::Sys::CompositeTable;
22              
23 4     4   27 use Scalar::Util qw(weaken);
  4         6  
  4         182  
24 4     4   21 use Carp qw(croak);
  4         7  
  4         164  
25 4     4   19 use Params::Util qw(_HASH _ARRAY);
  4         5  
  4         271  
26 4     4   18 use Clone qw(clone);
  4         7  
  4         305  
27              
28             use Module::Pluggable
29 4         48 require => 1,
30             search_path => ['DBD::Sys::Plugin'],
31             inner => 0,
32 4     4   2334 only => qr/^DBD::Sys::Plugin::\p{Word}+$/;
  4         31759  
33              
34             $VERSION = "0.102";
35              
36             =head1 DESCRIPTION
37              
38             The plugin manager provides a basic management of plugins to extend
39             DBD::Sys with additional tables. All plugins are expected to be directly
40             under the C namespace:
41              
42             use Module::Pluggable
43             require => 1,
44             search_path => ['DBD::Sys::Plugin'],
45             inner => 0,
46             only => qr/^DBD::Sys::Plugin::\p{Word}+$/;
47              
48             =head1 METHODS
49              
50             =head2 new
51              
52             Instantiates a new plugin manager and loads all plugins and available
53             tables. During the loading of all that modules, some internal dictionaries
54             are created to find the implementor classes for tables and all valid
55             attributes to tweak the data of the tables.
56              
57             =cut
58              
59             sub new
60             {
61 4     4 1 9 my $class = $_[0];
62 4         10 my %instance = ();
63 4         11 my $self = bless( \%instance, $class );
64 4         7 my @tableAttrs;
65              
66 4         20 foreach my $plugin ( $self->plugins() )
67             {
68 16 50       28172 croak "Invalid plugin: $plugin" unless ( $plugin->isa('DBD::Sys::Plugin') );
69 16         110 my %pluginTables = $plugin->get_supported_tables();
70 16         58 foreach my $pluginTable ( keys %pluginTables )
71             {
72 48         81 my $pte = lc $pluginTable;
73 4         14 my @pluginClasses =
74             defined( _ARRAY( $pluginTables{$pluginTable} ) )
75 48 100       179 ? @{ $pluginTables{$pluginTable} }
76             : ( $pluginTables{$pluginTable} );
77              
78 48 100       143 if ( exists( $self->{tables2classes}->{$pte} ) )
79             {
80 12 50       80 defined( _ARRAY( $self->{tables2classes}->{$pte} ) )
81             or $self->{tables2classes}->{$pte} = [ $self->{tables2classes}->{$pte} ];
82              
83 12         56 push(
84 0         0 @{ $self->{tables2classes}->{$pte} },
85             defined( _ARRAY( $pluginTables{$pluginTable} ) )
86 12 50       20 ? @{ $pluginTables{$pluginTable} }
87             : $pluginTables{$pluginTable}
88             );
89             }
90             else
91             {
92 36         86 $self->{tables2classes}->{$pte} = $pluginTables{$pluginTable};
93             }
94              
95 48         67 foreach my $pluginClass (@pluginClasses)
96             {
97 20         98 $pluginClass->can('get_attributes')
98             and push( @tableAttrs,
99 52 100       682 map { join( '_', 'sys', $pte, $_ ) } $pluginClass->get_attributes() );
100             }
101             }
102             }
103              
104 4         18 $self->{tables_attrs} = \@tableAttrs;
105              
106 4         31 return $self;
107             }
108              
109             =head2 get_table_list
110              
111             Returns the list of the known table names. It's intended for internal use
112             only, so be aware that the API might change!
113              
114             =cut
115              
116             sub get_table_list
117             {
118 0     0 1 0 return keys %{ $_[0]->{tables2classes} };
  0         0  
119             }
120              
121             =head2 get_table_details
122              
123             Returns a hash containing the table names and the table implementor
124             classes as value. It's intended for internal use only, so be aware
125             that the API might change!
126              
127             =cut
128              
129             sub get_table_details
130             {
131 0     0 1 0 return %{ clone( $_[0]->{tables2classes} ) };
  0         0  
132             }
133              
134             =head2 get_tables_attrs
135              
136             Returns a C<< $dbh->{sys_valid_attrs} >> compatible hash map of valid
137             attributes of the loaded tables. It's intended for internal use only,
138             so be aware that the API might change!
139              
140             =cut
141              
142             sub get_tables_attrs
143             {
144 4     4 1 11 my $self = $_[0];
145 4         9 my %attrMap = map { $_ => 1 } @{ $self->{tables_attrs} };
  20         61  
  4         14  
146 4         24 return \%attrMap;
147             }
148              
149             =head2 get_table
150              
151             Instantiates the appropriate table class for a given table name.
152             If multiple implementators for the specified table are known, a
153             L is instantiated which manages the
154             merging of the data delivered by each table and return one,
155             consolidated data set to the calling SQL engine. It's intended for
156             internal use only, so be aware that the API might change!
157              
158             =cut
159              
160             sub get_table
161             {
162 6     6 1 15 my ( $self, $tableName, $attrs ) = @_;
163 6         11 $tableName = lc $tableName;
164 6 50       28 exists $self->{tables2classes}->{$tableName}
165             or croak("Specified table '$tableName' not known");
166              
167 6         17 my $tableInfo = $self->{tables2classes}->{$tableName};
168 6         8 my $table;
169 6 100       30 if ( ref($tableInfo) )
170             {
171 5         41 $table = DBD::Sys::CompositeTable->new( $tableInfo, $attrs );
172             }
173             else
174             {
175 1         18 $table = $tableInfo->new($attrs);
176             }
177              
178 0           return $table;
179             }
180              
181             =head1 AUTHOR
182              
183             Jens Rehsack
184             CPAN ID: REHSACK
185             rehsack@cpan.org
186             http://search.cpan.org/~rehsack/
187              
188             =head1 COPYRIGHT
189              
190             This program is free software; you can redistribute
191             it and/or modify it under the same terms as Perl itself.
192              
193             The full text of the license can be found in the
194             LICENSE file included with this module.
195              
196             =head1 SUPPORT
197              
198             Free support can be requested via regular CPAN bug-tracking system at
199             L. There is
200             no guaranteed reaction time or solution time, but it's always tried to give
201             accept or reject a reported ticket within a week. It depends on business load.
202             That doesn't mean that ticket via rt aren't handles as soon as possible,
203             that means that soon depends on how much I have to do.
204              
205             Business and commercial support should be acquired from the authors via
206             preferred freelancer agencies.
207              
208             =cut
209              
210             1;