All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.mosip.authentication.common.service.builder.MatchInputBuilder Maven / Gradle / Ivy

package io.mosip.authentication.common.service.builder;
import static io.mosip.authentication.core.constant.IdAuthCommonConstants.ID_NAME;
import static io.mosip.authentication.core.constant.IdAuthCommonConstants.MAPPING_CONFIG;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import io.mosip.authentication.common.service.impl.match.IdaIdMapping;
import io.mosip.authentication.common.service.util.EnvUtil;
import io.mosip.authentication.core.constant.IdAuthCommonConstants;
import io.mosip.authentication.core.constant.IdAuthenticationErrorConstants;
import io.mosip.authentication.core.exception.IdAuthUncheckedException;
import io.mosip.authentication.core.indauth.dto.AuthRequestDTO;
import io.mosip.authentication.core.indauth.dto.IdentityInfoDTO;
import io.mosip.authentication.core.indauth.dto.RequestDTO;
import io.mosip.authentication.core.logger.IdaLogger;
import io.mosip.authentication.core.spi.indauth.match.AuthType;
import io.mosip.authentication.core.spi.indauth.match.IdInfoFetcher;
import io.mosip.authentication.core.spi.indauth.match.IdMapping;
import io.mosip.authentication.core.spi.indauth.match.MatchInput;
import io.mosip.authentication.core.spi.indauth.match.MatchType;
import io.mosip.authentication.core.spi.indauth.match.MatchType.Category;
import io.mosip.authentication.core.spi.indauth.match.MatchingStrategyType;
import io.mosip.kernel.core.logger.spi.Logger;

/**
 * Builder class to match Inputs.
 *
 * @author Dinesh Karuppiah.T
 */
@Component
public class MatchInputBuilder {

	/** The mosip logger. */
	private static Logger mosipLogger = IdaLogger.getLogger(MatchInputBuilder.class);

	/** The id info fetcher. */
	@Autowired
	private IdInfoFetcher idInfoFetcher;
	
	/** The environment. */
	@Autowired
	private EnvUtil environment;

	/** The Constant DEFAULT_MATCH_VALUE. */
	public static final String DEFAULT_MATCH_VALUE = "demo.threshold";

	/**
	 * Construct match input.
	 *
	 * @param authRequestDTO the auth request DTO
	 * @param authTypes      the auth types
	 * @param matchTypes     the match types
	 * @param demoEntity the demo entity
	 * @return the list
	 */
	public List buildMatchInput(AuthRequestDTO authRequestDTO, AuthType[] authTypes, MatchType[] matchTypes,
			Map> demoEntity) {
		List languages = idInfoFetcher.getSystemSupportedLanguageCodes();
		return Stream.of(matchTypes).flatMap(matchType -> {
			List matchInputs = new ArrayList<>();			
			if (matchType.isDynamic()) {
				if (authRequestDTO.getRequest().getDemographics() != null
						&& authRequestDTO.getRequest().getDemographics().getMetadata() != null) {
					for (Entry entry : authRequestDTO.getRequest().getDemographics().getMetadata()
							.entrySet()) {
						String propName = getMappedPropertyName(entry.getKey(), matchType, authRequestDTO, languages).orElseGet(entry::getKey);
						if (matchType.isMultiLanguage(propName, demoEntity, idInfoFetcher.getMappingConfig())) {
							validateDynamicAttributeLanguage(propName, matchType, authRequestDTO,
									languages);
							for (String language : languages) {
								addMatchInput(authRequestDTO, authTypes, matchType, matchInputs, language);
							}
						} else {
							addMatchInput(authRequestDTO, authTypes, matchType, matchInputs, null);
						}
					}
				}
			} else {
				if (matchType.isMultiLanguage()) {
					for (String language : languages) {
						addMatchInput(authRequestDTO, authTypes, matchType, matchInputs, language);
					}
				} else {
					addMatchInput(authRequestDTO, authTypes, matchType, matchInputs, null);
				}

			}
			return matchInputs.stream();
		})
				.filter(Objects::nonNull)
				.distinct()
				.collect(Collectors.toList());
	}
	
	/**
	 * Validates dynamic attribute language details.
	 *
	 * @param propName the prop name
	 * @param matchType the match type
	 * @param authRequestDTO the auth request DTO
	 * @param supportedLanguages the supported languages
	 */
	private void validateDynamicAttributeLanguage(String propName, MatchType matchType,
			AuthRequestDTO authRequestDTO, List supportedLanguages) {		
		Map> identityInfosMap = idInfoFetcher.getIdentityInfo(matchType, propName,
				authRequestDTO.getRequest());
		for (List identityInfos : identityInfosMap.values()) {
			checkIdentityInfoLanguage(identityInfos, propName, supportedLanguages);
		}		
	}
	
