Sync up the changes for v15
[aai/aai-common.git] / aai-core / src / main / java / org / onap / aai / rest / db / HttpEntry.java
1 /**
2  * ============LICENSE_START=======================================================
3  * org.onap.aai
4  * ================================================================================
5  * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *    http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20 package org.onap.aai.rest.db;
21
22
23 import java.io.IOException;
24 import java.io.UnsupportedEncodingException;
25 import java.lang.reflect.InvocationTargetException;
26 import java.net.MalformedURLException;
27 import java.net.URI;
28 import java.net.URISyntaxException;
29 import java.util.ArrayList;
30 import java.util.HashMap;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.Set;
34 import java.util.concurrent.TimeUnit;
35 import java.util.stream.Collectors;
36
37 import javax.ws.rs.core.HttpHeaders;
38 import javax.ws.rs.core.MediaType;
39 import javax.ws.rs.core.MultivaluedMap;
40 import javax.ws.rs.core.Response;
41 import javax.ws.rs.core.Response.Status;
42 import javax.ws.rs.core.UriBuilder;
43
44 import com.att.eelf.configuration.EELFLogger;
45 import com.att.eelf.configuration.EELFManager;
46 import com.fasterxml.jackson.databind.JsonNode;
47 import com.fasterxml.jackson.databind.ObjectMapper;
48 import com.github.fge.jsonpatch.JsonPatchException;
49 import com.github.fge.jsonpatch.mergepatch.JsonMergePatch;
50 import org.apache.commons.lang.StringUtils;
51 import org.apache.tinkerpop.gremlin.structure.Graph;
52 import org.apache.tinkerpop.gremlin.structure.Vertex;
53 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
54 import org.janusgraph.core.JanusGraphException;
55 import org.javatuples.Pair;
56 import org.json.JSONException;
57 import org.json.JSONObject;
58 import org.onap.aai.db.props.AAIProperties;
59 import org.onap.aai.dbmap.DBConnectionType;
60 import org.onap.aai.domain.responseMessage.AAIResponseMessage;
61 import org.onap.aai.domain.responseMessage.AAIResponseMessageDatum;
62 import org.onap.aai.exceptions.AAIException;
63 import org.onap.aai.extensions.AAIExtensionMap;
64 import org.onap.aai.extensions.ExtensionController;
65 import org.onap.aai.introspection.*;
66 import org.onap.aai.introspection.exceptions.AAIUnknownObjectException;
67 import org.onap.aai.logging.ErrorLogHelper;
68 import org.onap.aai.logging.LoggingContext;
69 import org.onap.aai.nodes.NodeIngestor;
70 import org.onap.aai.parsers.query.QueryParser;
71 import org.onap.aai.parsers.uri.URIToExtensionInformation;
72
73 import org.onap.aai.parsers.uri.URIToObject;
74 import org.onap.aai.rest.ueb.UEBNotification;
75 import org.onap.aai.restcore.HttpMethod;
76 import org.onap.aai.schema.enums.ObjectMetadata;
77 import org.onap.aai.serialization.db.DBSerializer;
78 import org.onap.aai.serialization.engines.JanusGraphDBEngine;
79 import org.onap.aai.serialization.engines.QueryStyle;
80 import org.onap.aai.serialization.engines.TransactionalGraphEngine;
81 import org.onap.aai.serialization.engines.query.QueryEngine;
82 import org.onap.aai.serialization.queryformats.Format;
83 import org.onap.aai.serialization.queryformats.FormatFactory;
84 import org.onap.aai.serialization.queryformats.Formatter;
85 import org.onap.aai.setup.SchemaVersion;
86 import org.onap.aai.setup.SchemaVersions;
87 import org.onap.aai.util.AAIConfig;
88 import org.springframework.beans.factory.annotation.Autowired;
89 import org.springframework.beans.factory.annotation.Value;
90
91 /**
92  * The Class HttpEntry.
93  */
94 public class HttpEntry {
95
96         private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(HttpEntry.class);
97         private static final String TARGET_ENTITY = "DB";
98
99         private ModelType introspectorFactoryType;
100
101         private QueryStyle queryStyle;
102
103         private SchemaVersion version;
104
105         private Loader loader;
106
107         private TransactionalGraphEngine dbEngine;
108
109         private boolean processSingle = true;
110
111         private int paginationBucket = -1;
112         private int paginationIndex = -1;
113         private int totalVertices = 0;
114         private int totalPaginationBuckets = 0;
115
116         @Autowired
117         private NodeIngestor nodeIngestor;
118
119         @Autowired
120         private LoaderFactory loaderFactory;
121
122         @Autowired
123         private SchemaVersions schemaVersions;
124
125         @Value("${schema.uri.base.path}")
126         private String basePath;
127
128         private UEBNotification notification;
129
130         /**
131          * Instantiates a new http entry.
132          *
133          * @param modelType the model type
134          * @param queryStyle the query style
135          */
136         public HttpEntry(ModelType modelType, QueryStyle queryStyle) {
137                 this.introspectorFactoryType = modelType;
138                 this.queryStyle = queryStyle;
139         }
140
141         public HttpEntry setHttpEntryProperties(SchemaVersion version, DBConnectionType connectionType) {
142                 this.version = version;
143                 this.loader = loaderFactory.createLoaderForVersion(introspectorFactoryType, version);
144                 this.dbEngine = new JanusGraphDBEngine(
145                         queryStyle,
146                         connectionType,
147                         loader);
148
149                 getDbEngine().startTransaction();
150                 this.notification = new UEBNotification(loader, loaderFactory, schemaVersions);
151                 return this;
152         }
153
154
155         public HttpEntry setHttpEntryProperties(SchemaVersion version, DBConnectionType connectionType, UEBNotification notification) {
156                 this.version = version;
157                 this.loader = loaderFactory.createLoaderForVersion(introspectorFactoryType, version);
158                 this.dbEngine = new JanusGraphDBEngine(
159                         queryStyle,
160                         connectionType,
161                         loader);
162
163                 this.notification = notification;
164                 //start transaction on creation
165                 getDbEngine().startTransaction();
166                 return this;
167         }
168
169
170         /**
171          * Gets the introspector factory type.
172          *
173          * @return the introspector factory type
174          */
175         public ModelType getIntrospectorFactoryType() {
176                 return introspectorFactoryType;
177         }
178
179         /**
180          * Gets the query style.
181          *
182          * @return the query style
183          */
184         public QueryStyle getQueryStyle() {
185                 return queryStyle;
186         }
187
188         /**
189          * Gets the version.
190          *
191          * @return the version
192          */
193         public SchemaVersion getVersion() {
194                 return version;
195         }
196
197         /**
198          * Gets the loader.
199          *
200          * @return the loader
201          */
202         public Loader getLoader() {
203                 return loader;
204         }
205
206         /**
207          * Gets the db engine.
208          *
209          * @return the db engine
210          */
211         public TransactionalGraphEngine getDbEngine() {
212                 return dbEngine;
213         }
214
215         public Pair<Boolean, List<Pair<URI, Response>>> process(List<DBRequest> requests, String sourceOfTruth) throws AAIException {
216                 return this.process(requests, sourceOfTruth, true);
217         }
218
219
220         /**
221          * Checks the pagination bucket and pagination index variables to determine whether or not the user
222          * requested paginated results
223          *
224          * @return a boolean true/false of whether the user requested paginated results
225          */
226         public boolean isPaginated() {
227                 return this.paginationBucket > -1 && this.paginationIndex > -1;
228         }
229
230         /**
231          * Returns the pagination size
232          * @return integer of the size of results to be returned when paginated
233          */
234         public int getPaginationBucket() {
235                 return this.paginationBucket;
236         }
237
238         /**
239          * Setter for the pagination bucket variable which stores in this object the size of results to return
240          * @param pb
241          */
242         public void setPaginationBucket(int pb) {
243                 this.paginationBucket = pb;
244         }
245
246         /**
247          * Getter to return the pagination index requested by the user when requesting paginated results
248          * @return
249          */
250         public int getPaginationIndex() {
251                 return this.paginationIndex;
252         }
253
254         /**
255          * Sets the pagination index that was passed in by the user, to determine which index or results to retrieve when
256          * paginated
257          * @param pi
258          */
259         public void setPaginationIndex(int pi) {
260                 if (pi == 0) {
261                         pi = 1;
262                 }
263                 this.paginationIndex = pi;
264         }
265
266         /**
267          * Sets the total vertices variables and calculates the amount of pages based on size and total vertices
268          * @param totalVertices
269          * @param paginationBucketSize
270          */
271         public void setTotalsForPaging(int totalVertices, int paginationBucketSize) {
272                 this.totalVertices = totalVertices;
273                 //set total number of buckets equal to full pages
274                 this.totalPaginationBuckets = totalVertices / paginationBucketSize;
275                 //conditionally add a page for the remainder
276                 if (totalVertices % paginationBucketSize > 0) {
277                         this.totalPaginationBuckets++;
278                 }
279         }
280
281         /**
282          * @return the total amount of pages
283          */
284         public int getTotalPaginationBuckets() {
285                 return this.totalPaginationBuckets;
286         }
287
288         /**
289          *
290          * @return the total number of vertices when paginated
291          */
292         public int getTotalVertices() {
293                 return this.totalVertices;
294         }
295
296         /**
297          * Process.
298          * @param requests the requests
299          * @param sourceOfTruth the source of truth
300          *
301          * @return the pair
302          * @throws AAIException the AAI exception
303          */
304         public Pair<Boolean, List<Pair<URI, Response>>> process(List<DBRequest> requests, String sourceOfTruth, boolean enableResourceVersion) throws AAIException {
305
306                 DBSerializer serializer = new DBSerializer(version, dbEngine, introspectorFactoryType, sourceOfTruth);
307                 String methodName = "process";
308                 Response response;
309                 Introspector obj = null;
310                 QueryParser query = null;
311                 URI uri = null;
312                 String transactionId = null;
313                 int depth = AAIProperties.MAXIMUM_DEPTH;
314                 Format format = null;
315                 List<Pair<URI, Response>> responses = new ArrayList<>();
316                 MultivaluedMap<String, String> params = null;
317                 HttpMethod method = null;
318                 String uriTemp = "";
319                 Boolean success = true;
320                 QueryEngine queryEngine = dbEngine.getQueryEngine();
321                 int maxRetries = 10;
322                 int retry = 0;
323
324                 LoggingContext.save();
325                 for (DBRequest request : requests) {
326                         response = null;
327                         Status status = Status.NOT_FOUND;
328                         method = request.getMethod();
329                         try {
330                                 for (retry = 0; retry < maxRetries; ++retry) {
331                                         try {
332
333                                                 LoggingContext.targetEntity(TARGET_ENTITY);
334                                                 LoggingContext.targetServiceName(methodName + " " + method);
335
336                                                 obj = request.getIntrospector();
337                                                 query = request.getParser();
338                                                 transactionId = request.getTransactionId();
339                                                 uriTemp = request.getUri().getRawPath().replaceFirst("^v\\d+/", "");
340                                                 uri = UriBuilder.fromPath(uriTemp).build();
341                                                 LoggingContext.startTime();
342                                                 List<Vertex> vertTemp;
343                                                 List<Vertex> vertices;
344                                                 if (this.isPaginated()) {
345                                                         vertTemp = query.getQueryBuilder().toList();
346                                                         this.setTotalsForPaging(vertTemp.size(), this.paginationBucket);
347                                                         vertices = vertTemp.subList(((this.paginationIndex - 1) * this.paginationBucket), Math.min((this.paginationBucket * this.paginationIndex), vertTemp.size()));
348                                                 } else {
349                                                         vertices = query.getQueryBuilder().toList();
350                                                 }
351                                                 boolean isNewVertex = false;
352                                                 String outputMediaType = getMediaType(request.getHeaders().getAcceptableMediaTypes());
353                                                 String result = null;
354                                                 params = request.getInfo().getQueryParameters(false);
355                                                 depth = setDepth(obj, params.getFirst("depth"));
356                                                 if (params.containsKey("format")) {
357                                                         format = Format.getFormat(params.getFirst("format"));
358                                                 }
359                                                 String cleanUp = params.getFirst("cleanup");
360                                                 String requestContext = "";
361                                                 List<String> requestContextList = request.getHeaders().getRequestHeader("aai-request-context");
362                                                 if (requestContextList != null) {
363                                                         requestContext = requestContextList.get(0);
364                                                 }
365
366                                                 if (cleanUp == null) {
367                                                         cleanUp = "false";
368                                                 }
369                                                 if (vertices.size() > 1 && processSingle && !(method.equals(HttpMethod.GET) || method.equals(HttpMethod.GET_RELATIONSHIP))) {
370                                                         if (method.equals(HttpMethod.DELETE)) {
371                                                                 LoggingContext.restoreIfPossible();
372                                                                 throw new AAIException("AAI_6138");
373                                                         } else {
374                                                                 LoggingContext.restoreIfPossible();
375                                                                 throw new AAIException("AAI_6137");
376                                                         }
377                                                 }
378                                                 if (method.equals(HttpMethod.PUT)) {
379                                                         String resourceVersion = (String) obj.getValue("resource-version");
380                                                         if (vertices.isEmpty()) {
381                                                                 if (enableResourceVersion) {
382                                                                         serializer.verifyResourceVersion("create", query.getResultType(), "", resourceVersion, obj.getURI());
383                                                                 }
384                                                                 isNewVertex = true;
385                                                         } else {
386                                                                 if (enableResourceVersion) {
387                                                                         serializer.verifyResourceVersion("update", query.getResultType(), vertices.get(0).<String>property("resource-version").orElse(null), resourceVersion, obj.getURI());
388                                                                 }
389                                                                 isNewVertex = false;
390                                                         }
391                                                 } else {
392                                                         if (vertices.isEmpty()) {
393                                                                 String msg = createNotFoundMessage(query.getResultType(), request.getUri());
394                                                                 throw new AAIException("AAI_6114", msg);
395                                                         } else {
396                                                                 isNewVertex = false;
397                                                         }
398                                                 }
399                                                 Vertex v = null;
400                                                 if (!isNewVertex) {
401                                                         v = vertices.get(0);
402                                                 }
403                                                 HashMap<String, Introspector> relatedObjects = new HashMap<>();
404                                                 String nodeOnly = params.getFirst("nodes-only");
405                                                 boolean isNodeOnly = nodeOnly != null;
406                                                 switch (method) {
407                                                         case GET:
408
409                                                                 if (format == null) {
410                                                                         obj = this.getObjectFromDb(vertices, serializer, query, obj, request.getUri(), depth, isNodeOnly, cleanUp);
411
412
413                                                                         LoggingContext.elapsedTime((long) serializer.getDBTimeMsecs(), TimeUnit.MILLISECONDS);
414                                                                         LOGGER.info("Completed");
415                                                                         LoggingContext.restoreIfPossible();
416
417                                                                         if (obj != null) {
418                                                                                 status = Status.OK;
419                                                                                 MarshallerProperties properties;
420                                                                                 if (!request.getMarshallerProperties().isPresent()) {
421                                                                                         properties = new MarshallerProperties.Builder(org.onap.aai.restcore.MediaType.getEnum(outputMediaType)).build();
422                                                                                 } else {
423                                                                                         properties = request.getMarshallerProperties().get();
424                                                                                 }
425                                                                                 result = obj.marshal(properties);
426                                                                         }
427                                                                 } else {
428                                                                         FormatFactory ff = new FormatFactory(loader, serializer, schemaVersions, basePath + "/");
429                                                                         Formatter formatter = ff.get(format, params);
430                                                                         result = formatter.output(vertices.stream().map(vertex -> (Object) vertex).collect(Collectors.toList())).toString();
431                                                                         status = Status.OK;
432                                                                 }
433
434                                                                 break;
435                                                         case GET_RELATIONSHIP:
436                                                                 if (format == null) {
437                                                                         obj = this.getRelationshipObjectFromDb(vertices, serializer, query, request.getInfo().getRequestUri());
438
439                                                                         LoggingContext.elapsedTime((long) serializer.getDBTimeMsecs(), TimeUnit.MILLISECONDS);
440                                                                         LOGGER.info("Completed");
441                                                                         LoggingContext.restoreIfPossible();
442
443                                                                         if (obj != null) {
444                                                                                 status = Status.OK;
445                                                                                 MarshallerProperties properties;
446                                                                                 if (!request.getMarshallerProperties().isPresent()) {
447                                                                                         properties = new MarshallerProperties.Builder(org.onap.aai.restcore.MediaType.getEnum(outputMediaType)).build();
448                                                                                 } else {
449                                                                                         properties = request.getMarshallerProperties().get();
450                                                                                 }
451                                                                                 result = obj.marshal(properties);
452                                                                         } else {
453                                                                                 String msg = createRelationshipNotFoundMessage(query.getResultType(), request.getUri());
454                                                                                 throw new AAIException("AAI_6149", msg);
455                                                                         }
456                                                                 } else {
457                                                                         FormatFactory ff = new FormatFactory(loader, serializer, schemaVersions, basePath + "/");
458                                                                         Formatter formatter = ff.get(format, params);
459                                                                         result = formatter.output(vertices.stream().map(vertex -> (Object) vertex).collect(Collectors.toList())).toString();
460                                                                         status = Status.OK;
461                                                                 }
462                                                                 break;
463                                                         case PUT:
464                                                                 response = this.invokeExtension(dbEngine, this.dbEngine.tx(), method, request, sourceOfTruth, version, loader, obj, uri, true);
465                                                                 if (isNewVertex) {
466                                                                         v = serializer.createNewVertex(obj);
467                                                                 }
468                                                                 serializer.serializeToDb(obj, v, query, uri.getRawPath(), requestContext);
469                                                                 this.invokeExtension(dbEngine, this.dbEngine.tx(), HttpMethod.PUT, request, sourceOfTruth, version, loader, obj, uri, false);
470                                                                 status = Status.OK;
471                                                                 if (isNewVertex) {
472                                                                         status = Status.CREATED;
473                                                                 }
474                                                                 obj = serializer.getLatestVersionView(v);
475                                                                 if (query.isDependent()) {
476                                                                         relatedObjects = this.getRelatedObjects(serializer, queryEngine, v, obj, this.loader);
477                                                                 }
478                                                                 LoggingContext.elapsedTime((long) serializer.getDBTimeMsecs() +
479                                                                         (long) queryEngine.getDBTimeMsecs(), TimeUnit.MILLISECONDS);
480                                                                 LOGGER.info("Completed ");
481                                                                 LoggingContext.restoreIfPossible();
482                                                                 notification.createNotificationEvent(transactionId, sourceOfTruth, status, uri, obj, relatedObjects, basePath);
483
484                                                                 break;
485                                                         case PUT_EDGE:
486                                                                 serializer.touchStandardVertexProperties(v, false);
487                                                                 this.invokeExtension(dbEngine, this.dbEngine.tx(), method, request, sourceOfTruth, version, loader, obj, uri, true);
488                                                                 serializer.createEdge(obj, v);
489
490                                                                 LoggingContext.elapsedTime((long) serializer.getDBTimeMsecs(), TimeUnit.MILLISECONDS);
491                                                                 LOGGER.info("Completed");
492                                                                 LoggingContext.restoreIfPossible();
493                                                                 status = Status.OK;
494                                                                 notification.createNotificationEvent(transactionId, sourceOfTruth, status, new URI(uri.toString().replace("/relationship-list/relationship", "")), serializer.getLatestVersionView(v), relatedObjects, basePath);
495                                                                 break;
496                                                         case MERGE_PATCH:
497                                                                 Introspector existingObj = loader.introspectorFromName(obj.getDbName());
498                                                                 existingObj = this.getObjectFromDb(vertices, serializer, query, existingObj, request.getUri(), 0, false, cleanUp);
499                                                                 String existingJson = existingObj.marshal(false);
500                                                                 String newJson;
501
502                                                                 if (request.getRawRequestContent().isPresent()) {
503                                                                         newJson = request.getRawRequestContent().get();
504                                                                 } else {
505                                                                         newJson = "";
506                                                                 }
507                                                                 Object relationshipList = request.getIntrospector().getValue("relationship-list");
508                                                                 ObjectMapper mapper = new ObjectMapper();
509                                                                 try {
510                                                                         JsonNode existingNode = mapper.readTree(existingJson);
511                                                                         JsonNode newNode = mapper.readTree(newJson);
512                                                                         JsonMergePatch patch = JsonMergePatch.fromJson(newNode);
513                                                                         JsonNode completed = patch.apply(existingNode);
514                                                                         String patched = mapper.writeValueAsString(completed);
515                                                                         Introspector patchedObj = loader.unmarshal(existingObj.getName(), patched);
516                                                                         if (relationshipList == null) {
517                                                                                 //if the caller didn't touch the relationship-list, we shouldn't either
518                                                                                 patchedObj.setValue("relationship-list", null);
519                                                                         }
520                                                                         serializer.serializeToDb(patchedObj, v, query, uri.getRawPath(), requestContext);
521                                                                         status = Status.OK;
522                                                                         patchedObj = serializer.getLatestVersionView(v);
523                                                                         if (query.isDependent()) {
524                                                                                 relatedObjects = this.getRelatedObjects(serializer, queryEngine, v, patchedObj, this.loader);
525                                                                         }
526                                                                         LoggingContext.elapsedTime((long) serializer.getDBTimeMsecs() +
527                                                                                 (long) queryEngine.getDBTimeMsecs(), TimeUnit.MILLISECONDS);
528                                                                         LOGGER.info("Completed");
529                                                                         LoggingContext.restoreIfPossible();
530                                                                         notification.createNotificationEvent(transactionId, sourceOfTruth, status, uri, patchedObj, relatedObjects, basePath);
531                                                                 } catch (IOException | JsonPatchException e) {
532
533                                                                         LOGGER.info("Caught exception: " + e.getMessage());
534                                                                         LoggingContext.restoreIfPossible();
535                                                                         throw new AAIException("AAI_3000", "could not perform patch operation");
536                                                                 }
537                                                                 break;
538                                                         case DELETE:
539                                                                 String resourceVersion = params.getFirst("resource-version");
540                                                                 obj = serializer.getLatestVersionView(v);
541                                                                 if (query.isDependent()) {
542                                                                         relatedObjects = this.getRelatedObjects(serializer, queryEngine, v, obj, this.loader);
543                                                                 }
544                                                                 /*
545                                                                  * Find all Delete-other-vertex vertices and create structure for notify
546                                                                  * findDeleatble also returns the startVertex v and we dont want to create
547                                                                  * duplicate notification events for the same
548                                                                  * So remove the startvertex first
549                                                                  */
550
551                                                                 List<Vertex> deletableVertices = dbEngine.getQueryEngine().findDeletable(v);
552                                                                 Long vId = (Long) v.id();
553
554                                                                 /*
555                                                                  * I am assuming vertexId cant be null
556                                                                  */
557                                                                 deletableVertices.removeIf(s -> vId.equals(s.id()));
558                                                                 boolean isDelVerticesPresent = !deletableVertices.isEmpty();
559                                                                 Map<Vertex, Introspector> deleteObjects = new HashMap<>();
560                                                                 Map<String, URI> uriMap = new HashMap<>();
561                                                                 Map<String, HashMap<String, Introspector>> deleteRelatedObjects = new HashMap<>();
562
563                                                                 if (isDelVerticesPresent) {
564                                                                         deleteObjects = this.buildIntrospectorObjects(serializer, deletableVertices);
565
566                                                                         uriMap = this.buildURIMap(serializer, deleteObjects);
567                                                                         deleteRelatedObjects = this.buildRelatedObjects(serializer, queryEngine, deleteObjects);
568                                                                 }
569
570                                                                 this.invokeExtension(dbEngine, this.dbEngine.tx(), method, request, sourceOfTruth, version, loader, obj, uri, true);
571                                                                 serializer.delete(v, deletableVertices, resourceVersion, enableResourceVersion);
572                                                                 this.invokeExtension(dbEngine, this.dbEngine.tx(), method, request, sourceOfTruth, version, loader, obj, uri, false);
573
574                                                                 LoggingContext.elapsedTime((long) serializer.getDBTimeMsecs() +
575                                                                         (long) queryEngine.getDBTimeMsecs(), TimeUnit.MILLISECONDS);
576                                                                 LOGGER.info("Completed");
577                                                                 LoggingContext.restoreIfPossible();
578                                                                 status = Status.NO_CONTENT;
579                                                                 notification.createNotificationEvent(transactionId, sourceOfTruth, status, uri, obj, relatedObjects, basePath);
580
581                                                                 /*
582                                                                  * Notify delete-other-v candidates
583                                                                  */
584
585                                                                 if (isDelVerticesPresent) {
586                                                                         this.buildNotificationEvent(sourceOfTruth, status, transactionId, notification, deleteObjects,
587                                                                                 uriMap, deleteRelatedObjects, basePath);
588                                                                 }
589
590                                                                 break;
591                                                         case DELETE_EDGE:
592                                                                 serializer.touchStandardVertexProperties(v, false);
593                                                                 serializer.deleteEdge(obj, v);
594
595                                                                 LoggingContext.elapsedTime((long) serializer.getDBTimeMsecs(), TimeUnit.MILLISECONDS);
596                                                                 LOGGER.info("Completed");
597                                                                 LoggingContext.restoreIfPossible();
598                                                                 status = Status.NO_CONTENT;
599                                                                 notification.createNotificationEvent(transactionId, sourceOfTruth, Status.OK, new URI(uri.toString().replace("/relationship-list/relationship", "")), serializer.getLatestVersionView(v), relatedObjects, basePath);
600                                                                 break;
601                                                         default:
602                                                                 break;
603                                                 }
604
605
606                                                 /* temporarily adding vertex id to the headers
607                                                  * to be able to use for testing the vertex id endpoint functionality
608                                                  * since we presently have no other way of generating those id urls
609                                                  */
610                                                 if (response == null && v != null && (
611                                                         method.equals(HttpMethod.PUT)
612                                                                 || method.equals(HttpMethod.GET)
613                                                                 || method.equals(HttpMethod.MERGE_PATCH)
614                                                                 || method.equals(HttpMethod.GET_RELATIONSHIP))
615
616                                                         ) {
617                                                         String myvertid = v.id().toString();
618                                                         if (this.isPaginated()) {
619                                                                 response = Response.status(status)
620                                                                         .header("vertex-id", myvertid)
621                                                                         .header("total-results", this.getTotalVertices())
622                                                                         .header("total-pages", this.getTotalPaginationBuckets())
623                                                                         .entity(result)
624                                                                         .type(outputMediaType).build();
625                                                         } else {
626                                                                 response = Response.status(status)
627                                                                         .header("vertex-id", myvertid)
628                                                                         .entity(result)
629                                                                         .type(outputMediaType).build();
630                                                         }
631                                                 } else if (response == null) {
632                                                         response = Response.status(status)
633                                                                 .type(outputMediaType).build();
634                                                 } else {
635                                                         //response already set to something
636                                                 }
637                                                 Pair<URI, Response> pairedResp = Pair.with(request.getUri(), response);
638                                                 responses.add(pairedResp);
639                                                 //break out of retry loop
640                                                 break;
641                                         } catch (JanusGraphException e) {
642                                                 this.dbEngine.rollback();
643
644                                                 LOGGER.info("Caught exception: " + e.getMessage());
645                                                 LoggingContext.restoreIfPossible();
646                                                 AAIException ex = new AAIException("AAI_6142", e);
647                                                 ErrorLogHelper.logException(ex);
648                                                 Thread.sleep((retry + 1) * 20L);
649                                                 this.dbEngine.startTransaction();
650                                                 queryEngine = dbEngine.getQueryEngine();
651                                                 serializer = new DBSerializer(version, dbEngine, introspectorFactoryType, sourceOfTruth);
652                                         }
653                                         if (retry == maxRetries) {
654                                                 throw new AAIException("AAI_6134");
655                                         }
656                                 }
657                         } catch (AAIException e) {
658                                 success = false;
659                                 ArrayList<String> templateVars = new ArrayList<>();
660                                 templateVars.add(request.getMethod().toString()); //GET, PUT, etc
661                                 templateVars.add(request.getUri().getPath());
662                                 templateVars.addAll(e.getTemplateVars());
663                                 ErrorLogHelper.logException(e);
664                                 response = Response
665                                         .status(e.getErrorObject().getHTTPResponseCode())
666                                         .entity(ErrorLogHelper.getRESTAPIErrorResponse(request.getHeaders().getAcceptableMediaTypes(), e, templateVars))
667                                         .build();
668                                 Pair<URI, Response> pairedResp = Pair.with(request.getUri(), response);
669                                 responses.add(pairedResp);
670                                 continue;
671                         } catch (Exception e) {
672                                 success = false;
673                                 e.printStackTrace();
674                                 AAIException ex = new AAIException("AAI_4000", e);
675                                 ArrayList<String> templateVars = new ArrayList<String>();
676                                 templateVars.add(request.getMethod().toString()); //GET, PUT, etc
677                                 templateVars.add(request.getUri().getPath().toString());
678                                 ErrorLogHelper.logException(ex);
679                                 response = Response
680                                         .status(ex.getErrorObject().getHTTPResponseCode())
681                                         .entity(ErrorLogHelper.getRESTAPIErrorResponse(request.getHeaders().getAcceptableMediaTypes(), ex, templateVars))
682                                         .build();
683                                 Pair<URI, Response> pairedResp = Pair.with(request.getUri(), response);
684                                 responses.add(pairedResp);
685                                 continue;
686                         }
687                 }
688                 notification.triggerEvents();
689                 return Pair.with(success, responses);
690         }
691
692
693         /**
694          * Gets the media type.
695          *
696          * @param mediaTypeList the media type list
697          * @return the media type
698          */
699         private String getMediaType(List<MediaType> mediaTypeList) {
700                 String mediaType = MediaType.APPLICATION_JSON;  // json is the default
701                 for (MediaType mt : mediaTypeList) {
702                         if (MediaType.APPLICATION_XML_TYPE.isCompatible(mt)) {
703                                 mediaType = MediaType.APPLICATION_XML;
704                         }
705                 }
706                 return mediaType;
707         }
708
709         /**
710          * Gets the object from db.
711          *
712          * @param serializer the serializer
713          * @param query the query
714          * @param obj the obj
715          * @param uri the uri
716          * @param depth the depth
717          * @param cleanUp the clean up
718          * @return the object from db
719          * @throws AAIException the AAI exception
720          * @throws IllegalAccessException the illegal access exception
721          * @throws IllegalArgumentException the illegal argument exception
722          * @throws InvocationTargetException the invocation target exception
723          * @throws SecurityException the security exception
724          * @throws InstantiationException the instantiation exception
725          * @throws NoSuchMethodException the no such method exception
726          * @throws UnsupportedEncodingException the unsupported encoding exception
727          * @throws MalformedURLException the malformed URL exception
728          * @throws AAIUnknownObjectException
729          * @throws URISyntaxException
730          */
731         private Introspector getObjectFromDb(List<Vertex> results, DBSerializer serializer, QueryParser query, Introspector obj, URI uri, int depth, boolean nodeOnly, String cleanUp) throws AAIException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException, InstantiationException, NoSuchMethodException, UnsupportedEncodingException, AAIUnknownObjectException, URISyntaxException {
732
733                 //nothing found
734                 if (results.isEmpty()) {
735                         String msg = createNotFoundMessage(query.getResultType(), uri);
736                         throw new AAIException("AAI_6114", msg);
737                 }
738
739                 return serializer.dbToObject(results, obj, depth, nodeOnly, cleanUp);
740
741         }
742
743         /**
744          * Gets the object from db.
745          *
746          * @param serializer the serializer
747          * @param query the query
748          * @param obj the obj
749          * @param uri the uri
750          * @param depth the depth
751          * @param cleanUp the clean up
752          * @return the object from db
753          * @throws AAIException the AAI exception
754          * @throws IllegalAccessException the illegal access exception
755          * @throws IllegalArgumentException the illegal argument exception
756          * @throws InvocationTargetException the invocation target exception
757          * @throws SecurityException the security exception
758          * @throws InstantiationException the instantiation exception
759          * @throws NoSuchMethodException the no such method exception
760          * @throws UnsupportedEncodingException the unsupported encoding exception
761          * @throws MalformedURLException the malformed URL exception
762          * @throws AAIUnknownObjectException
763          * @throws URISyntaxException
764          */
765         private Introspector getRelationshipObjectFromDb(List<Vertex> results, DBSerializer serializer, QueryParser query, URI uri) throws AAIException, IllegalArgumentException, SecurityException, UnsupportedEncodingException, AAIUnknownObjectException {
766
767                 //nothing found
768                 if (results.isEmpty()) {
769                         String msg = createNotFoundMessage(query.getResultType(), uri);
770                         throw new AAIException("AAI_6114", msg);
771                 }
772
773                 if (results.size() > 1) {
774                         throw new AAIException("AAI_6148", uri.getPath());
775                 }
776
777                 Vertex v = results.get(0);
778                 return serializer.dbToRelationshipObject(v);
779         }
780
781         /**
782          * Invoke extension.
783          *
784          * @param dbEngine the db engine
785          * @param g the g
786          * @param httpMethod the http method
787          * @param fromAppId the from app id
788          * @param apiVersion the api version
789          * @param loader the loader
790          * @param obj the obj
791          * @param uri the uri
792          * @param isPreprocess the is preprocess
793          * @return the response
794          * @throws IllegalArgumentException the illegal argument exception
795          * @throws UnsupportedEncodingException the unsupported encoding exception
796          * @throws AAIException the AAI exception
797          */
798         private Response invokeExtension(TransactionalGraphEngine dbEngine, Graph g, HttpMethod httpMethod, DBRequest request, String fromAppId, SchemaVersion apiVersion, Loader loader, Introspector obj, URI uri, boolean isPreprocess) throws IllegalArgumentException, UnsupportedEncodingException, AAIException {
799                 AAIExtensionMap aaiExtMap = new AAIExtensionMap();
800                 //ModelInjestor injestor = ModelInjestor.getInstance();
801                 Response response = null;
802                 URIToExtensionInformation extensionInformation = new URIToExtensionInformation(loader, uri);
803                 aaiExtMap.setHttpEntry(this);
804                 aaiExtMap.setDbRequest(request);
805                 aaiExtMap.setTransId(request.getTransactionId());
806                 aaiExtMap.setFromAppId(fromAppId);
807                 aaiExtMap.setGraph(g);
808                 aaiExtMap.setApiVersion(apiVersion.toString());
809                 aaiExtMap.setObjectFromRequest(obj);
810                 aaiExtMap.setObjectFromRequestType(obj.getJavaClassName());
811                 aaiExtMap.setObjectFromResponse(obj);
812                 aaiExtMap.setObjectFromResponseType(obj.getJavaClassName());
813                 aaiExtMap.setJaxbContext(nodeIngestor.getContextForVersion(apiVersion));
814                 aaiExtMap.setUri(uri.getRawPath());
815                 aaiExtMap.setTransactionalGraphEngine(dbEngine);
816                 aaiExtMap.setLoader(loader);
817                 aaiExtMap.setNamespace(extensionInformation.getNamespace());
818
819                 ExtensionController ext = new ExtensionController();
820                 ext.runExtension(aaiExtMap.getApiVersion(),
821                         extensionInformation.getNamespace(),
822                         extensionInformation.getTopObject(),
823                         extensionInformation.getMethodName(httpMethod, isPreprocess),
824                         aaiExtMap,
825                         isPreprocess);
826
827                 if (aaiExtMap.getPrecheckAddedList().size() > 0) {
828                         response = notifyOnSkeletonCreation(aaiExtMap, obj, request.getHeaders());
829                 }
830
831                 return response;
832         }
833
834         /**
835          * Notify on skeleton creation.
836          *
837          * @param aaiExtMap the aai ext map
838          * @param input the input
839          * @param headers the headers
840          * @return the response
841          */
842         //Legacy support
843         private Response notifyOnSkeletonCreation(AAIExtensionMap aaiExtMap, Introspector input, HttpHeaders headers) {
844                 Response response = null;
845                 HashMap<AAIException, ArrayList<String>> exceptionList = new HashMap<AAIException, ArrayList<String>>();
846
847                 StringBuilder keyString = new StringBuilder();
848
849                 Set<String> resourceKeys = input.getKeys();
850                 for (String key : resourceKeys) {
851                         keyString.append(key).append("=").append(input.getValue(key).toString()).append(" ");
852                 }
853
854                 for (AAIResponseMessage msg : aaiExtMap.getPrecheckResponseMessages().getAAIResponseMessage()) {
855                         ArrayList<String> templateVars = new ArrayList<>();
856
857                         templateVars.add("PUT " + input.getDbName());
858                         templateVars.add(keyString.toString());
859                         List<String> keys = new ArrayList<>();
860                         templateVars.add(msg.getAaiResponseMessageResourceType());
861                         for (AAIResponseMessageDatum dat : msg.getAaiResponseMessageData().getAAIResponseMessageDatum()) {
862                                 keys.add(dat.getAaiResponseMessageDatumKey() + "=" + dat.getAaiResponseMessageDatumValue());
863                         }
864                         templateVars.add(StringUtils.join(keys, ", "));
865                         exceptionList.put(new AAIException("AAI_0004", msg.getAaiResponseMessageResourceType()),
866                                 templateVars);
867                 }
868                 response = Response
869                         .status(Status.ACCEPTED).entity(ErrorLogHelper
870                                 .getRESTAPIInfoResponse(headers.getAcceptableMediaTypes(), exceptionList))
871                         .build();
872
873                 return response;
874         }
875
876         /**
877          * Creates the not found message.
878          *
879          * @param resultType the result type
880          * @param uri the uri
881          * @return the string
882          */
883         private String createNotFoundMessage(String resultType, URI uri) {
884
885                 String msg = "No Node of type " + resultType + " found at: " + uri.getPath();
886
887                 return msg;
888         }
889
890         /**
891          * Creates the not found message.
892          *
893          * @param resultType the result type
894          * @param uri the uri
895          * @return the string
896          */
897         private String createRelationshipNotFoundMessage(String resultType, URI uri) {
898
899                 String msg = "No relationship found of type " + resultType + " at the given URI: " + uri.getPath() + "/relationship-list";
900
901                 return msg;
902         }
903
904         /**
905          * Sets the depth.
906          *
907          * @param depthParam the depth param
908          * @return the int
909          * @throws AAIException the AAI exception
910          */
911         protected int setDepth(Introspector obj, String depthParam) throws AAIException {
912                 int depth = AAIProperties.MAXIMUM_DEPTH;
913
914                 String getAllRandomStr = AAIConfig.get("aai.rest.getall.depthparam", "");
915                 if (depthParam != null && getAllRandomStr != null && !getAllRandomStr.isEmpty()
916                         && getAllRandomStr.equals(depthParam)) {
917                         return depth;
918                 }
919
920                 if (depthParam == null) {
921                         if (this.version.compareTo(schemaVersions.getDepthVersion()) >= 0) {
922                                 depth = 0;
923                         } else {
924                                 depth = AAIProperties.MAXIMUM_DEPTH;
925                         }
926                 } else {
927                         if (!depthParam.isEmpty() && !"all".equals(depthParam)) {
928                                 try {
929                                         depth = Integer.parseInt(depthParam);
930                                 } catch (Exception e) {
931                                         throw new AAIException("AAI_4016");
932                                 }
933
934                         }
935                 }
936                 String maxDepth = obj.getMetadata(ObjectMetadata.MAXIMUM_DEPTH);
937
938                 int maximumDepth = AAIProperties.MAXIMUM_DEPTH;
939
940                 if (maxDepth != null) {
941                         try {
942                                 maximumDepth = Integer.parseInt(maxDepth);
943                         } catch (Exception ex) {
944                                 throw new AAIException("AAI_4018");
945                         }
946                 }
947
948                 if (depth > maximumDepth) {
949                         throw new AAIException("AAI_3303");
950                 }
951
952                 return depth;
953         }
954
955         /**
956          * Checks if is modification method.
957          *
958          * @param method the method
959          * @return true, if is modification method
960          */
961         private boolean isModificationMethod(HttpMethod method) {
962                 boolean result = false;
963
964                 if (method.equals(HttpMethod.PUT) || method.equals(HttpMethod.PUT_EDGE) || method.equals(HttpMethod.DELETE_EDGE) || method.equals(HttpMethod.MERGE_PATCH)) {
965                         result = true;
966                 }
967
968                 return result;
969
970         }
971
972         /**
973          * Given an uri, introspector object and loader object
974          * it will check if the obj is top level object if it is,
975          * it will return immediately returning the uri passed in
976          * If it isn't, it will go through, get the uriTemplate
977          * from the introspector object and get the count of "/"s
978          * and remove that part of the uri using substring
979          * and keep doing that until the current object is top level
980          * Also added the max depth just so worst case scenario
981          * Then keep adding aai-uri to the list include the aai-uri passed in
982          * Convert that list into an array and return it
983          * <p>
984          *
985          * Example:
986          *
987          * <blockquote>
988          * aai-uri -> /cloud-infrastructure/cloud-regions/cloud-region/cloud-owner/cloud-region-id/tenants/tenant/tenant1/vservers/vserver/v1
989          *
990          * Given the uriTemplate vserver -> /vservers/vserver/{vserver-id}
991          * it converts to /vservers/vserver
992          *
993          * lastIndexOf /vservers/vserver in /cloud-infrastructure/cloud-regions/cloud-region/cloud-owner/cloud-region-id/tenants/tenant/tenant1/vservers/vserver/v1
994          *                                                                                                                                                                                                                                                                      ^
995          *                                                                                                                                                                                                                                                                      |
996          *                                                                                                                                                                                                                                                                      |
997          *                                                                                                                                                                                                                                                              lastIndexOf
998          * Use substring to get the string from 0 to that lastIndexOf
999          * aai-uri -> /cloud-infrastructure/cloud-regions/cloud-region/cloud-owner/cloud-region-id/tenants/tenant/tenant1
1000          *
1001          * From this new aai-uri, generate a introspector from the URITOObject class
1002          * and keep doing this until you
1003          *
1004          * </blockquote>
1005          *
1006          * @param aaiUri - aai-uri of the vertex representating the unique id of a given vertex
1007          * @param obj   - introspector object of the given starting vertex
1008          * @param loader - Type of loader which will always be MoxyLoader to support model driven
1009          * @return an array of strings which can be used to get the vertexes of parent and grand parents from a given vertex
1010          * @throws UnsupportedEncodingException
1011          * @throws AAIException
1012          */
1013         String[] convertIntrospectorToUriList(String aaiUri, Introspector obj, Loader loader) throws UnsupportedEncodingException, AAIException {
1014
1015                 List<String> uriList = new ArrayList<>();
1016                 String template = StringUtils.EMPTY;
1017                 String truncatedUri = aaiUri;
1018                 int depth = AAIProperties.MAXIMUM_DEPTH;
1019                 uriList.add(truncatedUri);
1020
1021                 while (depth >= 0 && !obj.isTopLevel()) {
1022                         template = obj.getMetadata(ObjectMetadata.URI_TEMPLATE);
1023
1024                         if (template == null) {
1025                                 LOGGER.warn("Unable to find the uriTemplate for the object {}", obj.getDbName());
1026                                 return null;
1027                         }
1028
1029                         int templateCount = StringUtils.countMatches(template, "/");
1030                         int truncatedUriCount = StringUtils.countMatches(truncatedUri, "/");
1031
1032                         if (templateCount > truncatedUriCount) {
1033                                 LOGGER.warn("Template uri {} contains more slashes than truncatedUri {}", template, truncatedUri);
1034                                 return null;
1035                         }
1036
1037                         int cutIndex = StringUtils.ordinalIndexOf(truncatedUri, "/", truncatedUriCount - templateCount + 1);
1038                         truncatedUri = StringUtils.substring(truncatedUri, 0, cutIndex);
1039                         uriList.add(truncatedUri);
1040                         obj = new URIToObject(loader, UriBuilder.fromPath(truncatedUri).build()).getEntity();
1041                         depth--;
1042                 }
1043
1044                 return uriList.toArray(new String[uriList.size()]);
1045         }
1046
1047         /**
1048          *
1049          * @param serializer
1050          * @param queryEngine
1051          * @param v
1052          * @param obj
1053          * @param loader
1054          * @return
1055          * @throws IllegalAccessException
1056          * @throws IllegalArgumentException
1057          * @throws InvocationTargetException
1058          * @throws SecurityException
1059          * @throws InstantiationException
1060          * @throws NoSuchMethodException
1061          * @throws UnsupportedEncodingException
1062          * @throws AAIException
1063          * @throws URISyntaxException
1064          */
1065         private HashMap<String, Introspector> getRelatedObjects(DBSerializer serializer, QueryEngine queryEngine, Vertex v, Introspector obj, Loader loader) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException, InstantiationException, NoSuchMethodException, UnsupportedEncodingException, AAIException, URISyntaxException {
1066
1067                 HashMap<String, Introspector> relatedVertices = new HashMap<>();
1068                 VertexProperty aaiUriProperty = v.property(AAIProperties.AAI_URI);
1069
1070                 if (!aaiUriProperty.isPresent()) {
1071                         if (LOGGER.isDebugEnabled()) {
1072                                 LOGGER.debug("For the given vertex {}, it seems aai-uri is not present so not getting related objects", v.id().toString());
1073                         } else {
1074                                 LOGGER.info("It seems aai-uri is not present in vertex, so not getting related objects, for more info enable debug log");
1075                         }
1076                         return relatedVertices;
1077                 }
1078
1079                 String aaiUri = aaiUriProperty.value().toString();
1080
1081                 if (!obj.isTopLevel()) {
1082                         String[] uriList = convertIntrospectorToUriList(aaiUri, obj, loader);
1083                         List<Vertex> vertexChain = null;
1084                         // If the uriList is null then there is something wrong with converting the uri
1085                         // into a list of aai-uris so falling back to the old mechanism for finding parents
1086                         if (uriList == null) {
1087                                 LOGGER.info("Falling back to the old mechanism due to unable to convert aai-uri to list of uris but this is not optimal");
1088                                 vertexChain = queryEngine.findParents(v);
1089                         } else {
1090                                 vertexChain = queryEngine.findParents(uriList);
1091                         }
1092                         for (Vertex vertex : vertexChain) {
1093                                 try {
1094                                         final Introspector vertexObj = serializer.getVertexProperties(vertex);
1095                                         relatedVertices.put(vertexObj.getObjectId(), vertexObj);
1096                                 } catch (AAIUnknownObjectException e) {
1097                                         LOGGER.warn("Unable to get vertex properties, partial list of related vertices returned");
1098                                 }
1099                         }
1100                 } else {
1101                         try {
1102                                 final Introspector vertexObj = serializer.getVertexProperties(v);
1103                                 relatedVertices.put(vertexObj.getObjectId(), vertexObj);
1104                         } catch (AAIUnknownObjectException e) {
1105                                 LOGGER.warn("Unable to get vertex properties, partial list of related vertices returned");
1106                         }
1107                 }
1108
1109                 return relatedVertices;
1110         }
1111
1112         private Map<Vertex, Introspector> buildIntrospectorObjects(DBSerializer serializer, Iterable<Vertex> vertices) {
1113                 Map<Vertex, Introspector> deleteObjectMap = new HashMap<>();
1114                 for (Vertex vertex : vertices) {
1115                         try {
1116                                 // deleteObjectMap.computeIfAbsent(vertex, s ->
1117                                 // serializer.getLatestVersionView(vertex));
1118                                 Introspector deleteObj = serializer.getLatestVersionView(vertex);
1119                                 deleteObjectMap.put(vertex, deleteObj);
1120                         } catch (UnsupportedEncodingException | AAIException e) {
1121                                 LOGGER.warn("Unable to get Introspctor Objects, Just continue");
1122                                 continue;
1123                         }
1124
1125                 }
1126
1127                 return deleteObjectMap;
1128
1129         }
1130
1131         private Map<String, URI> buildURIMap(DBSerializer serializer, Map<Vertex, Introspector> introSpector) {
1132                 Map<String, URI> uriMap = new HashMap<>();
1133                 for (Map.Entry<Vertex, Introspector> entry : introSpector.entrySet()) {
1134                         URI uri;
1135                         try {
1136                                 uri = serializer.getURIForVertex(entry.getKey());
1137                                 if (null != entry.getValue()) {
1138                                         uriMap.put(entry.getValue().getObjectId(), uri);
1139                                 }
1140                         } catch (UnsupportedEncodingException e) {
1141                                 LOGGER.warn("Unable to get URIs, Just continue");
1142                                 continue;
1143                         }
1144
1145                 }
1146
1147                 return uriMap;
1148
1149         }
1150
1151         private Map<String, HashMap<String, Introspector>> buildRelatedObjects(DBSerializer serializer,
1152                                                                                                                                                    QueryEngine queryEngine, Map<Vertex, Introspector> introSpector) {
1153
1154                 Map<String, HashMap<String, Introspector>> relatedObjectsMap = new HashMap<>();
1155                 for (Map.Entry<Vertex, Introspector> entry : introSpector.entrySet()) {
1156                         try {
1157                                 HashMap<String, Introspector> relatedObjects = this.getRelatedObjects(serializer, queryEngine,
1158                                         entry.getKey(), entry.getValue(), this.loader);
1159                                 if (null != entry.getValue()) {
1160                                         relatedObjectsMap.put(entry.getValue().getObjectId(), relatedObjects);
1161                                 }
1162                         } catch (IllegalAccessException | IllegalArgumentException
1163                                 | InvocationTargetException | SecurityException | InstantiationException | NoSuchMethodException
1164                                 | UnsupportedEncodingException | AAIException | URISyntaxException e) {
1165                                 LOGGER.warn("Unable to get realted Objects, Just continue");
1166                                 continue;
1167                         }
1168
1169                 }
1170
1171                 return relatedObjectsMap;
1172
1173         }
1174
1175         private void buildNotificationEvent(String sourceOfTruth, Status status, String transactionId,
1176                                                                                 UEBNotification notification, Map<Vertex, Introspector> deleteObjects, Map<String, URI> uriMap,
1177                                                                                 Map<String, HashMap<String, Introspector>> deleteRelatedObjects, String basePath) {
1178                 for (Map.Entry<Vertex, Introspector> entry : deleteObjects.entrySet()) {
1179                         try {
1180                                 String vertexObjectId = "";
1181
1182                                 if (null != entry.getValue()) {
1183                                         vertexObjectId = entry.getValue().getObjectId();
1184
1185                                         if (uriMap.containsKey(vertexObjectId) && deleteRelatedObjects.containsKey(vertexObjectId)) {
1186                                                 notification.createNotificationEvent(transactionId, sourceOfTruth, status,
1187                                                         uriMap.get(vertexObjectId), entry.getValue(), deleteRelatedObjects.get(vertexObjectId), basePath);
1188                                         }
1189                                 }
1190                         } catch (UnsupportedEncodingException | AAIException e) {
1191
1192                                 LOGGER.warn("Error in sending notification");
1193                         }
1194                 }
1195         }
1196
1197         public void setPaginationParameters(String resultIndex, String resultSize) {
1198                 if (resultIndex != null && resultIndex != "-1" && resultSize != null && resultSize != "-1") {
1199                         this.setPaginationIndex(Integer.parseInt(resultIndex));
1200                         this.setPaginationBucket(Integer.parseInt(resultSize));
1201                 }
1202         }
1203
1204         public List<Object> getPaginatedVertexList(List<Object> vertexList) throws AAIException {
1205                 List<Object> vertices;
1206                 if (this.isPaginated()) {
1207                         this.setTotalsForPaging(vertexList.size(), this.getPaginationBucket());
1208                         int startIndex = (this.getPaginationIndex() - 1) * this.getPaginationBucket();
1209                         int endIndex = Math.min((this.getPaginationBucket() * this.getPaginationIndex()), vertexList.size());
1210                         if (startIndex > endIndex) {
1211                                 throw new AAIException("AAI_6150", " ResultIndex is not appropriate for the result set, Needs to be <= " + endIndex);
1212                         }
1213                         vertices = vertexList.subList(startIndex, endIndex);
1214                 } else {
1215                         vertices = vertexList;
1216                 }
1217                 return vertices;
1218         }
1219 }