/*
 * Copyright 2011-2015 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.snomed.datastore.request;


import static com.b2international.snowowl.snomed.datastore.index.entry.SnomedRelationshipIndexEntry.Expressions.characteristicTypeIds;
import static com.b2international.snowowl.snomed.datastore.index.entry.SnomedRelationshipIndexEntry.Expressions.destinationIds;
import static com.b2international.snowowl.snomed.datastore.index.entry.SnomedRelationshipIndexEntry.Expressions.group;
import static com.b2international.snowowl.snomed.datastore.index.entry.SnomedRelationshipIndexEntry.Expressions.modifierIds;
import static com.b2international.snowowl.snomed.datastore.index.entry.SnomedRelationshipIndexEntry.Expressions.sourceIds;
import static com.b2international.snowowl.snomed.datastore.index.entry.SnomedRelationshipIndexEntry.Expressions.typeIds;
import static com.b2international.snowowl.snomed.datastore.index.entry.SnomedRelationshipIndexEntry.Expressions.unionGroup;

import java.io.IOException;

import com.b2international.index.Hits;
import com.b2international.index.query.Expressions;
import com.b2international.index.query.Expressions.ExpressionBuilder;
import com.b2international.index.query.Query;
import com.b2international.index.revision.RevisionSearcher;
import com.b2international.snowowl.core.domain.BranchContext;
import com.b2international.snowowl.snomed.core.domain.SnomedRelationships;
import com.b2international.snowowl.snomed.datastore.converter.SnomedConverters;
import com.b2international.snowowl.snomed.datastore.index.entry.SnomedRelationshipIndexEntry;

/**
 * @since 4.5
 */
final class SnomedRelationshipSearchRequest extends SnomedComponentSearchRequest<SnomedRelationships> {

	enum OptionKey {
		SOURCE,
		TYPE,
		DESTINATION,
		CHARACTERISTIC_TYPE, 
		GROUP,
		UNION_GROUP,
		MODIFIER
	}
	
	SnomedRelationshipSearchRequest() {}

	@Override
	protected SnomedRelationships doExecute(BranchContext context) throws IOException {
		final RevisionSearcher searcher = context.service(RevisionSearcher.class);
		
		final ExpressionBuilder queryBuilder = Expressions.builder();
		addActiveClause(queryBuilder);
		addModuleClause(queryBuilder);
		addComponentIdFilter(queryBuilder);
		addEffectiveTimeClause(queryBuilder);
		addActiveMemberOfClause(queryBuilder);
		
		if (containsKey(OptionKey.TYPE)) {
			queryBuilder.must(typeIds(getCollection(OptionKey.TYPE, String.class)));
		}
		
		if (containsKey(OptionKey.CHARACTERISTIC_TYPE)) {
			queryBuilder.must(characteristicTypeIds(getCollection(OptionKey.CHARACTERISTIC_TYPE, String.class)));
		}

		if (containsKey(OptionKey.SOURCE)) {
			queryBuilder.must(sourceIds(getCollection(OptionKey.SOURCE, String.class)));
		}
		
		if (containsKey(OptionKey.DESTINATION)) {
			queryBuilder.must(destinationIds(getCollection(OptionKey.DESTINATION, String.class)));
		}
		
		if (containsKey(OptionKey.GROUP)) {
			queryBuilder.must(group(get(OptionKey.GROUP, Integer.class)));
		}
		
		if (containsKey(OptionKey.UNION_GROUP)) {
			queryBuilder.must(unionGroup(get(OptionKey.UNION_GROUP, Integer.class)));
		}
		
		if (containsKey(OptionKey.MODIFIER)) {
			queryBuilder.must(modifierIds(getCollection(OptionKey.UNION_GROUP, String.class)));
		}
		
		final Hits<SnomedRelationshipIndexEntry> hits = searcher.search(Query.select(SnomedRelationshipIndexEntry.class)
				.where(queryBuilder.build())
				.offset(offset())
				.limit(limit())
				.build());
		final int totalHits = hits.getTotal();
		
		if (limit() < 1 || totalHits < 1) {
			return new SnomedRelationships(offset(), limit(), totalHits);
		}
		
		return SnomedConverters.newRelationshipConverter(context, expand(), locales()).convert(hits.getHits(), offset(), limit(), totalHits);
	}

	@Override
	protected Class<SnomedRelationships> getReturnType() {
		return SnomedRelationships.class;
	}
}

@@ -801,645 +801,13 @@
 ons.
-characteristicTypeIds;%0Aimport static com.b2international.snowowl.snomed.datastore.index.entry.SnomedRelationshipIndexEntry.Expressions.destinationIds;%0Aimport static com.b2international.snowowl.snomed.datastore.index.entry.SnomedRelationshipIndexEntry.Expressions.group;%0Aimport static com.b2international.snowowl.snomed.datastore.index.entry.SnomedRelationshipIndexEntry.Expressions.modifierIds;%0Aimport static com.b2international.snowowl.snomed.datastore.index.entry.SnomedRelationshipIndexEntry.Expressions.sourceIds;%0Aimport static com.b2international.snowowl.snomed.datastore.index.entry.SnomedRelationshipIndexEntry.Expressions.typeIds
+group
 ;%0Aim
@@ -2249,554 +2249,590 @@
 ;%0A%09%09
-%0A%09%09if (containsKey(OptionKey.TYPE)) %7B%0A%09%09%09queryBuilder.must(typeIds(getCollection(OptionKey.TYPE, String.class)));%0A%09%09%7D%0A%09%09%0A%09%09if (containsKey(OptionKey.CHARACTERISTIC_TYPE)) %7B%0A%09%09%09queryBuilder.must(characteristicTypeIds(getCollection(OptionKey.CHARACTERISTIC_TYPE, String.class)));%0A%09%09%7D%0A%0A%09%09if (containsKey(OptionKey.SOURCE)) %7B%0A%09%09%09queryBuilder.must(sourceIds(getCollection(OptionKey.SOURCE, String.class)));%0A%09%09%7D%0A%09%09%0A%09%09if (containsKey(OptionKey.DESTINATION)) %7B%0A%09%09%09queryBuilder.must(destinationIds(getCollection(OptionKey.DESTINATION, String.class)));%0A%09%09%7D
+addEclFilter(context, queryBuilder, OptionKey.SOURCE, SnomedRelationshipIndexEntry.Expressions::sourceIds);%0A%09%09addEclFilter(context, queryBuilder, OptionKey.TYPE, SnomedRelationshipIndexEntry.Expressions::typeIds);%0A%09%09addEclFilter(context, queryBuilder, OptionKey.DESTINATION, SnomedRelationshipIndexEntry.Expressions::destinationIds);%0A%09%09addEclFilter(context, queryBuilder, OptionKey.CHARACTERISTIC_TYPE, SnomedRelationshipIndexEntry.Expressions::characteristicTypeIds);%0A%09%09addEclFilter(context, queryBuilder, OptionKey.MODIFIER, SnomedRelationshipIndexEntry.Expressions::modifierIds);
 %0A%09%09%0A
@@ -3074,143 +3074,8 @@
 %0A%09%09%0A
-%09%09if (containsKey(OptionKey.MODIFIER)) %7B%0A%09%09%09queryBuilder.must(modifierIds(getCollection(OptionKey.UNION_GROUP, String.class)));%0A%09%09%7D%0A%09%09%0A
 %09%09fi

support ECL expressions when filtering relationships by...