Skip to content

Commit ada1d10

Browse files
authored
Оптимизировано чтение и хранение информации о поддержке (#108)
оптимизировано чтение и хранение информации о поддержке
1 parent 370cabf commit ada1d10

File tree

8 files changed

+488
-189
lines changed

8 files changed

+488
-189
lines changed

build.gradle.kts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ gitVersioning.apply {
4444
repositories {
4545
mavenLocal()
4646
mavenCentral()
47+
maven("https://central.sonatype.com/repository/maven-snapshots")
4748
}
4849

4950
dependencies {
@@ -52,7 +53,7 @@ dependencies {
5253

5354
// прочее
5455
implementation("commons-io", "commons-io", "2.18.0")
55-
api("io.github.1c-syntax", "bsl-common-library", "0.8.1")
56+
api("io.github.1c-syntax", "bsl-common-library", "0.9.0.18-SNAPSHOT")
5657

5758
// тестирование
5859
testImplementation("org.junit.jupiter", "junit-jupiter-api", "5.11.4")
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/*
2+
* This file is a part of Support Configuration.
3+
*
4+
* Copyright (c) 2019 - 2025
5+
* Tymko Oleg <[email protected]>, Maximov Valery <[email protected]> and contributors
6+
*
7+
* SPDX-License-Identifier: LGPL-3.0-or-later
8+
*
9+
* Support Configuration is free software; you can redistribute it and/or
10+
* modify it under the terms of the GNU Lesser General Public
11+
* License as published by the Free Software Foundation; either
12+
* version 3.0 of the License, or (at your option) any later version.
13+
*
14+
* Support Configuration is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17+
* Lesser General Public License for more details.
18+
*
19+
* You should have received a copy of the GNU Lesser General Public
20+
* License along with Support Configuration.
21+
*/
22+
package com.github._1c_syntax.bsl.supconf;
23+
24+
import com.github._1c_syntax.bsl.support.SupportVariant;
25+
import lombok.Getter;
26+
import lombok.extern.slf4j.Slf4j;
27+
28+
import java.io.FileNotFoundException;
29+
import java.nio.file.Path;
30+
import java.util.Collections;
31+
import java.util.Map;
32+
33+
/**
34+
* Содержимое настроек поставки конфигурации поставщика.
35+
* Предоставляет возможность получить варианты поддержки для каждой конфигурации поставщика
36+
*/
37+
@Slf4j
38+
public final class FullSupportData {
39+
/**
40+
* Путь к файлу описания поставки
41+
*/
42+
@Getter
43+
private final Path pathParentConfigurationBin;
44+
45+
/**
46+
* Прочитанная информация о настройка поставки
47+
*/
48+
@Getter
49+
private final Map<String, Map<SupportConfiguration, SupportVariant>> supportVariants;
50+
51+
private FullSupportData(Path pathParentConfigurationBin) {
52+
this(pathParentConfigurationBin, Collections.emptyMap());
53+
}
54+
55+
private FullSupportData(Path pathParentConfigurationBin, Map<String, Map<SupportConfiguration, SupportVariant>> supportVariants) {
56+
this.supportVariants = supportVariants;
57+
this.pathParentConfigurationBin = pathParentConfigurationBin;
58+
}
59+
60+
/**
61+
* Читает данные настроек поставки по переданному файлу
62+
*
63+
* @param pathParentConfigurationBin Путь к файлу описания поставки
64+
* @return Прочитанные данные
65+
*/
66+
public static FullSupportData create(Path pathParentConfigurationBin) {
67+
Map<String, Map<SupportConfiguration, SupportVariant>> supportVariants;
68+
try {
69+
supportVariants = SupportDataReader.readFull(pathParentConfigurationBin);
70+
} catch (NumberFormatException | FileNotFoundException exception) {
71+
LOGGER.error("Ошибка чтения файла {}", pathParentConfigurationBin);
72+
LOGGER.debug("TRACE", exception);
73+
supportVariants = Collections.emptyMap();
74+
}
75+
76+
if (supportVariants.isEmpty()) {
77+
return new FullSupportData(pathParentConfigurationBin);
78+
} else {
79+
return new FullSupportData(pathParentConfigurationBin, supportVariants);
80+
}
81+
}
82+
83+
/**
84+
* Возвращает варианты поддержки для указанного идентификатора объекта для всех конфигураций поставщика.
85+
* Если значения нет, то вернет пустую коллекцию
86+
*
87+
* @param uid Идентификатор объекта
88+
* @return Значение варианта поддержки
89+
*/
90+
public Map<SupportConfiguration, SupportVariant> get(String uid) {
91+
if (uid.isBlank() || supportVariants.isEmpty()) {
92+
return Collections.emptyMap();
93+
}
94+
var configurations = supportVariants.get(uid);
95+
if (configurations == null || configurations.isEmpty()) {
96+
return Collections.emptyMap();
97+
}
98+
return Map.copyOf(configurations);
99+
}
100+
101+
/**
102+
* Возвращает значение о варианте поддержке для указанного идентификатора объекта и конфигурации поставщика
103+
* Если значения нет, то вернет SupportVariant.NONE
104+
*
105+
* @param uid Идентификатор объекта
106+
* @param configuration Конфигурация поставщика
107+
* @return Значение варианта поддержки
108+
*/
109+
public SupportVariant get(String uid, SupportConfiguration configuration) {
110+
if (uid.isBlank() || supportVariants.isEmpty()) {
111+
return SupportVariant.NONE;
112+
}
113+
return supportVariants.getOrDefault(uid, Collections.emptyMap()).getOrDefault(configuration, SupportVariant.NONE);
114+
}
115+
}

src/main/java/com/github/_1c_syntax/bsl/supconf/ParseSupportData.java

Lines changed: 35 additions & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -26,184 +26,74 @@
2626
import lombok.extern.slf4j.Slf4j;
2727
import org.apache.commons.io.FilenameUtils;
2828

29-
import java.io.FileInputStream;
30-
import java.io.FileNotFoundException;
31-
import java.nio.charset.StandardCharsets;
3229
import java.nio.file.Path;
3330
import java.nio.file.Paths;
34-
import java.util.Collections;
35-
import java.util.HashMap;
31+
import java.util.Comparator;
3632
import java.util.Map;
37-
import java.util.Scanner;
3833
import java.util.concurrent.ConcurrentHashMap;
39-
import java.util.regex.Pattern;
4034

4135
/**
4236
* Используется для чтения информации о поддержке из файла ParentConfigurations.bin конфигурации
4337
*/
4438
@Slf4j
4539
@UtilityClass
4640
public class ParseSupportData {
47-
48-
// взято из https://stackoverflow.com/questions/18144431/regex-to-split-a-csv
49-
private static final String REGEX = "(?:,[\\n\\r]*|\\n|^)(\"(?:(?:\"\")*[^\"]*)*\"|[^\",\\n]*|(?:\\n|$))"; // NOSONAR
50-
private static final Pattern patternSplit = Pattern.compile(REGEX);
51-
52-
private static final int POINT_COUNT_CONFIGURATION = 2;
53-
private static final int SHIFT_CONFIGURATION_VERSION = 3;
54-
private static final int SHIFT_CONFIGURATION_PRODUCER = 4;
55-
private static final int SHIFT_CONFIGURATION_NAME = 5;
56-
private static final int SHIFT_CONFIGURATION_COUNT_OBJECT = 6;
57-
private static final int SHIFT_OBJECT_COUNT = 7;
58-
private static final int COUNT_ELEMENT_OBJECT = 4;
59-
private static final int CONFIGURATION_SUPPORT = 1;
60-
private static final int START_READ_POSITION = 3;
61-
private static final int SHIFT_SIZE = 2;
62-
63-
private static final Map<Path, Map<String, Map<SupportConfiguration, SupportVariant>>> SUPPORT_MAPS
64-
= new ConcurrentHashMap<>();
65-
66-
private static final Map<Path, Map<String, SupportVariant>> SUPPORT_SIMPLE_MAPS
67-
= new ConcurrentHashMap<>();
41+
private static final Map<Path, SupportData> CACHE = new ConcurrentHashMap<>();
6842

6943
/**
70-
* Выполняет чтение информации о поддержке и возвращает упрощенный вариант: UUID / MAX(SupportVariant)
44+
* Выполняет чтение сводной информации о поддержке и помещает значение в кеше
7145
*
72-
* @param path Путь к файлу описания поддержки
73-
* @return Прочитанная информация
46+
* @param pathParentConfigurationBin Путь к файлу конфигурации поставщика
7447
*/
75-
public static Map<String, SupportVariant> readSimple(Path path) {
76-
var rootPath = getRootPathByParentConfigurations(path);
77-
var supportMap = SUPPORT_SIMPLE_MAPS.get(rootPath);
78-
if (supportMap == null && path.toFile().exists()) {
79-
readFile(path, rootPath, false);
80-
supportMap = SUPPORT_SIMPLE_MAPS.get(rootPath);
81-
}
82-
83-
if (supportMap == null) {
84-
return Collections.emptyMap();
85-
}
86-
87-
return supportMap;
48+
public static void read(Path pathParentConfigurationBin) {
49+
var rootPath = getRootConfiguration(pathParentConfigurationBin);
50+
CACHE.computeIfAbsent(rootPath, key -> SupportData.create(pathParentConfigurationBin));
8851
}
8952

9053
/**
91-
* Выполняет чтение информации о поддержке и возвращает весь набор прочитанных данных
54+
* Выполняет чтение сводной информации о поддержке без кеширования
9255
*
93-
* @param path Путь к файлу описания поддержки
94-
* @return Прочитанная информация
56+
* @param pathParentConfigurationBin Путь к файлу конфигурации поставщика
9557
*/
96-
public static Map<String, Map<SupportConfiguration, SupportVariant>> readFull(Path path) {
97-
var rootPath = getRootPathByParentConfigurations(path);
98-
var supportMap = SUPPORT_MAPS.get(rootPath);
99-
if (supportMap == null && path.toFile().exists()) {
100-
readFile(path, rootPath, true);
101-
supportMap = SUPPORT_MAPS.get(rootPath);
102-
}
103-
104-
if (supportMap == null) {
105-
return Collections.emptyMap();
106-
}
58+
public static SupportData readNoCache(Path pathParentConfigurationBin) {
59+
return SupportData.create(pathParentConfigurationBin);
60+
}
10761

108-
return supportMap;
62+
/**
63+
* Выполняет чтение полной информации о поддержке без кеширования
64+
*
65+
* @param pathParentConfigurationBin Путь к файлу конфигурации поставщика
66+
*/
67+
public static FullSupportData readFull(Path pathParentConfigurationBin) {
68+
return FullSupportData.create(pathParentConfigurationBin);
10969
}
11070

11171
/**
112-
* Возвращает максимальный вариант поддержки для объекта с явным указанием пути.
113-
* Используется обычно для объектов, не имеющих собственного файла
72+
* Возвращает вариант поддержки для объекта с явным указанием пути, на основании которого
73+
* находится нужный комплект поддержки в кеше
11474
*
115-
* @param uuid Строка-идентификатор объекта, для которого определяется вариант поддержки
75+
* @param uid Строка-идентификатор объекта, для которого определяется вариант поддержки
11676
* @param path Путь к файлу MDO объекта / родительского объекта
11777
* @return Вариант поддержки
11878
*/
119-
public static SupportVariant getSupportVariantByMDO(String uuid, Path path) {
120-
var key = SUPPORT_SIMPLE_MAPS.keySet().stream().filter(path::startsWith).findFirst();
121-
if (key.isPresent()) {
122-
return SUPPORT_SIMPLE_MAPS.get(key.get()).getOrDefault(uuid, SupportVariant.NONE);
123-
}
124-
125-
return SupportVariant.NONE;
126-
}
127-
128-
private void readFile(Path pathToBinFile, Path rootPath, boolean fullRead) {
129-
LOGGER.debug("Чтения файла поставки ParentConfigurations.bin, полное чтение = " + fullRead);
130-
131-
try {
132-
var supportMap = read(pathToBinFile);
133-
if(fullRead) {
134-
SUPPORT_MAPS.put(rootPath, supportMap);
135-
} else {
136-
Map<String, SupportVariant> result = new HashMap<>();
137-
supportMap.forEach((String uuid, Map<SupportConfiguration, SupportVariant> supportVariantMap)
138-
-> result.put(uuid, SupportVariant.max(supportVariantMap.values())));
139-
SUPPORT_SIMPLE_MAPS.put(rootPath, result);
140-
}
141-
} catch (FileNotFoundException | NumberFormatException exception) {
142-
LOGGER.error(
143-
String.format("Ошибка чтения файла %s", pathToBinFile.toFile()));
144-
LOGGER.debug("TRACE", exception);
79+
public static SupportVariant get(String uid, Path path) {
80+
var supportData = CACHE.get(path);
81+
if (supportData == null) {
82+
supportData = CACHE.entrySet().stream()
83+
.filter(entry -> path.startsWith(entry.getKey()))
84+
.max(Comparator.comparingInt(entry -> entry.getKey().getNameCount()))
85+
.map(Map.Entry::getValue)
86+
.orElse(null);
14587
}
146-
}
147-
148-
private Map<String, Map<SupportConfiguration, SupportVariant>> read(Path pathToBinFile) throws FileNotFoundException {
149-
Map<String, Map<SupportConfiguration, SupportVariant>> supportMap = new HashMap<>();
150-
String[] dataStrings;
151-
var fileInputStream = new FileInputStream(pathToBinFile.toFile());
152-
try (var scanner = new Scanner(fileInputStream, StandardCharsets.UTF_8)) {
153-
dataStrings = scanner.findAll(patternSplit)
154-
.map(matchResult -> matchResult.group(1))
155-
.toArray(String[]::new);
156-
}
157-
158-
var countConfiguration = Integer.parseInt(dataStrings[POINT_COUNT_CONFIGURATION]);
159-
LOGGER.debug("Найдено конфигураций: {}", countConfiguration);
16088

161-
var startPoint = START_READ_POSITION;
162-
for (var numberConfiguration = 1; numberConfiguration <= countConfiguration; numberConfiguration++) {
163-
var configurationVersion = dataStrings[startPoint + SHIFT_CONFIGURATION_VERSION];
164-
var configurationProducer = dataStrings[startPoint + SHIFT_CONFIGURATION_PRODUCER];
165-
var configurationName = dataStrings[startPoint + SHIFT_CONFIGURATION_NAME];
166-
var countObjectsConfiguration = Integer.parseInt(dataStrings[startPoint + SHIFT_CONFIGURATION_COUNT_OBJECT]);
167-
var configurationSupport = Integer.parseInt(dataStrings[CONFIGURATION_SUPPORT]);
168-
var configurationSupportVariant = GeneralSupportVariant.valueOf(configurationSupport);
169-
170-
var supportConfiguration
171-
= new SupportConfiguration(configurationName, configurationProducer, configurationVersion);
172-
173-
LOGGER.debug(String.format(
174-
"Конфигурация: %s Версия: %s Поставщик: %s Количество объектов: %s",
175-
configurationName,
176-
configurationVersion,
177-
configurationProducer,
178-
countObjectsConfiguration));
179-
180-
var startObjectPoint = startPoint + SHIFT_OBJECT_COUNT;
181-
for (var numberObject = 0; numberObject < countObjectsConfiguration; numberObject++) {
182-
var currentObjectPoint = startObjectPoint + numberObject * COUNT_ELEMENT_OBJECT;
183-
// 0 - не редактируется, 1 - с сохранением поддержки, 2 - снято
184-
var support = Integer.parseInt(dataStrings[currentObjectPoint]);
185-
var guidObject = dataStrings[currentObjectPoint + SHIFT_SIZE];
186-
SupportVariant supportVariant;
187-
if (configurationSupportVariant == GeneralSupportVariant.LOCKED) {
188-
supportVariant = SupportVariant.NOT_EDITABLE;
189-
} else {
190-
supportVariant = SupportVariant.valueOf(support);
191-
}
192-
193-
Map<SupportConfiguration, SupportVariant> map = supportMap.computeIfAbsent(guidObject, k -> new HashMap<>());
194-
map.put(supportConfiguration, supportVariant);
195-
}
196-
197-
startPoint = startObjectPoint + SHIFT_SIZE + countObjectsConfiguration * COUNT_ELEMENT_OBJECT;
89+
if (supportData == null) {
90+
return SupportVariant.NONE;
91+
} else {
92+
return supportData.get(uid);
19893
}
199-
200-
return supportMap;
20194
}
20295

203-
/**
204-
* Получает каталог проекта по файлу поддержки конфигурации
205-
*/
206-
private Path getRootPathByParentConfigurations(Path mdoPath) {
96+
private static Path getRootConfiguration(Path mdoPath) {
20797
return Paths.get(
20898
FilenameUtils.getFullPathNoEndSeparator(
20999
FilenameUtils.getFullPathNoEndSeparator(mdoPath.toString())));

src/main/java/com/github/_1c_syntax/bsl/supconf/SupportConfiguration.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public int compareTo(SupportConfiguration o) {
4848
}
4949

5050
private static String stripQuotes(String value) {
51-
if (value == null || value.length() < 2) {
51+
if (value.length() < 2) {
5252
return value;
5353
}
5454

0 commit comments

Comments
 (0)