view Lib/IMPL/Web/Handler/RestController.pm @ 253:0a228a35645c

added application exception class
author sergey
date Mon, 19 Nov 2012 17:54:01 +0400
parents a02b110da931
children 827cf96faa1c
line wrap: on
line source

package IMPL::Web::Handler::RestController;
use strict;

use IMPL::Const qw(:prop);
use IMPL::declare {
	require => {
	    Locator => 'IMPL::Web::AutoLocator',
	    ResourceInterface => 'IMPL::Web::Application::ResourceInterface', 
		Exception => 'IMPL::Exception',
		ArgumentExecption => '-IMPL::InvalidArgumentException',
		NotFoundException => 'IMPL::Web::NotFoundException'
	},
	base => {
		'IMPL::Object' => undef,
		'IMPL::Object::Autofill' => '@_',
		'IMPL::Object::Serializable' => undef
	},
	props => [
	   resourceFactory => PROP_RO,
	   trailingSlash => PROP_RO
	]	
};

sub CTOR {
	my ($this) = @_;
	
	die ArgumentException->new(resourceFactory => "A web-resource is required")
	   unless $this->resourceFactory;
	   #unless eval { $this->resourceFacotry->isa(ResourceInterface) };
	 
}

sub GetResourcePath {
    my ($this,$action) = @_;
    
    my $pathInfo = $action->pathInfo;
    my @segments;
    
    if (length $pathInfo) {
    
        @segments = split(/\//, $pathInfo, $this->trailingSlash ? -1 : 0);
        
        # remove first segment if it is empty
        shift @segments if @segments && length($segments[0]) == 0;
        
        if(@segments) {
            my ($obj,$view) = (pop(@segments) =~ m/(.*?)(?:\.(\w+))?$/);
            push @segments, $obj;
        }
    
    }
    
    return @segments;    
}


sub Invoke {
	my ($this,$action) = @_;
	
	my $method = $action->requestMethod;
	
	my @segments = $this->GetResourcePath($action);
	
	my $res = $this->resourceFactory->new(
	   id => 'root',
	   location => Locator->new(base => $action->application->baseUrl)
	);
	
	while(@segments) {
		my $id = shift @segments;
		
		$res = $res->FetchChildResource($id);
	}
	
	$res = $res->InvokeHttpVerb($method,$action);
}

1;

__END__

=pod

=head1 NAME

C<IMPL::Web::Handler::RestController> - Обрабатывает C<HTTP> запрос передавая
его соответствующему ресурсу.

=head1 SYNOPSIS

Используется в конфигурации приложения как элемент цепочки обработчиков.
Как правило располагается на самом верхнем уровне.

=begin code xml

    <handlers type="ARRAY">
        <item type="IMPL::Web::Handler::RestController">
            <rootResource type="My::App::Web::RootResource"/>
        </item>
        <item type="IMPL::Web::Handler::JSONView" />
        <item type="IMPL::Web::Handler::SecureCookie" />
        <item type="IMPL::Web::Handler::ErrorHandler" />
    </handlers>

=end code xml


=head1 DESCRIPTION

Использует C<PATH_INFO> для определения нужного ресурса, затем предает
найденному ресурсу управление для обработки запроса.

Если ресурс не найден, то возникает исключение C<IMPL::Web::NotFoundException>.

Для определения нужного ресурса контроллер разбивает C<PATH_INFO> на фрагменты
и использует каждый фрагмент для получения дочернего ресурса начиная с корневого.
Для чего используется метод
C<< IMPL::Web::Application::ResourceInterface->FetchChildResource($childId) >>.

=head1 MEMEBERS

=head2 C<[get]rootResource>

Корневой ресурс приложения, должен быть всегда и реализовывать интерфес ресурса
C<IMPL::Web::Application::ResourceInterface>.

=head2 C<[get]trailingSlash>

Если данная переменная имеет значение C<true>, то слеш в конце пути к ресурсу
будет интерпретироваться, как дочерний ресурс с пустым идентификатором.

=cut