For the Wednesday, 2/25/2009 Impact SIG conference call,
attached are: the PowerPoint file (CustomODLa.ppt)
containing the contents of the Custom ODL Function
presentation, a sample Production Object (odlfilt.prj and
odlfilt.mod) which illustrates the code from some of the
PowerPoint slides, and a Test Drive data file for the sample
Production Object (diet.dat).

#dll lib1 "cltran.dll"
#dll lib2 "cltrnide.dll"
#dll lib3 "clfile.dll"
#dll lib4 "clmtbl.dll"
#dll lib5 "clrepo.dll"
#dll lib6 "clutil.dll"
#dll lib7 "cltdmsql.dll"
#dll lib8 "cldbi.dll"
#dll lib9 "cltbl.dll"
#dll lib10 "clproto.dll"
#include "odlfilt.mod"

module odlfilt

static CombinedQual_func( string fldval );
static FmtDate_func( blob *pb, char mode, string args );
static HexDecConv_func( blob *pb, char mode, string args );
static CallBuiltin_func( blob *pb, char mode, string args );
static CancelDietOrders_func( blob *pb, char mode, string args );
static Mode_func( blob *pb, char mode, string args );
static CallTest_func( blob *pb, char mode, string args );
static CallBuiltinWithArgs_func( blob *pb, char mode, string args );
static CallJustifyBuiltin_func( blob *pb, char mode, string args );

static object PIDEnd : clTrFld
{ arguments
{
RsFtFLD = 1;
RsFoAfter = 1;
RsFoEORLen = 1;
RsFoSubfld = 1;
RsFoff = -1;
RsFtRaw = 1;
RsFtX = 1;
RsFcASCI = 1;
RsFlocRef = PIDHeader;
RsFparentRef = PIDSegment;
RsFoper = 3;
};
};

static object PIDHeader : clTrFld
{ arguments
{
RsFtFLD = 1;
RsFoRedef = 1;
RsFoSepRef = 1;
RsFoEORLen = 1;
RsFoSubfld = 1;
RsFoOptional = 1;
RsFoff = -1;
RsFtRaw = 1;
RsFtX = 1;
RsFcASCI = 1;
RsFlocRef = PIDSegment;
RsFsepRef = MSHFieldSeparator;
RsFparentRef = PIDSegment;
RsFoper = 3;
RsFoSepRefFldSrc = 1;
};
};

static object PIDSegment : clTrFld
{ arguments
{
RsFtFLD = 1;
RsFoSep = 1;
RsFoOffPat = 1;
RsFoInclSep = 1;
RsFoff = -1;
RsFtRaw = 1;
RsFtX = 1;
RsFcASCI = 1;
RsFsep = '\015';
RsFlocRef = MSHSegment;
RsFoffPattern = "PID";
RsFoper = 3;
RsFoPscopeSiz = 1;
RsPatScope = 4;
RsFIsAParent = 1;
};
};

static object MSHSendingApplication : clTrFld
{ arguments
{
RsFtFLD = 1;
RsFoAfter = 1;
RsFoSepRef = 1;
RsFoSubfld = 1;
RsFoff = -1;
RsFtRaw = 1;
RsFtX = 1;
RsFcASCI = 1;
RsFlocRef = MSHSeparatorCharacters;
RsFsepRef = MSHFieldSeparator;
RsFparentRef = MSHSegment;
RsFoper = 3;
RsFoSepRefFldSrc = 1;
};
};

static object CombinedQual_qual : clQual
{ arguments
{
RsQoCustom = 1;
RsQoFldSrc = 1;
RsQfunc = CombinedQual_func;
};
};

static object MultiQual_rc : clPart
{ arguments
{
RsPoLit = 1;
RsLit = "COMBINED_QUAL_TRUE";
};
controls
{
clQual CombinedQual_qual;
};
};

static object XYZ_qual : clQual
{ arguments
{
RsQoTable = 1;
RsQoFldSrc = 1;
RsMulticol = 1;
RsRef = MSHEnd;
RsTable = "strings";
RsKeyCol = "0";
};
};

static object PID_qual : clQual
{ arguments
{
RsQoTable = 1;
RsQoFldSrc = 1;
RsMulticol = 1;
RsRef = PIDHeader;
RsTable = "strings";
RsKeyCol = "0";
};
};

