using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using Microsoft.Win32;
using Com.StellmanGreene.PubMed;
namespace SCGen
{
public partial class Form1 : Form
{
///
/// Roster object
///
private Roster roster;
public Form1()
{
InitializeComponent();
UpdateStatus();
}
///
/// Pop up the About box
///
private void About_Click(object sender, EventArgs e)
{
AboutBox1 aboutBox = new AboutBox1();
aboutBox.ShowDialog(this);
}
private void Form1_Load(object sender, EventArgs e)
{
// Add the version to the status bar
toolStripStatusLabel2.Text = "v" + Application.ProductVersion;
// Set the log filename
LogFilename.Text = (Environment.GetEnvironmentVariable("TMP")
+ ("PublicationHarvester log " + DateTime.Now.Month + "-" + DateTime.Now.Day + "-" + DateTime.Now.Year
+ " " + DateTime.Now.Hour + DateTime.Now.Minute + ".log"));
// Set the initial directory for open file dialog boxes
openFileDialog1.InitialDirectory = AppDomain.CurrentDomain.BaseDirectory;
// Retrieve the DSNs from the registry
GetODBCDataSourceNames();
// Set the DSN dropdown listbox to its last value
string dsn = PubMed.Settings.GetValueString("DSN", String.Empty);
if (!String.IsNullOrEmpty(dsn))
{
DSN.Text = dsn;
}
// Set the people file textbox to its last value
string rosterFile = PubMed.Settings.GetValueString("RosterFile", String.Empty);
if (!String.IsNullOrEmpty(rosterFile))
{
RosterFile.Text = rosterFile;
}
// Set the alternate table checkbox and textbox
bool useAlternateCheckboxValue;
if (!bool.TryParse(PubMed.Settings.GetValueString("UseAlternateTableName", "False"), out useAlternateCheckboxValue))
useAlternateCheckboxValue = false;
useAlternateCheckbox.Checked = useAlternateCheckboxValue;
string alternateTableNameValue = PubMed.Settings.GetValueString("AlternateTableName", "PeoplePublications");
if (!String.IsNullOrEmpty(alternateTableNameValue))
{
alternateTableName.Text = alternateTableNameValue;
}
}
///
/// Retrieve the ODBC DSNs from the registry and populate the DSN dropdown listbox
///
public void GetODBCDataSourceNames()
{
string DropDownListText = DSN.Text;
string str;
RegistryKey rootKey;
RegistryKey subKey;
string[] dsnList;
DSN.Items.Clear();
rootKey = Registry.LocalMachine;
str = "SOFTWARE\\\\ODBC\\\\ODBC.INI\\\\ODBC Data Sources";
subKey = rootKey.OpenSubKey(str);
if (subKey != null)
{
dsnList = subKey.GetValueNames();
DSN.Items.Add("System DSNs");
DSN.Items.Add("================");
foreach (string dsnName in dsnList)
{
DSN.Items.Add(dsnName);
}
subKey.Close();
}
rootKey.Close();
rootKey = Registry.CurrentUser;
str = "SOFTWARE\\\\ODBC\\\\ODBC.INI\\\\ODBC Data Sources";
subKey = rootKey.OpenSubKey(str);
dsnList = subKey.GetValueNames();
if (subKey != null)
{
DSN.Items.Add("================");
DSN.Items.Add("User DSNs");
DSN.Items.Add("================");
foreach (string dsnName in dsnList)
{
DSN.Items.Add(dsnName);
}
subKey.Close();
}
rootKey.Close();
DSN.Text = DropDownListText;
}
///
/// Implement the "..." button to pop up the ODBC administrator (odbcad32.exe)
///
///
///
private void ODBCPanel_Click(object sender, EventArgs e)
{
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.EnableRaisingEvents = false;
proc.StartInfo.FileName = "odbcad32.exe";
proc.Start();
}
///
/// Display the Open File dialog for the Roster file
///
private void RosterFileDialog_Click(object sender, EventArgs e)
{
openFileDialog1.FileName = RosterFile.Text;
openFileDialog1.Filter = "Comma-Delimited Files (*.csv)|*.csv|XML Files (*.xml)|*.xml|All files (*.*)|*.*";
openFileDialog1.Title = "Select the Roster file";
openFileDialog1.CheckFileExists = true;
openFileDialog1.CheckPathExists = true;
DialogResult result = openFileDialog1.ShowDialog();
if (result == DialogResult.Cancel)
return;
RosterFile.Text = openFileDialog1.FileName;
}
///
/// When a DSN is changed, write it to the resgistry
///
private void DSN_SelectedIndexChanged(object sender, EventArgs e)
{
PubMed.Settings.SetValue("DSN", DSN.Text);
UpdateStatus();
}
///
/// When the roster file is changed, write it to the resgistry
///
private void RosterFile_TextChanged(object sender, EventArgs e)
{
PubMed.Settings.SetValue("RosterFile", RosterFile.Text);
UpdateStatus();
}
public void UpdateStatus()
{
try
{
Database UpdateDB = new Database(DSN.Text);
bool TablesCreated;
int NumPeople;
int NumHarvestedPeople;
int NumPublications;
int NumErrors;
UpdateDB.GetStatus(out TablesCreated, out NumPeople, out NumHarvestedPeople, out NumPublications, out NumErrors);
this.TablesCreated.Text = TablesCreated.ToString();
this.TablesCreated.Refresh();
this.People.Text = NumPeople.ToString();
this.People.Refresh();
this.PeopleHarvested.Text = NumHarvestedPeople.ToString();
this.PeopleHarvested.Refresh();
this.PublicationsFound.Text = NumPublications.ToString();
this.PublicationsFound.Refresh();
// People With Errors textbox -- set it to red if there are errors
this.PeopleWithErrors.Text = NumErrors.ToString();
if (NumErrors > 0)
PeopleWithErrors.BackColor = Color.Red;
else
PeopleWithErrors.BackColor = People.BackColor;
this.PeopleNotHarvested.Text = ((int)(NumPeople - NumHarvestedPeople)).ToString();
// People Not Harvested textbox -- set it to red if there are unharvested
// people and the software is not currently processing
if (NumPeople - NumHarvestedPeople > 0)
PeopleNotHarvested.BackColor = Color.Red;
else
PeopleNotHarvested.BackColor = People.BackColor;
// Get the colleague status, enable buttons appropriately
int DiadsFound;
int ColleaguesFound;
int ColleaguesHarvested;
int ColleaguePublications;
int StarsWithColleagues;
ColleagueFinder.GetDBStatus(UpdateDB, out ColleaguesFound, out DiadsFound, out ColleaguesHarvested, out ColleaguePublications, out StarsWithColleagues);
this.DiadsFound.Text = DiadsFound.ToString();
this.ColleaguesFound.Text = ColleaguesFound.ToString();
this.ColleaguesHarvested.Text = ColleaguesHarvested.ToString();
this.ColleaguePublications.Text = ColleaguePublications.ToString();
this.StarsWithColleagues.Text = StarsWithColleagues.ToString();
// Colleagues With Errors textbox -- set it to red if there are errors
// (first check ColleaguesFound so we don't issue this SELECT against a database with no Colleagues table)
if (ColleaguesFound > 0)
{
try
{
NumErrors = UpdateDB.GetIntValue("SELECT Count(*) FROM Colleagues WHERE Error IS NOT NULL");
this.ColleaguesWithErrors.Text = NumErrors.ToString();
}
catch (Exception ex)
{
this.ColleaguesWithErrors.Text = ex.Message;
NumErrors = -1;
}
if (NumErrors != 0)
ColleaguesWithErrors.BackColor = Color.Red;
else
ColleaguesWithErrors.BackColor = People.BackColor;
}
// Enable/disable buttons
if (ColleaguesFound == 0)
{
RetrieveColleaguePublications.Enabled = false;
CopyPublicationsFromAnotherDB.Enabled = false;
}
else
{
RetrieveColleaguePublications.Enabled = true;
CopyPublicationsFromAnotherDB.Enabled = true;
}
if (ColleaguePublications > 0)
RemoveFalseColleagues.Enabled = true;
else
RemoveFalseColleagues.Enabled = false;
// Roster status -- disable buttons if the roster is not loaded
if (roster != null)
{
this.RosterRows.Text = roster.RosterData.Rows.Count.ToString();
FindPotentialColleagues.Enabled = true;
}
else
{
this.RosterRows.Text = "not loaded";
FindPotentialColleagues.Enabled = false;
RetrieveColleaguePublications.Enabled = false;
CopyPublicationsFromAnotherDB.Enabled = false;
}
Application.DoEvents();
}
catch
{
//
}
}
///
/// Read the roster
///
private void ReadRoster_Click(object sender, EventArgs e)
{
if (roster != null)
{
if (MessageBox.Show("The roster is already loaded. Are you sure you want to reload it?",
"Reload the Roster?", MessageBoxButtons.YesNo, MessageBoxIcon.Hand) == DialogResult.No)
return;
}
this.Enabled = false;
this.Cursor = Cursors.WaitCursor;
roster = new Roster(RosterFile.Text);
UpdateStatus();
this.Cursor = Cursors.Default;
this.Enabled = true;
AddLogEntry("Read " + roster.RosterData.Rows.Count.ToString() + " from " + RosterFile.Text);
}
///
/// Generate the colleagues using the Colleagues class
///
private void FindPotentialColleagues_Click(object sender, EventArgs e)
{
// If the tables aren't populated, don't look for colleagues.
Database UpdateDB = new Database(DSN.Text);
bool TablesCreated;
int NumPeople;
int NumHarvestedPeople;
int NumPublications;
int NumErrors;
UpdateDB.GetStatus(out TablesCreated, out NumPeople, out NumHarvestedPeople, out NumPublications, out NumErrors);
if ((!TablesCreated) || (NumPeople == 0) || (NumHarvestedPeople == 0))
{
MessageBox.Show("Please select a database that the Publication Harvester has been run on.", "Specify a Valid Database", MessageBoxButtons.OK, MessageBoxIcon.Stop);
return;
}
// Reset the database by default -- if the user says "Yes" when asked,
// then continue from the previous search.
bool ResetDatabase = true;
if (DiadsFound.Text != "0")
{
if (MessageBox.Show("Colleagues have already been found. Are you sure you want to re-find them (or continue the previous search)?",
"Re-find Colleagues?", MessageBoxButtons.YesNo, MessageBoxIcon.Hand) == DialogResult.No)
return;
if (MessageBox.Show("Should the colleague search continue where it was previously left off? (Click 'No' to reset the database and start finding new colleagues.)",
"Continue from previous search?", MessageBoxButtons.YesNo, MessageBoxIcon.Hand) == DialogResult.Yes)
ResetDatabase = false;
}
this.Enabled = false;
this.Cursor = Cursors.WaitCursor;
Database DB = new Database(DSN.Text);
// Use the ResetDatabase variable to determine whether or not to resume
// a past find. If resuming, get the Setnb's of stars from the StarColleagues
// table so they can be skipped.
if (ResetDatabase)
ColleagueFinder.CreateTables(DB);
DataTable StarSetnbsResult = DB.ExecuteQuery("SELECT StarSetnb FROM StarColleagues");
ArrayList StarSetnbs = new ArrayList();
foreach (DataRow Row in StarSetnbsResult.Rows)
{
if (!(StarSetnbs.Contains(Row[0].ToString())))
StarSetnbs.Add(Row[0].ToString());
}
NCBI ncbi = new NCBI("Medline");
ColleagueFinder finder = new ColleagueFinder(DB, roster, ncbi,
GetPeoplePublicationTableName());
People Stars = new People(DB);
int NumStars = Stars.PersonList.Count;
toolStripProgressBar1.Minimum = 0;
toolStripProgressBar1.Maximum = NumStars;
int Count = 0;
foreach (Person Star in Stars.PersonList)
{
Count++;
toolStripProgressBar1.Value = Count;
statusStrip1.Refresh();
Application.DoEvents();
if (StarSetnbs.Contains(Star.Setnb))
{
AddLogEntry("Already found colleagues for " + Star.Last + " (" + Star.Setnb + "), " + Count.ToString() + " of " + NumStars.ToString());
}
else
{
AddLogEntry("Finding " + Star.Last + " (" + Star.Setnb + "), " + Count.ToString() + " of " + NumStars.ToString());
UpdateStatus();
Person[] Colleagues = finder.FindPotentialColleagues(Star);
}
}
UpdateStatus();
this.Cursor = Cursors.Default;
this.Enabled = true;
}
///
/// Open the log in Notepad
///
private void OpenInNotepad_Click(object sender, EventArgs e)
{
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.EnableRaisingEvents = false;
proc.StartInfo.FileName = "notepad.exe";
proc.StartInfo.Arguments = LogFilename.Text;
proc.Start();
}
///
/// Set the status bar values
///
public void SetProgressBar(int Min, int Max, int Value)
{
toolStripProgressBar1.Minimum = Min;
toolStripProgressBar1.Maximum = Max;
toolStripProgressBar1.Value = Value;
Application.DoEvents();
}
///
/// Add an entry to the log -- write it to the file, add it to the listbox
///
/// Entry to add
public void AddLogEntry(string Entry)
{
// Write the entry to the log file
StreamWriter writer = new StreamWriter(LogFilename.Text, true);
writer.WriteLine(DateTime.Now.ToString() + ": " + Entry);
writer.Close();
// Append it to the log listbox
OpenInNotepad.Enabled = true;
Log.Items.Add(DateTime.Now.ToString() + ": " + Entry);
Log.SelectedIndex = Log.Items.Count - 1;
//this.Refresh();
//Log.Refresh();
statusStrip1.Text = Entry;
Application.DoEvents();
}
///
/// Add an entry to the log and display an error box
///
/// Entry to add
private void AddLogEntryWithErrorBox(string Entry, string ErrorCaption)
{
AddLogEntry(Entry);
MessageBox.Show(Entry, ErrorCaption, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
///
/// Retrieve the publications for found colleagues
///
private void RetrieveColleaguePublications_Click(object sender, EventArgs e)
{
this.Enabled = false;
this.Cursor = Cursors.WaitCursor;
// Set the language restriction
string[] Languages = null;
if (LanguageList.Text != "")
{
Languages = LanguageList.Text.Split(',');
foreach (string Language in Languages)
AddLogEntry("Adding language restriction: " + Language);
}
else
{
AddLogEntry("No language restriction added");
}
Database DB = new Database(DSN.Text);
// Clear any publications left over after an interruption
DB.ExecuteNonQuery(
@"DELETE p.* FROM ColleaguePublications p, Colleagues c
WHERE c.Setnb = p.Setnb
AND c.Harvested = 0"
);
// Clear any errors
int NumberOfErrors = DB.GetIntValue("SELECT Count(*) FROM Colleagues WHERE Error IS NOT NULL");
AddLogEntry("Clearing " + NumberOfErrors.ToString() + " colleagues with errors");
DB.ExecuteNonQuery(
@"DELETE p.* FROM ColleaguePublications p, Colleagues c
WHERE c.Setnb = p.Setnb
AND c.Error IS NOT NULL"
);
DB.ExecuteNonQuery(
@"UPDATE Colleagues
SET Harvested = 0, Error = NULL, ErrorMessage = NULL
WHERE Error IS NOT NULL"
);
NumberOfErrors = DB.GetIntValue("SELECT Count(*) FROM Colleagues WHERE Error = 1");
if (NumberOfErrors != 0)
{
AddLogEntry("WARNING: " + NumberOfErrors + " errors were not cleared!");
}
UpdateStatus();
// Retrieve the publications for each unharvested colleague
NCBI ncbi = new NCBI("Medline");
ColleagueFinder finder = new ColleagueFinder(DB, roster, ncbi,
GetPeoplePublicationTableName());
People Colleagues = new People(DB, "Colleagues");
int Total = Colleagues.PersonList.Count;
int Count = 0;
toolStripProgressBar1.Minimum = 0;
toolStripProgressBar1.Maximum = Total;
foreach (Person person in Colleagues.PersonList)
{
Count++;
toolStripProgressBar1.Value = Count;
statusStrip1.Refresh();
if (person.Harvested == false)
{
AddLogEntry("Harvesting publications for colleague " + person.Last + " (" + person.Setnb + "), " + Count.ToString() + " of " + Total.ToString());
UpdateStatus();
// Check for existing publications in ColleaguePublications
ArrayList Parameters = new ArrayList();
Parameters.Add(Database.Parameter(person.Setnb));
int ExistingPublications = DB.GetIntValue(
"SELECT Count(*) FROM ColleaguePublications WHERE Setnb = ?", Parameters);
if (ExistingPublications > 0)
{
DB.ExecuteNonQuery("UPDATE Colleagues SET Harvested = 1 WHERE Setnb = ?", Parameters);
AddLogEntry(ExistingPublications.ToString() + " publications already exist for colleague " + person.Last + " (" + person.Setnb + "), " + Count.ToString() + " of " + Total.ToString());
}
else
{
Person[] personArray = new Person[1];
personArray[0] = person;
try
{
List allowedPubTypes = new List();
foreach (string type in AllowedPubTypeCategories.Text.Split(','))
allowedPubTypes.Add(int.Parse(type));
finder.GetColleaguePublications(personArray, Languages, allowedPubTypes);
GC.Collect(); // no need to wait for finalizers, because they don't do anything
}
catch (Exception ex)
{
AddLogEntry(ex.Message);
// Set the error for the colleague
Parameters = new ArrayList();
Parameters.Add(Database.Parameter(ex.Message));
Parameters.Add(Database.Parameter(person.Setnb));
DB.ExecuteNonQuery(
@"UPDATE Colleagues
SET Error = 1, ErrorMessage = ?
WHERE Setnb = ?", Parameters);
}
}
UpdateStatus();
}
else
{
AddLogEntry("Already harvested publications for colleague " + person.Last + " (" + person.Setnb + "), " + Count.ToString() + " of " + Total.ToString());
}
}
this.Cursor = Cursors.Default;
this.Enabled = true;
}
private string GetPeoplePublicationTableName()
{
string tableName = useAlternateCheckbox.Checked ? alternateTableName.Text : null;
if (String.IsNullOrEmpty(tableName))
AddLogEntry("Using default PeoplePublication table name");
else
AddLogEntry("Using alternate PeoplePublicationtable name: " + tableName);
return tableName;
}
///
/// Remove any false colleagues from the database
///
private void RemoveFalseColleagues_Click(object sender, EventArgs e)
{
this.Enabled = false;
this.Cursor = Cursors.WaitCursor;
Database DB = new Database(DSN.Text);
int Before = DB.GetIntValue("SELECT Count(*) FROM StarColleagues");
if (useAlternateCheckbox.Checked)
ColleagueFinder.RemoveFalseColleagues(DB, this, alternateTableName.Text);
else
ColleagueFinder.RemoveFalseColleagues(DB, this, "PeoplePublications");
int After = DB.GetIntValue("SELECT Count(*) FROM StarColleagues"); ;
int Removed = Before - After;
AddLogEntry("Removed " + Removed.ToString() + " false colleague" +
((Removed == 1) ? "" : "s"));
UpdateStatus();
this.Cursor = Cursors.Default;
this.Enabled = true;
}
///
/// Pop up the Harvesting Reports dialog box
///
private void GenerateReports_Click(object sender, EventArgs e)
{
if (DSN.Text == "")
{
MessageBox.Show("Please specify a valid ODBC data source that points to a MySQL 5.1 server", "Unable to Initialize Database", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
ReportsDialog reportsDialog = new ReportsDialog();
reportsDialog.DB = new Database(DSN.Text);
reportsDialog.MainForm = this;
this.Enabled = false;
reportsDialog.ShowDialog(this);
this.Enabled = true;
}
private void DSN_Click(object sender, EventArgs e)
{
GetODBCDataSourceNames();
}
///
/// Copy the publications for the square roster
///
private void CopyPublicationsFromAnotherDB_Click(object sender, EventArgs e)
{
this.Enabled = false;
this.Cursor = Cursors.WaitCursor;
CopyPublicationsDialog Dialog = new CopyPublicationsDialog(this, new Database(DSN.Text), AllowedPubTypeCategories.Text);
Dialog.ShowDialog(this);
this.Cursor = Cursors.Default;
this.Enabled = true;
}
private void useAlternateCheckbox_CheckedChanged(object sender, EventArgs e)
{
alternateTableName.Enabled = useAlternateCheckbox.Checked;
PubMed.Settings.SetValue("UseAlternateTableName", useAlternateCheckbox.Checked.ToString());
UpdateStatus();
}
private void alternateTableName_TextChanged(object sender, EventArgs e)
{
PubMed.Settings.SetValue("AlternateTableName", alternateTableName.Text);
UpdateStatus();
}
}
}