856380720bf0aa6e0481ea6e57341ab91c1afaa5
[aai/gizmo.git] / src / main / java / org / onap / crud / dao / champ / ChampDao.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.dao.champ;
22
23 import java.nio.charset.Charset;
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 import java.util.Set;
31 import javax.ws.rs.core.MediaType;
32 import javax.ws.rs.core.Response;
33 import org.apache.http.NameValuePair;
34 import org.apache.http.client.utils.URLEncodedUtils;
35 import org.apache.http.message.BasicNameValuePair;
36 import org.eclipse.jetty.util.security.Password;
37 import org.onap.aai.cl.mdc.MdcContext;
38 import org.onap.aai.restclient.client.OperationResult;
39 import org.onap.aai.restclient.client.RestClient;
40 import org.onap.aai.restclient.enums.RestAuthenticationMode;
41 import org.onap.crud.dao.GraphDao;
42 import org.onap.crud.entity.Edge;
43 import org.onap.crud.entity.Vertex;
44 import org.onap.crud.exception.CrudException;
45 import org.onap.crud.util.CrudServiceConstants;
46 import org.slf4j.MDC;
47 import com.google.gson.Gson;
48 import com.google.gson.GsonBuilder;
49 import com.google.gson.reflect.TypeToken;
50 import net.dongliu.gson.GsonJava8TypeAdapterFactory;
51
52 public class ChampDao implements GraphDao {
53   protected RestClient client;
54   protected String baseObjectUrl;
55   protected String baseRelationshipUrl;
56   protected String baseTransactionUrl;
57
58   protected static final String HEADER_FROM_APP = "X-FromAppId";
59   protected static final String HEADER_TRANS_ID = "X-TransactionId";
60   protected static final String FROM_APP_NAME = "Gizmo";
61   protected static final String OBJECT_SUB_URL = "objects";
62   protected static final String RELATIONSHIP_SUB_URL = "relationships";
63   protected static final String TRANSACTION_SUB_URL = "transaction";
64
65   // We use a custom vertex serializer for champ because it expects "key"
66   // instead of "id"
67   protected static final Gson champGson = new GsonBuilder()
68       .registerTypeAdapterFactory(new GsonJava8TypeAdapterFactory())
69       .registerTypeAdapter(Vertex.class, new ChampVertexSerializer())
70       .registerTypeAdapter(Edge.class, new ChampEdgeSerializer()).create();
71
72   public ChampDao() {
73   }
74
75   public ChampDao(String champUrl, String certPassword) {
76     try {
77       client = new RestClient().authenticationMode(RestAuthenticationMode.SSL_CERT).validateServerHostname(false)
78           .validateServerCertChain(false).clientCertFile(CrudServiceConstants.CRD_CHAMP_AUTH_FILE)
79           .clientCertPassword(Password.deobfuscate(certPassword));
80
81       baseObjectUrl = champUrl + OBJECT_SUB_URL;
82       baseRelationshipUrl = champUrl + RELATIONSHIP_SUB_URL;
83       baseTransactionUrl = champUrl + TRANSACTION_SUB_URL;
84     } catch (Exception e) {
85       System.out.println("Error setting up Champ configuration");
86       e.printStackTrace();
87       System.exit(1);
88     }
89   }
90
91   public ChampDao(RestClient client, String baseObjectUrl, String baseRelationshipUrl, String baseTransactionUrl) {
92       this.client = client;
93       this.baseObjectUrl = baseObjectUrl;
94       this.baseRelationshipUrl = baseRelationshipUrl;
95       this.baseTransactionUrl = baseTransactionUrl;
96   }
97
98   @Override
99   public Vertex getVertex(String id, String version) throws CrudException {
100     String url = baseObjectUrl + "/" + id;
101     OperationResult getResult = client.get(url, createHeader(), MediaType.APPLICATION_JSON_TYPE);
102
103     if (getResult.getResultCode() == 200) {
104       return Vertex.fromJson(getResult.getResult(), version);
105     } else {
106       // We didn't find a vertex with the supplied id, so just throw an
107       // exception.
108       throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No vertex with id " + id + " found in graph");
109     }
110   }
111
112   @Override
113   public OperationResult getVertex(String id, String type, String version, Map<String, String> queryParams) throws CrudException {
114     StringBuilder strBuild = new StringBuilder(baseObjectUrl);
115     strBuild.append("/");
116     strBuild.append(id);
117     if(queryParams != null && !queryParams.isEmpty())
118     {
119         strBuild.append("?");
120         strBuild.append(URLEncodedUtils.format(convertToNameValuePair(queryParams), Charset.defaultCharset()));
121     }
122
123     OperationResult getResult = client.get(strBuild.toString(), createHeader(), MediaType.APPLICATION_JSON_TYPE);
124
125     if (getResult.getResultCode() == 200) {
126       Vertex vert = Vertex.fromJson(getResult.getResult(), version);
127
128       if (!vert.getType().equalsIgnoreCase(type)) {
129         // We didn't find a vertex with the supplied type, so just throw an
130         // exception.
131         throw new CrudException("No vertex with id " + id + " and type " + type + " found in graph",
132             javax.ws.rs.core.Response.Status.NOT_FOUND);
133       }
134       return getResult;
135     } else {
136       // We didn't find a vertex with the supplied id, so just throw an
137       // exception.
138         throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No vertex with id " + id + " found in graph");
139     }
140   }
141
142   @Override
143   public List<Edge> getVertexEdges(String id, Map<String, String> queryParams, String txId) throws CrudException {
144       StringBuilder strBuild = new StringBuilder(baseObjectUrl);
145       strBuild.append("/relationships/");
146       strBuild.append(id);
147
148       Map<String,String> queryParamsCopy = null;
149       if (queryParams != null) {
150           queryParamsCopy = new HashMap<String,String>(queryParams);
151       }
152       else {
153           queryParamsCopy = new HashMap<String,String>();
154       }
155
156       if (txId != null) {
157           queryParamsCopy.put("transactionId", txId);
158       }
159
160       if (!queryParamsCopy.isEmpty())
161       {
162           strBuild.append("?");
163           strBuild.append(URLEncodedUtils.format(convertToNameValuePair(queryParamsCopy), Charset.defaultCharset()));
164       }
165
166       OperationResult getResult = client.get(strBuild.toString(), createHeader(), MediaType.APPLICATION_JSON_TYPE);
167
168       if (getResult.getResultCode() == 200) {
169           return champGson.fromJson(getResult.getResult(), new TypeToken<List<Edge>>() {
170           }.getType());
171       } else {
172           // We didn't find a vertex with the supplied id, so just throw an
173           // exception.
174           throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No vertex with id " + id + " found in graph");
175       }
176   }
177
178   @Override
179   public OperationResult getVertices(String type, Map<String, Object> filter, String version) throws CrudException {
180     return getVertices(type, filter, new HashSet<String>(), version);
181   }
182
183   @Override
184   public OperationResult getVertices(String type, Map<String, Object> filter, Set<String> properties, String version) throws CrudException {
185     filter.put(org.onap.schema.validation.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type);
186
187     List<NameValuePair> queryParams = convertToNameValuePair(filter);
188     queryParams.addAll(convertToNameValuePair("properties", properties));
189     String url = baseObjectUrl + "/filter" + "?"
190         + URLEncodedUtils.format(queryParams, Charset.defaultCharset());
191
192     OperationResult getResult = client.get(url, createHeader(), MediaType.APPLICATION_JSON_TYPE);
193
194     if (getResult.getResultCode() == 200) {
195       return getResult;
196     } else {
197       // We didn't find a vertex with the supplied id, so just throw an
198       // exception.
199       throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No vertices found in graph for given filters");
200     }
201   }
202
203   @Override
204   public OperationResult getEdge(String id, String type, Map<String, String> queryParams) throws CrudException {
205     StringBuilder strBuild = new StringBuilder(baseRelationshipUrl);
206     strBuild.append("/");
207     strBuild.append(id);
208     if(queryParams != null && !queryParams.isEmpty())
209     {
210         strBuild.append("?");
211         strBuild.append(URLEncodedUtils.format(convertToNameValuePair(queryParams), Charset.defaultCharset()));
212     }
213     OperationResult getResult = client.get(strBuild.toString(), createHeader(), MediaType.APPLICATION_JSON_TYPE);
214
215     if (getResult.getResultCode() == 200) {
216       Edge edge = Edge.fromJson(getResult.getResult());
217
218       if (!edge.getType().equalsIgnoreCase(type)) {
219         // We didn't find an edge with the supplied type, so just throw an
220         // exception.
221         throw new CrudException("No edge with id " + id + " and type " + type + " found in graph",
222             javax.ws.rs.core.Response.Status.NOT_FOUND);
223       }
224       return getResult;
225     } else {
226       // We didn't find a edge with the supplied type, so just throw an
227       // exception.
228       throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No edge with id " + id + " found in graph");
229     }
230   }
231
232   @Override
233   public OperationResult getEdges(String type, Map<String, Object> filter) throws CrudException {
234     String url = baseRelationshipUrl + "/filter" + "?"
235         + URLEncodedUtils.format(convertToNameValuePair(filter), Charset.defaultCharset());
236
237     OperationResult getResult = client.get(url, createHeader(), MediaType.APPLICATION_JSON_TYPE);
238
239     if (getResult.getResultCode() == 200) {
240         return getResult;
241     } else {
242       // We didn't find a vertex with the supplied id, so just throw an
243       // exception.
244       throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No edges found in graph  for given filters");
245     }
246   }
247
248   @Override
249   public OperationResult addVertex(String type, Map<String, Object> properties, String version) throws CrudException {
250     String url = baseObjectUrl;
251
252     // Add the aai_node_type so that AAI can read the data created by gizmo
253     // TODO: This probably shouldn't be here
254     properties.put(org.onap.schema.validation.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type);
255
256     Vertex.Builder insertVertexBuilder = new Vertex.Builder(type);
257     properties.forEach(insertVertexBuilder::property);
258     Vertex insertVertex = insertVertexBuilder.build();
259
260     OperationResult getResult = client.post(url, insertVertex.toJson(), createHeader(), MediaType.APPLICATION_JSON_TYPE,
261         MediaType.APPLICATION_JSON_TYPE);
262
263     if (getResult.getResultCode() == Response.Status.CREATED.getStatusCode()) {
264       return getResult;
265     } else {
266       // We didn't create a vertex with the supplied type, so just throw an
267       // exception.
268       throw new CrudException("Failed to create vertex: " + getResult.getFailureCause(), Response.Status.fromStatusCode(getResult.getResultCode()));
269     }
270   }
271
272   @Override
273   public OperationResult updateVertex(String id, String type, Map<String, Object> properties, String version) throws CrudException {
274     String url = baseObjectUrl + "/" + id;
275
276     // Add the aai_node_type so that AAI can read the data created by gizmo
277     // TODO: This probably shouldn't be here
278     properties.put(org.onap.schema.validation.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type);
279
280     Vertex.Builder insertVertexBuilder = new Vertex.Builder(type);
281     insertVertexBuilder.id(id);
282     properties.forEach(insertVertexBuilder::property);
283     Vertex insertVertex = insertVertexBuilder.build();
284
285     String payload = insertVertex.toJson(champGson);
286     OperationResult getResult = client.put(url, payload, createHeader(), MediaType.APPLICATION_JSON_TYPE,
287         MediaType.APPLICATION_JSON_TYPE);
288
289     if (getResult.getResultCode() == Response.Status.OK.getStatusCode()) {
290       return getResult;
291     } else {
292       // We didn't create a vertex with the supplied type, so just throw an
293       // exception.
294       throw new CrudException("Failed to update vertex: " + getResult.getFailureCause(), Response.Status.fromStatusCode(getResult.getResultCode()));
295     }
296   }
297
298   @Override
299   public void deleteVertex(String id, String type) throws CrudException {
300     String url = baseObjectUrl + "/" + id;
301     OperationResult getResult = client.delete(url, createHeader(), MediaType.APPLICATION_JSON_TYPE);
302
303     if (getResult.getResultCode() != Response.Status.OK.getStatusCode()) {
304       // We didn't delete a vertex with the supplied id, so just throw an
305       // exception.
306       throw new CrudException("Failed to delete vertex: " + getResult.getFailureCause(), Response.Status.fromStatusCode(getResult.getResultCode()));
307     }
308   }
309
310   @Override
311   public OperationResult addEdge(String type, Vertex source, Vertex target, Map<String, Object> properties, String version) throws CrudException {
312     String url = baseRelationshipUrl;
313
314     // Try requests to ensure source and target exist in Champ
315     OperationResult dbSourceOpResult = getVertex(source.getId().get(), source.getType(), version, new HashMap<String, String>());
316     Vertex dbSource = Vertex.fromJson(dbSourceOpResult.getResult(), version);
317     OperationResult dbTargetOpResult = getVertex(target.getId().get(), target.getType(), version, new HashMap<String, String>());
318     Vertex dbTarget = Vertex.fromJson(dbTargetOpResult.getResult(), version);
319
320     Edge.Builder insertEdgeBuilder = new Edge.Builder(type).source(dbSource).target(dbTarget);
321     properties.forEach(insertEdgeBuilder::property);
322     Edge insertEdge = insertEdgeBuilder.build();
323
324     String edgeJson = insertEdge.toJson(champGson);
325     OperationResult getResult = client.post(url, edgeJson, createHeader(), MediaType.APPLICATION_JSON_TYPE,
326         MediaType.APPLICATION_JSON_TYPE);
327
328     if (getResult.getResultCode() == Response.Status.CREATED.getStatusCode()) {
329       return getResult;
330     } else {
331       // We didn't create an edge with the supplied type, so just throw an
332       // exception.
333       throw new CrudException("Failed to create edge: " + getResult.getFailureCause(), Response.Status.fromStatusCode(getResult.getResultCode()));
334     }
335   }
336
337   @Override
338   public OperationResult updateEdge(Edge edge) throws CrudException {
339     if (!edge.getId().isPresent()) {
340       throw new CrudException("Unable to identify edge: " + edge.toString(), Response.Status.BAD_REQUEST);
341     }
342     String url = baseRelationshipUrl + "/" + edge.getId().get();
343
344     String edgeJson = edge.toJson(champGson);
345     OperationResult getResult = client.put(url, edgeJson, createHeader(), MediaType.APPLICATION_JSON_TYPE,
346         MediaType.APPLICATION_JSON_TYPE);
347
348     if (getResult.getResultCode() == Response.Status.OK.getStatusCode()) {
349       return getResult;
350     } else {
351       // We didn't create an edge with the supplied type, so just throw an
352       // exception.
353       throw new CrudException("Failed to update edge: " + getResult.getFailureCause(), Response.Status.fromStatusCode(getResult.getResultCode()));
354     }
355   }
356
357   @Override
358   public void deleteEdge(String id) throws CrudException {
359     String url = baseRelationshipUrl + "/" + id;
360     OperationResult getResult = client.delete(url, createHeader(), MediaType.APPLICATION_JSON_TYPE);
361
362     if (getResult.getResultCode() != 200) {
363       // We didn't find an edge with the supplied type, so just throw an
364       // exception.
365       throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No edge with id " + id + " found in graph");
366     }
367   }
368
369   @Override
370   public String openTransaction() {
371     String url = baseTransactionUrl;
372
373     OperationResult getResult = client.post(url, "", createHeader(), MediaType.TEXT_PLAIN_TYPE, MediaType.TEXT_PLAIN_TYPE);
374
375     if (getResult.getResultCode() == 200) {
376       return getResult.getResult();
377     } else {
378       return null;
379     }
380   }
381
382   @Override
383   public void commitTransaction(String id) throws CrudException {
384     String url = baseTransactionUrl + "/" + id;
385
386     OperationResult getResult = client.put(url, "{\"method\": \"commit\"}", createHeader(), MediaType.APPLICATION_JSON_TYPE,
387         MediaType.TEXT_PLAIN_TYPE);
388
389     if (getResult.getResultCode() != 200) {
390       throw new CrudException("Unable to commit transaction",
391           Response.Status.fromStatusCode(getResult.getResultCode()));
392     }
393   }
394
395   @Override
396   public void rollbackTransaction(String id) throws CrudException {
397     String url = baseTransactionUrl + "/" + id;
398
399     OperationResult getResult = client.put(url, "{\"method\": \"rollback\"}", createHeader(), MediaType.APPLICATION_JSON_TYPE,
400         MediaType.TEXT_PLAIN_TYPE);
401
402     if (getResult.getResultCode() != 200) {
403       throw new CrudException("Unable to rollback transaction",
404           Response.Status.fromStatusCode(getResult.getResultCode()));
405     }
406   }
407
408   @Override
409   public boolean transactionExists(String id) throws CrudException {
410     String url = baseTransactionUrl + "/" + id;
411     Map<String, List<String>> headers = new HashMap<>();
412     headers.put(HEADER_FROM_APP, Arrays.asList("Gizmo"));
413     headers.put(HEADER_TRANS_ID, Arrays.asList(MDC.get(MdcContext.MDC_REQUEST_ID)));
414
415     OperationResult getResult = client.get(url, headers, MediaType.APPLICATION_JSON_TYPE);
416
417     return getResult.getResultCode() == 200;
418   }
419
420   @Override
421   public Vertex addVertex(String type, Map<String, Object> properties, String version, String txId) throws CrudException {
422     String url = baseObjectUrl + "?transactionId=" + txId;
423
424     // Add the aai_node_type so that AAI can read the data created by gizmo
425     // TODO: This probably shouldn't be here
426     properties.put(org.onap.schema.validation.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type);
427
428     Vertex.Builder insertVertexBuilder = new Vertex.Builder(type);
429     properties.forEach(insertVertexBuilder::property);
430     Vertex insertVertex = insertVertexBuilder.build();
431
432     OperationResult getResult = client.post(url, insertVertex.toJson(), createHeader(), MediaType.APPLICATION_JSON_TYPE,
433         MediaType.APPLICATION_JSON_TYPE);
434
435     if (getResult.getResultCode() == Response.Status.CREATED.getStatusCode()) {
436       return Vertex.fromJson(getResult.getResult(), version);
437     } else {
438       // We didn't create a vertex with the supplied type, so just throw an
439       // exception.
440       throw new CrudException("Failed to create vertex: " + getResult.getFailureCause(), Response.Status.fromStatusCode(getResult.getResultCode()));
441     }
442   }
443
444   @Override
445   public Edge addEdge(String type, Vertex source, Vertex target, Map<String, Object> properties, String version, String txId)
446       throws CrudException {
447     String url = baseRelationshipUrl + "?transactionId=" + txId;
448
449     // Try requests to ensure source and target exist in Champ
450     Vertex dbSource = getVertex(source.getId().get(), source.getType(), version, txId);
451     Vertex dbTarget = getVertex(target.getId().get(), target.getType(), version, txId);
452
453     Edge.Builder insertEdgeBuilder = new Edge.Builder(type).source(dbSource).target(dbTarget);
454     properties.forEach(insertEdgeBuilder::property);
455     Edge insertEdge = insertEdgeBuilder.build();
456
457     OperationResult getResult = client.post(url, insertEdge.toJson(champGson), createHeader(),
458         MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON_TYPE);
459
460     if (getResult.getResultCode() == Response.Status.CREATED.getStatusCode()) {
461       return Edge.fromJson(getResult.getResult());
462     } else {
463       // We didn't create an edge with the supplied type, so just throw an
464       // exception.
465       throw new CrudException("Failed to create edge: " + getResult.getFailureCause(), Response.Status.fromStatusCode(getResult.getResultCode()));
466     }
467   }
468
469   @Override
470   public Vertex updateVertex(String id, String type, Map<String, Object> properties, String version, String txId) throws CrudException {
471     String url = baseObjectUrl + "/" + id + "?transactionId=" + txId;
472
473     // Add the aai_node_type so that AAI can read the data created by gizmo
474     // TODO: This probably shouldn't be here
475     properties.put(org.onap.schema.validation.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type);
476
477     Vertex.Builder insertVertexBuilder = new Vertex.Builder(type);
478     insertVertexBuilder.id(id);
479     properties.forEach(insertVertexBuilder::property);
480     Vertex insertVertex = insertVertexBuilder.build();
481
482     String payload = insertVertex.toJson(champGson);
483     OperationResult getResult = client.put(url, payload, createHeader(), MediaType.APPLICATION_JSON_TYPE,
484         MediaType.APPLICATION_JSON_TYPE);
485
486     if (getResult.getResultCode() == Response.Status.OK.getStatusCode()) {
487       return Vertex.fromJson(getResult.getResult(), version);
488     } else {
489       // We didn't create a vertex with the supplied type, so just throw an
490       // exception.
491       throw new CrudException("Failed to update vertex: " + getResult.getFailureCause(), Response.Status.fromStatusCode(getResult.getResultCode()));
492     }
493   }
494
495   @Override
496   public void deleteVertex(String id, String type, String txId) throws CrudException {
497     String url = baseObjectUrl + "/" + id + "?transactionId=" + txId;
498     OperationResult getResult = client.delete(url, createHeader(), MediaType.APPLICATION_JSON_TYPE);
499
500     if (getResult.getResultCode() != Response.Status.OK.getStatusCode()) {
501       // We didn't delete a vertex with the supplied id, so just throw an
502       // exception.
503       throw new CrudException("Failed to delete vertex: " + getResult.getFailureCause(), Response.Status.fromStatusCode(getResult.getResultCode()));
504     }
505   }
506
507   @Override
508   public Edge updateEdge(Edge edge, String txId) throws CrudException {
509     if (!edge.getId().isPresent()) {
510       throw new CrudException("Unable to identify edge: " + edge.toString(), Response.Status.BAD_REQUEST);
511     }
512     String url = baseRelationshipUrl + "/" + edge.getId().get() + "?transactionId=" + txId;
513     OperationResult getResult = client.put(url, edge.toJson(champGson), createHeader(), MediaType.APPLICATION_JSON_TYPE,
514         MediaType.APPLICATION_JSON_TYPE);
515
516     if (getResult.getResultCode() == Response.Status.OK.getStatusCode()) {
517       return Edge.fromJson(getResult.getResult());
518     } else {
519       // We didn't create an edge with the supplied type, so just throw an
520       // exception.
521       throw new CrudException("Failed to update edge: " + getResult.getFailureCause(),
522           Response.Status.fromStatusCode(getResult.getResultCode()));
523     }
524   }
525
526   @Override
527   public void deleteEdge(String id, String txId) throws CrudException {
528     String url = baseRelationshipUrl + "/" + id + "?transactionId=" + txId;
529     OperationResult getResult = client.delete(url, createHeader(), MediaType.APPLICATION_JSON_TYPE);
530
531     if (getResult.getResultCode() != 200) {
532       // We didn't find an edge with the supplied type, so just throw an
533       // exception.
534       throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No edge with id " + id + " found in graph");
535     }
536   }
537
538   @Override
539   public Edge getEdge(String id, String txId) throws CrudException {
540     String url = baseRelationshipUrl + "/" + id + "?transactionId=" + txId;
541     OperationResult getResult = client.get(url, createHeader(), MediaType.APPLICATION_JSON_TYPE);
542
543     if (getResult.getResultCode() == 200) {
544       Edge edge = Edge.fromJson(getResult.getResult());
545       return edge;
546     } else {
547       // We didn't find an edge with the supplied id, so just throw an
548       // exception.
549       throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No edge with id " + id + " found in graph");
550     }
551   }
552
553   @Override
554   public Edge getEdge(String id) throws CrudException {
555     String url = baseRelationshipUrl + "/" + id;
556     OperationResult getResult = client.get(url, createHeader(), MediaType.APPLICATION_JSON_TYPE);
557
558     if (getResult.getResultCode() == 200) {
559       Edge edge = Edge.fromJson(getResult.getResult());
560       return edge;
561     } else {
562       // We didn't find an edge with the supplied id, so just throw an exception.
563       throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No edge with id " + id + " found in graph");
564     }
565   }
566
567   public Vertex getVertex(String id, String type, String version, String txId) throws CrudException {
568     String url = baseObjectUrl + "/" + id + "?transactionId=" + txId;
569     OperationResult getResult = client.get(url, createHeader(), MediaType.APPLICATION_JSON_TYPE);
570
571     if (getResult.getResultCode() == 200) {
572       Vertex vert = Vertex.fromJson(getResult.getResult(), version);
573
574       if (!vert.getType().equalsIgnoreCase(type)) {
575         // We didn't find a vertex with the supplied type, so just throw an
576         // exception.
577         throw new CrudException("No vertex with id " + id + " and type " + type + " found in graph",
578             javax.ws.rs.core.Response.Status.NOT_FOUND);
579       }
580       return vert;
581     } else {
582       // We didn't find a vertex with the supplied id, so just throw an
583       // exception.
584       throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No vertex with id " + id + " found in graph");
585     }
586   }
587
588   // https://stackoverflow.com/questions/26942330/convert-mapstring-string-to-listnamevaluepair-is-this-the-most-efficient
589   private List<NameValuePair> convertToNameValuePair(Map<String, ? super String> pairs) {
590     List<NameValuePair> nvpList = new ArrayList<>(pairs.size());
591
592     pairs.forEach((key, value) -> nvpList.add(new BasicNameValuePair(key, value.toString())));
593
594     return nvpList;
595   }
596
597   // https://stackoverflow.com/questions/26942330/convert-mapstring-string-to-listnamevaluepair-is-this-the-most-efficient
598   private List<NameValuePair> convertToNameValuePair(String k, Set<String> values) {
599     List<NameValuePair> nvpList = new ArrayList<>(values.size());
600
601     values.forEach((v) -> nvpList.add(new BasicNameValuePair(k, v)));
602
603     return nvpList;
604   }
605
606   private Map<String, List<String>> createHeader() {
607     Map<String, List<String>> headers = new HashMap<>();
608     headers.put(HEADER_FROM_APP, Arrays.asList(FROM_APP_NAME));
609     headers.put(HEADER_TRANS_ID, Arrays.asList(MDC.get(MdcContext.MDC_REQUEST_ID)));
610     return headers;
611   }
612
613   private CrudException createErrorException(OperationResult result, javax.ws.rs.core.Response.Status defaultErrorCode , String defaultErrorMsg)
614   {
615       CrudException ce = null;
616       if(result != null)
617           ce = new CrudException(result.getFailureCause(), Response.Status.fromStatusCode(result.getResultCode()));
618       else
619           ce = new CrudException(defaultErrorMsg, defaultErrorCode);
620       return ce;
621   }
622
623 }