feat: API записи объектов метаданных (Subsystem, Catalog, Configuration) в формате конфигуратора (JAXB)#597
Conversation
📝 WalkthroughWalkthroughAdded JAXB-based XML writing support for 1C metadata objects. This PR introduces XSD schemas for multiple v8.x namespaces, JAXB configuration bindings, infrastructure classes for marshalling metadata to Designer XML format, type-specific converters for each metadata object kind, and comprehensive tests validating output generation. Changes
Sequence Diagram(s)sequenceDiagram
participant App as Application
participant Converter as Type Converter<br/>(e.g., CatalogToJaxbConverter)
participant Factory as JAXB<br/>ObjectFactory
participant Marshaller as JAXB<br/>Marshaller
participant PostProcessor as XML<br/>Post-Processor
participant File as Output<br/>File
App->>Converter: toMetaDataObject(domainObject)
Converter->>Factory: create MetaDataObject
Factory-->>Converter: jaxbRoot
Converter->>Factory: create inner JAXB DTO
Factory-->>Converter: innerDto
Converter->>Converter: buildProperties(domainObject)
Converter->>Converter: buildChildObjects(domainObject)
Converter-->>App: MetaDataObject tree
App->>Marshaller: marshal MetaDataObject
Marshaller->>PostProcessor: transform XML string
PostProcessor->>PostProcessor: adjust namespaces
PostProcessor->>PostProcessor: inject InternalInfo blocks
PostProcessor->>PostProcessor: strip formatVersion from config
PostProcessor-->>Marshaller: processed XML
Marshaller->>File: write UTF-8 XML
File-->>App: File written
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
✨ Finishing Touches🧪 Generate unit tests (beta)
|
There was a problem hiding this comment.
Actionable comments posted: 17
Note
Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.
🟡 Minor comments (10)
src/test/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/DesignerPathResolverTest.java-50-65 (1)
50-65:⚠️ Potential issue | 🟡 MinorTest silently passes if nested subsystem data is missing.
The early return on lines 56-58 means if the test fixture has no child subsystems, the test passes without validating nested path resolution. This could mask regressions if test data changes.
Consider using
assumeTrueto skip explicitly, or assert that children exist to fail fast:Proposed fix
var children = parentSub.getSubsystems(); - if (children == null || children.isEmpty()) { - return; - } + assertThat(children).as("Expected nested subsystems in test fixture").isNotEmpty(); MD child = children.get(0);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/test/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/DesignerPathResolverTest.java` around lines 50 - 65, The test pathForObjectNestedSubsystem currently returns early when parentSub.getSubsystems() is null or empty, hiding missing test data; replace the early return with an explicit precondition/assertion such as using assumeTrue(children != null && !children.isEmpty()) to skip the test when fixtures are missing or assertThat(children).isNotEmpty() to fail fast, referencing the test method pathForObjectNestedSubsystem and the children variable (parentSub.getSubsystems()) so downstream code always exercises DesignerPathResolver.pathForObject when child subsystems are present.src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/CommonModuleToJaxbConverter.java-55-58 (1)
55-58:⚠️ Potential issue | 🟡 MinorPotential
IllegalArgumentExceptionfrom enumfromValue().
ReturnValuesReuse.fromValue(...)may throwIllegalArgumentExceptionif the English name doesn't match any JAXB enum value. Consider wrapping in try-catch or validating the value first.Proposed defensive handling
ReturnValueReuse rvr = c.getReturnValuesReuse(); if (rvr != null && rvr != ReturnValueReuse.UNKNOWN && rvr.fullName() != null) { - p.setReturnValuesReuse(com.github._1c_syntax.bsl.mdclasses.jaxb.v8_3_xcf_enums.ReturnValuesReuse.fromValue(rvr.fullName().getEn())); + try { + p.setReturnValuesReuse( + com.github._1c_syntax.bsl.mdclasses.jaxb.v8_3_xcf_enums.ReturnValuesReuse.fromValue(rvr.fullName().getEn())); + } catch (IllegalArgumentException ignored) { + // Skip if enum value doesn't map to JAXB enum + } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/CommonModuleToJaxbConverter.java` around lines 55 - 58, ReturnValuesReuse.fromValue(...) can throw IllegalArgumentException when the English name doesn't match a JAXB enum; update the block that reads ReturnValueReuse rvr in CommonModuleToJaxbConverter to defensively handle invalid values (reference symbols: ReturnValueReuse, rvr, p.setReturnValuesReuse, ReturnValuesReuse.fromValue, rvr.fullName().getEn()). Wrap the fromValue call in a try-catch (catch IllegalArgumentException) or pre-validate/mapping the string to a known JAXB enum value, and only call p.setReturnValuesReuse(...) when a valid enum is resolved; on invalid value, skip setting or log/debug the unexpected name so conversion won't throw.src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/CommonModuleToJaxbConverter.java-45-45 (1)
45-45:⚠️ Potential issue | 🟡 MinorMissing null check for
nameproperty.Same issue as in
AccumulationRegisterToJaxbConverter-nameshould have a null check for consistency with other string properties.Proposed fix
- p.setName(c.getName()); + p.setName(c.getName() != null ? c.getName() : "");🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/CommonModuleToJaxbConverter.java` at line 45, In CommonModuleToJaxbConverter, the call p.setName(c.getName()) lacks a null check; update the converter to mirror the pattern used for other string properties (as in AccumulationRegisterToJaxbConverter) by only calling p.setName(...) when c.getName() is non-null (e.g., check c.getName() != null before invoking p.setName), ensuring you reference the same variables/methods (p, c, getName, setName) within the CommonModuleToJaxbConverter class.src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/AccumulationRegisterToJaxbConverter.java-47-47 (1)
47-47:⚠️ Potential issue | 🟡 MinorMissing null check for
nameproperty.Unlike other properties in this method (e.g.,
commenton line 49),nameis set directly without a null check. This inconsistency could lead to null values in the output XML.Proposed fix
- p.setName(ar.getName()); + p.setName(ar.getName() != null ? ar.getName() : "");🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/AccumulationRegisterToJaxbConverter.java` at line 47, The assignment p.setName(ar.getName()) in AccumulationRegisterToJaxbConverter should be guarded like the other properties to avoid emitting nulls; update the conversion logic to check ar.getName() for null (e.g., if (ar.getName() != null) p.setName(ar.getName()); or use a safe default) when setting the JAXB property on p so name is only set when non-null.src/main/xsd/v8.3.27/v8.1c.ru-8.2-managed-application-cmi.xsd-104-115 (1)
104-115:⚠️ Potential issue | 🟡 MinorThis is a confirmed typo inherited from the official 1C platform schema.
CommansShortCutInfoandCommansShortCutInfoVectorcontain a spelling error ("Commans" instead of "Commands"). This appears in the official 1C schema namespace (http://v8.1c.ru/8.2/managed-application/cmi) and is mirrored across multiple versions (v8.3.27 and v8.5). The web search found no evidence of "CommansShortCutInfo" in official 1C documentation or EDT API, confirming this is a typo from the upstream source rather than an intentional naming convention.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/xsd/v8.3.27/v8.1c.ru-8.2-managed-application-cmi.xsd` around lines 104 - 115, Rename the misspelled complexType names CommansShortCutInfo and CommansShortCutInfoVector to CommandsShortCutInfo and CommandsShortCutInfoVector, update every reference to tns:CommansShortCutInfo (and the vector type) across the schema to use tns:CommandsShortCutInfo, and update the element declarations that reference those types (e.g., the "info" element). To preserve backward compatibility, add a deprecated alias complexType named CommansShortCutInfo that extends or references the new CommandsShortCutInfo (and similarly for the vector) so existing consumers still resolve the old name while new code uses the corrected names.src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/WriteOptions.java-22-28 (1)
22-28:⚠️ Potential issue | 🟡 MinorDefensive copy needed for
typeFilterto ensure immutability.The
typeFilterSet is stored and returned by reference, allowing external mutation of the "immutable"WriteOptions. Consider making a defensive copy in the constructor and returning an unmodifiable view from the getter.🛡️ Proposed fix for immutability
import com.github._1c_syntax.bsl.types.MDOType; +import java.util.Collections; import java.util.Set; ... private WriteOptions(Builder builder) { this.useShortNamesInChildObjects = builder.useShortNamesInChildObjects; this.version = builder.version; - this.typeFilter = builder.typeFilter; + this.typeFilter = builder.typeFilter != null ? Set.copyOf(builder.typeFilter) : null; } ... public Set<MDOType> getTypeFilter() { - return typeFilter; + return typeFilter; // Already immutable from Set.copyOf() }Also applies to: 50-52
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/WriteOptions.java` around lines 22 - 28, The WriteOptions class currently stores the Builder.typeFilter reference directly, allowing external mutation; in the WriteOptions(Builder builder) constructor make a defensive copy of builder.typeFilter (e.g., new HashSet<>(builder.typeFilter) or Collections.emptySet() when null) and assign that to this.typeFilter, and update the getTypeFilter() accessor to return an unmodifiable view (Collections.unmodifiableSet(this.typeFilter)) to preserve immutability; reference the WriteOptions constructor, the typeFilter field, the Builder.typeFilter and the getTypeFilter() method when applying the change.src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/ConfigurationToJaxbConverter.java-56-59 (1)
56-59:⚠️ Potential issue | 🟡 MinorRandom UUID generation may cause non-deterministic output.
Generating a random UUID when the source UUID is missing makes the output non-reproducible across runs. Consider logging a warning or throwing an exception instead, or accepting the UUID as a parameter.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/ConfigurationToJaxbConverter.java` around lines 56 - 59, The nonEmptyUuid method in ConfigurationToJaxbConverter currently generates a random UUID when input is null/blank, causing non-deterministic output; change this to fail fast instead: remove random UUID generation and throw an IllegalArgumentException (or IllegalStateException) with a clear message when uuid is null or blank, and optionally log a warning before throwing; update any callers of nonEmptyUuid to handle or propagate this exception so missing UUIDs are surfaced instead of silently inserting random values.src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/ChartOfAccountsToJaxbConverter.java-45-51 (1)
45-51:⚠️ Potential issue | 🟡 MinorIncomplete property mapping compared to other converters.
The
buildPropertiesmethod only setsname,synonym, andcomment. Other converters (e.g.,AccountingRegisterToJaxbConverter) set many additional default properties likeobjectBelonging,useStandardCommands,standardAttributes, etc. This inconsistency may cause validation errors or incomplete XML output.💡 Consider adding standard default properties
private static ChartOfAccountsProperties buildProperties(ChartOfAccounts coa) { ChartOfAccountsProperties p = FACTORY.createChartOfAccountsProperties(); p.setName(coa.getName()); p.setSynonym(JaxbWriteDefaults.localStringType(JaxbWriteUtils.contentForLocalString(coa.getSynonym()))); p.setComment(coa.getComment() != null ? coa.getComment() : ""); + p.setObjectBelonging(JaxbWriteDefaults.objectBelongingNative()); + p.setUseStandardCommands(false); + // Add other standard defaults as needed return p; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/ChartOfAccountsToJaxbConverter.java` around lines 45 - 51, The buildProperties method in ChartOfAccountsToJaxbConverter only sets name, synonym and comment; update ChartOfAccountsToJaxbConverter.buildProperties to populate the same standard/default JAXB fields other converters set (for example see AccountingRegisterToJaxbConverter): set objectBelonging, useStandardCommands, standardAttributes, useStandardAccounting, standardAccumulation, and any other default boolean/string/list properties your other converters initialize; use the same helper utilities (JaxbWriteDefaults.* and JaxbWriteUtils.contentForLocalString) to create default values and local strings so the ChartOfAccountsProperties object matches the shape produced by the other converters and avoids validation/serialization gaps.src/test/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/DesignerJaxbWriterTest.java-97-103 (1)
97-103:⚠️ Potential issue | 🟡 MinorAvoid filesystem writes outside
@TempDirin negative-path test.At Line 102, using
Path.of("out.xml")ties the test to process working directory and can create flaky side effects. Prefer@TempDir-scoped output even when expecting an exception.Suggested fix
- void writeUnsupportedTypeThrows() { + void writeUnsupportedTypeThrows(`@TempDir` Path tempDir) { ... - assertThatThrownBy(() -> MDClassesJaxbWriter.writeObjectJaxb(Path.of("out.xml"), mdo)) + Path out = tempDir.resolve("out.xml"); + assertThatThrownBy(() -> MDClassesJaxbWriter.writeObjectJaxb(out, mdo)) .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("does not support type"); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/test/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/DesignerJaxbWriterTest.java` around lines 97 - 103, The test writeUnsupportedTypeThrows should avoid writing to the process CWD; update the test to accept a JUnit `@TempDir` Path parameter (e.g., Path tempDir) and replace the hardcoded Path.of("out.xml") when calling MDClassesJaxbWriter.writeObjectJaxb with tempDir.resolve("out.xml") so the attempted write/exception is scoped to the temporary directory while preserving the assertThatThrownBy(...).isInstanceOf(IllegalArgumentException.class) behavior.src/main/xsd/v8.3.27/v8.1c.ru-8.2-managed-application-logform.xsd-1239-1258 (1)
1239-1258:⚠️ Potential issue | 🟡 MinorAdd type declarations to untyped attributes in
GanttChartFieldData.Lines 1254-1257 define four attributes without type specifications:
valuesSelectionModeintervalsSelectionModeshowHorizontalLinesFlagshowVerticalLinesFlagWithout explicit types, these default to
xs:anySimpleType. Based on naming conventions elsewhere in this schema, consider adding types:Suggested fix
- <xs:attribute name="valuesSelectionMode"/> - <xs:attribute name="intervalsSelectionMode"/> - <xs:attribute name="showHorizontalLinesFlag"/> - <xs:attribute name="showVerticalLinesFlag"/> + <xs:attribute name="valuesSelectionMode" type="tns:GanttChartValuesSelectionMode"/> + <xs:attribute name="intervalsSelectionMode" type="tns:GanttChartIntervalsSelectionMode"/> + <xs:attribute name="showHorizontalLinesFlag" type="xs:boolean"/> + <xs:attribute name="showVerticalLinesFlag" type="xs:boolean"/>If this matches the original 1C:Enterprise schema exactly, keep as-is for compatibility.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/xsd/v8.3.27/v8.1c.ru-8.2-managed-application-logform.xsd` around lines 1239 - 1258, The four untyped attributes on the GanttChartFieldData complexType need explicit types: update the attributes valuesSelectionMode and intervalsSelectionMode to use the schema's selection-mode type (e.g. tns:SelectionMode or the equivalent selection enum used elsewhere) and set showHorizontalLinesFlag and showVerticalLinesFlag to xs:boolean; modify the attributes named valuesSelectionMode, intervalsSelectionMode, showHorizontalLinesFlag and showVerticalLinesFlag inside the GanttChartFieldData complexType accordingly (or if a different specific enum type exists for value/interval selection in this XSD, use that existing tns:... type).
🧹 Nitpick comments (21)
src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/SettingsStorageToJaxbConverter.java (1)
32-41: Add null validation for consistency.Same recommendation: add null check for
ssparameter.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/SettingsStorageToJaxbConverter.java` around lines 32 - 41, The toMetaDataObject(SettingsStorage ss) method in SettingsStorageToJaxbConverter lacks a null check for the ss parameter; add validation at the start of the method to handle null input (e.g., throw IllegalArgumentException or return a sensible default) so subsequent calls like ss.getUuid() and buildProperties(ss) cannot NPE; update the method signature body in SettingsStorageToJaxbConverter.toMetaDataObject to perform this null check and document the behavior (exception type or return behavior) consistently with other converters.src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/LanguageToJaxbConverter.java (1)
32-40: Add null validation forlanguageparameter.Consistent with other converters, add a null guard.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/LanguageToJaxbConverter.java` around lines 32 - 40, Add a null guard at the start of LanguageToJaxbConverter.toMetaDataObject to validate the language parameter (consistent with other converters); e.g., call Objects.requireNonNull(language, "language") or throw an IllegalArgumentException when language is null, then proceed with existing logic that creates MetaDataObject, sets version, creates and populates the inner Language (inner.setUuid(...) and inner.setProperties(...)), and returns root.src/main/xsd/v8.5/v8.1c.ru-8.2-managed-application-modules.xsd (2)
71-71: Add trailing newline.The file is missing a trailing newline at the end, which is a common convention for text files and helps with version control diffs.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/xsd/v8.5/v8.1c.ru-8.2-managed-application-modules.xsd` at line 71, The file ends with the closing XML tag </xs:schema> but lacks a trailing newline; open the file containing the </xs:schema> element and add a single newline character after that closing tag so the file ends with a trailing newline.
1-1: Remove UTF-8 BOM from XSD file.The file starts with a UTF-8 BOM (
). While technically valid, BOMs in XML can cause issues with some parsers and tools. Consider removing it for broader compatibility.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/xsd/v8.5/v8.1c.ru-8.2-managed-application-modules.xsd` at line 1, Remove the leading UTF-8 BOM character from the top of the XSD so the file begins directly with the XML declaration "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; open the file (v8.1c.ru-8.2-managed-application-modules.xsd), delete the invisible BOM character preceding the XML declaration, save the file with UTF-8 encoding without BOM to ensure parsers and tools don't choke on the hidden byte-order-mark.src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/JaxbWriteDefaults.java (1)
35-35: Consider consolidating duplicateDEFAULT_LANGconstant.
DEFAULT_LANG = "ru"is also defined inJaxbWriteUtils(line 18). Consider extracting this to a single shared location to avoid duplication and ensure consistency if the default language ever changes.♻️ Suggested approach
Either expose one constant publicly and reference it from the other class, or extract to a common constants class:
public final class JaxbWriteDefaults { public static final String DEFAULT_FORMAT_VERSION = "2.20"; - private static final String DEFAULT_LANG = "ru"; + public static final String DEFAULT_LANG = "ru";Then in
JaxbWriteUtils:- private static final String DEFAULT_LANG = "ru"; + // Use JaxbWriteDefaults.DEFAULT_LANG instead🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/JaxbWriteDefaults.java` at line 35, There are duplicate DEFAULT_LANG = "ru" constants in JaxbWriteDefaults (DEFAULT_LANG) and JaxbWriteUtils; consolidate by exposing one shared constant and removing the other: either make DEFAULT_LANG public in one class (e.g., JaxbWriteUtils.DEFAULT_LANG) and reference it from the other, or create a new common constant holder (e.g., class JaxbWriteConstants.DEFAULT_LANG) and update both JaxbWriteDefaults and JaxbWriteUtils to use that single source of truth, then delete the duplicate definition.src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/ReportToJaxbConverter.java (2)
1-62: Consider extracting common converter logic.This converter shares nearly identical structure with
DataProcessorToJaxbConverterand likely other converters. While the current approach is acceptable, a future refactor could extract common patterns (null-safe UUID, properties building, form iteration) into a base helper to reduce boilerplate.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/ReportToJaxbConverter.java` around lines 1 - 62, Extract shared conversion patterns into a reusable helper or base class to reduce duplication between ReportToJaxbConverter and DataProcessorToJaxbConverter: pull out null-safe UUID handling (used in toMetaDataObject), local-string wrapping (JaxbWriteDefaults.localStringType + JaxbWriteUtils.contentForLocalString used in buildProperties), null-safe comment/name defaults, and collection-to-JAXB-list iteration (as in buildChildObjects iterating r.getForms()). Create a small utility class (e.g., JaxbConverterUtils or an abstract BaseToJaxbConverter) with methods like safeUuid(String), safeString(String), toLocalString(String), and addCollectionItems(Collection, Consumer<String>) then update ReportToJaxbConverter (toMetaDataObject, buildProperties, buildChildObjects) and DataProcessorToJaxbConverter to delegate to these helpers.
34-43: Same null validation concern asDataProcessorToJaxbConverter.Consider adding a null guard for the
reportparameter to fail fast with a clear message rather than NPE.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/ReportToJaxbConverter.java` around lines 34 - 43, The toMetaDataObject(Report report) method lacks a null guard for its report parameter, which can cause a generic NPE; add an explicit null check at the start of toMetaDataObject and throw an IllegalArgumentException (or NullPointerException with a clear message) when report is null so callers fail fast with a descriptive error; update the method that constructs the MetaDataObject and references to report.getUuid(), buildProperties(report), and buildChildObjects(report) accordingly to rely on the validated non-null report.src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/DataProcessorToJaxbConverter.java (1)
34-43: Consider adding null check for input parameter.The method doesn't validate that
dpis non-null. ANullPointerExceptionwill occur atdp.getUuid()if null is passed. Consider adding an early guard or using@NonNullannotation per coding guidelines.🛡️ Proposed fix
public static MetaDataObject toMetaDataObject(DataProcessor dp) { + if (dp == null) { + throw new IllegalArgumentException("DataProcessor cannot be null"); + } MetaDataObject root = FACTORY.createMetaDataObject();Or use
Objects.requireNonNull(dp, "DataProcessor cannot be null").🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/DataProcessorToJaxbConverter.java` around lines 34 - 43, Add a null-check at the start of toMetaDataObject to validate the DataProcessor argument (dp) before dereferencing it: ensure dp is non-null (e.g., use Objects.requireNonNull(dp, "DataProcessor cannot be null") or an explicit if (dp == null) throw/return) so calls like dp.getUuid(), buildProperties(dp) and buildChildObjects(dp) don't cause a NPE; update toMetaDataObject accordingly and keep existing behavior of creating FACTORY.createMetaDataObject() and the inner DataProcessor population.src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/BusinessProcessToJaxbConverter.java (1)
43-61: Consider importing JAXB types for consistency.This converter uses fully qualified class names (
com.github._1c_syntax.bsl.mdclasses.jaxb.mdclasses.BusinessProcessProperties, etc.) while other converters in this PR import these types. Using imports would improve readability and maintain consistency across the codebase.♻️ Suggested imports
import com.github._1c_syntax.bsl.mdo.BusinessProcess; import com.github._1c_syntax.bsl.mdo.children.ObjectForm; +import com.github._1c_syntax.bsl.mdclasses.jaxb.mdclasses.BusinessProcessChildObjects; +import com.github._1c_syntax.bsl.mdclasses.jaxb.mdclasses.BusinessProcessProperties; import com.github._1c_syntax.bsl.mdclasses.jaxb.mdclasses.MetaDataObject; import com.github._1c_syntax.bsl.mdclasses.jaxb.mdclasses.ObjectFactory;Then simplify the method signatures:
- private static com.github._1c_syntax.bsl.mdclasses.jaxb.mdclasses.BusinessProcessProperties buildProperties(BusinessProcess bp) { - com.github._1c_syntax.bsl.mdclasses.jaxb.mdclasses.BusinessProcessProperties p = - FACTORY.createBusinessProcessProperties(); + private static BusinessProcessProperties buildProperties(BusinessProcess bp) { + BusinessProcessProperties p = FACTORY.createBusinessProcessProperties();🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/BusinessProcessToJaxbConverter.java` around lines 43 - 61, Replace the fully-qualified JAXB types with imports and simplify the method signatures/locals: add imports for BusinessProcessProperties and BusinessProcessChildObjects (and any other mdclasses types used), then update buildProperties and buildChildObjects to return and declare variables using the imported types (e.g., BusinessProcessProperties p = FACTORY.createBusinessProcessProperties(); and BusinessProcessChildObjects childObjects = FACTORY.createBusinessProcessChildObjects();), and also update any other fully-qualified mdclasses usages in this file to the imported short names to match other converters.src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/ExchangePlanToJaxbConverter.java (1)
21-62: LGTM, but consider extracting shared conversion logic.This converter (and 6+ others in this PR) repeats nearly identical patterns:
- Root creation with version default
- UUID null-to-empty fallback
- Properties building (name, synonym via
localStringType, comment null fallback)- ChildObjects forms iteration
A shared abstract base or helper class could reduce duplication and ensure consistent behavior. For example:
// Example helper in JaxbWriteUtils public static void populateCommonProperties( Consumer<String> nameSetter, Consumer<LocalStringType> synonymSetter, Consumer<String> commentSetter, String name, LocalString synonym, String comment) { nameSetter.accept(name); synonymSetter.accept(JaxbWriteDefaults.localStringType( contentForLocalString(synonym))); commentSetter.accept(comment != null ? comment : ""); }This is a recommended refactor that could be deferred if preferred.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/ExchangePlanToJaxbConverter.java` around lines 21 - 62, The converter ExchangePlanToJaxbConverter duplicates common JAXB conversion logic (root/version setup, UUID null->empty, properties mapping, forms iteration); refactor by extracting shared helper(s) (e.g., in JaxbWriteUtils) to centralize: a method to create/populate the MetaDataObject root with version and setExchangePlan, a helper to map UUID with ep.getUuid() -> "" fallback, and a populateCommonProperties helper to replace buildProperties (handling name, synonym via JaxbWriteDefaults.localStringType(JaxbWriteUtils.contentForLocalString(...)), and comment null->""), plus a helper to append forms for buildChildObjects; then update toMetaDataObject, buildProperties and buildChildObjects to call these helpers so behavior is consistent across converters like ExchangePlanToJaxbConverter.src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/DesignerNamespacePrefixMapper.java (1)
20-26: Redundant ternary expression.Line 25
suggestion != null ? suggestion : nullalways returnssuggestion. Simplify:♻️ Proposed fix
`@Override` public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) { if (MDCLASSES_NS.equals(namespaceUri)) { return requirePrefix ? "v8" : ""; } - return suggestion != null ? suggestion : null; + return suggestion; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/DesignerNamespacePrefixMapper.java` around lines 20 - 26, In DesignerNamespacePrefixMapper's getPreferredPrefix method the return expression "suggestion != null ? suggestion : null" is redundant; simplify by returning suggestion directly. Update the method so that when MDCLASSES_NS.equals(namespaceUri) it returns requirePrefix ? "v8" : "" and otherwise return suggestion; keep use of MDCLASSES_NS and method name getPreferredPrefix unchanged.src/test/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/JaxbWriterExampleTest.java (1)
46-49: Consider cleaning up output directory before test run.Without cleanup, stale files from previous runs may cause false positives. Add a
@BeforeEachor cleanup in the test:♻️ Proposed cleanup addition
import org.junit.jupiter.api.BeforeEach; import org.apache.commons.io.FileUtils; `@BeforeEach` void setUp() throws Exception { if (Files.exists(OUTPUT_DIR)) { FileUtils.deleteDirectory(OUTPUT_DIR.toFile()); } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/test/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/JaxbWriterExampleTest.java` around lines 46 - 49, Add a test cleanup that deletes the OUTPUT_DIR before each run to avoid stale files affecting writeExampleToBuildDir; implement a `@BeforeEach` method (e.g., setUp) that checks Files.exists(OUTPUT_DIR) and if present uses FileUtils.deleteDirectory(OUTPUT_DIR.toFile()) (or equivalent safe recursive delete) so MDClassesJaxbWriter.writeConfigurationToFolder and the test method run against a clean directory.build.gradle.kts (1)
105-122: Consider ensuring output directory exists before XJC runs.The XJC task may fail on first run if
build/generated/sources/xjc-mdclassesdoesn't exist. Add directory creation indoFirst:♻️ Proposed fix
tasks.register<JavaExec>("xjcMDClasses") { group = "Build" description = "Generate JAXB classes from v8.5 MDClasses XSD" classpath = xjc mainClass = "com.sun.tools.xjc.Driver" workingDir = xsdV85Dir.asFile doFirst { + xjcOutputMDClasses.get().asFile.mkdirs() args( "-extension", "-catalog", "catalog.xml",🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@build.gradle.kts` around lines 105 - 122, The xjcMDClasses JavaExec task can fail if the output directory referenced by xjcOutputMDClasses doesn't exist; modify the task's doFirst block in the xjcMDClasses registration to create the destination directory before invoking XJC (use xjcOutputMDClasses.get().asFile or its absolutePath) so the directory exists, then proceed to set args and run; ensure you call mkdirs() (or equivalent) on that File before setting args.src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/InformationRegisterToJaxbConverter.java (1)
45-51: Converter appears incomplete — only basic properties mapped.The
buildPropertiesmethod only mapsname,synonym, andcomment. Information registers typically have many more properties (periodicity, write mode, dimensions, resources, etc.). If this is intentional for an MVP, consider adding a TODO comment.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/InformationRegisterToJaxbConverter.java` around lines 45 - 51, The buildProperties method currently only maps name, synonym and comment for InformationRegister -> InformationRegisterProperties; update buildProperties (in InformationRegisterToJaxbConverter) to map the remaining register properties (e.g., periodicity, writeMode, dimensions, resources, accumulationType, owner, and any flags present on InformationRegister) into the corresponding setters on InformationRegisterProperties, or if this reduced mapping is intentional for an MVP add a clear TODO comment inside buildProperties stating which fields are intentionally omitted and referencing the missing property names so future work can complete them. Ensure you reference the InformationRegister getters and the InformationRegisterProperties setters when adding mappings or the TODO.src/main/xsd/v8.3.27/v8.1c.ru-8.2-data-bsl.xsd (1)
1-2: Remove UTF-8 BOM character at file start.The file begins with a UTF-8 BOM (
), which may cause issues with some XML parsers or tooling. Consider saving without BOM.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/xsd/v8.3.27/v8.1c.ru-8.2-data-bsl.xsd` around lines 1 - 2, The file begins with a UTF-8 BOM character before the XML declaration which can break XML parsers; open the file that contains the XML declaration "<?xml version="1.0" encoding="UTF-8"?>" and remove the leading BOM character so the file starts exactly with the "<?xml" token (save the file without BOM / as UTF-8 without signature).src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/DesignerJaxbWriter.java (1)
54-88: Extract magic ClassId constants.The hardcoded ClassId GUIDs (e.g.,
9cd510cd-abfc-11d4-9434-004095e12fc7) are platform constants. Consider extracting them to named constants with documentation explaining their purpose for maintainability.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/DesignerJaxbWriter.java` around lines 54 - 88, The hardcoded GUID strings inside buildConfigurationInternalInfoBlock() should be extracted into well-named static final constants (e.g., CLASS_ID_COMMONS, CLASS_ID_SOME_NAME) with a Javadoc comment explaining each GUID's platform meaning; replace the literal GUID values in the XML template with those constants (referencing buildConfigurationInternalInfoBlock and the xr:ClassId occurrences) and keep the UUID.randomUUID() objectId generation as-is—this improves maintainability and documents the platform constants.src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/DesignerPathResolver.java (1)
48-53: Path manipulation can be simplified usingPathAPI.The combination of
FilenameUtils.getFullPathNoEndSeparatorandFilenameUtils.getBaseNamewithPaths.getis verbose. ThePathAPI can handle this more elegantly.Simplified path resolution
if (type == MDOType.SUBSYSTEM && parentSubsystemPath != null) { - Path parentDir = Paths.get( - FilenameUtils.getFullPathNoEndSeparator(parentSubsystemPath.toString()), - FilenameUtils.getBaseName(parentSubsystemPath.toString())); + // Parent directory + base name without extension + Path parentDir = parentSubsystemPath.resolveSibling( + parentSubsystemPath.getFileName().toString().replace(".xml", "")); return parentDir.resolve(type.groupName()).resolve(name + ".xml"); }Or even more robustly:
String baseName = parentSubsystemPath.getFileName().toString(); int dotIndex = baseName.lastIndexOf('.'); if (dotIndex > 0) { baseName = baseName.substring(0, dotIndex); } Path parentDir = parentSubsystemPath.resolveSibling(baseName);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/DesignerPathResolver.java` around lines 48 - 53, In DesignerPathResolver where you handle MDOType.SUBSYSTEM (the block referencing parentSubsystemPath, parentDir, FilenameUtils.*), replace the FilenameUtils/Paths.get dance with pure Path API: obtain the file name via parentSubsystemPath.getFileName().toString(), strip the extension by finding lastIndexOf('.') (if present) to produce baseName, compute parentDir using parentSubsystemPath.resolveSibling(baseName), then continue with parentDir.resolve(type.groupName()).resolve(name + ".xml"); update the variables type, parentSubsystemPath, parentDir, and name usage accordingly.src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/CalculationRegisterToJaxbConverter.java (1)
75-83: Consider exporting additional child object types.The
buildChildObjectsmethod currently only exports forms. CalculationRegisters may also have resources, dimensions, and recalculations that could need export. If this is intentional for the initial implementation scope, consider adding a TODO comment for future expansion.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/CalculationRegisterToJaxbConverter.java` around lines 75 - 83, The buildChildObjects method currently only handles forms (CalculationRegisterChildObjects co built from CalculationRegister.getForms()); update it to also export other child object types present on CalculationRegister — e.g., iterate and add names from getResources(), getDimensions(), and getRecalculations() into the appropriate lists on CalculationRegisterChildObjects (using FACTORY as needed) or, if intentionally omitted for now, add a clear TODO comment inside buildChildObjects referencing the missing types (resources, dimensions, recalculations) so future maintainers know to implement exporting for those collections.src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/ConfigurationToJaxbConverter.java (1)
107-127: Fallback tovalues()[0]is fragile.Using
values()[0]as the default depends on enum declaration order, which could change. Consider using an explicit named constant for the default value.♻️ Proposed fix using explicit defaults
private static com.github._1c_syntax.bsl.mdclasses.jaxb.v8_3_xcf_enums.CompatibilityMode safeCompatibilityMode(String value) { if (value == null || value.isEmpty()) { - return com.github._1c_syntax.bsl.mdclasses.jaxb.v8_3_xcf_enums.CompatibilityMode.values()[0]; + return com.github._1c_syntax.bsl.mdclasses.jaxb.v8_3_xcf_enums.CompatibilityMode.DONT_USE; // or appropriate default } try { return com.github._1c_syntax.bsl.mdclasses.jaxb.v8_3_xcf_enums.CompatibilityMode.fromValue(value); } catch (IllegalArgumentException e) { - return com.github._1c_syntax.bsl.mdclasses.jaxb.v8_3_xcf_enums.CompatibilityMode.values()[0]; + return com.github._1c_syntax.bsl.mdclasses.jaxb.v8_3_xcf_enums.CompatibilityMode.DONT_USE; } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/ConfigurationToJaxbConverter.java` around lines 107 - 127, Replace the fragile values()[0] fallback in safeCompatibilityMode and safeScriptVariant with an explicit, named default enum constant (e.g., com.github._1c_syntax.bsl.mdclasses.jaxb.v8_3_xcf_enums.CompatibilityMode.DEFAULT and com.github._1c_syntax.bsl.mdclasses.jaxb.v8_3_xcf_enums.ScriptVariant.DEFAULT); if such a constant doesn't exist in the enum definitions, add a clear default constant to each enum and use that constant in both safeCompatibilityMode(String) and safeScriptVariant(String) instead of values()[0], keeping the current null/empty check and try/catch behavior.src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/MDClassesJaxbWriter.java (2)
133-207: Annotate the public null contract.
configuration,options, andparentSubsystemPathare intentionally nullable here, but the signatures leave that implicit. Adding@NonNull/@Nullablewould make the contract obvious to callers and tooling.As per coding guidelines "Use
@Nullableand@NonNullannotations from org.jspecify for null safety".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/MDClassesJaxbWriter.java` around lines 133 - 207, Add org.jspecify nullability annotations to make nullable/nonnull contracts explicit: mark parameters that may be null as `@Nullable` (e.g., the Configuration parameter in writeObjectJaxb(Path, MD, Configuration) and writeConfigurationToFolder(Path, Configuration, WriteOptions), the options parameter in writeConfigurationToFolder, and parentSubsystemPath in getPathForObject(Path, MD, Path)), and mark non-null return values and non-null parameters as `@NonNull` where appropriate (e.g., Path rootPath, MD md, Configuration in writeConfigurationJaxb). Import annotations from org.jspecify.annotations and update the method signatures for writeObjectJaxb, writeConfigurationJaxb, getPathForObject (both overloads) and writeConfigurationToFolder to reflect these annotations consistently.
40-40: Refactor the writer API to be serializer-neutral.
MDClassesJaxbWriter, method nameswrite*Jaxb, and theJAXBExceptionchecked exception expose the serialization implementation as part of the public contract. While the implementation is functional, the API design couples clients to JAXB. Consider creating a neutral facade (e.g.,MDClassesWriterorConfigurationWriter) with internal exception translation, keeping JAXB details in the.jaxb.writesubpackage. This aligns with the codebase pattern where XStream is abstracted in reader implementations.Also applies to: lines 55–55, 133–163
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/MDClassesJaxbWriter.java` at line 40, MDClassesJaxbWriter and its write*Jaxb methods leak JAXB into the public API (exposed via method names and the checked JAXBException); refactor by introducing a serializer-neutral interface/class (suggest MDClassesWriter or ConfigurationWriter) that declares generic write methods (e.g., write(MDClasses, OutputStream) or write(Configuration, Writer)) and translate/wrap JAXBException into an unchecked or domain-specific exception inside the .jaxb.write package; move JAXB-specific implementation into the existing .jaxb.write subpackage (keep MDClassesJaxbWriter as an internal adapter implementing the new interface) and update callers to depend on the neutral MDClassesWriter contract rather than JAXB types or write*Jaxb method names.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 7015a8be-3bd5-4849-b97d-0308c24e10c1
📒 Files selected for processing (68)
build.gradle.ktssrc/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/AccountingRegisterToJaxbConverter.javasrc/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/AccumulationRegisterToJaxbConverter.javasrc/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/BusinessProcessToJaxbConverter.javasrc/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/CalculationRegisterToJaxbConverter.javasrc/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/CatalogToJaxbConverter.javasrc/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/ChartOfAccountsToJaxbConverter.javasrc/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/ChartOfCalculationTypesToJaxbConverter.javasrc/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/ChartOfCharacteristicTypesToJaxbConverter.javasrc/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/CommandGroupToJaxbConverter.javasrc/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/CommonModuleToJaxbConverter.javasrc/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/ConfigurationToJaxbConverter.javasrc/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/DataProcessorToJaxbConverter.javasrc/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/DesignerJaxbWriter.javasrc/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/DesignerNamespacePrefixMapper.javasrc/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/DesignerPathResolver.javasrc/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/DocumentJournalToJaxbConverter.javasrc/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/DocumentToJaxbConverter.javasrc/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/EnumToJaxbConverter.javasrc/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/ExchangePlanToJaxbConverter.javasrc/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/FilterCriterionToJaxbConverter.javasrc/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/FormToJaxbConverter.javasrc/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/InformationRegisterToJaxbConverter.javasrc/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/JaxbWriteDefaults.javasrc/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/JaxbWriteUtils.javasrc/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/LanguageToJaxbConverter.javasrc/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/MDClassesJaxbWriter.javasrc/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/ReportToJaxbConverter.javasrc/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/RoleToJaxbConverter.javasrc/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/SettingsStorageToJaxbConverter.javasrc/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/SubsystemToJaxbConverter.javasrc/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/TaskToJaxbConverter.javasrc/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/WriteOptions.javasrc/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/package-info.javasrc/main/xsd/v8.3.27/catalog.xmlsrc/main/xsd/v8.3.27/v8.1c.ru-8.1-data-core.xsdsrc/main/xsd/v8.3.27/v8.1c.ru-8.1-data-enterprise.xsdsrc/main/xsd/v8.3.27/v8.1c.ru-8.1-data-ui.xsdsrc/main/xsd/v8.3.27/v8.1c.ru-8.2-data-bsl.xsdsrc/main/xsd/v8.3.27/v8.1c.ru-8.2-data-spreadsheet.xsdsrc/main/xsd/v8.3.27/v8.1c.ru-8.2-managed-application-cmi.xsdsrc/main/xsd/v8.3.27/v8.1c.ru-8.2-managed-application-core.xsdsrc/main/xsd/v8.3.27/v8.1c.ru-8.2-managed-application-logform.xsdsrc/main/xsd/v8.3.27/v8.1c.ru-8.2-managed-application-modules.xsdsrc/main/xsd/v8.3.27/v8.1c.ru-8.2-uobjects.xsdsrc/main/xsd/v8.3.27/v8.1c.ru-8.3-MDClasses.xsdsrc/main/xsd/v8.3.27/v8.1c.ru-8.3-xcf-enums.xsdsrc/main/xsd/v8.3.27/v8.1c.ru-8.3-xcf-predef.xsdsrc/main/xsd/v8.3.27/v8.1c.ru-8.3-xcf-readable.xsdsrc/main/xsd/v8.5/bindings.xjbsrc/main/xsd/v8.5/catalog.xmlsrc/main/xsd/v8.5/v8.1c.ru-8.1-data-core.xsdsrc/main/xsd/v8.5/v8.1c.ru-8.1-data-enterprise.xsdsrc/main/xsd/v8.5/v8.1c.ru-8.1-data-ui.xsdsrc/main/xsd/v8.5/v8.1c.ru-8.2-data-bsl.xsdsrc/main/xsd/v8.5/v8.1c.ru-8.2-data-spreadsheet.xsdsrc/main/xsd/v8.5/v8.1c.ru-8.2-managed-application-cmi.xsdsrc/main/xsd/v8.5/v8.1c.ru-8.2-managed-application-core.xsdsrc/main/xsd/v8.5/v8.1c.ru-8.2-managed-application-logform.xsdsrc/main/xsd/v8.5/v8.1c.ru-8.2-managed-application-modules.xsdsrc/main/xsd/v8.5/v8.1c.ru-8.2-uobjects.xsdsrc/main/xsd/v8.5/v8.1c.ru-8.3-MDClasses.xsdsrc/main/xsd/v8.5/v8.1c.ru-8.3-xcf-enums.xsdsrc/main/xsd/v8.5/v8.1c.ru-8.3-xcf-predef.xsdsrc/main/xsd/v8.5/v8.1c.ru-8.3-xcf-readable.xsdsrc/test/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/DesignerJaxbWriterTest.javasrc/test/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/DesignerPathResolverTest.javasrc/test/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/JaxbWriterExampleTest.java
| p.setUseStandardCommands(false); | ||
| p.setDefaultListForm(""); | ||
| p.setAuxiliaryListForm(""); | ||
| p.setRegisterType(JaxbWriteDefaults.accumulationRegisterTypeBalance()); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check if AccumulationRegister has registerType property
rg -n "getRegisterType|registerType" --type java -g "**/mdo/AccumulationRegister.java"Repository: 1c-syntax/mdclasses
Length of output: 45
🏁 Script executed:
#!/bin/bash
# First, let's find the AccumulationRegister class
find . -name "AccumulationRegister.java" -type f 2>/dev/null | head -20Repository: 1c-syntax/mdclasses
Length of output: 134
🏁 Script executed:
#!/bin/bash
# List files in the mdo directory to understand structure
fd -t f "AccumulationRegister" | head -20Repository: 1c-syntax/mdclasses
Length of output: 392
🏁 Script executed:
#!/bin/bash
# Check the converter file to see the current implementation
cat -n src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/AccumulationRegisterToJaxbConverter.java | head -80Repository: 1c-syntax/mdclasses
Length of output: 4014
🏁 Script executed:
#!/bin/bash
# Check AccumulationRegister class for registerType property
cat -n src/main/java/com/github/_1c_syntax/bsl/mdo/AccumulationRegister.java | head -100Repository: 1c-syntax/mdclasses
Length of output: 3865
🏁 Script executed:
#!/bin/bash
# Search for registerType in AccumulationRegister class
rg -n "registerType" src/main/java/com/github/_1c_syntax/bsl/mdo/AccumulationRegister.javaRepository: 1c-syntax/mdclasses
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Continue reading AccumulationRegister to see all fields
cat -n src/main/java/com/github/_1c_syntax/bsl/mdo/AccumulationRegister.java | tail -n +100 | head -100Repository: 1c-syntax/mdclasses
Length of output: 745
🏁 Script executed:
#!/bin/bash
# Check the Register interface
find . -name "Register.java" -type f 2>/dev/null | xargs cat -n | head -100Repository: 1c-syntax/mdclasses
Length of output: 1830
🏁 Script executed:
#!/bin/bash
# Check if any other register types have registerType property
rg -n "registerType" --type java | head -30Repository: 1c-syntax/mdclasses
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Search for AccumulationRegisterType or similar enum
rg -n "registerType|RegisterType|Balance|Turnovers" --type java | grep -i "accumulation\|register.*type" | head -40Repository: 1c-syntax/mdclasses
Length of output: 847
🏁 Script executed:
#!/bin/bash
# Check the test file to understand the expected behavior
cat src/test/java/com/github/_1c_syntax/bsl/mdo/AccumulationRegisterTest.javaRepository: 1c-syntax/mdclasses
Length of output: 2292
🏁 Script executed:
#!/bin/bash
# Check the JSON fixture file to see if registerType is in the source data
cat src/test/resources/fixtures/mdclasses/AccumulationRegisters.РегистрНакопления1.json | head -100Repository: 1c-syntax/mdclasses
Length of output: 3464
🏁 Script executed:
#!/bin/bash
# Search for how AccumulationRegisterType enum is used elsewhere
rg -n "AccumulationRegisterType" --type java -A 3 -B 1Repository: 1c-syntax/mdclasses
Length of output: 1794
🏁 Script executed:
#!/bin/bash
# Check if registerType is parsed from the 1C metadata files anywhere
rg -n "registerType" --type java -B 5 -A 5 | head -100Repository: 1c-syntax/mdclasses
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Look for AccumulationRegisterType enum values
find . -name "AccumulationRegisterType.java" -type f 2>/dev/null | xargs cat -nRepository: 1c-syntax/mdclasses
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Search for AccumulationRegisterType in all file types
find . -name "*AccumulationRegisterType*" -type f 2>/dev/nullRepository: 1c-syntax/mdclasses
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Check what methods are available in AccumulationRegisterType enum
rg -n "BALANCE|TURNOVERS" --type java | head -20Repository: 1c-syntax/mdclasses
Length of output: 534
🏁 Script executed:
#!/bin/bash
# Look at how Designer XML is parsed from the input side (read operations)
find . -name "*read*" -type d | head -10Repository: 1c-syntax/mdclasses
Length of output: 160
🏁 Script executed:
#!/bin/bash
# Check the reader directory for AccumulationRegister parsing
find ./src/main/java/com/github/_1c_syntax/bsl/reader -name "*Accumulation*" -type f 2>/dev/nullRepository: 1c-syntax/mdclasses
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Look at the write converters to understand the pattern - check other register converters
find ./src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write -name "*RegisterToJaxbConverter.java" -type f 2>/dev/null | head -10Repository: 1c-syntax/mdclasses
Length of output: 474
🏁 Script executed:
#!/bin/bash
# Check what registerType value should be for different register types
rg -n "setRegisterType\|RegisterType" --type java src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/ -B 2 -A 2Repository: 1c-syntax/mdclasses
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Check InformationRegisterToJaxbConverter to understand the pattern
cat -n ./src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/InformationRegisterToJaxbConverter.java | head -80Repository: 1c-syntax/mdclasses
Length of output: 2968
🏁 Script executed:
#!/bin/bash
# Check AccountingRegisterToJaxbConverter which might have registerType
cat -n ./src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/AccountingRegisterToJaxbConverter.java | grep -A 5 -B 5 "registerType\|RegisterType"Repository: 1c-syntax/mdclasses
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Check if there's a field or property related to register type in any 1C metadata format
rg -n "registerType\|RegisterType\|balance\|turnovers" --type java src/main/java/com/github/_1c_syntax/bsl/reader/ -B 2 -A 2 | head -60Repository: 1c-syntax/mdclasses
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Check the JAXB generated classes to see what AccumulationRegisterType values exist
find . -path "*/jaxb/v8_3_xcf_enums*" -name "AccumulationRegisterType*" -type f 2>/dev/nullRepository: 1c-syntax/mdclasses
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Look for JAXB classes directory structure
find . -path "*/jaxb/*enums*" -type d 2>/dev/null | head -5Repository: 1c-syntax/mdclasses
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Check if there are any Designer XML examples or test files that show accumulation register structure
find . -path "*/test*" -name "*.xml" -type f 2>/dev/null | xargs grep -l "AccumulationRegister\|registerType\|balance\|turnovers" 2>/dev/null | head -10Repository: 1c-syntax/mdclasses
Length of output: 922
🏁 Script executed:
#!/bin/bash
# Check the Designer XML files for registerType values
cat ./src/test/resources/ext/designer/mdclasses_3_25/src/cf/AccumulationRegisters/РегистрНакопления1.xml | grep -A 5 -B 5 "registerType\|RegisterType" | head -50Repository: 1c-syntax/mdclasses
Length of output: 469
🏁 Script executed:
#!/bin/bash
# Check what's in the actual Designer XML accumulation register files
cat ./src/test/resources/ext/designer/mdclasses_3_25/src/cf/AccumulationRegisters/РегистрНакопления2.xml | head -100Repository: 1c-syntax/mdclasses
Length of output: 4776
🏁 Script executed:
#!/bin/bash
# Check all accumulation register XML files for registerType
grep -n "registerType" ./src/test/resources/ext/designer/mdclasses_3_25/src/cf/AccumulationRegisters/*.xmlRepository: 1c-syntax/mdclasses
Length of output: 45
RegisterType hardcoding causes data loss during round-trip conversion.
The Designer XML format supports two accumulation register types: "Balance" (остатки) and "Turnovers" (обороты). The converter hardcodes accumulationRegisterTypeBalance() at line 54, ignoring the actual registerType value from source metadata. Test fixtures confirm both types exist (РегистрНакопления1.xml has "Balance", РегистрНакопления2.xml has "Turnovers"), but the AccumulationRegister model lacks a registerType field to preserve this information, making round-trip conversion lossy.
Add registerType field to AccumulationRegister and update the converter to use the actual value.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/AccumulationRegisterToJaxbConverter.java`
at line 54, The converter currently hardcodes
JaxbWriteDefaults.accumulationRegisterTypeBalance() in
AccumulationRegisterToJaxbConverter, causing loss of the original registerType;
add a registerType field (enum or String matching Designer values, e.g.,
"Balance"/"Turnovers") to the AccumulationRegister model with getter/setter,
populate it when parsing, and then change AccumulationRegisterToJaxbConverter to
call p.setRegisterType(accumulationRegister.getRegisterType()) (or map the enum
to the correct JAXB value) instead of using the hardcoded
JaxbWriteDefaults.accumulationRegisterTypeBalance(); ensure any constructors,
equals/hashCode/serialization logic and tests are updated to account for the new
field.
| public static MetaDataObject toMetaDataObject(Catalog catalog) { | ||
| return toMetaDataObject(catalog, null); | ||
| } | ||
|
|
||
| /** | ||
| * Собирает JAXB MetaDataObject из справочника mdclasses с указанием группы команд по умолчанию. | ||
| * | ||
| * @param catalog справочник из модели mdclasses | ||
| * @param defaultCommandGroupRef MDO-ссылка группы команд (например, "CommandGroup.ГруппаКоманд1") для команд без группы | ||
| * @return корневой элемент для маршаллинга в Designer XML | ||
| */ | ||
| public static MetaDataObject toMetaDataObject(Catalog catalog, String defaultCommandGroupRef) { |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Annotate public API nullability contract.
Public converter entrypoints should explicitly declare nullability for parameters.
Proposed fix
+import org.jspecify.annotations.NonNull;
+import org.jspecify.annotations.Nullable;
...
- public static MetaDataObject toMetaDataObject(Catalog catalog) {
+ public static MetaDataObject toMetaDataObject(`@NonNull` Catalog catalog) {
return toMetaDataObject(catalog, null);
}
...
- public static MetaDataObject toMetaDataObject(Catalog catalog, String defaultCommandGroupRef) {
+ public static MetaDataObject toMetaDataObject(
+ `@NonNull` Catalog catalog,
+ `@Nullable` String defaultCommandGroupRef
+ ) {As per coding guidelines: "Use @Nullable and @NonNull annotations from org.jspecify for null safety".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/CatalogToJaxbConverter.java`
around lines 64 - 75, The public API lacks nullability annotations: annotate the
two converter entrypoints toMetaDataObject(Catalog) and
toMetaDataObject(Catalog, String defaultCommandGroupRef) using org.jspecify
annotations—mark the Catalog parameter as `@NonNull` (or `@Nullable` if null is
acceptable) and the defaultCommandGroupRef parameter as `@Nullable`, and annotate
the return type appropriately (`@NonNull` or `@Nullable`); add the corresponding
import for org.jspecify.annotations.Nullable/@NonNull at the top of
CatalogToJaxbConverter.java and adjust any callers/tests if their nullability
expectations change.
| private static CatalogProperties buildProperties(Catalog c) { | ||
| CatalogProperties p = FACTORY.createCatalogProperties(); | ||
| p.setName(c.getName()); | ||
| p.setSynonym(JaxbWriteDefaults.localStringType(JaxbWriteUtils.contentForLocalString(c.getSynonym()))); | ||
| p.setComment(c.getComment() != null ? c.getComment() : ""); | ||
| p.setObjectBelonging(JaxbWriteDefaults.objectBelongingNative()); | ||
| p.setHierarchical(false); | ||
| p.setHierarchyType(HierarchyType.HIERARCHY_FOLDERS_AND_ITEMS); | ||
| p.setLimitLevelCount(false); | ||
| p.setLevelCount(BigDecimal.ONE); | ||
| p.setFoldersOnTop(true); | ||
| p.setUseStandardCommands(true); | ||
| p.setOwners(buildOwners(c)); | ||
| p.setSubordinationUse(SubordinationUse.TO_FOLDERS_AND_ITEMS); | ||
| p.setCodeLength(BigDecimal.valueOf(9)); | ||
| p.setDescriptionLength(BigDecimal.valueOf(150)); | ||
| p.setCodeType(CatalogCodeType.STRING); | ||
| p.setCodeAllowedLength(AllowedLength.VARIABLE); | ||
| p.setCodeSeries(codeSeriesToJaxb(c.getCodeSeries())); | ||
| p.setCheckUnique(c.isCheckUnique()); | ||
| p.setAutonumbering(false); | ||
| p.setDefaultPresentation(CatalogMainPresentation.AS_DESCRIPTION); | ||
| p.setStandardAttributes(JaxbWriteDefaults.emptyStandardAttributeDescriptions()); | ||
| p.setCharacteristics(JaxbWriteDefaults.emptyCharacteristicsDescriptions()); | ||
| p.setPredefined(""); | ||
| p.setPredefinedDataUpdate(PredefinedDataUpdate.DONT_AUTO_UPDATE); | ||
| p.setEditType(EditType.IN_LIST); | ||
| p.setQuickChoice(false); | ||
| p.setChoiceMode(JaxbWriteDefaults.choiceModeFromForm()); | ||
| p.setInputByString(JaxbWriteDefaults.emptyFieldList()); | ||
| p.setSearchStringModeOnInputByString(SearchStringModeOnInputByString.ANY_PART); | ||
| p.setFullTextSearchOnInputByString(FullTextSearchOnInputByString.USE); | ||
| p.setChoiceDataGetModeOnInputByString(ChoiceDataGetModeOnInputByString.DIRECTLY); | ||
| p.setDefaultObjectForm(EMPTY_REF); | ||
| p.setDefaultFolderForm(EMPTY_REF); | ||
| p.setDefaultListForm(EMPTY_REF); | ||
| p.setDefaultChoiceForm(EMPTY_REF); | ||
| p.setDefaultFolderChoiceForm(EMPTY_REF); | ||
| p.setAuxiliaryObjectForm(EMPTY_REF); | ||
| p.setAuxiliaryFolderForm(EMPTY_REF); | ||
| p.setAuxiliaryListForm(EMPTY_REF); | ||
| p.setAuxiliaryChoiceForm(EMPTY_REF); | ||
| p.setAuxiliaryFolderChoiceForm(EMPTY_REF); | ||
| p.setObjectModule(EMPTY_REF); | ||
| p.setManagerModule(EMPTY_REF); | ||
| p.setIncludeHelpInContents(false); | ||
| p.setHelp(EMPTY_REF); | ||
| p.setBasedOn(JaxbWriteDefaults.emptyMDListType()); | ||
| p.setDataLockFields(JaxbWriteDefaults.emptyFieldList()); | ||
| p.setDataLockControlMode(JaxbWriteDefaults.defaultDataLockControlModeAutomatic()); | ||
| p.setFullTextSearch(JaxbWriteDefaults.fullTextSearchDontUse()); | ||
| p.setObjectPresentation(JaxbWriteDefaults.localStringType("")); | ||
| p.setExtendedObjectPresentation(JaxbWriteDefaults.localStringType("")); | ||
| p.setListPresentation(JaxbWriteDefaults.localStringType("")); | ||
| p.setExtendedListPresentation(JaxbWriteDefaults.localStringType("")); | ||
| p.setExplanation(JaxbWriteDefaults.localStringType(JaxbWriteUtils.contentForLocalString(c.getExplanation()))); | ||
| p.setCreateOnInput(CreateOnInput.DONT_USE); | ||
| p.setChoiceHistoryOnInput(JaxbWriteDefaults.choiceHistoryOnInputAuto()); | ||
| p.setDataHistory(DataHistoryUse.DONT_USE); | ||
| p.setUpdateDataHistoryImmediatelyAfterWrite(false); | ||
| p.setExecuteAfterWriteDataHistoryVersionProcessing(false); | ||
| p.setAdditionalIndexes(EMPTY_REF); | ||
| return p; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# 1) Locate Catalog model class and list available getters.
CATALOG_FILE="$(fd 'Catalog.java' src/main/java | head -n1)"
echo "Catalog file: ${CATALOG_FILE}"
rg -nP '\b(public|protected)\s+[A-Za-z0-9_<>, ?]+\s+(get|is)[A-Z][A-Za-z0-9_]*\s*\(' "${CATALOG_FILE}"
# 2) List all property assignments currently hardcoded in converter.
rg -nP 'p\.set[A-Z][A-Za-z0-9_]*\(' src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/CatalogToJaxbConverter.javaRepository: 1c-syntax/mdclasses
Length of output: 133
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Check the size of Catalog.java first
wc -l src/main/java/com/github/_1c_syntax/bsl/mdo/Catalog.java
# Get first part of file to understand structure
head -100 src/main/java/com/github/_1c_syntax/bsl/mdo/Catalog.javaRepository: 1c-syntax/mdclasses
Length of output: 3303
🏁 Script executed:
#!/bin/bash
# Search for public getters/isters in Catalog.java with simpler pattern
rg -n 'public.*\(get|is\)[A-Z]' src/main/java/com/github/_1c_syntax/bsl/mdo/Catalog.java | head -50Repository: 1c-syntax/mdclasses
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Extract all p.set* calls from the converter to list what's being hardcoded
rg 'p\.set[A-Z]' src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/CatalogToJaxbConverter.java | sed -n '86,148p'Repository: 1c-syntax/mdclasses
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Read the converter file to see the buildProperties method
cat -n src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/CatalogToJaxbConverter.java | sed -n '86,148p'Repository: 1c-syntax/mdclasses
Length of output: 3867
🏁 Script executed:
#!/bin/bash
# Read complete Catalog.java to see all fields
cat -n src/main/java/com/github/_1c_syntax/bsl/mdo/Catalog.javaRepository: 1c-syntax/mdclasses
Length of output: 6640
Use the Catalog.objectBelonging field instead of hardcoding to objectBelongingNative().
Line 91 sets p.setObjectBelonging(JaxbWriteDefaults.objectBelongingNative()) as a hardcoded default. The Catalog model has an objectBelonging field (defined with @Default ObjectBelonging objectBelonging = ObjectBelonging.OWN), so the current code drops user-provided values during serialization. This should be changed to p.setObjectBelonging(JaxbWriteDefaults.objectBelongingToJaxb(c.getObjectBelonging())) or equivalent to preserve the model's state.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/CatalogToJaxbConverter.java`
around lines 86 - 148, The buildProperties method in CatalogToJaxbConverter
currently hardcodes object belonging via
p.setObjectBelonging(JaxbWriteDefaults.objectBelongingNative()), which discards
the Catalog.model value; change this to use the Catalog instance: call
p.setObjectBelonging(JaxbWriteDefaults.objectBelongingToJaxb(c.getObjectBelonging()))
(or the equivalent helper that converts Catalog.getObjectBelonging()) so the
Catalog.objectBelonging field is preserved during conversion.
| private static void addAttributes(CatalogChildObjects co, Catalog c) { | ||
| if (c.getAttributes() == null) { | ||
| return; | ||
| } | ||
| for (Attribute attr : c.getAttributes()) { | ||
| if (attr.getName() == null || STANDARD_CATALOG_ATTRIBUTE_NAMES.contains(attr.getName())) { | ||
| continue; | ||
| } |
There was a problem hiding this comment.
Skip blank attribute names before writing attributes.
Line 215 checks only null; "" still passes and produces unnamed metadata attributes.
Proposed fix
- if (attr.getName() == null || STANDARD_CATALOG_ATTRIBUTE_NAMES.contains(attr.getName())) {
+ if (attr.getName() == null || attr.getName().isBlank()
+ || STANDARD_CATALOG_ATTRIBUTE_NAMES.contains(attr.getName())) {
continue;
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| private static void addAttributes(CatalogChildObjects co, Catalog c) { | |
| if (c.getAttributes() == null) { | |
| return; | |
| } | |
| for (Attribute attr : c.getAttributes()) { | |
| if (attr.getName() == null || STANDARD_CATALOG_ATTRIBUTE_NAMES.contains(attr.getName())) { | |
| continue; | |
| } | |
| private static void addAttributes(CatalogChildObjects co, Catalog c) { | |
| if (c.getAttributes() == null) { | |
| return; | |
| } | |
| for (Attribute attr : c.getAttributes()) { | |
| if (attr.getName() == null || attr.getName().isBlank() | |
| || STANDARD_CATALOG_ATTRIBUTE_NAMES.contains(attr.getName())) { | |
| continue; | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/CatalogToJaxbConverter.java`
around lines 210 - 217, The addAttributes method is allowing empty-string names
because it only checks attr.getName() == null; update the guard in addAttributes
(working on CatalogChildObjects, Catalog, Attribute) to skip attributes whose
name is null or blank (e.g., trim and check isEmpty()) in addition to filtering
STANDARD_CATALOG_ATTRIBUTE_NAMES so unnamed/whitespace-only Attribute instances
are not written.
| private static String makeMDClassesDefaultNamespace(String xml) { | ||
| xml = xml.replace("xmlns=\"" + NS_XCF_READABLE + "\"", "xmlns:xr=\"" + NS_XCF_READABLE + "\""); | ||
| xml = xml.replace("xmlns:ns2=\"" + NS_MDCLASSES + "\"", "xmlns=\"" + NS_MDCLASSES + "\""); | ||
| xml = xml.replace("<ns2:", "<"); | ||
| xml = xml.replace("</ns2:", "</"); | ||
| // Как в фикстурах: у Configuration только uuid, без formatVersion | ||
| xml = xml.replace(" formatVersion=\"2.20\"", ""); | ||
| // Configuration: InternalInfo с ContainedObject (как в фикстурах платформы) | ||
| xml = xml.replaceFirst( | ||
| "(<Configuration uuid=\"[^\"]+\">)\\s*\\n\\s*<Properties>", | ||
| "$1\n " + buildConfigurationInternalInfoBlock() + "\n <Properties>"); | ||
| // Catalog: InternalInfo с GeneratedType (Object, Ref, Selection, List, Manager) | ||
| xml = xml.replaceFirst( | ||
| "(<Catalog uuid=\"[^\"]+\">)\\s*\\n\\s*<Properties>", | ||
| "$1\n " + buildCatalogInternalInfoBlock() + "\n <Properties>"); | ||
| // Подставить имя справочника из первого тега <Name> | ||
| if (xml.contains(CATALOG_NAME_PLACEHOLDER)) { | ||
| Matcher m = NAME_TAG.matcher(xml); | ||
| if (m.find()) { | ||
| xml = xml.replace(CATALOG_NAME_PLACEHOLDER, m.group(1)); | ||
| } | ||
| } | ||
| return xml; | ||
| } |
There was a problem hiding this comment.
String-based XML post-processing is fragile.
The namespace and InternalInfo injection relies on specific XML formatting (whitespace patterns like ">\\s*\\n\\s*<Properties>"). If the JAXB marshaller changes its output formatting, or if properties are reordered, these replacements will silently fail or produce malformed XML.
Consider using a proper XML transformation approach (DOM/SAX post-processing or XSLT) for more robust manipulation.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@src/main/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/DesignerJaxbWriter.java`
around lines 164 - 187, The current makeMDClassesDefaultNamespace method
performs fragile string-based XML edits (namespace swaps, removing
formatVersion, and injecting InternalInfo blocks via regex/replaceFirst) which
break if JAXB formatting changes; replace this logic by parsing the XML into a
DOM (or using StAX/XSLT), programmatically rename/attach namespaces and
elements, remove the formatVersion attribute via the DOM API, and insert the
nodes produced by buildConfigurationInternalInfoBlock() and
buildCatalogInternalInfoBlock() as actual XML Elements into Configuration and
Catalog elements; also locate the first <Name> element via the DOM and replace
CATALOG_NAME_PLACEHOLDER with its text content instead of using NAME_TAG regex,
ensuring all changes are done with proper namespace-aware APIs in
makeMDClassesDefaultNamespace.
| <xs:complexType name="SpreadsheetDocument"> | ||
| <xs:choice> | ||
| <xs:element name="distributedKey" type="xs:string" minOccurs="0"/> | ||
| <xs:element name="languageSettings" minOccurs="0"> | ||
| <xs:complexType> | ||
| <xs:sequence> | ||
| <xs:element name="currentLanguage" type="xs:string"/> | ||
| <xs:element name="defaultLanguage" type="xs:string"/> | ||
| <xs:element name="languageInfo" minOccurs="0" maxOccurs="unbounded"> | ||
| <xs:complexType> | ||
| <xs:sequence> | ||
| <xs:element name="id" type="xs:string"/> | ||
| <xs:element name="code" type="xs:string"/> | ||
| <xs:element name="description" type="xs:string" minOccurs="0"/> | ||
| </xs:sequence> | ||
| </xs:complexType> | ||
| </xs:element> | ||
| </xs:sequence> | ||
| </xs:complexType> | ||
| </xs:element> | ||
| <xs:element name="languageCode" type="xs:string" minOccurs="0"/> | ||
| <xs:element name="columns" type="tns:Columns" minOccurs="0" maxOccurs="unbounded"/> | ||
| <xs:element name="rowsItem" type="tns:RowsItem" minOccurs="0" maxOccurs="unbounded"/> | ||
| <xs:element name="drawing" type="tns:Drawing" minOccurs="0" maxOccurs="unbounded"/> | ||
| <xs:element name="backPicture" minOccurs="0"/> | ||
| <xs:element name="fixedBackground" type="xs:boolean" minOccurs="0"/> | ||
| <xs:element name="leftHeader" type="tns:Cell" minOccurs="0"/> | ||
| <xs:element name="centerHeader" type="tns:Cell" minOccurs="0"/> | ||
| <xs:element name="rightHeader" type="tns:Cell" minOccurs="0"/> | ||
| <xs:element name="leftFooter" type="tns:Cell" minOccurs="0"/> | ||
| <xs:element name="centerFooter" type="tns:Cell" minOccurs="0"/> | ||
| <xs:element name="rightFooter" type="tns:Cell" minOccurs="0"/> | ||
| <xs:element name="templateMode" type="xs:boolean" minOccurs="0"/> | ||
| <xs:element name="stepDirection" type="tns:SpreadsheetDocumentStepDirectionType" minOccurs="0"/> | ||
| <xs:element name="totalsRight" type="xs:boolean" minOccurs="0"/> | ||
| <xs:element name="totalsBelow" type="xs:boolean" minOccurs="0"/> | ||
| <xs:element name="defaultFormatIndex" type="xs:decimal" minOccurs="0"/> | ||
| <xs:element name="height" type="xs:decimal" minOccurs="0"/> | ||
| <xs:element name="vgLevels" type="xs:decimal" minOccurs="0"/> | ||
| <xs:element name="vgRows" type="xs:decimal" minOccurs="0"/> | ||
| <xs:element name="vg" type="tns:Group" minOccurs="0" maxOccurs="unbounded"/> | ||
| <xs:element name="hg" type="tns:Group" minOccurs="0" maxOccurs="unbounded"/> | ||
| <xs:element name="verticalPageBreak" type="tns:PageBreak" minOccurs="0" maxOccurs="unbounded"/> | ||
| <xs:element name="horizontalPageBreak" type="tns:PageBreak" minOccurs="0" maxOccurs="unbounded"/> | ||
| <xs:element name="merge" type="tns:Merge" minOccurs="0" maxOccurs="unbounded"/> | ||
| <xs:element name="verticalUnmerge" type="tns:Merge" minOccurs="0" maxOccurs="unbounded"/> | ||
| <xs:element name="horizontalUnmerge" type="tns:Merge" minOccurs="0" maxOccurs="unbounded"/> | ||
| <xs:element name="namedItem" type="tns:NamedItem" minOccurs="0" maxOccurs="unbounded"/> | ||
| <xs:element name="printSettingsName" type="xs:string" minOccurs="0"/> | ||
| <xs:element name="printSettings" type="tns:PrintSettings" minOccurs="0"/> | ||
| <xs:element name="printArea" type="tns:Area" minOccurs="0"/> | ||
| <xs:element name="repeatRows" type="tns:Area" minOccurs="0"/> | ||
| <xs:element name="repeatColumns" type="tns:Area" minOccurs="0"/> | ||
| <xs:element name="drawingDataSource" type="tns:DrawingsDataSource" minOccurs="0" maxOccurs="unbounded"/> | ||
| <xs:element name="groupsBackColor" type="ns2:Color" minOccurs="0" maxOccurs="unbounded"/> | ||
| <xs:element name="groupsColor" type="ns2:Color" minOccurs="0" maxOccurs="unbounded"/> | ||
| <xs:element name="headersBackColor" type="ns2:Color" minOccurs="0" maxOccurs="unbounded"/> | ||
| <xs:element name="headersColor" type="ns2:Color" minOccurs="0" maxOccurs="unbounded"/> | ||
| <xs:element name="saveViewSettings" type="xs:boolean" minOccurs="0"/> | ||
| <xs:element name="viewSettings" type="tns:ViewSettings" minOccurs="0"/> | ||
| <xs:element name="embeddedTable" type="tns:EmbeddedTableItem" minOccurs="0" maxOccurs="unbounded"/> | ||
| <xs:element name="line" type="ns2:Line" minOccurs="0" maxOccurs="unbounded"/> | ||
| <xs:element name="font" type="ns2:Font" minOccurs="0" maxOccurs="unbounded"/> | ||
| <xs:element name="format" type="tns:Format" minOccurs="0" maxOccurs="unbounded"/> | ||
| <xs:element name="picture" type="tns:Picture" minOccurs="0" maxOccurs="unbounded"/> | ||
| <xs:element name="usedFileName" type="xs:string" minOccurs="0"/> | ||
| <xs:element name="output" type="ns2:UseOutput" minOccurs="0"/> | ||
| <xs:element name="nextInsertionRow" type="xs:decimal" minOccurs="0"/> | ||
| <xs:element name="nextInsertionCol" type="xs:decimal" minOccurs="0"/> | ||
| <xs:element name="readOnly" type="xs:boolean" minOccurs="0"/> | ||
| <xs:element name="protection" type="xs:boolean" minOccurs="0"/> | ||
| <xs:element name="baseSheet" type="tns:SpreadsheetDocument" minOccurs="0"/> | ||
| <xs:element name="extensionMethod" type="tns:SpreadsheetDocumentExtensionAlgorithm" minOccurs="0"/> | ||
| <xs:element name="isCompactMode" type="xs:boolean" minOccurs="0"/> | ||
| <xs:element name="originalSheet" type="tns:SpreadsheetDocument" minOccurs="0"/> | ||
| <xs:element name="textDirection" type="ns2:TextDirection" minOccurs="0"/> | ||
| <xs:element name="savedPicturesDensity" type="tns:SpreadsheetDocumentSavedPicturesDensity" minOccurs="0"/> | ||
| </xs:choice> | ||
| </xs:complexType> |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
python - <<'PY'
import xml.etree.ElementTree as ET
from pathlib import Path
ns = {'xs': 'http://www.w3.org/2001/XMLSchema'}
for path in [
Path('src/main/xsd/v8.5/v8.1c.ru-8.2-data-spreadsheet.xsd'),
Path('src/main/xsd/v8.3.27/v8.1c.ru-8.2-data-spreadsheet.xsd'),
]:
root = ET.parse(path).getroot()
ct = next(
ct for ct in root.findall('xs:complexType', ns)
if ct.get('name') == 'SpreadsheetDocument'
)
choice = ct.find('xs:choice', ns)
children = [el.get('name') for el in choice.findall('xs:element', ns)]
print(path)
print(' choice.maxOccurs =', repr(choice.get('maxOccurs')))
print(' child_count =', len(children))
print(' sample_children =', children[:10])
PYRepository: 1c-syntax/mdclasses
Length of output: 605
Fix the SpreadsheetDocument content model to allow multiple sections.
The xs:choice compositor at lines 605–679 has an implicit maxOccurs="1" constraint, meaning a SpreadsheetDocument can contain only one of: columns, rowsItem, format, drawing, etc., but not a combination. This makes any spreadsheet requiring both layout (columns) and content (rows) invalid against the schema. Either change the compositor to xs:sequence or xs:all, or set maxOccurs="unbounded" on the choice to allow repeated mixed sections.
The identical issue exists in the mirrored src/main/xsd/v8.3.27/v8.1c.ru-8.2-data-spreadsheet.xsd file; both versions should be updated together.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/main/xsd/v8.5/v8.1c.ru-8.2-data-spreadsheet.xsd` around lines 602 - 680,
The SpreadsheetDocument complexType uses an xs:choice with its implicit
maxOccurs="1", preventing multiple child sections; update the compositor in the
SpreadsheetDocument definition (the xs:choice surrounding elements like columns,
rowsItem, drawing, format, etc.) to allow multiple mixed children—either replace
xs:choice with xs:sequence or add maxOccurs="unbounded" to xs:choice so the
document can contain multiple sections; apply the same edit to the mirrored
SpreadsheetDocument definition in the other XSD (v8.3.27) as well.
| <xs:complexType name="CommansShortCutInfo"> | ||
| <xs:sequence> | ||
| <xs:element name="shortCut" type="ns2:ShortCutType"/> | ||
| <xs:element name="fragments" type="tns:SubsystemAndPanel" minOccurs="0" maxOccurs="unbounded"/> | ||
| <xs:element name="commandId" type="ns1:CompositeID"/> | ||
| </xs:sequence> | ||
| </xs:complexType> | ||
| <xs:complexType name="CommansShortCutInfoVector"> | ||
| <xs:sequence> | ||
| <xs:element name="info" type="tns:CommansShortCutInfo" minOccurs="0" maxOccurs="unbounded"/> | ||
| </xs:sequence> | ||
| </xs:complexType> |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
1C v8.2 managed application CMI schema CommansShortCutInfo
💡 Result:
In 1C:Enterprise 8.2 managed applications, CMI refers to the Command Interface Model (com._1c.g5.v8.dt.cmi.model package in 1C EDT), an EMF-based schema used in the development tools (EDT) for modeling the command interface. This includes classes like CommandInterface, CommandsVisibility, CommandsOrder, etc., which define the structure, visibility, order, and placement of commands in the UI. No exact class or element named "CommansShortCutInfo" (likely a misspelling of "CommandsShortCutInfo") exists in the CMI schema. However, command information in related form layout models includes a "shortCut" field of type String, as seen in ICommandsManagerInfo.CommandInfo. This field stores the keyboard shortcut representation for commands (e.g., "Ctrl+Shift+F1"). The command interface supports keyboard shortcuts via command properties, but shortcuts are not a dedicated CMI schema element. They are part of command metadata and runtime info for managed forms. Official docs describe command interface structure via subsystems, command groups, and properties like visibility and order, with no specific "CommansShortCutInfo" structure identified.
Citations:
- 1: https://edt.1c.ru/dev/edt/2024.2/apidocs/com/_1c/g5/v8/dt/cmi/model/package-summary.html
- 2: https://edt.1c.ru/dev/edt/2024.2/apidocs/com/_1c/g5/v8/dt/form/layout/model/common/ICommandsManagerInfo.CommandInfo.html
- 3: https://edt.1c.ru/dev/edt/2024.2/apidocs/com/_1c/g5/v8/dt/cmi/model/util/CmiModelUtil.html
- 4: https://edt.1c.ru/dev/edt/2024.2/apidocs/com/_1c/g5/v8/dt/cmi/model/package-tree.html
- 5: https://edt.1c.ru/dev/edt/2024.2/apidocs/com/_1c/g5/v8/dt/cmi/model/CommandInterface.html
- 6: https://edt.1c.ru/dev/edt/2024.2/apidocs/com/_1c/g5/v8/dt/form/layout/model/common/ICommandsManagerInfo.html
- 7: https://edt.1c.ru/dev/edt/2024.2/apidocs/com/_1c/g5/v8/dt/internal/cmi/bm/derived/CommandInterfaceManager.html
- 8: https://edt.1c.ru/dev/edt/2024.2/apidocs/com/_1c/g5/v8/dt/cmi/model/CmiPackage.Literals.html
- 9: https://yellow-erp.com/page/guides/dev/command-interface/
🏁 Script executed:
# First, check if the file exists and read its contents
cat -n src/main/xsd/v8.5/v8.1c.ru-8.2-managed-application-cmi.xsd | head -120 | tail -30Repository: 1c-syntax/mdclasses
Length of output: 1512
🏁 Script executed:
# Also get the full context around lines 105-116 and check for any comments
wc -l src/main/xsd/v8.5/v8.1c.ru-8.2-managed-application-cmi.xsdRepository: 1c-syntax/mdclasses
Length of output: 125
🏁 Script executed:
# Search for other occurrences of "Commans" in the codebase
rg "Commans" --type xmlRepository: 1c-syntax/mdclasses
Length of output: 1168
🏁 Script executed:
# Check the XSD file header for any notes about source or origin
head -50 src/main/xsd/v8.5/v8.1c.ru-8.2-managed-application-cmi.xsdRepository: 1c-syntax/mdclasses
Length of output: 2861
Correct the typo in type names from "Commans" to "Commands".
The type names CommansShortCutInfo and CommansShortCutInfoVector contain a typo. The official 1C CMI schema documentation does not reference a "CommansShortCutInfo" type; no such element exists in the official platform schema. This appears to be an unintentional mistake rather than a preserved compatibility issue. Correct these to CommandsShortCutInfo and CommandsShortCutInfoVector to match the intended naming pattern and official conventions.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/main/xsd/v8.5/v8.1c.ru-8.2-managed-application-cmi.xsd` around lines 105
- 116, Rename the misspelled complexType names and any references from
CommansShortCutInfo to CommandsShortCutInfo and from CommansShortCutInfoVector
to CommandsShortCutInfoVector; update the type attributes on the <xs:complexType
name="CommansShortCutInfo"> and <xs:complexType
name="CommansShortCutInfoVector"> declarations and update any element/type
references such as type="tns:CommansShortCutInfo" to use the corrected
identifiers so all definitions and usages (e.g., the <xs:element name="info"
type="tns:CommansShortCutInfo" .../>) remain consistent.
| <xs:complexType name="CollectionOperations"> | ||
| <xs:choice> | ||
| <xs:element name="add" type="tns:CollectionOperationAdd" minOccurs="0" maxOccurs="unbounded"/> | ||
| <xs:element name="addRange" type="tns:CollectionOperationAddRange" minOccurs="0" maxOccurs="unbounded"/> | ||
| <xs:element name="remove" type="tns:CollectionOperationRemove" minOccurs="0" maxOccurs="unbounded"/> | ||
| <xs:element name="removeRange" type="tns:CollectionOperationRemoveRange" minOccurs="0" maxOccurs="unbounded"/> | ||
| <xs:element name="swap" type="tns:CollectionOperationSwap" minOccurs="0" maxOccurs="unbounded"/> | ||
| <xs:element name="move" type="tns:CollectionOperationMove" minOccurs="0" maxOccurs="unbounded"/> | ||
| <xs:element name="clear" type="tns:CollectionOperationClear" minOccurs="0" maxOccurs="unbounded"/> | ||
| </xs:choice> | ||
| </xs:complexType> |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
python - <<'PY'
import xml.etree.ElementTree as ET
from pathlib import Path
ns = {'xs': 'http://www.w3.org/2001/XMLSchema'}
targets = ('CollectionOperations', 'TreeOperations')
for path in [
Path('src/main/xsd/v8.5/v8.1c.ru-8.2-uobjects.xsd'),
Path('src/main/xsd/v8.3.27/v8.1c.ru-8.2-uobjects.xsd'),
]:
root = ET.parse(path).getroot()
print(path)
for name in targets:
ct = next(
ct for ct in root.findall('xs:complexType', ns)
if ct.get('name') == name
)
choice = ct.find('xs:choice', ns)
children = [el.get('name') for el in choice.findall('xs:element', ns)]
print(f' {name}: choice.maxOccurs={choice.get("maxOccurs")!r}, children={children}')
PYRepository: 1c-syntax/mdclasses
Length of output: 645
Fix non-repeating xs:choice in operation content models.
The xs:choice elements in CollectionOperations (lines 126–136) and TreeOperations (lines 360–370) have no maxOccurs attribute, defaulting to 1. This permits only a single operation per block. If mixed operations like add + move are valid, add maxOccurs="unbounded" to allow repeating choices. The same issue exists in the mirrored file src/main/xsd/v8.3.27/v8.1c.ru-8.2-uobjects.xsd and both versions must stay aligned.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/main/xsd/v8.5/v8.1c.ru-8.2-uobjects.xsd` around lines 126 - 136, The
xs:choice in the CollectionOperations and TreeOperations complexTypes currently
lacks maxOccurs, restricting the block to a single operation; update the
xs:choice element inside the CollectionOperations and the xs:choice inside
TreeOperations to include maxOccurs="unbounded" so multiple operation elements
(e.g., add + move) can appear, and mirror the same change in the corresponding
file under v8.3.27 to keep both versions aligned; locate the choice nodes by the
complexType names CollectionOperations and TreeOperations and add the maxOccurs
attribute to each xs:choice.
| <xs:complexType name="ValueList"> | ||
| <xs:sequence> | ||
| <xs:element name="Item" type="tns:ValueListItem"/> | ||
| </xs:sequence> |
There was a problem hiding this comment.
ValueList currently allows only one item.
Line 261 should allow repeated Item entries; otherwise list serialization is artificially capped at one value.
Proposed fix
<xs:complexType name="ValueList">
<xs:sequence>
- <xs:element name="Item" type="tns:ValueListItem"/>
+ <xs:element name="Item" type="tns:ValueListItem" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <xs:complexType name="ValueList"> | |
| <xs:sequence> | |
| <xs:element name="Item" type="tns:ValueListItem"/> | |
| </xs:sequence> | |
| <xs:complexType name="ValueList"> | |
| <xs:sequence> | |
| <xs:element name="Item" type="tns:ValueListItem" minOccurs="0" maxOccurs="unbounded"/> | |
| </xs:sequence> | |
| </xs:complexType> |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/main/xsd/v8.5/v8.1c.ru-8.3-xcf-readable.xsd` around lines 259 - 262, The
ValueList complexType currently defines a single xs:element name="Item"
(type="tns:ValueListItem") so lists are capped at one; update the Item element
declaration inside the ValueList xs:sequence to allow multiple entries (e.g.,
set maxOccurs="unbounded" and adjust minOccurs if needed) so ValueList can
contain repeated Item elements, ensuring to modify the xs:element with name
"Item" in the ValueList complexType.
| Path configPath = OUTPUT_DIR.resolve("Configuration.xml"); | ||
| assert Files.exists(configPath) : "Configuration.xml"; | ||
| assert Files.exists(OUTPUT_DIR.resolve("Languages").resolve("Русский.xml")) : "Languages/Русский.xml"; | ||
| assert Files.exists(OUTPUT_DIR.resolve("Subsystems").resolve("ПерваяПодсистема.xml")) : "Subsystems/ПерваяПодсистема.xml"; | ||
| assert Files.exists(OUTPUT_DIR.resolve("Subsystems").resolve("ВтораяПодсистема.xml")) : "Subsystems/ВтораяПодсистема.xml"; | ||
| Path nestedSub = OUTPUT_DIR.resolve("Subsystems").resolve("ПерваяПодсистема").resolve("Subsystems").resolve("ПодчиненнаяПодсистема.xml"); | ||
| assert Files.exists(nestedSub) : "Subsystems/ПерваяПодсистема/Subsystems/ПодчиненнаяПодсистема.xml"; | ||
| assert Files.exists(OUTPUT_DIR.resolve("Catalogs").resolve("Справочник1.xml")) : "Catalogs/Справочник1.xml"; | ||
| Path formsDir = OUTPUT_DIR.resolve("Catalogs").resolve("Справочник1").resolve("Forms"); | ||
| assert Files.exists(formsDir.resolve("ФормаЭлемента.xml")) : "Catalogs/Справочник1/Forms/ФормаЭлемента.xml"; | ||
| assert Files.exists(formsDir.resolve("ФормаСписка.xml")) : "Catalogs/Справочник1/Forms/ФормаСписка.xml"; | ||
| assert Files.exists(formsDir.resolve("ФормаВыбора.xml")) : "Catalogs/Справочник1/Forms/ФормаВыбора.xml"; | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Use AssertJ assertions instead of raw assert statements.
Raw Java assert statements are disabled by default at runtime and don't provide the fluent API or detailed failure messages that AssertJ offers. As per coding guidelines: "Use JUnit 5 for testing with AssertJ for fluent assertions."
♻️ Proposed fix using AssertJ
+import static org.assertj.core.api.Assertions.assertThat;
+
`@Test`
void writeExampleToBuildDir() throws Exception {
Configuration cf = (Configuration) MDClasses.createConfiguration(DESIGNER_CF, MDCReadSettings.DEFAULT);
MDClassesJaxbWriter.writeConfigurationToFolder(OUTPUT_DIR, cf);
Path configPath = OUTPUT_DIR.resolve("Configuration.xml");
- assert Files.exists(configPath) : "Configuration.xml";
- assert Files.exists(OUTPUT_DIR.resolve("Languages").resolve("Русский.xml")) : "Languages/Русский.xml";
- assert Files.exists(OUTPUT_DIR.resolve("Subsystems").resolve("ПерваяПодсистема.xml")) : "Subsystems/ПерваяПодсистема.xml";
- assert Files.exists(OUTPUT_DIR.resolve("Subsystems").resolve("ВтораяПодсистема.xml")) : "Subsystems/ВтораяПодсистема.xml";
+ assertThat(configPath).exists();
+ assertThat(OUTPUT_DIR.resolve("Languages").resolve("Русский.xml")).exists();
+ assertThat(OUTPUT_DIR.resolve("Subsystems").resolve("ПерваяПодсистема.xml")).exists();
+ assertThat(OUTPUT_DIR.resolve("Subsystems").resolve("ВтораяПодсистема.xml")).exists();
Path nestedSub = OUTPUT_DIR.resolve("Subsystems").resolve("ПерваяПодсистема").resolve("Subsystems").resolve("ПодчиненнаяПодсистема.xml");
- assert Files.exists(nestedSub) : "Subsystems/ПерваяПодсистема/Subsystems/ПодчиненнаяПодсистема.xml";
- assert Files.exists(OUTPUT_DIR.resolve("Catalogs").resolve("Справочник1.xml")) : "Catalogs/Справочник1.xml";
+ assertThat(nestedSub).exists();
+ assertThat(OUTPUT_DIR.resolve("Catalogs").resolve("Справочник1.xml")).exists();
Path formsDir = OUTPUT_DIR.resolve("Catalogs").resolve("Справочник1").resolve("Forms");
- assert Files.exists(formsDir.resolve("ФормаЭлемента.xml")) : "Catalogs/Справочник1/Forms/ФормаЭлемента.xml";
- assert Files.exists(formsDir.resolve("ФормаСписка.xml")) : "Catalogs/Справочник1/Forms/ФормаСписка.xml";
- assert Files.exists(formsDir.resolve("ФормаВыбора.xml")) : "Catalogs/Справочник1/Forms/ФормаВыбора.xml";
+ assertThat(formsDir.resolve("ФормаЭлемента.xml")).exists();
+ assertThat(formsDir.resolve("ФормаСписка.xml")).exists();
+ assertThat(formsDir.resolve("ФормаВыбора.xml")).exists();
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@src/test/java/com/github/_1c_syntax/bsl/mdclasses/jaxb/write/JaxbWriterExampleTest.java`
around lines 51 - 63, Replace raw Java assert statements in
JaxbWriterExampleTest with AssertJ fluent assertions: for each occurrence like
assert Files.exists(path) : "msg" or checking existence of Paths (e.g.,
configPath, nestedSub, formsDir.resolve(...)), use
org.assertj.core.api.Assertions.assertThat(...) with a descriptive assertion
(for Path use assertThat(path).as("...").exists() or
assertThat(Files.exists(path)).as("...").isTrue()) so failures show clear
messages; update imports to include AssertJ (Assertions) and remove reliance on
JVM-enabled assertions.
Описание
TODO
Связанные задачи
Closes #158
Чеклист
Общие
gradlew precommit)Дополнительно
Summary by CodeRabbit
New Features
Dependencies