view Lib/IMPL/Web/Handler/ViewSelector.pm @ 206:c8fe3f84feba

+IMPL::Web::Handlers::ViewSelector +IMPL::Web::Handlers::ErrorHandler *IMPL::Web::Handlers::RestController moved types mappings to ViewSelector
author sergey
date Thu, 03 May 2012 16:48:39 +0400
parents
children 3d433a977e3b
line wrap: on
line source

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

use IMPL::lang qw(:declare :constants);

use IMPL::declare {
	require => {
		NotAcceptable => 'IMPL::Web::NotAcceptableException'
	},
	base => {
		'IMPL::Object' => undef,
		'IMPL::Object::Autofill' => '@_',
		'IMPL::Object::Serializable' => undef
	}
};

BEGIN {
	public property views => PROP_ALL | PROP_LIST;
	public property fallback => PROP_ALL;
	public property types => PROP_ALL;
}

sub Invoke {
	my ($this,$action,$next) = @_;
	
	my $handler;
	my $path = $action->query->path_info;
	
	if ($this->types and $path =~ m/\.(\w+)$/) {
		my $forced;	
		if ($forced = $this->types->{$1} and $action->query->Accept($forced) ) {
			($handler) = grep eval { $_->can('contentType') } && $_->contentType eq $forced, $this->views;
		}
	}
	
	if (not $handler) {
	
		my @handlers =
	        sort {
	            $b->{preference} <=> $a->{preference}
	        } map {
	            {
	            	handler => $_,
	                preference =>
	                    eval { $_->can('contentType') } ? $action->query->Accept($_->contentType) : 0
	            }
			} $this->views;
	
	    my $info = shift @handlers;
	    $handler = $info ? $info->{handler} : undef;
    
	}
    
    die NotAcceptable->new(map { eval {$_->can('contentType') } ? $_->contentType : () } $this->views )
        unless $handler;
        
    return $handler->Invoke($action,$next);
}

1;