metadataengine/server/src/mdsobjectdef.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 26 Jan 2010 12:13:20 +0200
changeset 1 acef663c1218
parent 0 c53acadfccc6
child 14 646a02f170b9
permissions -rw-r--r--
Revision: 201001 Kit: 201004

/*
* 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:  Class to hold description about one object and it's properties
*
*/

#include "mdsobjectdef.h"

#include "mdcdef.h"
#include "mdspropertydef.h"
#include "mdsdbconnectionpool.h"
#include "mdcserializationbuffer.h"
#include "mdsindexer.h"
#include "mdeinternalerror.h"

/**
 * NewLC
 */
CMdsObjectDef* CMdsObjectDef::NewLC(const TDesC& aName, const CMdsObjectDef* aParent )
	{
	CMdsObjectDef* ret = new( ELeave ) CMdsObjectDef( aParent );
	CleanupStack::PushL( ret );
	ret->ConstructL( aName );
	return ret;
	}
	
/**
 * NewL
 */
CMdsObjectDef* CMdsObjectDef::NewL( const TDesC& aName, const CMdsObjectDef* aParent )
	{
	CMdsObjectDef* ret = CMdsObjectDef::NewLC( aName, aParent );
	CleanupStack::Pop( ret );
	return ret;
	}

/**
 * default constructor
 */
inline CMdsObjectDef::CMdsObjectDef( const CMdsObjectDef* aParent )
	: iParent ( aParent ), iFlags( EObjectDefFlagsNone ), iMandatoryPropertyCount( 0 )
	{}

/**
 * ConstructL
 */
void CMdsObjectDef::ConstructL( const TDesC& aName )
	{
	// check that only allowed characters (A-Z, a-z) are used
	CheckAllowerCharatersL( aName, EFalse );

	CMdsItemDef::ConstructL( aName );
	}

/**
 * Destructor
 */
CMdsObjectDef::~CMdsObjectDef()
	{
	// deleting properties
	iPropertyDefs.ResetAndDestroy();
	iPropertyDefs.Close();

	iCol2Prop.Close();
	}

void CMdsObjectDef::AddPropertyL( const TDesC& aName, TPropertyType aType,
								  const TMdCValueUnion& aMinAdd, const TMdCValueUnion& aMaxAdd,
								  TBool aReadOnly, TBool aMandatory, TBool aIndexed )
	{
	CMdsPropertyDef* newProp = CommonAddPropertyL( aName, aType, aReadOnly, aMandatory, aIndexed );
	if (!newProp)
		{
		User::Leave( KErrMdEUnknownPropertyDef );
		}
	switch (aType)
		{									
		case EPropertyUint32:
		case EPropertyText:
		case EPropertyBool:		
			{									
			newProp->AddMinMaxValueL(aMinAdd.iUint32,aMaxAdd.iUint32);
			break;
			}
		case EPropertyInt32:
			{	
			newProp->AddMinMaxValueL(aMinAdd.iInt32,aMaxAdd.iInt32);
			break;
			}
		case EPropertyInt64:
		case EPropertyTime:
			{	
			newProp->AddMinMaxValueL(aMinAdd.iInt64,aMaxAdd.iInt64);
			break;
			}
		case EPropertyReal64:
			{									
			newProp->AddMinMaxValueL(aMinAdd.iReal,aMaxAdd.iReal);
			break;
			}

	    default:
	    	{
#ifdef _DEBUG
            User::Panic( _L("MdSODAdd") , KErrMdEUnknownPropertyType );
#endif		    	
	    	User::Leave( KErrMdEUnknownPropertyType );
	    	}
		}
	}
	
/**
 * AddPropertyL
 */
void CMdsObjectDef::AddPropertyL( const TDesC& aName, TPropertyType aType,
	                              TInt32 aMinAdd, TInt32 aMaxAdd,
	                              TBool aReadOnly, TBool aMandatory, TBool aIndexed )
	{
	CMdsPropertyDef* newProp = CommonAddPropertyL( aName, aType, aReadOnly, aMandatory, aIndexed );
	newProp->AddMinMaxValueL( aMinAdd, aMaxAdd );
	}

