OSDN Git Service

本番スキーマ移行
[mikutoga/Vmd2XML.git] / src / main / java / jp / sfjp / mikutoga / vmd2xml / OptInfo.java
1 /*
2  * command line argument info
3  *
4  * License : The MIT License
5  * Copyright(c) 2013 MikuToga Partners
6  */
7
8 package jp.sfjp.mikutoga.vmd2xml;
9
10 import java.text.MessageFormat;
11 import java.util.List;
12 import java.util.Locale;
13
14 /**
15  * コマンドラインオプション情報。
16  */
17 final class OptInfo {
18
19     private static final String EOL_LF = "\n";
20     private static final String EOL_CRLF = "\r\n";
21     private static final String EOL_DEFAULT = EOL_LF;
22
23     private static final String FORMAT_VMD       = "vmd";
24     private static final String FORMAT_XML       = "xml";
25     private static final String FORMAT_XML110820 = "xml110820";
26     private static final String FORMAT_XML130609 = "xml130609";
27
28     private static final String SFX_VMD = ".vmd";
29     private static final String SFX_XML = ".xml";
30
31     private static final String NL_LF   =   "lf";
32     private static final String NL_CRLF = "crlf";
33
34     private static final String ERRMSG_UNKNOWN =
35             "Unknown option : {0}";
36     private static final String ERRMSG_MOREARG =
37             "You need option arg with : {0}";
38     private static final String ERRMSG_INTYPE =
39             "You must specify input format with -iform.";
40     private static final String ERRMSG_OUTTYPE =
41             "You must specify output format with -oform.";
42     private static final String ERRMSG_NOINFILE =
43             "You must specify input file with -i.";
44     private static final String ERRMSG_NOOUTFILE =
45             "You must specify output file with -o.";
46     private static final String ERRMSG_INVFORM =
47             "Unknown format : \"{0}\" must be \"vmd\" or \"xml\" "
48             + "or \"xml110820\"";
49     private static final String ERRMSG_INVNL =
50             "Unknown newline : \"{0}\" must be \"lf\" or \"crlf\"";
51     private static final String ERRMSG_INVBOOL =
52             "Unknown switch : \"{0}\" must be \"on\" or \"off\"";
53
54
55     private boolean needHelp = false;
56     private MotionFileType inTypes  = MotionFileType.NONE;
57     private MotionFileType outTypes = MotionFileType.NONE;
58     private String inFilename = null;
59     private String outFilename = null;
60     private boolean overwrite = false;
61     private String newline = EOL_DEFAULT;
62     private String generator = Vmd2Xml.GENERATOR;
63     private boolean isQuaternionMode = true;
64
65
66     /**
67      * コンストラクタ。
68      */
69     private OptInfo(){
70         super();
71         return;
72     }
73
74
75     /**
76      * フォーマット種別指定子をデコードする。
77      * @param arg 文字列
78      * @return デコード結果。
79      * @throws CmdLineException 不正なフォーマット種別
80      */
81     private static MotionFileType decodeFormatType(String arg)
82             throws CmdLineException{
83         MotionFileType result;
84
85         if      (FORMAT_VMD.equals(arg)){
86             result = MotionFileType.VMD;
87         }else if(FORMAT_XML.equals(arg)){
88             result = MotionFileType.XML_AUTO;
89         }else if(FORMAT_XML110820.equals(arg)){
90             result = MotionFileType.XML_110820;
91         }else if(FORMAT_XML130609.equals(arg)){
92             result = MotionFileType.XML_130609;
93         }else{
94             String errMsg = MessageFormat.format(ERRMSG_INVFORM, arg);
95             throw new CmdLineException(errMsg);
96         }
97
98         return result;
99     }
100
101     /**
102      * 改行文字指定子をデコードする。
103      * @param arg 文字列
104      * @return デコード結果。
105      * @throws CmdLineException 不正なフォーマット種別
106      */
107     private static String decodeNewline(String arg)
108             throws CmdLineException{
109         String result;
110
111         if      (NL_LF.equals(arg)){
112             result = EOL_LF;
113         }else if(NL_CRLF.equals(arg)){
114             result = EOL_CRLF;
115         }else{
116             String errMsg = MessageFormat.format(ERRMSG_INVNL, arg);
117             throw new CmdLineException(errMsg);
118         }
119
120         return result;
121     }
122
123     /**
124      * ブール指定子をデコードする。
125      * @param arg 文字列
126      * @return デコード結果。
127      * @throws CmdLineException 不正なフォーマット種別
128      */
129     private static boolean decodeBoolean(String arg)
130             throws CmdLineException{
131         boolean result;
132
133         if(   "on"  .equals(arg)
134            || "true".equals(arg)
135            || "yes" .equals(arg) ){
136             result = true;
137         }else if(   "off"  .equals(arg)
138                  || "false".equals(arg)
139                  || "no"   .equals(arg) ){
140             result = false;
141         }else{
142             String errMsg = MessageFormat.format(ERRMSG_INVBOOL, arg);
143             throw new CmdLineException(errMsg);
144         }
145
146         return result;
147     }
148
149     /**
150      * ファイル名からファイル種別を類推する。
151      * <p>拡張子が「.vmd」ならVMDファイル、「.xml」ならXMLファイル。
152      * @param fileName ファイル名
153      * @return ファイル種別。識別不可ならNONE。
154      */
155     private static MotionFileType getFileType(String fileName){
156         MotionFileType result = MotionFileType.NONE;
157         if(fileName == null) return result;
158
159         String lower = fileName.toLowerCase(Locale.ROOT);
160         if     (lower.endsWith(SFX_VMD)) result = MotionFileType.VMD;
161         else if(lower.endsWith(SFX_XML)) result = MotionFileType.XML_AUTO;
162
163         return result;
164     }
165
166     /**
167      * ヘルプ要求があるかコマンドライン列を調べる。
168      * @param cmds コマンドライン列
169      * @return ヘルプ要求があればtrue
170      */
171     private static boolean hasHelp(List<CmdLine> cmds){
172         for(CmdLine cmd : cmds){
173             OptSwitch opt = cmd.getOptSwitch();
174             if(opt == OptSwitch.OPT_HELP){
175                 return true;
176             }
177         }
178         return false;
179     }
180
181     /**
182      * 個別のオプション情報を格納する。
183      * @param opt オプション識別子
184      * @param exArg 引数。なければnull
185      * @param result オプション情報格納先
186      * @throws CmdLineException 不正なコマンドライン
187      */
188     private static void storeOptInfo(OptSwitch opt,
189                                        String exArg,
190                                        OptInfo result )
191             throws CmdLineException{
192         switch(opt){
193         case OPT_FORCE:
194             result.overwrite = true;
195             break;
196         case OPT_QUAT:
197             result.isQuaternionMode = true;
198             break;
199         case OPT_EYXZ:
200             result.isQuaternionMode = false;
201             break;
202         case OPT_INFILE:
203             result.inFilename = exArg;
204             break;
205         case OPT_OUTFILE:
206             result.outFilename = exArg;
207             break;
208         case OPT_NEWLINE:
209             result.newline = decodeNewline(exArg);
210             break;
211         case OPT_IFORM:
212             MotionFileType itype = decodeFormatType(exArg);
213             result.inTypes  = itype;
214             break;
215         case OPT_OFORM:
216             MotionFileType otype = decodeFormatType(exArg);
217             result.outTypes  = otype;
218             break;
219         case OPT_GENOUT:
220             boolean genout = decodeBoolean(exArg);
221             if(genout) result.generator = Vmd2Xml.GENERATOR;
222             else       result.generator = null;
223             break;
224         default:
225             break;
226         }
227
228         return;
229     }
230
231     /**
232      * コマンドラインを解析する。
233      * @param args コマンドライン
234      * @return オプション情報
235      * @throws CmdLineException 不正なコマンドライン
236      */
237     static OptInfo parseOption(String... args) throws CmdLineException{
238         List<CmdLine> cmdLines = CmdLine.parse(args);
239
240         OptInfo result = new OptInfo();
241
242         if(hasHelp(cmdLines)){
243             result.needHelp = true;
244             return result;
245         }
246
247         checkCmdLineList(cmdLines);
248
249         for(CmdLine cmd : cmdLines){
250             OptSwitch opt = cmd.getOptSwitch();
251
252             List<String> optArgs = cmd.getOptArgs();
253             String exArg1 = null;
254             if(optArgs.size() >= 2){
255                 exArg1 = optArgs.get(1);
256             }
257
258             storeOptInfo(opt, exArg1, result);
259         }
260
261         fixFormat(result);
262
263         checkResult(result);
264
265         return result;
266     }
267
268     /**
269      * 単純なコマンドラインエラーを検出する。
270      * <p>検出項目は未知のオプションおよび不正な引数の個数
271      * @param cmdLines コマンドライン
272      * @throws CmdLineException 異常系
273      */
274     private static void checkCmdLineList(List<CmdLine> cmdLines)
275             throws CmdLineException{
276         for(CmdLine cmd : cmdLines){
277             List<String> optArgs = cmd.getOptArgs();
278             assert ! optArgs.isEmpty();
279
280             String optTxt = optArgs.get(0);
281             assert optTxt != null;
282
283             OptSwitch opt = cmd.getOptSwitch();
284             if(opt == null){
285                 String errMsg =
286                         MessageFormat.format(ERRMSG_UNKNOWN, optTxt);
287                 throw new CmdLineException(errMsg);
288             }
289
290             int exArgNum = opt.getExArgNum();
291             if(optArgs.size() != 1 + exArgNum){
292                 String errMsg =
293                         MessageFormat.format(ERRMSG_MOREARG, optTxt);
294                 throw new CmdLineException(errMsg);
295             }
296         }
297
298         return;
299     }
300
301     /**
302      * ファイルフォーマット情報の推測を行う。
303      * @param result オプション情報
304      */
305     private static void fixFormat(OptInfo result){
306         if(result.inTypes == MotionFileType.NONE){
307             result.inTypes = getFileType(result.inFilename);
308         }
309
310         if(result.outTypes == MotionFileType.NONE){
311             result.outTypes = getFileType(result.outFilename);
312         }
313
314         return;
315     }
316
317     /**
318      * オプション整合性の事後検査。
319      * @param result オプション情報
320      * @throws CmdLineException 不正なオプション設定
321      */
322     private static void checkResult(OptInfo result)
323             throws CmdLineException{
324         if(result.getInFilename() == null){
325             throw new CmdLineException(ERRMSG_NOINFILE);
326         }
327
328         if(result.getOutFilename() == null){
329             throw new CmdLineException(ERRMSG_NOOUTFILE);
330         }
331
332         if(result.getInFileType()  == MotionFileType.NONE){
333             throw new CmdLineException(ERRMSG_INTYPE);
334         }
335
336         if(result.getOutFileType()  == MotionFileType.NONE){
337             throw new CmdLineException(ERRMSG_OUTTYPE);
338         }
339
340         return;
341     }
342
343
344     /**
345      * ヘルプ表示が必要か否か判定する。
346      * @return 必要ならtrue
347      */
348     boolean needHelp(){
349         return this.needHelp;
350     }
351
352     /**
353      * 入力ファイル種別を返す。
354      * @return 入力ファイル種別
355      */
356     MotionFileType getInFileType(){
357         return this.inTypes;
358     }
359
360     /**
361      * 出力ファイル種別を返す。
362      * @return 出力ファイル種別
363      */
364     MotionFileType getOutFileType(){
365         return this.outTypes;
366     }
367
368     /**
369      * 入力ファイル名を返す。
370      * @return 入力ファイル名
371      */
372     String getInFilename(){
373         return this.inFilename;
374     }
375
376     /**
377      * 出力ファイル名を返す。
378      * @return 出力ファイル名
379      */
380     String getOutFilename(){
381         return this.outFilename;
382     }
383
384     /**
385      * 上書きモードか否か返す。
386      * @return 上書きモードならtrue
387      */
388     boolean overwriteMode(){
389         return this.overwrite;
390     }
391
392     /**
393      * XML改行文字を返す。
394      * @return 改行文字
395      */
396     String getNewline(){
397         return this.newline;
398     }
399
400     /**
401      * ジェネレータ名を返す。
402      * @return ジェネレータ名。表示したくない時はnull
403      */
404     String getGenerator(){
405         return this.generator;
406     }
407
408     /**
409      * 回転情報のXML出力形式を得る。
410      * @return クォータニオン形式ならtrue、YXZオイラー角形式ならfalse。
411      */
412     boolean isQuaterniomMode(){
413         return this.isQuaternionMode;
414     }
415
416 }