File Coverage

lib/XML/Schema/Factory.pm
Criterion Covered Total %
statement 52 59 88.1
branch 18 32 56.2
condition 4 6 66.6
subroutine 9 10 90.0
pod 1 6 16.6
total 84 113 74.3


line stmt bran cond sub pod time code
1             #============================================================= -*-perl-*-
2             #
3             # XML::Schema::Factory
4             #
5             # DESCRIPTION
6             # Factory module for managing (e.g. loading and instantiating) other
7             # modules in the XML::Schema set.
8             #
9             # AUTHOR
10             # Andy Wardley
11             #
12             # COPYRIGHT
13             # Copyright (C) 2001 Canon Research Centre Europe Ltd.
14             # All Rights Reserved.
15             #
16             # This module is free software; you can redistribute it and/or
17             # modify it under the same terms as Perl itself.
18             #
19             # REVISION
20             # $Id: Factory.pm,v 1.2 2001/12/20 13:26:27 abw Exp $
21             #
22             #========================================================================
23              
24             package XML::Schema::Factory;
25              
26 28     28   142 use strict;
  28         43  
  28         1287  
27 28     28   128 use vars qw( $VERSION $AUTOLOAD $DEBUG $ERROR $ETYPE $MODULES );
  28         47  
  28         2318  
28 28     28   143 use base qw( XML::Schema::Base );
  28         41  
  28         27499  
