r13919@rob-kinyons-powerbook58: rob | 2006-06-02 10:30:39 -0400
[p5sagit/Excel-Template.git] / lib / Excel / Template / Factory.pm
1 package Excel::Template::Factory;
2
3 use strict;
4
5 my %Manifest = (
6
7 # These are the instantiable nodes
8     'IF'        => 'Excel::Template::Container::Conditional',
9     'LOOP'      => 'Excel::Template::Container::Loop',
10     'ROW'       => 'Excel::Template::Container::Row',
11     'SCOPE'     => 'Excel::Template::Container::Scope',
12     'WORKBOOK'  => 'Excel::Template::Container::Workbook',
13     'WORKSHEET' => 'Excel::Template::Container::Worksheet',
14
15     'BACKREF'   => 'Excel::Template::Element::Backref',
16     'CELL'      => 'Excel::Template::Element::Cell',
17     'FORMULA'   => 'Excel::Template::Element::Formula',
18     'IMAGE'     => 'Excel::Template::Element::Image',
19     'RANGE'     => 'Excel::Template::Element::Range',
20     'VAR'       => 'Excel::Template::Element::Var',
21
22     'FORMAT'    => 'Excel::Template::Container::Format',
23
24 # These are all the Format short-cut objects
25 # They are also instantiable
26     'BOLD'      => 'Excel::Template::Container::Bold',
27     'HIDDEN'    => 'Excel::Template::Container::Hidden',
28     'ITALIC'    => 'Excel::Template::Container::Italic',
29     'LOCKED'    => 'Excel::Template::Container::Locked',
30     'OUTLINE'   => 'Excel::Template::Container::Outline',
31     'SHADOW'    => 'Excel::Template::Container::Shadow',
32     'STRIKEOUT' => 'Excel::Template::Container::Strikeout',
33
34     'KEEP_LEADING_ZEROS' => 'Excel::Template::Container::KeepLeadingZeros',
35
36 # These are the helper objects
37 # They are also in here to make E::T::Factory::isa() work.
38     'CONTEXT'    => 'Excel::Template::Context',
39     'ITERATOR'   => 'Excel::Template::Iterator',
40     'TEXTOBJECT' => 'Excel::Template::TextObject',
41
42     'CONTAINER'  => 'Excel::Template::Container',
43     'ELEMENT'    => 'Excel::Template::Element',
44
45     'BASE'       => 'Excel::Template::Base',
46 );
47
48 my %isBuildable = map { $_ => ~~1 } qw(
49     WORKBOOK WORKSHEET
50     FORMAT BOLD HIDDEN ITALIC LOCKED OUTLINE SHADOW STRIKEOUT
51     IF ROW LOOP SCOPE KEEP_LEADING_ZEROS
52     CELL FORMULA IMAGE
53     VAR BACKREF RANGE
54 );
55
56 {
57     my %Loaded;
58     sub _load_class
59     {
60         my $self = shift;
61         my ($class) = @_;
62
63         unless ( exists $Loaded{$class} )
64         {
65             (my $filename = $class) =~ s!::!/!g;
66             eval {
67                 require "$filename.pm";
68             }; if ($@) {
69                 die "Cannot find or compile PM file for '$class' ($filename)\n";
70             }
71
72             $Loaded{$class} = ~~1;
73         }
74
75         return ~~1;
76     }
77 }
78
79 {
80     my @param_names = qw(name class isa);
81     sub register
82     {
83         my $self = shift;
84         my %params = @_;
85
86         for (@param_names)
87         {
88             unless ($params{$_})
89             {
90                 warn "$_ was not supplied to register()\n" if $^W;
91                 return;
92             }
93         }
94
95         my $name = uc $params{name};
96         if (exists $Manifest{$name})
97         {
98             warn "$params{name} already exists in the manifest.\n" if $^W;
99             return;
100         }
101
102         my $isa = uc $params{isa};
103         unless (exists $Manifest{$isa})
104         {
105             warn "$params{isa} does not exist in the manifest.\n" if $^W;
106             return;
107         }
108
109         {
110             no strict 'refs';
111             unshift @{"$params{class}::ISA"}, $Manifest{$isa};
112         }
113
114         $self->_load_class( $Manifest{$isa} );
115         $self->_load_class( $params{class} );
116
117         $Manifest{$name} = $params{class};
118         $isBuildable{$name} = ~~1;
119
120         return ~~1;
121     }
122 }
123
124 sub _create
125 {
126     my $self = shift;
127     my $name = uc shift;
128
129     return unless exists $Manifest{$name};
130
131     $self->_load_class( $Manifest{$name} );
132  
133     return $Manifest{$name}->new(@_);
134 }
135
136 sub _create_node
137 {
138     my $self = shift;
139     my $name = uc shift;
140
141     return unless exists $isBuildable{$name};
142
143     return $self->_create($name, @_);
144 }
145
146 sub isa
147 {
148     return unless @_ >= 2;
149     exists $Manifest{uc $_[1]}
150         ? UNIVERSAL::isa($_[0], $Manifest{uc $_[1]})
151         : UNIVERSAL::isa(@_)
152 }
153
154 sub is_embedded
155 {
156     return unless @_ >= 1;
157
158     isa( $_[0], $_ ) && return ~~1 for qw( VAR BACKREF RANGE );
159     return;
160 }
161
162 1;
163 __END__
164
165 =head1 NAME
166
167 Excel::Template::Factory
168
169 =head1 PURPOSE
170
171 To provide a common way to instantiate Excel::Template nodes
172
173 =head1 USAGE
174
175 =head2 register()
176
177 Use this to register your own nodes.
178
179 Example forthcoming.
180
181 =head1 METHODS
182
183 =head2 isa
184
185 This is a customized isa() wrapper for syntactic sugar
186
187 =head2 is_embedded
188
189 =head1 AUTHOR
190
191 Rob Kinyon (rob.kinyon@gmail.com)
192
193 =head1 SEE ALSO
194
195 =cut