all files / fc-er/ Model.js

82.54% Statements 156/189
69% Branches 69/100
75.61% Functions 31/41
86.08% Lines 136/158
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 34020×     64×   64×                 18× 17×   13×     17×     18×       18× 18×   18× 15×   15×                                               10× 10× 13× 13× 13× 11×     13×       10×     34×     32×     28×     24× 14×     10×             13×         13× 13× 13×     13×             59× 59× 59×   59× 57×           64×   64×   64× 64×   64× 22×     64× 64×                       14×         14× 14× 14× 14×                     24×         28×   28× 28× 13× 13×     28×         31×   31× 31× 32× 31× 31× 30×         31×     31×                                                                                                                                                  
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; Eif ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { Eif (protoProps) defineProperties(Constructor.prototype, protoProps); Iif (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
 
function _defaults(obj, defaults) { var keys = Object.getOwnPropertyNames(defaults); for (var i = 0; i < keys.length; i++) { var key = keys[i]; var value = Object.getOwnPropertyDescriptor(defaults, key); if (value && value.configurable && obj[key] === undefined) { Object.defineProperty(obj, key, value); } } return obj; }
 
function _classCallCheck(instance, Constructor) { Iif (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
 
function _possibleConstructorReturn(self, call) { Iif (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
 
function _inherits(subClass, superClass) { Iif (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); Eif (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : _defaults(subClass, superClass); }
 
Eif (typeof define !== 'function') {
    var define = require('amdefine')(module);
}
 
define(function (require) {
    'use strict';
 
    var util = require('./util');
    var Deferred = require('./Deferred');
    var EventTarget = require('fc-mini-event/EventTarget');
 
    var SILENT = { silent: true };
 
    var loadData = function loadData(model, options) {
        var addDataToModel = function addDataToModel(value) {
            if (options.dump) {
                model.fill(value, SILENT);
            } else {
                model.set(options.name, value, SILENT);
            }
 
            return { success: true, name: options.name, options: options, value: value };
        };
 
        var buildError = function buildError(error) {
            return { success: false, name: options.name, options: options, error: error };
        };
 
        try {
            var value = options.retrieve(model, options);
 
            if (Deferred.isPromise(value)) {
                if (typeof value.abort === 'function') {
                    model.addPendingWorker(value);
                }
                return value.then(addDataToModel, function (error) {
                    error = buildError(error);
                    try {
                        var result = model.handleError(error);
                        return addDataToModel(result);
                    } catch (ex) {
                        if (ex.success === false) {
                            throw ex;
                        } else {
                            throw buildError(ex);
                        }
                    }
                });
            } else {
                var result = addDataToModel(value);
                return Promise.resolve(result);
            }
        } catch (ex) {
            var error = buildError(ex);
            return Promise.reject(error);
        }
    };
 
    var loadSequence = function loadSequence(model, datasource) {
        var loading = Promise.resolve();
        for (var i = 0; i < datasource.length; i++) {
            var unit = datasource[i];
            var task = util.bind(_load, null, model, unit);
            loading = loading.then(task);
        }
        return loading;
    };
 
    var loadParallel = function loadParallel(model, datasource) {
        var workers = [];
        for (var name in datasource) {
            Eif (datasource.hasOwnProperty(name)) {
                var unit = datasource[name];
                if (typeof unit === 'function') {
                    unit = { retrieve: unit, name: name };
                } else Eif (typeof unit.retrieve === 'function') {
                    unit = util.mix({ name: name }, unit);
                }
 
                workers.push(_load(model, unit));
            }
        }
 
        return Promise.all(workers);
    };
 
    var _load = function _load(model, datasource) {
        if (!datasource) {
            return Promise.resolve();
        }
 
        if (typeof datasource === 'function') {
            var options = { retrieve: datasource, dump: true };
            return loadData(model, options);
        }
 
        if (datasource instanceof Array) {
            return loadSequence(model, datasource);
        }
 
        if (typeof datasource.retrieve === 'function') {
            return loadData(model, datasource);
        }
 
        return loadParallel(model, datasource);
    };
 
    var removePendingWorker = function removePendingWorker(model, worker) {
        for (var i = 0; i < model.pendingWorkers.length; i++) {
            Eif (model.pendingWorkers[i] === worker) {
                model.pendingWorkers.splice(i, 1);
                return;
            }
        }
    };
 
    var forwardToPrepare = function forwardToPrepare() {
        var processError = function processError(ex) {
            var error = { success: false, name: '$prepare', options: {}, error: ex };
            throw error;
        };
 
        try {
            var preparing = this.prepare();
            Iif (Deferred.isPromise(preparing)) {
                return preparing.then(null, processError);
            } else {
                return preparing;
            }
        } catch (ex) {
            processError(ex);
        }
    };
 
    var setProperty = function setProperty(model, name, value) {
        var type = model.store.hasOwnProperty(name) ? 'change' : 'add';
        var oldValue = model.store[name];
        model.store[name] = value;
 
        if (oldValue !== value) {
            return { type: type, name: name, oldValue: oldValue, newValue: value };
        }
 
        return null;
    };
 
    var Model = function (_EventTarget) {
        _inherits(Model, _EventTarget);
 
        function Model(args) {
            _classCallCheck(this, Model);
 
            var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(Model).call(this));
 
            _this.store = {};
            _this.pendingWorkers = [];
 
            if (args) {
                _this.fill(args, SILENT);
            }
 
            _this.initialize();
            return _this;
        }
 
        _createClass(Model, [{
            key: 'initialize',
            value: function initialize() {}
        }, {
            key: 'addPendingWorker',
            value: function addPendingWorker(worker) {
                this.pendingWorkers.push(worker);
                var cbk = util.bind(removePendingWorker, null, this, worker);
                worker.then(cbk, cbk);
            }
        }, {
            key: 'getDatasource',
            value: function getDatasource() {
                return this.datasource;
            }
        }, {
            key: 'load',
            value: function load() {
                try {
                    var datasource = this.getDatasource();
                    var loading = _load(this, datasource);
                    return loading.then(util.bind(forwardToPrepare, this));
                } catch (ex) {
                    return Promise.reject(ex);
                }
            }
        }, {
            key: 'prepare',
            value: function prepare() {}
        }, {
            key: 'get',
            value: function get(name) {
                return this.store[name];
            }
        }, {
            key: 'set',
            value: function set(name, value, options) {
                options = options || {};
 
                var record = setProperty(this, name, value);
                if (record && !options.silent) {
                    var event = { changes: [record] };
                    this.fire('change', event);
                }
 
                return value;
            }
        }, {
            key: 'fill',
            value: function fill(extension, options) {
                options = options || {};
 
                var changes = [];
                for (var name in extension) {
                    if (extension.hasOwnProperty(name)) {
                        var record = setProperty(this, name, extension[name]);
                        if (record) {
                            changes.push(record);
                        }
                    }
                }
 
                if (changes.length && !options.silent) {
                    var event = { changes: changes };
                    this.fire('change', event);
                }
 
                return extension;
            }
        }, {
            key: 'remove',
            value: function remove(name, options) {
                if (!this.store.hasOwnProperty(name)) {
                    return;
                }
 
                options = options || {};
                var value = this.store[name];
                delete this.store[name];
 
                if (!options.silent) {
                    var event = { changes: [{ type: 'remove', name: name, oldValue: value, newValue: undefined }] };
                    this.fire('change', event);
                }
 
                return value;
            }
        }, {
            key: 'getAsModel',
            value: function getAsModel(name) {
                var value = this.get(name);
                Iif (!value || {}.toString.call(value) !== '[object Object]') {
                    return new Model();
                } else {
                    return new Model(value);
                }
            }
        }, {
            key: 'dump',
            value: function dump() {
                return util.mix({}, this.store);
            }
        }, {
            key: 'has',
            value: function has(name) {
                return this.store.hasOwnProperty(name);
            }
        }, {
            key: 'hasValue',
            value: function hasValue(name) {
                return this.has(name) && this.store[name] != null;
            }
        }, {
            key: 'hasReadableValue',
            value: function hasReadableValue(name) {
                return this.hasValue(name) && this.store[name] !== '';
            }
        }, {
            key: 'valueOf',
            value: function valueOf() {
                return this.dump();
            }
        }, {
            key: 'clone',
            value: function clone() {
                return new Model(this.store);
            }
        }, {
            key: 'handleError',
            value: function handleError(error) {
                throw error;
            }
        }, {
            key: 'dispose',
            value: function dispose() {
                Eif (this.pendingWorkers) {
                    for (var i = 0; i < this.pendingWorkers.length; i++) {
                        var worker = this.pendingWorkers[i];
                        Eif (typeof worker.abort === 'function') {
                            try {
                                worker.abort();
                            } catch (ex) {}
                        }
                    }
                    this.pendingWorkers = null;
                }
            }
        }, {
            key: 'setContext',
            value: function setContext(context) {
                this.context = context;
            }
        }, {
            key: 'getContext',
            value: function getContext() {
                return this.context;
            }
        }]);
 
        return Model;
    }(EventTarget);
 
    return Model;
});
//# sourceMappingURL=data:application/json;base64,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QUFDTix1QkFBTyxLQUFLLEtBQUwsQ0FBVyxjQUFYLENBQTBCLElBQTFCLENBQVAsQ0FETTs7OztxQ0FJRCxNQUFNO0FBQ1gsdUJBQU8sS0FBSyxHQUFMLENBQVMsSUFBVCxLQUFrQixLQUFLLEtBQUwsQ0FBVyxJQUFYLEtBQW9CLElBQXBCLENBRGQ7Ozs7NkNBSUUsTUFBTTtBQUNuQix1QkFBTyxLQUFLLFFBQUwsQ0FBYyxJQUFkLEtBQXVCLEtBQUssS0FBTCxDQUFXLElBQVgsTUFBcUIsRUFBckIsQ0FEWDs7OztzQ0FJYjtBQUNOLHVCQUFPLEtBQUssSUFBTCxFQUFQLENBRE07Ozs7b0NBSUY7QUFDSix1QkFBTyxJQUFJLEtBQUosQ0FBVSxLQUFLLEtBQUwsQ0FBakIsQ0FESTs7Ozt3Q0FJSSxPQUFPO0FBQ2Ysc0JBQU0sS0FBTixDQURlOzs7O3NDQUlUO0FBQ04sb0JBQUksS0FBSyxjQUFMLEVBQXFCO0FBQ3JCLHlCQUFLLElBQUksSUFBSSxDQUFKLEVBQU8sSUFBSSxLQUFLLGNBQUwsQ0FBb0IsTUFBcEIsRUFBNEIsR0FBaEQsRUFBcUQ7QUFDakQsNEJBQU0sU0FBUyxLQUFLLGNBQUwsQ0FBb0IsQ0FBcEIsQ0FBVCxDQUQyQztBQUVqRCw0QkFBSSxPQUFPLE9BQU8sS0FBUCxLQUFpQixVQUF4QixFQUFvQztBQUNwQyxnQ0FBSTtBQUNBLHVDQUFPLEtBQVAsR0FEQTs2QkFBSixDQUdBLE9BQU8sRUFBUCxFQUFXLEVBQVg7eUJBSko7cUJBRko7QUFVQSx5QkFBSyxjQUFMLEdBQXNCLElBQXRCLENBWHFCO2lCQUF6Qjs7Ozt1Q0FlTyxTQUFTO0FBQ2hCLHFCQUFLLE9BQUwsR0FBZSxPQUFmLENBRGdCOzs7O3lDQUlQO0FBQ1QsdUJBQU8sS0FBSyxPQUFMLENBREU7Ozs7O01BdkpHLGFBcEpFOztBQWlUdEIsV0FBTyxLQUFQLENBalRzQjtDQUFuQixDQUFQIiwiZmlsZSI6Ik1vZGVsLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaWYgKHR5cGVvZiBkZWZpbmUgIT09ICdmdW5jdGlvbicpIHt2YXIgZGVmaW5lID0gcmVxdWlyZSgnYW1kZWZpbmUnKShtb2R1bGUpfVxuXG5kZWZpbmUoZnVuY3Rpb24gKHJlcXVpcmUpIHtcbiAgICAndXNlIHN0cmljdCc7XG5cbiAgICBjb25zdCB1dGlsID0gcmVxdWlyZSgnLi91dGlsJyk7XG4gICAgY29uc3QgRGVmZXJyZWQgPSByZXF1aXJlKCcuL0RlZmVycmVkJyk7XG4gICAgY29uc3QgRXZlbnRUYXJnZXQgPSByZXF1aXJlKCdmYy1taW5pLWV2ZW50L0V2ZW50VGFyZ2V0Jyk7XG5cbiAgICBjb25zdCBTSUxFTlQgPSB7c2lsZW50OiB0cnVlfTtcblxuICAgIGNvbnN0IGxvYWREYXRhID0gKG1vZGVsLCBvcHRpb25zKSA9PiB7XG4gICAgICAgIGNvbnN0IGFkZERhdGFUb01vZGVsID0gKHZhbHVlKSA9PiB7XG4gICAgICAgICAgICBpZiAob3B0aW9ucy5kdW1wKSB7XG4gICAgICAgICAgICAgICAgbW9kZWwuZmlsbCh2YWx1ZSwgU0lMRU5UKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIG1vZGVsLnNldChvcHRpb25zLm5hbWUsIHZhbHVlLCBTSUxFTlQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4ge3N1Y2Nlc3M6IHRydWUsIG5hbWU6IG9wdGlvbnMubmFtZSwgb3B0aW9ucywgdmFsdWV9O1xuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IGJ1aWxkRXJyb3IgPSAoZXJyb3IpID0+ICh7c3VjY2VzczogZmFsc2UsIG5hbWU6IG9wdGlvbnMubmFtZSwgb3B0aW9ucywgZXJyb3J9KTtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBvcHRpb25zLnJldHJpZXZlKG1vZGVsLCBvcHRpb25zKTtcblxuICAgICAgICAgICAgaWYgKERlZmVycmVkLmlzUHJvbWlzZSh2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlLmFib3J0ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vZGVsLmFkZFBlbmRpbmdXb3JrZXIodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUudGhlbihhZGREYXRhVG9Nb2RlbCwgKGVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yID0gYnVpbGRFcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSBtb2RlbC5oYW5kbGVFcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYWRkRGF0YVRvTW9kZWwocmVzdWx0KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjYXRjaCAoZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChleC5zdWNjZXNzID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgYnVpbGRFcnJvcihleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGFkZERhdGFUb01vZGVsKHZhbHVlKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHJlc3VsdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGV4KSB7XG4gICAgICAgICAgICBjb25zdCBlcnJvciA9IGJ1aWxkRXJyb3IoZXgpO1xuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGVycm9yKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBjb25zdCBsb2FkU2VxdWVuY2UgPSAobW9kZWwsIGRhdGFzb3VyY2UpID0+IHtcbiAgICAgICAgbGV0IGxvYWRpbmcgPSBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkYXRhc291cmNlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBjb25zdCB1bml0ID0gZGF0YXNvdXJjZVtpXTtcbiAgICAgICAgICAgIGNvbnN0IHRhc2sgPSB1dGlsLmJpbmQobG9hZCwgbnVsbCwgbW9kZWwsIHVuaXQpO1xuICAgICAgICAgICAgbG9hZGluZyA9IGxvYWRpbmcudGhlbih0YXNrKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbG9hZGluZztcbiAgICB9O1xuXG4gICAgY29uc3QgbG9hZFBhcmFsbGVsID0gKG1vZGVsLCBkYXRhc291cmNlKSA9PiB7XG4gICAgICAgIGNvbnN0IHdvcmtlcnMgPSBbXTtcbiAgICAgICAgZm9yIChjb25zdCBuYW1lIGluIGRhdGFzb3VyY2UpIHtcbiAgICAgICAgICAgIGlmIChkYXRhc291cmNlLmhhc093blByb3BlcnR5KG5hbWUpKSB7XG4gICAgICAgICAgICAgICAgbGV0IHVuaXQgPSBkYXRhc291cmNlW25hbWVdO1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdW5pdCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgICAgICB1bml0ID0ge3JldHJpZXZlOiB1bml0LCBuYW1lfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIHVuaXQucmV0cmlldmUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAgdW5pdCA9IHV0aWwubWl4KHtuYW1lfSwgdW5pdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgd29ya2Vycy5wdXNoKGxvYWQobW9kZWwsIHVuaXQpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBQcm9taXNlLmFsbCh3b3JrZXJzKTtcbiAgICB9O1xuXG4gICAgY29uc3QgbG9hZCA9IChtb2RlbCwgZGF0YXNvdXJjZSkgPT4ge1xuICAgICAgICBpZiAoIWRhdGFzb3VyY2UpIHtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgZGF0YXNvdXJjZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHtyZXRyaWV2ZTogZGF0YXNvdXJjZSwgZHVtcDogdHJ1ZX07XG4gICAgICAgICAgICByZXR1cm4gbG9hZERhdGEobW9kZWwsIG9wdGlvbnMpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGRhdGFzb3VyY2UgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgICAgICAgcmV0dXJuIGxvYWRTZXF1ZW5jZShtb2RlbCwgZGF0YXNvdXJjZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIGRhdGFzb3VyY2UucmV0cmlldmUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHJldHVybiBsb2FkRGF0YShtb2RlbCwgZGF0YXNvdXJjZSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbG9hZFBhcmFsbGVsKG1vZGVsLCBkYXRhc291cmNlKTtcbiAgICB9O1xuXG4gICAgY29uc3QgcmVtb3ZlUGVuZGluZ1dvcmtlciA9IChtb2RlbCwgd29ya2VyKSA9PiB7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbW9kZWwucGVuZGluZ1dvcmtlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmIChtb2RlbC5wZW5kaW5nV29ya2Vyc1tpXSA9PT0gd29ya2VyKSB7XG4gICAgICAgICAgICAgICAgbW9kZWwucGVuZGluZ1dvcmtlcnMuc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBjb25zdCBmb3J3YXJkVG9QcmVwYXJlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBwcm9jZXNzRXJyb3IgPSAoZXgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGVycm9yID0ge3N1Y2Nlc3M6IGZhbHNlLCBuYW1lOiAnJHByZXBhcmUnLCBvcHRpb25zOiB7fSwgZXJyb3I6IGV4fTtcbiAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9O1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBwcmVwYXJpbmcgPSB0aGlzLnByZXBhcmUoKTtcbiAgICAgICAgICAgIGlmIChEZWZlcnJlZC5pc1Byb21pc2UocHJlcGFyaW5nKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBwcmVwYXJpbmcudGhlbihudWxsLCBwcm9jZXNzRXJyb3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHByZXBhcmluZztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZXgpIHtcbiAgICAgICAgICAgIHByb2Nlc3NFcnJvcihleCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgY29uc3Qgc2V0UHJvcGVydHkgPSAobW9kZWwsIG5hbWUsIHZhbHVlKSA9PiB7XG4gICAgICAgIGNvbnN0IHR5cGUgPSBtb2RlbC5zdG9yZS5oYXNPd25Qcm9wZXJ0eShuYW1lKSA/ICdjaGFuZ2UnIDogJ2FkZCc7XG4gICAgICAgIGNvbnN0IG9sZFZhbHVlID0gbW9kZWwuc3RvcmVbbmFtZV07XG4gICAgICAgIG1vZGVsLnN0b3JlW25hbWVdID0gdmFsdWU7XG5cbiAgICAgICAgaWYgKG9sZFZhbHVlICE9PSB2YWx1ZSkge1xuICAgICAgICAgICAgcmV0dXJuIHt0eXBlLCBuYW1lLCBvbGRWYWx1ZSwgbmV3VmFsdWU6IHZhbHVlfTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH07XG5cbiAgICBjbGFzcyBNb2RlbCBleHRlbmRzIEV2ZW50VGFyZ2V0IHtcbiAgICAgICAgY29uc3RydWN0b3IoYXJncykge1xuICAgICAgICAgICAgc3VwZXIoKTtcblxuICAgICAgICAgICAgdGhpcy5zdG9yZSA9IHt9O1xuICAgICAgICAgICAgdGhpcy5wZW5kaW5nV29ya2VycyA9IFtdO1xuXG4gICAgICAgICAgICBpZiAoYXJncykge1xuICAgICAgICAgICAgICAgIHRoaXMuZmlsbChhcmdzLCBTSUxFTlQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLmluaXRpYWxpemUoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGluaXRpYWxpemUoKSB7fVxuXG4gICAgICAgIGFkZFBlbmRpbmdXb3JrZXIod29ya2VyKSB7XG4gICAgICAgICAgICB0aGlzLnBlbmRpbmdXb3JrZXJzLnB1c2god29ya2VyKTtcbiAgICAgICAgICAgIGNvbnN0IGNiayA9IHV0aWwuYmluZChyZW1vdmVQZW5kaW5nV29ya2VyLCBudWxsLCB0aGlzLCB3b3JrZXIpO1xuICAgICAgICAgICAgd29ya2VyLnRoZW4oY2JrLCBjYmspO1xuICAgICAgICB9XG5cbiAgICAgICAgZ2V0RGF0YXNvdXJjZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRhdGFzb3VyY2U7XG4gICAgICAgIH1cblxuICAgICAgICBsb2FkKCkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBjb25zdCBkYXRhc291cmNlID0gdGhpcy5nZXREYXRhc291cmNlKCk7XG4gICAgICAgICAgICAgICAgY29uc3QgbG9hZGluZyA9IGxvYWQodGhpcywgZGF0YXNvdXJjZSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGxvYWRpbmcudGhlbih1dGlsLmJpbmQoZm9yd2FyZFRvUHJlcGFyZSwgdGhpcykpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGV4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGV4KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHByZXBhcmUoKSB7fVxuXG4gICAgICAgIGdldChuYW1lKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zdG9yZVtuYW1lXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHNldChuYW1lLCB2YWx1ZSwgb3B0aW9ucykge1xuICAgICAgICAgICAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cbiAgICAgICAgICAgIGNvbnN0IHJlY29yZCA9IHNldFByb3BlcnR5KHRoaXMsIG5hbWUsIHZhbHVlKTtcbiAgICAgICAgICAgIGlmIChyZWNvcmQgJiYgIW9wdGlvbnMuc2lsZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZXZlbnQgPSB7Y2hhbmdlczogW3JlY29yZF19O1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZSgnY2hhbmdlJywgZXZlbnQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH1cblxuICAgICAgICBmaWxsKGV4dGVuc2lvbiwgb3B0aW9ucykge1xuICAgICAgICAgICAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cbiAgICAgICAgICAgIGNvbnN0IGNoYW5nZXMgPSBbXTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgbmFtZSBpbiBleHRlbnNpb24pIHtcbiAgICAgICAgICAgICAgICBpZiAoZXh0ZW5zaW9uLmhhc093blByb3BlcnR5KG5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlY29yZCA9IHNldFByb3BlcnR5KHRoaXMsIG5hbWUsIGV4dGVuc2lvbltuYW1lXSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZWNvcmQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoYW5nZXMucHVzaChyZWNvcmQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoY2hhbmdlcy5sZW5ndGggJiYgIW9wdGlvbnMuc2lsZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZXZlbnQgPSB7Y2hhbmdlc307XG4gICAgICAgICAgICAgICAgdGhpcy5maXJlKCdjaGFuZ2UnLCBldmVudCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBleHRlbnNpb247XG4gICAgICAgIH1cblxuICAgICAgICByZW1vdmUobmFtZSwgb3B0aW9ucykge1xuICAgICAgICAgICAgaWYgKCF0aGlzLnN0b3JlLmhhc093blByb3BlcnR5KG5hbWUpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gdGhpcy5zdG9yZVtuYW1lXTtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnN0b3JlW25hbWVdO1xuXG4gICAgICAgICAgICBpZiAoIW9wdGlvbnMuc2lsZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZXZlbnQgPSB7Y2hhbmdlczogW3t0eXBlOiAncmVtb3ZlJywgbmFtZSwgb2xkVmFsdWU6IHZhbHVlLCBuZXdWYWx1ZTogdW5kZWZpbmVkfV19O1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZSgnY2hhbmdlJywgZXZlbnQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH1cblxuICAgICAgICBnZXRBc01vZGVsKG5hbWUpIHtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gdGhpcy5nZXQobmFtZSk7XG4gICAgICAgICAgICBpZiAoIXZhbHVlIHx8IHt9LnRvU3RyaW5nLmNhbGwodmFsdWUpICE9PSAnW29iamVjdCBPYmplY3RdJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgTW9kZWwoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgTW9kZWwodmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZHVtcCgpIHtcbiAgICAgICAgICAgIHJldHVybiB1dGlsLm1peCh7fSwgdGhpcy5zdG9yZSk7XG4gICAgICAgIH1cblxuICAgICAgICBoYXMobmFtZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc3RvcmUuaGFzT3duUHJvcGVydHkobmFtZSk7XG4gICAgICAgIH1cblxuICAgICAgICBoYXNWYWx1ZShuYW1lKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5oYXMobmFtZSkgJiYgdGhpcy5zdG9yZVtuYW1lXSAhPSBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgaGFzUmVhZGFibGVWYWx1ZShuYW1lKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5oYXNWYWx1ZShuYW1lKSAmJiB0aGlzLnN0b3JlW25hbWVdICE9PSAnJztcbiAgICAgICAgfVxuXG4gICAgICAgIHZhbHVlT2YoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kdW1wKCk7XG4gICAgICAgIH1cblxuICAgICAgICBjbG9uZSgpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgTW9kZWwodGhpcy5zdG9yZSk7XG4gICAgICAgIH1cblxuICAgICAgICBoYW5kbGVFcnJvcihlcnJvcikge1xuICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cblxuICAgICAgICBkaXNwb3NlKCkge1xuICAgICAgICAgICAgaWYgKHRoaXMucGVuZGluZ1dvcmtlcnMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMucGVuZGluZ1dvcmtlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgd29ya2VyID0gdGhpcy5wZW5kaW5nV29ya2Vyc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB3b3JrZXIuYWJvcnQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd29ya2VyLmFib3J0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXRjaCAoZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnBlbmRpbmdXb3JrZXJzID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHNldENvbnRleHQoY29udGV4dCkge1xuICAgICAgICAgICAgdGhpcy5jb250ZXh0ID0gY29udGV4dDtcbiAgICAgICAgfVxuXG4gICAgICAgIGdldENvbnRleHQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb250ZXh0O1xuICAgICAgICB9XG5cbiAgICB9XG5cbiAgICByZXR1cm4gTW9kZWw7XG59KTtcbiJdfQ==