量産メモ帳

忘れっぽいのでメモを残しています。

PropertyUtilsを利用したディープコピー。

スポンサーリンク

とりあえずその場しのぎで実装してみたのが、これ。
orig が org.apache.commons.beanutils.DynaBean のケースは考慮してない。

import java.beans.PropertyDescriptor;
import java.lang.reflect.Array;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.collections.Factory;
import org.apache.commons.collections.FactoryUtils;

/** ディープコピー。 */
public static T deepCopy(T orig)
        throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
    if (orig == null) {
        return null;
    }

    Class origClass = orig.getClass();
    if (origClass.isPrimitive()
            || String.class.equals(origClass)
            || Boolean.class.equals(origClass)
            || Number.class.isAssignableFrom(origClass)) {
        return orig;
    } else if (origClass.isArray()) {
        Object[ ] origArray = (Object[ ]) orig;
        Class origComponentType = origClass.getComponentType();
        int origSize = origArray.length;

        Object[ ] destArray = (Object[ ]) Array.newInstance(origComponentType, origSize);
        for (int i = 0; i < origSize; i++) {
            destArray[i] = deepCopy(origArray[i]);
        }

        return (T) destArray;
    }

    Factory factory = FactoryUtils.instantiateFactory(origClass);
    T dest = (T) factory.create();

    if (dest instanceof List) {
        List destList = (List) dest;
        List origList = (List) orig;
        int origSize = origList.size();
        for (int i = 0; i < origSize; i++) {
            Object origElement = origList.get(i);
            Object destElement = deepCopy(origElement);
            destList.add(destElement);
        }
    } else if (dest instanceof Map) {
        Map destMap = (Map) dest;
        Map origMap = (Map) orig;
        Set origKeySet = origMap.keySet();
        Iterator origKeyIter = origKeySet.iterator();
        while (origKeyIter.hasNext()) {
            Object origKey = (Object) origKeyIter.next();
            Object origValue = origMap.get(origKey);
            Object destValue = deepCopy(origValue);
            destMap.put(origKey, destValue);
        }
    } else {
        PropertyDescriptor origDescriptors[ ] = PropertyUtils.getPropertyDescriptors(orig);
        for (int i = 0; i < origDescriptors.length; i++) {
            String propName = origDescriptors[i].getName();
            if (PropertyUtils.isReadable(orig, propName)) {
                if (PropertyUtils.isWriteable(dest, propName)) {
                    Object origValue = PropertyUtils.getSimpleProperty(orig, propName);
                    Object destValue = deepCopy(origValue);
                    PropertyUtils.setSimpleProperty(dest, propName, destValue);
                }
            }
        }
    }

    return dest;
}

大したテストはしてないので、取り扱い注意w