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