using System; using System.Collections; using System.Linq; using System.Diagnostics; using DHI.OpenMI2.Sdk.Backbone; using OpenDA.DotNet.AdditionalInterfaces; using OpenMI.Standard2.TimeSpace; using System.Xml.Linq; using System.Xml; using System.IO; using DHI.MikeShe.Engine; using DHI.OpenMI2.MikeShe; using DHI.DHIfl; namespace MikeSheInOpenDA { public class MikeSheOpenMIModelFactory : IOpenDaModelProvider { private static int _instanceCounter; private string _omiFileRef; private string _msheFileName; /// /// The path should point to where the OMI-file is located. /// The first args is the omi file name without path. /// /// /// public void Initialize(string workingDirPath, params string[] args) { /* Read OpenMI MikeShe specific configuration * name and directory of the Mike-She inputfile * time configuration (precicion of time handling) (may-be from the java side) * buffering of exchageItems * whether or not to copy the models * which exchangeItems to consider C:\some\path\model.she false Name1;Name2;Name3 */ _omiFileRef = Path.Combine(workingDirPath, args[0]); //Get the she file name Hashtable properties = new Hashtable(); XmlTextReader reader = new XmlTextReader(_omiFileRef); while (reader.Read()) { if (reader.LocalName.Equals("Argument")) { string key = reader.GetAttribute("Key"); string value = reader.GetAttribute("Value"); if (key != null && value != null) properties.Add(key, value); } } _msheFileName = Path.Combine(properties["SetupPath"].ToString(), properties["SetupFileName"].ToString()); } public ITimeSpaceComponent CreateInstance() { // Copy Entire 'base' directory to a new one in the same root directory with instancenumber name DirectoryInfo sourceDirectory = Directory.GetParent(_msheFileName); DirectoryInfo targetDirectory = Directory.GetParent(Directory.GetParent(sourceDirectory.ToString()) + "\\" + _instanceCounter + "\\" + _instanceCounter); CopyDirectory(sourceDirectory, targetDirectory); string correct = targetDirectory.ToString() + "\\" + Path.GetFileName(_omiFileRef); XDocument omi = XDocument.Load(targetDirectory.ToString() + "\\" + Path.GetFileName(_omiFileRef)); var ominamespace = omi.Elements().First().Name.Namespace; var v = omi.Element(XName.Get("LinkableComponent", ominamespace.NamespaceName)).Element(XName.Get("Arguments", ominamespace.NamespaceName)).Elements(); var vv = v.First(var => var.Attribute("Key").Value == "SetupPath").Attribute("Value").Value = targetDirectory.ToString(); omi.Save(targetDirectory.ToString() + "\\" + Path.GetFileName(_omiFileRef)); string newSheFileName = targetDirectory.ToString() + "\\" + Path.GetFileName(_msheFileName); //Preprocess mshe before initializing. Should have put this in the engine years ago string path; DHIRegistry key = new DHIRegistry(DHIProductAreas.COMMON_COMPONNETS, false); key.GetHomeDirectory(out path); Process runner = new Process(); runner.StartInfo.FileName = System.IO.Path.Combine(path, "Mshe_preprocessor.exe"); runner.StartInfo.Arguments = newSheFileName; //ZZZ Change the Working Directory necessary for the SVAT runner.StartInfo.WorkingDirectory = System.IO.Path.GetDirectoryName(newSheFileName); runner.StartInfo.UseShellExecute = false; runner.Start(); runner.WaitForExit(); _instanceCounter++; //Create the mshe engine var mshe = MsheEngineFactory.CreateWM(true); mshe.Initialize(newSheFileName, false); //Create the linkable component WMEngineAccess wm = new WMEngineAccess(); wm.Id = newSheFileName; wm.Initialize(mshe); // For OpenMI 2.0 we need to add a consumer ( a dummy in this case ) for each Output // Exchange Item. Input dummyInput1 = new Input("dummyIn"); foreach (ITimeSpaceOutput actualOutput in wm.EngineOutputItems) { if (actualOutput is ITimeSpaceOutput) { actualOutput.AddConsumer(dummyInput1); } } wm.Prepare(); wm.Update(); return wm; } public void SaveInstance(ITimeSpaceComponent timeSpaceComponent) { //throw new NotImplementedException(); } private string InsertInFileNameAndCopy(string oldFileName, string insertion) { string ext = Path.GetExtension(oldFileName); string newname = oldFileName.Substring(0, oldFileName.Length - ext.Length) + insertion + ext; if (File.Exists(oldFileName)) { File.Copy(oldFileName, newname, true); FileInfo f = new FileInfo(newname); f.IsReadOnly = false; //Will not be possible to owerwrite later if readonly } return newname; } static void CopyDirectory(DirectoryInfo source, DirectoryInfo destination) { if (!destination.Exists) { try { destination.Create(); // Copy all files. FileInfo[] files = source.GetFiles(); foreach (FileInfo file in files) { file.CopyTo(Path.Combine(destination.FullName, file.Name)); } // Process subdirectories. DirectoryInfo[] dirs = source.GetDirectories(); foreach (DirectoryInfo dir in dirs) { // Get destination directory. string destinationDir = Path.Combine(destination.FullName, dir.Name); // Call CopyDirectory() recursively. CopyDirectory(dir, new DirectoryInfo(destinationDir)); } } catch { Console.WriteLine("Problem Copying Directory from: {0} to {1}", source, destination); } } } } }