package fr.lteconsulting.hexa.client.ui.miracle;
import java.util.HashMap;
public abstract class TreeCollectionOf<T> implements TreeRefMng<T>
{
abstract protected int getObjectId( T object );
abstract protected int getParentObjectId( T object );
abstract protected void updated( T object );
abstract protected void deleted( int ref, T object );
abstract protected void refreshed( Iterable<T> objects );
class ObjInfo
{
T obj;
T parent;
T prev;
T next;
}
HashMap<Integer, ObjInfo> objects = new HashMap<Integer, ObjInfo>();
ObjInfo firstItem = null;
HashMap<Integer, ObjInfo> firstChilds = new HashMap<Integer, ObjInfo>();
public int getRef( T object )
{
return getObjectId( object );
}
@Override
public T getObject( int ref )
{
ObjInfo info = objects.get( ref );
if( info == null )
return null;
return info.obj;
}
@Override
public T getParentObject( T object )
{
ObjInfo info = objects.get( getRef( object ) );
if( info == null )
return null;
return info.parent;
}
public void clear()
{
firstItem = null;
objects.clear();
firstChilds.clear();
}
final public void refresh( Iterable<T> list )
{
clear();
if( list != null )
{
for( T t : list )
updateRecordInternal( t );
}
refreshed( list );
}
final public void updateRecord( T b )
{
updateRecordInternal( b );
updated( b );
}
private void updateRecordInternal( T b )
{
// until we have the info on the parent, we cannot really add the item
T parent = null;
int parentBookingId = getParentObjectId( b );
if( parentBookingId > 0 )
{
ObjInfo parentInfo = objects.get( parentBookingId );
assert (parentInfo != null) : "Cannot add a child if the parent has not been inserted first";
parent = parentInfo.obj;
}
// do we have already an info on b ?
ObjInfo info = objects.get( getRef( b ) );
if( info == null )
{
// that's a new object here
info = new ObjInfo();
info.obj = b;
info.parent = parent;
// are we the first child of the parent ?
ObjInfo firstChild = null;
if( parent == null )
firstChild = firstItem;
else
firstChild = firstChilds.get( getRef( parent ) );
if( firstChild == null )
{
// yes we are
if( parent == null )
firstItem = info;
else
firstChilds.put( getRef( parent ), info );
}
else
{
// no we are not
info.prev = firstChild.obj;
info.next = firstChild.next;
firstChild.next = info.obj;
if( info.next != null )
objects.get( getRef( info.next ) ).prev = info.obj;
}
objects.put( getRef( b ), info );
}
else
{
info.obj = b;
}
}
final public void removeRecord( int ref )
{
ObjInfo info = objects.get( ref );
if( info == null )
return; // nothing to be deleted
// recursively remove children
ObjInfo child = firstChilds.remove( ref );
while( child != null )
{
int childRef = getRef( child.obj );
child = objects.get( child.next );
removeRecord( childRef );
}
// remove the item reference from its parent
if( info.parent == null )
{
// parent is the root
if( info == firstItem )
{
// we are the first of the first !!!
if( firstItem.next == null )
firstItem = null;
else
{
firstItem = objects.get( getRef( firstItem.next ) );
firstItem.prev = null;
}
}
else
{
// remove us from the chained list
ObjInfo prev = null;
ObjInfo next = null;
if( info.prev != null )
prev = objects.get( getRef( info.prev ) );
if( info.next != null )
next = objects.get( getRef( info.next ) );
if( prev != null )
prev.next = info.next;
if( next != null )
next.prev = info.prev;
}
}
else
{
int parentRef = getRef( info.parent );
if( info == firstChilds.get( parentRef ) )
{
ObjInfo next = null;
if( info.next != null )
next = objects.get( getRef( info.next ) );
if( next == null )
firstChilds.remove( parentRef );
else
{
firstChilds.put( parentRef, next );
next.prev = null;
}
}
else
{
// remove us from the chained list
ObjInfo prev = null;
ObjInfo next = null;
if( info.prev != null )
prev = objects.get( getRef( info.prev ) );
if( info.next != null )
next = objects.get( getRef( info.next ) );
if( prev != null )
prev.next = info.next;
if( next != null )
next.prev = info.prev;
}
}
// effectively remove from maps
objects.remove( ref );
// signal the table to remove the corresponding row
deleted( ref, info.obj );
}
}