Step3:リフレクションAPIで変換ルールを動的に適用する
Step3ではいよいよ読み取ったデータの変換処理を組み込みます。変換ルールはデータ項目に応じて異なるので,リフレクションAPI(コラム参照)を使用して動的に変換処理を適用する必要がでてきます。
下ごしらえとして,変換ルール用のConverterというインタフェースを用意し,変換ルールごとにConverterを実装するクラスを用意します(リスト3~6)。ここでは,IntegerConverter,DateConverter,TrimConverterの3つのクラスを作成しました。これらはStep1のstaticメソッドtoInteger,toDate,trimの処理をクラス化したものになります。
次に,Excelの設定ファイルに「変換ルール」列を追加します(表3)。変換ルールには適用したい変換クラスのクラス名を指定します。
最後に,動的に変換オブジェクトを生成して実行するコードを追記します(リスト7)。
①で設定ファイルの「変換ルール」列に記述されたクラス名を取得しています。
そして,②が一番のポイントです。おーこわ注2。リフレクションAPIでクラス名の文字列から動的にClass型のオブジェクトを取得し,newInstanceメソッドでオブジェクトを生成しています。newInstanceメソッドは引数なしのコンストラクタを呼び出して,オブジェクトの生成を行います。つまり,②のコードは次のコードと同じ意味になります。
Converter converter = new IntegerConverter();
リフレクションAPIを使用することで,コードに「具体的なクラス名やメソッド」を書くことなく,動的にプログラムを実行できるようになりました。今後,変換クラスの種類が増えていっても,Step3のコードは書き換える必要がありません。
- 注2)
- 「ガリガリガリクソン」でググってみてください。
リスト3 Step3:変換ルール用のインタフェース
public interface Converter {
Object convert(Object value);
}
リスト4 Step3:変換ルール実装クラスIntegerConverter
public class IntegerConverter implements Converter {
public Object convert(Object value) {
return Integer.parseInt(value.toString());
}
}
リスト5 Step3:変換ルール実装クラスDateConverter
public class DateConverter implements Converter {
public Object convert(Object value) {
try {
return new SimpleDateFormat("yyyyMMdd")
.parse(value.toString());
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
}
リスト6 Step3:変換ルール実装クラスTrimConverter
public class TrimConverter implements Converter {
public Object convert(Object value) {
return StringUtils.trim(value.toString());
}
}
リスト7 Step3:リフレクションAPIを使用したコード
private static class MessageParser {
...
public void parse() throws Exception {
while (index < bytes.getLength() - 1) {
Map<String, Object> record =
new HashMap<String, Object>();
for (int i = 0; i < config.getRowSize(); i++) {
DataRow row = config.getRow(i);
String name =
(String) row.getValue("データ名称");
int length =
((BigDecimal) row.getValue("バイト数"))
.intValue();
String ruleClassName = ┓
(String) row.getValue("変換ルール"); ┛①
String value = getString(length);
Class<?> clazz = Class.forName(ruleClassName); ┓
Converter converter =   |
(Converter)clazz.newInstance(); ┛②
Object newValue = converter.convert(value); ―③
record.put(name, newValue);
}
System.out.println(record);
}
}
...
}
表3 Excel設定ファイル(変換ルールを追加)
| No | データ名称 | 長さ | 変換ルール |
|---|---|---|---|
| 1 | 送信日 | 8 | gcw.gcw5.converter.DateConverter |
| 2 | ユーザ名 | 10 | gcw.gcw5.converter.TrimConverter |
| 3 | メールアドレス | 20 | gcw.gcw5.converter.TrimConverter |
| 4 | ポイント | 5 | gcw.gcw5.converter.IntegerConverter |
COLUMN JavaのリフレクションAPI
リフレクションAPIとは,JavaのClassオブジェクトを通して,フィールドやメソッド,アノテーションなどのメタ情報を取得することができるAPIのことです。
Javaでメタプログラミングをする際によく使用するリフレクションAPIとして表aのものがあります。
以下の例ではリフレクションAPIを利用して,プロパティ名からゲッタメソッドを実行して戻り値を取得しています(注a)。
Employee emp = new Employee(1, "田中一郎");
String[] propNames = {"id", "name"};
for (String propName : propNames) {
// プロパティ名をメソッド名に変換(name -> getName)
String methodName = "get" +
propName.substring(0, 1).toUpperCase() +
propName.substring(1);
// メソッド名からメソッドオブジェクトを取得
Method m = emp.getClass().getMethod(methodName);
// メソッドを実行
Object result = m.invoke(emp);
// 戻り値の値を出力
System.out.println(propName + "=" + result);
}
- 注a)
- プロパティの取得には,java.beansパッケージ使用した方法もあります。
表a JavaのリフレクションAPI
| メソッド名 | 説明 |
|---|---|
| java.lang.Class#forName | クラス名からClassオブジェクトを取得する |
| java.lang.Class#newInstance | オブジェクトを生成する |
| java.lang.Class#getConstructor | コンストラクタオブジェクトを取得する |
| java.lang.Class#getMethod | メソッドオブジェクトを取得する |
| java.lang.Class#getField | フィールドオブジェクトを取得する |

