Mercurial > pub > Impl
comparison Lib/IMPL/Web/Application/Resource.pm @ 268:4abda21186cd
*refactoring IMPL::Web: added 'application' property to resources
| author | cin |
|---|---|
| date | Mon, 21 Jan 2013 02:08:17 +0400 |
| parents | 32aceba4ee6d |
| children | 546957c50a36 |
comparison
equal
deleted
inserted
replaced
| 267:bbc0da7ef90e | 268:4abda21186cd |
|---|---|
| 15 base => [ | 15 base => [ |
| 16 'IMPL::Object' => undef, | 16 'IMPL::Object' => undef, |
| 17 'IMPL::Web::Application::ResourceInterface' => undef | 17 'IMPL::Web::Application::ResourceInterface' => undef |
| 18 ], | 18 ], |
| 19 props => [ | 19 props => [ |
| 20 parent => PROP_RO, | 20 application => PROP_RO, |
| 21 model => PROP_RO, | 21 parent => PROP_RO, |
| 22 id => PROP_RO, | 22 model => PROP_RO, |
| 23 contract => PROP_RO, | 23 id => PROP_RO, |
| 24 location => PROP_RO, | 24 contract => PROP_RO, |
| 25 location => PROP_RO, | |
| 25 ] | 26 ] |
| 26 }; | 27 }; |
| 27 | 28 |
| 28 sub CTOR { | 29 sub CTOR { |
| 29 my ( $this, %args ) = @_; | 30 my ( $this, %args ) = @_; |
| 35 | 36 |
| 36 $this->parent( $args{parent} ); | 37 $this->parent( $args{parent} ); |
| 37 $this->model( $args{model} ); | 38 $this->model( $args{model} ); |
| 38 $this->id( $args{id} ); | 39 $this->id( $args{id} ); |
| 39 $this->contract( $args{contract} ); | 40 $this->contract( $args{contract} ); |
| 40 | 41 $this->application( $args{application} || ($args{parent} && $args{parent}->application) ); |
| 41 # если расположение явно не указано, то оно вычисляется автоматически, | 42 |
| 42 # либо остается не заданным | 43 # если расположение явно не указано, то оно вычисляется автоматически, |
| 43 $this->location( $args{location} || eval { $this->parent->location->Child( $this->id ) } ); | 44 # либо остается не заданным |
| 45 $this->location( $args{location} | |
| 46 || eval { $this->parent->location->Child( $this->id ) } ); | |
| 44 } | 47 } |
| 45 | 48 |
| 46 sub InvokeHttpVerb { | 49 sub InvokeHttpVerb { |
| 47 my ( $this, $verb, $action ) = @_; | 50 my ( $this, $verb, $action ) = @_; |
| 48 | 51 |
| 49 my $operation = $this->contract->verbs->{ lc($verb) }; | 52 my $operation = $this->contract->verbs->{ lc($verb) }; |
| 50 | 53 |
| 51 die NotAllowedException->new( | 54 die NotAllowedException->new( |
| 52 allow => join( ',', map( uc, keys %{ $this->contract->verbs } ) ) | 55 allow => join( ',', map( uc, keys %{ $this->contract->verbs } ) ) ) |
| 53 ) | 56 unless $operation; |
| 54 unless $operation; | 57 |
| 55 | 58 # в случае, когда один ресурс вызывает HTTP метод другого ресурса, нужно |
| 56 # в случае, когда один ресурс вызывает HTTP метод другого ресурса, нужно | 59 # сохранить оригинальный resourceLocation |
| 57 # сохранить оригинальный resourceLocation | 60 $action->context->{resourceLocation} ||= $this->location; |
| 58 $action->context->{resourceLocation} ||= $this->location; | 61 |
| 59 | 62 return _InvokeDelegate($operation, $this, $action ); |
| 60 return $operation->Invoke( $this, $action ); | |
| 61 } | 63 } |
| 62 | 64 |
| 63 # это реализация по умолчанию, базируется информации о ресурсах, содержащийся | 65 # это реализация по умолчанию, базируется информации о ресурсах, содержащийся |
| 64 # в контракте. | 66 # в контракте. |
| 65 sub FetchChildResource { | 67 sub FetchChildResource { |
| 66 my ( $this, $childId ) = @_; | 68 my ( $this, $childId ) = @_; |
| 67 | 69 |
| 68 my ($info,$childIdParts) = $this->contract->FindChildResourceInfo($childId); | 70 my ( $info, $childIdParts ) = |
| 69 | 71 $this->contract->FindChildResourceInfo($childId); |
| 70 die NotFoundException->new($this->location->url,$childId) unless $info; | 72 |
| 71 | 73 die NotFoundException->new( $this->location->url, $childId ) unless $info; |
| 72 my $binding = $info->{binding}; | 74 |
| 73 my $contract = $info->{contract}; | 75 my $binding = $info->{binding}; |
| 74 | 76 my $contract = $info->{contract}; |
| 75 if (ref $contract eq 'CODE') { | 77 my $model = _InvokeDelegate( $binding, $this, @$childIdParts ); |
| 76 $contract = $contract->(); | 78 |
| 77 $info->{contract} = $contract; | 79 if ( ref $contract eq 'CODE' || $contract->can('Invoke')) { |
| 78 } | 80 $contract = _InvokeDelegate($contract,$this,$model); |
| 79 | 81 $info->{contract} = $contract; |
| 80 die OperationException->new("Can't fetch a contract for the resource", $childId) | 82 } |
| 81 unless $contract; | 83 |
| 82 | 84 die OperationException->new( "Can't fetch a contract for the resource", |
| 83 my %args = ( | 85 $childId ) |
| 84 parent => $this, | 86 unless $contract; |
| 85 id => $childId | 87 |
| 86 ); | 88 my %args = ( |
| 87 | 89 parent => $this, |
| 88 $args{model} = _InvokeDelegate($binding,$this,@$childIdParts); | 90 id => $childId, |
| 89 | 91 model => $model |
| 90 return $contract->CreateResource(%args); | 92 ); |
| 93 | |
| 94 return $contract->CreateResource(%args); | |
| 91 } | 95 } |
| 92 | 96 |
| 93 sub _InvokeDelegate { | 97 sub _InvokeDelegate { |
| 94 my $delegate = shift; | 98 my $delegate = shift; |
| 95 | 99 |
| 96 return $delegate->(@_) if ref $delegate eq 'CODE'; | 100 return $delegate->(@_) if ref $delegate eq 'CODE'; |
| 97 return $delegate->Invoke(@_) if eval { $delegate->can('Invoke')}; | 101 return $delegate->Invoke(@_) if eval { $delegate->can('Invoke') }; |
| 98 } | 102 } |
| 99 | 103 |
| 100 1; | 104 1; |
| 101 | 105 |
| 102 __END__ | 106 __END__ |
| 156 собственный класс ресурса, например унаследованный от | 160 собственный класс ресурса, например унаследованный от |
| 157 C<IMPL::Web::Application::CustomResource>. | 161 C<IMPL::Web::Application::CustomResource>. |
| 158 | 162 |
| 159 =head1 MEMBERS | 163 =head1 MEMBERS |
| 160 | 164 |
| 165 =head2 C<[get]application> | |
| 166 | |
| 167 Ссылка на приложение, к которому относится данный ресурс. Его следует задавать | |
| 168 только для коренвых ресурсов, дочерние ресурсы получают это свойство от | |
| 169 родителей. | |
| 170 | |
| 161 =head2 C<[get]contract> | 171 =head2 C<[get]contract> |
| 162 | 172 |
| 163 Обязательное свойство для ресурса, ссылается, на контракт, соответствующий | 173 Обязательное свойство для ресурса, ссылается, на контракт, соответствующий |
| 164 данному ресурсу, используется для выполнения C<HTTP> методов и получения | 174 данному ресурсу, используется для выполнения C<HTTP> методов и получения |
| 165 дочерних ресурсов. | 175 дочерних ресурсов. |
| 183 Объект типа C<IMPL::Web::AutoLocator> или аналогичный описывающий адрес текущего | 193 Объект типа C<IMPL::Web::AutoLocator> или аналогичный описывающий адрес текущего |
| 184 ресурса, может быть как явно передан при создании ресурса, так и вычислен | 194 ресурса, может быть как явно передан при создании ресурса, так и вычислен |
| 185 автоматически (только для ресурсов имеющих родителя). Следует заметить, что | 195 автоматически (только для ресурсов имеющих родителя). Следует заметить, что |
| 186 адрес ресурса не содержит параметров запроса, а только путь. | 196 адрес ресурса не содержит параметров запроса, а только путь. |
| 187 | 197 |
| 198 =head2 C<[get]FetchChildResource($id)> | |
| 199 | |
| 200 Возвращает дочерний ресурс, по его идентификатору. | |
| 201 | |
| 202 Данная реализация использует контракт текущего ресурса для поиска информации о | |
| 203 дочернем ресурсе C<< $this->contract->FindChildResourceInfo($id) >>. | |
| 204 | |
| 205 Затем осуществляется привязка к моделе, тоесть, выполняется делегат, для | |
| 206 получения модели дочернего ресурса, а затем осуществляется привязка к контракту, | |
| 207 при этом в делегат, который должен вернуть контракт дочернего ресурса передаются | |
| 208 текущий ресурc и модель дочернего ресурса. | |
| 209 | |
| 188 =cut | 210 =cut |
