File Coverage

blib/lib/JSORB/Dispatcher/Path.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             package JSORB::Dispatcher::Path;
2 4     4   10732 use Moose;
  0            
  0            
3              
4             use Try::Tiny;
5             use Path::Router;
6              
7             our $VERSION = '0.04';
8             our $AUTHORITY = 'cpan:STEVAN';
9              
10             with 'MooseX::Traits';
11              
12             has 'namespace' => (
13             is => 'ro',
14             isa => 'JSORB::Namespace',
15             trigger => sub {
16             my $self = shift;
17             $self->_clear_router if $self->_has_router;
18             # the router will get
19             # initialized the next
20             # time it is needed
21             }
22             );
23              
24             has 'router' => (
25             is => 'ro',
26             isa => 'Path::Router',
27             lazy => 1,
28             builder => '_build_router',
29             clearer => '_clear_router',
30             predicate => '_has_router',
31             );
32              
33             sub handler {
34             my ($self, $call, @args) = @_;
35             (blessed $call && $call->isa('JSON::RPC::Common::Procedure::Call'))
36             || confess "You must pass a JSON::RPC::Common::Procedure::Call to the handler, not $call";
37              
38             my $procedure = $self->get_procedure_from_call($call);
39              
40             return $self->throw_error(
41             $call, "Could not find method " . $call->method . " in " . $self->namespace->name
42             ) unless defined $procedure;
43              
44             try {
45             $call->return_result(
46             $self->call_procedure(
47             $procedure,
48             $call,
49             @args
50             )
51             );
52             } catch {
53             $self->throw_error($call, $_);
54             };
55             }
56              
57             sub get_procedure_from_call {
58             my ($self, $call) = @_;
59             my $match = $self->router->match($call->method);
60             return unless $match;
61             return $match->target;
62             }
63              
64             sub call_procedure {
65             my ($self, $procedure, $call, @args) = @_;
66             $procedure->call( $self->assemble_params_list( $call, @args ) );
67             }
68              
69             sub assemble_params_list {
70             my ($self, $call, @args) = @_;
71             return $call->params_list;
72             }
73              
74             sub throw_error {
75             my ($self, $call, $message) = @_;
76             return $call->return_error(
77             message => $message,
78             code => 1,
79             );
80             }
81              
82             # ........
83              
84             sub _build_router {
85             my $self = shift;
86             my $router = Path::Router->new;
87             $self->_process_elements(
88             $router,
89             '/',
90             $self->namespace
91             );
92             $router;
93             }
94              
95             sub _process_elements {
96             my ($self, $router, $base_url, $namespace) = @_;
97              
98             $base_url .= lc($namespace->name) . '/';
99              
100             foreach my $element (@{ $namespace->elements }) {
101             $self->_process_interface($router, $base_url, $element)
102             if $element->isa('JSORB::Interface');
103             $self->_process_elements($router, $base_url, $element);
104             }
105             }
106              
107             sub _process_interface {
108             my ($self, $router, $base_url, $interface) = @_;
109              
110             $base_url .= lc($interface->name) . '/';
111              
112             # NOTE:
113             # perhaps I want to actually do:
114             # $router->add_route(
115             # ($base_url . ':method'),
116             # target => $interface,
117             # );
118             # instead so that the method becomes
119             # a param and then the interface
120             # itself is the target ... which
121             # means I can then hand off the
122             # rest of the dispatching to the
123             # interface .. hmmm
124              
125             foreach my $procedure (@{ $interface->procedures }) {
126             $router->add_route(
127             ($base_url . lc($procedure->name)),
128             target => $procedure
129             );
130             }
131             }
132              
133             __PACKAGE__->meta->make_immutable;
134              
135             no Moose; 1;
136              
137             __END__
138              
139             =pod
140              
141             =head1 NAME
142              
143             JSORB::Dispatcher::Path - Simple path based dispatcher
144              
145             =head1 DESCRIPTION
146              
147             This module will dispatch RPC methods/procedures that are in a
148             path-like format, such as:
149              
150             { method : 'math/simple/add', params : [ 2, 2 ] }
151              
152             This will look for the C<add> procedure in the C<Math::Simple>
153             namespace.
154              
155             =head1 BUGS
156              
157             All complex software has bugs lurking in it, and this module is no
158             exception. If you find a bug please either email me, or add the bug
159             to cpan-RT.
160              
161             =head1 AUTHOR
162              
163             Stevan Little E<lt>stevan.little@iinteractive.comE<gt>
164              
165             =head1 COPYRIGHT AND LICENSE
166              
167             Copyright 2008-2010 Infinity Interactive, Inc.
168              
169             L<http://www.iinteractive.com>
170              
171             This library is free software; you can redistribute it and/or modify
172             it under the same terms as Perl itself.
173              
174             =cut