package jane.core; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import jane.core.SContext.Safe; /** * List类型的安全修改类 */ public final class SList<V, S> implements List<S>, Cloneable { private final Safe<?> _owner; private final List<V> _list; private SContext _sctx; public SList(Safe<?> owner, List<V> list) { _owner = owner; _list = list; } private SContext sContext() { _owner.checkLock(); if(_sctx != null) return _sctx; _owner.dirty(); return _sctx = SContext.current(); } @SuppressWarnings("unchecked") private S safe(V v) { return (S)(v instanceof Bean ? ((Bean<?>)v).safe(_owner) : v); } @SuppressWarnings("unchecked") private S safeAlone(V v) { return (S)(v instanceof Bean ? ((Bean<?>)v).safe(null) : v); } @SuppressWarnings({ "unchecked", "deprecation" }) private V unsafe(Object v) { return (V)(v instanceof Safe ? ((Safe<?>)v).unsafe() : v); } @Override public int size() { return _list.size(); } @Override public boolean isEmpty() { return _list.isEmpty(); } @Override public boolean contains(Object o) { return _list.contains(unsafe(o)); } @Override public boolean containsAll(Collection<?> c) { return _list.containsAll(c); } @Override public int indexOf(Object o) { return _list.indexOf(unsafe(o)); } @Override public int lastIndexOf(Object o) { return _list.lastIndexOf(unsafe(o)); } @Deprecated @Override public Object[] toArray() { return _list.toArray(); } @Deprecated @Override public <T> T[] toArray(T[] a) { return _list.toArray(a); } @Override public S get(int idx) { return safe(_list.get(idx)); } /** * NOTE: do NOT modify v after called */ public boolean addDirect(V v) { SContext ctx = sContext(); if(!_list.add(v)) return false; ctx.addOnRollback(new Runnable() { @Override public void run() { _list.remove(_list.size() - 1); } }); return true; } @Override public boolean add(S s) { return addDirect(unsafe(s)); } public void addDirect(final int idx, V v) { SContext ctx = sContext(); _list.add(idx, v); ctx.addOnRollback(new Runnable() { @Override public void run() { _list.remove(idx); } }); } @Override public void add(int idx, S s) { addDirect(idx, unsafe(s)); } public boolean addAllDirect(Collection<? extends V> c) { SContext ctx = sContext(); final int n = c.size(); if(!_list.addAll(c)) return false; ctx.addOnRollback(new Runnable() { @Override public void run() { for(int i = _list.size() - 1; i >= n; --i) _list.remove(i); } }); return true; } @Override public boolean addAll(Collection<? extends S> c) { SContext ctx = sContext(); final int n = c.size(); for(S s : c) _list.add(unsafe(s)); ctx.addOnRollback(new Runnable() { @Override public void run() { for(int i = _list.size() - 1; i >= n; --i) _list.remove(i); } }); return true; } public boolean addAllDirect(final int idx, Collection<? extends V> c) { SContext ctx = sContext(); final int n = c.size(); if(!_list.addAll(idx, c)) return false; ctx.addOnRollback(new Runnable() { @Override public void run() { for(int i = idx + n - 1, e = i - n; i > e; --i) _list.remove(i); } }); return true; } @Override public boolean addAll(int idx, Collection<? extends S> c) { List<V> list = new ArrayList<>(c.size()); for(S s : c) list.add(unsafe(s)); return addAllDirect(idx, list); } public V setDirect(final int idx, V v) { SContext ctx = sContext(); final V vOld = _list.set(idx, v); ctx.addOnRollback(new Runnable() { @Override public void run() { _list.set(idx, vOld); } }); return vOld; } @Override public S set(int idx, S s) { return safeAlone(setDirect(idx, unsafe(s))); } public V removeDirect(final int idx) { SContext ctx = sContext(); final V vOld = _list.remove(idx); ctx.addOnRollback(new Runnable() { @Override public void run() { _list.add(idx, vOld); } }); return vOld; } @Override public S remove(int idx) { return safeAlone(removeDirect(idx)); } @Override public boolean remove(Object o) { int idx = indexOf(o); if(idx < 0) return false; remove(idx); return true; } @Override public boolean removeAll(Collection<?> c) { boolean r = false; for(SIterator it = iterator(); it.hasNext();) { if(c.contains(it.nextUnsafe())) { it.remove(); r = true; } } return r; } @Override public boolean retainAll(Collection<?> c) { boolean r = false; for(SIterator it = iterator(); it.hasNext();) { if(!c.contains(it.nextUnsafe())) { it.remove(); r = true; } } return r; } @SuppressWarnings("unchecked") @Override public void clear() { SContext ctx = sContext(); if(_list.isEmpty()) return; ctx.addOnRollback(new Runnable() { private final List<V> _saved; { try { _saved = _list.getClass().newInstance(); _saved.addAll(_list); } catch(Exception e) { throw new Error(e); } } @Override public void run() { _list.clear(); _list.addAll(_saved); _saved.clear(); } }); _list.clear(); } public final class SIterator implements Iterator<S> { private final Iterator<V> _it = _list.iterator(); private V _cur; private int _idx = -1; private SIterator() { } @Override public boolean hasNext() { return _it.hasNext(); } @Deprecated public V nextUnsafe() { _cur = _it.next(); ++_idx; return _cur; } @Override public S next() { return safe(nextUnsafe()); } @Override public void remove() { SContext ctx = sContext(); _it.remove(); ctx.addOnRollback(new Runnable() { private final V _v = _cur; private final int _i = _idx; @Override public void run() { _list.add(_i, _v); } }); --_idx; } } public final class SListIterator implements ListIterator<S> { private final ListIterator<V> _it; private V _cur; private int _idx; private int _idxOff; private SListIterator(int idx) { _it = _list.listIterator(idx); _idx = idx - 1; } @Override public boolean hasNext() { return _it.hasNext(); } @Override public boolean hasPrevious() { return _it.hasPrevious(); } @Override public int nextIndex() { return _it.nextIndex(); } @Override public int previousIndex() { return _it.previousIndex(); } @Deprecated public V nextUnsafe() { _cur = _it.next(); ++_idx; _idxOff = 0; return _cur; } @Override public S next() { return safe(nextUnsafe()); } @Deprecated public V previousUnsafe() { _cur = _it.previous(); --_idx; _idxOff = 1; return _cur; } @Override public S previous() { return safe(previousUnsafe()); } @Override public void remove() { SContext ctx = sContext(); _it.remove(); ctx.addOnRollback(new Runnable() { private final V _v = _cur; private final int _i = _idx + _idxOff; @Override public void run() { _list.add(_i, _v); } }); _idx -= 1 - _idxOff; } public void setDirect(V v) { SContext ctx = sContext(); _it.set(v); ctx.addOnRollback(new Runnable() { private final V _v = _cur; private final int _i = _idx + _idxOff; @Override public void run() { _list.set(_i, _v); } }); } @Override public void set(S s) { setDirect(unsafe(s)); } public void addDirect(V v) { SContext ctx = sContext(); _it.add(v); ctx.addOnRollback(new Runnable() { private final int _i = _idx + _idxOff; @Override public void run() { _list.remove(_i); } }); } @Override public void add(S s) { addDirect(unsafe(s)); } } @Override public SIterator iterator() { return new SIterator(); } @Override public SListIterator listIterator() { return new SListIterator(0); } @Override public SListIterator listIterator(int idx) { return new SListIterator(idx); } @Override public SList<V, S> subList(int idxFrom, int idxTo) { return new SList<>(_owner, _list.subList(idxFrom, idxTo)); } public SList<V, S> append(List<V> list) { Util.appendDeep(list, _list); return this; } public SList<V, S> assign(List<V> list) { clear(); Util.appendDeep(list, _list); return this; } public void appendTo(List<V> list) { Util.appendDeep(_list, list); } public void cloneTo(List<V> list) { list.clear(); Util.appendDeep(_list, list); } @SuppressWarnings("unchecked") @Override public List<V> clone() { try { return (List<V>)Util.appendDeep(_list, _list.getClass().newInstance()); } catch(Exception e) { throw new Error(e); } } @Override public int hashCode() { return _list.hashCode(); } @Override public boolean equals(Object o) { return this == o || _list.equals(o); } @Override public String toString() { return _list.toString(); } }