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

com.brihaspathee.zeus.validator.impl.AccountValidatorImpl Maven / Gradle / Ivy

package com.brihaspathee.zeus.validator.impl;

import com.brihaspathee.zeus.domain.entity.PayloadTracker;
import com.brihaspathee.zeus.domain.entity.RuleSetImplementation;
import com.brihaspathee.zeus.dto.account.AccountDto;
import com.brihaspathee.zeus.dto.rules.RuleCategoryDto;
import com.brihaspathee.zeus.dto.rules.RuleSetDto;
import com.brihaspathee.zeus.dto.rules.RuleTypeDto;
import com.brihaspathee.zeus.exception.RuleSetImplNotFound;
import com.brihaspathee.zeus.helper.interfaces.RuleExecutionHelper;
import com.brihaspathee.zeus.helper.interfaces.RuleSetImplementationHelper;
import com.brihaspathee.zeus.service.interfaces.RuleService;
import com.brihaspathee.zeus.util.ZeusRandomStringGenerator;
import com.brihaspathee.zeus.validator.AccountValidationResult;
import com.brihaspathee.zeus.validator.MemberValidationResult;
import com.brihaspathee.zeus.validator.ValidationResponse;
import com.brihaspathee.zeus.validator.rules.RuleResult;
import com.brihaspathee.zeus.validator.rulesets.interfaces.AccountRuleSet;
import com.brihaspathee.zeus.validator.interfaces.AccountValidator;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created in Intellij IDEA
 * User: Balaji Varadharajan
 * Date: 26, September 2022
 * Time: 9:22 AM
 * Project: Zeus
 * Package Name: com.brihaspathee.zeus.validator.impl
 * To change this template use File | Settings | File and Code Template
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class AccountValidatorImpl implements AccountValidator {

    /**
     * This is a map of all the implementations of the AccountRuleSet interface
     * The key is the camel case version of the implementation class name
     * E.g. if the class name is "DemographicRuleSet" the key is assigned as
     * "demographicRuleSet"
     */
    private final Map accountRuleSets;

    /**
     * Get the rules that are to be executed
     */
    private final RuleService ruleService;

    /**
     * The rule set implementation helper instance to get the implementations for each ruleset
     */
    private final RuleSetImplementationHelper ruleSetImplementationHelper;

    /**
     * The rule execution helper to save all the rules there were executed for the payload
     */
    private final RuleExecutionHelper ruleExecutionHelper;


    /**
     * The method to validate the account
     * @param payloadTracker
     * @param accountDto
     * @return
     */
    @Override
    public Mono> validateAccount(PayloadTracker payloadTracker, AccountDto accountDto) {
        log.info("Inside the account validator, the validators are:{}", this.accountRuleSets);
        // Get the list of all the rules for the account
        RuleCategoryDto ruleCategory = ruleService.getRules("ACCOUNT",
                "ACCOUNT_RULE");
        ValidationResponse validationResponse = null;
        if(ruleCategory.getRuleTypes() != null && !ruleCategory.getRuleTypes().isEmpty()){
            RuleTypeDto accountRuleType = ruleCategory.getRuleTypes().get(0);
            List ruleSets = accountRuleType.getRuleSets();
            // Create the account validation result object with the necessary members
            // so that the results of the rules for the account and for each member can be stored
            AccountValidationResult finalAccountValidationResult =
                    constructAccountValidationResult(payloadTracker, accountDto);
            // Iterate through each rule set
            ruleSets.stream().forEach(ruleSet -> {
                log.info("Rule Set:{}", ruleSet);
                // Get the implementation of the rule set
                RuleSetImplementation ruleSetImplementation =
                        ruleSetImplementationHelper.getRuleSetImplementation(ruleSet.getRuleSetId());
                String ruleSetImplName = ruleSetImplementation.getRuleSetImplName();
                // Get the implementation class of the rule set that was auto wired
                AccountRuleSet accountRuleSet = accountRuleSets.get(ruleSetImplementation);
                // Generate an exception if no implementation is found for the rule
                if(accountRuleSet == null){
                    throw new RuleSetImplNotFound("No implementation found for rule set " + ruleSet.getRuleSetName());
                }
                // Execute all the rules withing the rule set
                accountRuleSet.validate(finalAccountValidationResult, accountDto, ruleSet, ruleSetImplementation);
            });
            // Once all the rules within the ruleset are executed check if any account or member level rules failed to
            // indicate if the validation of the account overall passed or failed
            checkIfValidationPassed(finalAccountValidationResult);
            log.info("Final Account Validation Result:{}", finalAccountValidationResult);
            saveExecutedRules(payloadTracker,finalAccountValidationResult);
            // Send the results back
            validationResponse =
                    ValidationResponse.builder()
                            .payloadTracker(payloadTracker)
                            .validationResult(finalAccountValidationResult)
                            .build();
        }
        return Mono.justOrEmpty(validationResponse).delayElement(Duration.ofSeconds(5));
    }

    /**
     * Method that constructs the account validation result object
     * @param accountDto
     * @return
     */
    private AccountValidationResult constructAccountValidationResult(PayloadTracker payloadTracker,
                                                                     AccountDto accountDto){
        return AccountValidationResult.builder()
                .responseId(ZeusRandomStringGenerator.randomString(15))
                .requestPayloadId(payloadTracker.getPayloadId())
                // Set the account number of the account that is to be validated
                .accountNumber(accountDto.getAccountNumber())
                // Create an empty array of rule result objects where the result of the rules will be stored
                .ruleResults(new ArrayList())
                // Construct a member validation object for each member in the account
                .memberValidationResults(constructMemberValidationResult(accountDto))
                .build();
    }

    /**
     * Construct the member validation result for each member in the account
     * @param accountDto
     * @return
     */
    private List constructMemberValidationResult(AccountDto accountDto){
        List memberValidationResults =
                new ArrayList();
        accountDto.getMembers().stream().forEach(memberDto -> {
            memberValidationResults.add(MemberValidationResult.builder()
                    // set the member code of the member
                            .memberCode(memberDto.getMemberCode())
                    // Create an empty array of rule result objects where the result of the rules will be stored
                            .ruleResults(new ArrayList())
                    .build());
        });
        return memberValidationResults;
    }

    /**
     * Check if the account validations passed or failed
     * @param accountValidationResult
     */
    private void checkIfValidationPassed(AccountValidationResult accountValidationResult){
        // Get the count of the number of account level rules that have failed
        long numberOfAccountRuleFailed = accountValidationResult.getRuleResults()
                .stream()
                .filter(ruleResult -> !ruleResult.isRulePassed()).count();
        if (numberOfAccountRuleFailed > 0){
            // if any account level rule failed then set the validation passed as false
            // It does not matter if one or more member level validations failed as well
            accountValidationResult.setValidationPassed(false);
        }else{
            // if no account level rules failed check if any member level rules failed
            accountValidationResult.getMemberValidationResults().stream().forEach(
                    memberValidationResult -> {
                long numberOfMemberRulesFailed = memberValidationResult.getRuleResults()
                        .stream()
                        .filter(ruleResult -> !ruleResult.isRulePassed()).count();
                if (numberOfMemberRulesFailed > 0){
                    // if one or more member level rules failed set the validation passed as false
                    accountValidationResult.setValidationPassed(false);
                }else {
                    // at this point all the account and member level rules have passed
                    accountValidationResult.setValidationPassed(true);
                }
            });
        }
    }

    /**
     * Save all the rules that were executed
     * @param payloadTracker
     * @param accountValidationResult
     */
    private void saveExecutedRules(PayloadTracker payloadTracker, AccountValidationResult accountValidationResult){
        if (accountValidationResult.getRuleResults() != null &&
                accountValidationResult.getRuleResults().size() > 0){
            accountValidationResult.getRuleResults().stream().forEach(ruleResult -> {
                ruleExecutionHelper.saveRulesExecuted(payloadTracker, ruleResult);
            });
        }
        if(accountValidationResult.getMemberValidationResults() != null &&
                accountValidationResult.getMemberValidationResults().size() > 0){
            accountValidationResult.getMemberValidationResults().stream().forEach(memberValidationResult -> {
                if(memberValidationResult.getRuleResults() != null &&
                        memberValidationResult.getRuleResults().size() > 0){
                    memberValidationResult.getRuleResults().stream().forEach(ruleResult -> {
                        ruleExecutionHelper.saveRulesExecuted(payloadTracker, ruleResult);
                    });
                }
            });
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy