527 QContactDetailFilter f(filter); |
527 QContactDetailFilter f(filter); |
528 if (f.detailDefinitionName() == QContactPhoneNumber::DefinitionName && |
528 if (f.detailDefinitionName() == QContactPhoneNumber::DefinitionName && |
529 f.detailFieldName() == QContactPhoneNumber::FieldNumber && |
529 f.detailFieldName() == QContactPhoneNumber::FieldNumber && |
530 f.matchFlags() == QContactFilter::MatchPhoneNumber) |
530 f.matchFlags() == QContactFilter::MatchPhoneNumber) |
531 { |
531 { |
532 QString matchNumber = f.value().toString().right(d->m_phoneNumberMatchLen); |
|
533 QList<QContactPhoneNumber> pns = contact.details<QContactPhoneNumber>(); |
532 QList<QContactPhoneNumber> pns = contact.details<QContactPhoneNumber>(); |
534 foreach (QContactPhoneNumber pn, pns) { |
533 foreach (QContactPhoneNumber pn, pns) { |
535 QString number = pn.number().right(d->m_phoneNumberMatchLen); |
534 // Best matching enabled |
536 if (number == matchNumber) |
535 if(d->m_phoneNumberMatchLen == 0) { |
537 return true; |
536 bool bestMatchFound(false); |
|
537 QString matchingNumber = f.value().toString(); |
|
538 QString numberToMatch = pn.number(); |
|
539 TRAP_IGNORE( |
|
540 bestMatchFound = CntSymbianSimPhoneNumberMatching::isBestMatchL(numberToMatch,matchingNumber); |
|
541 ) |
|
542 if (bestMatchFound) |
|
543 return true; |
|
544 } |
|
545 else { |
|
546 // Default matching |
|
547 QString matchNumber = f.value().toString().right(d->m_phoneNumberMatchLen); |
|
548 QString number = pn.number().right(d->m_phoneNumberMatchLen); |
|
549 if (number == matchNumber) |
|
550 return true; |
|
551 } |
538 } |
552 } |
539 return false; |
553 return false; |
540 } |
554 } |
541 } |
555 } |
542 return QContactManagerEngine::testFilter(filter, contact); |
556 return QContactManagerEngine::testFilter(filter, contact); |
|
557 } |
|
558 |
|
559 /*! |
|
560 Returns whether the supplied \a phonenumber is the best matching number. |
|
561 */ |
|
562 TBool CntSymbianSimPhoneNumberMatching::isBestMatchL(const QString& numberToMatch, const QString& matchingNumber) |
|
563 { |
|
564 bool bestMatchFound(false); |
|
565 TPtrC numberPtr(reinterpret_cast<const TUint16*>(numberToMatch.utf16())); |
|
566 TPtrC matchNumberPtr(reinterpret_cast<const TUint16*>(matchingNumber.utf16())); |
|
567 |
|
568 if (CntSymbianSimPhoneNumberMatching::validateBestMatchingRulesL(numberPtr,matchNumberPtr)) { |
|
569 bestMatchFound = true; |
|
570 } |
|
571 return bestMatchFound; |
543 } |
572 } |
544 |
573 |
545 /*! |
574 /*! |
546 * Executes an asynchronous request so that it will appear synchronous. This is |
575 * Executes an asynchronous request so that it will appear synchronous. This is |
547 * used internally in all synchronous functions. This way we only need to |
576 * used internally in all synchronous functions. This way we only need to |
591 CleanupStack::PushL(repository); |
620 CleanupStack::PushL(repository); |
592 User::LeaveIfError(repository->Get(KTelMatchDigits, matchLength)); |
621 User::LeaveIfError(repository->Get(KTelMatchDigits, matchLength)); |
593 CleanupStack::PopAndDestroy(repository); |
622 CleanupStack::PopAndDestroy(repository); |
594 } |
623 } |
595 |
624 |
|
625 /*! |
|
626 Validates the supplied \a phonenumber against best matching rules. |
|
627 */ |
|
628 TBool CntSymbianSimPhoneNumberMatching::validateBestMatchingRulesL(const TDesC& phoneNumber, const TDesC& matchNumber) |
|
629 { |
|
630 RBuf numberA; |
|
631 numberA.CleanupClosePushL(); |
|
632 numberA.CreateL(matchNumber); |
|
633 TNumberType numberAType = (TNumberType) CntSymbianSimPhoneNumberMatching::formatAndCheckNumberType(numberA); |
|
634 RBuf numberB; |
|
635 numberB.CleanupClosePushL(); |
|
636 numberB.CreateL(phoneNumber); |
|
637 TNumberType numberBType = (TNumberType) CntSymbianSimPhoneNumberMatching::formatAndCheckNumberType(numberB); |
|
638 |
|
639 TBool match = (!numberB.Compare(numberA) || |
|
640 CntSymbianSimPhoneNumberMatching::checkBestMatchingRules(numberA, numberAType, numberB, numberBType) || |
|
641 CntSymbianSimPhoneNumberMatching::checkBestMatchingRules(numberB, numberBType, numberA, numberAType)); |
|
642 |
|
643 // cleanup |
|
644 CleanupStack::PopAndDestroy(2); |
|
645 return match; |
|
646 } |
|
647 |
|
648 /*! |
|
649 Removes non-digit chars except plus form the beginning. |
|
650 Checks if number matches to one of defined types. |
|
651 */ |
|
652 TInt CntSymbianSimPhoneNumberMatching::formatAndCheckNumberType(TDes& number) |
|
653 { |
|
654 _LIT( KOneZeroPattern, "0*" ); |
|
655 _LIT( KTwoZerosPattern, "00*" ); |
|
656 _LIT( KPlusPattern, "+*" ); |
|
657 const TChar KPlus = TChar('+'); |
|
658 const TChar KZero = TChar('0'); |
|
659 const TChar KAsterisk = TChar('*'); |
|
660 const TChar KHash = TChar('#'); |
|
661 |
|
662 for( TInt pos = 0; pos < number.Length(); ++pos ) { |
|
663 TChar chr = number[pos]; |
|
664 if ( !chr.IsDigit() && !( pos == 0 && chr == KPlus ) |
|
665 && !( chr == KAsterisk ) && !( chr == KHash ) ) { |
|
666 number.Delete( pos, 1 ); |
|
667 --pos; |
|
668 } |
|
669 } |
|
670 |
|
671 TInt format; |
|
672 |
|
673 if (!number.Match(KTwoZerosPattern) && number.Length() > 2 && number[2] != KZero) { |
|
674 format = ETwoZeros; |
|
675 } |
|
676 else if (!number.Match(KOneZeroPattern)&& number.Length() > 1 && number[1] != KZero) { |
|
677 format = EOneZero; |
|
678 } |
|
679 else if (!number.Match(KPlusPattern) && number.Length() > 1 && number[1] != KZero) { |
|
680 format = EPlus; |
|
681 } |
|
682 else if (number.Length() > 0 && number[0] != KZero && ( ( TChar ) number[0] ).IsDigit()) { |
|
683 format = EDigit; |
|
684 } |
|
685 else { |
|
686 format = EUnknown; |
|
687 } |
|
688 |
|
689 return format; |
|
690 } |
|
691 |
|
692 TBool CntSymbianSimPhoneNumberMatching::checkBestMatchingRules( |
|
693 const TDesC& numberA, TNumberType numberAType, |
|
694 const TDesC& numberB, TNumberType numberBType ) |
|
695 { |
|
696 TBool result = EFalse; |
|
697 |
|
698 // Rules for matching not identical numbers |
|
699 // Rules details are presented in Best_Number_Matching_Algorithm_Description.doc |
|
700 |
|
701 // rule International-International 1 |
|
702 if (!result && numberAType == EPlus && numberBType == ETwoZeros) { |
|
703 TPtrC numberAPtr = numberA.Right(numberA.Length() - 1); |
|
704 TPtrC numberBPtr = numberB.Right(numberB.Length() - 2); |
|
705 result = !(numberAPtr.Compare(numberBPtr)); |
|
706 if (result) { |
|
707 return result; |
|
708 } |
|
709 } |
|
710 |
|
711 // rule International-International 2 |
|
712 if (numberAType == EPlus && numberBType == EDigit) { |
|
713 TPtrC numberAPtr = numberA.Right( numberA.Length() - 1 ); |
|
714 if (numberAPtr.Length() < numberB.Length()) { |
|
715 TPtrC numberBPtr = numberB.Right( numberAPtr.Length() ); |
|
716 result = !(numberAPtr.Compare(numberBPtr)); |
|
717 if (result) { |
|
718 return result; |
|
719 } |
|
720 } |
|
721 } |
|
722 |
|
723 // rule International-International 3 |
|
724 if (numberAType == ETwoZeros && numberBType == EDigit) { |
|
725 TPtrC numberAPtr = numberA.Right(numberA.Length() - 2); |
|
726 if (numberAPtr.Length() < numberB.Length()) { |
|
727 TPtrC numberBPtr = numberB.Right(numberAPtr.Length()); |
|
728 result = !(numberAPtr.Compare(numberBPtr)); |
|
729 if (result) { |
|
730 return result; |
|
731 } |
|
732 } |
|
733 } |
|
734 |
|
735 // rule International-Operator 1 |
|
736 if (numberAType == EOneZero && numberBType == EPlus |
|
737 || numberAType == EDigit && numberBType == EPlus) { |
|
738 TPtrC numberAPtr; |
|
739 if (numberAType == EOneZero) { |
|
740 numberAPtr.Set(numberA.Right(numberA.Length() - 1)); |
|
741 } |
|
742 else { |
|
743 numberAPtr.Set(numberA); |
|
744 } |
|
745 if (numberAPtr.Length() < numberB.Length() - 1) { |
|
746 TPtrC numberBPtr = numberB.Right(numberAPtr.Length()); |
|
747 result = !(numberAPtr.Compare(numberBPtr)); |
|
748 if (result) { |
|
749 return result; |
|
750 } |
|
751 } |
|
752 } |
|
753 |
|
754 // rule International-Operator 2 |
|
755 if (numberAType == EOneZero && numberBType == ETwoZeros |
|
756 || numberAType == EDigit && numberBType == ETwoZeros) { |
|
757 TPtrC numberAPtr; |
|
758 if (numberAType == EOneZero) { |
|
759 numberAPtr.Set(numberA.Right(numberA.Length() - 1)); |
|
760 } |
|
761 else { |
|
762 numberAPtr.Set(numberA); |
|
763 } |
|
764 if (numberAPtr.Length() < numberB.Length() - 2) { |
|
765 TPtrC numberBPtr = numberB.Right(numberAPtr.Length()); |
|
766 result = !(numberAPtr.Compare(numberBPtr)); |
|
767 if (result) { |
|
768 return result; |
|
769 } |
|
770 } |
|
771 } |
|
772 |
|
773 // rule International-Operator 3 |
|
774 if (numberAType == EOneZero && numberBType == EDigit |
|
775 || numberAType == EDigit && numberBType == EDigit) { |
|
776 TPtrC numberAPtr; |
|
777 if (numberAType == EOneZero) { |
|
778 numberAPtr.Set(numberA.Right( numberA.Length() - 1)); |
|
779 } |
|
780 else { |
|
781 numberAPtr.Set(numberA); |
|
782 } |
|
783 if (numberAPtr.Length() < numberB.Length()) { |
|
784 TPtrC numberBPtr = numberB.Right(numberAPtr.Length()); |
|
785 result = !(numberAPtr.Compare(numberBPtr)); |
|
786 if (result) { |
|
787 return result; |
|
788 } |
|
789 } |
|
790 } |
|
791 |
|
792 // rule Operator-Operator 1 |
|
793 if (numberAType == EOneZero && numberBType == EDigit) { |
|
794 TPtrC numberAPtr = numberA.Right(numberA.Length() - 1); |
|
795 result = !(numberAPtr.Compare(numberB)); |
|
796 if (result) { |
|
797 return result; |
|
798 } |
|
799 } |
|
800 |
|
801 // rule North America Numbering Plan 1 |
|
802 if (numberAType == EDigit && numberBType == EPlus) { |
|
803 TPtrC numberBPtr = numberB.Right(numberB.Length() - 1); |
|
804 result = !(numberA.Compare(numberBPtr)); |
|
805 if (result) { |
|
806 return result; |
|
807 } |
|
808 } |
|
809 |
|
810 // More exceptional acceptance rules can be added here |
|
811 // Keep rules updated in the document Best_Number_Matching_Algorithm_Description.doc |
|
812 |
|
813 return result; |
|
814 } |
|
815 |
596 QContactManagerEngine* CntSymbianSimFactory::engine(const QMap<QString, QString>& parameters, QContactManager::Error* error) |
816 QContactManagerEngine* CntSymbianSimFactory::engine(const QMap<QString, QString>& parameters, QContactManager::Error* error) |
597 { |
817 { |
598 CntSymbianSimEngine *engine = new CntSymbianSimEngine(parameters, error); |
818 CntSymbianSimEngine *engine = new CntSymbianSimEngine(parameters, error); |
599 if(*error != QContactManager::NoError) { |
819 if(*error != QContactManager::NoError) { |
600 delete engine; |
820 delete engine; |