protected CoderBase(StateMachineType model, StateBuilderOptions options, CodeNamespace codeNamespace) { Model = model; Options = options; CodeNamespace = codeNamespace; OnCoderBaseCreated(model, options, codeNamespace); }
partial void OnFilledDefaultSettings(StateMachineType model, string inputFileName) { //todo parse such thing like event param shortcut so we dont have to do it at many places foreach (var eventSource in model.events) { foreach (var evt in eventSource.@event) { if (evt.parameter != null) { foreach (ParameterType param in evt.parameter) { #region param shortcut /*@param shortcut : * If you named the event args * with the same name as the event * example: * eventID: PhoneAnswered * event params: PhoneAnswered e * you will get "EventArgs" added in the code like * PhoneAnswered(object sender, PhoneAnsweredEventArgs e) */ //Deals with the shortcut of using the same event id as args if (param.type == evt.id) { param.type = evt.id + CoderBase.OptionsStatic.EventMessageSuffix; } #endregion } } } } }
public void Build() { //ext OnBuildStarting(); xmlModel = new StateMachineXmlModel(InputFileName); model = xmlModel.Build(); //ext OnModelRead(model); StreamWriter streamWriter = new StreamWriter(OutputFileName); CodeCompileUnit code = new CodeCompileUnit(); CodeNamespace codeNamespace = CreateNameSpace(code); WriteHeader(codeNamespace); coder = new CoderStateMachine(model, Options, codeNamespace); coder.WriteCode(); OnBuildWriteCompleted(coder, codeNamespace, code, model); codeDomProvider.GenerateCodeFromNamespace(codeNamespace, streamWriter, null); streamWriter.Close(); OnBuildCompleted(coder, codeNamespace, code, model, OutputFileName, OutputDirectory); }
/// <summary> /// Validate a transition such as the nextState and the event attribute. /// </summary> /// <param name="reader">The Xml reader.</param> /// <param name="model">The State Machine Model</param> /// <param name="model">The state for this transition.</param> private void ValidateTransition(XmlReader reader, StateMachineType model, StateType state) { string eventName = reader[TAG_EVENT]; string conditionAttribute = reader[TAG_CONDITION]; ts.TraceEvent(TraceEventType.Verbose, 1, "ValidateTransition state {0} event {1}", state.name, eventName); using (XmlReader subReader = reader.ReadSubtree()) { List <TransitionType> transitions = model.GetTransitionList(state, eventName); CheckDuplicatedTransition(reader, model, transitions); CheckTransitionOrder(reader, model, transitions); while (reader.MoveToNextAttribute()) { if (reader.Name == TAG_EVENT) { ValidateTransitionEvent(reader, model); } else if (reader.Name == TAG_NEXT_STATE) { ValidateTransitionNextState(reader, model); } else if (reader.Name == TAG_CONDITION) { ValidateTransitionAttributeCondition(reader, model, state); } } while (subReader.Read()) { switch (subReader.NodeType) { case XmlNodeType.Element: ts.TraceEvent(TraceEventType.Verbose, 1, "ValidateTransition element {0}", reader.Name); if (subReader.Name == TAG_CONDITION) { TransitionType transition = model.GetTransition(state, eventName, reader.ReadString()); ValidateTransitionElementCondition(subReader, model, transition, conditionAttribute); } else if (subReader.Name == TAG_TIMER_START) { ValidateTimerStart(subReader, model); } else if (subReader.Name == TAG_TIMER_STOP) { ValidateTimerStop(subReader, model); } break; case XmlNodeType.Attribute: ts.TraceEvent(TraceEventType.Verbose, 1, "ValidateTransition attribute {0}", reader.Name); break; } } } }
/// <summary> /// Validate the event tag. /// </summary> /// <param name="reader">The Xml reader.</param> /// <param name="model">The State Machine Model</param> private void ValidateEvent(XmlReader reader, StateMachineType model, string feeder) { string eventName = reader[TAG_NAME]; string eventId = reader[TAG_EVENT_ID]; ts.TraceEvent(TraceEventType.Verbose, 1, "ValidateEvent name {0}, id {1}", eventName, eventId); model.AddEventToFeeder(feeder, eventId); }
public CoderStateMachine(StateMachineType model, StateBuilderOptions options, CodeNamespace codeNamespace) : base(model, options, codeNamespace) { this.coderFeeder = new CoderFeeder(model, options, codeNamespace); this.coderContext = new CoderContext(model, options, codeNamespace); this.coderParallel = new CoderParallel(model, options, codeNamespace); this.coderState = new CoderState(model, options, codeNamespace); }
/// <summary> /// Check that the transition with an attribute condition is a valid transition. /// </summary> /// <param name="reader">The Xml reader.</param> /// <param name="model">The State Machine Model</param> /// <param name="state">The state for this transition.</param> private void ValidateTransitionAttributeCondition(XmlReader reader, StateMachineType model, StateType state) { IXmlLineInfo xmlInfo = (IXmlLineInfo)reader; int lineNumber = xmlInfo.LineNumber; int linePosition = xmlInfo.LinePosition; string condition = reader.Value; ts.TraceEvent(TraceEventType.Verbose, 1, "ValidateTransitionEvent ({0},{1}) condition {2}", lineNumber, linePosition, condition); }
/// <summary> /// Validate the attribute state@kind /// Composite and final flags are imcompatible. /// </summary> /// <param name="reader">The Xml reader.</param> /// <param name="model">The State Machine Model</param> private void ValidateStateKind(XmlReader reader, StateMachineType model, StateType state) { string kind = reader.Value; ts.TraceEvent(TraceEventType.Verbose, 1, "ValidateStateKind state {0}, kind {1}", state.name, kind); if (state.Type.HasFlag(StateType.TypeFlags.FINAL) && state.Type.HasFlag(StateType.TypeFlags.COMPOSITE)) { string error = "State " + state.name + " is a composite state which cannot have the final or the error attribute"; ReportError(reader, ERROR_COMPOSITE_AND_FINAL, error); } }
/// <summary> /// Validate the timer tag. /// Synchronous machine cannot have this tag. /// </summary> /// <param name="reader">The Xml reader.</param> /// <param name="model">The State Machine Model</param> private void ValidateTimer(XmlReader reader, StateMachineType model) { string timerName = reader[TAG_NAME]; ts.TraceEvent(TraceEventType.Verbose, 1, "ValidateTimer {0}", timerName); if (model.settings.asynchronous == false) { string error = "Synchronous state machine cannot handle timers, set asynchronous=\"true\" or remove this timer element."; ReportError(reader, ERROR_SYNCHRONOUS_CANNOT_HAVE_TIMERS, error); } }
/// <summary> /// Create and fill the State Machine object from its XML file. /// </summary> /// <param name="inputFileName"></param> /// <returns></returns> protected StateMachineType DeserializeFile(string inputFileName) { ts.TraceEvent(TraceEventType.Verbose, 1, "DeserializeFile: {0}", inputFileName); XmlSerializer serializer = new XmlSerializer(typeof(StateMachineType)); // TODO HEEFRE use "using()" TextReader reader = new StreamReader(inputFileName); StateMachineType fsm = (StateMachineType)serializer.Deserialize(reader); reader.Close(); return(fsm); }
/// <summary> /// Check for duplicated condition, condition may have either the attribute or the element but not both. /// </summary> /// <param name="reader">The Xml reader.</param> /// <param name="model">The State Machine Model</param> /// <param name="transition"></param> private void ValidateTransitionElementCondition( XmlReader reader, StateMachineType model, TransitionType transition, string conditionAttribute) { if (conditionAttribute != null) { string error = "Transition " + model.GetTransitionName(transition) + " have condition as an attribute and as an element, remove one of them"; ReportError(reader, ERROR_CONDITION_DUPLICATED, error); } }
/// <summary> /// Check that the attribute transition@nextState is a valid state. /// </summary> /// <param name="reader">The Xml reader.</param> /// <param name="model">The State Machine Model</param> private void ValidateTransitionNextState(XmlReader reader, StateMachineType model) { string nextStateName = reader.Value; ts.TraceEvent(TraceEventType.Verbose, 1, "ValidateTransitionNextState next state {0}", nextStateName); StateType nextState = model.GetStateType(nextStateName); if (nextState == null) { string error = "Next state " + nextStateName + " does not exist"; ReportError(reader, ERROR_NEXT_STATE_DOES_NOT_EXIST, error); } }
/// <summary> /// Check that the attribute transition@event is a valid event. /// </summary> /// <param name="reader">The Xml reader.</param> /// <param name="model">The State Machine Model</param> private void ValidateTransitionEvent(XmlReader reader, StateMachineType model) { string eventId = reader.Value; ts.TraceEvent(TraceEventType.Verbose, 1, "ValidateTransitionEvent event {0}", eventId); EventType evt = model.GetEventFromId(eventId); if (evt == null) { string error = "Event " + eventId + " does not exist"; ReportError(reader, ERROR_EVENT_DOES_NOT_EXIST, error); } }
/// <summary> /// Buid the State Machine code. /// </summary> /// <returns></returns> public StateMachineType Build() { ValidateInputFile(InputFileName); StateMachineType model = DeserializeFile(InputFileName); FillDefaultSettings(model, InputFileName); // Post Process model to add state parent ad fill state map, fill the event and interface map model.FillModelPost(); ValidateModel(InputFileName, model); return(model); }
/// <summary> /// Transition without condition must be the last one. /// </summary> /// <param name="reader">The Xml reader.</param> /// <param name="model">The State Machine Model</param> /// <param name="transitions"></param> private void CheckTransitionOrder(XmlReader reader, StateMachineType model, List <TransitionType> transitions) { if (transitions.Count >= 2) { for (int i = 0; i < transitions.Count - 1; i++) { if (string.IsNullOrEmpty(model.GetCondition(transitions[i])) == true) { string error = "Transition " + model.GetTransitionName(transitions[i]) + " does not have a condition. Transition without condition must be last and unique"; ReportError(reader, ERROR_TRANSITION_ORDER, error); } } } }
/// <summary> /// Fill the default settings. /// </summary> /// <param name="model"></param> /// <param name="inputFileName"></param> private void FillDefaultSettings(StateMachineType model, string inputFileName) { if (String.IsNullOrEmpty(model.settings.name) == true) { model.settings.name = Path.GetFileNameWithoutExtension(inputFileName); } if (model.settings.@using == null) { model.settings.@using = new string[0]; } FillDefaultContext(model); }
public void FsmEventList(StateMachineType fsm) { foreach (EventSourceType eventSource in fsm.events) { Console.WriteLine("EventProvider:"); Console.WriteLine("name: " + eventSource.name); Console.WriteLine("description: " + eventSource.description); foreach (EventType smEvent in eventSource.@event) { Console.WriteLine("Event:"); Console.WriteLine("name: " + smEvent.name); Console.WriteLine("id: " + smEvent.id); Console.WriteLine("description: " + smEvent.description); } } }
/// <summary> /// Validate the timerStop tag, the attribute timerStop@timer must exist in events /// </summary> /// <param name="reader">The Xml reader.</param> /// <param name="model">The State Machine Model</param> private void ValidateTimerStop(XmlReader reader, StateMachineType model) { string timerName = reader[TAG_TIMER]; ts.TraceEvent(TraceEventType.Verbose, 1, "ValidateTimerStop {0}", timerName); while (reader.MoveToNextAttribute()) { if (reader.Name == TAG_TIMER) { if (model.GetTimerFromName(timerName) == null) { string error = "Timer " + timerName + " does not exist"; ReportError(reader, ERROR_TIMER_DOES_NOT_EXIST, error); } } } }
/// <summary> /// Check for duplicated transition. /// </summary> /// <param name="reader">The Xml reader.</param> /// <param name="model">The State Machine Model</param> /// <param name="transitions"></param> private void CheckDuplicatedTransition(XmlReader reader, StateMachineType model, List <TransitionType> transitions) { var TransitionIdList = new List <string>(); foreach (TransitionType transition in transitions) { string transitionId = model.GetTransitionName(transition); if (TransitionIdList.IndexOf(transitionId) < 0) { TransitionIdList.Add(transitionId); } else { string error = "Duplicated transitions " + transitionId + ", remove one transition"; ReportError(reader, ERROR_TRANSITION_DUPLICATED, error); } } }
/// <summary> /// Fill set default context class name and instance name. /// </summary> /// <param name="model"></param> private void FillDefaultContext(StateMachineType model) { ContextType context = model.settings.context; if (context == null) { context = new ContextType(); model.settings.context = context; } if (String.IsNullOrEmpty(context.instance)) { context.instance = "context"; } if (String.IsNullOrEmpty(context.@class)) { context.@class = model.settings.name + "Context"; } }
public void Build() { xmlModel = new StateMachineXmlModel(InputFileName); model = xmlModel.Build(); StreamWriter streamWriter = new StreamWriter(OutputFileName); CodeCompileUnit code = new CodeCompileUnit(); CodeNamespace codeNamespace = CreateNameSpace(code); WriteHeader(codeNamespace); coder = new CoderStateMachine(model, Options, codeNamespace); coder.WriteCode(); codeDomProvider.GenerateCodeFromNamespace(codeNamespace, streamWriter, null); streamWriter.Close(); }
//private CoderEventsArgs coderEventsArgs; public CoderStateMachine(StateMachineType model, StateBuilderOptions options, CodeNamespace codeNamespace) : base(model, options, codeNamespace) { this.coderFeeder = new CoderFeeder(model, options, codeNamespace); OnCoderFeederCreated(coderFeeder, model, options, codeNamespace); this.coderContext = new CoderContext(model, options, codeNamespace); OnCoderContextCreated(coderContext, model, options, codeNamespace); this.coderParallel = new CoderParallel(model, options, codeNamespace); OnCoderParallelCreated(coderParallel, model, options, codeNamespace); this.coderState = new CoderState(model, options, codeNamespace); OnCoderStateCreated(coderState, model, options, codeNamespace); //this.coderEventsArgs = new CoderEventsArgs(model, options, codeNamespace); OnCoderStateMachineCreated(coderFeeder, coderContext, coderParallel, coderState, model, options, codeNamespace); }
/// <summary> /// Validate the event list. /// </summary> /// <param name="reader">The Xml reader.</param> /// <param name="model">The State Machine Model</param> private void ValidateEventList(XmlReader reader, StateMachineType model) { ts.TraceEvent(TraceEventType.Verbose, 1, "ValidateEventList"); using (XmlReader subReader = reader.ReadSubtree()) { while (subReader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: if (reader.Name == TAG_EVENT_PROVIDER) { ValidateEventProvider(subReader, model); } break; } } } }
/// <summary> /// Validate the eventSource tag. /// </summary> /// <param name="reader">The Xml reader.</param> /// <param name="model">The State Machine Model</param> private void ValidateEventProvider(XmlReader reader, StateMachineType model) { string name = reader[TAG_NAME]; string file = reader[TAG_EVENT_FILE]; string feeder = reader[TAG_FEEDER]; ts.TraceEvent(TraceEventType.Verbose, 1, "ValidateEventProvider {0}, feeder {1}", name == null ? "" : name, file == null ? "" : file, feeder == null ? "" : feeder); //TODO check if file exist using (XmlReader subReader = reader.ReadSubtree()) { while (reader.MoveToNextAttribute()) { if (reader.Name == TAG_EVENT_FILE) { ParseEventInterface(reader, model, name, file, feeder); } } while (subReader.Read()) { switch (subReader.NodeType) { case XmlNodeType.Element: if (subReader.Name == TAG_TIMER) { ValidateTimer(subReader, model); } else if (subReader.Name == TAG_EVENT) { ValidateEvent(subReader, model, feeder); } break; } } } }
public void UnserializeFile(string fileName) { //try //{ TextReader reader = new StreamReader(fileName); StateMachineType fsm = (StateMachineType)Serializer.Deserialize(reader); FsmPrint(fsm); reader.Close(); //} //catch (IOException ioException) //{ // Console.WriteLine("Error: " + ioException.Message); //} //catch (System.InvalidOperationException invalidOperationException) //{ // Console.WriteLine("Error: " + invalidOperationException.Message); // //Console.WriteLine(); //} }
/// <summary> /// Validate the onEntry and onEntry tag. /// </summary> /// <param name="reader">The Xml reader.</param> /// <param name="model">The State Machine Model</param> /// <param name="state"></param> private void ValidateEntryExit(XmlReader reader, StateMachineType model, StateType state) { ts.TraceEvent(TraceEventType.Verbose, 1, "ValidateEntryExit state {0}", state.name); using (XmlReader subReader = reader.ReadSubtree()) { while (reader.MoveToNextAttribute()) { if (reader.Name == TAG_ACTION) { ts.TraceEvent(TraceEventType.Verbose, 1, "ValidateEntryExit state {0} action {1}", state.name, reader.Value); } } while (subReader.Read()) { switch (subReader.NodeType) { case XmlNodeType.Element: ts.TraceEvent(TraceEventType.Verbose, 1, "ValidateEntryExit element {0}", subReader.Name); if (subReader.Name == TAG_ACTION) { } else if (subReader.Name == TAG_TIMER_START) { ValidateTimerStart(subReader, model); } else if (subReader.Name == TAG_TIMER_STOP) { ValidateTimerStop(subReader, model); } break; case XmlNodeType.Attribute: ts.TraceEvent(TraceEventType.Verbose, 1, "ValidateEntryExit attribute {0}", subReader.Name); break; } } } }
/// <summary> /// Parse an event interface /// </summary> /// <param name="reader">The Xml reader.</param> /// <param name="model"></param> /// <param name="interfaceName">The interface name.</param> /// <param name="file">The filename where is the interface.</param> /// <param name="feeder">The class that feeds the events</param> private void ParseEventInterface(XmlReader reader, StateMachineType model, string interfaceName, string file, string feeder) { if (string.IsNullOrEmpty(file) == true) { return; } string inputDirectory = Path.GetDirectoryName(this.InputFileName); string interfaceFileName = inputDirectory + Path.DirectorySeparatorChar + file; try { StreamReader textReader = new StreamReader(interfaceFileName); IParser parser = ParserFactory.CreateParser(SupportedLanguage.CSharp, textReader); parser.Parse(); if (parser.Errors.Count > 0) { string error = "Error parsing interface " + interfaceFileName + ": " + parser.Errors.ErrorOutput; ReportError(reader, ERROR_EVENT_INTERFACE_INVALID, error); return; } CompilationUnit cu = parser.CompilationUnit; var visitorEvent = new VisitorEventInterface(model, interfaceName, feeder); cu.AcceptVisitor(visitorEvent, null); if (visitorEvent.InterfaceFound == false) { string error = "Interface " + interfaceName + " not found in file " + interfaceFileName; ReportError(reader, ERROR_EVENT_INTERFACE_NOT_FOUND_IN_FILE, error); } } catch (IOException iOException) { string error = "IOException for file " + interfaceFileName + ": " + iOException.Message; ReportError(reader, ERROR_FILE_NOT_FOUND, error); } }
/// <summary> /// Validates the model, it performs checks that the XSD validator cannot do. /// </summary> /// <param name="inputFileName">The input file name.</param> /// <param name="model">The State Machine Model</param> private void ValidateModel(string inputFileName, StateMachineType model) { ts.TraceEvent(TraceEventType.Verbose, 1, "ValidateModel {0}", model.settings.name); using (XmlReader reader = XmlReader.Create(inputFileName)) { while (reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: if (reader.Name == TAG_STATE) { ValidateState(reader, model); } else if (reader.Name == TAG_EVENT_LIST) { ValidateEventList(reader, model); } break; } } } }
/// <summary> /// Validate a parallel region. /// </summary> /// <param name="subReader"></param> /// <param name="model"></param> /// <param name="state"></param> private void ValidateParallel(XmlReader reader, StateMachineType model, StateType state) { string name = reader[TAG_NAME]; ts.TraceEvent(TraceEventType.Verbose, 1, "ValidateParallel name {0}", name); using (XmlReader subReader = reader.ReadSubtree()) { while (reader.MoveToNextAttribute()) { if (reader.Name == TAG_NEXT_STATE) { ValidateTransitionNextState(reader, model); } } while (subReader.Read()) { switch (subReader.NodeType) { case XmlNodeType.Element: ts.TraceEvent(TraceEventType.Verbose, 1, "ValidateParallel element {0}", subReader.Name); if (subReader.Name == TAG_STATE) { ValidateState(subReader, model); } break; case XmlNodeType.Attribute: ts.TraceEvent(TraceEventType.Verbose, 1, "ValidateParallel attribute {0}", subReader.Name); break; } } } }
partial void OnWriteCodeCompleted(StateType state, StateMachineType model);