UNPKG

32.9 kBJavaScriptView Raw
1'use strict';
2
3var _slicedToArray2 = require('babel-runtime/helpers/slicedToArray');
4
5var _slicedToArray3 = _interopRequireDefault(_slicedToArray2);
6
7var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
8
9var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
10
11var _createClass2 = require('babel-runtime/helpers/createClass');
12
13var _createClass3 = _interopRequireDefault(_createClass2);
14
15function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16
17var ChatServiceError = require('./ChatServiceError');
18var Promise = require('bluebird');
19var _ = require('lodash');
20
21var _require = require('./utils');
22
23var checkNameSymbols = _require.checkNameSymbols;
24var possiblyCallback = _require.possiblyCallback;
25
26/**
27 * Server side operations.
28 *
29 * @mixin
30 * @memberof chat-service
31 * @see chat-service.ChatService
32 */
33
34var ServiceAPI = function () {
35 function ServiceAPI(state, makeUser, clusterBus) {
36 (0, _classCallCheck3.default)(this, ServiceAPI);
37
38 this.state = state;
39 this.makeUser = makeUser;
40 this.clusterBus = clusterBus;
41 }
42
43 /**
44 * Executes {@link rpc.clientRequests} handlers.
45 *
46 * @param {string|boolean|Object} context Is a `userName` if
47 * `string`, or a `bypassPermissions` if `boolean`, or an options
48 * object if `Object`.
49 * @param {string} command Command name.
50 * @param {...*} args Command arguments.
51 * @param {callback} [cb] Optional callback.
52 *
53 * @property {string} [context.userName] User name.
54 * @property {string} [context.id] Socket id, it is required for
55 * {@link rpc.clientRequests.roomJoin} and {@link
56 * rpc.clientRequests.roomLeave} commands.
57 * @property {boolean} [context.bypassHooks=false] If `false`
58 * executes command without before and after hooks.
59 * @property {boolean} [context.bypassPermissions=false] If `true`
60 * executes command (except {@link rpc.clientRequests.roomJoin})
61 * bypassing built-in permissions checking.
62 *
63 * @return {Promise<Array>} Array of command results.
64 *
65 * @see rpc.clientRequests
66 */
67
68
69 (0, _createClass3.default)(ServiceAPI, [{
70 key: 'execUserCommand',
71 value: function execUserCommand(context, command) {
72 var _this = this;
73
74 if (_.isObject(context)) {
75 var _context = context;
76 var userName = _context.userName;
77
78 context = _.clone(context);
79 } else if (_.isBoolean(context)) {
80 context = { bypassPermissions: context };
81 } else {
82 userName = context;
83 context = {};
84 }
85 context.isLocalCall = true;
86
87 for (var _len = arguments.length, args = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
88 args[_key - 2] = arguments[_key];
89 }
90
91 var _possiblyCallback = possiblyCallback(args);
92
93 var _possiblyCallback2 = (0, _slicedToArray3.default)(_possiblyCallback, 2);
94
95 var nargs = _possiblyCallback2[0];
96 var cb = _possiblyCallback2[1];
97
98 return Promise.try(function () {
99 if (userName) {
100 return _this.state.getUser(userName);
101 } else {
102 return _this.makeUser();
103 }
104 }).then(function (user) {
105 return user.exec(command, context, nargs);
106 }).asCallback(cb, { spread: true });
107 }
108
109 /**
110 * Adds an user with a state.
111 *
112 * @param {string} userName User name.
113 * @param {Object} [state] User state.
114 * @param {callback} [cb] Optional callback.
115 *
116 * @property {Array<string>} [state.whitelist=[]] User direct messages
117 * whitelist.
118 * @property {Array<string>} [state.blacklist=[]] User direct messages
119 * blacklist.
120 * @property {boolean} [state.whitelistOnly=false] User direct
121 * messages whitelistOnly mode.
122 *
123 * @return {Promise<undefined>} Promise that resolves without any data.
124 */
125
126 }, {
127 key: 'addUser',
128 value: function addUser(userName, state, cb) {
129 var _this2 = this;
130
131 return checkNameSymbols(userName).then(function () {
132 return _this2.state.addUser(userName, state);
133 }).return().asCallback(cb);
134 }
135
136 /**
137 * Deletes an offline user. Will raise an error if a user has online
138 * sockets.
139 *
140 * @param {string} userName User name.
141 * @param {callback} [cb] Optional callback.
142 *
143 * @return {Promise<undefined>} Promise that resolves without any data.
144 */
145
146 }, {
147 key: 'deleteUser',
148 value: function deleteUser(userName, cb) {
149 var _this3 = this;
150
151 return this.state.getUser(userName).then(function (user) {
152 return user.listOwnSockets().then(function (sockets) {
153 if (sockets && _.size(sockets) > 0) {
154 return Promise.reject(new ChatServiceError('userOnline', userName));
155 } else {
156 return Promise.all([user.removeState(), _this3.state.removeUser(userName)]);
157 }
158 });
159 }).return().asCallback(cb);
160 }
161
162 /**
163 * Checks for an user existence.
164 *
165 * @param {string} userName User name.
166 * @param {callback} [cb] Optional callback.
167 *
168 * @return {Promise<boolean>} Predicate result.
169 */
170
171 }, {
172 key: 'hasUser',
173 value: function hasUser(userName, cb) {
174 return this.state.getUser(userName, true).then(function (user) {
175 return Boolean(user);
176 }).asCallback(cb);
177 }
178
179 /**
180 * Checks for a name existence in a direct messaging list.
181 *
182 * @param {string} userName User name.
183 * @param {string} listName List name.
184 * @param {string} item List element.
185 * @param {callback} [cb] Optional callback.
186 *
187 * @return {Promise<boolean>} Predicate result.
188 */
189
190 }, {
191 key: 'userHasInList',
192 value: function userHasInList(userName, listName, item, cb) {
193 return this.state.getUser(userName).then(function (user) {
194 return user.directMessaging.hasInList(listName, item);
195 }).asCallback(cb);
196 }
197
198 /**
199 * Checks for a direct messaging permission.
200 *
201 * @param {string} recipient Recipient name.
202 * @param {string} sender Sender name.
203 * @param {callback} [cb] Optional callback.
204 *
205 * @return {Promise<boolean>} Predicate result.
206 */
207
208 }, {
209 key: 'hasDirectAccess',
210 value: function hasDirectAccess(recipient, sender, cb) {
211 return this.state.getUser(recipient).then(function (user) {
212 return user.directMessaging.checkAcess(sender);
213 }).return(true).catchReturn(ChatServiceError, false).asCallback(cb);
214 }
215
216 /**
217 * Disconnects user's sockets for all service instances. Method is
218 * asynchronous, returns without waiting for the completion.
219 *
220 * @param {string} userName User name.
221 *
222 * @return {undefined} Returns no data.
223 */
224
225 }, {
226 key: 'disconnectUserSockets',
227 value: function disconnectUserSockets(userName) {
228 this.clusterBus.emit('disconnectUserSockets', userName);
229 }
230
231 /**
232 * Adds a room with a state.
233 *
234 * @param {string} roomName Room name.
235 * @param {Object} [state] Room state.
236 * @param {callback} [cb] Optional callback.
237 *
238 * @property {Array<string>} [state.whitelist=[]] Room whitelist.
239 * @property {Array<string>} [state.blacklist=[]] Room blacklist
240 * @property {Array<string>} [state.adminlist=[]] Room adminlist.
241 * @property {boolean} [state.whitelistOnly=false] Room
242 * whitelistOnly mode.
243 * @property {string} [state.owner] Room owner.
244 * @property {number} [state.historyMaxSize] Room history maximum
245 * size. Defalut value is {@link chat-service.config.options}
246 * `historyMaxSize`.
247 * @property {boolean} [state.enableAccessListsUpdates] Room enable
248 * access lists updates. Defalut value is {@link
249 * chat-service.config.options} `enableAccessListsUpdates`.
250 * @property {boolean} [state.enableUserlistUpdates] Room enable
251 * userlist updates. Defalut value is {@link
252 * chat-service.config.options} `enableUserlistUpdates`.
253 *
254 * @return {Promise<undefined>} Promise that resolves without any data.
255 */
256
257 }, {
258 key: 'addRoom',
259 value: function addRoom(roomName, state, cb) {
260 var _this4 = this;
261
262 return checkNameSymbols(roomName).then(function () {
263 return _this4.state.addRoom(roomName, state);
264 }).return().asCallback(cb);
265 }
266
267 /**
268 * Removes all joined users from the room and removes all room data.
269 *
270 * @param {string} roomName Room name.
271 * @param {callback} [cb] Optional callback.
272 *
273 * @return {Promise<undefined>} Promise that resolves without any data.
274 */
275
276 }, {
277 key: 'deleteRoom',
278 value: function deleteRoom(roomName, cb) {
279 return this.execUserCommand(true, 'roomDelete', roomName).return().asCallback(cb);
280 }
281
282 /**
283 * Checks for a room existence.
284 *
285 * @param {string} roomName Room name.
286 * @param {callback} [cb] Optional callback.
287 *
288 * @return {Promise<boolean>} Predicate result.
289 */
290
291 }, {
292 key: 'hasRoom',
293 value: function hasRoom(roomName, cb) {
294 return this.state.getRoom(roomName, true).then(function (room) {
295 return Boolean(room);
296 }).asCallback(cb);
297 }
298
299 /**
300 * Checks for a name existence in a room list.
301 *
302 * @param {string} roomName Room name.
303 * @param {string} listName List name.
304 * @param {string} item List element.
305 * @param {callback} [cb] Optional callback.
306 *
307 * @return {Promise<boolean>} Predicate result.
308 */
309
310 }, {
311 key: 'roomHasInList',
312 value: function roomHasInList(roomName, listName, item, cb) {
313 return this.state.getRoom(roomName).then(function (room) {
314 return room.roomState.hasInList(listName, item);
315 }).asCallback(cb);
316 }
317
318 /**
319 * Checks for a room access permission.
320 *
321 * @param {string} roomName Room name.
322 * @param {string} userName User name.
323 * @param {callback} [cb] Optional callback.
324 *
325 * @return {Promise<boolean>} Predicate result.
326 */
327
328 }, {
329 key: 'hasRoomAccess',
330 value: function hasRoomAccess(roomName, userName, cb) {
331 return this.state.getRoom(roomName).then(function (room) {
332 return room.checkAcess(userName);
333 }).return(true).catchReturn(ChatServiceError, false).asCallback(cb);
334 }
335
336 /**
337 * Changes the room owner.
338 *
339 * @param {string} roomName Room name.
340 * @param {string} owner Owner user name.
341 * @param {callback} [cb] Optional callback.
342 *
343 * @return {Promise<undefined>} Promise that resolves without any data.
344 */
345
346 }, {
347 key: 'changeRoomOwner',
348 value: function changeRoomOwner(roomName, owner, cb) {
349 return this.state.getRoom(roomName).then(function (room) {
350 return room.roomState.ownerSet(owner);
351 }).return().asCallback(cb);
352 }
353
354 /**
355 * Changes the room history size.
356 *
357 * @param {string} roomName Room name.
358 * @param {number} size Room history size.
359 * @param {callback} [cb] Optional callback.
360 *
361 * @return {Promise<undefined>} Promise that resolves without any data.
362 */
363
364 }, {
365 key: 'changeRoomHistoryMaxSize',
366 value: function changeRoomHistoryMaxSize(roomName, size, cb) {
367 return this.state.getRoom(roomName).then(function (room) {
368 return room.roomState.historyMaxSizeSet(size);
369 }).return().asCallback(cb);
370 }
371
372 /**
373 * Enables or disables access lists updates for the room.
374 *
375 * @param {string} roomName Room name.
376 * @param {boolean} mode Enable or disable.
377 * @param {callback} [cb] Optional callback.
378 *
379 * @return {Promise<undefined>} Promise that resolves without any data.
380 *
381 * @see rpc.serverNotifications.roomAccessListAdded
382 * @see rpc.serverNotifications.roomAccessListRemoved
383 * @see rpc.serverNotifications.roomModeChanged
384 */
385
386 }, {
387 key: 'changeAccessListsUpdates',
388 value: function changeAccessListsUpdates(roomName, mode, cb) {
389 return this.state.getRoom(roomName).then(function (room) {
390 return room.roomState.accessListsUpdatesSet(mode);
391 }).return().asCallback(cb);
392 }
393
394 /**
395 * Enables or disables user list updates for the room.
396 *
397 * @param {string} roomName Room name.
398 * @param {boolean} mode Enable or disable.
399 * @param {callback} [cb] Optional callback.
400 *
401 * @return {Promise<undefined>} Promise that resolves without any data.
402 *
403 * @see rpc.serverNotifications.roomUserJoined
404 * @see rpc.serverNotifications.roomUserLeft
405 */
406
407 }, {
408 key: 'changeUserlistUpdates',
409 value: function changeUserlistUpdates(roomName, mode, cb) {
410 return this.state.getRoom(roomName).then(function (room) {
411 return room.roomState.userlistUpdatesSet(mode);
412 }).return().asCallback(cb);
413 }
414 }]);
415 return ServiceAPI;
416}();
417
418module.exports = ServiceAPI;
419//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9TZXJ2aWNlQVBJLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7O0FBRUEsSUFBTSxtQkFBbUIsUUFBUSxvQkFBUixDQUF6QjtBQUNBLElBQU0sVUFBVSxRQUFRLFVBQVIsQ0FBaEI7QUFDQSxJQUFNLElBQUksUUFBUSxRQUFSLENBQVY7O2VBQytDLFFBQVEsU0FBUixDOztJQUF2QyxnQixZQUFBLGdCO0lBQWtCLGdCLFlBQUEsZ0I7O0FBRTFCOzs7Ozs7OztJQU9NLFU7QUFFSixzQkFBYSxLQUFiLEVBQW9CLFFBQXBCLEVBQThCLFVBQTlCLEVBQTBDO0FBQUE7O0FBQ3hDLFNBQUssS0FBTCxHQUFhLEtBQWI7QUFDQSxTQUFLLFFBQUwsR0FBZ0IsUUFBaEI7QUFDQSxTQUFLLFVBQUwsR0FBa0IsVUFBbEI7QUFDRDs7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztvQ0F3QmlCLE8sRUFBUyxPLEVBQWtCO0FBQUE7O0FBQzFDLFVBQUksRUFBRSxRQUFGLENBQVcsT0FBWCxDQUFKLEVBQXlCO0FBQUEsdUJBQ0osT0FESTtBQUFBLFlBQ2pCLFFBRGlCLFlBQ2pCLFFBRGlCOztBQUV2QixrQkFBVSxFQUFFLEtBQUYsQ0FBUSxPQUFSLENBQVY7QUFDRCxPQUhELE1BR08sSUFBSSxFQUFFLFNBQUYsQ0FBWSxPQUFaLENBQUosRUFBMEI7QUFDL0Isa0JBQVUsRUFBQyxtQkFBbUIsT0FBcEIsRUFBVjtBQUNELE9BRk0sTUFFQTtBQUNMLG1CQUFXLE9BQVg7QUFDQSxrQkFBVSxFQUFWO0FBQ0Q7QUFDRCxjQUFRLFdBQVIsR0FBc0IsSUFBdEI7O0FBVjBDLHdDQUFOLElBQU07QUFBTixZQUFNO0FBQUE7O0FBQUEsOEJBV3hCLGlCQUFpQixJQUFqQixDQVh3Qjs7QUFBQTs7QUFBQSxVQVdyQyxLQVhxQztBQUFBLFVBVzlCLEVBWDhCOztBQVkxQyxhQUFPLFFBQVEsR0FBUixDQUFZLFlBQU07QUFDdkIsWUFBSSxR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LENBQ0M7QUFBQSxlQUFRLEtBQUssU0FBTCxDQUFlLFFBQWYsQ0FBd0IsS0FBeEIsQ0FBUjtBQUFBLE9BREQsRUFFSixNQUZJLEdBR0osVUFISSxDQUdPLEVBSFAsQ0FBUDtBQUlEOztBQUVEOzs7Ozs7Ozs7Ozs7NkNBUzBCLFEsRUFBVSxJLEVBQU0sRSxFQUFJO0FBQzVDLGFBQU8sS0FBSyxLQUFMLENBQVcsT0FBWCxDQUFtQixRQUFuQixFQUNKLElBREksQ0FDQztBQUFBLGVBQVEsS0FBSyxTQUFMLENBQWUsaUJBQWYsQ0FBaUMsSUFBakMsQ0FBUjtBQUFBLE9BREQsRUFFSixNQUZJLEdBR0osVUFISSxDQUdPLEVBSFAsQ0FBUDtBQUlEOztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7OzZDQWEwQixRLEVBQVUsSSxFQUFNLEUsRUFBSTtBQUM1QyxhQUFPLEtBQUssS0FBTCxDQUFXLE9BQVgsQ0FBbUIsUUFBbkIsRUFDSixJQURJLENBQ0M7QUFBQSxlQUFRLEtBQUssU0FBTCxDQUFlLHFCQUFmLENBQXFDLElBQXJDLENBQVI7QUFBQSxPQURELEVBRUosTUFGSSxHQUdKLFVBSEksQ0FHTyxFQUhQLENBQVA7QUFJRDs7QUFFRDs7Ozs7Ozs7Ozs7Ozs7OzBDQVl1QixRLEVBQVUsSSxFQUFNLEUsRUFBSTtBQUN6QyxhQUFPLEtBQUssS0FBTCxDQUFXLE9BQVgsQ0FBbUIsUUFBbkIsRUFDSixJQURJLENBQ0M7QUFBQSxlQUFRLEtBQUssU0FBTCxDQUFlLGtCQUFmLENBQWtDLElBQWxDLENBQVI7QUFBQSxPQURELEVBRUosTUFGSSxHQUdKLFVBSEksQ0FHTyxFQUhQLENBQVA7QUFJRDs7Ozs7QUFJSCxPQUFPLE9BQVAsR0FBaUIsVUFBakIiLCJmaWxlIjoiU2VydmljZUFQSS5qcyIsInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0J1xuXG5jb25zdCBDaGF0U2VydmljZUVycm9yID0gcmVxdWlyZSgnLi9DaGF0U2VydmljZUVycm9yJylcbmNvbnN0IFByb21pc2UgPSByZXF1aXJlKCdibHVlYmlyZCcpXG5jb25zdCBfID0gcmVxdWlyZSgnbG9kYXNoJylcbmNvbnN0IHsgY2hlY2tOYW1lU3ltYm9scywgcG9zc2libHlDYWxsYmFjayB9ID0gcmVxdWlyZSgnLi91dGlscycpXG5cbi8qKlxuICogU2VydmVyIHNpZGUgb3BlcmF0aW9ucy5cbiAqXG4gKiBAbWl4aW5cbiAqIEBtZW1iZXJvZiBjaGF0LXNlcnZpY2VcbiAqIEBzZWUgY2hhdC1zZXJ2aWNlLkNoYXRTZXJ2aWNlXG4gKi9cbmNsYXNzIFNlcnZpY2VBUEkge1xuXG4gIGNvbnN0cnVjdG9yIChzdGF0ZSwgbWFrZVVzZXIsIGNsdXN0ZXJCdXMpIHtcbiAgICB0aGlzLnN0YXRlID0gc3RhdGVcbiAgICB0aGlzLm1ha2VVc2VyID0gbWFrZVVzZXJcbiAgICB0aGlzLmNsdXN0ZXJCdXMgPSBjbHVzdGVyQnVzXG4gIH1cblxuICAvKipcbiAgICogRXhlY3V0ZXMge0BsaW5rIHJwYy5jbGllbnRSZXF1ZXN0c30gaGFuZGxlcnMuXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfGJvb2xlYW58T2JqZWN0fSBjb250ZXh0IElzIGEgYHVzZXJOYW1lYCBpZlxuICAgKiBgc3RyaW5nYCwgb3IgYSBgYnlwYXNzUGVybWlzc2lvbnNgIGlmIGBib29sZWFuYCwgb3IgYW4gb3B0aW9uc1xuICAgKiBvYmplY3QgaWYgYE9iamVjdGAuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBjb21tYW5kIENvbW1hbmQgbmFtZS5cbiAgICogQHBhcmFtIHsuLi4qfSBhcmdzIENvbW1hbmQgYXJndW1lbnRzLlxuICAgKiBAcGFyYW0ge2NhbGxiYWNrfSBbY2JdIE9wdGlvbmFsIGNhbGxiYWNrLlxuICAgKlxuICAgKiBAcHJvcGVydHkge3N0cmluZ30gW2NvbnRleHQudXNlck5hbWVdIFVzZXIgbmFtZS5cbiAgICogQHByb3BlcnR5IHtzdHJpbmd9IFtjb250ZXh0LmlkXSBTb2NrZXQgaWQsIGl0IGlzIHJlcXVpcmVkIGZvclxuICAgKiB7QGxpbmsgcnBjLmNsaWVudFJlcXVlc3RzLnJvb21Kb2lufSBhbmQge0BsaW5rXG4gICAqIHJwYy5jbGllbnRSZXF1ZXN0cy5yb29tTGVhdmV9IGNvbW1hbmRzLlxuICAgKiBAcHJvcGVydHkge2Jvb2xlYW59IFtjb250ZXh0LmJ5cGFzc0hvb2tzPWZhbHNlXSBJZiBgZmFsc2VgXG4gICAqIGV4ZWN1dGVzIGNvbW1hbmQgd2l0aG91dCBiZWZvcmUgYW5kIGFmdGVyIGhvb2tzLlxuICAgKiBAcHJvcGVydHkge2Jvb2xlYW59IFtjb250ZXh0LmJ5cGFzc1Blcm1pc3Npb25zPWZhbHNlXSBJZiBgdHJ1ZWBcbiAgICogZXhlY3V0ZXMgY29tbWFuZCAoZXhjZXB0IHtAbGluayBycGMuY2xpZW50UmVxdWVzdHMucm9vbUpvaW59KVxuICAgKiBieXBhc3NpbmcgYnVpbHQtaW4gcGVybWlzc2lvbnMgY2hlY2tpbmcuXG4gICAqXG4gICAqIEByZXR1cm4ge1Byb21pc2U8QXJyYXk+fSBBcnJheSBvZiBjb21tYW5kIHJlc3VsdHMuXG4gICAqXG4gICAqIEBzZWUgcnBjLmNsaWVudFJlcXVlc3RzXG4gICAqL1xuICBleGVjVXNlckNvbW1hbmQgKGNvbnRleHQsIGNvbW1hbmQsIC4uLmFyZ3MpIHtcbiAgICBpZiAoXy5pc09iamVjdChjb250ZXh0KSkge1xuICAgICAgdmFyIHsgdXNlck5hbWUgfSA9IGNvbnRleHRcbiAgICAgIGNvbnRleHQgPSBfLmNsb25lKGNvbnRleHQpXG4gICAgfSBlbHNlIGlmIChfLmlzQm9vbGVhbihjb250ZXh0KSkge1xuICAgICAgY29udGV4dCA9IHtieXBhc3NQZXJtaXNzaW9uczogY29udGV4dH1cbiAgICB9IGVsc2Uge1xuICAgICAgdXNlck5hbWUgPSBjb250ZXh0XG4gICAgICBjb250ZXh0ID0ge31cbiAgICB9XG4gICAgY29udGV4dC5pc0xvY2FsQ2FsbCA9IHRydWVcbiAgICBsZXQgW25hcmdzLCBjYl0gPSBwb3NzaWJseUNhbGxiYWNrKGFyZ3MpXG4gICAgcmV0dXJuIFByb21pc2UudHJ5KCgpID0+IHtcbiAgICAgIGlmICh1c2VyTmFtZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5zdGF0ZS5nZXRVc2VyKHVzZXJOYW1lKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWFrZVVzZXIoKVxuICAgICAgfVxuICAgIH0pLnRoZW4odXNlciA9PiB1c2VyLmV4ZWMoY29tbWFuZCwgY29udGV4dCwgbmFyZ3MpKVxuICAgICAgLmFzQ2FsbGJhY2soY2IsIHsgc3ByZWFkOiB0cnVlIH0pXG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhbiB1c2VyIHdpdGggYSBzdGF0ZS5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHVzZXJOYW1lIFVzZXIgbmFtZS5cbiAgICogQHBhcmFtIHtPYmplY3R9IFtzdGF0ZV0gVXNlciBzdGF0ZS5cbiAgICogQHBhcmFtIHtjYWxsYmFja30gW2NiXSBPcHRpb25hbCBjYWxsYmFjay5cbiAgICpcbiAgICogQHByb3BlcnR5IHtBcnJheTxzdHJpbmc+fSBbc3RhdGUud2hpdGVsaXN0PVtdXSBVc2VyIGRpcmVjdCBtZXNzYWdlc1xuICAgKiB3aGl0ZWxpc3QuXG4gICAqIEBwcm9wZXJ0eSB7QXJyYXk8c3RyaW5nPn0gW3N0YXRlLmJsYWNrbGlzdD1bXV0gVXNlciBkaXJlY3QgbWVzc2FnZXNcbiAgICogYmxhY2tsaXN0LlxuICAgKiBAcHJvcGVydHkge2Jvb2xlYW59IFtzdGF0ZS53aGl0ZWxpc3RPbmx5PWZhbHNlXSBVc2VyIGRpcmVjdFxuICAgKiBtZXNzYWdlcyB3aGl0ZWxpc3RPbmx5IG1vZGUuXG4gICAqXG4gICAqIEByZXR1cm4ge1Byb21pc2U8dW5kZWZpbmVkPn0gUHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGhvdXQgYW55IGRhdGEuXG4gICAqL1xuICBhZGRVc2VyICh1c2VyTmFtZSwgc3RhdGUsIGNiKSB7XG4gICAgcmV0dXJuIGNoZWNrTmFtZVN5bWJvbHModXNlck5hbWUpXG4gICAgICAudGhlbigoKSA9PiB0aGlzLnN0YXRlLmFkZFVzZXIodXNlck5hbWUsIHN0YXRlKSlcbiAgICAgIC5yZXR1cm4oKVxuICAgICAgLmFzQ2FsbGJhY2soY2IpXG4gIH1cblxuICAvKipcbiAgICogRGVsZXRlcyBhbiBvZmZsaW5lIHVzZXIuIFdpbGwgcmFpc2UgYW4gZXJyb3IgaWYgYSB1c2VyIGhhcyBvbmxpbmVcbiAgICogc29ja2V0cy5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHVzZXJOYW1lIFVzZXIgbmFtZS5cbiAgICogQHBhcmFtIHtjYWxsYmFja30gW2NiXSBPcHRpb25hbCBjYWxsYmFjay5cbiAgICpcbiAgICogQHJldHVybiB7UHJvbWlzZTx1bmRlZmluZWQ+fSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aG91dCBhbnkgZGF0YS5cbiAgICovXG4gIGRlbGV0ZVVzZXIgKHVzZXJOYW1lLCBjYikge1xuICAgIHJldHVybiB0aGlzLnN0YXRlLmdldFVzZXIodXNlck5hbWUpLnRoZW4odXNlciA9PiB7XG4gICAgICByZXR1cm4gdXNlci5saXN0T3duU29ja2V0cygpLnRoZW4oc29ja2V0cyA9PiB7XG4gICAgICAgIGlmIChzb2NrZXRzICYmIF8uc2l6ZShzb2NrZXRzKSA+IDApIHtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IENoYXRTZXJ2aWNlRXJyb3IoJ3VzZXJPbmxpbmUnLCB1c2VyTmFtZSkpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKFtcbiAgICAgICAgICAgIHVzZXIucmVtb3ZlU3RhdGUoKSxcbiAgICAgICAgICAgIHRoaXMuc3RhdGUucmVtb3ZlVXNlcih1c2VyTmFtZSlcbiAgICAgICAgICBdKVxuICAgICAgICB9XG4gICAgICB9KVxuICAgIH0pLnJldHVybigpLmFzQ2FsbGJhY2soY2IpXG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGZvciBhbiB1c2VyIGV4aXN0ZW5jZS5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHVzZXJOYW1lIFVzZXIgbmFtZS5cbiAgICogQHBhcmFtIHtjYWxsYmFja30gW2NiXSBPcHRpb25hbCBjYWxsYmFjay5cbiAgICpcbiAgICogQHJldHVybiB7UHJvbWlzZTxib29sZWFuPn0gUHJlZGljYXRlIHJlc3VsdC5cbiAgICovXG4gIGhhc1VzZXIgKHVzZXJOYW1lLCBjYikge1xuICAgIHJldHVybiB0aGlzLnN0YXRlLmdldFVzZXIodXNlck5hbWUsIHRydWUpXG4gICAgICAudGhlbih1c2VyID0+IEJvb2xlYW4odXNlcikpXG4gICAgICAuYXNDYWxsYmFjayhjYilcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVja3MgZm9yIGEgbmFtZSBleGlzdGVuY2UgaW4gYSBkaXJlY3QgbWVzc2FnaW5nIGxpc3QuXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB1c2VyTmFtZSBVc2VyIG5hbWUuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBsaXN0TmFtZSBMaXN0IG5hbWUuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBpdGVtIExpc3QgZWxlbWVudC5cbiAgICogQHBhcmFtIHtjYWxsYmFja30gW2NiXSBPcHRpb25hbCBjYWxsYmFjay5cbiAgICpcbiAgICogQHJldHVybiB7UHJvbWlzZTxib29sZWFuPn0gUHJlZGljYXRlIHJlc3VsdC5cbiAgICovXG4gIHVzZXJIYXNJbkxpc3QgKHVzZXJOYW1lLCBsaXN0TmFtZSwgaXRlbSwgY2IpIHtcbiAgICByZXR1cm4gdGhpcy5zdGF0ZS5nZXRVc2VyKHVzZXJOYW1lKVxuICAgICAgLnRoZW4odXNlciA9PiB1c2VyLmRpcmVjdE1lc3NhZ2luZy5oYXNJbkxpc3QobGlzdE5hbWUsIGl0ZW0pKVxuICAgICAgLmFzQ2FsbGJhY2soY2IpXG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGZvciBhIGRpcmVjdCBtZXNzYWdpbmcgcGVybWlzc2lvbi5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHJlY2lwaWVudCBSZWNpcGllbnQgbmFtZS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHNlbmRlciBTZW5kZXIgbmFtZS5cbiAgICogQHBhcmFtIHtjYWxsYmFja30gW2NiXSBPcHRpb25hbCBjYWxsYmFjay5cbiAgICpcbiAgICogQHJldHVybiB7UHJvbWlzZTxib29sZWFuPn0gUHJlZGljYXRlIHJlc3VsdC5cbiAgICovXG4gIGhhc0RpcmVjdEFjY2VzcyAocmVjaXBpZW50LCBzZW5kZXIsIGNiKSB7XG4gICAgcmV0dXJuIHRoaXMuc3RhdGUuZ2V0VXNlcihyZWNpcGllbnQpXG4gICAgICAudGhlbih1c2VyID0+IHVzZXIuZGlyZWN0TWVzc2FnaW5nLmNoZWNrQWNlc3Moc2VuZGVyKSlcbiAgICAgIC5yZXR1cm4odHJ1ZSlcbiAgICAgIC5jYXRjaFJldHVybihDaGF0U2VydmljZUVycm9yLCBmYWxzZSlcbiAgICAgIC5hc0NhbGxiYWNrKGNiKVxuICB9XG5cbiAgLyoqXG4gICAqIERpc2Nvbm5lY3RzIHVzZXIncyBzb2NrZXRzIGZvciBhbGwgc2VydmljZSBpbnN0YW5jZXMuIE1ldGhvZCBpc1xuICAgKiBhc3luY2hyb25vdXMsIHJldHVybnMgd2l0aG91dCB3YWl0aW5nIGZvciB0aGUgY29tcGxldGlvbi5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHVzZXJOYW1lIFVzZXIgbmFtZS5cbiAgICpcbiAgICogQHJldHVybiB7dW5kZWZpbmVkfSBSZXR1cm5zIG5vIGRhdGEuXG4gICAqL1xuICBkaXNjb25uZWN0VXNlclNvY2tldHMgKHVzZXJOYW1lKSB7XG4gICAgdGhpcy5jbHVzdGVyQnVzLmVtaXQoJ2Rpc2Nvbm5lY3RVc2VyU29ja2V0cycsIHVzZXJOYW1lKVxuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYSByb29tIHdpdGggYSBzdGF0ZS5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHJvb21OYW1lIFJvb20gbmFtZS5cbiAgICogQHBhcmFtIHtPYmplY3R9IFtzdGF0ZV0gUm9vbSBzdGF0ZS5cbiAgICogQHBhcmFtIHtjYWxsYmFja30gW2NiXSBPcHRpb25hbCBjYWxsYmFjay5cbiAgICpcbiAgICogQHByb3BlcnR5IHtBcnJheTxzdHJpbmc+fSBbc3RhdGUud2hpdGVsaXN0PVtdXSBSb29tIHdoaXRlbGlzdC5cbiAgICogQHByb3BlcnR5IHtBcnJheTxzdHJpbmc+fSBbc3RhdGUuYmxhY2tsaXN0PVtdXSBSb29tIGJsYWNrbGlzdFxuICAgKiBAcHJvcGVydHkge0FycmF5PHN0cmluZz59IFtzdGF0ZS5hZG1pbmxpc3Q9W11dIFJvb20gYWRtaW5saXN0LlxuICAgKiBAcHJvcGVydHkge2Jvb2xlYW59IFtzdGF0ZS53aGl0ZWxpc3RPbmx5PWZhbHNlXSBSb29tXG4gICAqIHdoaXRlbGlzdE9ubHkgbW9kZS5cbiAgICogQHByb3BlcnR5IHtzdHJpbmd9IFtzdGF0ZS5vd25lcl0gUm9vbSBvd25lci5cbiAgICogQHByb3BlcnR5IHtudW1iZXJ9IFtzdGF0ZS5oaXN0b3J5TWF4U2l6ZV0gUm9vbSBoaXN0b3J5IG1heGltdW1cbiAgICogc2l6ZS4gRGVmYWx1dCB2YWx1ZSBpcyB7QGxpbmsgY2hhdC1zZXJ2aWNlLmNvbmZpZy5vcHRpb25zfVxuICAgKiBgaGlzdG9yeU1heFNpemVgLlxuICAgKiBAcHJvcGVydHkge2Jvb2xlYW59IFtzdGF0ZS5lbmFibGVBY2Nlc3NMaXN0c1VwZGF0ZXNdIFJvb20gZW5hYmxlXG4gICAqIGFjY2VzcyBsaXN0cyB1cGRhdGVzLiBEZWZhbHV0IHZhbHVlIGlzIHtAbGlua1xuICAgKiBjaGF0LXNlcnZpY2UuY29uZmlnLm9wdGlvbnN9IGBlbmFibGVBY2Nlc3NMaXN0c1VwZGF0ZXNgLlxuICAgKiBAcHJvcGVydHkge2Jvb2xlYW59IFtzdGF0ZS5lbmFibGVVc2VybGlzdFVwZGF0ZXNdIFJvb20gZW5hYmxlXG4gICAqIHVzZXJsaXN0IHVwZGF0ZXMuIERlZmFsdXQgdmFsdWUgaXMge0BsaW5rXG4gICAqIGNoYXQtc2VydmljZS5jb25maWcub3B0aW9uc30gYGVuYWJsZVVzZXJsaXN0VXBkYXRlc2AuXG4gICAqXG4gICAqIEByZXR1cm4ge1Byb21pc2U8dW5kZWZpbmVkPn0gUHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGhvdXQgYW55IGRhdGEuXG4gICAqL1xuICBhZGRSb29tIChyb29tTmFtZSwgc3RhdGUsIGNiKSB7XG4gICAgcmV0dXJuIGNoZWNrTmFtZVN5bWJvbHMocm9vbU5hbWUpXG4gICAgICAudGhlbigoKSA9PiB0aGlzLnN0YXRlLmFkZFJvb20ocm9vbU5hbWUsIHN0YXRlKSlcbiAgICAgIC5yZXR1cm4oKVxuICAgICAgLmFzQ2FsbGJhY2soY2IpXG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlcyBhbGwgam9pbmVkIHVzZXJzIGZyb20gdGhlIHJvb20gYW5kIHJlbW92ZXMgYWxsIHJvb20gZGF0YS5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHJvb21OYW1lIFJvb20gbmFtZS5cbiAgICogQHBhcmFtIHtjYWxsYmFja30gW2NiXSBPcHRpb25hbCBjYWxsYmFjay5cbiAgICpcbiAgICogQHJldHVybiB7UHJvbWlzZTx1bmRlZmluZWQ+fSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aG91dCBhbnkgZGF0YS5cbiAgICovXG4gIGRlbGV0ZVJvb20gKHJvb21OYW1lLCBjYikge1xuICAgIHJldHVybiB0aGlzLmV4ZWNVc2VyQ29tbWFuZCh0cnVlLCAncm9vbURlbGV0ZScsIHJvb21OYW1lKVxuICAgICAgLnJldHVybigpXG4gICAgICAuYXNDYWxsYmFjayhjYilcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVja3MgZm9yIGEgcm9vbSBleGlzdGVuY2UuXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSByb29tTmFtZSBSb29tIG5hbWUuXG4gICAqIEBwYXJhbSB7Y2FsbGJhY2t9IFtjYl0gT3B0aW9uYWwgY2FsbGJhY2suXG4gICAqXG4gICAqIEByZXR1cm4ge1Byb21pc2U8Ym9vbGVhbj59IFByZWRpY2F0ZSByZXN1bHQuXG4gICAqL1xuICBoYXNSb29tIChyb29tTmFtZSwgY2IpIHtcbiAgICByZXR1cm4gdGhpcy5zdGF0ZS5nZXRSb29tKHJvb21OYW1lLCB0cnVlKVxuICAgICAgLnRoZW4ocm9vbSA9PiBCb29sZWFuKHJvb20pKVxuICAgICAgLmFzQ2FsbGJhY2soY2IpXG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGZvciBhIG5hbWUgZXhpc3RlbmNlIGluIGEgcm9vbSBsaXN0LlxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gcm9vbU5hbWUgUm9vbSBuYW1lLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbGlzdE5hbWUgTGlzdCBuYW1lLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gaXRlbSBMaXN0IGVsZW1lbnQuXG4gICAqIEBwYXJhbSB7Y2FsbGJhY2t9IFtjYl0gT3B0aW9uYWwgY2FsbGJhY2suXG4gICAqXG4gICAqIEByZXR1cm4ge1Byb21pc2U8Ym9vbGVhbj59IFByZWRpY2F0ZSByZXN1bHQuXG4gICAqL1xuICByb29tSGFzSW5MaXN0IChyb29tTmFtZSwgbGlzdE5hbWUsIGl0ZW0sIGNiKSB7XG4gICAgcmV0dXJuIHRoaXMuc3RhdGUuZ2V0Um9vbShyb29tTmFtZSlcbiAgICAgIC50aGVuKHJvb20gPT4gcm9vbS5yb29tU3RhdGUuaGFzSW5MaXN0KGxpc3ROYW1lLCBpdGVtKSlcbiAgICAgIC5hc0NhbGxiYWNrKGNiKVxuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyBmb3IgYSByb29tIGFjY2VzcyBwZXJtaXNzaW9uLlxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gcm9vbU5hbWUgUm9vbSBuYW1lLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdXNlck5hbWUgVXNlciBuYW1lLlxuICAgKiBAcGFyYW0ge2NhbGxiYWNrfSBbY2JdIE9wdGlvbmFsIGNhbGxiYWNrLlxuICAgKlxuICAgKiBAcmV0dXJuIHtQcm9taXNlPGJvb2xlYW4+fSBQcmVkaWNhdGUgcmVzdWx0LlxuICAgKi9cbiAgaGFzUm9vbUFjY2VzcyAocm9vbU5hbWUsIHVzZXJOYW1lLCBjYikge1xuICAgIHJldHVybiB0aGlzLnN0YXRlLmdldFJvb20ocm9vbU5hbWUpXG4gICAgICAudGhlbihyb29tID0+IHJvb20uY2hlY2tBY2Vzcyh1c2VyTmFtZSkpXG4gICAgICAucmV0dXJuKHRydWUpXG4gICAgICAuY2F0Y2hSZXR1cm4oQ2hhdFNlcnZpY2VFcnJvciwgZmFsc2UpXG4gICAgICAuYXNDYWxsYmFjayhjYilcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGFuZ2VzIHRoZSByb29tIG93bmVyLlxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gcm9vbU5hbWUgUm9vbSBuYW1lLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gb3duZXIgT3duZXIgdXNlciBuYW1lLlxuICAgKiBAcGFyYW0ge2NhbGxiYWNrfSBbY2JdIE9wdGlvbmFsIGNhbGxiYWNrLlxuICAgKlxuICAgKiBAcmV0dXJuIHtQcm9taXNlPHVuZGVmaW5lZD59IFByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRob3V0IGFueSBkYXRhLlxuICAgKi9cbiAgY2hhbmdlUm9vbU93bmVyIChyb29tTmFtZSwgb3duZXIsIGNiKSB7XG4gICAgcmV0dXJuIHRoaXMuc3RhdGUuZ2V0Um9vbShyb29tTmFtZSlcbiAgICAgIC50aGVuKHJvb20gPT4gcm9vbS5yb29tU3RhdGUub3duZXJTZXQob3duZXIpKVxuICAgICAgLnJldHVybigpXG4gICAgICAuYXNDYWxsYmFjayhjYilcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGFuZ2VzIHRoZSByb29tIGhpc3Rvcnkgc2l6ZS5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHJvb21OYW1lIFJvb20gbmFtZS5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHNpemUgUm9vbSBoaXN0b3J5IHNpemUuXG4gICAqIEBwYXJhbSB7Y2FsbGJhY2t9IFtjYl0gT3B0aW9uYWwgY2FsbGJhY2suXG4gICAqXG4gICAqIEByZXR1cm4ge1Byb21pc2U8dW5kZWZpbmVkPn0gUHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGhvdXQgYW55IGRhdGEuXG4gICAqL1xuICBjaGFuZ2VSb29tSGlzdG9yeU1heFNpemUgKHJvb21OYW1lLCBzaXplLCBjYikge1xuICAgIHJldHVybiB0aGlzLnN0YXRlLmdldFJvb20ocm9vbU5hbWUpXG4gICAgICAudGhlbihyb29tID0+IHJvb20ucm9vbVN0YXRlLmhpc3RvcnlNYXhTaXplU2V0KHNpemUpKVxuICAgICAgLnJldHVybigpXG4gICAgICAuYXNDYWxsYmFjayhjYilcbiAgfVxuXG4gIC8qKlxuICAgKiBFbmFibGVzIG9yIGRpc2FibGVzIGFjY2VzcyBsaXN0cyB1cGRhdGVzIGZvciB0aGUgcm9vbS5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHJvb21OYW1lIFJvb20gbmFtZS5cbiAgICogQHBhcmFtIHtib29sZWFufSBtb2RlIEVuYWJsZSBvciBkaXNhYmxlLlxuICAgKiBAcGFyYW0ge2NhbGxiYWNrfSBbY2JdIE9wdGlvbmFsIGNhbGxiYWNrLlxuICAgKlxuICAgKiBAcmV0dXJuIHtQcm9taXNlPHVuZGVmaW5lZD59IFByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRob3V0IGFueSBkYXRhLlxuICAgKlxuICAgKiBAc2VlIHJwYy5zZXJ2ZXJOb3RpZmljYXRpb25zLnJvb21BY2Nlc3NMaXN0QWRkZWRcbiAgICogQHNlZSBycGMuc2VydmVyTm90aWZpY2F0aW9ucy5yb29tQWNjZXNzTGlzdFJlbW92ZWRcbiAgICogQHNlZSBycGMuc2VydmVyTm90aWZpY2F0aW9ucy5yb29tTW9kZUNoYW5nZWRcbiAgICovXG4gIGNoYW5nZUFjY2Vzc0xpc3RzVXBkYXRlcyAocm9vbU5hbWUsIG1vZGUsIGNiKSB7XG4gICAgcmV0dXJuIHRoaXMuc3RhdGUuZ2V0Um9vbShyb29tTmFtZSlcbiAgICAgIC50aGVuKHJvb20gPT4gcm9vbS5yb29tU3RhdGUuYWNjZXNzTGlzdHNVcGRhdGVzU2V0KG1vZGUpKVxuICAgICAgLnJldHVybigpXG4gICAgICAuYXNDYWxsYmFjayhjYilcbiAgfVxuXG4gIC8qKlxuICAgKiBFbmFibGVzIG9yIGRpc2FibGVzIHVzZXIgbGlzdCB1cGRhdGVzIGZvciB0aGUgcm9vbS5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHJvb21OYW1lIFJvb20gbmFtZS5cbiAgICogQHBhcmFtIHtib29sZWFufSBtb2RlIEVuYWJsZSBvciBkaXNhYmxlLlxuICAgKiBAcGFyYW0ge2NhbGxiYWNrfSBbY2JdIE9wdGlvbmFsIGNhbGxiYWNrLlxuICAgKlxuICAgKiBAcmV0dXJuIHtQcm9taXNlPHVuZGVmaW5lZD59IFByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRob3V0IGFueSBkYXRhLlxuICAgKlxuICAgKiBAc2VlIHJwYy5zZXJ2ZXJOb3RpZmljYXRpb25zLnJvb21Vc2VySm9pbmVkXG4gICAqIEBzZWUgcnBjLnNlcnZlck5vdGlmaWNhdGlvbnMucm9vbVVzZXJMZWZ0XG4gICAqL1xuICBjaGFuZ2VVc2VybGlzdFVwZGF0ZXMgKHJvb21OYW1lLCBtb2RlLCBjYikge1xuICAgIHJldHVybiB0aGlzLnN0YXRlLmdldFJvb20ocm9vbU5hbWUpXG4gICAgICAudGhlbihyb29tID0+IHJvb20ucm9vbVN0YXRlLnVzZXJsaXN0VXBkYXRlc1NldChtb2RlKSlcbiAgICAgIC5yZXR1cm4oKVxuICAgICAgLmFzQ2FsbGJhY2soY2IpXG4gIH1cblxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IFNlcnZpY2VBUElcbiJdfQ==
\No newline at end of file