UNPKG

kepler.gl

Version:

kepler.gl is a webgl based application to visualize large scale location data in the browser

386 lines (346 loc) 26 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = void 0; var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var _icons = require("../components/common/icons"); // Copyright (c) 2020 Uber Technologies, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. var NAME = 'cloud-provider'; var DISPLAY_NAME = 'Cloud Provider'; var THUMBNAIL = { width: 300, height: 200 }; var ICON = _icons.Upload; /** * The default provider class * @param {object} props * @param {string} props.name * @param {string} props.displayName * @param {ReactElement} props.icon - React element * @param {object} props.thumbnail - thumbnail size object * @param {number} props.thumbnail.width - thumbnail width in pixels * @param {number} props.thumbnail.height - thumbnail height in pixels * @public * @example * * const myProvider = new Provider({ * name: 'foo', * displayName: 'Foo Storage' * icon: Icon, * thumbnail: {width: 300, height: 200} * }) */ var Provider = /*#__PURE__*/ function () { function Provider(props) { (0, _classCallCheck2["default"])(this, Provider); this.name = props.name || NAME; this.displayName = props.displayName || DISPLAY_NAME; this.icon = props.icon || ICON; this.thumbnail = props.thumbnail || THUMBNAIL; } /** * Whether this provider support upload map to a private storage. If truthy, user will be displayed with the storage save icon on the top right of the side bar. * @returns {boolean} * @public */ (0, _createClass2["default"])(Provider, [{ key: "hasPrivateStorage", value: function hasPrivateStorage() { return true; } /** * Whether this provider support share map via a public url, if truthy, user will be displayed with a share map via url under the export map option on the top right of the side bar * @returns {boolean} * @public */ }, { key: "hasSharingUrl", value: function hasSharingUrl() { return true; } /** * This method is called after user share a map, to display the share url. * @param {boolean} fullUrl - Whether to return the full url with domain, or just the location * @returns {string} shareUrl * @public */ }, { key: "getShareUrl", value: function getShareUrl() { var fullUrl = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; return ''; } /** * This method is called by kepler.gl demo app to pushes a new location to history, becoming the current location. * @param {boolean} fullURL - Whether to return the full url with domain, or just the location * @returns {string} mapUrl * @public */ }, { key: "getMapUrl", value: function getMapUrl() { var fullURL = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; return ''; } /** * This method is called to determine whether user already logged in to this provider * @public * @returns {boolean} true if a user already logged in */ }, { key: "getAccessToken", value: function getAccessToken() { return true; } /** * This method is called to get the user name of the current user. It will be displayed in the cloud provider tile. * @public * @returns {string} true if a user already logged in */ }, { key: "getUserName", value: function getUserName() { return ''; } /** * This method will be called when user click the login button in the cloud provider tile. * Upon login success, `onCloudLoginSuccess` has to be called to notify kepler.gl UI * @param {function} onCloudLoginSuccess - callbacks to be called after login success * @public */ }, { key: "login", value: function () { var _login = (0, _asyncToGenerator2["default"])( /*#__PURE__*/ _regenerator["default"].mark(function _callee(onCloudLoginSuccess) { return _regenerator["default"].wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: onCloudLoginSuccess(); return _context.abrupt("return"); case 2: case "end": return _context.stop(); } } }, _callee); })); function login(_x) { return _login.apply(this, arguments); } return login; }() /** * This method will be called when user click the logout button under the cloud provider tile. * Upon login success, `onCloudLoginSuccess` has to be called to notify kepler.gl UI * @param {function} onCloudLogoutSuccess - callbacks to be called after logout success * @public */ }, { key: "logout", value: function () { var _logout = (0, _asyncToGenerator2["default"])( /*#__PURE__*/ _regenerator["default"].mark(function _callee2(onCloudLogoutSuccess) { return _regenerator["default"].wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: onCloudLogoutSuccess(); return _context2.abrupt("return"); case 2: case "end": return _context2.stop(); } } }, _callee2); })); function logout(_x2) { return _logout.apply(this, arguments); } return logout; }() /** * This method will be called to upload map for saving and sharing. Kepler.gl will package map data, config, title, description and thumbnail for upload to storage. * With the option to overwrite already saved map, and upload as private or public map. * * @param {Object} param * @param {Object} param.mapData - the map object * @param {Object} param.mapData.map - {datasets. config, info: {title, description}} * @param {Blob} param.mapData.thumbnail - A thumbnail of current map. thumbnail size can be defined by provider by this.thumbnail * @param {Object} param.options * @param {boolean} param.options.overwrite - whether user choose to overwrite already saved map under the same name * @param {boolean} param.options.isPublic - whether user wish to share the map with others. if isPublic is truthy, kepler will call this.getShareUrl() to display an URL they can share with others * @public */ }, { key: "uploadMap", value: function () { var _uploadMap = (0, _asyncToGenerator2["default"])( /*#__PURE__*/ _regenerator["default"].mark(function _callee3(_ref) { var mapData, _ref$options, options; return _regenerator["default"].wrap(function _callee3$(_context3) { while (1) { switch (_context3.prev = _context3.next) { case 0: mapData = _ref.mapData, _ref$options = _ref.options, options = _ref$options === void 0 ? {} : _ref$options; return _context3.abrupt("return"); case 2: case "end": return _context3.stop(); } } }, _callee3); })); function uploadMap(_x3) { return _uploadMap.apply(this, arguments); } return uploadMap; }() /** * This method is called to get a list of maps saved by the current logged in user. * @returns {Array<Viz>} an array of Viz objects * @public * @example * async listMaps() { * return [ * { * id: 'a', * title: 'My map', * description: 'My first kepler map', * imageUrl: 'http://', * lastModification: 1582677787000, * privateMap: false, * loadParams: {} * } * ]; * } */ }, { key: "listMaps", value: function () { var _listMaps = (0, _asyncToGenerator2["default"])( /*#__PURE__*/ _regenerator["default"].mark(function _callee4() { return _regenerator["default"].wrap(function _callee4$(_context4) { while (1) { switch (_context4.prev = _context4.next) { case 0: return _context4.abrupt("return", []); case 1: case "end": return _context4.stop(); } } }, _callee4); })); function listMaps() { return _listMaps.apply(this, arguments); } return listMaps; }() /** * This method will be called when user select a map to load from the storage map viewer * @param {*} loadParams - the loadParams property of each visualization object * @returns {MapResponse} - the map object containing dataset config info and format option * @public * @example * async downloadMap(loadParams) { * const mockResponse = { * map: { * datasets: [], * config: {}, * info: { * app: 'kepler.gl', * created_at: '' * title: 'test map', * description: 'Hello this is my test dropbox map' * } * }, * // pass csv here if your provider currently only support save / load file as csv * format: 'keplergl' * }; * * return downloadMap; * } */ }, { key: "downloadMap", value: function () { var _downloadMap = (0, _asyncToGenerator2["default"])( /*#__PURE__*/ _regenerator["default"].mark(function _callee5(loadParams) { return _regenerator["default"].wrap(function _callee5$(_context5) { while (1) { switch (_context5.prev = _context5.next) { case 0: return _context5.abrupt("return"); case 1: case "end": return _context5.stop(); } } }, _callee5); })); function downloadMap(_x4) { return _downloadMap.apply(this, arguments); } return downloadMap; }() /** * @typedef {Object} Viz * @property {string} id - An unique id * @property {string} title - The title of the map * @property {string} description - The description of the map * @property {string} imageUrl - The imageUrl of the map * @property {number} lastModification - An epoch timestamp in milliseconds * @property {boolean} privateMap - Optional, whether if this map is private to the user, or can be accessed by others via URL * @property {*} loadParams - A property to be passed to `downloadMap` * @public */ /** * The returned object of `downloadMap`. The response object should contain: datasets: [], config: {}, and info: {} * each dataset object should be {info: {id, label}, data: {...}} * to inform how kepler should process your data object, pass in `format` * @typedef {Object} MapResponse * @property {Object} map * @property {Array<Object>} map.datasets * @property {Object} map.config * @property {Object} map.info * @property {string} format - one of 'csv': csv file string, 'geojson': geojson object, 'row': row object, 'keplergl': datasets array saved using KeplerGlSchema.save * @public */ }]); return Provider; }(); exports["default"] = Provider; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jbG91ZC1wcm92aWRlcnMvcHJvdmlkZXIuanMiXSwibmFtZXMiOlsiTkFNRSIsIkRJU1BMQVlfTkFNRSIsIlRIVU1CTkFJTCIsIndpZHRoIiwiaGVpZ2h0IiwiSUNPTiIsIlVwbG9hZCIsIlByb3ZpZGVyIiwicHJvcHMiLCJuYW1lIiwiZGlzcGxheU5hbWUiLCJpY29uIiwidGh1bWJuYWlsIiwiZnVsbFVybCIsImZ1bGxVUkwiLCJvbkNsb3VkTG9naW5TdWNjZXNzIiwib25DbG91ZExvZ291dFN1Y2Nlc3MiLCJtYXBEYXRhIiwib3B0aW9ucyIsImxvYWRQYXJhbXMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBb0JBOztBQXBCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUlBLElBQU1BLElBQUksR0FBRyxnQkFBYjtBQUNBLElBQU1DLFlBQVksR0FBRyxnQkFBckI7QUFDQSxJQUFNQyxTQUFTLEdBQUc7QUFBQ0MsRUFBQUEsS0FBSyxFQUFFLEdBQVI7QUFBYUMsRUFBQUEsTUFBTSxFQUFFO0FBQXJCLENBQWxCO0FBQ0EsSUFBTUMsSUFBSSxHQUFHQyxhQUFiO0FBRUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0lBbUJxQkMsUTs7O0FBQ25CLG9CQUFZQyxLQUFaLEVBQW1CO0FBQUE7QUFDakIsU0FBS0MsSUFBTCxHQUFZRCxLQUFLLENBQUNDLElBQU4sSUFBY1QsSUFBMUI7QUFDQSxTQUFLVSxXQUFMLEdBQW1CRixLQUFLLENBQUNFLFdBQU4sSUFBcUJULFlBQXhDO0FBQ0EsU0FBS1UsSUFBTCxHQUFZSCxLQUFLLENBQUNHLElBQU4sSUFBY04sSUFBMUI7QUFDQSxTQUFLTyxTQUFMLEdBQWlCSixLQUFLLENBQUNJLFNBQU4sSUFBbUJWLFNBQXBDO0FBQ0Q7QUFFRDs7Ozs7Ozs7O3dDQUtvQjtBQUNsQixhQUFPLElBQVA7QUFDRDtBQUVEOzs7Ozs7OztvQ0FLZ0I7QUFDZCxhQUFPLElBQVA7QUFDRDtBQUVEOzs7Ozs7Ozs7a0NBTTZCO0FBQUEsVUFBakJXLE9BQWlCLHVFQUFQLEtBQU87QUFDM0IsYUFBTyxFQUFQO0FBQ0Q7QUFFRDs7Ozs7Ozs7O2dDQU0wQjtBQUFBLFVBQWhCQyxPQUFnQix1RUFBTixJQUFNO0FBQ3hCLGFBQU8sRUFBUDtBQUNEO0FBRUQ7Ozs7Ozs7O3FDQUtpQjtBQUNmLGFBQU8sSUFBUDtBQUNEO0FBRUQ7Ozs7Ozs7O2tDQUtjO0FBQ1osYUFBTyxFQUFQO0FBQ0Q7QUFFRDs7Ozs7Ozs7Ozs7O29EQU1ZQyxtQjs7Ozs7QUFDVkEsZ0JBQUFBLG1CQUFtQjs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFJckI7Ozs7Ozs7Ozs7OztxREFNYUMsb0I7Ozs7O0FBQ1hBLGdCQUFBQSxvQkFBb0I7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBSXRCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQWFpQkMsZ0JBQUFBLE8sUUFBQUEsTyxzQkFBU0MsTyxFQUFBQSxPLDZCQUFVLEU7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBSXBDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7a0RBb0JTLEU7Ozs7Ozs7Ozs7Ozs7Ozs7QUFHVDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztxREF5QmtCQyxVOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFJbEI7Ozs7Ozs7Ozs7OztBQVlBIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IChjKSAyMDIwIFViZXIgVGVjaG5vbG9naWVzLCBJbmMuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuLy8gb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbFxuLy8gaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0c1xuLy8gdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbFxuLy8gY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4vLyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4vLyBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4vLyBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbi8vIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuLy8gQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuLy8gTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbi8vIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU5cbi8vIFRIRSBTT0ZUV0FSRS5cblxuaW1wb3J0IHtVcGxvYWR9IGZyb20gJ2NvbXBvbmVudHMvY29tbW9uL2ljb25zJztcblxuY29uc3QgTkFNRSA9ICdjbG91ZC1wcm92aWRlcic7XG5jb25zdCBESVNQTEFZX05BTUUgPSAnQ2xvdWQgUHJvdmlkZXInO1xuY29uc3QgVEhVTUJOQUlMID0ge3dpZHRoOiAzMDAsIGhlaWdodDogMjAwfTtcbmNvbnN0IElDT04gPSBVcGxvYWQ7XG5cbi8qKlxuICogVGhlIGRlZmF1bHQgcHJvdmlkZXIgY2xhc3NcbiAqIEBwYXJhbSB7b2JqZWN0fSBwcm9wc1xuICogQHBhcmFtIHtzdHJpbmd9IHByb3BzLm5hbWVcbiAqIEBwYXJhbSB7c3RyaW5nfSBwcm9wcy5kaXNwbGF5TmFtZVxuICogQHBhcmFtIHtSZWFjdEVsZW1lbnR9IHByb3BzLmljb24gLSBSZWFjdCBlbGVtZW50XG4gKiBAcGFyYW0ge29iamVjdH0gcHJvcHMudGh1bWJuYWlsIC0gdGh1bWJuYWlsIHNpemUgb2JqZWN0XG4gKiBAcGFyYW0ge251bWJlcn0gcHJvcHMudGh1bWJuYWlsLndpZHRoIC0gdGh1bWJuYWlsIHdpZHRoIGluIHBpeGVsc1xuICogQHBhcmFtIHtudW1iZXJ9IHByb3BzLnRodW1ibmFpbC5oZWlnaHQgLSB0aHVtYm5haWwgaGVpZ2h0IGluIHBpeGVsc1xuICogQHB1YmxpY1xuICogQGV4YW1wbGVcbiAqXG4gKiBjb25zdCBteVByb3ZpZGVyID0gbmV3IFByb3ZpZGVyKHtcbiAqICBuYW1lOiAnZm9vJyxcbiAqICBkaXNwbGF5TmFtZTogJ0ZvbyBTdG9yYWdlJ1xuICogIGljb246IEljb24sXG4gKiAgdGh1bWJuYWlsOiB7d2lkdGg6IDMwMCwgaGVpZ2h0OiAyMDB9XG4gKiB9KVxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBQcm92aWRlciB7XG4gIGNvbnN0cnVjdG9yKHByb3BzKSB7XG4gICAgdGhpcy5uYW1lID0gcHJvcHMubmFtZSB8fCBOQU1FO1xuICAgIHRoaXMuZGlzcGxheU5hbWUgPSBwcm9wcy5kaXNwbGF5TmFtZSB8fCBESVNQTEFZX05BTUU7XG4gICAgdGhpcy5pY29uID0gcHJvcHMuaWNvbiB8fCBJQ09OO1xuICAgIHRoaXMudGh1bWJuYWlsID0gcHJvcHMudGh1bWJuYWlsIHx8IFRIVU1CTkFJTDtcbiAgfVxuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoaXMgcHJvdmlkZXIgc3VwcG9ydCB1cGxvYWQgbWFwIHRvIGEgcHJpdmF0ZSBzdG9yYWdlLiBJZiB0cnV0aHksIHVzZXIgd2lsbCBiZSBkaXNwbGF5ZWQgd2l0aCB0aGUgc3RvcmFnZSBzYXZlIGljb24gb24gdGhlIHRvcCByaWdodCBvZiB0aGUgc2lkZSBiYXIuXG4gICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgKiBAcHVibGljXG4gICAqL1xuICBoYXNQcml2YXRlU3RvcmFnZSgpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoaXMgcHJvdmlkZXIgc3VwcG9ydCBzaGFyZSBtYXAgdmlhIGEgcHVibGljIHVybCwgaWYgdHJ1dGh5LCB1c2VyIHdpbGwgYmUgZGlzcGxheWVkIHdpdGggYSBzaGFyZSBtYXAgdmlhIHVybCB1bmRlciB0aGUgZXhwb3J0IG1hcCBvcHRpb24gb24gdGhlIHRvcCByaWdodCBvZiB0aGUgc2lkZSBiYXJcbiAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAqIEBwdWJsaWNcbiAgICovXG4gIGhhc1NoYXJpbmdVcmwoKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBtZXRob2QgaXMgY2FsbGVkIGFmdGVyIHVzZXIgc2hhcmUgYSBtYXAsIHRvIGRpc3BsYXkgdGhlIHNoYXJlIHVybC5cbiAgICogQHBhcmFtIHtib29sZWFufSBmdWxsVXJsIC0gV2hldGhlciB0byByZXR1cm4gdGhlIGZ1bGwgdXJsIHdpdGggZG9tYWluLCBvciBqdXN0IHRoZSBsb2NhdGlvblxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBzaGFyZVVybFxuICAgKiBAcHVibGljXG4gICAqL1xuICBnZXRTaGFyZVVybChmdWxsVXJsID0gZmFsc2UpIHtcbiAgICByZXR1cm4gJyc7XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBtZXRob2QgaXMgY2FsbGVkIGJ5IGtlcGxlci5nbCBkZW1vIGFwcCB0byBwdXNoZXMgYSBuZXcgbG9jYXRpb24gdG8gaGlzdG9yeSwgYmVjb21pbmcgdGhlIGN1cnJlbnQgbG9jYXRpb24uXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gZnVsbFVSTCAtIFdoZXRoZXIgdG8gcmV0dXJuIHRoZSBmdWxsIHVybCB3aXRoIGRvbWFpbiwgb3IganVzdCB0aGUgbG9jYXRpb25cbiAgICogQHJldHVybnMge3N0cmluZ30gbWFwVXJsXG4gICAqIEBwdWJsaWNcbiAgICovXG4gIGdldE1hcFVybChmdWxsVVJMID0gdHJ1ZSkge1xuICAgIHJldHVybiAnJztcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIG1ldGhvZCBpcyBjYWxsZWQgdG8gZGV0ZXJtaW5lIHdoZXRoZXIgdXNlciBhbHJlYWR5IGxvZ2dlZCBpbiB0byB0aGlzIHByb3ZpZGVyXG4gICAqIEBwdWJsaWNcbiAgICogQHJldHVybnMge2Jvb2xlYW59IHRydWUgaWYgYSB1c2VyIGFscmVhZHkgbG9nZ2VkIGluXG4gICAqL1xuICBnZXRBY2Nlc3NUb2tlbigpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIG1ldGhvZCBpcyBjYWxsZWQgdG8gZ2V0IHRoZSB1c2VyIG5hbWUgb2YgdGhlIGN1cnJlbnQgdXNlci4gSXQgd2lsbCBiZSBkaXNwbGF5ZWQgaW4gdGhlIGNsb3VkIHByb3ZpZGVyIHRpbGUuXG4gICAqIEBwdWJsaWNcbiAgICogQHJldHVybnMge3N0cmluZ30gdHJ1ZSBpZiBhIHVzZXIgYWxyZWFkeSBsb2dnZWQgaW5cbiAgICovXG4gIGdldFVzZXJOYW1lKCkge1xuICAgIHJldHVybiAnJztcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIG1ldGhvZCB3aWxsIGJlIGNhbGxlZCB3aGVuIHVzZXIgY2xpY2sgdGhlIGxvZ2luIGJ1dHRvbiBpbiB0aGUgY2xvdWQgcHJvdmlkZXIgdGlsZS5cbiAgICogVXBvbiBsb2dpbiBzdWNjZXNzLCBgb25DbG91ZExvZ2luU3VjY2Vzc2AgaGFzIHRvIGJlIGNhbGxlZCB0byBub3RpZnkga2VwbGVyLmdsIFVJXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb259IG9uQ2xvdWRMb2dpblN1Y2Nlc3MgLSBjYWxsYmFja3MgdG8gYmUgY2FsbGVkIGFmdGVyIGxvZ2luIHN1Y2Nlc3NcbiAgICogQHB1YmxpY1xuICAgKi9cbiAgYXN5bmMgbG9naW4ob25DbG91ZExvZ2luU3VjY2Vzcykge1xuICAgIG9uQ2xvdWRMb2dpblN1Y2Nlc3MoKTtcbiAgICByZXR1cm47XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBtZXRob2Qgd2lsbCBiZSBjYWxsZWQgd2hlbiB1c2VyIGNsaWNrIHRoZSBsb2dvdXQgYnV0dG9uIHVuZGVyIHRoZSBjbG91ZCBwcm92aWRlciB0aWxlLlxuICAgKiBVcG9uIGxvZ2luIHN1Y2Nlc3MsIGBvbkNsb3VkTG9naW5TdWNjZXNzYCBoYXMgdG8gYmUgY2FsbGVkIHRvIG5vdGlmeSBrZXBsZXIuZ2wgVUlcbiAgICogQHBhcmFtIHtmdW5jdGlvbn0gb25DbG91ZExvZ291dFN1Y2Nlc3MgLSBjYWxsYmFja3MgdG8gYmUgY2FsbGVkIGFmdGVyIGxvZ291dCBzdWNjZXNzXG4gICAqIEBwdWJsaWNcbiAgICovXG4gIGFzeW5jIGxvZ291dChvbkNsb3VkTG9nb3V0U3VjY2Vzcykge1xuICAgIG9uQ2xvdWRMb2dvdXRTdWNjZXNzKCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoaXMgbWV0aG9kIHdpbGwgYmUgY2FsbGVkIHRvIHVwbG9hZCBtYXAgZm9yIHNhdmluZyBhbmQgc2hhcmluZy4gS2VwbGVyLmdsIHdpbGwgcGFja2FnZSBtYXAgZGF0YSwgY29uZmlnLCB0aXRsZSwgZGVzY3JpcHRpb24gYW5kIHRodW1ibmFpbCBmb3IgdXBsb2FkIHRvIHN0b3JhZ2UuXG4gICAqIFdpdGggdGhlIG9wdGlvbiB0byBvdmVyd3JpdGUgYWxyZWFkeSBzYXZlZCBtYXAsIGFuZCB1cGxvYWQgYXMgcHJpdmF0ZSBvciBwdWJsaWMgbWFwLlxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gcGFyYW1cbiAgICogQHBhcmFtIHtPYmplY3R9IHBhcmFtLm1hcERhdGEgLSB0aGUgbWFwIG9iamVjdFxuICAgKiBAcGFyYW0ge09iamVjdH0gcGFyYW0ubWFwRGF0YS5tYXAgLSB7ZGF0YXNldHMuIGNvbmZpZywgaW5mbzoge3RpdGxlLCBkZXNjcmlwdGlvbn19XG4gICAqIEBwYXJhbSB7QmxvYn0gcGFyYW0ubWFwRGF0YS50aHVtYm5haWwgLSBBIHRodW1ibmFpbCBvZiBjdXJyZW50IG1hcC4gdGh1bWJuYWlsIHNpemUgY2FuIGJlIGRlZmluZWQgYnkgcHJvdmlkZXIgYnkgdGhpcy50aHVtYm5haWxcbiAgICogQHBhcmFtIHtPYmplY3R9IHBhcmFtLm9wdGlvbnNcbiAgICogQHBhcmFtIHtib29sZWFufSBwYXJhbS5vcHRpb25zLm92ZXJ3cml0ZSAtIHdoZXRoZXIgdXNlciBjaG9vc2UgdG8gb3ZlcndyaXRlIGFscmVhZHkgc2F2ZWQgbWFwIHVuZGVyIHRoZSBzYW1lIG5hbWVcbiAgICogQHBhcmFtIHtib29sZWFufSBwYXJhbS5vcHRpb25zLmlzUHVibGljIC0gd2hldGhlciB1c2VyIHdpc2ggdG8gc2hhcmUgdGhlIG1hcCB3aXRoIG90aGVycy4gaWYgaXNQdWJsaWMgaXMgdHJ1dGh5LCBrZXBsZXIgd2lsbCBjYWxsIHRoaXMuZ2V0U2hhcmVVcmwoKSB0byBkaXNwbGF5IGFuIFVSTCB0aGV5IGNhbiBzaGFyZSB3aXRoIG90aGVyc1xuICAgKiBAcHVibGljXG4gICAqL1xuICBhc3luYyB1cGxvYWRNYXAoe21hcERhdGEsIG9wdGlvbnMgPSB7fX0pIHtcbiAgICByZXR1cm47XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBtZXRob2QgaXMgY2FsbGVkIHRvIGdldCBhIGxpc3Qgb2YgbWFwcyBzYXZlZCBieSB0aGUgY3VycmVudCBsb2dnZWQgaW4gdXNlci5cbiAgICogQHJldHVybnMge0FycmF5PFZpej59IGFuIGFycmF5IG9mIFZpeiBvYmplY3RzXG4gICAqIEBwdWJsaWNcbiAgICogQGV4YW1wbGVcbiAgICogIGFzeW5jIGxpc3RNYXBzKCkge1xuICAgKiAgICByZXR1cm4gW1xuICAgKiAgICAgIHtcbiAgICogICAgICAgIGlkOiAnYScsXG4gICAqICAgICAgICB0aXRsZTogJ015IG1hcCcsXG4gICAqICAgICAgICBkZXNjcmlwdGlvbjogJ015IGZpcnN0IGtlcGxlciBtYXAnLFxuICAgKiAgICAgICAgaW1hZ2VVcmw6ICdodHRwOi8vJyxcbiAgICogICAgICAgIGxhc3RNb2RpZmljYXRpb246IDE1ODI2Nzc3ODcwMDAsXG4gICAqICAgICAgICBwcml2YXRlTWFwOiBmYWxzZSxcbiAgICogICAgICAgIGxvYWRQYXJhbXM6IHt9XG4gICAqICAgICAgfVxuICAgKiAgICBdO1xuICAgKiAgfVxuICAgKi9cbiAgYXN5bmMgbGlzdE1hcHMoKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoaXMgbWV0aG9kIHdpbGwgYmUgY2FsbGVkIHdoZW4gdXNlciBzZWxlY3QgYSBtYXAgdG8gbG9hZCBmcm9tIHRoZSBzdG9yYWdlIG1hcCB2aWV3ZXJcbiAgICogQHBhcmFtIHsqfSBsb2FkUGFyYW1zIC0gdGhlIGxvYWRQYXJhbXMgcHJvcGVydHkgb2YgZWFjaCB2aXN1YWxpemF0aW9uIG9iamVjdFxuICAgKiBAcmV0dXJucyB7TWFwUmVzcG9uc2V9IC0gdGhlIG1hcCBvYmplY3QgY29udGFpbmluZyBkYXRhc2V0IGNvbmZpZyBpbmZvIGFuZCBmb3JtYXQgb3B0aW9uXG4gICAqIEBwdWJsaWNcbiAgICogQGV4YW1wbGVcbiAgICogYXN5bmMgZG93bmxvYWRNYXAobG9hZFBhcmFtcykge1xuICAgKiAgY29uc3QgbW9ja1Jlc3BvbnNlID0ge1xuICAgKiAgICBtYXA6IHtcbiAgICogICAgICBkYXRhc2V0czogW10sXG4gICAqICAgICAgY29uZmlnOiB7fSxcbiAgICogICAgICBpbmZvOiB7XG4gICAqICAgICAgICBhcHA6ICdrZXBsZXIuZ2wnLFxuICAgKiAgICAgICAgY3JlYXRlZF9hdDogJydcbiAgICogICAgICAgIHRpdGxlOiAndGVzdCBtYXAnLFxuICAgKiAgICAgICAgZGVzY3JpcHRpb246ICdIZWxsbyB0aGlzIGlzIG15IHRlc3QgZHJvcGJveCBtYXAnXG4gICAqICAgICAgfVxuICAgKiAgICB9LFxuICAgKiAgICAvLyBwYXNzIGNzdiBoZXJlIGlmIHlvdXIgcHJvdmlkZXIgY3VycmVudGx5IG9ubHkgc3VwcG9ydCBzYXZlIC8gbG9hZCBmaWxlIGFzIGNzdlxuICAgKiAgICBmb3JtYXQ6ICdrZXBsZXJnbCdcbiAgICogIH07XG4gICAqXG4gICAqICByZXR1cm4gZG93bmxvYWRNYXA7XG4gICAqIH1cbiAgICovXG4gIGFzeW5jIGRvd25sb2FkTWFwKGxvYWRQYXJhbXMpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICAvKipcbiAgICogQHR5cGVkZWYge09iamVjdH0gVml6XG4gICAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBpZCAtIEFuIHVuaXF1ZSBpZFxuICAgKiBAcHJvcGVydHkge3N0cmluZ30gdGl0bGUgLSBUaGUgdGl0bGUgb2YgdGhlIG1hcFxuICAgKiBAcHJvcGVydHkge3N0cmluZ30gZGVzY3JpcHRpb24gLSBUaGUgZGVzY3JpcHRpb24gb2YgdGhlIG1hcFxuICAgKiBAcHJvcGVydHkge3N0cmluZ30gaW1hZ2VVcmwgLSBUaGUgaW1hZ2VVcmwgb2YgdGhlIG1hcFxuICAgKiBAcHJvcGVydHkge251bWJlcn0gbGFzdE1vZGlmaWNhdGlvbiAtIEFuIGVwb2NoIHRpbWVzdGFtcCBpbiBtaWxsaXNlY29uZHNcbiAgICogQHByb3BlcnR5IHtib29sZWFufSBwcml2YXRlTWFwIC0gT3B0aW9uYWwsIHdoZXRoZXIgaWYgdGhpcyBtYXAgaXMgcHJpdmF0ZSB0byB0aGUgdXNlciwgb3IgY2FuIGJlIGFjY2Vzc2VkIGJ5IG90aGVycyB2aWEgVVJMXG4gICAqIEBwcm9wZXJ0eSB7Kn0gbG9hZFBhcmFtcyAtIEEgcHJvcGVydHkgdG8gYmUgcGFzc2VkIHRvIGBkb3dubG9hZE1hcGBcbiAgICogQHB1YmxpY1xuICAgKi9cblxuICAvKipcbiAgICogVGhlIHJldHVybmVkIG9iamVjdCBvZiBgZG93bmxvYWRNYXBgLiBUaGUgcmVzcG9uc2Ugb2JqZWN0IHNob3VsZCBjb250YWluOiBkYXRhc2V0czogW10sIGNvbmZpZzoge30sIGFuZCBpbmZvOiB7fVxuICAgKiBlYWNoIGRhdGFzZXQgb2JqZWN0IHNob3VsZCBiZSB7aW5mbzoge2lkLCBsYWJlbH0sIGRhdGE6IHsuLi59fVxuICAgKiB0byBpbmZvcm0gaG93IGtlcGxlciBzaG91bGQgcHJvY2VzcyB5b3VyIGRhdGEgb2JqZWN0LCBwYXNzIGluIGBmb3JtYXRgXG4gICAqIEB0eXBlZGVmIHtPYmplY3R9IE1hcFJlc3BvbnNlXG4gICAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBtYXBcbiAgICogQHByb3BlcnR5IHtBcnJheTxPYmplY3Q+fSBtYXAuZGF0YXNldHNcbiAgICogQHByb3BlcnR5IHtPYmplY3R9IG1hcC5jb25maWdcbiAgICogQHByb3BlcnR5IHtPYmplY3R9IG1hcC5pbmZvXG4gICAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBmb3JtYXQgLSBvbmUgb2YgJ2Nzdic6IGNzdiBmaWxlIHN0cmluZywgJ2dlb2pzb24nOiBnZW9qc29uIG9iamVjdCwgJ3Jvdyc6IHJvdyBvYmplY3QsICdrZXBsZXJnbCc6IGRhdGFzZXRzIGFycmF5IHNhdmVkIHVzaW5nIEtlcGxlckdsU2NoZW1hLnNhdmVcbiAgICogQHB1YmxpY1xuICAgKi9cbn1cbiJdfQ==