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

    //@include lib_Class.js
    //@include lib_sol.common.Config.js
    //@include lib_sol.common.SordUtils.js
    //@include lib_sol.common.ObjectFormatter.js
    //@include lib_sol.common.ix.ServiceBase.js
    //@include lib_sol.common.ix.DataCollectorBase.js

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

    /**
     * Collects all parent information from the hierarchy.
     *
     * The hierarchy will be returned as a flat structure.
     *
     * The result hierarchy contains the following properties:
     *
     * - sord: The selected element itself
     * - parent: The direct parent element
     * - SOL_TYPE: For each found SOL_TYPE one property (see {@link #mode}), could contain duplicates to 'parent' and 'sord'
     *
     * # Example
     *
     *     var result = sol.common.IxUtils.execute("RF_sol_common_service_ParentDataCollector", {
     *       objId: "5690",
     *       formatter: "sol.common.ObjectFormatter.StatisticSord"
     *     });
     *
     * # Result
     *
     *     {
     *       version: '1.00.000',
     *       formatter: 'sol.common.ObjectFormatter.StatisticSord',
     *       sord: {
     *         id: "5690",
     *         name: 'Annual report',
     *         O_INVOICE_DATE: '20160101'
     *       },
     *       parent: {
     *         id: "5669",
     *         name: '12 Public relations',
     *         O_INVOICE_DATE: '20151202'
     *       },
     *       FILE: {
     *         id: "5669",
     *         name: '12 Public relations',
     *         O_INVOICE_DATE: '20151202'
     *       },
     *       ...
     *     }
     *
     *
     * @author PZ, ELO Digital Office GmbH
     * @version 1.1
     *
     * @eloix
     * @requires sol.common.Config
     * @requires sol.common.JsonUtils
     * @requires sol.common.SordUtils
     * @requires sol.common.ObjectFormatter
     * @requires sol.common.ix.RfUtils
     * @requires sol.common.ix.ServiceBase
     * @requires sol.common.ix.DataCollectorBase
     *
     */
    sol.define("sol.common.ix.services.ParentDataCollector", {
      extend: "sol.common.ix.DataCollectorBase",

      requiredConfig: ["objId"],

      collectorVersion: "1.01.000",

      MODES: {
        FIRST_WINS: "FIRST_WINS",
        LAST_WINS: "LAST_WINS",
        ALL: "ALL"
      },

      DEFAULT_VALUES: {
        hierarchicalIdentifier: "SOL_TYPE",
        mode: "FIRST_WINS",
        formatter: "sol.common.ObjectFormatter.TemplateSord",
        sordKeys: ["id", "guid", "maskName", "name", "desc", "IDateIso", "XDateIso", "ownerName"],
        allMapFields: false
      },

      /**
       * @cfg {String} objId (required)
       * id of the parent element (guid, objId or archivepath)
       */

      /**
       * @cfg {String} [hierarchicalIdentifier="SOL_TYPE"]
       * The value from this field will be used to collect the hierarchy
       */

      /**
       * @cfg {String} [mode="FIRST_WINS"]
       * The mode defines, which object from the hierarchy will be send with the result.
       *
       * - "FIRST_WINS": the first hit (upwards) in the hierarchy for each type wins
       * - "LAST_WINS": the last hit (upwards) in the hierarchy for each type wins
       * - "ALL": collects an array of the specific type (not implemented yet)
       *
       */

      /**
       * @cfg {String} [formatter="sol.common.ObjectFormatter.TemplateSord"]
       * Sord object formatter implementation.
       *
       * e.g. `sol.common.ObjectFormatter.StatisticSord` or `sol.common.ObjectFormatter.TemplateSord`
       */

      /**
       * @cfg {String[]} sordKeys
       * The data objects will contain this keys from the sord.
       * By default the following keys will be returned: ['id', 'guid', 'maskName', 'name', 'desc', 'IDateIso', 'XDateIso', 'ownerName']
       */

      /**
       * @cfg {Boolean} allMapFields
       * The data objects will contain all map fields.
       */

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

        me.hierarchicalIdentifier = config.hierarchicalIdentifier || me.DEFAULT_VALUES.hierarchicalIdentifier;
        me.mode = config.mode || me.DEFAULT_VALUES.mode;
        me.formatter = config.formatter || me.DEFAULT_VALUES.formatter;
        me.sordKeys = config.sordKeys || me.DEFAULT_VALUES.sordKeys;
        me.allMapFields = config.allMapFields || me.DEFAULT_VALUES.allMapFields;
      },

      /**
       * Starts the collection of the desired data
       * @return {String}
       */
      execute: function () {
        var me = this,
            data = {},
            sord, parentSord;

        data.version = me.collectorVersion;
        data.formatter = me.formatter;

        try {
          sord = ixConnect.ix().checkoutSord(me.objId, SordC.mbAllIndex, LockC.NO);
          data.sord = me.createTemplateSord(sord);
        } catch (ex) {
          me.logger.warn("Error collecting sord data, continue with data collected so far", ex);
        }

        try {
          parentSord = ixConnect.ix().checkoutSord(sord.parentId, SordC.mbAllIndex, LockC.NO);
          data.parent = me.createTemplateSord(parentSord);
        } catch (ex) {
          me.logger.warn("Error collecting parent sord data, continue with data collected so far", ex);
        }

        try {
          me.collectHierarchy(sord, data);
        } catch (ex) {
          me.logger.warn("Error collecting sord hierarchy, continue with data collected so far", ex);
        }

        return sol.common.JsonUtils.stringifyAll(data);
      },

      /**
       * @private
       * @param {de.elo.ix.client.Sord} sord
       * @param {Object} dataObj
       */
      collectHierarchy: function (sord, dataObj) {
        var me = this,
            type;

        if (sord.id > 1) {
          type = sol.common.SordUtils.getObjKeyValue(sord, me.hierarchicalIdentifier);
          if (type) {
            switch (me.mode) {
              case me.MODES.FIRST_WINS:
                if (!dataObj[type]) {
                  dataObj[type] = me.createTemplateSord(sord);
                }
                break;
              case me.MODES.LAST_WINS:
                dataObj[type] = me.createTemplateSord(sord);
                break;
              case me.MODES.ALL:
                throw "mode '" + me.MODES.ALL + "' is not implemented yet";
              default:
                throw "mode" + me.mode + "is not defined";
            }
          }
          me.collectHierarchy(ixConnect.ix().checkoutSord(sord.parentId, SordC.mbAllIndex, LockC.NO), dataObj);
        }
      },

      /**
       * @private
       * @param {de.elo.ix.client.Sord} sord
       * @return {Object}
       */
      createTemplateSord: function (sord) {
        var me = this;
        return sol.common.ObjectFormatter.format({
          sord: {
            formatter: me.formatter,
            data: sord,
            config: {
              allMapFields: me.allMapFields,
              sordKeys: me.sordKeys
            }
          }
        }).sord;
      }

    });

    /**
     * @member sol.common.ix.services.ParentDataCollector
     * @method RF_sol_common_service_ParentDataCollector
     * @static
     * @inheritdoc sol.common.ix.ServiceBase#RF_ServiceBaseName
     */
    function RF_sol_common_service_ParentDataCollector(ec, configAny) {
      logger.enter("RF_sol_common_service_ParentDataCollector", configAny);
      var rfUtils = sol.common.ix.RfUtils,
          config = rfUtils.parseAndCheckParams(ec, arguments.callee.name, configAny, "objId"),
          jsonDataCollector, result;

      jsonDataCollector = sol.create("sol.common.ix.services.ParentDataCollector", config);
      result = jsonDataCollector.execute();
      logger.exit("RF_sol_common_service_ParentDataCollector", result);
      return result;
    }