comparison Lib/IMPL/Web/Application/RestResource.pm @ 198:2ffe6f661605

Implemented IMPL::Web::Handler::RestController fixes in IMPL::Serialization completed IMPL::Web::Application::RestResource added IMPL::Web::Handler::JSONView added IMPL::Web::RestContract
author cin
date Fri, 20 Apr 2012 16:06:36 +0400
parents 6b1dda998839
children e743a8481327
comparison
equal deleted inserted replaced
197:6b1dda998839 198:2ffe6f661605
1 package IMPL::Web::Application::RestResource; 1 package IMPL::Web::Application::RestResource;
2 use strict; 2 use strict;
3 3
4 use IMPL::lang qw(:declare :constants); 4 use IMPL::lang qw(:declare :constants is);
5 use IMPL::Exception();
6
5 use IMPL::declare { 7 use IMPL::declare {
6 require => { 8 require => {
7 ForbiddenException => 'IMPL::Web::ForbiddenException' 9 ForbiddenException => 'IMPL::Web::ForbiddenException',
10 InvalidOpException => '-IMPL::InvalidOperationException',
11 ArgumentException => '-IMPL::InvalidArgumentException',
12 TTransform => '-IMPL::Transform'
8 }, 13 },
9 base => { 14 base => {
10 'IMPL::Object' => undef 15 'IMPL::Object' => undef,
16 'IMPL::Object::Autofill' => '@_'
11 } 17 }
12 }; 18 };
13 19
14 BEGIN { 20 BEGIN {
15 public property target => PROP_GET | PROP_OWNERSET; 21 public property target => PROP_GET | PROP_OWNERSET;
20 public property insert => PROP_GET | PROP_OWNERSET; 26 public property insert => PROP_GET | PROP_OWNERSET;
21 public property update => PROP_GET | PROP_OWNERSET; 27 public property update => PROP_GET | PROP_OWNERSET;
22 public property delete => PROP_GET | PROP_OWNERSET; 28 public property delete => PROP_GET | PROP_OWNERSET;
23 } 29 }
24 30
31 sub CTOR {
32 my ($this) = @_;
33
34 die ArgumentException->new("target") unless $this->target;
35 }
36
25 sub GetHttpImpl { 37 sub GetHttpImpl {
26 my($this,$method) = @_; 38 my($this,$method) = @_;
27 39
28 my %map = ( 40 my %map = (
29 GET => 'GetImpl', 41 GET => 'GetImpl',
34 46
35 return $map{$method}; 47 return $map{$method};
36 } 48 }
37 49
38 sub InvokeHttpMethod { 50 sub InvokeHttpMethod {
39 my ($this,$method,$child,$action) = @_; 51 my ($this,$method,$childId,$action) = @_;
40 52
41 my $impl = $this->GetHttpImpl($method) || 'FallbackImpl'; 53 my $impl = $this->GetHttpImpl($method) || 'HttpFallbackImpl';
42 54
43 return $this->$impl($child,$action); 55 return $this->$impl($childId,$action);
44 } 56 }
45 57
46 sub GetImpl { 58 sub GetImpl {
47 my ($this,$id,$action) = @_; 59 my ($this,$id,$action) = @_;
48 60
49 my $rx; 61 my $rx;
50 my $method; 62 my $method;
51 if (length $id == 0) { 63 if (length $id == 0) {
52 $method = $this->list; 64 $method = $this->list or die ForbiddenException->new();
53 } elsif ($method = $this->methods->{$id}) { 65 } elsif ($this->methods and $method = $this->methods->{$id}) {
54 if (ref $method eq 'HASH' and not $method->{allowGet}) { 66 if (ref $method eq 'HASH' and not $method->{allowGet}) {
55 die ForbiddenException->new(); 67 die ForbiddenException->new();
56 } 68 }
57 } elsif($rx = $this->childRegex and $id =~ m/$rx/ ) { 69 } elsif($rx = $this->childRegex and $id =~ m/$rx/ ) {
58 $method = $this->fetch or die ForbiddenException->new(); 70 $method = $this->fetch or die ForbiddenException->new();
60 $method = { 72 $method = {
61 method => $method, 73 method => $method,
62 parameters => [qw(id)] 74 parameters => [qw(id)]
63 } unless ref $method; 75 } unless ref $method;
64 76
65 } else {
66 die ForbiddenException->new();
67 } 77 }
68 78
69 return $this->InvokeMember($method,$id,$action); 79 return $this->InvokeMember($method,$id,$action);
70 } 80 }
71 81
129 die ForbiddenException->new(); 139 die ForbiddenException->new();
130 } 140 }
131 141
132 sub InvokeMember { 142 sub InvokeMember {
133 my ($this,$method,$id,$action) = @_; 143 my ($this,$method,$id,$action) = @_;
134 } 144
145 #normalize method info
146 if (not ref $method) {
147 $method = {
148 method => $method
149 };
150 }
151
152 if (ref $method eq 'HASH') {
153 my @args;
154 my $member = $method->{method} or die InvalidOpException->new("A member name isn't specified");
155 if (my $params = $method->{parameters}) {
156 if (ref $params eq 'HASH') {
157 @args = map {
158 $_,
159 $this->MakeParameter($params->{$_},$id,$action)
160 } keys %$params;
161 } elsif (ref $params eq 'ARRAY') {
162 @args = map $this->MakeParameter($_,$id,$action), @$params;
163 } else {
164 @args = ($this->MakeParameter($params,$id,$action));
165 }
166 }
167 $this->target->$member(@args);
168 } else {
169 die InvalidOpException->new("Unsupported type of the method information", ref $method);
170 }
171 }
172
173 sub MakeParameter {
174 my ($this,$param,$id,$action) = @_;
175
176 if ($param) {
177 if (is $param, TTransform ) {
178 return $param->Transform($this,$action->query);
179 } elsif ($param and not ref $param) {
180 my %std = (
181 id => $id,
182 action => $action,
183 query => $action->query
184 );
185
186 return $std{$param} || $action->query->param($param);
187 }
188 } else {
189 return undef;
190 }
191 }
192
193
135 194
136 195
137 1; 196 1;
138 197
139 __END__ 198 __END__
193 252
194 my $cds = TRes->new( 253 my $cds = TRes->new(
195 DataContext->Default, 254 DataContext->Default,
196 { 255 {
197 methods => { 256 methods => {
198 get => { 257 history => {
199 258 allowGet => 1,
259 method => 'GetHistory',
260 parameters => [qw(from to)]
200 }, 261 },
201 post => {
202
203 }
204 } 262 }
205 get => 'search', 263 list => 'search',
206 264 fetch => 'GetItemById'
207
208 } 265 }
209 ); 266 );
210 267
211 =end code 268 =end code
212 269
239 296
240 =head3 C<POST> 297 =head3 C<POST>
241 298
242 Добавляет новый дочерний ресурс в коллекцию. 299 Добавляет новый дочерний ресурс в коллекцию.
243 300
301 =head3 C<POST {method}>
302
303 Вызывает метод C<method>.
304
244 =head2 HTTP METHOD MAPPING 305 =head2 HTTP METHOD MAPPING
245 306
246 =head3 C<POST {method}> 307 =head3 C<POST {method}>
247 308
248 Вызывает метод C<method>, в отличии от C<GET> методы опубликованные через C<POST> могут вносить 309 Вызывает метод C<method>, в отличии от C<GET> методы опубликованные через C<POST> могут вносить
254 315
255 Объект (также может быть и класс), обеспечивающий функционал ресурса. 316 Объект (также может быть и класс), обеспечивающий функционал ресурса.
256 317
257 =head2 C<[get]methods> 318 =head2 C<[get]methods>
258 319
320 Содержит описания методов, которые будут публиковаться как дочерние ресурсы.
321
259 =head2 C<[get]childRegex> 322 =head2 C<[get]childRegex>
260 323
324 Содержит регулярное выражение для идентификаторов дочерних объектов. Если оно
325 не задано, то данный ресурс не является коллекцией.
326
261 =head2 C<[get]fetch> 327 =head2 C<[get]fetch>
262 328
329 Содержит описание метода для получения дочернего объекта. Если данный метод
330 отсутствует, то дочерние ресурсы не получится адресовать относительно данного.
331 По умолчанию получает идентификатор дочернего ресурса первым параметром.
332
263 =head2 C<[get]list> 333 =head2 C<[get]list>
264 334
335 Описание метода для получения списка дочерних объектов. По умолчанию не
336 получает параметров.
337
265 =head2 C<[get]insert> 338 =head2 C<[get]insert>
266 339
340 Описание метода для добавление дочернего ресурса. По умолчанию получает
341 объект C<CGI> описывабщий текущий запрос первым параметром.
342
267 =head2 C<[get]update> 343 =head2 C<[get]update>
268 344
345 Описание метода для обновления дочернего ресурса. По умолчанию получает
346 идентификатор дочернего ресурса и объект C<CGI> текущего запроса.
347
269 =head2 C<[get]delete> 348 =head2 C<[get]delete>
270 349
350 Описание метода для удаления дочернего ресурса. По умолчанию получает
351 идентификатор дочернего ресурса.
352
271 =head2 C<GetImpl($child,$action)> 353 =head2 C<GetImpl($child,$action)>
272 354
355 =over
356
357 =item C<$child>
358
359 Идентификатор дочернего ресутсра
360
361 =item C<$action>
362
363 Текущий запрос C<IMPL::Web::Application::Action>.
364
365 =back
366
367 Переадресует запрос нужному методу внутреннего объекта C<target> при
368 помощи C<InvokeMember>.
369
273 =head2 C<PutImpl($child,$action)> 370 =head2 C<PutImpl($child,$action)>
274 371
372 =over
373
374 =item C<$child>
375
376 Идентификатор дочернего ресутсра
377
378 =item C<$action>
379
380 Текущий запрос C<IMPL::Web::Application::Action>.
381
382 =back
383
384 Переадресует запрос нужному методу внутреннего объекта C<target> при
385 помощи C<InvokeMember>.
386
275 =head2 C<PostImpl($child,$action)> 387 =head2 C<PostImpl($child,$action)>
276 388
389 =over
390
391 =item C<$child>
392
393 Идентификатор дочернего ресутсра
394
395 =item C<$action>
396
397 Текущий запрос C<IMPL::Web::Application::Action>.
398
399 =back
400
401 Переадресует запрос нужному методу внутреннего объекта C<target> при
402 помощи C<InvokeMember>.
403
277 =head2 C<DeleteImpl($child,$action)> 404 =head2 C<DeleteImpl($child,$action)>
278 405
406 =over
407
408 =item C<$child>
409
410 Идентификатор дочернего ресутсра
411
412 =item C<$action>
413
414 Текущий запрос C<IMPL::Web::Application::Action>.
415
416 =back
417
418 Переадресует запрос нужному методу внутреннего объекта C<target> при
419 помощи C<InvokeMember>.
420
279 =head2 C<InvokeMember($memberInfo,$child,$action)> 421 =head2 C<InvokeMember($memberInfo,$child,$action)>
280 422
423 =over
424
425 =item C<$memberInfo>
426
427 Описание члена внутреннего объекта C<target>, который нужно вызвать.
428
429 =item C<$child>
430
431 Идентификатор дочернего ресутсра
432
433 =item C<$action>
434
435 Текущий запрос C<IMPL::Web::Application::Action>.
436
437 =back
438
439 Вызывает метод внутреннего объекта C<target>, предварительно подготовив
440 параметры на основе описания C<$memberInfo> и при помощи С<MakeParameter()>.
441
442 =head2 C<MakeParameter($paramDef,$child,$action)>
443
444 =over
445
446 =item C<$paramDef>
447
448 Описание параметра, может быть C<IMPL::Transform> или простая строка.
449
450 Если описание параметра - простая строка, то ее имя либо
451
452 =over
453
454 =item C<id>
455
456 Идентификатор дочернего ресурса
457
458 =item C<query>
459
460 Объект C<CGI> текущего запроса
461
462 =item C<action>
463
464 Текущий запрос C<IMPL::Web::Application::Action>
465
466 =item C<любое другое значение>
467
468 Интерпретируется как параметр текущего запроса.
469
470 =back
471
472 Если описание параметра - объект C<IMPL::Transform>, то будет выполнено это преобразование над C<CGI>
473 объектом текущего запроса C<< $paramDef->Transform($action->query) >>.
474
475 =back
476
281 =cut 477 =cut