Umsetzung von Datendeklarationen

Grundsätzlich werden nur solche Datendeklarationen migriert, die auch tatsächlich im Code verwendet werden. Die Datendeklarationen, die strukturrelevant sind, werden getrennt in einer partial Klasse mit dem Suffix localdata.cs generiert. Alle übrigen Datendeklarationen landen in der für den Baustein generierten Klasse.

Definitionen innerhalb der Klasse

Lokale Variablen

Für Datendeklaration welche als lokale Variablen erkannt werden, werden die Interop Klassen verwendet. Dazu wird aus den Klauseln zu der Datendeklaration eine Formatklasse erzeugt, welche als Argument für die entsprechende generische Klasse verwendet wird.

Beispiele

Alphanumerisch, 10 Stellen:

  1. 10 ZW-SUCH-PT PIC X(10).
private Alphanumeric<ZwSuchPtFormat> ZwSuchPt = new Alphanumeric<ZwSuchPtFormat>();
private sealed class ZwSuchPtFormat : AlphanumericFormat
{
	public ZwSuchPtFormat() : base(length:10) {}
}

Numerisch, 11 Stellen, USAGE COMP(binary):

  1. 10 L-MAX-ID PIC 9(11) COMP.
private Numeric<System.UInt64, LMaxIdFormat> LMaxId = new Numeric<System.UInt64, LMaxIdFormat>();
private sealed class LMaxIdFormat : NumericFormat<System.UInt64>
{
	public LMaxIdFormat() : base(predecimals:11, usage:UsageEnum.Limited) {}
}

Numerisch, 10 Vorkommastellen, 5 Nachkomastellen, mit Vorzeichen, USAGE COMP(binary):

  1. 10 L-MAX-BETRAG PIC S9(10)V9(5) COMP.
private Numeric<System.Double, LMaxBetragFormat> LMaxBetrag = new Numeric<System.Double, LMaxBetragFormat>();
private sealed class LMaxBetragFormat : NumericFormat<System.Double>
{
	public LMaxBetragFormat() : base(predecimals:10, decimals:5, isSigned:true, usage:UsageEnum.Limited) {}
}

Numerisch editiertes Feld mit 10 Vorkommastellen, 2 Nachkomastellen, sowie Dezimalpunkt und Tausender Trennzeichen:

  1. 10 L-ABRECHNUNGS-PME-X PIC Z.ZZZ.ZZZ.ZZ9,99.
private Numeric<System.Double, LAbrechnungsPmeXFormat> LAbrechnungsPmeX = new Numeric<System.Double, LAbrechnungsPmeXFormat>();
private sealed class LAbrechnungsPmeXFormat : NumericFormat<System.Double>
{
	public LAbrechnungsPmeXFormat() : base(predecimals:10, decimals:2, usage:UsageEnum.Literal, displayFormat: "#,###,###,##0.00") {}
}

Sonderfälle

Datendeklarationen welche als Datumsfelder erkannt werden, werden als System.DateTime erzeugt:

  1. 10 L-VON-DATUM.
  2. 15 VON-JJJJ PIC 9(4).
  3. 15 FILLER PIC X(1).
  4. 15 VON-MM PIC 9(2).
  5. 15 FILLER PIC X(1).
  6. 15 VON-TT PIC 9(2).
private System.DateTime LVonDatum;

Für Datendeklarationen welche als enumerative Variable erkannt werden, wird ein System.Enum erzeugt:

  1. 10 S-VEV-STORNIERT PIC X.
  2. 88 B-VEV-STORNIERT-NEIN VALUE 'N'.
  3. 88 B-VEV-STORNIERT-GEVO VALUE 'G'.
  4. 88 B-VEV-STORNIERT-JA VALUE 'J'.
private enum VevStorniertEnum
{
	Nein,
	Gevo,
	Ja  ,
};
private VevStorniertEnum SVevStorniert;

Wobei für bitweise Variablen der Enum als Flagable gekennzeichnet wird:

  1. 10 S-JNP-BER PIC 9.
  2. 88 B-JNP-BER-AB-NULL VALUE ZEROS.
  3. 88 B-JNP-BER-AB-INDBNDNLRZ VALUE 1.
  4. 88 B-JNP-BER-AB-ZWISU7 VALUE 2 1.
  5. 88 B-JNP-BER-AB-ZWISU8 VALUE 3 2 1.
  6. 88 B-JNP-BER-AB-JNETPRAE VALUE 4.
