User:Pedersen/Code Samples/Persistence

From Robowiki
Jump to navigation Jump to search

I have overhauled my persistence implementation. One addition I have made is allowing logging that does not wait until the end of the match before posting anything (through the getPrintStream( filename ) method). All methods are static.

If the dataDirectory value is not provided, all calls will return null instead of the desired content, preventing file I/O (and the potential for the CanonCaches bug). In the setup of my bot I have the following line:
if( Constraints.allowFileIO ) Persistence.setDataDirectory( this.getDataDirectory() );

The Console class manages printing of text and exceptions to System.out, which is the tank's log / debug window.

Modify to taste.


/**
 * Stores and retrieves data from the local cache.
 * Data may be targeting or movement statistics, debug information, etc.
 * 
 * @author Martin Alan Pedersen
 */
public class Persistence
{
	
	//:://////////////////////////////////////
	//::  Static Methods
	//:://////////////////////////////////////
	
	public static void setDataDirectory( File newDataDirectory )
	{
		Persistence.dataDirectory = newDataDirectory;
	}

	/**
	 * Creates a PrintStream that is compatible with RoboCode's file permissions management.
	 * 
	 * @param filename the name of the data directory file to be written to
	 *
	 * @return a print stream associated with the file
	 */
	public static PrintStream getPrintStream( String filename )
	{
		PrintStream outputStream = null;

		File dataFile = getDataFile( filename );
		if( dataFile != null )
		{
			try
			{
				outputStream = new PrintStream( new RobocodeFileOutputStream( dataFile ) );
			}
			catch( Exception ex )
			{
				Console.getInstance().log( "Exception thrown opening PrintStream [" + filename + "]." );
				Console.getInstance().log( ex );
				if( outputStream != null ) outputStream.close();
			}
		}

		return outputStream;
	}

	/**
	 * Places the contents of a file in a CharBuffer.
	 * 
	 * @param filename the name of the data directory file to be read from
	 *
	 * @return a CharBuffer containing the entire contents of the file
	 */
	public static CharBuffer getFileContents( String filename )
	{
		CharBuffer fileContents = null;
		
		File dataFile = getDataFile( filename );
		if( dataFile != null )
		{
			FileReader inputStream = null;
			try
			{
				inputStream = new FileReader( dataFile );
				CharBuffer buffer = CharBuffer.allocate( (int)dataFile.length() );
				if( inputStream.read( buffer ) == (int)dataFile.length() )
				{
					fileContents = buffer;
				}
			}
			catch( Exception ex )
			{
				Console.getInstance().log( "Exception thrown reading contents of file [" + filename + "]." );
				Console.getInstance().log( ex );
			}
			finally
			{
				try
				{
					if( inputStream != null ) inputStream.close();
				}
				catch( IOException ex )
				{
					Console.getInstance().log( "Exception thrown closing input stream [" + filename + "]." );
					Console.getInstance().log( ex );
				}
			}
		}
		
		return fileContents;
	}
	
	/**
	 * Writes a list of strings to a file.
	 * 
	 * @param list the list of strings
	 * @param filename the name of the file to write to
	 */
	public static void writeListToFile( String filename, List list )
	{
		PrintStream outputStream = getPrintStream( filename );
		if( outputStream != null )
		{
			try
			{
				Iterator iterator = list.iterator();
				while( iterator.hasNext() )
				{
					outputStream.println( encrypt( (String) iterator.next() ) );
				}
			}
			catch( Exception ex )
			{
				Console.getInstance().log( "Exception thrown writing list to file" );
				Console.getInstance().log( ex );
			}
			finally
			{
				if( outputStream != null ) outputStream.close();
			}
		}
	}

	/**
	 * Reads a file and converts each line into a list entry.
	 * 
	 * @param filename the name of the file to read.
	 * 
	 * @return the lines of the file in the form of a list
	 */
	public static List readListFromFile( String filename )
	{
		List list = new ArrayList();

		CharBuffer fileContents = getFileContents( filename );
		if( fileContents != null )
		{
			String buffer = fileContents.toString();
			int indexStart = 0;
			int indexEnd = buffer.indexOf( "\n", indexStart );
			while( indexEnd != -1 )
			{
				list.add( decrypt( buffer.substring( indexStart, indexEnd ) ) );
				indexStart = indexEnd + 1;
				indexEnd = buffer.indexOf( "\n", indexStart );
			}
		}

		return list;
	}


	/**
	 * Gets a data directory file.
	 * 
	 * @param filename the name of the data file
	 * 
	 * @return a File object associated with the data file
	 */
	private static File getDataFile( String filename )
	{
		File dataFile = null;
		
		if( dataDirectory != null )
		{
			dataFile = new File( dataDirectory, mangle( filename ) );
		}

		if( dataFile == null )
		{
			Console.getInstance().log( "Access to file [" + filename + "] is denied." );
		}

		return dataFile;
	}
	
	
	/**
	 * Converts readable data into encrypted data.
	 * 
	 * @param readable the readable data
	 * 
	 * @return encrypted data
	 */
	private static String encrypt( String readable )
	{
		String unreadable = null;
		unreadable = readable; // placeholder
		return unreadable;
	}
	
	
	/**
	 * Converts encrypted data into readable data.
	 * 
	 * @param unreadable encrypted data
	 * 
	 * @return readable data
	 */
	private static String decrypt( String unreadable )
	{
		String readable = null;
		readable = unreadable; // placeholder
		return readable;
	}
	
	
	/**
	 * Converts a string into a file-friendly one.  Intended for converting tank names.
	 * 
	 * @param original the original name
	 * 
	 * @return the converted filename
	 */
	private static String mangle( String original )
	{
		StringBuffer buffer = new StringBuffer();
		char character;
		for( int i = 0; i < original.length(); i++ )
		{
			character = original.charAt( i );
			if( ( character > 47 ) && ( character < 58 ) ) buffer.append( character );
			else if( ( character > 64 ) && ( character < 91 ) ) buffer.append( character );
			else if( ( character > 96 ) && ( character < 123 ) ) buffer.append( character );
		}
		buffer.append( ".txt" );
		return buffer.toString();
	}

	//:://////////////////////////////////////
	//::  Static Variables
	//:://////////////////////////////////////
	
	private static File dataDirectory = null;

}