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