[Flags]
private enum JnpBerEnum
{
	AbNull       = 0x00000001, // values ZEROS
	AbIndbndnlrz = 0x00000002, // values 1
	AbZwisu7     = 0x00000004, // values 2, 1
	AbZwisu8     = 0x00000008, // values 3, 2, 1
	AbJnetprae   = 0x00000010, // values 4
};
private JnpBerEnum SJnpBer;

Datendeklarationen welche als boolsche Variablen erkannt werden, werden als System.Boolean erzeugt:

  1. 10 GEFUNDEN-MARKER PIC X.
  2. 88 B-NICHT-GEFUNDEN VALUE "N".
  3. 88 B-GEFUNDEN VALUE "J".
private System.Boolean BGefunden;

Variablen mit variabler Länge

Lokale Konstanten

Wenn eine Datendeklaration als Konstante erkannt wird, wird dieser auch als const mit seinem Initialwert erzeugt.

Beispiele

  1. 05 K-DIFF-MAX PIC S9(10)V9(5) COMP VALUE 0,50000.
private const System.Double KDiffMax                     = 0.50000;
  1. 10 K-MLD-GRP-SNPRAEMIE PIC X(10) VALUE 'SNPRAEMIE'.
private const System.String KMldGrpSnpraemie             = @"SNPRAEMIE ";

Symbolische Konstanten

In der localdata.cs ausgelagerte Definitionen

Struktur

Wenn Datendeklarationen als strukturrelevant erkannt werden, werden für die benötigte übergeordnete Gruppenstufen Klassen erzeugt, um die Struktur abzubilden. Diese Klassen basieren alle auf die Interop Klasse DataGroup.

Die generierte Klasse enthält für alle in der Gruppestufe benötigte Datendeklarationen eine property die die Methoden GetMember und SetMember der Basisklasse aufrufen.

Für die Umsetzung des LENGTH OF-Abfrage wird zusätzlich ein static property mit dem Namen Size erzeugt, welches die Methode SizeOf der Basisklasse aufruft.

Für die Datendeklaration welche als Strukturwurzel erkannt werden, wird ein readonly property erzeugt, was mit einer Instanz der zugehörige Klasse bestückt ist. Zusätzlich werden für alle referenzierte Datendeklarationen sog. Accessors erzeugt, damit diese im Code direkt angesprochen werden können, ohne diese über die jeweilige übergeordnete Gruppestufen qualifizieren zu müssen.

Beispiel

Datendeklaration, wobei die einzelne Felder und die übergeordnete Gruppenstufe im Code angesprochen werden:

  1. 05 HILFS-FELDER.
  2. 10 L-VSU-ID.
  3. 15 L-VSU-ID-TL1 PIC 9(10).
  4. 15 L-VSU-ID-TL2 PIC 9(05).
  5. ...
  6. * doppelte Einträge für VU + PRAE-TYP-K (BND)
  7. * auf inaktiv setzen, Einzelgänger sind OK.
  8. IF Z0AAMPM-PRIM-K-SNMPM-VPL-MPM-1 = L-VSU-ID
  9. AND Z0AAMPM-X50-PRAE-TYP-K = L-X50-PRAE-TYP-K
  10. THEN
  11. PERFORM M52-MPM-INAKTIV
  12. END-IF
  13. MOVE Z0AAMPM-Z01-PBS-ID TO L-VSU-ID-TL1
  14. MOVE Z0AAMPM-Z01-PBS-VRS-NR TO L-VSU-ID-TL2

Generierte Code in localdata.cs:

private LVsuIdGroup LVsuId  { get; } = new LVsuIdGroup();
private sealed class LVsuIdGroup : DataGroup
{
	public static int Size => SizeOf<LVsuIdGroup>();
 
	public NumericLiteral<System.UInt64, LVsuIdTl1Format> LVsuIdTl1 { get => GetMember<NumericLiteral<System.UInt64, LVsuIdTl1Format>>(); set => SetMember(value); }
	public NumericLiteral<System.UInt32, LVsuIdTl2Format> LVsuIdTl2 { get => GetMember<NumericLiteral<System.UInt32, LVsuIdTl2Format>>(); set => SetMember(value); }
}
private NumericLiteral<System.UInt64, LVsuIdTl1Format> LVsuIdTl1 { get => LVsuId.LVsuIdTl1; set => LVsuId.LVsuIdTl1 = value; }
private NumericLiteral<System.UInt32, LVsuIdTl2Format> LVsuIdTl2 { get => LVsuId.LVsuIdTl2; set => LVsuId.LVsuIdTl2 = value; }

