@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
265 lines • 37.8 kB
JavaScript
import { Injectable } from '@angular/core';
import { isUndefined, sortBy } from 'lodash-es';
import { debounceTime, take } from 'rxjs/operators';
import { ApplicationType, ApplicationService, TenantService, TenantOptionsService } from '@c8y/client';
import { HumanizeAppNamePipe } from '@c8y/ngx-components';
import { DefaultSubscriptionsContext as DefaultSubscriptionsContextTenant } from './default-subscriptions.model';
import * as i0 from "@angular/core";
import * as i1 from "@c8y/client";
import * as i2 from "@c8y/ngx-components";
export class DefaultSubscriptionsService {
constructor(applicationService, tenantService, tenantOptionsService, humanizeAppNamePipe) {
this.applicationService = applicationService;
this.tenantService = tenantService;
this.tenantOptionsService = tenantOptionsService;
this.humanizeAppNamePipe = humanizeAppNamePipe;
}
/**
* Gets the list of applications which can be used in default subscriptions, i.e.:
* - current tenant's all own applications,
* - inherited applications, which do not have the same names as current tenant's own apps.
* The list is sorted alphabetically by humanized app name and contains up to 2000 items.
* @returns The list of applications, which can be used in default subscriptions.
*/
async getSubscribableTenantApps() {
const currentTenant = (await this.tenantService.current()).data;
const allApps = (await this.applicationService.listByTenant(null, { pageSize: 2000 })).data;
const ownApps = allApps.filter(app => app.owner.tenant.id === currentTenant.name);
const inheritedApps = allApps.filter(app => app.owner.tenant.id !== currentTenant.name);
const filteredApps = [...ownApps];
inheritedApps.forEach(inheritedApp => {
if (!filteredApps.some(filteredApp => filteredApp.name === inheritedApp.name)) {
filteredApps.push(inheritedApp);
}
});
const filteredAppsWithHumanizedNames = await Promise.all(filteredApps.map(async (app) => {
const humanizedName = await this.humanizeAppNamePipe
.transform(app.name)
.pipe(debounceTime(250), take(1))
.toPromise();
return { app, humanizedName };
}));
const sortedAppsWithHumanizedNames = sortBy(filteredAppsWithHumanizedNames, ['humanizedName']);
const sortedApps = sortedAppsWithHumanizedNames.map(({ app }) => app);
return sortedApps;
}
/**
* Gets the default subscriptions configuration inherited from parent tenant.
* @returns The default subscriptions object with settings from parent tenant.
*/
async getDefaultSubscriptionsEvaluatedFromParentTenant() {
return this.getDefaultSubscriptions(DefaultSubscriptionsContextTenant.PARENT_TENANT);
}
/**
* Gets the default subscriptions configuration from the current tenant.
* @returns The default subscriptions object with settings from the current tenant.
*/
async getDefaultSubscriptionsFromCurrentTenant() {
return this.getDefaultSubscriptions(DefaultSubscriptionsContextTenant.CURRENT_TENANT);
}
/**
* Saves given default subscriptions configuration to the current tenant
* (either sets, updates, or deletes corresponding tenant options).
* @param defaultSubscriptions The default subscriptions configuration to be saved.
*/
async saveDefaultSubscriptionsToCurrentTenant(defaultSubscriptions) {
await this.saveOnCreationSubscriptions(defaultSubscriptions);
await this.saveOnUpgradeSubscriptions(defaultSubscriptions);
}
/**
* Gets default subscriptions in the context of current or parent tenant.
* @param contextTenant Tells whether to use current or parent tenant as context.
*/
async getDefaultSubscriptions(contextTenant) {
let tenantOptionsParams;
let overridable;
switch (contextTenant) {
case DefaultSubscriptionsContextTenant.CURRENT_TENANT:
tenantOptionsParams = { evaluate: 'current' };
overridable = true;
break;
case DefaultSubscriptionsContextTenant.PARENT_TENANT:
tenantOptionsParams = { evaluate: 'inherited' };
overridable = false;
break;
}
const { onCreationApps, onCreationMicroservices, onUpgradeAppsEnabled, onUpgradeApps, onUpgradeMicroservicesEnabled, onUpgradeMicroservices } = await this.getTenantOptions(tenantOptionsParams);
const onCreationSubscriptions = this.namesToPartialApps({
appsNamesStr: onCreationApps,
microservicesNamesStr: onCreationMicroservices
});
const onUpgradeAppsDefault = overridable ? null : onCreationApps;
const onUpgradeMicroservicesDefault = overridable ? null : onCreationMicroservices;
const onUpgradeSubscriptions = this.namesToPartialApps({
appsNamesStr: onUpgradeAppsEnabled ? onUpgradeApps : onUpgradeAppsDefault,
microservicesNamesStr: onUpgradeMicroservicesEnabled
? onUpgradeMicroservices
: onUpgradeMicroservicesDefault
});
const defaultSubscriptions = {
onCreationSubscriptions,
onUpgradeSubscriptions
};
if (overridable) {
defaultSubscriptions.overrideOnCreationSubscriptions =
onCreationApps !== null || onCreationMicroservices !== null;
defaultSubscriptions.overrideOnUpgradeSubscriptions =
onUpgradeAppsEnabled || onUpgradeMicroservicesEnabled;
}
return defaultSubscriptions;
}
async getTenantOptions(params = {}) {
return {
onCreationApps: await this.getTenantOption({
category: 'configuration',
key: 'default.tenant.applications'
}, null, params),
onCreationMicroservices: await this.getTenantOption({
category: 'configuration',
key: 'default.tenant.microservices'
}, null, params),
onUpgradeAppsEnabled: await this.getTenantOption({
category: 'configuration',
key: 'on-update.tenant.applications.enabled'
}, false, params),
onUpgradeApps: await this.getTenantOption({
category: 'configuration',
key: 'on-update.tenant.applications'
}, null, params),
onUpgradeMicroservicesEnabled: await this.getTenantOption({
category: 'configuration',
key: 'on-update.tenant.microservices.enabled'
}, false, params),
onUpgradeMicroservices: await this.getTenantOption({
category: 'configuration',
key: 'on-update.tenant.microservices'
}, null, params)
};
}
async saveOnCreationSubscriptions(defaultSubscriptions) {
if (defaultSubscriptions.overrideOnCreationSubscriptions) {
await this.setTenantOption({
category: 'configuration',
key: 'default.tenant.applications',
value: this.partialAppsListToAppsNames(defaultSubscriptions.onCreationSubscriptions)
});
await this.setTenantOption({
category: 'configuration',
key: 'default.tenant.microservices',
value: this.partialAppsToMicroservicesNames(defaultSubscriptions.onCreationSubscriptions)
});
}
else {
await this.unsetTenantOption({
category: 'configuration',
key: 'default.tenant.applications'
});
await this.unsetTenantOption({
category: 'configuration',
key: 'default.tenant.microservices'
});
}
}
async saveOnUpgradeSubscriptions(defaultSubscriptions) {
if (defaultSubscriptions.overrideOnUpgradeSubscriptions) {
await this.setTenantOption({
category: 'configuration',
key: 'on-update.tenant.applications.enabled',
value: 'true'
});
await this.setTenantOption({
category: 'configuration',
key: 'on-update.tenant.microservices.enabled',
value: 'true'
});
await this.setTenantOption({
category: 'configuration',
key: 'on-update.tenant.applications',
value: this.partialAppsListToAppsNames(defaultSubscriptions.onUpgradeSubscriptions)
});
await this.setTenantOption({
category: 'configuration',
key: 'on-update.tenant.microservices',
value: this.partialAppsToMicroservicesNames(defaultSubscriptions.onUpgradeSubscriptions)
});
}
else {
await this.unsetTenantOption({
category: 'configuration',
key: 'on-update.tenant.applications.enabled'
});
await this.unsetTenantOption({
category: 'configuration',
key: 'on-update.tenant.microservices.enabled'
});
await this.unsetTenantOption({
category: 'configuration',
key: 'on-update.tenant.applications'
});
await this.unsetTenantOption({
category: 'configuration',
key: 'on-update.tenant.microservices'
});
}
}
async getTenantOption(option, defaultValue = null, params = {}) {
let value;
try {
value = (await this.tenantOptionsService.detail(option, params)).data.value;
value = JSON.parse(value);
}
catch (ex) {
value = !isUndefined(value) ? value : defaultValue;
}
return value;
}
async setTenantOption(option) {
return this.tenantOptionsService.update(option);
}
async unsetTenantOption(option) {
try {
await this.tenantOptionsService.delete(option);
}
catch (ex) {
if (!ex || !ex.res || ex.res.status !== 404) {
throw ex;
}
}
}
namesToPartialApps({ appsNamesStr, microservicesNamesStr }) {
if (appsNamesStr === null && microservicesNamesStr === null) {
return null;
}
return [
...(appsNamesStr || '')
.split(',')
.filter(name => name.length)
.map(name => ({ name: name.trim() })),
...(microservicesNamesStr || '')
.split(',')
.filter(name => name.length)
.map(name => ({
name: name.trim(),
type: ApplicationType.MICROSERVICE
}))
];
}
partialAppsListToAppsNames(apps) {
return apps
.filter(app => app.type !== ApplicationType.MICROSERVICE)
.map(app => app.name)
.join(',');
}
partialAppsToMicroservicesNames(apps) {
return apps
.filter(app => app.type === ApplicationType.MICROSERVICE)
.map(app => app.name)
.join(',');
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DefaultSubscriptionsService, deps: [{ token: i1.ApplicationService }, { token: i1.TenantService }, { token: i1.TenantOptionsService }, { token: i2.HumanizeAppNamePipe }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DefaultSubscriptionsService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DefaultSubscriptionsService, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: i1.ApplicationService }, { type: i1.TenantService }, { type: i1.TenantOptionsService }, { type: i2.HumanizeAppNamePipe }] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVmYXVsdC1zdWJzY3JpcHRpb25zLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9kZWZhdWx0LXN1YnNjcmlwdGlvbnMvZGVmYXVsdC1zdWJzY3JpcHRpb25zLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNoRCxPQUFPLEVBQUUsWUFBWSxFQUFFLElBQUksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRXBELE9BQU8sRUFFTCxlQUFlLEVBQ2Ysa0JBQWtCLEVBRWxCLGFBQWEsRUFDYixvQkFBb0IsRUFDckIsTUFBTSxhQUFhLENBQUM7QUFDckIsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFFMUQsT0FBTyxFQUdMLDJCQUEyQixJQUFJLGlDQUFpQyxFQUNqRSxNQUFNLCtCQUErQixDQUFDOzs7O0FBR3ZDLE1BQU0sT0FBTywyQkFBMkI7SUFDdEMsWUFDVSxrQkFBc0MsRUFDdEMsYUFBNEIsRUFDNUIsb0JBQTBDLEVBQzFDLG1CQUF3QztRQUh4Qyx1QkFBa0IsR0FBbEIsa0JBQWtCLENBQW9CO1FBQ3RDLGtCQUFhLEdBQWIsYUFBYSxDQUFlO1FBQzVCLHlCQUFvQixHQUFwQixvQkFBb0IsQ0FBc0I7UUFDMUMsd0JBQW1CLEdBQW5CLG1CQUFtQixDQUFxQjtJQUMvQyxDQUFDO0lBRUo7Ozs7OztPQU1HO0lBQ0gsS0FBSyxDQUFDLHlCQUF5QjtRQUM3QixNQUFNLGFBQWEsR0FBRyxDQUFDLE1BQU0sSUFBSSxDQUFDLGFBQWEsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQztRQUVoRSxNQUFNLE9BQU8sR0FBRyxDQUFDLE1BQU0sSUFBSSxDQUFDLGtCQUFrQixDQUFDLFlBQVksQ0FBQyxJQUFJLEVB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QkFDN0IsS0FBSyxDQUFDLEdBQUcsQ0FBQztpQkFDVixNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDO2lCQUMzQixHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUNaLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSSxFQUFFO2dCQUNqQixJQUFJLEVBQUUsZUFBZSxDQUFDLFlBQVk7YUFDbkMsQ0FBQyxDQUFDO1NBQ04sQ0FBQztJQUNKLENBQUM7SUFFTywwQkFBMEIsQ0FBQyxJQUFxQjtRQUN0RCxPQUFPLElBQUk7YUFDUixNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxLQUFLLGVBQWUsQ0FBQyxZQUFZLENBQUM7YUFDeEQsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQzthQUNwQixJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDZixDQUFDO0lBRU8sK0JBQStCLENBQUMsSUFBcUI7UUFDM0QsT0FBTyxJQUFJO2FBQ1IsTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksS0FBSyxlQUFlLENBQUMsWUFBWSxDQUFDO2FBQ3hELEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUM7YUFDcEIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ2YsQ0FBQzsrR0F4VFUsMkJBQTJCO21IQUEzQiwyQkFBMkI7OzRGQUEzQiwyQkFBMkI7a0JBRHZDLFVBQVUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBpc1VuZGVmaW5lZCwgc29ydEJ5IH0gZnJvbSAnbG9kYXNoLWVzJztcbmltcG9ydCB7IGRlYm91bmNlVGltZSwgdGFrZSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuaW1wb3J0IHtcbiAgSUFwcGxpY2F0aW9uLFxuICBBcHBsaWNhdGlvblR5cGUsXG4gIEFwcGxpY2F0aW9uU2VydmljZSxcbiAgSVN5c3RlbU9wdGlvbixcbiAgVGVuYW50U2VydmljZSxcbiAgVGVuYW50T3B0aW9uc1NlcnZpY2Vcbn0gZnJvbSAnQGM4eS9jbGllbnQnO1xuaW1wb3J0IHsgSHVtYW5pemVBcHBOYW1lUGlwZSB9IGZyb20gJ0BjOHkvbmd4LWNvbXBvbmVudHMnO1xuXG5pbXBvcnQge1xuICBQYXJ0aWFsQXBwc0xpc3QsXG4gIERlZmF1bHRTdWJzY3JpcHRpb25zLFxuICBEZWZhdWx0U3Vic2NyaXB0aW9uc0NvbnRleHQgYXMgRGVmYXVsdFN1YnNjcmlwdGlvbnNDb250ZXh0VGVuYW50XG59IGZyb20gJy4vZGVmYXVsdC1zdWJzY3JpcHRpb25zLm1vZGVsJztcblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIERlZmF1bHRTdWJzY3JpcHRpb25zU2VydmljZSB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgYXBwbGljYXRpb25TZXJ2aWNlOiBBcHBsaWNhdGlvblNlcnZpY2UsXG4gICAgcHJpdmF0ZSB0ZW5hbnRTZXJ2aWNlOiBUZW5hbnRTZXJ2aWNlLFxuICAgIHByaXZhdGUgdGVuYW50T3B0aW9uc1NlcnZpY2U6IFRlbmFudE9wdGlvbnNTZXJ2aWNlLFxuICAgIHByaXZhdGUgaHVtYW5pemVBcHBOYW1lUGlwZTogSHVtYW5pemVBcHBOYW1lUGlwZVxuICApIHt9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGxpc3Qgb2YgYXBwbGljYXRpb25zIHdoaWNoIGNhbiBiZSB1c2VkIGluIGRlZmF1bHQgc3Vic2NyaXB0aW9ucywgaS5lLjpcbiAgICogLSBjdXJyZW50IHRlbmFudCdzIGFsbCBvd24gYXBwbGljYXRpb25zLFxuICAgKiAtIGluaGVyaXRlZCBhcHBsaWNhdGlvbnMsIHdoaWNoIGRvIG5vdCBoYXZlIHRoZSBzYW1lIG5hbWVzIGFzIGN1cnJlbnQgdGVuYW50J3Mgb3duIGFwcHMuXG4gICAqIFRoZSBsaXN0IGlzIHNvcnRlZCBhbHBoYWJldGljYWxseSBieSBodW1hbml6ZWQgYXBwIG5hbWUgYW5kIGNvbnRhaW5zIHVwIHRvIDIwMDAgaXRlbXMuXG4gICAqIEByZXR1cm5zIFRoZSBsaXN0IG9mIGFwcGxpY2F0aW9ucywgd2hpY2ggY2FuIGJlIHVzZWQgaW4gZGVmYXVsdCBzdWJzY3JpcHRpb25zLlxuICAgKi9cbiAgYXN5bmMgZ2V0U3Vic2NyaWJhYmxlVGVuYW50QXBwcygpOiBQcm9taXNlPElBcHBsaWNhdGlvbltdPiB7XG4gICAgY29uc3QgY3VycmVudFRlbmFudCA9IChhd2FpdCB0aGlzLnRlbmFudFNlcnZpY2UuY3VycmVudCgpKS5kYXRhO1xuXG4gICAgY29uc3QgYWxsQXBwcyA9IChhd2FpdCB0aGlzLmFwcGxpY2F0aW9uU2VydmljZS5saXN0QnlUZW5hbnQobnVsbCwgeyBwYWdlU2l6ZTogMjAwMCB9KSkuZGF0YTtcbiAgICBjb25zdCBvd25BcHBzID0gYWxsQXBwcy5maWx0ZXIoYXBwID0+IGFwcC5vd25lci50ZW5hbnQuaWQgPT09IGN1cnJlbnRUZW5hbnQubmFtZSk7XG4gICAgY29uc3QgaW5oZXJpdGVkQXBwcyA9IGFsbEFwcHMuZmlsdGVyKGFwcCA9PiBhcHAub3duZXIudGVuYW50LmlkICE9PSBjdXJyZW50VGVuYW50Lm5hbWUpO1xuXG4gICAgY29uc3QgZmlsdGVyZWRBcHBzOiBJQXBwbGljYXRpb25bXSA9IFsuLi5vd25BcHBzXTtcbiAgICBpbmhlcml0ZWRBcHBzLmZvckVhY2goaW5oZXJpdGVkQXBwID0+IHtcbiAgICAgIGlmICghZmlsdGVyZWRBcHBzLnNvbWUoZmlsdGVyZWRBcHAgPT4gZmlsdGVyZWRBcHAubmFtZSA9PT0gaW5oZXJpdGVkQXBwLm5hbWUpKSB7XG4gICAgICAgIGZpbHRlcmVkQXBwcy5wdXNoKGluaGVyaXRlZEFwcCk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBjb25zdCBmaWx0ZXJlZEFwcHNXaXRoSHVtYW5pemVkTmFtZXMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIGZpbHRlcmVkQXBwcy5tYXAoYXN5bmMgYXBwID0+IHtcbiAgICAgICAgY29uc3QgaHVtYW5pemVkTmFtZSA9IGF3YWl0IHRoaXMuaHVtYW5pemVBcHBOYW1lUGlwZVxuICAgICAgICAgIC50cmFuc2Zvcm0oYXBwLm5hbWUpXG4gICAgICAgICAgLnBpcGUoZGVib3VuY2VUaW1lKDI1MCksIHRha2UoMSkpXG4gICAgICAgICAgLnRvUHJvbWlzZSgpO1xuICAgICAgICByZXR1cm4geyBhcHAsIGh1bWFuaXplZE5hbWUgfTtcbiAgICAgIH0pXG4gICAgKTtcbiAgICBjb25zdCBzb3J0ZWRBcHBzV2l0aEh1bWFuaXplZE5hbWVzID0gc29ydEJ5KGZpbHRlcmVkQXBwc1dpdGhIdW1hbml6ZWROYW1lcywgWydodW1hbml6ZWROYW1lJ10pO1xuICAgIGNvbnN0IHNvcnRlZEFwcHMgPSBzb3J0ZWRBcHBzV2l0aEh1bWFuaXplZE5hbWVzLm1hcCgoeyBhcHAgfSkgPT4gYXBwKTtcblxuICAgIHJldHVybiBzb3J0ZWRBcHBzO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGRlZmF1bHQgc3Vic2NyaXB0aW9ucyBjb25maWd1cmF0aW9uIGluaGVyaXRlZCBmcm9tIHBhcmVudCB0ZW5hbnQuXG4gICAqIEByZXR1cm5zIFRoZSBkZWZhdWx0IHN1YnNjcmlwdGlvbnMgb2JqZWN0IHdpdGggc2V0dGluZ3MgZnJvbSBwYXJlbnQgdGVuYW50LlxuICAgKi9cbiAgYXN5bmMgZ2V0RGVmYXVsdFN1YnNjcmlwdGlvbnNFdmFsdWF0ZWRGcm9tUGFyZW50VGVuYW50KCk6IFByb21pc2U8RGVmYXVsdFN1YnNjcmlwdGlvbnM+IHtcbiAgICByZXR1cm4gdGhpcy5nZXREZWZhdWx0U3Vic2NyaXB0aW9ucyhEZWZhdWx0U3Vic2NyaXB0aW9uc0NvbnRleHRUZW5hbnQuUEFSRU5UX1RFTkFOVCk7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgZGVmYXVsdCBzdWJzY3JpcHRpb25zIGNvbmZpZ3VyYXRpb24gZnJvbSB0aGUgY3VycmVudCB0ZW5hbnQuXG4gICAqIEByZXR1cm5zIFRoZSBkZWZhdWx0IHN1YnNjcmlwdGlvbnMgb2JqZWN0IHdpdGggc2V0dGluZ3MgZnJvbSB0aGUgY3VycmVudCB0ZW5hbnQuXG4gICAqL1xuICBhc3luYyBnZXREZWZhdWx0U3Vic2NyaXB0aW9uc0Zyb21DdXJyZW50VGVuYW50KCk6IFByb21pc2U8RGVmYXVsdFN1YnNjcmlwdGlvbnM+IHtcbiAgICByZXR1cm4gdGhpcy5nZXREZWZhdWx0U3Vic2NyaXB0aW9ucyhEZWZhdWx0U3Vic2NyaXB0aW9uc0NvbnRleHRUZW5hbnQuQ1VSUkVOVF9URU5BTlQpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNhdmVzIGdpdmVuIGRlZmF1bHQgc3Vic2NyaXB0aW9ucyBjb25maWd1cmF0aW9uIHRvIHRoZSBjdXJyZW50IHRlbmFudFxuICAgKiAoZWl0aGVyIHNldHMsIHVwZGF0ZXMsIG9yIGRlbGV0ZXMgY29ycmVzcG9uZGluZyB0ZW5hbnQgb3B0aW9ucykuXG4gICAqIEBwYXJhbSBkZWZhdWx0U3Vic2NyaXB0aW9ucyBUaGUgZGVmYXVsdCBzdWJzY3JpcHRpb25zIGNvbmZpZ3VyYXRpb24gdG8gYmUgc2F2ZWQuXG4gICAqL1xuICBhc3luYyBzYXZlRGVmYXVsdFN1YnNjcmlwdGlvbnNUb0N1cnJlbnRUZW5hbnQoZGVmYXVsdFN1YnNjcmlwdGlvbnM6IERlZmF1bHRTdWJzY3JpcHRpb25zKSB7XG4gICAgYXdhaXQgdGhpcy5zYXZlT25DcmVhdGlvblN1YnNjcmlwdGlvbnMoZGVmYXVsdFN1YnNjcmlwdGlvbnMpO1xuICAgIGF3YWl0IHRoaXMuc2F2ZU9uVXBncmFkZVN1YnNjcmlwdGlvbnMoZGVmYXVsdFN1YnNjcmlwdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgZGVmYXVsdCBzdWJzY3JpcHRpb25zIGluIHRoZSBjb250ZXh0IG9mIGN1cnJlbnQgb3IgcGFyZW50IHRlbmFudC5cbiAgICogQHBhcmFtIGNvbnRleHRUZW5hbnQgVGVsbHMgd2hldGhlciB0byB1c2UgY3VycmVudCBvciBwYXJlbnQgdGVuYW50IGFzIGNvbnRleHQuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGdldERlZmF1bHRTdWJzY3JpcHRpb25zKFxuICAgIGNvbnRleHRUZW5hbnQ6IERlZmF1bHRTdWJzY3JpcHRpb25zQ29udGV4dFRlbmFudFxuICApOiBQcm9taXNlPERlZmF1bHRTdWJzY3JpcHRpb25zPiB7XG4gICAgbGV0IHRlbmFudE9wdGlvbnNQYXJhbXM6IG9iamVjdDtcbiAgICBsZXQgb3ZlcnJpZGFibGU6IGJvb2xlYW47XG5cbiAgICBzd2l0Y2ggKGNvbnRleHRUZW5hbnQpIHtcbiAgICAgIGNhc2UgRGVmYXVsdFN1YnNjcmlwdGlvbnNDb250ZXh0VGVuYW50LkNVUlJFTlRfVEVOQU5UOlxuICAgICAgICB0ZW5hbnRPcHRpb25zUGFyYW1zID0geyBldmFsdWF0ZTogJ2N1cnJlbnQnIH07XG4gICAgICAgIG92ZXJyaWRhYmxlID0gdHJ1ZTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgRGVmYXVsdFN1YnNjcmlwdGlvbnNDb250ZXh0VGVuYW50LlBBUkVOVF9URU5BTlQ6XG4gICAgICAgIHRlbmFudE9wdGlvbnNQYXJhbXMgPSB7IGV2YWx1YXRlOiAnaW5oZXJpdGVkJyB9O1xuICAgICAgICBvdmVycmlkYWJsZSA9IGZhbHNlO1xuICAgICAgICBicmVhaztcbiAgICB9XG5cbiAgICBjb25zdCB7XG4gICAgICBvbkNyZWF0aW9uQXBwcyxcbiAgICAgIG9uQ3JlYXRpb25NaWNyb3NlcnZpY2VzLFxuICAgICAgb25VcGdyYWRlQXBwc0VuYWJsZWQsXG4gICAgICBvblVwZ3JhZGVBcHBzLFxuICAgICAgb25VcGdyYWRlTWljcm9zZXJ2aWNlc0VuYWJsZWQsXG4gICAgICBvblVwZ3JhZGVNaWNyb3NlcnZpY2VzXG4gICAgfSA9IGF3YWl0IHRoaXMuZ2V0VGVuYW50T3B0aW9ucyh0ZW5hbnRPcHRpb25zUGFyYW1zKTtcblxuICAgIGNvbnN0IG9uQ3JlYXRpb25TdWJzY3JpcHRpb25zID0gdGhpcy5uYW1lc1RvUGFydGlhbEFwcHMoe1xuICAgICAgYXBwc05hbWVzU3RyOiBvbkNyZWF0aW9uQXBwcyxcbiAgICAgIG1pY3Jvc2VydmljZXNOYW1lc1N0cjogb25DcmVhdGlvbk1pY3Jvc2VydmljZXNcbiAgICB9KTtcblxuICAgIGNvbnN0IG9uVXBncmFkZUFwcHNEZWZhdWx0ID0gb3ZlcnJpZGFibGUgPyBudWxsIDogb25DcmVhdGlvbkFwcHM7XG4gICAgY29uc3Qgb25VcGdyYWRlTWljcm9zZXJ2aWNlc0RlZmF1bHQgPSBvdmVycmlkYWJsZSA/IG51bGwgOiBvbkNyZWF0aW9uTWljcm9zZXJ2aWNlcztcbiAgICBjb25zdCBvblVwZ3JhZGVTdWJzY3JpcHRpb25zID0gdGhpcy5uYW1lc1RvUGFydGlhbEFwcHMoe1xuICAgICAgYXBwc05hbWVzU3RyOiBvblVwZ3JhZGVBcHBzRW5hYmxlZCA/IG9uVXBncmFkZUFwcHMgOiBvblVwZ3JhZGVBcHBzRGVmYXVsdCxcbiAgICAgIG1pY3Jvc2VydmljZXNOYW1lc1N0cjogb25VcGdyYWRlTWljcm9zZXJ2aWNlc0VuYWJsZWRcbiAgICAgICAgPyBvblVwZ3JhZGVNaWNyb3NlcnZpY2VzXG4gICAgICAgIDogb25VcGdyYWRlTWljcm9zZXJ2aWNlc0RlZmF1bHRcbiAgICB9KTtcblxuICAgIGNvbnN0IGRlZmF1bHRTdWJzY3JpcHRpb25zOiBEZWZhdWx0U3Vic2NyaXB0aW9ucyA9IHtcbiAgICAgIG9uQ3JlYXRpb25TdWJzY3JpcHRpb25zLFxuICAgICAgb25VcGdyYWRlU3Vic2NyaXB0aW9uc1xuICAgIH07XG5cbiAgICBpZiAob3ZlcnJpZGFibGUpIHtcbiAgICAgIGRlZmF1bHRTdWJzY3JpcHRpb25zLm92ZXJyaWRlT25DcmVhdGlvblN1YnNjcmlwdGlvbnMgPVxuICAgICAgICBvbkNyZWF0aW9uQXBwcyAhPT0gbnVsbCB8fCBvbkNyZWF0aW9uTWljcm9zZXJ2aWNlcyAhPT0gbnVsbDtcbiAgICAgIGRlZmF1bHRTdWJzY3JpcHRpb25zLm92ZXJyaWRlT25VcGdyYWRlU3Vic2NyaXB0aW9ucyA9XG4gICAgICAgIG9uVXBncmFkZUFwcHNFbmFibGVkIHx8IG9uVXBncmFkZU1pY3Jvc2VydmljZXNFbmFibGVkO1xuICAgIH1cblxuICAgIHJldHVybiBkZWZhdWx0U3Vic2NyaXB0aW9ucztcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZ2V0VGVuYW50T3B0aW9ucyhwYXJhbXMgPSB7fSkge1xuICAgIHJldHVybiB7XG4gICAgICBvbkNyZWF0aW9uQXBwczogYXdhaXQgdGhpcy5nZXRUZW5hbnRPcHRpb24oXG4gICAgICAgIHtcbiAgICAgICAgICBjYXRlZ29yeTogJ2NvbmZpZ3VyYXRpb24nLFxuICAgICAgICAgIGtleTogJ2RlZmF1bHQudGVuYW50LmFwcGxpY2F0aW9ucydcbiAgICAgICAgfSxcbiAgICAgICAgbnVsbCxcbiAgICAgICAgcGFyYW1zXG4gICAgICApLFxuICAgICAgb25DcmVhdGlvbk1pY3Jvc2VydmljZXM6IGF3YWl0IHRoaXMuZ2V0VGVuYW50T3B0aW9uKFxuICAgICAgICB7XG4gICAgICAgICAgY2F0ZWdvcnk6ICdjb25maWd1cmF0aW9uJyxcbiAgICAgICAgICBrZXk6ICdkZWZhdWx0LnRlbmFudC5taWNyb3NlcnZpY2VzJ1xuICAgICAgICB9LFxuICAgICAgICBudWxsLFxuICAgICAgICBwYXJhbXNcbiAgICAgICksXG4gICAgICBvblVwZ3JhZGVBcHBzRW5hYmxlZDogYXdhaXQgdGhpcy5nZXRUZW5hbnRPcHRpb24oXG4gICAgICAgIHtcbiAgICAgICAgICBjYXRlZ29yeTogJ2NvbmZpZ3VyYXRpb24nLFxuICAgICAgICAgIGtleTogJ29uLXVwZGF0ZS50ZW5hbnQuYXBwbGljYXRpb25zLmVuYWJsZWQnXG4gICAgICAgIH0sXG4gICAgICAgIGZhbHNlLFxuICAgICAgICBwYXJhbXNcbiAgICAgICksXG4gICAgICBvblVwZ3JhZGVBcHBzOiBhd2FpdCB0aGlzLmdldFRlbmFudE9wdGlvbihcbiAgICAgICAge1xuICAgICAgICAgIGNhdGVnb3J5OiAnY29uZmlndXJhdGlvbicsXG4gICAgICAgICAga2V5OiAnb24tdXBkYXRlLnRlbmFudC5hcHBsaWNhdGlvbnMnXG4gICAgICAgIH0sXG4gICAgICAgIG51bGwsXG4gICAgICAgIHBhcmFtc1xuICAgICAgKSxcbiAgICAgIG9uVXBncmFkZU1pY3Jvc2VydmljZXNFbmFibGVkOiBhd2FpdCB0aGlzLmdldFRlbmFudE9wdGlvbihcbiAgICAgICAge1xuICAgICAgICAgIGNhdGVnb3J5OiAnY29uZmlndXJhdGlvbicsXG4gICAgICAgICAga2V5OiAnb24tdXBkYXRlLnRlbmFudC5taWNyb3NlcnZpY2VzLmVuYWJsZWQnXG4gICAgICAgIH0sXG4gICAgICAgIGZhbHNlLFxuICAgICAgICBwYXJhbXNcbiAgICAgICksXG4gICAgICBvblVwZ3JhZGVNaWNyb3NlcnZpY2VzOiBhd2FpdCB0aGlzLmdldFRlbmFudE9wdGlvbihcbiAgICAgICAge1xuICAgICAgICAgIGNhdGVnb3J5OiAnY29uZmlndXJhdGlvbicsXG4gICAgICAgICAga2V5OiAnb24tdXBkYXRlLnRlbmFudC5taWNyb3NlcnZpY2VzJ1xuICAgICAgICB9LFxuICAgICAgICBudWxsLFxuICAgICAgICBwYXJhbXNcbiAgICAgIClcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBzYXZlT25DcmVhdGlvblN1YnNjcmlwdGlvbnMoZGVmYXVsdFN1YnNjcmlwdGlvbnM6IERlZmF1bHRTdWJzY3JpcHRpb25zKSB7XG4gICAgaWYgKGRlZmF1bHRTdWJzY3JpcHRpb25zLm92ZXJyaWRlT25DcmVhdGlvblN1YnNjcmlwdGlvbnMpIHtcbiAgICAgIGF3YWl0IHRoaXMuc2V0VGVuYW50T3B0aW9uKHtcbiAgICAgICAgY2F0ZWdvcnk6ICdjb25maWd1cmF0aW9uJyxcbiAgICAgICAga2V5OiAnZGVmYXVsdC50ZW5hbnQuYXBwbGljYXRpb25zJyxcbiAgICAgICAgdmFsdWU6IHRoaXMucGFydGlhbEFwcHNMaXN0VG9BcHBzTmFtZXMoZGVmYXVsdFN1YnNjcmlwdGlvbnMub25DcmVhdGlvblN1YnNjcmlwdGlvbnMpXG4gICAgICB9KTtcbiAgICAgIGF3YWl0IHRoaXMuc2V0VGVuYW50T3B0aW9uKHtcbiAgICAgICAgY2F0ZWdvcnk6ICdjb25maWd1cmF0aW9uJyxcbiAgICAgICAga2V5OiAnZGVmYXVsdC50ZW5hbnQubWljcm9zZXJ2aWNlcycsXG4gICAgICAgIHZhbHVlOiB0aGlzLnBhcnRpYWxBcHBzVG9NaWNyb3NlcnZpY2VzTmFtZXMoZGVmYXVsdFN1YnNjcmlwdGlvbnMub25DcmVhdGlvblN1YnNjcmlwdGlvbnMpXG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgYXdhaXQgdGhpcy51bnNldFRlbmFudE9wdGlvbih7XG4gICAgICAgIGNhdGVnb3J5OiAnY29uZmlndXJhdGlvbicsXG4gICAgICAgIGtleTogJ2RlZmF1bHQudGVuYW50LmFwcGxpY2F0aW9ucydcbiAgICAgIH0pO1xuICAgICAgYXdhaXQgdGhpcy51bnNldFRlbmFudE9wdGlvbih7XG4gICAgICAgIGNhdGVnb3J5OiAnY29uZmlndXJhdGlvbicsXG4gICAgICAgIGtleTogJ2RlZmF1bHQudGVuYW50Lm1pY3Jvc2VydmljZXMnXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHNhdmVPblVwZ3JhZGVTdWJzY3JpcHRpb25zKGRlZmF1bHRTdWJzY3JpcHRpb25zOiBEZWZhdWx0U3Vic2NyaXB0aW9ucykge1xuICAgIGlmIChkZWZhdWx0U3Vic2NyaXB0aW9ucy5vdmVycmlkZU9uVXBncmFkZVN1YnNjcmlwdGlvbnMpIHtcbiAgICAgIGF3YWl0IHRoaXMuc2V0VGVuYW50T3B0aW9uKHtcbiAgICAgICAgY2F0ZWdvcnk6ICdjb25maWd1cmF0aW9uJyxcbiAgICAgICAga2V5OiAnb24tdXBkYXRlLnRlbmFudC5hcHBsaWNhdGlvbnMuZW5hYmxlZCcsXG4gICAgICAgIHZhbHVlOiAndHJ1ZSdcbiAgICAgIH0pO1xuICAgICAgYXdhaXQgdGhpcy5zZXRUZW5hbnRPcHRpb24oe1xuICAgICAgICBjYXRlZ29yeTogJ2NvbmZpZ3VyYXRpb24nLFxuICAgICAgICBrZXk6ICdvbi11cGRhdGUudGVuYW50Lm1pY3Jvc2VydmljZXMuZW5hYmxlZCcsXG4gICAgICAgIHZhbHVlOiAndHJ1ZSdcbiAgICAgIH0pO1xuICAgICAgYXdhaXQgdGhpcy5zZXRUZW5hbnRPcHRpb24oe1xuICAgICAgICBjYXRlZ29yeTogJ2NvbmZpZ3VyYXRpb24nLFxuICAgICAgICBrZXk6ICdvbi11cGRhdGUudGVuYW50LmFwcGxpY2F0aW9ucycsXG4gICAgICAgIHZhbHVlOiB0aGlzLnBhcnRpYWxBcHBzTGlzdFRvQXBwc05hbWVzKGRlZmF1bHRTdWJzY3JpcHRpb25zLm9uVXBncmFkZVN1YnNjcmlwdGlvbnMpXG4gICAgICB9KTtcbiAgICAgIGF3YWl0IHRoaXMuc2V0VGVuYW50T3B0aW9uKHtcbiAgICAgICAgY2F0ZWdvcnk6ICdjb25maWd1cmF0aW9uJyxcbiAgICAgICAga2V5OiAnb24tdXBkYXRlLnRlbmFudC5taWNyb3NlcnZpY2VzJyxcbiAgICAgICAgdmFsdWU6IHRoaXMucGFydGlhbEFwcHNUb01pY3Jvc2VydmljZXNOYW1lcyhkZWZhdWx0U3Vic2NyaXB0aW9ucy5vblVwZ3JhZGVTdWJzY3JpcHRpb25zKVxuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGF3YWl0IHRoaXMudW5zZXRUZW5hbnRPcHRpb24oe1xuICAgICAgICBjYXRlZ29yeTogJ2NvbmZpZ3VyYXRpb24nLFxuICAgICAgICBrZXk6ICdvbi11cGRhdGUudGVuYW50LmFwcGxpY2F0aW9ucy5lbmFibGVkJ1xuICAgICAgfSk7XG4gICAgICBhd2FpdCB0aGlzLnVuc2V0VGVuYW50T3B0aW9uKHtcbiAgICAgICAgY2F0ZWdvcnk6ICdjb25maWd1cmF0aW9uJyxcbiAgICAgICAga2V5OiAnb24tdXBkYXRlLnRlbmFudC5taWNyb3NlcnZpY2VzLmVuYWJsZWQnXG4gICAgICB9KTtcbiAgICAgIGF3YWl0IHRoaXMudW5zZXRUZW5hbnRPcHRpb24oe1xuICAgICAgICBjYXRlZ29yeTogJ2NvbmZpZ3VyYXRpb24nLFxuICAgICAgICBrZXk6ICdvbi11cGRhdGUudGVuYW50LmFwcGxpY2F0aW9ucydcbiAgICAgIH0pO1xuICAgICAgYXdhaXQgdGhpcy51bnNldFRlbmFudE9wdGlvbih7XG4gICAgICAgIGNhdGVnb3J5OiAnY29uZmlndXJhdGlvbicsXG4gICAgICAgIGtleTogJ29uLXVwZGF0ZS50ZW5hbnQubWljcm9zZXJ2aWNlcydcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZ2V0VGVuYW50T3B0aW9uKG9wdGlvbjogSVN5c3RlbU9wdGlvbiwgZGVmYXVsdFZhbHVlID0gbnVsbCwgcGFyYW1zID0ge30pIHtcbiAgICBsZXQgdmFsdWU7XG4gICAgdHJ5IHtcbiAgICAgIHZhbHVlID0gKGF3YWl0IHRoaXMudGVuYW50T3B0aW9uc1NlcnZpY2UuZGV0YWlsKG9wdGlvbiwgcGFyYW1zKSkuZGF0YS52YWx1ZTtcbiAgICAgIHZhbHVlID0gSlNPTi5wYXJzZSh2YWx1ZSk7XG4gICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgIHZhbHVlID0gIWlzVW5kZWZpbmVkKHZhbHVlKSA/IHZhbHVlIDogZGVmYXVsdFZhbHVlO1xuICAgIH1cbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHNldFRlbmFudE9wdGlvbihvcHRpb246IElTeXN0ZW1PcHRpb24pIHtcbiAgICByZXR1cm4gdGhpcy50ZW5hbnRPcHRpb25zU2VydmljZS51cGRhdGUob3B0aW9uKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgdW5zZXRUZW5hbnRPcHRpb24ob3B0aW9uOiBJU3lzdGVtT3B0aW9uKSB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMudGVuYW50T3B0aW9uc1NlcnZpY2UuZGVsZXRlKG9wdGlvbik7XG4gICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgIGlmICghZXggfHwgIWV4LnJlcyB8fCBleC5yZXMuc3RhdHVzICE9PSA0MDQpIHtcbiAgICAgICAgdGhyb3cgZXg7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBuYW1lc1RvUGFydGlhbEFwcHMoe1xuICAgIGFwcHNOYW1lc1N0cixcbiAgICBtaWNyb3NlcnZpY2VzTmFtZXNTdHJcbiAgfToge1xuICAgIGFwcHNOYW1lc1N0cj86IHN0cmluZztcbiAgICBtaWNyb3NlcnZpY2VzTmFtZXNTdHI/OiBzdHJpbmc7XG4gIH0pOiBQYXJ0aWFsQXBwc0xpc3Qge1xuICAgIGlmIChhcHBzTmFtZXNTdHIgPT09IG51bGwgJiYgbWljcm9zZXJ2aWNlc05hbWVzU3RyID09PSBudWxsKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICByZXR1cm4gW1xuICAgICAgLi4uKGFwcHNOYW1lc1N0ciB8fCAnJylcbiAgICAgICAgLnNwbGl0KCcsJylcbiAgICAgICAgLmZpbHRlcihuYW1lID0+IG5hbWUubGVuZ3RoKVxuICAgICAgICAubWFwKG5hbWUgPT4gKHsgbmFtZTogbmFtZS50cmltKCkgfSkpLFxuICAgICAgLi4uKG1pY3Jvc2VydmljZXNOYW1lc1N0ciB8fCAnJylcbiAgICAgICAgLnNwbGl0KCcsJylcbiAgICAgICAgLmZpbHRlcihuYW1lID0+IG5hbWUubGVuZ3RoKVxuICAgICAgICAubWFwKG5hbWUgPT4gKHtcbiAgICAgICAgICBuYW1lOiBuYW1lLnRyaW0oKSxcbiAgICAgICAgICB0eXBlOiBBcHBsaWNhdGlvblR5cGUuTUlDUk9TRVJWSUNFXG4gICAgICAgIH0pKVxuICAgIF07XG4gIH1cblxuICBwcml2YXRlIHBhcnRpYWxBcHBzTGlzdFRvQXBwc05hbWVzKGFwcHM6IFBhcnRpYWxBcHBzTGlzdCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGFwcHNcbiAgICAgIC5maWx0ZXIoYXBwID0+IGFwcC50eXBlICE9PSBBcHBsaWNhdGlvblR5cGUuTUlDUk9TRVJWSUNFKVxuICAgICAgLm1hcChhcHAgPT4gYXBwLm5hbWUpXG4gICAgICAuam9pbignLCcpO1xuICB9XG5cbiAgcHJpdmF0ZSBwYXJ0aWFsQXBwc1RvTWljcm9zZXJ2aWNlc05hbWVzKGFwcHM6IFBhcnRpYWxBcHBzTGlzdCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGFwcHNcbiAgICAgIC5maWx0ZXIoYXBwID0+IGFwcC50eXBlID09PSBBcHBsaWNhdGlvblR5cGUuTUlDUk9TRVJWSUNFKVxuICAgICAgLm1hcChhcHAgPT4gYXBwLm5hbWUpXG4gICAgICAuam9pbignLCcpO1xuICB9XG59XG4iXX0=