breeze-client
Version:
Breeze data management for JavaScript clients
232 lines • 34 kB
JavaScript
import { core } from './core';
import { assertParam } from './assert-param';
import { BreezeEvent } from './event';
export class InterfaceDef {
name;
defaultInstance;
/** @hidden @internal */
_implMap;
constructor(name) {
this.name = name;
this.defaultInstance = undefined;
this._implMap = {};
}
/** Define an implementation of the given adaptername */
registerCtor(adapterName, ctor) {
this._implMap[adapterName.toLowerCase()] = { ctor: ctor, defaultInstance: undefined };
}
/** Return the definition for the given adapterName */
getImpl(adapterName) {
return this._implMap[adapterName.toLowerCase()];
}
/** Return the first implementation for this InterfaceDef */
getFirstImpl() {
let kv = core.objectFirst(this._implMap, function () {
return true;
});
return kv ? kv.value : null;
}
getDefaultInstance() {
return this.defaultInstance;
}
}
export class BreezeConfig {
functionRegistry = {};
typeRegistry = {};
objectRegistry = {};
interfaceInitialized;
stringifyPad = '';
/** whether to prohibit eval() and Function() in breeze code */
noEval;
/** @hidden @internal */
_interfaceRegistry; // will be set in adapter-interfaces. untyped here to avoid circularity issues.
constructor() {
this.interfaceInitialized = new BreezeEvent("interfaceInitialized", this);
if (this.noEval === undefined) {
try {
Error['x'] = Function('');
this.noEval = false; // eval succeeded
}
catch {
this.noEval = true; // eval failed, probably due to CSP
}
}
}
/**
Method use to register implementations of standard breeze interfaces. Calls to this method are usually
made as the last step within an adapter implementation.
@method registerAdapter
@param interfaceName {String} - one of the following interface names: "ajax", "dataService", "modelLibrary", "uriBuilder"
@param adapterCtor {Function} - an ctor function that returns an instance of the specified interface.
**/
registerAdapter(interfaceName, adapterCtor) {
assertParam(interfaceName, "interfaceName").isNonEmptyString().check();
assertParam(adapterCtor, "adapterCtor").isFunction().check();
// this impl will be thrown away after the name is retrieved.
let impl = new adapterCtor();
let implName = impl.name;
if (!implName) {
throw new Error("Unable to locate a 'name' property on the constructor passed into the 'registerAdapter' call.");
}
let idef = this.getInterfaceDef(interfaceName);
idef.registerCtor(implName, adapterCtor);
}
/**
Returns the ctor function used to implement a specific interface with a specific adapter name.
@method getAdapter
@param interfaceName {String} One of the following interface names: "ajax", "dataService", "modelLibrary", "uriBuilder"
@param [adapterName] {String} The name of any previously registered adapter. If this parameter is omitted then
this method returns the "default" adapter for this interface. If there is no default adapter, then a null is returned.
@return {Function|null} Returns either a ctor function or null.
**/
getAdapter(interfaceName, adapterName) {
let idef = this.getInterfaceDef(interfaceName);
if (adapterName) {
let impl = idef.getImpl(adapterName);
return impl ? impl.ctor : null;
}
else {
return idef.defaultInstance ? idef.defaultInstance._$impl.ctor : null;
}
}
/**
Initializes a single adapter implementation. Initialization means either newing a instance of the
specified interface and then calling "initialize" on it or simply calling "initialize" on the instance
if it already exists.
@method initializeAdapterInstance
@param interfaceName {String} The name of the interface to which the adapter to initialize belongs.
@param adapterName {String} - The name of a previously registered adapter to initialize.
@param [isDefault=true] {Boolean} - Whether to make this the default "adapter" for this interface.
@return {an instance of the specified adapter}
**/
initializeAdapterInstance(interfaceName, adapterName, isDefault = true) {
isDefault = isDefault === undefined ? true : isDefault;
assertParam(interfaceName, "interfaceName").isNonEmptyString().check();
assertParam(adapterName, "adapterName").isNonEmptyString().check();
assertParam(isDefault, "isDefault").isBoolean().check();
let idef = this.getInterfaceDef(interfaceName);
let impl = idef.getImpl(adapterName);
if (!impl) {
throw new Error("Unregistered adapter. Interface: " + interfaceName + " AdapterName: " + adapterName);
}
return this._initializeAdapterInstanceCore(idef, impl, isDefault);
}
/**
Returns the adapter instance corresponding to the specified interface and adapter names.
@method getAdapterInstance
@param interfaceName {String} The name of the interface.
@param [adapterName] {String} - The name of a previously registered adapter. If this parameter is
omitted then the default implementation of the specified interface is returned. If there is
no defaultInstance of this interface, then the first registered instance of this interface is returned.
@return {an instance of the specified adapter}
@internal
**/
getAdapterInstance(interfaceName, adapterName) {
let idef = this.getInterfaceDef(interfaceName);
let impl;
let isDefault = adapterName == null || adapterName === "";
if (isDefault) {
if (idef.defaultInstance)
return idef.defaultInstance;
impl = idef.getFirstImpl();
}
else {
impl = idef.getImpl(adapterName);
}
if (!impl)
return undefined;
if (impl.defaultInstance) {
return impl.defaultInstance;
}
else {
return this._initializeAdapterInstanceCore(idef, impl, isDefault);
}
}
/** this is needed for reflection purposes when deserializing an object that needs a fn or ctor.
Used to register validators. */
registerFunction(fn, fnName) {
assertParam(fn, "fn").isFunction().check();
assertParam(fnName, "fnName").isString().check();
if (fn.prototype) {
fn.prototype._$fnName = fnName;
}
this.functionRegistry[fnName] = fn;
}
registerType(ctor, typeName) {
assertParam(ctor, "ctor").isFunction().check();
assertParam(typeName, "typeName").isString().check();
if (ctor.prototype) {
ctor.prototype._$typeName = typeName;
}
this.typeRegistry[typeName] = ctor;
}
getRegisteredFunction(fnName) {
return this.functionRegistry[fnName];
}
getInterfaceDef(interfaceName) {
let lcName = interfaceName.toLowerCase();
// source may be null
let kv = core.objectFirst(this._interfaceRegistry || {}, function (k, v) {
return k.toLowerCase() === lcName;
});
if (!kv) {
throw new Error("Unknown interface name: " + interfaceName);
}
return kv.value;
}
/** @deprecated @internal no-op kept for backward compatibility */
setQ(q) {
console && console.warn("setQ does nothing; ES6 Promise support is required - use a shim if necessary.");
}
/** @hidden @internal */
_storeObject(obj, type, name) {
// uncomment this if we make this public.
//assertParam(obj, "obj").isObject().check();
//assertParam(name, "objName").isString().check();
let key = (typeof (type) === "string" ? type : type.prototype._$typeName) + "." + name;
this.objectRegistry[key] = obj;
}
/** @hidden @internal */
_fetchObject(type, name) {
if (!name)
return undefined;
let key = (typeof (type) === "string" ? type : type.prototype._$typeName) + "." + name;
let result = this.objectRegistry[key];
if (!result) {
throw new Error("Unable to locate a registered object by the name: " + key);
}
return result;
}
/** @hidden @internal */
_initializeAdapterInstanceCore(interfaceDef, impl, isDefault) {
let instance;
let inst = impl.defaultInstance;
if (!inst) {
instance = new (impl.ctor)();
impl.defaultInstance = instance;
instance._$impl = impl;
}
else {
instance = inst;
}
instance.initialize();
if (isDefault) {
// next line needs to occur before any recomposition
interfaceDef.defaultInstance = instance;
}
// recomposition of other impls will occur here.
this.interfaceInitialized.publish({ interfaceName: interfaceDef.name, instance: instance, isDefault: true });
if (instance.checkForRecomposition != null) {
// now register for own dependencies.
this.interfaceInitialized.subscribe((interfaceInitializedArgs) => {
// TODO: why '!'s needed here for typescript to compile correctly???
instance.checkForRecomposition(interfaceInitializedArgs);
});
}
return instance;
}
}
export const config = new BreezeConfig();
// legacy
core.config = config;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvbmZpZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sUUFBUSxDQUFDO0FBQzlCLE9BQU8sRUFBRSxXQUFXLEVBQUcsTUFBTSxnQkFBZ0IsQ0FBQztBQUM5QyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBU3RDLE1BQU0sT0FBTyxZQUFZO0lBRXJCLElBQUksQ0FBUztJQUNiLGVBQWUsQ0FBSztJQUNwQix3QkFBd0I7SUFDeEIsUUFBUSxDQUE4QjtJQUV0QyxZQUFZLElBQVk7UUFDcEIsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLGVBQWUsR0FBRyxTQUFTLENBQUM7UUFDakMsSUFBSSxDQUFDLFFBQVEsR0FBRyxFQUFFLENBQUM7SUFDdkIsQ0FBQztJQUVELHdEQUF3RDtJQUN4RCxZQUFZLENBQUMsV0FBbUIsRUFBRSxJQUFvQjtRQUNsRCxJQUFJLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxlQUFlLEVBQUUsU0FBUyxFQUFFLENBQUM7SUFDMUYsQ0FBQztJQUVELHNEQUFzRDtJQUN0RCxPQUFPLENBQUMsV0FBbUI7UUFDdkIsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO0lBQ3BELENBQUM7SUFFRCw0REFBNEQ7SUFDNUQsWUFBWTtRQUNSLElBQUksRUFBRSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRTtZQUNyQyxPQUFPLElBQUksQ0FBQztRQUNoQixDQUFDLENBQUMsQ0FBQztRQUNILE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FB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QUFDLE1BQU0sTUFBTSxHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7QUFFekMsU0FBUztBQUNSLElBQVksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY29yZSB9IGZyb20gJy4vY29yZSc7XHJcbmltcG9ydCB7IGFzc2VydFBhcmFtICB9IGZyb20gJy4vYXNzZXJ0LXBhcmFtJztcclxuaW1wb3J0IHsgQnJlZXplRXZlbnQgfSBmcm9tICcuL2V2ZW50JztcclxuXHJcbi8qKiBAaGlkZGVuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgQWRhcHRlckN0b3I8VCBleHRlbmRzIEJhc2VBZGFwdGVyPiB7IG5ldyAoLi4uYXJnczogYW55W10pOiBUOyB9XHJcbi8qKiBAaGlkZGVuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgSURlZjxUIGV4dGVuZHMgQmFzZUFkYXB0ZXI+IHsgY3RvcjogQWRhcHRlckN0b3I8VD47IGRlZmF1bHRJbnN0YW5jZT86IFQ7IH1cclxuXHJcbmV4cG9ydCB0eXBlIEFkYXB0ZXJUeXBlID0gJ2RhdGFTZXJ2aWNlJ3wnbW9kZWxMaWJyYXJ5J3wnYWpheCd8J3VyaUJ1aWxkZXInO1xyXG5cclxuZXhwb3J0IGNsYXNzIEludGVyZmFjZURlZjxUIGV4dGVuZHMgQmFzZUFkYXB0ZXI+IHtcclxuXHJcbiAgICBuYW1lOiBzdHJpbmc7XHJcbiAgICBkZWZhdWx0SW5zdGFuY2U/OiBUO1xyXG4gICAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgICBfaW1wbE1hcDogeyBbbmFtZTogc3RyaW5nXTogSURlZjxUPiB9O1xyXG5cclxuICAgIGNvbnN0cnVjdG9yKG5hbWU6IHN0cmluZykge1xyXG4gICAgICAgIHRoaXMubmFtZSA9IG5hbWU7XHJcbiAgICAgICAgdGhpcy5kZWZhdWx0SW5zdGFuY2UgPSB1bmRlZmluZWQ7XHJcbiAgICAgICAgdGhpcy5faW1wbE1hcCA9IHt9O1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBEZWZpbmUgYW4gaW1wbGVtZW50YXRpb24gb2YgdGhlIGdpdmVuIGFkYXB0ZXJuYW1lICovXHJcbiAgICByZWdpc3RlckN0b3IoYWRhcHRlck5hbWU6IHN0cmluZywgY3RvcjogQWRhcHRlckN0b3I8VD4pOiB2b2lkIHtcclxuICAgICAgICB0aGlzLl9pbXBsTWFwW2FkYXB0ZXJOYW1lLnRvTG93ZXJDYXNlKCldID0geyBjdG9yOiBjdG9yLCBkZWZhdWx0SW5zdGFuY2U6IHVuZGVmaW5lZCB9O1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBSZXR1cm4gdGhlIGRlZmluaXRpb24gZm9yIHRoZSBnaXZlbiBhZGFwdGVyTmFtZSAqL1xyXG4gICAgZ2V0SW1wbChhZGFwdGVyTmFtZTogc3RyaW5nKTogSURlZjxUPiB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX2ltcGxNYXBbYWRhcHRlck5hbWUudG9Mb3dlckNhc2UoKV07XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIFJldHVybiB0aGUgZmlyc3QgaW1wbGVtZW50YXRpb24gZm9yIHRoaXMgSW50ZXJmYWNlRGVmICovXHJcbiAgICBnZXRGaXJzdEltcGwoKTogSURlZjxUPiB7XHJcbiAgICAgICAgbGV0IGt2ID0gY29yZS5vYmplY3RGaXJzdCh0aGlzLl9pbXBsTWFwLCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIHJldHVybiBrdiA/IGt2LnZhbHVlIDogbnVsbDtcclxuICAgIH1cclxuXHJcbiAgICBnZXREZWZhdWx0SW5zdGFuY2UoKSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuZGVmYXVsdEluc3RhbmNlIGFzIFQ7XHJcbiAgICB9XHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgQmFzZUFkYXB0ZXIge1xyXG4gICAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgICBfJGltcGw/OiBhbnk7XHJcbiAgICBuYW1lOiBzdHJpbmc7XHJcbiAgICBpbml0aWFsaXplKCk6IHZvaWQ7XHJcbiAgICBjaGVja0ZvclJlY29tcG9zaXRpb24/OiAoY29udGV4dDogYW55KSA9PiB2b2lkO1xyXG59XHJcblxyXG5leHBvcnQgY2xhc3MgQnJlZXplQ29uZmlnIHtcclxuICAgIGZ1bmN0aW9uUmVnaXN0cnkgPSB7fTtcclxuICAgIHR5cGVSZWdpc3RyeSA9IHt9O1xyXG4gICAgb2JqZWN0UmVnaXN0cnkgPSB7fTtcclxuICAgIGludGVyZmFjZUluaXRpYWxpemVkOiBCcmVlemVFdmVudDx7IGludGVyZmFjZU5hbWU6IHN0cmluZywgaW5zdGFuY2U6IEJhc2VBZGFwdGVyLCBpc0RlZmF1bHQ6IGJvb2xlYW4gfT47XHJcblxyXG4gICAgc3RyaW5naWZ5UGFkID0gJyc7XHJcbiAgICAvKiogd2hldGhlciB0byBwcm9oaWJpdCBldmFsKCkgYW5kIEZ1bmN0aW9uKCkgaW4gYnJlZXplIGNvZGUgKi9cclxuICAgIG5vRXZhbDogYm9vbGVhbjtcclxuICAgIC8qKiBAaGlkZGVuIEBpbnRlcm5hbCAqL1xyXG4gICAgX2ludGVyZmFjZVJlZ2lzdHJ5OiBhbnk7ICAvLyB3aWxsIGJlIHNldCBpbiBhZGFwdGVyLWludGVyZmFjZXMuIHVudHlwZWQgaGVyZSB0byBhdm9pZCBjaXJjdWxhcml0eSBpc3N1ZXMuXHJcblxyXG4gICAgY29uc3RydWN0b3IoKSB7XHJcbiAgICAgICAgdGhpcy5pbnRlcmZhY2VJbml0aWFsaXplZCA9IG5ldyBCcmVlemVFdmVudChcImludGVyZmFjZUluaXRpYWxpemVkXCIsIHRoaXMpO1xyXG4gICAgICAgIGlmICh0aGlzLm5vRXZhbCA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICBFcnJvclsneCddID0gRnVuY3Rpb24oJycpO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5ub0V2YWwgPSBmYWxzZTsgLy8gZXZhbCBzdWNjZWVkZWRcclxuICAgICAgICAgICAgfSBjYXRjaCB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLm5vRXZhbCA9IHRydWU7IC8vIGV2YWwgZmFpbGVkLCBwcm9iYWJseSBkdWUgdG8gQ1NQXHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgXHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICBNZXRob2QgdXNlIHRvIHJlZ2lzdGVyIGltcGxlbWVudGF0aW9ucyBvZiBzdGFuZGFyZCBicmVlemUgaW50ZXJmYWNlcy4gIENhbGxzIHRvIHRoaXMgbWV0aG9kIGFyZSB1c3VhbGx5XHJcbiAgICBtYWRlIGFzIHRoZSBsYXN0IHN0ZXAgd2l0aGluIGFuIGFkYXB0ZXIgaW1wbGVtZW50YXRpb24uXHJcbiAgICBAbWV0aG9kIHJlZ2lzdGVyQWRhcHRlclxyXG4gICAgQHBhcmFtIGludGVyZmFjZU5hbWUge1N0cmluZ30gLSBvbmUgb2YgdGhlIGZvbGxvd2luZyBpbnRlcmZhY2UgbmFtZXM6IFwiYWpheFwiLCBcImRhdGFTZXJ2aWNlXCIsIFwibW9kZWxMaWJyYXJ5XCIsIFwidXJpQnVpbGRlclwiXHJcbiAgICBAcGFyYW0gYWRhcHRlckN0b3Ige0Z1bmN0aW9ufSAtIGFuIGN0b3IgZnVuY3Rpb24gdGhhdCByZXR1cm5zIGFuIGluc3RhbmNlIG9mIHRoZSBzcGVjaWZpZWQgaW50ZXJmYWNlLlxyXG4gICAgKiovXHJcbiAgICByZWdpc3RlckFkYXB0ZXI8VCBleHRlbmRzIEJhc2VBZGFwdGVyPihpbnRlcmZhY2VOYW1lOiBBZGFwdGVyVHlwZSwgYWRhcHRlckN0b3I6IEFkYXB0ZXJDdG9yPFQ+KSB7XHJcbiAgICAgICAgYXNzZXJ0UGFyYW0oaW50ZXJmYWNlTmFtZSwgXCJpbnRlcmZhY2VOYW1lXCIpLmlzTm9uRW1wdHlTdHJpbmcoKS5jaGVjaygpO1xyXG4gICAgICAgIGFzc2VydFBhcmFtKGFkYXB0ZXJDdG9yLCBcImFkYXB0ZXJDdG9yXCIpLmlzRnVuY3Rpb24oKS5jaGVjaygpO1xyXG4gICAgICAgIC8vIHRoaXMgaW1wbCB3aWxsIGJlIHRocm93biBhd2F5IGFmdGVyIHRoZSBuYW1lIGlzIHJldHJpZXZlZC5cclxuICAgICAgICBsZXQgaW1wbCA9IG5ldyBhZGFwdGVyQ3RvcigpO1xyXG4gICAgICAgIGxldCBpbXBsTmFtZSA9IGltcGwubmFtZTtcclxuICAgICAgICBpZiAoIWltcGxOYW1lKSB7XHJcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlVuYWJsZSB0byBsb2NhdGUgYSAnbmFtZScgcHJvcGVydHkgb24gdGhlIGNvbnN0cnVjdG9yIHBhc3NlZCBpbnRvIHRoZSAncmVnaXN0ZXJBZGFwdGVyJyBjYWxsLlwiKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgbGV0IGlkZWYgPSB0aGlzLmdldEludGVyZmFjZURlZihpbnRlcmZhY2VOYW1lKTtcclxuICAgICAgICBpZGVmLnJlZ2lzdGVyQ3RvcihpbXBsTmFtZSwgYWRhcHRlckN0b3IpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgUmV0dXJucyB0aGUgY3RvciBmdW5jdGlvbiB1c2VkIHRvIGltcGxlbWVudCBhIHNwZWNpZmljIGludGVyZmFjZSB3aXRoIGEgc3BlY2lmaWMgYWRhcHRlciBuYW1lLlxyXG4gICAgQG1ldGhvZCBnZXRBZGFwdGVyXHJcbiAgICBAcGFyYW0gaW50ZXJmYWNlTmFtZSB7U3RyaW5nfSBPbmUgb2YgdGhlIGZvbGxvd2luZyBpbnRlcmZhY2UgbmFtZXM6IFwiYWpheFwiLCBcImRhdGFTZXJ2aWNlXCIsIFwibW9kZWxMaWJyYXJ5XCIsIFwidXJpQnVpbGRlclwiXHJcbiAgICBAcGFyYW0gW2FkYXB0ZXJOYW1lXSB7U3RyaW5nfSBUaGUgbmFtZSBvZiBhbnkgcHJldmlvdXNseSByZWdpc3RlcmVkIGFkYXB0ZXIuIElmIHRoaXMgcGFyYW1ldGVyIGlzIG9taXR0ZWQgdGhlblxyXG4gICAgdGhpcyBtZXRob2QgcmV0dXJucyB0aGUgXCJkZWZhdWx0XCIgYWRhcHRlciBmb3IgdGhpcyBpbnRlcmZhY2UuIElmIHRoZXJlIGlzIG5vIGRlZmF1bHQgYWRhcHRlciwgdGhlbiBhIG51bGwgaXMgcmV0dXJuZWQuXHJcbiAgICBAcmV0dXJuIHtGdW5jdGlvbnxudWxsfSBSZXR1cm5zIGVpdGhlciBhIGN0b3IgZnVuY3Rpb24gb3IgbnVsbC5cclxuICAgICoqL1xyXG4gICAgZ2V0QWRhcHRlcihpbnRlcmZhY2VOYW1lOiBBZGFwdGVyVHlwZSwgYWRhcHRlck5hbWU6IHN0cmluZykge1xyXG4gICAgICAgIGxldCBpZGVmID0gdGhpcy5nZXRJbnRlcmZhY2VEZWYoaW50ZXJmYWNlTmFtZSk7XHJcbiAgICAgICAgaWYgKGFkYXB0ZXJOYW1lKSB7XHJcbiAgICAgICAgICAgIGxldCBpbXBsID0gaWRlZi5nZXRJbXBsKGFkYXB0ZXJOYW1lKTtcclxuICAgICAgICAgICAgcmV0dXJuIGltcGwgPyBpbXBsLmN0b3IgOiBudWxsO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHJldHVybiBpZGVmLmRlZmF1bHRJbnN0YW5jZSA/IGlkZWYuZGVmYXVsdEluc3RhbmNlLl8kaW1wbC5jdG9yIDogbnVsbDtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICBJbml0aWFsaXplcyBhIHNpbmdsZSBhZGFwdGVyIGltcGxlbWVudGF0aW9uLiBJbml0aWFsaXphdGlvbiBtZWFucyBlaXRoZXIgbmV3aW5nIGEgaW5zdGFuY2Ugb2YgdGhlXHJcbiAgICBzcGVjaWZpZWQgaW50ZXJmYWNlIGFuZCB0aGVuIGNhbGxpbmcgXCJpbml0aWFsaXplXCIgb24gaXQgb3Igc2ltcGx5IGNhbGxpbmcgXCJpbml0aWFsaXplXCIgb24gdGhlIGluc3RhbmNlXHJcbiAgICBpZiBpdCBhbHJlYWR5IGV4aXN0cy5cclxuICAgIEBtZXRob2QgaW5pdGlhbGl6ZUFkYXB0ZXJJbnN0YW5jZVxyXG4gICAgQHBhcmFtIGludGVyZmFjZU5hbWUge1N0cmluZ30gVGhlIG5hbWUgb2YgdGhlIGludGVyZmFjZSB0byB3aGljaCB0aGUgYWRhcHRlciB0byBpbml0aWFsaXplIGJlbG9uZ3MuXHJcbiAgICBAcGFyYW0gYWRhcHRlck5hbWUge1N0cmluZ30gLSBUaGUgbmFtZSBvZiBhIHByZXZpb3VzbHkgcmVnaXN0ZXJlZCBhZGFwdGVyIHRvIGluaXRpYWxpemUuXHJcbiAgICBAcGFyYW0gW2lzRGVmYXVsdD10cnVlXSB7Qm9vbGVhbn0gLSBXaGV0aGVyIHRvIG1ha2UgdGhpcyB0aGUgZGVmYXVsdCBcImFkYXB0ZXJcIiBmb3IgdGhpcyBpbnRlcmZhY2UuXHJcbiAgICBAcmV0dXJuIHthbiBpbnN0YW5jZSBvZiB0aGUgc3BlY2lmaWVkIGFkYXB0ZXJ9XHJcbiAgICAqKi9cclxuICAgIGluaXRpYWxpemVBZGFwdGVySW5zdGFuY2UoaW50ZXJmYWNlTmFtZTogQWRhcHRlclR5cGUsIGFkYXB0ZXJOYW1lOiBzdHJpbmcsIGlzRGVmYXVsdDogYm9vbGVhbiA9IHRydWUpIHtcclxuICAgICAgICBpc0RlZmF1bHQgPSBpc0RlZmF1bHQgPT09IHVuZGVmaW5lZCA/IHRydWUgOiBpc0RlZmF1bHQ7XHJcbiAgICAgICAgYXNzZXJ0UGFyYW0oaW50ZXJmYWNlTmFtZSwgXCJpbnRlcmZhY2VOYW1lXCIpLmlzTm9uRW1wdHlTdHJpbmcoKS5jaGVjaygpO1xyXG4gICAgICAgIGFzc2VydFBhcmFtKGFkYXB0ZXJOYW1lLCBcImFkYXB0ZXJOYW1lXCIpLmlzTm9uRW1wdHlTdHJpbmcoKS5jaGVjaygpO1xyXG4gICAgICAgIGFzc2VydFBhcmFtKGlzRGVmYXVsdCwgXCJpc0RlZmF1bHRcIikuaXNCb29sZWFuKCkuY2hlY2soKTtcclxuXHJcbiAgICAgICAgbGV0IGlkZWYgPSB0aGlzLmdldEludGVyZmFjZURlZihpbnRlcmZhY2VOYW1lKTtcclxuICAgICAgICBsZXQgaW1wbCA9IGlkZWYuZ2V0SW1wbChhZGFwdGVyTmFtZSk7XHJcbiAgICAgICAgaWYgKCFpbXBsKSB7XHJcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlVucmVnaXN0ZXJlZCBhZGFwdGVyLiAgSW50ZXJmYWNlOiBcIiArIGludGVyZmFjZU5hbWUgKyBcIiBBZGFwdGVyTmFtZTogXCIgKyBhZGFwdGVyTmFtZSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gdGhpcy5faW5pdGlhbGl6ZUFkYXB0ZXJJbnN0YW5jZUNvcmUoaWRlZiwgaW1wbCwgaXNEZWZhdWx0KTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgIFJldHVybnMgdGhlIGFkYXB0ZXIgaW5zdGFuY2UgY29ycmVzcG9uZGluZyB0byB0aGUgc3BlY2lmaWVkIGludGVyZmFjZSBhbmQgYWRhcHRlciBuYW1lcy5cclxuICAgIEBtZXRob2QgZ2V0QWRhcHRlckluc3RhbmNlXHJcbiAgICBAcGFyYW0gaW50ZXJmYWNlTmFtZSB7U3RyaW5nfSBUaGUgbmFtZSBvZiB0aGUgaW50ZXJmYWNlLlxyXG4gICAgQHBhcmFtIFthZGFwdGVyTmFtZV0ge1N0cmluZ30gLSBUaGUgbmFtZSBvZiBhIHByZXZpb3VzbHkgcmVnaXN0ZXJlZCBhZGFwdGVyLiAgSWYgdGhpcyBwYXJhbWV0ZXIgaXNcclxuICAgIG9taXR0ZWQgdGhlbiB0aGUgZGVmYXVsdCBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgc3BlY2lmaWVkIGludGVyZmFjZSBpcyByZXR1cm5lZC4gSWYgdGhlcmUgaXNcclxuICAgIG5vIGRlZmF1bHRJbnN0YW5jZSBvZiB0aGlzIGludGVyZmFjZSwgdGhlbiB0aGUgZmlyc3QgcmVnaXN0ZXJlZCBpbnN0YW5jZSBvZiB0aGlzIGludGVyZmFjZSBpcyByZXR1cm5lZC5cclxuICAgIEByZXR1cm4ge2FuIGluc3RhbmNlIG9mIHRoZSBzcGVjaWZpZWQgYWRhcHRlcn1cclxuICAgIEBpbnRlcm5hbFxyXG4gICAgKiovXHJcbiAgICBnZXRBZGFwdGVySW5zdGFuY2U8VCBleHRlbmRzIEJhc2VBZGFwdGVyPihpbnRlcmZhY2VOYW1lOiBBZGFwdGVyVHlwZSwgYWRhcHRlck5hbWU/OiBzdHJpbmcpIHtcclxuICAgICAgICBsZXQgaWRlZiA9IHRoaXMuZ2V0SW50ZXJmYWNlRGVmPFQ+KGludGVyZmFjZU5hbWUpO1xyXG4gICAgICAgIGxldCBpbXBsOiBJRGVmPFQ+O1xyXG5cclxuICAgICAgICBsZXQgaXNEZWZhdWx0ID0gYWRhcHRlck5hbWUgPT0gbnVsbCB8fCBhZGFwdGVyTmFtZSA9PT0gXCJcIjtcclxuICAgICAgICBpZiAoaXNEZWZhdWx0KSB7XHJcbiAgICAgICAgICAgIGlmIChpZGVmLmRlZmF1bHRJbnN0YW5jZSkgcmV0dXJuIGlkZWYuZGVmYXVsdEluc3RhbmNlO1xyXG4gICAgICAgICAgICBpbXBsID0gaWRlZi5nZXRGaXJzdEltcGwoKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBpbXBsID0gaWRlZi5nZXRJbXBsKGFkYXB0ZXJOYW1lISk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmICghaW1wbCkgcmV0dXJuIHVuZGVmaW5lZDtcclxuICAgICAgICBpZiAoaW1wbC5kZWZhdWx0SW5zdGFuY2UpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGltcGwuZGVmYXVsdEluc3RhbmNlO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9pbml0aWFsaXplQWRhcHRlckluc3RhbmNlQ29yZShpZGVmLCBpbXBsLCBpc0RlZmF1bHQpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKiogdGhpcyBpcyBuZWVkZWQgZm9yIHJlZmxlY3Rpb24gcHVycG9zZXMgd2hlbiBkZXNlcmlhbGl6aW5nIGFuIG9iamVjdCB0aGF0IG5lZWRzIGEgZm4gb3IgY3Rvci5cclxuICAgICAgICBVc2VkIHRvIHJlZ2lzdGVyIHZhbGlkYXRvcnMuICovXHJcbiAgICByZWdpc3RlckZ1bmN0aW9uKGZuOiBGdW5jdGlvbiwgZm5OYW1lOiBzdHJpbmcpIHtcclxuICAgICAgICBhc3NlcnRQYXJhbShmbiwgXCJmblwiKS5pc0Z1bmN0aW9uKCkuY2hlY2soKTtcclxuICAgICAgICBhc3NlcnRQYXJhbShmbk5hbWUsIFwiZm5OYW1lXCIpLmlzU3RyaW5nKCkuY2hlY2soKTtcclxuICAgICAgICBpZiAoZm4ucHJvdG90eXBlKSB7XHJcbiAgICAgICAgICAgIGZuLnByb3RvdHlwZS5fJGZuTmFtZSA9IGZuTmFtZTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5mdW5jdGlvblJlZ2lzdHJ5W2ZuTmFtZV0gPSBmbjtcclxuICAgIH1cclxuXHJcbiAgICByZWdpc3RlclR5cGUoY3RvcjogRnVuY3Rpb24sIHR5cGVOYW1lOiBzdHJpbmcpIHtcclxuICAgICAgICBhc3NlcnRQYXJhbShjdG9yLCBcImN0b3JcIikuaXNGdW5jdGlvbigpLmNoZWNrKCk7XHJcbiAgICAgICAgYXNzZXJ0UGFyYW0odHlwZU5hbWUsIFwidHlwZU5hbWVcIikuaXNTdHJpbmcoKS5jaGVjaygpO1xyXG4gICAgICAgIGlmIChjdG9yLnByb3RvdHlwZSkge1xyXG4gICAgICAgICAgICBjdG9yLnByb3RvdHlwZS5fJHR5cGVOYW1lID0gdHlwZU5hbWU7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMudHlwZVJlZ2lzdHJ5W3R5cGVOYW1lXSA9IGN0b3I7XHJcbiAgICB9XHJcblxyXG4gICAgZ2V0UmVnaXN0ZXJlZEZ1bmN0aW9uKGZuTmFtZTogc3RyaW5nKSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuZnVuY3Rpb25SZWdpc3RyeVtmbk5hbWVdO1xyXG4gICAgfVxyXG5cclxuICAgIGdldEludGVyZmFjZURlZjxUIGV4dGVuZHMgQmFzZUFkYXB0ZXI+KGludGVyZmFjZU5hbWU6IHN0cmluZykge1xyXG4gICAgICAgIGxldCBsY05hbWUgPSBpbnRlcmZhY2VOYW1lLnRvTG93ZXJDYXNlKCk7XHJcbiAgICAgICAgLy8gc291cmNlIG1heSBiZSBudWxsXHJcbiAgICAgICAgbGV0IGt2ID0gY29yZS5vYmplY3RGaXJzdCh0aGlzLl9pbnRlcmZhY2VSZWdpc3RyeSB8fCB7fSwgZnVuY3Rpb24gKGssIHYpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGsudG9Mb3dlckNhc2UoKSA9PT0gbGNOYW1lO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIGlmICgha3YpIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVW5rbm93biBpbnRlcmZhY2UgbmFtZTogXCIgKyBpbnRlcmZhY2VOYW1lKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIDxJbnRlcmZhY2VEZWY8VD4+a3YudmFsdWU7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIEBkZXByZWNhdGVkIEBpbnRlcm5hbCBuby1vcCBrZXB0IGZvciBiYWNrd2FyZCBjb21wYXRpYmlsaXR5ICovXHJcbiAgICBzZXRRKHE6IGFueSkge1xyXG4gICAgICAgIGNvbnNvbGUgJiYgY29uc29sZS53YXJuKFwic2V0USBkb2VzIG5vdGhpbmc7IEVTNiBQcm9taXNlIHN1cHBvcnQgaXMgcmVxdWlyZWQgLSB1c2UgYSBzaGltIGlmIG5lY2Vzc2FyeS5cIik7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgICBfc3RvcmVPYmplY3Qob2JqOiBPYmplY3QsIHR5cGU6IHN0cmluZyB8IEZ1bmN0aW9uLCBuYW1lOiBzdHJpbmcpIHtcclxuICAgICAgICAvLyB1bmNvbW1lbnQgdGhpcyBpZiB3ZSBtYWtlIHRoaXMgcHVibGljLlxyXG4gICAgICAgIC8vYXNzZXJ0UGFyYW0ob2JqLCBcIm9ialwiKS5pc09iamVjdCgpLmNoZWNrKCk7XHJcbiAgICAgICAgLy9hc3NlcnRQYXJhbShuYW1lLCBcIm9iak5hbWVcIikuaXNTdHJpbmcoKS5jaGVjaygpO1xyXG4gICAgICAgIGxldCBrZXkgPSAodHlwZW9mICh0eXBlKSA9PT0gXCJzdHJpbmdcIiA/IHR5cGUgOiB0eXBlLnByb3RvdHlwZS5fJHR5cGVOYW1lKSArIFwiLlwiICsgbmFtZTtcclxuICAgICAgICB0aGlzLm9iamVjdFJlZ2lzdHJ5W2tleV0gPSBvYmo7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIEBoaWRkZW4gQGludGVybmFsICovXHJcbiAgICBfZmV0Y2hPYmplY3QodHlwZTogc3RyaW5nIHwgRnVuY3Rpb24sIG5hbWU6IHN0cmluZykge1xyXG4gICAgICAgIGlmICghbmFtZSkgcmV0dXJuIHVuZGVmaW5lZDtcclxuICAgICAgICBsZXQga2V5ID0gKHR5cGVvZiAodHlwZSkgPT09IFwic3RyaW5nXCIgPyB0eXBlIDogdHlwZS5wcm90b3R5cGUuXyR0eXBlTmFtZSkgKyBcIi5cIiArIG5hbWU7XHJcbiAgICAgICAgbGV0IHJlc3VsdCA9IHRoaXMub2JqZWN0UmVnaXN0cnlba2V5XTtcclxuICAgICAgICBpZiAoIXJlc3VsdCkge1xyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbmFibGUgdG8gbG9jYXRlIGEgcmVnaXN0ZXJlZCBvYmplY3QgYnkgdGhlIG5hbWU6IFwiICsga2V5KTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcclxuICAgIH1cclxuXHJcbiAgICAvKiogQGhpZGRlbiBAaW50ZXJuYWwgKi9cclxuICAgIF9pbml0aWFsaXplQWRhcHRlckluc3RhbmNlQ29yZTxUIGV4dGVuZHMgQmFzZUFkYXB0ZXI+KGludGVyZmFjZURlZjogSW50ZXJmYWNlRGVmPFQ+LCBpbXBsOiBJRGVmPFQ+LCBpc0RlZmF1bHQ6IGJvb2xlYW4pIHtcclxuICAgICAgICBsZXQgaW5zdGFuY2U6IFQ7XHJcbiAgICAgICAgbGV0IGluc3QgPSBpbXBsLmRlZmF1bHRJbnN0YW5jZTtcclxuICAgICAgICBpZiAoIWluc3QpIHtcclxuICAgICAgICAgICAgaW5zdGFuY2UgPSBuZXcgKGltcGwuY3RvcikoKTtcclxuICAgICAgICAgICAgaW1wbC5kZWZhdWx0SW5zdGFuY2UgPSBpbnN0YW5jZTtcclxuICAgICAgICAgICAgaW5zdGFuY2UuXyRpbXBsID0gaW1wbDtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBpbnN0YW5jZSA9IGluc3Q7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpbnN0YW5jZS5pbml0aWFsaXplKCk7XHJcblxyXG4gICAgICAgIGlmIChpc0RlZmF1bHQpIHtcclxuICAgICAgICAgICAgLy8gbmV4dCBsaW5lIG5lZWRzIHRvIG9jY3VyIGJlZm9yZSBhbnkgcmVjb21wb3NpdGlvblxyXG4gICAgICAgICAgICBpbnRlcmZhY2VEZWYuZGVmYXVsdEluc3RhbmNlID0gaW5zdGFuY2U7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyByZWNvbXBvc2l0aW9uIG9mIG90aGVyIGltcGxzIHdpbGwgb2NjdXIgaGVyZS5cclxuICAgICAgICB0aGlzLmludGVyZmFjZUluaXRpYWxpemVkLnB1Ymxpc2goeyBpbnRlcmZhY2VOYW1lOiBpbnRlcmZhY2VEZWYubmFtZSwgaW5zdGFuY2U6IGluc3RhbmNlLCBpc0RlZmF1bHQ6IHRydWUgfSk7XHJcblxyXG4gICAgICAgIGlmIChpbnN0YW5jZS5jaGVja0ZvclJlY29tcG9zaXRpb24gIT0gbnVsbCkge1xyXG4gICAgICAgICAgICAvLyBub3cgcmVnaXN0ZXIgZm9yIG93biBkZXBlbmRlbmNpZXMuXHJcbiAgICAgICAgICAgIHRoaXMuaW50ZXJmYWNlSW5pdGlhbGl6ZWQuc3Vic2NyaWJlKChpbnRlcmZhY2VJbml0aWFsaXplZEFyZ3MpID0+IHtcclxuICAgICAgICAgICAgICAgIC8vIFRPRE86IHdoeSAnISdzIG5lZWRlZCBoZXJlIGZvciB0eXBlc2NyaXB0IHRvIGNvbXBpbGUgY29ycmVjdGx5Pz8/XHJcbiAgICAgICAgICAgICAgICBpbnN0YW5jZS5jaGVja0ZvclJlY29tcG9zaXRpb24hKGludGVyZmFjZUluaXRpYWxpemVkQXJncyk7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIGluc3RhbmNlO1xyXG4gICAgfVxyXG5cclxufVxyXG5cclxuZXhwb3J0IGNvbnN0IGNvbmZpZyA9IG5ldyBCcmVlemVDb25maWcoKTtcclxuXHJcbi8vIGxlZ2FjeVxyXG4oY29yZSBhcyBhbnkpLmNvbmZpZyA9IGNvbmZpZztcclxuXHJcblxyXG5cclxuIl19