package rabbitescape.engine.config;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.SortedSet;
import rabbitescape.engine.err.RabbitEscapeException;
import rabbitescape.engine.util.FileSystem;
/**
* Don't use this directly - wrap it in a Config object.
*
* Stores and retrieves config values to/from a file.
*/
public class ConfigFile implements IConfigStorage
{
public static class UnableToLoad extends RabbitEscapeException
{
private static final long serialVersionUID = 1L;
public final String filePath;
public UnableToLoad( String filePath, Exception cause )
{
super( cause );
this.filePath = filePath;
}
}
public static class UnableToSave extends RabbitEscapeException
{
private static final long serialVersionUID = 1L;
public final String filePath;
public UnableToSave( String filePath, Exception cause )
{
super( cause );
this.filePath = filePath;
}
}
private final Map<String, String> values;
private final FileSystem fs;
private final String filePath;
public ConfigFile( FileSystem fs, String filePath )
{
this.fs = fs;
this.filePath = filePath;
this.values = new HashMap<>();
load();
}
private void load()
{
if ( fs == null || filePath == null || !fs.exists( filePath ) )
{
return;
}
Properties props = new Properties();
try
{
props.load(
new ByteArrayInputStream( fs.read( filePath ).getBytes() ) );
}
catch ( Exception e )
{
throw new UnableToLoad( filePath, e );
}
for ( String name : props.stringPropertyNames() )
{
set( name, props.getProperty( name ) );
}
}
@Override
public void set( String key, String value )
{
values.put( key, value );
}
@Override
public String get( String key )
{
return values.get( key );
}
@Override
public void save( Config config )
{
try
{
fs.mkdirs( fs.parent( filePath ) );
fs.write( filePath, saveToString( config ) );
}
catch ( IOException e )
{
throw new UnableToSave( filePath, e );
}
}
private String saveToString( Config config )
{
StringBuilder ret = new StringBuilder();
// Tree set for sorting
SortedSet<String> keys = config.keys();
boolean first = true;
for ( String key : keys )
{
if ( first )
{
first = false;
}
else
{
ret.append( "\n" );
}
ret.append( "# " );
ret.append( config.schema.getDescription( key ) );
ret.append( "\n" );
if ( ! values.containsKey( key ) )
{
ret.append( '#' );
}
ret.append( propertyLine( config, key ) );
ret.append( "\n" );
}
return ret.toString();
}
private String propertyLine( Config config, String key )
{
Properties props = new Properties();
props.setProperty( key, config.get( key ) );
StringWriter writer = new StringWriter();
try
{
props.store( writer, null );
}
catch ( IOException e )
{
// Should never happen
throw new RuntimeException( e );
}
return writer.toString().split( "\n" )[1];
}
}