/*********************************************************************************************
* Copyright 2021 - Volian Enterprises, Inc. All rights reserved.
* Volian Enterprises - Proprietary Information - DO NOT COPY OR DISTRIBUTE
* ------------------------------------------------------------------------------
* $Workfile: RODBInterface.cs $ $Revision: 48 $
* $Author: Kathy $ $Date: 9/06/05 11:25a $
*
* $History: RODBInterface.cs $
*
* ***************** Version 48 *****************
* User: Kathy Date: 9/06/05 Time: 11:25a
* Updated in $/LibSource/RODBInterface
* B2005-035
*
* ***************** Version 47 *****************
* User: Jsj Date: 5/03/05 Time: 11:45a
* Updated in $/LibSource/RODBInterface
*
* ***************** Version 46 *****************
* User: Kathy Date: 7/15/04 Time: 11:10a
* Updated in $/LibSource/RODBInterface
* Fix B2004-016
*
* ***************** Version 45 *****************
* User: Jsj Date: 5/19/04 Time: 11:11a
* Updated in $/LibSource/RODBInterface
* fixed typo in warning message
*
* ***************** Version 44 *****************
* User: Jsj Date: 5/13/04 Time: 2:19p
* Updated in $/LibSource/RODBInterface
* RO FST will skip records that do not have a valid parent.
*
* ***************** Version 43 *****************
* User: Jsj Date: 5/11/04 Time: 9:28a
* Updated in $/LibSource/RODBInterface
* We were getting multiple tree entries after creating the FST file.
*
* ***************** Version 42 *****************
* User: Jsj Date: 4/08/04 Time: 9:42a
* Updated in $/LibSource/RODBInterface
* Optimized and added new read functions to speed up RO.FST file
* creation.
*
* ***************** Version 41 *****************
* User: Jsj Date: 3/19/04 Time: 9:40a
* Updated in $/LibSource/RODBInterface
* bug fix, was using parent node's group definition instead of the
* current node's group definition
* B2004-008
*
* ***************** Version 40 *****************
* User: Jsj Date: 1/12/04 Time: 12:08p
* Updated in $/LibSource/RODBInterface
* changed SQL Server catalog name from"RO" to "VEPROMS RO"
*
* ***************** Version 39 *****************
* User: Jsj Date: 1/07/04 Time: 2:17p
* Updated in $/LibSource/RODBInterface
* allow use of SQL Server
*
* ***************** Version 38 *****************
* User: Kathy Date: 5/30/03 Time: 12:47p
* Updated in $/LibSource/RODBInterface
* B2003-040: flag inserted groups have no children for xml
*
* ***************** Version 37 *****************
* User: Kathy Date: 5/21/03 Time: 12:44p
* Updated in $/LibSource/RODBInterface
* B2003-041: field name changes fixes.
*
* ***************** Version 36 *****************
* User: Kathy Date: 5/07/03 Time: 1:57p
* Updated in $/LibSource/RODBInterface
* B2003-033 fix
*
* ***************** Version 35 *****************
* User: Jsj Date: 4/14/03 Time: 2:59p
* Updated in $/LibSource/RODBInterface
* changes to help speed up RO FST file creation
*
* ***************** Version 34 *****************
* User: Kathy Date: 4/04/03 Time: 9:39a
* Updated in $/LibSource/RODBInterface
* B2003-030: flag parent's HasChild attribute for new ros
*
* ***************** Version 33 *****************
* User: Kathy Date: 3/13/03 Time: 1:17p
* Updated in $/LibSource/RODBInterface
* master different than local fieldname, use local
*
* ***************** Version 32 *****************
* User: Kathy Date: 1/27/03 Time: 2:12p
* Updated in $/LibSource/RODBInterface
* test oledb
*
* ***************** Version 31 *****************
* User: Kathy Date: 12/17/02 Time: 2:32p
* Updated in $/LibSource/RODBInterface
* new top group with apostrophe failed
*
* ***************** Version 30 *****************
* User: Kathy Date: 12/17/02 Time: 11:05a
* Updated in $/LibSource/RODBInterface
* fixed bug on apostrophe in field def (schema string)
*
* ***************** Version 29 *****************
* User: Kathy Date: 12/10/02 Time: 2:24p
* Updated in $/LibSource/RODBInterface
* fieldname special chars & various bug fixes
*
* ***************** Version 28 *****************
* User: Kathy Date: 12/06/02 Time: 11:57a
* Updated in $/LibSource/RODBInterface
* mods for SQL Server
*
* ***************** Version 27 *****************
* User: Kathy Date: 12/02/02 Time: 8:28a
* Updated in $/LibSource/RODBInterface
* fieldname replace chars
*
* ***************** Version 26 *****************
* User: Kathy Date: 12/02/02 Time: 6:11a
* Updated in $/LibSource/RODBInterface
* Fix some bugs and add status bar on long ops
*
* ***************** Version 25 *****************
* User: Jsj Date: 11/27/02 Time: 12:46p
* Updated in $/LibSource/RODBInterface
* modifications for RO.FST file creation
*
* ***************** Version 24 *****************
* User: Kathy Date: 11/26/02 Time: 12:56p
* Updated in $/LibSource/RODBInterface
* fixed single quote crash in accpageid
*
* ***************** Version 23 *****************
* User: Kathy Date: 11/11/02 Time: 7:15a
* Updated in $/LibSource/RODBInterface
* Added RODB_ReadRO to read an RO given a recid/table name
*
* ***************** Version 22 *****************
* User: Kathy Date: 10/24/02 Time: 11:16a
* Updated in $/LibSource/RODBInterface
* delete hi-level group (table)
*
* ***************** Version 21 *****************
* User: Kathy Date: 10/15/02 Time: 2:16p
* Updated in $/LibSource/RODBInterface
* minor bug fixes & new group (database, i.e. table level)
*
* ***************** Version 20 *****************
* User: Kathy Date: 10/10/02 Time: 1:04p
* Updated in $/LibSource/RODBInterface
* xmltree=tree control
*
* ***************** Version 19 *****************
* User: Kathy Date: 10/10/02 Time: 10:56a
* Updated in $/LibSource/RODBInterface
* console.writeline->Messagebox
*
* ***************** Version 18 *****************
* User: Kathy Date: 10/10/02 Time: 10:00a
* Updated in $/LibSource/RODBInterface
* delete bug fix & accessory page id support
*
* ***************** Version 17 *****************
* User: Kathy Date: 10/07/02 Time: 11:25a
* Updated in $/LibSource/RODBInterface
* image file saving of xml using xmltextwriter was missing sometext
*
* ***************** Version 16 *****************
* User: Kathy Date: 10/02/02 Time: 1:41p
* Updated in $/LibSource/RODBInterface
* tie tree to insert/delete changes (round 1)
*
* ***************** Version 15 *****************
* User: Jsj Date: 10/01/02 Time: 4:45p
* Updated in $/LibSource/RODBInterface
* hooks for passed in database path
*
* ***************** Version 14 *****************
* User: Kathy Date: 9/27/02 Time: 1:22p
* Updated in $/LibSource/RODBInterface
* remove using vlnxml
*
* ***************** Version 13 *****************
* User: Kathy Date: 9/27/02 Time: 1:18p
* Updated in $/LibSource/RODBInterface
* fix digit as first char in fieldname & recurse through tree adjusting
* for modified field names
*
* ***************** Version 12 *****************
* User: Jsj Date: 9/26/02 Time: 11:13a
* Updated in $/LibSource/RODBInterface
* added VLNXML reference
*
* ***************** Version 11 *****************
* User: Kathy Date: 9/25/02 Time: 9:55a
* Updated in $/LibSource/RODBInterface
* generate xml strings for writing to database by using xmltextwriter
*
* ***************** Version 10 *****************
* User: Kathy Date: 9/19/02 Time: 10:02a
* Updated in $/LibSource/RODBInterface
* minor changes for schema and other bug fixes
*
* ***************** Version 9 *****************
* User: Kathy Date: 9/11/02 Time: 1:14p
* Updated in $/LibSource/RODBInterface
* vlnxml
*
* ***************** Version 8 *****************
* User: Kathy Date: 9/10/02 Time: 12:54p
* Updated in $/LibSource/RODBInterface
* menu titles
*
* ***************** Version 7 *****************
* User: Kathy Date: 9/06/02 Time: 11:43a
* Updated in $/LibSource/RODBInterface
* datetimestamp
*
* ***************** Version 6 *****************
* User: Kathy Date: 8/30/02 Time: 11:56a
* Updated in $/LibSource/RODBInterface
* new/update ro field records.
*
* ***************** Version 5 *****************
* User: Kathy Date: 8/30/02 Time: 9:43a
* Updated in $/LibSource/RODBInterface
* compile
*
* ***************** Version 4 *****************
* User: Jsj Date: 8/28/02 Time: 3:40p
* Updated in $/LibSource/RODBInterface
* added a create table function
*
* ***************** Version 3 *****************
* User: Jsj Date: 8/28/02 Time: 3:03p
* Updated in $/LibSource/RODBInterface
* read connection strings from a text file
*
* ***************** Version 2 *****************
* User: Kathy Date: 8/28/02 Time: 10:52a
* Updated in $/LibSource/RODBInterface
* development
*********************************************************************************************/
using System;
using System.Collections;
using System.IO;
using System.Data;
using System.Xml;
using System.Xml.XPath;
using System.Xml.Schema;
using System.Text;
using System.Windows.Forms;
using DBEncapsulation;
using ROFields;
using VlnStatus;
using System.Collections.Specialized;
using Org.Mentalis.Files;
using System.Data.SqlClient;
using System.Collections.Generic;
namespace RODBInterface
{
///
/// Summary description for Class1
///
public enum RecordType : uint
{
Master = 0, SubDatabase = 1, Schema = 2, Group = 3, GroupSchema = 4, RRO = 5, SchemaStart = 6, SchemaEnd = 7, ConvertedToSql = 8
}
///
/// The following class handles generation of sql strings to get/put requested parts of
/// XML RO Tree. And performs the database access using the VLN_DB class.
///
public abstract partial class RODB
{
#region Properties
public DBEncapsulation.DBEncapsulate DBE;
public VlnXmlDocument ROXml;
public string schemastart;
public string schemaend;
public string lastTable = "";
public HybridDictionary dicFldTypes;
public string RODirectoryPath;
public int dbProviderType = 0;
public string strDatabaseConnectionCommand;
public string dbServerPath = "";
public string dbServerUserName = "";
public string dbServerPassword = "";
public enum DB_PROVIDER { ACCESS, SQL_SERVER, ORACLE };
private string _MyDBID;
public string MyDBID
{
get { return _MyDBID; }
set { _MyDBID = value; }
}
private string _MyRecID;
public string MyRecID
{
get { return _MyRecID; }
set { _MyRecID = value; }
}
private bool _OnlyConnectOnce=false;
public bool OnlyConnectOnce
{
get { return _OnlyConnectOnce; }
set { _OnlyConnectOnce = value; }
}
// C2021-026 used to access in the list of P/C Children
private static string[] _PCChildList = null;
public static string[] PCChildList
{
get { return _PCChildList; }
set { _PCChildList = value; }
}
#endregion
#region abstracts // need these for each method that must be defined for each database type
public abstract string RODB_GetNextGroupTable();
public abstract string RODB_GetNextRecId(string table);
public abstract bool RODB_GetRootGroups(VlnXmlElement root);
public abstract bool RODB_DeleteGroup(XmlNode group, string tbname, string toprecid);
public abstract bool RODB_DeleteRO(XmlNode group);
public abstract bool RODB_WriteGroup(XmlNode group, VlnXmlElement master);
public abstract bool RODB_InsertGroup(VlnXmlElement group);
public abstract string RODB_AddNewTable(string TblName, string newgrpname);
public abstract bool RODB_CopyFieldDefs(string fromtb, string totb, int type);
public abstract bool RODB_GetGroupAndSubgroups(VlnXmlElement node, StringBuilder sb);
public abstract bool RODB_GetChildData(VlnXmlElement node, bool CheckChildCount);
public abstract bool IsDuplicateAccPageID(VlnXmlElement ro, string newacc);
public abstract VlnXmlElement RODB_ReadRO(string tbl, string recid);
public abstract bool RODB_WriteRO(VlnXmlElement ro, bool movedRO = false);
public abstract bool RODB_InsertRO(VlnXmlElement ro);
public abstract ushort RODB_GetFieldType(VlnXmlElement elem, string TableName, string Fld);
public abstract ArrayList RODB_GetFields(VlnXmlElement elem, uint rtype, bool refresh = false);
public abstract string RODB_GetSchemaPiece(string Recid, string table);
public abstract bool RODB_NewSchemaPiece(string recid, string parentid, string table, string schpiece, uint rtype);
public abstract bool RODB_WriteSchemaPiece(string Recid, string table, string schpiece);
public abstract bool RODB_ProcessRROFieldChange(VlnXmlElement child, string oldname, string newname, uint editlevel, VlnStatusMessage StatMsgWindow, bool combofield);
public abstract bool RODB_UpdateFieldRecord(ROField myrof, VlnXmlElement myelem, string strschema,
string oldname, string newname, uint editlevel, bool combofield);
public abstract XmlSchema RODB_GetGroupSchema(VlnXmlElement elem);
public abstract XmlSchema RODB_GetSchema(VlnXmlElement elem);
public abstract int RODB_GetNumberOfROValueRecords(string tablename);
public abstract int RODB_GetNumberOfGroupRecords(string tablename);
public abstract string RODB_GetDBNameForAbout();
public abstract string RODB_GetDBServerForAbout();
public abstract string RODB_HasBeenConverted();
public abstract bool RODB_WriteSqlConnectToAccess(string newConectStr);
#endregion
public RODB()
{
}
#region GeneralDB
public void GetDbServerInfo(string ROdir)
{
string strServerProvider;
string ROiniPath = ROdir + "\\ROAPP.INI";
// Get the database Provider name - default to Access
IniReader in1 = new IniReader(ROiniPath);
strServerProvider = in1.ReadString("Database Server", "Driver", "ACCESS");
strServerProvider = strServerProvider.ToUpper();
if (strServerProvider.Equals("SQL SERVER"))
dbProviderType = (int)DB_PROVIDER.SQL_SERVER;
else if (strServerProvider.Equals("ORACLE"))
dbProviderType = (int)DB_PROVIDER.ORACLE;
else // default to ACCESS
dbProviderType = (int)DB_PROVIDER.ACCESS;
// Get the database server path
dbServerPath = in1.ReadString("Database Server", "Path", ROdir);
dbServerUserName = in1.ReadString("Database Server", "UserID", "");
dbServerPassword = in1.ReadString("Database Server", "Password", "");
if (dbProviderType.Equals((int)DB_PROVIDER.ACCESS))
{
if (dbServerUserName.Equals(""))
dbServerUserName = "Admin"; // default user name for Access
}
//else if (dbServerUserName.Equals("") || (dbServerUserName.Length > 0 && dbServerPassword.Equals("")))
//{
// userpass pwdlg = new userpass(dbServerUserName);
// // If using SQL Server or Oracle
// // prompt for a user name and password.
// pwdlg.Text = strServerProvider + pwdlg.Text;
// if (pwdlg.ShowDialog() == DialogResult.OK)
// {
// dbServerUserName = pwdlg.uname;
// dbServerPassword = pwdlg.pword;
// }
// else
// {
// dbServerUserName = "";
// dbServerPassword = "";
// }
//}
}
public void BuildConnectionString(string ropath, string DataConnectionPath)
{
GetDbServerInfo(ropath);
if (!dbProviderType.Equals((int)DB_PROVIDER.SQL_SERVER))
{
strDatabaseConnectionCommand = "Provider=Microsoft.Jet.OLEDB.4.0;Password=\"\";User ID=Admin;Data Source=" + DataConnectionPath + "\\ROMaster.mdb;Mode=Share Deny None;Extended Properties=\"\";Jet OLEDB:System database=\"\";Jet OLEDB:Registry Path=\"\";Jet OLEDB:Database Password=\"\";Jet OLEDB:Engine Type=5;Jet OLEDB:Database Locking Mode=1;Jet OLEDB:Global Partial Bulk Ops=2;Jet OLEDB:Global Bulk Transactions=1;Jet OLEDB:New Database Password=\"\";Jet OLEDB:Create System Database=False;Jet OLEDB:Encrypt Database=False;Jet OLEDB:Don't Copy Locale on Compact=False;Jet OLEDB:Compact Without Replica Repair=False;Jet OLEDB:SFP=False";
}
}
#endregion
#region XML
public VlnXmlDocument RODB_GetRoot()
{
// Create an xmldoc and initialize it with a root node
ROXml = new VlnXmlDocument();
XmlNode elem = ROXml.CreateNode(XmlNodeType.Element, "RO_Root", "");
ROXml.AppendChild(elem);
return ROXml;
}
public string ParseEleName(string info)
{
string elemname;
// need to find element type too.
int issingle = info.IndexOf("Single");
int idx1 = info.IndexOf("element name=");
if (idx1 > 0)
{
elemname = info.Substring(idx1 + 14, info.Length - idx1 - 14);
idx1 = elemname.IndexOf("\"");
elemname = CvtFldToUserFld(elemname.Substring(0, idx1));
// if we have a choice element, remove the last character (it was added to the
// field names in order to allow for unique fields names for the choice items.
if (info.IndexOf("xsd:choice") > 0)
{
string trun = elemname.Remove((elemname.Length) - 1, 1);
return trun;
}
return elemname;
}
return null;
}
// Given an element to start at, get the fields in use. Pass in the element you're
// on, the available list for this group & a string representing 'FieldsInUse' or
// 'GroupFieldsInUse'.
public ArrayList RODB_GetFieldsInUse(VlnXmlElement elem, ArrayList avail, string strFieldsInUse, ref string origFieldsInUse, bool RemoveFromAvailList)
{
VlnXmlElement startelem = elem;
// if this element doesn't have any fields in use, walk up the tree until
// we find them.
string FieldsInUse = "";
if (startelem.HasAttribute(strFieldsInUse) == false)
{
VlnXmlElement parent;
parent = (VlnXmlElement)startelem.ParentNode;
while (parent != null && FieldsInUse == "")
{
FieldsInUse = parent.GetAttribute(strFieldsInUse);
if (parent.Name != "RO_Root")
parent = (VlnXmlElement)parent.ParentNode;
else
parent = null;
}
}
else
FieldsInUse = startelem.GetAttribute(strFieldsInUse);
origFieldsInUse = FieldsInUse; // make a copy to compare to later.
ArrayList inuse = new ArrayList();
// if there are no fields in use (may be inserting a top group)
// return an empty list.
if (FieldsInUse == "") return inuse;
// Go through the FieldsInUse list and move elements from the avail list
// to the inuse list
int strpos = 0;
string recid;
recid = FieldsInUse.Substring(strpos, 8);
MyRecID = recid;
while (recid != null)
{
// find it in avail list. Remove it from there & add to inuse list
for (int i = 0; i < avail.Count; i++)
{
ROField rof = (ROField)avail[i];
string lrecid = rof.GetRecID;
if (lrecid == recid)
{
// remove it from avail list & add it to inuse list
ROField inuserof = new ROField(rof.GetFieldname, rof.GetRecID, rof.GetMasterRecID, rof.GetFieldType);
inuse.Add((object)inuserof);
if (RemoveFromAvailList)
avail.RemoveAt(i);
break;
}
}
strpos = strpos + 9;
if (strpos > FieldsInUse.Length)
recid = null;
else
{
recid = FieldsInUse.Substring(strpos, 8);
}
}
return inuse;
}
//C2021-026 adding ability to have field values based on Parent/Child applicability
// This reads the database and returns a list of the field where applicability was enabled
public ArrayList RODB_GetApplicabilityEnabledFields(VlnXmlElement elem, ArrayList fieldsInUse, ref string origApplcFields, bool pcApplicabilityEnabled)
{
ArrayList newApplicList = new ArrayList();
if (!pcApplicabilityEnabled)
{
origApplcFields = null;
return newApplicList;
}
VlnXmlElement startelem = elem;
string atribApplicFields = "ApplicabilityEnabled"; //xml attribute containing list of field recids
// if this element doesn't have any fields in use, walk up the tree until
// we find them.
string applicFields = "";
if (startelem.HasAttribute(atribApplicFields) == false)
{
VlnXmlElement parent;
parent = (VlnXmlElement)startelem.ParentNode;
while (parent != null && applicFields == "")
{
applicFields = parent.GetAttribute(atribApplicFields);
if (parent.Name != "RO_Root")
parent = (VlnXmlElement)parent.ParentNode;
else
parent = null;
}
}
else
applicFields = startelem.GetAttribute(atribApplicFields);
origApplcFields = applicFields; // make a copy to compare to later.
// if there are no fields with applicability (may be inserting a top group)
// return an empty list.
if (applicFields == "") return newApplicList;
// Go through the FieldsInUse list and copy elements to newApplicList
int strpos = 0;
string recid;
recid = applicFields.Substring(strpos, 8);
MyRecID = recid;
while (recid != null)
{
// find it in avail list and add to newApplicList
for (int i = 0; i < fieldsInUse.Count; i++)
{
ROField rof = (ROField)fieldsInUse[i];
string lrecid = rof.GetRecID;
if (lrecid == recid)
{
// add to newApplilcList if it is not already there list
ROField inuserof = new ROField(rof.GetFieldname, rof.GetRecID, rof.GetMasterRecID, rof.GetFieldType);
bool addit = true;
foreach (ROField arof in newApplicList)
{
if (arof.GetRecID == inuserof.GetRecID)
{
addit = false; //this field is already in the list
break;
}
}
if (addit)
newApplicList.Add((object)inuserof);
break;
}
}
strpos = strpos + 9;
if (strpos > applicFields.Length)
recid = null;
else
{
recid = applicFields.Substring(strpos, 8);
}
}
return newApplicList;
}
public string CvtUserFldToFld(string fldname)
{
if (fldname.Length < 2)
return fldname;
// a digit cannot start an xml fieldname, prepend a "__" to it.
string tmp0;
if (char.IsDigit(fldname, 0))
tmp0 = "__" + fldname;
else
tmp0 = fldname;
// an xml fieldname cannot have a space, change it to a "__"
string tmpstr = tmp0.Replace(" ", "__");
int len = tmpstr.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++;
}
return outstr;
}
public string CvtFldToUserFld(string fldname)
{
string tmpstr0;
if (fldname.Length < 2) return fldname;
// an xml element name cannot begin with a digit. we had prepended a "__"
if (fldname.Substring(0, 2) == "__" && char.IsDigit(fldname, 2))
tmpstr0 = fldname.Substring(2, fldname.Length - 2);
else
tmpstr0 = fldname;
// an xml element name cannot have a space, we converted to a "__"
string tmpstr = tmpstr0.Replace("__", " ");
int len = tmpstr.Length;
int cur = 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, indx;
if (tmpstr.Length < 6)
indx = -1;
else
indx = tmpstr.IndexOf(OKpunch, cur);
string asc_spchar;
while (indx >= 0)
{
outstr += tmpstr.Substring(cur, indx - cur);
asc_spchar = tmpstr.Substring(indx + 3, 3);
decval = System.Convert.ToInt16(asc_spchar, 10);
outstr += System.Convert.ToChar(decval).ToString();
cur = indx + 6;
if (cur + 6 > len)
indx = -1;
else
indx = tmpstr.IndexOf(OKpunch, cur);
}
if (cur < len) outstr += tmpstr.Substring(cur, len - cur);
return outstr;
}
// Process the given field type.
// return the type value used in the RO.FST file
public ushort GetFSTreturnType(ushort fldtype, string fldname, VlnXmlElement elem)
{
ushort rtnval = 0;
/*
* Here are the possible field types:
*
public enum FieldTypes: uint
{
Nil=0, SingleTxt=1, VariableTxt=2, FrmtSingleTxt=4, XYPlot=8, Table=10, Image=20,
MultiTxt=40, Combination=128, MultiFld=100
}
*/
switch ((uint)fldtype)
{
case 1: // Fixed length text
case 2: // Variable length text
case 4: // formatted text
case 40: // Multi line text
rtnval = 1;
break;
case 10: // Table
rtnval = 2;
break;
case 8: // X/Y Plot
rtnval = 4;
break;
case 32: // image (intergrated graphics) - this is the HEX representation
rtnval = 8;
break;
}
return rtnval;
}
public string GenerateXmlString(XmlNode node, bool isgroup) // KBR not sure - see end of method
{
string retstr;
XmlTextWriter xmlTextWriter;
StringWriter strWriter = new StringWriter();
xmlTextWriter = new XmlTextWriter(strWriter);
VlnXmlElement enode;
XmlNode kid;
kid = node.FirstChild;
enode = (VlnXmlElement)node;
if (isgroup == true)
{
xmlTextWriter.WriteStartElement("vlnGroup");
if (enode.HasAttribute("RetVal"))
{
xmlTextWriter.WriteStartAttribute("RetVal", null);
xmlTextWriter.WriteString(enode.GetAttribute("RetVal"));
xmlTextWriter.WriteEndAttribute();
}
if (enode.HasAttribute("MenuItem"))
{
xmlTextWriter.WriteStartAttribute("MenuItem", null);
xmlTextWriter.WriteString(enode.GetAttribute("MenuItem"));
xmlTextWriter.WriteEndAttribute();
}
if (enode.HasAttribute("FieldsInUse"))
{
xmlTextWriter.WriteStartAttribute("FieldsInUse", null);
xmlTextWriter.WriteString(enode.GetAttribute("FieldsInUse"));
xmlTextWriter.WriteEndAttribute();
}
if (enode.HasAttribute("ApplicabilityEnabled")) //C2021-026 save field applicability
{
xmlTextWriter.WriteStartAttribute("ApplicabilityEnabled", null);
xmlTextWriter.WriteString(enode.GetAttribute("ApplicabilityEnabled"));
xmlTextWriter.WriteEndAttribute();
}
if (enode.HasAttribute("GroupMenuItem"))
{
xmlTextWriter.WriteStartAttribute("GroupMenuItem", null);
xmlTextWriter.WriteString(enode.GetAttribute("GroupMenuItem"));
xmlTextWriter.WriteEndAttribute();
}
if (enode.HasAttribute("GroupFieldsInUse"))
{
xmlTextWriter.WriteStartAttribute("GroupFieldsInUse", null);
xmlTextWriter.WriteString(enode.GetAttribute("GroupFieldsInUse"));
xmlTextWriter.WriteEndAttribute();
}
if (enode.HasAttribute("AccPageID"))
{
xmlTextWriter.WriteStartAttribute("AccPageID", null);
xmlTextWriter.WriteString(enode.GetAttribute("AccPageID"));
xmlTextWriter.WriteEndAttribute();
}
if (enode.HasAttribute("AccPageIDPrefix"))
{
xmlTextWriter.WriteStartAttribute("AccPageIDPrefix", null);
xmlTextWriter.WriteString(enode.GetAttribute("AccPageIDPrefix"));
xmlTextWriter.WriteEndAttribute();
}
xmlTextWriter.WriteStartAttribute("MenuTitle", null);
xmlTextWriter.WriteString(enode.GetAttribute("MenuTitle"));
xmlTextWriter.WriteEndAttribute();
while (kid != null)
{
if ((kid is XmlText) || (kid.ChildNodes.Count == 1 && kid.Name != "vlnGroup"))
kid.WriteTo(xmlTextWriter);
kid = kid.NextSibling;
}
}
else
{
xmlTextWriter.WriteStartElement(node.Name);
xmlTextWriter.WriteStartAttribute("MenuTitle", null);
xmlTextWriter.WriteString(enode.GetAttribute("MenuTitle"));
xmlTextWriter.WriteEndAttribute();
while (kid != null)
{
kid.WriteTo(xmlTextWriter);
kid = kid.NextSibling;
}
}
xmlTextWriter.WriteEndElement(); // vlnGroup or top of RO.
xmlTextWriter.Flush();
xmlTextWriter.Close();
retstr = strWriter.ToString();
// replace the single quote because ODBC fails if it's in a string because
// the single quote represents the beg/end of string when sending string to
// ODBC.
retstr = retstr.Replace("\'", "'"); // KBR - not sure if this method should be in RODB class or db specific class
return (retstr);
}
// Create a new field record in master and reference in the current table.
// pass in current rodb object, the xml element creating and editlevel
// is a recordType of either Group (group field definitions) or rro for
// the ro definition. the string apd represents an append string which is
// appended to the fieldname for combo types, otherwise it's null
public bool RODB_NewFieldRecord(ROField myrof, VlnXmlElement myelem, string strschema, uint editlevel, string apd)
{
bool success;
// get a new record id for this and save it in the master table.
string mrecid = RODB_GetNextRecId("ROMaster");
// get recid in ROMaster for group, so that we can set the parent field.
// walk up the tree until we find a 'MasterRecID' attribute.
VlnXmlElement parent;
parent = myelem;
while (parent != null)
{
if (parent.HasAttribute("MasterRecID")) break;
parent = (VlnXmlElement)parent.ParentNode;
}
success = RODB_NewSchemaPiece(mrecid, parent.GetAttribute("MasterRecID"), "ROMaster", strschema, editlevel);
if (success != true) return false;
// also reference it from the local table.
string lrecid = RODB_GetNextRecId(myelem.GetAttribute("Table"));
myrof.SetRecID(lrecid);
myrof.SetMasterRecID(mrecid);
StringBuilder strbld = new StringBuilder();
strbld.Append(mrecid);
strbld.Append(" ");
string strtype = myrof.GetFieldType.ToString();
strbld.Append(strtype.PadLeft(3, '0'));
strbld.Append(" ");
strbld.Append(myrof.MakeFieldName(myrof.GetFieldname));
if (apd != null) strbld.Append(apd);
// Need ParentID field, get by looking up xml tree to find parentID attribute = "00000000", then
// use this recid.
parent = myelem;
while (parent.GetAttribute("ParentID") != "00000000")
{
parent = (VlnXmlElement)parent.ParentNode;
}
success = RODB_NewSchemaPiece(lrecid, parent.GetAttribute("RecID"), myelem.GetAttribute("Table"), strbld.ToString(), editlevel);
return success;
}
// C2021-026 rename any P/C Child fields
public string DoReplaceParentChildField(string infstr, string oldName, string newName)
{
string rtnInfoStr = infstr;
if (PCChildList == null) return rtnInfoStr;
int pcChildIdx = 0; // children indexing starts at one so initialize with zero
foreach (string chld in PCChildList)
{
pcChildIdx++;
string csufx = string.Format("_PCCHILD{0}", pcChildIdx); // Create child field name
string oldFldNameChild = oldName.Insert(oldName.Length - 1, CvtUserFldToFld(csufx));
string newFldNameChild = newName.Insert(newName.Length - 1, CvtUserFldToFld(csufx));
rtnInfoStr = rtnInfoStr.Replace(oldFldNameChild, newFldNameChild);
}
return rtnInfoStr;
}
public string DoCmbFieldReplace(string repstring, string oname, string nname, string letter)
{
string cmboname, cmbnname;
cmboname = oname.Insert(oname.Length - 1, letter);
cmbnname = nname.Insert(nname.Length - 1, letter);
string rtnstr = repstring.Replace(cmboname, cmbnname);
rtnstr = DoReplaceParentChildField(rtnstr, cmboname, cmbnname); // C2021-026 create child fields in combo group
return rtnstr;
}
// RODB_UpdateNamesInROs: goes through subtree (top node is 'fld') and if this
// updated field is used (either in [Group]FieldsInUse or was used in parent, then
// 1) if group node, check for attributes using "" and if found, update
// to "
// 2) if group edit, modify this node's xml data with the new fieldname,
// otherwise, edit 'ROs' under this to replace with
// Input: VlnXmlElement fld: start processing at this node.
// string myrecid: local recid to be used for check to see if used (in FieldsInUse
// or GroupFieldsInUse.
// string oldname, newname - old and new field names
// string myrecid - local record storing field name
// uint editlevel - if editting groups, do check for for item 1 above in
// Group attributes, otherwise do in
// bool parentused - set to false from caller, this is recursive and will
// be set appropriately for recursive calls.
public bool RODB_UpdateFieldNames(VlnXmlElement fld, string myrecid, string oldname,
string newname, uint editlevel, bool parentused, VlnStatusMessage StatMsgWindow, bool combofield)
{
bool success;
bool useAtLevel = false;
XmlNode node;
VlnXmlElement child;
string fldinuse;
if (editlevel == (uint)RecordType.Schema)
fldinuse = "FieldsInUse";
else
fldinuse = "GroupFieldsInUse";
// Do the current level before walking through any children groups.
if (fld.Name == "vlnGroup")
{
if (fld.HasAttribute(fldinuse))
{
// if recid not in here, don't process for this node.
string fiu = fld.GetAttribute(fldinuse);
if (fiu.IndexOf(myrecid) >= 0) useAtLevel = true;
}
if (useAtLevel == true || parentused == true) useAtLevel = true;
if (useAtLevel == true)
{
string haskids, kidsloaded;
haskids = fld.GetAttribute("HasChild");
kidsloaded = fld.GetAttribute("ChildLoaded");
if (haskids == "True" && kidsloaded == "False")
{
success = RODB_GetChildData(fld, true);
if (success == false) return false;
fld.SetAttribute("ChildLoaded", "True");
}
parentused = true; // for kids of this group.
success = RODB_ProcessRROFieldChange(fld, oldname, newname, editlevel, StatMsgWindow, combofield);
if (success == false) return false;
}
}
node = (XmlNode)fld.FirstChild;
while (node != null)
{
if (node is VlnXmlElement)
{
useAtLevel = false;
child = (VlnXmlElement)node;
// If this is a group menu edit, process group nodes, by recursive
// call and then modify data on group record.
// For both, when hitting a group node, check that it either doesn't
// have 'FieldsInUse' or 'GroupFieldsInUse' or that if it does,
// this record id is in the list -> only process these, otherwise
// the field is not used.
if (child.Name == "vlnGroup")
{
// see if inuse for this one, either defined here or from parent.
if (child.HasAttribute(fldinuse))
{
// if recid not in here, don't process for this node. Still
// need to check children because they may redefine fields in use.
string fiu = child.GetAttribute(fldinuse);
if (fiu.IndexOf(myrecid) >= 0) useAtLevel = true;
}
if (useAtLevel == false && parentused == true) useAtLevel = true;
// update this record if it doesn't have it's own , then do kids
// of it.
success = RODB_UpdateFieldNames(child, myrecid, oldname, newname, editlevel, useAtLevel, StatMsgWindow, combofield);
if (success == false) return false;
}
}
node = node.NextSibling;
}
return true;
}
// check if the name entered is one used for setting up
// the new graphics or setpoint databases.
public bool RODB_CheckForStandardName(string oname)
{
string oldname = CvtFldToUserFld(oname);
if (oldname.CompareTo("Name") == 0) return true;
if (oldname.CompareTo("Image ID") == 0) return true;
if (oldname.CompareTo("Image") == 0) return true;
if (oldname.CompareTo("Setpoint ID") == 0) return true;
if (oldname.CompareTo("Setpoint Value") == 0) return true;
if (oldname.CompareTo("Associated System/Component") == 0) return true;
if (oldname.CompareTo("Applicability") == 0) return true;
if (oldname.CompareTo("Revision") == 0) return true;
if (oldname.CompareTo("Short Description") == 0) return true;
if (oldname.CompareTo("Description") == 0) return true;
if (oldname.CompareTo("Key Assumptions") == 0) return true;
if (oldname.CompareTo("Basis") == 0) return true;
if (oldname.CompareTo("References") == 0) return true;
if (oldname.CompareTo("Group") == 0) return true;
if (oldname.CompareTo("Parameter") == 0) return true;
return false;
}
#endregion
}
///
/// The following class handles generation of sql strings to get/put requested parts of
/// XML RO Tree. And performs the database access using the VLN_DB class. This class is
/// to be used for MS Access
///
public partial class AccessRODB : RODB
{
public DBEncapsulation.OLEDB_DBEncap DBE_OLEDB;
public AccessRODB(string rODirectoyPath)
{
RODirectoryPath = rODirectoyPath;
BuildConnectionString(rODirectoyPath, rODirectoyPath);
DBE_OLEDB = new OLEDB_DBEncap();
DBE = DBE_OLEDB;
try
{
DBE.Connection(strDatabaseConnectionCommand);
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Setup of OLEDB/ODBC");
}
}
public override string RODB_GetDBNameForAbout()
{
return ("Database: RoMaster");
}
public override string RODB_GetDBServerForAbout()
{
return ("Microsoft Access");
}
public override string RODB_HasBeenConverted()
{
try
{
DBE.OpenConnection();
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Could not open database connection");
// MessageBox.Show(e.StackTrace,"Debug");
return null;
}
string constring = null;
string strHasBeen = "SELECT Info FROM ROMaster where RecType=" + (uint)RecordType.ConvertedToSql;
try
{
DBE.Command(strHasBeen);
DBE.Reader();
if (DBE.Read())
{
constring = DBE.GetString(0);
DBE.ReaderClose();
DBE.CommandDispose();
}
}
catch (Exception ex)
{
}
DBE.CloseConnection();
return constring;
}
public override bool RODB_WriteSqlConnectToAccess(string newConectStr)
{
//try
//{
// DBE.OpenConnection();
//}
//catch (Exception e)
//{
// MessageBox.Show(e.Message, "Could not open database connection");
// // MessageBox.Show(e.StackTrace,"Debug");
// return false;
//}
string dt = string.Format("{0:yyyyMMddHHmmss}", System.DateTime.Now);
string strUpdate = "UPDATE ROMaster SET Info = '" + newConectStr + "'";
// note that '8' for rectype flags database converted:
strUpdate = strUpdate + ", ModDateTime = '" + dt + "' WHERE RecType=" + (uint)RecordType.ConvertedToSql;
try
{
DBE.Command(strUpdate);
DBE.Reader();
DBE.ReaderClose();
DBE.CommandDispose();
}
catch (Exception ex)
{
return false;
}
return true;
}
// get the next table name & update it to the next possible.
public override string RODB_GetNextGroupTable()
{
// read record type of master for this table. This is where the highest recid is stored.
// Update the recid by 1, write it out and return the new recid.
string strGetNxt = "SELECT Info FROM ROMaster where RecID = '00000001' and RecType=" + (uint)RecordType.Master;
string rettable = null;
try
{
DBE.Command(strGetNxt);
DBE.Reader();
if (DBE.Read())
{
rettable = DBE.GetString(0);
string nxttable = rettable.Substring(2, 6);
int ltbl = System.Convert.ToInt32(nxttable, 10);
ltbl++;
nxttable = ltbl.ToString("d6"); // this format "d6" should pad left with zeros
string newstr = "RO" + nxttable;
DBE.ReaderClose();
DBE.CommandDispose();
string dt = string.Format("{0:yyyyMMddHHmmss}", System.DateTime.Now);
string strUpdate = "UPDATE ROMaster SET Info = '" + newstr + "'";
strUpdate = strUpdate + ", ModDateTime = '" + dt + "' WHERE RecID = '00000001' and RecType=" + (uint)RecordType.Master;
DBE.Command(strUpdate);
DBE.Reader();
DBE.ReaderClose();
DBE.CommandDispose();
return rettable;
}
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Getting new record id");
}
return null;
}
// get the next recid for this table & update it.
public override string RODB_GetNextRecId(string table)
{
// read record type of master for this table. This is where the highest recid is stored.
// Update the recid by 1, write it out and return the new recid.
string strGetNxt = "SELECT Info FROM " + table + " where RecID = '00000000' and RecType=" + (uint)RecordType.Master;
try
{
DBE.Command(strGetNxt);
DBE.Reader();
if (DBE.Read())
{
string RecID = DBE.GetString(0);
int lrecid = System.Convert.ToInt32(RecID, 16);
lrecid++;
RecID = lrecid.ToString("x");
// need an 8 char string so pad left with zero
string padstr = RecID.PadLeft(8, '0');
DBE.ReaderClose();
DBE.CommandDispose();
string dt = string.Format("{0:yyyyMMddHHmmss}", System.DateTime.Now);
string strUpdate = "UPDATE " + table + " SET Info = '" + padstr + "'";
strUpdate = strUpdate + ", ModDateTime = '" + dt + "' WHERE RecID = '00000000' and RecType=" + (uint)RecordType.Master;
DBE.Command(strUpdate);
DBE.Reader();
DBE.ReaderClose();
DBE.CommandDispose();
return padstr;
}
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Getting new record id");
}
return null;
}
// pass in root node. This will get Groups from Root node. This is a special case because
// the list of top level groups is off of the ROMaster database.
public override bool RODB_GetRootGroups(VlnXmlElement root)
{
ShowCount.GetRootGroups++;
string table;
string group;
string title;
// Get menu fields to display
try
{
DBE.OpenConnection();
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Could not open database connection");
// MessageBox.Show(e.StackTrace,"Debug");
return false;
}
string strGetGroups = "SELECT RecID,Info FROM ROMaster where RecType = " + (uint)RecordType.SubDatabase;
strGetGroups += " ORDER BY RecID ASC";
DBE.Command(strGetGroups);
DBE.Reader();
SortedList mySL = new SortedList();
while (DBE.Read())
{
// Parse info string, it has group name & table name. Store in a sorted
// list, sorting by Group Name.
string mrecid = DBE.GetString(0);
group = DBE.GetString(1);
mySL.Add(mrecid, group);
}
DBE.CommandDispose();
DBE.ReaderClose();
// Now, for each group, i.e. table, make xml elements for the top level groups by
// reading in the Xml Element for the group from each table.
for (int i = 0; i < mySL.Count; i++)
{
group = mySL.GetByIndex(i).ToString();
int grnamindx = group.IndexOf("\t");
if (grnamindx == -1)
{// no tab, default to RO000001
table = "RO000001";
title = group;
}
else
{
StringBuilder tablesb = new StringBuilder(70);
tablesb.Append(group);
tablesb.Remove(0, grnamindx + 1);
table = tablesb.ToString();
title = group.Substring(0, grnamindx);
}
strGetGroups = "SELECT RecID,Info FROM " + table + " where RecType = " + (uint)RecordType.Group;
strGetGroups = strGetGroups + " and ParentID = '00000000'";
strGetGroups += " ORDER BY RecID ASC";
try
{
DBE.Command(strGetGroups);
DBE.Reader();
if (DBE.Read())
{
string RecID = DBE.GetString(0);
string Info = DBE.GetString(1);
XmlTextReader rdr = new XmlTextReader(Info, XmlNodeType.Element, null);
XmlNode nd = ROXml.ReadNode(rdr);
VlnXmlElement elem = (VlnXmlElement)nd;
elem.MyROID = RecID;
root.AppendChild(elem);
elem.SetAttribute("RecID", RecID);
elem.SetAttribute("ParentID", "00000000");
elem.SetAttribute("Table", table);
elem.SetAttribute("MasterRecID", mySL.GetKey(i).ToString());
//elem.SetAttribute("MenuTitle", elem.InnerText);
}
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Error getting group data");
// try to continue on with the next group - may be one missing table.
}
DBE.CommandDispose();
DBE.ReaderClose();
}
// get child count for each group.
XmlNode node = root.FirstChild;
while (node != null)
{
if (node is VlnXmlElement)
{
VlnXmlElement child = (VlnXmlElement)node;
//get child count for each table listed in innertext.
string strGetSubCount = "SELECT COUNT (RecID) as cnt FROM " + child.GetAttribute("Table") + " WHERE ";
strGetSubCount = strGetSubCount + "ParentID='" + child.GetAttribute("RecID") + "'";
try
{
DBE.Command(strGetSubCount);
DBE.Reader();
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Error reading RO Data");
return false;
}
if (DBE.Read())
{
int cnt = DBE.GetInt32(0);
if (cnt > 0)
child.SetAttribute("HasChild", "True");
else
child.SetAttribute("HasChild", "False");
child.SetAttribute("ChildLoaded", "False");
}
DBE.CommandDispose();
DBE.ReaderClose();
}
node = node.NextSibling;
}
// for the beginning and end schema element, go to the master & read it from there. Store these to be used
// by all of the databases.
string strGetSchemaPiece;
schemastart = null;
strGetSchemaPiece = "SELECT Info From ROMaster where (ParentID='00000000' and RecType = " + (uint)RecordType.SchemaStart + ")";
DBE.Command(strGetSchemaPiece);
DBE.Reader();
if (DBE.Read())
schemastart = DBE.GetString(0);
else
{
DBE.CommandDispose();
DBE.ReaderClose();
return false;
}
DBE.CommandDispose();
DBE.ReaderClose();
schemaend = null;
strGetSchemaPiece = "SELECT Info From ROMaster where (ParentID='00000000' and RecType = " + (uint)RecordType.SchemaEnd + ")";
DBE.Command(strGetSchemaPiece);
DBE.Reader();
if (DBE.Read())
schemaend = DBE.GetString(0);
else
{
DBE.CommandDispose();
DBE.ReaderClose();
return false;
}
DBE.CommandDispose();
DBE.ReaderClose();
return true;
}
public override bool RODB_DeleteGroup(XmlNode group, string tbname, string toprecid)
{
VlnXmlElement egroup = null;
string strDel;
strDel = "DELETE FROM ROMaster WHERE ";
// delete table entry in ROMaster
if (group != null)
{
egroup = (VlnXmlElement)group;
strDel = strDel + "RecID='" + egroup.GetAttribute("MasterRecID") + "'";
}
else
strDel = strDel + "RecID='" + toprecid + "'";
try
{
DBE.Command(strDel);
DBE.Reader();
DBE.Read();
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Error When deleting SubGroup ROs.");
DBE.CommandDispose();
DBE.ReaderClose();
return false;
}
DBE.CommandDispose();
DBE.ReaderClose();
// now remove the table.
if (egroup != null)
strDel = "DROP TABLE " + egroup.GetAttribute("Table");
else
strDel = "DROP TABLE " + tbname;
try
{
DBE.Command(strDel);
DBE.Reader();
DBE.Read();
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Error When deleting SubGroup ROs.");
DBE.CommandDispose();
DBE.ReaderClose();
return false;
}
DBE.CommandDispose();
DBE.ReaderClose();
return true;
}
// Delete from database either the group or RO from input node.
public override bool RODB_DeleteRO(XmlNode group)
{
// delete from database and then delete from tree. delete group and all
// subgroups & ros beneath it. delete subgroups by calling this.
// note that if just an ro is passed in, it will only delete it.
XmlNode node = group.FirstChild;
VlnXmlElement child;
VlnXmlElement egroup = (VlnXmlElement)group;
string strDelSub;
if (group.Name == "vlnGroup")
{
while (node != null)
{
if (node is VlnXmlElement)
{
child = (VlnXmlElement)node;
// if this is a group, call this again.
if (child.Name == "vlnGroup")
{
bool success = RODB_DeleteRO(node);
if (success == false)
{
MessageBox.Show("error in RODB_DeleteGroup");
return false;
}
}
}
node = node.NextSibling;
}
// delete all db records that have the ParentID = to this group RecID.
// (All subgroups should be processed from above recursion.
strDelSub = "DELETE FROM " + egroup.GetAttribute("Table") + " WHERE ";
strDelSub = strDelSub + "ParentID='" + egroup.GetAttribute("RecID") + "'";
try
{
DBE.Command(strDelSub);
DBE.Reader();
DBE.Read();
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Error When deleting SubGroup ROs.");
DBE.CommandDispose();
DBE.ReaderClose();
return false;
}
DBE.CommandDispose();
DBE.ReaderClose();
}
// now delete this ro or group, i.e. the one passed in.
strDelSub = "DELETE FROM " + egroup.GetAttribute("Table") + " WHERE ";
strDelSub = strDelSub + "RecID='" + egroup.GetAttribute("RecID") + "'";
try
{
DBE.Command(strDelSub);
DBE.Reader();
DBE.Read();
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Error When deleting this RO.");
DBE.CommandDispose();
DBE.ReaderClose();
return false;
}
DBE.CommandDispose();
DBE.ReaderClose();
return true;
}
//public string GenerateXmlString(XmlNode node, bool isgroup) // KBR not sure - see end of method
//{
// string retstr;
// XmlTextWriter xmlTextWriter;
// StringWriter strWriter = new StringWriter();
// xmlTextWriter = new XmlTextWriter(strWriter);
// VlnXmlElement enode;
// XmlNode kid;
// kid = node.FirstChild;
// enode = (VlnXmlElement)node;
// if (isgroup == true)
// {
// xmlTextWriter.WriteStartElement("vlnGroup");
// if (enode.HasAttribute("RetVal"))
// {
// xmlTextWriter.WriteStartAttribute("RetVal", null);
// xmlTextWriter.WriteString(enode.GetAttribute("RetVal"));
// xmlTextWriter.WriteEndAttribute();
// }
// if (enode.HasAttribute("MenuItem"))
// {
// xmlTextWriter.WriteStartAttribute("MenuItem", null);
// xmlTextWriter.WriteString(enode.GetAttribute("MenuItem"));
// xmlTextWriter.WriteEndAttribute();
// }
// if (enode.HasAttribute("FieldsInUse"))
// {
// xmlTextWriter.WriteStartAttribute("FieldsInUse", null);
// xmlTextWriter.WriteString(enode.GetAttribute("FieldsInUse"));
// xmlTextWriter.WriteEndAttribute();
// }
// if (enode.HasAttribute("GroupMenuItem"))
// {
// xmlTextWriter.WriteStartAttribute("GroupMenuItem", null);
// xmlTextWriter.WriteString(enode.GetAttribute("GroupMenuItem"));
// xmlTextWriter.WriteEndAttribute();
// }
// if (enode.HasAttribute("GroupFieldsInUse"))
// {
// xmlTextWriter.WriteStartAttribute("GroupFieldsInUse", null);
// xmlTextWriter.WriteString(enode.GetAttribute("GroupFieldsInUse"));
// xmlTextWriter.WriteEndAttribute();
// }
// if (enode.HasAttribute("AccPageID"))
// {
// xmlTextWriter.WriteStartAttribute("AccPageID", null);
// xmlTextWriter.WriteString(enode.GetAttribute("AccPageID"));
// xmlTextWriter.WriteEndAttribute();
// }
// if (enode.HasAttribute("AccPageIDPrefix"))
// {
// xmlTextWriter.WriteStartAttribute("AccPageIDPrefix", null);
// xmlTextWriter.WriteString(enode.GetAttribute("AccPageIDPrefix"));
// xmlTextWriter.WriteEndAttribute();
// }
// xmlTextWriter.WriteStartAttribute("MenuTitle", null);
// xmlTextWriter.WriteString(enode.GetAttribute("MenuTitle"));
// xmlTextWriter.WriteEndAttribute();
// while (kid != null)
// {
// if ((kid is XmlText) || (kid.ChildNodes.Count == 1 && kid.Name != "vlnGroup"))
// kid.WriteTo(xmlTextWriter);
// kid = kid.NextSibling;
// }
// }
// else
// {
// xmlTextWriter.WriteStartElement(node.Name);
// xmlTextWriter.WriteStartAttribute("MenuTitle", null);
// xmlTextWriter.WriteString(enode.GetAttribute("MenuTitle"));
// xmlTextWriter.WriteEndAttribute();
// while (kid != null)
// {
// kid.WriteTo(xmlTextWriter);
// kid = kid.NextSibling;
// }
// }
// xmlTextWriter.WriteEndElement(); // vlnGroup or top of RO.
// xmlTextWriter.Flush();
// xmlTextWriter.Close();
// retstr = strWriter.ToString();
// // replace the single quote because ODBC fails if it's in a string because
// // the single quote represents the beg/end of string when sending string to
// // ODBC.
// retstr = retstr.Replace("\'", "'"); // KBR - not sure if this method should be in RODB class or db specific class
// return (retstr);
//}
public override bool RODB_WriteGroup(XmlNode group, VlnXmlElement master)
{
bool retval = true;
string dt = string.Format("{0:yyyyMMddHHmmss}", System.DateTime.Now);
string xmlstr = GenerateXmlString(group, true);
string strUpdate = "UPDATE " + master.GetAttribute("Table") + " SET Info = '" + xmlstr + "'";
strUpdate = strUpdate + ", ModDateTime = '" + dt + "' WHERE RecID='" + master.GetAttribute("RecID") + "'";
try
{
DBE.Command(strUpdate);
DBE.Reader();
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Error on write group");
retval = false;
}
DBE.ReaderClose();
DBE.CommandDispose();
return retval;
}
public override bool RODB_InsertGroup(VlnXmlElement group)
{
bool retval = true;
string dt = string.Format("{0:yyyyMMddHHmmss}", System.DateTime.Now);
string xmlstr = GenerateXmlString(group, true);
string strInsert = "INSERT INTO " + group.GetAttribute("Table") + "(RecID, RecType, ParentID, ModDateTime, Info) ";
strInsert = strInsert + " VALUES ('" + group.GetAttribute("RecID") + "'," + (uint)RecordType.Group + ",'";
strInsert = strInsert + group.GetAttribute("ParentID") + "','" + dt + "','" + xmlstr + "');";
try
{
DBE.Command(strInsert);
DBE.Reader();
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Error on insert group");
retval = false;
}
DBE.ReaderClose();
DBE.CommandDispose();
return retval;
}
// add a new database table, add a record to master to point to it. return
// that record number.
public override string RODB_AddNewTable(string TblName, string newgrpname)
{
bool retval = false;
// create the table. this is done by doing a select into the new table
// from the RoMaster because using the create table command didn't have
// a datatype that was compatible between sql & ms-access (for the memo
// field 'Info').
string strMkTable = "SELECT * INTO " + TblName;
strMkTable = strMkTable + " FROM ROMaster WHERE RecID = '00000000';";
try
{
DBE.Command(strMkTable);
DBE.Reader();
retval = true;
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Error creating table.");
}
DBE.ReaderClose();
DBE.CommandDispose();
// return if error on table create.
if (retval == false) return null;
// remove the first record. It was inserted just to have something to copy to
// create the table. (see previous comment)
string strDel = "DELETE FROM " + TblName + " WHERE RecID = '00000000'";
try
{
DBE.Command(strDel);
DBE.Reader();
DBE.Read();
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Error When deleting SubGroup ROs.");
DBE.CommandDispose();
DBE.ReaderClose();
return null;
}
DBE.CommandDispose();
DBE.ReaderClose();
// now insert the first record
string dt = string.Format("{0:yyyyMMddHHmmss}", System.DateTime.Now);
string strInsert = "INSERT INTO " + TblName + "( RecID, RecType, ParentID, ModDateTime, Info ) ";
strInsert = strInsert + " VALUES ('00000000', 0,'00000000','" + dt + "','00000001');";
retval = false;
try
{
DBE.Command(strInsert);
DBE.Reader();
retval = true;
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Error creating table.");
}
DBE.ReaderClose();
DBE.CommandDispose();
// return if error on insert of master record of new table, otherwise add
// this table reference to the master.
if (retval == false) return null;
string recid = RODB_GetNextRecId("ROMaster");
string info = CvtUserFldToFld(newgrpname) + "\t" + TblName;
strInsert = "INSERT INTO ROMaster ( RecID, RecType, ParentID, ModDateTime, Info ) ";
strInsert = strInsert + " VALUES ('" + recid + "', 1,'00000001','" + dt + "','" + info + "');";
retval = false;
try
{
DBE.Command(strInsert);
DBE.Reader();
retval = true;
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Error writing new table to master.");
}
DBE.ReaderClose();
DBE.CommandDispose();
if (retval == false)
return null;
else
return recid;
}
// Copy over field definitions from the ROMaster to the input table.
public override bool RODB_CopyFieldDefs(string fromtb, string totb, int type)
{
ArrayList retlist = new ArrayList();
string strGetFields;
string Info;
string RecID;
string name;
uint ftype;
ROField rof;
bool success;
// select all of the field definition records in this table.
strGetFields = "SELECT RecID, Info from ROMaster where RecType = 2";
DBE.Command(strGetFields);
DBE.Reader();
while (DBE.Read())
{
RecID = DBE.GetString(0);
Info = DBE.GetString(1);
// it's defined in the local table if the first character is "<" which starts
// the schema definition string.
name = ParseEleName(Info);
if (name != null)
{
// what type of schema element?
rof = new ROField(name, RecID, null, 0);
ftype = rof.ParseFieldType(Info);
rof.SetFieldType(ftype);
retlist.Add((object)rof);
}
}
DBE.ReaderClose();
DBE.CommandDispose();
// using this list, add new records for field definition references to the new
// table.
for (int i = 0; i < retlist.Count; i++)
{
rof = (ROField)retlist[i];
if (rof.GetFieldname != null)
{
string mrecid = rof.GetRecID;
string lrecid = RODB_GetNextRecId(totb);
StringBuilder strbld = new StringBuilder();
strbld.Append(mrecid);
strbld.Append(" ");
string strtype = rof.GetFieldType.ToString();
strbld.Append(strtype.PadLeft(3, '0'));
strbld.Append(" ");
if (strtype == "128") // append an 'a' for combo type
strbld.Append(rof.MakeFieldName(rof.GetFieldname) + "a");
else
strbld.Append(rof.MakeFieldName(rof.GetFieldname));
// add new field.
success = RODB_NewSchemaPiece(lrecid, "00000002", totb, strbld.ToString(), 2);
if (success == false) return false;
}
}
return true;
}
// This is simular to GetChildData() but this function reads in
// all the subgroups for the given node
// Note that this function is designed to be call for the
// root node (i.e. it gets all of group and RO data for a given
// database table)
public override bool RODB_GetGroupAndSubgroups(VlnXmlElement node, StringBuilder sb)
{
VlnStatusBar StatBar = new VlnStatusBar("Reading from the Database");
string tablename = node.GetAttribute("Table");
string strGetChildData = "SELECT * FROM " + tablename;
strGetChildData = strGetChildData + " where (RecType = 3 or RecType = 5) AND ParentID <> '00000002' ORDER BY ParentID,RecID ASC";
HybridDictionary dicGroups = new HybridDictionary();
dicGroups.Add(node.GetAttribute("RecID").ToString(), node);
StatBar.BarMax = RODB_GetNumberOfGroupRecords(tablename); //get number of groups
StatBar.BarStepValue = 5;
StatBar.StatMsg = node.InnerText;
DBE.Command(strGetChildData);
DBE.Reader();
// skip the first record - it's the node that we passed in
if (!DBE.Read())
{
DBE.ReaderClose();
StatBar.PerformStep(1);
return false;
}
while (DBE.Read())
{
string RecID = DBE.GetString(0);
int RecType = DBE.GetInt32(1);
string ParID = DBE.GetString(2);
string AccPageID = DBE.GetString(3);
string Info = DBE.GetString(5);
if (!ParID.Equals(node.GetAttribute("RecID")))
{
if (!dicGroups.Contains(ParID))
{
if (sb.Length == 0)
{
sb.AppendLine("The following records were skipped.");
sb.AppendLine("The parent for these RO's was missing.");
sb.AppendLine();
}
string strMBText = "RecID: " + RecID + "\n\n Table: " + tablename + "\n";
sb.AppendLine(strMBText);
// MessageBox.Show(strMBText, "Warning - Orphan RO Record");
continue; // skip - no parent for this node
}
node = (VlnXmlElement)dicGroups[ParID];
node.SetAttribute("HasChild", "True");
node.SetAttribute("ChildLoaded", "True");
}
else
{
node.SetAttribute("ChildLoaded", "True");
}
if (RecType == (uint)RecordType.Group)
{
VlnXmlElement elem;
StatBar.PerformStep();
try
{
XmlTextReader rdr = new XmlTextReader(Info, XmlNodeType.Element, null);
XmlNode nd = ROXml.ReadNode(rdr);
elem = (VlnXmlElement)nd;
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Error reading Xml Group From data");
DBE.ReaderClose();
return false;
}
elem.MyROID = RecID;
elem.SetAttribute("RecID", RecID);
elem.SetAttribute("ParentID", node.GetAttribute("RecID"));
elem.SetAttribute("Table", node.GetAttribute("Table"));
if (!dicGroups.Contains(RecID))
{
node.AppendChild(elem);
dicGroups.Add(RecID, elem);
}
// The Parameter Display Data is stored along with the group. This data
// was migrated over so that the data was not lost, but there is no
// User Interface to get to it. So remove the xml elements from the
// group part of tree. All valid group data only has one sublevel of
// data defining the group name.
XmlNode grp = (XmlNode)elem;
XmlNode kid = grp.FirstChild;
XmlNode tmpkid;
while (kid != null)
{
tmpkid = kid.NextSibling;
if (kid is VlnXmlElement)
if (kid.ChildNodes.Count > 1) grp.RemoveChild(kid);
kid = tmpkid;
}
}
// Store data in the VlnXmlElement as an RO
else if (RecType == (uint)RecordType.RRO)
{
//Create the reader.
XmlNode ro;
try
{
//B2022-043 &pos; was missing the ;
if (Info != null) Info = Info.Replace("'", "\'"); // B2021-071: crash when getting/saving field names
XmlTextReader roreader = new XmlTextReader(Info, XmlNodeType.Element, null);
ro = ROXml.ReadNode(roreader);
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Error reading Xml RRO From data");
DBE.ReaderClose();
return false;
}
VlnXmlElement elem = (VlnXmlElement)ro;
node.AppendChild(ro);
elem.MyROID = RecID;
elem.SetAttribute("RecID", RecID);
elem.SetAttribute("ParentID", node.GetAttribute("RecID"));
elem.SetAttribute("Table", node.GetAttribute("Table"));
elem.SetAttribute("AccPageID", AccPageID);
}
}
DBE.ReaderClose();
dicGroups = null;
StatBar.Dispose();
return true;
}
public override bool RODB_GetChildData(VlnXmlElement node, bool CheckChildCount)
{
ShowCount.GetChildData++;
// get menu fields to display here.
string tablename = node.GetAttribute("Table");
string strGetChildData = "SELECT RecID,RecType,AccPageID, Info FROM " + tablename + " where ";
strGetChildData = strGetChildData + "(RecType = " + (uint)RecordType.Group + " or RecType = ";
strGetChildData = strGetChildData + (uint)RecordType.RRO + ") and ";
strGetChildData = strGetChildData + "ParentID='" + node.GetAttribute("RecID") + "'";
strGetChildData += " ORDER BY RecID ASC";
//bool readit=false;
DBE.Command(strGetChildData);
DBE.Reader();
while (DBE.Read())
{
ShowCount.Children++;
//get count for attribute element
string RecID = DBE.GetString(0);
int RecType = DBE.GetInt32(1);
MyRecID = RecID;
string AccPageID = DBE.GetString(2);
string Info = DBE.GetString(3);
//B2022-043 &pos; was missing the ;
Info = Info.Replace("'", "\'"); // B2021-071: crash when getting/saving field names
node.SetAttribute("HasChild", "True");
// Store data in the VlnXmlElement as a subgroup
if (RecType == (uint)RecordType.Group)
{
VlnXmlElement elem;
try
{
XmlTextReader rdr = new XmlTextReader(Info, XmlNodeType.Element, null);
XmlNode nd = ROXml.ReadNode(rdr);
elem = (VlnXmlElement)nd;
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Error reading Xml Group From data");
DBE.ReaderClose();
return false;
}
node.AppendChild(elem);
elem.MyROID = RecID;
elem.SetAttribute("RecID", RecID);
elem.SetAttribute("ParentID", node.GetAttribute("RecID"));
elem.SetAttribute("Table", node.GetAttribute("Table"));
// The Parameter Display Data is stored along with the group. This data
// was migrated over so that the data was not lost, but there is no
// User Interface to get to it. So remove the xml elements from the
// group part of tree. All valid group data only has one sublevel of
// data defining the group name.
XmlNode grp = (XmlNode)elem;
XmlNode kid = grp.FirstChild;
XmlNode tmpkid;
while (kid != null)
{
tmpkid = kid.NextSibling;
if (kid is VlnXmlElement)
if (kid.ChildNodes.Count > 1) grp.RemoveChild(kid);
kid = tmpkid;
}
}
// Store data in the VlnXmlElement as an RO
else if (RecType == (uint)RecordType.RRO)
{
//Create the reader.
XmlNode ro;
try
{
XmlTextReader roreader = new XmlTextReader(Info, XmlNodeType.Element, null);
ro = ROXml.ReadNode(roreader);
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Error reading Xml RRO From data");
DBE.ReaderClose();
return false;
}
VlnXmlElement elem = (VlnXmlElement)ro;
elem.MyROID = RecID;
node.AppendChild(ro);
elem.SetAttribute("RecID", RecID);
elem.SetAttribute("ParentID", node.GetAttribute("RecID"));
elem.SetAttribute("Table", node.GetAttribute("Table"));
elem.SetAttribute("AccPageID", AccPageID);
}
}
DBE.ReaderClose();
// get child count for each subgroup.
if (CheckChildCount)
{
//A different approach - Look for grandchildren and set the haschildren attribute
//Build a query to get a list of children with children
string strGetSubCount = "SELECT R1.ParentID,COUNT(*) AS CNT FROM " + tablename + " R1 "
+ "INNER JOIN " + tablename + " R2 ON R1.ParentID = R2.RecID "
+ "WHERE (R1.RecType = " + (uint)RecordType.Group + " or R1.RecType=" + (uint)RecordType.RRO + ") "
+ "and R2.ParentID ='" + node.GetAttribute("RecID") + "' group by R1.ParentID;";
try
{
DBE.Command(strGetSubCount);
DBE.Reader();
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Error reading data");
}
//Build a Dictionary of Children with Children from the query results
HybridDictionary dicChild = new HybridDictionary();
while (DBE.Read())
dicChild[DBE.GetString(0)] = DBE.GetInt32(1);//This adds the entry and sets the value
DBE.CommandDispose();
DBE.ReaderClose();
XmlNode child = node.FirstChild;
while (child != null) //Look at each child node
{
if (child is VlnXmlElement)
{
VlnXmlElement echild = (VlnXmlElement)child;
if (echild.Name == "vlnGroup")
{
//If the dictionary contains an entry, the child has children
echild.SetAttribute("HasChild", (dicChild.Contains(echild.GetAttribute("RecID"))) ? "True" : "False");
echild.SetAttribute("ChildLoaded", "False");
}
}
child = child.NextSibling;
}
dicChild = null;
}
node.SetAttribute("ChildLoaded", "True");
return true;
}
public override bool IsDuplicateAccPageID(VlnXmlElement ro, string newacc)
{
string strcheck, inacc = null;
bool isdup = false;
int indx = newacc.IndexOf("'");
if (indx >= 0)
inacc = newacc.Insert(indx, "'");
else
inacc = newacc;
strcheck = "SELECT Count(RecID) AS CNT FROM " + ro.GetAttribute("Table") + " WHERE AccPageID = '" + inacc + "'";
if (ro.HasAttribute("RecID")) // new ro's don't have recid defined yet before this test.
strcheck = strcheck + " AND (NOT RecID = '" + ro.GetAttribute("RecID") + "')";
try
{
DBE.Command(strcheck);
DBE.Reader();
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Error on check");
return true;
}
if (DBE.Read())
{
int cnt = DBE.GetInt32(0);
if (cnt > 0)
isdup = true;
else
isdup = false;
}
DBE.CommandDispose();
DBE.ReaderClose();
return isdup;
}
public override VlnXmlElement RODB_ReadRO(string tbl, string recid)
{
ShowCount.ReadRo++;
VlnXmlElement retele = null;
string readstr = "SELECT ParentID, AccPageID, Info FROM " + tbl + " WHERE " + ((recid == null) ? "RecType=3 and ParentID = '00000000'" : ("RecID = '" + recid + "'"));
try
{
DBE.Command(readstr);
DBE.Reader();
// With the additional check for a recid=null, in the WHERE statement (above), we now longer need to check and skip for a null recid - jsj 4-17-2015
//if (recid == null)
// DBE.Read(); // skip the first parentID record of 00000000
if (DBE.Read())
{
string ParentID = DBE.GetString(0);
string AccPageID = DBE.GetString(1);
string Info = DBE.GetString(2);
// Store data in the VlnXmlElement
XmlTextReader rdr = new XmlTextReader(Info, XmlNodeType.Element, null);
XmlNode nd = ROXml.ReadNode(rdr);
retele = (VlnXmlElement)nd;
retele.SetAttribute("RecID", recid);
retele.SetAttribute("ParentID", ParentID);
retele.SetAttribute("Table", tbl);
if (retele.Name != "vlnGroup") retele.SetAttribute("AccPageID", AccPageID);
}
DBE.CommandDispose();
DBE.ReaderClose();
// if this is a group, see if children.
// if the DBE.Read() cannot find the RO, then retele remains a NULL
// the null check was added to prevent a null reference error
if (retele != null && retele.Name == "vlnGroup")
{
string strGetSubCount = "SELECT COUNT (RecID) as cnt FROM " + tbl + " WHERE ";
strGetSubCount = strGetSubCount + "ParentID='" + recid + "'";
DBE.Command(strGetSubCount);
DBE.Reader();
if (DBE.Read())
{
int cnt = DBE.GetInt32(0);
if (cnt > 0)
retele.SetAttribute("HasChild", "True");
else
retele.SetAttribute("HasChild", "False");
retele.SetAttribute("ChildLoaded", "False");
}
DBE.CommandDispose();
DBE.ReaderClose();
}
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Error on Read of RO");
return null;
}
return retele;
}
public override bool RODB_WriteRO(VlnXmlElement ro, bool movedRO = false)
{
bool success;
if (ro.Name == "vlnGroup")
{
success = RODB_WriteGroup(ro, ro);
return success;
}
else
{
string wraccid = null;
string accid = ro.GetAttribute("AccPageID");
int quote = accid.IndexOf("'");
if (quote >= 0)
wraccid = accid.Insert(quote, "'");
else
wraccid = accid;
string dt = string.Format("{0:yyyyMMddHHmmss}", System.DateTime.Now);
string xmlstr = GenerateXmlString(ro, false);
string strUpdate = "UPDATE " + ro.GetAttribute("Table") + " SET Info = '" + xmlstr + "'";
if (movedRO)
{
VlnXmlElement parent = (VlnXmlElement)ro.ParentNode;
ro.SetAttribute("ParentID", parent.GetAttribute("RecID"));
strUpdate += ", ParentID = '" + ro.GetAttribute("ParentID") + "'";
}
strUpdate = strUpdate + ", ModDateTime = '" + dt + "', AccPageID = '" + wraccid + "' WHERE RecID='" + ro.GetAttribute("RecID") + "'";
try
{
DBE.Command(strUpdate);
DBE.Reader();
success = true;
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Database Write Error");
success = false;
}
DBE.ReaderClose();
DBE.CommandDispose();
}
return success;
}
public override bool RODB_InsertRO(VlnXmlElement ro)
{
bool success = false;
string strInsert = null;
string dt = string.Format("{0:yyyyMMddHHmmss}", System.DateTime.Now);
VlnXmlElement parent = (VlnXmlElement)ro.ParentNode;
string lrecid = RODB_GetNextRecId(parent.GetAttribute("Table"));
ro.SetAttribute("Table", parent.GetAttribute("Table"));
ro.SetAttribute("RecID", lrecid);
ro.SetAttribute("ParentID", parent.GetAttribute("RecID"));
string haskids = parent.GetAttribute("HasChild");
if (haskids == "False" || haskids == "")
{
parent.SetAttribute("HasChild", "True");
parent.SetAttribute("ChildLoaded", "True");
}
string xmlstr = GenerateXmlString(ro, false);
string wraccid = null;
if (ro.HasAttribute("AccPageID"))
{
string accid = ro.GetAttribute("AccPageID");
int quote = accid.IndexOf("'");
if (quote >= 0)
wraccid = accid.Insert(quote, "'");
else
wraccid = accid;
}
if (ro.Name == "vlnGroup")
{
// add attribute to flag that this does not have xml children, i.e. any
// other subgroups or ros under it.
ro.SetAttribute("HasChild", "False");
if (ro.HasAttribute("AccPageID"))
{
// Code is never reached, but this was noticed - this next line should likely be:
// strInsert = "INSERT INTO " + parent.GetAttribute("Table") + "( RecID, RecType, ParentID, AccPageID, ModDateTime, Info ) ";
strInsert = "INSERT INTO " + parent.GetAttribute("Table") + "( RecID, RecType, ParentID, ModDateTime, AccPageID, Info ) ";
strInsert = strInsert + " VALUES ('" + ro.GetAttribute("RecID") + "'," + (uint)RecordType.Group + ",'" + ro.GetAttribute("ParentID");
strInsert = strInsert + "','" + wraccid + "','" + dt + "','" + xmlstr + "');";
}
else
{
strInsert = "INSERT INTO " + parent.GetAttribute("Table") + "( RecID, RecType, ParentID, ModDateTime, Info ) ";
strInsert = strInsert + " VALUES ('" + ro.GetAttribute("RecID") + "'," + (uint)RecordType.Group + ",'" + ro.GetAttribute("ParentID");
strInsert = strInsert + "','" + dt + "','" + xmlstr + "');";
}
}
else
{
strInsert = "INSERT INTO " + parent.GetAttribute("Table") + "( RecID, RecType, ParentID, AccPageId, ModDateTime, Info ) ";
strInsert = strInsert + " VALUES ('" + ro.GetAttribute("RecID") + "'," + (uint)RecordType.RRO + ",'" + ro.GetAttribute("ParentID");
strInsert = strInsert + "','" + wraccid + "','" + dt + "','" + xmlstr + "');";
}
try
{
DBE.Command(strInsert);
DBE.Reader();
success = true;
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Database Write Error");
}
DBE.ReaderClose();
DBE.CommandDispose();
return success;
}
public override ushort RODB_GetFieldType(VlnXmlElement elem, string TableName, string Fld)
{
string strGetFields;
string Info;
string RecID;
string name;
string tmpname;
ushort ftype = 0;
ROField rof;
if (TableName != lastTable)
{
lastTable = TableName;
dicFldTypes = new HybridDictionary();
// select all of the field definition records in this table.
// strGetFields = "SELECT RecID, Info from " + elem.GetAttribute("Table");
strGetFields = "SELECT RecID, Info from " + TableName;
strGetFields = strGetFields + " where RecType = 2"; // + rtype.ToString();
DBE.Command(strGetFields);
DBE.Reader();
// NOTE !!!!
// This function does not handle Combo type fields (128).
while (DBE.Read())// && ftype == 0)
{
RecID = DBE.GetString(0);
Info = DBE.GetString(1);
// it's defined in the local table if the first character is "<" which starts
// the schema definition string.
if ("<" == Info.Substring(0, 1))
{
name = ParseEleName(Info);
if (name != null)
{
tmpname = CvtUserFldToFld(name);
//if (tmpname.Equals(Fld))
//{
rof = new ROField(name, RecID, null, 0);
// uint tmpfldtype = rof.ParseFieldType(Info);
ftype = GetFSTreturnType(System.Convert.ToUInt16(rof.ParseFieldType(Info)), tmpname, elem);
dicFldTypes[tmpname] = ftype;
//}
}
}
else
{
// references master, but what we need is here: the field name and
// the the field type. Just parse this from the info field.
string parsename;
// string strftype;
// strftype = Info.Substring(9,3);
parsename = Info.Substring(13, Info.Length - 13);
//if (parsename.Equals(Fld))
//{
ftype = GetFSTreturnType(System.Convert.ToUInt16(Info.Substring(9, 3)), parsename, elem);
dicFldTypes[parsename] = ftype;
//}
}
}
DBE.ReaderClose();
DBE.CommandDispose();
}
ftype = ((ushort)dicFldTypes[Fld]);
return ftype;
}
// For the given element's table, get all of the RO fields defined in this table.
public override ArrayList RODB_GetFields(VlnXmlElement elem, uint rtype, bool refresh = false)
{
string table = elem.GetAttribute("Table");
if (!FieldDefinitions.ContainsKey(table))
FieldDefinitions.Add(table, RODB_GetFieldsFromDB(elem));
else if (refresh)
{
FieldDefinitions.Remove(table);
FieldDefinitions.Add(table, RODB_GetFieldsFromDB(elem));
}
return FieldDefinitions[table];
}
private Dictionary _FieldDefinitions = null;
public Dictionary FieldDefinitions
{
get
{
if (_FieldDefinitions == null) _FieldDefinitions = new Dictionary();
return _FieldDefinitions;
}
set { _FieldDefinitions = value; }
}
private ArrayList RODB_GetFieldsFromDB(VlnXmlElement elem)
{
ShowCount.GetFields++;
ArrayList retlist = new ArrayList();
string strGetFields;
string Info;
string RecID;
string name;
uint ftype;
ROField rof;
// select all of the field definition records in this table.
strGetFields = "SELECT RecID, Info from " + elem.GetAttribute("Table");
strGetFields = strGetFields + " where RecType = 2"; // + rtype.ToString();
DBE.Command(strGetFields);
DBE.Reader();
while (DBE.Read())
{
ShowCount.RoFields++;
RecID = DBE.GetString(0);
MyRecID = RecID;
Info = DBE.GetString(1);
// it's defined in the local table if the first character is "<" which starts
// the schema definition string.
if ("<" == Info.Substring(0, 1))
{
name = ParseEleName(Info);
if (name != null)
{
// what type of schema element?
rof = new ROField(name, RecID, null, 0);
ftype = rof.ParseFieldType(Info);
rof.SetFieldType(ftype);
retlist.Add((object)rof);
}
}
else
{
// the recid points to a field definition (schema) in the master - use it to get
// the schema element from the master and copy it.
string parsename;
string masterrecid;
string strftype;
masterrecid = Info.Substring(0, 8);
strftype = Info.Substring(9, 3);
ftype = System.Convert.ToUInt32(Info.Substring(9, 3));
parsename = CvtFldToUserFld(Info.Substring(13, Info.Length - 13));
// if we have a choice element, remove the last character (it was added to the
// field names in order to allow for unique fields names for the choice items.
if (ftype == (uint)FieldTypes.Combination)
{
string tparsename = parsename.Remove((parsename.Length) - 1, 1); // remove the choice string and the space
parsename = tparsename;
}
rof = new ROField(parsename, RecID, masterrecid, ftype);
retlist.Add((object)rof);
}
}
DBE.ReaderClose();
DBE.CommandDispose();
return retlist;
}
public override string RODB_GetSchemaPiece(string Recid, string table)
{
string strGetSchemaPiece;
string Info;
strGetSchemaPiece = "SELECT Info From " + table + " where (RecID = '" + Recid + "')";
DBE.Command(strGetSchemaPiece);
DBE.Reader();
if (DBE.Read())
Info = DBE.GetString(0);
else
Info = null;
DBE.ReaderClose();
DBE.CommandDispose();
return Info?.Replace("'", "\'");
}
public override bool RODB_NewSchemaPiece(string recid, string parentid, string table, string schpiece, uint rtype)
{
string strSchemaPiece;
bool success = true;
string dt = string.Format("{0:yyyyMMddHHmmss}", System.DateTime.Now);
strSchemaPiece = "INSERT INTO " + table + " (RecID, RecType, ParentID, ModDateTime, Info) VALUES ('";
// B2004-016: at one point all fields are returned using a record type of 2 (Schema) -
// but the insertion code did not account for this when inserting a type of 4 (GroupSchema) - i.e.
// RecordType of 4 is no longer used, all fields (whether schema or group) are defined
// as RecordTYpe of 2.
//strSchemaPiece = strSchemaPiece + recid + "', " + rtype.ToString() + ", '" + parentid + "', '" + dt + "', '" + schpiece.Replace("\'","'") + "');";
strSchemaPiece = strSchemaPiece + recid + "', 2, '" + parentid + "', '" + dt + "', '" + schpiece.Replace("\'", "'") + "');";
DBE.Command(strSchemaPiece);
try
{
DBE.Command(strSchemaPiece);
DBE.Reader();
}
catch (Exception e)
{
success = false;
MessageBox.Show(e.Message, "Database Write Error");
}
DBE.ReaderClose();
DBE.CommandDispose();
return success;
}
public override bool RODB_WriteSchemaPiece(string Recid, string table, string schpiece)
{
string strWriteSchemaPiece;
bool success = true;
string dt = string.Format("{0:yyyyMMddHHmmss}", System.DateTime.Now);
strWriteSchemaPiece = "UPDATE " + table + " SET " + table + ".Info = '" + schpiece.Replace("\'", "'") + "'";
strWriteSchemaPiece = strWriteSchemaPiece + ", ModDateTime = '" + dt + "' WHERE RecID = '" + Recid + "';";
try
{
DBE.Command(strWriteSchemaPiece);
DBE.Reader();
}
catch (Exception e)
{
success = false;
MessageBox.Show(e.Message, "Database Update Error");
}
DBE.ReaderClose();
DBE.CommandDispose();
return success;
}
public override bool RODB_ProcessRROFieldChange(VlnXmlElement child, string oldname, string newname, uint editlevel,
VlnStatusMessage StatMsgWindow, bool combofield)
{
bool success;
string str;
string info;
string tinfo1, tinfo2, tinfo3, tinfo4;
string dt;
string onameOpen, nnameOpen, onameClose, nnameClose, onameComma, nnameComma;
string onameOpenX, nnameOpenX;
onameOpen = "<" + oldname + ">";
nnameOpen = "<" + newname + ">";
onameOpenX = "<" + oldname + ">";
nnameOpenX = "<" + newname + ">";
onameComma = "<" + oldname + ","; // if format in attribute
nnameComma = "<" + newname + ",";
onameClose = "" + oldname + ">";
nnameClose = "" + newname + ">";
dt = string.Format("{0:yyyyMMddHHmmss}", System.DateTime.Now);
try
{
// first do the string replace for the group node. This will change any
// attributes which may have changed.
str = "SELECT Info From " + child.GetAttribute("Table") + " where (RecID = '" + child.GetAttribute("RecID") + "')";
DBE.Command(str);
DBE.Reader();
if (DBE.Read())
info = DBE.GetString(0);
else
info = null;
DBE.ReaderClose();
DBE.CommandDispose();
tinfo1 = info.Replace(onameOpen, nnameOpen);
tinfo2 = tinfo1.Replace(onameClose, nnameClose);
tinfo3 = tinfo2.Replace(onameComma, nnameComma);
tinfo4 = tinfo3.Replace(onameOpenX, nnameOpenX);
if (tinfo4 != info)
{
StatMsgWindow.StatusMessage = child.GetAttribute("MenuTitle");
str = "UPDATE " + child.GetAttribute("Table") + " SET Info = '" + tinfo4 + "'";
str = str + ", ModDateTime = '" + dt + "' WHERE RecID = '" + child.GetAttribute("RecID") + "';";
DBE.Command(str);
DBE.Reader();
DBE.ReaderClose();
DBE.CommandDispose();
if (child.Name == "vlnGroup" && child.ParentNode.Name != "RO_Root")
{
XmlNodeList nodeList;
nodeList = child.SelectNodes(oldname);
foreach (XmlNode nod in nodeList)
{
XmlNode newnode = ROXml.CreateNode(XmlNodeType.Element, newname, "");
newnode.InnerXml = nod.InnerXml;
child.ReplaceChild(newnode, nod);
}
}
// if at top, replace strings in attributes for xml node. Only needs done
// for top node because remainder are done in xml string replace for entire
// node and written to database, but XML tree is deleted from memory and
// reread in as needed.
if (child.ParentNode.Name == "RO_Root")
{
string tmp, tmp1;
tmp = child.GetAttribute("RetVal");
if (tmp != null)
{
tmp1 = tmp.Replace(onameOpen, nnameOpen);
child.SetAttribute("RetVal", tmp1);
}
tmp = child.GetAttribute("MenuItem");
if (tmp != null)
{
string conameOpen = "<" + oldname + ",";
string cnnameOpen = "<" + newname + ",";
tmp1 = tmp.Replace(onameOpen, nnameOpen);
string tmp2 = tmp1.Replace(conameOpen, cnnameOpen);
child.SetAttribute("MenuItem", tmp2);
}
tmp = child.GetAttribute("AccPageID");
if (tmp != null)
{
tmp1 = tmp.Replace(onameOpen, nnameOpen);
child.SetAttribute("AccPageID", tmp1);
}
tmp = child.GetAttribute("GroupMenuItem");
if (tmp != null)
{
tmp1 = tmp.Replace(onameOpen, nnameOpen);
child.SetAttribute("GroupMenuItem", tmp1);
}
}
}
// if this was an RO field definition change, need to go through the XML for
// the ROs too.
if (editlevel == (uint)RecordType.Schema)
{
XmlNode chldnode = (XmlNode)child.FirstChild;
VlnXmlElement echild;
while (chldnode != null)
{
if (chldnode is VlnXmlElement)
{
echild = (VlnXmlElement)chldnode;
if (echild.Name != "vlnGroup")
{
// If this is a group defintion subtree it will only have one
// child, which is the text definition for the subgroup. Don't
// include these in the tree.
int levelCnt = chldnode.ChildNodes.Count;
string TheMenuTitle = echild.GetAttribute("MenuTitle");
if ((levelCnt >= 1) && !TheMenuTitle.Equals(""))
{
// read record, do string replace in info & write record. Also, replace
// the xml node with a node with the new name.
str = "SELECT Info From " + echild.GetAttribute("Table") + " where (RecID = '" + echild.GetAttribute("RecID") + "')";
DBE.Command(str);
DBE.Reader();
if (DBE.Read())
info = DBE.GetString(0);
else
info = null;
DBE.ReaderClose();
DBE.CommandDispose();
if (info != null) info = info.Replace("\'", "&apos"); // B2021-071: crash when getting/saving field names
if (combofield == false)
{
tinfo1 = info.Replace(onameOpen, nnameOpen);
tinfo1 = DoReplaceParentChildField(tinfo1, onameOpen, nnameOpen); //C2021-0226 also update Parent/Child fields
tinfo2 = tinfo1.Replace(onameClose, nnameClose);
tinfo2 = DoReplaceParentChildField(tinfo2, onameClose, nnameClose); //C2021-0226 also update Parent/Child fields
XmlNodeList nodeList;
nodeList = echild.SelectNodes(oldname);
foreach (XmlNode nod in nodeList)
{
XmlNode newnode = ROXml.CreateNode(XmlNodeType.Element, newname, "");
newnode.InnerXml = nod.InnerXml;
echild.ReplaceChild(newnode, nod);
}
}
else // need a,b,c,d yikes
{
string nma, nmb, nmc, nmd;
nma = DoCmbFieldReplace(info, onameOpen, nnameOpen, "a");
nmb = DoCmbFieldReplace(nma, onameOpen, nnameOpen, "b");
nmc = DoCmbFieldReplace(nmb, onameOpen, nnameOpen, "c");
nmd = DoCmbFieldReplace(nmc, onameOpen, nnameOpen, "d");
nma = DoCmbFieldReplace(nmd, onameClose, nnameClose, "a");
nmb = DoCmbFieldReplace(nma, onameClose, nnameClose, "b");
nmc = DoCmbFieldReplace(nmb, onameClose, nnameClose, "c");
tinfo2 = DoCmbFieldReplace(nmc, onameClose, nnameClose, "d");
// replace the combo nodes with the new name, do a-d in case there are more than
// one value field stored for this combo type
for (char tmplet = 'a'; tmplet < 'e'; tmplet++)
{
XmlNodeList nodeList;
nodeList = echild.SelectNodes(oldname + tmplet.ToString());
foreach (XmlNode nod in nodeList)
{
XmlNode newnode = ROXml.CreateNode(XmlNodeType.Element, newname + tmplet, "");
newnode.InnerXml = nod.InnerXml;
echild.ReplaceChild(newnode, nod);
}
}
}
StatMsgWindow.StatusMessage = echild.GetAttribute("MenuTitle");
str = "UPDATE " + echild.GetAttribute("Table") + " SET Info = '" + tinfo2 + "'";
str = str + ", ModDateTime = '" + dt + "' WHERE RecID = '" + echild.GetAttribute("RecID") + "';";
DBE.Command(str);
DBE.Reader();
DBE.ReaderClose();
DBE.CommandDispose();
}
}
}
chldnode = chldnode.NextSibling;
}
}
return true;
}
catch (Exception e)
{
success = false;
MessageBox.Show(e.Message, "Database Update Error");
}
return success;
}
public override bool RODB_UpdateFieldRecord(ROField myrof, VlnXmlElement myelem, string strschema,
string oldname, string newname, uint editlevel, bool combofield)
{
bool success = false;
// If this is a generic definition that was modified, i.e. from ROMaster, ask
// the user whether to update the generic field definition or make it local.
if (myrof.GetMasterRecID != null)
{
// if field is defined in the ROMaster, and we change the field name -
// first check if it is using one of the names used to define new
// setpoint or graphics databases. If so, make it a local change only!
bool changegeneric = true;
if (oldname != newname)
{
// if this is one of the standard names - don't let them save it.
bool isused = RODB_CheckForStandardName(oldname);
if (isused == true)
{
MessageBox.Show("The field name is used to define new Setpoints or Graphics Database.\n The update will be for this local (database) group only.", "Field name modification.");
changegeneric = false;
}
}
// if standard name, from above check, don't ask user if it is generic
// or not.
if (changegeneric != false)
{
// B2021-072: don't update name if user selects No on dialog. This is actually misleading, because Yes updates
// Generic definition, i.e. all Groups, and No updates only Local definition, i.e. just this Group Added a
// Cancel button to Cancel from this dialog and return to previous dialog. Added more information to the
// dialog to inform user of this
string dmsg = $"Update Generic definition?\r\n\r\n Yes - updates Generic definitions, \r\n No - updates Local definitions, \r\n Cancel - returns to previous dialog." +
$"\r\n\r\n 'Generic' updates definition in ALL groups that use the name\r\n 'Local' updates definition only in the selected group, and will change the definition for all items in that table ({GetTopParentName(myelem)}).";
System.Windows.Forms.DialogResult result = MessageBox.Show(dmsg, "Referenced Object Definition", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
if (result == DialogResult.Cancel) return false;
if (result == DialogResult.No) changegeneric = false;
}
if (changegeneric == true)
{
success = RODB_WriteSchemaPiece(myrof.GetMasterRecID, "ROMaster", strschema);
if (success != true) return false;
// if change in fieldname, need to go through all of the databases to
// adjust for it.
if (oldname != newname)
{
VlnStatusMessage StatMsgWindow = new VlnStatusMessage("Status of RO Field Change");
// get root xml element
// loop through each subgroup under root.
VlnXmlElement topgroup;
topgroup = (VlnXmlElement)ROXml.FirstChild.FirstChild;
string sqlstr, recid, tbl;
while (topgroup != null)
{
tbl = topgroup.GetAttribute("Table");
// get the recid of this field definition from the current table.
sqlstr = "SELECT RecID FROM " + tbl;
sqlstr = sqlstr + " WHERE (((" + tbl + ".RecType) = 2) AND ((" + tbl + ".Info) like ('";
sqlstr = sqlstr + myrof.GetMasterRecID + "%')));";
DBE.Command(sqlstr);
DBE.Reader();
if (DBE.Read())
recid = DBE.GetString(0);
else
recid = null;
DBE.ReaderClose();
DBE.CommandDispose();
if (recid != null)
{
// update the local field definition record
StringBuilder strbld = new StringBuilder();
strbld.Append(myrof.GetMasterRecID);
strbld.Append(" ");
string strtype = myrof.GetFieldType.ToString();
strbld.Append(strtype.PadLeft(3, '0'));
strbld.Append(" ");
strbld.Append(myrof.MakeFieldName(myrof.GetFieldname));
success = RODB_WriteSchemaPiece(recid, topgroup.GetAttribute("Table"), strbld.ToString());
topgroup.SetAttribute("TreeNotData", "True");
// Update subelements too.
if (success == true)
success = RODB_UpdateFieldNames(topgroup, recid, oldname, newname, editlevel, false, StatMsgWindow, combofield);
//topgroup = (VlnXmlElement)topgroup.NextSibling;
}
topgroup = (VlnXmlElement)topgroup.NextSibling; // B2021-071: infinite loop (moved this from above loop
}
StatMsgWindow.Dispose();
}
}
else // change local
{
// modify the current to have the definition local.
success = RODB_WriteSchemaPiece(myrof.GetRecID, myelem.GetAttribute("Table"), strschema);
// get top group node in tree. and from there process fields if
// there was a change in fieldname text
if (success == true && oldname != newname)
{
VlnStatusMessage StatMsgWindow = new VlnStatusMessage("Status of RO Field Change");
// get top node - the one immediately below the RO_Root.
VlnXmlElement parent, startEle;
parent = myelem;
startEle = myelem;
while (parent.Name != "RO_Root")
{
startEle = parent;
parent = (VlnXmlElement)parent.ParentNode;
}
startEle.SetAttribute("TreeNotData", "True");
success = RODB_UpdateFieldNames(startEle, myrof.GetRecID, oldname, newname, editlevel, false, StatMsgWindow, combofield);
StatMsgWindow.Dispose();
}
}
}
else
{
success = RODB_WriteSchemaPiece(myrof.GetRecID, myelem.GetAttribute("Table"), strschema);
// changed the fieldname, change xml text.
if (success == true && oldname != newname)
{
VlnStatusMessage StatMsgWindow = new VlnStatusMessage("Status of RO Field Change");
// get top node - the one immediately below the RO_Root.
VlnXmlElement parent, startEle;
parent = myelem;
startEle = myelem;
while (parent.Name != "RO_Root")
{
startEle = parent;
parent = (VlnXmlElement)parent.ParentNode;
}
startEle.SetAttribute("TreeNotData", "True");
success = RODB_UpdateFieldNames(startEle, myrof.GetRecID, oldname, newname, editlevel, false, StatMsgWindow, combofield);
StatMsgWindow.Dispose();
}
}
return success;
}
//CSM-C2024-030
//Explain that Local is local to that table (and include Table name in wording displayed to user)
public string GetTopParentName(VlnXmlElement elem)
{
VlnXmlElement nodetocheck = elem;
while (nodetocheck.GetAttribute("ParentID") != "00000000" && nodetocheck.ParentNode != null)
{
nodetocheck = (VlnXmlElement) nodetocheck.ParentNode;
}
return nodetocheck.GetAttribute("MenuTitle");
}
public override XmlSchema RODB_GetGroupSchema(VlnXmlElement elem)
{
XmlSchema myschema;
VlnXmlElement parent;
string entireschema;
// if at top of tree, use this group schema information (fields in use). but if not,
// the parent node defines the schema for the subgroups.
if (elem.ParentNode.Name == "RO_Root")
parent = elem;
else
parent = elem;
// bug fix B2004-008
// need to use the current node's group definition all the time
// parent = (VlnXmlElement) elem.ParentNode;
while (parent != null)
{
if (parent.HasAttribute("GroupFieldsInUse") == true) break;
// if we've looped to the top, just set the parent to null. (B2004-015)
if (parent.ParentNode is VlnXmlElement)
parent = (VlnXmlElement)parent.ParentNode;
else
parent = null;
}
if (parent == null) return null;
// The group schema never gets saved as an attribute. it's always read in, because
// it's not used as often as the ro schema. So for the Group Schema, we're looking
// for 'GroupFieldsInUse'.
// otherwise, read in schema definitions for those 'FieldsInUse'.
string strGetSchemaPiece;
entireschema = null;
string GroupFieldsInUse = parent.GetAttribute("GroupFieldsInUse");
int strpos = 0;
string Info;
// For each item in use, get its xmlschema text. If unique to this group, the definition
// exists local to this table. Otherwise, go back to the master.
string recid;
recid = GroupFieldsInUse.Substring(0, 8);
while (recid != null)
{
strGetSchemaPiece = "SELECT Info From " + elem.GetAttribute("Table") + " where (RecID = '" + recid + "')";
DBE.Command(strGetSchemaPiece);
DBE.Reader();
if (DBE.Read())
{
Info = DBE.GetString(0);
// if the info string has "<", i.e. an opening XML schema bracket, use
// this text as the field definition, otherwise, go to the master to get
// it.
if ("<" == Info.Substring(0, 1))
{
// use this field definition, else get from the master.
entireschema = entireschema + Info;
}
else
{
string recidpart = Info.Substring(0, 8);
strGetSchemaPiece = "SELECT Info From RoMaster where (RecID = '" + recidpart + "')";
DBE.ReaderClose();
DBE.CommandDispose();
DBE.Command(strGetSchemaPiece);
DBE.Reader();
if (DBE.Read())
{
Info = DBE.GetString(0);
entireschema = entireschema + Info;
}
}
DBE.ReaderClose();
DBE.CommandDispose();
strpos = strpos + 9;
if (strpos > GroupFieldsInUse.Length)
recid = null;
else
recid = GroupFieldsInUse.Substring(strpos, 8);
}
DBE.ReaderClose();
DBE.CommandDispose();
}
entireschema = schemastart + entireschema + schemaend;
XmlTextReader schemareader = new XmlTextReader(entireschema, XmlNodeType.Element, null);
try
{
myschema = XmlSchema.Read(schemareader, null);
return myschema;
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Schema Error");
return null;
}
}
public override XmlSchema RODB_GetSchema(VlnXmlElement elem)
{
XmlSchema myschema;
VlnXmlElement parent;
string entireschema;
XmlNode nparent;
nparent = elem; //.ParentNode;
if (nparent is VlnXmlDocument)
{
// at top already. use this one.
parent = elem;
}
else
{
parent = (VlnXmlElement)nparent;
while (parent != null)
{
if (parent.HasAttribute("Schema") == true) break;
if (parent.HasAttribute("FieldsInUse") == true) break;
parent = (VlnXmlElement)parent.ParentNode;
}
}
// if the schema has already been read in, just use it from the schema attribute,
// otherwise, read in schema definitions for those 'FieldsInUse'.
if (parent.HasAttribute("Schema"))
{
entireschema = parent.GetAttribute("Schema");
}
else
{
string strGetSchemaPiece;
entireschema = null;
string FieldsInUse = parent.GetAttribute("FieldsInUse");
int strpos = 0;
string Info;
// For each item in use, get its xmlschema text. If unique to this group, the definition
// exists local to this table. Otherwise, go back to the master.
string recid;
recid = FieldsInUse.Substring(0, 8);
while (recid != null)
{
strGetSchemaPiece = "SELECT Info From " + elem.GetAttribute("Table") + " where (RecID = '" + recid + "')";
DBE.Command(strGetSchemaPiece);
DBE.Reader();
if (DBE.Read())
{
Info = DBE.GetString(0);
// if the info string has "<", i.e. an opening XML schema bracket, use
// this text as the field definition, otherwise, go to the master to get
// it.
if ("<" == Info.Substring(0, 1))
{
// use this field definition, else get from the master.
entireschema = entireschema + Info;
}
else
{
string recidpart = Info.Substring(0, 8);
string localfieldname = Info.Substring(13, Info.Length - 13);
strGetSchemaPiece = "SELECT Info From RoMaster where (RecID = '" + recidpart + "')";
DBE.ReaderClose();
DBE.CommandDispose();
DBE.Command(strGetSchemaPiece);
DBE.Reader();
if (DBE.Read())
{
// check if field name is same, if not, use local name.
string goodname;
Info = DBE.GetString(0);
int indx1 = Info.IndexOf("\"");
int indx2 = Info.IndexOf("\"", indx1 + 1);
string masterfieldname = Info.Substring(indx1 + 1, indx2 - indx1 - 1);
if (localfieldname != masterfieldname)
goodname = Info.Replace(masterfieldname, localfieldname);
else
goodname = Info;
entireschema = entireschema + goodname;
}
}
DBE.ReaderClose();
DBE.CommandDispose();
strpos = strpos + 9;
if (strpos > FieldsInUse.Length)
recid = null;
else
recid = FieldsInUse.Substring(strpos, 8);
}
}
DBE.ReaderClose();
DBE.CommandDispose();
entireschema = schemastart + entireschema + schemaend;
}
XmlTextReader schemareader = new XmlTextReader(entireschema, XmlNodeType.Element, null);
try
{
myschema = XmlSchema.Read(schemareader, null);
parent.SetAttribute("Schema", entireschema);
return myschema;
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Schema Read Error");
return null;
}
}
public override int RODB_GetNumberOfROValueRecords(string tablename)
{
// get menu fields to display here.
string strGetRoCount = "SELECT COUNT(RecType) AS NumRecs FROM " + tablename;
strGetRoCount += " WHERE RecType = " + (uint)RecordType.RRO;
DBE.Command(strGetRoCount);
DBE.Reader();
DBE.Read();
int ROCnt = DBE.GetInt32(0);
DBE.ReaderClose();
DBE.CommandDispose();
return ROCnt;
}
public override int RODB_GetNumberOfGroupRecords(string tablename)
{
// get menu fields to display here.
string strGetGrpCount = "SELECT COUNT(RecType) AS NumRecs FROM " + tablename;
strGetGrpCount += " WHERE RecType = " + (uint)RecordType.Group;
DBE.Command(strGetGrpCount);
DBE.Reader();
DBE.Read();
int GrpCnt = DBE.GetInt32(0);
DBE.ReaderClose();
DBE.CommandDispose();
return GrpCnt;
}
}
}