File Coverage

lib/XML/Schema/Type/Complex.pm
Criterion Covered Total %
statement 77 93 82.8
branch 14 24 58.3
condition 17 29 58.6
subroutine 16 24 66.6
pod 1 17 5.8
total 125 187 66.8


line stmt bran cond sub pod time code
1             #============================================================= -*-perl-*-
2             #
3             # XML::Schema::Type::Complex
4             #
5             # DESCRIPTION
6             # Module implementing an object class for representing complex XML
7             # Schema datatypes. Complex types are those that contain other
8             # elements and/or carry attributes.
9             #
10             # AUTHOR
11             # Andy Wardley
12             #
13             # COPYRIGHT
14             # Copyright (C) 2001 Canon Research Centre Europe Ltd.
15             # All Rights Reserved.
16             #
17             # This module is free software; you can redistribute it and/or
18             # modify it under the same terms as Perl itself.
19             #
20             # REVISION
21             # $Id: Complex.pm,v 1.2 2001/12/20 13:26:28 abw Exp $
22             #
23             #========================================================================
24              
25             package XML::Schema::Type::Complex;
26              
27 28     28   157 use strict;
  28         56  
  28         1221  
28 28     28   146 use XML::Schema;
  28         56  
  28         562  
29 28     28   147 use XML::Schema::Type;
  28         50  
  28         524  
30 28     28   152 use XML::Schema::Scope;
  28         49  
  28         561  
31 28     28   148 use XML::Schema::Scheduler;
  28         55  
  28         1020  
32 28     28   145 use base qw( XML::Schema::Scope XML::Schema::Type XML::Schema::Scheduler );
  28         50  
  28         4277  
33 28     28   153 use vars qw( $VERSION $DEBUG $ERROR @OPTIONAL @SCHEDULES );
  28         55  
  28         36993  
