    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.AclUtils.js
    //@include lib_sol.common.UserUtils.js
    //@include lib_sol.common.TranslateTerms.js
    //@include lib_sol.common.ix.DynKwlSearchIterator.js
    //@include lib_sol.contact.Utils.js

    /**
     * Dynamic keyword list that returns the sord content of contact lists by solution object type.
     *
     * @author PZ, ELO Digital Office GmbH
     * @version 1.02.002
     *
     * @requires sol.common.Config
     * @requires sol.common.SordUtils
     * @requires sol.common.AclUtils
     * @requires sol.common.UserUtils
     * @requires sol.common.TranslateTerms
     * @requires sol.common.ix.DynKwlSearchIterator
     * @requires sol.contact.Utils
     */
    sol.define("sol.contact.ix.dynkwl.FindContactlistIterator", {
      extend: "sol.common.ix.DynKwlSearchIterator",

      /**
       * @cfg
       * @inheritdoc
       */
      searchSordZ: SordC.mbAllIndex,

      /**
       * @cfg
       * @inheritdoc
       */
      tableHeaders: null,

      /**
       * @cfg
       * @inheritdoc
       */
      tableTitle: null,

      /**
       * @cfg
       * @inheritdoc
       */
      tableKeyNames: null,

      /**
       * @cfg
       * Array of datafields used by the search results.
       */
      rowDataFields: null,

      /**
       * @cfg
       * @inheritdoc
       */
      searchParams: [
        { name: "CONTACTLIST_NAME", mode: "STARTS_WITH" },
        { name: "CONTACTLIST_REFERENCE", mode: "STARTS_WITH" }
      ],

      initialize: function (config) {
        var me = this,
            i;

        me.contactlistConfig = sol.contact.Utils.loadConfig();
        me.tableTitle = me.contactlistConfig.dynkwl.contactlist.tableTitle;
        me.tableHeaders = me.contactlistConfig.dynkwl.contactlist.tableHeaders;
        me.tableKeyNames = me.contactlistConfig.dynkwl.contactlist.tableKeyNames;
        me.rowDataFields = me.contactlistConfig.dynkwl.contactlist.rowDataFields;
        me.solType = me.contactlistConfig.contactlist.solType;

        for (i = 0; i < me.tableHeaders.length; i++) {
          me.tableHeaders[i] = sol.common.TranslateTerms.translate(me.tableHeaders[i]);
        }
        me.tableTitle = sol.common.TranslateTerms.translate(me.tableTitle);

        me.$super("sol.common.ix.DynKwlSearchIterator", "initialize", [config]);
      },

      /**
       * Implements a find by type search that is filtered by ObjKeys.
       * @param {Array} filterList
       * @return {de.elo.ix.client.FindInfo}
       */
      getFindInfo: function (filterList) {
        this.log.enter("getFindInfo");
        var me = this,
            findInfo, findByIndex, okeys, okey, i;

        findInfo = new FindInfo();
        findByIndex = new FindByIndex();
        okeys = [];

        okey = new ObjKey();
        okey.name = "SOL_TYPE";
        okey.data = [me.solType];
        okeys.push(okey);

        if (filterList && filterList.length > 0) {
          for (i = 0; i < filterList.length; i++) {
            if (me.searchParams[i].name && filterList[i] && (filterList[i] != "")) {
              okey = new ObjKey();
              okey.name = me.searchParams[i].name;
              okey.data = [filterList[i]];
              okeys.push(okey);
            }
          }
        }

        findByIndex.objKeys = okeys;
        findInfo.findByIndex = findByIndex;

        this.log.exit("getFindInfo");
        return findInfo;
      },

      /**
       * Basic implementation for search results.
       * This returns the content of the sord index fields.
       * @param {de.elo.ix.client.Sord} sord
       * @return {String}
       */
      getRowData: function (sord) {
        var me = this,
            data = [],
            i;

        for (i = 0; i < me.rowDataFields.length; i++) {
          data.push(sol.common.SordUtils.getObjKeyValue(sord, me.rowDataFields[i]));
        }

        return data;
      },

      /**
       * @private
       * Filters the contactlists. Only contactlists, where the user has read and list right will be displayed.
       * @return {de.elo.ix.client.Sord[]}
       */
      getSearchResults: function () {
        var me = this,
            findResult, results, accessibleContactLists, rights;

        me.log.enter("FindContactListIterator_getSearchResults");

        findResult = ixConnect.ix().findFirstSords(this._findInfo, this.searchCount, this.searchSordZ);
        results = findResult.sords || [];
        ixConnect.ix().findClose(findResult.searchId);
        me.log.info("found sords: " + results.length);

        if (!sol.common.UserUtils.isMainAdmin(ixConnect.userName)) {
          accessibleContactLists = [];
          rights = { r: true, l: true };

          if (results && (results.length > 0)) {
            results.forEach(function (sord) {
              var hasCreateRights = me.hasCreateRights(sord, rights);
              if (hasCreateRights == true) {
                accessibleContactLists.push(sord);
              }
            });
          }
        } else {
          accessibleContactLists = results;
        }

        me.log.exit("FindContactListIterator_getSearchResults");

        return accessibleContactLists;
      },

      /**
       * @private
       * Checks wether the current user has effective rights
       * @param {de.elo.ix.client.Sord} sord
       * @param {Object} rights Rights
       * @return {Boolean}
       */
      hasCreateRights: function (sord, rights) {
        var hasCreateRights = false,
            aclAccessInfo, aclAccessResult, accessCode;

        if (!sord) {
          throw "Sord is empty";
        }

        try {
          aclAccessInfo = new AclAccessInfo();
          aclAccessInfo.aclItems = sord.aclItems;

          aclAccessResult = ixConnect.ix().getAclAccess(aclAccessInfo);
          accessCode = aclAccessResult.access;

          hasCreateRights = sol.common.AclUtils.containsRights(accessCode, rights);
        } catch (ignore) {
          // ignore
        }
        return hasCreateRights;
      }

    });

    /**
     * Implements a DynamicKeywordDataProvider for this keyword list that can be used by checkoutKeywordsDynamic.
     * @static
     * @member sol.contact.ix.dynkwl.FindContactlistIterator
     * @returns {DynamicKeywordDataProvider}
     */
    function getDataIterator() {
      var log = sol.create("sol.Logger", { scope: "sol.contact.ix.dynkwl.FindContactlistIterator" }),
          iterator;
      try {
        log.info("DynamicKeywordList (");
        iterator = sol.create("sol.contact.ix.dynkwl.FindContactlistIterator", {});
        return new DynamicKeywordDataProvider(iterator);
      } finally {
        log.info(")getDataIterator");
      }
    }