re base code
[sdc.git] / catalog-dao / src / main / java / org / openecomp / sdc / be / dao / impl / ESTimeBasedDao.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.openecomp.sdc.be.dao.impl;
22
23 import com.google.gson.Gson;
24 import com.google.gson.GsonBuilder;
25 import org.codehaus.jettison.json.JSONException;
26 import org.codehaus.jettison.json.JSONObject;
27 import org.elasticsearch.action.index.IndexResponse;
28 import org.elasticsearch.action.search.SearchRequestBuilder;
29 import org.elasticsearch.action.search.SearchResponse;
30 import org.elasticsearch.common.unit.TimeValue;
31 import org.elasticsearch.index.query.QueryBuilder;
32 import org.elasticsearch.search.sort.SortBuilder;
33 import org.openecomp.sdc.be.config.Configuration.ElasticSearchConfig.IndicesTimeFrequencyEntry;
34 import org.openecomp.sdc.be.config.ConfigurationManager;
35 import org.openecomp.sdc.be.dao.api.ActionStatus;
36 import org.openecomp.sdc.be.dao.es.ElasticSearchClient;
37 import org.openecomp.sdc.common.api.Constants;
38 import org.openecomp.sdc.common.datastructure.ESTimeBasedEvent;
39 import org.openecomp.sdc.common.log.wrappers.Logger;
40
41 import javax.annotation.Resource;
42 import java.util.ArrayList;
43 import java.util.HashMap;
44 import java.util.List;
45 import java.util.Map;
46
47 public abstract class ESTimeBasedDao {
48         private static final String SCORE_SCRIPT = "_score * ((doc.containsKey('alienScore') && !doc['alienScore'].empty) ? doc['alienScore'].value : 1)";
49         private static final int MAX_SEARCH_SIZE = 1000;
50         private static Logger log = Logger.getLogger(ESTimeBasedDao.class.getName());
51
52         private Gson gson;
53
54         private Map<String, String> indexPrefix2CreationPeriod;
55
56         private ConfigurationManager configurationManager;
57
58         protected ESTimeBasedDao() {
59                 gson = new GsonBuilder().setPrettyPrinting().create();
60                 configurationManager = ConfigurationManager.getConfigurationManager();
61                 setIndexPrefix2CreationPeriod();
62         }
63
64         public void setConfigurationManager(ConfigurationManager configurationManager) {
65                 this.configurationManager = configurationManager;
66         }
67
68         @Resource(name = "elasticsearch-client")
69         private ElasticSearchClient esClient;
70
71         protected final Map<String, Class<?>> typesToClasses = new HashMap<>();
72
73         public abstract String getIndexPrefix();
74
75         public ActionStatus write(String typeName, ESTimeBasedEvent data) {
76
77                 String indexPrefix = getIndexPrefix();
78                 String indexSuffix = getIndexSuffix(indexPrefix, data);
79                 StringBuilder sb = new StringBuilder();
80                 sb.append(indexPrefix);
81                 if (indexSuffix != null) {
82                         sb.append("-").append(indexSuffix);
83                 }
84
85                 ActionStatus res = ActionStatus.OK;
86                 JSONObject json = new JSONObject(data.getFields());
87                 try {
88                         IndexResponse actionGet = esClient.getClient().prepareIndex(sb.toString(), typeName)
89                                         .setSource(json.toString()).setRefresh(true).execute().actionGet(TimeValue.timeValueSeconds(15));
90
91                         if (actionGet.isCreated()) {
92                                 log.debug("Created record {}", data.toString());
93                                 // typesToClasses.put(typeName, data.getClass());
94                         } else {
95                                 log.error("Record {} couldn't be created", data.toString());
96                                 res = ActionStatus.GENERAL_ERROR;
97                         }
98                 } catch (Exception e) {
99                         log.error("Couldn't serialize object of type {}", typeName, e.getMessage());
100                         res = ActionStatus.GENERAL_ERROR;
101                 }
102                 return res;
103         }
104
105         public ActionStatus write(ESTimeBasedEvent data) {
106
107                 String indexPrefix = getIndexPrefix();
108                 String indexSuffix = getIndexSuffix(indexPrefix, data);
109                 StringBuilder sb = new StringBuilder();
110                 sb.append(indexPrefix);
111                 if (indexSuffix != null) {
112                         sb.append("-").append(indexSuffix);
113                 }
114
115                 String typeName = data.getClass().getSimpleName().toLowerCase();
116                 ActionStatus res = ActionStatus.OK;
117                 String json = gson.toJson(data);
118                 try {
119                         IndexResponse actionGet = esClient.getClient().prepareIndex(sb.toString(), typeName).setSource(json)
120                                         .setRefresh(true).execute().actionGet(TimeValue.timeValueSeconds(15));
121
122                         if (actionGet.isCreated()) {
123                                 log.debug("Created record {}", data.toString());
124                                 // typesToClasses.put(typeName, data.getClass());
125                         } else {
126                                 log.error("Record {} couldn't be created", data.toString());
127                                 res = ActionStatus.GENERAL_ERROR;
128                         }
129                 } catch (Exception e) {
130                         log.debug("Couldn't serialize object of type {}", typeName);
131                         res = ActionStatus.GENERAL_ERROR;
132                 }
133                 return res;
134         }
135
136         private void setIndexPrefix2CreationPeriod() {
137                 indexPrefix2CreationPeriod = new HashMap<>();
138                 List<IndicesTimeFrequencyEntry> indicesTimeFrequencyEntries = configurationManager.getConfiguration()
139                                 .getElasticSearch().getIndicesTimeFrequency();
140                 for (IndicesTimeFrequencyEntry entry : indicesTimeFrequencyEntries) {
141                         indexPrefix2CreationPeriod.put(entry.getIndexPrefix(), entry.getCreationPeriod());
142
143                 }
144         }
145
146         private String getIndexSuffix(String indexPrefix, ESTimeBasedEvent data) {
147                 String indexSuffix = indexPrefix2CreationPeriod.get(indexPrefix);
148                 String res = null;
149                 if (indexSuffix != null) {
150                         if (indexSuffix.equalsIgnoreCase(Constants.YEAR)) {
151                                 res = data.calculateYearIndexSuffix();
152                         } else if (indexSuffix.equalsIgnoreCase(Constants.MONTH)) {
153                                 res = data.calculateMonthIndexSuffix();
154                         } else if (indexSuffix.equalsIgnoreCase(Constants.DAY)) {
155                                 res = data.calculateDayIndexSuffix();
156                         } else if (indexSuffix.equalsIgnoreCase(Constants.HOUR)) {
157                                 res = data.calculateHourIndexSuffix();
158                         } else if (indexSuffix.equalsIgnoreCase(Constants.MINUTE)) {
159                                 res = data.calculateMinuteIndexSuffix();
160                         } else if (indexSuffix.equalsIgnoreCase(Constants.NONE)) {
161                                 // do nothing - no time-based behaviour. I wanted to ensure
162                                 // proper syntax, that's why this clause is needed.
163                         }
164                 } else {
165                         // Default behaviour - time-based with month period
166                         res = data.calculateMonthIndexSuffix();
167                 }
168                 return res;
169         }
170
171         public <T> long count(Class<T> clazz, QueryBuilder query) {
172                 String indexName = getIndexPrefix() + "*";
173                 String typeName = clazz.getSimpleName().toLowerCase();
174                 SearchRequestBuilder searchRequestBuilder = esClient.getClient().prepareSearch(indexName).setTypes(typeName)
175                                 .setSize(0);
176                 if (query != null) {
177                         searchRequestBuilder.setQuery(query);
178                 }
179
180                 SearchResponse response = searchRequestBuilder.execute().actionGet();
181                 return response.getHits().getTotalHits();
182         }
183
184         private <T> List<T> doCustomFind(Class<T> clazz, QueryBuilder query, SortBuilder sortBuilder, int size) {
185                 String indexName = getIndexPrefix() + "*";
186                 String typeName = clazz.getSimpleName().toLowerCase();
187                 SearchRequestBuilder searchRequestBuilder = esClient.getClient().prepareSearch(indexName).setTypes(typeName)
188                                 .setSize(size);
189                 if (query != null) {
190                         searchRequestBuilder.setQuery(query);
191                 }
192                 if (sortBuilder != null) {
193                         searchRequestBuilder.addSort(sortBuilder);
194                 }
195                 SearchResponse response = searchRequestBuilder.execute().actionGet();
196                 if (!somethingFound(response)) {
197                         return null;
198                 } else {
199                         List<T> hits = new ArrayList<>();
200                         for (int i = 0; i < response.getHits().getHits().length; i++) {
201                                 String hit = response.getHits().getAt(i).sourceAsString();
202
203                                 hits.add((T) gson.fromJson(hit, clazz));
204
205                         }
206                         return hits;
207                 }
208         }
209
210         private List<ESTimeBasedEvent> doCustomFindForEvent(String typeName, QueryBuilder query, SortBuilder sortBuilder,
211                         int size) {
212                 String indexName = getIndexPrefix() + "*";
213                 // String typeName = clazz.getSimpleName().toLowerCase();
214                 SearchRequestBuilder searchRequestBuilder = esClient.getClient().prepareSearch(indexName).setTypes(typeName)
215                                 .setSize(size);
216                 if (query != null) {
217                         searchRequestBuilder.setQuery(query);
218                 }
219                 if (sortBuilder != null) {
220                         searchRequestBuilder.addSort(sortBuilder);
221                 }
222                 SearchResponse response = searchRequestBuilder.execute().actionGet();
223                 if (!somethingFound(response)) {
224                         return null;
225                 } else {
226                         List<ESTimeBasedEvent> hits = new ArrayList<>();
227                         for (int i = 0; i < response.getHits().getHits().length; i++) {
228                                 String hit = response.getHits().getAt(i).sourceAsString();
229
230                                 ESTimeBasedEvent event;
231                                 try {
232                                         event = ESTimeBasedEvent.createEventFromJson(hit);
233                                         hits.add(event);
234                                 } catch (JSONException e) {
235                                         log.warn("failed to parse hit from audit index. error: {}", e.getMessage());
236                                         log.debug("failed to parse hit from audit. hit = {}", hit, e);
237                                 }
238                         }
239                         return hits;
240                 }
241         }
242
243         public List<ESTimeBasedEvent> customFindEvent(String typeName, QueryBuilder query, SortBuilder sortBuilder)
244                         throws JSONException {
245                 List<ESTimeBasedEvent> results = doCustomFindForEvent(typeName, query, sortBuilder, MAX_SEARCH_SIZE);
246                 if (results == null) {
247                         results = new ArrayList<>();
248                 }
249                 return results;
250         }
251
252         public <T> T customFind(Class<T> clazz, QueryBuilder query) {
253                 return customFind(clazz, query, null);
254         }
255
256         public <T> T customFind(Class<T> clazz, QueryBuilder query, SortBuilder sortBuilder) {
257                 List<T> results = doCustomFind(clazz, query, sortBuilder, 1);
258                 if (results == null || results.isEmpty()) {
259                         return null;
260                 } else {
261                         return results.iterator().next();
262                 }
263         }
264
265         public <T> List<T> customFindAll(Class<T> clazz, QueryBuilder query) {
266                 return customFindAll(clazz, query, null);
267         }
268
269         public <T> List<T> customFindAll(Class<T> clazz, QueryBuilder query, SortBuilder sortBuilder) {
270                 return doCustomFind(clazz, query, sortBuilder, Integer.MAX_VALUE);
271         }
272
273         private boolean somethingFound(final SearchResponse searchResponse) {
274                 if (searchResponse == null || searchResponse.getHits() == null || searchResponse.getHits().getHits() == null
275                                 || searchResponse.getHits().getHits().length == 0) {
276                         return false;
277                 }
278                 return true;
279         }
280
281         public String getEsHost() {
282                 String host = null;
283                 if (this.esClient != null) {
284                         host = this.esClient.getServerHost();
285                 } else {
286                         log.error("esClient is unavilable could not get host.");
287                 }
288                 return host;
289         }
290
291         public String getEsPort() {
292                 String port = null;
293                 if (this.esClient != null) {
294                         port = this.esClient.getServerPort();
295                 } else {
296                         log.error("esClient is unavilable could not get port.");
297                 }
298
299                 return port;
300         }
301
302 }