Data-FeatureFactory
view release on metacpan or search on metacpan
lib/Data/FeatureFactory.pm view on Meta::CPAN
package Data::FeatureFactory;
use strict;
use Carp;
use File::Basename;
use Scalar::Util;
our $VERSION = '0.0405';
my $PATH = &{ sub { return dirname( (caller)[1] ) } };
my $OPEN_OPTIONS;
our $CURRENT_FEATURE;
my %KNOWN_FORMATS = map {;$_=>1} qw/binary normal numeric/;
# check if perl can open files in utf8
{
my $fh;
undef $@;
eval { open $fh, '<:encoding(utf8)', $0 };
if ($@) {
$OPEN_OPTIONS = '';
warn qq{the open's :encoding directive not supported by your perl ($]). Files won't be opened in utf8 format.};
}
else { $OPEN_OPTIONS = ':encoding(utf8)' }
close $fh;
}
sub new : method {
my ($class, $args) = @_;
$class = ref $class if ref $class;
croak "Too many parameters to $class->new" if @_ > 2;
my $self = bless +{}, $class;
if (defined $args) {
croak "The parameter to ${class}->new must be a hashref with options or nothing" if ref $args ne 'HASH';
my %accepted_option = map {;$_=>1} qw(N/A);
while (my ($k, $v) = each %$args) {
if (not exists $accepted_option{$k}) {
croak "Unexpected option '$k' passed to ${class}->new"
}
if ($k eq 'N/A') {
$self->{'N/A'} = "$v";
}
}
}
no strict 'refs';
if (not @{$class."::features"}) {
croak "\@${class}::features not defined";
}
our @features;
*features = \@{$class."::features"};
use strict;
if (not @features) {
warn "$class has empty set of features. Not much fun";
}
$self->{'features'} = [];
my %feat_named;
$self->{'feat_named'} = \%feat_named;
my @featkeys;
$self->{'featkeys'} = \@featkeys;
$self->{'caller_path'} = dirname( (caller)[1] );
my %supported_option = ( map {;$_=>1} qw(code default format label name postproc range type values values_file) );
my %accepted_option = ( map {;$_=>1} qw(cat2num cat2num_dyna num2cat num2cat_dyna num_values_fh values_ordered) );
# parse the @features array
for my $original_feature (@features) {
my $feature = { %$original_feature };
if (not exists $feature->{'name'}) {
croak q{There was a feature without a name. Each record in the @features array must be a hashref with a 'name' field at least};
}
my $name = $feature->{'name'};
if (exists $feat_named{$name}) {
croak "Feature $name specified twice in \@${class}::features";
}
push @{ $self->{'features'} }, $feature;
$feat_named{$name} = $feature;
push @featkeys, $name;
# Check if there aren't illegal options
for (keys %$feature) {
if (not exists $supported_option{$_}) {
if (exists $accepted_option{$_}) {
warn "Option '$_' you specified for feature '$name' is not supported. Be sure you know what you are doing"
}
else {
croak "Unrecognized option '$_' specified for feature '$name'";
}
}
}
# Check if a postprocessing subroutine is declared
# If it's a CODEref, we're OK. Else try to load it.
if (exists $feature->{'postproc'} and ref $feature->{'postproc'} ne 'CODE') {
my $postproc = $feature->{'postproc'};
no strict 'refs';
my $postprocsub = \&{$postproc};
undef $@;
eval { $postprocsub->() };
if ($@ =~ /Undefined subroutine/) {
my ($package_name) = $postproc =~ /^( (?: \w+:: )+ )/x;
my $ppname;
if (defined $package_name and length $package_name > 0) {
$package_name =~ s/::$//;
local @INC = (@INC, $self->{'caller_path'});
undef $@;
eval "require $package_name";
if ($@) {
warn "Failed loading module '$package_name'";
}
$ppname = $postproc;
}
else {
$ppname = $class.'::'.$postproc;
}
$postprocsub = \&{$ppname};
undef $@;
eval { $postprocsub->() };
if ($@ =~ /^Undefined subroutine/) {
croak "Couldn't load postprocessing function '$postproc' ($@)"
}
( run in 0.509 second using v1.01-cache-2.11-cpan-63c85eba8c4 )