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