Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

181 changes: 89 additions & 92 deletions src/main/java/com/github/_1c_syntax/bsl/mdclasses/MDClasses.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import com.github._1c_syntax.bsl.reader.MDMerger;
import com.github._1c_syntax.bsl.reader.MDOReader;
import com.github._1c_syntax.bsl.types.MDOType;
import com.github._1c_syntax.bsl.types.MdoReference;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
Expand All @@ -38,7 +39,10 @@
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -90,18 +94,6 @@ public MDClass createConfiguration(Path path, MDCReadSettings readSettings) {
return MDOReader.readConfiguration(path, readSettings);
}

/**
* @param path Путь к корню проекта
* @param skipSupport Флаг управления чтением информации о поддержке
* @return Конфигурация или расширение
* @deprecated Стоит использовать метод с параметром MDCReadSettings.
* Создает конфигурацию или расширение по указанному пути
*/
@Deprecated(since = "0.16.0")
public MDClass createConfiguration(Path path, boolean skipSupport) {
return createConfiguration(path, MDCReadSettings.builder().skipSupport(skipSupport).build());
}

/**
* Создает внешнюю обработку или внешний отчет по указанному пути
*
Expand All @@ -122,19 +114,6 @@ public List<MDClass> createConfigurations(Path sourcePath) {
return createConfigurations(sourcePath, MDCReadSettings.DEFAULT);
}

/**
* Возвращает список конфигураций\расширений в указанном каталоге исходных файлов
*
* @param sourcePath каталог исходных файлов
* @param skipSupport Флаг управления чтением информации о поддержке
* @return Список прочитанных контейнеров конфигураций и расширений
* @deprecated Стоит использовать метод с параметром MDCReadSettings.
*/
@Deprecated(since = "0.16.0")
public List<MDClass> createConfigurations(Path sourcePath, boolean skipSupport) {
return createConfigurations(sourcePath, MDCReadSettings.builder().skipSupport(skipSupport).build());
}

