1 /*******************************************************************************
2 * ============LICENSE_START========================================================================
3 * ONAP : ccsdk feature sdnr wt
4 * =================================================================================================
5 * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
6 * =================================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
8 * in compliance with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software distributed under the License
13 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
14 * or implied. See the License for the specific language governing permissions and limitations under
16 * ============LICENSE_END==========================================================================
17 ******************************************************************************/
18 package org.onap.ccsdk.features.sdnr.wt.devicemanager.base.database;
20 import java.io.IOException;
21 import java.nio.charset.StandardCharsets;
22 import java.nio.file.Files;
23 import java.nio.file.Paths;
24 import java.util.HashSet;
25 import java.util.Iterator;
27 import javax.annotation.Nonnull;
28 import javax.annotation.Nullable;
29 import org.elasticsearch.ElasticsearchException;
30 import org.elasticsearch.action.admin.indices.alias.IndicesAliasesResponse;
31 import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
32 import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
33 import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
34 import org.elasticsearch.action.delete.DeleteResponse;
35 import org.elasticsearch.action.get.GetResponse;
36 import org.elasticsearch.action.index.IndexRequestBuilder;
37 import org.elasticsearch.action.index.IndexResponse;
38 import org.elasticsearch.action.search.SearchResponse;
39 import org.elasticsearch.client.Client;
40 import org.elasticsearch.common.bytes.BytesReference;
41 import org.elasticsearch.common.settings.Settings;
42 import org.elasticsearch.index.query.QueryBuilder;
43 import org.elasticsearch.index.query.QueryBuilders;
44 import org.elasticsearch.search.SearchHit;
45 import org.json.JSONObject;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
53 public class HtDatabaseClientAbstract implements HtDataBase, AutoCloseable {
55 private final Logger log = LoggerFactory.getLogger(HtDatabaseClientAbstract.class);
57 private final Client client;
58 private String esIndexAlias;
61 * Simple database initialization. Query all ES configuration information from cluster node.
63 * @param esIndex Database index
64 * @param database database node descriptor
66 public HtDatabaseClientAbstract(String esIndex, @Nonnull HtDatabaseNode database) {
68 this.esIndexAlias = esIndex;
69 this.client = database.getClient();
73 /*----------------------------------
74 * some constructing functions, used by public constructors
78 /*----------------------------------
83 public String getNetworkIndex() {
88 public void setNetworkIndex(String es_index) {
89 this.esIndexAlias = es_index;
93 public Client getClient() {
97 /*----------------------------------
105 public void close() {
110 * Verify if index already created
112 * @return boolean accordingly
114 public boolean isExistsIndex() {
116 if (esIndexAlias == null) {
117 throw new IllegalArgumentException("Missing Index");
120 log.debug("Check status of ES index: {}", esIndexAlias);
122 final IndicesExistsResponse indexStatus =
123 client.admin().indices().prepareExists(esIndexAlias).execute().actionGet();
125 return indexStatus.isExists();
131 * Create and write the mapping and setting of the index
133 * @param jsonIndexMappingSetting with mapping and setting definition Object or null for no
136 public void doCreateIndexWithMapping(JSONObject jsonIndexMappingSetting) {
138 if (esIndexAlias == null) {
139 throw new IllegalArgumentException("Missing Index");
143 // Create index with mapping and setting
144 String esIndexName = esIndexAlias + "_v1";
145 log.debug("Create not existing ES index: {} with alias:{}", esIndexName, esIndexAlias);
147 doCreateIndexWithMappingsAndSettings(esIndexName, jsonIndexMappingSetting);
150 log.debug("Set alias {} to index {}", esIndexAlias, esIndexName);
151 IndicesAliasesResponse setAliasResponse =
152 client.admin().indices().prepareAliases().addAlias(esIndexName, esIndexAlias).execute().actionGet();
153 log.debug("CreateIndex response {}", setAliasResponse);
155 } catch (ElasticsearchException e) {
156 log.warn("ElasticsearchException: {}", e.getDetailedMessage());
162 * Assign each mapping in the mappings section as separate mapping entry
164 * @param createIndexRequestBuilder builder for command to ES
165 * @param jsonIndexMappingSetting json with mapping information
167 private void doCreateIndexWithMappingsAndSettings(String esIndexName, JSONObject jsonIndexMappingSetting) {
169 CreateIndexRequestBuilder createIndexRequestBuilder = client.admin().indices().prepareCreate(esIndexName);
170 if (createIndexRequestBuilder == null) {
171 throw new HtDatabaseClientException("No client. Can not create index.", esIndexAlias);
174 if (jsonIndexMappingSetting != null) {
176 doAddMappings(createIndexRequestBuilder, jsonIndexMappingSetting);
177 doAddSetting(createIndexRequestBuilder, jsonIndexMappingSetting);
178 log.debug(" doCreateIndexWithMapping");
179 } catch (RuntimeException e) {
180 log.info("Exception during adding mappings or settings to CreateIndexRequestBuilder. ", e);
184 CreateIndexResponse createResponse = createIndexRequestBuilder.execute().actionGet();
185 log.debug("CreateIndex response {}", createResponse);
189 * Add one or more mappings to command
191 * @param createIndexRequestBuilder to add parameters
192 * @param jsonIndexMappingSetting contains mapping and setting information
194 private void doAddMappings(CreateIndexRequestBuilder createIndexRequestBuilder,
195 JSONObject jsonIndexMappingSetting) {
197 // If there are json information .. verify if they contain mappings
198 JSONObject jsonMapping = jsonIndexMappingSetting.optJSONObject("mappings");
200 // Handle optional mappings if requested
201 if (jsonMapping != null) {
202 log.debug("Set mapping for index {} {}", esIndexAlias, jsonMapping);
204 // For any reason the function below was not working without iterator
205 Set<String> keys = getStringKeySet(jsonMapping);
206 if (log.isDebugEnabled()) {
207 log.debug("Found length: {} keys: {}", jsonMapping.length(), keys.size());
210 for (String docType : keys) {
211 JSONObject jsonObject = jsonMapping.getJSONObject(docType);
212 if (jsonObject != null) {
213 String jsonObjectString = jsonObject.toString();
214 log.debug("Doctype:{} mapping:{}", docType, jsonObjectString);
215 createIndexRequestBuilder.addMapping(docType, jsonObjectString);
216 log.debug("Mapping created Doctype:{}", docType);
218 log.debug("No jsonObject for docType {}", docType);
222 log.debug("No mapping requested for index {}", esIndexAlias);
227 * Add one setting to command
229 * @param createIndexRequestBuilder to add parameters
230 * @param jsonIndexMappingSetting contains mapping and setting information
232 private void doAddSetting(CreateIndexRequestBuilder createIndexRequestBuilder, JSONObject jsonIndexMappingSetting) {
233 // Handle optional settings if requested
234 log.debug("Handle settings");
235 JSONObject jsonSettings = jsonIndexMappingSetting.optJSONObject("settings");
236 if (jsonSettings != null) {
237 log.debug("Set setting for index {} {}", esIndexAlias, jsonSettings);
238 createIndexRequestBuilder.setSettings(Settings.settingsBuilder().loadFromSource(jsonSettings.toString()));
240 log.debug("No settings requested for index {}", esIndexAlias);
245 * Create Index with alias according to definition, but no mapping
247 public void doCreateIndex() {
248 doCreateIndexWithMapping(null);
252 * Write one object into Database
254 * @param esId Database index
255 * @param dataTypeName Name of datatype
256 * @param json String in JSON format.
257 * @return esId of the object
260 public String doWriteJsonString(String dataTypeName, IsEsObject esId, String json) {
261 return doWriteByteArray(dataTypeName, esId, json.getBytes());
265 * Write one object into Database
267 * @param esId Database index
268 * @param dataTypeName Name of datatype
269 * @param json String in JSON format.
270 * @return esId of the object
274 public String doWriteByteArray(String dataTypeName, IsEsObject esId, byte[] json) {
275 return doWriteRaw(dataTypeName, esId.getEsId(), json);
279 * Write one object into Database
281 * @param dataTypeName Name of datatype
282 * @param id id of the object or null
283 * @param json Object as json
284 * @return esId of the Object
286 public String doWriteJsonObject(String dataTypeName, String id, JSONObject json) {
287 return doWriteRaw(dataTypeName, id, json.toString().getBytes());
291 * Write one object into Database
293 * @param esId Database index or null
294 * @param dataTypeName Name of datatype
295 * @param json String in JSON format.
296 * @return esId of the object
299 public String doWriteRaw(String dataTypeName, String esId, byte[] json) {
301 if (esIndexAlias == null) {
302 throw new IllegalArgumentException("Missing Index");
305 IndexRequestBuilder request = esId == null || esId.isEmpty() ? client.prepareIndex(esIndexAlias, dataTypeName)
306 : client.prepareIndex(esIndexAlias, dataTypeName, esId);
308 IndexResponse response = null;
310 response = request.setSource(json).execute().actionGet();
311 } catch (ElasticsearchException e) {
312 log.warn("ES Exception {} Json: {}", e.getMessage(), new String(json));
315 if (response == null) {
316 String jsonString = new String(json);
317 log.warn("Response null during write: {} {}", esId, jsonString);
320 return response.getId();
325 * Write JSON Data. First level contains datatype, next level id Example "datatype" : { "id" : { } }
328 public void doWriteJSONObject(JSONObject json) {
330 Set<String> docTypes = getStringKeySet(json);
331 log.debug("Found number of keys: {} keys: {}", json.length(), docTypes.size());
332 for (String docType : docTypes) {
333 JSONObject objects = json.optJSONObject(docType);
334 if (objects == null) {
335 log.debug("Skip json {} with class {}", docType, json.get(docType).getClass());
337 doWriteJsonObjectsWithIds(docType, objects);
343 * Write object and Id of object for a doctype
344 * @param docType of the objects
345 * @param objects a bunch of objects with ids as object name
347 private void doWriteJsonObjectsWithIds(String docType, JSONObject objects) {
348 Set<String> ids = getStringKeySet(objects);
349 log.debug("write doctype {} with elements {}", docType, ids.size());
350 for (String id : ids) {
351 JSONObject jsonIdObject = objects.optJSONObject(id);
352 if (jsonIdObject == null) {
353 log.debug("Skip jsonsub {} with class {}", id, objects.get(id).getClass());
355 if (log.isTraceEnabled()) {
356 log.trace("Jsonsub object of id {} '{}'", id, jsonIdObject);
358 this.doWriteRaw(docType, id, jsonIdObject.toString().getBytes());
364 * Remove Object from database
367 public boolean doRemove(String dataTypeName, IsEsObject esId) {
369 if (esIndexAlias == null) {
370 throw new IllegalArgumentException("Missing Index");
373 DeleteResponse response =
374 client.prepareDelete(esIndexAlias, dataTypeName, esId.getEsId()).execute().actionGet();
376 return response.isFound();
380 * Read Json Object from database
383 public @Nullable BytesReference doReadJsonData(String dataTypeName, IsEsObject esId) {
385 if (esId.getEsId() == null) {
386 throw new IllegalArgumentException("Read access to object without database Id");
389 return doReadJsonData(dataTypeName, esId.getEsId());
393 * Read Json Object from database
396 public @Nullable BytesReference doReadJsonData(String dataTypeName, String esId) {
398 log.debug("NetworkIndex read: {}", esIndexAlias);
400 GetResponse response = client.prepareGet(esIndexAlias, dataTypeName, esId)
401 // .setOperationThreaded(false)
402 .execute().actionGet();
404 return response.isExists() ? response.getSourceAsBytesRef() : null;
409 public SearchHit[] doReadByQueryJsonData(int start, int length, String dataTypeName, QueryBuilder qb) {
411 log.debug("NetworkIndex query and read: {}", esIndexAlias);
413 SearchResponse response1 = client.prepareSearch(esIndexAlias).setTypes(dataTypeName).setQuery(qb).setFrom(start)
414 .setSize(length).execute().actionGet();
416 return response1.getHits().hits();
421 public SearchHit[] doReadAllJsonData(int start, int length, String dataTypeName) {
423 QueryBuilder qb = QueryBuilders.matchAllQuery();
424 return doReadByQueryJsonData(start, length, dataTypeName, qb);
428 * Write Json datetype that is specified by file to ES
430 * @param dataType ES Datatype name
431 * @param fileName file name
433 public void writeJsonObjectsFromFile(String dataType, String fileName) {
435 log.debug("Start: Index: '{}' ' datatype: '{}' File: '{}'", esIndexAlias, dataType, fileName);
437 String content = null;
440 content = new String(Files.readAllBytes(Paths.get(fileName)), StandardCharsets.UTF_8);
441 } catch (IOException e1) {
442 log.warn("Can not read file: {}", e1.getMessage());
445 if (content != null && content.charAt(0) == 0xfeff) {
446 content = content.substring(1);
447 log.debug("Delete first char {} {}", dataType, fileName);
450 if (content != null) {
451 IndexResponse response = null;
453 response = client.prepareIndex(esIndexAlias, dataType).setSource(content).execute().actionGet();
454 } catch (ElasticsearchException e) {
455 log.error("ElasticsearchException during write: for {} from {} from {}", e.getMessage(), dataType, fileName);
456 } catch (Exception e) {
457 log.error("Exception during write: for {} from {} from {}", e.getMessage(), dataType, fileName);
460 if (response != null) {
461 if (!response.isCreated()) {
462 String responseAsString = response.toString();
463 log.warn("Jackson Response not created: {} {} {}", dataType, fileName, responseAsString);
465 log.debug("Created: {}", response.getId());
468 log.warn("Jackson Response null after write {} {}", dataType, fileName);
475 public void closeDb() {
476 if (client != null) {
482 // For any reason the function json.keySet() was not working in Oxygen => replaced by iterator
483 public static @Nonnull Set<String> getStringKeySet(JSONObject json) {
484 Set<String> keys = new HashSet<>();
485 Iterator<?> iterator = json.keys();
486 while (iterator.hasNext()) {
487 keys.add((String) iterator.next());
493 private static class HtDatabaseClientException extends RuntimeException {
495 private static final long serialVersionUID = 1L;
497 public HtDatabaseClientException(String string, String esIndexAlias) {
498 super(string + " Effected index: " + "esIndexAlias");