Add swagger docs for gizmo APIs
[aai/gizmo.git] / src / main / java / org / onap / crud / service / CrudRestService.java
1 /**
2  * ============LICENSE_START=======================================================
3  * org.onap.aai
4  * ================================================================================
5  * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6  * Copyright © 2017-2018 Amdocs
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *       http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21 package org.onap.crud.service;
22
23 import java.security.cert.X509Certificate;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.List;
29 import java.util.Map;
30
31 import javax.security.auth.x500.X500Principal;
32 import javax.servlet.http.HttpServletRequest;
33 import javax.ws.rs.Consumes;
34 import javax.ws.rs.DELETE;
35 import javax.ws.rs.Encoded;
36 import javax.ws.rs.GET;
37 import javax.ws.rs.POST;
38 import javax.ws.rs.PUT;
39 import javax.ws.rs.Path;
40 import javax.ws.rs.PathParam;
41 import javax.ws.rs.Produces;
42 import javax.ws.rs.core.Context;
43 import javax.ws.rs.core.EntityTag;
44 import javax.ws.rs.core.HttpHeaders;
45 import javax.ws.rs.core.MediaType;
46 import javax.ws.rs.core.Response;
47 import javax.ws.rs.core.Response.ResponseBuilder;
48 import javax.ws.rs.core.Response.Status;
49 import javax.ws.rs.core.UriInfo;
50
51 import org.apache.commons.lang3.tuple.ImmutablePair;
52 import org.apache.cxf.jaxrs.ext.PATCH;
53 import org.onap.aai.cl.api.Logger;
54 import org.onap.aai.cl.eelf.LoggerFactory;
55 import org.onap.aaiauth.auth.Auth;
56 import org.onap.crud.exception.CrudException;
57 import org.onap.crud.logging.CrudServiceMsgs;
58 import org.onap.crud.logging.LoggingUtil;
59 import org.onap.crud.parser.BulkPayload;
60 import org.onap.crud.parser.EdgePayload;
61 import org.onap.crud.parser.VertexPayload;
62 import org.onap.crud.util.CrudProperties;
63 import org.onap.crud.util.CrudServiceConstants;
64 import org.onap.crud.util.CrudServiceUtil;
65 import org.slf4j.MDC;
66
67 import com.google.gson.JsonElement;
68
69 import io.swagger.annotations.ApiImplicitParam;
70 import io.swagger.annotations.ApiImplicitParams;
71 import io.swagger.annotations.ApiOperation;
72 import io.swagger.annotations.ApiParam;
73 import io.swagger.annotations.ApiResponse;
74 import io.swagger.annotations.ApiResponses;
75
76 @Path("/inventory")
77 public class CrudRestService {
78
79     private AbstractGraphDataService graphDataService;
80     Logger logger = LoggerFactory.getInstance().getLogger(CrudRestService.class.getName());
81     Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(CrudRestService.class.getName());
82     private Auth auth;
83
84     private String mediaType = MediaType.APPLICATION_JSON;
85     public static final String HTTP_PATCH_METHOD_OVERRIDE = "X-HTTP-Method-Override";
86     public static final String TRANSACTIONID_HEADER = "X-TransactionId";
87
88     public CrudRestService(AbstractGraphDataService graphDataService) throws Exception {
89         this.graphDataService = graphDataService;
90         this.auth = new Auth(CrudServiceConstants.CRD_AUTH_FILE);
91     }
92
93     // For unit testing
94     public CrudRestService(AbstractGraphDataService graphDataService, Auth auth) throws Exception {
95         this.graphDataService = graphDataService;
96         this.auth = auth;
97     }
98
99     public enum Action {
100         POST, GET, PUT, DELETE, PATCH
101     }
102
103     public void startup() {
104
105     }
106     
107     @ApiOperation(value = "Get Vertex" , notes="For example : https://<host>:9520/services/inventory/v11/pserver/<id>")
108     @ApiResponses({    
109       @ApiResponse(code = 200, message = "Success"),
110       @ApiResponse(code = 403, message = "Forbidden"),    
111       @ApiResponse(code = 404, message = "Not Found"),
112       @ApiResponse(code = 500, message = "Internal Server Error") })
113     @ApiImplicitParams({
114       @ApiImplicitParam(name = "X-FromAppId", required = true, dataType = "string", paramType = "header"),
115       @ApiImplicitParam(name = "X-TransactionId",  required = true, dataType = "string", paramType = "header"),    
116     })
117     @GET
118     @Path("/{version}/{type}/{id}")
119     @Consumes({MediaType.APPLICATION_JSON})
120     @Produces({MediaType.APPLICATION_JSON})
121     public Response getVertex(@ApiParam(hidden=true) String content, @PathParam("version") @ApiParam(value="oxm model version",defaultValue="v13") String version, @PathParam("type") String type,
122             @PathParam("id") String id, @PathParam("uri") @Encoded @ApiParam(hidden=true) String uri, @Context HttpHeaders headers,
123             @Context UriInfo uriInfo, @Context HttpServletRequest req) {
124
125         LoggingUtil.initMdcContext(req, headers);
126         logger.debug("Incoming request..." + content);
127
128         ResponseBuilder responseBuilder;
129         Map<String, String> params = addParams(uriInfo, false, type, version);
130
131         try {
132             if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
133                 ImmutablePair<EntityTag, String> result = graphDataService.getVertex(version, id, type, params);
134                 responseBuilder =
135                         Response.status(Status.OK).entity(result.getValue()).tag(result.getKey()).type(mediaType);
136             } else {
137                 responseBuilder = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON);
138             }
139         } catch (CrudException ce) {
140             responseBuilder = Response.status(ce.getHttpStatus()).entity(ce.getMessage());
141         } catch (Exception e) {
142             responseBuilder = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage());
143
144         }
145
146         setTxIdOnResponseHeader(headers, responseBuilder);
147
148         Response response = responseBuilder.build();
149         LoggingUtil.logRestRequest(logger, auditLogger, req, response);
150         return response;
151     }
152
153     @ApiOperation(value = "Get Vertices" , notes="For example : https://<host>:9520/services/inventory/v11/pserver/")
154     @ApiResponses({    
155       @ApiResponse(code = 200, message = "Success"),
156       @ApiResponse(code = 403, message = "Forbidden"),    
157       @ApiResponse(code = 404, message = "Not Found"),
158       @ApiResponse(code = 500, message = "Internal Server Error") })
159     @ApiImplicitParams({
160       @ApiImplicitParam(name = "X-FromAppId", required = true, dataType = "string", paramType = "header"),    
161       @ApiImplicitParam(name = "X-TransactionId",  required = true, dataType = "string", paramType = "header"),    
162     })
163     @GET
164     @Path("/{version}/{type}/")
165     @Consumes({MediaType.APPLICATION_JSON})
166     @Produces({MediaType.APPLICATION_JSON})
167     public Response getVertices(@ApiParam(hidden=true) String content, @PathParam("version") @ApiParam(value="oxm model version",defaultValue="v13") String version, @PathParam("type") String type,
168             @PathParam("uri") @Encoded @ApiParam(hidden=true) String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
169             @Context HttpServletRequest req) {
170
171         LoggingUtil.initMdcContext(req, headers);
172         logger.debug("Incoming request..." + content);
173
174         ResponseBuilder responseBuilder;
175         try {
176             if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
177                 String propertiesKey = CrudProperties.get(CrudServiceConstants.CRD_COLLECTION_PROPERTIES_KEY);
178                 Map<String, String> filter = addParams(uriInfo, true, type, version);
179
180                 HashSet<String> properties;
181                 if (uriInfo.getQueryParameters().containsKey(propertiesKey)) {
182                     properties = new HashSet<>(uriInfo.getQueryParameters().get(propertiesKey));
183                 } else {
184                     properties = new HashSet<>();
185                 }
186
187                 ImmutablePair<EntityTag, String> result =
188                         graphDataService.getVertices(version, type, filter, properties);
189                 responseBuilder =
190                         Response.status(Status.OK).entity(result.getValue()).tag(result.getKey()).type(mediaType);
191             } else {
192                 responseBuilder = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON);
193             }
194         } catch (CrudException ce) {
195             responseBuilder = Response.status(ce.getHttpStatus()).entity(ce.getMessage());
196         } catch (Exception e) {
197             responseBuilder = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage());
198
199         }
200
201         setTxIdOnResponseHeader(headers, responseBuilder);
202
203         Response response = responseBuilder.build();
204         LoggingUtil.logRestRequest(logger, auditLogger, req, response);
205         return response;
206     }
207
208     @ApiOperation(value = "Get Edge" , notes="For example : https://<host>:9520/services/inventory/relationships/v11/tosca.relationships.HostedOn/<id>")
209     @ApiResponses({    
210       @ApiResponse(code = 200, message = "Success"),
211       @ApiResponse(code = 403, message = "Forbidden"),    
212       @ApiResponse(code = 404, message = "Not Found"),
213       @ApiResponse(code = 500, message = "Internal Server Error") })
214     @ApiImplicitParams({
215       @ApiImplicitParam(name = "X-FromAppId", required = true, dataType = "string", paramType = "header"),
216       @ApiImplicitParam(name = "X-TransactionId",  required = true, dataType = "string", paramType = "header"),    
217     })
218     @GET
219     @Path("/relationships/{version}/{type}/{id}")
220     @Consumes({MediaType.APPLICATION_JSON})
221     @Produces({MediaType.APPLICATION_JSON})
222     public Response getEdge(@ApiParam(hidden=true) String content, @PathParam("version") @ApiParam(value="oxm model version",defaultValue="v13") String version, @PathParam("type") String type,
223             @PathParam("id") String id, @PathParam("uri") @Encoded @ApiParam(hidden=true) String uri, @Context HttpHeaders headers,
224             @Context UriInfo uriInfo, @Context HttpServletRequest req) {
225
226         LoggingUtil.initMdcContext(req, headers);
227         logger.debug("Incoming request..." + content);
228
229         ResponseBuilder responseBuilder;
230         Map<String, String> params = addParams(uriInfo, false, type, version);
231
232         try {
233             if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
234
235                 ImmutablePair<EntityTag, String> result = graphDataService.getEdge(version, id, type, params);
236                 responseBuilder =
237                         Response.status(Status.OK).entity(result.getValue()).tag(result.getKey()).type(mediaType);
238             } else {
239                 responseBuilder = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON);
240             }
241         } catch (CrudException ce) {
242             responseBuilder = Response.status(ce.getHttpStatus()).entity(ce.getMessage());
243         } catch (Exception e) {
244             responseBuilder = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage());
245         }
246
247         setTxIdOnResponseHeader(headers, responseBuilder);
248
249         Response response = responseBuilder.build();
250         LoggingUtil.logRestRequest(logger, auditLogger, req, response);
251         return response;
252     }
253
254     @ApiOperation(value = "Get Edges" , notes="For example : https://<host>:9520/services/inventory/relationships/v11/tosca.relationships.HostedOn/")
255     @ApiResponses({    
256       @ApiResponse(code = 200, message = "Success"),
257       @ApiResponse(code = 403, message = "Forbidden"),    
258       @ApiResponse(code = 404, message = "Not Found"),
259       @ApiResponse(code = 500, message = "Internal Server Error") })
260     @ApiImplicitParams({
261       @ApiImplicitParam(name = "X-FromAppId", required = true, dataType = "string", paramType = "header"),
262       @ApiImplicitParam(name = "X-TransactionId",  required = true, dataType = "string", paramType = "header"),    
263     })
264     @GET
265     @Path("/relationships/{version}/{type}/")
266     @Consumes({MediaType.APPLICATION_JSON})
267     @Produces({MediaType.APPLICATION_JSON})
268     public Response getEdges(@ApiParam(hidden=true) String content, @PathParam("version") @ApiParam(value="oxm model version",defaultValue="v13") String version, @PathParam("type") String type,
269             @PathParam("uri") @Encoded @ApiParam(hidden=true) String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
270             @Context HttpServletRequest req) {
271
272         LoggingUtil.initMdcContext(req, headers);
273         logger.debug("Incoming request..." + content);
274
275         ResponseBuilder responseBuilder;
276         Map<String, String> filter = addParams(uriInfo, true, type, version);
277
278         try {
279             if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
280                 ImmutablePair<EntityTag, String> result = graphDataService.getEdges(version, type, filter);
281                 responseBuilder =
282                         Response.status(Status.OK).entity(result.getValue()).tag(result.getKey()).type(mediaType);
283             } else {
284                 responseBuilder = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON);
285             }
286         } catch (CrudException ce) {
287             responseBuilder = Response.status(ce.getHttpStatus()).entity(ce.getMessage());
288         } catch (Exception e) {
289             responseBuilder = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage());
290         }
291
292         setTxIdOnResponseHeader(headers, responseBuilder);
293
294         Response response = responseBuilder.build();
295         LoggingUtil.logRestRequest(logger, auditLogger, req, response);
296         return response;
297     }
298
299     @ApiOperation(value = "Update Edge" , notes = "# Payload \n"
300         + "{  \r\n" + 
301         "   \"properties\":{  \r\n" + 
302         "        \"prop1\" : \"value\",\r\n" + 
303         "        \"prop2\" :\"value\",\r\n" +  
304         "    ..}\r\n" + 
305         " }")
306     @ApiResponses({    
307       @ApiResponse(code = 200, message = "Success"),
308       @ApiResponse(code = 403, message = "Forbidden"),    
309       @ApiResponse(code = 404, message = "Not Found"),
310       @ApiResponse(code = 400, message = "Bad Request"),
311       @ApiResponse(code = 500, message = "Internal Server Error") })
312     @ApiImplicitParams({
313       @ApiImplicitParam(name = "X-FromAppId", required = true, dataType = "string", paramType = "header"),
314       @ApiImplicitParam(name = "X-TransactionId",  required = true, dataType = "string", paramType = "header"),    
315     })
316     @PUT
317     @Path("/relationships/{version}/{type}/{id}")
318     @Consumes({MediaType.APPLICATION_JSON})
319     @Produces({MediaType.APPLICATION_JSON})
320     public Response updateEdge(String content, @PathParam("version") @ApiParam(value="oxm model version",defaultValue="v13") String version, @PathParam("type") String type,
321             @PathParam("id") String id, @PathParam("uri") @Encoded @ApiParam(hidden=true) String uri, @Context HttpHeaders headers,
322             @Context UriInfo uriInfo, @Context HttpServletRequest req) {
323
324         LoggingUtil.initMdcContext(req, headers);
325         logger.debug("Incoming request..." + content);
326
327         ResponseBuilder responseBuilder;
328
329         try {
330             if (validateRequest(req, uri, content, Action.PUT, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
331                 EdgePayload payload = EdgePayload.fromJson(content);
332                 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
333                     throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
334                 }
335                 if (payload.getId() != null && !payload.getId().equals(id)) {
336                     throw new CrudException("ID Mismatch", Status.BAD_REQUEST);
337                 }
338                 ImmutablePair<EntityTag, String> result;
339                 if (headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE) != null
340                         && headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE).equalsIgnoreCase("PATCH")) {
341                     result = graphDataService.patchEdge(version, id, type, payload);
342                     responseBuilder =
343                             Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey());
344                 } else {
345                     result = graphDataService.updateEdge(version, id, type, payload);
346                     responseBuilder =
347                             Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey());
348                 }
349
350             } else {
351                 responseBuilder = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON);
352             }
353         } catch (CrudException ce) {
354             responseBuilder = Response.status(ce.getHttpStatus()).entity(ce.getMessage());
355         } catch (Exception e) {
356             responseBuilder = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage());
357         }
358
359         setTxIdOnResponseHeader(headers, responseBuilder);
360
361         Response response = responseBuilder.build();
362         LoggingUtil.logRestRequest(logger, auditLogger, req, response);
363         return response;
364     }
365
366     @ApiOperation(value = "Patch Edge" , notes = "# Payload \n"
367         + "{  \r\n" + 
368         "   \"properties\":{  \r\n" + 
369         "        \"prop1\" : \"value\",\r\n" + 
370         "        \"prop2\" :\"value\",\r\n" +  
371         "    ..}\r\n" + 
372         " }")
373     @ApiResponses({    
374       @ApiResponse(code = 200, message = "Success"),
375       @ApiResponse(code = 403, message = "Forbidden"), 
376       @ApiResponse(code = 400, message = "Bad Request"),
377       @ApiResponse(code = 404, message = "Not Found"),
378       @ApiResponse(code = 500, message = "Internal Server Error") })
379     @ApiImplicitParams({
380       @ApiImplicitParam(name = "X-FromAppId", required = true, dataType = "string", paramType = "header"),
381       @ApiImplicitParam(name = "X-TransactionId",  required = true, dataType = "string", paramType = "header"),    
382     })
383     @PATCH
384     @Path("/relationships/{version}/{type}/{id}")
385     @Consumes({"application/merge-patch+json"})
386     @Produces({MediaType.APPLICATION_JSON})
387     public Response patchEdge(String content, @PathParam("version") @ApiParam(value="oxm model version",defaultValue="v13") String version, @PathParam("type") String type,
388             @PathParam("id") String id, @PathParam("uri") @Encoded @ApiParam(hidden=true) String uri, @Context HttpHeaders headers,
389             @Context UriInfo uriInfo, @Context HttpServletRequest req) {
390
391         LoggingUtil.initMdcContext(req, headers);
392         logger.debug("Incoming request..." + content);
393
394         ResponseBuilder responseBuilder;
395
396         try {
397             if (validateRequest(req, uri, content, Action.PATCH, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
398                 EdgePayload payload = EdgePayload.fromJson(content);
399                 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
400                     throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
401                 }
402                 if (payload.getId() != null && !payload.getId().equals(id)) {
403                     throw new CrudException("ID Mismatch", Status.BAD_REQUEST);
404                 }
405
406                 ImmutablePair<EntityTag, String> result = graphDataService.patchEdge(version, id, type, payload);
407                 responseBuilder =
408                         Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey());
409             } else {
410                 responseBuilder = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON);
411             }
412         } catch (CrudException ce) {
413             responseBuilder = Response.status(ce.getHttpStatus()).entity(ce.getMessage());
414         } catch (Exception e) {
415             responseBuilder = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage());
416         }
417
418         setTxIdOnResponseHeader(headers, responseBuilder);
419
420         Response response = responseBuilder.build();
421         LoggingUtil.logRestRequest(logger, auditLogger, req, response);
422         return response;
423     }
424
425     @ApiOperation(value = "Update Vertex" , notes = "# Payload \n"
426         + "{\r\n" + 
427         "   \"type\" :\"vertex type from oxm like comcast.nodes.sdwan.vpn\",\r\n" + 
428         "    \"properties\": {\r\n" + 
429         "        \"prop1\" : \"value\",\r\n" + 
430         "        \"prop2\" :\"value\",\r\n" +          
431         "    ..}\r\n" + 
432         " }")
433     @ApiResponses({    
434       @ApiResponse(code = 200, message = "Success"),
435       @ApiResponse(code = 403, message = "Forbidden"), 
436       @ApiResponse(code = 400, message = "Bad Request"),
437       @ApiResponse(code = 404, message = "Not Found"),
438       @ApiResponse(code = 500, message = "Internal Server Error") })
439     @ApiImplicitParams({
440       @ApiImplicitParam(name = "X-FromAppId", required = true, dataType = "string", paramType = "header"),
441       @ApiImplicitParam(name = "X-TransactionId",  required = true, dataType = "string", paramType = "header"),    
442     })
443     @PUT
444     @Path("/{version}/{type}/{id}")
445     @Consumes({MediaType.APPLICATION_JSON})
446     @Produces({MediaType.APPLICATION_JSON})
447     public Response updateVertex(String content, @PathParam("version") @ApiParam(value="oxm model version",defaultValue="v13") String version, @PathParam("type") String type,
448             @PathParam("id") String id, @PathParam("uri") @Encoded @ApiParam(hidden=true) String uri, @Context HttpHeaders headers,
449             @Context UriInfo uriInfo, @Context HttpServletRequest req) {
450
451         LoggingUtil.initMdcContext(req, headers);
452         logger.debug("Incoming request..." + content);
453
454         ResponseBuilder responseBuilder;
455
456         try {
457             if (validateRequest(req, uri, content, Action.PUT, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
458                 VertexPayload payload = VertexPayload.fromJson(content);
459                 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
460                     throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
461                 }
462                 if (payload.getId() != null && !payload.getId().equals(id)) {
463                     throw new CrudException("ID Mismatch", Status.BAD_REQUEST);
464                 }
465
466                 payload.setProperties(
467                         CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, false));
468
469                 ImmutablePair<EntityTag, String> result;
470                 if (headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE) != null
471                         && headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE).equalsIgnoreCase("PATCH")) {
472                     result = graphDataService.patchVertex(version, id, type, payload);
473                     responseBuilder =
474                             Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey());
475                 } else {
476                     result = graphDataService.updateVertex(version, id, type, payload);
477                     responseBuilder =
478                             Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey());
479                 }
480
481             } else {
482                 responseBuilder = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON);
483             }
484         } catch (CrudException ce) {
485             responseBuilder = Response.status(ce.getHttpStatus()).entity(ce.getMessage());
486         } catch (Exception e) {
487             responseBuilder = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage());
488         }
489
490         setTxIdOnResponseHeader(headers, responseBuilder);
491
492         Response response = responseBuilder.build();
493         LoggingUtil.logRestRequest(logger, auditLogger, req, response);
494         return response;
495     }
496
497     @ApiOperation(value = "Patch Vertex" , notes = "# Payload \n"
498         + "{\r\n" + 
499         "   \"type\" :\"vertex type from oxm like comcast.nodes.sdwan.vpn\",\r\n" + 
500         "    \"properties\": {\r\n" + 
501         "        \"prop1\" : \"true\",\r\n" + 
502         "        \"prop2\" :\"name1\",\r\n" +         
503         "    ..}\r\n" + 
504         " }")
505     @ApiResponses({    
506       @ApiResponse(code = 200, message = "Success"),
507       @ApiResponse(code = 403, message = "Forbidden"), 
508       @ApiResponse(code = 400, message = "Bad Request"),
509       @ApiResponse(code = 404, message = "Not Found"),
510       @ApiResponse(code = 500, message = "Internal Server Error") })
511     @ApiImplicitParams({
512       @ApiImplicitParam(name = "X-FromAppId", required = true, dataType = "string", paramType = "header"),
513       @ApiImplicitParam(name = "X-TransactionId",  required = true, dataType = "string", paramType = "header"),    
514     })
515     @PATCH
516     @Path("/{version}/{type}/{id}")
517     @Consumes({"application/merge-patch+json"})
518     @Produces({MediaType.APPLICATION_JSON})
519     public Response patchVertex(String content, @PathParam("version") @ApiParam(value="oxm model version",defaultValue="v13") String version, @PathParam("type") String type,
520             @PathParam("id") String id, @PathParam("uri") @Encoded @ApiParam(hidden=true) String uri, @Context HttpHeaders headers,
521             @Context UriInfo uriInfo, @Context HttpServletRequest req) {
522
523         LoggingUtil.initMdcContext(req, headers);
524         logger.debug("Incoming request..." + content);
525
526         ResponseBuilder responseBuilder;
527
528         try {
529             if (validateRequest(req, uri, content, Action.PATCH, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
530                 VertexPayload payload = VertexPayload.fromJson(content);
531                 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
532                     throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
533                 }
534                 if (payload.getId() != null && !payload.getId().equals(id)) {
535                     throw new CrudException("ID Mismatch", Status.BAD_REQUEST);
536                 }
537
538                 payload.setProperties(
539                         CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, false));
540
541                 ImmutablePair<EntityTag, String> result = graphDataService.patchVertex(version, id, type, payload);
542                 responseBuilder =
543                         Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey());
544             } else {
545                 responseBuilder = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON);
546             }
547         } catch (CrudException ce) {
548             responseBuilder = Response.status(ce.getHttpStatus()).entity(ce.getMessage());
549         } catch (Exception e) {
550             responseBuilder = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage());
551         }
552
553         setTxIdOnResponseHeader(headers, responseBuilder);
554
555         Response response = responseBuilder.build();
556         LoggingUtil.logRestRequest(logger, auditLogger, req, response);
557         return response;
558     }
559
560     @ApiOperation(value = "Create Vertex" , notes = "# Payload \n"
561         + "{\r\n" +      
562         "    \"properties\": {\r\n" + 
563         "        \"prop1\" : \"value\",\r\n" + 
564         "        \"prop2\" :\"value\",\r\n" +         
565         "    ..}\r\n" + 
566         " }")
567     @ApiResponses({    
568       @ApiResponse(code = 201, message = "Created"),
569       @ApiResponse(code = 403, message = "Forbidden"), 
570       @ApiResponse(code = 400, message = "Bad Request"),
571       @ApiResponse(code = 404, message = "Not Found"),
572       @ApiResponse(code = 500, message = "Internal Server Error") })
573     @ApiImplicitParams({
574       @ApiImplicitParam(name = "X-FromAppId", required = true, dataType = "string", paramType = "header"),
575       @ApiImplicitParam(name = "X-TransactionId",  required = true, dataType = "string", paramType = "header"),    
576     })
577     @POST
578     @Path("/{version}/{type}/")
579     @Consumes({MediaType.APPLICATION_JSON})
580     @Produces({MediaType.APPLICATION_JSON})
581     public Response addVertex(String content, @PathParam("version") @ApiParam(value="oxm model version",defaultValue="v13") String version, @PathParam("type") String type,
582             @PathParam("uri") @Encoded @ApiParam(hidden=true) String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
583             @Context HttpServletRequest req) {
584
585         LoggingUtil.initMdcContext(req, headers);
586         logger.debug("Incoming request..." + content);
587
588         ResponseBuilder responseBuilder;
589
590         try {
591             if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
592                 VertexPayload payload = VertexPayload.fromJson(content);
593                 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
594                     throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
595                 }
596                 if (payload.getId() != null) {
597                     throw new CrudException("ID specified , use Http PUT to update Vertex", Status.BAD_REQUEST);
598                 }
599
600                 if (payload.getType() != null && !payload.getType().equals(type)) {
601                     throw new CrudException("Vertex Type mismatch", Status.BAD_REQUEST);
602                 }
603
604                 payload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, true));
605
606                 ImmutablePair<EntityTag, String> result = graphDataService.addVertex(version, type, payload);
607                 responseBuilder =
608                         Response.status(Status.CREATED).entity(result.getValue()).tag(result.getKey()).type(mediaType);
609             } else {
610                 responseBuilder = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON);
611             }
612         } catch (CrudException ce) {
613             responseBuilder = Response.status(ce.getHttpStatus()).entity(ce.getMessage());
614         } catch (Exception e) {
615             responseBuilder = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage());
616         }
617
618         setTxIdOnResponseHeader(headers, responseBuilder);
619
620         Response response = responseBuilder.build();
621         LoggingUtil.logRestRequest(logger, auditLogger, req, response);
622         return response;
623     }
624
625     private void validateBulkPayload(BulkPayload payload) throws CrudException {
626         List<String> vertices = new ArrayList<String>();
627         List<String> edges = new ArrayList<String>();
628
629         for (JsonElement v : payload.getObjects()) {
630             List<Map.Entry<String, JsonElement>> entries =
631                     new ArrayList<Map.Entry<String, JsonElement>>(v.getAsJsonObject().entrySet());
632
633             if (entries.size() != 2) {
634                 throw new CrudException("", Status.BAD_REQUEST);
635             }
636             Map.Entry<String, JsonElement> opr = entries.get(0);
637             Map.Entry<String, JsonElement> item = entries.get(1);
638
639             if (vertices.contains(item.getKey())) {
640                 throw new CrudException("duplicate vertex in payload: " + item.getKey(), Status.BAD_REQUEST);
641             }
642             VertexPayload vertexPayload = VertexPayload.fromJson(item.getValue().getAsJsonObject().toString());
643             if (vertexPayload.getType() == null) {
644                 throw new CrudException("Vertex Type cannot be null for: " + item.getKey(), Status.BAD_REQUEST);
645             }
646
647             if (!opr.getKey().equalsIgnoreCase("operation")) {
648                 throw new CrudException("operation missing in item: " + item.getKey(), Status.BAD_REQUEST);
649             }
650
651             if (!opr.getValue().getAsString().equalsIgnoreCase("add")
652                     && !opr.getValue().getAsString().equalsIgnoreCase("modify")
653                     && !opr.getValue().getAsString().equalsIgnoreCase("patch")
654                     && !opr.getValue().getAsString().equalsIgnoreCase("delete")) {
655                 throw new CrudException("Invalid operation at item: " + item.getKey(), Status.BAD_REQUEST);
656             }
657             // check if ID is populate for modify/patch/delete operation
658             if ((opr.getValue().getAsString().equalsIgnoreCase("modify")
659                     || opr.getValue().getAsString().equalsIgnoreCase("patch")
660                     || opr.getValue().getAsString().equalsIgnoreCase("delete")) && (vertexPayload.getId() == null)) {
661
662                 throw new CrudException("Mising ID at item: " + item.getKey(), Status.BAD_REQUEST);
663
664             }
665
666             vertices.add(item.getKey());
667         }
668
669         for (JsonElement v : payload.getRelationships()) {
670             List<Map.Entry<String, JsonElement>> entries =
671                     new ArrayList<Map.Entry<String, JsonElement>>(v.getAsJsonObject().entrySet());
672
673             if (entries.size() != 2) {
674                 throw new CrudException("", Status.BAD_REQUEST);
675             }
676             Map.Entry<String, JsonElement> opr = entries.get(0);
677             Map.Entry<String, JsonElement> item = entries.get(1);
678
679             if (edges.contains(item.getKey())) {
680                 throw new CrudException("duplicate Edge in payload: " + item.getKey(), Status.BAD_REQUEST);
681             }
682
683             EdgePayload edgePayload = EdgePayload.fromJson(item.getValue().getAsJsonObject().toString());
684
685             if (!opr.getKey().equalsIgnoreCase("operation")) {
686                 throw new CrudException("operation missing in item: " + item.getKey(), Status.BAD_REQUEST);
687             }
688
689             if (!opr.getValue().getAsString().equalsIgnoreCase("add")
690                     && !opr.getValue().getAsString().equalsIgnoreCase("modify")
691                     && !opr.getValue().getAsString().equalsIgnoreCase("patch")
692                     && !opr.getValue().getAsString().equalsIgnoreCase("delete")) {
693                 throw new CrudException("Invalid operation at item: " + item.getKey(), Status.BAD_REQUEST);
694             }
695             // check if ID is populate for modify/patch/delete operation
696             if ((edgePayload.getId() == null) && (opr.getValue().getAsString().equalsIgnoreCase("modify")
697                     || opr.getValue().getAsString().equalsIgnoreCase("patch")
698                     || opr.getValue().getAsString().equalsIgnoreCase("delete"))) {
699
700                 throw new CrudException("Mising ID at item: " + item.getKey(), Status.BAD_REQUEST);
701
702             }
703             if (opr.getValue().getAsString().equalsIgnoreCase("add")) {
704                 if (edgePayload.getSource() == null || edgePayload.getTarget() == null) {
705                     throw new CrudException("Source/Target cannot be null for edge: " + item.getKey(),
706                             Status.BAD_REQUEST);
707                 }
708                 if (edgePayload.getSource().startsWith("$")
709                         && !vertices.contains(edgePayload.getSource().substring(1))) {
710                     throw new CrudException("Source Vertex " + edgePayload.getSource().substring(1)
711                             + " not found for Edge: " + item.getKey(), Status.BAD_REQUEST);
712                 }
713
714                 if (edgePayload.getTarget().startsWith("$")
715                         && !vertices.contains(edgePayload.getTarget().substring(1))) {
716                     throw new CrudException("Target Vertex " + edgePayload.getSource().substring(1)
717                             + " not found for Edge: " + item.getKey(), Status.BAD_REQUEST);
718                 }
719             }
720             edges.add(item.getKey());
721
722         }
723
724     }
725
726     @ApiOperation(value = "Bulk API" , notes="For example : https://<host>:9520/services/inventory/v11/bulk")
727     @ApiResponses({    
728       @ApiResponse(code = 200, message = "Success"),
729       @ApiResponse(code = 403, message = "Forbidden"), 
730       @ApiResponse(code = 400, message = "Bad Request"),
731       @ApiResponse(code = 404, message = "Not Found"),
732       @ApiResponse(code = 500, message = "Internal Server Error") })
733     @ApiImplicitParams({
734       @ApiImplicitParam(name = "X-FromAppId", required = true, dataType = "string", paramType = "header"),
735       @ApiImplicitParam(name = "X-TransactionId",  required = true, dataType = "string", paramType = "header"),    
736     })
737     @POST
738     @Path("/{version}/bulk/")
739     @Consumes({MediaType.APPLICATION_JSON})
740     @Produces({MediaType.APPLICATION_JSON})
741     public Response addBulk(String content, @PathParam("version") @ApiParam(value="oxm model version",defaultValue="v13") String version, 
742             @PathParam("uri") @Encoded @ApiParam(hidden=true) String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
743             @Context HttpServletRequest req) {
744
745         LoggingUtil.initMdcContext(req, headers);
746         logger.debug("Incoming request..." + content);
747
748         ResponseBuilder responseBuilder;
749
750         try {
751             if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
752                 BulkPayload payload = BulkPayload.fromJson(content);
753                 if ((payload.getObjects() == null && payload.getRelationships() == null)
754                         || (payload.getObjects() != null && payload.getObjects().isEmpty()
755                                 && payload.getRelationships() != null && payload.getRelationships().isEmpty())) {
756                     throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
757                 }
758
759                 validateBulkPayload(payload);
760                 String result = graphDataService.addBulk(version, payload, headers);
761                 responseBuilder = Response.status(Status.OK).entity(result).type(mediaType);
762             } else {
763                 responseBuilder = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON);
764             }
765         } catch (CrudException ce) {
766             responseBuilder = Response.status(ce.getHttpStatus()).entity(ce.getMessage());
767         } catch (Exception e) {
768             responseBuilder = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage());
769         }
770
771         setTxIdOnResponseHeader(headers, responseBuilder);
772
773         Response response = responseBuilder.build();
774         LoggingUtil.logRestRequest(logger, auditLogger, req, response);
775         return response;
776     }
777
778     @ApiOperation(value = "Create Vertex (typeless endpoint)" , nickname="addVertex-typeless",notes = "# Payload \n"
779         + "{\r\n" +  
780         "   \"type\" :\"vertex type from oxm like comcast.nodes.sdwan.vpn\",\r\n" +       
781         "    \"properties\": {\r\n" + 
782         "        \"prop1\" : \"value\",\r\n" + 
783         "        \"prop2\" :\"value\",\r\n" +          
784         "    ..}\r\n" + 
785         " }")
786     @ApiResponses({   
787       @ApiResponse(code = 201, message = "Created"),
788       @ApiResponse(code = 403, message = "Forbidden"), 
789       @ApiResponse(code = 400, message = "Bad Request"),
790       @ApiResponse(code = 404, message = "Not Found"),
791       @ApiResponse(code = 500, message = "Internal Server Error") })
792     @ApiImplicitParams({
793       @ApiImplicitParam(name = "X-FromAppId", required = true, dataType = "string", paramType = "header"),
794       @ApiImplicitParam(name = "X-TransactionId",  required = true, dataType = "string", paramType = "header"),    
795     })
796     @POST
797     @Path("/{version}/")
798     @Consumes({MediaType.APPLICATION_JSON})
799     @Produces({MediaType.APPLICATION_JSON})
800     public Response addVertex(String content, @PathParam("version") @ApiParam(value="oxm model version",defaultValue="v13") String version,
801             @PathParam("uri") @Encoded  @ApiParam(hidden=true) String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
802             @Context HttpServletRequest req) {
803
804         LoggingUtil.initMdcContext(req, headers);
805         logger.debug("Incoming request..." + content);
806
807         ResponseBuilder responseBuilder;
808
809         try {
810
811             if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
812                 VertexPayload payload = VertexPayload.fromJson(content);
813                 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
814                     throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
815                 }
816                 if (payload.getId() != null) {
817                     throw new CrudException("ID specified , use Http PUT to update Vertex", Status.BAD_REQUEST);
818                 }
819
820                 if (payload.getType() == null || payload.getType().isEmpty()) {
821                     throw new CrudException("Missing Vertex Type ", Status.BAD_REQUEST);
822                 }
823
824                 payload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, true));
825
826                 ImmutablePair<EntityTag, String> result =
827                         graphDataService.addVertex(version, payload.getType(), payload);
828                 responseBuilder =
829                         Response.status(Status.CREATED).entity(result.getValue()).tag(result.getKey()).type(mediaType);
830             } else {
831                 responseBuilder = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON);
832             }
833         } catch (CrudException ce) {
834             responseBuilder = Response.status(ce.getHttpStatus()).entity(ce.getMessage());
835         } catch (Exception e) {
836             responseBuilder = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage());
837         }
838
839         setTxIdOnResponseHeader(headers, responseBuilder);
840
841         Response response = responseBuilder.build();
842         LoggingUtil.logRestRequest(logger, auditLogger, req, response);
843         return response;
844     }
845
846     @ApiOperation(value = "Create Edge" , notes = "# Payload \n"
847         + "{  \r\n" + 
848         "   \"source\":\"source vertex like : services/inventory/v11/vserver/0\",\r\n" + 
849         "   \"target\":\"target vertex like : services/inventory/v11/pserver/7\",\r\n" + 
850         "   \"properties\":{  \r\n" + 
851         "        \"prop1\" : \"value\",\r\n" + 
852         "        \"prop2\" :\"value\",\r\n" +  
853         "    ..}\r\n" + 
854         " }")
855     @ApiResponses({   
856       @ApiResponse(code = 201, message = "Created"),
857       @ApiResponse(code = 403, message = "Forbidden"), 
858       @ApiResponse(code = 400, message = "Bad Request"),
859       @ApiResponse(code = 404, message = "Not Found"),
860       @ApiResponse(code = 500, message = "Internal Server Error") })
861    
862     @ApiImplicitParams({
863       @ApiImplicitParam(name = "X-FromAppId", required = true, dataType = "string", paramType = "header"),
864       @ApiImplicitParam(name = "X-TransactionId",  required = true, dataType = "string", paramType = "header"),       
865     })
866     @POST
867     @Path("/relationships/{version}/{type}/")
868     @Consumes({MediaType.APPLICATION_JSON})
869     @Produces({MediaType.APPLICATION_JSON})
870     public Response addEdge(String content, @PathParam("version") @ApiParam(value="oxm model version",defaultValue="v13") String version, @PathParam("type") String type,
871             @PathParam("uri") @Encoded @ApiParam(hidden=true) String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
872             @Context HttpServletRequest req) {
873
874         LoggingUtil.initMdcContext(req, headers);
875         logger.debug("Incoming request..." + content);
876
877         ResponseBuilder responseBuilder;
878
879         try {
880             if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
881                 EdgePayload payload = EdgePayload.fromJson(content);
882                 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
883                     throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
884                 }
885                 if (payload.getId() != null) {
886                     throw new CrudException("ID specified , use Http PUT to update Edge", Status.BAD_REQUEST);
887                 }
888
889                 if (payload.getType() != null && !payload.getType().equals(type)) {
890                     throw new CrudException("Edge Type mismatch", Status.BAD_REQUEST);
891                 }
892                 ImmutablePair<EntityTag, String> result = graphDataService.addEdge(version, type, payload);
893                 responseBuilder =
894                         Response.status(Status.CREATED).entity(result.getValue()).tag(result.getKey()).type(mediaType);
895             } else {
896                 responseBuilder = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON);
897             }
898         } catch (CrudException ce) {
899             responseBuilder = Response.status(ce.getHttpStatus()).entity(ce.getMessage());
900         } catch (Exception e) {
901             responseBuilder = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage());
902         }
903
904         setTxIdOnResponseHeader(headers, responseBuilder);
905
906         Response response = responseBuilder.build();
907         LoggingUtil.logRestRequest(logger, auditLogger, req, response);
908         return response;
909     }
910
911     @ApiOperation(value = "Create Edge (typeless endpoint)" , nickname="addEdge-typeless",notes = "# Payload \n"
912         + "{  \r\n" + 
913         "   \"type\":\"edge type like : tosca.relationships.HostedOn\",\r\n" +      
914         "   \"source\":\"source vertex like : services/inventory/v11/vserver/0\",\r\n" + 
915         "   \"target\":\"target vertex like : services/inventory/v11/pserver/7\",\r\n" + 
916         "   \"properties\":{  \r\n" + 
917         "        \"prop1\" : \"value\",\r\n" + 
918         "        \"prop2\" :\"value\",\r\n" +  
919         "    ..}\r\n" + 
920         " }")
921     @ApiResponses({  
922       @ApiResponse(code = 201, message = "Created"),
923       @ApiResponse(code = 403, message = "Forbidden"), 
924       @ApiResponse(code = 400, message = "Bad Request"),
925       @ApiResponse(code = 404, message = "Not Found"),
926       @ApiResponse(code = 500, message = "Internal Server Error") })
927     @ApiImplicitParams({
928       @ApiImplicitParam(name = "X-FromAppId", required = true, dataType = "string", paramType = "header"),
929       @ApiImplicitParam(name = "X-TransactionId",  required = true, dataType = "string", paramType = "header"),    
930     })
931     @POST
932     @Path("/relationships/{version}/")
933     @Consumes({MediaType.APPLICATION_JSON})
934     @Produces({MediaType.APPLICATION_JSON})
935     public Response addEdge(String content, @PathParam("version")  @ApiParam(value="oxm model version",defaultValue="v13") String version, @PathParam("uri") @Encoded @ApiParam(hidden=true) String uri,
936             @Context HttpHeaders headers, @Context UriInfo uriInfo, @Context HttpServletRequest req) {
937
938         LoggingUtil.initMdcContext(req, headers);
939         logger.debug("Incoming request..." + content);
940
941         ResponseBuilder responseBuilder;
942
943         try {
944             if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
945                 EdgePayload payload = EdgePayload.fromJson(content);
946                 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
947                     throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
948                 }
949                 if (payload.getId() != null) {
950                     throw new CrudException("ID specified , use Http PUT to update Edge", Status.BAD_REQUEST);
951                 }
952
953                 if (payload.getType() == null || payload.getType().isEmpty()) {
954                     payload.setType(CrudServiceUtil.determineEdgeType(payload, version));
955                 }
956
957                 ImmutablePair<EntityTag, String> result = graphDataService.addEdge(version, payload.getType(), payload);
958                 responseBuilder =
959                         Response.status(Status.CREATED).entity(result.getValue()).tag(result.getKey()).type(mediaType);
960             } else {
961                 responseBuilder = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON);
962             }
963         } catch (CrudException ce) {
964             responseBuilder = Response.status(ce.getHttpStatus()).entity(ce.getMessage());
965         } catch (Exception e) {
966             responseBuilder = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage());
967         }
968
969         setTxIdOnResponseHeader(headers, responseBuilder);
970
971         Response response = responseBuilder.build();
972         LoggingUtil.logRestRequest(logger, auditLogger, req, response);
973         return response;
974     }
975
976     @ApiOperation(value = "Delete Vertex" , notes="For example : https://<host>:9520/services/inventory/v11/pserver/<id>")
977     @ApiResponses({  
978       @ApiResponse(code = 200, message = "Success"),
979       @ApiResponse(code = 403, message = "Forbidden"), 
980       @ApiResponse(code = 400, message = "Bad Request"),
981       @ApiResponse(code = 404, message = "Not Found"),
982       @ApiResponse(code = 500, message = "Internal Server Error") })
983     @ApiImplicitParams({
984       @ApiImplicitParam(name = "X-FromAppId", required = true, dataType = "string", paramType = "header"),
985       @ApiImplicitParam(name = "X-TransactionId",  required = true, dataType = "string", paramType = "header"),    
986     })
987     @DELETE
988     @Path("/{version}/{type}/{id}")
989     @Consumes({MediaType.APPLICATION_JSON})
990     @Produces({MediaType.APPLICATION_JSON})
991     public Response deleteVertex(@ApiParam(hidden=true) String content, @PathParam("version") @ApiParam(value="oxm model version",defaultValue="v13") String version, @PathParam("type") String type,
992             @PathParam("id") String id, @PathParam("uri") @Encoded @ApiParam(hidden=true)  String uri, @Context HttpHeaders headers,
993             @Context UriInfo uriInfo, @Context HttpServletRequest req) {
994
995         LoggingUtil.initMdcContext(req, headers);
996         logger.debug("Incoming request..." + content);
997
998         ResponseBuilder responseBuilder;
999
1000         try {
1001             if (validateRequest(req, uri, content, Action.DELETE, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
1002                 String result = graphDataService.deleteVertex(version, id, type);
1003                 responseBuilder = Response.status(Status.OK).entity(result).type(mediaType);
1004             } else {
1005                 responseBuilder = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON);
1006             }
1007         } catch (CrudException ce) {
1008             responseBuilder = Response.status(ce.getHttpStatus()).entity(ce.getMessage());
1009         } catch (Exception e) {
1010             responseBuilder = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage());
1011         }
1012
1013         setTxIdOnResponseHeader(headers, responseBuilder);
1014
1015         Response response = responseBuilder.build();
1016         LoggingUtil.logRestRequest(logger, auditLogger, req, response);
1017         return response;
1018     }
1019
1020     @ApiOperation(value = "Delete Edge" , notes="For example : https://<host>:9520/services/inventory/v11/pserver/<id>")
1021     @ApiResponses({ 
1022       @ApiResponse(code = 200, message = "Success"),
1023       @ApiResponse(code = 403, message = "Forbidden"), 
1024       @ApiResponse(code = 400, message = "Bad Request"),
1025       @ApiResponse(code = 404, message = "Not Found"),
1026       @ApiResponse(code = 500, message = "Internal Server Error") })
1027     @ApiImplicitParams({
1028       @ApiImplicitParam(name = "X-FromAppId", required = true, dataType = "string", paramType = "header"),
1029       @ApiImplicitParam(name = "X-TransactionId",  required = true, dataType = "string", paramType = "header"),    
1030     })
1031     @DELETE
1032     @Path("/relationships/{version}/{type}/{id}")
1033     @Consumes({MediaType.APPLICATION_JSON})
1034     @Produces({MediaType.APPLICATION_JSON})
1035     public Response deleteEdge(@ApiParam(hidden=true) String content, @PathParam("version") @ApiParam(value="oxm model version",defaultValue="v13") String version, @PathParam("type") String type,
1036             @PathParam("id") String id, @PathParam("uri") @Encoded @ApiParam(hidden=true) String uri, @Context HttpHeaders headers,
1037             @Context UriInfo uriInfo, @Context HttpServletRequest req) {
1038
1039         LoggingUtil.initMdcContext(req, headers);
1040         logger.debug("Incoming request..." + content);
1041
1042         ResponseBuilder responseBuilder;
1043
1044         try {
1045             if (validateRequest(req, uri, content, Action.DELETE, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
1046                 String result = graphDataService.deleteEdge(version, id, type);
1047                 responseBuilder = Response.status(Status.OK).entity(result).type(mediaType);
1048             } else {
1049                 responseBuilder = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON);
1050             }
1051         } catch (CrudException ce) {
1052             responseBuilder = Response.status(ce.getHttpStatus()).entity(ce.getMessage());
1053         } catch (Exception e) {
1054             responseBuilder = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage());
1055         }
1056
1057         setTxIdOnResponseHeader(headers, responseBuilder);
1058
1059         Response response = responseBuilder.build();
1060         LoggingUtil.logRestRequest(logger, auditLogger, req, response);
1061         return response;
1062     }
1063
1064     protected boolean validateRequest(HttpServletRequest req, String uri, String content, Action action,
1065             String authPolicyFunctionName, HttpHeaders headers) throws CrudException {
1066         boolean isValid = false;
1067         try {
1068             String cipherSuite = (String) req.getAttribute("javax.servlet.request.cipher_suite");
1069             String authUser = null;
1070             if (cipherSuite != null) {
1071                 X509Certificate[] certChain =
1072                         (X509Certificate[]) req.getAttribute("javax.servlet.request.X509Certificate");
1073                 X509Certificate clientCert = certChain[0];
1074                 X500Principal subjectDn = clientCert.getSubjectX500Principal();
1075                 authUser = subjectDn.toString();
1076             }
1077             if (null != authUser) {
1078                 isValid = this.auth.validateRequest(authUser.toLowerCase(),
1079                         action.toString() + ":" + authPolicyFunctionName);
1080             }
1081         } catch (Exception e) {
1082             logResult(action, uri, e);
1083             return false;
1084         }
1085
1086         validateRequestHeader(headers);
1087
1088         return isValid;
1089     }
1090
1091     public void validateRequestHeader(HttpHeaders headers) throws CrudException {
1092         String sourceOfTruth = null;
1093         if (headers.getRequestHeaders().containsKey("X-FromAppId")) {
1094             sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId");
1095         }
1096
1097         if (sourceOfTruth == null || sourceOfTruth.trim() == "") {
1098             throw new CrudException("Invalid request, Missing X-FromAppId header", Status.BAD_REQUEST);
1099         }
1100
1101         String transId = null;
1102         if (headers.getRequestHeaders().containsKey("X-TransactionId")) {
1103             transId = headers.getRequestHeaders().getFirst("X-TransactionId");
1104         }
1105
1106         if (transId == null || transId.trim() == "") {
1107             throw new CrudException("Invalid request, Missing X-TransactionId header", Status.BAD_REQUEST);
1108         }
1109     }
1110
1111     void logResult(Action op, String uri, Exception e) {
1112
1113         logger.error(CrudServiceMsgs.EXCEPTION_DURING_METHOD_CALL, op.toString(), uri,
1114                 Arrays.toString(e.getStackTrace()));
1115
1116         // Clear the MDC context so that no other transaction inadvertently
1117         // uses our transaction id.
1118         MDC.clear();
1119     }
1120
1121     private Map<String, String> addParams(UriInfo info, boolean filter, String type, String version) {
1122         String propertiesKey = CrudProperties.get(CrudServiceConstants.CRD_COLLECTION_PROPERTIES_KEY);
1123         Map<String, String> params = new HashMap<String, String>();
1124         params.put(CrudServiceConstants.CRD_RESERVED_VERSION, version);
1125         params.put(CrudServiceConstants.CRD_RESERVED_NODE_TYPE, type);
1126         if (filter) {
1127             for (Map.Entry<String, List<String>> e : info.getQueryParameters().entrySet()) {
1128                 if (!e.getKey().equals(propertiesKey)) {
1129                     params.put(e.getKey(), e.getValue().get(0));
1130                 }
1131             }
1132         } else {
1133             for (Map.Entry<String, List<String>> e : info.getQueryParameters().entrySet()) {
1134                 params.put(e.getKey(), e.getValue().get(0));
1135             }
1136         }
1137         return params;
1138     }
1139
1140     private void setTxIdOnResponseHeader(HttpHeaders headers, ResponseBuilder responseBuilder) {
1141         String txId = headers.getHeaderString(TRANSACTIONID_HEADER);
1142         if (txId != null) {
1143             responseBuilder.header(TRANSACTIONID_HEADER, txId);
1144         }
1145     }
1146 }