/*
 * Copyright 2017-2021 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 com.b2international.snowowl.core.domain.TransactionContext;
import com.b2international.snowowl.snomed.common.SnomedRf2Headers;
import com.b2international.snowowl.snomed.core.domain.SnomedConcept;
import com.b2international.snowowl.snomed.core.domain.SnomedConcepts;
import com.b2international.snowowl.snomed.core.domain.refset.SnomedRefSetType;
import com.b2international.snowowl.snomed.core.domain.refset.SnomedReferenceSet;
import com.b2international.snowowl.snomed.core.store.SnomedComponents;
import com.b2international.snowowl.snomed.datastore.index.entry.SnomedRefSetMemberIndexEntry;
import com.google.common.base.Strings;

/**
 * @since 5.0
 */
final class SnomedQueryMemberCreateDelegate extends SnomedRefSetMemberCreateDelegate {

	// "Synthetic" reference set member property that carries an entire SnomedConcept
	private static final String REFERENCED_COMPONENT = "referencedComponent";

	SnomedQueryMemberCreateDelegate(SnomedRefSetMemberCreateRequest request) {
		super(request);
	}

	@Override
	public String execute(SnomedReferenceSet refSet, TransactionContext context) {
		checkRefSetType(refSet, SnomedRefSetType.QUERY);
		checkNonEmptyProperty(SnomedRf2Headers.FIELD_QUERY);

		if (Strings.isNullOrEmpty(getReferencedComponentId())) {
			return createWithNewRefSet(refSet, context);
		} else {
			return createWithExistingRefSet(refSet, context);
		}
	}

	private String createWithNewRefSet(SnomedReferenceSet refSet, TransactionContext context) {
		checkNonEmptyProperty(REFERENCED_COMPONENT);
		checkComponentExists(refSet, context, SnomedRf2Headers.FIELD_MODULE_ID, getModuleId());

		// create new simple type reference set
		final SnomedConcept referencedComponent = getProperty(REFERENCED_COMPONENT, SnomedConcept.class);
		final String referencedComponentId = new IdRequest<>(referencedComponent.toCreateRequest()).execute(context);

		// write the generated ID back to the request  
		setReferencedComponentId(referencedComponentId);

		// add all matching members 
		final SnomedConcepts queryResults = SnomedRequests.prepareSearchConcept()
				.all()
				.filterByEcl(getProperty(SnomedRf2Headers.FIELD_QUERY))
				.build()
				.execute(context);

		for (SnomedConcept queryResult : queryResults) {
			SnomedComponents.newSimpleMember()
			.withActive(isActive())
			.withReferencedComponent(queryResult.getId())
			.withModuleId(getModuleId())
			.withRefSet(referencedComponentId)
			.addTo(context);
		}


		return createWithExistingRefSet(refSet, context);
	}

	private String createWithExistingRefSet(SnomedReferenceSet refSet, TransactionContext context) {
		checkReferencedComponent(refSet);

		checkComponentExists(refSet, context, SnomedRf2Headers.FIELD_MODULE_ID, getModuleId());
		checkComponentExists(refSet, context, SnomedRf2Headers.FIELD_REFERENCED_COMPONENT_ID, getReferencedComponentId());

		SnomedRefSetMemberIndexEntry member = SnomedComponents.newQueryMember()
				.withId(getId())
				.withActive(isActive())
				.withReferencedComponent(getReferencedComponentId())
				.withModuleId(getModuleId())
				.withRefSet(getReferenceSetId())
				.withQuery(getProperty(SnomedRf2Headers.FIELD_QUERY))
				.addTo(context);

		return member.getId();
	}

}

@@ -17,17 +17,17 @@
 2017-202
-1
+2
  B2i Hea
@@ -891,78 +891,8 @@
 pt;%0A
-import com.b2international.snowowl.snomed.core.domain.SnomedConcepts;%0A
 impo
@@ -1118,16 +1118,103 @@
 onents;%0A
+import com.b2international.snowowl.snomed.datastore.index.entry.SnomedConceptDocument;%0A
 import c
@@ -1851,63 +1851,8 @@
 RY);
-%0A%09%09checkNonEmptyProperty(SnomedRf2Headers.FIELD_QUERY);
 %0A%0A%09%09
@@ -2653,91 +2653,189 @@
  %0A%09%09
-final SnomedConcepts queryResults = SnomedRequests.prepareSearchConcept()%0A%09%09%09%09.all(
+if (!Strings.isNullOrEmpty(getProperty(SnomedRf2Headers.FIELD_QUERY))) %7B%0A%09%09%09SnomedRequests.prepareSearchConcept()%0A%09%09%09%09.setFields(SnomedConceptDocument.Fields.ID)%0A%09%09%09%09.setLimit(10000
 )%0A%09%09
@@ -2930,62 +2930,51 @@
 ext)
-;%0A%0A%09%09for (SnomedConcept queryResult : queryResults)
+%0A%09%09%09%09.stream()%0A%09%09%09%09.forEach(concept -%3E
  %7B%0A
+%09%09
 %09%09%09S
@@ -3007,16 +3007,18 @@
 ember()%0A
+%09%09
 %09%09%09.with
@@ -3035,24 +3035,26 @@
 ctive())%0A%09%09%09
+%09%09
 .withReferen
@@ -3070,18 +3070,14 @@
 ent(
-queryResul
+concep
 t.ge
@@ -3079,24 +3079,26 @@
 pt.getId())%0A
+%09%09
 %09%09%09.withModu
@@ -3120,16 +3120,18 @@
 d())%0A%09%09%09
+%09
+%09
 .withRef
@@ -3157,16 +3157,18 @@
 nentId)%0A
+%09%09
 %09%09%09.addT
@@ -3181,18 +3181,25 @@
 ext);%0A%09%09
+%09%09%7D);%0A%09%09
 %7D
-%0A
 %0A%0A%09%09retu

allow creating query type reference set member with...