comparison Lib/IMPL/Web/Application/RestResource.pm @ 197:6b1dda998839

Added IMPL::declare, IMPL::require, to simplify module definitions IMPL::Transform now admires object inheritance while searching for the transformation Added HTTP some exceptions IMPL::Web::Application::RestResource almost implemented
author sergey
date Thu, 19 Apr 2012 02:10:02 +0400
parents a705e848dcc7
children 2ffe6f661605
comparison
equal deleted inserted replaced
196:a705e848dcc7 197:6b1dda998839
1 package IMPL::Web::Application::RestResource; 1 package IMPL::Web::Application::RestResource;
2 use strict; 2 use strict;
3 3
4 use IMPL::lang qw(:declare :constants);
5 use IMPL::declare {
6 require => {
7 ForbiddenException => 'IMPL::Web::ForbiddenException'
8 },
9 base => {
10 'IMPL::Object' => undef
11 }
12 };
13
14 BEGIN {
15 public property target => PROP_GET | PROP_OWNERSET;
16 public property methods => PROP_GET | PROP_OWNERSET;
17 public property childRegex => PROP_GET | PROP_OWNERSET;
18 public property list => PROP_GET | PROP_OWNERSET;
19 public property fetch => PROP_GET | PROP_OWNERSET;
20 public property insert => PROP_GET | PROP_OWNERSET;
21 public property update => PROP_GET | PROP_OWNERSET;
22 public property delete => PROP_GET | PROP_OWNERSET;
23 }
24
25 sub GetHttpImpl {
26 my($this,$method) = @_;
27
28 my %map = (
29 GET => 'GetImpl',
30 PUT => 'PutImpl',
31 POST => 'PostImpl',
32 DELETE => 'DeleteImpl'
33 );
34
35 return $map{$method};
36 }
37
38 sub InvokeHttpMethod {
39 my ($this,$method,$child,$action) = @_;
40
41 my $impl = $this->GetHttpImpl($method) || 'FallbackImpl';
42
43 return $this->$impl($child,$action);
44 }
45
46 sub GetImpl {
47 my ($this,$id,$action) = @_;
48
49 my $rx;
50 my $method;
51 if (length $id == 0) {
52 $method = $this->list;
53 } elsif ($method = $this->methods->{$id}) {
54 if (ref $method eq 'HASH' and not $method->{allowGet}) {
55 die ForbiddenException->new();
56 }
57 } elsif($rx = $this->childRegex and $id =~ m/$rx/ ) {
58 $method = $this->fetch or die ForbiddenException->new();
59
60 $method = {
61 method => $method,
62 parameters => [qw(id)]
63 } unless ref $method;
64
65 } else {
66 die ForbiddenException->new();
67 }
68
69 return $this->InvokeMember($method,$id,$action);
70 }
71
72 sub PutImpl {
73 my ($this,$id,$action) = @_;
74
75 my $rx = $this->childRegex;
76 if ( $rx and $id =~ m/$rx/ and $this->update ) {
77 my $method = $this->update or die ForbiddenException->new();
78
79 $method = {
80 method => $method,
81 parameters => [qw(id query)]
82 } unless ref $method;
83
84 return $this->InvokeMember($method,$id,$action);
85 } else {
86 die ForbiddenException->new();
87 }
88 }
89
90 sub PostImpl {
91 my ($this,$id,$action) = @_;
92
93 my $method;
94
95 if (length $id == 0) {
96 $method = $this->insert or die ForbiddenException->new();
97
98 $method = {
99 method => $method,
100 parameters => [qw(query)]
101 } unless ref $method;
102 } elsif ($method = $this->methods->{$id}) {
103 die ForbiddenException->new() unless ref $method and $method->{allowPost};
104 } else {
105 die ForbiddenException->new();
106 }
107
108 return $this->InvokeMemeber($method,$id,$action);
109 }
110
111 sub DeleteImpl {
112 my ($this,$id,$action) = @_;
113
114 my $rx = $this->childRegex;
115 if ($rx and $id =~ m/$rx/ and my $method = $this->delete) {
116
117 $method = {
118 method => $method,
119 parameters => [qw(id)]
120 } unless ref $method;
121
122 return $this->InvokeMember($method,$id,$action);
123 } else {
124 die ForbiddenException->new();
125 }
126 }
127
128 sub HttpFallbackImpl {
129 die ForbiddenException->new();
130 }
131
132 sub InvokeMember {
133 my ($this,$method,$id,$action) = @_;
134 }
135
136
4 1; 137 1;
5 138
6 __END__ 139 __END__
7 140
8 =pod 141 =pod
9 142
10 =head1 NAME 143 =head1 NAME
11 144
12 C<IMPL::Web::Application::RestResource> - ресурс Rest вебсервиса. 145 C<IMPL::Web::Application::RestResource> - ресурс Rest вебсервиса.
13 146
147 =head1 SYNOPSIS
148
149 =begin text
150
151 [REQUEST]
152 GET /artists
153
154 [RESPONSE]
155 <artists>
156 <artist id="1">
157 <name>The Beatles <name/>
158 </atrist>
159 <artist id="2">
160 <name>Bonobo</name>
161 </artist>
162 </artists>
163
164 [REQUEST]
165 GET /artists/1/cds?title='Live at BBC'
166
167 [RESPONSE]
168 <cds>
169 <cd id="14">
170 <title>Live at BBC 1</title>
171 </cd>
172 <cd id="15">
173 <title>Live at BBC 2</title>
174 </cd>
175 </cds>
176
177 [REQUEST]
178 GET /cds/15
179
180 [RESPONSE]
181 <cd id="15">
182 <title>Live at BBC 2</title>
183 </cd>
184
185 =end text
186
187 =begin code
188
189 use IMPL::require {
190 TRes => 'IMPL::Web:Application::RestResource',
191 DataContext => 'My::App::DataContext'
192 };
193
194 my $cds = TRes->new(
195 DataContext->Default,
196 {
197 methods => {
198 get => {
199
200 },
201 post => {
202
203 }
204 }
205 get => 'search',
206
207
208 }
209 );
210
211 =end code
212
14 =head1 DESCRIPTION 213 =head1 DESCRIPTION
15 214
215 Каждый ресурс представляет собой коллекцию и реализует методы C<HTTP> C<GET,POST,PUT,DELETE>.
216
217 =head2 HTTP METHODS
218
219 =head3 C<GET>
220
221 Возвращает коллекцию дочерних ресурсов.
222
223 =head3 C<GET {id}>
224
225 Возвращает дочерний объект с идентификатором C<id>
226
227 =head3 C<GET {method}>
228
229 Вызывает метод C<method> и возвращает его результаты. При публикации методов доступных
230 через C<GET> данные методы не должны вносить изменений в предметную область.
231
232 =head3 C<PUT {id}>
233
234 Обновляет дочерний ресурс с указанным идентификатором.
235
236 =head3 C<DELETE {id}>
237
238 Удаляет дочерний ресурс с указанным идентификатором.
239
240 =head3 C<POST>
241
242 Добавляет новый дочерний ресурс в коллекцию.
243
244 =head2 HTTP METHOD MAPPING
245
246 =head3 C<POST {method}>
247
248 Вызывает метод C<method>, в отличии от C<GET> методы опубликованные через C<POST> могут вносить
249 изменения в объекты.
250
251 =head1 MEMBERS
252
253 =head2 C<[get]target>
254
255 Объект (также может быть и класс), обеспечивающий функционал ресурса.
256
257 =head2 C<[get]methods>
258
259 =head2 C<[get]childRegex>
260
261 =head2 C<[get]fetch>
262
263 =head2 C<[get]list>
264
265 =head2 C<[get]insert>
266
267 =head2 C<[get]update>
268
269 =head2 C<[get]delete>
270
271 =head2 C<GetImpl($child,$action)>
272
273 =head2 C<PutImpl($child,$action)>
274
275 =head2 C<PostImpl($child,$action)>
276
277 =head2 C<DeleteImpl($child,$action)>
278
279 =head2 C<InvokeMember($memberInfo,$child,$action)>
280
16 =cut 281 =cut