/** * Makes a deep copy of a {@link State} map. */ public static State deepCopy(State state) { return deepCopy(state, false); }
@Override public void createState(State state) { String id = (String) state.get(KEY_ID); if (log.isTraceEnabled()) { log.trace("Mem: CREATE " + id + ": " + state); } if (states.containsKey(id)) { throw new NuxeoException("Already exists: " + id); } state = StateHelper.deepCopy(state, true); // thread-safe StateHelper.resetDeltas(state); states.put(id, state); }
/** * Does a diff of two values. * * @return a {@link StateDiff}, a {@link ListDiff}, {@link #NOP}, or an actual value (including {@code null}) */ public static Serializable diff(Object a, Object b) { if (equalsLoose(a, b)) { return NOP; } if (a instanceof Object[] && b instanceof Object[]) { return diff((Object[]) a, (Object[]) b); } if (a instanceof List && b instanceof List) { @SuppressWarnings("unchecked") List<Object> la = (List<Object>) a; @SuppressWarnings("unchecked") List<Object> lb = (List<Object>) b; return (Serializable) diff(la, lb); } if (a instanceof State && b instanceof State) { StateDiff diff = diff((State) a, (State) b); return diff.isEmpty() ? NOP : diff; } return (Serializable) b; }
/** * 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; } }
|| a instanceof State && b == null // || a == null && b instanceof State) { return equalsLoose((State) a, (State) b); } else if (a instanceof List && b instanceof List // || a instanceof List && b == null // @SuppressWarnings("unchecked") List<Serializable> lb = (List<Serializable>) b; return equalsLoose(la, lb); } else if (a instanceof Object[] && b instanceof Object[] // || a instanceof Object[] && b == null // || a == null && b instanceof Object[]) { return equalsLoose((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 && equalsLoose(lda.diff, ldb.diff) && equalsLoose(lda.rpush, ldb.rpush); } else if (isScalar(a) && isScalar(b)) { return a.equals(b); // NOSONAR } else {
/** * 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; }
/** * Changes the deltas stored into actual full values. * * @since 6.0 */ public static void resetDeltas(State state) { if (Boolean.parseBoolean(Framework.getProperty(DISABLED_DELTA_PROP, "false"))) { return; } for (Entry<String, Serializable> en : state.entrySet()) { Serializable value = en.getValue(); if (value instanceof State) { resetDeltas((State) value); } else if (value instanceof Delta) { state.put(en.getKey(), ((Delta) value).getFullValue()); } } }
@Override public boolean equals(Object other) { return StateHelper.equalsStrict(this, other); }
public static Serializable diff(Object[] a, Object[] b) { List<Object> la = Arrays.asList(a); List<Object> lb = Arrays.asList(b); Serializable diff = diff(la, lb); if (diff instanceof List) { return b; } ListDiff listDiff = (ListDiff) diff; listDiff.isArray = true; return listDiff; }
/** * Compares two {@link List}s. * <p> * {@code null} values are equivalent to empty lists. */ public static boolean equalsLoose(List<Serializable> a, List<Serializable> b) { if (a != null && a.isEmpty()) { a = null; } if (b != null && b.isEmpty()) { b = null; } if (a == b) { return true; } if (a == null || b == null) { return false; } if (a.size() != b.size()) { return false; } for (Iterator<Serializable> ita = a.iterator(), itb = b.iterator(); ita.hasNext();) { if (!equalsLoose(ita.next(), itb.next())) { return false; } } return true; }
/** * Compares two {@link List}s. */ public static boolean equalsStrict(List<Serializable> a, List<Serializable> b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (a.size() != b.size()) { return false; } for (Iterator<Serializable> ita = a.iterator(), itb = b.iterator(); ita.hasNext();) { if (!equalsStrict(ita.next(), itb.next())) { return false; } } return true; }
int diffs = 0; for (int i = 0; i < len; i++) { Serializable elemDiff = diff(a.get(i), b.get(i)); if (elemDiff == NOP) { nops++;
if (!equalsLoose(va, vb)) { return false; if (!equalsLoose(null, vb)) { return false;
/** * Makes a deep copy of a value. */ public static Serializable deepCopy(Object value) { return deepCopy(value, false); }
} else { Serializable elemDiff = diff(va, vb); if (elemDiff != NOP) { if (elemDiff instanceof Delta) { if (!equalsLoose(null, vb)) {
/** * Compares two {@link State}s. */ public static boolean equalsStrict(State a, State b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (a.size() != b.size()) { return false; } if (!a.keySet().equals(b.keySet())) { return false; } for (Entry<String, Serializable> en : a.entrySet()) { String key = en.getKey(); Serializable va = en.getValue(); Serializable vb = b.get(key); if (!equalsStrict(va, vb)) { return false; } } return true; }
/** * Makes a deep copy of a {@link List}. */ public static List<Serializable> deepCopy(List<Serializable> list) { return deepCopy(list, false); }
/** * Makes a deep copy of a {@link List}, optionally thread-safe. * * @param threadSafe if {@code true}, then thread-safe datastructures are used */ public static List<Serializable> deepCopy(List<Serializable> list, boolean threadSafe) { List<Serializable> copy = threadSafe ? new CopyOnWriteArrayList<Serializable>() : new ArrayList<Serializable>( list.size()); for (Serializable v : list) { copy.add(deepCopy(v, threadSafe)); } return copy; }
/** * Makes a deep copy of a {@link State} map, optionally thread-safe. * * @param threadSafe if {@code true}, then thread-safe datastructures are used */ public static State deepCopy(State state, boolean threadSafe) { State copy = new State(state.size(), threadSafe); for (Entry<String, Serializable> en : state.entrySet()) { copy.put(en.getKey(), deepCopy(en.getValue(), threadSafe)); } return copy; }