2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
6 * Copyright © 2017 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 * ECOMP is a trademark and service mark of AT&T Intellectual Property.
23 package org.openecomp.sparky.viewandinspect.services;
25 import java.io.IOException;
26 import java.util.ArrayList;
27 import java.util.Collection;
28 import java.util.List;
31 import java.util.UUID;
33 import org.openecomp.cl.api.Logger;
34 import org.openecomp.cl.eelf.LoggerFactory;
35 import org.openecomp.sparky.dal.aai.config.ActiveInventoryConfig;
36 import org.openecomp.sparky.logging.AaiUiMsgs;
37 import org.openecomp.sparky.util.ConfigHelper;
38 import org.openecomp.sparky.viewandinspect.config.VisualizationConfig;
39 import org.openecomp.sparky.viewandinspect.entity.ActiveInventoryNode;
40 import org.openecomp.sparky.viewandinspect.entity.D3VisualizationOutput;
41 import org.openecomp.sparky.viewandinspect.entity.GraphMeta;
42 import org.openecomp.sparky.viewandinspect.entity.JsonNode;
43 import org.openecomp.sparky.viewandinspect.entity.JsonNodeLink;
44 import org.openecomp.sparky.viewandinspect.entity.NodeDebug;
46 import com.fasterxml.jackson.core.JsonProcessingException;
47 import com.fasterxml.jackson.databind.ObjectMapper;
48 import com.fasterxml.jackson.databind.ObjectWriter;
51 * The idea here is to receive a collection of graphs and then fold them together (or not) based on
52 * configuration. The first goal will be to fold all like-resources together, but the choice of
53 * folding could/should be configurable, and will simply change the degree of link based nodes when
54 * we generate the Node-Array and Link-Array output.
60 public class VisualizationTransformer {
62 private static final Logger LOG = LoggerFactory.getInstance().getLogger(
63 VisualizationTransformer.class);
65 List<JsonNode> flatNodeArray = new ArrayList<JsonNode>();
66 Set<String> enrichableUriPrefixes = null;
69 * Maybe this isn't a string but Json-Model objects that we will convert to final string
70 * representation when we dump the node-array and link-array collections the post-data blob in the
71 * HttpServletResponse.
74 List<JsonNodeLink> linkArrayOutput = new ArrayList<JsonNodeLink>();
78 private VisualizationConfig visualizationConfig;
82 * Instantiates a new visualization transformer.
84 * @throws Exception the exception
86 public VisualizationTransformer() throws Exception {
87 visualizationConfig = VisualizationConfig.getConfig();
95 * @param method the method
96 * @param startTimeInMs the start time in ms
98 private void logOptime(String method, long startTimeInMs) {
99 LOG.info(AaiUiMsgs.OPERATION_TIME, method,
100 String.valueOf((System.currentTimeMillis() - startTimeInMs)));
104 * Adds the search target attributes to root node.
106 public void addSearchTargetAttributesToRootNode() {
108 for (JsonNode n : flatNodeArray) {
109 if (n.isRootNode()) {
110 n.getNodeMeta().setSearchTarget(true);
111 n.getNodeMeta().setClassName(visualizationConfig.getSelectedSearchedNodeClassName());
119 * Generate visualization output.
121 * @param preProcessingOpTimeInMs the pre processing op time in ms
122 * @param graphMeta the graph meta
123 * @return the d 3 visualization output
124 * @throws JsonProcessingException the json processing exception
125 * @throws IOException Signals that an I/O exception has occurred.
128 public D3VisualizationOutput generateVisualizationOutput(long preProcessingOpTimeInMs,
129 GraphMeta graphMeta) throws JsonProcessingException, IOException {
131 long opStartTimeInMs = System.currentTimeMillis();
134 * iterate over the flat collection, and only add the graph nodes to the graph node collection
137 D3VisualizationOutput output = new D3VisualizationOutput();
139 output.setGraphMeta(graphMeta);
141 for (JsonNode n : flatNodeArray) {
142 if ( n.getItemType()!= null) {
143 output.pegCounter(n.getItemType());
147 output.addNodes(flatNodeArray);
148 output.addLinks(linkArrayOutput);
150 int numNodes = flatNodeArray.size();
151 int numLinks = linkArrayOutput.size();
153 LOG.info(AaiUiMsgs.VISUALIZATION_GRAPH_OUTPUT, String.valueOf(numNodes),
154 String.valueOf(numLinks));
156 if (numLinks < (numNodes - 1)) {
157 LOG.warn(AaiUiMsgs.DANGLING_NODE_WARNING, String.valueOf(numLinks),
158 String.valueOf(numNodes));
161 ObjectMapper mapper = new ObjectMapper();
163 final String fileContent = ConfigHelper.getFileContents(
164 System.getProperty("AJSC_HOME") + visualizationConfig.getAaiEntityNodeDescriptors());
165 com.fasterxml.jackson.databind.JsonNode aaiEntityNodeDefinitions = mapper.readTree(fileContent);
166 graphMeta.setAaiEntityNodeDescriptors(aaiEntityNodeDefinitions);
168 graphMeta.setNumLinks(linkArrayOutput.size());
169 graphMeta.setNumNodes(flatNodeArray.size());
170 graphMeta.setRenderTimeInMs(preProcessingOpTimeInMs);
172 output.setGraphMeta(graphMeta);
174 logOptime("generateVisualizationOutput()", opStartTimeInMs);
180 * Convert visualization output to json.
182 * @param output the output
184 * @throws JsonProcessingException the json processing exception
186 public String convertVisualizationOutputToJson(D3VisualizationOutput output)
187 throws JsonProcessingException {
189 if (output == null) {
193 ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
195 return ow.writeValueAsString(output);
200 * Builds the links from graph collection.
202 * @param nodeMap the node map
204 public void buildLinksFromGraphCollection(Map<String, ActiveInventoryNode> nodeMap) {
206 for (ActiveInventoryNode ain : nodeMap.values()) {
209 * This one is a little bit different, when we iterate over the collection we only want to
210 * draw the links for node that are less than the max traversal depth. We want to only draw
211 * links at a depth of n-1 because we are basing the links on the outbound neighbors from the
215 if (ain.getNodeDepth() < VisualizationConfig.getConfig().getMaxSelfLinkTraversalDepth()) {
217 Collection<String> outboundNeighbors = ain.getOutboundNeighbors();
219 for (String outboundNeighbor : outboundNeighbors) {
221 JsonNodeLink nodeLink = new JsonNodeLink();
223 nodeLink.setId(UUID.randomUUID().toString());
224 nodeLink.setSource(ain.getNodeId());
225 nodeLink.setTarget(outboundNeighbor);
227 linkArrayOutput.add(nodeLink);
231 Collection<String> inboundNeighbors = ain.getInboundNeighbors();
233 for (String inboundNeighbor : inboundNeighbors) {
235 JsonNodeLink nodeLink = new JsonNodeLink();
237 nodeLink.setId(UUID.randomUUID().toString());
238 nodeLink.setSource(ain.getNodeId());
239 nodeLink.setTarget(inboundNeighbor);
241 linkArrayOutput.add(nodeLink);
247 if (LOG.isDebugEnabled()) {
248 LOG.debug(AaiUiMsgs.DEBUG_GENERIC, "buildLinks(),"
249 + " Filtering node = " + ain.getNodeId() + " @ depth = "
250 + ain.getNodeDepth());
259 * Builds the flat node array from graph collection.
261 * @param nodeMap the node map
264 * Recursive function to walk multi-graph nodes and children to build a folded resource target
267 public void buildFlatNodeArrayFromGraphCollection(Map<String, ActiveInventoryNode> nodeMap) {
269 for (ActiveInventoryNode n : nodeMap.values()) {
271 if (n.getNodeDepth() <= VisualizationConfig.getConfig().getMaxSelfLinkTraversalDepth()) {
273 JsonNode jsonNode = new JsonNode(n);
275 if (this.isUriEnrichable(n.getSelfLink())) {
276 jsonNode.getNodeMeta().setEnrichableNode(true);
279 jsonNode.getNodeMeta().setClassName(visualizationConfig.getGeneralNodeClassName());
281 if (VisualizationConfig.getConfig().isVisualizationDebugEnabled()) {
283 NodeDebug nodeDebug = jsonNode.getNodeMeta().getNodeDebug();
285 if (nodeDebug != null) {
286 nodeDebug.setProcessingError(n.isProcessingErrorOccurred());
287 nodeDebug.setProcessingErrorCauses(n.getProcessingErrorCauses());
290 flatNodeArray.add(jsonNode);
292 if (LOG.isDebugEnabled()) {
293 LOG.debug(AaiUiMsgs.DEBUG_GENERIC,
294 "Filtering node from visualization: " + n.getNodeId() + " @ depth = "
302 * Checks if is uri enrichable.
305 * @return true, if is uri enrichable
307 private boolean isUriEnrichable(String uri) {
308 if (enrichableUriPrefixes != null) {
309 for (String prefix : enrichableUriPrefixes) {
310 if (uri.contains(prefix)) { // AAI-4089