/** * Makes a deep copy of a value, optionally thread-safe. * * @param threadSafe if {@code true}, then thread-safe datastructures are used */ public static Serializable deepCopy(Object value, boolean threadSafe) { if (value == null) { return (Serializable) value; } else if (value instanceof State) { return deepCopy((State) value, threadSafe); } else if (value instanceof List) { @SuppressWarnings("unchecked") List<Serializable> list = (List<Serializable>) value; return (Serializable) deepCopy(list, threadSafe); } else if (value instanceof Object[]) { // array values are supposed to be scalars return ((Object[]) value).clone(); } // else scalar value -- check anyway (debug) else if (!isScalar(value)) { throw new UnsupportedOperationException("Cannot deep copy: " + value.getClass().getName()); } return (Serializable) value; }
/** * Compares two values. */ public static boolean equalsStrict(Object a, Object b) { if (a == b) { return true; } else if (a == null || b == null) { return false; } else if (a instanceof State && b instanceof State) { return equalsStrict((State) a, (State) b); } else if (a instanceof List && b instanceof List) { @SuppressWarnings("unchecked") List<Serializable> la = (List<Serializable>) a; @SuppressWarnings("unchecked") List<Serializable> lb = (List<Serializable>) b; return equalsStrict(la, lb); } else if (a instanceof Object[] && b instanceof Object[]) { return equalsStrict((Object[]) a, (Object[]) b); } else if (a instanceof ListDiff && b instanceof ListDiff) { ListDiff lda = (ListDiff) a; ListDiff ldb = (ListDiff) b; return lda.isArray == ldb.isArray && equalsStrict(lda.diff, ldb.diff) && equalsStrict(lda.rpush, ldb.rpush); } else if (isScalar(a) && isScalar(b)) { return a.equals(b); } else { return false; } }