    //@include lib_Class.js

    /**
     * Rendering Word file from a Word template.
     *
     * This can either be used for creating a new Document in the archive (`objId` specified) or can create a new version on an existing object (`parentId`).
     *
     * @author PZ, ELO Digital Office GmbH
     * @version 1.0
     *
     * @eloas
     * @requires sol.common.RepoUtils
     * @requires sol.common.Template
     */
    sol.define("sol.common.as.renderer.Word", {

      requiredConfig: ["templateId"],

      /**
       * @cfg {String} templateId (reqiured)
       * The template which should be rendered
       */

      /**
       * @cfg {String} targetId (optional)
       * The target folder to store the rendered document
       */

      /**
       * @cfg {String} objId (optional)
       * The rendered document will be saved as a version of this object
       * Either `targetId` or `objId` has to be defined.
       */

      /**
       * @cfg {Boolean} copyMetaData (optional)
       * If `true`, the mask and the metadata of the template will be copied to the new document
       */

      /**
       * @cfg {Boolean} [fillContentControls=true] (optional)
       * If `true`, the content controls will be filled.
       */

      /**
       * @cfg {String} partIdsFromMapTableKey (optional)
       * Map field name key from which the part IDs are read, e.g. `CLAUSE_ID`
       */

      /**
       * @cfg {String} searchPartIdFieldName (optional)
       * Part ID field name to find the requested part
       */

      initialize: function (config) {
        var me = this;
        me.$super("sol.Base", "initialize", [config]);
        if (!me.saveToStream && !me.objId && !me.targetId) {
          throw "IllegalArgumentException: either 'saveToStream', 'targetId' or 'objId' has to defined";
        }
      },

      render: function (name, data) {
        var me = this,
            config = {},
            templateSord;

        if (me.objId) {
          config.objId = me.objId;
        } else {
          config.name = name;
          config.parentId = me.targetId;
        }

        if (typeof me.fillContentControls == "string") {
          me.fillContentControls = (me.fillContentControls === "true");
        }

        config.fillContentControls = typeof me.fillContentControls == "undefined" ? true : me.fillContentControls;

        if (typeof me.updateParts == "string") {
          me.updateParts = (me.updateParts === "true");
          config.updateParts = me.updateParts;
        }

        if (me.editParts) {
          config.editParts = me.editParts;
          config.partIdsFromMapTableKey = me.partIdsFromMapTableKey;
          config.searchPartIdFieldName = me.searchPartIdFieldName;
          config.partIds = me.getPartIds(me.partIdsFromMapTableKey);
          me.writePartIds(me.objId, me.partIdsTargetFieldName, config.partIds);
        }

        if (me.updateParts) {
          config.updateParts = me.updateParts;
          config.searchPartIdFieldName = me.searchPartIdFieldName;
        }

        if (me.saveToStream) {
          config.saveToStream = me.saveToStream;
        }

        config.format = me.format || "docx";
        if (me.copyMetaData === true) {
          templateSord = ixConnect.ix().checkoutSord(me.templateId, SordC.mbAllIndex, LockC.NO);
          config.maskId = templateSord.mask;
          config.objKeysObj = sol.common.SordUtils.getTemplateSord(templateSord).sord.objKeys;
        }

        return me.renderWord(data, config);
      },

      /**
       * @private
       * @param {Object} data
       * @param {Object} config
       * @return {Object}
       */
      renderWord: function (data, config) {
        var me = this,
            result = {},
            wordDocument;

        me.logger.info(["Render Word: editParts={0}({1}), fillContentControls={2}({3}), updateParts={4}({5})", config.editParts, typeof config.editParts, config.fillContentControls,
          typeof config.fillContentControls, config.updateParts, typeof config.updateParts]);

        try {
          wordDocument = sol.create("sol.common.as.WordDocument", {});
          wordDocument.openFromRepo({ objId: me.templateId });

          if (config.fillContentControls) {
            wordDocument.fillContentControls(data);
          }

          config.partsConfig = config.partsConfig || {};

          if (config.editParts) {
            wordDocument.editParts(config.partIds, { searchPartIdFieldName: config.searchPartIdFieldName });
          }

          if (config.updateParts) {
            wordDocument.updateParts();
          }

          if (config.saveToStream) {
            result.inputStream = wordDocument.saveToStream(config);
          }

          if (config.objId || config.parentId) {
            result.objId = wordDocument.saveToRepo(config);
          }
        } catch (ex) {
          me.logger.error(["error rendering report '{0}' (templateId='{1}')", config.name, me.templateId], ex);
        }

        return result;
      },

      getPartIds: function (partIdsFromMapTableKey) {
        var me = this,
            partIds = [],
            sordMap, sordMapTable, partId;

        me.logger.info(["getPartIds: objId={0}, mapKey={1}", me.objId, partIdsFromMapTableKey]);

        sordMap = sol.create("sol.common.SordMap", { objId: me.objId });
        sordMapTable = sol.create("sol.common.MapTable", { map: sordMap, columnNames: [partIdsFromMapTableKey] });
        while (sordMapTable.hasNextRow()) {
          sordMapTable.nextRow();
          partId = sordMapTable.getValue(partIdsFromMapTableKey);
          partIds.push(partId);
        }

        me.logger.info(["getPartIds: partIds={0}", partIds]);

        return partIds;
      },

      writePartIds: function (objId, partIdsTargetFieldName, partIds) {
        var me = this,
            sord;

        if (!partIdsTargetFieldName) {
          return;
        }

        me.logger.info(["writePartIds: objId={0}, fieldName={1}, partIds={2}", objId, partIdsTargetFieldName, partIds]);

        sord = ixConnect.ix().checkoutSord(objId, SordC.mbAllIndex, LockC.NO);
        sol.common.SordUtils.setObjKeyValues(sord, partIdsTargetFieldName, partIds);
        ixConnect.ix().checkinSord(sord, SordC.mbAllIndex, LockC.NO);
      }
    });