UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

305 lines 48 kB
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