In this step we will create a few classes (essentially our Data Tier) to hold the UDTs that we created in the first article; we will also create a reusable project that will allow us to easily import Palm databases into this data tier, and finally we will hook into an existing project to handle the WebLogAPI details. In the default project within VS .NET create a new class named "DataTier.cs". We will use this to hold all three of the data tier classes. Figure 1 below is the final output of all three of these classes. Notice that each class has a few properties associated with the Palm database itself. It is important to note the actual order of the properties in each class because we rely on these when we move on to importing the data from the synchronization process.
Figure 1 List of BlogEntry, BlogSetting, sTypes Types
using System;
namespace PBlgConduit.DataTier {
///<summary>
/// Used to be the managed representation of the BlogEntry UDT from the Palm
Database
/// Type BlogEntry
/// subject as String 'subject of the
entry
/// dDate as String 'date of the entry
/// entry as String 'the actuall full text entry
/// settingsName as String 'matching
settings name
/// End Type
///</summary>
publicclass BlogEntry {
/*app specific attributes*/
string key;
string subject;
string dDate;
string entry;
string settingsName;
publicstring Key{get{return key;}set{key=value;}}
publicstring Subject{get{return subject;}set{subject=value;}}
publicstring DDate{get{return dDate;}set{dDate=value;}}
publicstring Entry{get{return entry;}set{entry=value;}}
publicstring SettingsName{get{return settingsName;}set{settingsName=value;}}
/*Palm DB Specific attributes
for each record*/
private PDStandardLib.ERecordAttributes eAttributes;
privateint nIndex;
privateint nCategory;
privateobject vUniqueId;
privatebyte[] raw;
publicbyte[] Raw{get{return raw;}set{raw=value;}}
public PDStandardLib.ERecordAttributes EAttributes{get{return eAttributes;}set{eAttributes=value;}}
publicint Index{get{return nIndex;}set{nIndex=value;}}
publicint Category{get{return nCategory;}set{nCategory=value;}}
publicobject UniqueId{get{return vUniqueId;}set{vUniqueId=value;}}
public BlogEntry() {
}
public BlogEntry(string Subject, string DDate, string Entry, string SettingsName) {
subject=Subject;
dDate=DDate;
entry=Entry;
settingsName=SettingsName;
}
}
///<summary>
/// Used to represent the managed version of the BlogSetting UDT
/// Type BlogSetting
/// Name as String 'name of the setting, key
/// isDefault as Integer 'if this is the
default setting
/// sType as Integer 'type of setting it is
/// username as String 'username to use
during auth
/// password as String 'password to use during
auth
/// port as Integer 'what port is the
remote service running on
/// domain as String 'what domain/ip is
the remote server
/// path as String 'file path to the save
location
/// filename as String 'ftp file name,
/// 'http variable post name For xml
upload
/// 'or url end point
/// End Type
///</summary>
publicclass BlogSetting {
string key;
string name;
int isDefault;
string sType;
string username;
string password;
int port;
string domain;
string path;
string filename;
publicstring Key{get{return key;}set{key=value;}}
publicstring Name{get{return name;}set{name=value;}}
publicint IsDefault{get{return isDefault;}set{isDefault=value;}}
publicstring SType{get{return sType;}set{sType=value;}}
publicstring Username{get{return username;}set{username=value;}}
publicstring Password{get{return password;}set{password=value;}}
publicint Port{get{return port;}set{port=value;}}
publicstring Domain{get{return domain;}set{domain=value;}}
publicstring Path{get{return path;}set{path=value;}}
publicstring Filename{get{return filename;}set{filename=value;}}
/*Palm DB Specific attributes
for each record*/
private PDStandardLib.ERecordAttributes eAttributes;
privateint nIndex;
privateint nCategory;
privateobject vUniqueId;
privatebyte[] raw;
publicbyte[] Raw{get{return raw;}set{raw=value;}}
public PDStandardLib.ERecordAttributes EAttributes{get{return eAttributes;}set{eAttributes=value;}}
publicint Index{get{return nIndex;}set{nIndex=value;}}
publicint Category{get{return nCategory;}set{nCategory=value;}}
publicobject UniqueId{get{return vUniqueId;}set{vUniqueId=value;}}
public BlogSetting() {
}
public BlogSetting(string Name,int IsDefault,string SType,string Username,string Password,int Port,string Domain,string Path,string Filename) {
name=Name;
isDefault=IsDefault;
sType=SType;
username=Username;
password=Password;
port=Port;
domain=Domain;
path=Path;
filename=Filename;
}
}
}
Next we will add a new C# Class Library project to the solution named "PalmDBImporter", which will contain a simple class that will allow us to easily import the Palm databases into our data tier classes above. The sole reason why I want to create this as a new project is so that we can reuse this project in future solutions, since it will be a generic Palm database importer. Make sure you add a project reference in the PBlgConduit solution to the new project. Figure 2 below shows the code listing for this class.
Figure 2: Palm Database Importer
using System;
namespace PalmDBImporter {
///<summary>
/// Class used to import the byte[] from the Palm Synch process and bind it to a
Class, based on NULL \0 values and reflection
///</summary>
publicclass Importer {
///<summary>
/// called with an instantiated class and the byte[] of
data. It will attempt to move the data
into the class based on its public properties.
///</summary>
///<param
name="Class"></param>
///<param
name="data"></param>
///<returns></returns>
publicstaticbool BindToClass(object Class, byte[] data) {
try {
//get a list of
all the available properties
System.Reflection.PropertyInfo[] props =
Class.GetType().GetProperties();
int pCounter=0;
int bCounter=0;
//create a temp
buffer to hold current data
byte[]
propData = newbyte[data.Length];
//if we actually
have any public properties
if(props!=null && props.Length>0) {
//grab
the current property
System.Reflection.PropertyInfo
currentProp = props[pCounter];
//iterate
over the entire length of the data
for(int x=0;x<data.Length;x++) {
//if
it is a null value, then we hit a field terminator
if(data[x]==0)
{
//grab the bytes from the data into our temp buffer
byte[] newData = newbyte[bCounter];
newData =
GetBytes(propData, 0, bCounter);
//convert the bytes to a string
string val =
System.Text.ASCIIEncoding.ASCII.GetString(newData);
//set the value into the property
try {
//we are only gonna handle 3 data types right now
//boolean, string and numbers
string propType=currentProp.PropertyType.FullName.ToLower().Replace("system.","");
object[] propValue=GetValue(propType, val);
Class.GetType().InvokeMember(currentProp.Name,
System.Reflection.BindingFlags.SetProperty, null,
Class, propValue);
}catch(Exception exc) {
string f = exc.ToString();
//do nothing
}
pCounter++;
//if we have any more properties, lets continue
if(pCounter<props.Length) {
currentProp =
props[pCounter];
propData = newbyte[data.Length];
bCounter=0;
} else {
break;
}
} else {
//shove the current value into the temp buffer
propData[bCounter]=data[x];
bCounter++;
}
}
}
returntrue;
}catch(Exception
e) {
returnfalse;
}
}
///<summary>
/// Fix up the string to match HTML output for Weblogs
///</summary>
///<param
name="str"></param>
///<returns></returns>
publicstaticstring FixString(string str) {
str = str.Replace("\r\n", "<br
/>");
str = str.Replace("\r", "<br
/>");
str = str.Replace("\n", "<br
/>");
return str;
}
publicstaticobject[]
GetValue(string propType, string val) {
object[]
propValue=newobject[]{null};
try {
#region switch block for all data
types
switch(propType)
{
case "boolean":
case "bool":
propValue[0] =
System.Boolean.Parse(val);
break;
case "float":
propValue[0] = float.Parse(val);
break;
case "decimal":
propValue[0] = decimal.Parse(val);
break;
case "double":
propValue[0] = double.Parse(val);
break;
case "int16":
propValue[0] = int.Parse(val);
break;
case "int32":
propValue[0] = int.Parse(val);
break;
case "int64":
propValue[0] = long.Parse(val);
break;
case "single":
propValue[0] = short.Parse(val);
break;
case "long":
propValue[0] = long.Parse(val);
break;
case "short":
propValue[0] = short.Parse(val);
break;
case "uint":
propValue[0] = uint.Parse(val);
break;
case "uint16":
propValue[0] = uint.Parse(val);
break;
case "uint32":
propValue[0] = ulong.Parse(val);
break;
case "uint64":
propValue[0] = ulong.Parse(val);
break;
case "ulong":
propValue[0] = ulong.Parse(val);
break;
case "ushort":
propValue[0] = ushort.Parse(val);
break;
default:
propValue[0]=FixString(val);
break;
}
#endregion
}catch{}
return propValue;
}
///<summary>
/// used to get a range of bytes out of an existing byte[]
block
///</summary>
///<param
name="data"></param>
///<param
name="start"></param>
///<param
name="count"></param>
///<returns></returns>
publicstaticbyte[]
GetBytes(byte[] data, int start, int count) {
byte[] b = newbyte[count];
int ctr=0;
//copy over the bytes
for(int x=start;x<count;x++) {
b[ctr]=data[x];
ctr++;
}
retu