diff -r 000000000000 -r 2e3d3ce01487 contextframework/cfw/src/basicoperationsplugin/cfinrange.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/contextframework/cfw/src/basicoperationsplugin/cfinrange.cpp Tue Feb 02 10:12:00 2010 +0200 @@ -0,0 +1,479 @@ +/* +* Copyright (c) 2002-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: CCFInRange class implementation. +* +*/ + + + +// INCLUDES +#include "cfinrange.h" +#include "cfcontextobject.h" +#include "cfcontextoperationutils.h" +#include "cfbasicoptrace.h" + +#include +#include + +// CONSTANTS +_LIT( KScriptInRangeName, "inRange" ); + +const TReal KEarthRadius = 6378.137; +const TReal KFlattening = 1.000000 / 298.257223563; // Earth flattening (WGS84) +const TReal KEarthPS = 0.000000000005; + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CCFInRange::CCFInRange +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CCFInRange::CCFInRange( MCFOperationServices& aServices, + CCFOperationNode* aParent, + HBufC* aName, + HBufC* aSource, + const CCFContextOperation::TCmpType aType ) + : CCFContextOperation( aServices, aParent, aName, aSource ), + iType( aType ) + { + FUNC_LOG; + } + +// ----------------------------------------------------------------------------- +// CCFInRange::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CCFInRange::ConstructL( const TDesC& aMinVal, const TDesC& aMaxVal ) + { + FUNC_LOG; + + iMinVal = aMinVal.AllocL(); + iMaxVal = aMaxVal.AllocL(); + } + +// ----------------------------------------------------------------------------- +// CCFInRange::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CCFInRange* CCFInRange::NewL( MCFOperationServices& aServices, + CCFOperationNode* aParent, + TDesC& aName, + TDesC& aSource, + const CCFContextOperation::TCmpType aType, + const TDesC& aMinVal, + const TDesC& aMaxVal ) + { + FUNC_LOG; + + CCFInRange* self + = NewLC( aServices, aParent, aName, aSource, aType, aMinVal, aMaxVal ); + CleanupStack::Pop( self ); + return self; + } + +// ----------------------------------------------------------------------------- +// CCFInRange::NewLC +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CCFInRange* CCFInRange::NewLC( MCFOperationServices& aServices, + CCFOperationNode* aParent, + TDesC& aName, + TDesC& aSource, + const CCFContextOperation::TCmpType aType, + const TDesC& aMinVal, + const TDesC& aMaxVal ) + { + FUNC_LOG; + + HBufC* name = aName.AllocLC(); + HBufC* source = aSource.AllocLC(); + CCFInRange* self = + new( ELeave ) CCFInRange( aServices, aParent, name, source, aType ); + CleanupStack::PushL( self ); + self->ConstructL( aMinVal, aMaxVal ); + + // Cleanup + CleanupStack::Pop( self ); + CleanupStack::Pop( source ); + CleanupStack::Pop( name ); + + CleanupStack::PushL( self ); + return self; + } + +// ----------------------------------------------------------------------------- +// CCFInRange::ParseL +// Construction with parsing from a DOM node. +// ----------------------------------------------------------------------------- +// +CCFInRange* CCFInRange::ParseL( MCFOperationServices& aServices, + CCFOperationNode* aParent, + CMDXMLNode& aNode ) + { + FUNC_LOG; + + if ( aNode.NodeName().CompareF( KScriptInRangeName ) != 0 ) + { + return NULL; // Cannot create in range operation from the given node. + } + + TPtrC contextSource; + TPtrC contextType; + TPtrC contextValue; + TCmpType cmpMinType( CCFContextOperation::EInvalidCmpType ); + TCmpType cmpMaxType( CCFContextOperation::EInvalidCmpType ); + TPtrC minValue; + TPtrC maxValue; + TInt contextLevelDelay( 0 ); + + TBool contextRefOK( EFalse ); + TBool minArgOK( EFalse ); + TBool maxArgOK( EFalse ); + TBool argsOK( ETrue ); // Will be set to false if unknown nodes detected. + CMDXMLNode* child = aNode.FirstChild(); + while ( child ) + { + if ( child->NodeType() == CMDXMLNode::EElementNode ) + { + // Mandatory EElementNode order: 1. contextRef, 2. minArg, 3. maxArg + if ( !contextRefOK ) + { + contextRefOK = CFContextOperationUtils::ParseContextRef( + *child, + contextSource, + contextType, + contextValue, + contextLevelDelay ); + if ( !contextRefOK ) + { + argsOK = EFalse; + break; + } + } + else if ( !minArgOK ) + { + minArgOK = CFContextOperationUtils::ParseComparisonTypeValue( + *child, + cmpMinType, + minValue ); + if ( !minArgOK ) + { + argsOK = EFalse; + break; + } + } + else if ( !maxArgOK ) + { + maxArgOK = CFContextOperationUtils::ParseComparisonTypeValue( + *child, + cmpMaxType, + maxValue ); + if ( !maxArgOK ) + { + argsOK = EFalse; + break; + } + } + else + { + argsOK = EFalse; // Unsupported node encountered. + break; + } + } + else if ( child->NodeType() != CMDXMLNode::ECommentNode ) + { + argsOK = EFalse; // Unsupported node encountered. + break; + } + child = child->NextSibling(); + } + + TBool parsed( EFalse ); + if ( argsOK && contextRefOK && minArgOK && maxArgOK ) + { + if ( cmpMinType == cmpMaxType && !contextValue.Length() ) + { + parsed = ETrue; + } + } + + CCFInRange* self = NULL; + if ( parsed ) + { + self = NewL( aServices, + aParent, + contextType, + contextSource, + cmpMinType, + minValue, + maxValue ); + if ( contextLevelDelay ) + { + self->iContextLevelDelay = contextLevelDelay; + } + } + else + { + INFO( "CCFInRange::ParseL - Unsupported arguments" ); + } + + CREATE_DOM_INFO( self, aNode ); + + return self; + } + + +// Destructor +CCFInRange::~CCFInRange() + { + FUNC_LOG; + + delete iMinVal; + delete iMaxVal; + } + +// ----------------------------------------------------------------------------- +// CCFInRange::IsTrueL +// ----------------------------------------------------------------------------- +// +TBool CCFInRange::IsTrueL( const CCFContextObject& aContextObject ) + { + FUNC_LOG; + + TBool value( EFalse ); + switch ( iType ) + { + case CCFContextOperation::EIntCmp: + { + TInt min = CFContextOperationUtils::StringToIntL( *iMinVal ); + TInt max = CFContextOperationUtils::StringToIntL( *iMaxVal ); + TInt cmp = CFContextOperationUtils::StringToIntL( + aContextObject.Value() ); + value = ( cmp >= min ) && ( cmp <= max ); + break; + } + case CCFContextOperation::ETimeCmp: + { + TTime min = CFContextOperationUtils::StringToTimeL( *iMinVal ); + TTime max = CFContextOperationUtils::StringToTimeL( *iMaxVal ); + TTime cmp = CFContextOperationUtils::StringToTimeL( + aContextObject.Value() ); + value = ( cmp >= min ) && ( cmp <= max ); + break; + } + case CCFContextOperation::EPositionCmp: + { + // local variable declaration & initialization + TReal cmpLatitude( KErrNone ), cmpLongitude( KErrNone ), + objLatitude( KErrNone ), objLongitude( KErrNone ); + TReal calculatedDistance( KErrNone ); + TReal locationRadius( KErrNone ); + // get values contained by scripts + CFContextOperationUtils::PositionToRealsL( + *iMinVal, + cmpLatitude, + cmpLongitude ); + CFContextOperationUtils::PositionToRealsL( + aContextObject.Value(), + objLatitude, + objLongitude ); + locationRadius = CFContextOperationUtils::StringToRealL( + *iMaxVal ); + calculatedDistance = EllipsoidDistanceBetweenTwoPositions( + cmpLatitude, + cmpLongitude, + objLatitude, + objLongitude ); + // error occurred; leave + if ( calculatedDistance == KErrGeneral ) + { + User::Leave( static_cast< TInt > ( calculatedDistance ) ); + } + value = ( calculatedDistance <= locationRadius ); + break; + } + case CCFContextOperation::EFloatCmp: + { + TReal min = CFContextOperationUtils::StringToRealL( *iMinVal ); + TReal max = CFContextOperationUtils::StringToRealL( *iMaxVal ); + TReal cmp = CFContextOperationUtils::StringToRealL( + aContextObject.Value() ); + value = ( cmp >= min ) && ( cmp <= max ); + break; + } + case CCFContextOperation::EStringCmp: + default: + { + value = ( aContextObject.Value() >= ( *iMinVal ) ) && + ( aContextObject.Value() <= ( *iMaxVal ) ); + break; + } + + } + + return value; + } + +// ----------------------------------------------------------------------------- +// CCFInRange::EllipsoidDistanceBetweenTwoPoints +// Method that takes two GPS positions as (latitude,longitude)-pairs +// (units==DEGREES) and calculates their ellipsoid distance. +// ----------------------------------------------------------------------------- +// +TReal CCFInRange::EllipsoidDistanceBetweenTwoPositions( TReal aPos1Latitude, + TReal aPos1Longitude, + TReal aPos2Latitude, + TReal aPos2Longitude ) + { + FUNC_LOG; + + TInt err( KErrNone ); + TReal distance = 0.0; + TReal faz, baz; + TReal r = 1.0 - KFlattening; + TReal tu1, tu2, cu1, su1, cu2, x, sx, cx, sy, cy, y, sa, c2a, cz, e, c, d; + TReal cosy1, cosy2; + + // Make sure the coordinates differ. + if ( ( aPos1Longitude == aPos2Longitude ) && + ( aPos1Latitude == aPos2Latitude ) ) + { + return distance; + } + + // Convert longitude and latitudes to radians. + aPos1Longitude *= KDegToRad; + aPos1Latitude *= KDegToRad; + aPos2Longitude *= KDegToRad; + aPos2Latitude *= KDegToRad; + + err = Math::Cos( cosy1, aPos1Latitude ); + if ( err != KErrNone ) + { + return KErrGeneral; + } + err = Math::Cos( cosy2, aPos2Latitude ); + if ( err != KErrNone ) + { + return KErrGeneral; + } + + // Assure positive values since this is used as division denominator. + if ( cosy1 == 0.0 ) + { + cosy1 = 0.0000000001; + } + // Assure positive values since this is used as division denominator. + if ( cosy2 == 0.0 ) + { + cosy2 = 0.0000000001; + } + + TReal temp1, temp2, temp3, temp4; + err = Math::Sin( temp1, aPos1Latitude ); + if ( err != KErrNone ) + { + return KErrGeneral; + } + err = Math::Sin( temp2, aPos2Latitude ); + if ( err != KErrNone ) + { + return KErrGeneral; + } + + tu1 = r * temp1 / cosy1; + tu2 = r * temp2 / cosy2; + err = Math::Sqrt( temp3, ( tu2 * tu2 + 1.0 ) ); + if ( err != KErrNone ) + { + return KErrGeneral; + } + cu1 = 1.0 / temp3; + su1 = cu1 * tu1; + err = Math::Sqrt( temp4, ( tu2 * tu2 + 1.0 ) ); + if ( err != KErrNone ) + { + return KErrGeneral; + } + cu2 = 1.0 / temp4; + x = aPos2Longitude - aPos1Longitude; + + distance = cu1 * cu2; + baz = distance * tu2; + faz = baz * tu1; + + do { + err = Math::Sin( sx, x ); + if ( err != KErrNone ) + { + return KErrGeneral; + } + err = Math::Cos( cx, x ); + if ( err != KErrNone ) + { + return KErrGeneral; + } + tu1 = cu2 * sx; + tu2 = baz - su1 * cu2 * cx; + err = Math::Sqrt( sy, (tu1 * tu1 + tu2 * tu2) ); + if ( err != KErrNone ) + { + return KErrGeneral; + } + cy = distance * cx + faz; + err = Math::ATan( y, sy, cy ); + if ( err != KErrNone ) + { + return KErrGeneral; + } + sa = distance * sx / sy; + c2a = -sa * sa + 1.0; + cz = faz + faz; + if( c2a > 0.0 ) + { + cz = -cz / c2a + cy; + } + e = cz * cz * 2. - 1.0; + c = ( ( -3.0 * c2a + 4.0 ) * KFlattening + 4.0 ) + * c2a * KFlattening / 16.0; + d = x; + x = ( ( e * cy * c + cz ) * sy * c + y ) * sa; + x = ( 1.0 - c ) * x * KFlattening + aPos2Longitude - aPos1Longitude; + + } while( ( Abs( d - x ) ) > KEarthPS ); + + err = Math::Sqrt( x, ( ( 1.0 / r / r - 1.0 ) * c2a + 1.0 ) ); + if ( err != KErrNone ) + { + return KErrGeneral; + } + x += 1.0; + x = ( x - 2.0 ) / x; + c = 1.0 - x; + c = ( x * x / 4.0 + 1.0 ) / c; + d = ( 0.375 * x * x - 1.0 ) * x; + x = e * cy; + distance = 1.0 - e - e; + distance = ( ( ( ( sy * sy * 4.0 - 3.0 ) * distance * cz * d / 6.0 - x ) + * d / 4.0 + cz ) * sy * d + y ) * c * KEarthRadius * r; + + INFO_1( "Distance in meters: %d", distance * 1000.0 ); + + return ( distance * 1000.0 ); // Return distance in meters. + }