@orbit/memory
Version:
Orbit source for managing in-memory records.
264 lines • 41.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MemoryCache = void 0;
const core_1 = require("@orbit/core");
const immutable_1 = require("@orbit/immutable");
const record_cache_1 = require("@orbit/record-cache");
const records_1 = require("@orbit/records");
const utils_1 = require("@orbit/utils");
const { assert, deprecate } = core_1.Orbit;
/**
* A cache used to access records in memory.
*
* Because data is stored in immutable maps, this type of cache can be forked
* efficiently.
*/
class MemoryCache extends record_cache_1.SyncRecordCache {
constructor(settings) {
const { base, trackUpdateOperations } = settings;
super(settings);
this._base = base;
// Track update operations if explicitly told to do so, or if a `base`
// cache has been specified.
this._isTrackingUpdateOperations =
trackUpdateOperations !== null && trackUpdateOperations !== void 0 ? trackUpdateOperations : base !== undefined;
this.reset();
}
get base() {
return this._base;
}
/**
* Create a clone, or "fork", from a "base" cache.
*
* The forked cache will have the same `schema` and `keyMap` as its base
* source. The forked cache will start with the same immutable document as the
* base source. Its contents and log will evolve independently.
*
* @returns the forked cache
*/
fork(settings = {}) {
var _a, _b, _c, _d, _e;
// required settings
settings.base = this;
settings.schema = this.schema;
settings.keyMap = this._keyMap;
// customizable settings
(_a = settings.queryBuilder) !== null && _a !== void 0 ? _a : (settings.queryBuilder = this._queryBuilder);
(_b = settings.transformBuilder) !== null && _b !== void 0 ? _b : (settings.transformBuilder = this._transformBuilder);
(_c = settings.defaultQueryOptions) !== null && _c !== void 0 ? _c : (settings.defaultQueryOptions = this._defaultQueryOptions);
(_d = settings.defaultTransformOptions) !== null && _d !== void 0 ? _d : (settings.defaultTransformOptions = this._defaultTransformOptions);
if (settings.autoValidate !== false) {
(_e = settings.validatorFor) !== null && _e !== void 0 ? _e : (settings.validatorFor = this._validatorFor);
if (settings.autoValidate === undefined &&
settings.validatorFor === undefined) {
settings.autoValidate = false;
}
}
return new MemoryCache(settings);
}
merge(forkedCache, options) {
let { coalesce, ...remainingOptions } = options !== null && options !== void 0 ? options : {};
assert('MemoryCache#merge can only merge a forked cache that is configured with `trackUpdateOperations: true`.', forkedCache.isTrackingUpdateOperations);
let ops = forkedCache.getAllUpdateOperations();
if (coalesce !== false) {
ops = (0, records_1.coalesceRecordOperations)(ops);
}
if (options === null || options === void 0 ? void 0 : options.fullResponse) {
return this.update(ops, remainingOptions);
}
else {
return this.update(ops, remainingOptions);
}
}
/**
* Rebase resets this cache's state to that of its base cache, then re-applies
* any tracked update operations.
*
* Rebasing requires both a `base` cache as well as tracking of update
* operations (which is enabled by default when a `base` cache is assigned).
*/
rebase() {
const base = this._base;
assert('A `base` cache must be defined for `rebase` to work', base !== undefined);
assert('MemoryCache#rebase requires that the cache is configured with `trackUpdateOperations: true`.', this._isTrackingUpdateOperations);
// get update ops prior to resetting state
let ops = this.getAllUpdateOperations();
// reset the state of the cache to match its base cache
this.reset();
// reapply update ops
this.update(ops);
}
getRecordSync(identity) {
return this._records[identity.type].get(identity.id);
}
getRecordsSync(typeOrIdentities) {
if (typeOrIdentities === undefined) {
const types = Object.keys(this.schema.models);
const records = [];
types.forEach((type) => Array.prototype.push.apply(records, Array.from(this._records[type].values())));
return records;
}
else if (typeof typeOrIdentities === 'string') {
const type = typeOrIdentities;
return Array.from(this._records[type].values());
}
else {
const records = [];
const identities = typeOrIdentities;
for (let identity of identities) {
let record = this.getRecordSync(identity);
if (record) {
records.push(record);
}
}
return records;
}
}
setRecordSync(record) {
this._records[record.type].set(record.id, record);
}
setRecordsSync(records) {
let typedMap = {};
for (let record of records) {
typedMap[record.type] = typedMap[record.type] || [];
typedMap[record.type].push([record.id, record]);
}
for (let type in typedMap) {
this._records[type].setMany(typedMap[type]);
}
}
removeRecordSync(recordIdentity) {
const recordMap = this._records[recordIdentity.type];
const record = recordMap.get(recordIdentity.id);
if (record) {
recordMap.remove(recordIdentity.id);
return record;
}
else {
return undefined;
}
}
removeRecordsSync(recordIdentities) {
const records = [];
const typedIds = {};
for (let recordIdentity of recordIdentities) {
let record = this.getRecordSync(recordIdentity);
if (record) {
records.push(record);
typedIds[record.type] = typedIds[record.type] || [];
typedIds[record.type].push(recordIdentity.id);
}
}
for (let type in typedIds) {
this._records[type].removeMany(typedIds[type]);
}
return records;
}
getInverseRelationshipsSync(recordIdentityOrIdentities) {
const results = [];
const identities = Array.isArray(recordIdentityOrIdentities)
? recordIdentityOrIdentities
: [recordIdentityOrIdentities];
for (let identity of identities) {
const result = this._inverseRelationships[identity.type].get(identity.id);
if (result) {
Array.prototype.push.apply(results, result);
}
}
return results;
}
addInverseRelationshipsSync(relationships) {
relationships.forEach((r) => {
let rels = this._inverseRelationships[r.relatedRecord.type].get(r.relatedRecord.id);
rels = rels ? [...rels, (0, utils_1.clone)(r)] : [(0, utils_1.clone)(r)];
this._inverseRelationships[r.relatedRecord.type].set(r.relatedRecord.id, rels);
});
}
removeInverseRelationshipsSync(relationships) {
relationships.forEach((r) => {
let rels = this._inverseRelationships[r.relatedRecord.type].get(r.relatedRecord.id);
if (rels) {
let newRels = rels.filter((rel) => !((0, records_1.equalRecordIdentities)(rel.record, r.record) &&
rel.relationship === r.relationship));
this._inverseRelationships[r.relatedRecord.type].set(r.relatedRecord.id, newRels);
}
});
}
/**
* Resets the cache's to its initial state, which will be either empty or a
* clone of its `base` cache, if it has one.
*/
reset() {
let base = this._base;
if (arguments.length > 0) {
deprecate('Calling MemoryCache#reset with a `base` argument is deprecated. Instead configure your MemoryCache with a `base` cache.');
base !== null && base !== void 0 ? base : (base = arguments[0]);
}
this._records = {};
if (this._isTrackingUpdateOperations) {
this._updateOperations = [];
}
Object.keys(this._schema.models).forEach((type) => {
let baseRecords = base === null || base === void 0 ? void 0 : base._records[type];
this._records[type] = new immutable_1.ImmutableMap(baseRecords);
});
this._resetInverseRelationships(base);
this._processors.forEach((processor) => processor.reset(base));
this.emit('reset');
}
/**
* Upgrade the cache based on the current state of the schema.
*/
upgrade() {
Object.keys(this._schema.models).forEach((type) => {
if (!this._records[type]) {
this._records[type] = new immutable_1.ImmutableMap();
}
});
this._resetInverseRelationships();
for (let processor of this._processors) {
processor.upgrade();
}
}
get isTrackingUpdateOperations() {
return this._isTrackingUpdateOperations;
}
getAllUpdateOperations() {
assert('MemoryCache#getAllUpdateOperations requires that cache be configured with `trackUpdateOperations: true`.', this._isTrackingUpdateOperations);
return this._updateOperations;
}
/////////////////////////////////////////////////////////////////////////////
// Protected methods
/////////////////////////////////////////////////////////////////////////////
_update(transform, options) {
if (this._isTrackingUpdateOperations) {
Array.prototype.push.apply(this._updateOperations, (0, utils_1.toArray)(transform.operations));
}
return super._update(transform, options);
}
/**
* Override `_getTransformBuffer` on base `SyncRecordCache` to provide a
* `transformBuffer` if a custom one hasn't been provided via the constructor
* setting.
*/
_getTransformBuffer() {
if (this._transformBuffer === undefined) {
const { schema, keyMap } = this;
this._transformBuffer = new record_cache_1.SimpleRecordTransformBuffer({
schema,
keyMap
});
}
return this._transformBuffer;
}
_resetInverseRelationships(base) {
const inverseRelationships = {};
Object.keys(this._schema.models).forEach((type) => {
let baseRelationships = base && base._inverseRelationships[type];
inverseRelationships[type] = new immutable_1.ImmutableMap(baseRelationships);
});
this._inverseRelationships = inverseRelationships;
}
}
exports.MemoryCache = MemoryCache;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtb3J5LWNhY2hlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL21lbW9yeS1jYWNoZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxzQ0FBb0M7QUFPcEMsZ0RBQWdEO0FBQ2hELHNEQVM2QjtBQUM3Qiw0Q0FVd0I7QUFDeEIsd0NBQW9EO0FBRXBELE1BQU0sRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLEdBQUcsWUFBSyxDQUFDO0FBb0NwQzs7Ozs7R0FLRztBQUNILE1BQWEsV0FPWCxTQUFRLDhCQUF5QztJQVNqRCxZQUFZLFFBQXVEO1FBQ2pFLE1BQU0sRUFBRSxJQUFJLEVBQUUscUJBQXFCLEVBQUUsR0FBRyxRQUFRLENBQUM7UUFFakQsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBRWhCLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDO1FBRWxCLHNFQUFzRTtRQUN0RSw0QkFBNEI7UUFDNUIsSUFBSSxDQUFDLDJCQUEyQjtZQUM5QixxQkFBcUIsYUFBckIscUJBQXFCLGNBQXJCLHFCQUFxQixHQUFJLElBQUksS0FBSyxTQUFTLENBQUM7UUFFOUMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQ2YsQ0FBQztJQUVELElBQUksSUFBSTtRQUNOLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQztJQUNwQixDQUFDO0lBRUQ7Ozs7Ozs7O09BUUc7SUFDSCxJQUFJLENBQ0YsV0FBbUUsRUFBRTs7UUFFckUsb0JBQW9CO1FBQ3BCLFFBQVEsQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO1FBQ3JCLFFBQVEsQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQztRQUM5QixRQUFRLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUM7UUFFL0Isd0JBQXdCO1FBQ3hCLE1BQUEsUUFBUSxDQUFDLFlBQVksb0NBQXJCLFFBQVEsQ0FBQyxZQUFZLEdBQUssSUFBSSxDQUFDLGFBQWEsRUFBQztRQUM3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QyxJQUFJLEVBQUUsRUFBRTtZQUNoRCxJQUFJLGlCQUFpQixHQUFHLElBQUksSUFBSSxJQUFJLENBQUMscUJBQXFCLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDakUsb0JBQW9CLENBQUMsSUFBSSxDQUFDLEdBQUcsSUFBSSx3QkFBWSxDQUFDLGlCQUFpQixDQUFDLENBQUM7UUFDbkUsQ0FBQyxDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMscUJBQXFCLEdBQUcsb0JBQW9CLENBQUM7SUFDcEQsQ0FBQztDQUNGO0FBellELGtDQXlZQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE9yYml0IH0gZnJvbSAnQG9yYml0L2NvcmUnO1xuaW1wb3J0IHtcbiAgRGVmYXVsdFJlcXVlc3RPcHRpb25zLFxuICBGdWxsUmVxdWVzdE9wdGlvbnMsXG4gIEZ1bGxSZXNwb25zZSxcbiAgUmVxdWVzdE9wdGlvbnNcbn0gZnJvbSAnQG9yYml0L2RhdGEnO1xuaW1wb3J0IHsgSW1tdXRhYmxlTWFwIH0gZnJvbSAnQG9yYml0L2ltbXV0YWJsZSc7XG5pbXBvcnQge1xuICBSZWNvcmRDYWNoZVF1ZXJ5T3B0aW9ucyxcbiAgUmVjb3JkQ2FjaGVUcmFuc2Zvcm1PcHRpb25zLFxuICBSZWNvcmRDYWNoZVVwZGF0ZURldGFpbHMsXG4gIFJlY29yZFJlbGF0aW9uc2hpcElkZW50aXR5LFxuICBSZWNvcmRUcmFuc2Zvcm1CdWZmZXIsXG4gIFNpbXBsZVJlY29yZFRyYW5zZm9ybUJ1ZmZlcixcbiAgU3luY1JlY29yZENhY2hlLFxuICBTeW5jUmVjb3JkQ2FjaGVTZXR0aW5nc1xufSBmcm9tICdAb3JiaXQvcmVjb3JkLWNhY2hlJztcbmltcG9ydCB7XG4gIGNvYWxlc2NlUmVjb3JkT3BlcmF0aW9ucyxcbiAgZXF1YWxSZWNvcmRJZGVudGl0aWVzLFxuICBJbml0aWFsaXplZFJlY29yZCxcbiAgUmVjb3JkSWRlbnRpdHksXG4gIFJlY29yZE9wZXJhdGlvbixcbiAgUmVjb3JkUXVlcnlCdWlsZGVyLFxuICBSZWNvcmRUcmFuc2Zvcm0sXG4gIFJlY29yZFRyYW5zZm9ybUJ1aWxkZXIsXG4gIFJlY29yZFRyYW5zZm9ybVJlc3VsdFxufSBmcm9tICdAb3JiaXQvcmVjb3Jkcyc7XG5pbXBvcnQgeyBjbG9uZSwgRGljdCwgdG9BcnJheSB9IGZyb20gJ0BvcmJpdC91dGlscyc7XG5cbmNvbnN0IHsgYXNzZXJ0LCBkZXByZWNhdGUgfSA9IE9yYml0O1xuXG5leHBvcnQgaW50ZXJmYWNlIE1lbW9yeUNhY2hlTWVyZ2VPcHRpb25zIHtcbiAgY29hbGVzY2U/OiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE1lbW9yeUNhY2hlU2V0dGluZ3M8XG4gIFFPIGV4dGVuZHMgUmVxdWVzdE9wdGlvbnMgPSBSZWNvcmRDYWNoZVF1ZXJ5T3B0aW9ucyxcbiAgVE8gZXh0ZW5kcyBSZXF1ZXN0T3B0aW9ucyA9IFJlY29yZENhY2hlVHJhbnNmb3JtT3B0aW9ucyxcbiAgUUIgPSBSZWNvcmRRdWVyeUJ1aWxkZXIsXG4gIFRCID0gUmVjb3JkVHJhbnNmb3JtQnVpbGRlcixcbiAgUVJEID0gdW5rbm93bixcbiAgVFJEIGV4dGVuZHMgUmVjb3JkQ2FjaGVVcGRhdGVEZXRhaWxzID0gUmVjb3JkQ2FjaGVVcGRhdGVEZXRhaWxzXG4+IGV4dGVuZHMgU3luY1JlY29yZENhY2hlU2V0dGluZ3M8UU8sIFRPLCBRQiwgVEI+IHtcbiAgYmFzZT86IE1lbW9yeUNhY2hlPFFPLCBUTywgUUIsIFRCLCBRUkQsIFRSRD47XG4gIHRyYWNrVXBkYXRlT3BlcmF0aW9ucz86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTWVtb3J5Q2FjaGVDbGFzczxcbiAgUU8gZXh0ZW5kcyBSZXF1ZXN0T3B0aW9ucyA9IFJlY29yZENhY2hlUXVlcnlPcHRpb25zLFxuICBUTyBleHRlbmRzIFJlcXVlc3RPcHRpb25zID0gUmVjb3JkQ2FjaGVUcmFuc2Zvcm1PcHRpb25zLFxuICBRQiA9IFJlY29yZFF1ZXJ5QnVpbGRlcixcbiAgVEIgPSBSZWNvcmRUcmFuc2Zvcm1CdWlsZGVyLFxuICBRUkQgPSB1bmtub3duLFxuICBUUkQgZXh0ZW5kcyBSZWNvcmRDYWNoZVVwZGF0ZURldGFpbHMgPSBSZWNvcmRDYWNoZVVwZGF0ZURldGFpbHNcbj4ge1xuICBuZXcgKHNldHRpbmdzOiBNZW1vcnlDYWNoZVNldHRpbmdzPFFPLCBUTywgUUIsIFRCLCBRUkQsIFRSRD4pOiBNZW1vcnlDYWNoZTxcbiAgICBRTyxcbiAgICBUTyxcbiAgICBRQixcbiAgICBUQixcbiAgICBRUkQsXG4gICAgVFJEXG4gID47XG59XG5cbi8qKlxuICogQSBjYWNoZSB1c2VkIHRvIGFjY2VzcyByZWNvcmRzIGluIG1lbW9yeS5cbiAqXG4gKiBCZWNhdXNlIGRhdGEgaXMgc3RvcmVkIGluIGltbXV0YWJsZSBtYXBzLCB0aGlzIHR5cGUgb2YgY2FjaGUgY2FuIGJlIGZvcmtlZFxuICogZWZmaWNpZW50bHkuXG4gKi9cbmV4cG9ydCBjbGFzcyBNZW1vcnlDYWNoZTxcbiAgUU8gZXh0ZW5kcyBSZXF1ZXN0T3B0aW9ucyA9IFJlY29yZENhY2hlUXVlcnlPcHRpb25zLFxuICBUTyBleHRlbmRzIFJlcXVlc3RPcHRpb25zID0gUmVjb3JkQ2FjaGVUcmFuc2Zvcm1PcHRpb25zLFxuICBRQiA9IFJlY29yZFF1ZXJ5QnVpbGRlcixcbiAgVEIgPSBSZWNvcmRUcmFuc2Zvcm1CdWlsZGVyLFxuICBRUkQgPSB1bmtub3duLFxuICBUUkQgZXh0ZW5kcyBSZWNvcmRDYWNoZVVwZGF0ZURldGFpbHMgPSBSZWNvcmRDYWNoZVVwZGF0ZURldGFpbHNcbj4gZXh0ZW5kcyBTeW5jUmVjb3JkQ2FjaGU8UU8sIFRPLCBRQiwgVEIsIFFSRCwgVFJEPiB7XG4gIHByb3RlY3RlZCBfYmFzZT86IE1lbW9yeUNhY2hlPFFPLCBUTywgUUIsIFRCLCBRUkQsIFRSRD47XG4gIHByb3RlY3RlZCBfcmVjb3JkcyE6IERpY3Q8SW1tdXRhYmxlTWFwPHN0cmluZywgSW5pdGlhbGl6ZWRSZWNvcmQ+PjtcbiAgcHJvdGVjdGVkIF9pbnZlcnNlUmVsYXRpb25zaGlwcyE6IERpY3Q8XG4gICAgSW1tdXRhYmxlTWFwPHN0cmluZywgUmVjb3JkUmVsYXRpb25zaGlwSWRlbnRpdHlbXT5cbiAgPjtcbiAgcHJvdGVjdGVkIF91cGRhdGVPcGVyYXRpb25zPzogUmVjb3JkT3BlcmF0aW9uW107XG4gIHByb3RlY3RlZCBfaXNUcmFja2luZ1VwZGF0ZU9wZXJhdGlvbnM6IGJvb2xlYW47XG5cbiAgY29uc3RydWN0b3Ioc2V0dGluZ3M6IE1lbW9yeUNhY2hlU2V0dGluZ3M8UU8sIFRPLCBRQiwgVEIsIFFSRCwgVFJEPikge1xuICAgIGNvbnN0IHsgYmFzZSwgdHJhY2tVcGRhdGVPcGVyYXRpb25zIH0gPSBzZXR0aW5ncztcblxuICAgIHN1cGVyKHNldHRpbmdzKTtcblxuICAgIHRoaXMuX2Jhc2UgPSBiYXNlO1xuXG4gICAgLy8gVHJhY2sgdXBkYXRlIG9wZXJhdGlvbnMgaWYgZXhwbGljaXRseSB0b2xkIHRvIGRvIHNvLCBvciBpZiBhIGBiYXNlYFxuICAgIC8vIGNhY2hlIGhhcyBiZWVuIHNwZWNpZmllZC5cbiAgICB0aGlzLl9pc1RyYWNraW5nVXBkYXRlT3BlcmF0aW9ucyA9XG4gICAgICB0cmFja1VwZGF0ZU9wZXJhdGlvbnMgPz8gYmFzZSAhPT0gdW5kZWZpbmVkO1xuXG4gICAgdGhpcy5yZXNldCgpO1xuICB9XG5cbiAgZ2V0IGJhc2UoKTogTWVtb3J5Q2FjaGU8UU8sIFRPLCBRQiwgVEIsIFFSRCwgVFJEPiB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuX2Jhc2U7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgY2xvbmUsIG9yIFwiZm9ya1wiLCBmcm9tIGEgXCJiYXNlXCIgY2FjaGUuXG4gICAqXG4gICAqIFRoZSBmb3JrZWQgY2FjaGUgd2lsbCBoYXZlIHRoZSBzYW1lIGBzY2hlbWFgIGFuZCBga2V5TWFwYCBhcyBpdHMgYmFzZVxuICAgKiBzb3VyY2UuIFRoZSBmb3JrZWQgY2FjaGUgd2lsbCBzdGFydCB3aXRoIHRoZSBzYW1lIGltbXV0YWJsZSBkb2N1bWVudCBhcyB0aGVcbiAgICogYmFzZSBzb3VyY2UuIEl0cyBjb250ZW50cyBhbmQgbG9nIHdpbGwgZXZvbHZlIGluZGVwZW5kZW50bHkuXG4gICAqXG4gICAqIEByZXR1cm5zIHRoZSBmb3JrZWQgY2FjaGVcbiAgICovXG4gIGZvcmsoXG4gICAgc2V0dGluZ3M6IFBhcnRpYWw8TWVtb3J5Q2FjaGVTZXR0aW5nczxRTywgVE8sIFFCLCBUQiwgUVJELCBUUkQ+PiA9IHt9XG4gICk6IE1lbW9yeUNhY2hlPFFPLCBUTywgUUIsIFRCLCBRUkQsIFRSRD4ge1xuICAgIC8vIHJlcXVpcmVkIHNldHRpbmdzXG4gICAgc2V0dGluZ3MuYmFzZSA9IHRoaXM7XG4gICAgc2V0dGluZ3Muc2NoZW1hID0gdGhpcy5zY2hlbWE7XG4gICAgc2V0dGluZ3Mua2V5TWFwID0gdGhpcy5fa2V5TWFwO1xuXG4gICAgLy8gY3VzdG9taXphYmxlIHNldHRpbmdzXG4gICAgc2V0dGluZ3MucXVlcnlCdWlsZGVyID8/PSB0aGlzLl9xdWVyeUJ1aWxkZXI7XG4gICAgc2V0dGluZ3MudHJhbnNmb3JtQnVpbGRlciA/Pz0gdGhpcy5fdHJhbnNmb3JtQnVpbGRlcjtcbiAgICBzZXR0aW5ncy5kZWZhdWx0UXVlcnlPcHRpb25zID8/PSB0aGlzLl9kZWZhdWx0UXVlcnlPcHRpb25zO1xuICAgIHNldHRpbmdzLmRlZmF1bHRUcmFuc2Zvcm1PcHRpb25zID8/PSB0aGlzLl9kZWZhdWx0VHJhbnNmb3JtT3B0aW9ucztcbiAgICBpZiAoc2V0dGluZ3MuYXV0b1ZhbGlkYXRlICE9PSBmYWxzZSkge1xuICAgICAgc2V0dGluZ3MudmFsaWRhdG9yRm9yID8/PSB0aGlzLl92YWxpZGF0b3JGb3I7XG4gICAgICBpZiAoXG4gICAgICAgIHNldHRpbmdzLmF1dG9WYWxpZGF0ZSA9PT0gdW5kZWZpbmVkICYmXG4gICAgICAgIHNldHRpbmdzLnZhbGlkYXRvckZvciA9PT0gdW5kZWZpbmVkXG4gICAgICApIHtcbiAgICAgICAgc2V0dGluZ3MuYXV0b1ZhbGlkYXRlID0gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBNZW1vcnlDYWNoZShcbiAgICAgIHNldHRpbmdzIGFzIE1lbW9yeUNhY2hlU2V0dGluZ3M8UU8sIFRPLCBRQiwgVEIsIFFSRCwgVFJEPlxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogTWVyZ2VzIHRoZSBvcGVyYXRpb25zIGZyb20gYSBmb3JrZWQgY2FjaGUgYmFjayB0byB0aGlzIGNhY2hlLlxuICAgKlxuICAgKiBAcmV0dXJucyB0aGUgcmVzdWx0IG9mIGNhbGxpbmcgYHVwZGF0ZWAgd2l0aCB0aGUgb3BlcmF0aW9uc1xuICAgKi9cbiAgbWVyZ2U8UmVxdWVzdERhdGEgZXh0ZW5kcyBSZWNvcmRUcmFuc2Zvcm1SZXN1bHQgPSBSZWNvcmRUcmFuc2Zvcm1SZXN1bHQ+KFxuICAgIGZvcmtlZENhY2hlOiBNZW1vcnlDYWNoZTxRTywgVE8sIFFCLCBUQiwgUVJELCBUUkQ+LFxuICAgIG9wdGlvbnM/OiBEZWZhdWx0UmVxdWVzdE9wdGlvbnM8VE8+ICYgTWVtb3J5Q2FjaGVNZXJnZU9wdGlvbnNcbiAgKTogUmVxdWVzdERhdGE7XG4gIG1lcmdlPFJlcXVlc3REYXRhIGV4dGVuZHMgUmVjb3JkVHJhbnNmb3JtUmVzdWx0ID0gUmVjb3JkVHJhbnNmb3JtUmVzdWx0PihcbiAgICBmb3JrZWRDYWNoZTogTWVtb3J5Q2FjaGU8UU8sIFRPLCBRQiwgVEIsIFFSRCwgVFJEPixcbiAgICBvcHRpb25zOiBGdWxsUmVxdWVzdE9wdGlvbnM8VE8+ICYgTWVtb3J5Q2FjaGVNZXJnZU9wdGlvbnNcbiAgKTogRnVsbFJlc3BvbnNlPFJlcXVlc3REYXRhLCBUUkQsIFJlY29yZE9wZXJhdGlvbj47XG4gIG1lcmdlPFJlcXVlc3REYXRhIGV4dGVuZHMgUmVjb3JkVHJhbnNmb3JtUmVzdWx0ID0gUmVjb3JkVHJhbnNmb3JtUmVzdWx0PihcbiAgICBmb3JrZWRDYWNoZTogTWVtb3J5Q2FjaGU8UU8sIFRPLCBRQiwgVEIsIFFSRCwgVFJEPixcbiAgICBvcHRpb25zPzogVE8gJiBNZW1vcnlDYWNoZU1lcmdlT3B0aW9uc1xuICApOiBSZXF1ZXN0RGF0YSB8IEZ1bGxSZXNwb25zZTxSZXF1ZXN0RGF0YSwgVFJELCBSZWNvcmRPcGVyYXRpb24+IHtcbiAgICBsZXQgeyBjb2FsZXNjZSwgLi4ucmVtYWluaW5nT3B0aW9ucyB9ID0gb3B0aW9ucyA/PyB7fTtcblxuICAgIGFzc2VydChcbiAgICAgICdNZW1vcnlDYWNoZSNtZXJnZSBjYW4gb25seSBtZXJnZSBhIGZvcmtlZCBjYWNoZSB0aGF0IGlzIGNvbmZpZ3VyZWQgd2l0aCBgdHJhY2tVcGRhdGVPcGVyYXRpb25zOiB0cnVlYC4nLFxuICAgICAgZm9ya2VkQ2FjaGUuaXNUcmFja2luZ1VwZGF0ZU9wZXJhdGlvbnNcbiAgICApO1xuXG4gICAgbGV0IG9wcyA9IGZvcmtlZENhY2hlLmdldEFsbFVwZGF0ZU9wZXJhdGlvbnMoKTtcblxuICAgIGlmIChjb2FsZXNjZSAhPT0gZmFsc2UpIHtcbiAgICAgIG9wcyA9IGNvYWxlc2NlUmVjb3JkT3BlcmF0aW9ucyhvcHMpO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zPy5mdWxsUmVzcG9uc2UpIHtcbiAgICAgIHJldHVybiB0aGlzLnVwZGF0ZTxSZXF1ZXN0RGF0YT4oXG4gICAgICAgIG9wcyxcbiAgICAgICAgcmVtYWluaW5nT3B0aW9ucyBhcyBGdWxsUmVxdWVzdE9wdGlvbnM8VE8+XG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdGhpcy51cGRhdGU8UmVxdWVzdERhdGE+KFxuICAgICAgICBvcHMsXG4gICAgICAgIHJlbWFpbmluZ09wdGlvbnMgYXMgRGVmYXVsdFJlcXVlc3RPcHRpb25zPFRPPlxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmViYXNlIHJlc2V0cyB0aGlzIGNhY2hlJ3Mgc3RhdGUgdG8gdGhhdCBvZiBpdHMgYmFzZSBjYWNoZSwgdGhlbiByZS1hcHBsaWVzXG4gICAqIGFueSB0cmFja2VkIHVwZGF0ZSBvcGVyYXRpb25zLlxuICAgKlxuICAgKiBSZWJhc2luZyByZXF1aXJlcyBib3RoIGEgYGJhc2VgIGNhY2hlIGFzIHdlbGwgYXMgdHJhY2tpbmcgb2YgdXBkYXRlXG4gICAqIG9wZXJhdGlvbnMgKHdoaWNoIGlzIGVuYWJsZWQgYnkgZGVmYXVsdCB3aGVuIGEgYGJhc2VgIGNhY2hlIGlzIGFzc2lnbmVkKS5cbiAgICovXG4gIHJlYmFzZSgpOiB2b2lkIHtcbiAgICBjb25zdCBiYXNlID0gdGhpcy5fYmFzZTtcblxuICAgIGFzc2VydChcbiAgICAgICdBIGBiYXNlYCBjYWNoZSBtdXN0IGJlIGRlZmluZWQgZm9yIGByZWJhc2VgIHRvIHdvcmsnLFxuICAgICAgYmFzZSAhPT0gdW5kZWZpbmVkXG4gICAgKTtcblxuICAgIGFzc2VydChcbiAgICAgICdNZW1vcnlDYWNoZSNyZWJhc2UgcmVxdWlyZXMgdGhhdCB0aGUgY2FjaGUgaXMgY29uZmlndXJlZCB3aXRoIGB0cmFja1VwZGF0ZU9wZXJhdGlvbnM6IHRydWVgLicsXG4gICAgICB0aGlzLl9pc1RyYWNraW5nVXBkYXRlT3BlcmF0aW9uc1xuICAgICk7XG5cbiAgICAvLyBnZXQgdXBkYXRlIG9wcyBwcmlvciB0byByZXNldHRpbmcgc3RhdGVcbiAgICBsZXQgb3BzID0gdGhpcy5nZXRBbGxVcGRhdGVPcGVyYXRpb25zKCk7XG5cbiAgICAvLyByZXNldCB0aGUgc3RhdGUgb2YgdGhlIGNhY2hlIHRvIG1hdGNoIGl0cyBiYXNlIGNhY2hlXG4gICAgdGhpcy5yZXNldCgpO1xuXG4gICAgLy8gcmVhcHBseSB1cGRhdGUgb3BzXG4gICAgdGhpcy51cGRhdGUob3BzKTtcbiAgfVxuXG4gIGdldFJlY29yZFN5bmMoaWRlbnRpdHk6IFJlY29yZElkZW50aXR5KTogSW5pdGlhbGl6ZWRSZWNvcmQgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLl9yZWNvcmRzW2lkZW50aXR5LnR5cGVdLmdldChpZGVudGl0eS5pZCk7XG4gIH1cblxuICBnZXRSZWNvcmRzU3luYyhcbiAgICB0eXBlT3JJZGVudGl0aWVzPzogc3RyaW5nIHwgUmVjb3JkSWRlbnRpdHlbXVxuICApOiBJbml0aWFsaXplZFJlY29yZFtdIHtcbiAgICBpZiAodHlwZU9ySWRlbnRpdGllcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBjb25zdCB0eXBlcyA9IE9iamVjdC5rZXlzKHRoaXMuc2NoZW1hLm1vZGVscyk7XG4gICAgICBjb25zdCByZWNvcmRzOiBJbml0aWFsaXplZFJlY29yZFtdID0gW107XG4gICAgICB0eXBlcy5mb3JFYWNoKCh0eXBlKSA9PlxuICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShcbiAgICAgICAgICByZWNvcmRzLFxuICAgICAgICAgIEFycmF5LmZyb20odGhpcy5fcmVjb3Jkc1t0eXBlXS52YWx1ZXMoKSlcbiAgICAgICAgKVxuICAgICAgKTtcbiAgICAgIHJldHVybiByZWNvcmRzO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIHR5cGVPcklkZW50aXRpZXMgPT09ICdzdHJpbmcnKSB7XG4gICAgICBjb25zdCB0eXBlOiBzdHJpbmcgPSB0eXBlT3JJZGVudGl0aWVzO1xuICAgICAgcmV0dXJuIEFycmF5LmZyb20odGhpcy5fcmVjb3Jkc1t0eXBlXS52YWx1ZXMoKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHJlY29yZHM6IEluaXRpYWxpemVkUmVjb3JkW10gPSBbXTtcbiAgICAgIGNvbnN0IGlkZW50aXRpZXM6IFJlY29yZElkZW50aXR5W10gPSB0eXBlT3JJZGVudGl0aWVzO1xuICAgICAgZm9yIChsZXQgaWRlbnRpdHkgb2YgaWRlbnRpdGllcykge1xuICAgICAgICBsZXQgcmVjb3JkID0gdGhpcy5nZXRSZWNvcmRTeW5jKGlkZW50aXR5KTtcbiAgICAgICAgaWYgKHJlY29yZCkge1xuICAgICAgICAgIHJlY29yZHMucHVzaChyZWNvcmQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVjb3JkcztcbiAgICB9XG4gIH1cblxuICBzZXRSZWNvcmRTeW5jKHJlY29yZDogSW5pdGlhbGl6ZWRSZWNvcmQpOiB2b2lkIHtcbiAgICB0aGlzLl9yZWNvcmRzW3JlY29yZC50eXBlXS5zZXQocmVjb3JkLmlkLCByZWNvcmQpO1xuICB9XG5cbiAgc2V0UmVjb3Jkc1N5bmMocmVjb3JkczogSW5pdGlhbGl6ZWRSZWNvcmRbXSk6IHZvaWQge1xuICAgIGxldCB0eXBlZE1hcDogYW55ID0ge307XG4gICAgZm9yIChsZXQgcmVjb3JkIG9mIHJlY29yZHMpIHtcbiAgICAgIHR5cGVkTWFwW3JlY29yZC50eXBlXSA9IHR5cGVkTWFwW3JlY29yZC50eXBlXSB8fCBbXTtcbiAgICAgIHR5cGVkTWFwW3JlY29yZC50eXBlXS5wdXNoKFtyZWNvcmQuaWQsIHJlY29yZF0pO1xuICAgIH1cbiAgICBmb3IgKGxldCB0eXBlIGluIHR5cGVkTWFwKSB7XG4gICAgICB0aGlzLl9yZWNvcmRzW3R5cGVdLnNldE1hbnkodHlwZWRNYXBbdHlwZV0pO1xuICAgIH1cbiAgfVxuXG4gIHJlbW92ZVJlY29yZFN5bmMoXG4gICAgcmVjb3JkSWRlbnRpdHk6IFJlY29yZElkZW50aXR5XG4gICk6IEluaXRpYWxpemVkUmVjb3JkIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCByZWNvcmRNYXAgPSB0aGlzLl9yZWNvcmRzW3JlY29yZElkZW50aXR5LnR5cGVdO1xuICAgIGNvbnN0IHJlY29yZCA9IHJlY29yZE1hcC5nZXQocmVjb3JkSWRlbnRpdHkuaWQpO1xuICAgIGlmIChyZWNvcmQpIHtcbiAgICAgIHJlY29yZE1hcC5yZW1vdmUocmVjb3JkSWRlbnRpdHkuaWQpO1xuICAgICAgcmV0dXJuIHJlY29yZDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gIH1cblxuICByZW1vdmVSZWNvcmRzU3luYyhyZWNvcmRJZGVudGl0aWVzOiBSZWNvcmRJZGVudGl0eVtdKTogSW5pdGlhbGl6ZWRSZWNvcmRbXSB7XG4gICAgY29uc3QgcmVjb3JkcyA9IFtdO1xuICAgIGNvbnN0IHR5cGVkSWRzOiBhbnkgPSB7fTtcbiAgICBmb3IgKGxldCByZWNvcmRJZGVudGl0eSBvZiByZWNvcmRJZGVudGl0aWVzKSB7XG4gICAgICBsZXQgcmVjb3JkID0gdGhpcy5nZXRSZWNvcmRTeW5jKHJlY29yZElkZW50aXR5KTtcbiAgICAgIGlmIChyZWNvcmQpIHtcbiAgICAgICAgcmVjb3Jkcy5wdXNoKHJlY29yZCk7XG4gICAgICAgIHR5cGVkSWRzW3JlY29yZC50eXBlXSA9IHR5cGVkSWRzW3JlY29yZC50eXBlXSB8fCBbXTtcbiAgICAgICAgdHlwZWRJZHNbcmVjb3JkLnR5cGVdLnB1c2gocmVjb3JkSWRlbnRpdHkuaWQpO1xuICAgICAgfVxuICAgIH1cbiAgICBmb3IgKGxldCB0eXBlIGluIHR5cGVkSWRzKSB7XG4gICAgICB0aGlzLl9yZWNvcmRzW3R5cGVdLnJlbW92ZU1hbnkodHlwZWRJZHNbdHlwZV0pO1xuICAgIH1cbiAgICByZXR1cm4gcmVjb3JkcztcbiAgfVxuXG4gIGdldEludmVyc2VSZWxhdGlvbnNoaXBzU3luYyhcbiAgICByZWNvcmRJZGVudGl0eU9ySWRlbnRpdGllczogUmVjb3JkSWRlbnRpdHkgfCBSZWNvcmRJZGVudGl0eVtdXG4gICk6IFJlY29yZFJlbGF0aW9uc2hpcElkZW50aXR5W10ge1xuICAgIGNvbnN0IHJlc3VsdHM6IFJlY29yZFJlbGF0aW9uc2hpcElkZW50aXR5W10gPSBbXTtcbiAgICBjb25zdCBpZGVudGl0aWVzOiBSZWNvcmRJZGVudGl0eVtdID0gQXJyYXkuaXNBcnJheShcbiAgICAgIHJlY29yZElkZW50aXR5T3JJZGVudGl0aWVzXG4gICAgKVxuICAgICAgPyByZWNvcmRJZGVudGl0eU9ySWRlbnRpdGllc1xuICAgICAgOiBbcmVjb3JkSWRlbnRpdHlPcklkZW50aXRpZXNdO1xuXG4gICAgZm9yIChsZXQgaWRlbnRpdHkgb2YgaWRlbnRpdGllcykge1xuICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5faW52ZXJzZVJlbGF0aW9uc2hpcHNbaWRlbnRpdHkudHlwZV0uZ2V0KGlkZW50aXR5LmlkKTtcbiAgICAgIGlmIChyZXN1bHQpIHtcbiAgICAgICAgQXJyYXkucHJvdG90eXBlLnB1c2guYXBwbHkocmVzdWx0cywgcmVzdWx0KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0cztcbiAgfVxuXG4gIGFkZEludmVyc2VSZWxhdGlvbnNoaXBzU3luYyhcbiAgICByZWxhdGlvbnNoaXBzOiBSZWNvcmRSZWxhdGlvbnNoaXBJZGVudGl0eVtdXG4gICk6IHZvaWQge1xuICAgIHJlbGF0aW9uc2hpcHMuZm9yRWFjaCgocikgPT4ge1xuICAgICAgbGV0IHJlbHMgPSB0aGlzLl9pbnZlcnNlUmVsYXRpb25zaGlwc1tyLnJlbGF0ZWRSZWNvcmQudHlwZV0uZ2V0KFxuICAgICAgICByLnJlbGF0ZWRSZWNvcmQuaWRcbiAgICAgICk7XG4gICAgICByZWxzID0gcmVscyA/IFsuLi5yZWxzLCBjbG9uZShyKV0gOiBbY2xvbmUocildO1xuICAgICAgdGhpcy5faW52ZXJzZVJlbGF0aW9uc2hpcHNbci5yZWxhdGVkUmVjb3JkLnR5cGVdLnNldChcbiAgICAgICAgci5yZWxhdGVkUmVjb3JkLmlkLFxuICAgICAgICByZWxzXG4gICAgICApO1xuICAgIH0pO1xuICB9XG5cbiAgcmVtb3ZlSW52ZXJzZVJlbGF0aW9uc2hpcHNTeW5jKFxuICAgIHJlbGF0aW9uc2hpcHM6IFJlY29yZFJlbGF0aW9uc2hpcElkZW50aXR5W11cbiAgKTogdm9pZCB7XG4gICAgcmVsYXRpb25zaGlwcy5mb3JFYWNoKChyKSA9PiB7XG4gICAgICBsZXQgcmVscyA9IHRoaXMuX2ludmVyc2VSZWxhdGlvbnNoaXBzW3IucmVsYXRlZFJlY29yZC50eXBlXS5nZXQoXG4gICAgICAgIHIucmVsYXRlZFJlY29yZC5pZFxuICAgICAgKTtcbiAgICAgIGlmIChyZWxzKSB7XG4gICAgICAgIGxldCBuZXdSZWxzID0gcmVscy5maWx0ZXIoXG4gICAgICAgICAgKHJlbCkgPT5cbiAgICAgICAgICAgICEoXG4gICAgICAgICAgICAgIGVxdWFsUmVjb3JkSWRlbnRpdGllcyhyZWwucmVjb3JkLCByLnJlY29yZCkgJiZcbiAgICAgICAgICAgICAgcmVsLnJlbGF0aW9uc2hpcCA9PT0gci5yZWxhdGlvbnNoaXBcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5faW52ZXJzZVJlbGF0aW9uc2hpcHNbci5yZWxhdGVkUmVjb3JkLnR5cGVdLnNldChcbiAgICAgICAgICByLnJlbGF0ZWRSZWNvcmQuaWQsXG4gICAgICAgICAgbmV3UmVsc1xuICAgICAgICApO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc2V0cyB0aGUgY2FjaGUncyB0byBpdHMgaW5pdGlhbCBzdGF0ZSwgd2hpY2ggd2lsbCBiZSBlaXRoZXIgZW1wdHkgb3IgYVxuICAgKiBjbG9uZSBvZiBpdHMgYGJhc2VgIGNhY2hlLCBpZiBpdCBoYXMgb25lLlxuICAgKi9cbiAgcmVzZXQoKTogdm9pZCB7XG4gICAgbGV0IGJhc2UgPSB0aGlzLl9iYXNlO1xuXG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAwKSB7XG4gICAgICBkZXByZWNhdGUoXG4gICAgICAgICdDYWxsaW5nIE1lbW9yeUNhY2hlI3Jlc2V0IHdpdGggYSBgYmFzZWAgYXJndW1lbnQgaXMgZGVwcmVjYXRlZC4gSW5zdGVhZCBjb25maWd1cmUgeW91ciBNZW1vcnlDYWNoZSB3aXRoIGEgYGJhc2VgIGNhY2hlLidcbiAgICAgICk7XG4gICAgICBiYXNlID8/PSBhcmd1bWVudHNbMF07XG4gICAgfVxuXG4gICAgdGhpcy5fcmVjb3JkcyA9IHt9O1xuXG4gICAgaWYgKHRoaXMuX2lzVHJhY2tpbmdVcGRhdGVPcGVyYXRpb25zKSB7XG4gICAgICB0aGlzLl91cGRhdGVPcGVyYXRpb25zID0gW107XG4gICAgfVxuXG4gICAgT2JqZWN0LmtleXModGhpcy5fc2NoZW1hLm1vZGVscykuZm9yRWFjaCgodHlwZSkgPT4ge1xuICAgICAgbGV0IGJhc2VSZWNvcmRzID0gYmFzZT8uX3JlY29yZHNbdHlwZV07XG5cbiAgICAgIHRoaXMuX3JlY29yZHNbdHlwZV0gPSBuZXcgSW1tdXRhYmxlTWFwPHN0cmluZywgSW5pdGlhbGl6ZWRSZWNvcmQ+KFxuICAgICAgICBiYXNlUmVjb3Jkc1xuICAgICAgKTtcbiAgICB9KTtcblxuICAgIHRoaXMuX3Jlc2V0SW52ZXJzZVJlbGF0aW9uc2hpcHMoYmFzZSk7XG5cbiAgICB0aGlzLl9wcm9jZXNzb3JzLmZvckVhY2goKHByb2Nlc3NvcikgPT4gcHJvY2Vzc29yLnJlc2V0KGJhc2UpKTtcblxuICAgIHRoaXMuZW1pdCgncmVzZXQnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVcGdyYWRlIHRoZSBjYWNoZSBiYXNlZCBvbiB0aGUgY3VycmVudCBzdGF0ZSBvZiB0aGUgc2NoZW1hLlxuICAgKi9cbiAgdXBncmFkZSgpOiB2b2lkIHtcbiAgICBPYmplY3Qua2V5cyh0aGlzLl9zY2hlbWEubW9kZWxzKS5mb3JFYWNoKCh0eXBlKSA9PiB7XG4gICAgICBpZiAoIXRoaXMuX3JlY29yZHNbdHlwZV0pIHtcbiAgICAgICAgdGhpcy5fcmVjb3Jkc1t0eXBlXSA9IG5ldyBJbW11dGFibGVNYXA8c3RyaW5nLCBJbml0aWFsaXplZFJlY29yZD4oKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHRoaXMuX3Jlc2V0SW52ZXJzZVJlbGF0aW9uc2hpcHMoKTtcblxuICAgIGZvciAobGV0IHByb2Nlc3NvciBvZiB0aGlzLl9wcm9jZXNzb3JzKSB7XG4gICAgICBwcm9jZXNzb3IudXBncmFkZSgpO1xuICAgIH1cbiAgfVxuXG4gIGdldCBpc1RyYWNraW5nVXBkYXRlT3BlcmF0aW9ucygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5faXNUcmFja2luZ1VwZGF0ZU9wZXJhdGlvbnM7XG4gIH1cblxuICBnZXRBbGxVcGRhdGVPcGVyYXRpb25zKCk6IFJlY29yZE9wZXJhdGlvbltdIHtcbiAgICBhc3NlcnQoXG4gICAgICAnTWVtb3J5Q2FjaGUjZ2V0QWxsVXBkYXRlT3BlcmF0aW9ucyByZXF1aXJlcyB0aGF0IGNhY2hlIGJlIGNvbmZpZ3VyZWQgd2l0aCBgdHJhY2tVcGRhdGVPcGVyYXRpb25zOiB0cnVlYC4nLFxuICAgICAgdGhpcy5faXNUcmFja2luZ1VwZGF0ZU9wZXJhdGlvbnNcbiAgICApO1xuXG4gICAgcmV0dXJuIHRoaXMuX3VwZGF0ZU9wZXJhdGlvbnMgYXMgUmVjb3JkT3BlcmF0aW9uW107XG4gIH1cblxuICAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuICAvLyBQcm90ZWN0ZWQgbWV0aG9kc1xuICAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuXG4gIHByb3RlY3RlZCBfdXBkYXRlPFxuICAgIFJlcXVlc3REYXRhIGV4dGVuZHMgUmVjb3JkVHJhbnNmb3JtUmVzdWx0ID0gUmVjb3JkVHJhbnNmb3JtUmVzdWx0XG4gID4oXG4gICAgdHJhbnNmb3JtOiBSZWNvcmRUcmFuc2Zvcm0sXG4gICAgb3B0aW9ucz86IFRPXG4gICk6IEZ1bGxSZXNwb25zZTxSZXF1ZXN0RGF0YSwgVFJELCBSZWNvcmRPcGVyYXRpb24+IHtcbiAgICBpZiAodGhpcy5faXNUcmFja2luZ1VwZGF0ZU9wZXJhdGlvbnMpIHtcbiAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KFxuICAgICAgICB0aGlzLl91cGRhdGVPcGVyYXRpb25zLFxuICAgICAgICB0b0FycmF5KHRyYW5zZm9ybS5vcGVyYXRpb25zKVxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIHN1cGVyLl91cGRhdGU8UmVxdWVzdERhdGE+KHRyYW5zZm9ybSwgb3B0aW9ucyk7XG4gIH1cblxuICAvKipcbiAgICogT3ZlcnJpZGUgYF9nZXRUcmFuc2Zvcm1CdWZmZXJgIG9uIGJhc2UgYFN5bmNSZWNvcmRDYWNoZWAgdG8gcHJvdmlkZSBhXG4gICAqIGB0cmFuc2Zvcm1CdWZmZXJgIGlmIGEgY3VzdG9tIG9uZSBoYXNuJ3QgYmVlbiBwcm92aWRlZCB2aWEgdGhlIGNvbnN0cnVjdG9yXG4gICAqIHNldHRpbmcuXG4gICAqL1xuICBwcm90ZWN0ZWQgX2dldFRyYW5zZm9ybUJ1ZmZlcigpOiBSZWNvcmRUcmFuc2Zvcm1CdWZmZXIge1xuICAgIGlmICh0aGlzLl90cmFuc2Zvcm1CdWZmZXIgPT09IHVuZGVmaW5lZCkge1xuICAgICAgY29uc3QgeyBzY2hlbWEsIGtleU1hcCB9ID0gdGhpcztcbiAgICAgIHRoaXMuX3RyYW5zZm9ybUJ1ZmZlciA9IG5ldyBTaW1wbGVSZWNvcmRUcmFuc2Zvcm1CdWZmZXIoe1xuICAgICAgICBzY2hlbWEsXG4gICAgICAgIGtleU1hcFxuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl90cmFuc2Zvcm1CdWZmZXI7XG4gIH1cblxuICBwcm90ZWN0ZWQgX3Jlc2V0SW52ZXJzZVJlbGF0aW9uc2hpcHMoXG4gICAgYmFzZT86IE1lbW9yeUNhY2hlPFFPLCBUTywgUUIsIFRCLCBRUkQsIFRSRD5cbiAgKTogdm9pZCB7XG4gICAgY29uc3QgaW52ZXJzZVJlbGF0aW9uc2hpcHM6IERpY3Q8XG4gICAgICBJbW11dGFibGVNYXA8c3RyaW5nLCBSZWNvcmRSZWxhdGlvbnNoaXBJZGVudGl0eVtdPlxuICAgID4gPSB7fTtcbiAgICBPYmplY3Qua2V5cyh0aGlzLl9zY2hlbWEubW9kZWxzKS5mb3JFYWNoKCh0eXBlKSA9PiB7XG4gICAgICBsZXQgYmFzZVJlbGF0aW9uc2hpcHMgPSBiYXNlICYmIGJhc2UuX2ludmVyc2VSZWxhdGlvbnNoaXBzW3R5cGVdO1xuICAgICAgaW52ZXJzZVJlbGF0aW9uc2hpcHNbdHlwZV0gPSBuZXcgSW1tdXRhYmxlTWFwKGJhc2VSZWxhdGlvbnNoaXBzKTtcbiAgICB9KTtcbiAgICB0aGlzLl9pbnZlcnNlUmVsYXRpb25zaGlwcyA9IGludmVyc2VSZWxhdGlvbnNoaXBzO1xuICB9XG59XG4iXX0=