/android/import-contacts

To get this branch, use:
bzr branch http://bzr.ed.am/android/import-contacts

« back to all changes in this revision

Viewing changes to src/org/waxworlds/edam/importcontacts/Importer.java

  • Committer: edam
  • Date: 2011-05-02 18:28:24 UTC
  • Revision ID: edam@waxworlds.org-20110502182824-acgdi3qfxfzqgely
- fixed logic for vcard field types (home, work, cell, etc) so it works
- updated NEWS and TODO
- rewrote most of ContactsCache, including a new ContactIdentifier class to identify contacts in the cache and new cache building code
- contacts now identified in the same way that Andoid displays them (by name, or organisation, or number, or email, in that order)
- propper handling and support for organisations and titles
- validation of imported contact now done by Importer, not VcfImporter
- separated sanitisation and normalisation (for cache lookups)
- generacised PhoneData, EmailData and AddressData classes
- ContactData is now aware of primary numbers, emails and organisations (defaults to the first prefrred one seen, or the first one seen where none is preferred)

Show diffs side-by-side

added added

removed removed

55
55
        private int _last_merge_decision;
56
56
        private boolean _abort = false;
57
57
        private boolean _is_finished = false;
58
 
        private ContactsCache _contacts_cache = null;
 
58
        private ContactsCache _contactsCache = null;
59
59
 
60
60
        @SuppressWarnings("serial")
61
61
        protected class ContactNeedsMoreInfoException extends Exception
394
394
                        setProgressMessage( R.string.doit_caching );
395
395
 
396
396
                        // build a cache of existing contacts
397
 
                        _contacts_cache = new ContactsCache();
398
 
                        _contacts_cache.buildCache( _doit );
 
397
                        _contactsCache = new ContactsCache();
 
398
                        _contactsCache.buildCache( _doit );
399
399
 
400
400
                        // do the import
401
401
                        onImport();
522
522
                        Doit.MESSAGE_SETPROGRESSMESSAGE, getText( res ) ) );
523
523
        }
524
524
 
525
 
        protected void setProgressMax( int max_progress )
 
525
        protected void setProgressMax( int maxProgress )
526
526
                        throws AbortImportException
527
527
        {
528
528
                checkAbort();
529
529
                _doit._handler.sendMessage( Message.obtain(
530
530
                        _doit._handler, Doit.MESSAGE_SETMAXPROGRESS,
531
 
                        new Integer( max_progress ) ) );
 
531
                        new Integer( maxProgress ) ) );
532
532
        }
533
533
 
534
 
        protected void setTmpProgress( int tmp_progress )
535
 
                throws AbortImportException
 
534
        protected void setTmpProgress( int tmpProgress ) throws AbortImportException
536
535
        {
537
536
                checkAbort();
538
537
                _doit._handler.sendMessage( Message.obtain(
539
538
                        _doit._handler, Doit.MESSAGE_SETTMPPROGRESS,
540
 
                        new Integer( tmp_progress ) ) );
 
539
                        new Integer( tmpProgress ) ) );
541
540
        }
542
541
 
543
542
        protected void setProgress( int progress ) throws AbortImportException