/**
 * AddPropertyL
 */
void CMdsObjectDef::AddPropertyL( const TDesC& aName, TPropertyType aType,
	                              TUint32 aMinAdd, TUint32 aMaxAdd,
	                              TBool aReadOnly, TBool aMandatory, TBool aIndexed )
	{
	CMdsPropertyDef* newProp = CommonAddPropertyL( aName, aType, aReadOnly, aMandatory, aIndexed );
	newProp->AddMinMaxValueL( aMinAdd, aMaxAdd );
	}

/**
 * AddPropertyL
 */
void CMdsObjectDef::AddPropertyL( const TDesC& aName, TPropertyType aType,
	                              const TInt64& aMinAdd, const TInt64& aMaxAdd,
	                              TBool aReadOnly, TBool aMandatory, TBool aIndexed )
	{
	CMdsPropertyDef* newProp = CommonAddPropertyL( aName, aType, aReadOnly, aMandatory, aIndexed );
	newProp->AddMinMaxValueL( aMinAdd, aMaxAdd );
	}

/**
 * AddPropertyL
 */
void CMdsObjectDef::AddPropertyL( const TDesC& aName, TPropertyType aType,
	                              const TReal& aMinAdd, const TReal& aMaxAdd,
	                              TBool aReadOnly, TBool aMandatory, TBool aIndexed )
	{
	CMdsPropertyDef* newProp = CommonAddPropertyL( aName, aType, aReadOnly, aMandatory, aIndexed );
	newProp->AddMinMaxValueL( aMinAdd, aMaxAdd );
	}

/**
 * CommonAddPropertyL
 */
CMdsPropertyDef* CMdsObjectDef::CommonAddPropertyL( const TDesC& aName, TPropertyType aType,
		TBool aReadOnly, TBool aMandatory, TBool aIndexed )
	{
	CMdsPropertyDef* propertyDef = CMdsPropertyDef::NewLC( aName, aType, aReadOnly, aMandatory,
			aIndexed );
	iPropertyDefs.AppendL( propertyDef );
	CleanupStack::Pop( propertyDef );
	return propertyDef;
	}

CMdsPropertyDef* CMdsObjectDef::CommonAddPropertyL( const TDesC& aName, TPropertyType aType,
		TUint32 aFlags, TDefId aId )
	{
	CMdsPropertyDef* propertyDef = CMdsPropertyDef::NewLC( aName, aType, aFlags );
	propertyDef->SetId(aId);
	iPropertyDefs.AppendL( propertyDef );
	CleanupStack::Pop( propertyDef );
	return propertyDef;
	}

CMdsPropertyDef* CMdsObjectDef::GetProperty( TUint32 aIndex ) const
	{
	return iPropertyDefs[aIndex];
	}

CMdsPropertyDef* CMdsObjectDef::GetProperty( const TDesC& aName ) const
	{
	const TInt count = iPropertyDefs.Count();
	
	for ( TInt i = 0; i < count; ++i )
		{
		if( iPropertyDefs[i]->GetName().Compare( aName ) == 0 )
			{
			return iPropertyDefs[i];
			}
		}
	if ( iParent )
		{
		return iParent->GetProperty( aName );
		}
	return NULL;
	}


const CMdsPropertyDef* CMdsObjectDef::GetPropertyByIdL( TDefId aId ) const
	{
	const TInt propertyDefCount = iPropertyDefs.Count();
	for ( TInt i = 0; i < propertyDefCount; ++i )
		{
		const CMdsPropertyDef* propDef = iPropertyDefs[i];
		if( propDef->GetId() == aId )
			{
			return propDef;
			}
		}
	if ( iParent )
		{
		return iParent->GetPropertyByIdL( aId );
		}
	return NULL;
	}


