「Javaプログラミング能力認定試験課題プログラムのリファクタリングレポート」に触発されて

ryoasai さんの「Javaプログラミング能力認定試験課題プログラムのリファクタリングレポート」に触発されたので、
Java の勉強がてら、同様なプログラムを作成してみる。

Step 14 人材登録処理を追加

メニューを表示し、処理を選択させる

class SelectFunction extends AbstractDispatcher {
    // 選択肢 を 表示
    @Override
    protected void beforeDisplayMenu() {
        System.out.println("_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/");
        System.out.println("            人材管理システム");
        System.out.println("                メニュー");
        System.out.println("  [1].人材検索(S)");
        System.out.println("  [2].人材管理(JI:追加 JU:更新 JD:削除)");
        System.out.println("  [3].稼働状況管理(KI:追加 KD:削除)");
        System.out.println("  [4].終了(E)");
        System.out.println("_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/");
        System.out.println("どの機能を実行しますか?");
        System.out.print(" [S, JI, JU, JD, KI, KD, E]>");
    }

    // 選択した処理 を 実行
    @Override
    protected boolean runFunction(String inputCode) {
        if (inputCode.equals("S")) {
            // 人材検索処理
            AbstractDispatcher ad = new SelectSearchType();
            ad.run(reader);

        } else if (inputCode.equals("JI")) {
            // 人材追加処理
            AbstractDispatcher ad = new AppendJinzai();
            ad.run(reader);

        } else if (inputCode.equals("JU")) {
            // 人材更新処理
            AbstractDispatcher ad = new InputJinzaiID();
            ad.run(reader);

        } else if (inputCode.equals("JD"))
            System.out.println("人材削除処理...\n");
        else if (inputCode.equals("KI"))
            System.out.println("稼働状況追加処理...\n");
        else if (inputCode.equals("KD"))
            System.out.println("稼働状況削除処理...\n");
        else 
            System.out.println("");

        return false;
    }
}

人材情報を入力

class AppendJinzai extends AbstractDispatcher {
    private int fieldIdx;
    private Jinzai jinzai;

    protected boolean run(BufferedReader reader) {
        Repository<Jinzai> jinzaiRepository = new Repository<Jinzai>();
        jinzaiRepository.select("jinzai.txt", true, "", Jinzai.class);
        jinzai = new Jinzai();
        jinzai.setID(jinzaiRepository.getNewID());

        this.fieldIdx = 1;
        hasEndCommand = false;
        return super.run(reader);
    }

    // 選択肢 を 表示
    @Override
    protected void beforeDisplayMenu() {
        if      (fieldIdx == 1)  System.out.print("氏名");
        else if (fieldIdx == 2)  System.out.print("郵便番号");
        else if (fieldIdx == 3)  System.out.print("住所");
        else if (fieldIdx == 4)  System.out.print("電話番号");
        else if (fieldIdx == 5)  System.out.print("FAX番号");
        else if (fieldIdx == 6)  System.out.print("e-mailアドレス");
        else if (fieldIdx == 7)  System.out.print("生年月日");
        else if (fieldIdx == 8)  System.out.print("性別");
        else if (fieldIdx == 9)  System.out.print("業種");
        else if (fieldIdx == 10) System.out.print("経験年数");
        else if (fieldIdx == 11) System.out.print("最終学歴");
        else if (fieldIdx == 12) System.out.print("希望単価");

        System.out.print("を入力してください。\n>");
    }

    // 選択した処理 を 実行
    @Override
    protected boolean runFunction(String inputCode) {
        // 更新内容セット
        jinzai.setValue(fieldIdx, inputCode);
        System.out.println();
        if (fieldIdx++ < 12) return false; // 次の項目を 入力

        // 内容確認後 登録処理
        InsertConfirm ad = new InsertConfirm();
        if (ad.run(reader, jinzai)) {
            // 「以下の内容で更新します。」で 
            //      "Y" なら メニューに 戻る、 
            return true;
        } else {
            //      "N" なら 更新項目 選択
            SelectUpdateField su = new SelectUpdateField();
            return su.run(reader, jinzai);
        }
    }
}

内容確認後 更新
更新処理と、ほぼ同じ処理なので、「内容確認後 更新処理」を流用した

abstract class UpdateConfirmBase extends AbstractDispatcher {
    protected Jinzai jinzai;
    private boolean result = false;

    protected boolean run(BufferedReader reader, Jinzai jinzai) {
        this.jinzai = jinzai;
        return super.run(reader);
    }

    // 選択肢 を 表示
    @Override
    protected void beforeDisplayMenu() {
        // 確認メッセージ
        displayConfirmMessage();
        // 人材情報 表示
        JinzaiDetailView jinzaiDetailView = new JinzaiDetailView();
        jinzaiDetailView.display(jinzai);
        System.out.print(" [Y, N]>");
    }

    // 確認メッセージ
    protected abstract void displayConfirmMessage();

