Link to: header | other data directory
Copyright Turtle Creek Software 1996-2006. All Rights Reserved.
Comments
DB_TagIDIndex
This class manages id 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 object ID's and value ID's, for custom indexing
of clairvoyant fields.
SUPERCLASS = DB_PersistentObject
Constructor
/*********************************************************************************
constructor
*********************************************************************************/
DB_TagIDIndex::DB_TagIDIndex(const Boolean keepSorted)
{
mIDArray.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_TagIDIndex::GetFileLength(const CNeoFormat *aFormat) const
{
return THE_SUPERCLASS::GetFileLength(aFormat) +
ARRAY_FILE_SIZE(mIDArray) +
cFileLength;
}
/*********************************************************************************
GetMemberValue
return the value of the member with the given tag
*********************************************************************************/
Boolean DB_TagIDIndex::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_TagIDIndex::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;
ReadLongIDArrayFromStream(aStream, mIDArray, 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_TagIDIndex::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);
WriteLongIDArrayToStream(aStream, mIDArray, 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_TagIDIndex::GetIDArray(TObjectIDArray &array)
{
array.RemoveAllItems();
TLongIDInfoArrayIterator iterator(mIDArray);
SLongIDInfo 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_TagIDIndex::IncludesID(const DBid id)
{
TLongIDInfoArrayIterator iterator(mIDArray);
SLongIDInfo info;
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_TagIDIndex::ClearArray()
{
DB_ObjectTempRemover remover (this); // TCS 8/26/03
if (remover.WasRemoved())
{
mIDArray.RemoveAllItems();
}
}
/*********************************************************************************
SortMenuArray TCS 12/20/02
sort the items in this item's array.
*********************************************************************************/
void DB_TagIDIndex::SortMenuArray()
{
DB_ObjectTempRemover remover (this); // TCS 8/26/03
if (remover.WasRemoved())
{
mIDArray.SortWithComparator(NEW CListNameComparator);
}
}
/*********************************************************************************
AddToArray
add an object to this item's array.
*********************************************************************************/
Boolean DB_TagIDIndex::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));
SLongIDInfo info;
info.id = id;
object->GetMemberValue(mFieldTag, type_long, &info.number);
DB_ObjectTempRemover remover (this); // TCS 8/26/03
if (remover.WasRemoved())
{
// add to the array and sort by name rev TCS 9/20/00
mIDArray.Append(info);
if (sortArray) // TCS 12/20/02
mIDArray.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_TagIDIndex::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())
{
SLongIDInfo info;
mIDArray.FetchItemAt(itemIndex, info);
info.id = id;
object->GetMemberValue(mFieldTag, type_long, &info.number);
mIDArray.AssignItemAt(itemIndex, info);
if (doSort)
{ // rev TCS 10/3/00
mIDArray.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_TagIDIndex::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_TagIDIndex::RemoveObjectByID(const DBid id)
{
SInt32 index = IncludesID(id);
if (index)
{
DB_ObjectTempRemover remover (this); // TCS 8/26/03
if (remover.WasRemoved())
{
mIDArray.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_TagIDIndex::FindItemByID(const DBid compareID)
{
TLongIDInfoArrayIterator iterator(mIDArray);
SLongIDInfo info;
while (iterator.Next(info))
{
if (info.id == compareID)
return iterator.GetCurrentIndex();
}
// 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_TagIDIndex::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_TagIDIndex::FillListMatches(DB_MemberSelector *selector,
TObjectIDArray &matchArray, const Boolean matchAny, UInt8 &matchCount)
{
TCS_FailNILMsg(selector, TCS_GetErrString(errID_BadSelector));
TLongIDInfoArrayIterator iterator(mIDArray);
SLongIDInfo 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->MatchesLong(info.number))
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_TagIDIndex::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, "mIDArray", mIDArray);
FillFieldTableRow(table, stream, "mFieldTag", cLongSize, mFieldTag);
FillFieldTableRow(table, stream, "mRecordClassID", cShortSize, mRecordClassID);
FillEndSafetyTag(table, stream, mEndSafetyTag);
}
|