Line data Source code
1 : // Copyright (C) 2012 The Android Open Source Project
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : package com.google.gerrit.extensions.restapi;
16 :
17 : import com.google.gerrit.extensions.annotations.Export;
18 : import com.google.gerrit.extensions.annotations.Exports;
19 : import com.google.gerrit.extensions.config.FactoryModule;
20 : import com.google.inject.Provider;
21 : import com.google.inject.TypeLiteral;
22 : import com.google.inject.binder.LinkedBindingBuilder;
23 : import com.google.inject.binder.ScopedBindingBuilder;
24 :
25 : /** Guice DSL for binding {@link RestView} implementations. */
26 153 : public abstract class RestApiModule extends FactoryModule {
27 : protected static final String GET = "GET";
28 : protected static final String PUT = "PUT";
29 : protected static final String DELETE = "DELETE";
30 : protected static final String POST = "POST";
31 : protected static final String CREATE = "CREATE";
32 : protected static final String DELETE_MISSING = "DELETE_MISSING";
33 : protected static final String DELETE_ON_COLLECTION = "DELETE_ON_COLLECTION";
34 : protected static final String POST_ON_COLLECTION = "POST_ON_COLLECTION";
35 :
36 : protected <R extends RestResource> ReadViewBinder<R> get(TypeLiteral<RestView<R>> viewType) {
37 152 : return get(viewType, "/");
38 : }
39 :
40 : protected <R extends RestResource> ModifyViewBinder<R> put(TypeLiteral<RestView<R>> viewType) {
41 152 : return put(viewType, "/");
42 : }
43 :
44 : protected <R extends RestResource> ModifyViewBinder<R> post(TypeLiteral<RestView<R>> viewType) {
45 0 : return post(viewType, "/");
46 : }
47 :
48 : protected <R extends RestResource> ModifyViewBinder<R> delete(TypeLiteral<RestView<R>> viewType) {
49 152 : return delete(viewType, "/");
50 : }
51 :
52 : protected <R extends RestResource> RestCollectionViewBinder<R> postOnCollection(
53 : TypeLiteral<RestView<R>> viewType) {
54 152 : return new RestCollectionViewBinder<>(
55 152 : bind(viewType).annotatedWith(export(POST_ON_COLLECTION, "/")));
56 : }
57 :
58 : /**
59 : * Creates a binder that allows to bind a REST view to handle {@code DELETE} on the REST
60 : * collection of the provided view type.
61 : *
62 : * <p>This binding is ignored if the provided view type belongs to a root collection.
63 : *
64 : * @param viewType the type of the resources in the REST collection on which {@code DELETE} should
65 : * be handled
66 : * @return binder that allows to bind an implementation for the REST view that should handle
67 : * {@code DELETE} on the REST collection of the provided view type
68 : */
69 : protected <R extends RestResource> RestCollectionViewBinder<R> deleteOnCollection(
70 : TypeLiteral<RestView<R>> viewType) {
71 152 : return new RestCollectionViewBinder<>(
72 152 : bind(viewType).annotatedWith(export(DELETE_ON_COLLECTION, "/")));
73 : }
74 :
75 : protected <R extends RestResource> CreateViewBinder<R> create(TypeLiteral<RestView<R>> viewType) {
76 152 : return new CreateViewBinder<>(bind(viewType).annotatedWith(export(CREATE, "/")));
77 : }
78 :
79 : protected <R extends RestResource> DeleteViewBinder<R> deleteMissing(
80 : TypeLiteral<RestView<R>> viewType) {
81 152 : return new DeleteViewBinder<>(bind(viewType).annotatedWith(export(DELETE_MISSING, "/")));
82 : }
83 :
84 : protected <R extends RestResource> ReadViewBinder<R> get(
85 : TypeLiteral<RestView<R>> viewType, String name) {
86 152 : return new ReadViewBinder<>(view(viewType, GET, name));
87 : }
88 :
89 : protected <R extends RestResource> ModifyViewBinder<R> put(
90 : TypeLiteral<RestView<R>> viewType, String name) {
91 152 : return new ModifyViewBinder<>(view(viewType, PUT, name));
92 : }
93 :
94 : protected <R extends RestResource> ModifyViewBinder<R> post(
95 : TypeLiteral<RestView<R>> viewType, String name) {
96 152 : return new ModifyViewBinder<>(view(viewType, POST, name));
97 : }
98 :
99 : protected <R extends RestResource> ModifyViewBinder<R> delete(
100 : TypeLiteral<RestView<R>> viewType, String name) {
101 152 : return new ModifyViewBinder<>(view(viewType, DELETE, name));
102 : }
103 :
104 : protected <P extends RestResource> ChildCollectionBinder<P> child(
105 : TypeLiteral<RestView<P>> type, String name) {
106 152 : return new ChildCollectionBinder<>(view(type, GET, name));
107 : }
108 :
109 : private <R extends RestResource> LinkedBindingBuilder<RestView<R>> view(
110 : TypeLiteral<RestView<R>> viewType, String method, String name) {
111 152 : return bind(viewType).annotatedWith(export(method, name));
112 : }
113 :
114 : private static Export export(String method, String name) {
115 152 : if (name.length() > 1 && name.startsWith("/")) {
116 : // Views may be bound as "/" to mean the resource itself, or
117 : // as "status" as in "/type/{id}/status". Don't bind "/status"
118 : // if the caller asked for that, bind what the server expects.
119 0 : name = name.substring(1);
120 : }
121 152 : return Exports.named(method + "." + name);
122 : }
123 :
124 : public static class ReadViewBinder<P extends RestResource> {
125 : private final LinkedBindingBuilder<RestView<P>> binder;
126 :
127 152 : private ReadViewBinder(LinkedBindingBuilder<RestView<P>> binder) {
128 152 : this.binder = binder;
129 152 : }
130 :
131 : public <T extends RestReadView<P>> ScopedBindingBuilder to(Class<T> impl) {
132 152 : return binder.to(impl);
133 : }
134 :
135 : public <T extends RestReadView<P>> void toInstance(T impl) {
136 0 : binder.toInstance(impl);
137 0 : }
138 :
139 : public <T extends RestReadView<P>> ScopedBindingBuilder toProvider(
140 : Class<? extends Provider<? extends T>> providerType) {
141 0 : return binder.toProvider(providerType);
142 : }
143 :
144 : public <T extends RestReadView<P>> ScopedBindingBuilder toProvider(
145 : Provider<? extends T> provider) {
146 0 : return binder.toProvider(provider);
147 : }
148 : }
149 :
150 : public static class ModifyViewBinder<P extends RestResource> {
151 : private final LinkedBindingBuilder<RestView<P>> binder;
152 :
153 152 : private ModifyViewBinder(LinkedBindingBuilder<RestView<P>> binder) {
154 152 : this.binder = binder;
155 152 : }
156 :
157 : public <T extends RestModifyView<P, ?>> ScopedBindingBuilder to(Class<T> impl) {
158 152 : return binder.to(impl);
159 : }
160 :
161 : public <T extends RestModifyView<P, ?>> void toInstance(T impl) {
162 0 : binder.toInstance(impl);
163 0 : }
164 :
165 : public <T extends RestModifyView<P, ?>> ScopedBindingBuilder toProvider(
166 : Class<? extends Provider<? extends T>> providerType) {
167 0 : return binder.toProvider(providerType);
168 : }
169 :
170 : public <T extends RestModifyView<P, ?>> ScopedBindingBuilder toProvider(
171 : Provider<? extends T> provider) {
172 0 : return binder.toProvider(provider);
173 : }
174 : }
175 :
176 : public static class RestCollectionViewBinder<C extends RestResource> {
177 : private final LinkedBindingBuilder<RestView<C>> binder;
178 :
179 152 : private RestCollectionViewBinder(LinkedBindingBuilder<RestView<C>> binder) {
180 152 : this.binder = binder;
181 152 : }
182 :
183 : public <P extends RestResource, T extends RestCollectionModifyView<P, C, ?>>
184 : ScopedBindingBuilder to(Class<T> impl) {
185 152 : return binder.to(impl);
186 : }
187 :
188 : public <P extends RestResource, T extends RestCollectionModifyView<P, C, ?>> void toInstance(
189 : T impl) {
190 1 : binder.toInstance(impl);
191 1 : }
192 :
193 : public <P extends RestResource, T extends RestCollectionModifyView<P, C, ?>>
194 : ScopedBindingBuilder toProvider(Class<? extends Provider<? extends T>> providerType) {
195 0 : return binder.toProvider(providerType);
196 : }
197 :
198 : public <P extends RestResource, T extends RestCollectionModifyView<P, C, ?>>
199 : ScopedBindingBuilder toProvider(Provider<? extends T> provider) {
200 0 : return binder.toProvider(provider);
201 : }
202 : }
203 :
204 : public static class CreateViewBinder<C extends RestResource> {
205 : private final LinkedBindingBuilder<RestView<C>> binder;
206 :
207 152 : private CreateViewBinder(LinkedBindingBuilder<RestView<C>> binder) {
208 152 : this.binder = binder;
209 152 : }
210 :
211 : public <P extends RestResource, T extends RestCollectionCreateView<P, C, ?>>
212 : ScopedBindingBuilder to(Class<T> impl) {
213 152 : return binder.to(impl);
214 : }
215 :
216 : public <P extends RestResource, T extends RestCollectionCreateView<P, C, ?>> void toInstance(
217 : T impl) {
218 0 : binder.toInstance(impl);
219 0 : }
220 :
221 : public <P extends RestResource, T extends RestCollectionCreateView<P, C, ?>>
222 : ScopedBindingBuilder toProvider(Class<? extends Provider<? extends T>> providerType) {
223 0 : return binder.toProvider(providerType);
224 : }
225 :
226 : public <P extends RestResource, T extends RestCollectionCreateView<P, C, ?>>
227 : ScopedBindingBuilder toProvider(Provider<? extends T> provider) {
228 0 : return binder.toProvider(provider);
229 : }
230 : }
231 :
232 : public static class DeleteViewBinder<C extends RestResource> {
233 : private final LinkedBindingBuilder<RestView<C>> binder;
234 :
235 152 : private DeleteViewBinder(LinkedBindingBuilder<RestView<C>> binder) {
236 152 : this.binder = binder;
237 152 : }
238 :
239 : public <P extends RestResource, T extends RestCollectionDeleteMissingView<P, C, ?>>
240 : ScopedBindingBuilder to(Class<T> impl) {
241 152 : return binder.to(impl);
242 : }
243 :
244 : public <P extends RestResource, T extends RestCollectionDeleteMissingView<P, C, ?>>
245 : void toInstance(T impl) {
246 0 : binder.toInstance(impl);
247 0 : }
248 :
249 : public <P extends RestResource, T extends RestCollectionDeleteMissingView<P, C, ?>>
250 : ScopedBindingBuilder toProvider(Class<? extends Provider<? extends T>> providerType) {
251 0 : return binder.toProvider(providerType);
252 : }
253 :
254 : public <P extends RestResource, T extends RestCollectionDeleteMissingView<P, C, ?>>
255 : ScopedBindingBuilder toProvider(Provider<? extends T> provider) {
256 0 : return binder.toProvider(provider);
257 : }
258 : }
259 :
260 : public static class ChildCollectionBinder<P extends RestResource> {
261 : private final LinkedBindingBuilder<RestView<P>> binder;
262 :
263 152 : private ChildCollectionBinder(LinkedBindingBuilder<RestView<P>> binder) {
264 152 : this.binder = binder;
265 152 : }
266 :
267 : public <C extends RestResource, T extends ChildCollection<P, C>> ScopedBindingBuilder to(
268 : Class<T> impl) {
269 152 : return binder.to(impl);
270 : }
271 :
272 : public <C extends RestResource, T extends ChildCollection<P, C>> void toInstance(T impl) {
273 0 : binder.toInstance(impl);
274 0 : }
275 :
276 : public <C extends RestResource, T extends ChildCollection<P, C>>
277 : ScopedBindingBuilder toProvider(Class<? extends Provider<? extends T>> providerType) {
278 0 : return binder.toProvider(providerType);
279 : }
280 :
281 : public <C extends RestResource, T extends ChildCollection<P, C>>
282 : ScopedBindingBuilder toProvider(Provider<? extends T> provider) {
283 0 : return binder.toProvider(provider);
284 : }
285 : }
286 : }
|