package de.axone.tools;
import java.io.IOError;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Map;
public class F {
public static String ormat( Object o ){
StringBuilder r = new StringBuilder();
ormatB( r, o );
return r.toString();
}
public static void ormatB( Appendable r, Object o ){
try {
_ormatB( r, o );
} catch( IOException e ){
throw new IOError( e );
}
}
public static void _ormatB( Appendable r, Object o ) throws IOException {
if( o == null ) r.append( S._NULL_ );
else {
// TODO: Explicit vorhandenes toString checken
if( o instanceof String ) formatString( r, (String)o );
else if( o instanceof Path ) formatPath( r, (Path)o );
else if( o instanceof Iterable<?> ) formatIterable( r, (Iterable<?>)o );
else if( o instanceof Map<?,?> ) formatMap( r, (Map<?,?>) o );
else if( o instanceof Enumeration<?> ) formatEnumeration( r, (Enumeration<?>) o );
else if( o.getClass().isArray() ) formatArray( r, o );
else r.append( String.valueOf( o ) );
}
}
private static void formatIterable( Appendable r, Iterable<?> l ) throws IOException{
r.append( "(" );
boolean first = true;
for( Object o : l ){
if( first ) first = false;
else r.append( ", " );
formatItem( r, o );
}
r.append( ")" );
}
private static void formatEnumeration( Appendable r, Enumeration<?> l ) throws IOException{
r.append( "(" );
boolean first = true;
while( l.hasMoreElements() ){
Object o = l.nextElement();
if( first ) first = false;
else r.append( ", " );
formatItem( r, o );
}
r.append( ")" );
}
private static void formatMap( Appendable r, Map<?,?> m ) throws IOException {
r.append( "{" );
boolean first = true;
for( Map.Entry<?,?> entry : m.entrySet() ){
Object key = entry.getKey();
if( first ) first = false;
else r.append( ", " );
formatItem( r, key );
r.append( "=>" );
formatItem( r, entry.getValue() );
}
r.append( "}" );
}
private static void formatArray( Appendable r, Object a ) throws IOException{
Class<?> component = a.getClass().getComponentType();
r.append( "[" );
boolean first = true;
if( component == boolean.class ){
for( boolean o : (boolean[])a ){
_formatArrayItem( r, first, o );
first = false;
}
} else if( component == byte.class ){
for( byte o : (byte[])a ){
_formatArrayItem( r, first, o );
first = false;
}
} else if( component == char.class ){
for( char o : (char[])a ){
_formatArrayItem( r, first, o );
first = false;
}
} else if( component == short.class ){
for( short o : (byte[])a ){
_formatArrayItem( r, first, o );
first = false;
}
} else if( component == int.class ){
for( int o : (int[])a ){
_formatArrayItem( r, first, o );
first = false;
}
} else if( component == long.class ){
for( long o : (long[])a ){
_formatArrayItem( r, first, o );
first = false;
}
} else if( component == float.class ){
for( float o : (float[])a ){
_formatArrayItem( r, first, o );
first = false;
}
} else if( component == double.class ){
for( double o : (double[])a ){
_formatArrayItem( r, first, o );
first = false;
}
} else {
// This handles arrays of arrays, too
for( Object o : (Object[])a ){
_formatArrayItem( r, first, o );
first = false;
}
}
r.append( "]" );
}
private static void _formatArrayItem( Appendable r, boolean first, Object o ) throws IOException {
if( ! first ) r.append( ", " );
formatItem( r, o );
}
private static void formatString( Appendable r, String s ) throws IOException {
r.append( s );
}
// We need this because Path is recursive and Iterable
// TODO: General recusion handling ...
private static void formatPath( Appendable r, Path p ) throws IOException {
r.append( p.toFile().getAbsolutePath() );
}
private static void formatItem( Appendable r, Object o ) throws IOException {
boolean isSpecial =
o == null ||
o instanceof Collection<?> ||
o instanceof Map<?,?> ||
o.getClass().isArray()
;
if( !isSpecial ) r.append( '\'' );
ormatB( r, o );
if( !isSpecial ) r.append( '\'' );
}
}