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()
{
/*
//sam test
BMXNetSocketConnectionSpec spec = new BMXNetSocketConnectionSpec();
spec.Server = this.ConnectionSettings.DefaultConnectionSpec.Server;
spec.Port = this.ConnectionSettings.DefaultConnectionSpec.Port;
var broker = new BMXNetSocketBroker();
broker.ConnectionSpec = spec;
var initcxn = new BMXNetSessionSocketConnection(broker);
initcxn.ConnectionSpec = spec;
initcxn.OpenConnectionCommon();
initcxn.IsConnected = true;
string txt = initcxn.TransmitRPC("XUS INTRO TEXT", "");
//end test
*/
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
}
}