@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
193 lines • 32.7 kB
JavaScript
import { Injectable } from '@angular/core';
import { UserService, InventoryService, DeviceRegistrationService, DeviceRegistrationStatus } from '@c8y/client';
import { gettext } from '@c8y/ngx-components';
import { get, pick, set } from 'lodash-es';
import { BehaviorSubject, interval, merge, Subject } from 'rxjs';
import { ManagedObjectRealtimeService, DeviceBootstrapRealtimeService, AppStateService } from '@c8y/ngx-components';
import { SubscriptionStatusViewModelFactory, NewDeviceRequestStatusFactory } from './factories/data-broker.subscription.factory';
import { distinctUntilChanged, filter, map, switchMap, takeUntil, tap } from 'rxjs/operators';
import * as i0 from "@angular/core";
import * as i1 from "@c8y/ngx-components";
import * as i2 from "@c8y/client";
export class DataBrokerSubscriptionsService {
constructor(moRealtimeService, deviceBootstrapRealtimeService, inventoryService, userService, deviceRegistrationService, appStateService) {
this.moRealtimeService = moRealtimeService;
this.deviceBootstrapRealtimeService = deviceBootstrapRealtimeService;
this.inventoryService = inventoryService;
this.userService = userService;
this.deviceRegistrationService = deviceRegistrationService;
this.appStateService = appStateService;
this.FRAGMENT_TYPE = 'c8y_BrokerSource';
this.NEW_DEVICE_REQUEST_TYPE = 'c8y_DataBroker';
/**
* inventory polling interval
*/
this.POLL_INTERVAL_FOR_SUBSCRIPTIONS = 15000;
this.moRealtimeSubscriptionsMap = new Map();
this.refreshPendingTrigger$ = new BehaviorSubject(null);
this.filters = {
fragmentType: this.FRAGMENT_TYPE,
pageSize: 2000
};
this.subscriptionStatusViewModelFactory = new SubscriptionStatusViewModelFactory();
this.newDeviceRequestStatusViewModelFactory = new NewDeviceRequestStatusFactory();
// Build legacy enum structure for ng1 component
this.NEW_DEVICE_REQUEST_STATUS = this.generateDeviceRequestStatusEnum(this.newDeviceRequestStatusViewModelFactory);
}
async getBrokerSubscriptionsList() {
return (await this.inventoryService.list(this.filters)).data;
}
/**
* User status text (legacy compatibility)
*/
getVisibleUserStatusText(user) {
return user.enabled ? gettext('active`subscription`') : gettext('inactive`subscription`');
}
async remove(subscription) {
// handle realtime unsubsribe
if (this.moRealtimeSubscriptionsMap.has(subscription.id)) {
this.moRealtimeSubscriptionsMap.get(subscription.id).unsubscribe();
this.moRealtimeSubscriptionsMap.delete(subscription.id);
}
// handle removal
const brokerSourceRenamed = `_${this.FRAGMENT_TYPE}`;
set(subscription, this.FRAGMENT_TYPE, null);
return await this.inventoryService.update(pick(subscription, ['id', this.FRAGMENT_TYPE, brokerSourceRenamed]));
}
async setStatus(subscription, enabled) {
const userData = (await this.userService.update({
id: subscription.userId,
enabled
})).data;
subscription.userEnabled = userData.enabled;
subscription.visibleUserStatus = this.getVisibleUserStatusText(userData);
return subscription;
}
/**
* List of pending subscriptions
*/
async listPendingBrokerSubscriptions() {
return (await this.deviceRegistrationService.list({
pageSize: 2000,
withTotalPages: true
})).data;
}
/**
* Accept subscription
*/
async accept(code) {
return (await this.deviceRegistrationService.accept(code)).data;
}
/**
* Discard subscription
*/
async discard(code) {
return await this.deviceRegistrationService.delete(code);
}
/**
* Add new subscription
*/
async create(code) {
return (await this.deviceRegistrationService.create({
id: code,
type: this.NEW_DEVICE_REQUEST_TYPE
})).data;
}
getForNg1({ pollingInterval, onPendingSubscriptions, onExistingSubscriptions, onMoUpdate }) {
const reload$ = new Subject();
const destroy$ = new Subject();
const ready$ = new Subject();
const unsubscribeRealtime = () => {
const moRealtimeSubscriptionIterator = this.moRealtimeSubscriptionsMap.keys();
let key = moRealtimeSubscriptionIterator.next().value;
while (this.moRealtimeSubscriptionsMap.has(key)) {
this.moRealtimeSubscriptionsMap.get(key).unsubscribe();
this.moRealtimeSubscriptionsMap.delete(key);
key = moRealtimeSubscriptionIterator.next().value;
}
};
const userInitialized$ = this.appStateService.currentUser.pipe(filter(currentUser => currentUser !== null));
const triggers = merge(reload$, ready$);
const pendingSubscriptions$ = merge(triggers, this.deviceBootstrapRealtimeService.onAll$(), this.refreshPendingTrigger$).pipe(switchMap(() => userInitialized$), switchMap(() => this.listPendingBrokerSubscriptions()), map(pendingSubscriptions => this.convertDeviceRegistrationsToSubscriptionViewModels(pendingSubscriptions)), takeUntil(destroy$));
const existingSubscriptions$ = merge(triggers, interval(pollingInterval)).pipe(switchMap(() => userInitialized$), switchMap(() => this.getBrokerSubscriptionsList()), tap(mos => {
if (this.subscriptionsCount !== mos.length) {
this.refreshPendingTrigger$.next();
this.subscriptionsCount = mos.length;
}
mos.forEach(mo => {
if (!this.moRealtimeSubscriptionsMap.has(mo.id)) {
const mortObservable = this.moRealtimeService
.onUpdate$(mo.id)
.pipe(switchMap(mo => this.convertToViewModel([mo])));
this.moRealtimeSubscriptionsMap.set(mo.id, mortObservable.subscribe(onMoUpdate));
}
});
}), distinctUntilChanged(), switchMap(mos => this.convertToViewModel(mos)), takeUntil(destroy$));
return {
init() {
pendingSubscriptions$.subscribe(onPendingSubscriptions);
existingSubscriptions$.subscribe(onExistingSubscriptions);
setTimeout(() => {
ready$.next();
}, 1000);
},
reload() {
reload$.next();
},
destroy() {
destroy$.next();
destroy$.complete();
unsubscribeRealtime();
}
};
}
convertDeviceRegistrationsToSubscriptionViewModels(pendingSubscriptions) {
const convertedToViewModel = pendingSubscriptions
.filter(deviceRequest => deviceRequest.type === this.NEW_DEVICE_REQUEST_TYPE)
.map(deviceRequest => {
return Object.assign({}, get(deviceRequest, 'customProperties.c8y_BrokerSource'), {
status: this.newDeviceRequestStatusViewModelFactory.build(deviceRequest.status),
type: deviceRequest.type,
id: deviceRequest.id
});
});
return convertedToViewModel;
}
generateDeviceRequestStatusEnum(newDeviceRequestViewModelFactory) {
const result = {};
for (const status in DeviceRegistrationStatus) {
Object.defineProperty(result, status, {
enumerable: true,
writable: false,
configurable: false,
value: newDeviceRequestViewModelFactory.build(status)
});
}
return result;
}
// Function maps data in suitable manner to have it easier to display. Used in service mainly for compatibility
async convertToViewModel(subscriptions) {
const viewModelSubscriptions = subscriptions.map(async (subscription) => {
const { data: userDetails } = await this.userService.detail(subscription.owner);
return {
userEnabled: userDetails.enabled,
visibleUserStatus: this.getVisibleUserStatusText(userDetails), //TODO:IIAR should be extracted to ngx pipe when the rest of data-broker is migrated
userId: userDetails.id,
status: this.getStatusViewModel(subscription.c8y_BrokerSource.status), //TODO:IIAR should be extracted to ngx pipe when the rest of data-broker is migrated
id: subscription.id,
_c8y_BrokerSource: subscription.c8y_BrokerSource
};
});
return Promise.all(viewModelSubscriptions);
}
// Status decoration (legacy compatibility)
getStatusViewModel(status) {
return this.subscriptionStatusViewModelFactory.build(status);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DataBrokerSubscriptionsService, deps: [{ token: i1.ManagedObjectRealtimeService }, { token: i1.DeviceBootstrapRealtimeService }, { token: i2.InventoryService }, { token: i2.UserService }, { token: i2.DeviceRegistrationService }, { token: i1.AppStateService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DataBrokerSubscriptionsService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DataBrokerSubscriptionsService, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: i1.ManagedObjectRealtimeService }, { type: i1.DeviceBootstrapRealtimeService }, { type: i2.InventoryService }, { type: i2.UserService }, { type: i2.DeviceRegistrationService }, { type: i1.AppStateService }] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YS1icm9rZXItc3Vic2NyaXB0aW9ucy5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vZGF0YS1icm9rZXIvZGF0YS1icm9rZXItc3Vic2NyaXB0aW9ucy5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUlMLFdBQVcsRUFDWCxnQkFBZ0IsRUFDaEIseUJBQXlCLEVBQ3pCLHdCQUF3QixFQUN6QixNQUFNLGFBQWEsQ0FBQztBQUNyQixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDOUMsT0FBTyxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQzNDLE9BQU8sRUFBRSxlQUFlLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBYyxPQUFPLEVBQWdCLE1BQU0sTUFBTSxDQUFDO0FBQzNGLE9BQU8sRUFDTCw0QkFBNEIsRUFDNUIsOEJBQThCLEVBQzlCLGVBQWUsRUFDaEIsTUFBTSxxQkFBcUIsQ0FBQztBQU83QixPQUFPLEVBQ0wsa0NBQWtDLEVBQ2xDLDZCQUE2QixFQUM5QixNQUFNLDhDQUE4QyxDQUFDO0FBQ3RELE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7Ozs7QUFHOUYsTUFBTSxPQUFPLDhCQUE4QjtJQWdDekMsWUFDVSxpQkFBK0MsRUFDL0MsOEJBQThELEVBQzlELGdCQUFrQyxFQUNsQyxXQUF3QixFQUN4Qix5QkFBb0QsRUFDcEQsZUFBZ0M7UUFMaEMsc0JBQWlCLEdBQWpCLGlCQUFpQixDQUE4QjtRQUMvQyxtQ0FBOEIsR0FBOUIsOEJBQThCLENBQWdDO1FBQzlELHFCQUFnQixHQUFoQixnQkFBZ0IsQ0FBa0I7UUFDbEMs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ci9jb3JlJztcbmltcG9ydCB7XG4gIElEZXZpY2VSZWdpc3RyYXRpb24sXG4gIElNYW5hZ2VkT2JqZWN0LFxuICBJVXNlcixcbiAgVXNlclNlcnZpY2UsXG4gIEludmVudG9yeVNlcnZpY2UsXG4gIERldmljZVJlZ2lzdHJhdGlvblNlcnZpY2UsXG4gIERldmljZVJlZ2lzdHJhdGlvblN0YXR1c1xufSBmcm9tICdAYzh5L2NsaWVudCc7XG5pbXBvcnQgeyBnZXR0ZXh0IH0gZnJvbSAnQGM4eS9uZ3gtY29tcG9uZW50cyc7XG5pbXBvcnQgeyBnZXQsIHBpY2ssIHNldCB9IGZyb20gJ2xvZGFzaC1lcyc7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIGludGVydmFsLCBtZXJnZSwgT2JzZXJ2YWJsZSwgU3ViamVjdCwgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQge1xuICBNYW5hZ2VkT2JqZWN0UmVhbHRpbWVTZXJ2aWNlLFxuICBEZXZpY2VCb290c3RyYXBSZWFsdGltZVNlcnZpY2UsXG4gIEFwcFN0YXRlU2VydmljZVxufSBmcm9tICdAYzh5L25neC1jb21wb25lbnRzJztcbmltcG9ydCB7XG4gIFN1YnNjcmlwdGlvblN0YXR1c1ZpZXdNb2RlbCxcbiAgRGF0YUJyb2tlckNvbm5lY3RvclN0YXR1cyxcbiAgU3Vic2NyaXB0aW9uVmlld01vZGVsLFxuICBTdWJzY3JpcHRpb25zVmlld01vZGVsTmcxXG59IGZyb20gJy4vbW9kZWwvZGF0YS1icm9rZXIuc3Vic2NyaXB0aW9uLm1vZGVsJztcbmltcG9ydCB7XG4gIFN1YnNjcmlwdGlvblN0YXR1c1ZpZXdNb2RlbEZhY3RvcnksXG4gIE5ld0RldmljZVJlcXVlc3RTdGF0dXNGYWN0b3J5XG59IGZyb20gJy4vZmFjdG9yaWVzL2RhdGEtYnJva2VyLnN1YnNjcmlwdGlvbi5mYWN0b3J5JztcbmltcG9ydCB7IGRpc3RpbmN0VW50aWxDaGFuZ2VkLCBmaWx0ZXIsIG1hcCwgc3dpdGNoTWFwLCB0YWtlVW50aWwsIHRhcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIERhdGFCcm9rZXJTdWJzY3JpcHRpb25zU2VydmljZSB7XG4gIHByaXZhdGUgcmVhZG9ubHkgRlJBR01FTlRfVFlQRTogc3RyaW5nID0gJ2M4eV9Ccm9rZXJTb3VyY2UnO1xuICBwcml2YXRlIHJlYWRvbmx5IE5FV19ERVZJQ0VfUkVRVUVTVF9UWVBFOiBzdHJpbmcgPSAnYzh5X0RhdGFCcm9rZXInO1xuICAvKipcbiAgICogaW52ZW50b3J5IHBvbGxpbmcgaW50ZXJ2YWxcbiAgICovXG4gIHByaXZhdGUgcmVhZG9ubHkgUE9MTF9JTlRFUlZBTF9GT1JfU1VCU0NSSVBUSU9OUyA9IDE1MDAwO1xuICAvKipcbiAgICogcHJvZHVjZSBzdGF0dXMgZnJhZ21lbnQgZm9yIHN1YnNjcmlwdGlvblxuICAgKi9cbiAgcHJpdmF0ZSBzdWJzY3JpcHRpb25TdGF0dXNWaWV3TW9kZWxGYWN0b3J5OiBTdWJzY3JpcHRpb25TdGF0dXNWaWV3TW9kZWxGYWN0b3J5O1xuICAvKipcbiAgICogcHJvZHVjZSByZXF1ZXN0IHN0YXR1cyB2aWV3IG1vZGVsXG4gICAqL1xuICBwcml2YXRlIG5ld0RldmljZVJlcXVlc3RTdGF0dXNWaWV3TW9kZWxGYWN0b3J5OiBOZXdEZXZpY2VSZXF1ZXN0U3RhdHVzRmFjdG9yeTtcblxuICBwcml2YXRlIG1vUmVhbHRpbWVTdWJzY3JpcHRpb25zTWFwID0gbmV3IE1hcDxzdHJpbmcsIFN1YnNjcmlwdGlvbj4oKTtcblxuICBwcml2YXRlIHN1YnNjcmlwdGlvbnNDb3VudDtcblxuICBwcml2YXRlIHJlZnJlc2hQZW5kaW5nVHJpZ2dlciQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PHZvaWQ+KG51bGwpO1xuXG4gIGZpbHRlcnMgPSB7XG4gICAgZnJhZ21lbnRUeXBlOiB0aGlzLkZSQUdNRU5UX1RZUEUsXG4gICAgcGFnZVNpemU6IDIwMDBcbiAgfTtcblxuICAvKipcbiAgICogbGVnYWN5IGVudW0gdmFsdWVzXG4gICAqL1xuICBORVdfREVWSUNFX1JFUVVFU1RfU1RBVFVTO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgbW9SZWFsdGltZVNlcnZpY2U6IE1hbmFnZWRPYmplY3RSZWFsdGltZVNlcnZpY2UsXG4gICAgcHJpdmF0ZSBkZXZpY2VCb290c3RyYXBSZWFsdGltZVNlcnZpY2U6IERldmljZUJvb3RzdHJhcFJlYWx0aW1lU2VydmljZSxcbiAgICBwcml2YXRlIGludmVudG9yeVNlcnZpY2U6IEludmVudG9yeVNlcnZpY2UsXG4gICAgcHJpdmF0ZSB1c2VyU2VydmljZTogVXNlclNlcnZpY2UsXG4gICAgcHJpdmF0ZSBkZXZpY2VSZWdpc3RyYXRpb25TZXJ2aWNlOiBEZXZpY2VSZWdpc3RyYXRpb25TZXJ2aWNlLFxuICAgIHByaXZhdGUgYXBwU3RhdGVTZXJ2aWNlOiBBcHBTdGF0ZVNlcnZpY2VcbiAgKSB7XG4gICAgdGhpcy5zdWJzY3JpcHRpb25TdGF0dXNWaWV3TW9kZWxGYWN0b3J5ID0gbmV3IFN1YnNjcmlwdGlvblN0YXR1c1ZpZXdNb2RlbEZhY3RvcnkoKTtcbiAgICB0aGlzLm5ld0RldmljZVJlcXVlc3RTdGF0dXNWaWV3TW9kZWxGYWN0b3J5ID0gbmV3IE5ld0RldmljZVJlcXVlc3RTdGF0dXNGYWN0b3J5KCk7XG5cbiAgICAvLyBCdWlsZCBsZWdhY3kgZW51bSBzdHJ1Y3R1cmUgZm9yIG5nMSBjb21wb25lbnRcbiAgICB0aGlzLk5FV19ERVZJQ0VfUkVRVUVTVF9TVEFUVVMgPSB0aGlzLmdlbmVyYXRlRGV2aWNlUmVxdWVzdFN0YXR1c0VudW0oXG4gICAgICB0aGlzLm5ld0RldmljZVJlcXVlc3RTdGF0dXNWaWV3TW9kZWxGYWN0b3J5XG4gICAgKTtcbiAgfVxuXG4gIGFzeW5jIGdldEJyb2tlclN1YnNjcmlwdGlvbnNMaXN0KCk6IFByb21pc2U8SU1hbmFnZWRPYmplY3RbXT4ge1xuICAgIHJldHVybiAoYXdhaXQgdGhpcy5pbnZlbnRvcnlTZXJ2aWNlLmxpc3QodGhpcy5maWx0ZXJzKSkuZGF0YTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVc2VyIHN0YXR1cyB0ZXh0IChsZWdhY3kgY29tcGF0aWJpbGl0eSlcbiAgICovXG4gIGdldFZpc2libGVVc2VyU3RhdHVzVGV4dCh1c2VyKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdXNlci5lbmFibGVkID8gZ2V0dGV4dCgnYWN0aXZlYHN1YnNjcmlwdGlvbmAnKSA6IGdldHRleHQoJ2luYWN0aXZlYHN1YnNjcmlwdGlvbmAnKTtcbiAgfVxuXG4gIGFzeW5jIHJlbW92ZShzdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvblZpZXdNb2RlbCkge1xuICAgIC8vIGhhbmRsZSByZWFsdGltZSB1bnN1YnNyaWJlXG4gICAgaWYgKHRoaXMubW9SZWFsdGltZVN1YnNjcmlwdGlvbnNNYXAuaGFzKHN1YnNjcmlwdGlvbi5pZCkpIHtcbiAgICAgIHRoaXMubW9SZWFsdGltZVN1YnNjcmlwdGlvbnNNYXAuZ2V0KHN1YnNjcmlwdGlvbi5pZCkudW5zdWJzY3JpYmUoKTtcbiAgICAgIHRoaXMubW9SZWFsdGltZVN1YnNjcmlwdGlvbnNNYXAuZGVsZXRlKHN1YnNjcmlwdGlvbi5pZCk7XG4gICAgfVxuICAgIC8vIGhhbmRsZSByZW1vdmFsXG4gICAgY29uc3QgYnJva2VyU291cmNlUmVuYW1lZCA9IGBfJHt0aGlzLkZSQUdNRU5UX1RZUEV9YDtcbiAgICBzZXQoc3Vic2NyaXB0aW9uLCB0aGlzLkZSQUdNRU5UX1RZUEUsIG51bGwpO1xuXG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuaW52ZW50b3J5U2VydmljZS51cGRhdGUoXG4gICAgICBwaWNrKHN1YnNjcmlwdGlvbiwgWydpZCcsIHRoaXMuRlJBR01FTlRfVFlQRSwgYnJva2VyU291cmNlUmVuYW1lZF0pXG4gICAgKTtcbiAgfVxuXG4gIGFzeW5jIHNldFN0YXR1cyhcbiAgICBzdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvblZpZXdNb2RlbCxcbiAgICBlbmFibGVkOiBib29sZWFuXG4gICk6IFByb21pc2U8U3Vic2NyaXB0aW9uVmlld01vZGVsPiB7XG4gICAgY29uc3QgdXNlckRhdGEgPSAoXG4gICAgICBhd2FpdCB0aGlzLnVzZXJTZXJ2aWNlLnVwZGF0ZSh7XG4gICAgICAgIGlkOiBzdWJzY3JpcHRpb24udXNlcklkLFxuICAgICAgICBlbmFibGVkXG4gICAgICB9IGFzIFBhcnRpYWw8SVVzZXI+KVxuICAgICkuZGF0YTtcbiAgICBzdWJzY3JpcHRpb24udXNlckVuYWJsZWQgPSB1c2VyRGF0YS5lbmFibGVkO1xuICAgIHN1YnNjcmlwdGlvbi52aXNpYmxlVXNlclN0YXR1cyA9IHRoaXMuZ2V0VmlzaWJsZVVzZXJTdGF0dXNUZXh0KHVzZXJEYXRhKTtcbiAgICByZXR1cm4gc3Vic2NyaXB0aW9uO1xuICB9XG5cbiAgLyoqXG4gICAqIExpc3Qgb2YgcGVuZGluZyBzdWJzY3JpcHRpb25zXG4gICAqL1xuICBhc3luYyBsaXN0UGVuZGluZ0Jyb2tlclN1YnNjcmlwdGlvbnMoKTogUHJvbWlzZTxJRGV2aWNlUmVnaXN0cmF0aW9uW10+IHtcbiAgICByZXR1cm4gKFxuICAgICAgYXdhaXQgdGhpcy5kZXZpY2VSZWdpc3RyYXRpb25TZXJ2aWNlLmxpc3Qoe1xuICAgICAgICBwYWdlU2l6ZTogMjAwMCxcbiAgICAgICAgd2l0aFRvdGFsUGFnZXM6IHRydWVcbiAgICAgIH0pXG4gICAgKS5kYXRhO1xuICB9XG5cbiAgLyoqXG4gICAqIEFjY2VwdCBzdWJzY3JpcHRpb25cbiAgICovXG4gIGFzeW5jIGFjY2VwdChjb2RlOiBzdHJpbmcpOiBQcm9taXNlPElEZXZpY2VSZWdpc3RyYXRpb24+IHtcbiAgICByZXR1cm4gKGF3YWl0IHRoaXMuZGV2aWNlUmVnaXN0cmF0aW9uU2VydmljZS5hY2NlcHQoY29kZSkpLmRhdGE7XG4gIH1cblxuICAvKipcbiAgICogRGlzY2FyZCBzdWJzY3JpcHRpb25cbiAgICovXG4gIGFzeW5jIGRpc2NhcmQoY29kZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuZGV2aWNlUmVnaXN0cmF0aW9uU2VydmljZS5kZWxldGUoY29kZSk7XG4gIH1cblxuICAvKipcbiAgICogQWRkIG5ldyBzdWJzY3JpcHRpb25cbiAgICovXG4gIGFzeW5jIGNyZWF0ZShjb2RlOiBzdHJpbmcpOiBQcm9taXNlPElEZXZpY2VSZWdpc3RyYXRpb24+IHtcbiAgICByZXR1cm4gKFxuICAgICAgYXdhaXQgdGhpcy5kZXZpY2VSZWdpc3RyYXRpb25TZXJ2aWNlLmNyZWF0ZSh7XG4gICAgICAgIGlkOiBjb2RlLFxuICAgICAgICB0eXBlOiB0aGlzLk5FV19ERVZJQ0VfUkVRVUVTVF9UWVBFXG4gICAgICB9KVxuICAgICkuZGF0YTtcbiAgfVxuXG4gIGdldEZvck5nMSh7XG4gICAgcG9sbGluZ0ludGVydmFsLFxuICAgIG9uUGVuZGluZ1N1YnNjcmlwdGlvbnMsXG4gICAgb25FeGlzdGluZ1N1YnNjcmlwdGlvbnMsXG4gICAgb25Nb1VwZGF0ZVxuICB9KTogU3Vic2NyaXB0aW9uc1ZpZXdNb2RlbE5nMSB7XG4gICAgY29uc3QgcmVsb2FkJCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG4gICAgY29uc3QgZGVzdHJveSQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuICAgIGNvbnN0IHJlYWR5JCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cbiAgICBjb25zdCB1bnN1YnNjcmliZVJlYWx0aW1lID0gKCkgPT4ge1xuICAgICAgY29uc3QgbW9SZWFsdGltZVN1YnNjcmlwdGlvbkl0ZXJhdG9yID0gdGhpcy5tb1JlYWx0aW1lU3Vic2NyaXB0aW9uc01hcC5rZXlzKCk7XG4gICAgICBsZXQga2V5ID0gbW9SZWFsdGltZVN1YnNjcmlwdGlvbkl0ZXJhdG9yLm5leHQoKS52YWx1ZSBhcyBzdHJpbmc7XG4gICAgICB3aGlsZSAodGhpcy5tb1JlYWx0aW1lU3Vic2NyaXB0aW9uc01hcC5oYXMoa2V5KSkge1xuICAgICAgICB0aGlzLm1vUmVhbHRpbWVTdWJzY3JpcHRpb25zTWFwLmdldChrZXkpLnVuc3Vic2NyaWJlKCk7XG4gICAgICAgIHRoaXMubW9SZWFsdGltZVN1YnNjcmlwdGlvbnNNYXAuZGVsZXRlKGtleSBhcyBzdHJpbmcpO1xuICAgICAgICBrZXkgPSBtb1JlYWx0aW1lU3Vic2NyaXB0aW9uSXRlcmF0b3IubmV4dCgpLnZhbHVlIGFzIHN0cmluZztcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgY29uc3QgdXNlckluaXRpYWxpemVkJCA9IHRoaXMuYXBwU3RhdGVTZXJ2aWNlLmN1cnJlbnRVc2VyLnBpcGUoXG4gICAgICBmaWx0ZXIoY3VycmVudFVzZXIgPT4gY3VycmVudFVzZXIgIT09IG51bGwpXG4gICAgKTtcbiAgICBjb25zdCB0cmlnZ2VycyA9IG1lcmdlKHJlbG9hZCQsIHJlYWR5JCk7XG4gICAgY29uc3QgcGVuZGluZ1N1YnNjcmlwdGlvbnMkOiBPYnNlcnZhYmxlPFN1YnNjcmlwdGlvblZpZXdNb2RlbFtdPiA9IG1lcmdlKFxuICAgICAgdHJpZ2dlcnMsXG4gICAgICB0aGlzLmRldmljZUJvb3RzdHJhcFJlYWx0aW1lU2VydmljZS5vbkFsbCQoKSxcbiAgICAgIHRoaXMucmVmcmVzaFBlbmRpbmdUcmlnZ2VyJFxuICAgICkucGlwZShcbiAgICAgIHN3aXRjaE1hcCgoKSA9PiB1c2VySW5pdGlhbGl6ZWQkKSxcbiAgICAgIHN3aXRjaE1hcCgoKSA9PiB0aGlzLmxpc3RQZW5kaW5nQnJva2VyU3Vic2NyaXB0aW9ucygpKSxcbiAgICAgIG1hcChwZW5kaW5nU3Vic2NyaXB0aW9ucyA9PlxuICAgICAgICB0aGlzLmNvbnZlcnREZXZpY2VSZWdpc3RyYXRpb25zVG9TdWJzY3JpcHRpb25WaWV3TW9kZWxzKHBlbmRpbmdTdWJzY3JpcHRpb25zKVxuICAgICAgKSxcbiAgICAgIHRha2VVbnRpbChkZXN0cm95JClcbiAgICApO1xuICAgIGNvbnN0IGV4aXN0aW5nU3Vic2NyaXB0aW9ucyQ6IE9ic2VydmFibGU8U3Vic2NyaXB0aW9uVmlld01vZGVsW10+ID0gbWVyZ2UoXG4gICAgICB0cmlnZ2VycyxcbiAgICAgIGludGVydmFsKHBvbGxpbmdJbnRlcnZhbClcbiAgICApLnBpcGUoXG4gICAgICBzd2l0Y2hNYXAoKCkgPT4gdXNlckluaXRpYWxpemVkJCksXG4gICAgICBzd2l0Y2hNYXAoKCkgPT4gdGhpcy5nZXRCcm9rZXJTdWJzY3JpcHRpb25zTGlzdCgpKSxcbiAgICAgIHRhcChtb3MgPT4ge1xuICAgICAgICBpZiAodGhpcy5zdWJzY3JpcHRpb25zQ291bnQgIT09IG1vcy5sZW5ndGgpIHtcbiAgICAgICAgICB0aGlzLnJlZnJlc2hQZW5kaW5nVHJpZ2dlciQubmV4dCgpO1xuICAgICAgICAgIHRoaXMuc3Vic2NyaXB0aW9uc0NvdW50ID0gbW9zLmxlbmd0aDtcbiAgICAgICAgfVxuICAgICAgICBtb3MuZm9yRWFjaChtbyA9PiB7XG4gICAgICAgICAgaWYgKCF0aGlzLm1vUmVhbHRpbWVTdWJzY3JpcHRpb25zTWFwLmhhcyhtby5pZCkpIHtcbiAgICAgICAgICAgIGNvbnN0IG1vcnRPYnNlcnZhYmxlID0gdGhpcy5tb1JlYWx0aW1lU2VydmljZVxuICAgICAgICAgICAgICAub25VcGRhdGUkKG1vLmlkKVxuICAgICAgICAgICAgICAucGlwZShzd2l0Y2hNYXAobW8gPT4gdGhpcy5jb252ZXJ0VG9WaWV3TW9kZWwoW21vXSkpKTtcbiAgICAgICAgICAgIHRoaXMubW9SZWFsdGltZVN1YnNjcmlwdGlvbnNNYXAuc2V0KG1vLmlkLCBtb3J0T2JzZXJ2YWJsZS5zdWJzY3JpYmUob25Nb1VwZGF0ZSkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9KSxcbiAgICAgIGRpc3RpbmN0VW50aWxDaGFuZ2VkKCksXG4gICAgICBzd2l0Y2hNYXAobW9zID0+IHRoaXMuY29udmVydFRvVmlld01vZGVsKG1vcykpLFxuICAgICAgdGFrZVVudGlsKGRlc3Ryb3kkKVxuICAgICk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgaW5pdCgpIHtcbiAgICAgICAgcGVuZGluZ1N1YnNjcmlwdGlvbnMkLnN1YnNjcmliZShvblBlbmRpbmdTdWJzY3JpcHRpb25zKTtcbiAgICAgICAgZXhpc3RpbmdTdWJzY3JpcHRpb25zJC5zdWJzY3JpYmUob25FeGlzdGluZ1N1YnNjcmlwdGlvbnMpO1xuICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICByZWFkeSQubmV4dCgpO1xuICAgICAgICB9LCAxMDAwKTtcbiAgICAgIH0sXG4gICAgICByZWxvYWQoKSB7XG4gICAgICAgIHJlbG9hZCQubmV4dCgpO1xuICAgICAgfSxcbiAgICAgIGRlc3Ryb3koKSB7XG4gICAgICAgIGRlc3Ryb3kkLm5leHQoKTtcbiAgICAgICAgZGVzdHJveSQuY29tcGxldGUoKTtcbiAgICAgICAgdW5zdWJzY3JpYmVSZWFsdGltZSgpO1xuICAgICAgfVxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIGNvbnZlcnREZXZpY2VSZWdpc3RyYXRpb25zVG9TdWJzY3JpcHRpb25WaWV3TW9kZWxzKFxuICAgIHBlbmRpbmdTdWJzY3JpcHRpb25zXG4gICk6IFN1YnNjcmlwdGlvblZpZXdNb2RlbFtdIHtcbiAgICBjb25zdCBjb252ZXJ0ZWRUb1ZpZXdNb2RlbCA9IHBlbmRpbmdTdWJzY3JpcHRpb25zXG4gICAgICAuZmlsdGVyKGRldmljZVJlcXVlc3QgPT4gZGV2aWNlUmVxdWVzdC50eXBlID09PSB0aGlzLk5FV19ERVZJQ0VfUkVRVUVTVF9UWVBFKVxuICAgICAgLm1hcChkZXZpY2VSZXF1ZXN0ID0+IHtcbiAgICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oe30sIGdldChkZXZpY2VSZXF1ZXN0LCAnY3VzdG9tUHJvcGVydGllcy5jOHlfQnJva2VyU291cmNlJyksIHtcbiAgICAgICAgICBzdGF0dXM6IHRoaXMubmV3RGV2aWNlUmVxdWVzdFN0YXR1c1ZpZXdNb2RlbEZhY3RvcnkuYnVpbGQoZGV2aWNlUmVxdWVzdC5zdGF0dXMpLFxuICAgICAgICAgIHR5cGU6IGRldmljZVJlcXVlc3QudHlwZSxcbiAgICAgICAgICBpZDogZGV2aWNlUmVxdWVzdC5pZFxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIHJldHVybiBjb252ZXJ0ZWRUb1ZpZXdNb2RlbDtcbiAgfVxuXG4gIHByaXZhdGUgZ2VuZXJhdGVEZXZpY2VSZXF1ZXN0U3RhdHVzRW51bShuZXdEZXZpY2VSZXF1ZXN0Vmlld01vZGVsRmFjdG9yeSkge1xuICAgIGNvbnN0IHJlc3VsdCA9IHt9O1xuICAgIGZvciAoY29uc3Qgc3RhdHVzIGluIERldmljZVJlZ2lzdHJhdGlvblN0YXR1cykge1xuICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHJlc3VsdCwgc3RhdHVzLCB7XG4gICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgIHdyaXRhYmxlOiBmYWxzZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiBmYWxzZSxcbiAgICAgICAgdmFsdWU6IG5ld0RldmljZVJlcXVlc3RWaWV3TW9kZWxGYWN0b3J5LmJ1aWxkKHN0YXR1cyBhcyBhbnkgYXMgRGV2aWNlUmVnaXN0cmF0aW9uU3RhdHVzKVxuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvLyBGdW5jdGlvbiBtYXBzIGRhdGEgaW4gc3VpdGFibGUgbWFubmVyIHRvIGhhdmUgaXQgZWFzaWVyIHRvIGRpc3BsYXkuIFVzZWQgaW4gc2VydmljZSBtYWlubHkgZm9yIGNvbXBhdGliaWxpdHlcbiAgcHJpdmF0ZSBhc3luYyBjb252ZXJ0VG9WaWV3TW9kZWwoXG4gICAgc3Vic2NyaXB0aW9uczogSU1hbmFnZWRPYmplY3RbXVxuICApOiBQcm9taXNlPFN1YnNjcmlwdGlvblZpZXdNb2RlbFtdPiB7XG4gICAgY29uc3Qgdmlld01vZGVsU3Vic2NyaXB0aW9ucyA9IHN1YnNjcmlwdGlvbnMubWFwKGFzeW5jIHN1YnNjcmlwdGlvbiA9PiB7XG4gICAgICBjb25zdCB7IGRhdGE6IHVzZXJEZXRhaWxzIH0gPSBhd2FpdCB0aGlzLnVzZXJTZXJ2aWNlLmRldGFpbChzdWJzY3JpcHRpb24ub3duZXIpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdXNlckVuYWJsZWQ6IHVzZXJEZXRhaWxzLmVuYWJsZWQsXG4gICAgICAgIHZpc2libGVVc2VyU3RhdHVzOiB0aGlzLmdldFZpc2libGVVc2VyU3RhdHVzVGV4dCh1c2VyRGV0YWlscyksIC8vVE9ETzpJSUFSIHNob3VsZCBiZSBleHRyYWN0ZWQgdG8gbmd4IHBpcGUgd2hlbiB0aGUgcmVzdCBvZiBkYXRhLWJyb2tlciBpcyBtaWdyYXRlZFxuICAgICAgICB1c2VySWQ6IHVzZXJEZXRhaWxzLmlkLFxuICAgICAgICBzdGF0dXM6IHRoaXMuZ2V0U3RhdHVzVmlld01vZGVsKHN1YnNjcmlwdGlvbi5jOHlfQnJva2VyU291cmNlLnN0YXR1cyksIC8vVE9ETzpJSUFSIHNob3VsZCBiZSBleHRyYWN0ZWQgdG8gbmd4IHBpcGUgd2hlbiB0aGUgcmVzdCBvZiBkYXRhLWJyb2tlciBpcyBtaWdyYXRlZFxuICAgICAgICBpZDogc3Vic2NyaXB0aW9uLmlkLFxuICAgICAgICBfYzh5X0Jyb2tlclNvdXJjZTogc3Vic2NyaXB0aW9uLmM4eV9Ccm9rZXJTb3VyY2VcbiAgICAgIH0gYXMgU3Vic2NyaXB0aW9uVmlld01vZGVsO1xuICAgIH0pO1xuICAgIHJldHVybiBQcm9taXNlLmFsbCh2aWV3TW9kZWxTdWJzY3JpcHRpb25zKTtcbiAgfVxuXG4gIC8vIFN0YXR1cyBkZWNvcmF0aW9uIChsZWdhY3kgY29tcGF0aWJpbGl0eSlcbiAgcHJpdmF0ZSBnZXRTdGF0dXNWaWV3TW9kZWwoc3RhdHVzOiBEYXRhQnJva2VyQ29ubmVjdG9yU3RhdHVzKTogU3Vic2NyaXB0aW9uU3RhdHVzVmlld01vZGVsIHtcbiAgICByZXR1cm4gdGhpcy5zdWJzY3JpcHRpb25TdGF0dXNWaWV3TW9kZWxGYWN0b3J5LmJ1aWxkKHN0YXR1cyk7XG4gIH1cbn1cbiJdfQ==