expressir 2.1.27 → 2.1.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +25 -152
- data/README.adoc +289 -29
- data/expressir.gemspec +1 -0
- data/lib/expressir/changes/edition_change.rb +2 -4
- data/lib/expressir/changes/item_change.rb +1 -1
- data/lib/expressir/changes/mapping_change.rb +2 -2
- data/lib/expressir/changes/schema_change.rb +10 -16
- data/lib/expressir/changes.rb +3 -5
- data/lib/expressir/commands/changes_import_eengine.rb +132 -64
- data/lib/expressir/commands/changes_validate.rb +1 -1
- data/lib/expressir/eengine/arm_compare_report.rb +27 -0
- data/lib/expressir/eengine/changes_section.rb +19 -0
- data/lib/expressir/eengine/compare_report.rb +81 -0
- data/lib/expressir/eengine/mim_compare_report.rb +27 -0
- data/lib/expressir/eengine/modified_object.rb +23 -0
- data/lib/expressir/version.rb +1 -1
- metadata +21 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fbc607242e5dfe5db0276c14d37cdc1d38fc07e4f0014134b20105e443a3b96c
|
|
4
|
+
data.tar.gz: 32ba2fe11da1f6439b7a97e30215df127aa6826ae6199f205fa4376c7624a4d2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 06e09081cbb49ef2d4656e8f9104c830edf8fc0427ffbcef0f6fa686884468e561370656d74b3c0f893b1786e0e9d4d4d8f335d297e9e3ddb8211d9bc26bbfd1
|
|
7
|
+
data.tar.gz: 15350b06e45e272b7b7dbaee29c5030b794e67a30544344bf534ec2b86c89998fcb1123c1352201d4d41f217f8e11c3054f5e0ef3f94fccb96b3daa42aacda82
|
data/.rubocop_todo.yml
CHANGED
|
@@ -1,115 +1,56 @@
|
|
|
1
1
|
# This configuration was generated by
|
|
2
2
|
# `rubocop --auto-gen-config`
|
|
3
|
-
# on 2025-10-
|
|
3
|
+
# on 2025-10-15 09:12:23 UTC using RuboCop version 1.81.1.
|
|
4
4
|
# The point is for the user to remove these configuration records
|
|
5
5
|
# one by one as the offenses are removed from the code base.
|
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
|
7
7
|
# versions of RuboCop, may require this file to be generated again.
|
|
8
8
|
|
|
9
|
-
# Offense count:
|
|
9
|
+
# Offense count: 3
|
|
10
10
|
# This cop supports safe autocorrection (--autocorrect).
|
|
11
11
|
# Configuration parameters: EnforcedStyle, IndentationWidth.
|
|
12
12
|
# SupportedStyles: with_first_argument, with_fixed_indentation
|
|
13
13
|
Layout/ArgumentAlignment:
|
|
14
14
|
Exclude:
|
|
15
|
-
- 'lib/expressir/commands/
|
|
16
|
-
- 'spec/expressir/changes/schema_change_spec.rb'
|
|
17
|
-
- 'spec/expressir/commands/changes_import_eengine_spec.rb'
|
|
18
|
-
- 'spec/expressir/commands/changes_validate_spec.rb'
|
|
15
|
+
- 'lib/expressir/commands/changes_import_eengine.rb'
|
|
19
16
|
|
|
20
|
-
# Offense count:
|
|
17
|
+
# Offense count: 4
|
|
21
18
|
# This cop supports safe autocorrection (--autocorrect).
|
|
22
19
|
# Configuration parameters: EnforcedStyleAlignWith.
|
|
23
20
|
# SupportedStylesAlignWith: either, start_of_block, start_of_line
|
|
24
21
|
Layout/BlockAlignment:
|
|
25
22
|
Exclude:
|
|
26
|
-
- 'lib/expressir/
|
|
23
|
+
- 'lib/expressir/commands/changes_import_eengine.rb'
|
|
24
|
+
- 'spec/expressir/commands/changes_import_eengine_spec.rb'
|
|
27
25
|
|
|
28
|
-
# Offense count:
|
|
26
|
+
# Offense count: 4
|
|
29
27
|
# This cop supports safe autocorrection (--autocorrect).
|
|
30
28
|
Layout/BlockEndNewline:
|
|
31
29
|
Exclude:
|
|
32
|
-
- 'lib/expressir/
|
|
33
|
-
|
|
34
|
-
# Offense count: 1
|
|
35
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
36
|
-
# Configuration parameters: AllowForAlignment.
|
|
37
|
-
Layout/CommentIndentation:
|
|
38
|
-
Exclude:
|
|
39
|
-
- 'lib/expressir/commands/changes_validate.rb'
|
|
40
|
-
|
|
41
|
-
# Offense count: 2
|
|
42
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
43
|
-
Layout/ElseAlignment:
|
|
44
|
-
Exclude:
|
|
45
|
-
- 'lib/expressir/commands/changes_validate.rb'
|
|
46
|
-
|
|
47
|
-
# Offense count: 2
|
|
48
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
49
|
-
# Configuration parameters: EnforcedStyle.
|
|
50
|
-
# SupportedStyles: empty_lines, no_empty_lines
|
|
51
|
-
Layout/EmptyLinesAroundBlockBody:
|
|
52
|
-
Exclude:
|
|
53
|
-
- 'bin/validate_all_changes'
|
|
54
|
-
|
|
55
|
-
# Offense count: 1
|
|
56
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
57
|
-
# Configuration parameters: EnforcedStyleAlignWith, Severity.
|
|
58
|
-
# SupportedStylesAlignWith: keyword, variable, start_of_line
|
|
59
|
-
Layout/EndAlignment:
|
|
60
|
-
Exclude:
|
|
61
|
-
- 'lib/expressir/commands/changes_validate.rb'
|
|
62
|
-
|
|
63
|
-
# Offense count: 12
|
|
64
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
65
|
-
# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
|
|
66
|
-
# SupportedHashRocketStyles: key, separator, table
|
|
67
|
-
# SupportedColonStyles: key, separator, table
|
|
68
|
-
# SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit
|
|
69
|
-
Layout/HashAlignment:
|
|
70
|
-
Exclude:
|
|
71
|
-
- 'lib/expressir/commands/changes.rb'
|
|
72
|
-
- 'spec/expressir/changes/schema_change_spec.rb'
|
|
73
|
-
- 'spec/expressir/commands/changes_validate_spec.rb'
|
|
30
|
+
- 'lib/expressir/commands/changes_import_eengine.rb'
|
|
31
|
+
- 'spec/expressir/commands/changes_import_eengine_spec.rb'
|
|
74
32
|
|
|
75
|
-
# Offense count:
|
|
33
|
+
# Offense count: 8
|
|
76
34
|
# This cop supports safe autocorrection (--autocorrect).
|
|
77
35
|
# Configuration parameters: Width, AllowedPatterns.
|
|
78
36
|
Layout/IndentationWidth:
|
|
79
37
|
Exclude:
|
|
80
|
-
- '
|
|
81
|
-
- '
|
|
82
|
-
- 'lib/expressir/commands/changes_validate.rb'
|
|
38
|
+
- 'lib/expressir/commands/changes_import_eengine.rb'
|
|
39
|
+
- 'spec/expressir/commands/changes_import_eengine_spec.rb'
|
|
83
40
|
|
|
84
|
-
# Offense count:
|
|
41
|
+
# Offense count: 569
|
|
85
42
|
# This cop supports safe autocorrection (--autocorrect).
|
|
86
43
|
# Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings.
|
|
87
44
|
# URISchemes: http, https
|
|
88
45
|
Layout/LineLength:
|
|
89
46
|
Enabled: false
|
|
90
47
|
|
|
91
|
-
# Offense count:
|
|
92
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
93
|
-
Layout/RescueEnsureAlignment:
|
|
94
|
-
Exclude:
|
|
95
|
-
- 'bin/validate_all_changes'
|
|
96
|
-
|
|
97
|
-
# Offense count: 8
|
|
48
|
+
# Offense count: 3
|
|
98
49
|
# This cop supports safe autocorrection (--autocorrect).
|
|
99
50
|
# Configuration parameters: AllowInHeredoc.
|
|
100
51
|
Layout/TrailingWhitespace:
|
|
101
52
|
Exclude:
|
|
102
|
-
- '
|
|
103
|
-
- 'lib/expressir/commands/changes.rb'
|
|
104
|
-
- 'spec/expressir/changes/schema_change_spec.rb'
|
|
105
|
-
- 'spec/expressir/commands/changes_import_eengine_spec.rb'
|
|
106
|
-
- 'spec/expressir/commands/changes_validate_spec.rb'
|
|
107
|
-
|
|
108
|
-
# Offense count: 4
|
|
109
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
110
|
-
Lint/AmbiguousOperatorPrecedence:
|
|
111
|
-
Exclude:
|
|
112
|
-
- 'bin/validate_all_changes'
|
|
53
|
+
- 'lib/expressir/commands/changes_import_eengine.rb'
|
|
113
54
|
|
|
114
55
|
# Offense count: 1
|
|
115
56
|
# Configuration parameters: IgnoreLiteralBranches, IgnoreConstantBranches, IgnoreDuplicateElseBranch.
|
|
@@ -131,13 +72,13 @@ Lint/UnusedMethodArgument:
|
|
|
131
72
|
Metrics/AbcSize:
|
|
132
73
|
Enabled: false
|
|
133
74
|
|
|
134
|
-
# Offense count:
|
|
75
|
+
# Offense count: 1
|
|
135
76
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode.
|
|
136
77
|
# AllowedMethods: refine
|
|
137
78
|
Metrics/BlockLength:
|
|
138
|
-
Max:
|
|
79
|
+
Max: 46
|
|
139
80
|
|
|
140
|
-
# Offense count:
|
|
81
|
+
# Offense count: 61
|
|
141
82
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
|
142
83
|
Metrics/CyclomaticComplexity:
|
|
143
84
|
Exclude:
|
|
@@ -155,12 +96,12 @@ Metrics/CyclomaticComplexity:
|
|
|
155
96
|
- 'lib/expressir/model/model_element.rb'
|
|
156
97
|
- 'spec/support/model_element_helper.rb'
|
|
157
98
|
|
|
158
|
-
# Offense count:
|
|
99
|
+
# Offense count: 113
|
|
159
100
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
|
160
101
|
Metrics/MethodLength:
|
|
161
102
|
Max: 106
|
|
162
103
|
|
|
163
|
-
# Offense count:
|
|
104
|
+
# Offense count: 48
|
|
164
105
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
|
165
106
|
Metrics/PerceivedComplexity:
|
|
166
107
|
Exclude:
|
|
@@ -194,7 +135,7 @@ Performance/MapMethodChain:
|
|
|
194
135
|
- 'spec/expressir/commands/coverage_ignore_files_spec.rb'
|
|
195
136
|
- 'spec/expressir/coverage_spec.rb'
|
|
196
137
|
|
|
197
|
-
# Offense count:
|
|
138
|
+
# Offense count: 126
|
|
198
139
|
# Configuration parameters: CountAsOne.
|
|
199
140
|
RSpec/ExampleLength:
|
|
200
141
|
Max: 123
|
|
@@ -210,13 +151,7 @@ RSpec/IndexedLet:
|
|
|
210
151
|
- 'spec/expressir/model/data_types/set_spec.rb'
|
|
211
152
|
- 'spec/expressir/model/data_types/string_spec.rb'
|
|
212
153
|
|
|
213
|
-
# Offense count:
|
|
214
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
215
|
-
RSpec/IteratedExpectation:
|
|
216
|
-
Exclude:
|
|
217
|
-
- 'spec/expressir/schema_manifest_spec.rb'
|
|
218
|
-
|
|
219
|
-
# Offense count: 254
|
|
154
|
+
# Offense count: 257
|
|
220
155
|
RSpec/MultipleExpectations:
|
|
221
156
|
Max: 114
|
|
222
157
|
|
|
@@ -237,13 +172,7 @@ RSpec/RepeatedExample:
|
|
|
237
172
|
Exclude:
|
|
238
173
|
- 'spec/expressir/model/data_types/logical_spec.rb'
|
|
239
174
|
|
|
240
|
-
# Offense count:
|
|
241
|
-
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
242
|
-
Security/YAMLLoad:
|
|
243
|
-
Exclude:
|
|
244
|
-
- 'bin/validate_all_changes'
|
|
245
|
-
|
|
246
|
-
# Offense count: 1
|
|
175
|
+
# Offense count: 6
|
|
247
176
|
# This cop supports safe autocorrection (--autocorrect).
|
|
248
177
|
# Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, AllowedMethods, AllowedPatterns, AllowBracesOnProceduralOneLiners, BracesRequiredMethods.
|
|
249
178
|
# SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces
|
|
@@ -252,7 +181,8 @@ Security/YAMLLoad:
|
|
|
252
181
|
# AllowedMethods: lambda, proc, it
|
|
253
182
|
Style/BlockDelimiters:
|
|
254
183
|
Exclude:
|
|
255
|
-
- 'lib/expressir/
|
|
184
|
+
- 'lib/expressir/commands/changes_import_eengine.rb'
|
|
185
|
+
- 'spec/expressir/commands/changes_import_eengine_spec.rb'
|
|
256
186
|
|
|
257
187
|
# Offense count: 1
|
|
258
188
|
# This cop supports safe autocorrection (--autocorrect).
|
|
@@ -266,60 +196,3 @@ Style/EmptyElse:
|
|
|
266
196
|
Style/MissingRespondToMissing:
|
|
267
197
|
Exclude:
|
|
268
198
|
- 'lib/expressir/express/visitor.rb'
|
|
269
|
-
|
|
270
|
-
# Offense count: 1
|
|
271
|
-
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
272
|
-
# Configuration parameters: EnforcedStyle, AllowedMethods, AllowedPatterns.
|
|
273
|
-
# SupportedStyles: predicate, comparison
|
|
274
|
-
Style/NumericPredicate:
|
|
275
|
-
Exclude:
|
|
276
|
-
- 'spec/**/*'
|
|
277
|
-
- 'lib/expressir/commands/changes_import_eengine.rb'
|
|
278
|
-
|
|
279
|
-
# Offense count: 1
|
|
280
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
281
|
-
Style/RedundantBegin:
|
|
282
|
-
Exclude:
|
|
283
|
-
- 'bin/validate_all_changes'
|
|
284
|
-
|
|
285
|
-
# Offense count: 4
|
|
286
|
-
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
287
|
-
# Configuration parameters: Mode.
|
|
288
|
-
Style/StringConcatenation:
|
|
289
|
-
Exclude:
|
|
290
|
-
- 'bin/validate_all_changes'
|
|
291
|
-
|
|
292
|
-
# Offense count: 4
|
|
293
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
294
|
-
# Configuration parameters: EnforcedStyle.
|
|
295
|
-
# SupportedStyles: single_quotes, double_quotes
|
|
296
|
-
Style/StringLiteralsInInterpolation:
|
|
297
|
-
Exclude:
|
|
298
|
-
- 'bin/validate_all_changes'
|
|
299
|
-
|
|
300
|
-
# Offense count: 4
|
|
301
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
302
|
-
# Configuration parameters: EnforcedStyleForMultiline.
|
|
303
|
-
# SupportedStylesForMultiline: comma, consistent_comma, diff_comma, no_comma
|
|
304
|
-
Style/TrailingCommaInArguments:
|
|
305
|
-
Exclude:
|
|
306
|
-
- 'lib/expressir/changes/schema_change.rb'
|
|
307
|
-
- 'lib/expressir/commands/changes_import_eengine.rb'
|
|
308
|
-
|
|
309
|
-
# Offense count: 5
|
|
310
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
311
|
-
# Configuration parameters: EnforcedStyleForMultiline.
|
|
312
|
-
# SupportedStylesForMultiline: comma, consistent_comma, diff_comma, no_comma
|
|
313
|
-
Style/TrailingCommaInArrayLiteral:
|
|
314
|
-
Exclude:
|
|
315
|
-
- 'spec/expressir/changes/schema_change_spec.rb'
|
|
316
|
-
|
|
317
|
-
# Offense count: 10
|
|
318
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
319
|
-
# Configuration parameters: EnforcedStyleForMultiline.
|
|
320
|
-
# SupportedStylesForMultiline: comma, consistent_comma, diff_comma, no_comma
|
|
321
|
-
Style/TrailingCommaInHashLiteral:
|
|
322
|
-
Exclude:
|
|
323
|
-
- 'bin/validate_all_changes'
|
|
324
|
-
- 'lib/expressir/commands/changes_import_eengine.rb'
|
|
325
|
-
- 'spec/expressir/changes/schema_change_spec.rb'
|
data/README.adoc
CHANGED
|
@@ -724,13 +724,40 @@ This is useful for:
|
|
|
724
724
|
* **Catching errors early**: Validates before committing changes
|
|
725
725
|
* **Cleaning up files**: Removes inconsistencies in formatting
|
|
726
726
|
|
|
727
|
-
==== Importing from
|
|
727
|
+
==== Importing from Express Engine comparison report XML
|
|
728
728
|
|
|
729
|
-
The `changes import-eengine` command converts eengine comparison
|
|
730
|
-
EXPRESS Changes YAML format.
|
|
729
|
+
The `changes import-eengine` command converts Express Engine (eengine) comparison
|
|
730
|
+
XML files to EXPRESS Changes YAML format.
|
|
731
|
+
|
|
732
|
+
The eengine compare XML format is created through
|
|
733
|
+
`exp-engine-engine/kernel/compare.lisp` in the Express Engine code. Expressir is
|
|
734
|
+
compatible with v5.2.7 of eengine output.
|
|
735
|
+
|
|
736
|
+
The import command:
|
|
737
|
+
|
|
738
|
+
. Parses the eengine XML comparison file
|
|
739
|
+
. Automatically detects the XML mode (Schema/ARM/MIM)
|
|
740
|
+
. Extracts additions, modifications, and deletions
|
|
741
|
+
. Converts modified objects to EXPRESS Changes item format
|
|
742
|
+
. Preserves interface change information (`interfaced.items`)
|
|
743
|
+
. Creates or updates an EXPRESS Changes YAML file
|
|
744
|
+
. Supports appending new versions to existing files
|
|
745
|
+
|
|
746
|
+
When the output file already exists:
|
|
747
|
+
|
|
748
|
+
* **Same version**: Replaces the existing edition with that version
|
|
749
|
+
* **New version**: Adds a new edition to the file
|
|
750
|
+
|
|
751
|
+
This allows you to build up a complete change history incrementally across
|
|
752
|
+
multiple schema versions.
|
|
753
|
+
|
|
754
|
+
Syntax:
|
|
731
755
|
|
|
732
756
|
[source, sh]
|
|
733
757
|
----
|
|
758
|
+
# Basic syntax
|
|
759
|
+
expressir changes import-eengine INPUT_XML SCHEMA_NAME VERSION [options]
|
|
760
|
+
|
|
734
761
|
# Import and output to stdout
|
|
735
762
|
expressir changes import-eengine comparison.xml schema_name "2"
|
|
736
763
|
|
|
@@ -744,26 +771,62 @@ expressir changes import-eengine comparison.xml schema_name "2" -o output.yaml -
|
|
|
744
771
|
expressir changes import-eengine comparison.xml schema_name "3" -o existing.yaml
|
|
745
772
|
----
|
|
746
773
|
|
|
747
|
-
|
|
748
|
-
|===
|
|
749
|
-
| Option | Description
|
|
750
|
-
| `-o, --output PATH` | Output YAML file path (stdout if not specified)
|
|
751
|
-
| `--verbose` | Show verbose output
|
|
752
|
-
|===
|
|
774
|
+
Where:
|
|
753
775
|
|
|
754
|
-
|
|
776
|
+
`INPUT_XML`:: Path to the eengine comparison XML file
|
|
777
|
+
`SCHEMA_NAME`:: Name of the schema being tracked (e.g., `aic_csg`, `action_schema`)
|
|
778
|
+
`VERSION`:: Version number for this set of changes (e.g., `"2"`, `"3"`)
|
|
755
779
|
|
|
756
|
-
|
|
757
|
-
. Extracts additions, modifications, and removals
|
|
758
|
-
. Creates or updates an EXPRESS Changes YAML file
|
|
759
|
-
. Supports appending new versions to existing files
|
|
780
|
+
Options:
|
|
760
781
|
|
|
761
|
-
|
|
782
|
+
`-o, --output PATH`:: Output YAML file path (stdout if not specified)
|
|
783
|
+
`--verbose`:: Show verbose output including parsed items
|
|
762
784
|
|
|
763
|
-
|
|
764
|
-
|
|
785
|
+
The command automatically detects and handles all three eengine XML comparison
|
|
786
|
+
formats:
|
|
787
|
+
|
|
788
|
+
Schema mode:: `<schema.changes>` root element with `<schema.additions>`,
|
|
789
|
+
`<schema.modifications>`, and `<schema.deletions>` sections. See API docs for
|
|
790
|
+
details.
|
|
791
|
+
|
|
792
|
+
Example workflow for importing changes from multiple versions:
|
|
793
|
+
|
|
794
|
+
.Importing multiple versions incrementally
|
|
795
|
+
[example]
|
|
796
|
+
[source, sh]
|
|
797
|
+
----
|
|
798
|
+
# Import version 2 changes
|
|
799
|
+
expressir changes import-eengine v2_comparison.xml action_schema "2" \
|
|
800
|
+
-o action_schema.changes.yaml
|
|
765
801
|
|
|
766
|
-
|
|
802
|
+
# Import version 3 changes (appends to existing file)
|
|
803
|
+
expressir changes import-eengine v3_comparison.xml action_schema "3" \
|
|
804
|
+
-o action_schema.changes.yaml
|
|
805
|
+
|
|
806
|
+
# Import version 4 changes (appends to existing file)
|
|
807
|
+
expressir changes import-eengine v4_comparison.xml action_schema "4" \
|
|
808
|
+
-o action_schema.changes.yaml
|
|
809
|
+
|
|
810
|
+
# Verify the result
|
|
811
|
+
cat action_schema.changes.yaml
|
|
812
|
+
----
|
|
813
|
+
|
|
814
|
+
This creates a single YAML file tracking changes across all three versions:
|
|
815
|
+
|
|
816
|
+
[source,yaml]
|
|
817
|
+
----
|
|
818
|
+
schema: action_schema
|
|
819
|
+
editions:
|
|
820
|
+
- version: '2'
|
|
821
|
+
description: Changes from eengine comparison
|
|
822
|
+
additions: [...]
|
|
823
|
+
- version: '3'
|
|
824
|
+
description: Changes from eengine comparison
|
|
825
|
+
additions: [...]
|
|
826
|
+
- version: '4'
|
|
827
|
+
description: Changes from eengine comparison
|
|
828
|
+
additions: [...]
|
|
829
|
+
----
|
|
767
830
|
|
|
768
831
|
|
|
769
832
|
== Usage: Ruby
|
|
@@ -1167,15 +1230,214 @@ expressir coverage schemas.yml --format json --exclude=TYPE:SELECT
|
|
|
1167
1230
|
|
|
1168
1231
|
Expressir provides the `Changes` module for managing and tracking changes to
|
|
1169
1232
|
EXPRESS schemas across versions. This module implements the EXPRESS Changes YAML
|
|
1170
|
-
format defined by ELF (Express Language Foundation).
|
|
1233
|
+
format defined by ELF (Express Language Foundation) (ELF 5005).
|
|
1171
1234
|
|
|
1172
1235
|
The Changes module enables:
|
|
1173
1236
|
|
|
1174
1237
|
* Loading and saving schema change records from/to YAML files
|
|
1175
1238
|
* Programmatic creation and manipulation of change records
|
|
1176
1239
|
* Smart edition handling (replace same version, add new version)
|
|
1177
|
-
* Support for all change types: additions, modifications,
|
|
1240
|
+
* Support for all change types: additions, modifications, deletions
|
|
1178
1241
|
* Support for mapping changes in ARM/MIM schemas
|
|
1242
|
+
* Programmatic import from Express Engine comparison XML files
|
|
1243
|
+
|
|
1244
|
+
|
|
1245
|
+
=== Importing from Express Engine XML programmatically
|
|
1246
|
+
|
|
1247
|
+
==== General
|
|
1248
|
+
|
|
1249
|
+
Expressir provides programmatic API access for parsing Express Engine comparison XML
|
|
1250
|
+
and converting it to EXPRESS Changes format.
|
|
1251
|
+
|
|
1252
|
+
Parse Eengine XML into a structured object model:
|
|
1253
|
+
|
|
1254
|
+
[source,ruby]
|
|
1255
|
+
----
|
|
1256
|
+
require "expressir/eengine/compare_report"
|
|
1257
|
+
|
|
1258
|
+
# Parse from XML string
|
|
1259
|
+
xml_content = File.read("comparison.xml")
|
|
1260
|
+
report = Expressir::Eengine::CompareReport.from_xml(xml_content)
|
|
1261
|
+
|
|
1262
|
+
# Or parse from file
|
|
1263
|
+
report = Expressir::Eengine::CompareReport.from_file("comparison.xml")
|
|
1264
|
+
----
|
|
1265
|
+
|
|
1266
|
+
Convert Eengine XML directly to EXPRESS Changes format:
|
|
1267
|
+
|
|
1268
|
+
[source,ruby]
|
|
1269
|
+
----
|
|
1270
|
+
require "expressir/commands/changes_import_eengine"
|
|
1271
|
+
|
|
1272
|
+
# Parse XML and convert to SchemaChange in one step
|
|
1273
|
+
xml_content = File.read("comparison.xml")
|
|
1274
|
+
change_schema = Expressir::Commands::ChangesImportEengine.from_xml(
|
|
1275
|
+
xml_content,
|
|
1276
|
+
"aic_csg", # schema name
|
|
1277
|
+
"1.0" # version
|
|
1278
|
+
)
|
|
1279
|
+
|
|
1280
|
+
# Use the SchemaChange object
|
|
1281
|
+
change_schema.editions.first.additions.each do |item|
|
|
1282
|
+
puts "#{item.type}: #{item.name}"
|
|
1283
|
+
puts " interfaced_items: #{item.interfaced_items}" if item.interfaced_items
|
|
1284
|
+
end
|
|
1285
|
+
|
|
1286
|
+
# Save to file
|
|
1287
|
+
change_schema.to_file("output.changes.yaml")
|
|
1288
|
+
----
|
|
1289
|
+
|
|
1290
|
+
==== Compare modes
|
|
1291
|
+
|
|
1292
|
+
===== General
|
|
1293
|
+
|
|
1294
|
+
Expressir automatically detects and parses all three Eengine XML modes.
|
|
1295
|
+
|
|
1296
|
+
[source,ruby]
|
|
1297
|
+
----
|
|
1298
|
+
# All modes are handled automatically
|
|
1299
|
+
arm_report = Expressir::Eengine::CompareReport.from_file("arm_comparison.xml")
|
|
1300
|
+
mim_report = Expressir::Eengine::CompareReport.from_file("mim_comparison.xml")
|
|
1301
|
+
schema_report = Expressir::Eengine::CompareReport.from_file("schema_comparison.xml")
|
|
1302
|
+
|
|
1303
|
+
puts arm_report.mode # => "arm"
|
|
1304
|
+
puts mim_report.mode # => "mim"
|
|
1305
|
+
puts schema_report.mode # => "schema"
|
|
1306
|
+
----
|
|
1307
|
+
|
|
1308
|
+
===== Schema mode
|
|
1309
|
+
|
|
1310
|
+
`<schema.changes>` with `<schema.additions>`, `<schema.modifications>`, `<schema.deletions>`
|
|
1311
|
+
|
|
1312
|
+
[example]
|
|
1313
|
+
====
|
|
1314
|
+
[source,xml]
|
|
1315
|
+
----
|
|
1316
|
+
<schema.changes schema_name="aic_csg">
|
|
1317
|
+
<schema.additions>
|
|
1318
|
+
<modified.object type="ENTITY" name="new_entity" />
|
|
1319
|
+
</schema.additions>
|
|
1320
|
+
<schema.modifications>
|
|
1321
|
+
<modified.object type="TYPE" name="modified_type" />
|
|
1322
|
+
</schema.modifications>
|
|
1323
|
+
<schema.deletions>
|
|
1324
|
+
<modified.object type="FUNCTION" name="removed_function" />
|
|
1325
|
+
</schema.deletions>
|
|
1326
|
+
</schema.changes>
|
|
1327
|
+
----
|
|
1328
|
+
====
|
|
1329
|
+
|
|
1330
|
+
===== ARM mode
|
|
1331
|
+
|
|
1332
|
+
`<arm.changes>` root element with `<arm.additions>`,
|
|
1333
|
+
`<arm.modifications>`, and `<arm.deletions>` sections
|
|
1334
|
+
|
|
1335
|
+
[example]
|
|
1336
|
+
====
|
|
1337
|
+
[source,xml]
|
|
1338
|
+
----
|
|
1339
|
+
<arm.changes schema_name="example_arm">
|
|
1340
|
+
<arm.additions>
|
|
1341
|
+
<modified.object type="ENTITY" name="new_arm_entity" />
|
|
1342
|
+
</arm.additions>
|
|
1343
|
+
</arm.changes>
|
|
1344
|
+
----
|
|
1345
|
+
====
|
|
1346
|
+
|
|
1347
|
+
|
|
1348
|
+
===== MIM mode
|
|
1349
|
+
|
|
1350
|
+
`<mim.changes>` root element with `<mim.additions>`,
|
|
1351
|
+
`<mim.modifications>`, and `<mim.deletions>` sections
|
|
1352
|
+
|
|
1353
|
+
[example]
|
|
1354
|
+
====
|
|
1355
|
+
[source,xml]
|
|
1356
|
+
----
|
|
1357
|
+
<mim.changes schema_name="example_mim">
|
|
1358
|
+
<mim.additions>
|
|
1359
|
+
<modified.object type="ENTITY" name="new_mim_entity" />
|
|
1360
|
+
</mim.additions>
|
|
1361
|
+
</mim.changes>
|
|
1362
|
+
----
|
|
1363
|
+
====
|
|
1364
|
+
|
|
1365
|
+
==== Interface changes
|
|
1366
|
+
|
|
1367
|
+
The eengine XML format tracks interface changes (USE_FROM, REFERENCE_FROM) with
|
|
1368
|
+
the `interfaced.items` attribute. This attribute lists the specific items being
|
|
1369
|
+
imported or referenced from another schema.
|
|
1370
|
+
|
|
1371
|
+
.Example XML with interface changes
|
|
1372
|
+
[example]
|
|
1373
|
+
====
|
|
1374
|
+
[source,xml]
|
|
1375
|
+
----
|
|
1376
|
+
<schema.changes schema_name="aic_csg">
|
|
1377
|
+
<schema.additions>
|
|
1378
|
+
<modified.object type="USE_FROM" name="geometric_model_schema"
|
|
1379
|
+
interfaced.items="convex_hexahedron" />
|
|
1380
|
+
|
|
1381
|
+
<modified.object type="USE_FROM" name="geometric_model_schema"
|
|
1382
|
+
interfaced.items="cyclide_segment_solid" />
|
|
1383
|
+
|
|
1384
|
+
<modified.object type="REFERENCE_FROM" name="measure_schema"
|
|
1385
|
+
interfaced.items="length_measure" />
|
|
1386
|
+
</schema.additions>
|
|
1387
|
+
</schema.changes>
|
|
1388
|
+
----
|
|
1389
|
+
|
|
1390
|
+
This will be converted to EXPRESS Changes YAML as:
|
|
1391
|
+
|
|
1392
|
+
[source,yaml]
|
|
1393
|
+
----
|
|
1394
|
+
schema: aic_csg
|
|
1395
|
+
editions:
|
|
1396
|
+
- version: '2'
|
|
1397
|
+
description: Changes from eengine comparison
|
|
1398
|
+
additions:
|
|
1399
|
+
- type: USE_FROM
|
|
1400
|
+
name: geometric_model_schema
|
|
1401
|
+
interfaced_items: convex_hexahedron
|
|
1402
|
+
- type: USE_FROM
|
|
1403
|
+
name: geometric_model_schema
|
|
1404
|
+
interfaced_items: cyclide_segment_solid
|
|
1405
|
+
- type: REFERENCE_FROM
|
|
1406
|
+
name: measure_schema
|
|
1407
|
+
interfaced_items: length_measure
|
|
1408
|
+
----
|
|
1409
|
+
====
|
|
1410
|
+
|
|
1411
|
+
Eengine XML files track interface changes (USE_FROM, REFERENCE_FROM) with the
|
|
1412
|
+
`interfaced.items` attribute:
|
|
1413
|
+
|
|
1414
|
+
[source,ruby]
|
|
1415
|
+
----
|
|
1416
|
+
report = Expressir::Eengine::CompareReport.from_file("comparison.xml")
|
|
1417
|
+
|
|
1418
|
+
# Find interface changes
|
|
1419
|
+
report.additions&.modified_objects&.each do |obj|
|
|
1420
|
+
if obj.type == "USE_FROM" || obj.type == "REFERENCE_FROM"
|
|
1421
|
+
puts "#{obj.type} #{obj.name}"
|
|
1422
|
+
puts " Items: #{obj.interfaced_items}" if obj.interfaced_items
|
|
1423
|
+
end
|
|
1424
|
+
end
|
|
1425
|
+
----
|
|
1426
|
+
|
|
1427
|
+
|
|
1428
|
+
==== Supported change types
|
|
1429
|
+
|
|
1430
|
+
The import command recognizes all standard EXPRESS construct types:
|
|
1431
|
+
|
|
1432
|
+
* `ENTITY` - Entity definitions
|
|
1433
|
+
* `TYPE` - Type definitions
|
|
1434
|
+
* `FUNCTION` - Function definitions
|
|
1435
|
+
* `PROCEDURE` - Procedure definitions
|
|
1436
|
+
* `RULE` - Rule definitions
|
|
1437
|
+
* `CONSTANT` - Constant definitions
|
|
1438
|
+
* `USE_FROM` - Interface imports (preserves `interfaced.items`)
|
|
1439
|
+
* `REFERENCE_FROM` - Interface references (preserves `interfaced.items`)
|
|
1440
|
+
|
|
1179
1441
|
|
|
1180
1442
|
=== Reading change files
|
|
1181
1443
|
|
|
@@ -1192,14 +1454,13 @@ change_schema = Expressir::Changes::SchemaChange.from_file("schema.changes.yaml"
|
|
|
1192
1454
|
puts "Schema: #{change_schema.schema}"
|
|
1193
1455
|
|
|
1194
1456
|
# Iterate through change editions
|
|
1195
|
-
change_schema.
|
|
1457
|
+
change_schema.editions.each do |edition|
|
|
1196
1458
|
puts "Version #{edition.version}: #{edition.description}"
|
|
1197
1459
|
|
|
1198
1460
|
# Access changes by type
|
|
1199
1461
|
puts " Additions: #{edition.additions.size}" if edition.additions
|
|
1200
1462
|
puts " Modifications: #{edition.modifications.size}" if edition.modifications
|
|
1201
1463
|
puts " Deletions: #{edition.deletions.size}" if edition.deletions
|
|
1202
|
-
puts " Removals: #{edition.removals.size}" if edition.removals
|
|
1203
1464
|
end
|
|
1204
1465
|
----
|
|
1205
1466
|
|
|
@@ -1210,7 +1471,7 @@ Create a new change schema programmatically:
|
|
|
1210
1471
|
[source,ruby]
|
|
1211
1472
|
----
|
|
1212
1473
|
# Create a new empty change schema
|
|
1213
|
-
change_schema = Expressir::Changes::SchemaChange.
|
|
1474
|
+
change_schema = Expressir::Changes::SchemaChange.new(schema: "my_schema")
|
|
1214
1475
|
|
|
1215
1476
|
# Create change items
|
|
1216
1477
|
new_entity = Expressir::Changes::ItemChange.new(
|
|
@@ -1228,7 +1489,7 @@ modified_function = Expressir::Changes::ItemChange.new(
|
|
|
1228
1489
|
changes = {
|
|
1229
1490
|
additions: [new_entity],
|
|
1230
1491
|
modifications: [modified_function],
|
|
1231
|
-
|
|
1492
|
+
deletions: []
|
|
1232
1493
|
}
|
|
1233
1494
|
|
|
1234
1495
|
change_schema.add_or_update_edition(
|
|
@@ -1292,9 +1553,8 @@ Change editions support categorizing changes into:
|
|
|
1292
1553
|
|
|
1293
1554
|
`additions`:: New elements added to the schema
|
|
1294
1555
|
`modifications`:: Existing elements that were modified
|
|
1295
|
-
`
|
|
1296
|
-
`
|
|
1297
|
-
`mapping`:: Mapping-related changes (for ARM/MIM modules)
|
|
1556
|
+
`deletions`:: Elements removed from the schema
|
|
1557
|
+
`mappings`:: Mapping-related changes (for ARM/MIM modules)
|
|
1298
1558
|
`changes`:: General changes (alternative to mapping)
|
|
1299
1559
|
|
|
1300
1560
|
[source,ruby]
|
|
@@ -1305,7 +1565,7 @@ edition = Expressir::Changes::EditionChange.new(
|
|
|
1305
1565
|
additions: [item1, item2],
|
|
1306
1566
|
modifications: [item3],
|
|
1307
1567
|
deletions: [item4],
|
|
1308
|
-
|
|
1568
|
+
mappings: [mapping_change]
|
|
1309
1569
|
)
|
|
1310
1570
|
----
|
|
1311
1571
|
|
|
@@ -1326,7 +1586,7 @@ mapping_change = Expressir::Changes::MappingChange.new(
|
|
|
1326
1586
|
----
|
|
1327
1587
|
---
|
|
1328
1588
|
schema: support_resource_schema
|
|
1329
|
-
|
|
1589
|
+
editions:
|
|
1330
1590
|
- version: '2'
|
|
1331
1591
|
description: |-
|
|
1332
1592
|
The definitions of the following EXPRESS entity data types were modified:
|
data/expressir.gemspec
CHANGED
|
@@ -36,6 +36,7 @@ Gem::Specification.new do |spec|
|
|
|
36
36
|
spec.add_dependency "csv"
|
|
37
37
|
spec.add_dependency "liquid"
|
|
38
38
|
spec.add_dependency "lutaml-model"
|
|
39
|
+
spec.add_dependency "moxml"
|
|
39
40
|
spec.add_dependency "parslet", "~> 2.0"
|
|
40
41
|
spec.add_dependency "ruby-progressbar", "~> 1.11"
|
|
41
42
|
spec.add_dependency "table_tennis"
|
|
@@ -12,9 +12,8 @@ module Expressir
|
|
|
12
12
|
attribute :description, :string
|
|
13
13
|
attribute :additions, ItemChange, collection: true
|
|
14
14
|
attribute :modifications, ItemChange, collection: true
|
|
15
|
-
attribute :removals, ItemChange, collection: true
|
|
16
15
|
attribute :deletions, ItemChange, collection: true
|
|
17
|
-
attribute :
|
|
16
|
+
attribute :mappings, MappingChange, collection: true
|
|
18
17
|
attribute :changes, MappingChange, collection: true
|
|
19
18
|
|
|
20
19
|
yaml do
|
|
@@ -22,9 +21,8 @@ module Expressir
|
|
|
22
21
|
map "description", to: :description
|
|
23
22
|
map "additions", to: :additions
|
|
24
23
|
map "modifications", to: :modifications
|
|
25
|
-
map "removals", to: :removals
|
|
26
24
|
map "deletions", to: :deletions
|
|
27
|
-
map "
|
|
25
|
+
map "mappings", to: :mappings
|
|
28
26
|
map "changes", to: :changes
|
|
29
27
|
end
|
|
30
28
|
end
|
|
@@ -6,11 +6,11 @@ module Expressir
|
|
|
6
6
|
module Changes
|
|
7
7
|
# Represents a mapping change entry
|
|
8
8
|
class MappingChange < Lutaml::Model::Serializable
|
|
9
|
-
attribute :
|
|
9
|
+
attribute :name, :string
|
|
10
10
|
attribute :description, :string
|
|
11
11
|
|
|
12
12
|
yaml do
|
|
13
|
-
map "
|
|
13
|
+
map "name", to: :name
|
|
14
14
|
map "description", to: :description
|
|
15
15
|
end
|
|
16
16
|
end
|
|
@@ -8,11 +8,11 @@ module Expressir
|
|
|
8
8
|
# Represents changes to an EXPRESS schema across multiple versions
|
|
9
9
|
class SchemaChange < Lutaml::Model::Serializable
|
|
10
10
|
attribute :schema, :string
|
|
11
|
-
attribute :
|
|
11
|
+
attribute :editions, EditionChange, collection: true
|
|
12
12
|
|
|
13
13
|
yaml do
|
|
14
14
|
map "schema", to: :schema
|
|
15
|
-
map "
|
|
15
|
+
map "editions", to: :editions
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
class << self
|
|
@@ -23,31 +23,26 @@ module Expressir
|
|
|
23
23
|
def from_file(path)
|
|
24
24
|
content = File.read(path)
|
|
25
25
|
# Handle empty or minimal YAML files
|
|
26
|
-
return new
|
|
26
|
+
return new if content.strip == "---" || content.strip.empty?
|
|
27
27
|
|
|
28
28
|
from_yaml(content)
|
|
29
29
|
end
|
|
30
|
-
|
|
31
|
-
# Create a new empty SchemaChange
|
|
32
|
-
#
|
|
33
|
-
# @param schema_name [String] Name of the schema
|
|
34
|
-
# @return [SchemaChange] New instance with empty change editions
|
|
35
|
-
def create_new(schema_name)
|
|
36
|
-
new(schema: schema_name, edition_change: [])
|
|
37
|
-
end
|
|
38
30
|
end
|
|
39
31
|
|
|
40
32
|
# Add or update a change edition in this schema
|
|
41
33
|
#
|
|
42
34
|
# @param version [String] Version number
|
|
43
35
|
# @param description [String] Description of changes
|
|
44
|
-
# @param changes [Hash] Hash with :additions, :modifications, :
|
|
36
|
+
# @param changes [Hash] Hash with :additions, :modifications, :deletions
|
|
45
37
|
# @return [EditionChange] The added or updated edition
|
|
46
38
|
def add_or_update_edition(version, description, changes)
|
|
47
39
|
version_str = version.to_s
|
|
48
40
|
|
|
41
|
+
# Initialize editions array if nil
|
|
42
|
+
self.editions ||= []
|
|
43
|
+
|
|
49
44
|
# Find existing edition with this version
|
|
50
|
-
existing_index =
|
|
45
|
+
existing_index = editions.find_index do |ed|
|
|
51
46
|
ed.version == version_str
|
|
52
47
|
end
|
|
53
48
|
|
|
@@ -57,16 +52,15 @@ module Expressir
|
|
|
57
52
|
description: description,
|
|
58
53
|
additions: changes[:additions] || [],
|
|
59
54
|
modifications: changes[:modifications] || [],
|
|
60
|
-
removals: changes[:removals] || [],
|
|
61
55
|
deletions: changes[:deletions] || [],
|
|
62
56
|
)
|
|
63
57
|
|
|
64
58
|
if existing_index
|
|
65
59
|
# Replace existing edition with same version
|
|
66
|
-
|
|
60
|
+
editions[existing_index] = edition
|
|
67
61
|
else
|
|
68
62
|
# Add new edition
|
|
69
|
-
|
|
63
|
+
editions << edition
|
|
70
64
|
end
|
|
71
65
|
|
|
72
66
|
edition
|
data/lib/expressir/changes.rb
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative "changes/schema_change"
|
|
4
|
-
require_relative "changes/edition_change"
|
|
5
|
-
require_relative "changes/item_change"
|
|
6
|
-
require_relative "changes/mapping_change"
|
|
7
|
-
|
|
8
3
|
module Expressir
|
|
9
4
|
# Module for EXPRESS schema change tracking and management
|
|
10
5
|
module Changes
|
|
11
6
|
end
|
|
12
7
|
end
|
|
8
|
+
|
|
9
|
+
require_relative "changes/schema_change"
|
|
10
|
+
require_relative "changes/mapping_change"
|
|
@@ -1,37 +1,44 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "base"
|
|
4
|
-
|
|
4
|
+
require_relative "../eengine/compare_report"
|
|
5
5
|
|
|
6
6
|
module Expressir
|
|
7
7
|
module Commands
|
|
8
8
|
# Command to import eengine comparison XML to EXPRESS Changes YAML
|
|
9
9
|
class ChangesImportEengine < Base
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
# Parse XML string and convert to SchemaChange
|
|
11
|
+
#
|
|
12
|
+
# @param xml_content [String] Eengine XML content
|
|
13
|
+
# @param schema_name [String] Schema name
|
|
14
|
+
# @param version [String] Version identifier
|
|
15
|
+
# @param options [Hash] Additional options
|
|
16
|
+
# @return [Expressir::Changes::SchemaChange]
|
|
17
|
+
def self.from_xml(xml_content, schema_name, version, **options)
|
|
18
|
+
require "expressir/changes"
|
|
19
|
+
|
|
20
|
+
# Parse into CompareReport using Lutaml::Model
|
|
21
|
+
compare_report = Expressir::Eengine::CompareReport.from_xml(xml_content)
|
|
22
|
+
|
|
23
|
+
# Convert to SchemaChange
|
|
24
|
+
convert_to_schema_change(compare_report, schema_name, version,
|
|
25
|
+
xml_content: xml_content, **options)
|
|
12
26
|
end
|
|
13
27
|
|
|
14
|
-
|
|
28
|
+
# File-based workflow (backward compatible)
|
|
29
|
+
def self.call(input_file, output_file, schema_name, version, **options)
|
|
15
30
|
require "expressir/changes"
|
|
16
31
|
|
|
17
|
-
|
|
18
|
-
xml_doc = File.open(input_file) { |f| Nokogiri::XML(f) }
|
|
19
|
-
|
|
20
|
-
# Extract changes from XML
|
|
21
|
-
changes = extract_changes(xml_doc)
|
|
22
|
-
description = generate_description(xml_doc)
|
|
32
|
+
xml_content = File.read(input_file)
|
|
23
33
|
|
|
24
|
-
# Load
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
Expressir::Changes::SchemaChange.create_new(schema_name)
|
|
29
|
-
end
|
|
34
|
+
# Load existing schema if output file exists
|
|
35
|
+
existing_schema = if output_file && File.exist?(output_file) && File.size(output_file).positive?
|
|
36
|
+
Expressir::Changes::SchemaChange.from_file(output_file)
|
|
37
|
+
end
|
|
30
38
|
|
|
31
|
-
|
|
32
|
-
|
|
39
|
+
change_schema = from_xml(xml_content, schema_name, version,
|
|
40
|
+
existing_schema: existing_schema, **options)
|
|
33
41
|
|
|
34
|
-
# Save to file
|
|
35
42
|
if output_file
|
|
36
43
|
change_schema.to_file(output_file)
|
|
37
44
|
puts "Change YAML file written to: #{output_file}" if options[:verbose]
|
|
@@ -42,65 +49,126 @@ module Expressir
|
|
|
42
49
|
change_schema
|
|
43
50
|
end
|
|
44
51
|
|
|
45
|
-
|
|
52
|
+
class << self
|
|
53
|
+
private
|
|
46
54
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
55
|
+
def convert_to_schema_change(compare_report, schema_name, version,
|
|
56
|
+
**options)
|
|
57
|
+
require "expressir/changes"
|
|
58
|
+
|
|
59
|
+
# Extract changes from CompareReport
|
|
60
|
+
changes = {
|
|
61
|
+
additions: extract_items(compare_report.additions,
|
|
62
|
+
options[:xml_content]),
|
|
63
|
+
modifications: extract_items(compare_report.modifications,
|
|
64
|
+
options[:xml_content]),
|
|
65
|
+
deletions: extract_items(compare_report.deletions,
|
|
66
|
+
options[:xml_content]),
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
# Use existing schema or create new one
|
|
70
|
+
change_schema = options[:existing_schema] ||
|
|
71
|
+
Expressir::Changes::SchemaChange.new(schema: schema_name)
|
|
54
72
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
name: node["name"],
|
|
60
|
-
)
|
|
73
|
+
# No edition-level description from eengine (only item-level)
|
|
74
|
+
change_schema.add_or_update_edition(version, nil, changes)
|
|
75
|
+
|
|
76
|
+
change_schema
|
|
61
77
|
end
|
|
62
|
-
end
|
|
63
78
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
79
|
+
def extract_items(changes_section, xml_content)
|
|
80
|
+
return [] unless changes_section&.modified_objects
|
|
81
|
+
|
|
82
|
+
# Extract descriptions from XML as arrays
|
|
83
|
+
descriptions = extract_descriptions_from_xml(xml_content)
|
|
84
|
+
|
|
85
|
+
changes_section.modified_objects.map do |obj|
|
|
86
|
+
Expressir::Changes::ItemChange.new(
|
|
87
|
+
type: obj.type,
|
|
88
|
+
name: obj.name,
|
|
89
|
+
interfaced_items: obj.interfaced_items,
|
|
90
|
+
description: descriptions[obj.name],
|
|
91
|
+
)
|
|
92
|
+
end
|
|
70
93
|
end
|
|
71
|
-
end
|
|
72
94
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
95
|
+
def extract_descriptions_from_xml(xml_content)
|
|
96
|
+
return {} unless xml_content
|
|
97
|
+
|
|
98
|
+
require "nokogiri"
|
|
99
|
+
doc = Nokogiri::XML(xml_content)
|
|
100
|
+
|
|
101
|
+
doc.xpath("//modified.object").each_with_object({}) do |node, result|
|
|
102
|
+
name = node["name"]
|
|
103
|
+
desc_node = node.at_xpath("description")
|
|
104
|
+
next unless desc_node
|
|
105
|
+
|
|
106
|
+
html = desc_node.inner_html.strip
|
|
107
|
+
next if html.empty?
|
|
108
|
+
|
|
109
|
+
# Extract <li> elements or use text content
|
|
110
|
+
li_elements = Nokogiri::HTML.fragment(html).css("li")
|
|
111
|
+
result[name] = if li_elements.any?
|
|
112
|
+
li_elements.map do |li|
|
|
113
|
+
li.text.strip
|
|
114
|
+
end.reject(&:empty?)
|
|
115
|
+
else
|
|
116
|
+
[Nokogiri::HTML.fragment(html).text.strip]
|
|
117
|
+
end
|
|
118
|
+
end
|
|
79
119
|
end
|
|
80
|
-
end
|
|
81
120
|
|
|
82
|
-
|
|
83
|
-
|
|
121
|
+
def extract_description(compare_report)
|
|
122
|
+
parts = []
|
|
84
123
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
parts << text unless text.empty?
|
|
89
|
-
end
|
|
124
|
+
[compare_report.modifications, compare_report.additions,
|
|
125
|
+
compare_report.deletions].each do |section|
|
|
126
|
+
next unless section&.modified_objects
|
|
90
127
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
128
|
+
section.modified_objects.each do |obj|
|
|
129
|
+
next unless obj.description
|
|
130
|
+
|
|
131
|
+
description_text = normalize_description(obj.description)
|
|
132
|
+
next if description_text.strip.empty?
|
|
133
|
+
|
|
134
|
+
parts << convert_html_to_asciidoc(description_text.strip)
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
parts.empty? ? nil : parts.join("\n\n")
|
|
95
139
|
end
|
|
96
140
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
141
|
+
def normalize_description(description)
|
|
142
|
+
# Handle both String and Array (when XML has nested elements)
|
|
143
|
+
case description
|
|
144
|
+
when String
|
|
145
|
+
description
|
|
146
|
+
when Array
|
|
147
|
+
# Join array elements, handling nested structures
|
|
148
|
+
description.map { |elem| normalize_description(elem) }.join("\n")
|
|
149
|
+
when Hash
|
|
150
|
+
# Handle hash elements (from XML parsing)
|
|
151
|
+
if description.key?("__text__")
|
|
152
|
+
description["__text__"]
|
|
153
|
+
else
|
|
154
|
+
description.values.map { |v| normalize_description(v) }.join("\n")
|
|
155
|
+
end
|
|
156
|
+
else
|
|
157
|
+
description.to_s
|
|
158
|
+
end
|
|
101
159
|
end
|
|
102
160
|
|
|
103
|
-
|
|
161
|
+
def convert_html_to_asciidoc(text)
|
|
162
|
+
# Convert <ul><li>...</li></ul> to AsciiDoc list format
|
|
163
|
+
text = text.gsub(%r{<ul>\s*}i, "")
|
|
164
|
+
text = text.gsub(%r{\s*</ul>}i, "")
|
|
165
|
+
text = text.gsub(%r{<li>(.*?)</li>}im) do
|
|
166
|
+
"* #{Regexp.last_match(1).strip}"
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Clean up any extra whitespace
|
|
170
|
+
text.strip
|
|
171
|
+
end
|
|
104
172
|
end
|
|
105
173
|
end
|
|
106
174
|
end
|
|
@@ -31,7 +31,7 @@ module Expressir
|
|
|
31
31
|
|
|
32
32
|
say "✓ File is valid" if options[:verbose]
|
|
33
33
|
say " Schema: #{schema_change.schema}" if options[:verbose]
|
|
34
|
-
say " Editions: #{schema_change.
|
|
34
|
+
say " Editions: #{schema_change.editions.length}" if options[:verbose]
|
|
35
35
|
|
|
36
36
|
# Normalize if requested
|
|
37
37
|
if options[:normalize]
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
require_relative "changes_section"
|
|
5
|
+
require_relative "modified_object"
|
|
6
|
+
|
|
7
|
+
module Expressir
|
|
8
|
+
module Eengine
|
|
9
|
+
# Represents an Eengine ARM comparison XML report
|
|
10
|
+
class ArmCompareReport < Lutaml::Model::Serializable
|
|
11
|
+
attribute :modifications, ChangesSection
|
|
12
|
+
attribute :additions, ChangesSection
|
|
13
|
+
attribute :deletions, ChangesSection
|
|
14
|
+
|
|
15
|
+
xml do
|
|
16
|
+
root "arm.changes"
|
|
17
|
+
map_element "arm.modifications", to: :modifications
|
|
18
|
+
map_element "arm.additions", to: :additions
|
|
19
|
+
map_element "arm.deletions", to: :deletions
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def mode
|
|
23
|
+
"arm"
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
require_relative "modified_object"
|
|
5
|
+
|
|
6
|
+
module Expressir
|
|
7
|
+
module Eengine
|
|
8
|
+
# Represents a section of changes (modifications, additions, or deletions)
|
|
9
|
+
# in an Eengine comparison report
|
|
10
|
+
class ChangesSection < Lutaml::Model::Serializable
|
|
11
|
+
attribute :modified_objects, ModifiedObject, collection: true
|
|
12
|
+
|
|
13
|
+
xml do
|
|
14
|
+
root "changes.section"
|
|
15
|
+
map_element "modified.object", to: :modified_objects
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
|
|
5
|
+
Lutaml::Model::Config.configure do |config|
|
|
6
|
+
require "lutaml/model/xml_adapter/nokogiri_adapter"
|
|
7
|
+
config.xml_adapter = Lutaml::Model::XmlAdapter::NokogiriAdapter
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
require_relative "changes_section"
|
|
11
|
+
require_relative "modified_object"
|
|
12
|
+
require_relative "arm_compare_report"
|
|
13
|
+
require_relative "mim_compare_report"
|
|
14
|
+
|
|
15
|
+
module Expressir
|
|
16
|
+
module Eengine
|
|
17
|
+
# Represents an Eengine comparison XML report
|
|
18
|
+
# Supports three modes: ARM, MIM, and Schema
|
|
19
|
+
class CompareReport < Lutaml::Model::Serializable
|
|
20
|
+
attribute :modifications, ChangesSection
|
|
21
|
+
attribute :additions, ChangesSection
|
|
22
|
+
attribute :deletions, ChangesSection
|
|
23
|
+
|
|
24
|
+
xml do
|
|
25
|
+
root "schema.changes"
|
|
26
|
+
map_element "schema.modifications", to: :modifications
|
|
27
|
+
map_element "schema.additions", to: :additions
|
|
28
|
+
map_element "schema.deletions", to: :deletions
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
class << self
|
|
32
|
+
# Parse XML and return appropriate report class based on mode
|
|
33
|
+
#
|
|
34
|
+
# @param xml_content [String] XML content
|
|
35
|
+
# @return [CompareReport, ArmCompareReport, MimCompareReport]
|
|
36
|
+
def from_xml(xml_content)
|
|
37
|
+
mode = detect_mode(xml_content)
|
|
38
|
+
|
|
39
|
+
case mode
|
|
40
|
+
when "arm"
|
|
41
|
+
ArmCompareReport.from_xml(xml_content)
|
|
42
|
+
when "mim"
|
|
43
|
+
MimCompareReport.from_xml(xml_content)
|
|
44
|
+
else
|
|
45
|
+
super
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Load a CompareReport from an XML file
|
|
50
|
+
#
|
|
51
|
+
# @param path [String] Path to the XML file
|
|
52
|
+
# @return [CompareReport] The loaded comparison report
|
|
53
|
+
def from_file(path)
|
|
54
|
+
from_xml(File.read(path))
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
# Detect XML mode from content
|
|
60
|
+
#
|
|
61
|
+
# @param xml_content [String] XML content
|
|
62
|
+
# @return [String] "arm", "mim", or "schema"
|
|
63
|
+
def detect_mode(xml_content)
|
|
64
|
+
if xml_content.include?("<arm.changes")
|
|
65
|
+
"arm"
|
|
66
|
+
elsif xml_content.include?("<mim.changes")
|
|
67
|
+
"mim"
|
|
68
|
+
else
|
|
69
|
+
"schema"
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Detect XML mode from the report
|
|
75
|
+
# @return [String] "arm", "mim", or "schema"
|
|
76
|
+
def mode
|
|
77
|
+
"schema"
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
require_relative "changes_section"
|
|
5
|
+
require_relative "modified_object"
|
|
6
|
+
|
|
7
|
+
module Expressir
|
|
8
|
+
module Eengine
|
|
9
|
+
# Represents an Eengine MIM comparison XML report
|
|
10
|
+
class MimCompareReport < Lutaml::Model::Serializable
|
|
11
|
+
attribute :modifications, ChangesSection
|
|
12
|
+
attribute :additions, ChangesSection
|
|
13
|
+
attribute :deletions, ChangesSection
|
|
14
|
+
|
|
15
|
+
xml do
|
|
16
|
+
root "mim.changes"
|
|
17
|
+
map_element "mim.modifications", to: :modifications
|
|
18
|
+
map_element "mim.additions", to: :additions
|
|
19
|
+
map_element "mim.deletions", to: :deletions
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def mode
|
|
23
|
+
"mim"
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
|
|
5
|
+
module Expressir
|
|
6
|
+
module Eengine
|
|
7
|
+
# Represents a modified EXPRESS object in an Eengine comparison report
|
|
8
|
+
class ModifiedObject < Lutaml::Model::Serializable
|
|
9
|
+
attribute :type, :string
|
|
10
|
+
attribute :name, :string
|
|
11
|
+
attribute :interfaced_items, :string
|
|
12
|
+
attribute :description, :string
|
|
13
|
+
|
|
14
|
+
xml do
|
|
15
|
+
root "modified.object"
|
|
16
|
+
map_attribute "type", to: :type
|
|
17
|
+
map_attribute "name", to: :name
|
|
18
|
+
map_attribute "interfaced.items", to: :interfaced_items
|
|
19
|
+
map_element "description", to: :description
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
data/lib/expressir/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: expressir
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.1.
|
|
4
|
+
version: 2.1.29
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-10-
|
|
11
|
+
date: 2025-10-15 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: base64
|
|
@@ -80,6 +80,20 @@ dependencies:
|
|
|
80
80
|
- - ">="
|
|
81
81
|
- !ruby/object:Gem::Version
|
|
82
82
|
version: '0'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: moxml
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - ">="
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '0'
|
|
90
|
+
type: :runtime
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - ">="
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '0'
|
|
83
97
|
- !ruby/object:Gem::Dependency
|
|
84
98
|
name: parslet
|
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -188,6 +202,11 @@ files:
|
|
|
188
202
|
- lib/expressir/commands/version.rb
|
|
189
203
|
- lib/expressir/config.rb
|
|
190
204
|
- lib/expressir/coverage.rb
|
|
205
|
+
- lib/expressir/eengine/arm_compare_report.rb
|
|
206
|
+
- lib/expressir/eengine/changes_section.rb
|
|
207
|
+
- lib/expressir/eengine/compare_report.rb
|
|
208
|
+
- lib/expressir/eengine/mim_compare_report.rb
|
|
209
|
+
- lib/expressir/eengine/modified_object.rb
|
|
191
210
|
- lib/expressir/express/cache.rb
|
|
192
211
|
- lib/expressir/express/error.rb
|
|
193
212
|
- lib/expressir/express/formatter.rb
|