metadataengine/client/src/mdeobject.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 25 May 2010 13:10:05 +0300
branchRCL_3
changeset 13 4a4892eec172
parent 3 6752808b2036
child 14 3e156c80c15d
permissions -rw-r--r--
Revision: 201019 Kit: 2010121

/*
* Copyright (c) 2009 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:  ?Description
*
*/


#include <mdeobject.h>

#include <mdeproperty.h>
#include <mdeobjectdef.h>
#include <mdenamespacedef.h>
#include <mdesession.h>
#include "mdcitem.h"
#include "mdscommoninternal.h"
#include "mdcserializationbuffer.h"

//////////////////////////////
//                          //
//        TMdEObject        //
//                          //
//////////////////////////////

EXPORT_C TMdEObject::TMdEObject() : 
	iDef( NULL )
	{
	}

EXPORT_C TItemId TMdEObject::Id() const
	{
	return iId;
	}

EXPORT_C const CMdEObjectDef& TMdEObject::DefL() const
	{
	if( !iDef )
		{
		User::Leave( KErrNotFound );
		}

	return *iDef;
	}

EXPORT_C TBool TMdEObject::Confidential() const
	{
    return iFlags & EMdEObjectFlagConfidential ? ETrue : EFalse;
	}

EXPORT_C TBool TMdEObject::Placeholder() const
	{
	return iFlags & EMdEObjectFlagPlaceholder ? ETrue : EFalse;
	}

EXPORT_C TBool TMdEObject::Removed() const
	{
	return iFlags & EMdEObjectFlagRemoved ? ETrue : EFalse;
	}

EXPORT_C TBool TMdEObject::NotPresent() const
	{
	return iFlags & EMdEObjectFlagNotPresent ? ETrue : EFalse;
	}

TUint32 TMdEObject::RequiredBufferSize()
	{
	return sizeof(TMdCObject);
	}

void TMdEObject::DeSerializeL(CMdCSerializationBuffer& aBuffer, 
		CMdENamespaceDef& aNamespaceDef)
	{
	const TMdCObject& object = TMdCObject::GetFromBufferL(aBuffer);

	// ID
	if ( object.iId == KNoId )
		{
		User::Leave( KErrNotFound );
		}
	iId = object.iId;

	// definition
	if ( object.iDefId == KNoDefId )
		{
		User::Leave( KErrNotFound );
		}
	iDef = aNamespaceDef.GetObjectDefL( object.iDefId );

	// object flags	
	iFlags = object.iFlags;
	}

//////////////////////////////
//                          //
//        CMdEObject        //
//                          //
//////////////////////////////

CMdEObject* CMdEObject::NewL( CMdEObjectDef& aDef, const TDesC& aUri, TUint32 aMediaId )
	{
	CMdEObject* self = CMdEObject::NewLC( aDef, aUri, aMediaId );
    CleanupStack::Pop( self );
    return self;
	}

CMdEObject* CMdEObject::NewLC( CMdEObjectDef& aDef, const TDesC& aUri, TUint32 aMediaId )
	{
	CMdEObject* self = new ( ELeave ) CMdEObject( NULL, KNoId, aDef );
    CleanupStack::PushL( self );
    self->ConstructL( aUri, aMediaId );
    return self;
	}

CMdEObject::CMdEObject(CMdESession* aSession, TItemId aId, CMdEObjectDef& aDef)
		: CMdEInstanceItem( aSession, aId ), iDef( &aDef )
	{
	}

void CMdEObject::ConstructL( const TDesC& aUri, TUint32 aMediaId )
	{
	InstanceItemBaseConstruct();

	DoSetUriL( aUri );
	
	iMediaId = aMediaId;

    iFlags = EMdEObjectFlagModOpen;
   	}

CMdEObject::~CMdEObject()
	{
	if ( OpenForModifications() && BelongsToSession() )
		{
		TRAP_IGNORE( Session().CancelObjectL( *this ) );
		}

	delete iUri;

	iPropertyArray.ResetAndDestroy();
	iPropertyArray.Close();

	iFreeTextArray.ResetAndDestroy();
	iFreeTextArray.Close();
	}