Generierte C# Code wo die Felder angesprochen werden:

// doppelte Einträge für VU + PRAE-TYP-K (BND)
// auf inaktiv setzen, Einzelgänger sind OK.
if (Z0aampm.PrimKSnmpmVplMpm1 == LVsuId && 
	Z0aampm.X50PraeTypK == LX50PraeTypK) {
	M52MpmInaktiv();
}
LVsuIdTl1 = Z0aampm.Z01PbsId;
LVsuIdTl2 = Z0aampm.Z01PbsVrsNr;

Filler

Datendeklaration die als anonym erkannt werden, aber strukturrelevant sind, werden bei der Generierung in der localdata.cs berücksichtigt. Allerdings werden keine Accessors und setter erzeugt.

Beispiel

  1. 10 K-MAX-VEV-ANZ-UEBERSCHRITTEN.
  2. 15 FILLER PIC X(20) VALUE 'Maximale Anzahl von '.
  3. 15 K-MAX-VEV-ANZ PIC 99.
  4. 15 FILLER PIC X(31) VALUE
  5. ' Verträgen wurde überschritten!'.
  6. ...
  7. MOVE L-VTL-MAX TO K-MAX-VEV-ANZ
  8. MOVE K-MAX-VEV-ANZ-UEBERSCHRITTEN TO L-OM-CND-ARG-1

Code in localdata.cs

private KMaxVevAnzUeberschrittenGroup KMaxVevAnzUeberschritten  { get; } = new KMaxVevAnzUeberschrittenGroup();
private sealed class KMaxVevAnzUeberschrittenGroup : DataGroup
{
	public static int Size => SizeOf<KMaxVevAnzUeberschrittenGroup>();
 
	private AlphanumericFiller<Filler44Format> Filler44 => GetMember<AlphanumericFiller<Filler44Format>>();
	public NumericLiteral<System.UInt16, KMaxVevAnzFormat> KMaxVevAnz { get => GetMember<NumericLiteral<System.UInt16, KMaxVevAnzFormat>>(); set => SetMember(value); }
	private AlphanumericFiller<Filler46Format> Filler46 => GetMember<AlphanumericFiller<Filler46Format>>();
}
private NumericLiteral<System.UInt16, KMaxVevAnzFormat> KMaxVevAnz { get => KMaxVevAnzUeberschritten.KMaxVevAnz; set => KMaxVevAnzUeberschritten.KMaxVevAnz = value; }

Redefines

Wenn eine Datendeklaration redefiniert wird, bzw. eine andere Datendeklaration redefiniert, werden diese Felder zusammen in eine (auf der Basisklasse DataGroup basierende) Klasse generiert. Die property für eine Datendeklaration welche ein andere Datendeklaration redefiniert, wird mit den RedefinesAttribute versehen.

Beispiel

  1. 05 INDICES.
  2. ...
  3. 10 ZW-EBN-INDICES.
  4. ...
  5. 10 ZW-EBN-TAB REDEFINES ZW-EBN-INDICES.
  6. ...

Generierte Code in localdata.cs:

private sealed class IndicesGroup : DataGroup
{
	public static int Size => SizeOf<IndicesGroup>();
 
	public ZwEbnIndicesGroup ZwEbnIndices => GetMember<ZwEbnIndicesGroup>();
	[Redefines(nameof(ZwEbnIndices))]
	public ZwEbnTabGroup ZwEbnTab => GetMember<ZwEbnTabGroup>();
}

Arrays

Wenn für eine Datendeklaration eine OCCURS Angabe verwendet wird, wird für dieses Feld die generische Klasse Array verwendet. Im Falle einer Gruppenstufe werden für untergeordnete Felder Accessors generiert, die die Hilfsklassen verwenden.

Beispiel

Eine Gruppenstufe mit OCCURS:

  1. 10 PRAE-IND-TAB.
  2. 15 PRAE-IND-ROW OCCURS 54.
  3. 20 PRAE-X50-IND PIC S9(04) COMP.
  4. 20 K-PRAE-TYP-K PIC X(10).

Generierte Code in localdata.cs:

private PraeIndTabGroup PraeIndTab  { get; } = new PraeIndTabGroup();
private sealed class PraeIndTabGroup : DataGroup
{
	[ArrayFormat(54)]
	public Array<PraeIndRowGroup> PraeIndRow => GetMember<Array<PraeIndRowGroup>>();
}
 
