JSP/Servletのお勉強メモ その10

家にあるJSP/Servletの本見直してたら, 昨日のソースとよく似たのがあった.
しかも, 断然自分のより良い.
ちょっち修正するかな.


修正ついでに特定のHTMLタグだけを認識するようにするために,
そのためのターミナル上で動作するテストプログラムを組んでみた.

package test.textarea;

import java.util.*;

public class ProcessInputDataTest
{
    static Hashtable<String, Boolean> map = new Hashtable<String, Boolean>();

    static{
        fillMap();
    }

    // タグであれば0以上の値が, そうでなければ, -1が返戻される.
    private static int isTag( int start, String textarea )
    {
        int count = -1;

        try{
            for( int i=1; i<12; i++ ){
                // タグ'<'以降の文字列がタグ文字列と一致するかどうか. 一致しなければ, NullPointerException.
                if( map.get( textarea.substring( start+1, start+1+i ).toUpperCase() ) == true ){
                    // タグ文字列の次の文字は空白, もしくは, '>'でなければならない
                    char c = textarea.charAt( start+i+1 );
                    if( c == ' ' || c == '>' ){
                        count = i;
                        break;
                    }
                } else {
                    // コメント<!-- -->だった場合
                    count = i;
                    break;
                }
            }
        } catch( NullPointerException e ){
            return -1;
        }

        // 行末までに終端タグがあるかどうかを調べる
        if( count > 0 ){
            char c = textarea.charAt( start+count+1 );
            for( int i=1; c!='>'; count++ ){
                if( c == '\n' ){
                    count = -1;
                    break;
                }
                c = textarea.charAt( start+count+i );
            }
        }

        return count;
    }

    private static String processString( String textarea )
    {
        int slash = 0;          // 終端タグにつく/の分の文字数
        int count = 0;          // タグチェックにより進んだ文字数

        StringBuffer output = new StringBuffer();

        textarea += '\n';       // 文末に改行文字をつけておく(念のため)
        for( int i=0; i<textarea.length(); i++ ){
            char c = textarea.charAt(i);
            switch(c){
            case  '&':
                output.append( "&amp;" );
                break;
            case  '>':
                output.append( "&gt;" );
                break;
            case  '<':
                if( textarea.charAt(i+1) == '/' ){
                    slash = 1;
                }
                count = isTag( i+slash, textarea );
                if( count > 0 ){
                    // 第2引数で+2としているのは, substringが書き込む文字列の最終文字の次を指定しなければならないため.
                    output.append( textarea.substring( i, i+slash+count+2 ) );
                    slash = 0;
                    i += count+1;
                } else {
                    output.append( "&lt;" );
                }
                break;
            case  ' ':
                output.append( "&nbsp;");
                break;
            case '\"':
                output.append( "&quot;" );
                break;
            case '\'':
                output.append( "&#39;" );
                break;
            case '\t':
                output.append( "&nbsp;&nbsp;&nbsp;&nbsp;" ); // タグは空白4つ
                break;
            case '\n':
                output.append( "\n" );
                break;
            default:
                output.append(c);
                break;
            }
        }
        return output.toString();
    }

    static void setTag(String k, boolean v)
    {
        map.put( k, v );
    }

    // 値が無い場合はNULLを返す
    static void fillMap()
    {
        setTag(         "H1", true );
        setTag(         "H2", true );
        setTag(         "H3", true );
        setTag(         "H4", true );
        setTag(         "H5", true );
        setTag(         "H6", true );
        setTag(       "FONT", true );
        setTag(   "BASEFONT", true );
        setTag(        "BIG", true );
        setTag(      "SMALL", true );
        setTag(          "B", true );
        setTag(          "I", true );
        setTag(          "U", true );
        setTag(          "S", true );
        setTag(         "TT", true );
        setTag(        "SUP", true );
        setTag(        "SUB", true );
        setTag(      "BLINK", true );
        setTag(          "P", true );
        setTag(         "BR", true );
        setTag(         "HR", true );
        setTag(     "CENTER", true );
        setTag(        "DIV", true );
        setTag( "BLOCKQUOTE", true );
        setTag(        "PRE", true );
        setTag(        "XMP", true );
        setTag(       "NOBR", true );
        setTag(        "WBR", true );
        setTag(   "MULTICOL", true );
        setTag(     "SPACER", true );
        setTag(         "UL", true );
        setTag(         "OL", true );
        setTag(         "LI", true );
        setTag(         "DL", true );
        setTag(         "DT", true );
        setTag(         "DD", true );
        setTag(          "A", true );
        setTag(      "TABLE", true );
        setTag(         "TR", true );
        setTag(         "TD", true );
        setTag(         "TH", true );
        setTag(    "CAPTION", true );
        setTag(        "!--", false );
        setTag(        "IMG", true );
        setTag(        "MAP", true );
        setTag(       "AREA", true );
    }

    public static void main(String[] argv)
    {
        String input  = "てすと<i>てすと</i>\"日本語よ\"" + "\n"
            + "\'かなーり問題\'ぱやぱや<html>びろーん</html>" + "\n"
            + "<!--あらあら-->うふふ<big" + "\n";
        String output = processString( input );

        System.out.println( "--------------------------------------------------------------------------------"  );
        System.out.println( "入力データ"  );
        System.out.println( "--------------------------------------------------------------------------------"  );
        System.out.println( input  );
        System.out.println( "--------------------------------------------------------------------------------"  );
        System.out.println( "出力データ"  );
        System.out.println( "--------------------------------------------------------------------------------"  );
        System.out.println( output );
        System.out.println( "--------------------------------------------------------------------------------"  );
    }
}

やってて時計が4時半越えたから, やばいと思ったから詳細なテストは明日以降にする.
けど, 分かっているバグで, コメントだけ認識してくれない.
なんでだろう?
全部&なんたらかんたらのに変換しちまう.