Javaで型安全にプロパティファイルにアクセスするには。

皆さんこんにちは、このブログに記事を書くのも随分久しぶりです。

Javaでメッセージや設定を扱うときに使われるPropertiesクラス。皆さん好きでしょうか?
僕は嫌いです。引数が文字列で、型安全じゃないから。
properties.getProperty("setting.key1") みたいにプロパティを取得するとき "setting.key1" というキーが本当にあるのかどうか実行するまでわからないってすごくストレスじゃないですか?

動かない時に、プロパティファイルのキー名とソース中のキー名が同じかどうか確認する作業。最悪ですよね。
動的言語使ってる時に、そういう問題が起きるのはまぁいいんですよ。そういうもんなので。

けど、Java使ってる時にそういう問題が起きるって嫌じゃないですか。普段「コンパイル時に単純なエラーは検出できる〜〜!!」「IDEによる優れた補完によってコード入力の手間は少ないのだ〜〜!!」とか恥ずかしげもなく言ってるJava好きの人間が「プロパティファイルのキー名間違えた〜。再起動しないと…」とか言わざるをえない状況とか、心底クソだと思います。

で、思いましたよ。
Javaでも Resource.setting.key1() のようにプロパティファイルの値取ってこれたら便利じゃね?みたいな。
イデア元はRubyのsettingslogicです。あれはYAMLで記述した設定ファイルから Settings.setting.key1 のように値を取得できるのでこれをJavaでもやりたいわけですよ。
Javaで実現できたらそれってコンパイル時にキー名の間違いとか検出できますよね。型安全ですよね。うーん、人類はぜひこのようにプロパティファイルにアクセスできるようになるべきだ。

で、考えましたよ。
JavaにはAPTってありますよね。これで、コンパイル時にプロパティファイル読み込んで、すべてのキーに対応するメソッドを自動生成してやればいいのでは…、と。

で、作りました。APTで指定したプロパティファイルから型安全なアクセサを自動性するAPTライブラリを。
https://github.com/mitoma/ponto

詳細は github のページを見ていただければだいたいわかるかと思いますが、これで PontoResource.settings.key1() みたいにしてプロパティファイルにアクセスすることができます。

こんなpropertiesファイルに対して

product_name=Ponto
setting.key1=value1
setting.key2=value2
setting.key3=value3
setting.category1.sub1=subvalue

こんなJavaクラスを自動生成しているからです。

public class PontoResource {
  public static String product_name(){ return getProperties("product_name"); }
  public static class setting {
    public static String key3(){ return getProperties("setting.key3"); }
    public static String key2(){ return getProperties("setting.key2"); }
    public static String key1(){ return getProperties("setting.key1"); }
    public static class category1 {
      public static String sub1(){ return getProperties("setting.category1.sub1"); }
    }
  }
  private static java.util.Properties properties = new java.util.Properties();
  static {
    ClassLoader loader = ClassLoader.getSystemClassLoader();
    try{
      properties.load(loader.getResourceAsStream("ponto.properties"));
    }catch (Exception e){}
  }
  private static String getProperties(String key){
    return properties.getProperty(key);
  }
}

うーん、悪そうなクラスですね〜、クラス名とか規約とかに違反してそうですね〜。スタティックおじさんですね〜。
けどプロパティに型安全に、利便性を損ねずにアクセスするためにはこういうのもアリだと思うのです。

ありなのでは〜!!!?