'use strict';
var CLASS_NAME = 'PropertyInfo';
var Argument = require('../system/argument-check.js');
var DataType = require('../data-types/data-type.js');
var PropertyFlag = require('../shared/property-flag.js');
var ModelBase = require('../model-base.js');
var CollectionBase = require('../collection-base.js');
/**
* @classdesc
* Defines a property of a business object model.
* @description
* Creates a new property definition.
* </br></br>
* The data type can be any one from the {@link bo.dataTypes} namespace
* or a custom data type based on {@link bo.dataTypes.DataType DataType} object,
* or can be any business object model or collection defined by the
* model types available in the {@link bo} namespace (i.e. models based on
* {@link bo.ModelBase ModelBase} or {@link bo.CollectionBase CollectionBase}
* objects).
* </br></br>
* The flags parameter is ignored when data type is a model or collection.
*
* @memberof bo.shared
* @constructor
* @param {string} name - The name of the property.
* @param {*} type - The data type of the property.
* @param {bo.shared.PropertyFlag} [flags] - Other attributes of the property.
* @param {external.propertyGetter} [getter] - Custom function to read the value of the property.
* @param {external.propertySetter} [setter] - Custom function to write the value of the property.
*
* @throws {@link bo.system.ArgumentError Argument error}: The name must be a non-empty string.
* @throws {@link bo.system.ArgumentError Argument error}: The type must be a data type, a model or a collection.
* @throws {@link bo.system.ArgumentError Argument error}: The flags must be PropertyFlag items.
*/
function PropertyInfo (name, type, flags, getter, setter) {
var check = Argument.inConstructor(CLASS_NAME);
/**
* The name of the property.
* @type {string}
* @readonly
*/
this.name = check(name).forMandatory('name').asString();
/**
* The data type of the property.
* </br></br>
* The data type can be any one from the {@link bo.dataTypes} namespace
* or a custom data type based on {@link bo.dataTypes.DataType DataType} object,
* or can be any business object model or collection defined by the
* model types available in the {@link bo} namespace (i.e. models based on
* {@link bo.ModelBase ModelBase} or {@link bo.CollectionBase CollectionBase}
* objects).
*
* @type {*}
* @readonly
*/
this.type = check(type).forMandatory('type').asType([ DataType, ModelBase, CollectionBase ]);
/**
* The custom getter function of the property.
* @type {external.propertyGetter}
* @readonly
*/
this.getter = check(getter).forOptional('getter').asFunction();
/**
* The custom setter function of the property.
* @type {external.propertySetter}
* @readonly
*/
this.setter = check(setter).forOptional('setter').asFunction();
flags = type instanceof DataType ?
check(flags || PropertyFlag.none).forMandatory('flags').asInteger() :
PropertyFlag.readOnly | PropertyFlag.notOnDto | PropertyFlag.notOnCto;
/**
* Indicates whether the value of the property can be modified.
* @type {string}
* @readonly
*/
this.isReadOnly = (flags & PropertyFlag.readOnly) === PropertyFlag.readOnly;
/**
* Indicates if the property is a key element.
* @type {string}
* @readonly
*/
this.isKey = (flags & PropertyFlag.key) === PropertyFlag.key;
/**
* Indicates if the property is a key element of the parent object.
* @type {string}
* @readonly
*/
this.isParentKey = (flags & PropertyFlag.parentKey) === PropertyFlag.parentKey;
/**
* Indicates whether the value of the property would be passed to the data access object
* or would be received from the data access object, respectively.
* @type {string}
* @readonly
*/
this.isOnDto = (flags & PropertyFlag.notOnDto) === PropertyFlag.none;
/**
* Indicates whether the value of the property would be passed to the client
* or would be received from the client, respectively.
* @type {string}
* @readonly
*/
this.isOnCto = (flags & PropertyFlag.notOnCto) === PropertyFlag.none;
/**
* Checks if value has the appropriate type and it is not null,
* and not empty in case of Text data type.
*
* @function bo.shared.PropertyInfo#hasValue
* @param {data} value - The value to check.
* @returns {boolean} True if the value is neither null nor empty, otherwise false.
*/
this.hasValue = function (value) {
return this.type.hasValue(value);
};
// Immutable object.
Object.freeze(this);
}
module.exports = PropertyInfo;