expressir 2.1.28 → 2.1.30
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 +7 -16
- data/README.adoc +300 -42
- 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 +32 -22
- data/lib/expressir/changes/{edition_change.rb → version_change.rb} +5 -5
- data/lib/expressir/commands/changes_import_eengine.rb +126 -88
- 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
- data/lib/expressir.rb +1 -1
- metadata +8 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8b14a8f31cc94d89bc7229adf4ceb23a0180bc9bdf36e01024b7f1b27b638a9f
|
|
4
|
+
data.tar.gz: 249f65e92a803eac2a10a9c0717104e4e194d19b7fe30374f733e48b8807ab01
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7dbf61a6903ef0317b98fcbfd3b5056258b263001e81cf9150aa52a3712e7b040e2289fb8b779d1843428617f5b29002de4deb79775aa0e28182488d14ca8f2f
|
|
7
|
+
data.tar.gz: c1c6057d4618d4caf1c6af8ad39cf3c165e3ecbebc6894ffc98b47c777ec19b3a0c6c91798fcb055be3a8cc6d1e46bc69e128de87db1a512f9069d6281e3c19f
|
data/.rubocop_todo.yml
CHANGED
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
# This configuration was generated by
|
|
2
2
|
# `rubocop --auto-gen-config`
|
|
3
|
-
# on 2025-10-
|
|
3
|
+
# on 2025-10-16 03:45:37 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: 562
|
|
10
10
|
# This cop supports safe autocorrection (--autocorrect).
|
|
11
11
|
# Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings.
|
|
12
12
|
# URISchemes: http, https
|
|
13
13
|
Layout/LineLength:
|
|
14
14
|
Enabled: false
|
|
15
15
|
|
|
16
|
-
# Offense count:
|
|
16
|
+
# Offense count: 1
|
|
17
17
|
# Configuration parameters: IgnoreLiteralBranches, IgnoreConstantBranches, IgnoreDuplicateElseBranch.
|
|
18
18
|
Lint/DuplicateBranch:
|
|
19
19
|
Exclude:
|
|
20
|
-
- 'lib/expressir/commands/changes_import_eengine.rb'
|
|
21
20
|
- 'lib/expressir/coverage.rb'
|
|
22
21
|
|
|
23
22
|
# Offense count: 2
|
|
@@ -29,7 +28,7 @@ Lint/UnusedMethodArgument:
|
|
|
29
28
|
- 'lib/expressir/express/cache.rb'
|
|
30
29
|
- 'lib/expressir/express/parser.rb'
|
|
31
30
|
|
|
32
|
-
# Offense count:
|
|
31
|
+
# Offense count: 84
|
|
33
32
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
|
|
34
33
|
Metrics/AbcSize:
|
|
35
34
|
Enabled: false
|
|
@@ -40,7 +39,7 @@ Metrics/AbcSize:
|
|
|
40
39
|
Metrics/BlockLength:
|
|
41
40
|
Max: 46
|
|
42
41
|
|
|
43
|
-
# Offense count:
|
|
42
|
+
# Offense count: 61
|
|
44
43
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
|
45
44
|
Metrics/CyclomaticComplexity:
|
|
46
45
|
Exclude:
|
|
@@ -58,12 +57,12 @@ Metrics/CyclomaticComplexity:
|
|
|
58
57
|
- 'lib/expressir/model/model_element.rb'
|
|
59
58
|
- 'spec/support/model_element_helper.rb'
|
|
60
59
|
|
|
61
|
-
# Offense count:
|
|
60
|
+
# Offense count: 114
|
|
62
61
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
|
63
62
|
Metrics/MethodLength:
|
|
64
63
|
Max: 106
|
|
65
64
|
|
|
66
|
-
# Offense count:
|
|
65
|
+
# Offense count: 48
|
|
67
66
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
|
68
67
|
Metrics/PerceivedComplexity:
|
|
69
68
|
Exclude:
|
|
@@ -146,11 +145,3 @@ Style/EmptyElse:
|
|
|
146
145
|
Style/MissingRespondToMissing:
|
|
147
146
|
Exclude:
|
|
148
147
|
- '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 version with that version
|
|
749
|
+
* **New version**: Adds a new version 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
|
|
784
|
+
|
|
785
|
+
The command automatically detects and handles all three eengine XML comparison
|
|
786
|
+
formats:
|
|
766
787
|
|
|
767
|
-
|
|
768
|
-
|
|
788
|
+
Schema mode:: `<schema.changes>` root element with `<schema.additions>`,
|
|
789
|
+
`<schema.modifications>`, and `<schema.deletions>` sections. See API docs for
|
|
790
|
+
details.
|
|
769
791
|
|
|
770
|
-
|
|
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
|
|
801
|
+
|
|
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
|
+
versions:
|
|
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,15 +1230,214 @@ 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
|
|
|
1178
1237
|
* Loading and saving schema change records from/to YAML files
|
|
1179
1238
|
* Programmatic creation and manipulation of change records
|
|
1180
|
-
* Smart
|
|
1239
|
+
* Smart version 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.versions.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
|
+
versions:
|
|
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
|
|
|
@@ -1195,14 +1453,14 @@ change_schema = Expressir::Changes::SchemaChange.from_file("schema.changes.yaml"
|
|
|
1195
1453
|
# Access schema name
|
|
1196
1454
|
puts "Schema: #{change_schema.schema}"
|
|
1197
1455
|
|
|
1198
|
-
# Iterate through change
|
|
1199
|
-
change_schema.
|
|
1200
|
-
puts "Version #{
|
|
1456
|
+
# Iterate through change versions
|
|
1457
|
+
change_schema.versions.each do |version|
|
|
1458
|
+
puts "Version #{version.version}: #{version.description}"
|
|
1201
1459
|
|
|
1202
1460
|
# Access changes by type
|
|
1203
|
-
puts " Additions: #{
|
|
1204
|
-
puts " Modifications: #{
|
|
1205
|
-
puts " Deletions: #{
|
|
1461
|
+
puts " Additions: #{version.additions.size}" if version.additions
|
|
1462
|
+
puts " Modifications: #{version.modifications.size}" if version.modifications
|
|
1463
|
+
puts " Deletions: #{version.deletions.size}" if version.deletions
|
|
1206
1464
|
end
|
|
1207
1465
|
----
|
|
1208
1466
|
|
|
@@ -1227,14 +1485,14 @@ modified_function = Expressir::Changes::ItemChange.new(
|
|
|
1227
1485
|
description: "Updated parameters"
|
|
1228
1486
|
)
|
|
1229
1487
|
|
|
1230
|
-
# Add a change
|
|
1488
|
+
# Add a change version
|
|
1231
1489
|
changes = {
|
|
1232
1490
|
additions: [new_entity],
|
|
1233
1491
|
modifications: [modified_function],
|
|
1234
1492
|
deletions: []
|
|
1235
1493
|
}
|
|
1236
1494
|
|
|
1237
|
-
change_schema.
|
|
1495
|
+
change_schema.add_or_update_version(
|
|
1238
1496
|
"2",
|
|
1239
1497
|
"Added new entity and modified function",
|
|
1240
1498
|
changes
|
|
@@ -1246,10 +1504,10 @@ change_schema.to_file("my_schema.changes.yaml")
|
|
|
1246
1504
|
|
|
1247
1505
|
=== Updating existing change files
|
|
1248
1506
|
|
|
1249
|
-
The `
|
|
1507
|
+
The `add_or_update_version` method provides smart handling:
|
|
1250
1508
|
|
|
1251
|
-
* **Same version**: Replaces the existing
|
|
1252
|
-
* **Different version**: Adds a new
|
|
1509
|
+
* **Same version**: Replaces the existing version
|
|
1510
|
+
* **Different version**: Adds a new version
|
|
1253
1511
|
|
|
1254
1512
|
[source,ruby]
|
|
1255
1513
|
----
|
|
@@ -1262,10 +1520,10 @@ changes = {
|
|
|
1262
1520
|
Expressir::Changes::ItemChange.new(type: "TYPE", name: "updated_type")
|
|
1263
1521
|
]
|
|
1264
1522
|
}
|
|
1265
|
-
change_schema.
|
|
1523
|
+
change_schema.add_or_update_version("3", "Modified type definition", changes)
|
|
1266
1524
|
|
|
1267
1525
|
# Or replace existing version
|
|
1268
|
-
change_schema.
|
|
1526
|
+
change_schema.add_or_update_version("2", "Revised description", changes)
|
|
1269
1527
|
|
|
1270
1528
|
# Save changes
|
|
1271
1529
|
change_schema.to_file("schema.changes.yaml")
|
|
@@ -1289,25 +1547,25 @@ item = Expressir::Changes::ItemChange.new(
|
|
|
1289
1547
|
)
|
|
1290
1548
|
----
|
|
1291
1549
|
|
|
1292
|
-
=== Change
|
|
1550
|
+
=== Change version fields
|
|
1293
1551
|
|
|
1294
|
-
Change
|
|
1552
|
+
Change versions support categorizing changes into:
|
|
1295
1553
|
|
|
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]
|
|
1303
1561
|
----
|
|
1304
|
-
|
|
1562
|
+
version = Expressir::Changes::VersionChange.new(
|
|
1305
1563
|
version: "2",
|
|
1306
1564
|
description: "Added support for new functionality",
|
|
1307
1565
|
additions: [item1, item2],
|
|
1308
1566
|
modifications: [item3],
|
|
1309
1567
|
deletions: [item4],
|
|
1310
|
-
|
|
1568
|
+
mappings: [mapping_change]
|
|
1311
1569
|
)
|
|
1312
1570
|
----
|
|
1313
1571
|
|
|
@@ -1328,8 +1586,8 @@ mapping_change = Expressir::Changes::MappingChange.new(
|
|
|
1328
1586
|
----
|
|
1329
1587
|
---
|
|
1330
1588
|
schema: support_resource_schema
|
|
1331
|
-
|
|
1332
|
-
- version:
|
|
1589
|
+
versions:
|
|
1590
|
+
- version: 2
|
|
1333
1591
|
description: |-
|
|
1334
1592
|
The definitions of the following EXPRESS entity data types were modified:
|
|
1335
1593
|
|
|
@@ -1342,7 +1600,7 @@ editions:
|
|
|
1342
1600
|
modifications:
|
|
1343
1601
|
- type: FUNCTION
|
|
1344
1602
|
name: bag_to_set
|
|
1345
|
-
- version:
|
|
1603
|
+
- version: 4
|
|
1346
1604
|
description: |-
|
|
1347
1605
|
Added support for external element references.
|
|
1348
1606
|
additions:
|
|
@@ -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,18 +1,18 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "lutaml/model"
|
|
4
|
-
require_relative "
|
|
4
|
+
require_relative "version_change"
|
|
5
5
|
|
|
6
6
|
module Expressir
|
|
7
7
|
module Changes
|
|
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 :versions, VersionChange, collection: true
|
|
12
12
|
|
|
13
13
|
yaml do
|
|
14
14
|
map "schema", to: :schema
|
|
15
|
-
map "
|
|
15
|
+
map "versions", to: :versions
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
class << self
|
|
@@ -23,32 +23,40 @@ module Expressir
|
|
|
23
23
|
def from_file(path)
|
|
24
24
|
content = File.read(path)
|
|
25
25
|
# Handle empty or minimal YAML files
|
|
26
|
+
# Skip leading comments and empty lines
|
|
27
|
+
lines = content.lines
|
|
28
|
+
yaml_start_index = lines.find_index do |line|
|
|
29
|
+
!line.strip.start_with?("#") && !line.strip.empty?
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
if yaml_start_index
|
|
33
|
+
content = lines[yaml_start_index..].join
|
|
34
|
+
end
|
|
35
|
+
|
|
26
36
|
return new if content.strip == "---" || content.strip.empty?
|
|
27
37
|
|
|
28
38
|
from_yaml(content)
|
|
29
39
|
end
|
|
30
40
|
end
|
|
31
41
|
|
|
32
|
-
# Add or update a change
|
|
42
|
+
# Add or update a change version in this schema
|
|
33
43
|
#
|
|
34
44
|
# @param version [String] Version number
|
|
35
45
|
# @param description [String] Description of changes
|
|
36
46
|
# @param changes [Hash] Hash with :additions, :modifications, :deletions
|
|
37
|
-
# @return [
|
|
38
|
-
def
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
# Initialize editions array if nil
|
|
42
|
-
self.editions ||= []
|
|
47
|
+
# @return [VersionChange] The added or updated version
|
|
48
|
+
def add_or_update_version(version, description, changes)
|
|
49
|
+
# Initialize versions array if nil
|
|
50
|
+
self.versions ||= []
|
|
43
51
|
|
|
44
|
-
# Find existing
|
|
45
|
-
existing_index =
|
|
46
|
-
ed.version ==
|
|
52
|
+
# Find existing version with this version
|
|
53
|
+
existing_index = versions.find_index do |ed|
|
|
54
|
+
ed.version == version
|
|
47
55
|
end
|
|
48
56
|
|
|
49
|
-
# Create new
|
|
50
|
-
|
|
51
|
-
version:
|
|
57
|
+
# Create new version
|
|
58
|
+
version = VersionChange.new(
|
|
59
|
+
version: version,
|
|
52
60
|
description: description,
|
|
53
61
|
additions: changes[:additions] || [],
|
|
54
62
|
modifications: changes[:modifications] || [],
|
|
@@ -56,14 +64,14 @@ module Expressir
|
|
|
56
64
|
)
|
|
57
65
|
|
|
58
66
|
if existing_index
|
|
59
|
-
# Replace existing
|
|
60
|
-
|
|
67
|
+
# Replace existing version with same version
|
|
68
|
+
versions[existing_index] = version
|
|
61
69
|
else
|
|
62
|
-
# Add new
|
|
63
|
-
|
|
70
|
+
# Add new version
|
|
71
|
+
versions << version
|
|
64
72
|
end
|
|
65
73
|
|
|
66
|
-
|
|
74
|
+
version
|
|
67
75
|
end
|
|
68
76
|
|
|
69
77
|
# Save this SchemaChange to a YAML file
|
|
@@ -71,7 +79,9 @@ module Expressir
|
|
|
71
79
|
# @param path [String] Path where to save the file
|
|
72
80
|
# @return [Integer] Number of bytes written
|
|
73
81
|
def to_file(path)
|
|
74
|
-
|
|
82
|
+
# Add schema hint for editor support
|
|
83
|
+
content = "# yaml-language-server: $schema=https://www.expresslang.org/schemas/changes/v1/schema_changes.yaml\n#{to_yaml}"
|
|
84
|
+
File.write(path, content)
|
|
75
85
|
end
|
|
76
86
|
end
|
|
77
87
|
end
|
|
@@ -6,14 +6,14 @@ require_relative "mapping_change"
|
|
|
6
6
|
|
|
7
7
|
module Expressir
|
|
8
8
|
module Changes
|
|
9
|
-
# Represents a version
|
|
10
|
-
class
|
|
11
|
-
attribute :version, :
|
|
9
|
+
# Represents a version version of schema changes
|
|
10
|
+
class VersionChange < Lutaml::Model::Serializable
|
|
11
|
+
attribute :version, :integer
|
|
12
12
|
attribute :description, :string
|
|
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
|
|
@@ -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 version-level description from eengine (only item-level)
|
|
74
|
+
change_schema.add_or_update_version(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
|
|
@@ -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 "
|
|
34
|
+
say " Versions: #{schema_change.versions.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
data/lib/expressir.rb
CHANGED
|
@@ -180,7 +180,7 @@ module Expressir
|
|
|
180
180
|
# Autoload for Changes module classes
|
|
181
181
|
module Changes
|
|
182
182
|
autoload :SchemaChange, "expressir/changes/schema_change"
|
|
183
|
-
autoload :
|
|
183
|
+
autoload :VersionChange, "expressir/changes/version_change"
|
|
184
184
|
autoload :ItemChange, "expressir/changes/item_change"
|
|
185
185
|
autoload :MappingChange, "expressir/changes/mapping_change"
|
|
186
186
|
end
|
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.30
|
|
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-16 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: base64
|
|
@@ -184,10 +184,10 @@ files:
|
|
|
184
184
|
- lib/expressir.rb
|
|
185
185
|
- lib/expressir/benchmark.rb
|
|
186
186
|
- lib/expressir/changes.rb
|
|
187
|
-
- lib/expressir/changes/edition_change.rb
|
|
188
187
|
- lib/expressir/changes/item_change.rb
|
|
189
188
|
- lib/expressir/changes/mapping_change.rb
|
|
190
189
|
- lib/expressir/changes/schema_change.rb
|
|
190
|
+
- lib/expressir/changes/version_change.rb
|
|
191
191
|
- lib/expressir/cli.rb
|
|
192
192
|
- lib/expressir/commands/base.rb
|
|
193
193
|
- lib/expressir/commands/benchmark.rb
|
|
@@ -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
|