kepler.gl
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
386 lines (344 loc) • 27.9 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = exports.FILE_CONFLICT_MSG = 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) 2021 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;
var FILE_CONFLICT_MSG = 'file_conflict';
/**
* The default provider class
* @param {object} props
* @param {string} props.name
* @param {string} props.displayName
* @param {React.Component} 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}
* })
*/
exports.FILE_CONFLICT_MSG = FILE_CONFLICT_MSG;
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 return a standard error that will trigger the overwrite map modal
*/
}, {
key: "getFileConflictError",
value: function getFileConflictError() {
return new Error(FILE_CONFLICT_MSG);
}
/**
* 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 visualizations 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jbG91ZC1wcm92aWRlcnMvcHJvdmlkZXIuanMiXSwibmFtZXMiOlsiTkFNRSIsIkRJU1BMQVlfTkFNRSIsIlRIVU1CTkFJTCIsIndpZHRoIiwiaGVpZ2h0IiwiSUNPTiIsIlVwbG9hZCIsIkZJTEVfQ09ORkxJQ1RfTVNHIiwiUHJvdmlkZXIiLCJwcm9wcyIsIm5hbWUiLCJkaXNwbGF5TmFtZSIsImljb24iLCJ0aHVtYm5haWwiLCJmdWxsVXJsIiwiZnVsbFVSTCIsIkVycm9yIiwib25DbG91ZExvZ2luU3VjY2VzcyIsIm9uQ2xvdWRMb2dvdXRTdWNjZXNzIiwibWFwRGF0YSIsIm9wdGlvbnMiLCJsb2FkUGFyYW1zIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7OztBQW9CQTs7QUFwQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFJQSxJQUFNQSxJQUFJLEdBQUcsZ0JBQWI7QUFDQSxJQUFNQyxZQUFZLEdBQUcsZ0JBQXJCO0FBQ0EsSUFBTUMsU0FBUyxHQUFHO0FBQUNDLEVBQUFBLEtBQUssRUFBRSxHQUFSO0FBQWFDLEVBQUFBLE1BQU0sRUFBRTtBQUFyQixDQUFsQjtBQUNBLElBQU1DLElBQUksR0FBR0MsYUFBYjtBQUNPLElBQU1DLGlCQUFpQixHQUFHLGVBQTFCO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7SUFDcUJDLFE7QUFDbkIsb0JBQVlDLEtBQVosRUFBbUI7QUFBQTtBQUNqQixTQUFLQyxJQUFMLEdBQVlELEtBQUssQ0FBQ0MsSUFBTixJQUFjVixJQUExQjtBQUNBLFNBQUtXLFdBQUwsR0FBbUJGLEtBQUssQ0FBQ0UsV0FBTixJQUFxQlYsWUFBeEM7QUFDQSxTQUFLVyxJQUFMLEdBQVlILEtBQUssQ0FBQ0csSUFBTixJQUFjUCxJQUExQjtBQUNBLFNBQUtRLFNBQUwsR0FBaUJKLEtBQUssQ0FBQ0ksU0FBTixJQUFtQlgsU0FBcEM7QUFDRDtBQUVEO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7Ozs7O1dBQ0UsNkJBQW9CO0FBQ2xCLGFBQU8sSUFBUDtBQUNEO0FBRUQ7QUFDRjtBQUNBO0FBQ0E7QUFDQTs7OztXQUNFLHlCQUFnQjtBQUNkLGFBQU8sSUFBUDtBQUNEO0FBRUQ7QUFDRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O1dBQ0UsdUJBQTZCO0FBQUEsVUFBakJZLE9BQWlCLHVFQUFQLEtBQU87QUFDM0IsYUFBTyxFQUFQO0FBQ0Q7QUFFRDtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7V0FDRSxxQkFBMEI7QUFBQSxVQUFoQkMsT0FBZ0IsdUVBQU4sSUFBTTtBQUN4QixhQUFPLEVBQVA7QUFDRDtBQUVEO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7Ozs7V0FDRSwwQkFBaUI7QUFDZixhQUFPLElBQVA7QUFDRDtBQUVEO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7Ozs7V0FDRSx1QkFBYztBQUNaLGFBQU8sRUFBUDtBQUNEO0FBRUQ7QUFDRjtBQUNBOzs7O1dBQ0UsZ0NBQXVCO0FBQ3JCLGFBQU8sSUFBSUMsS0FBSixDQUFVVCxpQkFBVixDQUFQO0FBQ0Q7QUFFRDtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O2lHQUNFLGlCQUFZVSxtQkFBWjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQ0VBLGdCQUFBQSxtQkFBbUI7QUFEckI7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsTzs7Ozs7Ozs7QUFLQTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O2tHQUNFLGtCQUFhQyxvQkFBYjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQ0VBLGdCQUFBQSxvQkFBb0I7QUFEdEI7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsTzs7Ozs7Ozs7QUFLQTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7cUdBQ0U7QUFBQTs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFpQkMsZ0JBQUFBLE9BQWpCLFFBQWlCQSxPQUFqQixzQkFBMEJDLE9BQTFCLEVBQTBCQSxPQUExQiw2QkFBb0MsRUFBcEM7QUFBQTs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxPOzs7Ozs7OztBQUlBO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7OztvR0FDRTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsa0RBQ1MsRUFEVDs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxPOzs7Ozs7OztBQUlBO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozt1R0FDRSxrQkFBa0JDLFVBQWxCO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxPOzs7Ozs7OztBQUlBO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUU7QUFDRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IChjKSAyMDIxIFViZXIgVGVjaG5vbG9naWVzLCBJbmMuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuLy8gb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbFxuLy8gaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0c1xuLy8gdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbFxuLy8gY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4vLyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4vLyBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4vLyBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbi8vIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuLy8gQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuLy8gTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbi8vIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU5cbi8vIFRIRSBTT0ZUV0FSRS5cblxuaW1wb3J0IHtVcGxvYWR9IGZyb20gJ2NvbXBvbmVudHMvY29tbW9uL2ljb25zJztcblxuY29uc3QgTkFNRSA9ICdjbG91ZC1wcm92aWRlcic7XG5jb25zdCBESVNQTEFZX05BTUUgPSAnQ2xvdWQgUHJvdmlkZXInO1xuY29uc3QgVEhVTUJOQUlMID0ge3dpZHRoOiAzMDAsIGhlaWdodDogMjAwfTtcbmNvbnN0IElDT04gPSBVcGxvYWQ7XG5leHBvcnQgY29uc3QgRklMRV9DT05GTElDVF9NU0cgPSAnZmlsZV9jb25mbGljdCc7XG4vKipcbiAqIFRoZSBkZWZhdWx0IHByb3ZpZGVyIGNsYXNzXG4gKiBAcGFyYW0ge29iamVjdH0gcHJvcHNcbiAqIEBwYXJhbSB7c3RyaW5nfSBwcm9wcy5uYW1lXG4gKiBAcGFyYW0ge3N0cmluZ30gcHJvcHMuZGlzcGxheU5hbWVcbiAqIEBwYXJhbSB7UmVhY3QuQ29tcG9uZW50fSBwcm9wcy5pY29uIC0gUmVhY3QgZWxlbWVudFxuICogQHBhcmFtIHtvYmplY3R9IHByb3BzLnRodW1ibmFpbCAtIHRodW1ibmFpbCBzaXplIG9iamVjdFxuICogQHBhcmFtIHtudW1iZXJ9IHByb3BzLnRodW1ibmFpbC53aWR0aCAtIHRodW1ibmFpbCB3aWR0aCBpbiBwaXhlbHNcbiAqIEBwYXJhbSB7bnVtYmVyfSBwcm9wcy50aHVtYm5haWwuaGVpZ2h0IC0gdGh1bWJuYWlsIGhlaWdodCBpbiBwaXhlbHNcbiAqIEBwdWJsaWNcbiAqIEBleGFtcGxlXG4gKlxuICogY29uc3QgbXlQcm92aWRlciA9IG5ldyBQcm92aWRlcih7XG4gKiAgbmFtZTogJ2ZvbycsXG4gKiAgZGlzcGxheU5hbWU6ICdGb28gU3RvcmFnZSdcbiAqICBpY29uOiBJY29uLFxuICogIHRodW1ibmFpbDoge3dpZHRoOiAzMDAsIGhlaWdodDogMjAwfVxuICogfSlcbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUHJvdmlkZXIge1xuICBjb25zdHJ1Y3Rvcihwcm9wcykge1xuICAgIHRoaXMubmFtZSA9IHByb3BzLm5hbWUgfHwgTkFNRTtcbiAgICB0aGlzLmRpc3BsYXlOYW1lID0gcHJvcHMuZGlzcGxheU5hbWUgfHwgRElTUExBWV9OQU1FO1xuICAgIHRoaXMuaWNvbiA9IHByb3BzLmljb24gfHwgSUNPTjtcbiAgICB0aGlzLnRodW1ibmFpbCA9IHByb3BzLnRodW1ibmFpbCB8fCBUSFVNQk5BSUw7XG4gIH1cblxuICAvKipcbiAgICogV2hldGhlciB0aGlzIHByb3ZpZGVyIHN1cHBvcnQgdXBsb2FkIG1hcCB0byBhIHByaXZhdGUgc3RvcmFnZS4gSWYgdHJ1dGh5LCB1c2VyIHdpbGwgYmUgZGlzcGxheWVkIHdpdGggdGhlIHN0b3JhZ2Ugc2F2ZSBpY29uIG9uIHRoZSB0b3AgcmlnaHQgb2YgdGhlIHNpZGUgYmFyLlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICogQHB1YmxpY1xuICAgKi9cbiAgaGFzUHJpdmF0ZVN0b3JhZ2UoKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogV2hldGhlciB0aGlzIHByb3ZpZGVyIHN1cHBvcnQgc2hhcmUgbWFwIHZpYSBhIHB1YmxpYyB1cmwsIGlmIHRydXRoeSwgdXNlciB3aWxsIGJlIGRpc3BsYXllZCB3aXRoIGEgc2hhcmUgbWFwIHZpYSB1cmwgdW5kZXIgdGhlIGV4cG9ydCBtYXAgb3B0aW9uIG9uIHRoZSB0b3AgcmlnaHQgb2YgdGhlIHNpZGUgYmFyXG4gICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgKiBAcHVibGljXG4gICAqL1xuICBoYXNTaGFyaW5nVXJsKCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoaXMgbWV0aG9kIGlzIGNhbGxlZCBhZnRlciB1c2VyIHNoYXJlIGEgbWFwLCB0byBkaXNwbGF5IHRoZSBzaGFyZSB1cmwuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gZnVsbFVybCAtIFdoZXRoZXIgdG8gcmV0dXJuIHRoZSBmdWxsIHVybCB3aXRoIGRvbWFpbiwgb3IganVzdCB0aGUgbG9jYXRpb25cbiAgICogQHJldHVybnMge3N0cmluZ30gc2hhcmVVcmxcbiAgICogQHB1YmxpY1xuICAgKi9cbiAgZ2V0U2hhcmVVcmwoZnVsbFVybCA9IGZhbHNlKSB7XG4gICAgcmV0dXJuICcnO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoaXMgbWV0aG9kIGlzIGNhbGxlZCBieSBrZXBsZXIuZ2wgZGVtbyBhcHAgdG8gcHVzaGVzIGEgbmV3IGxvY2F0aW9uIHRvIGhpc3RvcnksIGJlY29taW5nIHRoZSBjdXJyZW50IGxvY2F0aW9uLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IGZ1bGxVUkwgLSBXaGV0aGVyIHRvIHJldHVybiB0aGUgZnVsbCB1cmwgd2l0aCBkb21haW4sIG9yIGp1c3QgdGhlIGxvY2F0aW9uXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IG1hcFVybFxuICAgKiBAcHVibGljXG4gICAqL1xuICBnZXRNYXBVcmwoZnVsbFVSTCA9IHRydWUpIHtcbiAgICByZXR1cm4gJyc7XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBtZXRob2QgaXMgY2FsbGVkIHRvIGRldGVybWluZSB3aGV0aGVyIHVzZXIgYWxyZWFkeSBsb2dnZWQgaW4gdG8gdGhpcyBwcm92aWRlclxuICAgKiBAcHVibGljXG4gICAqIEByZXR1cm5zIHtib29sZWFufSB0cnVlIGlmIGEgdXNlciBhbHJlYWR5IGxvZ2dlZCBpblxuICAgKi9cbiAgZ2V0QWNjZXNzVG9rZW4oKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBtZXRob2QgaXMgY2FsbGVkIHRvIGdldCB0aGUgdXNlciBuYW1lIG9mIHRoZSBjdXJyZW50IHVzZXIuIEl0IHdpbGwgYmUgZGlzcGxheWVkIGluIHRoZSBjbG91ZCBwcm92aWRlciB0aWxlLlxuICAgKiBAcHVibGljXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IHRydWUgaWYgYSB1c2VyIGFscmVhZHkgbG9nZ2VkIGluXG4gICAqL1xuICBnZXRVc2VyTmFtZSgpIHtcbiAgICByZXR1cm4gJyc7XG4gIH1cblxuICAvKipcbiAgICogVGhpcyByZXR1cm4gYSBzdGFuZGFyZCBlcnJvciB0aGF0IHdpbGwgdHJpZ2dlciB0aGUgb3ZlcndyaXRlIG1hcCBtb2RhbFxuICAgKi9cbiAgZ2V0RmlsZUNvbmZsaWN0RXJyb3IoKSB7XG4gICAgcmV0dXJuIG5ldyBFcnJvcihGSUxFX0NPTkZMSUNUX01TRyk7XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBtZXRob2Qgd2lsbCBiZSBjYWxsZWQgd2hlbiB1c2VyIGNsaWNrIHRoZSBsb2dpbiBidXR0b24gaW4gdGhlIGNsb3VkIHByb3ZpZGVyIHRpbGUuXG4gICAqIFVwb24gbG9naW4gc3VjY2VzcywgYG9uQ2xvdWRMb2dpblN1Y2Nlc3NgIGhhcyB0byBiZSBjYWxsZWQgdG8gbm90aWZ5IGtlcGxlci5nbCBVSVxuICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBvbkNsb3VkTG9naW5TdWNjZXNzIC0gY2FsbGJhY2tzIHRvIGJlIGNhbGxlZCBhZnRlciBsb2dpbiBzdWNjZXNzXG4gICAqIEBwdWJsaWNcbiAgICovXG4gIGFzeW5jIGxvZ2luKG9uQ2xvdWRMb2dpblN1Y2Nlc3MpIHtcbiAgICBvbkNsb3VkTG9naW5TdWNjZXNzKCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoaXMgbWV0aG9kIHdpbGwgYmUgY2FsbGVkIHdoZW4gdXNlciBjbGljayB0aGUgbG9nb3V0IGJ1dHRvbiB1bmRlciB0aGUgY2xvdWQgcHJvdmlkZXIgdGlsZS5cbiAgICogVXBvbiBsb2dpbiBzdWNjZXNzLCBgb25DbG91ZExvZ2luU3VjY2Vzc2AgaGFzIHRvIGJlIGNhbGxlZCB0byBub3RpZnkga2VwbGVyLmdsIFVJXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb259IG9uQ2xvdWRMb2dvdXRTdWNjZXNzIC0gY2FsbGJhY2tzIHRvIGJlIGNhbGxlZCBhZnRlciBsb2dvdXQgc3VjY2Vzc1xuICAgKiBAcHVibGljXG4gICAqL1xuICBhc3luYyBsb2dvdXQob25DbG91ZExvZ291dFN1Y2Nlc3MpIHtcbiAgICBvbkNsb3VkTG9nb3V0U3VjY2VzcygpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIG1ldGhvZCB3aWxsIGJlIGNhbGxlZCB0byB1cGxvYWQgbWFwIGZvciBzYXZpbmcgYW5kIHNoYXJpbmcuIEtlcGxlci5nbCB3aWxsIHBhY2thZ2UgbWFwIGRhdGEsIGNvbmZpZywgdGl0bGUsIGRlc2NyaXB0aW9uIGFuZCB0aHVtYm5haWwgZm9yIHVwbG9hZCB0byBzdG9yYWdlLlxuICAgKiBXaXRoIHRoZSBvcHRpb24gdG8gb3ZlcndyaXRlIGFscmVhZHkgc2F2ZWQgbWFwLCBhbmQgdXBsb2FkIGFzIHByaXZhdGUgb3IgcHVibGljIG1hcC5cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IHBhcmFtXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBwYXJhbS5tYXBEYXRhIC0gdGhlIG1hcCBvYmplY3RcbiAgICogQHBhcmFtIHtPYmplY3R9IHBhcmFtLm1hcERhdGEubWFwIC0ge2RhdGFzZXRzLiBjb25maWcsIGluZm86IHt0aXRsZSwgZGVzY3JpcHRpb259fVxuICAgKiBAcGFyYW0ge0Jsb2J9IHBhcmFtLm1hcERhdGEudGh1bWJuYWlsIC0gQSB0aHVtYm5haWwgb2YgY3VycmVudCBtYXAuIHRodW1ibmFpbCBzaXplIGNhbiBiZSBkZWZpbmVkIGJ5IHByb3ZpZGVyIGJ5IHRoaXMudGh1bWJuYWlsXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBbcGFyYW0ub3B0aW9uc11cbiAgICogQHBhcmFtIHtib29sZWFufSBbcGFyYW0ub3B0aW9ucy5vdmVyd3JpdGVdIC0gd2hldGhlciB1c2VyIGNob29zZSB0byBvdmVyd3JpdGUgYWxyZWFkeSBzYXZlZCBtYXAgdW5kZXIgdGhlIHNhbWUgbmFtZVxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtwYXJhbS5vcHRpb25zLmlzUHVibGljXSAtIHdoZXRoZXIgdXNlciB3aXNoIHRvIHNoYXJlIHRoZSBtYXAgd2l0aCBvdGhlcnMuIGlmIGlzUHVibGljIGlzIHRydXRoeSwga2VwbGVyIHdpbGwgY2FsbCB0aGlzLmdldFNoYXJlVXJsKCkgdG8gZGlzcGxheSBhbiBVUkwgdGhleSBjYW4gc2hhcmUgd2l0aCBvdGhlcnNcbiAgICogQHB1YmxpY1xuICAgKi9cbiAgYXN5bmMgdXBsb2FkTWFwKHttYXBEYXRhLCBvcHRpb25zID0ge319KSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoaXMgbWV0aG9kIGlzIGNhbGxlZCB0byBnZXQgYSBsaXN0IG9mIG1hcHMgc2F2ZWQgYnkgdGhlIGN1cnJlbnQgbG9nZ2VkIGluIHVzZXIuXG4gICAqIEByZXR1cm5zIHZpc3VhbGl6YXRpb25zIGFuIGFycmF5IG9mIFZpeiBvYmplY3RzXG4gICAqIEBwdWJsaWNcbiAgICogQGV4YW1wbGVcbiAgICogIGFzeW5jIGxpc3RNYXBzKCkge1xuICAgKiAgICByZXR1cm4gW1xuICAgKiAgICAgIHtcbiAgICogICAgICAgIGlkOiAnYScsXG4gICAqICAgICAgICB0aXRsZTogJ015IG1hcCcsXG4gICAqICAgICAgICBkZXNjcmlwdGlvbjogJ015IGZpcnN0IGtlcGxlciBtYXAnLFxuICAgKiAgICAgICAgaW1hZ2VVcmw6ICdodHRwOi8vJyxcbiAgICogICAgICAgIGxhc3RNb2RpZmljYXRpb246IDE1ODI2Nzc3ODcwMDAsXG4gICAqICAgICAgICBwcml2YXRlTWFwOiBmYWxzZSxcbiAgICogICAgICAgIGxvYWRQYXJhbXM6IHt9XG4gICAqICAgICAgfVxuICAgKiAgICBdO1xuICAgKiAgfVxuICAgKi9cbiAgYXN5bmMgbGlzdE1hcHMoKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoaXMgbWV0aG9kIHdpbGwgYmUgY2FsbGVkIHdoZW4gdXNlciBzZWxlY3QgYSBtYXAgdG8gbG9hZCBmcm9tIHRoZSBzdG9yYWdlIG1hcCB2aWV3ZXJcbiAgICogQHBhcmFtIHsqfSBsb2FkUGFyYW1zIC0gdGhlIGxvYWRQYXJhbXMgcHJvcGVydHkgb2YgZWFjaCB2aXN1YWxpemF0aW9uIG9iamVjdFxuICAgKiBAcmV0dXJucyBtYXBSZXNwb25zZSAtIHRoZSBtYXAgb2JqZWN0IGNvbnRhaW5pbmcgZGF0YXNldCBjb25maWcgaW5mbyBhbmQgZm9ybWF0IG9wdGlvblxuICAgKiBAcHVibGljXG4gICAqIEBleGFtcGxlXG4gICAqIGFzeW5jIGRvd25sb2FkTWFwKGxvYWRQYXJhbXMpIHtcbiAgICogIGNvbnN0IG1vY2tSZXNwb25zZSA9IHtcbiAgICogICAgbWFwOiB7XG4gICAqICAgICAgZGF0YXNldHM6IFtdLFxuICAgKiAgICAgIGNvbmZpZzoge30sXG4gICAqICAgICAgaW5mbzoge1xuICAgKiAgICAgICAgYXBwOiAna2VwbGVyLmdsJyxcbiAgICogICAgICAgIGNyZWF0ZWRfYXQ6ICcnXG4gICAqICAgICAgICB0aXRsZTogJ3Rlc3QgbWFwJyxcbiAgICogICAgICAgIGRlc2NyaXB0aW9uOiAnSGVsbG8gdGhpcyBpcyBteSB0ZXN0IGRyb3Bib3ggbWFwJ1xuICAgKiAgICAgIH1cbiAgICogICAgfSxcbiAgICogICAgLy8gcGFzcyBjc3YgaGVyZSBpZiB5b3VyIHByb3ZpZGVyIGN1cnJlbnRseSBvbmx5IHN1cHBvcnQgc2F2ZSAvIGxvYWQgZmlsZSBhcyBjc3ZcbiAgICogICAgZm9ybWF0OiAna2VwbGVyZ2wnXG4gICAqICB9O1xuICAgKlxuICAgKiAgcmV0dXJuIGRvd25sb2FkTWFwO1xuICAgKiB9XG4gICAqL1xuICBhc3luYyBkb3dubG9hZE1hcChsb2FkUGFyYW1zKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLyoqXG4gICAqIEB0eXBlZGVmIHtPYmplY3R9IFZpelxuICAgKiBAcHJvcGVydHkge3N0cmluZ30gaWQgLSBBbiB1bmlxdWUgaWRcbiAgICogQHByb3BlcnR5IHtzdHJpbmd9IHRpdGxlIC0gVGhlIHRpdGxlIG9mIHRoZSBtYXBcbiAgICogQHByb3BlcnR5IHtzdHJpbmd9IGRlc2NyaXB0aW9uIC0gVGhlIGRlc2NyaXB0aW9uIG9mIHRoZSBtYXBcbiAgICogQHByb3BlcnR5IHtzdHJpbmd9IGltYWdlVXJsIC0gVGhlIGltYWdlVXJsIG9mIHRoZSBtYXBcbiAgICogQHByb3BlcnR5IHtudW1iZXJ9IGxhc3RNb2RpZmljYXRpb24gLSBBbiBlcG9jaCB0aW1lc3RhbXAgaW4gbWlsbGlzZWNvbmRzXG4gICAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gcHJpdmF0ZU1hcCAtIE9wdGlvbmFsLCB3aGV0aGVyIGlmIHRoaXMgbWFwIGlzIHByaXZhdGUgdG8gdGhlIHVzZXIsIG9yIGNhbiBiZSBhY2Nlc3NlZCBieSBvdGhlcnMgdmlhIFVSTFxuICAgKiBAcHJvcGVydHkgeyp9IGxvYWRQYXJhbXMgLSBBIHByb3BlcnR5IHRvIGJlIHBhc3NlZCB0byBgZG93bmxvYWRNYXBgXG4gICAqIEBwdWJsaWNcbiAgICovXG5cbiAgLyoqXG4gICAqIFRoZSByZXR1cm5lZCBvYmplY3Qgb2YgYGRvd25sb2FkTWFwYC4gVGhlIHJlc3BvbnNlIG9iamVjdCBzaG91bGQgY29udGFpbjogZGF0YXNldHM6IFtdLCBjb25maWc6IHt9LCBhbmQgaW5mbzoge31cbiAgICogZWFjaCBkYXRhc2V0IG9iamVjdCBzaG91bGQgYmUge2luZm86IHtpZCwgbGFiZWx9LCBkYXRhOiB7Li4ufX1cbiAgICogdG8gaW5mb3JtIGhvdyBrZXBsZXIgc2hvdWxkIHByb2Nlc3MgeW91ciBkYXRhIG9iamVjdCwgcGFzcyBpbiBgZm9ybWF0YFxuICAgKiBAdHlwZWRlZiB7T2JqZWN0fSBNYXBSZXNwb25zZVxuICAgKiBAcHJvcGVydHkge09iamVjdH0gbWFwXG4gICAqIEBwcm9wZXJ0eSB7QXJyYXk8T2JqZWN0Pn0gbWFwLmRhdGFzZXRzXG4gICAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBtYXAuY29uZmlnXG4gICAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBtYXAuaW5mb1xuICAgKiBAcHJvcGVydHkge3N0cmluZ30gZm9ybWF0IC0gb25lIG9mICdjc3YnOiBjc3YgZmlsZSBzdHJpbmcsICdnZW9qc29uJzogZ2VvanNvbiBvYmplY3QsICdyb3cnOiByb3cgb2JqZWN0LCAna2VwbGVyZ2wnOiBkYXRhc2V0cyBhcnJheSBzYXZlZCB1c2luZyBLZXBsZXJHbFNjaGVtYS5zYXZlXG4gICAqIEBwdWJsaWNcbiAgICovXG59XG4iXX0=