=head1 NAME Palm::Progect::VersionDelegator - Delegate to specific Progect db driver based on version =head1 SYNOPSIS package Palm::Progect::Record; use vars qw(@ISA); @ISA = qw(Palm::Progect::Record); 1; =head1 DESCRIPTION Delegate to specific database driver based on database version. If version is not specified, then it will delegate to the database driver with the highest number. For instance to create a version 0.18 Record, the user can do the following: my $record = Palm::Progect::Record->new( raw_record => $some_raw_data, version => 18, ); Behind the scenes, this call will be translated into the equivalent of: require 'Palm/Progect/DB_18/Record.pm'; my $record = Palm::Progect::DB_18::Record->new( raw_record => $some_raw_data, ); =cut package Palm::Progect::VersionDelegator; use strict; use 5.004; use File::Spec; use Carp; sub new { my $proto = shift; my $this_class = ref $proto || $proto; my @base_class = split /::/, $this_class; # e.g. ('Palm', 'Progect') my $module_name = pop @base_class; # e.g. 'Record' my %args = @_; my $version = delete $args{'version'} || 0; my $version_class = ''; if ($version > 0) { $version_class = 'DB_' . $version; } else { # Latest version was requested. $version_class = 'DB_' . _latest_version(File::Spec->join(@base_class)); } my $module_path = File::Spec->join(@base_class,$version_class, $module_name . '.pm'); my $module_class = join '::', @base_class, $version_class, $module_name; require $module_path; return $module_class->new(%args); } # Cache the latest version to avoid repeatedly searching # through the filesystem # Find latest version of module # find directories matching DB_yy # and pick the one where yy is the greatest my %Latest_Version; sub _latest_version { my $base_class_path = shift; if (! exists $Latest_Version{$base_class_path}) { local *DIR; my $max_version = 0; my $max_version_filename = ''; foreach my $inc (@INC) { my $path = File::Spec->join($inc, $base_class_path); next unless -d $path; if (opendir DIR, $path) { my @subdirs = readdir(DIR); close DIR; foreach my $subdir (@subdirs) { next unless -d File::Spec->join($path, $subdir); next unless $subdir =~ /^DB_(\d+)$/; my $subdir_version = $1; next unless $subdir_version > $max_version; $max_version = $subdir_version; } } } $Latest_Version{$base_class_path} = $max_version; } return $Latest_Version{$base_class_path}; } 1; __END__ =head1 AUTHOR Michael Graham Emag-perl@occamstoothbrush.comE Copyright (C) 2002-2005 Michael Graham. All rights reserved. This program is free software. You can use, modify, and distribute it under the same terms as Perl itself. The latest version of this module can be found on http://www.occamstoothbrush.com/perl/ =head1 SEE ALSO C L http://progect.sourceforge.net/ =cut