static object DIET_qual : clQual
{ arguments
{
RsQoFld = 1;
RsQoFldLit = 1;
RsQoFldSrc = 1;
RsRef = MSHSendingApplication;
RsVal = "DIET";
RsQop = 1;
RsKeyCol = "0";
};
};

static object MSH_qual : clQual
{ arguments
{
RsQoTable = 1;
RsQoFldLit = 1;
RsQoFldSrc = 1;
RsMulticol = 1;
RsRef = MSHHeader;
RsTable = "strings";
RsKeyCol = "0";
};
};

static object CallTest_filt : clFilter
{ arguments
{
RsFunc = CallTest_func;
RsCustom = 1;
};
};

static object MSHComponentSeparator : clTrFld
{ arguments
{
RsFtFLD = 1;
RsFoRedef = 1;
RsFoAbsLen = 1;
RsFoSubfld = 1;
RsFoff = -1;
RsFlen = 1;
RsFtRaw = 1;
RsFtX = 1;
RsFcASCI = 1;
RsFlocRef = MSHSeparatorCharacters;
RsDataLnk = CompSep_dl;
RsFparentRef = MSHSeparatorCharacters;
RsFoper = 3;
};
};

static object MSHRepetitionSeparator : clTrFld
{ arguments
{
RsFtFLD = 1;
RsFoAfter = 1;
RsFoAbsLen = 1;
RsFoSubfld = 1;
RsFoff = -1;
RsFlen = 1;
RsFtRaw = 1;
RsFtX = 1;
RsFcASCI = 1;
RsFlocRef = MSHComponentSeparator;
RsFparentRef = MSHSeparatorCharacters;
RsFoper = 3;
};
};

static object MSHEscapeCharacter : clTrFld
{ arguments
{
RsFtFLD = 1;
RsFoAfter = 1;
RsFoAbsLen = 1;
RsFoSubfld = 1;
RsFoff = -1;
RsFlen = 1;
RsFtRaw = 1;
RsFtX = 1;
RsFcASCI = 1;
RsFlocRef = MSHRepetitionSeparator;
RsFparentRef = MSHSeparatorCharacters;
RsFoper = 3;
};
};

static object MSHSubComponentSeparator : clTrFld
{ arguments
{
RsFtFLD = 1;
RsFoAfter = 1;
RsFoAbsLen = 1;
RsFoSubfld = 1;
RsFoff = -1;
RsFlen = 1;
RsFtRaw = 1;
RsFtX = 1;
RsFcASCI = 1;
RsFlocRef = MSHEscapeCharacter;
RsFparentRef = MSHSeparatorCharacters;
RsFoper = 3;
};
};

static object MSHEnd : clTrFld
{ arguments
{
RsFtFLD = 1;
RsFoAfter = 1;
RsFoEORLen = 1;
RsFoSubfld = 1;
RsFoff = -1;
RsFtRaw = 1;
RsFtX = 1;
RsFcASCI = 1;
RsFlocRef = MSHSendingApplication;
RsFparentRef = MSHSegment;
RsFoper = 3;
};
};
static string FieldSep_dl;
static string CompSep_dl;

static object Mode_filt : clFilter
{ arguments
{
RsFunc = Mode_func;
RsCustom = 1;
};
};

static object CallBuiltinWithArgs_rc : clPart
{ arguments
{
RsPoFld = 1;
RsRef = MessageEnd;
};
controls
{
clFilter CallBuiltinWithArgs_filt;
};
};

static object CallBuiltinWithArgs_filt : clFilter
{ arguments
{
RsFunc = CallBuiltinWithArgs_func;
RsCustom = 1;
};
};

static object CallJustifyBuiltin_rc : clPart
{ arguments
{
RsPoFld = 1;
RsRef = MSHEnd;
};
controls
{
clFilter CallJustifyBuiltin_filt;
};
};

static object CallJustifyBuiltin_filt : clFilter
{ arguments
{
RsFunc = CallJustifyBuiltin_func;
RsCustom = 1;
};
};

static object FmtDate_filt : clFilter
{ arguments
{
RsFunc = FmtDate_func;
RsArgs = "MMDDYY";
RsCustom = 1;
RsMode = 4;
};
};

