1536 lines
43 KiB
C#

/*********************************************************************************************
* Copyright 2002 - Volian Enterprises, Inc. All rights reserved.
* Volian Enterprises - Proprietary Information - DO NOT COPY OR DISTRIBUTE
* ------------------------------------------------------------------------------
* $Workfile: ConvertParadoxROs.cs $ $Revision: 16 $
* $Author: Jsj $ $Date: 8/02/04 11:02a $
*
* $History: ConvertParadoxROs.cs $
*
* ***************** Version 16 *****************
* User: Jsj Date: 8/02/04 Time: 11:02a
* Updated in $/EXE/RefObj/ParadoxConversion
* Bug fix B2004-028 added check of local defined fields when checking if
* the field we are converting is a combo field.
*
* ***************** Version 15 *****************
* User: Kathy Date: 10/15/03 Time: 10:29a
* Updated in $/EXE/RefObj/ParadoxConversion
* Found/fix during debugging of B2003-060 (will go through QA process
* with that bug fix)
*
* ***************** Version 14 *****************
* User: Kathy Date: 3/13/03 Time: 1:15p
* Updated in $/EXE/RefObj/ParadoxConversion
* master different than local field name, use local
*
* ***************** Version 13 *****************
* User: Jsj Date: 1/22/03 Time: 12:49p
* Updated in $/EXE/RefObj/ParadoxConversion
* remove old paradox user and lock files before trying the convert. Was
* not able to open the paradox master file.
*
* ***************** Version 12 *****************
* User: Jsj Date: 1/06/03 Time: 12:56p
* Updated in $/EXE/RefObj/ParadoxConversion
* uses a special ROMASTER.MDB to convert data, will now remove temporary
* TXT files if the DEBUG switch is not passed in.
*
* ***************** Version 11 *****************
* User: Jsj Date: 12/19/02 Time: 9:17a
* Updated in $/EXE/RefObj/ParadoxConversion
* now modifies the VEPROMS INI file if it has a [Graphics] section
*
* ***************** Version 10 *****************
* User: Jsj Date: 12/18/02 Time: 9:01a
* Updated in $/EXE/RefObj/ParadoxConversion
* fix for IP2 and FNP data
*
* ***************** Version 9 *****************
* User: Jsj Date: 12/06/02 Time: 3:20p
* Updated in $/EXE/RefObj/ParadoxConversion
* added Debug and new function to replace invalid characters in the field
* names
*
* ***************** Version 8 *****************
* User: Jsj Date: 12/04/02 Time: 11:01a
* Updated in $/EXE/RefObj/ParadoxConversion
* added logic to handle Parameter Display Data data
*
* ***************** Version 7 *****************
* User: Jsj Date: 11/27/02 Time: 1:39p
* Updated in $/EXE/RefObj/ParadoxConversion
* Handle - and / in field names
*
* ***************** Version 6 *****************
* User: Jsj Date: 10/15/02 Time: 11:39a
* Updated in $/EXE/RefObj/ParadoxConversion
* added "a" to combo field names in non-master tables.
*
* ***************** Version 5 *****************
* User: Jsj Date: 10/04/02 Time: 2:02p
* Updated in $/EXE/RefObj/ParadoxConversion
* added better user interface
*
* ***************** Version 4 *****************
* User: Jsj Date: 9/27/02 Time: 2:57p
* Updated in $/EXE/RefObj/ParadoxConversion
* Fixed Graphic image information storage
*
* ***************** Version 3 *****************
* User: Jsj Date: 9/26/02 Time: 4:17p
* Updated in $/EXE/RefObj/ParadoxConversion
* There was a leading space in all of the field values - is now fixed.
*
* ***************** Version 2 *****************
* User: Jsj Date: 9/25/02 Time: 10:19a
* Updated in $/EXE/RefObj/ParadoxConversion
* added header
*********************************************************************************************/
using System;
using System.Collections;
using System.IO;
using System.Xml;
using System.Windows.Forms; // Application.StartupPath
using System.Diagnostics;
using DBEncapsulation;
using ROFields;
namespace ParadoxConversion
{
/// <summary>
/// This class contains the functions needed to convert the old Paradox RO Database
/// to a newer type database.
/// </summary>
public class ConvertParadoxROs
{
System.Windows.Forms.Label StatusWin;
bool ProcessingMasterTable = false;
bool DoDebugFile = false;
BinaryReader BReader; // read text file as binary (for chars like hard spaces)
BinaryWriter BWrite; // for a debug file
String AppPath;
String ROConvertPath;
String ROPath;
String LineOfText;
String ROTableName, ROTblElmt;
String RecID, RecType, ParentRecID, AccPageID, DateTime, Info, GroupTitle;
int intRecType = 0;
int CurrentFieldType = 0;
int NumCRLFs = 0;
XmlTextWriter xmlTxtWriter = null;
RODBRecordInterface MyDbRec;
ROField NewDbField;
struct FieldInfo
{
public String fldRecID; // Field Record ID
public String fldName; // Field name
public String fldType;
};
ArrayList MasterFieldInfoList = new ArrayList();
ArrayList LocalFieldInfoList = new ArrayList();
struct GroupTitles
{
public String GrpRecID;
public String GrpTitle;
}
ArrayList GroupTitlesList = new ArrayList();
public void OpenTextFile(String FName)
{
BReader = new BinaryReader(File.Open(FName,System.IO.FileMode.Open,System.IO.FileAccess.ReadWrite));
}
public void CloseTextFile()
{
BReader.Close();
}
public String TxF_ReadLine()
{
bool success = true;
String TxFstr = "";
byte rdByte = 0;
if (BReader != null)
{
NumCRLFs = 0;
while (success)
{
try
{
rdByte = BReader.ReadByte();
}
catch (Exception e)
{
success = false;
TxFstr = null;
}
if (rdByte == 0x0D) // carrage return (end of line)
{
NumCRLFs++;
rdByte = BReader.ReadByte(); // read the new line character
if (rdByte == 0x0D) // sometimes there's an extra carrage return
{
rdByte = BReader.ReadByte();
NumCRLFs++;
}
success = false; // to stop the loop
}
if (success)
{
TxFstr += Convert.ToString(Convert.ToChar(rdByte));
}
}
}
return TxFstr;
}
/*** for debugging..... */
public void DEBUG_OpenFile(String FName)
{
if (DoDebugFile)
BWrite = new BinaryWriter(File.Open(FName,System.IO.FileMode.Create,System.IO.FileAccess.ReadWrite));
}
public void DEBUG_CloseFile()
{
if (DoDebugFile)
BWrite.Close();
}
public void DEBUG_Write(string str)
{
if (DoDebugFile)
{
DEBUG_WriteString(str);
DEBUG_WriteString("\n");
}
}
public void DEBUG_WriteString(string str)
{
if (DoDebugFile)
{
int i;
for(i =0; i < str.Length; i++)
{
byte WrByte;
WrByte = (byte)str[i];
BWrite.Write(WrByte);
}
}
}
public void DEBUG_CheckFieldName(string fldname)
{
if (DoDebugFile)
{
char[] tmpstr = fldname.ToCharArray();
int len = fldname.Length;
int cnt = 0;
bool FirstOne = true;
string OKpunch = " -._"; // we're also going to ignore spaces
string outstr = "";
int decval;
while (cnt < len)
{
char tmpchr = tmpstr[cnt];
if(!char.IsLetterOrDigit(tmpchr))
{
if (OKpunch.IndexOf(tmpchr) == -1) // not found
{
if (FirstOne)
{
FirstOne = false;
DEBUG_Write(fldname);
}
decval = tmpchr;
outstr = " " + tmpchr.ToString() +" [" + decval.ToString() + "]";;
DEBUG_Write(outstr);
}
}
cnt++;
}
if (!FirstOne)
DEBUG_Write("----------------\n");
}
}
/** End - For Debugging **/
public ConvertParadoxROs(System.Windows.Forms.Label statWin, bool DoingDebugFile)
{
// Assume we are currently in the RO directory to be converted
// Was it already converted? (check for existance of a backup
// created during the conversion process)
// Yes - return
// else select the new database type
StatusWin = statWin;
DoDebugFile = DoingDebugFile;
ClearFieldStrings();
}
/*
* Initialize the fields to empty strings.
*/
public void ClearFieldStrings()
{
RecID = "";
RecType = "";
ParentRecID = "";
AccPageID = "";
DateTime = "";
Info = "";
}
public void CreateNewRoDatabase()
{
// Prompt user to select the new databaes type (ex Access, SQL Server, etc)
// For now, we will be creating just an Access database.
/*
* Copy our empty ROMaster.mdb file into the CONVERT directory (is the current
* directory at this point) This RomasterCvrt.mdb is located in the VE-PROMS.NET\BIN16
* directory and is different than the ROMaster.mdb in VE-PROM.NET\BIN. The one in the BIN16
* directory does not have any tables, while the one in the BIN directory has an
* ROMASTER table with the default records needed to create RO tables.
*/
String toPath = ROConvertPath + "\\ROMaster.mdb";
String fromPath = AppPath + "16\\RomasterCvrt.mdb";
File.Copy(fromPath,toPath,true); // overwrite the file if already there
// Create an empty database.
MyDbRec = new RODBRecordInterface(1,ROConvertPath);
// Open the database connection
MyDbRec.RODB_OpenConnection();
}
public void CloseNewRoDatabase()
{
MyDbRec.RODB_CloseConnection();
}
/*
* Create a ORIG_RO directory and move everything(except for the CONVERT directory)
* in RO into it. Then move everying in CONVERT into RO.
*/
public void MoveOldROData()
{
Directory.SetCurrentDirectory("..\\");
Directory.Move("RO","ORIG_RO");
Directory.Move("CONVERT","RO");
}
/* This function will create TXT files from the Paradox database (PX2TXT.EXE) then parse
* them and place the RO information in the new database.
*
* Note that the Microsoft Paradox driver could not read our Paradox BLOB fields.
* We had to write a program in the old Borland 16-bit environment that would basically
* dump the RO information into a file that the Microsoft drivers could read. We decided
* to keep things simple and just dump the RO information into text files.
*
* Each line in the text file represents a database record. Each "field" is separated by
* a space. Each "record" has the following fields:
*
* RECORD ID
* RECORD TYPE
* PARENT ID
* ACCPAGE ID
* DATETIME
* The Paradox BLOB data
*/
public void TestMessage()
{
StatusWin.Text = "This is a TEST!";
StatusWin.Refresh();
}
private void StatusMessage(String Mess1)
{
StatusWin.Text = Mess1;
StatusWin.Refresh();
}
private void StatusMessage(String Mess1, String Mess2)
{
StatusWin.Text = Mess1 + Mess2;
StatusWin.Refresh();
}
private void StatusMessage(String Mess1, String Mess2, String Mess3)
{
StatusWin.Text = Mess1 + Mess2 + Mess3;
StatusWin.Refresh();
}
public void ConvertParadoxRODb(string PassedInROPath)
{
// Set the current working directory to my sample RO directory
// Directory.SetCurrentDirectory("G:\\PROMSDAT\\VEWPB\\RO");
// ROPath = "G:\\PROMSDAT\\VEBRAID\\RO";
// Directory.SetCurrentDirectory(ROPath);
ROPath = PassedInROPath;
ROConvertPath = ROPath.Substring(0,ROPath.LastIndexOf("\\"));
ROConvertPath += "\\CONVERT";
// Create text files from the Paradox RO Database
StatusMessage("Paradox to Text Files");
// Get the path of where this executable resides
AppPath = Application.StartupPath;
// append "16\\px2txt.exe" to the path of the VE-PROMS.NET\BIN path
// to get the resulting path: VE-PROMS.NET\BIN16\px2txt.exe
String ToTxtAppPath = AppPath + "16\\px2txt.exe";
/*
* Before we run the PX2TXT.EXE program, delete any Paradox lock files that might
* be hanging around.
*/
File.Delete("Pdoxusrs.net");
File.Delete("Pdoxusrs.lck");
File.Delete("paradox.lck");
// create a process & wait until it exits.
Process myProcess = new Process();
myProcess.StartInfo.FileName = ToTxtAppPath;
myProcess.Start();
myProcess.WaitForExit();
/*
* Now change directory to the CONVERT sub-directory that was created
* from PX2TXT.EXE
*
* This directory should have the TXT files containing the RO data and
* the graphic files (Intergrated Graphics) used in the current RO database.
* Note that some of the graphic files might be converted to a different
* graphics format than what is used in the old RO Editor.
*/
Directory.SetCurrentDirectory(ROConvertPath);
/* The PX2TXT.EXE program also creates a file called PXCONLST.TXT which
* contains a list of the TXT files that it created.
*
* Read the PXCONLST.TXT file. This contains the list of TXT files
* that were generated as the first step to the conversion.
* Place these in a array list for processing.
* Assume that we are in the RO directory that is being converted
*/
string FileName = "Pxconlst.txt";
int numDbs = 0;
ArrayList DbList = new ArrayList();
ArrayList DbTitleList = new ArrayList();
if (!File.Exists(FileName))
{
// Conversion from Paradox to a text file failed.
// **** provide error message ****
StatusMessage("Conversion from Paradox to a text file failed.");
return;
}
OpenTextFile(FileName);
String FileNameTitle; // the title of the ROxxxxxx file
String TextFileName;
while ((FileNameTitle = TxF_ReadLine())!=null)
{
DbTitleList.Add(FileNameTitle);
TextFileName = TxF_ReadLine();
DbList.Add(TextFileName);
numDbs++;
}
CloseTextFile();
// delete the Pxconlst.txt file if we are NOT debugging
if (!DoDebugFile)
File.Delete(FileName);
// Create a new (empty) database
CreateNewRoDatabase();
// DEBUG - write the field names that have problem characters
DEBUG_OpenFile("DebugFieldNames");
// For each file listed in PXCONLST.TXT
// Open the file
// read each line
// (each line represents a record from the old Paradox database)
// translate each line into a database record
System.Collections.IEnumerator myEnumerator = DbList.GetEnumerator();
System.Collections.IEnumerator myTitleEnumerator = DbTitleList.GetEnumerator();
while(myEnumerator.MoveNext())
{
myTitleEnumerator.MoveNext();
// Clear the GroupTitles Array
GroupTitlesList.Clear();
// Clear the LocalFieldInfoList Array
LocalFieldInfoList.Clear();
TextFileName = myEnumerator.Current.ToString();
// Get the RO Table Name (ex. ROMASTER, RO000001)
ROTableName = myEnumerator.Current.ToString();
int slen = ROTableName.Length;
ROTableName = ROTableName.Remove(slen-4,4);
// Create the database table
MyDbRec.RODB_AddNewTable(ROTableName);
if (StringsAreEqualU(ROTableName,"ROMASTER"))
ProcessingMasterTable = true;
else
ProcessingMasterTable = false;
String tmpMess;
tmpMess = "Processing " + myTitleEnumerator.Current.ToString();
StatusMessage(tmpMess);
OpenTextFile(TextFileName); // Open the text file
DEBUG_Write("===================");
DEBUG_Write(tmpMess);
DEBUG_Write(TextFileName);
int cnt = 0;
while ((LineOfText = TxF_ReadLine()) != null)
{
// Process the text line (each line is a record)
ClearFieldStrings();
cnt++;
StatusMessage(tmpMess,"\nRecord: ",Convert.ToString(cnt));
ProcessTextLine();
}
StatusMessage(" ");
CloseTextFile();
// delete the ROxxxx.txt file if we are NOT debugging
if (!DoDebugFile)
File.Delete(TextFileName);
// Close database table
}
// DEBUG - Close Debug file
DEBUG_CloseFile();
CloseNewRoDatabase();
MoveOldROData();
}
/* This function makes a copy of the passed in string, then replaces
* any blank character with an underbar ('_') character.
* The copy is returned.
*/
String StrBlanksToUnderbars(String TheString)
{
String RtnStr = TheString;
RtnStr.Replace(" ", "_");
return RtnStr;
}
/*
* This function compares a String with a (char *) array and returns
* true if they are equal, else it returns false
*/
bool StringsAreEqual(String thisStr, String thatStr)
{
bool StringsAreEqual = false;
StringsAreEqual = (thisStr.CompareTo(thatStr) == 0);
return StringsAreEqual;
}
/*
* This function will first uppercase the strings then compare them
* and returns true if they are equal, else it returns false
*/
bool StringsAreEqualU(String thisStr, String thatStr)
{
String ThisOne = thisStr;
String ThatOne = thatStr;
ThisOne.ToUpper();
ThatOne.ToUpper();
bool StringsAreEqual = false;
StringsAreEqual = (ThisOne.CompareTo(ThatOne) == 0);
return StringsAreEqual;
}
/*
* This function reads up to the next space character (or null)
*/
String GetFieldTxt()
{
String RtnStr = "0";
char[] space = new char[1]{' '};
int txtIdxEnd = LineOfText.IndexOfAny(space); // blank is the end of a the field
if (txtIdxEnd > 0)
{
RtnStr = LineOfText.Substring(0,txtIdxEnd);
LineOfText = LineOfText.Remove(0,txtIdxEnd+1); // remove this "field" from the string
}
else if (LineOfText.Length > 0) // last field in the string
{
RtnStr = LineOfText;
LineOfText = "";
}
return RtnStr;
}
/*
* This function converts the given string to an interger
*/
int GetFieldInt(String TmpStr)
{
int RtnInt;
RtnInt = Convert.ToInt32(TmpStr);
return RtnInt;
}
/* This function will first read the length of the string (number of characters to get)
* Then get the string of that length.
*/
String GetStringByLength()
{
String RtnStr = "";
int len = (int)GetFieldInt(GetFieldTxt());
int LineTextLen = LineOfText.Length;
while (len > LineTextLen)
{
RtnStr += LineOfText + "\r\n"; // need both a '\r' and a '\n'
/* NumCRLFs accounts for the number of "\r\n"s that was originally counted when the text
* file was created.
*/
len -= (LineTextLen + NumCRLFs);
LineOfText = TxF_ReadLine();
if (len == 0)
// end of string had \r\n still may need to remove a blank at the beginning of the string buffer
{
if (LineOfText.StartsWith(" "))
LineOfText = LineOfText.Remove(0,1);
}
LineTextLen = LineOfText.Length;
}
if (len > 0)
{
RtnStr += LineOfText.Substring(0,len);
LineOfText = LineOfText.Remove(0,len+1); // add one to remove following space
}
return RtnStr;
}
/*
* This function builds the field definition string
*/
String GetFieldDefinition()
{
String tmpStr;
String RtnStr = "";
String FieldTypeStr = "";
int FieldType = 0;
String FieldLength = "";
String FieldName = "";
FieldName = GetStringByLength(); // get the field name
FieldName = FixFieldName(FieldName);
NewDbField.SetFieldname(FieldName);
// get the field type
FieldTypeStr = GetFieldTxt();
FieldType = GetFieldInt(FieldTypeStr);
// Save the name and rec id and type in an array
FieldInfo TheFieldInfo = new FieldInfo();
TheFieldInfo.fldName = FieldName;
TheFieldInfo.fldRecID = RecID;
TheFieldInfo.fldType = FieldTypeStr;
if (ProcessingMasterTable)
{
MasterFieldInfoList.Add(TheFieldInfo);
}
else // is a local definition
{
LocalFieldInfoList.Add(TheFieldInfo);
}
NewDbField.SetFieldType((uint)FieldType);
switch (FieldType)
{
case 1: // Fixed Length Text
case 2: // Variable Length Text
case 8: // X/Y Plot
case 0x10: // Table
// Get the field length
FieldLength = GetFieldTxt();
// append/save the Field Name and Field Length to RtnStr
RtnStr += NewDbField.MakeSchemaString(FieldName,FieldLength,"");
break;
case 4: // Formatted Text
String Pattern;
// Get the field length
FieldLength = GetFieldTxt();
// Get the pattern
Pattern = GetStringByLength();
// append/save the Field Name, Length, and Pattern to RtnStr
RtnStr += NewDbField.MakeSchemaString(FieldName,FieldLength,Pattern);
break;
case 0x20: // Image (Intergrated Graphics)
// append/save only the type to RtnStr
RtnStr = NewDbField.MakeImageSchemaString(FieldName);
break;
case 0x40: // Multi Field (used by Parameter Display Data)
RtnStr += FieldName + " " + FieldTypeStr;
tmpStr = GetFieldTxt();
// Create a list of RecIDs separated by a blank
while (!StringsAreEqual(tmpStr,"0")) // while not "0"
{
// append/save the RefRecID to Rtn Str
RtnStr += " " + tmpStr;
tmpStr = GetFieldTxt();
}
if (intRecType == 2)
{
RecType = "4";
intRecType = 4;
}
break;
case 0x100: // Generic Field (reference to a field definition)
tmpStr = GetFieldTxt();
string tmp1 = GetSavedMasterFieldNameAndType(tmpStr).Substring(0,4);
if (tmp1.Equals("128 "))
RtnStr = tmpStr + " " + tmp1 + FieldName + "a";
else
RtnStr = tmpStr + " " + tmp1 + FieldName;
// RtnStr = tmpStr + " " + (GetSavedMasterFieldNameAndType(tmpStr));
break;
case 0x80: // Combo Field
String SingleLineWidth = "";
String MultiLineWidth = "";
String TableWidth = "";
String XYPlotWidth = "";
bool Single = false, Multi = false, Tbl = false, XYPlt = false;
int fldtyp;
do
{
tmpStr = GetFieldTxt();
fldtyp = GetFieldInt(tmpStr);
switch (fldtyp)
{
case 1: // single line text
SingleLineWidth = GetFieldTxt();
Single = true;
break;
case 2: // multi line text
MultiLineWidth = GetFieldTxt();
Multi = true;
break;
case 8: // X/Y Plot
XYPlotWidth = GetFieldTxt();
XYPlt = true;
break;
case 16: // Table
TableWidth = GetFieldTxt();
Tbl = true;
break;
default:
break;
} // end switch
} while (!StringsAreEqual(tmpStr,"0"));
// append/save the Field Type to RtnStr
RtnStr = NewDbField.MakeComboSchemaString(FieldName,Single,SingleLineWidth,Multi,MultiLineWidth,Tbl,TableWidth,XYPlt,XYPlotWidth);
break;
default: // nothing to do
break;
} // end switch
return RtnStr;
}
String GetValueDefinition()
{
String RtnStr = "";
String tmpStr = "";
String tmpStr2 = "";
String tmpStr3 = "";
String RecIDRef = "";
String MenuText = "";
String ValueDefTypeStr = "";
int ValueDefType = 0;
int NumItems;
do
{
ValueDefTypeStr = GetFieldTxt();
ValueDefType = GetFieldInt(ValueDefTypeStr);
switch (ValueDefType)
{
case 1: // Record ID referencing a field record
RecIDRef = GetFieldTxt();
tmpStr = GetSavedLocalFieldName(RecIDRef);
// append/save ValueDefType and RecIDRef to RtnStr
RtnStr += "<" + tmpStr + ">";
break;
case 2: // Text value
tmpStr = GetStringByLength();
tmpStr = FixString(tmpStr);
// append/save ValueDefType and TxtStr to Rtn Str
RtnStr += tmpStr;
break;
case 3: // Decimal allignment field
// append/save RecIDRef, OffSetVal, and Width to RtnStr
RecIDRef = GetFieldTxt();
tmpStr = GetSavedLocalFieldName(RecIDRef);
// append/save ValueDefType and RecIDRef to RtnStr
RtnStr += "<" + tmpStr;
tmpStr = GetFieldTxt();
//int OffSetVal = GetFieldInt(tmpStr);
RtnStr += ","+tmpStr;
tmpStr = GetFieldTxt();
//int Width = GetFieldInt(tmpStr);
RtnStr += ","+tmpStr+">";
break;
case 4: // Menu value definition
MenuText = "";
// number of menu items
tmpStr = GetFieldTxt();
NumItems = GetFieldInt(tmpStr);
tmpStr2 = "";
while (NumItems > 0)
{
// menu text string (maybe)
tmpStr = GetFieldTxt();
if (!StringsAreEqual(tmpStr,"0")) // do we have MenuText?
{
MenuText = GetStringByLength();
MenuText = FixString(MenuText);
}
// append/save ValueDefType, NumItems, tmpStr, and MenuText to RtnStr
// Get list of other ValueDefTypes
tmpStr = GetValueDefinition(); // call itself
// append/save tmpStr to RtnStr
tmpStr2 += "{" + MenuText + "=" + tmpStr + "}";
NumItems--;
}
RtnStr += tmpStr2;
break;
case 5: // Conditional value definition
MenuText = "";
// number of menu items
tmpStr = GetFieldTxt();
NumItems = GetFieldInt(tmpStr);
tmpStr3 = "";
tmpStr2 = "";
while (NumItems > 0)
{
// menu text string (maybe)
tmpStr = GetFieldTxt();
if (!StringsAreEqual(tmpStr,"0")) // do we have MenuText?
{
MenuText = GetStringByLength();
MenuText = FixString(MenuText);
}
// append/save ValueDefType, NumItems, tmpStr, and MenuText to RtnStr
// Get list of other ValueDefTypes
tmpStr = GetValueDefinition(); // call itself
// append/save tmpStr to RtnStr
tmpStr2 += "{" + MenuText + "=" + tmpStr + "}";
NumItems--;
}
// Conditional text???
tmpStr = GetStringByLength();
// append/save tmpStr to RtnStr
tmpStr = FixString(tmpStr);
tmpStr3 = "{" + tmpStr + tmpStr2 + "}";
RtnStr += tmpStr3;
break;
case 6: // VARUSE
tmpStr = GetStringByLength();
tmpStr = FixString(tmpStr);
// append/save ValueDefType and TxtStr to RtnStr
RtnStr += "{" + tmpStr + "}";
break;
case 7: // VARDEFINE
tmpStr2 = GetStringByLength();
tmpStr2 = FixString(tmpStr2);
tmpStr = GetValueDefinition(); // call itself
// append/save ValueDefType, TxtStr, and tmpStr to RtnStr
RtnStr += "{" + tmpStr2 + "=" + tmpStr + "}";
break;
default: // nothing to do
break;
} // end switch
} while (ValueDefType != 0);
/*
* Need to replace '<' with '&lt;' and '>' with '&gt;'
*/
RtnStr = ReplaceGreaterLessSigns(RtnStr);
return RtnStr;
}
/*
* This function returns a string containing a value to an RO field.
*/
String GetFieldValue()
{
String RtnStr;
String tmpStr;
String ValueTypeStr;
int ValueType = 0;
ValueTypeStr = GetFieldTxt();
ValueType = GetFieldInt(ValueTypeStr);
CurrentFieldType = ValueType;
RtnStr = "";
switch (ValueType)
{
case 1: // Text String
case 2: // variable text string
tmpStr = GetStringByLength();
tmpStr = FixString(tmpStr);
RtnStr += tmpStr;
break;
case 0x20: // Image File (Intergrated Graphics)
tmpStr = GetStringByLength(); // image file name
tmpStr = FixString(tmpStr);
String DateTimeStr = GetFieldTxt();
String ImgHeight = GetFieldTxt();
String ImgWidth = GetFieldTxt();
RtnStr += "\r\n<Image_Filename>" + DateTimeStr + " " + tmpStr + "</Image_Filename>\r\n";
RtnStr += "<Image_Height>" + ImgHeight + "</Image_Height>\r\n";
RtnStr += "<Image_Width>" + ImgWidth + "</Image_Width>\r\n";
break;
case 0x40: // Parameter Display Data
tmpStr = GetFieldTxt();
while (!StringsAreEqual(tmpStr,"0"))
{
tmpStr = GetFieldTxt(); // get the RecID of the field
while (!StringsAreEqual(tmpStr,"0"))
{
string FieldName = GetSavedLocalFieldName(tmpStr);
RtnStr += "<" + FieldName+ ">";
RtnStr += GetFieldValue();
RtnStr += "</" + FieldName + ">\r\n";
tmpStr = GetFieldTxt(); // next
}
tmpStr = GetFieldTxt(); // next
}
break;
default:
// should never get into here....
tmpStr = GetStringByLength();
tmpStr = FixString(tmpStr);
RtnStr += tmpStr;
break;
} // end switch
return RtnStr;
}
// Search the local list for the given Record ID
// Return the field name
String GetSavedLocalFieldName(String RecordID)
{
String RtnStr = "";
FieldInfo TmpInfo;
System.Collections.IEnumerator FldLstEnumerator = LocalFieldInfoList.GetEnumerator();
while (FldLstEnumerator.MoveNext() && StringsAreEqual(RtnStr,""))
{
TmpInfo = (FieldInfo)FldLstEnumerator.Current;
if (StringsAreEqual(TmpInfo.fldRecID,RecordID))
RtnStr = TmpInfo.fldName;
}
return RtnStr;
}
// Search the master field list for a the given Record ID
// Return the field name and type if found
String GetSavedMasterFieldNameAndType(String RecordID)
{
String RtnStr = "";
FieldInfo TmpInfo;
System.Collections.IEnumerator FldLstEnumerator = MasterFieldInfoList.GetEnumerator();
while (FldLstEnumerator.MoveNext() && StringsAreEqual(RtnStr,""))
{
TmpInfo = (FieldInfo)FldLstEnumerator.Current;
if (StringsAreEqual(TmpInfo.fldRecID,RecordID))
{
RtnStr = TmpInfo.fldType.PadLeft(3,'0') + " " + TmpInfo.fldName;
if (TmpInfo.fldType.Equals("128")) // is this a combo type?
RtnStr += "a"; // append an "a"
}
}
return RtnStr;
}
/*
* See if the given RECID is referencing a combo field.
*/
bool IsComboFieldType(String fldName)
{
bool IsACombo = false;
bool wasFound = false;
FieldInfo TmpInfo;
System.Collections.IEnumerator LocFldLstEnumerator = LocalFieldInfoList.GetEnumerator();
System.Collections.IEnumerator FldLstEnumerator = MasterFieldInfoList.GetEnumerator();
// Bug fix: B2004-028
// Need to check local list of fields (of this group)
// Then then if not in the local list, check the "global" list
while (!IsACombo && LocFldLstEnumerator.MoveNext())
{
TmpInfo = (FieldInfo)LocFldLstEnumerator.Current;
if (StringsAreEqual(TmpInfo.fldName,fldName))
{
wasFound = true;
if (StringsAreEqual(TmpInfo.fldType,"128"))
IsACombo = true;
}
}
if (!wasFound)
{
while (!IsACombo && FldLstEnumerator.MoveNext())
{
TmpInfo = (FieldInfo)FldLstEnumerator.Current;
if (StringsAreEqual(TmpInfo.fldName,fldName) && StringsAreEqual(TmpInfo.fldType,"128"))
IsACombo = true;
}
}
return IsACombo;
}
String BuildComboFieldName(String FldName)
{
String RtnStr = FldName;
switch (CurrentFieldType)
{
case 1: //Fixed Text
RtnStr += "a";
break;
case 2: // Variable Text
RtnStr += "b";
break;
case 16: // Table
RtnStr += "c";
break;
case 8:
RtnStr += "d";
break;
default:
break;
}
return RtnStr;
}
String GetGroupTitle(String RecordID)
{
String RtnStr = "";
GroupTitles Tmpitem;
System.Collections.IEnumerator GrpLstEnumerator = GroupTitlesList.GetEnumerator();
while (GrpLstEnumerator.MoveNext() && StringsAreEqual(RtnStr,""))
{
Tmpitem = (GroupTitles)GrpLstEnumerator.Current;
if (StringsAreEqual(Tmpitem.GrpRecID,RecordID))
RtnStr = Tmpitem.GrpTitle;
}
return RtnStr;
}
String ReplaceGreaterLessSigns(String InStr)
{
String OutStr = InStr;
OutStr = OutStr.Replace("<","&lt;");
OutStr = OutStr.Replace(">","&gt;");
return OutStr;
}
// Replace any character less than 32 (space) or greater then
// 126 (~) with "&#D;" where D is the decimal value of the character
String ReplaceNonStandardChars(string instring)
{
string outstring = "";
int len = instring.Length;
int i=0;
int substart=0;
ushort decchar;
while (i < len)
{
while (i < len && instring[i] < 127) i++;
outstring += instring.Substring(substart, i-substart);
if (i < len)
{
decchar = instring[i];
outstring += "&#" + decchar.ToString() + ";";
i++;
substart = i;
}
}
return outstring;
}
/*
* String cannot have '&' or '/' chars
* replace them with an '_'
*/
String FixString(String instring)
{
String FixedString = "";
StringWriter strWriter = new StringWriter();
xmlTxtWriter = new XmlTextWriter(strWriter);
xmlTxtWriter.WriteString(instring);
FixedString = strWriter.ToString();
xmlTxtWriter.Close();
// Now replace any character less than 32 (space) or greater then
// 126 (~) with "&#D;" where D is the decimal value of the character
FixedString = ReplaceNonStandardChars(FixedString);
// need to replace the forward slash with an character reference
FixedString = FixedString.Replace("/","&#47;");
/*
* The WriteString method is not replacing the single
* and double quotes. So we will do it manually
*/
FixedString = FixedString.Replace("'","&apos;");
FixedString = FixedString.Replace("\"","&quot;");
return FixedString;
}
public string ReplaceNonValidCharsInFieldName(string fldname)
{
string tmpstr = fldname;
int len = fldname.Length;
int cnt = 0;
// this is also our sequence that tells us the follow 3 digits is the ascii number (base 10)
// of the character we replaced.
string OKpunch = "-._";
string outstr = "";
int decval;
while (cnt < len)
{
char tmpchr = tmpstr[cnt];
if(!char.IsLetterOrDigit(tmpchr)&& (OKpunch.IndexOf(tmpchr) == -1) )
{
decval = tmpchr;
outstr += OKpunch + decval.ToString("D3");
}
else
{
outstr += tmpchr.ToString();
}
cnt++;
}
DEBUG_Write(outstr);
return outstr;
}
/*
* Field names cannot have ' ', '&', or '/' characters
*/
String FixFieldName(String fldname)
{
String fixedField = fldname;
DEBUG_CheckFieldName(fldname);
fixedField = fixedField.Replace(" ","__");
/*
* If the first character is 0-9, then put a '_' in front of the field name
*/
if (Char.IsDigit(fixedField,0))
fixedField = "__" + fixedField;
fixedField = ReplaceNonValidCharsInFieldName(fixedField);
return fixedField;
}
/*
* This function will parse the remaining information in the LineOfText string
* and create the value needed for the Info field of the database record.
*/
String ParseInfoField()
{
String RtnStr = "";
String tmpStr;
String Title;
String ROMenuHead;
String GrpMenuHead;
String RoValueDef;
String RoMenuItemDef;
String GroupMenuItemDef;
String RoFieldsInUse;
String GroupFieldsInUse;
String FieldName;
int intRecType = GetFieldInt(RecType);
switch (intRecType)
{
case 0: // Next Record Id or next database table name
RtnStr = GetFieldTxt();
break;
case 1: // Database title and database name
RtnStr = GetStringByLength(); // database title
ROTblElmt = FixFieldName(RtnStr);
RtnStr += "\t";
tmpStr = GetStringByLength(); // database table name
if (tmpStr.Length == 0)
RtnStr += "RO000001"; // default database table name
else
RtnStr += tmpStr;
break;
case 2: // Field Description
// get the field definition
RtnStr = GetFieldDefinition();
break;
case 3: // RO Group
GroupTitle = GetStringByLength(); // group name (title)
ROMenuHead = GetStringByLength(); // RO menu header
GrpMenuHead = GetStringByLength();// Group menu header
RtnStr = "<vlnGroup "; // begin group definition
// RO return value definition
RoValueDef = GetValueDefinition();
if (!StringsAreEqual(RoValueDef,""))
RtnStr += "RetVal=\"" + RoValueDef + "\" ";
//RO menu item definition
RoMenuItemDef = GetValueDefinition();
if (!StringsAreEqual(RoMenuItemDef,""))
RtnStr += "MenuItem=\"" + RoMenuItemDef + "\" ";
// Group menu item definition
GroupMenuItemDef = GetValueDefinition();
if (!StringsAreEqual(GroupMenuItemDef,""))
RtnStr += "GroupMenuItem=\"" + GroupMenuItemDef + "\" ";
// Ro fields in use
RoFieldsInUse = "";
tmpStr = GetFieldTxt();
while (!StringsAreEqual(tmpStr,"0"))
{
RoFieldsInUse += tmpStr + " ";
tmpStr = GetFieldTxt(); //next
}
RoFieldsInUse = RoFieldsInUse.TrimEnd(' ');
if (!StringsAreEqual(RoFieldsInUse,""))
RtnStr += "FieldsInUse=\"" + RoFieldsInUse + "\" ";
// Group fields in use
GroupFieldsInUse = "";
tmpStr = GetFieldTxt();
while (!StringsAreEqual(tmpStr,"0"))
{
GroupFieldsInUse = GroupFieldsInUse + tmpStr + " ";
tmpStr = GetFieldTxt(); //next
}
GroupFieldsInUse = GroupFieldsInUse.TrimEnd(' ');
if (!StringsAreEqual(GroupFieldsInUse,""))
RtnStr += "GroupFieldsInUse=\"" + GroupFieldsInUse + "\" ";
// AccPageID prefix
String AccPagePreFix;
AccPagePreFix = GetStringByLength();
AccPagePreFix = FixString(AccPagePreFix);
if (!StringsAreEqual(AccPagePreFix,""))
RtnStr += "AccPageIDPrefix=\"" + AccPagePreFix + "\" ";
// AccdPageID definition
String AccPageDef;
AccPageDef = GetValueDefinition();
if (!StringsAreEqual(AccPageDef,""))
RtnStr += "AccPageID=\"" + AccPageDef + "\" ";
// end group attributes
RtnStr +=">";
// add group name
RtnStr += FixString(GroupTitle);
RtnStr += "</vlnGroup>"; // end group definition
break;
case 4: // sub group
Title = GetStringByLength(); // sub group name (title)
ROMenuHead = GetStringByLength(); // RO menu header
GrpMenuHead = GetStringByLength();// sub group menu header
// replace special chars
Title = FixString(Title);
// Save the group title and recid for use later on
GroupTitles TheGroupTitle = new GroupTitles();
TheGroupTitle.GrpRecID = RecID;
TheGroupTitle.GrpTitle = Title;
GroupTitlesList.Add(TheGroupTitle);
RtnStr = "<vlnGroup "; // begin sub group definition
// The Sub Group Title
RtnStr += "MenuTitle=\"" + Title + "\" ";
// RO return value definition
RoValueDef = GetValueDefinition();
if (!StringsAreEqual(RoValueDef,""))
RtnStr += "RetVal=\"" + RoValueDef + "\" ";
//RO menu item definition
RoMenuItemDef = GetValueDefinition();
if (!StringsAreEqual(RoMenuItemDef,""))
RtnStr += "MenuItem=\"" + RoMenuItemDef + "\" ";
// Group menu item definition
GroupMenuItemDef = GetValueDefinition();
if (!StringsAreEqual(GroupMenuItemDef,""))
RtnStr += "GroupMenuItem=\"" + GroupMenuItemDef + "\" ";
// Ro fields in use
RoFieldsInUse = "";
tmpStr = GetFieldTxt();
while (!StringsAreEqual(tmpStr,"0"))
{
RoFieldsInUse = RoFieldsInUse + tmpStr + " ";
tmpStr = GetFieldTxt(); // next
}
RoFieldsInUse = RoFieldsInUse.TrimEnd(' ');
if (!StringsAreEqual(RoFieldsInUse,""))
RtnStr += "FieldsInUse=\"" + RoFieldsInUse + "\" ";
// Group fields in use
GroupFieldsInUse = "";
tmpStr = GetFieldTxt();
while (!StringsAreEqual(tmpStr,"0"))
{
GroupFieldsInUse = GroupFieldsInUse + tmpStr + " ";
tmpStr = GetFieldTxt(); // next
}
GroupFieldsInUse = GroupFieldsInUse.TrimEnd(' ');
if (!StringsAreEqual(GroupFieldsInUse,""))
RtnStr += "GroupFieldsInUse=\"" + GroupFieldsInUse + "\" ";
// End attributes
RtnStr = RtnStr.TrimEnd(' ');
RtnStr += ">";
// Sub Group fields and values
String SubGrpFldsAndVals = "";
tmpStr = GetFieldTxt();
while (!StringsAreEqual(tmpStr,"0"))
{
FieldName = GetSavedLocalFieldName(tmpStr);
SubGrpFldsAndVals += "<" + FieldName+ ">";
SubGrpFldsAndVals += GetFieldValue();
SubGrpFldsAndVals += "</" + FieldName + ">\r\n";
tmpStr = GetFieldTxt(); // next
}
RtnStr += SubGrpFldsAndVals;
RtnStr += "</vlnGroup>"; // end group definition
break;
case 5: // RO Value Record
// RO Menu Item Value
String ROMenuItemValue = GetStringByLength();
ROMenuItemValue = FixString(ROMenuItemValue);
RtnStr = "<" + FixFieldName(GroupTitle) + " ";
// RO Menu Item
RtnStr += "MenuTitle=\"" + ROMenuItemValue + "\">\r\n";
//RO fields and values
String ROFldsAndVals = "";
tmpStr = GetFieldTxt();
while (!StringsAreEqual(tmpStr,"0"))
{
FieldName = GetSavedLocalFieldName(tmpStr);
tmpStr = GetFieldValue();
if (IsComboFieldType(FieldName))
{
FieldName = BuildComboFieldName(FieldName);
}
ROFldsAndVals += "<" + FieldName + ">";
ROFldsAndVals += tmpStr;
ROFldsAndVals += "</" + FieldName + ">\r\n";
tmpStr = GetFieldTxt();
}
RtnStr += ROFldsAndVals;
RtnStr += "</" + FixFieldName(GroupTitle) + ">\r\n";
break;
default:
break;
}// end switch
return RtnStr;
}
/*
* This function will parse the given text record (string) and place the
* information in a database record.
*/
void ProcessTextLine()
{
/*
* Get the first 5 database fields and save them in string types.
*/
RecID= GetFieldTxt();
RecType = GetFieldTxt();
ParentRecID = GetFieldTxt();
AccPageID = GetStringByLength();
DateTime = GetFieldTxt();
intRecType = GetFieldInt(RecType);
/***** For Debugging ***/
// if (RecID.Equals("000000c1"))
// {
// int test;
// test = 1;
// }
// if (AccPageID.Equals("R.29"))
// {
// MessageBox.Show("debug");
// }
/**** End - for debugging ****/
// setup a new database record
NewDbField = new ROField("", RecID, ParentRecID, (uint)intRecType);
/*
* Now what's remaining in the txtRecord string is the BLOB info from
* the old Paradox database record.
* Parse the remaining information and build the XML or XSD string that
* represents the data.
*/
Info = ParseInfoField();
// Fix the single quotes before writing to the database
// MS Access complained when we tried to write "C'.'99", wanted "C''.''99" instead
Info = Info.Replace("'","''");
// if we are processing a record type 4, save it as a record type 3.
// record type 4's were considered subgroups. We are going to store them
// as groups (type 3) with the parent id pointing to the the parent group
// or subgroup.
if (intRecType == 4 && !StringsAreEqual(RecType,"2"))
intRecType = 3;
// write to database
MyDbRec.RODB_WriteDbRecord(ROTableName,RecID,intRecType,ParentRecID,AccPageID,DateTime,Info);
if (StringsAreEqual(RecType,"0")&& StringsAreEqual(RecID,"00000001"))
{
// build schema header for the table just inserted
Info = "<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\r\n";
Info += "elementFormDefault=\"qualified\" targetNamespace=\"volianNS\" xmlns=\"volianNS\">\r\n";
Info += "<xsd:element name=\"volianElement\" type=\"volianElementType\" />";
Info += "<xsd:complexType name=\"volianElementType\">\r\n";
Info += "<xsd:sequence>";
// write the schema header record (type 6)
// Note that a null recid will cause RODB_WriteDbRecord to get the next
// available one and update the "next RecID" database record.
MyDbRec.RODB_WriteDbRecord(ROTableName,"",6,"00000000","",DateTime,Info);
// build the schema footer for the table just inserted
Info = "</xsd:sequence>\r\n";
Info += "</xsd:complexType>\r\n";
Info += "<xsd:simpleType name=\"Fixed\">\r\n";
Info += "<xsd:restriction base=\"xsd:normalizedString\">\r\n";
Info += "<xsd:maxLength value=\"16\"/>\r\n";
Info += "</xsd:restriction>\r\n";
Info += "</xsd:simpleType>\r\n";
Info += "<xsd:simpleType name=\"Variable\">\r\n";
Info += "<xsd:restriction base=\"xsd:string\">\r\n";
Info += "<xsd:maxLength value=\"72\"/>\r\n";
Info += "</xsd:restriction>\r\n";
Info += "</xsd:simpleType>\r\n";
Info += "<xsd:simpleType name=\"Table\">\r\n";
Info += "<xsd:restriction base=\"xsd:string\">\r\n";
Info += "<xsd:maxLength value=\"72\"/>\r\n";
Info += "</xsd:restriction>\r\n";
Info += "</xsd:simpleType>\r\n";
Info += "<xsd:simpleType name=\"XY_Plot\">\r\n";
Info += "<xsd:restriction base=\"xsd:string\">\r\n";
Info += "<xsd:maxLength value=\"72\"/>\r\n";
Info += "</xsd:restriction>\r\n";
Info += "</xsd:simpleType>\r\n";
Info += "</xsd:schema>\r\n";
// write the schema footer record (type 7)
// Note that a null recid will cause RODB_WriteDbRecord to get the next
// available one and update the "next RecID" database record.
MyDbRec.RODB_WriteDbRecord(ROTableName,"",7,"00000000","",DateTime,Info);
}
}
}
}