package org.andork.util; import java.util.IdentityHashMap; import java.util.function.Function; /** * A general-purpose replacement to the cruftastic {@link Cloneable} design. * * @author James */ public interface PowerCloneable { /** * Various hierarchical cloning functions. * * @author James */ public static class Cloners { /** * Clones an array of Objects. * * @param toClone * the array to clone. * @param subcloner * the subcloner used to clone each element of the array. * @return a new array of the same length as {@code toClone} where each * element was the result of applying {@code subcloner} to the * corresponding element in {@code toClone}. */ public static Object[] cloneArray(Object[] toClone, Function<Object, Object> subcloner) { Object[] result = new Object[toClone.length]; for (int i = 0; i < toClone.length; i++) { result[i] = subcloner.apply(toClone[i]); } return result; } /** * The default subcloner implementation. * * @param toClone * the object to clone. * @return if {@code toClone} is a {@link PowerCloneable}, returns * {@code toClone.clone( Cloners::defaultClone )}. Otherwise, * returns {@code toClone}. */ public static Object defaultClone(Object toClone) { if (toClone instanceof PowerCloneable) { return ((PowerCloneable) toClone).clone(Cloners::defaultClone); } return toClone; } } /** * Clones this object. The returned object should not be {@code ==} to this * object, but should {@code #equals(this)} . * * @param subcloner * a function that clones fields or other "elements" of this * object. Being able to choose the function allows you to * perform different styles of cloning, like deep or shallow * copying, or even a graph structure-preserving clone using an * {@link IdentityHashMap}. * @return A clone of this object. */ public PowerCloneable clone(Function<Object, Object> subcloner); }