org.jhotdraw8.icollection.facade.MutableListFacade Maven / Gradle / Ivy
/*
* @(#)MutableListFacade.java
* Copyright © 2023 The authors and contributors of JHotDraw. MIT License.
*/
package org.jhotdraw8.icollection.facade;
import org.jhotdraw8.icollection.immutable.ImmutableList;
import org.jhotdraw8.icollection.impl.iteration.FailFastIterator;
import org.jhotdraw8.icollection.impl.iteration.FailFastSpliterator;
import org.jhotdraw8.icollection.impl.iteration.MutableListIterator;
import org.jhotdraw8.icollection.readonly.ReadOnlyList;
import org.jhotdraw8.icollection.readonly.ReadOnlySequencedCollection;
import org.jhotdraw8.icollection.sequenced.ReversedListView;
import org.jspecify.annotations.Nullable;
import java.util.AbstractList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Objects;
import java.util.Spliterator;
import java.util.stream.Stream;
/**
* Provides a {@link List} facade to a set of {@code ImmutableList} functions.
*
* @param the element type
* @author Werner Randelshofer
*/
public class MutableListFacade extends AbstractList implements ReadOnlyList, List {
private ImmutableList backingList;
private int modCount;
public MutableListFacade(ImmutableList backingList) {
this.backingList = backingList;
}
@Override
public void addFirst(E e) {
backingList = backingList.add(0, e);
modCount++;
}
@Override
public void addLast(E e) {
backingList = backingList.add(e);
modCount++;
}
@Override
public List reversed() {
return new ReversedListView<>(this, this::getModCount);
}
private int getModCount() {
return modCount;
}
@Override
public ReadOnlySequencedCollection readOnlyReversed() {
return new ReadOnlyListFacade<>(
() -> backingList.size(),
index -> get(backingList.size() - 1 - index),
() -> this);
}
@SuppressWarnings("unchecked")
@Override
public boolean remove(Object o) {
ImmutableList oldList = backingList;
backingList = backingList.remove((E) o);
modCount++;
return oldList != backingList;
}
@Override
public E remove(int index) {
E removed = backingList.get(index);
backingList = backingList.removeAt(index);
modCount++;
return removed;
}
@Override
public void clear() {
ImmutableList oldList = backingList;
backingList = backingList.empty();
if (oldList != backingList) {
modCount++;
}
}
@Override
public Spliterator spliterator() {
return new FailFastSpliterator<>(backingList.spliterator(), () -> this.modCount, null);
}
@Override
public ReadOnlyList readOnlySubList(int fromIndex, int toIndex) {
int length = size();
Objects.checkFromToIndex(fromIndex, toIndex, length);
return new ReadOnlyListFacade<>(
() -> toIndex - fromIndex,
i -> get(i - fromIndex));
}
@Override
public Stream stream() {
return backingList.stream();
}
@Override
public Iterator iterator() {
Iterator it = new MyIterator<>(backingList.iterator());
return new FailFastIterator<>(it, () -> this.modCount);
}
public Iterator reverseIterator() {
Iterator it = new MyIterator<>(backingList.readOnlyReversed().iterator());
return new FailFastIterator<>(it, () -> this.modCount);
}
@Override
public int size() {
return backingList.size();
}
@Override
public boolean contains(Object o) {
return backingList.contains(o);
}
class MyIterator implements Iterator {
final Iterator b;
@Nullable EE current;
boolean canRemove;
MyIterator(Iterator b) {
this.b = b;
}
@Override
public boolean hasNext() {
return b.hasNext();
}
@Override
public EE next() {
current = b.next();
canRemove = true;
return current;
}
@Override
public void remove() {
if (canRemove) {
MutableListFacade.this.remove(current);
canRemove = false;
} else {
throw new IllegalStateException();
}
}
}
@Override
public boolean add(E e) {
ImmutableList oldList = backingList;
backingList = backingList.add(e);
if (oldList != backingList) {
modCount++;
return true;
}
return false;
}
@Override
public void add(int index, E e) {
backingList = backingList.add(index, e);
modCount++;
}
@Override
public E set(int index, E e) {
E oldValue = backingList.get(index);
backingList = backingList.set(index, e);
return oldValue;
}
@Override
public E get(int index) {
return backingList.get(index);
}
@Override
public E getFirst() {
return ReadOnlyList.super.getFirst();
}
@Override
public E getLast() {
return ReadOnlyList.super.getLast();
}
@Override
public ListIterator listIterator(int index) {
return new MutableListIterator<>(this, index, this::getModCount);
}
}