expressir 2.1.28 → 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 +57 -15
- data/README.adoc +280 -22
- data/lib/expressir/changes/edition_change.rb +2 -2
- data/lib/expressir/changes/item_change.rb +1 -1
- data/lib/expressir/changes/mapping_change.rb +2 -2
- data/lib/expressir/commands/changes_import_eengine.rb +126 -88
- 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 +7 -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,23 +1,61 @@
|
|
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
|
+
# This cop supports safe autocorrection (--autocorrect).
|
11
|
+
# Configuration parameters: EnforcedStyle, IndentationWidth.
|
12
|
+
# SupportedStyles: with_first_argument, with_fixed_indentation
|
13
|
+
Layout/ArgumentAlignment:
|
14
|
+
Exclude:
|
15
|
+
- 'lib/expressir/commands/changes_import_eengine.rb'
|
16
|
+
|
17
|
+
# Offense count: 4
|
18
|
+
# This cop supports safe autocorrection (--autocorrect).
|
19
|
+
# Configuration parameters: EnforcedStyleAlignWith.
|
20
|
+
# SupportedStylesAlignWith: either, start_of_block, start_of_line
|
21
|
+
Layout/BlockAlignment:
|
22
|
+
Exclude:
|
23
|
+
- 'lib/expressir/commands/changes_import_eengine.rb'
|
24
|
+
- 'spec/expressir/commands/changes_import_eengine_spec.rb'
|
25
|
+
|
26
|
+
# Offense count: 4
|
27
|
+
# This cop supports safe autocorrection (--autocorrect).
|
28
|
+
Layout/BlockEndNewline:
|
29
|
+
Exclude:
|
30
|
+
- 'lib/expressir/commands/changes_import_eengine.rb'
|
31
|
+
- 'spec/expressir/commands/changes_import_eengine_spec.rb'
|
32
|
+
|
33
|
+
# Offense count: 8
|
34
|
+
# This cop supports safe autocorrection (--autocorrect).
|
35
|
+
# Configuration parameters: Width, AllowedPatterns.
|
36
|
+
Layout/IndentationWidth:
|
37
|
+
Exclude:
|
38
|
+
- 'lib/expressir/commands/changes_import_eengine.rb'
|
39
|
+
- 'spec/expressir/commands/changes_import_eengine_spec.rb'
|
40
|
+
|
41
|
+
# Offense count: 569
|
10
42
|
# This cop supports safe autocorrection (--autocorrect).
|
11
43
|
# Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings.
|
12
44
|
# URISchemes: http, https
|
13
45
|
Layout/LineLength:
|
14
46
|
Enabled: false
|
15
47
|
|
16
|
-
# Offense count:
|
48
|
+
# Offense count: 3
|
49
|
+
# This cop supports safe autocorrection (--autocorrect).
|
50
|
+
# Configuration parameters: AllowInHeredoc.
|
51
|
+
Layout/TrailingWhitespace:
|
52
|
+
Exclude:
|
53
|
+
- 'lib/expressir/commands/changes_import_eengine.rb'
|
54
|
+
|
55
|
+
# Offense count: 1
|
17
56
|
# Configuration parameters: IgnoreLiteralBranches, IgnoreConstantBranches, IgnoreDuplicateElseBranch.
|
18
57
|
Lint/DuplicateBranch:
|
19
58
|
Exclude:
|
20
|
-
- 'lib/expressir/commands/changes_import_eengine.rb'
|
21
59
|
- 'lib/expressir/coverage.rb'
|
22
60
|
|
23
61
|
# Offense count: 2
|
@@ -40,7 +78,7 @@ Metrics/AbcSize:
|
|
40
78
|
Metrics/BlockLength:
|
41
79
|
Max: 46
|
42
80
|
|
43
|
-
# Offense count:
|
81
|
+
# Offense count: 61
|
44
82
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
45
83
|
Metrics/CyclomaticComplexity:
|
46
84
|
Exclude:
|
@@ -58,12 +96,12 @@ Metrics/CyclomaticComplexity:
|
|
58
96
|
- 'lib/expressir/model/model_element.rb'
|
59
97
|
- 'spec/support/model_element_helper.rb'
|
60
98
|
|
61
|
-
# Offense count:
|
99
|
+
# Offense count: 113
|
62
100
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
63
101
|
Metrics/MethodLength:
|
64
102
|
Max: 106
|
65
103
|
|
66
|
-
# Offense count:
|
104
|
+
# Offense count: 48
|
67
105
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
68
106
|
Metrics/PerceivedComplexity:
|
69
107
|
Exclude:
|
@@ -134,6 +172,18 @@ RSpec/RepeatedExample:
|
|
134
172
|
Exclude:
|
135
173
|
- 'spec/expressir/model/data_types/logical_spec.rb'
|
136
174
|
|
175
|
+
# Offense count: 6
|
176
|
+
# This cop supports safe autocorrection (--autocorrect).
|
177
|
+
# Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, AllowedMethods, AllowedPatterns, AllowBracesOnProceduralOneLiners, BracesRequiredMethods.
|
178
|
+
# SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces
|
179
|
+
# ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object
|
180
|
+
# FunctionalMethods: let, let!, subject, watch
|
181
|
+
# AllowedMethods: lambda, proc, it
|
182
|
+
Style/BlockDelimiters:
|
183
|
+
Exclude:
|
184
|
+
- 'lib/expressir/commands/changes_import_eengine.rb'
|
185
|
+
- 'spec/expressir/commands/changes_import_eengine_spec.rb'
|
186
|
+
|
137
187
|
# Offense count: 1
|
138
188
|
# This cop supports safe autocorrection (--autocorrect).
|
139
189
|
# Configuration parameters: EnforcedStyle, AllowComments.
|
@@ -146,11 +196,3 @@ Style/EmptyElse:
|
|
146
196
|
Style/MissingRespondToMissing:
|
147
197
|
Exclude:
|
148
198
|
- 'lib/expressir/express/visitor.rb'
|
149
|
-
|
150
|
-
# Offense count: 1
|
151
|
-
# This cop supports unsafe autocorrection (--autocorrect-all).
|
152
|
-
# Configuration parameters: AllowMethodsWithArguments, AllowedMethods, AllowedPatterns, AllowComments.
|
153
|
-
# AllowedMethods: define_method
|
154
|
-
Style/SymbolProc:
|
155
|
-
Exclude:
|
156
|
-
- 'spec/expressir/commands/changes_import_eengine_spec.rb'
|
data/README.adoc
CHANGED
@@ -724,17 +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
731
|
|
732
732
|
The eengine compare XML format is created through
|
733
|
-
`exp-engine-engine/kernel/compare.lisp` in the
|
733
|
+
`exp-engine-engine/kernel/compare.lisp` in the Express Engine code. Expressir is
|
734
734
|
compatible with v5.2.7 of eengine output.
|
735
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:
|
755
|
+
|
736
756
|
[source, sh]
|
737
757
|
----
|
758
|
+
# Basic syntax
|
759
|
+
expressir changes import-eengine INPUT_XML SCHEMA_NAME VERSION [options]
|
760
|
+
|
738
761
|
# Import and output to stdout
|
739
762
|
expressir changes import-eengine comparison.xml schema_name "2"
|
740
763
|
|
@@ -748,26 +771,62 @@ expressir changes import-eengine comparison.xml schema_name "2" -o output.yaml -
|
|
748
771
|
expressir changes import-eengine comparison.xml schema_name "3" -o existing.yaml
|
749
772
|
----
|
750
773
|
|
751
|
-
|
752
|
-
|===
|
753
|
-
| Option | Description
|
754
|
-
| `-o, --output PATH` | Output YAML file path (stdout if not specified)
|
755
|
-
| `--verbose` | Show verbose output
|
756
|
-
|===
|
774
|
+
Where:
|
757
775
|
|
758
|
-
|
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"`)
|
759
779
|
|
760
|
-
|
761
|
-
. Extracts additions, modifications, and deletions
|
762
|
-
. Creates or updates an EXPRESS Changes YAML file
|
763
|
-
. Supports appending new versions to existing files
|
780
|
+
Options:
|
764
781
|
|
765
|
-
|
782
|
+
`-o, --output PATH`:: Output YAML file path (stdout if not specified)
|
783
|
+
`--verbose`:: Show verbose output including parsed items
|
766
784
|
|
767
|
-
|
768
|
-
|
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
|
769
801
|
|
770
|
-
|
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
|
+
----
|
771
830
|
|
772
831
|
|
773
832
|
== Usage: Ruby
|
@@ -1171,7 +1230,7 @@ expressir coverage schemas.yml --format json --exclude=TYPE:SELECT
|
|
1171
1230
|
|
1172
1231
|
Expressir provides the `Changes` module for managing and tracking changes to
|
1173
1232
|
EXPRESS schemas across versions. This module implements the EXPRESS Changes YAML
|
1174
|
-
format defined by ELF (Express Language Foundation).
|
1233
|
+
format defined by ELF (Express Language Foundation) (ELF 5005).
|
1175
1234
|
|
1176
1235
|
The Changes module enables:
|
1177
1236
|
|
@@ -1180,6 +1239,205 @@ The Changes module enables:
|
|
1180
1239
|
* Smart edition handling (replace same version, add new version)
|
1181
1240
|
* Support for all change types: additions, modifications, deletions
|
1182
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
|
+
|
1183
1441
|
|
1184
1442
|
=== Reading change files
|
1185
1443
|
|
@@ -1296,7 +1554,7 @@ Change editions support categorizing changes into:
|
|
1296
1554
|
`additions`:: New elements added to the schema
|
1297
1555
|
`modifications`:: Existing elements that were modified
|
1298
1556
|
`deletions`:: Elements removed from the schema
|
1299
|
-
`
|
1557
|
+
`mappings`:: Mapping-related changes (for ARM/MIM modules)
|
1300
1558
|
`changes`:: General changes (alternative to mapping)
|
1301
1559
|
|
1302
1560
|
[source,ruby]
|
@@ -1307,7 +1565,7 @@ edition = Expressir::Changes::EditionChange.new(
|
|
1307
1565
|
additions: [item1, item2],
|
1308
1566
|
modifications: [item3],
|
1309
1567
|
deletions: [item4],
|
1310
|
-
|
1568
|
+
mappings: [mapping_change]
|
1311
1569
|
)
|
1312
1570
|
----
|
1313
1571
|
|
@@ -13,7 +13,7 @@ module Expressir
|
|
13
13
|
attribute :additions, ItemChange, collection: true
|
14
14
|
attribute :modifications, ItemChange, collection: true
|
15
15
|
attribute :deletions, ItemChange, collection: true
|
16
|
-
attribute :
|
16
|
+
attribute :mappings, MappingChange, collection: true
|
17
17
|
attribute :changes, MappingChange, collection: true
|
18
18
|
|
19
19
|
yaml do
|
@@ -22,7 +22,7 @@ module Expressir
|
|
22
22
|
map "additions", to: :additions
|
23
23
|
map "modifications", to: :modifications
|
24
24
|
map "deletions", to: :deletions
|
25
|
-
map "
|
25
|
+
map "mappings", to: :mappings
|
26
26
|
map "changes", to: :changes
|
27
27
|
end
|
28
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
|
@@ -1,41 +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
|
-
# Parse the eengine XML using Moxml
|
18
32
|
xml_content = File.read(input_file)
|
19
|
-
xml_doc = Moxml.new.parse(xml_content)
|
20
|
-
|
21
|
-
# Detect XML mode from root element
|
22
|
-
xml_mode = detect_xml_mode(xml_doc)
|
23
33
|
|
24
|
-
#
|
25
|
-
|
26
|
-
|
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
|
27
38
|
|
28
|
-
|
29
|
-
|
30
|
-
Expressir::Changes::SchemaChange.from_file(output_file)
|
31
|
-
else
|
32
|
-
Expressir::Changes::SchemaChange.new(schema: schema_name)
|
33
|
-
end
|
39
|
+
change_schema = from_xml(xml_content, schema_name, version,
|
40
|
+
existing_schema: existing_schema, **options)
|
34
41
|
|
35
|
-
# Add or update edition
|
36
|
-
change_schema.add_or_update_edition(version, description, changes)
|
37
|
-
|
38
|
-
# Save to file
|
39
42
|
if output_file
|
40
43
|
change_schema.to_file(output_file)
|
41
44
|
puts "Change YAML file written to: #{output_file}" if options[:verbose]
|
@@ -46,91 +49,126 @@ module Expressir
|
|
46
49
|
change_schema
|
47
50
|
end
|
48
51
|
|
49
|
-
|
52
|
+
class << self
|
53
|
+
private
|
50
54
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
return nil unless root
|
55
|
+
def convert_to_schema_change(compare_report, schema_name, version,
|
56
|
+
**options)
|
57
|
+
require "expressir/changes"
|
55
58
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
"schema"
|
66
|
-
end
|
67
|
-
end
|
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
68
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
modifications: extract_modified_objects(xml_doc, xml_mode),
|
73
|
-
deletions: extract_deleted_objects(xml_doc, xml_mode),
|
74
|
-
}
|
75
|
-
end
|
69
|
+
# Use existing schema or create new one
|
70
|
+
change_schema = options[:existing_schema] ||
|
71
|
+
Expressir::Changes::SchemaChange.new(schema: schema_name)
|
76
72
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
73
|
+
# No edition-level description from eengine (only item-level)
|
74
|
+
change_schema.add_or_update_edition(version, nil, changes)
|
75
|
+
|
76
|
+
change_schema
|
81
77
|
end
|
82
|
-
end
|
83
78
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
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
|
88
93
|
end
|
89
|
-
end
|
90
94
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
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
|
95
119
|
end
|
96
|
-
end
|
97
120
|
|
98
|
-
|
99
|
-
|
100
|
-
type: node["type"],
|
101
|
-
name: node["name"],
|
102
|
-
)
|
121
|
+
def extract_description(compare_report)
|
122
|
+
parts = []
|
103
123
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
end
|
124
|
+
[compare_report.modifications, compare_report.additions,
|
125
|
+
compare_report.deletions].each do |section|
|
126
|
+
next unless section&.modified_objects
|
108
127
|
|
109
|
-
|
110
|
-
|
128
|
+
section.modified_objects.each do |obj|
|
129
|
+
next unless obj.description
|
111
130
|
|
112
|
-
|
113
|
-
|
131
|
+
description_text = normalize_description(obj.description)
|
132
|
+
next if description_text.strip.empty?
|
114
133
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
parts << text unless text.empty?
|
119
|
-
end
|
134
|
+
parts << convert_html_to_asciidoc(description_text.strip)
|
135
|
+
end
|
136
|
+
end
|
120
137
|
|
121
|
-
|
122
|
-
xml_doc.xpath("//#{xml_mode}.additions/modified.object/description").each do |desc|
|
123
|
-
text = desc.text.strip
|
124
|
-
parts << text unless text.empty?
|
138
|
+
parts.empty? ? nil : parts.join("\n\n")
|
125
139
|
end
|
126
140
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
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
|
131
159
|
end
|
132
160
|
|
133
|
-
|
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
|
134
172
|
end
|
135
173
|
end
|
136
174
|
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 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
|
@@ -202,6 +202,11 @@ files:
|
|
202
202
|
- lib/expressir/commands/version.rb
|
203
203
|
- lib/expressir/config.rb
|
204
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
|
205
210
|
- lib/expressir/express/cache.rb
|
206
211
|
- lib/expressir/express/error.rb
|
207
212
|
- lib/expressir/express/formatter.rb
|