Загрузка данных
package com.efs.generator;
import java.util;
import java.util.*;
import java.util.Map.Entry;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.efs.generator.model.ProfileEntry;
import com.efs.generator.model.LastProfileData;
import com.efs.generator.model.CsvRow;
import com.efs.generator.util.UriNormalizer;
import com.efs.generator.util.MethodExtractor;
@Service
public class CsvGeneratorService {
private static final Logger log = LoggerFactory.getLogger(CsvGeneratorService.class);
private static final int DEFAULT_SLA = 0;
private final UriNormalizer uriNormalizer;
private final MethodExtractor methodExtractor;
public CsvGeneratorService(UriNormalizer uriNormalizer, MethodExtractor methodExtractor) {
this.uriNormalizer = uriNormalizer;
this.methodExtractor = methodExtractor;
}
public void generateProfile(List<ProfileEntry> scriptEntries,
List<ProfileEntry> profileEntries,
String projectType,
String urlPrefix,
String requirement,
Map<String, LastProfileData> lastProfileData,
List<CsvRow> allRowsForExcel) {
Map<String, List<String>> normalizedUrlToOpIds = new HashMap<>();
Set<String> matchedOpIds = new HashSet<>();
Set<String> usedOpIds = new HashSet<>();
int matchedCount = 0;
int newCount = 0;
int nextUcNum = 1;
int validProfileEntriesCount = 0;
// Build normalized URL -> operation IDs map from script entries
for (ProfileEntry entry : scriptEntries) {
String normalizedUri = uriNormalizer.normalizeUri(entry.getUri(), projectType);
List<String> opIds = normalizedUrlToOpIds.computeIfAbsent(normalizedUri, k -> new ArrayList<>());
String opId = generateNewOperationId(entry, usedOpIds, nextUcNum);
opIds.add(opId);
usedOpIds.add(opId);
nextUcNum = extractUcNumber(opId) + 1;
}
log.debug("--- Обработка операций из профиля аналитика ---");
for (ProfileEntry entry : profileEntries) {
log.debug(" Обработка entry: метод={}, uri={}, интенсивность={}", entry.getMethod(), entry.getUri(), entry.getIntensity());
if (entry.getIntensity() > 0) {
validProfileEntriesCount++;
} else {
log.info(" Операция с нулевой интенсивностью: {} {} - будет покрашена красным в Excel",
entry.getMethod(), entry.getUri());
}
String operationId = null;
String profileMethod = entry.getMethod();
String normalizedUri = uriNormalizer.normalizeUri(entry.getUri(), projectType);
if (normalizedUrlToOpIds.containsKey(normalizedUri)) {
List<String> opIds = normalizedUrlToOpIds.get(normalizedUri);
for (String opId : opIds) {
if (!matchedOpIds.contains(opId)) {
String opMethod = extractMethodFromOperationId(opId);
if (opMethod.equals(profileMethod)) {
operationId = opId;
matchedOpIds.add(opId);
break;
}
}
}
if (operationId == null) {
for (String opId : opIds) {
if (!matchedOpIds.contains(opId)) {
operationId = opId;
matchedOpIds.add(opId);
if (entry.getIntensity() > 0) {
log.warn(" Метод не совпадает! Профиль: {}, operationId: {} (URI: {})",
profileMethod, opId, entry.getUri());
}
break;
}
}
}
if (operationId != null) {
if (entry.getIntensity() > 0) {
if (opIds.size() > 1) {
log.debug(" Найден в скрипте (один из {}): {} {} → {} (инт: {})",
opIds.size(), profileMethod, entry.getUri(), operationId, entry.getIntensity());
} else {
log.debug(" Найден в скрипте: {} {} → {} (инт: {})",
profileMethod, entry.getUri(), operationId, entry.getIntensity());
}
matchedCount++;
}
} else {
if (entry.getIntensity() > 0) {
log.warn(" Все operation_id для URI {} уже использованы. Создаём новый.", entry.getUri());
}
operationId = generateNewOperationId(entry, usedOpIds, nextUcNum);
nextUcNum = extractUcNumber(operationId) + 1;
usedOpIds.add(operationId);
if (entry.getIntensity() > 0) {
newCount++;
}
}
} else {
operationId = generateNewOperationId(entry, usedOpIds, nextUcNum);
nextUcNum = extractUcNumber(operationId) + 1;
usedOpIds.add(operationId);
if (entry.getIntensity() > 0) {
log.info(" Создан новый: {} {} → {} (инт: {})",
profileMethod, entry.getUri(), operationId, entry.getIntensity());
newCount++;
} else {
log.info(" Создан ID для нулевой операции: {} {} → {} (инт: 0)",
profileMethod, entry.getUri(), operationId);
}
}
int sla = DEFAULT_SLA;
if (lastProfileData.containsKey(operationId)) {
sla = lastProfileData.get(operationId).getSla();
}
String fullUri;
String uriFromProfile = entry.getUri();
if ("PPRB".equals(projectType)) {
// Для PPRB не добавляем префикс и не меняем URI
fullUri = uriFromProfile;
} else if (uriFromProfile.startsWith("/ic/ufs/corp-retail/")) {
// Для WEB: уже содержит префикс, не добавляем urlPrefix
fullUri = uriFromProfile;
} else if (uriFromProfile.startsWith("/ic/ufs/mobile/")) {
// Убираем ведущий "/ic" для мобильного пути
String withoutIC = uriFromProfile.substring(3); // remove leading "/ic"
// После удаления, строка начинается с "/ufs/mobile/..."
if (withoutIC.startsWith("/ufs/mobile/")) {
// Уже содержит базовый путь, не добавляем urlPrefix
fullUri = withoutIC;
} else {
// На всякий случай, если после удаления не совпадает (не должно случиться)
fullUri = urlPrefix + withoutIC;
}
} else if (uriFromProfile.startsWith("/ufs/mobile/")) {
// Для мобильного: уже содержит базовый путь
fullUri = uriFromProfile;
} else if (uriFromProfile.startsWith("/")) {
// Относительный путь к корню сайта
fullUri = urlPrefix + uriFromProfile;
} else {
// Относительный путь без ведущего слеша
fullUri = urlPrefix + "/" + uriFromProfile;
}
CsvRow row = new CsvRow(
operationId,
fullUri,
entry.getMethod(),
entry.getIntensity(), // может быть 0
sla,
operationId,
requirement,
""
);
// ИЗМЕНЕНО: добавляем ВСЕ операции в список для Excel
allRowsForExcel.add(row);
}
log.debug("--- Итого ---");
log.debug(" Скрипт операций: {}", scriptEntries.size());
log.debug(" Профиль аналитика: {}", profileEntries.size());
log.debug(" Сопоставлено: {}", matchedCount);
log.debug(" Новых: {}", newCount);
log.debug(" Всего в результирующем профиле: {}", (matchedCount + newCount));
}
private String generateNewOperationId(ProfileEntry entry, Set<String> usedOpIds, int nextUcNum) {
String base = "UC" + String.format("%03d", nextUcNum) + "_" + entry.getMethod() + "_" + entry.getUri().replaceAll("[^a-zA-Z0-9]", "_").toUpperCase();
String opId = base;
int counter = 0;
while (usedOpIds.contains(opId)) {
counter++;
opId = base + "_" + counter;
}
return opId;
}
private String extractMethodFromOperationId(String opId) {
// Example: UC114_POST_business_analytics_industry_top_avgcheck_WEB
// We need to extract the method part between first and second underscore after UCxxx_
// Format: UCxxx_METHOD_REST
// We'll split by '_'
String[] parts = opId.split("_");
if (parts.length >= 3) {
// parts[0] = UCxxx, parts[1] = method, rest = rest
return parts[1];
}
// fallback: return empty
return "";
}
private int extractUcNumber(String opId) {
// Extract the numeric part after UC
// opId format: UCxxx_...
if (opId.startsWith("UC") && opId.length() >= 5) {
String numPart = opId.substring(2, 5); // assuming three digits
try {
return Integer.parseInt(numPart);
} catch (NumberFormatException e) {
return 0;
}
}
return 0;
}
}