EXPORT_C CMdEObjectDef& CMdEObject::Def() const
	{
	__ASSERT_DEBUG( iDef, User::Panic( _L("Object def is NULL!"), KErrBadHandle ) );
	
	return *iDef;
	}

EXPORT_C void CMdEObject::SetDefL(CMdEObjectDef& aDef)
	{
	__ASSERT_DEBUG( iDef, User::Panic( _L("Object def is NULL!"), KErrBadHandle ) );

	if( BelongsToSession() || ( iDef->Id() != KBaseObjectDefId ) )
		{
		User::Leave( KErrNotSupported );
		}

	iDef = &aDef;
	}

EXPORT_C const TDesC& CMdEObject::Uri() const
	{
	return *iUri;
	}

EXPORT_C void CMdEObject::SetUriL(const TDesC& aUri)
	{
	DoSetUriL(aUri);
	}

EXPORT_C TUint32 CMdEObject::MediaId() const
	{
	return iMediaId;
	}

EXPORT_C void CMdEObject::SetMediaId(TUint32 aMediaId)
	{
	iFlags |= EMdEObjectFlagModObject;
	iMediaId = aMediaId;
	}

EXPORT_C TUint32 CMdEObject::UsageCount() const
	{
	return iUsageCount;
	}

EXPORT_C void CMdEObject::Guid( TInt64& aGuidHigh, TInt64& aGuidLow ) const
	{
	aGuidHigh = iGuidHigh;
	aGuidLow  = iGuidLow;
	}
	
EXPORT_C void CMdEObject::SetGuid( const TInt64& aGuidHigh, const TInt64& aGuidLow )
	{
	iFlags |= EMdEObjectFlagModObject;
	iGuidHigh = aGuidHigh;
	iGuidLow  = aGuidLow;
	}


EXPORT_C TBool CMdEObject::Confidential() const
	{
    return iFlags & EMdEObjectFlagConfidential ? ETrue : EFalse;
	}

EXPORT_C void CMdEObject::SetConfidential( TBool aValue )
	{
	//check if no change to value
	if (Confidential() && aValue || !Confidential() && !aValue) // Confidential() == aValue
		{
		return;
		}

	if ( aValue )
		{
	    iFlags |= EMdEObjectFlagConfidential;
		}
	else
		{
	    iFlags &= ~EMdEObjectFlagConfidential;
		}
	iFlags |= EMdEObjectFlagModObject;
	}

EXPORT_C TBool CMdEObject::Placeholder() const
	{
	return iFlags & EMdEObjectFlagPlaceholder ? ETrue : EFalse;
	}

EXPORT_C void CMdEObject::SetPlaceholder( TBool aValue )
	{
	//check if no change to value
	if ( Placeholder() && aValue || !Placeholder() && !aValue) // Placeholder() == aValue
		{
		return;
		}

	if ( aValue )
		{
		iFlags |= EMdEObjectFlagPlaceholder;
		}
	else
		{
		iFlags &= ~EMdEObjectFlagPlaceholder;
		}
	iFlags |= EMdEObjectFlagModObject;
	}

void CMdEObject::DoSetUriL(const TDesC& aUri)
	{
	if ( iUri )
		{
		if ( *iUri == aUri )
			{
			return;
			}
		else
			{
			delete iUri;
			iUri = NULL;
			}
		}

	iUri = HBufC::NewL( aUri.Length() );
	// Note: CopyLC doesn't push anything to cleanup stack
	iUri->Des().CopyLC( aUri );
	iFlags |= EMdEObjectFlagModObject;
	}

EXPORT_C TInt CMdEObject::PropertyCount() const
	{
	const TInt propertyCount = iPropertyArray.Count();
	if (!(iFlags & EMdEObjectFlagModObject))
		{
		return propertyCount;
		}

	TInt c = 0;
	for (TInt i = 0; i < propertyCount; ++i)
		{
		if ( ! iPropertyArray[i]->Removed() )
			{
			++c;
			}
		}
	return c;
	}

