UNPKG

kepler.gl.geoiq

Version:

kepler.gl is a webgl based application to visualize large scale location data in the browser

541 lines 57.4 kB
"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.mergeWidgets = mergeWidgets;
exports.mergeFilters = mergeFilters;
exports.mergeLayers = mergeLayers;
exports.mergeInteractions = mergeInteractions;
exports.mergeInteractionTooltipConfig = mergeInteractionTooltipConfig;
exports.mergeLayerBlending = mergeLayerBlending;
exports.validateSavedLayerColumns = validateSavedLayerColumns;
exports.validateSavedTextLabel = validateSavedTextLabel;
exports.validateSavedVisualChannels = validateSavedVisualChannels;
exports.validateLayerWithData = validateLayerWithData;
exports.validateWidgetAndConfig = validateWidgetAndConfig;
exports.validateFilterWithData = validateFilterWithData;

var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));

var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));

var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));

var _lodash = _interopRequireDefault(require("lodash.uniq"));

var _lodash2 = _interopRequireDefault(require("lodash.pick"));

var _filterUtils = require("../utils/filter-utils");

var _widgetUtils = require("../utils/widget-utils/widget-utils");

var _defaultSettings = require("../constants/default-settings");

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

/**
 * Merge loaded widgets with current state, if no widget are loaded
 * save it for later
 *
 * @param {*} state
 * @param {*} widgetsToMerge
 * @return {onject} updatedState
 */
function mergeWidgets(state, widgetsToMerge) {
  var mergedWidget = [];
  var unmerged = [];
  var datasets = state.datasets;

  if (!Array.isArray(widgetsToMerge) || !widgetsToMerge.length) {
    return state;
  } // console.log(state);


  widgetsToMerge.forEach(function (widget) {
    if (datasets[widget.config.dataId]) {
      // datasets are already loaded
      var validateWidget = validateWidgetAndConfig(datasets[widget.config.dataId], widget, state.widgetClasses, state);

      if (validateWidget) {
        mergedWidget.push(validateWidget);
      }
    } else {
      // datasets not yet loaded
      unmerged.push(widget);
    }
  }); // console.log(mergedWidget);

  var widgets = [].concat((0, _toConsumableArray2["default"])(state.widgets), mergedWidget);
  var newWidgetOrder = mergedWidget.map(function (_, i) {
    return state.widgets.length + i;
  }); // put new layers in front of current layers

  var widgetOrder = [].concat((0, _toConsumableArray2["default"])(newWidgetOrder), (0, _toConsumableArray2["default"])(state.widgetOrder)); // console.log('mergeWidgets', widgets);

  return _objectSpread({}, state, {
    widgets: widgets,
    widgetOrder: widgetOrder,
    widgetToBeMerged: unmerged
  });
}
/**
 * Merge loaded filters with current state, if no fields or data are loaded
 * save it for later
 *
 * @param {Object} state
 * @param {Object[]} filtersToMerge
 * @return {Object} updatedState
 */


function mergeFilters(state, filtersToMerge) {
  var merged = [];
  var unmerged = [];
  var datasets = state.datasets;

  if (!Array.isArray(filtersToMerge) || !filtersToMerge.length) {
    return state;
  } // merge filters


  filtersToMerge.forEach(function (filter) {
    // match filter.dataId with current datesets id
    // uploaded data need to have the same dataId with the filter
    if (datasets[filter.dataId]) {
      // datasets is already loaded
      var validateFilter = validateFilterWithData(datasets[filter.dataId], filter);

      if (validateFilter) {
        merged.push(validateFilter);
      }
    } else {
      // datasets not yet loaded
      unmerged.push(filter);
    }
  }); // filter data

  var updatedFilters = [].concat((0, _toConsumableArray2["default"])(state.filters || []), merged);
  var datasetToFilter = (0, _lodash["default"])(merged.map(function (d) {
    return d.dataId;
  }));
  var updatedDataset = datasetToFilter.reduce(function (accu, dataId) {
    return _objectSpread({}, accu, (0, _defineProperty2["default"])({}, dataId, _objectSpread({}, datasets[dataId], {}, (0, _filterUtils.filterData)(datasets[dataId].allData, dataId, updatedFilters))));
  }, datasets);
  return _objectSpread({}, state, {
    filters: updatedFilters,
    datasets: updatedDataset,
    filterToBeMerged: unmerged
  });
}
/**
 * Merge layers from de-serialized state, if no fields or data are loaded
 * save it for later
 *
 * @param {object} state
 * @param {Object[]} layersToMerge
 * @return {Object} state
 */


function mergeLayers(state, layersToMerge) {
  var mergedLayer = [];
  var unmerged = [];
  var datasets = state.datasets;

  if (!Array.isArray(layersToMerge) || !layersToMerge.length) {
    return state;
  }

  layersToMerge.forEach(function (layer) {
    if (datasets[layer.config.dataId]) {
      // datasets are already loaded
      var validateLayer = validateLayerWithData(datasets[layer.config.dataId], layer, state.layerClasses);

      if (validateLayer) {
        mergedLayer.push(validateLayer);
      }
    } else {
      // datasets not yet loaded
      unmerged.push(layer);
    }
  });
  var layers = [].concat((0, _toConsumableArray2["default"])(state.layers), mergedLayer);
  var newLayerOrder = mergedLayer.map(function (_, i) {
    return state.layers.length + i;
  }); // put new layers in front of current layers

  var layerOrder = [].concat((0, _toConsumableArray2["default"])(newLayerOrder), (0, _toConsumableArray2["default"])(state.layerOrder));
  return _objectSpread({}, state, {
    layers: layers,
    layerOrder: layerOrder,
    layerToBeMerged: unmerged
  });
}
/**
 * Merge interactions with saved config
 *
 * @param {object} state
 * @param {Object} interactionToBeMerged
 * @return {Object} mergedState
 */


function mergeInteractions(state, interactionToBeMerged) {
  var merged = {};
  var unmerged = {};

  if (interactionToBeMerged) {
    Object.keys(interactionToBeMerged).forEach(function (key) {
      if (!state.interactionConfig[key]) {
        return;
      }

      var _ref = interactionToBeMerged[key] || {},
          enabled = _ref.enabled,
          configSaved = (0, _objectWithoutProperties2["default"])(_ref, ["enabled"]);

      var configToMerge = configSaved;

      if (key === 'tooltip') {
        var _mergeInteractionTool = mergeInteractionTooltipConfig(state, configSaved),
            mergedTooltip = _mergeInteractionTool.mergedTooltip,
            unmergedTooltip = _mergeInteractionTool.unmergedTooltip; // merge new dataset tooltips with original dataset tooltips


        configToMerge = {
          fieldsToShow: _objectSpread({}, state.interactionConfig[key].config.fieldsToShow, {}, mergedTooltip)
        };

        if (Object.keys(unmergedTooltip).length) {
          unmerged.tooltip = {
            fieldsToShow: unmergedTooltip,
            enabled: enabled
          };
        }
      }

      merged[key] = _objectSpread({}, state.interactionConfig[key], {
        enabled: enabled,
        config: (0, _lodash2["default"])(_objectSpread({}, state.interactionConfig[key].config, {}, configToMerge), Object.keys(state.interactionConfig[key].config))
      });
    });
  }

  return _objectSpread({}, state, {
    interactionConfig: _objectSpread({}, state.interactionConfig, {}, merged),
    interactionToBeMerged: unmerged
  });
}
/**
 * Merge interactionConfig.tooltip with saved config,
 * validate fieldsToShow
 *
 * @param {string} state
 * @param {Object} tooltipConfig
 * @return {Object} - {mergedTooltip: {}, unmergedTooltip: {}}
 */


function mergeInteractionTooltipConfig(state) {
  var tooltipConfig = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  var unmergedTooltip = {};
  var mergedTooltip = {};

  if (!tooltipConfig.fieldsToShow || !Object.keys(tooltipConfig.fieldsToShow).length) {
    return {
      mergedTooltip: mergedTooltip,
      unmergedTooltip: unmergedTooltip
    };
  }

  for (var dataId in tooltipConfig.fieldsToShow) {
    if (!state.datasets[dataId]) {
      // is not yet loaded
      unmergedTooltip[dataId] = tooltipConfig.fieldsToShow[dataId];
    } else {
      (function () {
        // if dataset is loaded
        var allFields = state.datasets[dataId].fields.map(function (d) {
          return d.name;
        });
        var foundFieldsToShow = tooltipConfig.fieldsToShow[dataId].filter(function (name) {
          return allFields.includes(name);
        });
        mergedTooltip[dataId] = foundFieldsToShow;
      })();
    }
  }

  return {
    mergedTooltip: mergedTooltip,
    unmergedTooltip: unmergedTooltip
  };
}
/**
 * Merge layerBlending with saved
 *
 * @param {object} state
 * @param {string} layerBlending
 * @return {object} merged state
 */


