DoltengのScaffoldを拡張するには。

Doltengには、DatabaseViewのテーブルで、「Generate Scaffold Application」を選択すると、
モーダルダイアログが起動し、そこでOKボタンを押下すると、
Scaffoldとなるアプリケーションが自動的に生成されます。


今回のリリースでは、このScaffold機能を拡張ポイントして差し込む事が出来る様になりました。


基本的には、例によってorg.seasar.dolteng.scaffoldのコードを読んで貰うのが確実かつ厳密です。


Scaffold機能を拡張する為に、押えるべきポイントは、以下の四点です。

  • ResourceLoader
  • ScaffoldConfigEnabler
  • テンプレートファイル及び出力されるリソースの構造定義
  • テンプレートの記述

ResourceLoader

以前に

で、説明したのと同じクラスですので、今回は割愛します。

ScaffoldConfigEnabler

Scaffoldは、前提となるライブラリや設定が存在する筈です。
Doltengにおける当該機能では出力先ディレクトリが固定となる為、
プロジェクトのディレクトリ構造にも前提条件が存在する筈です。

Scaffold実行前のダイアログでは、Scaffoldのタイプを選択する事が出来るのですが、
動作不能なタイプが選択可能であったとしても、特に意味は無く混乱を生むだけです。
その為、ScaffoldConfigEnablerによって、フィルタリングを行います。
このクラスは以下の様なインターフェースになっています。

public interface ScaffoldConfigEnabler {
	/**
	 * @param project 処理対象となるプロジェクト
	 * @return true : 利用可能 / false : 利用不能
	 */
	boolean enableFor(IProject project);
}

このクラスの実装クラスを作成する事によって、当該プロジェクトにおいて、
拡張したScaffoldが実行可能かをチェックする事が出来ます。


例えば、Doltengでは、

それぞれの組合わせによって、Scaffoldとして作成されるクラスやHTMLに違いがあります。

これを切り分ける為に、以下の様な実装を行っています。
以下の例では、Teeda + S2Daoのプロジェクトを対象とするScaffold機能が有効になる様なチェックを行っています。

public class TeedaS2DaoEnabler implements ScaffoldConfigEnabler {
	public boolean enableFor(IProject project) {
		DoltengPreferences pref = DoltengCore.getPreferences(project);
		return pref != null
				&& Constants.VIEW_TYPE_TEEDA.equals(pref.getViewType())
				&& Constants.DAO_TYPE_S2DAO.equals(pref.getDaoType());
	}
}

enableForメソッドで、falseが返ったプロジェクトでは、Scaffold機能実行時のダイアログに、
当該Scaffoldの名前が出力されません。

テンプレートファイル及び出力されるリソースの構造定義

Scaffold機能を実行すると、FreeMarkerで記述されたテンプレートが複数リソースを出力します。
テンプレートファイルが、どこに配置されており、それぞれのテンプレートの実行結果をどこに出力するのかを、
plugin.xmlに記述します。


Teeda + S2DaoのScaffold機能を例にとって説明します。
以下のXMLは、当該機能のplugin.xmlを部分的に抜粋したものです。

<templates
	enablement="org.seasar.dolteng.scaffold.enabler.TeedaS2DaoEnabler"
	id="0" name="Teeda + S2Dao"
	resourceLoader="org.seasar.dolteng.scaffold.ScaffoldResourceLoader">
	<template path="template/fm/java_entity_s2dao.ftl"
		override="false"
		outputpath="${javasrcroot}/${rootpackagepath}/${entitypackagename}/"
		outputname="${table_capitalize}.java" />
	<template path="template/fm/html_edit.ftl" override="true"
		outputpath="${webcontentsroot}/${viewrootpath}/${table}/"
		outputname="${table}Edit.html" />
	<template path="template/fm/html_confirm.ftl"
		override="true"
		outputpath="${webcontentsroot}/${viewrootpath}/${table}/"
		outputname="${table}Confirm.html" />
</templates>

若干分り辛いのですが、ここでは二つのタグが登場します。

  • templates
  • template


templatesタグでは、1つ以上のtemplateタグを子要素として抱えます。
属性として以下の項目を設定して下さい

  • id属性は、templatesタグが一意になる様に定義して下さい。Doltengでは面倒なので、数字を振ってしまっています。
  • name属性は、Scaffold機能実行時のダイアログに出力される名前です。
  • enablement属性は、ScaffoldConfigEnablerの実装クラスを指定します。
  • resourceLoader属性は、ResourceLoaderの実装クラスを指定します。
    templateタグで指定されたテンプレートファイルを読み込む際に使用されます。


templateタグでは、個別のテンプレートが、どこにあるのかと、その出力先を定義します。

  • path属性では、ResourceLoaderに引き渡されるテンプレートのパスを設定します。
  • outputpath属性では、出力先のパスを指定します。ここでは、Doltengが内部に抱えるコンテキスト情報によってある程度出力先を動的に変更する事が出来る様になっています。
  • outputname属性では、出力されるファイル名を指定します。ここでは、outputpath属性と同様にDoltengが内部に抱えるコンテキスト情報にアクセスできます。
  • override属性では、出力先に指定されたパスに、既にリソースが存在している際に上書きを行うか否かを定義します。trueを指定すると上書きします。

コンテキスト情報にアクセスする為には、${で始まり}で終わる様に、置換したい部分を記述します。
${と}に挟まれた内部の文字列をキーとして、Doltengが内部に抱えるコンテキスト情報から、
値を取り出し、${から}までの部分と置換します。


Doltengが内部で抱えるコンテキスト情報は、以下の様な種類があります。

キー 元になる情報
javasrcroot ウィザードでの入力(PackageFragmentRoot)
rootpackagename ウィザードでの入力(Root Package Name)
rootpackagepath ウィザードでの入力(Root Package Nameの.を/に置換した結果)
table DatabaseViewで選択されたテーブル名の_を基準にキャメライズを行い更に、一文字目を小文字にした結果
table_capitalize DatabaseViewで選択されたテーブル名の_を基準にキャメライズを行った結果
table_rdb DatabaseMetaDataとして取得したテーブル名
resourceroot プロジェクトのプロパティのResourcePath
flexsrcroot プロジェクトのプロパティのFlex Source Path
webcontentsroot Sysdeo Tomcat Plugin のWebアプリケーションルートとするサブディレクトリー

以上に加えて、NamingConventionに存在する全てのプロパティにアクセス出来ます。

テンプレートの記述の際にも、同様の情報にアクセスする事が出来ます。

テンプレートの記述

テンプレートの記述には、FreeMarkerを使用します。


テンプレートに引き渡されるオブジェクトは、ScaffoldModelです。
勢いで書いたコードがそのままなので、この部分にまるで拡張性がありません。
もし、Scaffoldを追加したいと言う方で、この部分の拡張性を求めるのであれば、
コメントかトラックバックを下さい。何か考えます。


FreeMarkerについては、特に説明しません。以下のマニュアルを読んで下さい。

http://freemarker.sourceforge.net/