EXPORT_C CMdEProperty& CMdEObject::PropertyL(TInt aIndex) const
	{
	if ( aIndex < 0 || aIndex > PropertyCount() )
		{
		User::Leave( KErrArgument );
		}
	if (!(iFlags & EMdEObjectFlagModObject))
		{
		return *iPropertyArray[aIndex];
		}
	
	TInt j = 0;
	const TInt count = iPropertyArray.Count();
	
	for (TInt i = 0; i < count; ++i)
		{
		if ( ! iPropertyArray[i]->Removed() )
			{
			if (j == aIndex)
				{
				return *iPropertyArray[j];
				}
			++j;
			}
		}
	User::Leave( KErrNotFound );
	return *iPropertyArray[0]; // <-- just to stop compiler warnings!!
	}

EXPORT_C TInt CMdEObject::PropertyCount(const CMdEPropertyDef& aDef) const
	{
	TInt propCount = 0;
	
	const TInt count = iPropertyArray.Count();
	
	for (TInt i = 0; i < count; i++)
		{
        if( ! iPropertyArray[i]->Removed() &&
            iPropertyArray[i]->Def().Compare( aDef ) == 0 )
        	{
        	++propCount;
        	}
		}
    return propCount;
	}

EXPORT_C TInt CMdEObject::Property(const CMdEPropertyDef& aDef, CMdEProperty*& aProperty, TInt aStartAt) const
    {
    const TInt count = iPropertyArray.Count();

    if( aStartAt >= 0 )
        {
        TInt low( aStartAt );
        TInt high( count );
    
        while( low < high )
            {
            TInt mid( (low+high)>>1 );
            
            TInt compare( aDef.Compare( iPropertyArray[mid]->Def() ) );
            if( compare == 0 )
                {
                if( !iPropertyArray[mid]->Removed() )
                    {
                    aProperty = iPropertyArray[mid];
                    return mid;
                    }
                }
            else if( compare > 0 )
                {
                low = mid + 1;
                }
            else
                {
                high = mid;
                }
            }
        }
    return KErrNotFound;
    }
    
EXPORT_C CMdEProperty& CMdEObject::AddBoolPropertyL(CMdEPropertyDef& aDef, TBool aValue)
	{
    if( aDef.PropertyType() != EPropertyBool )
    	{
    	User::Leave( KErrArgument );
    	}	
	
	CMdEProperty* property = CMdEProperty::NewLC(aDef, *this);
	property->SetBoolValueL( aValue );
	DoAddPropertyL(*property);
	CleanupStack::Pop(property);

	return *property;
	}

EXPORT_C CMdEProperty& CMdEObject::AddInt8PropertyL(CMdEPropertyDef& aDef, TInt8 aValue)
	{
    if( aDef.PropertyType() != EPropertyInt8 )
    	{
    	User::Leave( KErrArgument );
    	}	
	
    CMdEProperty* property = CMdEProperty::NewLC(aDef, *this);
    property->SetInt8ValueL( aValue );
	DoAddPropertyL(*property);
	CleanupStack::Pop(property);

	return *property;
	}

EXPORT_C CMdEProperty& CMdEObject::AddUint8PropertyL(CMdEPropertyDef& aDef, TUint8 aValue)
	{
    if( aDef.PropertyType() != EPropertyUint8 )
    	{
    	User::Leave( KErrArgument );
    	}	
	
    CMdEProperty* property = CMdEProperty::NewLC(aDef, *this);
    property->SetUint8ValueL( aValue );
	DoAddPropertyL(*property);
	CleanupStack::Pop(property);

	return *property;
	}

EXPORT_C CMdEProperty& CMdEObject::AddInt16PropertyL(CMdEPropertyDef& aDef, TInt16 aValue)
	{
    if( aDef.PropertyType() != EPropertyInt16 )
    	{
    	User::Leave( KErrArgument );
    	}	
	
    CMdEProperty* property = CMdEProperty::NewLC(aDef, *this);
    property->SetInt16ValueL( aValue );
	DoAddPropertyL(*property);
	CleanupStack::Pop(property);

	return *property;
	}