void CMdsObjectDef::StoreToDBL( TDefId aNamespaceDefId )
	{
	_LIT( KMdsSqlClauseTriggerObjectDef, "CREATE TRIGGER Delete%S%u DELETE ON Object%u BEGIN DELETE FROM %S%u WHERE ObjectId=OLD.ObjectId; END;" );
	_LIT( KMdsSqlClauseAddObjectDef, "INSERT INTO ObjectDef(NamespaceDefId, ParentDefId, Flags, Name) Values(?,?,?,?);" );

	RRowData rowData;
    CleanupClosePushL( rowData );

	if ( !GetStoredInDB() )
		{
		rowData.AppendL( TColumn( aNamespaceDefId ) );
		rowData.AppendL( TColumn( iParent ? iParent->GetId() : KNoDefId ) );
		rowData.AppendL( TColumn( (TInt32)iFlags ) );
		rowData.AppendL( TColumn( GetName().AllocL() ) );

		TDefId id = MMdSIndexer::ExecuteAndGetIndexL( KMdsSqlClauseAddObjectDef,rowData );

	    SetId( id );
       	SetStoredInDB();

    	if ( GetId() != KBaseObjectDefId )
    		{
	    	// Create trigger
	        HBufC* sqlQueryCreateTrigger = HBufC::NewLC( KMdsSqlClauseTriggerObjectDef().Size() + ( KMaxUintValueLength * 3 )  + ( GetName().Length() * 2 ) );
            TPtr sqlPtr = sqlQueryCreateTrigger->Des();
            sqlPtr.Format( KMdsSqlClauseTriggerObjectDef, &GetName(), aNamespaceDefId, aNamespaceDefId, &GetName(), aNamespaceDefId );
            RRowData rowDataDummy;
		    CleanupClosePushL( rowDataDummy );
		    CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL();
            connection.ExecuteL( *sqlQueryCreateTrigger, rowDataDummy );
            CleanupStack::PopAndDestroy( 2, sqlQueryCreateTrigger ); // rowDataDummy, sqlQueryCreateTrigger
    		}
		}

	// add propertyDef to DB
	for( TInt counter = 0; counter < iPropertyDefs.Count(); ++counter )
		{
		iPropertyDefs[counter]->StoreToDBL( GetId() );
		}
	
	CleanupStack::PopAndDestroy( &rowData );
	}

CMdsPropertyDef* CMdsObjectDef::FindProperty( const TDesC& aName ) const
	{
	const TInt count = iPropertyDefs.Count();
	
	for ( TInt i = 0; i < count; ++i )
		{
		if ( iPropertyDefs[i]->GetName().Compare( aName ) == 0 )
			{
			return iPropertyDefs[i];
			}
		}
	return NULL;
	}

void CMdsObjectDef::MergeL( CMdsObjectDef* aObjectDef, const TBool& /*aDryRun*/ )
	{
	const TInt count = aObjectDef->iPropertyDefs.Count();
	
	for ( TInt i = 0; i < count; ++i )
		{
		CMdsPropertyDef* lPropertyDef = FindProperty( aObjectDef->iPropertyDefs[i]->GetName() );
		if ( lPropertyDef )
			{
			if ( *lPropertyDef != *(aObjectDef->iPropertyDefs[i]) )
				{
				User::Leave( KErrAlreadyExists );
				}
			}
		else
			{
			User::Leave( KErrAccessDenied );
			}
		}
	}

