contextframework/cfw/src/basicoperationsplugin/cfinrange.cpp
changeset 0 2e3d3ce01487
equal deleted inserted replaced
-1:000000000000 0:2e3d3ce01487
       
     1 /*
       
     2 * Copyright (c) 2002-2008 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  CCFInRange class implementation.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 // INCLUDES
       
    21 #include "cfinrange.h"
       
    22 #include "cfcontextobject.h"
       
    23 #include "cfcontextoperationutils.h"
       
    24 #include "cfbasicoptrace.h"
       
    25 
       
    26 #include <e32math.h>
       
    27 #include <gmxmlnode.h>
       
    28 
       
    29 // CONSTANTS
       
    30 _LIT( KScriptInRangeName, "inRange" );
       
    31 
       
    32 const TReal KEarthRadius = 6378.137;
       
    33 const TReal KFlattening  = 1.000000 / 298.257223563; // Earth flattening (WGS84)
       
    34 const TReal KEarthPS     = 0.000000000005;
       
    35 
       
    36 // ============================ MEMBER FUNCTIONS ===============================
       
    37 
       
    38 // -----------------------------------------------------------------------------
       
    39 // CCFInRange::CCFInRange
       
    40 // C++ default constructor can NOT contain any code, that
       
    41 // might leave.
       
    42 // -----------------------------------------------------------------------------
       
    43 //
       
    44 CCFInRange::CCFInRange( MCFOperationServices& aServices,
       
    45     CCFOperationNode* aParent,
       
    46     HBufC* aName,
       
    47     HBufC* aSource,
       
    48     const CCFContextOperation::TCmpType aType )
       
    49     :   CCFContextOperation( aServices, aParent, aName, aSource ),
       
    50         iType( aType )
       
    51     {
       
    52     FUNC_LOG;
       
    53     }
       
    54 
       
    55 // -----------------------------------------------------------------------------
       
    56 // CCFInRange::ConstructL
       
    57 // Symbian 2nd phase constructor can leave.
       
    58 // -----------------------------------------------------------------------------
       
    59 //
       
    60 void CCFInRange::ConstructL( const TDesC& aMinVal, const TDesC& aMaxVal )
       
    61     {
       
    62     FUNC_LOG;
       
    63 
       
    64     iMinVal = aMinVal.AllocL();
       
    65     iMaxVal = aMaxVal.AllocL();
       
    66     }
       
    67 
       
    68 // -----------------------------------------------------------------------------
       
    69 // CCFInRange::NewL
       
    70 // Two-phased constructor.
       
    71 // -----------------------------------------------------------------------------
       
    72 //
       
    73 CCFInRange* CCFInRange::NewL( MCFOperationServices& aServices,
       
    74     CCFOperationNode* aParent,
       
    75     TDesC& aName,
       
    76     TDesC& aSource,
       
    77     const CCFContextOperation::TCmpType aType,
       
    78     const TDesC& aMinVal,
       
    79     const TDesC& aMaxVal )
       
    80     {
       
    81     FUNC_LOG;
       
    82 
       
    83     CCFInRange* self
       
    84         = NewLC( aServices, aParent, aName, aSource, aType, aMinVal, aMaxVal );
       
    85     CleanupStack::Pop( self );
       
    86     return self;
       
    87     }
       
    88 
       
    89 // -----------------------------------------------------------------------------
       
    90 // CCFInRange::NewLC
       
    91 // Two-phased constructor.
       
    92 // -----------------------------------------------------------------------------
       
    93 //
       
    94 CCFInRange* CCFInRange::NewLC( MCFOperationServices& aServices,
       
    95     CCFOperationNode* aParent,
       
    96     TDesC& aName,
       
    97     TDesC& aSource,
       
    98     const CCFContextOperation::TCmpType aType,
       
    99     const TDesC& aMinVal,
       
   100     const TDesC& aMaxVal )
       
   101     {
       
   102     FUNC_LOG;
       
   103 
       
   104     HBufC* name = aName.AllocLC();
       
   105     HBufC* source = aSource.AllocLC();
       
   106     CCFInRange* self =
       
   107         new( ELeave ) CCFInRange( aServices, aParent, name, source, aType );
       
   108     CleanupStack::PushL( self );
       
   109     self->ConstructL( aMinVal, aMaxVal );
       
   110 
       
   111     // Cleanup
       
   112     CleanupStack::Pop( self );
       
   113     CleanupStack::Pop( source );
       
   114     CleanupStack::Pop( name );
       
   115 
       
   116     CleanupStack::PushL( self );
       
   117     return self;
       
   118     }
       
   119 
       
   120 // -----------------------------------------------------------------------------
       
   121 // CCFInRange::ParseL
       
   122 // Construction with parsing from a DOM node.
       
   123 // -----------------------------------------------------------------------------
       
   124 //
       
   125 CCFInRange* CCFInRange::ParseL( MCFOperationServices& aServices,
       
   126     CCFOperationNode* aParent,
       
   127     CMDXMLNode& aNode )
       
   128     {
       
   129     FUNC_LOG;
       
   130 
       
   131     if ( aNode.NodeName().CompareF( KScriptInRangeName ) != 0 )
       
   132         {
       
   133         return NULL; // Cannot create in range operation from the given node.
       
   134         }
       
   135 
       
   136     TPtrC contextSource;
       
   137     TPtrC contextType;
       
   138     TPtrC contextValue;
       
   139     TCmpType cmpMinType( CCFContextOperation::EInvalidCmpType );
       
   140     TCmpType cmpMaxType( CCFContextOperation::EInvalidCmpType );
       
   141     TPtrC minValue;
       
   142     TPtrC maxValue;
       
   143     TInt contextLevelDelay( 0 );
       
   144 
       
   145     TBool contextRefOK( EFalse );
       
   146     TBool minArgOK( EFalse );
       
   147     TBool maxArgOK( EFalse );
       
   148     TBool argsOK( ETrue ); // Will be set to false if unknown nodes detected.
       
   149     CMDXMLNode* child = aNode.FirstChild();
       
   150     while ( child )
       
   151         {
       
   152         if ( child->NodeType() == CMDXMLNode::EElementNode )
       
   153             {
       
   154             // Mandatory EElementNode order: 1. contextRef, 2. minArg, 3. maxArg
       
   155             if ( !contextRefOK )
       
   156                 {
       
   157                 contextRefOK = CFContextOperationUtils::ParseContextRef(
       
   158                         *child,
       
   159                         contextSource,
       
   160                         contextType,
       
   161                         contextValue,
       
   162                         contextLevelDelay );
       
   163                 if ( !contextRefOK )
       
   164                     {
       
   165                     argsOK = EFalse;
       
   166                     break;
       
   167                     }
       
   168                 }
       
   169             else if ( !minArgOK )
       
   170                 {
       
   171                 minArgOK = CFContextOperationUtils::ParseComparisonTypeValue(
       
   172                         *child,
       
   173                         cmpMinType,
       
   174                         minValue );
       
   175                 if ( !minArgOK )
       
   176                     {
       
   177                     argsOK = EFalse;
       
   178                     break;
       
   179                     }
       
   180                 }
       
   181             else if ( !maxArgOK )
       
   182                 {
       
   183                 maxArgOK = CFContextOperationUtils::ParseComparisonTypeValue(
       
   184                         *child,
       
   185                         cmpMaxType,
       
   186                         maxValue );
       
   187                 if ( !maxArgOK )
       
   188                     {
       
   189                     argsOK = EFalse;
       
   190                     break;
       
   191                     }
       
   192                 }
       
   193             else
       
   194                 {
       
   195                 argsOK = EFalse; // Unsupported node encountered.
       
   196                 break;
       
   197                 }
       
   198             }
       
   199         else if ( child->NodeType() != CMDXMLNode::ECommentNode )
       
   200             {
       
   201             argsOK = EFalse; // Unsupported node encountered.
       
   202             break;
       
   203             }
       
   204         child = child->NextSibling();
       
   205         }
       
   206 
       
   207     TBool parsed( EFalse );
       
   208     if ( argsOK && contextRefOK && minArgOK && maxArgOK )
       
   209         {
       
   210         if ( cmpMinType == cmpMaxType && !contextValue.Length() )
       
   211             {
       
   212             parsed = ETrue;
       
   213             }
       
   214         }
       
   215 
       
   216     CCFInRange* self = NULL;
       
   217     if ( parsed )
       
   218         {
       
   219         self = NewL( aServices,
       
   220                 aParent,
       
   221                 contextType,
       
   222                 contextSource,
       
   223                 cmpMinType,
       
   224                 minValue,
       
   225                 maxValue );
       
   226         if ( contextLevelDelay )
       
   227             {
       
   228             self->iContextLevelDelay = contextLevelDelay;
       
   229             }
       
   230         }
       
   231     else
       
   232         {
       
   233         INFO( "CCFInRange::ParseL - Unsupported arguments" );
       
   234         }
       
   235 
       
   236     CREATE_DOM_INFO( self, aNode );
       
   237 
       
   238     return self;
       
   239     }
       
   240 
       
   241 
       
   242 // Destructor
       
   243 CCFInRange::~CCFInRange()
       
   244     {
       
   245     FUNC_LOG;
       
   246 
       
   247     delete iMinVal;
       
   248     delete iMaxVal;
       
   249     }
       
   250 
       
   251 // -----------------------------------------------------------------------------
       
   252 // CCFInRange::IsTrueL
       
   253 // -----------------------------------------------------------------------------
       
   254 //
       
   255 TBool CCFInRange::IsTrueL( const CCFContextObject& aContextObject )
       
   256     {
       
   257     FUNC_LOG;
       
   258 
       
   259     TBool value( EFalse );
       
   260     switch ( iType )
       
   261         {
       
   262         case CCFContextOperation::EIntCmp:
       
   263             {
       
   264             TInt min = CFContextOperationUtils::StringToIntL( *iMinVal );
       
   265             TInt max = CFContextOperationUtils::StringToIntL( *iMaxVal );
       
   266             TInt cmp = CFContextOperationUtils::StringToIntL(
       
   267                     aContextObject.Value() );
       
   268             value = ( cmp >= min ) && ( cmp <= max );
       
   269             break;
       
   270             }
       
   271         case CCFContextOperation::ETimeCmp:
       
   272             {
       
   273             TTime min = CFContextOperationUtils::StringToTimeL( *iMinVal );
       
   274             TTime max = CFContextOperationUtils::StringToTimeL( *iMaxVal );
       
   275             TTime cmp = CFContextOperationUtils::StringToTimeL(
       
   276                     aContextObject.Value() );
       
   277             value = ( cmp >= min ) && ( cmp <= max );
       
   278             break;
       
   279             }
       
   280         case CCFContextOperation::EPositionCmp:
       
   281             {
       
   282             // local variable declaration & initialization
       
   283             TReal cmpLatitude( KErrNone ), cmpLongitude( KErrNone ),
       
   284                   objLatitude( KErrNone ), objLongitude( KErrNone );
       
   285             TReal calculatedDistance( KErrNone );
       
   286             TReal locationRadius( KErrNone );
       
   287             // get values contained by scripts
       
   288             CFContextOperationUtils::PositionToRealsL(
       
   289                 *iMinVal,
       
   290                 cmpLatitude,
       
   291                 cmpLongitude );
       
   292             CFContextOperationUtils::PositionToRealsL(
       
   293                 aContextObject.Value(),
       
   294                 objLatitude,
       
   295                 objLongitude );
       
   296             locationRadius = CFContextOperationUtils::StringToRealL(
       
   297                     *iMaxVal );
       
   298             calculatedDistance = EllipsoidDistanceBetweenTwoPositions(
       
   299                 cmpLatitude,
       
   300                 cmpLongitude,
       
   301                 objLatitude,
       
   302                 objLongitude );
       
   303             // error occurred; leave
       
   304             if ( calculatedDistance == KErrGeneral )
       
   305                 {
       
   306                 User::Leave( static_cast< TInt > ( calculatedDistance ) );
       
   307                 }
       
   308             value = ( calculatedDistance <= locationRadius );
       
   309             break;
       
   310             }
       
   311         case CCFContextOperation::EFloatCmp:
       
   312             {
       
   313             TReal min = CFContextOperationUtils::StringToRealL( *iMinVal );
       
   314             TReal max = CFContextOperationUtils::StringToRealL( *iMaxVal );
       
   315             TReal cmp = CFContextOperationUtils::StringToRealL(
       
   316                     aContextObject.Value() );
       
   317             value = ( cmp >= min ) && ( cmp <= max );
       
   318             break;
       
   319             }
       
   320         case CCFContextOperation::EStringCmp:
       
   321         default:
       
   322             {
       
   323             value = ( aContextObject.Value() >= ( *iMinVal ) ) &&
       
   324                 ( aContextObject.Value() <= ( *iMaxVal ) );
       
   325             break;
       
   326             }
       
   327 
       
   328         }
       
   329 
       
   330     return value;
       
   331     }
       
   332 
       
   333 // -----------------------------------------------------------------------------
       
   334 // CCFInRange::EllipsoidDistanceBetweenTwoPoints
       
   335 // Method that takes two GPS positions as (latitude,longitude)-pairs
       
   336 // (units==DEGREES) and calculates their ellipsoid distance.
       
   337 // -----------------------------------------------------------------------------
       
   338 //
       
   339 TReal CCFInRange::EllipsoidDistanceBetweenTwoPositions( TReal aPos1Latitude,
       
   340     TReal aPos1Longitude,
       
   341     TReal aPos2Latitude,
       
   342     TReal aPos2Longitude )
       
   343     {
       
   344     FUNC_LOG;
       
   345 
       
   346     TInt err( KErrNone );
       
   347     TReal distance = 0.0;
       
   348     TReal faz, baz;
       
   349     TReal r = 1.0 - KFlattening;
       
   350     TReal tu1, tu2, cu1, su1, cu2, x, sx, cx, sy, cy, y, sa, c2a, cz, e, c, d;
       
   351     TReal cosy1, cosy2;
       
   352 
       
   353     // Make sure the coordinates differ.
       
   354     if ( ( aPos1Longitude == aPos2Longitude ) &&
       
   355          ( aPos1Latitude  == aPos2Latitude  ) )
       
   356         {
       
   357         return distance;
       
   358         }
       
   359 
       
   360     // Convert longitude and latitudes to radians.
       
   361     aPos1Longitude *= KDegToRad;
       
   362     aPos1Latitude  *= KDegToRad;
       
   363     aPos2Longitude *= KDegToRad;
       
   364     aPos2Latitude  *= KDegToRad;
       
   365 
       
   366     err = Math::Cos( cosy1, aPos1Latitude );
       
   367     if ( err != KErrNone )
       
   368         {
       
   369         return KErrGeneral;
       
   370         }
       
   371     err = Math::Cos( cosy2, aPos2Latitude );
       
   372     if ( err != KErrNone )
       
   373         {
       
   374         return KErrGeneral;
       
   375         }
       
   376 
       
   377     // Assure positive values since this is used as division denominator.
       
   378     if ( cosy1 == 0.0 )
       
   379         {
       
   380         cosy1 = 0.0000000001;
       
   381         }
       
   382     // Assure positive values since this is used as division denominator.
       
   383     if ( cosy2 == 0.0 )
       
   384         {
       
   385         cosy2 = 0.0000000001;
       
   386         }
       
   387 
       
   388     TReal temp1, temp2, temp3, temp4;
       
   389     err = Math::Sin( temp1, aPos1Latitude );
       
   390     if ( err != KErrNone )
       
   391         {
       
   392         return KErrGeneral;
       
   393         }
       
   394     err = Math::Sin( temp2, aPos2Latitude );
       
   395     if ( err != KErrNone )
       
   396         {
       
   397         return KErrGeneral;
       
   398         }
       
   399 
       
   400     tu1 = r * temp1 / cosy1;
       
   401     tu2 = r * temp2 / cosy2;
       
   402     err = Math::Sqrt( temp3, ( tu2 * tu2 + 1.0 ) );
       
   403     if ( err != KErrNone )
       
   404         {
       
   405         return KErrGeneral;
       
   406         }
       
   407     cu1 = 1.0 / temp3;
       
   408     su1 = cu1 * tu1;
       
   409     err = Math::Sqrt( temp4, ( tu2 * tu2 + 1.0 ) );
       
   410     if ( err != KErrNone )
       
   411         {
       
   412         return KErrGeneral;
       
   413         }
       
   414     cu2 = 1.0 / temp4;
       
   415     x = aPos2Longitude - aPos1Longitude;
       
   416 
       
   417     distance = cu1 * cu2;
       
   418     baz = distance * tu2;
       
   419     faz = baz * tu1;
       
   420 
       
   421     do  {
       
   422         err = Math::Sin( sx, x );
       
   423         if ( err != KErrNone )
       
   424             {
       
   425             return KErrGeneral;
       
   426             }
       
   427         err = Math::Cos( cx, x );
       
   428         if ( err != KErrNone )
       
   429             {
       
   430             return KErrGeneral;
       
   431             }
       
   432         tu1 = cu2 * sx;
       
   433         tu2 = baz - su1 * cu2 * cx;
       
   434         err = Math::Sqrt( sy, (tu1 * tu1 + tu2 * tu2) );
       
   435         if ( err != KErrNone )
       
   436             {
       
   437             return KErrGeneral;
       
   438             }
       
   439         cy = distance * cx + faz;
       
   440         err = Math::ATan( y, sy, cy );
       
   441         if ( err != KErrNone )
       
   442             {
       
   443             return KErrGeneral;
       
   444             }
       
   445         sa = distance * sx / sy;
       
   446         c2a = -sa * sa + 1.0;
       
   447         cz = faz + faz;
       
   448         if( c2a > 0.0 )
       
   449             {
       
   450             cz = -cz / c2a + cy;
       
   451             }
       
   452         e = cz * cz * 2. - 1.0;
       
   453         c = ( ( -3.0 * c2a + 4.0 ) * KFlattening + 4.0 )
       
   454             * c2a * KFlattening / 16.0;
       
   455         d = x;
       
   456         x = ( ( e * cy * c + cz ) * sy * c + y ) * sa;
       
   457         x = ( 1.0 - c ) * x * KFlattening + aPos2Longitude - aPos1Longitude;
       
   458 
       
   459         } while( ( Abs( d - x ) ) > KEarthPS );
       
   460 
       
   461     err = Math::Sqrt( x, ( ( 1.0 / r / r - 1.0 ) * c2a + 1.0 ) );
       
   462     if ( err != KErrNone )
       
   463         {
       
   464         return KErrGeneral;
       
   465         }
       
   466     x += 1.0;
       
   467     x = ( x - 2.0 ) / x;
       
   468     c = 1.0 - x;
       
   469     c = ( x * x / 4.0 + 1.0 ) / c;
       
   470     d = ( 0.375 * x * x - 1.0 ) * x;
       
   471     x = e * cy;
       
   472     distance = 1.0 - e - e;
       
   473     distance = ( ( ( ( sy * sy * 4.0 - 3.0 ) * distance * cz * d / 6.0 - x )
       
   474             * d / 4.0 + cz ) * sy * d + y ) * c * KEarthRadius * r;
       
   475 
       
   476     INFO_1( "Distance in meters: %d", distance * 1000.0 );
       
   477 
       
   478     return ( distance * 1000.0 ); // Return distance in meters.
       
   479     }