aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBansal, Nitin (nb121v) <nitin.bansal@amdocs.com>2017-11-16 14:56:59 -0500
committerBansal, Nitin (nb121v) <nitin.bansal@amdocs.com>2017-11-16 15:01:37 -0500
commitbe2eab9395a787ca4b13447f9d2c382d12f5dcd5 (patch)
tree87c81f3a919ca61515212455fc90bc96402de9a5
parenteff2052b4a77690b4e2e67c8a5b438457657c99f (diff)
Add bulk API to gizmo
Add bulk API to gizmo IssueID: AAI-481 Change-Id: Iff9df1a8fdc73c87d726da7294c2eb9f471080f1 Signed-off-by: Bansal, Nitin (nb121v) <nitin.bansal@amdocs.com>
-rw-r--r--pom.xml11
-rw-r--r--src/main/java/org/openecomp/crud/dao/GraphDao.java24
-rw-r--r--src/main/java/org/openecomp/crud/dao/champ/ChampDao.java1343
-rw-r--r--src/main/java/org/openecomp/crud/dao/champion/ChampionDao.java585
-rw-r--r--src/main/java/org/openecomp/crud/dao/champion/ChampionEdgeSerializer.java49
-rw-r--r--src/main/java/org/openecomp/crud/dao/champion/ChampionVertexSerializer.java47
-rw-r--r--src/main/java/org/openecomp/crud/entity/Edge.java16
-rw-r--r--src/main/java/org/openecomp/crud/entity/Vertex.java16
-rw-r--r--src/main/java/org/openecomp/crud/logging/CrudServiceMsgs.java1
-rw-r--r--src/main/java/org/openecomp/crud/logging/LoggingUtil.java2
-rw-r--r--src/main/java/org/openecomp/crud/parser/CrudResponseBuilder.java55
-rw-r--r--src/main/java/org/openecomp/crud/service/BulkPayload.java128
-rw-r--r--src/main/java/org/openecomp/crud/service/CrudGraphDataService.java143
-rw-r--r--src/main/java/org/openecomp/crud/service/CrudRestService.java190
-rw-r--r--src/main/java/org/openecomp/crud/util/CrudServiceConstants.java1
-rw-r--r--src/main/java/org/openecomp/schema/OxmModelValidator.java49
-rw-r--r--src/main/java/org/openecomp/schema/RelationshipSchemaLoader.java39
-rw-r--r--src/main/resources/logging/CrudServiceMsgs.properties3
18 files changed, 2016 insertions, 686 deletions
diff --git a/pom.xml b/pom.xml
index e78968a..be7f88e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -135,7 +135,16 @@
</exclusion>
</exclusions>
</dependency>
-
+ <dependency>
+ <groupId>org.openecomp.aai</groupId>
+ <artifactId>rest-client</artifactId>
+ <version>1.1.1</version>
+ </dependency>
+ <dependency>
+ <groupId>net.dongliu</groupId>
+ <artifactId>gson-java8-datatype</artifactId>
+ <version>1.0.3</version>
+ </dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
diff --git a/src/main/java/org/openecomp/crud/dao/GraphDao.java b/src/main/java/org/openecomp/crud/dao/GraphDao.java
index c714249..67c1ff3 100644
--- a/src/main/java/org/openecomp/crud/dao/GraphDao.java
+++ b/src/main/java/org/openecomp/crud/dao/GraphDao.java
@@ -23,13 +23,14 @@
*/
package org.openecomp.crud.dao;
+import java.util.List;
+import java.util.Map;
+
import org.openecomp.crud.entity.Edge;
+
import org.openecomp.crud.entity.Vertex;
import org.openecomp.crud.exception.CrudException;
-import java.util.List;
-import java.util.Map;
-
public interface GraphDao {
public Vertex getVertex(String id) throws CrudException;
@@ -137,4 +138,21 @@ public interface GraphDao {
* @throws CrudException
*/
public void deleteEdge(String id, String type) throws CrudException;
+
+
+ public String openTransaction();
+ public void commitTransaction(String id) throws CrudException;
+ public void rollbackTransaction(String id) throws CrudException;
+ public boolean transactionExists(String id) throws CrudException;
+
+ public Vertex addVertex(String type, Map<String, Object> properties, String txId) throws CrudException;
+ public Edge addEdge(String type, Vertex source, Vertex target, Map<String, Object> properties, String txId)
+ throws CrudException;
+ public Vertex updateVertex(String id, String type, Map<String, Object> properties, String txId)
+ throws CrudException;
+
+ public Edge updateEdge(Edge edge, String txId) throws CrudException;
+ public void deleteVertex(String id, String type, String txId) throws CrudException;
+ public void deleteEdge(String id, String type, String txId) throws CrudException;
+ public Edge getEdge(String id, String type, String txId) throws CrudException;
}
diff --git a/src/main/java/org/openecomp/crud/dao/champ/ChampDao.java b/src/main/java/org/openecomp/crud/dao/champ/ChampDao.java
index 31bc9ab..ed01038 100644
--- a/src/main/java/org/openecomp/crud/dao/champ/ChampDao.java
+++ b/src/main/java/org/openecomp/crud/dao/champ/ChampDao.java
@@ -23,7 +23,16 @@
*/
package org.openecomp.crud.dao.champ;
+import java.util.ArrayList;
+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.openecomp.aai.champcore.ChampGraph;
+import org.openecomp.aai.champcore.ChampTransaction;
import org.openecomp.aai.champcore.exceptions.ChampMarshallingException;
import org.openecomp.aai.champcore.exceptions.ChampObjectNotExistsException;
import org.openecomp.aai.champcore.exceptions.ChampRelationshipNotExistsException;
@@ -41,628 +50,770 @@ import org.openecomp.crud.entity.Vertex;
import org.openecomp.crud.exception.CrudException;
import org.openecomp.crud.logging.CrudServiceMsgs;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-
/**
- * This is the integration layer between the CRUD API service and the low level Champ library
- * for graph database interaction.
+ * 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 {
- 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";
-
-
- public static final String DEFAULT_GRAPH_NAME = "default_graph";
-
- private enum GraphType {
- IN_MEMORY,
- TITAN,
- DSE
- }
-
- /**
- * Instance of the API used for interacting with the Champ library.
- */
- private ChampGraph champApi = null;
-
- private Logger logger = LoggerFactory.getInstance().getLogger(ChampDao.class.getName());
-
-
- /**
- * Creates a new instance of the ChampDao.
- *
- * @param champGraph - Concrete implementation of the graph dao layer
- */
- public ChampDao(ChampGraph champGraph) {
- this.champApi = champGraph;
- }
-
- @Override
- public Vertex getVertex(String id) throws CrudException {
-
- try {
-
- if (logger.isDebugEnabled()) {
- logger.debug("getVertex with id: " + id);
- }
-
- long idAsLong = Long.parseLong(id);
-
- Optional<ChampObject> retrievedVertex = champApi.retrieveObject(idAsLong);
-
- String nodeType = org.openecomp.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
- // exception.
- throw new CrudException("No vertex with id " + id + " 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);
- }
- }
-
- @Override
- public Vertex getVertex(String id, String type) throws CrudException {
-
- try {
-
- if (logger.isDebugEnabled()) {
- logger.debug("getVertex with id: " + id);
- }
-
- long idAsLong = Long.parseLong(id);
-
- // Request the vertex from the graph db.
- Optional<ChampObject> retrievedVertex = champApi.retrieveObject(idAsLong);
-
- // Did we find it?
- if (retrievedVertex.isPresent() && retrievedVertex.get().getProperties()
- .get(org.openecomp.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName())!=null && retrievedVertex.get().getProperties()
- .get(org.openecomp.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName()).toString()
- .equalsIgnoreCase(type)) {
-
- // Yup, convert it to a Vector object and return it.
- return vertexFromChampObject(retrievedVertex.get(),type);
-
- } 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);
- }
-
- } 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<Edge> 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<ChampObject> retrievedVertex = champApi.retrieveObject(idAsLong);
-
- // Did we find it?
- if (retrievedVertex.isPresent()) {
-
- // Query the Champ library for the edges which are incident to the specified
- // vertex.
- Stream<ChampRelationship> relationships =
- champApi.retrieveRelationships(retrievedVertex.get());
-
- // Build an edge list from the result stream.
- List<Edge> edges = new ArrayList<Edge>();
- relationships.forEach(r -> edges.add(edgeFromChampRelationship(r)));
-
- return edges;
-
- } else {
-
- // 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 (ChampUnmarshallingException e) {
-
- // Something went wrong, so throw an exception.
- throw new CrudException(e.getMessage(),
- javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
+ 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";
+
+ private static Map<String, ChampTransaction> transactions = new ConcurrentHashMap<String, ChampTransaction>();
+ public static final String DEFAULT_GRAPH_NAME = "default_graph";
+
+ private enum GraphType {
+ IN_MEMORY, TITAN, DSE
+ }
+
+ /**
+ * Instance of the API used for interacting with the Champ library.
+ */
+ private ChampGraph champApi = null;
+
+ private Logger logger = LoggerFactory.getInstance().getLogger(ChampDao.class.getName());
+
+ /**
+ * Creates a new instance of the ChampDao.
+ *
+ * @param champGraph
+ * - Concrete implementation of the graph dao layer
+ */
+ public ChampDao(ChampGraph champGraph) {
+ this.champApi = champGraph;
+ }
+
+ @Override
+ public Vertex getVertex(String id) throws CrudException {
+
+ try {
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("getVertex with id: " + id);
+ }
+
+ long idAsLong = Long.parseLong(id);
+
+ Optional<ChampObject> retrievedVertex = champApi.retrieveObject(idAsLong);
+
+ String nodeType = org.openecomp.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
+ // exception.
+ throw new CrudException("No vertex with id " + id + " 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);
+ }
+ }
+
+ @Override
+ public Vertex getVertex(String id, String type) throws CrudException {
+
+ try {
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("getVertex with id: " + id);
+ }
+
+ long idAsLong = Long.parseLong(id);
+
+ // Request the vertex from the graph db.
+ Optional<ChampObject> retrievedVertex = champApi.retrieveObject(idAsLong);
+
+ // Did we find it?
+ if (retrievedVertex.isPresent()
+ && retrievedVertex.get().getProperties().get(org.openecomp.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName()) != null
+ && retrievedVertex.get().getProperties().get(org.openecomp.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName()).toString()
+ .equalsIgnoreCase(type)) {
+
+ // Yup, convert it to a Vector object and return it.
+ return vertexFromChampObject(retrievedVertex.get(), type);
+
+ } 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);
+ }
+
+ } 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<Edge> 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<ChampObject> retrievedVertex = champApi.retrieveObject(idAsLong);
+
+ // Did we find it?
+ if (retrievedVertex.isPresent()) {
+
+ // Query the Champ library for the edges which are incident to the specified
+ // vertex.
+ Stream<ChampRelationship> relationships = champApi.retrieveRelationships(retrievedVertex.get());
+
+ // Build an edge list from the result stream.
+ List<Edge> edges = new ArrayList<Edge>();
+ relationships.forEach(r -> edges.add(edgeFromChampRelationship(r)));
+
+ return edges;
+
+ } else {
+
+ // 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 (ChampUnmarshallingException e) {
+
+ // Something went wrong, so throw an exception.
+ throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
+
+ } catch (ChampObjectNotExistsException e) {
+
+ // 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);
+ }
+ }
+
+ @Override
+ public Vertex addVertex(String type, Map<String, Object> properties) throws CrudException {
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Add/update vertex: {label: " + type + " properties:" + propertiesMapToString(properties));
+ }
+
+ // Add the aai_node_type so that AAI can read the data created by gizmo
+ properties.put(org.openecomp.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);
+
+ } catch (ChampMarshallingException | ChampSchemaViolationException | ChampObjectNotExistsException | ChampTransactionException e) {
+
+ // Something went wrong - throw an exception.
+ throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ @Override
+ public Vertex updateVertex(String id, String type, Map<String, Object> properties) throws CrudException {
+
+ 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
+ properties.put(org.openecomp.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<Vertex> getVertices(String type, Map<String, Object> filter) throws CrudException {
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Retrieve vertices with type label: " + type + " which map query parameters: " + propertiesMapToString(filter));
+ }
+
+ filter.put(org.openecomp.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type);
+
+ Stream<ChampObject> retrievedVertices;
+ try {
+ retrievedVertices = champApi.queryObjects(filter);
+
+ } catch (ChampTransactionException e) {
+ throw new CrudException("Transaction error occured", javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
+ }
+
+ List<Vertex> 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
+ }
+
+ 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<ChampRelationship> 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) {
+
+ // Something went wrong, so throw an exception.
+ throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ @Override
+ public Edge addEdge(String type, Vertex source, Vertex target, Map<String, Object> properties) throws CrudException {
+
+ // For now, assume source and target are straight ids...
+ try {
+
+ Optional<ChampObject> 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);
+ }
+
+ Optional<ChampObject> 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);
+ }
+
+ // 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);
+ }
+ }
+
+ @Override
+ public List<Edge> getEdges(String type, Map<String, Object> filter) throws CrudException {
+
+ filter.put(ChampRelationship.ReservedPropertyKeys.CHAMP_RELATIONSHIP_TYPE.toString(), type);
+
+ Stream<ChampRelationship> retrievedRelationships;
+ try {
+ retrievedRelationships = champApi.queryRelationships(filter);
+
+ } catch (ChampTransactionException e) {
+ throw new CrudException("Transaction error occured", javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
+ }
+
+ // Process the result stream from the Champ library into an Edge list, keeping only
+ // edges of the specified type.
+ List<Edge> 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()));
+ }
+
+ 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);
+ }
+ }
+
+ @Override
+ public void deleteVertex(String id, String type) throws CrudException {
+
+ try {
+
+ // First, retrieve the vertex that we intend to delete.
+ Optional<ChampObject> 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<ChampRelationship> 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);
+ }
+ }
+
+ @Override
+ public void deleteEdge(String id, String type) throws CrudException {
+
+ try {
+
+ // First, retrieve the edge that we want to delete.
+ Optional<ChampRelationship> 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<String, Object> properties) {
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("{");
+
+ for (String key : properties.keySet()) {
+ sb.append("(").append(key).append(" -> ").append(properties.get(key)).append(") ");
+ }
+
+ 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<String, Object> properties) {
+
+ ObjectBuildOrPropertiesStep objectInProgress = ChampObject.create().ofType(type).withoutKey();
+
+ 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<String, Object> properties) {
+
+ ObjectBuildOrPropertiesStep objectInProgress = ChampObject.create().ofType(type).withKey(Long.parseLong(id));
+
+ for (String key : properties.keySet()) {
+ objectInProgress.withProperty(key, properties.get(key));
+ }
+ 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("");
+
+ // Start building our {@link Vertex} object.
+ Vertex.Builder vertexBuilder = new Vertex.Builder(type);
+ vertexBuilder.id(id.toString());
+
+ // 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));
+ }
+
+ // ...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.openecomp.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName()) == null
+ ? relationship.getSource().getType()
+ : relationship.getSource().getProperties().get(org.openecomp.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName()).toString()));
+ edgeBuilder.target(vertexFromChampObject(relationship.getTarget(),
+ relationship.getTarget().getProperties().get(org.openecomp.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName()) == null
+ ? relationship.getTarget().getType()
+ : relationship.getTarget().getProperties().get(org.openecomp.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) {
+
+ logger.info(CrudServiceMsgs.STOPPING_CHAMP_DAO);
+
+ champApi.shutdown();
+ }
+ }
+
+ @Override
+ public String openTransaction() {
+
+ ChampTransaction transaction = champApi.openTransaction();
+
+ 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();
+ }
+
+ @Override
+ public void commitTransaction(String id) throws CrudException {
+
+ 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);
+ }
+ transactions.remove(id);
+ }
+
+ @Override
+ public void rollbackTransaction(String id) throws CrudException {
+
+ 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);
+ }
+
+ private ChampTransaction getTransaction(String id) throws CrudException {
+
+ logger.info(CrudServiceMsgs.TRANSACTION, "Looking up transaction " + id);
+ if (transactions.containsKey(id)) {
+ logger.info(CrudServiceMsgs.TRANSACTION, "Found it!");
+ return (transactions.get(id));
+ } 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);
+ }
+ }
+
+ @Override
+ public Vertex addVertex(String type, Map<String, Object> properties, String txId) throws CrudException {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Add/update vertex: {label: " + type + " properties:" + propertiesMapToString(properties));
+ }
+
+ // Add the aai_node_type so that AAI can read the data created by gizmo
+ properties.put(org.openecomp.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);
+
+ } catch (ChampMarshallingException | ChampSchemaViolationException | ChampObjectNotExistsException | ChampTransactionException e) {
+
+ // Something went wrong - throw an exception.
+ throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ @Override
+ public Edge addEdge(String type, Vertex source, Vertex target, Map<String, Object> properties, String txId) throws CrudException {
+ // For now, assume source and target are straight ids...
+ try {
+
+ Optional<ChampObject> 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<ChampObject> 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) {
+
+ throw new CrudException("Error creating edge: " + e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
+ }
+
+ }
+
+ @Override
+ public Vertex updateVertex(String id, String type, Map<String, Object> properties, String txId) throws CrudException {
+ 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
+ properties.put(org.openecomp.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, 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);
+ }
+ }
+
+ @Override
+ public boolean transactionExists(String id) throws CrudException {
+ return transactions.containsKey(id);
+ }
+
+ @Override
+ public void deleteVertex(String id, String type, String txId) throws CrudException {
+ try {
+
+ // First, retrieve the vertex that we intend to delete.
+ Optional<ChampObject> retrievedVertex = champApi.retrieveObject(Long.parseLong(id), Optional.of(getTransaction(txId)));
+
+ // 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<ChampRelationship> 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 (ChampObjectNotExistsException e) {
+ } catch (NumberFormatException | ChampUnmarshallingException | ChampObjectNotExistsException | ChampTransactionException e) {
- // 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);
- }
- }
+ throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
+ }
+ }
- @Override
- public Vertex addVertex(String type, Map<String, Object> properties) throws CrudException {
+ @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()));
+ }
- if (logger.isDebugEnabled()) {
- logger.debug("Add/update vertex: {label: " + type
- + " properties:" + propertiesMapToString(properties));
- }
+ 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))));
- //Add the aai_node_type so that AAI can read the data created by gizmo
- properties.put(org.openecomp.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type);
+ } catch (ChampRelationshipNotExistsException ex) {
+ throw new CrudException("Not Found", javax.ws.rs.core.Response.Status.NOT_FOUND);
+ } catch (NumberFormatException | ChampUnmarshallingException | ChampMarshallingException | ChampSchemaViolationException
+ | ChampTransactionException ex) {
- // Create an object to represent our vertex in the format expected by the Champ library.
- ChampObject objectToCreate = buildChampObject(type, properties);
+ throw new CrudException(ex.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
+ }
+ }
- try {
+ @Override
+ public void deleteEdge(String id, String type, String txId) throws CrudException {
+ 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);
+ // First, retrieve the edge that we want to delete.
+ Optional<ChampRelationship> relationshipToDelete = champApi.retrieveRelationship(getRelKey(id), Optional.of(getTransaction(txId)));
- } catch (ChampMarshallingException
- | ChampSchemaViolationException
- | ChampObjectNotExistsException
- | ChampTransactionException e) {
+ // 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);
+ }
- // Something went wrong - throw an exception.
- throw new CrudException(e.getMessage(),
- javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
- }
- }
+ // Now we can delete the edge.
+ champApi.deleteRelationship(relationshipToDelete.get(), Optional.of(getTransaction(txId)));
+ } catch (ChampRelationshipNotExistsException | NumberFormatException | ChampUnmarshallingException | ChampTransactionException e) {
- @Override
- public Vertex updateVertex(String id, String type, Map<String, Object> properties)
- throws CrudException {
+ throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
+ }
- 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
- properties.put(org.openecomp.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);
+ @Override
+ public Edge getEdge(String id, String type, String txId) throws CrudException {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Get edge with id: " + id);
+ }
- } 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);
- }
+ try {
- }
+ // Request the edge from the graph db.
+ Optional<ChampRelationship> relationship = champApi.retrieveRelationship(getRelKey(id), Optional.of(getTransaction(txId)));
+ // Did we find it?
+ if (relationship.isPresent() && relationship.get().getType().equals(type)) {
- @Override
- public List<Vertex> getVertices(String type, Map<String, Object> filter) throws CrudException {
+ // Yup - return the result.
+ return edgeFromChampRelationship(relationship.get());
- if (logger.isDebugEnabled()) {
- logger.debug("Retrieve vertices with type label: " + type + " which map query parameters: "
- + propertiesMapToString(filter));
- }
+ } 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);
+ }
- filter.put(org.openecomp.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type);
+ } catch (ChampUnmarshallingException | ChampTransactionException e) {
+ // Something went wrong, so throw an exception.
+ throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
+ }
+ }
- Stream<ChampObject> retrievedVertices;
- try {
- retrievedVertices = champApi.queryObjects(filter);
-
- } catch (ChampTransactionException e) {
- throw new CrudException("Transaction error occured",
- javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
- }
-
- List<Vertex> 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
- }
-
- 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<ChampRelationship> 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) {
-
- // Something went wrong, so throw an exception.
- throw new CrudException(e.getMessage(),
- javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
- }
- }
-
- @Override
- public Edge addEdge(String type,
- Vertex source,
- Vertex target,
- Map<String, Object> properties) throws CrudException {
-
- // For now, assume source and target are straight ids...
- try {
-
- Optional<ChampObject> 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);
- }
-
- Optional<ChampObject> 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);
- }
-
- // 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);
- }
- }
-
-
- @Override
- public List<Edge> getEdges(String type, Map<String, Object> filter) throws CrudException {
-
- filter.put(ChampRelationship.ReservedPropertyKeys.CHAMP_RELATIONSHIP_TYPE.toString(), type);
-
- Stream<ChampRelationship> retrievedRelationships;
- try {
- retrievedRelationships = champApi.queryRelationships(filter);
-
- } catch (ChampTransactionException e) {
- throw new CrudException("Transaction error occured",
- javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
- }
-
- // Process the result stream from the Champ library into an Edge list, keeping only
- // edges of the specified type.
- List<Edge> 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()));
- }
-
- 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);
- }
- }
-
- @Override
- public void deleteVertex(String id, String type) throws CrudException {
-
- try {
-
- // First, retrieve the vertex that we intend to delete.
- Optional<ChampObject> 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<ChampRelationship> 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);
- }
- }
-
- @Override
- public void deleteEdge(String id, String type) throws CrudException {
-
- try {
-
- // First, retrieve the edge that we want to delete.
- Optional<ChampRelationship> 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<String, Object> properties) {
-
- StringBuilder sb = new StringBuilder();
- sb.append("{");
-
- for (String key : properties.keySet()) {
- sb.append("(").append(key).append(" -> ").append(properties.get(key)).append(") ");
- }
-
- 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<String, Object> properties) {
-
- ObjectBuildOrPropertiesStep objectInProgress = ChampObject.create()
- .ofType(type)
- .withoutKey();
-
- 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<String, Object> properties) {
-
- ObjectBuildOrPropertiesStep objectInProgress = ChampObject.create()
- .ofType(type)
- .withKey(Long.parseLong(id));
-
- for (String key : properties.keySet()) {
- objectInProgress.withProperty(key, properties.get(key));
- }
- 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("");
-
- // Start building our {@link Vertex} object.
- Vertex.Builder vertexBuilder = new Vertex.Builder(type);
- vertexBuilder.id(id.toString());
-
- // 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));
- }
-
- // ...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.openecomp.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName()) == null
- ? relationship.getSource().getType()
- : relationship.getSource().getProperties()
- .get(org.openecomp.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName()).toString()));
- edgeBuilder.target(vertexFromChampObject(relationship.getTarget(),
- relationship.getTarget().getProperties()
- .get(org.openecomp.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName()) == null
- ? relationship.getTarget().getType()
- : relationship.getTarget().getProperties()
- .get(org.openecomp.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) {
-
- logger.info(CrudServiceMsgs.STOPPING_CHAMP_DAO);
-
- champApi.shutdown();
- }
- }
}
diff --git a/src/main/java/org/openecomp/crud/dao/champion/ChampionDao.java b/src/main/java/org/openecomp/crud/dao/champion/ChampionDao.java
new file mode 100644
index 0000000..e1bda7a
--- /dev/null
+++ b/src/main/java/org/openecomp/crud/dao/champion/ChampionDao.java
@@ -0,0 +1,585 @@
+/**
+ * ============LICENSE_START=======================================================
+ * Gizmo
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * 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
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * 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.openecomp.crud.dao.champion;
+
+import net.dongliu.gson.GsonJava8TypeAdapterFactory;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.reflect.TypeToken;
+
+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.openecomp.aai.logging.LoggingContext;
+import org.openecomp.cl.api.Logger;
+import org.openecomp.cl.eelf.LoggerFactory;
+import org.openecomp.crud.dao.GraphDao;
+import org.openecomp.crud.entity.Edge;
+import org.openecomp.crud.entity.Vertex;
+import org.openecomp.crud.exception.CrudException;
+import org.openecomp.crud.util.CrudServiceConstants;
+import org.openecomp.restclient.client.OperationResult;
+import org.openecomp.restclient.client.RestClient;
+import org.openecomp.restclient.enums.RestAuthenticationMode;
+import org.slf4j.MDC;
+
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+public class ChampionDao implements GraphDao {
+ private RestClient client;
+ private String baseUrl;
+
+ private static final String HEADER_FROM_APP = "X-FromAppId";
+ private static final String HEADER_TRANS_ID = "X-TransactionId";
+
+ private Logger logger = LoggerFactory.getInstance().getLogger(ChampionDao.class.getName());
+
+ // We use a custom vertex serializer for Champion because it expects "key" instead of "id"
+ private static final Gson championGson = new GsonBuilder()
+ .registerTypeAdapterFactory(new GsonJava8TypeAdapterFactory())
+ .registerTypeAdapter(Vertex.class, new ChampionVertexSerializer())
+ .registerTypeAdapter(Edge.class, new ChampionEdgeSerializer())
+ .create();
+
+ public ChampionDao(String championUrl, String certPassword) {
+ try {
+ client = new RestClient().authenticationMode(RestAuthenticationMode.SSL_CERT)
+ .validateServerHostname(false)
+ .validateServerCertChain(false)
+ .clientCertFile(CrudServiceConstants.CRD_CHAMPION_AUTH_FILE)
+ .clientCertPassword(Password.deobfuscate(certPassword));
+
+ baseUrl = championUrl;
+ } catch (Exception e) {
+ System.out.println("Error setting up Champion configuration");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ @Override
+ public Vertex getVertex(String id) throws CrudException {
+ String url = baseUrl + "objects/" + id;
+ Map<String, List<String>> headers = new HashMap<>();
+ headers.put(HEADER_FROM_APP, Arrays.asList("Gizmo"));
+ headers.put(HEADER_TRANS_ID, Arrays.asList(MDC.get(LoggingContext.LoggingField.REQUEST_ID.toString())));
+
+ OperationResult getResult = client.get(url, headers, MediaType.APPLICATION_JSON_TYPE);
+
+ if (getResult.getResultCode() == 200) {
+ return Vertex.fromJson(getResult.getResult());
+ } 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);
+ }
+ }
+
+ @Override
+ public Vertex getVertex(String id, String type) throws CrudException {
+ String url = baseUrl + "objects/" + id;
+ Map<String, List<String>> headers = new HashMap<>();
+ headers.put(HEADER_FROM_APP, Arrays.asList("Gizmo"));
+ headers.put(HEADER_TRANS_ID, Arrays.asList(MDC.get(LoggingContext.LoggingField.REQUEST_ID.toString())));
+
+ OperationResult getResult = client.get(url, headers, MediaType.APPLICATION_JSON_TYPE);
+
+ if (getResult.getResultCode() == 200) {
+ Vertex vert = Vertex.fromJson(getResult.getResult());
+
+ 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);
+ }
+ return vert;
+ } 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);
+ }
+ }
+
+ @Override
+ public List<Edge> getVertexEdges(String id) throws CrudException {
+ String url = baseUrl + "objects/relationships/" + id;
+ Map<String, List<String>> headers = new HashMap<>();
+ headers.put(HEADER_FROM_APP, Arrays.asList("Gizmo"));
+ headers.put(HEADER_TRANS_ID, Arrays.asList(MDC.get(LoggingContext.LoggingField.REQUEST_ID.toString())));
+
+ OperationResult getResult = client.get(url, headers, MediaType.APPLICATION_JSON_TYPE);
+
+ if (getResult.getResultCode() == 200) {
+ return championGson.fromJson(getResult.getResult(), new TypeToken<List<Edge>>(){}.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);
+ }
+ }
+
+ @Override
+ public List<Vertex> getVertices(String type, Map<String, Object> filter) throws CrudException {
+ filter.put(org.openecomp.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type);
+
+ String url = baseUrl + "objects/filter" + "?" +
+ URLEncodedUtils.format(convertToNameValuePair(filter), Charset.defaultCharset());
+
+ Map<String, List<String>> headers = new HashMap<>();
+ headers.put(HEADER_FROM_APP, Arrays.asList("Gizmo"));
+ headers.put(HEADER_TRANS_ID, Arrays.asList(MDC.get(LoggingContext.LoggingField.REQUEST_ID.toString())));
+
+ OperationResult getResult = client.get(url, headers, MediaType.APPLICATION_JSON_TYPE);
+
+ if (getResult.getResultCode() == 200) {
+ return championGson.fromJson(getResult.getResult(), new TypeToken<List<Vertex>>(){}.getType());
+ } else {
+ // We didn't find a vertex with the supplied id, so just throw an exception.
+ throw new CrudException("No vertices found in graph for given filters", javax.ws.rs.core.Response.Status.NOT_FOUND);
+ }
+ }
+
+ @Override
+ public Edge getEdge(String id, String type) throws CrudException {
+ String url = baseUrl + "relationships/" + id;
+ Map<String, List<String>> headers = new HashMap<>();
+ headers.put(HEADER_FROM_APP, Arrays.asList("Gizmo"));
+ headers.put(HEADER_TRANS_ID, Arrays.asList(MDC.get(LoggingContext.LoggingField.REQUEST_ID.toString())));
+
+ OperationResult getResult = client.get(url, headers, 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 edge;
+ } else {
+ // We didn't find a edge with the supplied type, so just throw an exception.
+ throw new CrudException("No edge with id " + id + " found in graph", javax.ws.rs.core.Response.Status.NOT_FOUND);
+ }
+ }
+
+ @Override
+ public List<Edge> getEdges(String type, Map<String, Object> filter) throws CrudException {
+ String url = baseUrl + "relationships/filter" + "?" +
+ URLEncodedUtils.format(convertToNameValuePair(filter), Charset.defaultCharset());
+
+ Map<String, List<String>> headers = new HashMap<>();
+ headers.put(HEADER_FROM_APP, Arrays.asList("Gizmo"));
+ headers.put(HEADER_TRANS_ID, Arrays.asList(MDC.get(LoggingContext.LoggingField.REQUEST_ID.toString())));
+
+ OperationResult getResult = client.get(url, headers, MediaType.APPLICATION_JSON_TYPE);
+
+ if (getResult.getResultCode() == 200) {
+ return championGson.fromJson(getResult.getResult(), new TypeToken<List<Edge>>(){}.getType());
+ } else {
+ // We didn't find a vertex with the supplied id, so just throw an exception.
+ throw new CrudException("No edges found in graph for given filters", javax.ws.rs.core.Response.Status.NOT_FOUND);
+ }
+ }
+
+ @Override
+ public Vertex addVertex(String type, Map<String, Object> properties) throws CrudException {
+ String url = baseUrl + "objects";
+ Map<String, List<String>> headers = new HashMap<>();
+ headers.put(HEADER_FROM_APP, Arrays.asList("Gizmo"));
+ headers.put(HEADER_TRANS_ID, Arrays.asList(MDC.get(LoggingContext.LoggingField.REQUEST_ID.toString())));
+
+ // 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.openecomp.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type);
+
+ Vertex.Builder insertVertexBuilder = new Vertex.Builder(type);
+ properties.forEach(insertVertexBuilder::property);
+ Vertex insertVertex = insertVertexBuilder.build();
+
+ OperationResult getResult = client.post(url, insertVertex.toJson(), headers,
+ MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON_TYPE);
+
+ if (getResult.getResultCode() == Response.Status.CREATED.getStatusCode()) {
+ return Vertex.fromJson(getResult.getResult());
+ } else {
+ // We didn't create a vertex with the supplied type, so just throw an exception.
+ throw new CrudException("Failed to create vertex", Response.Status.fromStatusCode(getResult.getResultCode()));
+ }
+ }
+
+ @Override
+ public Vertex updateVertex(String id, String type, Map<String, Object> properties) throws CrudException {
+ String url = baseUrl + "objects/" + id;
+ Map<String, List<String>> headers = new HashMap<>();
+ headers.put(HEADER_FROM_APP, Arrays.asList("Gizmo"));
+ headers.put(HEADER_TRANS_ID, Arrays.asList(MDC.get(LoggingContext.LoggingField.REQUEST_ID.toString())));
+
+ // 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.openecomp.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type);
+
+ Vertex.Builder insertVertexBuilder = new Vertex.Builder(type);
+ insertVertexBuilder.id(id);
+ properties.forEach(insertVertexBuilder::property);
+ Vertex insertVertex = insertVertexBuilder.build();
+
+ String payload = insertVertex.toJson(championGson);
+ OperationResult getResult = client.put(url, payload, headers,
+ MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON_TYPE);
+
+ if (getResult.getResultCode() == Response.Status.OK.getStatusCode()) {
+ return Vertex.fromJson(getResult.getResult());
+ } else {
+ // We didn't create a vertex with the supplied type, so just throw an exception.
+ throw new CrudException("Failed to update vertex", Response.Status.fromStatusCode(getResult.getResultCode()));
+ }
+ }
+
+ @Override
+ public void deleteVertex(String id, String type) throws CrudException {
+ String url = baseUrl + "objects/" + id;
+ Map<String, List<String>> headers = new HashMap<>();
+ headers.put(HEADER_FROM_APP, Arrays.asList("Gizmo"));
+ headers.put(HEADER_TRANS_ID, Arrays.asList(MDC.get(LoggingContext.LoggingField.REQUEST_ID.toString())));
+
+ OperationResult getResult = client.delete(url, headers, MediaType.APPLICATION_JSON_TYPE);
+
+ 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", Response.Status.fromStatusCode(getResult.getResultCode()));
+ }
+ }
+
+ @Override
+ public Edge addEdge(String type, Vertex source, Vertex target, Map<String, Object> properties) throws CrudException {
+ String url = baseUrl + "relationships";
+ Map<String, List<String>> headers = new HashMap<>();
+ headers.put(HEADER_FROM_APP, Arrays.asList("Gizmo"));
+ headers.put(HEADER_TRANS_ID, Arrays.asList(MDC.get(LoggingContext.LoggingField.REQUEST_ID.toString())));
+
+ // Try requests to ensure source and target exist in Champion
+ Vertex dbSource = getVertex(source.getId().get(), source.getType());
+ Vertex dbTarget = getVertex(target.getId().get(), target.getType());
+
+ Edge.Builder insertEdgeBuilder = new Edge.Builder(type).source(dbSource).target(dbTarget);
+ properties.forEach(insertEdgeBuilder::property);
+ Edge insertEdge = insertEdgeBuilder.build();
+
+ String edgeJson = insertEdge.toJson(championGson);
+ OperationResult getResult = client.post(url, edgeJson, headers,
+ MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON_TYPE);
+
+ if (getResult.getResultCode() == Response.Status.CREATED.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 create edge", Response.Status.fromStatusCode(getResult.getResultCode()));
+ }
+ }
+
+ @Override
+ public Edge updateEdge(Edge edge) throws CrudException {
+ if (!edge.getId().isPresent())
+ {
+ throw new CrudException("Unable to identify edge: " + edge.toString(), Response.Status.BAD_REQUEST);
+ }
+ String url = baseUrl + "relationships/" + edge.getId().get();
+ Map<String, List<String>> headers = new HashMap<>();
+ headers.put(HEADER_FROM_APP, Arrays.asList("Gizmo"));
+ headers.put(HEADER_TRANS_ID, Arrays.asList(MDC.get(LoggingContext.LoggingField.REQUEST_ID.toString())));
+
+ String edgeJson = edge.toJson(championGson);
+ OperationResult getResult = client.put(url, edgeJson, headers,
+ MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON_TYPE);
+
+ 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", Response.Status.fromStatusCode(getResult.getResultCode()));
+ }
+ }
+
+ @Override
+ public void deleteEdge(String id, String type) throws CrudException {
+ String url = baseUrl + "relationships/" + id;
+ Map<String, List<String>> headers = new HashMap<>();
+ headers.put(HEADER_FROM_APP, Arrays.asList("Gizmo"));
+ headers.put(HEADER_TRANS_ID, Arrays.asList(MDC.get(LoggingContext.LoggingField.REQUEST_ID.toString())));
+
+ OperationResult getResult = client.delete(url, headers, MediaType.APPLICATION_JSON_TYPE);
+
+ if (getResult.getResultCode() != 200) {
+ // We didn't find an edge with the supplied type, so just throw an exception.
+ throw new CrudException("No edge with id " + id + " found in graph", javax.ws.rs.core.Response.Status.NOT_FOUND);
+ }
+ }
+
+ @Override
+ public String openTransaction() {
+ String url = baseUrl + "transaction";
+ Map<String, List<String>> headers = new HashMap<>();
+ headers.put(HEADER_FROM_APP, Arrays.asList("Gizmo"));
+ headers.put(HEADER_TRANS_ID, Arrays.asList(MDC.get(LoggingContext.LoggingField.REQUEST_ID.toString())));
+
+ OperationResult getResult = client.post(url, "", headers, MediaType.TEXT_PLAIN_TYPE, MediaType.TEXT_PLAIN_TYPE);
+
+ if (getResult.getResultCode() == 200) {
+ return getResult.getResult();
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public void commitTransaction(String id) throws CrudException {
+ String url = baseUrl + "transaction/" + id;
+ Map<String, List<String>> headers = new HashMap<>();
+ headers.put(HEADER_FROM_APP, Arrays.asList("Gizmo"));
+ headers.put(HEADER_TRANS_ID, Arrays.asList(MDC.get(LoggingContext.LoggingField.REQUEST_ID.toString())));
+
+ OperationResult getResult = client.put(url, "{\"method\": \"commit\"}", headers, MediaType.APPLICATION_JSON_TYPE, MediaType.TEXT_PLAIN_TYPE);
+
+ if (getResult.getResultCode() != 200) {
+ throw new CrudException("Unable to commit transaction", Response.Status.fromStatusCode(getResult.getResultCode()));
+ }
+ }
+
+ @Override
+ public void rollbackTransaction(String id) throws CrudException {
+ String url = baseUrl + "transaction/" + id;
+ Map<String, List<String>> headers = new HashMap<>();
+ headers.put(HEADER_FROM_APP, Arrays.asList("Gizmo"));
+ headers.put(HEADER_TRANS_ID, Arrays.asList(MDC.get(LoggingContext.LoggingField.REQUEST_ID.toString())));
+
+ OperationResult getResult = client.put(url, "{\"method\": \"rollback\"}", headers, MediaType.APPLICATION_JSON_TYPE, MediaType.TEXT_PLAIN_TYPE);
+
+ if (getResult.getResultCode() != 200) {
+ throw new CrudException("Unable to rollback transaction", Response.Status.fromStatusCode(getResult.getResultCode()));
+ }
+ }
+
+ @Override
+ public boolean transactionExists(String id) throws CrudException {
+ String url = baseUrl + "transaction/" + id;
+ Map<String, List<String>> headers = new HashMap<>();
+ headers.put(HEADER_FROM_APP, Arrays.asList("Gizmo"));
+ headers.put(HEADER_TRANS_ID, Arrays.asList(MDC.get(LoggingContext.LoggingField.REQUEST_ID.toString())));
+
+ OperationResult getResult = client.get(url, headers, MediaType.APPLICATION_JSON_TYPE);
+
+ return getResult.getResultCode() == 200;
+ }
+
+ @Override
+ public Vertex addVertex(String type, Map<String, Object> properties, String txId) throws CrudException {
+ String url = baseUrl + "objects?transactionId=" + txId;
+ Map<String, List<String>> headers = new HashMap<>();
+ headers.put(HEADER_FROM_APP, Arrays.asList("Gizmo"));
+ headers.put(HEADER_TRANS_ID, Arrays.asList(MDC.get(LoggingContext.LoggingField.REQUEST_ID.toString())));
+
+ // 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.openecomp.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type);
+
+ Vertex.Builder insertVertexBuilder = new Vertex.Builder(type);
+ properties.forEach(insertVertexBuilder::property);
+ Vertex insertVertex = insertVertexBuilder.build();
+
+ OperationResult getResult = client.post(url, insertVertex.toJson(), headers,
+ MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON_TYPE);
+
+ if (getResult.getResultCode() == Response.Status.CREATED.getStatusCode()) {
+ return Vertex.fromJson(getResult.getResult());
+ } else {
+ // We didn't create a vertex with the supplied type, so just throw an exception.
+ throw new CrudException("Failed to create vertex", Response.Status.fromStatusCode(getResult.getResultCode()));
+ }
+ }
+
+ @Override
+ public Edge addEdge(String type, Vertex source, Vertex target, Map<String, Object> properties, String txId) throws CrudException {
+ String url = baseUrl + "relationships?transactionId=" + txId;
+ Map<String, List<String>> headers = new HashMap<>();
+ headers.put(HEADER_FROM_APP, Arrays.asList("Gizmo"));
+ headers.put(HEADER_TRANS_ID, Arrays.asList(MDC.get(LoggingContext.LoggingField.REQUEST_ID.toString())));
+
+ // Try requests to ensure source and target exist in Champion
+ Vertex dbSource = getVertex(source.getId().get(), source.getType(), txId);
+ Vertex dbTarget = getVertex(target.getId().get(), target.getType(), txId);
+
+ Edge.Builder insertEdgeBuilder = new Edge.Builder(type).source(dbSource).target(dbTarget);
+ properties.forEach(insertEdgeBuilder::property);
+ Edge insertEdge = insertEdgeBuilder.build();
+
+ OperationResult getResult = client.post(url, insertEdge.toJson(championGson), headers,
+ MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON_TYPE);
+
+ if (getResult.getResultCode() == Response.Status.CREATED.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 create edge", Response.Status.fromStatusCode(getResult.getResultCode()));
+ }
+ }
+
+ @Override
+ public Vertex updateVertex(String id, String type, Map<String, Object> properties, String txId) throws CrudException {
+ String url = baseUrl + "objects/" + id + "?transactionId=" + txId;
+ Map<String, List<String>> headers = new HashMap<>();
+ headers.put(HEADER_FROM_APP, Arrays.asList("Gizmo"));
+ headers.put(HEADER_TRANS_ID, Arrays.asList(MDC.get(LoggingContext.LoggingField.REQUEST_ID.toString())));
+
+ // 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.openecomp.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type);
+
+ Vertex.Builder insertVertexBuilder = new Vertex.Builder(type);
+ insertVertexBuilder.id(id);
+ properties.forEach(insertVertexBuilder::property);
+ Vertex insertVertex = insertVertexBuilder.build();
+
+ String payload = insertVertex.toJson(championGson);
+ OperationResult getResult = client.put(url, payload, headers,
+ MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON_TYPE);
+
+ if (getResult.getResultCode() == Response.Status.OK.getStatusCode()) {
+ return Vertex.fromJson(getResult.getResult());
+ } else {
+ // We didn't create a vertex with the supplied type, so just throw an exception.
+ throw new CrudException("Failed to update vertex", Response.Status.fromStatusCode(getResult.getResultCode()));
+ }
+ }
+
+ @Override
+ public void deleteVertex(String id, String type, String txId) throws CrudException {
+ String url = baseUrl + "objects/" + id + "?transactionId=" + txId;
+ Map<String, List<String>> headers = new HashMap<>();
+ headers.put(HEADER_FROM_APP, Arrays.asList("Gizmo"));
+ headers.put(HEADER_TRANS_ID, Arrays.asList(MDC.get(LoggingContext.LoggingField.REQUEST_ID.toString())));
+
+ OperationResult getResult = client.delete(url, headers, MediaType.APPLICATION_JSON_TYPE);
+
+ 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", Response.Status.fromStatusCode(getResult.getResultCode()));
+ }
+ }
+
+ @Override
+ 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);
+ }
+ String url = baseUrl + "relationships/" + edge.getId().get() + "?transactionId=" + txId;
+ Map<String, List<String>> headers = new HashMap<>();
+ headers.put(HEADER_FROM_APP, Arrays.asList("Gizmo"));
+ headers.put(HEADER_TRANS_ID, Arrays.asList(MDC.get(LoggingContext.LoggingField.REQUEST_ID.toString())));
+
+ OperationResult getResult = client.put(url, edge.toJson(championGson), headers,
+ MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON_TYPE);
+
+ 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 void deleteEdge(String id, String type, String txId) throws CrudException {
+ String url = baseUrl + "relationships/" + id + "?transactionId=" + txId;
+ Map<String, List<String>> headers = new HashMap<>();
+ headers.put(HEADER_FROM_APP, Arrays.asList("Gizmo"));
+ headers.put(HEADER_TRANS_ID, Arrays.asList(MDC.get(LoggingContext.LoggingField.REQUEST_ID.toString())));
+
+ OperationResult getResult = client.delete(url, headers, MediaType.APPLICATION_JSON_TYPE);
+
+ if (getResult.getResultCode() != 200) {
+ // We didn't find an edge with the supplied type, so just throw an exception.
+ throw new CrudException("No edge with id " + id + " found in graph", javax.ws.rs.core.Response.Status.NOT_FOUND);
+ }
+ }
+
+ @Override
+ public Edge getEdge(String id, String type, String txId) throws CrudException {
+ String url = baseUrl + "relationships/" + id + "?transactionId=" + txId;
+ Map<String, List<String>> headers = new HashMap<>();
+ headers.put(HEADER_FROM_APP, Arrays.asList("Gizmo"));
+ headers.put(HEADER_TRANS_ID, Arrays.asList(MDC.get(LoggingContext.LoggingField.REQUEST_ID.toString())));
+
+ OperationResult getResult = client.get(url, headers, 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 edge;
+ } else {
+ // We didn't find an edge with the supplied id, so just throw an exception.
+ throw new CrudException("No edge with id " + id + " found in graph", javax.ws.rs.core.Response.Status.NOT_FOUND);
+ }
+ }
+
+ public Vertex getVertex(String id, String type, String txId) throws CrudException {
+ String url = baseUrl + "objects/" + id + "?transactionId=" + txId;
+ Map<String, List<String>> headers = new HashMap<>();
+ headers.put(HEADER_FROM_APP, Arrays.asList("Gizmo"));
+ headers.put(HEADER_TRANS_ID, Arrays.asList(MDC.get(LoggingContext.LoggingField.REQUEST_ID.toString())));
+
+ OperationResult getResult = client.get(url, headers, MediaType.APPLICATION_JSON_TYPE);
+
+ if (getResult.getResultCode() == 200) {
+ Vertex vert = Vertex.fromJson(getResult.getResult());
+
+ 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);
+ }
+ return vert;
+ } 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);
+ }
+ }
+
+ // https://stackoverflow.com/questions/26942330/convert-mapstring-string-to-listnamevaluepair-is-this-the-most-efficient
+ private List<NameValuePair> convertToNameValuePair(Map<String, Object> pairs) {
+ List<NameValuePair> nvpList = new ArrayList<>(pairs.size());
+
+ pairs.forEach((key, value) -> nvpList.add(new BasicNameValuePair(key, value.toString())));
+
+ return nvpList;
+ }
+}
diff --git a/src/main/java/org/openecomp/crud/dao/champion/ChampionEdgeSerializer.java b/src/main/java/org/openecomp/crud/dao/champion/ChampionEdgeSerializer.java
new file mode 100644
index 0000000..5ca6c2c
--- /dev/null
+++ b/src/main/java/org/openecomp/crud/dao/champion/ChampionEdgeSerializer.java
@@ -0,0 +1,49 @@
+/**
+ * ============LICENSE_START=======================================================
+ * Gizmo
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * 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
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * 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.openecomp.crud.dao.champion;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+
+import org.openecomp.crud.entity.Edge;
+import org.openecomp.crud.entity.Vertex;
+
+import java.lang.reflect.Type;
+
+public class ChampionEdgeSerializer implements JsonSerializer<Edge> {
+ @Override
+ public JsonElement serialize(Edge edge, Type type, JsonSerializationContext jsonSerializationContext) {
+ final JsonObject edgeObj = new JsonObject();
+ if (edge.getId().isPresent()) {
+ edgeObj.add("key", jsonSerializationContext.serialize(edge.getId().get()));
+ }
+ edgeObj.add("type", jsonSerializationContext.serialize(edge.getType()));
+ edgeObj.add("properties", jsonSerializationContext.serialize(edge.getProperties()));
+ edgeObj.add("source", jsonSerializationContext.serialize(edge.getSource()));
+ edgeObj.add("target", jsonSerializationContext.serialize(edge.getTarget()));
+ return edgeObj;
+ }
+}
diff --git a/src/main/java/org/openecomp/crud/dao/champion/ChampionVertexSerializer.java b/src/main/java/org/openecomp/crud/dao/champion/ChampionVertexSerializer.java
new file mode 100644
index 0000000..ab743d7
--- /dev/null
+++ b/src/main/java/org/openecomp/crud/dao/champion/ChampionVertexSerializer.java
@@ -0,0 +1,47 @@
+/**
+ * ============LICENSE_START=======================================================
+ * Gizmo
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * 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
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * 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.openecomp.crud.dao.champion;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+
+import org.openecomp.crud.entity.Vertex;
+
+import java.lang.reflect.Type;
+
+public class ChampionVertexSerializer implements JsonSerializer<Vertex> {
+ @Override
+ public JsonElement serialize(Vertex vertex, Type type, JsonSerializationContext jsonSerializationContext) {
+ final JsonObject vertexObj = new JsonObject();
+ if (vertex.getId().isPresent()) {
+ vertexObj.add("key", jsonSerializationContext.serialize(vertex.getId().get()));
+ }
+ vertexObj.add("type", jsonSerializationContext.serialize(vertex.getType()));
+ vertexObj.add("properties", jsonSerializationContext.serialize(vertex.getProperties()));
+
+ return vertexObj;
+ }
+}
diff --git a/src/main/java/org/openecomp/crud/entity/Edge.java b/src/main/java/org/openecomp/crud/entity/Edge.java
index 803511f..ceae494 100644
--- a/src/main/java/org/openecomp/crud/entity/Edge.java
+++ b/src/main/java/org/openecomp/crud/entity/Edge.java
@@ -23,16 +23,22 @@
*/
package org.openecomp.crud.entity;
+import net.dongliu.gson.GsonJava8TypeAdapterFactory;
+
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
+import com.google.gson.annotations.SerializedName;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
public class Edge {
- private static final Gson gson = new GsonBuilder().create();
+ private static final Gson gson = new GsonBuilder()
+ .registerTypeAdapterFactory(new GsonJava8TypeAdapterFactory())
+ .create();
+ @SerializedName(value="id", alternate={"key"})
private final Optional<String> id;
private final String type;
private final Map<String, Object> properties;
@@ -106,6 +112,14 @@ public class Edge {
return gson.toJson(this);
}
+ public String toJson(Gson customGson) {
+ return customGson.toJson(this);
+ }
+
+ public static Edge fromJson(String jsonString) {
+ return gson.fromJson(jsonString, Edge.class);
+ }
+
public Optional<String> getId() {
return id;
}
diff --git a/src/main/java/org/openecomp/crud/entity/Vertex.java b/src/main/java/org/openecomp/crud/entity/Vertex.java
index 1b0b97d..d2f2b08 100644
--- a/src/main/java/org/openecomp/crud/entity/Vertex.java
+++ b/src/main/java/org/openecomp/crud/entity/Vertex.java
@@ -23,17 +23,23 @@
*/
package org.openecomp.crud.entity;
+import net.dongliu.gson.GsonJava8TypeAdapterFactory;
+
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
+import com.google.gson.annotations.SerializedName;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
public class Vertex {
- private static final Gson gson = new GsonBuilder().create();
+ private static final Gson gson = new GsonBuilder()
+ .registerTypeAdapterFactory(new GsonJava8TypeAdapterFactory()).create();
+ @SerializedName(value="id", alternate={"key"})
private final Optional<String> id;
+
private final String type;
private final Map<String, Object> properties;
@@ -82,6 +88,14 @@ public class Vertex {
return gson.toJson(this);
}
+ public String toJson(Gson customGson) {
+ return customGson.toJson(this);
+ }
+
+ public static Vertex fromJson(String jsonString) {
+ return gson.fromJson(jsonString, Vertex.class);
+ }
+
@Override
public String toString() {
return "Vertex [id=" + id + ", type=" + type + ", properties=" + properties + "]";
diff --git a/src/main/java/org/openecomp/crud/logging/CrudServiceMsgs.java b/src/main/java/org/openecomp/crud/logging/CrudServiceMsgs.java
index 265f327..98cc4fa 100644
--- a/src/main/java/org/openecomp/crud/logging/CrudServiceMsgs.java
+++ b/src/main/java/org/openecomp/crud/logging/CrudServiceMsgs.java
@@ -43,6 +43,7 @@ public enum CrudServiceMsgs implements LogMessageEnum {
INVALID_OXM_FILE,
INVALID_OXM_DIR,
OXM_FILE_CHANGED,
+ TRANSACTION,
/**
* Successfully loaded schema: {0}
diff --git a/src/main/java/org/openecomp/crud/logging/LoggingUtil.java b/src/main/java/org/openecomp/crud/logging/LoggingUtil.java
index aaa250a..2ef2772 100644
--- a/src/main/java/org/openecomp/crud/logging/LoggingUtil.java
+++ b/src/main/java/org/openecomp/crud/logging/LoggingUtil.java
@@ -81,7 +81,7 @@ public class LoggingUtil {
(req != null) ? req.getMethod() : "Unknown",
(req != null) ? req.getRequestURL().toString() : "Unknown",
(req != null) ? req.getRemoteHost() : "Unknown",
- Integer.toString(response.getStatus()) + " error: " + (response.getEntity() == null ? ""
+ Integer.toString(response.getStatus()) + " payload: " + (response.getEntity() == null ? ""
: response.getEntity().toString()));
MDC.clear();
}
diff --git a/src/main/java/org/openecomp/crud/parser/CrudResponseBuilder.java b/src/main/java/org/openecomp/crud/parser/CrudResponseBuilder.java
index 1a84322..308583d 100644
--- a/src/main/java/org/openecomp/crud/parser/CrudResponseBuilder.java
+++ b/src/main/java/org/openecomp/crud/parser/CrudResponseBuilder.java
@@ -23,20 +23,27 @@
*/
package org.openecomp.crud.parser;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonObject;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.ws.rs.core.Response.Status;
import org.openecomp.crud.entity.Edge;
import org.openecomp.crud.entity.Vertex;
import org.openecomp.crud.exception.CrudException;
+import org.openecomp.crud.service.BulkPayload;
import org.openecomp.crud.service.EdgePayload;
import org.openecomp.crud.service.VertexPayload;
import org.openecomp.schema.RelationshipSchemaLoader;
-import java.util.ArrayList;
-import java.util.List;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
public class CrudResponseBuilder {
@@ -45,6 +52,42 @@ public class CrudResponseBuilder {
public static final String SOURCE = "source";
public static final String TARGET = "target";
public static final String URL_BASE = "services/inventory/";
+
+ public static String buildUpsertBulkResponse(HashMap<String,Vertex> vertices, HashMap<String,Edge> edges , String version,BulkPayload incomingPayload)
+ throws CrudException {
+
+ for (JsonElement e : incomingPayload.getObjects()) {
+ List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(e.getAsJsonObject().entrySet());
+
+ Map.Entry<String, JsonElement> item = entries.get(1);
+
+ Vertex responseVertex = vertices.get(item.getKey());
+ if(responseVertex != null){
+ JsonObject v = gson.fromJson(buildUpsertVertexResponse(responseVertex,version), JsonObject.class);
+ item.setValue(v);
+ }else{
+ item.setValue(gson.fromJson("{}", JsonObject.class));
+ }
+
+ }
+ for (JsonElement e : incomingPayload.getRelationships()) {
+ List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(e.getAsJsonObject().entrySet());
+
+ Map.Entry<String, JsonElement> item = entries.get(1);
+
+ Edge responseEdge = edges.get(item.getKey());
+ if(responseEdge != null){
+ JsonObject v = gson.fromJson(buildUpsertEdgeResponse(responseEdge,version), JsonObject.class);
+ item.setValue(v);
+ }else{
+ item.setValue(gson.fromJson("{}", JsonObject.class));
+ }
+
+ }
+ return incomingPayload.toJson();
+ }
+
+
public static String buildUpsertVertexResponse(Vertex vertex, String version)
throws CrudException {
diff --git a/src/main/java/org/openecomp/crud/service/BulkPayload.java b/src/main/java/org/openecomp/crud/service/BulkPayload.java
new file mode 100644
index 0000000..28cf420
--- /dev/null
+++ b/src/main/java/org/openecomp/crud/service/BulkPayload.java
@@ -0,0 +1,128 @@
+/**
+ * ============LICENSE_START=======================================================
+ * Gizmo
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * 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
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * 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.openecomp.crud.service;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+
+import org.openecomp.crud.exception.CrudException;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.ws.rs.core.Response.Status;
+
+public class BulkPayload {
+ public enum OperationType {
+ CREATE, UPDATE, DELETE
+ }
+
+
+
+ private List<JsonElement> objects = new ArrayList<JsonElement>();
+ private List<JsonElement> relationships = new ArrayList<JsonElement>();
+
+ private static final Gson gson = new GsonBuilder().disableHtmlEscaping().create();
+
+ public String toJson() {
+ return gson.toJson(this);
+ }
+
+ public static BulkPayload fromJson(String payload) throws CrudException {
+ try {
+ if (payload == null || payload.isEmpty()) {
+ throw new CrudException("Invalid Json Payload", Status.BAD_REQUEST);
+ }
+ return gson.fromJson(payload, BulkPayload.class);
+ } catch (Exception ex) {
+ throw new CrudException("Invalid Json Payload", Status.BAD_REQUEST);
+ }
+ }
+
+ public List<JsonElement> getObjects() {
+ return objects;
+ }
+
+ public void setObjects(List<JsonElement> objects) {
+ this.objects = objects;
+ }
+
+ public List<JsonElement> getRelationships() {
+ return relationships;
+ }
+
+ public void setRelationships(List<JsonElement> relationships) {
+ this.relationships = relationships;
+ }
+
+ @Override
+ public String toString() {
+ return "BulkPayload [objects=" + objects + ", relationships=" + relationships + "]";
+ }
+
+ public static void main(String[] args) throws Exception {
+ BulkPayload p = new BulkPayload();
+ JsonObject root = new JsonObject();
+ JsonArray vertices = new JsonArray();
+ JsonObject v1 = new JsonObject();
+ JsonObject v2 = new JsonObject();
+ JsonObject prop = new JsonObject();
+
+ prop.addProperty("p1","value1");
+ prop.addProperty("p2","value2");
+ v1.add("v1", prop);
+ v2.add("v2",prop);
+
+ vertices.add(v1);
+ vertices.add(v2);
+
+
+ root.add("objects", vertices);
+
+ String s = "{\"objects\":[{\"v1\":{\"p1\":\"value1\",\"p2\":\"value2\"}},{\"v2\":{\"p1\":\"value1\",\"p2\":\"value2\"}}]}";
+
+ p = BulkPayload.fromJson(s);
+
+ List<JsonElement> po = p.getObjects();
+ List<String> ids = new ArrayList<String>();
+ for (JsonElement e : po){
+ Set<Map.Entry<String, JsonElement>> entries = e.getAsJsonObject().entrySet();
+
+ for (Map.Entry<String, JsonElement> entry : entries) {
+ ids.add(entry.getKey());
+ }
+ }
+
+
+ System.out.println("root: " + root.toString());
+ System.out.println("payload ids: " + ids.toString());
+
+ }
+
+} \ No newline at end of file
diff --git a/src/main/java/org/openecomp/crud/service/CrudGraphDataService.java b/src/main/java/org/openecomp/crud/service/CrudGraphDataService.java
index f38fe0f..c6b6a48 100644
--- a/src/main/java/org/openecomp/crud/service/CrudGraphDataService.java
+++ b/src/main/java/org/openecomp/crud/service/CrudGraphDataService.java
@@ -23,11 +23,19 @@
*/
package org.openecomp.crud.service;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.ws.rs.core.Response.Status;
+
import org.onap.aaiutils.oxm.OxmModelLoader;
import org.openecomp.aai.champcore.ChampGraph;
import org.openecomp.crud.dao.GraphDao;
import org.openecomp.crud.dao.champ.ChampDao;
import org.openecomp.crud.entity.Edge;
+
import org.openecomp.crud.entity.Vertex;
import org.openecomp.crud.exception.CrudException;
import org.openecomp.crud.parser.CrudResponseBuilder;
@@ -35,32 +43,149 @@ import org.openecomp.schema.OxmModelValidator;
import org.openecomp.schema.RelationshipSchemaLoader;
import org.openecomp.schema.RelationshipSchemaValidator;
-import java.util.List;
-import java.util.Map;
+import com.google.gson.JsonElement;
public class CrudGraphDataService {
private GraphDao dao;
public CrudGraphDataService(ChampGraph graphImpl) throws CrudException {
+ this.dao = new ChampDao(graphImpl);
+
+ loadModels();
+ }
- this.dao = new ChampDao(graphImpl);
- //load the schemas
- try {
+ public CrudGraphDataService(GraphDao dao) throws CrudException {
+ this.dao = dao;
+
+ loadModels();
+ }
+
+ private void loadModels() throws CrudException {
+ //load the schemas
+ try {
OxmModelLoader.loadModels();
} catch (Exception e) {
throw new CrudException(e);
}
- RelationshipSchemaLoader.loadModels();
- }
-
+ RelationshipSchemaLoader.loadModels();
+ }
public String addVertex(String version, String type, VertexPayload payload) throws CrudException {
Vertex vertex = OxmModelValidator.validateIncomingUpsertPayload(null, version, type,
payload.getProperties());
return addVertex(version, vertex);
}
+
+ public String addBulk(String version, BulkPayload payload) throws CrudException {
+ HashMap<String, Vertex> vertices = new HashMap<String, Vertex>();
+ HashMap<String, Edge> edges = new HashMap<String, Edge>();
+ String txId = dao.openTransaction();
+ try {
+ // Handle vertices
+ for (JsonElement v : payload.getObjects()) {
+ List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(v.getAsJsonObject().entrySet());
+
+ if (entries.size() != 2) {
+ throw new CrudException("", Status.BAD_REQUEST);
+ }
+ Map.Entry<String, JsonElement> opr = entries.get(0);
+ Map.Entry<String, JsonElement> item = entries.get(1);
+
+ VertexPayload vertexPayload = VertexPayload.fromJson(item.getValue().getAsJsonObject().toString());
+
+ if (opr.getValue().getAsString().equalsIgnoreCase("add") || opr.getValue().getAsString().equalsIgnoreCase("modify")) {
+ Vertex validatedVertex;
+ Vertex persistedVertex;
+ if (opr.getValue().getAsString().equalsIgnoreCase("add")) {
+ validatedVertex = OxmModelValidator.validateIncomingUpsertPayload(null, version, vertexPayload.getType(),
+ vertexPayload.getProperties());
+ // Call champDAO to add the vertex
+ persistedVertex = dao.addVertex(validatedVertex.getType(), validatedVertex.getProperties(), txId);
+ } else {
+ validatedVertex = OxmModelValidator.validateIncomingUpsertPayload(vertexPayload.getId(), version, vertexPayload.getType(),
+ vertexPayload.getProperties());
+ // Call champDAO to update the vertex
+ persistedVertex = dao.updateVertex(vertexPayload.getId(), validatedVertex.getType(), validatedVertex.getProperties(), txId);
+ }
+
+ Vertex outgoingVertex = OxmModelValidator.validateOutgoingPayload(version, persistedVertex);
+
+ vertices.put(item.getKey(), outgoingVertex);
+
+ } else if (opr.getValue().getAsString().equalsIgnoreCase("delete")) {
+ dao.deleteVertex(vertexPayload.getId(), OxmModelValidator.resolveCollectionType(version, vertexPayload.getType()), txId);
+ }
+
+ }
+ // Handle Edges
+ for (JsonElement v : payload.getRelationships()) {
+ List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(v.getAsJsonObject().entrySet());
+
+ if (entries.size() != 2) {
+ throw new CrudException("", Status.BAD_REQUEST);
+ }
+ Map.Entry<String, JsonElement> opr = entries.get(0);
+ Map.Entry<String, JsonElement> item = entries.get(1);
+
+ EdgePayload edgePayload = EdgePayload.fromJson(item.getValue().getAsJsonObject().toString());
+
+ if (opr.getValue().getAsString().equalsIgnoreCase("add") || opr.getValue().getAsString().equalsIgnoreCase("modify")) {
+ Edge validatedEdge;
+ Edge persistedEdge;
+ if (opr.getValue().getAsString().equalsIgnoreCase("add")) {
+ // Fix the source/detination
+ if (edgePayload.getSource().startsWith("$")) {
+ Vertex source = vertices.get(edgePayload.getSource().substring(1));
+ if (source == null) {
+ throw new CrudException("Not able to find vertex: " + edgePayload.getSource().substring(1), Status.INTERNAL_SERVER_ERROR);
+ }
+ edgePayload.setSource("services/inventory/" + version + "/" + source.getType() + "/" + source.getId().get());
+ }
+ if (edgePayload.getTarget().startsWith("$")) {
+ Vertex target = vertices.get(edgePayload.getTarget().substring(1));
+ if (target == null) {
+ throw new CrudException("Not able to find vertex: " + edgePayload.getTarget().substring(1), Status.INTERNAL_SERVER_ERROR);
+ }
+ edgePayload.setTarget("services/inventory/" + version + "/" + target.getType() + "/" + target.getId().get());
+ }
+ validatedEdge = RelationshipSchemaValidator.validateIncomingAddPayload(version, edgePayload.getType(), edgePayload);
+ persistedEdge = dao.addEdge(validatedEdge.getType(), validatedEdge.getSource(), validatedEdge.getTarget(),
+ validatedEdge.getProperties(), txId);
+ } else {
+ Edge edge = dao.getEdge(edgePayload.getId(), edgePayload.getType(), txId);
+ validatedEdge = RelationshipSchemaValidator.validateIncomingUpdatePayload(edge, version, edgePayload);
+ persistedEdge = dao.updateEdge(edge, txId);
+ }
+
+ Edge outgoingEdge = RelationshipSchemaValidator.validateOutgoingPayload(version, persistedEdge);
+
+ edges.put(item.getKey(), outgoingEdge);
+
+ } else if (opr.getValue().getAsString().equalsIgnoreCase("delete")) {
+ RelationshipSchemaValidator.validateType(version, edgePayload.getType());
+ dao.deleteEdge(edgePayload.getId(), edgePayload.getType(), txId);
+ }
+
+ }
+ // close champ TX
+ dao.commitTransaction(txId);
+ } catch (CrudException ex) {
+ dao.rollbackTransaction(txId);
+ throw ex;
+ } catch (Exception ex) {
+ dao.rollbackTransaction(txId);
+ throw ex;
+ } finally {
+ if (dao.transactionExists(txId)) {
+ dao.rollbackTransaction(txId);
+ }
+ }
+
+
+ return CrudResponseBuilder.buildUpsertBulkResponse(vertices, edges, version, payload);
+ }
private String addVertex(String version, Vertex vertex) throws CrudException {
Vertex addedVertex = dao.addVertex(vertex.getType(), vertex.getProperties());
@@ -182,5 +307,7 @@ public class CrudGraphDataService {
type, filter));
return CrudResponseBuilder.buildGetVerticesResponse(items, version);
}
+
+
}
diff --git a/src/main/java/org/openecomp/crud/service/CrudRestService.java b/src/main/java/org/openecomp/crud/service/CrudRestService.java
index bef7b04..8a9f1c0 100644
--- a/src/main/java/org/openecomp/crud/service/CrudRestService.java
+++ b/src/main/java/org/openecomp/crud/service/CrudRestService.java
@@ -23,20 +23,13 @@
*/
package org.openecomp.crud.service;
-import org.apache.cxf.jaxrs.ext.PATCH;
-import org.openecomp.auth.Auth;
-import org.openecomp.cl.api.Logger;
-import org.openecomp.cl.eelf.LoggerFactory;
-import org.openecomp.crud.exception.CrudException;
-import org.openecomp.crud.logging.CrudServiceMsgs;
-import org.openecomp.crud.logging.LoggingUtil;
-import org.openecomp.crud.util.CrudServiceConstants;
-import org.slf4j.MDC;
-
import java.security.cert.X509Certificate;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
+
import javax.security.auth.x500.X500Principal;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
@@ -55,6 +48,18 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo;
+import org.apache.cxf.jaxrs.ext.PATCH;
+import org.openecomp.auth.Auth;
+import org.openecomp.cl.api.Logger;
+import org.openecomp.cl.eelf.LoggerFactory;
+import org.openecomp.crud.exception.CrudException;
+import org.openecomp.crud.logging.CrudServiceMsgs;
+import org.openecomp.crud.logging.LoggingUtil;
+import org.openecomp.crud.util.CrudServiceConstants;
+import org.slf4j.MDC;
+
+import com.google.gson.JsonElement;
+
public class CrudRestService {
private CrudGraphDataService crudGraphDataService;
@@ -222,21 +227,6 @@ public class CrudRestService {
}
@PUT
- @Path("/relationships/{version}/{type}/")
- @Consumes({MediaType.APPLICATION_JSON})
- @Produces({MediaType.APPLICATION_JSON})
- public Response updateEdgeWithoutId(String content, @Context HttpHeaders headers, @Context HttpServletRequest req) {
-
- LoggingUtil.initMdcContext(req, headers);
-
- logger.debug("Incoming request..." + content);
- Response response = Response.status (Status.BAD_REQUEST).entity ("Cannot Update Edge Without Specifying Id in URL").build();
-
- LoggingUtil.logRestRequest(logger, auditLogger, req, response);
- return response;
- }
-
- @PUT
@Path("/relationships/{version}/{type}/{id}")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
@@ -463,6 +453,142 @@ public class CrudRestService {
LoggingUtil.logRestRequest(logger, auditLogger, req, response);
return response;
}
+
+ private void validateBulkPayload(BulkPayload payload) throws CrudException {
+ List<String> vertices = new ArrayList<String>();
+ List<String> edges = new ArrayList<String>();
+
+ for (JsonElement v : payload.getObjects()) {
+ List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(v.getAsJsonObject().entrySet());
+
+ if (entries.size() != 2) {
+ throw new CrudException("", Status.BAD_REQUEST);
+ }
+ Map.Entry<String, JsonElement> opr = entries.get(0);
+ Map.Entry<String, JsonElement> item = entries.get(1);
+
+ if (vertices.contains(item.getKey())) {
+ throw new CrudException("duplicate vertex in payload: " + item.getKey(), Status.BAD_REQUEST);
+ }
+ VertexPayload vertexPayload = VertexPayload.fromJson(item.getValue().getAsJsonObject().toString());
+ if (vertexPayload.getType() == null) {
+ throw new CrudException("Vertex Type cannot be null for: " + item.getKey(), Status.BAD_REQUEST);
+ }
+
+ if (!opr.getKey().equalsIgnoreCase("operation")) {
+ throw new CrudException("operation missing in item: " + item.getKey(), Status.BAD_REQUEST);
+ }
+
+ if (!opr.getValue().getAsString().equalsIgnoreCase("add") && !opr.getValue().getAsString().equalsIgnoreCase("modify")
+ && !opr.getValue().getAsString().equalsIgnoreCase("delete")) {
+ throw new CrudException("Invalid operation at item: " + item.getKey(), Status.BAD_REQUEST);
+ }
+ // check if ID is populate for modify/delete operation
+ if ((opr.getValue().getAsString().equalsIgnoreCase("modify") || opr.getValue().getAsString().equalsIgnoreCase("delete"))
+ && (vertexPayload.getId() == null)) {
+
+ throw new CrudException("Mising ID at item: " + item.getKey(), Status.BAD_REQUEST);
+
+ }
+
+ vertices.add(item.getKey());
+ }
+
+ for (JsonElement v : payload.getRelationships()) {
+ List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(v.getAsJsonObject().entrySet());
+
+ if (entries.size() != 2) {
+ throw new CrudException("", Status.BAD_REQUEST);
+ }
+ Map.Entry<String, JsonElement> opr = entries.get(0);
+ Map.Entry<String, JsonElement> item = entries.get(1);
+
+ if (edges.contains(item.getKey())) {
+ throw new CrudException("duplicate Edge in payload: " + item.getKey(), Status.BAD_REQUEST);
+ }
+
+ EdgePayload edgePayload = EdgePayload.fromJson(item.getValue().getAsJsonObject().toString());
+
+ if (edgePayload.getType() == null) {
+ throw new CrudException("Edge Type cannot be null for: " + item.getKey(), Status.BAD_REQUEST);
+ }
+
+ if (!opr.getKey().equalsIgnoreCase("operation")) {
+ throw new CrudException("operation missing in item: " + item.getKey(), Status.BAD_REQUEST);
+ }
+
+ if (!opr.getValue().getAsString().equalsIgnoreCase("add") && !opr.getValue().getAsString().equalsIgnoreCase("modify")
+ && !opr.getValue().getAsString().equalsIgnoreCase("delete")) {
+ throw new CrudException("Invalid operation at item: " + item.getKey(), Status.BAD_REQUEST);
+ }
+ // check if ID is populate for modify/delete operation
+ if ((edgePayload.getId() == null) && (opr.getValue().getAsString().equalsIgnoreCase("modify")
+ || opr.getValue().getAsString().equalsIgnoreCase("delete"))) {
+
+ throw new CrudException("Mising ID at item: " + item.getKey(), Status.BAD_REQUEST);
+
+ }
+ if (opr.getValue().getAsString().equalsIgnoreCase("add")) {
+ if(edgePayload.getSource()==null || edgePayload.getTarget()==null){
+ throw new CrudException("Source/Target cannot be null for edge: " + item.getKey(),
+ Status.BAD_REQUEST);
+ }
+ if (edgePayload.getSource().startsWith("$") && !vertices.contains(edgePayload.getSource().substring(1))) {
+ throw new CrudException("Source Vertex " + edgePayload.getSource().substring(1) + " not found for Edge: " + item.getKey(),
+ Status.BAD_REQUEST);
+ }
+
+ if (edgePayload.getTarget().startsWith("$") && !vertices.contains(edgePayload.getTarget().substring(1))) {
+ throw new CrudException("Target Vertex " + edgePayload.getSource().substring(1) + " not found for Edge: " + item.getKey(),
+ Status.BAD_REQUEST);
+ }
+ }
+ edges.add(item.getKey());
+
+ }
+
+ }
+
+ @POST
+ @Path("/{version}/bulk/")
+ @Consumes({MediaType.APPLICATION_JSON})
+ @Produces({MediaType.APPLICATION_JSON})
+ public Response addBulk(String content, @PathParam("version") String version,
+ @PathParam("type") String type, @PathParam("uri") @Encoded String uri,
+ @Context HttpHeaders headers, @Context UriInfo uriInfo,
+ @Context HttpServletRequest req) {
+
+ LoggingUtil.initMdcContext(req, headers);
+
+ logger.debug("Incoming request..." + content);
+ Response response = null;
+
+ if (validateRequest(req, uri, content, Action.POST,
+ CrudServiceConstants.CRD_AUTH_POLICY_NAME)) {
+
+ try {
+ BulkPayload payload = BulkPayload.fromJson(content);
+ if ((payload.getObjects() == null && payload.getRelationships() == null) || (payload.getObjects() != null && payload.getObjects().isEmpty()
+ && payload.getRelationships() != null && payload.getRelationships().isEmpty())) {
+ throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
+ }
+
+ validateBulkPayload(payload);
+ String result = crudGraphDataService.addBulk(version, payload);
+ response = Response.status(Status.OK).entity(result).type(mediaType).build();
+ } catch (CrudException ce) {
+ response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
+ } catch (Exception e) {
+ response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
+ }
+ } else {
+ response = Response.status(Status.FORBIDDEN).entity(content)
+ .type(MediaType.APPLICATION_JSON).build();
+ }
+
+ LoggingUtil.logRestRequest(logger, auditLogger, req, response);
+ return response;
+ }
@POST
@Path("/{version}/")
@@ -637,20 +763,6 @@ public class CrudRestService {
}
@DELETE
- @Path("/relationships/{version}/{type}/")
- @Consumes({MediaType.APPLICATION_JSON})
- @Produces({MediaType.APPLICATION_JSON})
- public Response deleteEdgeWithouId(String content, @Context HttpHeaders headers, @Context HttpServletRequest req) {
-
- LoggingUtil.initMdcContext(req, headers);
-
- logger.debug("Incoming request..." + content);
- Response response = Response.status ( Status.BAD_REQUEST ).entity ( "Cannot Delete Edge Without Specifying Id in URL" ).build ();
- LoggingUtil.logRestRequest(logger, auditLogger, req, response);
- return response;
- }
-
- @DELETE
@Path("/relationships/{version}/{type}/{id}")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
diff --git a/src/main/java/org/openecomp/crud/util/CrudServiceConstants.java b/src/main/java/org/openecomp/crud/util/CrudServiceConstants.java
index 9543e2d..1a4858f 100644
--- a/src/main/java/org/openecomp/crud/util/CrudServiceConstants.java
+++ b/src/main/java/org/openecomp/crud/util/CrudServiceConstants.java
@@ -43,6 +43,7 @@ public class CrudServiceConstants {
public static final String CRD_CONFIG_FILE = CRD_SPECIFIC_CONFIG + "crud-api.properties";
public static final String CRD_AUTH_FILE = CRD_HOME_AUTH + "crud_policy.json";
+ public static final String CRD_CHAMPION_AUTH_FILE = CRD_HOME_AUTH + "champion-cert.p12";
public static final String CRD_AUTH_POLICY_NAME = "crud";
diff --git a/src/main/java/org/openecomp/schema/OxmModelValidator.java b/src/main/java/org/openecomp/schema/OxmModelValidator.java
index 0ae3e13..e51b23f 100644
--- a/src/main/java/org/openecomp/schema/OxmModelValidator.java
+++ b/src/main/java/org/openecomp/schema/OxmModelValidator.java
@@ -163,6 +163,7 @@ public class OxmModelValidator {
CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, type));
final DynamicType modelObjectType = jaxbContext.getDynamicType(modelObjectClass);
+ final DynamicType reservedType = jaxbContext.getDynamicType("ReservedPropNames");
Set<Map.Entry<String, JsonElement>> payloadEntriesSet = properties.getAsJsonObject()
.entrySet();
@@ -173,7 +174,9 @@ public class OxmModelValidator {
// check for valid field
if (modelObjectType.getDescriptor().getMappingForAttributeName(keyJavaName) == null) {
- throw new CrudException("Invalid field: " + entry.getKey(), Status.BAD_REQUEST);
+ if(reservedType.getDescriptor().getMappingForAttributeName(keyJavaName) == null){
+ throw new CrudException("Invalid field: " + entry.getKey(), Status.BAD_REQUEST);
+ }
}
}
@@ -219,6 +222,20 @@ public class OxmModelValidator {
}
}
}
+
+ // Handle reserved properties
+ for (DatabaseMapping mapping : reservedType.getDescriptor().getMappings()) {
+ if (mapping.isAbstractDirectMapping()) {
+ DatabaseField field = mapping.getField();
+ String keyName = field.getName().substring(0, field.getName().indexOf("/"));
+
+ if (entriesMap.containsKey(keyName)) {
+ Object value = CrudServiceUtil.validateFieldType(entriesMap.get(keyName)
+ .getAsString(), field.getType());
+ modelVertexBuilder.property(keyName, value);
+ }
+ }
+ }
return modelVertexBuilder.build();
} catch (Exception e) {
@@ -237,6 +254,7 @@ public class OxmModelValidator {
CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, type));
final DynamicType modelObjectType = jaxbContext.getDynamicType(modelObjectClass);
+ final DynamicType reservedType = jaxbContext.getDynamicType("ReservedPropNames");
Set<Map.Entry<String, JsonElement>> payloadEntriesSet = properties.getAsJsonObject()
.entrySet();
@@ -247,19 +265,26 @@ public class OxmModelValidator {
String keyJavaName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL, entry.getKey());
- // check for valid field
- if (modelObjectType.getDescriptor().getMappingForAttributeName(keyJavaName) == null) {
+ DatabaseField field = null;
+ String defaultValue = null;
+
+ if (modelObjectType.getDescriptor().getMappingForAttributeName(keyJavaName) != null) {
+ field = modelObjectType.getDescriptor().getMappingForAttributeName(keyJavaName).getField();
+ defaultValue = modelObjectType.getDescriptor()
+ .getMappingForAttributeName(keyJavaName)
+ .getProperties().get("defaultValue") == null ? ""
+ : modelObjectType.getDescriptor().getMappingForAttributeName(keyJavaName)
+ .getProperties().get("defaultValue").toString();
+ }
+ else if (reservedType.getDescriptor().getMappingForAttributeName(keyJavaName) != null) {
+ field = reservedType.getDescriptor().getMappingForAttributeName(keyJavaName).getField();
+ defaultValue = "";
+ }
+
+ if (field == null) {
throw new CrudException("Invalid field: " + entry.getKey(), Status.BAD_REQUEST);
}
- DatabaseField field = modelObjectType.getDescriptor()
- .getMappingForAttributeName(keyJavaName).getField();
- String defaultValue = modelObjectType.getDescriptor()
- .getMappingForAttributeName(keyJavaName)
- .getProperties().get("defaultValue") == null ? ""
- : modelObjectType.getDescriptor().getMappingForAttributeName(keyJavaName)
- .getProperties().get("defaultValue").toString();
-
// check if mandatory field is not set to null
if (((XMLField) field).isRequired() && entry.getValue() instanceof JsonNull
&& !defaultValue.isEmpty()) {
@@ -288,7 +313,7 @@ public class OxmModelValidator {
}
}
-
+
private static DatabaseField getDatabaseField(String fieldName, DynamicType modelObjectType) {
for (DatabaseField field : modelObjectType.getDescriptor().getAllFields()) {
int ix = field.getName().indexOf("/");
diff --git a/src/main/java/org/openecomp/schema/RelationshipSchemaLoader.java b/src/main/java/org/openecomp/schema/RelationshipSchemaLoader.java
index d4ae2b9..89a9e58 100644
--- a/src/main/java/org/openecomp/schema/RelationshipSchemaLoader.java
+++ b/src/main/java/org/openecomp/schema/RelationshipSchemaLoader.java
@@ -23,34 +23,38 @@
*/
package org.openecomp.schema;
-import org.apache.commons.io.IOUtils;
-import org.openecomp.aai.dbmodel.DbEdgeRules;
-import org.openecomp.cl.eelf.LoggerFactory;
-import org.openecomp.crud.exception.CrudException;
-import org.openecomp.crud.logging.CrudServiceMsgs;
-import org.openecomp.crud.util.CrudServiceConstants;
-import org.openecomp.crud.util.FileWatcher;
-import org.springframework.core.io.UrlResource;
-import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
-import org.springframework.core.io.support.ResourcePatternResolver;
-
-import java.io.*;
-import java.util.Arrays;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Comparator;
-import java.util.concurrent.ConcurrentHashMap;
import java.util.Date;
import java.util.List;
import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
import java.util.SortedSet;
-import java.util.stream.Collectors;
import java.util.Timer;
import java.util.TimerTask;
import java.util.TreeSet;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
import javax.ws.rs.core.Response.Status;
+import org.apache.commons.io.IOUtils;
+import org.openecomp.cl.eelf.LoggerFactory;
+import org.openecomp.crud.exception.CrudException;
+import org.openecomp.crud.logging.CrudServiceMsgs;
+import org.openecomp.crud.util.CrudServiceConstants;
+import org.openecomp.crud.util.FileWatcher;
+import org.springframework.core.io.UrlResource;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+import org.springframework.core.io.support.ResourcePatternResolver;
+
public class RelationshipSchemaLoader {
private static Map<String, RelationshipSchema> versionContextMap = new ConcurrentHashMap<>();
@@ -153,7 +157,6 @@ public class RelationshipSchemaLoader {
String errorMsg = "Expecting a rules and a edge_properties files for " + version + ". Found: " + filenames;
logger.warn(CrudServiceMsgs.INVALID_OXM_FILE, errorMsg);
}});
-
logger.info(CrudServiceMsgs.LOADED_OXM_FILE, "Relationship Schema and Properties files: " + rulesFiles.stream().map(f -> filename(f)).collect(Collectors.toList()));
} catch (IOException e) {
logger.error(CrudServiceMsgs.INVALID_OXM_DIR, rulesDir);
diff --git a/src/main/resources/logging/CrudServiceMsgs.properties b/src/main/resources/logging/CrudServiceMsgs.properties
index 13554e5..a4c2991 100644
--- a/src/main/resources/logging/CrudServiceMsgs.properties
+++ b/src/main/resources/logging/CrudServiceMsgs.properties
@@ -55,3 +55,6 @@ EXCEPTION_DURING_METHOD_CALL=\
OXM_LOAD_ERROR=\
CRD0503E|\
Unable to load OXM schema: {0}
+TRANSACTION=\
+ CRD0008I|\
+ TRANSACTION: {0}