Link to: header | other data directory
Copyright Turtle Creek Software 1996-2006. All Rights Reserved.
Comments
DB_TagShortTextIndex
This class manages short text values for the Goldenseal job cost accounting software,
project management software, construction
estimating software
and construction project estimating software.
It's the owner of an array of short names and ids, used for custom indexed fields.
This index uses only 7 character text, which makes it sufficient for zip
codes or postal codes, part numbers and similar short text.
SUPERCLASS = DB_PersistentObject
Constructor
/*********************************************************************************
constructor
*********************************************************************************/
DB_TagShortTextIndex::DB_TagShortTextIndex(const Boolean keepSorted)
{
mTextArray.SetKeepSorted(keepSorted);
mFieldTag = 0;
mRecordClassID = 0;
mEndSafetyTag = tag_endsafetytag; // TCS 9/8/02
}
Source Code
/*********************************************************************************
GetFileLength
read the object from the db stream
*********************************************************************************/
NeoSize DB_TagShortTextIndex::GetFileLength(const CNeoFormat *aFormat) const
{
return THE_SUPERCLASS::GetFileLength(aFormat) +
ARRAY_FILE_SIZE(mTextArray) +
cFileLength;
}
/*********************************************************************************
GetMemberValue
return the value of the member with the given tag
*********************************************************************************/
Boolean DB_TagShortTextIndex::GetMemberValue(const NeoTag aTag, const NeoTag aType,
void *aValue) const
{
switch (aTag)
{
case tag_menuname: // get the name of the class TCS 9/30/02
{
CTextString className = DB_ClassDescriptor::GetClassNamePlural(GetDBID());
return ConvertMember(&className, type_cstring, aValue, aType);
}
break;
default:
return THE_SUPERCLASS::GetMemberValue(aTag, aType, aValue);
break;
}
}
/*********************************************************************************
ReadObject
read the object from the db stream
*********************************************************************************/
void DB_TagShortTextIndex::ReadObject(CNeoStream *aStream, const TagType aTag)
{
TCS_FailNILMsg(aStream, TCS_GetErrString(errID_BadStream));
CNeoDebugImport checker(aStream, this);
THE_SUPERCLASS::ReadObject(aStream, aTag);
if (!IsIOValid())
return;
ReadShortNameIDArrayFromStream(aStream, mTextArray, cHasSafetyTag);
mFieldTag = aStream->ReadTag();
mRecordClassID = aStream->ReadShort();
mEndSafetyTag = aStream->ReadEndSafetyTag(this); // mfs_sa rev 20feb2k3
if (!IsValidEndTag(mEndSafetyTag))
ReportDamagedObject(GetDBClassID(), GetDBID());
}
/*********************************************************************************
WriteObject
write the object to the db stream
*********************************************************************************/
void DB_TagShortTextIndex::WriteObject(CNeoStream *aStream, const TagType aTag)
{
TCS_FailNILMsg(aStream, TCS_GetErrString(errID_BadStream));
// make sure we have valid data to write TCS 9/8/02
if (!IsValidEndTag(mEndSafetyTag))
{
ReportDamagedObject(GetDBClassID(), GetDBID());
mEndSafetyTag = tag_endsafetytag; // rev TCS 11/26/02
}
CNeoDebugExport checker(aStream, this);
THE_SUPERCLASS::WriteObject(aStream, aTag);
WriteShortNameIDArrayToStream(aStream, mTextArray, cHasSafetyTag);
aStream->WriteTag(mFieldTag);
aStream->WriteShort(mRecordClassID);
aStream->WriteEndSafetyTag(mEndSafetyTag, this); // mfs_sa rev 20feb2k3
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
GetIDArray TCS 3/28/99
fill in the array of object id's
*********************************************************************************/
Boolean DB_TagShortTextIndex::GetIDArray(TObjectIDArray &array)
{
array.RemoveAllItems();
TShortNameIDArrayIterator iterator(mTextArray);
SShortNameIDInfo info;
while (iterator.Next(info))
{
array.Append(info.id);
}
return true;
}
/*********************************************************************************
IncludesID TCS 3/28/99
return whether the given id is already included in this array
*********************************************************************************/
SInt32 DB_TagShortTextIndex::IncludesID(const DBid id)
{
SShortNameIDInfo info;
TShortNameIDArrayIterator iterator(mTextArray);
while (iterator.Next(info))
{
if (info.id == id)
return iterator.GetCurrentIndex();
}
// if we got this far, it's not there
return 0;
}
/*********************************************************************************
ClearArray TCS 12/20/02
remove all items from this item's array.
*********************************************************************************/
void DB_TagShortTextIndex::ClearArray()
{
DB_ObjectTempRemover remover (this); // TCS 8/26/03
if (remover.WasRemoved())
{
mTextArray.RemoveAllItems();
}
}
/*********************************************************************************
SortMenuArray TCS 12/20/02
sort the items in this item's array.
*********************************************************************************/
void DB_TagShortTextIndex::SortMenuArray()
{
DB_ObjectTempRemover remover (this); // TCS 8/26/03
if (remover.WasRemoved())
{
mTextArray.SortWithComparator(NEW CListNameComparator);
}
}
/*********************************************************************************
AddToArray
add an object to this item's array.
*********************************************************************************/
Boolean DB_TagShortTextIndex::AddToArray(const DB_PersistentObject *object,
const Boolean sortArray)
{
TCS_FailNILMsg(object, TCS_GetErrString(errID_BadObject));
DBid id = object->GetDBID();
if (IncludesID(id)) // already there
return false;
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
SShortNameIDInfo info;
info.id = id;
CTextString theText;
object->GetMemberValue(mFieldTag, type_cstring, &theText);
TCS_BufferFromText(info.itemName, theText, cShortTextLen);
DB_ObjectTempRemover remover (this); // TCS 8/26/03
if (remover.WasRemoved())
{
// add to the array and sort by name rev TCS 9/20/00
mTextArray.Append(info);
if (sortArray) // TCS 12/20/02
mTextArray.SortWithComparator(NEW CListNameComparator);
}
return true;
}
/*********************************************************************************
HandleObjectChanged TCS 3/22/00
update status for an object in this item's array. This is used for an object
change
*********************************************************************************/
void DB_TagShortTextIndex::HandleObjectChanged(const DB_PersistentObject *object,
const Boolean doSort)
{
if (object->ShouldBeListed())
{
DBid id = object->GetDBID();
SInt32 itemIndex = FindItemByID(id);
if (itemIndex == LArray::index_Bad)
{ // object is not here, so add it
AddToArray(object);
}
else
{ // object is here, so update it. Object length may change,
// so we need to remove temporarily from the dbase TCS 10/3/00
DB_ObjectTempRemover remover (this); // TCS 8/26/03
if (remover.WasRemoved())
{
SShortNameIDInfo info;
mTextArray.FetchItemAt(itemIndex, info);
CTextString theText;
object->GetMemberValue(mFieldTag, type_cstring, &theText);
TCS_BufferFromText(info.itemName, theText, cShortTextLen);
mTextArray.AssignItemAt(itemIndex, info);
if (doSort)
{ // rev TCS 10/3/00
mTextArray.SortWithComparator(NEW CListNameComparator);
}
}
}
}
else // object should not be listed, so remove it
RemoveFromArray(object);
MakeDirty();
}
/*********************************************************************************
RemoveFromArray
remove an object from this item's array.
*********************************************************************************/
void DB_TagShortTextIndex::RemoveFromArray(const DB_PersistentObject *object)
{
TCS_FailNILMsg(object, TCS_GetErrString(errID_BadObject));
DBid id = object->GetDBID();
if (id)
RemoveObjectByID(id);
}
/*********************************************************************************
RemoveObjectByID TCS split 10/17/03
remove an object id from this item's array. Use this form directly to remove
an object that doesn't exist
*********************************************************************************/
void DB_TagShortTextIndex::RemoveObjectByID(const DBid id)
{
SInt32 index = IncludesID(id);
if (index)
{
DB_ObjectTempRemover remover (this); // TCS 8/26/03
if (remover.WasRemoved())
{
mTextArray.RemoveItemAt(index);
}
}
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
FindItemByID TCS 10/2/00
Check if the given ID is already in the array, and return its index
*********************************************************************************/
SInt32 DB_TagShortTextIndex::FindItemByID(const DBid compareID)
{
SShortNameIDInfo info;
TShortNameIDArrayIterator iterator(mTextArray);
while (iterator.Next(info))
{
if (info.id == compareID)
return iterator.GetCurrentIndex();
}
// if we got this far, it's not included
return 0;
}
/*********************************************************************************
FetchObjectWithName TCS 7/25/01 rev 1/15/02
Return whether the given name already exists here.
*********************************************************************************/
DBid DB_TagShortTextIndex::FetchObjectWithName(const CTextString &matchName, const DBid skipID)
{
SShortNameIDInfo info;
TShortNameIDArrayIterator iterator(mTextArray);
char *matchText = matchName.GetCharPtr();
while (iterator.Next(info))
{
if (info.id != skipID)
{
if (TCS_EqualStrings(matchText, info.itemName))
return info.id;
}
}
// if we got this far, it's not included
return 0;
}
/*********************************************************************************
FindListMatches TCS 12/18/02
doing a find. For some tags, we can search in the menu array and/or
indexed fields in the object class info (future upgrade). That's much faster
than looking through every object.
*********************************************************************************/
Boolean DB_TagShortTextIndex::FindListMatches(CTCS_Array &selectorArray,
TObjectIDArray &matchArray, const Boolean matchAny)
{
DB_MemberSelector *selector = nil;
CTCS_ArrayIterator iterator (selectorArray, iter_from_end);
Boolean success = false;
UInt8 matchCount = 0;
// loop through the selectors
while (iterator.Previous(&selector))
{
TCS_FailNILMsg(selector, TCS_GetErrString(errID_BadSelector));
if (selector->IsFromTable()) // TCS 1/16/03
continue;
// we can do a quick find for name, id or status
switch (selector->getSelectTag())
{
case tag_name:
case tag_objectid:
// we have values here, so fetch them
// from the array
FillListMatches(selector, matchArray, matchAny, matchCount);
success = true;
// remove the selector so we don't
// repeat the search later on
TCS_Forget(selector);
selectorArray.RemoveItemAt(iterator.GetCurrentIndex());
break;
default:
break;
}
}
// sort the list by object ID so we
// stay in the order originally entered TCS 12/23/02
if (matchArray.GetCount() > 0)
matchArray.SortWithComparator(NEW LLongComparator);
return success;
}
/*********************************************************************************
FillListMatches TCS 12/23/02
fill in matches for the given selector
*********************************************************************************/
Boolean DB_TagShortTextIndex::FillListMatches(DB_MemberSelector *selector,
TObjectIDArray &matchArray, const Boolean matchAny, UInt8 &matchCount)
{
TCS_FailNILMsg(selector, TCS_GetErrString(errID_BadSelector));
TShortNameIDArrayIterator iterator (mTextArray);
SShortNameIDInfo info;
Boolean gaveWarning = false;
NeoTag tag;
Boolean foundMatch = false;
// we first fill matches into a temporary array
TObjectIDArray tempArray;
while (iterator.Next(info))
{
tag = selector->getSelectTag();
if (tag == mFieldTag)
{
if (selector->MatchesString(CTextString(info.itemName)))
tempArray.Append(info.id);
foundMatch = true;
}
}
if (foundMatch)
matchCount++;
// fill in the actual match array. How we do that depends
// on the type of match, and whether this is the first match
if (matchCount < 2) // TCS 12/23/02
matchArray = tempArray; // first match
else if (matchAny)
matchArray.Add(tempArray); // do a 'union'
else
matchArray.Collapse(tempArray); // do an 'intersection'
return (matchArray.GetCount() > 0);
}
/*********************************************************************************
FillDataReport TCS 9/7/02
fill in a diagnostic table that shows data field values.
*********************************************************************************/
void DB_TagShortTextIndex::FillDataReport(CTCS_Table *table, CNeoStream *stream) const
{
TCS_FailNILMsg(table, TCS_GetErrString(errID_BadTable));
TCS_FailNILMsg(stream, TCS_GetErrString(errID_BadStream));
THE_SUPERCLASS::FillDataReport(table, stream);
FillFieldArrayRow(table, stream, "mTextArray", mTextArray);
FillFieldTableRow(table, stream, "mFieldTag", cLongSize, mFieldTag);
FillFieldTableRow(table, stream, "mRecordClassID", cShortSize, mRecordClassID);
FillEndSafetyTag(table, stream, mEndSafetyTag);
}
|