Mercurial > pub > Impl
diff Lib/IMPL/Web/Application/RestResource.pm @ 200:a9dbe534d236
sync
author | sergey |
---|---|
date | Tue, 24 Apr 2012 02:34:49 +0400 |
parents | e743a8481327 |
children | 0c018a247c8a |
line wrap: on
line diff
--- a/Lib/IMPL/Web/Application/RestResource.pm Mon Apr 23 01:36:52 2012 +0400 +++ b/Lib/IMPL/Web/Application/RestResource.pm Tue Apr 24 02:34:49 2012 +0400 @@ -7,29 +7,32 @@ use IMPL::declare { require => { ForbiddenException => 'IMPL::Web::ForbiddenException', + NotFoundException => 'IMPL::Web::NotFoundException', InvalidOpException => '-IMPL::InvalidOperationException', ArgumentException => '-IMPL::InvalidArgumentException', TTransform => '-IMPL::Transform', - TResolve => '-IMPL::Config::Resolve' + TResolve => '-IMPL::Config::Resolve', + CustomResource => 'IMPL::Web::Application::CustomResource' }, base => { - 'IMPL::Object' => undef, - 'IMPL::Object::Autofill' => '@_' + 'IMPL::Web::Application::RestBaseResource' => '@_' } }; BEGIN { - public property id => PROP_GET | PROP_OWNERSET; public property target => PROP_GET | PROP_OWNERSET; - public property parent => PROP_GET | PROP_OWNERSET; + public property methods => PROP_GET | PROP_OWNERSET; + public property childRegex => PROP_GET | PROP_OWNERSET; public property enableForms => PROP_GET | PROP_OWNERSET; - public property list => PROP_GET | PROP_OWNERSET; - public property fetch => PROP_GET | PROP_OWNERSET; - public property insert => PROP_GET | PROP_OWNERSET; - public property update => PROP_GET | PROP_OWNERSET; - public property delete => PROP_GET | PROP_OWNERSET; + public property orphan => PROP_GET | PROP_OWNERSET; + + public property listChildren => PROP_GET | PROP_OWNERSET; + public property fetchChild => PROP_GET | PROP_OWNERSET; + public property createChild => PROP_GET | PROP_OWNERSET; + public property updateChild => PROP_GET | PROP_OWNERSET; + public property deleteChild => PROP_GET | PROP_OWNERSET; } sub CTOR { @@ -37,108 +40,25 @@ die ArgumentException->new("id","Identifier is required for non-root resources") if $this->id and not length $this->id; die ArgumentException->new("target") unless $this->target; + die ArgumentException->new("A contract is required") unless $this->contract; - if ($this->enableForms && $this->parent) { - $this->methods({}) unless $this->methods; - - if ($this->insert) { - $this->methods->{create} = { - get => sub { - my ($that,$id,$action) = @_; - return $that->target; - } - }; - } + if ($this->enableForms) { - if ($this->parent->update) { - $this->methods->{edit} = { - get => sub { - my ($that,$id,$action) = @_; - return $that->target; - }, - post => sub { - my ($that,$id,$action) = @_; - return $that->parent->PutImpl($that->id,$action); - } - }; - } - - if ($this->parent->delete) { - $this->methods->{delete} = { - get => sub { - my ($that,$id,$action) = @_; - return $that->target; - }, - post => sub { - my ($that,$id,$action) = @_; - return $that->parent->DeleteImpl($that->id,$action); - } - }; - } } } -sub GetHttpImpl { - my($this,$method) = @_; - - my %map = ( - GET => 'GetImpl', - PUT => 'PutImpl', - POST => 'PostImpl', - DELETE => 'DeleteImpl' - ); - - return $map{$method}; -} - -sub InvokeHttpMethod { - my ($this,$method,$childId,$action) = @_; - - my $impl = $this->GetHttpImpl($method) || 'HttpFallbackImpl'; - - return $this->$impl($childId,$action); -} - sub GetImpl { - my ($this,$id,$action) = @_; + my ($this,$action) = @_; - my $rx; - my $method; - if (length $id == 0) { - $method = $this->list or die ForbiddenException->new(); - } elsif ($this->methods and $method = $this->methods->{$id}->{get}) { - # we got method info - } elsif($rx = $this->childRegex and $id =~ m/$rx/ ) { - $method = $this->fetch or die ForbiddenException->new(); - - $method = { - method => $method, - parameters => [qw(id)] - } unless ref $method; - - } else { - die ForbiddenException->new(); - } - - return $this->InvokeMember($method,$id,$action); + return $this->target; } sub PutImpl { - my ($this,$id,$action) = @_; + my ($this,$action) = @_; - my $rx = $this->childRegex; - if ( $rx and $id =~ m/$rx/ and $this->update ) { - my $method = $this->update or die ForbiddenException->new(); - - $method = { - method => $method, - parameters => [qw(id query)] - } unless ref $method; - - return $this->InvokeMember($method,$id,$action); - } else { - die ForbiddenException->new(); - } + die ForbiddenException->new() if $this->orhpan; + + $this->parent->UpdateImpl($this->id,$action); } sub PostImpl { @@ -183,6 +103,50 @@ die ForbiddenException->new(); } +sub UpdateImpl { + my ($this,$id,$action) = @_; + + my $method = $this->updateChild or die ForbiddenException->new(); + $this->InvokeMember($method,$action); +} + +sub FetchChildResource { + my ($this,$id,$action) = @_; + + my $rx = $this->childRegex; + my $method; + my %params = ( + parent => $this, + id => $id + ); + + if (length $id == 0) { + + $method = $this->list; + die ForbiddenException->new() unless $method; + + return $this->contract->Transform( $this->InvokeMember($method,$id,$action), \%params ); + + } elsif ($method = $this->methods->{$id}) { + # поскольку данный объект был получен не как дочерний объект, + # а как выполнение метода, то для него не определены операции + # put и delete по умолчанию. + $params{orphan} = 1; + + return $this->contract->Transform( $this->InvokeMember($method,$id,$action), \%params ); + + } elsif ($rx and $id =~ m/^$rx$/ and $method = $this->fetch) { + # ok + } else { + die ForbiddenException->new(); + } + + my $res = $this->InvokeMember($method,$id,$action); + die NotFoundException->new() unless defined $res; + + return $this->contract->Transform($res, {parent => $this, id => $id} ); +} + sub InvokeMember { my ($this,$method,$id,$action) = @_; @@ -332,6 +296,10 @@ Каждый ресурс представляет собой коллекцию и реализует методы C<HTTP> C<GET,POST,PUT,DELETE>. +Ресурсы выстраиваются в иерархию, на основе пути. Поиск конечного реурса происходит последовательным +вызовом метода GET с именем очередного ресурса. + + =head2 HTTP METHODS =head3 C<GET> @@ -373,8 +341,8 @@ =head1 BROWSER COMPATIBILITY Однако существует проблема с браузерами, поскольку тег C<< <form> >> реализет только методы -C<GET,POST>. Для решения данной проблемы используется режим совместимости C<compatible>. В -случае когда данный режим активен, автоматически публикуются дочерние C<create,edit,delete>. +C<GET,POST>. Для решения данной проблемы используется режим совместимости C<enableForms>. В +случае когда данный режим активен, автоматически публикуются дочерние ресурсы C<create,edit,delete>. =head2 C<GET create>