static object FmtDate_rc : clPart
{ arguments
{
RsPoLit = 1;
RsLit = "091808";
};
controls
{
clFilter FmtDate_filt;
};
};

static object HexDecConv_filt : clFilter
{ arguments
{
RsFunc = HexDecConv_func;
RsCustom = 1;
};
};

static object HexDecConv_rc : clPart
{ arguments
{
RsPoLit = 1;
RsLit = "255";
};
controls
{
clFilter HexDecConv_filt;
};
};

static object CallBuiltin_filt : clFilter
{ arguments
{
RsFunc = CallBuiltin_func;
RsCustom = 1;
};
};

static object CallBuiltin_rc : clPart
{ arguments
{
RsPoFld = 1;
RsRef = MSHHeader;
};
controls
{
clFilter CallBuiltin_filt;
};
};

static object CallBuiltin_rule : clRule
{ controls
{
clPart CallBuiltin_rc;
clPart CallBuiltinWithArgs_rc;
clPart CallJustifyBuiltin_rc;
clPart HexDecConv_rc;
clPart FmtDate_rc;
clPart MultiQual_rc;
};
};

static object Mode_rc : clPart
{ arguments
{
RsPoNone = 1;
};
controls
{
clFilter Mode_filt;
};
};

static object Mode_rule : clRule
{ controls
{
clPart Mode_rc;
};
};

static object CancelDietOrders_filt : clFilter
{ arguments
{
RsFunc = CancelDietOrders_func;
RsArgs = "DT100DT101DT102";
RsCustom = 1;
};
};

static object CancelDietOrders_rc : clPart
{ arguments
{
RsPoNone = 1;
};
controls
{
clFilter CancelDietOrders_filt;
};
};

static object CancelDietOrders_rule : clRule
{ controls
{
clPart CancelDietOrders_rc;
};
};

static object sample_prod : clTran
{ arguments
{
RsOpts = 144;
RsName = "sample_prod";
RsEoHalt = 1;
RsMode = 1;
};
controls
{
clTrFld MSHSegment;
clTrFld MSHHeader;
clTrFld MSHFieldSeparator;
clTrFld MSHSeparatorCharacters;
clTrFld MSHComponentSeparator;
clTrFld MSHRepetitionSeparator;
clTrFld MSHEscapeCharacter;
clTrFld MSHSubComponentSeparator;
clTrFld MSHSendingApplication;
clTrFld MSHEnd;
clTrFld PIDSegment;
clTrFld PIDHeader;
clTrFld PIDEnd;
clTrFld MessageEnd;
clRule Mode_rule;
clRule CallBuiltin_rule;
clRule CancelDietOrders_rule;
};
};

static object MSHSeparatorCharacters : clTrFld
{ arguments
{
RsFtFLD = 1;
RsFoAfter = 1;
RsFoSepRef = 1;
RsFoSubfld = 1;
RsFoff = -1;
RsFtRaw = 1;
RsFtX = 1;
RsFcASCI = 1;
RsFlocRef = MSHFieldSeparator;
RsFsepRef = MSHFieldSeparator;
RsFparentRef = MSHSegment;
RsFoper = 3;
RsFIsAParent = 1;
RsFoSepRefFldSrc = 1;
};
};

static object MessageEnd : clTrFld
{ arguments
{
RsFtFLD = 1;
RsFoAfter = 1;
RsFoEORLen = 1;
RsFoOptional = 1;
RsFoff = -1;
RsFtRaw = 1;
RsFtX = 1;
RsFcASCI = 1;
RsFlocRef = PIDSegment;
RsFoper = 3;
};
};

static object MSHSegment : clTrFld
{ arguments
{
RsFtFLD = 1;
RsFoSep = 1;
RsFoOffPat = 1;
RsFoInclSep = 1;
RsFoff = -1;
RsFtRaw = 1;
RsFtX = 1;
RsFcASCI = 1;
RsFsep = '\015';
RsFoffPattern = "MSH";
RsFoper = 3;
RsFoPscopeSiz = 1;
RsPatScope = 3;
RsFIsAParent = 1;
};
};

