Initial search service commit
[aai/search-data-service.git] / src / main / java / org / openecomp / sa / rest / AnalysisConfiguration.java
1 /**
2  * ============LICENSE_START=======================================================
3  * Search Data Service
4  * ================================================================================
5  * Copyright © 2017 AT&T Intellectual Property.
6  * Copyright © 2017 Amdocs
7  * All rights reserved.
8  * ================================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License ati
12  *
13  *    http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * ============LICENSE_END=========================================================
21  *
22  * ECOMP and OpenECOMP are trademarks
23  * and service marks of AT&T Intellectual Property.
24  */
25 package org.openecomp.sa.rest;
26
27 import com.fasterxml.jackson.databind.ObjectMapper;
28 import org.openecomp.cl.api.Logger;
29 import org.openecomp.cl.eelf.LoggerFactory;
30 import org.openecomp.sa.rest.AnalyzerSchema;
31 import org.openecomp.sa.rest.FilterSchema;
32 import org.openecomp.sa.searchdbabstraction.logging.SearchDbMsgs;
33 import org.openecomp.sa.searchdbabstraction.util.SearchDbConstants;
34
35 import java.io.File;
36 import java.io.IOException;
37 import java.util.concurrent.atomic.AtomicBoolean;
38
39 /**
40  * This class encapsulates the configuration of the predefined
41  * Analyzer and Filter behaviours that help to tell the document
42  * store how to index the documents that are provided to it.
43  */
44 public class AnalysisConfiguration {
45
46   /**
47    * Contains all of the predefined indexing filters.
48    */
49   private FilterSchema[] customFilters;
50
51   /**
52    * Contains all of the predefined indexing analyzers.
53    */
54   private AnalyzerSchema[] customAnalysers;
55
56   /**
57    * Indicates whether or not we have imported the filter and
58    * analyzer configurations.
59    */
60   private AtomicBoolean configured = new AtomicBoolean(false);
61
62   /**
63    * A json format string which is readable by Elastic Search and defines
64    * all of the custom filters and analyzers that we need Elastic Search
65    * to know about.
66    */
67   private static String esSettings = null;
68
69   private static Logger logger = LoggerFactory.getInstance()
70       .getLogger(AnalysisConfiguration.class.getName());
71
72
73   /**
74    * Imports the filter and analyzer configuration files and
75    * builds an Elastic Search readable settings file from the
76    * contents.
77    *
78    * @param filterConfigFile   - Location of filter configuration json file
79    * @param analyzerConfigFile - Location of analyzer configuration json file
80    */
81   public void init(String filterConfigFile, String analyzerConfigFile) {
82
83     if (configured.compareAndSet(false, true)) {
84       ObjectMapper mapper = new ObjectMapper();
85
86       File filtersConfig = new File(filterConfigFile);
87       try {
88         customFilters = mapper.readValue(filtersConfig, FilterSchema[].class);
89       } catch (IOException e) {
90
91         // generate log
92         logger.warn(SearchDbMsgs.FILTERS_CONFIG_FAILURE, filterConfigFile, e.getMessage());
93       }
94
95       File analysersConfig = new File(analyzerConfigFile);
96       try {
97         customAnalysers = mapper.readValue(analysersConfig, AnalyzerSchema[].class);
98       } catch (IOException e) {
99
100         // generate log
101         logger.warn(SearchDbMsgs.ANALYSYS_CONFIG_FAILURE, analyzerConfigFile, e.getMessage());
102       }
103
104       esSettings = buildEsIndexSettings();
105     }
106   }
107
108
109   /**
110    * Returns the set of pre-configured filters.
111    *
112    * @return - An array of filters.
113    */
114   public FilterSchema[] getFilters() {
115     return customFilters;
116   }
117
118
119   /**
120    * Returns the set of pre-configured analyzers.
121    *
122    * @return - An array of analyzers.
123    */
124   public AnalyzerSchema[] getAnalyzers() {
125     init(SearchDbConstants.SDB_FILTER_CONFIG_FILE, SearchDbConstants.SDB_ANALYSIS_CONFIG_FILE);
126     return customAnalysers;
127   }
128
129
130   /**
131    * Imports the filter and analyzer configurations and translates those
132    * into a settings string that will be parseable by Elastic Search.
133    *
134    * @return - Elastic Search formatted settings string.
135    */
136   public String getEsIndexSettings() {
137
138     // Generate the es-settings string from our filter and analyzer
139     // configurations if we have not already done so.
140     init(SearchDbConstants.SDB_FILTER_CONFIG_FILE, SearchDbConstants.SDB_ANALYSIS_CONFIG_FILE);
141
142     // Now, return the es-settings string.
143     return esSettings;
144   }
145
146
147   /**
148    * Constructs a settings string that is readable by Elastic Search based
149    * on the contents of the filter and analyzer configuration files.
150    *
151    * @return Elastic Search formatted settings string.
152    */
153   public String buildEsIndexSettings() {
154
155     StringBuilder sb = new StringBuilder();
156
157     sb.append("{");
158     sb.append("\"analysis\": {");
159
160     // Define the custom filters.
161     boolean atLeastOneFilter = false;
162     sb.append("\"filter\": {");
163     AtomicBoolean firstFilter = new AtomicBoolean(true);
164     for (FilterSchema filter : customFilters) {
165
166       // Append a comma before the next entry, unless it is the
167       // first one.
168       if (!firstFilter.compareAndSet(true, false)) {
169         sb.append(", ");
170       }
171
172       // Now, build the filter entry.
173       buildFilterEntry(filter, sb);
174       atLeastOneFilter = true;
175     }
176     sb.append((atLeastOneFilter) ? "}," : "}");
177
178     // Define the custom analyzers.
179     sb.append("\"analyzer\": {");
180     AtomicBoolean firstAnalyzer = new AtomicBoolean(true);
181     for (AnalyzerSchema analyzer : customAnalysers) {
182
183       // Prepend a comma before the entry, unless it is the
184       // first one.
185       if (!firstAnalyzer.compareAndSet(true, false)) {
186         sb.append(",");
187       }
188
189       // Now, construct the entry for this analyzer.
190       buildAnalyzerEntry(analyzer, sb);
191     }
192     sb.append("}");
193
194     sb.append("}");
195     sb.append("}");
196
197     return sb.toString();
198   }
199
200
201   /**
202    * Constructs an ElasticSearch friendly custom filter definition.
203    *
204    * @param filter - The filter to generate ElasticSearch json for.
205    * @param sb     - The string builder to append the filter definition
206    *               to.
207    */
208   private void buildFilterEntry(FilterSchema filter, StringBuilder sb) {
209
210     sb.append("\"" + filter.getName()).append("\": {");
211
212     sb.append(filter.getConfiguration());
213
214     sb.append("}");
215   }
216
217
218   /**
219    * Constructs an ElasticSearch friendly custom analyzer definition.
220    *
221    * @param analyzer - The analyzer to generate ElasticSearch json for.
222    * @param sb       - The string builder to append the analyzer definition
223    *                 to.
224    */
225   private void buildAnalyzerEntry(AnalyzerSchema analyzer, StringBuilder sb) {
226
227     sb.append("\"").append(analyzer.getName()).append("\": {");
228     sb.append("\"type\": \"custom\",");
229     sb.append("\"tokenizer\": ").append("\"").append(analyzer.getTokenizer()).append("\",");
230     sb.append("\"filter\": [");
231     boolean firstFilter = true;
232     for (String filter : analyzer.getFilters()) {
233       if (!firstFilter) {
234         sb.append(",");
235       } else {
236         firstFilter = false;
237       }
238       sb.append("\"").append(filter).append("\"");
239     }
240     sb.append("]");
241     sb.append("}");
242   }
243 }