--- /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 <e32cmn.h>
+#include <charconv.h>
+#include <convgeneratedcpp.h>
+#include <badesca.h>
+#include <e32math.h>
+#include <pathinfo.h>
+
+#include <mdeconstants.h>
+
+#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 <name> <readonly>
+ TBuf16<KMdsMaxUriLenght> 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<KMdsMaxUriLenght> 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<KMdsMaxUriLenght> 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 <name> <readonly> <mandatory> <type> <minv> <maxv>
+ _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<KMdsMaxUriLenght> 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<TPropertyType>(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<TInt32>( CheckForConstant(aParser), minVal32, 0, 1, 0 );
+ if ( error < KErrNone )
+ {
+ User::LeaveIfError( ImportNum( minVal32, aParser ) );
+ }
+ error = SetMinMaxDefValueL<TInt32>( 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<TInt32>( CheckForConstant(aParser),
+ minVal32, KMinVal32, KMaxVal32, 0 );
+ if ( error < KErrNone )
+ {
+ User::LeaveIfError( ImportNum( minVal32, aParser ) );
+ }
+ error = SetMinMaxDefValueL<TInt32>( 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<TInt32>( CheckForConstant(aParser),
+ minVal32, 1, KSerializedDesMaxLength, 1 );
+ if ( error < KErrNone )
+ {
+ User::LeaveIfError( ImportNum( minVal32, aParser ) );
+ }
+ error = SetMinMaxDefValueL<TInt32>( 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<TUint32>( CheckForConstant(aParser),
+ minVal32, 0, KMaxTUint32, 0 );
+ if ( error < KErrNone )
+ {
+ User::LeaveIfError( ImportUInt32( minVal32, aParser ) );
+ }
+ error = SetMinMaxDefValueL<TUint32>( 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<TInt64>( CheckForConstant(aParser),
+ minVal64, KMinTInt64, KMaxTInt64, 0 );
+ if ( error < KErrNone )
+ {
+ User::LeaveIfError( ImportInt64( minVal64, aParser ) );
+ }
+ error = SetMinMaxDefValueL<TInt64>( 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<TTime>( CheckForConstant(aParser),
+ minTime, 0, KMaxTInt64, 0 );
+ if ( error < KErrNone )
+ {
+ User::LeaveIfError( ImportTime( minTime, aParser ) );
+ }
+ error = SetMinMaxDefValueL<TTime>( 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<TReal32>( CheckForConstant(aParser),
+ minReal, -KMaxTReal32, KMaxTReal32, 0 );
+ if ( error < KErrNone )
+ {
+ User::LeaveIfError( ImportNum( minReal, aParser ) );
+ }
+ error = SetMinMaxDefValueL<TReal32>( 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<TReal64>( CheckForConstant(aParser),
+ minReal, -KMDSMaxTReal64, KMDSMaxTReal64, 0 );
+ if ( error < KErrNone )
+ {
+ User::LeaveIfError( ImportNum( minReal, aParser ) );
+ }
+ error = SetMinMaxDefValueL<TReal64>( 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 <ns> <name>
+ TBuf16<KMdsMaxUriLenght> 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 <ns> <name> <priority>
+ TBuf16<KMdsMaxUriLenght> 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<KMdsMaxUriLenght> 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<KMdsMaxUriLenght> 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<KMdsMaxUriLenght> 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<KMdsMaxUriLenght> 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<KMdsMaxUriLenght> 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<CMdsObjectDef> objectDefToExport;
+ CleanupClosePushL( objectDefToExport );
+ RPointerArray<CMdsEventDef> eventDefToExport;
+ CleanupClosePushL( eventDefToExport );
+ RPointerArray<CMdsRelationDef> 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<KMdsMaxLogLineLenght> 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;
+ }