X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=src%2Fmain%2Fjava%2Forg%2Fonap%2Fcrud%2Fdao%2Fchamp%2FChampDao.java;h=554b9fa3cf2382bd37db15fd5b7929add945bb78;hb=0c40bcde9facc109ceb8dabb91156df2b4fb4129;hp=f2178972b9f000849f0ed420948f0195f3ccf49d;hpb=94cbd3286b5fdd2f3f8fa3325835e713d71aac73;p=aai%2Fgizmo.git diff --git a/src/main/java/org/onap/crud/dao/champ/ChampDao.java b/src/main/java/org/onap/crud/dao/champ/ChampDao.java index f217897..554b9fa 100644 --- a/src/main/java/org/onap/crud/dao/champ/ChampDao.java +++ b/src/main/java/org/onap/crud/dao/champ/ChampDao.java @@ -1,16 +1,15 @@ /** * ============LICENSE_START======================================================= - * Gizmo + * org.onap.aai * ================================================================================ - * Copyright © 2017 AT&T Intellectual Property. - * Copyright © 2017 Amdocs - * All rights reserved. + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -18,866 +17,608 @@ * See the License for the specific language governing permissions and * limitations under the License. * ============LICENSE_END========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ package org.onap.crud.dao.champ; +import java.nio.charset.Charset; import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Optional; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.onap.aai.champcore.ChampGraph; -import org.onap.aai.champcore.ChampTransaction; -import org.onap.aai.champcore.exceptions.ChampMarshallingException; -import org.onap.aai.champcore.exceptions.ChampObjectNotExistsException; -import org.onap.aai.champcore.exceptions.ChampRelationshipNotExistsException; -import org.onap.aai.champcore.exceptions.ChampSchemaViolationException; -import org.onap.aai.champcore.exceptions.ChampTransactionException; -import org.onap.aai.champcore.exceptions.ChampUnmarshallingException; -import org.onap.aai.champcore.model.ChampObject; -import org.onap.aai.champcore.model.ChampRelationship; -import org.onap.aai.champcore.model.fluent.object.ObjectBuildOrPropertiesStep; -import org.onap.aai.cl.api.Logger; -import org.onap.aai.cl.eelf.LoggerFactory; +import java.util.Set; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import org.apache.http.NameValuePair; +import org.apache.http.client.utils.URLEncodedUtils; +import org.apache.http.message.BasicNameValuePair; +import org.eclipse.jetty.util.security.Password; +import org.onap.aai.cl.mdc.MdcContext; +import org.onap.aai.restclient.client.OperationResult; +import org.onap.aai.restclient.client.RestClient; +import org.onap.aai.restclient.enums.RestAuthenticationMode; import org.onap.crud.dao.GraphDao; import org.onap.crud.entity.Edge; import org.onap.crud.entity.Vertex; import org.onap.crud.exception.CrudException; -import org.onap.crud.logging.CrudServiceMsgs; +import org.onap.crud.util.CrudServiceConstants; +import org.slf4j.MDC; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.reflect.TypeToken; +import net.dongliu.gson.GsonJava8TypeAdapterFactory; -/** - * This is the integration layer between the CRUD API service and the low level - * Champ library for graph database interaction. - */ public class ChampDao implements GraphDao { + protected RestClient client; + protected String baseObjectUrl; + protected String baseRelationshipUrl; + protected String baseTransactionUrl; - public static final String CONFIG_STORAGE_BACKEND = "storage.backend"; - public static final String CONFIG_STORAGE_BACKEND_DB = "storage.backend.db"; - public static final String STORAGE_HBASE_DB = "hbase"; - public static final String STORAGE_CASSANDRA_DB = "cassandra"; - public static final String CONFIG_STORAGE_HOSTNAMES = "storage.hostnames"; - public static final String CONFIG_STORAGE_PORT = "storage.port"; - public static final String CONFIG_HBASE_ZNODE_PARENT = "storage.hbase.ext.zookeeper.znode.parent"; - public static final String CONFIG_GRAPH_NAME = "graph.name"; - public static final String GRAPH_UNQ_INSTANCE_ID_SUFFIX = "graph.unique-instance-id-suffix"; - - public static final String CONFIG_EVENT_STREAM_PUBLISHER = "event.stream.publisher"; - public static final String CONFIG_EVENT_STREAM_NUM_PUBLISHERS = "event.stream.num-publishers"; + protected static final String HEADER_FROM_APP = "X-FromAppId"; + protected static final String HEADER_TRANS_ID = "X-TransactionId"; + protected static final String FROM_APP_NAME = "Gizmo"; + protected static final String OBJECT_SUB_URL = "objects"; + protected static final String RELATIONSHIP_SUB_URL = "relationships"; + protected static final String TRANSACTION_SUB_URL = "transaction"; - private static Map transactions = new ConcurrentHashMap(); - public static final String DEFAULT_GRAPH_NAME = "default_graph"; + // We use a custom vertex serializer for champ because it expects "key" + // instead of "id" + protected static final Gson champGson = new GsonBuilder() + .registerTypeAdapterFactory(new GsonJava8TypeAdapterFactory()) + .registerTypeAdapter(Vertex.class, new ChampVertexSerializer()) + .registerTypeAdapter(Edge.class, new ChampEdgeSerializer()).create(); - private enum GraphType { - IN_MEMORY, TITAN, DSE + public ChampDao() { } - /** - * Instance of the API used for interacting with the Champ library. - */ - private ChampGraph champApi = null; + public ChampDao(String champUrl, String certPassword) { + try { + String deobfuscatedCertPassword = certPassword.startsWith("OBF:")?Password.deobfuscate(certPassword):certPassword; + client = new RestClient().authenticationMode(RestAuthenticationMode.SSL_CERT).validateServerHostname(false) + .validateServerCertChain(false).clientCertFile(CrudServiceConstants.CRD_CHAMP_AUTH_FILE) + .clientCertPassword(deobfuscatedCertPassword); - private Logger logger = LoggerFactory.getInstance().getLogger(ChampDao.class.getName()); + baseObjectUrl = champUrl + OBJECT_SUB_URL; + baseRelationshipUrl = champUrl + RELATIONSHIP_SUB_URL; + baseTransactionUrl = champUrl + TRANSACTION_SUB_URL; + } catch (Exception e) { + System.out.println("Error setting up Champ configuration"); + e.printStackTrace(); + System.exit(1); + } + } - /** - * Creates a new instance of the ChampDao. - * - * @param champGraph - * - Concrete implementation of the graph dao layer - */ - public ChampDao(ChampGraph champGraph) { - this.champApi = champGraph; + public ChampDao(RestClient client, String baseObjectUrl, String baseRelationshipUrl, String baseTransactionUrl) { + this.client = client; + this.baseObjectUrl = baseObjectUrl; + this.baseRelationshipUrl = baseRelationshipUrl; + this.baseTransactionUrl = baseTransactionUrl; } @Override - public Vertex getVertex(String id) throws CrudException { + public Vertex getVertex(String id, String version) throws CrudException { + String url = baseObjectUrl + "/" + id; + OperationResult getResult = client.get(url, createHeader(), MediaType.APPLICATION_JSON_TYPE); - try { + if (getResult.getResultCode() == 200) { + return Vertex.fromJson(getResult.getResult(), version); + } else { + // We didn't find a vertex with the supplied id, so just throw an + // exception. + throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No vertex with id " + id + " found in graph"); + } + } - if (logger.isDebugEnabled()) { - logger.debug("getVertex with id: " + id); - } + @Override + public OperationResult getVertex(String id, String type, String version, Map queryParams) throws CrudException { + StringBuilder strBuild = new StringBuilder(baseObjectUrl); + strBuild.append("/"); + strBuild.append(id); + if(queryParams != null && !queryParams.isEmpty()) + { + strBuild.append("?"); + strBuild.append(URLEncodedUtils.format(convertToNameValuePair(queryParams), Charset.defaultCharset())); + } - long idAsLong = Long.parseLong(id); + OperationResult getResult = client.get(strBuild.toString(), createHeader(), MediaType.APPLICATION_JSON_TYPE); - Optional retrievedVertex = champApi.retrieveObject(idAsLong); + if (getResult.getResultCode() == 200) { + Vertex vert = Vertex.fromJson(getResult.getResult(), version); - String nodeType = org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(); - if (retrievedVertex.isPresent() && retrievedVertex.get().getProperties().get(nodeType) != null) { - return vertexFromChampObject(retrievedVertex.get(), - retrievedVertex.get().getProperties().get(nodeType).toString()); - } else { - - // We didn't find a vertex with the supplied id, so just throw an + if (!vert.getType().equalsIgnoreCase(type)) { + // We didn't find a vertex with the supplied type, so just throw an // exception. - throw new CrudException("No vertex with id " + id + " found in graph", + throw new CrudException("No vertex with id " + id + " and type " + type + " found in graph", javax.ws.rs.core.Response.Status.NOT_FOUND); } - - } catch (ChampUnmarshallingException | ChampTransactionException e) { - - // Something went wrong - throw an exception. - throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); + return getResult; + } else { + // We didn't find a vertex with the supplied id, so just throw an + // exception. + throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No vertex with id " + id + " found in graph"); } } @Override - public Vertex getVertex(String id, String type) throws CrudException { - - try { - - if (logger.isDebugEnabled()) { - logger.debug("getVertex with id: " + id); + public List getVertexEdges(String id, Map queryParams, String txId) throws CrudException { + StringBuilder strBuild = new StringBuilder(baseObjectUrl); + strBuild.append("/relationships/"); + strBuild.append(id); + + Map queryParamsCopy = null; + if (queryParams != null) { + queryParamsCopy = new HashMap(queryParams); + } + else { + queryParamsCopy = new HashMap(); } - long idAsLong = Long.parseLong(id); - - // Request the vertex from the graph db. - Optional retrievedVertex = champApi.retrieveObject(idAsLong); + if (txId != null) { + queryParamsCopy.put("transactionId", txId); + } - // Did we find it? - if (retrievedVertex.isPresent() - && retrievedVertex.get().getProperties() - .get(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName()) != null - && retrievedVertex.get().getProperties() - .get(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName()).toString() - .equalsIgnoreCase(type)) { + if (!queryParamsCopy.isEmpty()) + { + strBuild.append("?"); + strBuild.append(URLEncodedUtils.format(convertToNameValuePair(queryParamsCopy), Charset.defaultCharset())); + } - // Yup, convert it to a Vector object and return it. - return vertexFromChampObject(retrievedVertex.get(), type); + OperationResult getResult = client.get(strBuild.toString(), createHeader(), MediaType.APPLICATION_JSON_TYPE); + if (getResult.getResultCode() == 200) { + return champGson.fromJson(getResult.getResult(), new TypeToken>() { + }.getType()); } else { - - // We didn't find a vertex with the supplied id, so just throw an - // exception. - throw new CrudException("No vertex with id " + id + " found in graph", - javax.ws.rs.core.Response.Status.NOT_FOUND); + // We didn't find a vertex with the supplied id, so just throw an + // exception. + throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No vertex with id " + id + " found in graph"); } - - } catch (ChampUnmarshallingException | ChampTransactionException e) { - - // Something went wrong - throw an exception. - throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); - } } @Override - public List getVertexEdges(String id) throws CrudException { - - if (logger.isDebugEnabled()) { - logger.debug("get Edges incident to vertex with id: " + id + " from graph"); - } - - try { - long idAsLong = Long.parseLong(id); // GDF - what to do about id??? - - // Request the vertex from the graph db. - Optional retrievedVertex = champApi.retrieveObject(idAsLong); - - // Did we find it? - if (retrievedVertex.isPresent()) { + public OperationResult getVertices(String type, Map filter, String version) throws CrudException { + return getVertices(type, filter, new HashSet(), version); + } - // Query the Champ library for the edges which are incident to the - // specified - // vertex. - Stream relationships = champApi.retrieveRelationships(retrievedVertex.get()); + @Override + public OperationResult getVertices(String type, Map filter, Set properties, String version) throws CrudException { + filter.put(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type); - // Build an edge list from the result stream. - List edges = new ArrayList(); - relationships.forEach(r -> edges.add(edgeFromChampRelationship(r))); + List queryParams = convertToNameValuePair(filter); + queryParams.addAll(convertToNameValuePair("properties", properties)); + String url = baseObjectUrl + "/filter" + "?" + + URLEncodedUtils.format(queryParams, Charset.defaultCharset()); - return edges; + OperationResult getResult = client.get(url, createHeader(), MediaType.APPLICATION_JSON_TYPE); - } else { + if (getResult.getResultCode() == 200) { + return getResult; + } else { + // We didn't find a vertex with the supplied id, so just throw an + // exception. + throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No vertices found in graph for given filters"); + } + } - // We couldn't find the specified vertex, so throw an exception. - throw new CrudException("No vertex with id " + id + " found in graph", + @Override + public OperationResult getEdge(String id, String type, Map queryParams) throws CrudException { + StringBuilder strBuild = new StringBuilder(baseRelationshipUrl); + strBuild.append("/"); + strBuild.append(id); + if(queryParams != null && !queryParams.isEmpty()) + { + strBuild.append("?"); + strBuild.append(URLEncodedUtils.format(convertToNameValuePair(queryParams), Charset.defaultCharset())); + } + OperationResult getResult = client.get(strBuild.toString(), createHeader(), MediaType.APPLICATION_JSON_TYPE); + + if (getResult.getResultCode() == 200) { + Edge edge = Edge.fromJson(getResult.getResult()); + + if (!edge.getType().equalsIgnoreCase(type)) { + // We didn't find an edge with the supplied type, so just throw an + // exception. + throw new CrudException("No edge with id " + id + " and type " + type + " found in graph", javax.ws.rs.core.Response.Status.NOT_FOUND); } + return getResult; + } else { + // We didn't find a edge with the supplied type, so just throw an + // exception. + throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No edge with id " + id + " found in graph"); + } + } - } catch (ChampUnmarshallingException e) { - - // Something went wrong, so throw an exception. - throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); + @Override + public OperationResult getEdges(String type, Map filter) throws CrudException { + String url = baseRelationshipUrl + "/filter" + "?" + + URLEncodedUtils.format(convertToNameValuePair(filter), Charset.defaultCharset()); - } catch (ChampObjectNotExistsException e) { + OperationResult getResult = client.get(url, createHeader(), MediaType.APPLICATION_JSON_TYPE); - // We couldn't find the specified vertex, so throw an exception. - throw new CrudException("No vertex with id " + id + " found in graph", - javax.ws.rs.core.Response.Status.NOT_FOUND); - } catch (ChampTransactionException e) { - throw new CrudException("Transaction error occured", javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); + if (getResult.getResultCode() == 200) { + return getResult; + } else { + // We didn't find a vertex with the supplied id, so just throw an + // exception. + throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No edges found in graph for given filters"); } } @Override - public Vertex addVertex(String type, Map properties) throws CrudException { - - if (logger.isDebugEnabled()) { - logger.debug("Add/update vertex: {label: " + type + " properties:" + propertiesMapToString(properties)); - } + public OperationResult addVertex(String type, Map properties, String version) throws CrudException { + String url = baseObjectUrl; // Add the aai_node_type so that AAI can read the data created by gizmo + // TODO: This probably shouldn't be here properties.put(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type); - // Create an object to represent our vertex in the format expected by the - // Champ library. - ChampObject objectToCreate = buildChampObject(type, properties); - - try { - - // Ask the Champ library to store our vertex, placing the returned object - // into a - // list so that we can easily put that into our result object. - return vertexFromChampObject(champApi.storeObject(objectToCreate), type); + Vertex.Builder insertVertexBuilder = new Vertex.Builder(type); + properties.forEach(insertVertexBuilder::property); + Vertex insertVertex = insertVertexBuilder.build(); - } catch (ChampMarshallingException | ChampSchemaViolationException | ChampObjectNotExistsException - | ChampTransactionException e) { + OperationResult getResult = client.post(url, insertVertex.toJson(), createHeader(), MediaType.APPLICATION_JSON_TYPE, + MediaType.APPLICATION_JSON_TYPE); - // Something went wrong - throw an exception. - throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); + if (getResult.getResultCode() == Response.Status.CREATED.getStatusCode()) { + return getResult; + } else { + // We didn't create a vertex with the supplied type, so just throw an + // exception. + throw new CrudException("Failed to create vertex: " + getResult.getFailureCause(), Response.Status.fromStatusCode(getResult.getResultCode())); } } @Override - public Vertex updateVertex(String id, String type, Map properties) throws CrudException { + public OperationResult updateVertex(String id, String type, Map properties, String version) throws CrudException { + String url = baseObjectUrl + "/" + id; - if (logger.isDebugEnabled()) { - logger.debug("Update vertex with id: " + id + " with properties: " + propertiesMapToString(properties)); - } // Add the aai_node_type so that AAI can read the data created by gizmo + // TODO: This probably shouldn't be here properties.put(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type); - try { - // Now, build the updated version of the Champ Object... - ChampObject updateObject = buildChampObject(id, type, properties); - // ...and send it to the Champ library. - return vertexFromChampObject(champApi.replaceObject(updateObject), type); - - } catch (ChampObjectNotExistsException e) { - throw new CrudException("Not Found", javax.ws.rs.core.Response.Status.NOT_FOUND); - } catch (NumberFormatException | ChampMarshallingException | ChampSchemaViolationException e) { - throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); - } catch (ChampTransactionException e) { - throw new CrudException("Transaction error occured", javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); - } - - } - - @Override - public List getVertices(String type, Map filter) throws CrudException { + Vertex.Builder insertVertexBuilder = new Vertex.Builder(type); + insertVertexBuilder.id(id); + properties.forEach(insertVertexBuilder::property); + Vertex insertVertex = insertVertexBuilder.build(); - if (logger.isDebugEnabled()) { - logger.debug("Retrieve vertices with type label: " + type + " which map query parameters: " - + propertiesMapToString(filter)); - } - - filter.put(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type); - - Stream retrievedVertices; - try { - retrievedVertices = champApi.queryObjects(filter); - - } catch (ChampTransactionException e) { - throw new CrudException("Transaction error occured", javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); - } + String payload = insertVertex.toJson(champGson); + OperationResult getResult = client.put(url, payload, createHeader(), MediaType.APPLICATION_JSON_TYPE, + MediaType.APPLICATION_JSON_TYPE); - List vertices = retrievedVertices.map(v -> vertexFromChampObject(v, type)).collect(Collectors.toList()); - - if (logger.isDebugEnabled()) { - logger.debug("Resulting vertex list: " + retrievedVertices); - } - - // ...and return it to the caller. - return vertices; - } - - private Object getRelKey(String id) { - Object key = id; - // convert into Long if applicable . TODO : revisit in story NUC-304 - try { - key = Long.parseLong(id); - } catch (NumberFormatException e) { - // The id isn't a Long, leave it as a string + if (getResult.getResultCode() == Response.Status.OK.getStatusCode()) { + return getResult; + } else { + // We didn't create a vertex with the supplied type, so just throw an + // exception. + throw new CrudException("Failed to update vertex: " + getResult.getFailureCause(), Response.Status.fromStatusCode(getResult.getResultCode())); } - - return key; } @Override - public Edge getEdge(String id, String type) throws CrudException { - - if (logger.isDebugEnabled()) { - logger.debug("Get edge with id: " + id); - } - - try { - - // Request the edge from the graph db. - Optional relationship = champApi.retrieveRelationship(getRelKey(id)); - - // Did we find it? - if (relationship.isPresent() && relationship.get().getType().equals(type)) { - - // Yup - return the result. - return edgeFromChampRelationship(relationship.get()); - - } else { - - // We didn't find an edge with the supplied id, so throw an exception. - throw new CrudException("No edge with id " + id + " found in graph", - javax.ws.rs.core.Response.Status.NOT_FOUND); - } - - } catch (ChampUnmarshallingException | ChampTransactionException e) { + public void deleteVertex(String id, String type) throws CrudException { + String url = baseObjectUrl + "/" + id; + OperationResult getResult = client.delete(url, createHeader(), MediaType.APPLICATION_JSON_TYPE); - // Something went wrong, so throw an exception. - throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); + if (getResult.getResultCode() != Response.Status.OK.getStatusCode()) { + // We didn't delete a vertex with the supplied id, so just throw an + // exception. + throw new CrudException("Failed to delete vertex: " + getResult.getFailureCause(), Response.Status.fromStatusCode(getResult.getResultCode())); } } @Override - public Edge addEdge(String type, Vertex source, Vertex target, Map properties) throws CrudException { + public OperationResult addEdge(String type, Vertex source, Vertex target, Map properties, String version) throws CrudException { + String url = baseRelationshipUrl; - // For now, assume source and target are straight ids... - try { + // Try requests to ensure source and target exist in Champ + OperationResult dbSourceOpResult = getVertex(source.getId().get(), source.getType(), version, new HashMap()); + Vertex dbSource = Vertex.fromJson(dbSourceOpResult.getResult(), version); + OperationResult dbTargetOpResult = getVertex(target.getId().get(), target.getType(), version, new HashMap()); + Vertex dbTarget = Vertex.fromJson(dbTargetOpResult.getResult(), version); - Optional sourceObject = champApi.retrieveObject(Long.parseLong(source.getId().get())); - if (!sourceObject.isPresent() || !sourceObject.get().getType().equals(source.getType())) { - throw new CrudException( - "Error creating edge - source vertex with id " + source + " does not exist in graph data base", - javax.ws.rs.core.Response.Status.BAD_REQUEST); - } + Edge.Builder insertEdgeBuilder = new Edge.Builder(type).source(dbSource).target(dbTarget); + properties.forEach(insertEdgeBuilder::property); + Edge insertEdge = insertEdgeBuilder.build(); - Optional targetObject = champApi.retrieveObject(Long.parseLong(target.getId().get())); - if (!targetObject.isPresent() || !targetObject.get().getType().equals(target.getType())) { - throw new CrudException( - "Error creating edge - target vertex with id " + target + " does not exist in graph data base", - javax.ws.rs.core.Response.Status.BAD_REQUEST); - } + String edgeJson = insertEdge.toJson(champGson); + OperationResult getResult = client.post(url, edgeJson, createHeader(), MediaType.APPLICATION_JSON_TYPE, + MediaType.APPLICATION_JSON_TYPE); - // Now, create the ChampRelationship object for our edge and store it in - // the graph database. - return edgeFromChampRelationship(champApi.storeRelationship( - new ChampRelationship.Builder(sourceObject.get(), targetObject.get(), type).properties(properties).build())); - - } catch (ChampMarshallingException | ChampObjectNotExistsException | ChampSchemaViolationException - | ChampRelationshipNotExistsException | ChampUnmarshallingException | NumberFormatException - | ChampTransactionException e) { - - throw new CrudException("Error creating edge: " + e.getMessage(), - javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); + if (getResult.getResultCode() == Response.Status.CREATED.getStatusCode()) { + return getResult; + } else { + // We didn't create an edge with the supplied type, so just throw an + // exception. + throw new CrudException("Failed to create edge: " + getResult.getFailureCause(), Response.Status.fromStatusCode(getResult.getResultCode())); } } @Override - public List getEdges(String type, Map filter) throws CrudException { - - filter.put(ChampRelationship.ReservedPropertyKeys.CHAMP_RELATIONSHIP_TYPE.toString(), type); - - Stream retrievedRelationships; - try { - retrievedRelationships = champApi.queryRelationships(filter); - - } catch (ChampTransactionException e) { - throw new CrudException("Transaction error occured", javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); + public OperationResult updateEdge(Edge edge) throws CrudException { + if (!edge.getId().isPresent()) { + throw new CrudException("Unable to identify edge: " + edge.toString(), Response.Status.BAD_REQUEST); } + String url = baseRelationshipUrl + "/" + edge.getId().get(); - // Process the result stream from the Champ library into an Edge list, - // keeping only - // edges of the specified type. - List edges = retrievedRelationships.map(r -> edgeFromChampRelationship(r)).collect(Collectors.toList()); - - return edges; - } - - @Override - public Edge updateEdge(Edge edge) throws CrudException { - - if (logger.isDebugEnabled()) { - logger.debug( - "Update edge with id: " + edge.getId() + " with properties: " + propertiesMapToString(edge.getProperties())); - } + String edgeJson = edge.toJson(champGson); + OperationResult getResult = client.put(url, edgeJson, createHeader(), MediaType.APPLICATION_JSON_TYPE, + MediaType.APPLICATION_JSON_TYPE); - try { - // Now, build the updated version of the Champ Relationship... - ChampRelationship updateRelationship = new ChampRelationship.Builder( - buildChampObject(edge.getSource().getId().get(), edge.getSource().getType(), - edge.getSource().getProperties()), - buildChampObject(edge.getTarget().getId().get(), edge.getTarget().getType(), - edge.getTarget().getProperties()), - edge.getType()).key(getRelKey(edge.getId().get())).properties(edge.getProperties()).build(); - // ...and send it to the Champ library. - return edgeFromChampRelationship(champApi.replaceRelationship(updateRelationship)); - - } catch (ChampRelationshipNotExistsException ex) { - throw new CrudException("Not Found", javax.ws.rs.core.Response.Status.NOT_FOUND); - } catch (NumberFormatException | ChampUnmarshallingException | ChampMarshallingException - | ChampSchemaViolationException | ChampTransactionException ex) { - - throw new CrudException(ex.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); + if (getResult.getResultCode() == Response.Status.OK.getStatusCode()) { + return getResult; + } else { + // We didn't create an edge with the supplied type, so just throw an + // exception. + throw new CrudException("Failed to update edge: " + getResult.getFailureCause(), Response.Status.fromStatusCode(getResult.getResultCode())); } } @Override - public void deleteVertex(String id, String type) throws CrudException { + public void deleteEdge(String id) throws CrudException { + String url = baseRelationshipUrl + "/" + id; + OperationResult getResult = client.delete(url, createHeader(), MediaType.APPLICATION_JSON_TYPE); - try { - - // First, retrieve the vertex that we intend to delete. - Optional retrievedVertex = champApi.retrieveObject(Long.parseLong(id)); - - // Did we find it? - if (!retrievedVertex.isPresent() || !retrievedVertex.get().getType().equals(type)) { - throw new CrudException("Failed to delete vertex with id: " + id + " - vertex does not exist.", - javax.ws.rs.core.Response.Status.NOT_FOUND); - } - - // Now, verify that there are no edges incident to the vertex (they must - // be deleted - // first if so). - Stream relationships = champApi.retrieveRelationships(retrievedVertex.get()); - - if (relationships.count() > 0) { - throw new CrudException("Attempt to delete vertex with id " + id + " which has incident edges.", - javax.ws.rs.core.Response.Status.BAD_REQUEST); - } - - // Finally, we can attempt to delete our vertex. - champApi.deleteObject(Long.parseLong(id)); - - } catch (NumberFormatException | ChampUnmarshallingException | ChampObjectNotExistsException - | ChampTransactionException e) { - - throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); + if (getResult.getResultCode() != 200) { + // We didn't find an edge with the supplied type, so just throw an + // exception. + throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No edge with id " + id + " found in graph"); } } @Override - public void deleteEdge(String id, String type) throws CrudException { - - try { - - // First, retrieve the edge that we want to delete. - Optional relationshipToDelete = champApi.retrieveRelationship(getRelKey(id)); - - // Did we find it? - if (!relationshipToDelete.isPresent() || !relationshipToDelete.get().getType().equals(type)) { - throw new CrudException("Failed to delete edge with id: " + id + " - edge does not exist", - javax.ws.rs.core.Response.Status.NOT_FOUND); - } - - // Now we can delete the edge. - champApi.deleteRelationship(relationshipToDelete.get()); - - } catch (ChampRelationshipNotExistsException | NumberFormatException | ChampUnmarshallingException - | ChampTransactionException e) { - - throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); - } - } - - /** - * This helper method generates a string representation of a properties map - * for logging purposes. - * - * @param properties - * - The properties map to be converted. - * @return - The log statement friendly conversion of the properties map. - */ - private String propertiesMapToString(Map properties) { + public String openTransaction() { + String url = baseTransactionUrl; - StringBuilder sb = new StringBuilder(); - sb.append("{"); + OperationResult getResult = client.post(url, "", createHeader(), MediaType.TEXT_PLAIN_TYPE, MediaType.TEXT_PLAIN_TYPE); - for (String key : properties.keySet()) { - sb.append("(").append(key).append(" -> ").append(properties.get(key)).append(") "); + if (getResult.getResultCode() == 200) { + return getResult.getResult(); + } else { + return null; } - - sb.append("}"); - - return sb.toString(); } - /** - * This helper method constructs a {@link ChampObject} suitable for passing to - * the Champ library. - * - * @param type - * - The type to assign to our ChampObject - * @param properties - * - The set of properties to assign to our ChampObject - * @return - A populated ChampObject - */ - private ChampObject buildChampObject(String type, Map properties) { + @Override + public void commitTransaction(String id) throws CrudException { + String url = baseTransactionUrl + "/" + id; - ObjectBuildOrPropertiesStep objectInProgress = ChampObject.create().ofType(type).withoutKey(); + OperationResult getResult = client.put(url, "{\"method\": \"commit\"}", createHeader(), MediaType.APPLICATION_JSON_TYPE, + MediaType.TEXT_PLAIN_TYPE); - for (String key : properties.keySet()) { - objectInProgress.withProperty(key, properties.get(key)); - } - return objectInProgress.build(); - } - - /** - * This helper method constructs a {@link ChampObject} suitable for passing to - * the Champ library. - * - * @param id - * - Unique identifier for this object. - * @param type - * - The type to assign to our ChampObject - * @param properties - * - The set of properties to assign to our ChampObject - * @return - A populated ChampObject - */ - private ChampObject buildChampObject(String id, String type, Map properties) { - - ObjectBuildOrPropertiesStep objectInProgress = ChampObject.create().ofType(type).withKey(Long.parseLong(id)); - - for (String key : properties.keySet()) { - objectInProgress.withProperty(key, properties.get(key)); + if (getResult.getResultCode() != 200) { + throw new CrudException("Unable to commit transaction", + Response.Status.fromStatusCode(getResult.getResultCode())); } - return objectInProgress.build(); } - private Vertex vertexFromChampObject(ChampObject champObject, String type) { - - // Get the identifier for this vertex from the Champ object. - Object id = champObject.getKey().orElse(""); + @Override + public void rollbackTransaction(String id) throws CrudException { + String url = baseTransactionUrl + "/" + id; - // Start building our {@link Vertex} object. - Vertex.Builder vertexBuilder = new Vertex.Builder(type); - vertexBuilder.id(id.toString()); + OperationResult getResult = client.put(url, "{\"method\": \"rollback\"}", createHeader(), MediaType.APPLICATION_JSON_TYPE, + MediaType.TEXT_PLAIN_TYPE); - // Convert the properties associated with the Champ object into the form - // expected for - // a Vertex object. - for (String key : champObject.getProperties().keySet()) { - vertexBuilder.property(key, champObject.getProperties().get(key)); + if (getResult.getResultCode() != 200) { + throw new CrudException("Unable to rollback transaction", + Response.Status.fromStatusCode(getResult.getResultCode())); } - - // ...and return it. - return vertexBuilder.build(); - } - - /** - * This helper method converts a {@link ChampRelationship} from the Champ - * library into an equivalent {@link Edge} object that is understood by the - * CRUD Service. - * - * @param relationship - * - The ChampRelationship object to be converted. - * @return - An Edge object corresponding to the supplied ChampRelationship - */ - private Edge edgeFromChampRelationship(ChampRelationship relationship) { - - // Populate the edge's id, if available. - Object relationshipId = relationship.getKey().orElse(""); - - Edge.Builder edgeBuilder = new Edge.Builder(relationship.getType()).id(relationshipId.toString()); - edgeBuilder.source(vertexFromChampObject(relationship.getSource(), - relationship.getSource().getProperties() - .get(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName()) == null - ? relationship.getSource().getType() - : relationship.getSource().getProperties() - .get(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName()).toString())); - edgeBuilder.target(vertexFromChampObject(relationship.getTarget(), - relationship.getTarget().getProperties() - .get(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName()) == null - ? relationship.getTarget().getType() - : relationship.getTarget().getProperties() - .get(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName()).toString())); - - for (String key : relationship.getProperties().keySet()) { - edgeBuilder.property(key, relationship.getProperties().get(key).toString()); - } - - return edgeBuilder.build(); } - /** - * Performs any necessary shut down operations when the DAO is no longer - * needed. - */ - public void close() { - - if (champApi != null) { + @Override + public boolean transactionExists(String id) throws CrudException { + String url = baseTransactionUrl + "/" + id; + Map> headers = new HashMap<>(); + headers.put(HEADER_FROM_APP, Arrays.asList("Gizmo")); + headers.put(HEADER_TRANS_ID, Arrays.asList(MDC.get(MdcContext.MDC_REQUEST_ID))); - logger.info(CrudServiceMsgs.STOPPING_CHAMP_DAO); + OperationResult getResult = client.get(url, headers, MediaType.APPLICATION_JSON_TYPE); - champApi.shutdown(); - } + return getResult.getResultCode() == 200; } @Override - public String openTransaction() { + public Vertex addVertex(String type, Map properties, String version, String txId) throws CrudException { + String url = baseObjectUrl + "?transactionId=" + txId; - ChampTransaction transaction = champApi.openTransaction(); + // Add the aai_node_type so that AAI can read the data created by gizmo + // TODO: This probably shouldn't be here + properties.put(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type); - transactions.put(transaction.id(), transaction); - logger.info(CrudServiceMsgs.TRANSACTION, "Stored transaction " + transaction.id() + " in hashmap"); - logger.info(CrudServiceMsgs.TRANSACTION, "Hash map contents:"); - for (String key : transactions.keySet()) { - logger.info(CrudServiceMsgs.TRANSACTION, key); - } - return transaction.id(); - } + Vertex.Builder insertVertexBuilder = new Vertex.Builder(type); + properties.forEach(insertVertexBuilder::property); + Vertex insertVertex = insertVertexBuilder.build(); - @Override - public void commitTransaction(String id) throws CrudException { + OperationResult getResult = client.post(url, insertVertex.toJson(), createHeader(), MediaType.APPLICATION_JSON_TYPE, + MediaType.APPLICATION_JSON_TYPE); - try { - champApi.commitTransaction(getTransaction(id)); - } catch (ChampTransactionException e) { - throw new CrudException("Error while commiting transaction " + id, - javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); + if (getResult.getResultCode() == Response.Status.CREATED.getStatusCode()) { + return Vertex.fromJson(getResult.getResult(), version); + } else { + // We didn't create a vertex with the supplied type, so just throw an + // exception. + throw new CrudException("Failed to create vertex: " + getResult.getFailureCause(), Response.Status.fromStatusCode(getResult.getResultCode())); } - transactions.remove(id); } @Override - public void rollbackTransaction(String id) throws CrudException { + public Edge addEdge(String type, Vertex source, Vertex target, Map properties, String version, String txId) + throws CrudException { + String url = baseRelationshipUrl + "?transactionId=" + txId; - try { - champApi.rollbackTransaction(getTransaction(id)); - } catch (ChampTransactionException e) { - throw new CrudException("Error while transaction rollback " + id, - javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); - } - transactions.remove(id); - } + // Try requests to ensure source and target exist in Champ + Vertex dbSource = getVertex(source.getId().get(), source.getType(), version, txId); + Vertex dbTarget = getVertex(target.getId().get(), target.getType(), version, txId); + + Edge.Builder insertEdgeBuilder = new Edge.Builder(type).source(dbSource).target(dbTarget); + properties.forEach(insertEdgeBuilder::property); + Edge insertEdge = insertEdgeBuilder.build(); - private ChampTransaction getTransaction(String id) throws CrudException { + OperationResult getResult = client.post(url, insertEdge.toJson(champGson), createHeader(), + MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON_TYPE); - logger.info(CrudServiceMsgs.TRANSACTION, "Looking up transaction " + id); - if (transactions.containsKey(id)) { - logger.info(CrudServiceMsgs.TRANSACTION, "Found it!"); - return (transactions.get(id)); + if (getResult.getResultCode() == Response.Status.CREATED.getStatusCode()) { + return Edge.fromJson(getResult.getResult()); } else { - logger.info(CrudServiceMsgs.TRANSACTION, "Didn't find transaction id " + id + ". Hash map contains: "); - for (String key : transactions.keySet()) { - logger.info(CrudServiceMsgs.TRANSACTION, key); - } - throw new CrudException("No open transaction with id: " + id, javax.ws.rs.core.Response.Status.NOT_FOUND); + // We didn't create an edge with the supplied type, so just throw an + // exception. + throw new CrudException("Failed to create edge: " + getResult.getFailureCause(), Response.Status.fromStatusCode(getResult.getResultCode())); } } @Override - public Vertex addVertex(String type, Map properties, String txId) throws CrudException { - if (logger.isDebugEnabled()) { - logger.debug("Add/update vertex: {label: " + type + " properties:" + propertiesMapToString(properties)); - } + public Vertex updateVertex(String id, String type, Map properties, String version, String txId) throws CrudException { + String url = baseObjectUrl + "/" + id + "?transactionId=" + txId; // Add the aai_node_type so that AAI can read the data created by gizmo + // TODO: This probably shouldn't be here properties.put(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type); - // Create an object to represent our vertex in the format expected by the - // Champ library. - ChampObject objectToCreate = buildChampObject(type, properties); - - try { - - // Ask the Champ library to store our vertex, placing the returned object - // into a - // list so that we can easily put that into our result object. - return vertexFromChampObject(champApi.storeObject(objectToCreate, Optional.of(getTransaction(txId))), type); + Vertex.Builder insertVertexBuilder = new Vertex.Builder(type); + insertVertexBuilder.id(id); + properties.forEach(insertVertexBuilder::property); + Vertex insertVertex = insertVertexBuilder.build(); - } catch (ChampMarshallingException | ChampSchemaViolationException | ChampObjectNotExistsException - | ChampTransactionException e) { + String payload = insertVertex.toJson(champGson); + OperationResult getResult = client.put(url, payload, createHeader(), MediaType.APPLICATION_JSON_TYPE, + MediaType.APPLICATION_JSON_TYPE); - // Something went wrong - throw an exception. - throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); + if (getResult.getResultCode() == Response.Status.OK.getStatusCode()) { + return Vertex.fromJson(getResult.getResult(), version); + } else { + // We didn't create a vertex with the supplied type, so just throw an + // exception. + throw new CrudException("Failed to update vertex: " + getResult.getFailureCause(), Response.Status.fromStatusCode(getResult.getResultCode())); } } @Override - public Edge addEdge(String type, Vertex source, Vertex target, Map properties, String txId) - throws CrudException { - // For now, assume source and target are straight ids... - try { - - Optional sourceObject = champApi.retrieveObject(Long.parseLong(source.getId().get()), - Optional.of(getTransaction(txId))); - if (!sourceObject.isPresent() || !sourceObject.get().getType().equals(source.getType())) { - throw new CrudException( - "Error creating edge - source vertex with id " + source + " does not exist in graph data base", - javax.ws.rs.core.Response.Status.BAD_REQUEST); - } - - Optional targetObject = champApi.retrieveObject(Long.parseLong(target.getId().get()), - Optional.of(getTransaction(txId))); - if (!targetObject.isPresent() || !targetObject.get().getType().equals(target.getType())) { - throw new CrudException( - "Error creating edge - target vertex with id " + target + " does not exist in graph data base", - javax.ws.rs.core.Response.Status.BAD_REQUEST); - } - - // Now, create the ChampRelationship object for our edge and store it in - // the graph database. - return edgeFromChampRelationship(champApi.storeRelationship( - new ChampRelationship.Builder(sourceObject.get(), targetObject.get(), type).properties(properties).build(), - Optional.of(getTransaction(txId)))); - - } catch (ChampMarshallingException | ChampObjectNotExistsException | ChampSchemaViolationException - | ChampTransactionException | ChampRelationshipNotExistsException | ChampUnmarshallingException e) { + public void deleteVertex(String id, String type, String txId) throws CrudException { + String url = baseObjectUrl + "/" + id + "?transactionId=" + txId; + OperationResult getResult = client.delete(url, createHeader(), MediaType.APPLICATION_JSON_TYPE); - throw new CrudException("Error creating edge: " + e.getMessage(), - javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); + if (getResult.getResultCode() != Response.Status.OK.getStatusCode()) { + // We didn't delete a vertex with the supplied id, so just throw an + // exception. + throw new CrudException("Failed to delete vertex: " + getResult.getFailureCause(), Response.Status.fromStatusCode(getResult.getResultCode())); } - } @Override - public Vertex updateVertex(String id, String type, Map properties, String txId) throws CrudException { - if (logger.isDebugEnabled()) { - logger.debug("Update vertex with id: " + id + " with properties: " + propertiesMapToString(properties)); + public Edge updateEdge(Edge edge, String txId) throws CrudException { + if (!edge.getId().isPresent()) { + throw new CrudException("Unable to identify edge: " + edge.toString(), Response.Status.BAD_REQUEST); } - // Add the aai_node_type so that AAI can read the data created by gizmo - properties.put(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type); + String url = baseRelationshipUrl + "/" + edge.getId().get() + "?transactionId=" + txId; + OperationResult getResult = client.put(url, edge.toJson(champGson), createHeader(), MediaType.APPLICATION_JSON_TYPE, + MediaType.APPLICATION_JSON_TYPE); - try { - // Now, build the updated version of the Champ Object... - ChampObject updateObject = buildChampObject(id, type, properties); - // ...and send it to the Champ library. - return vertexFromChampObject(champApi.replaceObject(updateObject, Optional.of(getTransaction(txId))), type); - - } catch (ChampObjectNotExistsException e) { - throw new CrudException("Not Found", javax.ws.rs.core.Response.Status.NOT_FOUND); - } catch (NumberFormatException | ChampMarshallingException | ChampTransactionException - | ChampSchemaViolationException e) { - throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); + if (getResult.getResultCode() == Response.Status.OK.getStatusCode()) { + return Edge.fromJson(getResult.getResult()); + } else { + // We didn't create an edge with the supplied type, so just throw an + // exception. + throw new CrudException("Failed to update edge: " + getResult.getFailureCause(), + Response.Status.fromStatusCode(getResult.getResultCode())); } } @Override - public boolean transactionExists(String id) throws CrudException { - return transactions.containsKey(id); + public void deleteEdge(String id, String txId) throws CrudException { + String url = baseRelationshipUrl + "/" + id + "?transactionId=" + txId; + OperationResult getResult = client.delete(url, createHeader(), MediaType.APPLICATION_JSON_TYPE); + + if (getResult.getResultCode() != 200) { + // We didn't find an edge with the supplied type, so just throw an + // exception. + throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No edge with id " + id + " found in graph"); + } } @Override - public void deleteVertex(String id, String type, String txId) throws CrudException { - try { - - // First, retrieve the vertex that we intend to delete. - Optional retrievedVertex = champApi.retrieveObject(Long.parseLong(id), - Optional.of(getTransaction(txId))); + public Edge getEdge(String id, String txId) throws CrudException { + String url = baseRelationshipUrl + "/" + id + "?transactionId=" + txId; + OperationResult getResult = client.get(url, createHeader(), MediaType.APPLICATION_JSON_TYPE); - // Did we find it? - if (!retrievedVertex.isPresent() || !retrievedVertex.get().getType().equals(type)) { - throw new CrudException("Failed to delete vertex with id: " + id + " - vertex does not exist.", - javax.ws.rs.core.Response.Status.NOT_FOUND); - } - - // Now, verify that there are no edges incident to the vertex (they must - // be deleted - // first if so). - Stream relationships = champApi.retrieveRelationships(retrievedVertex.get(), - Optional.of(getTransaction(txId))); - - if (relationships.count() > 0) { - throw new CrudException("Attempt to delete vertex with id " + id + " which has incident edges.", - javax.ws.rs.core.Response.Status.BAD_REQUEST); - } - - // Finally, we can attempt to delete our vertex. - champApi.deleteObject(Long.parseLong(id), Optional.of(getTransaction(txId))); - - } catch (NumberFormatException | ChampUnmarshallingException | ChampObjectNotExistsException - | ChampTransactionException e) { - - throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); + if (getResult.getResultCode() == 200) { + Edge edge = Edge.fromJson(getResult.getResult()); + return edge; + } else { + // We didn't find an edge with the supplied id, so just throw an + // exception. + throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No edge with id " + id + " found in graph"); } - } @Override - public Edge updateEdge(Edge edge, String txId) throws CrudException { - if (logger.isDebugEnabled()) { - logger.debug( - "Update edge with id: " + edge.getId() + " with properties: " + propertiesMapToString(edge.getProperties())); - } + public Edge getEdge(String id) throws CrudException { + String url = baseRelationshipUrl + "/" + id; + OperationResult getResult = client.get(url, createHeader(), MediaType.APPLICATION_JSON_TYPE); - try { - // Now, build the updated version of the Champ Relationship... - ChampRelationship updateRelationship = new ChampRelationship.Builder( - buildChampObject(edge.getSource().getId().get(), edge.getSource().getType(), - edge.getSource().getProperties()), - buildChampObject(edge.getTarget().getId().get(), edge.getTarget().getType(), - edge.getTarget().getProperties()), - edge.getType()).key(getRelKey(edge.getId().get())).properties(edge.getProperties()).build(); - // ...and send it to the Champ library. - return edgeFromChampRelationship( - champApi.replaceRelationship(updateRelationship, Optional.of(getTransaction(txId)))); - - } catch (ChampRelationshipNotExistsException ex) { - throw new CrudException("Not Found", javax.ws.rs.core.Response.Status.NOT_FOUND); - } catch (NumberFormatException | ChampUnmarshallingException | ChampMarshallingException - | ChampSchemaViolationException | ChampTransactionException ex) { - - throw new CrudException(ex.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); + if (getResult.getResultCode() == 200) { + Edge edge = Edge.fromJson(getResult.getResult()); + return edge; + } else { + // We didn't find an edge with the supplied id, so just throw an exception. + throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No edge with id " + id + " found in graph"); } } - @Override - public void deleteEdge(String id, String type, String txId) throws CrudException { - try { + public Vertex getVertex(String id, String type, String version, String txId) throws CrudException { + String url = baseObjectUrl + "/" + id + "?transactionId=" + txId; + OperationResult getResult = client.get(url, createHeader(), MediaType.APPLICATION_JSON_TYPE); - // First, retrieve the edge that we want to delete. - Optional relationshipToDelete = champApi.retrieveRelationship(getRelKey(id), - Optional.of(getTransaction(txId))); + if (getResult.getResultCode() == 200) { + Vertex vert = Vertex.fromJson(getResult.getResult(), version); - // Did we find it? - if (!relationshipToDelete.isPresent() || !relationshipToDelete.get().getType().equals(type)) { - throw new CrudException("Failed to delete edge with id: " + id + " - edge does not exist", + if (!vert.getType().equalsIgnoreCase(type)) { + // We didn't find a vertex with the supplied type, so just throw an + // exception. + throw new CrudException("No vertex with id " + id + " and type " + type + " found in graph", javax.ws.rs.core.Response.Status.NOT_FOUND); } - - // Now we can delete the edge. - champApi.deleteRelationship(relationshipToDelete.get(), Optional.of(getTransaction(txId))); - - } catch (ChampRelationshipNotExistsException | NumberFormatException | ChampUnmarshallingException - | ChampTransactionException e) { - - throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); + return vert; + } else { + // We didn't find a vertex with the supplied id, so just throw an + // exception. + throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No vertex with id " + id + " found in graph"); } - } - @Override - public Edge getEdge(String id, String type, String txId) throws CrudException { - if (logger.isDebugEnabled()) { - logger.debug("Get edge with id: " + id); - } - - try { + // https://stackoverflow.com/questions/26942330/convert-mapstring-string-to-listnamevaluepair-is-this-the-most-efficient + private List convertToNameValuePair(Map pairs) { + List nvpList = new ArrayList<>(pairs.size()); - // Request the edge from the graph db. - Optional relationship = champApi.retrieveRelationship(getRelKey(id), - Optional.of(getTransaction(txId))); + pairs.forEach((key, value) -> nvpList.add(new BasicNameValuePair(key, value.toString()))); - // Did we find it? - if (relationship.isPresent() && relationship.get().getType().equals(type)) { + return nvpList; + } - // Yup - return the result. - return edgeFromChampRelationship(relationship.get()); + // https://stackoverflow.com/questions/26942330/convert-mapstring-string-to-listnamevaluepair-is-this-the-most-efficient + private List convertToNameValuePair(String k, Set values) { + List nvpList = new ArrayList<>(values.size()); - } else { + values.forEach((v) -> nvpList.add(new BasicNameValuePair(k, v))); - // We didn't find an edge with the supplied id, so throw an exception. - throw new CrudException("No edge with id " + id + " found in graph", - javax.ws.rs.core.Response.Status.NOT_FOUND); - } + return nvpList; + } - } catch (ChampUnmarshallingException | ChampTransactionException e) { + private Map> createHeader() { + Map> headers = new HashMap<>(); + headers.put(HEADER_FROM_APP, Arrays.asList(FROM_APP_NAME)); + headers.put(HEADER_TRANS_ID, Arrays.asList(MDC.get(MdcContext.MDC_REQUEST_ID))); + return headers; + } - // Something went wrong, so throw an exception. - throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); - } + private CrudException createErrorException(OperationResult result, javax.ws.rs.core.Response.Status defaultErrorCode , String defaultErrorMsg) + { + CrudException ce = null; + if(result != null) + ce = new CrudException(result.getFailureCause(), Response.Status.fromStatusCode(result.getResultCode())); + else + ce = new CrudException(defaultErrorMsg, defaultErrorCode); + return ce; } }