UNPKG

saij

Version:
313 lines (254 loc) 24.8 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = exports.assertConnectable = void 0; var _Object = _interopRequireDefault(require("../core/Object")); var _Collection = _interopRequireDefault(require("../core/Collection")); var _AssertionError = _interopRequireDefault(require("../core/AssertionError")); var _Errors = _interopRequireDefault(require("../core/Errors")); var _Observable = require("../core/Observable"); var _ConnectionType = _interopRequireDefault(require("./ConnectionType")); /** * @module saij/connection/Connection */ /* eslint max-len: 0 */ /** * A {@link module:saij/connection/Connection~Connection} will be one of the * {@link module:saij/connection/ConnectionType}s. * @typedef {module:saij/connection/ConnectionType} ConnectionType * @property {module:saij/connection/ConnectionType} type * @api */ /** * Key created when a new {@link module:saij/connection/Connection~Connection} * is created. * * @typedef {Object} ConnectionKey * @property {string} id * @property {module:saij/connection/ConnectionType} type * @api */ /** * Object requirements for use with this connection object. Must contains the * `getInput` and `getOuput` functions, that must return {@link module:saij/core/Object}. * @typedef {Object} Connectable * @property {function} getInput returns {@link module:saij/core/Object~BaseObject} * @property {function} getOutput returns {@link module:saij/core/Object~BaseObject} * @api */ /** * Determine if an object is connectable. * @param {Object} obj object to check if Connectable * @return {Boolean} true if object is Connectable * @function * @api */ const assertConnectable = obj => { if (!obj || typeof obj.getInput !== 'function' || typeof obj.getOutput !== 'function') { return false; } if (!(obj.getInput() instanceof _Object.default)) { return false; } if (!(obj.getOutput() instanceof _Object.default)) { return false; } return true; }; /** * @classdesc * A connection is an abstract base class to build * {@link module:saij/connection/ConnectionType}s from. * * A Connection will connect the inputs and outputs of two connectable * objects together. For an object to be connectable it must have `getInput` * and `getOutput` functions that return a {@link module:saij/core/Object}. A * connection will set listeners on the inputs and output that match up, * and forward them on to each other. * * @api */ exports.assertConnectable = assertConnectable; class Connection extends _Object.default { /** * @param {module:saij/connection/Connection~ConnectionKey} connectionKey connection key * @param {module:saij/connection/Connection~Connectable} source forward connectable object * @param {module:saij/connection/Connection~Connectable} destination reverse connectable object */ // eslint-disable-next-line max-statements constructor(connectionKey, source, destination) { super(); if (!assertConnectable(source) || !assertConnectable(destination)) { throw new _AssertionError.default(_Errors.default.ASSERT_CONNECTABLE.code); } /** * @private * @type {module:saij/connection/Connection~ConnectionKey} */ this.key_ = null; /** * @private * @type {module:saij/connection/Connection~ConnectionType} */ this.type_ = null; this.setKey(connectionKey); /** * @private * @type {module:saij/core/Collection~Collection.<module:saij/connection/Connection~Connectable>} */ this.connectables_ = new _Collection.default([source, destination]); /** * @private * @type {module:saij/connection/Connection~Connectable} */ this.source_ = source; /** * @private * @type {module:saij/connection/Connection~Connectable} */ this.destination_ = destination; /** * @private * @type {module:saij/core/Collection~Collection.<module:saij/core/utils/events~EventsKey>} */ this.listeners_ = new _Collection.default(); /** * @private * @type {Boolean} */ this.hasConnection_ = false; // Initialise the connection this.connect(); } /** * Connect the outputs of connectable A to the inputs of * connectable B * @param {module:saij/connection/Connection~Connectable} conA connectable A * @param {module:saij/connection/Connection~Connectable} conB connectable B * @private */ connectOutAtoInB_(conA, conB) { // Get the input and output data objects const outputA = conA.getOutput(); const inputB = conB.getInput(); for (const keyA of Reflect.ownKeys(outputA.getProperties())) { for (const keyB of Reflect.ownKeys(inputB.getProperties())) { if (keyA === keyB) { // Connect outputs of A to inputs of B this.listeners_.push(outputA.on(`change:${keyA}`, () => { inputB.set(keyA, outputA.get(keyA)); })); } } } } /** * Check the connection is setup. * @return {Boolean} true if connected * @api */ isConnected() { return this.hasConnection_; } /** * Check the connection has listeners. * @return {Boolean} true if has listeners * @api */ isListening() { return this.listeners_.getArray().length > 0; } /** * Connect source to destination in the way described by the type. * @return {module:saij/core/Collection~Collection.<module:saij/core/utils/events~EventsKey>} listeners * @api */ connect() { if (!this.hasConnection_) { switch (this.type_) { case _ConnectionType.default.SIMPLEX: { this.connectOutAtoInB_(this.source_, this.destination_); this.hasConnection_ = true; return this.listeners_; } case _ConnectionType.default.DUPLEX: { this.connectOutAtoInB_(this.source_, this.destination_); this.connectOutAtoInB_(this.destination_, this.source_); this.hasConnection_ = true; return this.listeners_; } default: { throw new _AssertionError.default(_Errors.default.ASSERT_CONNECTION_TYPE.code); } } } } /** * Disconnect the connection and clear it's listeners. * @return {Boolean} true if disconnected * @api */ disconnect() { (0, _Observable.unByKey)(this.listeners_.getArray()); this.listeners_.clear(); this.hasConnection_ = false; return true; } /** * Set the connection key. It is advised to use a * {@link module:saij/connection/Connection~ConnectionKey} with a unique id, * unless you wish to group connections. Changing the key type will trigger * a reconnection to occur. * @param {module:saij/connection/Connection~ConnectionKey} key connection key * @return {Boolean} true if set the key * @api */ // eslint-disable-next-line max-statements setKey(key) { if (!key) { throw new _AssertionError.default(_Errors.default.ASSERT_CONNECTION_KEY.code); } const id = key.id; const type = key.type; if (typeof id === 'string' && typeof type === 'string') { // Create new key object in case original object is corrupted this.key_ = { ...key }; if (this.hasConnection_ && type !== this.type_) { this.disconnect(); this.type_ = type; this.connect(); return true; } this.type_ = type; return true; } // A connection key id must be defined and a string if (typeof id !== 'string') { throw new _AssertionError.default(_Errors.default.ASSERT_CONNECTION_ID.code); } // A connection key type must be defined and a string throw new _AssertionError.default(_Errors.default.ASSERT_CONNECTION_TYPE.code); } /** * Get the connection key. * @return {module:saij/connection/Connection~ConnectionKey} connection key * @api */ getKey() { return this.key_; } /** * Get the listeners keys for all the input/output listeners on the connection. * @return {module:saij/core/Collection<module:saij/core/utils/events~EventsKey>} connection key * @api */ getListeners() { return this.listeners_; } } var _default = Connection; exports.default = _default; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9zYWlqL2Nvbm5lY3Rpb24vQ29ubmVjdGlvbi5qcyJdLCJuYW1lcyI6WyJhc3NlcnRDb25uZWN0YWJsZSIsIm9iaiIsImdldElucHV0IiwiZ2V0T3V0cHV0IiwiQmFzZU9iamVjdCIsIkNvbm5lY3Rpb24iLCJjb25zdHJ1Y3RvciIsImNvbm5lY3Rpb25LZXkiLCJzb3VyY2UiLCJkZXN0aW5hdGlvbiIsIkFzc2VydGlvbkVycm9yIiwiRXJyb3JzIiwiQVNTRVJUX0NPTk5FQ1RBQkxFIiwiY29kZSIsImtleV8iLCJ0eXBlXyIsInNldEtleSIsImNvbm5lY3RhYmxlc18iLCJDb2xsZWN0aW9uIiwic291cmNlXyIsImRlc3RpbmF0aW9uXyIsImxpc3RlbmVyc18iLCJoYXNDb25uZWN0aW9uXyIsImNvbm5lY3QiLCJjb25uZWN0T3V0QXRvSW5CXyIsImNvbkEiLCJjb25CIiwib3V0cHV0QSIsImlucHV0QiIsImtleUEiLCJSZWZsZWN0Iiwib3duS2V5cyIsImdldFByb3BlcnRpZXMiLCJrZXlCIiwicHVzaCIsIm9uIiwic2V0IiwiZ2V0IiwiaXNDb25uZWN0ZWQiLCJpc0xpc3RlbmluZyIsImdldEFycmF5IiwibGVuZ3RoIiwiQ29ubmVjdGlvblR5cGUiLCJTSU1QTEVYIiwiRFVQTEVYIiwiQVNTRVJUX0NPTk5FQ1RJT05fVFlQRSIsImRpc2Nvbm5lY3QiLCJjbGVhciIsImtleSIsIkFTU0VSVF9DT05ORUNUSU9OX0tFWSIsImlkIiwidHlwZSIsIkFTU0VSVF9DT05ORUNUSU9OX0lEIiwiZ2V0S2V5IiwiZ2V0TGlzdGVuZXJzIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7QUFJQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFUQTs7OztBQVlBOztBQUdBOzs7Ozs7OztBQVFBOzs7Ozs7Ozs7O0FBVUE7Ozs7Ozs7OztBQVVBOzs7Ozs7O0FBT08sTUFBTUEsaUJBQWlCLEdBQUlDLEdBQUQsSUFBUTtBQUN2QyxNQUNFLENBQUNBLEdB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Wjs7QUFFQSxVQUFJLEtBQUsxQixjQUFMLElBQXVCNkIsSUFBSSxLQUFLLEtBQUtwQyxLQUF6QyxFQUFnRDtBQUM5QyxhQUFLK0IsVUFBTDtBQUNBLGFBQUsvQixLQUFMLEdBQWFvQyxJQUFiO0FBQ0EsYUFBSzVCLE9BQUw7QUFDQSxlQUFPLElBQVA7QUFDRDs7QUFFRCxXQUFLUixLQUFMLEdBQWFvQyxJQUFiO0FBQ0EsYUFBTyxJQUFQO0FBQ0QsS0FyQlMsQ0FzQlY7OztBQUNBLFFBQUksT0FBT0QsRUFBUCxLQUFjLFFBQWxCLEVBQTRCO0FBQzFCLFlBQU0sSUFBSXhDLHVCQUFKLENBQW1CQyxnQkFBT3lDLG9CQUFQLENBQTRCdkMsSUFBL0MsQ0FBTjtBQUNELEtBekJTLENBMEJWOzs7QUFDQSxVQUFNLElBQUlILHVCQUFKLENBQW1CQyxnQkFBT2tDLHNCQUFQLENBQThCaEMsSUFBakQsQ0FBTjtBQUNEO0FBRUQ7Ozs7Ozs7QUFLQXdDLEVBQUFBLE1BQU0sR0FBRztBQUNQLFdBQU8sS0FBS3ZDLElBQVo7QUFDRDtBQUVEOzs7Ozs7O0FBS0F3QyxFQUFBQSxZQUFZLEdBQUc7QUFDYixXQUFPLEtBQUtqQyxVQUFaO0FBQ0Q7O0FBck1pQzs7ZUF3TXJCaEIsVSIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQG1vZHVsZSBzYWlqL2Nvbm5lY3Rpb24vQ29ubmVjdGlvblxuICovXG5cbmltcG9ydCBCYXNlT2JqZWN0IGZyb20gJy4uL2NvcmUvT2JqZWN0JztcbmltcG9ydCBDb2xsZWN0aW9uIGZyb20gJy4uL2NvcmUvQ29sbGVjdGlvbic7XG5pbXBvcnQgQXNzZXJ0aW9uRXJyb3IgZnJvbSAnLi4vY29yZS9Bc3NlcnRpb25FcnJvcic7XG5pbXBvcnQgRXJyb3JzIGZyb20gJy4uL2NvcmUvRXJyb3JzJztcbmltcG9ydCB7dW5CeUtleX0gZnJvbSAnLi4vY29yZS9PYnNlcnZhYmxlJztcbmltcG9ydCBDb25uZWN0aW9uVHlwZSBmcm9tICcuL0Nvbm5lY3Rpb25UeXBlJztcblxuXG4vKiBlc2xpbnQgbWF4LWxlbjogMCAqL1xuXG5cbi8qKlxuICogQSB7QGxpbmsgbW9kdWxlOnNhaWovY29ubmVjdGlvbi9Db25uZWN0aW9ufkNvbm5lY3Rpb259IHdpbGwgYmUgb25lIG9mIHRoZVxuICoge0BsaW5rIG1vZHVsZTpzYWlqL2Nvbm5lY3Rpb24vQ29ubmVjdGlvblR5cGV9cy5cbiAqIEB0eXBlZGVmIHttb2R1bGU6c2Fpai9jb25uZWN0aW9uL0Nvbm5lY3Rpb25UeXBlfSBDb25uZWN0aW9uVHlwZVxuICogQHByb3BlcnR5IHttb2R1bGU6c2Fpai9jb25uZWN0aW9uL0Nvbm5lY3Rpb25UeXBlfSB0eXBlXG4gKiBAYXBpXG4gKi9cblxuLyoqXG4gKiBLZXkgY3JlYXRlZCB3aGVuIGEgbmV3IHtAbGluayBtb2R1bGU6c2Fpai9jb25uZWN0aW9uL0Nvbm5lY3Rpb25+Q29ubmVjdGlvbn1cbiAqIGlzIGNyZWF0ZWQuXG4gKlxuICogQHR5cGVkZWYge09iamVjdH0gQ29ubmVjdGlvbktleVxuICogQHByb3BlcnR5IHtzdHJpbmd9IGlkXG4gKiBAcHJvcGVydHkge21vZHVsZTpzYWlqL2Nvbm5lY3Rpb24vQ29ubmVjdGlvblR5cGV9IHR5cGVcbiAqIEBhcGlcbiAqL1xuXG4vKipcbiAqIE9iamVjdCByZXF1aXJlbWVudHMgZm9yIHVzZSB3aXRoIHRoaXMgY29ubmVjdGlvbiBvYmplY3QuIE11c3QgY29udGFpbnMgdGhlXG4gKiBgZ2V0SW5wdXRgIGFuZCBgZ2V0T3VwdXRgIGZ1bmN0aW9ucywgdGhhdCBtdXN0IHJldHVybiB7QGxpbmsgbW9kdWxlOnNhaWovY29yZS9PYmplY3R9LlxuICogQHR5cGVkZWYge09iamVjdH0gQ29ubmVjdGFibGVcbiAqIEBwcm9wZXJ0eSB7ZnVuY3Rpb259IGdldElucHV0IHJldHVybnMge0BsaW5rIG1vZHVsZTpzYWlqL2NvcmUvT2JqZWN0fkJhc2VPYmplY3R9XG4gKiBAcHJvcGVydHkge2Z1bmN0aW9ufSBnZXRPdXRwdXQgcmV0dXJucyB7QGxpbmsgbW9kdWxlOnNhaWovY29yZS9PYmplY3R+QmFzZU9iamVjdH1cbiAqIEBhcGlcbiovXG5cblxuLyoqXG4gKiBEZXRlcm1pbmUgaWYgYW4gb2JqZWN0IGlzIGNvbm5lY3RhYmxlLlxuICogQHBhcmFtICB7T2JqZWN0fSBvYmogb2JqZWN0IHRvIGNoZWNrIGlmIENvbm5lY3RhYmxlXG4gKiBAcmV0dXJuIHtCb29sZWFufSB0cnVlIGlmIG9iamVjdCBpcyBDb25uZWN0YWJsZVxuICogQGZ1bmN0aW9uXG4gKiBAYXBpXG4gKi9cbmV4cG9ydCBjb25zdCBhc3NlcnRDb25uZWN0YWJsZSA9IChvYmopPT4ge1xuICBpZiAoXG4gICAgIW9ialxuICAgIHx8IHR5cGVvZiBvYmouZ2V0SW5wdXQgIT09ICdmdW5jdGlvbidcbiAgICB8fCB0eXBlb2Ygb2JqLmdldE91dHB1dCAhPT0gJ2Z1bmN0aW9uJ1xuICApIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBpZiAoIShvYmouZ2V0SW5wdXQoKSBpbnN0YW5jZW9mIEJhc2VPYmplY3QpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgaWYgKCEob2JqLmdldE91dHB1dCgpIGluc3RhbmNlb2YgQmFzZU9iamVjdCkpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn07XG5cblxuLyoqXG4gKiBAY2xhc3NkZXNjXG4gKiBBIGNvbm5lY3Rpb24gaXMgYW4gYWJzdHJhY3QgYmFzZSBjbGFzcyB0byBidWlsZFxuICoge0BsaW5rIG1vZHVsZTpzYWlqL2Nvbm5lY3Rpb24vQ29ubmVjdGlvblR5cGV9cyBmcm9tLlxuICpcbiAqIEEgQ29ubmVjdGlvbiB3aWxsIGNvbm5lY3QgdGhlIGlucHV0cyBhbmQgb3V0cHV0cyBvZiB0d28gY29ubmVjdGFibGVcbiAqIG9iamVjdHMgdG9nZXRoZXIuICBGb3IgYW4gb2JqZWN0IHRvIGJlIGNvbm5lY3RhYmxlIGl0IG11c3QgaGF2ZSBgZ2V0SW5wdXRgXG4gKiBhbmQgYGdldE91dHB1dGAgZnVuY3Rpb25zIHRoYXQgcmV0dXJuIGEge0BsaW5rIG1vZHVsZTpzYWlqL2NvcmUvT2JqZWN0fS4gQVxuICogY29ubmVjdGlvbiB3aWxsIHNldCBsaXN0ZW5lcnMgb24gdGhlIGlucHV0cyBhbmQgb3V0cHV0IHRoYXQgbWF0Y2ggdXAsXG4gKiBhbmQgZm9yd2FyZCB0aGVtIG9uIHRvIGVhY2ggb3RoZXIuXG4gKlxuICogQGFwaVxuICovXG5jbGFzcyBDb25uZWN0aW9uIGV4dGVuZHMgQmFzZU9iamVjdCB7XG4gIC8qKlxuICAgKiBAcGFyYW0gIHttb2R1bGU6c2Fpai9jb25uZWN0aW9uL0Nvbm5lY3Rpb25+Q29ubmVjdGlvbktleX0gY29ubmVjdGlvbktleSBjb25uZWN0aW9uIGtleVxuICAgKiBAcGFyYW0gIHttb2R1bGU6c2Fpai9jb25uZWN0aW9uL0Nvbm5lY3Rpb25+Q29ubmVjdGFibGV9IHNvdXJjZSBmb3J3YXJkIGNvbm5lY3RhYmxlIG9iamVjdFxuICAgKiBAcGFyYW0gIHttb2R1bGU6c2Fpai9jb25uZWN0aW9uL0Nvbm5lY3Rpb25+Q29ubmVjdGFibGV9IGRlc3RpbmF0aW9uIHJldmVyc2UgY29ubmVjdGFibGUgb2JqZWN0XG4gICAqL1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbWF4LXN0YXRlbWVudHNcbiAgY29uc3RydWN0b3IoY29ubmVjdGlvbktleSwgc291cmNlLCBkZXN0aW5hdGlvbikge1xuICAgIHN1cGVyKCk7XG5cbiAgICBpZiAoIWFzc2VydENvbm5lY3RhYmxlKHNvdXJjZSkgfHwgIWFzc2VydENvbm5lY3RhYmxlKGRlc3RpbmF0aW9uKSkge1xuICAgICAgdGhyb3cgbmV3IEFzc2VydGlvbkVycm9yKEVycm9ycy5BU1NFUlRfQ09OTkVDVEFCTEUuY29kZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bW9kdWxlOnNhaWovY29ubmVjdGlvbi9Db25uZWN0aW9ufkNvbm5lY3Rpb25LZXl9XG4gICAgICovXG4gICAgdGhpcy5rZXlfID0gbnVsbDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHttb2R1bGU6c2Fpai9jb25uZWN0aW9uL0Nvbm5lY3Rpb25+Q29ubmVjdGlvblR5cGV9XG4gICAgICovXG4gICAgdGhpcy50eXBlXyA9IG51bGw7XG5cbiAgICB0aGlzLnNldEtleShjb25uZWN0aW9uS2V5KTtcblxuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge21vZHVsZTpzYWlqL2NvcmUvQ29sbGVjdGlvbn5Db2xsZWN0aW9uLjxtb2R1bGU6c2Fpai9jb25uZWN0aW9uL0Nvbm5lY3Rpb25+Q29ubmVjdGFibGU+fVxuICAgICAqL1xuICAgIHRoaXMuY29ubmVjdGFibGVzXyA9IG5ldyBDb2xsZWN0aW9uKFtzb3VyY2UsIGRlc3RpbmF0aW9uXSk7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bW9kdWxlOnNhaWovY29ubmVjdGlvbi9Db25uZWN0aW9ufkNvbm5lY3RhYmxlfVxuICAgICAqL1xuICAgIHRoaXMuc291cmNlXyA9IHNvdXJjZTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHttb2R1bGU6c2Fpai9jb25uZWN0aW9uL0Nvbm5lY3Rpb25+Q29ubmVjdGFibGV9XG4gICAgICovXG4gICAgdGhpcy5kZXN0aW5hdGlvbl8gPSBkZXN0aW5hdGlvbjtcblxuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge21vZHVsZTpzYWlqL2NvcmUvQ29sbGVjdGlvbn5Db2xsZWN0aW9uLjxtb2R1bGU6c2Fpai9jb3JlL3V0aWxzL2V2ZW50c35FdmVudHNLZXk+fVxuICAgICAqL1xuICAgIHRoaXMubGlzdGVuZXJzXyA9IG5ldyBDb2xsZWN0aW9uKCk7XG5cbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtCb29sZWFufVxuICAgICAqL1xuICAgIHRoaXMuaGFzQ29ubmVjdGlvbl8gPSBmYWxzZTtcblxuICAgIC8vIEluaXRpYWxpc2UgdGhlIGNvbm5lY3Rpb25cbiAgICB0aGlzLmNvbm5lY3QoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb25uZWN0IHRoZSBvdXRwdXRzIG9mIGNvbm5lY3RhYmxlIEEgdG8gdGhlIGlucHV0cyBvZlxuICAgKiBjb25uZWN0YWJsZSBCXG4gICAqIEBwYXJhbSB7bW9kdWxlOnNhaWovY29ubmVjdGlvbi9Db25uZWN0aW9ufkNvbm5lY3RhYmxlfSBjb25BIGNvbm5lY3RhYmxlIEFcbiAgICogQHBhcmFtIHttb2R1bGU6c2Fpai9jb25uZWN0aW9uL0Nvbm5lY3Rpb25+Q29ubmVjdGFibGV9IGNvbkIgY29ubmVjdGFibGUgQlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgY29ubmVjdE91dEF0b0luQl8oY29uQSwgY29uQikge1xuICAgIC8vIEdldCB0aGUgaW5wdXQgYW5kIG91dHB1dCBkYXRhIG9iamVjdHNcbiAgICBjb25zdCBvdXRwdXRBID0gY29uQS5nZXRPdXRwdXQoKTtcbiAgICBjb25zdCBpbnB1dEIgPSBjb25CLmdldElucHV0KCk7XG5cbiAgICBmb3IgKGNvbnN0IGtleUEgb2YgUmVmbGVjdC5vd25LZXlzKG91dHB1dEEuZ2V0UHJvcGVydGllcygpKSkge1xuICAgICAgZm9yIChjb25zdCBrZXlCIG9mIFJlZmxlY3Qub3duS2V5cyhpbnB1dEIuZ2V0UHJvcGVydGllcygpKSkge1xuICAgICAgICBpZiAoa2V5QSA9PT0ga2V5Qikge1xuICAgICAgICAgIC8vIENvbm5lY3Qgb3V0cHV0cyBvZiBBIHRvIGlucHV0cyBvZiBCXG4gICAgICAgICAgdGhpcy5saXN0ZW5lcnNfLnB1c2goXG4gICAgICAgICAgICBvdXRwdXRBLm9uKGBjaGFuZ2U6JHtrZXlBfWAsICgpPT4ge1xuICAgICAgICAgICAgICBpbnB1dEIuc2V0KGtleUEsIG91dHB1dEEuZ2V0KGtleUEpKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayB0aGUgY29ubmVjdGlvbiBpcyBzZXR1cC5cbiAgICogQHJldHVybiB7Qm9vbGVhbn0gdHJ1ZSBpZiBjb25uZWN0ZWRcbiAgICogQGFwaVxuICAgKi9cbiAgaXNDb25uZWN0ZWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuaGFzQ29ubmVjdGlvbl87XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgdGhlIGNvbm5lY3Rpb24gaGFzIGxpc3RlbmVycy5cbiAgICogQHJldHVybiB7Qm9vbGVhbn0gdHJ1ZSBpZiBoYXMgbGlzdGVuZXJzXG4gICAqIEBhcGlcbiAgICovXG4gIGlzTGlzdGVuaW5nKCkge1xuICAgIHJldHVybiB0aGlzLmxpc3RlbmVyc18uZ2V0QXJyYXkoKS5sZW5ndGggPiAwO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbm5lY3Qgc291cmNlIHRvIGRlc3RpbmF0aW9uIGluIHRoZSB3YXkgZGVzY3JpYmVkIGJ5IHRoZSB0eXBlLlxuICAgKiBAcmV0dXJuIHttb2R1bGU6c2Fpai9jb3JlL0NvbGxlY3Rpb25+Q29sbGVjdGlvbi48bW9kdWxlOnNhaWovY29yZS91dGlscy9ldmVudHN+RXZlbnRzS2V5Pn0gbGlzdGVuZXJzXG4gICAqIEBhcGlcbiAgICovXG4gIGNvbm5lY3QoKSB7XG4gICAgaWYgKCF0aGlzLmhhc0Nvbm5lY3Rpb25fKSB7XG4gICAgICBzd2l0Y2ggKHRoaXMudHlwZV8pIHtcbiAgICAgICAgY2FzZSBDb25uZWN0aW9uVHlwZS5TSU1QTEVYOiB7XG4gICAgICAgICAgdGhpcy5jb25uZWN0T3V0QXRvSW5CXyh0aGlzLnNvdXJjZV8sIHRoaXMuZGVzdGluYXRpb25fKTtcbiAgICAgICAgICB0aGlzLmhhc0Nvbm5lY3Rpb25fID0gdHJ1ZTtcbiAgICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lcnNfO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgQ29ubmVjdGlvblR5cGUuRFVQTEVYOiB7XG4gICAgICAgICAgdGhpcy5jb25uZWN0T3V0QXRvSW5CXyh0aGlzLnNvdXJjZV8sIHRoaXMuZGVzdGluYXRpb25fKTtcbiAgICAgICAgICB0aGlzLmNvbm5lY3RPdXRBdG9JbkJfKHRoaXMuZGVzdGluYXRpb25fLCB0aGlzLnNvdXJjZV8pO1xuICAgICAgICAgIHRoaXMuaGFzQ29ubmVjdGlvbl8gPSB0cnVlO1xuICAgICAgICAgIHJldHVybiB0aGlzLmxpc3RlbmVyc187XG4gICAgICAgIH1cbiAgICAgICAgZGVmYXVsdDoge1xuICAgICAgICAgIHRocm93IG5ldyBBc3NlcnRpb25FcnJvcihFcnJvcnMuQVNTRVJUX0NPTk5FQ1RJT05fVFlQRS5jb2RlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEaXNjb25uZWN0IHRoZSBjb25uZWN0aW9uIGFuZCBjbGVhciBpdCdzIGxpc3RlbmVycy5cbiAgICogQHJldHVybiB7Qm9vbGVhbn0gdHJ1ZSBpZiBkaXNjb25uZWN0ZWRcbiAgICogQGFwaVxuICAgKi9cbiAgZGlzY29ubmVjdCgpIHtcbiAgICB1bkJ5S2V5KHRoaXMubGlzdGVuZXJzXy5nZXRBcnJheSgpKTtcbiAgICB0aGlzLmxpc3RlbmVyc18uY2xlYXIoKTtcbiAgICB0aGlzLmhhc0Nvbm5lY3Rpb25fID0gZmFsc2U7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHRoZSBjb25uZWN0aW9uIGtleS4gSXQgaXMgYWR2aXNlZCB0byB1c2UgYVxuICAgKiB7QGxpbmsgbW9kdWxlOnNhaWovY29ubmVjdGlvbi9Db25uZWN0aW9ufkNvbm5lY3Rpb25LZXl9IHdpdGggYSB1bmlxdWUgaWQsXG4gICAqIHVubGVzcyB5b3Ugd2lzaCB0byBncm91cCBjb25uZWN0aW9ucy4gIENoYW5naW5nIHRoZSBrZXkgdHlwZSB3aWxsIHRyaWdnZXJcbiAgICogYSByZWNvbm5lY3Rpb24gdG8gb2NjdXIuXG4gICAqIEBwYXJhbSB7bW9kdWxlOnNhaWovY29ubmVjdGlvbi9Db25uZWN0aW9ufkNvbm5lY3Rpb25LZXl9IGtleSBjb25uZWN0aW9uIGtleVxuICAgKiBAcmV0dXJuIHtCb29sZWFufSB0cnVlIGlmIHNldCB0aGUga2V5XG4gICAqIEBhcGlcbiAgICovXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBtYXgtc3RhdGVtZW50c1xuICBzZXRLZXkoa2V5KSB7XG4gICAgaWYgKCFrZXkpIHtcbiAgICAgIHRocm93IG5ldyBBc3NlcnRpb25FcnJvcihFcnJvcnMuQVNTRVJUX0NPTk5FQ1RJT05fS0VZLmNvZGUpO1xuICAgIH1cblxuICAgIGNvbnN0IGlkID0ga2V5LmlkO1xuICAgIGNvbnN0IHR5cGUgPSBrZXkudHlwZTtcblxuICAgIGlmICh0eXBlb2YgaWQgPT09ICdzdHJpbmcnICYmIHR5cGVvZiB0eXBlID09PSAnc3RyaW5nJykge1xuICAgICAgLy8gQ3JlYXRlIG5ldyBrZXkgb2JqZWN0IGluIGNhc2Ugb3JpZ2luYWwgb2JqZWN0IGlzIGNvcnJ1cHRlZFxuICAgICAgdGhpcy5rZXlfID0gey4uLmtleX07XG5cbiAgICAgIGlmICh0aGlzLmhhc0Nvbm5lY3Rpb25fICYmIHR5cGUgIT09IHRoaXMudHlwZV8pIHtcbiAgICAgICAgdGhpcy5kaXNjb25uZWN0KCk7XG4gICAgICAgIHRoaXMudHlwZV8gPSB0eXBlO1xuICAgICAgICB0aGlzLmNvbm5lY3QoKTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG5cbiAgICAgIHRoaXMudHlwZV8gPSB0eXBlO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIC8vIEEgY29ubmVjdGlvbiBrZXkgaWQgbXVzdCBiZSBkZWZpbmVkIGFuZCBhIHN0cmluZ1xuICAgIGlmICh0eXBlb2YgaWQgIT09ICdzdHJpbmcnKSB7XG4gICAgICB0aHJvdyBuZXcgQXNzZXJ0aW9uRXJyb3IoRXJyb3JzLkFTU0VSVF9DT05ORUNUSU9OX0lELmNvZGUpO1xuICAgIH1cbiAgICAvLyBBIGNvbm5lY3Rpb24ga2V5IHR5cGUgbXVzdCBiZSBkZWZpbmVkIGFuZCBhIHN0cmluZ1xuICAgIHRocm93IG5ldyBBc3NlcnRpb25FcnJvcihFcnJvcnMuQVNTRVJUX0NPTk5FQ1RJT05fVFlQRS5jb2RlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIGNvbm5lY3Rpb24ga2V5LlxuICAgKiBAcmV0dXJuIHttb2R1bGU6c2Fpai9jb25uZWN0aW9uL0Nvbm5lY3Rpb25+Q29ubmVjdGlvbktleX0gY29ubmVjdGlvbiBrZXlcbiAgICogQGFwaVxuICAgKi9cbiAgZ2V0S2V5KCkge1xuICAgIHJldHVybiB0aGlzLmtleV87XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBsaXN0ZW5lcnMga2V5cyBmb3IgYWxsIHRoZSBpbnB1dC9vdXRwdXQgbGlzdGVuZXJzIG9uIHRoZSBjb25uZWN0aW9uLlxuICAgKiBAcmV0dXJuIHttb2R1bGU6c2Fpai9jb3JlL0NvbGxlY3Rpb248bW9kdWxlOnNhaWovY29yZS91dGlscy9ldmVudHN+RXZlbnRzS2V5Pn0gY29ubmVjdGlvbiBrZXlcbiAgICogQGFwaVxuICAgKi9cbiAgZ2V0TGlzdGVuZXJzKCkge1xuICAgIHJldHVybiB0aGlzLmxpc3RlbmVyc187XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgQ29ubmVjdGlvbjtcbiJdfQ==