breeze-client
Version:
Breeze data management for JavaScript clients
192 lines • 26.4 kB
JavaScript
import { DataProperty } from './entity-metadata';
import { EntityKey } from './entity-key';
import { EntityState } from './entity-state';
import { MergeStrategy } from './query-options';
/** @hidden @internal */
export class EntityGroup {
entityManager;
entityType;
_indexMap;
_entities;
_emptyIndexes;
constructor(entityManager, entityType) {
this.entityManager = entityManager;
this.entityType = entityType;
// freeze the entityType after the first instance of this type is either created or queried.
this.entityType.isFrozen = true;
this._indexMap = {};
this._entities = [];
this._emptyIndexes = [];
}
attachEntity(entity, entityState, mergeStrategy) {
// entity should already have an aspect.
let aspect = entity.entityAspect;
if (!aspect._initialized) {
this.entityType._initializeInstance(entity);
}
delete aspect._initialized;
let keyInGroup = aspect.getKey()._keyInGroup;
let ix = this._indexMap[keyInGroup];
if (ix >= 0) {
// safecast because key was found not ix will not return a null
let targetEntity = this._entities[ix];
let targetEntityState = targetEntity.entityAspect.entityState;
let wasUnchanged = targetEntityState.isUnchanged();
if (targetEntity === entity) {
aspect.entityState = entityState;
}
else if (mergeStrategy === MergeStrategy.Disallowed) {
throw new Error("A MergeStrategy of 'Disallowed' does not allow you to attach an entity when an entity with the same key is already attached: " + aspect.getKey());
}
else if (mergeStrategy === MergeStrategy.OverwriteChanges || (mergeStrategy === MergeStrategy.PreserveChanges && wasUnchanged)) {
// unwrapInstance returns an entity with server side property names - so we need to use DataProperty.getRawValueFromServer these when we apply
// the property values back to the target.
let rawServerEntity = this.entityManager.helper.unwrapInstance(entity);
this.entityType._updateTargetFromRaw(targetEntity, rawServerEntity, DataProperty.getRawValueFromServer);
targetEntity.entityAspect.setEntityState(entityState);
}
return targetEntity;
}
else {
if (this._emptyIndexes.length === 0) {
ix = this._entities.push(entity) - 1;
}
else {
ix = this._emptyIndexes.pop();
this._entities[ix] = entity;
}
this._indexMap[keyInGroup] = ix;
aspect.entityState = entityState;
aspect.entityGroup = this;
aspect.entityManager = this.entityManager;
return entity;
}
}
detachEntity(entity) {
// by this point we have already determined that this entity
// belongs to this group.
let aspect = entity.entityAspect;
let keyInGroup = aspect.getKey()._keyInGroup;
let ix = this._indexMap[keyInGroup];
if (ix === undefined) {
// shouldn't happen.
throw new Error("internal error - entity cannot be found in group");
}
delete this._indexMap[keyInGroup];
this._emptyIndexes.push(ix);
this._entities[ix] = null;
return entity;
}
// returns entity based on an entity key defined either as an array of key values or an EntityKey
findEntityByKey(entityKey) {
let keyInGroup;
if (entityKey instanceof EntityKey) {
keyInGroup = entityKey._keyInGroup;
}
else {
keyInGroup = EntityKey.createKeyString(entityKey);
}
let ix = this._indexMap[keyInGroup];
// can't use just (ix) below because 0 is valid
let r = (ix !== undefined) ? this._entities[ix] : undefined;
// coerce null to undefined
return r == null ? undefined : r;
}
hasChanges() {
let entities = this._entities;
let unchanged = EntityState.Unchanged;
for (let i = 0, len = entities.length; i < len; i++) {
let e = entities[i];
if (e && e.entityAspect.entityState !== unchanged) {
return true;
}
}
return false;
}
getChanges() {
let entities = this._entities;
let unchanged = EntityState.Unchanged;
let changes = [];
for (let i = 0, len = entities.length; i < len; i++) {
let e = entities[i];
if (e && e.entityAspect.entityState !== unchanged) {
changes.push(e);
}
}
return changes;
}
getEntities(entityStates) {
let filter = getFilter(entityStates);
return this._entities.filter(filter);
}
_checkOperation(operationName) {
this._entities.forEach(function (entity) {
entity && entity.entityAspect._checkOperation(operationName);
});
// for chaining;
return this;
}
// do not expose this method. It is doing a special purpose INCOMPLETE fast detach operation
// just for the entityManager clear method - the entityGroup will be in an inconsistent state
// after this op, which is ok because it will be thrown away.
// TODO: rename this to be clear that it is UNSAFE...
_clear() {
this._entities.forEach(function (entity) {
if (entity != null) {
entity.entityAspect._detach();
}
});
this._entities = null;
this._indexMap = null;
this._emptyIndexes = null;
}
_updateFkVal(fkProp, oldValue, newValue) {
let fkPropName = fkProp.name;
this._entities.forEach(function (entity) {
if (entity != null) {
if (entity.getProperty(fkPropName) === oldValue) {
entity.setProperty(fkPropName, newValue);
}
}
});
}
_fixupKey(tempValue, realValue) {
// single part keys appear directly in map
let ix = this._indexMap[tempValue];
if (ix === undefined) {
throw new Error("Internal Error in key fixup - unable to locate entity");
}
let entity = this._entities[ix];
let keyPropName = entity.entityType.keyProperties[0].name;
// fks on related entities will automatically get updated by this as well
entity.setProperty(keyPropName, realValue);
delete entity.entityAspect.hasTempKey;
delete this._indexMap[tempValue];
this._indexMap[realValue] = ix;
}
_replaceKey(oldKey, newKey) {
let ix = this._indexMap[oldKey._keyInGroup];
delete this._indexMap[oldKey._keyInGroup];
this._indexMap[newKey._keyInGroup] = ix;
}
}
function getFilter(entityStates) {
if (entityStates.length === 0) {
return function (e) {
return !!e;
};
}
else if (entityStates.length === 1) {
let entityState = entityStates[0];
return function (e) {
return !!e && e.entityAspect.entityState === entityState;
};
}
else {
return function (e) {
return !!e && -1 !== entityStates.indexOf(e.entityAspect.entityState);
};
}
}
// do not expose EntityGroup - internal only
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW50aXR5LWdyb3VwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2VudGl0eS1ncm91cC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQWMsWUFBWSxFQUFHLE1BQU0sbUJBQW1CLENBQUM7QUFDOUQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUN6QyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFN0MsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRWhELHdCQUF3QjtBQUN4QixNQUFNLE9BQU8sV0FBVztJQUN0QixhQUFhLENBQWdCO0lBQzdCLFVBQVUsQ0FBYTtJQUN2QixTQUFTLENBQThCO0lBQ3ZDLFNBQVMsQ0FBb0I7SUFDN0IsYUFBYSxDQUFXO0lBRXhCLFlBQVksYUFBNEIsRUFBRSxVQUFzQjtRQUM5RCxJQUFJLENBQUMsYUFBYSxHQUFHLGFBQWEsQ0FBQztRQUNuQyxJQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQztRQUM3Qiw0RkFBNEY7UUFDNUYsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDO1FBQ2hDLElBQUksQ0FBQyxTQUFTLEdBQUcsRUFBRSxDQUFDO1FBQ3BCLElBQUksQ0FBQyxTQUFTLEdBQUcsRUFBRSxDQUFDO1FBQ3BCLElBQUksQ0FBQyxhQUFhLEdBQUcsRUFBRSxDQUFDO0lBQzFCLENBQUM7SUFHRCxZQUFZLENBQUMsTUFBYyxFQUFFLFdBQXdCLEVBQUUsYUFBNkI7UUFDbEYsd0NBQXdDO1FBQ3hDLElBQUksTUFBTSxHQUFHLE1BQU0sQ0FBQyxZQUFZLENBQUM7UUFFakMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZLEVBQUU7WUFDeEIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxtQkFBbUIsQ0FBQyxNQUFNLENBQUMsQ0FBQztTQUM3QztRQUNELE9BQU8sTUFBTSxDQUFDLFlBQVks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QUFHLEVBQUUsQ0FBQztJQUNqQyxDQUFDO0lBRUQsV0FBVyxDQUFDLE1BQWlCLEVBQUUsTUFBaUI7UUFDOUMsSUFBSSxFQUFFLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDNUMsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUMxQyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsR0FBRyxFQUFFLENBQUM7SUFDMUMsQ0FBQztDQUVGO0FBRUQsU0FBUyxTQUFTLENBQUMsWUFBMkI7SUFDNUMsSUFBSSxZQUFZLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtRQUM3QixPQUFPLFVBQVUsQ0FBUztZQUN4QixPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDYixDQUFDLENBQUM7S0FDSDtTQUFNLElBQUksWUFBWSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7UUFDcEMsSUFBSSxXQUFXLEdBQUcsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2xDLE9BQU8sVUFBVSxDQUFTO1lBQ3hCLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsWUFBWSxDQUFDLFdBQVcsS0FBSyxXQUFXLENBQUM7UUFDM0QsQ0FBQyxDQUFDO0tBQ0g7U0FBTTtRQUNMLE9BQU8sVUFBVSxDQUFTO1lBQ3hCLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsS0FBSyxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDeEUsQ0FBQyxDQUFDO0tBQ0g7QUFDSCxDQUFDO0FBR0QsNENBQTRDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRW50aXR5IH0gZnJvbSAnLi9lbnRpdHktYXNwZWN0JztcclxuaW1wb3J0IHsgRW50aXR5VHlwZSwgRGF0YVByb3BlcnR5ICB9IGZyb20gJy4vZW50aXR5LW1ldGFkYXRhJztcclxuaW1wb3J0IHsgRW50aXR5S2V5IH0gZnJvbSAnLi9lbnRpdHkta2V5JztcclxuaW1wb3J0IHsgRW50aXR5U3RhdGUgfSBmcm9tICcuL2VudGl0eS1zdGF0ZSc7XHJcbmltcG9ydCB7IEVudGl0eU1hbmFnZXIgfSBmcm9tICcuL2VudGl0eS1tYW5hZ2VyJztcclxuaW1wb3J0IHsgTWVyZ2VTdHJhdGVneSB9IGZyb20gJy4vcXVlcnktb3B0aW9ucyc7XHJcblxyXG4vKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuZXhwb3J0IGNsYXNzIEVudGl0eUdyb3VwIHtcclxuICBlbnRpdHlNYW5hZ2VyOiBFbnRpdHlNYW5hZ2VyO1xyXG4gIGVudGl0eVR5cGU6IEVudGl0eVR5cGU7XHJcbiAgX2luZGV4TWFwOiB7IFtpbmRleDogc3RyaW5nXTogbnVtYmVyIH07XHJcbiAgX2VudGl0aWVzOiAoRW50aXR5IHwgbnVsbClbXTtcclxuICBfZW1wdHlJbmRleGVzOiBudW1iZXJbXTtcclxuXHJcbiAgY29uc3RydWN0b3IoZW50aXR5TWFuYWdlcjogRW50aXR5TWFuYWdlciwgZW50aXR5VHlwZTogRW50aXR5VHlwZSkge1xyXG4gICAgdGhpcy5lbnRpdHlNYW5hZ2VyID0gZW50aXR5TWFuYWdlcjtcclxuICAgIHRoaXMuZW50aXR5VHlwZSA9IGVudGl0eVR5cGU7XHJcbiAgICAvLyBmcmVlemUgdGhlIGVudGl0eVR5cGUgYWZ0ZXIgdGhlIGZpcnN0IGluc3RhbmNlIG9mIHRoaXMgdHlwZSBpcyBlaXRoZXIgY3JlYXRlZCBvciBxdWVyaWVkLlxyXG4gICAgdGhpcy5lbnRpdHlUeXBlLmlzRnJvemVuID0gdHJ1ZTtcclxuICAgIHRoaXMuX2luZGV4TWFwID0ge307XHJcbiAgICB0aGlzLl9lbnRpdGllcyA9IFtdO1xyXG4gICAgdGhpcy5fZW1wdHlJbmRleGVzID0gW107XHJcbiAgfVxyXG5cclxuXHJcbiAgYXR0YWNoRW50aXR5KGVudGl0eTogRW50aXR5LCBlbnRpdHlTdGF0ZTogRW50aXR5U3RhdGUsIG1lcmdlU3RyYXRlZ3k/OiBNZXJnZVN0cmF0ZWd5KSB7XHJcbiAgICAvLyBlbnRpdHkgc2hvdWxkIGFscmVhZHkgaGF2ZSBhbiBhc3BlY3QuXHJcbiAgICBsZXQgYXNwZWN0ID0gZW50aXR5LmVudGl0eUFzcGVjdDtcclxuXHJcbiAgICBpZiAoIWFzcGVjdC5faW5pdGlhbGl6ZWQpIHtcclxuICAgICAgdGhpcy5lbnRpdHlUeXBlLl9pbml0aWFsaXplSW5zdGFuY2UoZW50aXR5KTtcclxuICAgIH1cclxuICAgIGRlbGV0ZSBhc3BlY3QuX2luaXRpYWxpemVkO1xyXG5cclxuICAgIGxldCBrZXlJbkdyb3VwID0gYXNwZWN0LmdldEtleSgpLl9rZXlJbkdyb3VwO1xyXG4gICAgbGV0IGl4ID0gdGhpcy5faW5kZXhNYXBba2V5SW5Hcm91cF07XHJcbiAgICBpZiAoaXggPj0gMCkge1xyXG4gICAgICAvLyBzYWZlY2FzdCBiZWNhdXNlIGtleSB3YXMgZm91bmQgbm90IGl4IHdpbGwgbm90IHJldHVybiBhIG51bGxcclxuICAgICAgbGV0IHRhcmdldEVudGl0eSA9IHRoaXMuX2VudGl0aWVzW2l4XSBhcyBFbnRpdHk7XHJcbiAgICAgIGxldCB0YXJnZXRFbnRpdHlTdGF0ZSA9IHRhcmdldEVudGl0eS5lbnRpdHlBc3BlY3QuZW50aXR5U3RhdGU7XHJcbiAgICAgIGxldCB3YXNVbmNoYW5nZWQgPSB0YXJnZXRFbnRpdHlTdGF0ZS5pc1VuY2hhbmdlZCgpO1xyXG4gICAgICBpZiAodGFyZ2V0RW50aXR5ID09PSBlbnRpdHkpIHtcclxuICAgICAgICBhc3BlY3QuZW50aXR5U3RhdGUgPSBlbnRpdHlTdGF0ZTtcclxuICAgICAgfSBlbHNlIGlmIChtZXJnZVN0cmF0ZWd5ID09PSBNZXJnZVN0cmF0ZWd5LkRpc2FsbG93ZWQpIHtcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJBIE1lcmdlU3RyYXRlZ3kgb2YgJ0Rpc2FsbG93ZWQnIGRvZXMgbm90IGFsbG93IHlvdSB0byBhdHRhY2ggYW4gZW50aXR5IHdoZW4gYW4gZW50aXR5IHdpdGggdGhlIHNhbWUga2V5IGlzIGFscmVhZHkgYXR0YWNoZWQ6IFwiICsgYXNwZWN0LmdldEtleSgpKTtcclxuICAgICAgfSBlbHNlIGlmIChtZXJnZVN0cmF0ZWd5ID09PSBNZXJnZVN0cmF0ZWd5Lk92ZXJ3cml0ZUNoYW5nZXMgfHwgKG1lcmdlU3RyYXRlZ3kgPT09IE1lcmdlU3RyYXRlZ3kuUHJlc2VydmVDaGFuZ2VzICYmIHdhc1VuY2hhbmdlZCkpIHtcclxuICAgICAgICAvLyB1bndyYXBJbnN0YW5jZSByZXR1cm5zIGFuIGVudGl0eSB3aXRoIHNlcnZlciBzaWRlIHByb3BlcnR5IG5hbWVzIC0gc28gd2UgbmVlZCB0byB1c2UgRGF0YVByb3BlcnR5LmdldFJhd1ZhbHVlRnJvbVNlcnZlciB0aGVzZSB3aGVuIHdlIGFwcGx5XHJcbiAgICAgICAgLy8gdGhlIHByb3BlcnR5IHZhbHVlcyBiYWNrIHRvIHRoZSB0YXJnZXQuXHJcbiAgICAgICAgbGV0IHJhd1NlcnZlckVudGl0eSA9IHRoaXMuZW50aXR5TWFuYWdlci5oZWxwZXIudW53cmFwSW5zdGFuY2UoZW50aXR5KTtcclxuICAgICAgICB0aGlzLmVudGl0eVR5cGUuX3VwZGF0ZVRhcmdldEZyb21SYXcodGFyZ2V0RW50aXR5LCByYXdTZXJ2ZXJFbnRpdHksIERhdGFQcm9wZXJ0eS5nZXRSYXdWYWx1ZUZyb21TZXJ2ZXIpO1xyXG4gICAgICAgIHRhcmdldEVudGl0eS5lbnRpdHlBc3BlY3Quc2V0RW50aXR5U3RhdGUoZW50aXR5U3RhdGUpO1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiB0YXJnZXRFbnRpdHk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBpZiAodGhpcy5fZW1wdHlJbmRleGVzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgIGl4ID0gdGhpcy5fZW50aXRpZXMucHVzaChlbnRpdHkpIC0gMTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBpeCA9IHRoaXMuX2VtcHR5SW5kZXhlcy5wb3AoKTtcclxuICAgICAgICB0aGlzLl9lbnRpdGllc1tpeF0gPSBlbnRpdHk7XHJcbiAgICAgIH1cclxuICAgICAgdGhpcy5faW5kZXhNYXBba2V5SW5Hcm91cF0gPSBpeDtcclxuICAgICAgYXNwZWN0LmVudGl0eVN0YXRlID0gZW50aXR5U3RhdGU7XHJcbiAgICAgIGFzcGVjdC5lbnRpdHlHcm91cCA9IHRoaXM7XHJcbiAgICAgIGFzcGVjdC5lbnRpdHlNYW5hZ2VyID0gdGhpcy5lbnRpdHlNYW5hZ2VyO1xyXG4gICAgICByZXR1cm4gZW50aXR5O1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgZGV0YWNoRW50aXR5KGVudGl0eTogRW50aXR5KSB7XHJcbiAgICAvLyBieSB0aGlzIHBvaW50IHdlIGhhdmUgYWxyZWFkeSBkZXRlcm1pbmVkIHRoYXQgdGhpcyBlbnRpdHlcclxuICAgIC8vIGJlbG9uZ3MgdG8gdGhpcyBncm91cC5cclxuICAgIGxldCBhc3BlY3QgPSBlbnRpdHkuZW50aXR5QXNwZWN0O1xyXG4gICAgbGV0IGtleUluR3JvdXAgPSBhc3BlY3QuZ2V0S2V5KCkuX2tleUluR3JvdXA7XHJcbiAgICBsZXQgaXggPSB0aGlzLl9pbmRleE1hcFtrZXlJbkdyb3VwXTtcclxuICAgIGlmIChpeCA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgIC8vIHNob3VsZG4ndCBoYXBwZW4uXHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcImludGVybmFsIGVycm9yIC0gZW50aXR5IGNhbm5vdCBiZSBmb3VuZCBpbiBncm91cFwiKTtcclxuICAgIH1cclxuICAgIGRlbGV0ZSB0aGlzLl9pbmRleE1hcFtrZXlJbkdyb3VwXTtcclxuICAgIHRoaXMuX2VtcHR5SW5kZXhlcy5wdXNoKGl4KTtcclxuICAgIHRoaXMuX2VudGl0aWVzW2l4XSA9IG51bGw7XHJcbiAgICByZXR1cm4gZW50aXR5O1xyXG4gIH1cclxuXHJcblxyXG4gIC8vIHJldHVybnMgZW50aXR5IGJhc2VkIG9uIGFuIGVudGl0eSBrZXkgZGVmaW5lZCBlaXRoZXIgYXMgYW4gYXJyYXkgb2Yga2V5IHZhbHVlcyBvciBhbiBFbnRpdHlLZXlcclxuICBmaW5kRW50aXR5QnlLZXkoZW50aXR5S2V5OiBFbnRpdHlLZXkpIHtcclxuICAgIGxldCBrZXlJbkdyb3VwOiBzdHJpbmc7XHJcbiAgICBpZiAoZW50aXR5S2V5IGluc3RhbmNlb2YgRW50aXR5S2V5KSB7XHJcbiAgICAgIGtleUluR3JvdXAgPSBlbnRpdHlLZXkuX2tleUluR3JvdXA7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBrZXlJbkdyb3VwID0gRW50aXR5S2V5LmNyZWF0ZUtleVN0cmluZyhlbnRpdHlLZXkpO1xyXG4gICAgfVxyXG4gICAgbGV0IGl4ID0gdGhpcy5faW5kZXhNYXBba2V5SW5Hcm91cF07XHJcbiAgICAvLyBjYW4ndCB1c2UganVzdCAoaXgpIGJlbG93IGJlY2F1c2UgMCBpcyB2YWxpZFxyXG4gICAgbGV0IHIgPSAoaXggIT09IHVuZGVmaW5lZCkgPyB0aGlzLl9lbnRpdGllc1tpeF0gOiB1bmRlZmluZWQ7XHJcbiAgICAvLyBjb2VyY2UgbnVsbCB0byB1bmRlZmluZWRcclxuICAgIHJldHVybiByID09IG51bGwgPyB1bmRlZmluZWQgOiByO1xyXG4gIH1cclxuXHJcbiAgaGFzQ2hhbmdlcygpIHtcclxuICAgIGxldCBlbnRpdGllcyA9IHRoaXMuX2VudGl0aWVzO1xyXG4gICAgbGV0IHVuY2hhbmdlZCA9IEVudGl0eVN0YXRlLlVuY2hhbmdlZDtcclxuICAgIGZvciAobGV0IGkgPSAwLCBsZW4gPSBlbnRpdGllcy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG4gICAgICBsZXQgZSA9IGVudGl0aWVzW2ldO1xyXG4gICAgICBpZiAoZSAmJiBlLmVudGl0eUFzcGVjdC5lbnRpdHlTdGF0ZSAhPT0gdW5jaGFuZ2VkKSB7XHJcbiAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiBmYWxzZTtcclxuICB9XHJcblxyXG4gIGdldENoYW5nZXMoKSB7XHJcbiAgICBsZXQgZW50aXRpZXMgPSB0aGlzLl9lbnRpdGllcztcclxuICAgIGxldCB1bmNoYW5nZWQgPSBFbnRpdHlTdGF0ZS5VbmNoYW5nZWQ7XHJcbiAgICBsZXQgY2hhbmdlczogRW50aXR5W10gPSBbXTtcclxuICAgIGZvciAobGV0IGkgPSAwLCBsZW4gPSBlbnRpdGllcy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG4gICAgICBsZXQgZSA9IGVudGl0aWVzW2ldO1xyXG4gICAgICBpZiAoZSAmJiBlLmVudGl0eUFzcGVjdC5lbnRpdHlTdGF0ZSAhPT0gdW5jaGFuZ2VkKSB7XHJcbiAgICAgICAgY2hhbmdlcy5wdXNoKGUpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gY2hhbmdlcztcclxuICB9XHJcblxyXG4gIGdldEVudGl0aWVzKGVudGl0eVN0YXRlczogRW50aXR5U3RhdGVbXSkge1xyXG4gICAgbGV0IGZpbHRlciA9IGdldEZpbHRlcihlbnRpdHlTdGF0ZXMpO1xyXG4gICAgcmV0dXJuIHRoaXMuX2VudGl0aWVzLmZpbHRlcihmaWx0ZXIpIGFzIEVudGl0eVtdO1xyXG4gIH1cclxuXHJcbiAgX2NoZWNrT3BlcmF0aW9uKG9wZXJhdGlvbk5hbWU6IHN0cmluZykge1xyXG4gICAgdGhpcy5fZW50aXRpZXMuZm9yRWFjaChmdW5jdGlvbiAoZW50aXR5KSB7XHJcbiAgICAgIGVudGl0eSAmJiBlbnRpdHkuZW50aXR5QXNwZWN0Ll9jaGVja09wZXJhdGlvbihvcGVyYXRpb25OYW1lKTtcclxuICAgIH0pO1xyXG4gICAgLy8gZm9yIGNoYWluaW5nO1xyXG4gICAgcmV0dXJuIHRoaXM7XHJcbiAgfVxyXG5cclxuICAvLyBkbyBub3QgZXhwb3NlIHRoaXMgbWV0aG9kLiBJdCBpcyBkb2luZyBhIHNwZWNpYWwgcHVycG9zZSBJTkNPTVBMRVRFIGZhc3QgZGV0YWNoIG9wZXJhdGlvblxyXG4gIC8vIGp1c3QgZm9yIHRoZSBlbnRpdHlNYW5hZ2VyIGNsZWFyIG1ldGhvZCAtIHRoZSBlbnRpdHlHcm91cCB3aWxsIGJlIGluIGFuIGluY29uc2lzdGVudCBzdGF0ZVxyXG4gIC8vIGFmdGVyIHRoaXMgb3AsIHdoaWNoIGlzIG9rIGJlY2F1c2UgaXQgd2lsbCBiZSB0aHJvd24gYXdheS5cclxuICAvLyBUT0RPOiByZW5hbWUgdGhpcyB0byBiZSBjbGVhciB0aGF0IGl0IGlzIFVOU0FGRS4uLlxyXG4gIF9jbGVhcigpIHtcclxuICAgIHRoaXMuX2VudGl0aWVzLmZvckVhY2goZnVuY3Rpb24gKGVudGl0eSkge1xyXG4gICAgICBpZiAoZW50aXR5ICE9IG51bGwpIHtcclxuICAgICAgICBlbnRpdHkuZW50aXR5QXNwZWN0Ll9kZXRhY2goKTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgICAodGhpcyBhcyBhbnkpLl9lbnRpdGllcyA9IG51bGw7XHJcbiAgICAodGhpcyBhcyBhbnkpLl9pbmRleE1hcCA9IG51bGw7XHJcbiAgICAodGhpcyBhcyBhbnkpLl9lbXB0eUluZGV4ZXMgPSBudWxsO1xyXG4gIH1cclxuXHJcbiAgX3VwZGF0ZUZrVmFsKGZrUHJvcDogRGF0YVByb3BlcnR5LCBvbGRWYWx1ZTogYW55LCBuZXdWYWx1ZTogYW55KSB7XHJcbiAgICBsZXQgZmtQcm9wTmFtZSA9IGZrUHJvcC5uYW1lO1xyXG4gICAgdGhpcy5fZW50aXRpZXMuZm9yRWFjaChmdW5jdGlvbiAoZW50aXR5KSB7XHJcbiAgICAgIGlmIChlbnRpdHkgIT0gbnVsbCkge1xyXG4gICAgICAgIGlmIChlbnRpdHkuZ2V0UHJvcGVydHkoZmtQcm9wTmFtZSkgPT09IG9sZFZhbHVlKSB7XHJcbiAgICAgICAgICBlbnRpdHkuc2V0UHJvcGVydHkoZmtQcm9wTmFtZSwgbmV3VmFsdWUpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBfZml4dXBLZXkodGVtcFZhbHVlOiBhbnksIHJlYWxWYWx1ZTogYW55KSB7XHJcbiAgICAvLyBzaW5nbGUgcGFydCBrZXlzIGFwcGVhciBkaXJlY3RseSBpbiBtYXBcclxuICAgIGxldCBpeCA9IHRoaXMuX2luZGV4TWFwW3RlbXBWYWx1ZV07XHJcbiAgICBpZiAoaXggPT09IHVuZGVmaW5lZCkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnRlcm5hbCBFcnJvciBpbiBrZXkgZml4dXAgLSB1bmFibGUgdG8gbG9jYXRlIGVudGl0eVwiKTtcclxuICAgIH1cclxuICAgIGxldCBlbnRpdHkgPSB0aGlzLl9lbnRpdGllc1tpeF0gYXMgRW50aXR5O1xyXG4gICAgbGV0IGtleVByb3BOYW1lID0gZW50aXR5LmVudGl0eVR5cGUua2V5UHJvcGVydGllc1swXS5uYW1lO1xyXG4gICAgLy8gZmtzIG9uIHJlbGF0ZWQgZW50aXRpZXMgd2lsbCBhdXRvbWF0aWNhbGx5IGdldCB1cGRhdGVkIGJ5IHRoaXMgYXMgd2VsbFxyXG4gICAgZW50aXR5LnNldFByb3BlcnR5KGtleVByb3BOYW1lLCByZWFsVmFsdWUpO1xyXG4gICAgZGVsZXRlIGVudGl0eS5lbnRpdHlBc3BlY3QuaGFzVGVtcEtleTtcclxuICAgIGRlbGV0ZSB0aGlzLl9pbmRleE1hcFt0ZW1wVmFsdWVdO1xyXG4gICAgdGhpcy5faW5kZXhNYXBbcmVhbFZhbHVlXSA9IGl4O1xyXG4gIH1cclxuXHJcbiAgX3JlcGxhY2VLZXkob2xkS2V5OiBFbnRpdHlLZXksIG5ld0tleTogRW50aXR5S2V5KSB7XHJcbiAgICBsZXQgaXggPSB0aGlzLl9pbmRleE1hcFtvbGRLZXkuX2tleUluR3JvdXBdO1xyXG4gICAgZGVsZXRlIHRoaXMuX2luZGV4TWFwW29sZEtleS5fa2V5SW5Hcm91cF07XHJcbiAgICB0aGlzLl9pbmRleE1hcFtuZXdLZXkuX2tleUluR3JvdXBdID0gaXg7XHJcbiAgfVxyXG5cclxufVxyXG5cclxuZnVuY3Rpb24gZ2V0RmlsdGVyKGVudGl0eVN0YXRlczogRW50aXR5U3RhdGVbXSkge1xyXG4gIGlmIChlbnRpdHlTdGF0ZXMubGVuZ3RoID09PSAwKSB7XHJcbiAgICByZXR1cm4gZnVuY3Rpb24gKGU6IEVudGl0eSkge1xyXG4gICAgICByZXR1cm4gISFlO1xyXG4gICAgfTtcclxuICB9IGVsc2UgaWYgKGVudGl0eVN0YXRlcy5sZW5ndGggPT09IDEpIHtcclxuICAgIGxldCBlbnRpdHlTdGF0ZSA9IGVudGl0eVN0YXRlc1swXTtcclxuICAgIHJldHVybiBmdW5jdGlvbiAoZTogRW50aXR5KSB7XHJcbiAgICAgIHJldHVybiAhIWUgJiYgZS5lbnRpdHlBc3BlY3QuZW50aXR5U3RhdGUgPT09IGVudGl0eVN0YXRlO1xyXG4gICAgfTtcclxuICB9IGVsc2Uge1xyXG4gICAgcmV0dXJuIGZ1bmN0aW9uIChlOiBFbnRpdHkpIHtcclxuICAgICAgcmV0dXJuICEhZSAmJiAtMSAhPT0gZW50aXR5U3RhdGVzLmluZGV4T2YoZS5lbnRpdHlBc3BlY3QuZW50aXR5U3RhdGUpO1xyXG4gICAgfTtcclxuICB9XHJcbn1cclxuXHJcblxyXG4vLyBkbyBub3QgZXhwb3NlIEVudGl0eUdyb3VwIC0gaW50ZXJuYWwgb25seVxyXG5cclxuXHJcbiJdfQ==