2 * ============LICENSE_START=======================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 package org.onap.aai.serialization.queryformats;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25 import com.google.gson.*;
26 import org.apache.tinkerpop.gremlin.structure.Direction;
27 import org.apache.tinkerpop.gremlin.structure.Edge;
28 import org.apache.tinkerpop.gremlin.structure.Vertex;
29 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
30 import org.onap.aai.db.props.AAIProperties;
31 import org.onap.aai.exceptions.AAIException;
32 import org.onap.aai.introspection.Introspector;
33 import org.onap.aai.introspection.Loader;
34 import org.onap.aai.introspection.exceptions.AAIUnknownObjectException;
35 import org.onap.aai.logging.LogFormatTools;
36 import org.onap.aai.serialization.db.DBSerializer;
37 import org.onap.aai.serialization.queryformats.exceptions.AAIFormatQueryResultFormatNotSupported;
38 import org.onap.aai.serialization.queryformats.exceptions.AAIFormatVertexException;
39 import org.onap.aai.serialization.queryformats.params.AsTree;
40 import org.onap.aai.serialization.queryformats.params.Depth;
41 import org.onap.aai.serialization.queryformats.params.NodesOnly;
42 import org.onap.aai.serialization.queryformats.utils.UrlBuilder;
44 import java.io.UnsupportedEncodingException;
46 import java.util.stream.Collectors;
47 import java.util.stream.Stream;
49 public class Aggregate extends MultiFormatMapper {
50 private static final Logger LOGGER = LoggerFactory.getLogger(LifecycleFormat.class);
51 protected JsonParser parser = new JsonParser();
52 protected final DBSerializer serializer;
53 protected final Loader loader;
54 protected final UrlBuilder urlBuilder;
55 protected final int depth;
56 protected final boolean nodesOnly;
58 protected Aggregate(Builder builder) {
59 this.urlBuilder = builder.getUrlBuilder();
60 this.loader = builder.getLoader();
61 this.serializer = builder.getSerializer();
62 this.depth = builder.getDepth();
63 this.nodesOnly = builder.isNodesOnly();
64 this.isTree = builder.isTree();
68 public Optional<JsonObject> getJsonFromVertex(Vertex v, Map<String, List<String>> selectedProps) throws AAIFormatVertexException{
69 JsonObject json = new JsonObject();
70 JsonObject outer = new JsonObject();
71 Optional<JsonObject> properties = this.createSelectedPropertiesObject(v,selectedProps);
72 if (properties.isPresent()) {
73 json.add("properties", properties.get());
74 outer.add(this.urlBuilder.pathed(v),json.getAsJsonObject());
76 return Optional.empty();
78 return Optional.of(outer);
82 public int parallelThreshold() {
86 public Optional<JsonObject> createPropertiesObject(Vertex v) throws AAIFormatVertexException {
88 final Introspector obj =
89 loader.introspectorFromName(v.<String>property(AAIProperties.NODE_TYPE).orElse(null));
91 final List<Vertex> wrapper = new ArrayList<>();
95 serializer.dbToObject(wrapper, obj, 0, true, "false");
96 } catch (AAIException | UnsupportedEncodingException e) {
97 throw new AAIFormatVertexException(
98 "Failed to format vertex - error while serializing: " + e.getMessage(), e);
101 final String json = obj.marshal(false);
102 return Optional.of(parser.parse(json).getAsJsonObject());
103 } catch (AAIUnknownObjectException e) {
104 return Optional.empty();
108 public Optional<JsonObject> createSelectedPropertiesObject(Vertex v, Map<String, List<String>> selectedProps) throws AAIFormatVertexException {
109 JsonObject json = new JsonObject();
110 Set<String> propList = null;
111 String nodeType = v.<String>value(AAIProperties.NODE_TYPE);
112 if (selectedProps != null && !selectedProps.isEmpty() && selectedProps.containsKey(nodeType)) {
113 propList = removeSingleQuotesForProperties(selectedProps.get(nodeType));
115 Iterator<VertexProperty<Object>> iter = v.properties();
117 Gson gson = new Gson();
118 while (iter.hasNext()) {
119 VertexProperty<Object> prop = iter.next();
120 if (propList != null && !propList.isEmpty()) {
121 if (propList.contains(prop.label())) {
122 if (prop.value() instanceof String) {
123 json.addProperty(prop.key(), (String) prop.value());
124 } else if (prop.value() instanceof Boolean) {
125 json.addProperty(prop.key(), (Boolean) prop.value());
126 } else if (prop.value() instanceof Number) {
127 json.addProperty(prop.key(), (Number) prop.value());
128 } else if (prop.value() instanceof List) {
129 json.addProperty(prop.key(), gson.toJson(prop.value()));
132 return Optional.empty();
136 return this.createPropertiesObject(v);
140 return Optional.of(json);
143 private Set<String> removeSingleQuotesForProperties(List<String> props){
144 if (props != null && !props.isEmpty()) {
145 return props.stream().map(
146 e -> e.substring(1, e.length()-1)).collect(Collectors.toSet());
148 return Collections.emptySet();
152 public JsonArray process(List<Object> queryResults, Map<String, List<String>> properties) {
153 JsonArray body = new JsonArray();
154 Stream<Object> stream;
155 if (queryResults.size() >= this.parallelThreshold()) {
156 stream = queryResults.parallelStream();
158 stream = queryResults.stream();
160 final boolean isParallel = stream.isParallel();
164 return this.formatObject(o, properties);
165 } catch (AAIFormatVertexException e) {
166 LOGGER.warn("Failed to format vertex, returning a partial list " + LogFormatTools.getStackTop(e));
167 } catch (AAIFormatQueryResultFormatNotSupported e) {
168 LOGGER.warn("Failed to format result type of the query " + LogFormatTools.getStackTop(e));
171 return Optional.<JsonObject>empty();
172 }).filter(Optional::isPresent)
176 synchronized (body) {
187 public Optional<JsonObject> formatObject(Object input, Map<String, List<String>> properties)
188 throws AAIFormatVertexException, AAIFormatQueryResultFormatNotSupported {
189 JsonObject json = new JsonObject();
190 if (input instanceof ArrayList) {
191 Optional<JsonArray> ja = processInput(input, properties);
192 json.add("results", ja.get());
194 throw new AAIFormatQueryResultFormatNotSupported();
196 return Optional.of(json);
199 private Optional<JsonArray> processInput(Object input, Map properties) throws AAIFormatVertexException {
200 JsonArray json = new JsonArray();
201 for (Object l : (ArrayList) input) {
202 if (l instanceof ArrayList) {
203 JsonArray inner = new JsonArray();
204 for (Vertex o : (ArrayList<Vertex>) l) {
205 if (o instanceof Vertex) {
206 Optional<JsonObject> obj = this.getJsonFromVertex((Vertex) o, properties);
207 if (obj.isPresent()) {
208 inner.add(obj.get());
216 Optional<JsonObject> obj = this.getJsonFromVertex((Vertex)l, properties);
217 if(obj.isPresent()) json.add(obj.get());
220 return Optional.of(json);
223 public static class Builder implements NodesOnly<Builder>, Depth<Builder>, AsTree<Builder> {
225 protected final Loader loader;
226 protected final DBSerializer serializer;
227 protected final UrlBuilder urlBuilder;
228 protected boolean includeUrl = false;
229 protected boolean nodesOnly = false;
230 protected int depth = 1;
231 protected boolean modelDriven = false;
232 private boolean tree = false;
234 public Builder(Loader loader, DBSerializer serializer, UrlBuilder urlBuilder) {
235 this.loader = loader;
236 this.serializer = serializer;
237 this.urlBuilder = urlBuilder;
240 protected boolean isTree() { return this.tree; }
242 public Builder isTree(Boolean tree) {
247 protected Loader getLoader() {
251 protected DBSerializer getSerializer() {
252 return this.serializer;
255 protected UrlBuilder getUrlBuilder() {
256 return this.urlBuilder;
259 public Builder includeUrl() {
260 this.includeUrl = true;
264 public Builder nodesOnly(Boolean nodesOnly) {
265 this.nodesOnly = nodesOnly;
269 public boolean isNodesOnly() {
270 return this.nodesOnly;
273 public Builder depth(Integer depth) {
278 public int getDepth() {
282 public boolean isIncludeUrl() {
283 return this.includeUrl;
286 public Builder modelDriven() {
287 this.modelDriven = true;
291 public boolean getModelDriven() {
292 return this.modelDriven;
295 public Aggregate build() {
296 return new Aggregate(this);
301 protected Optional<JsonObject> getJsonFromVertex(Vertex v) throws AAIFormatVertexException {
303 JsonObject json = new JsonObject();
304 json.addProperty("url", this.urlBuilder.pathed(v));
305 Optional<JsonObject> properties = this.createPropertiesObject(v);
306 if (properties.isPresent()) {
307 json.add("properties", properties.get());
309 return Optional.empty();
311 return Optional.of(json);