From 908b4693e5a0a4c2f323dbf518b35e4620f183a1 Mon Sep 17 00:00:00 2001 From: "Bansal, Nitin (nb121v)" Date: Mon, 20 Nov 2017 16:02:06 -0500 Subject: Refactor to move from openecomp to onap Refactor to move from openecomp to onap IssueID: AAI-486 Change-Id: I1d5634739514acf11d5fbdf5e2c7865aaccd864e Signed-off-by: Bansal, Nitin (nb121v) --- src/main/java/org/onap/crud/dao/GraphDao.java | 183 +++++ .../java/org/onap/crud/dao/champ/ChampDao.java | 883 +++++++++++++++++++++ .../org/onap/crud/dao/champion/ChampionDao.java | 623 +++++++++++++++ .../crud/dao/champion/ChampionEdgeSerializer.java | 49 ++ .../dao/champion/ChampionVertexSerializer.java | 47 ++ src/main/java/org/onap/crud/entity/Edge.java | 140 ++++ src/main/java/org/onap/crud/entity/Vertex.java | 115 +++ src/main/java/org/onap/crud/event/GraphEvent.java | 235 ++++++ .../java/org/onap/crud/event/GraphEventEdge.java | 212 +++++ .../java/org/onap/crud/event/GraphEventVertex.java | 181 +++++ .../org/onap/crud/exception/CrudException.java | 62 ++ .../org/onap/crud/logging/CrudServiceMsgs.java | 87 ++ .../java/org/onap/crud/logging/LoggingUtil.java | 82 ++ .../org/onap/crud/parser/CrudResponseBuilder.java | 212 +++++ .../org/onap/crud/service/AaiResourceService.java | 533 +++++++++++++ .../java/org/onap/crud/service/BulkPayload.java | 124 +++ .../onap/crud/service/CrudGraphDataService.java | 301 +++++++ .../org/onap/crud/service/CrudRestService.java | 784 ++++++++++++++++++ .../java/org/onap/crud/service/EdgePayload.java | 115 +++ .../org/onap/crud/service/JaxrsEchoService.java | 63 ++ .../java/org/onap/crud/service/VertexPayload.java | 117 +++ .../org/onap/crud/util/CrudJaxbTransformation.java | 92 +++ .../java/org/onap/crud/util/CrudProperties.java | 77 ++ .../org/onap/crud/util/CrudServiceConstants.java | 54 ++ .../java/org/onap/crud/util/CrudServiceUtil.java | 63 ++ src/main/java/org/onap/crud/util/FileWatcher.java | 48 ++ .../java/org/onap/schema/OxmModelValidator.java | 331 ++++++++ .../java/org/onap/schema/RelationshipSchema.java | 108 +++ .../org/onap/schema/RelationshipSchemaLoader.java | 263 ++++++ .../onap/schema/RelationshipSchemaValidator.java | 352 ++++++++ src/main/java/org/openecomp/crud/dao/GraphDao.java | 183 ----- .../org/openecomp/crud/dao/champ/ChampDao.java | 883 --------------------- .../openecomp/crud/dao/champion/ChampionDao.java | 623 --------------- .../crud/dao/champion/ChampionEdgeSerializer.java | 49 -- .../dao/champion/ChampionVertexSerializer.java | 47 -- src/main/java/org/openecomp/crud/entity/Edge.java | 140 ---- .../java/org/openecomp/crud/entity/Vertex.java | 115 --- .../java/org/openecomp/crud/event/GraphEvent.java | 235 ------ .../org/openecomp/crud/event/GraphEventEdge.java | 212 ----- .../org/openecomp/crud/event/GraphEventVertex.java | 181 ----- .../openecomp/crud/exception/CrudException.java | 62 -- .../openecomp/crud/logging/CrudServiceMsgs.java | 87 -- .../org/openecomp/crud/logging/LoggingUtil.java | 82 -- .../openecomp/crud/parser/CrudResponseBuilder.java | 212 ----- .../openecomp/crud/service/AaiResourceService.java | 533 ------------- .../org/openecomp/crud/service/BulkPayload.java | 124 --- .../crud/service/CrudGraphDataService.java | 301 ------- .../openecomp/crud/service/CrudRestService.java | 784 ------------------ .../org/openecomp/crud/service/EdgePayload.java | 115 --- .../openecomp/crud/service/JaxrsEchoService.java | 63 -- .../org/openecomp/crud/service/VertexPayload.java | 117 --- .../crud/util/CrudJaxbTransformation.java | 92 --- .../org/openecomp/crud/util/CrudProperties.java | 77 -- .../openecomp/crud/util/CrudServiceConstants.java | 54 -- .../org/openecomp/crud/util/CrudServiceUtil.java | 63 -- .../java/org/openecomp/crud/util/FileWatcher.java | 48 -- .../org/openecomp/schema/OxmModelValidator.java | 331 -------- .../org/openecomp/schema/RelationshipSchema.java | 108 --- .../openecomp/schema/RelationshipSchemaLoader.java | 263 ------ .../schema/RelationshipSchemaValidator.java | 352 -------- 60 files changed, 6536 insertions(+), 6536 deletions(-) create mode 100644 src/main/java/org/onap/crud/dao/GraphDao.java create mode 100644 src/main/java/org/onap/crud/dao/champ/ChampDao.java create mode 100644 src/main/java/org/onap/crud/dao/champion/ChampionDao.java create mode 100644 src/main/java/org/onap/crud/dao/champion/ChampionEdgeSerializer.java create mode 100644 src/main/java/org/onap/crud/dao/champion/ChampionVertexSerializer.java create mode 100644 src/main/java/org/onap/crud/entity/Edge.java create mode 100644 src/main/java/org/onap/crud/entity/Vertex.java create mode 100644 src/main/java/org/onap/crud/event/GraphEvent.java create mode 100644 src/main/java/org/onap/crud/event/GraphEventEdge.java create mode 100644 src/main/java/org/onap/crud/event/GraphEventVertex.java create mode 100644 src/main/java/org/onap/crud/exception/CrudException.java create mode 100644 src/main/java/org/onap/crud/logging/CrudServiceMsgs.java create mode 100644 src/main/java/org/onap/crud/logging/LoggingUtil.java create mode 100644 src/main/java/org/onap/crud/parser/CrudResponseBuilder.java create mode 100644 src/main/java/org/onap/crud/service/AaiResourceService.java create mode 100644 src/main/java/org/onap/crud/service/BulkPayload.java create mode 100644 src/main/java/org/onap/crud/service/CrudGraphDataService.java create mode 100644 src/main/java/org/onap/crud/service/CrudRestService.java create mode 100644 src/main/java/org/onap/crud/service/EdgePayload.java create mode 100644 src/main/java/org/onap/crud/service/JaxrsEchoService.java create mode 100644 src/main/java/org/onap/crud/service/VertexPayload.java create mode 100644 src/main/java/org/onap/crud/util/CrudJaxbTransformation.java create mode 100644 src/main/java/org/onap/crud/util/CrudProperties.java create mode 100644 src/main/java/org/onap/crud/util/CrudServiceConstants.java create mode 100644 src/main/java/org/onap/crud/util/CrudServiceUtil.java create mode 100644 src/main/java/org/onap/crud/util/FileWatcher.java create mode 100644 src/main/java/org/onap/schema/OxmModelValidator.java create mode 100644 src/main/java/org/onap/schema/RelationshipSchema.java create mode 100644 src/main/java/org/onap/schema/RelationshipSchemaLoader.java create mode 100644 src/main/java/org/onap/schema/RelationshipSchemaValidator.java delete mode 100644 src/main/java/org/openecomp/crud/dao/GraphDao.java delete mode 100644 src/main/java/org/openecomp/crud/dao/champ/ChampDao.java delete mode 100644 src/main/java/org/openecomp/crud/dao/champion/ChampionDao.java delete mode 100644 src/main/java/org/openecomp/crud/dao/champion/ChampionEdgeSerializer.java delete mode 100644 src/main/java/org/openecomp/crud/dao/champion/ChampionVertexSerializer.java delete mode 100644 src/main/java/org/openecomp/crud/entity/Edge.java delete mode 100644 src/main/java/org/openecomp/crud/entity/Vertex.java delete mode 100644 src/main/java/org/openecomp/crud/event/GraphEvent.java delete mode 100644 src/main/java/org/openecomp/crud/event/GraphEventEdge.java delete mode 100644 src/main/java/org/openecomp/crud/event/GraphEventVertex.java delete mode 100644 src/main/java/org/openecomp/crud/exception/CrudException.java delete mode 100644 src/main/java/org/openecomp/crud/logging/CrudServiceMsgs.java delete mode 100644 src/main/java/org/openecomp/crud/logging/LoggingUtil.java delete mode 100644 src/main/java/org/openecomp/crud/parser/CrudResponseBuilder.java delete mode 100644 src/main/java/org/openecomp/crud/service/AaiResourceService.java delete mode 100644 src/main/java/org/openecomp/crud/service/BulkPayload.java delete mode 100644 src/main/java/org/openecomp/crud/service/CrudGraphDataService.java delete mode 100644 src/main/java/org/openecomp/crud/service/CrudRestService.java delete mode 100644 src/main/java/org/openecomp/crud/service/EdgePayload.java delete mode 100644 src/main/java/org/openecomp/crud/service/JaxrsEchoService.java delete mode 100644 src/main/java/org/openecomp/crud/service/VertexPayload.java delete mode 100644 src/main/java/org/openecomp/crud/util/CrudJaxbTransformation.java delete mode 100644 src/main/java/org/openecomp/crud/util/CrudProperties.java delete mode 100644 src/main/java/org/openecomp/crud/util/CrudServiceConstants.java delete mode 100644 src/main/java/org/openecomp/crud/util/CrudServiceUtil.java delete mode 100644 src/main/java/org/openecomp/crud/util/FileWatcher.java delete mode 100644 src/main/java/org/openecomp/schema/OxmModelValidator.java delete mode 100644 src/main/java/org/openecomp/schema/RelationshipSchema.java delete mode 100644 src/main/java/org/openecomp/schema/RelationshipSchemaLoader.java delete mode 100644 src/main/java/org/openecomp/schema/RelationshipSchemaValidator.java (limited to 'src/main/java/org') diff --git a/src/main/java/org/onap/crud/dao/GraphDao.java b/src/main/java/org/onap/crud/dao/GraphDao.java new file mode 100644 index 0000000..bc42b15 --- /dev/null +++ b/src/main/java/org/onap/crud/dao/GraphDao.java @@ -0,0 +1,183 @@ +/** + * ============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.onap.crud.dao; + +import java.util.List; +import java.util.Map; + +import org.onap.crud.entity.Edge; + +import org.onap.crud.entity.Vertex; +import org.onap.crud.exception.CrudException; + +public interface GraphDao { + + public Vertex getVertex(String id) throws CrudException; + + public Vertex getVertex(String id, String type) throws CrudException; + + /** + * Retrieve all of the edges which are incident to the vertex with the + * specified identifier. + * + * @param id + * - The unique identifier of the vertex to retrieve the edges for. + * @return - A collection of edges. + * @throws CrudException + */ + public List getVertexEdges(String id) throws CrudException; + + /** + * Retrieve a collection of {@link Vertex} objects which match the supplied + * type label and filter properties. + * + * @param type + * - The vertex type that we want to retrieve. + * @param filter + * - The parameters to filter our results by. + * @return - A collection of vertices. + * @throws CrudException + */ + public List getVertices(String type, Map filter) throws CrudException; + + /** + * Retrieve an {@link Edge} from the graph database by specifying its unique + * identifier. + * + * @param id + * - The unique identifier for the Edge to be retrieved. + * @return - The Edge corresponding to the specified identifier. + * @throws CrudException + */ + public Edge getEdge(String id, String type) throws CrudException; + + /** + * Retrieve a collection of {@link Edge} objects with a given type and which + * match a set of supplied filter parameters. + * + * @param type + * - The type of edges that we are interested in. + * @param filter + * - The parameters that we want to filter our edges by. + * @return - A collection of edges which match the supplied filter parameters. + * @throws CrudException + */ + public List getEdges(String type, Map filter) throws CrudException; + + /** + * Insert a new {@link Vertex} into the graph data store. + * + * @param type + * - The type label to assign to the vertex. + * @param properties + * - The properties to associated with this vertex. + * @return - The {@link Vertex} object that was created. + * @throws CrudException + */ + public Vertex addVertex(String type, Map properties) throws CrudException; + + /** + * Updates an existing {@link Vertex}. + * + * @param id + * - The unique identifier of the vertex to be updated. + * @param properties + * - The properties to associate with the vertex. + * @return - The udpated vertex. + * @throws CrudException + */ + public Vertex updateVertex(String id, String type, Map properties) throws CrudException; + + /** + * Removes the specified vertex from the graph data base. + * + *

+ * NOTE: The vertex MUST contain NO incident edges before it can be deleted. + * + * @param id + * - The unique identifier of the vertex to be deleted. + * @throws CrudException + */ + public void deleteVertex(String id, String type) throws CrudException; + + /** + * Adds an edge to the graph database. + * + * @param type + * - The 'type' label to apply to the edge. + * @param source + * - The source vertex for this edge. + * @param target + * - The target vertex for this edge. + * @param properties + * - The properties map to associate with this edge. + * @return - The {@link Edge} object that was created. + * @throws CrudException + */ + public Edge addEdge(String type, Vertex source, Vertex target, Map properties) throws CrudException; + + /** + * Updates an existing {@link Edge}. + * + * @param id + * - The unique identifier of the edge to be updated. + * @param properties + * - The properties to associate with the edge. + * @return - The update edge. + * @throws CrudException + */ + public Edge updateEdge(Edge edge) throws CrudException; + + /** + * Remove the specified edge from the graph data base. + * + * @param id + * - The unique identifier of the edge to be deleted. + * @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 properties, String txId) throws CrudException; + + public Edge addEdge(String type, Vertex source, Vertex target, Map properties, String txId) + throws CrudException; + + public Vertex updateVertex(String id, String type, Map 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/onap/crud/dao/champ/ChampDao.java b/src/main/java/org/onap/crud/dao/champ/ChampDao.java new file mode 100644 index 0000000..f217897 --- /dev/null +++ b/src/main/java/org/onap/crud/dao/champ/ChampDao.java @@ -0,0 +1,883 @@ +/** + * ============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.onap.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.onap.aai.champcore.ChampGraph; +import org.onap.aai.champcore.ChampTransaction; +import org.onap.aai.champcore.exceptions.ChampMarshallingException; +import org.onap.aai.champcore.exceptions.ChampObjectNotExistsException; +import org.onap.aai.champcore.exceptions.ChampRelationshipNotExistsException; +import org.onap.aai.champcore.exceptions.ChampSchemaViolationException; +import org.onap.aai.champcore.exceptions.ChampTransactionException; +import org.onap.aai.champcore.exceptions.ChampUnmarshallingException; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.aai.champcore.model.fluent.object.ObjectBuildOrPropertiesStep; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.crud.dao.GraphDao; +import org.onap.crud.entity.Edge; +import org.onap.crud.entity.Vertex; +import org.onap.crud.exception.CrudException; +import org.onap.crud.logging.CrudServiceMsgs; + +/** + * 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"; + + private static Map transactions = new ConcurrentHashMap(); + 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 retrievedVertex = champApi.retrieveObject(idAsLong); + + String nodeType = org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(); + if (retrievedVertex.isPresent() && retrievedVertex.get().getProperties().get(nodeType) != null) { + return vertexFromChampObject(retrievedVertex.get(), + retrievedVertex.get().getProperties().get(nodeType).toString()); + } else { + + // We didn't find a vertex with the supplied id, so just throw an + // 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 retrievedVertex = champApi.retrieveObject(idAsLong); + + // Did we find it? + if (retrievedVertex.isPresent() + && retrievedVertex.get().getProperties() + .get(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName()) != null + && retrievedVertex.get().getProperties() + .get(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName()).toString() + .equalsIgnoreCase(type)) { + + // 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 getVertexEdges(String id) throws CrudException { + + if (logger.isDebugEnabled()) { + logger.debug("get Edges incident to vertex with id: " + id + " from graph"); + } + + try { + long idAsLong = Long.parseLong(id); // GDF - what to do about id??? + + // Request the vertex from the graph db. + Optional retrievedVertex = champApi.retrieveObject(idAsLong); + + // Did we find it? + if (retrievedVertex.isPresent()) { + + // Query the Champ library for the edges which are incident to the + // specified + // vertex. + Stream relationships = champApi.retrieveRelationships(retrievedVertex.get()); + + // Build an edge list from the result stream. + List edges = new ArrayList(); + 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 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.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type); + + // Create an object to represent our vertex in the format expected by the + // Champ library. + ChampObject objectToCreate = buildChampObject(type, properties); + + try { + + // Ask the Champ library to store our vertex, placing the returned object + // into a + // list so that we can easily put that into our result object. + return vertexFromChampObject(champApi.storeObject(objectToCreate), type); + + } 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 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.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type); + + try { + // Now, build the updated version of the Champ Object... + ChampObject updateObject = buildChampObject(id, type, properties); + // ...and send it to the Champ library. + return vertexFromChampObject(champApi.replaceObject(updateObject), type); + + } catch (ChampObjectNotExistsException e) { + throw new CrudException("Not Found", javax.ws.rs.core.Response.Status.NOT_FOUND); + } catch (NumberFormatException | ChampMarshallingException | ChampSchemaViolationException e) { + throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); + } catch (ChampTransactionException e) { + throw new CrudException("Transaction error occured", javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); + } + + } + + @Override + public List getVertices(String type, Map filter) throws CrudException { + + if (logger.isDebugEnabled()) { + logger.debug("Retrieve vertices with type label: " + type + " which map query parameters: " + + propertiesMapToString(filter)); + } + + filter.put(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type); + + Stream retrievedVertices; + try { + retrievedVertices = champApi.queryObjects(filter); + + } catch (ChampTransactionException e) { + throw new CrudException("Transaction error occured", javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); + } + + List vertices = retrievedVertices.map(v -> vertexFromChampObject(v, type)).collect(Collectors.toList()); + + if (logger.isDebugEnabled()) { + logger.debug("Resulting vertex list: " + retrievedVertices); + } + + // ...and return it to the caller. + return vertices; + } + + private Object getRelKey(String id) { + Object key = id; + // convert into Long if applicable . TODO : revisit in story NUC-304 + try { + key = Long.parseLong(id); + } catch (NumberFormatException e) { + // The id isn't a Long, leave it as a string + } + + return key; + } + + @Override + public Edge getEdge(String id, String type) throws CrudException { + + if (logger.isDebugEnabled()) { + logger.debug("Get edge with id: " + id); + } + + try { + + // Request the edge from the graph db. + Optional relationship = champApi.retrieveRelationship(getRelKey(id)); + + // Did we find it? + if (relationship.isPresent() && relationship.get().getType().equals(type)) { + + // Yup - return the result. + return edgeFromChampRelationship(relationship.get()); + + } else { + + // We didn't find an edge with the supplied id, so throw an exception. + throw new CrudException("No edge with id " + id + " found in graph", + javax.ws.rs.core.Response.Status.NOT_FOUND); + } + + } catch (ChampUnmarshallingException | ChampTransactionException e) { + + // 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 properties) throws CrudException { + + // For now, assume source and target are straight ids... + try { + + Optional sourceObject = champApi.retrieveObject(Long.parseLong(source.getId().get())); + if (!sourceObject.isPresent() || !sourceObject.get().getType().equals(source.getType())) { + throw new CrudException( + "Error creating edge - source vertex with id " + source + " does not exist in graph data base", + javax.ws.rs.core.Response.Status.BAD_REQUEST); + } + + Optional targetObject = champApi.retrieveObject(Long.parseLong(target.getId().get())); + if (!targetObject.isPresent() || !targetObject.get().getType().equals(target.getType())) { + throw new CrudException( + "Error creating edge - target vertex with id " + target + " does not exist in graph data base", + javax.ws.rs.core.Response.Status.BAD_REQUEST); + } + + // 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 getEdges(String type, Map filter) throws CrudException { + + filter.put(ChampRelationship.ReservedPropertyKeys.CHAMP_RELATIONSHIP_TYPE.toString(), type); + + Stream retrievedRelationships; + try { + retrievedRelationships = champApi.queryRelationships(filter); + + } catch (ChampTransactionException e) { + throw new CrudException("Transaction error occured", javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); + } + + // Process the result stream from the Champ library into an Edge list, + // keeping only + // edges of the specified type. + List edges = retrievedRelationships.map(r -> edgeFromChampRelationship(r)).collect(Collectors.toList()); + + return edges; + } + + @Override + public Edge updateEdge(Edge edge) throws CrudException { + + if (logger.isDebugEnabled()) { + logger.debug( + "Update edge with id: " + edge.getId() + " with properties: " + propertiesMapToString(edge.getProperties())); + } + + 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 retrievedVertex = champApi.retrieveObject(Long.parseLong(id)); + + // Did we find it? + if (!retrievedVertex.isPresent() || !retrievedVertex.get().getType().equals(type)) { + throw new CrudException("Failed to delete vertex with id: " + id + " - vertex does not exist.", + javax.ws.rs.core.Response.Status.NOT_FOUND); + } + + // Now, verify that there are no edges incident to the vertex (they must + // be deleted + // first if so). + Stream relationships = champApi.retrieveRelationships(retrievedVertex.get()); + + if (relationships.count() > 0) { + throw new CrudException("Attempt to delete vertex with id " + id + " which has incident edges.", + javax.ws.rs.core.Response.Status.BAD_REQUEST); + } + + // Finally, we can attempt to delete our vertex. + champApi.deleteObject(Long.parseLong(id)); + + } catch (NumberFormatException | ChampUnmarshallingException | ChampObjectNotExistsException + | ChampTransactionException e) { + + throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); + } + } + + @Override + public void deleteEdge(String id, String type) throws CrudException { + + try { + + // First, retrieve the edge that we want to delete. + Optional relationshipToDelete = champApi.retrieveRelationship(getRelKey(id)); + + // Did we find it? + if (!relationshipToDelete.isPresent() || !relationshipToDelete.get().getType().equals(type)) { + throw new CrudException("Failed to delete edge with id: " + id + " - edge does not exist", + javax.ws.rs.core.Response.Status.NOT_FOUND); + } + + // Now we can delete the edge. + champApi.deleteRelationship(relationshipToDelete.get()); + + } catch (ChampRelationshipNotExistsException | NumberFormatException | ChampUnmarshallingException + | ChampTransactionException e) { + + throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); + } + } + + /** + * This helper method generates a string representation of a properties map + * for logging purposes. + * + * @param properties + * - The properties map to be converted. + * @return - The log statement friendly conversion of the properties map. + */ + private String propertiesMapToString(Map properties) { + + 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 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 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.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName()) == null + ? relationship.getSource().getType() + : relationship.getSource().getProperties() + .get(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName()).toString())); + edgeBuilder.target(vertexFromChampObject(relationship.getTarget(), + relationship.getTarget().getProperties() + .get(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName()) == null + ? relationship.getTarget().getType() + : relationship.getTarget().getProperties() + .get(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName()).toString())); + + for (String key : relationship.getProperties().keySet()) { + edgeBuilder.property(key, relationship.getProperties().get(key).toString()); + } + + return edgeBuilder.build(); + } + + /** + * Performs any necessary shut down operations when the DAO is no longer + * needed. + */ + public void close() { + + if (champApi != null) { + + 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 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.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type); + + // Create an object to represent our vertex in the format expected by the + // Champ library. + ChampObject objectToCreate = buildChampObject(type, properties); + + try { + + // Ask the Champ library to store our vertex, placing the returned object + // into a + // list so that we can easily put that into our result object. + return vertexFromChampObject(champApi.storeObject(objectToCreate, Optional.of(getTransaction(txId))), type); + + } 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 properties, String txId) + throws CrudException { + // For now, assume source and target are straight ids... + try { + + Optional sourceObject = champApi.retrieveObject(Long.parseLong(source.getId().get()), + Optional.of(getTransaction(txId))); + if (!sourceObject.isPresent() || !sourceObject.get().getType().equals(source.getType())) { + throw new CrudException( + "Error creating edge - source vertex with id " + source + " does not exist in graph data base", + javax.ws.rs.core.Response.Status.BAD_REQUEST); + } + + Optional targetObject = champApi.retrieveObject(Long.parseLong(target.getId().get()), + Optional.of(getTransaction(txId))); + if (!targetObject.isPresent() || !targetObject.get().getType().equals(target.getType())) { + throw new CrudException( + "Error creating edge - target vertex with id " + target + " does not exist in graph data base", + javax.ws.rs.core.Response.Status.BAD_REQUEST); + } + + // Now, create the ChampRelationship object for our edge and store it in + // the graph database. + return edgeFromChampRelationship(champApi.storeRelationship( + new ChampRelationship.Builder(sourceObject.get(), targetObject.get(), type).properties(properties).build(), + Optional.of(getTransaction(txId)))); + + } catch (ChampMarshallingException | ChampObjectNotExistsException | ChampSchemaViolationException + | ChampTransactionException | ChampRelationshipNotExistsException | ChampUnmarshallingException e) { + + 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 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.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type); + + try { + // Now, build the updated version of the Champ Object... + ChampObject updateObject = buildChampObject(id, type, properties); + // ...and send it to the Champ library. + return vertexFromChampObject(champApi.replaceObject(updateObject, 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 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 relationships = champApi.retrieveRelationships(retrievedVertex.get(), + Optional.of(getTransaction(txId))); + + if (relationships.count() > 0) { + throw new CrudException("Attempt to delete vertex with id " + id + " which has incident edges.", + javax.ws.rs.core.Response.Status.BAD_REQUEST); + } + + // Finally, we can attempt to delete our vertex. + champApi.deleteObject(Long.parseLong(id), Optional.of(getTransaction(txId))); + + } catch (NumberFormatException | ChampUnmarshallingException | ChampObjectNotExistsException + | ChampTransactionException e) { + + throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); + } + + } + + @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())); + } + + try { + // Now, build the updated version of the Champ Relationship... + ChampRelationship updateRelationship = new ChampRelationship.Builder( + buildChampObject(edge.getSource().getId().get(), edge.getSource().getType(), + edge.getSource().getProperties()), + buildChampObject(edge.getTarget().getId().get(), edge.getTarget().getType(), + edge.getTarget().getProperties()), + edge.getType()).key(getRelKey(edge.getId().get())).properties(edge.getProperties()).build(); + // ...and send it to the Champ library. + return edgeFromChampRelationship( + champApi.replaceRelationship(updateRelationship, Optional.of(getTransaction(txId)))); + + } catch (ChampRelationshipNotExistsException ex) { + throw new CrudException("Not Found", javax.ws.rs.core.Response.Status.NOT_FOUND); + } catch (NumberFormatException | ChampUnmarshallingException | ChampMarshallingException + | ChampSchemaViolationException | ChampTransactionException ex) { + + throw new CrudException(ex.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); + } + } + + @Override + public void deleteEdge(String id, String type, String txId) throws CrudException { + try { + + // First, retrieve the edge that we want to delete. + Optional relationshipToDelete = champApi.retrieveRelationship(getRelKey(id), + Optional.of(getTransaction(txId))); + + // 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(), Optional.of(getTransaction(txId))); + + } catch (ChampRelationshipNotExistsException | NumberFormatException | ChampUnmarshallingException + | ChampTransactionException e) { + + throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); + } + + } + + @Override + public Edge getEdge(String id, String type, String txId) throws CrudException { + if (logger.isDebugEnabled()) { + logger.debug("Get edge with id: " + id); + } + + try { + + // Request the edge from the graph db. + Optional relationship = champApi.retrieveRelationship(getRelKey(id), + Optional.of(getTransaction(txId))); + + // 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); + } + } + +} diff --git a/src/main/java/org/onap/crud/dao/champion/ChampionDao.java b/src/main/java/org/onap/crud/dao/champion/ChampionDao.java new file mode 100644 index 0000000..4bde2e0 --- /dev/null +++ b/src/main/java/org/onap/crud/dao/champion/ChampionDao.java @@ -0,0 +1,623 @@ +/** + * ============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.onap.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.onap.aai.logging.LoggingContext; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.crud.dao.GraphDao; +import org.onap.crud.entity.Edge; +import org.onap.crud.entity.Vertex; +import org.onap.crud.exception.CrudException; +import org.onap.crud.util.CrudServiceConstants; +import org.onap.aai.restclient.client.OperationResult; +import org.onap.aai.restclient.client.RestClient; +import org.onap.aai.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> 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> 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 getVertexEdges(String id) throws CrudException { + String url = baseUrl + "objects/relationships/" + id; + Map> 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>() { + }.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 getVertices(String type, Map filter) throws CrudException { + filter.put(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type); + + String url = baseUrl + "objects/filter" + "?" + + URLEncodedUtils.format(convertToNameValuePair(filter), Charset.defaultCharset()); + + Map> 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>() { + }.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> 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 getEdges(String type, Map filter) throws CrudException { + String url = baseUrl + "relationships/filter" + "?" + + URLEncodedUtils.format(convertToNameValuePair(filter), Charset.defaultCharset()); + + Map> 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>() { + }.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 properties) throws CrudException { + String url = baseUrl + "objects"; + Map> 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.onap.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 properties) throws CrudException { + String url = baseUrl + "objects/" + id; + Map> 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.onap.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> 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 properties) throws CrudException { + String url = baseUrl + "relationships"; + Map> 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> 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> 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> 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> 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> 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> 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 properties, String txId) throws CrudException { + String url = baseUrl + "objects?transactionId=" + txId; + Map> 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.onap.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 properties, String txId) + throws CrudException { + String url = baseUrl + "relationships?transactionId=" + txId; + Map> 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 properties, String txId) throws CrudException { + String url = baseUrl + "objects/" + id + "?transactionId=" + txId; + Map> 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.onap.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> 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> 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> 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> 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> 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 convertToNameValuePair(Map pairs) { + List 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/onap/crud/dao/champion/ChampionEdgeSerializer.java b/src/main/java/org/onap/crud/dao/champion/ChampionEdgeSerializer.java new file mode 100644 index 0000000..655d096 --- /dev/null +++ b/src/main/java/org/onap/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.onap.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.onap.crud.entity.Edge; +import org.onap.crud.entity.Vertex; + +import java.lang.reflect.Type; + +public class ChampionEdgeSerializer implements JsonSerializer { + @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/onap/crud/dao/champion/ChampionVertexSerializer.java b/src/main/java/org/onap/crud/dao/champion/ChampionVertexSerializer.java new file mode 100644 index 0000000..904ad2e --- /dev/null +++ b/src/main/java/org/onap/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.onap.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.onap.crud.entity.Vertex; + +import java.lang.reflect.Type; + +public class ChampionVertexSerializer implements JsonSerializer { + @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/onap/crud/entity/Edge.java b/src/main/java/org/onap/crud/entity/Edge.java new file mode 100644 index 0000000..87b0ac4 --- /dev/null +++ b/src/main/java/org/onap/crud/entity/Edge.java @@ -0,0 +1,140 @@ +/** + * ============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.onap.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().registerTypeAdapterFactory(new GsonJava8TypeAdapterFactory()) + .create(); + + @SerializedName(value = "id", alternate = { "key" }) + private final Optional id; + private final String type; + private final Map properties; + private final Vertex source; + private final Vertex target; + + private Edge(Builder builder) { + this.id = builder.id; + this.type = builder.type; + this.source = builder.source; + this.target = builder.target; + this.properties = builder.properties; + } + + public static class Builder { + private Optional id = Optional.empty(); + private final String type; + private Vertex source; + private Vertex target; + private final Map properties = new HashMap(); + + public Builder(String type) { + if (type == null) { + throw new IllegalArgumentException("Type cannot be null"); + } + + this.type = type; + } + + public Builder id(String id) { + if (id == null) { + throw new IllegalArgumentException("id cannot be null"); + } + + this.id = Optional.of(id); + return this; + } + + public Builder property(String key, Object value) { + if (key == null || value == null) { + throw new IllegalArgumentException("Property key/value cannot be null"); + } + properties.put(key, value); + return this; + } + + public Builder source(Vertex source) { + this.source = source; + return this; + } + + public Builder target(Vertex target) { + this.target = target; + return this; + } + + public Edge build() { + return new Edge(this); + } + } + + @Override + public String toString() { + return "Edge [id=" + id + ", type=" + type + ", properties=" + properties + ", source=" + source + ", target=" + + target + "]"; + } + + public String toJson() { + 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 getId() { + return id; + } + + public String getType() { + return type; + } + + public Map getProperties() { + return properties; + } + + public Vertex getSource() { + return source; + } + + public Vertex getTarget() { + return target; + } + +} diff --git a/src/main/java/org/onap/crud/entity/Vertex.java b/src/main/java/org/onap/crud/entity/Vertex.java new file mode 100644 index 0000000..42d0eef --- /dev/null +++ b/src/main/java/org/onap/crud/entity/Vertex.java @@ -0,0 +1,115 @@ +/** + * ============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.onap.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().registerTypeAdapterFactory(new GsonJava8TypeAdapterFactory()) + .create(); + + @SerializedName(value = "id", alternate = { "key" }) + private final Optional id; + + private final String type; + private final Map properties; + + private Vertex(Builder builder) { + this.id = builder.id; + this.type = builder.type; + this.properties = builder.properties; + } + + public static class Builder { + private Optional id = Optional.empty(); + private final String type; + private final Map properties = new HashMap(); + + public Builder(String type) { + if (type == null) { + throw new IllegalArgumentException("Type cannot be null"); + } + this.type = type; + } + + public Builder id(String id) { + if (id == null) { + throw new IllegalArgumentException("id cannot be null"); + } + + this.id = Optional.of(id); + return this; + } + + public Builder property(String key, Object value) { + if (key == null || value == null) { + throw new IllegalArgumentException("Property key/value cannot be null"); + } + properties.put(key, value); + return this; + } + + public Vertex build() { + return new Vertex(this); + } + } + + public String toJson() { + 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 + "]"; + } + + public Optional getId() { + return id; + } + + public String getType() { + return type; + } + + public Map getProperties() { + return properties; + } + +} diff --git a/src/main/java/org/onap/crud/event/GraphEvent.java b/src/main/java/org/onap/crud/event/GraphEvent.java new file mode 100644 index 0000000..9e9c44c --- /dev/null +++ b/src/main/java/org/onap/crud/event/GraphEvent.java @@ -0,0 +1,235 @@ +/** + * ============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.onap.crud.event; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.annotations.SerializedName; + +import org.onap.crud.exception.CrudException; + +import javax.ws.rs.core.Response.Status; + +public class GraphEvent { + + public enum GraphEventOperation { + CREATE, UPDATE, DELETE + } + + public enum GraphEventResult { + SUCCESS, FAILURE + } + + private GraphEventOperation operation; + + @SerializedName("transaction-id") + private String transactionId; + + private long timestamp; + + private GraphEventVertex vertex; + + private GraphEventEdge edge; + + private GraphEventResult result; + + @SerializedName("error-message") + private String errorMessage; + + private Status httpErrorStatus; + + /** + * Marshaller/unmarshaller for converting to/from JSON. + */ + private static final Gson gson = new GsonBuilder().disableHtmlEscaping() + .setPrettyPrinting().create(); + + public static Builder builder(GraphEventOperation operation) { + return new Builder(operation); + } + + public GraphEventOperation getOperation() { + return operation; + } + + public String getTransactionId() { + return transactionId; + } + + public long getTimestamp() { + return timestamp; + } + + public GraphEventVertex getVertex() { + return vertex; + } + + public GraphEventEdge getEdge() { + return edge; + } + + public GraphEventResult getResult() { + return result; + } + + public String getErrorMessage() { + return errorMessage; + } + + public void setResult(GraphEventResult result) { + this.result = result; + } + + + public Status getHttpErrorStatus() { + return httpErrorStatus; + } + + public void setHttpErrorStatus(Status httpErrorStatus) { + this.httpErrorStatus = httpErrorStatus; + } + + public void setTimestamp(long timestamp) { + this.timestamp = timestamp; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + public void setVertex(GraphEventVertex vertex) { + this.vertex = vertex; + } + + public void setEdge(GraphEventEdge edge) { + this.edge = edge; + } + + /** + * Unmarshalls this Vertex object into a JSON string. + * + * @return - A JSON format string representation of this Vertex. + */ + public String toJson() { + return gson.toJson(this); + } + + /** + * Marshalls the provided JSON string into a Vertex object. + * + * @param json - The JSON string to produce the Vertex from. + * @return - A Vertex object. + * @throws SpikeException + */ + public static GraphEvent fromJson(String json) throws CrudException { + + try { + + // Make sure that we were actually provided a non-empty string + // before we + // go any further. + if (json == null || json.isEmpty()) { + throw new CrudException("Empty or null JSON string.", Status.BAD_REQUEST); + } + + // Marshall the string into a Vertex object. + return gson.fromJson(json, GraphEvent.class); + + } catch (Exception ex) { + throw new CrudException("Unable to parse JSON string: ", Status.BAD_REQUEST); + } + } + + @Override + public String toString() { + + return toJson(); + } + + public String getObjectKey() { + if (this.getVertex() != null) { + return this.getVertex().getId(); + } else if (this.getEdge() != null) { + return this.getEdge().getId(); + } + + return null; + + } + + public String getObjectType() { + if (this.getVertex() != null) { + return "vertex->" + this.getVertex().getType(); + } else if (this.getEdge() != null) { + return "edge->" + this.getEdge().getType(); + } + + return null; + + } + + public static class Builder { + + GraphEvent event = null; + + public Builder(GraphEventOperation operation) { + event = new GraphEvent(); + event.operation = operation; + } + + public Builder vertex(GraphEventVertex vertex) { + event.vertex = vertex; + return this; + } + + public Builder edge(GraphEventEdge edge) { + event.edge = edge; + return this; + } + + public Builder result(GraphEventResult result) { + event.result = result; + return this; + } + + public Builder errorMessage(String errorMessage) { + event.errorMessage = errorMessage; + return this; + } + + public Builder httpErrorStatus(Status httpErrorStatus) { + event.httpErrorStatus = httpErrorStatus; + return this; + } + + public GraphEvent build() { + + event.timestamp = System.currentTimeMillis(); + event.transactionId = java.util.UUID.randomUUID().toString(); + + return event; + } + } + +} diff --git a/src/main/java/org/onap/crud/event/GraphEventEdge.java b/src/main/java/org/onap/crud/event/GraphEventEdge.java new file mode 100644 index 0000000..58ea4a7 --- /dev/null +++ b/src/main/java/org/onap/crud/event/GraphEventEdge.java @@ -0,0 +1,212 @@ +/** + * ============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.onap.crud.event; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.annotations.SerializedName; +import com.google.gson.reflect.TypeToken; + +import org.onap.crud.entity.Edge; +import org.onap.crud.entity.Vertex; +import org.onap.crud.exception.CrudException; + +import java.util.Map; +import javax.ws.rs.core.Response.Status; + +/** + * This class provides a generic representation of an Edge as provided by the + * graph data store. + */ +public class GraphEventEdge { + + /** + * The unique identifier used to identify this edge in the graph data store. + */ + @SerializedName("key") + private String id; + + @SerializedName("schema-version") + private String modelVersion; + + /** + * Type label assigned to this vertex. + */ + private String type; + + /** + * Source vertex for our edge. + */ + private GraphEventVertex source; + + /** + * Target vertex for our edge. + */ + private GraphEventVertex target; + + /** + * Map of all of the properties assigned to this vertex. + */ + private JsonElement properties; + + /** + * Marshaller/unmarshaller for converting to/from JSON. + */ + private static final Gson gson = new GsonBuilder().disableHtmlEscaping().create(); + + public GraphEventEdge(String id, String modelVersion, String type, GraphEventVertex source, + GraphEventVertex target, JsonElement properties) { + this.id = id; + this.modelVersion = modelVersion; + this.type = type; + this.source = source; + this.target = target; + this.properties = properties; + } + + public GraphEventEdge() { + + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public GraphEventVertex getSource() { + return source; + } + + public void setSource(GraphEventVertex source) { + this.source = source; + } + + public GraphEventVertex getTarget() { + return target; + } + + public void setTarget(GraphEventVertex target) { + this.target = target; + } + + public JsonElement getProperties() { + return properties; + } + + public void setProperties(JsonElement properties) { + this.properties = properties; + } + + public String getModelVersion() { + return modelVersion; + } + + public void setModelVersion(String modelVersion) { + this.modelVersion = modelVersion; + } + + /** + * Unmarshalls this Edge object into a JSON string. + * + * @return - A JSON format string representation of this Edge. + */ + public String toJson() { + return gson.toJson(this); + } + + /** + * Marshalls the provided JSON string into a Edge object. + * + * @param json - The JSON string to produce the Edge from. + * @return - A Edge object. + * @throws SpikeException + */ + public static GraphEventEdge fromJson(String json) throws CrudException { + + try { + + // Make sure that we were actually provided a non-empty string + // before we + // go any further. + if (json == null || json.isEmpty()) { + throw new CrudException("Unable to parse JSON string: ", Status.BAD_REQUEST); + } + + // Marshall the string into an Edge object. + return gson.fromJson(json, GraphEventEdge.class); + + } catch (Exception ex) { + throw new CrudException("Unable to parse JSON string: ", Status.BAD_REQUEST); + } + } + + public static GraphEventEdge fromEdge(Edge edge, String modelVersion) { + + java.lang.reflect.Type mapType = new TypeToken>() {}.getType(); + JsonObject props = gson.toJsonTree(edge.getProperties(), mapType).getAsJsonObject(); + + GraphEventEdge graphEventEdge = new GraphEventEdge(edge.getId().orElse(""), modelVersion, + edge.getType(), new GraphEventVertex(edge.getSource().getId().orElse(""), null, + edge.getSource().getType(), null), new GraphEventVertex(edge.getTarget().getId().orElse(""), + null, edge.getTarget().getType(), null), props); + + return graphEventEdge; + + } + + public Edge toEdge() { + Edge.Builder builder = new Edge.Builder(this.getType()).id(this.getId()); + if (this.getSource() != null) { + builder.source(new Vertex.Builder(this.getSource().getType()).id(this.getSource().getId()) + .build()); + } + if (this.getTarget() != null) { + builder.target(new Vertex.Builder(this.getTarget().getType()).id(this.getTarget().getId()) + .build()); + } + + if (this.getProperties() != null) { + java.lang.reflect.Type mapType = new TypeToken>() {}.getType(); + Map propertiesMap = gson.fromJson(this.getProperties(), mapType); + for (String key : propertiesMap.keySet()) { + builder.property(key, propertiesMap.get(key)); + } + } + return builder.build(); + + } +} diff --git a/src/main/java/org/onap/crud/event/GraphEventVertex.java b/src/main/java/org/onap/crud/event/GraphEventVertex.java new file mode 100644 index 0000000..d9a06d4 --- /dev/null +++ b/src/main/java/org/onap/crud/event/GraphEventVertex.java @@ -0,0 +1,181 @@ +/** + * ============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.onap.crud.event; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.annotations.SerializedName; +import com.google.gson.reflect.TypeToken; + +import org.onap.crud.entity.Vertex; +import org.onap.crud.exception.CrudException; + +import java.util.Map; +import javax.ws.rs.core.Response.Status; + +/** + * This class provides a generic representation of a Vertex as provided by the + * graph data store. + */ +public class GraphEventVertex { + + /** + * The unique identifier used to identify this vertex in the graph data + * store. + */ + @SerializedName("key") + private String id; + + @SerializedName("schema-version") + private String modelVersion; + + /** + * Type label assigned to this vertex. + */ + private String type; + + /** + * Map of all of the properties assigned to this vertex. + */ + private JsonElement properties; + + /** + * Marshaller/unmarshaller for converting to/from JSON. + */ + private static final Gson gson = new GsonBuilder().disableHtmlEscaping().create(); + + public GraphEventVertex(String id, String modelVersion, String type, JsonElement properties) { + this.id = id; + this.modelVersion = modelVersion; + this.type = type; + this.properties = properties; + } + + public GraphEventVertex() { + + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + + public JsonElement getProperties() { + return properties; + } + + public void setProperties(JsonElement properties) { + this.properties = properties; + } + + public String getModelVersion() { + return modelVersion; + } + + public void setModelVersion(String modelVersion) { + this.modelVersion = modelVersion; + } + + /** + * Unmarshalls this Vertex object into a JSON string. + * + * @return - A JSON format string representation of this Vertex. + */ + public String toJson() { + return gson.toJson(this); + } + + /** + * Marshalls the provided JSON string into a Vertex object. + * + * @param json - The JSON string to produce the Vertex from. + * @return - A Vertex object. + * @throws SpikeException + */ + public static GraphEventVertex fromJson(String json) throws CrudException { + + try { + + // Make sure that we were actually provided a non-empty string + // before we + // go any further. + if (json == null || json.isEmpty()) { + throw new CrudException("Empty or null JSON string.", Status.BAD_REQUEST); + } + + // Marshall the string into a Vertex object. + return gson.fromJson(json, GraphEventVertex.class); + + } catch (Exception ex) { + throw new CrudException("Unable to parse JSON string: ", Status.BAD_REQUEST); + } + } + + @Override + public String toString() { + + return toJson(); + } + + public static GraphEventVertex fromVertex(Vertex vertex, String modelVersion) { + + java.lang.reflect.Type mapType = new TypeToken>() {}.getType(); + JsonObject props = gson.toJsonTree(vertex.getProperties(), mapType).getAsJsonObject(); + GraphEventVertex graphEventVertex = new GraphEventVertex(vertex.getId().orElse(""), + modelVersion, vertex.getType(), props); + return graphEventVertex; + + } + + public Vertex toVertex() { + Vertex.Builder builder = new Vertex.Builder(this.getType()).id(this.getId()); + + if (this.getProperties() != null) { + java.lang.reflect.Type mapType = new TypeToken>() {}.getType(); + Map propertiesMap = gson.fromJson(this.getProperties(), mapType); + for (String key : propertiesMap.keySet()) { + builder.property(key, propertiesMap.get(key)); + } + } + + return builder.build(); + + } + + +} diff --git a/src/main/java/org/onap/crud/exception/CrudException.java b/src/main/java/org/onap/crud/exception/CrudException.java new file mode 100644 index 0000000..a3d3127 --- /dev/null +++ b/src/main/java/org/onap/crud/exception/CrudException.java @@ -0,0 +1,62 @@ +/** + * ============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.onap.crud.exception; + +import javax.ws.rs.core.Response.Status; + +public class CrudException extends Exception { + + private static final long serialVersionUID = 8162385108397238865L; + + private Status httpStatus; + + public CrudException() { + } + + public CrudException(String message, Status httpStatus) { + super(message); + this.setHttpStatus(httpStatus); + } + + public CrudException(Throwable cause) { + super(cause); + } + + public CrudException(String message, Throwable cause) { + super(message, cause); + } + + public CrudException(String message, Throwable cause, boolean enableSuppression, + boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } + + public Status getHttpStatus() { + return httpStatus; + } + + public void setHttpStatus(Status httpStatus) { + this.httpStatus = httpStatus; + } +} diff --git a/src/main/java/org/onap/crud/logging/CrudServiceMsgs.java b/src/main/java/org/onap/crud/logging/CrudServiceMsgs.java new file mode 100644 index 0000000..6b04a0f --- /dev/null +++ b/src/main/java/org/onap/crud/logging/CrudServiceMsgs.java @@ -0,0 +1,87 @@ +/** + * ============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.onap.crud.logging; + +import com.att.eelf.i18n.EELFResourceManager; + +import org.onap.aai.cl.eelf.LogMessageEnum; + +public enum CrudServiceMsgs implements LogMessageEnum { + + /** + * Received request {0} {1} from {2}. Sending response: {3} + * + *

+ * Arguments: {0} = operation {1} = target URL {2} = source {3} = response + * code + */ + PROCESS_REST_REQUEST, + + INVALID_OXM_FILE, INVALID_OXM_DIR, OXM_FILE_CHANGED, TRANSACTION, + + /** + * Successfully loaded schema: {0} + * + *

+ * Arguments: {0} = oxm filename + */ + LOADED_OXM_FILE, + + /** + * Unable to load OXM schema: {0} + * + *

+ * Arguments: {0} = error + */ + OXM_LOAD_ERROR, + + /** + * Stopping ChampDAO... + * + *

+ * Arguments: + */ + STOPPING_CHAMP_DAO, + + /** + * Failure instantiating CRUD Rest Service. Cause: {0} + * + *

+ * Arguments: {0} - Failure cause. + */ + INSTANTIATE_AUTH_ERR, + + /** + * Arguments: {0} Opertaion {1} URI {2} = Exception + */ + EXCEPTION_DURING_METHOD_CALL; + + /** + * Static initializer to ensure the resource bundles for this class are + * loaded... + */ + static { + EELFResourceManager.loadMessageBundle("logging/CrudServiceMsgs"); + } +} diff --git a/src/main/java/org/onap/crud/logging/LoggingUtil.java b/src/main/java/org/onap/crud/logging/LoggingUtil.java new file mode 100644 index 0000000..453dc9d --- /dev/null +++ b/src/main/java/org/onap/crud/logging/LoggingUtil.java @@ -0,0 +1,82 @@ +/** + * ============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.onap.crud.logging; + +import org.onap.aai.cl.api.LogFields; +import org.onap.aai.cl.api.LogLine; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.mdc.MdcContext; +import org.onap.crud.util.CrudServiceConstants; +import org.slf4j.MDC; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.Response; + +public class LoggingUtil { + /** + * Initializes mdc context. + */ + public static void initMdcContext(HttpServletRequest httpReq, HttpHeaders headers) { + String fromIp = httpReq.getRemoteAddr(); + String fromAppId = ""; + String transId = null; + + if (headers.getRequestHeaders().getFirst("X-FromAppId") != null) { + fromAppId = headers.getRequestHeaders().getFirst("X-FromAppId"); + } + + if ((headers.getRequestHeaders().getFirst("X-TransactionId") == null) + || headers.getRequestHeaders().getFirst("X-TransactionId").isEmpty()) { + transId = java.util.UUID.randomUUID().toString(); + } else { + transId = headers.getRequestHeaders().getFirst("X-TransactionId"); + } + + MdcContext.initialize(transId, CrudServiceConstants.CRD_SERVICE_NAME, "", fromAppId, fromIp); + } + + /** + * Logs the rest request. + */ + public static void logRestRequest(Logger logger, Logger auditLogger, HttpServletRequest req, Response response) { + String respStatusString = ""; + if (Response.Status.fromStatusCode(response.getStatus()) != null) { + respStatusString = Response.Status.fromStatusCode(response.getStatus()).toString(); + } + + // Generate error log + logger.info(CrudServiceMsgs.PROCESS_REST_REQUEST, req.getMethod(), req.getRequestURL().toString(), + req.getRemoteHost(), Integer.toString(response.getStatus())); + + // Generate audit log. + auditLogger.info(CrudServiceMsgs.PROCESS_REST_REQUEST, + new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, response.getStatus()) + .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, respStatusString), + (req != null) ? req.getMethod() : "Unknown", (req != null) ? req.getRequestURL().toString() : "Unknown", + (req != null) ? req.getRemoteHost() : "Unknown", Integer.toString(response.getStatus()) + " payload: " + + (response.getEntity() == null ? "" : response.getEntity().toString())); + MDC.clear(); + } +} diff --git a/src/main/java/org/onap/crud/parser/CrudResponseBuilder.java b/src/main/java/org/onap/crud/parser/CrudResponseBuilder.java new file mode 100644 index 0000000..62d1408 --- /dev/null +++ b/src/main/java/org/onap/crud/parser/CrudResponseBuilder.java @@ -0,0 +1,212 @@ +/** + * ============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.onap.crud.parser; + +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.onap.crud.entity.Edge; +import org.onap.crud.entity.Vertex; +import org.onap.crud.exception.CrudException; +import org.onap.crud.service.BulkPayload; +import org.onap.crud.service.EdgePayload; +import org.onap.crud.service.VertexPayload; +import org.onap.schema.RelationshipSchemaLoader; + +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 { + + private static final Gson gson = new GsonBuilder().create(); + + 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 vertices, HashMap edges, + String version, BulkPayload incomingPayload) throws CrudException { + + for (JsonElement e : incomingPayload.getObjects()) { + List> entries = new ArrayList>( + e.getAsJsonObject().entrySet()); + + Map.Entry 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> entries = new ArrayList>( + e.getAsJsonObject().entrySet()); + + Map.Entry 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 { + VertexPayload payload = new VertexPayload(); + payload.setId(vertex.getId().get()); + payload.setType(vertex.getType()); + payload.setUrl(URL_BASE + version + "/" + vertex.getType() + "/" + vertex.getId().get()); + JsonObject props = new JsonObject(); + for (String key : vertex.getProperties().keySet()) { + addJsonProperperty(props, key, vertex.getProperties().get(key)); + } + payload.setProperties(props); + return payload.toJson(); + } + + public static String buildUpsertEdgeResponse(Edge edge, String version) throws CrudException { + return buildGetEdgeResponse(edge, version); + } + + public static String buildGetVertexResponse(Vertex vertex, List edges, String version) throws CrudException { + VertexPayload vertexPayload = new VertexPayload(); + vertexPayload.setId(vertex.getId().get()); + vertexPayload.setType(vertex.getType()); + vertexPayload.setUrl(URL_BASE + version + "/" + vertex.getType() + "/" + vertex.getId().get()); + JsonObject props = new JsonObject(); + for (String key : vertex.getProperties().keySet()) { + addJsonProperperty(props, key, vertex.getProperties().get(key)); + } + vertexPayload.setProperties(props); + List inEdges = new ArrayList(); + List outEdges = new ArrayList(); + for (Edge e : edges) { + if (e.getTarget().getId().get().equals(vertex.getId().get())) { + EdgePayload inEdge = new EdgePayload(); + inEdge.setId(e.getId().get()); + inEdge.setType(e.getType()); + inEdge.setUrl(URL_BASE + "relationships/" + RelationshipSchemaLoader.getLatestSchemaVersion() + "/" + + e.getType() + "/" + e.getId().get()); + inEdge.setSource(URL_BASE + version + "/" + e.getSource().getType() + "/" + e.getSource().getId().get()); + + inEdges.add(inEdge); + } else if (e.getSource().getId().get().equals(vertex.getId().get())) { + EdgePayload outEdge = new EdgePayload(); + outEdge.setId(e.getId().get()); + outEdge.setType(e.getType()); + outEdge.setUrl(URL_BASE + "relationships/" + RelationshipSchemaLoader.getLatestSchemaVersion() + "/" + + e.getType() + "/" + e.getId().get()); + outEdge.setTarget(URL_BASE + version + "/" + e.getTarget().getType() + "/" + e.getTarget().getId().get()); + outEdges.add(outEdge); + } + } + + vertexPayload.setIn(inEdges); + vertexPayload.setOut(outEdges); + + return vertexPayload.toJson(); + } + + public static String buildGetVerticesResponse(List items, String version) throws CrudException { + + JsonArray arry = new JsonArray(); + for (Vertex v : items) { + JsonObject item = new JsonObject(); + item.addProperty("id", v.getId().get()); + item.addProperty("type", v.getType()); + item.addProperty("url", "services/inventory/" + version + "/" + v.getType() + "/" + v.getId().get()); + + arry.add(item); + } + + return gson.toJson(arry); + } + + public static String buildGetEdgeResponse(Edge edge, String version) throws CrudException { + + EdgePayload payload = new EdgePayload(); + payload.setId(edge.getId().get()); + payload.setType(edge.getType()); + payload.setUrl(URL_BASE + "relationships/" + version + "/" + edge.getType() + "/" + edge.getId().get()); + payload.setSource(URL_BASE + version + "/" + edge.getSource().getType() + "/" + edge.getSource().getId().get()); + payload.setTarget(URL_BASE + version + "/" + edge.getTarget().getType() + "/" + edge.getTarget().getId().get()); + + JsonObject props = new JsonObject(); + for (String key : edge.getProperties().keySet()) { + addJsonProperperty(props, key, edge.getProperties().get(key)); + } + payload.setProperties(props); + return payload.toJson(); + } + + public static String buildGetEdgesResponse(List items, String version) throws CrudException { + + JsonArray arry = new JsonArray(); + for (Edge e : items) { + JsonObject item = new JsonObject(); + item.addProperty("id", e.getId().get()); + item.addProperty("type", e.getType()); + item.addProperty("url", URL_BASE + "relationships/" + version + "/" + e.getType() + "/" + e.getId().get()); + item.addProperty(SOURCE, + "services/inventory/" + version + "/" + e.getSource().getType() + "/" + e.getSource().getId().get()); + item.addProperty(TARGET, + "services/inventory/" + version + "/" + e.getTarget().getType() + "/" + e.getTarget().getId().get()); + arry.add(item); + } + + return gson.toJson(arry); + } + + private static void addJsonProperperty(JsonObject jsonObj, String key, Object value) { + if (value instanceof Integer) { + jsonObj.addProperty(key, (Integer) value); + } else if (value instanceof Boolean) { + jsonObj.addProperty(key, (Boolean) value); + } else if (value instanceof Double) { + jsonObj.addProperty(key, (Double) value); + } else if (value instanceof String) { + jsonObj.addProperty(key, (String) value); + } else { + jsonObj.addProperty(key, value.toString()); + } + } + +} diff --git a/src/main/java/org/onap/crud/service/AaiResourceService.java b/src/main/java/org/onap/crud/service/AaiResourceService.java new file mode 100644 index 0000000..2e4464d --- /dev/null +++ b/src/main/java/org/onap/crud/service/AaiResourceService.java @@ -0,0 +1,533 @@ +/** + * ============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.onap.crud.service; + +import java.security.cert.X509Certificate; +import java.util.AbstractMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import javax.security.auth.x500.X500Principal; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.Consumes; +import javax.ws.rs.Encoded; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; +import javax.ws.rs.core.Response.Status; + +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.serialization.db.EdgeProperty; +import org.onap.aai.serialization.db.EdgeRule; +import org.onap.aai.serialization.db.EdgeRules; +import org.onap.aai.serialization.db.EdgeType; +import org.openecomp.auth.Auth; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.crud.exception.CrudException; +import org.onap.crud.logging.CrudServiceMsgs; +import org.onap.crud.logging.LoggingUtil; +import org.onap.crud.service.CrudRestService.Action; +import org.onap.crud.util.CrudServiceConstants; +import org.onap.schema.RelationshipSchemaLoader; +import org.onap.schema.RelationshipSchemaValidator; +import org.slf4j.MDC; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; + + +/** + * This defines a set of REST endpoints which allow clients to create or update graph edges + * where the edge rules defined by the A&AI will be invoked to automatically populate the + * defined edge properties. + */ +public class AaiResourceService { + + private String mediaType = MediaType.APPLICATION_JSON; + public static final String HTTP_PATCH_METHOD_OVERRIDE = "X-HTTP-Method-Override"; + + private Auth auth; + CrudGraphDataService crudGraphDataService; + Gson gson = new Gson(); + + private Logger logger = LoggerFactory.getInstance().getLogger(AaiResourceService.class.getName()); + private Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(AaiResourceService.class.getName()); + + public AaiResourceService() {} + + /** + * Creates a new instance of the AaiResourceService. + * + * @param crudGraphDataService - Service used for interacting with the graph. + * + * @throws Exception + */ + public AaiResourceService(CrudGraphDataService crudGraphDataService) throws Exception { + this.crudGraphDataService = crudGraphDataService; + this.auth = new Auth(CrudServiceConstants.CRD_AUTH_FILE); + } + + /** + * Perform any one-time initialization required when starting the service. + */ + public void startup() { + + if(logger.isDebugEnabled()) { + logger.debug("AaiResourceService started!"); + } + } + + + /** + * Creates a new relationship in the graph, automatically populating the edge + * properties based on the A&AI edge rules. + * + * @param content - Json structure describing the relationship to create. + * @param type - Relationship type supplied as a URI parameter. + * @param uri - Http request uri + * @param headers - Http request headers + * @param uriInfo - Http URI info field + * @param req - Http request structure. + * + * @return - Standard HTTP response. + */ + @POST + @Path("/relationships/{type}/") + @Consumes({MediaType.APPLICATION_JSON}) + @Produces({MediaType.APPLICATION_JSON}) + public Response createRelationship(String content, + @PathParam("type") String type, + @PathParam("uri") @Encoded String uri, + @Context HttpHeaders headers, + @Context UriInfo uriInfo, + @Context HttpServletRequest req) { + + LoggingUtil.initMdcContext(req, headers); + + if(logger.isDebugEnabled()) { + logger.debug("Incoming request..." + content); + } + + Response response = null; + + if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) { + + try { + + // Extract the edge payload from the request. + EdgePayload payload = EdgePayload.fromJson(content); + + // Do some basic validation on the payload. + if (payload.getProperties() == null || payload.getProperties().isJsonNull()) { + throw new CrudException("Invalid request Payload", Status.BAD_REQUEST); + } + if (payload.getId() != null) { + throw new CrudException("ID specified , use Http PUT to update Edge", Status.BAD_REQUEST); + } + if (payload.getType() != null && !payload.getType().equals(type)) { + throw new CrudException("Edge Type mismatch", Status.BAD_REQUEST); + } + + // Apply the edge rules to our edge. + payload = applyEdgeRulesToPayload(payload); + + if(logger.isDebugEnabled()) { + logger.debug("Creating AAI edge using version " + RelationshipSchemaLoader.getLatestSchemaVersion() ); + } + + // Now, create our edge in the graph store. + String result = crudGraphDataService.addEdge(RelationshipSchemaLoader.getLatestSchemaVersion(), type, payload); + response = Response.status(Status.CREATED).entity(result).type(mediaType).build(); + + } catch (CrudException e) { + + response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build(); + } + } + + LoggingUtil.logRestRequest(logger, auditLogger, req, response); + return response; + } + + + /** + * Creates a new relationship in the graph, automatically populating the edge + * properties based on the A&AI edge rules. + * + * @param content - Json structure describing the relationship to create. + * @param uri - Http request uri + * @param headers - Http request headers + * @param uriInfo - Http URI info field + * @param req - Http request structure. + * + * @return - Standard HTTP response. + * + */ + @POST + @Path("/relationships/") + @Consumes({MediaType.APPLICATION_JSON}) + @Produces({MediaType.APPLICATION_JSON}) + public Response createRelationship(String content, + @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 { + + // Extract the edge payload from the request. + EdgePayload payload = EdgePayload.fromJson(content); + + // Do some basic validation on the payload. + if (payload.getProperties() == null || payload.getProperties().isJsonNull()) { + throw new CrudException("Invalid request Payload", Status.BAD_REQUEST); + } + if (payload.getId() != null) { + throw new CrudException("ID specified , use Http PUT to update Edge", Status.BAD_REQUEST); + } + if (payload.getType() == null || payload.getType().isEmpty()) { + throw new CrudException("Missing Edge Type ", Status.BAD_REQUEST); + } + + // Apply the edge rules to our edge. + payload = applyEdgeRulesToPayload(payload); + + // Now, create our edge in the graph store. + String result = crudGraphDataService.addEdge(RelationshipSchemaLoader.getLatestSchemaVersion(), payload.getType(), payload); + response = Response.status(Status.CREATED).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; + } + + + + /** + * Upserts a relationship into the graph, automatically populating the edge properties + * based on the A&AI edge rules. The behaviour is as follows: + *

+ *

  • If no relationship with the supplied identifier already exists, then a new relationship + * is created with that id.
    + *
  • If a relationship with the supplied id DOES exist, then it is replaced with the supplied + * content. + * + * @param content - Json structure describing the relationship to create. + * @param type - Relationship type supplied as a URI parameter. + * @param id - Edge identifier. + * @param uri - Http request uri + * @param headers - Http request headers + * @param uriInfo - Http URI info field + * @param req - Http request structure. + * + * @return - Standard HTTP response. + */ + @PUT + @Path("/relationships/{type}/{id}") + @Consumes({MediaType.APPLICATION_JSON}) + @Produces({MediaType.APPLICATION_JSON}) + public Response upsertEdge(String content, + @PathParam("type") String type, + @PathParam("id") String id, + @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.PUT, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) { + + try { + + // Extract the edge payload from the request. + EdgePayload payload = EdgePayload.fromJson(content); + + // Do some basic validation on the payload. + if (payload.getProperties() == null || payload.getProperties().isJsonNull()) { + throw new CrudException("Invalid request Payload", Status.BAD_REQUEST); + } + if (payload.getId() != null && !payload.getId().equals(id)) { + throw new CrudException("ID Mismatch", Status.BAD_REQUEST); + } + + // Apply the edge rules to our edge. + payload = applyEdgeRulesToPayload(payload); + + String result; + if (headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE) != null && + headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE).equalsIgnoreCase("PATCH")) { + result = crudGraphDataService.patchEdge(RelationshipSchemaLoader.getLatestSchemaVersion(), id, type, payload); + } else { + + result = crudGraphDataService.updateEdge(RelationshipSchemaLoader.getLatestSchemaVersion(), id, type, 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; + } + + + /** + * Retrieves the properties defined in the edge rules for a relationship between the + * supplied vertex types. + * + * @param sourceVertexType - Type of source vertex for the relationship. + * @param targetVertexType - Type of target vertex for the relationship. + * + * @return - The defined properties for the relationship type. + * + * @throws CrudException + */ + private Map getEdgeRuleProperties(String sourceVertexType, String targetVertexType) throws CrudException { + + if(logger.isDebugEnabled()) { + logger.debug("Lookup db edge rules for " + sourceVertexType + " -> " + targetVertexType); + } + + EdgeRules rules = EdgeRules.getInstance(); + EdgeRule rule; + try { + + if(logger.isDebugEnabled()) { + logger.debug("Lookup by edge type TREE"); + } + + // We have no way of knowing in advance whether our relationship is considered to + // be a tree or cousing relationship, so try looking it up as a tree type first. + rule = rules.getEdgeRule(EdgeType.TREE, sourceVertexType, targetVertexType); + + } catch (AAIException e) { + try { + + if(logger.isDebugEnabled()) { + logger.debug("Lookup by edge type COUSIN"); + } + + // If we are here, then our lookup by 'tree' type failed, so try looking it up + // as a 'cousin' relationship. + rule = rules.getEdgeRule(EdgeType.COUSIN, sourceVertexType, targetVertexType); + + } catch (AAIException e1) { + + // If we're here then we failed to find edge rules for this relationship. Time to + // give up... + throw new CrudException("No edge rules for " + sourceVertexType + " -> " + targetVertexType, Status.NOT_FOUND); + } + } catch (Exception e) { + + throw new CrudException("General failure getting edge rule properties - " + + e.getMessage(), Status.INTERNAL_SERVER_ERROR); + } + + return rule.getEdgeProperties(); + } + + + /** + * This method takes an inbound edge request payload, looks up the edge rules for the + * sort of relationship defined in the payload, and automatically applies the defined + * edge properties to it. + * + * @param payload - The original edge request payload + * + * @return - An updated edge request payload, with the properties defined in the edge + * rules automatically populated. + * + * @throws CrudException + */ + public EdgePayload applyEdgeRulesToPayload(EdgePayload payload) throws CrudException { + + // Extract the types for both the source and target vertices. + String srcType = RelationshipSchemaValidator.vertexTypeFromUri(payload.getSource()); + String tgtType = RelationshipSchemaValidator.vertexTypeFromUri(payload.getTarget()); + + // Now, get the default properties for this edge based on the edge rules definition... + Map props = getEdgeRuleProperties(srcType, tgtType); + + // ...and merge them with any custom properties provided in the request. + JsonElement mergedProperties = mergeProperties(payload.getProperties(), props); + payload.setProperties(mergedProperties); + + + if(logger.isDebugEnabled()) { + logger.debug("Edge properties after applying rules for '" + srcType + " -> " + tgtType + "': " + mergedProperties); + } + + return payload; + } + + + /** + * Given a set of edge properties extracted from an edge request payload and a set of properties + * taken from the db edge rules, this method merges them into one set of properties. + *

    + * If the client has attempted to override the defined value for a property in the db edge rules + * then the request will be rejected as invalid. + * + * @param propertiesFromRequest - Set of properties from the edge request. + * @param propertyDefaults - Set of properties from the db edge rules. + * + * @return - A merged set of properties. + * + * @throws CrudException + */ + public JsonElement mergeProperties(JsonElement propertiesFromRequest, Map propertyDefaults) throws CrudException { + + // Convert the properties from the edge payload into something we can + // manipulate. + Set> properties = new HashSet>(); + properties.addAll(propertiesFromRequest.getAsJsonObject().entrySet()); + + Set propertyKeys = new HashSet(); + for(Map.Entry property : properties) { + propertyKeys.add(property.getKey()); + } + + // Now, merge in the properties specified in the Db Edge Rules. + for(EdgeProperty defProperty : propertyDefaults.keySet()) { + + // If the edge rules property was explicitly specified by the + // client then we will reject the request... + if(!propertyKeys.contains(defProperty.toString())) { + properties.add(new AbstractMap.SimpleEntry(defProperty.toString(), + (JsonElement)(new JsonPrimitive(propertyDefaults.get(defProperty))))); + + } else { + throw new CrudException("Property " + defProperty + " defined in db edge rules can not be overriden by the client.", + Status.BAD_REQUEST); + } + } + + Object[] propArray = properties.toArray(); + StringBuilder sb = new StringBuilder(); + sb.append("{"); + boolean first=true; + for(int i=0; i entry = (Entry) propArray[i]; + if(!first) { + sb.append(","); + } + sb.append("\"").append(entry.getKey()).append("\"").append(":").append(entry.getValue()); + first=false; + } + sb.append("}"); + + // We're done. Return the result as a JsonElement. + return gson.fromJson(sb.toString(), JsonElement.class); + } + + + /** + * Invokes authentication validation on an incoming HTTP request. + * + * @param req - The HTTP request. + * @param uri - HTTP URI + * @param content - Payload of the HTTP request. + * @param action - What HTTP action is being performed (GET/PUT/POST/PATCH/DELETE) + * @param authPolicyFunctionName - Policy function being invoked. + * + * @return true - if the request passes validation, + * false - otherwise. + */ + protected boolean validateRequest(HttpServletRequest req, + String uri, + String content, + Action action, + String authPolicyFunctionName) { + try { + String cipherSuite = (String) req.getAttribute("javax.servlet.request.cipher_suite"); + String authUser = null; + if (cipherSuite != null) { + + X509Certificate[] certChain = (X509Certificate[]) req.getAttribute("javax.servlet.request.X509Certificate"); + X509Certificate clientCert = certChain[0]; + X500Principal subjectDn = clientCert.getSubjectX500Principal(); + authUser = subjectDn.toString(); + } + + return this.auth.validateRequest(authUser.toLowerCase(), action.toString() + ":" + authPolicyFunctionName); + + } catch (Exception e) { + logResult(action, uri, e); + return false; + } + } + + protected void logResult(Action op, String uri, Exception e) { + + logger.error(CrudServiceMsgs.EXCEPTION_DURING_METHOD_CALL, + op.toString(), + uri, + e.getStackTrace().toString()); + + // Clear the MDC context so that no other transaction inadvertently + // uses our transaction id. + MDC.clear(); + } +} diff --git a/src/main/java/org/onap/crud/service/BulkPayload.java b/src/main/java/org/onap/crud/service/BulkPayload.java new file mode 100644 index 0000000..538d9c0 --- /dev/null +++ b/src/main/java/org/onap/crud/service/BulkPayload.java @@ -0,0 +1,124 @@ +/** + * ============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.onap.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.onap.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 objects = new ArrayList(); + private List relationships = new ArrayList(); + + 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 getObjects() { + return objects; + } + + public void setObjects(List objects) { + this.objects = objects; + } + + public List getRelationships() { + return relationships; + } + + public void setRelationships(List 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 po = p.getObjects(); + List ids = new ArrayList(); + for (JsonElement e : po) { + Set> entries = e.getAsJsonObject().entrySet(); + + for (Map.Entry 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/onap/crud/service/CrudGraphDataService.java b/src/main/java/org/onap/crud/service/CrudGraphDataService.java new file mode 100644 index 0000000..268e492 --- /dev/null +++ b/src/main/java/org/onap/crud/service/CrudGraphDataService.java @@ -0,0 +1,301 @@ +/** + * ============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.onap.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.onap.aai.champcore.ChampGraph; +import org.onap.crud.dao.GraphDao; +import org.onap.crud.dao.champ.ChampDao; +import org.onap.crud.entity.Edge; + +import org.onap.crud.entity.Vertex; +import org.onap.crud.exception.CrudException; +import org.onap.crud.parser.CrudResponseBuilder; +import org.onap.schema.OxmModelValidator; +import org.onap.schema.RelationshipSchemaLoader; +import org.onap.schema.RelationshipSchemaValidator; + +import com.google.gson.JsonElement; + +public class CrudGraphDataService { + + private GraphDao dao; + + public CrudGraphDataService(ChampGraph graphImpl) throws CrudException { + this.dao = new ChampDao(graphImpl); + + loadModels(); + } + + 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(); + } + + 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 vertices = new HashMap(); + HashMap edges = new HashMap(); + String txId = dao.openTransaction(); + try { + // Handle vertices + for (JsonElement v : payload.getObjects()) { + List> entries = new ArrayList>( + v.getAsJsonObject().entrySet()); + + if (entries.size() != 2) { + throw new CrudException("", Status.BAD_REQUEST); + } + Map.Entry opr = entries.get(0); + Map.Entry 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> entries = new ArrayList>( + v.getAsJsonObject().entrySet()); + + if (entries.size() != 2) { + throw new CrudException("", Status.BAD_REQUEST); + } + Map.Entry opr = entries.get(0); + Map.Entry 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()); + return CrudResponseBuilder + .buildUpsertVertexResponse(OxmModelValidator.validateOutgoingPayload(version, addedVertex), version); + } + + public String addEdge(String version, String type, EdgePayload payload) throws CrudException { + Edge edge = RelationshipSchemaValidator.validateIncomingAddPayload(version, type, payload); + return addEdge(version, edge); + } + + private String addEdge(String version, Edge edge) throws CrudException { + Edge addedEdge = dao.addEdge(edge.getType(), edge.getSource(), edge.getTarget(), edge.getProperties()); + return CrudResponseBuilder + .buildUpsertEdgeResponse(RelationshipSchemaValidator.validateOutgoingPayload(version, addedEdge), version); + } + + public String getEdge(String version, String id, String type) throws CrudException { + RelationshipSchemaValidator.validateType(version, type); + Edge edge = dao.getEdge(id, type); + + return CrudResponseBuilder.buildGetEdgeResponse(RelationshipSchemaValidator.validateOutgoingPayload(version, edge), + version); + } + + public String getEdges(String version, String type, Map filter) throws CrudException { + RelationshipSchemaValidator.validateType(version, type); + List items = dao.getEdges(type, RelationshipSchemaValidator.resolveCollectionfilter(version, type, filter)); + return CrudResponseBuilder.buildGetEdgesResponse(items, version); + } + + public String updateVertex(String version, String id, String type, VertexPayload payload) throws CrudException { + Vertex vertex = OxmModelValidator.validateIncomingUpsertPayload(id, version, type, payload.getProperties()); + return updateVertex(version, vertex); + + } + + private String updateVertex(String version, Vertex vertex) throws CrudException { + Vertex updatedVertex = dao.updateVertex(vertex.getId().get(), vertex.getType(), vertex.getProperties()); + return CrudResponseBuilder + .buildUpsertVertexResponse(OxmModelValidator.validateOutgoingPayload(version, updatedVertex), version); + } + + public String patchVertex(String version, String id, String type, VertexPayload payload) throws CrudException { + Vertex existingVertex = dao.getVertex(id, OxmModelValidator.resolveCollectionType(version, type)); + Vertex vertex = OxmModelValidator.validateIncomingPatchPayload(id, version, type, payload.getProperties(), + existingVertex); + return updateVertex(version, vertex); + + } + + public String deleteVertex(String version, String id, String type) throws CrudException { + type = OxmModelValidator.resolveCollectionType(version, type); + dao.deleteVertex(id, type); + return ""; + + } + + public String deleteEdge(String version, String id, String type) throws CrudException { + RelationshipSchemaValidator.validateType(version, type); + dao.deleteEdge(id, type); + return ""; + + } + + public String updateEdge(String version, String id, String type, EdgePayload payload) throws CrudException { + Edge edge = dao.getEdge(id, type); + Edge validatedEdge = RelationshipSchemaValidator.validateIncomingUpdatePayload(edge, version, payload); + return updateEdge(version, validatedEdge); + + } + + private String updateEdge(String version, Edge edge) throws CrudException { + Edge updatedEdge = dao.updateEdge(edge); + return CrudResponseBuilder + .buildUpsertEdgeResponse(RelationshipSchemaValidator.validateOutgoingPayload(version, updatedEdge), version); + } + + public String patchEdge(String version, String id, String type, EdgePayload payload) throws CrudException { + Edge edge = dao.getEdge(id, type); + Edge patchedEdge = RelationshipSchemaValidator.validateIncomingPatchPayload(edge, version, payload); + return updateEdge(version, patchedEdge); + + } + + public Vertex getVertex(String id) throws CrudException { + return dao.getVertex(id); + } + + public String getVertex(String version, String id, String type) throws CrudException { + type = OxmModelValidator.resolveCollectionType(version, type); + Vertex vertex = dao.getVertex(id, type); + List edges = dao.getVertexEdges(id); + return CrudResponseBuilder.buildGetVertexResponse(OxmModelValidator.validateOutgoingPayload(version, vertex), edges, + version); + } + + public String getVertices(String version, String type, Map filter) throws CrudException { + type = OxmModelValidator.resolveCollectionType(version, type); + List items = dao.getVertices(type, OxmModelValidator.resolveCollectionfilter(version, type, filter)); + return CrudResponseBuilder.buildGetVerticesResponse(items, version); + } + +} diff --git a/src/main/java/org/onap/crud/service/CrudRestService.java b/src/main/java/org/onap/crud/service/CrudRestService.java new file mode 100644 index 0000000..da792b5 --- /dev/null +++ b/src/main/java/org/onap/crud/service/CrudRestService.java @@ -0,0 +1,784 @@ +/** + * ============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.onap.crud.service; + +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; +import javax.ws.rs.DELETE; +import javax.ws.rs.Encoded; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +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.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.crud.exception.CrudException; +import org.onap.crud.logging.CrudServiceMsgs; +import org.onap.crud.logging.LoggingUtil; +import org.onap.crud.util.CrudServiceConstants; +import org.slf4j.MDC; + +import com.google.gson.JsonElement; + +public class CrudRestService { + + private CrudGraphDataService crudGraphDataService; + Logger logger = LoggerFactory.getInstance().getLogger(CrudRestService.class.getName()); + Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(CrudRestService.class.getName()); + private Auth auth; + + private String mediaType = MediaType.APPLICATION_JSON; + public static final String HTTP_PATCH_METHOD_OVERRIDE = "X-HTTP-Method-Override"; + + public CrudRestService(CrudGraphDataService crudGraphDataService) throws Exception { + this.crudGraphDataService = crudGraphDataService; + this.auth = new Auth(CrudServiceConstants.CRD_AUTH_FILE); + } + + public enum Action { + POST, GET, PUT, DELETE, PATCH + } + + ; + + public void startup() { + + } + + @GET + @Path("/{version}/{type}/{id}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public Response getVertex(String content, @PathParam("version") String version, @PathParam("type") String type, + @PathParam("id") String id, @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.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) { + + try { + String result = crudGraphDataService.getVertex(version, id, type); + 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; + } + + @GET + @Path("/{version}/{type}/") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public Response getVertices(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.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) { + + Map filter = new HashMap(); + for (Map.Entry> e : uriInfo.getQueryParameters().entrySet()) { + filter.put(e.getKey(), e.getValue().get(0)); + } + + try { + String result = crudGraphDataService.getVertices(version, type, filter); + 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; + } + + @GET + @Path("/relationships/{version}/{type}/{id}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public Response getEdge(String content, @PathParam("version") String version, @PathParam("type") String type, + @PathParam("id") String id, @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.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) { + + try { + + String result = crudGraphDataService.getEdge(version, id, type); + 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; + } + + @GET + @Path("/relationships/{version}/{type}/") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public Response getEdges(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.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) { + + Map filter = new HashMap(); + for (Map.Entry> e : uriInfo.getQueryParameters().entrySet()) { + filter.put(e.getKey(), e.getValue().get(0)); + } + + try { + String result = crudGraphDataService.getEdges(version, type, filter); + 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; + } + + @PUT + @Path("/relationships/{version}/{type}/{id}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public Response updateEdge(String content, @PathParam("version") String version, @PathParam("type") String type, + @PathParam("id") String id, @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.PUT, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) { + + try { + EdgePayload payload = EdgePayload.fromJson(content); + if (payload.getProperties() == null || payload.getProperties().isJsonNull()) { + throw new CrudException("Invalid request Payload", Status.BAD_REQUEST); + } + if (payload.getId() != null && !payload.getId().equals(id)) { + throw new CrudException("ID Mismatch", Status.BAD_REQUEST); + } + String result; + + if (headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE) != null + && headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE).equalsIgnoreCase("PATCH")) { + result = crudGraphDataService.patchEdge(version, id, type, payload); + } else { + + result = crudGraphDataService.updateEdge(version, id, type, 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; + } + + @PATCH + @Path("/relationships/{version}/{type}/{id}") + @Consumes({ "application/merge-patch+json" }) + @Produces({ MediaType.APPLICATION_JSON }) + public Response patchEdge(String content, @PathParam("version") String version, @PathParam("type") String type, + @PathParam("id") String id, @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.PATCH, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) { + + try { + EdgePayload payload = EdgePayload.fromJson(content); + if (payload.getProperties() == null || payload.getProperties().isJsonNull()) { + throw new CrudException("Invalid request Payload", Status.BAD_REQUEST); + } + if (payload.getId() != null && !payload.getId().equals(id)) { + throw new CrudException("ID Mismatch", Status.BAD_REQUEST); + } + + String result = crudGraphDataService.patchEdge(version, id, type, 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; + } + + @PUT + @Path("/{version}/{type}/{id}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public Response updateVertex(String content, @PathParam("version") String version, @PathParam("type") String type, + @PathParam("id") String id, @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.PUT, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) { + + try { + VertexPayload payload = VertexPayload.fromJson(content); + if (payload.getProperties() == null || payload.getProperties().isJsonNull()) { + throw new CrudException("Invalid request Payload", Status.BAD_REQUEST); + } + if (payload.getId() != null && !payload.getId().equals(id)) { + throw new CrudException("ID Mismatch", Status.BAD_REQUEST); + } + String result; + if (headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE) != null + && headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE).equalsIgnoreCase("PATCH")) { + result = crudGraphDataService.patchVertex(version, id, type, payload); + } else { + + result = crudGraphDataService.updateVertex(version, id, type, 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; + } + + @PATCH + @Path("/{version}/{type}/{id}") + @Consumes({ "application/merge-patch+json" }) + @Produces({ MediaType.APPLICATION_JSON }) + public Response patchVertex(String content, @PathParam("version") String version, @PathParam("type") String type, + @PathParam("id") String id, @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.PATCH, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) { + try { + VertexPayload payload = VertexPayload.fromJson(content); + if (payload.getProperties() == null || payload.getProperties().isJsonNull()) { + throw new CrudException("Invalid request Payload", Status.BAD_REQUEST); + } + if (payload.getId() != null && !payload.getId().equals(id)) { + throw new CrudException("ID Mismatch", Status.BAD_REQUEST); + } + + String result = crudGraphDataService.patchVertex(version, id, type, 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}/{type}/") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public Response addVertex(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 { + VertexPayload payload = VertexPayload.fromJson(content); + if (payload.getProperties() == null || payload.getProperties().isJsonNull()) { + throw new CrudException("Invalid request Payload", Status.BAD_REQUEST); + } + if (payload.getId() != null) { + throw new CrudException("ID specified , use Http PUT to update Vertex", Status.BAD_REQUEST); + } + + if (payload.getType() != null && !payload.getType().equals(type)) { + throw new CrudException("Vertex Type mismatch", Status.BAD_REQUEST); + } + + String result = crudGraphDataService.addVertex(version, type, payload); + response = Response.status(Status.CREATED).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; + } + + private void validateBulkPayload(BulkPayload payload) throws CrudException { + List vertices = new ArrayList(); + List edges = new ArrayList(); + + for (JsonElement v : payload.getObjects()) { + List> entries = new ArrayList>( + v.getAsJsonObject().entrySet()); + + if (entries.size() != 2) { + throw new CrudException("", Status.BAD_REQUEST); + } + Map.Entry opr = entries.get(0); + Map.Entry 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> entries = new ArrayList>( + v.getAsJsonObject().entrySet()); + + if (entries.size() != 2) { + throw new CrudException("", Status.BAD_REQUEST); + } + Map.Entry opr = entries.get(0); + Map.Entry 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}/") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public Response addVertex(String content, @PathParam("version") String version, @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 { + + VertexPayload payload = VertexPayload.fromJson(content); + if (payload.getProperties() == null || payload.getProperties().isJsonNull()) { + throw new CrudException("Invalid request Payload", Status.BAD_REQUEST); + } + if (payload.getId() != null) { + throw new CrudException("ID specified , use Http PUT to update Vertex", Status.BAD_REQUEST); + } + + if (payload.getType() == null || payload.getType().isEmpty()) { + throw new CrudException("Missing Vertex Type ", Status.BAD_REQUEST); + } + String result = crudGraphDataService.addVertex(version, payload.getType(), payload); + response = Response.status(Status.CREATED).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("/relationships/{version}/{type}/") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public Response addEdge(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 { + EdgePayload payload = EdgePayload.fromJson(content); + if (payload.getProperties() == null || payload.getProperties().isJsonNull()) { + throw new CrudException("Invalid request Payload", Status.BAD_REQUEST); + } + if (payload.getId() != null) { + throw new CrudException("ID specified , use Http PUT to update Edge", Status.BAD_REQUEST); + } + + if (payload.getType() != null && !payload.getType().equals(type)) { + throw new CrudException("Edge Type mismatch", Status.BAD_REQUEST); + } + String result = crudGraphDataService.addEdge(version, type, payload); + response = Response.status(Status.CREATED).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("/relationships/{version}/") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public Response addEdge(String content, @PathParam("version") String version, @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 { + EdgePayload payload = EdgePayload.fromJson(content); + if (payload.getProperties() == null || payload.getProperties().isJsonNull()) { + throw new CrudException("Invalid request Payload", Status.BAD_REQUEST); + } + if (payload.getId() != null) { + throw new CrudException("ID specified , use Http PUT to update Edge", Status.BAD_REQUEST); + } + + if (payload.getType() == null || payload.getType().isEmpty()) { + throw new CrudException("Missing Edge Type ", Status.BAD_REQUEST); + } + String result = crudGraphDataService.addEdge(version, payload.getType(), payload); + + response = Response.status(Status.CREATED).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; + } + + @DELETE + @Path("/{version}/{type}/{id}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public Response deleteVertex(String content, @PathParam("version") String version, @PathParam("type") String type, + @PathParam("id") String id, @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.DELETE, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) { + + try { + String result = crudGraphDataService.deleteVertex(version, id, type); + 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; + } + + @DELETE + @Path("/relationships/{version}/{type}/{id}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public Response deleteEdge(String content, @PathParam("version") String version, @PathParam("type") String type, + @PathParam("id") String id, @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.DELETE, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) { + + try { + String result = crudGraphDataService.deleteEdge(version, id, type); + 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; + } + + protected boolean validateRequest(HttpServletRequest req, String uri, String content, Action action, + String authPolicyFunctionName) { + try { + String cipherSuite = (String) req.getAttribute("javax.servlet.request.cipher_suite"); + String authUser = null; + if (cipherSuite != null) { + X509Certificate[] certChain = (X509Certificate[]) req.getAttribute("javax.servlet.request.X509Certificate"); + X509Certificate clientCert = certChain[0]; + X500Principal subjectDn = clientCert.getSubjectX500Principal(); + authUser = subjectDn.toString(); + } + return this.auth.validateRequest(authUser.toLowerCase(), action.toString() + ":" + authPolicyFunctionName); + } catch (Exception e) { + logResult(action, uri, e); + return false; + } + } + + void logResult(Action op, String uri, Exception e) { + + logger.error(CrudServiceMsgs.EXCEPTION_DURING_METHOD_CALL, op.toString(), uri, e.getStackTrace().toString()); + + // Clear the MDC context so that no other transaction inadvertently + // uses our transaction id. + MDC.clear(); + } +} diff --git a/src/main/java/org/onap/crud/service/EdgePayload.java b/src/main/java/org/onap/crud/service/EdgePayload.java new file mode 100644 index 0000000..dc25497 --- /dev/null +++ b/src/main/java/org/onap/crud/service/EdgePayload.java @@ -0,0 +1,115 @@ +/** + * ============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.onap.crud.service; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; + +import org.onap.crud.exception.CrudException; + +import javax.ws.rs.core.Response.Status; + +public class EdgePayload { + + private String id; + private String type; + private String url; + private String source; + private String target; + private JsonElement properties; + + private static final Gson gson = new GsonBuilder().disableHtmlEscaping().create(); + + + @Override + public String toString() { + return "EdgePayload [id=" + id + ", type=" + type + ", url=" + url + ", source=" + + source + ", target=" + target + ", properties=" + properties + "]"; + } + + public String toJson() { + return gson.toJson(this); + } + + public static EdgePayload fromJson(String payload) throws CrudException { + try { + if (payload == null || payload.isEmpty()) { + throw new CrudException("Invalid Json Payload", Status.BAD_REQUEST); + } + return gson.fromJson(payload, EdgePayload.class); + } catch (Exception ex) { + throw new CrudException("Invalid Json Payload", Status.BAD_REQUEST); + } + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getSource() { + return source; + } + + public void setSource(String source) { + this.source = source; + } + + public String getTarget() { + return target; + } + + public void setTarget(String target) { + this.target = target; + } + + public JsonElement getProperties() { + return properties; + } + + public void setProperties(JsonElement properties) { + this.properties = properties; + } + +} \ No newline at end of file diff --git a/src/main/java/org/onap/crud/service/JaxrsEchoService.java b/src/main/java/org/onap/crud/service/JaxrsEchoService.java new file mode 100644 index 0000000..cdea726 --- /dev/null +++ b/src/main/java/org/onap/crud/service/JaxrsEchoService.java @@ -0,0 +1,63 @@ +/** + * ============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.onap.crud.service; + +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.crud.logging.LoggingUtil; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.UriInfo; + + +public class JaxrsEchoService { + + private static Logger logger = LoggerFactory.getInstance() + .getLogger(JaxrsEchoService.class.getName()); + private static Logger auditLogger = LoggerFactory.getInstance() + .getAuditLogger(JaxrsEchoService.class.getName()); + + @GET + @Path("echo/{input}") + @Produces("text/plain") + public String ping(@PathParam("input") String input, + @Context HttpHeaders headers, + @Context UriInfo info, + @Context HttpServletRequest req) { + + LoggingUtil.initMdcContext(req, headers); + LoggingUtil.logRestRequest(logger, auditLogger, req, Response.status(Status.OK) + .entity("OK").build()); + + return "Hello, " + input + "."; + } +} \ No newline at end of file diff --git a/src/main/java/org/onap/crud/service/VertexPayload.java b/src/main/java/org/onap/crud/service/VertexPayload.java new file mode 100644 index 0000000..4529d70 --- /dev/null +++ b/src/main/java/org/onap/crud/service/VertexPayload.java @@ -0,0 +1,117 @@ +/** + * ============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.onap.crud.service; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; + +import org.onap.crud.exception.CrudException; + +import java.util.ArrayList; +import java.util.List; +import javax.ws.rs.core.Response.Status; + +public class VertexPayload { + + private String id; + private String type; + private String url; + private JsonElement properties; + private List in = new ArrayList(); + private List out = new ArrayList(); + + private static final Gson gson = new GsonBuilder().disableHtmlEscaping().create(); + + public String toJson() { + return gson.toJson(this); + } + + public static VertexPayload fromJson(String payload) throws CrudException { + try { + if (payload == null || payload.isEmpty()) { + throw new CrudException("Invalid Json Payload", Status.BAD_REQUEST); + } + return gson.fromJson(payload, VertexPayload.class); + } catch (Exception ex) { + throw new CrudException("Invalid Json Payload", Status.BAD_REQUEST); + } + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public JsonElement getProperties() { + return properties; + } + + public void setProperties(JsonElement properties) { + this.properties = properties; + } + + public List getIn() { + return in; + } + + public void setIn(List in) { + this.in = in; + } + + public List getOut() { + return out; + } + + public void setOut(List out) { + this.out = out; + } + + + @Override + public String toString() { + return "VertexPayload [id=" + id + ", type=" + type + ", url=" + url + ", properties=" + + properties + ", in=" + in + ", out=" + out + "]"; + } + +} \ No newline at end of file diff --git a/src/main/java/org/onap/crud/util/CrudJaxbTransformation.java b/src/main/java/org/onap/crud/util/CrudJaxbTransformation.java new file mode 100644 index 0000000..05afea2 --- /dev/null +++ b/src/main/java/org/onap/crud/util/CrudJaxbTransformation.java @@ -0,0 +1,92 @@ +/** + * ============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.onap.crud.util; + +import org.eclipse.persistence.dynamic.DynamicEntity; +import org.eclipse.persistence.jaxb.JAXBMarshaller; +import org.eclipse.persistence.jaxb.MarshallerProperties; +import org.eclipse.persistence.jaxb.UnmarshallerProperties; +import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext; + +import java.io.StringReader; +import java.io.StringWriter; +import javax.ws.rs.core.MediaType; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import javax.xml.transform.stream.StreamSource; + +public class CrudJaxbTransformation { + /** + * Marshal a dynamic entity into a string. + * + * @param entity the dynamic entity + * @param jaxbContext the dynamic jaxb context + * @return the marshaled entity + * @throws RouterException on error + */ + public static String marshal(MediaType mediaType, final DynamicEntity entity, + final DynamicJAXBContext jaxbContext) throws JAXBException { + + final JAXBMarshaller marshaller = jaxbContext.createMarshaller(); + marshaller.setProperty(JAXBMarshaller.JAXB_FORMATTED_OUTPUT, false); + + if (MediaType.APPLICATION_JSON_TYPE.isCompatible(mediaType)) { + marshaller.setProperty("eclipselink.media-type", "application/json"); + marshaller.setProperty("eclipselink.json.include-root", false); + marshaller.setProperty(MarshallerProperties.JSON_MARSHAL_EMPTY_COLLECTIONS, Boolean.FALSE); + } + + final StringWriter writer = new StringWriter(); + marshaller.marshal(entity, writer); + return writer.toString(); + + } + + /** + * @param type + * @param json + * @param mediaType + * @return + * @throws JAXBException + * @throws Exception + */ + public static Object unmarshal(String javaClass, String content, MediaType mediaType, + final DynamicJAXBContext jaxbContext) throws JAXBException { + Object clazz = null; + Unmarshaller unmarshaller = null; + + clazz = jaxbContext.newDynamicEntity(javaClass); + + unmarshaller = jaxbContext.createUnmarshaller(); + if (mediaType.equals(MediaType.APPLICATION_JSON_TYPE)) { + unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json"); + unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false); + unmarshaller.setProperty(UnmarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true); + } + + return unmarshaller.unmarshal(new StreamSource(new StringReader(content)), + clazz.getClass()).getValue(); + } + +} diff --git a/src/main/java/org/onap/crud/util/CrudProperties.java b/src/main/java/org/onap/crud/util/CrudProperties.java new file mode 100644 index 0000000..b029dd1 --- /dev/null +++ b/src/main/java/org/onap/crud/util/CrudProperties.java @@ -0,0 +1,77 @@ +/** + * ============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.onap.crud.util; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Properties; + +public class CrudProperties { + + private static Properties properties; + + static { + properties = new Properties(); + File file = new File(CrudServiceConstants.CRD_CONFIG_FILE); + try { + properties.load(new FileInputStream(file)); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static String get(String key) { + return properties.getProperty(key); + } + + public static String get(String key, String defaultValue) { + return properties.getProperty(key, defaultValue); + } + + public static void put(String key, String value) { + properties.setProperty(key, value); + FileOutputStream fileOut = null; + try { + fileOut = new FileOutputStream(new File(CrudServiceConstants.CRD_CONFIG_FILE)); + properties.store(fileOut, "Added property: " + key); + } catch (Exception e) { + e.printStackTrace(); + } finally { + + try { + fileOut.close(); + } catch (IOException ex) { + ex.printStackTrace(); + } + } + + } + + +} diff --git a/src/main/java/org/onap/crud/util/CrudServiceConstants.java b/src/main/java/org/onap/crud/util/CrudServiceConstants.java new file mode 100644 index 0000000..0d07707 --- /dev/null +++ b/src/main/java/org/onap/crud/util/CrudServiceConstants.java @@ -0,0 +1,54 @@ +/** + * ============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.onap.crud.util; + +public class CrudServiceConstants { + public static final String CRD_SERVICE_NAME = "Crud-Service"; + + public static final String CRD_FILESEP = (System.getProperty("file.separator") == null) ? "/" + : System.getProperty("file.separator"); + + public static final String CRD_SPECIFIC_CONFIG = System.getProperty("CONFIG_HOME") + CRD_FILESEP; + + public static final String CRD_HOME_MODEL = CRD_SPECIFIC_CONFIG + "model" + CRD_FILESEP; + public static final String CRD_HOME_AUTH = CRD_SPECIFIC_CONFIG + "auth" + CRD_FILESEP; + + public static final String CRD_GRAPH_HOST = "crud.graph.host"; + public static final String CRD_GRAPH_PORT = "crud.graph.port"; + public static final String CRD_GRAPH_NAME = "crud.graph.name"; + public static final String CRD_STORAGE_BACKEND_DB = "crud.storage.backend.db"; + public static final String CRD_HBASE_ZNODE_PARENT + = "crud.storage.hbase.ext.zookeeper.znode.parent"; + + 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"; + + public static final String CRD_EVENT_STREAM_HOSTS = "event.stream.hosts"; + + + +} diff --git a/src/main/java/org/onap/crud/util/CrudServiceUtil.java b/src/main/java/org/onap/crud/util/CrudServiceUtil.java new file mode 100644 index 0000000..49b0317 --- /dev/null +++ b/src/main/java/org/onap/crud/util/CrudServiceUtil.java @@ -0,0 +1,63 @@ +/** + * ============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.onap.crud.util; + +import org.onap.crud.exception.CrudException; + +import javax.ws.rs.core.Response.Status; + +public class CrudServiceUtil { + + + public static Object validateFieldType(String value, Class clazz) throws CrudException { + try { + if (clazz.isAssignableFrom(Integer.class)) { + return Integer.parseInt(value); + } else if (clazz.isAssignableFrom(Long.class)) { + return Long.parseLong(value); + } else if (clazz.isAssignableFrom(Float.class)) { + return Float.parseFloat(value); + } else if (clazz.isAssignableFrom(Double.class)) { + return Double.parseDouble(value); + } else if (clazz.isAssignableFrom(Boolean.class)) { + + // If the value is an IN/OUT direction, this gets seen as a boolean, so + // check for that first. + if (value.equals("OUT") || value.equals("IN")) { + return value; + } + + if (!value.equals("true") && !value.equals("false")) { + throw new CrudException("Invalid propertry value: " + value, Status.BAD_REQUEST); + } + return Boolean.parseBoolean(value); + } else { + return value; + } + } catch (Exception e) { + throw new CrudException("Invalid property value: " + value, Status.BAD_REQUEST); + } + } + +} diff --git a/src/main/java/org/onap/crud/util/FileWatcher.java b/src/main/java/org/onap/crud/util/FileWatcher.java new file mode 100644 index 0000000..711fa08 --- /dev/null +++ b/src/main/java/org/onap/crud/util/FileWatcher.java @@ -0,0 +1,48 @@ +/** + * ============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.onap.crud.util; + +import java.io.File; +import java.util.TimerTask; + +public abstract class FileWatcher extends TimerTask { + private long timeStamp; + private File file; + + public FileWatcher(File file) { + this.file = file; + this.timeStamp = file.lastModified(); + } + + public final void run() { + long timeStamp = file.lastModified(); + + if ((timeStamp - this.timeStamp) > 500) { + this.timeStamp = timeStamp; + onChange(file); + } + } + + protected abstract void onChange(File file); +} \ No newline at end of file diff --git a/src/main/java/org/onap/schema/OxmModelValidator.java b/src/main/java/org/onap/schema/OxmModelValidator.java new file mode 100644 index 0000000..d23804c --- /dev/null +++ b/src/main/java/org/onap/schema/OxmModelValidator.java @@ -0,0 +1,331 @@ +/** + * ============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.onap.schema; + +import com.google.common.base.CaseFormat; +import com.google.gson.JsonElement; +import com.google.gson.JsonNull; + +import org.eclipse.persistence.dynamic.DynamicType; +import org.eclipse.persistence.internal.helper.DatabaseField; +import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext; +import org.eclipse.persistence.mappings.DatabaseMapping; +import org.eclipse.persistence.oxm.XMLField; +import org.onap.aaiutils.oxm.OxmModelLoader; +import org.onap.crud.entity.Vertex; +import org.onap.crud.exception.CrudException; +import org.onap.crud.util.CrudServiceUtil; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import javax.ws.rs.core.Response.Status; + +public class OxmModelValidator { + public enum Metadata { + NODE_TYPE("aai-node-type"), URI("aai-uri"), CREATED_TS("aai-created-ts"), SOT("source-of-truth"), LAST_MOD_SOT( + "last-mod-source-of-truth"); + + private final String propName; + + Metadata(String propName) { + this.propName = propName; + } + + public String propertyName() { + return propName; + } + + public static boolean isProperty(String property) { + for (Metadata meta : Metadata.values()) { + if (meta.propName.equals(property)) { + return true; + } + } + return false; + } + } + + public static Map resolveCollectionfilter(String version, String type, Map filter) + throws CrudException { + + DynamicJAXBContext jaxbContext = null; + try { + jaxbContext = OxmModelLoader.getContextForVersion(version); + } catch (Exception e) { + throw new CrudException(e); + } + + Map result = new HashMap(); + if (jaxbContext == null) { + throw new CrudException("", Status.NOT_FOUND); + } + final DynamicType modelObjectType = jaxbContext.getDynamicType( + CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, type))); + + for (String key : filter.keySet()) { + String keyJavaName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL, key); + if (modelObjectType.getDescriptor().getMappingForAttributeName(keyJavaName) != null) { + try { + DatabaseMapping mapping = modelObjectType.getDescriptor().getMappingForAttributeName(keyJavaName); + Object value = CrudServiceUtil.validateFieldType(filter.get(key), mapping.getField().getType()); + result.put(key, value); + } catch (Exception ex) { + // Skip any exceptions thrown while validating the filter + // key value + continue; + } + } + } + + return result; + + } + + public static String resolveCollectionType(String version, String type) throws CrudException { + + DynamicJAXBContext jaxbContext = null; + try { + jaxbContext = OxmModelLoader.getContextForVersion(version); + } catch (Exception e) { + throw new CrudException(e); + } + + if (jaxbContext == null) { + throw new CrudException("", Status.NOT_FOUND); + } + // Determine if the Object part is a collection type in the model + // definition + final DynamicType modelObjectType = jaxbContext.getDynamicType( + CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, type))); + + if (modelObjectType == null) { + throw new CrudException("", Status.NOT_FOUND); + } + + if (modelObjectType.getDescriptor().getMappings().size() == 1 + && modelObjectType.getDescriptor().getMappings().get(0).isCollectionMapping()) { + String childJavaObjectName = modelObjectType.getDescriptor().getMappings().get(0).getAttributeName(); + childJavaObjectName = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, childJavaObjectName); + final DynamicType childObjectType = jaxbContext.getDynamicType(childJavaObjectName); + if (childObjectType == null) { + // Should not happen as child object is defined in oxm model + // itself + throw new CrudException("", Status.NOT_FOUND); + } + return childObjectType.getDescriptor().getTableName(); + } else { + return modelObjectType.getDescriptor().getTableName(); + } + + } + + public static Vertex validateIncomingUpsertPayload(String id, String version, String type, JsonElement properties) + throws CrudException { + + try { + type = resolveCollectionType(version, type); + DynamicJAXBContext jaxbContext = OxmModelLoader.getContextForVersion(version); + String modelObjectClass = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, + CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, type)); + + final DynamicType modelObjectType = jaxbContext.getDynamicType(modelObjectClass); + final DynamicType reservedType = jaxbContext.getDynamicType("ReservedPropNames"); + + Set> payloadEntriesSet = properties.getAsJsonObject().entrySet(); + + // loop through input to validate against schema + for (Map.Entry entry : payloadEntriesSet) { + String keyJavaName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL, entry.getKey()); + + // check for valid field + if (modelObjectType.getDescriptor().getMappingForAttributeName(keyJavaName) == null) { + if (reservedType.getDescriptor().getMappingForAttributeName(keyJavaName) == null) { + throw new CrudException("Invalid field: " + entry.getKey(), Status.BAD_REQUEST); + } + } + + } + + Map entriesMap = new HashMap(); + for (Map.Entry entry : payloadEntriesSet) { + entriesMap.put(entry.getKey(), entry.getValue()); + } + + Vertex.Builder modelVertexBuilder = new Vertex.Builder(type); + if (id != null) { + modelVertexBuilder.id(id); + } + for (DatabaseMapping mapping : modelObjectType.getDescriptor().getMappings()) { + if (mapping.isAbstractDirectMapping()) { + DatabaseField field = mapping.getField(); + String defaultValue = mapping.getProperties().get("defaultValue") == null ? "" + : mapping.getProperties().get("defaultValue").toString(); + + String keyName = field.getName().substring(0, field.getName().indexOf("/")); + + if (((XMLField) field).isRequired() && !entriesMap.containsKey(keyName) && !defaultValue.isEmpty()) { + modelVertexBuilder.property(keyName, CrudServiceUtil.validateFieldType(defaultValue, field.getType())); + } + // if schema field is required and not set then reject + if (((XMLField) field).isRequired() && !entriesMap.containsKey(keyName) && defaultValue.isEmpty()) { + throw new CrudException("Missing required field: " + keyName, Status.BAD_REQUEST); + } + // If invalid field then reject + if (entriesMap.containsKey(keyName)) { + Object value = CrudServiceUtil.validateFieldType(entriesMap.get(keyName).getAsString(), field.getType()); + modelVertexBuilder.property(keyName, value); + } + + // Set defaults + if (!defaultValue.isEmpty() && !entriesMap.containsKey(keyName)) { + modelVertexBuilder.property(keyName, CrudServiceUtil.validateFieldType(defaultValue, field.getType())); + } + } + } + + // 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) { + throw new CrudException(e.getMessage(), Status.BAD_REQUEST); + } + } + + public static Vertex validateIncomingPatchPayload(String id, String version, String type, JsonElement properties, + Vertex existingVertex) throws CrudException { + + try { + type = resolveCollectionType(version, type); + DynamicJAXBContext jaxbContext = OxmModelLoader.getContextForVersion(version); + String modelObjectClass = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, + CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, type)); + + final DynamicType modelObjectType = jaxbContext.getDynamicType(modelObjectClass); + final DynamicType reservedType = jaxbContext.getDynamicType("ReservedPropNames"); + + Set> payloadEntriesSet = properties.getAsJsonObject().entrySet(); + + // Loop through the payload properties and merge with existing + // vertex props + for (Map.Entry entry : payloadEntriesSet) { + + String keyJavaName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL, entry.getKey()); + + 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); + } + + // check if mandatory field is not set to null + if (((XMLField) field).isRequired() && entry.getValue() instanceof JsonNull && !defaultValue.isEmpty()) { + existingVertex.getProperties().put(entry.getKey(), + CrudServiceUtil.validateFieldType(defaultValue, field.getType())); + } else if (((XMLField) field).isRequired() && entry.getValue() instanceof JsonNull && defaultValue.isEmpty()) { + throw new CrudException("Mandatory field: " + entry.getKey() + " can't be set to null", Status.BAD_REQUEST); + } else if (!((XMLField) field).isRequired() && entry.getValue() instanceof JsonNull + && existingVertex.getProperties().containsKey(entry.getKey())) { + existingVertex.getProperties().remove(entry.getKey()); + } else if (!(entry.getValue() instanceof JsonNull)) { + // add/update the value if found in existing vertex + Object value = CrudServiceUtil.validateFieldType(entry.getValue().getAsString(), field.getType()); + existingVertex.getProperties().put(entry.getKey(), value); + } + + } + + return existingVertex; + } catch (Exception e) { + throw new CrudException(e.getMessage(), Status.BAD_REQUEST); + } + + } + + private static DatabaseField getDatabaseField(String fieldName, DynamicType modelObjectType) { + for (DatabaseField field : modelObjectType.getDescriptor().getAllFields()) { + int ix = field.getName().indexOf("/"); + if (ix <= 0) { + ix = field.getName().length(); + } + + String keyName = field.getName().substring(0, ix); + if (fieldName.equals(keyName)) { + return field; + } + } + return null; + } + + public static Vertex validateOutgoingPayload(String version, Vertex vertex) { + + Vertex.Builder modelVertexBuilder = new Vertex.Builder(vertex.getType()).id(vertex.getId().get()); + + try { + DynamicJAXBContext jaxbContext = OxmModelLoader.getContextForVersion(version); + String modelObjectClass = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, + CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, + vertex.getProperties().get(Metadata.NODE_TYPE.propertyName()) != null + ? vertex.getProperties().get(Metadata.NODE_TYPE.propertyName()).toString() : vertex.getType())); + final DynamicType modelObjectType = jaxbContext.getDynamicType(modelObjectClass); + + for (String key : vertex.getProperties().keySet()) { + DatabaseField field = getDatabaseField(key, modelObjectType); + if (field != null) { + if (!Metadata.isProperty(key)) { + modelVertexBuilder.property(key, vertex.getProperties().get(key)); + } + } + } + return modelVertexBuilder.build(); + } catch (Exception ex) { + return vertex; + } + + } + +} diff --git a/src/main/java/org/onap/schema/RelationshipSchema.java b/src/main/java/org/onap/schema/RelationshipSchema.java new file mode 100644 index 0000000..e6a40b5 --- /dev/null +++ b/src/main/java/org/onap/schema/RelationshipSchema.java @@ -0,0 +1,108 @@ +/** + * ============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.onap.schema; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import org.codehaus.jackson.map.ObjectMapper; +import org.onap.crud.exception.CrudException; + +import java.io.IOException; +import java.util.*; +import java.util.stream.Collectors; +import javax.ws.rs.core.Response.Status; + + +public class RelationshipSchema { + private static final Gson gson = new GsonBuilder().create(); + + public static final String SCHEMA_SOURCE_NODE_TYPE = "from"; + public static final String SCHEMA_TARGET_NODE_TYPE = "to"; + public static final String SCHEMA_RELATIONSHIP_TYPE = "label"; + public static final String SCHEMA_RULES_ARRAY = "rules"; + + + private Map>> relations = new HashMap<>(); + /** + * Hashmap of valid relationship types along with properties. + */ + private Map>> relationTypes = new HashMap<>(); + + + public RelationshipSchema(List jsonStrings) throws CrudException, IOException { + String edgeRules = jsonStrings.get(0); + String props = jsonStrings.get(1); + + HashMap>> rules = new ObjectMapper().readValue(edgeRules, HashMap.class); + HashMap properties = new ObjectMapper().readValue(props, HashMap.class); + Map> edgeProps = properties.entrySet().stream().collect(Collectors.toMap(p -> p.getKey(), p -> { + try { + return resolveClass(p.getValue()); + } catch (CrudException | ClassNotFoundException e) { + e.printStackTrace(); + } + return null; + })); + + rules.get(SCHEMA_RULES_ARRAY).forEach(l -> { + relationTypes.put(l.get(SCHEMA_RELATIONSHIP_TYPE), edgeProps); + relations.put(buildRelation(l.get(SCHEMA_SOURCE_NODE_TYPE), l.get(SCHEMA_TARGET_NODE_TYPE), l.get(SCHEMA_RELATIONSHIP_TYPE)), edgeProps); + }); + } + + + + public Map> lookupRelation(String key) { + return this.relations.get(key); + } + + public Map> lookupRelationType(String type) { + return this.relationTypes.get(type); + } + + public boolean isValidType(String type) { + return relationTypes.containsKey(type); + } + + + private String buildRelation(String source, String target, String relation){ + return source + ":" + target + ":" + relation; + } + + private Class resolveClass(String type) throws CrudException, ClassNotFoundException { + Class clazz = Class.forName(type); + validateClassTypes(clazz); + return clazz; + } + + private void validateClassTypes(Class clazz) throws CrudException { + if (!clazz.isAssignableFrom(Integer.class) && !clazz.isAssignableFrom(Double.class) + && !clazz.isAssignableFrom(Boolean.class) && !clazz.isAssignableFrom(String.class)) { + throw new CrudException("", Status.BAD_REQUEST); + } + } +} + + diff --git a/src/main/java/org/onap/schema/RelationshipSchemaLoader.java b/src/main/java/org/onap/schema/RelationshipSchemaLoader.java new file mode 100644 index 0000000..48727a0 --- /dev/null +++ b/src/main/java/org/onap/schema/RelationshipSchemaLoader.java @@ -0,0 +1,263 @@ +/** + * ============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.onap.schema; + +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.Date; +import java.util.List; +import java.util.Map; +import java.util.SortedSet; +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.onap.aai.cl.eelf.LoggerFactory; +import org.onap.crud.exception.CrudException; +import org.onap.crud.logging.CrudServiceMsgs; +import org.onap.crud.util.CrudServiceConstants; +import org.onap.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 versionContextMap = new ConcurrentHashMap<>(); + private static SortedSet versions = new TreeSet(); + private static Map timers = new ConcurrentHashMap(); + final static String edgePropsFiles = "edge_properties_"; + final static String fileExt = ".json"; + final static Pattern rulesFilePattern = Pattern.compile("DbEdgeRules(.*)" + fileExt); + final static Pattern propsFilePattern = Pattern.compile(edgePropsFiles + "(.*)" + fileExt); + final static Pattern versionPattern = Pattern.compile(".*(v\\d+)" + fileExt); + + private static org.onap.aai.cl.api.Logger logger = LoggerFactory.getInstance() + .getLogger(RelationshipSchemaLoader.class.getName()); + + public synchronized static void loadModels() throws CrudException { + load(rulesFilePattern, propsFilePattern); + } + + public synchronized static void loadModels(String version) throws CrudException { + String pattern = String.format(".*(%s)" + fileExt, version); + load(Pattern.compile(pattern), Pattern.compile(edgePropsFiles + version + fileExt)); + } + + public static RelationshipSchema getSchemaForVersion(String version) throws CrudException { + if (versionContextMap == null || versionContextMap.isEmpty()) { + loadModels(); + } else if (!versionContextMap.containsKey(version)) { + try { + loadModels(version); + } catch (Exception e) { + throw new CrudException("", Status.NOT_FOUND); + } + } + RelationshipSchema schema = versionContextMap.get(version); + if (schema == null) { + throw new CrudException("", Status.NOT_FOUND); + } else + return schema; + } + + public static String getLatestSchemaVersion() throws CrudException { + return "v" + versions.last(); + } + + public static Map getVersionContextMap() { + return versionContextMap; + } + + public static void setVersionContextMap(Map versionContextMap) { + RelationshipSchemaLoader.versionContextMap = versionContextMap; + } + + public static void resetVersionContextMap() { + RelationshipSchemaLoader.versionContextMap = new ConcurrentHashMap<>(); + } + + private static void load(Pattern rulesPattern, Pattern edgePropsPattern) throws CrudException { + ClassLoader cl = RelationshipSchemaLoader.class.getClassLoader(); + ResourcePatternResolver rulesResolver = new PathMatchingResourcePatternResolver(cl); + List rulesFiles; + String rulesDir = CrudServiceConstants.CRD_HOME_MODEL; + try { + + // getResources method returns objects of type "Resource" + // 1. We are getting all the objects from the classpath which has + // "DbEdgeRules" in the name. + // 2. We run them through a filter and return only the objects which match + // the supplied pattern "p" + // 3. We then collect the objects in a list. At this point we have a list + // of the kind of files we require. + rulesFiles = Arrays.stream(rulesResolver.getResources("classpath*:/dbedgerules/DbEdgeRules*" + fileExt)) + .filter(r -> !myMatcher(rulesPattern, r.getFilename()).isEmpty()).collect(Collectors.toList()); + + // This gets all the objects of type "File" from external directory (not + // on the classpath) + // 1. From an external directory (one not on the classpath) we get all the + // objects of type "File" + // 2. We only return the files whose names matched the supplied pattern + // "p2". + // 3. We then collect all the objects in a list and add the contents of + // this list + // to the previous collection (rulesFiles) + rulesFiles + .addAll(Arrays.stream(new File(rulesDir).listFiles((d, name) -> edgePropsPattern.matcher(name).matches())) + .collect(Collectors.toList())); + + if (rulesFiles.isEmpty()) { + logger.error(CrudServiceMsgs.INVALID_OXM_DIR, rulesDir); + throw new FileNotFoundException("DbEdgeRules and edge_properties files were not found."); + } + + // Sort and then group the files with their versions, convert them to the + // schema, and add them to versionContextMap + // 1. Sort the files. We need the DbEdgeRules files to be before the + // edgeProperties files. + // 2. Group the files with their versions. ie. v11 -> + // ["DbEdgeRule_v11.json", "edgeProperties_v11.json"]. + // The "group method" returns a HashMap whose key is the version and the + // value is a list of objects. + // 3. Go through each version and map the files into one schema using the + // "jsonFilesLoader" method. + // Also update the "versionContextMap" with the version and it's schema. + rulesFiles.stream().sorted(Comparator.comparing(RelationshipSchemaLoader::filename)) + .collect(Collectors.groupingBy(f -> myMatcher(versionPattern, filename(f)))) + .forEach((version, resourceAndFile) -> { + if (resourceAndFile.size() == 2) { + versionContextMap.put(version, jsonFilesLoader(version, resourceAndFile)); + } else { + String filenames = resourceAndFile.stream().map(f -> filename(f)).collect(Collectors.toList()).toString(); + 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); + throw new CrudException("DbEdgeRules or edge_properties files were not found.", new FileNotFoundException()); + } + } + + private static String filename(Object k) throws ClassCastException { + if (k instanceof UrlResource) { + return ((UrlResource) k).getFilename(); + } else if (k instanceof File) { + return ((File) k).getName(); + } else { + throw new ClassCastException(); + } + } + + private static RelationshipSchema jsonFilesLoader(String version, List files) { + List fileContents = new ArrayList<>(); + RelationshipSchema rsSchema = null; + if (files.size() == 2) { + for (Object file : files) { + fileContents.add(jsonToRelationSchema(version, file)); + versions.add(Integer.parseInt(version.substring(1))); + } + + try { + rsSchema = new RelationshipSchema(fileContents); + } catch (CrudException | IOException e) { + e.printStackTrace(); + logger.error(CrudServiceMsgs.INVALID_OXM_FILE, + files.stream().map(f -> filename(f)).collect(Collectors.toList()).toString(), e.getMessage()); + } + return rsSchema; + } + return rsSchema; + } + + private synchronized static void updateVersionContext(String version, RelationshipSchema rs) { + versionContextMap.put(version, rs); + } + + private synchronized static String jsonToRelationSchema(String version, Object file) { + InputStream inputStream = null; + String content = null; + + try { + if (file instanceof UrlResource) { + inputStream = ((UrlResource) file).getInputStream(); + } else { + inputStream = new FileInputStream((File) file); + addtimer(version, file); + } + content = IOUtils.toString(inputStream, "UTF-8"); + } catch (IOException e) { + e.printStackTrace(); + } + return content; + } + + private static void addtimer(String version, Object file) { + TimerTask task = null; + task = new FileWatcher((File) file) { + protected void onChange(File file) { + // here we implement the onChange + logger.info(CrudServiceMsgs.OXM_FILE_CHANGED, file.getName()); + + try { + // Cannot use the file object here because we also have to get the + // edge properties associated with that version. + // The properties are stored in a different file. + RelationshipSchemaLoader.loadModels(version); + } catch (Exception e) { + e.printStackTrace(); + } + } + }; + + if (!timers.containsKey(version)) { + Timer timer = new Timer("db_edge_rules_" + version); + timer.schedule(task, new Date(), 10000); + timers.put(version, timer); + + } + } + + private static String myMatcher(Pattern p, String s) { + Matcher m = p.matcher(s); + return m.matches() ? m.group(1) : ""; + } +} diff --git a/src/main/java/org/onap/schema/RelationshipSchemaValidator.java b/src/main/java/org/onap/schema/RelationshipSchemaValidator.java new file mode 100644 index 0000000..53048be --- /dev/null +++ b/src/main/java/org/onap/schema/RelationshipSchemaValidator.java @@ -0,0 +1,352 @@ +/** + * ============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.onap.schema; + +import com.google.gson.JsonElement; +import com.google.gson.JsonNull; + +import org.onap.crud.entity.Edge; +import org.onap.crud.entity.Vertex; +import org.onap.crud.exception.CrudException; +import org.onap.crud.service.EdgePayload; +import org.onap.crud.util.CrudServiceUtil; +import org.radeox.util.logging.Logger; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.ws.rs.core.Response.Status; + +public class RelationshipSchemaValidator { + + public static final String SOURCE_NODE = "source"; + public static final String TARGET_NODE = "target"; + + final static Pattern urlPattern = Pattern.compile("services/inventory/(.*)/(.*)/(.*)"); + + public static Map resolveCollectionfilter(String version, String type, + Map filter) + throws CrudException { + + RelationshipSchema schema = RelationshipSchemaLoader.getSchemaForVersion(version); + if (schema == null) { + throw new CrudException("", Status.NOT_FOUND); + } + + Map> props = schema.lookupRelationType(type); + Map result = new HashMap(); + + for (String key : filter.keySet()) { + + if (props.containsKey(key)) { + try { + Object value = CrudServiceUtil.validateFieldType(filter.get(key), props.get(key)); + result.put(key, value); + } catch (Exception ex) { + // Skip any exceptions thrown while validating the filter + // key value + continue; + } + } + } + + return result; + + } + + public static void validateType(String version, String type) throws CrudException { + + RelationshipSchema schema = RelationshipSchemaLoader.getSchemaForVersion(version); + if (!schema.isValidType(type)) { + throw new CrudException("Invalid " + RelationshipSchema.SCHEMA_RELATIONSHIP_TYPE + + ": " + type, + Status.BAD_REQUEST); + } + + } + + public static Edge validateIncomingAddPayload(String version, String type, Vertex sourceNode, + Vertex targetNode, JsonElement properties) + throws CrudException { + EdgePayload payload = new EdgePayload(); + payload.setSource("services/inventory/" + version + "/" + sourceNode.getType() + + "/" + sourceNode.getId().get()); + payload.setTarget("services/inventory/" + version + "/" + targetNode.getType() + + "/" + targetNode.getId().get()); + payload.setType(type); + payload.setProperties(properties); + return validateIncomingAddPayload(version, type, payload); + } + + public static Edge validateIncomingAddPayload(String version, String type, EdgePayload payload) + throws CrudException { + RelationshipSchema schema = RelationshipSchemaLoader.getSchemaForVersion(version); + + try { + + if (payload.getSource() == null || payload.getTarget() == null) { + throw new CrudException("Source/Target not specified", Status.BAD_REQUEST); + } + + Matcher sourceMatcher = urlPattern.matcher(payload.getSource()); + Matcher targetMatcher = urlPattern.matcher(payload.getTarget()); + + if (!sourceMatcher.matches() || !targetMatcher.matches()) { + throw new CrudException("Invalid Source/Target Urls", Status.BAD_REQUEST); + } + + // create key based on source:target:relationshipType + String sourceNodeType = sourceMatcher.group(2); + String targetNodeType = targetMatcher.group(2); + + String sourceNodeId = sourceMatcher.group(3); + String targetNodeId = targetMatcher.group(3); + + String key = sourceNodeType + ":" + targetNodeType + ":" + type; + + // find the validate the key from the schema + Map> schemaObject = schema.lookupRelation(key); + + if (schemaObject == null) { + throw new CrudException("Invalid source/target/relationship type: " + key, + Status.BAD_REQUEST); + } + + Edge.Builder modelEdgeBuilder = new Edge.Builder(type); + + modelEdgeBuilder.source(new Vertex.Builder(sourceNodeType).id(sourceNodeId).build()); + modelEdgeBuilder.target(new Vertex.Builder(targetNodeType).id(targetNodeId).build()); + + // validate it properties + validateEdgeProps(modelEdgeBuilder, payload.getProperties(), schemaObject); + + return modelEdgeBuilder.build(); + } catch (Exception ex) { + + throw new CrudException(ex.getMessage(), Status.BAD_REQUEST); + } + + } + + public static Edge validateIncomingPatchPayload(Edge edge, String version, EdgePayload payload) + throws CrudException { + RelationshipSchema schema = RelationshipSchemaLoader.getSchemaForVersion(version); + + try { + if (payload.getSource() != null) { + Matcher sourceMatcher = urlPattern.matcher(payload.getSource()); + + if (!sourceMatcher.matches()) { + throw new CrudException("Invalid Target Urls", Status.BAD_REQUEST); + } + String sourceNodeId = sourceMatcher.group(3); + if (!sourceNodeId.equals(edge.getSource().getId().get())) { + throw new CrudException("Source can't be updated", Status.BAD_REQUEST); + } + } + + if (payload.getTarget() != null) { + Matcher targetMatcher = urlPattern.matcher(payload.getTarget()); + + if (!targetMatcher.matches()) { + throw new CrudException("Invalid Target Urls", Status.BAD_REQUEST); + } + String sourceNodeId = targetMatcher.group(3); + if (!sourceNodeId.equals(edge.getTarget().getId().get())) { + throw new CrudException("Target can't be updated", Status.BAD_REQUEST); + } + } + // create key based on source:target:relationshipType + + String key = edge.getSource().getType() + ":" + edge.getTarget().getType() + + ":" + edge.getType(); + + // find the validate the key from the schema + Map> schemaObject = schema.lookupRelation(key); + + if (schemaObject == null) { + Logger.warn("key :" + key + + " not found in relationship schema . Skipping the schema validation"); + return edge; + } + + Set> entries = payload.getProperties() + .getAsJsonObject().entrySet(); + + for (Map.Entry entry : entries) { + + if (!schemaObject.containsKey(entry.getKey())) { + throw new CrudException("Invalid property: " + entry.getKey(), Status.BAD_REQUEST); + } else if (entry.getValue() instanceof JsonNull && edge.getProperties() + .containsKey(entry.getKey())) { + edge.getProperties().remove(entry.getKey()); + } else if (!(entry.getValue() instanceof JsonNull)) { + Object value = CrudServiceUtil.validateFieldType(entry.getValue().getAsString(), + schemaObject.get(entry.getKey())); + edge.getProperties().put(entry.getKey(), value); + } + + } + + return edge; + + } catch (Exception ex) { + + throw new CrudException(ex.getMessage(), Status.BAD_REQUEST); + } + } + + public static Edge validateIncomingUpdatePayload(Edge edge, String version, Vertex sourceNode, + Vertex targetNode, JsonElement properties) + throws CrudException { + EdgePayload payload = new EdgePayload(); + payload.setSource("services/inventory/" + version + "/" + sourceNode.getType() + + "/" + sourceNode.getId().get()); + payload.setTarget("services/inventory/" + version + "/" + targetNode.getType() + + "/" + targetNode.getId().get()); + payload.setType(edge.getType()); + payload.setProperties(properties); + return validateIncomingUpdatePayload(edge, version, payload); + } + + public static Edge validateIncomingUpdatePayload(Edge edge, String version, EdgePayload payload) + throws CrudException { + RelationshipSchema schema = RelationshipSchemaLoader.getSchemaForVersion(version); + + try { + + if (payload.getSource() != null) { + Matcher sourceMatcher = urlPattern.matcher(payload.getSource()); + + if (!sourceMatcher.matches()) { + throw new CrudException("Invalid Target Urls", Status.BAD_REQUEST); + } + String sourceNodeId = sourceMatcher.group(3); + if (!sourceNodeId.equals(edge.getSource().getId().get())) { + throw new CrudException("Source can't be updated", Status.BAD_REQUEST); + } + } + + if (payload.getTarget() != null) { + Matcher targetMatcher = urlPattern.matcher(payload.getTarget()); + + if (!targetMatcher.matches()) { + throw new CrudException("Invalid Target Urls", Status.BAD_REQUEST); + } + String sourceNodeId = targetMatcher.group(3); + if (!sourceNodeId.equals(edge.getTarget().getId().get())) { + throw new CrudException("Target can't be updated", Status.BAD_REQUEST); + } + } + // create key based on source:target:relationshipType + + String key = edge.getSource().getType() + ":" + edge.getTarget().getType() + + ":" + edge.getType(); + + // find the validate the key from the schema + Map> schemaObject = schema.lookupRelation(key); + + if (schemaObject == null) { + Logger.warn("key :" + key + + " not found in relationship schema . Skipping the schema validation"); + return edge; + } + + Edge.Builder updatedEdgeBuilder = new Edge.Builder(edge.getType()).id(edge.getId().get()); + + updatedEdgeBuilder + .source(new Vertex.Builder(edge.getSource().getType()).id(edge.getSource().getId() + .get()).build()); + updatedEdgeBuilder + .target(new Vertex.Builder(edge.getTarget().getType()).id(edge.getTarget().getId() + .get()).build()); + + validateEdgeProps(updatedEdgeBuilder, payload.getProperties(), schemaObject); + + return updatedEdgeBuilder.build(); + } catch (Exception ex) { + + throw new CrudException(ex.getMessage(), Status.BAD_REQUEST); + } + } + + + private static void validateEdgeProps(Edge.Builder builder, JsonElement props, + Map> schemaObject) + throws CrudException { + Set> entries = props.getAsJsonObject().entrySet(); + + for (Map.Entry entry : entries) { + + if (!schemaObject.containsKey(entry.getKey())) { + throw new CrudException("Invalid property: " + entry.getKey(), Status.BAD_REQUEST); + } else { + Object value = CrudServiceUtil.validateFieldType(entry.getValue().getAsString(), + schemaObject.get(entry.getKey())); + builder.property(entry.getKey(), value); + } + + } + + } + + public static Edge validateOutgoingPayload(String version, Edge edge) throws CrudException { + + Edge.Builder modelEdgeBuilder = new Edge.Builder(edge.getType()).id(edge.getId() + .get()).source(edge.getSource()) + .target(edge.getTarget()); + + RelationshipSchema schema = RelationshipSchemaLoader.getSchemaForVersion(version); + + String key = edge.getSource().getType() + ":" + edge.getTarget().getType() + + ":" + edge.getType(); + Map> schemaObject = schema.lookupRelation(key); + + if (schemaObject == null || schemaObject.isEmpty()) { + return edge; + } + + for (String prop : edge.getProperties().keySet()) { + if (schemaObject.containsKey(prop)) { + modelEdgeBuilder.property(prop, edge.getProperties().get(prop)); + } + + } + return modelEdgeBuilder.build(); + } + + + public static String vertexTypeFromUri(String uri) throws CrudException { + + Matcher matcher = urlPattern.matcher(uri); + + if (!matcher.matches()) { + throw new CrudException("Invalid Source/Target Urls", Status.BAD_REQUEST); + } + + return matcher.group(2); + } +} diff --git a/src/main/java/org/openecomp/crud/dao/GraphDao.java b/src/main/java/org/openecomp/crud/dao/GraphDao.java deleted file mode 100644 index 7e8c043..0000000 --- a/src/main/java/org/openecomp/crud/dao/GraphDao.java +++ /dev/null @@ -1,183 +0,0 @@ -/** - * ============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; - -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; - -public interface GraphDao { - - public Vertex getVertex(String id) throws CrudException; - - public Vertex getVertex(String id, String type) throws CrudException; - - /** - * Retrieve all of the edges which are incident to the vertex with the - * specified identifier. - * - * @param id - * - The unique identifier of the vertex to retrieve the edges for. - * @return - A collection of edges. - * @throws CrudException - */ - public List getVertexEdges(String id) throws CrudException; - - /** - * Retrieve a collection of {@link Vertex} objects which match the supplied - * type label and filter properties. - * - * @param type - * - The vertex type that we want to retrieve. - * @param filter - * - The parameters to filter our results by. - * @return - A collection of vertices. - * @throws CrudException - */ - public List getVertices(String type, Map filter) throws CrudException; - - /** - * Retrieve an {@link Edge} from the graph database by specifying its unique - * identifier. - * - * @param id - * - The unique identifier for the Edge to be retrieved. - * @return - The Edge corresponding to the specified identifier. - * @throws CrudException - */ - public Edge getEdge(String id, String type) throws CrudException; - - /** - * Retrieve a collection of {@link Edge} objects with a given type and which - * match a set of supplied filter parameters. - * - * @param type - * - The type of edges that we are interested in. - * @param filter - * - The parameters that we want to filter our edges by. - * @return - A collection of edges which match the supplied filter parameters. - * @throws CrudException - */ - public List getEdges(String type, Map filter) throws CrudException; - - /** - * Insert a new {@link Vertex} into the graph data store. - * - * @param type - * - The type label to assign to the vertex. - * @param properties - * - The properties to associated with this vertex. - * @return - The {@link Vertex} object that was created. - * @throws CrudException - */ - public Vertex addVertex(String type, Map properties) throws CrudException; - - /** - * Updates an existing {@link Vertex}. - * - * @param id - * - The unique identifier of the vertex to be updated. - * @param properties - * - The properties to associate with the vertex. - * @return - The udpated vertex. - * @throws CrudException - */ - public Vertex updateVertex(String id, String type, Map properties) throws CrudException; - - /** - * Removes the specified vertex from the graph data base. - * - *

    - * NOTE: The vertex MUST contain NO incident edges before it can be deleted. - * - * @param id - * - The unique identifier of the vertex to be deleted. - * @throws CrudException - */ - public void deleteVertex(String id, String type) throws CrudException; - - /** - * Adds an edge to the graph database. - * - * @param type - * - The 'type' label to apply to the edge. - * @param source - * - The source vertex for this edge. - * @param target - * - The target vertex for this edge. - * @param properties - * - The properties map to associate with this edge. - * @return - The {@link Edge} object that was created. - * @throws CrudException - */ - public Edge addEdge(String type, Vertex source, Vertex target, Map properties) throws CrudException; - - /** - * Updates an existing {@link Edge}. - * - * @param id - * - The unique identifier of the edge to be updated. - * @param properties - * - The properties to associate with the edge. - * @return - The update edge. - * @throws CrudException - */ - public Edge updateEdge(Edge edge) throws CrudException; - - /** - * Remove the specified edge from the graph data base. - * - * @param id - * - The unique identifier of the edge to be deleted. - * @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 properties, String txId) throws CrudException; - - public Edge addEdge(String type, Vertex source, Vertex target, Map properties, String txId) - throws CrudException; - - public Vertex updateVertex(String id, String type, Map 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 deleted file mode 100644 index 93c3cdd..0000000 --- a/src/main/java/org/openecomp/crud/dao/champ/ChampDao.java +++ /dev/null @@ -1,883 +0,0 @@ -/** - * ============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.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; -import org.openecomp.aai.champcore.exceptions.ChampSchemaViolationException; -import org.openecomp.aai.champcore.exceptions.ChampTransactionException; -import org.openecomp.aai.champcore.exceptions.ChampUnmarshallingException; -import org.openecomp.aai.champcore.model.ChampObject; -import org.openecomp.aai.champcore.model.ChampRelationship; -import org.openecomp.aai.champcore.model.fluent.object.ObjectBuildOrPropertiesStep; -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.logging.CrudServiceMsgs; - -/** - * 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"; - - private static Map transactions = new ConcurrentHashMap(); - 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 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 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 getVertexEdges(String id) throws CrudException { - - if (logger.isDebugEnabled()) { - logger.debug("get Edges incident to vertex with id: " + id + " from graph"); - } - - try { - long idAsLong = Long.parseLong(id); // GDF - what to do about id??? - - // Request the vertex from the graph db. - Optional retrievedVertex = champApi.retrieveObject(idAsLong); - - // Did we find it? - if (retrievedVertex.isPresent()) { - - // Query the Champ library for the edges which are incident to the - // specified - // vertex. - Stream relationships = champApi.retrieveRelationships(retrievedVertex.get()); - - // Build an edge list from the result stream. - List edges = new ArrayList(); - 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 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 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 getVertices(String type, Map 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 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 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 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 properties) throws CrudException { - - // For now, assume source and target are straight ids... - try { - - Optional sourceObject = champApi.retrieveObject(Long.parseLong(source.getId().get())); - if (!sourceObject.isPresent() || !sourceObject.get().getType().equals(source.getType())) { - throw new CrudException( - "Error creating edge - source vertex with id " + source + " does not exist in graph data base", - javax.ws.rs.core.Response.Status.BAD_REQUEST); - } - - Optional targetObject = champApi.retrieveObject(Long.parseLong(target.getId().get())); - if (!targetObject.isPresent() || !targetObject.get().getType().equals(target.getType())) { - throw new CrudException( - "Error creating edge - target vertex with id " + target + " does not exist in graph data base", - javax.ws.rs.core.Response.Status.BAD_REQUEST); - } - - // 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 getEdges(String type, Map filter) throws CrudException { - - filter.put(ChampRelationship.ReservedPropertyKeys.CHAMP_RELATIONSHIP_TYPE.toString(), type); - - Stream retrievedRelationships; - try { - retrievedRelationships = champApi.queryRelationships(filter); - - } catch (ChampTransactionException e) { - throw new CrudException("Transaction error occured", javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); - } - - // Process the result stream from the Champ library into an Edge list, - // keeping only - // edges of the specified type. - List edges = retrievedRelationships.map(r -> edgeFromChampRelationship(r)).collect(Collectors.toList()); - - return edges; - } - - @Override - public Edge updateEdge(Edge edge) throws CrudException { - - if (logger.isDebugEnabled()) { - logger.debug( - "Update edge with id: " + edge.getId() + " with properties: " + propertiesMapToString(edge.getProperties())); - } - - 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 retrievedVertex = champApi.retrieveObject(Long.parseLong(id)); - - // Did we find it? - if (!retrievedVertex.isPresent() || !retrievedVertex.get().getType().equals(type)) { - throw new CrudException("Failed to delete vertex with id: " + id + " - vertex does not exist.", - javax.ws.rs.core.Response.Status.NOT_FOUND); - } - - // Now, verify that there are no edges incident to the vertex (they must - // be deleted - // first if so). - Stream relationships = champApi.retrieveRelationships(retrievedVertex.get()); - - if (relationships.count() > 0) { - throw new CrudException("Attempt to delete vertex with id " + id + " which has incident edges.", - javax.ws.rs.core.Response.Status.BAD_REQUEST); - } - - // Finally, we can attempt to delete our vertex. - champApi.deleteObject(Long.parseLong(id)); - - } catch (NumberFormatException | ChampUnmarshallingException | ChampObjectNotExistsException - | ChampTransactionException e) { - - throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); - } - } - - @Override - public void deleteEdge(String id, String type) throws CrudException { - - try { - - // First, retrieve the edge that we want to delete. - Optional relationshipToDelete = champApi.retrieveRelationship(getRelKey(id)); - - // Did we find it? - if (!relationshipToDelete.isPresent() || !relationshipToDelete.get().getType().equals(type)) { - throw new CrudException("Failed to delete edge with id: " + id + " - edge does not exist", - javax.ws.rs.core.Response.Status.NOT_FOUND); - } - - // Now we can delete the edge. - champApi.deleteRelationship(relationshipToDelete.get()); - - } catch (ChampRelationshipNotExistsException | NumberFormatException | ChampUnmarshallingException - | ChampTransactionException e) { - - throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); - } - } - - /** - * This helper method generates a string representation of a properties map - * for logging purposes. - * - * @param properties - * - The properties map to be converted. - * @return - The log statement friendly conversion of the properties map. - */ - private String propertiesMapToString(Map properties) { - - 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 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 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 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 properties, String txId) - throws CrudException { - // For now, assume source and target are straight ids... - try { - - Optional sourceObject = champApi.retrieveObject(Long.parseLong(source.getId().get()), - Optional.of(getTransaction(txId))); - if (!sourceObject.isPresent() || !sourceObject.get().getType().equals(source.getType())) { - throw new CrudException( - "Error creating edge - source vertex with id " + source + " does not exist in graph data base", - javax.ws.rs.core.Response.Status.BAD_REQUEST); - } - - Optional targetObject = champApi.retrieveObject(Long.parseLong(target.getId().get()), - Optional.of(getTransaction(txId))); - if (!targetObject.isPresent() || !targetObject.get().getType().equals(target.getType())) { - throw new CrudException( - "Error creating edge - target vertex with id " + target + " does not exist in graph data base", - javax.ws.rs.core.Response.Status.BAD_REQUEST); - } - - // Now, create the ChampRelationship object for our edge and store it in - // the graph database. - return edgeFromChampRelationship(champApi.storeRelationship( - new ChampRelationship.Builder(sourceObject.get(), targetObject.get(), type).properties(properties).build(), - Optional.of(getTransaction(txId)))); - - } catch (ChampMarshallingException | ChampObjectNotExistsException | ChampSchemaViolationException - | ChampTransactionException | ChampRelationshipNotExistsException | ChampUnmarshallingException e) { - - 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 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 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 relationships = champApi.retrieveRelationships(retrievedVertex.get(), - Optional.of(getTransaction(txId))); - - if (relationships.count() > 0) { - throw new CrudException("Attempt to delete vertex with id " + id + " which has incident edges.", - javax.ws.rs.core.Response.Status.BAD_REQUEST); - } - - // Finally, we can attempt to delete our vertex. - champApi.deleteObject(Long.parseLong(id), Optional.of(getTransaction(txId))); - - } catch (NumberFormatException | ChampUnmarshallingException | ChampObjectNotExistsException - | ChampTransactionException e) { - - throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); - } - - } - - @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())); - } - - try { - // Now, build the updated version of the Champ Relationship... - ChampRelationship updateRelationship = new ChampRelationship.Builder( - buildChampObject(edge.getSource().getId().get(), edge.getSource().getType(), - edge.getSource().getProperties()), - buildChampObject(edge.getTarget().getId().get(), edge.getTarget().getType(), - edge.getTarget().getProperties()), - edge.getType()).key(getRelKey(edge.getId().get())).properties(edge.getProperties()).build(); - // ...and send it to the Champ library. - return edgeFromChampRelationship( - champApi.replaceRelationship(updateRelationship, Optional.of(getTransaction(txId)))); - - } catch (ChampRelationshipNotExistsException ex) { - throw new CrudException("Not Found", javax.ws.rs.core.Response.Status.NOT_FOUND); - } catch (NumberFormatException | ChampUnmarshallingException | ChampMarshallingException - | ChampSchemaViolationException | ChampTransactionException ex) { - - throw new CrudException(ex.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); - } - } - - @Override - public void deleteEdge(String id, String type, String txId) throws CrudException { - try { - - // First, retrieve the edge that we want to delete. - Optional relationshipToDelete = champApi.retrieveRelationship(getRelKey(id), - Optional.of(getTransaction(txId))); - - // 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(), Optional.of(getTransaction(txId))); - - } catch (ChampRelationshipNotExistsException | NumberFormatException | ChampUnmarshallingException - | ChampTransactionException e) { - - throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); - } - - } - - @Override - public Edge getEdge(String id, String type, String txId) throws CrudException { - if (logger.isDebugEnabled()) { - logger.debug("Get edge with id: " + id); - } - - try { - - // Request the edge from the graph db. - Optional relationship = champApi.retrieveRelationship(getRelKey(id), - Optional.of(getTransaction(txId))); - - // 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); - } - } - -} diff --git a/src/main/java/org/openecomp/crud/dao/champion/ChampionDao.java b/src/main/java/org/openecomp/crud/dao/champion/ChampionDao.java deleted file mode 100644 index 48fa6cb..0000000 --- a/src/main/java/org/openecomp/crud/dao/champion/ChampionDao.java +++ /dev/null @@ -1,623 +0,0 @@ -/** - * ============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> 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> 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 getVertexEdges(String id) throws CrudException { - String url = baseUrl + "objects/relationships/" + id; - Map> 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>() { - }.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 getVertices(String type, Map 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> 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>() { - }.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> 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 getEdges(String type, Map filter) throws CrudException { - String url = baseUrl + "relationships/filter" + "?" - + URLEncodedUtils.format(convertToNameValuePair(filter), Charset.defaultCharset()); - - Map> 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>() { - }.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 properties) throws CrudException { - String url = baseUrl + "objects"; - Map> 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 properties) throws CrudException { - String url = baseUrl + "objects/" + id; - Map> 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> 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 properties) throws CrudException { - String url = baseUrl + "relationships"; - Map> 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> 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> 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> 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> 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> 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> 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 properties, String txId) throws CrudException { - String url = baseUrl + "objects?transactionId=" + txId; - Map> 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 properties, String txId) - throws CrudException { - String url = baseUrl + "relationships?transactionId=" + txId; - Map> 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 properties, String txId) throws CrudException { - String url = baseUrl + "objects/" + id + "?transactionId=" + txId; - Map> 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> 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> 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> 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> 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> 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 convertToNameValuePair(Map pairs) { - List 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 deleted file mode 100644 index 5ca6c2c..0000000 --- a/src/main/java/org/openecomp/crud/dao/champion/ChampionEdgeSerializer.java +++ /dev/null @@ -1,49 +0,0 @@ -/** - * ============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 { - @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 deleted file mode 100644 index ab743d7..0000000 --- a/src/main/java/org/openecomp/crud/dao/champion/ChampionVertexSerializer.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * ============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 { - @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 deleted file mode 100644 index 4d2de24..0000000 --- a/src/main/java/org/openecomp/crud/entity/Edge.java +++ /dev/null @@ -1,140 +0,0 @@ -/** - * ============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.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().registerTypeAdapterFactory(new GsonJava8TypeAdapterFactory()) - .create(); - - @SerializedName(value = "id", alternate = { "key" }) - private final Optional id; - private final String type; - private final Map properties; - private final Vertex source; - private final Vertex target; - - private Edge(Builder builder) { - this.id = builder.id; - this.type = builder.type; - this.source = builder.source; - this.target = builder.target; - this.properties = builder.properties; - } - - public static class Builder { - private Optional id = Optional.empty(); - private final String type; - private Vertex source; - private Vertex target; - private final Map properties = new HashMap(); - - public Builder(String type) { - if (type == null) { - throw new IllegalArgumentException("Type cannot be null"); - } - - this.type = type; - } - - public Builder id(String id) { - if (id == null) { - throw new IllegalArgumentException("id cannot be null"); - } - - this.id = Optional.of(id); - return this; - } - - public Builder property(String key, Object value) { - if (key == null || value == null) { - throw new IllegalArgumentException("Property key/value cannot be null"); - } - properties.put(key, value); - return this; - } - - public Builder source(Vertex source) { - this.source = source; - return this; - } - - public Builder target(Vertex target) { - this.target = target; - return this; - } - - public Edge build() { - return new Edge(this); - } - } - - @Override - public String toString() { - return "Edge [id=" + id + ", type=" + type + ", properties=" + properties + ", source=" + source + ", target=" - + target + "]"; - } - - public String toJson() { - 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 getId() { - return id; - } - - public String getType() { - return type; - } - - public Map getProperties() { - return properties; - } - - public Vertex getSource() { - return source; - } - - public Vertex getTarget() { - return target; - } - -} diff --git a/src/main/java/org/openecomp/crud/entity/Vertex.java b/src/main/java/org/openecomp/crud/entity/Vertex.java deleted file mode 100644 index 12c274f..0000000 --- a/src/main/java/org/openecomp/crud/entity/Vertex.java +++ /dev/null @@ -1,115 +0,0 @@ -/** - * ============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.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().registerTypeAdapterFactory(new GsonJava8TypeAdapterFactory()) - .create(); - - @SerializedName(value = "id", alternate = { "key" }) - private final Optional id; - - private final String type; - private final Map properties; - - private Vertex(Builder builder) { - this.id = builder.id; - this.type = builder.type; - this.properties = builder.properties; - } - - public static class Builder { - private Optional id = Optional.empty(); - private final String type; - private final Map properties = new HashMap(); - - public Builder(String type) { - if (type == null) { - throw new IllegalArgumentException("Type cannot be null"); - } - this.type = type; - } - - public Builder id(String id) { - if (id == null) { - throw new IllegalArgumentException("id cannot be null"); - } - - this.id = Optional.of(id); - return this; - } - - public Builder property(String key, Object value) { - if (key == null || value == null) { - throw new IllegalArgumentException("Property key/value cannot be null"); - } - properties.put(key, value); - return this; - } - - public Vertex build() { - return new Vertex(this); - } - } - - public String toJson() { - 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 + "]"; - } - - public Optional getId() { - return id; - } - - public String getType() { - return type; - } - - public Map getProperties() { - return properties; - } - -} diff --git a/src/main/java/org/openecomp/crud/event/GraphEvent.java b/src/main/java/org/openecomp/crud/event/GraphEvent.java deleted file mode 100644 index 392bf2d..0000000 --- a/src/main/java/org/openecomp/crud/event/GraphEvent.java +++ /dev/null @@ -1,235 +0,0 @@ -/** - * ============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.event; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.annotations.SerializedName; - -import org.openecomp.crud.exception.CrudException; - -import javax.ws.rs.core.Response.Status; - -public class GraphEvent { - - public enum GraphEventOperation { - CREATE, UPDATE, DELETE - } - - public enum GraphEventResult { - SUCCESS, FAILURE - } - - private GraphEventOperation operation; - - @SerializedName("transaction-id") - private String transactionId; - - private long timestamp; - - private GraphEventVertex vertex; - - private GraphEventEdge edge; - - private GraphEventResult result; - - @SerializedName("error-message") - private String errorMessage; - - private Status httpErrorStatus; - - /** - * Marshaller/unmarshaller for converting to/from JSON. - */ - private static final Gson gson = new GsonBuilder().disableHtmlEscaping() - .setPrettyPrinting().create(); - - public static Builder builder(GraphEventOperation operation) { - return new Builder(operation); - } - - public GraphEventOperation getOperation() { - return operation; - } - - public String getTransactionId() { - return transactionId; - } - - public long getTimestamp() { - return timestamp; - } - - public GraphEventVertex getVertex() { - return vertex; - } - - public GraphEventEdge getEdge() { - return edge; - } - - public GraphEventResult getResult() { - return result; - } - - public String getErrorMessage() { - return errorMessage; - } - - public void setResult(GraphEventResult result) { - this.result = result; - } - - - public Status getHttpErrorStatus() { - return httpErrorStatus; - } - - public void setHttpErrorStatus(Status httpErrorStatus) { - this.httpErrorStatus = httpErrorStatus; - } - - public void setTimestamp(long timestamp) { - this.timestamp = timestamp; - } - - public void setErrorMessage(String errorMessage) { - this.errorMessage = errorMessage; - } - - public void setVertex(GraphEventVertex vertex) { - this.vertex = vertex; - } - - public void setEdge(GraphEventEdge edge) { - this.edge = edge; - } - - /** - * Unmarshalls this Vertex object into a JSON string. - * - * @return - A JSON format string representation of this Vertex. - */ - public String toJson() { - return gson.toJson(this); - } - - /** - * Marshalls the provided JSON string into a Vertex object. - * - * @param json - The JSON string to produce the Vertex from. - * @return - A Vertex object. - * @throws SpikeException - */ - public static GraphEvent fromJson(String json) throws CrudException { - - try { - - // Make sure that we were actually provided a non-empty string - // before we - // go any further. - if (json == null || json.isEmpty()) { - throw new CrudException("Empty or null JSON string.", Status.BAD_REQUEST); - } - - // Marshall the string into a Vertex object. - return gson.fromJson(json, GraphEvent.class); - - } catch (Exception ex) { - throw new CrudException("Unable to parse JSON string: ", Status.BAD_REQUEST); - } - } - - @Override - public String toString() { - - return toJson(); - } - - public String getObjectKey() { - if (this.getVertex() != null) { - return this.getVertex().getId(); - } else if (this.getEdge() != null) { - return this.getEdge().getId(); - } - - return null; - - } - - public String getObjectType() { - if (this.getVertex() != null) { - return "vertex->" + this.getVertex().getType(); - } else if (this.getEdge() != null) { - return "edge->" + this.getEdge().getType(); - } - - return null; - - } - - public static class Builder { - - GraphEvent event = null; - - public Builder(GraphEventOperation operation) { - event = new GraphEvent(); - event.operation = operation; - } - - public Builder vertex(GraphEventVertex vertex) { - event.vertex = vertex; - return this; - } - - public Builder edge(GraphEventEdge edge) { - event.edge = edge; - return this; - } - - public Builder result(GraphEventResult result) { - event.result = result; - return this; - } - - public Builder errorMessage(String errorMessage) { - event.errorMessage = errorMessage; - return this; - } - - public Builder httpErrorStatus(Status httpErrorStatus) { - event.httpErrorStatus = httpErrorStatus; - return this; - } - - public GraphEvent build() { - - event.timestamp = System.currentTimeMillis(); - event.transactionId = java.util.UUID.randomUUID().toString(); - - return event; - } - } - -} diff --git a/src/main/java/org/openecomp/crud/event/GraphEventEdge.java b/src/main/java/org/openecomp/crud/event/GraphEventEdge.java deleted file mode 100644 index aaf9b72..0000000 --- a/src/main/java/org/openecomp/crud/event/GraphEventEdge.java +++ /dev/null @@ -1,212 +0,0 @@ -/** - * ============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.event; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.annotations.SerializedName; -import com.google.gson.reflect.TypeToken; - -import org.openecomp.crud.entity.Edge; -import org.openecomp.crud.entity.Vertex; -import org.openecomp.crud.exception.CrudException; - -import java.util.Map; -import javax.ws.rs.core.Response.Status; - -/** - * This class provides a generic representation of an Edge as provided by the - * graph data store. - */ -public class GraphEventEdge { - - /** - * The unique identifier used to identify this edge in the graph data store. - */ - @SerializedName("key") - private String id; - - @SerializedName("schema-version") - private String modelVersion; - - /** - * Type label assigned to this vertex. - */ - private String type; - - /** - * Source vertex for our edge. - */ - private GraphEventVertex source; - - /** - * Target vertex for our edge. - */ - private GraphEventVertex target; - - /** - * Map of all of the properties assigned to this vertex. - */ - private JsonElement properties; - - /** - * Marshaller/unmarshaller for converting to/from JSON. - */ - private static final Gson gson = new GsonBuilder().disableHtmlEscaping().create(); - - public GraphEventEdge(String id, String modelVersion, String type, GraphEventVertex source, - GraphEventVertex target, JsonElement properties) { - this.id = id; - this.modelVersion = modelVersion; - this.type = type; - this.source = source; - this.target = target; - this.properties = properties; - } - - public GraphEventEdge() { - - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public GraphEventVertex getSource() { - return source; - } - - public void setSource(GraphEventVertex source) { - this.source = source; - } - - public GraphEventVertex getTarget() { - return target; - } - - public void setTarget(GraphEventVertex target) { - this.target = target; - } - - public JsonElement getProperties() { - return properties; - } - - public void setProperties(JsonElement properties) { - this.properties = properties; - } - - public String getModelVersion() { - return modelVersion; - } - - public void setModelVersion(String modelVersion) { - this.modelVersion = modelVersion; - } - - /** - * Unmarshalls this Edge object into a JSON string. - * - * @return - A JSON format string representation of this Edge. - */ - public String toJson() { - return gson.toJson(this); - } - - /** - * Marshalls the provided JSON string into a Edge object. - * - * @param json - The JSON string to produce the Edge from. - * @return - A Edge object. - * @throws SpikeException - */ - public static GraphEventEdge fromJson(String json) throws CrudException { - - try { - - // Make sure that we were actually provided a non-empty string - // before we - // go any further. - if (json == null || json.isEmpty()) { - throw new CrudException("Unable to parse JSON string: ", Status.BAD_REQUEST); - } - - // Marshall the string into an Edge object. - return gson.fromJson(json, GraphEventEdge.class); - - } catch (Exception ex) { - throw new CrudException("Unable to parse JSON string: ", Status.BAD_REQUEST); - } - } - - public static GraphEventEdge fromEdge(Edge edge, String modelVersion) { - - java.lang.reflect.Type mapType = new TypeToken>() {}.getType(); - JsonObject props = gson.toJsonTree(edge.getProperties(), mapType).getAsJsonObject(); - - GraphEventEdge graphEventEdge = new GraphEventEdge(edge.getId().orElse(""), modelVersion, - edge.getType(), new GraphEventVertex(edge.getSource().getId().orElse(""), null, - edge.getSource().getType(), null), new GraphEventVertex(edge.getTarget().getId().orElse(""), - null, edge.getTarget().getType(), null), props); - - return graphEventEdge; - - } - - public Edge toEdge() { - Edge.Builder builder = new Edge.Builder(this.getType()).id(this.getId()); - if (this.getSource() != null) { - builder.source(new Vertex.Builder(this.getSource().getType()).id(this.getSource().getId()) - .build()); - } - if (this.getTarget() != null) { - builder.target(new Vertex.Builder(this.getTarget().getType()).id(this.getTarget().getId()) - .build()); - } - - if (this.getProperties() != null) { - java.lang.reflect.Type mapType = new TypeToken>() {}.getType(); - Map propertiesMap = gson.fromJson(this.getProperties(), mapType); - for (String key : propertiesMap.keySet()) { - builder.property(key, propertiesMap.get(key)); - } - } - return builder.build(); - - } -} diff --git a/src/main/java/org/openecomp/crud/event/GraphEventVertex.java b/src/main/java/org/openecomp/crud/event/GraphEventVertex.java deleted file mode 100644 index 7fde12a..0000000 --- a/src/main/java/org/openecomp/crud/event/GraphEventVertex.java +++ /dev/null @@ -1,181 +0,0 @@ -/** - * ============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.event; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.annotations.SerializedName; -import com.google.gson.reflect.TypeToken; - -import org.openecomp.crud.entity.Vertex; -import org.openecomp.crud.exception.CrudException; - -import java.util.Map; -import javax.ws.rs.core.Response.Status; - -/** - * This class provides a generic representation of a Vertex as provided by the - * graph data store. - */ -public class GraphEventVertex { - - /** - * The unique identifier used to identify this vertex in the graph data - * store. - */ - @SerializedName("key") - private String id; - - @SerializedName("schema-version") - private String modelVersion; - - /** - * Type label assigned to this vertex. - */ - private String type; - - /** - * Map of all of the properties assigned to this vertex. - */ - private JsonElement properties; - - /** - * Marshaller/unmarshaller for converting to/from JSON. - */ - private static final Gson gson = new GsonBuilder().disableHtmlEscaping().create(); - - public GraphEventVertex(String id, String modelVersion, String type, JsonElement properties) { - this.id = id; - this.modelVersion = modelVersion; - this.type = type; - this.properties = properties; - } - - public GraphEventVertex() { - - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - - public JsonElement getProperties() { - return properties; - } - - public void setProperties(JsonElement properties) { - this.properties = properties; - } - - public String getModelVersion() { - return modelVersion; - } - - public void setModelVersion(String modelVersion) { - this.modelVersion = modelVersion; - } - - /** - * Unmarshalls this Vertex object into a JSON string. - * - * @return - A JSON format string representation of this Vertex. - */ - public String toJson() { - return gson.toJson(this); - } - - /** - * Marshalls the provided JSON string into a Vertex object. - * - * @param json - The JSON string to produce the Vertex from. - * @return - A Vertex object. - * @throws SpikeException - */ - public static GraphEventVertex fromJson(String json) throws CrudException { - - try { - - // Make sure that we were actually provided a non-empty string - // before we - // go any further. - if (json == null || json.isEmpty()) { - throw new CrudException("Empty or null JSON string.", Status.BAD_REQUEST); - } - - // Marshall the string into a Vertex object. - return gson.fromJson(json, GraphEventVertex.class); - - } catch (Exception ex) { - throw new CrudException("Unable to parse JSON string: ", Status.BAD_REQUEST); - } - } - - @Override - public String toString() { - - return toJson(); - } - - public static GraphEventVertex fromVertex(Vertex vertex, String modelVersion) { - - java.lang.reflect.Type mapType = new TypeToken>() {}.getType(); - JsonObject props = gson.toJsonTree(vertex.getProperties(), mapType).getAsJsonObject(); - GraphEventVertex graphEventVertex = new GraphEventVertex(vertex.getId().orElse(""), - modelVersion, vertex.getType(), props); - return graphEventVertex; - - } - - public Vertex toVertex() { - Vertex.Builder builder = new Vertex.Builder(this.getType()).id(this.getId()); - - if (this.getProperties() != null) { - java.lang.reflect.Type mapType = new TypeToken>() {}.getType(); - Map propertiesMap = gson.fromJson(this.getProperties(), mapType); - for (String key : propertiesMap.keySet()) { - builder.property(key, propertiesMap.get(key)); - } - } - - return builder.build(); - - } - - -} diff --git a/src/main/java/org/openecomp/crud/exception/CrudException.java b/src/main/java/org/openecomp/crud/exception/CrudException.java deleted file mode 100644 index 2911070..0000000 --- a/src/main/java/org/openecomp/crud/exception/CrudException.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * ============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.exception; - -import javax.ws.rs.core.Response.Status; - -public class CrudException extends Exception { - - private static final long serialVersionUID = 8162385108397238865L; - - private Status httpStatus; - - public CrudException() { - } - - public CrudException(String message, Status httpStatus) { - super(message); - this.setHttpStatus(httpStatus); - } - - public CrudException(Throwable cause) { - super(cause); - } - - public CrudException(String message, Throwable cause) { - super(message, cause); - } - - public CrudException(String message, Throwable cause, boolean enableSuppression, - boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - } - - public Status getHttpStatus() { - return httpStatus; - } - - public void setHttpStatus(Status httpStatus) { - this.httpStatus = httpStatus; - } -} diff --git a/src/main/java/org/openecomp/crud/logging/CrudServiceMsgs.java b/src/main/java/org/openecomp/crud/logging/CrudServiceMsgs.java deleted file mode 100644 index 4298709..0000000 --- a/src/main/java/org/openecomp/crud/logging/CrudServiceMsgs.java +++ /dev/null @@ -1,87 +0,0 @@ -/** - * ============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.logging; - -import com.att.eelf.i18n.EELFResourceManager; - -import org.openecomp.cl.eelf.LogMessageEnum; - -public enum CrudServiceMsgs implements LogMessageEnum { - - /** - * Received request {0} {1} from {2}. Sending response: {3} - * - *

    - * Arguments: {0} = operation {1} = target URL {2} = source {3} = response - * code - */ - PROCESS_REST_REQUEST, - - INVALID_OXM_FILE, INVALID_OXM_DIR, OXM_FILE_CHANGED, TRANSACTION, - - /** - * Successfully loaded schema: {0} - * - *

    - * Arguments: {0} = oxm filename - */ - LOADED_OXM_FILE, - - /** - * Unable to load OXM schema: {0} - * - *

    - * Arguments: {0} = error - */ - OXM_LOAD_ERROR, - - /** - * Stopping ChampDAO... - * - *

    - * Arguments: - */ - STOPPING_CHAMP_DAO, - - /** - * Failure instantiating CRUD Rest Service. Cause: {0} - * - *

    - * Arguments: {0} - Failure cause. - */ - INSTANTIATE_AUTH_ERR, - - /** - * Arguments: {0} Opertaion {1} URI {2} = Exception - */ - EXCEPTION_DURING_METHOD_CALL; - - /** - * Static initializer to ensure the resource bundles for this class are - * loaded... - */ - static { - EELFResourceManager.loadMessageBundle("logging/CrudServiceMsgs"); - } -} diff --git a/src/main/java/org/openecomp/crud/logging/LoggingUtil.java b/src/main/java/org/openecomp/crud/logging/LoggingUtil.java deleted file mode 100644 index b66a309..0000000 --- a/src/main/java/org/openecomp/crud/logging/LoggingUtil.java +++ /dev/null @@ -1,82 +0,0 @@ -/** - * ============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.logging; - -import org.openecomp.cl.api.LogFields; -import org.openecomp.cl.api.LogLine; -import org.openecomp.cl.api.Logger; -import org.openecomp.cl.mdc.MdcContext; -import org.openecomp.crud.util.CrudServiceConstants; -import org.slf4j.MDC; - -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.Response; - -public class LoggingUtil { - /** - * Initializes mdc context. - */ - public static void initMdcContext(HttpServletRequest httpReq, HttpHeaders headers) { - String fromIp = httpReq.getRemoteAddr(); - String fromAppId = ""; - String transId = null; - - if (headers.getRequestHeaders().getFirst("X-FromAppId") != null) { - fromAppId = headers.getRequestHeaders().getFirst("X-FromAppId"); - } - - if ((headers.getRequestHeaders().getFirst("X-TransactionId") == null) - || headers.getRequestHeaders().getFirst("X-TransactionId").isEmpty()) { - transId = java.util.UUID.randomUUID().toString(); - } else { - transId = headers.getRequestHeaders().getFirst("X-TransactionId"); - } - - MdcContext.initialize(transId, CrudServiceConstants.CRD_SERVICE_NAME, "", fromAppId, fromIp); - } - - /** - * Logs the rest request. - */ - public static void logRestRequest(Logger logger, Logger auditLogger, HttpServletRequest req, Response response) { - String respStatusString = ""; - if (Response.Status.fromStatusCode(response.getStatus()) != null) { - respStatusString = Response.Status.fromStatusCode(response.getStatus()).toString(); - } - - // Generate error log - logger.info(CrudServiceMsgs.PROCESS_REST_REQUEST, req.getMethod(), req.getRequestURL().toString(), - req.getRemoteHost(), Integer.toString(response.getStatus())); - - // Generate audit log. - auditLogger.info(CrudServiceMsgs.PROCESS_REST_REQUEST, - new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, response.getStatus()) - .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, respStatusString), - (req != null) ? req.getMethod() : "Unknown", (req != null) ? req.getRequestURL().toString() : "Unknown", - (req != null) ? req.getRemoteHost() : "Unknown", 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 deleted file mode 100644 index b527fa1..0000000 --- a/src/main/java/org/openecomp/crud/parser/CrudResponseBuilder.java +++ /dev/null @@ -1,212 +0,0 @@ -/** - * ============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.parser; - -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 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 { - - private static final Gson gson = new GsonBuilder().create(); - - 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 vertices, HashMap edges, - String version, BulkPayload incomingPayload) throws CrudException { - - for (JsonElement e : incomingPayload.getObjects()) { - List> entries = new ArrayList>( - e.getAsJsonObject().entrySet()); - - Map.Entry 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> entries = new ArrayList>( - e.getAsJsonObject().entrySet()); - - Map.Entry 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 { - VertexPayload payload = new VertexPayload(); - payload.setId(vertex.getId().get()); - payload.setType(vertex.getType()); - payload.setUrl(URL_BASE + version + "/" + vertex.getType() + "/" + vertex.getId().get()); - JsonObject props = new JsonObject(); - for (String key : vertex.getProperties().keySet()) { - addJsonProperperty(props, key, vertex.getProperties().get(key)); - } - payload.setProperties(props); - return payload.toJson(); - } - - public static String buildUpsertEdgeResponse(Edge edge, String version) throws CrudException { - return buildGetEdgeResponse(edge, version); - } - - public static String buildGetVertexResponse(Vertex vertex, List edges, String version) throws CrudException { - VertexPayload vertexPayload = new VertexPayload(); - vertexPayload.setId(vertex.getId().get()); - vertexPayload.setType(vertex.getType()); - vertexPayload.setUrl(URL_BASE + version + "/" + vertex.getType() + "/" + vertex.getId().get()); - JsonObject props = new JsonObject(); - for (String key : vertex.getProperties().keySet()) { - addJsonProperperty(props, key, vertex.getProperties().get(key)); - } - vertexPayload.setProperties(props); - List inEdges = new ArrayList(); - List outEdges = new ArrayList(); - for (Edge e : edges) { - if (e.getTarget().getId().get().equals(vertex.getId().get())) { - EdgePayload inEdge = new EdgePayload(); - inEdge.setId(e.getId().get()); - inEdge.setType(e.getType()); - inEdge.setUrl(URL_BASE + "relationships/" + RelationshipSchemaLoader.getLatestSchemaVersion() + "/" - + e.getType() + "/" + e.getId().get()); - inEdge.setSource(URL_BASE + version + "/" + e.getSource().getType() + "/" + e.getSource().getId().get()); - - inEdges.add(inEdge); - } else if (e.getSource().getId().get().equals(vertex.getId().get())) { - EdgePayload outEdge = new EdgePayload(); - outEdge.setId(e.getId().get()); - outEdge.setType(e.getType()); - outEdge.setUrl(URL_BASE + "relationships/" + RelationshipSchemaLoader.getLatestSchemaVersion() + "/" - + e.getType() + "/" + e.getId().get()); - outEdge.setTarget(URL_BASE + version + "/" + e.getTarget().getType() + "/" + e.getTarget().getId().get()); - outEdges.add(outEdge); - } - } - - vertexPayload.setIn(inEdges); - vertexPayload.setOut(outEdges); - - return vertexPayload.toJson(); - } - - public static String buildGetVerticesResponse(List items, String version) throws CrudException { - - JsonArray arry = new JsonArray(); - for (Vertex v : items) { - JsonObject item = new JsonObject(); - item.addProperty("id", v.getId().get()); - item.addProperty("type", v.getType()); - item.addProperty("url", "services/inventory/" + version + "/" + v.getType() + "/" + v.getId().get()); - - arry.add(item); - } - - return gson.toJson(arry); - } - - public static String buildGetEdgeResponse(Edge edge, String version) throws CrudException { - - EdgePayload payload = new EdgePayload(); - payload.setId(edge.getId().get()); - payload.setType(edge.getType()); - payload.setUrl(URL_BASE + "relationships/" + version + "/" + edge.getType() + "/" + edge.getId().get()); - payload.setSource(URL_BASE + version + "/" + edge.getSource().getType() + "/" + edge.getSource().getId().get()); - payload.setTarget(URL_BASE + version + "/" + edge.getTarget().getType() + "/" + edge.getTarget().getId().get()); - - JsonObject props = new JsonObject(); - for (String key : edge.getProperties().keySet()) { - addJsonProperperty(props, key, edge.getProperties().get(key)); - } - payload.setProperties(props); - return payload.toJson(); - } - - public static String buildGetEdgesResponse(List items, String version) throws CrudException { - - JsonArray arry = new JsonArray(); - for (Edge e : items) { - JsonObject item = new JsonObject(); - item.addProperty("id", e.getId().get()); - item.addProperty("type", e.getType()); - item.addProperty("url", URL_BASE + "relationships/" + version + "/" + e.getType() + "/" + e.getId().get()); - item.addProperty(SOURCE, - "services/inventory/" + version + "/" + e.getSource().getType() + "/" + e.getSource().getId().get()); - item.addProperty(TARGET, - "services/inventory/" + version + "/" + e.getTarget().getType() + "/" + e.getTarget().getId().get()); - arry.add(item); - } - - return gson.toJson(arry); - } - - private static void addJsonProperperty(JsonObject jsonObj, String key, Object value) { - if (value instanceof Integer) { - jsonObj.addProperty(key, (Integer) value); - } else if (value instanceof Boolean) { - jsonObj.addProperty(key, (Boolean) value); - } else if (value instanceof Double) { - jsonObj.addProperty(key, (Double) value); - } else if (value instanceof String) { - jsonObj.addProperty(key, (String) value); - } else { - jsonObj.addProperty(key, value.toString()); - } - } - -} diff --git a/src/main/java/org/openecomp/crud/service/AaiResourceService.java b/src/main/java/org/openecomp/crud/service/AaiResourceService.java deleted file mode 100644 index 9c6565a..0000000 --- a/src/main/java/org/openecomp/crud/service/AaiResourceService.java +++ /dev/null @@ -1,533 +0,0 @@ -/** - * ============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 java.security.cert.X509Certificate; -import java.util.AbstractMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -import javax.security.auth.x500.X500Principal; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.Consumes; -import javax.ws.rs.Encoded; -import javax.ws.rs.POST; -import javax.ws.rs.PUT; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; -import javax.ws.rs.core.Response.Status; - -import org.onap.aai.exceptions.AAIException; -import org.onap.aai.serialization.db.EdgeProperty; -import org.onap.aai.serialization.db.EdgeRule; -import org.onap.aai.serialization.db.EdgeRules; -import org.onap.aai.serialization.db.EdgeType; -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.service.CrudRestService.Action; -import org.openecomp.crud.util.CrudServiceConstants; -import org.openecomp.schema.RelationshipSchemaLoader; -import org.openecomp.schema.RelationshipSchemaValidator; -import org.slf4j.MDC; - -import com.google.gson.Gson; -import com.google.gson.JsonElement; -import com.google.gson.JsonPrimitive; - - -/** - * This defines a set of REST endpoints which allow clients to create or update graph edges - * where the edge rules defined by the A&AI will be invoked to automatically populate the - * defined edge properties. - */ -public class AaiResourceService { - - private String mediaType = MediaType.APPLICATION_JSON; - public static final String HTTP_PATCH_METHOD_OVERRIDE = "X-HTTP-Method-Override"; - - private Auth auth; - CrudGraphDataService crudGraphDataService; - Gson gson = new Gson(); - - private Logger logger = LoggerFactory.getInstance().getLogger(AaiResourceService.class.getName()); - private Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(AaiResourceService.class.getName()); - - public AaiResourceService() {} - - /** - * Creates a new instance of the AaiResourceService. - * - * @param crudGraphDataService - Service used for interacting with the graph. - * - * @throws Exception - */ - public AaiResourceService(CrudGraphDataService crudGraphDataService) throws Exception { - this.crudGraphDataService = crudGraphDataService; - this.auth = new Auth(CrudServiceConstants.CRD_AUTH_FILE); - } - - /** - * Perform any one-time initialization required when starting the service. - */ - public void startup() { - - if(logger.isDebugEnabled()) { - logger.debug("AaiResourceService started!"); - } - } - - - /** - * Creates a new relationship in the graph, automatically populating the edge - * properties based on the A&AI edge rules. - * - * @param content - Json structure describing the relationship to create. - * @param type - Relationship type supplied as a URI parameter. - * @param uri - Http request uri - * @param headers - Http request headers - * @param uriInfo - Http URI info field - * @param req - Http request structure. - * - * @return - Standard HTTP response. - */ - @POST - @Path("/relationships/{type}/") - @Consumes({MediaType.APPLICATION_JSON}) - @Produces({MediaType.APPLICATION_JSON}) - public Response createRelationship(String content, - @PathParam("type") String type, - @PathParam("uri") @Encoded String uri, - @Context HttpHeaders headers, - @Context UriInfo uriInfo, - @Context HttpServletRequest req) { - - LoggingUtil.initMdcContext(req, headers); - - if(logger.isDebugEnabled()) { - logger.debug("Incoming request..." + content); - } - - Response response = null; - - if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) { - - try { - - // Extract the edge payload from the request. - EdgePayload payload = EdgePayload.fromJson(content); - - // Do some basic validation on the payload. - if (payload.getProperties() == null || payload.getProperties().isJsonNull()) { - throw new CrudException("Invalid request Payload", Status.BAD_REQUEST); - } - if (payload.getId() != null) { - throw new CrudException("ID specified , use Http PUT to update Edge", Status.BAD_REQUEST); - } - if (payload.getType() != null && !payload.getType().equals(type)) { - throw new CrudException("Edge Type mismatch", Status.BAD_REQUEST); - } - - // Apply the edge rules to our edge. - payload = applyEdgeRulesToPayload(payload); - - if(logger.isDebugEnabled()) { - logger.debug("Creating AAI edge using version " + RelationshipSchemaLoader.getLatestSchemaVersion() ); - } - - // Now, create our edge in the graph store. - String result = crudGraphDataService.addEdge(RelationshipSchemaLoader.getLatestSchemaVersion(), type, payload); - response = Response.status(Status.CREATED).entity(result).type(mediaType).build(); - - } catch (CrudException e) { - - response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build(); - } - } - - LoggingUtil.logRestRequest(logger, auditLogger, req, response); - return response; - } - - - /** - * Creates a new relationship in the graph, automatically populating the edge - * properties based on the A&AI edge rules. - * - * @param content - Json structure describing the relationship to create. - * @param uri - Http request uri - * @param headers - Http request headers - * @param uriInfo - Http URI info field - * @param req - Http request structure. - * - * @return - Standard HTTP response. - * - */ - @POST - @Path("/relationships/") - @Consumes({MediaType.APPLICATION_JSON}) - @Produces({MediaType.APPLICATION_JSON}) - public Response createRelationship(String content, - @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 { - - // Extract the edge payload from the request. - EdgePayload payload = EdgePayload.fromJson(content); - - // Do some basic validation on the payload. - if (payload.getProperties() == null || payload.getProperties().isJsonNull()) { - throw new CrudException("Invalid request Payload", Status.BAD_REQUEST); - } - if (payload.getId() != null) { - throw new CrudException("ID specified , use Http PUT to update Edge", Status.BAD_REQUEST); - } - if (payload.getType() == null || payload.getType().isEmpty()) { - throw new CrudException("Missing Edge Type ", Status.BAD_REQUEST); - } - - // Apply the edge rules to our edge. - payload = applyEdgeRulesToPayload(payload); - - // Now, create our edge in the graph store. - String result = crudGraphDataService.addEdge(RelationshipSchemaLoader.getLatestSchemaVersion(), payload.getType(), payload); - response = Response.status(Status.CREATED).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; - } - - - - /** - * Upserts a relationship into the graph, automatically populating the edge properties - * based on the A&AI edge rules. The behaviour is as follows: - *

    - *

  • If no relationship with the supplied identifier already exists, then a new relationship - * is created with that id.
    - *
  • If a relationship with the supplied id DOES exist, then it is replaced with the supplied - * content. - * - * @param content - Json structure describing the relationship to create. - * @param type - Relationship type supplied as a URI parameter. - * @param id - Edge identifier. - * @param uri - Http request uri - * @param headers - Http request headers - * @param uriInfo - Http URI info field - * @param req - Http request structure. - * - * @return - Standard HTTP response. - */ - @PUT - @Path("/relationships/{type}/{id}") - @Consumes({MediaType.APPLICATION_JSON}) - @Produces({MediaType.APPLICATION_JSON}) - public Response upsertEdge(String content, - @PathParam("type") String type, - @PathParam("id") String id, - @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.PUT, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) { - - try { - - // Extract the edge payload from the request. - EdgePayload payload = EdgePayload.fromJson(content); - - // Do some basic validation on the payload. - if (payload.getProperties() == null || payload.getProperties().isJsonNull()) { - throw new CrudException("Invalid request Payload", Status.BAD_REQUEST); - } - if (payload.getId() != null && !payload.getId().equals(id)) { - throw new CrudException("ID Mismatch", Status.BAD_REQUEST); - } - - // Apply the edge rules to our edge. - payload = applyEdgeRulesToPayload(payload); - - String result; - if (headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE) != null && - headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE).equalsIgnoreCase("PATCH")) { - result = crudGraphDataService.patchEdge(RelationshipSchemaLoader.getLatestSchemaVersion(), id, type, payload); - } else { - - result = crudGraphDataService.updateEdge(RelationshipSchemaLoader.getLatestSchemaVersion(), id, type, 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; - } - - - /** - * Retrieves the properties defined in the edge rules for a relationship between the - * supplied vertex types. - * - * @param sourceVertexType - Type of source vertex for the relationship. - * @param targetVertexType - Type of target vertex for the relationship. - * - * @return - The defined properties for the relationship type. - * - * @throws CrudException - */ - private Map getEdgeRuleProperties(String sourceVertexType, String targetVertexType) throws CrudException { - - if(logger.isDebugEnabled()) { - logger.debug("Lookup db edge rules for " + sourceVertexType + " -> " + targetVertexType); - } - - EdgeRules rules = EdgeRules.getInstance(); - EdgeRule rule; - try { - - if(logger.isDebugEnabled()) { - logger.debug("Lookup by edge type TREE"); - } - - // We have no way of knowing in advance whether our relationship is considered to - // be a tree or cousing relationship, so try looking it up as a tree type first. - rule = rules.getEdgeRule(EdgeType.TREE, sourceVertexType, targetVertexType); - - } catch (AAIException e) { - try { - - if(logger.isDebugEnabled()) { - logger.debug("Lookup by edge type COUSIN"); - } - - // If we are here, then our lookup by 'tree' type failed, so try looking it up - // as a 'cousin' relationship. - rule = rules.getEdgeRule(EdgeType.COUSIN, sourceVertexType, targetVertexType); - - } catch (AAIException e1) { - - // If we're here then we failed to find edge rules for this relationship. Time to - // give up... - throw new CrudException("No edge rules for " + sourceVertexType + " -> " + targetVertexType, Status.NOT_FOUND); - } - } catch (Exception e) { - - throw new CrudException("General failure getting edge rule properties - " + - e.getMessage(), Status.INTERNAL_SERVER_ERROR); - } - - return rule.getEdgeProperties(); - } - - - /** - * This method takes an inbound edge request payload, looks up the edge rules for the - * sort of relationship defined in the payload, and automatically applies the defined - * edge properties to it. - * - * @param payload - The original edge request payload - * - * @return - An updated edge request payload, with the properties defined in the edge - * rules automatically populated. - * - * @throws CrudException - */ - public EdgePayload applyEdgeRulesToPayload(EdgePayload payload) throws CrudException { - - // Extract the types for both the source and target vertices. - String srcType = RelationshipSchemaValidator.vertexTypeFromUri(payload.getSource()); - String tgtType = RelationshipSchemaValidator.vertexTypeFromUri(payload.getTarget()); - - // Now, get the default properties for this edge based on the edge rules definition... - Map props = getEdgeRuleProperties(srcType, tgtType); - - // ...and merge them with any custom properties provided in the request. - JsonElement mergedProperties = mergeProperties(payload.getProperties(), props); - payload.setProperties(mergedProperties); - - - if(logger.isDebugEnabled()) { - logger.debug("Edge properties after applying rules for '" + srcType + " -> " + tgtType + "': " + mergedProperties); - } - - return payload; - } - - - /** - * Given a set of edge properties extracted from an edge request payload and a set of properties - * taken from the db edge rules, this method merges them into one set of properties. - *

    - * If the client has attempted to override the defined value for a property in the db edge rules - * then the request will be rejected as invalid. - * - * @param propertiesFromRequest - Set of properties from the edge request. - * @param propertyDefaults - Set of properties from the db edge rules. - * - * @return - A merged set of properties. - * - * @throws CrudException - */ - public JsonElement mergeProperties(JsonElement propertiesFromRequest, Map propertyDefaults) throws CrudException { - - // Convert the properties from the edge payload into something we can - // manipulate. - Set> properties = new HashSet>(); - properties.addAll(propertiesFromRequest.getAsJsonObject().entrySet()); - - Set propertyKeys = new HashSet(); - for(Map.Entry property : properties) { - propertyKeys.add(property.getKey()); - } - - // Now, merge in the properties specified in the Db Edge Rules. - for(EdgeProperty defProperty : propertyDefaults.keySet()) { - - // If the edge rules property was explicitly specified by the - // client then we will reject the request... - if(!propertyKeys.contains(defProperty.toString())) { - properties.add(new AbstractMap.SimpleEntry(defProperty.toString(), - (JsonElement)(new JsonPrimitive(propertyDefaults.get(defProperty))))); - - } else { - throw new CrudException("Property " + defProperty + " defined in db edge rules can not be overriden by the client.", - Status.BAD_REQUEST); - } - } - - Object[] propArray = properties.toArray(); - StringBuilder sb = new StringBuilder(); - sb.append("{"); - boolean first=true; - for(int i=0; i entry = (Entry) propArray[i]; - if(!first) { - sb.append(","); - } - sb.append("\"").append(entry.getKey()).append("\"").append(":").append(entry.getValue()); - first=false; - } - sb.append("}"); - - // We're done. Return the result as a JsonElement. - return gson.fromJson(sb.toString(), JsonElement.class); - } - - - /** - * Invokes authentication validation on an incoming HTTP request. - * - * @param req - The HTTP request. - * @param uri - HTTP URI - * @param content - Payload of the HTTP request. - * @param action - What HTTP action is being performed (GET/PUT/POST/PATCH/DELETE) - * @param authPolicyFunctionName - Policy function being invoked. - * - * @return true - if the request passes validation, - * false - otherwise. - */ - protected boolean validateRequest(HttpServletRequest req, - String uri, - String content, - Action action, - String authPolicyFunctionName) { - try { - String cipherSuite = (String) req.getAttribute("javax.servlet.request.cipher_suite"); - String authUser = null; - if (cipherSuite != null) { - - X509Certificate[] certChain = (X509Certificate[]) req.getAttribute("javax.servlet.request.X509Certificate"); - X509Certificate clientCert = certChain[0]; - X500Principal subjectDn = clientCert.getSubjectX500Principal(); - authUser = subjectDn.toString(); - } - - return this.auth.validateRequest(authUser.toLowerCase(), action.toString() + ":" + authPolicyFunctionName); - - } catch (Exception e) { - logResult(action, uri, e); - return false; - } - } - - protected void logResult(Action op, String uri, Exception e) { - - logger.error(CrudServiceMsgs.EXCEPTION_DURING_METHOD_CALL, - op.toString(), - uri, - e.getStackTrace().toString()); - - // Clear the MDC context so that no other transaction inadvertently - // uses our transaction id. - MDC.clear(); - } -} diff --git a/src/main/java/org/openecomp/crud/service/BulkPayload.java b/src/main/java/org/openecomp/crud/service/BulkPayload.java deleted file mode 100644 index 619c53b..0000000 --- a/src/main/java/org/openecomp/crud/service/BulkPayload.java +++ /dev/null @@ -1,124 +0,0 @@ -/** - * ============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 objects = new ArrayList(); - private List relationships = new ArrayList(); - - 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 getObjects() { - return objects; - } - - public void setObjects(List objects) { - this.objects = objects; - } - - public List getRelationships() { - return relationships; - } - - public void setRelationships(List 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 po = p.getObjects(); - List ids = new ArrayList(); - for (JsonElement e : po) { - Set> entries = e.getAsJsonObject().entrySet(); - - for (Map.Entry 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 deleted file mode 100644 index 340fafa..0000000 --- a/src/main/java/org/openecomp/crud/service/CrudGraphDataService.java +++ /dev/null @@ -1,301 +0,0 @@ -/** - * ============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 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; -import org.openecomp.schema.OxmModelValidator; -import org.openecomp.schema.RelationshipSchemaLoader; -import org.openecomp.schema.RelationshipSchemaValidator; - -import com.google.gson.JsonElement; - -public class CrudGraphDataService { - - private GraphDao dao; - - public CrudGraphDataService(ChampGraph graphImpl) throws CrudException { - this.dao = new ChampDao(graphImpl); - - loadModels(); - } - - 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(); - } - - 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 vertices = new HashMap(); - HashMap edges = new HashMap(); - String txId = dao.openTransaction(); - try { - // Handle vertices - for (JsonElement v : payload.getObjects()) { - List> entries = new ArrayList>( - v.getAsJsonObject().entrySet()); - - if (entries.size() != 2) { - throw new CrudException("", Status.BAD_REQUEST); - } - Map.Entry opr = entries.get(0); - Map.Entry 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> entries = new ArrayList>( - v.getAsJsonObject().entrySet()); - - if (entries.size() != 2) { - throw new CrudException("", Status.BAD_REQUEST); - } - Map.Entry opr = entries.get(0); - Map.Entry 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()); - return CrudResponseBuilder - .buildUpsertVertexResponse(OxmModelValidator.validateOutgoingPayload(version, addedVertex), version); - } - - public String addEdge(String version, String type, EdgePayload payload) throws CrudException { - Edge edge = RelationshipSchemaValidator.validateIncomingAddPayload(version, type, payload); - return addEdge(version, edge); - } - - private String addEdge(String version, Edge edge) throws CrudException { - Edge addedEdge = dao.addEdge(edge.getType(), edge.getSource(), edge.getTarget(), edge.getProperties()); - return CrudResponseBuilder - .buildUpsertEdgeResponse(RelationshipSchemaValidator.validateOutgoingPayload(version, addedEdge), version); - } - - public String getEdge(String version, String id, String type) throws CrudException { - RelationshipSchemaValidator.validateType(version, type); - Edge edge = dao.getEdge(id, type); - - return CrudResponseBuilder.buildGetEdgeResponse(RelationshipSchemaValidator.validateOutgoingPayload(version, edge), - version); - } - - public String getEdges(String version, String type, Map filter) throws CrudException { - RelationshipSchemaValidator.validateType(version, type); - List items = dao.getEdges(type, RelationshipSchemaValidator.resolveCollectionfilter(version, type, filter)); - return CrudResponseBuilder.buildGetEdgesResponse(items, version); - } - - public String updateVertex(String version, String id, String type, VertexPayload payload) throws CrudException { - Vertex vertex = OxmModelValidator.validateIncomingUpsertPayload(id, version, type, payload.getProperties()); - return updateVertex(version, vertex); - - } - - private String updateVertex(String version, Vertex vertex) throws CrudException { - Vertex updatedVertex = dao.updateVertex(vertex.getId().get(), vertex.getType(), vertex.getProperties()); - return CrudResponseBuilder - .buildUpsertVertexResponse(OxmModelValidator.validateOutgoingPayload(version, updatedVertex), version); - } - - public String patchVertex(String version, String id, String type, VertexPayload payload) throws CrudException { - Vertex existingVertex = dao.getVertex(id, OxmModelValidator.resolveCollectionType(version, type)); - Vertex vertex = OxmModelValidator.validateIncomingPatchPayload(id, version, type, payload.getProperties(), - existingVertex); - return updateVertex(version, vertex); - - } - - public String deleteVertex(String version, String id, String type) throws CrudException { - type = OxmModelValidator.resolveCollectionType(version, type); - dao.deleteVertex(id, type); - return ""; - - } - - public String deleteEdge(String version, String id, String type) throws CrudException { - RelationshipSchemaValidator.validateType(version, type); - dao.deleteEdge(id, type); - return ""; - - } - - public String updateEdge(String version, String id, String type, EdgePayload payload) throws CrudException { - Edge edge = dao.getEdge(id, type); - Edge validatedEdge = RelationshipSchemaValidator.validateIncomingUpdatePayload(edge, version, payload); - return updateEdge(version, validatedEdge); - - } - - private String updateEdge(String version, Edge edge) throws CrudException { - Edge updatedEdge = dao.updateEdge(edge); - return CrudResponseBuilder - .buildUpsertEdgeResponse(RelationshipSchemaValidator.validateOutgoingPayload(version, updatedEdge), version); - } - - public String patchEdge(String version, String id, String type, EdgePayload payload) throws CrudException { - Edge edge = dao.getEdge(id, type); - Edge patchedEdge = RelationshipSchemaValidator.validateIncomingPatchPayload(edge, version, payload); - return updateEdge(version, patchedEdge); - - } - - public Vertex getVertex(String id) throws CrudException { - return dao.getVertex(id); - } - - public String getVertex(String version, String id, String type) throws CrudException { - type = OxmModelValidator.resolveCollectionType(version, type); - Vertex vertex = dao.getVertex(id, type); - List edges = dao.getVertexEdges(id); - return CrudResponseBuilder.buildGetVertexResponse(OxmModelValidator.validateOutgoingPayload(version, vertex), edges, - version); - } - - public String getVertices(String version, String type, Map filter) throws CrudException { - type = OxmModelValidator.resolveCollectionType(version, type); - List items = dao.getVertices(type, OxmModelValidator.resolveCollectionfilter(version, 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 deleted file mode 100644 index 79b5624..0000000 --- a/src/main/java/org/openecomp/crud/service/CrudRestService.java +++ /dev/null @@ -1,784 +0,0 @@ -/** - * ============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 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; -import javax.ws.rs.DELETE; -import javax.ws.rs.Encoded; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.PUT; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.MediaType; -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; - Logger logger = LoggerFactory.getInstance().getLogger(CrudRestService.class.getName()); - Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(CrudRestService.class.getName()); - private Auth auth; - - private String mediaType = MediaType.APPLICATION_JSON; - public static final String HTTP_PATCH_METHOD_OVERRIDE = "X-HTTP-Method-Override"; - - public CrudRestService(CrudGraphDataService crudGraphDataService) throws Exception { - this.crudGraphDataService = crudGraphDataService; - this.auth = new Auth(CrudServiceConstants.CRD_AUTH_FILE); - } - - public enum Action { - POST, GET, PUT, DELETE, PATCH - } - - ; - - public void startup() { - - } - - @GET - @Path("/{version}/{type}/{id}") - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - public Response getVertex(String content, @PathParam("version") String version, @PathParam("type") String type, - @PathParam("id") String id, @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.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) { - - try { - String result = crudGraphDataService.getVertex(version, id, type); - 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; - } - - @GET - @Path("/{version}/{type}/") - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - public Response getVertices(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.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) { - - Map filter = new HashMap(); - for (Map.Entry> e : uriInfo.getQueryParameters().entrySet()) { - filter.put(e.getKey(), e.getValue().get(0)); - } - - try { - String result = crudGraphDataService.getVertices(version, type, filter); - 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; - } - - @GET - @Path("/relationships/{version}/{type}/{id}") - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - public Response getEdge(String content, @PathParam("version") String version, @PathParam("type") String type, - @PathParam("id") String id, @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.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) { - - try { - - String result = crudGraphDataService.getEdge(version, id, type); - 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; - } - - @GET - @Path("/relationships/{version}/{type}/") - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - public Response getEdges(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.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) { - - Map filter = new HashMap(); - for (Map.Entry> e : uriInfo.getQueryParameters().entrySet()) { - filter.put(e.getKey(), e.getValue().get(0)); - } - - try { - String result = crudGraphDataService.getEdges(version, type, filter); - 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; - } - - @PUT - @Path("/relationships/{version}/{type}/{id}") - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - public Response updateEdge(String content, @PathParam("version") String version, @PathParam("type") String type, - @PathParam("id") String id, @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.PUT, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) { - - try { - EdgePayload payload = EdgePayload.fromJson(content); - if (payload.getProperties() == null || payload.getProperties().isJsonNull()) { - throw new CrudException("Invalid request Payload", Status.BAD_REQUEST); - } - if (payload.getId() != null && !payload.getId().equals(id)) { - throw new CrudException("ID Mismatch", Status.BAD_REQUEST); - } - String result; - - if (headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE) != null - && headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE).equalsIgnoreCase("PATCH")) { - result = crudGraphDataService.patchEdge(version, id, type, payload); - } else { - - result = crudGraphDataService.updateEdge(version, id, type, 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; - } - - @PATCH - @Path("/relationships/{version}/{type}/{id}") - @Consumes({ "application/merge-patch+json" }) - @Produces({ MediaType.APPLICATION_JSON }) - public Response patchEdge(String content, @PathParam("version") String version, @PathParam("type") String type, - @PathParam("id") String id, @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.PATCH, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) { - - try { - EdgePayload payload = EdgePayload.fromJson(content); - if (payload.getProperties() == null || payload.getProperties().isJsonNull()) { - throw new CrudException("Invalid request Payload", Status.BAD_REQUEST); - } - if (payload.getId() != null && !payload.getId().equals(id)) { - throw new CrudException("ID Mismatch", Status.BAD_REQUEST); - } - - String result = crudGraphDataService.patchEdge(version, id, type, 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; - } - - @PUT - @Path("/{version}/{type}/{id}") - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - public Response updateVertex(String content, @PathParam("version") String version, @PathParam("type") String type, - @PathParam("id") String id, @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.PUT, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) { - - try { - VertexPayload payload = VertexPayload.fromJson(content); - if (payload.getProperties() == null || payload.getProperties().isJsonNull()) { - throw new CrudException("Invalid request Payload", Status.BAD_REQUEST); - } - if (payload.getId() != null && !payload.getId().equals(id)) { - throw new CrudException("ID Mismatch", Status.BAD_REQUEST); - } - String result; - if (headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE) != null - && headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE).equalsIgnoreCase("PATCH")) { - result = crudGraphDataService.patchVertex(version, id, type, payload); - } else { - - result = crudGraphDataService.updateVertex(version, id, type, 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; - } - - @PATCH - @Path("/{version}/{type}/{id}") - @Consumes({ "application/merge-patch+json" }) - @Produces({ MediaType.APPLICATION_JSON }) - public Response patchVertex(String content, @PathParam("version") String version, @PathParam("type") String type, - @PathParam("id") String id, @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.PATCH, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) { - try { - VertexPayload payload = VertexPayload.fromJson(content); - if (payload.getProperties() == null || payload.getProperties().isJsonNull()) { - throw new CrudException("Invalid request Payload", Status.BAD_REQUEST); - } - if (payload.getId() != null && !payload.getId().equals(id)) { - throw new CrudException("ID Mismatch", Status.BAD_REQUEST); - } - - String result = crudGraphDataService.patchVertex(version, id, type, 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}/{type}/") - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - public Response addVertex(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 { - VertexPayload payload = VertexPayload.fromJson(content); - if (payload.getProperties() == null || payload.getProperties().isJsonNull()) { - throw new CrudException("Invalid request Payload", Status.BAD_REQUEST); - } - if (payload.getId() != null) { - throw new CrudException("ID specified , use Http PUT to update Vertex", Status.BAD_REQUEST); - } - - if (payload.getType() != null && !payload.getType().equals(type)) { - throw new CrudException("Vertex Type mismatch", Status.BAD_REQUEST); - } - - String result = crudGraphDataService.addVertex(version, type, payload); - response = Response.status(Status.CREATED).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; - } - - private void validateBulkPayload(BulkPayload payload) throws CrudException { - List vertices = new ArrayList(); - List edges = new ArrayList(); - - for (JsonElement v : payload.getObjects()) { - List> entries = new ArrayList>( - v.getAsJsonObject().entrySet()); - - if (entries.size() != 2) { - throw new CrudException("", Status.BAD_REQUEST); - } - Map.Entry opr = entries.get(0); - Map.Entry 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> entries = new ArrayList>( - v.getAsJsonObject().entrySet()); - - if (entries.size() != 2) { - throw new CrudException("", Status.BAD_REQUEST); - } - Map.Entry opr = entries.get(0); - Map.Entry 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}/") - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - public Response addVertex(String content, @PathParam("version") String version, @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 { - - VertexPayload payload = VertexPayload.fromJson(content); - if (payload.getProperties() == null || payload.getProperties().isJsonNull()) { - throw new CrudException("Invalid request Payload", Status.BAD_REQUEST); - } - if (payload.getId() != null) { - throw new CrudException("ID specified , use Http PUT to update Vertex", Status.BAD_REQUEST); - } - - if (payload.getType() == null || payload.getType().isEmpty()) { - throw new CrudException("Missing Vertex Type ", Status.BAD_REQUEST); - } - String result = crudGraphDataService.addVertex(version, payload.getType(), payload); - response = Response.status(Status.CREATED).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("/relationships/{version}/{type}/") - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - public Response addEdge(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 { - EdgePayload payload = EdgePayload.fromJson(content); - if (payload.getProperties() == null || payload.getProperties().isJsonNull()) { - throw new CrudException("Invalid request Payload", Status.BAD_REQUEST); - } - if (payload.getId() != null) { - throw new CrudException("ID specified , use Http PUT to update Edge", Status.BAD_REQUEST); - } - - if (payload.getType() != null && !payload.getType().equals(type)) { - throw new CrudException("Edge Type mismatch", Status.BAD_REQUEST); - } - String result = crudGraphDataService.addEdge(version, type, payload); - response = Response.status(Status.CREATED).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("/relationships/{version}/") - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - public Response addEdge(String content, @PathParam("version") String version, @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 { - EdgePayload payload = EdgePayload.fromJson(content); - if (payload.getProperties() == null || payload.getProperties().isJsonNull()) { - throw new CrudException("Invalid request Payload", Status.BAD_REQUEST); - } - if (payload.getId() != null) { - throw new CrudException("ID specified , use Http PUT to update Edge", Status.BAD_REQUEST); - } - - if (payload.getType() == null || payload.getType().isEmpty()) { - throw new CrudException("Missing Edge Type ", Status.BAD_REQUEST); - } - String result = crudGraphDataService.addEdge(version, payload.getType(), payload); - - response = Response.status(Status.CREATED).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; - } - - @DELETE - @Path("/{version}/{type}/{id}") - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - public Response deleteVertex(String content, @PathParam("version") String version, @PathParam("type") String type, - @PathParam("id") String id, @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.DELETE, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) { - - try { - String result = crudGraphDataService.deleteVertex(version, id, type); - 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; - } - - @DELETE - @Path("/relationships/{version}/{type}/{id}") - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - public Response deleteEdge(String content, @PathParam("version") String version, @PathParam("type") String type, - @PathParam("id") String id, @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.DELETE, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) { - - try { - String result = crudGraphDataService.deleteEdge(version, id, type); - 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; - } - - protected boolean validateRequest(HttpServletRequest req, String uri, String content, Action action, - String authPolicyFunctionName) { - try { - String cipherSuite = (String) req.getAttribute("javax.servlet.request.cipher_suite"); - String authUser = null; - if (cipherSuite != null) { - X509Certificate[] certChain = (X509Certificate[]) req.getAttribute("javax.servlet.request.X509Certificate"); - X509Certificate clientCert = certChain[0]; - X500Principal subjectDn = clientCert.getSubjectX500Principal(); - authUser = subjectDn.toString(); - } - return this.auth.validateRequest(authUser.toLowerCase(), action.toString() + ":" + authPolicyFunctionName); - } catch (Exception e) { - logResult(action, uri, e); - return false; - } - } - - void logResult(Action op, String uri, Exception e) { - - logger.error(CrudServiceMsgs.EXCEPTION_DURING_METHOD_CALL, op.toString(), uri, e.getStackTrace().toString()); - - // Clear the MDC context so that no other transaction inadvertently - // uses our transaction id. - MDC.clear(); - } -} diff --git a/src/main/java/org/openecomp/crud/service/EdgePayload.java b/src/main/java/org/openecomp/crud/service/EdgePayload.java deleted file mode 100644 index d098d16..0000000 --- a/src/main/java/org/openecomp/crud/service/EdgePayload.java +++ /dev/null @@ -1,115 +0,0 @@ -/** - * ============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.JsonElement; - -import org.openecomp.crud.exception.CrudException; - -import javax.ws.rs.core.Response.Status; - -public class EdgePayload { - - private String id; - private String type; - private String url; - private String source; - private String target; - private JsonElement properties; - - private static final Gson gson = new GsonBuilder().disableHtmlEscaping().create(); - - - @Override - public String toString() { - return "EdgePayload [id=" + id + ", type=" + type + ", url=" + url + ", source=" - + source + ", target=" + target + ", properties=" + properties + "]"; - } - - public String toJson() { - return gson.toJson(this); - } - - public static EdgePayload fromJson(String payload) throws CrudException { - try { - if (payload == null || payload.isEmpty()) { - throw new CrudException("Invalid Json Payload", Status.BAD_REQUEST); - } - return gson.fromJson(payload, EdgePayload.class); - } catch (Exception ex) { - throw new CrudException("Invalid Json Payload", Status.BAD_REQUEST); - } - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public String getSource() { - return source; - } - - public void setSource(String source) { - this.source = source; - } - - public String getTarget() { - return target; - } - - public void setTarget(String target) { - this.target = target; - } - - public JsonElement getProperties() { - return properties; - } - - public void setProperties(JsonElement properties) { - this.properties = properties; - } - -} \ No newline at end of file diff --git a/src/main/java/org/openecomp/crud/service/JaxrsEchoService.java b/src/main/java/org/openecomp/crud/service/JaxrsEchoService.java deleted file mode 100644 index 0edd316..0000000 --- a/src/main/java/org/openecomp/crud/service/JaxrsEchoService.java +++ /dev/null @@ -1,63 +0,0 @@ -/** - * ============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 org.openecomp.cl.api.Logger; -import org.openecomp.cl.eelf.LoggerFactory; -import org.openecomp.crud.logging.LoggingUtil; - -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.Status; -import javax.ws.rs.core.UriInfo; - - -public class JaxrsEchoService { - - private static Logger logger = LoggerFactory.getInstance() - .getLogger(JaxrsEchoService.class.getName()); - private static Logger auditLogger = LoggerFactory.getInstance() - .getAuditLogger(JaxrsEchoService.class.getName()); - - @GET - @Path("echo/{input}") - @Produces("text/plain") - public String ping(@PathParam("input") String input, - @Context HttpHeaders headers, - @Context UriInfo info, - @Context HttpServletRequest req) { - - LoggingUtil.initMdcContext(req, headers); - LoggingUtil.logRestRequest(logger, auditLogger, req, Response.status(Status.OK) - .entity("OK").build()); - - return "Hello, " + input + "."; - } -} \ No newline at end of file diff --git a/src/main/java/org/openecomp/crud/service/VertexPayload.java b/src/main/java/org/openecomp/crud/service/VertexPayload.java deleted file mode 100644 index ed79002..0000000 --- a/src/main/java/org/openecomp/crud/service/VertexPayload.java +++ /dev/null @@ -1,117 +0,0 @@ -/** - * ============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.JsonElement; - -import org.openecomp.crud.exception.CrudException; - -import java.util.ArrayList; -import java.util.List; -import javax.ws.rs.core.Response.Status; - -public class VertexPayload { - - private String id; - private String type; - private String url; - private JsonElement properties; - private List in = new ArrayList(); - private List out = new ArrayList(); - - private static final Gson gson = new GsonBuilder().disableHtmlEscaping().create(); - - public String toJson() { - return gson.toJson(this); - } - - public static VertexPayload fromJson(String payload) throws CrudException { - try { - if (payload == null || payload.isEmpty()) { - throw new CrudException("Invalid Json Payload", Status.BAD_REQUEST); - } - return gson.fromJson(payload, VertexPayload.class); - } catch (Exception ex) { - throw new CrudException("Invalid Json Payload", Status.BAD_REQUEST); - } - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public JsonElement getProperties() { - return properties; - } - - public void setProperties(JsonElement properties) { - this.properties = properties; - } - - public List getIn() { - return in; - } - - public void setIn(List in) { - this.in = in; - } - - public List getOut() { - return out; - } - - public void setOut(List out) { - this.out = out; - } - - - @Override - public String toString() { - return "VertexPayload [id=" + id + ", type=" + type + ", url=" + url + ", properties=" - + properties + ", in=" + in + ", out=" + out + "]"; - } - -} \ No newline at end of file diff --git a/src/main/java/org/openecomp/crud/util/CrudJaxbTransformation.java b/src/main/java/org/openecomp/crud/util/CrudJaxbTransformation.java deleted file mode 100644 index c1a1e18..0000000 --- a/src/main/java/org/openecomp/crud/util/CrudJaxbTransformation.java +++ /dev/null @@ -1,92 +0,0 @@ -/** - * ============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.util; - -import org.eclipse.persistence.dynamic.DynamicEntity; -import org.eclipse.persistence.jaxb.JAXBMarshaller; -import org.eclipse.persistence.jaxb.MarshallerProperties; -import org.eclipse.persistence.jaxb.UnmarshallerProperties; -import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext; - -import java.io.StringReader; -import java.io.StringWriter; -import javax.ws.rs.core.MediaType; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Unmarshaller; -import javax.xml.transform.stream.StreamSource; - -public class CrudJaxbTransformation { - /** - * Marshal a dynamic entity into a string. - * - * @param entity the dynamic entity - * @param jaxbContext the dynamic jaxb context - * @return the marshaled entity - * @throws RouterException on error - */ - public static String marshal(MediaType mediaType, final DynamicEntity entity, - final DynamicJAXBContext jaxbContext) throws JAXBException { - - final JAXBMarshaller marshaller = jaxbContext.createMarshaller(); - marshaller.setProperty(JAXBMarshaller.JAXB_FORMATTED_OUTPUT, false); - - if (MediaType.APPLICATION_JSON_TYPE.isCompatible(mediaType)) { - marshaller.setProperty("eclipselink.media-type", "application/json"); - marshaller.setProperty("eclipselink.json.include-root", false); - marshaller.setProperty(MarshallerProperties.JSON_MARSHAL_EMPTY_COLLECTIONS, Boolean.FALSE); - } - - final StringWriter writer = new StringWriter(); - marshaller.marshal(entity, writer); - return writer.toString(); - - } - - /** - * @param type - * @param json - * @param mediaType - * @return - * @throws JAXBException - * @throws Exception - */ - public static Object unmarshal(String javaClass, String content, MediaType mediaType, - final DynamicJAXBContext jaxbContext) throws JAXBException { - Object clazz = null; - Unmarshaller unmarshaller = null; - - clazz = jaxbContext.newDynamicEntity(javaClass); - - unmarshaller = jaxbContext.createUnmarshaller(); - if (mediaType.equals(MediaType.APPLICATION_JSON_TYPE)) { - unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json"); - unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false); - unmarshaller.setProperty(UnmarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true); - } - - return unmarshaller.unmarshal(new StreamSource(new StringReader(content)), - clazz.getClass()).getValue(); - } - -} diff --git a/src/main/java/org/openecomp/crud/util/CrudProperties.java b/src/main/java/org/openecomp/crud/util/CrudProperties.java deleted file mode 100644 index 69b2e16..0000000 --- a/src/main/java/org/openecomp/crud/util/CrudProperties.java +++ /dev/null @@ -1,77 +0,0 @@ -/** - * ============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.util; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.Properties; - -public class CrudProperties { - - private static Properties properties; - - static { - properties = new Properties(); - File file = new File(CrudServiceConstants.CRD_CONFIG_FILE); - try { - properties.load(new FileInputStream(file)); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - public static String get(String key) { - return properties.getProperty(key); - } - - public static String get(String key, String defaultValue) { - return properties.getProperty(key, defaultValue); - } - - public static void put(String key, String value) { - properties.setProperty(key, value); - FileOutputStream fileOut = null; - try { - fileOut = new FileOutputStream(new File(CrudServiceConstants.CRD_CONFIG_FILE)); - properties.store(fileOut, "Added property: " + key); - } catch (Exception e) { - e.printStackTrace(); - } finally { - - try { - fileOut.close(); - } catch (IOException ex) { - ex.printStackTrace(); - } - } - - } - - -} diff --git a/src/main/java/org/openecomp/crud/util/CrudServiceConstants.java b/src/main/java/org/openecomp/crud/util/CrudServiceConstants.java deleted file mode 100644 index 1a4858f..0000000 --- a/src/main/java/org/openecomp/crud/util/CrudServiceConstants.java +++ /dev/null @@ -1,54 +0,0 @@ -/** - * ============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.util; - -public class CrudServiceConstants { - public static final String CRD_SERVICE_NAME = "Crud-Service"; - - public static final String CRD_FILESEP = (System.getProperty("file.separator") == null) ? "/" - : System.getProperty("file.separator"); - - public static final String CRD_SPECIFIC_CONFIG = System.getProperty("CONFIG_HOME") + CRD_FILESEP; - - public static final String CRD_HOME_MODEL = CRD_SPECIFIC_CONFIG + "model" + CRD_FILESEP; - public static final String CRD_HOME_AUTH = CRD_SPECIFIC_CONFIG + "auth" + CRD_FILESEP; - - public static final String CRD_GRAPH_HOST = "crud.graph.host"; - public static final String CRD_GRAPH_PORT = "crud.graph.port"; - public static final String CRD_GRAPH_NAME = "crud.graph.name"; - public static final String CRD_STORAGE_BACKEND_DB = "crud.storage.backend.db"; - public static final String CRD_HBASE_ZNODE_PARENT - = "crud.storage.hbase.ext.zookeeper.znode.parent"; - - 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"; - - public static final String CRD_EVENT_STREAM_HOSTS = "event.stream.hosts"; - - - -} diff --git a/src/main/java/org/openecomp/crud/util/CrudServiceUtil.java b/src/main/java/org/openecomp/crud/util/CrudServiceUtil.java deleted file mode 100644 index b88f20b..0000000 --- a/src/main/java/org/openecomp/crud/util/CrudServiceUtil.java +++ /dev/null @@ -1,63 +0,0 @@ -/** - * ============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.util; - -import org.openecomp.crud.exception.CrudException; - -import javax.ws.rs.core.Response.Status; - -public class CrudServiceUtil { - - - public static Object validateFieldType(String value, Class clazz) throws CrudException { - try { - if (clazz.isAssignableFrom(Integer.class)) { - return Integer.parseInt(value); - } else if (clazz.isAssignableFrom(Long.class)) { - return Long.parseLong(value); - } else if (clazz.isAssignableFrom(Float.class)) { - return Float.parseFloat(value); - } else if (clazz.isAssignableFrom(Double.class)) { - return Double.parseDouble(value); - } else if (clazz.isAssignableFrom(Boolean.class)) { - - // If the value is an IN/OUT direction, this gets seen as a boolean, so - // check for that first. - if (value.equals("OUT") || value.equals("IN")) { - return value; - } - - if (!value.equals("true") && !value.equals("false")) { - throw new CrudException("Invalid propertry value: " + value, Status.BAD_REQUEST); - } - return Boolean.parseBoolean(value); - } else { - return value; - } - } catch (Exception e) { - throw new CrudException("Invalid property value: " + value, Status.BAD_REQUEST); - } - } - -} diff --git a/src/main/java/org/openecomp/crud/util/FileWatcher.java b/src/main/java/org/openecomp/crud/util/FileWatcher.java deleted file mode 100644 index 8c7cbc1..0000000 --- a/src/main/java/org/openecomp/crud/util/FileWatcher.java +++ /dev/null @@ -1,48 +0,0 @@ -/** - * ============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.util; - -import java.io.File; -import java.util.TimerTask; - -public abstract class FileWatcher extends TimerTask { - private long timeStamp; - private File file; - - public FileWatcher(File file) { - this.file = file; - this.timeStamp = file.lastModified(); - } - - public final void run() { - long timeStamp = file.lastModified(); - - if ((timeStamp - this.timeStamp) > 500) { - this.timeStamp = timeStamp; - onChange(file); - } - } - - protected abstract void onChange(File file); -} \ No newline at end of file diff --git a/src/main/java/org/openecomp/schema/OxmModelValidator.java b/src/main/java/org/openecomp/schema/OxmModelValidator.java deleted file mode 100644 index 79136e4..0000000 --- a/src/main/java/org/openecomp/schema/OxmModelValidator.java +++ /dev/null @@ -1,331 +0,0 @@ -/** - * ============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.schema; - -import com.google.common.base.CaseFormat; -import com.google.gson.JsonElement; -import com.google.gson.JsonNull; - -import org.eclipse.persistence.dynamic.DynamicType; -import org.eclipse.persistence.internal.helper.DatabaseField; -import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext; -import org.eclipse.persistence.mappings.DatabaseMapping; -import org.eclipse.persistence.oxm.XMLField; -import org.onap.aaiutils.oxm.OxmModelLoader; -import org.openecomp.crud.entity.Vertex; -import org.openecomp.crud.exception.CrudException; -import org.openecomp.crud.util.CrudServiceUtil; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import javax.ws.rs.core.Response.Status; - -public class OxmModelValidator { - public enum Metadata { - NODE_TYPE("aai-node-type"), URI("aai-uri"), CREATED_TS("aai-created-ts"), SOT("source-of-truth"), LAST_MOD_SOT( - "last-mod-source-of-truth"); - - private final String propName; - - Metadata(String propName) { - this.propName = propName; - } - - public String propertyName() { - return propName; - } - - public static boolean isProperty(String property) { - for (Metadata meta : Metadata.values()) { - if (meta.propName.equals(property)) { - return true; - } - } - return false; - } - } - - public static Map resolveCollectionfilter(String version, String type, Map filter) - throws CrudException { - - DynamicJAXBContext jaxbContext = null; - try { - jaxbContext = OxmModelLoader.getContextForVersion(version); - } catch (Exception e) { - throw new CrudException(e); - } - - Map result = new HashMap(); - if (jaxbContext == null) { - throw new CrudException("", Status.NOT_FOUND); - } - final DynamicType modelObjectType = jaxbContext.getDynamicType( - CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, type))); - - for (String key : filter.keySet()) { - String keyJavaName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL, key); - if (modelObjectType.getDescriptor().getMappingForAttributeName(keyJavaName) != null) { - try { - DatabaseMapping mapping = modelObjectType.getDescriptor().getMappingForAttributeName(keyJavaName); - Object value = CrudServiceUtil.validateFieldType(filter.get(key), mapping.getField().getType()); - result.put(key, value); - } catch (Exception ex) { - // Skip any exceptions thrown while validating the filter - // key value - continue; - } - } - } - - return result; - - } - - public static String resolveCollectionType(String version, String type) throws CrudException { - - DynamicJAXBContext jaxbContext = null; - try { - jaxbContext = OxmModelLoader.getContextForVersion(version); - } catch (Exception e) { - throw new CrudException(e); - } - - if (jaxbContext == null) { - throw new CrudException("", Status.NOT_FOUND); - } - // Determine if the Object part is a collection type in the model - // definition - final DynamicType modelObjectType = jaxbContext.getDynamicType( - CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, type))); - - if (modelObjectType == null) { - throw new CrudException("", Status.NOT_FOUND); - } - - if (modelObjectType.getDescriptor().getMappings().size() == 1 - && modelObjectType.getDescriptor().getMappings().get(0).isCollectionMapping()) { - String childJavaObjectName = modelObjectType.getDescriptor().getMappings().get(0).getAttributeName(); - childJavaObjectName = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, childJavaObjectName); - final DynamicType childObjectType = jaxbContext.getDynamicType(childJavaObjectName); - if (childObjectType == null) { - // Should not happen as child object is defined in oxm model - // itself - throw new CrudException("", Status.NOT_FOUND); - } - return childObjectType.getDescriptor().getTableName(); - } else { - return modelObjectType.getDescriptor().getTableName(); - } - - } - - public static Vertex validateIncomingUpsertPayload(String id, String version, String type, JsonElement properties) - throws CrudException { - - try { - type = resolveCollectionType(version, type); - DynamicJAXBContext jaxbContext = OxmModelLoader.getContextForVersion(version); - String modelObjectClass = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, - CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, type)); - - final DynamicType modelObjectType = jaxbContext.getDynamicType(modelObjectClass); - final DynamicType reservedType = jaxbContext.getDynamicType("ReservedPropNames"); - - Set> payloadEntriesSet = properties.getAsJsonObject().entrySet(); - - // loop through input to validate against schema - for (Map.Entry entry : payloadEntriesSet) { - String keyJavaName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL, entry.getKey()); - - // check for valid field - if (modelObjectType.getDescriptor().getMappingForAttributeName(keyJavaName) == null) { - if (reservedType.getDescriptor().getMappingForAttributeName(keyJavaName) == null) { - throw new CrudException("Invalid field: " + entry.getKey(), Status.BAD_REQUEST); - } - } - - } - - Map entriesMap = new HashMap(); - for (Map.Entry entry : payloadEntriesSet) { - entriesMap.put(entry.getKey(), entry.getValue()); - } - - Vertex.Builder modelVertexBuilder = new Vertex.Builder(type); - if (id != null) { - modelVertexBuilder.id(id); - } - for (DatabaseMapping mapping : modelObjectType.getDescriptor().getMappings()) { - if (mapping.isAbstractDirectMapping()) { - DatabaseField field = mapping.getField(); - String defaultValue = mapping.getProperties().get("defaultValue") == null ? "" - : mapping.getProperties().get("defaultValue").toString(); - - String keyName = field.getName().substring(0, field.getName().indexOf("/")); - - if (((XMLField) field).isRequired() && !entriesMap.containsKey(keyName) && !defaultValue.isEmpty()) { - modelVertexBuilder.property(keyName, CrudServiceUtil.validateFieldType(defaultValue, field.getType())); - } - // if schema field is required and not set then reject - if (((XMLField) field).isRequired() && !entriesMap.containsKey(keyName) && defaultValue.isEmpty()) { - throw new CrudException("Missing required field: " + keyName, Status.BAD_REQUEST); - } - // If invalid field then reject - if (entriesMap.containsKey(keyName)) { - Object value = CrudServiceUtil.validateFieldType(entriesMap.get(keyName).getAsString(), field.getType()); - modelVertexBuilder.property(keyName, value); - } - - // Set defaults - if (!defaultValue.isEmpty() && !entriesMap.containsKey(keyName)) { - modelVertexBuilder.property(keyName, CrudServiceUtil.validateFieldType(defaultValue, field.getType())); - } - } - } - - // 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) { - throw new CrudException(e.getMessage(), Status.BAD_REQUEST); - } - } - - public static Vertex validateIncomingPatchPayload(String id, String version, String type, JsonElement properties, - Vertex existingVertex) throws CrudException { - - try { - type = resolveCollectionType(version, type); - DynamicJAXBContext jaxbContext = OxmModelLoader.getContextForVersion(version); - String modelObjectClass = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, - CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, type)); - - final DynamicType modelObjectType = jaxbContext.getDynamicType(modelObjectClass); - final DynamicType reservedType = jaxbContext.getDynamicType("ReservedPropNames"); - - Set> payloadEntriesSet = properties.getAsJsonObject().entrySet(); - - // Loop through the payload properties and merge with existing - // vertex props - for (Map.Entry entry : payloadEntriesSet) { - - String keyJavaName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL, entry.getKey()); - - 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); - } - - // check if mandatory field is not set to null - if (((XMLField) field).isRequired() && entry.getValue() instanceof JsonNull && !defaultValue.isEmpty()) { - existingVertex.getProperties().put(entry.getKey(), - CrudServiceUtil.validateFieldType(defaultValue, field.getType())); - } else if (((XMLField) field).isRequired() && entry.getValue() instanceof JsonNull && defaultValue.isEmpty()) { - throw new CrudException("Mandatory field: " + entry.getKey() + " can't be set to null", Status.BAD_REQUEST); - } else if (!((XMLField) field).isRequired() && entry.getValue() instanceof JsonNull - && existingVertex.getProperties().containsKey(entry.getKey())) { - existingVertex.getProperties().remove(entry.getKey()); - } else if (!(entry.getValue() instanceof JsonNull)) { - // add/update the value if found in existing vertex - Object value = CrudServiceUtil.validateFieldType(entry.getValue().getAsString(), field.getType()); - existingVertex.getProperties().put(entry.getKey(), value); - } - - } - - return existingVertex; - } catch (Exception e) { - throw new CrudException(e.getMessage(), Status.BAD_REQUEST); - } - - } - - private static DatabaseField getDatabaseField(String fieldName, DynamicType modelObjectType) { - for (DatabaseField field : modelObjectType.getDescriptor().getAllFields()) { - int ix = field.getName().indexOf("/"); - if (ix <= 0) { - ix = field.getName().length(); - } - - String keyName = field.getName().substring(0, ix); - if (fieldName.equals(keyName)) { - return field; - } - } - return null; - } - - public static Vertex validateOutgoingPayload(String version, Vertex vertex) { - - Vertex.Builder modelVertexBuilder = new Vertex.Builder(vertex.getType()).id(vertex.getId().get()); - - try { - DynamicJAXBContext jaxbContext = OxmModelLoader.getContextForVersion(version); - String modelObjectClass = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, - CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, - vertex.getProperties().get(Metadata.NODE_TYPE.propertyName()) != null - ? vertex.getProperties().get(Metadata.NODE_TYPE.propertyName()).toString() : vertex.getType())); - final DynamicType modelObjectType = jaxbContext.getDynamicType(modelObjectClass); - - for (String key : vertex.getProperties().keySet()) { - DatabaseField field = getDatabaseField(key, modelObjectType); - if (field != null) { - if (!Metadata.isProperty(key)) { - modelVertexBuilder.property(key, vertex.getProperties().get(key)); - } - } - } - return modelVertexBuilder.build(); - } catch (Exception ex) { - return vertex; - } - - } - -} diff --git a/src/main/java/org/openecomp/schema/RelationshipSchema.java b/src/main/java/org/openecomp/schema/RelationshipSchema.java deleted file mode 100644 index a8d101d..0000000 --- a/src/main/java/org/openecomp/schema/RelationshipSchema.java +++ /dev/null @@ -1,108 +0,0 @@ -/** - * ============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.schema; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import org.codehaus.jackson.map.ObjectMapper; -import org.openecomp.crud.exception.CrudException; - -import java.io.IOException; -import java.util.*; -import java.util.stream.Collectors; -import javax.ws.rs.core.Response.Status; - - -public class RelationshipSchema { - private static final Gson gson = new GsonBuilder().create(); - - public static final String SCHEMA_SOURCE_NODE_TYPE = "from"; - public static final String SCHEMA_TARGET_NODE_TYPE = "to"; - public static final String SCHEMA_RELATIONSHIP_TYPE = "label"; - public static final String SCHEMA_RULES_ARRAY = "rules"; - - - private Map>> relations = new HashMap<>(); - /** - * Hashmap of valid relationship types along with properties. - */ - private Map>> relationTypes = new HashMap<>(); - - - public RelationshipSchema(List jsonStrings) throws CrudException, IOException { - String edgeRules = jsonStrings.get(0); - String props = jsonStrings.get(1); - - HashMap>> rules = new ObjectMapper().readValue(edgeRules, HashMap.class); - HashMap properties = new ObjectMapper().readValue(props, HashMap.class); - Map> edgeProps = properties.entrySet().stream().collect(Collectors.toMap(p -> p.getKey(), p -> { - try { - return resolveClass(p.getValue()); - } catch (CrudException | ClassNotFoundException e) { - e.printStackTrace(); - } - return null; - })); - - rules.get(SCHEMA_RULES_ARRAY).forEach(l -> { - relationTypes.put(l.get(SCHEMA_RELATIONSHIP_TYPE), edgeProps); - relations.put(buildRelation(l.get(SCHEMA_SOURCE_NODE_TYPE), l.get(SCHEMA_TARGET_NODE_TYPE), l.get(SCHEMA_RELATIONSHIP_TYPE)), edgeProps); - }); - } - - - - public Map> lookupRelation(String key) { - return this.relations.get(key); - } - - public Map> lookupRelationType(String type) { - return this.relationTypes.get(type); - } - - public boolean isValidType(String type) { - return relationTypes.containsKey(type); - } - - - private String buildRelation(String source, String target, String relation){ - return source + ":" + target + ":" + relation; - } - - private Class resolveClass(String type) throws CrudException, ClassNotFoundException { - Class clazz = Class.forName(type); - validateClassTypes(clazz); - return clazz; - } - - private void validateClassTypes(Class clazz) throws CrudException { - if (!clazz.isAssignableFrom(Integer.class) && !clazz.isAssignableFrom(Double.class) - && !clazz.isAssignableFrom(Boolean.class) && !clazz.isAssignableFrom(String.class)) { - throw new CrudException("", Status.BAD_REQUEST); - } - } -} - - diff --git a/src/main/java/org/openecomp/schema/RelationshipSchemaLoader.java b/src/main/java/org/openecomp/schema/RelationshipSchemaLoader.java deleted file mode 100644 index cc6315c..0000000 --- a/src/main/java/org/openecomp/schema/RelationshipSchemaLoader.java +++ /dev/null @@ -1,263 +0,0 @@ -/** - * ============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.schema; - -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.Date; -import java.util.List; -import java.util.Map; -import java.util.SortedSet; -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 versionContextMap = new ConcurrentHashMap<>(); - private static SortedSet versions = new TreeSet(); - private static Map timers = new ConcurrentHashMap(); - final static String edgePropsFiles = "edge_properties_"; - final static String fileExt = ".json"; - final static Pattern rulesFilePattern = Pattern.compile("DbEdgeRules(.*)" + fileExt); - final static Pattern propsFilePattern = Pattern.compile(edgePropsFiles + "(.*)" + fileExt); - final static Pattern versionPattern = Pattern.compile(".*(v\\d+)" + fileExt); - - private static org.openecomp.cl.api.Logger logger = LoggerFactory.getInstance() - .getLogger(RelationshipSchemaLoader.class.getName()); - - public synchronized static void loadModels() throws CrudException { - load(rulesFilePattern, propsFilePattern); - } - - public synchronized static void loadModels(String version) throws CrudException { - String pattern = String.format(".*(%s)" + fileExt, version); - load(Pattern.compile(pattern), Pattern.compile(edgePropsFiles + version + fileExt)); - } - - public static RelationshipSchema getSchemaForVersion(String version) throws CrudException { - if (versionContextMap == null || versionContextMap.isEmpty()) { - loadModels(); - } else if (!versionContextMap.containsKey(version)) { - try { - loadModels(version); - } catch (Exception e) { - throw new CrudException("", Status.NOT_FOUND); - } - } - RelationshipSchema schema = versionContextMap.get(version); - if (schema == null) { - throw new CrudException("", Status.NOT_FOUND); - } else - return schema; - } - - public static String getLatestSchemaVersion() throws CrudException { - return "v" + versions.last(); - } - - public static Map getVersionContextMap() { - return versionContextMap; - } - - public static void setVersionContextMap(Map versionContextMap) { - RelationshipSchemaLoader.versionContextMap = versionContextMap; - } - - public static void resetVersionContextMap() { - RelationshipSchemaLoader.versionContextMap = new ConcurrentHashMap<>(); - } - - private static void load(Pattern rulesPattern, Pattern edgePropsPattern) throws CrudException { - ClassLoader cl = RelationshipSchemaLoader.class.getClassLoader(); - ResourcePatternResolver rulesResolver = new PathMatchingResourcePatternResolver(cl); - List rulesFiles; - String rulesDir = CrudServiceConstants.CRD_HOME_MODEL; - try { - - // getResources method returns objects of type "Resource" - // 1. We are getting all the objects from the classpath which has - // "DbEdgeRules" in the name. - // 2. We run them through a filter and return only the objects which match - // the supplied pattern "p" - // 3. We then collect the objects in a list. At this point we have a list - // of the kind of files we require. - rulesFiles = Arrays.stream(rulesResolver.getResources("classpath*:/dbedgerules/DbEdgeRules*" + fileExt)) - .filter(r -> !myMatcher(rulesPattern, r.getFilename()).isEmpty()).collect(Collectors.toList()); - - // This gets all the objects of type "File" from external directory (not - // on the classpath) - // 1. From an external directory (one not on the classpath) we get all the - // objects of type "File" - // 2. We only return the files whose names matched the supplied pattern - // "p2". - // 3. We then collect all the objects in a list and add the contents of - // this list - // to the previous collection (rulesFiles) - rulesFiles - .addAll(Arrays.stream(new File(rulesDir).listFiles((d, name) -> edgePropsPattern.matcher(name).matches())) - .collect(Collectors.toList())); - - if (rulesFiles.isEmpty()) { - logger.error(CrudServiceMsgs.INVALID_OXM_DIR, rulesDir); - throw new FileNotFoundException("DbEdgeRules and edge_properties files were not found."); - } - - // Sort and then group the files with their versions, convert them to the - // schema, and add them to versionContextMap - // 1. Sort the files. We need the DbEdgeRules files to be before the - // edgeProperties files. - // 2. Group the files with their versions. ie. v11 -> - // ["DbEdgeRule_v11.json", "edgeProperties_v11.json"]. - // The "group method" returns a HashMap whose key is the version and the - // value is a list of objects. - // 3. Go through each version and map the files into one schema using the - // "jsonFilesLoader" method. - // Also update the "versionContextMap" with the version and it's schema. - rulesFiles.stream().sorted(Comparator.comparing(RelationshipSchemaLoader::filename)) - .collect(Collectors.groupingBy(f -> myMatcher(versionPattern, filename(f)))) - .forEach((version, resourceAndFile) -> { - if (resourceAndFile.size() == 2) { - versionContextMap.put(version, jsonFilesLoader(version, resourceAndFile)); - } else { - String filenames = resourceAndFile.stream().map(f -> filename(f)).collect(Collectors.toList()).toString(); - 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); - throw new CrudException("DbEdgeRules or edge_properties files were not found.", new FileNotFoundException()); - } - } - - private static String filename(Object k) throws ClassCastException { - if (k instanceof UrlResource) { - return ((UrlResource) k).getFilename(); - } else if (k instanceof File) { - return ((File) k).getName(); - } else { - throw new ClassCastException(); - } - } - - private static RelationshipSchema jsonFilesLoader(String version, List files) { - List fileContents = new ArrayList<>(); - RelationshipSchema rsSchema = null; - if (files.size() == 2) { - for (Object file : files) { - fileContents.add(jsonToRelationSchema(version, file)); - versions.add(Integer.parseInt(version.substring(1))); - } - - try { - rsSchema = new RelationshipSchema(fileContents); - } catch (CrudException | IOException e) { - e.printStackTrace(); - logger.error(CrudServiceMsgs.INVALID_OXM_FILE, - files.stream().map(f -> filename(f)).collect(Collectors.toList()).toString(), e.getMessage()); - } - return rsSchema; - } - return rsSchema; - } - - private synchronized static void updateVersionContext(String version, RelationshipSchema rs) { - versionContextMap.put(version, rs); - } - - private synchronized static String jsonToRelationSchema(String version, Object file) { - InputStream inputStream = null; - String content = null; - - try { - if (file instanceof UrlResource) { - inputStream = ((UrlResource) file).getInputStream(); - } else { - inputStream = new FileInputStream((File) file); - addtimer(version, file); - } - content = IOUtils.toString(inputStream, "UTF-8"); - } catch (IOException e) { - e.printStackTrace(); - } - return content; - } - - private static void addtimer(String version, Object file) { - TimerTask task = null; - task = new FileWatcher((File) file) { - protected void onChange(File file) { - // here we implement the onChange - logger.info(CrudServiceMsgs.OXM_FILE_CHANGED, file.getName()); - - try { - // Cannot use the file object here because we also have to get the - // edge properties associated with that version. - // The properties are stored in a different file. - RelationshipSchemaLoader.loadModels(version); - } catch (Exception e) { - e.printStackTrace(); - } - } - }; - - if (!timers.containsKey(version)) { - Timer timer = new Timer("db_edge_rules_" + version); - timer.schedule(task, new Date(), 10000); - timers.put(version, timer); - - } - } - - private static String myMatcher(Pattern p, String s) { - Matcher m = p.matcher(s); - return m.matches() ? m.group(1) : ""; - } -} diff --git a/src/main/java/org/openecomp/schema/RelationshipSchemaValidator.java b/src/main/java/org/openecomp/schema/RelationshipSchemaValidator.java deleted file mode 100644 index e2374be..0000000 --- a/src/main/java/org/openecomp/schema/RelationshipSchemaValidator.java +++ /dev/null @@ -1,352 +0,0 @@ -/** - * ============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.schema; - -import com.google.gson.JsonElement; -import com.google.gson.JsonNull; - -import org.openecomp.crud.entity.Edge; -import org.openecomp.crud.entity.Vertex; -import org.openecomp.crud.exception.CrudException; -import org.openecomp.crud.service.EdgePayload; -import org.openecomp.crud.util.CrudServiceUtil; -import org.radeox.util.logging.Logger; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import javax.ws.rs.core.Response.Status; - -public class RelationshipSchemaValidator { - - public static final String SOURCE_NODE = "source"; - public static final String TARGET_NODE = "target"; - - final static Pattern urlPattern = Pattern.compile("services/inventory/(.*)/(.*)/(.*)"); - - public static Map resolveCollectionfilter(String version, String type, - Map filter) - throws CrudException { - - RelationshipSchema schema = RelationshipSchemaLoader.getSchemaForVersion(version); - if (schema == null) { - throw new CrudException("", Status.NOT_FOUND); - } - - Map> props = schema.lookupRelationType(type); - Map result = new HashMap(); - - for (String key : filter.keySet()) { - - if (props.containsKey(key)) { - try { - Object value = CrudServiceUtil.validateFieldType(filter.get(key), props.get(key)); - result.put(key, value); - } catch (Exception ex) { - // Skip any exceptions thrown while validating the filter - // key value - continue; - } - } - } - - return result; - - } - - public static void validateType(String version, String type) throws CrudException { - - RelationshipSchema schema = RelationshipSchemaLoader.getSchemaForVersion(version); - if (!schema.isValidType(type)) { - throw new CrudException("Invalid " + RelationshipSchema.SCHEMA_RELATIONSHIP_TYPE - + ": " + type, - Status.BAD_REQUEST); - } - - } - - public static Edge validateIncomingAddPayload(String version, String type, Vertex sourceNode, - Vertex targetNode, JsonElement properties) - throws CrudException { - EdgePayload payload = new EdgePayload(); - payload.setSource("services/inventory/" + version + "/" + sourceNode.getType() - + "/" + sourceNode.getId().get()); - payload.setTarget("services/inventory/" + version + "/" + targetNode.getType() - + "/" + targetNode.getId().get()); - payload.setType(type); - payload.setProperties(properties); - return validateIncomingAddPayload(version, type, payload); - } - - public static Edge validateIncomingAddPayload(String version, String type, EdgePayload payload) - throws CrudException { - RelationshipSchema schema = RelationshipSchemaLoader.getSchemaForVersion(version); - - try { - - if (payload.getSource() == null || payload.getTarget() == null) { - throw new CrudException("Source/Target not specified", Status.BAD_REQUEST); - } - - Matcher sourceMatcher = urlPattern.matcher(payload.getSource()); - Matcher targetMatcher = urlPattern.matcher(payload.getTarget()); - - if (!sourceMatcher.matches() || !targetMatcher.matches()) { - throw new CrudException("Invalid Source/Target Urls", Status.BAD_REQUEST); - } - - // create key based on source:target:relationshipType - String sourceNodeType = sourceMatcher.group(2); - String targetNodeType = targetMatcher.group(2); - - String sourceNodeId = sourceMatcher.group(3); - String targetNodeId = targetMatcher.group(3); - - String key = sourceNodeType + ":" + targetNodeType + ":" + type; - - // find the validate the key from the schema - Map> schemaObject = schema.lookupRelation(key); - - if (schemaObject == null) { - throw new CrudException("Invalid source/target/relationship type: " + key, - Status.BAD_REQUEST); - } - - Edge.Builder modelEdgeBuilder = new Edge.Builder(type); - - modelEdgeBuilder.source(new Vertex.Builder(sourceNodeType).id(sourceNodeId).build()); - modelEdgeBuilder.target(new Vertex.Builder(targetNodeType).id(targetNodeId).build()); - - // validate it properties - validateEdgeProps(modelEdgeBuilder, payload.getProperties(), schemaObject); - - return modelEdgeBuilder.build(); - } catch (Exception ex) { - - throw new CrudException(ex.getMessage(), Status.BAD_REQUEST); - } - - } - - public static Edge validateIncomingPatchPayload(Edge edge, String version, EdgePayload payload) - throws CrudException { - RelationshipSchema schema = RelationshipSchemaLoader.getSchemaForVersion(version); - - try { - if (payload.getSource() != null) { - Matcher sourceMatcher = urlPattern.matcher(payload.getSource()); - - if (!sourceMatcher.matches()) { - throw new CrudException("Invalid Target Urls", Status.BAD_REQUEST); - } - String sourceNodeId = sourceMatcher.group(3); - if (!sourceNodeId.equals(edge.getSource().getId().get())) { - throw new CrudException("Source can't be updated", Status.BAD_REQUEST); - } - } - - if (payload.getTarget() != null) { - Matcher targetMatcher = urlPattern.matcher(payload.getTarget()); - - if (!targetMatcher.matches()) { - throw new CrudException("Invalid Target Urls", Status.BAD_REQUEST); - } - String sourceNodeId = targetMatcher.group(3); - if (!sourceNodeId.equals(edge.getTarget().getId().get())) { - throw new CrudException("Target can't be updated", Status.BAD_REQUEST); - } - } - // create key based on source:target:relationshipType - - String key = edge.getSource().getType() + ":" + edge.getTarget().getType() - + ":" + edge.getType(); - - // find the validate the key from the schema - Map> schemaObject = schema.lookupRelation(key); - - if (schemaObject == null) { - Logger.warn("key :" + key - + " not found in relationship schema . Skipping the schema validation"); - return edge; - } - - Set> entries = payload.getProperties() - .getAsJsonObject().entrySet(); - - for (Map.Entry entry : entries) { - - if (!schemaObject.containsKey(entry.getKey())) { - throw new CrudException("Invalid property: " + entry.getKey(), Status.BAD_REQUEST); - } else if (entry.getValue() instanceof JsonNull && edge.getProperties() - .containsKey(entry.getKey())) { - edge.getProperties().remove(entry.getKey()); - } else if (!(entry.getValue() instanceof JsonNull)) { - Object value = CrudServiceUtil.validateFieldType(entry.getValue().getAsString(), - schemaObject.get(entry.getKey())); - edge.getProperties().put(entry.getKey(), value); - } - - } - - return edge; - - } catch (Exception ex) { - - throw new CrudException(ex.getMessage(), Status.BAD_REQUEST); - } - } - - public static Edge validateIncomingUpdatePayload(Edge edge, String version, Vertex sourceNode, - Vertex targetNode, JsonElement properties) - throws CrudException { - EdgePayload payload = new EdgePayload(); - payload.setSource("services/inventory/" + version + "/" + sourceNode.getType() - + "/" + sourceNode.getId().get()); - payload.setTarget("services/inventory/" + version + "/" + targetNode.getType() - + "/" + targetNode.getId().get()); - payload.setType(edge.getType()); - payload.setProperties(properties); - return validateIncomingUpdatePayload(edge, version, payload); - } - - public static Edge validateIncomingUpdatePayload(Edge edge, String version, EdgePayload payload) - throws CrudException { - RelationshipSchema schema = RelationshipSchemaLoader.getSchemaForVersion(version); - - try { - - if (payload.getSource() != null) { - Matcher sourceMatcher = urlPattern.matcher(payload.getSource()); - - if (!sourceMatcher.matches()) { - throw new CrudException("Invalid Target Urls", Status.BAD_REQUEST); - } - String sourceNodeId = sourceMatcher.group(3); - if (!sourceNodeId.equals(edge.getSource().getId().get())) { - throw new CrudException("Source can't be updated", Status.BAD_REQUEST); - } - } - - if (payload.getTarget() != null) { - Matcher targetMatcher = urlPattern.matcher(payload.getTarget()); - - if (!targetMatcher.matches()) { - throw new CrudException("Invalid Target Urls", Status.BAD_REQUEST); - } - String sourceNodeId = targetMatcher.group(3); - if (!sourceNodeId.equals(edge.getTarget().getId().get())) { - throw new CrudException("Target can't be updated", Status.BAD_REQUEST); - } - } - // create key based on source:target:relationshipType - - String key = edge.getSource().getType() + ":" + edge.getTarget().getType() - + ":" + edge.getType(); - - // find the validate the key from the schema - Map> schemaObject = schema.lookupRelation(key); - - if (schemaObject == null) { - Logger.warn("key :" + key - + " not found in relationship schema . Skipping the schema validation"); - return edge; - } - - Edge.Builder updatedEdgeBuilder = new Edge.Builder(edge.getType()).id(edge.getId().get()); - - updatedEdgeBuilder - .source(new Vertex.Builder(edge.getSource().getType()).id(edge.getSource().getId() - .get()).build()); - updatedEdgeBuilder - .target(new Vertex.Builder(edge.getTarget().getType()).id(edge.getTarget().getId() - .get()).build()); - - validateEdgeProps(updatedEdgeBuilder, payload.getProperties(), schemaObject); - - return updatedEdgeBuilder.build(); - } catch (Exception ex) { - - throw new CrudException(ex.getMessage(), Status.BAD_REQUEST); - } - } - - - private static void validateEdgeProps(Edge.Builder builder, JsonElement props, - Map> schemaObject) - throws CrudException { - Set> entries = props.getAsJsonObject().entrySet(); - - for (Map.Entry entry : entries) { - - if (!schemaObject.containsKey(entry.getKey())) { - throw new CrudException("Invalid property: " + entry.getKey(), Status.BAD_REQUEST); - } else { - Object value = CrudServiceUtil.validateFieldType(entry.getValue().getAsString(), - schemaObject.get(entry.getKey())); - builder.property(entry.getKey(), value); - } - - } - - } - - public static Edge validateOutgoingPayload(String version, Edge edge) throws CrudException { - - Edge.Builder modelEdgeBuilder = new Edge.Builder(edge.getType()).id(edge.getId() - .get()).source(edge.getSource()) - .target(edge.getTarget()); - - RelationshipSchema schema = RelationshipSchemaLoader.getSchemaForVersion(version); - - String key = edge.getSource().getType() + ":" + edge.getTarget().getType() - + ":" + edge.getType(); - Map> schemaObject = schema.lookupRelation(key); - - if (schemaObject == null || schemaObject.isEmpty()) { - return edge; - } - - for (String prop : edge.getProperties().keySet()) { - if (schemaObject.containsKey(prop)) { - modelEdgeBuilder.property(prop, edge.getProperties().get(prop)); - } - - } - return modelEdgeBuilder.build(); - } - - - public static String vertexTypeFromUri(String uri) throws CrudException { - - Matcher matcher = urlPattern.matcher(uri); - - if (!matcher.matches()) { - throw new CrudException("Invalid Source/Target Urls", Status.BAD_REQUEST); - } - - return matcher.group(2); - } -} -- cgit 1.2.3-korg