File Coverage

blib/lib/SeeAlso/Identifier/Factory.pm
Criterion Covered Total %
statement 77 82 93.9
branch 24 38 63.1
condition 1 3 33.3
subroutine 14 16 87.5
pod 3 3 100.0
total 119 142 83.8


line stmt bran cond sub pod time code
1 1     1   1037 use strict;
  1         2  
  1         45  
2 1     1   6 use warnings;
  1         2  
  1         60  
3             package SeeAlso::Identifier::Factory;
4             {
5             $SeeAlso::Identifier::Factory::VERSION = '0.71';
6             }
7             #ABSTRACT: Identify and create identifiers
8              
9 1     1   620 use SeeAlso::Identifier;
  1         3  
  1         27  
10 1     1   8 use Carp;
  1         2  
  1         597  
11              
12              
13             sub new {
14 8     8 1 2866 my ($class, %params) = @_;
15              
16 8         42 my $self = bless {
17             type => [ 'SeeAlso::Identifier' ]
18             }, $class;
19              
20 8         17 my $type = $params{'type'};
21 8         12 my $parse = $params{'parse'};
22              
23 8 100       25 if ($parse) {
24 3 50       11 croak('parse parameter must be a code reference')
25             unless ref($parse) eq 'CODE';
26 3         6 $self->{parse} = $parse;
27             }
28              
29 8 100 33     49 if (ref($type) eq 'ARRAY') {
    50          
30 3         7 $self->{type} = $type;
31             } elsif (not ref($type) and $type) {
32 5         21 $self->{type} = [$type];
33             } else {
34 0         0 croak('type parameter must be scalar or array reference');
35             # TODO: also support hash reference
36             }
37              
38             ## no critic
39 8         17 foreach my $type (@{$self->{type}}) {
  8         23  
40 9 100       517 if ( not eval 'require ' . $type ) {
41 3 100       5 if ( @{$self->{type}} == 1 ) {
  3         13  
42 2         3 $params{type} = $type;
43 2         8 makeclass( %params );
44             }
45             }
46 9 100       108 UNIVERSAL::isa( $type, 'SeeAlso::Identifier' )
47             or croak("$type must be a (subclass of) SeeAlso::Identifier");
48             }
49             ## use critic
50              
51 6         35 return $self;
52             }
53              
54              
55             sub create {
56 10     10 1 1105 my ($self, $value) = @_;
57              
58             # optional pre-parsing
59 10 100       41 $value = $self->{parse}->($value) if $self->{parse};
60              
61             # use the first type that successfully parses the value
62 10         31 foreach my $type (@{$self->{type}}) {
  10         29  
63 12         58 my $id = $type->new( $value );
64 12 100       89 return $id if $id;
65             }
66              
67             # if none of the types creates a non-empty identifier, use the first type
68 3         14 return $self->{type}->[0]->new( $value );
69             }
70              
71              
72             sub makeclass {
73 2     2 1 6 my (%params) = @_;
74              
75 2         4 my $type = $params{'type'}; # required
76 2         3 my $parse = $params{'parse'};
77 2         3 my $canonical = $params{'canonical'};
78 2         3 my $hash = $params{'hash'};
79 2         5 my $cmp = $params{'cmp'};
80              
81 2         6 my @out = "{\n package $type;";
82 2         5 push @out, ' require SeeAlso::Identifier; use Data::Dumper;';
83 2         2 push @out, ' our @ISA = qw(SeeAlso::Identifier);';
84 2 50       6 if ($parse) {
85 2         3 push @out, ' sub parse {';
86 2         3 push @out, ' my $value = $parse->( shift );';
87 2         3 push @out, ' return defined $value ? "$value" : "";';
88 2         4 push @out, ' }';
89             }
90              
91 2 50       9 push @out, 'sub canonical { my $s = $canonical->($_[0]->value); defined $s ? "$s" : ""; }'
92             if $canonical;
93              
94 2 50       6 push @out, 'sub hash { my $s = $hash->($_[0]->value); defined $s ? "$s" : ""; }'
95             if $hash;
96              
97             # TODO: cmp
98              
99 2         2 push @out, '1; };';
100 2         21 my $out = join("\n",@out);
101              
102             ## no critic
103             # print $out;# if $print;
104 1 0   1   7 { no warnings; eval $out; }
  1 50   1   2  
  1 0   1   104  
  1 50   0   5  
  1 50   2   2  
  1 50   0   212  
  1     1   4  
  1     3   2  
  1     1   225  
  2         4  
  2         155  
  0         0  
  0         0  
  2         6  
  2         54  
  0         0  
  0         0  
  1         4  
  1         35  
  3         7  
  3         87  
  1         4  
  1         37  
105 2 50       7 carp $@ if $@;
106             ## use critic
107              
108 2         9 return $type;
109             }
110              
111             1;
112              
113             __END__