91d2d084fd94219e10e562c2d82cb7428058c2e4
[aai/aai-common.git] / aai-core / src / main / java / org / onap / aai / query / builder / TraversalURIOptimizedQuery.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
21 package org.onap.aai.query.builder;
22
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Optional;
27 import java.util.stream.Collectors;
28
29 import org.apache.tinkerpop.gremlin.process.traversal.Step;
30 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
31 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
32 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
33 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
34 import org.apache.tinkerpop.gremlin.structure.Vertex;
35 import org.onap.aai.db.props.AAIProperties;
36 import org.onap.aai.introspection.Introspector;
37 import org.onap.aai.introspection.Loader;
38 import org.onap.aai.schema.enums.ObjectMetadata;
39
40 public class TraversalURIOptimizedQuery<E> extends TraversalQuery {
41
42     protected Map<Integer, String> stepToAaiUri = new HashMap<>();
43
44     public TraversalURIOptimizedQuery(Loader loader, GraphTraversalSource source) {
45         super(loader, source);
46         optimize = true;
47     }
48
49     public TraversalURIOptimizedQuery(Loader loader, GraphTraversalSource source, Vertex start) {
50         super(loader, source, start);
51         optimize = true;
52     }
53
54     protected TraversalURIOptimizedQuery(GraphTraversal traversal, Loader loader, GraphTraversalSource source,
55             GraphTraversalBuilder gtb) {
56         super(traversal, loader, source, gtb);
57         optimize = true;
58     }
59
60     protected TraversalURIOptimizedQuery(GraphTraversal traversal, Loader loader, GraphTraversalSource source,
61             GraphTraversalBuilder gtb, Map<Integer, String> stepToAaiUri) {
62         super(traversal, loader, source, gtb);
63         optimize = gtb.optimize;
64         this.stepToAaiUri = stepToAaiUri;
65     }
66
67     @Override
68     protected void executeQuery() {
69
70         this.completeTraversal = this.traversal.asAdmin().clone();
71
72         if (this.optimize) {
73             this.completeTraversal = this.pivotTraversal(this.completeTraversal);
74         }
75
76         if (start == null) {
77             Traversal.Admin admin = source.V().asAdmin();
78             TraversalHelper.insertTraversal(admin.getEndStep(), completeTraversal, admin);
79
80             this.completeTraversal = (Traversal.Admin<Vertex, E>) admin;
81
82         }
83
84     }
85
86     private Traversal.Admin<Vertex, E> pivotTraversal(Traversal.Admin<Vertex, E> traversalAdmin) {
87
88         List<Step> steps = traversalAdmin.getSteps();
89
90         Traversal.Admin<Vertex, E> traversalAdminStart = traversalAdmin.clone();
91
92         // if we do not have an index or other conditions do no optimization
93         if (stepToAaiUri.isEmpty()) {
94             return traversalAdmin;
95         }
96
97         int lastURIStepKey = getLastURIStepKey();
98
99         // clean up traversal steps
100         for (int i = 0; i < steps.size(); i++) {
101             traversalAdminStart.removeStep(0);
102         }
103
104         ((GraphTraversal<Vertex, E>) traversalAdminStart).has(AAIProperties.AAI_URI, stepToAaiUri.get(lastURIStepKey));
105         for (int i = lastURIStepKey; i < steps.size(); i++) {
106             traversalAdminStart.addStep(steps.get(i));
107         }
108
109         return traversalAdminStart;
110     }
111
112     @Override
113     public QueryBuilder<Vertex> createKeyQuery(Introspector obj) {
114         super.createKeyQuery(obj);
115
116         if (shouldAddStepUri(obj)) {
117             Optional<String> uri = getStepUriFromIntrospector(obj);
118             if (uri.isPresent()) {
119                 if (stepToAaiUri.isEmpty()) {
120                     stepToAaiUri.put(stepIndex + 1, uri.get());
121                 } else {
122                     stepToAaiUri.put(stepIndex, uri.get());
123                 }
124             }
125         } else {
126             optimize = false;
127             stepToAaiUri = new HashMap<>();
128         }
129         return (QueryBuilder<Vertex>) this;
130     }
131
132     private boolean shouldAddStepUri(Introspector obj) {
133         boolean shouldOptimize = optimize;
134
135         if (shouldOptimize && start != null) {
136             shouldOptimize = false;
137         }
138
139         if (shouldOptimize && stepToAaiUri.isEmpty() && !obj.isTopLevel()) {
140             shouldOptimize = false;
141         }
142
143         if (shouldOptimize && obj.getMetadata(ObjectMetadata.ABSTRACT) != null) {
144             shouldOptimize = false;
145         }
146
147         return shouldOptimize;
148
149     }
150
151     private Optional<String> getStepUriFromIntrospector(Introspector obj) {
152         String uri = "";
153         try {
154             uri = obj.getURI();
155         } catch (Exception e) {
156         }
157
158         if ("".equals(uri)) {
159             return Optional.empty();
160         }
161
162         if (!stepToAaiUri.isEmpty()) {
163             uri = stepToAaiUri.get(getLastURIStepKey()) + uri;
164         }
165
166         return Optional.of(uri);
167     }
168
169     private int getLastURIStepKey() {
170         return stepToAaiUri.keySet().stream().mapToInt(Integer::intValue).max().getAsInt();
171     }
172
173     private Map<Integer, String> getStepToAaiUriWithoutStepGreaterThan(final int index) {
174         return stepToAaiUri.entrySet().stream().filter(kv -> kv.getKey() <= index)
175                 .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
176     }
177
178     @Override
179     protected QueryBuilder<E> cloneQueryAtStep(int index) {
180         GraphTraversal.Admin<Vertex, E> cloneAdmin = getCloneAdmin(index);
181         return new TraversalURIOptimizedQuery<>(cloneAdmin, loader, source, this,
182                 getStepToAaiUriWithoutStepGreaterThan(index));
183     }
184
185 }