/*
	File:		CMessagePart.10.1.cpp

	Contains:	C++ implementation of a blob-based message part object

	Copyright:	© 2003 by Apple Computer, Inc., all rights reserved.

 	NOT_FOR_OPEN_SOURCE <to be reevaluated at a later time>

	Change History:
*/


// App
#include <string.h>

#include "CMessagePart.10.1.h"
#include "CSmallMsgPart.10.1.h"
#include "Database.10.1.h"
#include "CGlobals.h"


Boolean	CMessagePart_10_1::GetSetFields	(const eFieldDataRequest_10_1 inFieldRequest, const void *inObjDataPtr, void *outFieldData)
{
	Boolean	result = false;
	CMessagePartData_10_1	*theData = (CMessagePartData_10_1 *) inObjDataPtr;
	CMessagePart_10_1		*aTempObject = NULL;
	ObjID				*anObjIDPtr = (ObjID *) outFieldData;

	switch (inFieldRequest)
	{
		case kSetObjID_10_1:
			theData->fMessagePartID = *anObjIDPtr;
			break;
			
		case kObjectPINGRequest_10_1:
			// cause the objects constructor to get called, so we force a check of
			// the struct alignment...
			aTempObject = new CMessagePart_10_1;
			delete aTempObject;
			break;

		case k2ndIDTargetChk_10_1:
			// fall through...
			
		default:
			result = false;
			break;
	}
	
	return result;
}

ObjID CMessagePart_10_1::GetObjectID	( void )
{
	return fMsgPartData.fMessagePartID;
}

//--------------------------------------------------------------------------------------------------
//	 Done
//
//--------------------------------------------------------------------------------------------------

void CMessagePart_10_1::Done ( CMessagePart_10_1* &inPtr )
{
	CDBBaseObject_10_1 *aDBObject = (CDBBaseObject_10_1 *) inPtr;
	aDBObject->Done(aDBObject);

	inPtr = (CMessagePart_10_1 *)aDBObject;
}


CDBBaseObject_10_1 * CMessagePart_10_1::ObjectAllocNew	( void )
{
	return new CMessagePart_10_1;
}

CMessagePart_10_1* CMessagePart_10_1::FindByID ( const ObjID inObjectID )
{
	OSErr			result;
	CMessagePart_10_1	*theMessagePart = NULL;
	CMessagePart_10_1	*anotherMsgPart = NULL;
	
	if (inObjectID == 0)
	{
		return (NULL);
	}

	try
	{
		(gDB_10_1->GetBaseObjectCachePtr())->LockTheCache(CMessagePart_10_1::GetObjTypeConstant());

		theMessagePart = (CMessagePart_10_1 *) (gDB_10_1->GetBaseObjectCachePtr())->Search4Object(CMessagePart_10_1::GetObjTypeConstant(), inObjectID);

		if (theMessagePart != NULL)
		{
			if ( (theMessagePart->GetObjectType() != CMessagePart_10_1::GetObjTypeConstant()) ||
				 (theMessagePart->GetObjectVersion() != CMessagePart_10_1::GetObjVersConstant()) )
			{
				theMessagePart->Done( theMessagePart );
				theMessagePart = NULL;
			}
		}
		else if (theMessagePart == NULL)
		{
			theMessagePart = new CMessagePart_10_1;

			ThrowIfNULL_( theMessagePart );

			result = gDB_10_1->GetObjData(CMessagePart_10_1::GetObjTypeConstant(), inObjectID, theMessagePart->GetObjectData());
			if ( result != kNoErr )
			{
				delete theMessagePart;
				theMessagePart = NULL;
			}
			else
			{
				if ( (theMessagePart->GetObjectType() != CMessagePart_10_1::GetObjTypeConstant()) ||
					 (theMessagePart->GetObjectVersion() != CMessagePart_10_1::GetObjVersConstant()) )
				{
					delete theMessagePart;
					theMessagePart = NULL;
				}

				if ( theMessagePart != NULL )
				{	
					anotherMsgPart = (CMessagePart_10_1 *) theMessagePart->Use();
					if (anotherMsgPart != theMessagePart)
					{	// hmm the object got added to the list while we were futzing around in the
						// Database...one of those "danger" "danger" points caused us grief...
						// oh well we detected the case and now can fix it...
						// Use has incremented the use count of the object it "returned"
						// therefore all we need to do now is Dispose of the new copy we created..
						// and return the object that "use" found...
						
						delete theMessagePart;
						theMessagePart = NULL;

						// we should hold the new part to the same standard we held the "other" part too..
						if ( (anotherMsgPart->GetObjectType() != CMessagePart_10_1::GetObjTypeConstant()) ||
							 (anotherMsgPart->GetObjectVersion() != CMessagePart_10_1::GetObjVersConstant()))
						{
							// we're _VERY_ confused at this point, just return nothing...

							anotherMsgPart->Done(anotherMsgPart);
						}
						else
						{
							theMessagePart = anotherMsgPart;
						}
					}
				}
			}
		}
		
		(gDB_10_1->GetBaseObjectCachePtr())->UnLockTheCache(CMessagePart_10_1::GetObjTypeConstant());
	}
	catch ( ExceptionCode err )
	{
		if ( theMessagePart != NULL )
		{
			delete theMessagePart;
			theMessagePart = NULL;
		}
		
		(gDB_10_1->GetBaseObjectCachePtr())->UnLockTheCache(CMessagePart_10_1::GetObjTypeConstant());
	}
	
	return( theMessagePart );

} // FindByID


