/// <summary>
        /// Loads the state/tranistion information for an XML config file.
        /// </summary>
        /// <remarks>
        /// The path to the config file to load is specified in the application's config file
        /// appSettings section, with the "statesConfigPath" setting.
        /// </remarks>
        /// <returns>A <b></b> object with the state/transition information loaded from the
        ///			config file.</returns>
        public StateInfo LoadStates()
        {
            List<IState> states = new List<IState>();
            StateInfo info = new StateInfo();

            try {
                //  get the path to the states.config file from web.config
                String statesConfigPath = ConfigurationManager.AppSettings["statesConfigPath"];

                if (statesConfigPath == null) {
                    throw new Exception("No states.config path in config file.");
                }

                //  make the XmlDocument object for the states.config file & load it
                XmlDocument stateSettings = new XmlDocument();
                stateSettings.Load(AppInfo.BasePath + statesConfigPath);

                //======================================================
                //  load the transition groups
                //======================================================

                //  get the "transitiongroup" nodes
                XmlNodeList transGroupNodes = stateSettings.SelectNodes("/states/" + TRANSITION_GROUP_NAME);

                Hashtable transGroups = new Hashtable();

                foreach (XmlNode groupNode in transGroupNodes) {
                    try {
                        string name = groupNode.Attributes[NAME_ATTRIBUTE].Value;
                        List<Transition> transitions = this.LoadTransitions(groupNode);
                        transGroups.Add(name, transitions);
                    } catch (Exception) {}
                }

                //======================================================
                //  load the config settings
                //======================================================

                //  read the config settings from the states file
                XmlNode configNode = stateSettings.SelectSingleNode("/states/config");
                if (configNode != null) {
                    try {
                        bool trace = bool.Parse(configNode.Attributes["trace"].Value);
                        info.AddConfig("trace", trace);
                    } catch (Exception) {}
                }

                //======================================================
                //  load the states
                //======================================================

                //  get the "state" nodes
                XmlNodeList stateNodes = stateSettings.SelectNodes("/states/state");

                IState state = null;
                NameValueCollection attributes = new NameValueCollection();

                foreach (XmlNode stateNode in stateNodes) {
                    try {
                        string type = stateNode.Attributes[TYPE_ATTRIBUTE].Value;
                        long id = long.Parse(stateNode.Attributes[ID_ATTRIBUTE].Value);

                        attributes.Clear();
                        foreach (XmlAttribute attr in stateNode.Attributes) {
                            attributes.Add(attr.Name, attr.Value);
                        }

                        state = StateFactory.MakeState(type, id, attributes);

                        if (state == null) {
                            throw new ApplicationException("Null state exception.");
                        }
                    } catch (Exception e) {
                        LogManager.GetCurrentClassLogger().Error(
                            errorMessage => errorMessage("Failed to make state: node = {0}", stateNode.OuterXml), e);
                    }

                    //  if we successfully generated the state...
            //				if (state != null) {
                    if (state is BaseState) {
                        //  load the state's transitions
                        List<Transition> transitions = this.LoadTransitions(stateNode);
                        foreach (Transition trans in transitions) {
                            try {
                                ((BaseState)state).AddTransition(trans);
                            } catch (Exception e) {
                                throw new ApplicationException(
                                    string.Format("Invalid transition '{0}' in state {1}.", trans.Name, state.Id),
                                    e);
                            }
                        }

                        //  add the transitions from transition groups if there are any
                        XmlNodeList groupNodes = stateNode.SelectNodes(TRANSITION_GROUP_NAME);
                        foreach (XmlNode groupNode in groupNodes) {
                            try {
                                //  get the name of the tranistion group
                                string name = groupNode.Attributes[NAME_ATTRIBUTE].Value;
                                //  if no transition group is defined for the given name, throw exception
                                if (!transGroups.ContainsKey(name)) {
                                    throw new ApplicationException(string.Format(
                                                                    "No transition group defined for '{0}'. State = {1}.", name, state.Id));
                                }
                                //  add the transitions from the transition group to the state
                                foreach (Transition trans in (List<Transition>)transGroups[name]) {
                                    ((BaseState)state).AddTransition(trans.Clone(state.Id));
                                }
                            } catch (Exception e) {
                                LogManager.GetCurrentClassLogger().Error(
                                    errorMessage => errorMessage("ConfigSmStateDao.LoadStates: failure loading transitiongroup (" + groupNode.OuterXml + "): "), e);
                            }
                        }
                    }

                    states.Add(state);
            //				}
                }

                //  dump the local transition groups hashtable
                transGroups.Clear();

                LogManager.GetCurrentClassLogger().Debug(
                    debugMessage => debugMessage("ConfigSmStateDao -  successfully loaded page config settings"));
            } catch (Exception e) {
                LogManager.GetCurrentClassLogger().Error(
                    errorMessage => errorMessage("ConfigSmStateDao.LoadStates: "), e);
                throw;
            }

            info.States = states.ToArray();
            return info;
        }