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 final DBSerializer serializer;
60 protected final Loader loader;
61 protected final UrlBuilder urlBuilder;
62 protected final int depth;
63 protected final boolean nodesOnly;
65 protected Aggregate(Builder builder) {
66 this.urlBuilder = builder.getUrlBuilder();
67 this.loader = builder.getLoader();
68 this.serializer = builder.getSerializer();
69 this.depth = builder.getDepth();
70 this.nodesOnly = builder.isNodesOnly();
71 this.isTree = builder.isTree();
75 public Optional<JsonObject> getJsonFromVertex(Vertex v, Map<String, List<String>> selectedProps)
76 throws AAIFormatVertexException {
77 JsonObject json = new JsonObject();
78 JsonObject outer = new JsonObject();
79 Optional<JsonObject> properties = this.createSelectedPropertiesObject(v, selectedProps);
80 if (properties.isPresent()) {
81 json.add("properties", properties.get());
82 outer.add(this.urlBuilder.pathed(v), json.getAsJsonObject());
84 return Optional.empty();
86 return Optional.of(outer);
90 public int parallelThreshold() {
94 public Optional<JsonObject> createPropertiesObject(Vertex v) throws AAIFormatVertexException {
96 final Introspector obj =
97 loader.introspectorFromName(v.<String>property(AAIProperties.NODE_TYPE).orElse(null));
99 final List<Vertex> wrapper = new ArrayList<>();
103 serializer.dbToObject(wrapper, obj, 0, true, "false");
104 } catch (AAIException | UnsupportedEncodingException e) {
105 throw new AAIFormatVertexException(
106 "Failed to format vertex - error while serializing: " + e.getMessage(), e);
109 final String json = obj.marshal(false);
110 return Optional.of(JsonParser.parseString(json).getAsJsonObject());
111 } catch (AAIUnknownObjectException e) {
112 return Optional.empty();
116 public Optional<JsonObject> createSelectedPropertiesObject(Vertex v, Map<String, List<String>> selectedProps)
117 throws AAIFormatVertexException {
118 JsonObject json = new JsonObject();
119 Set<String> propList = null;
120 String nodeType = v.<String>value(AAIProperties.NODE_TYPE);
121 if (selectedProps != null && !selectedProps.isEmpty() && selectedProps.containsKey(nodeType)) {
122 propList = removeSingleQuotesForProperties(selectedProps.get(nodeType));
124 Iterator<VertexProperty<Object>> iter = v.properties();
126 Gson gson = new Gson();
127 while (iter.hasNext()) {
128 VertexProperty<Object> prop = iter.next();
129 if (propList != null && !propList.isEmpty()) {
130 if (propList.contains(prop.label())) {
131 if (prop.value() instanceof String) {
132 json.addProperty(prop.key(), (String) prop.value());
133 } else if (prop.value() instanceof Boolean) {
134 json.addProperty(prop.key(), (Boolean) prop.value());
135 } else if (prop.value() instanceof Number) {
136 json.addProperty(prop.key(), (Number) prop.value());
137 } else if (prop.value() instanceof List) {
138 json.addProperty(prop.key(), gson.toJson(prop.value()));
141 return Optional.empty();
145 return this.createPropertiesObject(v);
149 return Optional.of(json);
152 private Set<String> removeSingleQuotesForProperties(List<String> props) {
153 if (props != null && !props.isEmpty()) {
154 return props.stream().map(e -> e.substring(1, e.length() - 1)).collect(Collectors.toSet());
156 return Collections.emptySet();
160 public JsonArray process(List<Object> queryResults, Map<String, List<String>> properties) {
161 JsonArray body = new JsonArray();
162 Stream<Object> stream;
163 if (queryResults.size() >= this.parallelThreshold()) {
164 stream = queryResults.parallelStream();
166 stream = queryResults.stream();
168 final boolean isParallel = stream.isParallel();
172 return this.formatObject(o, properties);
173 } catch (AAIFormatVertexException e) {
174 LOGGER.warn("Failed to format vertex, returning a partial list " + LogFormatTools.getStackTop(e));
175 } catch (AAIFormatQueryResultFormatNotSupported e) {
176 LOGGER.warn("Failed to format result type of the query " + LogFormatTools.getStackTop(e));
179 return Optional.<JsonObject>empty();
180 }).filter(Optional::isPresent).map(Optional::get).forEach(json -> {
182 synchronized (body) {
193 public Optional<JsonObject> formatObject(Object input, Map<String, List<String>> properties)
194 throws AAIFormatVertexException, AAIFormatQueryResultFormatNotSupported {
195 JsonObject json = new JsonObject();
196 if (input instanceof ArrayList) {
197 Optional<JsonArray> ja = processInput(input, properties);
198 json.add("results", ja.get());
200 throw new AAIFormatQueryResultFormatNotSupported();
202 return Optional.of(json);
205 private Optional<JsonArray> processInput(Object input, Map<String, List<String>> properties)
206 throws AAIFormatVertexException {
207 JsonArray json = new JsonArray();
208 for (Object l : (ArrayList) input) {
209 if (l instanceof ArrayList) {
210 JsonArray inner = new JsonArray();
211 for (Vertex o : (ArrayList<Vertex>) l) {
212 if (o instanceof Vertex) {
213 Optional<JsonObject> obj = this.getJsonFromVertex((Vertex) o, properties);
214 if (obj.isPresent()) {
215 inner.add(obj.get());
223 Optional<JsonObject> obj = this.getJsonFromVertex((Vertex) l, properties);
228 return Optional.of(json);
231 public static class Builder implements NodesOnly<Builder>, Depth<Builder>, AsTree<Builder> {
233 protected final Loader loader;
234 protected final DBSerializer serializer;
235 protected final UrlBuilder urlBuilder;
236 protected boolean includeUrl = false;
237 protected boolean nodesOnly = false;
238 protected int depth = 1;
239 protected boolean modelDriven = false;
240 private boolean tree = false;
242 public Builder(Loader loader, DBSerializer serializer, UrlBuilder urlBuilder) {
243 this.loader = loader;
244 this.serializer = serializer;
245 this.urlBuilder = urlBuilder;
248 protected boolean isTree() {
252 public Builder isTree(Boolean tree) {
257 protected Loader getLoader() {
261 protected DBSerializer getSerializer() {
262 return this.serializer;
265 protected UrlBuilder getUrlBuilder() {
266 return this.urlBuilder;
269 public Builder includeUrl() {
270 this.includeUrl = true;
274 public Builder nodesOnly(Boolean nodesOnly) {
275 this.nodesOnly = nodesOnly;
279 public boolean isNodesOnly() {
280 return this.nodesOnly;
283 public Builder depth(Integer depth) {
288 public int getDepth() {
292 public boolean isIncludeUrl() {
293 return this.includeUrl;
296 public Builder modelDriven() {
297 this.modelDriven = true;
301 public boolean getModelDriven() {
302 return this.modelDriven;
305 public Aggregate build() {
306 return new Aggregate(this);
311 protected Optional<JsonObject> getJsonFromVertex(Vertex v) throws AAIFormatVertexException {
313 JsonObject json = new JsonObject();
314 json.addProperty("url", this.urlBuilder.pathed(v));
315 Optional<JsonObject> properties = this.createPropertiesObject(v);
316 if (properties.isPresent()) {
317 json.add("properties", properties.get());
319 return Optional.empty();
321 return Optional.of(json);