EXPORT_C CMdEProperty& CMdEObject::AddUint16PropertyL(CMdEPropertyDef& aDef, TUint16 aValue)
	{
    if( aDef.PropertyType() != EPropertyUint16 )
    	{
    	User::Leave( KErrArgument );
    	}	
	
    CMdEProperty* property = CMdEProperty::NewLC(aDef, *this);
    property->SetUint16ValueL( aValue );
	DoAddPropertyL(*property);
	CleanupStack::Pop(property);

	return *property;
	}

EXPORT_C CMdEProperty& CMdEObject::AddInt32PropertyL(CMdEPropertyDef& aDef, TInt32 aValue)
	{
    if( aDef.PropertyType() != EPropertyInt32 )
    	{
    	User::Leave( KErrArgument );
    	}	

    CMdEProperty* property = CMdEProperty::NewLC(aDef, *this);
    property->SetInt32ValueL( aValue );
	DoAddPropertyL(*property);
	CleanupStack::Pop(property);

	return *property;
	}

EXPORT_C CMdEProperty& CMdEObject::AddUint32PropertyL(CMdEPropertyDef& aDef, TUint32 aValue)
	{
    if( aDef.PropertyType() != EPropertyUint32 )
    	{
    	User::Leave( KErrArgument );
    	}	

    CMdEProperty* property = CMdEProperty::NewLC(aDef, *this);
    property->SetUint32ValueL( aValue );
	DoAddPropertyL(*property);
	CleanupStack::Pop(property);

	return *property;
	}

EXPORT_C CMdEProperty& CMdEObject::AddInt64PropertyL(CMdEPropertyDef& aDef, TInt64 aValue)
	{
    if( aDef.PropertyType() != EPropertyInt64 )
	   	{
    	User::Leave( KErrArgument );
    	}

    CMdEProperty* property = CMdEProperty::NewLC(aDef, *this);
    property->SetInt64ValueL( aValue );
	DoAddPropertyL(*property);
	CleanupStack::Pop(property);

	return *property;
	}

EXPORT_C CMdEProperty& CMdEObject::AddReal32PropertyL(CMdEPropertyDef& aDef, TReal32 aValue)
	{
    if( aDef.PropertyType() != EPropertyReal32 )
    	{
    	User::Leave( KErrArgument );
    	}

    CMdEProperty* property = CMdEProperty::NewLC(aDef, *this);
    property->SetReal32ValueL( aValue );
	DoAddPropertyL(*property);
	CleanupStack::Pop(property);

	return *property;
	}

EXPORT_C CMdEProperty& CMdEObject::AddReal64PropertyL(CMdEPropertyDef& aDef, TReal64 aValue)
	{
    if( aDef.PropertyType() != EPropertyReal64 )
    	{
    	User::Leave( KErrArgument );
    	}

    CMdEProperty* property = CMdEProperty::NewLC(aDef, *this);
    property->SetReal64ValueL( aValue );
	DoAddPropertyL(*property);
	CleanupStack::Pop(property);

	return *property;
	}

EXPORT_C CMdEProperty& CMdEObject::AddTextPropertyL(CMdEPropertyDef& aDef, const TDesC& aValue)
	{
    if( aDef.PropertyType() != EPropertyText )
    	{
    	User::Leave( KErrArgument );
    	}
	
    CMdEProperty* property = CMdEProperty::NewLC(aDef, *this);
    property->SetTextValueL( aValue );
	DoAddPropertyL(*property);
	CleanupStack::Pop(property);

	return *property;
	}

EXPORT_C CMdEProperty& CMdEObject::AddTimePropertyL(CMdEPropertyDef& aDef, TTime aValue)
	{
    if( aDef.PropertyType() != EPropertyTime )
    	{
    	User::Leave( KErrArgument );
    	}	

    CMdEProperty* property = CMdEProperty::NewLC(aDef, *this);
    property->SetTimeValueL( aValue );
	DoAddPropertyL(*property);
	CleanupStack::Pop(property);

	return *property;
	}

