Files
cobol-tna-system/JavaSrc/src/Kin05MatMain.java
T

567 lines
24 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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未管理)
}
}
}