<commit_before>import { Injectable, Inject, Optional } from "@angular/core";
import {
    AbstractControl,
    AsyncValidatorFn,
    ValidatorFn,
    Validators,
    NG_VALIDATORS,
    NG_ASYNC_VALIDATORS
} from "@angular/forms";
import { DynamicFormControlModel } from "../model/dynamic-form-control.model";
import {
    DynamicValidatorDescriptor,
    DynamicValidatorsConfig
} from "../model/misc/dynamic-form-control-validation.model";
import { isObject, isString } from "../utils/core.utils";
import { DYNAMIC_VALIDATORS, Validator, ValidatorFactory, ValidatorsToken } from "./dynamic-form.validators";

@Injectable({
    providedIn: "root"
})
export class DynamicFormValidationService {

    constructor(@Optional() @Inject(NG_VALIDATORS) private NG_VALIDATORS: ValidatorFn[],
                @Optional() @Inject(NG_ASYNC_VALIDATORS) private NG_ASYNC_VALIDATORS: AsyncValidatorFn[],
                @Optional() @Inject(DYNAMIC_VALIDATORS) private DYNAMIC_VALIDATORS: Map<string, Validator | ValidatorFactory>) {}


    private getValidatorFn(validatorName: string, validatorArgs: any = null,
                           validatorsToken: ValidatorsToken = this.NG_VALIDATORS): Validator | never {

        let validatorFn: ValidatorFactory | Validator | undefined;

        if (Validators.hasOwnProperty(validatorName)) { // Built-in Angular Validators

            validatorFn = (Validators as any)[validatorName];

        } else { // Custom Validators

            if (this.DYNAMIC_VALIDATORS && this.DYNAMIC_VALIDATORS.has(validatorName)) {
                validatorFn = this.DYNAMIC_VALIDATORS.get(validatorName);

            } else if (validatorsToken) {
                validatorFn = validatorsToken.find(validatorFn => validatorFn.name === validatorName);
            }
        }

        if (validatorFn === undefined) { // throw when no validator could be resolved
            throw new Error(`validator "${validatorName}" is not provided via NG_VALIDATORS, NG_ASYNC_VALIDATORS or DYNAMIC_FORM_VALIDATORS`);
        }

        if (validatorArgs !== null) {
            return (validatorFn as ValidatorFactory)(validatorArgs);
        }

        return validatorFn as Validator;
    }


    private getValidatorFns(validatorsConfig: DynamicValidatorsConfig,
                            validatorsToken: ValidatorsToken = this.NG_VALIDATORS): Validator[] {

        let validatorFns: Validator[] = [];

        if (isObject(validatorsConfig)) {

            validatorFns = Object.keys(validatorsConfig).map(validatorConfigKey => {

                let validatorConfigValue = (validatorsConfig as DynamicValidatorsConfig)[validatorConfigKey];

                if (this.isValidatorDescriptor(validatorConfigValue)) {

                    let descriptor = validatorConfigValue as DynamicValidatorDescriptor;

                    return this.getValidatorFn(descriptor.name, descriptor.args, validatorsToken);
                }

                return this.getValidatorFn(validatorConfigKey, validatorConfigValue, validatorsToken);
            });
        }

        return validatorFns;
    }


    private parseErrorMessageConfig(template: string, model: DynamicFormControlModel, error: any = null): string {

        return template.replace(/{{\s*(.+?)\s*}}/mg, (_match: string, expression: string) => {

            let propertySource: any = model,
                propertyName: string = expression;

            if (expression.indexOf("validator.") >= 0 && error) {

                propertySource = error;
                propertyName = expression.replace("validator.", "");
            }

            return propertySource[propertyName] ? propertySource[propertyName] : null;
        });
    }
<commit_msg>catered for `0` in null check for `parseErrorMessageConfig`.<commit_after>import { Injectable, Inject, Optional } from "@angular/core";
import {
    AbstractControl,
    AsyncValidatorFn,
    ValidatorFn,
    Validators,
    NG_VALIDATORS,
    NG_ASYNC_VALIDATORS
} from "@angular/forms";
import { DynamicFormControlModel } from "../model/dynamic-form-control.model";
import {
    DynamicValidatorDescriptor,
    DynamicValidatorsConfig
} from "../model/misc/dynamic-form-control-validation.model";
import { isObject, isString } from "../utils/core.utils";
import { DYNAMIC_VALIDATORS, Validator, ValidatorFactory, ValidatorsToken } from "./dynamic-form.validators";

@Injectable({
    providedIn: "root"
})
export class DynamicFormValidationService {