CMessagePart_10_1* CMessagePart_10_1::Create ( OSType inPartType,
									ObjID inEnvelopeID,
									uInt32 inSequenceNumber)
{
	CMessagePart_10_1*	theMessagePart = new CMessagePart_10_1;
	OSErr			result = kNoErr;
	ObjID			aNewID = 0;

	try
	{
		if (theMessagePart != NULL)
		{
			// Initialize it
			(gDB_10_1->GetBaseObjectCachePtr())->LockTheCache(CMessagePart_10_1::GetObjTypeConstant());
			
			result = gDB_10_1->CreateObj(kMessagePartSignature_10_1, aNewID, theMessagePart->GetWholeMessagePartData());

			if ( result == CMailDatabase_10_1::kDBNoErr )
			{
				theMessagePart->Use();
				theMessagePart->SetPartType(inPartType);			// 'data' is only one for now
				theMessagePart->SetEnvelopeID(inEnvelopeID);
				theMessagePart->SetSequenceNumber(inSequenceNumber);
		
				theMessagePart->SetDirty();

//				DBGLOG3 (kLogDBOperation, 
//						 "CMessagePart_10_1::Create: ID = %l, Sequence# = %l, EnvelopeID = %l",
//				 		 theMessagePart->GetMessagePartID(), theMessagePart->GetSequenceNumber(), 
//				 		 theMessagePart->GetEnvelopeID());
			}
			else
			{
				delete theMessagePart;
				theMessagePart = NULL;
			}
			
			(gDB_10_1->GetBaseObjectCachePtr())->UnLockTheCache(CMessagePart_10_1::GetObjTypeConstant());
		}
	}
	catch ( ExceptionCode err )
	{
	}

	return (theMessagePart);
}

Boolean CMessagePart_10_1::Delete(CMessagePart_10_1* inMessagePart)
{
	Boolean deleted = false;
	OSErr	result;
	
	try
	{
		if (inMessagePart != NULL)
		{
			(gDB_10_1->GetBaseObjectCachePtr())->LockTheCache(CMessagePart_10_1::GetObjTypeConstant());

			result = gDB_10_1->RemoveObj(kMessagePartSignature_10_1, inMessagePart->GetMessagePartID());
			deleted = (result == kNoErr);
			if (deleted)
			{
				inMessagePart->fMsgPartData.fMessagePartID = 0;
			}
			
			(gDB_10_1->GetBaseObjectCachePtr())->UnLockTheCache(CMessagePart_10_1::GetObjTypeConstant());
		}
	}
	catch ( ExceptionCode err )
	{
		(gDB_10_1->GetBaseObjectCachePtr())->UnLockTheCache(CMessagePart_10_1::GetObjTypeConstant());
	}
	
	return (deleted);
}

uInt32 CMessagePart_10_1::Count (void)
{
	uInt32	aCount = 0;
	OSErr	result;

	result = gDB_10_1->GetObjectCount( kMessagePartSignature_10_1, aCount );

	if (result != kNoErr)
	{
		aCount = 0;
	}
	
	return aCount;
}

CMessagePartData_10_1* CMessagePart_10_1::GetWholeMessagePartData	( void )
{
	if (this != NULL)
	{
		return &(this->fMsgPartData);
	}
	else
	{
		return NULL;
	}
}

