Source: br-presenter/src/br/presenter/validator/CrossPropertyValidatorProxy.js

/**
 * @module br/presenter/validator/CrossPropertyValidatorProxy
 */

var Validator = require('br/validation/Validator');
var CrossValidationPropertyListener = require('br/presenter/validator/CrossValidationPropertyListener');
var brCore = require("br/Core");
var EditableProperty = require("br/presenter/property/EditableProperty");

/**
 * @private
 * @class
 * @alias module:br/presenter/validator/CrossPropertyValidatorProxy
 * @implements module:br/validation/Validator
 *
 * @classdesc
 * This class is to be used via the {@link module:br/presenter/validator/CrossValidationPropertyBinder}.
 *
 * <p>This proxy class implements the {@link module:br/validation/Validator} interface so that it can be added as a validator
 * of {@link module:br/presenter/property/EditableProperty} instances. It then handles the routing pf validation calls
 * to the instance of {@link module:br/presenter/validator/CrossPropertyValidator} that it is constructed with. If there
 * are instances of non-editable properties, this proxy listens to changes on them and triggers re-validation when they happen.</p>
 *
 * <p>The <code>mProperties</code> parameter that this class is constructed with must match what the <code>oCrossPropertyValidator</code>'s
 * {@link module:br/presenter/validator/CrossPropertyValidator#validate} expects.</p>
 *
 * @param {Object} mProperties A name-to-property mapping of all the properties that <code>oCrossPropertyValidator</code> expects.
 * @param {module:br/presenter/validator/CrossPropertyValidator} oCrossPropertyValidator The validator to proxy validations to.
 */
function CrossPropertyValidatorProxy(mProperties, oCrossPropertyValidator)
{
	/** @private */
	this.m_mAllProperties = mProperties;

	/** @private */
	this.m_mEditableProperties = {}; // populated below

	/** @private */
	this.m_oCrossPropertyValidator = oCrossPropertyValidator;

	/** @private */
	this.m_bPropagateValidation = true;

	/** @private */
	this.m_mCrossValidationPropertyListeners = {};

	for (var sPropId in this.m_mAllProperties)
	{
		var oProperty = this.m_mAllProperties[sPropId];
		if(oProperty instanceof EditableProperty)
		{
			this.m_mEditableProperties[sPropId] = oProperty;
			oProperty.addValidator(this, {"sPropertyId": sPropId});
		}
		var oListener = new CrossValidationPropertyListener(this, sPropId);
		oProperty.addListener(oListener);
		this.m_mCrossValidationPropertyListeners[sPropId] = oListener;
	}
}
brCore.implement(CrossPropertyValidatorProxy, Validator);

/**
 * @private
 * @param vValue IGNORED (interface compatibility)
 * @param mAttributes
 * @param oValidationResult passed to the Cross Validator
 */
CrossPropertyValidatorProxy.prototype.validate = function(vValue, mAttributes, oValidationResult) {
	var Utility = require('br/core/Utility');

	if(!Utility.isEmpty(this.m_mAllProperties))
	{
		this.m_oCrossPropertyValidator.validate(this.m_mAllProperties, oValidationResult);

		if(this.m_bPropagateValidation)
		{
			var sCurrentProperty = mAttributes["sPropertyId"];
			this._propagateValidation(sCurrentProperty);
		}
	}
	else
	{
		oValidationResult.setResult(true, "");
	}
};

CrossPropertyValidatorProxy.prototype._propagateValidation = function(sPropertyToSkip)
{
	this.m_bPropagateValidation = false;
	for (var sPropId in this.m_mEditableProperties)
	{
		if(sPropId === sPropertyToSkip)
		{
			continue;
		}
		this.m_mEditableProperties[sPropId].forceValidation();
	}
	this.m_bPropagateValidation = true;
};

CrossPropertyValidatorProxy.prototype.destroy = function()
{
	this.m_mAllProperties = {};
	this.m_mEditableProperties = {};
	for(var sPropId in this.m_mAllProperties)
	{
		if(this.m_mAllProperties[sPropId].removeListener)
		{
			this.m_mAllProperties[sPropId].removeListener(this.m_mCrossValidationPropertyListeners[sPropId]);
		}
	}
};

/**
 * @private
 * @param sPropId ID of the property that just changed
 */
CrossPropertyValidatorProxy.prototype._$onPropertyChanged = function(sPropId)
{
	this._propagateValidation(sPropId); // force-validate all editable properties
};

module.exports = CrossPropertyValidatorProxy;