function mergeLayerBlending(state, layerBlending) {
  if (layerBlending && _defaultSettings.LAYER_BLENDINGS[layerBlending]) {
    return _objectSpread({}, state, {
      layerBlending: layerBlending
    });
  }

  return state;
}
/**
 * Validate saved layer columns with new data,
 * update fieldIdx based on new fields
 *
 * @param {Object[]} fields
 * @param {Object} savedCols
 * @param {Object} emptyCols
 * @return {null | Object} - validated columns or null
 */


function validateSavedLayerColumns(fields, savedCols, emptyCols) {
  var colFound = {}; // find actual column fieldIdx, in case it has changed

  var allColFound = Object.keys(emptyCols).every(function (key) {
    var saved = savedCols[key];
    colFound[key] = _objectSpread({}, emptyCols[key]);
    var fieldIdx = fields.findIndex(function (_ref2) {
      var name = _ref2.name;
      return name === saved;
    });

    if (fieldIdx > -1) {
      // update found columns
      colFound[key].fieldIdx = fieldIdx;
      colFound[key].value = saved;
      return true;
    } // if col is optional, allow null value


    return emptyCols[key].optional || false;
  });
  return allColFound && colFound;
}
/**
 * Validate saved text label config with new data
 * refer to vis-state-schema.js TextLabelSchemaV1
 *
 * @param {Object[]} fields
 * @param {Object} savedTextLabel
 * @return {Object} - validated textlabel
 */


function validateSavedTextLabel(fields, layerTextLabel, savedTextLabel) {
  // validate field
  var field = savedTextLabel.field ? fields.find(function (fd) {
    return Object.keys(savedTextLabel.field).every(function (key) {
      return savedTextLabel.field[key] === fd[key];
    });
  }) : null;
  return Object.keys(layerTextLabel).reduce(function (accu, key) {
    return _objectSpread({}, accu, (0, _defineProperty2["default"])({}, key, key === 'field' ? field : savedTextLabel[key] || layerTextLabel[key]));
  }, {});
}
/**
 * Validate saved visual channels config with new data,
 * refer to vis-state-schema.js VisualChannelSchemaV1
 *
 * @param {Object[]} fields
 * @param {Object} visualChannels
 * @param {Object} savedLayer
 * @return {Object} - validated visual channel in config or {}
 */


function validateSavedVisualChannels(fields, visualChannels, savedLayer) {
  return Object.values(visualChannels).reduce(function (found, _ref3) {
    var field = _ref3.field,
        scale = _ref3.scale;
    var foundField;

    if (savedLayer.config[field]) {
      foundField = fields.find(function (fd) {
        return Object.keys(savedLayer.config[field]).every(function (key) {
          return savedLayer.config[field][key] === fd[key];
        });
      });
    }

    return _objectSpread({}, found, {}, foundField ? (0, _defineProperty2["default"])({}, field, foundField) : {}, {}, savedLayer.config[scale] ? (0, _defineProperty2["default"])({}, scale, savedLayer.config[scale]) : {});
  }, {});
}
/**
 * Validate saved layer config with new data,
 * update fieldIdx based on new fields
 *
 * @param {Object[]} fields
 * @param {String} dataId
 * @param {Object} savedLayer
 * @param {Object} layerClasses
 * @return {null | Object} - validated layer or null
 */


function validateLayerWithData(_ref6, savedLayer, layerClasses) {
  var fields = _ref6.fields,
      dataId = _ref6.id;
  var type = savedLayer.type; // layer doesnt have a valid type

  if (!layerClasses.hasOwnProperty(type) || !savedLayer.config || !savedLayer.config.columns) {
    return null;
  }

  var newLayer = new layerClasses[type]({
    id: savedLayer.id,
    dataId: dataId,
    label: savedLayer.config.label,
    color: savedLayer.config.color,
    isVisible: savedLayer.config.isVisible
  }); // find column fieldIdx

  var columns = validateSavedLayerColumns(fields, savedLayer.config.columns, newLayer.getLayerColumns());

  if (!columns) {
    return null;
  } // visual channel field is saved to be {name, type}
  // find visual channel field by matching both name and type
  // refer to vis-state-schema.js VisualChannelSchemaV1


  var foundVisualChannelConfigs = validateSavedVisualChannels(fields, newLayer.visualChannels, savedLayer);
  var textLabel = savedLayer.config.textLabel && newLayer.config.textLabel ? validateSavedTextLabel(fields, newLayer.config.textLabel, savedLayer.config.textLabel) : newLayer.config.textLabel; // copy visConfig over to emptyLayer to make sure it has all the props

  var visConfig = newLayer.copyLayerConfig(newLayer.config.visConfig, savedLayer.config.visConfig || {}, {
    notToDeepMerge: 'colorRange'
  });
  newLayer.updateLayerConfig(_objectSpread({
    columns: columns,
    visConfig: visConfig,
    textLabel: textLabel
  }, foundVisualChannelConfigs));

  if (type === 'boundary' || type === 'pincode') {
    var boundaryAggregation = savedLayer.config.boundaryAggregation; // console.log(boundaryAggregation);

    newLayer.updateLayerConfig({
      boundaryAggregation: boundaryAggregation,
      apiCallRequest: true,
      apiCallLoader: true
    });
  }

  return newLayer;
}
/**
 * Validate saved layer config with new data,
 * update fieldIdx based on new fields
 *
 * @param {Object[]} fields
 * @param {String} dataId
 * @param {Object} savedWidget
 * @param {Object} widgetClasses
 * @return {null | Object} - validated layer or null
 */


function validateWidgetAndConfig(_ref7, savedWidget, widgetClasses, state) {
  var fields = _ref7.fields,
      dataId = _ref7.id;
  // console.log('saved widget inside validate widget and confg', savedWidget);
  var type = savedWidget.type; // layer doesnt have a valid type

  if (!widgetClasses.hasOwnProperty(type) || !savedWidget.config) {
    return null;
  }

  var newWidget = new widgetClasses[type]({
    id: savedWidget.id,
    dataId: dataId,
    color: savedWidget.config.color,
    isVisible: savedWidget.config.isVisible
  });
  var config = newWidget.copyWidgetConfig(newWidget.config, savedWidget.config || {}); // console.log('config before updating config', config);

  newWidget.updateWidgetConfig(config); // console.log('new widget before aggregation data calculation ', newWidget);

  if (state.layerData.length) {
    (0, _widgetUtils.calculateAggregationData)(newWidget, state);
  } // console.log(newWidget);


  return newWidget;
}
/**
 * Validate saved filter config with new data,
 * calculate domain and fieldIdx based new fields and data
 *
 * @param {Object[]} dataset.fields
 * @param {Object[]} dataset.allData
 * @param {Object} filter - filter to be validate
 * @return {Object | null} - validated filter
 */


