var UB = require('./UB');
var _ = require('./libs/lodash/lodash');
/**
* @classdesc
* UnityBase domain object model.
* Construct new UBDomain instance based on getDomainInfo UB server method result
*
* Usage sample:
*
* UBDomain.get('uba_user').attr('name').caption;
*
* @class
* @param {Object} domainInfo getDomainInfo UB server method result
* @param {Object} domainInfo.domain raw entities collection
* @param {Object} domainInfo.entityMethods entities methods access rights for current user
* @param {Object} domainInfo.models information about domain models
* @param {Object} domainInfo.i18n entities localization to current user language
* @param {Object} domainInfo.forceMIMEConvertors list of registered server-side MIME converters for document type attribute content
*/
function UBDomain(domainInfo) {
var me = this,
entityCodes = Object.keys(domainInfo.domain);
/**
* Collection of entities
* @type {Object<String, UBEntity>}
*/
this.entities = {};
entityCodes.forEach(function(entityCode){
me.entities[entityCode] = new UBEntity(
domainInfo.domain[entityCode],
domainInfo.entityMethods[entityCode] || {},
domainInfo.i18n[entityCode],
entityCode,
me
);
});
/**
* Models collection
* @type {Object<String, UBModel>}
*/
this.models = {};
var modelCodes = Object.keys(domainInfo.models);
modelCodes.forEach(function(modelCode){
var m = domainInfo.models[modelCode];
me.models[modelCode] = new UBModel(m.path, m.needInit, m.needLocalize, m.order);
});
/**
*
* @type {Object}
* @readonly
*/
this.forceMIMEConvertors = domainInfo.forceMIMEConvertors;
}
/**
* Get entity by code
* @param {String} entityCode
* @param {Boolean} [raiseErrorIfNotExists=false] If `true` and entity does not exists throw error
* @returns {UBEntity}
*/
UBDomain.prototype.get = function(entityCode, raiseErrorIfNotExists){
var result = this.entities[entityCode];
if (raiseErrorIfNotExists && !result){
throw new Error('Entity with code ' + entityCode + ' does not exists.');
}
return result;
};
/**
* Call collBack function for each entity.
* @param {Function} callBack
* @param {Object} [scope]
*/
UBDomain.prototype.eachEntity = function(callBack, scope){
return _.forEach(this.entities, callBack, scope);
};
/**
* Filter entities by properties
* @example
*
* // sessionCachedEntites contains all entities with property cacheType equal Session
* var sessionCachedEntites = domain.filterEntities({cacheType: 'Session'});
*
* @param {Object|Function} config
* @returns {Array}
*/
UBDomain.prototype.filterEntities = function(config){
if (_.isFunction(config)){
return _.filter(this.entities, config);
} else {
return _.filter(this.entities, function (item) {
var res = true;
for (var prop in config) {
if (config.hasOwnProperty(prop)) {
res = res && (item[prop] === config[prop]);
}
}
return res;
});
}
};
/**
* UnityBase base attribute data types
* @readonly
* @enum
*/
UBDomain.ubDataTypes = {
Many: "Many",
Entity: "Entity",
Int: "Int",
BigInt: "BigInt",
String: "String",
Boolean: "Boolean",
Float: "Float",
DateTime: "DateTime",
Date: "Date",
Currency: "Currency",
Document: "Document",
ID: "ID",
Text: "Text",
Enum: "Enum"
};
/**
* UnityBase base mixins
* @readonly
* @enum
*/
UBDomain.ubMixins = {
dataHistory: "dataHistory",
mStorage: "mStorage",
unity: "unity",
treePath: "treePath"
};
/**
* Service attribute names
* @readonly
* @enum
*/
UBDomain.ubServiceFields = {
dateFrom: "mi_datefrom",
dateTo: "mi_dateto"
};
/**
* Return physical type by UBDataType
* @param {String} dataType
* @return {String}
*/
UBDomain.getPhysicalDataType = function(dataType) {
var me = this;
if (!me.physicalTypeMap) {
var ubDataTypes = UBDomain.ubDataTypes,
typeMap = {};
typeMap[ubDataTypes.Int] = 'int';
typeMap[ubDataTypes.Entity] = 'int';
typeMap[ubDataTypes.ID] = 'int';
typeMap[ubDataTypes.BigInt] = 'int';
typeMap[ubDataTypes.String] = 'string';
typeMap[ubDataTypes.Text] = 'string';
typeMap[ubDataTypes.Enum] = 'string';
typeMap[ubDataTypes.Float] = 'float';
typeMap[ubDataTypes.Currency] = 'float';
typeMap[ubDataTypes.Boolean] = 'boolean';
typeMap[ubDataTypes.Date] = 'date';
typeMap[ubDataTypes.DateTime] = 'date';
me.physicalTypeMap = typeMap;
}
return me.physicalTypeMap[dataType] || 'auto';
};
/**
* Model (logical group of entities)
* @class
* @param path
* @param needInit
* @param needLocalize
* @param order
* @constructor
*/
function UBModel(path, needInit, needLocalize, order){
this.path = path;
if (needInit) {
this.needInit = needInit;
}
if (needLocalize) {
this.needLocalize = needLocalize;
}
this.order = order;
}
UBModel.prototype.needInit = false;
UBModel.prototype.needLocalize = false;
/**
* Collection of attributes
* @class
*/
function UBEntityAttributes(){}
/**
* Return a JSON representation of all entity attributes
* @returns {{}}
*/
UBEntityAttributes.prototype.asJSON = function(){
var me = this, result = {};
_.forEach(me, function(prop, propName){
if (prop.asJSON){
result[propName] = prop.asJSON();
} else {
result[propName] = prop;
}
});
return result;
};
/**
* @class
* @param {Object} entityInfo
* @param {Object} entityMethods
* @param {Object} i18n
* @param {String} entityCode
* @param {UBDomain} domain
*/
function UBEntity(entityInfo, entityMethods, i18n, entityCode, domain){
var me = this, attributeNames, attributeInfo,
mixinNames, mixinInfo, i18nMixin;
/**
* @type {UBDomain}
* @readonly
*/
this.domain = domain;
/**
* @type {String}
* @readonly
*/
this.code = entityCode;
//???
this.autoImplementMixins = true;
//TODO - write documentation for attributes assigned from entityInfo
/**
* Entity model name
* @property {String} modelName
* @readonly
*/
/**
* @property {String} name
* @readonly
*/
/**
* Internal short alias
* @property {String} sqlAlias
* @readonly
*/
/**
* Data source connection name
* @property {String} connectionName
* @readonly
*/
_.assign(me, entityInfo);
if (i18n){
_.assign(me, i18n);
}
attributeNames = Object.keys(entityInfo.attributes || {});
/**
* Entity attributes collection
* @type {Object.<string, UBEntityAttribute>}
*/
this.attributes = new UBEntityAttributes();
attributeNames.forEach(function(attributeCode){
attributeInfo = entityInfo.attributes[attributeCode];
me.attributes[attributeCode] = new UBEntityAttribute(attributeInfo,
(i18n && i18n.attributes ? i18n.attributes[attributeCode]: null), attributeCode, me);
});
mixinNames = Object.keys(entityInfo.mixins || {});
/**
* Collection of entity mixins
* @type {Object<String, UBEntityMixin>}
*/
this.mixins = {};
mixinNames.forEach(function(mixinCode){
mixinInfo = entityInfo.mixins[mixinCode];
i18nMixin = (i18n && i18n.mixins ? i18n.mixins[mixinCode]: null);
switch(mixinCode){
case 'mStorage':
me.mixins[mixinCode] = new UBEntityStoreMixin(mixinInfo, i18nMixin, mixinCode);
break;
case 'dataHistory':
me.mixins[mixinCode] = new UBEntityHistoryMixin(mixinInfo, i18nMixin, mixinCode);
break;
case 'aclRls':
me.mixins[mixinCode] = new UBEntityAclRlsMixin(mixinInfo, i18nMixin, mixinCode);
break;
case 'fts':
me.mixins[mixinCode] = new UBEntityFtsMixin(mixinInfo, i18nMixin, mixinCode);
break;
case 'als':
me.mixins[mixinCode] = new UBEntityAlsMixin(mixinInfo, i18nMixin, mixinCode);
break;
default:
me.mixins[mixinCode] = new UBEntityMixin(mixinInfo, i18nMixin, mixinCode);
}
});
/**
* Entity methods, allowed for current logged-in user in format {method1: 1, method2: 1}. 1 mean method is allowed
* @type {Object<String, Number>}
* @readOnly
*/
this.entityMethods = entityMethods || {};
}
/**
* Entity caption
* @type {string}
*/
UBEntity.prototype.caption = '';
/**
* Entity description
* @type {string}
*/
UBEntity.prototype.description = '';
/**
* Documentation
* @type {string}
*/
UBEntity.prototype.documentation = '';
/**
* Name of attribute witch used as a display value in lookup
* @type {string}
*/
UBEntity.prototype.descriptionAttribute = '';
UBEntity.prototype.fullPath = '';
UBEntity.prototype.sqlAlias = '';
/**
* Indicate how entity content is cached on the client side.
*
* Possible cache types: None, "None", "Entity", "Session", "SessionEntity"
* @type {String}
* @readonly
*/
UBEntity.prototype.cacheType = 'None';
UBEntity.prototype.dsType = 'Normal';
/**
* Return an entity caption to display on UI
* @returns {string}
*/
UBEntity.prototype.getEntityCaption = function() {
return this.caption || this.description;
};
/**
* Get entity attribute by code. Return undefined if attribute does not found
* @param {String} attributeCode
* @param {Boolean} [simple] Is do not complex attribute name. By default false.
* @returns {UBEntityAttribute}
*/
UBEntity.prototype.attr = function(attributeCode, simple){
if (simple){
return this.attributes[attributeCode];
} else {
return this.getEntityAttribute(attributeCode);
}
};
/**
* Get entity attribute by code. Throw error if attribute does not found.
* @param attributeCode
* @returns {UBEntityAttribute}
*/
UBEntity.prototype.getAttribute = function(attributeCode){
var me = this, attr;
attr = me.attributes[attributeCode];
if(!attr){
throw new Error('Attribute ' + me.code + '.' + attributeCode + ' doesn\'t exist' );
}
return attr;
};
/**
* Call collBack function for each attribute.
* @param {Function} callBack
* @param {Object} [scope]
*/
UBEntity.prototype.eachAttribute = function(callBack, scope){
return _.forEach(this.attributes, callBack, scope);
};
/**
* Get entity mixin by code. Returns "undefined" if the mixin is not found
* @param {String} mixinCode
* @returns {UBEntityMixin}
*/
UBEntity.prototype.mixin = function(mixinCode){
return this.mixins[mixinCode];
};
/**
* Check the entity has mixin. Returns `true` if the mixin is exist and enabled
* @param {String} mixinCode
* @returns {Boolean}
*/
UBEntity.prototype.hasMixin = function(mixinCode){
var mixin = this.mixins[mixinCode];
if ('audit' === mixinCode){
return !mixin || (!!mixin && mixin.enabled);
}
return (!!mixin && mixin.enabled);
};
/**
* Check the entity has mixin. Throw error if mixin dose not exist or not enabled
* @param {String} mixinCode
*/
UBEntity.prototype.checkMixin = function(mixinCode){
if (!this.hasMixin(mixinCode)){
throw new Error("Entity " + this.code + ' does not have mixin ' + mixinCode);
}
};
UBEntity.prototype.asJSON = function(){
var me = this, result = {code: me.code};
_.forEach(me, function(prop, propName){
if (propName === 'domain'){
return;
}
if (prop.asJSON){
result[propName] = prop.asJSON();
} else {
result[propName] = prop;
}
});
return result;
};
/**
* Filter attributes by properties
* @param {Object|Function} config
* @returns {Array}
* example
*
* domain.get('uba_user').filterAttribute({dataType: 'Document'});
*
* return all attributes where property dataType equal Document
*/
UBEntity.prototype.filterAttribute = function(config){
if (_.isFunction(config)){
return _.filter(this.attributes, config);
} else {
return _.filter(this.attributes, function (item) {
var res = true;
for (var prop in config) {
if (config.hasOwnProperty(prop)) {
res = res && (item[prop] === config[prop]);
}
}
return res;
});
}
};
/**
* Check current user have access to specified entity method
* @param {String} methodCode
* @returns {Boolean}
*/
UBEntity.prototype.haveAccessToMethod = function(methodCode){
return this.entityMethods[methodCode] === 1;
};
/**
* Check current user have access to AT LAST one of specified methods
* @param {Array} methods
* @returns {boolean}
*/
UBEntity.prototype.haveAccessToAnyMethods = function(methods){
var me = this,
fMethods = methods || [], result = false;
fMethods.forEach(function(methodCode){
result = result || me.entityMethods[methodCode] === 1;
});
return result;
};
/**
* Check current user have access to ALL of specified methods
* @param {Array<String>} Method names
* @returns {Boolean}
*/
UBEntity.prototype.haveAccessToMethods = function(methods){
var me = this,
result = true,
fMethods = methods || [];
fMethods.forEach(function(methodCode){
result = result && (me.entityMethods[methodCode] === 1);
});
return result;
};
/**
* return array of conversion rules for raw server response data
* @param {Array<String>} fieldList
* @returns {Array<{index: number, convertFn: function}>}
*/
UBEntity.prototype.getConvertRules = function(fieldList) {
var
me = this,
rules = [],
attribute,
types = UBDomain.ubDataTypes;
fieldList.forEach(function(fieldName, index){
attribute = me.attr(fieldName);
if(attribute) {
if (attribute.dataType === types.DateTime) {
rules.push({
index: index,
convertFn: UB.iso8601Parse
});
} else if (attribute.dataType === types.Date){
rules.push({
index: index,
convertFn: UB.iso8601ParseAsDate
});
} else if (attribute.dataType === types.Boolean) {
rules.push({
index: index,
convertFn: UB.booleanParse
});
}
}
});
return rules;
};
/**
* Return description attribute name (`descriptionAttribute` metadata property)
* This property may be empty or valid(validation performed by server)
* If case property is empty - try to get attribute with code `caption`
*
* @return {String}
*/
UBEntity.prototype.getDescriptionAttribute = function() {
var result = this.descriptionAttribute || 'caption';
if (!this.attr(result)){
throw new Error('Missing description attribute for entity ' + this.code);
}
return result;
};
/**
* Return information about attribute and attribute entity. Understand complex attributes like firmID.firmType.code
* @param {String} attributeName
* @param {Number} [deep] If 0 - last, -1 - before last, > 0 - root. Default 0.
* @return {{ entity: String, attribute: Object, attributeCode: String }}
*/
UBEntity.prototype.getEntityAttributeInfo = function(attributeName, deep) {
var me = this,
domainEntity = me,
attributeNameParts = attributeName.split('.'),
currentLevel = - (attributeNameParts.length - 1),
complexAttr = [],
currentEntity = me.code,
/** @type UBEntityAttribute */ attribute, key;
if (deep && deep > 0){
return { entity: currentEntity, attribute: domainEntity.attr(attributeNameParts[0]), attributeCode: attributeNameParts[0] };
}
while(domainEntity && attributeNameParts.length){
if(domainEntity && attributeNameParts.length === 1 ){
complexAttr = attributeNameParts[0].split('@');
if (complexAttr.length > 1){
domainEntity = me.domain.get(complexAttr[1]); //real entity is text after @
attributeName = complexAttr[0];
}
return { entity: currentEntity, attribute: domainEntity.attr(attributeName), attributeCode: attributeName };
}
key = attributeNameParts.shift();
complexAttr = key.split('@');
if (complexAttr.length > 1){
currentEntity = complexAttr[1];
domainEntity = me.domain.get(currentEntity); //real entity is text after @
key = complexAttr[0];
}
attribute = domainEntity.attr(key);
if (attribute){ //check that attribute exists in domainEntity
if (currentLevel === (deep || 0) ){
return { entity: currentEntity, attribute: attribute, attributeCode: key };
}
attributeName = attributeNameParts[0];
if(attribute.dataType === "Enum" && attributeName === 'name'){
return { entity: currentEntity, attribute: attribute, attributeCode: key };
} else {
currentEntity = attribute.associatedEntity;
domainEntity = attribute.getAssociatedEntity();
}
} else {
return undefined;
}
currentLevel += 1;
}
return undefined;
};
/**
* Return Entity attribute. Understand complex attributes like firmID.firmType.code
* @param {String} attributeName
* @param {Number} [deep] If 0 - last, -1 - before last, > 0 - root. Default 0.
* @return {UBEntityAttribute}
*/
UBEntity.prototype.getEntityAttribute = function(attributeName, deep) {
var
me = this,
domainEntity = me,
attributeNameParts = attributeName.split('.'),
currentLevel = - (attributeNameParts.length - 1),
complexAttr = [],
attribute, key;
if (deep && deep > 0){
return domainEntity.attributes[attributeNameParts[0]];
}
//TODO: Сделать так же для других спец.символов, кроме @
while(domainEntity && attributeNameParts.length){
if(domainEntity && attributeNameParts.length ===1 ){
complexAttr = attributeNameParts[0].split('@');
if (complexAttr.length > 1){
domainEntity = me.domain.get(complexAttr[1]); //real entity is text after @
attributeName = complexAttr[0];
}
return domainEntity.attributes[attributeName];
}
key = attributeNameParts.shift();
complexAttr = key.split('@');
if (complexAttr.length > 1){
domainEntity = me.domain.get(complexAttr[1]); //real entity is text after @
key = complexAttr[0];
}
attribute = domainEntity.attributes[key];
if (attribute){ //check that attribute exists in domainEntity
if (currentLevel === (deep || 0) ){
return attribute;
}
attributeName = attributeNameParts[0];
if(attribute.dataType === "Enum" && attributeName === 'name'){
return attribute;
} else {
domainEntity = me.domain.get(attribute.associatedEntity);
}
} else {
return undefined;
}
currentLevel += 1;
}
return undefined;
};
/**
* return attributes code list
* @param {Object|Function} [filter]
* @returns String[]
*/
UBEntity.prototype.getAttributeNames = function(filter) {
var attributes = [];
if (filter){
_.forEach( this.filterAttribute(filter) , function(attr){
attributes.push(attr.code);
});
return attributes;
} else {
return Object.keys(this.attributes);
}
};
/**
* Return requirements entity code list for field list
* @param {String[]} [fieldList] (optional)
* @return {String[]}
*/
UBEntity.prototype.getEntityRequirements = function(fieldList) {
var
me = this,
result = [],
fieldNameParts, attr, tail;
fieldList = fieldList || me.getAttributeNames();
for(var i = 0, len = fieldList.length; i < len; ++i){
fieldNameParts = fieldList[i].split('.');
attr = me.getEntityAttribute(fieldNameParts[0]);
if(attr.dataType === 'Entity'){
if(fieldNameParts.length > 1) {
tail = [fieldNameParts.slice(1).join('.')];
result = _.union(result, attr.getAssociatedEntity().getEntityRequirements( tail ) );
} else {
result = _.union(result, [attr.associatedEntity]);
}
}
}
return result;
};
/**
* Check the entity contains attribute(s) and throw error if not contains
* @param {String|Array<String>} attributeName
* @param {String} contextMessage
*/
UBEntity.prototype.checkAttributeExist = function(attributeName, contextMessage){
var me = this;
attributeName = !_.isArray(attributeName) ? [attributeName]: attributeName;
_.forEach(attributeName, function(fieldName){
if (!me.getEntityAttributeInfo(fieldName)){
throw new Error(contextMessage + (contextMessage ? ' ': '') +
'The entity "' + me.code + '" does not have attribute "' + fieldName + '"' );
}
});
};
/**
* Return entity description.
* @returns {string}
*/
UBEntity.prototype.getEntityDescription = function(){
return this.description || this.caption;
};
/**
*
* @param {Object} attributeInfo
* @param {Object} i18n
* @param {String} attributeCode
* @param {UBEntity} entity
* @constructor
*/
function UBEntityAttribute(attributeInfo, i18n, attributeCode, entity){
/**
* @property {String}
* @readonly
*/
this.code = attributeCode;
/**
* @property {UBEntity}
* @readonly
*/
this.entity = entity;
/**
* Data type
* String, Строка небольшой длины. MSSQL: NVARCHAR, ORACLE: NVARCHAR2, POSTGRE: VARCHAR
* Int, 32-разрядный Integer. MSSQL: INT, ORACLE: INTEGER, POSTGRE: INTEGER
* BigInt, 64-разрядный Integer. MSSQL: BIGINT, ORACLE: NUMBER(19), POSTGRE: BIGINT
* Float, Double. MSSQL: FLOAT, ORACLE: NUMBER(19, 4), POSTGRE: NUMERIC(19, 4)
* Currency, Currency(4 знака после запятой). MSSQL: FLOAT, ORACLE: NUMBER(19, 2), POSTGRE: NUMERIC(19, 2)
* Boolean, Boolean. MSSQL: TINYINT, ORACLE: NUMBER(1), POSTGRE: SMALLINT
* DateTime, Дата и время в часовом поясе UTC. MSSQL: DATETIME, OARCLE: DATE, POSTGRE: TIMESTAMP WITH TIME ZONE
* Text, Строка большой длины. MSSQL: NVARCHAR(MAX), ORACLE: CLOB, POSTGRE: TEXT
* ID, 64-разрядный Integer. Типы аналогичны BigInt
* Entity, Ссылка на значение ID сущности. Типы аналогичны BigInt
* Document, Строка длиной 4000 или более. MSSQL: NVARCHAR(MAX), ORACLE: VARCHAR2(4000), POSTGRE: TEXT
* Many,
* TimeLog, Кол-во секунд от X даты, 64-разрядный Integer. MSSQL: BIGINT, ORACLE: NUMBER(19), POSTGRE: BIGINT
* Enum, Строка небольшой длины. MSSQL: NVARCHAR, ORACLE: NVARCHAR2, POSTGRE: VARCHAR
* BLOB, Бинарные данные. MSSQL: VARBINARY(MAX), ORACLE: BLOB, POSTGRE: BYTEA
* Date Дата в локальном часовом поясе.
* @property {String} dataType
* @readonly
*/
/**
* @property {String} associatedEntity
* Название сущности, на которую ссылаемся (для adtMany сущность, на которую ссылаемся из AssociationManyData)
* @readonly
*/
/**
* @property {String} associationAttr
* associationAttr
* @readonly
*/
/**
* @property {String} caption
* caption
* @readonly
*/
/**
* @property {String} description
* description
* @readonly
*/
/**
* @property {String} documentation
* documentation
* @readonly
*/
/**
* @property {Number} size
* size
* @readonly
*/
/**
* @property {boolean} allowNull
* Can the value of attribute to be null
* @readonly
*/
/**
* @property {boolean} allowSort
* Allow sort by this attribute
* @readonly
*/
/**
* @property {boolean} isUnique
* isUnique
* @readonly
*/
/**
* @property {String} defaultValue
* Default value
* @readonly
*/
/**
* @property {Boolean} readOnly
* Allow edit the value.
* @readonly
*/
/**
* @property {Boolean} isMultiLang
* isMultiLang.
* @readonly
*/
/**
* @property {Boolean} cascadeDelete
* cascadeDelete.
* Только для атрибутов типа adtEntity! Удалять ли связанные child-записи каскадно
* @readonly
*/
/**
* @property {String} documentMIME
* documentMIME.
* @readonly
*/
/**
* @property {String} enumGroup
* enumGroup.
* @readonly
*/
/**
* @property {Object} customSettings
* Custom settings
* @readonly
*/
/**
* @property {String} associationManyData
* Table name where stored values for attributes with type Many
* @readonly
*/
/**
* @property {String} storeName
* Store, where the files are stored (one of the stores from storeConfig of m3Config.json). Used for dataType: Document.
* If emtpy - server uses store with 'isDefault'=true
* @readonly
*/
_.assign(this, attributeInfo);
if (i18n){
_.assign(this, i18n);
}
/**
* @property {String} physicalDataType
* @readonly
*/
this.physicalDataType = UBDomain.getPhysicalDataType(this.dataType || 'String');
}
// defaults
UBEntityAttribute.prototype.caption = ''; //possible for service(mixin) attributes
UBEntityAttribute.prototype.description = '';
UBEntityAttribute.prototype.documentation = '';
UBEntityAttribute.prototype.size = 0;
UBEntityAttribute.prototype.allowNull = true; // Boolean; { Может ли значение атрибута быть null }
UBEntityAttribute.prototype.allowSort = true; // Boolean; { Можно ли сортировать по этому атрибуту }
UBEntityAttribute.prototype.isUnique = false;
UBEntityAttribute.prototype.defaultView = true; // Boolean; { True = атрибут участвует в автопостроителе форм и появляется в запросах '*' }
UBEntityAttribute.prototype.readOnly = false; // Boolean; { Может ли клиент редактировать этот атрибут }
UBEntityAttribute.prototype.isMultiLang = false;
UBEntityAttribute.prototype.cascadeDelete = false;
UBEntityAttribute.prototype.customSettings = {};
UBEntityAttribute.prototype.dataType = 'String';
/**
* @property associatedEntity
* @type {string}
*/
UBEntityAttribute.prototype.associatedEntity = '';
/**
* Return associated entity. Return null if attribute type is not Entity.
* @returns {UBEntity}
*/
UBEntityAttribute.prototype.getAssociatedEntity = function(){
if (this.associatedEntity){
return this.entity.domain.get(this.associatedEntity);
}
return null;
};
UBEntityAttribute.prototype.asJSON = function(){
var me = this, result = {};
_.forEach(me, function(prop, propName){
if (propName === 'entity'){
return;
}
if (prop.asJSON){
result[propName] = prop.asJSON();
} else {
result[propName] = prop;
}
});
return result;
};
/**
* Contains all properties defined in mixin section of a entity metafile
* @class
* @protected
* @param {Object} mixinInfo
* @param {Object} i18n
* @param {String} mixinCode
*/
function UBEntityMixin(mixinInfo, i18n, mixinCode){
/**
* Mixin code
* @type {String}
*/
this.code = mixinCode;
_.assign(this, mixinInfo);
if (i18n){
_.assign(this, i18n);
}
}
UBEntityMixin.prototype.enabled = true;
/**
* Mixin for persisting entity to a database
* @class
* @extends UBEntityMixin
* @param mixinInfo
* @param i18n
* @param mixinCode
*/
function UBEntityStoreMixin(mixinInfo, i18n, mixinCode){
UBEntityMixin.apply(this, arguments);
}
UBEntityStoreMixin.prototype = Object.create(UBEntityMixin.prototype);
UBEntityStoreMixin.prototype.constructor = UBEntityStoreMixin;
// defaults
/**
* Is `simpleAudit` enabled
* @type {boolean}
*/
UBEntityStoreMixin.prototype.simpleAudit = false;
/**
* Use a soft delete
* @type {boolean}
*/
UBEntityStoreMixin.prototype.safeDelete = false;
/**
* Historical data storage mixin
* @class
* @extends UBEntityMixin
* @param mixinInfo
* @param i18n
* @param mixinCode
* @constructor
*/
function UBEntityHistoryMixin(mixinInfo, i18n, mixinCode){
UBEntityMixin.apply(this, arguments);
}
UBEntityHistoryMixin.prototype = Object.create(UBEntityMixin.prototype);
UBEntityHistoryMixin.prototype.constructor = UBEntityHistoryMixin;
/**
* A history storage strategy
* @type {string}
*/
UBEntityHistoryMixin.prototype.historyType = 'common';
/**
* Access control list mixin
* @class
* @extends UBEntityMixin
* @param mixinInfo
* @param i18n
* @param mixinCode
*/
function UBEntityAclRlsMixin(mixinInfo, i18n, mixinCode){
UBEntityMixin.apply(this, arguments);
}
UBEntityAclRlsMixin.prototype = Object.create(UBEntityMixin.prototype);
UBEntityAclRlsMixin.prototype.constructor = UBEntityAclRlsMixin;
// defaults
UBEntityAclRlsMixin.prototype.aclRlsUseUnityName = false;
UBEntityAclRlsMixin.prototype.aclRlsSelectionRule = 'exists';
/**
* Full text search mixin
* @class
* @extends UBEntityMixin
* @param mixinInfo
* @param i18n
* @param mixinCode
*/
function UBEntityFtsMixin(mixinInfo, i18n, mixinCode){
UBEntityMixin.apply(this, arguments);
}
UBEntityFtsMixin.prototype = Object.create(UBEntityMixin.prototype);
UBEntityFtsMixin.prototype.constructor = UBEntityFtsMixin;
/**
* scope
* @type {string}
*/
UBEntityFtsMixin.prototype.scope = 'connection'; //sConnection
/**
* Data provider type
* @type {string}
*/
UBEntityFtsMixin.prototype.dataProvider = 'mixin';//dcMixin
/**
* Attribute level security mixin
* @param mixinInfo
* @param i18n
* @param mixinCode
* @constructor
* @extends UBEntityMixin
*/
function UBEntityAlsMixin(mixinInfo, i18n, mixinCode){
UBEntityMixin.apply(this, arguments);
}
UBEntityAlsMixin.prototype = Object.create(UBEntityMixin.prototype);
UBEntityAlsMixin.prototype.constructor = UBEntityAlsMixin;
/**
* Is optimistic
* @type {boolean}
*/
UBEntityAlsMixin.prototype.alsOptimistic = true;
module.exports = UBDomain;