<commit_before>/*
 * Copyright 2011-2017 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.id;

import static com.google.common.base.Preconditions.checkArgument;

import java.util.Collection;

import com.b2international.commons.VerhoeffCheck;
import com.b2international.snowowl.core.terminology.ComponentCategory;
import com.b2international.snowowl.snomed.datastore.internal.id.SnomedComponentIdentifierValidator;
import com.b2international.snowowl.snomed.datastore.internal.id.SnomedIdentifierImpl;
import com.google.common.base.Strings;

/**
 * Contains utility methods related to SCTID part checks.
 * 
 * @since 4.0
 */
public class SnomedIdentifiers {
	
	public static final String INT_NAMESPACE = "INT";
	
	public static final long MIN_INT_ITEMID = 100L;
	public static final long MIN_INT_METADATA_ITEMID = 9000_0000_0000_000L; // SNOMED CT Model Component IDs are placed at the end of the range
	public static final long MAX_INT_ITEMID = 9999_9999_9999_999L; // 8 + 7 = 15 digits for itemId
	
	public static final long MAX_NAMESPACE_ITEMID = 9999_9999L; // 8 digits for itemId, 7 digits for namespaceId
	public static final long MIN_NAMESPACE_ITEMID = 1L;

	/**
	 * Validates the given componentId by using the rules defined in the latest
	 * SNOMED CT Identifier specification, which are the following constraints:
	 * <ul>
	 * <li>Can't start with leading zeros</li>
	 * <li>Lengths should be between 6 and 18 characters</li>
	 * <li>Should parse to a long value</li>
	 * <li>Should pass the Verhoeff check-digit test</li>
	 * </ul>
	 * 
	 * @param componentId
	 * @see VerhoeffCheck
	 * @throws IllegalArgumentException
	 *             - if the given componentId is invalid according to the SNOMED
	 *             CT Identifier specification
	 */
	public static void validate(final String componentId) throws IllegalArgumentException {
		checkArgument(!Strings.isNullOrEmpty(componentId), "SCTID may not be null or empty");
		checkArgument(!componentId.startsWith("0"), "SCTID can't start with leading zero");
		checkArgument(componentId.length() >= 6 && componentId.length() <= 18, "SCTID length must be between 6-18 characters");
		
		try {
			Long.parseLong(componentId);
		} catch (final NumberFormatException e) {
			throw new IllegalArgumentException("SCTID should be parseable to a long value");
		}
		
		checkArgument(VerhoeffCheck.validateLastChecksumDigit(componentId), "ComponentId should pass Verhoeff check-digit test");
	}

	/**
	 * Validates the given collection of componentIds by using the rules defined
	 * in the latest SNOMED CT Identifier specification, which are the following
	 * constraints:
	 * <ul>
	 * <li>Can't start with leading zeros</li>
	 * <li>Lengths should be between 6 and 18 characters</li>
	 * <li>Should parse to a long value</li>
	 * <li>Should pass the Verhoeff check-digit test</li>
	 * </ul>
	 * 
	 * @param componentIds
	 * @see VerhoeffCheck
	 * @throws IllegalArgumentException
	 *             - if the given collection contains a component ID which is
	 *             invalid according to the SNOMED CT Identifier specification
	 */<commit_msg>SO-2191: Print expected check digit in SnomedIdentifiers#validate<commit_after>/*
 * Copyright 2011-2017 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.id;

import static com.google.common.base.Preconditions.checkArgument;

import java.util.Collection;

import com.b2international.commons.VerhoeffCheck;
import com.b2international.snowowl.core.terminology.ComponentCategory;
import com.b2international.snowowl.snomed.datastore.internal.id.SnomedComponentIdentifierValidator;
import com.b2international.snowowl.snomed.datastore.internal.id.SnomedIdentifierImpl;
import com.google.common.base.Strings;

/**
 * Contains utility methods related to SCTID part checks.
 * 
 * @since 4.0
 */
public class SnomedIdentifiers {
	
	public static final String INT_NAMESPACE = "INT";
	
	public static final long MIN_INT_ITEMID = 100L;
	public static final long MIN_INT_METADATA_ITEMID = 9000_0000_0000_000L; // SNOMED CT Model Component IDs are placed at the end of the range
	public static final long MAX_INT_ITEMID = 9999_9999_9999_999L; // 8 + 7 = 15 digits for itemId
	
	public static final long MAX_NAMESPACE_ITEMID = 9999_9999L; // 8 digits for itemId, 7 digits for namespaceId
	public static final long MIN_NAMESPACE_ITEMID = 1L;

	/**
	 * Validates the given componentId by using the rules defined in the latest
	 * SNOMED CT Identifier specification, which are the following constraints:
	 * <ul>
	 * <li>Can't start with leading zeros</li>
	 * <li>Lengths should be between 6 and 18 characters</li>
	 * <li>Should parse to a long value</li>
	 * <li>Should pass the Verhoeff check-digit test</li>
	 * </ul>
	 * 
	 * @param componentId
	 * @see VerhoeffCheck
	 * @throws IllegalArgumentException
	 *             - if the given componentId is invalid according to the SNOMED
	 *             CT Identifier specification
	 */
	public static void validate(final String componentId) throws IllegalArgumentException {
		checkArgument(!Strings.isNullOrEmpty(componentId), "SCTID may not be null or empty");
		checkArgument(!componentId.startsWith("0"), "SCTID can't start with leading zero");
		checkArgument(componentId.length() >= 6 && componentId.length() <= 18, "SCTID length must be between 6-18 characters");
		
		try {
			Long.parseLong(componentId);
		} catch (final NumberFormatException e) {
			throw new IllegalArgumentException("SCTID should be parseable to a long value");
		}
		
		final CharSequence idHead = componentId.subSequence(0, componentId.length() - 1);
		final char originalChecksum = componentId.charAt(componentId.length() - 1);
		final char checksum = VerhoeffCheck.calculateChecksum(idHead, false);

		checkArgument(VerhoeffCheck.validateLastChecksumDigit(componentId), "%s has incorrect Verhoeff check-digit; expected %s, was %s", componentId, checksum, originalChecksum);
	}

	/**
	 * Validates the given collection of componentIds by using the rules defined
	 * in the latest SNOMED CT Identifier specification, which are the following
	 * constraints:
	 * <ul>
	 * <li>Can't start with leading zeros</li>
	 * <li>Lengths should be between 6 and 18 characters</li>
	 * <li>Should parse to a long value</li>
	 * <li>Should pass the Verhoeff check-digit test</li>
	 * </ul>
	 * 
	 * @param componentIds
	 * @see VerhoeffCheck
	 * @throws IllegalArgumentException
	 *             - if the given collection contains a component ID which is
	 *             invalid according to the SNOMED CT Identifier specification
	 */
{'fraction_non_alphanumeric': 0.08388179119886437, 'fraction_numerical': 0.022067363530778164, 'mean_word_length': 4.149501661129568, 'pattern_counts': {'":': 0, '<': 45, '<?xml version=': 0, '>': 45, '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': '989618', 'n_tokens_mistral': 2420, 'n_tokens_neox': 2134, 'n_words': 782}