void CMessagePart_10_1::SetDirty	( void )
{
	if ((this != NULL) && (this->GetMessagePartID() != 0))
	{
		setDirty();
	}
}

#pragma mark -

CMessagePart_10_1::CMessagePart_10_1(void) :
	CDBMailBaseObject_10_1(	&fMsgPartData.fDBHeader,
				&fMsgPartData.fDBFooter,
				&fMsgPartData,
				CMessagePart_10_1::GetObjTypeConstant(),
				CMessagePart_10_1::GetObjVersConstant(),
				CMessagePart_10_1::GetObjSizeConstant() )
{
	fMsgHasBeenAttached	= false;
	
	fMsgPartData.fMessagePartID			= 0;
	fMsgPartData.fNextMsgPartID			= 0;
	fMsgPartData.fEnvelopeID			= 0;
	
	fMsgPartData.fPartType				= kUnknownPartType;
	fMsgPartData.fSequenceNumber		= 0;
	
	fMsgPartData.fLengthIsSet			= false;
	fMsgPartData.fDotStuffingRequired	= true;
	fMsgPartData.fDataLength			= 0;
	::memset (fMsgPartData.fPartData, 0, kMessagePartSize_10_1);

	// Reserved
	fMsgPartData.fReserved1				= kReservedConst;
	fMsgPartData.fReserved2				= kReservedConst;

	this->ChkCompilerStructAlignment();
}

CMessagePart_10_1::~CMessagePart_10_1(void)
{
}

void	CMessagePart_10_1::ChkCompilerStructAlignment	( void )
{
	/*
		this dump was aquired by using the MPW command DumpSYM - TTE from the .xsym file produced
		from a Code Warrior Pro 1 Release Build of the AppleShare IP Mail Server for MacOS version 6.2
		
		this version of the structure is consider the "reference" standard for all future ASIP Mail Servers.
		If the structure does NOT match these offsets the version of the Mail Server that 
		you are compiling will _NOT_ be compatible with AppleShare IP 6.0, 6.1, or 6.2 (this also effects
		the AppleShare IP Mail Tool, and to a more limited extent the AppleShare IP Mail Admin since some
		of these structures are passed across the wire..)
		
		If _ANY_ of these Asserts "fire" you've got a backwards compatibility problem that _MUST_ be fixed!!
		
		this code wasn't put here for my personal amusement, this code was put here from a hard earned lesson
		that simple changes to headers/compilers _WILL_ break this stuff, better to know now than after we
		ship.  Look upon this code as a debugging AIDE, not an impediment.
		
		Type Name:  CMessagePartData_10_1		TINFO offset: 42640		(TINFO SYM file offset (hex): $122690)
			RecordOf
			offset 0 NamedTypeOf fDBHeader TypeDef of "Type ID 248"
			offset 12 NamedTypeOf fMessagePartID 
			offset 16 NamedTypeOf fNextMsgPartID unsigned long 
			offset 20 NamedTypeOf fEnvelopeID 
			offset 24 NamedTypeOf fReserved1 unsigned long 
			offset 28 NamedTypeOf fReserved2 
			offset 32 NamedTypeOf fPartType unsigned long 
			offset 36 NamedTypeOf fSequenceNumber 
			offset 40 NamedTypeOf fLengthIsSet unsigned byte 
			offset 41 NamedTypeOf fDotStuffingRequired 
			offset 44 NamedTypeOf fDataLength unsigned long 
			offset 48 NamedTypeOf fPartData 
			offset 8132 NamedTypeOf fDBFooter TypeDef of "Type ID 250"
	*/

	static Boolean	aRunOnceFlag = false;	
	if (aRunOnceFlag == false)
	{
		//FileFormatSaftyChk(CMessagePartData_10_1, fDBHeader,				0);
		//FileFormatSaftyChk(CMessagePartData_10_1, fMessagePartID,		12);		// this is us (denormalized)
		//FileFormatSaftyChk(CMessagePartData_10_1, fNextMsgPartID,		16);
		//FileFormatSaftyChk(CMessagePartData_10_1, fEnvelopeID,			20);
		//FileFormatSaftyChk(CMessagePartData_10_1, fReserved1,				24);
		//FileFormatSaftyChk(CMessagePartData_10_1, fReserved2,				28);
		//FileFormatSaftyChk(CMessagePartData_10_1, fPartType,				32);
		//FileFormatSaftyChk(CMessagePartData_10_1, fSequenceNumber,		36);
		//FileFormatSaftyChk(CMessagePartData_10_1, fLengthIsSet,			40);
		//FileFormatSaftyChk(CMessagePartData_10_1, fDotStuffingRequired,	41);
		//FileFormatSaftyChk(CMessagePartData_10_1, fDataLength,			44);
		//FileFormatSaftyChk(CMessagePartData_10_1, fPartData[0],			48);
		//FileFormatSaftyChk(CMessagePartData_10_1, fDBFooter,				8132);
//		this->ReportBackwardCompatibility(sizeof(CMessagePartData_10_1),	8136,	"CMessagePartData_10_1", "SIZEOF()");
//		this->ReportBackwardCompatibility(kMessagePartFixedDataSize,	8136,	"CMessagePartData_10_1", "kMessagePartFixedDataSize");
	}
	
	aRunOnceFlag = true;
}

