Add gremlin-based pagination to aai-common 94/138294/7
authorFiete Ostkamp <Fiete.Ostkamp@telekom.de>
Thu, 20 Jun 2024 13:24:32 +0000 (15:24 +0200)
committerFiete Ostkamp <Fiete.Ostkamp@telekom.de>
Wed, 26 Jun 2024 08:36:08 +0000 (10:36 +0200)
- enhance query building to support gremlin-based pagination
- pagination is supported in two variants: with and without the total count of elements [1]
- enhance query building to support gremlin-based sorting
- add query logging that is currently disabled

[1] due to the design of gremlin, including the total count results in a full graph scan.
As such there is the option to not include it, which should make it (much) faster for the first pages that are returned.
Issue-ID: AAI-3893
Change-Id: I6bc0c9b9f398556cc41a0a8f82e24e50c85e5690
Signed-off-by: Fiete Ostkamp <Fiete.Ostkamp@telekom.de>
28 files changed:
aai-aaf-auth/pom.xml
aai-annotations/pom.xml
aai-auth/pom.xml
aai-common-docker/aai-common-images/pom.xml
aai-common-docker/aai-haproxy-image/pom.xml
aai-common-docker/pom.xml
aai-core/pom.xml
aai-core/src/main/java/org/onap/aai/query/builder/GraphTraversalBuilder.java
aai-core/src/main/java/org/onap/aai/query/builder/GremlinQueryBuilder.java
aai-core/src/main/java/org/onap/aai/query/builder/GremlinUnique.java
aai-core/src/main/java/org/onap/aai/query/builder/Pageable.java [new file with mode: 0644]
aai-core/src/main/java/org/onap/aai/query/builder/QueryBuilder.java
aai-core/src/main/java/org/onap/aai/query/builder/QueryOptions.java [new file with mode: 0644]
aai-core/src/main/java/org/onap/aai/query/builder/Sort.java [new file with mode: 0644]
aai-core/src/main/java/org/onap/aai/query/entities/PaginationResult.java [new file with mode: 0644]
aai-core/src/main/java/org/onap/aai/rest/db/HttpEntry.java
aai-core/src/test/java/org/onap/aai/parsers/query/GraphTraversalTest.java
aai-core/src/test/java/org/onap/aai/rest/db/HttpEntryTest.java
aai-els-onap-logging/pom.xml
aai-failover/pom.xml
aai-parent/pom.xml
aai-rest/pom.xml
aai-schema-abstraction/pom.xml
aai-schema-ingest/.classpath
aai-schema-ingest/pom.xml
aai-utils/pom.xml
pom.xml
version.properties

index cb58d44..87bb603 100644 (file)
@@ -6,7 +6,7 @@
     <parent>
         <groupId>org.onap.aai.aai-common</groupId>
         <artifactId>aai-parent</artifactId>
-        <version>1.14.2-SNAPSHOT</version>
+        <version>1.14.3-SNAPSHOT</version>
         <relativePath>../aai-parent/pom.xml</relativePath>
     </parent>
     <artifactId>aai-aaf-auth</artifactId>
index 0c4bfbb..6580416 100644 (file)
@@ -27,7 +27,7 @@
     <parent>
         <groupId>org.onap.aai.aai-common</groupId>
         <artifactId>aai-parent</artifactId>
-        <version>1.14.2-SNAPSHOT</version>
+        <version>1.14.3-SNAPSHOT</version>
         <relativePath>../aai-parent/pom.xml</relativePath>
     </parent>
     <artifactId>aai-annotations</artifactId>
index 958e7bc..19ac818 100644 (file)
@@ -27,7 +27,7 @@
     <parent>
         <groupId>org.onap.aai.aai-common</groupId>
         <artifactId>aai-parent</artifactId>
-        <version>1.14.2-SNAPSHOT</version>
+        <version>1.14.3-SNAPSHOT</version>
         <relativePath>../aai-parent/pom.xml</relativePath>
     </parent>
     <artifactId>aai-auth</artifactId>
index fcca55d..12d0077 100644 (file)
     <parent>
         <groupId>org.onap.aai.aai-common</groupId>
         <artifactId>aai-common-docker</artifactId>
-        <version>1.14.2-SNAPSHOT</version>
+        <version>1.14.3-SNAPSHOT</version>
     </parent>
 
     <artifactId>aai-common-images</artifactId>
-    <version>1.14.2-SNAPSHOT</version>
+    <version>1.14.3-SNAPSHOT</version>
     <packaging>pom</packaging>
     <name>aai-aai-common-images</name>
     <description>Contains dockerfiles for aai-common images (alpine and ubuntu based).</description>
index 583fa93..b001981 100644 (file)
     <parent>
         <groupId>org.onap.aai.aai-common</groupId>
         <artifactId>aai-common-docker</artifactId>
-        <version>1.14.2-SNAPSHOT</version>
+        <version>1.14.3-SNAPSHOT</version>
     </parent>
 
     <artifactId>aai-haproxy-image</artifactId>
-    <version>1.14.2-SNAPSHOT</version>
+    <version>1.14.3-SNAPSHOT</version>
     <packaging>pom</packaging>
     <name>aai-aai-haproxy-image</name>
     <description>Contains dockerfiles for aai-haproxy image.</description>
index 132e2e0..4a637bb 100644 (file)
@@ -26,7 +26,7 @@
     <parent>
         <groupId>org.onap.aai.aai-common</groupId>
         <artifactId>aai-parent</artifactId>
-        <version>1.14.2-SNAPSHOT</version>
+        <version>1.14.3-SNAPSHOT</version>
         <relativePath>../aai-parent/pom.xml</relativePath>
     </parent>
 
index 490d1a4..30820d8 100644 (file)
@@ -26,7 +26,7 @@ limitations under the License.
        <parent>
                <groupId>org.onap.aai.aai-common</groupId>
                <artifactId>aai-parent</artifactId>
-               <version>1.14.2-SNAPSHOT</version>
+               <version>1.14.3-SNAPSHOT</version>
                <relativePath>../aai-parent/pom.xml</relativePath>
        </parent>
        <artifactId>aai-core</artifactId>
@@ -416,6 +416,12 @@ limitations under the License.
                                <version>${log4j.version}</version>
                                <type>pom</type>
                </dependency>