/**
* Читает каталог проекта и
* - возвращает объект MDClass, если содержится только один объект MDC
Expand All @@ -144,55 +123,56 @@ public List<MDClass> createConfigurations(Path sourcePath, boolean skipSupport)
* @param sourcePath Путь к каталогу исходников
* @return Результат чтения решения
*/
public MDClass createSolution(Path sourcePath) {
public Solution createSolution(Path sourcePath) {
return createSolution(sourcePath, MDCReadSettings.DEFAULT);
}

/**
* Читает каталог проекта и
* - возвращает объект MDClass, если содержится только один объект MDC
* - возвращает объединенную конфигурацию с расширениями
* - возвращает объединение расширений с пустой конфигурацией
* - возвращает Solution с единственной конфигурацией, если содержится только один объект MDC
* - возвращает Solution с объединенной конфигурацией и расширениями
* - возвращает Solution с объединением расширений с пустой конфигурацией
*
* @param sourcePath Путь к каталогу исходников
* @param readSettings Настройки чтения проекта
* @return Результат чтения решения
*/
public MDClass createSolution(Path sourcePath, MDCReadSettings readSettings) {
public Solution createSolution(Path sourcePath, MDCReadSettings readSettings) {
var mdcs = createConfigurations(sourcePath, readSettings);
MDClass result;
if (mdcs.isEmpty()) {
result = Configuration.EMPTY;
} else if (mdcs.size() == 1) {
result = mdcs.getFirst();
} else {
var mdc = mdcs.stream().filter(Configuration.class::isInstance).map(Configuration.class::cast).findFirst();
var cf = mdc.orElse(Configuration.EMPTY);

if (!mdcs.isEmpty()) {
if (mdcs.size() == 1) {
var mdc = mdcs.getFirst();
if (mdc instanceof Configuration cf) {
return buildSolution(cf, Collections.emptyList());
}
if (mdc instanceof ConfigurationExtension ext) {
return buildSolution(Configuration.EMPTY, List.of(ext));
}

// заглушка, если получилось что-то странное
return Solution.EMPTY;
}

// решение содержит несколько компонент, разделяем
var base = mdcs.stream()
.filter(Configuration.class::isInstance)
.map(Configuration.class::cast)
.findFirst()
.orElse(Configuration.EMPTY);

var extensions = mdcs.stream()
.filter(ConfigurationExtension.class::isInstance)
.map(ConfigurationExtension.class::cast)
.toList();

if (cf.isEmpty()) {
if (extensions.isEmpty()) {
// вернем первое значение, т.к. там нет ни конфы, ни расширений
return mdcs.getFirst();
} else if (extensions.size() == 1) {
// есть одно расширение, вернем его
return extensions.getFirst();
}
} else if (extensions.isEmpty()) {
// расширений нет, вернем конфигурацию
return cf;
}

// объединим расширения с конфигурацией в одно целое
result = cf;
for (var extension : extensions) {
result = MDMerger.merge((Configuration) result, extension);
// что-то странное прочли
if (!base.isEmpty() || !extensions.isEmpty()) {
return buildSolution(base, extensions);
}
}
return result;

return Solution.EMPTY;
}

/**
Expand Down Expand Up @@ -241,19 +221,6 @@ public List<MDClass> create(Path sourcePath) {
return create(sourcePath, MDCReadSettings.DEFAULT);
}

/**
* Возвращает список контейнеров метаданных в указанном каталоге исходных файлов
*
* @param sourcePath каталог исходных файлов
* @param skipSupport Флаг управления чтением информации о поддержке
* @return Список прочитанных контейнеров
* @deprecated Стоит использовать метод с параметром MDCReadSettings.
*/
@Deprecated(since = "0.16.0")
public List<MDClass> create(Path sourcePath, boolean skipSupport) {
return create(sourcePath, MDCReadSettings.builder().skipSupport(skipSupport).build());
}

/**
* Возвращает список контейнеров метаданных в указанном каталоге исходных файлов
*
Expand Down Expand Up @@ -285,29 +252,7 @@ public FileVisitResult visitFileFailed(Path file, IOException exc) {

@Override
public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) {
if (!attrs.isRegularFile()) {
return FileVisitResult.CONTINUE;
}

var parentName = path.getParent().getFileName().toString();
var parentParentName = "";
if (path.getParent().getParent() != null && path.getParent().getParent().getFileName() != null) {
parentParentName = path.getParent().getParent().getFileName().toString();
}

if (excludeFolders.contains(parentName) || excludeFolders.contains(parentParentName)) {
return FileVisitResult.CONTINUE;
}
var fileName = path.getFileName().toString();
var ext = FilenameUtils.getExtension(fileName);
if (!("xml".equals(ext) || "mdo".equals(ext))) {
return FileVisitResult.CONTINUE;
}

if (pattern.matcher(fileName).matches()) {
listPath.add(path);
}
return FileVisitResult.CONTINUE;
return handleFile(path, attrs, excludeFolders, pattern, listPath);
}
});
} catch (IOException e) {
Expand All @@ -317,6 +262,34 @@ public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) {
return listPath;
}

private static FileVisitResult handleFile(Path path, BasicFileAttributes attrs,
Set<String> excludeFolders, Pattern pattern,
List<Path> listPath) {
if (!attrs.isRegularFile()) {
return FileVisitResult.CONTINUE;
}

var parentName = path.getParent().getFileName().toString();
var parentParentName = "";
if (path.getParent().getParent() != null && path.getParent().getParent().getFileName() != null) {
parentParentName = path.getParent().getParent().getFileName().toString();
}

if (excludeFolders.contains(parentName) || excludeFolders.contains(parentParentName)) {
return FileVisitResult.CONTINUE;
}
var fileName = path.getFileName().toString();
var ext = FilenameUtils.getExtension(fileName);
if (!("xml".equals(ext) || "mdo".equals(ext))) {
return FileVisitResult.CONTINUE;
}

if (pattern.matcher(fileName).matches()) {
listPath.add(path);
}
return FileVisitResult.CONTINUE;
}

private Set<String> mdoTypeGroupNames() {
return Arrays.stream(MDOType.values())
.filter(type -> type != MDOType.EXTERNAL_REPORT
Expand All @@ -326,4 +299,28 @@ private Set<String> mdoTypeGroupNames() {
.map(MDOType::groupName)
.collect(Collectors.toSet());
}

private static Solution buildSolution(Configuration base, List<ConfigurationExtension> extensions) {
if (extensions.isEmpty()) {
var provenance = new HashMap<MdoReference, ObjectProvenance>();
base.getChildrenByMdoRef().forEach((ref, md) ->
provenance.put(ref, ObjectProvenance.builder()
.ownerRef(base.getMdoReference())
.objectBelonging(md.getObjectBelonging())
.build()));
return Solution.builder()
.mergedConfiguration(base)
.baseConfiguration(base)
.provenance(Collections.unmodifiableMap(provenance))
.build();
}

var mergeResult = MDMerger.mergeAll(base, extensions);
return Solution.builder()
.mergedConfiguration(mergeResult.configuration())
.baseConfiguration(base)
.extensions(extensions)
.provenance(mergeResult.provenance())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* This file is a part of MDClasses.
*
* Copyright (c) 2019 - 2026
* Tymko Oleg <olegtymko@yandex.ru>, Maximov Valery <maximovvalery@gmail.com> and contributors
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*
* MDClasses is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* MDClasses is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with MDClasses.
*/
package com.github._1c_syntax.bsl.mdclasses;

import com.github._1c_syntax.bsl.mdo.support.ObjectBelonging;
import com.github._1c_syntax.bsl.reader.MDMerger;
import com.github._1c_syntax.bsl.types.MdoReference;
import lombok.Builder;
import lombok.Singular;
import lombok.Value;

import java.util.List;

/**
* Хранит информацию о происхождении объекта метаданных в составе {@link Solution}.
* <p>
* Заполняется автоматически в {@link MDMerger#mergeAll(Configuration, java.util.List)}
* при построении решения.
*
*/
@Value
@Builder
public class ObjectProvenance {

/**
* Конфигурация или расширение, которая является владельцем объекта
*/
@Builder.Default
MdoReference ownerRef = MdoReference.EMPTY;

/**
* Расширения (если есть), которые модифицировали объект
*/
@Singular
List<MdoReference> modifiedByExtensionRefs;
Comment thread
coderabbitai[bot] marked this conversation as resolved.

/**
* Признак собственного или заимствованного (унаследованного) объекта.
*/
@Builder.Default
ObjectBelonging objectBelonging = ObjectBelonging.OWN;
}
Loading
Loading