#pragma mark -

ObjID CMessagePart_10_1::GetMessagePartID(void)
{
	return (fMsgPartData.fMessagePartID);
}

ObjID CMessagePart_10_1::GetEnvelopeID (void)
{
	return (fMsgPartData.fEnvelopeID);
}

void CMessagePart_10_1::SetEnvelopeID (ObjID inEnvelopeID)
{
	if (fMsgPartData.fEnvelopeID != inEnvelopeID)
	{
		fMsgPartData.fEnvelopeID = inEnvelopeID;
		this->SetDirty();
	}
}

void CMessagePart_10_1::SetMsgHasBeenAttached	( const Boolean inSetFlag )
{
	fMsgHasBeenAttached = inSetFlag;
}

Boolean CMessagePart_10_1::GetMsgHasBeenAttached	( void )
{
	return (fMsgHasBeenAttached == true);
}

#pragma mark -

OSType CMessagePart_10_1::GetPartType(void)
{
	return (fMsgPartData.fPartType);
}

void CMessagePart_10_1::SetPartType(OSType inPartType)
{
	if (fMsgPartData.fPartType != inPartType)
	{
		fMsgPartData.fPartType = inPartType;
		this->SetDirty();
	}
}

ObjID CMessagePart_10_1::GetNextMessagePartID(void)
{
	return(fMsgPartData.fNextMsgPartID);
}

void CMessagePart_10_1::SetNextMessagePartID(const ObjID inMessagePartID)
{
	if (fMsgPartData.fNextMsgPartID != inMessagePartID)
	{
		fMsgPartData.fNextMsgPartID = inMessagePartID;
		this->SetDirty();
	}
}
		

uInt32 CMessagePart_10_1::GetSequenceNumber (void)
{
	return (fMsgPartData.fSequenceNumber);
}
	
void CMessagePart_10_1::SetSequenceNumber (uInt32 inSequenceNumber)
{
	if (fMsgPartData.fSequenceNumber != inSequenceNumber)
	{
		fMsgPartData.fSequenceNumber = inSequenceNumber;
		this->SetDirty();
	}
}

Boolean CMessagePart_10_1::GetDotStuffingRequired (void)
{
	return (fMsgPartData.fDotStuffingRequired);
}
	
void CMessagePart_10_1::SetDotStuffingRequired (const Boolean inDoDotStuffingFlag)
{
	if (fMsgPartData.fDotStuffingRequired != inDoDotStuffingFlag)
	{
		fMsgPartData.fDotStuffingRequired = inDoDotStuffingFlag;
		this->SetDirty();
	}
}

uInt32 CMessagePart_10_1::GetDataLength (void)
{
	return (fMsgPartData.fDataLength);
}

void CMessagePart_10_1::SetDataLength(uInt32 inDataLength)
{
	fMsgPartData.fLengthIsSet = true;				
	fMsgPartData.fDataLength = inDataLength;
	this->SetDirty();
}

char* CMessagePart_10_1::GetPartData(void)
{
	return (fMsgPartData.fPartData);
}

void CMessagePart_10_1::VerifyData(void)
{
	ThrowIfNULL_ (this->GetPartData());
}

uInt32 CMessagePart_10_1::GetObjectLength (void)
{
	return (kMessagePartFixedDataSize_10_1 + fMsgPartData.fDataLength);
}
