public static T copy()

in empire-db/src/main/java/org/apache/empire/commons/ClassUtils.java [149:248]


    public static <T> T copy(T obj, int flags)
    {
        if (obj==null)
            return null;
        // the class
        Class<T> clazz = (Class<T>)obj.getClass(); 
        if (isImmutableClass(clazz)) 
        {   // no need to copy
            return obj; 
        }
        // class check
        if (clazz.isInterface() || clazz.isAnnotation()) {
            log.warn("Unable to copy Interface or Annotation {}", clazz.getName());
            return (Copy.has(flags, Copy.RET_NULL) ? null : obj); // not supported
        }
        // try serialize
        if ((obj instanceof Serializable) && !Copy.has(flags, Copy.SKIP_SERIAL))
        {   try
            {   ByteArrayOutputStream baos = new ByteArrayOutputStream();
                // Write the object
                ObjectOutputStream oos = new ObjectOutputStream(baos);
                oos.writeObject(obj);
                // Read the object
                ObjectInputStream oin = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
                Object copy = oin.readObject();
                // return result
                return (T)copy;
            } catch (IOException | ClassNotFoundException e) {
                log.error("Copy through Serialization failed for : "+clazz.getName(), e);
            }
        }
        // array copy
        if (clazz.isArray())
        {   // check primitive array like int[] or boolean[]
            if (!(obj instanceof Object[]))
            {   if (Copy.has(flags, Copy.RECURSE_DEEP))
                    log.warn("Copy.RECURSE_DEEP not supported for primitive arrays of type {}", clazz.getSimpleName());
                return (T)invokeSimpleMethod(java.lang.Object.class, obj, "clone", true);
            }
            // Object-array: cast and clone
            T[] cpy = ((T[])obj).clone();
            if (Copy.has(flags, Copy.RECURSE_DEEP))
            {   // copy array items
                for (int i=0; i<cpy.length; i++)
                    cpy[i] = copy(cpy[i], (flags & ~(Copy.RET_NULL)));
            }
            return (T)cpy;
        }
        // try clone
        if ((obj instanceof Cloneable) && !Copy.has(flags, Copy.SKIP_CLONE))
        {   try {
                return (T)invokeSimpleMethod(java.lang.Object.class, obj, "clone", true);
            } catch (Exception e) {
                log.error("Copy through Cloning failed for : "+clazz.getName(), e);
            }
        }
        // try copy through instantiation
        Constructor<T> ctor = (Copy.has(flags, Copy.SKIP_INST) ? null : findMatchingConstructor(clazz, 0, clazz));
        if (ctor!=null)
        {   try
            {   if (ctor.getParameterCount()==1)
                {   // try copy constructor
                    return ctor.newInstance(obj);
                }
                else
                {   // Try default constructor and copy fields
                    T copy = ctor.newInstance();
                    // copy fields of this class and all superclasses
                    for (Class<?> cl = clazz; (cl!=null && cl!=Object.class); cl=cl.getSuperclass())  
                    {
                        Field[] fields = cl.getDeclaredFields();
                        for (Field field : fields) {
                            // ignore static fields
                            if (Modifier.isStatic(field.getModifiers()))
                                continue;
                            // make accessible
                            boolean accessible = field.isAccessible();
                            if (!accessible)
                                field.setAccessible(true);
                            // copy
                            Object value = field.get(obj);
                            if (Copy.has(flags, Copy.RECURSE_FLAT | Copy.RECURSE_DEEP))
                                value = copy(value, (flags & ~(Copy.RET_NULL | Copy.RECURSE_FLAT)));
                            field.set(copy, value);
                            // restore
                            if (!accessible)
                                field.setAccessible(false);
                        }
                    }
                    return copy;
                }
            } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
                // ReflectiveOperationException
                Throwable cause = (e.getCause()!=null ? e.getCause() : e);
                log.error("Copy through Instantiation failed for {}: {}", clazz.getName(), cause);
            }
        }
        // not supported
        return (Copy.has(flags, Copy.RET_NULL) ? null : obj);
    }