contextframework/cfw/src/basicoperationsplugin/cfinrange.cpp
changeset 0 2e3d3ce01487
--- /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 <e32math.h>
+#include <gmxmlnode.h>
+
+// 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.
+    }