void CMdEObject::DoAddPropertyL(CMdEProperty& aProperty)
	{
	TInt err = iPropertyArray.InsertInOrder(&aProperty, 
								TLinearOrder<CMdEProperty>(CMdEObject::CompareProperties));
	if (err == KErrAlreadyExists)
		{
		const TInt f = iPropertyArray.FindInOrder(&aProperty,
								TLinearOrder<CMdEProperty>(CMdEObject::CompareProperties));

		// this must never happen
		__ASSERT_DEBUG( f >= KErrNone, User::Panic( _L("AddProperty find!"), KErrGeneral ) );

		if( ! iPropertyArray[f]->Removed() )
			{
			User::LeaveIfError( err );
			}

		CMdEProperty* oldProperty = iPropertyArray[f];
		iPropertyArray[f] = &aProperty;
		delete oldProperty;
		}
	else if (err < KErrNone)
		{
		User::Leave(err);
		}

	iFlags |= EMdEObjectFlagModProperty;
	}

EXPORT_C void CMdEObject::RemoveProperty(TInt aIndex)
	{
	const TInt propertyCount = iPropertyArray.Count();
	if ( aIndex < 0 || aIndex >= propertyCount )
		{
		return;
		}

	TInt j = 0;
	TBool found = EFalse;
	for (TInt i = 0; i < propertyCount; ++i)
		{
		if ( ! iPropertyArray[i]->Removed() )
			{
			if (j == aIndex)
				{
				found = ETrue;
				break;
				}
			++j;
			}
		}

	if ( !found )
		{
		return;
		}

	CMdEProperty* property = iPropertyArray[j];
	if( property->Def().ReadOnly() )
    	{
    	return;
    	}

	property->SetRemoved();

	iFlags |= EMdEObjectFlagModProperty;
	}

TInt CMdEObject::CompareProperties(const CMdEProperty& aFirst, const CMdEProperty& aSecond)
	{
	return aFirst.Def().Compare( aSecond.Def() );
	}

EXPORT_C TInt CMdEObject::FreeTextCount() const
	{
	return iFreeTextArray.Count();
	}

EXPORT_C TPtrC CMdEObject::FreeText(TInt aIndex) const
	{
	return *iFreeTextArray[aIndex];
	}

EXPORT_C TInt CMdEObject::FreeTextIndex(const TDesC& aFreeText) const
	{
	const TInt count = iFreeTextArray.Count();
	
	for (TInt i = 0; i < count; i++)
		{
		if (aFreeText.Compare(*iFreeTextArray[i]) == 0)
			{
			return i;
			}
		}

	return KErrNotFound;
	}

EXPORT_C void CMdEObject::AddFreeTextL(const TDesC& aFreeText)
	{
	HBufC* freeText = aFreeText.AllocLC();
	if (DoAddFreeTextL(*freeText) == KErrNone)
		{
		CleanupStack::Pop(freeText);
		}
	else
		{
		CleanupStack::PopAndDestroy(freeText);
		}
	}

TInt CMdEObject::DoAddFreeTextL(const HBufC& aFreeText)
	{
	TInt err = iFreeTextArray.InsertInOrder(&aFreeText, TLinearOrder<HBufC>(CMdEObject::CompareFreeTexts));

	if (err == KErrNone)
		{
		iFlags |= EMdEObjectFlagModFreeText;
		}
	return err;
	}

EXPORT_C void CMdEObject::RemoveFreeText(TInt aIndex)
	{
	delete iFreeTextArray[aIndex];
	iFreeTextArray[aIndex] = NULL;
	iFreeTextArray.Remove(aIndex);
	iFlags |= EMdEObjectFlagModFreeText;
	}

TInt CMdEObject::CompareFreeTexts(const HBufC& aFirst, const HBufC& aSecond)
	{
	return aFirst.Compare(aSecond);
	}

