package rabbitescape.engine.err; import static rabbitescape.engine.util.Util.*; import java.lang.reflect.Field; import java.util.Locale; import java.util.Map; import java.util.MissingResourceException; import java.util.ResourceBundle; import java.util.TreeMap; import rabbitescape.engine.util.NamedFieldFormatter; public class ExceptionTranslation { private static final String prefix = "rabbitescape.engine."; public static String translate( RabbitEscapeException exception, Locale locale ) { String name = exception.getClass().getCanonicalName(); if ( !name.startsWith( prefix ) ) { return name + " " + extractFields( exception ).toString(); } String key = stripPrefix( name ); ResourceBundle bundle = ResourceBundle.getBundle( "rabbitescape.engine.err.exceptions", locale ); try { return substituteFields( bundle.getString( key ), exception ); } catch( MissingResourceException e ) { return key + " " + extractFields( exception ).toString(); } } private static String substituteFields( String format, RabbitEscapeException exception ) { return NamedFieldFormatter.format( format, extractFields( exception ) ); } private static Map<String, Object> extractFields( RabbitEscapeException exception ) { // TreeMap for predictable ordering Map<String, Object> ret = new TreeMap<>(); for ( Field field : exception.getClass().getFields() ) { ret.put( field.getName(), fieldValue( field, exception ) ); } return ret; } private static Object fieldValue( Field field, RabbitEscapeException exception ) { try { return field.get( exception ); } catch ( IllegalArgumentException e ) { // Should never happen e.printStackTrace(); return "<<ERROR FINDING VALUE>>"; } catch ( IllegalAccessException e ) { // Will happen if the field is private e.printStackTrace(); return "<<ERROR FINDING VALUE - NOT PUBLIC IN EXCEPTION>>"; } } private static String stripPrefix( String name ) { reAssert( name.startsWith( prefix ) ); return name.substring( prefix.length() ); } }