File: Factory.pm

package info (click to toggle)
libclass-mixinfactory-perl 0.92-5
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 172 kB
  • sloc: perl: 135; makefile: 2
file content (138 lines) | stat: -rw-r--r-- 3,673 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package Class::MixinFactory::Factory;

$VERSION = 0.91;

########################################################################

use strict;
use Carp ();

########################################################################

use Class::MixinFactory::InsideOutAttr qw(base_class mixin_prefix mixed_prefix);

use Class::MixinFactory::NEXT;
sub next_dispatch_class { 'Class::MixinFactory::NEXT' }

########################################################################

sub new { 
  my $sym;
  my $self = bless \$sym, shift;
  while ( my $method = shift @_ ) {
    $self->$method( shift );
  }
  $self;
}

########################################################################

sub class {
  my $factory = shift;
  my @mixins = ( @_ == 1 and ref($_[0]) ) ? @{ $_[0] } : @_;
  
  my $base_class = $factory->base_class();
  my $mixin_prefix = $factory->mixin_prefix() || $base_class || '';
  my $mixed_prefix = $factory->mixed_prefix() || ( $base_class ? $base_class : ref($factory) || $factory ) . "::AUTO";

  my @classes = map { ( $_ =~ /::/ ) ? $_ : $mixin_prefix ? $mixin_prefix . '::' . $_ : $_ } @mixins;

  my $label = join '_', map { s/^\Q$mixin_prefix\E:://; s/:://g; $_ } map "$_", @classes;
  
  my $new_class = $mixed_prefix . "::" . ( $label || "Base" );
  
  return $new_class if do { no strict 'refs'; @{ "$new_class\::ISA" } };
  
  my @isa = ( @classes, $base_class, $factory->next_dispatch_class );
  
  foreach my $package ( @classes ) {
    next if do { no strict 'refs'; scalar keys %{ $package . '::' } };
    my $filename = "$package.pm";
    $filename =~ s{::}{/}g;
    # warn "require $filename";
    require $filename;
  }

  { no strict; @{ "$new_class\::ISA" } = @isa; }
  
  $new_class;
}

########################################################################

1;

__END__

=head1 NAME

Class::MixinFactory::Factory - Class Factory with Selection of Mixins

=head1 SYNOPSIS

  use Class::MixinFactory::Factory;

  my $factory = Class::MixinFactory::Factory->new();
  
  $factory->base_class( "MyClass");

  $factory->mixin_prefix( "MyMixins" );
  $factory->mixed_prefix( "MyClasses" );

  my $class = $factory->class( @mixins );

=head1 DESCRIPTION

A mixin factory generates new classes at run-time which inherit from each of several classes.

=head1 PUBLIC METHODS

=over 4

=item new()

  $factory_class->new() : $factory
  $factory_class->new( %attributes ) : $factory

Create a new factory object. 

May be passed a hash of attributes, with the key matching one of the supported accessor methods named below and the value containing the value to assign.

=item base_class()

  $factory->base_class() : $package_name
  $factory->base_class( $package_name )

Required. Get or set the base class to be inherited from by all mixed classes.

=item mixin_prefix()

  $factory->mixin_prefix() : $package_name
  $factory->mixin_prefix( $package_name )

Optional. Get or set a prefix to be placed before all mixin class names that don't contain a double-colon. Defaults to the name of the base class. 

=item mixed_prefix()

  $factory->mixed_prefix() : $package_name
  $factory->mixed_prefix( $package_name )

Optional. Get or set a prefix to be placed before all generated class names. Defaults to the name of the base class or the factory class followed by "::AUTO"

=item class()

  $factory->class( @mixins ) : $package_name

Find or generate a class combining the requested mixin classes.

=back


=head1 SEE ALSO

For a facade interface that facilitates access to this functionality, see L<Class::MixinFactory>.

For distribution, installation, support, copyright and license 
information, see L<Class::MixinFactory::ReadMe>.

=cut