Adding interfaces in documentation
[aai/sparky-be.git] / src / main / java / org / onap / aai / sparky / viewandinspect / services / VisualizationTransformer.java
1 /**
2  * ============LICENSE_START=======================================================
3  * org.onap.aai
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
11  *
12  *       http://www.apache.org/licenses/LICENSE-2.0
13  *
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=========================================================
20  */
21 package org.onap.aai.sparky.viewandinspect.services;
22
23 import java.io.IOException;
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.UUID;
29
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;
42
43 import com.fasterxml.jackson.core.JsonProcessingException;
44 import com.fasterxml.jackson.databind.ObjectMapper;
45 import com.fasterxml.jackson.databind.ObjectWriter;
46
47 /**
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.
52  * 
53  * @author DAVEA
54  *
55  */
56
57 public class VisualizationTransformer {
58
59   private static final Logger LOG = LoggerFactory.getInstance().getLogger(
60       VisualizationTransformer.class);
61
62   List<SparkyGraphNode> flatNodeArray = new ArrayList<SparkyGraphNode>();
63
64   /*
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.
68    */
69
70   List<SparkyGraphLink> linkArrayOutput = new ArrayList<SparkyGraphLink>();
71   
72   private VisualizationConfigs visualizationConfigs;
73   private SubscriptionConfig subConfig;
74
75   /**
76    * Instantiates a new visualization transformer.
77    *
78    * @throws Exception the exception
79    */
80   public VisualizationTransformer(VisualizationConfigs visualizationConfigs,
81       SubscriptionConfig subConfig) throws Exception {
82           this.visualizationConfigs = visualizationConfigs; 
83           this.subConfig = subConfig;
84   }
85
86
87   /**
88    * Log optime.
89    *
90    * @param method the method
91    * @param startTimeInMs the start time in ms
92    */
93   private void logOptime(String method, long startTimeInMs) {
94     LOG.info(AaiUiMsgs.OPERATION_TIME, method,
95         String.valueOf((System.currentTimeMillis() - startTimeInMs)));
96   }
97
98   /**
99    * Adds the search target attributes to root node.
100    */
101   public void addSearchTargetAttributesToRootNode() {
102
103     for (SparkyGraphNode n : flatNodeArray) {
104       if (n.isRootNode()) {
105         n.getNodeMeta().setSearchTarget(true);
106         n.getNodeMeta().setClassName(this.visualizationConfigs.getSelectedSearchedNodeClassName());
107       }
108
109     }
110
111   }
112
113   /**
114    * Generate visualization output.
115    *
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.
121    */
122
123   public D3VisualizationOutput generateVisualizationOutput(long preProcessingOpTimeInMs,
124       GraphMeta graphMeta) throws JsonProcessingException, IOException {
125
126     long opStartTimeInMs = System.currentTimeMillis();
127
128     /*
129      * iterate over the flat collection, and only add the graph nodes to the graph node collection
130      */
131
132     D3VisualizationOutput output = new D3VisualizationOutput();
133
134     output.setGraphMeta(graphMeta);
135
136     for (SparkyGraphNode n : flatNodeArray) {
137       if ( n.getItemType()!= null) {
138         output.pegCounter(n.getItemType());
139       }
140     }
141
142     output.addNodes(flatNodeArray);
143     output.addLinks(linkArrayOutput);
144
145     int numNodes = flatNodeArray.size();
146     int numLinks = linkArrayOutput.size();
147
148     LOG.info(AaiUiMsgs.VISUALIZATION_GRAPH_OUTPUT, String.valueOf(numNodes),
149         String.valueOf(numLinks));
150
151     if (numLinks < (numNodes - 1)) {
152       LOG.warn(AaiUiMsgs.DANGLING_NODE_WARNING, String.valueOf(numLinks),
153           String.valueOf(numNodes));
154     }
155
156     ObjectMapper mapper = new ObjectMapper();
157
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);
162
163     graphMeta.setNumLinks(linkArrayOutput.size());
164     graphMeta.setNumNodes(flatNodeArray.size());
165     graphMeta.setRenderTimeInMs(preProcessingOpTimeInMs);
166
167     output.setGraphMeta(graphMeta);
168
169     logOptime("generateVisualizationOutput()", opStartTimeInMs);
170
171     return output;
172   }
173
174   /**
175    * Convert visualization output to json.
176    *
177    * @param output the output
178    * @return the string
179    * @throws JsonProcessingException the json processing exception
180    */
181   public String convertVisualizationOutputToJson(D3VisualizationOutput output)
182       throws JsonProcessingException {
183
184     if (output == null) {
185       return null;
186     }
187
188     ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
189
190     return ow.writeValueAsString(output);
191
192   }
193
194   /**
195    * Builds the links from graph collection.
196    *
197    * @param nodeMap the node map
198    */
199   public void buildLinksFromGraphCollection(Map<String, ActiveInventoryNode> nodeMap) {
200
201     for (ActiveInventoryNode ain : nodeMap.values()) {
202
203       /*
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
207        * current node.
208        */
209
210       if (ain.getNodeDepth() < this.visualizationConfigs.getMaxSelfLinkTraversalDepth()) {
211
212         Collection<String> outboundNeighbors = ain.getOutboundNeighbors();
213
214         for (String outboundNeighbor : outboundNeighbors) {
215
216           SparkyGraphLink nodeLink = new SparkyGraphLink();
217
218           nodeLink.setId(UUID.randomUUID().toString());
219           nodeLink.setSource(ain.getNodeId());
220           nodeLink.setTarget(outboundNeighbor);
221
222           linkArrayOutput.add(nodeLink);
223
224         }
225
226         Collection<String> inboundNeighbors = ain.getInboundNeighbors();
227
228         for (String inboundNeighbor : inboundNeighbors) {
229
230           SparkyGraphLink nodeLink = new SparkyGraphLink();
231
232           nodeLink.setId(UUID.randomUUID().toString());
233           nodeLink.setSource(ain.getNodeId());
234           nodeLink.setTarget(inboundNeighbor);
235
236           linkArrayOutput.add(nodeLink);
237
238         }
239
240
241       } else {
242         if (LOG.isDebugEnabled()) {
243           LOG.debug(AaiUiMsgs.DEBUG_GENERIC, "buildLinks(),"
244               + " Filtering node = " + ain.getNodeId() + " @ depth = "
245               + ain.getNodeDepth());
246         }
247
248       }
249     }
250
251   }
252
253   /**
254    * Builds the flat node array from graph collection.
255    *
256    * @param nodeMap the node map
257    */
258   /*
259    * Recursive function to walk multi-graph nodes and children to build a folded resource target
260    * graph.
261    */
262   public void buildFlatNodeArrayFromGraphCollection(Map<String, ActiveInventoryNode> nodeMap) {
263
264     for (ActiveInventoryNode n : nodeMap.values()) {
265
266       if (n.getNodeDepth() <= this.visualizationConfigs.getMaxSelfLinkTraversalDepth()) {
267
268         SparkyGraphNode jsonNode = new SparkyGraphNode(n, this.visualizationConfigs, this.subConfig);
269
270         jsonNode.getNodeMeta().setClassName(this.visualizationConfigs.getGeneralNodeClassName());
271
272         if (this.visualizationConfigs.isVisualizationDebugEnabled()) {
273
274           NodeDebug nodeDebug = jsonNode.getNodeMeta().getNodeDebug();
275
276           if (nodeDebug != null) {
277             nodeDebug.setProcessingError(n.isProcessingErrorOccurred());
278             nodeDebug.setProcessingErrorCauses(n.getProcessingErrorCauses());
279           }
280         }
281         flatNodeArray.add(jsonNode);
282       } else {
283         if (LOG.isDebugEnabled()) {
284           LOG.debug(AaiUiMsgs.DEBUG_GENERIC, 
285               "Filtering node from visualization: " + n.getNodeId() + " @ depth = "
286               + n.getNodeDepth());
287         }
288       }
289     }
290   }
291
292 }