// --------------------------------------------------------------------------
// www.UnitedBusinessTechnologies.com
// Copyright (c) 1998 - 2002 All Rights Reserved.
//
// Source in this file is released to the public under the following license:
// --------------------------------------------------------------------------
// This toolkit may be used free of charge for any purpose including corporate
// and academic use. For profit, and Non-Profit uses are permitted.
//
// This source code and any work derived from this source code must retain
// this copyright at the top of each source file.
//
// UBT welcomes any suggestions, improvements or new platform ports.
// email to: XMLFoundation@UnitedBusinessTechnologies.com
// --------------------------------------------------------------------------
#include "MemberDescriptor.h"
#include "xmlDefines.h"
#include "xmlObject.h"
#include "FrameworkAuditLog.h"
#include "StackFrameCheck.h"
#include "ListAbstraction.h"
#include "StringAbstraction.h"
#include "MemberHandler.h"
#include "ObjectDataHandler.h"
#include "GException.h"
#include <stdio.h> // for: sprintf(), sscanf()
MemberDescriptor::~MemberDescriptor()
{
delete m_pAttributes;
};
void MemberDescriptor::SetAsTempObject(XMLObject *pO)
{
pO->m_nIsTempObject = 1;
}
void MemberDescriptor::TabifyXML(GString& xml, int nTabs )
{
static const char* TABS =
"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"
"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
const int MAX_TABS = 80;
if (xml.Length())
#ifdef _WIN32
xml << "\r\n";
#else
xml << "\n";
#endif
xml.write( TABS, (nTabs > MAX_TABS) ? MAX_TABS : nTabs );
}
#define WriteMemberBeginTag(xml,nTabs) \
{ \
TabifyXML(xml,nTabs); \
xml << '<' << strTagName; \
if (m_pAttributes) \
{ \
GListIterator Iter(&m_pAttributes->m_attrList); \
while ( Iter() ) \
{ \
XMLAttributeList::XMLAttributeNameValuePair *temp = \
(XMLAttributeList::XMLAttributeNameValuePair *)Iter++; \
xml << " "; \
xml << temp->strAttrName; \
xml << '=' << '"'; \
xml << temp->strAttrValue; \
xml << '"'; \
} \
} \
xml << '>'; \
}
#define WriteMemberEndTag(xml) xml << "</" << strTagName << '>';
void MemberDescriptor::MemberToXML(GString& xml, int nTabs, StackFrameCheck *pStack,int nSerializeFlags)
{
if ( DataType == ManagedByDerivedClass )
{
bool bDirty = ( nSerializeFlags & FORCE_CLEAN_MEMBERS_OUT ) != 0;
if (!bDirty)
{
bDirty = m_DataAbstractor.pMemberHandler->IsMemberDirty((const char *)strTagName);
}
if (bDirty)
{
if (m_DataAbstractor.pMemberHandler->IsMemberObject((const char *)strTagName))
{
/* We must delegate to the derived class since we don't know if*/
/* the object is a collection, or if there is any special processing */
m_DataAbstractor.pMemberHandler->StreamObject((const char *)strTagName,xml,nTabs,!pStack->isNestedStackFrame());
}
else
{
/* add the value of the member variable*/
WriteMemberBeginTag(xml,nTabs);
m_DataAbstractor.pMemberHandler->GetMember( (const char *)strTagName, xml );
WriteMemberEndTag(xml);
}
}
}
else if ( IsDirty() || DataType == XMLObj || DataType == XMLObjList || DataType == XMLObjPtr
|| ((( nSerializeFlags & FORCE_CLEAN_MEMBERS_OUT ) != 0) && IsCached() ) ||
((nSerializeFlags & FORCE_FULL_SERIALIZE) != 0)
)
{
if (!IsSerializable())
{
return;
}
if(DataType == EntityReference)
{
TabifyXML(xml,nTabs);
xml << (const char *)strTagName;
}
else if(DataType == UserString)
{
// In one case we needed empty strings to not be included in the serialization. This should be
// added as a serilazation flag in the future.
// if ( !m_DataAbstractor.pStringHandler->isEmpty(m_Member.pUserString) || IsDirty())
// {
WriteMemberBeginTag( xml,nTabs );
char const* src = m_DataAbstractor.pStringHandler->data(m_Member.pUserString);
xml.AppendEscapeXMLReserved(src);
WriteMemberEndTag(xml);
// }
}
else if (DataType == Str)
{
WriteMemberBeginTag(xml,nTabs);
/*implement native char * */
WriteMemberEndTag(xml);
}
else if (DataType == Bool)
{
WriteMemberBeginTag(xml,nTabs);
if (*m_Member.pBool)
xml << "YES";
else
xml << "NO";
WriteMemberEndTag(xml);
}
else if(DataType == Int)
{
WriteMemberBeginTag(xml,nTabs);
xml << *m_Member.pInt;
WriteMemberEndTag(xml);
}
else if(DataType == Long)
{
WriteMemberBeginTag(xml,nTabs);
xml << *m_Member.pLong;
WriteMemberEndTag(xml);
}
else if(DataType == Int64)
{
WriteMemberBeginTag(xml,nTabs);
char szBuffer[30];
sprintf(szBuffer, "%I64d", *m_Member.pInt64);
xml << szBuffer;
WriteMemberEndTag(xml);
}
else if(DataType == UserStringCollection)
{
userStringListIterator iter;
const char *pzEntry = m_DataAbstractor.pStrListHandler->getFirst(m_Member.pUserStringCollection,&iter);
while (pzEntry)
{
WriteMemberBeginTag(xml,nTabs);
xml << pzEntry;
WriteMemberEndTag(xml);
pzEntry = m_DataAbstractor.pStrListHandler->getNext(m_Member.pUserStringCollection,iter);
}
}
else if (DataType == UserIntegerArray)
{
int nIndex = 0;
int nIsValidIndex = 0;
int nValue = m_DataAbstractor.pIntArrayHandler->getAt(m_Member.pUserIntegerArray,nIndex,&nIsValidIndex);
while(nIsValidIndex)
{
WriteMemberBeginTag(xml,nTabs);
xml << nValue;
WriteMemberEndTag(xml);
nIndex++;
nValue = m_DataAbstractor.pIntArrayHandler->getAt(m_Member.pUserIntegerArray,nIndex,&nIsValidIndex);
}
}
else if( ( ( DataType == XMLObjPtr && *(m_Member.ppObject) ) ||
( DataType == XMLObj ) ||
( DataType == XMLObjList ) ||
( DataType == KeyedDataStructure )
) && !pStack->isNestedStackFrame()
)
{
/* nObjectCount is always 1 if the DataType == XMLObj or ObjPointer */
/* it may be 0 or more if the DataType == XMLObjList */
xmlObjectIterator iter;
XMLObject *pObj = GetFirstContainedObject(&iter);
while (pObj)
{
/*only check if we know we want to recursivly serialize*/
if ( (nSerializeFlags & FORCE_FULL_SERIALIZE)
/* don't bother walking the tree if we already know */
/* we must include this member in the XMLstream */
&& !( pObj->getMemberStateSummary(DATA_DIRTY) ||
(( nSerializeFlags & FORCE_CLEAN_MEMBERS_OUT ) && pObj->getMemberStateSummary(DATA_CACHED) )) )
{
/*If the object is not dirty already recurse it's children */
m_memberStateFlags |= pObj->CalculateObjectState();
}
if ( pObj->getMemberStateSummary(DATA_DIRTY) ||
((( nSerializeFlags & FORCE_CLEAN_MEMBERS_OUT ) != 0) && pObj->getMemberStateSummary(DATA_CACHED) ) ||
((nSerializeFlags & FORCE_FULL_SERIALIZE) != 0)
)
{
if ( ( nSerializeFlags & USE_OBJECT_MARKERS ) != 0)
{
// If the object has no OID, we cannot treat it as a real object.
// It is merely a structure embedded in an object. Since the
// structure (a user defined data type, not an object) is contained
// in an object we treat this as any other member by deeply
// recursing it's value into the XML stream. This case also applies
// to RelationshipWrappers that are really structs containing
// pointers to objects.
if (!pObj->getOID())
{
pObj->ToXML( &xml, nTabs , (const char *)strTagName, nSerializeFlags, pStack );
}
else
{
/* If we are not deeply recursing nested objects write */
/* out just an "Object Marker" enough to re-associate */
/* the objects later. */
pObj->WriteObjectBeginTag( xml, nTabs, 0, nSerializeFlags );
pObj->WriteObjectEndTag( xml, nTabs, 0, nSerializeFlags );
}
}
else if ( DataType == XMLObjList )
{
pObj->ToXML( &xml, nTabs, 0, nSerializeFlags, pStack );
}
else
{
/* write full object and all contained data */
pObj->ToXML( &xml, nTabs , (const char *)strTagName, nSerializeFlags, pStack );
}
}
pObj = GetNextContainedObject(iter);
}
}
}
}
void MemberDescriptor::GetTypeName(GString &strTypeDescription)
{
if ( DataType == ManagedByDerivedClass )
{
strTypeDescription = "ManagedByDerivedClass";
}
if(DataType == UserString)
{
strTypeDescription = "string";
}
else if (DataType == Str)
{
strTypeDescription = "char *";
}
else if (DataType == Bool)
{
strTypeDescription = "bool";
}
else if(DataType == Int)
{
strTypeDescription = "int";
}
else if(DataType == Long)
{
strTypeDescription = "long";
}
else if(DataType == XMLObj)
{
strTypeDescription = "XMLObject";
}
else if(DataType == XMLObjPtr)
{
strTypeDescription = "XMLObject *";
}
else if(DataType == XMLObjList)
{
strTypeDescription = "List<XMLObject *>";
}
else if(DataType == KeyedDataStructure )
{
// could be binary tree, hash table, sorted array, etc..
strTypeDescription = "KeyedDataStructure";
}
else
{
strTypeDescription = "Unknown";
}
}
bool MemberDescriptor::IsCached()
{
if ( DataType == ManagedByDerivedClass )
{
return m_DataAbstractor.pMemberHandler->IsCached( (const char *)strTagName );
}
return ( ( m_memberStateFlags & DATA_CACHED ) != 0);
}
bool MemberDescriptor::IsDirty()
{
if ( DataType == ManagedByDerivedClass )
{
return m_DataAbstractor.pMemberHandler->IsMemberDirty((const char *)strTagName);
}
return ( ( m_memberStateFlags & DATA_DIRTY ) != 0);
}
bool MemberDescriptor::IsSerializable()
{
return ( ( m_memberStateFlags & DATA_SERIALIZE ) != 0);
}
void MemberDescriptor::SetDirty( )
{
m_memberStateFlags |= DATA_DIRTY;
m_ParentObject->setMemberStateSummary(DATA_DIRTY);
}
void MemberDescriptor::SetSerializable( bool bSerialize )
{
if ( bSerialize )
{
m_memberStateFlags |= DATA_SERIALIZE;
}
else
{
m_memberStateFlags ^= DATA_SERIALIZE;
}
}
bool MemberDescriptor::IsNull()
{
if ( DataType == ManagedByDerivedClass )
{
m_DataAbstractor.pMemberHandler->IsNull( (const char *)strTagName );
}
return ( ( m_memberStateFlags & DATA_NULL ) != 0);
}
//*********************************************************
// Description:
// When the XML Parser sets the data, it is setting the initial value
// so it is not considered dirty, however when an application developer
// sets the state of a member variable, it is now dirty.
//
//*********************************************************
void MemberDescriptor::Set(const char * pzData,
int nDataLen,
bool bSetDirty,
bool bUpdateCleanMembers)
{
// if ( !bSetDirty && IsDirty() )
// {
// When bSetDirty = false, this means the member is being set by the
// DataSource. The state becomes CACHED, and NOT_NULL when the DataSource
// sets the value of a member. However if the member is already DIRTY
// when the DataSource attempts to set the value this means the ORB has
// explicitly defined the value for this member. Possibly we intentionally
// want the value to differ from that of the DataSource (in preperation
// for a database update) when this happens the ORB has the correct value
// and we should ignore the 'older' value that the DataSource is attempting
// to assign this member.
// return;
// }
if ( !bUpdateCleanMembers && IsCached() )
{
// If we're not bUpdateCleanMembers (because the TimeStamp matched
// a previously cached instance of this object) and we already have
// the data there is nothing to do.
return;
}
static GString strYes("yes");
static GString strTrue("true");
switch(DataType)
{
case ManagedByDerivedClass:
m_DataAbstractor.pMemberHandler->SetMember((const char *)strTagName,pzData);
break;
case Int:
if (strYes.CompareNoCase(pzData) == 0 || strTrue.CompareNoCase(pzData) == 0)
*m_Member.pInt = 1; // "True", and "yes" mapped to an Int becomes a 1
else
sscanf (pzData, "%d", m_Member.pInt); // No, and false are 0. "123" is 123.
break;
case Long:
if (strYes.CompareNoCase(pzData) == 0 || strTrue.CompareNoCase(pzData) == 0)
*m_Member.pLong = 1; // "True", and "yes" mapped to an Long becomes a 1
else
sscanf (pzData, "%ld", m_Member.pLong); // No, and false are 0. "123" is 123.
break;
#ifdef _WIN32
case Int64 :
*m_Member.pInt64 = _atoi64( pzData );
break;
#endif
case Str:
break;
case UserStringCollection:
m_DataAbstractor.pStrListHandler->append(m_Member.pUserStringCollection,pzData);
break;
case UserIntegerArray:
int nTemp;
sscanf (pzData, "%d", &nTemp);
m_DataAbstractor.pIntArrayHandler->append(m_Member.pUserIntegerArray,nTemp);
break;
case UserString:
if ( pzData && pzData[0] )
{
m_DataAbstractor.pStringHandler->assign(m_Member.pUserString,pzData);
}
else
{
m_DataAbstractor.pStringHandler->assign(m_Member.pUserString,"");
}
break;
case XMLObjList:
{
XMLObject *pX = m_DataAbstractor.pListHandler->getLast( m_Member.pXMLObjList );
//MemberDescriptor *pM = m_ParentObject->GetObjectDescriptor();
if (pX)
{
if ( (pX->m_pDataHandler) && (*pzData) )
{
pX->m_pDataHandler->SetObjectValue(pzData);
}
}
}
break;
case XMLObj:
if ( (m_Member.pObject)->m_pDataHandler )
{
(m_Member.pObject)->m_pDataHandler->SetObjectValue(pzData);
}
break;
}
// there is a m_ParentObject for all but 'Root'
if (m_ParentObject)
{
if(bSetDirty)
{
// set by the user of the business object
m_memberStateFlags |= DATA_DIRTY;
m_ParentObject->setMemberStateSummary(DATA_DIRTY);
}
else
{
// set by the Object Factory from a DataSource update
m_memberStateFlags |= DATA_CACHED;
m_ParentObject->setMemberStateSummary(DATA_CACHED);
}
}
// If the data is ever assigned a value then it becomes (not null)
// This allows access via a Get() method, to throw an exception
// when uninitialized data is accessed.
m_memberStateFlags |= DATA_NOT_NULL;
m_memberStateFlags &= ~DATA_NULL;
}
void MemberDescriptor::AddAttribute( const char * pzName, int nValue )
{
char pzTempBuf[20];
sprintf(pzTempBuf,"%d",nValue);
AddAttribute( pzName, pzTempBuf );
}
void MemberDescriptor::AddAttribute( const char * pzName, const char * pzValue )
{
if (!m_pAttributes)
{
m_pAttributes = new XMLAttributeList;
}
m_pAttributes->AddAttribute( pzName, pzValue );
}
const char *MemberDescriptor::FindAttribute( const char *pzAttName )
{
if (!m_pAttributes)
{
return 0;
}
return m_pAttributes->FindAttribute( pzAttName );
}
void *MemberDescriptor::GetItemData()
{
return m_pUserData;
}
void MemberDescriptor::SetItemData(void *p)
{
m_pUserData = p;
}
void MemberDescriptor::Init(XMLObject *pParent)
{
m_pAttributes = 0;
m_ParentObject = pParent;
m_memberStateFlags = ( DATA_NULL | DATA_SERIALIZE );
Left = 0;
Right = 0;
m_pfnFactoryCreate = 0;
m_DataAbstractor.pListHandler = 0;
m_pUserData = 0;
m_bFirstMap = 1;
}
MemberDescriptor::MemberDescriptor(XMLObject *pParent, const char *pzTag,
void *pKeyedDSA,KeyedDataStructureAbstraction *pHandler)
{
Init(pParent);
strTagName = pzTag;
m_Member.pKeyedDSA = pKeyedDSA;
DataType = KeyedDataStructure;
m_DataAbstractor.pKeyDSA= pHandler;
}
MemberDescriptor::MemberDescriptor (XMLObject *pParent, const char *pzTag,MemberHandler *pHandle)
{
Init(pParent);
strTagName = pzTag;
m_Member.pObject = pParent;
DataType = ManagedByDerivedClass;
m_DataAbstractor.pMemberHandler = pHandle;
}
MemberDescriptor::MemberDescriptor
(XMLObject *pParent, const char *pzTag, ObjectFactory pFactory, const char * pzClassType)
{
Init(pParent);
strTagName = pzTag;
m_pfnFactoryCreate = pFactory;
DataType = Root;
m_Member.pClassName = pzClassType;
}
MemberDescriptor::MemberDescriptor (XMLObject *pParent, const char *pzTag, long *pVal)
{
Init(pParent);
strTagName = pzTag;
m_Member.pLong = pVal;
DataType = Long;
}
MemberDescriptor::MemberDescriptor (XMLObject *pParent, const char *pzTag, int *pVal)
{
Init(pParent);
strTagName = pzTag;
m_Member.pInt = pVal;
DataType = Int;
}
MemberDescriptor::MemberDescriptor (XMLObject *pParent, const char *pzTag, __int64 *pVal)
{
Init(pParent);
strTagName = pzTag;
m_Member.pInt64 = pVal;
DataType = Int64;
}
MemberDescriptor::MemberDescriptor(XMLObject *pParent, const char *pzEntityName)
{
Init(pParent);
strTagName.Format("&%s;", pzEntityName);
DataType = EntityReference;
}
MemberDescriptor::MemberDescriptor(XMLObject *pParent, const char *pzTag, void *pVal, StringAbstraction *pHandler)
{
Init(pParent);
strTagName = pzTag;
m_Member.pUserString = pVal;
DataType = UserString;
m_DataAbstractor.pStringHandler = pHandler;
}
// Construct a string collection mapping entry
MemberDescriptor::MemberDescriptor(XMLObject *pParent, const char *pzTag, void *pStringCollection, StringCollectionAbstraction *pHandler)
{
Init(pParent);
strTagName = pzTag;
m_Member.pUserStringCollection = pStringCollection;
DataType = UserStringCollection;
m_DataAbstractor.pStrListHandler = pHandler;
}
// Construct an integer array mapping entry
MemberDescriptor::MemberDescriptor(XMLObject *pParent, const char *pzTag, void *pIntegerArray, IntegerArrayAbstraction *pHandler)
{
Init(pParent);
strTagName = pzTag;
m_Member.pUserIntegerArray = pIntegerArray;
DataType = UserIntegerArray;
m_DataAbstractor.pIntArrayHandler = pHandler;
}
MemberDescriptor::MemberDescriptor(XMLObject *pParent, const char *pzTag, XMLObject *pObj)
{
Init(pParent);
strTagName = pzTag;
m_Member.pObject = pObj;
DataType = XMLObj;
}
MemberDescriptor::MemberDescriptor(XMLObject *pParent, const char *pzTag, XMLObject **pObj, ObjectFactory pFactory)
{
Init(pParent);
strTagName = pzTag;
m_Member.ppObject = pObj;
m_pfnFactoryCreate = pFactory;
DataType = XMLObjPtr;
}
MemberDescriptor::MemberDescriptor(XMLObject *pParent, const char *pzTag, void *pList, ListAbstraction *pHandler, ObjectFactory pFactory)
{
Init(pParent);
strTagName = pzTag;
m_pfnFactoryCreate = pFactory;
m_Member.pXMLObjList = pList;
DataType = XMLObjList;
m_DataAbstractor.pListHandler = pHandler;
}
int MemberDescriptor::GetObjectContainmentCount()
{
int nContainmentCount = 0;
if ( DataType == XMLObj )
{
nContainmentCount = 1;
}
else if ( DataType == XMLObjPtr )
{
// if we've allocated the object pointer, consider it an instance
if ( *(m_Member.ppObject) )
{
nContainmentCount = 1;
}
}
else if ( DataType == XMLObjList )
{
nContainmentCount = m_DataAbstractor.pListHandler->itemCount(m_Member.pXMLObjList);
}
else if (DataType == KeyedDataStructure )
{
m_DataAbstractor.pKeyDSA->itemCount(m_Member.pKeyedDSA);
}
return nContainmentCount;
}
// Only release an iterator if you have not walked the entire list.
// Calling GetNextContainedObject() after the last item in a list
// will return null and delete the iterator.
void MemberDescriptor::ReleaseObjectIterator( xmlObjectIterator iter )
{
if ( DataType == XMLObjList && iter )
{
m_DataAbstractor.pListHandler->releaseIterator(iter);
}
else if (DataType == KeyedDataStructure )
{
m_DataAbstractor.pKeyDSA->releaseIterator(iter);
}
}
void MemberDescriptor::RemoveLastContainedObject( xmlObjectIterator iter )
{
if ( DataType == XMLObjPtr )
{
// Null out what the ObjectPtr<> was pointing to.
*(m_Member.ppObject) = 0;
}
else if ( DataType == XMLObjList )
{
try
{
m_DataAbstractor.pListHandler->removeObject( m_Member.pXMLObjList, iter );
}
catch(...)
{
GString strError;
strError.Format("The list mapped to tag %s has an invalid list handler.", (const char *)strTagName);
TRACE_ERROR((const char *)strError);
}
}
else if (DataType == KeyedDataStructure )
{
// ignore. don't add the same object twice to keyed index search
}
}
int MemberDescriptor::AddContainedObject( XMLObject *pO )
{
int nRet = 1; // success
if ( DataType == XMLObjList )
{
m_DataAbstractor.pListHandler->append( m_Member.pXMLObjList, pO );
}
else if ( DataType == KeyedDataStructure )
{
m_DataAbstractor.pKeyDSA->AddObjectToStructure(m_Member.pKeyedDSA,pO,pO->getOID());
}
else if ( DataType == XMLObjPtr )
{
*(m_Member.ppObject) = pO;
}
else
{
// cannot Add an object to this member type.
nRet = 0;
}
return nRet;
}
XMLObject *MemberDescriptor::GetFirstContainedObject( xmlObjectIterator *iter )
{
XMLObject *pReturnObject = 0;
if ( DataType == XMLObj )
{
pReturnObject = m_Member.pObject;
}
else if ( DataType == XMLObjPtr )
{
pReturnObject = *(m_Member.ppObject);
}
else if ( DataType == XMLObjList )
{
try
{
pReturnObject = m_DataAbstractor.pListHandler->getFirst( m_Member.pXMLObjList, iter );
}
catch(...)
{
GString strError;
strError.Format("The list mapped to tag %s has an invalid list handler.", (const char *)strTagName);
TRACE_ERROR((const char *)strError);
pReturnObject = 0;
}
}
else if (DataType == KeyedDataStructure )
{
pReturnObject = m_DataAbstractor.pKeyDSA->getFirst( m_Member.pKeyedDSA,iter);
}
if (pReturnObject)
{
// a usefull development time object reference validation. 777 is good.
// any other value indicates corrupt or unowned memory at this location.
// only possible if the implementation object was deleted in the application
// without sync'ing the ref count.
if (pReturnObject->m_ValidObjectBeg != 777 ||
pReturnObject->m_ValidObjectEnd != 777 )
{
return 0;
// This indicates that the return object is no longer valid.
// The object has been deleted but some data structure kept
// an invalid pointer to it. This can happen when Objects with
// Interfaces (CORBA,COM,RPC) decrement to destroy the object.
// Then leave a reference to it in a list, hash, or ObjPointer.
GString strTypeDescription;
GetTypeName(strTypeDescription);
const char *pzOwningObject = (m_ParentObject) ? m_ParentObject->GetObjectType() : "Global";
// Object [O] conains an invalid Obj Ref in a [List] mapped to tag [MyXMLTag]
throw GenericException("XML Object", 2, pzOwningObject,
(const char *)strTypeDescription,
(const char *)strTagName);
}
}
return pReturnObject;
}
XMLObject *MemberDescriptor::GetNextContainedObject( xmlObjectIterator iter )
{
XMLObject *pReturnObject = 0;
if ( DataType == XMLObjList )
{
pReturnObject = m_DataAbstractor.pListHandler->getNext( m_Member.pXMLObjList, iter );
}
else if (DataType == KeyedDataStructure )
{
pReturnObject = m_DataAbstractor.pKeyDSA->getNext( m_Member.pKeyedDSA, iter );
}
return pReturnObject;
}
bool MemberDescriptor::IsSimpleType()
{
if (DataType == ManagedByDerivedClass || DataType == UserString
|| DataType == Str || DataType == Bool || DataType == Int || DataType == Long)
return true;
return false;
}
bool MemberDescriptor::IsSubObject()
{
if ( DataType == ManagedByDerivedClass )
{
return m_DataAbstractor.pMemberHandler->IsMemberObject((const char *)strTagName);
}
return (DataType == XMLObjList || DataType == XMLObj || DataType == Root || DataType == XMLObjPtr || DataType == KeyedDataStructure);
}
// GetMemberValue() returns the value for all simple datatypes.
// For complex types (list<void>, list<object>, object&, and UserCollections )
// false is returned, since there is no simple value.
bool MemberDescriptor::GetMemberValue(GString &strValue)
{
bool bRet = false;
if ( DataType == ManagedByDerivedClass )
{
try
{
m_DataAbstractor.pMemberHandler->GetMember( (const char *)strTagName, strValue/*oStr*/ );
bRet = true;
}
catch(...)
{
GString strError;
strError.Format("The custom handler for %s failed.", (const char *)strTagName);
TRACE_ERROR((const char *)strError);
bRet = false;
}
}
else if(DataType == UserString)
{
try
{
strValue = m_DataAbstractor.pStringHandler->data(m_Member.pUserString);
bRet = true;
}
catch(...)
{
GString strError;
strError.Format("The string mapped to tag %s has an invalid string handler.", (const char *)strTagName);
TRACE_ERROR((const char *)strError);
bRet = false;
}
}
else if (DataType == Str)
{
bRet = true;
}
else if (DataType == Bool)
{
if (*m_Member.pBool)
strValue = "True";
else
strValue = "False";
bRet = true;
}
else if(DataType == Int)
{
strValue.Format("%d",*m_Member.pInt);
bRet = true;
}
else if(DataType == Long)
{
strValue.Format("%ld",*m_Member.pLong);
bRet = true;
}
// else DataType is one of:
// ( XMLObjList || XMLObj || Root || XMLObjPtr || UserStringCollection || UserIntegerArray)
return bRet;
}