4
* Copyright (C) 2011 to 2012 Tim Marston <tim@ed.am>
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
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.
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.
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/>.
24
package am.ed.importcontacts;
26
import java.util.HashMap;
27
import java.util.HashSet;
28
import java.util.Locale;
30
public class ContactsCache
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.
37
public static class CacheIdentifier
39
public enum Type { NAME, ORGANISATION, PRIMARY_NUMBER, PRIMARY_EMAIL }
42
private String _detail;
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
52
public static CacheIdentifier factory( Type type, String detail )
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;
62
if( detail == null ) return null;
63
return new CacheIdentifier( type, detail );
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
73
public static CacheIdentifier factory( Importer.ContactData contact )
75
CacheIdentifier ret = null;
77
if( contact.hasName() )
78
ret = factory( CacheIdentifier.Type.NAME,
80
if( ret == null && contact.hasPrimaryOrganisation() )
81
ret = factory( CacheIdentifier.Type.ORGANISATION,
82
contact.getPrimaryOrganisation() );
83
if( ret == null && contact.hasPrimaryNumber() )
84
ret = factory( CacheIdentifier.Type.PRIMARY_NUMBER,
85
contact.getPrimaryNumber() );
86
if( ret == null && contact.hasPrimaryEmail() )
87
ret = factory( CacheIdentifier.Type.PRIMARY_EMAIL,
88
contact.getPrimaryEmail() );
93
protected CacheIdentifier( Type type, String detail )
104
public String getDetail()
110
// mappings of contact names, organisations and primary numbers to ids
111
private HashMap< String, Long > _contactsByName
112
= new HashMap< String, Long >();
113
private HashMap< String, Long > _contactsByOrg
114
= new HashMap< String, Long >();
115
private HashMap< String, Long > _contactsByNumber
116
= new HashMap< String, Long >();
117
private HashMap< String, Long > _contactsByEmail
118
= new HashMap< String, Long >();
120
// mapping of contact ids to sets of associated data
121
private HashMap< Long, HashSet< String > > _contactNumbers
122
= new HashMap< Long, HashSet< String > >();
123
private HashMap< Long, HashSet< String > > _contactEmails
124
= new HashMap< Long, HashSet< String > >();
125
private HashMap< Long, HashSet< String > > _contactAddresses
126
= new HashMap< Long, HashSet< String > >();
127
private HashMap< Long, HashSet< String > > _contactOrganisations
128
= new HashMap< Long, HashSet< String > >();
129
private HashMap< Long, HashSet< String > > _contactNotes
130
= new HashMap< Long, HashSet< String > >();
132
public boolean canLookup( CacheIdentifier identifier )
134
return lookup( identifier ) != null;
138
* Retrieve the contact id of a contact identified by the specified cache
139
* identifier, if it exists.
140
* @param identifier the cache identifier
141
* @return a contact id, or null
143
public Long lookup( CacheIdentifier identifier )
145
switch( identifier.getType() )
148
return _contactsByName.get( identifier.getDetail() );
150
return _contactsByOrg.get( identifier.getDetail() );
152
return _contactsByNumber.get( identifier.getDetail() );
154
return _contactsByEmail.get( identifier.getDetail() );
160
* Remove any cache entry that is identified by the cache identifier.
161
* @param identifier the cache identifier
162
* @return the contact id of the contact that was removed, or null
164
public Long removeLookup( CacheIdentifier identifier )
166
switch( identifier.getType() )
169
return _contactsByName.remove( identifier.getDetail() );
171
return _contactsByOrg.remove( identifier.getDetail() );
173
return _contactsByNumber.remove( identifier.getDetail() );
175
return _contactsByEmail.remove( identifier.getDetail() );
181
* Add a lookup from a contact identifier to a contact id to the cache.
182
* @param identifier the cache identifier
183
* @param id teh contact id
185
public void addLookup( CacheIdentifier identifier, Long id )
187
switch( identifier.getType() )
190
_contactsByName.put( identifier.getDetail(), id );
193
_contactsByOrg.put( identifier.getDetail(), id );
196
_contactsByNumber.put( identifier.getDetail(), id );
199
_contactsByEmail.put( identifier.getDetail(), id );
205
* Remove any data that is associated with an contact id.
208
public void removeAssociatedData( Long id )
210
_contactNumbers.remove( id );
211
_contactEmails.remove( id );
212
_contactAddresses.remove( id );
213
_contactOrganisations.remove( id );
214
_contactNotes.remove( id );
217
public boolean hasAssociatedNumber( Long id, String number )
219
number = normalisePhoneNumber( number );
220
if( number == null ) return false;
222
HashSet< String > set = _contactNumbers.get( id );
223
return set != null && set.contains( number );
226
public void addAssociatedNumber( Long id, String number )
228
number = normalisePhoneNumber( number );
229
if( number == null ) return;
231
HashSet< String > set = _contactNumbers.get( id );
233
set = new HashSet< String >();
234
_contactNumbers.put( id, set );
239
public boolean hasAssociatedEmail( Long id, String email )
241
email = normaliseEmailAddress( email );
242
if( email == null ) return false;
244
HashSet< String > set = _contactEmails.get( id );
245
return set != null && set.contains( email );
248
public void addAssociatedEmail( Long id, String email )
250
email = normaliseEmailAddress( email );
251
if( email == null ) return;
253
HashSet< String > set = _contactEmails.get( id );
255
set = new HashSet< String >();
256
_contactEmails.put( id, set );
261
public boolean hasAssociatedAddress( Long id, String address )
263
address = normaliseAddress( address );
264
if( address == null ) return false;
266
HashSet< String > set = _contactAddresses.get( id );
267
return set != null && set.contains( address );
270
public void addAssociatedAddress( Long id, String address )
272
address = normaliseAddress( address );
273
if( address == null ) return;
275
HashSet< String > set = _contactAddresses.get( id );
277
set = new HashSet< String >();
278
_contactAddresses.put( id, set );
283
public boolean hasAssociatedOrganisation( Long id, String organisation )
285
organisation = normaliseOrganisation( organisation );
286
if( organisation == null ) return false;
288
HashSet< String > set = _contactOrganisations.get( id );
289
return set != null && set.contains( organisation );
292
public void addAssociatedOrganisation( Long id, String organisation )
294
organisation = normaliseOrganisation( organisation );
295
if( organisation == null ) return;
297
HashSet< String > set = _contactOrganisations.get( id );
299
set = new HashSet< String >();
300
_contactOrganisations.put( id, set );
302
set.add( organisation );
305
public boolean hasAssociatedNote( Long id, String note )
307
note = normaliseNote( note );
308
if( note == null ) return false;
310
HashSet< String > set = _contactNotes.get( id );
311
return set != null && set.contains( note );
314
public void addAssociatedNote( Long id, String note )
316
note = normaliseNote( note );
317
if( note == null ) return;
319
HashSet< String > set = _contactNotes.get( id );
321
set = new HashSet< String >();
322
_contactNotes.put( id, set );
327
static public String normaliseName( String name )
329
if( name == null ) return null;
331
return name.length() > 0? name : null;
334
static public String normalisePhoneNumber( String number )
336
if( number == null ) return null;
337
number = number.trim().replaceAll( "[-\\(\\) ]", "" );
338
return number.length() > 0? number : null;
341
static public String normaliseEmailAddress( String email )
343
if( email == null ) return null;
344
email = email.trim().toLowerCase( Locale.US );
345
return email.length() > 0? email : null;
348
static public String normaliseOrganisation( String organisation )
350
if( organisation == null ) return null;
351
organisation = organisation.trim();
352
return organisation.length() > 0? organisation : null;
355
static public String normaliseAddress( String address )
357
if( address == null ) return null;
358
address = address.trim();
359
return address.length() > 0? address : null;
362
static public String normaliseNote( String note )
364
if( note == null ) return null;
366
return note.length() > 0? note : null;