    importPackage(Packages.de.elo.ix.jscript);
    importPackage(Packages.de.elo.ix.scripting);

    //@include lib_Class.js
    //@include lib_sol.common.Config.js
    //@include lib_sol.common.SordUtils.js
    //@include lib_sol.common.ObjectUtils.js
    //@include lib_sol.common.TranslateTerms.js
    //@include lib_sol.common.Injection.js

    /**
     * Dynamic keyword list that returns the config content.
     *
     * @author ELO Digital Office GmbH
     * @version 1.0
     *
     * @requires sol.common.Config
     * @requires sol.common.SordUtils
     * @requires sol.common.ObjectUtils
     * @requires sol.common.TranslateTerms
     * @requires sol.common.Injection
     */
    sol.define("sol.common_monitoring.ix.dynkwl.ConfigKwl", {
      logger: sol.create("sol.Logger", { scope: "sol.common_monitoring.dynkwl.ConfigKwl" }),

      type: null,
      translate: false,
      tableTitle: undefined,
      tableHeaders: [
        "Name",
        "Shift",
        "Workflow",
        "Namensraum",
        "Schlüssel"
      ],
      tableKeyNames: [null],
      rowDataFields: [
        "name",
        "shift.value",
        "action.action",
        "namespace",
        "key"
      ],
      errorMessage: "",

      index: 0,
      resultSet: [],

      inject: {},
      $configRelation: {},

      initialize: function (config) {
        var me = this;
        config = config || {};
        me.initializeInjections(config);
        me.prepareConfig();
      },

      initializeInjections: function (config) {
        var me = this,
            baseKwlPath = config.kwlName + ".";

        if (config.configPath && config.kwlConfigPath && config.kwlName) {
          // setup configRelation
          me.$configRelation.kwlConfig = config.kwlConfigPath;
          me.$configRelation.config = config.configPath;
          // setup injection
          me.inject = {
            namespace: { config: "kwlConfig", prop: 'namespace' },
            type: { config: "kwlConfig", prop: baseKwlPath + 'type' },
            translate: { config: "kwlConfig", prop: baseKwlPath + 'translate' },
            tableTitle: { config: "kwlConfig", prop: baseKwlPath + 'title' },
            tableHeaders: { config: "kwlConfig", prop: baseKwlPath + 'header' },
            tableKeyNames: { config: "kwlConfig", prop: baseKwlPath + 'output' },
            rowDataFields: { config: "kwlConfig", prop: baseKwlPath + 'dataFields' },
            searchParams: { config: "kwlConfig", prop: baseKwlPath + 'searchParams' },
            errorMessage: { config: "kwlConfig", prop: baseKwlPath + 'errorMessage' },
            configs: { config: "config", prop: "configs" }
          };
          // inject
          sol.create("sol.common.Injection").inject(me);
        }
      },

      prepareConfig: function () {
        var me = this;

        Object.keys(me.configs || {}).forEach(function (key) {
          me.configs[key].key = me.configs[key].key || key;
          me.configs[key].namespace = me.configs[key].namespace || me.namespace;
        });
      },

      getResults: function (searchValue) {
        var me = this,
            configs = me.configs,
            searchParams = me.searchParams;

        return me.eachObjectKey(configs)
          .filter(function (config) {
            return (searchParams || [])
              .reduce(
                me.useOperator(searchValue, config, {}).bind(me),
                true
              );
          });
      },

      eachObjectKey: function (obj) {
        return Object.keys(obj || {})
          .map(function (key) {
            return obj[key];
          });
      },

      useOperator: function (value, config, parentParam) {
        var me = this;

        function matches(_value, _config, param) {
          return param.operator
            ? (param.searchParams || [])
              .reduce(
                me.useOperator(_value, _config, param).bind(me),
                param.operator != "or"
              )
            : me.compare(param.mode)(
              (_config[param.name] || "").toLowerCase(),
              (param.value || _value || "").toLowerCase()
            );
        }

        return function (intermediate, param) {
          return parentParam.operator == "or"
            ? intermediate || matches.apply(me, [value, config, param])
            : intermediate && matches.apply(me, [value, config, param]);
        };
      },

      compare: function (method) {
        var compare = {
          STARTS_WITH: function (searchIn, search) {
            return (searchIn || "")
              .indexOf(search || "", 0) == 0;
          },
          ENDS_WITH: function (searchIn, search) {
            return (searchIn || "")
              .indexOf((search || ""), (searchIn || "").length - (search || "").length) != -1;
          },
          CONTAINS: function (searchIn, search) {
            return (searchIn || "").indexOf(search || "") != -1;
          },
          default: function (searchIn, search) {
            return typeof search != undefined && searchIn == search;
          }
        };

        return compare[method] || compare.default;
      },

      open: function (ec, sord, fieldName) {
        var me = this;
        me.logger.info("open", [sord.id, fieldName]);

        me.index = 0;
        me.fieldName = fieldName;

        me.resultSet = me.getResults(sol.common.SordUtils.getObjKeyValue(sord, fieldName));
      },

      openMap: function (ec, map, focusName) {
        var me = this;
        me.logger.info("open", [map, focusName]);

        me.index = 0;
        me.fieldName = focusName;

        me.updateTableKeyNames(focusName);

        me.resultSet = me.getResults(map[focusName]);
      },

      updateTableKeyNames: function (focusName) {
        var me = this,
            fieldIndex;

        fieldIndex = me.getIndexFromName(focusName);

        me.tableKeyNames = !fieldIndex
          ? (me.tableKeyNames || [])
          : (me.tableKeyNames || [])
            .map(function (keyName) {
              return !!keyName
                ? keyName.replace("{i}", fieldIndex)
                : null;
            });
      },

      getIndexFromName: function (focusName) {
        var name = String(focusName);
        return !name
          ? null
          : name.search(/\d+$/) > 0
            ? name.substring(name.search(/\d+$/))
            : "";
      },

      close: function () { },

      hasMoreRows: function () {
        var me = this;

        return me.index < me.resultSet.length;
      },

      getTitle: function () {
        var me = this;
        return me.tableTitle;
      },

      getHeader: function () {
        var me = this;
        return me.tableHeaders;
      },

      getNextRow: function () {
        var me = this;

        if (me.resultSet[me.index]) {
          return me.getRowData(me.resultSet[me.index++]);
        }
      },

      getRowData: function (data) {
        var me = this;

        return (me.rowDataFields || [])
          .map(function (rowDataField) {
            return sol.common.ObjectUtils.getProp(data, rowDataField);
          });
      },

      getKeyNames: function () {
        var me = this,
            keyNames;

        keyNames = (me.tableKeyNames || []).length == me.rowDataFields.length
          ? me.tableKeyNames || []
          : (me.rowDataFields || [])
            .map(function () {
              return null;
            });

        keyNames[keyNames.length - 1] = keyNames[keyNames.length - 1] || me.fieldName;
        return keyNames;
      },

      getMessage: function () {
        var me = this;
        return me.errorMessage;
      },

      getIterator: function () {
        var me = this;
        return me;
      }
    });

    /**
     * Implements a DynamicKeywordDataProvider
     * @static
     * @member sol.common_monitoring.dynkwl.ConfigKwlIterator
     * @return {DynamicKeywordDataProvider}
     */
    function getDataIterator() {
      var log = sol.create("sol.Logger", { scope: "sol.common_monitoring.dynkwl.ConfigKwl" }),
          iterator;

      try {
        log.info("DynamicKeywordList (");

        iterator = sol.create("sol.common_monitoring.ix.dynkwl.ConfigKwl", {
          // eslint-disable-next-line no-undef
          configPath: configPath,
          // eslint-disable-next-line no-undef
          kwlConfigPath: kwlConfigPath,
          // eslint-disable-next-line no-undef
          kwlName: kwlName
        });

        return new DynamicKeywordDataProvider(iterator);
      } catch (e) {
        if (e instanceof ReferenceError) {
          // Handle error as necessary
          log.info('please specify configPath, kwlConfigPath and kwlName');
        }
      } finally {
        log.info(")getDataIterator");
      }
    }