Enhancements for the aai-common library
[aai/aai-common.git] / aai-core / src / main / java / org / onap / aai / serialization / queryformats / RawFormat.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.serialization.queryformats;
22
23 import com.google.gson.Gson;
24 import com.google.gson.JsonArray;
25 import com.google.gson.JsonObject;
26 import com.google.gson.JsonParser;
27
28 import java.util.*;
29 import java.util.stream.Collectors;
30
31 import org.apache.tinkerpop.gremlin.structure.Direction;
32 import org.apache.tinkerpop.gremlin.structure.Edge;
33 import org.apache.tinkerpop.gremlin.structure.Vertex;
34 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
35 import org.onap.aai.db.props.AAIProperties;
36 import org.onap.aai.introspection.Loader;
37 import org.onap.aai.serialization.db.DBSerializer;
38 import org.onap.aai.serialization.queryformats.exceptions.AAIFormatVertexException;
39 import org.onap.aai.serialization.queryformats.params.Depth;
40 import org.onap.aai.serialization.queryformats.params.AsTree;
41 import org.onap.aai.serialization.queryformats.params.NodesOnly;
42 import org.onap.aai.serialization.queryformats.utils.UrlBuilder;
43
44 public class RawFormat extends MultiFormatMapper {
45     protected JsonParser parser = new JsonParser();
46     protected final DBSerializer serializer;
47     protected final Loader loader;
48     protected final UrlBuilder urlBuilder;
49     protected final int depth;
50     protected final boolean nodesOnly;
51
52     protected RawFormat(Builder builder) {
53         this.urlBuilder = builder.getUrlBuilder();
54         this.loader = builder.getLoader();
55         this.serializer = builder.getSerializer();
56         this.depth = builder.getDepth();
57         this.nodesOnly = builder.isNodesOnly();
58         this.isTree = builder.isTree();
59     }
60
61     @Override
62     public Optional<JsonObject> getJsonFromVertex(Vertex v, Map<String, List<String>> selectedProps) throws AAIFormatVertexException {
63         JsonObject json = new JsonObject();
64         json.addProperty("id", v.id().toString());
65         json.addProperty("node-type", v.<String>value(AAIProperties.NODE_TYPE));
66         json.addProperty("url", this.urlBuilder.pathed(v));
67         Optional<JsonObject> properties = this.createSelectedPropertiesObject(v, selectedProps);
68         if (properties.isPresent()) {
69             json.add("properties", properties.get());
70         } else {
71             return Optional.empty();
72         }
73         if (!nodesOnly) {
74             json.add("related-to", this.createRelationshipObject(v));
75         }
76         return Optional.of(json);
77     }
78
79     @Override
80     public int parallelThreshold() {
81         return 100;
82     }
83
84     public Optional<JsonObject> createPropertiesObject(Vertex v) throws AAIFormatVertexException {
85         JsonObject json = new JsonObject();
86         Iterator<VertexProperty<Object>> iter = v.properties();
87
88         while (iter.hasNext()) {
89             VertexProperty<Object> prop = iter.next();
90             if (prop.value() instanceof String) {
91                 json.addProperty(prop.key(), (String) prop.value());
92             } else if (prop.value() instanceof Boolean) {
93                 json.addProperty(prop.key(), (Boolean) prop.value());
94             } else if (prop.value() instanceof Number) {
95                 json.addProperty(prop.key(), (Number) prop.value());
96             } else if (prop.value() instanceof List) {
97                 Gson gson = new Gson();
98                 String list = gson.toJson(prop.value());
99
100                 json.addProperty(prop.key(), list);
101             } else {
102                 // throw exception?
103                 return null;
104             }
105         }
106
107         return Optional.of(json);
108     }
109
110     public Optional<JsonObject> createSelectedPropertiesObject(Vertex v, Map<String, List<String>> selectedProps) throws AAIFormatVertexException {
111         JsonObject json = new JsonObject();
112         String nodeType = v.<String>value(AAIProperties.NODE_TYPE);
113         Set<String> propList = removeSingleQuotesForProperties(selectedProps.get(nodeType));
114         Iterator<VertexProperty<Object>> iter = v.properties();
115
116         Gson gson = new Gson();
117         while (iter.hasNext()) {
118             VertexProperty<Object> prop = iter.next();
119             if (propList != null && !propList.isEmpty()) {
120                 if (propList.contains(prop.label())) {
121                     if (prop.value() instanceof String) {
122                         json.addProperty(prop.key(), (String) prop.value());
123                     } else if (prop.value() instanceof Boolean) {
124                         json.addProperty(prop.key(), (Boolean) prop.value());
125                     } else if (prop.value() instanceof Number) {
126                         json.addProperty(prop.key(), (Number) prop.value());
127                     } else if (prop.value() instanceof List) {
128                         json.addProperty(prop.key(), gson.toJson(prop.value()));
129                     } else {
130                         // throw exception?
131                         return null;
132                     }
133                 }
134             } else {
135                 return this.createPropertiesObject(v);
136             }
137         }
138
139         return Optional.of(json);
140     }
141
142     private Set<String> removeSingleQuotesForProperties(List<String> props){
143         if (props != null && !props.isEmpty()) {
144             return props.stream().map(
145                 e -> e.substring(1, e.length()-1)).collect(Collectors.toSet());
146         } else {
147             return Collections.emptySet();
148         }
149
150     }
151
152     protected JsonArray createRelationshipObject(Vertex v) throws AAIFormatVertexException {
153         JsonArray jarray = new JsonArray();
154         Iterator<Edge> inIter = v.edges(Direction.IN);
155         Iterator<Edge> outIter = v.edges(Direction.OUT);
156
157         while (inIter.hasNext()) {
158             Edge e = inIter.next();
159             Vertex outVertex = e.outVertex();
160             this.addEdge(e, outVertex, jarray);
161         }
162
163         while (outIter.hasNext()) {
164             Edge e = outIter.next();
165             Vertex inVertex = e.inVertex();
166             this.addEdge(e, inVertex, jarray);
167         }
168
169         return jarray;
170     }
171
172     protected void addEdge(Edge e, Vertex vertex, JsonArray array) throws AAIFormatVertexException {
173         array.add(this.getRelatedObject(e.label(), vertex));
174     }
175
176     protected JsonObject getRelatedObject(String label, Vertex related) throws AAIFormatVertexException {
177         JsonObject json = new JsonObject();
178         json.addProperty("id", related.id().toString());
179         json.addProperty("relationship-label", label);
180         json.addProperty("node-type", related.<String>value(AAIProperties.NODE_TYPE));
181         json.addProperty("url", this.urlBuilder.pathed(related));
182
183         return json;
184     }
185
186     public static class Builder implements NodesOnly<Builder>, Depth<Builder>, AsTree<Builder> {
187
188         protected final Loader loader;
189         protected final DBSerializer serializer;
190         protected final UrlBuilder urlBuilder;
191         protected boolean includeUrl = false;
192         protected boolean nodesOnly = false;
193         protected int depth = 1;
194         protected boolean modelDriven = false;
195         protected boolean tree = false;
196
197         public Builder(Loader loader, DBSerializer serializer, UrlBuilder urlBuilder) {
198             this.loader = loader;
199             this.serializer = serializer;
200             this.urlBuilder = urlBuilder;
201         }
202
203         protected Loader getLoader() {
204             return this.loader;
205         }
206
207         protected DBSerializer getSerializer() {
208             return this.serializer;
209         }
210
211         protected UrlBuilder getUrlBuilder() {
212             return this.urlBuilder;
213         }
214
215         protected boolean isTree() { return this.tree; }
216
217         public Builder isTree(Boolean tree) {
218             this.tree = tree;
219             return this;
220         }
221
222         public Builder includeUrl() {
223             this.includeUrl = true;
224             return this;
225         }
226
227         public Builder nodesOnly(Boolean nodesOnly) {
228             this.nodesOnly = nodesOnly;
229             return this;
230         }
231
232         public boolean isNodesOnly() {
233             return this.nodesOnly;
234         }
235
236         public Builder depth(Integer depth) {
237             this.depth = depth;
238             return this;
239         }
240
241         public int getDepth() {
242             return this.depth;
243         }
244
245         public boolean isIncludeUrl() {
246             return this.includeUrl;
247         }
248
249         public Builder modelDriven() {
250             this.modelDriven = true;
251             return this;
252         }
253
254         public boolean getModelDriven() {
255             return this.modelDriven;
256         }
257
258         public RawFormat build() {
259             if (modelDriven) {
260                 return new SimpleFormat(this);
261             } else {
262                 return new RawFormat(this);
263             }
264         }
265     }
266
267     @Override
268     protected Optional<JsonObject> getJsonFromVertex(Vertex v) throws AAIFormatVertexException {
269
270         JsonObject json = new JsonObject();
271         json.addProperty("id", v.id().toString());
272         json.addProperty("node-type", v.<String>value(AAIProperties.NODE_TYPE));
273         json.addProperty("url", this.urlBuilder.pathed(v));
274         Optional<JsonObject> properties = this.createPropertiesObject(v);
275         if (properties.isPresent()) {
276             json.add("properties", properties.get());
277         } else {
278             return Optional.empty();
279         }
280         if (!nodesOnly) {
281             json.add("related-to", this.createRelationshipObject(v));
282         }
283         return Optional.of(json);
284     }
285 }