設計
忘れないようにメモ。
一々エスケープしないで済むように、
HereDocumetn中では、特殊文字(\,",\nなど)も普通の文字として扱う。
特殊文字として扱いたい場合には、Javaコードとして埋め込む(<%= "\n" %>など)。
- スクリプトレットの有効・無効モード
スクリプトレットの有効・無効モードは、以下の3種類とする。
※悩みの種。
無名インナークラスから、final宣言なしの変数を参照できれば、全有効・全無効の2モードで済むんだけど。
第3のクォーテーション記号があれば、3モードでもキレイなんだけど。
いっそ、全無効のモードを削ってしまったほうが良いだろうか?
- 全無効
一番単純なモード。変数も制御構造も使えない。
記法は、
シングルクォーテーションのトリプルクォートと、
シングルクォーテーションで終端文字列をくくったheredocの2種類。
// シングルクォーテーションのトリプルクォート String tripleQuotes = '''AAA BBB'''; // シングルクォーテーションで終端文字列をくくったheredoc String heredoc = <<<'EOS' AAA BBB EOS;
- 有効(制御構造は無効)
記法は、
ダブルクォーテーションのトリプルクォートと、
ダブルクォーテーションで終端文字列をくくったheredocの2種類。
// ダブルクォーテーションのトリプルクォート String tripleQuotes = '''AAA <%-- コメントアウト BBB --%> <%= ccc %>'''; // ダブルクォーテーションで終端文字列をくくったheredoc String heredoc = <<<"EOS" AAA <%-- コメントアウト BBB --%> <%= ccc %> EOS;
- 全有効
記法は、終端文字列がくくられていないheredocのみ。
// 終端文字列がくくられていないheredoc String heredoc = <<<EOS AAA <%-- コメントアウト BBB --%> <% if (null != ccc) { %><%= ccc %><% } %> EOS;
-
- 制御構造(if,forなど)を無効とする理由
制御構造を含む場合、Javaコード上は無名インナークラス(無名内部クラス:anonymous inner class)とする必要がある。
インナークラスなので、参照する変数はfinal宣言が必要。finalでないと、コンパイルエラーになる。
String sql = <<<SQL SELECT * FROM aaa WHERE bbb = ? <% if ((null != ccc) && (0 < ccc.length())) { %> AND ccc = ? <% } %> SQL;
↓プリコンパイル
String sql = new Object() { public String toString() { StringBuffer buf = new StringBuffer(""); buf.append("SELECT *"); buf.append(" FROM aaa"); buf.append(" WHERE bbb = ?"); if ((null != ccc) && (0 < ccc.length())) { buf.append(" AND ccc = ?"); } return buf.toString(); } }.toString();
- プリコンパイル設定
heredoc中の改行をJavaの文字列としてどう扱うか(実行環境の改行文字、\n、\r、改行なし、等)や、
フィルタリング機能(後述)で使うメソッド等を、設定ファイルに記述する。
終端文字列ごと設定できるので、デフォルト設定を上書きすることもできる。
この機能は、ResourceBundleの国際化機能をそのまま利用する。
hdj.properties | デフォルトの設定ファイル |
hdj_SQL.properties | 終端文字列 SQL の設定ファイル。デフォルトの設定を継承 |
hdj_SQL_ORACLE.properties | 終端文字列 SQL_ORACLE の設定ファイル。SQLの設定を継承 |
hdj_SQL_ORACLE_10G.properties | 終端文字列 SQL_ORACLE_10G の設定ファイル。SQL_ORACLEの設定を継承 |
- フィルタリング機能
JSPのスクリプトレットに、HTMLの特殊文字をエスケープして出力してくれる記法があれば、
カスタムタグなしでも、簡単なHTMLの表示には十分だと思うので、
heredocjには、出力をJavaのメソッドでフィルタリングする記法を追加。
String str = <<<"AAA" <%-- --%> <%af[xxx]= aaa, bbb %> <%nf[xxx]= name=aaa, value=bbb %> "AAA";
hdj_AAA.properties
ArrayFilter[xxx]= Aaa.xxx({0},{1}) NamedFilter[xxx]= Aaa.xxx({name},{value})
- HereDocumentのネスト
HereDocumentのスクリプトレット内に書かれたHereDocumentについて。
トリプルクォーテーションの場合は、外側のHereDocumentのプリコンパイル設定を引き継ぐべきだと思うが、
終端文字列を指定されたらどうしよう?
どのようにすべきか悩む=使う人にとっても分かりづらい、となるはずなので、
ネストの場合、終端文字列指定のHereDocumentは許さない?