/** * @abstract */ Ext.define("Terrasoft.manager.ObjectManager", { extend: "Terrasoft.manager.BaseManager", alternateClassName: "Terrasoft.ObjectManager", // region Properties: Private /** * If true then removes duplicated rows. * @property {Boolean} isDistinct * @deprecated */ isDistinct: false, /** * Entity schema name. * @private * @property {String} entitySchemaName */ entitySchemaName: null, /** * Entity schema. * @private * @property {Terrasoft.BaseEntitySchema} entitySchema */ entitySchema: null, /** * Manager item class name. * @private * @property {String} itemClassName */ itemClassName: "Terrasoft.ObjectManagerItem", /** * Properties to columns mapping. * @private * @property {Object} propertyColumnNames */ propertyColumnNames: null, /** * Properties to columns mapping config. * @private * @property {Object} propertyColumnConfig */ propertyColumnConfig: null, /** * Initialization property. * @private * @property {Boolean} initialized */ initialized: false, /** * Indicates whether manager is in initialization process. * @private * @property {Boolean} _initializing */ _initializing: false, /** * Properties to columns default mapping. * @private * @property {Object} defaultPropertyColumnNames */ defaultPropertyColumnNames: { id: "Id" }, // endregion // region Properties: Protected /** * Lazy loading property names. * @protected * @property {Array} lazyLoadingProperties * */ lazyLoadingProperties: null, // endregion // region Constructor: Public /** * Creates object instance. * @constructor * @param {Object} config Configuration object. */ constructor: function (config) { this.callParent([config]); this.propertyColumnNames = Ext.apply(this.propertyColumnNames || {}, this.defaultPropertyColumnNames); }, // endregion // region Methods: Private /** * Executes action over columns config. * @private * @param {Function} action Action to execute. * @param {Object} scope Action scope; */ _forEachColumn: function (action, scope) { var config = this.propertyColumnConfig || {}; Terrasoft.each(this.propertyColumnNames, function (name, key) { var columnConfig = config[key]; action.call(scope, name, key, columnConfig); }); }, /** * Returns columns info collection. * @private * @return {Array} Columns info. */ _getColumnsInfo: function () { var result = []; this._forEachColumn(function (name, key, config) { var columnInfo = Ext.apply({}, config); columnInfo.columnName = name; columnInfo.columnKey = key; result.push(columnInfo); }, this); return result; }, /** * Returns columns config. * @private * @returns {Object} Columns config. */ _getEntityColumnsConfig: function () { var result = null; this._forEachColumn(function (name, key, config) { if (!Ext.isEmpty(config)) { result = result || {}; result[name] = { dataValueType: config.columnDataValueType }; } }, this); return result; }, /** * Returns columns by properties. * @private * @param {Array} properties Properties. * @return {Array} Data manager columns. */ getColumnsByProperties: function (properties) { if (!Ext.isEmpty(properties)) { var propertyColumnNames = this.propertyColumnNames; return properties.map(function (propertyName) { return propertyColumnNames[propertyName]; }); } return null; }, /** * Init manager items. * @private * @param {Terrasoft.Collection} dataManagerItemCollection Manager items collection. */ initManagerItems: function (dataManagerItemCollection) { dataManagerItemCollection.each(function (dataManagerItem) { var itemId = dataManagerItem.getId(); var item = this.createManagerItem({ id: itemId, dataManagerItem: dataManagerItem }); this.addItem(item); }, this); }, /** * Subscribes on managerInitialized event. * @private * @param {Function} callback Callback function. * @param {Object} scope Callback function context. */ _subscribeOnInitializedEvent: function (callback, scope) { this.on("managerInitialized", function () { Ext.callback(callback, scope); }, this, { single: true }); }, //endregion // region Methods: Protected /** * @deprecated */ initializeManger: function () { this.log(Ext.String.format(Terrasoft.Resources.ObsoleteMessages.ObsoleteMethodMessage, "initializeManger", "initializeManager"), Terrasoft.LogMessageType.WARNING); this.initializeManager.apply(this, arguments); }, /** * Initialize manager. * @protected * @param {Object} config Configuration object. * @param {Function} callback Callback function. * @param {Object} scope Callback function context. */ initializeManager: function (config, callback, scope) { config = Ext.apply({ entitySchemaName: this.entitySchemaName, lazyLoadingColumns: this.getColumnsByProperties(this.lazyLoadingProperties), columnsInfo: this._getColumnsInfo() }, config); Terrasoft.chain(function (next) { this.initializeEntitySchema(next, this); }, function (next) { Terrasoft.DataManager.select(config, next, this); }, function (next, dataManagerItemCollection) { this.initManagerItems(dataManagerItemCollection); this.initialized = true; this.isOutdated = false; Ext.callback(callback, scope || this); }, this); }, /** * Init entity schema of manager. * @protected * @param {Function} callback The callback function. * @param {Object} scope The scope of callback function. */ initializeEntitySchema: function (callback, scope) { Terrasoft.require([this.entitySchemaName], function (entitySchema) { this.entitySchema = entitySchema; callback.call(scope); }, this); }, /** * Checks is manager initialized or not. * @protected * @throws {Terrasoft.InvalidObjectState} */ checkIsInitialized: function () { if (!this.initialized) { throw new Terrasoft.InvalidObjectState({ message: Terrasoft.Resources.Managers.Exceptions.ManagerIsNotInitialized }); } }, /** * Creates config object. * @protected * @param {Object} config Config object. * @return {Object} Resulted config object. */ getInitConfig: function (config) { return config; }, /** * Returns name for package schema data for item. * @protected * @param {Terrasoft.ObjectManagerItem} item Object manager item. * @return {String} */ getPackageSchemaDataName: function (item) { var itemId = item.getPropertyValue("id"); var className = this.alternateClassName.replace("Terrasoft.", ""); var dataName = Ext.String.format("{0}_{1}_{2}", this.entitySchemaName, className, itemId.replace(/-/g, "")); return dataName; }, /** * Updates schema data in package. * @protected * @param {String} packageUId Package UId. * @param {Terrasoft.Collection} items Manager items. * @param {Function} callback Callback function. * @param {Object} scope Callback function scope. */ updatePackageSchemaData: function (packageUId, items, callback, scope) { var updatePackageSchemaDataChain = []; items.each(function (item) { var itemId = item.getPropertyValue("id"); updatePackageSchemaDataChain.push(function (next) { var config = { entitySchemaName: this.entitySchemaName, recordList: [itemId], packageUId: packageUId, packageSchemaDataName: this.getPackageSchemaDataName(item), entitySchema: Terrasoft[this.entitySchemaName] }; var request = Ext.create("Terrasoft.UpdatePackageSchemaDataRequest", config); request.execute(function (response) { if (response && response.success) { next(); } else { throw new Terrasoft.InvalidOperationException({ message: response.errorInfo.toString() }); } }, this); }); }, this); updatePackageSchemaDataChain.push(function () { callback.call(scope); }); updatePackageSchemaDataChain.push(this); Terrasoft.chain.apply(this, updatePackageSchemaDataChain); }, /** * Removes package schema data. * @protected * @param {Terrasoft.Collection} items Manager items. * @param {String} packageUId Package UId. * @return {Promise} Delete package schema data promise object. */ deletePackageSchemaData: function (items, packageUId) { var promiseChain = items.mapArray(function (item) { var packageSchemaDataName = this.getPackageSchemaDataName(item); return new Promise(function (resolve, reject) { var request = Ext.create("Terrasoft.DeletePackageSchemaDataRequest", { packageSchemaDataName: packageSchemaDataName, packageUId: packageUId }); request.execute(function (response) { if (response && response.success) { resolve(); } else { reject(response && response.errorInfo); } }, this); }); }, this); return Promise.all(promiseChain).catch(function (errorInfo) { throw new Terrasoft.InvalidOperationException({ message: errorInfo && errorInfo.toString() }); }); }, /** * Unsubscribes from events for all manager items. * @protected */ unsubscribeEvents: function () { this.items.each(function (item) { item.un("remove", this.onRemoveManagerItem, this); }, this); }, // endregion //region Methods: Public /** * @inheritdoc Terrasoft.manager.BaseManager#createManagerItem * @override */ createManagerItem: function (config) { if (this.propertyColumnNames) { Ext.apply(config, { propertyColumnNames: this.propertyColumnNames, lazyLoadingProperties: this.lazyLoadingProperties }); } return this.callParent(arguments); }, /** * @inheritdoc Terrasoft.manager.BaseManager#findItem * @override */ findItem: function () { this.checkIsInitialized(); return this.callParent(arguments); }, /** * @inheritdoc Terrasoft.manager.BaseManager#getItem * @override */ getItem: function () { this.checkIsInitialized(); return this.callParent(arguments); }, /** * @inheritdoc Terrasoft.manager.BaseManager#remove * @override */ remove: function () { this.checkIsInitialized(); this.callParent(arguments); }, /** * @inheritdoc Terrasoft.manager.BaseManager#getItems * @override */ getItems: function () { this.checkIsInitialized(); return this.callParent(arguments); }, /** * @inheritdoc Terrasoft.manager.BaseManager#clear * @override */ clear: function () { var dataStore = Terrasoft.DataManager.getDataStore(); delete dataStore[this.entitySchemaName]; this.callParent(arguments); }, /** * @inheritdoc Terrasoft.core.BaseObject#onDestroy * @override */ onDestroy: function () { this.unsubscribeEvents(); this.callParent(arguments); }, /** * Generates object with parameters for manager element properties. * @return {Object} */ getPropertiesAttributes: function () { if (!this.entitySchema) { return null; } var entitySchemaColumns = this.entitySchema.columns; var properties = {}; Terrasoft.each(this.propertyColumnNames, function (columnName, propertyName) { properties[propertyName] = Terrasoft.deepClone(entitySchemaColumns[columnName]); Ext.apply(properties[propertyName], { columnPath: propertyName, name: propertyName }); }, this); return properties; }, /** * Init manager items. * @param {Object} [config] Config object. * @param {Function} callback The callback function. * @param {Object} scope The scope of callback function. */ initialize: function (config, callback, scope) { if (Ext.isFunction(config)) { scope = callback || this; callback = config; config = null; } scope = scope || this; if (this.initialized) { if (this.isOutdated) { this.reInitialize(config, callback, scope); } else { callback.call(scope); } return; } this._subscribeOnInitializedEvent(callback, scope); if (this._initializing) { return; } this._initializing = true; var initConfig = this.getInitConfig(config); this.initializeManager(initConfig, function () { this._initializing = false; this.fireEvent("managerInitialized"); }, this); }, /** * Add item method. * @param {Terrasoft.BaseManagerItem} item Element. * @return {Terrasoft.BaseManagerItem} Added item. */ addItem: function (item) { var resultItem = this.callParent([item]); var dataManagerItem = resultItem.getDataManagerItem(); Terrasoft.DataManager.addItem(dataManagerItem); return resultItem; }, /** * Discard item changes. * @param {Terrasoft.DataManagerItem} item Data manager element. * @return {Terrasoft.DataManagerItem} Data manager element. */ discardItem: function (item) { if (item.getIsNew()) { if (item.dataManagerItem) { var dataManagerItem = item.dataManagerItem; Terrasoft.DataManager.discardItem(dataManagerItem); } this.items.remove(item); } else { item.discard(); } return item; }, /** * Save changes of manager elements. * @param {Function} callback The callback function. * @param {Object} scope The scope of callback function. */ save: function (callback, scope) { this.callParent(arguments); Terrasoft.DataManager.save({ entitySchemaNames: [this.entitySchemaName] }, callback, scope); }, /** * Save changes of manager elements. * @param {String} packageUId Package identifier. * @param {Function} callback The callback function. * @param {Object} scope The scope of callback function. */ saveAndUpdateSchemaData: function (packageUId, callback, scope) { var changedItems = this.items.filterByFn(function (item) { return (item.getIsNew() || item.getIsChanged()) && !item.getIsDeleted(); }, this); var deletedItems = this.items.filterByFn(function (item) { return !item.getIsNew() && item.getIsChanged() && item.getIsDeleted(); }); Terrasoft.chain(function (next) { this.save(next, this); }, function (next) { this.updatePackageSchemaData(packageUId, changedItems, next, this); }, function (next) { this.deletePackageSchemaData(deletedItems, packageUId).then(next); }, function () { this.notify(this.outdatedEventName); callback.call(scope); }, this); }, /** * Discard manager items changes. */ discard: Terrasoft.abstractFn, /** * Create manager item. * @param {Object} config Config object. * @param {Terrasoft.DataManagerItem} [config.dataManagerItem] Optional DataManagerItem, uses for new manager item. * @param {Object} [config.propertyValues] Uses for create item when dataManagerItem not defined. * @param {Function} callback The callback function. * @param {Terrasoft.ObjectManagerItem} callback.objectManagerItem Created object manager item. * @param {Object} scope The scope of callback function. */ createItem: function (config, callback, scope) { scope = scope || this; var objectManagerItem; if (config && config.dataManagerItem) { objectManagerItem = this.createManagerItem(config); callback.call(scope, objectManagerItem); } else { var createConfig = { entitySchemaName: this.entitySchemaName }; var columnsConfig = this._getEntityColumnsConfig(); if (columnsConfig) { createConfig.columns = columnsConfig; } var createCallback = function (dataManagerItem) { objectManagerItem = this.createManagerItem({ dataManagerItem: dataManagerItem }); var propertyValues = config && config.propertyValues; Terrasoft.each(propertyValues, function (propertyValue, propertyName) { objectManagerItem.setPropertyValue(propertyName, propertyValue); }, this); callback.call(scope, objectManagerItem); }; Terrasoft.DataManager.createItem(createConfig, createCallback, this); } }, /** * Resets and initializes manager. * @param {Object} [config] Optional, configuration object. * @param {Function} callback The callback function. * @param {Object} scope The scope for the callback. */ reInitialize: function (config, callback, scope) { if (arguments.length === 2 && Ext.isFunction(config)) { scope = callback; callback = config; config = null; } this.clear(); this.initialized = false; this.initialize(config, callback, scope); } // endregion });