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