package io.gitlab.jfronny.inceptum.util; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.util.*; public class DeepCloner { public static T clone(T source) { try { return (T) cloneI(source); } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException e) { throw new RuntimeException("Could not clone object", e); } } private static Object cloneI(Object source) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { if (source == null) return null; if (source instanceof String || source instanceof Integer || source instanceof Byte || source instanceof Short || source instanceof Double || source instanceof Float) return source; if (source instanceof List list) return List.copyOf(list); if (source instanceof Map map) return Map.copyOf(map); if (source instanceof Set set) return new LinkedHashSet<>(set); if (source instanceof Date date) return new Date(date.getTime()); Class klazz = source.getClass(); if (!klazz.getName().startsWith("io.gitlab.jfronny.inceptum.model")) throw new IllegalStateException("Default java classes must have special impls! (" + klazz.getName() + ")"); Object instance = klazz.getConstructor().newInstance(); for (Field field : klazz.getFields()) field.set(instance, cloneI(field.get(source))); return instance; } }