UNPKG

matrix-react-sdk

Version:
329 lines (261 loc) 46.2 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _events = _interopRequireDefault(require("events")); var _groups = require("../groups"); var _FlairStore = _interopRequireDefault(require("./FlairStore")); var _MatrixClientPeg = require("../MatrixClientPeg"); var _dispatcher = _interopRequireDefault(require("../dispatcher/dispatcher")); /* Copyright 2017 New Vector Ltd Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ function parseMembersResponse(response) { return response.chunk.map(apiMember => (0, _groups.groupMemberFromApiObject)(apiMember)); } function parseRoomsResponse(response) { return response.chunk.map(apiRoom => (0, _groups.groupRoomFromApiObject)(apiRoom)); } // The number of ongoing group requests let ongoingRequestCount = 0; // This has arbitrarily been set to a small number to lower the priority // of doing group-related requests because we care about other important // requests like hitting /sync. const LIMIT = 3; // Maximum number of ongoing group requests // FIFO queue of functions to call in the backlog const backlogQueue = [// () => {...} ]; // Pull from the FIFO queue function checkBacklog() { const item = backlogQueue.shift(); if (typeof item === 'function') item(); } // Limit the maximum number of ongoing promises returned by fn to LIMIT and // use a FIFO queue to handle the backlog. async function limitConcurrency(fn) { if (ongoingRequestCount >= LIMIT) { // Enqueue this request for later execution await new Promise((resolve, reject) => { backlogQueue.push(resolve); }); } ongoingRequestCount++; try { return await fn(); } catch (err) { // We explicitly do not handle the error here, but let it propogate. throw err; } finally { ongoingRequestCount--; checkBacklog(); } } /** * Global store for tracking group summary, members, invited members and rooms. */ class GroupStore extends _events.default { constructor() { super(); (0, _defineProperty2.default)(this, "STATE_KEY", { GroupMembers: 'GroupMembers', GroupInvitedMembers: 'GroupInvitedMembers', Summary: 'Summary', GroupRooms: 'GroupRooms' }); this._state = {}; this._state[this.STATE_KEY.Summary] = {}; this._state[this.STATE_KEY.GroupRooms] = {}; this._state[this.STATE_KEY.GroupMembers] = {}; this._state[this.STATE_KEY.GroupInvitedMembers] = {}; this._ready = {}; this._ready[this.STATE_KEY.Summary] = {}; this._ready[this.STATE_KEY.GroupRooms] = {}; this._ready[this.STATE_KEY.GroupMembers] = {}; this._ready[this.STATE_KEY.GroupInvitedMembers] = {}; this._fetchResourcePromise = { [this.STATE_KEY.Summary]: {}, [this.STATE_KEY.GroupRooms]: {}, [this.STATE_KEY.GroupMembers]: {}, [this.STATE_KEY.GroupInvitedMembers]: {} }; this._resourceFetcher = { [this.STATE_KEY.Summary]: groupId => { return limitConcurrency(() => _MatrixClientPeg.MatrixClientPeg.get().getGroupSummary(groupId)); }, [this.STATE_KEY.GroupRooms]: groupId => { return limitConcurrency(() => _MatrixClientPeg.MatrixClientPeg.get().getGroupRooms(groupId).then(parseRoomsResponse)); }, [this.STATE_KEY.GroupMembers]: groupId => { return limitConcurrency(() => _MatrixClientPeg.MatrixClientPeg.get().getGroupUsers(groupId).then(parseMembersResponse)); }, [this.STATE_KEY.GroupInvitedMembers]: groupId => { return limitConcurrency(() => _MatrixClientPeg.MatrixClientPeg.get().getGroupInvitedUsers(groupId).then(parseMembersResponse)); } }; } _fetchResource(stateKey, groupId) { // Ongoing request, ignore if (this._fetchResourcePromise[stateKey][groupId]) return; const clientPromise = this._resourceFetcher[stateKey](groupId); // Indicate ongoing request this._fetchResourcePromise[stateKey][groupId] = clientPromise; clientPromise.then(result => { this._state[stateKey][groupId] = result; this._ready[stateKey][groupId] = true; this._notifyListeners(); }).catch(err => { // Invited users not visible to non-members if (stateKey === this.STATE_KEY.GroupInvitedMembers && err.httpStatus === 403) { return; } console.error(`Failed to get resource ${stateKey} for ${groupId}`, err); this.emit('error', err, groupId, stateKey); }).finally(() => { // Indicate finished request, allow for future fetches delete this._fetchResourcePromise[stateKey][groupId]; }); return clientPromise; } _notifyListeners() { this.emit('update'); } /** * Register a listener to recieve updates from the store. This also * immediately triggers an update to send the current state of the * store (which could be the initial state). * * If a group ID is specified, this also causes a fetch of all data * of the specified group, which might cause 4 separate HTTP * requests, but only if said requests aren't already ongoing. * * @param {string?} groupId the ID of the group to fetch data for. * Optional. * @param {function} fn the function to call when the store updates. * @return {Object} tok a registration "token" with a single * property `unregister`, a function that can * be called to unregister the listener such * that it won't be called any more. */ registerListener(groupId, fn) { this.on('update', fn); // Call to set initial state (before fetching starts) this.emit('update'); if (groupId) { this._fetchResource(this.STATE_KEY.Summary, groupId); this._fetchResource(this.STATE_KEY.GroupRooms, groupId); this._fetchResource(this.STATE_KEY.GroupMembers, groupId); this._fetchResource(this.STATE_KEY.GroupInvitedMembers, groupId); } // Similar to the Store of flux/utils, we return a "token" that // can be used to unregister the listener. return { unregister: () => { this.unregisterListener(fn); } }; } unregisterListener(fn) { this.removeListener('update', fn); } isStateReady(groupId, id) { return this._ready[id][groupId]; } getGroupIdsForRoomId(roomId) { const groupIds = Object.keys(this._state[this.STATE_KEY.GroupRooms]); return groupIds.filter(groupId => { const rooms = this._state[this.STATE_KEY.GroupRooms][groupId] || []; return rooms.some(room => room.roomId === roomId); }); } getSummary(groupId) { return this._state[this.STATE_KEY.Summary][groupId] || {}; } getGroupRooms(groupId) { return this._state[this.STATE_KEY.GroupRooms][groupId] || []; } getGroupMembers(groupId) { return this._state[this.STATE_KEY.GroupMembers][groupId] || []; } getGroupInvitedMembers(groupId) { return this._state[this.STATE_KEY.GroupInvitedMembers][groupId] || []; } getGroupPublicity(groupId) { return (this._state[this.STATE_KEY.Summary][groupId] || {}).user ? (this._state[this.STATE_KEY.Summary][groupId] || {}).user.is_publicised : null; } isUserPrivileged(groupId) { return (this._state[this.STATE_KEY.Summary][groupId] || {}).user ? (this._state[this.STATE_KEY.Summary][groupId] || {}).user.is_privileged : null; } refreshGroupRooms(groupId) { return this._fetchResource(this.STATE_KEY.GroupRooms, groupId); } refreshGroupMembers(groupId) { return this._fetchResource(this.STATE_KEY.GroupMembers, groupId); } addRoomToGroup(groupId, roomId, isPublic) { return _MatrixClientPeg.MatrixClientPeg.get().addRoomToGroup(groupId, roomId, isPublic).then(this._fetchResource.bind(this, this.STATE_KEY.GroupRooms, groupId)); } updateGroupRoomVisibility(groupId, roomId, isPublic) { return _MatrixClientPeg.MatrixClientPeg.get().updateGroupRoomVisibility(groupId, roomId, isPublic).then(this._fetchResource.bind(this, this.STATE_KEY.GroupRooms, groupId)); } removeRoomFromGroup(groupId, roomId) { return _MatrixClientPeg.MatrixClientPeg.get().removeRoomFromGroup(groupId, roomId) // Room might be in the summary, refresh just in case .then(this._fetchResource.bind(this, this.STATE_KEY.Summary, groupId)).then(this._fetchResource.bind(this, this.STATE_KEY.GroupRooms, groupId)); } inviteUserToGroup(groupId, userId) { return _MatrixClientPeg.MatrixClientPeg.get().inviteUserToGroup(groupId, userId).then(this._fetchResource.bind(this, this.STATE_KEY.GroupInvitedMembers, groupId)); } acceptGroupInvite(groupId) { return _MatrixClientPeg.MatrixClientPeg.get().acceptGroupInvite(groupId) // The user should now be able to access (personal) group settings .then(this._fetchResource.bind(this, this.STATE_KEY.Summary, groupId)) // The user might be able to see more rooms now .then(this._fetchResource.bind(this, this.STATE_KEY.GroupRooms, groupId)) // The user should now appear as a member .then(this._fetchResource.bind(this, this.STATE_KEY.GroupMembers, groupId)) // The user should now not appear as an invited member .then(this._fetchResource.bind(this, this.STATE_KEY.GroupInvitedMembers, groupId)); } joinGroup(groupId) { return _MatrixClientPeg.MatrixClientPeg.get().joinGroup(groupId) // The user should now be able to access (personal) group settings .then(this._fetchResource.bind(this, this.STATE_KEY.Summary, groupId)) // The user might be able to see more rooms now .then(this._fetchResource.bind(this, this.STATE_KEY.GroupRooms, groupId)) // The user should now appear as a member .then(this._fetchResource.bind(this, this.STATE_KEY.GroupMembers, groupId)) // The user should now not appear as an invited member .then(this._fetchResource.bind(this, this.STATE_KEY.GroupInvitedMembers, groupId)); } leaveGroup(groupId) { // ensure the tag panel filter is cleared if the group was selected _dispatcher.default.dispatch({ action: "deselect_tags", tag: groupId }); return _MatrixClientPeg.MatrixClientPeg.get().leaveGroup(groupId) // The user should now not be able to access group settings .then(this._fetchResource.bind(this, this.STATE_KEY.Summary, groupId)) // The user might only be able to see a subset of rooms now .then(this._fetchResource.bind(this, this.STATE_KEY.GroupRooms, groupId)) // The user should now not appear as a member .then(this._fetchResource.bind(this, this.STATE_KEY.GroupMembers, groupId)); } addRoomToGroupSummary(groupId, roomId, categoryId) { return _MatrixClientPeg.MatrixClientPeg.get().addRoomToGroupSummary(groupId, roomId, categoryId).then(this._fetchResource.bind(this, this.STATE_KEY.Summary, groupId)); } addUserToGroupSummary(groupId, userId, roleId) { return _MatrixClientPeg.MatrixClientPeg.get().addUserToGroupSummary(groupId, userId, roleId).then(this._fetchResource.bind(this, this.STATE_KEY.Summary, groupId)); } removeRoomFromGroupSummary(groupId, roomId) { return _MatrixClientPeg.MatrixClientPeg.get().removeRoomFromGroupSummary(groupId, roomId).then(this._fetchResource.bind(this, this.STATE_KEY.Summary, groupId)); } removeUserFromGroupSummary(groupId, userId) { return _MatrixClientPeg.MatrixClientPeg.get().removeUserFromGroupSummary(groupId, userId).then(this._fetchResource.bind(this, this.STATE_KEY.Summary, groupId)); } setGroupPublicity(groupId, isPublished) { return _MatrixClientPeg.MatrixClientPeg.get().setGroupPublicity(groupId, isPublished).then(() => { _FlairStore.default.invalidatePublicisedGroups(_MatrixClientPeg.MatrixClientPeg.get().credentials.userId); }).then(this._fetchResource.bind(this, this.STATE_KEY.Summary, groupId)); } } let singletonGroupStore = null; if (!singletonGroupStore) { singletonGroupStore = new GroupStore(); } var _default = singletonGroupStore; exports.default = _default; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zdG9yZXMvR3JvdXBTdG9yZS5qcyJdLCJuYW1lcyI6WyJwYXJzZU1lbWJlcnNSZXNwb25zZSIsInJlc3BvbnNlIiwiY2h1bmsiLCJtYXAiLCJhcGlNZW1iZXIiLCJwYXJzZVJvb21zUmVzcG9uc2UiLCJhcGlSb29tIiwib25nb2luZ1JlcXVlc3RDb3VudCIsIkxJTUlUIiwiYmFja2xvZ1F1ZXVlIiwiY2hlY2tCYWNrbG9nIiwiaXRlbSIsInNoaWZ0IiwibGltaXRDb25jdXJyZW5jeSIsImZuIiwiUHJvbWlzZSIsInJlc29sdmUiLCJyZWplY3QiLCJwdXNoIiwiZXJyIiwiR3JvdXBTdG9yZSIsIkV2ZW50RW1pdHRlciIsImNvbnN0cnVjdG9yIiwiR3JvdXBNZW1iZXJzIiwiR3JvdXBJbnZpdGVkTWVtYmVycyIsIlN1bW1hcnkiLCJHcm91cFJvb21zIiwiX3N0YXRlIiwiU1RBVEVfS0VZIiwiX3JlYWR5IiwiX2ZldGNoUmVzb3VyY2VQcm9taXNlIiwiX3Jlc291cmNlRmV0Y2hlciIsImdyb3VwSWQiLCJNYXRyaXhDbGllbnRQZWciLCJnZXQiLCJnZXRHcm91cFN1bW1hcnkiLCJnZXRHcm91cFJvb21zIiwidGhlbiIsImdldEdyb3VwVXNlcnMiLCJnZXRHcm91cEludml0ZWRVc2VycyIsIl9mZXRjaFJlc291cmNlIiwic3RhdGVLZXkiLCJjbGllbnRQcm9taXNlIiwicmVzdWx0IiwiX25vdGlmeUxpc3RlbmVycyIsImNhdGNoIiwiaHR0cFN0YXR1cyIsImNvbnNvbGUiLCJlcnJvciIsImVtaXQiLCJmaW5hbGx5IiwicmVnaXN0ZXJMaXN0ZW5lciIsIm9uIiwidW5yZWdpc3RlciIsInVucmVnaXN0ZXJMaXN0ZW5lciIsInJlbW92ZUxpc3RlbmVyIiwiaXNTdGF0ZVJlYWR5IiwiaWQiLCJnZXRHcm91cElkc0ZvclJvb21JZCIsInJvb21JZCIsImdyb3VwSWRzIiwiT2JqZWN0Iiwia2V5cyIsImZpbHRlciIsInJvb21zIiwic29tZSIsInJvb20iLCJnZXRTdW1tYXJ5IiwiZ2V0R3JvdXBNZW1iZXJzIiwiZ2V0R3JvdXBJbnZpdGVkTWVtYmVycyIsImdldEdyb3VwUHVibGljaXR5IiwidXNlciIsImlzX3B1YmxpY2lzZWQiLCJpc1VzZXJQcml2aWxlZ2VkIiwiaXNfcHJpdmlsZWdlZCIsInJlZnJlc2hHcm91cFJvb21zIiwicmVmcmVzaEdyb3VwTWVtYmVycyIsImFkZFJvb21Ub0dyb3VwIiwiaXNQdWJsaWMiLCJiaW5kIiwidXBkYXRlR3JvdXBSb29tVmlzaWJpbGl0eSIsInJlbW92ZVJvb21Gcm9tR3JvdXAiLCJpbnZpdGVVc2VyVG9Hcm91cCIsInVzZXJJZCIsImFjY2VwdEdyb3VwSW52aXRlIiwiam9pbkdyb3VwIiwibGVhdmVHcm91cCIsImRpcyIsImRpc3BhdGNoIiwiYWN0aW9uIiwidGFnIiwiYWRkUm9vbVRvR3JvdXBTdW1tYXJ5IiwiY2F0ZWdvcnlJZCIsImFkZFVzZXJUb0dyb3VwU3VtbWFyeSIsInJvbGVJZCIsInJlbW92ZVJvb21Gcm9tR3JvdXBTdW1tYXJ5IiwicmVtb3ZlVXNlckZyb21Hcm91cFN1bW1hcnkiLCJzZXRHcm91cFB1YmxpY2l0eSIsImlzUHVibGlzaGVkIiwiRmxhaXJTdG9yZSIsImludmFsaWRhdGVQdWJsaWNpc2VkR3JvdXBzIiwiY3JlZGVudGlhbHMiLCJzaW5nbGV0b25Hcm91cFN0b3JlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7OztBQWdCQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFwQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBUUEsU0FBU0Esb0JBQVQsQ0FBOEJDLFFBQTlCLEVBQXdDO0FBQ3BDLFNBQU9BLFFBQVEsQ0FBQ0MsS0FBVCxDQUFlQyxHQUFmLENBQW9CQyxTQUFELElBQWUsc0NBQXlCQSxTQUF6QixDQUFsQyxDQUFQO0FBQ0g7O0FBRUQsU0FBU0Msa0JBQVQsQ0FBNEJKLFFBQTVCLEVBQXNDO0FB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dURPLE9BQXZELENBRkgsQ0FBUDtBQUdIOztBQUVEZ0UsRUFBQUEsMEJBQTBCLENBQUNoRSxPQUFELEVBQVVtRCxNQUFWLEVBQWtCO0FBQ3hDLFdBQU9sRCxpQ0FBZ0JDLEdBQWhCLEdBQ0Y4RCwwQkFERSxDQUN5QmhFLE9BRHpCLEVBQ2tDbUQsTUFEbEMsRUFFRjlDLElBRkUsQ0FFRyxLQUFLRyxjQUFMLENBQW9CdUMsSUFBcEIsQ0FBeUIsSUFBekIsRUFBK0IsS0FBS25ELFNBQUwsQ0FBZUgsT0FBOUMsRUFBdURPLE9BQXZELENBRkgsQ0FBUDtBQUdIOztBQUVEaUUsRUFBQUEsaUJBQWlCLENBQUNqRSxPQUFELEVBQVVrRSxXQUFWLEVBQXVCO0FBQ3BDLFdBQU9qRSxpQ0FBZ0JDLEdBQWhCLEdBQ0YrRCxpQkFERSxDQUNnQmpFLE9BRGhCLEVBQ3lCa0UsV0FEekIsRUFFRjdELElBRkUsQ0FFRyxNQUFNO0FBQUU4RCwwQkFBV0MsMEJBQVgsQ0FBc0NuRSxpQ0FBZ0JDLEdBQWhCLEdBQXNCbUUsV0FBdEIsQ0FBa0NsQixNQUF4RTtBQUFrRixLQUY3RixFQUdGOUMsSUFIRSxDQUdHLEtBQUtHLGNBQUwsQ0FBb0J1QyxJQUFwQixDQUF5QixJQUF6QixFQUErQixLQUFLbkQsU0FBTCxDQUFlSCxPQUE5QyxFQUF1RE8sT0FBdkQsQ0FISCxDQUFQO0FBSUg7O0FBM1FpQzs7QUE4UXRDLElBQUlzRSxtQkFBbUIsR0FBRyxJQUExQjs7QUFDQSxJQUFJLENBQUNBLG1CQUFMLEVBQTBCO0FBQ3RCQSxFQUFBQSxtQkFBbUIsR0FBRyxJQUFJbEYsVUFBSixFQUF0QjtBQUNIOztlQUNja0YsbUIiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuQ29weXJpZ2h0IDIwMTcgTmV3IFZlY3RvciBMdGRcblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4qL1xuXG5pbXBvcnQgRXZlbnRFbWl0dGVyIGZyb20gJ2V2ZW50cyc7XG5pbXBvcnQgeyBncm91cE1lbWJlckZyb21BcGlPYmplY3QsIGdyb3VwUm9vbUZyb21BcGlPYmplY3QgfSBmcm9tICcuLi9ncm91cHMnO1xuaW1wb3J0IEZsYWlyU3RvcmUgZnJvbSAnLi9GbGFpclN0b3JlJztcbmltcG9ydCB7TWF0cml4Q2xpZW50UGVnfSBmcm9tICcuLi9NYXRyaXhDbGllbnRQZWcnO1xuaW1wb3J0IGRpcyBmcm9tICcuLi9kaXNwYXRjaGVyL2Rpc3BhdGNoZXInO1xuXG5mdW5jdGlvbiBwYXJzZU1lbWJlcnNSZXNwb25zZShyZXNwb25zZSkge1xuICAgIHJldHVybiByZXNwb25zZS5jaHVuay5tYXAoKGFwaU1lbWJlcikgPT4gZ3JvdXBNZW1iZXJGcm9tQXBpT2JqZWN0KGFwaU1lbWJlcikpO1xufVxuXG5mdW5jdGlvbiBwYXJzZVJvb21zUmVzcG9uc2UocmVzcG9uc2UpIHtcbiAgICByZXR1cm4gcmVzcG9uc2UuY2h1bmsubWFwKChhcGlSb29tKSA9PiBncm91cFJvb21Gcm9tQXBpT2JqZWN0KGFwaVJvb20pKTtcbn1cblxuLy8gVGhlIG51bWJlciBvZiBvbmdvaW5nIGdyb3VwIHJlcXVlc3RzXG5sZXQgb25nb2luZ1JlcXVlc3RDb3VudCA9IDA7XG5cbi8vIFRoaXMgaGFzIGFyYml0cmFyaWx5IGJlZW4gc2V0IHRvIGEgc21hbGwgbnVtYmVyIHRvIGxvd2VyIHRoZSBwcmlvcml0eVxuLy8gb2YgZG9pbmcgZ3JvdXAtcmVsYXRlZCByZXF1ZXN0cyBiZWNhdXNlIHdlIGNhcmUgYWJvdXQgb3RoZXIgaW1wb3J0YW50XG4vLyByZXF1ZXN0cyBsaWtlIGhpdHRpbmcgL3N5bmMuXG5jb25zdCBMSU1JVCA9IDM7IC8vIE1heGltdW0gbnVtYmVyIG9mIG9uZ29pbmcgZ3JvdXAgcmVxdWVzdHNcblxuLy8gRklGTyBxdWV1ZSBvZiBmdW5jdGlvbnMgdG8gY2FsbCBpbiB0aGUgYmFja2xvZ1xuY29uc3QgYmFja2xvZ1F1ZXVlID0gW1xuICAgIC8vICgpID0+IHsuLi59XG5dO1xuXG4vLyBQdWxsIGZyb20gdGhlIEZJRk8gcXVldWVcbmZ1bmN0aW9uIGNoZWNrQmFja2xvZygpIHtcbiAgICBjb25zdCBpdGVtID0gYmFja2xvZ1F1ZXVlLnNoaWZ0KCk7XG4gICAgaWYgKHR5cGVvZiBpdGVtID09PSAnZnVuY3Rpb24nKSBpdGVtKCk7XG59XG5cbi8vIExpbWl0IHRoZSBtYXhpbXVtIG51bWJlciBvZiBvbmdvaW5nIHByb21pc2VzIHJldHVybmVkIGJ5IGZuIHRvIExJTUlUIGFuZFxuLy8gdXNlIGEgRklGTyBxdWV1ZSB0byBoYW5kbGUgdGhlIGJhY2tsb2cuXG5hc3luYyBmdW5jdGlvbiBsaW1pdENvbmN1cnJlbmN5KGZuKSB7XG4gICAgaWYgKG9uZ29pbmdSZXF1ZXN0Q291bnQgPj0gTElNSVQpIHtcbiAgICAgICAgLy8gRW5xdWV1ZSB0aGlzIHJlcXVlc3QgZm9yIGxhdGVyIGV4ZWN1dGlvblxuICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBiYWNrbG9nUXVldWUucHVzaChyZXNvbHZlKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgb25nb2luZ1JlcXVlc3RDb3VudCsrO1xuICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBhd2FpdCBmbigpO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAvLyBXZSBleHBsaWNpdGx5IGRvIG5vdCBoYW5kbGUgdGhlIGVycm9yIGhlcmUsIGJ1dCBsZXQgaXQgcHJvcG9nYXRlLlxuICAgICAgICB0aHJvdyBlcnI7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgICAgb25nb2luZ1JlcXVlc3RDb3VudC0tO1xuICAgICAgICBjaGVja0JhY2tsb2coKTtcbiAgICB9XG59XG5cbi8qKlxuICogR2xvYmFsIHN0b3JlIGZvciB0cmFja2luZyBncm91cCBzdW1tYXJ5LCBtZW1iZXJzLCBpbnZpdGVkIG1lbWJlcnMgYW5kIHJvb21zLlxuICovXG5jbGFzcyBHcm91cFN0b3JlIGV4dGVuZHMgRXZlbnRFbWl0dGVyIHtcbiAgICBTVEFURV9LRVkgPSB7XG4gICAgICAgIEdyb3VwTWVtYmVyczogJ0dyb3VwTWVtYmVycycsXG4gICAgICAgIEdyb3VwSW52aXRlZE1lbWJlcnM6ICdHcm91cEludml0ZWRNZW1iZXJzJyxcbiAgICAgICAgU3VtbWFyeTogJ1N1bW1hcnknLFxuICAgICAgICBHcm91cFJvb21zOiAnR3JvdXBSb29tcycsXG4gICAgfTtcblxuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICB0aGlzLl9zdGF0ZSA9IHt9O1xuICAgICAgICB0aGlzLl9zdGF0ZVt0aGlzLlNUQVRFX0tFWS5TdW1tYXJ5XSA9IHt9O1xuICAgICAgICB0aGlzLl9zdGF0ZVt0aGlzLlNUQVRFX0tFWS5Hcm91cFJvb21zXSA9IHt9O1xuICAgICAgICB0aGlzLl9zdGF0ZVt0aGlzLlNUQVRFX0tFWS5Hcm91cE1lbWJlcnNdID0ge307XG4gICAgICAgIHRoaXMuX3N0YXRlW3RoaXMuU1RBVEVfS0VZLkdyb3VwSW52aXRlZE1lbWJlcnNdID0ge307XG5cbiAgICAgICAgdGhpcy5fcmVhZHkgPSB7fTtcbiAgICAgICAgdGhpcy5fcmVhZHlbdGhpcy5TVEFURV9LRVkuU3VtbWFyeV0gPSB7fTtcbiAgICAgICAgdGhpcy5fcmVhZHlbdGhpcy5TVEFURV9LRVkuR3JvdXBSb29tc10gPSB7fTtcbiAgICAgICAgdGhpcy5fcmVhZHlbdGhpcy5TVEFURV9LRVkuR3JvdXBNZW1iZXJzXSA9IHt9O1xuICAgICAgICB0aGlzLl9yZWFkeVt0aGlzLlNUQVRFX0tFWS5Hcm91cEludml0ZWRNZW1iZXJzXSA9IHt9O1xuXG4gICAgICAgIHRoaXMuX2ZldGNoUmVzb3VyY2VQcm9taXNlID0ge1xuICAgICAgICAgICAgW3RoaXMuU1RBVEVfS0VZLlN1bW1hcnldOiB7fSxcbiAgICAgICAgICAgIFt0aGlzLlNUQVRFX0tFWS5Hcm91cFJvb21zXToge30sXG4gICAgICAgICAgICBbdGhpcy5TVEFURV9LRVkuR3JvdXBNZW1iZXJzXToge30sXG4gICAgICAgICAgICBbdGhpcy5TVEFURV9LRVkuR3JvdXBJbnZpdGVkTWVtYmVyc106IHt9LFxuICAgICAgICB9O1xuXG4gICAgICAgIHRoaXMuX3Jlc291cmNlRmV0Y2hlciA9IHtcbiAgICAgICAgICAgIFt0aGlzLlNUQVRFX0tFWS5TdW1tYXJ5XTogKGdyb3VwSWQpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbGltaXRDb25jdXJyZW5jeShcbiAgICAgICAgICAgICAgICAgICAgKCkgPT4gTWF0cml4Q2xpZW50UGVnLmdldCgpLmdldEdyb3VwU3VtbWFyeShncm91cElkKSxcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFt0aGlzLlNUQVRFX0tFWS5Hcm91cFJvb21zXTogKGdyb3VwSWQpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbGltaXRDb25jdXJyZW5jeShcbiAgICAgICAgICAgICAgICAgICAgKCkgPT4gTWF0cml4Q2xpZW50UGVnLmdldCgpLmdldEdyb3VwUm9vbXMoZ3JvdXBJZCkudGhlbihwYXJzZVJvb21zUmVzcG9uc2UpLFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgW3RoaXMuU1RBVEVfS0VZLkdyb3VwTWVtYmVyc106IChncm91cElkKSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGxpbWl0Q29uY3VycmVuY3koXG4gICAgICAgICAgICAgICAgICAgICgpID0+IE1hdHJpeENsaWVudFBlZy5nZXQoKS5nZXRHcm91cFVzZXJzKGdyb3VwSWQpLnRoZW4ocGFyc2VNZW1iZXJzUmVzcG9uc2UpLFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgW3RoaXMuU1RBVEVfS0VZLkdyb3VwSW52aXRlZE1lbWJlcnNdOiAoZ3JvdXBJZCkgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiBsaW1pdENvbmN1cnJlbmN5KFxuICAgICAgICAgICAgICAgICAgICAoKSA9PiBNYXRyaXhDbGllbnRQZWcuZ2V0KCkuZ2V0R3JvdXBJbnZpdGVkVXNlcnMoZ3JvdXBJZCkudGhlbihwYXJzZU1lbWJlcnNSZXNwb25zZSksXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgX2ZldGNoUmVzb3VyY2Uoc3RhdGVLZXksIGdyb3VwSWQpIHtcbiAgICAgICAgLy8gT25nb2luZyByZXF1ZXN0LCBpZ25vcmVcbiAgICAgICAgaWYgKHRoaXMuX2ZldGNoUmVzb3VyY2VQcm9taXNlW3N0YXRlS2V5XVtncm91cElkXSkgcmV0dXJuO1xuXG4gICAgICAgIGNvbnN0IGNsaWVudFByb21pc2UgPSB0aGlzLl9yZXNvdXJjZUZldGNoZXJbc3RhdGVLZXldKGdyb3VwSWQpO1xuXG4gICAgICAgIC8vIEluZGljYXRlIG9uZ29pbmcgcmVxdWVzdFxuICAgICAgICB0aGlzLl9mZXRjaFJlc291cmNlUHJvbWlzZVtzdGF0ZUtleV1bZ3JvdXBJZF0gPSBjbGllbnRQcm9taXNlO1xuXG4gICAgICAgIGNsaWVudFByb21pc2UudGhlbigocmVzdWx0KSA9PiB7XG4gICAgICAgICAgICB0aGlzLl9zdGF0ZVtzdGF0ZUtleV1bZ3JvdXBJZF0gPSByZXN1bHQ7XG4gICAgICAgICAgICB0aGlzLl9yZWFkeVtzdGF0ZUtleV1bZ3JvdXBJZF0gPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5fbm90aWZ5TGlzdGVuZXJzKCk7XG4gICAgICAgIH0pLmNhdGNoKChlcnIpID0+IHtcbiAgICAgICAgICAgIC8vIEludml0ZWQgdXNlcnMgbm90IHZpc2libGUgdG8gbm9uLW1lbWJlcnNcbiAgICAgICAgICAgIGlmIChzdGF0ZUtleSA9PT0gdGhpcy5TVEFURV9LRVkuR3JvdXBJbnZpdGVkTWVtYmVycyAmJiBlcnIuaHR0cFN0YXR1cyA9PT0gNDAzKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGBGYWlsZWQgdG8gZ2V0IHJlc291cmNlICR7c3RhdGVLZXl9IGZvciAke2dyb3VwSWR9YCwgZXJyKTtcbiAgICAgICAgICAgIHRoaXMuZW1pdCgnZXJyb3InLCBlcnIsIGdyb3VwSWQsIHN0YXRlS2V5KTtcbiAgICAgICAgfSkuZmluYWxseSgoKSA9PiB7XG4gICAgICAgICAgICAvLyBJbmRpY2F0ZSBmaW5pc2hlZCByZXF1ZXN0LCBhbGxvdyBmb3IgZnV0dXJlIGZldGNoZXNcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLl9mZXRjaFJlc291cmNlUHJvbWlzZVtzdGF0ZUtleV1bZ3JvdXBJZF07XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBjbGllbnRQcm9taXNlO1xuICAgIH1cblxuICAgIF9ub3RpZnlMaXN0ZW5lcnMoKSB7XG4gICAgICAgIHRoaXMuZW1pdCgndXBkYXRlJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVnaXN0ZXIgYSBsaXN0ZW5lciB0byByZWNpZXZlIHVwZGF0ZXMgZnJvbSB0aGUgc3RvcmUuIFRoaXMgYWxzb1xuICAgICAqIGltbWVkaWF0ZWx5IHRyaWdnZXJzIGFuIHVwZGF0ZSB0byBzZW5kIHRoZSBjdXJyZW50IHN0YXRlIG9mIHRoZVxuICAgICAqIHN0b3JlICh3aGljaCBjb3VsZCBiZSB0aGUgaW5pdGlhbCBzdGF0ZSkuXG4gICAgICpcbiAgICAgKiBJZiBhIGdyb3VwIElEIGlzIHNwZWNpZmllZCwgdGhpcyBhbHNvIGNhdXNlcyBhIGZldGNoIG9mIGFsbCBkYXRhXG4gICAgICogb2YgdGhlIHNwZWNpZmllZCBncm91cCwgd2hpY2ggbWlnaHQgY2F1c2UgNCBzZXBhcmF0ZSBIVFRQXG4gICAgICogcmVxdWVzdHMsIGJ1dCBvbmx5IGlmIHNhaWQgcmVxdWVzdHMgYXJlbid0IGFscmVhZHkgb25nb2luZy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nP30gZ3JvdXBJZCB0aGUgSUQgb2YgdGhlIGdyb3VwIHRvIGZldGNoIGRhdGEgZm9yLlxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICBPcHRpb25hbC5cbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBmbiB0aGUgZnVuY3Rpb24gdG8gY2FsbCB3aGVuIHRoZSBzdG9yZSB1cGRhdGVzLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gdG9rIGEgcmVnaXN0cmF0aW9uIFwidG9rZW5cIiB3aXRoIGEgc2luZ2xlXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgcHJvcGVydHkgYHVucmVnaXN0ZXJgLCBhIGZ1bmN0aW9uIHRoYXQgY2FuXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgYmUgY2FsbGVkIHRvIHVucmVnaXN0ZXIgdGhlIGxpc3RlbmVyIHN1Y2hcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICB0aGF0IGl0IHdvbid0IGJlIGNhbGxlZCBhbnkgbW9yZS5cbiAgICAgKi9cbiAgICByZWdpc3Rlckxpc3RlbmVyKGdyb3VwSWQsIGZuKSB7XG4gICAgICAgIHRoaXMub24oJ3VwZGF0ZScsIGZuKTtcbiAgICAgICAgLy8gQ2FsbCB0byBzZXQgaW5pdGlhbCBzdGF0ZSAoYmVmb3JlIGZldGNoaW5nIHN0YXJ0cylcbiAgICAgICAgdGhpcy5lbWl0KCd1cGRhdGUnKTtcblxuICAgICAgICBpZiAoZ3JvdXBJZCkge1xuICAgICAgICAgICAgdGhpcy5fZmV0Y2hSZXNvdXJjZSh0aGlzLlNUQVRFX0tFWS5TdW1tYXJ5LCBncm91cElkKTtcbiAgICAgICAgICAgIHRoaXMuX2ZldGNoUmVzb3VyY2UodGhpcy5TVEFURV9LRVkuR3JvdXBSb29tcywgZ3JvdXBJZCk7XG4gICAgICAgICAgICB0aGlzLl9mZXRjaFJlc291cmNlKHRoaXMuU1RBVEVfS0VZLkdyb3VwTWVtYmVycywgZ3JvdXBJZCk7XG4gICAgICAgICAgICB0aGlzLl9mZXRjaFJlc291cmNlKHRoaXMuU1RBVEVfS0VZLkdyb3VwSW52aXRlZE1lbWJlcnMsIGdyb3VwSWQpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU2ltaWxhciB0byB0aGUgU3RvcmUgb2YgZmx1eC91dGlscywgd2UgcmV0dXJuIGEgXCJ0b2tlblwiIHRoYXRcbiAgICAgICAgLy8gY2FuIGJlIHVzZWQgdG8gdW5yZWdpc3RlciB0aGUgbGlzdGVuZXIuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB1bnJlZ2lzdGVyOiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy51bnJlZ2lzdGVyTGlzdGVuZXIoZm4pO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICB1bnJlZ2lzdGVyTGlzdGVuZXIoZm4pIHtcbiAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcigndXBkYXRlJywgZm4pO1xuICAgIH1cblxuICAgIGlzU3RhdGVSZWFkeShncm91cElkLCBpZCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fcmVhZHlbaWRdW2dyb3VwSWRdO1xuICAgIH1cblxuICAgIGdldEdyb3VwSWRzRm9yUm9vbUlkKHJvb21JZCkge1xuICAgICAgICBjb25zdCBncm91cElkcyA9IE9iamVjdC5rZXlzKHRoaXMuX3N0YXRlW3RoaXMuU1RBVEVfS0VZLkdyb3VwUm9vbXNdKTtcbiAgICAgICAgcmV0dXJuIGdyb3VwSWRzLmZpbHRlcihncm91cElkID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHJvb21zID0gdGhpcy5fc3RhdGVbdGhpcy5TVEFURV9LRVkuR3JvdXBSb29tc11bZ3JvdXBJZF0gfHwgW107XG4gICAgICAgICAgICByZXR1cm4gcm9vbXMuc29tZShyb29tID0+IHJvb20ucm9vbUlkID09PSByb29tSWQpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBnZXRTdW1tYXJ5KGdyb3VwSWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3N0YXRlW3RoaXMuU1RBVEVfS0VZLlN1bW1hcnldW2dyb3VwSWRdIHx8IHt9O1xuICAgIH1cblxuICAgIGdldEdyb3VwUm9vbXMoZ3JvdXBJZCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fc3RhdGVbdGhpcy5TVEFURV9LRVkuR3JvdXBSb29tc11bZ3JvdXBJZF0gfHwgW107XG4gICAgfVxuXG4gICAgZ2V0R3JvdXBNZW1iZXJzKGdyb3VwSWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3N0YXRlW3RoaXMuU1RBVEVfS0VZLkdyb3VwTWVtYmVyc11bZ3JvdXBJZF0gfHwgW107XG4gICAgfVxuXG4gICAgZ2V0R3JvdXBJbnZpdGVkTWVtYmVycyhncm91cElkKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9zdGF0ZVt0aGlzLlNUQVRFX0tFWS5Hcm91cEludml0ZWRNZW1iZXJzXVtncm91cElkXSB8fCBbXTtcbiAgICB9XG5cbiAgICBnZXRHcm91cFB1YmxpY2l0eShncm91cElkKSB7XG4gICAgICAgIHJldHVybiAodGhpcy5fc3RhdGVbdGhpcy5TVEFURV9LRVkuU3VtbWFyeV1bZ3JvdXBJZF0gfHwge30pLnVzZXIgP1xuICAgICAgICAgICAgKHRoaXMuX3N0YXRlW3RoaXMuU1RBVEVfS0VZLlN1bW1hcnldW2dyb3VwSWRdIHx8IHt9KS51c2VyLmlzX3B1YmxpY2lzZWQgOiBudWxsO1xuICAgIH1cblxuICAgIGlzVXNlclByaXZpbGVnZWQoZ3JvdXBJZCkge1xuICAgICAgICByZXR1cm4gKHRoaXMuX3N0YXRlW3RoaXMuU1RBVEVfS0VZLlN1bW1hcnldW2dyb3VwSWRdIHx8IHt9KS51c2VyID9cbiAgICAgICAgICAgICh0aGlzLl9zdGF0ZVt0aGlzLlNUQVRFX0tFWS5TdW1tYXJ5XVtncm91cElkXSB8fCB7fSkudXNlci5pc19wcml2aWxlZ2VkIDogbnVsbDtcbiAgICB9XG5cbiAgICByZWZyZXNoR3JvdXBSb29tcyhncm91cElkKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9mZXRjaFJlc291cmNlKHRoaXMuU1RBVEVfS0VZLkdyb3VwUm9vbXMsIGdyb3VwSWQpO1xuICAgIH1cblxuICAgIHJlZnJlc2hHcm91cE1lbWJlcnMoZ3JvdXBJZCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZmV0Y2hSZXNvdXJjZSh0aGlzLlNUQVRFX0tFWS5Hcm91cE1lbWJlcnMsIGdyb3VwSWQpO1xuICAgIH1cblxuICAgIGFkZFJvb21Ub0dyb3VwKGdyb3VwSWQsIHJvb21JZCwgaXNQdWJsaWMpIHtcbiAgICAgICAgcmV0dXJuIE1hdHJpeENsaWVudFBlZy5nZXQoKVxuICAgICAgICAgICAgLmFkZFJvb21Ub0dyb3VwKGdyb3VwSWQsIHJvb21JZCwgaXNQdWJsaWMpXG4gICAgICAgICAgICAudGhlbih0aGlzLl9mZXRjaFJlc291cmNlLmJpbmQodGhpcywgdGhpcy5TVEFURV9LRVkuR3JvdXBSb29tcywgZ3JvdXBJZCkpO1xuICAgIH1cblxuICAgIHVwZGF0ZUdyb3VwUm9vbVZpc2liaWxpdHkoZ3JvdXBJZCwgcm9vbUlkLCBpc1B1YmxpYykge1xuICAgICAgICByZXR1cm4gTWF0cml4Q2xpZW50UGVnLmdldCgpXG4gICAgICAgICAgICAudXBkYXRlR3JvdXBSb29tVmlzaWJpbGl0eShncm91cElkLCByb29tSWQsIGlzUHVibGljKVxuICAgICAgICAgICAgLnRoZW4odGhpcy5fZmV0Y2hSZXNvdXJjZS5iaW5kKHRoaXMsIHRoaXMuU1RBVEVfS0VZLkdyb3VwUm9vbXMsIGdyb3VwSWQpKTtcbiAgICB9XG5cbiAgICByZW1vdmVSb29tRnJvbUdyb3VwKGdyb3VwSWQsIHJvb21JZCkge1xuICAgICAgICByZXR1cm4gTWF0cml4Q2xpZW50UGVnLmdldCgpXG4gICAgICAgICAgICAucmVtb3ZlUm9vbUZyb21Hcm91cChncm91cElkLCByb29tSWQpXG4gICAgICAgICAgICAvLyBSb29tIG1pZ2h0IGJlIGluIHRoZSBzdW1tYXJ5LCByZWZyZXNoIGp1c3QgaW4gY2FzZVxuICAgICAgICAgICAgLnRoZW4odGhpcy5fZmV0Y2hSZXNvdXJjZS5iaW5kKHRoaXMsIHRoaXMuU1RBVEVfS0VZLlN1bW1hcnksIGdyb3VwSWQpKVxuICAgICAgICAgICAgLnRoZW4odGhpcy5fZmV0Y2hSZXNvdXJjZS5iaW5kKHRoaXMsIHRoaXMuU1RBVEVfS0VZLkdyb3VwUm9vbXMsIGdyb3VwSWQpKTtcbiAgICB9XG5cbiAgICBpbnZpdGVVc2VyVG9Hcm91cChncm91cElkLCB1c2VySWQpIHtcbiAgICAgICAgcmV0dXJuIE1hdHJpeENsaWVudFBlZy5nZXQoKS5pbnZpdGVVc2VyVG9Hcm91cChncm91cElkLCB1c2VySWQpXG4gICAgICAgICAgICAudGhlbih0aGlzLl9mZXRjaFJlc291cmNlLmJpbmQodGhpcywgdGhpcy5TVEFURV9LRVkuR3JvdXBJbnZpdGVkTWVtYmVycywgZ3JvdXBJZCkpO1xuICAgIH1cblxuICAgIGFjY2VwdEdyb3VwSW52aXRlKGdyb3VwSWQpIHtcbiAgICAgICAgcmV0dXJuIE1hdHJpeENsaWVudFBlZy5nZXQoKS5hY2NlcHRHcm91cEludml0ZShncm91cElkKVxuICAgICAgICAgICAgLy8gVGhlIHVzZXIgc2hvdWxkIG5vdyBiZSBhYmxlIHRvIGFjY2VzcyAocGVyc29uYWwpIGdyb3VwIHNldHRpbmdzXG4gICAgICAgICAgICAudGhlbih0aGlzLl9mZXRjaFJlc291cmNlLmJpbmQodGhpcywgdGhpcy5TVEFURV9LRVkuU3VtbWFyeSwgZ3JvdXBJZCkpXG4gICAgICAgICAgICAvLyBUaGUgdXNlciBtaWdodCBiZSBhYmxlIHRvIHNlZSBtb3JlIHJvb21zIG5vd1xuICAgICAgICAgICAgLnRoZW4odGhpcy5fZmV0Y2hSZXNvdXJjZS5iaW5kKHRoaXMsIHRoaXMuU1RBVEVfS0VZLkdyb3VwUm9vbXMsIGdyb3VwSWQpKVxuICAgICAgICAgICAgLy8gVGhlIHVzZXIgc2hvdWxkIG5vdyBhcHBlYXIgYXMgYSBtZW1iZXJcbiAgICAgICAgICAgIC50aGVuKHRoaXMuX2ZldGNoUmVzb3VyY2UuYmluZCh0aGlzLCB0aGlzLlNUQVRFX0tFWS5Hcm91cE1lbWJlcnMsIGdyb3VwSWQpKVxuICAgICAgICAgICAgLy8gVGhlIHVzZXIgc2hvdWxkIG5vdyBub3QgYXBwZWFyIGFzIGFuIGludml0ZWQgbWVtYmVyXG4gICAgICAgICAgICAudGhlbih0aGlzLl9mZXRjaFJlc291cmNlLmJpbmQodGhpcywgdGhpcy5TVEFURV9LRVkuR3JvdXBJbnZpdGVkTWVtYmVycywgZ3JvdXBJZCkpO1xuICAgIH1cblxuICAgIGpvaW5Hcm91cChncm91cElkKSB7XG4gICAgICAgIHJldHVybiBNYXRyaXhDbGllbnRQZWcuZ2V0KCkuam9pbkdyb3VwKGdyb3VwSWQpXG4gICAgICAgICAgICAvLyBUaGUgdXNlciBzaG91bGQgbm93IGJlIGFibGUgdG8gYWNjZXNzIChwZXJzb25hbCkgZ3JvdXAgc2V0dGluZ3NcbiAgICAgICAgICAgIC50aGVuKHRoaXMuX2ZldGNoUmVzb3VyY2UuYmluZCh0aGlzLCB0aGlzLlNUQVRFX0tFWS5TdW1tYXJ5LCBncm91cElkKSlcbiAgICAgICAgICAgIC8vIFRoZSB1c2VyIG1pZ2h0IGJlIGFibGUgdG8gc2VlIG1vcmUgcm9vbXMgbm93XG4gICAgICAgICAgICAudGhlbih0aGlzLl9mZXRjaFJlc291cmNlLmJpbmQodGhpcywgdGhpcy5TVEFURV9LRVkuR3JvdXBSb29tcywgZ3JvdXBJZCkpXG4gICAgICAgICAgICAvLyBUaGUgdXNlciBzaG91bGQgbm93IGFwcGVhciBhcyBhIG1lbWJlclxuICAgICAgICAgICAgLnRoZW4odGhpcy5fZmV0Y2hSZXNvdXJjZS5iaW5kKHRoaXMsIHRoaXMuU1RBVEVfS0VZLkdyb3VwTWVtYmVycywgZ3JvdXBJZCkpXG4gICAgICAgICAgICAvLyBUaGUgdXNlciBzaG91bGQgbm93IG5vdCBhcHBlYXIgYXMgYW4gaW52aXRlZCBtZW1iZXJcbiAgICAgICAgICAgIC50aGVuKHRoaXMuX2ZldGNoUmVzb3VyY2UuYmluZCh0aGlzLCB0aGlzLlNUQVRFX0tFWS5Hcm91cEludml0ZWRNZW1iZXJzLCBncm91cElkKSk7XG4gICAgfVxuXG4gICAgbGVhdmVHcm91cChncm91cElkKSB7XG4gICAgICAgIC8vIGVuc3VyZSB0aGUgdGFnIHBhbmVsIGZpbHRlciBpcyBjbGVhcmVkIGlmIHRoZSBncm91cCB3YXMgc2VsZWN0ZWRcbiAgICAgICAgZGlzLmRpc3BhdGNoKHtcbiAgICAgICAgICAgIGFjdGlvbjogXCJkZXNlbGVjdF90YWdzXCIsXG4gICAgICAgICAgICB0YWc6IGdyb3VwSWQsXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gTWF0cml4Q2xpZW50UGVnLmdldCgpLmxlYXZlR3JvdXAoZ3JvdXBJZClcbiAgICAgICAgICAgIC8vIFRoZSB1c2VyIHNob3VsZCBub3cgbm90IGJlIGFibGUgdG8gYWNjZXNzIGdyb3VwIHNldHRpbmdzXG4gICAgICAgICAgICAudGhlbih0aGlzLl9mZXRjaFJlc291cmNlLmJpbmQodGhpcywgdGhpcy5TVEFURV9LRVkuU3VtbWFyeSwgZ3JvdXBJZCkpXG4gICAgICAgICAgICAvLyBUaGUgdXNlciBtaWdodCBvbmx5IGJlIGFibGUgdG8gc2VlIGEgc3Vic2V0IG9mIHJvb21zIG5vd1xuICAgICAgICAgICAgLnRoZW4odGhpcy5fZmV0Y2hSZXNvdXJjZS5iaW5kKHRoaXMsIHRoaXMuU1RBVEVfS0VZLkdyb3VwUm9vbXMsIGdyb3VwSWQpKVxuICAgICAgICAgICAgLy8gVGhlIHVzZXIgc2hvdWxkIG5vdyBub3QgYXBwZWFyIGFzIGEgbWVtYmVyXG4gICAgICAgICAgICAudGhlbih0aGlzLl9mZXRjaFJlc291cmNlLmJpbmQodGhpcywgdGhpcy5TVEFURV9LRVkuR3JvdXBNZW1iZXJzLCBncm91cElkKSk7XG4gICAgfVxuXG4gICAgYWRkUm9vbVRvR3JvdXBTdW1tYXJ5KGdyb3VwSWQsIHJvb21JZCwgY2F0ZWdvcnlJZCkge1xuICAgICAgICByZXR1cm4gTWF0cml4Q2xpZW50UGVnLmdldCgpXG4gICAgICAgICAgICAuYWRkUm9vbVRvR3JvdXBTdW1tYXJ5KGdyb3VwSWQsIHJvb21JZCwgY2F0ZWdvcnlJZClcbiAgICAgICAgICAgIC50aGVuKHRoaXMuX2ZldGNoUmVzb3VyY2UuYmluZCh0aGlzLCB0aGlzLlNUQVRFX0tFWS5TdW1tYXJ5LCBncm91cElkKSk7XG4gICAgfVxuXG4gICAgYWRkVXNlclRvR3JvdXBTdW1tYXJ5KGdyb3VwSWQsIHVzZXJJZCwgcm9sZUlkKSB7XG4gICAgICAgIHJldHVybiBNYXRyaXhDbGllbnRQZWcuZ2V0KClcbiAgICAgICAgICAgIC5hZGRVc2VyVG9Hcm91cFN1bW1hcnkoZ3JvdXBJZCwgdXNlcklkLCByb2xlSWQpXG4gICAgICAgICAgICAudGhlbih0aGlzLl9mZXRjaFJlc291cmNlLmJpbmQodGhpcywgdGhpcy5TVEFURV9LRVkuU3VtbWFyeSwgZ3JvdXBJZCkpO1xuICAgIH1cblxuICAgIHJlbW92ZVJvb21Gcm9tR3JvdXBTdW1tYXJ5KGdyb3VwSWQsIHJvb21JZCkge1xuICAgICAgICByZXR1cm4gTWF0cml4Q2xpZW50UGVnLmdldCgpXG4gICAgICAgICAgICAucmVtb3ZlUm9vbUZyb21Hcm91cFN1bW1hcnkoZ3JvdXBJZCwgcm9vbUlkKVxuICAgICAgICAgICAgLnRoZW4odGhpcy5fZmV0Y2hSZXNvdXJjZS5iaW5kKHRoaXMsIHRoaXMuU1RBVEVfS0VZLlN1bW1hcnksIGdyb3VwSWQpKTtcbiAgICB9XG5cbiAgICByZW1vdmVVc2VyRnJvbUdyb3VwU3VtbWFyeShncm91cElkLCB1c2VySWQpIHtcbiAgICAgICAgcmV0dXJuIE1hdHJpeENsaWVudFBlZy5nZXQoKVxuICAgICAgICAgICAgLnJlbW92ZVVzZXJGcm9tR3JvdXBTdW1tYXJ5KGdyb3VwSWQsIHVzZXJJZClcbiAgICAgICAgICAgIC50aGVuKHRoaXMuX2ZldGNoUmVzb3VyY2UuYmluZCh0aGlzLCB0aGlzLlNUQVRFX0tFWS5TdW1tYXJ5LCBncm91cElkKSk7XG4gICAgfVxuXG4gICAgc2V0R3JvdXBQdWJsaWNpdHkoZ3JvdXBJZCwgaXNQdWJsaXNoZWQpIHtcbiAgICAgICAgcmV0dXJuIE1hdHJpeENsaWVudFBlZy5nZXQoKVxuICAgICAgICAgICAgLnNldEdyb3VwUHVibGljaXR5KGdyb3VwSWQsIGlzUHVibGlzaGVkKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4geyBGbGFpclN0b3JlLmludmFsaWRhdGVQdWJsaWNpc2VkR3JvdXBzKE1hdHJpeENsaWVudFBlZy5nZXQoKS5jcmVkZW50aWFscy51c2VySWQpOyB9KVxuICAgICAgICAgICAgLnRoZW4odGhpcy5fZmV0Y2hSZXNvdXJjZS5iaW5kKHRoaXMsIHRoaXMuU1RBVEVfS0VZLlN1bW1hcnksIGdyb3VwSWQpKTtcbiAgICB9XG59XG5cbmxldCBzaW5nbGV0b25Hcm91cFN0b3JlID0gbnVsbDtcbmlmICghc2luZ2xldG9uR3JvdXBTdG9yZSkge1xuICAgIHNpbmdsZXRvbkdyb3VwU3RvcmUgPSBuZXcgR3JvdXBTdG9yZSgpO1xufVxuZXhwb3J0IGRlZmF1bHQgc2luZ2xldG9uR3JvdXBTdG9yZTtcbiJdfQ==