'use strict';
var CLASS_NAME = 'ValidationRule';
var util = require('util');
var Argument = require('../system/argument-check.js');
var RuleBase = require('./rule-base.js');
var RuleSeverity = require('./rule-severity.js');
var ValidationResult = require('./validation-result.js');
var PropertyInfo = require('../shared/property-info.js');
/**
* @classdesc
* Represents a validation rule.
* @description
* Creates a new validation rule object.
* The rule instances should be frozen.
*
* @memberof bo.rules
* @constructor
* @param {string} ruleName - The name of the rule.
* It is typically the name of the constructor, without the Rule suffix.
*
* @extends bo.rules.RuleBase
*
* @throws {@link bo.system.ArgumentError Argument error}: The rule name must be a non-empty string.
*/
function ValidationRule (ruleName) {
RuleBase.call(this, ruleName);
/**
* The definition of the property the rule relates to.
* @type {bo.shared.PropertyInfo}
* @readonly
*/
this.primaryProperty = null;
/**
* Sets the properties of the rule.
*
* @param {bo.shared.PropertyInfo} primaryProperty - The property definition the rule relates to.
* @param {string} message - Human-readable description of the rule failure.
* @param {number} [priority=10] - The priority of the rule.
* @param {boolean} [stopsProcessing=false] - Indicates the rule behavior in case of failure.
*
* @throws {@link bo.system.ArgumentError Argument error}: The primary property must be a PropertyInfo object.
* @throws {@link bo.system.ArgumentError Argument error}: The message must be a non-empty string.
*/
this.initialize = function (primaryProperty, message, priority, stopsProcessing) {
this.primaryProperty = Argument.inMethod(CLASS_NAME, 'initialize')
.check(primaryProperty).forMandatory('primaryProperty').asType(PropertyInfo);
// Initialize base properties.
RuleBase.prototype.initialize.call(this, message, priority, stopsProcessing);
};
var inputProperties = [];
var affectedProperties = [];
/**
* Adds an additional property to the rule that will use its value.
*
* @param {bo.shared.PropertyInfo} property - An input property that value is used by the rule of.
*
* @throws {@link bo.system.ArgumentError Argument error}: The input property must be a PropertyInfo object.
*/
this.addInputProperty = function (property) {
property = Argument.inMethod(CLASS_NAME, 'addInputProperty')
.check(property).forMandatory('property').asType(PropertyInfo);
if (inputProperties.indexOf(property) < 0)
inputProperties.push(property);
};
/**
* Adds an additional property that is influenced by the rule.
*
* @param {bo.shared.PropertyInfo} property - An affected property influenced by the rule.
*
* @throws {@link bo.system.ArgumentError Argument error}: The affected property must be a PropertyInfo object.
*/
this.addAffectedProperty = function (property) {
property = Argument.inMethod(CLASS_NAME, 'addAffectedProperty')
.check(property).forMandatory('property').asType(PropertyInfo);
if (affectedProperties.indexOf(property) < 0)
affectedProperties.push(property);
};
/**
* Returns the values of the properties that are used by the rule.
* This method is called by the rule manager internally to provide
* the values of the input properties for the execute() method.
*
* @protected
* @param {internal~getValue} getValue - A function that returns the value of a property.
* @returns {object} An object that properties hold the values of the input properties of.
*
* @throws {@link bo.system.ArgumentError Argument error}: The getValue argument must be a function..
*/
this.getInputValues = function (getValue) {
getValue = Argument.inMethod(CLASS_NAME, 'getInputValues')
.check(getValue).forMandatory('getValue').asFunction();
var inputValues = {};
var combined = new Array(this.primaryProperty).concat(inputProperties);
for (var i = 0; i < combined.length; i++) {
var property = combined[i];
inputValues[property.name] = getValue(property);
}
return inputValues;
};
/**
* Returns the result of the rule executed.
*
* @param {string} [message] - Human-readable description of the rule failure.
* @param {bo.rules.RuleSeverity} severity - The severity of the failed rule.
* @returns {bo.rules.ValidationResult} The result of the validation rule.
*/
this.result = function (message, severity) {
var result = new ValidationResult(this.ruleName, this.primaryProperty.name, message || this.message);
result.severity = Argument.inMethod(CLASS_NAME, 'result')
.check(severity).for('severity').asEnumMember(RuleSeverity, RuleSeverity.error);
result.stopsProcessing = this.stopsProcessing;
result.isPreserved = false;
result.affectedProperties = affectedProperties;
return result;
};
// Immutable object.
Object.freeze(ValidationRule);
}
util.inherits(ValidationRule, RuleBase);
module.exports = ValidationRule;