Actionscript 2.0 Configuration Class (read/write)

@Update – Please note that this post is considered deprecated – please refer to: http://www.jonnyreeves.co.uk/2008/06/actionscript-20-configuration-class/

I like all of my apps to be as flexible as possible; as a result I tend to make nearly every aspect configurable. There are quite a few approaches to Configuring your Flash app, with many programmers settling for putting _root variables on the first frame of the .fla file. Sure, this works, but it does not enable script type checking at run-time and it also means that you can’t feed values in as flashVars.

To combat these problems, I created a simple Configuration base class and a Factory method which allows you to access it as a singleton:

Config (Singleton) Class

/**
 * Config.as
 * John Reeves (www.jonnyreeves.co.uk)
 *
 * Actionscript 2.0 Singleton Configuration Class.  This class will load
 * specified config and then allow you to read/write from it at run-time.
*/
import BaseConfig;
class Config
{
	/**
	 * @var _instance
	 * Instance of config, created only by load() method.
	*/
	private var _instance:Config;
 
	/**
	 * Private constructor, as this class is a Singleton we don't
	 * want instances to be be created outside of the Factory
	 * method (load()).
	*/
	private function Config()
	{
	}
 
	/**
	 * Factory method for loading the desired configuration instance.
	 * Extend this method out if you intend to have multiple
	 * Configurations accessible at compile time.
	 *
	 *	@param config	Configuration you wish to load.
	*/
	static public function load(config:String):Void
	{
		// Check if configuration has already loaded.
		if (_configuration !== undefined)
		{
			throw new Error('Config::load() -> Configuration'
				+' has already been loaded.');
		}
 
		switch (config.toString())
		{
			case 'base':
				_configuration = new BaseConfig();
				break;
 
			default:
				throw new Error('Config::load() -> Invalid'
					+ ' configuration requested');
		}
	}
 
	/**
	 * Read a configuration value from the loaded instance.
	 *
	 *	@param key	Property you wish to read from loaded instance.
	*/
	static public function read(key:String)
	{
		// Check user has loaded a config.
		if (_configuration == undefined) {
			throw new Error('Config::read() -> No configuration'
				+' loaded, please Config.load() one first.');
		}
 
		// Using the Array access method.
		return _configuration[key];
	}
 
	/**
	 * Write to the currently loaded configuration instance.
	 *
	 *	@param key	Property you wish to write
	 *	@param value	New value for above Property
	*/
	static public function write(key:String, value:Object)
	{
 
		if (_configuration == undefined) {
			throw new Error('Config::read() -> No configuration'
				+' loaded, please use Config.load() first.');
		}
 
		// Only write values if the property exists in the Config's 
		// Constructor, this is a nasty ActionScript 2.0 hack.
		if (_configuration.hasOwnProperty("_" + key))
		{
			// Using array access method, will call custom setter.
			_configuration[key] = value;
		}
 
		// Refusing to write key, add any error handling here.
		else 
		{
			trace ('Config.write() -> Invalid Property: '
				+key.toString());
		}
	}
}

Example Configuration Class (set your values here)

/**
 * BaseConfiguration.as
 * John Reeves (www.jonnyreeves.co.uk)
 *
 * Base configuration class, should you need even more flexibility
 * at run-time you can extend this and add to the Factory Method in
 * the Config class.
 *
 * This file contains the actual configuration values for your application
 * complete with Strict Type Checking at both Compile and Run time.
*/
class BaseConfiguration
{
	/**
	 * @var _exampleProtectedString
	 * This is an example string which has a default value but can't be
	 * over-ridden at run time with a flashVar. (see Constructor)
	*/
 	protected var _exampleProtectedString:String = 'default value';
 
	/**
	 * @var _exampleString
	 * This is an example string, it doesn't have a default value but
	 * can be over-ridden at run time with a flashVar.  (see Constructor)
	*/
	private var _exampleString:String;
 
	/**
	 * @var _exampleNumber
	 * private var _examplePrivateNumber
	 * This is an example number, it has a default value and can be
	 * over-ridden by a flashVar at runtime.
	*/
	private var _exampleNumber:Number = 1234;
 
	/**
	 * Constructor
	 * Any properties defined here can be over-ridden at run-time by flashVars
	 * embedded in the HTML.  Any properties not defined will be "protected"
	*/
	public function BaseConfiguration()
	{
		// These props are modifiy-able at runtime with flashVars.
		exampleString = this._exampleString;
		exampleNumber = this._exampleNumber;
 
		// If the next line were un-commented, we would be able to
		// modify exampleProtectedString at runtime with a flashVar
		// exampleProtectedString = this._exampleProtectedString;
	}
 
	/**
	 * Getter and Setter for exampleString
	*/
	public function get exampleString():String
	{
		return this._exampleString;
	}
	public function set exampleString(value:String):Void
	{
		// Run time type checking.
		if (value !== undefined || value !== null)
		{
			this._exampleString = value.toString();
		}
	}
 
	/**
	 * Getter and Setter for exampleProtectedString
	*/
	public function get exampleProtectedString():String
	{
		return this._exampleProtectedString;
	}
	public function set exampleProtectedString(value:String):Void
	{
		// Run time type checking.
		if (value !== undefined || value !== null)
		{
			this._exampleString = value.toString();
		}
	}
 
	/**
	 * Getter and Setter for exampleNumber
	*/
	public function get exampleNumber():Number
	{
		return this._exampleNumber;
	}
	public function set exampleNumber(value:Number):Void
	{
		// Run time type checking.
		if (!isNaN(value))
		{
			this._exampleNumber = Number(value);
		}
	}
}

Example Script which Reads and Writes from the Config

/**
 * Main.as
 * John Reeves (www.jonnyreeves.co.uk)
 *
 * Example application which will use our Config class to read a value
 * and write any flashVars which were passed in at run time.
 *
 * Please note that this is psudo code and probably wont' compile.
*/
import Config;
class Main
{
	/**
	 * Constructor, just an example of using the config class.
	*/
	public function Main()
	{
		// Load 'base' config
		Config.load('base');
 
		// Trace out exampleString
		trace(Config.read('exampleNumber');	// outputs "1234"
 
		// Set an example flashVar (_root), this can also be done
		// in the HTML using the flashVar param, or
		// using the URI param: move="main.swf?exampleNumber=4321"
		_root.exampleNumber = 4321		
 
		// Load in all flashVars from the _root and set them
		for (var flashVar in _root)
		{
			// Loop each _root var and set it in our config
			Config.write(flashVar, unescape(_root[flashVar]));
 
		}
 
		trace (Config.read('exampleNumber'));	// outputs "4321"
 
		// And with a string (outputs "default Value")
		trace (Config.read('exampleProtectedString'))
 
		// try to over-write a "protected" value (one not set in the
		// BaseConfiguration constructor.
		_root.exampleProtectedString = "a new value";
 
		// Load in all flashVars from _root again...
		for (var flashVar in _root)
		{
			// Loop each _root var and set it in our config
			Config.write(flashVar, unescape(_root[flashVar]));
		}
 
		// as it's protected, it won't have written it
		trace (Config.read('exampleProtectedString') // still outputs
							// "default value"
	}
}

So, as I hope you can see, usage is pretty straight forward, and as the Config class is a singleton, and the read() and write() methods are both static, they can be accessed from anywhere in your code (as long as you import Config.as)

Download all 3 .as files above: Actionscript 2.0 Configuration Class .zip

This entry was posted in ActionScript 2. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">