<commit_before>/*
 * 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.index.mapping;

import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.COMPONENT_REFERRING_PREDICATE;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.COMPONENT_RELEASED;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.CONCEPT_DEGREE_OF_INTEREST;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.CONCEPT_EFFECTIVE_TIME;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.CONCEPT_EXHAUSTIVE;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.CONCEPT_PRIMITIVE;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.DESCRIPTION_CASE_SIGNIFICANCE_ID;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.DESCRIPTION_EFFECTIVE_TIME;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_ACCEPTABILITY_ID;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_ACCEPTABILITY_LABEL;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_CHARACTERISTIC_TYPE_ID;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_CONTAINER_MODULE_ID;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_CORRELATION_ID;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_DATA_TYPE_VALUE;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_DESCRIPTION_FORMAT_ID;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_DESCRIPTION_FORMAT_LABEL;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_DESCRIPTION_LENGTH;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_EFFECTIVE_TIME;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_MAP_ADVICE;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_MAP_CATEGORY_ID;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_MAP_GROUP;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_MAP_PRIORITY;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_MAP_RULE;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_MAP_TARGET_COMPONENT_DESCRIPTION;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_MAP_TARGET_COMPONENT_DESCRIPTION_SORT_KEY;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_MAP_TARGET_COMPONENT_ID;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_MAP_TARGET_COMPONENT_LABEL;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_MAP_TARGET_COMPONENT_TYPE_ID;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_OPERATOR_ID;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_QUERY;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_SERIALIZED_VALUE;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_SOURCE_EFFECTIVE_TIME;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_TARGET_COMPONENT_ID;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_TARGET_EFFECTIVE_TIME;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_UOM_ID;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_UUID;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_VALUE_ID;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_REFERENCED_COMPONENT_TYPE;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_STRUCTURAL;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_TYPE;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.RELATIONSHIP_DESTINATION_NEGATED;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.RELATIONSHIP_EFFECTIVE_TIME;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.RELATIONSHIP_GROUP;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.RELATIONSHIP_INFERRED;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.RELATIONSHIP_OBJECT_ID;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.RELATIONSHIP_UNION_GROUP;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.RELATIONSHIP_UNIVERSAL;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.RELATIONSHIP_VALUE_ID;

import org.apache.lucene.document.Document;

import com.b2international.snowowl.core.ApplicationContext;
import com.b2international.snowowl.datastore.BranchPathUtils;
import com.b2international.snowowl.datastore.index.IndexUtils;
import com.b2international.snowowl.datastore.index.SortKeyMode;
import com.b2international.snowowl.datastore.index.mapping.DocumentBuilderBase;
import com.b2international.snowowl.datastore.index.mapping.DocumentBuilderFactory;
import com.b2international.snowowl.datastore.index.mapping.IndexField;
import com.b2international.snowowl.datastore.index.mapping.IntIndexField;
import com.b2international.snowowl.datastore.index.mapping.Mappings;
import com.b2international.snowowl.snomed.SnomedConstants.Concepts;
import com.b2international.snowowl.snomed.common.SnomedTerminologyComponentConstants;
import com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants;
import com.b2international.snowowl.snomed.datastore.index.update.ConceptDescriptionUpdater.DescriptionType;
import com.b2international.snowowl.snomed.datastore.services.ISnomedComponentService;
import com.b2international.snowowl.snomed.snomedrefset.SnomedRefSetType;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;

/**
 * @since 4.3
 */
public class SnomedDocumentBuilder extends DocumentBuilderBase<SnomedDocumentBuilder> {

	public static class Factory implements DocumentBuilderFactory<SnomedDocumentBuilder> {

		@Override
		public SnomedDocumentBuilder createBuilder() {
			return new SnomedDocumentBuilder();
		}

