Пример #1
0
        public void Parse(bool simulator=true)
        {
            var rootNode = _doc.SelectNodes("ussd");
           
            _screens = new List<UssdScreen>();
            _scripts = new List<UssdScript>();
            _actions = new List<UssdAction>();
            _formLists = new List<UssdFormList>();
            _forms = new List<UssdForm>();
            _menus = new List<UssdMenu>();
            _boundModels = new  Dictionary<string, dynamic>();


            if (rootNode==null)
            {
                throw new Exception("no \"ussd\" element found");
            }

            //gather scripts
            foreach (XmlNode node in rootNode)
            {
                foreach (XmlNode ussdElement in node.ChildNodes)
                {
                    if (ussdElement.Name == "script")
                    {
                        if (ussdElement.Attributes.GetNamedItem("id") == null)
                        {
                            throw new Exception("script attribute \"id\" is required");
                        }

                       
                        var scriptId = ussdElement.Attributes["id"].InnerText;

                        Console.WriteLine("gotten script {0}", scriptId);
                        if (_screens.Any(s => s.Id == scriptId))
                        {
                            throw new Exception($"script id already exists at {scriptId}");
                        }
                        
                        var script = new UssdScript
                        {
                            Id = scriptId,
                            Content = ussdElement.InnerText,
                            BindFrom = ussdElement.Attributes.GetNamedItem("bindfrom") != null?ussdElement.Attributes["bindfrom"].InnerText:"",
                            BindTo= ussdElement.Attributes.GetNamedItem("bindto") != null?ussdElement.Attributes["bindto"].InnerText:"",
                            
                        };

                        _scripts.Add(script);
                        Console.WriteLine("added script {0}",scriptId);
                    }
                }
            }


            foreach (XmlNode node in rootNode)
            {
                foreach (XmlNode ussdElement in node.ChildNodes)
                {

                    #region screens

                    if (ussdElement.Name=="screen")
                    {
                        if (ussdElement.Attributes["id"] == null)
                        {
                            throw new Exception("screen id is required");
                        }
                        var screenId = ussdElement.Attributes["id"].InnerText;

                        Console.WriteLine("gotten screen {0}", screenId);
                        if (_screens.Any(s => s.Id == screenId))
                        {
                            throw new Exception($"screen id already exists at {screenId}");
                        }

                        var ussdScreen = new UssdScreen
                        {
                            Id = screenId,

                        };

                        foreach (XmlNode screenItem in ussdElement.ChildNodes)
                        {
                            #region Menu Element
                            if (screenItem.Name.Equals("menu"))
                            {
                                var menuNodes = screenItem.ChildNodes;

                                var ussdMenu = new UssdMenu();
                                if (screenItem.Attributes.Count > 0)
                                {
                                    if (screenItem.Attributes["bindfrom"] != null)
                                    {
                                        //todo: always check if there's a corresponding bindto in another screen
                                        ussdMenu.BindFrom = new UssdBoundModel
                                        {
                                            Name = screenItem.Attributes["bindfrom"].InnerText
                                        };

                                    }
                                    if (screenItem.Attributes["bindaction"] != null)
                                    {

                                        ussdMenu.BindAction = new UssdBoundAction(screenItem.Attributes["bindaction"].InnerText);

                                    }

                                }

                                foreach (XmlNode menuNode in menuNodes)
                                {

                                    if (menuNode.Name == "title")
                                    {
                                        ussdMenu.Title = menuNode.InnerText.ToUssdString(simulator);
                                    }

                                    if (menuNode.Name == "option")
                                    {
                                        var menuOption = new UssdMenuOption
                                        {
                                            Text = menuNode.InnerText,
                                            Value = menuNode.Attributes["value"].InnerText.ToUssdString(simulator),
                                            OnSelect = new UssdNavigator(menuNode.Attributes["onselect"].InnerText)
                                        };

                                        ussdMenu.Options.Add(menuOption);


                                    }
                                }


                                ussdScreen.UssdItems.Add(ussdMenu);
                                _menus.Add(ussdMenu);
                                Console.WriteLine("added menu {0}", ussdMenu.Title);
                            }
                            #endregion

                            #region Form Element
                            if (screenItem.Name.Equals("form"))
                            {
                                var formNodes = screenItem.ChildNodes;

                                var ussdForm = new UssdForm();
                                if (screenItem.Attributes.Count > 0)
                                {
                                    if (screenItem.Attributes["bindto"] != null)
                                    {
                                        ussdForm.BindTo = new UssdBoundModel
                                        {
                                            Name = screenItem.Attributes["bindto"].InnerText
                                        };
                                        //_boundModels[screenItem.Attributes["bindto"].InnerText] = new Dictionary<string, string>();

                                    }
                                    if (screenItem.Attributes["onsubmit"] != null)
                                    {
                                        ussdForm.OnSubmit = new UssdNavigator(screenItem.Attributes["onsubmit"].InnerText);

                                    }
                                    else
                                    {
                                        throw new Exception("form attribute \"onsubmit\" is required");
                                    }


                                }

                                foreach (XmlNode formNode in formNodes)
                                {

                                    if (formNode.Name == "title")
                                    {
                                        ussdForm.Title = formNode.InnerText.ToUssdString(simulator);
                                    }

                                    if (formNode.Name == "input")
                                    {
                                        var ussdFormInput = new UssdFormInput
                                        {

                                            Id = formNode.Attributes["id"].InnerText,
                                            Type = formNode.Attributes["type"].InnerText,
                                            Display = formNode.Attributes["display"].Value.ToUssdString(simulator),
                                            Required =
                                                                 bool.Parse(formNode.Attributes["required"].InnerText),
                                            MaxLength = formNode.Attributes["maxlength"] == null ? (int?)null : int.Parse(formNode.Attributes["maxlength"].InnerText)
                                        };

                                        if (ussdFormInput.Type == "list")
                                        {
                                            ussdFormInput.IsList = true;
                                            ussdFormInput.ListId = formNode.Attributes["listid"].InnerText;
                                        }



                                        ussdForm.Inputs.Add(ussdFormInput);


                                    }
                                    if (formNode.Name == "list")
                                    {


                                        var formListNodes = formNode.ChildNodes;

                                        var ussdFormList = new UssdFormList { Id = formNode.Attributes["id"].InnerText };



                                        bool hasRepeater = formNode.Attributes.GetNamedItem("repeater") != null;

                                        if (hasRepeater)
                                        {
                                       
                                         
                                            ussdFormList.Repeater = formNode.Attributes["repeater"].InnerText;

                                            var scriptItem =
                                                _scripts.FirstOrDefault(s => s.Id == ussdFormList.RepeaterScriptId);
                                            if (scriptItem == null)
                                            {
                                                throw new Exception(
                                                    $"script id \"{ussdFormList.RepeaterScriptId}\" not found");
                                            }

                                            
                                        }
                                        else
                                        {
                                            foreach (XmlNode formListNode in formListNodes)
                                            {

                                                ussdFormList.Choices.Add(new UssdFormListChoice
                                                {
                                                    Text = formListNode.InnerText,
                                                    Selector = formListNode.Attributes["selector"].InnerText,
                                                    Value = formListNode.Attributes["value"].InnerText
                                                });
                                            }
                                        }

                                        _formLists.Add(ussdFormList);

                                    }
                                }


                                ussdScreen.UssdItems.Add(ussdForm);
                                _forms.Add(ussdForm);

                                Console.WriteLine("added form {0}", ussdForm.Title);
                            }

                            #endregion

                            #region Text Element
                            if (screenItem.Name.Equals("text"))
                            {
                                var ussdText = new UssdText(screenItem.InnerText.ToUssdString(simulator));
                                if (screenItem.Attributes.Count > 0)
                                {
                                    if (screenItem.Attributes["bindfrom"] != null)
                                    {
                                        //todo: always check if there's a corresponding bindto in another screen
                                        ussdText.BindFrom = new UssdBoundModel
                                        {
                                            Name = screenItem.Attributes["bindfrom"].InnerText
                                        };

                                    }
                                    if (screenItem.Attributes["bindaction"] != null)
                                    {

                                        ussdText.BindAction = new UssdBoundAction(screenItem.Attributes["bindaction"].InnerText);

                                    }

                                }
                                ussdScreen.UssdItems.Add(ussdText);
                            }
                            #endregion

                            #region Action Element
                            if (screenItem.Name.Equals("action"))
                            {
                                var actionNode = screenItem.ChildNodes;

                                var ussdAction = new UssdAction();
                                if (screenItem.Attributes.Count > 0)
                                {
                                    if (screenItem.Attributes["id"] != null)
                                    {
                                        ussdAction.Id = screenItem.Attributes["id"].InnerText;

                                    }
                                    else
                                    {
                                        throw new Exception("action attribute id is required");
                                    }

                                    if (screenItem.Attributes["bindto"] != null)
                                    {
                                        ussdAction.BindTo = new UssdBoundModel
                                        {
                                            Name = screenItem.Attributes["bindto"].InnerText
                                        };
                                     //   _boundModels[screenItem.Attributes["bindto"].InnerText] = new Dictionary<string, string>();

                                    }
                                    else
                                    {
                                        throw new Exception("action attribute bindto is required");
                                    }

                                    if (screenItem.Attributes["cycle"] != null)
                                    {
                                        UssdActionCycle cycle;
                                        if (!Enum.TryParse(screenItem.Attributes["cycle"].InnerText, true, out cycle))
                                        {
                                            throw new Exception(String.Format("action attribute cycle has an unknown value. Allowed values are: {0} or {1}", UssdActionCycle.Always, UssdActionCycle.Once));
                                        }

                                        ussdAction.Http.Cycle = cycle;
                                    }
                                }
                                else
                                {
                                    throw new Exception("form attribute id and bindto is required");
                                }

                                foreach (XmlNode xmlNode in actionNode)
                                {


                                    if (xmlNode.Attributes.Count > 0)
                                    {
                                        if (xmlNode.Attributes["url"] != null)
                                        {
                                            ussdAction.Http.Url = xmlNode.Attributes["url"].InnerText.ToUssdString(simulator);

                                        }
                                        else
                                        {
                                            throw new Exception("http attribute url is required");
                                        }
                                        if (xmlNode.Attributes["method"] != null)
                                        {
                                            UssdActionHttpMethod httpMethod;
                                            if (!Enum.TryParse(xmlNode.Attributes["method"].InnerText, true, out httpMethod))
                                            {
                                                throw new Exception("http attribute method is invalid");
                                            }

                                            ussdAction.Http.Method = httpMethod;
                                        }
                                        else
                                        {
                                            throw new Exception("http attribute method is required");
                                        }
                                    }


                                    if (xmlNode.Name == "http")
                                    {
                                        var httpNodes = xmlNode.ChildNodes;

                                        foreach (XmlNode httpNode in httpNodes)
                                        {
                                            if (httpNode.Name == "header")
                                            {
                                                var headers = httpNode.ChildNodes;

                                                foreach (XmlNode header in headers)
                                                {
                                                    if (header.Name == "add")
                                                    {
                                                        var ussdActionHttpHeader = new UssdActionHttpHeader
                                                        {

                                                            Name = header.Attributes["key"].InnerText,
                                                            Value = header.Attributes["value"].InnerText,

                                                        };

                                                        ussdAction.Http.Headers.Add(ussdActionHttpHeader);
                                                    }

                                                }
                                            }
                                            if (httpNode.Name == "body")
                                            {
                                                if (httpNode.Attributes["bindfrom"] != null)
                                                {

                                                    ussdAction.Http.Body.BindFrom = new UssdBoundModel
                                                    {
                                                        Name = httpNode.Attributes["bindfrom"].InnerText
                                                    };

                                                }

                                                var headers = httpNode.ChildNodes;

                                                foreach (XmlNode header in headers)
                                                {
                                                    if (header.Name == "add")
                                                    {
                                                        var ussdActionHttpBody = new UssdActionHttpBodyParam
                                                        {

                                                            Name = header.Attributes["key"].InnerText,
                                                            Value = header.Attributes["value"].InnerText,

                                                        };

                                                        ussdAction.Http.Body.Params.Add(ussdActionHttpBody);
                                                    }

                                                }
                                            }
                                            if (httpNode.Name == "response")
                                            {
                                                var responses = httpNode.ChildNodes;

                                                foreach (XmlNode response in responses)
                                                {
                                                    if (response.Name == "code")
                                                    {
                                                        var ussdActionHttpResponse = new UssdActionHttpResponse
                                                        {

                                                            Value = int.Parse(response.Attributes["value"].InnerText),
                                                            Goto = new UssdNavigator(response.Attributes["goto"].InnerText),

                                                        };

                                                        ussdAction.Http.Responses.Add(ussdActionHttpResponse);
                                                    }

                                                }
                                            }
                                        }



                                    }
                                }


                                ussdScreen.UssdItems.Add(ussdAction);
                                _actions.Add(ussdAction);
                                Console.WriteLine("added action {0}", ussdAction.Id);
                            }

                            #endregion

                        }

                        if (ussdElement.Attributes["main"] != null
                            )
                        {
                            var mainString = ussdElement.Attributes["main"].InnerText;

                            bool isMain;

                            if (bool.TryParse(mainString, out isMain))
                            {
                                ussdScreen.Main = isMain;
                            }
                        }

                        _screens.Add(ussdScreen);

                        Console.WriteLine("{0} screens", _screens.Count);
                    }
                   
                    #endregion

                }
            }

            if (_screens.Count == 0)
            {
                throw new Exception("no screens");
            }

            if (!_screens.Any(s=>s.Main))
            {
                throw new Exception("no main attribute on any of the screens. Please include main=\"true\" as attribute on your main screen element");
            }
        }
