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

    //@include lib_Class.js
    //@include lib_sol.common.SordUtils.js
    //@include lib_sol.common.AclUtils.js
    //@include lib_sol.common.AsyncUtils.js
    //@include lib_sol.common.WfUtils.js
    //@include lib_sol.common.ix.RfUtils.js
    //@include lib_sol.common.ix.FunctionBase.js
    //@include lib_sol.contact.Utils.js

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

    /**
     * Moves a contact element to a new location in a company if possible.
     *
     * # As workflow node
     *
     * ObjId is set based on the element that the workflow is attached to.
     *
     * # As IX function call
     *
     * In addition to the workflow node configuration the objId must be passed.
     *
     *     sol.common.IxUtils.execute('RF_sol_contact_function_MoveContact', {
     *       objId: "4711"
     *     });
     *
     * |Property|Description|
     * |:------|:------|
     * |contactlist.referenceField|Reference field to the contact list|
     * |contactlist.maskName|Mask for contact lists|
     * |company.referenceField|Reference field to the company|
     * |company.maskName|Mask for companies|
     *
     * @author JHR, ELO Digital Office GmbH
     * @version 1.0
     *
     * @eloix
     * @requires  handlebars
     * @requires  sol.common.SordUtils
     * @requires  sol.common.WfUtils
     * @requires  sol.common.ix.RfUtils
     * @requires  sol.common.ix.FunctionBase
     *
     */
    sol.define("sol.contact.ix.functions.MoveContact", {
      extend: "sol.common.ix.FunctionBase",

      requiredConfig: ["objId"],

      /**
       * @cfg {String} objId (required)
       * Object ID
       */

      /**
       * @cfg {Boolean} [update=false]
       * Update mode
       */

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

      /**
       * Moves the contact element to a new location in a company or contact list if possible.
       */
      process: function () {
        var me = this,
            alreadyMoved = false,
            sord, rightsConfig, configPart, currentUserRightsEntry;

        me.logger.debug(["Move contact element: objId={0}, ixConnect.user={1}, update={2}", me.objId + "", ixConnect.loginResult.user.name + "", me.update]);

        sord = ixConnect.ix().checkoutSord(me.objId, EditInfoC.mbSord, LockC.NO).sord;

        if (!sol.contact.Utils.isCompany(sord)) {
          alreadyMoved = me.moveByReferenceField(sord, "CompanyReference", me.config.company.maskName, me.config.company.referenceField);
        }

        if (!alreadyMoved) {
          me.moveByReferenceField(sord, "ContactlistReference", me.config.contactlist.maskName, me.config.contactlist.referenceField);
        }

        if (!me.update) {
          configPart = sol.contact.Utils.getConfigPart(me.config, sord);
          currentUserRightsEntry = { name: "$CURRENTUSER", rights: { r: true, w: true, d: true, e: true, l: true, p: true } };

          rightsConfig = configPart.rightsConfig;

          if (rightsConfig) {
            rightsConfig.users = rightsConfig.users || [];
            rightsConfig.users.push(currentUserRightsEntry);
          } else {
            rightsConfig = {
              mode: "SET",
              inherit: true,
              users: [currentUserRightsEntry]
            };
          }

          me.logger.debug(["Set contact element rights: objId={0}, rightsConfig={1}", me.objId + "", JSON.stringify(rightsConfig)]);

          sol.common.AclUtils.changeRightsInBackground(me.objId, rightsConfig);
        }
      },

      /**
       * @private
       * Moves the contract to the correct lcation.
       * @param {de.elo.ix.client.Sord} sord
       * @param {String} refName
       * @param {String} targetMask
       * @param {String} refField
       * @return {Boolean}
       */
      moveByReferenceField: function (sord, refName, targetMask, refField) {
        var me = this,
            ref = sol.common.SordUtils.getObjKeyValue(sord, refField),
            targetSord, oldParentId;
        if (ref) {
          targetSord = me.findSord({ mask: targetMask, objKeyData: [{ key: refField, value: ref }] });
          if (targetSord) {
            oldParentId = ixConnect.ix().checkoutSord(sord.id, EditInfoC.mbOnlyId, LockC.NO).sord.parentId;
            me.logger.info(["move sord: ({0}) from -> ({1}) to ({2})", sord.id, oldParentId, targetSord.id]);
            ixConnectAdmin.ix().refSord(oldParentId, targetSord.id, sord.id, -1);
            return true;
          } else {
            me.logger.error(["could not resolve {0}: {1}", refName, ref]);
            throw "could not resolve " + refName + ": " + ref;
          }
        }
      },

      /**
       * @private
       * Retrieves a sord by index value
       * @param {Object} cfg
       * @return {de.elo.ix.client.Sord}
       */
      findSord: function (cfg) {
        try {
          return sol.common.RepoUtils.getSord(sol.common.RepoUtils.getObjIdByIndex(cfg));
        } catch (ignore) {
          // ignore
        }
      }
    });

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

      params.objId = wFDiagram.objId;
      module = sol.create("sol.contact.ix.functions.MoveContact", params);

      module.process();

      logger.exit("onEnterNode_MoveContact");
    }

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

      params.objId = wFDiagram.objId;
      module = sol.create("sol.contact.ix.functions.MoveContact", params);

      module.process();

      logger.exit("onExitNode_MoveContact");
    }

    /**
     * @member sol.contact.ix.functions.MoveContact
     * @method RF_sol_contact_function_MoveContact
     * @static
     * @inheritdoc sol.common.ix.FunctionBase#RF_FunctionName
     */
    function RF_sol_contact_function_MoveContact(iXSEContext, args) {
      logger.enter("RF_sol_contact_function_MoveContact", args);
      var params, module;

      params = sol.common.ix.RfUtils.parseAndCheckParams(iXSEContext, arguments.callee.name, args, "objId");
      module = sol.create("sol.contact.ix.functions.MoveContact", params);

      module.process();

      logger.exit("RF_sol_contact_function_MoveContact");
    }