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