diff --git a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/cobj_api/ApiFiles.java b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/cobj_api/ApiFiles.java
index b427ba8a7..056fb1e86 100755
--- a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/cobj_api/ApiFiles.java
+++ b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/cobj_api/ApiFiles.java
@@ -32,7 +32,13 @@ public static void main(String[] args) {
javaCreate(filePath);
}
- /** API連携用のJavaファイルを生成する */
+ /**
+ * API連携用のJavaファイルを生成する。
+ * 引数で指定されたJSONファイルを読み込み、そのPROGRAM-IDとPROCEDURE DIVISION USING句の情報から
+ * {@code Controller.java}と{@code Record.java}の2つのJavaファイルを出力する。
+ *
+ * @param filePath cobjコマンドの{@code -info-json-dir}オプションで生成されたJSONファイルのパス
+ */
static void javaCreate(String filePath) {
try {
String json = new String(Files.readAllBytes(Paths.get(filePath)));
@@ -63,10 +69,11 @@ static void javaCreate(String filePath) {
}
/**
- * Controller.javaのコードを記述する
+ * {@code Controller.java}のコードを記述する。
+ * Spring BootのRestControllerとして動作するクラスを生成し、GET・POSTリクエストを受け付けて
+ * COBOLプログラムを呼び出した結果を{@code Record}として返す処理を出力する。
*
- * @param ctlFile Controller.javaのファイルの情報を保持する
- * @param programId PROGRAM-IDに記述されているプログラム名
+ * @param ctlFile 生成する{@code Controller.java}の書き込み先FileWriter
* @param params PROCEDURE DIVISION USING句に記述されている引数の配列
*/
private static void writeController(FileWriter ctlFile, JSONArray params) {
@@ -214,9 +221,12 @@ private static void writeController(FileWriter ctlFile, JSONArray params) {
}
/**
- * Record.javaのコードを記述する
+ * {@code Record.java}のコードを記述する。
+ * Controllerクラスがレスポンスとして返却するJava recordクラスを生成する。
+ * PROCEDURE DIVISION USING句の各引数をrecordのフィールドとして定義し、HTTPステータスコードを表す
+ * {@code statuscode}フィールドを先頭に持つ。
*
- * @param rcdFile Record.javaのファイル情報を保持する
+ * @param rcdFile 生成する{@code Record.java}の書き込み先FileWriter
* @param params PROCEDURE DIVISION USING句に記述されている引数の配列
*/
private static void writeRecord(FileWriter rcdFile, JSONArray params) {
@@ -258,12 +268,18 @@ private static void writeRecord(FileWriter rcdFile, JSONArray params) {
}
/**
- * 生成されるJavaファイルに記述されるメソッドの引数などを記述する
+ * 生成されるJavaファイルに記述されるメソッドの引数などをカンマ区切りで出力する。
+ * {@code isType}と{@code isRecord}の組み合わせにより、出力される文字列の形式が変化する。
+ *
+ * - {@code isType=true}の場合: {@code <型> <変数名>}の形式で宣言として出力する
+ * - {@code isRecord=true}の場合: {@code Record.<変数名>()}の形式でrecordアクセサ呼び出しとして出力する
+ * - どちらもfalseの場合: {@code <変数名>}のみを出力する
+ *
*
- * @param writer 生成されるJavaファイルの情報を保持する
+ * @param writer 書き込み先のPrintWriter
* @param params PROCEDURE DIVISION USING句に記述されている引数の配列
- * @param isType 引数の型を記述するかどうか
- * @param isRecord 引数がレコード型かどうか
+ * @param isType 引数に型を付与して宣言形式で出力する場合は{@code true}
+ * @param isRecord 引数をrecordのアクセサ呼び出しとして出力する場合は{@code true}
*/
private static void argPrint(
PrintWriter writer, JSONArray params, boolean isType, boolean isRecord) {
diff --git a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/cobj_api/ApiFilesOptions.java b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/cobj_api/ApiFilesOptions.java
index 4964f412d..73c02a13a 100755
--- a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/cobj_api/ApiFilesOptions.java
+++ b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/cobj_api/ApiFilesOptions.java
@@ -15,6 +15,7 @@ class ApiFilesOptions {
/** cobj-apiコマンドによって生成されるJavaファイルが配置されるディレクトリ名 */
static String outputDir;
+ /** cobj-apiコマンドの入力として指定されたJSONファイルのパス */
static String filePath;
/**
diff --git a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/indexed_file/CobolFileKeyInfo.java b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/indexed_file/CobolFileKeyInfo.java
index a015d2bd6..28ae5a9b8 100644
--- a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/indexed_file/CobolFileKeyInfo.java
+++ b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/indexed_file/CobolFileKeyInfo.java
@@ -1,10 +1,27 @@
package jp.osscons.opensourcecobol.libcobj.user_util.indexed_file;
+/**
+ * インデックスファイルのキー情報を保持するクラス。
+ * 1つのキーをレコード先頭からのオフセット(1始まり)、バイト単位のサイズ、
+ * および重複キーを許可するかどうかの3つの情報で表現する。
+ */
class CobolFileKeyInfo {
+ /** レコード先頭からのキーのオフセット(1始まり) */
public int offset;
+
+ /** キーのサイズ(バイト数) */
public int size;
+
+ /** 重複キーを許可する場合は{@code true}、そうでない場合は{@code false} */
public boolean duplicate;
+ /**
+ * 新しい{@code CobolFileKeyInfo}インスタンスを生成する。
+ *
+ * @param offset レコード先頭からのキーのオフセット(1始まり)
+ * @param size キーのサイズ(バイト数)
+ * @param duplicate 重複キーを許可する場合は{@code true}
+ */
public CobolFileKeyInfo(int offset, int size, boolean duplicate) {
this.offset = offset;
this.size = size;
diff --git a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/indexed_file/ErrorLib.java b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/indexed_file/ErrorLib.java
index 6d9f9480c..7d3e1ddb4 100644
--- a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/indexed_file/ErrorLib.java
+++ b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/indexed_file/ErrorLib.java
@@ -1,12 +1,12 @@
package jp.osscons.opensourcecobol.libcobj.user_util.indexed_file;
-/** Manage error info */
+/** cobj-idxコマンドで発生するエラーのメッセージ出力と終了コードの生成をまとめたクラス */
class ErrorLib {
/**
- * Error when indexed file does not exist
+ * 指定されたインデックスファイルが存在しない場合のエラーメッセージを標準エラー出力へ出力する。
*
- * @param indexedFilePath TODO: 準備中
- * @return 1
+ * @param indexedFilePath 存在が確認できなかったインデックスファイルのパス
+ * @return 終了コードとして用いる{@code 1}
*/
static int errorFileDoesNotExist(String indexedFilePath) {
System.err.println("error: '" + indexedFilePath + "' does not exist.");
@@ -14,10 +14,10 @@ static int errorFileDoesNotExist(String indexedFilePath) {
}
/**
- * Error when indexed file is not a valid indexed file
+ * 指定されたファイルが正しいインデックスファイルでない場合のエラーメッセージを標準エラー出力へ出力する。
*
- * @param indexedFilePath TODO: 準備中
- * @return 1
+ * @param indexedFilePath 正しいインデックスファイルとして認識できなかったファイルのパス
+ * @return 終了コードとして用いる{@code 1}
*/
static int errorInvalidIndexedFile(String indexedFilePath) {
System.err.println("error: '" + indexedFilePath + "' is not a valid indexed file.");
@@ -25,9 +25,9 @@ static int errorInvalidIndexedFile(String indexedFilePath) {
}
/**
- * Error when IO operations of indexed files
+ * インデックスファイルに対する入出力処理でエラーが発生した場合のエラーメッセージを標準エラー出力へ出力する。
*
- * @return 1
+ * @return 終了コードとして用いる{@code 1}
*/
static int errorIO() {
System.err.println("error: IO error.");
@@ -35,9 +35,9 @@ static int errorIO() {
}
/**
- * Error when some keys in input data have conflicts
+ * 入力データの中でキーの重複があるためにロードに失敗した場合のエラーメッセージを標準エラー出力へ出力する。
*
- * @return 1
+ * @return 終了コードとして用いる{@code 1}
*/
static int errorDuplicateKeys() {
System.err.println("error: loading fails because of duplicate keys.");
@@ -45,10 +45,10 @@ static int errorDuplicateKeys() {
}
/**
- * Error when some records in input data have invalid size
+ * 入力データに想定と異なる長さのレコードが含まれる場合のエラーメッセージを標準エラー出力へ出力する。
*
- * @param correctSize TODO: 準備中
- * @return TODO: 準備中
+ * @param correctSize インデックスファイルに定義されている正しいレコードサイズ(バイト数)
+ * @return 終了コードとして用いる{@code 1}
*/
static int errorDataSizeMismatch(int correctSize) {
System.err.println("error: all record must have the length of " + correctSize + " bytes.");
diff --git a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/indexed_file/FileLineSeqRecordReader.java b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/indexed_file/FileLineSeqRecordReader.java
index 149e8fa7a..fffbde373 100644
--- a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/indexed_file/FileLineSeqRecordReader.java
+++ b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/indexed_file/FileLineSeqRecordReader.java
@@ -5,21 +5,25 @@
import java.io.IOException;
import jp.osscons.opensourcecobol.libcobj.data.CobolDataStorage;
-/** TODO: 準備中 */
+/**
+ * LINE SEQUENTIAL形式で書かれたファイルから1レコードずつ読み込む{@link RecordReader}の実装。
+ * 1行を1レコードとして扱い、各行のバイト数がコンストラクタで指定された{@code recordSize}と一致することを期待する。
+ */
class FileLineSeqRecordReader implements RecordReader {
- /** TODO: 準備中 */
+ /** 1レコードのバイト数 */
int recordSize;
- /** TODO: 準備中 */
+ /** 入力ファイルを行単位で読み込むためのリーダ */
BufferedReader reader;
private String filePath;
/**
- * TODO: 準備中
+ * 新しい{@code FileLineSeqRecordReader}インスタンスを生成する。
+ * この時点ではファイルは開かれず、{@link #open()}の呼び出しによって開かれる。
*
- * @param recordSize TODO: 準備中
- * @param filePath TODO: 準備中
+ * @param recordSize 1レコードのバイト数
+ * @param filePath 読み込み対象のファイルのパス
*/
FileLineSeqRecordReader(int recordSize, String filePath) {
this.recordSize = recordSize;
diff --git a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/indexed_file/FileSeqRecordReader.java b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/indexed_file/FileSeqRecordReader.java
index 2f94103ff..fc1f3b0a7 100644
--- a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/indexed_file/FileSeqRecordReader.java
+++ b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/indexed_file/FileSeqRecordReader.java
@@ -4,17 +4,22 @@
import java.io.IOException;
import jp.osscons.opensourcecobol.libcobj.data.CobolDataStorage;
-/** TODO: 準備中 */
+/**
+ * SEQUENTIAL形式で書かれたファイルから1レコードずつ読み込む{@link RecordReader}の実装。
+ * 入力ファイルはレコード区切りを持たず、{@code recordSize}バイトずつ連続して並んでいることを想定する。
+ * 末尾に{@code \n}または{@code \r\n}のみが残っている場合は終端として扱う。
+ */
public class FileSeqRecordReader implements RecordReader {
private FileInputStream reader;
private String filePath;
private byte[] readData;
/**
- * TODO: 準備中
+ * 新しい{@code FileSeqRecordReader}インスタンスを生成する。
+ * この時点ではファイルは開かれず、{@link #open()}の呼び出しによって開かれる。
*
- * @param recordSize TODO: 準備中
- * @param filePath TODO: 準備中
+ * @param recordSize 1レコードのバイト数
+ * @param filePath 読み込み対象のファイルのパス
*/
FileSeqRecordReader(int recordSize, String filePath) {
this.filePath = filePath;
diff --git a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/indexed_file/IndexedFileUtilMain.java b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/indexed_file/IndexedFileUtilMain.java
index 0b9f7ad0a..dc12f79ab 100644
--- a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/indexed_file/IndexedFileUtilMain.java
+++ b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/indexed_file/IndexedFileUtilMain.java
@@ -42,9 +42,11 @@ class IndexedFileUtilMain {
private static final String version = jp.osscons.opensourcecobol.libcobj.Const.version;
/**
- * Main method
+ * cobj-idxコマンドのエントリポイント。
+ * コマンドライン引数をパースし、指定されたサブコマンド({@code info} / {@code create} / {@code load} /
+ * {@code unload} / {@code migrate} / {@code unlock})を実行する。
*
- * @param args TODO: 準備中
+ * @param args コマンドラインから入力された引数の配列
*/
public static void main(String[] args) {
@@ -215,7 +217,7 @@ public static void main(String[] args) {
}
}
- /** Print help message. */
+ /** cobj-idxコマンドのヘルプメッセージを標準出力へ出力する。 */
private static void printHelpMessage() {
System.out.println(
"cobj-idx - A utility tool to handle an indexed file of opensource COBOL 4J");
@@ -293,10 +295,15 @@ private static void printHelpMessage() {
}
/**
- * Parse the key options and return a list of CobolFileKeyInfo.
+ * {@code -k}オプション({@code --key})の値をパースし、{@link CobolFileKeyInfo}のリストを返す。
+ * キーは{@code offset,size}の組をコロン区切りで並べた文字列で指定され、
+ * 先頭に{@code d}を付けた{@code dOFFSET,SIZE}は重複キーを意味する。例えば
+ * {@code 2,2:5,4:d15,5}は「プライマリキーがオフセット2長さ2、重複なしのオルタネートキーが
+ * オフセット5長さ4、重複ありのオルタネートキーがオフセット15長さ5」を表す。
*
- * @param cmd the CommandLine object containing the parsed command line arguments
- * @return a list of CobolFileKeyInfo objects parsed from the key options in the provided CommandLine argument
+ * @param cmd パース済みのコマンドライン
+ * @return キー情報のリスト
+ * @throws Exception キーの指定が不正な場合や、プライマリキーが重複キーとして指定されている場合など
*/
private static List parseKeyOptions(CommandLine cmd) throws Exception {
if (cmd.hasOption("k")) {
@@ -385,10 +392,11 @@ private static List parseKeyOptions(CommandLine cmd) throws Ex
}
/**
- * Process info sub command, which shows information of the indexed file.
+ * {@code info}サブコマンドを実行し、インデックスファイルのメタ情報(レコードサイズ、レコード件数、
+ * プライマリキー・オルタネートキーの位置など)を標準出力へ出力する。
*
- * @param indexedFilePath TODO: 準備中
- * @return 0 if success, otherwise non-zero. The return value is error code.
+ * @param indexedFilePath 情報を表示する対象のインデックスファイルのパス
+ * @return 成功した場合は{@code 0}、失敗した場合は非ゼロの終了コード
*/
private static int processInfoCommand(String indexedFilePath) {
File indexedFile = new File(indexedFilePath);
@@ -453,6 +461,15 @@ private static int processInfoCommand(String indexedFilePath) {
}
}
+ /**
+ * {@code migrate}サブコマンドの実体。
+ * opensource COBOL 4J 1.1.12より前のバージョンで作成されたインデックスファイルを最新形式へ移行する。
+ * 具体的には{@code file_lock}テーブルを作成し、{@code table0}にファイルロック用の列
+ * ({@code locked_by}、{@code process_id}、{@code locked_at})が存在しない場合にそれらを追加する。
+ *
+ * @param indexedFilePath 移行対象のインデックスファイルのパス
+ * @throws Exception インデックスファイルへの接続に失敗した場合
+ */
private static void migrateIndexedFile(String indexedFilePath) throws Exception {
try (Connection conn = DriverManager.getConnection("jdbc:sqlite:" + indexedFilePath);
Statement st = conn.createStatement()) {
@@ -495,6 +512,14 @@ private static void migrateIndexedFile(String indexedFilePath) throws Exception
}
}
+ /**
+ * {@code unlock}サブコマンドの実体。
+ * 指定されたインデックスファイルに対してかけられているすべてのロック情報を削除する。
+ * {@code file_lock}テーブルのすべての行を削除し、{@code table0}のロック関連列をすべて{@code NULL}に戻す。
+ *
+ * @param indexedFilePath ロック解除対象のインデックスファイルのパス
+ * @throws Exception インデックスファイルへの接続に失敗した場合
+ */
private static void unlockIndexedFile(String indexedFilePath) throws Exception {
try (Connection conn = DriverManager.getConnection("jdbc:sqlite:" + indexedFilePath);
Statement st = conn.createStatement()) {
@@ -508,10 +533,14 @@ private static void unlockIndexedFile(String indexedFilePath) throws Exception {
}
/**
- * Process load sub command, which loads data inputted from stdin to the indexed file.
+ * {@code load}サブコマンドを実行し、指定された入力ソース(標準入力またはファイル)から読み込んだ
+ * データをインデックスファイルに書き込む。
*
- * @param indexedFilePath TODO: 準備中
- * @return TODO: 準備中
+ * @param indexedFilePath ロード先のインデックスファイルのパス
+ * @param deleteBeforeLoading ロード前に既存のレコードをすべて削除する場合は{@code true}
+ * @param userDataFormat 入力データの形式
+ * @param filePath 入力データのファイルパス。標準入力から読み込む場合は空の{@link Optional}
+ * @return 成功した場合は{@code 0}、失敗した場合は非ゼロの終了コード
*/
private static int processLoadCommand(
String indexedFilePath,
@@ -587,14 +616,15 @@ private static int processLoadCommand(
}
/**
- * Process unload sub command, which writes records stored in the indexed file to stdout.
+ * {@code unload}サブコマンドを実行し、インデックスファイル内のすべてのレコードを指定された出力先
+ * (標準出力またはファイル)に書き出す。
*
- * @param indexedFilePath The path of the indexed file.
- * @param userDataFormat The format of the output data. If this value is
- * UserDataFormat.LINE_SEQUENTIAL, each records are separated by a newline character (0x20).
- * If this value is UserDataFormat.SEQUENTIAL, each records are concatenated without any
- * separator.
- * @return 0 if success, otherwise non-zero. The return value is error code.
+ * @param indexedFilePath アンロード元のインデックスファイルのパス
+ * @param userDataFormat 出力データの形式。{@link UserDataFormat#LINE_SEQUENTIAL}の場合、各レコードは
+ * 改行文字で区切られる。{@link UserDataFormat#SEQUENTIAL}の場合、各レコードは区切り文字なしで
+ * 連結される
+ * @param filePath 出力先のファイルパス。標準出力に書き出す場合は空の{@link Optional}
+ * @return 成功した場合は{@code 0}、失敗した場合は非ゼロの終了コード
*/
private static int processUnloadCommand(
String indexedFilePath, UserDataFormat userDataFormat, Optional filePath) {
@@ -709,10 +739,14 @@ private static Optional createCobolFileFromIndexedFilePath(String ind
}
/**
- * Create a CobolFile instance from the path of the indexed file.
+ * 指定されたパス・レコードサイズ・キー情報から新規に{@link CobolFile}のインスタンスを生成する。
+ * {@code create}サブコマンドの実装で、インデックスファイルをこれから作成する際に使用される。
*
- * @param indexedFilePath TODO: 準備中
- * @return CobolFile instance if success, otherwise empty.
+ * @param indexedFilePath 作成するインデックスファイルのパス
+ * @param recordSize 1レコードのバイト数
+ * @param keyInfoList インデックスファイルに設定するキー情報のリスト
+ * @return 生成された{@link CobolFile}インスタンスを含む{@link Optional}。このメソッドは常に値を含む
+ * {@link Optional}を返す
*/
private static Optional createCobolFile(
String indexedFilePath, Integer recordSize, List keyInfoList) {
diff --git a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/indexed_file/RecordReader.java b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/indexed_file/RecordReader.java
index 16c88f989..0eb589a83 100644
--- a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/indexed_file/RecordReader.java
+++ b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/indexed_file/RecordReader.java
@@ -3,29 +3,34 @@
import java.util.Optional;
import jp.osscons.opensourcecobol.libcobj.data.CobolDataStorage;
-/** TODO: 準備中 */
+/**
+ * 入力ソース(ファイル/標準入力)から1レコードずつ読み込むためのインタフェース。
+ * {@code cobj-idx load}コマンドで、入力データをインデックスファイルへ書き込むために使用される。
+ * 実装は入力データの形式(SEQUENTIAL / LINE SEQUENTIAL)および入力ソースによって切り替わる。
+ */
interface RecordReader {
- /** TODO: 準備中 */
+ /** 入力ソースをオープンし、読み込み可能な状態にする。 */
void open();
/**
- * TODO: 準備中
+ * 入力ソースから1レコードを読み込み、{@code record}に格納する。
*
- * @param record TODO: 準備中
- * @return TODO: 準備中
+ * @param record 読み込んだレコードの格納先
+ * @return 読み込み結果を表す{@link LoadResult}
*/
LoadResult read(CobolDataStorage record);
- /** TODO: 準備中 */
+ /** 入力ソースをクローズし、保持しているリソースを解放する。 */
void close();
/**
- * TODO: 準備中
+ * 指定された入力データ形式および入力ソースに対応する{@code RecordReader}の実装を返す。
+ * {@code filePath}が指定されている場合はファイルから、指定されていない場合は標準入力から読み込む実装を返す。
*
- * @param userDataFormat TODO: 準備中
- * @param recordSize TODO: 準備中
- * @param filePath TODO: 準備中
- * @return TODO: 準備中
+ * @param userDataFormat 入力データの形式
+ * @param recordSize 1レコードのバイト数
+ * @param filePath 読み込み対象のファイルのパス。標準入力から読み込む場合は空の{@link Optional}
+ * @return 入力データ形式と入力ソースに対応する{@code RecordReader}の実装
*/
static RecordReader getInstance(
UserDataFormat userDataFormat, int recordSize, Optional filePath) {
diff --git a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/indexed_file/RecordWriter.java b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/indexed_file/RecordWriter.java
index ba2c683ae..976b0b071 100644
--- a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/indexed_file/RecordWriter.java
+++ b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/indexed_file/RecordWriter.java
@@ -1,18 +1,22 @@
package jp.osscons.opensourcecobol.libcobj.user_util.indexed_file;
-/** TODO: 準備中 */
+/**
+ * 出力先(ファイル/標準出力)へ1レコードずつ書き込むためのインタフェース。
+ * {@code cobj-idx unload}コマンドで、インデックスファイルから読み出したレコードを
+ * 指定された形式で外部へ書き出すために使用される。
+ */
interface RecordWriter {
- /** TODO: 準備中 */
+ /** 出力先をオープンし、書き込み可能な状態にする。 */
void open();
/**
- * TODO: 準備中
+ * 1レコードを出力先に書き込む。
*
- * @param record TODO: 準備中
- * @return TODO: 準備中
+ * @param record 書き込むレコードのバイト列
+ * @return 書き込みに成功した場合は{@code true}、失敗した場合は{@code false}
*/
boolean write(byte[] record);
- /** TODO: 準備中 */
+ /** 出力先をクローズし、保持しているリソースを解放する。 */
void close();
}
diff --git a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/indexed_file/StdinRecordReader.java b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/indexed_file/StdinRecordReader.java
index bc5d8d68c..d7bd839a7 100644
--- a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/indexed_file/StdinRecordReader.java
+++ b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/user_util/indexed_file/StdinRecordReader.java
@@ -3,18 +3,24 @@
import java.util.Scanner;
import jp.osscons.opensourcecobol.libcobj.data.CobolDataStorage;
-/** TODO: 準備中 */
+/**
+ * 標準入力から1レコードずつ読み込む{@link RecordReader}の基底クラス。
+ * 具体的な読み込みロジックは入力データ形式ごとに内部クラス
+ * ({@link StdinLineSeqReader} / {@link StdinSeqReader})で実装され、
+ * {@link #getInstance(UserDataFormat, int)}から対応するインスタンスが取得される。
+ * このクラス自体の{@link #read(CobolDataStorage)}は呼び出されることを想定せず、{@code null}を返す。
+ */
class StdinRecordReader implements RecordReader {
- /** TODO: 準備中 */
+ /** 1レコードのバイト数 */
protected int recordSize;
- /** TODO: 準備中 */
+ /** 標準入力から読み込みを行うScanner */
protected Scanner scan;
/**
- * TODO: 準備中
+ * 新しい{@code StdinRecordReader}インスタンスを生成する。
*
- * @param recordSize TODO: 準備中
+ * @param recordSize 1レコードのバイト数
*/
protected StdinRecordReader(int recordSize) {
this.recordSize = recordSize;
@@ -35,11 +41,15 @@ public void close() {
this.scan.close();
}
+ /**
+ * 標準入力からLINE SEQUENTIAL形式で1レコードずつ読み込む内部クラス。
+ * 1行を1レコードとして扱い、行のバイト数が{@code recordSize}と一致することを期待する。
+ */
static class StdinLineSeqReader extends StdinRecordReader {
/**
- * TODO: 準備中
+ * 新しい{@code StdinLineSeqReader}インスタンスを生成する。
*
- * @param recordSize TODO: 準備中
+ * @param recordSize 1レコードのバイト数
*/
StdinLineSeqReader(int recordSize) {
super(recordSize);
@@ -60,15 +70,23 @@ public LoadResult read(CobolDataStorage record) {
}
}
+ /**
+ * 標準入力からSEQUENTIAL形式で1レコードずつ読み込む内部クラス。
+ * 実装上は{@link Scanner#next()}で標準入力から空白区切りの1トークンを{@link String}として取得し、
+ * そのバイト列を{@code recordSize}バイトずつ区切って1レコードとして扱う。このため、入力全体が
+ * 空白文字を含まない1つのトークンであり、かつそのバイト長が{@code recordSize}の倍数であることを想定する。
+ * 1トークン分のバイト長が{@code recordSize}の倍数でない場合は
+ * {@link LoadResult#LoadResultDataSizeMismatch}を返す。
+ */
static class StdinSeqReader extends StdinRecordReader {
private boolean firstFetchFail;
private byte[] readData;
private int readDataOffset;
/**
- * TODO: 準備中
+ * 新しい{@code StdinSeqReader}インスタンスを生成する。
*
- * @param recordSize TODO: 準備中
+ * @param recordSize 1レコードのバイト数
*/
public StdinSeqReader(int recordSize) {
super(recordSize);
@@ -107,11 +125,11 @@ public LoadResult read(CobolDataStorage record) {
}
/**
- * TODO: 準備中
+ * 指定された入力データ形式に対応する標準入力用の{@link RecordReader}実装を返す。
*
- * @param userDataFormat TODO: 準備中
- * @param recordSize TODO: 準備中
- * @return TODO: 準備中
+ * @param userDataFormat 入力データの形式
+ * @param recordSize 1レコードのバイト数
+ * @return 入力データ形式に対応する{@code RecordReader}の実装。形式が未対応の場合は{@code null}
*/
static RecordReader getInstance(UserDataFormat userDataFormat, int recordSize) {
switch (userDataFormat) {