UNPKG

@themost/data

Version:

MOST Web Framework Codename Blueshift - Data module

122 lines (120 loc) 5.4 kB
// MOST Web Framework 2.0 Codename Blueshift BSD-3-Clause license Copyright (c) 2017-2022, THEMOST LP All rights reserved var Q = require('q'); var _ = require('lodash'); var {DataError} = require('@themost/common'); var {DataObjectJunction} = require('./data-object-junction'); require('@themost/promise-sequence'); function ZeroOrOneMultiplicityListener() { // } /** * @param {DataEventArgs} event * @param {Function(Error=)} callback */ ZeroOrOneMultiplicityListener.prototype.afterSave = function(event, callback) { var afterSaveAsync = ZeroOrOneMultiplicityListener.prototype.afterSaveAsync.bind(this); return afterSaveAsync(event).then(function() { return callback(); }).catch(function(err) { return callback(err); }); } /** * @param {DataEventArgs} event * @return {Promise<void>} */ ZeroOrOneMultiplicityListener.prototype.afterSaveAsync = function(event) { return Q.Promise(function(resolve, reject) { // get attributes that defines an zero or one multiplicity association // with this context model var attributes = _.filter(event.model.attributes, function(attribute) { if (Object.prototype.hasOwnProperty.call(event.target, attribute.name) === false) { return false; } if (attribute.mapping == null) { return false; } // get mapping var mapping = event.model.inferMapping(attribute.name); return !attribute.nested && //exclude nested attributes attribute.multiplicity === 'ZeroOrOne' && // validate multiplicity mapping.associationType === 'junction' && // and association type mapping.parentModel === event.model.name ; }); if (attributes.length === 0) { // do nothing return resolve(); } var sources = _.map(attributes, function(attribute) { return function() { return Q.Promise(function(_resolve, _reject) { // exclude readonly attributes if (Object.prototype.hasOwnProperty.call(attribute, 'readonly')) { if (attribute.readonly) { return _resolve(); } } // exclude non-editable attributes while updating object if (Object.prototype.hasOwnProperty.call(attribute, 'editable') && event.state === 2) { if (!attribute.editable) { return _resolve(); } } const child = event.target[attribute.name]; var context = event.model.context; // get target var target = event.model.convert(event.target); // get attribute mapping var mapping = event.model.inferMapping(attribute.name); // force set refersTo if (mapping && mapping.refersTo == null) { mapping.refersTo = attribute.name; } // get association def var association = new DataObjectJunction(target, mapping); if (child != null) { // get silent model of parent model var silent = event.model.isSilent(); // find child var childModel = context.model(mapping.childModel); return childModel.silent(silent).find(child).getItem().then(function(item) { if (item == null) { return _reject(new DataError('EDATA','An associated object cannot be found.',null, event.model.name, attribute.name)); } // try to create association between parent and child return association.silent(silent).insert(item).then(function() { return _resolve(); }); }).catch(function(err) { return _reject(err); }); } else { // remove zero or one association // get item return association.silent(silent).getItem().then(function(item) { // if child already exists remove association if (item) { return association.silent(silent).remove(item).then(function() { return _resolve(); }); } // otherwise do nothing return _resolve(); }).catch(function(err) { return _reject(err); }); } }); } }); // execute all promises Promise.sequence(sources).then(function() { return resolve(); }).catch(function(err) { return reject(err); }); }); } module.exports = { ZeroOrOneMultiplicityListener };