define([
'entity/js/api/PropertyClassification',
'entity/js/api/PropertyType',
'entity/js/spi/Attributed',
'translations/js/api/I18n'
], function (
PropertyClassification,
PropertyType,
Attributed,
I18n
) {
'use strict';
/**
* Represents a property of an Entity.
*
* @AbcsAPI stable
* @version 15.4.5
* @exports entity/js/api/Property
*
* @constructor
* @private
*
* @param {Object} model object literal w/ following properties:
* @param {String} model.id
* @param {String} model.name
* @param {entity/js/api/PropertyType} model.type
* @param {entity/js/api/PropertyClassification} model.classification
* @param {String} model.initialValue - initial value
* @param {Boolean} model.required
* @param {entity/js/api/Entity} entity - An instance of the owning {@link entity/js/api/Entity Entity}.
* @param {Object} baseModel read only base model (optional)
*/
var Property = function (model, entity, baseModel) {
AbcsLib.checkThis(this);
if (AbcsLib.isString(model)) {
//the passed parameter is a string, which is interpreted as desired property ID
//convert to the common notation...
model = {
id: model,
classification: PropertyClassification.BASIC
};
}
if (baseModel) {
AbcsLib.checkDefined(baseModel.id, 'model.id');
} else if (AbcsLib.isObject(model)) {
AbcsLib.checkDefined(model.id, 'model.id');
}
if (!entity && model.entity) {
// Support legacy code passing in entity as part of the model.
entity = model.entity;
}
delete model.entity;
Attributed.call(this, model, entity, baseModel);
};
AbcsLib.extend(Property, Attributed);
Property._KEY_ID = 'id';
Property._KEY_NAME = 'name';
Property._KEY_TYPE = 'type';
Property._KEY_REQUIRED = 'required';
Property._KEY_UNIQUE = 'unique';
Property._KEY_INITIAL_VALUE = 'initialValue';
Property._KEY_CLASSIFICATION = 'classification';
Property._KEY_FORMULA = 'formula';
Property._KEY_AGGREGATION = 'aggregation';
Property._KEY_VALIDATORS = 'validators';
Property._ATTRIBUTE_KEY_DESCRIPTION = 'description';
Property._ATTRIBUTE_KEY_SEARCHABLE = 'searchable';
Property._ATTRIBUTE_KEY_SORTABLE = 'sortable';
Property.I18N_SCOPE_PROPERTIES = 'properties';
/**
* @returns {Entity}
*/
Property.prototype.getEntity = function () {
return this.getParentObject();
};
/**
* Gets a map with the translatable attribute info for Entity.
* @override
* @returns {Object} model key -> I18n key.
*/
Property.prototype.getTranslatableKeys = function() {
var map = {};
map[Property._KEY_NAME]
= I18n.key(I18n.Type.Entity, this.getEntity().getId(), Property.I18N_SCOPE_PROPERTIES, this.getId(), I18n.Suffix.Name);
return map;
};
/**
* Gets a map with the translatable attribute info for Entity.
* @override
* @returns {Object} model key -> I18n key.
*/
Property.prototype.getTranslatableAttributes = function() {
var map = {};
map[Property._ATTRIBUTE_KEY_DESCRIPTION]
= I18n.key(I18n.Type.Entity, this.getEntity().getId(), Property.I18N_SCOPE_PROPERTIES, this.getId(), I18n.Suffix.Description);
return map;
};
/**
* Returns ID of this property.
*
* @AbcsAPI stable
* @version 15.4.5
*
* @returns {String}
*/
Property.prototype.getId = function () {
return this.getModelValue(Property._KEY_ID);
};
/**
* Gets human readable singular name of this property, e.g. 'Address'
*
* @AbcsAPI stable
* @version 15.4.5
*
* @returns {String}
*/
Property.prototype.getSingularName = function () {
return this.getModelValueAsString(Property._KEY_NAME);
};
/**
* Gets human readable singular name of this property, e.g. 'Address'
*
* @deprecated use {@link #getSingularName} instead.
* @returns {String}
*/
Property.prototype.getName = Property.prototype.getSingularName;
/**
* Gets the human readable description for this property.
* @returns {String} the property description
*/
Property.prototype.getDescription = function() {
return this.getAttributeAsString(Property._ATTRIBUTE_KEY_DESCRIPTION);
};
/**
* Returns type of this property.
*
* @AbcsAPI stable
* @version 15.4.5
*
* @returns {entity/js/api/PropertyType}
*/
Property.prototype.getType = function () {
return this.getModelValue(Property._KEY_TYPE);
};
/**
* Is this property required?
*
* @returns {Boolean}
*/
Property.prototype.isRequired = function () {
// return boolean, defaulting to false if undefined or null
return !!this.getModelValue(Property._KEY_REQUIRED);
};
/**
* Is this property unique?
*
* @returns {Boolean}
*/
Property.prototype.isUnique = function () {
// return boolean, defaulting to false if undefined or null
return !!this.getModelValue(Property._KEY_UNIQUE);
};
/**
* Returns initial value of this property.
*
* @returns {String}
*/
Property.prototype.getInitialValue = function () {
return this.getModelValue(Property._KEY_INITIAL_VALUE);
};
/**
* Returns classification of this property. If the model has no
* classification value, this method returns BASIC.
*
* @returns {PropertyClassification}
*/
Property.prototype.getClassification = function () {
var res = this.getModelValue(Property._KEY_CLASSIFICATION);
if (!res) {
res = PropertyClassification.BASIC;
}
return res;
};
/**
* Finds out if the property is a key or not.
*
* @returns {Boolean} true if the property is a key, false otherwise
*/
Property.prototype.isKey = function () {
return this.getType() === PropertyType.KEY;
};
/**
* Finds out if the property is a reference or not.
*
* @returns {Boolean} true if the property is a reference, false otherwise
*/
Property.prototype.isReference = function () {
return this.getType() === PropertyType.REFERENCE;
};
/**
* Checks if this property is sortable or not.
*
* @returns {Boolean}
*/
Property.prototype.isSortable = function () {
return this.getAttribute(Property._ATTRIBUTE_KEY_SORTABLE, !this.isReference());
};
/**
* Checks if this property is searchable or not.
*
* <p>
* The difference between 'searchable' and 'filterable' is that some properties are allowed to be
* searched, but doesn't make sense in the context of basic filter working over that single field.
* </p>
*
* <p>
* Example could be DateTime property which would be hard to use for basic filtering (it would be
* pretty hard to set exact date-time value into basic filter field). But on the other hand, it could
* be easily used as part of default query where one wants to see all records with date-time later
* than included value.
* </p>
*
* @returns {Boolean}
*/
Property.prototype.isSearchable = function () {
return this.getAttribute('searchable', true);
};
/**
* Checks if this property is filerable or not.
*
* @returns {Boolean}
*/
Property.prototype.isFilterable = function () {
switch (this.getType()) {
case PropertyType.BOOLEAN:
case PropertyType.DATETIME:
case PropertyType.TIME:
case PropertyType.ATTACHMENT:
return false;
default:
return true;
}
};
/**
* Returns formula to calculate value of this property.
*
* @returns {String} a snippet of JavaScript code
*/
Property.prototype.getFormula = function () {
return this.getModelValue(Property._KEY_FORMULA);
};
/**
* Gets the declarative aggregation information used to calculate the value
* of this property from related Entities.
*
* <p>
* The returned object has the following properties:
* <ul><li>aggregationFunction - AVG, COUNT, MIN, MAX or SUM</li>
* <li>aggregationPath - an array of objects which each represent a releation
* and therefore have an entityId and mappingPropertyId</li>
* <li>aggregatedPropertyId - the id of the property being aggregated</li></ul>
* </p>
* <p>
* Example aggregation object for averaging the "salary" property of child
* entity "employee": {
* aggregationFunction: 'AVG',
* aggregationPath: [{entityId: 'employee', mappingPropertyId: 'ref2departments'}],
* aggregatedPropertyId: 'salary'
* }
* </p>
* @returns {Object} the declarative aggregate forumla
*/
Property.prototype.getAggregation = function () {
// Until there is a child object representing aggregation (which can
// fire change events) return a clone to force modifiers to call
// setAggregation.
return AbcsLib.clone(this.getModelValue(Property._KEY_AGGREGATION));
};
/**
* Return the array of validators assigned to the property
* @returns {Array} array of validators parameters/descriptors
*/
Property.prototype.getValidators = function () {
// Until there is a child object representing a validator (which can
// fire change events) return a clone to force modifiers to call
// setValidators.
return AbcsLib.clone(this.getModelValue(Property._KEY_VALIDATORS));
};
return Property;
});