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.*;
25 import java.io.UnsupportedEncodingException;
27 import java.util.stream.Collectors;
28 import java.util.stream.Stream;
30 import org.apache.tinkerpop.gremlin.structure.Vertex;
31 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
32 import org.onap.aai.db.props.AAIProperties;
33 import org.onap.aai.exceptions.AAIException;
34 import org.onap.aai.introspection.Introspector;
35 import org.onap.aai.introspection.Loader;
36 import org.onap.aai.introspection.exceptions.AAIUnknownObjectException;
37 import org.onap.aai.logging.LogFormatTools;
38 import org.onap.aai.serialization.db.DBSerializer;
39 import org.onap.aai.serialization.queryformats.exceptions.AAIFormatQueryResultFormatNotSupported;
40 import org.onap.aai.serialization.queryformats.exceptions.AAIFormatVertexException;
41 import org.onap.aai.serialization.queryformats.params.AsTree;
42 import org.onap.aai.serialization.queryformats.params.Depth;
43 import org.onap.aai.serialization.queryformats.params.NodesOnly;
44 import org.onap.aai.serialization.queryformats.utils.UrlBuilder;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
48 public class Aggregate extends MultiFormatMapper {
49 private static final Logger LOGGER = LoggerFactory.getLogger(LifecycleFormat.class);
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;
57 protected Aggregate(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();
67 public Optional<JsonObject> getJsonFromVertex(Vertex v, Map<String, List<String>> selectedProps)
68 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)
109 throws AAIFormatVertexException {
110 JsonObject json = new JsonObject();
111 Set<String> propList = null;
112 String nodeType = v.<String>value(AAIProperties.NODE_TYPE);
113 if (selectedProps != null && !selectedProps.isEmpty() && selectedProps.containsKey(nodeType)) {
114 propList = removeSingleQuotesForProperties(selectedProps.get(nodeType));
116 Iterator<VertexProperty<Object>> iter = v.properties();
118 Gson gson = new Gson();
119 while (iter.hasNext()) {
120 VertexProperty<Object> prop = iter.next();
121 if (propList != null && !propList.isEmpty()) {
122 if (propList.contains(prop.label())) {
123 if (prop.value() instanceof String) {
124 json.addProperty(prop.key(), (String) prop.value());
125 } else if (prop.value() instanceof Boolean) {
126 json.addProperty(prop.key(), (Boolean) prop.value());
127 } else if (prop.value() instanceof Number) {
128 json.addProperty(prop.key(), (Number) prop.value());
129 } else if (prop.value() instanceof List) {
130 json.addProperty(prop.key(), gson.toJson(prop.value()));
133 return Optional.empty();
137 return this.createPropertiesObject(v);
141 return Optional.of(json);
144 private Set<String> removeSingleQuotesForProperties(List<String> props) {
145 if (props != null && !props.isEmpty()) {
146 return props.stream().map(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).map(Optional::get).forEach(json -> {
174 synchronized (body) {
185 public Optional<JsonObject> formatObject(Object input, Map<String, List<String>> properties)
186 throws AAIFormatVertexException, AAIFormatQueryResultFormatNotSupported {
187 JsonObject json = new JsonObject();
188 if (input instanceof ArrayList) {
189 Optional<JsonArray> ja = processInput(input, properties);
190 json.add("results", ja.get());
192 throw new AAIFormatQueryResultFormatNotSupported();
194 return Optional.of(json);
197 private Optional<JsonArray> processInput(Object input, Map properties) throws AAIFormatVertexException {
198 JsonArray json = new JsonArray();
199 for (Object l : (ArrayList) input) {
200 if (l instanceof ArrayList) {
201 JsonArray inner = new JsonArray();
202 for (Vertex o : (ArrayList<Vertex>) l) {
203 if (o instanceof Vertex) {
204 Optional<JsonObject> obj = this.getJsonFromVertex((Vertex) o, properties);
205 if (obj.isPresent()) {
206 inner.add(obj.get());
214 Optional<JsonObject> obj = this.getJsonFromVertex((Vertex) l, properties);
219 return Optional.of(json);
222 public static class Builder implements NodesOnly<Builder>, Depth<Builder>, AsTree<Builder> {
224 protected final Loader loader;
225 protected final DBSerializer serializer;
226 protected final UrlBuilder urlBuilder;
227 protected boolean includeUrl = false;
228 protected boolean nodesOnly = false;
229 protected int depth = 1;
230 protected boolean modelDriven = false;
231 private boolean tree = false;
233 public Builder(Loader loader, DBSerializer serializer, UrlBuilder urlBuilder) {
234 this.loader = loader;
235 this.serializer = serializer;
236 this.urlBuilder = urlBuilder;
239 protected boolean isTree() {
243 public Builder isTree(Boolean tree) {
248 protected Loader getLoader() {
252 protected DBSerializer getSerializer() {
253 return this.serializer;
256 protected UrlBuilder getUrlBuilder() {
257 return this.urlBuilder;
260 public Builder includeUrl() {
261 this.includeUrl = true;
265 public Builder nodesOnly(Boolean nodesOnly) {
266 this.nodesOnly = nodesOnly;
270 public boolean isNodesOnly() {
271 return this.nodesOnly;
274 public Builder depth(Integer depth) {
279 public int getDepth() {
283 public boolean isIncludeUrl() {
284 return this.includeUrl;
287 public Builder modelDriven() {
288 this.modelDriven = true;
292 public boolean getModelDriven() {
293 return this.modelDriven;
296 public Aggregate build() {
297 return new Aggregate(this);
302 protected Optional<JsonObject> getJsonFromVertex(Vertex v) throws AAIFormatVertexException {
304 JsonObject json = new JsonObject();
305 json.addProperty("url", this.urlBuilder.pathed(v));
306 Optional<JsonObject> properties = this.createPropertiesObject(v);
307 if (properties.isPresent()) {
308 json.add("properties", properties.get());
310 return Optional.empty();
312 return Optional.of(json);