/*
* Bibliothek - DockingFrames
* Library built on Java/Swing, allows the user to "drag and drop"
* panels containing any Swing-Component the developer likes to add.
*
* Copyright (C) 2010 Benjamin Sigg
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Benjamin Sigg
* benjamin_sigg@gmx.ch
* CH - Switzerland
*/
package bibliothek.test;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import bibliothek.test.inspect.NullInspectable;
import bibliothek.test.inspect.ObjectInspectable;
/**
* A graph built by the contents of an {@link Inspect}.
* @author Benjamin Sigg
*/
public class InspectionGraph {
private int id = 0;
private Map<Class<?>, Adapter<?, Inspectable>> inspectableAdapters = new HashMap<Class<?>, Adapter<?, Inspectable>>();
private Map<Class<?>, Adapter<?, String>> stringAdapters = new HashMap<Class<?>, Adapter<?,String>>();
private Map<Object, Inspectable> inspectables = new IdentityHashMap<Object, Inspectable>();
private Map<Inspectable, Inspect> inspects = new IdentityHashMap<Inspectable, Inspect>();
private Map<Inspect, InspectionNode> nodes = new IdentityHashMap<Inspect, InspectionNode>();
public InspectionGraph(){
putInspectableAdapter( Inspectable.class, new Adapter<Inspectable, Inspectable>() {
public Inspectable adapt( Inspectable value ){
return value;
}
});
putInspectableAdapter( Object.class, ObjectInspectable.class );
putStringAdapter( Object.class, new Adapter<Object, String>() {
public String adapt( Object value ){
return String.valueOf( value );
}
});
}
public void updateAll(){
InspectionNode[] update = nodes.values().toArray( new InspectionNode[ nodes.size() ] );
for( InspectionNode node : update ){
node.update();
}
}
public void retainAll( Set<InspectionNode> usedNodes ){
Iterator<InspectionNode> nodeIterator = nodes.values().iterator();
while( nodeIterator.hasNext() ){
if( !usedNodes.contains( nodeIterator.next() )){
nodeIterator.remove();
}
}
Iterator<Inspect> iterator = inspects.values().iterator();
while( iterator.hasNext() ){
if( !nodes.containsKey( iterator.next() )){
iterator.remove();
}
}
Iterator<Inspectable> inspectableIterator = inspectables.values().iterator();
while( inspectableIterator.hasNext() ){
if( !inspects.containsKey( inspectableIterator.next() )){
inspectableIterator.remove();
}
}
}
public <C> void putInspectableAdapter( Class<C> clazz, Adapter<C, Inspectable> adapter ){
inspectableAdapters.put( clazz, adapter );
}
public <C> void putInspectableAdapter( Class<C> source, Class<? extends Inspectable> destination ){
putInspectableAdapter( source, new ReflectionAdapter<C,Inspectable>( source, destination ) );
}
public <C> void putStringAdapter( Class<C> clazz, Adapter<C, String> adapter ){
stringAdapters.put( clazz, adapter );
}
private <X> X get( Class<?> clazz, Map<Class<?>, X> adapters ){
while( clazz != null ){
X adapter = adapters.get( clazz );
if( adapter != null ){
return adapter;
}
for( Class<?> interfaze : clazz.getInterfaces() ){
adapter = adapters.get( interfaze );
if( adapter != null ){
return adapter;
}
}
clazz = clazz.getSuperclass();
}
return null;
}
@SuppressWarnings("unchecked")
public Inspectable getInspectable( Object object ){
if( object == null ){
return NullInspectable.INSTANCE;
}
Inspectable result = inspectables.get( object );
if( result == null ){
Adapter<?, Inspectable> adapter = get( object.getClass(), inspectableAdapters );
result = ((Adapter<Object, Inspectable>)adapter).adapt( object );
inspectables.put( object, result );
}
return result;
}
public Inspect getInspect( Inspectable inspectable ){
Inspect inspect = inspects.get( inspectable );
if( inspect == null ){
inspect = inspectable.inspect( this );
inspects.put( inspectable, inspect );
}
return inspect;
}
public InspectionNode getNode( Inspect inspect ){
InspectionNode node = nodes.get( inspect );
if( node == null ){
node = new InspectionNode( this, inspect, id++ );
nodes.put( inspect, node );
node.update();
}
return node;
}
public InspectionNode getNode( Object value ){
return getNode( getInspect( getInspectable( value ) ) );
}
@SuppressWarnings("unchecked")
public String toString( Object object ){
if( object == null ){
return "null";
}
Adapter<?, String> adapter = get( object.getClass(), stringAdapters );
return ((Adapter<Object, String>)adapter).adapt( object );
}
}