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

//@include lib_Class.js
//@include lib_sol.common.ObjectUtils.js
//@include lib_sol.common.JsonUtils.js
//@include lib_sol.common.SordUtils.js
//@include lib_sol.common.ix.RfUtils.js

/**
 * @abstract
 *
 * Operations used by elo business solutions are modularized as ix service.
 *
 * Implementations should allow using services in different ways:
 *   - Executed as a registered function call.
 *
 * # Implementing a service
 *
 * A service must extend the class ServiceBase and should implement the registered function RF_custom_services_MyFunction on js script scope level.
 *
 *     sol.define("custom.services.MyFunction", {
 *       extend: "sol.common.ix.ServiceBase",
 *
 *       initialize: function (config) {
 *         var me = this;
 *         me.$super("sol.common.ix.ServiceBase", "initialize", [config]);
 *         me.checkMandatoryProperties("objId");
 *       },
 *
 *       process: function() {
 *         // function logic goes here
 *         var me = this;
 *         me.myParam;
 *       },
 *     });
 *
 *     function RF_custom_services_MyFunction(iXSEContext, args) {
 *       var params = sol.common.ix.RfUtils.parseAndCheckParams(iXSEContext, arguments.callee.name, args, "objId", "myParam"),
 *           service;
 *         service = sol.create("custom.services.MyFunction", params);
 *         service.process();
 *     }
 *
 * # Execute service as ix registered function
 *
 * Functions can be executed with the help of sol.common.ix.RfUtils.execute. In this case the Utils class handles the
 * ix Any-Object transformation.
 *
 *     var data = sol.common.IxUtils.execute('custom.services.MyFunction', {
 *       objId: "4711",
 *       myParam: "Yeah!"
 *     });
 *
 * @author PZ, ELO Digital Office GmbH
 * @version 1.1
 *
 * @eloix
 * @requires sol.common.ObjectUtils
 * @requires sol.common.JsonUtils
 * @requires sol.common.SordUtils
 * @requires sol.common.ix.RfUtils
 * @requires sol.common.ix.ServiceBase
 */
sol.define("sol.common.ix.ServiceBase", {

  /**
   * @property {sol.Logger}
   * @protected
   * The logger for the service
   */
  logger: undefined,

  /**
   * @property {Object} data (optional)
   * Has to be in a specific form (see {@link sol.common.SordUtils#updateSord}).
   */
  data: undefined,

  /** @cfg {string}
   * Object ID for the element
   */
  objId: undefined,

  initialize: function (config) {
    var me = this,
        property;
    me.logger = sol.create("sol.Logger", { scope: me.$className });
    RhinoManager.registerClass(me.$className);
    for (property in config) {
      if (config.hasOwnProperty(property)) {
        me[property] = config[property];
      }
    }
  },

  /**
   * @protected
   * Checks if all mandatory properties have been set.
   */
  checkMandatoryProperties: function () {
    var me = this,
        args = Array.prototype.slice.call(arguments);
    args.forEach(function (arg) {
      if (!me.hasOwnProperty(arg)) {
        throw "missing mandatory argument '" + arg + "'";
      }
    });
  },

  /**
   * @protected
   * Initializes the metadata of an element (defined by `objId`) from the internal `data` object.
   *
   * The `data` property has to be in a specific {@link #data form}.
   * If there is no data object no prefilling will be performed.
   *
   * @param {String} objId
   */
  prefillMetadata: function (objId) {
    var me = this,
        sord, mapitems;

    me.logger.enter("prefillMetadata", arguments);

    if (sol.common.ObjectUtils.isEmpty(me.data)) {
      me.logger.debug("Skip prefillMetadata(): no/empty 'data' property defined");
      return;
    }

    me.logger.debug("Start prefillMetadata() using data", me.data);

    sord = ixConnect.ix().checkoutSord(objId, SordC.mbAllIndex, LockC.NO);
    mapitems = sol.common.SordUtils.updateSord(sord, me.data);

    ixConnect.ix().checkinSord(sord, SordC.mbAllIndex, LockC.NO);

    if (mapitems && (mapitems.length > 0)) {
      ixConnect.ix().checkinMap(MapDomainC.DOMAIN_SORD, objId, objId, mapitems, LockC.NO);
    }

    me.logger.exit("prefillMetadata");
  },

  /**
   * @abstract
   * Implementation of services' process. This function must be implemented by the child class and should contain the logic of the function module.
   */
  process: function () {
    throw "cannot call 'process' of abstract ServiceBase";
  },

  /**
   * Checks wether an array contains the class name
   * @param {Array} classNames
   * @return {Boolean}
   */
  containsClassName: function (classNames) {
    var me = this,
        result = false;
    result = (sol.common.ObjectUtils.isArray(classNames) && (classNames.indexOf(me.$className) > -1));
    return result;
  }
});

/**
 * @member sol.common.ix.ServiceBase
 * @method RF_ServiceBaseName
 * @static
 * @abstract
 *
 * This service can be called from an application by invoking the API function "executeRegisteredFunction" or by using
 * sol.common.IxUtils.execute which internally handles the Any-Object conversion.
 *
 * All configuration params should be passed as a configuration object to the args param.
 *
 *     sol.common.IxUtils.execute('RF_ServiceBaseName', {
 *       configParam1: 'myParam'
 *     });
 *
 * @param {de.elo.ix.client.IXServerEventsContext} Execution context
 * @param {Object} args Argument array sent by the client application.
 */