void CMdsObjectDef::AddPropertyL( const TDefId aId, TPropertyType aType, TUint32 aFlags,
	                              const TDesC& aMinAdd, const TDesC& aMaxAdd, const TDesC& aName )
	{
	CMdsPropertyDef* prop = CommonAddPropertyL( aName, aType, aFlags, aId );
	prop->SetStoredInDB();
	switch( aType )
		{
		case EPropertyBool: case EPropertyInt8: case EPropertyUint8: case EPropertyInt16:
        case EPropertyUint16: case EPropertyInt32: case EPropertyText:
        	{
        	TInt32 minValue = 0;
            TInt32 maxValue = 0;
        	TLex lex( aMinAdd );
        	lex.Val( minValue );
        	lex.Assign( aMaxAdd );
        	lex.Val( maxValue );
        	prop->AddMinMaxValueL( minValue, maxValue );
        	break;
        	}
        case EPropertyUint32:
        	{
        	TUint32 minValue = 0;
        	TUint32 maxValue = 0;
        	TLex lex( aMinAdd );
        	lex.Val( (TInt64&)minValue );
        	lex.Assign( aMaxAdd );
        	lex.Val( (TInt64&)maxValue );
        	prop->AddMinMaxValueL( minValue, maxValue );
        	break;
        	}
        case EPropertyInt64:
        case EPropertyTime:
        	{
        	TInt64 minValue, maxValue;
        	TLex lex( aMinAdd );
        	lex.Val( minValue );
        	lex.Assign( aMaxAdd );
        	lex.Val( maxValue );
        	prop->AddMinMaxValueL( minValue, maxValue );
        	break;
        	}
        case EPropertyReal32:
        case EPropertyReal64:
        	{
        	TReal minValue, maxValue;
        	TLex lex( aMinAdd );
        	lex.Val( minValue );
        	lex.Assign( aMaxAdd );
        	lex.Val( maxValue );
        	prop->AddMinMaxValueL( minValue, maxValue );
        	break;
        	}
        default:
        	{
#ifdef _DEBUG
            User::Panic( _L("MdSODAd2") , KErrMdEUnknownPropertyType );
#endif		    	
        	
        	User::Leave( KErrMdEUnknownPropertyType );
        	}
		}
	}


void CMdsObjectDef::ImportFromDBL()
	{
	_LIT( KMdsQueryGetPropertyDefs, "SELECT PropertyDefId,Flags,Type,MinValue,MaxValue,Name FROM PropertyDef WHERE ObjectDefId=?;" );
	_LIT( KMdsQueryGetCol2Prop,     "SELECT PropertyDefId,ColumnId FROM Col2Prop WHERE ObjectDefId=?;" );

	RMdsStatement query;
	CleanupClosePushL( query );

	// importing properties
	RRowData objectNumber;
	CleanupClosePushL( objectNumber );
	objectNumber.AppendL( TColumn( GetId() ) );

	CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL();
	TDefId propertyDefId = 0;
	TPropertyType type;
	TInt32 typeValue = 0;
	TUint32 propertyFlags = 0;
	TPtrC16 name;
    TPtrC16 minValue;
    TPtrC16 maxValue;
	RRowData getData;
	CleanupClosePushL( getData );
	getData.AppendL( TColumn( propertyDefId ) );
	getData.AppendL( TColumn( propertyFlags ) );
	getData.AppendL( TColumn( typeValue ) );
	getData.AppendL( TColumn( EColumnHBuf16 ) );
	getData.AppendL( TColumn( EColumnHBuf16 ) );
	getData.AppendL( TColumn( EColumnHBuf16 ) );
	connection.ExecuteQueryL( KMdsQueryGetPropertyDefs, query, objectNumber );
	while( connection.NextRowL( query, getData ) )
		{
		getData.Column( 0 ).Get( propertyDefId );
		getData.Column( 1 ).Get( propertyFlags );
		getData.Column( 2 ).Get( typeValue );
		type = (TPropertyType)typeValue;
		getData.Column( 3 ).Get( minValue );
		getData.Column( 4 ).Get( maxValue );
		getData.Column( 5 ).Get( name );
		AddPropertyL( propertyDefId, type, propertyFlags, minValue, maxValue, name );
		getData.Column( 5 ).Free( );
		getData.Column( 4 ).Free( );
		getData.Column( 3 ).Free( );
		}

	iCol2Prop.Reset();
	RMdsStatement queryCol;
	CleanupClosePushL( queryCol );
	RRowData getColData;
	CleanupClosePushL( getColData );
	TUint32 columnId = 0;
	getColData.AppendL( TColumn( propertyDefId ) );
	getColData.AppendL( TColumn( columnId ) );
	connection.ExecuteQueryL( KMdsQueryGetCol2Prop, queryCol, objectNumber );
	while( connection.NextRowL( queryCol, getColData ) )
		{
		getColData.Column( 0 ).Get( propertyDefId );
		getColData.Column( 1 ).Get( columnId );
		const CMdsPropertyDef* propertyDef = GetPropertyByIdL( propertyDefId );
		
		if( !propertyDef )
			{
			User::Leave( KErrMdEUnknownPropertyDef );
			}

		CMdsObjectDef::TMdsColumnOrder col = { columnId, *propertyDef };
		iCol2Prop.AppendL( col );
		
		if( propertyDef->GetMandatory() )
			{
			++iMandatoryPropertyCount;
			}
		}

	// everything is ok, so set the flags
	SetStoredInDB();
	SetTableStoredInDB();
	SetC2PStoredInDB();

	CleanupStack::PopAndDestroy( 5, &query ); // getColData, queryCol, getData, objectNumber, query
	}
	
