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