ImageRegistryの初期化。

初期化のタイミングに困ったので、フィールドのサイズを比較しているガード節
を消してしまいました。


この部分。

if (descBd.getFieldSize() != imageBd.getFieldSize()) {
            return;
}

挙句の果てに、他人様のImageRegistryにお邪魔すると言う暴挙に出る事に。
JFaceResourcesなら、勝手知ったる我家。と、いう事にしました。
正直、全く知らない他人の家ですが…。


結局、どんなコードになったかと言うと、

public class StaticImageLoader {

    public static void loadResources(Class desc, Class image, String name) {
        loadResources(JFaceResources.getImageRegistry(), desc, image, name);
    }

    public static void loadResources(ImageRegistry registry, Class desc,
            Class image, String name) {
        ResourceBundle bundle = getBundle(name, desc.getClassLoader());
        if (bundle == null) {
            return;
        }
        BeanDesc descBd = BeanDescFactory.getBeanDesc(desc);
        BeanDesc imageBd = BeanDescFactory.getBeanDesc(image);
        Map pathMap = ResourceBundleUtil.convertMap(bundle);
        for (int i = 0; i < descBd.getFieldSize(); i++) {
            Field descF = descBd.getField(i);
            String key = descF.getName();
            Field imgF = imageBd.getField(key);
            if (validateMask(descF) || validateMask(imgF)) {
                continue;
            }

            if (pathMap.containsKey(key) == false) {
                log(key + " not found in " + name);
                continue;
            }

            ImageDescriptor id = ImageDescriptor.createFromFile(desc, pathMap
                    .get(key).toString());
            registry.put(key, id);
            FieldUtil.set(descF, null, id);
            FieldUtil.set(imgF, null, registry.get(key));
        }
    }

    private static boolean validateMask(Field f) {
        final int MOD_EXPECTED = Modifier.PUBLIC | Modifier.STATIC;
        final int MOD_MASK = MOD_EXPECTED | Modifier.FINAL;
        return (f.getModifiers() & MOD_MASK) != MOD_EXPECTED;
    }

    private static void log(String msg) {
        // FIXME : FrameworkAdaptor とか、そんなん使う?
        System.out.println(msg);
    }

    private static ResourceBundle getBundle(String name, ClassLoader loader) {
        try {
            return ResourceBundle.getBundle(name, Locale.getDefault(), loader);
        } catch (MissingResourceException e) {
            return null;
        }
    }

こんなコードになりました。何か大切なモノを失った感がありますが、
便利である事の方が重要なのです。


今回のコードを使って、画像リソースを初期化するコードは、こうなります。

public class ImageDescriptors {

    public static ImageDescriptor PLUGIN_IMAGE;
}

public class Images {
    public static Image PLUGIN_IMAGE;

    static {
        StaticImageLoader.loadResources(ImageDescriptors.class, 
            Images.class, Images.class.getName());
    }
}

Images.properties
PLUGIN_IMAGE=images/sample.gif

知ってか、知らずか、NLSのサブクラスを初期化する時と、
コードの構成が非常に良く似た感じになりました。
予定調和だったのかもしれません。


ちなみにNLSのサブクラスを初期化する時のコードは、こうなります。

public class Labels extends NLS {
    public static String PLUGIN_NAME;
    static {
        Class clazz = Labels.class;
        NLS.initializeMessages(clazz.getName(), clazz);
    }
}

Labels.properties
PLUGIN_NAME=Example Plugin