Adding interfaces in documentation
[aai/sparky-be.git] / sparkybe-onap-service / src / main / java / org / onap / aai / sparky / search / filters / FilterQueryBuilder.java
1 /**
2  * ============LICENSE_START===================================================
3  * SPARKY (AAI UI 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 at
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.onap.aai.sparky.search.filters;
26
27 import java.util.ArrayList;
28 import java.util.List;
29
30 import javax.json.Json;
31 import javax.json.JsonArrayBuilder;
32 import javax.json.JsonObject;
33 import javax.json.JsonObjectBuilder;
34
35 import org.onap.aai.sparky.search.filters.config.FiltersConfig;
36 import org.onap.aai.sparky.search.filters.config.UiFilterConfig;
37 import org.onap.aai.sparky.search.filters.entity.AggregationEntity;
38 import org.onap.aai.sparky.search.filters.entity.BoolQueryBuilder;
39 import org.onap.aai.sparky.search.filters.entity.FilteredAggregationQueryBuilder;
40 import org.onap.aai.sparky.search.filters.entity.MatchFilterCriteriaEntity;
41 import org.onap.aai.sparky.search.filters.entity.SearchFilter;
42
43 /**
44  * Used to generate queries against Elasticsearch for filter related queries.
45  */
46 public class FilterQueryBuilder {
47   
48   private static final int EXISTING_FILTERS_LIMIT = 0;
49   private static final int SHOULD_BRANCH_LIMIT = 2;
50
51   public static JsonObject createFilteredBoolQueryObject(FiltersConfig filtersConfig, List<SearchFilter> searchFilters, int minShouldMatch, List<String> fields) {
52
53     if (searchFilters == null || searchFilters.size() == 0) {
54       return null;
55     }
56
57     int searchFilterValueSize = 0;
58
59     BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
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 = filtersConfig.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(FiltersConfig filtersConfig, 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     for (SearchFilter searchFilter : searchFilters) {
109
110       /*
111        * translate the filter-id into the filter-name from the oxm data model/config file
112        */
113       UiFilterConfig filter = filtersConfig.getFilterById(searchFilter.getFilterId());
114
115       if (filter == null || filter.getFilterName() == null) {
116         // log error and continue
117       } else {
118         String fieldName = filter.getDataSource().getFieldName();
119         aggQueryBuilder.addAggregationEntity(new AggregationEntity(fieldName, fieldName, 0));
120       }
121
122     }
123
124     return aggQueryBuilder.getJsonObject();
125   }
126
127   public static JsonObject createCombinedBoolAndAggQuery(FiltersConfig filtersConfig, List<SearchFilter> searchFilters, int minShouldMatch) {
128     JsonObjectBuilder wrappedQueryBuilder = Json.createObjectBuilder();
129     if(searchFilters != null) {
130       List<String> fields = new ArrayList<String>();
131       JsonObject boolQuery = createFilteredBoolQueryObject(filtersConfig,searchFilters, minShouldMatch, fields);
132       JsonObject aggQuery = createAggregationQueryArray(filtersConfig, searchFilters);
133
134       if (boolQuery != null) {
135         wrappedQueryBuilder.add("size", 0);
136         
137         JsonArrayBuilder filedsArrayBuilder = Json.createBuilderFactory(null).createArrayBuilder(); // TODO -> Should we use a class instance factory?
138         for(String field : fields) {
139           filedsArrayBuilder.add(field);
140         }
141         wrappedQueryBuilder.add("fields", filedsArrayBuilder.build());
142         
143         wrappedQueryBuilder.add("query", boolQuery);
144       }
145
146       if (aggQuery != null) {
147         wrappedQueryBuilder.add("aggs", aggQuery);
148       }
149     }
150     return wrappedQueryBuilder.build();
151   }
152
153   public static JsonObject createFilterValueQueryObject(String fieldValue) {
154     JsonObjectBuilder jsonBuilder = Json.createObjectBuilder();
155     jsonBuilder.add("size", "0"); // avoid source data
156     buildZeroTermSummaryQuery(jsonBuilder, fieldValue);
157
158     return jsonBuilder.build();
159   }
160
161   public static JsonObject createNestedFilterValueQueryObject(String fieldValue,
162       String pathToField) {
163     JsonObjectBuilder jsonBuilder = Json.createObjectBuilder();
164     jsonBuilder.add("size", "0"); // avoid source data
165     generateNestedAggregations(jsonBuilder, fieldValue, pathToField);
166
167     return jsonBuilder.build();
168   }
169
170   public static void buildZeroTermSummaryQuery(JsonObjectBuilder jsonBuilder, String fieldValue) {
171     JsonObjectBuilder aggsBlobBuilder = Json.createObjectBuilder();
172     getSummaryAggsBlob(aggsBlobBuilder, fieldValue, 0);
173     jsonBuilder.add("aggs", aggsBlobBuilder.build());
174   }
175
176   public static void getSummaryAggsBlob(JsonObjectBuilder aggsBlobBuilder, String fieldValue,
177       int resultSize) {
178     JsonObjectBuilder fieldBuilder =
179         Json.createObjectBuilder().add("field", fieldValue).add("size", resultSize);
180     JsonObject aggsFieldBlob = fieldBuilder.build();
181     JsonObjectBuilder defaultBlobBuilder = Json.createObjectBuilder().add("terms", aggsFieldBlob);
182     JsonObject defaultBlob = defaultBlobBuilder.build();
183     aggsBlobBuilder.add("default", defaultBlob);
184   }
185
186   public static void addNestedSummaryAggsBlob(JsonObjectBuilder nestedAggsBuilder,
187       String containerValue, String fieldValue, int resultSize) {
188     JsonObjectBuilder fieldBuilder = Json.createObjectBuilder()
189         .add("field", containerValue + "." + fieldValue).add("size", resultSize);
190     JsonObject aggsFieldObject = fieldBuilder.build();
191
192     JsonObjectBuilder termBuilder = Json.createObjectBuilder().add("terms", aggsFieldObject);
193     JsonObject termObject = termBuilder.build();
194
195     JsonObjectBuilder namedAggsBuilder = Json.createObjectBuilder().add(fieldValue, termObject);
196     JsonObject namedAggsObject = namedAggsBuilder.build();
197
198     nestedAggsBuilder.add("aggs", namedAggsObject);
199   }
200
201   public static void generateNestedAggregations(JsonObjectBuilder jsonBuilder, String fieldValue,
202       String pathToField) {
203     JsonObjectBuilder nestedAggsBuilder = Json.createObjectBuilder();
204
205     JsonObjectBuilder pathObjectBuilder = Json.createObjectBuilder().add("path", pathToField);
206     JsonObject nestedPathObject = pathObjectBuilder.build();
207
208     JsonObjectBuilder nestedObjectBuilder =
209         Json.createObjectBuilder().add("nested", nestedPathObject);
210
211     addNestedSummaryAggsBlob(nestedObjectBuilder, pathToField, fieldValue, 0);
212
213     JsonObject nestedObject = nestedObjectBuilder.build();
214     nestedAggsBuilder.add(pathToField, nestedObject);
215
216     jsonBuilder.add("aggs", nestedAggsBuilder.build());
217   }
218 }