2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6 * Copyright © 2017-2018 Amdocs
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
22 package org.onap.crud.dao.champ;
24 import com.google.gson.Gson;
25 import com.google.gson.GsonBuilder;
26 import com.google.gson.JsonElement;
28 import java.util.ArrayList;
29 import java.util.HashMap;
30 import java.util.List;
33 import javax.ws.rs.core.HttpHeaders;
34 import javax.ws.rs.core.Response.Status;
36 import org.onap.aai.restclient.client.OperationResult;
37 import org.onap.crud.dao.GraphDao;
38 import org.onap.crud.entity.Edge;
39 import org.onap.crud.entity.Vertex;
40 import org.onap.crud.exception.CrudException;
41 import org.onap.crud.service.BulkPayload;
42 import org.onap.crud.service.EdgePayload;
43 import org.onap.crud.service.VertexPayload;
44 import org.onap.crud.util.CrudServiceUtil;
45 import org.onap.schema.OxmModelValidator;
46 import org.onap.schema.RelationshipSchemaValidator;
48 public class ChampBulkPayload {
50 public static String ADD_OP = "add";
51 public static String UPDATE_OP = "modify";
52 public static String DELETE_OP = "delete";
53 public static String PATCH_OP = "patch";
55 private List<ChampBulkOp> edgeDeleteOps = new ArrayList<ChampBulkOp>();
56 private List<ChampBulkOp> vertexDeleteOps = new ArrayList<ChampBulkOp>();
57 private List<ChampBulkOp> vertexAddModifyOps = new ArrayList<ChampBulkOp>();
58 private List<ChampBulkOp> edgeAddModifyOps = new ArrayList<ChampBulkOp>();
60 private static final Gson gson = new GsonBuilder().disableHtmlEscaping().create();
62 public String toJson() {
63 return gson.toJson(this);
66 public static ChampBulkPayload fromJson(String payload) {
67 return gson.fromJson(payload, ChampBulkPayload.class);
70 public List<ChampBulkOp> getEdgeDeleteOps() {
74 public void setEdgeDeleteOps(List<ChampBulkOp> ops) {
75 this.edgeDeleteOps = ops;
78 public List<ChampBulkOp> getVertexDeleteOps() {
79 return vertexDeleteOps;
82 public void setVertexDeleteOps(List<ChampBulkOp> ops) {
83 this.vertexDeleteOps = ops;
86 public List<ChampBulkOp> getVertexAddModifyOps() {
87 return vertexAddModifyOps;
90 public void setVertexAddModifyOps(List<ChampBulkOp> ops) {
91 this.vertexAddModifyOps = ops;
94 public List<ChampBulkOp> getEdgeAddModifyOps() {
95 return edgeAddModifyOps;
98 public void setEdgeAddModifyOps(List<ChampBulkOp> ops) {
99 this.edgeAddModifyOps = ops;
102 public void fromGizmoPayload(BulkPayload gizmoPayload, String version, HttpHeaders headers, GraphDao champDao) throws CrudException {
103 edgeDeleteOps = new ArrayList<ChampBulkOp>();
104 vertexDeleteOps = new ArrayList<ChampBulkOp>();
105 vertexAddModifyOps = new ArrayList<ChampBulkOp>();
106 edgeAddModifyOps = new ArrayList<ChampBulkOp>();
108 Map<String,String> addedVertexes = new HashMap<String,String>();
110 // Step 1. Extract edge deletes
111 for (JsonElement v : gizmoPayload.getRelationships()) {
112 List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
113 v.getAsJsonObject().entrySet());
115 if (entries.size() != 2) {
116 throw new CrudException("", Status.BAD_REQUEST);
118 Map.Entry<String, JsonElement> opr = entries.get(0);
119 Map.Entry<String, JsonElement> item = entries.get(1);
120 EdgePayload edgePayload = EdgePayload.fromJson(item.getValue().getAsJsonObject().toString());
122 if (opr.getValue().getAsString().equalsIgnoreCase("delete")) {
123 ChampBulkOp champOp = new ChampBulkOp();
124 champOp.setId(edgePayload.getId());
125 champOp.setOperation(DELETE_OP);
126 edgeDeleteOps.add(champOp);
130 // Step 2: Extract vertex deletes
131 for (JsonElement v : gizmoPayload.getObjects()) {
132 List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
133 v.getAsJsonObject().entrySet());
135 if (entries.size() != 2) {
136 throw new CrudException("", Status.BAD_REQUEST);
139 Map.Entry<String, JsonElement> opr = entries.get(0);
140 Map.Entry<String, JsonElement> item = entries.get(1);
141 VertexPayload vertexPayload = VertexPayload.fromJson(item.getValue().getAsJsonObject().toString());
143 if (opr.getValue().getAsString().equalsIgnoreCase("delete")) {
144 String type = OxmModelValidator.resolveCollectionType(version, vertexPayload.getType());
145 ChampBulkOp champOp = new ChampBulkOp();
146 champOp.setId(vertexPayload.getId());
147 champOp.setOperation(DELETE_OP);
148 champOp.setType(type);
149 vertexDeleteOps.add(champOp);
153 // Step 3: Extract vertex add/modify
154 for (JsonElement v : gizmoPayload.getObjects()) {
155 List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
156 v.getAsJsonObject().entrySet());
158 if (entries.size() != 2) {
159 throw new CrudException("", Status.BAD_REQUEST);
161 Map.Entry<String, JsonElement> opr = entries.get(0);
162 Map.Entry<String, JsonElement> item = entries.get(1);
163 VertexPayload vertexPayload = VertexPayload.fromJson(item.getValue().getAsJsonObject().toString());
166 if (opr.getValue().getAsString().equalsIgnoreCase("add")) {
167 vertexPayload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(vertexPayload.getProperties(),
169 Vertex validatedVertex = OxmModelValidator.validateIncomingUpsertPayload(null, version, vertexPayload.getType(),
170 vertexPayload.getProperties());
171 validatedVertex.getProperties().put(OxmModelValidator.Metadata.NODE_TYPE.propertyName(), vertexPayload.getType());
173 ChampBulkOp champOp = new ChampBulkOp();
174 champOp.setLabel(item.getKey());
175 champOp.setOperation(ADD_OP);
176 champOp.setType(vertexPayload.getType());
177 champOp.setProperties(validatedVertex.getProperties());
178 vertexAddModifyOps.add(champOp);
182 else if (opr.getValue().getAsString().equalsIgnoreCase("modify")) {
183 vertexPayload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(vertexPayload.getProperties(),
185 Vertex validatedVertex = OxmModelValidator.validateIncomingUpsertPayload(vertexPayload.getId(), version,
186 vertexPayload.getType(), vertexPayload.getProperties());
187 validatedVertex.getProperties().put(OxmModelValidator.Metadata.NODE_TYPE.propertyName(), vertexPayload.getType());
189 ChampBulkOp champOp = new ChampBulkOp();
190 champOp.setLabel(item.getKey());
191 champOp.setId(vertexPayload.getId());
192 champOp.setOperation(UPDATE_OP);
193 champOp.setType(vertexPayload.getType());
194 champOp.setProperties(validatedVertex.getProperties());
195 vertexAddModifyOps.add(champOp);
199 else if (opr.getValue().getAsString().equalsIgnoreCase("patch")) {
200 if ( (vertexPayload.getId() == null) || (vertexPayload.getType() == null) ) {
201 throw new CrudException("id and type must be specified for patch request", Status.BAD_REQUEST);
204 vertexPayload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(vertexPayload.getProperties(),
207 OperationResult existingVertexOpResult =
208 champDao.getVertex(vertexPayload.getId(),
209 OxmModelValidator.resolveCollectionType(version, vertexPayload.getType()),
210 version, new HashMap<String, String>());
212 Vertex existingVertex = Vertex.fromJson(existingVertexOpResult.getResult(), version);
213 Vertex validatedVertex = OxmModelValidator.validateIncomingPatchPayload(vertexPayload.getId(),
214 version, vertexPayload.getType(), vertexPayload.getProperties(), existingVertex);
215 validatedVertex.getProperties().put(OxmModelValidator.Metadata.NODE_TYPE.propertyName(), vertexPayload.getType());
217 ChampBulkOp champOp = new ChampBulkOp();
218 champOp.setLabel(item.getKey());
219 champOp.setId(vertexPayload.getId());
220 champOp.setOperation(UPDATE_OP);
221 champOp.setType(vertexPayload.getType());
222 champOp.setProperties(validatedVertex.getProperties());
223 vertexAddModifyOps.add(champOp);
226 addedVertexes.put(item.getKey(), "services/inventory/" + version + "/" + vertexPayload.getType()+ "/" + item.getKey());
229 // Step 4: Extract edge add/modify
230 for (JsonElement v : gizmoPayload.getRelationships()) {
231 List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
232 v.getAsJsonObject().entrySet());
234 if (entries.size() != 2) {
235 throw new CrudException("", Status.BAD_REQUEST);
237 Map.Entry<String, JsonElement> opr = entries.get(0);
238 Map.Entry<String, JsonElement> item = entries.get(1);
239 EdgePayload edgePayload = EdgePayload.fromJson(item.getValue().getAsJsonObject().toString());
242 if (opr.getValue().getAsString().equalsIgnoreCase("add")
243 || opr.getValue().getAsString().equalsIgnoreCase("modify")
244 || opr.getValue().getAsString().equalsIgnoreCase("patch")) {
249 ChampBulkOp champOp = new ChampBulkOp();
250 champOp.setLabel(item.getKey());
252 if (opr.getValue().getAsString().equalsIgnoreCase("add")) {
253 // If the source/target is a vertex that hasn't been created yet, get the types from the map
254 String sourceUrl = edgePayload.getSource();
255 String targetUrl = edgePayload.getTarget();
256 edgePayload.setSource(resolveUrl(edgePayload.getSource(), addedVertexes));
257 edgePayload.setTarget(resolveUrl(edgePayload.getTarget(), addedVertexes));
259 // If the type isn't set, resolve it based on on the source and target vertex types
260 if (edgePayload.getType() == null || edgePayload.getType().isEmpty()) {
261 edgePayload.setType(CrudServiceUtil.determineEdgeType(edgePayload, version));
264 champOp.setType(edgePayload.getType());
265 Edge validatedEdge = RelationshipSchemaValidator.validateIncomingAddPayload(version, edgePayload.getType(), edgePayload);
266 champOp.setOperation(ADD_OP);
267 champOp.setProperties(validatedEdge.getProperties());
268 champOp.setSource(sourceUrl.substring(sourceUrl.lastIndexOf('/') + 1));
269 champOp.setTarget(targetUrl.substring(targetUrl.lastIndexOf('/') + 1));
270 } else if (opr.getValue().getAsString().equalsIgnoreCase("modify")) {
271 Edge edge = champDao.getEdge(edgePayload.getId());
272 if (edgePayload.getType() == null || edgePayload.getType().isEmpty()) {
273 edgePayload.setType(edge.getType());
275 champOp.setType(edgePayload.getType());
276 Edge validatedEdge = RelationshipSchemaValidator.validateIncomingUpdatePayload(edge, version, edgePayload);
277 champOp.setOperation(UPDATE_OP);
278 champOp.setId(edgePayload.getId());
279 champOp.setProperties(validatedEdge.getProperties());
280 champOp.setSource(edge.getSource().getId().get());
281 champOp.setTarget(edge.getTarget().getId().get());
283 if (edgePayload.getId() == null) {
284 throw new CrudException("id must be specified for patch request", Status.BAD_REQUEST);
286 Edge existingEdge = champDao.getEdge(edgePayload.getId());
287 if (edgePayload.getType() == null || edgePayload.getType().isEmpty()) {
288 edgePayload.setType(existingEdge.getType());
290 champOp.setType(edgePayload.getType());
291 Edge patchedEdge = RelationshipSchemaValidator.validateIncomingPatchPayload(existingEdge, version, edgePayload);
292 champOp.setOperation(UPDATE_OP);
293 champOp.setId(edgePayload.getId());
294 champOp.setProperties(patchedEdge.getProperties());
295 champOp.setSource(existingEdge.getSource().getId().get());
296 champOp.setTarget(existingEdge.getTarget().getId().get());
299 edgeAddModifyOps.add(champOp);
304 private String resolveUrl(String vertexUrl, Map<String, String> addedVertexes) throws CrudException {
305 if (vertexUrl.startsWith("$")) {
306 String key = vertexUrl.substring(1);
307 if (addedVertexes.get(key) != null) {
308 return addedVertexes.get(key);
311 throw new CrudException("Unable to resolve vertex " + key, Status.BAD_REQUEST);