Renaming openecomp to onap
[aai/data-router.git] / src / main / java / org / onap / aai / datarouter / entity / SuggestionSearchEntity.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.onap.aai.datarouter.entity;
24
25 import java.io.IOException;
26 import java.io.Serializable;
27 import java.security.NoSuchAlgorithmException;
28 import java.util.ArrayList;
29 import java.util.HashMap;
30 import java.util.List;
31 import java.util.Map;
32
33 import org.json.JSONArray;
34 import org.json.JSONObject;
35 import org.onap.aai.datarouter.search.filters.config.UiFilterConfig;
36 import org.onap.aai.datarouter.search.filters.config.UiFiltersConfig;
37 import org.onap.aai.datarouter.search.filters.config.UiFiltersSchemaUtility;
38 import org.onap.aai.datarouter.util.NodeUtils;
39 import org.onap.aai.datarouter.util.SearchSuggestionPermutation;
40
41 import com.fasterxml.jackson.databind.JsonNode;
42
43 public class SuggestionSearchEntity implements DocumentStoreDataEntity, Serializable {
44   private static final long serialVersionUID = -3636393943669310760L;
45
46   private static final String FILTER_ID = "filterId";
47   private static final String FILTER_VALUE = "filterValue";
48   private static final String FILTER_LIST = "filterList";
49
50   protected String id; // generated SHA-256 digest
51   private String entityType;
52   private List<String> entityTypeAliases;
53   private List<String> suggestionInputPermutations = new ArrayList<>();
54   private List<String> statusPermutations = new ArrayList<>();
55   private List<String> suggestableAttr = new ArrayList<>();
56   
57   private Map<String, String> inputOutputData = new HashMap<>();
58   private Map<String, UiFilterConfig> filters = new HashMap<>();
59   private JSONObject filterPayload = new JSONObject();
60   private StringBuilder searchSuggestionDisplayString = new StringBuilder();
61   private JSONArray payloadFilters = new JSONArray();
62   private UiFiltersSchemaUtility filtersSchemaUtility = new UiFiltersSchemaUtility();
63
64   public SuggestionSearchEntity() {
65     UiFiltersConfig filterConfigList = filtersSchemaUtility.loadUiFiltersConfig();
66
67     // Populate the map with keys that will match the suggestableAttr values
68     for (UiFilterConfig filter : filterConfigList.getFilters()) {
69       if (filter.getDataSource() != null) {
70         filters.put(filter.getDataSource().getFieldName(), filter);
71       }
72     }
73   }
74
75   /**
76    * Create the search suggestion string to display to the user in the search suggestion drop-down
77    * 
78    * @throws NoSuchAlgorithmException
79    */
80   public void generateSearchSuggestionDisplayStringAndId() throws NoSuchAlgorithmException {
81     int payloadEntryCounter = 1;
82
83     for (Map.Entry<String, String> outputValue : inputOutputData.entrySet()) {
84       if (outputValue.getValue() != null && outputValue.getValue().length() > 0) {
85         this.searchSuggestionDisplayString.append(outputValue.getValue());
86
87         if (payloadEntryCounter < inputOutputData.entrySet().size()) {
88           this.searchSuggestionDisplayString.append(" and ");
89         } else {
90           this.searchSuggestionDisplayString.append(" ");
91         }
92       }
93
94       payloadEntryCounter++;
95     }
96
97     this.searchSuggestionDisplayString.append(getEntityTypeAliases().get(0));
98     generateSearchSuggestionId(searchSuggestionDisplayString.toString());
99   }
100   
101   /**
102    * Generates an ID by encrypting the string to display to the user in the search suggestion
103    * drop-down
104    * 
105    * @param outputString The string to create the encrypted ID from
106    */
107   private void generateSearchSuggestionId(String searchSuggestionDisplayString) {
108     this.id = NodeUtils.generateUniqueShaDigest(searchSuggestionDisplayString);
109   }
110
111   /**
112    * Launch pad for performing permutations of the entity type, aliases, prov status and orchestration status.
113    * SHA-256 will result in an ID with a guaranteed uniqueness compared to just a java hashcode value
114    * 
115    * @return
116    */
117   public List<String> generateSuggestionInputPermutations() {
118     List<String> entityNames = new ArrayList<>();
119     entityNames.add(entityType);
120
121     if ((entityTypeAliases != null) && !(entityTypeAliases.isEmpty())) {
122       for (String alias : entityTypeAliases) {
123         entityNames.add(alias);
124       }
125     }
126
127     ArrayList<String> listOfSearchSuggestionPermutations = new ArrayList<>();
128     ArrayList<String> listToPermutate = 
129         new ArrayList<>(this.getInputOutputData().values());
130
131     for (String entityName : entityNames) {
132       listToPermutate.add(entityName);
133       List<List<String>> lists = SearchSuggestionPermutation.getListPermutations(listToPermutate);
134       for (List<String> li : lists){
135         listOfSearchSuggestionPermutations.add(String.join(" ", li));
136       }
137       listToPermutate.remove(entityName);
138     }
139
140     return listOfSearchSuggestionPermutations;
141   }
142
143   /**
144    * Return a custom JSON representation of this class
145    */
146   @Override
147   public String getAsJson() throws IOException {
148     if (entityType == null || suggestionInputPermutations == null) {
149       return null;
150     }
151
152     JSONObject rootNode = new JSONObject();
153     JSONArray inputArray = new JSONArray();
154     JSONObject payloadNode = new JSONObject();
155     StringBuilder outputString = new StringBuilder();
156
157     int payloadEntryCounter = 1;
158
159     // Add prov and orchestration status to search suggestion string
160     for (Map.Entry<String, String> payload : inputOutputData.entrySet()) {
161       payloadNode.put(payload.getKey(), payload.getValue());
162       outputString.append(payload.getValue());
163
164       if (payloadEntryCounter < inputOutputData.entrySet().size()) {
165         // Add the word "and" between prov and orchestration statuses, if both are present
166         outputString.append(" and ");
167         payloadEntryCounter++;
168       }
169     }
170
171     /* Add entity type to search suggestion string. We've decided to use the first entity type alias
172      * from the OXM */
173     outputString.append(" ").append(getEntityTypeAliases().get(0));
174
175     for (String permutation : suggestionInputPermutations) {
176       inputArray.put(permutation);
177     }
178
179     // Build up the search suggestion as JSON
180     JSONObject entitySuggest = new JSONObject();
181     entitySuggest.put("input", inputArray);
182     entitySuggest.put("output", outputString);
183     entitySuggest.put("payload", this.filterPayload);
184     rootNode.put("entity_suggest", entitySuggest);
185
186     return rootNode.toString();
187   }
188
189   public boolean isSuggestableDoc() {
190     return this.getFilterPayload().length() != 0;
191   }
192
193   /**
194    * Generate all permutations of Entity Type and (Prov Status and/or Orchestration Status)
195    * 
196    * @param list The list of unique elements to create permutations of
197    * @param permutation A list to hold the current permutation used during
198    * @param size To keep track of the original size of the number of unique elements
199    * @param listOfSearchSuggestionPermutationList The list to hold all of the different permutations
200    */
201   private void permutateList(List<String> list, List<String> permutation, int size,
202       List<String> listOfSearchSuggestionPermutationList) {
203     if (permutation.size() == size) {
204       StringBuilder newPermutation = new StringBuilder();
205
206       for (int i = 0; i < permutation.size(); i++) {
207         newPermutation.append(permutation.get(i)).append(" ");
208       }
209
210       listOfSearchSuggestionPermutationList.add(newPermutation.toString().trim());
211
212       return;
213     }
214
215     String[] availableItems = list.toArray(new String[0]);
216
217     for (String i : availableItems) {
218       permutation.add(i);
219       list.remove(i);
220       permutateList(list, permutation, size, listOfSearchSuggestionPermutationList);
221       list.add(i);
222       permutation.remove(i);
223     }
224   }
225
226   /**
227    * Populate a string that will represent the UI filters portion of the JSON payload that's stored in the
228    * search engine
229    * 
230    * @param entityFromUebEvent
231    * @param suggestibleAttrInPayload
232    */
233   public void setFilterBasedPayloadFromResponse(JsonNode entityFromUebEvent,
234       List<String> suggestibleAttrInOxm, List<String> suggestibleAttrInPayload) {
235     if (suggestibleAttrInOxm != null) {
236       for (String attribute : suggestibleAttrInOxm) {
237         UiFilterConfig filterConfig = filters.get(attribute);
238
239         if (suggestibleAttrInPayload.contains(attribute)) {
240           inputOutputData.put(attribute, entityFromUebEvent.get(attribute).asText());
241
242           if(filterConfig != null) {
243             JSONObject jsonFilterPayload = new JSONObject();
244             jsonFilterPayload.put(FILTER_ID, filterConfig.getFilterId());
245             jsonFilterPayload.put(FILTER_VALUE, entityFromUebEvent.get(attribute).asText());
246             this.payloadFilters.put(jsonFilterPayload);
247           } else {
248             this.filterPayload.put(attribute, entityFromUebEvent.get(attribute).asText()); 
249           }
250         } else {
251           if(filterConfig != null) {
252             JSONObject emptyValueFilterPayload = new JSONObject();
253             emptyValueFilterPayload.put(FILTER_ID, filterConfig.getFilterId());
254             this.payloadFilters.put(emptyValueFilterPayload);
255           }
256         }
257       }
258
259       this.filterPayload.put(FILTER_LIST, this.payloadFilters);
260     }
261   }
262
263   public void setPayloadFromResponse(JsonNode node) {
264     if (suggestableAttr != null) {
265       for (String attribute : suggestableAttr) {
266         if (node.get(attribute) != null) {
267           inputOutputData.put(attribute, node.get(attribute).asText());
268           this.filterPayload.put(attribute, node.get(attribute).asText());
269         }
270       }
271     }
272   }
273
274   public String getEntityType() {
275     return entityType;
276   }
277
278   public void setEntityType(String entityType) {
279     this.entityType = entityType;
280   }
281
282   public List<String> getEntityTypeAliases() {
283     return entityTypeAliases;
284   }
285
286   public void setEntityTypeAliases(List<String> entityTypeAliases) {
287     this.entityTypeAliases = entityTypeAliases;
288   }
289
290   @Override
291   public String getId() {
292     return id;
293   }
294
295   public StringBuilder getSearchSuggestionDisplayString() {
296     return searchSuggestionDisplayString;
297   }
298
299   public JSONObject getFilterPayload() {
300     return filterPayload;
301   }
302
303   public List<String> getStatusPermutations() {
304     return statusPermutations;
305   }
306
307   public List<String> getSuggestableAttr() {
308     return suggestableAttr;
309   }
310
311   public List<String> getSuggestionInputPermutations() {
312     return this.suggestionInputPermutations;
313   }
314
315   public void setId(String id) {
316     this.id = id;
317   }
318   
319   public void setInputOutputData(Map<String, String> inputOutputData) {
320     this.inputOutputData = inputOutputData;
321   }
322
323   public Map<String, String> getInputOutputData() {
324     return inputOutputData;
325   }
326
327   public void setSearchSuggestionDisplayString(StringBuilder searchSuggestionDisplayString) {
328     this.searchSuggestionDisplayString = searchSuggestionDisplayString;
329   }
330
331   public void setFilterPayload(JSONObject filterPayload) {
332     this.filterPayload = filterPayload;
333   }
334   
335   public void setFiltersSchemaUtility(UiFiltersSchemaUtility filtersSchemaUtility) {
336     this.filtersSchemaUtility = filtersSchemaUtility;
337   }
338
339   public void setStatusPermutations(List<String> statusPermutations) {
340     this.statusPermutations = statusPermutations;
341   }
342
343   public void setSuggestableAttr(List<String> attributes) {
344     for (String attribute : attributes) {
345       this.suggestableAttr.add(attribute);
346     }
347   }
348
349   public void setSuggestionInputPermutations(List<String> permutations) {
350     this.suggestionInputPermutations = permutations;
351   }
352
353   @Override
354   public String toString() {
355     return "SuggestionSearchEntity [id=" + id + ", entityType=" + entityType
356         + ", entityTypeAliases=" + entityTypeAliases + ", suggestionInputPermutations="
357         + suggestionInputPermutations + ", statusPermutations=" + statusPermutations
358         + ", suggestableAttr=" + suggestableAttr + ", inputOutputData=" + inputOutputData
359         + ", filters=" + filters + ", filterPayload=" + filterPayload
360         + ", searchSuggestionDisplayString=" + searchSuggestionDisplayString + ", payloadFilters="
361         + payloadFilters + "]";
362   }
363 }