2 * ============LICENSE_START=======================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
20 package org.onap.aai.rest.db;
23 import java.io.IOException;
24 import java.io.UnsupportedEncodingException;
25 import java.lang.reflect.InvocationTargetException;
26 import java.net.MalformedURLException;
28 import java.net.URISyntaxException;
29 import java.util.ArrayList;
30 import java.util.HashMap;
31 import java.util.List;
34 import java.util.concurrent.TimeUnit;
35 import java.util.stream.Collectors;
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;
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.janusgraph.core.JanusGraphException;
54 import org.javatuples.Pair;
55 import org.onap.aai.db.props.AAIProperties;
56 import org.onap.aai.dbmap.DBConnectionType;
57 import org.onap.aai.domain.responseMessage.AAIResponseMessage;
58 import org.onap.aai.domain.responseMessage.AAIResponseMessageDatum;
59 import org.onap.aai.exceptions.AAIException;
60 import org.onap.aai.extensions.AAIExtensionMap;
61 import org.onap.aai.extensions.ExtensionController;
62 import org.onap.aai.introspection.*;
63 import org.onap.aai.introspection.exceptions.AAIUnknownObjectException;
64 import org.onap.aai.logging.ErrorLogHelper;
65 import org.onap.aai.logging.LoggingContext;
66 import org.onap.aai.nodes.NodeIngestor;
67 import org.onap.aai.parsers.query.QueryParser;
68 import org.onap.aai.parsers.uri.URIToExtensionInformation;
70 import org.onap.aai.rest.ueb.UEBNotification;
71 import org.onap.aai.restcore.HttpMethod;
72 import org.onap.aai.schema.enums.ObjectMetadata;
73 import org.onap.aai.serialization.db.DBSerializer;
74 import org.onap.aai.serialization.engines.JanusGraphDBEngine;
75 import org.onap.aai.serialization.engines.QueryStyle;
76 import org.onap.aai.serialization.engines.TransactionalGraphEngine;
77 import org.onap.aai.serialization.engines.query.QueryEngine;
78 import org.onap.aai.serialization.queryformats.Format;
79 import org.onap.aai.serialization.queryformats.FormatFactory;
80 import org.onap.aai.serialization.queryformats.Formatter;
81 import org.onap.aai.setup.SchemaVersion;
82 import org.onap.aai.setup.SchemaVersions;
83 import org.onap.aai.util.AAIConfig;
84 import org.springframework.beans.factory.annotation.Autowired;
85 import org.springframework.beans.factory.annotation.Value;
88 * The Class HttpEntry.
90 public class HttpEntry {
92 private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(HttpEntry.class);
93 private static final String TARGET_ENTITY = "DB";
95 private ModelType introspectorFactoryType;
97 private QueryStyle queryStyle;
99 private SchemaVersion version;
101 private Loader loader;
103 private TransactionalGraphEngine dbEngine;
105 private boolean processSingle = true;
107 private int paginationBucket = -1;
108 private int paginationIndex = -1;
109 private int totalVertices = 0;
110 private int totalPaginationBuckets = 0;
113 private NodeIngestor nodeIngestor;
116 private LoaderFactory loaderFactory;
119 private SchemaVersions schemaVersions;
121 @Value("${schema.uri.base.path}")
122 private String basePath;
124 private UEBNotification notification;
127 * Instantiates a new http entry.
129 * @param modelType the model type
130 * @param queryStyle the query style
132 public HttpEntry(ModelType modelType, QueryStyle queryStyle) {
133 this.introspectorFactoryType = modelType;
134 this.queryStyle = queryStyle;
137 public HttpEntry setHttpEntryProperties(SchemaVersion version, DBConnectionType connectionType){
138 this.version = version;
139 this.loader = loaderFactory.createLoaderForVersion(introspectorFactoryType, version);
140 this.dbEngine = new JanusGraphDBEngine(
145 getDbEngine().startTransaction();
146 this.notification = new UEBNotification(loader, loaderFactory, schemaVersions);
151 public HttpEntry setHttpEntryProperties(SchemaVersion version, DBConnectionType connectionType, UEBNotification notification){
152 this.version = version;
153 this.loader = loaderFactory.createLoaderForVersion(introspectorFactoryType, version);
154 this.dbEngine = new JanusGraphDBEngine(
159 this.notification = notification;
160 //start transaction on creation
161 getDbEngine().startTransaction();
167 * Gets the introspector factory type.
169 * @return the introspector factory type
171 public ModelType getIntrospectorFactoryType() {
172 return introspectorFactoryType;
176 * Gets the query style.
178 * @return the query style
180 public QueryStyle getQueryStyle() {
187 * @return the version
189 public SchemaVersion getVersion() {
198 public Loader getLoader() {
203 * Gets the db engine.
205 * @return the db engine
207 public TransactionalGraphEngine getDbEngine() {
211 public Pair<Boolean, List<Pair<URI, Response>>> process (List<DBRequest> requests, String sourceOfTruth) throws AAIException {
212 return this.process(requests, sourceOfTruth, true);
217 * Checks the pagination bucket and pagination index variables to determine whether or not the user
218 * requested paginated results
220 * @return a boolean true/false of whether the user requested paginated results
222 public boolean isPaginated(){
223 return this.paginationBucket > -1 && this.paginationIndex > -1;
227 * Setter for the pagination bucket variable which stores in this object the size of results to return
230 public void setPaginationBucket(int pb){
231 this.paginationBucket = pb;
235 * Returns the pagination size
236 * @return integer of the size of results to be returned when paginated
238 public int getPaginationBucket(){
239 return this.paginationBucket;
243 * Sets the pagination index that was passed in by the user, to determine which index or results to retrieve when
247 public void setPaginationIndex(int pi){
251 this.paginationIndex = pi;
255 * Getter to return the pagination index requested by the user when requesting paginated results
258 public int getPaginationIndex(){
259 return this.paginationIndex;
263 * Sets the total vertices variables and calculates the amount of pages based on size and total vertices
264 * @param totalVertices
265 * @param paginationBucketSize
267 public void setTotalsForPaging(int totalVertices, int paginationBucketSize){
268 this.totalVertices = totalVertices;
269 //set total number of buckets equal to full pages
270 this.totalPaginationBuckets = totalVertices/paginationBucketSize;
271 //conditionally add a page for the remainder
272 if(totalVertices % paginationBucketSize > 0){
273 this.totalPaginationBuckets++;
278 * @return the total amount of pages
280 public int getTotalPaginationBuckets(){
281 return this.totalPaginationBuckets;
286 * @return the total number of vertices when paginated
288 public int getTotalVertices(){
289 return this.totalVertices;
294 * @param requests the requests
295 * @param sourceOfTruth the source of truth
298 * @throws AAIException the AAI exception
300 public Pair<Boolean, List<Pair<URI, Response>>> process (List<DBRequest> requests, String sourceOfTruth, boolean enableResourceVersion) throws AAIException {
302 DBSerializer serializer = new DBSerializer(version, dbEngine, introspectorFactoryType, sourceOfTruth);
303 String methodName = "process";
305 Introspector obj = null;
306 QueryParser query = null;
308 String transactionId = null;
309 int depth = AAIProperties.MAXIMUM_DEPTH;
310 Format format = null;
311 List<Pair<URI,Response>> responses = new ArrayList<>();
312 MultivaluedMap<String, String> params = null;
313 HttpMethod method = null;
315 Boolean success = true;
316 QueryEngine queryEngine = dbEngine.getQueryEngine();
320 LoggingContext.save();
321 for (DBRequest request : requests) {
323 Status status = Status.NOT_FOUND;
324 method = request.getMethod();
326 for (retry = 0; retry < maxRetries; ++retry) {
329 LoggingContext.targetEntity(TARGET_ENTITY);
330 LoggingContext.targetServiceName(methodName + " " + method);
332 obj = request.getIntrospector();
333 query = request.getParser();
334 transactionId = request.getTransactionId();
335 uriTemp = request.getUri().getRawPath().replaceFirst("^v\\d+/", "");
336 uri = UriBuilder.fromPath(uriTemp).build();
337 LoggingContext.startTime();
338 List<Vertex> vertTemp;
339 List<Vertex> vertices;
340 if(this.isPaginated()) {
341 vertTemp = query.getQueryBuilder().toList();
342 this.setTotalsForPaging(vertTemp.size(), this.paginationBucket);
343 vertices = vertTemp.subList(((this.paginationIndex - 1) * this.paginationBucket), Math.min((this.paginationBucket * this.paginationIndex), vertTemp.size()));
345 vertices = query.getQueryBuilder().toList();
347 boolean isNewVertex = false;
348 String outputMediaType = getMediaType(request.getHeaders().getAcceptableMediaTypes());
349 String result = null;
350 params = request.getInfo().getQueryParameters(false);
351 depth = setDepth(obj, params.getFirst("depth"));
352 if (params.containsKey("format")) {
353 format = Format.getFormat(params.getFirst("format"));
355 String cleanUp = params.getFirst("cleanup");
356 String requestContext = "";
357 List<String> requestContextList = request.getHeaders().getRequestHeader("aai-request-context");
358 if (requestContextList != null) {
359 requestContext = requestContextList.get(0);
362 if (cleanUp == null) {
365 if (vertices.size() > 1 && processSingle && !method.equals(HttpMethod.GET)) {
366 if (method.equals(HttpMethod.DELETE)) {
367 LoggingContext.restoreIfPossible();
368 throw new AAIException("AAI_6138");
370 LoggingContext.restoreIfPossible();
371 throw new AAIException("AAI_6137");
374 if (method.equals(HttpMethod.PUT)) {
375 String resourceVersion = (String)obj.getValue("resource-version");
376 if (vertices.isEmpty()) {
377 if (enableResourceVersion) {
378 serializer.verifyResourceVersion("create", query.getResultType(), "", resourceVersion, obj.getURI());
382 if (enableResourceVersion) {
383 serializer.verifyResourceVersion("update", query.getResultType(), vertices.get(0).<String>property("resource-version").orElse(null), resourceVersion, obj.getURI());
388 if (vertices.isEmpty()) {
389 String msg = createNotFoundMessage(query.getResultType(), request.getUri());
390 throw new AAIException("AAI_6114", msg);
399 HashMap<String, Introspector> relatedObjects = new HashMap<>();
402 String nodeOnly = params.getFirst("nodes-only");
403 boolean isNodeOnly = nodeOnly != null;
405 if (format == null) {
406 obj = this.getObjectFromDb(vertices, serializer, query, obj, request.getUri(), depth, isNodeOnly, cleanUp);
409 LoggingContext.elapsedTime((long) serializer.getDBTimeMsecs(), TimeUnit.MILLISECONDS);
410 LOGGER.info ("Completed");
411 LoggingContext.restoreIfPossible();
415 MarshallerProperties properties;
416 if (!request.getMarshallerProperties().isPresent()) {
417 properties = new MarshallerProperties.Builder(org.onap.aai.restcore.MediaType.getEnum(outputMediaType)).build();
419 properties = request.getMarshallerProperties().get();
421 result = obj.marshal(properties);
424 FormatFactory ff = new FormatFactory(loader, serializer, schemaVersions, basePath + "/");
425 Formatter formatter = ff.get(format, params);
426 result = formatter.output(vertices.stream().map(vertex -> (Object) vertex).collect(Collectors.toList())).toString();
432 response = this.invokeExtension(dbEngine, this.dbEngine.tx(), method, request, sourceOfTruth, version, loader, obj, uri, true);
434 v = serializer.createNewVertex(obj);
436 serializer.serializeToDb(obj, v, query, uri.getRawPath(), requestContext);
437 this.invokeExtension(dbEngine, this.dbEngine.tx(), HttpMethod.PUT, request, sourceOfTruth, version, loader, obj, uri, false);
440 status = Status.CREATED;
442 obj = serializer.getLatestVersionView(v);
443 if (query.isDependent()) {
444 relatedObjects = this.getRelatedObjects(serializer, queryEngine, v);
446 LoggingContext.elapsedTime((long)serializer.getDBTimeMsecs() +
447 (long)queryEngine.getDBTimeMsecs(), TimeUnit.MILLISECONDS);
448 LOGGER.info ("Completed ");
449 LoggingContext.restoreIfPossible();
450 notification.createNotificationEvent(transactionId, sourceOfTruth, status, uri, obj, relatedObjects, basePath);
454 serializer.touchStandardVertexProperties(v, false);
455 this.invokeExtension(dbEngine, this.dbEngine.tx(), method, request, sourceOfTruth, version, loader, obj, uri, true);
456 serializer.createEdge(obj, v);
458 LoggingContext.elapsedTime((long)serializer.getDBTimeMsecs(),TimeUnit.MILLISECONDS);
459 LOGGER.info ("Completed");
460 LoggingContext.restoreIfPossible();
462 notification.createNotificationEvent(transactionId, sourceOfTruth, status, new URI(uri.toString().replace("/relationship-list/relationship", "")), serializer.getLatestVersionView(v), relatedObjects, basePath);
465 Introspector existingObj = loader.introspectorFromName(obj.getDbName());
466 existingObj = this.getObjectFromDb(vertices, serializer, query, existingObj, request.getUri(), 0, false, cleanUp);
467 String existingJson = existingObj.marshal(false);
470 if (request.getRawRequestContent().isPresent()) {
471 newJson = request.getRawRequestContent().get();
475 Object relationshipList = request.getIntrospector().getValue("relationship-list");
476 ObjectMapper mapper = new ObjectMapper();
478 JsonNode existingNode = mapper.readTree(existingJson);
479 JsonNode newNode = mapper.readTree(newJson);
480 JsonMergePatch patch = JsonMergePatch.fromJson(newNode);
481 JsonNode completed = patch.apply(existingNode);
482 String patched = mapper.writeValueAsString(completed);
483 Introspector patchedObj = loader.unmarshal(existingObj.getName(), patched);
484 if (relationshipList == null) {
485 //if the caller didn't touch the relationship-list, we shouldn't either
486 patchedObj.setValue("relationship-list", null);
488 serializer.serializeToDb(patchedObj, v, query, uri.getRawPath(), requestContext);
490 patchedObj = serializer.getLatestVersionView(v);
491 if (query.isDependent()) {
492 relatedObjects = this.getRelatedObjects(serializer, queryEngine, v);
494 LoggingContext.elapsedTime((long)serializer.getDBTimeMsecs() +
495 (long)queryEngine.getDBTimeMsecs(), TimeUnit.MILLISECONDS);
496 LOGGER.info ("Completed");
497 LoggingContext.restoreIfPossible();
498 notification.createNotificationEvent(transactionId, sourceOfTruth, status, uri, patchedObj, relatedObjects, basePath);
499 } catch (IOException | JsonPatchException e) {
501 LOGGER.info ("Caught exception: " + e.getMessage());
502 LoggingContext.restoreIfPossible();
503 throw new AAIException("AAI_3000", "could not perform patch operation");
507 String resourceVersion = params.getFirst("resource-version");
508 obj = serializer.getLatestVersionView(v);
509 if (query.isDependent()) {
510 relatedObjects = this.getRelatedObjects(serializer, queryEngine, v);
513 * Find all Delete-other-vertex vertices and create structure for notify
514 * findDeleatble also returns the startVertex v and we dont want to create
515 * duplicate notification events for the same
516 * So remove the startvertex first
519 List<Vertex> deletableVertices = dbEngine.getQueryEngine().findDeletable(v);
520 Long vId = (Long) v.id();
523 * I am assuming vertexId cant be null
525 deletableVertices.removeIf(s -> vId.equals(s.id()));
526 boolean isDelVerticesPresent = !deletableVertices.isEmpty();
527 Map<Vertex, Introspector> deleteObjects = new HashMap<>();
528 Map<String, URI> uriMap = new HashMap<>();
529 Map<String, HashMap<String, Introspector>> deleteRelatedObjects = new HashMap<>();
531 if(isDelVerticesPresent){
532 deleteObjects = this.buildIntrospectorObjects(serializer, deletableVertices);
534 uriMap = this.buildURIMap(serializer, deleteObjects);
535 deleteRelatedObjects = this.buildRelatedObjects(serializer, queryEngine, deleteObjects);
538 this.invokeExtension(dbEngine, this.dbEngine.tx(), method, request, sourceOfTruth, version, loader, obj, uri, true);
539 serializer.delete(v, deletableVertices, resourceVersion, enableResourceVersion);
540 this.invokeExtension(dbEngine, this.dbEngine.tx(), method, request, sourceOfTruth, version, loader, obj, uri, false);
542 LoggingContext.elapsedTime((long)serializer.getDBTimeMsecs() +
543 (long)queryEngine.getDBTimeMsecs(), TimeUnit.MILLISECONDS);
544 LOGGER.info ("Completed");
545 LoggingContext.restoreIfPossible();
546 status = Status.NO_CONTENT;
547 notification.createNotificationEvent(transactionId, sourceOfTruth, status, uri, obj, relatedObjects, basePath);
550 * Notify delete-other-v candidates
553 if(isDelVerticesPresent){
554 this.buildNotificationEvent(sourceOfTruth, status, transactionId, notification, deleteObjects,
555 uriMap, deleteRelatedObjects, basePath);
560 serializer.touchStandardVertexProperties(v, false);
561 serializer.deleteEdge(obj, v);
563 LoggingContext.elapsedTime((long)serializer.getDBTimeMsecs(),TimeUnit.MILLISECONDS);
564 LOGGER.info ("Completed");
565 LoggingContext.restoreIfPossible();
566 status = Status.NO_CONTENT;
567 notification.createNotificationEvent(transactionId, sourceOfTruth, Status.OK, new URI(uri.toString().replace("/relationship-list/relationship", "")), serializer.getLatestVersionView(v), relatedObjects, basePath);
574 /* temporarily adding vertex id to the headers
575 * to be able to use for testing the vertex id endpoint functionality
576 * since we presently have no other way of generating those id urls
578 if (response == null && v != null && (
579 method.equals(HttpMethod.PUT)
580 || method.equals(HttpMethod.GET)
581 || method.equals(HttpMethod.MERGE_PATCH))
583 String myvertid = v.id().toString();
584 if(this.isPaginated()){
585 response = Response.status(status)
586 .header("vertex-id", myvertid)
587 .header("total-results", this.getTotalVertices())
588 .header("total-pages", this.getTotalPaginationBuckets())
590 .type(outputMediaType).build();
592 response = Response.status(status)
593 .header("vertex-id", myvertid)
595 .type(outputMediaType).build();
597 } else if (response == null) {
598 response = Response.status(status)
599 .type(outputMediaType).build();
601 //response already set to something
603 Pair<URI,Response> pairedResp = Pair.with(request.getUri(), response);
604 responses.add(pairedResp);
605 //break out of retry loop
607 } catch (JanusGraphException e) {
608 this.dbEngine.rollback();
610 LOGGER.info ("Caught exception: " + e.getMessage());
611 LoggingContext.restoreIfPossible();
612 AAIException ex = new AAIException("AAI_6142", e);
613 ErrorLogHelper.logException(ex);
614 Thread.sleep((retry + 1) * 20L);
615 this.dbEngine.startTransaction();
616 queryEngine = dbEngine.getQueryEngine();
617 serializer = new DBSerializer(version, dbEngine, introspectorFactoryType, sourceOfTruth);
619 if (retry == maxRetries) {
620 throw new AAIException("AAI_6134");
623 } catch (AAIException e) {
625 ArrayList<String> templateVars = new ArrayList<>();
626 templateVars.add(request.getMethod().toString()); //GET, PUT, etc
627 templateVars.add(request.getUri().getPath());
628 templateVars.addAll(e.getTemplateVars());
629 ErrorLogHelper.logException(e);
631 .status(e.getErrorObject().getHTTPResponseCode())
632 .entity(ErrorLogHelper.getRESTAPIErrorResponse(request.getHeaders().getAcceptableMediaTypes(), e, templateVars))
634 Pair<URI,Response> pairedResp = Pair.with(request.getUri(), response);
635 responses.add(pairedResp);
637 } catch (Exception e) {
640 AAIException ex = new AAIException("AAI_4000", e);
641 ArrayList<String> templateVars = new ArrayList<String>();
642 templateVars.add(request.getMethod().toString()); //GET, PUT, etc
643 templateVars.add(request.getUri().getPath().toString());
644 ErrorLogHelper.logException(ex);
646 .status(ex.getErrorObject().getHTTPResponseCode())
647 .entity(ErrorLogHelper.getRESTAPIErrorResponse(request.getHeaders().getAcceptableMediaTypes(), ex, templateVars))
649 Pair<URI, Response> pairedResp = Pair.with(request.getUri(), response);
650 responses.add(pairedResp);
654 notification.triggerEvents();
655 return Pair.with(success, responses);
660 * Gets the media type.
662 * @param mediaTypeList the media type list
663 * @return the media type
665 private String getMediaType(List <MediaType> mediaTypeList) {
666 String mediaType = MediaType.APPLICATION_JSON; // json is the default
667 for (MediaType mt : mediaTypeList) {
668 if (MediaType.APPLICATION_XML_TYPE.isCompatible(mt)) {
669 mediaType = MediaType.APPLICATION_XML;
676 * Gets the object from db.
678 * @param serializer the serializer
679 * @param query the query
682 * @param depth the depth
683 * @param cleanUp the clean up
684 * @return the object from db
685 * @throws AAIException the AAI exception
686 * @throws IllegalAccessException the illegal access exception
687 * @throws IllegalArgumentException the illegal argument exception
688 * @throws InvocationTargetException the invocation target exception
689 * @throws SecurityException the security exception
690 * @throws InstantiationException the instantiation exception
691 * @throws NoSuchMethodException the no such method exception
692 * @throws UnsupportedEncodingException the unsupported encoding exception
693 * @throws MalformedURLException the malformed URL exception
694 * @throws AAIUnknownObjectException
695 * @throws URISyntaxException
697 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 {
700 if (results.isEmpty()) {
701 String msg = createNotFoundMessage(query.getResultType(), uri);
702 throw new AAIException("AAI_6114", msg);
705 return serializer.dbToObject(results, obj, depth, nodeOnly, cleanUp);
712 * @param dbEngine the db engine
714 * @param httpMethod the http method
715 * @param fromAppId the from app id
716 * @param apiVersion the api version
717 * @param loader the loader
720 * @param isPreprocess the is preprocess
721 * @return the response
722 * @throws IllegalArgumentException the illegal argument exception
723 * @throws UnsupportedEncodingException the unsupported encoding exception
724 * @throws AAIException the AAI exception
726 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 {
727 AAIExtensionMap aaiExtMap = new AAIExtensionMap();
728 //ModelInjestor injestor = ModelInjestor.getInstance();
729 Response response = null;
730 URIToExtensionInformation extensionInformation = new URIToExtensionInformation(loader, uri);
731 aaiExtMap.setHttpEntry(this);
732 aaiExtMap.setDbRequest(request);
733 aaiExtMap.setTransId(request.getTransactionId());
734 aaiExtMap.setFromAppId(fromAppId);
735 aaiExtMap.setGraph(g);
736 aaiExtMap.setApiVersion(apiVersion.toString());
737 aaiExtMap.setObjectFromRequest(obj);
738 aaiExtMap.setObjectFromRequestType(obj.getJavaClassName());
739 aaiExtMap.setObjectFromResponse(obj);
740 aaiExtMap.setObjectFromResponseType(obj.getJavaClassName());
741 aaiExtMap.setJaxbContext(nodeIngestor.getContextForVersion(apiVersion));
742 aaiExtMap.setUri(uri.getRawPath());
743 aaiExtMap.setTransactionalGraphEngine(dbEngine);
744 aaiExtMap.setLoader(loader);
745 aaiExtMap.setNamespace(extensionInformation.getNamespace());
747 ExtensionController ext = new ExtensionController();
748 ext.runExtension(aaiExtMap.getApiVersion(),
749 extensionInformation.getNamespace(),
750 extensionInformation.getTopObject(),
751 extensionInformation.getMethodName(httpMethod, isPreprocess),
755 if (aaiExtMap.getPrecheckAddedList().size() > 0) {
756 response = notifyOnSkeletonCreation(aaiExtMap, obj, request.getHeaders());
763 * Notify on skeleton creation.
765 * @param aaiExtMap the aai ext map
766 * @param input the input
767 * @param headers the headers
768 * @return the response
771 private Response notifyOnSkeletonCreation(AAIExtensionMap aaiExtMap, Introspector input, HttpHeaders headers) {
772 Response response = null;
773 HashMap<AAIException, ArrayList<String>> exceptionList = new HashMap<AAIException, ArrayList<String>>();
775 StringBuilder keyString = new StringBuilder();
777 Set<String> resourceKeys = input.getKeys();
778 for (String key : resourceKeys) {
779 keyString.append(key).append("=").append(input.getValue(key).toString()).append(" ");
782 for (AAIResponseMessage msg : aaiExtMap.getPrecheckResponseMessages().getAAIResponseMessage()) {
783 ArrayList<String> templateVars = new ArrayList<>();
785 templateVars.add("PUT " + input.getDbName());
786 templateVars.add(keyString.toString());
787 List<String> keys = new ArrayList<>();
788 templateVars.add(msg.getAaiResponseMessageResourceType());
789 for (AAIResponseMessageDatum dat : msg.getAaiResponseMessageData().getAAIResponseMessageDatum()) {
790 keys.add(dat.getAaiResponseMessageDatumKey() + "=" + dat.getAaiResponseMessageDatumValue());
792 templateVars.add(StringUtils.join(keys, ", "));
793 exceptionList.put(new AAIException("AAI_0004", msg.getAaiResponseMessageResourceType()),
797 .status(Status.ACCEPTED).entity(ErrorLogHelper
798 .getRESTAPIInfoResponse(headers.getAcceptableMediaTypes(), exceptionList))
805 * Creates the not found message.
807 * @param resultType the result type
811 private String createNotFoundMessage(String resultType, URI uri) {
813 String msg = "No Node of type " + resultType + " found at: " + uri.getPath();
821 * @param depthParam the depth param
823 * @throws AAIException the AAI exception
825 protected int setDepth(Introspector obj, String depthParam) throws AAIException {
826 int depth = AAIProperties.MAXIMUM_DEPTH;
828 String getAllRandomStr = AAIConfig.get("aai.rest.getall.depthparam", "");
829 if (depthParam != null && getAllRandomStr != null && !getAllRandomStr.isEmpty()
830 && getAllRandomStr.equals(depthParam)) {
834 if(depthParam == null){
835 if(this.version.compareTo(schemaVersions.getDepthVersion()) >= 0){
838 depth = AAIProperties.MAXIMUM_DEPTH;
841 if (!depthParam.isEmpty() && !"all".equals(depthParam)){
843 depth = Integer.parseInt(depthParam);
844 } catch (Exception e) {
845 throw new AAIException("AAI_4016");
850 String maxDepth = obj.getMetadata(ObjectMetadata.MAXIMUM_DEPTH);
852 int maximumDepth = AAIProperties.MAXIMUM_DEPTH;
854 if(maxDepth != null){
856 maximumDepth = Integer.parseInt(maxDepth);
857 } catch(Exception ex){
858 throw new AAIException("AAI_4018");
862 if(depth > maximumDepth){
863 throw new AAIException("AAI_3303");
870 * Checks if is modification method.
872 * @param method the method
873 * @return true, if is modification method
875 private boolean isModificationMethod(HttpMethod method) {
876 boolean result = false;
878 if (method.equals(HttpMethod.PUT) || method.equals(HttpMethod.PUT_EDGE) || method.equals(HttpMethod.DELETE_EDGE) || method.equals(HttpMethod.MERGE_PATCH)) {
886 private HashMap<String, Introspector> getRelatedObjects(DBSerializer serializer, QueryEngine queryEngine, Vertex v) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException, InstantiationException, NoSuchMethodException, UnsupportedEncodingException, AAIException, URISyntaxException {
887 HashMap<String, Introspector> relatedVertices = new HashMap<>();
888 List<Vertex> vertexChain = queryEngine.findParents(v);
889 for (Vertex vertex : vertexChain) {
891 final Introspector vertexObj = serializer.getVertexProperties(vertex);
892 relatedVertices.put(vertexObj.getObjectId(), vertexObj);
893 } catch (AAIUnknownObjectException e) {
894 LOGGER.warn("Unable to get vertex properties, partial list of related vertices returned");
899 return relatedVertices;
902 private Map<Vertex, Introspector> buildIntrospectorObjects(DBSerializer serializer, Iterable<Vertex> vertices) {
903 Map<Vertex, Introspector> deleteObjectMap = new HashMap<>();
904 for (Vertex vertex : vertices) {
906 // deleteObjectMap.computeIfAbsent(vertex, s ->
907 // serializer.getLatestVersionView(vertex));
908 Introspector deleteObj = serializer.getLatestVersionView(vertex);
909 deleteObjectMap.put(vertex, deleteObj);
910 } catch (UnsupportedEncodingException | AAIException e) {
911 LOGGER.warn("Unable to get Introspctor Objects, Just continue");
917 return deleteObjectMap;
921 private Map<String, URI> buildURIMap(DBSerializer serializer, Map<Vertex, Introspector> introSpector) {
922 Map<String, URI> uriMap = new HashMap<>();
923 for (Map.Entry<Vertex, Introspector> entry : introSpector.entrySet()) {
926 uri = serializer.getURIForVertex(entry.getKey());
927 if (null != entry.getValue())
928 uriMap.put(entry.getValue().getObjectId(), uri);
929 } catch (UnsupportedEncodingException e) {
930 LOGGER.warn("Unable to get URIs, Just continue");
940 private Map<String, HashMap<String, Introspector>> buildRelatedObjects(DBSerializer serializer,
941 QueryEngine queryEngine, Map<Vertex, Introspector> introSpector) {
943 Map<String, HashMap<String, Introspector>> relatedObjectsMap = new HashMap<>();
944 for (Map.Entry<Vertex, Introspector> entry : introSpector.entrySet()) {
946 HashMap<String, Introspector> relatedObjects = this.getRelatedObjects(serializer, queryEngine,
948 if (null != entry.getValue())
949 relatedObjectsMap.put(entry.getValue().getObjectId(), relatedObjects);
950 } catch (IllegalAccessException | IllegalArgumentException
951 | InvocationTargetException | SecurityException | InstantiationException | NoSuchMethodException
952 | UnsupportedEncodingException | AAIException | URISyntaxException e) {
953 LOGGER.warn("Unable to get realted Objects, Just continue");
959 return relatedObjectsMap;
963 private void buildNotificationEvent(String sourceOfTruth, Status status, String transactionId,
964 UEBNotification notification, Map<Vertex, Introspector> deleteObjects, Map<String, URI> uriMap,
965 Map<String, HashMap<String, Introspector>> deleteRelatedObjects, String basePath) {
966 for (Map.Entry<Vertex, Introspector> entry : deleteObjects.entrySet()) {
968 String vertexObjectId = "";
970 if (null != entry.getValue()) {
971 vertexObjectId = entry.getValue().getObjectId();
973 if (uriMap.containsKey(vertexObjectId) && deleteRelatedObjects.containsKey(vertexObjectId))
974 notification.createNotificationEvent(transactionId, sourceOfTruth, status,
975 uriMap.get(vertexObjectId), entry.getValue(), deleteRelatedObjects.get(vertexObjectId), basePath);
977 } catch (UnsupportedEncodingException | AAIException e) {
979 LOGGER.warn("Error in sending notification");