OSDN Git Service

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