diff -r 000000000000 -r c53acadfccc6 metadataengine/server/src/mdsimportexport.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/metadataengine/server/src/mdsimportexport.cpp Mon Jan 18 20:34:07 2010 +0200 @@ -0,0 +1,2509 @@ +/* +* Copyright (c) 2007-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: Metadata schema container within server +* +*/ + +#include +#include +#include +#include +#include +#include + +#include + +#include "mdsimportexport.h" + +#include "mdcresult.h" +#include "mdcitem.h" +#include "mdcdef.h" +#include "mdsnamespacedef.h" +#include "mdsobjectdef.h" +#include "mdccommon.h" +#include "mdspropertydef.h" +#include "mdsschema.h" +#include "mdssqliteconnection.h" +#include "mdsdbconnectionpool.h" +#include "mdcserializationbuffer.h" +#include "mdssqlobjectmanipulate.h" +#include "mdsrelationdef.h" +#include "mdseventdef.h" +#include "mdsfindsqlclausedef.h" +#include "mdsclausebuffer.h" +#include "mdsmaintenanceengine.h" +#include "mdssqldbmaintenance.h" +#include "mdspreferences.h" +#include "mdscommoninternal.h" + +const TInt KMdsMaxUriLenght = KMaxFileName; +const TChar KMdsLineFeed = '\n'; + +const TInt KMdsMaxLogLineLenght( 2056 ); + +_LIT( KMdsErrorLogDirectory, "Metadata" ); +_LIT( KMdsErrorLogFilename, "importerror.log" ); + +// keyword definitions in import file +_LIT8( KMdsKeywordComment, "//" ); +_LIT8( KMdsKeywordNamespace, "namespace" ); +_LIT8( KMdsKeywordObjectDef, "object" ); +_LIT8( KMdsKeywordPropertyDef, "property" ); +_LIT8( KMdsKeywordRelationDef, "relationdef" ); +_LIT8( KMdsKeywordEventDef, "eventdef" ); + +_LIT8( KMdsKeywordVersion, "version" ); + +_LIT8( KMdsKeywordObject, "object" ); +_LIT8( KMdsKeywordProperty, "property" ); +_LIT8( KMdsKeywordFreeText, "freetext" ); +_LIT8( KMdsKeywordRelation, "relation" ); +_LIT8( KMdsKeywordEvent, "event" ); + +_LIT8( KExportMetadataNewLine, "\r\n" ); +_LIT8( KExportMetadataSpace, " " ); +_LIT8( KExportMetadataQuotationMark, "\"" ); +_LIT8( KExportMetadataTimeFormat, "%04d%02d%02d%02d%02d%02d" ); + + +_LIT( KMdsKeywordMinValue, "min" ); +_LIT( KMdsKeywordMaxValue, "max" ); +_LIT( KMdsKeywordDefValue, "def" ); + +/** + * NewLC + */ +CMdsImportExport* CMdsImportExport::NewLC() + { + CMdsImportExport* ret = new(ELeave) CMdsImportExport(); + CleanupStack::PushL( ret ); + ret->ConstructL(); + return ret; + } + +/** + * NewL + */ +CMdsImportExport* CMdsImportExport::NewL() + { + CMdsImportExport* ret = CMdsImportExport::NewLC(); + CleanupStack::Pop( ret ); + return ret; + } + +/** + * Constructor + */ +CMdsImportExport::CMdsImportExport() : iLastDriveNumber ( -1 ) + { + } + +/** + * Default destructor + */ +CMdsImportExport::~CMdsImportExport() + { + delete iConverter; + + iLog.CloseLog(); + iLog.Close(); + iFs.Close(); + + delete iBuffer; + + delete iSchema; + } + +/** + * ConstructL + */ +void CMdsImportExport::ConstructL() + { + iSchema = CMdsSchema::NewL(); + iConverter = CCnvCharacterSetConverter::NewL(); + + User::LeaveIfError( iFs.Connect() ); + iConverter->PrepareToConvertToOrFromL( KCharacterSetIdentifierUtf8, iFs ); + + User::LeaveIfError( iLog.Connect( ) ); + iLog.CreateLog( KMdsErrorLogDirectory, KMdsErrorLogFilename, EFileLoggingModeOverwrite ); + iLog.SetDateAndTime(EFalse, ETrue); + + iBuffer = NULL; + iLastObjectDef = NULL; + } + +void CMdsImportExport::ImportSchemaFromFileL( const TDesC& aFileName, + CMdsSchema& aSchema, TUint32 aVendorId ) + { + iDefaultSchema = &aSchema; + iVendorId = aVendorId; + + if ( !iDefaultSchema->iBaseObject ) + { + // If the default schema doesn't already have a base object, add one to iSchema together + // with default namespace. + iSchema->AddDefaultObjectL(); + iDefaultSchema->iBaseObject = iSchema->iBaseObject; + iSchema->AddDefaultNamespaceL(); + } + else + { + iSchema->iBaseObject = iDefaultSchema->iBaseObject; + } + + iReadStream.PushL(); + // Read the schema file. + TInt fileOpenStatus = iReadStream.Open( iFs, aFileName, EFileStreamText ); + if (fileOpenStatus != KErrNone) + { + iSchema->iBaseObject = NULL; + iDefaultSchema = NULL; + _LIT( KError, "Failed to open schema file" ); + LogError( KError ); + User::Leave( fileOpenStatus ); + } + iFileName.Copy( aFileName ); + + iLineNumber = 0; + iLastObjectDef = NULL; + if ( aFileName == KSchemaImportFile || aFileName == KSchemaRomImportFile ) + { + iVersionFlags = EVersionNone; + } + else + { + iVersionFlags = EVersionAlreadyRead; + } + + // start reading lines from the schema file + while( ETrue ) + { + TRAPD( e, iReadStream.ReadL( iLine, KMdsLineFeed ) ); + if ( e == KErrEof ) break; // succesful exit + else if ( e != KErrNone ) + { + iSchema->iBaseObject = NULL; + iDefaultSchema = NULL; + _LIT( KError, "Failed to read line from schema file" ); + LogError( KError ); + User::Leave( e ); + } + + ++iLineNumber; + if ( iLine.Length() > 0 ) + { + // parse the line + TLex8 parser( iLine ); + TRAP( e, ImportSchemaLineL( parser ) ); + if ( e != KErrNone ) + { + iSchema->iBaseObject = NULL; + iDefaultSchema = NULL; + _LIT( KError, "Schema corrupted" ); + LogError( KError ); + User::Leave( e ); + } + } + } + + CleanupStack::PopAndDestroy( &iReadStream ); // Closes stream. + + TRAPD( err, aSchema.MergeNamespacesL( *iSchema ) ); + + iSchema->iBaseObject = NULL; + iDefaultSchema = NULL; + iVendorId = 0; + + if ( err != KErrNone ) + { + User::Leave( err ); + } + } + +/** + * ImportL imports a single line of data + */ +void CMdsImportExport::ImportSchemaLineL( TLex8& aParser ) + { + TPtrC8 token = aParser.NextToken(); + + // valid keywords in beginning of line + if ( token.Length() == 0 || token.Left(2) == KMdsKeywordComment ) + { + // ignore + return; + } + else if ( token == KMdsKeywordVersion ) + { + ImportSchemaVersionL( aParser ); + } + else if ( !(iVersionFlags & EVersionAlreadyRead ) ) + { + User::Leave( KErrCorrupt ); + } + else if ( token == KMdsKeywordNamespace ) + { + ImportSchemaNamespaceL( aParser ); + return; + } + else if ( token == KMdsKeywordObjectDef ) + { + ImportSchemaObjectDefL( aParser ); + } + else if(token == KMdsKeywordPropertyDef ) + { + ImportSchemaPropertyDefL( aParser ); + } + else if ( token == KMdsKeywordRelationDef ) + { + ImportSchemaRelationDefL( aParser ); + } + else if ( token == KMdsKeywordEventDef ) + { + ImportSchemaEventDefL( aParser ); + } + else + { + _LIT( KError, "Keyword not recognized" ); + LogError( KError ); + User::Leave( KErrCorrupt ); + } + TPtrC8 tokenLast = aParser.NextToken(); + if ( tokenLast.Length() != 0 && tokenLast.Left(2) != KMdsKeywordComment ) + { + _LIT( KMdsUnknownToken, "Undefined schema item" ); + LogError( KMdsUnknownToken ); + User::Leave( KErrCorrupt ); + } + } + +/** + * Schema import checklist: + * 1. Are all the namespaces new? If not, discard any duplicates + * 2. Do all the (object/event/relation) defs about to be imported actually + * belong to a proper namespace (which is also not read-only)? If not, discard + */ +// ------------------------------------------------ +// ImportSchemaNamespaceL +// ------------------------------------------------ +// +void CMdsImportExport::ImportSchemaNamespaceL( TLex8& aParser ) + { + // namespace + TBuf16 name; + User::LeaveIfError( ImportText( name, aParser ) ); + + TInt ro = 0; + TBool readOnly = EFalse; + User::LeaveIfError( ImportNum( ro, aParser ) ); + readOnly = ro ? ETrue : EFalse; + + // Check out if the namespace already exists + if ( iSchema->GetNamespace( name ) ) + { + return; + } + + // in case there is namespace in old schema + CMdsNamespaceDef* actualNamespace = iDefaultSchema->GetNamespace( name ); + if ( actualNamespace ) + { + iSchema->NamespaceAddL( actualNamespace->GetName(), + actualNamespace->GetReadOnly(), actualNamespace->GetVendorId(), + actualNamespace->GetId() ); + return; + } + + // Ok, the namespace is new + iSchema->NamespaceAddL( name, readOnly, iVendorId ); + } + +// ------------------------------------------------ +// ImportSchemaObjectDefL +// ------------------------------------------------ +// +void CMdsImportExport::ImportSchemaObjectDefL( TLex8& aParser ) + { + // First read the name of the namespace. + TBuf16 name; + User::LeaveIfError( ImportText( name, aParser ) ); + + CMdsNamespaceDef* actualNamespace = iSchema->GetNamespace( name ); + if ( !actualNamespace ) + { + actualNamespace = iDefaultSchema->GetNamespace( name ); + if ( !actualNamespace ) + { + _LIT( KMdsNamespaceNotFound, "Namespace not found !!!" ); + LogError( KMdsNamespaceNotFound ); + User::Leave( KErrAccessDenied ); + } + CMdsNamespaceDef* nmsp = iSchema->NamespaceAddL( + actualNamespace->GetName(), actualNamespace->GetReadOnly(), + actualNamespace->GetVendorId() ); + if ( !actualNamespace->GetFirstRead() ) + { + nmsp->UnsetFirstRead(); + } + actualNamespace = nmsp; + } + + if ( actualNamespace->GetReadOnly() && !actualNamespace->GetFirstRead() ) + { + iLastObjectDef = NULL; + _LIT( KError, "Namespace not allowed" ); + LogError( KError ); + User::Leave( KErrAccessDenied ); + } + + // Next read the name of the object. + TBuf16 nameObject; + User::LeaveIfError( ImportText( nameObject, aParser ) ); + if ( nameObject == MdeConstants::Object::KBaseObject ) + { + _LIT( KError, "Cannot redefine Object" ); + LogError( KError ); + User::Leave( KErrArgument ); + } + + // Next read the name of the parent object. + User::LeaveIfError( ImportText( name, aParser ) ); + + // Add new object definition to the DB. + TRAPD( err, iLastObjectDef = actualNamespace->AddObjectDefL( nameObject, name, iDefaultSchema ) ); + + if ( err != KErrNone && err != KErrAlreadyExists ) + { + User::Leave( err ); + } + + // Finally read object flags (currently only two values: 0/1). + TInt flags; + CMdsObjectDef::TObjectDefFlags objFlags = CMdsObjectDef::EObjectDefFlagsNone; + User::LeaveIfError( ImportNum(flags, aParser) ); + switch( flags ) + { + case CMdsObjectDef::EObjectDefFlagsNone: + objFlags = CMdsObjectDef::EObjectDefFlagsNone; + break; + + case CMdsObjectDef::EObjectDefFlagsContext: + objFlags = CMdsObjectDef::EObjectDefFlagsContext; + break; + + default: + _LIT( KUnsupportedFlag, "Unsupported flag" ); + LogError( KUnsupportedFlag ); + User::Leave( KErrCorrupt ); + } + iLastObjectDef->SetFlags( objFlags ); + } + +// ------------------------------------------------ +// ImportSchemaPropertyDefL +// ------------------------------------------------ +// +void CMdsImportExport::ImportSchemaPropertyDefL( TLex8& aParser ) + { + // property + _LIT( KMinMaxWrongValue, "Min value is bigger then max" ); + _LIT( KWrongValue, "Min or max value is incorrect" ); + _LIT( KTextWrongValue, "Min or max text value is incorrect" ); + + // Property definitions always come immediately after object definitions in a schema file. + // If there is no object definition before property definitions, it's an error. + if ( !iLastObjectDef ) + { + _LIT( KNoLastObject, "Try to add to no existing object" ); + LogError( KNoLastObject ); + User::Leave( KErrNotFound ); + } + + // Read property name. + TBuf16 name; + User::LeaveIfError( ImportText( name, aParser ) ); + if ( iLastObjectDef->GetProperty( name ) ) + { + _LIT( KError, "Property already exists" ); + LogError( KError ); + User::Leave( KErrArgument ); + } + + // Read read-only and mandatory flags. + TBool readOnly, mandatory; + User::LeaveIfError( ImportNum( readOnly, aParser ) ); + User::LeaveIfError( ImportNum( mandatory, aParser ) ); + + // Read property type. + TPropertyType type; + TInt32 readType; + User::LeaveIfError( ImportNum( readType, aParser ) ); + type = static_cast(readType); + + // Depending on the property type read the next two parameters with the correct data type. + TInt error = KErrNone; + switch( type ) + { + case EPropertyBool: + { + TInt32 minVal32, + maxVal32; + error = SetMinMaxDefValueL( CheckForConstant(aParser), minVal32, 0, 1, 0 ); + if ( error < KErrNone ) + { + User::LeaveIfError( ImportNum( minVal32, aParser ) ); + } + error = SetMinMaxDefValueL( CheckForConstant(aParser), maxVal32, 0, 1, 1 ); + if ( error < KErrNone ) + { + User::LeaveIfError( ImportNum( maxVal32, aParser ) ); + } + + CheckNoMoreNumericParametersL( aParser ); + + // boolean cannot have different values + minVal32 = 0; + maxVal32 = 1; + // Add this property to the previously defined object. + iLastObjectDef->AddPropertyL( name, type, minVal32, maxVal32, readOnly, mandatory, EFalse ); + break; + } + case EPropertyInt8: + case EPropertyUint8: + case EPropertyInt16: + case EPropertyUint16: + case EPropertyInt32: + { + TInt32 minVal32, + maxVal32; + const TInt32 KMinVal32 = type == EPropertyInt8 ? KMinTInt8 : + type == EPropertyInt16 ? KMinTInt16 : + type == EPropertyInt32 ? KMinTInt32 : 0; + const TInt32 KMaxVal32 = type == EPropertyInt8 ? KMaxTInt8 : + type == EPropertyUint8 ? KMaxTUint8 : + type == EPropertyInt16 ? KMaxTInt16 : + type == EPropertyUint16 ? KMaxTUint16 : KMaxTInt32; + error = SetMinMaxDefValueL( CheckForConstant(aParser), + minVal32, KMinVal32, KMaxVal32, 0 ); + if ( error < KErrNone ) + { + User::LeaveIfError( ImportNum( minVal32, aParser ) ); + } + error = SetMinMaxDefValueL( CheckForConstant(aParser), + maxVal32, KMinVal32, KMaxVal32, KMaxVal32 ); + if ( error < KErrNone ) + { + User::LeaveIfError( ImportNum( maxVal32, aParser ) ); + } + if ( minVal32 > maxVal32 ) + { + LogError( KMinMaxWrongValue ); + User::Leave( KErrCorrupt ); + } + if ( ( type == EPropertyInt8 && ( minVal32 < KMinTInt8 || maxVal32 > KMaxTInt8 ) ) || + ( type == EPropertyUint8 && ( minVal32 < 0 || maxVal32 > KMaxTUint8 ) ) || + ( type == EPropertyInt16 && ( minVal32 < KMinTInt16 || maxVal32 > KMaxTInt16 ) ) || + ( type == EPropertyUint16 && ( minVal32 < 0 || maxVal32 > KMaxTUint16 ) ) ) + { + LogError( KWrongValue ); + User::Leave( KErrCorrupt ); + } + + CheckNoMoreNumericParametersL( aParser ); + // Add this property to the previously defined object. + iLastObjectDef->AddPropertyL( name, type, minVal32, maxVal32, readOnly, mandatory, EFalse ); + break; + } + case EPropertyText: + { + TInt32 minVal32, + maxVal32; + error = SetMinMaxDefValueL( CheckForConstant(aParser), + minVal32, 1, KSerializedDesMaxLength, 1 ); + if ( error < KErrNone ) + { + User::LeaveIfError( ImportNum( minVal32, aParser ) ); + } + error = SetMinMaxDefValueL( CheckForConstant(aParser), + maxVal32, 1, KSerializedDesMaxLength, 256 ); + if ( error < KErrNone ) + { + User::LeaveIfError( ImportNum( maxVal32, aParser ) ); + } + if ( minVal32 > maxVal32 ) + { + LogError( KMinMaxWrongValue ); + User::Leave( KErrCorrupt ); + } + if ( minVal32 < 1 || minVal32 > KSerializedDesMaxLength || + maxVal32 < 1 || maxVal32 > KSerializedDesMaxLength ) + { + LogError( KTextWrongValue ); + User::Leave( KErrCorrupt ); + } + + // Text properties may have an extra flag: index flag. + TBool indexed( EFalse ); + ImportNum( indexed, aParser ); + // Add this property to the previously defined object. + iLastObjectDef->AddPropertyL( name, type, minVal32, maxVal32, readOnly, mandatory, indexed ); + break; + } + case EPropertyUint32: + { + TUint32 minVal32, + maxVal32; + error = SetMinMaxDefValueL( CheckForConstant(aParser), + minVal32, 0, KMaxTUint32, 0 ); + if ( error < KErrNone ) + { + User::LeaveIfError( ImportUInt32( minVal32, aParser ) ); + } + error = SetMinMaxDefValueL( CheckForConstant(aParser), + maxVal32, 0, KMaxTUint32, KMaxTUint32 ); + if ( error < KErrNone ) + { + User::LeaveIfError( ImportUInt32( maxVal32, aParser ) ); + } + if ( minVal32 > maxVal32 ) + { + LogError( KMinMaxWrongValue ); + User::Leave( KErrCorrupt ); + } + + CheckNoMoreNumericParametersL( aParser ); + // Add this property to the previously defined object. + iLastObjectDef->AddPropertyL( name, type, minVal32, maxVal32, readOnly, mandatory, EFalse ); + break; + } + case EPropertyInt64: + { + TInt64 minVal64, maxVal64; + error = SetMinMaxDefValueL( CheckForConstant(aParser), + minVal64, KMinTInt64, KMaxTInt64, 0 ); + if ( error < KErrNone ) + { + User::LeaveIfError( ImportInt64( minVal64, aParser ) ); + } + error = SetMinMaxDefValueL( CheckForConstant(aParser), + maxVal64, KMinTInt64, KMaxTInt64, KMaxTInt64 ); + if ( error < KErrNone ) + { + User::LeaveIfError( ImportInt64( maxVal64, aParser ) ); + } + if ( minVal64 > maxVal64 ) + { + LogError( KMinMaxWrongValue ); + User::Leave( KErrCorrupt ); + } + + CheckNoMoreNumericParametersL( aParser ); + // Add this property to the previously defined object. + iLastObjectDef->AddPropertyL( name, type, minVal64, maxVal64, readOnly, mandatory, EFalse ); + break; + } + case EPropertyTime: + { + TTime minTime, maxTime; + error = SetMinMaxDefValueL( CheckForConstant(aParser), + minTime, 0, KMaxTInt64, 0 ); + if ( error < KErrNone ) + { + User::LeaveIfError( ImportTime( minTime, aParser ) ); + } + error = SetMinMaxDefValueL( CheckForConstant(aParser), + maxTime, 0, KMaxTInt64, KMaxTInt64 ); + if ( error < KErrNone ) + { + User::LeaveIfError( ImportTime( maxTime, aParser ) ); + } + if ( minTime > maxTime ) + { + LogError( KMinMaxWrongValue ); + User::Leave( KErrCorrupt ); + } + + CheckNoMoreNumericParametersL( aParser ); + // Add this property to the previously defined object. + iLastObjectDef->AddPropertyL( name, type, minTime.Int64(), maxTime.Int64(), readOnly, + mandatory, EFalse ); + break; + } + case EPropertyReal32: + { + TReal32 minReal, maxReal; + error = SetMinMaxDefValueL( CheckForConstant(aParser), + minReal, -KMaxTReal32, KMaxTReal32, 0 ); + if ( error < KErrNone ) + { + User::LeaveIfError( ImportNum( minReal, aParser ) ); + } + error = SetMinMaxDefValueL( CheckForConstant(aParser), + maxReal, -KMaxTReal32, KMaxTReal32, KMaxTReal32 ); + if ( error < KErrNone ) + { + User::LeaveIfError( ImportNum( maxReal, aParser ) ); + } + if ( minReal > maxReal ) + { + LogError( KMinMaxWrongValue ); + User::Leave( KErrCorrupt ); + } + + CheckNoMoreNumericParametersL( aParser ); + // Add this property to the previously defined object. + iLastObjectDef->AddPropertyL( name, type, minReal, maxReal, readOnly, mandatory, EFalse ); + break; + } + case EPropertyReal64: + { + const TReal64 KMDSMaxTReal64( 1.79769313486200E+308 ); + TReal64 minReal, maxReal; + error = SetMinMaxDefValueL( CheckForConstant(aParser), + minReal, -KMDSMaxTReal64, KMDSMaxTReal64, 0 ); + if ( error < KErrNone ) + { + User::LeaveIfError( ImportNum( minReal, aParser ) ); + } + error = SetMinMaxDefValueL( CheckForConstant(aParser), + maxReal, -KMDSMaxTReal64, KMDSMaxTReal64, KMDSMaxTReal64 ); + if ( error < KErrNone ) + { + User::LeaveIfError( ImportNum( maxReal, aParser ) ); + } + if ( minReal > maxReal ) + { + LogError( KMinMaxWrongValue ); + User::Leave( KErrCorrupt ); + } + + CheckNoMoreNumericParametersL( aParser ); + // Add this property to the previously defined object. + iLastObjectDef->AddPropertyL( name, type, minReal, maxReal, readOnly, mandatory, EFalse ); + break; + } + default: + User::Leave( KErrNotFound ); + } + } + +// ------------------------------------------------ +// CheckNoIndexFlagL +// ------------------------------------------------ +// +void CMdsImportExport::CheckNoMoreNumericParametersL( TLex8& aParser ) + { + // This function is used to check that indexing flag is not set for other than + // text properties. + TBool parameterFound( EFalse ); + TInt err = ImportNum( parameterFound, aParser ); + if ( err == KErrNone ) + { + // Index boolean not supported for other property types than text. + User::Leave( KErrNotSupported ); + } + } + +// ------------------------------------------------ +// ImportSchemaRelationDefL +// ------------------------------------------------ +// +void CMdsImportExport::ImportSchemaRelationDefL( TLex8& aParser ) + { + // relationdef + TBuf16 name; + // read namespace + User::LeaveIfError( ImportText( name, aParser ) ); + + CMdsNamespaceDef* actualNamespace = iSchema->GetNamespace( name ); + if ( !actualNamespace ) + { + _LIT( KMdsNamespaceNotFound, "Namespace not found !!!" ); + LogError( KMdsNamespaceNotFound ); + User::Leave( KErrAccessDenied ); + } + + if( actualNamespace->GetReadOnly() && !actualNamespace->GetFirstRead() ) + { + _LIT( KError, "Namespace not allowed" ); + LogError( KError ); + User::Leave( KErrAccessDenied ); + } + + // read name + User::LeaveIfError( ImportText( name, aParser ) ); + + actualNamespace->AddRelationDefL( name ); + } + +// ------------------------------------------------ +// ImportSchemaEventDefL +// ------------------------------------------------ +// +void CMdsImportExport::ImportSchemaEventDefL( TLex8& aParser ) + { + // eventdef + TBuf16 name; + User::LeaveIfError( ImportText( name, aParser ) ); + + CMdsNamespaceDef* actualNamespace = iSchema->GetNamespace( name ); + if ( !actualNamespace ) + { + _LIT( KMdsNamespaceNotFound, "Namespace not found !!!" ); + LogError( KMdsNamespaceNotFound ); + User::Leave( KErrAccessDenied ); + } + + if ( actualNamespace->GetReadOnly() && !actualNamespace->GetFirstRead() ) + { + _LIT( KError, "Namespace not allowed" ); + LogError( KError ); + User::Leave( KErrAccessDenied ); + } + + User::LeaveIfError( ImportText( name, aParser ) ); + + TInt32 priority=0; + User::LeaveIfError( ImportNum( priority, aParser ) ); + + actualNamespace->AddEventDefL( name, priority ); + } + +void CMdsImportExport::ImportSchemaVersionL( TLex8& aParser ) + { + if ( iVersionFlags & EVersionAlreadyRead ) + { + _LIT( KError, "Schema version redefined" ); + LogError( KError ); + User::Leave( KErrCorrupt ); + } + TBuf16 version; + User::LeaveIfError( ImportText( version, aParser ) ); + + // convert version to two numbers + TInt32 majorVersion, minorVersion; + TLex16 parser( version ); + User::LeaveIfError( parser.BoundedVal( majorVersion, KMaxTInt ) ); + parser.Get(); + User::LeaveIfError( parser.BoundedVal( minorVersion, KMaxTInt ) ); + + if ( KSchemaFileMajorVersion != majorVersion ) + { + _LIT( KError, "Schema version mismatch" ); + LogError( KError ); + User::Leave( KErrCorrupt ); + } + + MMdsPreferences::InsertL( KMdsSchemaVersionName, MMdsPreferences::EPreferenceBothSet, + majorVersion, minorVersion ); + + iVersionFlags |= EVersionAlreadyRead; + } + +void CMdsImportExport::ImportNamespaceFromDBL() + { + _LIT( MdsQueryGetNamespaceDefs, "SELECT NamespaceDefID,ReadOnly,VendorId,Name FROM NamespaceDef;" ); + TDefId namespaceDefId = KNoDefId; + TInt32 vendorId = 0; + TInt32 namespaceReadOnly = 0; + TPtrC namespaceName; + + CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); + + // importing namespaces + RRowData emptyData; + CleanupClosePushL( emptyData ); + RRowData getData; + CleanupClosePushL( getData ); + getData.AppendL( TColumn( namespaceDefId ) ); + getData.AppendL( TColumn( namespaceReadOnly ) ); + getData.AppendL( TColumn( vendorId ) ); + getData.AppendL( TColumn( EColumnHBuf16 ) ); + RMdsStatement query; + CleanupClosePushL( query ); + connection.ExecuteQueryL( MdsQueryGetNamespaceDefs, query, emptyData ); + + // read query results and add namespaces to the schema + while( connection.NextRowL( query, getData ) ) + { + getData.Column( 0 ).Get( namespaceDefId ); + getData.Column( 1 ).Get( namespaceReadOnly ); + getData.Column( 2 ).Get( vendorId ); + getData.Column( 3 ).Get( namespaceName ); + CMdsNamespaceDef* nmsp = iSchema->NamespaceAddL( namespaceName, + namespaceReadOnly ? ETrue : EFalse, vendorId, namespaceDefId ); + if ( !nmsp ) + { + User::Leave( KErrGeneral ); + } + nmsp->UnsetFirstRead(); + getData.Column( 3 ).Free(); + } + CleanupStack::PopAndDestroy( 3, &emptyData ); // query, getData, emptyData + } + +TBool CMdsImportExport::ImportCheckVersionInfoL() + { + TInt32 majorVersion = 0; + TInt64 minorVersion = 0; + + // DB version + MMdsPreferences::GetL( KMdsDBVersionName, MMdsPreferences::EPreferenceBothGet, + majorVersion, &minorVersion ); + if ( majorVersion != KMdSServMajorVersionNumber && (TInt)minorVersion != KMdSServMinorVersionNumber ) + { + return EFalse; + } + + // schema version + MMdsPreferences::GetL( KMdsSchemaVersionName, MMdsPreferences::EPreferenceBothGet, + majorVersion, &minorVersion ); + if ( majorVersion == KSchemaFileMajorVersion ) + { + return ETrue; + } + + return EFalse; + } + +void CMdsImportExport::ImportSchemaFromDBL( CMdsSchema& aSchema ) + { + // clear iSchema (we read everything from DB) + if ( !aSchema.iBaseObject ) + { + iSchema->AddDefaultObjectL(); + iSchema->iBaseObject->SetStoredEveryInDB(); + aSchema.iBaseObject = iSchema->iBaseObject; + } + else + { + iSchema->iBaseObject = aSchema.iBaseObject; + } + iSchema->Reset(); + + if ( !ImportCheckVersionInfoL() ) + { + iSchema->iBaseObject = NULL; + User::Leave( KErrCorrupt ); + } + + TRAPD( err, ImportNamespaceFromDBL() ); + if ( err != KErrNone ) + { + iSchema->iBaseObject = NULL; + User::Leave( err ); + } + + const TInt count = iSchema->iNamespaceDefs.Count(); + + for ( TInt i = 0; i < count; ++i ) + { + CMdsNamespaceDef* namespaceDef = iSchema->iNamespaceDefs[i]; + TRAP( err, namespaceDef->ImportFromDBL() ); + if ( err != KErrNone ) + { + iSchema->iBaseObject = NULL; + User::Leave( err ); + } + } + + TRAP( err, aSchema.MergeNamespacesL( *iSchema ) ); + iSchema->iBaseObject = NULL; + if ( err != KErrNone ) + { + User::Leave( err ); + } + } + + +TBool CMdsImportExport::ReadMetadataFileLineL() + { + if ( iLastLineProcessed ) + { + TRAPD( e, iReadStream.ReadL( iLine, KMdsLineFeed ) ); + if ( e == KErrEof ) + { + return EFalse; // succesful exit + } + else if ( e != KErrNone ) + { + iDefaultSchema = NULL; + User::Leave( e ); + } + iLastLineProcessed = EFalse; + } + ++iLineNumber; + return ETrue; + } + +TInt CMdsImportExport::ImportMetadataL( CMdSSqlObjectManipulate& aManipulate, + CMdsSchema& aSchemaNew, const TDesC16& aFileName ) + { + iReadStream.PushL(); + User::LeaveIfError( iReadStream.Open( iFs, aFileName, EFileStreamText ) ); + iFileName.Copy( aFileName ); + + if ( !iBuffer ) + { + iBuffer = CMdCSerializationBuffer::NewL( 8192 ); // 8kB - should be enough + } + + iDefaultSchema = &aSchemaNew; + iLineNumber = 0; + iFailed = 0; + while( ReadMetadataFileLineL() ) + { + if ( iLine.Length() > 0 ) + { + // parse the line + TLex8 parser( iLine ); + TRAPD( e, ImportMetadataItemL( parser, aManipulate ) ); + if ( e != KErrNone ) + { + ++iFailed; + } + } + else + iLastLineProcessed = ETrue; + } + + iDefaultSchema = NULL; + CleanupStack::PopAndDestroy( &iReadStream ); // Closes stream. + return iFailed; + } + +void CMdsImportExport::ImportMetadataItemL( TLex8& aParser, CMdSSqlObjectManipulate& aManipulate ) + { + TPtrC8 token = aParser.NextToken(); + + // valid keywords in beginning of line + if ( token.Length() == 0 || token.Left(2) == KMdsKeywordComment ) + { + // ignore + iLastLineProcessed = ETrue; + return; + } + else if ( token == KMdsKeywordObject ) + { + TRAPD( err, ImportMetadataFileObjectL( aParser, aManipulate ) ); + if (err != KErrNone) + { + _LIT( KError, "Object error" ); + LogError( KError ); + User::Leave( err ); + } + } + else if ( token == KMdsKeywordRelation ) + { + TRAPD( err, ImportMetadataFileRelationL( aParser, aManipulate ) ); + if (err != KErrNone) + { + _LIT( KError, "Relation error" ); + LogError( KError ); + User::Leave( err ); + } + } + else if ( token == KMdsKeywordEvent ) + { + TRAPD( err, ImportMetadataFileEventL( aParser, aManipulate ) ); + if (err != KErrNone) + { + _LIT( KError, "Relation error" ); + LogError( KError ); + User::Leave( err ); + } + } + else + { + iLastLineProcessed = ETrue; + _LIT( KError, "Keyword not recognized" ); + LogError( KError ); + User::Leave( KErrCorrupt ); + } + TPtrC8 tokenLast = aParser.NextToken(); + if ( tokenLast.Length() != 0 && tokenLast.Left(2) != KMdsKeywordComment ) + { + _LIT( KMdsUnknownToken, "Undefined metadata file item" ); + LogError( KMdsUnknownToken ); + User::Leave( KErrCorrupt ); + } + } + +void CMdsImportExport::AddObjectToDBL( CMdSSqlObjectManipulate& aManipulate, CMdsNamespaceDef* aNamespaceDef ) + { + iLastObjectDef = NULL; + iBuffer->PositionL( KNoOffset ); + TItemId id = KNoId; + aManipulate.SetNamespace( aNamespaceDef ); + RMdsStatement baseObjStmt; + CleanupClosePushL(baseObjStmt); + RMdsStatement objStmt; + CleanupClosePushL(objStmt); + + TRAPD( err, id = aManipulate.AddObjectL( MMdSDbConnectionPool::GetDefaultDBL(), *iBuffer, baseObjStmt, objStmt ) ); + + CleanupStack::PopAndDestroy(&objStmt); + CleanupStack::PopAndDestroy(&baseObjStmt); + + aManipulate.SetNamespace( NULL ); + if ( err != KErrNone || id == 0 ) + { + User::Leave( err ); + } + } + +void CMdsImportExport::ImportMetadataFileObjectL( TLex8& aParser, CMdSSqlObjectManipulate& aManipulate ) + { + TInt error = KErrNone; + + if ( iLastObjectDef ) + { + User::Leave( KErrCorrupt ); + } + iLastLineProcessed = ETrue; + + TMdCObject object; + object.iId = KNoId; + object.iFlags = EMdEObjectFlagModOpen; + object.iUsageCount = 0; + object.iGuidHigh = 0; + object.iGuidLow = 0; + object.iFreeTexts.iPtr.iCount = 0; + object.iFreeTexts.iPtr.iOffset = KNoOffset; + + TMdCOffset freespaceOffset = sizeof(TMdCObject); + + TBuf16 textValue; + + // namespace + User::LeaveIfError( ImportText( textValue, aParser ) ); + + CMdsNamespaceDef* namespaceDef = iDefaultSchema->GetNamespace( textValue ); + if ( !namespaceDef ) + { + User::Leave( KErrNotFound ); + } + + // read object variables + // objectDef name + User::LeaveIfError( ImportText( textValue, aParser ) ); + + iLastObjectDef = namespaceDef->GetObjectDef( textValue ); + if ( !iLastObjectDef ) + { + User::Leave( KErrNotFound ); + } + object.iDefId = iLastObjectDef->GetId(); + + // object uri + User::LeaveIfError( ImportText( textValue, aParser ) ); + object.iUri.iPtr.iCount = textValue.Length(); + object.iUri.iPtr.iOffset = freespaceOffset; + iBuffer->PositionL( freespaceOffset ); + freespaceOffset = iBuffer->InsertL( textValue ); + + // Object must not be context object and + // the length of the URI must be atleast 3 (X:\) + if ( !(iLastObjectDef->GetFlags() & CMdsObjectDef::EObjectDefFlagsContext) && + textValue.Length() >= 3 ) + { + // possible drive letter + TChar driveLetter( textValue[0] ); + driveLetter.UpperCase(); + + // possible colon and backslash + _LIT( KColonBackslashMatch, ":\\" ); + TPtrC beginUri = textValue.Mid( 1, KColonBackslashMatch.iTypeLength ); + TBool validUri( ETrue ); + + // URI must begin with "X:\" + if( 'A' <= driveLetter && driveLetter <= 'Z' && + beginUri.Compare( KColonBackslashMatch ) == 0 ) + { + // check if uri exists + RFileReadStream tmpFile; + TInt err = KErrNone; + err = tmpFile.Open( iFs, textValue, EFileRead | EFileShareAny ); + tmpFile.Close(); + if ( err != KErrNone ) + { + _LIT( KError, "uri is not real" ); + validUri = EFalse; + LogError( KError ); + error = err; + } + } + else + { + validUri = EFalse; + } + + if( validUri ) + { + User::LeaveIfError( ImportMediaId( object.iMediaId, aParser, driveLetter ) ); + } + else + { + User::LeaveIfError( ImportUInt32( object.iMediaId, aParser ) ); + } + } + else + { + User::LeaveIfError( ImportUInt32( object.iMediaId, aParser ) ); + } + + const TUint32 allPropCount = iLastObjectDef->GetAllPropertiesCount(); + object.iProperties.iPtr.iCount = allPropCount; + object.iProperties.iPtr.iOffset = freespaceOffset; + + freespaceOffset += allPropCount * sizeof(TMdCProperty); + + // set property offset + CDesC16ArrayFlat* freeTextBuffer = new(ELeave) CDesC16ArrayFlat(8); + CleanupStack::PushL( freeTextBuffer ); + + TUint32 propertyCount = 0; + while ( ReadMetadataFileLineL() ) + { + TLex8 parser( iLine ); + TPtrC8 token = parser.NextToken(); + + if ( iLine.Length() == 0 || token.Length() == 0 || token.Left(2) == KMdsKeywordComment ) + { + // ignore line + iLastLineProcessed = ETrue; + } + // now if exists there should be one or more properties + else if(token == KMdsKeywordProperty ) + { + if ( object.iFreeTexts.iPtr.iOffset != KNoOffset || propertyCount >= allPropCount ) + { + _LIT( KError, "Property after freetext" ); + LogError( KError ); + error = KErrCorrupt; + } + if (error != KErrNone) + { + // just fetch rest of object lines + iLastLineProcessed = ETrue; + } + else + { + iBuffer->PositionL( object.iProperties.iPtr.iOffset + + propertyCount * sizeof(TMdCProperty) ); + TRAP( error, freespaceOffset = ImportMetadataFilePropertyL( + parser, freespaceOffset ) ); + if (error != KErrNone) + { + _LIT( KError, "Property error" ); + LogError( KError ); + } + ++propertyCount; + } + } + // and after those there should be freetext + else if ( token == KMdsKeywordFreeText ) + { + if (error != KErrNone) + { + // just fetch rest of object lines + iLastLineProcessed = ETrue; + } + else + { + if ( object.iFreeTexts.iPtr.iOffset == KNoOffset) + { + object.iFreeTexts.iPtr.iOffset = freespaceOffset; + } + else + { + TRAP( error, ImportMetadataFileFreeTextL( parser, *freeTextBuffer ) ); + if (error != KErrNone) + { + _LIT( KError, "Freetext error" ); + LogError( KError ); + } + } + } + } + else + { + if ( token == KMdsKeywordObject || token == KMdsKeywordRelation || token == KMdsKeywordEvent ) + { + break; + } + iLastLineProcessed = ETrue; + } + } + + if ( error != KErrNone ) + { + iLastObjectDef = NULL; + User::Leave( error ); + } + + object.iProperties.iPtr.iCount = propertyCount; + + // add freetext + object.iFreeTexts.iPtr.iCount = freeTextBuffer->Count(); + if ( object.iFreeTexts.iPtr.iCount > 0 ) + { + // set flags + object.iFlags |= EMdEObjectFlagFreetexts | EMdEObjectFlagModFreeText; + + iBuffer->PositionL( object.iFreeTexts.iPtr.iOffset ); + for ( TInt32 i = 0; i < object.iFreeTexts.iPtr.iCount; ++i ) + { + TPtrC16 word = (*freeTextBuffer)[i]; + iBuffer->InsertL( word ); + } + } + else + { + object.iFreeTexts.iPtr.iOffset = KNoOffset; + } + + iBuffer->PositionL( KNoOffset ); + object.SerializeL( *iBuffer ); + + // add object to DB + AddObjectToDBL(aManipulate, namespaceDef); + + CleanupStack::PopAndDestroy( freeTextBuffer ); + } + +TMdCOffset CMdsImportExport::ImportMetadataFilePropertyL( TLex8& aParser, TMdCOffset aFreespaceOffset ) + { + if ( !iLastObjectDef ) + { + User::Leave( KErrCorrupt ); + } + iLastLineProcessed = ETrue; + TBuf16 textValue; + + // property name + User::LeaveIfError( ImportText( textValue, aParser ) ); + + _LIT( KGuidHigh, "GuidHigh" ); + _LIT( KGuidLow, "GuidLow" ); + + if( textValue == KGuidHigh || textValue == KGuidLow ) + { + User::Leave( KErrCorrupt ); + } + + CMdsPropertyDef* propertyDef = iLastObjectDef->GetProperty( textValue ); + if ( !propertyDef ) + { + User::Leave( KErrCorrupt ); + } + + TMdCProperty property; + property.iModFlags = EMdEPropertyModChange; + property.iPropertyDefId = propertyDef->GetId(); + + // find proper place to put property + const TMdCOffset propertyOffset = iBuffer->Position(); + + switch( propertyDef->GetType() ) + { + case EPropertyBool: + { + TInt32 intValue; + User::LeaveIfError( ImportNum( intValue, aParser ) ); + TBool value = intValue ? ETrue : EFalse; + property.iValue.iInt32 = value; + break; + } + case EPropertyInt8: + { + TInt32 intValue; + User::LeaveIfError( ImportNum( intValue, aParser ) ); + property.iValue.iInt32 = intValue; + break; + } + case EPropertyUint8: + { + TInt32 intValue; + User::LeaveIfError( ImportNum( intValue, aParser ) ); + property.iValue.iUint32 = intValue; + break; + } + case EPropertyInt16: + { + TInt32 intValue; + User::LeaveIfError( ImportNum( intValue, aParser ) ); + property.iValue.iInt32 = intValue; + break; + } + case EPropertyUint16: + { + TInt32 intValue; + User::LeaveIfError( ImportNum( intValue, aParser ) ); + property.iValue.iUint32 = intValue; + break; + } + case EPropertyInt32: + { + TInt32 value; + User::LeaveIfError( ImportNum( value, aParser ) ); + property.iValue.iInt32 = value; + break; + } + case EPropertyUint32: + { + TUint32 value; + User::LeaveIfError( ImportUInt32( value, aParser ) ); + property.iValue.iUint32 = value; + break; + } + case EPropertyInt64: + { + TInt64 value; + User::LeaveIfError( ImportInt64( value, aParser ) ); + property.iValue.iInt64 = value; + break; + } + case EPropertyTime: + { + TTime value; + User::LeaveIfError( ImportTime( value, aParser ) ); + property.iValue.iInt64 = value.Int64(); + break; + } + case EPropertyReal32: + { + TReal32 value; + User::LeaveIfError( ImportNum( value, aParser ) ); + property.iValue.iReal = value; + break; + } + case EPropertyReal64: + { + TReal64 value; + User::LeaveIfError( ImportNum( value, aParser ) ); + property.iValue.iReal = value; + break; + } + case EPropertyText: + { + TBuf16<256> value; + User::LeaveIfError( ImportText( value, aParser ) ); + property.iValue.iPtr.iCount = value.Length(); + if (property.iValue.iPtr.iCount > 0) + { + property.iValue.iPtr.iOffset = aFreespaceOffset; + iBuffer->PositionL( aFreespaceOffset ); + aFreespaceOffset = iBuffer->InsertL( value ); + } + else + { + User::Leave( KErrCorrupt ); + } + break; + } + default: + User::Leave( KErrNotFound ); + } + + iBuffer->PositionL( propertyOffset ); + property.SerializeL( *iBuffer ); + + return aFreespaceOffset; + } + +void CMdsImportExport::ImportMetadataFileFreeTextL( TLex8& aParser, CDesC16ArrayFlat& aFreeTextArray ) + { + if ( !iLastObjectDef ) + { + User::Leave( KErrCorrupt ); + } + iLastLineProcessed = ETrue; + + TBuf16<256> freeText; + while( ImportText( freeText, aParser ) == KErrNone ) + { + aFreeTextArray.AppendL( freeText ); + } + } + +void CMdsImportExport::ImportMetadataFileRelationL( TLex8& aParser, CMdSSqlObjectManipulate& aManipulate ) + { + _LIT( KImportRelationGetObjectId, "SELECT ObjectId FROM Object%u WHERE URI=? LIMIT 1;" ); + if(iLastObjectDef) + { + User::Leave( KErrCorrupt ); + } + iLastLineProcessed = ETrue; + + CMdsClauseBuffer* clauseBuffer = CMdsClauseBuffer::NewLC( KImportRelationGetObjectId.iTypeLength + 10 ); // one uint + + TBuf16 textValue; + + // namespace + User::LeaveIfError( ImportText( textValue, aParser ) ); + + CMdsNamespaceDef* namespaceDef = iDefaultSchema->GetNamespace( textValue ); + if ( !namespaceDef ) + { + User::Leave( KErrNotFound ); + } + + clauseBuffer->BufferL().Format( KImportRelationGetObjectId, namespaceDef->GetId() ); + + TMdCRelation relation; + relation.iId = KNoId; + relation.iGuidHigh = 0; + relation.iGuidLow = 0; + relation.iLastModifiedDate.UniversalTime(); + + // read relation variables + // relationDef name + User::LeaveIfError( ImportText( textValue, aParser ) ); + CMdsRelationDef* relationDef = namespaceDef->GetRelationDef( textValue ); + if ( !relationDef ) + { + User::Leave( KErrNotFound ); + } + relation.iDefId = relationDef->GetId(); + + RRowData dataRow; + CleanupClosePushL( dataRow ); + RMdsStatement query; + CleanupClosePushL( query ); + + CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); + + // left object name + User::LeaveIfError( ImportText( textValue, aParser ) ); + relation.iLeftObjectId = KNoId; + + dataRow.AppendL( TColumn( textValue ) ); + connection.ExecuteQueryL( clauseBuffer->ConstBufferL(), query, dataRow ); + dataRow.Free(); + dataRow.Column( 0 ).Set( relation.iLeftObjectId ); + if( connection.NextRowL( query, dataRow ) ) + { + dataRow.Column( 0 ).Get( relation.iLeftObjectId ); + } + if (relation.iLeftObjectId == KNoId) + { + User::Leave( KErrNotFound ); + } + + // right object name + User::LeaveIfError( ImportText( textValue, aParser ) ); + relation.iRightObjectId = KNoId; + dataRow.Column( 0 ).Set( textValue ); + + connection.ExecuteQueryL( clauseBuffer->ConstBufferL(), query, dataRow ); + dataRow.Free(); + dataRow.Column( 0 ).Set( relation.iLeftObjectId ); + if( connection.NextRowL( query, dataRow ) ) + { + dataRow.Column( 0 ).Get( relation.iRightObjectId ); + } + if (relation.iRightObjectId == KNoId) + { + User::Leave( KErrNotFound ); + } + + CleanupStack::PopAndDestroy( 2, &dataRow ); // query, dataRow + + relation.iParameter = 0; + User::LeaveIfError( ImportNum( relation.iParameter, aParser ) ); + + iBuffer->PositionL( KNoOffset ); + relation.SerializeL( *iBuffer ); + + TItemId id = KNoId; + iBuffer->PositionL( KNoOffset ); + aManipulate.SetNamespace( namespaceDef ); + TRAPD( err, id = aManipulate.AddRelationL( connection, *iBuffer ) ); + aManipulate.SetNamespace( NULL ); + if (err != KErrNone || id == KNoId) + { + User::Leave( err ); + } + CleanupStack::PopAndDestroy( clauseBuffer ); // clauseBuffer + } + +void CMdsImportExport::ImportMetadataFileEventL( TLex8& aParser, CMdSSqlObjectManipulate& aManipulate ) + { + _LIT( KImportEventGetObjectId, "SELECT ObjectId FROM Object%u WHERE URI=? LIMIT 1;" ); + if ( iLastObjectDef ) + { + User::Leave( KErrCorrupt ); + } + iLastLineProcessed = ETrue; + + CMdsClauseBuffer* clauseBuffer = CMdsClauseBuffer::NewLC( KImportEventGetObjectId.iTypeLength + 10 ); // one uint + + TBuf16 textValue; + + // namespace + User::LeaveIfError( ImportText( textValue, aParser ) ); + + CMdsNamespaceDef* namespaceDef = iDefaultSchema->GetNamespace( textValue ); + if ( !namespaceDef ) + { + User::Leave( KErrNotFound ); + } + + clauseBuffer->BufferL().Format( KImportEventGetObjectId, namespaceDef->GetId() ); + + TMdCEvent event; + event.iId = KNoId; + + // read event variables + // eventDef name + User::LeaveIfError( ImportText( textValue, aParser ) ); + CMdsEventDef* eventDef = namespaceDef->GetEventDef( textValue ); + if ( !eventDef ) + { + User::Leave( KErrNotFound ); + } + event.iDefId = eventDef->GetId(); + + RRowData dataRow; + CleanupClosePushL( dataRow ); + RMdsStatement query; + CleanupClosePushL( query ); + + CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); + + // object name + User::LeaveIfError( ImportText( textValue, aParser ) ); + event.iObjectId = KNoId; + + dataRow.AppendL( TColumn( textValue ) ); + connection.ExecuteQueryL( clauseBuffer->ConstBufferL(), query, dataRow ); + dataRow.Free(); + dataRow.Column( 0 ).Set( event.iObjectId ); + if ( connection.NextRowL( query, dataRow ) ) + { + dataRow.Column( 0 ).Get( event.iObjectId ); + } + if ( event.iObjectId == KNoId ) + { + User::Leave( KErrNotFound ); + } + + CleanupStack::PopAndDestroy( 2, &dataRow ); // query, dataRow + + TMdCOffset freespaceOffset = sizeof(TMdCEvent); + // source + User::LeaveIfError( ImportText( textValue, aParser ) ); + event.iSourceText.iPtr.iCount = textValue.Length(); + if (event.iSourceText.iPtr.iCount > 0) + { + event.iSourceText.iPtr.iOffset = freespaceOffset; + iBuffer->PositionL( freespaceOffset ); + freespaceOffset = iBuffer->InsertL( textValue ); + } + else + { + event.iSourceText.iPtr.iOffset = KNoOffset; + } + + // participant + User::LeaveIfError( ImportText( textValue, aParser ) ); + event.iParticipantText.iPtr.iCount = textValue.Length(); + if (event.iParticipantText.iPtr.iCount > 0) + { + event.iParticipantText.iPtr.iOffset = freespaceOffset; + iBuffer->PositionL( freespaceOffset ); + freespaceOffset = iBuffer->InsertL( textValue ); + } + else + { + event.iParticipantText.iPtr.iOffset = KNoOffset; + } + + // time + User::LeaveIfError( ImportTime( event.iTime, aParser ) ); + + iBuffer->PositionL( KNoOffset ); + event.SerializeL( *iBuffer ); + + TItemId id = KNoId; + iBuffer->PositionL( KNoOffset ); + aManipulate.SetNamespace( namespaceDef ); + TRAPD( err, id = aManipulate.AddEventL( connection, *iBuffer ) ); + aManipulate.SetNamespace( NULL ); + if (err != KErrNone || id == KNoId) + { + User::Leave( err ); + } + + CleanupStack::PopAndDestroy( clauseBuffer ); // clauseBuffer + } + +void CMdsImportExport::ExportMetadataL( CMdsSchema& aSchemaNew, const TDesC16& aFileName, + CMdCSerializationBuffer& aItems ) + { + iFs.PrivatePath( iFileName ); + if ( aFileName.Find(iFileName) != KErrNotFound ) + { + User::Leave( KErrAccessDenied ); + } + + CleanupClosePushL( iWriteStream ); + User::LeaveIfError( iWriteStream.Replace( iFs, aFileName, EFileShareExclusive | EFileStreamText | EFileWrite ) ); + + // reading import "filters" + aItems.PositionL( KNoOffset ); // start from the beginning of buffer + const TMdCItemIds& itemIds = TMdCItemIds::GetFromBufferL( aItems ); // read item ids from buffer + const CMdsNamespaceDef* namespaceDefRestrict = NULL; + if ( itemIds.iNamespaceDefId != KNoDefId ) + { + namespaceDefRestrict = aSchemaNew.GetNamespaceByIdL( itemIds.iNamespaceDefId ); + } + + RPointerArray objectDefToExport; + CleanupClosePushL( objectDefToExport ); + RPointerArray eventDefToExport; + CleanupClosePushL( eventDefToExport ); + RPointerArray relationDefToExport; + CleanupClosePushL( relationDefToExport ); + + // Get all object definitions from buffer. + if ( itemIds.iObjectIds.iPtr.iCount > 0 ) + { + if ( !namespaceDefRestrict ) + { + User::Leave( KErrCorrupt ); + } + objectDefToExport.ReserveL( itemIds.iObjectIds.iPtr.iCount ); + aItems.PositionL( itemIds.iObjectIds.iPtr.iOffset ); + TDefId objectDefId; + for ( TInt i = 0; i < itemIds.iObjectIds.iPtr.iCount; ++i ) + { + aItems.ReceiveL( objectDefId ); + const CMdsObjectDef* objectDef = namespaceDefRestrict->GetObjectByIdL( objectDefId ); + if (objectDef) + { + objectDefToExport.Append( objectDef ); + } + } + } + + // Get all event definitions from buffer. + if ( itemIds.iEventIds.iPtr.iCount > 0 ) + { + if (!namespaceDefRestrict) + { + User::Leave( KErrCorrupt ); + } + eventDefToExport.ReserveL( itemIds.iEventIds.iPtr.iCount ); + aItems.PositionL( itemIds.iEventIds.iPtr.iOffset ); + TDefId eventDefId; + for ( TInt i = 0; i < itemIds.iEventIds.iPtr.iCount; ++i ) + { + aItems.ReceiveL( eventDefId ); + const CMdsEventDef* eventDef = namespaceDefRestrict->GetEventByIdL( eventDefId ); + if (eventDef) + { + eventDefToExport.Append( eventDef ); + } + } + } + + // Get all relation definitions from buffer. + if ( itemIds.iRelationIds.iPtr.iCount > 0 ) + { + if ( !namespaceDefRestrict ) + { + User::Leave( KErrCorrupt ); + } + relationDefToExport.ReserveL( itemIds.iRelationIds.iPtr.iCount ); + aItems.PositionL( itemIds.iRelationIds.iPtr.iOffset ); + TDefId relationDefId; + for ( TInt i = 0; i < itemIds.iRelationIds.iPtr.iCount; ++i ) + { + aItems.ReceiveL( relationDefId ); + const CMdsRelationDef* relationDef = namespaceDefRestrict->GetRelationByIdL( relationDefId ); + if ( relationDef ) + { + relationDefToExport.Append( relationDef ); + } + } + } + + CMdsClauseBuffer* clause = CMdsClauseBuffer::NewLC( 2048 ); + CMdsClauseBuffer* freeTextClause = CMdsClauseBuffer::NewLC( 512 ); + + RRowData dataRow; + CleanupClosePushL( dataRow ); + RRowData freeTextRow; + CleanupClosePushL( freeTextRow ); + + TInt j; + + const TInt namespaceCount = aSchemaNew.iNamespaceDefs.Count(); + + for ( TInt i = 0; i < namespaceCount; ++i ) + { + CMdsNamespaceDef* namespaceDef = aSchemaNew.iNamespaceDefs[i]; + if ( namespaceDefRestrict && namespaceDefRestrict != namespaceDef ) + { + continue; + } + + ExportMetadataMakeFreeTextSqlClauseL( *namespaceDef, *freeTextClause, freeTextRow ); + // writing object information + + const TInt objectDefCount = namespaceDef->iObjectDefs.Count(); + + for ( j = 0; j < objectDefCount; ++j ) + { + CMdsObjectDef* objectDef = namespaceDef->iObjectDefs[j]; + if ( !namespaceDefRestrict || objectDefToExport.Count() == 0 || objectDefToExport.Find( objectDef ) != KErrNotFound ) + { + ExportMetadataMakeSqlObjectClauseL( *namespaceDef, *objectDef, *clause, dataRow ); + ExportMetadataWriteObjectInfoL( *namespaceDef, *objectDef, *clause, dataRow, *freeTextClause, freeTextRow ); + } + } + + // writing relation information + ExportMetadataMakeSqlRelationClauseL( *namespaceDef, *clause, dataRow ); + + const TInt relationDefCount = namespaceDef->iRelationDefs.Count(); + + for ( j = 0; j < relationDefCount; ++j ) + { + CMdsRelationDef* relationDef = namespaceDef->iRelationDefs[j]; + if ( !namespaceDefRestrict || relationDefToExport.Count() == 0 || relationDefToExport.Find( relationDef ) != KErrNotFound ) + { + ExportMetadataWriteRelationInfoL( *namespaceDef, *relationDef, *clause, dataRow ); + } + if ( j == namespaceDef->iRelationDefs.Count() - 1 ) + { + iWriteStream.WriteL( KExportMetadataNewLine ); + } + } + + // writing event information + ExportMetadataMakeSqlEventClauseL( *namespaceDef, *clause, dataRow ); + + const TInt eventDefCount = namespaceDef->iEventDefs.Count(); + + for ( j = 0; j < eventDefCount; ++j ) + { + CMdsEventDef* eventDef = namespaceDef->iEventDefs[j]; + if ( !namespaceDefRestrict || eventDefToExport.Count() == 0 || eventDefToExport.Find( eventDef ) != KErrNotFound ) + { + ExportMetadataWriteEventInfoL( *namespaceDef, *eventDef, *clause, dataRow ); + } + } + } + + CleanupStack::PopAndDestroy( 8, &iWriteStream ); // freeTextRow, dataRow, freeTextClause, clause, relationDefToExport, eventDefToExport, objectDefToExport, iWriteStream + } + +void CMdsImportExport::ExportMetadataMakeSqlObjectClauseL( const CMdsNamespaceDef& aNamespaceDef, const CMdsObjectDef& aObjectDef, + CMdsClauseBuffer& aClause, RRowData& aDataRow ) + { + _LIT( KExportMetadataNotConfidential, " NOT (Flags&? OR Flags&? OR Flags&?);" ); + aClause.BufferL().Zero(); // reset clause + aDataRow.Free(); // free and reset dataRow + aDataRow.Reset(); + + aClause.AppendL( KSelectPropertyFilterBegin ); + aDataRow.AppendL( TColumn( TItemId(0) ) ); // objectId + aDataRow.AppendL( TColumn( TDefId(0) ) ); // objectDefId + aDataRow.AppendL( TColumn( TUint32(0) ) ); // objectFlags + aDataRow.AppendL( TColumn( TUint32(0) ) ); // objectMediaId + aDataRow.AppendL( TColumn( TUint32(0) ) ); // usageCount + aDataRow.AppendL( TColumn( TInt64(0) ) ); // objectGuidHigh + aDataRow.AppendL( TColumn( TInt64(0) ) ); // objectGuidLow + aDataRow.AppendL( TColumn( EColumnDes16 ) ); // objectURI + + const TInt allPropertiesCount = aObjectDef.GetAllPropertiesCount(); + for ( TInt i = 0; i < allPropertiesCount; ++i ) + { + const CMdsObjectDef::TMdsColumnOrder& column = aObjectDef.GetPropertyColumnL( i ); + const CMdsPropertyDef& property = column.iPropertyDef; + + aClause.AppendL( KComma ); + aClause.AppendL( property.GetName() ); + + aDataRow.AppendL( TColumn( property.GetSqlType() ) ); + } + aClause.AppendL( KSpace ); + + aClause.AppendL( KFromBaseObject, KMaxUintValueLength ); // + namespace id + aClause.BufferL().AppendNum( aNamespaceDef.GetId() ); + aClause.AppendL( KAsBaseObject ); + + aClause.AppendL( KComma ); + aClause.AppendL( aObjectDef.GetName(), KMaxUintValueLength ); // + namespace id + aClause.BufferL().AppendNum( aNamespaceDef.GetId() ); + + aClause.AppendL( KAsObjectOnEqual ); + + aClause.AppendL( KWhere ); + aClause.AppendL( KSpace ); + aClause.AppendL( KExportMetadataNotConfidential ); + } + +void CMdsImportExport::ExportMetadataMakeFreeTextSqlClauseL( const CMdsNamespaceDef& aNamespaceDef, + CMdsClauseBuffer& aFreeTextClause, RRowData& aFreeTextRow ) + { + _LIT( KExportMetadataFreeTextSearch, + "SELECT Word FROM TextSearchDictionary%u WHERE WordId IN (SELECT WordId FROM TextSearch%u WHERE ObjectId = ?);" ); + + aFreeTextClause.BufferL().Zero(); + aFreeTextClause.ReserveSpaceL( KExportMetadataFreeTextSearch.iTypeLength + 2*KMaxUintValueLength ); + + aFreeTextClause.BufferL().Format( KExportMetadataFreeTextSearch, aNamespaceDef.GetId(), aNamespaceDef.GetId() ); + + aFreeTextRow.Free(); + aFreeTextRow.Reset(); + aFreeTextRow.AppendL( TItemId(0) ); + } + +void CMdsImportExport::ExportMetadataWriteObjectInfoL( const CMdsNamespaceDef& aNamespaceDef, const CMdsObjectDef& aObjectDef, + CMdsClauseBuffer& aClause, RRowData& aDataRow, + CMdsClauseBuffer& aFreeTextClause, RRowData& aFreeTextRow ) + { + TItemId objectId; + TDefId objectDefId; + TUint32 objectFlags, objectMediaId, usageCount; + TInt64 objectGuidHigh, objectGuidLow; + TPtrC16 objectURI; + + RRowData confidentialFlagRow; + CleanupClosePushL( confidentialFlagRow ); + confidentialFlagRow.AppendL( TColumn( EMdEObjectFlagRemoved ) ); + confidentialFlagRow.AppendL( TColumn( EMdEObjectFlagNotPresent ) ); + confidentialFlagRow.AppendL( TColumn( EMdEObjectFlagConfidential ) ); + + CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); + + RMdsStatement query; + CleanupClosePushL( query ); + + RMdsStatement freeTextQuery; + CleanupClosePushL( freeTextQuery ); + RRowData textRow; + CleanupClosePushL( textRow ); + textRow.AppendL( TColumn( EColumnDes16 ) ); + + RRowData queryResult; + CleanupClosePushL( queryResult ); + queryResult.AppendColumnTypesL( aDataRow ); + connection.ExecuteQueryL( aClause.ConstBufferL(), query, confidentialFlagRow ); + while( connection.NextRowL( query, queryResult ) ) + { + // get result from query + queryResult.Column( 0 ).Get( objectId ); // objectId + queryResult.Column( 1 ).Get( objectDefId ); // objectDefId + __ASSERT_DEBUG( objectDefId == aObjectDef.GetId(), User::Panic( _L( "CMdsImportExport::ExportMetadataWriteObjectInfo" ), KErrGeneral ) ); + queryResult.Column( 2 ).Get( objectFlags ); // objectFlags + queryResult.Column( 3 ).Get( objectMediaId ); // objectMediaId + queryResult.Column( 4 ).Get( usageCount ); // usageCount + queryResult.Column( 5 ).Get( objectGuidHigh ); // objectGuidHigh + queryResult.Column( 6 ).Get( objectGuidLow ); // objectGuidLow + queryResult.Column( 7 ).Get( objectURI ); // objectURI + + // writing basic object information + iWriteStream.WriteL( KMdsKeywordObject ); + iWriteStream.WriteL( KExportMetadataSpace ); + Conv16To8( aNamespaceDef.GetName(), iLine ); + iWriteStream.WriteL( iLine ); + iWriteStream.WriteL( KExportMetadataSpace ); + Conv16To8( aObjectDef.GetName(), iLine ); + iWriteStream.WriteL( iLine ); + iWriteStream.WriteL( KExportMetadataSpace ); + Conv16To8( objectURI, iLine ); + iLine.Insert( 0, KExportMetadataQuotationMark ); + iLine.Append( KExportMetadataQuotationMark ); + iWriteStream.WriteL( iLine ); + iWriteStream.WriteL( KExportMetadataSpace ); + iLine.Num( objectMediaId ); + iWriteStream.WriteL( iLine ); + iWriteStream.WriteL( KExportMetadataNewLine ); + + const TInt count = aObjectDef.GetAllPropertiesCount(); + + // writing property information + for ( TInt i = 0; i < count; ++i ) + { + if ( queryResult.Column( i + KBaseObjectBasicValueColumnOffset ).IsNull() ) + { + continue; + } + + const CMdsObjectDef::TMdsColumnOrder& column = aObjectDef.GetPropertyColumnL( i ); + const CMdsPropertyDef& property = column.iPropertyDef; + + iWriteStream.WriteL( KMdsKeywordProperty ); + iWriteStream.WriteL( KExportMetadataSpace ); + Conv16To8( property.GetName(), iLine ); + iWriteStream.WriteL( iLine ); + iWriteStream.WriteL( KExportMetadataSpace ); + + switch( property.GetSqlType() ) + { + case EColumnBool: + { + TBool value; + queryResult.Column( i + KBaseObjectBasicValueColumnOffset ).Get( value ); + iLine.Num( value ); + break; + } + case EColumnInt32: + { + TInt32 value; + queryResult.Column( i + KBaseObjectBasicValueColumnOffset ).Get( value ); + iLine.Num( value ); + break; + } + case EColumnUint32: + { + TUint32 value; + queryResult.Column( i + KBaseObjectBasicValueColumnOffset ).Get( value ); + iLine.Num( value ); + break; + } + case EColumnInt64: + { + TInt64 value; + queryResult.Column( i + KBaseObjectBasicValueColumnOffset ).Get( value ); + iLine.Num( value ); + break; + } + case EColumnTime: + { + TTime value; + queryResult.Column( i + KBaseObjectBasicValueColumnOffset ).Get( value ); + TDateTime time = value.DateTime(); + iLine.Format( KExportMetadataTimeFormat, time.Year(), time.Month()+1, time.Day()+1, time.Hour(), time.Minute(), time.Second() ); + break; + } + case EColumnReal32: + { + TReal32 value; + queryResult.Column( i + KBaseObjectBasicValueColumnOffset ).Get( value ); + TRealFormat realFormat; + realFormat.iType |= KAllowThreeDigitExp | KDoNotUseTriads; + realFormat.iPoint = TChar('.'); + iLine.Num( value, realFormat ); + break; + } + case EColumnReal64: + { + TReal64 value; + queryResult.Column( i + KBaseObjectBasicValueColumnOffset ).Get( value ); + TRealFormat realFormat; + realFormat.iType |= KAllowThreeDigitExp | KDoNotUseTriads; + realFormat.iPoint = TChar('.'); + iLine.Num( value, realFormat ); + break; + } + case EColumnDes16: + { + TPtrC16 value; + queryResult.Column( i + KBaseObjectBasicValueColumnOffset ).Get( value ); + Conv16To8( value, iLine ); + iLine.Insert( 0, KExportMetadataQuotationMark ); + iLine.Append( KExportMetadataQuotationMark ); + break; + } + default: + { + User::Leave( KErrCorrupt ); + } + } + iWriteStream.WriteL( iLine ); + + iWriteStream.WriteL( KExportMetadataNewLine ); + } + + // restore query + queryResult.AppendColumnTypesL( aDataRow ); + + // writing freetext + // get freetext + aFreeTextRow.Column( 0 ).Set( objectId ); + connection.ExecuteQueryL( aFreeTextClause.ConstBufferL(), freeTextQuery, aFreeTextRow ); + TBool freeTextPreamble = EFalse; + TInt lineSize = KMdsKeywordFreeText().Size() + 3; // space + line ending + while( connection.NextRowL( freeTextQuery, textRow ) ) + { + // get result from query + if ( !freeTextPreamble ) + { + iWriteStream.WriteL( KMdsKeywordFreeText ); + iWriteStream.WriteL( KExportMetadataSpace ); + freeTextPreamble = ETrue; + } + TPtrC16 word; + textRow.Column( 0 ).Get( word ); + Conv16To8( word, iLine ); + iLine.Insert( 0, KExportMetadataQuotationMark ); + iLine.Append( KExportMetadataQuotationMark ); + lineSize += iLine.Length() + 2; + if ( lineSize >= KMdsMaxLineLenght ) + { + iWriteStream.WriteL( KExportMetadataNewLine ); + iWriteStream.WriteL( KMdsKeywordFreeText ); + iWriteStream.WriteL( KExportMetadataSpace ); + lineSize = KMdsKeywordFreeText().Size() + 3; // space + line ending + } + iWriteStream.WriteL( iLine ); + iWriteStream.WriteL( KExportMetadataSpace ); + textRow.Free(); + } + if ( freeTextPreamble ) + { + iWriteStream.WriteL( KExportMetadataNewLine ); + } + + iWriteStream.WriteL( KExportMetadataNewLine ); + } + + CleanupStack::PopAndDestroy( 5, &confidentialFlagRow ); // queryResult, textRow, freeTextQuery, query, confidentialFlagRow + } + + +void CMdsImportExport::ExportMetadataMakeSqlRelationClauseL( const CMdsNamespaceDef& aNamespaceDef, + CMdsClauseBuffer& aClause, RRowData& aDataRow ) + { + _LIT( KExportMetadataRelationQuery, "SELECT LO.URI,RO.URI,Parameter FROM Relations%u AS R,Object%u AS LO ON LeftObjectId=LO.ObjectId JOIN Object%u AS RO ON RightObjectId=RO.ObjectId WHERE RelationDefId=? AND NOT R.Flags&? AND NOT R.Flags&?;" ); + + aClause.BufferL().Zero(); // reset clause + aClause.ReserveSpaceL( KExportMetadataRelationQuery.iTypeLength + 30 ); + aClause.BufferL().Format( KExportMetadataRelationQuery, aNamespaceDef.GetId(), aNamespaceDef.GetId(), aNamespaceDef.GetId() ); + + aDataRow.Free(); // free and reset dataRow + aDataRow.Reset(); + aDataRow.AppendL( TColumn( TDefId(0) ) ); // relationDefId + aDataRow.AppendL( TColumn( EMdERelationFlagDeleted ) ); + aDataRow.AppendL( TColumn( EMdERelationFlagNotPresent ) ); + } + +void CMdsImportExport::ExportMetadataWriteRelationInfoL( const CMdsNamespaceDef& aNamespaceDef, const CMdsRelationDef& aRelationDef, + CMdsClauseBuffer& aClause, RRowData& aDataRow ) + { + CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); + + RRowData resultRow; + CleanupClosePushL( resultRow ); + resultRow.AppendL( TColumn( EColumnDes16 ) ); // LeftObjectIds URI + resultRow.AppendL( TColumn( EColumnDes16 ) ); // RightObjectIds URI + resultRow.AppendL( TColumn( TInt32(0) ) ); // RelationParameter + + RMdsStatement query; + CleanupClosePushL( query ); + RRowData resultRowGet; + CleanupClosePushL( resultRowGet ); + resultRowGet.AppendColumnTypesL( resultRow ); + + aDataRow.Column( 0 ).Set( aRelationDef.GetId() ); + connection.ExecuteQueryL( aClause.ConstBufferL(), query, aDataRow ); + while( connection.NextRowL( query, resultRowGet ) ) + { + iWriteStream.WriteL( KMdsKeywordRelation ); + iWriteStream.WriteL( KExportMetadataSpace ); + Conv16To8( aNamespaceDef.GetName(), iLine ); + iWriteStream.WriteL( iLine ); + iWriteStream.WriteL( KExportMetadataSpace ); + Conv16To8( aRelationDef.GetName(), iLine ); + iWriteStream.WriteL( iLine ); + iWriteStream.WriteL( KExportMetadataSpace ); + + TPtrC16 uri; + resultRowGet.Column( 0 ).Get( uri ); + Conv16To8( uri, iLine ); + iLine.Insert( 0, KExportMetadataQuotationMark ); + iLine.Append( KExportMetadataQuotationMark ); + iWriteStream.WriteL( iLine ); + iWriteStream.WriteL( KExportMetadataSpace ); + + resultRowGet.Column( 1 ).Get( uri ); + Conv16To8( uri, iLine ); + iLine.Insert( 0, KExportMetadataQuotationMark ); + iLine.Append( KExportMetadataQuotationMark ); + iWriteStream.WriteL( iLine ); + iWriteStream.WriteL( KExportMetadataSpace ); + + TInt32 relationParameter; + resultRowGet.Column( 2 ).Get( relationParameter ); + iLine.Num( relationParameter ); + iWriteStream.WriteL( iLine ); + iWriteStream.WriteL( KExportMetadataNewLine ); + + resultRowGet.AppendColumnTypesL( resultRow ); + } + + CleanupStack::PopAndDestroy( 3, &resultRow ); // query, resultRowGet, resultRow + } + + +void CMdsImportExport::ExportMetadataMakeSqlEventClauseL( const CMdsNamespaceDef& aNamespaceDef, + CMdsClauseBuffer& aClause, RRowData& aDataRow ) + { + _LIT( KExportMetadataEventQuery, "SELECT URI,Source,Participant,Timestamp FROM Event%u AS EL,Object%u AS O ON EL.ObjectId=O.ObjectId WHERE EventDefId=?;" ); + + aClause.BufferL().Zero(); // reset clause + aClause.ReserveSpaceL( KExportMetadataEventQuery.iTypeLength + 20 ); + aClause.BufferL().Format( KExportMetadataEventQuery, aNamespaceDef.GetId(), aNamespaceDef.GetId() ); + + aDataRow.Free(); // free and reset dataRow + aDataRow.Reset(); + aDataRow.AppendL( TColumn( TDefId(0) ) ); // eventDefId + } + +void CMdsImportExport::ExportMetadataWriteEventInfoL( const CMdsNamespaceDef& aNamespaceDef, const CMdsEventDef& aEventDef, + CMdsClauseBuffer& aClause, RRowData& aDataRow ) + { + CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); + + RRowData resultRow; + CleanupClosePushL( resultRow ); + resultRow.AppendL( TColumn( EColumnDes16 ) ); // target + resultRow.AppendL( TColumn( EColumnDes16 ) ); // source + resultRow.AppendL( TColumn( EColumnDes16 ) ); // participant + resultRow.AppendL( TColumn( TTime(0) ) ); // time + + RMdsStatement query; + CleanupClosePushL( query ); + + RRowData resultRowGet; + CleanupClosePushL( resultRowGet ); + resultRowGet.AppendColumnTypesL( resultRow ); + + aDataRow.Column( 0 ).Set( aEventDef.GetId() ); + connection.ExecuteQueryL( aClause.ConstBufferL(), query, aDataRow ); + while( connection.NextRowL( query, resultRowGet ) ) + { + iWriteStream.WriteL( KMdsKeywordEvent ); + iWriteStream.WriteL( KExportMetadataSpace ); + Conv16To8( aNamespaceDef.GetName(), iLine ); + iWriteStream.WriteL( iLine ); + iWriteStream.WriteL( KExportMetadataSpace ); + Conv16To8( aEventDef.GetName(), iLine ); + iWriteStream.WriteL( iLine ); + iWriteStream.WriteL( KExportMetadataSpace ); + + TPtrC16 word; + // target + resultRowGet.Column( 0 ).Get( word ); + Conv16To8( word, iLine ); + iLine.Insert( 0, KExportMetadataQuotationMark ); + iLine.Append( KExportMetadataQuotationMark ); + iWriteStream.WriteL( iLine ); + iWriteStream.WriteL( KExportMetadataSpace ); + + // source + resultRowGet.Column( 1 ).Get( word ); + Conv16To8( word, iLine ); + iLine.Insert( 0, KExportMetadataQuotationMark ); + iLine.Append( KExportMetadataQuotationMark ); + iWriteStream.WriteL( iLine ); + iWriteStream.WriteL( KExportMetadataSpace ); + + // participant + resultRowGet.Column( 2 ).Get( word ); + Conv16To8( word, iLine ); + iLine.Insert( 0, KExportMetadataQuotationMark ); + iLine.Append( KExportMetadataQuotationMark ); + iWriteStream.WriteL( iLine ); + iWriteStream.WriteL( KExportMetadataSpace ); + + TTime value; + resultRowGet.Column( 3 ).Get( value ); + TDateTime time = value.DateTime(); + iLine.Format( KExportMetadataTimeFormat, time.Year(), time.Month()+1, time.Day()+1, time.Hour(), time.Minute(), time.Second() ); + iWriteStream.WriteL( iLine ); + iWriteStream.WriteL( KExportMetadataNewLine ); + + resultRowGet.AppendColumnTypesL( resultRow ); + } + + CleanupStack::PopAndDestroy( 3, &resultRow ); // query, resultRowGet, resultRow + } + + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// IMPORT HELPER FUNCTIONS +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- + + +// --------------------------------------------------------------------------- +// ImportText imports text which may be quoted and escaped +// ------------------------------------------------ +// +TInt CMdsImportExport::ImportText( TDes16& aBuffer, TLex8& aParser ) + { + TPtrC8 token; + token.Set( aParser.NextToken() ); + + if ( token.Length() == 0 || token.Length() >= aBuffer.MaxLength() ) + { + return KErrCorrupt; + } + + /** + * The string may be enclosed in quotes. Unfortunately the parser always stops at + * whitespace, so we must loop with the NextToken() until we find a token that ends with + * an unescaped quotation mark. The bit below will then mark everything inside the quotes + * as a single uninterrupted token. + */ + if ( token[0] == '\"' ) + { + TInt currentTokenLength(token.Length()); + TInt start = aParser.Offset() - currentTokenLength; + TInt end = aParser.Offset(); + TBool forceContinue( EFalse ); + while( ETrue ) + { + // if there is a closing quote in the token see if is escaped + if ( currentTokenLength > 1 ) + { + // First skip any escaped dollar signs in the string + // to avoid a false match in case the string is something + // like "foo$$" + TInt loc = token.Find(_L8("$$")); + while( loc != KErrNotFound ) + { + token.Set(token.Mid(loc+2)); + loc = token.Find(_L8("$$")); + } + // Now the token contains only non-escaped dollars + currentTokenLength = token.Length(); + if ( currentTokenLength > 2 && token.Right(2) == _L8("$\"") ) + { + forceContinue = ETrue; + } + } + + if(token[currentTokenLength - 1] == '\"' && !forceContinue) + { + // The token contains a closing quote which is not escaped, + // leave loop because the string is finished + break; + } + forceContinue = EFalse; + token.Set(aParser.NextToken()); + currentTokenLength = token.Length(); + end = aParser.Offset(); + if ( currentTokenLength == 0 || currentTokenLength >= aBuffer.MaxLength() - (end-start) ) + { + return KErrCorrupt; + } + } + // We have the complete token length now, set the TPtrC accordingly + token.Set(iLine.Mid(start + 1, (end-start) - 2)); // skip the quotes + TBuf8<256> fp(token); + } + // The token now contains the full string + Conv8To16( token, aBuffer ); + + return KErrNone; + } + +// ------------------------------------------------ +// ImportUInt32 +// ------------------------------------------------ +// +TInt CMdsImportExport::ImportUInt32( TUint32& aValue, TLex8& aParser ) + { + TLex8 tokenParser( aParser.NextToken() ); + aParser.SkipSpace(); + if ( tokenParser.Val( aValue, EDecimal ) != KErrNone ) + { + _LIT( KError, "Expecting a numeric value" ); + LogError( KError ); + return KErrCorrupt; + } + return KErrNone; + } + +// ------------------------------------------------ +// ImportMediaId +// ------------------------------------------------ +// +TInt CMdsImportExport::ImportMediaId( TUint32& aValue, TLex8& aParser, TChar& aDriveLetter ) + { + TLex8 tokenParser( aParser.NextToken() ); + aParser.SkipSpace(); + if ( tokenParser.Val( aValue, EDecimal ) != KErrNone ) + { + _LIT( KError, "Expecting a numeric value" ); + LogError( KError ); + return KErrCorrupt; + } + + TInt error( KErrNone ); + TInt driveNumber( -1 ); + error = iFs.CharToDrive( aDriveLetter, driveNumber ); + + if ( error != KErrNone ) + { + return error; + } + + if( driveNumber != iLastDriveNumber ) + { + error = iFs.Volume( iLastVolumeInfo, driveNumber ); + + if ( error != KErrNone ) + { + return error; + } + + iLastDriveNumber = driveNumber; + } + + aValue = iLastVolumeInfo.iUniqueID; + + return KErrNone; + } + +// ------------------------------------------------ +// ImportInt64 +// ------------------------------------------------ +// +TInt CMdsImportExport::ImportInt64( Int64& aValue, TLex8& aParser ) + { + // due to symbian int64 parser error + // for now we will use ImportNum version + ImportNum( aValue, aParser ); + + return KErrNone; + } + +// ------------------------------------------------ +// ImportTime +// ------------------------------------------------ +// +TInt CMdsImportExport::ImportTime( TTime& aValue, TLex8& aParser ) + { + // format: YYYYMMDDhhmmss + TPtrC8 token( aParser.NextToken() ); + if ( token.Length() != 14 ) + { + _LIT( KError, "Expecting a time value" ); + LogError( KError ); + return KErrCorrupt; + } + + TLex8 year_p( token.Mid( 0, 4 ) ); + TLex8 month_p( token.Mid( 4, 2 ) ); + TLex8 day_p( token.Mid( 6, 2 ) ); + TLex8 hour_p( token.Mid( 8, 2 ) ); + TLex8 minute_p( token.Mid( 10, 2 ) ); + TLex8 second_p( token.Mid( 12, 2 ) ); + TInt year; + TInt month; + TInt day; + TInt hour; + TInt minute; + TInt second; + + year_p.Val( year ); + month_p.Val( month ); + day_p.Val( day ); + hour_p.Val( hour ); + minute_p.Val( minute ); + second_p.Val( second ); + + TDateTime datetime; + const TInt error = datetime.Set( year, (TMonth)(month-1), day-1, hour, + minute, second, 0 ); + if ( error != KErrNone ) + { + return error; + } + + aValue = datetime; + return KErrNone; + } + +// ------------------------------------------------ +// Conv8To16 +// ------------------------------------------------ +// +TDesC16& CMdsImportExport::Conv8To16( const TDesC8& aUtf8, TDes16& aBuffer ) + { + TInt conversionState = CCnvCharacterSetConverter::KStateDefault; + iConverter->ConvertToUnicode( aBuffer, aUtf8, conversionState ); + return aBuffer; + } + +// ------------------------------------------------ +// Conv16To8 +// ------------------------------------------------ +// +TDesC8& CMdsImportExport::Conv16To8( const TDesC16& aUnicode, TDes8& aBuffer ) + { + iConverter->ConvertFromUnicode( aBuffer, aUnicode ); + return aBuffer; + } + +// ------------------------------------------------ +// LogError +// ------------------------------------------------ +// +void CMdsImportExport::LogError( const TDesC& aMessage ) + { + _LIT( KParseError, "Parse error: %S" ); + _LIT( KCurrentFile, "Current file: %S" ); + _LIT( KCurrentLineNum, "Current line number: %d" ); + _LIT( KCurrentLine, "Current line: %S" ); + iLog.WriteFormat( KParseError, &aMessage ); + iLog.WriteFormat( KCurrentFile, &iFileName ); + iLog.WriteFormat( KCurrentLineNum, iLineNumber ); + TBuf16 line16; + Conv8To16( iLine, line16 ); + iLog.WriteFormat( KCurrentLine, &line16 ); + } + + +// ------------------------------------------------ +// CheckForConstant +// ------------------------------------------------ +// +TInt CMdsImportExport::CheckForConstant( TLex8& aParser ) + { + TInt ret = KErrNone; + TBuf<32> buf; + aParser.Mark(); + ret = ImportText( buf, aParser ); + if ( ret < KErrNone ) + { + aParser.UnGetToMark(); + return ret; + } + if ( buf.CompareF(KMdsKeywordMinValue) == 0 ) + { + return KPropertyMinValue; + } + else if ( buf.CompareF(KMdsKeywordMaxValue) == 0 ) + { + return KPropertyMaxValue; + } + else if ( buf.CompareF(KMdsKeywordDefValue) == 0 ) + { + return KPropertyDefValue; + } + aParser.UnGetToMark(); + return KErrNotFound; + }