/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/am/ed/importcontacts/ContactsCache.java

  • Committer: edam
  • Date: 2009-01-13 06:35:26 UTC
  • Revision ID: edam@waxworlds.org-20090113063526-l9t1s9git4bav60a
- new contact's phone numebrs and email addresses are added to the caches after those contacts are updated to account for the situation where the same contact is imported again from another file (or the contact exists twice in the same file!?)

Show diffs side-by-side

added added

removed removed

1
 
/*
2
 
 * ContactsCache.java
3
 
 *
4
 
 * Copyright (C) 2011 to 2012 Tim Marston <tim@ed.am>
5
 
 *
6
 
 * This file is part of the Import Contacts program (hereafter referred
7
 
 * to as "this program"). For more information, see
8
 
 * http://ed.am/dev/android/import-contacts
9
 
 *
10
 
 * This program is free software: you can redistribute it and/or modify
11
 
 * it under the terms of the GNU General Public License as published by
12
 
 * the Free Software Foundation, either version 3 of the License, or
13
 
 * (at your option) any later version.
14
 
 *
15
 
 * This program is distributed in the hope that it will be useful,
16
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 
 * GNU General Public License for more details.
19
 
 *
20
 
 * You should have received a copy of the GNU General Public License
21
 
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
 
 */
23
 
 
24
 
package am.ed.importcontacts;
25
 
 
26
 
import java.util.HashMap;
27
 
import java.util.HashSet;
28
 
import java.util.Locale;
29
 
 
30
 
public class ContactsCache
31
 