EXPORT_C void CMdEObject::MovePropertiesL(CMdEObject& aObject)
	{
	__ASSERT_DEBUG( iDef, User::Panic( _L("Object def is NULL!"), KErrBadHandle ) );
	
	// definitions must match
	if ( iDef->Compare( *aObject.iDef ) )
		{
		User::Leave( KErrArgument );
		}

	// object must be open
	if ( !OpenForModifications() )
		{
		User::Leave( KErrAccessDenied );
		}

	// and cannot contain any properties
	ClearObject( EFalse );
	if ( iPropertyArray.Count() )
		{
		User::Leave( KErrAlreadyExists );
		}

	const TInt arraySize = aObject.iPropertyArray.Count();
	iPropertyArray.ReserveL( arraySize );

	// add all properties to this object, 
	// but don't remove yet from other object
	for ( TInt i = 0; i < arraySize; ++i )
		{
        TInt err = iPropertyArray.InsertInOrder(aObject.iPropertyArray[i], 
                                TLinearOrder<CMdEProperty>(CMdEObject::CompareProperties));
    
        if (err == KErrAlreadyExists)
            {
            const TInt f = iPropertyArray.FindInOrder(aObject.iPropertyArray[i],
                                TLinearOrder<CMdEProperty>(CMdEObject::CompareProperties));

            if( !iPropertyArray[f]->Removed() )
                {
				continue;
                }

            CMdEProperty* oldProperty = iPropertyArray[f];
            iPropertyArray[f] = aObject.iPropertyArray[i];
            delete oldProperty;
            }
        else if (err < KErrNone)
            {
            // restore this objects to original state
            iPropertyArray.Reset();
            User::Leave(err);
            }	
		}

	// remove properties from other object
	aObject.iPropertyArray.Reset();

	// mark all moved properties as modified
	for ( TInt i = 0; i < arraySize; ++i )
		{
		CMdEProperty* property = iPropertyArray[i];
		property->SetModified();
		}

	iFlags |= EMdEObjectFlagModProperty;
	}


TBool CMdEObject::ObjectModified() const
    {
    return iFlags & EMdEObjectFlagModObject ? ETrue : EFalse;
    }

TBool CMdEObject::FreeTextModified() const
    {
    return iFlags & EMdEObjectFlagModFreeText ? ETrue : EFalse;
    }

TBool CMdEObject::PropertyModified() const
    {
    return iFlags & EMdEObjectFlagModProperty ? ETrue : EFalse;
    }

void CMdEObject::AutoLockL() const
	{
	if( BelongsToSession() )
		{
		User::Leave( KErrAlreadyExists );
		}
	
	iFlags |= EMdEObjectFlagAutoLock;
	}

EXPORT_C TBool CMdEObject::OpenForModifications() const
	{
	return iFlags & EMdEObjectFlagModOpen ? ETrue : EFalse;
	}

void CMdEObject::ClearObject( TBool aClearFlags )
	{
	// clear mod flags
	if (aClearFlags)
		{
		iFlags &= ~(EMdEObjectFlagModObject | EMdEObjectFlagModProperty | EMdEObjectFlagModFreeText | EMdEObjectFlagModOpen);

		// auto locked object's are marked back to open for modifications
		if ( iFlags & EMdEObjectFlagAutoLock )
			{
			iFlags |= EMdEObjectFlagModOpen;
			}
		}

	// clear mod flags in properties
	for (TInt i = iPropertyArray.Count() - 1; i >= 0 ; --i)
		{
    	CMdEProperty* prop = iPropertyArray[i];
        if ( prop->Removed() )
        	{
        	delete prop;
        	iPropertyArray.Remove( i );
        	continue;
        	}
        if (aClearFlags)
        	{
        	prop->ClearFlags();
        	}
		}
	}

void CMdEObject::SetNotOpenForModifications()
	{
	iFlags &= ~EMdEObjectFlagModOpen;
	}

TUint32 CMdEObject::ModifiedPropertiesCount() const
	{
	TUint32 modCount = 0;
	const TInt count = iPropertyArray.Count();
	
	for ( TInt i = 0; i < count; ++i )
		{
		if (iPropertyArray[i]->Modified())
			{
			++modCount;
			}
		}
	return modCount;
	}

