2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright © 2017 AT&T Intellectual Property.
6 * Copyright © 2017 Amdocs
8 * ================================================================================
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 * ============LICENSE_END=========================================================
22 * ECOMP is a trademark and service mark of AT&T Intellectual Property.
24 package org.onap.crud.dao.champ;
26 import java.util.ArrayList;
27 import java.util.List;
29 import java.util.Optional;
30 import java.util.concurrent.ConcurrentHashMap;
31 import java.util.stream.Collectors;
32 import java.util.stream.Stream;
34 import org.onap.aai.champcore.ChampGraph;
35 import org.onap.aai.champcore.ChampTransaction;
36 import org.onap.aai.champcore.exceptions.ChampMarshallingException;
37 import org.onap.aai.champcore.exceptions.ChampObjectNotExistsException;
38 import org.onap.aai.champcore.exceptions.ChampRelationshipNotExistsException;
39 import org.onap.aai.champcore.exceptions.ChampSchemaViolationException;
40 import org.onap.aai.champcore.exceptions.ChampTransactionException;
41 import org.onap.aai.champcore.exceptions.ChampUnmarshallingException;
42 import org.onap.aai.champcore.model.ChampObject;
43 import org.onap.aai.champcore.model.ChampRelationship;
44 import org.onap.aai.champcore.model.fluent.object.ObjectBuildOrPropertiesStep;
45 import org.onap.aai.cl.api.Logger;
46 import org.onap.aai.cl.eelf.LoggerFactory;
47 import org.onap.crud.dao.GraphDao;
48 import org.onap.crud.entity.Edge;
49 import org.onap.crud.entity.Vertex;
50 import org.onap.crud.exception.CrudException;
51 import org.onap.crud.logging.CrudServiceMsgs;
54 * This is the integration layer between the CRUD API service and the low level
55 * Champ library for graph database interaction.
57 public class ChampDao implements GraphDao {
59 public static final String CONFIG_STORAGE_BACKEND = "storage.backend";
60 public static final String CONFIG_STORAGE_BACKEND_DB = "storage.backend.db";
61 public static final String STORAGE_HBASE_DB = "hbase";
62 public static final String STORAGE_CASSANDRA_DB = "cassandra";
63 public static final String CONFIG_STORAGE_HOSTNAMES = "storage.hostnames";
64 public static final String CONFIG_STORAGE_PORT = "storage.port";
65 public static final String CONFIG_HBASE_ZNODE_PARENT = "storage.hbase.ext.zookeeper.znode.parent";
66 public static final String CONFIG_GRAPH_NAME = "graph.name";
67 public static final String GRAPH_UNQ_INSTANCE_ID_SUFFIX = "graph.unique-instance-id-suffix";
69 public static final String CONFIG_EVENT_STREAM_PUBLISHER = "event.stream.publisher";
70 public static final String CONFIG_EVENT_STREAM_NUM_PUBLISHERS = "event.stream.num-publishers";
72 private static Map<String, ChampTransaction> transactions = new ConcurrentHashMap<String, ChampTransaction>();
73 public static final String DEFAULT_GRAPH_NAME = "default_graph";
75 private enum GraphType {
80 * Instance of the API used for interacting with the Champ library.
82 private ChampGraph champApi = null;
84 private Logger logger = LoggerFactory.getInstance().getLogger(ChampDao.class.getName());
87 * Creates a new instance of the ChampDao.
90 * - Concrete implementation of the graph dao layer
92 public ChampDao(ChampGraph champGraph) {
93 this.champApi = champGraph;
97 public Vertex getVertex(String id) throws CrudException {
101 if (logger.isDebugEnabled()) {
102 logger.debug("getVertex with id: " + id);
105 long idAsLong = Long.parseLong(id);
107 Optional<ChampObject> retrievedVertex = champApi.retrieveObject(idAsLong);
109 String nodeType = org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName();
110 if (retrievedVertex.isPresent() && retrievedVertex.get().getProperties().get(nodeType) != null) {
111 return vertexFromChampObject(retrievedVertex.get(),
112 retrievedVertex.get().getProperties().get(nodeType).toString());
115 // We didn't find a vertex with the supplied id, so just throw an
117 throw new CrudException("No vertex with id " + id + " found in graph",
118 javax.ws.rs.core.Response.Status.NOT_FOUND);
121 } catch (ChampUnmarshallingException | ChampTransactionException e) {
123 // Something went wrong - throw an exception.
124 throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
129 public Vertex getVertex(String id, String type) throws CrudException {
133 if (logger.isDebugEnabled()) {
134 logger.debug("getVertex with id: " + id);
137 long idAsLong = Long.parseLong(id);
139 // Request the vertex from the graph db.
140 Optional<ChampObject> retrievedVertex = champApi.retrieveObject(idAsLong);
143 if (retrievedVertex.isPresent()
144 && retrievedVertex.get().getProperties()
145 .get(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName()) != null
146 && retrievedVertex.get().getProperties()
147 .get(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName()).toString()
148 .equalsIgnoreCase(type)) {
150 // Yup, convert it to a Vector object and return it.
151 return vertexFromChampObject(retrievedVertex.get(), type);
155 // We didn't find a vertex with the supplied id, so just throw an
157 throw new CrudException("No vertex with id " + id + " found in graph",
158 javax.ws.rs.core.Response.Status.NOT_FOUND);
161 } catch (ChampUnmarshallingException | ChampTransactionException e) {
163 // Something went wrong - throw an exception.
164 throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
169 public List<Edge> getVertexEdges(String id) throws CrudException {
171 if (logger.isDebugEnabled()) {
172 logger.debug("get Edges incident to vertex with id: " + id + " from graph");
176 long idAsLong = Long.parseLong(id); // GDF - what to do about id???
178 // Request the vertex from the graph db.
179 Optional<ChampObject> retrievedVertex = champApi.retrieveObject(idAsLong);
182 if (retrievedVertex.isPresent()) {
184 // Query the Champ library for the edges which are incident to the
187 Stream<ChampRelationship> relationships = champApi.retrieveRelationships(retrievedVertex.get());
189 // Build an edge list from the result stream.
190 List<Edge> edges = new ArrayList<Edge>();
191 relationships.forEach(r -> edges.add(edgeFromChampRelationship(r)));
197 // We couldn't find the specified vertex, so throw an exception.
198 throw new CrudException("No vertex with id " + id + " found in graph",
199 javax.ws.rs.core.Response.Status.NOT_FOUND);
202 } catch (ChampUnmarshallingException e) {
204 // Something went wrong, so throw an exception.
205 throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
207 } catch (ChampObjectNotExistsException e) {
209 // We couldn't find the specified vertex, so throw an exception.
210 throw new CrudException("No vertex with id " + id + " found in graph",
211 javax.ws.rs.core.Response.Status.NOT_FOUND);
212 } catch (ChampTransactionException e) {
213 throw new CrudException("Transaction error occured", javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
218 public Vertex addVertex(String type, Map<String, Object> properties) throws CrudException {
220 if (logger.isDebugEnabled()) {
221 logger.debug("Add/update vertex: {label: " + type + " properties:" + propertiesMapToString(properties));
224 // Add the aai_node_type so that AAI can read the data created by gizmo
225 properties.put(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type);
227 // Create an object to represent our vertex in the format expected by the
229 ChampObject objectToCreate = buildChampObject(type, properties);
233 // Ask the Champ library to store our vertex, placing the returned object
235 // list so that we can easily put that into our result object.
236 return vertexFromChampObject(champApi.storeObject(objectToCreate), type);
238 } catch (ChampMarshallingException | ChampSchemaViolationException | ChampObjectNotExistsException
239 | ChampTransactionException e) {
241 // Something went wrong - throw an exception.
242 throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
247 public Vertex updateVertex(String id, String type, Map<String, Object> properties) throws CrudException {
249 if (logger.isDebugEnabled()) {
250 logger.debug("Update vertex with id: " + id + " with properties: " + propertiesMapToString(properties));
252 // Add the aai_node_type so that AAI can read the data created by gizmo
253 properties.put(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type);
256 // Now, build the updated version of the Champ Object...
257 ChampObject updateObject = buildChampObject(id, type, properties);
258 // ...and send it to the Champ library.
259 return vertexFromChampObject(champApi.replaceObject(updateObject), type);
261 } catch (ChampObjectNotExistsException e) {
262 throw new CrudException("Not Found", javax.ws.rs.core.Response.Status.NOT_FOUND);
263 } catch (NumberFormatException | ChampMarshallingException | ChampSchemaViolationException e) {
264 throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
265 } catch (ChampTransactionException e) {
266 throw new CrudException("Transaction error occured", javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
272 public List<Vertex> getVertices(String type, Map<String, Object> filter) throws CrudException {
274 if (logger.isDebugEnabled()) {
275 logger.debug("Retrieve vertices with type label: " + type + " which map query parameters: "
276 + propertiesMapToString(filter));
279 filter.put(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type);
281 Stream<ChampObject> retrievedVertices;
283 retrievedVertices = champApi.queryObjects(filter);
285 } catch (ChampTransactionException e) {
286 throw new CrudException("Transaction error occured", javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
289 List<Vertex> vertices = retrievedVertices.map(v -> vertexFromChampObject(v, type)).collect(Collectors.toList());
291 if (logger.isDebugEnabled()) {
292 logger.debug("Resulting vertex list: " + retrievedVertices);
295 // ...and return it to the caller.
299 private Object getRelKey(String id) {
301 // convert into Long if applicable . TODO : revisit in story NUC-304
303 key = Long.parseLong(id);
304 } catch (NumberFormatException e) {
305 // The id isn't a Long, leave it as a string
312 public Edge getEdge(String id, String type) throws CrudException {
314 if (logger.isDebugEnabled()) {
315 logger.debug("Get edge with id: " + id);
320 // Request the edge from the graph db.
321 Optional<ChampRelationship> relationship = champApi.retrieveRelationship(getRelKey(id));
324 if (relationship.isPresent() && relationship.get().getType().equals(type)) {
326 // Yup - return the result.
327 return edgeFromChampRelationship(relationship.get());
331 // We didn't find an edge with the supplied id, so throw an exception.
332 throw new CrudException("No edge with id " + id + " found in graph",
333 javax.ws.rs.core.Response.Status.NOT_FOUND);
336 } catch (ChampUnmarshallingException | ChampTransactionException e) {
338 // Something went wrong, so throw an exception.
339 throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
344 public Edge addEdge(String type, Vertex source, Vertex target, Map<String, Object> properties) throws CrudException {
346 // For now, assume source and target are straight ids...
349 Optional<ChampObject> sourceObject = champApi.retrieveObject(Long.parseLong(source.getId().get()));
350 if (!sourceObject.isPresent() || !sourceObject.get().getType().equals(source.getType())) {
351 throw new CrudException(
352 "Error creating edge - source vertex with id " + source + " does not exist in graph data base",
353 javax.ws.rs.core.Response.Status.BAD_REQUEST);
356 Optional<ChampObject> targetObject = champApi.retrieveObject(Long.parseLong(target.getId().get()));
357 if (!targetObject.isPresent() || !targetObject.get().getType().equals(target.getType())) {
358 throw new CrudException(
359 "Error creating edge - target vertex with id " + target + " does not exist in graph data base",
360 javax.ws.rs.core.Response.Status.BAD_REQUEST);
363 // Now, create the ChampRelationship object for our edge and store it in
364 // the graph database.
365 return edgeFromChampRelationship(champApi.storeRelationship(
366 new ChampRelationship.Builder(sourceObject.get(), targetObject.get(), type).properties(properties).build()));
368 } catch (ChampMarshallingException | ChampObjectNotExistsException | ChampSchemaViolationException
369 | ChampRelationshipNotExistsException | ChampUnmarshallingException | NumberFormatException
370 | ChampTransactionException e) {
372 throw new CrudException("Error creating edge: " + e.getMessage(),
373 javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
378 public List<Edge> getEdges(String type, Map<String, Object> filter) throws CrudException {
380 filter.put(ChampRelationship.ReservedPropertyKeys.CHAMP_RELATIONSHIP_TYPE.toString(), type);
382 Stream<ChampRelationship> retrievedRelationships;
384 retrievedRelationships = champApi.queryRelationships(filter);
386 } catch (ChampTransactionException e) {
387 throw new CrudException("Transaction error occured", javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
390 // Process the result stream from the Champ library into an Edge list,
392 // edges of the specified type.
393 List<Edge> edges = retrievedRelationships.map(r -> edgeFromChampRelationship(r)).collect(Collectors.toList());
399 public Edge updateEdge(Edge edge) throws CrudException {
401 if (logger.isDebugEnabled()) {
403 "Update edge with id: " + edge.getId() + " with properties: " + propertiesMapToString(edge.getProperties()));
407 // Now, build the updated version of the Champ Relationship...
408 ChampRelationship updateRelationship = new ChampRelationship.Builder(
409 buildChampObject(edge.getSource().getId().get(), edge.getSource().getType(),
410 edge.getSource().getProperties()),
411 buildChampObject(edge.getTarget().getId().get(), edge.getTarget().getType(),
412 edge.getTarget().getProperties()),
413 edge.getType()).key(getRelKey(edge.getId().get())).properties(edge.getProperties()).build();
414 // ...and send it to the Champ library.
415 return edgeFromChampRelationship(champApi.replaceRelationship(updateRelationship));
417 } catch (ChampRelationshipNotExistsException ex) {
418 throw new CrudException("Not Found", javax.ws.rs.core.Response.Status.NOT_FOUND);
419 } catch (NumberFormatException | ChampUnmarshallingException | ChampMarshallingException
420 | ChampSchemaViolationException | ChampTransactionException ex) {
422 throw new CrudException(ex.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
427 public void deleteVertex(String id, String type) throws CrudException {
431 // First, retrieve the vertex that we intend to delete.
432 Optional<ChampObject> retrievedVertex = champApi.retrieveObject(Long.parseLong(id));
435 if (!retrievedVertex.isPresent() || !retrievedVertex.get().getType().equals(type)) {
436 throw new CrudException("Failed to delete vertex with id: " + id + " - vertex does not exist.",
437 javax.ws.rs.core.Response.Status.NOT_FOUND);
440 // Now, verify that there are no edges incident to the vertex (they must
443 Stream<ChampRelationship> relationships = champApi.retrieveRelationships(retrievedVertex.get());
445 if (relationships.count() > 0) {
446 throw new CrudException("Attempt to delete vertex with id " + id + " which has incident edges.",
447 javax.ws.rs.core.Response.Status.BAD_REQUEST);
450 // Finally, we can attempt to delete our vertex.
451 champApi.deleteObject(Long.parseLong(id));
453 } catch (NumberFormatException | ChampUnmarshallingException | ChampObjectNotExistsException
454 | ChampTransactionException e) {
456 throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
461 public void deleteEdge(String id, String type) throws CrudException {
465 // First, retrieve the edge that we want to delete.
466 Optional<ChampRelationship> relationshipToDelete = champApi.retrieveRelationship(getRelKey(id));
469 if (!relationshipToDelete.isPresent() || !relationshipToDelete.get().getType().equals(type)) {
470 throw new CrudException("Failed to delete edge with id: " + id + " - edge does not exist",
471 javax.ws.rs.core.Response.Status.NOT_FOUND);
474 // Now we can delete the edge.
475 champApi.deleteRelationship(relationshipToDelete.get());
477 } catch (ChampRelationshipNotExistsException | NumberFormatException | ChampUnmarshallingException
478 | ChampTransactionException e) {
480 throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
485 * This helper method generates a string representation of a properties map
486 * for logging purposes.
489 * - The properties map to be converted.
490 * @return - The log statement friendly conversion of the properties map.
492 private String propertiesMapToString(Map<String, Object> properties) {
494 StringBuilder sb = new StringBuilder();
497 for (String key : properties.keySet()) {
498 sb.append("(").append(key).append(" -> ").append(properties.get(key)).append(") ");
503 return sb.toString();
507 * This helper method constructs a {@link ChampObject} suitable for passing to
511 * - The type to assign to our ChampObject
513 * - The set of properties to assign to our ChampObject
514 * @return - A populated ChampObject
516 private ChampObject buildChampObject(String type, Map<String, Object> properties) {
518 ObjectBuildOrPropertiesStep objectInProgress = ChampObject.create().ofType(type).withoutKey();
520 for (String key : properties.keySet()) {
521 objectInProgress.withProperty(key, properties.get(key));
523 return objectInProgress.build();
527 * This helper method constructs a {@link ChampObject} suitable for passing to
531 * - Unique identifier for this object.
533 * - The type to assign to our ChampObject
535 * - The set of properties to assign to our ChampObject
536 * @return - A populated ChampObject
538 private ChampObject buildChampObject(String id, String type, Map<String, Object> properties) {
540 ObjectBuildOrPropertiesStep objectInProgress = ChampObject.create().ofType(type).withKey(Long.parseLong(id));
542 for (String key : properties.keySet()) {
543 objectInProgress.withProperty(key, properties.get(key));
545 return objectInProgress.build();
548 private Vertex vertexFromChampObject(ChampObject champObject, String type) {
550 // Get the identifier for this vertex from the Champ object.
551 Object id = champObject.getKey().orElse("");
553 // Start building our {@link Vertex} object.
554 Vertex.Builder vertexBuilder = new Vertex.Builder(type);
555 vertexBuilder.id(id.toString());
557 // Convert the properties associated with the Champ object into the form
560 for (String key : champObject.getProperties().keySet()) {
561 vertexBuilder.property(key, champObject.getProperties().get(key));
565 return vertexBuilder.build();
569 * This helper method converts a {@link ChampRelationship} from the Champ
570 * library into an equivalent {@link Edge} object that is understood by the
573 * @param relationship
574 * - The ChampRelationship object to be converted.
575 * @return - An Edge object corresponding to the supplied ChampRelationship
577 private Edge edgeFromChampRelationship(ChampRelationship relationship) {
579 // Populate the edge's id, if available.
580 Object relationshipId = relationship.getKey().orElse("");
582 Edge.Builder edgeBuilder = new Edge.Builder(relationship.getType()).id(relationshipId.toString());
583 edgeBuilder.source(vertexFromChampObject(relationship.getSource(),
584 relationship.getSource().getProperties()
585 .get(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName()) == null
586 ? relationship.getSource().getType()
587 : relationship.getSource().getProperties()
588 .get(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName()).toString()));
589 edgeBuilder.target(vertexFromChampObject(relationship.getTarget(),
590 relationship.getTarget().getProperties()
591 .get(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName()) == null
592 ? relationship.getTarget().getType()
593 : relationship.getTarget().getProperties()
594 .get(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName()).toString()));
596 for (String key : relationship.getProperties().keySet()) {
597 edgeBuilder.property(key, relationship.getProperties().get(key).toString());
600 return edgeBuilder.build();
604 * Performs any necessary shut down operations when the DAO is no longer
607 public void close() {
609 if (champApi != null) {
611 logger.info(CrudServiceMsgs.STOPPING_CHAMP_DAO);
618 public String openTransaction() {
620 ChampTransaction transaction = champApi.openTransaction();
622 transactions.put(transaction.id(), transaction);
623 logger.info(CrudServiceMsgs.TRANSACTION, "Stored transaction " + transaction.id() + " in hashmap");
624 logger.info(CrudServiceMsgs.TRANSACTION, "Hash map contents:");
625 for (String key : transactions.keySet()) {
626 logger.info(CrudServiceMsgs.TRANSACTION, key);
628 return transaction.id();
632 public void commitTransaction(String id) throws CrudException {
635 champApi.commitTransaction(getTransaction(id));
636 } catch (ChampTransactionException e) {
637 throw new CrudException("Error while commiting transaction " + id,
638 javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
640 transactions.remove(id);
644 public void rollbackTransaction(String id) throws CrudException {
647 champApi.rollbackTransaction(getTransaction(id));
648 } catch (ChampTransactionException e) {
649 throw new CrudException("Error while transaction rollback " + id,
650 javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
652 transactions.remove(id);
655 private ChampTransaction getTransaction(String id) throws CrudException {
657 logger.info(CrudServiceMsgs.TRANSACTION, "Looking up transaction " + id);
658 if (transactions.containsKey(id)) {
659 logger.info(CrudServiceMsgs.TRANSACTION, "Found it!");
660 return (transactions.get(id));
662 logger.info(CrudServiceMsgs.TRANSACTION, "Didn't find transaction id " + id + ". Hash map contains: ");
663 for (String key : transactions.keySet()) {
664 logger.info(CrudServiceMsgs.TRANSACTION, key);
666 throw new CrudException("No open transaction with id: " + id, javax.ws.rs.core.Response.Status.NOT_FOUND);
671 public Vertex addVertex(String type, Map<String, Object> properties, String txId) throws CrudException {
672 if (logger.isDebugEnabled()) {
673 logger.debug("Add/update vertex: {label: " + type + " properties:" + propertiesMapToString(properties));
676 // Add the aai_node_type so that AAI can read the data created by gizmo
677 properties.put(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type);
679 // Create an object to represent our vertex in the format expected by the
681 ChampObject objectToCreate = buildChampObject(type, properties);
685 // Ask the Champ library to store our vertex, placing the returned object
687 // list so that we can easily put that into our result object.
688 return vertexFromChampObject(champApi.storeObject(objectToCreate, Optional.of(getTransaction(txId))), type);
690 } catch (ChampMarshallingException | ChampSchemaViolationException | ChampObjectNotExistsException
691 | ChampTransactionException e) {
693 // Something went wrong - throw an exception.
694 throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
699 public Edge addEdge(String type, Vertex source, Vertex target, Map<String, Object> properties, String txId)
700 throws CrudException {
701 // For now, assume source and target are straight ids...
704 Optional<ChampObject> sourceObject = champApi.retrieveObject(Long.parseLong(source.getId().get()),
705 Optional.of(getTransaction(txId)));
706 if (!sourceObject.isPresent() || !sourceObject.get().getType().equals(source.getType())) {
707 throw new CrudException(
708 "Error creating edge - source vertex with id " + source + " does not exist in graph data base",
709 javax.ws.rs.core.Response.Status.BAD_REQUEST);
712 Optional<ChampObject> targetObject = champApi.retrieveObject(Long.parseLong(target.getId().get()),
713 Optional.of(getTransaction(txId)));
714 if (!targetObject.isPresent() || !targetObject.get().getType().equals(target.getType())) {
715 throw new CrudException(
716 "Error creating edge - target vertex with id " + target + " does not exist in graph data base",
717 javax.ws.rs.core.Response.Status.BAD_REQUEST);
720 // Now, create the ChampRelationship object for our edge and store it in
721 // the graph database.
722 return edgeFromChampRelationship(champApi.storeRelationship(
723 new ChampRelationship.Builder(sourceObject.get(), targetObject.get(), type).properties(properties).build(),
724 Optional.of(getTransaction(txId))));
726 } catch (ChampMarshallingException | ChampObjectNotExistsException | ChampSchemaViolationException
727 | ChampTransactionException | ChampRelationshipNotExistsException | ChampUnmarshallingException e) {
729 throw new CrudException("Error creating edge: " + e.getMessage(),
730 javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
736 public Vertex updateVertex(String id, String type, Map<String, Object> properties, String txId) throws CrudException {
737 if (logger.isDebugEnabled()) {
738 logger.debug("Update vertex with id: " + id + " with properties: " + propertiesMapToString(properties));
740 // Add the aai_node_type so that AAI can read the data created by gizmo
741 properties.put(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type);
744 // Now, build the updated version of the Champ Object...
745 ChampObject updateObject = buildChampObject(id, type, properties);
746 // ...and send it to the Champ library.
747 return vertexFromChampObject(champApi.replaceObject(updateObject, Optional.of(getTransaction(txId))), type);
749 } catch (ChampObjectNotExistsException e) {
750 throw new CrudException("Not Found", javax.ws.rs.core.Response.Status.NOT_FOUND);
751 } catch (NumberFormatException | ChampMarshallingException | ChampTransactionException
752 | ChampSchemaViolationException e) {
753 throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
758 public boolean transactionExists(String id) throws CrudException {
759 return transactions.containsKey(id);
763 public void deleteVertex(String id, String type, String txId) throws CrudException {
766 // First, retrieve the vertex that we intend to delete.
767 Optional<ChampObject> retrievedVertex = champApi.retrieveObject(Long.parseLong(id),
768 Optional.of(getTransaction(txId)));
771 if (!retrievedVertex.isPresent() || !retrievedVertex.get().getType().equals(type)) {
772 throw new CrudException("Failed to delete vertex with id: " + id + " - vertex does not exist.",
773 javax.ws.rs.core.Response.Status.NOT_FOUND);
776 // Now, verify that there are no edges incident to the vertex (they must
779 Stream<ChampRelationship> relationships = champApi.retrieveRelationships(retrievedVertex.get(),
780 Optional.of(getTransaction(txId)));
782 if (relationships.count() > 0) {
783 throw new CrudException("Attempt to delete vertex with id " + id + " which has incident edges.",
784 javax.ws.rs.core.Response.Status.BAD_REQUEST);
787 // Finally, we can attempt to delete our vertex.
788 champApi.deleteObject(Long.parseLong(id), Optional.of(getTransaction(txId)));
790 } catch (NumberFormatException | ChampUnmarshallingException | ChampObjectNotExistsException
791 | ChampTransactionException e) {
793 throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
799 public Edge updateEdge(Edge edge, String txId) throws CrudException {
800 if (logger.isDebugEnabled()) {
802 "Update edge with id: " + edge.getId() + " with properties: " + propertiesMapToString(edge.getProperties()));
806 // Now, build the updated version of the Champ Relationship...
807 ChampRelationship updateRelationship = new ChampRelationship.Builder(
808 buildChampObject(edge.getSource().getId().get(), edge.getSource().getType(),
809 edge.getSource().getProperties()),
810 buildChampObject(edge.getTarget().getId().get(), edge.getTarget().getType(),
811 edge.getTarget().getProperties()),
812 edge.getType()).key(getRelKey(edge.getId().get())).properties(edge.getProperties()).build();
813 // ...and send it to the Champ library.
814 return edgeFromChampRelationship(
815 champApi.replaceRelationship(updateRelationship, Optional.of(getTransaction(txId))));
817 } catch (ChampRelationshipNotExistsException ex) {
818 throw new CrudException("Not Found", javax.ws.rs.core.Response.Status.NOT_FOUND);
819 } catch (NumberFormatException | ChampUnmarshallingException | ChampMarshallingException
820 | ChampSchemaViolationException | ChampTransactionException ex) {
822 throw new CrudException(ex.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
827 public void deleteEdge(String id, String type, String txId) throws CrudException {
830 // First, retrieve the edge that we want to delete.
831 Optional<ChampRelationship> relationshipToDelete = champApi.retrieveRelationship(getRelKey(id),
832 Optional.of(getTransaction(txId)));
835 if (!relationshipToDelete.isPresent() || !relationshipToDelete.get().getType().equals(type)) {
836 throw new CrudException("Failed to delete edge with id: " + id + " - edge does not exist",
837 javax.ws.rs.core.Response.Status.NOT_FOUND);
840 // Now we can delete the edge.
841 champApi.deleteRelationship(relationshipToDelete.get(), Optional.of(getTransaction(txId)));
843 } catch (ChampRelationshipNotExistsException | NumberFormatException | ChampUnmarshallingException
844 | ChampTransactionException e) {
846 throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
852 public Edge getEdge(String id, String type, String txId) throws CrudException {
853 if (logger.isDebugEnabled()) {
854 logger.debug("Get edge with id: " + id);
859 // Request the edge from the graph db.
860 Optional<ChampRelationship> relationship = champApi.retrieveRelationship(getRelKey(id),
861 Optional.of(getTransaction(txId)));
864 if (relationship.isPresent() && relationship.get().getType().equals(type)) {
866 // Yup - return the result.
867 return edgeFromChampRelationship(relationship.get());
871 // We didn't find an edge with the supplied id, so throw an exception.
872 throw new CrudException("No edge with id " + id + " found in graph",
873 javax.ws.rs.core.Response.Status.NOT_FOUND);
876 } catch (ChampUnmarshallingException | ChampTransactionException e) {
878 // Something went wrong, so throw an exception.
879 throw new CrudException(e.getMessage(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);