diff --git a/docs/ru/examples.md b/docs/ru/examples.md
index 273bef64a..195129d7e 100644
--- a/docs/ru/examples.md
+++ b/docs/ru/examples.md
@@ -144,6 +144,110 @@ catalogs.forEach(catalog -> {
});
```
+### Детальный анализ типов реквизитов
+
+```java
+// Полный пример анализа типов реквизитов с демонстрацией нового функционала
+public class TypeAnalysisExample {
+
+ public static void main(String[] args) {
+ // Путь к каталогу конфигурации
+ Path configurationPath = Paths.get("path/to/configuration");
+
+ // Чтение конфигурации
+ Configuration configuration = (Configuration) MDClasses.createConfiguration(configurationPath);
+
+ System.out.println("=== АНАЛИЗ ТИПОВ РЕКВИЗИТОВ ===\n");
+
+ // Анализ реквизитов справочников
+ configuration.getCatalogs().forEach(catalog -> {
+ System.out.println("Справочник: " + catalog.getName());
+ System.out.println("=====================================");
+
+ catalog.getAttributes().forEach(attribute -> {
+ analyzeAttributeType(attribute);
+ });
+
+ System.out.println();
+ });
+ }
+
+ private static void analyzeAttributeType(ObjectAttribute attribute) {
+ ValueTypeDescription typeDescription = attribute.getType();
+
+ System.out.println("Реквизит: " + attribute.getName());
+ System.out.println(" Полное описание типа: " + typeDescription.getDescription());
+ System.out.println(" Составной тип: " + typeDescription.isComposite());
+ System.out.println(" Количество типов в составе: " + typeDescription.getTypes().size());
+
+ // Анализ каждого типа в составе
+ typeDescription.getTypes().forEach(type -> {
+ System.out.println(" Тип: " + type.getClass().getSimpleName());
+
+ if (type instanceof MetadataValueType metadataType) {
+ System.out.println(" Ссылка на объект: " + metadataType.getName());
+ System.out.println(" Тип метаданных: " + metadataType.getKind());
+ System.out.println(" Составной: " + metadataType.isComposite());
+ } else if (type instanceof PrimitiveValueType primitiveType) {
+ System.out.println(" Примитивный тип: " + primitiveType);
+ }
+ });
+
+ // Анализ квалификаторов
+ if (!typeDescription.getQualifiers().isEmpty()) {
+ System.out.println(" Квалификаторы:");
+ typeDescription.getQualifiers().forEach(qualifier -> {
+ if (qualifier instanceof StringQualifiers stringQual) {
+ System.out.println(" Строковые: длина=" + stringQual.getLength() +
+ ", допустимая длина=" + stringQual.getAllowedLength());
+ } else if (qualifier instanceof NumberQualifiers numberQual) {
+ System.out.println(" Числовые: точность=" + numberQual.getPrecision() +
+ ", масштаб=" + numberQual.getScale());
+ } else {
+ System.out.println(" " + qualifier.getClass().getSimpleName() + ": " + qualifier);
+ }
+ });
+ }
+
+ System.out.println();
+ }
+}
+```
+
+**Ожидаемый вывод:**
+
+```sh
+=== АНАЛИЗ ТИПОВ РЕКВИЗИТОВ ===
+
+Справочник: Справочник1
+=====================================
+Реквизит: Наименование
+ Полное описание типа: Строка(100)
+ Составной тип: false
+ Количество типов в составе: 1
+ Тип: PrimitiveValueType
+ Примитивный тип: STRING
+ Квалификаторы:
+ Строковые: длина=100, допустимая длина=FIXED
+
+Реквизит: СсылкаНаДругойСправочник
+ Полное описание типа: СправочникСсылка.ДругойСправочник
+ Составной тип: false
+ Количество типов в составе: 1
+ Тип: MetadataValueType
+ Ссылка на объект: ДругойСправочник
+ Тип метаданных: CATALOG
+ Составной: false
+```
+
+**Особенности нового функционала:**
+
+1. **Полное описание типов**: Метод `getDescription()` возвращает понятное описание типа, включая квалификаторы
+2. **Составные типы**: Поддержка типов, содержащих несколько вариантов значений
+3. **Детальный анализ**: Возможность получить доступ к каждому типу в составе и его свойствам
+4. **Квалификаторы**: Полная информация о квалификаторах типов (длина строк, точность чисел и т.д.)
+5. **Ссылки на метаданные**: Извлечение информации о ссылках на объекты метаданных
+
### Работа с документами
```java
@@ -272,134 +376,26 @@ allModules.stream()
## Анализ типов данных
-При чтении описания метаданных для объектов и их атрибутов вычисляются описания типов. Все сущности, имеющие описания типов данных, реализуют интерфейс `ValueTypeOwner`.
-
-Ниже приведены примеры, как можно использовать данную информацию.
-
-### Получение описания типа реквизита справочника
+При чтении описания метаданных для объектов и их атрибутов вычисляются описания типов. Все сущности, имеющие описания типов данных, реализуют интерфейс `ValueTypeOwner`.
-Часть описания реквизита справочника
-
-```xml
-
- Реквизит2
-
- Number
-
- 10
-
-
-
-
-
- Use
-
-```
-
-Код, которым можно посмотреть описание типа
+### Работа с определяемыми типами
```java
-// найдем справочник из прочитанной конфигурации
-var childMDO = configuration.findChild("Catalog.Справочник1");
-
-// проверим, что это на самом деле справочник
-if (childMDO.isPresent() && childMDO.get() instanceof Catalog catalog) {
-
- // убедимся, что у справочника есть дочерние
- assertThat(catalog.getChildren()).isNotEmpty();
-
- // найдем нужный дочерний (реквизит)
- var childAttribute = catalog.findChild(md -> "Реквизит2".equals(md.getName()));
-
- // проверим, что он есть и нужного типа
- if (childAttribute.isPresent() && childAttribute.get() instanceof ObjectAttribute objectAttribute) {
-
- // проверим наименование
- assertThat(objectAttribute.getName()).isEqualTo("Реквизит2");
-
- // описание типа доступно через getValueType()
- assertThat(objectAttribute.getValueType()).isNotNull();
- // убедимся в наличии примитивного типа СТРОКА в составе описания
- assertThat(objectAttribute.getValueType().contains(PrimitiveValueType.NUMBER)).isTrue();
- // убедимся, что тип не составной
- assertThat(objectAttribute.getValueType().isComposite()).isFalse();
- // убедимся, что квалификаторы прочитаны
- assertThat(objectAttribute.getValueType().getQualifiers()).hasSize(1);
-
- // убедимся, что прочитан квалификатор числа
- var qualifier = objectAttribute.getValueType().getQualifiers().get(0);
- assertThat(qualifier).isInstanceOf(NumberQualifiers.class);
-
- // убедимся, что квалификатор числа содежржит верную информацию
- var numberQualifiers = (NumberQualifiers) qualifier;
- assertThat(numberQualifiers.getPrecision()).isEqualTo(10); // длина 10
- assertThat(numberQualifiers.getScale()).isEqualTo(0); // точность 0
- assertThat(numberQualifiers.isNonNegative()).isFalse(); // возможны любые знаки
- }
- }
-}
-```
-
-### Определение состава определяемого типа
-
-Часть описания определяемого типа
-
-```xml
- ЗначениеДоступа
-
- CatalogRef.ПапкиФайлов
- CatalogRef.ВнешниеПользователи
- CatalogRef.КлючиДоступа
- CatalogRef.ИдентификаторыОбъектовРасширений
- CatalogRef.ГруппыВнешнихПользователей
- CatalogRef.ГруппыПользователей
- EnumRef.ДополнительныеЗначенияДоступа
- ChartOfCharacteristicTypesRef.ДополнительныеРеквизитыИСведения
- CatalogRef.ДополнительныеОтчетыИОбработки
- CatalogRef.Пользователи
- CatalogRef.ГруппыИсполнителейЗадач
- CatalogRef.УчетныеЗаписиЭлектроннойПочты
- CatalogRef.ИдентификаторыОбъектовМетаданных
-
-```
-
-Код, которым можно посмотреть описание типа
-
-```java
-
-// найдем определяемый тип прочитанной конфигурации
+// Поиск определяемого типа и анализ его состава
var childMDO = configuration.findChild("DefinedType.ЗначениеДоступа");
if (childMDO.isPresent() && childMDO.get() instanceof DefinedType definedType) {
- assertThat(definedType.getName()).isEqualTo("ЗначениеДоступа");
- // убедимся, что тип прочитан
- assertThat(definedType.getValueType()).isNotNull();
- // убедимся, что в составе нет ЧИСЛА
- assertThat(definedType.getValueType().contains(PrimitiveValueType.NUMBER)).isFalse();
- // убедимся, что описание соответствует составному типу
- assertThat(definedType.getValueType().isComposite()).isTrue();
- // квалификаторов нет
- assertThat(definedType.getValueType().getQualifiers()).isEmpty();
-
- // создадим тип по имени
- var typeContains = MetadataValueType.fromString("EnumRef.ДополнительныеЗначенияДоступа");
-
- assertThat(typeContains).isNotNull();
- // полученный тип относится к перечислению
- assertThat(typeContains.getKind()).isEqualTo(MDOType.ENUM);
- // тип не составной
- assertThat(typeContains.isComposite()).isFalse();
- // есть имя на английском
- assertThat(typeContains.getName()).isEqualTo("EnumRef.ДополнительныеЗначенияДоступа");
- // и русском
- assertThat(typeContains.getNameRu()).isEqualTo("ПеречислениеСсылка.ДополнительныеЗначенияДоступа");
-
- // второй тип
- var typeNotContains = MetadataValueType.fromString("CatalogRef.Контрагенты");
- assertThat(typeNotContains).isNotNull();
- // убедимся, что первый тип входит в состав описания
- assertThat(definedType.getValueType().contains(typeContains)).isTrue();
- // убедимся, что второй тип не входит в состав
- assertThat(definedType.getValueType().contains(typeNotContains)).isFalse();
+ System.out.println("Определяемый тип: " + definedType.getName());
+
+ ValueTypeDescription typeDescription = definedType.getValueType();
+ System.out.println(" Составной тип: " + typeDescription.isComposite());
+ System.out.println(" Количество типов в составе: " + typeDescription.getTypes().size());
+
+ // Анализ каждого типа в составе
+ typeDescription.getTypes().forEach(type -> {
+ if (type instanceof MetadataValueType metadataType) {
+ System.out.println(" - " + metadataType.getName() + " (" + metadataType.getKind() + ")");
+ }
+ });
}
```
@@ -450,7 +446,7 @@ objectsWithPrefix.forEach(obj -> {
### Построение диаграммы зависимостей объектов
```java
-// Упрощенный пример построения графа зависимостей между объектами
+// Построение графа зависимостей с использованием нового функционала анализа типов
Map> dependencies = new HashMap<>();
// Сбор зависимостей из типов реквизитов справочников
@@ -459,14 +455,15 @@ configuration.getCatalogs().forEach(catalog -> {
dependencies.putIfAbsent(catalogKey, new HashSet<>());
catalog.getAttributes().forEach(attribute -> {
- if (attribute.getType() != null) {
- String typeDescription = attribute.getType().getDescription();
- // Проверяем, что тип ссылается на другой объект метаданных
- if (typeDescription != null && typeDescription.contains("CatalogRef.")) {
- String referencedObject = typeDescription.replace("CatalogRef.", "Catalog.");
+ ValueTypeDescription typeDescription = attribute.getType();
+
+ // Анализ каждого типа в составе
+ typeDescription.getTypes().forEach(type -> {
+ if (type instanceof MetadataValueType metadataType) {
+ String referencedObject = metadataType.getKind() + "." + metadataType.getName();
dependencies.get(catalogKey).add(referencedObject);
}
- }
+ });
});
});
diff --git a/docs/ru/features.md b/docs/ru/features.md
index 835a657e6..6b2f4ddea 100644
--- a/docs/ru/features.md
+++ b/docs/ru/features.md
@@ -25,6 +25,16 @@
На данный момент поддерживается загрузка всех видов метаданных, существующих в версиях платформы 1С до 8.5. В зависимости от типа объекта и потребностей, объем читаемой информации может различаться (реализация чтения дополнительной информации выполняется от задач).
Актуальное содержимое того или иного вида объекта метаданных можно всегда находится в классе его реализации в пакете [mdo](com.github._1c_syntax.bsl.mdo).
+## Чтение типов реквизитов и метаданных
+
+Библиотека предоставляет расширенные возможности для работы с типами данных реквизитов и метаданных:
+
+- **Полное описание типов**: Чтение составных типов данных, включая примитивные типы, ссылки на объекты метаданных и определяемые типы
+- **Квалификаторы типов**: Поддержка всех видов квалификаторов (строковые, числовые, дата и т.д.)
+- **Составные типы**: Работа с типами, содержащими несколько вариантов значений
+- **Строковое представление**: Получение понятного описания типа через метод `getDescription()`
+- **Анализ зависимостей**: Возможность извлечения ссылок на объекты метаданных из типов реквизитов
+
Немного о структуре пакета:
- в корне расположены классы видов объектов метаданных (Справочники, Документы, Перечисления и т.д.), базовые интерфейсы