/// <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;
        }
        /// <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()
        {
            StateInfo info = new StateInfo();
            Hashtable transGroups = new Hashtable();

            try {
                // get the path to the states.config directory from web.config
                string statesConfigPath = AppInfo.BasePath + ConfigurationManager.AppSettings["statesDiagramPath"];

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

                // read all the .graphml files in the directory.
                // XmlDocument stateSettings = new XmlDocument();

                // Key is the StateID, value is the element representing the state
                Dictionary<long, IState> states = new Dictionary<long, IState>();

                // key is the id of the node, value is the transition name
                Dictionary<string, Dictionary<string, long>> transitionGroups = new Dictionary<string, Dictionary<string, long>>();
                Dictionary<long, List<string>> stateTransitionGroups = new Dictionary<long, List<string>>();

                if (Directory.Exists(statesConfigPath)) {
                    if (Directory.GetFiles(statesConfigPath, "*.graphml", SearchOption.TopDirectoryOnly).Length > 0) {
                        string[] graphmlFiles = Directory.GetFiles(statesConfigPath, "*.graphml", SearchOption.TopDirectoryOnly);
                        foreach (string fileName in graphmlFiles) {
                            PreProcessGraphmlFile(fileName);
                        }
                        foreach (string fileName in graphmlFiles) {
                            ProcessGraphmlFile(fileName, states, transitionGroups, stateTransitionGroups);
                        }

                        foreach (KeyValuePair<long, List<string>> kvp in stateTransitionGroups) {
                            long fromStateId = kvp.Key;
                            IState state = states[fromStateId];
                            foreach (string stateTransitionGroup in kvp.Value) {
                                if (transitionGroups.ContainsKey(stateTransitionGroup)) {
                                    Dictionary<string, long> transitionGroup = transitionGroups[stateTransitionGroup];
                                    foreach (KeyValuePair<string, long> trans in transitionGroup) {
                                        long toStateId = trans.Value;
                                        Transition transition = new Transition(fromStateId, toStateId, trans.Key, null);
                                        try {
                                            ((BaseState)state).AddTransition(transition);
                                        } catch {
                                            this.log.Debug(debug => debug("Attempting to add a transition ({0}) to a state ({1}) that already exists.",
                                                                          trans.Key,
                                                                          toStateId));
                                        }
                                    }
                                } else {
                                    this.log.Debug(debug => debug("Unable to locate transition group {0} for stateid {1}", stateTransitionGroup, fromStateId));
                                }
                            }
                        }
                    } else {
                        this.log.Error(error => error("LoadStates: No States config files found"));
                        throw new IndexOutOfRangeException("LoadStates: No States config files found");
                    }
                } else {
                    this.log.Error(error => error("LoadStates: No States Folder found"));
                    throw new NotSupportedException("LoadStates: No States Folder found");
                }

                info.States = states.Values.ToArray();

                this.log.Info(infoMessage => infoMessage("Successfully loaded page config settings"));
            } catch (Exception e) {
                this.log.Error(error => error("Error occured in LoadStates: ", e));
                throw;
            } finally {
                transGroups.Clear();
            }

            return info;
        }