594
593
                {
595
594
                case Doit.ACTION_KEEP:
596
595
                        // if we keep contacts on duplicate, we better check for one
597
 
                        return !_contacts_cache.canLookup( identifier );
 
596
                        return !_contactsCache.canLookup( identifier );
598
597
 
599
598
                case Doit.ACTION_PROMPT:
600
599
                        // if we are prompting on duplicate, we better check for one and if
601
600
                        // the contact doesn'te exist, we want to import it
602
 
                        if( !_contacts_cache.canLookup( identifier ) )
 
601
                        if( !_contactsCache.canLookup( identifier ) )
603
602
                                return true;
604
603
 
605
604
                        // ok, it exists, so do prompt
641
640
//                      finish( ACTION_ABORT );
642
641
 
643
642
                ContentValues values = new ContentValues();
644
 
                boolean ui_informed = false;
 
643
                boolean uiInformed = false;
645
644
                Long id = null;
646
645
 
647
646
                // give the contact a chance to finalise it's data
652
651
                // the cache with it
653
652
                ContactsCache.CacheIdentifier identifier =
654
653
                        ContactsCache.createIdentifier( contact );
655
 
                if( identifier != null ) id = (Long)_contacts_cache.lookup( identifier );
 
654
                if( identifier != null ) id = (Long)_contactsCache.lookup( identifier );
656
655
 
657
656
                // does contact exist already?
658
657
                if( id != null )
661
660
                        if( _last_merge_decision == Doit.ACTION_KEEP ) return;
662
661
 
663
662
                        // get contact's URI
664
 
                        Uri contact_uri = ContentUris.withAppendedId(
 
663
                        Uri contactUri = ContentUris.withAppendedId(
665
664
                                Contacts.People.CONTENT_URI, id );
666
665
 
667
666
                        // should we destroy the existing contact before importing?
668
667
                        if( _last_merge_decision == Doit.ACTION_OVERWRITE )
669
668
                        {
670
669
                                // remove from device
671
 
                                _doit.getContentResolver().delete( contact_uri, null, null );
 
670
                                _doit.getContentResolver().delete( contactUri, null, null );
672
671
 
673
672
                                // update cache
674
 
                                _contacts_cache.removeLookup( identifier );
675
 
                                _contacts_cache.removeAssociatedData( id );
 
673
                                _contactsCache.removeLookup( identifier );
 
674
                                _contactsCache.removeAssociatedData( id );
676
675
 
677
676
                                // show that we're overwriting a contact
678
677
                                _doit._handler.sendEmptyMessage(
679
678
                                                Doit.MESSAGE_CONTACTOVERWRITTEN );
680
 
                                ui_informed = true;
 
679
                                uiInformed = true;
681
680
 
682
681
                                // discard the contact id
683
682
                                id = null;
690
689
                {
691
690
                        // create a new contact
692
691
                        values.put( Contacts.People.NAME, contact._name );
693
 
                        Uri contact_uri = _doit.getContentResolver().insert(
 
692
                        Uri contactUri = _doit.getContentResolver().insert(
694
693
                                Contacts.People.CONTENT_URI, values );
695
 
                        id = ContentUris.parseId( contact_uri );
 
694
                        id = ContentUris.parseId( contactUri );
696
695
                        if( id == null || id <= 0 )
697
696
                                showError( R.string.error_unabletoaddcontact );
698
697
 
706
705
                        }
707
706
 
708
707
                        // update cache
709
 
                        _contacts_cache.addLookup(
 
708
                        _contactsCache.addLookup(
710
709
                                ContactsCache.createIdentifier( contact ), id );
711
710
 
712
711
                        // if we haven't already shown that we're overwriting a contact,
713
712
                        // show that we're creating a new contact
714
 
                        if( !ui_informed ) {
 
713
                        if( !uiInformed ) {
715
714
                                _doit._handler.sendEmptyMessage( Doit.MESSAGE_CONTACTCREATED );
716
 
                                ui_informed = true;
 
715
                                uiInformed = true;
717
716
                        }
718
717
                }
719
718
 
720
719
                // if we haven't already shown that we're overwriting or creating a
721
720
                // contact show that we're merging a contact
722
 
                if( !ui_informed )
 
721
                if( !uiInformed )
723
722
                        _doit._handler.sendEmptyMessage( Doit.MESSAGE_CONTACTMERGED );
724
723
 
725
724
                // import contact parts
737
736
                        HashMap< String, ContactData.PreferredDetail > datas )
738
737
        {
739
738
                // get URI to contact's phones
740
 
                Uri contact_phones_uri = Uri.withAppendedPath(
 
739
                Uri contactPhonesUri = Uri.withAppendedPath(
741
740
                        ContentUris.withAppendedId( Contacts.People.CONTENT_URI, id ),
742
741
                        Contacts.People.Phones.CONTENT_DIRECTORY );
743
 
                Set< String > datas_keys = datas.keySet();
 
742
                Set< String > datasKeys = datas.keySet();
744
743
 
745
744
                // add phone numbers
746
 
                Iterator< String > i = datas_keys.iterator();
 
745
                Iterator< String > i = datasKeys.iterator();
747
746
                while( i.hasNext() ) {
748
747
                        String number = i.next();
749
748
                        ContactData.PreferredDetail data = datas.get( number );
755
754
                        // if the number exists at all, it doesn't need importing. Because
756
755
                        // of this, we also can't update the cache (which we don't need to
757
756
                        // anyway, so it's not a problem).
758
 
                        if( _contacts_cache.hasAssociatedNumber( id, number ) )
 
757
                        if( _contactsCache.hasAssociatedNumber( id, number ) )
759
758
                                continue;
760
759
 
761
760
                        // add phone number
764
763
                        values.put( Contacts.Phones.NUMBER, number );
765
764
                        if( data.isPreferred() )
766
765
                                values.put( Contacts.Phones.ISPRIMARY, 1 );
767
 
                        _doit.getContentResolver().insert( contact_phones_uri, values );
 
766
                        _doit.getContentResolver().insert( contactPhonesUri, values );
768
767
 
769
768
                        // and add this address to the cache to prevent a addition of
770
769
                        // duplicate date from another file
771
 
                        _contacts_cache.addAssociatedNumber( id, number );
 
770
                        _contactsCache.addAssociatedNumber( id, number );
772
771
                }
773
772
        }
774
773
 
776
775
                        HashMap< String, ContactData.PreferredDetail > datas )
777
776
        {
778
777
                // get URI to contact's contact methods
779
 
                Uri contact_contact_methods_uri = Uri.withAppendedPath(
 
778
                Uri contactContactMethodsUri = Uri.withAppendedPath(
780
779
                        ContentUris.withAppendedId( Contacts.People.CONTENT_URI, id ),
781
780
                        Contacts.People.ContactMethods.CONTENT_DIRECTORY );
782
 
                Set< String > datas_keys = datas.keySet();
 
781
                Set< String > datasKeys = datas.keySet();
783
782
 
784
783
                // add email addresses
785
 
                Iterator< String > i = datas_keys.iterator();
 
784
                Iterator< String > i = datasKeys.iterator();
786
785
                while( i.hasNext() ) {
787
786
                        String email = i.next();
788
787
                        ContactData.PreferredDetail data = datas.get( email );
789
788
 
790
789
                        // we don't want to add this email address if it exists already or
791
790
                        // we would introduce duplicates.
792
 
                        if( _contacts_cache.hasAssociatedEmail( id, email ) )
 
791
                        if( _contactsCache.hasAssociatedEmail( id, email ) )
793
792
                                continue;
794
793
 
795
794
                        // add phone number
799
798
                        values.put( Contacts.ContactMethods.TYPE, data.getType() );
800
799
                        if( data.isPreferred() )
801
800
                                values.put( Contacts.ContactMethods.ISPRIMARY, 1 );
802
 
                        _doit.getContentResolver().insert( contact_contact_methods_uri,
 
801
                        _doit.getContentResolver().insert( contactContactMethodsUri,
803
802
                                values );
804
803
 
805
804
                        // and add this address to the cache to prevent a addition of
806
805
                        // duplicate date from another file
807
 
                        _contacts_cache.addAssociatedEmail( id, email );
 
806
                        _contactsCache.addAssociatedEmail( id, email );
808
807
                }
809
808
        }
810
809
 
812
811
                HashMap< String, ContactData.TypeDetail > datas )
813
812
        {
814
813
                // get URI to contact's contact methods
815
 
                Uri contact_contact_methods_uri = Uri.withAppendedPath(
 
814
                Uri contactContactMethodsUri = Uri.withAppendedPath(
816
815
                        ContentUris.withAppendedId( Contacts.People.CONTENT_URI, id ),
817
816
                        Contacts.People.ContactMethods.CONTENT_DIRECTORY );
818
817
 
819
818
                // add addresses
820
 
                Set< String > datas_keys = datas.keySet();
821
 
                Iterator< String > i = datas_keys.iterator();
 
819
                Set< String > datasKeys = datas.keySet();
 
820
                Iterator< String > i = datasKeys.iterator();
822
821
                while( i.hasNext() ) {
823
822
                        String address = i.next();
824
823
                        ContactData.TypeDetail data = datas.get( address );
825
824
 
826
825
                        // we don't want to add this address if it exists already or we
827
826
                        // would introduce duplicates
828
 
                        if( _contacts_cache.hasAssociatedAddress( id, address ) )
 
827
                        if( _contactsCache.hasAssociatedAddress( id, address ) )
829
828
                                continue;
830
829
 
831
830
                        // add postal address
833
832
                        values.put( Contacts.ContactMethods.KIND, Contacts.KIND_POSTAL );
834
833
                        values.put( Contacts.ContactMethods.DATA, address );
835
834
                        values.put( Contacts.ContactMethods.TYPE, data.getType() );
836
 
                        _doit.getContentResolver().insert( contact_contact_methods_uri,
 
835
                        _doit.getContentResolver().insert( contactContactMethodsUri,
837
836
                                values );
838
837
 
839
838
                        // and add this address to the cache to prevent a addition of
840
839
                        // duplicate date from another file
841
 
                        _contacts_cache.addAssociatedAddress( id, address );
 
840
                        _contactsCache.addAssociatedAddress( id, address );
842
841
                }
843
842
        }
844
843
 
846
845
                HashMap< String, ContactData.ExtraDetail > datas )
847
846
        {
848
847
                // add addresses
849
 
                Set< String > datas_keys = datas.keySet();
850
 
                Iterator< String > i = datas_keys.iterator();
 
848
                Set< String > datasKeys = datas.keySet();
 
849
                Iterator< String > i = datasKeys.iterator();
851
850
                while( i.hasNext() ) {
852
851
                        String organisation = i.next();
853
852
                        ContactData.ExtraDetail data = datas.get( organisation );
854
853
 
855
854
                        // we don't want to add this address if it exists already or we
856
855
                        // would introduce duplicates
857
 
                        if( _contacts_cache.hasAssociatedOrganisation( id, organisation ) )
 
856
                        if( _contactsCache.hasAssociatedOrganisation( id, organisation ) )
858
857
                                continue;
859
858
 
860
859
                        // add organisation address
870
869
 
871
870
                        // and add this address to the cache to prevent a addition of
872
871
                        // duplicate date from another file
873
 
                        _contacts_cache.addAssociatedOrganisation( id, organisation );
 
872
                        _contactsCache.addAssociatedOrganisation( id, organisation );
874
873
                }
875
874
        }
876
875