Adding license header to newly added files
[aai/data-router.git] / src / main / java / org / onap / aai / datarouter / policy / SpikeAutosuggestIndexProcessor.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.policy;
22
23 import java.io.FileNotFoundException;
24 import java.io.IOException;
25 import java.security.NoSuchAlgorithmException;
26 import java.util.ArrayList;
27 import java.util.Collections;
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.Map;
31
32 import org.apache.camel.Exchange;
33 import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
34 import org.json.JSONException;
35 import org.json.JSONObject;
36 import org.onap.aai.datarouter.entity.OxmEntityDescriptor;
37 import org.onap.aai.datarouter.entity.SpikeEventVertex;
38 import org.onap.aai.datarouter.entity.SuggestionSearchEntity;
39 import org.onap.aai.datarouter.logging.EntityEventPolicyMsgs;
40 import org.onap.aai.datarouter.util.EntityOxmReferenceHelper;
41 import org.onap.aai.datarouter.util.SearchSuggestionPermutation;
42 import org.onap.aai.datarouter.util.Version;
43 import org.onap.aai.datarouter.util.VersionedOxmEntities;
44
45 import com.fasterxml.jackson.databind.JsonNode;
46
47
48 public class SpikeAutosuggestIndexProcessor extends AbstractSpikeEntityEventProcessor {
49
50   public static final String additionalInfo = "Response of SpikeEntityEventPolicy";
51
52   private final String EVENT_VERTEX = "vertex";
53
54   private String oxmVersion = null;
55
56   /** Agent for communicating with the Search Service. */
57
58   public SpikeAutosuggestIndexProcessor(SpikeEventPolicyConfig config)
59       throws FileNotFoundException {
60     super(config);
61     parseLatestOxmVersion();
62   }
63
64   @Override
65   protected void startup() {
66     // Create the indexes in the search service if they do not already exist.
67     searchAgent.createSearchIndex(searchIndexName, searchIndexSchema, createIndexUrl);
68     logger.info(EntityEventPolicyMsgs.ENTITY_EVENT_POLICY_REGISTERED);
69   }
70
71   @Override
72   public void process(Exchange exchange) throws Exception {
73    
74     long startTime = System.currentTimeMillis();
75     String uebPayload = getExchangeBody(exchange);
76     if (uebPayload == null) {
77       return;
78     }
79     JsonNode uebAsJson = null;
80     try {
81       uebAsJson = mapper.readTree(uebPayload);
82     } catch (IOException e) {
83       returnWithError(exchange, uebPayload, "Invalid Payload");
84       return;
85     }
86     
87     String action = getSpikeEventAction(exchange, uebPayload);
88     if (action == null) {
89       return;
90     }
91     JSONObject uebObjEntity = getUebContentAsJson(uebPayload, EVENT_VERTEX);
92     if (uebObjEntity == null) {
93       returnWithError(exchange, uebPayload, "Payload is missing " + EVENT_VERTEX);
94       return;
95     }
96     
97     SpikeEventVertex eventVertex = populateEventVertex(exchange, uebPayload);
98     if (eventVertex == null) {
99       return;
100     }
101     String entityType = getEntityType(exchange, eventVertex, uebPayload);
102     if (entityType == null) {
103       return;
104     }
105     String entityLink = getEntityLink(exchange, eventVertex, uebPayload);
106     if (entityLink == null) {
107       return;
108     }
109     DynamicJAXBContext oxmJaxbContext = readOxm(exchange, uebPayload);
110     if (oxmJaxbContext == null) {
111       return;
112     }
113     String oxmEntityType = getOxmEntityType(entityType);
114     List<String> searchableAttr =  getSearchableAttibutes(oxmJaxbContext, oxmEntityType, entityType, uebPayload,
115         exchange);
116     if (searchableAttr == null) {
117       return;
118     }    
119    
120     // log the fact that all data are in good shape
121     logger.info(EntityEventPolicyMsgs.PROCESS_ENTITY_EVENT_POLICY_NONVERBOSE, action, entityType);
122     logger.debug(EntityEventPolicyMsgs.PROCESS_ENTITY_EVENT_POLICY_VERBOSE, action, entityType,
123         uebPayload);
124     
125         
126     /*
127      * Use the versioned OXM Entity class to get access to cross-entity reference helper collections
128      */
129     VersionedOxmEntities oxmEntities =
130         EntityOxmReferenceHelper.getInstance().getVersionedOxmEntities(Version.valueOf(oxmVersion));
131     
132     /*
133      * Process for autosuggestable entities
134      */
135     if (oxmEntities != null) {
136       Map<String, OxmEntityDescriptor> rootDescriptor =
137           oxmEntities.getSuggestableEntityDescriptors();
138       if (!rootDescriptor.isEmpty()) {
139         List<String> suggestibleAttrInPayload = new ArrayList<>();
140         List<String> suggestibleAttrInOxm = extractSuggestableAttr(oxmEntities, entityType);
141         if (suggestibleAttrInOxm != null) {
142           for (String attr: suggestibleAttrInOxm){
143             if ( uebAsJson.get("vertex").get("properties").has(attr) ){
144               suggestibleAttrInPayload.add(attr);
145             }
146           }
147         }
148
149         if (suggestibleAttrInPayload.isEmpty()) {
150           return;
151         }
152         List<String> suggestionAliases = extractAliasForSuggestableEntity(oxmEntities, entityType);       
153
154         /*
155          * It was decided to silently ignore DELETE requests for resources we don't allow to be
156          * deleted. e.g. auto-suggestion deletion is not allowed while aggregation deletion is.
157          */
158         if (!ACTION_DELETE.equalsIgnoreCase(action)) {
159           List<ArrayList<String>> listOfValidPowerSetElements =
160               SearchSuggestionPermutation.getNonEmptyUniqueLists(suggestibleAttrInPayload);
161
162           // Now we have a list containing the power-set (minus empty element) for the status that are
163           // available in the payload. Try inserting a document for every combination.
164           for (ArrayList<String> list : listOfValidPowerSetElements) {
165             SuggestionSearchEntity suggestionSearchEntity = new SuggestionSearchEntity();
166             suggestionSearchEntity.setEntityType(entityType);
167             suggestionSearchEntity.setSuggestableAttr(list);
168             suggestionSearchEntity.setEntityTypeAliases(suggestionAliases);
169             suggestionSearchEntity.setFilterBasedPayloadFromResponse(uebAsJson.get("vertex").get("properties"),
170                 suggestibleAttrInOxm, list);
171             suggestionSearchEntity.setSuggestionInputPermutations(
172                 suggestionSearchEntity.generateSuggestionInputPermutations());
173
174             if (suggestionSearchEntity.isSuggestableDoc()) {
175               try {
176                 suggestionSearchEntity.generateSearchSuggestionDisplayStringAndId();
177               } catch (NoSuchAlgorithmException e) {
178                 logger.error(EntityEventPolicyMsgs.DISCARD_UPDATING_SEARCH_SUGGESTION_DATA,
179                     "Cannot create unique SHA digest for search suggestion data. Exception: "
180                         + e.getLocalizedMessage());
181               }
182
183               handleSearchServiceOperation(suggestionSearchEntity, action, searchIndexName);
184             }
185           }
186         }
187       }
188     }
189     long stopTime = System.currentTimeMillis();
190     metricsLogger.info(EntityEventPolicyMsgs.OPERATION_RESULT_NO_ERRORS, PROCESS_SPIKE_EVENT,
191         String.valueOf(stopTime - startTime));
192     setResponse(exchange, ResponseType.SUCCESS, additionalInfo);
193     return;
194   }
195
196   public List<String> extractSuggestableAttr(VersionedOxmEntities oxmEntities, String entityType) {
197     // Extract suggestable attributeshandleTopographicalData
198     Map<String, OxmEntityDescriptor> rootDescriptor = oxmEntities.getSuggestableEntityDescriptors();
199
200     if (rootDescriptor == null) {
201       return Collections.emptyList();
202     }
203
204     OxmEntityDescriptor desc = rootDescriptor.get(entityType);
205
206     if (desc == null) {
207       return Collections.emptyList();
208     }
209
210     return desc.getSuggestableAttributes();
211   }
212
213
214   public List<String> extractAliasForSuggestableEntity(VersionedOxmEntities oxmEntities,
215       String entityType) {
216
217     // Extract alias
218     Map<String, OxmEntityDescriptor> rootDescriptor = oxmEntities.getEntityAliasDescriptors();
219
220     if (rootDescriptor == null) {
221       return Collections.emptyList();
222     }
223
224     OxmEntityDescriptor desc = rootDescriptor.get(entityType);
225     return desc.getAlias();
226   }
227
228   private void parseLatestOxmVersion() {
229     int latestVersion = -1;
230     if (oxmVersionContextMap != null) {
231       Iterator it = oxmVersionContextMap.entrySet().iterator();
232       while (it.hasNext()) {
233         Map.Entry pair = (Map.Entry) it.next();
234
235         String version = pair.getKey().toString();
236         int versionNum = Integer.parseInt(version.substring(1, version.length()));
237
238         if (versionNum > latestVersion) {
239           latestVersion = versionNum;
240           oxmVersion = pair.getKey().toString();
241         }
242
243         logger.info(EntityEventPolicyMsgs.PROCESS_OXM_MODEL_FOUND, pair.getKey().toString());
244       }
245     } else {
246       logger.error(EntityEventPolicyMsgs.PROCESS_OXM_MODEL_MISSING, "");
247     }
248   }
249   
250   
251
252 }