docs: public final <I extends AI18nName<?, ?>, T extends AItemSpecifics<?, ?>> void updateForItemSpecificsList(
      final Map<String, Object> pReqVars, final List<T> pOutdGdSpList,
        final SettingsAdd pSettingsAdd, final GoodsInListLuv pGoodsInListLuv,
          final TradingSettings pTradingSettings, final Class<I> pI18nItemClass, final EShopItemType pItemType) throws Exception {
      if (pOutdGdSpList.size() == 0) {
        //Beige ORM may return empty list
        return;
      }
      @SuppressWarnings("unchecked")
      List<IHasIdLongVersionName> itemsForSpecifics = (List<IHasIdLongVersionName>) pReqVars.get("itemsForSpecifics");
      pReqVars.remove("itemsForSpecifics");
      @SuppressWarnings("unchecked")
      Set<Long> htmlTemplatesIds = (Set<Long>) pReqVars.get("htmlTemplatesIds");
      pReqVars.remove("htmlTemplatesIds");
      List<HtmlTemplate> htmlTemplates = null;
      List<ItemInList> itemsInList = null;
      List<I18nChooseableSpecifics> i18nChooseableSpecificsLst = null;
      List<I18nSpecificsOfItemGroup> i18nSpecificsOfItemGroupLst = null;
      List<I18nSpecificsOfItem> i18nSpecificsOfItemLst = null;
      List<I> i18nItemLst = null;
      List<I18nSpecificInList> i18nSpecificInListLst = null;
      List<I18nUnitOfMeasure> i18nUomLst = null;
      try {
        this.srvDatabase.setIsAutocommit(false);
        this.srvDatabase.
          setTransactionIsolation(ISrvDatabase.TRANSACTION_READ_UNCOMMITTED);
        this.srvDatabase.beginTransaction();
        StringBuffer itemsIdsIn = new StringBuffer("(");
        boolean isFirst = true;
        for (IHasIdLongVersionName it : itemsForSpecifics) {
          if (isFirst) {
            isFirst = false;
          } else {
            itemsIdsIn.append(", ");
          }
          itemsIdsIn.append(it.getItsId().toString());
        }
        itemsIdsIn.append(")");
        itemsInList = getSrvOrm().retrieveListWithConditions(pReqVars, ItemInList.class, "where ITSTYPE=" + pItemType.ordinal() + " and ITEMID in " + itemsIdsIn.toString());
        if (htmlTemplatesIds.size() > 0) {
          StringBuffer whereStr = new StringBuffer("where ITSID in (");
          isFirst = true;
          for (Long id : htmlTemplatesIds) {
            if (isFirst) {
              isFirst = false;
            } else {
              whereStr.append(", ");
            }
            whereStr.append(id.toString());
          }
          whereStr.append(")");
          htmlTemplates = getSrvOrm().retrieveListWithConditions(pReqVars, HtmlTemplate.class, whereStr.toString());
        }
        if (pTradingSettings.getUseAdvancedI18n()) {
          i18nItemLst = retrieveI18nItem(pReqVars, pI18nItemClass, itemsIdsIn.toString());
          if (i18nItemLst.size() > 0) {
            i18nSpecificInListLst = getSrvOrm().retrieveListWithConditions(pReqVars, I18nSpecificInList.class, "where ITSTYPE=" + pItemType.ordinal() + " and ITEMID in " + itemsIdsIn.toString());
            StringBuffer specGrIdIn = null;
            StringBuffer specChIdIn = null;
            StringBuffer specIdIn = new StringBuffer("(");
            isFirst = true;
            boolean isFirstGr = true;
            boolean isFirstCh = true;
            for (AItemSpecifics<?, ?> gs : pOutdGdSpList) {
              if (isFirst) {
                isFirst = false;
              } else {
                specIdIn.append(", ");
              }
              specIdIn.append(gs.getSpecifics().getItsId().toString());
              if (gs.getSpecifics().getItsGroop() != null) {
                if (isFirstGr) {
                  specGrIdIn = new StringBuffer("(");
                  isFirstGr = false;
                } else {
                  specGrIdIn.append(", ");
                }
                specGrIdIn.append(gs.getSpecifics().getItsGroop().getItsId().toString());
              }
              if (gs.getSpecifics().getItsType().equals(ESpecificsItemType.CHOOSEABLE_SPECIFICS)) {
                if (isFirstCh) {
                  specChIdIn = new StringBuffer("(");
                  isFirstCh = false;
                } else {
                  specChIdIn.append(", ");
                }
                specChIdIn.append(gs.getLongValue1().toString());
              }
            }
            specIdIn.append(")");
            if (specGrIdIn != null) {
              specGrIdIn.append(")");
            }
            if (specChIdIn != null) {
              specChIdIn.append(")");
            }
            pReqVars.put("I18nSpecificsOfItemhasNamedeepLevel", 1);
            pReqVars.put("I18nSpecificsOfItemlangdeepLevel", 1);
            i18nSpecificsOfItemLst = getSrvOrm().retrieveListWithConditions(pReqVars, I18nSpecificsOfItem.class, "where HASNAME in " + specIdIn.toString());
            pReqVars.remove("I18nSpecificsOfItemhasNamedeepLevel");
            pReqVars.remove("I18nSpecificsOfItemlangdeepLevel");
            pReqVars.put("I18nUnitOfMeasurehasNamedeepLevel", 1);
            pReqVars.put("I18nUnitOfMeasurelangdeepLevel", 1);
            i18nUomLst = getSrvOrm().retrieveList(pReqVars, I18nUnitOfMeasure.class);
            pReqVars.remove("I18nUnitOfMeasurehasNamedeepLevel");
            pReqVars.remove("I18nUnitOfMeasurelangdeepLevel");
            if (specGrIdIn != null) {
              pReqVars.put("I18nSpecificsOfItemGrouphasNamedeepLevel", 1);
              pReqVars.put("I18nSpecificsOfItemGrouplangdeepLevel", 1);
              i18nSpecificsOfItemGroupLst = getSrvOrm().retrieveListWithConditions(pReqVars, I18nSpecificsOfItemGroup.class, "where HASNAME in " + specGrIdIn.toString());
              pReqVars.remove("I18nSpecificsOfItemGrouphasNamedeepLevel");
              pReqVars.remove("I18nSpecificsOfItemGrouplangdeepLevel");
            }
            if (specChIdIn != null) {
              pReqVars.put("I18nChooseableSpecificshasNamedeepLevel", 1);
              pReqVars.put("I18nChooseableSpecificslangdeepLevel", 1);
              i18nChooseableSpecificsLst = getSrvOrm().retrieveListWithConditions(pReqVars, I18nChooseableSpecifics.class, "where HASNAME in " + specChIdIn.toString());
              pReqVars.remove("I18nChooseableSpecificshasNamedeepLevel");
              pReqVars.remove("I18nChooseableSpecificslangdeepLevel");
            }
          }
        }
      } catch (Exception ex) {
        if (!this.srvDatabase.getIsAutocommit()) {
          this.srvDatabase.rollBackTransaction();
        }
        throw ex;
      } finally {
        this.srvDatabase.releaseResources();
      }
      if (htmlTemplates != null && htmlTemplates.size() > 0) {
        for (AItemSpecifics<?, ?> gs : pOutdGdSpList) {
          if (gs.getSpecifics().getTempHtml() != null) {
            gs.getSpecifics().setTempHtml(
            findTemplate(htmlTemplates, gs.getSpecifics().getTempHtml().getItsId()));
          }
          if (gs.getSpecifics().getItsGroop() != null) {
            if (gs.getSpecifics().getItsGroop().getTemplateStart() != null) {
              gs.getSpecifics().getItsGroop().setTemplateStart(findTemplate(htmlTemplates, gs.getSpecifics().getItsGroop().getTemplateStart().getItsId()));
            }
            if (gs.getSpecifics().getItsGroop().getTemplateEnd() != null) {
              gs.getSpecifics().getItsGroop().setTemplateEnd(findTemplate(htmlTemplates, gs.getSpecifics().getItsGroop().getTemplateEnd().getItsId()));
            }
            if (gs.getSpecifics().getItsGroop().getTemplateStart() != null) {
              gs.getSpecifics().getItsGroop().setTemplateDetail(findTemplate(htmlTemplates, gs.getSpecifics().getItsGroop().getTemplateDetail().getItsId()));
            }
          }
        }
      }
      int steps = itemsForSpecifics.size() / pSettingsAdd.getRecordsPerTransaction();
      int currentStep = 1;
      Long lastUpdatedVersion = null;
      do {
        try {
          this.srvDatabase.setIsAutocommit(false);
          this.srvDatabase.setTransactionIsolation(ISrvDatabase.TRANSACTION_READ_UNCOMMITTED);
          this.srvDatabase.beginTransaction();
          int stepLen = Math.min(itemsForSpecifics.size(), currentStep * pSettingsAdd.getRecordsPerTransaction());
          for (int i = (currentStep - 1) * pSettingsAdd.getRecordsPerTransaction(); i < stepLen; i++) {
            IHasIdLongVersionName item = itemsForSpecifics.get(i);
            ItemInList itemInList = findItemInListFor(itemsInList, item.getItsId(), pItemType);
            if (itemInList == null) {
              itemInList = createItemInList(pReqVars, item);
            }
            int j = findFirstIdxFor(pOutdGdSpList, item);
            SpecificsOfItemGroup specificsOfItemGroupWas = null;
            //reset any way:
            itemInList.setItsName(item.getItsName());
            itemInList.setDetailsMethod(null);
            itemInList.setImageUrl(null);
            //i18n:
            List<I18nSpecificInList> i18nSpInLsLstFg = null;
            if (i18nItemLst != null) {
              for (I i18nItem : i18nItemLst) {
                if (i18nSpInLsLstFg == null) {
                  i18nSpInLsLstFg = new ArrayList<I18nSpecificInList>();
                }
                if (i18nItem.getHasName().getItsId().equals(item.getItsId())) {
                  I18nSpecificInList i18nspInLs = findI18nSpecificInListFor(i18nSpecificInListLst, item, pItemType, i18nItem.getLang());
                  if (i18nspInLs == null) {
                    i18nspInLs = new I18nSpecificInList();
                    i18nspInLs.setIsNew(true);
                    i18nspInLs.setItsType(pItemType);
                    i18nspInLs.setItemId(item.getItsId());
                    i18nspInLs.setLang(i18nItem.getLang());
                  }
                  i18nspInLs.setItsName(i18nItem.getItsName());
                  i18nSpInLsLstFg.add(i18nspInLs);
                }
              }
            }
            if (pSettingsAdd.getSpecHtmlStart() !=  null) {
              itemInList.setSpecificInList(pSettingsAdd.getSpecHtmlStart());
              if (i18nSpInLsLstFg != null) {
                for (I18nSpecificInList i18nspInLs : i18nSpInLsLstFg) {
                  i18nspInLs.setSpecificInList(pSettingsAdd.getSpecHtmlStart());
                }
              }
            } else {
              itemInList.setSpecificInList("");
              if (i18nSpInLsLstFg != null) {
                for (I18nSpecificInList i18nspInLs : i18nSpInLsLstFg) {
                  i18nspInLs.setSpecificInList("");
                }
              }
            }
            boolean wasGrStart = false;
            do {
              if (pOutdGdSpList.get(j).getSpecifics().getIsShowInList()) {
                if (pOutdGdSpList.get(j).getSpecifics().getItsType().equals(ESpecificsItemType.IMAGE)) {
                  itemInList.setImageUrl(pOutdGdSpList.get(j).getStringValue1());
                } else { // build ItemInList.specificInList:
                  if (pOutdGdSpList.get(j).getSpecifics().getItsGroop() == null || specificsOfItemGroupWas == null
                        || !pOutdGdSpList.get(j).getSpecifics().getItsGroop().getItsId().equals(specificsOfItemGroupWas.getItsId())) {
                    if (wasGrStart) {
                      if (pSettingsAdd.getSpecGrSeparator() != null && pSettingsAdd.getSpecGrHtmlEnd() != null) {
                        itemInList.setSpecificInList(itemInList.getSpecificInList() + pSettingsAdd.getSpecGrHtmlEnd() + pSettingsAdd.getSpecGrSeparator());
                      } else if (pSettingsAdd.getSpecGrHtmlEnd() != null) {
                        itemInList.setSpecificInList(itemInList.getSpecificInList() + pSettingsAdd.getSpecGrHtmlEnd());
                      } else if (pSettingsAdd.getSpecGrSeparator() != null) {
                        itemInList.setSpecificInList(itemInList.getSpecificInList() + pSettingsAdd.getSpecGrSeparator());
                      }
                    }
                    wasGrStart = true;
                    if (pSettingsAdd.getSpecGrHtmlStart() != null) {
                      itemInList.setSpecificInList(itemInList.getSpecificInList() + pSettingsAdd.getSpecGrHtmlStart());
                      if (i18nSpInLsLstFg != null) {
                        for (I18nSpecificInList i18nspInLs : i18nSpInLsLstFg) {
                          i18nspInLs.setSpecificInList(i18nspInLs.getSpecificInList() + pSettingsAdd.getSpecGrHtmlStart());
                        }
                      }
                    }
                    if (pOutdGdSpList.get(j).getSpecifics().getItsGroop() != null && pOutdGdSpList.get(j).getSpecifics().getItsGroop().getTemplateStart() != null) {
                      String grst = pOutdGdSpList.get(j).getSpecifics().getItsGroop().getTemplateStart()
                        .getHtmlTemplate().replace(":SPECGRNM", pOutdGdSpList.get(j).getSpecifics().getItsGroop().getItsName());
                      itemInList.setSpecificInList(itemInList.getSpecificInList() + grst);
                      if (i18nSpInLsLstFg != null) {
                        for (I18nSpecificInList i18nspInLs : i18nSpInLsLstFg) {
                          String gn = findI18nSpecGrName(i18nSpecificsOfItemGroupLst, pOutdGdSpList.get(j).getSpecifics().getItsGroop(), i18nspInLs.getLang());
                          grst = pOutdGdSpList.get(j).getSpecifics().getItsGroop().getTemplateStart()
                            .getHtmlTemplate().replace(":SPECGRNM", gn);
                          i18nspInLs.setSpecificInList(i18nspInLs.getSpecificInList() + grst);
                        }
                      }
                    }
                  }
                  updateGoodsSpecificsInList(pReqVars, pSettingsAdd, pOutdGdSpList.get(j), itemInList, specificsOfItemGroupWas, i18nSpInLsLstFg, i18nSpecificsOfItemLst, i18nChooseableSpecificsLst, i18nUomLst);
                  specificsOfItemGroupWas = pOutdGdSpList.get(j).getSpecifics().getItsGroop();
                }
              } else {
                itemInList.setDetailsMethod(1);
              }
              j++;
            } while (j < pOutdGdSpList.size() && pOutdGdSpList.get(j).getItem().getItsId().equals(item.getItsId()));
            if (pSettingsAdd.getSpecGrHtmlEnd() != null) {
              itemInList.setSpecificInList(itemInList.getSpecificInList() + pSettingsAdd.getSpecGrHtmlEnd());
              if (i18nSpInLsLstFg != null) {
                for (I18nSpecificInList i18nspInLs : i18nSpInLsLstFg) {
                  i18nspInLs.setSpecificInList(i18nspInLs.getSpecificInList() + pSettingsAdd.getSpecGrHtmlEnd());
                }
              }
            }
            if (pSettingsAdd.getSpecHtmlEnd() != null) {
              itemInList.setSpecificInList(itemInList.getSpecificInList() + pSettingsAdd.getSpecHtmlEnd());
              if (i18nSpInLsLstFg != null) {
                for (I18nSpecificInList i18nspInLs : i18nSpInLsLstFg) {
                  i18nspInLs.setSpecificInList(i18nspInLs.getSpecificInList() + pSettingsAdd.getSpecHtmlEnd());
                }
              }
            }
            if (itemInList.getIsNew()) {
              getSrvOrm().insertEntity(pReqVars, itemInList);
            } else {
              getSrvOrm().updateEntity(pReqVars, itemInList);
            }
            if (i18nSpInLsLstFg != null) {
              for (I18nSpecificInList i18nspInLs : i18nSpInLsLstFg) {
                if (i18nspInLs.getIsNew()) {
                  getSrvOrm().insertEntity(pReqVars, i18nspInLs);
                } else {
                  getSrvOrm().updateEntity(pReqVars, i18nspInLs);
                }
              }
            }
            //item holds item-specifics version
            lastUpdatedVersion = item.getItsVersion();
          }
          if (pItemType.equals(EShopItemType.GOODS)) {
            pGoodsInListLuv.setGoodsSpecificLuv(lastUpdatedVersion);
          } else if (pItemType.equals(EShopItemType.SERVICE)) {
            pGoodsInListLuv.setServiceSpecificLuv(lastUpdatedVersion);
          } else if (pItemType.equals(EShopItemType.SEGOODS)) {
            pGoodsInListLuv.setSeGoodSpecificLuv(lastUpdatedVersion);
          } else if (pItemType.equals(EShopItemType.SESERVICE)) {
            pGoodsInListLuv.setSeServiceSpecificLuv(lastUpdatedVersion);
          } else {
            throw new Exception("NYI for " + pItemType);
          }
          getSrvOrm().updateEntity(pReqVars, pGoodsInListLuv);
          this.srvDatabase.commitTransaction();
        } catch (Exception ex) {
          if (!this.srvDatabase.getIsAutocommit()) {
            this.srvDatabase.rollBackTransaction();
          }
          throw ex;
        } finally {
          this.srvDatabase.releaseResources();
        }
      } while (currentStep++ < steps);
    }