File Coverage

blib/lib/VoiceXML/Client/Item.pm
Criterion Covered Total %
statement 123 148 83.1
branch 31 48 64.5
condition 8 31 25.8
subroutine 23 28 82.1
pod 2 21 9.5
total 187 276 67.7


line stmt bran cond sub pod time code
1             package VoiceXML::Client::Item;
2              
3 3     3   19 use VoiceXML::Client;
  3         6  
  3         71  
4 3     3   17 use VoiceXML::Client::Item::Factory;
  3         8  
  3         69  
5 3     3   1622 use VoiceXML::Client::Flow;
  3         8  
  3         85  
6 3     3   17 use VoiceXML::Client::Util;
  3         6  
  3         64  
7              
8 3     3   13 use Hash::Util qw(lock_hash);
  3         6  
  3         12  
9              
10 3     3   129 use strict;
  3         5  
  3         86  
11              
12 3         4811 use vars qw{
13             $VERSION
14 3     3   27 };
  3         5  
15              
16              
17             $VERSION = $VoiceXML::Client::VERSION;
18              
19              
20             =head1 COPYRIGHT AND LICENSE
21              
22            
23             Copyright (C) 2007,2008 by Pat Deegan.
24             All rights reserved
25             http://voicexml.psychogenic.com
26              
27             This library is released under the terms of the GNU GPL version 3, making it available only for
28             free programs ("free" here being used in the sense of the GPL, see http://www.gnu.org for more details).
29             Anyone wishing to use this library within a proprietary or otherwise non-GPLed program MUST contact psychogenic.com to
30             acquire a distinct license for their application. This approach encourages the use of free software
31             while allowing for proprietary solutions that support further development.
32              
33              
34             This file is part of VoiceXML::Client.
35              
36            
37            
38             VoiceXML::Client is free software: you can redistribute it and/or modify
39             it under the terms of the GNU General Public License as published by
40             the Free Software Foundation, either version 3 of the License, or
41             (at your option) any later version.
42              
43             VoiceXML::Client is distributed in the hope that it will be useful,
44             but WITHOUT ANY WARRANTY; without even the implied warranty of
45             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
46             GNU General Public License for more details.
47              
48             You should have received a copy of the GNU General Public License
49             along with VoiceXML::Client. If not, see .
50              
51              
52             =cut
53              
54             =head2 new XMLELEMENTOBJ PARENTOBJ [PARAMS]
55              
56              
57             Creates a new instance of the appropriate class. Parses all children elements and then calls init, passing the
58             optional PARAMS href (init() exists to be overridden in subclasses, where required.).
59              
60              
61             =cut
62              
63             sub new {
64 59     59 1 83 my $class = shift;
65 59   50     131 my $xmlElement = shift || return VoiceXML::Client::Util::error("VoiceXML::Client::Item::Factory::new() Must pass an XML element to new.");
66 59         94 my $parent = shift;
67 59         57 my $params = shift;
68            
69            
70 59         91 my $self = {};
71            
72 59   33     289 bless $self, ref $class || $class;
73            
74 59   33     379 $self->{'type'} = ref $class || $class;
75 59         92 $self->{'XMLElement'} = $xmlElement;
76 59         92 $self->{'parent'} = $parent;
77            
78            
79 59 50 33     188 if ($params && ref $params && exists $params->{'context'})
      33        
80             {
81 0         0 $self->{'_context'} = $params->{'context'};
82             } else {
83 59         186 $self->{'_context'} = undef;
84             }
85            
86 59         92 $self->{'currentchild'} = 0;
87            
88 59         245 my $retVal = $self->init($params);
89 59 50       131 return $retVal unless ($retVal); # if init didn't go well, we say so here and skip the kids...
90            
91             # create children lastly
92 59         282 $self->createChildren();
93            
94 59         204 return $self;
95             }
96              
97             sub getType {
98 9     9 0 15 my $self = shift;
99            
100 9         33 return $self->{'type'};
101             }
102              
103            
104              
105             sub createChildren {
106 59     59 0 79 my $self = shift;
107 59         71 my $params = shift;
108            
109 59         170 my $children = $self->{'XMLElement'}->getAllChildren();
110            
111 59         1197 my $numChildren = scalar @{$children};
  59         93  
112              
113            
114 59         157 $self->{'children'} = [];
115 59         71 my $itemCount = 0;
116 59         142 for (my $i=0; $i<$numChildren; $i++)
117             {
118 50         147 my $name = $children->[$i]->name();
119            
120 50 100       368 if ($name eq 'var')
121             {
122             # Variable declaration - ensure we have an interpreter context in this scope
123            
124 3         11 my $varName = $children->[$i]->attribute('name');
125 3 50       38 if (defined $varName)
126             {
127 3         10 $self->{'declaredVariables'}->{$varName}++;
128             }
129 3 100       29 $self->createContext() unless ($self->{'_context'});
130             }
131            
132 50         203 my $newItem = VoiceXML::Client::Item::Factory->newItem($name, $children->[$i], $self);
133            
134 50 100       110 unless (defined $newItem)
135             {
136 3         14 VoiceXML::Client::Util::log_msg("VoiceXML::Client::Item::init() Don't yet know how to deal with '$name' elements - skipping");
137 3         10 next;
138             }
139            
140 47 50       83 if ($newItem)
141             {
142 47         171 $self->{'children'}->[$itemCount++] = $newItem;
143             } else {
144 0 0       0 VoiceXML::Client::Util::log_msg("VoiceXML::Client::Item::init() skipping creation of '$name' element")
145             if ($VoiceXML::Client::Debug);
146             }
147              
148            
149             }
150            
151 59         104 return $itemCount;
152             }
153              
154            
155            
156              
157             sub getChildrenImmediate {
158 0     0 0 0 my $self = shift;
159            
160 0         0 return $self->{'children'};
161             }
162              
163             sub getChildrenRecursive {
164 0     0 0 0 my $self = shift;
165            
166 0         0 my @results;
167            
168 0         0 foreach my $child (@{$self->{'children'}})
  0         0  
169             {
170 0         0 push @results, $child;
171 0         0 my $grandChildren = $child->getChildrenRecursive();
172            
173 0         0 push @results, @{$grandChildren};
  0         0  
174             }
175            
176 0         0 return \@results;
177             }
178              
179              
180             sub getAttribute {
181 0     0 0 0 my $self = shift;
182 0   0     0 my $attrname = shift || return undef;
183            
184 0         0 return $self->{'XMLElement'}->attribute($attrname);
185             }
186            
187              
188             =head2 init [PARAMS]
189              
190             Called by new(), override in derived classes to implement subclass-specific initialisation.
191              
192             =cut
193              
194             sub init {
195 10     10 1 16 my $self = shift;
196 10         15 my $params = shift;
197            
198 10         20 return 1;
199             }
200              
201              
202             sub getRuntime {
203 2     2 0 4 my $self = shift;
204            
205 2 100       13 if (defined $self->{'_runtime'})
206             {
207 1         6 return $self->{'_runtime'};
208             } else {
209 1 50       33 return $self->{'parent'}->getRuntime()
210             if ($self->{'parent'});
211             }
212              
213 0         0 return undef;
214             }
215              
216             sub getContext {
217 0     0 0 0 my $self = shift;
218            
219 0 0 0     0 return $self->{'_context'}
      0        
220             if (exists $self->{'_context'} && defined $self->{'_context'} && $self->{'_context'});
221            
222 0 0 0     0 return $self->{'parent'}->getContext if (defined $self->{'parent'} && $self->{'parent'});
223            
224 0         0 return undef;
225             }
226              
227             sub createContext {
228 1     1 0 3 my $self = shift;
229            
230 1   33     15 my $runtime = $self->getRuntime() || VoiceXML::Client::Util::error("VoiceXML::Client::Item::createContext() Could not find runtime!");
231            
232 1         5 $self->{'_context'} = $runtime->create_context();
233            
234 1         3 return $self->{'_context'};
235            
236             }
237              
238              
239             sub abortProcessing {
240 16     16 0 19 my $self = shift;
241 16         17 my $setTo = shift; # optional
242            
243 16 50       57 if (defined $setTo)
244             {
245 16         28 $self->{'_abortprocessing'} = $setTo;
246             }
247            
248 16         23 return $self->{'_abortprocessing'};
249             }
250              
251             sub shouldContinueProcessing {
252 45     45 0 53 my $self = shift;
253            
254 45 50       98 return 0 if ($self->{'_abortprocessing'}); # this item think I should continue...
255            
256 45 100       145 return $self->{'parent'}->shouldContinueProcessing() if ($self->{'parent'});
257            
258 19         92 return 1;
259             }
260              
261             sub reset {
262 16     16 0 21 my $self = shift;
263              
264 16 50       31 VoiceXML::Client::Util::log_msg("item reset() called") if ($VoiceXML::Client::Debug > 3);
265            
266 16         63 $self->abortProcessing(0);
267 16         18 foreach my $child (@{$self->{'children'}})
  16         33  
268             {
269 13         50 $child->reset();
270             }
271            
272 16         63 $self->resetChildPositionIndex();
273             }
274              
275              
276             sub resetChildPositionIndex {
277 19     19 0 23 my $self = shift;
278            
279 19 100       17 if (scalar @{$self->{'children'}})
  19         55  
280             {
281 3         12 for (my $i=0; $i <= $self->{'currentchild'}; $i++)
282             {
283            
284 3 50       11 if ($self->{'children'}->[$i])
285             {
286 3         10 $self->{'children'}->[$i]->resetChildPositionIndex();
287             }
288             }
289            
290             }
291            
292 19         25 $self->{'currentchild'} = 0;
293            
294 19         47 return ;
295             }
296              
297             sub proceedToNextChild {
298 14     14 0 35 my $self = shift;
299            
300 14         40 return $self->{'currentchild'}++;
301            
302             }
303            
304             sub getCurrentChild {
305 37     37 0 44 my $self = shift;
306            
307 37 100       50 return undef unless ($self->{'currentchild'} < scalar @{$self->{'children'}});
  37         147  
308            
309 19         126 return $self->{'children'}->[$self->{'currentchild'}];
310             }
311              
312              
313             sub execute {
314 6     6 0 11 my $self = shift;
315 6         8 my $handle = shift;
316 6         6 my $optParms = shift;
317            
318            
319 6         25 return $self->executeChildren($handle, $optParms);
320             }
321              
322             sub executeChildren {
323 24     24 0 36 my $self = shift;
324 24         29 my $handle = shift;
325 24         27 my $optParms = shift;
326            
327 24   66     94 while ((my $curChild = $self->getCurrentChild()) && $self->shouldContinueProcessing())
328             {
329            
330 19         84 my $rv = $curChild->execute($handle, $optParms) ;
331            
332            
333 19 100       68 return $rv if ($rv != $VoiceXML::Client::Flow::Directive{'CONTINUE'});
334            
335 13         41 $self->proceedToNextChild();
336             }
337            
338 18         55 return $VoiceXML::Client::Flow::Directive{'CONTINUE'};
339            
340             }
341              
342              
343              
344              
345              
346             sub getParentVXMLDocument {
347 145     145 0 170 my $self = shift;
348            
349 145 100       614 if ($self->can('isaVXMLDocument'))
350             {
351 53         233 return $self;
352             }
353            
354 92 50       197 if ($self->{'parent'})
355             {
356 92         222 return $self->{'parent'}->getParentVXMLDocument();
357             }
358            
359 0         0 return undef;
360             }
361              
362             sub getParentForm {
363 6     6 0 17 my $self = shift;
364            
365 6 100       36 if ($self->can('isaFormItem'))
366             {
367 3         11 return $self;
368             }
369            
370 3 50       11 if ($self->{'parent'})
371             {
372 3         25 return $self->{'parent'}->getParentForm();
373             }
374            
375 0           return undef;
376             }
377              
378             sub toString {
379 0     0 0   my $self = shift;
380            
381 0           return $self->{'XMLElement'}->toString();
382             }
383              
384             1;