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

    //@include lib_Class.js

    /**
     * Base class for a dynamic keyword list that provides user names and IDs
     *
     * The list of current fields is returned as a table.
     *
     * |ID|Name|
     * |:-----|:------|
     * |0|Administrator|
     * |1|Michael Jackson|
     * |2|Donald Duck|
     *
     * # Example implementation
     *
     * Following example shows the implementation of an iterator that returns user names and IDs:
     *
     *     // script: sol.common.ix.DynKwlUserNameIterator.js
     *     sol.define("sol.common.ix.dynkwl.UserNames", {
     *       extend: "sol.common.ix.DynKwlUserNameIterator",
     *       initialize: function (config) {
     *         var me = this;
     *         me.$super("sol.common.ix.DynKwlUserNameIterator", "initialize", [config]);
     *       }
     *     });
     *
     *     function getDataIterator () {
     *       var log = sol.create("sol.Logger", { scope: "sol.common.ix.DynKwlUserNameIterator" }),
     *           iterator;
     *       try {
     *         log.info("DynamicKeywordList (");
     *         iterator = sol.create("sol.common.ix.dynkwl.UserNames", {});
     *         return new DynamicKeywordDataProvider(iterator);
     *       } finally {
     *         log.info(")getDataIterator");
     *       }
     *     }
     *
     * @author MW, ELO Digital Office GmbH
     * @version 1.1
     *
     * @eloix
     *
     * @requires sol.common.SordUtils
     * @requires sol.common.StringUtils
     * @requires sol.common.TranslateTerms
     * @requires sol.common.UserUtils
     */
    sol.define("sol.common.ix.DynKwlUserNameIterator", {

      /**
       * @cfg {string} tableTitle
       * name of this table. The title is displayed by the client.
       */
      tableTitle: undefined,

      /**
       * @cfg {Array} tableHeaders (required)
       * column header names. if null column is hidden in the client.
       *
       *     ["Name", "Description"]
       */
      tableHeaders: undefined,

      /**
       * @cfg {Boolean} [onlyUsers=false] If set to `true` the iterator only returns users
       */
      onlyUsers: false,

      /**
       * @cfg {Boolean} [onlyGroups=false] If set to `true` the iterator only returns groups
       */
      onlyGroups: false,

      /**
       * @cfg {Boolean} [visible=false] If set to `true` the iterator only returns visible users
       */
      visible: false,

      /**
       * @cfg {Boolean} [excludeLockedUsers=false] If set to `true` the iterator only returns excludeLocked users
       */
      excludeLockedUsers: false,

      /**
       * @property
       * @private
       * Error message that is passed to the client if value is missing.
       */
      errorMessage: "",

      /**
       * @cfg {String} userIdFieldName (optional)
       * Name of the user ID field. If this field name is not provided then it will be {{currentFieldName}} + _ID + {{index}}.
       */

      initialize: function (config) {
        var me = this,
            terms = sol.common.TranslateTerms;

        me.log = sol.create("sol.Logger", { scope: this.$className || "sol.common.ix.DynKwlUserNameIterator" });
        me.log.enter("initialize", config);
        config = config || {};

        terms.require("sol.common.dynkwl.userNames");

        me.tableTitle = config.tableTitle || me.tableTitle || terms.translate("sol.common.dynkwl.userNames.tableTitle");
        me.tableHeaders = config.tableHeaders || me.tableHeaders || [null, terms.translate("sol.common.dynkwl.userNames.header.name")];
        me.userIdFieldName = config.userIdFieldName;

        me.onlyUsers = config.onlyUsers || me.onlyUsers;
        me.onlyGroups = config.onlyGroups || me.onlyGroups;

        me.errorMessage = "";
        me.log.exit("initialize");
      },

      /**
       * Opens a connection for the elo java client and non map field capable clients.
       *
       * @param {de.elo.ix.client.IXServerEventsContext} ec
       * @param {de.elo.ix.client.Sord} sord Working version of the current sord object
       * @param {String} fieldName Name of the currently focused field
       */
      open: function (ec, sord, fieldName) {
        var me = this,
            value;
        me.log.enter("open", { sord: sord, fieldName: fieldName });

        value = sol.common.SordUtils.getObjKeyValue(sord, fieldName);
        me.buildKeyNames(fieldName);

        me.index = 0;
        me.resultSet = me.getUserTable(value);
        me.log.exit("open");
      },

      /**
       * Opens a connection for elo wf forms and map field capable components
       *
       * @param {de.elo.ix.client.IXServerEventsContext} ec
       * @param {java.util.HashMap} map Map of all entries passed by the client
       * @param {String} focusName Name of the currently focused field
       */
      openMap: function (ec, map, focusName) {
        var me = this,
            value;

        me.log.enter("openMap", { focusName: focusName, map: map });

        value = map[focusName];
        me.buildKeyNames(focusName);

        me.index = 0;
        me.resultSet = me.getUserTable(value);
        me.log.exit("openMap");
      },

      /**
       * Builds the table key names
       * @param {String} fieldName Field name
       */
      buildKeyNames: function (fieldName) {
        var me = this,
            userFieldName, fieldIndex;
        userFieldName = String(fieldName);
        fieldIndex = sol.common.StringUtils.getTrailingNumber(userFieldName) || "";
        if (!me.userIdFieldName) {
          me.userIdFieldName = sol.common.StringUtils.removeTrailingNumber(userFieldName) + "_ID" + fieldIndex;
        }
        me._keyNames = [me.userIdFieldName, userFieldName];
      },

      /**
       * Returns the next row of the table.
       *
       * @return {Array} table row
       */
      getNextRow: function () {
        var me = this,
            row;
        me.log.debug("getNextRow");
        row = me.resultSet[me.index++];
        return row;
      },

      /**
       * Returns the header of this table that can be displayed by the clients.
       *
       * @return {Array} table header
       */
      getHeader: function () {
        var me = this;
        me.log.debug("getHeader");
        return me.tableHeaders;
      },

      /**
       * Returns the keys of this table that can be used in order to map
       * map or group fields with columns.
       *
       * @return {Array} Table keys
       */
      getKeyNames: function () {
        var me = this;
        me.log.debug("getKeyNames");
        return me._keyNames;
      },

      /**
       * Returns true if table has more rows.
       *
       * @return {Boolean} Has more rows
       */
      hasMoreRows: function () {
        var me = this;
        me.log.debug("hasMoreRows");
        return (this.index < (this.resultSet.length));
      },

      /**
       * Returns the error message that should be displayed by the client
       * instead of the table data.
       *
       * @return {String} Error message
       */
      getMessage: function () {
        var me = this;
        me.log.debug("getMessage");
        return this.errorMessage;
      },

      /**
       * Returns a title for this table used by the user interface.
       *
       * @return {String} title
       */
      getTitle: function () {
        var me = this;
        me.log.debug("getTitle");
        return this.tableTitle;
      },

      /**
       * Returns the user name and ID table
       * @private
       * @param {String} value Current value
       * @return {Array}
       */
      getUserTable: function (value) {
        var me = this, userNames,
            userNameTable = [],
            i, userName;

        value = (value == undefined) ? "" : String(value);
        userNames = sol.common.UserUtils.getUserNames({ namePart: value, onlyUsers: me.onlyUsers, onlyGroups: me.onlyGroups,
          excludeLockedUsers: me.excludeLockedUsers, visible: me.visible });

        for (i = 0; i < userNames.length; i++) {
          userName = userNames[i];
          userNameTable.push([String(userName.id), String(userName.name)]);
        }

        userNameTable = sol.common.ObjectUtils.sortTableByColumn(userNameTable, 1);

        return userNameTable;
      }
    });