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()` +- **Анализ зависимостей**: Возможность извлечения ссылок на объекты метаданных из типов реквизитов + Немного о структуре пакета: - в корне расположены классы видов объектов метаданных (Справочники, Документы, Перечисления и т.д.), базовые интерфейсы