/*
 * Returns an sql query to fetch contact item IDs for all the contact items which may contain
 * the specified telephone number in a telephone, fax or SMS type field.
 *
 * This is improved version of createMatchPhoneNumberQuery method.
 * The number is compared starting from the right side of the number and 
 * the method returns an array of candidate matches.  
 * Punctuation (e.g. spaces) and other alphabetic characters are ignored
 * when comparing. Leading zeros are removed. Digits are compared up to 
 * the length of shorter number.
 */
void CntFilterDetail::bestMatchPhoneNumberQuery(const QContactFilter& filter,
                                                QString& sqlQuery,
                                                QContactManager::Error* error)
    {
    if (!filterSupported(filter) ) {
          *error = QContactManager::NotSupportedError;
          return;
        }
              
    QContactDetailFilter detailFilter(filter);
    QString number((detailFilter.value()).toString());
    TPtrC numberPtr(reinterpret_cast<const TUint16*>(number.utf16()));
    
    const TInt KUpperMaxLength = KMaxPhoneMatchLength - KLowerSevenDigits;
    TMatch phoneDigits = createPaddedPhoneDigits(numberPtr, KLowerSevenDigits, KUpperMaxLength, error);
    
    if (*error == QContactManager::NoError) {
        // select fields for contacts that match phone lookup
        //  SELECT contact_id, extra_value FROM comm_addr
        //      WHERE value = [value string] AND type = [type value];
        //
        QString type =  QString(" type = %1").arg(CntDbInfo::EPhoneNumber);
        QString value =  QString(" value = %1").arg(phoneDigits.iLowerSevenDigits);
        QString whereClause = " WHERE" + value + " AND" + type;
        sqlQuery = "SELECT contact_id, extra_value FROM comm_addr" + whereClause;
        
        QList<QPair<QContactLocalId, QString> > contactMatches =  m_srvConnection.searchPhoneNumbers(sqlQuery, error);
        
        // Check if search query was successful
        if (*error != QContactManager::NoError) {
              return;
            }
        
        QStringList list;
        for (int i=0; i<contactMatches.count(); ++i) {
            // Check the upper digits...
            TInt32 number = phoneDigits.iUpperDigits;
            QString extraValue = contactMatches.at(i).second;
            TPtrC extValString(reinterpret_cast<const TUint16*>(extraValue.utf16()));
            
            TInt32 storedUpperDigits(0);
            if (TLex(extValString).Val(storedUpperDigits) == KErrNone) {
                
                TInt32 stored = storedUpperDigits;
                TBool nonZeroInStoredFound = EFalse;
                TBool nonZeroInNumberFound = EFalse;
                while ((number != 0) && (stored != 0)) {
                    nonZeroInNumberFound |= (number % 10 != 0);
                    nonZeroInStoredFound |= (stored % 10 != 0);
                    if (nonZeroInStoredFound && nonZeroInNumberFound) {
                        break;
                    }
                    number /= 10;
                    stored /= 10;
                }
                
                if ((phoneDigits.iUpperDigits == 0) || (storedUpperDigits == 0) ||
                     (number == stored)) {
                    list.append(QString("%1").arg(contactMatches.at(i).first));
                }
            }
            else {
                *error = QContactManager::UnspecifiedError;
                return;
            }
        }
        // Recreate query to fetch all match ids
        // SELECT DISTINCT contact_id FROM contact WHERE contact_id in (
        //      ..
        // )  
        QString ids = list.join(" ,");
        sqlQuery = "SELECT DISTINCT contact_id FROM contact WHERE contact_id in (";
        sqlQuery += ids;
        sqlQuery += ')';
        }
    }
/*
 * Creates an sql query to fetch contact item IDs for all the contact items
 * which may contain the specified telephone number in a telephone, fax
 * or SMS type field.
 *
 * The comparison method used is not exact.  The number is compared starting from
 * the right side of the number and the method returns an array of candidate
 * matches.  Punctuation (e.g. spaces) and other alphabetic characters are ignored
 * when comparing.
 * 
 * Note that due to the way numbers are stored in the database, it is recommended
 * that at least 7 match digits are specified even when matching a number
 * containing fewer digits.  Failure to follow this guideline may (depending on the
 * database contents) mean that the function will not return the expected Contact
 * IDs.
 */
