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

414 lines
17 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.nio.charset.StandardCharsets;
import dto.Kyu04Rec;
import dto.Kyu05Rec;
import dto.Kyu99Rec;
import dto.ZandatacPar;
import dto.ZanendacPar;
import dto.ZanmsgacPar;
import util.ConvUtil;
/**
* ============================================================
* 【COBOL→Java】KYU08PRI 給与明細印刷処理
* ============================================================
* PROGRAM-ID. KYU08PRI → 类 Kyu08PriMainPGMパターン:レイアウト編集のみ GETPUT)
*
* 使用ファイル(SELECT ASSIGN → パス定数):
* R01INNFIL(KYU08R01 SALARY-NET F200B 入力) → R01INN_FILECOPY KYU04REC → dto.Kyu04Rec
* W01OUTFIL(KYU08W01 PAYSLIP F200B 出力) → W01OUT_FILECOPY KYU05REC → dto.Kyu05Rec
* W02OUTFIL(KYU08W02 ERROR-LOG VB200B 出力)→ W02OUT_FILECOPY KYU99REC → dto.Kyu99Rec、将来拡張・現状出力なし)
*
* 使用SUBCALL → 类#execute):
* SUB01DAT→Sub01DatSub / SUB02MSG→Sub02MsgSub / SUB03END→Sub03EndSub
*
* 段落対応:
* 0000MAJCOLSOR→run() 1000ITTSOR→initPara() 1100R01INNSOR→readR01Para()
* 2000MAJSOR→majPara() 3000STPSOR→termPara() 4000MSGOUTSOR→msgOutPara()
* 9999ABDSOR→abendPara()
*
* 処理要点(詳細設計書_KYU08PRI 準拠):
* - 1社員1ページ。ヘッダ行→明細行→フッタ行を 200B 固定長で順次出力(LINAGE 66行/ページ相当)。
* - ヘッダ行:HL-TITLE('========== 給与明細書 ==========') ページ番号(Z(03)9) 'PG'。
* - 明細行:DETAIL-LINE は KYU05REC 布局と一致(PAGE-TITLE=SPACE)するため Kyu05Rec で編集。
* EMP-NAME は X(020) JUSTIFIED RIGHT、BASIC/NET は Z(008)9 BLANK WHEN ZERO で編集。
* - フッタ行:FL-MSG('--- 明細終了 ---')。
* - COBOL は LINAGE/ADVANCING PAGE を用いるが、Java 平文テキスト出力では 200B 行の連続書出とし
* ページ制御(フォームフィード等)は行わない(設計上 1社員1ページのため実害なし)。
* - W02(ERROR-LOG) は OPEN OUTPUT のみ(現状 WRITE なし/将来拡張)。
*/
public class Kyu08PriMain {
// ==================== コンスタント領域 CNSARA ====================
/** 03 CNS-PRGIDX PIC X(008) VALUE 'KYU08PRI'. */
private static final String CST_PRGIDX = "KYU08PRI";
/** 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-MSGSUBEEK PIC 9(003) VALUE 005. サブエラーメッセージ */
private static final int CST_MSGSUBEEK = 5;
/** 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-HEADER-LINES PIC 9(002) VALUE 6. LINAGE TOP 相当・参照用) */
private static final int CST_HEADER_LINES = 6;
/** 03 CNS-DETAIL-LINES PIC 9(002) VALUE 54. LINAGE 明細相当・参照用) */
private static final int CST_DETAIL_LINES = 54;
/** 03 CNS-FOOTER-LINES PIC 9(002) VALUE 6. LINAGE BOTTOM 相当・参照用) */
private static final int CST_FOOTER_LINES = 6;
// ==================== ファイル定義(SELECT ASSIGN 相当) ====================
/** SELECT R01INNFIL ASSIGN TO KYU08R01.SALARY-NET 入力 F200B */
private static final String R01INN_FILE = "data/KYU08R01.txt";
/** SELECT W01OUTFIL ASSIGN TO KYU08W01.PAYSLIP 出力 F200B */
private static final String W01OUT_FILE = "data/KYU08W01.txt";
/** SELECT W02OUTFIL ASSIGN TO KYU08W02.ERROR-LOG 出力 VB200B・現状出力なし) */
private static final String W02OUT_FILE = "data/KYU08W02.txt";
// ==================== カウンタ領域 CUNARACOMP-3 → long ====================
/** 03 CUN-R01INN PIC S9(009) COMP-3 VALUE ZERO. */
private long cunR01Inn;
/** 03 CUN-W01OUT PIC S9(009) COMP-3 VALUE ZERO. */
private long cunW01Out;
/** 03 CUN-W02OUT PIC S9(009) COMP-3 VALUE ZERO. */
private long cunW02Out;
// ==================== 作業領域 WRKARA ====================
/** 03 WRK-EOF PIC X(001). 読込フラグ(88 WRK-EOF-Y VALUE '1' */
private String wrkEof = "0";
/** 03 WRK-LINE-NO PIC 9(002). */
private int wrkLineNo;
/** 03 WRK-PAGE-COUNTER PIC 9(004) VALUE 0. */
private int wrkPageCounter = 0;
/** 03 WS-PAD-CHAR PIC X(001) VALUE SPACE. */
private String wsPadChar = " ";
/** 03 WS-FILE-STATUS PIC X(002). */
private String wsFileStatus = "";
/** 03 WS-DISP-PG PIC Z(03)9. HL-PAGE-NO 編集用・参照用) */
private int wsDispPg;
/** 88 WRK-EOF-Y VALUE '1'. */
private boolean isEof() {
return "1".equals(wrkEof);
}
// ==================== サブプログラム連絡領域(LINKAGE COPY → DTO ====================
/** COPY ZANMSGAC.SUB02MSG用) */
private final ZanmsgacPar m00MhoPar = new ZanmsgacPar();
/** COPY ZANENDAC.SUB03END用) */
private final ZanendacPar e01AbdPar = new ZanendacPar();
/** COPY ZANDATAC.SUB01DAT用) */
private final ZandatacPar d01UbsPar = new ZandatacPar();
// ==================== 入出力レコード(FILE SECTION → DTO ====================
/** 01 R01INNREC.FD R01INNFIL / COPY KYU04REC */
private final Kyu04Rec r01 = new Kyu04Rec();
/** 01 W01OUTREC.FD W01OUTFIL / COPY KYU05REC */
private final Kyu05Rec w01 = new Kyu05Rec();
/** 01 W02OUTREC.FD W02OUTFIL / COPY KYU99REC */
private final Kyu99Rec w02 = new Kyu99Rec();
// ==================== ファイルハンドル(OPEN/CLOSE 相当) ====================
private BufferedReader r01InnFil;
private PrintWriter w01OutFil;
private PrintWriter w02OutFil;
// ==================== PROCEDURE DIVISION ====================
public static void main(final String[] args) {
new Kyu08PriMain().run();
}
/**
* 段落 0000MAJCOLSOR:制御処理。
* PERFORM 1000ITTSOR → PERFORM 2000MAJSOR UNTIL WRK-EOF-Y → PERFORM 3000STPSOR → GOBACK.
*/
private void run() {
try {
initPara();
while (!isEof()) { // PERFORM 2000MAJSOR UNTIL WRK-EOF = '1'
majPara();
}
termPara();
} finally {
closeFiles();
}
}
/**
* 段落 1000ITTSOR:初期処理。
* 開始メッセージ→コンパイル日時→ワーク初期化→SUB01DAT→OPEN→初回読込。
*/
private void initPara() {
// *** 開始メッセージ出力
// MOVE CNS-MSGSTR TO M00MSGCOD.PERFORM 4000MSGOUTSOR.
msgOutPara(CST_MSGSTR, null, null);
// *** コンパイル日時出力 ※FUNCTION WHEN-COMPILED→起動時刻で代用
// MOVE CNS-MSGKEYINF TO M00MSGCOD.
// MOVE FUNCTION WHEN-COMPILED TO M00UMKDATS22-01.
// MOVE 'COMPILED' TO M00UMKDATS22-02.
final String compiled = java.time.LocalDateTime.now()
.format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
msgOutPara(CST_MSGKEYINF, compiled, "COMPILED");
// *** ワークエリア初期化 INITIALIZE WRKARA.
wrkEof = "0";
wrkLineNo = 0;
wrkPageCounter = 0;
wsPadChar = " ";
wsFileStatus = "";
wsDispPg = 0;
// *** 運用日付取得 SUB01DAT
// INITIALIZE D01UBSPAR.CALL 'SUB01DAT' USING D01UBSPAR.
d01UbsPar.reset();
Sub01DatSub.execute(d01UbsPar);
if (d01UbsPar.getD01FkiCod() != 0) {
// IF D01FKICOD NOT = ZERO
// MOVE CNS-MSGSUBEEK TO M00MSGCOD
// MOVE 'SUB01DAT' TO M00UMKDATS22-01
// MOVE D01FKICOD TO M00UMKDATS22-02
// PERFORM 4000MSGOUTSOR
// PERFORM 9999ABDSOR
msgOutPara(CST_MSGSUBEEK, "SUB01DAT",
ConvUtil.padLeftZero(d01UbsPar.getD01FkiCod(), 4));
abendPara();
return;
}
// *** 使用ファイルのオープン
// OPEN INPUT R01INNFIL.OPEN OUTPUT W01OUTFIL W02OUTFIL.
openFiles();
// *** R01 初回読込(1100R01INNSOR
readR01Para();
}
/**
* 段落 1100R01INNSORR01読込処理。
* READ R01INNFIL AT END SET WRK-EOF-Y / NOT AT END ADD 1 TO CUN-R01INN.
*/
private void readR01Para() {
try {
final String line = r01InnFil.readLine();
if (line == null) {
// AT END: SET WRK-EOF-Y TO TRUE.
wrkEof = "1";
} else {
// NOT AT END: 固定長解析 → R01INNREC、ADD 1 TO CUN-R01INN.
r01.parseRecord(line);
cunR01Inn++;
}
} catch (IOException e) {
throw new UncheckedIOException(e); // READ異常 ≈ ABEND
}
}
/**
* 段落 2000MAJSOR:主処理。
* ヘッダ出力(改ページ+ページ番号)→明細行編集・出力→フッタ出力(改ページ)→次レコード読込。
*/
private void majPara() {
// *** ページカウンタ加算
// ADD 1 TO WRK-PAGE-COUNTER.
wrkPageCounter++;
// MOVE WRK-PAGE-COUNTER TO HL-PAGE-NO.MOVE WRK-PAGE-COUNTER TO WS-DISP-PG.
wsDispPg = wrkPageCounter;
// *** ヘッダ出力(BEFORE ADVANCING PAGE
// WRITE W01OUTREC FROM HEADER-LINE BEFORE ADVANCING PAGE.
w01OutFil.println(buildHeaderLine(wrkPageCounter));
// *** 明細行編集(DETAIL-LINE ≡ KYU05REC 布局:PAGE-TITLE=SPACE
// MOVE R01EMP-ID TO DL-EMP-ID.
// MOVE R01EMP-NAME TO DL-EMP-NAME.
// MOVE R01GROSS-PAYMENT TO DL-BASIC-SALARY.
// MOVE R01NET-PAYMENT TO DL-NET-PAYMENT.
w01.reset();
w01.setW01EmpId(r01.getR01EmpId());
w01.setW01EmpName(r01.getR01EmpName());
w01.setW01BasicSalary((int) r01.getR01GrossPayment());
w01.setW01NetPayment((int) r01.getR01NetPayment());
w01.setW01PageTitle(""); // 明細行の PAGE-TITLE は SPACE
// WRITE W01OUTREC FROM DETAIL-LINE BEFORE ADVANCING 1 LINE
// AT END-OF-PAGE WRITE W01OUTREC FROM FOOTER-LINE BEFORE ADVANCING PAGE.
// 1社員1ページのため AT END-OF-PAGE は発動しない)
w01OutFil.println(w01.toRecordLine());
// ADD 1 TO CUN-W01OUT.
cunW01Out++;
// *** フッタ出力(BEFORE ADVANCING PAGE
// WRITE W01OUTREC FROM FOOTER-LINE BEFORE ADVANCING PAGE.
w01OutFil.println(buildFooterLine());
// *** 次レコード読込(1100R01INNSOR
readR01Para();
}
/**
* 段落 3000STPSOR:終了処理。
* CLOSE→入出力件数メッセージ×3→終了メッセージ。
*/
private void termPara() {
// *** 入出力ファイルのクローズ
// CLOSE R01INNFIL W01OUTFIL W02OUTFIL.
closeFiles();
// *** 入出力件数メッセージ出力
// MOVE CNS-MSGIINKES TO M00MSGCOD. MOVE 'KYU08R01' TO PARM1. MOVE CUN-R01INN TO PARM2.
msgOutPara(CST_MSGIINKES, "KYU08R01", ConvUtil.padLeftZero(cunR01Inn, 9));
// MOVE CNS-MSGOUTKES TO M00MSGCOD. MOVE 'KYU08W01' TO PARM1. MOVE CUN-W01OUT TO PARM2.
msgOutPara(CST_MSGOUTKES, "KYU08W01", ConvUtil.padLeftZero(cunW01Out, 9));
// MOVE CNS-MSGOUTKES TO M00MSGCOD. MOVE 'KYU08W02' TO PARM1. MOVE CUN-W02OUT TO PARM2.
msgOutPara(CST_MSGOUTKES, "KYU08W02", ConvUtil.padLeftZero(cunW02Out, 9));
// *** 終了メッセージ出力
// MOVE CNS-MSGFIN TO M00MSGCOD.PERFORM 4000MSGOUTSOR.
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();
m00MhoPar.setM00MsgCod(msgCod);
if (p1 != null) {
m00MhoPar.setM00Umkdats2201(p1);
}
if (p2 != null) {
m00MhoPar.setM00Umkdats2202(p2);
}
// MOVE CNS-KN0002 TO M00UMKDATS22-03(1:1). → 先頭1桁 '2' 後続SPACE(30)
m00MhoPar.setM00Umkdats2203(ConvUtil.padRight(Integer.toString(CST_KN0002), 30));
// MOVE CNS-KN0002 TO M00UMKDATS22-04(1:1).
m00MhoPar.setM00Umkdats2204(ConvUtil.padRight(Integer.toString(CST_KN0002), 30));
// MOVE CNS-PRGIDX TO M00UMKDATS22-05.
m00MhoPar.setM00Umkdats2205(CST_PRGIDX);
Sub02MsgSub.execute(m00MhoPar);
}
/**
* 段落 9999ABDSORABEND処理。
* MOVE 999 TO E01ABDCOD.CALL 'SUB03END' USING E01ABDPAR.
*/
private void abendPara() {
e01AbdPar.reset();
e01AbdPar.setE01AbdCod(CST_ABD999);
Sub03EndSub.execute(e01AbdPar);
}
// ==================== 印刷行編集補助(HEADER-LINE / FOOTER-LINE ====================
/**
* 01 HEADER-LINE 編集(200B)。
* 05 HL-TITLE PIC X(040) VALUE '========== 給与明細書 =========='
* 05 FILLER PIC X(010) VALUE SPACES
* 05 HL-PAGE-NO PIC Z(03)9
* 05 FILLER PIC X(002) VALUE 'PG'
* 05 FILLER PIC X(144) VALUE SPACES
*/
private static String buildHeaderLine(final int pageNo) {
// PIC Z(03)9 編集(4桁、先頭3桁ゼロ抑制)
final String pageNoEd = editZ(pageNo, 3);
return ConvUtil.padRight("========== 給与明細書 ==========", 40)
+ ConvUtil.padRight("", 10)
+ pageNoEd
+ "PG"
+ ConvUtil.padRight("", 144);
}
/**
* 01 FOOTER-LINE 編集(200B)。
* 05 FL-MSG PIC X(040) VALUE '--- 明細終了 ---'
* 05 FILLER PIC X(160) VALUE SPACES
*/
private static String buildFooterLine() {
return ConvUtil.padRight("--- 明細終了 ---", 40)
+ ConvUtil.padRight("", 160);
}
/** PIC Z(n)9 BLANK WHEN ZERO 編集(編集桁数 = zCount + 1)。 */
private static String editZ(final int val, final int zCount) {
final int len = zCount + 1;
if (val == 0) {
// BLANK WHEN ZERO
return ConvUtil.padRight("", len);
}
final String s = ConvUtil.padLeftZero(val, len);
final char[] ca = s.toCharArray();
for (int i = 0; i < zCount; i++) {
if (ca[i] == '0') {
ca[i] = ' ';
} else {
break;
}
}
return new String(ca);
}
// ==================== ファイル操作補助(OPEN/CLOSE 相当) ====================
/** OPEN INPUT R01INNFIL / OUTPUT W01OUTFIL W02OUTFIL. */
private void openFiles() {
try {
r01InnFil = new BufferedReader(
new InputStreamReader(new FileInputStream(R01INN_FILE), StandardCharsets.UTF_8));
w01OutFil = new PrintWriter(
new OutputStreamWriter(new FileOutputStream(W01OUT_FILE), StandardCharsets.UTF_8));
w02OutFil = new PrintWriter(
new OutputStreamWriter(new FileOutputStream(W02OUT_FILE), StandardCharsets.UTF_8));
} catch (IOException e) {
throw new UncheckedIOException(e); // OPEN失敗 ≈ ABEND
}
}
/** CLOSE R01INNFIL W01OUTFIL W02OUTFIL. */
private void closeFiles() {
closeQuiet(r01InnFil);
closeQuiet(w01OutFil);
closeQuiet(w02OutFil);
r01InnFil = null;
w01OutFil = null;
w02OutFil = 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未管理)
}
}
}