1163623e07582073ba4e912e3655a82195220cc3
[aai/gizmo.git] / src / main / java / org / onap / crud / service / AbstractGraphDataService.java
1 /**
2  * ============LICENSE_START=======================================================
3  * Gizmo
4  * ================================================================================
5  * Copyright © 2017 AT&T Intellectual Property.
6  * Copyright © 2017 Amdocs
7  * All rights reserved.
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
12  *
13  *    http://www.apache.org/licenses/LICENSE-2.0
14  *
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=========================================================
21  *
22  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
23  */
24 package org.onap.crud.service;
25
26 import java.util.ArrayList;
27 import java.util.HashMap;
28 import java.util.HashSet;
29 import java.util.List;
30 import java.util.Map;
31
32 import javax.ws.rs.core.HttpHeaders;
33 import javax.ws.rs.core.Response.Status;
34
35 import org.onap.crud.dao.GraphDao;
36 import org.onap.crud.entity.Edge;
37 import org.onap.crud.entity.Vertex;
38 import org.onap.crud.exception.CrudException;
39 import org.onap.crud.parser.CrudResponseBuilder;
40 import org.onap.crud.util.CrudServiceUtil;
41 import org.onap.schema.OxmModelValidator;
42 import org.onap.schema.RelationshipSchemaValidator;
43
44 import com.google.gson.JsonElement;
45
46 public abstract class AbstractGraphDataService {
47   protected GraphDao dao;
48   
49   public AbstractGraphDataService(GraphDao dao) throws CrudException {
50     this.dao = dao;
51
52     CrudServiceUtil.loadModels();
53   }
54   
55   public String getEdge(String version, String id, String type) throws CrudException {
56     RelationshipSchemaValidator.validateType(version, type);
57     Edge edge = dao.getEdge(id, type);
58
59     return CrudResponseBuilder.buildGetEdgeResponse(RelationshipSchemaValidator.validateOutgoingPayload(version, edge), version);
60   }
61   
62   public String getEdges(String version, String type, Map<String, String> filter) throws CrudException {
63     RelationshipSchemaValidator.validateType(version, type);
64     List<Edge> items = dao.getEdges(type, RelationshipSchemaValidator.resolveCollectionfilter(version, type, filter));
65     return CrudResponseBuilder.buildGetEdgesResponse(items, version);
66   }
67   
68   public String getVertex(String version, String id, String type) throws CrudException {
69     type = OxmModelValidator.resolveCollectionType(version, type);
70     Vertex vertex = dao.getVertex(id, type, version);
71     List<Edge> edges = dao.getVertexEdges(id);
72     return CrudResponseBuilder.buildGetVertexResponse(OxmModelValidator.validateOutgoingPayload(version, vertex), edges,
73         version);
74   }
75
76   public String getVertices(String version, String type, Map<String, String> filter, HashSet<String> properties) throws CrudException {
77     type = OxmModelValidator.resolveCollectionType(version, type);
78     List<Vertex> items = dao.getVertices(type, OxmModelValidator.resolveCollectionfilter(version, type, filter), properties);
79     return CrudResponseBuilder.buildGetVerticesResponse(items, version);
80   }
81   
82   public String addBulk(String version, BulkPayload payload, HttpHeaders headers) throws CrudException {
83     HashMap<String, Vertex> vertices = new HashMap<String, Vertex>();
84     HashMap<String, Edge> edges = new HashMap<String, Edge>();
85
86     String txId = dao.openTransaction();   
87      
88     try {
89       // Step 1. Handle edge deletes (must happen before vertex deletes)
90       for (JsonElement v : payload.getRelationships()) {
91         List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
92             v.getAsJsonObject().entrySet());
93
94         if (entries.size() != 2) {
95           throw new CrudException("", Status.BAD_REQUEST);
96         }
97         Map.Entry<String, JsonElement> opr = entries.get(0);
98         Map.Entry<String, JsonElement> item = entries.get(1);
99         EdgePayload edgePayload = EdgePayload.fromJson(item.getValue().getAsJsonObject().toString());
100
101         if (opr.getValue().getAsString().equalsIgnoreCase("delete")) {
102           RelationshipSchemaValidator.validateType(version, edgePayload.getType());
103           deleteBulkEdge(edgePayload.getId(), version, edgePayload.getType(), txId);
104         }
105       } 
106       
107       // Step 2: Handle vertex deletes
108       for (JsonElement v : payload.getObjects()) {
109         List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
110             v.getAsJsonObject().entrySet());
111
112         if (entries.size() != 2) {
113           throw new CrudException("", Status.BAD_REQUEST);
114         }
115
116         Map.Entry<String, JsonElement> opr = entries.get(0);
117         Map.Entry<String, JsonElement> item = entries.get(1);
118         VertexPayload vertexPayload = VertexPayload.fromJson(item.getValue().getAsJsonObject().toString());
119
120         if (opr.getValue().getAsString().equalsIgnoreCase("delete")) {
121           String type = OxmModelValidator.resolveCollectionType(version, vertexPayload.getType());
122           deleteBulkVertex(vertexPayload.getId(), version, type, txId);
123         }
124       }
125       
126       // Step 3: Handle vertex add/modify (must happen before edge adds)
127       for (JsonElement v : payload.getObjects()) {
128         List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
129             v.getAsJsonObject().entrySet());
130
131         if (entries.size() != 2) {
132           throw new CrudException("", Status.BAD_REQUEST);
133         }
134         Map.Entry<String, JsonElement> opr = entries.get(0);
135         Map.Entry<String, JsonElement> item = entries.get(1);
136         VertexPayload vertexPayload = VertexPayload.fromJson(item.getValue().getAsJsonObject().toString());
137         
138         // Add vertex
139         if (opr.getValue().getAsString().equalsIgnoreCase("add")) {
140           vertexPayload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(vertexPayload.getProperties(), 
141               headers, true));  
142           Vertex validatedVertex = OxmModelValidator.validateIncomingUpsertPayload(null, version, vertexPayload.getType(),
143               vertexPayload.getProperties());
144           Vertex persistedVertex = addBulkVertex(validatedVertex, version, txId);
145           Vertex outgoingVertex = OxmModelValidator.validateOutgoingPayload(version, persistedVertex);
146           vertices.put(item.getKey(), outgoingVertex);
147         }
148         
149         // Update vertex 
150         else if (opr.getValue().getAsString().equalsIgnoreCase("modify")) {
151           vertexPayload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(vertexPayload.getProperties(), 
152               headers, false));
153           Vertex validatedVertex = OxmModelValidator.validateIncomingUpsertPayload(vertexPayload.getId(), version,
154               vertexPayload.getType(), vertexPayload.getProperties());
155           Vertex persistedVertex = updateBulkVertex(validatedVertex, vertexPayload.getId(), version, txId);
156           Vertex outgoingVertex = OxmModelValidator.validateOutgoingPayload(version, persistedVertex);
157           vertices.put(item.getKey(), outgoingVertex);
158         }
159         
160         // Patch vertex 
161         else if (opr.getValue().getAsString().equalsIgnoreCase("patch")) {
162           if ( (vertexPayload.getId() == null) || (vertexPayload.getType() == null) ) {
163             throw new CrudException("id and type must be specified for patch request", Status.BAD_REQUEST);
164           }
165           
166           vertexPayload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(vertexPayload.getProperties(), 
167               headers, false));
168           
169           Vertex existingVertex = dao.getVertex(vertexPayload.getId(), OxmModelValidator.resolveCollectionType(version, vertexPayload.getType()), version);
170           Vertex validatedVertex = OxmModelValidator.validateIncomingPatchPayload(vertexPayload.getId(), 
171               version, vertexPayload.getType(), vertexPayload.getProperties(), existingVertex);
172           Vertex persistedVertex = updateBulkVertex(validatedVertex, vertexPayload.getId(), version, txId);
173           Vertex outgoingVertex = OxmModelValidator.validateOutgoingPayload(version, persistedVertex);
174           vertices.put(item.getKey(), outgoingVertex);
175         }
176       }
177
178       // Step 4: Handle edge add/modify 
179       for (JsonElement v : payload.getRelationships()) {
180         List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
181             v.getAsJsonObject().entrySet());
182
183         if (entries.size() != 2) {
184           throw new CrudException("", Status.BAD_REQUEST);
185         }
186         Map.Entry<String, JsonElement> opr = entries.get(0);
187         Map.Entry<String, JsonElement> item = entries.get(1);
188         EdgePayload edgePayload = EdgePayload.fromJson(item.getValue().getAsJsonObject().toString());
189
190         // Add/Update edge
191         if (opr.getValue().getAsString().equalsIgnoreCase("add")
192             || opr.getValue().getAsString().equalsIgnoreCase("modify") 
193             || opr.getValue().getAsString().equalsIgnoreCase("patch")) {
194           Edge validatedEdge;
195           Edge persistedEdge;
196           if (opr.getValue().getAsString().equalsIgnoreCase("add")) {
197             // Fix the source/destination
198             if (edgePayload.getSource().startsWith("$")) {
199               Vertex source = vertices.get(edgePayload.getSource().substring(1));
200               if (source == null) {
201                 throw new CrudException("Not able to find vertex: " + edgePayload.getSource().substring(1),
202                     Status.INTERNAL_SERVER_ERROR);
203               }
204               edgePayload
205                   .setSource("services/inventory/" + version + "/" + source.getType() + "/" + source.getId().get());
206             }
207             if (edgePayload.getTarget().startsWith("$")) {
208               Vertex target = vertices.get(edgePayload.getTarget().substring(1));
209               if (target == null) {
210                 throw new CrudException("Not able to find vertex: " + edgePayload.getTarget().substring(1),
211                     Status.INTERNAL_SERVER_ERROR);
212               }
213               edgePayload
214                   .setTarget("services/inventory/" + version + "/" + target.getType() + "/" + target.getId().get());
215             }
216             validatedEdge = RelationshipSchemaValidator.validateIncomingAddPayload(version, edgePayload.getType(),
217                 edgePayload);
218             persistedEdge = addBulkEdge(validatedEdge, version, txId);
219           } else if (opr.getValue().getAsString().equalsIgnoreCase("modify")) {
220             Edge edge = dao.getEdge(edgePayload.getId(), edgePayload.getType(), txId);
221             validatedEdge = RelationshipSchemaValidator.validateIncomingUpdatePayload(edge, version, edgePayload);
222             persistedEdge = updateBulkEdge(validatedEdge, version, txId);
223           } else {
224             if ( (edgePayload.getId() == null) || (edgePayload.getType() == null) ) {
225               throw new CrudException("id and type must be specified for patch request", Status.BAD_REQUEST);
226             }
227             Edge existingEdge = dao.getEdge(edgePayload.getId(), edgePayload.getType(), txId);
228             Edge patchedEdge = RelationshipSchemaValidator.validateIncomingPatchPayload(existingEdge, version, edgePayload);
229             persistedEdge = updateBulkEdge(patchedEdge, version, txId);
230           }
231           
232
233           Edge outgoingEdge = RelationshipSchemaValidator.validateOutgoingPayload(version, persistedEdge);
234           edges.put(item.getKey(), outgoingEdge);
235         } 
236       } 
237       
238       // commit transaction
239       dao.commitTransaction(txId);
240     } catch (CrudException ex) {
241       dao.rollbackTransaction(txId);
242       throw ex;
243     } catch (Exception ex) {
244       dao.rollbackTransaction(txId);
245       throw ex;
246     } finally {
247       if (dao.transactionExists(txId)) {
248         dao.rollbackTransaction(txId);
249       }
250     }
251     
252     return CrudResponseBuilder.buildUpsertBulkResponse(vertices, edges, version, payload);
253   }
254
255
256   public abstract String addVertex(String version, String type, VertexPayload payload) throws CrudException;
257   public abstract String updateVertex(String version, String id, String type, VertexPayload payload) throws CrudException;
258   public abstract String patchVertex(String version, String id, String type, VertexPayload payload) throws CrudException;
259   public abstract String deleteVertex(String version, String id, String type) throws CrudException;
260   public abstract String addEdge(String version, String type, EdgePayload payload) throws CrudException;
261   public abstract String deleteEdge(String version, String id, String type) throws CrudException;
262   public abstract String updateEdge(String version, String id, String type, EdgePayload payload) throws CrudException;
263   public abstract String patchEdge(String version, String id, String type, EdgePayload payload) throws CrudException;
264   
265   protected abstract Vertex addBulkVertex(Vertex vertex, String version, String dbTransId) throws CrudException;
266   protected abstract Vertex updateBulkVertex(Vertex vertex, String id, String version, String dbTransId) throws CrudException;
267   protected abstract void deleteBulkVertex(String id, String version, String type, String dbTransId) throws CrudException;
268   
269   protected abstract Edge addBulkEdge(Edge edge, String version, String dbTransId) throws CrudException;
270   protected abstract Edge updateBulkEdge(Edge edge, String version, String dbTransId) throws CrudException;
271   protected abstract void deleteBulkEdge(String id, String version, String type, String dbTransId) throws CrudException;
272 }