/// <summary> /// Loads the transitions defined within the given node. /// </summary> /// <remarks> /// If the given parent node has an <b>id</b> attribute, that ID value is used /// as the parent state ID for the transitions loaded from the node. /// </remarks> /// <param name="parentNode">The XmlNode to load the transitions from.</param> /// <returns>A <b>List<Transition></b> containing the transitions loaded from the given node.</returns> private List<Transition> LoadTransitions( XmlNode parentNode) { List<Transition> tranistions = new List<Transition>(); // load the node's transitions XmlNodeList transitionNodes = parentNode.SelectNodes("transition"); long id = -1; // if the parent node has an ID, get it if (parentNode.Attributes[ID_ATTRIBUTE] != null) { try { id = long.Parse(parentNode.Attributes[ID_ATTRIBUTE].Value); } catch (Exception) {} } foreach (XmlNode transNode in transitionNodes) { try { Transition trans = new Transition(id, long.Parse(transNode.Attributes["targetState"].Value), transNode.Attributes["name"].Value.ToLower(), (transNode.Attributes["publishKeyParams"] == null) ? null : transNode.Attributes["publishKeyParams"].Value.ToLower(), (transNode.Attributes["contentProvider"] == null) ? null : transNode.Attributes["contentProvider"].Value.ToLower()); tranistions.Add(trans); } catch (Exception e) { LogManager.GetCurrentClassLogger().Error( errorMessage => errorMessage("ConfigSmStateDao.LoadTransitions: failure loading transition ({0}): ", transNode.OuterXml), e); } } return tranistions; }
/// <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; }
public void AddTransition( Transition trans) { this.transitions.Add(trans.Name, trans); }
private void ProcessGraphmlFile( string filename, IDictionary<long, IState> states, IDictionary<string, Dictionary<string, long>> transitionGroups, IDictionary<long, List<string>> stateTransitionGroups) { // Key is the id of the node, Value is the stateID Dictionary<string, int> transitionLookup = new Dictionary<string, int>(); Dictionary<string, string> transitionGroupLookup = new Dictionary<string, string>(); XDocument xdoc = XDocument.Load(filename); XPathNavigator nav = xdoc.CreateNavigator(); IEnumerable<XPathNavigator> nodes = this.FindNodes(nav, "node"); IEnumerable<XPathNavigator> edges = this.FindNodes(nav, "edge"); foreach (XPathNavigator node in nodes) { string type = string.Empty; string contents = string.Empty; string nodeId = string.Empty; XPathNavigator nodeAttributes = node.Clone(); nodeAttributes.MoveToFirstAttribute(); do { if (nodeAttributes.Name == "id") { nodeId = nodeAttributes.Value; break; } } while (nodeAttributes.MoveToNextAttribute()); node.MoveToChild(XPathNodeType.All); XPathNavigator label = null; XPathNavigator shape = null; do { if ((node.Name == "data") && node.HasAttributes) { XPathNavigator dataNodes = node.Clone(); do { XPathNavigator dataNode = dataNodes.Clone(); string key = dataNodes.GetAttribute("key", string.Empty); if (!string.IsNullOrEmpty(key) && key.StartsWith("d") && dataNode.HasChildren) { try { XPathNavigator shapeNode = dataNode.Clone(); if (shapeNode.HasChildren) { shapeNode.MoveToChild(XPathNodeType.All); shapeNode.MoveToChild(XPathNodeType.All); do { switch (shapeNode.Name) { case "y:Fill": break; case "y:NodeLabel": label = shapeNode.Clone(); break; case "y:BorderStyle": break; case "y:Shape": shape = shapeNode.Clone(); break; } } while (shapeNode.MoveToNext()); Trace.WriteLine(string.Empty); if (shape != null) { shape.MoveToFirstAttribute(); } if (shape != null) { type = shape.Value; } if (label != null) { contents = label.Value; } } } catch (NullReferenceException exception) { this.log.Error( errorMessage => errorMessage("ProcessFile() and error occured processing file ({1}) {0}", exception, filename)); } } } while (dataNodes.MoveToNext()); } } while (node.MoveToNext()); try { int stateId; switch (type) { case "rectangle": // page state IState pageNode = this.CreatePageState(out stateId, contents); if (states.ContainsKey(pageNode.Id)) { throw new ApplicationException(string.Format("Page State ({0})already exists.", pageNode.Id)); } states[pageNode.Id] = pageNode; transitionLookup[nodeId] = stateId; break; case "octagon": // stop state IState stopNode = this.CreateStopState(out stateId, contents); if (states.ContainsKey(stopNode.Id)) { throw new ApplicationException(string.Format("Stop State ({0})already exists.", stopNode.Id)); } states[stopNode.Id] = stopNode; transitionLookup[nodeId] = stateId; break; case "roundrectangle": // action state IState actionNode = this.CreateActionState(out stateId, contents); if (states.ContainsKey(actionNode.Id)) { throw new ApplicationException(string.Format("Action State ({0})already exists.", actionNode.Id)); } states[actionNode.Id] = actionNode; transitionLookup[nodeId] = stateId; break; case "ellipse": // connector transitionLookup[nodeId] = int.Parse(contents); break; case "diamond": // prerequisite definitions are handled in PreProcessGraphmlFile break; case "parallelogram": string transitionGroupName = string.Empty; string[] split = contents.Split('\n'); NameValueCollection nodeContents = this.ProcessContent(split); if (nodeContents[NAME_ATTRIBUTE] == null) { transitionGroupName = split[0]; } Dictionary<string, long> tranGroup = new Dictionary<string, long>(); try { transitionGroupLookup[nodeId] = transitionGroupName; transitionGroupLookup[transitionGroupName] = nodeId; tranGroup = transitionGroups[transitionGroupName]; } catch { transitionGroups.Add(transitionGroupName, tranGroup); } break; default: break; } } catch (ApplicationException ex) { this.log.Warn(warn => warn("The was an error processing node {0} : {1}.", nodeId, ex.ToString())); } catch (Exception ex) { throw new ApplicationException("A fatal error has occured. Could not load states.", ex); } } // process all the edges foreach (XPathNavigator edge in edges) { string transitions = string.Empty; string fromNodeId = string.Empty; string toNodeId = string.Empty; XPathNavigator graphAttr = edge.Clone(); graphAttr.MoveToFirstAttribute(); do { switch (graphAttr.Name) { case "source": fromNodeId = graphAttr.Value; break; case "target": toNodeId = graphAttr.Value; break; } } while (graphAttr.MoveToNextAttribute()); // find the y:PolyLineEdge node XPathNavigator dataNodes = edge.Clone(); dataNodes.MoveToChild(XPathNodeType.All); do { if ((dataNodes.Name == "data") && dataNodes.HasAttributes && dataNodes.HasChildren) { string key = dataNodes.GetAttribute("key", string.Empty); if (!string.IsNullOrEmpty(key) && key.StartsWith("d")) { XPathNavigator dataNode = dataNodes.Clone(); dataNode.MoveToChild(XPathNodeType.All); dataNode.MoveToChild(XPathNodeType.All); do { switch (dataNode.Name) { case "y:EdgeLabel": // get the attributes transitions += edge.Value; break; } } while (dataNode.MoveToNext()); } } } while (dataNodes.MoveToNext()); // process the info int fromStateId = int.MinValue; if (transitionLookup.ContainsKey(fromNodeId)) { fromStateId = transitionLookup[fromNodeId]; } else { this.log.Error(error => error("Unable to locate transition node from node id {0}.", fromNodeId)); } if (transitionGroupLookup.ContainsKey(toNodeId)) { string[] edgecontents = transitionGroupLookup[toNodeId].Split('\n'); string[] transitionSplit = transitions.Split('\n'); foreach (string transition in transitionSplit) { if (transition == "transitionGroup") { // add this to a list of transition for a state // to be filled later //NameValueCollection content = this.ProcessContent(edgecontents); foreach (string key in edgecontents) { List<string> transitionGroupList = new List<string>(); try { transitionGroupList = stateTransitionGroups[fromStateId]; } catch { if (!stateTransitionGroups.ContainsKey(fromStateId)) { stateTransitionGroups.Add(fromStateId, transitionGroupList); } } if (!transitionGroupList.Contains(key)) { transitionGroupList.Add(key); } } } } // this must be a transitionGroups transition } else if (transitionGroupLookup.ContainsKey(fromNodeId)) { string transitionGroupName = transitionGroupLookup[fromNodeId]; //string transitionGroupNodeId = transitionGroupLookup[transitionGroupName]; string[] transitionSplit = transitions.ToLower().Split('\n'); foreach (string transition in transitionSplit) { if (transitionGroups.ContainsKey(transitionGroupName)) { Dictionary<string, long> transitionGroup = transitionGroups[transitionGroupName]; // add this transition to the transitionGroup int toStateId = transitionLookup[toNodeId]; if (!transitionGroup.ContainsKey(transition)) { transitionGroup.Add(transition, Convert.ToInt64(toStateId)); } else { this.log.Info(info => info("Transition '{0}' already exists for TransitionGroup '{1}'", transition, transitionGroupName)); } } else { // need to log something this.log.Info(info => info("Cannot locate transition group '{0}' while processing Edge", transitionGroupName)); } } } else { if (transitionLookup.ContainsKey(toNodeId)) { int toStateId = transitionLookup[toNodeId]; string[] transitionSplit = transitions.ToLower().Split('\n'); // Temporary, finish then see if this was the best way to do this before merging into the core proper. List<string> contentProviderCheck = transitionSplit.ToList(); string contentProvider = contentProviderCheck.Find(x => x.Contains("contentprovider:")); string providerType = null; if (!string.IsNullOrEmpty(contentProvider)) { providerType = contentProvider.Replace("contentprovider:", ""); providerType = providerType.Trim(); this.log.Info(info => info("Created transition with a content provider.")); contentProviderCheck.Remove(contentProvider); } foreach (string transition in contentProviderCheck) { if (fromStateId > 0 && toStateId > 0) { try { Transition trans = new Transition(fromStateId, toStateId, transition, null, providerType); ((BaseState)states[fromStateId]).AddTransition(trans); } catch (Exception) { this.log.Error(error => error("Error Adding Transition to State ({0} -> {1} -> ({2}))", fromStateId, transition, toStateId)); } } } } else { this.log.Info(info => info("Unable to locate transition to node {0} in transition {1}", toNodeId, transitions)); } } } nav.MoveToChild(XPathNodeType.All); nav.MoveToChild(XPathNodeType.All); }