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