OSDN Git Service

コマンドライン解析部の整理見直し
authorOlyutorskii <olyutorskii@users.osdn.me>
Tue, 7 Jun 2016 12:05:08 +0000 (21:05 +0900)
committerOlyutorskii <olyutorskii@users.osdn.me>
Tue, 7 Jun 2016 12:05:08 +0000 (21:05 +0900)
src/main/java/jp/sourceforge/jindolf/archiver/JinArchiver.java
src/main/java/jp/sourceforge/jindolf/archiver/LandUtils.java
src/main/java/jp/sourceforge/jindolf/archiver/OptArg.java [new file with mode: 0644]
src/main/java/jp/sourceforge/jindolf/archiver/OptInfo.java [new file with mode: 0644]
src/test/java/jp/sourceforge/jindolf/archiver/LandUtilsTest.java [new file with mode: 0644]
src/test/java/jp/sourceforge/jindolf/archiver/OptArgTest.java [new file with mode: 0644]
src/test/java/jp/sourceforge/jindolf/archiver/OptInfoTest.java [new file with mode: 0644]

index 8b83d2a..496217c 100644 (file)
@@ -59,7 +59,8 @@ public final class JinArchiver{
      * 隠しコンストラクタ。
      */
     private JinArchiver(){
-        throw new Error();
+        assert false;
+        throw new AssertionError();
     }
 
 
@@ -73,16 +74,15 @@ public final class JinArchiver{
         Properties result = new Properties();
 
         InputStream istream = klass.getResourceAsStream(RES_VERDEF);
+
         try{
-            result.load(istream);
-        }catch(IOException e){
-            return result;
-        }finally{
             try{
+                result.load(istream);
+            }finally{
                 istream.close();
-            }catch(IOException e){
-                return result;
             }
+        }catch(IOException e){
+            // NOTHING
         }
 
         return result;
@@ -144,112 +144,20 @@ public final class JinArchiver{
      * ヘルプメッセージ出力。
      */
     private static void helpMessage(){
-        errprintln(
-                "\n" + GENERATOR + " 人狼BBS アーカイブ作成ツール\n\n"
-                +"-h, -help, -?\n\tヘルプメッセージ\n"
-                +"-land 国識別子\n"
-                +"-vid 村番号\n"
-                +"-outdir 出力ディレクトリ\n"
-                +"-stdout\n\t標準出力へ出力\n\n"
-                +"※ -outdir と -stdout は排他指定\n"
-                );
-
-        String landList = LandUtils.getLandList();
-        errprintln("利用可能な国識別子は " + landList + "\n");
-
+        String msg = OptArg.getHelpMessage(GENERATOR);
+        errprintln(msg);
         return;
     }
 
     /**
      * オプション文字列を解析する。
-     * @param args オプション文字列
+     * @param optInfo オプション情報
      */
-    private static void parseOption(String[] args){
-        if(args.length <= 0){
-            helpMessage();
-            exit(0);
-            return;
-        }
+    private static void dumpOut(OptInfo optInfo){
 
-        LandDef landDef = null;
-        int vid = -1;
-        String outdir = null;
-        boolean stdout = false;
-
-        for(int pos = 0; pos < args.length; pos++){
-            String arg = args[pos];
-
-            if( ! arg.startsWith("-") ){
-                errprintln("不正なオプションです。 " + arg);
-                exit(1);
-                return;
-            }
-
-            if(arg.equals("-h") || arg.equals("-help") || arg.equals("-?")){
-                helpMessage();
-                exit(0);
-                return;
-            }
-
-            if(arg.equals("-stdout")){
-                stdout = true;
-                outdir = null;
-                continue;
-            }
-
-            if(++pos >= args.length){
-                errprintln(
-                        "オプション " + arg + " に引数がありません。");
-                exit(1);
-                return;
-            }
-
-            String val = args[pos];
-            if(arg.equals("-land")){
-                landDef = LandUtils.getLandDef(val);
-                if(landDef == null){
-                    errprintln("不正な国識別子です。 " + val);
-                    exit(1);
-                    return;
-                }
-            }else if(arg.equals("-vid")){
-                vid = Integer.parseInt(val);
-                if(vid < 0){
-                    errprintln("不正な村番号です。 " + vid);
-                    exit(1);
-                    return;
-                }
-            }else if(arg.equals("-outdir")){
-                outdir = val;
-                stdout = false;
-            }else{
-                errprintln("不正なオプションです。 " + arg);
-                exit(1);
-                return;
-            }
-        }
-
-        if(landDef == null){
-            errprintln(
-                    "-land オプションで国識別子を指定してください。");
-            exit(1);
-            return;
-        }
-
-        if(vid < 0){
-            errprintln(
-                    "-vid オプションで村番号を指定してください。");
-            exit(1);
-            return;
-        }
-
-        if(   (outdir == null && stdout == false)
-           || (outdir != null && stdout == true)  ){
-            errprintln(
-                    "-outdir か -stdout のどちらか一方を指定してください。");
-            exit(1);
-            return;
-        }
+        String outdir   = optInfo.getOutdir();
+        LandDef landDef = optInfo.getLandDef();
+        int vid         = optInfo.getVid();
 
         Writer writer;
         if(outdir != null){
@@ -335,63 +243,63 @@ public final class JinArchiver{
     public static Writer getFileWriter(String outdir,
                                          LandDef landDef,
                                          int vid ){
-            File outFile = new File(outdir);
-            if( ! outFile.exists() ){
-                errprintln(
-                        outdir + " が存在しません。");
-                exit(1);
-                return null;
-            }
-            if( ! outFile.isDirectory() ){
-                errprintln(
-                        outdir + " はディレクトリではありません。");
-                exit(1);
-                return null;
-            }
-            if( ! outFile.canWrite() ){
-                errprintln(
-                        outdir + " に書き込めません。");
-                exit(1);
-                return null;
-            }
-            String fname = MessageFormat.format(
-                "jin_{0}_{1,number,#00000}.xml", landDef.getLandId(), vid);
-            File xmlFile = new File(outFile, fname);
-            boolean created;
-            try{
-                created = xmlFile.createNewFile();
-            }catch(IOException e){
-                errprintln(
-                        xmlFile.getName() + " が作成できません。");
-                exit(1);
-                return null;
-            }
-            if( ! created ){
-                errprintln(
-                        fname + " が既に" + outdir + "に存在します。");
-                exit(1);
-                return null;
-            }
-            /* JRE 1.6 only
-            xmlFile.setReadable(true);
-            xmlFile.setWritable(true);
-            xmlFile.setExecutable(false, false);
-            */
-            Writer writer;
-            try{
-                OutputStream ostream;
-                ostream = new FileOutputStream(xmlFile);
-                ostream = new BufferedOutputStream(ostream, 4 * 1024);
-                writer = new OutputStreamWriter(ostream, "UTF-8");
-                writer = new BufferedWriter(writer, 4 * 1024);
-            }catch(IOException e){
-                errprintln(
-                        xmlFile.getName() + " に書き込めません。");
-                exit(1);
-                return null;
-            }
+        File outFile = new File(outdir);
+        if( ! outFile.exists() ){
+            errprintln(
+                    outdir + " が存在しません。");
+            exit(1);
+            return null;
+        }
+        if( ! outFile.isDirectory() ){
+            errprintln(
+                    outdir + " はディレクトリではありません。");
+            exit(1);
+            return null;
+        }
+        if( ! outFile.canWrite() ){
+            errprintln(
+                    outdir + " に書き込めません。");
+            exit(1);
+            return null;
+        }
+        String fname = MessageFormat.format(
+            "jin_{0}_{1,number,#00000}.xml", landDef.getLandId(), vid);
+        File xmlFile = new File(outFile, fname);
+        boolean created;
+        try{
+            created = xmlFile.createNewFile();
+        }catch(IOException e){
+            errprintln(
+                    xmlFile.getName() + " が作成できません。");
+            exit(1);
+            return null;
+        }
+        if( ! created ){
+            errprintln(
+                    fname + " が既に" + outdir + "に存在します。");
+            exit(1);
+            return null;
+        }
+        /* JRE 1.6 only
+        xmlFile.setReadable(true);
+        xmlFile.setWritable(true);
+        xmlFile.setExecutable(false, false);
+        */
+        Writer writer;
+        try{
+            OutputStream ostream;
+            ostream = new FileOutputStream(xmlFile);
+            ostream = new BufferedOutputStream(ostream, 4 * 1024);
+            writer = new OutputStreamWriter(ostream, "UTF-8");
+            writer = new BufferedWriter(writer, 4 * 1024);
+        }catch(IOException e){
+            errprintln(
+                    xmlFile.getName() + " に書き込めません。");
+            exit(1);
+            return null;
+        }
 
-            return writer;
+        return writer;
     }
 
     /**
@@ -399,8 +307,28 @@ public final class JinArchiver{
      * @param args 引数
      */
     public static void main(String[] args){
-        parseOption(args);
+        OptInfo optInfo = OptInfo.parseOptInfo(args);
+
+        if(optInfo.isHelp()){
+            helpMessage();
+            exit(0);
+            assert false;
+            return;
+        }
+
+        if(optInfo.hasError()){
+            String errMsg = optInfo.getErrMsg();
+            errprintln(errMsg);
+            exit(1);
+            assert false;
+            return;
+        }
+
+        dumpOut(optInfo);
+
         exit(0);
+        assert false;
+
         return;
     }
 
index c5f3f5d..561c181 100644 (file)
@@ -15,7 +15,7 @@ import jp.sourceforge.jindolf.corelib.LandDef;
 import org.xml.sax.SAXException;
 
 /**
- * 国周りの各種情報提供
+ * 国情報の各種アクセス
  */
 public final class LandUtils{
 
@@ -33,7 +33,9 @@ public final class LandUtils{
 
         try{
             LANDDEF_LIST = LandDef.buildLandDefList(builder);
-        }catch(IOException | SAXException e){
+        }catch(IOException e){
+            throw new ExceptionInInitializerError(e);
+        }catch(SAXException e){
             throw new ExceptionInInitializerError(e);
         }
     }
@@ -67,15 +69,18 @@ public final class LandUtils{
      * 各識別子は空白記号で区切られる。
      * @return 一覧文字列
      */
-    public static String getLandList(){
-        StringBuilder landList = new StringBuilder();
+    public static String getLandIdCatalog(){
+        StringBuilder catalog = new StringBuilder();
 
         for(LandDef landDef : LANDDEF_LIST){
+            if(catalog.length() > 0){
+                catalog.append(DELIM_SP);
+            }
             String id = landDef.getLandId();
-            landList.append(id).append(DELIM_SP);
+            catalog.append(id);
         }
 
-        String result = landList.toString();
+        String result = catalog.toString();
         return result;
     }
 
diff --git a/src/main/java/jp/sourceforge/jindolf/archiver/OptArg.java b/src/main/java/jp/sourceforge/jindolf/archiver/OptArg.java
new file mode 100644 (file)
index 0000000..88f534c
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * option argument
+ *
+ * License : The MIT License
+ * Copyright(c) 2016 olyutorskii
+ */
+
+package jp.sourceforge.jindolf.archiver;
+
+import java.text.MessageFormat;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * オプション指定子。
+ */
+public enum OptArg implements Iterable<String> {
+
+    /** ヘルプ。 */
+    OPT_HELP   ("-h", "-help", "-?"),
+    /** 国名指定。 */
+    OPT_LAND   ("-land"),
+    /** 村ID指定。 */
+    OPT_VID    ("-vid"),
+    /** 指定ディレクトリに書き込む。 */
+    OPT_OUTDIR ("-outdir"),
+    /** 標準出力へ書き込む。 */
+    OPT_STDOUT ("-stdout"),
+    ;
+
+
+    private static final Map<String, OptArg> MAP_OPT;
+    private static final String FMT_HELP =
+        "\n"
+        + "{0} 人狼BBS アーカイブ作成ツール\n\n"
+        + "-h, -help, -?\n\tヘルプメッセージ\n"
+        + "-land 国識別子\n"
+        + "-vid 村番号\n"
+        + "-outdir 出力ディレクトリ\n"
+        + "-stdout\n\t標準出力へ出力\n\n"
+        + "※ -outdir と -stdout は排他指定\n\n"
+        + "利用可能な国識別子は {1}\n";
+
+
+    private final List<String> argList;
+
+
+    static{
+        Map<String, OptArg> map = new HashMap<>();
+
+        for(OptArg optArg : values()){
+            for(String argtxt : optArg){
+                map.put(argtxt, optArg);
+            }
+        }
+
+        MAP_OPT = Collections.unmodifiableMap(map);
+    }
+
+
+    /**
+     * コンストラクタ。
+     * @param opts オプション文字列。
+     */
+    private OptArg(String ... opts){
+        List<String> list;
+        list = Arrays.asList(opts);
+        list = Collections.unmodifiableList(list);
+
+        this.argList = list;
+
+        return;
+    }
+
+
+    /**
+     * 文字列からオプション指定子を得る。
+     * @param txt 文字列
+     * @return オプション指定子。見つからなければnull
+     */
+    public static OptArg parseOptArg(String txt){
+        OptArg result = MAP_OPT.get(txt);
+        return result;
+    }
+
+    /**
+     * ヘルプメッセージを生成する。
+     * @param generator アプリ名
+     * @return メッセージ
+     */
+    public static String getHelpMessage(String generator){
+        String appName = "";
+        if(generator != null) appName = generator;
+        String catalog = LandUtils.getLandIdCatalog();
+
+        String result = MessageFormat.format(FMT_HELP, appName, catalog);
+
+        return result;
+    }
+
+
+    /**
+     * オプション文字列のリストを得る。
+     * @return オプション文字列のリスト
+     */
+    public List<String> getArgList(){
+        return this.argList;
+    }
+
+    /**
+     * {@inheritDoc}
+     * オプション文字列の列挙。
+     * @return {@inheritDoc}
+     */
+    @Override
+    public Iterator<String> iterator(){
+        return this.argList.iterator();
+    }
+
+}
diff --git a/src/main/java/jp/sourceforge/jindolf/archiver/OptInfo.java b/src/main/java/jp/sourceforge/jindolf/archiver/OptInfo.java
new file mode 100644 (file)
index 0000000..9ff3d01
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * option info
+ *
+ * License : The MIT License
+ * Copyright(c) 2016 olyutorskii
+ */
+
+package jp.sourceforge.jindolf.archiver;
+
+import java.text.MessageFormat;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import jp.sourceforge.jindolf.corelib.LandDef;
+
+/**
+ * オプション情報。
+ * <p>
+ * ヘルプ指定がある場合、他の情報は無効。
+ * ヘルプ指定が無くエラー情報がある場合、他の情報は無効。
+ */
+public final class OptInfo{
+
+    private static final String FMT_INVOPT =
+            "不正なオプションです。 {0}";
+    private static final String FMT_NOARG =
+            "オプション {0} に引数がありません。";
+    private static final String FMT_INVVID =
+            "不正な村番号です。 {0}";
+    private static final String FMT_INVLID =
+            "不正な国識別子です。 {0}";
+    private static final String MSG_NOLID =
+            "-land オプションで国識別子を指定してください。";
+    private static final String MSG_NOVID =
+            "-vid オプションで村番号を指定してください。";
+    private static final String MSG_EXCOUT =
+            "-outdir か -stdout のどちらか一方を指定してください。";
+
+
+    private boolean isHelp = false;
+
+    private LandDef landDef = null;
+    private int vid = -1;
+
+    private boolean isStdout = false;
+    private String outDir = null;
+
+    private String errMsg = null;
+
+
+    /**
+     * コンストラクタ。
+     */
+    private OptInfo(){
+        super();
+        return;
+    }
+
+
+    /**
+     * オプション情報をパースする。
+     * @param args コマンドライン文字列配列
+     * @return オプション情報
+     */
+    public static OptInfo parseOptInfo(String ... args){
+        List<String> argList = Arrays.asList(args);
+        return parseOptInfo(argList);
+    }
+
+    /**
+     * オプション情報をパースする。
+     * @param argList コマンドライン文字列リスト
+     * @return オプション情報
+     */
+    public static OptInfo parseOptInfo(List<String> argList){
+        OptInfo optInfo = new OptInfo();
+
+        if(argList.isEmpty()){
+            optInfo.isHelp = true;
+            return optInfo;
+        }
+
+        Iterator<String> it = argList.iterator();
+        while(it.hasNext()){
+            String arg = it.next();
+
+            OptArg optArg = OptArg.parseOptArg(arg);
+            if(optArg == null){
+                optInfo.errMsg = MessageFormat.format(FMT_INVOPT, arg);
+                break;
+            }
+
+            boolean isNoArgOpt;
+            isNoArgOpt = optInfo.applyDepOpt(optArg);
+            if(optInfo.isHelp()) break;
+            if(isNoArgOpt) continue;
+
+            if(! it.hasNext()){
+                optInfo.errMsg = MessageFormat.format(FMT_NOARG, arg);
+                break;
+            }
+
+            String val = it.next();
+            optInfo.applyOptWithVal(optArg, val);
+
+            if(optInfo.hasError()) break;
+        }
+
+        if(optInfo.isHelp() || optInfo.hasError()){
+            return optInfo;
+        }
+
+        optInfo.condErrCheck();
+
+        return optInfo;
+    }
+
+
+    /**
+     * 引数無しオプションのパース。
+     * @param opt オプション種別
+     * @return 引数無しオプションだったらtrue
+     */
+    private boolean applyDepOpt(OptArg opt){
+        boolean isNoArgOpt = true;
+
+        switch(opt){
+        case OPT_HELP:
+            this.isHelp = true;
+            break;
+        case OPT_STDOUT:
+            this.isStdout = true;
+            this.outDir = null;
+            break;
+        default:
+            isNoArgOpt = false;
+            break;
+        }
+
+        return isNoArgOpt;
+    }
+
+    /**
+     * 引数付きオプションのパース。
+     * @param opt オプション種別
+     * @param val オプション引数
+     */
+    private void applyOptWithVal(OptArg opt, String val){
+        switch(opt){
+        case OPT_LAND:
+            this.landDef = LandUtils.getLandDef(val);
+            if(getLandDef() == null){
+                this.errMsg = MessageFormat.format(FMT_INVLID, val);
+            }
+            break;
+        case OPT_VID:
+            try{
+                this.vid = Integer.parseInt(val);
+            }catch(NumberFormatException e){
+                this.vid = -1;
+            }
+
+            if(getVid() < 0){
+                this.errMsg = MessageFormat.format(FMT_INVVID, val);
+            }
+            break;
+        case OPT_OUTDIR:
+            this.outDir = val;
+            this.isStdout = false;
+            break;
+        default:
+            break;
+        }
+
+        return;
+    }
+
+    /**
+     * 状況に応じて異常系を察知しエラーメッセージを組み立てる。
+     */
+    private void condErrCheck(){
+        String msg = null;
+
+        if(getLandDef() == null) msg = MSG_NOLID;
+        else if(getVid() < 0)    msg = MSG_NOVID;
+        else if(! isSingleOut()) msg = MSG_EXCOUT;
+
+        if(msg != null){
+            this.errMsg = msg;
+        }
+
+        return;
+    }
+
+    /**
+     * 出力先が一つにしぼれているケースをテストする。
+     * @return 一つにしぼれていればtrue
+     */
+    private boolean isSingleOut(){
+        boolean exclusiveCase;
+        exclusiveCase = (getOutdir() != null) ^ isStdout();
+        return exclusiveCase;
+    }
+
+    /**
+     * ヘルプ出力が指定されたか調べる。
+     * @return 指定されていればtrue
+     */
+    public boolean isHelp(){
+        return this.isHelp;
+    }
+
+    /**
+     * 国情報を得る。
+     * @return 国情報。無ければnull
+     */
+    public LandDef getLandDef(){
+        return this.landDef;
+    }
+
+    /**
+     * 村IDを得る。
+     * @return 村ID
+     */
+    public int getVid(){
+        return this.vid;
+    }
+
+    /**
+     * 標準出力への出力が指定されたか調べる。
+     * @return 指定されていればtrue
+     */
+    public boolean isStdout(){
+        return this.isStdout;
+    }
+
+    /**
+     * 出力ディレクトリを得る。
+     * @return 出力ディレクトリ。無ければnull。
+     */
+    public String getOutdir(){
+        return this.outDir;
+    }
+
+    /**
+     * エラーメッセージを得る。
+     * @return メッセージ。無ければnull
+     */
+    public String getErrMsg(){
+        return this.errMsg;
+    }
+
+    /**
+     * エラーの有無を返す。
+     * @return エラー情報があればtrue
+     */
+    public boolean hasError(){
+        if(this.isHelp) return false;
+        if(this.errMsg == null) return false;
+
+        return true;
+    }
+
+    /**
+     * エラーの有無を返す。
+     * @return エラー情報があればtrue
+     */
+    public boolean hasError(){
+        if(this.isHelp) return false;
+        if(this.errMsg == null) return false;
+
+        return true;
+    }
+
+}
diff --git a/src/test/java/jp/sourceforge/jindolf/archiver/LandUtilsTest.java b/src/test/java/jp/sourceforge/jindolf/archiver/LandUtilsTest.java
new file mode 100644 (file)
index 0000000..1ca3738
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ */
+
+package jp.sourceforge.jindolf.archiver;
+
+import jp.sourceforge.jindolf.corelib.LandDef;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ *
+ */
+public class LandUtilsTest {
+
+    public LandUtilsTest() {
+    }
+
+    @BeforeClass
+    public static void setUpClass() {
+    }
+
+    @AfterClass
+    public static void tearDownClass() {
+    }
+
+    @Before
+    public void setUp() {
+    }
+
+    @After
+    public void tearDown() {
+    }
+
+    /**
+     * Test of getLandDef method, of class LandUtils.
+     */
+    @Test
+    public void testGetLandDef() {
+        System.out.println("getLandDef");
+
+        String landId;
+        LandDef landDef;
+
+        landId = "";
+        landDef = LandUtils.getLandDef(landId);
+        assertNull(landDef);
+
+        landId = "XXX";
+        landDef = LandUtils.getLandDef(landId);
+        assertNull(landDef);
+
+        landId = "wolf";
+        landDef = LandUtils.getLandDef(landId);
+        assertNotNull(landDef);
+        assertEquals("人狼BBS 古国(旧人狼BBS 2) 過去ログのみ",
+                landDef.getDescription());
+
+        landId = "wolfg";
+        landDef = LandUtils.getLandDef(landId);
+        assertNotNull(landDef);
+        assertEquals("人狼BBS G国",
+                landDef.getDescription());
+
+        return;
+    }
+
+    /**
+     * Test of getLandIdCatalog method, of class LandUtils.
+     */
+    @Test
+    public void testGetLandIdCatalog() {
+        System.out.println("getLandIdCatalog");
+
+        String result;
+        String expResult;
+
+        expResult = "wolf wolf0 wolfa wolfb wolfc wolfd wolfe wolff wolfg";
+        result = LandUtils.getLandIdCatalog();
+        assertEquals(expResult, result);
+
+        return;
+    }
+
+}
diff --git a/src/test/java/jp/sourceforge/jindolf/archiver/OptArgTest.java b/src/test/java/jp/sourceforge/jindolf/archiver/OptArgTest.java
new file mode 100644 (file)
index 0000000..f85a66f
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ */
+
+package jp.sourceforge.jindolf.archiver;
+
+import java.util.Iterator;
+import java.util.List;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ *
+ */
+public class OptArgTest {
+
+    public OptArgTest() {
+    }
+
+    @BeforeClass
+    public static void setUpClass() {
+    }
+
+    @AfterClass
+    public static void tearDownClass() {
+    }
+
+    @Before
+    public void setUp() {
+    }
+
+    @After
+    public void tearDown() {
+    }
+
+    /**
+     * Test of values method, of class OptArg.
+     */
+    @Test
+    public void testValues() {
+        System.out.println("values");
+
+        OptArg[] values;
+        values = OptArg.values();
+
+        assertEquals(5, values.length);
+
+        int pos;
+        pos = 0;
+        assertEquals(OptArg.OPT_HELP,   values[pos++]);
+        assertEquals(OptArg.OPT_LAND,   values[pos++]);
+        assertEquals(OptArg.OPT_VID,    values[pos++]);
+        assertEquals(OptArg.OPT_OUTDIR, values[pos++]);
+        assertEquals(OptArg.OPT_STDOUT, values[pos++]);
+
+        return;
+    }
+
+    /**
+     * Test of valueOf method, of class OptArg.
+     */
+    @Test
+    public void testValueOf() {
+        System.out.println("valueOf");
+        return;
+    }
+
+    /**
+     * Test of parseOptArg method, of class OptArg.
+     */
+    @Test
+    public void testParseOptArg() {
+        System.out.println("parseOptArg");
+
+        String arg;
+        OptArg optArg;
+
+        arg = null;
+        optArg = OptArg.parseOptArg(arg);
+        assertNull(optArg);
+
+        arg = "";
+        optArg = OptArg.parseOptArg(arg);
+        assertNull(optArg);
+
+        arg = "XXX";
+        optArg = OptArg.parseOptArg(arg);
+        assertNull(optArg);
+
+        arg = "-";
+        optArg = OptArg.parseOptArg(arg);
+        assertNull(optArg);
+
+        arg = "-h";
+        optArg = OptArg.parseOptArg(arg);
+        assertEquals(OptArg.OPT_HELP, optArg);
+
+        arg = "-help";
+        optArg = OptArg.parseOptArg(arg);
+        assertEquals(OptArg.OPT_HELP, optArg);
+
+        arg = "-?";
+        optArg = OptArg.parseOptArg(arg);
+        assertEquals(OptArg.OPT_HELP, optArg);
+
+        arg = "-land";
+        optArg = OptArg.parseOptArg(arg);
+        assertEquals(OptArg.OPT_LAND, optArg);
+
+        arg = "-vid";
+        optArg = OptArg.parseOptArg(arg);
+        assertEquals(OptArg.OPT_VID, optArg);
+
+        arg = "-outdir";
+        optArg = OptArg.parseOptArg(arg);
+        assertEquals(OptArg.OPT_OUTDIR, optArg);
+
+        arg = "-stdout";
+        optArg = OptArg.parseOptArg(arg);
+        assertEquals(OptArg.OPT_STDOUT, optArg);
+
+        return;
+    }
+
+    /**
+     * Test of getHelpMessage method, of class OptArg.
+     */
+    @Test
+    public void testGetHelpMessage() {
+        System.out.println("getHelpMessage");
+
+        String generator = JinArchiver.GENERATOR;
+        String catalog = LandUtils.getLandIdCatalog();
+
+        String center =
+          " 人狼BBS アーカイブ作成ツール\n\n"
+        + "-h, -help, -?\n\tヘルプメッセージ\n"
+        + "-land 国識別子\n"
+        + "-vid 村番号\n"
+        + "-outdir 出力ディレクトリ\n"
+        + "-stdout\n\t標準出力へ出力\n\n"
+        + "※ -outdir と -stdout は排他指定\n\n"
+        + "利用可能な国識別子は ";
+
+        String expResult;
+        String result;
+
+        expResult = "\n" + generator + center + catalog + "\n";
+        result = OptArg.getHelpMessage(generator);
+        assertEquals(expResult, result);
+
+        expResult = "\n" + center + catalog + "\n";
+        result = OptArg.getHelpMessage(null);
+        assertEquals(expResult, result);
+
+        return;
+    }
+
+    /**
+     * Test of getArgList method, of class OptArg.
+     */
+    @Test
+    public void testGetArgList() {
+        System.out.println("getArgList");
+
+        List<String> result;
+
+        result = OptArg.OPT_HELP.getArgList();
+        assertEquals(3, result.size());
+        assertTrue(result.contains("-h"));
+        assertTrue(result.contains("-help"));
+        assertTrue(result.contains("-?"));
+
+        result = OptArg.OPT_LAND.getArgList();
+        assertEquals(1, result.size());
+        assertTrue(result.contains("-land"));
+
+        result = OptArg.OPT_VID.getArgList();
+        assertEquals(1, result.size());
+        assertTrue(result.contains("-vid"));
+
+        result = OptArg.OPT_STDOUT.getArgList();
+        assertEquals(1, result.size());
+        assertTrue(result.contains("-stdout"));
+
+        result = OptArg.OPT_OUTDIR.getArgList();
+        assertEquals(1, result.size());
+        assertTrue(result.contains("-outdir"));
+
+        return;
+    }
+
+    /**
+     * Test of iterator method, of class OptArg.
+     */
+    @Test
+    public void testIterator() {
+        System.out.println("iterator");
+
+        Iterator<String> it;
+
+        it = OptArg.OPT_HELP.iterator();
+        assertEquals("-h", it.next());
+        assertEquals("-help", it.next());
+        assertEquals("-?", it.next());
+        assertFalse(it.hasNext());
+
+        return;
+    }
+
+}
diff --git a/src/test/java/jp/sourceforge/jindolf/archiver/OptInfoTest.java b/src/test/java/jp/sourceforge/jindolf/archiver/OptInfoTest.java
new file mode 100644 (file)
index 0000000..edc6db8
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package jp.sourceforge.jindolf.archiver;
+
+import java.util.Arrays;
+import java.util.List;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ *
+ */
+public class OptInfoTest {
+
+    public OptInfoTest() {
+    }
+
+    @BeforeClass
+    public static void setUpClass() {
+    }
+
+    @AfterClass
+    public static void tearDownClass() {
+    }
+
+    @Before
+    public void setUp() {
+    }
+
+    @After
+    public void tearDown() {
+    }
+
+    /**
+     * Test of parseOptInfo method, of class OptInfo.
+     */
+    @Test
+    public void testParseOptInfo() {
+        System.out.println("parseOptInfo");
+
+        List<String> argList;
+        OptInfo result;
+
+        argList = Arrays.asList();
+        result = OptInfo.parseOptInfo(argList);
+        assertTrue(result.isHelp());
+        assertFalse(result.hasError());
+
+        argList = Arrays.asList("X");
+        result = OptInfo.parseOptInfo(argList);
+        assertFalse(result.isHelp());
+        assertEquals("不正なオプションです。 X", result.getErrMsg());
+        assertTrue(result.hasError());
+
+        argList = Arrays.asList("-help#");
+        result = OptInfo.parseOptInfo(argList);
+        assertFalse(result.isHelp());
+        assertEquals("不正なオプションです。 -help#", result.getErrMsg());
+
+        argList = Arrays.asList("-help");
+        result = OptInfo.parseOptInfo(argList);
+        assertTrue(result.isHelp());
+
+        argList = Arrays.asList("-h");
+        result = OptInfo.parseOptInfo(argList);
+        assertTrue(result.isHelp());
+
+        argList = Arrays.asList("-?");
+        result = OptInfo.parseOptInfo(argList);
+        assertTrue(result.isHelp());
+
+        argList = Arrays.asList("-land", "wolfg", "-vid", "999", "-outdir", "/tmp");
+        result = OptInfo.parseOptInfo(argList);
+        assertFalse(result.isHelp());
+        assertNull(result.getErrMsg());
+        assertEquals("wolfg", result.getLandDef().getLandId());
+        assertEquals(999, result.getVid());
+        assertEquals("/tmp", result.getOutdir());
+        assertFalse(result.isStdout());
+
+        result = OptInfo.parseOptInfo("-land", "wolfg", "-vid", "999", "-outdir", "/tmp");
+        assertFalse(result.isHelp());
+        assertNull(result.getErrMsg());
+        assertEquals("wolfg", result.getLandDef().getLandId());
+        assertEquals(999, result.getVid());
+        assertEquals("/tmp", result.getOutdir());
+        assertFalse(result.isStdout());
+
+        argList = Arrays.asList("-land", "wolfg", "-vid", "999", "-stdout");
+        result = OptInfo.parseOptInfo(argList);
+        assertFalse(result.isHelp());
+        assertNull(result.getErrMsg());
+        assertEquals("wolfg", result.getLandDef().getLandId());
+        assertEquals(999, result.getVid());
+        assertNull(result.getOutdir());
+        assertTrue(result.isStdout());
+
+        argList = Arrays.asList("-land", "wolf@", "-vid", "999", "-outdir", "/tmp");
+        result = OptInfo.parseOptInfo(argList);
+        assertFalse(result.isHelp());
+        assertEquals("不正な国識別子です。 wolf@", result.getErrMsg());
+
+        argList = Arrays.asList("-land", "wolfg", "-vid", "ZZZ", "-outdir", "/tmp");
+        result = OptInfo.parseOptInfo(argList);
+        assertFalse(result.isHelp());
+        assertEquals("不正な村番号です。 ZZZ", result.getErrMsg());
+
+        argList = Arrays.asList("-land", "wolfg", "-vid", "999", "-outdir", "/tmp", "-help");
+        result = OptInfo.parseOptInfo(argList);
+        assertTrue(result.isHelp());
+
+        argList = Arrays.asList("-land", "wolfg", "-vid", "999", "-outdir");
+        result = OptInfo.parseOptInfo(argList);
+        assertFalse(result.isHelp());
+        assertEquals("オプション -outdir に引数がありません。", result.getErrMsg());
+
+        argList = Arrays.asList("-vid", "999", "-outdir", "/tmp");
+        result = OptInfo.parseOptInfo(argList);
+        assertFalse(result.isHelp());
+        assertEquals("-land オプションで国識別子を指定してください。", result.getErrMsg());
+
+        argList = Arrays.asList("-land", "wolfg", "-outdir", "/tmp");
+        result = OptInfo.parseOptInfo(argList);
+        assertFalse(result.isHelp());
+        assertEquals("-vid オプションで村番号を指定してください。", result.getErrMsg());
+
+        argList = Arrays.asList("-land", "wolfg", "-vid", "999");
+        result = OptInfo.parseOptInfo(argList);
+        assertFalse(result.isHelp());
+        assertEquals("-outdir か -stdout のどちらか一方を指定してください。", result.getErrMsg());
+
+        argList = Arrays.asList("-land", "wolfg", "-vid", "999", "-outdir", "/tmp", "-stdout");
+        result = OptInfo.parseOptInfo(argList);
+        assertFalse(result.isHelp());
+        assertNull(result.getOutdir());
+        assertTrue(result.isStdout());
+        assertNull(result.getErrMsg());
+
+        argList = Arrays.asList("-land", "wolfg", "-vid", "999", "-stdout", "-outdir", "/tmp");
+        result = OptInfo.parseOptInfo(argList);
+        assertFalse(result.isHelp());
+        assertEquals("/tmp", result.getOutdir());
+        assertFalse(result.isStdout());
+        assertNull(result.getErrMsg());
+
+        argList = Arrays.asList("-land", "wolfg", "-vid", "999", "-outdir", "/tmp", "-land", "wolff");
+        result = OptInfo.parseOptInfo(argList);
+        assertFalse(result.isHelp());
+        assertNull(result.getErrMsg());
+        assertEquals("wolff", result.getLandDef().getLandId());
+
+        argList = Arrays.asList("-land", "wolfg", "-vid", "999", "-outdir", "/tmp", "-vid", "777");
+        result = OptInfo.parseOptInfo(argList);
+        assertFalse(result.isHelp());
+        assertNull(result.getErrMsg());
+        assertEquals(777, result.getVid());
+
+        argList = Arrays.asList("-land", "wolfg", "-vid", "999", "-outdir", "/tmp", "-outdir", "/var/tmp");
+        result = OptInfo.parseOptInfo(argList);
+        assertFalse(result.isHelp());
+        assertNull(result.getErrMsg());
+        assertEquals("/var/tmp", result.getOutdir());
+
+        return;
+    }
+
+}