"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.updateRelationshipSets = updateRelationshipSets;
var _isEmpty2 = _interopRequireDefault(require("lodash/isEmpty"));
var _omit2 = _interopRequireDefault(require("lodash/omit"));
var _uniq2 = _interopRequireDefault(require("lodash/uniq"));
var _set = require("./set");
var _util = require("../util");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/*
* Copyright (C) 2018 Ben Ockmore
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
function getAffectedBBIDs(addedItems, removedItems) {
const affectedSourceBBIDs = [...addedItems, ...removedItems].map(relationship => relationship.sourceBbid);
const affectedTargetBBIDs = [...addedItems, ...removedItems].map(relationship => relationship.targetBbid);
return (0, _uniq2.default)([...affectedSourceBBIDs, ...affectedTargetBBIDs]);
}
async function getMasterRelationshipSetForEntity(orm, transacting, bbid) {
const {
Entity,
Author,
Edition,
EditionGroup,
Publisher,
RelationshipSet,
Series,
Work
} = orm;
const entityHeader = await Entity.forge({
bbid
}).fetch({
require: true,
transacting
});
const typeModelMap = {
Author,
Edition,
EditionGroup,
Publisher,
Series,
Work
};
// Extract entity type
const type = entityHeader.get('type');
// Fetch master revision of entity
const entity = await typeModelMap[type].forge({
bbid
}).fetch({
require: false,
transacting
});
if (!entity) {
return null;
}
const relationshipSetId = entity.get('relationshipSetId');
if (!relationshipSetId) {
return null;
}
// Return relationship set
return RelationshipSet.forge({
id: relationshipSetId
}).fetch({
require: true,
transacting,
withRelated: ['relationships']
});
}
async function updateRelationshipSetForEntity(orm, transacting, bbid, allAddedItems, allRemovedItems, comparisonFunc) {
const {
RelationshipSet
} = orm;
const oldSet = await getMasterRelationshipSetForEntity(orm, transacting, bbid);
const oldSetItems = oldSet ? oldSet.related('relationships').toJSON() : [];
const addedItems = allAddedItems.filter(relationship => relationship.sourceBbid === bbid || relationship.targetBbid === bbid);
const unchangedItems = (0, _set.removeItemsFromSet)(oldSetItems, allRemovedItems, comparisonFunc);
return (0, _set.createNewSetWithItems)(orm, transacting, RelationshipSet, unchangedItems, addedItems, 'relationships');
}
/**
* Takes an array of relationships that should be set for the entity, and
* compares it to the currently set list of relationships to determine the
* difference. Compiles a list of affected entity BBIDs from this difference,
* and then updates the relationship sets for all affected entities, and returns
* these. If no entities are affected (there are no changes), an empty object
* is returned.
*
* @param {ORM} orm - an initialized instance of bookbrainz-data-js
* @param {Transaction} transacting - the current transaction
* @param {any} oldSet - the RelationshipSet object for the old entity data
* @param {Array<Relationship>} newSetItems - the edited RelationshipSet for the
* entity
*
* @returns {Promise<any>} a promise which resolves to a {BBID: RelationshipSet}
* map
*/
function updateRelationshipSets(orm, transacting, oldSet, newSetItems) {
function comparisonFunc(obj, other) {
return obj.typeId === other.typeId && obj.sourceBbid === other.sourceBbid && obj.targetBbid === other.targetBbid && obj.attributeSetId === other.attributeSetId;
}
const allAddedItems = newSetItems.filter(rel => rel.isAdded).map(rel => (0, _omit2.default)(rel, ['isRemoved', 'isAdded']));
const allRemovedItems = newSetItems.filter(rel => rel.isRemoved).map(rel => (0, _omit2.default)(rel, ['isRemoved', 'isAdded']));
if ((0, _isEmpty2.default)(allAddedItems) && (0, _isEmpty2.default)(allRemovedItems)) {
// No action - set has not changed
return Promise.resolve({});
}
const affectedBBIDs = getAffectedBBIDs(allAddedItems, allRemovedItems);
// For each BBID, get the entity and the old relationship set, then apply
// the relevant changes to create a new set.
const newSetPromises = affectedBBIDs.reduce((result, bbid) => ({
...result,
[bbid]: updateRelationshipSetForEntity(orm, transacting, bbid, allAddedItems, allRemovedItems, comparisonFunc)
}), {});
return (0, _util.promiseProps)(newSetPromises);
}