	/**
	 *  Checks for identityInfoDto object will have value for language or not 
	 *  for a given dynamic attribute.
	 *
	 * @param identityInfos the identity infos
	 * @param propertyName the property name
	 * @param supportedLanguages the supported languages
	 */
	private void checkIdentityInfoLanguage(List identityInfos, String propertyName, List supportedLanguages) {
		for (IdentityInfoDTO identityInfoDTO : identityInfos) {
			if (Objects.isNull(identityInfoDTO.getLanguage())) {
				mosipLogger.error(IdAuthCommonConstants.SESSION_ID, this.getClass().getSimpleName(),
						String.format(IdAuthenticationErrorConstants.MISSING_INPUT_PARAMETER.getErrorMessage(),
								propertyName + " language"), "language cannot be null");
				throw new IdAuthUncheckedException(
						IdAuthenticationErrorConstants.MISSING_INPUT_PARAMETER.getErrorCode(),
						String.format(IdAuthenticationErrorConstants.MISSING_INPUT_PARAMETER.getErrorMessage(),
								propertyName + ": language"));
			}
			if(identityInfoDTO.getLanguage().isEmpty() || identityInfoDTO.getLanguage().isBlank()) {
				mosipLogger.error(IdAuthCommonConstants.SESSION_ID, this.getClass().getSimpleName(),
						String.format(IdAuthenticationErrorConstants.INVALID_INPUT_PARAMETER.getErrorMessage(),
								propertyName + " language"), "language cannot be empty");
				throw new IdAuthUncheckedException(
						IdAuthenticationErrorConstants.INVALID_INPUT_PARAMETER.getErrorCode(),
						String.format(IdAuthenticationErrorConstants.INVALID_INPUT_PARAMETER.getErrorMessage(),
								propertyName + ": language"));				
			}
			if(!supportedLanguages.contains(identityInfoDTO.getLanguage())){
				mosipLogger.error(IdAuthCommonConstants.SESSION_ID, this.getClass().getSimpleName(),
						String.format(IdAuthenticationErrorConstants.MISSING_INPUT_PARAMETER.getErrorMessage(),
								propertyName + " language"), "language cannot be null");
				throw new IdAuthUncheckedException(
						IdAuthenticationErrorConstants.UNSUPPORTED_LANGUAGE.getErrorCode(),
						String.format(IdAuthenticationErrorConstants.UNSUPPORTED_LANGUAGE.getErrorMessage(),
								identityInfoDTO.getLanguage() + " for attribute " + propertyName));				
			}
		}
	}
	
	/**
	 * Gets mapped attribute name .
	 *
	 * @param inAttribute the in attribute
	 * @param matchType the match type
	 * @param authRequestDTO the auth request DTO
	 * @param languages the languages
	 * @return the mapped property name
	 */
	private Optional getMappedPropertyName(String inAttribute, MatchType matchType, AuthRequestDTO authRequestDTO, List languages) {
		return idInfoFetcher.getMappingConfig().getDynamicAttributes().keySet().stream()
				.filter(idName -> idName.equals(inAttribute))
				.filter(idName -> {
					if(languages != null && !languages.isEmpty()) {
						return languages.stream()
									.anyMatch(language -> idInfoFetcher
								.getIdentityRequestInfo(matchType, idName, authRequestDTO.getRequest(), language).size() > 0);
					} else {
						return idInfoFetcher
								.getIdentityRequestInfo(matchType, idName, authRequestDTO.getRequest(), null).size() > 0;
					}
				})
				.findFirst();
	}

	/**
	 * Add MatchInput.
	 *
	 * @param authRequestDTO the auth request DTO
	 * @param authTypes the auth types
	 * @param matchType the match type
	 * @param matchInputs the match inputs
	 * @param language the language
	 */
	private void addMatchInput(AuthRequestDTO authRequestDTO, AuthType[] authTypes, MatchType matchType,
			List matchInputs, String language) {
		Map infoFromAuthRequest = matchType.getReqestInfoFunction().apply(authRequestDTO);
		Optional authTypeOpt = AuthType.getAuthTypeForMatchType(matchType, authTypes);
		if (authTypeOpt.isPresent()) {
			matchInputs
					.addAll(buildMatchInput(authRequestDTO, matchType, infoFromAuthRequest, authTypeOpt.get(), language));
		}
	}