		@Override
		public SnomedDocumentBuilder createBuilder(Document doc) {
			final IntIndexField typeField = Mappings.type();
			final boolean refSetMember = doc.getField(typeField.fieldName()) == null;
			final Document newDoc = new Document();
			final SnomedDocumentBuilder newDocBuilder = new SnomedDocumentBuilder(newDoc);
			
			final Builder<IndexField<?>> fieldsToCopy = ImmutableSet.<IndexField<?>>builder();
			final IndexField<Long> storageKey = Mappings.storageKey();
			final IndexField<String> label = Mappings.label();
			fieldsToCopy.add(storageKey);
			
			// compute type specific fields
			if (refSetMember) {
				fieldsToCopy
					.add(label)
					.add(SnomedMappings.active())
					.add(SnomedMappings.memberRefSetType())
					.add(SnomedMappings.memberRefSetId())
					.add(SnomedMappings.memberReferencedComponentId())
					.add(SnomedMappings.memberReferencedComponentType())
					.add(Mappings.storedOnlyIntField(COMPONENT_RELEASED))
					.add(Mappings.stringField(REFERENCE_SET_MEMBER_UUID))
					.add(Mappings.longField(REFERENCE_SET_MEMBER_EFFECTIVE_TIME));
				final SnomedRefSetType refSetType = SnomedRefSetType.get(SnomedMappings.memberRefSetType().getValue(doc));
				switch (refSetType) {
				case SIMPLE: break;
				case ASSOCIATION:
					fieldsToCopy.add(Mappings.stringField(REFERENCE_SET_MEMBER_TARGET_COMPONENT_ID));
					break;
				case ATTRIBUTE_VALUE:
					fieldsToCopy.add(Mappings.stringField(REFERENCE_SET_MEMBER_VALUE_ID));
					break;
				case QUERY:
					fieldsToCopy.add(Mappings.stringField(REFERENCE_SET_MEMBER_QUERY));
					break;
				case EXTENDED_MAP:
				case COMPLEX_MAP:
					fieldsToCopy
						.add(Mappings.storedOnlyIntField(REFERENCE_SET_MEMBER_MAP_GROUP))
						.add(Mappings.storedOnlyIntField(REFERENCE_SET_MEMBER_MAP_PRIORITY))
						.add(Mappings.stringField(REFERENCE_SET_MEMBER_MAP_RULE))
						.add(Mappings.stringField(REFERENCE_SET_MEMBER_MAP_ADVICE))
						.add(Mappings.longField(REFERENCE_SET_MEMBER_MAP_CATEGORY_ID))
						.add(Mappings.longField(REFERENCE_SET_MEMBER_CORRELATION_ID))
						.add(Mappings.stringField(REFERENCE_SET_MEMBER_MAP_TARGET_COMPONENT_ID))
						.add(Mappings.intField(REFERENCE_SET_MEMBER_MAP_TARGET_COMPONENT_TYPE_ID))
						.add(Mappings.intField(REFERENCE_SET_MEMBER_MAP_TARGET_COMPONENT_LABEL));
					break;
				case DESCRIPTION_TYPE:
					fieldsToCopy
						.add(Mappings.longField(REFERENCE_SET_MEMBER_DESCRIPTION_FORMAT_ID))
						.add(Mappings.intField(REFERENCE_SET_MEMBER_DESCRIPTION_LENGTH))
						.add(Mappings.intField(REFERENCE_SET_MEMBER_DESCRIPTION_FORMAT_LABEL));
					break;
				case LANGUAGE:
					fieldsToCopy
						.add(Mappings.longField(REFERENCE_SET_MEMBER_ACCEPTABILITY_ID))
						.add(Mappings.stringField(REFERENCE_SET_MEMBER_ACCEPTABILITY_LABEL));
					break;
				case CONCRETE_DATA_TYPE:
					fieldsToCopy
						.add(Mappings.longField(REFERENCE_SET_MEMBER_OPERATOR_ID))
						.add(Mappings.stringDocValuesField(REFERENCE_SET_MEMBER_SERIALIZED_VALUE))
						.add(Mappings.longDocValuesField(REFERENCE_SET_MEMBER_UOM_ID))
						.add(Mappings.longField(REFERENCE_SET_MEMBER_CHARACTERISTIC_TYPE_ID))
						.add(Mappings.intDocValuesField(REFERENCE_SET_MEMBER_DATA_TYPE_VALUE))
						.add(Mappings.longDocValuesField(REFERENCE_SET_MEMBER_CONTAINER_MODULE_ID));
					SortKeyMode.INSTANCE.update(newDocBuilder, label.getValue(doc));
					break;
				case SIMPLE_MAP:
					fieldsToCopy
						.add(Mappings.stringField(REFERENCE_SET_MEMBER_MAP_TARGET_COMPONENT_ID))
						.add(Mappings.intField(REFERENCE_SET_MEMBER_MAP_TARGET_COMPONENT_TYPE_ID))
						.add(Mappings.stringField(REFERENCE_SET_MEMBER_MAP_TARGET_COMPONENT_LABEL))
						.add(Mappings.textField(REFERENCE_SET_MEMBER_MAP_TARGET_COMPONENT_DESCRIPTION));
					final String componentDescription = Mappings.textField(REFERENCE_SET_MEMBER_MAP_TARGET_COMPONENT_DESCRIPTION).getValue(doc);
					Mappings.searchOnlyStringField(REFERENCE_SET_MEMBER_MAP_TARGET_COMPONENT_DESCRIPTION_SORT_KEY).addTo(newDoc, IndexUtils.getSortKey(componentDescription));
					break;
				case MODULE_DEPENDENCY:
					fieldsToCopy
						.add(Mappings.longField(REFERENCE_SET_MEMBER_SOURCE_EFFECTIVE_TIME))
						.add(Mappings.longField(REFERENCE_SET_MEMBER_TARGET_EFFECTIVE_TIME));
					break;
				default: throw new IllegalArgumentException("Unknown refset type " + refSetType);
				}
			} else {
				fieldsToCopy
					.add(typeField)
					.add(SnomedMappings.id())
					.add(SnomedMappings.module());
				final short type = typeField.getShortValue(doc);
				switch (type) {
				case SnomedTerminologyComponentConstants.PREDICATE_TYPE_ID:
					// ignored<commit_msg>SO-1352: fixed NPE when upserting refset member documents<commit_after>/*
 * 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.index.mapping;

import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.COMPONENT_REFERRING_PREDICATE;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.COMPONENT_RELEASED;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.CONCEPT_DEGREE_OF_INTEREST;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.CONCEPT_EFFECTIVE_TIME;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.CONCEPT_EXHAUSTIVE;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.CONCEPT_PRIMITIVE;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.DESCRIPTION_CASE_SIGNIFICANCE_ID;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.DESCRIPTION_EFFECTIVE_TIME;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_ACCEPTABILITY_ID;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_ACCEPTABILITY_LABEL;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_CHARACTERISTIC_TYPE_ID;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_CONTAINER_MODULE_ID;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_CORRELATION_ID;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_DATA_TYPE_VALUE;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_DESCRIPTION_FORMAT_ID;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_DESCRIPTION_FORMAT_LABEL;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_DESCRIPTION_LENGTH;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_EFFECTIVE_TIME;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_MAP_ADVICE;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_MAP_CATEGORY_ID;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_MAP_GROUP;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_MAP_PRIORITY;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_MAP_RULE;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_MAP_TARGET_COMPONENT_DESCRIPTION;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_MAP_TARGET_COMPONENT_DESCRIPTION_SORT_KEY;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_MAP_TARGET_COMPONENT_ID;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_MAP_TARGET_COMPONENT_LABEL;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_MAP_TARGET_COMPONENT_TYPE_ID;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_OPERATOR_ID;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_QUERY;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_SERIALIZED_VALUE;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_SOURCE_EFFECTIVE_TIME;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_TARGET_COMPONENT_ID;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_TARGET_EFFECTIVE_TIME;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_UOM_ID;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_UUID;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_MEMBER_VALUE_ID;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_REFERENCED_COMPONENT_TYPE;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_STRUCTURAL;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.REFERENCE_SET_TYPE;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.RELATIONSHIP_DESTINATION_NEGATED;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.RELATIONSHIP_EFFECTIVE_TIME;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.RELATIONSHIP_GROUP;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.RELATIONSHIP_INFERRED;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.RELATIONSHIP_OBJECT_ID;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.RELATIONSHIP_UNION_GROUP;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.RELATIONSHIP_UNIVERSAL;
import static com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants.RELATIONSHIP_VALUE_ID;

import org.apache.lucene.document.Document;

import com.b2international.snowowl.core.ApplicationContext;
import com.b2international.snowowl.datastore.BranchPathUtils;
import com.b2international.snowowl.datastore.index.IndexUtils;
import com.b2international.snowowl.datastore.index.SortKeyMode;
import com.b2international.snowowl.datastore.index.mapping.DocumentBuilderBase;
import com.b2international.snowowl.datastore.index.mapping.DocumentBuilderFactory;
import com.b2international.snowowl.datastore.index.mapping.IndexField;
import com.b2international.snowowl.datastore.index.mapping.IntIndexField;
import com.b2international.snowowl.datastore.index.mapping.Mappings;
import com.b2international.snowowl.snomed.SnomedConstants.Concepts;
import com.b2international.snowowl.snomed.common.SnomedTerminologyComponentConstants;
import com.b2international.snowowl.snomed.datastore.browser.SnomedIndexBrowserConstants;
import com.b2international.snowowl.snomed.datastore.index.update.ConceptDescriptionUpdater.DescriptionType;
import com.b2international.snowowl.snomed.datastore.services.ISnomedComponentService;
import com.b2international.snowowl.snomed.snomedrefset.SnomedRefSetType;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;

/**
 * @since 4.3
 */
public class SnomedDocumentBuilder extends DocumentBuilderBase<SnomedDocumentBuilder> {

	public static class Factory implements DocumentBuilderFactory<SnomedDocumentBuilder> {

		@Override
		public SnomedDocumentBuilder createBuilder() {
			return new SnomedDocumentBuilder();
		}

		@Override
		public SnomedDocumentBuilder createBuilder(Document doc) {
			final IntIndexField typeField = Mappings.type();
			final boolean refSetMember = doc.getField(typeField.fieldName()) == null;
			final Document newDoc = new Document();
			final SnomedDocumentBuilder newDocBuilder = new SnomedDocumentBuilder(newDoc);
			
			final Builder<IndexField<?>> fieldsToCopy = ImmutableSet.<IndexField<?>>builder();
			final IndexField<Long> storageKey = Mappings.storageKey();
			final IndexField<String> label = Mappings.label();
			fieldsToCopy.add(storageKey);
			
			// compute type specific fields
			if (refSetMember) {
				fieldsToCopy
					.add(label)
					.add(SnomedMappings.active())
					.add(SnomedMappings.memberRefSetType())
					.add(SnomedMappings.memberRefSetId())
					.add(SnomedMappings.memberReferencedComponentId())
					.add(SnomedMappings.memberReferencedComponentType())
					.add(Mappings.storedOnlyIntField(COMPONENT_RELEASED))
					.add(Mappings.stringField(REFERENCE_SET_MEMBER_UUID))
					.add(Mappings.longField(REFERENCE_SET_MEMBER_EFFECTIVE_TIME));
				final SnomedRefSetType refSetType = SnomedRefSetType.get(SnomedMappings.memberRefSetType().getValue(doc));
				switch (refSetType) {
				case SIMPLE: break;
				case ASSOCIATION:
					fieldsToCopy.add(Mappings.stringField(REFERENCE_SET_MEMBER_TARGET_COMPONENT_ID));
					break;
				case ATTRIBUTE_VALUE:
					fieldsToCopy.add(Mappings.stringField(REFERENCE_SET_MEMBER_VALUE_ID));
					break;
				case QUERY:
					fieldsToCopy.add(Mappings.stringField(REFERENCE_SET_MEMBER_QUERY));
					break;
				case EXTENDED_MAP:
				case COMPLEX_MAP:
					fieldsToCopy
						.add(Mappings.storedOnlyIntField(REFERENCE_SET_MEMBER_MAP_GROUP))
						.add(Mappings.storedOnlyIntField(REFERENCE_SET_MEMBER_MAP_PRIORITY))
						.add(Mappings.stringField(REFERENCE_SET_MEMBER_MAP_RULE))
						.add(Mappings.stringField(REFERENCE_SET_MEMBER_MAP_ADVICE))
						.add(Mappings.longField(REFERENCE_SET_MEMBER_MAP_CATEGORY_ID))
						.add(Mappings.longField(REFERENCE_SET_MEMBER_CORRELATION_ID))
						.add(Mappings.stringField(REFERENCE_SET_MEMBER_MAP_TARGET_COMPONENT_ID))
						.add(Mappings.intField(REFERENCE_SET_MEMBER_MAP_TARGET_COMPONENT_TYPE_ID))
						.add(Mappings.intField(REFERENCE_SET_MEMBER_MAP_TARGET_COMPONENT_LABEL));
					break;
				case DESCRIPTION_TYPE:
					fieldsToCopy
						.add(Mappings.longField(REFERENCE_SET_MEMBER_DESCRIPTION_FORMAT_ID))
						.add(Mappings.intField(REFERENCE_SET_MEMBER_DESCRIPTION_LENGTH))
						.add(Mappings.intField(REFERENCE_SET_MEMBER_DESCRIPTION_FORMAT_LABEL));
					break;
				case LANGUAGE:
					fieldsToCopy
						.add(Mappings.longField(REFERENCE_SET_MEMBER_ACCEPTABILITY_ID))
						.add(Mappings.stringField(REFERENCE_SET_MEMBER_ACCEPTABILITY_LABEL));
					break;
				case CONCRETE_DATA_TYPE:
					fieldsToCopy
						.add(Mappings.longField(REFERENCE_SET_MEMBER_OPERATOR_ID))
						.add(Mappings.stringDocValuesField(REFERENCE_SET_MEMBER_SERIALIZED_VALUE))
						.add(Mappings.longDocValuesField(REFERENCE_SET_MEMBER_UOM_ID))
						.add(Mappings.longField(REFERENCE_SET_MEMBER_CHARACTERISTIC_TYPE_ID))
						.add(Mappings.intDocValuesField(REFERENCE_SET_MEMBER_DATA_TYPE_VALUE))
						.add(Mappings.longDocValuesField(REFERENCE_SET_MEMBER_CONTAINER_MODULE_ID));
					SortKeyMode.INSTANCE.update(newDocBuilder, label.getValue(doc));
					break;
				case SIMPLE_MAP:
					fieldsToCopy
						.add(Mappings.stringField(REFERENCE_SET_MEMBER_MAP_TARGET_COMPONENT_ID))
						.add(Mappings.intField(REFERENCE_SET_MEMBER_MAP_TARGET_COMPONENT_TYPE_ID))
						.add(Mappings.stringField(REFERENCE_SET_MEMBER_MAP_TARGET_COMPONENT_LABEL))
						.add(Mappings.textField(REFERENCE_SET_MEMBER_MAP_TARGET_COMPONENT_DESCRIPTION));
					for (String value : Mappings.textField(REFERENCE_SET_MEMBER_MAP_TARGET_COMPONENT_DESCRIPTION).getValues(doc)) {
						Mappings.searchOnlyStringField(REFERENCE_SET_MEMBER_MAP_TARGET_COMPONENT_DESCRIPTION_SORT_KEY).addTo(newDoc, IndexUtils.getSortKey(value));
					}
					break;
				case MODULE_DEPENDENCY:
					fieldsToCopy
						.add(Mappings.longField(REFERENCE_SET_MEMBER_SOURCE_EFFECTIVE_TIME))
						.add(Mappings.longField(REFERENCE_SET_MEMBER_TARGET_EFFECTIVE_TIME));
					break;
				default: throw new IllegalArgumentException("Unknown refset type " + refSetType);
				}
			} else {
				fieldsToCopy
					.add(typeField)
					.add(SnomedMappings.id())
					.add(SnomedMappings.module());
				final short type = typeField.getShortValue(doc);
				switch (type) {
				case SnomedTerminologyComponentConstants.PREDICATE_TYPE_ID:
					// ignored
{'fraction_non_alphanumeric': 0.07455706790358148, 'fraction_numerical': 0.0062352672800547486, 'mean_word_length': 7.504041383769803, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2377477', 'n_tokens_mistral': 9515, 'n_tokens_neox': 8533, 'n_words': 892}