Пример #1
0
 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);
        }
Пример #17
0
 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";
            }
        }
Пример #21
0
        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;
                    }
                }
            }
        }
Пример #25
0
        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);