	/**
	 * Build Match Input.
	 *
	 * @param authRequestDTO the auth request DTO
	 * @param matchType the match type
	 * @param infoFromAuthRequest the info from auth request
	 * @param authType the auth type
	 * @param language the language
	 * @return the list
	 */
	private List buildMatchInput(AuthRequestDTO authRequestDTO, MatchType matchType,
			Map infoFromAuthRequest, AuthType authType, String language) {
		if (infoFromAuthRequest.isEmpty()) {
			// For Identity
			Optional identityOpt = Optional.ofNullable(authRequestDTO.getRequest());
			if (identityOpt.isPresent()) {
				RequestDTO identity = identityOpt.get();
				if (authType.isAuthTypeEnabled(authRequestDTO, idInfoFetcher)) {
					IdMapping idMapping = matchType.getIdMapping();
					if(idMapping.equals(IdaIdMapping.DYNAMIC)) {
						Map> mappedDynamicAttributes = idInfoFetcher.getMappingConfig().getDynamicAttributes();
						List matchInputsForDynamicAttributes = new ArrayList<>();
						//Construct the match inputs for the demo attributes which are mapped in mapping json
						List matchInpuptsForMappedDynamicAttribute = mappedDynamicAttributes
								.keySet()
								.stream()
								.filter(idName -> 
						idInfoFetcher.getIdentityRequestInfo(matchType, idName, identity, language).size() > 0)
								.map(idName -> contstructMatchInput(authRequestDTO, idName, matchType, authType, language))
									.collect(Collectors.toList());
						matchInputsForDynamicAttributes.addAll(matchInpuptsForMappedDynamicAttribute);
						
						//Construct the match inputs for the demo attributes which are not mapped in mapping json
						if(identity.getDemographics() != null && identity.getDemographics().getMetadata() != null && !identity.getDemographics().getMetadata().isEmpty()) {
							List matchInpuptsForUnmappedDynamicAttribute = getMatchInputsForUnmappedDynamicAttributes(
									identity.getDemographics().getMetadata(), mappedDynamicAttributes, 
									language,
									authRequestDTO,
									matchType,
									authType,
									identity);
							if(!matchInpuptsForUnmappedDynamicAttribute.isEmpty()) {
								matchInputsForDynamicAttributes.addAll(matchInpuptsForUnmappedDynamicAttribute);
							}
						}
						return matchInputsForDynamicAttributes;
					} else {
						if(idInfoFetcher.getIdentityRequestInfo(matchType, identity, language).size() > 0) {
							return List.of(contstructMatchInput(authRequestDTO, matchType.getIdMapping().getIdname(), matchType, authType, language));
						}
					}
				}
			}
		} else {
			// For non-identity
			if (authType.isAuthTypeEnabled(authRequestDTO, idInfoFetcher)
					&& authType.isAuthTypeInfoAvailable(authRequestDTO)) {
				return List.of(contstructMatchInput(authRequestDTO, matchType.getIdMapping().getIdname(), matchType , authType, null));
			}
		}
		return List.of();
	}

	/**
	 * Gets the match inputs for unmapped dynamic attributes.
	 *
	 * @param metadata the metadata
	 * @param mappedDynamicAttributes the mapped dynamic attributes
	 * @param language the language
	 * @param authRequestDTO the auth request DTO
	 * @param matchType the match type
	 * @param authType the auth type
	 * @param identity 
	 * @return the match inputs for unmapped dynamic attributes
	 */
	private List getMatchInputsForUnmappedDynamicAttributes(Map metadata,
			Map> mappedDynamicAttributes, String language, AuthRequestDTO authRequestDTO, MatchType matchType, AuthType authType, RequestDTO identity) {
		return metadata.keySet()
				.stream()
				.filter(demoAttrib -> !mappedDynamicAttributes.containsKey(demoAttrib))
				.filter(demoAttrib -> idInfoFetcher.getIdentityRequestInfo(matchType, demoAttrib, identity, language).size() > 0)
				.map(demoAttrib -> contstructMatchInput(authRequestDTO, demoAttrib, matchType, authType, language))
				.collect(Collectors.toList());
	}


	/**
	 * Construct match input.
	 *
	 * @param authRequestDTO the auth request DTO
	 * @param idName the id name
	 * @param matchType      TODO
	 * @param authType       TODO
	 * @param language       the language
	 * @return the list
	 */
	private MatchInput contstructMatchInput(AuthRequestDTO authRequestDTO, String idName, MatchType matchType, AuthType authType,
			String language) {

		if (matchType.getCategory() == Category.BIO && !authType.isAuthTypeInfoAvailable(authRequestDTO)) {
			return null;
		} else {
			Integer matchValue = IdAuthCommonConstants.DEFAULT_EXACT_MATCH_VALUE;
			String matchingStrategy = MatchingStrategyType.DEFAULT_MATCHING_STRATEGY.getType();

			Optional matchingStrategyOpt = authType.getMatchingStrategy(authRequestDTO, language);
			if (matchingStrategyOpt.isPresent()) {
				matchingStrategy = matchingStrategyOpt.get();
				if (matchingStrategyOpt.get().equals(MatchingStrategyType.PARTIAL.getType())
						|| matchingStrategyOpt.get().equals(MatchingStrategyType.PHONETICS.getType())) {
					Optional matchThresholdOpt = authType.getMatchingThreshold(authRequestDTO, language,
							environment.getEnvironment(), idInfoFetcher);
					matchValue = matchThresholdOpt.orElseGet(() -> EnvUtil.getDefaultMatchValue());
				}
			}
			Map matchProperties = new HashMap<>(authType.getMatchProperties(authRequestDTO, idInfoFetcher, language));
			matchProperties.put(ID_NAME, idName);
			matchProperties.put(MAPPING_CONFIG, idInfoFetcher.getMappingConfig());
			return new MatchInput(authType, idName, matchType, matchingStrategy, matchValue, matchProperties, language);
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy