Commit | Line | Data |
b8a92065 |
1 | package stemmaweb::Controller::Microservice; |
2 | use Moose; |
3 | use namespace::autoclean; |
4 | use JSON; |
13c54385 |
5 | use TryCatch; |
b8a92065 |
6 | use Text::Tradition; |
13c54385 |
7 | #use Text::Tradition::Error; |
b8a92065 |
8 | use Text::Tradition::Stemma; |
9 | use Text::Tradition::StemmaUtil qw/ character_input phylip_pars newick_to_svg /; |
10 | |
11 | BEGIN { extends 'Catalyst::Controller' } |
12 | |
13 | =head1 NAME |
14 | |
15 | stemmaweb::Controller::Microservice - Controller for stemmaweb standalone |
16 | components |
17 | |
18 | =head1 DESCRIPTION |
19 | |
20 | This package contains the pieces of web functionality relating to text tradition |
21 | objects that are useful outside the framework of this application. |
22 | |
23 | =head1 COLLATION PARSING INPUT |
24 | |
25 | Each URL call which operates on a provided collation is called by POST with the |
26 | following form parameters in the body: |
27 | |
28 | =over 4 |
29 | |
30 | =item * type - Can be one of CollateX, CSV, JSON, nCritic, TEI, Tabular. |
31 | |
32 | =item * data - The collation data itself. |
33 | |
34 | =back |
35 | |
36 | =head1 COLLATION URLs |
37 | |
38 | =head2 renderSVG |
39 | |
40 | POST microservice/renderSVG |
41 | |
42 | Parse the passed collation data and return an SVG of the collated text. |
43 | |
44 | =cut |
45 | |
46 | # Utility function to render SVG from a collation in some recognized format. |
47 | sub renderSVG :Local :Args(0) { |
48 | my( $self, $c ) = @_; |
49 | my $tradition = _parse_to_tradition( $c->request ); |
13c54385 |
50 | try { |
51 | $c->stash->{'result'} = $tradition->collation->as_svg; |
52 | $c->forward('View::SVG'); |
53 | } catch( Text::Tradition::Error $e ) { |
54 | $c->detach( 'error', [ $e ] ); |
55 | } |
b8a92065 |
56 | } |
57 | |
58 | =head1 STEMMA / DISTANCE TREE URLs |
59 | |
60 | =head2 stemma_svg |
61 | |
62 | POST microservice/stemma_svg |
63 | |
64 | Parameter: dot => a string containing the dot description of the stemma. |
65 | |
66 | =cut |
67 | |
68 | sub stemma_svg :Local :Args(0) { |
69 | my( $self, $c ) = @_; |
70 | my $t = Text::Tradition->new(); |
13c54385 |
71 | my $stemma; |
72 | try { |
73 | $stemma = $t->add_stemma( 'dot' => $c->req->param('dot') ); |
74 | } catch( Text::Tradition::Error $e ) { |
75 | $c->detach( 'error', [ $e ] ); |
76 | } |
b8a92065 |
77 | $c->stash->{'result'} = $stemma->as_svg; |
78 | $c->forward('View::SVG'); |
79 | } |
80 | |
81 | =head2 character_matrix |
82 | |
83 | POST microservice/character_matrix |
84 | |
85 | Given an alignment table in JSON form, in the parameter 'alignment', returns a |
86 | character matrix suitable for input to Phylip PARS. |
87 | |
88 | =cut |
89 | |
90 | sub character_matrix :Local :Args(0) { |
91 | my( $self, $c ) = @_; |
92 | my $json = $c->request->params->{'alignment'}; |
93 | $c->log->debug( $json ); |
94 | my $table = from_json( $json ); |
95 | my $matrix = character_input( $table ); |
96 | $c->stash->{'result'} = { 'matrix' => $matrix }; |
97 | $c->forward( 'View::JSON' ); |
98 | } |
99 | |
100 | =head2 run_pars |
101 | |
102 | POST microservice/run_pars |
103 | |
104 | Runs Phylip PARS on the provided alignment, and returns the result. Parameters include: |
105 | |
106 | =over 4 |
107 | |
108 | =item * alignment - A JSON alignment table, as produced by CollateX |
109 | |
110 | =item * matrix - A character matrix suitable for Phylip. |
111 | |
112 | =item * format - The format in which to return the results. Default is 'newick'; also allowed is 'svg'. |
113 | |
114 | =back |
115 | |
116 | Exactly one of 'alignment' or 'matrix' must be specified. |
117 | |
118 | =cut |
119 | |
120 | sub run_pars :Local :Args(0) { |
121 | my( $self, $c ) = @_; |
b8a92065 |
122 | my $matrix; |
123 | if( $c->request->param('matrix') ) { |
124 | $matrix = $c->request->param('matrix'); |
125 | } elsif( $c->request->param('alignment') ) { |
126 | # Make the matrix from the alignment |
127 | my $table = from_json( $c->request->param('alignment') ); |
128 | $matrix = character_input( $table ); |
129 | } else { |
13c54385 |
130 | $c->detach( 'error', [ "Must pass either an alignment or a matrix" ] ); |
b8a92065 |
131 | } |
132 | |
133 | # Got the matrix, so try to run pars. |
13c54385 |
134 | my $output; |
135 | try { |
136 | $output = phylip_pars( $matrix ); |
137 | } catch( Text::Tradition::Error $e ) { |
138 | $c->detach( 'error', [ $e ] ); |
b8a92065 |
139 | } |
140 | |
141 | # Did we want newick or a graph? |
13c54385 |
142 | my $view = 'View::JSON'; |
143 | my $format = 'newick'; |
144 | $format = $c->request->param('format') if $c->request->param('format'); |
145 | if( $format eq 'svg' ) { |
146 | # Do something |
147 | try { |
b8a92065 |
148 | $c->stash->{'result'} = newick_to_svg( $output ); |
149 | $view = 'View::SVG'; |
13c54385 |
150 | } catch( Text::Tradition::Error $e ) { |
151 | $c->detach( 'error', [ $e ] ); |
b8a92065 |
152 | } |
13c54385 |
153 | } elsif( $format ne 'newick' ) { |
154 | $c->detach( 'error', [ "Requested output format $format unknown" ] ); |
155 | } else { |
156 | $c->stash->{'result'} = { 'tree' => $output }; |
b8a92065 |
157 | } |
158 | |
b8a92065 |
159 | $c->forward( $view ); |
160 | } |
161 | |
162 | |
163 | =head1 OPENSOCIAL URLs |
164 | |
165 | =head2 view_table |
166 | |
167 | Simple gadget to return the analysis table for the stexaminer |
168 | |
169 | =cut |
170 | |
171 | sub view_table :Local :Args(0) { |
172 | my( $self, $c ) = @_; |
173 | my $m = $c->model('Directory'); |
174 | my $id = $c->request->params->{'textid'}; |
175 | my $t = run_analysis( $m->tradition( $id ), $m->stemma( $id ) ); |
176 | $c->stash->{variants} = $t->{'variants'}; |
177 | $c->stash->{template} = 'table_gadget.tt'; |
178 | } |
179 | |
180 | =head2 view_stemma_svg |
181 | |
182 | Simple gadget to return the SVG for a given stemma |
183 | |
184 | =cut |
185 | |
186 | sub view_svg :Local :Args(0) { |
187 | my( $self, $c ) = @_; |
188 | my $m = $c->model('Directory'); |
189 | my $stemma = $m->tradition( $c->request->params->{'textid'} )->stemma; |
190 | if( $stemma ) { |
191 | $c->stash->{svg} = $stemma->as_svg; |
192 | } |
193 | $c->stash->{template} = 'stemma_gadget.tt'; |
194 | } |
195 | |
13c54385 |
196 | =head2 error |
197 | |
198 | Default response when actions generate Text::Tradition::Error exceptions |
199 | |
200 | =cut |
201 | |
202 | sub error :Private { |
203 | my( $self, $c, $error ) = @_; |
204 | my $errstr = $error; |
205 | if( ref( $error ) eq 'Text::Tradition::Error' ) { |
206 | $errstr = $error->ident . ": " . $error->message; |
207 | } |
208 | $c->response->code( 500 ); |
209 | $c->stash->{'error'} = $errstr; |
210 | $c->stash->{'template'} = 'error.tt'; |
211 | } |
212 | |
b8a92065 |
213 | =head2 default |
214 | |
215 | Standard 404 error page |
216 | |
217 | =cut |
218 | |
219 | sub default :Path { |
220 | my ( $self, $c ) = @_; |
221 | $c->response->body( 'Page not found' ); |
222 | $c->response->status(404); |
223 | } |
224 | |
225 | ## Internal utility function |
226 | |
227 | sub _parse_to_tradition { |
228 | my $req = shift; |
229 | my $type = $req->body_params->{'type'}; |
230 | my $name = $req->param('name') || 'Collation graph'; |
231 | my $data = $req->body_params->{'data'}; |
232 | my $opts = { |
233 | 'name' => $name, |
234 | 'input' => $type, |
235 | 'string' => $data |
236 | }; |
237 | $opts->{'sep_char'} = ',' if $type eq 'CSV'; |
238 | $opts->{'sep_char'} = "\t" if $type eq 'TabSep'; |
239 | return Text::Tradition->new( $opts ); |
240 | } |
241 | |
b8a92065 |
242 | |
243 | =head1 AUTHOR |
244 | |
245 | Tara L Andrews |
246 | |
247 | =head1 LICENSE |
248 | |
249 | This library is free software. You can redistribute it and/or modify |
250 | it under the same terms as Perl itself. |
251 | |
252 | =cut |
253 | |
254 | __PACKAGE__->meta->make_immutable; |
255 | |
256 | 1; |