2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6 * Copyright © 2017-2018 Amdocs
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
21 package org.onap.aai.sparky.viewandinspect.services;
23 import java.io.IOException;
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.List;
28 import java.util.UUID;
30 import org.onap.aai.cl.api.Logger;
31 import org.onap.aai.cl.eelf.LoggerFactory;
32 import org.onap.aai.sparky.logging.AaiUiMsgs;
33 import org.onap.aai.sparky.subscription.config.SubscriptionConfig;
34 import org.onap.aai.sparky.util.ConfigHelper;
35 import org.onap.aai.sparky.viewandinspect.config.VisualizationConfigs;
36 import org.onap.aai.sparky.viewandinspect.entity.ActiveInventoryNode;
37 import org.onap.aai.sparky.viewandinspect.entity.D3VisualizationOutput;
38 import org.onap.aai.sparky.viewandinspect.entity.GraphMeta;
39 import org.onap.aai.sparky.viewandinspect.entity.SparkyGraphNode;
40 import org.onap.aai.sparky.viewandinspect.entity.SparkyGraphLink;
41 import org.onap.aai.sparky.viewandinspect.entity.NodeDebug;
43 import com.fasterxml.jackson.core.JsonProcessingException;
44 import com.fasterxml.jackson.databind.ObjectMapper;
45 import com.fasterxml.jackson.databind.ObjectWriter;
48 * The idea here is to receive a collection of graphs and then fold them together (or not) based on
49 * configuration. The first goal will be to fold all like-resources together, but the choice of
50 * folding could/should be configurable, and will simply change the degree of link based nodes when
51 * we generate the Node-Array and Link-Array output.
57 public class VisualizationTransformer {
59 private static final Logger LOG = LoggerFactory.getInstance().getLogger(
60 VisualizationTransformer.class);
62 List<SparkyGraphNode> flatNodeArray = new ArrayList<SparkyGraphNode>();
65 * Maybe this isn't a string but Json-Model objects that we will convert to final string
66 * representation when we dump the node-array and link-array collections the post-data blob in the
67 * HttpServletResponse.
70 List<SparkyGraphLink> linkArrayOutput = new ArrayList<SparkyGraphLink>();
72 private VisualizationConfigs visualizationConfigs;
73 private SubscriptionConfig subConfig;
76 * Instantiates a new visualization transformer.
78 * @throws Exception the exception
80 public VisualizationTransformer(VisualizationConfigs visualizationConfigs,
81 SubscriptionConfig subConfig) throws Exception {
82 this.visualizationConfigs = visualizationConfigs;
83 this.subConfig = subConfig;
90 * @param method the method
91 * @param startTimeInMs the start time in ms
93 private void logOptime(String method, long startTimeInMs) {
94 LOG.info(AaiUiMsgs.OPERATION_TIME, method,
95 String.valueOf((System.currentTimeMillis() - startTimeInMs)));
99 * Adds the search target attributes to root node.
101 public void addSearchTargetAttributesToRootNode() {
103 for (SparkyGraphNode n : flatNodeArray) {
104 if (n.isRootNode()) {
105 n.getNodeMeta().setSearchTarget(true);
106 n.getNodeMeta().setClassName(this.visualizationConfigs.getSelectedSearchedNodeClassName());
114 * Generate visualization output.
116 * @param preProcessingOpTimeInMs the pre processing op time in ms
117 * @param graphMeta the graph meta
118 * @return the d 3 visualization output
119 * @throws JsonProcessingException the json processing exception
120 * @throws IOException Signals that an I/O exception has occurred.
123 public D3VisualizationOutput generateVisualizationOutput(long preProcessingOpTimeInMs,
124 GraphMeta graphMeta) throws JsonProcessingException, IOException {
126 long opStartTimeInMs = System.currentTimeMillis();
129 * iterate over the flat collection, and only add the graph nodes to the graph node collection
132 D3VisualizationOutput output = new D3VisualizationOutput();
134 output.setGraphMeta(graphMeta);
136 for (SparkyGraphNode n : flatNodeArray) {
137 if ( n.getItemType()!= null) {
138 output.pegCounter(n.getItemType());
142 output.addNodes(flatNodeArray);
143 output.addLinks(linkArrayOutput);
145 int numNodes = flatNodeArray.size();
146 int numLinks = linkArrayOutput.size();
148 LOG.info(AaiUiMsgs.VISUALIZATION_GRAPH_OUTPUT, String.valueOf(numNodes),
149 String.valueOf(numLinks));
151 if (numLinks < (numNodes - 1)) {
152 LOG.warn(AaiUiMsgs.DANGLING_NODE_WARNING, String.valueOf(numLinks),
153 String.valueOf(numNodes));
156 ObjectMapper mapper = new ObjectMapper();
158 final String fileContent = ConfigHelper.getFileContents(
159 System.getProperty("AJSC_HOME") + this.visualizationConfigs.getAaiEntityNodeDescriptors());
160 com.fasterxml.jackson.databind.JsonNode aaiEntityNodeDefinitions = mapper.readTree(fileContent);
161 graphMeta.setAaiEntityNodeDescriptors(aaiEntityNodeDefinitions);
163 graphMeta.setNumLinks(linkArrayOutput.size());
164 graphMeta.setNumNodes(flatNodeArray.size());
165 graphMeta.setRenderTimeInMs(preProcessingOpTimeInMs);
167 output.setGraphMeta(graphMeta);
169 logOptime("generateVisualizationOutput()", opStartTimeInMs);
175 * Convert visualization output to json.
177 * @param output the output
179 * @throws JsonProcessingException the json processing exception
181 public String convertVisualizationOutputToJson(D3VisualizationOutput output)
182 throws JsonProcessingException {
184 if (output == null) {
188 ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
190 return ow.writeValueAsString(output);
195 * Builds the links from graph collection.
197 * @param nodeMap the node map
199 public void buildLinksFromGraphCollection(Map<String, ActiveInventoryNode> nodeMap) {
201 for (ActiveInventoryNode ain : nodeMap.values()) {
204 * This one is a little bit different, when we iterate over the collection we only want to
205 * draw the links for node that are less than the max traversal depth. We want to only draw
206 * links at a depth of n-1 because we are basing the links on the outbound neighbors from the
210 if (ain.getNodeDepth() < this.visualizationConfigs.getMaxSelfLinkTraversalDepth()) {
212 Collection<String> outboundNeighbors = ain.getOutboundNeighbors();
214 for (String outboundNeighbor : outboundNeighbors) {
216 SparkyGraphLink nodeLink = new SparkyGraphLink();
218 nodeLink.setId(UUID.randomUUID().toString());
219 nodeLink.setSource(ain.getNodeId());
220 nodeLink.setTarget(outboundNeighbor);
222 linkArrayOutput.add(nodeLink);
226 Collection<String> inboundNeighbors = ain.getInboundNeighbors();
228 for (String inboundNeighbor : inboundNeighbors) {
230 SparkyGraphLink nodeLink = new SparkyGraphLink();
232 nodeLink.setId(UUID.randomUUID().toString());
233 nodeLink.setSource(ain.getNodeId());
234 nodeLink.setTarget(inboundNeighbor);
236 linkArrayOutput.add(nodeLink);
242 if (LOG.isDebugEnabled()) {
243 LOG.debug(AaiUiMsgs.DEBUG_GENERIC, "buildLinks(),"
244 + " Filtering node = " + ain.getNodeId() + " @ depth = "
245 + ain.getNodeDepth());
254 * Builds the flat node array from graph collection.
256 * @param nodeMap the node map
259 * Recursive function to walk multi-graph nodes and children to build a folded resource target
262 public void buildFlatNodeArrayFromGraphCollection(Map<String, ActiveInventoryNode> nodeMap) {
264 for (ActiveInventoryNode n : nodeMap.values()) {
266 if (n.getNodeDepth() <= this.visualizationConfigs.getMaxSelfLinkTraversalDepth()) {
268 SparkyGraphNode jsonNode = new SparkyGraphNode(n, this.visualizationConfigs, this.subConfig);
270 jsonNode.getNodeMeta().setClassName(this.visualizationConfigs.getGeneralNodeClassName());
272 if (this.visualizationConfigs.isVisualizationDebugEnabled()) {
274 NodeDebug nodeDebug = jsonNode.getNodeMeta().getNodeDebug();
276 if (nodeDebug != null) {
277 nodeDebug.setProcessingError(n.isProcessingErrorOccurred());
278 nodeDebug.setProcessingErrorCauses(n.getProcessingErrorCauses());
281 flatNodeArray.add(jsonNode);
283 if (LOG.isDebugEnabled()) {
284 LOG.debug(AaiUiMsgs.DEBUG_GENERIC,
285 "Filtering node from visualization: " + n.getNodeId() + " @ depth = "