001    /*
002     * Copyright (c) 2009 The openGion Project.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     *     http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
013     * either express or implied. See the License for the specific language
014     * governing permissions and limitations under the License.
015     */
016    package org.opengion.fukurou.util;
017    
018    import java.io.BufferedReader;
019    import java.io.PrintWriter;
020    import java.io.File;
021    import java.io.IOException;
022    
023    /**
024     * CommentLineParser.java は、ファイルを行単位に処?て、コメントを除去するクラスです?
025     * ?行?の??を読み取って、コメント部?削除した??を返します?
026     *
027     * ブロ?コメント?状態や、コメント除外?状態を管?て?す?
028     * オブジェクト作?後?line( String ) メソ?に、ファイルから読み取った1行?の??を渡せ??
029     * コメントが除外された形で返されます?
030     * 行として存在しな??合?、null を返します?
031     *
032     * @og.rev 5.7.4.0 (2014/03/07) 新規追?
033     * @og.group ユー?リ?
034     *
035     * @version  6.0
036     * @author       Kazuhiko Hasegawa
037     * @since    JDK7.0,
038     */
039    public class CommentLineParser {
040            private String LINE_CMNT   = "//" ;             // ラインコメン?
041            private String BLOCK_CMNT1 = "/*" ;             // ブロ?コメント?開?
042            private String BLOCK_CMNT2 = "*/" ;             // ブロ?コメント?終?
043            private char   ESC_CHAR    = '"'  ;             // コメント除?プログラ?で使用)
044    
045            private boolean escIn   = false;                // コメント除外中かど?
046            private boolean blockIn = false;                // ブロ?コメントが継続して?かど?
047            private boolean rtnOnly = false;                // 前?行が改行?み?たかど??
048    
049            /**
050             * コメント?種類を?します?何も?しな??合?、Javaコメントを初期値で設定します?
051             *
052             * Javaの場合???番に?#47;/ , /* , */ , "(二重引用符) になります?
053             * JavaScriptなら?// , <!-- , --> , "
054             * ORACLEなら?-- , /* , */ , "(?引用符) になります?
055             *
056             * ※ サブクラスで?てもよかった?ですが、とりあえず引数私にしました?
057             *
058             * @og.rev 5.7.4.0 (2014/03/07) 新規追?
059             *
060             * @param       lineCmnt        ラインコメン?
061             * @param       blockCmnt1      ブロ?コメント?開?
062             * @param       blockCmnt2      ブロ?コメント?終?
063             * @param       escChar         コメント除?プログラ?で使用)
064             */
065            public void init( final String lineCmnt,final String blockCmnt1,final String blockCmnt2,final char escChar ) {
066                    LINE_CMNT   = lineCmnt ;                // ラインコメン?
067                    BLOCK_CMNT1 = blockCmnt1 ;              // ブロ?コメント?開?
068                    BLOCK_CMNT2 = blockCmnt2 ;              // ブロ?コメント?終?
069                    ESC_CHAR    = escChar  ;                // コメント除?プログラ?で使用)
070            }
071    
072            /**
073             * ?行?の??を読み取って、コメント部?削除した??を返します?
074             * 行として存在しな??合?、null を返します?
075             *
076             * @og.rev 5.7.4.0 (2014/03/07) 新規追?
077             *
078             * @param       inLine ?行???
079             * @return      コメント削除後??行???
080             */
081            public String line( final String inLine ) {
082                    if( inLine == null ) { return null; }
083    
084                    int size = inLine.length();
085    
086                    StringBuilder buf = new StringBuilder( size );
087    
088                    for( int st=0; st<size; st++ ) {
089                            char ch = inLine.charAt(st);
090    
091                            // ブロ?外で、エスケープ文字?場合?、?外反転
092                            if( !blockIn && ESC_CHAR == ch ) { escIn = !escIn ; }
093    
094                            if( !escIn ) {                                                                          // エスケープ外ら、??進める
095                                    // ブロ?コメント継続中
096                                    if( blockIn ) {
097                                            int ed = inLine.indexOf( BLOCK_CMNT2,st ) ;             // 終?見つける
098                                            if( ed >= 0 ) {                                                                      // 終?あれば、そこまで進める?
099                                                    blockIn = false;
100                                                    st = ed+BLOCK_CMNT2.length();
101                                                    continue;                                                                       // ブロ?コメント脱出。?読み込み
102                                            }
103                                            break;                                                                                  // ブロ?コメント未発見?次の行へ
104                                    }
105    
106                                    // ラインコメント発見?次の行へ
107                                    if( inLine.startsWith( LINE_CMNT,st ) ) { break; }      
108    
109                                    // ブロ?コメントを見つける
110                                    if( inLine.startsWith( BLOCK_CMNT1,st ) ) {
111                                            int ed = inLine.indexOf( BLOCK_CMNT2,st ) ;             // 終?見つける
112                                            if( ed >= 0 ) {
113                                                    st = ed+BLOCK_CMNT2.length();
114                                                    continue;                                                                       // ブロ?コメント脱出。?読み込み
115                                            }
116                                            else {
117                                                    blockIn = true;
118                                            }
119                                            break;                                                                                  // ブロ?コメント未発見?次の行へ
120                                    }
121                            }
122    
123                            // 通常の?なので、追?る?
124                            buf.append( ch );
125                    }
126    
127                    // rTrim() と同等?処?
128                    int len = buf.length();
129                    while ((0 < len) && (buf.charAt(len-1) <= ' ')) {
130                            len--;
131                    }
132                    buf.setLength( len );
133    
134                    String rtn = null;
135                    // 長さが 0 の行???続で現れな??します?
136                    if( len == 0 ) {
137                            if( !rtnOnly ) {
138                                    rtnOnly = true;
139                                    rtn = "";
140                            }
141                    }
142                    else {
143                            rtnOnly = false;
144                            rtn = buf.toString();
145                    }
146    
147                    return rtn ;
148            }
149    
150            /**
151             * こ?クラスの動作確認用の、main メソ?です?
152             *
153             * Usage: java org.opengion.fukurou.util.CommentLineParser inFile outFile [encode]
154             *
155             * @param       args    コマンド引数配?
156             */
157            public static void main( final String[] args ) {
158                    if( args.length < 2 ) {
159                            System.out.println( "Usage: java org.opengion.fukurou.util.CommentLineParser inFile outFile [encode]" );
160                    }
161    
162                    File inFile  = new File( args[0] );
163                    File outFile = new File( args[1] );
164                    String encode  = (args.length >= 3 ) ? args[3] : "UTF-8" ;
165    
166                    BufferedReader reader = FileUtil.getBufferedReader( inFile ,encode );
167                    PrintWriter    writer = FileUtil.getPrintWriter(   outFile ,encode );
168    
169                    try {
170                            String line1;
171                            while((line1 = reader.readLine()) != null) {
172                                    writer.println( line1 );
173                            }
174                    }
175                    catch( IOException ex ) {
176                            String errMsg = "ファイルコピ?中に例外が発生しました?n"
177                                                    + " inFile=[" + inFile + "] , outFile=[" + outFile + "]\n" ;
178                            throw new RuntimeException( errMsg,ex );
179                    }
180                    finally {
181                            Closer.ioClose( reader ) ;
182                            Closer.ioClose( writer ) ;
183                    }
184            }
185    }