TUint32 CMdEObject::RequiredBufferSize() const
	{
	TUint32 bufferSize = sizeof( TMdCObject );

	if (iUri)
		{
		bufferSize += CMdCSerializationBuffer::RequiredSize( *iUri );
		}

	TUint32 bufSave = bufferSize;
	// properties
	if ( iPropertyArray.Count() > 0 )
		{
		const TInt count = iPropertyArray.Count();
		for ( TInt i = 0; i < count; ++i )
			{
			if (iPropertyArray[i]->Modified())
				{
				bufferSize += iPropertyArray[i]->RequiredBufferSize();
				iFlags |= EMdEObjectFlagModProperty;
				}
			}
		}
	
	if (!(iFlags & EMdEObjectFlagModProperty))
		{
		bufferSize = bufSave;
		}
	
	// freetext
	if ( iFlags & EMdEObjectFlagModFreeText && iFreeTextArray.Count() > 0 )
		{
		
		const TInt count = iFreeTextArray.Count();
		for ( TInt i = 0; i < count; ++i )
			{
			bufferSize += CMdCSerializationBuffer::RequiredSize( *iFreeTextArray[i] );
			}
		}

	return bufferSize;
	}

TMdCOffset CMdEObject::SerializeL(CMdCSerializationBuffer& aBuffer, TMdCOffset aFreespaceOffset) const
	{
	__ASSERT_DEBUG( iDef, User::Panic( _L("Object def is NULL!"), KErrBadHandle ) );

	const TMdCOffset objectOffset = aBuffer.Position();
	TMdCObject object;
	
	// objectId
	object.iId = Id();
	// objectDefId
	object.iDefId = iDef->Id();
	// object flags
	object.iFlags = iFlags;
	// mediaId
	object.iMediaId = iMediaId;
	// usageCount
	object.iUsageCount = iUsageCount;
	// guid low
	object.iGuidHigh = iGuidHigh;
	// guid high
	object.iGuidLow = iGuidLow;
	// uri
	object.iUri.iPtr.iCount = iUri->Length();
	object.iUri.iPtr.iOffset = aFreespaceOffset;
	
	aBuffer.PositionL( aFreespaceOffset );
	aFreespaceOffset = aBuffer.InsertL( *iUri );

	// adding properties
	if ( iFlags & EMdEObjectFlagModProperty && iPropertyArray.Count() > 0 )
		{
		// first set up offset and count to properties
		object.iProperties.iPtr.iOffset = aFreespaceOffset;
		object.iProperties.iPtr.iCount = ModifiedPropertiesCount();

		// move after properties table
		aFreespaceOffset += object.iProperties.iPtr.iCount * sizeof( TMdCProperty );

		const TInt count = iPropertyArray.Count();
		TInt modifiedPropertyCounter = 0;
		// insert properties
		for ( TInt i = 0; i < count; ++i )
			{
			if (!iPropertyArray[i]->Modified())
				{
				continue;
				}
			aBuffer.PositionL( object.iProperties.iPtr.iOffset + modifiedPropertyCounter * sizeof( TMdCProperty ) );
			aFreespaceOffset = iPropertyArray[i]->SerializeL(aBuffer, aFreespaceOffset);
			++modifiedPropertyCounter;
			}
		}
	else
		{
		object.iProperties.iPtr.iOffset = KNoOffset;
		object.iProperties.iPtr.iCount = 0;
		}

	// adding freetext
	if ( iFlags & EMdEObjectFlagModFreeText && iFreeTextArray.Count() > 0 )
		{
		// first set up offset to freetext
		object.iFreeTexts.iPtr.iOffset = aFreespaceOffset;
		object.iFreeTexts.iPtr.iCount = iFreeTextArray.Count();

		const TInt count = iFreeTextArray.Count();
		
		// insert freetext
		aBuffer.PositionL( aFreespaceOffset );
		for ( TInt i = 0; i < count; ++i )
			{
			aFreespaceOffset = aBuffer.InsertL( *iFreeTextArray[i] );
			}
		}
	else
		{
		object.iFreeTexts.iPtr.iOffset = KNoOffset;
		object.iFreeTexts.iPtr.iCount = 0;
		}
	
	// store object informations
	aBuffer.PositionL( objectOffset );
	object.SerializeL( aBuffer );

	return aFreespaceOffset;
	}