34              
35             $VERSION = sprintf("%d.%02d", q$Revision: 1.2 $ =~ /(\d+)\.(\d+)/);
36             $DEBUG = 0 unless defined $DEBUG;
37             $ERROR = '';
38              
39             @OPTIONAL = qw( annotation mixed scope );
40             @SCHEDULES = qw( start_element end_element start_child end_child text );
41              
42              
43             sub init {
44 28     28 1 66 my ($self, $config) = @_;
45              
46 28 50       164 $self->SUPER::init($config)
47             || return;
48              
49             # set by base class (Scope) constructor
50 28         67 my $factory = $self->{ _FACTORY };
51              
52             # tell attribute group to delegate to $self for types
53 28   66     128 $config->{ scope } ||= $self;
54 28   100     95 $config->{ name } ||= 'anon';
55 28         61 $config->{ name } = '_complex_type_$config->{ name }';
56              
57             # create attribute group to manage attributes
58 28   50     167 $self->{ attributes } = $factory->create( attribute_group => $config )
59             || return $self->error($factory->error());
60              
61             # initialise scheduler
62 28 50       205 $self->init_scheduler($config)
63             || return;
64              
65             # required ??
66 28         83 $self->{ simple } = 0;
67 28         76 $self->{ complex } = 1;
68              
69 28         61 my $content;
70 28 100       101 if ($content = $config->{ content }) {
71 1 50       7 if ($factory->isa( content => $content )) {
    50          
72 0         0 return $content;
73             }
74             elsif ($content = $factory->create( content => $content )) {
75 1         3 $self->{ content } = $content;
76             }
77             else {
78 0         0 return $self->error($factory->error());
79             }
80             }
81             else {
82             # TODO: this is laborious, need to find a better way
83 27   50     162 my $ctype = $factory->module('content')
84             || return $self->error($factory->error());
85 27 50       127 $factory->load($ctype)
86             || return $self->error($factory->error());
87              
88 27   50     124 my $ptype = $factory->module('particle')
89             || return $self->error($factory->error());
90 27 50       101 $factory->load($ptype)
91             || return $self->error($factory->error());
92              
93 27         190 my $regex = join('|', $ctype->args(), $ptype->models());
94 27 100       1000 if (grep(/^$regex$/, keys %$config)) {
95             # create content model
96 24   100     131 $self->{ content } = $factory->create( content => $config )
97             || return $self->error($factory->error());
98             }
99             }
100              
101 26         221 return $self;
102             }
103              
104              
105             #------------------------------------------------------------------------
106             # attribute( ... )
107             #
108             # Accessor method to fetch and update attributes. Delegates to
109             # equivalent method of internal $self->{ attributes } attribute group
110             # object.
111             #------------------------------------------------------------------------
112              
113             sub attribute {
114 18     18 0 36 my $self = shift;
115 18         33 my $agroup = $self->{ attributes };
116              
117 18   66     67 return $agroup->attribute(@_)
118             || $self->error($agroup->error());
119             }
120              
121              
122             #------------------------------------------------------------------------
123             # attributes( )
124             #
125             # Returns reference to the internal XML::Schema::Attribute::Group object
126             # which manages attributes.
127             #------------------------------------------------------------------------
128              
129             sub attributes {
130 1     1 0 3 my $self = shift;
131 1         4 return $self->{ attributes };
132             }
133              
134              
135             #------------------------------------------------------------------------
136             # content()
137             #
138             # Return a reference to the current content model object. Creates a
139             # new content object via the current factory if called with
140             # arguments.
141             #------------------------------------------------------------------------
142              
143             sub content {
144 26     26 0 43 my $self = shift;
145 26 100       155 return $self->{ content } unless @_;
146              
147             my $factory = $self->{ _FACTORY }
148 2   50     10 || return $self->error("no factory defined");
149              
150 2   50     11 $self->{ content } = $factory->create( content => @_ )
151             || return $self->error($factory->error());
152             }
153              
154              
155             #------------------------------------------------------------------------
156             # sequence( @items )
157             #
158             # Used to create a sequence content model, e.g.
159             #
160             #
161             #
162             #
163             #
164             #
165             #
166             #------------------------------------------------------------------------
167              
168             sub sequence {
169 1     1 0 10 my $self = shift;
170 1         3 my $content = { };
171              
172 1         6 while (! ref $_[0]) {
173 2         4 my $key = shift;
174 2         8 $content->{ $key } = shift;
175             }
176 1         4 $content->{ sequence } = [ @_ ];
177              
178 1 50       15 $self->TRACE("content => ", $content) if $DEBUG;
179 1         9 $self->content($content);
180             }
181              
182              
183              
184             #------------------------------------------------------------------------
185             # choice( @items )
186             #
187             # Used to create a choice content model, e.g.
188             #
189             #
190             #
191             #
192             #
193             #
194             #
195             #------------------------------------------------------------------------
196              
197             sub choice {
198 1     1 0 12 my $self = shift;
199 1         2 my $content = { };
200              
201 1         6 while (! ref $_[0]) {
202 2         4 my $key = shift;
203 2         9 $content->{ $key } = shift;
204             }
205 1         4 $content->{ choice } = [ @_ ];
206              
207 1 50       13 $self->TRACE("choice => ", $content) if $DEBUG;
208 1         4 $self->content($content);
209             }
210              
211              
212             #------------------------------------------------------------------------
213             # simpleContent( @items )
214             #
215             # Used to create a simpleContent model for the complexType, e.g.
216             #
217             # 3.14
218             #
219             #
220             #
221             # <---- simpleContent()
222             #
223             #
224             #
225             #
226             #
227             #------------------------------------------------------------------------
228              
229             sub simpleContent {
230 0     0 0 0 my $self = shift;
231 0         0 $self->throw('simpleContent() not yet implemented');
232             }
233              
234              
235             #------------------------------------------------------------------------
236             # complexContent( @items )
237             #
238             # Used to create a complexContent model for the complexType, e.g.
239             #
240             #
241             #
242             #
243             #
244             # <---- complexContent()
245             #
246             #
247             #
248             #
249             #
250             #
251             #------------------------------------------------------------------------
252              
253             sub complexContent {
254 0     0 0 0 my $self = shift;
255 0         0 $self->throw('complexContent() not yet implemented');
256             }
257              
258              
259             #========================================================================
260             # misc accessor methods
261             #========================================================================
262              
263             sub annotation {
264 0     0 0 0 my $self = shift;
265 0 0       0 return @_ ? ($self->{ annotation } = shift) : $self->{ annotation };
266             }
267              
268             sub simple {
269 0     0 0 0 return 0;
270             }
271              
272             sub complex {
273 0     0 0 0 return 1;
274             }
275              
276             sub mixed {
277 17     17 0 29 my $self = shift;
278             my $content = $self->{ content }
279 17   100     51 || return $self->error("no content defined");
280 16         36 return $content->mixed(@_);
281             }
282              
283             sub empty {
284 1     1 0 3 my $self = shift;
285             my $content = $self->{ content }
286 1   50     13 || return $self->error("no content defined");
287 1         6 return $content->empty(@_);
288             }
289              
290             sub element_only {
291 5     5 0 6 my $self = shift;
292             my $content = $self->{ content }
293 5   50     14 || return $self->error("no content defined");
294 5         20 return $content->element_only(@_);
295             }
296              
297             #========================================================================
298             # parser methods
299             #========================================================================
300              
301             #------------------------------------------------------------------------
302             # handler($instance, $element)
303             #
304             # Calls the complex_handler($self, $element) method on the $instance
305             # reference.
306             #
307             # TODO: we could optimise away this chain of method calls by having the
308             # instance Start() method unwrap the calls.
309             #------------------------------------------------------------------------
310              
311             sub handler {
312 0     0 0   my ($self, $instance, $element) = @_;
313 0   0       return $instance->complex_handler($self, $element)
314             || $self->error($instance->error());
315             }
316              
317             sub present {
318 0     0 0   my ($self, $view) = @_;
319 0           $view->view( complex => $self );
320             }
321              
322             sub ID {
323 0     0 0   my $self = shift;
324 0           return 'ComplexType';
325             }
326              
327             1;
328              
329             __END__