void CntFilterDetail::createMatchPhoneNumberQuery(
                                      const QContactFilter& filter,
                                      QString& sqlQuery,
                                      QContactManager::Error* error)

{
    if (!filterSupported(filter) ) {
      *error = QContactManager::NotSupportedError;
      return;
    }
          
    QContactDetailFilter detailFilter(filter);
    QString number((detailFilter.value()).toString());
    TPtrC numberPtr(reinterpret_cast<const TUint16*>(number.utf16()));
    
    TInt matchLengthFromRight(KDefaultMatchLength);
    // no need to propagate error, we can use the default match length
    TRAP_IGNORE(getMatchLengthL(matchLengthFromRight));
    
    TInt numLowerDigits = matchLengthFromRight;
    TInt numUpperDigits = 0;
    
    if (numLowerDigits > KLowerSevenDigits) {
        numLowerDigits = KLowerSevenDigits;
        numUpperDigits = matchLengthFromRight - KLowerSevenDigits;
    }
    else if (numLowerDigits == 0) {
        // best match phonenumbers
        numLowerDigits = KLowerSevenDigits;
    }
    
    TMatch phoneDigits = createPaddedPhoneDigits(
                          numberPtr, numLowerDigits, numUpperDigits, error);
    
    if (*error == QContactManager::NoError) {
        // select fields for contacts that match phone lookup
        //  SELECT contact_id FROM comm_addr
        //      WHERE value = [value string] AND type = [type value];
        //
        QString type =  QString(" type = %1").arg(CntDbInfo::EPhoneNumber);
        QString value =  QString(" value = %1").arg(phoneDigits.iLowerSevenDigits);
        QString whereClause = " WHERE" + value + " AND" + type;
        if (matchLengthFromRight <= KLowerSevenDigits) {
            // Matching 7 or less digits...
            sqlQuery = "SELECT contact_id FROM comm_addr" + whereClause;
        }
        else {
            // Checking the upper digits...
        
            // select fields for contacts that match phone lookup
            //  SELECT contact_id, extra_value FROM comm_addr
            //      WHERE value = [value string] AND type = [type value];
            //
            QString type =  QString(" type = %1").arg(CntDbInfo::EPhoneNumber);
            QString value =  QString(" value = %1").arg(phoneDigits.iLowerSevenDigits);
            QString whereClause = " WHERE" + value + " AND" + type;
            sqlQuery = "SELECT contact_id, extra_value FROM comm_addr" + whereClause;
            
            QList<QPair<QContactLocalId, QString> > contactMatches =  m_srvConnection.searchPhoneNumbers(sqlQuery, error);
            
            // Check if search query was successful
            if (*error != QContactManager::NoError) {
                  return;
                }
            
            QStringList list;
            for (int i=0; i<contactMatches.count(); ++i) {
                // Check the upper digits...
                TInt32 storedUpperDigits(0);
                QString extraValue = contactMatches.at(i).second;
                TPtrC extValString(reinterpret_cast<const TUint16*>(extraValue.utf16()));
                if (TLex(extValString).Val(storedUpperDigits) == KErrNone) {
                
                    const TInt KDigitsToRemove = KMaxPhoneMatchLength - KLowerSevenDigits - phoneDigits.iNumUpperDigits;
                    for (TInt j = 0; j < KDigitsToRemove; ++j) {
                        // repeatedly divide by 10 to lop off the appropriate number of digits from the right
                        storedUpperDigits /= 10;
                    }
                
                    storedUpperDigits = TMatch::padOutPhoneMatchNumber(storedUpperDigits, KDigitsToRemove);
                
                    if (phoneDigits.iUpperDigits == storedUpperDigits) {
                        list.append(QString("%1").arg(contactMatches.at(i).first));
                    }
                }
                else {
                    *error = QContactManager::UnspecifiedError;
                }
            }
            // Recreate query to fetch all match ids
            // SELECT DISTINCT contact_id FROM contact WHERE contact_id in (
            //      ..
            // )  
            QString ids = list.join(" ,");
            sqlQuery = "SELECT DISTINCT contact_id FROM contact WHERE contact_id in (";
            sqlQuery += ids;
            sqlQuery += ')';
        }
      
        // refine search
        if (bestMatchingEnabled()) {
            QList<QContactLocalId> list =  m_srvConnection.searchContacts(sqlQuery,error);
            QList<QContactLocalId> bestMatchingIds;
            if (*error == QContactManager::NoError) {
                TRAP_IGNORE(
                        bestMatchingIds = getBestMatchPhoneNumbersL(number, list, error);
                )
                if (bestMatchingIds.count()>0) {
                    // recreate query
                    QString selectQuery = " SELECT contact_id FROM comm_addr WHERE contact_id in (";
                    QString ids = QString("%1").arg(bestMatchingIds.at(0));
                    for(int i=1; i<bestMatchingIds.count(); ++i) {
                        ids += QString(" ,%1").arg(bestMatchingIds.at(i));
                    }
                    selectQuery += ids + ')';
                    sqlQuery = selectQuery;
                }
                else {
                    // empty list
                    QString selectQuery = " SELECT contact_id FROM comm_addr WHERE contact_id in (null)";
                    sqlQuery = selectQuery;
                }
            }
Beispiel #3
0
/**
 * Extracts the real phone number from a contacts phone number field.
 * This method strips away any DTMF strings or extended services. An empty
 * descriptor is returned in aRawNumber if the field doesn't have a valid phone
 * number.
 *
 * @param aTextualNumber Descriptor containing a contacts model phone number field
 * @param aRawNumber Descriptor to write the raw number to (loaned by caller)
 */
void CContactDefaultPhoneNumberParser::ExtractRawNumber(const TDesC& aTextualNumber, TDes& aRawNumber)
{
    aRawNumber.Zero();

    TInt length = aTextualNumber.Length();
    if (length==0)
    {
        return;
    }


    TPtrC numberPtr( aTextualNumber );
    TUint firstChar = numberPtr[0];

    //gobble spaces
    while (TChar(firstChar).IsSpace())
    {
        --length;
        if (length==0)
        {
            return;
        }

        numberPtr.Set(numberPtr.Right(length));
        firstChar = numberPtr[0];
    }

    // Get left hand side
    if ( firstChar == KSymbolAsterisk || firstChar == KSymbolHash )
    {
        //Check if there is plus on first five chars:
        TInt newStartPlace = numberPtr.Locate( KSymbolPlus );
        if ( newStartPlace>=KPlusWithinChars || newStartPlace==KErrNotFound )
        {
            // There is always star or hash...
            newStartPlace = Max( numberPtr.LocateReverse(KSymbolAsterisk ) ,numberPtr.LocateReverse( KSymbolHash) );
        }

        length = length - newStartPlace -1;
        if ( length <= 0 )
        {
            return;
        }
        numberPtr.Set( numberPtr.Right( length ) );
        firstChar = numberPtr[0];
    }

    //test condition to satisfy the removal of '(' the next if
    //statement removes the '+' if needed
    if ( firstChar == KSymbolOpenBrace )
    {
        length--;
        numberPtr.Set( numberPtr.Right( length ) );
        // This may be the only character in the descriptor so only access if
        // 1 or more characters left.
        if (length > 0 )
        {
            firstChar = numberPtr[0];
        }
    }

    if ( firstChar == KSymbolPlus )
    {
        length--;
        numberPtr.Set( numberPtr.Right( length ) );
    }

    if (length==0)
    {
        return;
    }

    // Find right hand side
    TLex numberLexer( numberPtr );
    for ( ; ; )
    {
        TChar nextChar = numberLexer.Peek();
        if ( !nextChar )
        {
            break;
        }

        if ( nextChar.IsDigit() )
        {
            aRawNumber.Append( nextChar );
            numberLexer.Inc();
        }
        else if ( nextChar == KSymbolAsterisk || nextChar == KSymbolHash )
        {
            aRawNumber.Zero();
            return;
        }
        else
        {
            nextChar.LowerCase();
            if ( nextChar == KSymbolPause
                    || nextChar == KSymbolWait
                    || nextChar == KSymbolPlus)
            {
                break;
            }
            numberLexer.Inc();
        }
    }
}