/*
* Copyright (c) 2005,2006 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: Primary datatype for the entire Document Object Model.
*
*/
// INCLUDE FILES
#include "xndomnode.h"
#include "xndomattribute.h"
#include "xndomproperty.h"
#include "xndomlist.h"
#include "xndomstringpool.h"
// LOCAL CONSTANTS AND MACROS
const TInt KNotDefined = -1;
const TInt KPropertyListGranularity = 8;
// ============================ MEMBER FUNCTIONS ===============================
// -----------------------------------------------------------------------------
// CXnDomNode::CXnDomNode
// C++ default constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
//
CXnDomNode::CXnDomNode(CXnDomStringPool* aStringPool) :
iNameRef( KNotDefined ),
iNSRef( KNotDefined ),
iStringPool( aStringPool ),
iNodeId( KNotDefined )
{
}
// -----------------------------------------------------------------------------
// CXnDomNode::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CXnDomNode::ConstructL(const TDesC8& aName, const TDesC8& aNS)
{
iNameRef = iStringPool->AddStringL(aName);
iNSRef = iStringPool->AddStringL(aNS);
iChildList = CXnDomList::NewL(CXnDomList::ENodeList, iStringPool);
iAttributeList
= CXnDomList::NewL(CXnDomList::EAttributeList, iStringPool);
iPropertyList = CXnDomList::NewL(CXnDomList::EPropertyList, iStringPool,
KPropertyListGranularity);
}
// -----------------------------------------------------------------------------
// CXnDomNode::NewL
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CXnDomNode* CXnDomNode::NewL(const TDesC8& aName, const TDesC8& aNS,
CXnDomStringPool* aStringPool)
{
CXnDomNode* self = new (ELeave) CXnDomNode(aStringPool);
CleanupStack::PushL(self);
self->ConstructL(aName, aNS);
CleanupStack::Pop(self);
return self;
}
// -----------------------------------------------------------------------------
// CXnDomNode::NewL
// Two-phased stream constructor.
// -----------------------------------------------------------------------------
//
CXnDomNode* CXnDomNode::NewL(RReadStream& aStream,
CXnDomStringPool* aStringPool)
{
CXnDomNode* self = new (ELeave) CXnDomNode(aStringPool);
CleanupStack::PushL(self);
aStream >> *self;
CleanupStack::Pop(self);
return self;
}
// Destructor
CXnDomNode::~CXnDomNode()
{
delete iChildList;
delete iAttributeList;
delete iPropertyList;
delete iPCData;
}
// ---------------------------------------------------------------------
// CXnDomNode::CloneL
// Clones this node and it's child nodes. This is a recursive function.
// -----------------------------------------------------------------------------
//
EXPORT_C CXnDomNode* CXnDomNode::CloneL(CXnDomStringPool& aStringPool)
{
const TDesC8& name = iStringPool->String(iNameRef);
const TDesC8& ns = iStringPool->String(iNSRef);
CXnDomNode* clone = CXnDomNode::NewL(name, ns, &aStringPool);
CleanupStack::PushL(clone);
if (iPCData)
{
clone->AppendPCDataL(*iPCData);
}
clone->iNodeId = iNodeId;
TInt childCount(iChildList->Length());
for (TInt i = 0; i < childCount; i++)
{
CXnDomNode* childClone =
static_cast<CXnDomNode*> (iChildList->Item(i))->CloneL(
aStringPool);
CleanupStack::PushL(childClone);
childClone->iParentNode = clone;
clone->iChildList->AddItemL(childClone);
CleanupStack::Pop(childClone);
}
TInt attrCount(iAttributeList->Length());
for (TInt j = 0; j < attrCount; j++)
{
CXnDomAttribute
* attrClone =
static_cast<CXnDomAttribute*> (iAttributeList->Item(j))->CloneL(
aStringPool);
CleanupStack::PushL(attrClone);
clone->iAttributeList->AddItemL(attrClone);
CleanupStack::Pop(attrClone);
}
TInt propertyCount(iPropertyList->Length());
for (TInt k = 0; k < propertyCount; k++)
{
CXnDomProperty
* propClone =
static_cast<CXnDomProperty*> (iPropertyList->Item(k))->CloneL(
aStringPool);
CleanupStack::PushL(propClone);
clone->iPropertyList->AddItemL(propClone);
CleanupStack::Pop(propClone);
}
CleanupStack::Pop(clone);
return clone;
}
// -----------------------------------------------------------------------------
// CXnDomNode::Name
// -----------------------------------------------------------------------------
//
EXPORT_C const TDesC8& CXnDomNode::Name()
{
if( iNameRef == KNotDefined )
{
return KNullDesC8();
}
else
{
return iStringPool->String( iNameRef );
}
}
// -----------------------------------------------------------------------------
// CXnDomNode::Namespace
// -----------------------------------------------------------------------------
//
EXPORT_C const TDesC8& CXnDomNode::Namespace()
{
if( iNSRef == KNotDefined )
{
return KNullDesC8();
}
else
{
return iStringPool->String( iNSRef );
}
}
// -----------------------------------------------------------------------------
// CXnDomNode::AttributeList
// -----------------------------------------------------------------------------
//
EXPORT_C CXnDomList& CXnDomNode::AttributeList() const
{
return *iAttributeList;
}
// -----------------------------------------------------------------------------
// CXnDomNode::PropertyList
// -----------------------------------------------------------------------------
//
EXPORT_C CXnDomList& CXnDomNode::PropertyList()
{
return *iPropertyList;
}
// -----------------------------------------------------------------------------
// CXnDomNode::SetParent
// -----------------------------------------------------------------------------
//
EXPORT_C void CXnDomNode::SetParent(CXnDomNode* aParent)
{
iParentNode = aParent;
}
// -----------------------------------------------------------------------------
// CXnDomNode::Parent
// -----------------------------------------------------------------------------
//
EXPORT_C CXnDomNode* CXnDomNode::Parent() const
{
return iParentNode;
}
// -----------------------------------------------------------------------------
// CXnDomNode::AddChildL
// -----------------------------------------------------------------------------
//
EXPORT_C void CXnDomNode::AddChildL(CXnDomNode* aNode)
{
aNode->SetParent(this);
iChildList->AddItemL(aNode);
}
// -----------------------------------------------------------------------------
// CXnDomNode::AddChildL
// -----------------------------------------------------------------------------
//
EXPORT_C void CXnDomNode::AddChildL(CXnDomNode* aNode, TInt aIndex)
{
aNode->SetParent(this);
iChildList->AddItemL(aNode, aIndex);
}
// -----------------------------------------------------------------------------
// CXnDomNode::DeleteChild
// -----------------------------------------------------------------------------
//
EXPORT_C void CXnDomNode::DeleteChild(CXnDomNode* aNode)
{
iChildList->DeleteItem(aNode);
}
// -----------------------------------------------------------------------------
// CXnDomNode::ReplaceChildL
// -----------------------------------------------------------------------------
//
EXPORT_C void CXnDomNode::ReplaceChildL(CXnDomNode* aNode,
CXnDomNode* aNewNode)
{
CXnDomNode* swapChild = NULL;
CXnDomList& childList = aNode->ChildNodes();
TInt childCount(childList.Length());
for (TInt i = 0; i < childCount; i++)
{
swapChild = static_cast<CXnDomNode*> (childList.Item(i));
aNewNode->AddChildL(swapChild); //Let the new node adopt the child
childList.RemoveItem(swapChild); //Remove it from the orginal parent
}
iChildList->DeleteItem(aNode); // Delete the old child
aNewNode->SetParent(this); //Set new child
iChildList->AddItemL(aNewNode);
}
// -----------------------------------------------------------------------------
// CXnDomNode::ChildNodes
// -----------------------------------------------------------------------------
//
EXPORT_C CXnDomList& CXnDomNode::ChildNodes()
{
return *iChildList;
}
// -----------------------------------------------------------------------------
// CXnDomNode::SetNodeId
// -----------------------------------------------------------------------------
//
EXPORT_C void CXnDomNode::SetNodeId(const TInt aNodeId)
{
iNodeId = aNodeId;
}
// -----------------------------------------------------------------------------
// CXnDomNode::NodeId
// -----------------------------------------------------------------------------
//
EXPORT_C TInt CXnDomNode::NodeId() const
{
return iNodeId;
}
// -----------------------------------------------------------------------------
// CXnDomNode::ItemIndex
// -----------------------------------------------------------------------------
//
EXPORT_C TInt CXnDomNode::ItemIndex(const MXnDomListItem& aItem) const
{
return iChildList->ItemIndex(aItem);
}
// -----------------------------------------------------------------------------
// CXnDomNode::AppendPCDataL
// -----------------------------------------------------------------------------
//
EXPORT_C void CXnDomNode::AppendPCDataL(const TDesC8& aPCData)
{
if (iPCData)
{
iPCData = iPCData->ReAllocL(iPCData->Length() + aPCData.Length());
iPCData->Des().Append(aPCData);
}
else
{
iPCData = aPCData.AllocL();
}
}
// -----------------------------------------------------------------------------
// CXnDomNode::PCData
// -----------------------------------------------------------------------------
//
EXPORT_C const TDesC8& CXnDomNode::PCData()
{
if (iPCData)
{
return *iPCData;
}
return KNullDesC8;
}
// -----------------------------------------------------------------------------
// CXnDomNode::SetPCDataL
// -----------------------------------------------------------------------------
//
EXPORT_C void CXnDomNode::SetPCDataL(const TDesC8& aPCData)
{
if (iPCData)
{
delete iPCData;
iPCData = NULL;
}
iPCData = aPCData.AllocL();
}
// -----------------------------------------------------------------------------
// CXnDomNode::ContentType
// -----------------------------------------------------------------------------
//
EXPORT_C const TContentType& CXnDomNode::ContentType()
{
return iContentType;
}
// -----------------------------------------------------------------------------
// CXnDomNode::SetContentType
// -----------------------------------------------------------------------------
//
EXPORT_C void CXnDomNode::SetContentType(const TContentType& aContentType)
{
iContentType = aContentType;
}
// -----------------------------------------------------------------------------
// CXnDomNode::StringPool
// -----------------------------------------------------------------------------
//
EXPORT_C CXnDomStringPool* CXnDomNode::StringPool() const
{
return iStringPool;
}
// -----------------------------------------------------------------------------
// CXnDomNode::Size
// -----------------------------------------------------------------------------
//
TInt CXnDomNode::Size() const
{
TInt size(0);
size += sizeof(TInt16); //iNameRef
size += sizeof(TInt16); //iNSRef
size += sizeof(TBool); //iRefNode
if (iPCData)
{
size += sizeof(TInt8);
size += sizeof(TInt16);
size += iPCData->Size();
size++;
}
else
{
size += sizeof(TInt8);
}
size += sizeof(TInt32); //For nodeId
size += iAttributeList->Size();
size += iPropertyList->Size();
size += iChildList->Size();
return size;
}
// -----------------------------------------------------------------------------
// CXnDomNode::ExternalizeL
// NOTE: This function is not implemented yet!
// -----------------------------------------------------------------------------
//
void CXnDomNode::ExternalizeL(RWriteStream& aStream) const
{
aStream.WriteInt16L(iNameRef);
aStream.WriteInt16L(iNSRef);
aStream.WriteInt8L( 0 ); // ref node legacy.
if (iPCData)
{
aStream.WriteInt8L(ETrue);
aStream.WriteInt16L(iPCData->Length());
aStream << *iPCData;
}
else
{
aStream.WriteInt8L(EFalse);
}
aStream.WriteInt32L(iNodeId);
aStream << *iChildList;
aStream << *iAttributeList;
aStream << *iPropertyList;
}
// -----------------------------------------------------------------------------
// CXnDomNode::InternalizeL
// -----------------------------------------------------------------------------
//
void CXnDomNode::InternalizeL( RReadStream& aStream )
{
iNameRef = aStream.ReadInt16L();
iNSRef = KNotDefined; // This is set later by call to setnamespace,
aStream.ReadInt16L(); // so only consume legacy data from stream.
aStream.ReadInt8L(); // Consume legacy ref node parameter.
TInt len(0);
TBool exist(aStream.ReadInt8L());
if (exist)
{
len = aStream.ReadInt16L();
delete iPCData;
iPCData = NULL;
iPCData = HBufC8::NewL(aStream, len);
}
iNodeId = aStream.ReadInt32L();
iChildList = CXnDomList::NewL(aStream, iStringPool);
TInt count(iChildList->Length());
for (TInt i = 0; i < count; i++)
{
CXnDomNode* node = static_cast<CXnDomNode*> (iChildList->Item(i));
if (node)
{
node->SetParent(this);
}
else
{
User::Leave(KErrArgument);
}
}
iAttributeList = CXnDomList::NewL(aStream, iStringPool);
iPropertyList = CXnDomList::NewL(aStream, iStringPool);
}
// -----------------------------------------------------------------------------
// CXnDomNode::DescendantCount
// Recursive counting function
// -----------------------------------------------------------------------------
//
EXPORT_C TInt CXnDomNode::DescendantCount() const
{
TInt count(1); //Node itself
TInt length(iChildList->Length());
for (TInt i = 0; i < length; i++)
{
count
+= static_cast<CXnDomNode*> (iChildList->Item(i))->DescendantCount();
}
return count;
}
// -----------------------------------------------------------------------------
// CXnDomNode::DeleteAttributeList
// Deletes the attribute list
// -----------------------------------------------------------------------------
//
EXPORT_C void CXnDomNode::DeleteAttributeList()
{
delete iAttributeList;
iAttributeList = NULL;
}
// -----------------------------------------------------------------------------
// CXnDomNode::AttributeValue
// Returns value of "name" attribute
// -----------------------------------------------------------------------------
//
EXPORT_C const TDesC8& CXnDomNode::AttributeValue(const TDesC8& aAttribute) const
{
CXnDomAttribute* attribute =
static_cast<CXnDomAttribute*> (iAttributeList->FindByName(
aAttribute));
if (attribute)
{
return attribute->Value();
}
else
{
return KNullDesC8;
}
}
// -----------------------------------------------------------------------------
// CXnDomNode::SetLayoutNode
// Sets pointer to associated layout node
// -----------------------------------------------------------------------------
//
EXPORT_C void CXnDomNode::SetLayoutNode(CXnNode* aNode)
{
iLayoutNode = aNode;
}
// -----------------------------------------------------------------------------
// CXnDomNode::LayoutNode
// Gets pointer to associated layout node
// -----------------------------------------------------------------------------
//
EXPORT_C CXnNode* CXnDomNode::LayoutNode()
{
return iLayoutNode;
}
// -----------------------------------------------------------------------------
// CXnDomNode::SetNamespaceL
// -----------------------------------------------------------------------------
//
EXPORT_C void CXnDomNode::SetNamespaceL(const TDesC8& aNS)
{
iNSRef = iStringPool->AddStringL(aNS);
}
// -----------------------------------------------------------------------------
// CXnDomNode::SetOwnershipL
// Clones this node and it's child nodes and sets new namespace. This is a
// recursive function.
// -----------------------------------------------------------------------------
//
EXPORT_C void CXnDomNode::SetOwnershipL(const TDesC8& aNS)
{
TInt childCount(iChildList->Length());
SetNamespaceL(aNS);
for (TInt i = 0; i < childCount; i++)
{
CXnDomNode* child = static_cast<CXnDomNode*> (iChildList->Item(i));
child->SetOwnershipL(aNS);
}
}
// -----------------------------------------------------------------------------
// CXnDomNode::SwapStringPoolL
// -----------------------------------------------------------------------------
//
EXPORT_C void CXnDomNode::SwapStringPoolL( CXnDomStringPool* aStringPool )
{
if( !aStringPool )
{
User::Leave( KErrArgument );
}
if( iNameRef != KNotDefined )
{
iNameRef = aStringPool->AddStringL( iStringPool->String( iNameRef ) );
}
if( iNSRef != KNotDefined )
{
iNSRef = aStringPool->AddStringL( iStringPool->String( iNSRef ) );
}
iChildList->SwapStringPoolL( aStringPool );
TInt count = iChildList->Length();
for( TInt i = 0; i < count; i++ )
{
CXnDomNode* obj =
static_cast<CXnDomNode*> ( iChildList->Item( i ) );
obj->SwapStringPoolL( aStringPool );
}
iAttributeList->SwapStringPoolL( aStringPool );
count = iAttributeList->Length();
for( TInt i = 0; i < count; i++ )
{
CXnDomAttribute* obj =
static_cast<CXnDomAttribute*> ( iAttributeList->Item( i ) );
obj->SwapStringPoolL( aStringPool );
}
count = iPropertyList->Length();
iPropertyList->SwapStringPoolL( aStringPool );
for( TInt i = 0; i < count; i++ )
{
CXnDomProperty* obj =
static_cast<CXnDomProperty*> ( iPropertyList->Item( i ) );
obj->SwapStringPoolL( aStringPool );
}
iStringPool = aStringPool;
}
// End of File