    importPackage(Packages.de.elo.ix.client);

    //@include lib_Class.js
    //@include lib_sol.common.SordUtils.js
    //@include lib_sol.common.ix.FunctionBase.js

    var logger = sol.create("sol.Logger", { scope: "sol.common.ix.functions.CheckMandatoryFields" });

    /**
     * Checks if all mandatory fields are set.
     *
     * When called as RF it just throws an exception when not all mandatory fields are properly set.
     *
     * When used in a workflow script, it either updates the ELO_WF_STATUS field as configured or throws an exception (in case the check fails).
     * If the `wfStatus` is configured, no exception will be thrown and instead the workflow status will be updated (either the the configured values or the defaults).
     *
     * # As workflow node
     *
     * `ObjId` is set based on the element that the workflow is attached to.
     * Following configuration should be applied to the comments field.
     *
     *     {
     *       "mandatory": [ { "key": "REFERENCE", "type": "GRP" } ],
     *       "wfStatus": { "onSuccess": "yaaay", "onFailure": "ohNooo" }
     *     }
     *
     * # As IX function call
     *
     * In addition to the workflow node configuration the `objId` must be passed.
     *
     *     sol.common.IxUtils.execute("RF_sol_function_CheckMandatoryFields", {
     *       objId: "4711",
     *       mandatory: [ { "key": "REFERENCE", "type": "GRP" } ],
     *       wfStatus: { "onSuccess": "yaaay", "onFailure": "ohNooo" }
     *     });
     *
     * @author PZ, ELO Digital Office GmbH
     * @version 1.0
     *
     * @eloix
     * @requires  sol.common.SordUtils
     * @requires  sol.common.WfUtils
     * @requires  sol.common.ix.RfUtils
     * @requires  sol.common.ix.FunctionBase
     *
     */
    sol.define("sol.common.ix.functions.CheckMandatoryFields", {
      extend: "sol.common.ix.FunctionBase",

      requiredConfig: ["objId", "mandatory"],

      /**
       * @cfg {String} objId
       * The object which should be checked.
       */

      /**
       * @cfg {Array} mandatory
       * A list of mandatory fields. The objects need two properties: `key` and `type`.
       *
       *     "mandatory": [ { "key": "REFERENCE", "type": "GRP" } ],
       *
       * - `type`: This string can either be "GRP", "SORD", "MAP", or "WFMAP"
       * - `key`: This is, depending on the `type`, either an index field name, a map field, a workflow map field or a property name of de.elo.ix.client.Sord
       */

      /**
       * @cfg {Object} wfStatus
       *
       *     "wfStatus": { "onSuccess": "yaaay", "onFailure": "ohNooo" }
       *
       * This object can override the default workflow states which will be set after the check, if ths was used in a workflow node.
       * If the is `undefined`, the unction will throw an exception in case the checke fails.
       *
       * - `onSuccess`: set as ELO_WF_STATUS after a successfull check
       * - `onFailure`: set as ELO_WF_STATUS after a check failure
       */

      /**
       * @private
       * @property {String} [DEFAULT_PASSED_STATUS="PASSED"] Default workflow status in case of a successful check
       */
      DEFAULT_PASSED_STATUS: "PASSED",
      /**
       * @private
       * @property {String} [DEFAULT_FAILED_STATUS="FAILED"] Default workflow status in case of a check failure
       */
      DEFAULT_FAILED_STATUS: "FAILED",

      initialize: function (config) {
        var me = this;
        me.$super("sol.common.ix.FunctionBase", "initialize", [config]);
      },

      /**
       * Change the node user.
       */
      process: function () {
        var me = this,
            valid = me.checkMandatoryFields(),
            startNode, status;

        if (me.wfDiagram) {
          startNode = sol.common.WfUtils.getNode(me.wfDiagram, 0);
          if (valid) {
            status = (me.wfStatus && me.wfStatus.onSuccess) ? me.wfStatus.onSuccess : me.DEFAULT_PASSED_STATUS;
          } else {
            status = (me.wfStatus && me.wfStatus.onFailure) ? me.wfStatus.onFailure : me.DEFAULT_FAILED_STATUS;
          }
          startNode.yesNoCondition = status;
          me.logger.info(["changed ELO_WF_STATUS to '{0}' (objId={1}, flowId={2})", status, me.objId, me.wfDiagram.id]);
        }
      },

      /**
       * @private
       * @return {Boolean} status
       */
      checkMandatoryFields: function () {
        var me = this,
            sord = ixConnect.ix().checkoutSord(me.objId, SordC.mbAllIndex, LockC.NO),
            invalid, error;

        me.logger.info(["start check: objId={0}", me.objId]);

        if (!Array.isArray(me.mandatory)) {
          throw "'mandatory' has to be an Array";
        }

        if (me.mandatory.length <= 0) {
          throw "'mandatory' attribute can not be empty";
        }

        invalid = me.mandatory.some(function (field) {
          var value, mapitems;

          if (!field.type || !field.key) {
            throw "invalid field declaration: " + JSON.stringify(field);
          }

          switch (field.type) {
            case "GRP":
              value = sol.common.SordUtils.getObjKeyValue(sord, field.key);
              if (me.isEmpty(value)) {
                error = "missing or empty objkey: '" + field.key + "'";
                return true;
              }
              break;
            case "SORD":
              value = sord[field.key];
              if (me.isEmpty(value)) {
                error = "invalid or empty sordkey: '" + field.key + "'";
                return true;
              }
              break;
            case "MAP":
              mapitems = ixConnect.ix().checkoutMap(MapDomainC.DOMAIN_SORD, sord.id, [field.key], LockC.NO).items;
              if (!mapitems || mapitems.length <= 0) {
                error = "invalid or empty mapkey: '" + field.key + "'";
                return true;
              }
              break;
            case "WFMAP":
              mapitems = ixConnect.ix().checkoutMap(MapDomainC.DOMAIN_WORKFLOW_ACTIVE, sord.id, [field.key], LockC.NO).items;
              if (!mapitems || mapitems.length <= 0) {
                error = "invalid or empty wfmapkey: '" + field.key + "'";
                return true;
              }
              break;
            default:
              throw "unsuported type: '" + field.type + "'";
          }
          return false;
        });

        if (error) {
          me.logger.debug("error in check: ", error);
        }

        if ((!me.wfDiagram && invalid) || (me.wfDiagram && !me.wfStatus && invalid)) {
          throw error;
        }

        me.logger.info(["check finished: objId={0}; successful={1};", me.objId, !invalid]);

        return !invalid;
      },

      /**
       * @private
       * @param {String} str
       * @return {Boolean} status
       */
      isEmpty: function (str) {
        return !str || Packages.org.apache.commons.lang.StringUtils.isBlank(str);
      }
    });

    /**
     * @member sol.common.ix.functions.CheckMandatoryFields
     * @static
     * @inheritdoc sol.common.ix.FunctionBase#onEnterNode
     */
    function onEnterNode(clInfo, userId, wFDiagram, nodeId) {
      logger.enter("onEnterNode_CheckMandatoryFields", { flowId: wFDiagram.id, nodeId: nodeId });
      var params = sol.common.WfUtils.parseAndCheckParams(wFDiagram, nodeId, "mandatory"),
          module;

      params.objId = wFDiagram.objId;
      params.wfDiagram = wFDiagram;
      module = sol.create("sol.common.ix.functions.CheckMandatoryFields", params);

      module.process();

      logger.exit("onEnterNode_CheckMandatoryFields");
    }

    /**
     * @member sol.common.ix.functions.CheckMandatoryFields
     * @static
     * @inheritdoc sol.common.ix.FunctionBase#onExitNode
     */
    function onExitNode(clInfo, userId, wFDiagram, nodeId) {
      logger.enter("onExitNode_CheckMandatoryFields", { flowId: wFDiagram.id, nodeId: nodeId });
      var params = sol.common.WfUtils.parseAndCheckParams(wFDiagram, nodeId, "mandatory"),
          module;

      params.objId = wFDiagram.objId;
      params.wfDiagram = wFDiagram;
      module = sol.create("sol.common.ix.functions.CheckMandatoryFields", params);

      module.process();

      logger.exit("onExitNode_CheckMandatoryFields");
    }

    /**
     * @member sol.common.ix.functions.CheckMandatoryFields
     * @method RF_sol_function_CheckMandatoryFields
     * @static
     * @inheritdoc sol.common.ix.FunctionBase#RF_FunctionName
     */
    function RF_sol_function_CheckMandatoryFields(iXSEContext, args) {
      logger.enter("RF_sol_function_CheckMandatoryFields", args);
      var params = sol.common.ix.RfUtils.parseAndCheckParams(iXSEContext, arguments.callee.name, args, "objId", "mandatory"),
          module = sol.create("sol.common.ix.functions.CheckMandatoryFields", params);

      module.process();

      logger.exit("RF_sol_function_CheckMandatoryFields");
    }