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

    //@include lib_Class.js
    //@include lib_sol.common.ObjectUtils.js
    //@include lib_sol.common.ObjectFormatter.js
    //@include lib_sol.common.RepoUtils.js
    //@include sol.common.ix.services.ChildrenDataCollector.js

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

    /**
     * Collects all child sords for a given parent with all objKeys, all mapFields and the maskFieldnames of all objKeys.
     * # Example
     *
     *     var result = sol.common.IxUtils.execute("RF_sol_common_services_ChildrenDataWithMaps", {
     *        "parentId": "ARCPATH[(E10E1000-E100-E100-E100-E10E10E10E00)]:/Business Solutions/common/Configuration",
     *        "sordKeys": ["name", "id", "maskName", "guid", "parentId", "type", "desc"]
     *     });
     *
     * # Result
     * {
     *   "sord": {
     *      "name": "Configuration",
     *      "id": "1838",
     *      "maskName": "Folder",
     *      "guid": "(5EE11DB8-CBE5-F0F6-4C8C-F9D292AEDD79)",
     *      "parentId": "1788",
     *      "type": "47",
     *      "desc": ""
     *    },
     *    "sords": [
     *      {
     *        "name": "as.config",
     *        "id": "1841",
     *        "maskName": "ELO Business Solution Configuration",
     *        "guid": "(89A52C86-6DF6-4EB6-1A7A-F9E84A016C0D)",
     *        "parentId": "1838",
     *        "type": "254",
     *        "desc": "",
     *        "mapKeys": {},
     *        "objKeys": {
     *          "BS_CONFIG_NAME": "ELO AS settings",
     *          "BS_CONFIG_VERSION": "1.0",
     *          "BS_CONFIG_TYPE": "",
     *          "SOL_TYPE": "",
     *          "ELO_FNAME": "as.config.json"
     *        }
     *      },
     *      {
     *         ...
     *      }
     *    ],
     *    "masks": {
     *      "ELO Business Solution Configuration": {
     *        "fields": {
     *          "BS_CONFIG_NAME": {
     *            "name": "Name",
     *            "type": "TEXT"
     *          },
     *          "BS_CONFIG_VERSION": {
     *            "name": "Version",
     *            "type": "TEXT"
     *          },
     *          "BS_CONFIG_TYPE": {
     *            "name": "Type",
     *            "type": "TEXT"
     *          },
     *          "SOL_TYPE": {
     *            "name": "Solution object type",
     *            "type": "TEXT"
     *          }
     *        }
     *      }
     *    }
     *  }
     */

    sol.define("sol.common.ix.services.ChildrenDataWithMaps", {
      extend: "sol.common.ix.ServiceBase",

      collectorVersion: "1.00.000",

      /**
       * @property {Number} totalCount
       * The search is terminated if this number of objects is found. If the number of results should not be constrained,
       * set this value to 232-1 = 2147483647 (maximum value of a positive 32bit integer minus 1).
       *
       * Please note that collecting huge amounts of data might lead to performance issues.
       */
      totalCount: 10000,

      /**
       * @cfg {Array} sordKeys
       * List of required sord keys.
       *
       * This only returns the given sord keys. This is required in order to limit traffic for not required keys.
       *
       *     sordKeys: ["id", "guid", "name", "desc"],
       */
      sordKeys: ["id", "guid", "name", "desc"],

      docMasks: {},

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

        me.getTypeConstants();
        if (me.maskNames && me.maskNames.length > 0) {
          for (i = 0; i < me.maskNames.length; i++) {
            me.addDocMaskData(me.maskNames[i]);
          }
        }
        var result = me.collectChildren();

        return result;
      },

      /**
       * @private
       * helpers for collectChildren
       */
      getSord: function (objId) {

        try {
          return ixConnect.ix().checkoutSord(objId, SordC.mbAll, LockC.NO);
        } catch (e) {
          throw "ChildrenDataWithMaps: could not checkout sord with objId/guid `" + objId + "`";
        }
        return null;
      },

      /**
       * @private
       * helpers for collectChildren
       */
      addMapKeys: function (resultObj) {
        var me = this;

        return (resultObj.sords || [])
          .map(function (formattedSord) {
            var result = sol.common.ObjectFormatter.format({
              sord: {
                formatter: 'sol.common.ObjectFormatter.TemplateSord',
                data: me.getSord(formattedSord.id),
                config: {
                  allMapFields: true,
                  allObjKeys: true
                }
              }
            });

            formattedSord.mapKeys = (result || {sord: {}}).sord.mapKeys;
            formattedSord.objKeys = (result || { sord: {} }).sord.objKeys;
            if (!me.docMasks[result.sord.maskName]) {
              me.addDocMaskData(result.sord.maskName);
            }
            return formattedSord;
          });
      },

      /**
       * @private
       */
      collectChildren: function () {
        var me = this,
            tmpConfig, jsonDataCollector, resultString, result, resultObj;

        tmpConfig = { ec: me.ec, user: me.user, parentId: me.parentId, sordKeys: me.sordKeys };

        jsonDataCollector = sol.create("sol.common.ix.services.ChildrenDataCollector", tmpConfig);

        resultString = jsonDataCollector.execute();
        resultObj = JSON.parse(resultString);

        result = { sord: resultObj.sord, sords: me.addMapKeys(resultObj), masks: me.docMasks };

        return JSON.stringify(result);
      },

      /**
       * @private
       * Adds document mask data
       * @param {String} maskName
       * @return {Object}
       */
       addDocMaskData: function (maskName) {
        var me = this;
        if (!me.docMasks[maskName]) {
          me.docMasks[maskName] = me.buildDocMaskData(maskName);
        }
        return me.docMasks[maskName];
      },

      /**
       * @private
       * Builds the document mask data
       * @param {String} docMaskName Document mask name
       * @return {Object}
       */
      buildDocMaskData: function (docMaskName) {
        var me = this,
            docMask, docMaskData;

        docMaskData = { fields: {} };

        try {
          docMask = sol.common.SordUtils.getDocMask(docMaskName, me.ec.ci.language);
          docMask.lines.forEach(function (docMaskLine) {
            docMaskData.fields[docMaskLine.key] = { name: String(docMaskLine.name), type: me.docMaskLineTypes[docMaskLine.type] };
          });
        } catch (ex) {
          logger.warn(["Can't get mask info: mask={0}, ec.ci.language={1}, exception={2}", docMaskName, me.ec.ci.language, ex]);
        }

        return docMaskData;
      },

      /**
       * @private
       */
      getTypeConstants: function () {
        var me = this,
            i, field, docMaskLineC, fields;
        me.docMaskLineTypes = {};
        docMaskLineC = new DocMaskLineC();
        fields = docMaskLineC.class.declaredFields;
        for (i = 0; i < fields.length; i++) {
          field = fields[i];
          field.accessible = true;
          if (field.name.startsWith("TYPE_")) {
            me.docMaskLineTypes[String(field.getInt(docMaskLineC))] = String(field.name.substring(5));
          }
        }
      }

    });

    /**
     * @member sol.common.ix.services.ChildrenDataWithMaps
     * @method RF_sol_common_services_ChildrenDataWithMaps
     * @static
     * @inheritdoc sol.common.ix.ServiceBase#RF_ServiceBaseName
     */
    function RF_sol_common_services_ChildrenDataWithMaps(ec, configAny) {
      var config, jsonDataCollector, ecLang, ixConnectLang, result;

      ecLang = String(ec.ci.language);
      ixConnectLang = String(ixConnect.loginResult.clientInfo.language);

      config = sol.common.ix.RfUtils.parseAndCheckParams(ec, arguments.callee.name, configAny),
      config.ec = ec;

      log.info("ec.ci.language=" + ecLang);
      log.info("ixConnect.loginResult.clientInfo.language=" + ixConnectLang);

      jsonDataCollector = sol.create("sol.common.ix.services.ChildrenDataWithMaps", config);
      result = jsonDataCollector.execute();
      return result;
    }