xml/xmlfw/src/xmlframework/matchdata.cpp
changeset 0 e35f40988205
child 14 243519c5055f
equal deleted inserted replaced
-1:000000000000 0:e35f40988205
       
     1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Implementation of CMatchData class
       
    15 // 
       
    16 //
       
    17 
       
    18 /**
       
    19  @file 
       
    20  @publishedAll
       
    21  @released
       
    22 */
       
    23 
       
    24 #include <xml/matchdata.h>
       
    25 #include <xml/xmlframeworkerrors.h>
       
    26 
       
    27 using namespace Xml;
       
    28 
       
    29 /**
       
    30 The maximum length of variant field
       
    31 
       
    32 @internalComponent
       
    33 */
       
    34 const TInt KXmlMaxVariantLength = 32;
       
    35 
       
    36 /**
       
    37 The maximum length of mime type field
       
    38 
       
    39 @internalComponent
       
    40 */
       
    41 const TInt KXmlMaxMimeTypeLength = 255;
       
    42 
       
    43 /**
       
    44 Fields separator for data and opaque data in resource information file
       
    45 
       
    46 @internalComponent
       
    47 */
       
    48 _LIT8(KXmlDataSeparator, "||");
       
    49 
       
    50 /**
       
    51 Set flag macro to simplify bitmap management
       
    52 
       
    53 @internalComponent
       
    54 */
       
    55 #define SYMBIAN_XML_FLAG_SET(bitmap, flag, setting) \
       
    56 			bitmap = setting?(bitmap|flag):(bitmap&(~flag))
       
    57 			
       
    58 /**
       
    59 Rom only flag
       
    60 To request for rom based parsers only
       
    61 Default value is FALSE
       
    62 
       
    63 @internalComponent
       
    64 */ 
       
    65 const TInt32 KXmlRomOnlyFlag = 0x00000001;
       
    66 
       
    67 /**
       
    68 Case Sensitivity flag
       
    69 To specify how case sensitivity should be applied, while performing strings matching
       
    70 Default value is TRUE
       
    71 
       
    72 @internalComponent
       
    73 */
       
    74 const TInt32 KXmlCaseSensitivityFlag = 0x00000002;
       
    75 
       
    76 /**
       
    77 Leave on many flag
       
    78 To leave when the query is narrowed down to more than one parser.
       
    79 If not set, the XML framework will choose a parser.
       
    80 Default value is FALSE
       
    81 
       
    82 @internalComponent
       
    83 */
       
    84 const TInt32 KXmlLeaveOnManyFlag = 0x00000004;
       
    85 
       
    86 /**
       
    87 Reserved, unused flags in iAddInfo attribute
       
    88 
       
    89 @internalComponent
       
    90 */
       
    91 const TInt32 KXmlAddInfoReservedFlags = 0xFFFFFFF8;
       
    92 
       
    93 /**  
       
    94 Object constructor. Initializes internal state to default values 
       
    95 
       
    96 @internalComponent
       
    97 */
       
    98 CMatchData::CMatchData(): 
       
    99 			iMimeType(NULL),
       
   100 			iVariant(NULL),
       
   101 			iAddInfo(KXmlCaseSensitivityFlag)
       
   102 	{
       
   103 	
       
   104 	}
       
   105 
       
   106 /** 
       
   107 Object destructor. Deletes allocated heap based memory. 
       
   108 
       
   109 @internalComponent
       
   110 */
       
   111 CMatchData::~CMatchData()
       
   112 	{
       
   113 	if (iMimeType != NULL)
       
   114 		{
       
   115 		delete iMimeType;
       
   116 		iMimeType = NULL;
       
   117 		}
       
   118 	
       
   119 	if (iVariant != NULL)
       
   120 		{
       
   121 		delete iVariant;
       
   122 		iVariant = NULL;
       
   123 		}
       
   124 	}
       
   125 
       
   126 /**
       
   127 Creates CMatchData object with its default values. 
       
   128 
       
   129 @leave KErrNoMemory 	If there is not enough memory to create an object.
       
   130 
       
   131 @return A pointer to the newly created CMatchData object.
       
   132 
       
   133 */
       
   134 EXPORT_C CMatchData* CMatchData::NewL()
       
   135 	{
       
   136 	CMatchData* me = CMatchData::NewLC();
       
   137 	CleanupStack::Pop(me); 
       
   138 	return me;
       
   139 	}
       
   140 	
       
   141 /** 
       
   142 Creates CMatchData object using heap based stream of externalized object's data. 
       
   143 
       
   144 @param aPackage Descriptor to the heap based stream of externalized object 
       
   145 
       
   146 @leave KErrNoMemory 	If there is not enough memory to create an object. 
       
   147 @leave KErrArgument 	If the argument passed to an object is incorrect.
       
   148 
       
   149 @return A pointer to the newly created CMatchData object.
       
   150 
       
   151 @internalComponent
       
   152 */
       
   153 EXPORT_C CMatchData* CMatchData::NewL(const TDesC8& aPackage)
       
   154 	{
       
   155 	CMatchData* me = CMatchData::NewLC(aPackage);
       
   156 	CleanupStack::Pop(me);
       
   157 	return me;
       
   158 	}
       
   159 	
       
   160 
       
   161 /**
       
   162 Creates CMatchData object with its default values. 
       
   163 Leaves an obeject pointer on a cleanup stack. 
       
   164 
       
   165 @leave KErrNoMemory If there is not enough memory
       
   166 
       
   167 @return A pointer to the newly created CMatchData object.
       
   168 
       
   169 */
       
   170 EXPORT_C CMatchData* CMatchData::NewLC()
       
   171 	{
       
   172 	CMatchData* me = new (ELeave) CMatchData();
       
   173 	CleanupStack::PushL(me);
       
   174        return me;	
       
   175 	}
       
   176 	
       
   177 
       
   178 /**
       
   179 Creates CMatchData object using heap based stream of externalized object's data. 
       
   180 Leaves an obeject pointer on a cleanup stack. 
       
   181 
       
   182 @param aPackage Descriptor to the heap based stream of externalized object 
       
   183 
       
   184 @leave KErrNoMemory 	If there is not enough memory to create an object.
       
   185 @leave KErrArgument 	If the argument passed to an object is incorrect.
       
   186 
       
   187 @return A pointer to the newly created CMatchData object.
       
   188 
       
   189 @internalComponent
       
   190 */
       
   191 EXPORT_C CMatchData* CMatchData::NewLC(const TDesC8& aPackage)
       
   192 	{
       
   193 	CMatchData* me = new (ELeave) CMatchData();
       
   194 	CleanupStack::PushL(me);
       
   195 	me->ConstructL(aPackage);
       
   196 	return me;
       
   197 	}
       
   198 
       
   199 /**
       
   200 Standard symbian 2-phase construction method.
       
   201 It reads a stream stored on a heap and internalize the object. 
       
   202 
       
   203 @param aPackage Descriptor to the heap based stream of externalized object 
       
   204 
       
   205 @leave KErrNoMemory 	If there is not enough memory to create an object.
       
   206 @leave KErrArgument 	If the argument passed to an object is incorrect.
       
   207 
       
   208 @return A pointer to the newly created CMatchData object.
       
   209 
       
   210 @internalComponent
       
   211 */		
       
   212 void CMatchData::ConstructL(const TDesC8& aPackage)
       
   213 	{
       
   214 	RDesReadStream stream(aPackage);
       
   215 	InternalizeL(stream);
       
   216 	stream.Close();
       
   217 	}
       
   218 
       
   219 /** 
       
   220 Externalizes the object into RWriteStrem.
       
   221 
       
   222 @param aStream Stream to write to
       
   223 
       
   224 @internalComponent
       
   225 */		
       
   226 void CMatchData::ExternalizeL(RWriteStream& aStream) const
       
   227 	{
       
   228 	aStream.WriteInt16L(iMimeType? iMimeType->Length():0);
       
   229 	if(iMimeType && iMimeType->Length() > 0)
       
   230 		{
       
   231 		aStream.WriteL(*iMimeType, iMimeType->Length());
       
   232 		}
       
   233 	
       
   234 	aStream.WriteInt16L(iVariant?iVariant->Length():0);
       
   235 	if (iVariant && iVariant->Length() > 0 )
       
   236 		{
       
   237 		aStream.WriteL(*iVariant, iVariant->Length());
       
   238 		}
       
   239 	
       
   240 	aStream.WriteUint32L(iAddInfo);
       
   241 	}
       
   242 	
       
   243 /** 
       
   244 Internalizes the object out of RReadStream.
       
   245 
       
   246 @param aStream Stream to read from 
       
   247 
       
   248 @leave KErrNoMemory 	If there is not enough memory for new string allocation.
       
   249 @leave KErrArgument 	If passed descriptor doesn't comply with length constraints.  
       
   250 
       
   251 @internalComponent
       
   252 */	
       
   253 void CMatchData::InternalizeL(RReadStream& aStream)
       
   254 	{
       
   255 	TInt16 temp;
       
   256 	
       
   257 	// read mime type and create the heap buffer for it. 
       
   258 	// verify constraints
       
   259 	temp = aStream.ReadInt16L();
       
   260 	if (temp <=0 || temp > KXmlMaxMimeTypeLength)
       
   261 		{
       
   262 		// must not be greater then max
       
   263 		User::LeaveIfError(KErrArgument);
       
   264 		}
       
   265 	
       
   266 	// delete current value as it is no longer valid
       
   267 	if (iMimeType != NULL)
       
   268 		{
       
   269 		delete iMimeType;
       
   270 		iMimeType = NULL;
       
   271 		}
       
   272 	
       
   273 	// create buffer and read new data if available
       
   274 	if (temp > 0)
       
   275 		{
       
   276 		iMimeType = HBufC8::NewL(temp);
       
   277 		TPtr8 ptr = iMimeType->Des();
       
   278 		aStream.ReadL(ptr, temp);
       
   279 		}
       
   280 	
       
   281 	// read variant and create the heap buffer for it. 
       
   282 	// verify constarints
       
   283 	temp = aStream.ReadInt16L();
       
   284 	if (temp <0 || temp > KXmlMaxVariantLength)
       
   285 		{
       
   286 		// must not be greater then max, zero possible. 
       
   287 		User::LeaveIfError(KErrArgument);
       
   288 		}
       
   289 	 	
       
   290 	// delete current value as it is no longer valid
       
   291 	if (iVariant != NULL)
       
   292 		{
       
   293 		delete iVariant;
       
   294 		iVariant = NULL;
       
   295 		}
       
   296 	
       
   297 	// create buffer and read new data if available
       
   298 	if (temp > 0)
       
   299 		{
       
   300 		iVariant = HBufC8::NewL(temp);
       
   301 		TPtr8 ptr = iVariant->Des();
       
   302 		aStream.ReadL(ptr, temp);	
       
   303 		}
       
   304 	
       
   305 	// read additional info 
       
   306 	iAddInfo = aStream.ReadUint32L();
       
   307 	// check for correctness of the iAddInfo bitmap
       
   308 	if (iAddInfo & KXmlAddInfoReservedFlags > 0 )
       
   309 		{
       
   310 		// Leave as unexpected flags are set. 
       
   311 		User::LeaveIfError(KErrArgument);
       
   312 		}	
       
   313 }
       
   314 
       
   315 /**
       
   316 Sets up a mime type attribute to a string given as an aData descriptor. 
       
   317 
       
   318 @param aData String descriptor
       
   319 
       
   320 @leave KErrNoMemory 	If there is not enough memory for new string allocation.
       
   321 @leave KErrArgument 	If passed descriptor doesn't comply with length constraints. 
       
   322 
       
   323 */		
       
   324 EXPORT_C void CMatchData::SetMimeTypeL(const TDesC8& aData)
       
   325 	{
       
   326 	// verify constraints
       
   327 	if (aData.Length() == 0 || aData.Length() > KXmlMaxMimeTypeLength)
       
   328 		{
       
   329 		// must not be greater than max
       
   330 		User::Leave(KErrArgument);
       
   331 		}
       
   332 
       
   333 	// delete current value as it is no longer valid
       
   334 	if (iMimeType != NULL)
       
   335 		{
       
   336 		delete iMimeType;
       
   337 		iMimeType = NULL;
       
   338 		}
       
   339 		
       
   340 	// allocate required buffer and copy new data
       
   341 	iMimeType = aData.AllocL();
       
   342 	
       
   343 	}
       
   344 
       
   345 /**
       
   346 Sets up a variant attribute to a string given as an aVariant descriptor. 
       
   347 If this is not set OR is set to a string of length 0 the Variant ID is
       
   348 not used during parser resolution and hence the variant IDs of plug-in 
       
   349 parsers are ignored.
       
   350 
       
   351 @param aData String descriptor
       
   352 
       
   353 @leave KErrNoMemory 	If there is not enough memory for new string allocation.
       
   354 @leave KErrArgument 	If passed descriptor doesn't comply with length constraints. 
       
   355 
       
   356 */			
       
   357 EXPORT_C void CMatchData::SetVariantL(const TDesC8& aVariant)
       
   358 	{
       
   359 
       
   360 	// verify constraints
       
   361 	if (aVariant.Length() > KXmlMaxVariantLength)
       
   362 		{
       
   363 		// must not be greater than max
       
   364 		User::Leave(KErrArgument);
       
   365 		}
       
   366 
       
   367 	// delete current value as it is no longer valid
       
   368 	if (iVariant != NULL)
       
   369 		{
       
   370 		delete iVariant;
       
   371 		iVariant = NULL;
       
   372 		}
       
   373 	
       
   374 	// allocate required buffer and copy new data	
       
   375 	iVariant = aVariant.AllocL();
       
   376 	}
       
   377 
       
   378 /**
       
   379 Returns a pointer to the mime type string.  
       
   380 
       
   381 @return A pointer to the mime type string. 
       
   382 		Pointer to KNullDesC8 is returned if not set up yet.
       
   383 
       
   384 */		
       
   385 EXPORT_C const TPtrC8 CMatchData::MimeType() const
       
   386 	{
       
   387 	TPtrC8 result;
       
   388 
       
   389 	if(iMimeType)
       
   390 		result.Set(*iMimeType);
       
   391 	else
       
   392 		result.Set(KNullDesC8);
       
   393 
       
   394 	return result;
       
   395 	}
       
   396 	
       
   397 /**
       
   398 Returns a pointer to the variant string.  
       
   399 
       
   400 @return A pointer to the variant string. 
       
   401 		Pointer to KNullDesC8 is returned if not set up yet.
       
   402 
       
   403 */	
       
   404 EXPORT_C const TPtrC8 CMatchData::Variant() const
       
   405 	{
       
   406 	TPtrC8 result;
       
   407 
       
   408 	if(iVariant)
       
   409 		result.Set(*iVariant);
       
   410 	else
       
   411 		result.Set(KNullDesC8);
       
   412 
       
   413 	return result;
       
   414 	}
       
   415 
       
   416 /**
       
   417 Returns a heap based buffer descriptor of an externalized CMatchData object stream. 
       
   418 The newly created object's ownership is shifted to the caller. 
       
   419 
       
   420 @leave KErrNoMemory If there is not enough memory to create an heap based buffer. 
       
   421 
       
   422 @return Heap based buffer descriptor of an externalized object stream.
       
   423 
       
   424 @internalComponent
       
   425 */		
       
   426 HBufC8* CMatchData::PackToBufferL() const
       
   427 	{
       
   428 	//Create new Heap Descriptor with the size of externalized CMatchData
       
   429 	HBufC8* data = HBufC8::NewLC(	(iMimeType?iMimeType->Size():0)
       
   430 								+ (iVariant?iVariant->Size():0) 
       
   431 								+ 2*sizeof(TInt16) 		// length of mime type and variant strings
       
   432 								+ sizeof(TUint32));		// size of addinfo variable
       
   433 	
       
   434 	// create the stream using allocated buffer
       
   435 	TPtr8   dataDes = data->Des();
       
   436 	RDesWriteStream stream(dataDes);
       
   437 
       
   438 	// pack object into the allocated buffer
       
   439 	ExternalizeL(stream);
       
   440 	
       
   441 	//cleanup
       
   442 	stream.Close();
       
   443 	CleanupStack::Pop(data);
       
   444 	return data;
       
   445 	}
       
   446 
       
   447 
       
   448 /**
       
   449 Sets the LeaveOnManyFlag flag. 
       
   450 If set, it notifies customized resolver it should leave when the query is resolved to more than one parser. 
       
   451 By default this flag is not set, so the framework chooses a parser in this case. 
       
   452 
       
   453 @param aSetting The setting value. 
       
   454 
       
   455 */		
       
   456 EXPORT_C void CMatchData::SetLeaveOnMany(TBool aSetting) 
       
   457 	{
       
   458 	SYMBIAN_XML_FLAG_SET(iAddInfo, KXmlLeaveOnManyFlag, aSetting);
       
   459 	}
       
   460 	
       
   461 /**
       
   462 Sets the Rom Only flag. 
       
   463 If set, it notifies customized resolver the request is for ROM-based parsers only. 
       
   464 By default this flag is not set, so the framework searches for rom and non-rom based parsers. 
       
   465 
       
   466 @param aSetting The setting value. 
       
   467 
       
   468 */
       
   469 EXPORT_C void CMatchData::SetRomOnly(TBool aSetting) 
       
   470 	{
       
   471 	SYMBIAN_XML_FLAG_SET(iAddInfo, KXmlRomOnlyFlag, aSetting);
       
   472 	}
       
   473 
       
   474 /**
       
   475 Sets the Case Sensitivity flag. 
       
   476 Customized resolver uses this setting to turn on or off case sensitivity for strings matching.
       
   477 
       
   478 @param aSetting The setting value. 
       
   479 
       
   480 */
       
   481 EXPORT_C void CMatchData::SetCaseSensitivity(TBool aSetting)
       
   482 	{
       
   483 	SYMBIAN_XML_FLAG_SET(iAddInfo, KXmlCaseSensitivityFlag, aSetting);
       
   484 	}
       
   485 
       
   486 /**
       
   487 Static function to sort an array of CImplementationInformation objects, 
       
   488 in ascending order of their Uid values.
       
   489 The function is used in CMatchData::ResolveL().
       
   490 
       
   491 @param aImpInfo1	pointer of first CImplementationInformation object
       
   492 @param aImpInfo2	pointer of second CImplementationInformation object
       
   493 
       
   494 @return			zero, if the two objects have equal Uids
       
   495 @return			a negative value, if the first object's Uid is less than the second object's Uid.
       
   496 @return			a positive value, if the first object's Uid is greater than the second object's Uid.
       
   497 
       
   498 @internalComponent
       
   499 
       
   500 */	
       
   501 TInt CMatchData::SortOrder(const CImplementationInformation &aImpInfo1, 
       
   502 							const CImplementationInformation &aImpInfo2)
       
   503 	{
       
   504     if (aImpInfo1.ImplementationUid().iUid > aImpInfo2.ImplementationUid().iUid)
       
   505 		{
       
   506 		return 1;
       
   507 		}
       
   508 	if (aImpInfo1.ImplementationUid().iUid < aImpInfo2.ImplementationUid().iUid)
       
   509 		{
       
   510 		return -1;
       
   511 		}
       
   512 	return 0;		
       
   513 	}
       
   514 
       
   515 /**
       
   516 Performs a parser resolution. 
       
   517 Following criteria are considered:
       
   518  - Case sensitivity for string matching is applied according to the Case Sensitivity flag.
       
   519  - Only ROM-based parsers are considered when ROM only flag is set. 
       
   520  - Mime type is mandatory as it must match the data field in resource information file.
       
   521  - Variant is optional. If present it must match first entry in the opaque data field. 
       
   522  - If the query is narrowed down to more than one parser the behaviour is determined in 
       
   523     SelectSingleParserL function. 
       
   524 
       
   525 @param 	aImplList The list of available parsers to choose from. 
       
   526 
       
   527 @leave 	KErrNoMemory
       
   528 @leave 	KErrXmlMoreThanOneParserMatched
       
   529 
       
   530 @return 	Parser's Uid or KNullUid if parser isn't found. 
       
   531 
       
   532 @see SelectSingleParserL
       
   533 
       
   534 @internalComponent
       
   535 
       
   536 */
       
   537 EXPORT_C TUid CMatchData::ResolveL(RImplInfoArray& aImplList) const
       
   538 	{
       
   539 	TUid matchUid;
       
   540 	
       
   541 	// Create an array to hold multiple matching parser uids
       
   542 	// RImplInfoPtrArray is used here for the usage of TLinearOrder<> pattern
       
   543 	RImplInfoPtrArray parserArray;
       
   544 	
       
   545 	CleanupClosePushL(parserArray);
       
   546 	
       
   547 	// go through the list of implementations for the 
       
   548 	for (TInt i = 0 ; i < aImplList.Count(); i++)
       
   549 		{
       
   550 		::CImplementationInformation* impData = aImplList[i];
       
   551 		
       
   552 		if (RomOnly() && !(impData->RomBased()))
       
   553 			{
       
   554 			// Request for rom based parser only. 
       
   555 			// This one isn't rom based, so continue with the next one
       
   556 			continue;
       
   557 			}
       
   558 			
       
   559 		if ((MimeTypeMatch(impData->DataType()) == TRUE) 
       
   560 			&& (VariantMatch(impData->OpaqueData()) == TRUE) )
       
   561 			{
       
   562 			// store the matching implementation occurance 
       
   563 			// if there is only one occurance, this Uid will be returned
       
   564 			// otherwise, the list will contain items sorted by Uid
       
   565 			// (see CMatchData::SortOrder())
       
   566 			parserArray.InsertInOrderL(impData, 
       
   567 							TLinearOrder<CImplementationInformation>(CMatchData::SortOrder));			
       
   568 			}
       
   569 		}
       
   570 	
       
   571 	// check if multiple match found
       
   572 	if (parserArray.Count()==1)
       
   573 		{
       
   574 		// list filtered down to one parser.
       
   575 		matchUid = parserArray[0]->ImplementationUid();
       
   576 		}
       
   577 	else if (parserArray.Count()>1)
       
   578 		{
       
   579 		// multiple matches found. we need to make a decision 
       
   580 		matchUid = SelectSingleParserL(parserArray);
       
   581 		}
       
   582 	else
       
   583 		{
       
   584 		// no match
       
   585 		matchUid = KNullUid;
       
   586 		}
       
   587 		
       
   588 	CleanupStack::PopAndDestroy(&parserArray);
       
   589 	return matchUid;
       
   590 	}
       
   591 	
       
   592 /**
       
   593 Helps parser resolution when multiple matches are found
       
   594 Following criteria are considered on the list filtered by ResolveL:
       
   595 - The code might either leave with an error if LeaveOnMany flag is set, or 
       
   596   select a parser from the multiple-item list. The default behaviour is to select
       
   597   the parser with lowest uid. To preserve backwards compatibility, in the case of 
       
   598   no variant a Symbian supplied parser will be returned if present. If there are 
       
   599   multiple matching Symbian parsers, the one with the lowest Uid will be returned.
       
   600 
       
   601 @param 	aImplList The filtered list of parsers to choose from. 
       
   602 
       
   603 @leave 	KErrNoMemory
       
   604 @leave 	KErrXmlMoreThanOneParserMatched
       
   605 
       
   606 @return 	Parser's Uid
       
   607 
       
   608 @internalComponent
       
   609 */
       
   610 TUid CMatchData::SelectSingleParserL(RImplInfoPtrArray& aImplList) const	
       
   611 	{
       
   612 	TInt arrayLen = aImplList.Count();
       
   613 	
       
   614 	// check if multiple match found
       
   615 	if ( LeaveOnMany() )
       
   616 		{
       
   617 		// At this point more than one parser was found matching resolution criteria,
       
   618 		// the user is requesting to leave in such a case
       
   619 		User::Leave(KErrXmlMoreThanOneParserMatched);					
       
   620 		}
       
   621 	
       
   622 	if (IsInvalidVariant()) 
       
   623 		{
       
   624 		// multiple matches in list and variant is invalid means we should look for Symbian plugin
       
   625 		// we go through the (ascending) sorted list of implementations
       
   626 		for (TInt j = 0 ; j <= arrayLen-1; j++)
       
   627 			{
       
   628 			::CImplementationInformation* impData = aImplList[j];
       
   629 		
       
   630 			// we check every matching parser variant for Symbian string
       
   631 			if ((CaseSensitivity() && (impData->OpaqueData().Compare(KXmlSymbianPluginVariant) == 0))
       
   632 				||(!CaseSensitivity() && (impData->OpaqueData().CompareF(KXmlSymbianPluginVariant) == 0))  )
       
   633 				{
       
   634 				// this match is the lowest Uid Symbian parser, return it
       
   635 				return impData->ImplementationUid();
       
   636 				}
       
   637 			}
       
   638 		// if this for loop finishes without returning, this means there are multiple
       
   639 		// matching parsers none of which are Symbian. We defer their processing to the
       
   640 		// common 'return lowest uid' part of the algorithm
       
   641 		}
       
   642 		
       
   643 	// return the lowest uid, which should be the first item in the list
       
   644 	return aImplList[0]->ImplementationUid();
       
   645 	}
       
   646 	
       
   647 /**
       
   648 Performs string matching for all the entries in an aField string separated by aSeparator. 
       
   649 
       
   650 @param aField		string with several entries separated by aSeparator. 
       
   651 @param aMatchString string to match against entries in aField
       
   652 @param aSeparator   string which separates entries in aField
       
   653 
       
   654 @return Match result
       
   655 
       
   656 @internalComponent
       
   657 */
       
   658 TBool CMatchData::MatchField(const TDesC8& aField, const TDesC8& aMatchString, const TDesC8& aSeparator) const
       
   659 	{
       
   660 	// verify input data
       
   661 	if (aField.Length() == 0 || aMatchString.Length() == 0)
       
   662 		{
       
   663 		return EFalse;
       
   664 		}
       
   665 	
       
   666 	// Check if aField and aMatchString are not the same.
       
   667 	// For most cases aField is a one-entry string, so for better performance it is worth to check it up front. 
       
   668 	if (	(CaseSensitivity() && (aField.Compare(aMatchString) == 0))
       
   669 		|| (!CaseSensitivity() && (aField.CompareF(aMatchString) == 0) )  )
       
   670 		{
       
   671 		return ETrue;
       
   672 		}
       
   673 	
       
   674 	// Find the first separator position
       
   675 	TInt separatorPos = aField.Find(aSeparator);
       
   676 	if (separatorPos == KErrNotFound)
       
   677 		{
       
   678 		// No separators in the string. 
       
   679 		// Only one entry in the aField string, which was already verified as non-matching. 
       
   680 		// No matches found then. 
       
   681 		return EFalse;
       
   682 		}
       
   683 		
       
   684 	TInt separatorLength =  aSeparator.Length();
       
   685 	
       
   686 	// call again the method with the "first field" of the string
       
   687 	if (MatchField(aField.Left(separatorPos), aMatchString, aSeparator) == TRUE)
       
   688 		{
       
   689 		return ETrue;
       
   690 		}
       
   691 	
       
   692 	// call the method with the remaining sections of the string
       
   693 	if (MatchField(aField.Mid(separatorPos + separatorLength), aMatchString, aSeparator) == TRUE)
       
   694 		{
       
   695 		return ETrue;
       
   696 		}
       
   697 	
       
   698 	//All recursive calls returned false, so the match wasn't found
       
   699 	return EFalse;
       
   700 	}
       
   701 	
       
   702 /**
       
   703 Checks for mime type entry in aDataField string.
       
   704 
       
   705 @param aDataFiled string with several mime type entries separated by "||" string. 
       
   706 
       
   707 @return Match result
       
   708 
       
   709 @internalComponent
       
   710 */	
       
   711 TBool CMatchData::MimeTypeMatch(const TDesC8& aDataField) const
       
   712 	{
       
   713 	return MatchField(aDataField, *iMimeType, KXmlDataSeparator);
       
   714 	}
       
   715 
       
   716 /**
       
   717 Checks for variant string entry in first field of aOpaqueField string.
       
   718 
       
   719 @param aOpaqueField string with several entries separated by "||" string. 
       
   720 
       
   721 @return Match result
       
   722 
       
   723 @internalComponent
       
   724 */	
       
   725 TBool CMatchData::VariantMatch(const TDesC8& aOpaqueField) const
       
   726 	{
       
   727 	TPtrC8 matchString;
       
   728 	
       
   729 	if (IsInvalidVariant())
       
   730 		{
       
   731 		// optional variant is not set
       
   732 		// return true in all cases
       
   733 		return ETrue;
       
   734 		}
       
   735 		
       
   736 	TInt separatorPos = aOpaqueField.Find(KXmlDataSeparator);
       
   737 	
       
   738 	// set the first entry in the opague data to match against
       
   739 	if (separatorPos == KErrNotFound)
       
   740 		{
       
   741 		matchString.Set(aOpaqueField);
       
   742 		}
       
   743 	else
       
   744 		{
       
   745 		matchString.Set(aOpaqueField.Left(separatorPos));
       
   746 		}
       
   747 		
       
   748 	// perform string matching
       
   749 	if (	(CaseSensitivity() && (iVariant->Compare(matchString) == 0))
       
   750 		||(!CaseSensitivity() && (iVariant->CompareF(matchString) == 0))  )
       
   751 		{
       
   752 		return ETrue;
       
   753 		}
       
   754 		
       
   755 	return EFalse;
       
   756 	}
       
   757 /**
       
   758 Returns Case Sensitivity flag value
       
   759 
       
   760 @return Flag state
       
   761 
       
   762 @internalComponent
       
   763 */
       
   764 TBool CMatchData::CaseSensitivity() const
       
   765 	{
       
   766 	return (iAddInfo & KXmlCaseSensitivityFlag)?ETrue:EFalse;
       
   767 	}
       
   768 
       
   769 /**
       
   770 Returns LeaveOnMany flag value
       
   771 
       
   772 @return Flag state
       
   773 
       
   774 @internalComponent
       
   775 */	
       
   776 TBool CMatchData::LeaveOnMany() const
       
   777 	{
       
   778 	return (iAddInfo & KXmlLeaveOnManyFlag)?ETrue:EFalse;
       
   779 	}
       
   780 	
       
   781 /**
       
   782 Returns Rom-Only flag value 
       
   783 
       
   784 @return Flag state
       
   785 
       
   786 @internalComponent
       
   787 */
       
   788 TBool CMatchData::RomOnly() const
       
   789 	{
       
   790 	return (iAddInfo & KXmlRomOnlyFlag)?ETrue:EFalse;
       
   791 	}
       
   792 	
       
   793 /**
       
   794 Assignement operator
       
   795 
       
   796 @param aMatchData CMatchData object to assign from
       
   797 
       
   798 @internalComponent
       
   799 */
       
   800 CMatchData& CMatchData::operator=(const CMatchData & aMatchData)
       
   801 	{
       
   802 
       
   803 	 /*
       
   804 	  * SYMBIAN DEF132492 FIX : Added TRAP statements to handle	the case wherein the functions
       
   805 	  * called here leave.
       
   806 	  */
       
   807      TRAPD( err, SetMimeTypeL(aMatchData.MimeType()) ) ; 
       
   808      if( err != KErrNone )
       
   809 	  {     
       
   810 		 return *this; 
       
   811 	 }	  	   
       
   812 
       
   813 	 /*
       
   814 	  * SYMBIAN DEF132492 FIX : Added TRAP statements to handle	the case wherein the functions
       
   815 	  * called here leave.
       
   816 	  */	 
       
   817 	TRAP( err, SetVariantL(aMatchData.Variant()));
       
   818     if( err != KErrNone )
       
   819 	  {     
       
   820 	     return *this; 
       
   821 	 }	  	   
       
   822 
       
   823 
       
   824 	iAddInfo = aMatchData.iAddInfo;
       
   825 	return *this;
       
   826 	}
       
   827 /**
       
   828 Comparison operator.
       
   829 
       
   830 @param aMatchData CMatchData object to compare with
       
   831 
       
   832 @internalComponent
       
   833 */
       
   834 TBool CMatchData::operator==(const CMatchData & aMatchData) const
       
   835 	{
       
   836 	
       
   837 	// verify iAddInfo first as the fastest comparision
       
   838 	if (aMatchData.iAddInfo != iAddInfo)
       
   839 		{
       
   840 		return EFalse;
       
   841 		}
       
   842 	
       
   843 	// verfiy mime type 
       
   844 	if (iMimeType == NULL 
       
   845 		|| (CaseSensitivity() && iMimeType->Compare(aMatchData.MimeType()) != 0)
       
   846 		|| (!CaseSensitivity() && iMimeType->CompareF(aMatchData.MimeType()) != 0) ) 		
       
   847 		{
       
   848 		// iMimeType is NULL or strings doesn't match
       
   849 		// verify the case where both might be NULL. 
       
   850 		if ( (iMimeType != NULL) || (aMatchData.iMimeType != NULL ) )
       
   851 			{
       
   852 			// mime type doesn't match
       
   853 			return EFalse;
       
   854 			}
       
   855 		}
       
   856 	
       
   857 	// verfiy variant
       
   858 	if (iVariant == NULL 
       
   859 		|| (CaseSensitivity() && iVariant->Compare(aMatchData.Variant()) != 0)
       
   860 		|| (!CaseSensitivity() && iVariant->CompareF(aMatchData.Variant()) != 0) ) 		
       
   861 		{
       
   862 		// iVariant is NULL or strings doesn't match
       
   863 		// verify the case where both might be NULL. 
       
   864 		if ( (iVariant != NULL) || (aMatchData.iVariant != NULL) )
       
   865 			{
       
   866 			// variant doesn't match
       
   867 			return EFalse;
       
   868 			}
       
   869 		}
       
   870 	return ETrue;
       
   871 	}
       
   872 	
       
   873 /**
       
   874 Checks if iVariant is not set or empty
       
   875 
       
   876 @return Variant string validness
       
   877 
       
   878 @internalComponent
       
   879 */
       
   880 TBool CMatchData::IsInvalidVariant() const
       
   881 	{
       
   882 	return (iVariant == NULL || (iVariant && iVariant->Length() == 0));	
       
   883 	}
       
   884