/*
 * Copyright 2018 B2i Healthcare Pte Ltd, http://b2i.sg
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.b2international.snowowl.core.validation.whitelist;

import java.util.Collection;
import java.util.Collections;
import java.util.stream.Collectors;

import com.b2international.index.Hits;
import com.b2international.index.Searcher;
import com.b2international.index.query.Expression;
import com.b2international.index.query.Expressions;
import com.b2international.index.query.Expressions.ExpressionBuilder;
import com.b2international.snowowl.core.ServiceProvider;
import com.b2international.snowowl.core.internal.validation.ValidationRepository;
import com.b2international.snowowl.datastore.request.SearchIndexResourceRequest;

/**
 * @since 6.1
 */
final class ValidationWhiteListSearchRequest extends SearchIndexResourceRequest<ServiceProvider, ValidationWhiteLists, ValidationWhiteList>{

	enum OptionKey {

		/**
		 * Filter by rule id
		 */
		RULE_ID,
		
		/**
		 * Filter matches by component identifier.
		 */
		COMPONENT_ID,
		
		/**
		 * Filter matches by component type. 
		 */
		COMPONENT_TYPE,
		
		/**
		 * Filter matches by reporter and component identifier
		 */
		TERM, 
		
		/**
		 * Filter matches by reporter
		 */
		REPORTER
		
	}
	
	@Override
	protected Searcher searcher(ServiceProvider context) {
		return context.service(ValidationRepository.class).searcher();
	}
	
	@Override
	protected Expression prepareQuery(ServiceProvider context) {
		final ExpressionBuilder queryBuilder = Expressions.builder();
		
		addIdFilter(queryBuilder, ids -> Expressions.matchAny(ValidationWhiteList.Fields.ID, ids));
		
		if (containsKey(OptionKey.TERM)) {
			String searchTerm = getString(OptionKey.TERM);

			queryBuilder.should(Expressions.matchAny(ValidationWhiteList.Fields.COMPONENT_ID, Collections.singleton(searchTerm)));
			queryBuilder.should(Expressions.prefixMatch(ValidationWhiteList.Fields.REPORTER, searchTerm));
		}
		
		if (containsKey(OptionKey.RULE_ID)) {
			Collection<String> ruleIds = getCollection(OptionKey.RULE_ID, String.class);
			queryBuilder.filter(Expressions.matchAny(ValidationWhiteList.Fields.RULE_ID, ruleIds));
		}
		
		if (containsKey(OptionKey.COMPONENT_ID)) {
			Collection<String> componentIds = getCollection(OptionKey.COMPONENT_ID, String.class);
			queryBuilder.filter(Expressions.matchAny(ValidationWhiteList.Fields.COMPONENT_ID, componentIds));
		}
		
		if (containsKey(OptionKey.COMPONENT_TYPE)) {
			Collection<Integer> terminologyComponentIds = getCollection(OptionKey.COMPONENT_TYPE, Short.class).stream().map(Integer::valueOf).collect(Collectors.toSet());
			queryBuilder.filter(Expressions.matchAnyInt(ValidationWhiteList.Fields.TERMINOLOGY_COMPONENT_ID, terminologyComponentIds));
		}
		
		if (containsKey(OptionKey.REPORTER)) {
			Collection<String> reporters = getCollection(OptionKey.REPORTER, String.class);
			queryBuilder.filter(Expressions.matchAny(ValidationWhiteList.Fields.REPORTER, reporters));
		}
		
		return queryBuilder.build();
	}
	
	@Override
	protected Class<ValidationWhiteList> getDocumentType() {
		return ValidationWhiteList.class;
	}

	@Override
	protected ValidationWhiteLists toCollectionResource(ServiceProvider context, Hits<ValidationWhiteList> hits) {
		return new ValidationWhiteLists(hits.getHits(), hits.getScrollId(), hits.getSearchAfter(), hits.getLimit(), hits.getTotal());
	}

	@Override
	protected ValidationWhiteLists createEmptyResult(int limit) {
		return new ValidationWhiteLists(limit, 0);
	}

}
@@ -735,24 +735,47 @@
 ollections;%0A
+import java.util.List;%0A
 import java.
@@ -798,16 +798,16 @@
 ectors;%0A
-
 %0Aimport 
@@ -1273,16 +1273,103 @@
 Request;
+%0Aimport com.google.common.collect.ImmutableMap;%0Aimport com.google.common.collect.Lists;
 %0A%0A/**%0A *
@@ -2348,39 +2348,606 @@
 .TERM);%0A
-%0A%09%09%09queryBuilder.should
+%09%09%09%0A%09%09%09List%3CExpression%3E disjuncts = Lists.newArrayListWithExpectedSize(2);%0A%09%09%09disjuncts.add(Expressions.scriptScore(Expressions.matchTextPhrase(ValidationWhiteList.Fields.AFFECTED_COMPONENT_LABELS, searchTerm), %22normalizeWithOffset%22, ImmutableMap.of(%22offset%22, 1)));%0A%09%09%09disjuncts.add(Expressions.scriptScore(Expressions.matchTextAll(ValidationWhiteList.Fields.AFFECTED_COMPONENT_LABELS_PREFIX, searchTerm), %22normalizeWithOffset%22, ImmutableMap.of(%22offset%22, 0)));%0A%09%09%09%0A%09%09%09queryBuilder.must(%0A%09%09%09%09%09Expressions.builder()%0A%09%09%09%09%09%09.should(Expressions.dismax(disjuncts))%0A%09%09%09%09%09%09.should(Expressions.boost
 (Express
@@ -3035,34 +3035,32 @@
 chTerm))
-);%0A%09%09%09queryBuilder
+, 1000f))%0A%09%09%09%09%09%09
 .should(
@@ -3071,16 +3071,34 @@
 essions.
+boost(Expressions.
 prefixMa
@@ -3149,16 +3149,43 @@
 rchTerm)
+, 1000f))%0A%09%09%09%09%09.build()%0A%09%09%09
 );%0A%09%09%7D%0A%09

Enable filtering for component labels in white list view (#376)