    constructor(@Optional() @Inject(NG_VALIDATORS) private NG_VALIDATORS: ValidatorFn[],
                @Optional() @Inject(NG_ASYNC_VALIDATORS) private NG_ASYNC_VALIDATORS: AsyncValidatorFn[],
                @Optional() @Inject(DYNAMIC_VALIDATORS) private DYNAMIC_VALIDATORS: Map<string, Validator | ValidatorFactory>) {}


    private getValidatorFn(validatorName: string, validatorArgs: any = null,
                           validatorsToken: ValidatorsToken = this.NG_VALIDATORS): Validator | never {

        let validatorFn: ValidatorFactory | Validator | undefined;

        if (Validators.hasOwnProperty(validatorName)) { // Built-in Angular Validators

            validatorFn = (Validators as any)[validatorName];

        } else { // Custom Validators

            if (this.DYNAMIC_VALIDATORS && this.DYNAMIC_VALIDATORS.has(validatorName)) {
                validatorFn = this.DYNAMIC_VALIDATORS.get(validatorName);

            } else if (validatorsToken) {
                validatorFn = validatorsToken.find(validatorFn => validatorFn.name === validatorName);
            }
        }

        if (validatorFn === undefined) { // throw when no validator could be resolved
            throw new Error(`validator "${validatorName}" is not provided via NG_VALIDATORS, NG_ASYNC_VALIDATORS or DYNAMIC_FORM_VALIDATORS`);
        }

        if (validatorArgs !== null) {
            return (validatorFn as ValidatorFactory)(validatorArgs);
        }

        return validatorFn as Validator;
    }


    private getValidatorFns(validatorsConfig: DynamicValidatorsConfig,
                            validatorsToken: ValidatorsToken = this.NG_VALIDATORS): Validator[] {

        let validatorFns: Validator[] = [];

        if (isObject(validatorsConfig)) {

            validatorFns = Object.keys(validatorsConfig).map(validatorConfigKey => {

                let validatorConfigValue = (validatorsConfig as DynamicValidatorsConfig)[validatorConfigKey];

                if (this.isValidatorDescriptor(validatorConfigValue)) {

                    let descriptor = validatorConfigValue as DynamicValidatorDescriptor;

                    return this.getValidatorFn(descriptor.name, descriptor.args, validatorsToken);
                }

                return this.getValidatorFn(validatorConfigKey, validatorConfigValue, validatorsToken);
            });
        }

        return validatorFns;
    }


    private parseErrorMessageConfig(template: string, model: DynamicFormControlModel, error: any = null): string {

        return template.replace(/{{\s*(.+?)\s*}}/mg, (_match: string, expression: string) => {

            let propertySource: any = model,
                propertyName: string = expression;

            if (expression.indexOf("validator.") >= 0 && error) {

                propertySource = error;
                propertyName = expression.replace("validator.", "");
            }

            return propertySource[propertyName] === null || propertySource[propertyName] === undefined ? propertySource[propertyName] : null;
        });
    }

{'fraction_non_alphanumeric': 0.09954931071049841, 'fraction_numerical': 0.00039766702014846237, 'mean_word_length': 2.85539090444558, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '2890311', 'n_tokens_mistral': 2044, 'n_tokens_neox': 1963, 'n_words': 414}