APTでテンプレートメソッドパターンを生成する その2
前回はテンプレートメソッドパターンの実装の基となる抽象クラスと、生成するクラスのメタ情報となるアノテーションを用意した。
さてここでおさらいだ。前回用意したアノテーションを元になるクラス又はインタフェースに記述することにより、指定された抽象クラスを継承する具象クラスを生成する。大体以下のような形になる
- 対象となるクラス(インタフェース)を用意する
XMLPullParsarをパースし、その要素をマップする型を用意するが、ここではその型そのものではなくアノテーションを記述するための土台となるクラスを用意し、アノテーションは予想されるXML要素に合わせて記述する。
-
- UserInfo.java (例のため、フィールドを絞っている)
@XmlAutoBean(beandClass="net.kazzz.dto.UserInfoDto",
elements={
@Element(name="user-cd", fieldName="userCd"), // 利用者CD
@Element(name="name"), // 名前
@Element(name="address") // 住所
})
public class UserInfo {}ポイントとしてJavaは同名のアノテーションを同一のエレメント(この場合はクラス)に複数記述することができないので@Elementアノテーションの配列を内部に保持することで複数の要素とフィールドをマップできるようにしている所だ。
また、最初の要素名"user-cd"に対応するJavaフィールド名は"userCd"と違う名前を指定することも可能になっており、その場合はフィールド名に合わせてキャメルケースでアクセサが出力される。
そして今回のアノテーションプロセッサにより生成されるクラスは以下のようになる。
-
- UserInfoDto.java
package net.kazzz.dto;
import java.io.IOException;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import net.kazzz.dto.xml.AbstractXmlDto;
@Generated(
value={"net.kazzz.annotation.XmlAutoBeanAnnotationProcessor"}
, date="2011-01-02T00:21:53.295+0900")
public class UserInfoDto extends AbstractXmlDto {
protected String userCd;
protected String name;
protected String address;
/* (non-Javadoc)
* @see parse(org.jaffa.dto.xml.AbstractXmlDto)
*/
@Override
public void parse(XmlPullParser parser) throws XmlPullParserException, IOException {
int type;
String tagName = "";
while((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
switch(type) {
case XmlPullParser.START_DOCUMENT:
break;
case XmlPullParser.START_TAG:
tagName = parser.getName();
break;
case XmlPullParser.TEXT:
if( tagName.equalsIgnoreCase("user-cd")) {
this.setUserCd(parser.getText());
} else
if( tagName.equalsIgnoreCase("name")) {
this.setName(parser.getText());
} else
if( tagName.equalsIgnoreCase("address")) {
this.setAddress(parser.getText());
}
break;
case XmlPullParser.END_TAG:
tagName = "";
break;
}
}
}
public String getUserCd() {
return this.userCd;
}
public void setUserCd(String userCd) {
this.userCd = userCd;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return this.address;
}
public void setAddress(String address) {
this.address = address;
}
}こちらも特別なことはしておらず、処理としては標準的なフィールドアクセを生成することと、サアノテーションに記述された通りにパーサがパース中のXML要素の値からJavaオブジェクトのセッターを呼び出しして自身のプロパティをセットしているだけである。
java beansであることを厳密にするためにはequalsメソッドとhashCodeメソッドのオーバライドが必要だが、そもそもAndroidではJava Beansをサポートしておらず、今回は厳密な等値検査にも拘らないので、これらのメソッドの生成は割愛することにする。
アノテーションプロセッサの実装は以前に紹介した通りだが、難しい所は何も無い。
1. アノテーションが記述された型を検出する
2. 記述されたアノテーションの属性値(規定値)を読み出す
3. 属性値を使って新しいクラスの実装を出力する
次回は順を追ってアノテーションプロセッサの実装について解説していこう。