TUint32 CMdsObjectDef::RequiredBufferSize()
	{
	TUint32 bufferSize = sizeof(TMdCObjectDef) + CMdsItemDef::RequiredBufferSize();

	// propertydefs
	const TInt propertyDefsCount = iPropertyDefs.Count();
	bufferSize += propertyDefsCount * sizeof(TMdCPropertyDef);
	for ( TInt i = 0; i < propertyDefsCount; ++i )
		{
		bufferSize += iPropertyDefs[i]->RequiredBufferSize();
		}

	return bufferSize;
	}

TMdCOffset CMdsObjectDef::SerializeL( CMdCSerializationBuffer& aBuffer, TMdCOffset aFreeSpace )
	{
	const TMdCOffset objectDefOffset = aBuffer.Position();
	TMdCObjectDef objectDef;
	// get const data and store Name
	objectDef.iDefId = GetId();
	objectDef.iParentId = iParent ? iParent->GetId() : KNoDefId;
	objectDef.iName.iPtr.iCount = GetName().Length();
	objectDef.iName.iPtr.iOffset = aFreeSpace;
	aBuffer.PositionL( aFreeSpace );
	aFreeSpace = CMdsItemDef::SerializeL( aBuffer );

	// calculate necessary stuff for propertyDefs
	const TInt propertyDefsCount = iPropertyDefs.Count();
	objectDef.iPropertyDefs.iPtr.iCount = propertyDefsCount;
	objectDef.iPropertyDefs.iPtr.iOffset = aFreeSpace;

	// create space for propertyDefs
	aFreeSpace += propertyDefsCount * sizeof(TMdCPropertyDef);

	for ( TInt i = 0; i < propertyDefsCount; ++i )
		{
		aBuffer.PositionL( objectDef.iPropertyDefs.iPtr.iOffset + i * sizeof(TMdCPropertyDef) );
		// write object
		aFreeSpace = iPropertyDefs[i]->SerializeL( aBuffer, aFreeSpace );
		}

	// store objectDef itself
	aBuffer.PositionL( objectDefOffset );
	objectDef.SerializeL( aBuffer );

	return aFreeSpace;
	}

TInt CMdsObjectDef::GetAllPropertiesCount() const
	{
#ifdef _DEBUG
	_LIT( KCountPanicError, "CMdsObjectDef::GetAllPropertiesCount()" );
	TInt temp = iPropertyDefs.Count() + ( iParent ? iParent->GetAllPropertiesCount() : 0 );
	__ASSERT_DEBUG( temp == iCol2Prop.Count(), User::Panic( KCountPanicError, KErrCorrupt ) );
#endif
	return iCol2Prop.Count();
	}

TInt CMdsObjectDef::GetMandatoryPropertyCount() const
	{
	return iMandatoryPropertyCount;
	}

void CMdsObjectDef::SetStoredEveryInDB()
	{
	SetStoredInDB();
	
	const TInt count = iPropertyDefs.Count();
	
	for ( TInt i = 0; i < count; ++i )
		{
		iPropertyDefs[i]->SetStoredInDB();
		}
	}

void CMdsObjectDef::SetNotStoredEveryInDB()
	{
	SetAllNotStoredInDB();
	
	const TInt count = iPropertyDefs.Count();
	
	for ( TInt i = 0; i < count; ++i )
		{
		iPropertyDefs[i]->SetAllNotStoredInDB();
		}
	}