Add JavaSrc: cobol-tna-system COBOL->Java conversion (ZAN01-06/KIN01-09/KYU01-09 + 变换规则 doc)

This commit is contained in:
opencode
2026-08-29 20:50:08 +08:00
parent c9ea370397
commit f99f6696a6
71 changed files with 15350 additions and 0 deletions
+566
View File
@@ -0,0 +1,566 @@
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UncheckedIOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import dto.Kin02Rec;
import dto.Kin03Rec;
import dto.Kin04Rec;
import dto.ZanendacPar;
import dto.ZanmsgacPar;
import util.ConvUtil;
/**
* ============================================================
* 【COBOL→Java】KIN05MAT 打刻休暇照合処理
* ============================================================
* PROGRAM-ID. KIN05MAT → 类 Kin05MatMainPGMパターン:マッチング(1:N))
*
* 使用文件(SELECT ASSIGN → 路径常量):
* R01INNFIL(KIN04W01 EDITED-PUNCH F80B) → R01INN_FILECOPY KIN04REC → dto.Kin04Rec
* R02INNFIL(KIN02W01 LEAVE-DAILY F80B) → R02INN_FILECOPY KIN02REC → dto.Kin02Rec
* W01OUTFIL(KIN05W01 KIN-LEAVE F160B)→ W01OUT_FILECOPY KIN03REC → dto.Kin03Rec
* 使用SUBCALL → 类#execute):
* SUB02MSG→Sub02MsgSub / SUB03END→Sub03EndSub
* 段落对应:
* 0000MAJCOLSOR→run() 1000ITTSOR→initPara() 1100R01INNSOR→readR01Para()
* 1200R02INNSOR→readR02Para() 2000MAJSOR→majPara() 2020MATCHSOR→matchPara()
* 2030PRIOSOR→prioSor() 2100R01ONLYSOR→r01OnlyPara() 2200R02ONLYSOR→r02OnlyPara()
* 3000STPSOR→termPara() 4000MSGOUTSOR→msgOutPara() 9999ABDSOR→abendPara()
*
* 与原代码的差异(详见 doc\conv\KIN05MAT_对照表.md 疑问·回答记录):
* #Q1 照合キー(EMP-ID+DATE)はグループ項目のバイト比較と等価なため、文字列連結で比較。
* #Q2 優先順位選定(2030PRIOSOR)は COBOL の EVALUATE TRUE を if/else で忠実に再現。
* #Q3 COBOL は WRK-BEST-* を 2020MATCHSOR と 1000ITTSOR のみ初期化し、
* R01単独出力(2100R01ONLYSOR)ではリセットしないため、前件マッチの休暇情報が
* 継続する不具合がある(設計書 2-1/3-5「R01単独→LEAVE-TYPE='99'」と矛盾)。
* ⇒ Java は【設計書準拠】とし、每条 R01 処理前(majPara先頭)に WRK-BEST-* を
* '99'/0 に初期化する(resetBest())。COBOL の不整合は本ファイル内コメントで指摘。
* #Q4 FUNCTION WHEN-COMPILED → 程序启动时刻代替。
*/
public class Kin05MatMain {
// ==================== コンスタント領域 CNSARA ====================
/** 03 CNS-PRGIDX PIC X(008) VALUE 'KIN05MAT'. */
private static final String CST_PRGIDX = "KIN05MAT";
/** 03 CNS-MSGSTR PIC 9(003) VALUE 001. 開始メッセージ */
private static final int CST_MSGSTR = 1;
/** 03 CNS-MSGFIN PIC 9(003) VALUE 002. 終了メッセージ */
private static final int CST_MSGFIN = 2;
/** 03 CNS-MSGIINKES PIC 9(003) VALUE 006. 入力件数 */
private static final int CST_MSGIINKES = 6;
/** 03 CNS-MSGOUTKES PIC 9(003) VALUE 007. 出力件数 */
private static final int CST_MSGOUTKES = 7;
/** 03 CNS-MSGKEYINF PIC 9(003) VALUE 033. コンパイル日時 */
private static final int CST_MSGKEYINF = 33;
/** 03 CNS-KN0002 PIC 9(001) VALUE 2. */
private static final int CST_KN0002 = 2;
/** 03 CNS-ABD999 PIC 9(003) VALUE 999. */
private static final int CST_ABD999 = 999;
/** 03 CNS-NO-LEAVE PIC X(002) VALUE '99'. 休暇なし */
private static final String CST_NO_LEAVE = "99";
/** 03 CNS-LEAVE-01 PIC X(002) VALUE '01'. */
private static final String CST_LEAVE_01 = "01";
/** 03 CNS-LEAVE-02 PIC X(002) VALUE '02'. */
private static final String CST_LEAVE_02 = "02";
/** 03 CNS-LEAVE-03 PIC X(002) VALUE '03'. */
private static final String CST_LEAVE_03 = "03";
/** 03 CNS-LEAVE-04 PIC X(002) VALUE '04'. */
private static final String CST_LEAVE_04 = "04";
// ==================== ファイル定義(SELECT ASSIGN 相当) ====================
/** SELECT R01INNFIL ASSIGN TO KIN04W01.EDITED-PUNCH入力) */
private static final String R01INN_FILE = "data/KIN04W01.dat";
/** SELECT R02INNFIL ASSIGN TO KIN02W01.LEAVE-DAILY入力) */
private static final String R02INN_FILE = "data/KIN02W01.dat";
/** SELECT W01OUTFIL ASSIGN TO KIN05W01.KIN-LEAVE出力) */
private static final String W01OUT_FILE = "data/KIN05W01.dat";
// ==================== カウンタ領域 CUNARACOMP-3 → long ====================
/** 03 CUN-R01INN PIC S9(009) COMP-3 VALUE ZERO. */
private long cunR01Inn;
/** 03 CUN-R02INN PIC S9(009) COMP-3 VALUE ZERO. */
private long cunR02Inn;
/** 03 CUN-W01OUT PIC S9(009) COMP-3 VALUE ZERO. */
private long cunW01Out;
// ==================== 作業領域 WRKARA ====================
/** 03 WS-R01-STATUS PIC X(002).OPENチェック用、Javaは例外で代替) */
private String wsR01Status = "00";
/** 03 WS-R02-STATUS PIC X(002). */
private String wsR02Status = "00";
/** 03 WS-W01-STATUS PIC X(002). */
private String wsW01Status = "00";
/** 03 WRK-R01EOF PIC X(001). 読込フラグ */
private String wrkR01Eof = "0";
/** 03 WRK-R02EOF PIC X(001). 読込フラグ */
private String wrkR02Eof = "0";
/** 03 WRK-R01KEYEMP-ID 8 + DATE 8 */
private String wrkR01Key = "";
/** 03 WRK-R02KEYEMP-ID 8 + DATE 8 */
private String wrkR02Key = "";
/** 03 WRK-BEST-TYPE PIC X(002). 選定休暇種別 */
private String wrkBestType = CST_NO_LEAVE;
/** 03 WRK-BEST-STR-TIME PIC 9(004). */
private int wrkBestStrTime;
/** 03 WRK-BEST-END-TIME PIC 9(004). */
private int wrkBestEndTime;
/** 03 WRK-BEST-APPL-ID PIC 9(009). */
private int wrkBestApplId;
/** 03 WRK-BEST-FOUND PIC X(001). 選定済フラグ */
private String wrkBestFound = "0";
/** 88 WRK-BEST-IS-FOUND VALUE '1'. */
private boolean isBestFound() {
return "1".equals(wrkBestFound);
}
// ==================== サブプログラム連絡領域(LINKAGE COPY → DTO ====================
/** COPY ZANMSGAC.SUB02MSG用) */
private final ZanmsgacPar m00MhoPar = new ZanmsgacPar();
/** COPY ZANENDAC.SUB03END用) */
private final ZanendacPar e01AbdPar = new ZanendacPar();
// ==================== 入出力レコード(FILE SECTION → DTO ====================
/** FD R01INNFIL の 01 R01INNREC.(現在レコードバッファ) */
private final Kin04Rec r01 = new Kin04Rec();
/** FD R02INNFIL の 01 R02OUTREC.(現在レコードバッファ) */
private final Kin02Rec r02 = new Kin02Rec();
/** FD W01OUTFIL の 01 W01OUTREC. */
private final Kin03Rec w01 = new Kin03Rec();
// ==================== ファイルハンドル(OPEN/CLOSE 相当) ====================
private BufferedReader r01InnFil;
private BufferedReader r02InnFil;
private PrintWriter w01OutFil;
/** 入力ファイルパス(R01/R02/W01)。引数で上書き可。 */
private final String r01InnFile;
private final String r02InnFile;
private final String w01OutFile;
// ==================== PROCEDURE DIVISION ====================
public static void main(String[] args) {
final String r1 = (args != null && args.length > 0) ? args[0] : R01INN_FILE;
final String r2 = (args != null && args.length > 1) ? args[1] : R02INN_FILE;
final String w1 = (args != null && args.length > 2) ? args[2] : W01OUT_FILE;
new Kin05MatMain(r1, r2, w1).run(); // PERFORM 0000MAJCOLSOR 相当
}
/** 引数付コンストラクタ:各ファイルパスを指定(テスト等で使用)。 */
public Kin05MatMain(final String r01InnFile, final String r02InnFile, final String w01OutFile) {
this.r01InnFile = r01InnFile;
this.r02InnFile = r02InnFile;
this.w01OutFile = w01OutFile;
}
/**
* 段落 0000MAJCOLSOR:制御処理。
* PERFORM 1000ITTSOR → PERFORM 2000MAJSOR UNTIL R01-EOF → PERFORM 3000STPSOR → GOBACK.
*/
private void run() {
try {
initPara();
while (!"1".equals(wrkR01Eof)) { // PERFORM 2000MAJSOR UNTIL WRK-R01-EOF
majPara();
}
termPara();
} finally {
closeFiles();
}
}
/**
* 段落 1000ITTSOR:初期処理。
* 開始メッセージ→コンパイル日時→BEST領域初期化→OPEN→OPENチェック→初回読込。
*/
private void initPara() {
// *** 開始メッセージ出力
msgOutPara(CST_MSGSTR, null, null);
// *** コンパイル日時出力 ※疑问#Q4:WHEN-COMPILED→启动时刻代替
String compiled = LocalDateTime.now()
.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
msgOutPara(CST_MSGKEYINF, compiled, "COMPILED");
// *** ワークエリア初期化 INITIALIZE WRKARA.
wrkR01Eof = "0";
wrkR02Eof = "0";
wrkR01Key = "";
wrkR02Key = "";
// *** BEST領域初期化(R01のみ出力時に使用)
wrkBestFound = "0"; // MOVE '0' TO WRK-BEST-FOUND.
wrkBestType = CST_NO_LEAVE; // MOVE CNS-NO-LEAVE TO WRK-BEST-TYPE.
wrkBestStrTime = 0; // MOVE ZERO TO WRK-BEST-STR-TIME.
wrkBestEndTime = 0; // MOVE ZERO TO WRK-BEST-END-TIME.
wrkBestApplId = 0; // MOVE ZERO TO WRK-BEST-APPL-ID.
// *** 入出力ファイル OPEN INPUT R01/R02 / OUTPUT W01.
openFiles();
// *** OPENチェック(STATUS≠'00' → ABEND 999
if (!"00".equals(wsR01Status) || !"00".equals(wsR02Status) || !"00".equals(wsW01Status)) {
abendPara();
}
// *** R01/R02を読み込み
readR01Para();
readR02Para();
}
/**
* 段落 1100R01INNSOR##R01##読込処理。
* READ AT END / NOT AT END のマッピング。
*/
private void readR01Para() {
try {
String line = r01InnFil.readLine();
if (line == null) {
wrkR01Eof = "1"; // AT END: MOVE '1' TO WRK-R01EOF.
} else {
r01.fromRecordLine(line); // FD R01INNREC への転送.
cunR01Inn++; // ADD 1 TO CUN-R01INN.
}
} catch (IOException e) {
throw new UncheckedIOException(e); // READ異常 ≈ ABEND
}
}
/**
* 段落 1200R02INNSOR##R02##読込処理。
* READ AT END / NOT AT END のマッピング. AT END→EOF、NOT AT END→件数++.
*/
private void readR02Para() {
try {
String line = r02InnFil.readLine();
if (line == null) {
wrkR02Eof = "1"; // AT END: MOVE '1' TO WRK-R02EOF.
} else {
r02.fromRecordLine(line); // FD R02OUTREC への転送.
cunR02Inn++; // ADD 1 TO CUN-R02INN.
}
} catch (IOException e) {
throw new UncheckedIOException(e); // READ異常 ≈ ABEND
}
}
/**
* 段落 2000MAJSOR:主処理(マッチング制御)。
* R01キー設定→R02キー設定(有効時)→EVALUATE TRUE で3分岐。
*/
private void majPara() {
// *** 設計書準拠:每条打刻(R01)は独立に判定。COBOL(KIN05MAT.cbl)は
// WRK-BEST-* を 2020MATCHSOR と 1000ITTSOR のみ初期化し、
// R01単独出力(2100R01ONLYSOR)ではリセットしないため、前件マッチの
// 休暇情報が継続する不具合がある。Java は設計書意図(='99')どおり、
// 每条 R01 処理前に WRK-BEST-* を初期化する。
resetBest();
// *** R01キー設定
setR01Key();
// *** R02キー設定(有効な場合)
if (!"1".equals(wrkR02Eof)) {
setR02Key();
}
// *** EVALUATE TRUE マッチング3分岐(COBOL の WHEN 順序を if/else で再現)
if ("1".equals(wrkR02Eof)) {
// WHEN WRK-R02-EOF → R01のみ出力+R01次読込
r01OnlyPara();
readR01Para();
} else if (wrkR01Key.compareTo(wrkR02Key) < 0) {
// WHEN WRK-R01KEY < WRK-R02KEY → R01のみ出力+R01次読込
r01OnlyPara();
readR01Para();
} else if (wrkR01Key.compareTo(wrkR02Key) == 0) {
// WHEN WRK-R01KEY = WRK-R02KEY → マッチング処理+R01次読込
matchPara();
readR01Para();
} else {
// WHEN WRK-R01KEY > WRK-R02KEY → R02のみスキップ+R02次読込
r02OnlyPara();
readR02Para();
}
}
/** WRK-R01KEY = R01EMP-ID(8) + R01WORK-DATE(8)(グループ比較と等価)。 */
private void setR01Key() {
wrkR01Key = r01.getEmpId() + r01.getWorkDate();
}
/** WRK-R02KEY = R02EMP-ID(8) + R02DATE(8)(グループ比較と等価)。 */
private void setR02Key() {
wrkR02Key = r02.getEmpId() + ConvUtil.padLeftZero(r02.getDate(), 8);
}
/**
* WRK-BEST-* 初期化('99'/0)。
* 設計書(KIN05MAT)準拠:每条打刻(R01)の処理前に実施し、前件マッチの
* 休暇情報が継続しないよう保証する。COBOL は本初期化を 2020MATCHSOR と
* 1000ITTSOR のみに記述し R01単独出力で漏れたため、無休假打刻に前件の
* 休暇種別が残る不具合がある(#Q3)。
*/
private void resetBest() {
wrkBestFound = "0"; // MOVE '0' TO WRK-BEST-FOUND.
wrkBestType = CST_NO_LEAVE; // MOVE CNS-NO-LEAVE TO WRK-BEST-TYPE.
wrkBestStrTime = 0; // MOVE ZERO TO WRK-BEST-STR-TIME.
wrkBestEndTime = 0; // MOVE ZERO TO WRK-BEST-END-TIME.
wrkBestApplId = 0; // MOVE ZERO TO WRK-BEST-APPL-ID.
}
/**
* 段落 2020MATCHSOR:マッチング処理(N:1ループレ)。
* 一致キーの全R02を読込み、最適休暇を選定した上で KIN-LEAVE 出力。
* ※ majPara() 先頭の resetBest() で既に '99'/0 初期化済だが、COBOL 互換の
* 位置でも再初期化(冪等)。設計書準拠の挙動は majPara() 側で保証される。
*/
private void matchPara() {
// *** 選定領域初期化(majPara() での初期化と同一内容)
resetBest();
// *** N:1ループ 一致するR02を全件処理
while (true) {
if ("1".equals(wrkR02Eof)) {
break; // WRK-R02-EOF
}
if (!wrkR01Key.equals(wrkR02Key)) {
break; // WRK-R01KEY < WRK-R02KEY OR WRK-R01KEY > WRK-R02KEY
}
// *** ベスト選定
if (!isBestFound()) {
// 初回 → ベストとして保持
wrkBestFound = "1"; // MOVE '1' TO WRK-BEST-FOUND.
wrkBestType = r02.getLeaveType();
wrkBestStrTime = r02.getStartTime();
wrkBestEndTime = r02.getEndTime();
wrkBestApplId = r02.getApplId();
} else {
prioSor(r02.getLeaveType(), r02.getStartTime(),
r02.getEndTime(), r02.getApplId());
}
// *** R02次読込
readR02Para();
// *** R02キー再設定(有効な場合)
if (!"1".equals(wrkR02Eof)) {
setR02Key();
}
}
// *** KIN-LEAVE出力(R01のみ出力サブルーチンを共用)
r01OnlyPara();
}
/**
* 段落 2030PRIOSOR:優先順位判定。
* 優先順位 01 > 02 > 03 > 04。同種別は APPL-ID の小さい方を採用。
* COBOL の EVALUATE TRUE を if/else で忠実に再現(WHEN OTHER→CONTINUE)。
*/
private void prioSor(final String r02Type, final int r02Str,
final int r02End, final int r02Appl) {
// EVALUATE TRUER02LEAVE-TYPE で分岐)
if (CST_LEAVE_01.equals(r02Type)) {
if (!CST_LEAVE_01.equals(wrkBestType)) {
wrkBestType = r02Type;
wrkBestStrTime = r02Str;
wrkBestEndTime = r02End;
wrkBestApplId = r02Appl;
} else if (r02Appl < wrkBestApplId) {
wrkBestStrTime = r02Str;
wrkBestEndTime = r02End;
wrkBestApplId = r02Appl;
}
} else if (CST_LEAVE_02.equals(r02Type)) {
if (CST_LEAVE_01.equals(wrkBestType)) {
// CONTINUE01 が優先)
} else if (CST_LEAVE_02.equals(wrkBestType)) {
if (r02Appl < wrkBestApplId) {
wrkBestStrTime = r02Str;
wrkBestEndTime = r02End;
wrkBestApplId = r02Appl;
}
} else {
wrkBestType = r02Type;
wrkBestStrTime = r02Str;
wrkBestEndTime = r02End;
wrkBestApplId = r02Appl;
}
} else if (CST_LEAVE_03.equals(r02Type)) {
if (CST_LEAVE_01.equals(wrkBestType)) {
// CONTINUE
} else if (CST_LEAVE_02.equals(wrkBestType)) {
// CONTINUE
} else if (CST_LEAVE_03.equals(wrkBestType)) {
if (r02Appl < wrkBestApplId) {
wrkBestStrTime = r02Str;
wrkBestEndTime = r02End;
wrkBestApplId = r02Appl;
}
} else {
wrkBestType = r02Type;
wrkBestStrTime = r02Str;
wrkBestEndTime = r02End;
wrkBestApplId = r02Appl;
}
} else if (CST_LEAVE_04.equals(r02Type)) {
if (CST_LEAVE_01.equals(wrkBestType)) {
// CONTINUE
} else if (CST_LEAVE_02.equals(wrkBestType)) {
// CONTINUE
} else if (CST_LEAVE_03.equals(wrkBestType)) {
// CONTINUE
} else if (CST_LEAVE_04.equals(wrkBestType)) {
if (r02Appl < wrkBestApplId) {
wrkBestStrTime = r02Str;
wrkBestEndTime = r02End;
wrkBestApplId = r02Appl;
}
} else {
wrkBestType = r02Type;
wrkBestStrTime = r02Str;
wrkBestEndTime = r02End;
wrkBestApplId = r02Appl;
}
} else {
// WHEN OTHER → CONTINUE(未知種別は無視)
}
}
/**
* 段落 2100R01ONLYSOR:R01のみ出力(またはマッチ結果出力)。
* 打刻情報(1-80B)+休暇情報(81-160B、WRK-BEST-* を使用)を KIN-LEAVE に出力。
*/
private void r01OnlyPara() {
// *** KIN-LEAVEレコード編集
w01.reset(); // INITIALIZE W01OUTREC.
// *** 打刻情報(1-80B)
w01.setEmpId(r01.getEmpId()); // MOVE R01EMP-ID TO W01EMP-ID.
w01.setWorkDate(r01.getWorkDate()); // MOVE R01WORK-DATE TO W01WORK-DATE.
w01.setStrTime(r01.getStrTime()); // MOVE R01STR-TIME TO W01STR-TIME.
w01.setEndTime(r01.getEndTime()); // MOVE R01END-TIME TO W01END-TIME.
w01.setDeptId(r01.getDeptId()); // MOVE R01DEPT-ID TO W01DEPT-ID.
w01.setTerminal(r01.getTerminal()); // MOVE R01TERMINAL TO W01TERMINAL.
// *** 休暇情報(81-160B)
w01.setLeaveType(wrkBestType); // MOVE WRK-BEST-TYPE TO W01LEAVE-TYPE.
w01.setLeaveStrTime(wrkBestStrTime); // MOVE WRK-BEST-STR-TIME TO W01LEAVE-STR-TIME.
w01.setLeaveEndTime(wrkBestEndTime); // MOVE WRK-BEST-END-TIME TO W01LEAVE-END-TIME.
w01.setLeaveHours(0); // MOVE ZERO TO W01LEAVE-HOURS.
w01.setApplicationId(wrkBestApplId); // MOVE WRK-BEST-APPL-ID TO W01APPLICATION-ID.
writeW01(); // WRITE W01OUTREC.ADD 1 TO CUN-W01OUT.
}
/**
* 段落 2200R02ONLYSOR:R02のみスキップ(該当打刻のない休暇レコードは出力しない)。
*/
private void r02OnlyPara() {
// PERFORM 1200R02INNSOR は呼出元(majPara)で実施済(CONTINUE)。
}
/**
* 段落 3000STPSOR:終了処理。
* CLOSE→入出力件数メッセージ×3→終了メッセージ。
*/
private void termPara() {
// *** 入出力ファイル CLOSE
closeFiles();
// *** 入出力ファイル件数出力(数値→X(30)転送は9桁ゼロ埋め表示形)
msgOutPara(CST_MSGIINKES, "KIN04W01", ConvUtil.padLeftZero(cunR01Inn, 9));
msgOutPara(CST_MSGIINKES, "KIN02W01", ConvUtil.padLeftZero(cunR02Inn, 9));
msgOutPara(CST_MSGOUTKES, "KIN05W01", ConvUtil.padLeftZero(cunW01Out, 9));
// *** 終了メッセージ出力
msgOutPara(CST_MSGFIN, null, null);
}
/**
* 段落 4000MSGOUTSOR:メッセージ編集出力処理。
* M00UMKDATS22-03(1:1)/-04(1:1) に '2'、-05 にプログラムIDを設定し SUB02MSG を呼ぶ。
*/
private void msgOutPara(final int msgCod, final String p1, final String p2) {
m00MhoPar.reset(); // INITIALIZE M00MHOPAR.
m00MhoPar.setM00MsgCod(msgCod); // MOVE ... TO M00MSGCOD.
if (p1 != null) {
m00MhoPar.setM00Umkdats2201(p1); // MOVE ... TO M00UMKDATS22-01.
}
if (p2 != null) {
m00MhoPar.setM00Umkdats2202(p2); // MOVE ... TO M00UMKDATS22-02.
}
// MOVE CNS-KN0002 TO M00UMKDATS22-03(1:1).(参照修改→先頭1桁上書き、残り29桁はSPACE)
m00MhoPar.setM00Umkdats2203(ConvUtil.padRight(Integer.toString(CST_KN0002), 30));
m00MhoPar.setM00Umkdats2204(ConvUtil.padRight(Integer.toString(CST_KN0002), 30));
m00MhoPar.setM00Umkdats2205(CST_PRGIDX); // MOVE CNS-PRGIDX TO ...-05.
Sub02MsgSub.execute(m00MhoPar); // CALL 'SUB02MSG' USING M00MHOPAR.
}
/**
* 段落 9999ABDSORABEND処理。
* MOVE 999 TO E01ABDCOD.CALL 'SUB03END' USING E01ABDPAR.
*/
private void abendPara() {
e01AbdPar.reset();
e01AbdPar.setE01AbdCod(CST_ABD999); // MOVE CNS-ABD999 TO E01ABDCOD.
Sub03EndSub.execute(e01AbdPar); // CALL 'SUB03END'.
}
// ==================== ファイル操作補助(OPEN/CLOSE/WRITE 相当) ====================
/** OPEN INPUT R01INNFIL/R02INNFIL / OUTPUT W01OUTFIL(失敗時は STATUS='99'→ABEND)。 */
private void openFiles() {
try {
r01InnFil = new BufferedReader(
new InputStreamReader(new FileInputStream(r01InnFile), "UTF-8"));
r02InnFil = new BufferedReader(
new InputStreamReader(new FileInputStream(r02InnFile), "UTF-8"));
w01OutFil = new PrintWriter(
new OutputStreamWriter(new FileOutputStream(w01OutFile), "UTF-8"));
} catch (IOException e) {
// OPEN失敗相当:FILE STATUS ≠ '00'(後続の OPENチェックで ABEND 999
wsR01Status = "99";
wsR02Status = "99";
wsW01Status = "99";
}
}
/** WRITE W01OUTREC.ADD 1 TO CUN-W01OUT. */
private void writeW01() {
w01OutFil.println(w01.toRecordLine());
cunW01Out++;
}
/** CLOSE R01INNFIL R02INNFIL W01OUTFIL. */
private void closeFiles() {
closeQuiet(r01InnFil);
closeQuiet(r02InnFil);
closeQuiet(w01OutFil);
r01InnFil = null;
r02InnFil = null;
w01OutFil = null;
}
private static void closeQuiet(final Object handle) {
try {
if (handle instanceof BufferedReader) {
((BufferedReader) handle).close();
} else if (handle instanceof PrintWriter) {
((PrintWriter) handle).close();
}
} catch (IOException e) {
// CLOSE異常は無視(原程序もFILE STATUS未管理)
}
}
}