Mercurial > pub > Impl
diff 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 |
line wrap: on
line diff
--- a/Lib/IMPL/Web/Application/RestResource.pm Thu Apr 19 02:10:02 2012 +0400 +++ b/Lib/IMPL/Web/Application/RestResource.pm Fri Apr 20 16:06:36 2012 +0400 @@ -1,13 +1,19 @@ package IMPL::Web::Application::RestResource; use strict; -use IMPL::lang qw(:declare :constants); +use IMPL::lang qw(:declare :constants is); +use IMPL::Exception(); + use IMPL::declare { require => { - ForbiddenException => 'IMPL::Web::ForbiddenException' + ForbiddenException => 'IMPL::Web::ForbiddenException', + InvalidOpException => '-IMPL::InvalidOperationException', + ArgumentException => '-IMPL::InvalidArgumentException', + TTransform => '-IMPL::Transform' }, base => { - 'IMPL::Object' => undef + 'IMPL::Object' => undef, + 'IMPL::Object::Autofill' => '@_' } }; @@ -22,6 +28,12 @@ public property delete => PROP_GET | PROP_OWNERSET; } +sub CTOR { + my ($this) = @_; + + die ArgumentException->new("target") unless $this->target; +} + sub GetHttpImpl { my($this,$method) = @_; @@ -36,11 +48,11 @@ } sub InvokeHttpMethod { - my ($this,$method,$child,$action) = @_; + my ($this,$method,$childId,$action) = @_; - my $impl = $this->GetHttpImpl($method) || 'FallbackImpl'; + my $impl = $this->GetHttpImpl($method) || 'HttpFallbackImpl'; - return $this->$impl($child,$action); + return $this->$impl($childId,$action); } sub GetImpl { @@ -49,8 +61,8 @@ my $rx; my $method; if (length $id == 0) { - $method = $this->list; - } elsif ($method = $this->methods->{$id}) { + $method = $this->list or die ForbiddenException->new(); + } elsif ($this->methods and $method = $this->methods->{$id}) { if (ref $method eq 'HASH' and not $method->{allowGet}) { die ForbiddenException->new(); } @@ -62,8 +74,6 @@ parameters => [qw(id)] } unless ref $method; - } else { - die ForbiddenException->new(); } return $this->InvokeMember($method,$id,$action); @@ -131,8 +141,57 @@ sub InvokeMember { my ($this,$method,$id,$action) = @_; + + #normalize method info + if (not ref $method) { + $method = { + method => $method + }; + } + + if (ref $method eq 'HASH') { + my @args; + my $member = $method->{method} or die InvalidOpException->new("A member name isn't specified"); + if (my $params = $method->{parameters}) { + if (ref $params eq 'HASH') { + @args = map { + $_, + $this->MakeParameter($params->{$_},$id,$action) + } keys %$params; + } elsif (ref $params eq 'ARRAY') { + @args = map $this->MakeParameter($_,$id,$action), @$params; + } else { + @args = ($this->MakeParameter($params,$id,$action)); + } + } + $this->target->$member(@args); + } else { + die InvalidOpException->new("Unsupported type of the method information", ref $method); + } } +sub MakeParameter { + my ($this,$param,$id,$action) = @_; + + if ($param) { + if (is $param, TTransform ) { + return $param->Transform($this,$action->query); + } elsif ($param and not ref $param) { + my %std = ( + id => $id, + action => $action, + query => $action->query + ); + + return $std{$param} || $action->query->param($param); + } + } else { + return undef; + } +} + + + 1; @@ -195,16 +254,14 @@ DataContext->Default, { methods => { - get => { - + history => { + allowGet => 1, + method => 'GetHistory', + parameters => [qw(from to)] }, - post => { - - } } - get => 'search', - - + list => 'search', + fetch => 'GetItemById' } ); @@ -241,6 +298,10 @@ Добавляет новый дочерний ресурс в коллекцию. +=head3 C<POST {method}> + +Вызывает метод C<method>. + =head2 HTTP METHOD MAPPING =head3 C<POST {method}> @@ -256,26 +317,161 @@ =head2 C<[get]methods> +Содержит описания методов, которые будут публиковаться как дочерние ресурсы. + =head2 C<[get]childRegex> +Содержит регулярное выражение для идентификаторов дочерних объектов. Если оно +не задано, то данный ресурс не является коллекцией. + =head2 C<[get]fetch> +Содержит описание метода для получения дочернего объекта. Если данный метод +отсутствует, то дочерние ресурсы не получится адресовать относительно данного. +По умолчанию получает идентификатор дочернего ресурса первым параметром. + =head2 C<[get]list> +Описание метода для получения списка дочерних объектов. По умолчанию не +получает параметров. + =head2 C<[get]insert> +Описание метода для добавление дочернего ресурса. По умолчанию получает +объект C<CGI> описывабщий текущий запрос первым параметром. + =head2 C<[get]update> +Описание метода для обновления дочернего ресурса. По умолчанию получает +идентификатор дочернего ресурса и объект C<CGI> текущего запроса. + =head2 C<[get]delete> +Описание метода для удаления дочернего ресурса. По умолчанию получает +идентификатор дочернего ресурса. + =head2 C<GetImpl($child,$action)> +=over + +=item C<$child> + +Идентификатор дочернего ресутсра + +=item C<$action> + +Текущий запрос C<IMPL::Web::Application::Action>. + +=back + +Переадресует запрос нужному методу внутреннего объекта C<target> при +помощи C<InvokeMember>. + =head2 C<PutImpl($child,$action)> +=over + +=item C<$child> + +Идентификатор дочернего ресутсра + +=item C<$action> + +Текущий запрос C<IMPL::Web::Application::Action>. + +=back + +Переадресует запрос нужному методу внутреннего объекта C<target> при +помощи C<InvokeMember>. + =head2 C<PostImpl($child,$action)> +=over + +=item C<$child> + +Идентификатор дочернего ресутсра + +=item C<$action> + +Текущий запрос C<IMPL::Web::Application::Action>. + +=back + +Переадресует запрос нужному методу внутреннего объекта C<target> при +помощи C<InvokeMember>. + =head2 C<DeleteImpl($child,$action)> +=over + +=item C<$child> + +Идентификатор дочернего ресутсра + +=item C<$action> + +Текущий запрос C<IMPL::Web::Application::Action>. + +=back + +Переадресует запрос нужному методу внутреннего объекта C<target> при +помощи C<InvokeMember>. + =head2 C<InvokeMember($memberInfo,$child,$action)> +=over + +=item C<$memberInfo> + +Описание члена внутреннего объекта C<target>, который нужно вызвать. + +=item C<$child> + +Идентификатор дочернего ресутсра + +=item C<$action> + +Текущий запрос C<IMPL::Web::Application::Action>. + +=back + +Вызывает метод внутреннего объекта C<target>, предварительно подготовив +параметры на основе описания C<$memberInfo> и при помощи С<MakeParameter()>. + +=head2 C<MakeParameter($paramDef,$child,$action)> + +=over + +=item C<$paramDef> + +Описание параметра, может быть C<IMPL::Transform> или простая строка. + +Если описание параметра - простая строка, то ее имя либо + +=over + +=item C<id> + +Идентификатор дочернего ресурса + +=item C<query> + +Объект C<CGI> текущего запроса + +=item C<action> + +Текущий запрос C<IMPL::Web::Application::Action> + +=item C<любое другое значение> + +Интерпретируется как параметр текущего запроса. + +=back + +Если описание параметра - объект C<IMPL::Transform>, то будет выполнено это преобразование над C<CGI> +объектом текущего запроса C<< $paramDef->Transform($action->query) >>. + +=back + =cut \ No newline at end of file