using System; using System.Collections.Generic; using System.Text; using IndianHealthService.BMXNet.Model; using IndianHealthService.BMXNet.WinForm.Model; using IndianHealthService.BMXNet.WinForm.Services; using IndianHealthService.BMXNet.WinForm.Configuration; using IndianHealthService.BMXNet.Net; using System.IO; using System.IO.IsolatedStorage; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Soap; using System.Reflection; using System.Security.Policy; using System.Xml; using System.Data; using System.Globalization; using System.Windows.Forms; using IndianHealthService.BMXNet.Forms; using IndianHealthService.BMXNet.Ado; using System.Threading; using IndianHealthService.BMXNet.Services; namespace IndianHealthService.BMXNet.WinForm { /// /// Instance manages the context/access to RPMS /// - Configuration information /// - Login entry points /// - External changes to patient context /// /// public class WinFramework : Log { private Log _log = new NullLog(); /// /// Logger to be used by all BMX objects. /// public Log Log { get { return _log; } set { _log = value; } } public static WinFramework EasyLogin(IWin32Window aUiOwnerForPositioningDialog, params string[] configKeys) { WinFramework easyFramework = CreateWithNetworkBroker(true, new NullLog()); easyFramework.LoadConnectionSpecs(LocalPersistentStore.CreateDefaultStorage(true), configKeys); LoginProcess login = easyFramework.CreateLoginProcess(); if (login.HasDefaultConnectionWithUseWindowsAuth && login.AttemptWindowsAuthLogin()) { login.AttemptWindowsAuthLogin(); } if (!login.WasLoginAttempted || !login.WasSuccessful) { login.AttemptUserInputLogin("RPMS Login", 3, true, aUiOwnerForPositioningDialog); } easyFramework.Login = login; return easyFramework; } public RemoteSessionPool RemoteSessionPool { get { return this.Broker.RemoteSessionPool; } } public static WinFramework CreateWithNetworkBroker() { return WinFramework.CreateWithNetworkBroker(false, new NullLog()); } public static WinFramework CreateWithNetworkBroker(bool parseCommandLineArguments) { return WinFramework.CreateWithNetworkBroker(parseCommandLineArguments, new NullLog()); } public static WinFramework CreateWithNetworkBroker(bool parseCommandLineArguments, Log aLogger) { WinFramework framework = new WinFramework(); framework.Log = aLogger; framework.HardCodedSettings = new Settings(); if (parseCommandLineArguments) { Settings commandLineSettings = new CommandLineArguments().ParseSlashKeyValue(Environment.GetCommandLineArgs(), true); commandLineSettings.BackupSettings = framework.HardCodedSettings; framework.BootStrapSettings = commandLineSettings; } else { framework.BootStrapSettings = framework.HardCodedSettings; } return framework; } /// /// Ping the server, will reset read-timeout /// /// public double ImHereServer() { return this.SocketBroker.ImHereServer(); } private Settings _hardCodedSettings = null; public Settings HardCodedSettings { get { return _hardCodedSettings; } set { _hardCodedSettings = value; } } private Settings _bootStrapSettings = new Settings(); public Settings BootStrapSettings { get { return _bootStrapSettings; } set { _bootStrapSettings = value; } } public Settings Settengs { get { return this.BootStrapSettings; } } private RpmsConnectionSettings _connectionSettings = null; public RpmsConnectionSettings ConnectionSettings { get { return _connectionSettings; } set { _connectionSettings = value; } } private BMXNetBroker _socketBroker = null; internal BMXNetBroker SocketBroker { get { if (_socketBroker == null) { if (this.BootStrapSettings.Get("UseBMXNetSocketBroker", true)) { this.SocketBroker = BMXNetBroker.CreateSocketBroker(); this.SocketBroker.Log = (Log)this; } } return _socketBroker; } set { _socketBroker = value; } } private BMXNetBroker _broker = null; internal BMXNetBroker Broker { get { if (_broker == null) { return this.SocketBroker; } return _broker; } set { _broker = value; } } private LoginProcess _login = null; public LoginProcess Login { get { return _login; } set { if (this.Login != null) { this.Close(); } _login = value; if (this.Login != null) { if (this.Login.WasSuccessful) { this.Start(this.Broker.PrimaryRemoteSession); } } } } private RemoteSession _primaryRemoteSession = null; public RemoteSession PrimaryRemoteSession { get { return _primaryRemoteSession; } set { _primaryRemoteSession = value; } } public LocalSession LocalSession { get { return (LocalSession)this.FrameworkSession; } } private WinSession _brokerSession = null; internal WinSession FrameworkSession { get { return _brokerSession; } set { _brokerSession = value; } } private List _sessions = new List(); internal List Sessions { get { return _sessions; } set { _sessions = value; } } public static WinFramework OpenOn(RemoteSession aSession) { WinFramework framework = new WinFramework(); framework.Start(aSession); return framework; } public void TriggerLocalEvent(String anEvent, String eventInfo) { this.FrameworkSession.TriggerEvent(anEvent, eventInfo); } internal void Start(RemoteSession aSession) { this.PrimaryRemoteSession = aSession; WinUser user = new WinUser(); user.RemoteSession= this.PrimaryRemoteSession; user.Name = ((BMXNetRemoteSession)aSession).AuthenicatedUserName; user.Ien = ((BMXNetRemoteSession)aSession).AuthenicatedDuz; this._user = user; this.Broker.User = user; WinSession session = new WinSession(); session.Framework = this; WinContext context = new WinContext(); context.User = user; session.Open(this, context); this.Sessions.Add(session); this.FrameworkSession = session; context.ChangePatient(this.FrameworkSession.Context.Patient); context.ChangeVisit(this.FrameworkSession.Context.Visit); } private EventRegistry _eventRegistry = new EventRegistry(); internal EventRegistry EventRegistry { get { return _eventRegistry; } set { _eventRegistry = value; } } public bool ChangePatient(Patient aPatient, bool force) { bool canChange = true; foreach (WinSession each in this.Sessions) { canChange = canChange && each.DesktopContext.RequestCanChangePatient(aPatient,force); } if (canChange) { foreach (WinSession each in this.Sessions) { each.DesktopContext.ChangePatient(aPatient); } } return canChange; } public bool ChangeVisit(Visit aVisit, bool force) { bool canChange = true; foreach (WinSession each in this.Sessions) { canChange = canChange && each.DesktopContext.RequestCanChangeVisit(aVisit, force); } if (canChange) { foreach (WinSession each in this.Sessions) { each.DesktopContext.ChangeVisit(aVisit); } } return canChange; } public bool ChangeVisit(Visit aVisit) { return this.ChangeVisit(aVisit, false); } public bool ChangePatient(Patient aPatient) { return this.ChangePatient(aPatient, false); } public Context Context { get { return this.FrameworkSession.Context; } } internal ChangableContext ChangableContext { get { return (ChangableContext)this.FrameworkSession.Context; } } private User _user = null; public User User { get { return _user; } } public DataTable DivisionTable(User aUser) { return this.DivisionTable(aUser.Duz); } public DataTable DivisionTable(String anIen) { return this.PrimaryRemoteSession.TableFromCommand("BMXGetFacRS^" + anIen); } void future_Returned(object sender, DataTableFutureEventArgs e) { DataTable peek = e.Future.Result; } internal List Divisions(User aUser) { return this.Divisions(aUser.Duz); } internal List Divisions(String anIen) { DataTable data = this.DivisionTable(anIen); List answer = new List(); foreach (DataRow each in data.Rows) { WinDivision division = new WinDivision(); division.Ien = each["FACILITY_IEN"].ToString(); division.Name = each["FACILITY_NAME"].ToString(); division.MostRecentLookup = "1".Equals(each["MOST_RECENT_LOOKUP"].ToString()); answer.Add((SelectableDivision)division); } return answer; } public bool SetDivision(String aDivisionIen) { DataTable data = this.PrimaryRemoteSession.TableFromCommand("BMXSetFac^" + aDivisionIen); if (data.Rows.Count == 1) { String duz2 = data.Rows[0]["FACILITY_IEN"].ToString(); if ("0".Equals(duz2)) { return false; } else { WinDivision division = new WinDivision(); division.Ien = duz2; division.Name = data.Rows[0]["FACILITY_NAME"].ToString(); (this.User as WinUser).Division = division; this.ChangePatient(null); return true; } } else { return false; } } public bool SetDivision(Division aDivision) { return this.SetDivision(aDivision.Ien); } /// /// Answer true if changed, false if the same /// /// /// /// public bool AttemptUserInputSetDivision(string aDialogTitle, IWin32Window aUiOwnerForPositioningDialog) { ChangeDivisionDialog dialog = new ChangeDivisionDialog(); dialog.Divisions = this.Divisions(this.User); if (aDialogTitle != null) { dialog.Text = aDialogTitle; } if (aUiOwnerForPositioningDialog == null) { dialog.StartPosition = FormStartPosition.CenterScreen; } if (dialog.ShowDialog(aUiOwnerForPositioningDialog) == DialogResult.OK) { //This isn't really an optimization but rather if ((this.User.Division != null) && dialog.SelectedDivision.Equals(this.User.Division)) { return true; } if (this.SetDivision(dialog.SelectedDivision)) { return true; } else { MessageBox.Show(aUiOwnerForPositioningDialog, "Unable to set division. Please try again or contact your helpdesk.", "RPMS RPC Error"); return this.AttemptUserInputSetDivision(aDialogTitle, aUiOwnerForPositioningDialog); } } else { return false; } } public void Close() { if (this.Broker != null) { this.Broker.Close(); } if (this.FrameworkSession != null) { this.FrameworkSession.Close(); } } protected object GetTypeFromEvidence(Evidence evidence, Type aType) { foreach (object each in evidence) { if (each.GetType() == aType) { return each; } } return null; } protected object GetAssemblyIdentityFromEvidence(Evidence evidence) { return GetTypeFromEvidence(evidence, typeof(Publisher)) ?? GetTypeFromEvidence(evidence, typeof(StrongName)) ?? GetTypeFromEvidence(evidence, typeof(Url)); } protected RpmsConnectionSpec RetrievePriorBMXConfiguration(Assembly priorAssemblyReadFromFile) { try { object identity = this.GetAssemblyIdentityFromEvidence(priorAssemblyReadFromFile.Evidence); using (IsolatedStorageFile isStore = IsolatedStorageFile.GetStore(IsolatedStorageScope.User | IsolatedStorageScope.Assembly, null, identity)) { string sFileName = "mserver0200.dat"; String[] peeks = isStore.GetFileNames("*.*"); using (Stream stStorage = new IsolatedStorageFileStream(sFileName, FileMode.Open, isStore)) { XmlDocument doc = new XmlDocument(); doc.Load(stStorage); //Deserializing is yucky because SOAP XML is assembly version specific //Peek into doc and grab values RpmsConnectionSpec spec = new RpmsConnectionSpec(); spec.Name = "Current Connection"; spec.IsDefault = true; spec.Server = doc.GetElementsByTagName("m_sAddress").Item(0).InnerText; int port = 0; int.TryParse(doc.GetElementsByTagName("m_nPort").Item(0).InnerText, out port); spec.Port = port; spec.NameSpace = doc.GetElementsByTagName("m_sNamespace").Item(0).InnerText; return spec; } } } catch { return null; } } public void LoadConnectionSpecsAndMergeWithExistingBMXConfiguration(Assembly priorAssemblyReadFromFile, PersistentStore aPersistentStore, params string[] keys) { this.LoadConnectionSpecs(aPersistentStore, keys); if (this.ConnectionSettings.ConnectionSpecs.Count == 0) { RpmsConnectionSpec spec = this.RetrievePriorBMXConfiguration(priorAssemblyReadFromFile); if (spec != null) { this.ConnectionSettings.AddConnectionSpec(spec); this.ConnectionSettings.Save(); } } } public void LoadSettings(PersistentStore aPersistentStore, params string[] keys) { Settings settings = new Settings(); settings.Store = aPersistentStore; settings.StorageKeys = keys; settings.WillPersistFutureSets = true; settings.Load(); settings.BackupSettings = this.HardCodedSettings; this.BootStrapSettings.BackupSettings = settings; } public void LoadConnectionSpecs(PersistentStore aPersistentStore, params string[] keys) { RpmsConnectionSettings settings = new RpmsConnectionSettings(); settings.Store = aPersistentStore; settings.StorageKeys = keys; settings.Load(); //Look for: /rpms:Server,Port,[Connection Name],[Namespace] String[] commandLineSpecParts = this.BootStrapSettings.Get("rpms", "").Split(new char[] { ',' }); if (commandLineSpecParts.Length >= 2) { RpmsConnectionSpec spec = new RpmsConnectionSpec(); spec.Name = "[Command-Line Connection]"; spec.Server = commandLineSpecParts[0]; spec.UseDefaultNamespace = true; spec.UseWindowsAuthentication = false; int port = 0; if (int.TryParse(commandLineSpecParts[1], out port)) { spec.Port = port; settings.CommandLineConnectionSpec = spec; } if (commandLineSpecParts.Length >= 3) { spec.Name = commandLineSpecParts[2]; if (commandLineSpecParts.Length >= 4) { spec.NameSpace = commandLineSpecParts[3]; spec.UseDefaultNamespace = spec.NameSpace.Length == 0; } else { spec.UseDefaultNamespace = true; } if (commandLineSpecParts.Length >= 5) { spec.UseWindowsAuthentication= commandLineSpecParts[4].Equals("Win",StringComparison.InvariantCultureIgnoreCase); if (commandLineSpecParts.Length >= 6) { int timeOut = 0; if (int.TryParse(commandLineSpecParts[5], out timeOut)) { spec.ReceiveTimeout= timeOut; } if (commandLineSpecParts.Length >= 7) { if (int.TryParse(commandLineSpecParts[6], out timeOut)) { spec.SendTimeout= timeOut; } } } } } } String connectionName = this.BootStrapSettings.Get("connection", "").Trim(); if (connectionName.Length > 0) { foreach (RpmsConnectionSpec each in settings.ConnectionSpecs) { if (each.Name.Equals(connectionName, StringComparison.InvariantCultureIgnoreCase)) { settings.DefaultConnectionSpec = each; break; } } } this.ConnectionSettings = settings; } public LoginProcess CreateLoginProcess() { return new LoginProcess(this); } public Patient FindPatient(String aSearchString) { this.Log.Log("BMX WIN", "Info", "FindPatient > " + aSearchString); List patients = this.FindPatients(aSearchString, 2); return patients.Count == 1 ? patients[0] : null; } public List FindPatients(String aSearchString, int max) { this.Log.Log("BMX WIN", "Info", "FindPatients > " + aSearchString + ", " + max.ToString()); DataTable data = this.FindPatientsAsTable(aSearchString, max); //this.Bmx.TableFromCommand("BMX FIND PATIENT^" + aSearchString.ToUpper() + "|" + max.ToString()); ; List answer = new List(); foreach (DataRow each in data.Rows) { WinPatient patient = new WinPatient(); patient.Ien = each["IEN"].ToString(); patient.PatientName = each["PATIENTNAME"].ToString(); patient.Sex = each["SEX"].ToString(); patient.HealthRecordNumber = each["CHART"].ToString(); patient.Age = int.Parse(each["AGE"].ToString()); patient.Ssn = each["SSN"].ToString(); //patient.????= each["CLASSBEN"].ToString(); //patient.????= each["REG"].ToString(); //patient.????= each["LASTUPDATE"].ToString(); DateTime dob; if (DateTime.TryParse(each["DOB"].ToString(), out dob)) { patient.Dob = dob; }; answer.Add(patient); } return answer; } public DataTable FindPatientsAsTable(String aSearchString, int max) { this.Log.Log("BMX WIN", "Info", "FindPatientsAsTable > " + aSearchString + ", " + max.ToString()); return this.PrimaryRemoteSession.TableFromCommand("BMX FIND PATIENT^" + aSearchString + "|" + max.ToString()); } public DataTable VisitsAsTable(Patient aPatient, int aMax) { return this.VisitsAsTable(aPatient.Ien, aMax); } public DataTable VisitsAsTable(String aDFN, int aMax) { return this.PrimaryRemoteSession.TableFromCommand("BMX FIND VISIT^" + aDFN + "|" + aMax.ToString()); ; } public List Visits(Patient aPatient, int aMax) { return this.Visits(aPatient.Ien, aMax); } public List Visits(String aDFN, int aMax) { DataTable data = this.VisitsAsTable(aDFN, aMax); List answer = new List(); foreach (DataRow each in data.Rows) { WinVisit visit = new WinVisit(); visit.Ien = each["VISIT_IEN"].ToString(); visit.ProviderName = each["PRIMARY_PROVIDER"].ToString(); visit.Clinic = each["CLINIC"].ToString(); visit.LocationName = each["LOCATION"].ToString(); visit.ServiceCategory = each["SERVICE CATEGORY"].ToString(); visit.VisitType = each["VISIT_TYPE"].ToString(); DateTime date; String[] formats = new string[] { "MMM dd, yyyy@HH:mm", "MMM d, yyyy@HH:mm", "MMM d,yyyy@HH:mm", "MMM d, yyyy@H:mm", "MMM d,yyyy@H:mm", "MMM dd,yyyy@HH:mm" }; String dateText = each["TIMESTAMP"].ToString(); if (DateTime.TryParseExact(dateText, formats, CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces, out date)) { visit.DateTime = date; } else if (DateTime.TryParse(dateText, out date)) { visit.DateTime = date; } answer.Add(visit); } return answer; } internal void Close(WinSession winSession) { if (this.Broker != null) { this.Broker.Close(); } } #region ILog Members public bool IsLogging { get { return this.Log.IsLogging; } set { this.Log.IsLogging = value; } } void Log.Log(string aClass, string aCategory, params string[] lines) { this.Log.Log(aClass, aCategory, lines); } void Log.Log(string aClass, string aCategory, Exception anException, params string[] lines) { this.Log.Log(aClass, aCategory, anException, lines); } #endregion } }