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