PropertiesFactory

上の話題関連。ブクマ貰って嬉しいので(笑)、ちょろっと作った。雑だけど、こりゃ楽だ。

  • PropertiesFactory.load(class)でカレントディレクトリからXML形式のプロパティファイルを開いて設定をセット、返却。
  • PropertiesFactory.save(object)でカレントディレクトリへXML形式のプロパティファイルとして保存。

今後の課題としては、アノテーションで保存する/しないを指定できるようにしたり、setter/getterでアクセスするようにしたり。とりあえず保存先のディレクトリを何とかしたりすれば、かなり使えるんじゃないでしょうか。

ProperteisFactory

むりやりclassのfieldにセットしてます。

import java.io.*;
import java.lang.reflect.Field;
import java.util.Properties;

public class PropertiesFactory {
    private static final String EXTENSION = "properties.xml";
    
    /**
     * 指定したクラスのクラス名でプロパティファイルを開き、
     * 定義されたフィールド情報から設定をセットして返却します。
     * 指定したファイルがない場合、空のインスタンスを返却します。
     */
    public static <T> T load(Class<T> propertiesClass) {
        try {
            T ret = propertiesClass.newInstance();
            File f = new File(propertiesClass.getName() + "." + EXTENSION);
            if (f.exists()) {
                InputStream stream = new FileInputStream(f);
                Properties p = new Properties();
                p.loadFromXML(stream);
                Field[] fields = propertiesClass.getDeclaredFields();
                for (Field field : fields) {
                    field.setAccessible(true);
                    field.set(ret, p.getProperty(field.getName()));
                }
                stream.close();
            }
            return ret;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    
    /**
     * 指定したオブジェクトのクラス名でプロパティファイルを開き、
     * 定義されたフィールド情報から設定を保存します。
     */
    public static void save(Object properties) {
        try {
            OutputStream stream = new FileOutputStream(
                    properties.getClass().getName() + "." + EXTENSION);
            Properties p = new Properties();
            Field[] fields = properties.getClass().getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                Object entry = field.get(properties);
                p.setProperty(field.getName(),
                        (entry == null? "": entry.toString()));
            }
            p.storeToXML(stream, "", "UTF-8");
            stream.close();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

テストケース

作り慣れてないけど、こんな感じでいいんです…よね。

import static org.junit.Assert.*;
import java.io.*;
import org.junit.*;

public class PropertiesFactoryTest {
    @Before
    public void setUp() throws Exception {
        File f = new File("TargetProperties.properties.xml");
        if(f.exists()) f.delete();
    }

    @After
    public void tearDown() throws Exception {
        //内容見たいですよね?
//      File f = new File("TargetProperties.properties.xml");
//      if(f.exists()) f.delete();
    }

    @Test
    public final void test() {
        TargetProperties t;
        t = PropertiesFactory.load(TargetProperties.class);
        assertNull("ファイルがないとき、メンバはnull。", t.getHoge());
        assertNull("ファイルがないとき、メンバはnull。", t.getFuga());
        
        t.setHoge("ほげ");
        t.setFuga("ふが");
        PropertiesFactory.save(t);
        File f = new File("TargetProperties.properties.xml");
        assertTrue("ファイルに保存できる。", f.exists());
        
        t = PropertiesFactory.load(TargetProperties.class);
        assertEquals("保存したプロパティを取得できる。", t.getHoge(), "ほげ");
        assertEquals("保存したプロパティを取得できる。", t.getFuga(), "ふが");
    }

}

class TargetProperties {
    private String hoge;
    private String fuga;
    
    public String getHoge() {
        return hoge;
    }
    public void setHoge(String hoge) {
        this.hoge = hoge;
    }
    public String getFuga() {
        return fuga;
    }
    public void setFuga(String fuga) {
        this.fuga = fuga;
    }
}