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 |