@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
305 lines • 48 kB
JavaScript
import { Injectable } from '@angular/core';
import { InventoryService, SmartGroupsService, SmartRulesService, UserService } from '@c8y/client';
import { AlertService, AppStateService, AssetTypesRealtimeService, DataGridService, Permissions, UserPreferencesService, gettext } from '@c8y/ngx-components';
import { AssetNodeService } from '@c8y/ngx-components/assets-navigator';
import { AlarmsDeviceGridColumn, ImeiDeviceGridColumn, ModelDeviceGridColumn, NameDeviceGridColumn, RegistrationDateDeviceGridColumn, SerialNumberDeviceGridColumn, SystemIdDeviceGridColumn } from '@c8y/ngx-components/device-grid';
import { TranslateService } from '@ngx-translate/core';
import { AssetTypeGridColumn } from '@c8y/ngx-components/data-grid-columns/asset-type';
import { firstValueFrom } from 'rxjs';
import * as i0 from "@angular/core";
import * as i1 from "@ngx-translate/core";
import * as i2 from "@c8y/client";
import * as i3 from "@c8y/ngx-components";
import * as i4 from "@c8y/ngx-components/assets-navigator";
export class SubAssetsService extends DataGridService {
constructor(translateService, inventoryService, appState, user, assetNodeService, smartGroupsService, smartRulesService, alertService, permissionsService, assetTypes, userPreferencesService) {
super(userPreferencesService);
this.translateService = translateService;
this.inventoryService = inventoryService;
this.appState = appState;
this.user = user;
this.assetNodeService = assetNodeService;
this.smartGroupsService = smartGroupsService;
this.smartRulesService = smartRulesService;
this.alertService = alertService;
this.permissionsService = permissionsService;
this.assetTypes = assetTypes;
this.userPreferencesService = userPreferencesService;
this.GRID_CONFIG_DEFAULT_STORAGE_KEY = 'sub-assets-grid-config';
this.IS_DEVICE_GROUP_FRAGMENT = 'c8y_IsDeviceGroup';
this.IS_DYNAMIC_GROUP_FRAGMENT = 'c8y_IsDynamicGroup';
}
async getCustomProperties(group) {
const assetType$ = this.assetTypes.getAssetTypeByName$(group.type);
const assetType = await firstValueFrom(assetType$);
if (assetType) {
const { data } = await this.inventoryService.childAdditionsList(assetType, {
pageSize: 2000,
query: "$filter=(has('c8y_IsAssetProperty'))"
});
return data;
}
return [];
}
getDefaultColumns(_filterable = true, _sortable = true) {
const defaultColumns = [
new AssetTypeGridColumn({ sortOrder: 'desc' }),
new NameDeviceGridColumn({ sortOrder: 'asc' }),
new ModelDeviceGridColumn(),
new SerialNumberDeviceGridColumn({ visible: false }),
new RegistrationDateDeviceGridColumn({ visible: false }),
new SystemIdDeviceGridColumn({ visible: false }),
new ImeiDeviceGridColumn({ visible: false }),
new AlarmsDeviceGridColumn()
];
return defaultColumns;
}
getDefaultPagination() {
return {
pageSize: 25,
currentPage: 1
};
}
getDefaultActionControls() {
return [];
}
async unassignAsset(asset, parentRef) {
const { id: assetId } = asset;
const { id: parentId } = parentRef;
if (this.isDevice(asset)) {
try {
await this.inventoryService.childAssetsRemove(assetId, parentId);
const alertMessage = this.translateService.instant(gettext('Device unassigned.'));
this.alertService.success(alertMessage);
}
catch (error) {
const alertMessage = this.translateService.instant(gettext('Could not unassign device.'));
this.alertService.danger(alertMessage, error);
}
await this.deactivateSmartrulesForAsset(asset, parentRef);
}
}
isDevice(asset) {
return (!asset.hasOwnProperty(this.IS_DEVICE_GROUP_FRAGMENT) &&
!asset.hasOwnProperty(this.IS_DYNAMIC_GROUP_FRAGMENT));
}
async deleteAsset(asset, parentRef, params = {}) {
const isGroup = asset.hasOwnProperty(this.IS_DEVICE_GROUP_FRAGMENT) ||
this.smartGroupsService.isSmartGroup(asset);
if (isGroup) {
await this.deleteGroup(asset, params);
}
else {
await this.deleteDevice(asset, params);
}
if (parentRef && !this.smartGroupsService.isSmartGroup(asset)) {
await this.deactivateSmartrulesForAsset(asset, parentRef);
}
}
shouldShowWithDeviceUserCheckbox(asset) {
const { owner, c8y_IsDevice: isRootDevice } = asset;
const hasDeviceUserAsOwner = asset.owner && this.isDeviceUser(owner);
return Boolean(isRootDevice && hasDeviceUserAsOwner);
}
getDefaultBulkActionControls() {
return [];
}
async getData(columns, pagination, parentReference, baseQuery = {}, text = null) {
const isRoot = !parentReference;
if (isRoot) {
const query = this.buildCombinedRootQueryFilter(columns, pagination, baseQuery);
return this.assetNodeService.getRootNodes({ ...pagination, ...(text && { text }), query });
}
const filters = {
...this.getAssetsFilters(columns, pagination, baseQuery, text),
withParents: false
};
if (this.assetNodeService.isGroup(parentReference)) {
return this.assetNodeService.getGroupItems(parentReference.id, filters);
}
if (this.assetNodeService.isDynamicGroup(parentReference)) {
return this.assetNodeService.getDynamicGroupItems(parentReference.c8y_DeviceQueryString, filters);
}
if (this.assetNodeService.isDevice(parentReference)) {
return this.assetNodeService.getDeviceChildren(parentReference.id, filters);
}
}
async getCount(columns, pagination, parentReference, baseQuery = {}, text = null) {
const defaultFilters = {
pageSize: 1,
withChildren: false
};
const filters = !parentReference
? {
query: this.buildCombinedRootQueryFilter(columns, pagination, baseQuery),
...defaultFilters
}
: {
...this.getAssetsFilters(columns, pagination, baseQuery, text),
...defaultFilters
};
return this.getAssetsStatistics(parentReference, filters);
}
getTotal(parentReference, baseQuery = {}) {
const queryFilter = this.assetNodeService.rootQueryFilter();
const query = !parentReference
? this.queriesUtil.addAndFilter(queryFilter, baseQuery)
: baseQuery;
const filters = {
query: this.queriesUtil.buildQuery(query),
withChildren: false,
withTotalPages: true,
pageSize: 1
};
return this.getAssetsStatistics(parentReference, filters);
}
async canEditGroup(group) {
return await this.permissionsService.canEdit([Permissions.ROLE_INVENTORY_ADMIN, Permissions.ROLE_MANAGED_OBJECT_ADMIN], group);
}
canCreateGroup() {
const currentUser = this.appState.currentUser.value;
const hasAdminRole = this.user.hasAnyRole(currentUser, [
Permissions.ROLE_INVENTORY_ADMIN,
Permissions.ROLE_INVENTORY_CREATE,
Permissions.ROLE_MANAGED_OBJECT_ADMIN,
Permissions.ROLE_MANAGED_OBJECT_CREATE
]);
return hasAdminRole;
}
async canAssignDevice(group) {
return await this.permissionsService.canEdit([Permissions.ROLE_INVENTORY_ADMIN, Permissions.ROLE_MANAGED_OBJECT_ADMIN], group);
}
canEditSmartGroup() {
const SMART_GROUPS_ROLES_EDIT = [
Permissions.ROLE_SMARTGROUP_UPDATE,
Permissions.ROLE_SMARTGROUP_ADMIN
];
return this.permissionsService.hasAnyRole(SMART_GROUPS_ROLES_EDIT);
}
canDeleteSmartGroup() {
const SMART_GROUPS_ROLES_DELETE = [
Permissions.ROLE_SMARTGROUP_ADMIN,
Permissions.ROLE_INVENTORY_ADMIN,
Permissions.ROLE_MANAGED_OBJECT_ADMIN
];
return this.permissionsService.hasAnyRole(SMART_GROUPS_ROLES_DELETE);
}
isSmartGroup(group) {
return this.smartGroupsService.isSmartGroup(group);
}
isUsingInventoryRoles() {
const currentUser = this.appState.currentUser.value;
const hasAnyInventoryRole = this.user.hasAnyRole(currentUser, [
Permissions.ROLE_INVENTORY_ADMIN,
Permissions.ROLE_INVENTORY_READ,
Permissions.ROLE_INVENTORY_CREATE,
Permissions.ROLE_MANAGED_OBJECT_ADMIN,
Permissions.ROLE_MANAGED_OBJECT_CREATE,
Permissions.ROLE_MANAGED_OBJECT_READ
]);
return !hasAnyInventoryRole;
}
async getAssetsStatistics(parentReference, filters) {
const isRoot = !parentReference;
if (isRoot) {
return (await this.assetNodeService.getRootNodes(filters)).paging.totalPages;
}
if (this.assetNodeService.isGroup(parentReference)) {
return (await this.assetNodeService.getGroupItems(parentReference.id, filters)).paging
.totalPages;
}
if (this.assetNodeService.isDynamicGroup(parentReference)) {
return (await this.assetNodeService.getDynamicGroupItems(parentReference.c8y_DeviceQueryString, filters)).paging.totalPages;
}
if (this.assetNodeService.isDevice(parentReference)) {
return (await this.assetNodeService.getDeviceChildren(parentReference.id, filters)).paging
.totalPages;
}
}
buildCombinedRootQueryFilter(columns, pagination, baseQuery = {}) {
const userQuery = this.getQueryObj(columns, pagination);
const rootQuery = this.assetNodeService.rootQueryFilter();
const orderedRootQuery = this.queriesUtil.addOrderbys(rootQuery, userQuery.__orderby, 'append');
const rootAndUserQuery = this.queriesUtil.addAndFilter(orderedRootQuery, userQuery.__filter);
const fullQuery = this.queriesUtil.addAndFilter(rootAndUserQuery, baseQuery);
return this.queriesUtil.buildQuery(fullQuery);
}
async deleteGroup(group, params = {}) {
const { cascade } = params;
try {
this.smartGroupsService.isSmartGroup(group)
? await this.smartGroupsService.delete(group, { cascade })
: await this.inventoryService.delete(group, { cascade });
const alertMessage = this.translateService.instant(gettext('"{{ name }}" deleted.'), {
name: group.name
});
this.alertService.success(alertMessage);
}
catch (error) {
const alertMessage = this.translateService.instant(gettext('Could not delete "{{ name }}".'), {
name: group.name
});
this.alertService.danger(alertMessage, error);
}
}
async deleteDevice(device, params = {}) {
const { cascade, withDeviceUser } = params;
try {
const { owner } = device;
const shouldRemoveOwner = withDeviceUser && owner && this.isDeviceUser(owner);
shouldRemoveOwner
? await this.deleteDeviceWithUser(device, cascade)
: await this.inventoryService.delete(device, { cascade });
const alertMessage = this.translateService.instant(gettext('Device deleted.'));
this.alertService.success(alertMessage);
}
catch (error) {
const alertMessage = this.translateService.instant(gettext('Could not delete device.'));
this.alertService.danger(alertMessage, error);
}
}
async deactivateSmartrulesForAsset(asset, parentRef) {
const { id: assetId } = asset;
const { id: parentId } = parentRef;
const rules = (await this.smartRulesService.listByContext(parentId)).data;
const upateSmartrulesPromises = rules.map(rule => this.smartRulesService.bulkDeactivateEnabledSources(rule, [assetId]));
try {
await Promise.all(upateSmartrulesPromises);
}
catch (error) {
const alertMessage = this.translateService.instant(gettext('Could not deactivate smart rules.'));
this.alertService.danger(alertMessage);
}
}
isDeviceUser(userId) {
return userId.match(/^device_/);
}
async deleteDeviceWithUser(device, cascade) {
const params = { cascade, withDeviceUser: true };
try {
return await this.inventoryService.delete(device, params);
}
catch (error) {
return await this.inventoryService.delete(device, { cascade });
}
}
getAssetsFilters(columns, pagination, baseQuery, text) {
const query = this.queriesUtil.addAndFilter(this.getQueryObj(columns), baseQuery);
return {
...(text && { text }),
query: this.queriesUtil.buildQuery(query),
pageSize: pagination.pageSize || this.DEFAULT_PAGE_SIZE,
currentPage: pagination.currentPage,
withTotalPages: true
};
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SubAssetsService, deps: [{ token: i1.TranslateService }, { token: i2.InventoryService }, { token: i3.AppStateService }, { token: i2.UserService }, { token: i4.AssetNodeService }, { token: i2.SmartGroupsService }, { token: i2.SmartRulesService }, { token: i3.AlertService }, { token: i3.Permissions }, { token: i3.AssetTypesRealtimeService }, { token: i3.UserPreferencesService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SubAssetsService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SubAssetsService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: i1.TranslateService }, { type: i2.InventoryService }, { type: i3.AppStateService }, { type: i2.UserService }, { type: i4.AssetNodeService }, { type: i2.SmartGroupsService }, { type: i2.SmartRulesService }, { type: i3.AlertService }, { type: i3.Permissions }, { type: i3.AssetTypesRealtimeService }, { type: i3.UserPreferencesService }] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3ViLWFzc2V0cy5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3ViLWFzc2V0cy9zdWItYXNzZXRzLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzQyxPQUFPLEVBR0wsZ0JBQWdCLEVBRWhCLGtCQUFrQixFQUNsQixpQkFBaUIsRUFDakIsV0FBVyxFQUNaLE1BQU0sYUFBYSxDQUFDO0FBQ3JCLE9BQU8sRUFFTCxZQUFZLEVBQ1osZUFBZSxFQUNmLHlCQUF5QixFQUd6QixlQUFlLEVBRWYsV0FBVyxFQUNYLHNCQUFzQixFQUN0QixPQUFPLEVBQ1IsTUFBTSxxQkFBcUIsQ0FBQztBQUM3QixPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxzQ0FBc0MsQ0FBQztBQUN4RSxPQUFPLEVBQ0wsc0JBQXNCLEVBQ3RCLG9CQUFvQixFQUNwQixxQkFBcUIsRUFDckIsb0JBQW9CLEVBQ3BCLGdDQUFnQyxFQUNoQyw0QkFBNEIsRUFDNUIsd0JBQXdCLEVBQ3pCLE1BQU0saUNBQWlDLENBQUM7QUFDekMsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDdkQsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sa0RBQWtELENBQUM7QUFDdkYsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLE1BQU0sQ0FBQzs7Ozs7O0FBS3RDLE1BQU0sT0FBTyxnQkFBaUIsU0FBUSxlQUFlO0lBTW5ELFlBQ1ksZ0JBQWtDLEVBQ2xDLGdCQUFrQyxFQUNsQyxRQUF5QixFQUN6QixJQUFpQixFQUNqQixnQkFBa0MsRUFDbEMsa0JBQXNDLEVBQ3RDLGlCQUFvQyxFQUNwQyxZQUEwQixFQUMxQixrQkFBK0IsRUFDL0IsVUFBcUMsRUFDckMsc0JBQThDO1FBRXhELEtBQUssQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO1FBWnBCLHFCQUFnQixHQUFo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QUFNLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQzVELENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsT0FBTyxNQUFNLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztRQUNqRSxDQUFDO0lBQ0gsQ0FBQztJQUVPLGdCQUFnQixDQUFDLE9BQWlCLEVBQUUsVUFBc0IsRUFBRSxTQUFTLEVBQUUsSUFBYTtRQUMxRixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBQ2xGLE9BQU87WUFDTCxHQUFHLENBQUMsSUFBSSxJQUFJLEVBQUUsSUFBSSxFQUFFLENBQUM7WUFDckIsS0FBSyxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQztZQUN6QyxRQUFRLEVBQUUsVUFBVSxDQUFDLFFBQVEsSUFBSSxJQUFJLENBQUMsaUJBQWlCO1lBQ3ZELFdBQVcsRUFBRSxVQUFVLENBQUMsV0FBVztZQUNuQyxjQUFjLEVBQUUsSUFBSTtTQUNyQixDQUFDO0lBQ0osQ0FBQzsrR0FsV1UsZ0JBQWdCO21IQUFoQixnQkFBZ0IsY0FGZixNQUFNOzs0RkFFUCxnQkFBZ0I7a0JBSDVCLFVBQVU7bUJBQUM7b0JBQ1YsVUFBVSxFQUFFLE1BQU07aUJBQ25CIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgSU1hbmFnZWRPYmplY3QsXG4gIElSdWxlLFxuICBJbnZlbnRvcnlTZXJ2aWNlLFxuICBRdWVyaWVzVXRpbCxcbiAgU21hcnRHcm91cHNTZXJ2aWNlLFxuICBTbWFydFJ1bGVzU2VydmljZSxcbiAgVXNlclNlcnZpY2Vcbn0gZnJvbSAnQGM4eS9jbGllbnQnO1xuaW1wb3J0IHtcbiAgQWN0aW9uQ29udHJvbCxcbiAgQWxlcnRTZXJ2aWNlLFxuICBBcHBTdGF0ZVNlcnZpY2UsXG4gIEFzc2V0VHlwZXNSZWFsdGltZVNlcnZpY2UsXG4gIEJ1bGtBY3Rpb25Db250cm9sLFxuICBDb2x1bW4sXG4gIERhdGFHcmlkU2VydmljZSxcbiAgUGFnaW5hdGlvbixcbiAgUGVybWlzc2lvbnMsXG4gIFVzZXJQcmVmZXJlbmNlc1NlcnZpY2UsXG4gIGdldHRleHRcbn0gZnJvbSAnQGM4eS9uZ3gtY29tcG9uZW50cyc7XG5pbXBvcnQgeyBBc3NldE5vZGVTZXJ2aWNlIH0gZnJvbSAnQGM4eS9uZ3gtY29tcG9uZW50cy9hc3NldHMtbmF2aWdhdG9yJztcbmltcG9ydCB7XG4gIEFsYXJtc0RldmljZUdyaWRDb2x1bW4sXG4gIEltZWlEZXZpY2VHcmlkQ29sdW1uLFxuICBNb2RlbERldmljZUdyaWRDb2x1bW4sXG4gIE5hbWVEZXZpY2VHcmlkQ29sdW1uLFxuICBSZWdpc3RyYXRpb25EYXRlRGV2aWNlR3JpZENvbHVtbixcbiAgU2VyaWFsTnVtYmVyRGV2aWNlR3JpZENvbHVtbixcbiAgU3lzdGVtSWREZXZpY2VHcmlkQ29sdW1uXG59IGZyb20gJ0BjOHkvbmd4LWNvbXBvbmVudHMvZGV2aWNlLWdyaWQnO1xuaW1wb3J0IHsgVHJhbnNsYXRlU2VydmljZSB9IGZyb20gJ0BuZ3gtdHJhbnNsYXRlL2NvcmUnO1xuaW1wb3J0IHsgQXNzZXRUeXBlR3JpZENvbHVtbiB9IGZyb20gJ0BjOHkvbmd4LWNvbXBvbmVudHMvZGF0YS1ncmlkLWNvbHVtbnMvYXNzZXQtdHlwZSc7XG5pbXBvcnQgeyBmaXJzdFZhbHVlRnJvbSB9IGZyb20gJ3J4anMnO1xuXG5ASW5qZWN0YWJsZSh7XG4gIHByb3ZpZGVkSW46ICdyb290J1xufSlcbmV4cG9ydCBjbGFzcyBTdWJBc3NldHNTZXJ2aWNlIGV4dGVuZHMgRGF0YUdyaWRTZXJ2aWNlIHtcbiAgcXVlcmllc1V0aWw6IFF1ZXJpZXNVdGlsO1xuICBwcm90ZWN0ZWQgR1JJRF9DT05GSUdfREVGQVVMVF9TVE9SQUdFX0tFWSA9ICdzdWItYXNzZXRzLWdyaWQtY29uZmlnJztcbiAgcHJpdmF0ZSBJU19ERVZJQ0VfR1JPVVBfRlJBR01FTlQgPSAnYzh5X0lzRGV2aWNlR3JvdXAnO1xuICBwcml2YXRlIElTX0RZTkFNSUNfR1JPVVBfRlJBR01FTlQgPSAnYzh5X0lzRHluYW1pY0dyb3VwJztcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcm90ZWN0ZWQgdHJhbnNsYXRlU2VydmljZTogVHJhbnNsYXRlU2VydmljZSxcbiAgICBwcm90ZWN0ZWQgaW52ZW50b3J5U2VydmljZTogSW52ZW50b3J5U2VydmljZSxcbiAgICBwcm90ZWN0ZWQgYXBwU3RhdGU6IEFwcFN0YXRlU2VydmljZSxcbiAgICBwcm90ZWN0ZWQgdXNlcjogVXNlclNlcnZpY2UsXG4gICAgcHJvdGVjdGVkIGFzc2V0Tm9kZVNlcnZpY2U6IEFzc2V0Tm9kZVNlcnZpY2UsXG4gICAgcHJvdGVjdGVkIHNtYXJ0R3JvdXBzU2VydmljZTogU21hcnRHcm91cHNTZXJ2aWNlLFxuICAgIHByb3RlY3RlZCBzbWFydFJ1bGVzU2VydmljZTogU21hcnRSdWxlc1NlcnZpY2UsXG4gICAgcHJvdGVjdGVkIGFsZXJ0U2VydmljZTogQWxlcnRTZXJ2aWNlLFxuICAgIHByb3RlY3RlZCBwZXJtaXNzaW9uc1NlcnZpY2U6IFBlcm1pc3Npb25zLFxuICAgIHByb3RlY3RlZCBhc3NldFR5cGVzOiBBc3NldFR5cGVzUmVhbHRpbWVTZXJ2aWNlLFxuICAgIHByb3RlY3RlZCB1c2VyUHJlZmVyZW5jZXNTZXJ2aWNlOiBVc2VyUHJlZmVyZW5jZXNTZXJ2aWNlXG4gICkge1xuICAgIHN1cGVyKHVzZXJQcmVmZXJlbmNlc1NlcnZpY2UpO1xuICB9XG5cbiAgYXN5bmMgZ2V0Q3VzdG9tUHJvcGVydGllcyhncm91cDogSU1hbmFnZWRPYmplY3QpOiBQcm9taXNlPElNYW5hZ2VkT2JqZWN0W10+IHtcbiAgICBjb25zdCBhc3NldFR5cGUkID0gdGhpcy5hc3NldFR5cGVzLmdldEFzc2V0VHlwZUJ5TmFtZSQoZ3JvdXAudHlwZSk7XG4gICAgY29uc3QgYXNzZXRUeXBlID0gYXdhaXQgZmlyc3RWYWx1ZUZyb20oYXNzZXRUeXBlJCk7XG4gICAgaWYgKGFzc2V0VHlwZSkge1xuICAgICAgY29uc3QgeyBkYXRhIH0gPSBhd2FpdCB0aGlzLmludmVudG9yeVNlcnZpY2UuY2hpbGRBZGRpdGlvbnNMaXN0KGFzc2V0VHlwZSwge1xuICAgICAgICBwYWdlU2l6ZTogMjAwMCxcbiAgICAgICAgcXVlcnk6IFwiJGZpbHRlcj0oaGFzKCdjOHlfSXNBc3NldFByb3BlcnR5JykpXCJcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfVxuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIGdldERlZmF1bHRDb2x1bW5zKF9maWx0ZXJhYmxlID0gdHJ1ZSwgX3NvcnRhYmxlID0gdHJ1ZSk6IENvbHVtbltdIHtcbiAgICBjb25zdCBkZWZhdWx0Q29sdW1ucyA9IFtcbiAgICAgIG5ldyBBc3NldFR5cGVHcmlkQ29sdW1uKHsgc29ydE9yZGVyOiAnZGVzYycgfSksXG4gICAgICBuZXcgTmFtZURldmljZUdyaWRDb2x1bW4oeyBzb3J0T3JkZXI6ICdhc2MnIH0pLFxuICAgICAgbmV3IE1vZGVsRGV2aWNlR3JpZENvbHVtbigpLFxuICAgICAgbmV3IFNlcmlhbE51bWJlckRldmljZUdyaWRDb2x1bW4oeyB2aXNpYmxlOiBmYWxzZSB9KSxcbiAgICAgIG5ldyBSZWdpc3RyYXRpb25EYXRlRGV2aWNlR3JpZENvbHVtbih7IHZpc2libGU6IGZhbHNlIH0pLFxuICAgICAgbmV3IFN5c3RlbUlkRGV2aWNlR3JpZENvbHVtbih7IHZpc2libGU6IGZhbHNlIH0pLFxuICAgICAgbmV3IEltZWlEZXZpY2VHcmlkQ29sdW1uKHsgdmlzaWJsZTogZmFsc2UgfSksXG4gICAgICBuZXcgQWxhcm1zRGV2aWNlR3JpZENvbHVtbigpXG4gICAgXTtcbiAgICByZXR1cm4gZGVmYXVsdENvbHVtbnM7XG4gIH1cblxuICBnZXREZWZhdWx0UGFnaW5hdGlvbigpOiBQYWdpbmF0aW9uIHtcbiAgICByZXR1cm4ge1xuICAgICAgcGFnZVNpemU6IDI1LFxuICAgICAgY3VycmVudFBhZ2U6IDFcbiAgICB9O1xuICB9XG5cbiAgZ2V0RGVmYXVsdEFjdGlvbkNvbnRyb2xzKCk6IEFjdGlvbkNvbnRyb2xbXSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgYXN5bmMgdW5hc3NpZ25Bc3NldChhc3NldDogSU1hbmFnZWRPYmplY3QsIHBhcmVudFJlZjogSU1hbmFnZWRPYmplY3QpIHtcbiAgICBjb25zdCB7IGlkOiBhc3NldElkIH0gPSBhc3NldDtcbiAgICBjb25zdCB7IGlkOiBwYXJlbnRJZCB9ID0gcGFyZW50UmVmO1xuXG4gICAgaWYgKHRoaXMuaXNEZXZpY2UoYXNzZXQpKSB7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCB0aGlzLmludmVudG9yeVNlcnZpY2UuY2hpbGRBc3NldHNSZW1vdmUoYXNzZXRJZCwgcGFyZW50SWQpO1xuICAgICAgICBjb25zdCBhbGVydE1lc3NhZ2UgPSB0aGlzLnRyYW5zbGF0ZVNlcnZpY2UuaW5zdGFudChnZXR0ZXh0KCdEZXZpY2UgdW5hc3NpZ25lZC4nKSk7XG4gICAgICAgIHRoaXMuYWxlcnRTZXJ2aWNlLnN1Y2Nlc3MoYWxlcnRNZXNzYWdlKTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGNvbnN0IGFsZXJ0TWVzc2FnZSA9IHRoaXMudHJhbnNsYXRlU2VydmljZS5pbnN0YW50KGdldHRleHQoJ0NvdWxkIG5vdCB1bmFzc2lnbiBkZXZpY2UuJykpO1xuICAgICAgICB0aGlzLmFsZXJ0U2VydmljZS5kYW5nZXIoYWxlcnRNZXNzYWdlLCBlcnJvcik7XG4gICAgICB9XG4gICAgICBhd2FpdCB0aGlzLmRlYWN0aXZhdGVTbWFydHJ1bGVzRm9yQXNzZXQoYXNzZXQsIHBhcmVudFJlZik7XG4gICAgfVxuICB9XG5cbiAgaXNEZXZpY2UoYXNzZXQ6IElNYW5hZ2VkT2JqZWN0KTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIChcbiAgICAgICFhc3NldC5oYXNPd25Qcm9wZXJ0eSh0aGlzLklTX0RFVklDRV9HUk9VUF9GUkFHTUVOVCkgJiZcbiAgICAgICFhc3NldC5oYXNPd25Qcm9wZXJ0eSh0aGlzLklTX0RZTkFNSUNfR1JPVVBfRlJBR01FTlQpXG4gICAgKTtcbiAgfVxuXG4gIGFzeW5jIGRlbGV0ZUFzc2V0KGFzc2V0OiBJTWFuYWdlZE9iamVjdCwgcGFyZW50UmVmOiBJTWFuYWdlZE9iamVjdCwgcGFyYW1zID0ge30pIHtcbiAgICBjb25zdCBpc0dyb3VwID1cbiAgICAgIGFzc2V0Lmhhc093blByb3BlcnR5KHRoaXMuSVNfREVWSUNFX0dST1VQX0ZSQUdNRU5UKSB8fFxuICAgICAgdGhpcy5zbWFydEdyb3Vwc1NlcnZpY2UuaXNTbWFydEdyb3VwKGFzc2V0KTtcblxuICAgIGlmIChpc0dyb3VwKSB7XG4gICAgICBhd2FpdCB0aGlzLmRlbGV0ZUdyb3VwKGFzc2V0LCBwYXJhbXMpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhd2FpdCB0aGlzLmRlbGV0ZURldmljZShhc3NldCwgcGFyYW1zKTtcbiAgICB9XG5cbiAgICBpZiAocGFyZW50UmVmICYmICF0aGlzLnNtYXJ0R3JvdXBzU2VydmljZS5pc1NtYXJ0R3JvdXAoYXNzZXQpKSB7XG4gICAgICBhd2FpdCB0aGlzLmRlYWN0aXZhdGVTbWFydHJ1bGVzRm9yQXNzZXQoYXNzZXQsIHBhcmVudFJlZik7XG4gICAgfVxuICB9XG5cbiAgc2hvdWxkU2hvd1dpdGhEZXZpY2VVc2VyQ2hlY2tib3goYXNzZXQ6IElNYW5hZ2VkT2JqZWN0KTogYm9vbGVhbiB7XG4gICAgY29uc3QgeyBvd25lciwgYzh5X0lzRGV2aWNlOiBpc1Jvb3REZXZpY2UgfSA9IGFzc2V0O1xuICAgIGNvbnN0IGhhc0RldmljZVVzZXJBc093bmVyID0gYXNzZXQub3duZXIgJiYgdGhpcy5pc0RldmljZVVzZXIob3duZXIpO1xuXG4gICAgcmV0dXJuIEJvb2xlYW4oaXNSb290RGV2aWNlICYmIGhhc0RldmljZVVzZXJBc093bmVyKTtcbiAgfVxuXG4gIGdldERlZmF1bHRCdWxrQWN0aW9uQ29udHJvbHMoKTogQnVsa0FjdGlvbkNvbnRyb2xbXSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgYXN5bmMgZ2V0RGF0YShcbiAgICBjb2x1bW5zOiBDb2x1bW5bXSxcbiAgICBwYWdpbmF0aW9uOiBQYWdpbmF0aW9uLFxuICAgIHBhcmVudFJlZmVyZW5jZTogSU1hbmFnZWRPYmplY3QsXG4gICAgYmFzZVF1ZXJ5OiBhbnkgPSB7fSxcbiAgICB0ZXh0OiBzdHJpbmcgPSBudWxsXG4gICkge1xuICAgIGNvbnN0IGlzUm9vdCA9ICFwYXJlbnRSZWZlcmVuY2U7XG4gICAgaWYgKGlzUm9vdCkge1xuICAgICAgY29uc3QgcXVlcnkgPSB0aGlzLmJ1aWxkQ29tYmluZWRSb290UXVlcnlGaWx0ZXIoY29sdW1ucywgcGFnaW5hdGlvbiwgYmFzZVF1ZXJ5KTtcbiAgICAgIHJldHVybiB0aGlzLmFzc2V0Tm9kZVNlcnZpY2UuZ2V0Um9vdE5vZGVzKHsgLi4ucGFnaW5hdGlvbiwgLi4uKHRleHQgJiYgeyB0ZXh0IH0pLCBxdWVyeSB9KTtcbiAgICB9XG4gICAgY29uc3QgZmlsdGVycyA9IHtcbiAgICAgIC4uLnRoaXMuZ2V0QXNzZXRzRmlsdGVycyhjb2x1bW5zLCBwYWdpbmF0aW9uLCBiYXNlUXVlcnksIHRleHQpLFxuICAgICAgd2l0aFBhcmVudHM6IGZhbHNlXG4gICAgfTtcbiAgICBpZiAodGhpcy5hc3NldE5vZGVTZXJ2aWNlLmlzR3JvdXAocGFyZW50UmVmZXJlbmNlKSkge1xuICAgICAgcmV0dXJuIHRoaXMuYXNzZXROb2RlU2VydmljZS5nZXRHcm91cEl0ZW1zKHBhcmVudFJlZmVyZW5jZS5pZCwgZmlsdGVycyk7XG4gICAgfVxuICAgIGlmICh0aGlzLmFzc2V0Tm9kZVNlcnZpY2UuaXNEeW5hbWljR3JvdXAocGFyZW50UmVmZXJlbmNlKSkge1xuICAgICAgcmV0dXJuIHRoaXMuYXNzZXROb2RlU2VydmljZS5nZXREeW5hbWljR3JvdXBJdGVtcyhcbiAgICAgICAgcGFyZW50UmVmZXJlbmNlLmM4eV9EZXZpY2VRdWVyeVN0cmluZyxcbiAgICAgICAgZmlsdGVyc1xuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuYXNzZXROb2RlU2VydmljZS5pc0RldmljZShwYXJlbnRSZWZlcmVuY2UpKSB7XG4gICAgICByZXR1cm4gdGhpcy5hc3NldE5vZGVTZXJ2aWNlLmdldERldmljZUNoaWxkcmVuKHBhcmVudFJlZmVyZW5jZS5pZCwgZmlsdGVycyk7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgZ2V0Q291bnQoXG4gICAgY29sdW1uczogQ29sdW1uW10sXG4gICAgcGFnaW5hdGlvbjogUGFnaW5hdGlvbixcbiAgICBwYXJlbnRSZWZlcmVuY2U6IElNYW5hZ2VkT2JqZWN0LFxuICAgIGJhc2VRdWVyeTogYW55ID0ge30sXG4gICAgdGV4dDogc3RyaW5nID0gbnVsbFxuICApOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGNvbnN0IGRlZmF1bHRGaWx0ZXJzID0ge1xuICAgICAgcGFnZVNpemU6IDEsXG4gICAgICB3aXRoQ2hpbGRyZW46IGZhbHNlXG4gICAgfTtcbiAgICBjb25zdCBmaWx0ZXJzID0gIXBhcmVudFJlZmVyZW5jZVxuICAgICAgPyB7XG4gICAgICAgICAgcXVlcnk6IHRoaXMuYnVpbGRDb21iaW5lZFJvb3RRdWVyeUZpbHRlcihjb2x1bW5zLCBwYWdpbmF0aW9uLCBiYXNlUXVlcnkpLFxuICAgICAgICAgIC4uLmRlZmF1bHRGaWx0ZXJzXG4gICAgICAgIH1cbiAgICAgIDoge1xuICAgICAgICAgIC4uLnRoaXMuZ2V0QXNzZXRzRmlsdGVycyhjb2x1bW5zLCBwYWdpbmF0aW9uLCBiYXNlUXVlcnksIHRleHQpLFxuICAgICAgICAgIC4uLmRlZmF1bHRGaWx0ZXJzXG4gICAgICAgIH07XG4gICAgcmV0dXJuIHRoaXMuZ2V0QXNzZXRzU3RhdGlzdGljcyhwYXJlbnRSZWZlcmVuY2UsIGZpbHRlcnMpO1xuICB9XG5cbiAgZ2V0VG90YWwocGFyZW50UmVmZXJlbmNlOiBJTWFuYWdlZE9iamVjdCwgYmFzZVF1ZXJ5OiBhbnkgPSB7fSk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgY29uc3QgcXVlcnlGaWx0ZXIgPSB0aGlzLmFzc2V0Tm9kZVNlcnZpY2Uucm9vdFF1ZXJ5RmlsdGVyKCk7XG4gICAgY29uc3QgcXVlcnkgPSAhcGFyZW50UmVmZXJlbmNlXG4gICAgICA/IHRoaXMucXVlcmllc1V0aWwuYWRkQW5kRmlsdGVyKHF1ZXJ5RmlsdGVyLCBiYXNlUXVlcnkpXG4gICAgICA6IGJhc2VRdWVyeTtcbiAgICBjb25zdCBmaWx0ZXJzID0ge1xuICAgICAgcXVlcnk6IHRoaXMucXVlcmllc1V0aWwuYnVpbGRRdWVyeShxdWVyeSksXG4gICAgICB3aXRoQ2hpbGRyZW46IGZhbHNlLFxuICAgICAgd2l0aFRvdGFsUGFnZXM6IHRydWUsXG4gICAgICBwYWdlU2l6ZTogMVxuICAgIH07XG4gICAgcmV0dXJuIHRoaXMuZ2V0QXNzZXRzU3RhdGlzdGljcyhwYXJlbnRSZWZlcmVuY2UsIGZpbHRlcnMpO1xuICB9XG5cbiAgYXN5bmMgY2FuRWRpdEdyb3VwKGdyb3VwOiBJTWFuYWdlZE9iamVjdCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIHJldHVybiBhd2FpdCB0aGlzLnBlcm1pc3Npb25zU2VydmljZS5jYW5FZGl0KFxuICAgICAgW1Blcm1pc3Npb25zLlJPTEVfSU5WRU5UT1JZX0FETUlOLCBQZXJtaXNzaW9ucy5ST0xFX01BTkFHRURfT0JKRUNUX0FETUlOXSxcbiAgICAgIGdyb3VwXG4gICAgKTtcbiAgfVxuXG4gIGNhbkNyZWF0ZUdyb3VwKCk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IGN1cnJlbnRVc2VyID0gdGhpcy5hcHBTdGF0ZS5jdXJyZW50VXNlci52YWx1ZTtcbiAgICBjb25zdCBoYXNBZG1pblJvbGUgPSB0aGlzLnVzZXIuaGFzQW55Um9sZShjdXJyZW50VXNlciwgW1xuICAgICAgUGVybWlzc2lvbnMuUk9MRV9JTlZFTlRPUllfQURNSU4sXG4gICAgICBQZXJtaXNzaW9ucy5ST0xFX0lOVkVOVE9SWV9DUkVBVEUsXG4gICAgICBQZXJtaXNzaW9ucy5ST0xFX01BTkFHRURfT0JKRUNUX0FETUlOLFxuICAgICAgUGVybWlzc2lvbnMuUk9MRV9NQU5BR0VEX09CSkVDVF9DUkVBVEVcbiAgICBdKTtcbiAgICByZXR1cm4gaGFzQWRtaW5Sb2xlO1xuICB9XG5cbiAgYXN5bmMgY2FuQXNzaWduRGV2aWNlKGdyb3VwOiBJTWFuYWdlZE9iamVjdCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIHJldHVybiBhd2FpdCB0aGlzLnBlcm1pc3Npb25zU2VydmljZS5jYW5FZGl0KFxuICAgICAgW1Blcm1pc3Npb25zLlJPTEVfSU5WRU5UT1JZX0FETUlOLCBQZXJtaXNzaW9ucy5ST0xFX01BTkFHRURfT0JKRUNUX0FETUlOXSxcbiAgICAgIGdyb3VwXG4gICAgKTtcbiAgfVxuXG4gIGNhbkVkaXRTbWFydEdyb3VwKCk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IFNNQVJUX0dST1VQU19ST0xFU19FRElUID0gW1xuICAgICAgUGVybWlzc2lvbnMuUk9MRV9TTUFSVEdST1VQX1VQREFURSxcbiAgICAgIFBlcm1pc3Npb25zLlJPTEVfU01BUlRHUk9VUF9BRE1JTlxuICAgIF07XG4gICAgcmV0dXJuIHRoaXMucGVybWlzc2lvbnNTZXJ2aWNlLmhhc0FueVJvbGUoU01BUlRfR1JPVVBTX1JPTEVTX0VESVQpO1xuICB9XG5cbiAgY2FuRGVsZXRlU21hcnRHcm91cCgpOiBib29sZWFuIHtcbiAgICBjb25zdCBTTUFSVF9HUk9VUFNfUk9MRVNfREVMRVRFID0gW1xuICAgICAgUGVybWlzc2lvbnMuUk9MRV9TTUFSVEdST1VQX0FETUlOLFxuICAgICAgUGVybWlzc2lvbnMuUk9MRV9JTlZFTlRPUllfQURNSU4sXG4gICAgICBQZXJtaXNzaW9ucy5ST0xFX01BTkFHRURfT0JKRUNUX0FETUlOXG4gICAgXTtcbiAgICByZXR1cm4gdGhpcy5wZXJtaXNzaW9uc1NlcnZpY2UuaGFzQW55Um9sZShTTUFSVF9HUk9VUFNfUk9MRVNfREVMRVRFKTtcbiAgfVxuXG4gIGlzU21hcnRHcm91cChncm91cDogSU1hbmFnZWRPYmplY3QpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5zbWFydEdyb3Vwc1NlcnZpY2UuaXNTbWFydEdyb3VwKGdyb3VwKTtcbiAgfVxuXG4gIGlzVXNpbmdJbnZlbnRvcnlSb2xlcygpIHtcbiAgICBjb25zdCBjdXJyZW50VXNlciA9IHRoaXMuYXBwU3RhdGUuY3VycmVudFVzZXIudmFsdWU7XG4gICAgY29uc3QgaGFzQW55SW52ZW50b3J5Um9sZSA9IHRoaXMudXNlci5oYXNBbnlSb2xlKGN1cnJlbnRVc2VyLCBbXG4gICAgICBQZXJtaXNzaW9ucy5ST0xFX0lOVkVOVE9SWV9BRE1JTixcbiAgICAgIFBlcm1pc3Npb25zLlJPTEVfSU5WRU5UT1JZX1JFQUQsXG4gICAgICBQZXJtaXNzaW9ucy5ST0xFX0lOVkVOVE9SWV9DUkVBVEUsXG4gICAgICBQZXJtaXNzaW9ucy5ST0xFX01BTkFHRURfT0JKRUNUX0FETUlOLFxuICAgICAgUGVybWlzc2lvbnMuUk9MRV9NQU5BR0VEX09CSkVDVF9DUkVBVEUsXG4gICAgICBQZXJtaXNzaW9ucy5ST0xFX01BTkFHRURfT0JKRUNUX1JFQURcbiAgICBdKTtcbiAgICByZXR1cm4gIWhhc0FueUludmVudG9yeVJvbGU7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgZ2V0QXNzZXRzU3RhdGlzdGljcyhcbiAgICBwYXJlbnRSZWZlcmVuY2U6IElNYW5hZ2VkT2JqZWN0LFxuICAgIGZpbHRlcnM6IG9iamVjdFxuICApOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGNvbnN0IGlzUm9vdCA9ICFwYXJlbnRSZWZlcmVuY2U7XG4gICAgaWYgKGlzUm9vdCkge1xuICAgICAgcmV0dXJuIChhd2FpdCB0aGlzLmFzc2V0Tm9kZVNlcnZpY2UuZ2V0Um9vdE5vZGVzKGZpbHRlcnMpKS5wYWdpbmcudG90YWxQYWdlcztcbiAgICB9XG4gICAgaWYgKHRoaXMuYXNzZXROb2RlU2VydmljZS5pc0dyb3VwKHBhcmVudFJlZmVyZW5jZSkpIHtcbiAgICAgIHJldHVybiAoYXdhaXQgdGhpcy5hc3NldE5vZGVTZXJ2aWNlLmdldEdyb3VwSXRlbXMocGFyZW50UmVmZXJlbmNlLmlkLCBmaWx0ZXJzKSkucGFnaW5nXG4gICAgICAgIC50b3RhbFBhZ2VzO1xuICAgIH1cbiAgICBpZiAodGhpcy5hc3NldE5vZGVTZXJ2aWNlLmlzRHluYW1pY0dyb3VwKHBhcmVudFJlZmVyZW5jZSkpIHtcbiAgICAgIHJldHVybiAoXG4gICAgICAgIGF3YWl0IHRoaXMuYXNzZXROb2RlU2VydmljZS5nZXREeW5hbWljR3JvdXBJdGVtcyhcbiAgICAgICAgICBwYXJlbnRSZWZlcmVuY2UuYzh5X0RldmljZVF1ZXJ5U3RyaW5nLFxuICAgICAgICAgIGZpbHRlcnNcbiAgICAgICAgKVxuICAgICAgKS5wYWdpbmcudG90YWxQYWdlcztcbiAgICB9XG4gICAgaWYgKHRoaXMuYXNzZXROb2RlU2VydmljZS5pc0RldmljZShwYXJlbnRSZWZlcmVuY2UpKSB7XG4gICAgICByZXR1cm4gKGF3YWl0IHRoaXMuYXNzZXROb2RlU2VydmljZS5nZXREZXZpY2VDaGlsZHJlbihwYXJlbnRSZWZlcmVuY2UuaWQsIGZpbHRlcnMpKS5wYWdpbmdcbiAgICAgICAgLnRvdGFsUGFnZXM7XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIGJ1aWxkQ29tYmluZWRSb290UXVlcnlGaWx0ZXIoY29sdW1ucywgcGFnaW5hdGlvbiwgYmFzZVF1ZXJ5ID0ge30pIHtcbiAgICBjb25zdCB1c2VyUXVlcnkgPSB0aGlzLmdldFF1ZXJ5T2JqKGNvbHVtbnMsIHBhZ2luYXRpb24pO1xuICAgIGNvbnN0IHJvb3RRdWVyeSA9IHRoaXMuYXNzZXROb2RlU2VydmljZS5yb290UXVlcnlGaWx0ZXIoKTtcbiAgICBjb25zdCBvcmRlcmVkUm9vdFF1ZXJ5ID0gdGhpcy5xdWVyaWVzVXRpbC5hZGRPcmRlcmJ5cyhyb290UXVlcnksIHVzZXJRdWVyeS5fX29yZGVyYnksICdhcHBlbmQnKTtcbiAgICBjb25zdCByb290QW5kVXNlclF1ZXJ5ID0gdGhpcy5xdWVyaWVzVXRpbC5hZGRBbmRGaWx0ZXIob3JkZXJlZFJvb3RRdWVyeSwgdXNlclF1ZXJ5Ll9fZmlsdGVyKTtcbiAgICBjb25zdCBmdWxsUXVlcnkgPSB0aGlzLnF1ZXJpZXNVdGlsLmFkZEFuZEZpbHRlcihyb290QW5kVXNlclF1ZXJ5LCBiYXNlUXVlcnkpO1xuICAgIHJldHVybiB0aGlzLnF1ZXJpZXNVdGlsLmJ1aWxkUXVlcnkoZnVsbFF1ZXJ5KTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZGVsZXRlR3JvdXAoZ3JvdXA6IElNYW5hZ2VkT2JqZWN0LCBwYXJhbXM6IGFueSA9IHt9KSB7XG4gICAgY29uc3QgeyBjYXNjYWRlIH0gPSBwYXJhbXM7XG5cbiAgICB0cnkge1xuICAgICAgdGhpcy5zbWFydEdyb3Vwc1NlcnZpY2UuaXNTbWFydEdyb3VwKGdyb3VwKVxuICAgICAgICA/IGF3YWl0IHRoaXMuc21hcnRHcm91cHNTZXJ2aWNlLmRlbGV0ZShncm91cCwgeyBjYXNjYWRlIH0pXG4gICAgICAgIDogYXdhaXQgdGhpcy5pbnZlbnRvcnlTZXJ2aWNlLmRlbGV0ZShncm91cCwgeyBjYXNjYWRlIH0pO1xuXG4gICAgICBjb25zdCBhbGVydE1lc3NhZ2UgPSB0aGlzLnRyYW5zbGF0ZVNlcnZpY2UuaW5zdGFudChnZXR0ZXh0KCdcInt7IG5hbWUgfX1cIiBkZWxldGVkLicpLCB7XG4gICAgICAgIG5hbWU6IGdyb3VwLm5hbWVcbiAgICAgIH0pO1xuICAgICAgdGhpcy5hbGVydFNlcnZpY2Uuc3VjY2VzcyhhbGVydE1lc3NhZ2UpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjb25zdCBhbGVydE1lc3NhZ2UgPSB0aGlzLnRyYW5zbGF0ZVNlcnZpY2UuaW5zdGFudChcbiAgICAgICAgZ2V0dGV4dCgnQ291bGQgbm90IGRlbGV0ZSBcInt7IG5hbWUgfX1cIi4nKSxcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6IGdyb3VwLm5hbWVcbiAgICAgICAgfVxuICAgICAgKTtcbiAgICAgIHRoaXMuYWxlcnRTZXJ2aWNlLmRhbmdlcihhbGVydE1lc3NhZ2UsIGVycm9yKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGRlbGV0ZURldmljZShkZXZpY2U6IElNYW5hZ2VkT2JqZWN0LCBwYXJhbXM6IGFueSA9IHt9KSB7XG4gICAgY29uc3QgeyBjYXNjYWRlLCB3aXRoRGV2aWNlVXNlciB9ID0gcGFyYW1zO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCB7IG93bmVyIH0gPSBkZXZpY2U7XG4gICAgICBjb25zdCBzaG91bGRSZW1vdmVPd25lciA9IHdpdGhEZXZpY2VVc2VyICYmIG93bmVyICYmIHRoaXMuaXNEZXZpY2VVc2VyKG93bmVyKTtcblxuICAgICAgc2hvdWxkUmVtb3ZlT3duZXJcbiAgICAgICAgPyBhd2FpdCB0aGlzLmRlbGV0ZURldmljZVdpdGhVc2VyKGRldmljZSwgY2FzY2FkZSlcbiAgICAgICAgOiBhd2FpdCB0aGlzLmludmVudG9yeVNlcnZpY2UuZGVsZXRlKGRldmljZSwgeyBjYXNjYWRlIH0pO1xuXG4gICAgICBjb25zdCBhbGVydE1lc3NhZ2UgPSB0aGlzLnRyYW5zbGF0ZVNlcnZpY2UuaW5zdGFudChnZXR0ZXh0KCdEZXZpY2UgZGVsZXRlZC4nKSk7XG4gICAgICB0aGlzLmFsZXJ0U2VydmljZS5zdWNjZXNzKGFsZXJ0TWVzc2FnZSk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNvbnN0IGFsZXJ0TWVzc2FnZSA9IHRoaXMudHJhbnNsYXRlU2VydmljZS5pbnN0YW50KGdldHRleHQoJ0NvdWxkIG5vdCBkZWxldGUgZGV2aWNlLicpKTtcbiAgICAgIHRoaXMuYWxlcnRTZXJ2aWNlLmRhbmdlcihhbGVydE1lc3NhZ2UsIGVycm9yKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGRlYWN0aXZhdGVTbWFydHJ1bGVzRm9yQXNzZXQoYXNzZXQ6IElNYW5hZ2VkT2JqZWN0LCBwYXJlbnRSZWY6IElNYW5hZ2VkT2JqZWN0KSB7XG4gICAgY29uc3QgeyBpZDogYXNzZXRJZCB9ID0gYXNzZXQ7XG4gICAgY29uc3QgeyBpZDogcGFyZW50SWQgfSA9IHBhcmVudFJlZjtcbiAgICBjb25zdCBydWxlczogSVJ1bGVbXSA9IChhd2FpdCB0aGlzLnNtYXJ0UnVsZXNTZXJ2aWNlLmxpc3RCeUNvbnRleHQocGFyZW50SWQpKS5kYXRhO1xuXG4gICAgY29uc3QgdXBhdGVTbWFydHJ1bGVzUHJvbWlzZXMgPSBydWxlcy5tYXAocnVsZSA9PlxuICAgICAgdGhpcy5zbWFydFJ1bGVzU2VydmljZS5idWxrRGVhY3RpdmF0ZUVuYWJsZWRTb3VyY2VzKHJ1bGUsIFthc3NldElkXSlcbiAgICApO1xuXG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IFByb21pc2UuYWxsKHVwYXRlU21hcnRydWxlc1Byb21pc2VzKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgY29uc3QgYWxlcnRNZXNzYWdlID0gdGhpcy50cmFuc2xhdGVTZXJ2aWNlLmluc3RhbnQoXG4gICAgICAgIGdldHRleHQoJ0NvdWxkIG5vdCBkZWFjdGl2YXRlIHNtYXJ0IHJ1bGVzLicpXG4gICAgICApO1xuICAgICAgdGhpcy5hbGVydFNlcnZpY2UuZGFuZ2VyKGFsZXJ0TWVzc2FnZSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBpc0RldmljZVVzZXIodXNlcklkOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdXNlcklkLm1hdGNoKC9eZGV2aWNlXy8pO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBkZWxldGVEZXZpY2VXaXRoVXNlcihkZXZpY2U6IElNYW5hZ2VkT2JqZWN0LCBjYXNjYWRlOiBib29sZWFuKSB7XG4gICAgY29uc3QgcGFyYW1zID0geyBjYXNjYWRlLCB3aXRoRGV2aWNlVXNlcjogdHJ1ZSB9O1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5pbnZlbnRvcnlTZXJ2aWNlLmRlbGV0ZShkZXZpY2UsIHBhcmFtcyk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHJldHVybiBhd2FpdCB0aGlzLmludmVudG9yeVNlcnZpY2UuZGVsZXRlKGRldmljZSwgeyBjYXNjYWRlIH0pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZ2V0QXNzZXRzRmlsdGVycyhjb2x1bW5zOiBDb2x1bW5bXSwgcGFnaW5hdGlvbjogUGFnaW5hdGlvbiwgYmFzZVF1ZXJ5LCB0ZXh0Pzogc3RyaW5nKSB7XG4gICAgY29uc3QgcXVlcnkgPSB0aGlzLnF1ZXJpZXNVdGlsLmFkZEFuZEZpbHRlcih0aGlzLmdldFF1ZXJ5T2JqKGNvbHVtbnMpLCBiYXNlUXVlcnkpO1xuICAgIHJldHVybiB7XG4gICAgICAuLi4odGV4dCAmJiB7IHRleHQgfSksXG4gICAgICBxdWVyeTogdGhpcy5xdWVyaWVzVXRpbC5idWlsZFF1ZXJ5KHF1ZXJ5KSxcbiAgICAgIHBhZ2VTaXplOiBwYWdpbmF0aW9uLnBhZ2VTaXplIHx8IHRoaXMuREVGQVVMVF9QQUdFX1NJWkUsXG4gICAgICBjdXJyZW50UGFnZTogcGFnaW5hdGlvbi5jdXJyZW50UGFnZSxcbiAgICAgIHdpdGhUb3RhbFBhZ2VzOiB0cnVlXG4gICAgfTtcbiAgfVxufVxuIl19