function validateFilterWithData(_ref8, filter) {
  var fields = _ref8.fields,
      allData = _ref8.allData;
  // match filter.name to field.name
  var fieldIdx = fields.findIndex(function (_ref9) {
    var name = _ref9.name;
    return name === filter.name;
  });

  if (fieldIdx < 0) {
    // if can't find field with same name, discharge filter
    return null;
  }

  var field = fields[fieldIdx];
  var value = filter.value; // return filter type, default value, fieldType and fieldDomain from field

  var filterPropsFromField = (0, _filterUtils.getFilterProps)(allData, field);

  var matchedFilter = _objectSpread({}, (0, _filterUtils.getDefaultFilter)(filter.dataId), {}, filter, {}, filterPropsFromField, {
    freeze: true,
    fieldIdx: fieldIdx
  });

  var _matchedFilter = matchedFilter,
      yAxis = _matchedFilter.yAxis;

  if (yAxis) {
    var matcheAxis = fields.find(function (_ref10) {
      var name = _ref10.name,
          type = _ref10.type;
      return name === yAxis.name && type === yAxis.type;
    });
    matchedFilter = matcheAxis ? _objectSpread({}, matchedFilter, {
      yAxis: matcheAxis
    }, (0, _filterUtils.getFilterPlot)(_objectSpread({}, matchedFilter, {
      yAxis: matcheAxis
    }), allData)) : matchedFilter;
  }

  matchedFilter.value = (0, _filterUtils.adjustValueToFilterDomain)(value, matchedFilter);

  if (matchedFilter.value === null) {
    // cannt adjust saved value to filter
    return null;
  }

  return matchedFilter;
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9yZWR1Y2Vycy92aXMtc3RhdGUtbWVyZ2VyLmpzIl0sIm5hbWVzIjpbIm1lcmdlV2lkZ2V0cyIsInN0YXRlIiwid2lkZ2V0c1RvTWVyZ2UiLCJtZXJnZWRXaWRnZXQiLCJ1bm1lcmdlZCIsImRhdGFzZXRzIiwiQXJyYXkiLCJpc0FycmF5IiwibGVuZ3RoIiwiZm9yRWFjaCIsIndpZGdldCIsImNvbmZpZyIsImRhdGFJZCIsInZhbGlkYXRlV2lkZ2V0IiwidmFsaWRhdGVXaWRnZXRBbmRDb25maWciLCJ3aWRnZXRDbGFzc2VzIiwicHVzaCIsIndpZGdldHMiLCJuZXdXaWRnZXRPcmRlciIsIm1hcCIsIl8iLCJpIiwid2lkZ2V0T3JkZXIiLCJ3aWRnZXRUb0JlTWVyZ2VkIiwibWVyZ2VGaWx0ZXJzIiwiZmlsdGVyc1RvTWVyZ2UiLCJtZXJnZWQiLCJmaWx0ZXIiLCJ2YWxpZGF0ZUZpbHRlciIsInZhbGlkYXRlRmlsdGVyV2l0aERhdGEiLCJ1cGRhdGVkRmlsdGVycyIsImZpbHRlcnMiLCJkYXRhc2V0VG9GaWx0ZXIiLCJkIiwidXBkYXRlZERhdGFzZXQiLCJyZWR1Y2UiLCJhY2N1IiwiYWxsRGF0YSIsImZpbHRlclRvQmVNZXJnZWQiLCJtZXJnZUxheWVycyIsImxheWVyc1RvTWVyZ2UiLCJtZXJnZWRMYXllciIsImxheWVyIiwidmFsaWRhdGVMYXllciIsInZhbGlkYXRlTGF5ZXJXaXRoRGF0YSIsImxheWVyQ2xhc3NlcyIsImxheWVycyIsIm5ld0xheWVyT3JkZXIiLCJsYXllck9yZGVyIiwibGF5ZXJUb0JlTWVyZ2VkIiwibWVyZ2VJbnRlcmFjdGlvbnMiLCJpbnRlcmFjdGlvblRvQmVNZXJnZWQiLCJPYmplY3QiLCJrZXlzIiwia2V5IiwiaW50ZXJhY3Rpb25Db25maWciLCJlbmFibGVkIiwiY29uZmlnU2F2ZWQiLCJjb25maWdUb01lcmdlIiwibWVyZ2VJbnRlcmFjdGlvblRvb2x0aXBDb25maWciLCJtZXJnZWRUb29sdGlwIiwidW5tZXJnZWRUb29sdGlwIiwiZmllbGRzVG9TaG93IiwidG9vbHRpcCIsInRvb2x0aXBDb25maWciLCJhbGxGaWVsZHMiLCJmaWVsZHMiLCJuYW1lIiwiZm91bmRGaWVsZHNUb1Nob3ciLCJpbmNsdWRlcyIsIm1lcmdlTGF5ZXJCbGVuZGluZyIsImxheWVyQmxlbmRpbmciLCJMQVlFUl9CTEVORElOR1MiLCJ2YWxpZGF0ZVNhdmVkTGF5ZXJDb2x1bW5zIiwic2F2ZWRDb2xzIiwiZW1wdHlDb2xzIiwiY29sRm91bmQiLCJhbGxDb2xGb3VuZCIsImV2ZXJ5Iiwic2F2ZWQiLCJmaWVsZElkeCIsImZpbmRJbmRleCIsInZhbHVlIiwib3B0aW9uYWwiLCJ2YWxpZGF0ZVNhdmVkVGV4dExhYmVsIiwibGF5ZXJUZXh0TGFiZWwiLCJzYXZlZFRleHRMYWJlbCIsImZpZWxkIiwiZmluZCIsImZkIiwidmFsaWRhdGVTYXZlZFZpc3VhbENoYW5uZWxzIiwidmlzdWFsQ2hhbm5lbHMiLCJzYXZlZExheWVyIiwidmFsdWVzIiwiZm91bmQiLCJzY2FsZSIsImZvdW5kRmllbGQiLCJpZCIsInR5cGUiLCJoYXNPd25Qcm9wZXJ0eSIsImNvbHVtbnMiLCJuZXdMYXllciIsImxhYmVsIiwiY29sb3IiLCJpc1Zpc2libGUiLCJnZXRMYXllckNvbHVtbnMiLCJmb3VuZFZpc3VhbENoYW5uZWxDb25maWdzIiwidGV4dExhYmVsIiwidmlzQ29uZmlnIiwiY29weUxheWVyQ29uZmlnIiwibm90VG9EZWVwTWVyZ2UiLCJ1cGRhdGVMYXllckNvbmZpZyIsImJvdW5kYXJ5QWdncmVnYXRpb24iLCJhcGlDYWxsUmVxdWVzdCIsImFwaUNhbGxMb2FkZXIiLCJzYXZlZFdpZGdldCIsIm5ld1dpZGdldCIsImNvcHlXaWRnZXRDb25maWciLCJ1cGRhdGVXaWRnZXRDb25maWciLCJsYXllckRhdGEiLCJmaWx0ZXJQcm9wc0Zyb21GaWVsZCIsIm1hdGNoZWRGaWx0ZXIiLCJmcmVlemUiLCJ5QXhpcyIsIm1hdGNoZUF4aXMiXSwibWFwcGluZ3MiOiI7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a0M7QUFDaEM7QUFDQSxXQUFPLElBQVA7QUFDRDs7QUFFRCxTQUFPdUMsYUFBUDtBQUNEIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IChjKSAyMDE5IFViZXIgVGVjaG5vbG9naWVzLCBJbmMuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuLy8gb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbFxuLy8gaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0c1xuLy8gdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbFxuLy8gY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4vLyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4vLyBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4vLyBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbi8vIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuLy8gQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuLy8gTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbi8vIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU5cbi8vIFRIRSBTT0ZUV0FSRS5cblxuaW1wb3J0IHVuaXEgZnJvbSAnbG9kYXNoLnVuaXEnO1xuaW1wb3J0IHBpY2sgZnJvbSAnbG9kYXNoLnBpY2snO1xuXG5pbXBvcnQge1xuICBnZXREZWZhdWx0RmlsdGVyLFxuICBnZXRGaWx0ZXJQcm9wcyxcbiAgZ2V0RmlsdGVyUGxvdCxcbiAgZmlsdGVyRGF0YSxcbiAgYWRqdXN0VmFsdWVUb0ZpbHRlckRvbWFpblxufSBmcm9tICd1dGlscy9maWx0ZXItdXRpbHMnO1xuXG5pbXBvcnQge2NhbGN1bGF0ZUFnZ3JlZ2F0aW9uRGF0YX0gZnJvbSAndXRpbHMvd2lkZ2V0LXV0aWxzL3dpZGdldC11dGlscyc7XG5cbmltcG9ydCB7TEFZRVJfQkxFTkRJTkdTfSBmcm9tICdjb25zdGFudHMvZGVmYXVsdC1zZXR0aW5ncyc7XG5cbi8qKlxuICogTWVyZ2UgbG9hZGVkIHdpZGdldHMgd2l0aCBjdXJyZW50IHN0YXRlLCBpZiBubyB3aWRnZXQgYXJlIGxvYWRlZFxuICogc2F2ZSBpdCBmb3IgbGF0ZXJcbiAqXG4gKiBAcGFyYW0geyp9IHN0YXRlXG4gKiBAcGFyYW0geyp9IHdpZGdldHNUb01lcmdlXG4gKiBAcmV0dXJuIHtvbmplY3R9IHVwZGF0ZWRTdGF0ZVxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBtZXJnZVdpZGdldHMoc3RhdGUsIHdpZGdldHNUb01lcmdlKSB7XG4gIGNvbnN0IG1lcmdlZFdpZGdldCA9IFtdO1xuICBjb25zdCB1bm1lcmdlZCA9IFtdO1xuXG4gIGNvbnN0IHtkYXRhc2V0c30gPSBzdGF0ZTtcblxuICBpZiAoIUFycmF5LmlzQXJyYXkod2lkZ2V0c1RvTWVyZ2UpIHx8ICF3aWRnZXRzVG9NZXJnZS5sZW5ndGgpIHtcbiAgICByZXR1cm4gc3RhdGU7XG4gIH1cblxuICAvLyBjb25zb2xlLmxvZyhzdGF0ZSk7XG5cbiAgd2lkZ2V0c1RvTWVyZ2UuZm9yRWFjaCh3aWRnZXQgPT4ge1xuICAgIGlmIChkYXRhc2V0c1t3aWRnZXQuY29uZmlnLmRhdGFJZF0pIHtcbiAgICAgIC8vIGRhdGFzZXRzIGFyZSBhbHJlYWR5IGxvYWRlZFxuICAgICAgY29uc3QgdmFsaWRhdGVXaWRnZXQgPSB2YWxpZGF0ZVdpZGdldEFuZENvbmZpZyhcbiAgICAgICAgZGF0YXNldHNbd2lkZ2V0LmNvbmZpZy5kYXRhSWRdLFxuICAgICAgICB3aWRnZXQsXG4gICAgICAgIHN0YXRlLndpZGdldENsYXNzZXMsXG4gICAgICAgIHN0YXRlXG4gICAgICApO1xuXG4gICAgICBpZiAodmFsaWRhdGVXaWRnZXQpIHtcbiAgICAgICAgbWVyZ2VkV2lkZ2V0LnB1c2godmFsaWRhdGVXaWRnZXQpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBkYXRhc2V0cyBub3QgeWV0IGxvYWRlZFxuICAgICAgdW5tZXJnZWQucHVzaCh3aWRnZXQpO1xuICAgIH1cbiAgfSk7XG4gIC8vIGNvbnNvbGUubG9nKG1lcmdlZFdpZGdldCk7XG4gIGNvbnN0IHdpZGdldHMgPSBbLi4uc3RhdGUud2lkZ2V0cywgLi4ubWVyZ2VkV2lkZ2V0XTtcbiAgY29uc3QgbmV3V2lkZ2V0T3JkZXIgPSBtZXJnZWRXaWRnZXQubWFwKChfLCBpKSA9PiBzdGF0ZS53aWRnZXRzLmxlbmd0aCArIGkpO1xuXG4gIC8vIHB1dCBuZXcgbGF5ZXJzIGluIGZyb250IG9mIGN1cnJlbnQgbGF5ZXJzXG4gIGNvbnN0IHdpZGdldE9yZGVyID0gWy4uLm5ld1dpZGdldE9yZGVyLCAuLi5zdGF0ZS53aWRnZXRPcmRlcl07XG4gIC8vIGNvbnNvbGUubG9nKCdtZXJnZVdpZGdldHMnLCB3aWRnZXRzKTtcbiAgcmV0dXJuIHtcbiAgICAuLi5zdGF0ZSxcbiAgICB3aWRnZXRzLFxuICAgIHdpZGdldE9yZGVyLFxuICAgIHdpZGdldFRvQmVNZXJnZWQ6IHVubWVyZ2VkXG4gIH07XG59XG5cbi8qKlxuICogTWVyZ2UgbG9hZGVkIGZpbHRlcnMgd2l0aCBjdXJyZW50IHN0YXRlLCBpZiBubyBmaWVsZHMgb3IgZGF0YSBhcmUgbG9hZGVkXG4gKiBzYXZlIGl0IGZvciBsYXRlclxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBzdGF0ZVxuICogQHBhcmFtIHtPYmplY3RbXX0gZmlsdGVyc1RvTWVyZ2VcbiAqIEByZXR1cm4ge09iamVjdH0gdXBkYXRlZFN0YXRlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtZXJnZUZpbHRlcnMoc3RhdGUsIGZpbHRlcnNUb01lcmdlKSB7XG4gIGNvbnN0IG1lcmdlZCA9IFtdO1xuICBjb25zdCB1bm1lcmdlZCA9IFtdO1xuICBjb25zdCB7ZGF0YXNldHN9ID0gc3RhdGU7XG5cbiAgaWYgKCFBcnJheS5pc0FycmF5KGZpbHRlcnNUb01lcmdlKSB8fCAhZmlsdGVyc1RvTWVyZ2UubGVuZ3RoKSB7XG4gICAgcmV0dXJuIHN0YXRlO1xuICB9XG5cbiAgLy8gbWVyZ2UgZmlsdGVyc1xuICBmaWx0ZXJzVG9NZXJnZS5mb3JFYWNoKGZpbHRlciA9PiB7XG4gICAgLy8gbWF0Y2ggZmlsdGVyLmRhdGFJZCB3aXRoIGN1cnJlbnQgZGF0ZXNldHMgaWRcbiAgICAvLyB1cGxvYWRlZCBkYXRhIG5lZWQgdG8gaGF2ZSB0aGUgc2FtZSBkYXRhSWQgd2l0aCB0aGUgZmlsdGVyXG4gICAgaWYgKGRhdGFzZXRzW2ZpbHRlci5kYXRhSWRdKSB7XG4gICAgICAvLyBkYXRhc2V0cyBpcyBhbHJlYWR5IGxvYWRlZFxuICAgICAgY29uc3QgdmFsaWRhdGVGaWx0ZXIgPSB2YWxpZGF0ZUZpbHRlcldpdGhEYXRhKFxuICAgICAgICBkYXRhc2V0c1tmaWx0ZXIuZGF0YUlkXSxcbiAgICAgICAgZmlsdGVyXG4gICAgICApO1xuXG4gICAgICBpZiAodmFsaWRhdGVGaWx0ZXIpIHtcbiAgICAgICAgbWVyZ2VkLnB1c2godmFsaWRhdGVGaWx0ZXIpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBkYXRhc2V0cyBub3QgeWV0IGxvYWRlZFxuICAgICAgdW5tZXJnZWQucHVzaChmaWx0ZXIpO1xuICAgIH1cbiAgfSk7XG5cbiAgLy8gZmlsdGVyIGRhdGFcbiAgY29uc3QgdXBkYXRlZEZpbHRlcnMgPSBbLi4uKHN0YXRlLmZpbHRlcnMgfHwgW10pLCAuLi5tZXJnZWRdO1xuICBjb25zdCBkYXRhc2V0VG9GaWx0ZXIgPSB1bmlxKG1lcmdlZC5tYXAoZCA9PiBkLmRhdGFJZCkpO1xuXG4gIGNvbnN0IHVwZGF0ZWREYXRhc2V0ID0gZGF0YXNldFRvRmlsdGVyLnJlZHVjZShcbiAgICAoYWNjdSwgZGF0YUlkKSA9PiAoe1xuICAgICAgLi4uYWNjdSxcbiAgICAgIFtkYXRhSWRdOiB7XG4gICAgICAgIC4uLmRhdGFzZXRzW2RhdGFJZF0sXG4gICAgICAgIC4uLmZpbHRlckRhdGEoZGF0YXNldHNbZGF0YUlkXS5hbGxEYXRhLCBkYXRhSWQsIHVwZGF0ZWRGaWx0ZXJzKVxuICAgICAgfVxuICAgIH0pLFxuICAgIGRhdGFzZXRzXG4gICk7XG5cbiAgcmV0dXJuIHtcbiAgICAuLi5zdGF0ZSxcbiAgICBmaWx0ZXJzOiB1cGRhdGVkRmlsdGVycyxcbiAgICBkYXRhc2V0czogdXBkYXRlZERhdGFzZXQsXG4gICAgZmlsdGVyVG9CZU1lcmdlZDogdW5tZXJnZWRcbiAgfTtcbn1cblxuLyoqXG4gKiBNZXJnZSBsYXllcnMgZnJvbSBkZS1zZXJpYWxpemVkIHN0YXRlLCBpZiBubyBmaWVsZHMgb3IgZGF0YSBhcmUgbG9hZGVkXG4gKiBzYXZlIGl0IGZvciBsYXRlclxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBzdGF0ZVxuICogQHBhcmFtIHtPYmplY3RbXX0gbGF5ZXJzVG9NZXJnZVxuICogQHJldHVybiB7T2JqZWN0fSBzdGF0ZVxuICovXG5leHBvcnQgZnVuY3Rpb24gbWVyZ2VMYXllcnMoc3RhdGUsIGxheWVyc1RvTWVyZ2UpIHtcbiAgY29uc3QgbWVyZ2VkTGF5ZXIgPSBbXTtcbiAgY29uc3QgdW5tZXJnZWQgPSBbXTtcblxuICBjb25zdCB7ZGF0YXNldHN9ID0gc3RhdGU7XG5cbiAgaWYgKCFBcnJheS5pc0FycmF5KGxheWVyc1RvTWVyZ2UpIHx8ICFsYXllcnNUb01lcmdlLmxlbmd0aCkge1xuICAgIHJldHVybiBzdGF0ZTtcbiAgfVxuXG4gIGxheWVyc1RvTWVyZ2UuZm9yRWFjaChsYXllciA9PiB7XG4gICAgaWYgKGRhdGFzZXRzW2xheWVyLmNvbmZpZy5kYXRhSWRdKSB7XG4gICAgICAvLyBkYXRhc2V0cyBhcmUgYWxyZWFkeSBsb2FkZWRcbiAgICAgIGNvbnN0IHZhbGlkYXRlTGF5ZXIgPSB2YWxpZGF0ZUxheWVyV2l0aERhdGEoXG4gICAgICAgIGRhdGFzZXRzW2xheWVyLmNvbmZpZy5kYXRhSWRdLFxuICAgICAgICBsYXllcixcbiAgICAgICAgc3RhdGUubGF5ZXJDbGFzc2VzXG4gICAgICApO1xuXG4gICAgICBpZiAodmFsaWRhdGVMYXllcikge1xuICAgICAgICBtZXJnZWRMYXllci5wdXNoKHZhbGlkYXRlTGF5ZXIpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBkYXRhc2V0cyBub3QgeWV0IGxvYWRlZFxuICAgICAgdW5tZXJnZWQucHVzaChsYXllcik7XG4gICAgfVxuICB9KTtcblxuICBjb25zdCBsYXllcnMgPSBbLi4uc3RhdGUubGF5ZXJzLCAuLi5tZXJnZWRMYXllcl07XG4gIGNvbnN0IG5ld0xheWVyT3JkZXIgPSBtZXJnZWRMYXllci5tYXAoKF8sIGkpID0+IHN0YXRlLmxheWVycy5sZW5ndGggKyBpKTtcblxuICAvLyBwdXQgbmV3IGxheWVycyBpbiBmcm9udCBvZiBjdXJyZW50IGxheWVyc1xuICBjb25zdCBsYXllck9yZGVyID0gWy4uLm5ld0xheWVyT3JkZXIsIC4uLnN0YXRlLmxheWVyT3JkZXJdO1xuXG4gIHJldHVybiB7XG4gICAgLi4uc3RhdGUsXG4gICAgbGF5ZXJzLFxuICAgIGxheWVyT3JkZXIsXG4gICAgbGF5ZXJUb0JlTWVyZ2VkOiB1bm1lcmdlZFxuICB9O1xufVxuXG4vKipcbiAqIE1lcmdlIGludGVyYWN0aW9ucyB3aXRoIHNhdmVkIGNvbmZpZ1xuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBzdGF0ZVxuICogQHBhcmFtIHtPYmplY3R9IGludGVyYWN0aW9uVG9CZU1lcmdlZFxuICogQHJldHVybiB7T2JqZWN0fSBtZXJnZWRTdGF0ZVxuICovXG5leHBvcnQgZnVuY3Rpb24gbWVyZ2VJbnRlcmFjdGlvbnMoc3RhdGUsIGludGVyYWN0aW9uVG9CZU1lcmdlZCkge1xuICBjb25zdCBtZXJnZWQgPSB7fTtcbiAgY29uc3QgdW5tZXJnZWQgPSB7fTtcblxuICBpZiAoaW50ZXJhY3Rpb25Ub0JlTWVyZ2VkKSB7XG4gICAgT2JqZWN0LmtleXMoaW50ZXJhY3Rpb25Ub0JlTWVyZ2VkKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICBpZiAoIXN0YXRlLmludGVyYWN0aW9uQ29uZmlnW2tleV0pIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCB7ZW5hYmxlZCwgLi4uY29uZmlnU2F2ZWR9ID0gaW50ZXJhY3Rpb25Ub0JlTWVyZ2VkW2tleV0gfHwge307XG4gICAgICBsZXQgY29uZmlnVG9NZXJnZSA9IGNvbmZpZ1NhdmVkO1xuXG4gICAgICBpZiAoa2V5ID09PSAndG9vbHRpcCcpIHtcbiAgICAgICAgY29uc3Qge21lcmdlZFRvb2x0aXAsIHVubWVyZ2VkVG9vbHRpcH0gPSBtZXJnZUludGVyYWN0aW9uVG9vbHRpcENvbmZpZyhcbiAgICAgICAgICBzdGF0ZSxcbiAgICAgICAgICBjb25maWdTYXZlZFxuICAgICAgICApO1xuXG4gICAgICAgIC8vIG1lcmdlIG5ldyBkYXRhc2V0IHRvb2x0aXBzIHdpdGggb3JpZ2luYWwgZGF0YXNldCB0b29sdGlwc1xuICAgICAgICBjb25maWdUb01lcmdlID0ge1xuICAgICAgICAgIGZpZWxkc1RvU2hvdzoge1xuICAgICAgICAgICAgLi4uc3RhdGUuaW50ZXJhY3Rpb25Db25maWdba2V5XS5jb25maWcuZmllbGRzVG9TaG93LFxuICAgICAgICAgICAgLi4ubWVyZ2VkVG9vbHRpcFxuICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBpZiAoT2JqZWN0LmtleXModW5tZXJnZWRUb29sdGlwKS5sZW5ndGgpIHtcbiAgICAgICAgICB1bm1lcmdlZC50b29sdGlwID0ge2ZpZWxkc1RvU2hvdzogdW5tZXJnZWRUb29sdGlwLCBlbmFibGVkfTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBtZXJnZWRba2V5XSA9IHtcbiAgICAgICAgLi4uc3RhdGUuaW50ZXJhY3Rpb25Db25maWdba2V5XSxcbiAgICAgICAgZW5hYmxlZCxcbiAgICAgICAgY29uZmlnOiBwaWNrKFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIC4uLnN0YXRlLmludGVyYWN0aW9uQ29uZmlnW2tleV0uY29uZmlnLFxuICAgICAgICAgICAgLi4uY29uZmlnVG9NZXJnZVxuICAgICAgICAgIH0sXG4gICAgICAgICAgT2JqZWN0LmtleXMoc3RhdGUuaW50ZXJhY3Rpb25Db25maWdba2V5XS5jb25maWcpXG4gICAgICAgIClcbiAgICAgIH07XG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIC4uLnN0YXRlLFxuICAgIGludGVyYWN0aW9uQ29uZmlnOiB7XG4gICAgICAuLi5zdGF0ZS5pbnRlcmFjdGlvbkNvbmZpZyxcbiAgICAgIC4uLm1lcmdlZFxuICAgIH0sXG4gICAgaW50ZXJhY3Rpb25Ub0JlTWVyZ2VkOiB1bm1lcmdlZFxuICB9O1xufVxuXG4vKipcbiAqIE1lcmdlIGludGVyYWN0aW9uQ29uZmlnLnRvb2x0aXAgd2l0aCBzYXZlZCBjb25maWcsXG4gKiB2YWxpZGF0ZSBmaWVsZHNUb1Nob3dcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gc3RhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSB0b29sdGlwQ29uZmlnXG4gKiBAcmV0dXJuIHtPYmplY3R9IC0ge21lcmdlZFRvb2x0aXA6IHt9LCB1bm1lcmdlZFRvb2x0aXA6IHt9fVxuICovXG5leHBvcnQgZnVuY3Rpb24gbWVyZ2VJbnRlcmFjdGlvblRvb2x0aXBDb25maWcoc3RhdGUsIHRvb2x0aXBDb25maWcgPSB7fSkge1xuICBjb25zdCB1bm1lcmdlZFRvb2x0aXAgPSB7fTtcbiAgY29uc3QgbWVyZ2VkVG9vbHRpcCA9IHt9O1xuXG4gIGlmIChcbiAgICAhdG9vbHRpcENvbmZpZy5maWVsZHNUb1Nob3cgfHxcbiAgICAhT2JqZWN0LmtleXModG9vbHRpcENvbmZpZy5maWVsZHNUb1Nob3cpLmxlbmd0aFxuICApIHtcbiAgICByZXR1cm4ge21lcmdlZFRvb2x0aXAsIHVubWVyZ2VkVG9vbHRpcH07XG4gIH1cblxuICBmb3IgKGNvbnN0IGRhdGFJZCBpbiB0b29sdGlwQ29uZmlnLmZpZWxkc1RvU2hvdykge1xuICAgIGlmICghc3RhdGUuZGF0YXNldHNbZGF0YUlkXSkge1xuICAgICAgLy8gaXMgbm90IHlldCBsb2FkZWRcbiAgICAgIHVubWVyZ2VkVG9vbHRpcFtkYXRhSWRdID0gdG9vbHRpcENvbmZpZy5maWVsZHNUb1Nob3dbZGF0YUlkXTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gaWYgZGF0YXNldCBpcyBsb2FkZWRcbiAgICAgIGNvbnN0IGFsbEZpZWxkcyA9IHN0YXRlLmRhdGFzZXRzW2RhdGFJZF0uZmllbGRzLm1hcChkID0+IGQubmFtZSk7XG4gICAgICBjb25zdCBmb3VuZEZpZWxkc1RvU2hvdyA9IHRvb2x0aXBDb25maWcuZmllbGRzVG9TaG93W2RhdGFJZF0uZmlsdGVyKFxuICAgICAgICBuYW1lID0+IGFsbEZpZWxkcy5pbmNsdWRlcyhuYW1lKVxuICAgICAgKTtcblxuICAgICAgbWVyZ2VkVG9vbHRpcFtkYXRhSWRdID0gZm91bmRGaWVsZHNUb1Nob3c7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHttZXJnZWRUb29sdGlwLCB1bm1lcmdlZFRvb2x0aXB9O1xufVxuLyoqXG4gKiBNZXJnZSBsYXllckJsZW5kaW5nIHdpdGggc2F2ZWRcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gc3RhdGVcbiAqIEBwYXJhbSB7c3RyaW5nfSBsYXllckJsZW5kaW5nXG4gKiBAcmV0dXJuIHtvYmplY3R9IG1lcmdlZCBzdGF0ZVxuICovXG5leHBvcnQgZnVuY3Rpb24gbWVyZ2VMYXllckJsZW5kaW5nKHN0YXRlLCBsYXllckJsZW5kaW5nKSB7XG4gIGlmIChsYXllckJsZW5kaW5nICYmIExBWUVSX0JMRU5ESU5HU1tsYXllckJsZW5kaW5nXSkge1xuICAgIHJldHVybiB7XG4gICAgICAuLi5zdGF0ZSxcbiAgICAgIGxheWVyQmxlbmRpbmdcbiAgICB9O1xuICB9XG5cbiAgcmV0dXJuIHN0YXRlO1xufVxuXG4vKipcbiAqIFZhbGlkYXRlIHNhdmVkIGxheWVyIGNvbHVtbnMgd2l0aCBuZXcgZGF0YSxcbiAqIHVwZGF0ZSBmaWVsZElkeCBiYXNlZCBvbiBuZXcgZmllbGRzXG4gKlxuICogQHBhcmFtIHtPYmplY3RbXX0gZmllbGRzXG4gKiBAcGFyYW0ge09iamVjdH0gc2F2ZWRDb2xzXG4gKiBAcGFyYW0ge09iamVjdH0gZW1wdHlDb2xzXG4gKiBAcmV0dXJuIHtudWxsIHwgT2JqZWN0fSAtIHZhbGlkYXRlZCBjb2x1bW5zIG9yIG51bGxcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVTYXZlZExheWVyQ29sdW1ucyhmaWVsZHMsIHNhdmVkQ29scywgZW1wdHlDb2xzKSB7XG4gIGNvbnN0IGNvbEZvdW5kID0ge307XG4gIC8vIGZpbmQgYWN0dWFsIGNvbHVtbiBmaWVsZElkeCwgaW4gY2FzZSBpdCBoYXMgY2hhbmdlZFxuICBjb25zdCBhbGxDb2xGb3VuZCA9IE9iamVjdC5rZXlzKGVtcHR5Q29scykuZXZlcnkoa2V5ID0+IHtcbiAgICBjb25zdCBzYXZlZCA9IHNhdmVkQ29sc1trZXldO1xuICAgIGNvbEZvdW5kW2tleV0gPSB7Li4uZW1wdHlDb2xzW2tleV19O1xuXG4gICAgY29uc3QgZmllbGRJZHggPSBmaWVsZHMuZmluZEluZGV4KCh7bmFtZX0pID0+IG5hbWUgPT09IHNhdmVkKTtcblxuICAgIGlmIChmaWVsZElkeCA+IC0xKSB7XG4gICAgICAvLyB1cGRhdGUgZm91bmQgY29sdW1uc1xuICAgICAgY29sRm91bmRba2V5XS5maWVsZElkeCA9IGZpZWxkSWR4O1xuICAgICAgY29sRm91bmRba2V5XS52YWx1ZSA9IHNhdmVkO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgLy8gaWYgY29sIGlzIG9wdGlvbmFsLCBhbGxvdyBudWxsIHZhbHVlXG4gICAgcmV0dXJuIGVtcHR5Q29sc1trZXldLm9wdGlvbmFsIHx8IGZhbHNlO1xuICB9KTtcblxuICByZXR1cm4gYWxsQ29sRm91bmQgJiYgY29sRm91bmQ7XG59XG5cbi8qKlxuICogVmFsaWRhdGUgc2F2ZWQgdGV4dCBsYWJlbCBjb25maWcgd2l0aCBuZXcgZGF0YVxuICogcmVmZXIgdG8gdmlzLXN0YXRlLXNjaGVtYS5qcyBUZXh0TGFiZWxTY2hlbWFWMVxuICpcbiAqIEBwYXJhbSB7T2JqZWN0W119IGZpZWxkc1xuICogQHBhcmFtIHtPYmplY3R9IHNhdmVkVGV4dExhYmVsXG4gKiBAcmV0dXJuIHtPYmplY3R9IC0gdmFsaWRhdGVkIHRleHRsYWJlbFxuICovXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVTYXZlZFRleHRMYWJlbChmaWVsZHMsIGxheWVyVGV4dExhYmVsLCBzYXZlZFRleHRMYWJlbCkge1xuICAvLyB2YWxpZGF0ZSBmaWVsZFxuICBjb25zdCBmaWVsZCA9IHNhdmVkVGV4dExhYmVsLmZpZWxkXG4gICAgPyBmaWVsZHMuZmluZChmZCA9PlxuICAgICAgICBPYmplY3Qua2V5cyhzYXZlZFRleHRMYWJlbC5maWVsZCkuZXZlcnkoXG4gICAgICAgICAga2V5ID0+IHNhdmVkVGV4dExhYmVsLmZpZWxkW2tleV0gPT09IGZkW2tleV1cbiAgICAgICAgKVxuICAgICAgKVxuICAgIDogbnVsbDtcblxuICByZXR1cm4gT2JqZWN0LmtleXMobGF5ZXJUZXh0TGFiZWwpLnJlZHVjZShcbiAgICAoYWNjdSwga2V5KSA9PiAoe1xuICAgICAgLi4uYWNjdSxcbiAgICAgIFtrZXldOlxuICAgICAgICBrZXkgPT09ICdmaWVsZCcgPyBmaWVsZCA6IHNhdmVkVGV4dExhYmVsW2tleV0gfHwgbGF5ZXJUZXh0TGFiZWxba2V5XVxuICAgIH0pLFxuICAgIHt9XG4gICk7XG59XG5cbi8qKlxuICogVmFsaWRhdGUgc2F2ZWQgdmlzdWFsIGNoYW5uZWxzIGNvbmZpZyB3aXRoIG5ldyBkYXRhLFxuICogcmVmZXIgdG8gdmlzLXN0YXRlLXNjaGVtYS5qcyBWaXN1YWxDaGFubmVsU2NoZW1hVjFcbiAqXG4gKiBAcGFyYW0ge09iamVjdFtdfSBmaWVsZHNcbiAqIEBwYXJhbSB7T2JqZWN0fSB2aXN1YWxDaGFubmVsc1xuICogQHBhcmFtIHtPYmplY3R9IHNhdmVkTGF5ZXJcbiAqIEByZXR1cm4ge09iamVjdH0gLSB2YWxpZGF0ZWQgdmlzdWFsIGNoYW5uZWwgaW4gY29uZmlnIG9yIHt9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZVNhdmVkVmlzdWFsQ2hhbm5lbHMoXG4gIGZpZWxkcyxcbiAgdmlzdWFsQ2hhbm5lbHMsXG4gIHNhdmVkTGF5ZXJcbikge1xuICByZXR1cm4gT2JqZWN0LnZhbHVlcyh2aXN1YWxDaGFubmVscykucmVkdWNlKChmb3VuZCwge2ZpZWxkLCBzY2FsZX0pID0+IHtcbiAgICBsZXQgZm91bmRGaWVsZDtcbiAgICBpZiAoc2F2ZWRMYXllci5jb25maWdbZmllbGRdKSB7XG4gICAgICBmb3VuZEZpZWxkID0gZmllbGRzLmZpbmQoZmQgPT5cbiAgICAgICAgT2JqZWN0LmtleXMoc2F2ZWRMYXllci5jb25maWdbZmllbGRdKS5ldmVyeShcbiAgICAgICAgICBrZXkgPT4gc2F2ZWRMYXllci5jb25maWdbZmllbGRdW2tleV0gPT09IGZkW2tleV1cbiAgICAgICAgKVxuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgLi4uZm91bmQsXG4gICAgICAuLi4oZm91bmRGaWVsZCA/IHtbZmllbGRdOiBmb3VuZEZpZWxkfSA6IHt9KSxcbiAgICAgIC4uLihzYXZlZExheWVyLmNvbmZpZ1tzY2FsZV0gPyB7W3NjYWxlXTogc2F2ZWRMYXllci5jb25maWdbc2NhbGVdfSA6IHt9KVxuICAgIH07XG4gIH0sIHt9KTtcbn1cblxuLyoqXG4gKiBWYWxpZGF0ZSBzYXZlZCBsYXllciBjb25maWcgd2l0aCBuZXcgZGF0YSxcbiAqIHVwZGF0ZSBmaWVsZElkeCBiYXNlZCBvbiBuZXcgZmllbGRzXG4gKlxuICogQHBhcmFtIHtPYmplY3RbXX0gZmllbGRzXG4gKiBAcGFyYW0ge1N0cmluZ30gZGF0YUlkXG4gKiBAcGFyYW0ge09iamVjdH0gc2F2ZWRMYXllclxuICogQHBhcmFtIHtPYmplY3R9IGxheWVyQ2xhc3Nlc1xuICogQHJldHVybiB7bnVsbCB8IE9iamVjdH0gLSB2YWxpZGF0ZWQgbGF5ZXIgb3IgbnVsbFxuICovXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVMYXllcldpdGhEYXRhKFxuICB7ZmllbGRzLCBpZDogZGF0YUlkfSxcbiAgc2F2ZWRMYXllcixcbiAgbGF5ZXJDbGFzc2VzXG4pIHtcbiAgY29uc3Qge3R5cGV9ID0gc2F2ZWRMYXllcjtcbiAgLy8gbGF5ZXIgZG9lc250IGhhdmUgYSB2YWxpZCB0eXBlXG4gIGlmIChcbiAgICAhbGF5ZXJDbGFzc2VzLmhhc093blByb3BlcnR5KHR5cGUpIHx8XG4gICAgIXNhdmVkTGF5ZXIuY29uZmlnIHx8XG4gICAgIXNhdmVkTGF5ZXIuY29uZmlnLmNvbHVtbnNcbiAgKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjb25zdCBuZXdMYXllciA9IG5ldyBsYXllckNsYXNzZXNbdHlwZV0oe1xuICAgIGlkOiBzYXZlZExheWVyLmlkLFxuICAgIGRhdGFJZCxcbiAgICBsYWJlbDogc2F2ZWRMYXllci5jb25maWcubGFiZWwsXG4gICAgY29sb3I6IHNhdmVkTGF5ZXIuY29uZmlnLmNvbG9yLFxuICAgIGlzVmlzaWJsZTogc2F2ZWRMYXllci5jb25maWcuaXNWaXNpYmxlXG4gIH0pO1xuXG4gIC8vIGZpbmQgY29sdW1uIGZpZWxkSWR4XG4gIGNvbnN0IGNvbHVtbnMgPSB2YWxpZGF0ZVNhdmVkTGF5ZXJDb2x1bW5zKFxuICAgIGZpZWxkcyxcbiAgICBzYXZlZExheWVyLmNvbmZpZy5jb2x1bW5zLFxuICAgIG5ld0xheWVyLmdldExheWVyQ29sdW1ucygpXG4gICk7XG5cbiAgaWYgKCFjb2x1bW5zKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICAvLyB2aXN1YWwgY2hhbm5lbCBmaWVsZCBpcyBzYXZlZCB0byBiZSB7bmFtZSwgdHlwZX1cbiAgLy8gZmluZCB2aXN1YWwgY2hhbm5lbCBmaWVsZCBieSBtYXRjaGluZyBib3RoIG5hbWUgYW5kIHR5cGVcbiAgLy8gcmVmZXIgdG8gdmlzLXN0YXRlLXNjaGVtYS5qcyBWaXN1YWxDaGFubmVsU2NoZW1hVjFcbiAgY29uc3QgZm91bmRWaXN1YWxDaGFubmVsQ29uZmlncyA9IHZhbGlkYXRlU2F2ZWRWaXN1YWxDaGFubmVscyhcbiAgICBmaWVsZHMsXG4gICAgbmV3TGF5ZXIudmlzdWFsQ2hhbm5lbHMsXG4gICAgc2F2ZWRMYXllclxuICApO1xuXG4gIGNvbnN0IHRleHRMYWJlbCA9XG4gICAgc2F2ZWRMYXllci5jb25maWcudGV4dExhYmVsICYmIG5ld0xheWVyLmNvbmZpZy50ZXh0TGFiZWxcbiAgICAgID8gdmFsaWRhdGVTYXZlZFRleHRMYWJlbChcbiAgICAgICAgICBmaWVsZHMsXG4gICAgICAgICAgbmV3TGF5ZXIuY29uZmlnLnRleHRMYWJlbCxcbiAgICAgICAgICBzYXZlZExheWVyLmNvbmZpZy50ZXh0TGFiZWxcbiAgICAgICAgKVxuICAgICAgOiBuZXdMYXllci5jb25maWcudGV4dExhYmVsO1xuXG4gIC8vIGNvcHkgdmlzQ29uZmlnIG92ZXIgdG8gZW1wdHlMYXllciB0byBtYWtlIHN1cmUgaXQgaGFzIGFsbCB0aGUgcHJvcHNcbiAgY29uc3QgdmlzQ29uZmlnID0gbmV3TGF5ZXIuY29weUxheWVyQ29uZmlnKFxuICAgIG5ld0xheWVyLmNvbmZpZy52aXNDb25maWcsXG4gICAgc2F2ZWRMYXllci5jb25maWcudmlzQ29uZmlnIHx8IHt9LFxuICAgIHtub3RUb0RlZXBNZXJnZTogJ2NvbG9yUmFuZ2UnfVxuICApO1xuXG4gIG5ld0xheWVyLnVwZGF0ZUxheWVyQ29uZmlnKHtcbiAgICBjb2x1bW5zLFxuICAgIHZpc0NvbmZpZyxcbiAgICB0ZXh0TGFiZWwsXG4gICAgLi4uZm91bmRWaXN1YWxDaGFubmVsQ29uZmlnc1xuICB9KTtcblxuICBpZiAodHlwZSA9PT0gJ2JvdW5kYXJ5JyB8fCB0eXBlID09PSAncGluY29kZScpIHtcbiAgICBjb25zdCB7Ym91bmRhcnlBZ2dyZWdhdGlvbn0gPSBzYXZlZExheWVyLmNvbmZpZztcbiAgICAvLyBjb25zb2xlLmxvZyhib3VuZGFyeUFnZ3JlZ2F0aW9uKTtcbiAgICBuZXdMYXllci51cGRhdGVMYXllckNvbmZpZyh7XG4gICAgICBib3VuZGFyeUFnZ3JlZ2F0aW9uLFxuICAgICAgYXBpQ2FsbFJlcXVlc3Q6IHRydWUsXG4gICAgICBhcGlDYWxsTG9hZGVyOiB0cnVlXG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gbmV3TGF5ZXI7XG59XG5cbi8qKlxuICogVmFsaWRhdGUgc2F2ZWQgbGF5ZXIgY29uZmlnIHdpdGggbmV3IGRhdGEsXG4gKiB1cGRhdGUgZmllbGRJZHggYmFzZWQgb24gbmV3IGZpZWxkc1xuICpcbiAqIEBwYXJhbSB7T2JqZWN0W119IGZpZWxkc1xuICogQHBhcmFtIHtTdHJpbmd9IGRhdGFJZFxuICogQHBhcmFtIHtPYmplY3R9IHNhdmVkV2lkZ2V0XG4gKiBAcGFyYW0ge09iamVjdH0gd2lkZ2V0Q2xhc3Nlc1xuICogQHJldHVybiB7bnVsbCB8IE9iamVjdH0gLSB2YWxpZGF0ZWQgbGF5ZXIgb3IgbnVsbFxuICovXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVXaWRnZXRBbmRDb25maWcoXG4gIHtmaWVsZHMsIGlkOiBkYXRhSWR9LFxuICBzYXZlZFdpZGdldCxcbiAgd2lkZ2V0Q2xhc3NlcyxcbiAgc3RhdGVcbikge1xuICAvLyBjb25zb2xlLmxvZygnc2F2ZWQgd2lkZ2V0IGluc2lkZSB2YWxpZGF0ZSB3aWRnZXQgYW5kIGNvbmZnJywgc2F2ZWRXaWRnZXQpO1xuICBjb25zdCB7dHlwZX0gPSBzYXZlZFdpZGdldDtcbiAgLy8gbGF5ZXIgZG9lc250IGhhdmUgYSB2YWxpZCB0eXBlXG4gIGlmICghd2lkZ2V0Q2xhc3Nlcy5oYXNPd25Qcm9wZXJ0eSh0eXBlKSB8fCAhc2F2ZWRXaWRnZXQuY29uZmlnKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjb25zdCBuZXdXaWRnZXQgPSBuZXcgd2lkZ2V0Q2xhc3Nlc1t0eXBlXSh7XG4gICAgaWQ6IHNhdmVkV2lkZ2V0LmlkLFxuICAgIGRhdGFJZCxcbiAgICBjb2xvcjogc2F2ZWRXaWRnZXQuY29uZmlnLmNvbG9yLFxuICAgIGlzVmlzaWJsZTogc2F2ZWRXaWRnZXQuY29uZmlnLmlzVmlzaWJsZVxuICB9KTtcbiAgY29uc3QgY29uZmlnID0gbmV3V2lkZ2V0LmNvcHlXaWRnZXRDb25maWcoXG4gICAgbmV3V2lkZ2V0LmNvbmZpZyxcbiAgICBzYXZlZFdpZGdldC5jb25maWcgfHwge31cbiAgKTtcbiAgLy8gY29uc29sZS5sb2coJ2NvbmZpZyBiZWZvcmUgdXBkYXRpbmcgY29uZmlnJywgY29uZmlnKTtcbiAgbmV3V2lkZ2V0LnVwZGF0ZVdpZGdldENvbmZpZyhjb25maWcpO1xuXG4gIC8vIGNvbnNvbGUubG9nKCduZXcgd2lkZ2V0IGJlZm9yZSBhZ2dyZWdhdGlvbiBkYXRhIGNhbGN1bGF0aW9uICcsIG5ld1dpZGdldCk7XG5cbiAgaWYgKHN0YXRlLmxheWVyRGF0YS5sZW5ndGgpIHtcbiAgICBjYWxjdWxhdGVBZ2dyZWdhdGlvbkRhdGEobmV3V2lkZ2V0LCBzdGF0ZSk7XG4gIH1cblxuICAvLyBjb25zb2xlLmxvZyhuZXdXaWRnZXQpO1xuICByZXR1cm4gbmV3V2lkZ2V0O1xufVxuXG4vKipcbiAqIFZhbGlkYXRlIHNhdmVkIGZpbHRlciBjb25maWcgd2l0aCBuZXcgZGF0YSxcbiAqIGNhbGN1bGF0ZSBkb21haW4gYW5kIGZpZWxkSWR4IGJhc2VkIG5ldyBmaWVsZHMgYW5kIGRhdGFcbiAqXG4gKiBAcGFyYW0ge09iamVjdFtdfSBkYXRhc2V0LmZpZWxkc1xuICogQHBhcmFtIHtPYmplY3RbXX0gZGF0YXNldC5hbGxEYXRhXG4gKiBAcGFyYW0ge09iamVjdH0gZmlsdGVyIC0gZmlsdGVyIHRvIGJlIHZhbGlkYXRlXG4gKiBAcmV0dXJuIHtPYmplY3QgfCBudWxsfSAtIHZhbGlkYXRlZCBmaWx0ZXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlRmlsdGVyV2l0aERhdGEoe2ZpZWxkcywgYWxsRGF0YX0sIGZpbHRlcikge1xuICAvLyBtYXRjaCBmaWx0ZXIubmFtZSB0byBmaWVsZC5uYW1lXG4gIGNvbnN0IGZpZWxkSWR4ID0gZmllbGRzLmZpbmRJbmRleCgoe25hbWV9KSA9PiBuYW1lID09PSBmaWx0ZXIubmFtZSk7XG5cbiAgaWYgKGZpZWxkSWR4IDwgMCkge1xuICAgIC8vIGlmIGNhbid0IGZpbmQgZmllbGQgd2l0aCBzYW1lIG5hbWUsIGRpc2NoYXJnZSBmaWx0ZXJcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGNvbnN0IGZpZWxkID0gZmllbGRzW2ZpZWxkSWR4XTtcbiAgY29uc3QgdmFsdWUgPSBmaWx0ZXIudmFsdWU7XG5cbiAgLy8gcmV0dXJuIGZpbHRlciB0eXBlLCBkZWZhdWx0IHZhbHVlLCBmaWVsZFR5cGUgYW5kIGZpZWxkRG9tYWluIGZyb20gZmllbGRcbiAgY29uc3QgZmlsdGVyUHJvcHNGcm9tRmllbGQgPSBnZXRGaWx0ZXJQcm9wcyhhbGxEYXRhLCBmaWVsZCk7XG5cbiAgbGV0IG1hdGNoZWRGaWx0ZXIgPSB7XG4gICAgLi4uZ2V0RGVmYXVsdEZpbHRlcihmaWx0ZXIuZGF0YUlkKSxcbiAgICAuLi5maWx0ZXIsXG4gICAgLi4uZmlsdGVyUHJvcHNGcm9tRmllbGQsXG4gICAgZnJlZXplOiB0cnVlLFxuICAgIGZpZWxkSWR4XG4gIH07XG5cbiAgY29uc3Qge3lBeGlzfSA9IG1hdGNoZWRGaWx0ZXI7XG4gIGlmICh5QXhpcykge1xuICAgIGNvbnN0IG1hdGNoZUF4aXMgPSBmaWVsZHMuZmluZChcbiAgICAgICh7bmFtZSwgdHlwZX0pID0+IG5hbWUgPT09IHlBeGlzLm5hbWUgJiYgdHlwZSA9PT0geUF4aXMudHlwZVxuICAgICk7XG5cbiAgICBtYXRjaGVkRmlsdGVyID0gbWF0Y2hlQXhpc1xuICAgICAgPyB7XG4gICAgICAgICAgLi4ubWF0Y2hlZEZpbHRlcixcbiAgICAgICAgICB5QXhpczogbWF0Y2hlQXhpcyxcbiAgICAgICAgICAuLi5nZXRGaWx0ZXJQbG90KHsuLi5tYXRjaGVkRmlsdGVyLCB5QXhpczogbWF0Y2hlQXhpc30sIGFsbERhdGEpXG4gICAgICAgIH1cbiAgICAgIDogbWF0Y2hlZEZpbHRlcjtcbiAgfVxuXG4gIG1hdGNoZWRGaWx0ZXIudmFsdWUgPSBhZGp1c3RWYWx1ZVRvRmlsdGVyRG9tYWluKHZhbHVlLCBtYXRjaGVkRmlsdGVyKTtcblxuICBpZiAobWF0Y2hlZEZpbHRlci52YWx1ZSA9PT0gbnVsbCkge1xuICAgIC8vIGNhbm50IGFkanVzdCBzYXZlZCB2YWx1ZSB0byBmaWx0ZXJcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBtYXRjaGVkRmlsdGVyO1xufVxuIl19