{
32
 
        /**
33
 
         * A thing that can be used to identify (or lookup) a contact within the
34
 
         * contacts cache.  It is not a reference to a cache entry and may not
35
 
         * identify an existing contact in the cache.
36
 
         */
37
 
        public static class CacheIdentifier
38
 
        {
39
 
                public enum Type { NAME, ORGANISATION, PRIMARY_NUMBER, PRIMARY_EMAIL }
40
 
 
41
 
                private Type _type;
42
 
                private String _detail;
43
 
 
44
 
                /**
45
 
                 * Obtain a cache identifier.  This routine is designed to be as robust
46
 
                 * as possible (in terms of bad or null detail values), and to return
47
 
                 * null when a cache identifier can not be created.
48
 
                 * @param type the detail type
49
 
                 * @param detail the detail
50
 
                 * @return the cache identifier, or null
51
 
                 */
52
 
                public static CacheIdentifier factory( Type type, String detail )
53
 
                {
54
 
                        switch( type )
55
 
                        {
56
 
                        case NAME: detail = normaliseName( detail ); break;
57
 
                        case ORGANISATION: detail = normaliseOrganisation( detail ); break;
58
 
                        case PRIMARY_NUMBER: detail = normalisePhoneNumber( detail ); break;
59
 
                        case PRIMARY_EMAIL: detail = normaliseEmailAddress( detail ); break;
60
 
                        default: return null;
61
 
                        }
62
 
                        if( detail == null ) return null;
63
 
                        return new CacheIdentifier( type, detail );
64
 
                }
65
 
 
66
 
                /**
67
 
                 * Obtain a cache identifier from contact data.  This routine is
68
 
                 * designed to be as robust as possible and may return null when a cache
69
 
                 * identifier can not be created.
70
 
                 * @param contact the contact data
71
 
                 * @return the cache identifier, or null
72
 
                 */
73
 
                public static CacheIdentifier factory( Importer.ContactData contact )
74
 
                {
75
 
                        CacheIdentifier identifier = null;
76
 
 
77
 
                        if( contact.hasName() )
78
 
                                identifier = factory( CacheIdentifier.Type.NAME,
79
 
                                        contact.getName() );
80
 
                        if( identifier != null ) return identifier;
81
 
 
82
 
                        if( contact.hasPrimaryOrganisation() )
83
 
                                identifier = factory( CacheIdentifier.Type.ORGANISATION,
84
 
                                        contact.getPrimaryOrganisation() );
85
 
                        if( identifier != null ) return identifier;
86
 
 
87
 
                        if( contact.hasPrimaryNumber() )
88
 
                                identifier = factory( CacheIdentifier.Type.PRIMARY_NUMBER,
89
 
                                        contact.getPrimaryNumber() );
90
 
                        if( identifier != null ) return identifier;
91
 
 
92
 
                        if( contact.hasPrimaryEmail() )
93
 
                                identifier = factory( CacheIdentifier.Type.PRIMARY_EMAIL,
94
 
                                        contact.getPrimaryEmail() );
95
 
                        if( identifier != null ) return identifier;
96
 
 
97
 
                        return null;
98
 
                }
99
 
 
100
 
                protected CacheIdentifier( Type type, String detail )
101
 
                {
102
 
                        _type = type;
103
 
                        _detail = detail;
104
 
                }
105
 
 
106
 
                public Type getType()
107
 
                {
108
 
                        return _type;
109
 
                }
110
 
 
111
 
                public String getDetail()
112
 
                {
113
 
                        return _detail;
114
 
                }
115
 
        }
116
 
 
117
 
        // mappings of contact names, organisations and primary numbers to ids
118
 
        private HashMap< String, Long > _contactsByName
119
 
                = new HashMap< String, Long >();
120
 
        private HashMap< String, Long > _contactsByOrg
121
 
                = new HashMap< String, Long >();
122
 
        private HashMap< String, Long > _contactsByNumber
123
 
                = new HashMap< String, Long >();
124
 
        private HashMap< String, Long > _contactsByEmail
125
 
                = new HashMap< String, Long >();
126
 
 
127
 
        // mapping of contact ids to sets of associated data
128
 
        private HashMap< Long, HashSet< String > > _contactNumbers
129
 
                = new HashMap< Long, HashSet< String > >();
130
 
        private HashMap< Long, HashSet< String > > _contactEmails
131
 
                = new HashMap< Long, HashSet< String > >();
132
 
        private HashMap< Long, HashSet< String > > _contactAddresses
133
 
                = new HashMap< Long, HashSet< String > >();
134
 
        private HashMap< Long, HashSet< String > > _contactOrganisations
135
 
                = new HashMap< Long, HashSet< String > >();
136
 
        private HashMap< Long, HashSet< String > > _contactNotes
137
 
                = new HashMap< Long, HashSet< String > >();
138
 
 
139
 
        public boolean canLookup( CacheIdentifier identifier )
140
 
        {
141
 
                return lookup( identifier ) != null;
142
 
        }
143
 
 
144
 
        /**
145
 
         * Retrieve the contact id of a contact identified by the specified cache
146
 
         * identifier, if it exists.
147
 
         * @param identifier the cache identifier
148
 
         * @return a contact id, or null
149
 
         */
150
 
        public Long lookup( CacheIdentifier identifier )
151
 
        {
152
 
                switch( identifier.getType() )
153
 
                {
154
 
                case NAME:
155
 
                        return _contactsByName.get( identifier.getDetail() );
156
 
                case ORGANISATION:
157
 
                        return _contactsByOrg.get( identifier.getDetail() );
158
 
                case PRIMARY_NUMBER:
159
 
                        return _contactsByNumber.get( identifier.getDetail() );
160
 
                case PRIMARY_EMAIL:
161
 
                        return _contactsByEmail.get( identifier.getDetail() );
162
 
                }
163
 
                return null;
164
 
        }
165
 
 
166
 
        /**
167
 
         * Remove any cache entry that is identified by the cache identifier.
168
 
         * @param identifier the cache identifier
169
 
         * @return the contact id of the contact that was removed, or null
170
 
         */
171
 
        public Long removeLookup( CacheIdentifier identifier )
172
 
        {
173
 
                switch( identifier.getType() )
174
 
                {
175
 
                case NAME:
176
 
                        return _contactsByName.remove( identifier.getDetail() );
177
 
                case ORGANISATION:
178
 
                        return _contactsByOrg.remove( identifier.getDetail() );
179
 
                case PRIMARY_NUMBER:
180
 
                        return _contactsByNumber.remove( identifier.getDetail() );
181
 
                case PRIMARY_EMAIL:
182
 
                        return _contactsByEmail.remove( identifier.getDetail() );
183
 
                }
184
 
                return null;
185
 
        }
186
 
 
187
 
        /**
188
 
         * Add a lookup from a contact identifier to a contact id to the cache.
189
 
         * @param identifier the cache identifier
190
 
         * @param id teh contact id
191
 
         */
192
 
        public void addLookup( CacheIdentifier identifier, Long id )
193
 
        {
194
 
                switch( identifier.getType() )
195
 
                {
196
 
                case NAME:
197
 
                        _contactsByName.put( identifier.getDetail(), id );
198
 
                        break;
199
 
                case ORGANISATION:
200
 
                        _contactsByOrg.put( identifier.getDetail(), id );
201
 
                        break;
202
 
                case PRIMARY_NUMBER:
203
 
                        _contactsByNumber.put( identifier.getDetail(), id );
204
 
                        break;
205
 
                case PRIMARY_EMAIL:
206
 
                        _contactsByEmail.put( identifier.getDetail(), id );
207
 
                        break;
208
 
                }
209
 
        }
210
 
 
211
 
        /**
212
 
         * Remove any data that is associated with an contact id.
213
 
         * @param id
214
 
         */
215
 
        public void removeAssociatedData( Long id )
216
 
        {
217
 
                _contactNumbers.remove( id );
218
 
                _contactEmails.remove( id );
219
 
                _contactAddresses.remove( id );
220
 
                _contactOrganisations.remove( id );
221
 
                _contactNotes.remove( id );
222
 
        }
223
 
 
224
 
        public boolean hasAssociatedNumber( Long id, String number )
225
 
        {
226
 
                number = normalisePhoneNumber( number );
227
 
                if( number == null ) return false;
228
 
 
229
 
                HashSet< String > set = _contactNumbers.get( id );
230
 
                return set != null && set.contains( number );
231
 
        }
232
 
 
233
 
        public void addAssociatedNumber( Long id, String number )
234
 
        {
235
 
                number = normalisePhoneNumber( number );
236
 
                if( number == null ) return;
237
 
 
238
 
                HashSet< String > set = _contactNumbers.get( id );
239
 
                if( set == null ) {
240
 
                        set = new HashSet< String >();
241
 
                        _contactNumbers.put( id, set );
242
 
                }
243
 
                set.add( number );
244
 
        }
245
 
 
246
 
        public boolean hasAssociatedEmail( Long id, String email )
247
 
        {
248
 
                email = normaliseEmailAddress( email );
249
 
                if( email == null ) return false;
250
 
 
251
 
                HashSet< String > set = _contactEmails.get( id );
252
 
                return set != null && set.contains( email );
253
 
        }
254
 
 
255
 
        public void addAssociatedEmail( Long id, String email )
256
 
        {
257
 
                email = normaliseEmailAddress( email );
258
 
                if( email == null ) return;
259
 
 
260
 
                HashSet< String > set = _contactEmails.get( id );
261
 
                if( set == null ) {
262
 
                        set = new HashSet< String >();
263
 
                        _contactEmails.put( id, set );
264
 
                }
265
 
                set.add( email );
266
 
        }
267
 
 
268
 
        public boolean hasAssociatedAddress( Long id, String address )
269
 
        {
270
 
                address = normaliseAddress( address );
271
 
                if( address == null ) return false;
272
 
 
273
 
                HashSet< String > set = _contactAddresses.get( id );
274
 
                return set != null && set.contains( address );
275
 
        }
276
 
 
277
 
        public void addAssociatedAddress( Long id, String address )
278
 
        {
279
 
                address = normaliseAddress( address );
280
 
                if( address == null ) return;
281
 
 
282
 
                HashSet< String > set = _contactAddresses.get( id );
283
 
                if( set == null ) {
284
 
                        set = new HashSet< String >();
285
 
                        _contactAddresses.put( id, set );
286
 
                }
287
 
                set.add( address );
288
 
        }
289
 
 
290
 
        public boolean hasAssociatedOrganisation( Long id, String organisation )
291
 
        {
292
 
                organisation = normaliseOrganisation( organisation );
293
 
                if( organisation == null ) return false;
294
 
 
295
 
                HashSet< String > set = _contactOrganisations.get( id );
296
 
                return set != null && set.contains( organisation );
297
 
        }
298
 
 
299
 
        public void addAssociatedOrganisation( Long id, String organisation )
300
 
        {
301
 
                organisation = normaliseOrganisation( organisation );
302
 
                if( organisation == null ) return;
303
 
 
304
 
                HashSet< String > set = _contactOrganisations.get( id );
305
 
                if( set == null ) {
306
 
                        set = new HashSet< String >();
307
 
                        _contactOrganisations.put( id, set );
308
 
                }
309
 
                set.add( organisation );
310
 
        }
311
 
 
312
 
        public boolean hasAssociatedNote( Long id, String note )
313
 
        {
314
 
                note = normaliseNote( note );
315
 
                if( note == null ) return false;
316
 
 
317
 
                HashSet< String > set = _contactNotes.get( id );
318
 
                return set != null && set.contains( note );
319
 
        }
320
 
 
321
 
        public void addAssociatedNote( Long id, String note )
322
 
        {
323
 
                note = normaliseNote( note );
324
 
                if( note == null ) return;
325
 
 
326
 
                HashSet< String > set = _contactNotes.get( id );
327
 
                if( set == null ) {
328
 
                        set = new HashSet< String >();
329
 
                        _contactNotes.put( id, set );
330
 
                }
331
 
                set.add( note );
332
 
        }
333
 
 
334
 
        static public String normaliseName( String name )
335
 
        {
336
 
                if( name == null ) return null;
337
 
                name = name.trim();
338
 
                return name.length() > 0? name : null;
339
 
        }
340
 
 
341
 
        static public String normalisePhoneNumber( String number )
342
 
        {
343
 
                if( number == null ) return null;
344
 
                number = number.trim().replaceAll( "[-\\(\\) ]", "" );
345
 
                return number.length() > 0? number : null;
346
 
        }
347
 
 
348
 
        static public String normaliseEmailAddress( String email )
349
 
        {
350
 
                if( email == null ) return null;
351
 
                email = email.trim().toLowerCase( Locale.US );
352
 
                return email.length() > 0? email : null;
353
 
        }
354
 
 
355
 
        static public String normaliseOrganisation( String organisation )
356
 
        {
357
 
                if( organisation == null ) return null;
358
 
                organisation = organisation.trim();
359
 
                return organisation.length() > 0? organisation : null;
360
 
        }
361
 
 
362
 
        static public String normaliseAddress( String address )
363
 
        {
364
 
                if( address == null ) return null;
365
 
                address = address.trim();
366
 
                return address.length() > 0? address : null;
367
 
        }
368
 
 
369
 
        static public String normaliseNote( String note )
370
 
        {
371
 
                if( note == null ) return null;
372
 
                note = note.trim();
373
 
                return note.length() > 0? note : null;
374
 
        }
375
 
}