CMdEObject* CMdEObject::NewL( CMdESession* aSession, CMdCSerializationBuffer& aBuffer, CMdENamespaceDef& aNamespaceDef )
	{
	CMdEObject* ret = CMdEObject::NewLC( aSession, aBuffer, aNamespaceDef );
	CleanupStack::Pop( ret );
	return ret;
	}


CMdEObject* CMdEObject::NewLC( CMdESession* aSession, CMdCSerializationBuffer& aBuffer, CMdENamespaceDef& aNamespaceDef )
	{
	const TMdCObject& serializedObject = TMdCObject::GetFromBufferL( aBuffer );
	
	// objectid
	if (serializedObject.iId == KNoId)
		{
		User::Leave( KErrNotFound );
		}

	// objectDefId
	if (serializedObject.iDefId == KNoDefId)
		{
		User::Leave( KErrNotFound );
		}
	CMdEObjectDef* newObjectDef = aNamespaceDef.GetObjectDefL( serializedObject.iDefId );
	if( !newObjectDef )
		{
		User::Leave( KErrNotFound );
		}

	CMdEObject* newObject = new (ELeave) CMdEObject( aSession, serializedObject.iId, *newObjectDef );
	CleanupStack::PushL( newObject );

	// set correct variables
	// object flags
	newObject->iFlags = serializedObject.iFlags;
	// mediaId
	newObject->iMediaId = serializedObject.iMediaId;
	// usage count
	newObject->iUsageCount = serializedObject.iUsageCount;
	// guid low
	newObject->iGuidHigh = serializedObject.iGuidHigh;
	// guid high
	newObject->iGuidLow = serializedObject.iGuidLow;
	// uri
	if ( serializedObject.iUri.iPtr.iCount == 0 )
		{
		User::Leave( KErrNotFound );
		}
	aBuffer.PositionL( serializedObject.iUri.iPtr.iOffset );
	newObject->iUri = aBuffer.ReceiveDes16L();

	// read properties array
	if ( serializedObject.iProperties.iPtr.iOffset != KNoOffset )
		{
		newObject->iPropertyArray.ReserveL( serializedObject.iProperties.iPtr.iCount );

		for ( TUint32 i = 0; i < serializedObject.iProperties.iPtr.iCount; ++i )
			{
			aBuffer.PositionL( serializedObject.iProperties.iPtr.iOffset
					+ i * sizeof(TMdCProperty) );

			CMdEProperty* property = CMdEProperty::NewLC( *newObject, aBuffer );
		    TInt err = newObject->iPropertyArray.InsertInOrder(property, 
		                                TLinearOrder<CMdEProperty>(CMdEObject::CompareProperties));
		    
		    if (err == KErrAlreadyExists)
		        {
		        const TInt f = newObject->iPropertyArray.FindInOrder(property,
		                                TLinearOrder<CMdEProperty>(CMdEObject::CompareProperties));

		        if( !newObject->iPropertyArray[f]->Removed() )
		            {
		            continue;
		            }

		        CMdEProperty* oldProperty = newObject->iPropertyArray[f];
		        newObject->iPropertyArray[f] = property;
		        delete oldProperty;
		        }
		    else if (err < KErrNone)
		        {
		        User::Leave(err);
		        }
			CleanupStack::Pop( property );
			}
		}

	// read freetext array
	if ( serializedObject.iFreeTexts.iPtr.iOffset != KNoOffset )
		{
		aBuffer.PositionL( serializedObject.iFreeTexts.iPtr.iOffset );

		newObject->iFreeTextArray.ReserveL( serializedObject.iFreeTexts.iPtr.iCount );
		for ( TUint32 i = 0; i < serializedObject.iFreeTexts.iPtr.iCount; ++i )
			{
			HBufC16* hbuf = aBuffer.ReceiveDes16L();
			CleanupStack::PushL( hbuf );
			newObject->iFreeTextArray.AppendL( hbuf );
			CleanupStack::Pop( hbuf );
			}
		}

	return newObject;
	}

TMdEInstanceType CMdEObject::InstanceType() const
	{
	return EMdETypeObject;
	}