clock2/clockengines/clocktimezoneresolver/src/clockmcctzmapper.cpp
author Simon Howkins <simonh@symbian.org>
Mon, 22 Nov 2010 16:01:09 +0000
branchRCL_3
changeset 93 d216ae5a8733
parent 66 bd7edf625bdd
child 67 1539a383d7b6
permissions -rw-r--r--
Adjusted to avoid exports, etc, from a top-level bld.inf

/*
* Copyright (c) 2008 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:   The source file for the CClockMCCTzIdMapper class.
*
*/

// System includes
#include <tz.h>
#include <tzdefines.h>
#include <vtzrules.h>
#include <bautils.h>

// User includes
#include "clockmcctzmapper.h"
#include "clock_debug.h"

// Constants

// Literals
_LIT( KMCCResourceFileDir, "\\resource\\mcc\\" );
_LIT( KMCCResourceFileName, "mcc.rsc" );

// ---------------------------------------------------------
// CClockMCCTzIdMapper::NewL
// rest of the details are commented in the header
// ---------------------------------------------------------
//
CClockMCCTzIdMapper* CClockMCCTzIdMapper::NewL()
	{
	__PRINTS( "CClockMCCTzIdMapper::NewL - Entry" );
    
    CClockMCCTzIdMapper* self = CClockMCCTzIdMapper::NewLC();
	CleanupStack::Pop( self );
	
	__PRINTS( "CClockMCCTzIdMapper::NewL - Exit" );
	
	return self;
	}

// ---------------------------------------------------------
// CClockMCCTzIdMapper::NewLC
// rest of the details are commented in the header
// ---------------------------------------------------------
//
CClockMCCTzIdMapper* CClockMCCTzIdMapper::NewLC()
	{
	__PRINTS( "CClockMCCTzIdMapper::NewLC - Entry" );
	
	CClockMCCTzIdMapper* self = new ( ELeave ) CClockMCCTzIdMapper();
	CleanupStack::PushL( self );

	self->ConstructL();
	
	__PRINTS( "CClockMCCTzIdMapper::NewLC - Exit" );
	
	return self;
	}

// ---------------------------------------------------------
// CClockMCCTzIdMapper::ConstructL
// rest of the details are commented in the header
// ---------------------------------------------------------
//
void CClockMCCTzIdMapper::ConstructL()
	{
	__PRINTS( "CClockMCCTzIdMapper::ConstructL - Entry" );
	
	// Connect to the file server
	User::LeaveIfError( iFs.Connect() );	
    
    // Get the full filename with drive letter
    TFileName rscFileName; 
    TFindFile fileFinder( iFs );

    // TFindFile applies search order that is from drive Y to A, then Z
    TInt err = fileFinder.FindByDir( KMCCResourceFileName, KMCCResourceFileDir );

    if ( err == KErrNone )
        {
        // Found file.
        rscFileName = fileFinder.File();
        }
    else
        {
        __PRINTS( "Unable to open mcc.rsc. Leaving now!!" );
        
        // Leave with reason, file not found.
        User::Leave( KErrPathNotFound );
        }
    
	// Open the resource file.  The resource file will not be localized as it
	// only contains integers, so there is no need to find a language specific
	// resource file name.
	iMCCResourceFile.OpenL( iFs, rscFileName );
	iMCCResourceFile.ConfirmSignatureL();

	// Assign buffer for holding resource
	TInt resourceId = iMCCResourceFile.Offset() + EMCCFirstResource;
	iResourceBuffer = iMCCResourceFile.AllocReadL( resourceId );
	
	__PRINTS( "CClockMCCTzIdMapper::ConstructL - Exit" );
	}

// ---------------------------------------------------------
// CClockMCCTzIdMapper::~CClockMCCTzIdMapper
// rest of the details are commented in the header
// ---------------------------------------------------------
//
CClockMCCTzIdMapper::~CClockMCCTzIdMapper()
	{
	__PRINTS( "CClockMCCTzIdMapper::~CClockMCCTzIdMapper - Entry" );
	
	// Close the resource file.
	iMCCResourceFile.Close();
	// Free up the resource buffer.
	if( iResourceBuffer )
	    {
	    delete iResourceBuffer;
	    iResourceBuffer = NULL;
	    }

	// Close the file server session.
	iFs.Close();
	
	__PRINTS( "CClockMCCTzIdMapper::~CClockMCCTzIdMapper - Exit" );
	}

