114463e97718f164f669b0bd6312f21036fb1f14
[aai/sparky-be.git] / src / main / java / org / openecomp / sparky / inventory / servlet / EntityCountHistoryServlet.java
1 /**
2  * ============LICENSE_START=======================================================
3  * org.onap.aai
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
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  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22  */
23 package org.openecomp.sparky.inventory.servlet;
24
25 import org.openecomp.cl.mdc.MdcContext;
26 import com.fasterxml.jackson.core.JsonProcessingException;
27 import com.fasterxml.jackson.databind.JsonNode;
28 import com.fasterxml.jackson.databind.ObjectMapper;
29 import com.fasterxml.jackson.databind.SerializationFeature;
30
31 import java.io.IOException;
32 import java.io.PrintWriter;
33 import java.nio.ByteBuffer;
34 import java.security.SecureRandom;
35 import java.util.Arrays;
36 import java.util.HashMap;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Map.Entry;
40 import java.util.TreeMap;
41
42 import javax.servlet.ServletException;
43 import javax.servlet.http.HttpServlet;
44 import javax.servlet.http.HttpServletRequest;
45 import javax.servlet.http.HttpServletResponse;
46
47 import org.openecomp.cl.api.Logger;
48 import org.openecomp.cl.eelf.LoggerFactory;
49 import org.openecomp.sparky.logging.AaiUiMsgs;
50 import org.json.JSONArray;
51 import org.json.JSONObject;
52 import org.openecomp.sparky.dal.elasticsearch.SearchAdapter;
53 import org.openecomp.sparky.dal.elasticsearch.config.ElasticSearchConfig;
54 import org.openecomp.sparky.dal.rest.OperationResult;
55 import org.openecomp.sparky.dal.rest.RestClientBuilder;
56 import org.openecomp.sparky.inventory.EntityHistoryQueryBuilder;
57 import org.openecomp.sparky.util.NodeUtils;
58 import org.openecomp.sparky.util.ServletUtils;
59 import org.openecomp.sparky.viewandinspect.config.VisualizationConfig;
60
61 /**
62  * The Class EntityCountHistoryServlet.
63  */
64 public class EntityCountHistoryServlet extends HttpServlet {
65
66   private static final Logger LOG = LoggerFactory.getInstance().getLogger(EntityCountHistoryServlet.class);
67
68   private static final long serialVersionUID = 1L;
69
70   private SearchAdapter search = null;
71   private ElasticSearchConfig elasticConfig = null;
72   private VisualizationConfig visualConfig = null;
73   private ObjectMapper mapper;
74
75   private static final String SEARCH_STRING = "_search";
76   private static final String TABLE = "table";
77   private static final String GRAPH = "graph";
78
79   private List<String> vnfEntityTypesToSummarize;
80   private boolean summarizevnf = false;
81
82   /**
83    * Instantiates a new entity count history servlet.
84    *
85    * @throws ServletException the servlet exception
86    */
87   public EntityCountHistoryServlet() throws ServletException {
88     init();
89   }
90
91   /* (non-Javadoc)
92    * @see javax.servlet.GenericServlet#init()
93    */
94   @Override
95   public void init() throws ServletException {
96     super.init();
97     try {
98       if (elasticConfig == null) {
99         elasticConfig = ElasticSearchConfig.getConfig();
100       }
101       if (visualConfig == null) {
102         visualConfig = VisualizationConfig.getConfig();
103         vnfEntityTypesToSummarize =
104             Arrays.asList(visualConfig.getVnfEntityTypes().toLowerCase().split("[\\s,]+"));
105         summarizevnf = visualConfig.getEntityTypesToSummarize().toLowerCase().contains("vnf");
106       }
107       if (search == null) {
108         search = new SearchAdapter();
109       }
110       this.mapper = new ObjectMapper();
111       this.mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
112     } catch (Exception exc) {
113       new ServletException(
114           "Caught an exception while getting an instance of servlet configuration.", exc);
115     }
116   }
117
118   public void setSearch(SearchAdapter search) {
119     this.search = search;
120   }
121
122   public void setElasticConfig(ElasticSearchConfig elasticConfig) {
123     this.elasticConfig = elasticConfig;
124   }
125
126   /* (non-Javadoc)
127    * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
128    */
129   @Override
130   protected void doGet(HttpServletRequest request, HttpServletResponse response)
131       throws ServletException, IOException {
132           String txnID = request.getHeader("X-TransactionId");
133             if (txnID == null){
134               txnID = NodeUtils.getRandomTxnId();
135             }
136               
137           String partnerName = request.getHeader("X-FromAppId");
138           if ( partnerName == null)
139             partnerName = "Browser";
140               
141           MdcContext.initialize(txnID, "AAI-UI", "", partnerName,
142                     request.getRemoteAddr());
143
144         @SuppressWarnings("unused")
145         OperationResult operationResult = null;
146     if (request.getParameter("type") != null
147         && (request.getParameter("type").equalsIgnoreCase(TABLE)
148             || request.getParameter("type").equalsIgnoreCase(GRAPH))) {
149       try {
150           operationResult = getResults(response, request.getParameter("type"));
151       } catch (Exception exc) {
152         LOG.error(AaiUiMsgs.ERROR_SERVLET_PROCESSSING, exc);
153       }
154     } else {
155       ServletUtils.setServletResponse(LOG, true, 501, response,
156           ServletUtils.generateJsonErrorResponse("Unsupported request"));
157     }
158   }
159
160   /* (non-Javadoc)
161    * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
162    */
163   @Override
164   protected void doPost(HttpServletRequest request, HttpServletResponse response)
165       throws ServletException {
166
167   }
168
169   /**
170    * Gets the results.
171    *
172    * @param response the response
173    * @param type the type
174    * @return the results
175    * @throws Exception the exception
176    */
177   private OperationResult getResults(HttpServletResponse response, String type) throws Exception {
178     OperationResult operationResult = new OperationResult();
179
180     String requestString =
181         String.format("/%s/%s?pretty", elasticConfig.getEntityCountHistoryIndex(), SEARCH_STRING);
182
183     String reqPayload = EntityHistoryQueryBuilder.getQuery(type).toString();
184
185     try {
186       final String fullUrlStr = ServletUtils.getFullUrl(elasticConfig, requestString);
187       OperationResult opResult =
188           ServletUtils.executePostQuery(LOG, search, response, fullUrlStr, reqPayload);
189
190       JSONObject finalOutput = null;
191       if (type.equalsIgnoreCase(TABLE)) {
192         finalOutput = formatTableOutput(opResult.getResult());
193       } else if (type.equalsIgnoreCase(GRAPH)) {
194         finalOutput = formatLineGraphOutput(opResult.getResult());
195       }
196
197       if (finalOutput != null) {
198         response.setContentType("application/json");
199         PrintWriter out = response.getWriter();
200         out.println(finalOutput);
201         out.close();
202       }
203
204     } catch (JsonProcessingException exc) {
205       ServletUtils.handleSearchServletErrors(LOG, "Unable to map JSONpayload", exc, response);
206     }
207
208     return operationResult;
209   }
210
211   /**
212    * Format table output.
213    *
214    * @param results the results
215    * @return the JSON object
216    * @throws JsonProcessingException the json processing exception
217    */
218   private JSONObject formatTableOutput(String results) throws JsonProcessingException {
219     JsonNode resultNode = null;
220
221     JSONObject finalResult = new JSONObject();
222     JSONArray entitiesArr = new JSONArray();
223
224     Map<String, Long> entityCountInTable = initializeEntityMap();
225
226     long vnfCount = 0;
227
228     try {
229       resultNode = mapper.readTree(results);
230
231       final JsonNode bucketsNode = getBucketsNode(resultNode);
232       if (bucketsNode.isArray()) {
233
234         for (final JsonNode entityNode : bucketsNode) {
235           String entityType = entityNode.get("key").asText();
236           boolean isAVnf = vnfEntityTypesToSummarize.contains(entityType);
237           long countValue = 0;
238
239           if (isAVnf || entityCountInTable.get(entityType) != null) {
240             final JsonNode hitsBucketNode = entityNode.get("sort_by_date").get("hits").get("hits");
241             if (hitsBucketNode.isArray()) {
242               // the first bucket will be the latest
243               final JsonNode hitNode = hitsBucketNode.get(0);
244
245               countValue = hitNode.get("_source").get("count").asLong();
246
247               /*
248                * Special case: Add all the VNF types together to get aggregate count
249                */
250               if (summarizevnf && isAVnf) {
251                 vnfCount += countValue;
252                 countValue = vnfCount;
253                 entityType = "vnf";
254               }
255
256               entityCountInTable.replace(entityType, countValue);
257             }
258           }
259
260         }
261       }
262       for (Entry<String, Long> entry : entityCountInTable.entrySet()) {
263         JSONObject entityType = new JSONObject();
264         entityType.put("key", entry.getKey());
265         entityType.put("doc_count", entry.getValue());
266         entitiesArr.put(entityType);
267       }
268
269       finalResult.put("result", entitiesArr);
270
271     } catch (Exception exc) {
272       LOG.warn(AaiUiMsgs.ERROR_BUILDING_RESPONSE_FOR_TABLE_QUERY, exc.getLocalizedMessage());
273     }
274
275     return finalResult;
276   }
277
278
279   /**
280    * Format line graph output.
281    *
282    * @param results the results
283    * @return the JSON object
284    * @throws JsonProcessingException the json processing exception
285    */
286   private JSONObject formatLineGraphOutput(String results) throws JsonProcessingException {
287     Map<Long, Long> countByDateMap = new HashMap<Long, Long>();
288
289     JsonNode resultNode = null;
290
291     JSONObject finalResult = new JSONObject();
292     JSONArray finalResultArr = new JSONArray();
293
294     try {
295       resultNode = mapper.readTree(results);
296
297       final JsonNode bucketsNode = getBucketsNode(resultNode);
298
299       if (bucketsNode.isArray()) {
300
301         for (final JsonNode entityNode : bucketsNode) {
302           final JsonNode dateBucketNode = entityNode.get("group_by_date").get("buckets");
303           if (dateBucketNode.isArray()) {
304             for (final JsonNode dateBucket : dateBucketNode) {
305               Long date = dateBucket.get("key").asLong();
306               final JsonNode countBucketNode =
307                   dateBucket.get("sort_by_date").get("hits").get("hits");
308
309               if (countBucketNode.isArray()) {
310                 final JsonNode latestEntityNode = countBucketNode.get(0);
311
312                 long currentCount = latestEntityNode.get("_source").get("count").asLong();
313                 if (countByDateMap.containsKey(date)) {
314                   // add to the value if map already contains this date
315                   currentCount += countByDateMap.get(date);
316                 }
317
318                 countByDateMap.put(date, currentCount);
319               }
320             }
321
322           }
323         }
324       }
325       /*
326        * Sort the map by epoch timestamp
327        */
328       Map<Long, Long> sortedMap = new TreeMap<Long, Long>(countByDateMap);
329       for (Entry<Long, Long> entry : sortedMap.entrySet()) {
330         JSONObject dateEntry = new JSONObject();
331         dateEntry.put("date", entry.getKey());
332         dateEntry.put("count", entry.getValue());
333         finalResultArr.put(dateEntry);
334       }
335
336     } catch (Exception exc) {
337       LOG.warn(AaiUiMsgs.ERROR_BUILDING_SEARCH_RESPONSE, exc.getLocalizedMessage());
338     }
339
340     return finalResult.put("result", finalResultArr);
341   }
342
343   /**
344    * Gets the buckets node.
345    *
346    * @param node the node
347    * @return the buckets node
348    * @throws Exception the exception
349    */
350   private JsonNode getBucketsNode(JsonNode node) throws Exception {
351     if (node.get("aggregations").get("group_by_entityType").get("buckets") != null) {
352       return node.get("aggregations").get("group_by_entityType").get("buckets");
353     } else {
354       throw new Exception("Failed to map JSON response");
355     }
356   }
357
358   /**
359    * Initialize entity map.
360    *
361    * @return the map
362    */
363   private Map<String, Long> initializeEntityMap() {
364     Map<String, Long> entityMap = new HashMap<String, Long>();
365     String[] entityTypes = visualConfig.getEntityTypesToSummarize().split(",");
366     for (String entity : entityTypes) {
367       entityMap.put(entity, (long) 0);
368     }
369
370     return entityMap;
371   }
372
373 }