using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using System.Xml; using System.Globalization; using System.Xml.Linq; using HeuristicLab.Services.Optimization.ControllerService.Azure; using HeuristicLab.Services.Optimization.ControllerService.Interfaces; using System.Diagnostics; namespace HeuristicLab.Services.Optimization.ControllerService { public class ScenarioParser { private static IList scenarios; private static object lockable = new object(); private IDataAccessLayer dal = DataAccessLayerProvider.GetLayer(); public IList Scenarios { get { if (scenarios == null) { lock (lockable) { if (scenarios == null) { ParseScenarios(); } } } return scenarios; } } public Model.OptimizationScenario GetByName(string name) { foreach (var scen in Scenarios) { if (scen.Id == name) { return scen; } } return null; } /*// http://www.sascha-dittmann.de/post/Webseitenpfade-einer-Windows-Azure-Web-Rolle-bestimmen.aspx private static IEnumerable WebSiteDirectories { get { var roleRootDir = Environment.GetEnvironmentVariable("RdRoleRoot"); if (roleRootDir == null) return Enumerable.Empty(); XNamespace roleModelNs = "http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition"; var roleModelDoc = XDocument.Load(Path.Combine(roleRootDir, "RoleModel.xml")); if (roleModelDoc.Root == null) return Enumerable.Empty(); var sites = roleModelDoc.Root.Element(roleModelNs + "Sites"); if (sites == null) return Enumerable.Empty(); var siteElements = sites.Elements(roleModelNs + "Site"); return from siteElement in siteElements where siteElement.Attribute("name") != null && siteElement.Attribute("name").Value == "Web" && siteElement.Attribute("physicalDirectory") != null select Path.Combine(roleRootDir, siteElement.Attribute("physicalDirectory").Value); } } */ private void ParseScenarios() { var scens = new List(); /*string path; if (WebSiteDirectories.Count() != 0) { path = WebSiteDirectories.FirstOrDefault() + @"\Mappings"; } else { path = AppDomain.CurrentDomain.BaseDirectory + @"\Mappings"; } foreach (var file in Directory.EnumerateFiles(path, "*.xml")) { var scenario = ParseScenarioFromFile(file); if (scenario != null) scens.Add(scenario); }*/ var scenarioDao = dal.ScenarioDao; var blobDao = dal.BlobDao; foreach (var entity in scenarioDao.GetAllEntities()) { var scenarioXml = blobDao.FindByKey(entity.Scenario).Text; var scenario = ParseScenarioFromXml(scenarioXml); if (scenario != null) scens.Add(scenario); } scenarios = scens; } private XmlReaderSettings GetSettings() { // Set the validation settings. XmlReaderSettings settings = new XmlReaderSettings(); settings.ValidationType = ValidationType.Schema; settings.Schemas.Add("urn:scenario-schema", AppDomain.CurrentDomain.BaseDirectory + @"\Mappings\scenario.xsd"); return settings; } public Model.OptimizationScenario ParseScenarioFromXml(string xml) { //using (var reader = XmlReader.Create(new StringReader(xml), GetSettings())) { return ParseScenario(new StringReader(xml)); //} } /* private Model.OptimizationScenario ParseScenarioFromFile(string filename) { using (var reader = XmlReader.Create(new FileStream(filename, FileMode.Open), GetSettings())) { return ParseScenario(reader); } } */ private Model.Problem ParseProblem(XmlReader reader) { var problem = new Model.Problem(); while (reader.Read()) { if (reader.NodeType == XmlNodeType.EndElement) break; if (reader.Name == "parameters") problem.Parameters.Items = ParseParameters(reader); } return problem; } private void ParseAlgorithms(out IList algos, XmlReader reader) { algos = new List(); var depth = reader.Depth; do { if (reader.Name == "algorithm" && reader.Depth == depth) { var innerAlg = new Model.Algorithm(); algos.Add(innerAlg); innerAlg.Mapper = reader.GetAttribute("mapper"); reader.Read(); for (;;) { if (reader.Name == "algorithm" && reader.NodeType == XmlNodeType.EndElement) break; if (reader.Name == "parameters" && reader.NodeType == XmlNodeType.Element) { innerAlg.Parameters.Items = ParseParameters(reader); continue; } else if (reader.Name == "problem" && reader.NodeType == XmlNodeType.Element) { innerAlg.Problem = ParseProblem(reader); continue; } else if (reader.Name == "algorithm" && reader.NodeType == XmlNodeType.Element) { IList childAlgos; ParseAlgorithms(out childAlgos, reader); innerAlg.ChildAlgorithms = childAlgos; //TODO: Test with child algorithms continue; } reader.Read(); } } } while (reader.Read() && reader.Depth >= depth); } private Model.OptimizationScenario ParseScenarioElement(XmlReader reader) { var scenario = new Model.OptimizationScenario(); var depth = reader.Depth; while (reader.Depth >= depth) { if (reader.Name == "scenario" && reader.NodeType == XmlNodeType.EndElement) break; if (reader.Name == "name") { scenario.Id = reader.ReadElementContentAsString(); continue; } else if (reader.Name == "algorithm") { IList algos; ParseAlgorithms(out algos, reader); scenario.Algorithm = algos; continue; } reader.Read(); } return scenario; } private Model.OptimizationScenario ParseScenario(StringReader str) { // Set the validation settings. bool isErrorPresent = false; var settings = GetSettings(); settings.ValidationEventHandler += (sender, args) => { Trace.WriteLine(args.Message); isErrorPresent = true; }; Model.OptimizationScenario scenario = null; using (var reader = XmlReader.Create(str, settings)) { while (!reader.EOF) { if (reader.Name == "scenario" && reader.NodeType == XmlNodeType.Element) { scenario = ParseScenarioElement(reader); } reader.Read(); } } if (isErrorPresent) return null; return scenario; } struct ValueEntry { public double v1; public double v2; }; private void ParseDecimalMatrix(Model.DecimalMatrix matrix, XmlReader reader) { IList ventries = new List(); while (reader.Read()) { if (reader.Name == "param") break; if (reader.Name == "value") { var val1 = Convert.ToDouble(reader.GetAttribute("v1"), CultureInfo.InvariantCulture.NumberFormat); var val2 = Convert.ToDouble(reader.GetAttribute("v2"), CultureInfo.InvariantCulture.NumberFormat); ventries.Add(new ValueEntry() { v1 = val1, v2 = val2 }); } } double[][] mat = new double[ventries.Count][]; int i=0; foreach (var entry in ventries) { mat[i] = new double[2]; mat[i][0] = entry.v1; mat[i][1] = entry.v2; i++; } matrix.Value = mat; } private IList ParseParameters(XmlReader reader) { IList parameters = new List(); while (reader.Read()) { if (reader.Name == "parameters" && reader.NodeType == XmlNodeType.EndElement) break; // parse parameter if (reader.Name == "param" && reader.NodeType == XmlNodeType.Element) { var param = new Model.Parameter(); var typeAtt = reader.GetAttribute("type"); param.Type = (Model.ParameterType)Enum.Parse(typeof(Model.ParameterType), typeAtt); switch (param.Type) { case Model.ParameterType.Boolean: param.Value = new Model.BoolValue() { Name = reader.GetAttribute("name"), Value = Convert.ToBoolean(reader.GetAttribute("value")) }; break; case Model.ParameterType.Integer: case Model.ParameterType.Percent: case Model.ParameterType.Decimal: //TODO: Check which comma char is being used; enhance to use any param.Value = new Model.DecimalValue() { Name = reader.GetAttribute("name"), Value = Convert.ToDouble(reader.GetAttribute("value"), CultureInfo.InvariantCulture.NumberFormat) }; break; case Model.ParameterType.DecimalMatrix: var decMatrix = new Model.DecimalMatrix() { Name = reader.GetAttribute("name") }; ParseDecimalMatrix(decMatrix, reader); param.Value = decMatrix; break; case Model.ParameterType.DecimalVector: var decVec = new Model.DecimalVector() { Name = reader.GetAttribute("name") }; ParseDecimalVector(decVec, reader); param.Value = decVec; break; case Model.ParameterType.Type: var type = new Model.TypeValue() { Name = reader.GetAttribute("name") }; ParseType(type, reader); param.Value = type; break; case Model.ParameterType.String: param.Value = new Model.StringValue() { Name = reader.GetAttribute("name"), Value = reader.GetAttribute("value") }; break; default: Console.WriteLine("Unhandled model type: " + param.Type); break; } parameters.Add(param); } } return parameters; } private void ParseType(Model.TypeValue type, XmlReader reader) { var choices = new List(); string selected = null; while (reader.Read()) { if (reader.Name == "param") break; if (reader.Name == "choice") { var choice = reader.GetAttribute("name"); if (reader.HasAttributes && Convert.ToBoolean(reader.GetAttribute("selected"))) { selected = choice; } choices.Add(choice); } } type.Options = choices.ToArray(); type.Value = selected; } private void ParseDecimalVector(Model.DecimalVector decVec, XmlReader reader) { var entries = new List(); //IList ventries = new List(); while (reader.Read()) { if (reader.Name == "param") break; if (reader.Name == "value") { var val1 = Convert.ToDouble(reader.GetAttribute("v1"), CultureInfo.InvariantCulture.NumberFormat); entries.Add(val1); } } decVec.Value = entries.ToArray(); } } }