Webアプリケーションやソースの自動生成など,テキスト生成をする機会は世の中にたくさんあります.java.io.Writerなどで直接テキストを書き出せば目的を達成できますが,この場合,プログラムソースと文書が混在してしまい,可読性やメンテナンスが低下してしまいます.
この場合は,元となるテンプレートテキストと,プログラムを分離して管理した方が何かと便利です.
それらのテキスト生成を,テンプレートとコンテキスト(文脈)によって生成する仕組みをこのフレームワークでは提供します.
以下の環境を前提にしています。
表1.動作環境 SDK Java 2 SDK 1.2 以上 OS Windows, Linux など 上記 SDK が動作する OS
全環境を試していないので、動作しない環境があるかもしれません。

表2.主な機能 部 機能 備考 テンプレート(ファイル) 文書要素の挿入 コンテキストリソースの値を挿入できます。 テキスト分岐(真偽) コンテキストリソースの値が"true"または"false"の時に、文書要素を差し替えることができます。 テキスト分岐(ケース) コンテキストリソースの値を条件として,文書要素を差し替えることができます。 テキストの繰り返し コンテキストリソースの値が,"true"である間、文書要素の繰り返しができます。 コンテキスト(TemplateContext) 挿入要素のマッピング そのコンテキストによって格納されたリソースの値を、挿入要素として返します.リソースの値は,Propertiesなどの固定的なものやコンテキスト内で動的に作られた値等を返せます.
lib/guatemala.jar, lib/lex.jar を 環境変数 CLASSPATH などに通してください。
以下のページからダウンロードできます。
http://cappuccino.jp/keisuken/java/guatemala/guatemala-0.5.2.tar.gz
ライセンス
質問や要望などがありましたら keisuken atmark cappuccino.ne.jp まで内容を書いてお送りください。
TAG_NORMAL ::= '%%'
TAG_TRIM_SPACE ::= '!!'
TAG_TRIM_LINE ::= '##'
TAG_TRIM_WHITE_SPACE ::= '@@'
TAG_DESC ::= (TAG_NORMAL | TAG_TRIM_SPACE | TAG_TRIM_LINE | TAG_TRIM_WHITE_SPACE)
TAG_SEPARATOR ::= ':'
LABEL ::= Character.isJavaIdentifierStart Character.isJavaIdentifierPart*
VALUE ::= '"' [^"] '"' | Character.isJavaIdentifierPart*
TAG ::= TAG_DESC LABEL (':' (LABEL | VALUE))? TAG_DESC
| タグシグネチャ | トリミング |
|---|---|
| %% | なし |
| !! | 改行までのスペースを取り除く |
| ## | 改行までのスペースと1行分の改行を取り除く |
| @@ | 改行, スペースを取り除く |
| 右側 | 左側 | ||
|---|---|---|---|
| テンプレート | 出力 | テンプレート | 出力 |
| abc __%%foo%%__ def |
abc __{foo}__ def |
abc __%%foo%%__ def |
abc __{foo}__ def |
| abc __!!foo%%__ def |
abc {foo}__ def |
abc __%%foo!!__ def |
abc __{foo} def |
| abc __##foo%%__ def |
abc {foo}__ def |
abc __%%foo##__ def |
abc __{foo} def |
| abc __@@foo%%__ def |
abc{foo}__ def |
abc __%%foo@@__ def |
abc __{foo}def |
Hello, world!
%%message%%
context.class=HelloWorldContext message=Hello, world!
public class HelloWorldContext implements TemplateContext {
private Map elements;
pubilic void init(Properties config) {
elements = config;
}
public Object getElement(String name) {
return elements.get(name);
}
}
こんにちは ただ今2005/05/06 15:05です。
%%switch:time%% %%case:"goodmorning"%% %%goodmorning%% %%endcase%% %%case:"goodafternoon"%% %%goodafternoon%% %%endcase%% %%case:"goodevening"%% %%goodevening%% %%endcase%% %%endswitch%% ただ今%%date%%です。
context.class=DateContext goodmorning=おはようございます goodafternoon=こんにちは goodeveninig=こんばんは message=Hello, world!
public class HelloWorldContext implements TemplateContext {
private Map elements;
private Calendar calendar = Calendar.getInstance();
private Date date = new Date();
private DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm");
pubilic void init(Properties config) {
elements = config;
Calendar calendar = Calendar
elements.put("date", new Object() {
public String toString() {
return dateFormat.format(date);
}
});
elements.put("time", new Object() {
public String toString() {
calendar.setTime(date);
int hour = calendar.get(Calendar.HOUR_OF_DAY);
if(hour >= 4 && hour < 10) {
return "goodmorning";
} else if(hour >= 10 && hour < 17) {
return "goodafternoon";
} else {
return "goodevening";
}
}
});
}
public Object getElement(String name) {
return elements.get(name);
}
}
1 2 3 4 5 6 7 8 9 10
%%while:loop%% %%i%% %%endwhile%%
context.class=SimpleLoopContext start=1 end=10
public class SimpleLoopContext implements TemplateContext {
private Map elements;
private int start;
private int end;
private int i;
pubilic void init(Properties config) {
elements = config;
start = getIntProperty("start") - 1;
end = getIntProperty("end");
elements.put("i", new Object() {
public String toString() {
return Integer.toString(i);
}
});
elements.put("loop", new Object() {
public String toString() {
i++;
return new Boolean(i <= end);
}
});
}
public Object getElement(String name) {
return elements.get(name);
}
private int getIntProperty(String name) {
try {
String value = elements.get(name).trim();
return Integer.parseInt(value);
} catch(Exception e) {
return 0;
}
}
}
// Configファイル読み込み
Properties config = new Properties();
FileInputStream configIn = null;
try {
configIn = new FileInputStream("hello.props");
config.load(configIn);
} catch(IOException e) {
...
} finally {
if(configIn != null) {
configIn.close();
}
}
// TemplateDocumentFactory生成
TemplateDocument document = null;
try {
document = TemplateDocumentParser.parse("hello.tpl");
} catch(TemplateException e) {
...
} catch(IOException e) {
...
}
// 必要なContextを設定
Properties configInstance = (Properties)config.clone();
configInstance.put(..., ...);
// Document生成
FileWriter writer = null;
try {
writer = new FileWriter("hello.txt");
document.write(configInstance, writer);
} catch(IOException e) {
...
} finally {
if(writer != null) {
writer.close();
}
}