Fieldを利用して設定ファイルの記述を簡易化

http://d.hatena.ne.jp/alpha_neet/20101001/1285945730


前回のenumを使った簡易化なんですが今見るとかなりひどいです。おまえenum使いたかっただけちゃうんかと自分に思わずツッコミそうです。


今度はFieldを使ったやつに書き換えてみました。今回は型指定しているので変換が楽だと思います。

import java.util.Properties;
import java.util.Enumeration;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.InvocationTargetException;


class PropertiesLoader {
  private final String filename;

  /**
   * save
   */
  public void save() { this.save(this.filename); }
  public void save(String filename) {
    try {
      Properties p = new Properties();

      // 前回のPropertiesファイル読み込み
      File f = new File(this.filename);
      if(f.exists()) {
        p.load(new FileInputStream(this.filename));
      }

      // 保存するpropertiesファイルの読み込む
      f = new File(filename);
      if(!f.exists()) f.createNewFile();
      
      Class<?> clazz = this.getClass();
      Field[] fields = clazz.getDeclaredFields();

      for(Field val: fields) { 
        try {
          val.setAccessible(true);
          if(val.get(this) == null) continue;

          /**
           * インナークラスで使用した場合親オブジェクトへの
           * 参照を持ってしまうのでfinal修飾子は外す
           * ほかにも単純にfinalは使わないようにする仕様
           */
          if(Modifier.isFinal(val.getModifiers())) continue;

          p.setProperty(val.getName(), val.get(this).toString());
          p.store(new FileOutputStream(filename), null);
        //} catch(IllegalAccessException e2) { }
        } catch(Exception e2) { e2.printStackTrace(); }
      }
    } catch(IOException e) { e.printStackTrace(); }
  }

  /**
   * initialize
   */
  public PropertiesLoader() { this("config.properties"); }
  public PropertiesLoader(String filename) {
    this.filename = filename;

    try {
      // Propertiesファイル読み込み
      File f = new File(filename);
      if(!f.exists()) f.createNewFile();
      Properties p = new Properties();
      p.load(new FileInputStream(filename));

      // Propertiesファイルのkeyを一つずつ取得
      Enumeration e = p.propertyNames();
      while(e.hasMoreElements()) {
        try { 
          String key = e.nextElement().toString();
          String data = p.getProperty(key);
          if(data==null) continue; 

          // keyと同じ名前のfieldがあるか検索
          Class<?> clazz = this.getClass();
          Field val = clazz.getDeclaredField(key);
          val.setAccessible(true);
          Class<?> type = val.getType();

          // 同じ名前があれば型ごとにキャスト
          if(type == String.class) { 
            val.set(this,data);
          } else if(type == int.class) {
            val.set(this,Integer.valueOf(data));
          // int以外のプリミティブ型の場合
          } else if(type.isPrimitive())  {
            String name = type.getName();

            // 先頭だけ大文字にする
            name =  name.substring(0, 1).toUpperCase() +
                    name.substring(1).toLowerCase();

            name = "java.lang."+name;
            Method valueOf = Class.forName(name).
              getMethod("valueOf", String.class);
            val.set(this,valueOf.invoke(null, data));
          // それ以外の場合は(Integer, Floatなど)は
          // valueOfがあればinvokeする
          } else {
            Method valueOf=type.getMethod("valueOf", String.class);
            val.set(this,valueOf.invoke(null, data));
          }
        } 
        catch(NoSuchFieldException e2) { continue; }
//        catch(ClassNotFoundException e2) {  }
//        catch(InvocationTargetException e2) {  }
//        catch(NoSuchMethodException e2) {  }
//        catch(IllegalAccessException e2) {  }
        catch(Exception e2) { e2.printStackTrace(); }
      }
    } catch(IOException e) { e.printStackTrace(); }
  }
}


class ConfigTest {
class MyConfig extends PropertiesLoader {
  String FILE_PATH;
  boolean WINDOW_MAXIMIZED;
  int WINDOW_X;
  int WINDOW_Y;
  int WINDOW_W;
  int WINDOW_H;
  Integer In;
  float fl;
  Float Fl;
}


void p(Object o) { System.out.println(o); }
ConfigTest() {
  MyConfig $ = new MyConfig();

  p($.FILE_PATH);
  p($.WINDOW_X);
  p($.WINDOW_Y);
  p($.WINDOW_W);
  p($.WINDOW_H);
  p($.WINDOW_MAXIMIZED);

  p($.In);
  p($.fl);
  p($.Fl);

  $.FILE_PATH = "aiueo";
  $.WINDOW_X = 10;
  $.WINDOW_Y = 20;
  $.WINDOW_W = 30;
  $.WINDOW_H = 40;
  $.WINDOW_MAXIMIZED = true;

  $.In = 30;
  $.fl = 5.0f;
  $.Fl = 10.0f;
  $.save();
}

public static void main(String[] args) {
  new ConfigTest();
}}