|
26 | 26 | import lombok.extern.slf4j.Slf4j; |
27 | 27 | import org.apache.commons.io.FilenameUtils; |
28 | 28 |
|
29 | | -import java.io.FileInputStream; |
30 | | -import java.io.FileNotFoundException; |
31 | | -import java.nio.charset.StandardCharsets; |
32 | 29 | import java.nio.file.Path; |
33 | 30 | import java.nio.file.Paths; |
34 | | -import java.util.Collections; |
35 | | -import java.util.HashMap; |
| 31 | +import java.util.Comparator; |
36 | 32 | import java.util.Map; |
37 | | -import java.util.Scanner; |
38 | 33 | import java.util.concurrent.ConcurrentHashMap; |
39 | | -import java.util.regex.Pattern; |
40 | 34 |
|
41 | 35 | /** |
42 | 36 | * Используется для чтения информации о поддержке из файла ParentConfigurations.bin конфигурации |
43 | 37 | */ |
44 | 38 | @Slf4j |
45 | 39 | @UtilityClass |
46 | 40 | 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<>(); |
68 | 42 |
|
69 | 43 | /** |
70 | | - * Выполняет чтение информации о поддержке и возвращает упрощенный вариант: UUID / MAX(SupportVariant) |
| 44 | + * Выполняет чтение сводной информации о поддержке и помещает значение в кеше |
71 | 45 | * |
72 | | - * @param path Путь к файлу описания поддержки |
73 | | - * @return Прочитанная информация |
| 46 | + * @param pathParentConfigurationBin Путь к файлу конфигурации поставщика |
74 | 47 | */ |
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)); |
88 | 51 | } |
89 | 52 |
|
90 | 53 | /** |
91 | | - * Выполняет чтение информации о поддержке и возвращает весь набор прочитанных данных |
| 54 | + * Выполняет чтение сводной информации о поддержке без кеширования |
92 | 55 | * |
93 | | - * @param path Путь к файлу описания поддержки |
94 | | - * @return Прочитанная информация |
| 56 | + * @param pathParentConfigurationBin Путь к файлу конфигурации поставщика |
95 | 57 | */ |
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 | + } |
107 | 61 |
|
108 | | - return supportMap; |
| 62 | + /** |
| 63 | + * Выполняет чтение полной информации о поддержке без кеширования |
| 64 | + * |
| 65 | + * @param pathParentConfigurationBin Путь к файлу конфигурации поставщика |
| 66 | + */ |
| 67 | + public static FullSupportData readFull(Path pathParentConfigurationBin) { |
| 68 | + return FullSupportData.create(pathParentConfigurationBin); |
109 | 69 | } |
110 | 70 |
|
111 | 71 | /** |
112 | | - * Возвращает максимальный вариант поддержки для объекта с явным указанием пути. |
113 | | - * Используется обычно для объектов, не имеющих собственного файла |
| 72 | + * Возвращает вариант поддержки для объекта с явным указанием пути, на основании которого |
| 73 | + * находится нужный комплект поддержки в кеше |
114 | 74 | * |
115 | | - * @param uuid Строка-идентификатор объекта, для которого определяется вариант поддержки |
| 75 | + * @param uid Строка-идентификатор объекта, для которого определяется вариант поддержки |
116 | 76 | * @param path Путь к файлу MDO объекта / родительского объекта |
117 | 77 | * @return Вариант поддержки |
118 | 78 | */ |
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); |
145 | 87 | } |
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); |
160 | 88 |
|
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); |
198 | 93 | } |
199 | | - |
200 | | - return supportMap; |
201 | 94 | } |
202 | 95 |
|
203 | | - /** |
204 | | - * Получает каталог проекта по файлу поддержки конфигурации |
205 | | - */ |
206 | | - private Path getRootPathByParentConfigurations(Path mdoPath) { |
| 96 | + private static Path getRootConfiguration(Path mdoPath) { |
207 | 97 | return Paths.get( |
208 | 98 | FilenameUtils.getFullPathNoEndSeparator( |
209 | 99 | FilenameUtils.getFullPathNoEndSeparator(mdoPath.toString()))); |
|
0 commit comments