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