import { Severity , ValidationFailure } from "../shared" ; import { PropertyValidator } from "../validators/PropertyValidator" ; import { RuleApplicationOutcome } from "./RuleApplicationOutcome" ; import { ValidationCondition } from "./ValidationCondition" ; const successfulOutcome = new RuleApplicationOutcome ( ) ; export class ValidationRule < T , TProperty > { protected validators : PropertyValidator < TProperty > [ ] ; protected propertyName : string ; protected errorCode : string ; protected errorMessage : string ; protected severity : Severity ; protected conditions : ValidationCondition < T > [ ] ; protected callback : ( failure : ValidationFailure ) => void ; constructor ( public lambdaExpression ) { this . validators = [ ] ; this . conditions = [ ] ; let regexArray = lambdaExpression . toString ( ) . match ( "\\s+\\w+\\.(\\w+(\\.\\w+)*)" ) ; this . propertyName = regexArray && regexArray . length > 1 ? regexArray [ 1 ] : lambdaExpression . toString ( ) ; this . errorMessage = `${ this . propertyName } is invalid` ; } setPropertyName ( propertyName ) { this . propertyName = propertyName ; } addValidator ( validator ) { this . validators . push ( validator ) ; } setErrorCode ( errorCode ) { this . errorCode = errorCode ; } setErrorMessage ( errorMessage ) { this . errorMessage = errorMessage ; } setSeverity ( severity ) { this . severity = severity ; } addCondition ( condition ) { if ( condition ) { this . conditions . push ( condition ) ; } } onFailure ( callback ) { this . callback = callback ; } apply ( input ) { const propertyValue = this . lambdaExpressionResultWith ( input ) ; if ( this . isValid ( input , propertyValue ) ) { return successfulOutcome ; } const failure = this . createValidationFailure ( input , propertyValue ) ; this . invokeCallbackWith ( failure ) ; return new RuleApplicationOutcome ( failure ) ; } protected lambdaExpressionResultWith ( input ) { try { return this . lambdaExpression ( input ) ; } catch ( e ) { return undefined ; } } protected isValid ( input , propertyValue ) { return this . isNoValidationRequired ( input ) || this . allValidatorsAreValid ( propertyValue ) ; } protected isNoValidationRequired ( input ) { return ! this . isValidationRequired ( input ) ; } private isValidationRequired ( input ) { return this . conditions . length === 0 || this . conditions . every ( cond => cond . shouldDoValidation ( input ) ) ; } private allValidatorsAreValid ( propertyValue ) { return this . validators . every ( validator => validator . isValid ( propertyValue ) ) ; } protected createValidationFailure ( input , propertyValue ) { return new ValidationFailure ( input , this . propertyName , propertyValue , this . errorCode , this . errorMessage , this . severity ) ; } protected invokeCallbackWith ( failure ) { if ( this . callback ) { this . callback ( failure ) ; } } }