UNPKG

objection

Version:
348 lines (258 loc) 30.5 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = undefined; var _create = require('babel-runtime/core-js/object/create'); var _create2 = _interopRequireDefault(_create); var _keys = require('babel-runtime/core-js/object/keys'); var _keys2 = _interopRequireDefault(_keys); var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _lodash = require('lodash'); var _lodash2 = _interopRequireDefault(_lodash); var _bluebird = require('bluebird'); var _bluebird2 = _interopRequireDefault(_bluebird); var _DependencyGraph = require('./DependencyGraph'); var _DependencyGraph2 = _interopRequireDefault(_DependencyGraph); var _TableInsertion = require('./TableInsertion'); var _TableInsertion2 = _interopRequireDefault(_TableInsertion); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var GraphInserter = function () { function GraphInserter(_ref) { var modelClass = _ref.modelClass, models = _ref.models, allowedRelations = _ref.allowedRelations, knex = _ref.knex; (0, _classCallCheck3.default)(this, GraphInserter); /** * @type {Constructor.<Model>} */ this.modelClass = modelClass; /** * @type {Model|Array.<Model>} */ this.models = models; /** * @type {RelationExpression} */ this.allowedRelations = allowedRelations || null; /** * @type {boolean} */ this.done = false; /** * @type {DependencyGraph} */ this.graph = this._buildDependencyGraph(); /** * @type {knex} */ this.knex = knex; } /** * @param {function(TableInsertion)} inserter * @return {Promise} */ GraphInserter.prototype.execute = function execute(inserter) { return this._executeNextBatch(inserter); }; /** * @returns {DependencyGraph} * @private */ GraphInserter.prototype._buildDependencyGraph = function _buildDependencyGraph() { var graph = new _DependencyGraph2.default(this.allowedRelations); graph.build(this.modelClass, this.models); return graph; }; /** * @param {function(TableInsertion)} inserter * @returns {Promise} * @private */ GraphInserter.prototype._executeNextBatch = function _executeNextBatch(inserter) { var _this = this; var batch = this._nextBatch(); if (!batch) { // If we get here, we are done. All we need to do now is to finalize the object graph // and return it as the final output. return this._finalize(); } // Insert the batch using the `inserter` function. return _bluebird2.default.all((0, _keys2.default)(batch).map(function (tableName) { var tableInsertion = batch[tableName]; var uids = void 0; if (!tableInsertion.isJoinTableInsertion) { // We need to omit the uid properties so that they don't get inserted // into the database. Join table insertions never have uids. uids = _this._omitUids(tableInsertion); } return inserter(tableInsertion).then(function () { if (!tableInsertion.isJoinTableInsertion) { // Resolve dependencies to the inserted objects. Join table insertions // never resolve any dependencies. _this._resolveDepsForInsertion(tableInsertion, uids); } }); })).then(function () { return _this._executeNextBatch(inserter); }); }; /** * @private * @returns {Object.<string, TableInsertion>} */ GraphInserter.prototype._nextBatch = function _nextBatch() { if (this.done) { return null; } var batch = this._createBatch(); if (_lodash2.default.isEmpty(batch)) { this.done = true; return this._createManyToManyRelationJoinRowBatch(); } else { this._markBatchHandled(batch); return batch; } }; /** * @private * @returns {Object.<string, TableInsertion>} */ GraphInserter.prototype._createBatch = function _createBatch() { var batch = (0, _create2.default)(null); var nodes = this.graph.nodes; for (var n = 0, ln = nodes.length; n < ln; ++n) { var node = nodes[n]; if (!node.handled && node.needs.length === node.numHandledNeeds) { var tableInsertion = batch[node.modelClass.tableName]; if (!tableInsertion) { tableInsertion = new _TableInsertion2.default(node.modelClass, false); batch[node.modelClass.tableName] = tableInsertion; } tableInsertion.models.push(node.model); tableInsertion.isInputModel.push(!!this.graph.inputNodesById[node.id]); } } return batch; }; /** * @private * @param {Object.<string, TableInsertion>} batch */ GraphInserter.prototype._markBatchHandled = function _markBatchHandled(batch) { var models = _lodash2.default.flatten(_lodash2.default.map(batch, 'models')); var nodes = this.graph.nodesById; for (var m = 0, lm = models.length; m < lm; ++m) { var id = models[m][models[m].constructor.uidProp]; var node = nodes[id]; for (var nb = 0, lnb = node.isNeededBy.length; nb < lnb; ++nb) { var dep = node.isNeededBy[nb]; dep.node.numHandledNeeds++; } node.handled = true; } }; /** * @private * @returns {Object.<string, TableInsertion>} */ GraphInserter.prototype._createManyToManyRelationJoinRowBatch = function _createManyToManyRelationJoinRowBatch() { var batch = (0, _create2.default)(null); for (var n = 0, ln = this.graph.nodes.length; n < ln; ++n) { var node = this.graph.nodes[n]; for (var m = 0, lm = node.manyToManyConnections.length; m < lm; ++m) { var conn = node.manyToManyConnections[m]; var tableInsertion = batch[conn.relation.joinTable]; var ownerProp = node.model.$values(conn.relation.ownerProp); var modelClass = conn.relation.joinTableModelClass(this.knex); var joinModel = conn.relation.createJoinModels(ownerProp, [conn.node.model])[0]; if (conn.refNode) { // Also take extra properties from the referring model, it there was one. for (var k = 0, lk = conn.relation.joinTableExtras.length; k < lk; ++k) { var extra = conn.relation.joinTableExtras[k]; if (!_lodash2.default.isUndefined(conn.refNode.model[extra.aliasProp])) { joinModel[extra.joinTableProp] = conn.refNode.model[extra.aliasProp]; } } } joinModel = modelClass.fromJson(joinModel); if (!tableInsertion) { tableInsertion = new _TableInsertion2.default(modelClass, true); batch[modelClass.tableName] = tableInsertion; } tableInsertion.models.push(joinModel); tableInsertion.isInputModel.push(false); } } var modelNames = (0, _keys2.default)(batch); // Remove duplicates. for (var i = 0, l = modelNames.length; i < l; ++i) { var modelName = modelNames[i]; var _tableInsertion = batch[modelName]; if (_tableInsertion.models.length) { (function () { var keys = _lodash2.default.uniq(_lodash2.default.flatMap(_tableInsertion.models, _lodash2.default.keys)); _tableInsertion.models = _lodash2.default.uniqBy(_tableInsertion.models, function (model) { return model.$propKey(keys); }); _tableInsertion.isInputModel = _lodash2.default.times(_tableInsertion.models.length, _lodash2.default.constant(false)); })(); } } return batch; }; /** * @private */ GraphInserter.prototype._omitUids = function _omitUids(tableInsertion) { var ids = _lodash2.default.map(tableInsertion.models, tableInsertion.modelClass.uidProp); for (var m = 0, lm = tableInsertion.models.length; m < lm; ++m) { tableInsertion.models[m].$omit(tableInsertion.modelClass.uidProp); } return ids; }; /** * @private * @param {TableInsertion} tableInsertion * @param {Array.<string>} uids */ GraphInserter.prototype._resolveDepsForInsertion = function _resolveDepsForInsertion(tableInsertion, uids) { for (var m = 0, lm = tableInsertion.models.length; m < lm; ++m) { var node = this.graph.nodesById[uids[m]]; var model = tableInsertion.models[m]; for (var d = 0, ld = node.isNeededBy.length; d < ld; ++d) { node.isNeededBy[d].resolve(model); } } }; /** * @private * @return {Promise} */ GraphInserter.prototype._finalize = function _finalize() { for (var n = 0, ln = this.graph.nodes.length; n < ln; ++n) { var refNode = this.graph.nodes[n]; var ref = refNode.model[refNode.modelClass.uidRefProp]; if (ref) { // Copy all the properties to the reference nodes. var actualNode = this.graph.nodesById[ref]; var relations = actualNode.modelClass.getRelations(); var keys = (0, _keys2.default)(actualNode.model); for (var i = 0, l = keys.length; i < l; ++i) { var key = keys[i]; var value = actualNode.model[key]; if (!relations[key] && !_lodash2.default.isFunction(value)) { refNode.model[key] = value; } } refNode.model.$omit(refNode.modelClass.uidProp, refNode.modelClass.uidRefProp); } } return _bluebird2.default.resolve(this.models); }; return GraphInserter; }(); exports.default = GraphInserter; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkdyYXBoSW5zZXJ0ZXIuanMiXSwibmFtZXMiOlsiR3JhcGhJbnNlcnRlciIsIm1vZGVsQ2xhc3MiLCJtb2RlbHMiLCJhbGxvd2VkUmVsYXRpb25zIiwia25leCIsImRvbmUiLCJncmFwaCIsIl9idWlsZERlcGVuZGVuY3lHcmFwaCIsImV4ZWN1dGUiLCJpbnNlcnRlciIsIl9leGVjdXRlTmV4dEJhdGNoIiwiYnVpbGQiLCJiYXRjaCIsIl9uZXh0QmF0Y2giLCJfZmluYWxpemUiLCJhbGwiLCJtYXAiLCJ0YWJsZUluc2VydGlvbiIsInRhYmxlTmFtZSIsInVpZHMiLCJpc0pvaW5UYWJsZUluc2VydGlvbiIsIl9vbWl0VWlkcyIsInRoZW4iLCJfcmVzb2x2ZURlcHNGb3JJbnNlcnRpb24iLCJfY3JlYXRlQmF0Y2giLCJpc0VtcHR5IiwiX2NyZWF0ZU1hbnlUb01hbnlSZWxhdGlvbkpvaW5Sb3dCYXRjaCIsIl9tYXJrQmF0Y2hIYW5kbGVkIiwibm9kZXMiLCJuIiwibG4iLCJsZW5ndGgiLCJub2RlIiwiaGFuZGxlZCIsIm5lZWRzIiwibnVtSGFuZGxlZE5lZWRzIiwicHVzaCIsIm1vZGVsIiwiaXNJbnB1dE1vZGVsIiwiaW5wdXROb2Rlc0J5SWQiLCJpZCIsImZsYXR0ZW4iLCJub2Rlc0J5SWQiLCJtIiwibG0iLCJjb25zdHJ1Y3RvciIsInVpZFByb3AiLCJuYiIsImxuYiIsImlzTmVlZGVkQnkiLCJkZXAiLCJtYW55VG9NYW55Q29ubmVjdGlvbnMiLCJjb25uIiwicmVsYXRpb24iLCJqb2luVGFibGUiLCJvd25lclByb3AiLCIkdmFsdWVzIiwiam9pblRhYmxlTW9kZWxDbGFzcyIsImpvaW5Nb2RlbCIsImNyZWF0ZUpvaW5Nb2RlbHMiLCJyZWZOb2RlIiwiayIsImxrIiwiam9pblRhYmxlRXh0cmFzIiwiZXh0cmEiLCJpc1VuZGVmaW5lZCIsImFsaWFzUHJvcCIsImpvaW5UYWJsZVByb3AiLCJmcm9tSnNvbiIsIm1vZGVsTmFtZXMiLCJpIiwibCIsIm1vZGVsTmFtZSIsImtleXMiLCJ1bmlxIiwiZmxhdE1hcCIsInVuaXFCeSIsIiRwcm9wS2V5IiwidGltZXMiLCJjb25zdGFudCIsImlkcyIsIiRvbWl0IiwiZCIsImxkIiwicmVzb2x2ZSIsInJlZiIsInVpZFJlZlByb3AiLCJhY3R1YWxOb2RlIiwicmVsYXRpb25zIiwiZ2V0UmVsYXRpb25zIiwia2V5IiwidmFsdWUiLCJpc0Z1bmN0aW9uIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7Ozs7QUFDQTs7OztBQUVBOzs7O0FBQ0E7Ozs7OztJQUVxQkEsYTtBQUVuQiwrQkFBMEQ7QUFBQSxRQUE3Q0MsVUFBNkMsUUFBN0NBLFVBQTZDO0FBQUEsUUFBakNDLE1BQWlDLFFBQWpDQSxNQUFpQztBQUFBLFFBQXpCQyxnQkFBeUIsUUFBekJBLGdCQUF5QjtBQUFBLFFBQVBDLElBQU8sUUFBUEEsSUFBTztBQUFBOztBQUN4RDs7O0FBR0EsU0FBS0gsVUFBTCxHQUFrQkEsVUFBbEI7O0FBRUE7OztBQUdBLFNBQUtDLE1BQUwsR0FBY0EsTUFBZDs7QUFFQTs7O0FBR0EsU0FBS0MsZ0JBQUwsR0FBd0JBLG9CQUFvQixJQUE1Qzs7QUFFQTs7O0FBR0EsU0FBS0UsSUFBTCxHQUFZLEtBQVo7O0FBRUE7OztBQUdBLFNBQUtDLEtBQUwsR0FBYSxLQUFLQyxxQkFBTCxFQUFiOztBQUVBOzs7QUFHQSxTQUFLSCxJQUFMLEdBQVlBLElBQVo7QUFDRDs7QUFFRDs7Ozs7OzBCQUlBSSxPLG9CQUFRQyxRLEVBQVU7QUFDaEIsV0FBTyxLQUFLQyxpQkFBTCxDQUF1QkQsUUFBdkIsQ0FBUDtBQUNELEc7O0FBRUQ7Ozs7OzswQkFJQUYscUIsb0NBQXdCO0FBQ3RCLFFBQUlELFFBQVEsOEJBQW9CLEtBQUtILGdCQUF6QixDQUFaO0FBQ0FHLFVBQU1LLEtBQU4sQ0FBWSxLQUFLVixVQUFqQixFQUE2QixLQUFLQyxNQUFsQztBQUNBLFdBQU9JLEtBQVA7QUFDRCxHOztBQUVEOzs7Ozs7OzBCQUtBSSxpQiw4QkFBa0JELFEs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aEIsT0FBTyxvQkFBWWMsV0FBV2xELEtBQXZCLENBQWI7O0FBRUEsYUFBSyxJQUFJaUMsSUFBSSxDQUFSLEVBQVdDLElBQUlFLEtBQUsxQyxNQUF6QixFQUFpQ3VDLElBQUlDLENBQXJDLEVBQXdDLEVBQUVELENBQTFDLEVBQTZDO0FBQzNDLGNBQU1vQixNQUFNakIsS0FBS0gsQ0FBTCxDQUFaO0FBQ0EsY0FBTXFCLFFBQVFKLFdBQVdsRCxLQUFYLENBQWlCcUQsR0FBakIsQ0FBZDs7QUFFQSxjQUFJLENBQUNGLFVBQVVFLEdBQVYsQ0FBRCxJQUFtQixDQUFDLGlCQUFFRSxVQUFGLENBQWFELEtBQWIsQ0FBeEIsRUFBNkM7QUFDM0MvQixvQkFBUXZCLEtBQVIsQ0FBY3FELEdBQWQsSUFBcUJDLEtBQXJCO0FBQ0Q7QUFDRjs7QUFFRC9CLGdCQUFRdkIsS0FBUixDQUFjNEMsS0FBZCxDQUFvQnJCLFFBQVEzRCxVQUFSLENBQW1CNkMsT0FBdkMsRUFBZ0RjLFFBQVEzRCxVQUFSLENBQW1CcUYsVUFBbkU7QUFDRDtBQUNGOztBQUVELFdBQU8sbUJBQVFGLE9BQVIsQ0FBZ0IsS0FBS2xGLE1BQXJCLENBQVA7QUFDRCxHOzs7OztrQkFqUmtCRixhIiwiZmlsZSI6IkdyYXBoSW5zZXJ0ZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IFByb21pc2UgZnJvbSAnYmx1ZWJpcmQnO1xuXG5pbXBvcnQgRGVwZW5kZW5jeUdyYXBoIGZyb20gJy4vRGVwZW5kZW5jeUdyYXBoJztcbmltcG9ydCBUYWJsZUluc2VydGlvbiBmcm9tICcuL1RhYmxlSW5zZXJ0aW9uJztcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgR3JhcGhJbnNlcnRlciB7XG5cbiAgY29uc3RydWN0b3Ioe21vZGVsQ2xhc3MsIG1vZGVscywgYWxsb3dlZFJlbGF0aW9ucywga25leH0pIHtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7Q29uc3RydWN0b3IuPE1vZGVsPn1cbiAgICAgKi9cbiAgICB0aGlzLm1vZGVsQ2xhc3MgPSBtb2RlbENsYXNzO1xuXG4gICAgLyoqXG4gICAgICogQHR5cGUge01vZGVsfEFycmF5LjxNb2RlbD59XG4gICAgICovXG4gICAgdGhpcy5tb2RlbHMgPSBtb2RlbHM7XG5cbiAgICAvKipcbiAgICAgKiBAdHlwZSB7UmVsYXRpb25FeHByZXNzaW9ufVxuICAgICAqL1xuICAgIHRoaXMuYWxsb3dlZFJlbGF0aW9ucyA9IGFsbG93ZWRSZWxhdGlvbnMgfHwgbnVsbDtcblxuICAgIC8qKlxuICAgICAqIEB0eXBlIHtib29sZWFufVxuICAgICAqL1xuICAgIHRoaXMuZG9uZSA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQHR5cGUge0RlcGVuZGVuY3lHcmFwaH1cbiAgICAgKi9cbiAgICB0aGlzLmdyYXBoID0gdGhpcy5fYnVpbGREZXBlbmRlbmN5R3JhcGgoKTtcblxuICAgIC8qKlxuICAgICAqIEB0eXBlIHtrbmV4fVxuICAgICAqL1xuICAgIHRoaXMua25leCA9IGtuZXg7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtmdW5jdGlvbihUYWJsZUluc2VydGlvbil9IGluc2VydGVyXG4gICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAqL1xuICBleGVjdXRlKGluc2VydGVyKSB7XG4gICAgcmV0dXJuIHRoaXMuX2V4ZWN1dGVOZXh0QmF0Y2goaW5zZXJ0ZXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm5zIHtEZXBlbmRlbmN5R3JhcGh9XG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBfYnVpbGREZXBlbmRlbmN5R3JhcGgoKSB7XG4gICAgbGV0IGdyYXBoID0gbmV3IERlcGVuZGVuY3lHcmFwaCh0aGlzLmFsbG93ZWRSZWxhdGlvbnMpO1xuICAgIGdyYXBoLmJ1aWxkKHRoaXMubW9kZWxDbGFzcywgdGhpcy5tb2RlbHMpO1xuICAgIHJldHVybiBncmFwaDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge2Z1bmN0aW9uKFRhYmxlSW5zZXJ0aW9uKX0gaW5zZXJ0ZXJcbiAgICogQHJldHVybnMge1Byb21pc2V9XG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBfZXhlY3V0ZU5leHRCYXRjaChpbnNlcnRlcikge1xuICAgIGxldCBiYXRjaCA9IHRoaXMuX25leHRCYXRjaCgpO1xuXG4gICAgaWYgKCFiYXRjaCkge1xuICAgICAgLy8gSWYgd2UgZ2V0IGhlcmUsIHdlIGFyZSBkb25lLiBBbGwgd2UgbmVlZCB0byBkbyBub3cgaXMgdG8gZmluYWxpemUgdGhlIG9iamVjdCBncmFwaFxuICAgICAgLy8gYW5kIHJldHVybiBpdCBhcyB0aGUgZmluYWwgb3V0cHV0LlxuICAgICAgcmV0dXJuIHRoaXMuX2ZpbmFsaXplKCk7XG4gICAgfVxuXG4gICAgLy8gSW5zZXJ0IHRoZSBiYXRjaCB1c2luZyB0aGUgYGluc2VydGVyYCBmdW5jdGlvbi5cbiAgICByZXR1cm4gUHJvbWlzZS5hbGwoT2JqZWN0LmtleXMoYmF0Y2gpLm1hcCh0YWJsZU5hbWUgPT4ge1xuICAgICAgY29uc3QgdGFibGVJbnNlcnRpb24gPSBiYXRjaFt0YWJsZU5hbWVdO1xuICAgICAgbGV0IHVpZHM7XG5cbiAgICAgIGlmICghdGFibGVJbnNlcnRpb24uaXNKb2luVGFibGVJbnNlcnRpb24pIHtcbiAgICAgICAgLy8gV2UgbmVlZCB0byBvbWl0IHRoZSB1aWQgcHJvcGVydGllcyBzbyB0aGF0IHRoZXkgZG9uJ3QgZ2V0IGluc2VydGVkXG4gICAgICAgIC8vIGludG8gdGhlIGRhdGFiYXNlLiBKb2luIHRhYmxlIGluc2VydGlvbnMgbmV2ZXIgaGF2ZSB1aWRzLlxuICAgICAgICB1aWRzID0gdGhpcy5fb21pdFVpZHModGFibGVJbnNlcnRpb24pO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gaW5zZXJ0ZXIodGFibGVJbnNlcnRpb24pLnRoZW4oKCkgPT4ge1xuICAgICAgICBpZiAoIXRhYmxlSW5zZXJ0aW9uLmlzSm9pblRhYmxlSW5zZXJ0aW9uKSB7XG4gICAgICAgICAgLy8gUmVzb2x2ZSBkZXBlbmRlbmNpZXMgdG8gdGhlIGluc2VydGVkIG9iamVjdHMuIEpvaW4gdGFibGUgaW5zZXJ0aW9uc1xuICAgICAgICAgIC8vIG5ldmVyIHJlc29sdmUgYW55IGRlcGVuZGVuY2llcy5cbiAgICAgICAgICB0aGlzLl9yZXNvbHZlRGVwc0Zvckluc2VydGlvbih0YWJsZUluc2VydGlvbiwgdWlkcyk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pKS50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLl9leGVjdXRlTmV4dEJhdGNoKGluc2VydGVyKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcmV0dXJucyB7T2JqZWN0LjxzdHJpbmcsIFRhYmxlSW5zZXJ0aW9uPn1cbiAgICovXG4gIF9uZXh0QmF0Y2goKSB7XG4gICAgaWYgKHRoaXMuZG9uZSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgbGV0IGJhdGNoID0gdGhpcy5fY3JlYXRlQmF0Y2goKTtcblxuICAgIGlmIChfLmlzRW1wdHkoYmF0Y2gpKSB7XG4gICAgICB0aGlzLmRvbmUgPSB0cnVlO1xuICAgICAgcmV0dXJuIHRoaXMuX2NyZWF0ZU1hbnlUb01hbnlSZWxhdGlvbkpvaW5Sb3dCYXRjaCgpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9tYXJrQmF0Y2hIYW5kbGVkKGJhdGNoKTtcbiAgICAgIHJldHVybiBiYXRjaDtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHByaXZhdGVcbiAgICogQHJldHVybnMge09iamVjdC48c3RyaW5nLCBUYWJsZUluc2VydGlvbj59XG4gICAqL1xuICBfY3JlYXRlQmF0Y2goKSB7XG4gICAgbGV0IGJhdGNoID0gT2JqZWN0LmNyZWF0ZShudWxsKTtcbiAgICBsZXQgbm9kZXMgPSB0aGlzLmdyYXBoLm5vZGVzO1xuXG4gICAgZm9yIChsZXQgbiA9IDAsIGxuID0gbm9kZXMubGVuZ3RoOyBuIDwgbG47ICsrbikge1xuICAgICAgbGV0IG5vZGUgPSBub2Rlc1tuXTtcblxuICAgICAgaWYgKCFub2RlLmhhbmRsZWQgJiYgbm9kZS5uZWVkcy5sZW5ndGggPT09IG5vZGUubnVtSGFuZGxlZE5lZWRzKSB7XG4gICAgICAgIGxldCB0YWJsZUluc2VydGlvbiA9IGJhdGNoW25vZGUubW9kZWxDbGFzcy50YWJsZU5hbWVdO1xuXG4gICAgICAgIGlmICghdGFibGVJbnNlcnRpb24pIHtcbiAgICAgICAgICB0YWJsZUluc2VydGlvbiA9IG5ldyBUYWJsZUluc2VydGlvbihub2RlLm1vZGVsQ2xhc3MsIGZhbHNlKTtcbiAgICAgICAgICBiYXRjaFtub2RlLm1vZGVsQ2xhc3MudGFibGVOYW1lXSA9IHRhYmxlSW5zZXJ0aW9uO1xuICAgICAgICB9XG5cbiAgICAgICAgdGFibGVJbnNlcnRpb24ubW9kZWxzLnB1c2gobm9kZS5tb2RlbCk7XG4gICAgICAgIHRhYmxlSW5zZXJ0aW9uLmlzSW5wdXRNb2RlbC5wdXNoKCEhdGhpcy5ncmFwaC5pbnB1dE5vZGVzQnlJZFtub2RlLmlkXSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGJhdGNoO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7T2JqZWN0LjxzdHJpbmcsIFRhYmxlSW5zZXJ0aW9uPn0gYmF0Y2hcbiAgICovXG4gIF9tYXJrQmF0Y2hIYW5kbGVkKGJhdGNoKSB7XG4gICAgbGV0IG1vZGVscyA9IF8uZmxhdHRlbihfLm1hcChiYXRjaCwgJ21vZGVscycpKTtcbiAgICBsZXQgbm9kZXMgPSB0aGlzLmdyYXBoLm5vZGVzQnlJZDtcblxuICAgIGZvciAobGV0IG0gPSAwLCBsbSA9IG1vZGVscy5sZW5ndGg7IG0gPCBsbTsgKyttKSB7XG4gICAgICBsZXQgaWQgPSBtb2RlbHNbbV1bbW9kZWxzW21dLmNvbnN0cnVjdG9yLnVpZFByb3BdO1xuICAgICAgbGV0IG5vZGUgPSBub2Rlc1tpZF07XG5cbiAgICAgIGZvciAobGV0IG5iID0gMCwgbG5iID0gbm9kZS5pc05lZWRlZEJ5Lmxlbmd0aDsgbmIgPCBsbmI7ICsrbmIpIHtcbiAgICAgICAgbGV0IGRlcCA9IG5vZGUuaXNOZWVkZWRCeVtuYl07XG4gICAgICAgIGRlcC5ub2RlLm51bUhhbmRsZWROZWVkcysrO1xuICAgICAgfVxuXG4gICAgICBub2RlLmhhbmRsZWQgPSB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcmV0dXJucyB7T2JqZWN0LjxzdHJpbmcsIFRhYmxlSW5zZXJ0aW9uPn1cbiAgICovXG4gIF9jcmVhdGVNYW55VG9NYW55UmVsYXRpb25Kb2luUm93QmF0Y2goKSB7XG4gICAgbGV0IGJhdGNoID0gT2JqZWN0LmNyZWF0ZShudWxsKTtcblxuICAgIGZvciAobGV0IG4gPSAwLCBsbiA9IHRoaXMuZ3JhcGgubm9kZXMubGVuZ3RoOyBuIDwgbG47ICsrbikge1xuICAgICAgbGV0IG5vZGUgPSB0aGlzLmdyYXBoLm5vZGVzW25dO1xuXG4gICAgICBmb3IgKGxldCBtID0gMCwgbG0gPSBub2RlLm1hbnlUb01hbnlDb25uZWN0aW9ucy5sZW5ndGg7IG0gPCBsbTsgKyttKSB7XG4gICAgICAgIGxldCBjb25uID0gbm9kZS5tYW55VG9NYW55Q29ubmVjdGlvbnNbbV07XG4gICAgICAgIGxldCB0YWJsZUluc2VydGlvbiA9IGJhdGNoW2Nvbm4ucmVsYXRpb24uam9pblRhYmxlXTtcblxuICAgICAgICBsZXQgb3duZXJQcm9wID0gbm9kZS5tb2RlbC4kdmFsdWVzKGNvbm4ucmVsYXRpb24ub3duZXJQcm9wKTtcbiAgICAgICAgbGV0IG1vZGVsQ2xhc3MgPSBjb25uLnJlbGF0aW9uLmpvaW5UYWJsZU1vZGVsQ2xhc3ModGhpcy5rbmV4KTtcbiAgICAgICAgbGV0IGpvaW5Nb2RlbCA9IGNvbm4ucmVsYXRpb24uY3JlYXRlSm9pbk1vZGVscyhvd25lclByb3AsIFtjb25uLm5vZGUubW9kZWxdKVswXTtcblxuICAgICAgICBpZiAoY29ubi5yZWZOb2RlKSB7XG4gICAgICAgICAgLy8gQWxzbyB0YWtlIGV4dHJhIHByb3BlcnRpZXMgZnJvbSB0aGUgcmVmZXJyaW5nIG1vZGVsLCBpdCB0aGVyZSB3YXMgb25lLlxuICAgICAgICAgIGZvciAobGV0IGsgPSAwLCBsayA9IGNvbm4ucmVsYXRpb24uam9pblRhYmxlRXh0cmFzLmxlbmd0aDsgayA8IGxrOyArK2spIHtcbiAgICAgICAgICAgIGxldCBleHRyYSA9IGNvbm4ucmVsYXRpb24uam9pblRhYmxlRXh0cmFzW2tdO1xuXG4gICAgICAgICAgICBpZiAoIV8uaXNVbmRlZmluZWQoY29ubi5yZWZOb2RlLm1vZGVsW2V4dHJhLmFsaWFzUHJvcF0pKSB7XG4gICAgICAgICAgICAgIGpvaW5Nb2RlbFtleHRyYS5qb2luVGFibGVQcm9wXSA9IGNvbm4ucmVmTm9kZS5tb2RlbFtleHRyYS5hbGlhc1Byb3BdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGpvaW5Nb2RlbCA9IG1vZGVsQ2xhc3MuZnJvbUpzb24oam9pbk1vZGVsKTtcblxuICAgICAgICBpZiAoIXRhYmxlSW5zZXJ0aW9uKSB7XG4gICAgICAgICAgdGFibGVJbnNlcnRpb24gPSBuZXcgVGFibGVJbnNlcnRpb24obW9kZWxDbGFzcywgdHJ1ZSk7XG4gICAgICAgICAgYmF0Y2hbbW9kZWxDbGFzcy50YWJsZU5hbWVdID0gdGFibGVJbnNlcnRpb247XG4gICAgICAgIH1cblxuICAgICAgICB0YWJsZUluc2VydGlvbi5tb2RlbHMucHVzaChqb2luTW9kZWwpO1xuICAgICAgICB0YWJsZUluc2VydGlvbi5pc0lucHV0TW9kZWwucHVzaChmYWxzZSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgbW9kZWxOYW1lcyA9IE9iamVjdC5rZXlzKGJhdGNoKTtcbiAgICAvLyBSZW1vdmUgZHVwbGljYXRlcy5cbiAgICBmb3IgKGxldCBpID0gMCwgbCA9IG1vZGVsTmFtZXMubGVuZ3RoOyBpIDwgbDsgKytpKSB7XG4gICAgICBjb25zdCBtb2RlbE5hbWUgPSBtb2RlbE5hbWVzW2ldO1xuICAgICAgY29uc3QgdGFibGVJbnNlcnRpb24gPSBiYXRjaFttb2RlbE5hbWVdO1xuXG4gICAgICBpZiAodGFibGVJbnNlcnRpb24ubW9kZWxzLmxlbmd0aCkge1xuICAgICAgICBjb25zdCBrZXlzID0gXy51bmlxKF8uZmxhdE1hcCh0YWJsZUluc2VydGlvbi5tb2RlbHMsIF8ua2V5cykpO1xuXG4gICAgICAgIHRhYmxlSW5zZXJ0aW9uLm1vZGVscyA9IF8udW5pcUJ5KHRhYmxlSW5zZXJ0aW9uLm1vZGVscywgbW9kZWwgPT4gbW9kZWwuJHByb3BLZXkoa2V5cykpO1xuICAgICAgICB0YWJsZUluc2VydGlvbi5pc0lucHV0TW9kZWwgPSBfLnRpbWVzKHRhYmxlSW5zZXJ0aW9uLm1vZGVscy5sZW5ndGgsIF8uY29uc3RhbnQoZmFsc2UpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gYmF0Y2g7XG4gIH1cblxuICAvKipcbiAgICogQHByaXZhdGVcbiAgICovXG4gIF9vbWl0VWlkcyh0YWJsZUluc2VydGlvbikge1xuICAgIGxldCBpZHMgPSBfLm1hcCh0YWJsZUluc2VydGlvbi5tb2RlbHMsIHRhYmxlSW5zZXJ0aW9uLm1vZGVsQ2xhc3MudWlkUHJvcCk7XG5cbiAgICBmb3IgKGxldCBtID0gMCwgbG0gPSB0YWJsZUluc2VydGlvbi5tb2RlbHMubGVuZ3RoOyBtIDwgbG07ICsrbSkge1xuICAgICAgdGFibGVJbnNlcnRpb24ubW9kZWxzW21dLiRvbWl0KHRhYmxlSW5zZXJ0aW9uLm1vZGVsQ2xhc3MudWlkUHJvcCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGlkcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge1RhYmxlSW5zZXJ0aW9ufSB0YWJsZUluc2VydGlvblxuICAgKiBAcGFyYW0ge0FycmF5LjxzdHJpbmc+fSB1aWRzXG4gICAqL1xuICBfcmVzb2x2ZURlcHNGb3JJbnNlcnRpb24odGFibGVJbnNlcnRpb24sIHVpZHMpIHtcbiAgICBmb3IgKGxldCBtID0gMCwgbG0gPSB0YWJsZUluc2VydGlvbi5tb2RlbHMubGVuZ3RoOyBtIDwgbG07ICsrbSkge1xuICAgICAgbGV0IG5vZGUgPSB0aGlzLmdyYXBoLm5vZGVzQnlJZFt1aWRzW21dXTtcbiAgICAgIGxldCBtb2RlbCA9IHRhYmxlSW5zZXJ0aW9uLm1vZGVsc1ttXTtcblxuICAgICAgZm9yIChsZXQgZCA9IDAsIGxkID0gbm9kZS5pc05lZWRlZEJ5Lmxlbmd0aDsgZCA8IGxkOyArK2QpIHtcbiAgICAgICAgbm9kZS5pc05lZWRlZEJ5W2RdLnJlc29sdmUobW9kZWwpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKi9cbiAgX2ZpbmFsaXplKCkge1xuICAgIGZvciAobGV0IG4gPSAwLCBsbiA9IHRoaXMuZ3JhcGgubm9kZXMubGVuZ3RoOyBuIDwgbG47ICsrbikge1xuICAgICAgbGV0IHJlZk5vZGUgPSB0aGlzLmdyYXBoLm5vZGVzW25dO1xuICAgICAgbGV0IHJlZiA9IHJlZk5vZGUubW9kZWxbcmVmTm9kZS5tb2RlbENsYXNzLnVpZFJlZlByb3BdO1xuXG4gICAgICBpZiAocmVmKSB7XG4gICAgICAgIC8vIENvcHkgYWxsIHRoZSBwcm9wZXJ0aWVzIHRvIHRoZSByZWZlcmVuY2Ugbm9kZXMuXG4gICAgICAgIGNvbnN0IGFjdHVhbE5vZGUgPSB0aGlzLmdyYXBoLm5vZGVzQnlJZFtyZWZdO1xuICAgICAgICBjb25zdCByZWxhdGlvbnMgPSBhY3R1YWxOb2RlLm1vZGVsQ2xhc3MuZ2V0UmVsYXRpb25zKCk7XG4gICAgICAgIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhhY3R1YWxOb2RlLm1vZGVsKTtcblxuICAgICAgICBmb3IgKGxldCBpID0gMCwgbCA9IGtleXMubGVuZ3RoOyBpIDwgbDsgKytpKSB7XG4gICAgICAgICAgY29uc3Qga2V5ID0ga2V5c1tpXTtcbiAgICAgICAgICBjb25zdCB2YWx1ZSA9IGFjdHVhbE5vZGUubW9kZWxba2V5XTtcblxuICAgICAgICAgIGlmICghcmVsYXRpb25zW2tleV0gJiYgIV8uaXNGdW5jdGlvbih2YWx1ZSkpIHtcbiAgICAgICAgICAgIHJlZk5vZGUubW9kZWxba2V5XSA9IHZhbHVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJlZk5vZGUubW9kZWwuJG9taXQocmVmTm9kZS5tb2RlbENsYXNzLnVpZFByb3AsIHJlZk5vZGUubW9kZWxDbGFzcy51aWRSZWZQcm9wKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRoaXMubW9kZWxzKTtcbiAgfVxufVxuIl19