+               <dependency>
+                       <groupId>org.projectlombok</groupId>
+                       <artifactId>lombok</artifactId>
+                       <version>1.18.30</version>
+                       <scope>provided</scope>
+               </dependency>
        </dependencies>
 
        <!-- Plugins and repositories -->
index 24e5ec8..8d7da68 100644 (file)
@@ -27,14 +27,18 @@ import com.google.common.collect.Multimap;
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 
+import org.apache.tinkerpop.gremlin.groovy.jsr223.GroovyTranslator;
+import org.apache.tinkerpop.gremlin.process.traversal.Order;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
 import org.apache.tinkerpop.gremlin.process.traversal.Path;
 import org.apache.tinkerpop.gremlin.process.traversal.Pop;
+import org.apache.tinkerpop.gremlin.process.traversal.Scope;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal.Admin;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
@@ -53,15 +57,22 @@ import org.onap.aai.edges.exceptions.EdgeRuleNotFoundException;
 import org.onap.aai.exceptions.AAIException;
 import org.onap.aai.introspection.Introspector;
 import org.onap.aai.introspection.Loader;
+import org.onap.aai.query.entities.PaginationResult;
 import org.onap.aai.schema.enums.ObjectMetadata;
 import org.onap.aai.schema.enums.PropertyMetadata;
 import org.onap.aai.serialization.db.exceptions.NoEdgeRuleFoundException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * The Class GraphTraversalBuilder.
  */
 public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> {
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(GraphTraversalBuilder.class);
+
+    private final GroovyTranslator groovyTranslator = GroovyTranslator.of("source");
+
     protected GraphTraversal<Vertex, E> traversal = null;
     protected Admin<Vertex, E> completeTraversal = null;
 
@@ -875,7 +886,7 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> {
 
     @Override
     public QueryBuilder<E> getContainerQuery() {
-        
+
         if (this.parentStepIndex == 0) {
             return removeQueryStepsBetween(0, containerStepIndex);
         } else {
@@ -933,6 +944,12 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> {
         if (start != null) {
             this.completeTraversal = traversal.asAdmin();
         } else {
+            boolean queryLoggingEnabled = false;
+            if(queryLoggingEnabled) {
+                String query = groovyTranslator.translate(traversal.asAdmin().getBytecode());
+                LOGGER.info("Query: {}", query);
+            }
+
             admin = source.V().asAdmin();
             TraversalHelper.insertTraversal(admin.getEndStep(), traversal.asAdmin(), admin);
 
@@ -968,6 +985,79 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> {
         return this.completeTraversal.toList();
     }
 
+    @Override
+    public QueryBuilder<E> sort(Sort sort) {
+        Order order = sort.getDirection() == Sort.Direction.ASC ? Order.asc : Order.desc;
+        traversal.order().by(sort.getProperty(), order);
+        stepIndex++;
+        return this;
+    }
+
+    public PaginationResult<E> toPaginationResult(Pageable pageable) {
+        int page = pageable.getPage();
+        int pageSize = pageable.getPageSize();
+        if(pageable.isIncludeTotalCount()) {
+            return paginateWithTotalCount(page, pageSize);
+        } else {
+            return paginateWithoutTotalCount(page, pageSize);
+        }
+    }
+
+    private PaginationResult<E> paginateWithoutTotalCount(int page, int pageSize) {
+        int startIndex = page * pageSize;
+        traversal.range(startIndex, startIndex + pageSize);
+
+        if (this.completeTraversal == null) {
+            executeQuery();
+        }
+        return new PaginationResult<E>(completeTraversal.toList());
+    }
+
+    private PaginationResult<E> paginateWithTotalCount(int page, int pageSize) {
+        int startIndex = page * pageSize;
+        traversal.fold().as("results","count")
+                .select("results","count").
+                    by(__.range(Scope.local, startIndex, startIndex + pageSize)).
+                    by(__.count(Scope.local));
+
+        if (this.completeTraversal == null) {
+            executeQuery();
+        }
+        return mapPaginationResult((Map<String,Object>) completeTraversal.next());
+    }
+
+    private PaginationResult<E> mapPaginationResult(Map<String,Object> result) {
+        Object objCount = result.get("count");
+        Object vertices = result.get("results");
+        if(vertices == null) {
+            return new PaginationResult<E>(Collections.emptyList() ,0L);
+        }
+        List<E> results = null;
+        if(vertices instanceof List) {
+            results = (List<E>) vertices;
+        } else if (vertices instanceof Vertex) {
+            results = Collections.singletonList((E) vertices);
+        } else {
+            String msg = String.format("Results must be a list or a vertex, but was %s", vertices.getClass().getName());
+            LOGGER.error(msg);
+            throw new IllegalArgumentException(msg);
+        }
+        long totalCount = parseCount(objCount);
+        return new PaginationResult<E>(results, totalCount);
+    }
+
+    private long parseCount(Object count) {
+        if(count instanceof String) {
+            return Long.parseLong((String) count);
+        } else if(count instanceof Integer) {
+            return Long.valueOf((int) count);
+        } else if (count instanceof Long) {
+            return (long) count;
+        } else {
+            throw new IllegalArgumentException("Count must be a string, integer, or long");
+        }
+    }
+
     protected QueryBuilder<Edge> has(String key, String value) {
         traversal.has(key, value);
 
index db1c78a..292d88f 100644 (file)
@@ -44,6 +44,7 @@ import org.onap.aai.edges.exceptions.EdgeRuleNotFoundException;
 import org.onap.aai.exceptions.AAIException;
 import org.onap.aai.introspection.Introspector;
 import org.onap.aai.introspection.Loader;
+import org.onap.aai.query.entities.PaginationResult;
 import org.onap.aai.restcore.search.GremlinGroovyShell;
 import org.onap.aai.schema.enums.ObjectMetadata;
 import org.onap.aai.serialization.db.exceptions.NoEdgeRuleFoundException;
@@ -956,8 +957,16 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
         return (QueryBuilder<Edge>) this;
     }
 
-    /*
-     * This is required for the subgraphstrategies to work
-     */
+    @Override
+    public PaginationResult<E> toPaginationResult(Pageable pageable) {
+        // TODO Auto-generated method stub
+        throw new UnsupportedOperationException("Unimplemented method 'toPaginationResult'");
+    }
+
+    @Override
+    public QueryBuilder<E> sort(Sort sort) {
+        // TODO Auto-generated method stub
+        throw new UnsupportedOperationException("Unimplemented method 'sort'");
+    }
 
 }
index 2b117c4..5849520 100644 (file)
@@ -35,6 +35,7 @@ import org.onap.aai.introspection.Loader;
 import org.onap.aai.parsers.query.QueryParser;
 import org.onap.aai.parsers.query.TraversalStrategy;
 import org.onap.aai.parsers.query.UniqueStrategy;
+import org.onap.aai.query.entities.PaginationResult;
 
 /**
  * The Class GremlinUnique.
diff --git a/aai-core/src/main/java/org/onap/aai/query/builder/Pageable.java b/aai-core/src/main/java/org/onap/aai/query/builder/Pageable.java
new file mode 100644 (file)
index 0000000..cb6cb62
--- /dev/null
@@ -0,0 +1,42 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright Â© 2024 Deutsche Telekom. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.aai.query.builder;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+/**
+ * Object that contains the page and pageSize for pagination.
+ * `includeTotalCount` can optionally be provided to include the total count of objects in the response.
+ * Note that including the total count in the response will trigger a full graph scan (@see <a href="https://jayanta-mondal.medium.com/the-curious-case-of-pagination-for-gremlin-queries-d6fd9518620">The Curious Case of Pagination for Gremlin Queries</a>).
+ */
+@Getter
+@RequiredArgsConstructor
+public class Pageable {
+  private final int page;
+  private final int pageSize;
+  private boolean includeTotalCount = false;
+
+  public Pageable includeTotalCount() {
+    this.includeTotalCount = true;
+    return this;
+  }
+}
index 309ffa1..a22fc38 100644 (file)
@@ -47,6 +47,7 @@ import org.onap.aai.introspection.Introspector;
 import org.onap.aai.introspection.Loader;
 import org.onap.aai.parsers.query.QueryParser;
 import org.onap.aai.parsers.query.QueryParserStrategy;
+import org.onap.aai.query.entities.PaginationResult;
 import org.springframework.context.ApplicationContext;
 
 /**
@@ -501,7 +502,7 @@ public abstract class QueryBuilder<E> implements Iterator<E> {
      * This is necessary in cases such as "if the Optional Property 1 is sent,
      * find all Nodes of type A with edges to Nodes of type B with property 1,
      * otherwise, simply find all nodes of type A".
-     * 
+     *
      * @param type
      * @param outNodeType
      * @param inNodeType
@@ -520,7 +521,7 @@ public abstract class QueryBuilder<E> implements Iterator<E> {
      * This is necessary in cases such as "if the Optional Property 1 is sent,
      * find all Nodes of type A with edges to Nodes of type B with property 1,
      * otherwise, simply find all nodes of type A".
-     * 
+     *
      * @param type
      * @param outNodeType
      * @param inNodeType
@@ -743,6 +744,22 @@ public abstract class QueryBuilder<E> implements Iterator<E> {
 
     public abstract List<E> toList();
 
+    /**
+     * Paginate the resulting list.
+     * This is a final step that returns a PaginationResult.
+     * @param pageable object that contains page and page size
+     * @return returns a page of the results and the total count.
+     */
+    public abstract PaginationResult<E> toPaginationResult(Pageable pageable);
+
+    /**
+     * Sort the resulting list.
+     * @param sort object that contains the property to sort by and the direction
+     * @return returns the QueryBuilder for further query building
+     */
+    public abstract QueryBuilder<E> sort(Sort sort);
+
+
     /**
      * Used to skip step if there is an optional property missing.
      *
diff --git a/aai-core/src/main/java/org/onap/aai/query/builder/QueryOptions.java b/aai-core/src/main/java/org/onap/aai/query/builder/QueryOptions.java
new file mode 100644 (file)
index 0000000..920bc28
--- /dev/null
@@ -0,0 +1,41 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright Â© 2024 Deutsche Telekom. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.aai.query.builder;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+
+@Getter
+@Builder
+@AllArgsConstructor
+public class QueryOptions {
+  @Builder.Default Pageable pageable = null;
+  @Builder.Default Sort sort = null;
+
+  public QueryOptions(Pageable pageable) {
+    this.pageable = pageable;
+  }
+
+  public QueryOptions(Sort sort) {
+    this.sort = sort;
+  }
+}
diff --git a/aai-core/src/main/java/org/onap/aai/query/builder/Sort.java b/aai-core/src/main/java/org/onap/aai/query/builder/Sort.java
new file mode 100644 (file)
index 0000000..6009d61
--- /dev/null
@@ -0,0 +1,37 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright Â© 2024 Deutsche Telekom. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.aai.query.builder;
+
+import lombok.Builder;
+import lombok.Data;
+
+@Data
+@Builder
+public class Sort {
+  private final String property;
+
+  @Builder.Default
+  Direction direction = Direction.ASC;
+
+  public enum Direction {
+    ASC, DESC
+  }
+}
diff --git a/aai-core/src/main/java/org/onap/aai/query/entities/PaginationResult.java b/aai-core/src/main/java/org/onap/aai/query/entities/PaginationResult.java
new file mode 100644 (file)
index 0000000..23e68ad
--- /dev/null
@@ -0,0 +1,36 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright Â© 2024 Deutsche Telekom. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.query.entities;
+
+import java.util.List;
+
+import org.springframework.lang.Nullable;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+@Getter
+@AllArgsConstructor
+@RequiredArgsConstructor
+public class PaginationResult <E> {
+  private final List<E> results;
+  @Nullable private Long totalCount = null;
+}
index 7ecdd6d..7c65207 100644 (file)
@@ -4,6 +4,8 @@
  * ================================================================================
  * Copyright Â© 2017-2018 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
+ * Modifications Copyright Â© 2024 Deutsche Telekom.
+ * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
@@ -50,6 +52,8 @@ import org.onap.aai.logging.ErrorLogHelper;
 import org.onap.aai.nodes.NodeIngestor;
 import org.onap.aai.parsers.query.QueryParser;
 import org.onap.aai.prevalidation.ValidationService;
+import org.onap.aai.query.builder.QueryOptions;
+import org.onap.aai.query.entities.PaginationResult;
 import org.onap.aai.rest.ueb.UEBNotification;
 import org.onap.aai.restcore.HttpMethod;
 import org.onap.aai.schema.enums.ObjectMetadata;
@@ -219,16 +223,6 @@ public class HttpEntry {
         return dbEngine;
     }
 
-    public Pair<Boolean, List<Pair<URI, Response>>> process(List<DBRequest> requests, String sourceOfTruth,
-            Set<String> groups) throws AAIException {
-        return this.process(requests, sourceOfTruth, groups, true);
-    }
-
-    public Pair<Boolean, List<Pair<URI, Response>>> process(List<DBRequest> requests, String sourceOfTruth)
-            throws AAIException {
-        return this.process(requests, sourceOfTruth, true);
-    }
-
     /**
      * Checks the pagination bucket and pagination index variables to determine whether or not the user
      * requested paginated results
@@ -310,22 +304,21 @@ public class HttpEntry {
         return this.totalVertices;
     }
 
-    /**
-     * Process.
-     *
-     * @param requests the requests
-     * @param sourceOfTruth the source of truth
-     *
-     * @return the pair
-     * @throws AAIException the AAI exception
-     */
-    public Pair<Boolean, List<Pair<URI, Response>>> process(List<DBRequest> requests, String sourceOfTruth,
-            boolean enableResourceVersion) throws AAIException {
-        return this.process(requests, sourceOfTruth, Collections.EMPTY_SET, enableResourceVersion);
+    public Pair<Boolean, List<Pair<URI, Response>>> process(List<DBRequest> requests, String sourceOfTruth) throws AAIException {
+        return this.process(requests, sourceOfTruth, true);
     }
 
-    private Pair<Boolean, List<Pair<URI, Response>>> process(List<DBRequest> requests, String sourceOfTruth,
-            Set<String> groups, boolean enableResourceVersion) throws AAIException {
+    public Pair<Boolean, List<Pair<URI, Response>>> process(List<DBRequest> requests, String sourceOfTruth,boolean enableResourceVersion) throws AAIException {
+        return this.process(requests, sourceOfTruth, Collections.emptySet(), enableResourceVersion, null);
+    }
+
+    public Pair<Boolean, List<Pair<URI, Response>>> process(List<DBRequest> requests, String sourceOfTruth, Set<String> groups) throws AAIException {
+        return this.process(requests, sourceOfTruth, groups, true, null);
+    }
+
+
+    public Pair<Boolean, List<Pair<URI, Response>>> process(List<DBRequest> requests, String sourceOfTruth,
+            Set<String> groups, boolean enableResourceVersion, QueryOptions queryOptions) throws AAIException {
 
         DBSerializer serializer = null;
 
@@ -376,22 +369,21 @@ public class HttpEntry {
                     uri = UriBuilder.fromPath(uriTemp).build();
 
                     boolean groupsAvailable = serializer.getGroups() != null && !serializer.getGroups().isEmpty();
-                    List<Vertex> queryResult = query.getQueryBuilder().toList();
-                    List<Vertex> vertices;
-                    if (this.isPaginated()) {
-                        List<Vertex> vertTemp = groupsAvailable ? queryResult.stream().filter((vx) -> {
-                            return OwnerCheck.isAuthorized(groups, vx);
-                        }).collect(Collectors.toList()) : queryResult;
-                        this.setTotalsForPaging(vertTemp.size(), this.paginationBucket);
-                        vertices = vertTemp.subList(((this.paginationIndex - 1) * this.paginationBucket),
-                                Math.min((this.paginationBucket * this.paginationIndex), vertTemp.size()));
+                    List<Vertex> queryResult;
+                    PaginationResult<Vertex> paginationResult = null;
+                    if(queryOptions != null && queryOptions.getPageable() != null) {
+                        paginationResult = executePaginatedQuery(query, queryOptions);
+                        queryResult = paginationResult.getResults();
                     } else {
-                        vertices = groupsAvailable && queryResult.size() > 1 ? queryResult.stream().filter((vx) -> {
-                            return OwnerCheck.isAuthorized(groups, vx);
-                        }).collect(Collectors.toList()) : queryResult;
-
+                        queryResult = executeQuery(query, queryOptions);
                     }
 
+                    List<Vertex> vertices = groupsAvailable
+                        ? queryResult.stream()
+                            .filter(vertex -> OwnerCheck.isAuthorized(groups, vertex))
+                            .collect(Collectors.toList())
+                        : queryResult;
+
                     boolean isNewVertex;
                     HttpHeaders headers = request.getHeaders();
                     outputMediaType = getMediaType(headers.getAcceptableMediaTypes());
@@ -686,10 +678,10 @@ public class HttpEntry {
 
                     ) {
                         String myvertid = v.id().toString();
-                        if (this.isPaginated()) {
+                        if (paginationResult != null && paginationResult.getTotalCount() != null) {
                             response = Response.status(status).header("vertex-id", myvertid)
-                                    .header("total-results", this.getTotalVertices())
-                                    .header("total-pages", this.getTotalPaginationBuckets()).entity(result)
+                                    .header("total-results", paginationResult.getTotalCount())
+                                    .entity(result)
                                     .type(outputMediaType).build();
                         } else {
                             response = Response.status(status).header("vertex-id", myvertid).entity(result)
@@ -749,6 +741,18 @@ public class HttpEntry {
         return Pair.with(success, responses);
     }
 
+    private List<Vertex> executeQuery(QueryParser query, QueryOptions queryOptions) {
+        return (queryOptions != null && queryOptions.getSort() != null)
+            ? query.getQueryBuilder().sort(queryOptions.getSort()).toList()
+            : query.getQueryBuilder().toList();
+    }
+
+    private PaginationResult<Vertex> executePaginatedQuery(QueryParser query, QueryOptions queryOptions) {
+        return queryOptions.getSort() != null
+            ? query.getQueryBuilder().sort(queryOptions.getSort()).toPaginationResult(queryOptions.getPageable())
+            : query.getQueryBuilder().toPaginationResult(queryOptions.getPageable());
+    }
+
     /**
      * Generate notification events for the resulting db requests.
      */
@@ -815,7 +819,7 @@ public class HttpEntry {
 
     /**
      * Verifies that vertex has needed properties to generate on
-     * 
+     *
      * @param vertex Vertex to be verified
      * @return <code>true</code> if vertex has necessary properties and exists
      */
@@ -1126,6 +1130,7 @@ public class HttpEntry {
         }
     }
 
+    @Deprecated
     public List<Object> getPaginatedVertexListForAggregateFormat(List<Object> aggregateVertexList) throws AAIException {
         List<Object> finalList = new Vector<>();
         if (this.isPaginated()) {
@@ -1154,6 +1159,16 @@ public class HttpEntry {
         return aggregateVertexList;
     }
 
+    /**
+     * This method is used to paginate the vertex list based on the pagination index and bucket size
+     *
+     * @deprecated
+     * This method is no longer supported. Use {@link #process(List, String, Set, boolean, QueryOptions)} instead.
+     * @param vertexList
+     * @return
+     * @throws AAIException
+     */
+    @Deprecated
     public List<Object> getPaginatedVertexList(List<Object> vertexList) throws AAIException {
         List<Object> vertices;
         if (this.isPaginated()) {
index 34b29ce..04a2991 100644 (file)
@@ -52,6 +52,8 @@ import org.onap.aai.TinkerpopUpgrade;
 import org.onap.aai.db.props.AAIProperties;
 import org.onap.aai.exceptions.AAIException;
 import org.onap.aai.introspection.ModelType;
+import org.onap.aai.query.builder.Pageable;
+import org.onap.aai.query.builder.QueryBuilder;
 import org.onap.aai.rest.RestTokens;
 import org.onap.aai.serialization.engines.JanusGraphDBEngine;
 import org.onap.aai.serialization.engines.QueryStyle;
@@ -79,7 +81,7 @@ public class GraphTraversalTest extends DataLinkSetup {
 
     /**
      * Configure.
-     * 
+     *
      * @throws Exception
      * @throws SecurityException
      * @throws NoSuchFieldException
@@ -579,8 +581,7 @@ public class GraphTraversalTest extends DataLinkSetup {
 
         thrown.expect(AAIException.class);
         thrown.expectMessage(containsString(RestTokens.COUSIN.toString()));
-        QueryParser query = dbEngineDepthVersion.getQueryBuilder().createQueryFromURI(uri);
-
+        dbEngineDepthVersion.getQueryBuilder().createQueryFromURI(uri);
     }
 
     @Test
@@ -589,7 +590,6 @@ public class GraphTraversalTest extends DataLinkSetup {
 
         thrown.expect(AAIException.class);
         thrown.expectMessage(containsString("chain plurals"));
-        QueryParser query = dbEngineDepthVersion.getQueryBuilder().createQueryFromURI(uri);
-
+        dbEngineDepthVersion.getQueryBuilder().createQueryFromURI(uri);
     }
 }
index bdb02b9..0dcec24 100644 (file)
@@ -27,6 +27,7 @@ import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.not;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
@@ -35,6 +36,7 @@ import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import java.util.Collections;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.JsonMappingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -85,6 +87,10 @@ import org.onap.aai.introspection.Loader;
 import org.onap.aai.introspection.ModelType;
 import org.onap.aai.parsers.query.QueryParser;
 import org.onap.aai.prevalidation.ValidationService;
+import org.onap.aai.query.builder.Pageable;
+import org.onap.aai.query.builder.QueryOptions;
+import org.onap.aai.query.builder.Sort;
+import org.onap.aai.query.builder.Sort.Direction;
 import org.onap.aai.rest.db.responses.ErrorResponse;
 import org.onap.aai.rest.db.responses.Relationship;
 import org.onap.aai.rest.db.responses.RelationshipWrapper;
@@ -96,6 +102,7 @@ import org.onap.aai.serialization.engines.TransactionalGraphEngine;
 import org.onap.aai.util.AAIConfig;
 import org.skyscreamer.jsonassert.JSONAssert;
 import org.skyscreamer.jsonassert.JSONCompareMode;
+import org.skyscreamer.jsonassert.comparator.JSONComparator;
 import org.springframework.boot.test.mock.mockito.MockBean;
 
 @RunWith(value = Parameterized.class)
@@ -189,7 +196,7 @@ public class HttpEntryTest extends AAISetup {
     }
 
     @Test
-    public void thatObjectsCanBeRetrieved() throws UnsupportedEncodingException, AAIException {
+    public void thatObjectCanBeRetrieved() throws UnsupportedEncodingException, AAIException {
         String uri = "/cloud-infrastructure/pservers/pserver/theHostname";
         traversal.addV()
                 .property("aai-node-type", "pserver")
@@ -197,15 +204,11 @@ public class HttpEntryTest extends AAISetup {
                 .property("equip-type", "theEquipType")
                 .property(AAIProperties.AAI_URI, uri)
                 .next();
-        String requestBody = new JSONObject()
-                .put("hostname", "theHostname")
-                .put("equip-type", "theEquipType")
-                .toString();
 
         JSONObject expectedResponseBody = new JSONObject()
                 .put("hostname", "theHostname")
                 .put("equip-type", "theEquipType");
-        Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET, uri, requestBody);
+        Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET, uri);
         JSONObject actualResponseBody = new JSONObject(response.getEntity().toString());
 
         JSONAssert.assertEquals(expectedResponseBody, actualResponseBody, JSONCompareMode.NON_EXTENSIBLE);
@@ -213,12 +216,169 @@ public class HttpEntryTest extends AAISetup {
         verify(validationService, times(1)).validate(any());
     }
 
+    @Test
+    public void thatObjectsCanBeRetrieved() throws UnsupportedEncodingException, AAIException {
+        String uri = "/cloud-infrastructure/pservers/pserver/theHostname";
+        traversal.addV()
+                .property("aai-node-type", "pserver")
+                .property("hostname", "theHostname")
+                .property("equip-type", "theEquipType")
+                .property(AAIProperties.AAI_URI, uri)
+                .next();
+        traversal.addV()
+                .property("aai-node-type", "pserver")
+                .property("hostname", "theHostname2")
+                .property("equip-type", "theEquipType2")
+                .property(AAIProperties.AAI_URI, uri + "2")
+                .next();
+
+        JSONObject expectedResponseBody = new JSONObject();
+        JSONObject pserver1 = new JSONObject()
+                .put("hostname", "theHostname")
+                .put("equip-type", "theEquipType");
+        JSONObject pserver2 = new JSONObject()
+                .put("hostname", "theHostname2")
+                .put("equip-type", "theEquipType2");
+        expectedResponseBody.put("pserver", new JSONArray()
+                .put(pserver1)
+                .put(pserver2));
+
+        uri = "/cloud-infrastructure/pservers";
+        Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET, uri);
+        JSONObject actualResponseBody = new JSONObject(response.getEntity().toString());
+
+        JSONAssert.assertEquals(expectedResponseBody, actualResponseBody, JSONCompareMode.NON_EXTENSIBLE);
+        assertEquals("Expected the pservers to be returned", 200, response.getStatus());
+        verify(validationService, times(1)).validate(any());
+    }
+
+    @Test
+    public void thatPaginatedObjectsCanBeRetrieved() throws UnsupportedEncodingException, AAIException {
+        String uri = "/cloud-infrastructure/pservers/pserver/theHostname";
+        traversal.addV()
+                .property("aai-node-type", "pserver")
+                .property("hostname", "theHostname")
+                .property("equip-type", "theEquipType")
+                .property(AAIProperties.AAI_URI, uri)
+                .next();
+        traversal.addV()
+                .property("aai-node-type", "pserver")
+                .property("hostname", "theHostname2")
+                .property("equip-type", "theEquipType2")
+                .property(AAIProperties.AAI_URI, uri + "2")
+                .next();
+
+        JSONObject expectedResponseBody = new JSONObject();
+        JSONObject pserver1 = new JSONObject()
+                .put("hostname", "theHostname")
+                .put("equip-type", "theEquipType");
+        expectedResponseBody.put("pserver", new JSONArray()
+                .put(pserver1));
+
+        uri = "/cloud-infrastructure/pservers";
+        QueryOptions queryOptions = QueryOptions.builder().pageable(new Pageable(1, 1)).build();
+        Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET, uri, queryOptions);
+        JSONObject actualResponseBody = new JSONObject(response.getEntity().toString());
+
+        assertNull(response.getHeaderString("total-results"));
+        assertEquals(1, actualResponseBody.getJSONArray("pserver").length());
+        assertEquals("Expected the pservers to be returned", 200, response.getStatus());
+        verify(validationService, times(1)).validate(any());
+
+        queryOptions = QueryOptions.builder().pageable(new Pageable(0,5).includeTotalCount()).build();
+        response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET, uri, queryOptions);
+        actualResponseBody = new JSONObject(response.getEntity().toString());
+        assertEquals(2, actualResponseBody.getJSONArray("pserver").length());
+    }
+
+    @Test
+    public void thatPagationResultWithTotalCountCanBeRetrieved() throws UnsupportedEncodingException, AAIException {
+        String uri = "/cloud-infrastructure/pservers/pserver/theHostname";
+        traversal.addV()
+                .property("aai-node-type", "pserver")
+                .property("hostname", "theHostname")
+                .property("equip-type", "theEquipType")
+                .property(AAIProperties.AAI_URI, uri)
+                .next();
+        traversal.addV()
+                .property("aai-node-type", "pserver")
+                .property("hostname", "theHostname2")
+                .property("equip-type", "theEquipType2")
+                .property(AAIProperties.AAI_URI, uri + "2")
+                .next();
+
+        JSONObject expectedResponseBody = new JSONObject();
+        JSONObject pserver1 = new JSONObject()
+                .put("hostname", "theHostname")
+                .put("equip-type", "theEquipType");
+        expectedResponseBody.put("pserver", new JSONArray()
+                .put(pserver1));
+
+        uri = "/cloud-infrastructure/pservers";
+        QueryOptions queryOptions = QueryOptions.builder().pageable(new Pageable(1, 1).includeTotalCount()).build();
+        Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET, uri, queryOptions);
+        JSONObject actualResponseBody = new JSONObject(response.getEntity().toString());
+        String totalCount = response.getHeaderString("total-results");
+
+        assertEquals(2, Integer.parseInt(totalCount));
+        assertEquals(1, actualResponseBody.getJSONArray("pserver").length());
+        assertEquals("Expected the pservers to be returned", 200, response.getStatus());
+        verify(validationService, times(1)).validate(any());
+
+        queryOptions = QueryOptions.builder().pageable(new Pageable(0, 2)).build();
+        response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET, uri, queryOptions);
+        actualResponseBody = new JSONObject(response.getEntity().toString());
+        assertEquals(2, actualResponseBody.getJSONArray("pserver").length());
+    }
+
+    @Test
+    public void thatSortedObjectsCanBeRetrieved() throws UnsupportedEncodingException, AAIException {
+        String uri = "/cloud-infrastructure/pservers/pserver/theHostname";
+        traversal.addV()
+                .property("aai-node-type", "pserver")
+                .property("hostname", "theHostname")
+                .property("equip-type", "theEquipType")
+                .property(AAIProperties.AAI_URI, uri)
+                .next();
+        traversal.addV()
+                .property("aai-node-type", "pserver")
+                .property("hostname", "theHostname2")
+                .property("equip-type", "theEquipType2")
+                .property(AAIProperties.AAI_URI, uri + "2")
+                .next();
+
+        JSONObject expectedResponseBody = new JSONObject();
+        JSONObject pserver1 = new JSONObject()
+                .put("hostname", "theHostname")
+                .put("equip-type", "theEquipType");
+        JSONObject pserver2 = new JSONObject()
+                .put("hostname", "theHostname2")
+                .put("equip-type", "theEquipType2");
+        expectedResponseBody.put("pserver", new JSONArray()
+                .put(pserver1).put(pserver2));
+
+        // ascending
+        uri = "/cloud-infrastructure/pservers";
+        QueryOptions queryOptions = QueryOptions.builder().sort(Sort.builder().property("equip-type").direction(Direction.ASC).build()).build();
+        Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET, uri, queryOptions);
+        JSONObject actualResponseBody = new JSONObject(response.getEntity().toString());
+        assertEquals("theEquipType", actualResponseBody.getJSONArray("pserver").getJSONObject(0).getString("equip-type"));
+        assertEquals("theEquipType2", actualResponseBody.getJSONArray("pserver").getJSONObject(1).getString("equip-type"));
+
+        // descending
+        queryOptions = QueryOptions.builder().sort(Sort.builder().property("equip-type").direction(Direction.DESC).build()).build();
+        response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET, uri, queryOptions);
+        actualResponseBody = new JSONObject(response.getEntity().toString());
+        assertEquals("theEquipType2", actualResponseBody.getJSONArray("pserver").getJSONObject(0).getString("equip-type"));
+        assertEquals("theEquipType", actualResponseBody.getJSONArray("pserver").getJSONObject(1).getString("equip-type"));
+
+    }
+
     @Test
     public void thatObjectsCanNotBeFound() throws UnsupportedEncodingException, AAIException {
         String uri = "/cloud-infrastructure/pservers/pserver/junit-test2";
-        String requestBody = "";
 
-        Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET, uri, requestBody);
+        Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET, uri);
         assertEquals("The pserver is not found", 404, response.getStatus());
     }
 
@@ -536,7 +696,7 @@ public class HttpEntryTest extends AAISetup {
         queryParameters.add("format", "pathed");
         String requestBody = "";
         Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET,
-                "/cloud-infrastructure/pservers", requestBody);
+                "/cloud-infrastructure/pservers");
         queryParameters.remove("format");
 
         String responseEntity = response.getEntity().toString();
@@ -573,8 +733,7 @@ public class HttpEntryTest extends AAISetup {
                 .next();
 
         uri = "/cloud-infrastructure/complexes/complex/related-to-complex/related-to/pservers";
-        String responseBody = "";
-        Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET, uri, responseBody);
+        Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET, uri);
 
         assertEquals("Expected the response to be successful", 200, response.getStatus());
         assertThat("Related pserver is returned", response.getEntity().toString(),
@@ -604,9 +763,8 @@ public class HttpEntryTest extends AAISetup {
                 .addE("tosca.relationships.HostedOn").from("v2").to("v1")
                 .next();
 
-        String requestBody = "";
         uri = "/network/generic-vnfs/generic-vnf/abstract-generic-vnf/related-to/pservers";
-        Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET, uri, requestBody);
+        Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET, uri);
         assertThat("Related to pserver is returned.", response.getEntity().toString(),
                 containsString("\"hostname\":\"abstract-pserver\""));
         verify(validationService, times(1)).validate(any());
@@ -644,9 +802,7 @@ public class HttpEntryTest extends AAISetup {
 
         // Get Relationship
         uri = "/cloud-infrastructure/pservers/pserver/related-to-pserver";
-        String requestBody = "";
-        Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET_RELATIONSHIP, uri,
-                requestBody);
+        Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET_RELATIONSHIP, uri);
         Relationship[] relationships = mapper.readValue(response.getEntity().toString(), RelationshipWrapper.class)
                 .getRelationships();
 
@@ -691,9 +847,7 @@ public class HttpEntryTest extends AAISetup {
         // Get Relationship
         uri = "/cloud-infrastructure/pservers/pserver/related-to-pserver";
         queryParameters.add("format", "resource");
-        String requestBody = "";
-        Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET_RELATIONSHIP, uri,
-                requestBody);
+        Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET_RELATIONSHIP, uri);
 
         JSONObject actualResponseBody = new JSONObject(response.getEntity().toString());
 
@@ -766,10 +920,29 @@ public class HttpEntryTest extends AAISetup {
     }
 
     private Response doRequest(HttpEntry httpEntry, Loader loader, TransactionalGraphEngine dbEngine, HttpMethod method,
-            String uri, String requestBody) throws UnsupportedEncodingException, AAIException {
+    String uri) throws UnsupportedEncodingException, AAIException {
+        return doRequest(httpEntry, loader, dbEngine, method, uri, null, null);
+    }
+
+    private Response doRequest(HttpEntry httpEntry, Loader loader, TransactionalGraphEngine dbEngine, HttpMethod method,
+    String uri, String requestBody) throws UnsupportedEncodingException, AAIException {
+        return doRequest(httpEntry, loader, dbEngine, method, uri, requestBody, null);
+    }
+    private Response doRequest(HttpEntry httpEntry, Loader loader, TransactionalGraphEngine dbEngine, HttpMethod method,
+    String uri, QueryOptions queryOptions) throws UnsupportedEncodingException, AAIException {
+        return doRequest(httpEntry, loader, dbEngine, method, uri, null, queryOptions);
+    }
+
+    private Response doRequest(HttpEntry httpEntry, Loader loader, TransactionalGraphEngine dbEngine, HttpMethod method,
+            String uri, String requestBody, QueryOptions queryOptions) throws UnsupportedEncodingException, AAIException {
         URI uriObject = UriBuilder.fromPath(uri).build();
         QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject);
-        String objType = uriQuery.getResultType();
+        String objType;
+        if (!uriQuery.getContainerType().equals("")) {
+                objType = uriQuery.getContainerType();
+        } else {
+                objType = uriQuery.getResultType();
+        }
         if (uri.endsWith("relationship")) {
             objType = "relationship";
         }
@@ -780,14 +953,15 @@ public class HttpEntryTest extends AAISetup {
             obj = loader.unmarshal(objType, requestBody, org.onap.aai.restcore.MediaType.getEnum("application/json"));
         }
 
-        DBRequest dbRequest = new DBRequest.Builder(method, uriObject, uriQuery, obj, httpHeaders, uriInfo,
-                "JUNIT-TRANSACTION")
-                .rawRequestContent(requestBody).build();
+        DBRequest.Builder builder = new DBRequest.Builder(method, uriObject, uriQuery, obj, httpHeaders, uriInfo,
+                "JUNIT-TRANSACTION");
+        DBRequest dbRequest = requestBody != null
+                ? builder.rawRequestContent(requestBody).build()
+                : builder.build();
 
-        List<DBRequest> dbRequestList = new ArrayList<>();
-        dbRequestList.add(dbRequest);
+        List<DBRequest> dbRequestList = Collections.singletonList(dbRequest);
 
-        Pair<Boolean, List<Pair<URI, Response>>> responsesTuple = httpEntry.process(dbRequestList, "JUNIT");
+        Pair<Boolean, List<Pair<URI, Response>>> responsesTuple = httpEntry.process(dbRequestList, "JUNIT", Collections.emptySet(), true, queryOptions);
         return responsesTuple.getValue1().get(0).getValue1();
     }
 
@@ -844,15 +1018,11 @@ public class HttpEntryTest extends AAISetup {
                 .property("equip-type", "theEquipType")
                 .property(AAIProperties.AAI_URI, uri)
                 .next();
-        String requestBody = new JSONObject()
-                .put("hostname", "theHostname")
-                .put("equip-type", "theEquipType")
-                .toString();
 
         JSONObject expectedResponseBody = new JSONObject()
                 .put("hostname", "theHostname")
                 .put("equip-type", "theEquipType");
-        Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET, uri, requestBody);
+        Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET, uri);
         JSONObject actualResponseBody = new JSONObject(response.getEntity().toString());
 
         JSONAssert.assertEquals(expectedResponseBody, actualResponseBody, JSONCompareMode.NON_EXTENSIBLE);
index 3f77bb5..e1b27a1 100644 (file)
@@ -4,7 +4,7 @@
     <parent>
         <groupId>org.onap.aai.aai-common</groupId>
         <artifactId>aai-parent</artifactId>
-        <version>1.14.2-SNAPSHOT</version>
+        <version>1.14.3-SNAPSHOT</version>
         <relativePath>../aai-parent/pom.xml</relativePath>
     </parent>
     <artifactId>aai-els-onap-logging</artifactId>
index dedeeec..2127e27 100644 (file)
@@ -5,7 +5,7 @@
     <parent>
         <groupId>org.onap.aai.aai-common</groupId>
         <artifactId>aai-parent</artifactId>
-        <version>1.14.2-SNAPSHOT</version>
+        <version>1.14.3-SNAPSHOT</version>
         <relativePath>../aai-parent/pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>
index de66d80..84b79a4 100644 (file)
@@ -27,7 +27,7 @@ limitations under the License.
   <parent>
     <groupId>org.onap.aai.aai-common</groupId>
     <artifactId>aai-common</artifactId>
-    <version>1.14.2-SNAPSHOT</version>
+    <version>1.14.3-SNAPSHOT</version>
   </parent>
   <artifactId>aai-parent</artifactId>
   <name>aai-parent</name>
@@ -319,6 +319,15 @@ limitations under the License.
         <version>${janusgraph.version}</version>
       </dependency>
 
+
+      <!-- https://docs.datastax.com/en/developer/java-driver/3.5/manual/metrics/index.html#metrics-4-compatibility -->
+      <!-- remove this for janusgraph >= 0.6.0 -->
+      <dependency>
+        <groupId>io.dropwizard.metrics</groupId>
+        <artifactId>metrics-core</artifactId>
+        <version>3.2.6</version>
+      </dependency>
+
       <dependency>
         <groupId>org.janusgraph</groupId>
         <artifactId>janusgraph-cql</artifactId>
index 396c8d4..a9dddc5 100644 (file)
@@ -29,7 +29,7 @@
     <parent>
         <groupId>org.onap.aai.aai-common</groupId>
         <artifactId>aai-parent</artifactId>
-        <version>1.14.2-SNAPSHOT</version>
+        <version>1.14.3-SNAPSHOT</version>
         <relativePath>../aai-parent/pom.xml</relativePath>
     </parent>
     <artifactId>aai-rest</artifactId>
index 7276d4a..0a46974 100644 (file)
@@ -28,7 +28,7 @@
   <parent>
     <groupId>org.onap.aai.aai-common</groupId>
     <artifactId>aai-parent</artifactId>
-    <version>1.14.2-SNAPSHOT</version>
+    <version>1.14.3-SNAPSHOT</version>
     <relativePath>../aai-parent/pom.xml</relativePath>
   </parent>
 
index 25ba983..5811926 100644 (file)
        <classpathentry kind="src" path="target/generated-sources/annotations">
                <attributes>
                        <attribute name="optional" value="true"/>
+                       <attribute name="maven.pomderived" value="true"/>
+                       <attribute name="ignore_optional_problems" value="true"/>
+                       <attribute name="m2e-apt" value="true"/>
                </attributes>
        </classpathentry>
        <classpathentry kind="src" output="target/test-classes" path="target/generated-test-sources/test-annotations">
                <attributes>
                        <attribute name="optional" value="true"/>
+                       <attribute name="maven.pomderived" value="true"/>
+                       <attribute name="ignore_optional_problems" value="true"/>
+                       <attribute name="m2e-apt" value="true"/>
                        <attribute name="test" value="true"/>
                </attributes>
        </classpathentry>
index 6f049dd..4ee8226 100644 (file)
@@ -26,7 +26,7 @@ limitations under the License.
        <parent>
                <groupId>org.onap.aai.aai-common</groupId>
                <artifactId>aai-parent</artifactId>
-               <version>1.14.2-SNAPSHOT</version>
+               <version>1.14.3-SNAPSHOT</version>
                <relativePath>../aai-parent/pom.xml</relativePath>
        </parent>
        <artifactId>aai-schema-ingest</artifactId>
index 1cd141b..40b0588 100644 (file)
@@ -27,7 +27,7 @@
     <parent>
         <groupId>org.onap.aai.aai-common</groupId>
         <artifactId>aai-parent</artifactId>
-        <version>1.14.2-SNAPSHOT</version>
+        <version>1.14.3-SNAPSHOT</version>
         <relativePath>../aai-parent/pom.xml</relativePath>
     </parent>
     <artifactId>aai-utils</artifactId>
diff --git a/pom.xml b/pom.xml
index 769beab..250ebac 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -30,7 +30,7 @@
 
     <groupId>org.onap.aai.aai-common</groupId>
     <artifactId>aai-common</artifactId>
-    <version>1.14.2-SNAPSHOT</version>
+    <version>1.14.3-SNAPSHOT</version>
     <packaging>pom</packaging>
     <name>aai-aai-common</name>
     <description>Contains all of the common code for resources and traversal repos</description>
index 466ec95..a9c3f22 100644 (file)
@@ -5,7 +5,7 @@
 
 major_version=1
 minor_version=14
-patch_version=2
+patch_version=3
 
 base_version=${major_version}.${minor_version}.${patch_version}