File Coverage

blib/lib/RPC/ExtDirect/Config.pm
Criterion Covered Total %
statement 54 74 72.9
branch 5 16 31.2
condition 3 9 33.3
subroutine 14 20 70.0
pod 9 9 100.0
total 85 128 66.4


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