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                    CommentLineParser clp = new CommentLineParser();
170    
171                    try {
172                            String line1;
173                            while((line1 = reader.readLine()) != null) {
174                                    line1 = clp.line( line1 );
175                                    if( line1 != null ) {
176                                            writer.println( line1 );
177                                    }
178                            }
179                    }
180                    catch( IOException ex ) {
181                            String errMsg = "ファイルコピã?中に例外が発生しましたã€?n"
182                                                    + " inFile=[" + inFile + "] , outFile=[" + outFile + "]\n" ;
183                            throw new RuntimeException( errMsg,ex );
184                    }
185                    finally {
186                            Closer.ioClose( reader ) ;
187                            Closer.ioClose( writer ) ;
188                    }
189            }
190    }