XML を解析してデータを取得する際、外部に渡せる形、あるいは内部で扱いやすい形でデータを受け取るためのオブジェクト定義が必要です。このセクションでは、Android 環境で動作する SAX パーサーから得られる情報を保持するためのデータ構造を実装します。それぞれのクラスは Parcelable インターフェースを実装しており、コンポーネント間でのデータ転送が容易になります。
SchoolInfo クラス(学校情報)
最上位のデータ構造として SchoolInfo を定義します。このクラスには複数の専門コース(Major)を管理するリストフィールドが含まれています。XML の School タグに対応し、リストの追加および取得メソッドを実装しています。また、パケット送信に必要なパーセル処理も記述されています。
package tech.example.saxmodel;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.ArrayList;
import java.util.List;
public class SchoolInfo implements Parcelable {
public static final String NODE_NAME = "School";
public String displayName;
public String institutionCode;
public List<MajorInfo> departments;
public static final Parcelable.Creator<SchoolInfo> CREATOR =
new Parcelable.Creator<SchoolInfo>(){
@Override
public SchoolInfo createFromParcel(Parcel in) {
return new SchoolInfo(in);
}
@Override
public SchoolInfo[] newArray(int size) {
return new SchoolInfo[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.displayName);
dest.writeString(this.institutionCode);
dest.writeTypedList(this.departments);
}
protected SchoolInfo(Parcel in) {
this.displayName = in.readString();
this.institutionCode = in.readString();
if (in.readByte() != null) { // Check read status if list exists
this.departments = in.createTypedList(MajorInfo.CREATOR);
} else {
this.departments = new ArrayList<>();
}
}
public SchoolInfo(String name, String code) {
this.displayName = name;
this.institutionCode = code;
this.departments = new ArrayList<>();
}
public void appendDepartment(MajorInfo dept) {
this.departments.add(dept);
}
public List<MajorInfo> getDepartments() {
return this.departments;
}
@Override
public String toString() {
return getNameOrDefault();
}
private String getNameOrDefault() {
if(this.displayName == null) {
return "(未設定)";
}
return this.displayName;
}
}
MajorInfo クラス(学科情報)
次レベルの構造体です。学校内の各専攻を表し、さらにその下に授業グループ(ClassGroup)のリストを持ちます。同様に Parcelable をサポートし、階層構造を正しくシリアライズできるように実装されます。
package tech.example.saxmodel;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.ArrayList;
import java.util.List;
public class MajorInfo implements Parcelable {
public static final String NODE_NAME = "Major";
public String subjectName;
public String departmentCode;
public List<ClassGroup> groupClasses;
public static final Parcelable.Creator<MajorInfo> CREATOR =
new Parcelable.Creator<MajorInfo>(){
@Override
public MajorInfo createFromParcel(Parcel in) {
return new MajorInfo(in);
}
@Override
public MajorInfo[] newArray(int size) {
return new MajorInfo[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.subjectName);
dest.writeString(this.departmentCode);
dest.writeTypedList(this.groupClasses);
}
protected MajorInfo(Parcel in) {
this.subjectName = in.readString();
this.departmentCode = in.readString();
if (in.readByte() != null) {
this.groupClasses = in.createTypedList(ClassGroup.CREATOR);
} else {
this.groupClasses = new ArrayList<>();
}
}
public MajorInfo(String name, String code) {
this.subjectName = name;
this.departmentCode = code;
this.groupClasses = new ArrayList<>();
}
public String getCode() {
return (this.departmentCode);
}
public void addClassGroup(ClassGroup c) {
this.groupClasses.add(c);
}
public List<ClassGroup> getClassGroups() {
return this.groupClasses;
}
@Override
public String toString() {
return getNameOrDefault();
}
private String getNameOrDefault() {
if(this.subjectName == null) {
return "(未設定)";
}
return this.subjectName;
}
}
ClassGroup クラス(講義単位)
データ階層の終端となるクラスです。リストを持つ必要はありませんが、親クラス同様、 parcels 間の転送やログ出力のために Parcelable と toString() のオーバーライドが必要です。
package tech.example.saxmodel;
import android.os.Parcel;
import android.os.Parcelable;
public class ClassGroup implements Parcelable {
public static final String NODE_NAME = "Class";
public String className;
public String classIdentifier;
public static final Parcelable.Creator<ClassGroup> CREATOR =
new Parcelable.Creator<ClassGroup>(){
@Override
public ClassGroup createFromParcel(Parcel in) {
return new ClassGroup(in);
}
@Override
public ClassGroup[] newArray(int size) {
return new ClassGroup[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.className);
dest.writeString(this.classIdentifier);
}
protected ClassGroup(Parcel in){
this.className = in.readString();
this.classIdentifier = in.readString();
}
public ClassGroup(final String name, final String code){
this.className = name;
this.classIdentifier = code;
}
@Override
public String toString() {
return getNameOrDefault();
}
private String getNameOrDefault() {
if(this.className == null) {
return "(未設定)";
}
return this.className;
}
}
これらの実装において、静的な NODE_NAME フィールドは、元の XML ファイル内の要素名と照合するために使用されます。displayName および institutionCode (またはこれらに相当するフィールド)は、それぞれ XML ノードの属性またはテキスト内容と紐付けられます。オブジェクトの状態を確認するためには、必ず toString() メソッドをオーバーライドしてください。これを怠ると、参照アドレスの文字列が表示されたり、不正なデフォルト値が返ったりする可能性があります。