import { Expression , LookupFunctions } from 'aurelia-binding' ; import { ViewResources } from 'aurelia-templating' ; import { Validator } from '../validator' ; import { ValidateResult } from '../validate-result' ; import { Rule } from './rule' ; import { Rules } from './rules' ; import { ValidationMessageProvider } from './validation-messages' ; /**
 * Validates.
 * Responsible for validating objects and properties.
 */ export class StandardValidator extends Validator { public static inject = [ ValidationMessageProvider , ViewResources ] ; private messageProvider : ValidationMessageProvider ; private lookupFunctions : LookupFunctions ; private getDisplayName : ( propertyName : string ) => string ; constructor ( messageProvider , resources ) { super ( ) ; this . messageProvider = messageProvider ; this . lookupFunctions = ( resources as any ) . lookupFunctions ; this . getDisplayName = messageProvider . getDisplayName . bind ( messageProvider ) ; } param object param propertyName param rules public validateProperty ( object , propertyName , rules ? ) { return this . validate ( object , propertyName , rules || null ) ; } param object param rules public validateObject ( object , rules ? ) { return this . validate ( object , null , rules || null ) ; } param rules parem public ruleExists ( rules , rule ) { let i = rules . length ; while ( i -- ) { if ( rules [ i ] . indexOf ( rule ) !== - 1 ) { return true ; } } return false ; } private getMessage ( rule , object , value ) { const expression = rule . message || this . messageProvider . getMessage ( rule . messageKey ) ; let { name : propertyName , displayName } = rule . property ; if ( propertyName !== null ) { displayName = this . messageProvider . getDisplayName ( propertyName , displayName ) ; } const overrideContext = { $displayName : displayName , $propertyName : propertyName , $value : value , $object : object , $config : rule . config , $getDisplayName : this . getDisplayName } ; return expression . evaluate ( { bindingContext : object , overrideContext } , this . lookupFunctions ) ; } private validateRuleSequence ( object , propertyName , ruleSequence , sequence , results ) { const validateAllProperties = propertyName === null || propertyName === undefined ; const rules = ruleSequence [ sequence ] ; let allValid = true ; const promises = [ ] ; for ( let i = 0 ; i < rules . length ; i ++ ) { const rule = rules [ i ] ; if ( ! validateAllProperties && rule . property . name != propertyName ) { continue ; } if ( rule . when && ! rule . when ( object ) ) { continue ; } const value = rule . property . name === null ? object : object [ rule . property . name ] ; let promiseOrBoolean = rule . condition ( value , object ) ; if ( ! ( promiseOrBoolean instanceof Promise ) ) { promiseOrBoolean = Promise . resolve ( promiseOrBoolean ) ; } promises . push ( promiseOrBoolean . then ( valid => { const message = valid ? null : this . getMessage ( rule , object , value ) ; results . push ( new ValidateResult ( rule , object , rule . property . name , valid , message ) ) ; allValid = allValid && valid ; return valid ; } ) ) ; } return Promise . all ( promises ) . then ( ( ) => { sequence ++ ; if ( allValid && sequence < ruleSequence . length ) { return this . validateRuleSequence ( object , propertyName , ruleSequence , sequence , results ) ; } return results ; } ) ; } private validate ( object , propertyName , rules ) { if ( ! rules ) { rules = Rules . get ( object ) ; } if ( ! rules || rules . length === 0 ) { return Promise . resolve ( [ ] ) ; } return this . validateRuleSequence ( object , propertyName , rules , 0 , [ ] ) ; } }