Actionscript 2.0 Configuration Class (read/write)

11th February, 2008 – 10:54 pm

@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

Post a Comment