OSDN Git Service

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