Support for network service for alto-northbound
[alto.git] / alto-northbound / src / main / java / org / opendaylight / alto / northbound / AltoNorthbound.java
1 /*
2  * Copyright (c) 2015 Yale University and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.alto.northbound;
9
10 import javax.ws.rs.GET;
11 import javax.ws.rs.POST;
12 import javax.ws.rs.Path;
13 import javax.ws.rs.PathParam;
14 import javax.ws.rs.Consumes;
15 import javax.ws.rs.Produces;
16 import javax.ws.rs.core.Response;
17 import javax.ws.rs.core.Response.Status;
18
19 import org.opendaylight.alto.commons.types.rfc7285.RFC7285JSONMapper;
20 import org.opendaylight.alto.commons.types.rfc7285.FormatValidator;
21 import org.opendaylight.alto.commons.types.rfc7285.MediaType;
22 import org.opendaylight.alto.commons.types.rfc7285.RFC7285NetworkMap;
23 import org.opendaylight.alto.commons.types.rfc7285.RFC7285CostType;
24 import org.opendaylight.alto.commons.types.rfc7285.RFC7285IRD;
25 import org.opendaylight.alto.commons.types.rfc7285.RFC7285VersionTag;
26 import org.opendaylight.alto.commons.types.rfc7285.RFC7285CostMap;
27 import org.opendaylight.alto.commons.types.rfc7285.RFC7285Endpoint;
28
29 import org.opendaylight.alto.services.api.rfc7285.AltoService;
30 import org.opendaylight.alto.services.api.rfc7285.IRDService;
31 import org.opendaylight.alto.services.api.rfc7285.NetworkMapService;
32 import org.opendaylight.alto.services.api.rfc7285.CostMapService;
33 import org.opendaylight.alto.services.api.rfc7285.EndpointCostService;
34 import org.opendaylight.alto.services.api.rfc7285.EndpointPropertyService;
35
36
37 import org.opendaylight.alto.northbound.exception.AltoBasicException;
38 import org.opendaylight.alto.northbound.exception.AltoBadFormatException;
39
40 import org.opendaylight.controller.sal.utils.ServiceHelper;
41
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45 @Path("/")
46 public class AltoNorthbound {
47
48     private static final Logger logger = LoggerFactory.getLogger(AltoNorthbound.class);
49
50     private RFC7285JSONMapper mapper = new RFC7285JSONMapper();
51
52     private <E> E getService(Class<E> clazz) {
53         E service = (E)ServiceHelper.getGlobalInstance(clazz, this);
54         if (service == null) {
55             service = (E)ServiceHelper.getGlobalInstance(AltoService.class, this);
56         }
57         return service;
58     }
59
60     private void checkService(Object service) throws Exception {
61         if (service == null)
62             throw new AltoBasicException(Status.SERVICE_UNAVAILABLE, null);
63     }
64
65     private void checkResourceId(String rid) throws AltoBadFormatException {
66         if (!FormatValidator.validResourceId(rid))
67             throw new AltoBadFormatException("resource-id", rid);
68     }
69
70     private void checkTag(String tag) throws AltoBadFormatException {
71         if (!FormatValidator.validTag(tag))
72             throw new AltoBadFormatException("tag", tag);
73     }
74
75     private Response fail(Response.Status status, Object data) {
76         try {
77             String output = (data == null ? "" : mapper.asJSON(data));
78             return Response.status(status)
79                         .entity(output)
80                         .type(MediaType.ALTO_ERROR).build();
81         } catch (Exception e) {
82             logger.error("Failed to parse object to json: {}", data.toString());
83             return Response.status(status)
84                         .type(MediaType.ALTO_ERROR).build();
85         }
86     }
87
88     private Response success(Object data, String mediaType) {
89         try {
90             String output = mapper.asJSON(data);
91             return Response.ok(output, mediaType).build();
92         } catch (Exception e) {
93             logger.error("Failed to parse object to json: {}", data.toString());
94             return fail(Status.INTERNAL_SERVER_ERROR, null);
95         }
96     }
97
98     @GET
99     @Produces({ MediaType.ALTO_DIRECTORY, MediaType.ALTO_ERROR })
100     public Response retrieveIRD() throws Exception {
101         IRDService service = getService(IRDService.class);
102         checkService(service);
103
104         RFC7285IRD ird = service.getDefaultIRD();
105         if (ird == null)
106             return fail(Status.NOT_FOUND, null);
107         return success(ird, MediaType.ALTO_DIRECTORY);
108     }
109
110     @Path("/ird/{id}")
111     @GET
112     @Produces({ MediaType.ALTO_DIRECTORY, MediaType.ALTO_ERROR })
113     public Response retrieveIRD(
114             @PathParam("id") String id) throws Exception {
115         IRDService service = getService(IRDService.class);
116         checkService(service);
117         checkResourceId(id);
118
119         RFC7285IRD ird = service.getIRD(id);
120         if (ird == null)
121             return fail(Status.NOT_FOUND, id);
122         return success(ird, MediaType.ALTO_DIRECTORY);
123     }
124
125     @Path("/networkmap")
126     @GET
127     @Produces({ MediaType.ALTO_NETWORKMAP, MediaType.ALTO_ERROR })
128     public Response retrieveDefaultNetworkMap() throws Exception {
129         NetworkMapService service = getService(NetworkMapService.class);
130         checkService(service);
131
132         RFC7285NetworkMap map = service.getDefaultNetworkMap();
133         if (map == null)
134             return fail(Status.NOT_FOUND, null);
135         return success(map, MediaType.ALTO_NETWORKMAP);
136     }
137
138     @Path("/networkmap/{id}")
139     @GET
140     @Produces({ MediaType.ALTO_NETWORKMAP, MediaType.ALTO_ERROR })
141     public Response retrieveNetworkMap(
142             @PathParam("id") String id) throws Exception {
143         NetworkMapService service = getService(NetworkMapService.class);
144         checkService(service);
145         checkResourceId(id);
146
147         RFC7285NetworkMap map = service.getNetworkMap(id);
148         if (map == null)
149             return fail(Status.NOT_FOUND, id);
150         return success(map, MediaType.ALTO_NETWORKMAP);
151     }
152
153     @Path("/networkmap/{id}/{tag}")
154     @GET
155     @Produces({ MediaType.ALTO_NETWORKMAP, MediaType.ALTO_ERROR })
156     public Response retrieveNetworkMap(
157             @PathParam("id") String id,
158             @PathParam("tag") String tag) throws Exception {
159         NetworkMapService service = getService(NetworkMapService.class);
160         checkService(service);
161         checkResourceId(id);
162         checkTag(tag);
163
164         RFC7285VersionTag vtag = new RFC7285VersionTag(id, tag);
165         RFC7285NetworkMap map = service.getNetworkMap(vtag);
166         if (map == null)
167             return fail(Status.NOT_FOUND, vtag);
168         return success(map, MediaType.ALTO_NETWORKMAP);
169     }
170
171     @Path("/costmap/{id}")
172     @GET
173     @Produces({ MediaType.ALTO_COSTMAP, MediaType.ALTO_ERROR})
174     public Response retrieveCostMap(@PathParam("id") String id) throws Exception {
175         CostMapService service = getService(CostMapService.class);
176         checkService(service);
177         checkResourceId(id);
178
179         RFC7285CostMap map = service.getCostMap(id);
180         if (map == null)
181             return fail(Status.NOT_FOUND, id);
182         return success(map, MediaType.ALTO_COSTMAP);
183     }
184
185     @Path("/costmap/{id}/{tag}")
186     @GET
187     @Produces({ MediaType.ALTO_COSTMAP, MediaType.ALTO_ERROR})
188     public Response retrieveCostMap(
189             @PathParam("id") String id,
190             @PathParam("tag") String tag) throws Exception {
191         CostMapService service = getService(CostMapService.class);
192         checkService(service);
193         checkResourceId(id);
194         checkTag(tag);
195
196         RFC7285VersionTag vtag = new RFC7285VersionTag(id, tag);
197         RFC7285CostMap map = service.getCostMap(vtag);
198         if (map == null)
199             return fail(Status.NOT_FOUND, vtag);
200         return success(map, MediaType.ALTO_COSTMAP);
201     }
202
203     @Path("/costmap/{id}/{mode}/{metric}")
204     @GET
205     @Produces({ MediaType.ALTO_COSTMAP, MediaType.ALTO_ERROR})
206     public Response retrieveCostMap(
207             @PathParam("id") String id,
208             @PathParam("mode") String mode,
209             @PathParam("metric") String metric) throws Exception {
210         CostMapService service = getService(CostMapService.class);
211         checkService(service);
212         checkResourceId(id);
213
214         RFC7285CostType costType = new RFC7285CostType(mode, metric);
215         if (!service.supportCostType(id, costType))
216             return fail(Status.NOT_FOUND, costType);
217         RFC7285CostMap map = service.getCostMap(id, costType);
218         if (map == null)
219             return fail(Status.NOT_FOUND, id);
220         return success(map, MediaType.ALTO_COSTMAP);
221     }
222
223     @Path("/costmap/{id}/{tag}/{mode}/{metric}")
224     @GET
225     @Produces({ MediaType.ALTO_COSTMAP, MediaType.ALTO_ERROR})
226     public Response retrieveCostMap(
227             @PathParam("id") String id,
228             @PathParam("tag") String tag,
229             @PathParam("mode") String mode,
230             @PathParam("metric") String metric) throws Exception {
231         CostMapService service = getService(CostMapService.class);
232         checkService(service);
233         checkResourceId(id);
234         checkTag(tag);
235
236         RFC7285VersionTag vtag = new RFC7285VersionTag(id, tag);
237         RFC7285CostType costType = new RFC7285CostType(mode, metric);
238         if (!service.supportCostType(vtag, costType))
239             return fail(Status.NOT_FOUND, costType);
240         RFC7285CostMap map = service.getCostMap(vtag, costType);
241         if (map == null)
242             return fail(Status.NOT_FOUND, vtag);
243         return success(map, MediaType.ALTO_COSTMAP);
244     }
245
246     @Path("/filtered/networkmap/{id}")
247     @POST
248     @Consumes({ MediaType.ALTO_NETWORKMAP_FILTER})
249     @Produces({ MediaType.ALTO_NETWORKMAP, MediaType.ALTO_ERROR})
250     public Response retrieveFilteredNetworkMap(
251             @PathParam("id") String id, String filterJSON) throws Exception {
252         NetworkMapService service = getService(NetworkMapService.class);
253         checkService(service);
254         checkResourceId(id);
255
256         RFC7285NetworkMap.Filter filter = mapper.asNetworkMapFilter(filterJSON);
257
258         if (!service.validateNetworkMapFilter(id, filter))
259             return fail(Status.BAD_REQUEST, filter);
260         RFC7285NetworkMap map = service.getNetworkMap(id, filter);
261         if (map == null)
262             return fail(Status.NOT_FOUND, id);
263         return success(map, MediaType.ALTO_NETWORKMAP);
264     }
265
266     @Path("/filtered/networkmap/{id}/{tag}")
267     @POST
268     @Consumes({ MediaType.ALTO_NETWORKMAP_FILTER})
269     @Produces({ MediaType.ALTO_NETWORKMAP, MediaType.ALTO_ERROR})
270     public Response retrieveFilteredNetworkMap(
271             @PathParam("id") String id,
272             @PathParam("tag") String tag,
273             String filterJSON) throws Exception {
274         NetworkMapService service = getService(NetworkMapService.class);
275         checkService(service);
276         checkResourceId(id);
277         checkTag(tag);
278
279         RFC7285VersionTag vtag = new RFC7285VersionTag(id, tag);
280         RFC7285NetworkMap.Filter filter = mapper.asNetworkMapFilter(filterJSON);
281         if (!service.validateNetworkMapFilter(vtag, filter))
282             return fail(Status.BAD_REQUEST, filter);
283
284         RFC7285NetworkMap map = service.getNetworkMap(vtag, filter);
285         if (map == null)
286             return fail(Status.NOT_FOUND, vtag);
287         return success(map, MediaType.ALTO_NETWORKMAP);
288     }
289
290     @Path("/filtered/costmap/{id}")
291     @POST
292     @Consumes({ MediaType.ALTO_COSTMAP_FILTER })
293     @Produces({ MediaType.ALTO_COSTMAP, MediaType.ALTO_ERROR})
294     public Response retrieveFilteredCostMap(
295             @PathParam("id") String id, String filterJSON) throws Exception {
296         CostMapService service = getService(CostMapService.class);
297         checkService(service);
298         checkResourceId(id);
299
300         RFC7285CostMap.Filter filter = mapper.asCostMapFilter(filterJSON);
301         if (!service.validateCostMapFilter(id, filter))
302             return fail(Status.BAD_REQUEST, filter);
303
304         RFC7285CostMap map = service.getCostMap(id, filter);
305         if (map == null)
306             return fail(Status.NOT_FOUND, id);
307         return success(map, MediaType.ALTO_COSTMAP);
308     }
309
310     @Path("/filtered/costmap/{id}/{tag}")
311     @POST
312     @Consumes({ MediaType.ALTO_COSTMAP_FILTER })
313     @Produces({ MediaType.ALTO_COSTMAP, MediaType.ALTO_ERROR})
314     public Response retrieveFilteredCostMap(
315             @PathParam("id") String id,
316             @PathParam("tag") String tag, String filterJSON) throws Exception {
317         CostMapService service = getService(CostMapService.class);
318         checkService(service);
319         checkResourceId(id);
320         checkTag(tag);
321
322         RFC7285VersionTag vtag = new RFC7285VersionTag(id, tag);
323         RFC7285CostMap.Filter filter = mapper.asCostMapFilter(filterJSON);
324         if (!service.validateCostMapFilter(vtag, filter))
325             return fail(Status.BAD_REQUEST, filter);
326
327         RFC7285CostMap map = service.getCostMap(vtag, filter);
328         if (map == null)
329             return fail(Status.NOT_FOUND, vtag);
330         return success(map, MediaType.ALTO_COSTMAP);
331     }
332
333     @Path("/endpointprop/lookup/{id}")
334     @POST
335     @Consumes({ MediaType.ALTO_ENDPOINT_PROPPARAMS })
336     @Produces({ MediaType.ALTO_ENDPOINT_PROP, MediaType.ALTO_ERROR })
337     public Response retrieveEndpointPropMap(
338             @PathParam("id") String id,
339             String params) throws Exception {
340         EndpointPropertyService service = getService(EndpointPropertyService.class);
341         checkService(service);
342         checkResourceId(id);
343
344         RFC7285Endpoint.PropertyRequest request = mapper.asPropertyRequest(params);
345         RFC7285Endpoint.PropertyResponse response = service.getEndpointProperty(id, request);
346         if (response == null)
347             return fail(Status.NOT_FOUND, request);
348         return success(response, MediaType.ALTO_ENDPOINT_PROP);
349     }
350
351     @Path("/endpointprop/lookup/{id}/{tag}")
352     @POST
353     @Consumes({ MediaType.ALTO_ENDPOINT_PROPPARAMS })
354     @Produces({ MediaType.ALTO_ENDPOINT_PROP, MediaType.ALTO_ERROR })
355     public Response retrieveEndpointPropMap(
356             @PathParam("id") String id,
357             @PathParam("tag") String tag,
358             String params) throws Exception {
359         EndpointPropertyService service = getService(EndpointPropertyService.class);
360         checkService(service);
361         checkResourceId(id);
362         checkTag(tag);
363
364         RFC7285VersionTag vtag = new RFC7285VersionTag(id, tag);
365         RFC7285Endpoint.PropertyRequest request = mapper.asPropertyRequest(params);
366         RFC7285Endpoint.PropertyResponse response = service.getEndpointProperty(vtag, request);
367         if (response == null)
368             return fail(Status.NOT_FOUND, request);
369         return success(response, MediaType.ALTO_ENDPOINT_PROP);
370     }
371
372     @Path("/endpointcost/lookup/{id}")
373     @POST
374     @Consumes({ MediaType.ALTO_ENDPOINT_COSTPARAMS })
375     @Produces({ MediaType.ALTO_ENDPOINT_COST, MediaType.ALTO_ERROR })
376     public Response retrieveEndpointCostMap(
377             @PathParam("id") String id,
378             String params) throws Exception {
379         EndpointCostService service = getService(EndpointCostService.class);
380         checkService(service);
381         checkResourceId(id);
382
383         RFC7285Endpoint.CostRequest request = mapper.asCostRequest(params);
384         RFC7285Endpoint.CostResponse response = service.getEndpointCost(id, request);
385         if (response == null)
386             return fail(Status.NOT_FOUND, request);
387         return success(response, MediaType.ALTO_ENDPOINT_COST);
388     }
389
390     @Path("/endpointcost/lookup/{id}/{tag}")
391     @POST
392     @Consumes({ MediaType.ALTO_ENDPOINT_COSTPARAMS })
393     @Produces({ MediaType.ALTO_ENDPOINT_COST, MediaType.ALTO_ERROR })
394     public Response retrieveEndpointCostMap(
395             @PathParam("id") String id,
396             @PathParam("tag") String tag,
397             String params) throws Exception {
398         EndpointCostService service = getService(EndpointCostService.class);
399         checkService(service);
400         checkResourceId(id);
401         checkTag(tag);
402
403         RFC7285VersionTag vtag = new RFC7285VersionTag(id, tag);
404         RFC7285Endpoint.CostRequest request = mapper.asCostRequest(params);
405         RFC7285Endpoint.CostResponse response = service.getEndpointCost(vtag, request);
406         if (response == null)
407             return fail(Status.NOT_FOUND, request);
408         return success(response, MediaType.ALTO_ENDPOINT_COST);
409     }
410 }