// ---------------------------------------------------------
// CClockMCCTzIdMapper::UTCOffSetWithoutDSTChangesL
// rest of the details are commented in the header
// ---------------------------------------------------------
//
TInt CClockMCCTzIdMapper::UTCOffSetWithoutDSTChangesL( RTz& aTz, const CTzId& aTzId ) const
	{
	TInt timeOffset( KErrNotFound );

	TTime universalTime;
	universalTime.UniversalTime();

	// Get the current rules for the timezone rules
	CTzRules* currentRules = aTz.GetTimeZoneRulesL( aTzId, universalTime, universalTime, ETzUtcTimeReference );
	if( currentRules )
	    {
	    timeOffset = currentRules->InitialStdTimeOffset();
	    delete currentRules;
	    }
	
	return timeOffset;
	}

// ---------------------------------------------------------
// CClockMCCTzIdMapper::TzIdFromMccL
// rest of the details are commented in the header
// ---------------------------------------------------------
//
void CClockMCCTzIdMapper::TzIdFromMccL( const RMobilePhone::TMobilePhoneNetworkCountryCode& aMCC,
								        RArray< CTzId >& aTzIdArray,
								        const TTimeIntervalMinutes& aStdTimeOffset )
	{
	__PRINTS( "CClockMCCTzIdMapper::TzIdFromMccL - Entry" );
	
	// Convert the TMobilePhoneNetworkCountryCode to a TInt.
	TInt currentMcc;
	TLex lexUtil( aMCC );
	User::LeaveIfError( lexUtil.Val( currentMcc ) );
	
	__PRINT( "MCC: %d", currentMcc );

	// Get all the DST zones that match mcc
	DoGetTzIdFromMCCL( currentMcc, aTzIdArray );

	// Limit the returned entries to those with a specific StdTimeOffset
	TInt offset = aStdTimeOffset.Int();
	if( offset != -1 )
		{
		// Connect to Tz
		RTz tzHandle;
		CleanupClosePushL( tzHandle );
		User::LeaveIfError( tzHandle.Connect() );

		TInt currentZoneOffset;
		TInt count = aTzIdArray.Count();
		// Loop through the array in reverse order, removing all entries
		// with non matching standard time offsets.
		for( TInt index( count - 1 ); index >= KErrNone; --index )
			{
			currentZoneOffset = UTCOffSetWithoutDSTChangesL( tzHandle, aTzIdArray[ index ] );
			if( currentZoneOffset != offset )
				{
				aTzIdArray.Remove( index );
				}
			}
		// Cleanup.
		CleanupStack::PopAndDestroy( &tzHandle );
		}
	
	__PRINTS( "CClockMCCTzIdMapper::TzIdFromMccL - Exit" );
	}

// ---------------------------------------------------------
// CClockMCCTzIdMapper::TzIdFromOffsetL
// rest of the details are commented in the header
// ---------------------------------------------------------
//
void CClockMCCTzIdMapper::TzIdFromOffsetL( const TTimeIntervalMinutes& aStdTimeOffset, RArray< CTzId >& aTzIdArray )
	{
	__PRINTS( "CClockMCCTzIdMapper::TzIdFromOffsetL - Entry" );
	
	// Reset the position in the resource buffer
	iResourceReader.SetBuffer( iResourceBuffer );
	// First TInt is the number of array items
	TInt numberOfItems( iResourceReader.ReadInt16() );

	// Loop through the resource array reading the TzId
	for( TInt index( KErrNone ); index < numberOfItems; ++index )
		{
		TInt timeZoneId( iResourceReader.ReadInt16() );
		TInt mobileCC( iResourceReader.ReadInt16() );
		
		CTzId* timeZone = CTzId::NewL( timeZoneId );
		CleanupStack::PushL( timeZone );
		
		aTzIdArray.AppendL( *timeZone );
		
		CleanupStack::PopAndDestroy( timeZone );
		timeZone = NULL;
		}
	
	// Limit the returned entries to those with a specific StdTimeOffset
	TInt timeOffset( aStdTimeOffset.Int() );

	// Connect to Tz
	RTz tzHandle;
	CleanupClosePushL( tzHandle );
	User::LeaveIfError( tzHandle.Connect() );

	TInt currentZoneOffset;
	TInt idCount( aTzIdArray.Count() );

	// Loop through the array in reverse order, removing all entries
	// with non matching standard time offsets.
	for( TInt index( idCount - 1 ); index >= KErrNone; --index )
		{
		currentZoneOffset = UTCOffSetWithoutDSTChangesL( tzHandle, aTzIdArray[ index ] );
		if( currentZoneOffset != timeOffset )
			{
			aTzIdArray.Remove( index );
			}
		}
	CleanupStack::PopAndDestroy( &tzHandle );
	
	// This is a check to see if the timezone array has multiple entries with same timezone ID.
	// This happens because many countries have multiple MCCs for a single timezone ID.
	// For ex: India has MCCs 404 and 405 for the same timezone ID 1624 and offset GMT+5:30.
	TInt zoneCount( aTzIdArray.Count() );
	if( 1 < zoneCount )
		{
		CTzId& prevTzId = aTzIdArray[ KErrNone ];
		for( TInt zoneIndex( zoneCount - 1 ); zoneIndex > KErrNone; --zoneIndex )
			{
			CTzId& curTzId = aTzIdArray[ zoneIndex ];
			if( prevTzId != curTzId )
				{
				// There are multiple timezones. So skip.
				break;
				}
			else
				{
				// Keep removing duplicate zone IDs.
				aTzIdArray.Remove( zoneIndex );
				}
			}
		}

	__PRINTS( "CClockMCCTzIdMapper::TzIdFromOffsetL - Exit" );
	}