static object MSHHeader : clTrFld
{ arguments
{
RsFtFLD = 1;
RsFoRedef = 1;
RsFoAbsLen = 1;
RsFoSubfld = 1;
RsFoff = -1;
RsFlen = 3;
RsFtRaw = 1;
RsFtX = 1;
RsFcASCI = 1;
RsFlocRef = MSHSegment;
RsFparentRef = MSHSegment;
RsFoper = 3;
};
};

static object MSHFieldSeparator : clTrFld
{ arguments
{
RsFtFLD = 1;
RsFoAfter = 1;
RsFoAbsLen = 1;
RsFoSubfld = 1;
RsFoff = -1;
RsFlen = 1;
RsFtRaw = 1;
RsFtX = 1;
RsFcASCI = 1;
RsFlocRef = MSHHeader;
RsDataLnk = FieldSep_dl;
RsFparentRef = MSHSegment;
RsFoper = 3;
};
};
static int CombinedQual_func(string fldval)
{

// The qual() method allows access to any existing qualification objects within the current
// production object. By using it, you can create a new compound qualification object which
// combines your choice of existing qualifications in any logical relationship that you wish.
// Note that this lets you reference table qualification objects within your custom ODL function.

// MSH_qual, PID_qual, DIET_qual and XYZ_qual are qualification objects which are
// already defined in this module, so we can use them here.

if ((MSH_qual.qual() || PID_qual.qual()) && (XYZ_qual.qual() || ! DIET_qual.qual()))
{
clMessageBox("Custom Qual", "TRUE"); // For debugging only, remove call to clMessageBox
return 1; // Return code of 1 represents TRUE
}
else
{
clMessageBox("Custom Qual", "FALSE"); // before installing production object on server
return 0; // Return code of 0 represents FALSE
}
}
static int FmtDate_func(blob *pb, char mode, string args)
{
blob bTemp; // Declare local blob
int iRv; // Declare local integer
char cMode = 2; // Declare local char and set to 2 for 2000-based mode
string sInDateFormat; // Declare local string
string sOutDateFormat; // Declare local string

bTemp = *pb; // Assign data from prod object to local blob
sInDateFormat = args; // Assign string passed into function as input format
sOutDateFormat = "%m/%d/%Y"; // Set output format in local string
iRv = fmtDate(&bTemp, cMode, sOutDateFormat, sInDateFormat); // Call fmtDate, note sequence
if (iRv == 1)
{
*pb = bTemp; // If success, return blob to prod object
}
else
{
*pb = iRv; // If problem return status code to prod object blob
}
return 1; // Either way, keep prod obj going to the next item
}
static int HexDecConv_func(blob *pb, char mode, string args)
{
blob bTemp; // Declare local blob
int iRv; // Declare local integer
char cMode = 2; // Declare local char and set to 2
string sArgs; // Declare local string, but note that it is never set

bTemp = *pb; // Assign data from prod object to local blob

iRv = hexDecConv(&bTemp, cMode, sArgs); // Call hexDecConv builtin in reverse mode (cMode is 2)

//
// Normally, it is VERY BAD to pass an unitialized variable to a function (as with sArgs here)
// but in this case hexDecConv doesn't actually look at the value of sArgs, it just
// requires that sArgs be present when hexDecConv is called
//

if (iRv == 1) // If hexDecConv builtin returns 1...
{
*pb = bTemp; // Send converted decimal to hex value back to prod obj
}
else // If hexDecConv returns other than 1...
{
*pb = iRv; // Set prod obj blob to return code of hexDecConv
}
return 1; // In any case, return 1 so prod obj will continue on
}
static int CallBuiltin_func(blob *pb, char mode, string args)
{
blob bTemp; // Declare local blob
int iRv; // Declare local integer

bTemp = *pb; // Assign data from prod object to local blob
if (bTemp.size() > 0) // Make sure blob contains data
{
iRv = ToLower(&bTemp); // Convert blob contents to lower case
}
*pb = bTemp; // Return data back to prod object
return 1;
}
static int CancelDietOrders_func(blob *pb, char mode, string args)
{
// Generate three ODT segments for each Special Service code passed as argument
// One each for BRK, LUN and DIN
// Special Service codes are passed as a long string, e.g. DT100DT101DT102...
// and are processed 5 characters at a time in the "for" loop to generate ODT segments
// CompSep_dl is the MSH Component Separator character
// FieldSep_dl is the MSH Field Separator character
// Bill Flowers
// September 17, 2008

blob bOut;
string sArgs;
string sSvc;
string sTemp;
int iIndex;
int iLength;

sArgs = args;
iLength = sArgs.size();

for (iIndex = 0; iIndex < iLength; iIndex += 5)
{
sSvc.copy(sArgs, 5, iIndex);
sTemp.format("ODT%s%s%sBRK%sALL%s%s%s\015", FieldSep_dl, sSvc, FieldSep_dl, CompSep_dl,
CompSep_dl, CompSep_dl, FieldSep_dl);
bOut.add(sTemp);
sTemp.format("ODT%s%s%sLUN%sALL%s%s%s\015", FieldSep_dl, sSvc, FieldSep_dl, CompSep_dl,
CompSep_dl, CompSep_dl, FieldSep_dl);
bOut.add(sTemp);
sTemp.format("ODT%s%s%sDIN%sALL%s%s%s\015", FieldSep_dl, sSvc, FieldSep_dl, CompSep_dl,
CompSep_dl, CompSep_dl, FieldSep_dl);
bOut.add(sTemp);
}
*pb = bOut;

return 1;
}
static int Mode_func(blob *pb, char mode, string args)
{
*pb = mode;
return 1;
}
static int CallTest_func(blob *pb, char mode, string args)
{
blob bTemp;
int iRv;
char cMode;
string sArgs;

iRv = currHHMMSSColon(&bTemp);
*pb = bTemp;
return 1;

}
static int CallBuiltinWithArgs_func(blob *pb, char mode, string args)
{
blob bTemp;
int iRv;
char cMode = 1; // Declare char variable and initialize to constant
string sArgs;

bTemp = *pb; // Assign blob from prod object to local variable
sArgs = "\015ORC";
iRv = strTruncR(&bTemp, cMode, sArgs); // Truncate blob from start to before <CR>ORC
sArgs = "\015ODS";
iRv = strTruncL(&bTemp, cMode, sArgs); // Truncate blob from after <CR>ODS to end
sArgs = "\015";
iRv = zapLeadChar(&bTemp, cMode, sArgs); // Remove leading <CR> character from blob
iRv = delimit(&bTemp, cMode, sArgs); // Remove characters including and after <CR> from blob
bTemp += "\015"; // Append <CR> to end of blob
*pb = bTemp; // Assign blob from local variable to prod object
return 1;
}
static int CallJustifyBuiltin_func(blob *pb, char mode, string args)
{
blob bTemp; // Declare local blob
int iRv; // Declare local int
char cMode = 1; // Declare local char and initialize to constant of 1
string sArgs; // declare local string

bTemp = *pb; // Assign data from prod object to local blob
iRv = delimit(&bTemp, cMode, FieldSep_dl); // Remove everything including and after Field Sep
sArgs = "R#6";
iRv = justify(&bTemp, cMode, sArgs); // Right justify, pad with leading # to length of 6
sArgs = "L%8";
iRv = justify(&bTemp, cMode, sArgs); // Left justify, pad with trailing % to length of 8
*pb = bTemp; // Assign data from local blob to prod object
return 1;
}

end module;

MSH|^~\&|DIET|PLW|||200809111012||ORM^O01|LW212087913152188508|P|2.2|||AL|NE PID||2525|57634644||CARUSO^Test||19800101|F||||||||||222583 PV1||I|2W^2W16^2W16-01|3|||220921^CPOE^DOCTOR|||ALS||||1|||220921^CPOE^DOCTOR|||C||PLS-0|||||||||||||||||MCH||3|||200808050943||126.17|126.17 ORC|NW|389993^PLW-OIF||222583&68&68&1&&1^PLW-OC||E|1^MEALS^^200809111004^^R^^MEALS&&MINIMUM 000000003 DA&MAXIMUM 000000003 DA||200809111012|221029^PARYLAK^BONNIE^J||285^CAMORIANO^JOHN^K^^^MD|MCH^^QS29001||||MCH|QS29001|285^CAMORIANO^JOHN^K^^^MD ODS|D||^^^Clear^Diet Clear Liquid^PLW-20 ODS|D||^^^^Clear^PLW-COMMENT NTE|1|PROMPT: