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