// ---------------------------------------------------------
// CClockMCCTzIdMapper::DoGetTzIdFromMCCL
// rest of the details are commented in the header
// ---------------------------------------------------------
//
void CClockMCCTzIdMapper::DoGetTzIdFromMCCL( TInt aMcc, RArray< CTzId >& aTzIdArray )
	{
	__PRINTS( "CClockMCCTzIdMapper::DoGetTzIdFromMCCL - Entry" );
	
	__PRINT( "MCC:%d", aMcc );
	
	// Reset the position in the resource buffer.
	iResourceReader.SetBuffer( iResourceBuffer );
	// First TInt is the number of array items.
	TInt numberOfItems( iResourceReader.ReadInt16() );

	TInt timeZoneId;
	TInt mobileCC;
	CTzId* matchingDSTZone( NULL );

	// Loop through the resource array reading the TzId / MCC pairs.
	for( TInt index( KErrNone ); index < numberOfItems; ++index )
		{
		timeZoneId = iResourceReader.ReadInt16();
		mobileCC = iResourceReader.ReadInt16();

		// Found a match - create a new CTzId and append to the TzId array.
		if( mobileCC == aMcc )
			{
			matchingDSTZone = CTzId::NewL( timeZoneId );
			CleanupStack::PushL( matchingDSTZone );
			
			aTzIdArray.AppendL( *matchingDSTZone );
			
			CleanupStack::PopAndDestroy( matchingDSTZone );
			
			matchingDSTZone = NULL;
			}
		}
	
	__PRINTS( "CClockMCCTzIdMapper::DoGetTzIdFromMCCL - Exit" );
	}

// ---------------------------------------------------------
// CClockMCCTzIdMapper::MCCFromTzIdL
// rest of the details are commented in the header
// ---------------------------------------------------------
//
TInt CClockMCCTzIdMapper::MCCFromTzIdL( const CTzId& aTzId )
	{
	__PRINTS( "CClockMCCTzIdMapper::MCCFromTzIdL - Entry" );
	
	// Reset the position in the resource buffer
	iResourceReader.SetBuffer( iResourceBuffer );
	// First TInt is the number of array items
	TInt numberOfItems( iResourceReader.ReadInt16() );
	TInt timeZoneId;
	TInt mobileCC;

	// Loop through the resource array reading the TzId / MCC pairs
	for( TInt index( KErrNone ); index < numberOfItems; ++index )
		{
		timeZoneId = iResourceReader.ReadInt16();
		mobileCC = iResourceReader.ReadInt16();

		// Found a match return the mcc
		if( timeZoneId == aTzId.TimeZoneNumericID() )
			{
			__PRINT( "Found a match, MCC - %d", mobileCC );
			
			return mobileCC;
			}
		}
	
	__PRINTS( "CClockMCCTzIdMapper::MCCFromTzIdL - Exit" );
	
	return KErrNotFound;
	}

// End of file