Пример #2
0
        private async Task<Tuple<HttpStatusCode, JObject>> GrabActionResponse(UssdAction actionItem)
        {
            var resp = new Tuple<HttpStatusCode, JObject>(HttpStatusCode.Gone, JObject.FromObject(new {Name="fake"}));
            try
            {
                

                var restClient = new HttpClient();
         
                restClient.DefaultRequestHeaders.Clear();

                foreach (var ussdActionHttpHeader in actionItem.Http.Headers)
                {
                    restClient.DefaultRequestHeaders.Add(ussdActionHttpHeader.Name,ussdActionHttpHeader.Value);
                }

                HttpResponseMessage result = null;

                var formItems = _boundModels.FirstOrDefault(b => b.Key == actionItem.Http.Body.BindFrom.Name);

                Dictionary<string, string> f = new Dictionary<string, string>();
                if (formItems.Value!=null)
                {
                    f = formItems.Value;
                }

                if (actionItem.Http.Body.Params.Any())
                {
                    foreach (var ussdActionHttpBodyParam in actionItem.Http.Body.Params)
                    {
                        f.Add(ussdActionHttpBodyParam.Name, ussdActionHttpBodyParam.Value);
                    }
                }


                HttpContent content = new StringContent(JsonConvert.SerializeObject(f));
                content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); //todo: document that by default content-type is application/json

                switch (actionItem.Http.Method)
                {
                    case UssdActionHttpMethod.Post:
                        result = await restClient.PostAsync(new Uri(actionItem.Http.Url), content);
                        break;
                    case UssdActionHttpMethod.Put:
                        result = await restClient.PutAsync(new Uri(actionItem.Http.Url), content);
                      
                        break;
                    case UssdActionHttpMethod.Get:
                        result = await restClient.GetAsync(new Uri(actionItem.Http.Url));
                        break;
                    case UssdActionHttpMethod.Delete:
                        result = await restClient.DeleteAsync(new Uri(actionItem.Http.Url));
                      
                        break;
                    case UssdActionHttpMethod.Patch:
                        break;
                    default:
                        throw new ArgumentOutOfRangeException();
                }

                if (result==null)
                {
                    return resp;
                }

                
                var serverResp = await result.Content.ReadAsStringAsync();
                
                if (result.IsSuccessStatusCode)
                {
                    resp = new Tuple<HttpStatusCode, JObject>(HttpStatusCode.OK, JObject.Parse(serverResp));
                }
                else
                {
                    resp = new Tuple<HttpStatusCode, JObject>(result.StatusCode, JObject.Parse(serverResp));
                }
            }
            catch (Exception exception)
            {
                resp = new Tuple<HttpStatusCode, JObject>(HttpStatusCode.ExpectationFailed, JObject.FromObject(new {exception.Message}));
            }

            return resp;
        }