"use strict"; /** * Manifest - JavaScript class registry and metadata system * * This class maintains a registry of all JavaScript classes in the bundle, * tracking their names and inheritance relationships. It provides utilities * for working with class hierarchies and calling initialization methods. */ class Manifest { /** * Define classes in the manifest (framework internal) * @param {Array} items - Array of class definitions [[Class, "ClassName", ParentClass, decorators], ...] */ static _define(items) { // Initialize the classes object if not already defined if (typeof Manifest._classes === 'undefined') { Manifest._classes = {}; } // Process each class definition items.forEach(item => { let class_object = item[0]; let class_name = item[1]; let class_extends = item[2] || null; let decorators = item[3] || null; // Store the class information (using object to avoid duplicates) Manifest._classes[class_name] = { class: class_object, name: class_name, extends: class_extends, decorators: decorators // Store compact decorator data }; // Add metadata to the class object itself class_object._name = class_name; class_object._extends = class_extends; class_object._decorators = decorators; }); // Build the subclass index after all classes are defined Manifest._build_subclass_index(); } /** * Build an index of subclasses for efficient lookups * This creates a mapping where each class name points to an array of all its subclasses * @private */ static _build_subclass_index() { // Initialize the subclass index Manifest._subclass_index = {}; // Step through each class and walk up its parent chain for (let class_name in Manifest._classes) { const classdata = Manifest._classes[class_name]; let current_class_name = class_name; let current_classdata = classdata; // Walk up the parent chain until we reach the root while (current_classdata) { const extends_name = current_classdata.extends; if (extends_name) { // Initialize the parent's subclass array if needed if (!Manifest._subclass_index[extends_name]) { Manifest._subclass_index[extends_name] = []; } // Add this class to its parent's subclass list if (!Manifest._subclass_index[extends_name].includes(class_name)) { Manifest._subclass_index[extends_name].push(class_name); } // Move up to the parent's metadata (if it exists in manifest) if (Manifest._classes[extends_name]) { current_classdata = Manifest._classes[extends_name]; } else { // Parent not in manifest (e.g., native JavaScript class), stop here current_classdata = null; } } else { // No parent, we've reached the root current_classdata = null; } } } } /** * Get all classes that extend a given base class * @param {Class|string} base_class - The base class (object or name string) to check for * @returns {Array} Array of objects with {class_name, class_object} for classes that extend the base class */ static get_extending(base_class) { if (!Manifest._classes) { return []; } // Convert string to class object if needed let base_class_object = base_class; if (typeof base_class === 'string') { base_class_object = Manifest.get_class_by_name(base_class); if (!base_class_object) { throw new Error(`Base class not found: ${base_class}`); } } const classes = []; for (let class_name in Manifest._classes) { const classdata = Manifest._classes[class_name]; if (Manifest.js_is_subclass_of(classdata.class, base_class_object)) { classes.push({ class_name: class_name, class_object: classdata.class }); } } // Sort alphabetically by class name to ensure deterministic behavior and prevent race condition bugs classes.sort((a, b) => a.class_name.localeCompare(b.class_name)); return classes; } /** * Check if a class is a subclass of another class * Matches PHP Manifest::js_is_subclass_of() signature and behavior * @param {Class|string} subclass - The child class (object or name) to check * @param {Class|string} superclass - The parent class (object or name) to check against * @returns {boolean} True if subclass extends superclass (directly or indirectly) */ static js_is_subclass_of(subclass, superclass) { // Convert string names to class objects let subclass_object = subclass; if (typeof subclass === 'string') { subclass_object = Manifest.get_class_by_name(subclass); if (!subclass_object) { // Can't resolve subclass - return false per spec return false; } } let superclass_object = superclass; if (typeof superclass === 'string') { superclass_object = Manifest.get_class_by_name(superclass); if (!superclass_object) { // Can't resolve superclass - fail loud per spec throw new Error(`Superclass not found in manifest: ${superclass}`); } } // Classes are not subclasses of themselves if (subclass_object === superclass_object) { return false; } // Walk up the inheritance chain let current_class = subclass_object; while (current_class) { if (current_class === superclass_object) { return true; } // Move up to parent class if (current_class._extends) { // _extends may be a string or class reference if (typeof current_class._extends === 'string') { current_class = Manifest.get_class_by_name(current_class._extends); } else { current_class = current_class._extends; } } else { current_class = null; } } return false; } /** * Get a class by its name * @param {string} class_name - The name of the class * @returns {Class|null} The class object or null if not found */ static get_class_by_name(class_name) { if (!Manifest._classes || !Manifest._classes[class_name]) { return null; } return Manifest._classes[class_name].class; } /** * Get all registered classes * @returns {Array} Array of objects with {class_name, class_object, extends} */ static get_all_classes() { if (!Manifest._classes) { return []; } const results = []; for (let class_name in Manifest._classes) { const classdata = Manifest._classes[class_name]; results.push({ class_name: classdata.name, class_object: classdata.class, extends: classdata.extends }); } // Sort alphabetically by class name to ensure deterministic behavior and prevent race condition bugs results.sort((a, b) => a.class_name.localeCompare(b.class_name)); return results; } /** * Get the build key from the application configuration * @returns {string} The build key or "NOBUILD" if not available */ static build_key() { if (window.rsxapp && window.rsxapp.build_key) { return window.rsxapp.build_key; } return 'NOBUILD'; } /** * Get decorators for a specific class and method * @param {string|Class} class_name - The class name or class object * @param {string} method_name - The method name * @returns {Array|null} Array of decorator objects or null if none found */ static get_decorators(class_name, method_name) { // Convert class object to name if needed if (typeof class_name !== 'string') { class_name = class_name._name || class_name.name; } const class_info = Manifest._classes[class_name]; if (!class_info || !class_info.decorators || !class_info.decorators[method_name]) { return null; } // Transform compact format to object format return Manifest._transform_decorators(class_info.decorators[method_name]); } /** * Get all methods with decorators for a class * @param {string|Class} class_name - The class name or class object * @returns {Object} Object with method names as keys and decorator arrays as values */ static get_all_decorators(class_name) { // Convert class object to name if needed if (typeof class_name !== 'string') { class_name = class_name._name || class_name.name; } const class_info = Manifest._classes[class_name]; if (!class_info || !class_info.decorators) { return {}; } // Transform all decorators from compact to object format const result = {}; for (let method_name in class_info.decorators) { result[method_name] = Manifest._transform_decorators(class_info.decorators[method_name]); } return result; } /** * Transform compact decorator format to object format * @param {Array} compact_decorators - Array of [name, [args]] tuples * @returns {Array} Array of decorator objects with name and arguments properties * @private */ static _transform_decorators(compact_decorators) { if (!Array.isArray(compact_decorators)) { return []; } return compact_decorators.map(decorator => { if (Array.isArray(decorator) && decorator.length >= 2) { return { name: decorator[0], arguments: decorator[1] || [] }; } // Handle malformed decorator data return { name: 'unknown', arguments: [] }; }); } /** * Check if a method has a specific decorator * @param {string|Class} class_name - The class name or class object * @param {string} method_name - The method name * @param {string} decorator_name - The decorator name to check for * @returns {boolean} True if the method has the decorator */ static has_decorator(class_name, method_name, decorator_name) { const decorators = Manifest.get_decorators(class_name, method_name); if (!decorators) { return false; } return decorators.some(d => d.name === decorator_name); } /** * Get all subclasses of a given class using the pre-built index * This is the JavaScript equivalent of PHP's Manifest::js_get_subclasses_of() * @param {Class|string} base_class - The base class (object or name string) to get subclasses of * @returns {Array} Array of actual class objects that are subclasses of the base class */ static js_get_subclasses_of(base_class) { // Initialize index if needed if (!Manifest._subclass_index) { Manifest._build_subclass_index(); } // Convert class object to name if needed let base_class_name = base_class; if (typeof base_class !== 'string') { base_class_name = base_class._name || base_class.name; } // Check if the base class exists if (!Manifest._classes[base_class_name]) { // Base class not in manifest - return empty array return []; } // Get subclass names from the index const subclass_names = Manifest._subclass_index[base_class_name] || []; // Convert names to actual class objects const subclass_objects = []; for (let subclass_name of subclass_names) { const classdata = Manifest._classes[subclass_name]; subclass_objects.push(classdata.class); } // Sort by class name for deterministic behavior subclass_objects.sort((a, b) => { const name_a = a._name || a.name; const name_b = b._name || b.name; return name_a.localeCompare(name_b); }); return subclass_objects; } } // RSX manifest automatically makes classes global - no manual assignment needed //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJNYW5pZmVzdCIsIl9kZWZpbmUiLCJpdGVtcyIsIl9jbGFzc2VzIiwiZm9yRWFjaCIsIml0ZW0iLCJjbGFzc19vYmplY3QiLCJjbGFzc19uYW1lIiwiY2xhc3NfZXh0ZW5kcyIsImRlY29yYXRvcnMiLCJjbGFzcyIsIm5hbWUiLCJleHRlbmRzIiwiX25hbWUiLCJfZXh0ZW5kcyIsIl9kZWNvcmF0b3JzIiwiX2J1aWxkX3N1YmNsYXNzX2luZGV4IiwiX3N1YmNsYXNzX2luZGV4IiwiY2xhc3NkYXRhIiwiY3VycmVudF9jbGFzc19uYW1lIiwiY3VycmVudF9jbGFzc2RhdGEiLCJleHRlbmRzX25hbWUiLCJpbmNsdWRlcyIsInB1c2giLCJnZXRfZXh0ZW5kaW5nIiwiYmFzZV9jbGFzcyIsImJhc2VfY2xhc3Nfb2JqZWN0IiwiZ2V0X2NsYXNzX2J5X25hbWUiLCJFcnJvciIsImNsYXNzZXMiLCJqc19pc19zdWJjbGFzc19vZiIsInNvcnQiLCJhIiwiYiIsImxvY2FsZUNvbXBhcmUiLCJzdWJjbGFzcyIsInN1cGVyY2xhc3MiLCJzdWJjbGFzc19vYmplY3QiLCJzdXBlcmNsYXNzX29iamVjdCIsImN1cnJlbnRfY2xhc3MiLCJnZXRfYWxsX2NsYXNzZXMiLCJyZXN1bHRzIiwiYnVpbGRfa2V5Iiwid2luZG93IiwicnN4YXBwIiwiZ2V0X2RlY29yYXRvcnMiLCJtZXRob2RfbmFtZSIsImNsYXNzX2luZm8iLCJfdHJhbnNmb3JtX2RlY29yYXRvcnMiLCJnZXRfYWxsX2RlY29yYXRvcnMiLCJyZXN1bHQiLCJjb21wYWN0X2RlY29yYXRvcnMiLCJBcnJheSIsImlzQXJyYXkiLCJtYXAiLCJkZWNvcmF0b3IiLCJsZW5ndGgiLCJhcmd1bWVudHMiLCJoYXNfZGVjb3JhdG9yIiwiZGVjb3JhdG9yX25hbWUiLCJzb21lIiwiZCIsImpzX2dldF9zdWJjbGFzc2VzX29mIiwiYmFzZV9jbGFzc19uYW1lIiwic3ViY2xhc3NfbmFtZXMiLCJzdWJjbGFzc19vYmplY3RzIiwic3ViY2xhc3NfbmFtZSIsIm5hbWVfYSIsIm5hbWVfYiJdLCJzb3VyY2VzIjpbImFwcC9SU3BhZGUvQ29yZS9Kcy9NYW5pZmVzdC5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIE1hbmlmZXN0IC0gSmF2YVNjcmlwdCBjbGFzcyByZWdpc3RyeSBhbmQgbWV0YWRhdGEgc3lzdGVtXG4gKlxuICogVGhpcyBjbGFzcyBtYWludGFpbnMgYSByZWdpc3RyeSBvZiBhbGwgSmF2YVNjcmlwdCBjbGFzc2VzIGluIHRoZSBidW5kbGUsXG4gKiB0cmFja2luZyB0aGVpciBuYW1lcyBhbmQgaW5oZXJpdGFuY2UgcmVsYXRpb25zaGlwcy4gSXQgcHJvdmlkZXMgdXRpbGl0aWVzXG4gKiBmb3Igd29ya2luZyB3aXRoIGNsYXNzIGhpZXJhcmNoaWVzIGFuZCBjYWxsaW5nIGluaXRpYWxpemF0aW9uIG1ldGhvZHMuXG4gKi9cbmNsYXNzIE1hbmlmZXN0IHtcbiAgICAvKipcbiAgICAgKiBEZWZpbmUgY2xhc3NlcyBpbiB0aGUgbWFuaWZlc3QgKGZyYW1ld29yayBpbnRlcm5hbClcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBpdGVtcyAtIEFycmF5IG9mIGNsYXNzIGRlZmluaXRpb25zIFtbQ2xhc3MsIFwiQ2xhc3NOYW1lXCIsIFBhcmVudENsYXNzLCBkZWNvcmF0b3JzXSwgLi4uXVxuICAgICAqL1xuICAgIHN0YXRpYyBfZGVmaW5lKGl0ZW1zKSB7XG4gICAgICAgIC8vIEluaXRpYWxpemUgdGhlIGNsYXNzZXMgb2JqZWN0IGlmIG5vdCBhbHJlYWR5IGRlZmluZWRcbiAgICAgICAgaWYgKHR5cGVvZiBNYW5pZmVzdC5fY2xhc3NlcyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIE1hbmlmZXN0Ll9jbGFzc2VzID0ge307XG4gICAgICAgIH1cblxuICAgICAgICAvLyBQcm9jZXNzIGVhY2ggY2xhc3MgZGVmaW5pdGlvblxuICAgICAgICBpdGVtcy5mb3JFYWNoKChpdGVtKSA9PiB7XG4gICAgICAgICAgICBsZXQgY2xhc3Nfb2JqZWN0ID0gaXRlbVswXTtcbiAgICAgICAgICAgIGxldCBjbGFzc19uYW1lID0gaXRlbVsxXTtcbiAgICAgICAgICAgIGxldCBjbGFzc19leHRlbmRzID0gaXRlbVsyXSB8fCBudWxsO1xuICAgICAgICAgICAgbGV0IGRlY29yYXRvcnMgPSBpdGVtWzNdIHx8IG51bGw7XG5cbiAgICAgICAgICAgIC8vIFN0b3JlIHRoZSBjbGFzcyBpbmZvcm1hdGlvbiAodXNpbmcgb2JqZWN0IHRvIGF2b2lkIGR1cGxpY2F0ZXMpXG4gICAgICAgICAgICBNYW5pZmVzdC5fY2xhc3Nlc1tjbGFzc19uYW1lXSA9IHtcbiAgICAgICAgICAgICAgICBjbGFzczogY2xhc3Nfb2JqZWN0LFxuICAgICAgICAgICAgICAgIG5hbWU6IGNsYXNzX25hbWUsXG4gICAgICAgICAgICAgICAgZXh0ZW5kczogY2xhc3NfZXh0ZW5kcyxcbiAgICAgICAgICAgICAgICBkZWNvcmF0b3JzOiBkZWNvcmF0b3JzLCAgLy8gU3RvcmUgY29tcGFjdCBkZWNvcmF0b3IgZGF0YVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgLy8gQWRkIG1ldGFkYXRhIHRvIHRoZSBjbGFzcyBvYmplY3QgaXRzZWxmXG4gICAgICAgICAgICBjbGFzc19vYmplY3QuX25hbWUgPSBjbGFzc19uYW1lO1xuICAgICAgICAgICAgY2xhc3Nfb2JqZWN0Ll9leHRlbmRzID0gY2xhc3NfZXh0ZW5kcztcbiAgICAgICAgICAgIGNsYXNzX29iamVjdC5fZGVjb3JhdG9ycyA9IGRlY29yYXRvcnM7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIEJ1aWxkIHRoZSBzdWJjbGFzcyBpbmRleCBhZnRlciBhbGwgY2xhc3NlcyBhcmUgZGVmaW5lZFxuICAgICAgICBNYW5pZmVzdC5fYnVpbGRfc3ViY2xhc3NfaW5kZXgoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBCdWlsZCBhbiBpbmRleCBvZiBzdWJjbGFzc2VzIGZvciBlZmZpY2llbnQgbG9va3Vwc1xuICAgICAqIFRoaXMgY3JlYXRlcyBhIG1hcHBpbmcgd2hlcmUgZWFjaCBjbGFzcyBuYW1lIHBvaW50cyB0byBhbiBhcnJheSBvZiBhbGwgaXRzIHN1YmNsYXNzZXNcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfYnVpbGRfc3ViY2xhc3NfaW5kZXgoKSB7XG4gICAgICAgIC8vIEluaXRpYWxpemUgdGhlIHN1YmNsYXNzIGluZGV4XG4gICAgICAgIE1hbmlmZXN0Ll9zdWJjbGFzc19pbmRleCA9IHt9O1xuXG4gICAgICAgIC8vIFN0ZXAgdGhyb3VnaCBlYWNoIGNsYXNzIGFuZCB3YWxrIHVwIGl0cyBwYXJlbnQgY2hhaW5cbiAgICAgICAgZm9yIChsZXQgY2xhc3NfbmFtZSBpbiBNYW5pZmVzdC5fY2xhc3Nlcykge1xuICAgICAgICAgICAgY29uc3QgY2xhc3NkYXRhID0gTWFuaWZlc3QuX2NsYXNzZXNbY2xhc3NfbmFtZV07XG4gICAgICAgICAgICBsZXQgY3VycmVudF9jbGFzc19uYW1lID0gY2xhc3NfbmFtZTtcbiAgICAgICAgICAgIGxldCBjdXJyZW50X2NsYXNzZGF0YSA9IGNsYXNzZGF0YTtcblxuICAgICAgICAgICAgLy8gV2FsayB1cCB0aGUgcGFyZW50IGNoYWluIHVudGlsIHdlIHJlYWNoIHRoZSByb290XG4gICAgICAgICAgICB3aGlsZSAoY3VycmVudF9jbGFzc2RhdGEpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBleHRlbmRzX25hbWUgPSBjdXJyZW50X2NsYXNzZGF0YS5leHRlbmRzO1xuXG4gICAgICAgICAgICAgICAgaWYgKGV4dGVuZHNfbmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJbml0aWFsaXplIHRoZSBwYXJlbnQncyBzdWJjbGFzcyBhcnJheSBpZiBuZWVkZWRcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFNYW5pZmVzdC5fc3ViY2xhc3NfaW5kZXhbZXh0ZW5kc19uYW1lXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgTWFuaWZlc3QuX3N1YmNsYXNzX2luZGV4W2V4dGVuZHNfbmFtZV0gPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIEFkZCB0aGlzIGNsYXNzIHRvIGl0cyBwYXJlbnQncyBzdWJjbGFzcyBsaXN0XG4gICAgICAgICAgICAgICAgICAgIGlmICghTWFuaWZlc3QuX3N1YmNsYXNzX2luZGV4W2V4dGVuZHNfbmFtZV0uaW5jbHVkZXMoY2xhc3NfbmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIE1hbmlmZXN0Ll9zdWJjbGFzc19pbmRleFtleHRlbmRzX25hbWVdLnB1c2goY2xhc3NfbmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBNb3ZlIHVwIHRvIHRoZSBwYXJlbnQncyBtZXRhZGF0YSAoaWYgaXQgZXhpc3RzIGluIG1hbmlmZXN0KVxuICAgICAgICAgICAgICAgICAgICBpZiAoTWFuaWZlc3QuX2NsYXNzZXNbZXh0ZW5kc19uYW1lXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudF9jbGFzc2RhdGEgPSBNYW5pZmVzdC5fY2xhc3Nlc1tleHRlbmRzX25hbWVdO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gUGFyZW50IG5vdCBpbiBtYW5pZmVzdCAoZS5nLiwgbmF0aXZlIEphdmFTY3JpcHQgY2xhc3MpLCBzdG9wIGhlcmVcbiAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRfY2xhc3NkYXRhID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIE5vIHBhcmVudCwgd2UndmUgcmVhY2hlZCB0aGUgcm9vdFxuICAgICAgICAgICAgICAgICAgICBjdXJyZW50X2NsYXNzZGF0YSA9IG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IGFsbCBjbGFzc2VzIHRoYXQgZXh0ZW5kIGEgZ2l2ZW4gYmFzZSBjbGFzc1xuICAgICAqIEBwYXJhbSB7Q2xhc3N8c3RyaW5nfSBiYXNlX2NsYXNzIC0gVGhlIGJhc2UgY2xhc3MgKG9iamVjdCBvciBuYW1lIHN0cmluZykgdG8gY2hlY2sgZm9yXG4gICAgICogQHJldHVybnMge0FycmF5fSBBcnJheSBvZiBvYmplY3RzIHdpdGgge2NsYXNzX25hbWUsIGNsYXNzX29iamVjdH0gZm9yIGNsYXNzZXMgdGhhdCBleHRlbmQgdGhlIGJhc2UgY2xhc3NcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0X2V4dGVuZGluZyhiYXNlX2NsYXNzKSB7XG4gICAgICAgIGlmICghTWFuaWZlc3QuX2NsYXNzZXMpIHtcbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENvbnZlcnQgc3RyaW5nIHRvIGNsYXNzIG9iamVjdCBpZiBuZWVkZWRcbiAgICAgICAgbGV0IGJhc2VfY2xhc3Nfb2JqZWN0ID0gYmFzZV9jbGFzcztcbiAgICAgICAgaWYgKHR5cGVvZiBiYXNlX2NsYXNzID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgYmFzZV9jbGFzc19vYmplY3QgPSBNYW5pZmVzdC5nZXRfY2xhc3NfYnlfbmFtZShiYXNlX2NsYXNzKTtcbiAgICAgICAgICAgIGlmICghYmFzZV9jbGFzc19vYmplY3QpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEJhc2UgY2xhc3Mgbm90IGZvdW5kOiAke2Jhc2VfY2xhc3N9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjbGFzc2VzID0gW107XG5cbiAgICAgICAgZm9yIChsZXQgY2xhc3NfbmFtZSBpbiBNYW5pZmVzdC5fY2xhc3Nlcykge1xuICAgICAgICAgICAgY29uc3QgY2xhc3NkYXRhID0gTWFuaWZlc3QuX2NsYXNzZXNbY2xhc3NfbmFtZV07XG4gICAgICAgICAgICBpZiAoTWFuaWZlc3QuanNfaXNfc3ViY2xhc3Nfb2YoY2xhc3NkYXRhLmNsYXNzLCBiYXNlX2NsYXNzX29iamVjdCkpIHtcbiAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBjbGFzc19uYW1lOiBjbGFzc19uYW1lLFxuICAgICAgICAgICAgICAgICAgICBjbGFzc19vYmplY3Q6IGNsYXNzZGF0YS5jbGFzcyxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNvcnQgYWxwaGFiZXRpY2FsbHkgYnkgY2xhc3MgbmFtZSB0byBlbnN1cmUgZGV0ZXJtaW5pc3RpYyBiZWhhdmlvciBhbmQgcHJldmVudCByYWNlIGNvbmRpdGlvbiBidWdzXG4gICAgICAgIGNsYXNzZXMuc29ydCgoYSwgYikgPT4gYS5jbGFzc19uYW1lLmxvY2FsZUNvbXBhcmUoYi5jbGFzc19uYW1lKSk7XG5cbiAgICAgICAgcmV0dXJuIGNsYXNzZXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgaWYgYSBjbGFzcyBpcyBhIHN1YmNsYXNzIG9mIGFub3RoZXIgY2xhc3NcbiAgICAgKiBNYXRjaGVzIFBIUCBNYW5pZmVzdDo6anNfaXNfc3ViY2xhc3Nfb2YoKSBzaWduYXR1cmUgYW5kIGJlaGF2aW9yXG4gICAgICogQHBhcmFtIHtDbGFzc3xzdHJpbmd9IHN1YmNsYXNzIC0gVGhlIGNoaWxkIGNsYXNzIChvYmplY3Qgb3IgbmFtZSkgdG8gY2hlY2tcbiAgICAgKiBAcGFyYW0ge0NsYXNzfHN0cmluZ30gc3VwZXJjbGFzcyAtIFRoZSBwYXJlbnQgY2xhc3MgKG9iamVjdCBvciBuYW1lKSB0byBjaGVjayBhZ2FpbnN0XG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgc3ViY2xhc3MgZXh0ZW5kcyBzdXBlcmNsYXNzIChkaXJlY3RseSBvciBpbmRpcmVjdGx5KVxuICAgICAqL1xuICAgIHN0YXRpYyBqc19pc19zdWJjbGFzc19vZihzdWJjbGFzcywgc3VwZXJjbGFzcykge1xuICAgICAgICAvLyBDb252ZXJ0IHN0cmluZyBuYW1lcyB0byBjbGFzcyBvYmplY3RzXG4gICAgICAgIGxldCBzdWJjbGFzc19vYmplY3QgPSBzdWJjbGFzcztcbiAgICAgICAgaWYgKHR5cGVvZiBzdWJjbGFzcyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHN1YmNsYXNzX29iamVjdCA9IE1hbmlmZXN0LmdldF9jbGFzc19ieV9uYW1lKHN1YmNsYXNzKTtcbiAgICAgICAgICAgIGlmICghc3ViY2xhc3Nfb2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgLy8gQ2FuJ3QgcmVzb2x2ZSBzdWJjbGFzcyAtIHJldHVybiBmYWxzZSBwZXIgc3BlY1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBzdXBlcmNsYXNzX29iamVjdCA9IHN1cGVyY2xhc3M7XG4gICAgICAgIGlmICh0eXBlb2Ygc3VwZXJjbGFzcyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHN1cGVyY2xhc3Nfb2JqZWN0ID0gTWFuaWZlc3QuZ2V0X2NsYXNzX2J5X25hbWUoc3VwZXJjbGFzcyk7XG4gICAgICAgICAgICBpZiAoIXN1cGVyY2xhc3Nfb2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgLy8gQ2FuJ3QgcmVzb2x2ZSBzdXBlcmNsYXNzIC0gZmFpbCBsb3VkIHBlciBzcGVjXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBTdXBlcmNsYXNzIG5vdCBmb3VuZCBpbiBtYW5pZmVzdDogJHtzdXBlcmNsYXNzfWApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2xhc3NlcyBhcmUgbm90IHN1YmNsYXNzZXMgb2YgdGhlbXNlbHZlc1xuICAgICAgICBpZiAoc3ViY2xhc3Nfb2JqZWN0ID09PSBzdXBlcmNsYXNzX29iamVjdCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gV2FsayB1cCB0aGUgaW5oZXJpdGFuY2UgY2hhaW5cbiAgICAgICAgbGV0IGN1cnJlbnRfY2xhc3MgPSBzdWJjbGFzc19vYmplY3Q7XG4gICAgICAgIHdoaWxlIChjdXJyZW50X2NsYXNzKSB7XG4gICAgICAgICAgICBpZiAoY3VycmVudF9jbGFzcyA9PT0gc3VwZXJjbGFzc19vYmplY3QpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIE1vdmUgdXAgdG8gcGFyZW50IGNsYXNzXG4gICAgICAgICAgICBpZiAoY3VycmVudF9jbGFzcy5fZXh0ZW5kcykge1xuICAgICAgICAgICAgICAgIC8vIF9leHRlbmRzIG1heSBiZSBhIHN0cmluZyBvciBjbGFzcyByZWZlcmVuY2VcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGN1cnJlbnRfY2xhc3MuX2V4dGVuZHMgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRfY2xhc3MgPSBNYW5pZmVzdC5nZXRfY2xhc3NfYnlfbmFtZShjdXJyZW50X2NsYXNzLl9leHRlbmRzKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50X2NsYXNzID0gY3VycmVudF9jbGFzcy5fZXh0ZW5kcztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRfY2xhc3MgPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCBhIGNsYXNzIGJ5IGl0cyBuYW1lXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGNsYXNzX25hbWUgLSBUaGUgbmFtZSBvZiB0aGUgY2xhc3NcbiAgICAgKiBAcmV0dXJucyB7Q2xhc3N8bnVsbH0gVGhlIGNsYXNzIG9iamVjdCBvciBudWxsIGlmIG5vdCBmb3VuZFxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRfY2xhc3NfYnlfbmFtZShjbGFzc19uYW1lKSB7XG4gICAgICAgIGlmICghTWFuaWZlc3QuX2NsYXNzZXMgfHwgIU1hbmlmZXN0Ll9jbGFzc2VzW2NsYXNzX25hbWVdKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBNYW5pZmVzdC5fY2xhc3Nlc1tjbGFzc19uYW1lXS5jbGFzcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgYWxsIHJlZ2lzdGVyZWQgY2xhc3Nlc1xuICAgICAqIEByZXR1cm5zIHtBcnJheX0gQXJyYXkgb2Ygb2JqZWN0cyB3aXRoIHtjbGFzc19uYW1lLCBjbGFzc19vYmplY3QsIGV4dGVuZHN9XG4gICAgICovXG4gICAgc3RhdGljIGdldF9hbGxfY2xhc3NlcygpIHtcbiAgICAgICAgaWYgKCFNYW5pZmVzdC5fY2xhc3Nlcykge1xuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcmVzdWx0cyA9IFtdO1xuICAgICAgICBmb3IgKGxldCBjbGFzc19uYW1lIGluIE1hbmlmZXN0Ll9jbGFzc2VzKSB7XG4gICAgICAgICAgICBjb25zdCBjbGFzc2RhdGEgPSBNYW5pZmVzdC5fY2xhc3Nlc1tjbGFzc19uYW1lXTtcbiAgICAgICAgICAgIHJlc3VsdHMucHVzaCh7XG4gICAgICAgICAgICAgICAgY2xhc3NfbmFtZTogY2xhc3NkYXRhLm5hbWUsXG4gICAgICAgICAgICAgICAgY2xhc3Nfb2JqZWN0OiBjbGFzc2RhdGEuY2xhc3MsXG4gICAgICAgICAgICAgICAgZXh0ZW5kczogY2xhc3NkYXRhLmV4dGVuZHMsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNvcnQgYWxwaGFiZXRpY2FsbHkgYnkgY2xhc3MgbmFtZSB0byBlbnN1cmUgZGV0ZXJtaW5pc3RpYyBiZWhhdmlvciBhbmQgcHJldmVudCByYWNlIGNvbmRpdGlvbiBidWdzXG4gICAgICAgIHJlc3VsdHMuc29ydCgoYSwgYikgPT4gYS5jbGFzc19uYW1lLmxvY2FsZUNvbXBhcmUoYi5jbGFzc19uYW1lKSk7XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdHM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBidWlsZCBrZXkgZnJvbSB0aGUgYXBwbGljYXRpb24gY29uZmlndXJhdGlvblxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBidWlsZCBrZXkgb3IgXCJOT0JVSUxEXCIgaWYgbm90IGF2YWlsYWJsZVxuICAgICAqL1xuICAgIHN0YXRpYyBidWlsZF9rZXkoKSB7XG4gICAgICAgIGlmICh3aW5kb3cucnN4YXBwICYmIHdpbmRvdy5yc3hhcHAuYnVpbGRfa2V5KSB7XG4gICAgICAgICAgICByZXR1cm4gd2luZG93LnJzeGFwcC5idWlsZF9rZXk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICdOT0JVSUxEJztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgZGVjb3JhdG9ycyBmb3IgYSBzcGVjaWZpYyBjbGFzcyBhbmQgbWV0aG9kXG4gICAgICogQHBhcmFtIHtzdHJpbmd8Q2xhc3N9IGNsYXNzX25hbWUgLSBUaGUgY2xhc3MgbmFtZSBvciBjbGFzcyBvYmplY3RcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbWV0aG9kX25hbWUgLSBUaGUgbWV0aG9kIG5hbWVcbiAgICAgKiBAcmV0dXJucyB7QXJyYXl8bnVsbH0gQXJyYXkgb2YgZGVjb3JhdG9yIG9iamVjdHMgb3IgbnVsbCBpZiBub25lIGZvdW5kXG4gICAgICovXG4gICAgc3RhdGljIGdldF9kZWNvcmF0b3JzKGNsYXNzX25hbWUsIG1ldGhvZF9uYW1lKSB7XG4gICAgICAgIC8vIENvbnZlcnQgY2xhc3Mgb2JqZWN0IHRvIG5hbWUgaWYgbmVlZGVkXG4gICAgICAgIGlmICh0eXBlb2YgY2xhc3NfbmFtZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIGNsYXNzX25hbWUgPSBjbGFzc19uYW1lLl9uYW1lIHx8IGNsYXNzX25hbWUubmFtZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGNsYXNzX2luZm8gPSBNYW5pZmVzdC5fY2xhc3Nlc1tjbGFzc19uYW1lXTtcbiAgICAgICAgaWYgKCFjbGFzc19pbmZvIHx8ICFjbGFzc19pbmZvLmRlY29yYXRvcnMgfHwgIWNsYXNzX2luZm8uZGVjb3JhdG9yc1ttZXRob2RfbmFtZV0pIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVHJhbnNmb3JtIGNvbXBhY3QgZm9ybWF0IHRvIG9iamVjdCBmb3JtYXRcbiAgICAgICAgcmV0dXJuIE1hbmlmZXN0Ll90cmFuc2Zvcm1fZGVjb3JhdG9ycyhjbGFzc19pbmZvLmRlY29yYXRvcnNbbWV0aG9kX25hbWVdKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgYWxsIG1ldGhvZHMgd2l0aCBkZWNvcmF0b3JzIGZvciBhIGNsYXNzXG4gICAgICogQHBhcmFtIHtzdHJpbmd8Q2xhc3N9IGNsYXNzX25hbWUgLSBUaGUgY2xhc3MgbmFtZSBvciBjbGFzcyBvYmplY3RcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBPYmplY3Qgd2l0aCBtZXRob2QgbmFtZXMgYXMga2V5cyBhbmQgZGVjb3JhdG9yIGFycmF5cyBhcyB2YWx1ZXNcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0X2FsbF9kZWNvcmF0b3JzKGNsYXNzX25hbWUpIHtcbiAgICAgICAgLy8gQ29udmVydCBjbGFzcyBvYmplY3QgdG8gbmFtZSBpZiBuZWVkZWRcbiAgICAgICAgaWYgKHR5cGVvZiBjbGFzc19uYW1lICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgY2xhc3NfbmFtZSA9IGNsYXNzX25hbWUuX25hbWUgfHwgY2xhc3NfbmFtZS5uYW1lO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgY2xhc3NfaW5mbyA9IE1hbmlmZXN0Ll9jbGFzc2VzW2NsYXNzX25hbWVdO1xuICAgICAgICBpZiAoIWNsYXNzX2luZm8gfHwgIWNsYXNzX2luZm8uZGVjb3JhdG9ycykge1xuICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVHJhbnNmb3JtIGFsbCBkZWNvcmF0b3JzIGZyb20gY29tcGFjdCB0byBvYmplY3QgZm9ybWF0XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IHt9O1xuICAgICAgICBmb3IgKGxldCBtZXRob2RfbmFtZSBpbiBjbGFzc19pbmZvLmRlY29yYXRvcnMpIHtcbiAgICAgICAgICAgIHJlc3VsdFttZXRob2RfbmFtZV0gPSBNYW5pZmVzdC5fdHJhbnNmb3JtX2RlY29yYXRvcnMoY2xhc3NfaW5mby5kZWNvcmF0b3JzW21ldGhvZF9uYW1lXSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUcmFuc2Zvcm0gY29tcGFjdCBkZWNvcmF0b3IgZm9ybWF0IHRvIG9iamVjdCBmb3JtYXRcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBjb21wYWN0X2RlY29yYXRvcnMgLSBBcnJheSBvZiBbbmFtZSwgW2FyZ3NdXSB0dXBsZXNcbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIGRlY29yYXRvciBvYmplY3RzIHdpdGggbmFtZSBhbmQgYXJndW1lbnRzIHByb3BlcnRpZXNcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfdHJhbnNmb3JtX2RlY29yYXRvcnMoY29tcGFjdF9kZWNvcmF0b3JzKSB7XG4gICAgICAgIGlmICghQXJyYXkuaXNBcnJheShjb21wYWN0X2RlY29yYXRvcnMpKSB7XG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gY29tcGFjdF9kZWNvcmF0b3JzLm1hcChkZWNvcmF0b3IgPT4ge1xuICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoZGVjb3JhdG9yKSAmJiBkZWNvcmF0b3IubGVuZ3RoID49IDIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBuYW1lOiBkZWNvcmF0b3JbMF0sXG4gICAgICAgICAgICAgICAgICAgIGFyZ3VtZW50czogZGVjb3JhdG9yWzFdIHx8IFtdXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEhhbmRsZSBtYWxmb3JtZWQgZGVjb3JhdG9yIGRhdGFcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgbmFtZTogJ3Vua25vd24nLFxuICAgICAgICAgICAgICAgIGFyZ3VtZW50czogW11cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrIGlmIGEgbWV0aG9kIGhhcyBhIHNwZWNpZmljIGRlY29yYXRvclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfENsYXNzfSBjbGFzc19uYW1lIC0gVGhlIGNsYXNzIG5hbWUgb3IgY2xhc3Mgb2JqZWN0XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG1ldGhvZF9uYW1lIC0gVGhlIG1ldGhvZCBuYW1lXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGRlY29yYXRvcl9uYW1lIC0gVGhlIGRlY29yYXRvciBuYW1lIHRvIGNoZWNrIGZvclxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHRoZSBtZXRob2QgaGFzIHRoZSBkZWNvcmF0b3JcbiAgICAgKi9cbiAgICBzdGF0aWMgaGFzX2RlY29yYXRvcihjbGFzc19uYW1lLCBtZXRob2RfbmFtZSwgZGVjb3JhdG9yX25hbWUpIHtcbiAgICAgICAgY29uc3QgZGVjb3JhdG9ycyA9IE1hbmlmZXN0LmdldF9kZWNvcmF0b3JzKGNsYXNzX25hbWUsIG1ldGhvZF9uYW1lKTtcbiAgICAgICAgaWYgKCFkZWNvcmF0b3JzKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZGVjb3JhdG9ycy5zb21lKGQgPT4gZC5uYW1lID09PSBkZWNvcmF0b3JfbmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IGFsbCBzdWJjbGFzc2VzIG9mIGEgZ2l2ZW4gY2xhc3MgdXNpbmcgdGhlIHByZS1idWlsdCBpbmRleFxuICAgICAqIFRoaXMgaXMgdGhlIEphdmFTY3JpcHQgZXF1aXZhbGVudCBvZiBQSFAncyBNYW5pZmVzdDo6anNfZ2V0X3N1YmNsYXNzZXNfb2YoKVxuICAgICAqIEBwYXJhbSB7Q2xhc3N8c3RyaW5nfSBiYXNlX2NsYXNzIC0gVGhlIGJhc2UgY2xhc3MgKG9iamVjdCBvciBuYW1lIHN0cmluZykgdG8gZ2V0IHN1YmNsYXNzZXMgb2ZcbiAgICAgKiBAcmV0dXJucyB7QXJyYXk8Q2xhc3M+fSBBcnJheSBvZiBhY3R1YWwgY2xhc3Mgb2JqZWN0cyB0aGF0IGFyZSBzdWJjbGFzc2VzIG9mIHRoZSBiYXNlIGNsYXNzXG4gICAgICovXG4gICAgc3RhdGljIGpzX2dldF9zdWJjbGFzc2VzX29mKGJhc2VfY2xhc3MpIHtcbiAgICAgICAgLy8gSW5pdGlhbGl6ZSBpbmRleCBpZiBuZWVkZWRcbiAgICAgICAgaWYgKCFNYW5pZmVzdC5fc3ViY2xhc3NfaW5kZXgpIHtcbiAgICAgICAgICAgIE1hbmlmZXN0Ll9idWlsZF9zdWJjbGFzc19pbmRleCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ29udmVydCBjbGFzcyBvYmplY3QgdG8gbmFtZSBpZiBuZWVkZWRcbiAgICAgICAgbGV0IGJhc2VfY2xhc3NfbmFtZSA9IGJhc2VfY2xhc3M7XG4gICAgICAgIGlmICh0eXBlb2YgYmFzZV9jbGFzcyAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIGJhc2VfY2xhc3NfbmFtZSA9IGJhc2VfY2xhc3MuX25hbWUgfHwgYmFzZV9jbGFzcy5uYW1lO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2hlY2sgaWYgdGhlIGJhc2UgY2xhc3MgZXhpc3RzXG4gICAgICAgIGlmICghTWFuaWZlc3QuX2NsYXNzZXNbYmFzZV9jbGFzc19uYW1lXSkge1xuICAgICAgICAgICAgLy8gQmFzZSBjbGFzcyBub3QgaW4gbWFuaWZlc3QgLSByZXR1cm4gZW1wdHkgYXJyYXlcbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEdldCBzdWJjbGFzcyBuYW1lcyBmcm9tIHRoZSBpbmRleFxuICAgICAgICBjb25zdCBzdWJjbGFzc19uYW1lcyA9IE1hbmlmZXN0Ll9zdWJjbGFzc19pbmRleFtiYXNlX2NsYXNzX25hbWVdIHx8IFtdO1xuXG4gICAgICAgIC8vIENvbnZlcnQgbmFtZXMgdG8gYWN0dWFsIGNsYXNzIG9iamVjdHNcbiAgICAgICAgY29uc3Qgc3ViY2xhc3Nfb2JqZWN0cyA9IFtdO1xuICAgICAgICBmb3IgKGxldCBzdWJjbGFzc19uYW1lIG9mIHN1YmNsYXNzX25hbWVzKSB7XG4gICAgICAgICAgICBjb25zdCBjbGFzc2RhdGEgPSBNYW5pZmVzdC5fY2xhc3Nlc1tzdWJjbGFzc19uYW1lXTtcbiAgICAgICAgICAgIHN1YmNsYXNzX29iamVjdHMucHVzaChjbGFzc2RhdGEuY2xhc3MpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU29ydCBieSBjbGFzcyBuYW1lIGZvciBkZXRlcm1pbmlzdGljIGJlaGF2aW9yXG4gICAgICAgIHN1YmNsYXNzX29iamVjdHMuc29ydCgoYSwgYikgPT4ge1xuICAgICAgICAgICAgY29uc3QgbmFtZV9hID0gYS5fbmFtZSB8fCBhLm5hbWU7XG4gICAgICAgICAgICBjb25zdCBuYW1lX2IgPSBiLl9uYW1lIHx8IGIubmFtZTtcbiAgICAgICAgICAgIHJldHVybiBuYW1lX2EubG9jYWxlQ29tcGFyZShuYW1lX2IpO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gc3ViY2xhc3Nfb2JqZWN0cztcbiAgICB9XG59XG5cbi8vIFJTWCBtYW5pZmVzdCBhdXRvbWF0aWNhbGx5IG1ha2VzIGNsYXNzZXMgZ2xvYmFsIC0gbm8gbWFudWFsIGFzc2lnbm1lbnQgbmVlZGVkXG4iXSwibWFwcGluZ3MiOiI7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNQSxRQUFRLENBQUM7RUFDWDtBQUNKO0FBQ0E7QUFDQTtFQUNJLE9BQU9DLE9BQU9BLENBQUNDLEtBQUssRUFBRTtJQUNsQjtJQUNBLElBQUksT0FBT0YsUUFBUSxDQUFDRyxRQUFRLEtBQUssV0FBVyxFQUFFO01BQzFDSCxRQUFRLENBQUNHLFFBQVEsR0FBRyxDQUFDLENBQUM7SUFDMUI7O0lBRUE7SUFDQUQsS0FBSyxDQUFDRSxPQUFPLENBQUVDLElBQUksSUFBSztNQUNwQixJQUFJQyxZQUFZLEdBQUdELElBQUksQ0FBQyxDQUFDLENBQUM7TUFDMUIsSUFBSUUsVUFBVSxHQUFHRixJQUFJLENBQUMsQ0FBQyxDQUFDO01BQ3hCLElBQUlHLGFBQWEsR0FBR0gsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUk7TUFDbkMsSUFBSUksVUFBVSxHQUFHSixJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSTs7TUFFaEM7TUFDQUwsUUFBUSxDQUFDRyxRQUFRLENBQUNJLFVBQVUsQ0FBQyxHQUFHO1FBQzVCRyxLQUFLLEVBQUVKLFlBQVk7UUFDbkJLLElBQUksRUFBRUosVUFBVTtRQUNoQkssT0FBTyxFQUFFSixhQUFhO1FBQ3RCQyxVQUFVLEVBQUVBLFVBQVUsQ0FBRztNQUM3QixDQUFDOztNQUVEO01BQ0FILFlBQVksQ0FBQ08sS0FBSyxHQUFHTixVQUFVO01BQy9CRCxZQUFZLENBQUNRLFFBQVEsR0FBR04sYUFBYTtNQUNyQ0YsWUFBWSxDQUFDUyxXQUFXLEdBQUdOLFVBQVU7SUFDekMsQ0FBQyxDQUFDOztJQUVGO0lBQ0FULFFBQVEsQ0FBQ2dCLHFCQUFxQixDQUFDLENBQUM7RUFDcEM7O0VBRUE7QUFDSjtBQUNBO0FBQ0E7QUFDQTtFQUNJLE9BQU9BLHFCQUFxQkEsQ0FBQSxFQUFHO0lBQzNCO0lBQ0FoQixRQUFRLENBQUNpQixlQUFlLEdBQUcsQ0FBQyxDQUFDOztJQUU3QjtJQUNBLEtBQUssSUFBSVYsVUFBVSxJQUFJUCxRQUFRLENBQUNHLFFBQVEsRUFBRTtNQUN0QyxNQUFNZSxTQUFTLEdBQUdsQixRQUFRLENBQUNHLFFBQVEsQ0FBQ0ksVUFBVSxDQUFDO01BQy9DLElBQUlZLGtCQUFrQixHQUFHWixVQUFVO01BQ25DLElBQUlhLGlCQUFpQixHQUFHRixTQUFTOztNQUVqQztNQUNBLE9BQU9FLGlCQUFpQixFQUFFO1FBQ3RCLE1BQU1DLFlBQVksR0FBR0QsaUJBQWlCLENBQUNSLE9BQU87UUFFOUMsSUFBSVMsWUFBWSxFQUFFO1VBQ2Q7VUFDQSxJQUFJLENBQUNyQixRQUFRLENBQUNpQixlQUFlLENBQUNJLFlBQVksQ0FBQyxFQUFFO1lBQ3pDckIsUUFBUSxDQUFDaUIsZUFBZSxDQUFDSSxZQUFZLENBQUMsR0FBRyxFQUFFO1VBQy9DOztVQUVBO1VBQ0EsSUFBSSxDQUFDckIsUUFBUSxDQUFDaUIsZUFBZSxDQUFDSSxZQUFZLENBQUMsQ0FBQ0MsUUFBUSxDQUFDZixVQUFVLENBQUMsRUFBRTtZQUM5RFAsUUFBUSxDQUFDaUIsZUFBZSxDQUFDSSxZQUFZLENBQUMsQ0FBQ0UsSUFBSSxDQUFDaEIsVUFBVSxDQUFDO1VBQzNEOztVQUVBO1VBQ0EsSUFBSVAsUUFBUSxDQUFDRyxRQUFRLENBQUNrQixZQUFZLENBQUMsRUFBRTtZQUNqQ0QsaUJBQWlCLEdBQUdwQixRQUFRLENBQUNHLFFBQVEsQ0FBQ2tCLFlBQVksQ0FBQztVQUN2RCxDQUFDLE1BQU07WUFDSDtZQUNBRCxpQkFBaUIsR0FBRyxJQUFJO1VBQzVCO1FBQ0osQ0FBQyxNQUFNO1VBQ0g7VUFDQUEsaUJBQWlCLEdBQUcsSUFBSTtRQUM1QjtNQUNKO0lBQ0o7RUFDSjs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksT0FBT0ksYUFBYUEsQ0FBQ0MsVUFBVSxFQUFFO0lBQzdCLElBQUksQ0FBQ3pCLFFBQVEsQ0FBQ0csUUFBUSxFQUFFO01BQ3BCLE9BQU8sRUFBRTtJQUNiOztJQUVBO0lBQ0EsSUFBSXVCLGlCQUFpQixHQUFHRCxVQUFVO0lBQ2xDLElBQUksT0FBT0EsVUFBVSxLQUFLLFFBQVEsRUFBRTtNQUNoQ0MsaUJBQWlCLEdBQUcxQixRQUFRLENBQUMyQixpQkFBaUIsQ0FBQ0YsVUFBVSxDQUFDO01BQzFELElBQUksQ0FBQ0MsaUJBQWlCLEVBQUU7UUFDcEIsTUFBTSxJQUFJRSxLQUFLLENBQUMseUJBQXlCSCxVQUFVLEVBQUUsQ0FBQztNQUMxRDtJQUNKO0lBRUEsTUFBTUksT0FBTyxHQUFHLEVBQUU7SUFFbEIsS0FBSyxJQUFJdEIsVUFBVSxJQUFJUCxRQUFRLENBQUNHLFFBQVEsRUFBRTtNQUN0QyxNQUFNZSxTQUFTLEdBQUdsQixRQUFRLENBQUNHLFFBQVEsQ0FBQ0ksVUFBVSxDQUFDO01BQy9DLElBQUlQLFFBQVEsQ0FBQzhCLGlCQUFpQixDQUFDWixTQUFTLENBQUNSLEtBQUssRUFBRWdCLGlCQUFpQixDQUFDLEVBQUU7UUFDaEVHLE9BQU8sQ0FBQ04sSUFBSSxDQUFDO1VBQ1RoQixVQUFVLEVBQUVBLFVBQVU7VUFDdEJELFlBQVksRUFBRVksU0FBUyxDQUFDUjtRQUM1QixDQUFDLENBQUM7TUFDTjtJQUNKOztJQUVBO0lBQ0FtQixPQUFPLENBQUNFLElBQUksQ0FBQyxDQUFDQyxDQUFDLEVBQUVDLENBQUMsS0FBS0QsQ0FBQyxDQUFDekIsVUFBVSxDQUFDMkIsYUFBYSxDQUFDRCxDQUFDLENBQUMxQixVQUFVLENBQUMsQ0FBQztJQUVoRSxPQUFPc0IsT0FBTztFQUNsQjs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtFQUNJLE9BQU9DLGlCQUFpQkEsQ0FBQ0ssUUFBUSxFQUFFQyxVQUFVLEVBQUU7SUFDM0M7SUFDQSxJQUFJQyxlQUFlLEdBQUdGLFFBQVE7SUFDOUIsSUFBSSxPQUFPQSxRQUFRLEtBQUssUUFBUSxFQUFFO01BQzlCRSxlQUFlLEdBQUdyQyxRQUFRLENBQUMyQixpQkFBaUIsQ0FBQ1EsUUFBUSxDQUFDO01BQ3RELElBQUksQ0FBQ0UsZUFBZSxFQUFFO1FBQ2xCO1FBQ0EsT0FBTyxLQUFLO01BQ2hCO0lBQ0o7SUFFQSxJQUFJQyxpQkFBaUIsR0FBR0YsVUFBVTtJQUNsQyxJQUFJLE9BQU9BLFVBQVUsS0FBSyxRQUFRLEVBQUU7TUFDaENFLGlCQUFpQixHQUFHdEMsUUFBUSxDQUFDMkIsaUJBQWlCLENBQUNTLFVBQVUsQ0FBQztNQUMxRCxJQUFJLENBQUNFLGlCQUFpQixFQUFFO1FBQ3BCO1FBQ0EsTUFBTSxJQUFJVixLQUFLLENBQUMscUNBQXFDUSxVQUFVLEVBQUUsQ0FBQztNQUN0RTtJQUNKOztJQUVBO0lBQ0EsSUFBSUMsZUFBZSxLQUFLQyxpQkFBaUIsRUFBRTtNQUN2QyxPQUFPLEtBQUs7SUFDaEI7O0lBRUE7SUFDQSxJQUFJQyxhQUFhLEdBQUdGLGVBQWU7SUFDbkMsT0FBT0UsYUFBYSxFQUFFO01BQ2xCLElBQUlBLGFBQWEsS0FBS0QsaUJBQWlCLEVBQUU7UUFDckMsT0FBTyxJQUFJO01BQ2Y7TUFDQTtNQUNBLElBQUlDLGFBQWEsQ0FBQ3pCLFFBQVEsRUFBRTtRQUN4QjtRQUNBLElBQUksT0FBT3lCLGFBQWEsQ0FBQ3pCLFFBQVEsS0FBSyxRQUFRLEVBQUU7VUFDNUN5QixhQUFhLEdBQUd2QyxRQUFRLENBQUMyQixpQkFBaUIsQ0FBQ1ksYUFBYSxDQUFDekIsUUFBUSxDQUFDO1FBQ3RFLENBQUMsTUFBTTtVQUNIeUIsYUFBYSxHQUFHQSxhQUFhLENBQUN6QixRQUFRO1FBQzFDO01BQ0osQ0FBQyxNQUFNO1FBQ0h5QixhQUFhLEdBQUcsSUFBSTtNQUN4QjtJQUNKO0lBRUEsT0FBTyxLQUFLO0VBQ2hCOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7RUFDSSxPQUFPWixpQkFBaUJBLENBQUNwQixVQUFVLEVBQUU7SUFDakMsSUFBSSxDQUFDUCxRQUFRLENBQUNHLFFBQVEsSUFBSSxDQUFDSCxRQUFRLENBQUNHLFFBQVEsQ0FBQ0ksVUFBVSxDQUFDLEVBQUU7TUFDdEQsT0FBTyxJQUFJO0lBQ2Y7SUFFQSxPQUFPUCxRQUFRLENBQUNHLFFBQVEsQ0FBQ0ksVUFBVSxDQUFDLENBQUNHLEtBQUs7RUFDOUM7O0VBRUE7QUFDSjtBQUNBO0FBQ0E7RUFDSSxPQUFPOEIsZUFBZUEsQ0FBQSxFQUFHO0lBQ3JCLElBQUksQ0FBQ3hDLFFBQVEsQ0FBQ0csUUFBUSxFQUFFO01BQ3BCLE9BQU8sRUFBRTtJQUNiO0lBRUEsTUFBTXNDLE9BQU8sR0FBRyxFQUFFO0lBQ2xCLEtBQUssSUFBSWxDLFVBQVUsSUFBSVAsUUFBUSxDQUFDRyxRQUFRLEVBQUU7TUFDdEMsTUFBTWUsU0FBUyxHQUFHbEIsUUFBUSxDQUFDRyxRQUFRLENBQUNJLFVBQVUsQ0FBQztNQUMvQ2tDLE9BQU8sQ0FBQ2xCLElBQUksQ0FBQztRQUNUaEIsVUFBVSxFQUFFVyxTQUFTLENBQUNQLElBQUk7UUFDMUJMLFlBQVksRUFBRVksU0FBUyxDQUFDUixLQUFLO1FBQzdCRSxPQUFPLEVBQUVNLFNBQVMsQ0FBQ047TUFDdkIsQ0FBQyxDQUFDO0lBQ047O0lBRUE7SUFDQTZCLE9BQU8sQ0FBQ1YsSUFBSSxDQUFDLENBQUNDLENBQUMsRUFBRUMsQ0FBQyxLQUFLRCxDQUFDLENBQUN6QixVQUFVLENBQUMyQixhQUFhLENBQUNELENBQUMsQ0FBQzFCLFVBQVUsQ0FBQyxDQUFDO0lBRWhFLE9BQU9rQyxPQUFPO0VBQ2xCOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0VBQ0ksT0FBT0MsU0FBU0EsQ0FBQSxFQUFHO0lBQ2YsSUFBSUMsTUFBTSxDQUFDQyxNQUFNLElBQUlELE1BQU0sQ0FBQ0MsTUFBTSxDQUFDRixTQUFTLEVBQUU7TUFDMUMsT0FBT0MsTUFBTSxDQUFDQyxNQUFNLENBQUNGLFNBQVM7SUFDbEM7SUFDQSxPQUFPLFNBQVM7RUFDcEI7O0VBRUE7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksT0FBT0csY0FBY0EsQ0FBQ3RDLFVBQVUsRUFBRXVDLFdBQVcsRUFBRTtJQUMzQztJQUNBLElBQUksT0FBT3ZDLFVBQVUsS0FBSyxRQUFRLEVBQUU7TUFDaENBLFVBQVUsR0FBR0EsVUFBVSxDQUFDTSxLQUFLLElBQUlOLFVBQVUsQ0FBQ0ksSUFBSTtJQUNwRDtJQUVBLE1BQU1vQyxVQUFVLEdBQUcvQyxRQUFRLENBQUNHLFFBQVEsQ0FBQ0ksVUFBVSxDQUFDO0lBQ2hELElBQUksQ0FBQ3dDLFVBQVUsSUFBSSxDQUFDQSxVQUFVLENBQUN0QyxVQUFVLElBQUksQ0FBQ3NDLFVBQVUsQ0FBQ3RDLFVBQVUsQ0FBQ3FDLFdBQVcsQ0FBQyxFQUFFO01BQzlFLE9BQU8sSUFBSTtJQUNmOztJQUVBO0lBQ0EsT0FBTzlDLFFBQVEsQ0FBQ2dELHFCQUFxQixDQUFDRCxVQUFVLENBQUN0QyxVQUFVLENBQUNxQyxXQUFXLENBQUMsQ0FBQztFQUM3RTs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksT0FBT0csa0JBQWtCQSxDQUFDMUMsVUFBVSxFQUFFO0lBQ2xDO0lBQ0EsSUFBSSxPQUFPQSxVQUFVLEtBQUssUUFBUSxFQUFFO01BQ2hDQSxVQUFVLEdBQUdBLFVBQVUsQ0FBQ00sS0FBSyxJQUFJTixVQUFVLENBQUNJLElBQUk7SUFDcEQ7SUFFQSxNQUFNb0MsVUFBVSxHQUFHL0MsUUFBUSxDQUFDRyxRQUFRLENBQUNJLFVBQVUsQ0FBQztJQUNoRCxJQUFJLENBQUN3QyxVQUFVLElBQUksQ0FBQ0EsVUFBVSxDQUFDdEMsVUFBVSxFQUFFO01BQ3ZDLE9BQU8sQ0FBQyxDQUFDO0lBQ2I7O0lBRUE7SUFDQSxNQUFNeUMsTUFBTSxHQUFHLENBQUMsQ0FBQztJQUNqQixLQUFLLElBQUlKLFdBQVcsSUFBSUMsVUFBVSxDQUFDdEMsVUFBVSxFQUFFO01BQzNDeUMsTUFBTSxDQUFDSixXQUFXLENBQUMsR0FBRzlDLFFBQVEsQ0FBQ2dELHFCQUFxQixDQUFDRCxVQUFVLENBQUN0QyxVQUFVLENBQUNxQyxXQUFXLENBQUMsQ0FBQztJQUM1RjtJQUNBLE9BQU9JLE1BQU07RUFDakI7O0VBRUE7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksT0FBT0YscUJBQXFCQSxDQUFDRyxrQkFBa0IsRUFBRTtJQUM3QyxJQUFJLENBQUNDLEtBQUssQ0FBQ0MsT0FBTyxDQUFDRixrQkFBa0IsQ0FBQyxFQUFFO01BQ3BDLE9BQU8sRUFBRTtJQUNiO0lBRUEsT0FBT0Esa0JBQWtCLENBQUNHLEdBQUcsQ0FBQ0MsU0FBUyxJQUFJO01BQ3ZDLElBQUlILEtBQUssQ0FBQ0MsT0FBTyxDQUFDRSxTQUFTLENBQUMsSUFBSUEsU0FBUyxDQUFDQyxNQUFNLElBQUksQ0FBQyxFQUFFO1FBQ25ELE9BQU87VUFDSDdDLElBQUksRUFBRTRDLFNBQVMsQ0FBQyxDQUFDLENBQUM7VUFDbEJFLFNBQVMsRUFBRUYsU0FBUyxDQUFDLENBQUMsQ0FBQyxJQUFJO1FBQy9CLENBQUM7TUFDTDtNQUNBO01BQ0EsT0FBTztRQUNINUMsSUFBSSxFQUFFLFNBQVM7UUFDZjhDLFNBQVMsRUFBRTtNQUNmLENBQUM7SUFDTCxDQUFDLENBQUM7RUFDTjs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtFQUNJLE9BQU9DLGFBQWFBLENBQUNuRCxVQUFVLEVBQUV1QyxXQUFXLEVBQUVhLGNBQWMsRUFBRTtJQUMxRCxNQUFNbEQsVUFBVSxHQUFHVCxRQUFRLENBQUM2QyxjQUFjLENBQUN0QyxVQUFVLEVBQUV1QyxXQUFXLENBQUM7SUFDbkUsSUFBSSxDQUFDckMsVUFBVSxFQUFFO01BQ2IsT0FBTyxLQUFLO0lBQ2hCO0lBRUEsT0FBT0EsVUFBVSxDQUFDbUQsSUFBSSxDQUFDQyxDQUFDLElBQUlBLENBQUMsQ0FBQ2xELElBQUksS0FBS2dELGNBQWMsQ0FBQztFQUMxRDs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7RUFDSSxPQUFPRyxvQkFBb0JBLENBQUNyQyxVQUFVLEVBQUU7SUFDcEM7SUFDQSxJQUFJLENBQUN6QixRQUFRLENBQUNpQixlQUFlLEVBQUU7TUFDM0JqQixRQUFRLENBQUNnQixxQkFBcUIsQ0FBQyxDQUFDO0lBQ3BDOztJQUVBO0lBQ0EsSUFBSStDLGVBQWUsR0FBR3RDLFVBQVU7SUFDaEMsSUFBSSxPQUFPQSxVQUFVLEtBQUssUUFBUSxFQUFFO01BQ2hDc0MsZUFBZSxHQUFHdEMsVUFBVSxDQUFDWixLQUFLLElBQUlZLFVBQVUsQ0FBQ2QsSUFBSTtJQUN6RDs7SUFFQTtJQUNBLElBQUksQ0FBQ1gsUUFBUSxDQUFDRyxRQUFRLENBQUM0RCxlQUFlLENBQUMsRUFBRTtNQUNyQztNQUNBLE9BQU8sRUFBRTtJQUNiOztJQUVBO0lBQ0EsTUFBTUMsY0FBYyxHQUFHaEUsUUFBUSxDQUFDaUIsZUFBZSxDQUFDOEMsZUFBZSxDQUFDLElBQUksRUFBRTs7SUFFdEU7SUFDQSxNQUFNRSxnQkFBZ0IsR0FBRyxFQUFFO0lBQzNCLEtBQUssSUFBSUMsYUFBYSxJQUFJRixjQUFjLEVBQUU7TUFDdEMsTUFBTTlDLFNBQVMsR0FBR2xCLFFBQVEsQ0FBQ0csUUFBUSxDQUFDK0QsYUFBYSxDQUFDO01BQ2xERCxnQkFBZ0IsQ0FBQzFDLElBQUksQ0FBQ0wsU0FBUyxDQUFDUixLQUFLLENBQUM7SUFDMUM7O0lBRUE7SUFDQXVELGdCQUFnQixDQUFDbEMsSUFBSSxDQUFDLENBQUNDLENBQUMsRUFBRUMsQ0FBQyxLQUFLO01BQzVCLE1BQU1rQyxNQUFNLEdBQUduQyxDQUFDLENBQUNuQixLQUFLLElBQUltQixDQUFDLENBQUNyQixJQUFJO01BQ2hDLE1BQU15RCxNQUFNLEdBQUduQyxDQUFDLENBQUNwQixLQUFLLElBQUlvQixDQUFDLENBQUN0QixJQUFJO01BQ2hDLE9BQU93RCxNQUFNLENBQUNqQyxhQUFhLENBQUNrQyxNQUFNLENBQUM7SUFDdkMsQ0FBQyxDQUFDO0lBRUYsT0FBT0gsZ0JBQWdCO0VBQzNCO0FBQ0o7O0FBRUEiLCJpZ25vcmVMaXN0IjpbXX0=