// --------------------------------------------------------------------------------------
// Serializes TXmlEngNode to buffer
// --------------------------------------------------------------------------------------
//
TInt CXmlEngSerializerXOP::SerializeL( RBuf8& aBuffer, 
                                    const TXmlEngNode aRoot, 
									const TXmlEngSerializationOptions& aOptions )
    {
    if(aBuffer.Length())
        {
        aBuffer.Close();
        }
	LeaveIfXopIncludeL(aRoot);
    iDataContainerArray.Reset();	    
    if(aOptions.iDataSerializer)
    	{
    	return CXmlEngSerializer::SerializeL(aBuffer, aRoot, aOptions);
    	}    
    	
	TXmlEngSerializationOptions opt = aOptions;
	opt.iDataSerializer = this;
			
	RBuf8 xopDocument;
	CleanupClosePushL(xopDocument);
	aRoot.OwnerDocument().SaveL(xopDocument, aRoot, opt);

	if( iCleanXOPInfoset )		
		{
		if(xopDocument.Size() > aBuffer.MaxSize())
		    {
		    aBuffer.ReAllocL( xopDocument.Size() );
		    }
		aBuffer.Append(xopDocument);		
		}
	else		
		{    
	    // adjust buffer size
		TInt bufSize = KXOPDocumentStart().Size() 
					+ KMimeRoot().Size() 
					+ xopDocument.Size()
					+ KXOPDocumentEnd().Size();
		for(TInt j = 0; j < iDataContainerArray.Count(); j++)	
			{
			TPtrC8 contentTypeStr;
			if(GetContentTypeValue(iDataContainerArray[j], contentTypeStr))
				{
				bufSize += KMimeHeaderContentType().Size() 
						+ contentTypeStr.Size() 
						+ KNewLine().Size();					
				}
			bufSize += KMimeHeaderStart().Size() 
					+ KMimeHeaderContentIdStart().Size()
					+ iDataContainerArray[j].Cid().Length()
					+ KMimeHeaderContentIdEnd().Size()
					+ KNewLine().Size()
					+ iDataContainerArray[j].Size(); 
			}
		if (bufSize > aBuffer.MaxSize())
		    {
		    aBuffer.ReAllocL( bufSize );
		    }
		    
		// write to buffer
		aBuffer.Append(KXOPDocumentStart());
		aBuffer.Append(KMimeRoot());
		aBuffer.Append(xopDocument);
		for(TInt i = 0; i < iDataContainerArray.Count(); i++)	
			{
			aBuffer.Append(KMimeHeaderStart);
			TPtrC8 contentTypeStr;
			if(GetContentTypeValue(iDataContainerArray[i], contentTypeStr))
				{	
				aBuffer.Append(KMimeHeaderContentType);
				aBuffer.Append(contentTypeStr);
				aBuffer.Append(KNewLine);
				}
			aBuffer.Append(KMimeHeaderContentIdStart);				
			aBuffer.Append(iDataContainerArray[i].Cid());
			aBuffer.Append(KMimeHeaderContentIdEnd);
			aBuffer.Append(KNewLine);	
			switch(iDataContainerArray[i].NodeType())
				{
				case TXmlEngNode::EBinaryContainer:
					{
					if(opt.iOptions & TXmlEngSerializationOptions::KOptionDecodeBinaryContainers )	
						{						
						HBufC8* decodedData = CreateDecodedBufLC(iDataContainerArray[i].AsBinaryContainer().Contents());
						aBuffer.Append(decodedData->Des());
						CleanupStack::PopAndDestroy(); //decodedData
						}
					else
						{
						aBuffer.Append(iDataContainerArray[i].AsBinaryContainer().Contents());							
						}
					break;
					}
				case TXmlEngNode::EChunkContainer:
					{
					TPtrC8 data = TPtrC8(
						((RChunk&)iDataContainerArray[i].AsChunkContainer().Chunk()).Base()
						+ iDataContainerArray[i].AsChunkContainer().ChunkOffset(),
						iDataContainerArray[i].AsChunkContainer().Size());
					if(opt.iOptions & TXmlEngSerializationOptions::KOptionDecodeBinaryContainers )	
						{							
						HBufC8* decodedData = CreateDecodedBufLC(data); 
						aBuffer.Append(decodedData->Des());
						CleanupStack::PopAndDestroy(); //decodedData
						}
					else
						{
						aBuffer.Append(data);							
						}
					break;
					}
				case TXmlEngNode::EFileContainer:
					{
					TInt size = iDataContainerArray[i].AsFileContainer().Size();
					HBufC8* data = HBufC8::NewLC(size);
					TPtr8 dataPtr = data->Des();
					iDataContainerArray[i].AsFileContainer().File().Read(dataPtr, size);
					if(opt.iOptions & TXmlEngSerializationOptions::KOptionDecodeBinaryContainers )	
						{
						HBufC8* decodedData = CreateDecodedBufLC(dataPtr); 
						aBuffer.Append(decodedData->Des());
						CleanupStack::PopAndDestroy(); //decodedData							
						}
					else
						{
						aBuffer.Append(dataPtr);
						}
					CleanupStack::PopAndDestroy(); //data
					break;
					}														
				}						
			}
		aBuffer.Append(KXOPDocumentEnd);
		}
	CleanupStack::PopAndDestroy(); //xopDocument
	return aBuffer.Size(); 
    }