'use strict';
var CLASS_NAME = 'ExtensionManager';
var config = require('./configuration-reader.js');
var Argument = require('../system/argument-check.js');
var ModelError = require('./model-error.js');
/**
* @classdesc
* Provides properties to customize models' behavior.
* @description
* Creates a new base extension manager object.
*
* @memberof bo.shared
* @constructor
* @param {string} dataSource - The name of the data source.
* @param {string} modelPath - The full path of the model.
* @param {number} addArgs - The count of additional arguments for data portal methods of a model group.
*
* @throws {@link bo.system.ArgumentError Argument error}: The data source must be a non-empty string.
* @throws {@link bo.system.ArgumentError Argument error}: The model path must be a non-empty string.
* @throws {@link bo.system.ArgumentError Argument error}: The additional argument count must be an integer.
*/
function ExtensionManagerBase(dataSource, modelPath, addArgs) {
var check = Argument.inConstructor(CLASS_NAME);
/**
* The name of the data source.
* @type {string}
* @readonly
*/
this.dataSource = check(dataSource).forMandatory('dataSource').asString();
/**
* The path of the model definition.
* @type {string}
* @readonly
*/
this.modelPath = check(modelPath).forMandatory('modelPath').asString();
addArgs = check(addArgs).forMandatory('addArgs').asInteger();
var self = this;
var methods = {};
var definitions = [
{ name: 'daoBuilder', length: 3 },
{ name: 'toDto', length: 1 },
{ name: 'fromDto', length: 2 },
{ name: 'toCto', length: 1 },
{ name: 'fromCto', length: 2 },
{ name: 'dataCreate', length: 0 + addArgs },
{ name: 'dataFetch', length: 2 + addArgs },
{ name: 'dataInsert', length: 0 + addArgs },
{ name: 'dataUpdate', length: 0 + addArgs },
{ name: 'dataRemove', length: 0 + addArgs },
{ name: 'dataExecute', length: 1 + addArgs }
];
/**
* Factory method to create the data access object for a model instance.
* @name bo.shared.ExtensionManagerBase#daoBuilder
* @type {external.daoBuilder}
* @readonly
*/
/**
* Converts the model instance to data transfer object.
* @name bo.shared.ExtensionManagerBase#toDto
* @type {external.toDto}
* @readonly
*/
/**
* Converts the data transfer object to model instance.
* @name bo.shared.ExtensionManagerBase#fromDto
* @type {external.fromDto}
* @readonly
*/
/**
* Converts the model instance to client transfer object.
* @name bo.shared.ExtensionManagerBase#toCto
* @type {external.toCto}
* @readonly
*/
/**
* Converts the client transfer object to model instance.
* @name bo.shared.ExtensionManagerBase#fromCto
* @type {external.fromCto}
* @readonly
*/
/**
* Returns the property values of a new instance from the data source.
* @name bo.shared.ExtensionManagerBase#dataCreate
* @type {external.dataCreate}
* @readonly
*/
/**
* Returns the property values of an existing instance from the data source.
* @name bo.shared.ExtensionManagerBase#dataFetch
* @type {external.dataFetch}
* @readonly
*/
/**
* Saves a new instance into the data source.
* @name bo.shared.ExtensionManagerBase#dataInsert
* @type {external.dataInsert}
* @readonly
*/
/**
* Saves an existing instance into the data source.
* @name bo.shared.ExtensionManagerBase#dataUpdate
* @type {external.dataUpdate}
* @readonly
*/
/**
* Deletes an existing instance from the data source.
* @name bo.shared.ExtensionManagerBase#dataRemove
* @type {external.dataRemove}
* @readonly
*/
/**
* Executes a command on the data source.
* @name bo.shared.ExtensionManagerBase#dataExecute
* @type {external.dataExecute}
* @readonly
*/
definitions.map(function(definition) {
methods[definition.name] = null;
Object.defineProperty(self, definition.name, {
get: function () {
return methods[definition.name];
},
set: function (value) {
if (value && typeof value === 'function' && value.length == definition.length)
methods[definition.name] = value;
else
switch (definition.length) {
case 0:
throw new ModelError('propertyArg0', CLASS_NAME, definition.name);
case 1:
throw new ModelError('propertyArg1', CLASS_NAME, definition.name);
default:
throw new ModelError('propertyArgN', CLASS_NAME, definition.name, definition.length);
}
},
enumerable: true
});
});
//region Command object extensions
var otherMethods = [];
/**
* Adds a new instance method to the model.
* (The method will call a custom execute method on the data business object
* of command object.)
*
* @function bo.shared.ExtensionManagerBase#addOtherMethod
* @param {string} methodName - The name of the method on the data access object to be called.
*/
this.addOtherMethod = function (methodName) {
otherMethods.push(Argument.inMethod(CLASS_NAME, 'addOtherMethod')
.check(methodName).forMandatory('methodName').asString());
};
/**
* Instantiate the defined custom methods on the model instance.
* (The method is currently used by command objects only.)
*
* @function bo.shared.ExtensionManagerBase#buildOtherMethods
* @protected
* @param {ModelBase} instance - An instance of the model.
* @param {boolean} isSync - Indicates whether the model is synchronous or asynchronous.
*/
this.buildOtherMethods = function (instance, isSync) {
if (otherMethods) {
if (isSync)
otherMethods.map(function (methodName) {
instance[methodName] = function () {
instance.execute(methodName);
};
});
else
otherMethods.map(function (methodName) {
instance[methodName] = function (callback) {
instance.execute(methodName, callback);
};
});
}
};
//endregion
/**
* Gets the data access object instance of the model.
*
* @function bo.shared.ExtensionManagerBase#getDataAccessObject
* @protected
* @param {string} modelName - The name of the model.
* @returns {bo.dataAccess.DaoBase} The data access object instance of the model.
*/
this.getDataAccessObject = function (modelName) {
return self.daoBuilder ?
self.daoBuilder(dataSource, modelPath, modelName) :
config.daoBuilder(dataSource, modelPath, modelName);
};
// Immutable object.
Object.freeze(this);
}
module.exports = ExtensionManagerBase;