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 com.google.gson.Gson;
24 import com.google.gson.JsonArray;
25 import com.google.gson.JsonObject;
26 import com.google.gson.JsonParser;
28 import java.io.UnsupportedEncodingException;
29 import java.util.ArrayList;
30 import java.util.Collections;
31 import java.util.Iterator;
32 import java.util.List;
34 import java.util.Optional;
36 import java.util.stream.Collectors;
37 import java.util.stream.Stream;
39 import org.apache.tinkerpop.gremlin.structure.Vertex;
40 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
41 import org.onap.aai.db.props.AAIProperties;
42 import org.onap.aai.exceptions.AAIException;
43 import org.onap.aai.introspection.Introspector;
44 import org.onap.aai.introspection.Loader;
45 import org.onap.aai.introspection.exceptions.AAIUnknownObjectException;
46 import org.onap.aai.logging.LogFormatTools;
47 import org.onap.aai.serialization.db.DBSerializer;
48 import org.onap.aai.serialization.queryformats.exceptions.AAIFormatQueryResultFormatNotSupported;
49 import org.onap.aai.serialization.queryformats.exceptions.AAIFormatVertexException;
50 import org.onap.aai.serialization.queryformats.params.AsTree;
51 import org.onap.aai.serialization.queryformats.params.Depth;
52 import org.onap.aai.serialization.queryformats.params.NodesOnly;
53 import org.onap.aai.serialization.queryformats.utils.UrlBuilder;
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
57 public class Aggregate extends MultiFormatMapper {
58 private static final Logger LOGGER = LoggerFactory.getLogger(LifecycleFormat.class);
59 protected JsonParser parser = new JsonParser();
60 protected final DBSerializer serializer;
61 protected final Loader loader;
62 protected final UrlBuilder urlBuilder;
63 protected final int depth;
64 protected final boolean nodesOnly;
66 protected Aggregate(Builder builder) {
67 this.urlBuilder = builder.getUrlBuilder();
68 this.loader = builder.getLoader();
69 this.serializer = builder.getSerializer();
70 this.depth = builder.getDepth();
71 this.nodesOnly = builder.isNodesOnly();
72 this.isTree = builder.isTree();
76 public Optional<JsonObject> getJsonFromVertex(Vertex v, Map<String, List<String>> selectedProps)
77 throws AAIFormatVertexException {
78 JsonObject json = new JsonObject();
79 JsonObject outer = new JsonObject();
80 Optional<JsonObject> properties = this.createSelectedPropertiesObject(v, selectedProps);
81 if (properties.isPresent()) {
82 json.add("properties", properties.get());
83 outer.add(this.urlBuilder.pathed(v), json.getAsJsonObject());
85 return Optional.empty();
87 return Optional.of(outer);
91 public int parallelThreshold() {
95 public Optional<JsonObject> createPropertiesObject(Vertex v) throws AAIFormatVertexException {
97 final Introspector obj =
98 loader.introspectorFromName(v.<String>property(AAIProperties.NODE_TYPE).orElse(null));
100 final List<Vertex> wrapper = new ArrayList<>();
104 serializer.dbToObject(wrapper, obj, 0, true, "false");
105 } catch (AAIException | UnsupportedEncodingException e) {
106 throw new AAIFormatVertexException(
107 "Failed to format vertex - error while serializing: " + e.getMessage(), e);
110 final String json = obj.marshal(false);
111 return Optional.of(parser.parse(json).getAsJsonObject());
112 } catch (AAIUnknownObjectException e) {
113 return Optional.empty();
117 public Optional<JsonObject> createSelectedPropertiesObject(Vertex v, Map<String, List<String>> selectedProps)
118 throws AAIFormatVertexException {
119 JsonObject json = new JsonObject();
120 Set<String> propList = null;
121 String nodeType = v.<String>value(AAIProperties.NODE_TYPE);
122 if (selectedProps != null && !selectedProps.isEmpty() && selectedProps.containsKey(nodeType)) {
123 propList = removeSingleQuotesForProperties(selectedProps.get(nodeType));
125 Iterator<VertexProperty<Object>> iter = v.properties();
127 Gson gson = new Gson();
128 while (iter.hasNext()) {
129 VertexProperty<Object> prop = iter.next();
130 if (propList != null && !propList.isEmpty()) {
131 if (propList.contains(prop.label())) {
132 if (prop.value() instanceof String) {
133 json.addProperty(prop.key(), (String) prop.value());
134 } else if (prop.value() instanceof Boolean) {
135 json.addProperty(prop.key(), (Boolean) prop.value());
136 } else if (prop.value() instanceof Number) {
137 json.addProperty(prop.key(), (Number) prop.value());
138 } else if (prop.value() instanceof List) {
139 json.addProperty(prop.key(), gson.toJson(prop.value()));
142 return Optional.empty();
146 return this.createPropertiesObject(v);
150 return Optional.of(json);
153 private Set<String> removeSingleQuotesForProperties(List<String> props) {
154 if (props != null && !props.isEmpty()) {
155 return props.stream().map(e -> e.substring(1, e.length() - 1)).collect(Collectors.toSet());
157 return Collections.emptySet();
161 public JsonArray process(List<Object> queryResults, Map<String, List<String>> properties) {
162 JsonArray body = new JsonArray();
163 Stream<Object> stream;
164 if (queryResults.size() >= this.parallelThreshold()) {
165 stream = queryResults.parallelStream();
167 stream = queryResults.stream();
169 final boolean isParallel = stream.isParallel();
173 return this.formatObject(o, properties);
174 } catch (AAIFormatVertexException e) {
175 LOGGER.warn("Failed to format vertex, returning a partial list " + LogFormatTools.getStackTop(e));
176 } catch (AAIFormatQueryResultFormatNotSupported e) {
177 LOGGER.warn("Failed to format result type of the query " + LogFormatTools.getStackTop(e));
180 return Optional.<JsonObject>empty();
181 }).filter(Optional::isPresent).map(Optional::get).forEach(json -> {
183 synchronized (body) {
194 public Optional<JsonObject> formatObject(Object input, Map<String, List<String>> properties)
195 throws AAIFormatVertexException, AAIFormatQueryResultFormatNotSupported {
196 JsonObject json = new JsonObject();
197 if (input instanceof ArrayList) {
198 Optional<JsonArray> ja = processInput(input, properties);
199 json.add("results", ja.get());
201 throw new AAIFormatQueryResultFormatNotSupported();
203 return Optional.of(json);
206 private Optional<JsonArray> processInput(Object input, Map<String, List<String>> properties)
207 throws AAIFormatVertexException {
208 JsonArray json = new JsonArray();
209 for (Object l : (ArrayList) input) {
210 if (l instanceof ArrayList) {
211 JsonArray inner = new JsonArray();
212 for (Vertex o : (ArrayList<Vertex>) l) {
213 if (o instanceof Vertex) {
214 Optional<JsonObject> obj = this.getJsonFromVertex((Vertex) o, properties);
215 if (obj.isPresent()) {
216 inner.add(obj.get());
224 Optional<JsonObject> obj = this.getJsonFromVertex((Vertex) l, properties);
229 return Optional.of(json);
232 public static class Builder implements NodesOnly<Builder>, Depth<Builder>, AsTree<Builder> {
234 protected final Loader loader;
235 protected final DBSerializer serializer;
236 protected final UrlBuilder urlBuilder;
237 protected boolean includeUrl = false;
238 protected boolean nodesOnly = false;
239 protected int depth = 1;
240 protected boolean modelDriven = false;
241 private boolean tree = false;
243 public Builder(Loader loader, DBSerializer serializer, UrlBuilder urlBuilder) {
244 this.loader = loader;
245 this.serializer = serializer;
246 this.urlBuilder = urlBuilder;
249 protected boolean isTree() {
253 public Builder isTree(Boolean tree) {
258 protected Loader getLoader() {
262 protected DBSerializer getSerializer() {
263 return this.serializer;
266 protected UrlBuilder getUrlBuilder() {
267 return this.urlBuilder;
270 public Builder includeUrl() {
271 this.includeUrl = true;
275 public Builder nodesOnly(Boolean nodesOnly) {
276 this.nodesOnly = nodesOnly;
280 public boolean isNodesOnly() {
281 return this.nodesOnly;
284 public Builder depth(Integer depth) {
289 public int getDepth() {
293 public boolean isIncludeUrl() {
294 return this.includeUrl;
297 public Builder modelDriven() {
298 this.modelDriven = true;
302 public boolean getModelDriven() {
303 return this.modelDriven;
306 public Aggregate build() {
307 return new Aggregate(this);
312 protected Optional<JsonObject> getJsonFromVertex(Vertex v) throws AAIFormatVertexException {
314 JsonObject json = new JsonObject();
315 json.addProperty("url", this.urlBuilder.pathed(v));
316 Optional<JsonObject> properties = this.createPropertiesObject(v);
317 if (properties.isPresent()) {
318 json.add("properties", properties.get());
320 return Optional.empty();
322 return Optional.of(json);