private Array<PraeIndRowGroup> PraeIndRow => PraeIndTab.PraeIndRow;
private sealed class PraeIndRowGroup : DataGroup
{
	public Numeric<System.Int16, PraeX50IndFormat> PraeX50Ind { get => GetMember<Numeric<System.Int16, PraeX50IndFormat>>(); set => SetMember(value); }
	public Alphanumeric<KPraeTypKFormat> KPraeTypK { get => GetMember<Alphanumeric<KPraeTypKFormat>>(); set => SetMember(value); }
}
 
private Array<Numeric<System.Int16, PraeX50IndFormat>, PraeIndRowGroup> m_PraeX50Ind;
private Array<Numeric<System.Int16, PraeX50IndFormat>, PraeIndRowGroup> PraeX50Ind => m_PraeX50Ind ?? (m_PraeX50Ind = new Array<Numeric<System.Int16, PraeX50IndFormat>, PraeIndRowGroup>(PraeIndTab.PraeIndRow, o => o.PraeX50Ind, (o, value) => o.PraeX50Ind = value));
 
private Array<Alphanumeric<KPraeTypKFormat>, PraeIndRowGroup> m_KPraeTypK;
private Array<Alphanumeric<KPraeTypKFormat>, PraeIndRowGroup> KPraeTypK => m_KPraeTypK ?? (m_KPraeTypK = new Array<Alphanumeric<KPraeTypKFormat>, PraeIndRowGroup>(PraeIndTab.PraeIndRow, o => o.KPraeTypK, (o, value) => o.KPraeTypK = value));

2 Gruppenstufen mit OCCURS:

  1. 10 VEIN-EBN-ROW OCCURS 4.
  2. 15 VEIN-EBN-REC OCCURS 54.
  3. 20 VEIN-EBN-PRAE-K PIC S9(4) COMP.

Generierte Code in localdata.cs:

private Array<VeinEbnRowGroup> VeinEbnRow  { get; } = new Array<VeinEbnRowGroup>(4);
private sealed class VeinEbnRowGroup : DataGroup
{
	[ArrayFormat(54)]
	public Array<VeinEbnRecGroup> VeinEbnRec => GetMember<Array<VeinEbnRecGroup>>();
}
 
private sealed class VeinEbnRecGroup : DataGroup
{
	public Numeric<System.Int16, VeinEbnPraeKFormat> VeinEbnPraeK { get => GetMember<Numeric<System.Int16, VeinEbnPraeKFormat>>(); set => SetMember(value); }
}
 
private Array<Numeric<System.Int16, VeinEbnPraeKFormat>, VeinEbnRowGroup, VeinEbnRecGroup> m_VeinEbnPraeK;
private Array<Numeric<System.Int16, VeinEbnPraeKFormat>, VeinEbnRowGroup, VeinEbnRecGroup> VeinEbnPraeK => m_VeinEbnPraeK ?? (m_VeinEbnPraeK = new Array<Numeric<System.Int16, VeinEbnPraeKFormat>, VeinEbnRowGroup, VeinEbnRecGroup>(VeinEbnRow, o => o.VeinEbnRec, o => o.VeinEbnPraeK, (o, value) => o.VeinEbnPraeK = value));

Hat eine Deklaration zusätzlich die Sortierungsangabe „Aufsteigend“ wird es als „Wörterbuch“ Dictionary erzeugt 1)

  1. 05 TAB-BZ-SATZ OCCURS 541 ASCENDING KEY IS TAB-BE
Dictionary<Numeric<System.UInt16, TabBeFormat>,TabBzSatzGroup> TabBzSatz = new();

USAGE Angabe INDEX

Die Angabe der Verwendung Index Beziehungsweise die Angabe als Indexer bewirkt das die Deklaration als UInt32 erzeugt wird.2)

  1. 05 I-TAB USAGE INDEX.
  1. 05 TAB-BZ-SATZ OCCURS 541 INDEXED BY I-TAB
private System.UInt32 ITab = new System.UInt32();

TODO Liste

Syntaktisch erkannt, aber von den Generatoren derzeit nicht unterstützt sind folgende Bestandteile:

1) , 2)
Ab V10.00
cobmig:cs:datadefs:start · Zuletzt geändert: 31.03.2022 09:14

Copyright © 1992-2024 TeamWiSE Gesellschaft für Softwaretechnik mbH         Adressen |  Kontakt |  AGB |  Datenschutzerklärung |  Impressum