23f0dcedfdf70535ef5e0e4938a9b9b3f07c9576
[aai/sparky-be.git] / src / main / java / org / onap / aai / sparky / search / filters / FilterQueryBuilder.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.sparky.search.filters;
24
25 import java.util.ArrayList;
26 import java.util.List;
27
28 import javax.json.Json;
29 import javax.json.JsonArrayBuilder;
30 import javax.json.JsonObject;
31 import javax.json.JsonObjectBuilder;
32
33 import org.onap.aai.sparky.search.filters.config.FiltersConfig;
34 import org.onap.aai.sparky.search.filters.config.UiFilterConfig;
35 import org.onap.aai.sparky.search.filters.entity.AggregationEntity;
36 import org.onap.aai.sparky.search.filters.entity.BoolQueryBuilder;
37 import org.onap.aai.sparky.search.filters.entity.FilteredAggregationQueryBuilder;
38 import org.onap.aai.sparky.search.filters.entity.MatchFilterCriteriaEntity;
39 import org.onap.aai.sparky.search.filters.entity.SearchFilter;
40
41 /**
42  * Used to generate queries against Elasticsearch for filter related queries.
43  */
44 public class FilterQueryBuilder {
45   
46   private static final int EXISTING_FILTERS_LIMIT = 0;
47   private static final int SHOULD_BRANCH_LIMIT = 2;
48
49   public static JsonObject createFilteredBoolQueryObject(List<SearchFilter> searchFilters, int minShouldMatch, List<String> fields) {
50
51     if (searchFilters == null || searchFilters.size() == 0) {
52       return null;
53     }
54
55     int searchFilterValueSize = 0;
56
57     BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
58
59     FiltersConfig filters = FiltersConfig.getInstance();
60
61     for (SearchFilter searchFilter : searchFilters) {
62
63       searchFilterValueSize = searchFilter.getValues().size();
64
65       /*
66        * translate the filter-id into the filter-name from the oxm data model/config file
67        */
68       UiFilterConfig filter = filters.getFilterById(searchFilter.getFilterId());
69
70       if (filter == null || filter.getFilterName() == null) {
71         // log error and continue
72       } else {
73         
74         String fieldName = filter.getDataSource().getFieldName();
75         if(!fields.contains(fieldName)) {
76           fields.add(fieldName);
77         }
78         
79         if (searchFilterValueSize >= SHOULD_BRANCH_LIMIT) {
80           // Add should branches
81           for (String filterValue : searchFilter.getValues()) {
82             boolQueryBuilder.addShouldFilter(new MatchFilterCriteriaEntity(fieldName, filterValue)); 
83           }
84
85         } else if (searchFilterValueSize > EXISTING_FILTERS_LIMIT) {
86           // Add must branch
87           for (String filterValue : searchFilter.getValues()) {
88             boolQueryBuilder.addMustFilter(new MatchFilterCriteriaEntity(fieldName, filterValue));
89           }
90         }
91       }
92     }
93
94     boolQueryBuilder.setMinShouldMatch(minShouldMatch);
95     
96     return boolQueryBuilder.getJsonObject();
97   }
98
99   public static JsonObject createAggregationQueryArray(List<SearchFilter> searchFilters) {
100
101     if (searchFilters == null || searchFilters.size() == 0) {
102       // log error
103       return null;
104     }
105
106     FilteredAggregationQueryBuilder aggQueryBuilder = new FilteredAggregationQueryBuilder();
107
108     FiltersConfig filters = FiltersConfig.getInstance();
109
110     for (SearchFilter searchFilter : searchFilters) {
111
112       /*
113        * translate the filter-id into the filter-name from the oxm data model/config file
114        */
115       UiFilterConfig filter = filters.getFilterById(searchFilter.getFilterId());
116
117       if (filter == null || filter.getFilterName() == null) {
118         // log error and continue
119       } else {
120         String fieldName = filter.getDataSource().getFieldName();
121         aggQueryBuilder.addAggregationEntity(new AggregationEntity(fieldName, fieldName, 0));
122       }
123
124     }
125
126     return aggQueryBuilder.getJsonObject();
127   }
128
129   public static JsonObject createCombinedBoolAndAggQuery(List<SearchFilter> searchFilters, int minShouldMatch) {
130     JsonObjectBuilder wrappedQueryBuilder = Json.createObjectBuilder();
131     if(searchFilters != null) {
132       List<String> fields = new ArrayList<String>();
133       JsonObject boolQuery = createFilteredBoolQueryObject(searchFilters, minShouldMatch, fields);
134       JsonObject aggQuery = createAggregationQueryArray(searchFilters);
135
136       if (boolQuery != null) {
137         wrappedQueryBuilder.add("size", 0);
138         
139         JsonArrayBuilder filedsArrayBuilder = Json.createBuilderFactory(null).createArrayBuilder(); // TODO -> Should we use a class instance factory?
140         for(String field : fields) {
141           filedsArrayBuilder.add(field);
142         }
143         wrappedQueryBuilder.add("fields", filedsArrayBuilder.build());
144         
145         wrappedQueryBuilder.add("query", boolQuery);
146       }
147
148       if (aggQuery != null) {
149         wrappedQueryBuilder.add("aggs", aggQuery);
150       }
151     }
152     return wrappedQueryBuilder.build();
153   }
154
155   public static JsonObject createFilterValueQueryObject(String fieldValue) {
156     JsonObjectBuilder jsonBuilder = Json.createObjectBuilder();
157     jsonBuilder.add("size", "0"); // avoid source data
158     buildZeroTermSummaryQuery(jsonBuilder, fieldValue);
159
160     return jsonBuilder.build();
161   }
162
163   public static JsonObject createNestedFilterValueQueryObject(String fieldValue,
164       String pathToField) {
165     JsonObjectBuilder jsonBuilder = Json.createObjectBuilder();
166     jsonBuilder.add("size", "0"); // avoid source data
167     generateNestedAggregations(jsonBuilder, fieldValue, pathToField);
168
169     return jsonBuilder.build();
170   }
171
172   public static void buildZeroTermSummaryQuery(JsonObjectBuilder jsonBuilder, String fieldValue) {
173     JsonObjectBuilder aggsBlobBuilder = Json.createObjectBuilder();
174     getSummaryAggsBlob(aggsBlobBuilder, fieldValue, 0);
175     jsonBuilder.add("aggs", aggsBlobBuilder.build());
176   }
177
178   public static void getSummaryAggsBlob(JsonObjectBuilder aggsBlobBuilder, String fieldValue,
179       int resultSize) {
180     JsonObjectBuilder fieldBuilder =
181         Json.createObjectBuilder().add("field", fieldValue).add("size", resultSize);
182     JsonObject aggsFieldBlob = fieldBuilder.build();
183     JsonObjectBuilder defaultBlobBuilder = Json.createObjectBuilder().add("terms", aggsFieldBlob);
184     JsonObject defaultBlob = defaultBlobBuilder.build();
185     aggsBlobBuilder.add("default", defaultBlob);
186   }
187
188   public static void addNestedSummaryAggsBlob(JsonObjectBuilder nestedAggsBuilder,
189       String containerValue, String fieldValue, int resultSize) {
190     JsonObjectBuilder fieldBuilder = Json.createObjectBuilder()
191         .add("field", containerValue + "." + fieldValue).add("size", resultSize);
192     JsonObject aggsFieldObject = fieldBuilder.build();
193
194     JsonObjectBuilder termBuilder = Json.createObjectBuilder().add("terms", aggsFieldObject);
195     JsonObject termObject = termBuilder.build();
196
197     JsonObjectBuilder namedAggsBuilder = Json.createObjectBuilder().add(fieldValue, termObject);
198     JsonObject namedAggsObject = namedAggsBuilder.build();
199
200     nestedAggsBuilder.add("aggs", namedAggsObject);
201   }
202
203   public static void generateNestedAggregations(JsonObjectBuilder jsonBuilder, String fieldValue,
204       String pathToField) {
205     JsonObjectBuilder nestedAggsBuilder = Json.createObjectBuilder();
206
207     JsonObjectBuilder pathObjectBuilder = Json.createObjectBuilder().add("path", pathToField);
208     JsonObject nestedPathObject = pathObjectBuilder.build();
209
210     JsonObjectBuilder nestedObjectBuilder =
211         Json.createObjectBuilder().add("nested", nestedPathObject);
212
213     addNestedSummaryAggsBlob(nestedObjectBuilder, pathToField, fieldValue, 0);
214
215     JsonObject nestedObject = nestedObjectBuilder.build();
216     nestedAggsBuilder.add(pathToField, nestedObject);
217
218     jsonBuilder.add("aggs", nestedAggsBuilder.build());
219   }
220 }