File Coverage

blib/lib/RPC/ExtDirect/Config.pm
Criterion Covered Total %
statement 52 72 72.2
branch 5 16 31.2
condition 3 9 33.3
subroutine 14 20 70.0
pod 9 9 100.0
total 83 126 65.8


line stmt bran cond sub pod time code
1             package RPC::ExtDirect::Config;
2              
3 30     30   36125 use strict;
  30         37  
  30         2231  
4 30     30   89 use warnings;
  30         28  
  30         644  
5 30     30   142 no warnings 'uninitialized'; ## no critic
  30         616  
  30         706  
6              
7 30     30   86 use Carp;
  30         25  
  30         1374  
8              
9 30     30   11121 use RPC::ExtDirect::Util::Accessor;
  30         58  
  30         813  
10 30     30   9995 use RPC::ExtDirect::Util qw/ parse_global_flags /;
  30         45  
  30         27060  
11              
12             ### PUBLIC CLASS METHOD (CONSTRUCTOR) ###
13             #
14             # Create a new Config instance
15             #
16              
17             sub new {
18 162     162 1 61618 my $class = shift;
19            
20 162         183 my %arg;
21            
22 162 50 33     678 if ( @_ == 1 and 'HASH' eq ref $_[0] ) {
    50          
    0          
23 0         0 %arg = %{ $_[0] };
  0         0  
24             }
25             elsif ( @_ % 2 == 0 ) {
26 162         306 %arg = @_;
27             }
28             elsif ( @_ != 0 ) {
29 0         0 croak "Odd number of arguments in RPC::ExtDirect::Config->new()";
30             }
31            
32 162         270 my $self = bless {}, $class;
33            
34 162         304 $self->_init();
35 162         410 $self->set_options(%arg);
36            
37 162         377 return $self;
38             }
39              
40             ### PUBLIC INSTANCE METHOD (CONSTRUCTOR) ###
41             #
42             # Create a new Config instance from existing one (clone it)
43             # We're only doing shallow copying here.
44             #
45              
46             sub clone {
47 2     2 1 10 my ($self) = @_;
48            
49 2         10 my $clone = bless {}, ref $self;
50            
51 2         37 @$clone{ keys %$self } = values %$self;
52            
53 2         11 return $clone;
54             }
55              
56             ### PUBLIC INSTANCE METHOD ###
57             #
58             # Re-parse the global vars
59             #
60              
61             sub read_global_vars {
62 4     4 1 7 my ($self) = @_;
63            
64 4         12 $self->_parse_global_vars();
65            
66 4         8 return $self;
67             }
68              
69             ### PUBLIC INSTANCE METHOD ###
70             #
71             # Add specified accessors to the Config instance class
72             #
73              
74             sub add_accessors {
75 1     1 1 9 my ($self, %arg) = @_;
76            
77 1   33     15 RPC::ExtDirect::Util::Accessor->mk_accessors(
78             class => ref $self || $self, # Class method, too
79             ignore => 1,
80             %arg,
81             );
82            
83 1         2 return $self;
84             }
85              
86             ### PUBLIC INSTANCE METHOD ###
87             #
88             # Set the options in bulk by calling relevant setters
89             #
90              
91             sub set_options {
92 163     163 1 144 my $self = shift;
93            
94 163         2846 my $debug = $self->debug;
95            
96 163 50 33     626 my %options = @_ == 1 && 'HASH' eq ref($_[0]) ? %{ $_[0] } : @_;
  0         0  
97            
98 163         382 while ( my ($option, $value) = each %options ) {
99            
100             # We may as well be passed some options that we don't support;
101             # that may happen by accident, or the options hash may be passed
102             # on from unknown upper level. This does not represent a problem
103             # per se, so rather than bomb out with a cryptic error if a setter
104             # happens not to be defined, we warn in debug and silently ignore
105             # such occurences when not debugging.
106 115 50       353 if ( $self->can($option) ) {
    0          
107 115         1995 $self->$option($value);
108             }
109             elsif ( $debug ) {
110 0         0 warn ref($self)." instance was passed a config option $option ".
111             "for which there is no setter. A mistake?";
112             }
113             }
114            
115 163         492 return $self;
116             }
117              
118             #
119             # Note to self: the four deprecated methods below are *intentionally*
120             # left verbose and not collapsed to some helper sub.
121             #
122              
123             ### PUBLIC CLASS METHOD ###
124             #
125             # Return the default router path; provided for compatibility with 2.x
126             #
127             # DEPRECATED. Use `router_path` method on a Config instance instead.
128             #
129              
130             sub get_router_path {
131 0     0 1 0 warn __PACKAGE__."->get_router_path class method is deprecated; " .
132             "use router_path instance method instead";
133            
134 0         0 return __PACKAGE__->new->router_path;
135             }
136              
137             ### PUBLIC CLASS METHOD ###
138             #
139             # Return the default poll path; provided for compatibility with 2.x
140             #
141             # DEPRECATED. Use `poll_path` method on a Config instance instead.
142             #
143              
144             sub get_poll_path {
145 0     0 1 0 warn __PACKAGE__."->get_poll_path class method is deprecated; " .
146             "use poll_path instance method instead";
147            
148 0         0 return __PACKAGE__->new->poll_path;
149             }
150              
151             ### PUBLIC CLASS METHOD ###
152             #
153             # Return the default remoting variable name; provided for
154             # compatibility with 2.x
155             #
156             # DEPRECATED. Use `remoting_var` method on a Config instance instead.
157             #
158              
159             sub get_remoting_var {
160 0     0 1 0 warn __PACKAGE__."->get_remoting_var class method is deprecated; " .
161             "use remoting_var instance method instead";
162              
163 0         0 return __PACKAGE__->new->remoting_var;
164             }
165              
166             ### PUBLIC CLASS METHOD ###
167             #
168             # Return the default polling variable name; provided for
169             # compatibility with 2.x
170             #
171             # DEPRECATED. Use `polling_var` method on a Config instance instead.
172             #
173              
174             sub get_polling_var {
175 0     0 1 0 warn __PACKAGE__."->get_polling_var class method is deprecated; " .
176             "use polling_var instance method instead";
177            
178 0         0 return __PACKAGE__->new->polling_var;
179             }
180              
181             ############## PRIVATE METHODS BELOW ##############
182              
183             #
184             # This humongous hashref holds definitions for all fields,
185             # accessors, default values and global variables involved
186             # with config objects.
187             # It's just easier to keep all this stuff in one place
188             # and pluck the pieces needed for various purposes.
189             #
190             my $DEFINITIONS = [{
191             accessor => 'api_action_class',
192             default => 'RPC::ExtDirect::API::Action',
193             }, {
194             accessor => 'api_method_class',
195             default => 'RPC::ExtDirect::API::Method',
196             }, {
197             accessor => 'api_hook_class',
198             default => 'RPC::ExtDirect::API::Hook',
199             }, {
200             accessor => 'api_full_action_names',
201             default => !1,
202             }, {
203             accessor => 'debug',
204             default => !1,
205             }, {
206             package => 'RPC::ExtDirect::API',
207             var => 'DEBUG',
208             type => 'scalar',
209             setter => 'debug_api',
210             fallback => 'debug',
211             }, {
212             package => 'RPC::ExtDirect::EventProvider',
213             var => 'DEBUG',
214             type => 'scalar',
215             setter => 'debug_eventprovider',
216             fallback => 'debug',
217             }, {
218             package => 'RPC::ExtDirect::Serialize',
219             var => 'DEBUG',
220             type => 'scalar',
221             setter => 'debug_serialize',
222             fallback => 'debug',
223             }, {
224             package => 'RPC::ExtDirect::Deserialize',
225             var => 'DEBUG',
226             type => 'scalar',
227             setter => 'debug_deserialize',
228             fallback => 'debug',
229             }, {
230             package => 'RPC::ExtDirect::Request',
231             var => 'DEBUG',
232             type => 'scalar',
233             setter => 'debug_request',
234             fallback => 'debug',
235             }, {
236             package => 'RPC::ExtDirect::Router',
237             var => 'DEBUG',
238             type => 'scalar',
239             setter => 'debug_router',
240             fallback => 'debug',
241             }, {
242             accessor => 'exception_class',
243             default => 'RPC::ExtDirect::Exception',
244             }, {
245             package => 'RPC::ExtDirect::Serialize',
246             var => 'EXCEPTION_CLASS',
247             type => 'scalar',
248             setter => 'exception_class_serialize',
249             fallback => 'exception_class',
250             }, {
251             package => 'RPC::ExtDirect::Deserialize',
252             var => 'EXCEPTION_CLASS',
253             type => 'scalar',
254             setter => 'exception_class_deserialize',
255             fallback => 'exception_class',
256             }, {
257             package => 'RPC::ExtDirect::Request',
258             var => 'EXCEPTION_CLASS',
259             type => 'scalar',
260             setter => 'exception_class_request',
261             fallback => 'exception_class',
262             }, {
263             accessor => 'request_class',
264             default => 'RPC::ExtDirect::Request',
265             }, {
266             package => 'RPC::ExtDirect::Deserialize',
267             var => 'REQUEST_CLASS',
268             type => 'scalar',
269             setter => 'request_class_deserialize',
270             fallback => 'request_class',
271             }, {
272             # This is a special case - can be overridden
273             # but doesn't fall back to request_class
274             accessor => 'request_class_eventprovider',
275             default => 'RPC::ExtDirect::Request::PollHandler',
276             }, {
277             accessor => 'serializer_class',
278             default => 'RPC::ExtDirect::Serializer',
279             }, {
280             setter => 'serializer_class_api',
281             fallback => 'serializer_class',
282             }, {
283             package => 'RPC::ExtDirect::Router',
284             var => 'SERIALIZER_CLASS',
285             type => 'scalar',
286             setter => 'serializer_class_router',
287             fallback => 'serializer_class',
288             }, {
289             package => 'RPC::ExtDirect::EventProvider',
290             var => 'SERIALIZER_CLASS',
291             type => 'scalar',
292             setter => 'serializer_class_eventprovider',
293             fallback => 'serializer_class',
294             }, {
295             accessor => 'deserializer_class',
296             default => 'RPC::ExtDirect::Serializer',
297             }, {
298             package => 'RPC::ExtDirect::Router',
299             var => 'DESERIALIZER_CLASS',
300             type => 'scalar',
301             setter => 'deserializer_class_router',
302             fallback => 'deserializer_class',
303             }, {
304             accessor => 'json_options',
305             }, {
306             setter => 'json_options_serialize',
307             fallback => 'json_options',
308             }, {
309             package => 'RPC::ExtDirect::Deserialize',
310             var => 'JSON_OPTIONS',
311             type => 'hash',
312             setter => 'json_options_deserialize',
313             fallback => 'json_options',
314             }, {
315             accessor => 'router_class',
316             default => 'RPC::ExtDirect::Router',
317             }, {
318             accessor => 'timeout'
319             }, {
320             accessor => 'max_retries'
321             }, {
322             accessor => 'eventprovider_class',
323             default => 'RPC::ExtDirect::EventProvider',
324             }, {
325             accessor => 'verbose_exceptions',
326             default => !1, # In accordance with Ext.Direct spec
327             }, {
328             accessor => 'api_path',
329             default => '/extdirectapi',
330             }, {
331             accessor => 'router_path',
332             default => '/extdirectrouter',
333             }, {
334             accessor => 'poll_path',
335             default => '/extdirectevents',
336             }, {
337             accessor => 'remoting_var',
338             default => 'Ext.app.REMOTING_API',
339             }, {
340             accessor => 'polling_var',
341             default => 'Ext.app.POLLING_API',
342             }, {
343             accessor => 'namespace',
344             }, {
345             accessor => 'auto_connect',
346             default => !1,
347             }, {
348             accessor => 'no_polling',
349             default => !1,
350             }];
351              
352             my @simple_accessors = map { $_->{accessor} }
353             grep { $_->{accessor} }
354             @$DEFINITIONS;
355              
356             my @complex_accessors = grep { $_->{fallback} } @$DEFINITIONS;
357              
358             # Package globals are handled separately, this is only for
359             # accessors with default values
360             my %field_defaults = map { $_->{accessor} => $_ }
361             grep { defined $_->{default} and !exists $_->{var} }
362             @$DEFINITIONS;
363              
364             my @package_globals = grep { $_->{var} } @$DEFINITIONS;
365              
366             ### PRIVATE INSTANCE METHOD ###
367             #
368             # Return the default value for a field.
369             #
370              
371             sub _get_default {
372 0     0   0 my ($self, $field) = @_;
373            
374 0         0 my $def = $field_defaults{$field};
375            
376 0 0       0 return $def ? $def->{default} : undef;
377             }
378              
379             ### PRIVATE INSTANCE METHOD ###
380             #
381             # Return true if the current field value is the default.
382             #
383              
384             sub _is_default {
385 0     0   0 my ($self, $field) = @_;
386            
387 0         0 my $value = $self->$field();
388 0         0 my $default = $self->_get_default($field);
389            
390 0         0 return $value eq $default;
391             }
392              
393             ### PRIVATE INSTANCE METHOD ###
394             #
395             # Parse global package variables
396             #
397              
398             sub _parse_global_vars {
399 166     166   142 my ($self) = @_;
400            
401 166         508 parse_global_flags(\@package_globals, $self);
402             }
403              
404             ### PRIVATE INSTANCE METHOD ###
405             #
406             # Parse global package variables and apply default values
407             #
408              
409             sub _init {
410 162     162   178 my ($self) = @_;
411            
412 162         265 $self->_parse_global_vars();
413            
414             # Apply the defaults
415 162         517 while ( my ($field, $def) = each %field_defaults ) {
416 3240         2941 my $default = $def->{default};
417            
418 3240 50       58457 $self->$field($default) unless defined $self->$field();
419             }
420             }
421              
422             ### PRIVATE PACKAGE SUBROUTINE ###
423             #
424             # Export a deep copy of the definitions for testing
425             #
426              
427             sub _get_definitions {
428 1     1   7 return [ map { +{ %$_ } } @$DEFINITIONS ];
  40         86  
429             }
430              
431             RPC::ExtDirect::Util::Accessor::mk_accessors(
432             simple => \@simple_accessors,
433             complex => \@complex_accessors,
434             overwrite => 1,
435             );
436              
437             1;