29              
30             $VERSION = sprintf("%d.%02d", q$Revision: 1.2 $ =~ /(\d+)\.(\d+)/);
31             $DEBUG = 0 unless defined $DEBUG;
32             $ETYPE = 'Factory';
33             $ERROR = '';
34             $MODULES = {
35             # root schema object
36             schema => 'XML::Schema',
37              
38             # core XML::Schema::* objects
39             attribute => 'XML::Schema::Attribute',
40             attribute_group => 'XML::Schema::Attribute::Group',
41             complex => 'XML::Schema::Type::Complex',
42             content => 'XML::Schema::Content',
43             element => 'XML::Schema::Element',
44             exception => 'XML::Schema::Exception',
45             instance => 'XML::Schema::Instance',
46             model => 'XML::Schema::Model',
47             parser => 'XML::Schema::Parser',
48             particle => 'XML::Schema::Particle',
49             wildcard => 'XML::Schema::Wildcard',
50             simple => 'XML::Schema::Type::Simple',
51             # particle objects
52             element_particle => 'XML::Schema::Particle::Element',
53             sequence_particle => 'XML::Schema::Particle::Sequence',
54             choice_particle => 'XML::Schema::Particle::Choice',
55             model_particle => 'XML::Schema::Particle::Model',
56             # parser handlers
57             schema_handler => 'XML::Schema::Handler::Schema',
58             simple_handler => 'XML::Schema::Handler::Simple',
59             complex_handler => 'XML::Schema::Handler::Complex',
60             };
61              
62              
63             #------------------------------------------------------------------------
64             # init(\%config)
65             #
66             # Initialiser method called by base class new() constructor.
67             #------------------------------------------------------------------------
68              
69             sub init {
70 0     0 1 0 my ($self, $config) = @_;
71 0         0 my $class = ref $self;
72 0         0 bless { %$MODULES, %$config }, $class;
73             }
74              
75              
76             #------------------------------------------------------------------------
77             # create($module_type)
78             #
79             # Look up module name for a given type in $MODULES hash if called as a
80             # class method, or $self hash if called as an object method. Load the
81             # module via load() method and then instantiate an object via new()
82             #------------------------------------------------------------------------
83              
84             sub create {
85 208     208 0 329 my $self = shift;
86 208         250 my $type = shift;
87              
88 208 50       431 $self->DEBUG($self->ID, "->create('$type')\n")
89             if $DEBUG;
90              
91 208         249 my $module;
92 208 50       376 if (ref $self) {
93 0         0 $module = $self->{ $type };
94             }
95             else {
96 208         404 $module = $MODULES->{ $type };
97             }
98 208 50       392 return $self->error("module not recognised: '$type'")
99             unless $module;
100              
101 208 100       517 return undef unless $self->load($module);
102 207   66     1134 return $module->new(@_)
103             || $self->error($module->error());
104             }
105              
106              
107             #------------------------------------------------------------------------
108             # adopt($module_type, $object, \@args)
109             #
110             # Look up module name for a given type in $MODULES hash if called as a
111             # class method, or $self hash if called as an object method. Load the
112             # module via load() method, rebless $object into the new module class
113             # then call its new init() method passing a reference to an optional
114             # hash reference of configuration options.
115             #------------------------------------------------------------------------
116              
117             sub adopt {
118 22     22 0 42 my ($self, $type, $object, $config) = @_;
119              
120 22 50       51 $self->DEBUG($self->ID, "->adopt('$type', $object)\n")
121             if $DEBUG;
122              
123 22         29 my $module;
124 22 50       52 if (ref $self) {
125 0         0 $module = $self->{ $type };
126             }
127             else {
128 22         55 $module = $MODULES->{ $type };
129             }
130 22 50       50 return $self->error("module not recognised: '$type'")
131             unless $module;
132              
133 22 50       59 return undef unless $self->load($module);
134 22         66 bless $object, $module;
135              
136 22   66     81 return $object->init($config)
137             || $self->error($object->error());
138             }
139              
140              
141             #------------------------------------------------------------------------
142             # load($module)
143             #
144             # Load a module via require(). Any occurences of '::' in the module name
145             # are be converted to '/' and '.pm' is appended. Returns 1 on success
146             # or undef on error. Use $class->error() to examine the error string.
147             #------------------------------------------------------------------------
148              
149             sub load {
150 284     284 0 619 my ($self, $module) = @_;
151 284         1137 $module =~ s[::][/]g;
152 284         455 $module .= '.pm';
153 284 50       589 $self->DEBUG($self->ID, "->require('$module')\n")
154             if $DEBUG;
155 284         407 eval {
156 284         21418 require $module;
157             };
158 284 100       1179 return $@ ? $self->error("failed to load $module: $@") : 1;
159             }
160              
161              
162             #------------------------------------------------------------------------
163             # isa($type, $object)
164             #
165             # Look up class name for a given type in $MODULES hash if called as a
166             # class method, or $self hash if called as an object method, and check
167             # that $object is of, or derived from that type.
168             #------------------------------------------------------------------------
169              
170             sub isa {
171 125     125 0 233 my ($self, $type, $object) = @_;
172              
173 125 50       265 $self->DEBUG($self->ID, "->isa($type => ", $object->ID, ")\n")
174             if $DEBUG;
175              
176 125         147 my $class;
177 125 50       210 if (ref $self) {
178 0         0 $class = $self->{ $type };
179             }
180             else {
181 125         266 $class = $MODULES->{ $type };
182             }
183 125 50       249 return $self->error("type not recognised: '$type'")
184             unless $class;
185              
186 125         732 return UNIVERSAL::isa($object, $class);
187             }
188              
189              
190             #------------------------------------------------------------------------
191             # module($name)
192             #
193             # Look up module name for a given type in $MODULES hash if called as a
194             # class method, or $self hash if called as an object method.
195             #------------------------------------------------------------------------
196              
197             sub module {
198 154     154 0 289 my ($self, $name) = @_;
199 154         148 my $module;
200              
201 154 50       275 if (ref $self) {
202 0         0 $module = $self->{ $name };
203             }
204             else {
205 154         308 $module = $MODULES->{ $name };
206             }
207 154 50       322 return $self->error("module not recognised: '$name'")
208             unless $module;
209              
210 154         497 return $module;
211             }
212              
213              
214             #------------------------------------------------------------------------
215             # AUTOLOAD
216             #
217             # Map method calls of the form $modules->parser(....) to
218             # $modules->create('parser', ...)
219             #------------------------------------------------------------------------
220              
221             sub AUTOLOAD {
222 11     11   109 my $self = shift;
223 11         21 my $item = $AUTOLOAD;
224 11         183 $item =~ s/.*:://;
225 11 50       41 return if $item eq 'DESTROY';
226 11         41 $self->create($item, @_);
227             }
228            
229             1;
230