    // 選択した処理 を 実行
    @Override
    protected boolean runFunction(String inputCode) {
        if (!inputCode.equals("Y")) {
            System.out.println();
            result = false; // "N" なら 「更新したい項目を選択してください」に戻る
            return true;
        }

        // 人材更新 更新処理
        if (update(new Repository<Jinzai>())) {
            // 完了メッセージ
            displayCompleteMessage();
        }
        result = true; // "Y" なら 「人材IDを入力」に 戻る
        return true;
    }

    // 追加・変更・削除 処理
    protected abstract boolean update(Repository<Jinzai> jinzaiRepository);

    // 完了メッセージ
    protected abstract void displayCompleteMessage();

    // 処理結果を 返す
    @Override
    protected boolean getResult() {
        // "Y" なら 「人材IDを入力」に 戻る
        // "N" なら 「更新したい項目を選択してください」に戻る
        return result;
    }
}

内容確認後 追加

class InsertConfirm extends UpdateConfirmBase {
    // 追加・変更・削除 処理
    @Override
    protected boolean update(Repository<Jinzai> jinzaiRepository) {
        return jinzaiRepository.insert("jinzai.txt", jinzai, Jinzai.class);
    }
    // 確認メッセージ
    @Override
    protected void displayConfirmMessage() {
        System.out.print("\n以下の内容で登録します。");
    }
    // 完了メッセージ
    @Override
    protected void displayCompleteMessage() {
        System.out.println("登録しました。\n");
    }
}

内容確認後 変更

class UpdateConfirm extends UpdateConfirmBase {
    // 追加・変更・削除 処理
    @Override
    protected boolean update(Repository<Jinzai> jinzaiRepository) {
        return jinzaiRepository.update("jinzai.txt", jinzai, Jinzai.class);
    }
    // 確認メッセージ
    @Override
    protected void displayConfirmMessage() {
        System.out.print("\n以下の内容で更新します。");
    }
    // 完了メッセージ
    @Override
    protected void displayCompleteMessage() {
        System.out.println("更新しました。\n");
    }
}

内容確認後 削除

class DeleteConfirm extends UpdateConfirmBase {
    // 追加・変更・削除 処理
    @Override
    protected boolean update(Repository<Jinzai> jinzaiRepository) {
        return jinzaiRepository.delete("jinzai.txt", jinzai, Jinzai.class);
    }
    // 確認メッセージ
    @Override
    protected void displayConfirmMessage() {
        System.out.print("\n以下の人材情報を削除します。");
    }
    // 完了メッセージ
    @Override
    protected void displayCompleteMessage() {
        System.out.println("削除しました。\n");
    }
}

ファイル I/O クラス
データ登録処理を追加

    public boolean insert(String fileName, T entityNew, Class<T> entityClass) {
        select(fileName, true, "", entityClass);
        entityNew.setCreateDate("");

        FileWriter outFile = null;
        BufferedWriter outBuffer = null;

        try {
            outFile = new FileWriter(fileName.replace("txt","tmp"));
            outBuffer = new BufferedWriter(outFile);

            for (T entity: entityList) {
                outBuffer.write(entity.toString());
            }
            outBuffer.write(entityNew.toString());

            outBuffer.flush();
            outBuffer.close();
            outBuffer = null;

            File textFile = new File(fileName);
            File tempFile = new File(fileName.replace("txt","tmp"));
            textFile.delete();
            tempFile.renameTo(textFile);

        } catch (IOException e) { //面倒だがException全体をcatchしない方がよい。
            e.printStackTrace();
            return false;
        } finally {
            // finallyブロックで後処理
            if (outBuffer != null) {
                try {
                    outBuffer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return true;
    }

IDを採番する処理も追加

    public String getNewID() {
        int maxId = 0;

        for (T entity : entityList) {
            int id = 0;
            try {
                id = Integer.parseInt(entity.getID()); 
                if (maxId < id)
                    maxId = id;
            } catch (Exception e) {
            }
        }

        return Integer.toString(++maxId);
    }

また、更新処理で、更新日付をセットしてなかったので追加

    public boolean update(String fileName, T entityNew, Class<T> entityClass) {
        select(fileName, true, "", entityClass);
        entityNew.setUpdateDate("");

以下、略

データ保持クラス
登録日付、更新日付、削除日付の処理を追加

abstract class EntityBase {

略

    public void setCreateDate(String date) {
        createDate = getDate(date);
    }
    public void setUpdateDate(String date) {
        updateDate = getDate(date);
    }
    public void setDeleteDate(String date) {
        deleteDate = getDate(date);
    }
    private String getDate(String date) {
        java.text.SimpleDateFormat df = new java.text.SimpleDateFormat("yyyyMMdd");

        try {
            Date d = df.parse(date); 
            return date;

        } catch(Exception e) {
            return df.format(new Date());
        }
    }

略