Mercurial > pub > Impl
comparison Lib/IMPL/Web/Application/CustomResource.pm @ 334:71221d79e6b4
removing web resources contracts
| author | cin |
|---|---|
| date | Thu, 13 Jun 2013 02:24:57 +0400 |
| parents | 04a093f0a5a6 |
| children | e8be9062ecf2 |
comparison
equal
deleted
inserted
replaced
| 333:cd6409f66a5f | 334:71221d79e6b4 |
|---|---|
| 3 | 3 |
| 4 use IMPL::Const qw(:prop); | 4 use IMPL::Const qw(:prop); |
| 5 | 5 |
| 6 use IMPL::declare { | 6 use IMPL::declare { |
| 7 require => { | 7 require => { |
| 8 Factory => 'IMPL::Object::Factory', | 8 NotAllowedException => 'IMPL::Web::NotAllowedException', |
| 9 CustomResourceContract => 'IMPL::Web::Application::CustomResourceContract' | 9 HttpResponse => 'IMPL::Web::HttpResponse' |
| 10 }, | 10 }, |
| 11 base => [ | 11 base => [ |
| 12 'IMPL::Web::Application::Resource' => '@_' | 12 'IMPL::Web::Application::Resource' => '@_' |
| 13 ], | 13 ], |
| 14 props => [ | 14 props => [ |
| 15 accessCheck => PROP_RW | 15 accessCheck => PROP_RW |
| 16 ] | 16 ] |
| 17 }; | 17 }; |
| 18 | 18 |
| 19 __PACKAGE__->static_accessor(contractFactory => CustomResourceContract ); | 19 our %RESOURCE_BINDINGS = ( |
| 20 __PACKAGE__->static_accessor_own(_contractInstance => undef); | 20 GET => 'HttpGet', |
| 21 POST => 'HttpPost', | |
| 22 PUT => 'HttpPut', | |
| 23 DELETE => 'HttpDelete', | |
| 24 HEAD => 'HttpHead' | |
| 25 ); | |
| 26 | |
| 27 __PACKAGE__->static_accessor(_rxResourcesMap => undef, 'own'); | |
| 28 __PACKAGE__->static_accessor(_nameResourcesMap => undef, 'own'); | |
| 29 | |
| 30 sub namedResources { | |
| 31 shift->_nameResourcesMap; | |
| 32 } | |
| 33 | |
| 34 sub regexResources { | |
| 35 shift->_rxResourcesMap; | |
| 36 } | |
| 21 | 37 |
| 22 sub CTOR { | 38 sub CTOR { |
| 23 my ($this,%args) = @_; | 39 my ($this,%args) = @_; |
| 24 | 40 |
| 25 $this->accessCheck($args{accessCheck}) | 41 $this->accessCheck($args{accessCheck}) |
| 26 if $args{accessCheck}; | 42 if $args{accessCheck}; |
| 27 } | 43 |
| 28 | 44 $this->verbs->{options} ||= \&_HttpOptionsBinding; |
| 29 sub contractInstance { | 45 |
| 46 while(my ($verb,$methodName) = each %RESOURCE_BINDINGS) { | |
| 47 $this->verbs->{lc($verb)} ||= sub { | |
| 48 my ($resource,$action) = @_; | |
| 49 | |
| 50 if (eval { $resource->can($methodName) }) { | |
| 51 return $resource->$methodName($action); | |
| 52 } else { | |
| 53 die NotAllowedException->new(allow => join(',', _GetAllowedHttpMethods($resource))); | |
| 54 } | |
| 55 } | |
| 56 } | |
| 57 } | |
| 58 | |
| 59 sub FindChildResourceInfo { | |
| 60 my ( $this, $name ) = @_; | |
| 61 | |
| 62 $this->_PrepareResourcesCache() | |
| 63 unless($this->_nameResourcesMap); | |
| 64 | |
| 65 return $this->next::method($name); | |
| 66 } | |
| 67 | |
| 68 sub PrepareResourcesCache { | |
| 69 # suppress default caching mechanisn | |
| 70 } | |
| 71 | |
| 72 sub _PrepareResourcesCache { | |
| 73 # a little bit wired | |
| 30 my ($self) = @_; | 74 my ($self) = @_; |
| 31 | 75 my %nameMap; |
| 32 $self = ref $self || $self; | 76 my @rxMap; |
| 33 $self->_contractInstance ? $self->_contractInstance : $self->InitContract(); | 77 |
| 34 } | 78 foreach my $res ($self->GetChildResources()) { |
| 35 | 79 #skip resources without contract |
| 36 sub InitContract { | 80 next unless $res->{contract}; |
| 37 my ($self) = @_; | 81 |
| 38 $self->_contractInstance( | 82 if ( my $name = $res->{name} ) { |
| 39 $self->contractFactory->new( | 83 $nameMap{$name} = $res; |
| 40 resourceFactory => $self, | 84 } |
| 41 resources => [ $self->GetChildResources() ] | 85 if ( $res->{match} ) { |
| 42 ) | 86 push @rxMap,$res; |
| 43 ); | 87 } |
| 44 } | 88 } |
| 45 | 89 |
| 46 sub CreateContract { | 90 $self->_rxResourcesMap(\@rxMap); |
| 47 my ($self, %args) = @_; | 91 $self->_nameResourcesMap(\%nameMap); |
| 48 | |
| 49 $self->contractFactory->new( | |
| 50 resourceFactory => Factory->new( | |
| 51 $self, | |
| 52 \%args | |
| 53 ), | |
| 54 resources => [ $self->GetChildResources() ] | |
| 55 ) | |
| 56 } | |
| 57 | |
| 58 sub CreateResource { | |
| 59 my ($self,%args) = @_; | |
| 60 | |
| 61 $self->CreateContract()->CreateResource(%args); | |
| 62 } | 92 } |
| 63 | 93 |
| 64 sub AccessCheck { | 94 sub AccessCheck { |
| 65 my ($this,$verb) = @_; | 95 my ($this,$verb) = @_; |
| 66 | 96 |
| 67 my $handler = $this->accessCheck; | 97 my $handler = $this->accessCheck; |
| 68 | 98 |
| 69 if(ref($handler) eq 'CODE') { | 99 if(ref($handler) eq 'CODE') { |
| 70 &$handler($this,$verb); | 100 return &$handler($this,$verb); |
| 71 } | 101 } |
| 72 } | 102 } |
| 73 | 103 |
| 74 sub GetChildResources { | 104 sub GetChildResources { |
| 75 | 105 |
| 106 } | |
| 107 | |
| 108 sub _HttpOptionsBinding { | |
| 109 my ($this) = @_; | |
| 110 | |
| 111 my @allow = $this->_GetAllowedHttpMethods(); | |
| 112 return HttpResponse->new( | |
| 113 status => '200 OK', | |
| 114 headers => { | |
| 115 allow => join ( ',', @allow ) | |
| 116 } | |
| 117 ); | |
| 118 } | |
| 119 | |
| 120 sub _GetAllowedHttpMethods { | |
| 121 my ($this) = @_; | |
| 122 return grep $this->can($RESOURCE_BINDINGS{$_}), keys %RESOURCE_BINDINGS; | |
| 76 } | 123 } |
| 77 | 124 |
| 78 | 125 |
| 79 1; | 126 1; |
| 80 | 127 |
| 109 my $form = MyApp::Web::Schema::UpdateUser->new(); | 156 my $form = MyApp::Web::Schema::UpdateUser->new(); |
| 110 | 157 |
| 111 $this->model->update( $form->Bind($action) ); | 158 $this->model->update( $form->Bind($action) ); |
| 112 } | 159 } |
| 113 | 160 |
| 114 our %COMPONENTS = ( | 161 sub GetChildResources { |
| 115 item => { | 162 return { |
| 116 verbs => { | 163 name => 'create', |
| 117 get => sub { | 164 contract => { |
| 118 shift->model; | 165 class => 'My::Web::FormResource', |
| 119 } | 166 formName => 'create', |
| 120 }, | 167 schema => 'profile.schema' |
| 121 resources => [ | 168 } |
| 122 edit => | 169 }, |
| 123 ] | 170 { |
| 124 } | 171 match => qr/^(.*)$/, |
| 125 ); | 172 contract => { |
| 173 class => 'My::Web::ItemResource' | |
| 174 } | |
| 175 } | |
| 176 } | |
| 126 | 177 |
| 127 =end code | 178 =end code |
| 128 | 179 |
| 129 =head1 MEMBERS | 180 =head1 MEMBERS |
| 130 | 181 |
