package fr.lteconsulting.hexa.databinding.watchablecollection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import fr.lteconsulting.hexa.client.tools.Action1;
/**
* A Watchable List. Notifications are grouped and are deferred through
* Scheduler.scheduleDeferred() method.
*
* @author Arnaud
*
* @param <T> Data type
*/
public class WatchableCollection<T> implements List<T>
{
private final List<T> list;
private List<Change> scheduledChanges = new ArrayList<>();
private List<Action1<List<Change>>> callbacks = new ArrayList<>();
public WatchableCollection()
{
this( new ArrayList<T>() );
}
public WatchableCollection( List<T> list )
{
this.list = list;
}
public void addCallback( Action1<List<Change>> callback )
{
callbacks.add( callback );
}
public void addCallbackAndSendAll( Action1<List<Change>> callback )
{
callbacks.add( callback );
callback.exec( Change.ForItems( ChangeType.ADD, list, 0 ) );
}
public void removeCallback( Action1<List<Change>> callback )
{
callbacks.remove( callback );
}
private void scheduleChange( Change change )
{
scheduledChanges.add( change );
for( Action1<List<Change>> callback : callbacks )
callback.exec( scheduledChanges );
scheduledChanges.clear();
}
private void scheduleChanges( Collection<Change> changes )
{
scheduledChanges.addAll( changes );
for( Action1<List<Change>> callback : callbacks )
callback.exec( scheduledChanges );
scheduledChanges.clear();
}
public void add( int arg0, T arg1 )
{
list.add( arg0, arg1 );
scheduleChange( new Change( ChangeType.ADD, arg1, arg0 ) );
}
public boolean add( T arg0 )
{
boolean res = list.add( arg0 );
scheduleChange( new Change( ChangeType.ADD, arg0, list.size() - 1 ) );
return res;
}
public boolean addAll( Collection<? extends T> arg0 )
{
int startIndex = list.size();
boolean res = list.addAll( arg0 );
scheduleChanges( Change.ForItems( ChangeType.ADD, arg0, startIndex ) );
return res;
}
public boolean addAll( int arg0, Collection<? extends T> arg1 )
{
boolean res = list.addAll( arg0, arg1 );
scheduleChanges( Change.ForItems( ChangeType.ADD, arg1, arg0 ) );
return res;
}
public void clear()
{
Collection<Change> changes = Change.ForItems( ChangeType.REMOVE, list, 0 );
list.clear();
scheduleChanges( changes );
}
public boolean contains( Object arg0 )
{
return list.contains( arg0 );
}
public boolean containsAll( Collection<?> arg0 )
{
return list.containsAll( arg0 );
}
public boolean equals( Object arg0 )
{
return list.equals( arg0 );
}
public T get( int arg0 )
{
return list.get( arg0 );
}
public int hashCode()
{
return list.hashCode();
}
public int indexOf( Object arg0 )
{
return list.indexOf( arg0 );
}
public boolean isEmpty()
{
return list.isEmpty();
}
public Iterator<T> iterator()
{
return list.iterator();
}
public int lastIndexOf( Object arg0 )
{
return list.lastIndexOf( arg0 );
}
public ListIterator<T> listIterator()
{
return list.listIterator();
}
public ListIterator<T> listIterator( int arg0 )
{
return list.listIterator( arg0 );
}
public T remove( int arg0 )
{
T res = list.remove( arg0 );
scheduleChange( new Change( ChangeType.REMOVE, res, arg0 ) );
return res;
}
public boolean remove( Object arg0 )
{
int index = list.indexOf( arg0 );
boolean res = list.remove( arg0 );
scheduleChange( new Change( ChangeType.REMOVE, arg0, index ) );
return res;
}
public boolean removeAll( Collection<?> arg0 )
{
assert false : "This implementation is bugged !";
boolean res = list.removeAll( arg0 );
scheduleChanges( Change.ForItems( ChangeType.REMOVE, arg0, 0 ) );
return res;
}
public boolean retainAll( Collection<?> c )
{
throw new RuntimeException();
}
public T set( int index, T element )
{
if( list.size() > index )
scheduleChange( new Change( ChangeType.REMOVE, list.get( index ), index ) );
scheduleChange( new Change( ChangeType.ADD, element, index ) );
return list.set( index, element );
}
public int size()
{
return list.size();
}
public List<T> subList( int fromIndex, int toIndex )
{
return list.subList( fromIndex, toIndex );
}
public Object[] toArray()
{
return list.toArray();
}
@SuppressWarnings( "hiding" )
public <T> T[] toArray( T[] a )
{
return list.toArray( a );
}
}