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