Java OffsetDateTime cloneInternally(E source, Map visited)

Here you can find the source of cloneInternally(E source, Map visited)

Description

clone Internally

License

Apache License

Declaration

@SuppressWarnings("unchecked")
    static private <E> E cloneInternally(E source, Map<Object, Object> visited) 

Method Source Code


//package com.java2s;
//License from project: Apache License 

import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.MonthDay;
import java.time.OffsetDateTime;
import java.time.OffsetTime;
import java.time.Period;
import java.time.Year;
import java.time.YearMonth;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public class Main {
    /** Immutable types that are safe to copy by reference */
    final static Set<Class<?>> IMMUTABLES = new HashSet<>(Arrays.asList(Integer.class, Long.class, Double.class,
            Float.class, Byte.class, Character.class, Short.class, Boolean.class, BigDecimal.class,
            BigInteger.class, String.class, LocalDate.class, LocalTime.class, LocalDateTime.class, Instant.class,
            ZonedDateTime.class, Duration.class, MonthDay.class, OffsetDateTime.class, OffsetTime.class,
            Period.class, Year.class, YearMonth.class, ZoneOffset.class, Collections.emptyList().getClass(),
            Collections.emptySet().getClass(), Collections.emptyMap().getClass()));
    final static Set<String> SKIPPED_PROPS = new HashSet<>(Arrays.asList("class"));
    /** Static cache where property descriptors are kept for classes */
    final static Map<Class<?>, PropertyDescriptor[]> PDS_CACHE = new ConcurrentHashMap<>();
    static final List<Method> PROXY_TESTERS = new ArrayList<>();
    static Class<?> SPRING_PROXY = null;
    static final Set<Class<?>> NOT_PROXY = Collections.newSetFromMap(new ConcurrentHashMap<>());

    @SuppressWarnings("unchecked")
    static private <E> E cloneInternally(E source, Map<Object, Object> visited) {
        if (source == null) {
            return null;
        }/*from   w  w  w  .  ja v a 2s.co  m*/
        Class<?> clazz = source.getClass();
        if (clazz.isEnum() || IMMUTABLES.contains(clazz)) {
            return source;
        }
        if (clazz == Date.class) {
            return (E) ((Date) source).clone();
        }
        if (visited.containsKey(source)) {
            return (E) visited.get(source);
        }
        if (clazz.isArray()) {
            final int size = Array.getLength(source);
            Object copy = Array.newInstance(clazz.getComponentType(), size);
            visited.put(source, copy);
            for (int i = 0; i < size; i++) {
                Object o = cloneInternally(Array.get(source, i), visited);
                Array.set(copy, i, o);
            }
            return (E) copy;
        }
        try {
            Object copy = tryInstantiate(clazz);
            clazz = copy.getClass();
            visited.put(source, copy);
            if (Collection.class.isAssignableFrom(clazz)) {
                Collection<Object> c = (Collection<Object>) copy;
                ((Collection<?>) source).forEach(e -> c.add(cloneInternally(e, visited)));
            } else if (Map.class.isAssignableFrom(clazz)) {
                Map<Object, Object> m = (Map<Object, Object>) copy;
                ((Map<?, ?>) source)
                        .forEach((k, v) -> m.put(cloneInternally(k, visited), cloneInternally(v, visited)));
            } else {
                PropertyDescriptor[] pds = PDS_CACHE.get(clazz);
                if (pds == null) {
                    pds = Introspector.getBeanInfo(clazz).getPropertyDescriptors();
                    PDS_CACHE.put(clazz, pds);
                }
                for (PropertyDescriptor d : pds) {
                    try {
                        if (SKIPPED_PROPS.contains(d.getName())) {
                            continue;
                        }
                        Object c;
                        Object o = d.getReadMethod().invoke(source);
                        if (o == null || (c = cloneInternally(o, visited)) == null) {
                            continue;
                        }
                        if (d.getWriteMethod() != null) {
                            d.getWriteMethod().invoke(copy, c);
                        } else if (Collection.class.isAssignableFrom(d.getPropertyType())) {
                            Collection<Object> coll = (Collection<Object>) d.getReadMethod().invoke(copy);
                            coll.addAll((Collection<?>) c);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            return (E) copy;
        } catch (ReflectiveOperationException | IntrospectionException e) {
            e.printStackTrace();
            return null;
        }
    }

    static Object tryInstantiate(final Class<?> clazz) throws InstantiationException {
        Class<?> cl = clazz;
        while (cl != Object.class) {
            if (!isProxy(cl)) {
                try {
                    return cl.newInstance();
                } catch (ReflectiveOperationException goNext) {
                }
            }
            cl = cl.getSuperclass();
        }
        if (Set.class.isAssignableFrom(clazz)) {
            return new HashSet<>();
        } else if (Map.class.isAssignableFrom(clazz)) {
            return new HashMap<>();
        } else if (Collection.class.isAssignableFrom(clazz)) {
            return new ArrayList<>();
        }
        throw new InstantiationException(String.format(
                "Cannot find no-arg constructor in class %s or any its superclasses", clazz.getCanonicalName()));
    }

    static boolean isProxy(Class<?> clazz) {
        if (NOT_PROXY.contains(clazz)) {
            return false;
        }
        for (Method m : PROXY_TESTERS) {
            try {
                if ((boolean) m.invoke(null, clazz)) {
                    return true;
                }
            } catch (Exception e) {
            }
        }
        if (SPRING_PROXY != null && SPRING_PROXY.isAssignableFrom(clazz)) {
            return true;
        }
        NOT_PROXY.add(clazz);
        return false;
    }
}

Related

  1. asDate(Calendar calendar)
  2. compareChrono(TemporalAccessor date1, TemporalAccessor date2)
  3. compareOffsetDateTimes(OffsetDateTime offsetDateTime1, OffsetDateTime offsetDateTime2)
  4. convertDateToOffsetDateTime(Date date)
  5. getCurrentISODate()