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. 属性値を使って新しいクラスの実装を出力する
次回は順を追ってアノテーションプロセッサの実装について解説していこう。