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