/android/import-contacts

To get this branch, use:
bzr branch http://bzr.ed.am/android/import-contacts
39 by edam
- pulled contacts cache out in to seperate class
1
/*
2
 * ContactsCache.java
3
 *
50 by edam
updated all URLs, email addresses and package names to ed.am
4
 * Copyright (C) 2011 Tim Marston <tim@ed.am>
39 by edam
- pulled contacts cache out in to seperate class
5
 *
6
 * This file is part of the Import Contacts program (hereafter referred
7
 * to as "this program"). For more information, see
50 by edam
updated all URLs, email addresses and package names to ed.am
8
 * http://ed.am/dev/android/import-contacts
39 by edam
- pulled contacts cache out in to seperate class
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
50 by edam
updated all URLs, email addresses and package names to ed.am
24
package am.ed.importcontacts;
39 by edam
- pulled contacts cache out in to seperate class
25
26
import java.util.HashMap;
27
import java.util.HashSet;
28
29
import android.app.Activity;
30
31
32
public class ContactsCache
33
{
40 by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works
34
	/**
35
	 * Information that can be used to identify a contact within the cache
36
	 */
37
	static public class CacheIdentifier
38
	{
39
		public enum Type {
40
			NONE, NAME, ORGANISATION, PRIMARY_NUMBER, PRIMARY_EMAIL }
41
42
		private Type _type;
43
		private String _detail;
44
45
		protected CacheIdentifier()
46
		{
47
			_type = Type.NONE;
48
		}
49
50
		protected CacheIdentifier( Type type, String detail )
51
		{
52
			_type = type;
53
			_detail = detail;
54
		}
55
56
		public Type getType()
57
		{
58
			return _type;
59
		}
60
61
		public String getDetail()
62
		{
63
			return _detail;
64
		}
65
	}
66
67
	// mappings of contact names, organisations and primary numbers to ids
53 by edam
abstracted the android contacts API in to an interface, ready to be switched to
68
	private HashMap< String, Long > _contactsByName
69
		= new HashMap< String, Long >();
70
	private HashMap< String, Long > _contactsByOrg
71
		= new HashMap< String, Long >();
72
	private HashMap< String, Long > _contactsByNumber
73
		= new HashMap< String, Long >();
74
	private HashMap< String, Long > _contactsByEmail
75
		= new HashMap< String, Long >();
40 by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works
76
77
	// mapping of contact ids to sets of associated data
53 by edam
abstracted the android contacts API in to an interface, ready to be switched to
78
	private HashMap< Long, HashSet< String > > _contactNumbers
79
		= new HashMap< Long, HashSet< String > >();
80
	private HashMap< Long, HashSet< String > > _contactEmails
81
		= new HashMap< Long, HashSet< String > >();
82
	private HashMap< Long, HashSet< String > > _contactAddresses
83
		= new HashMap< Long, HashSet< String > >();
84
	private HashMap< Long, HashSet< String > > _contactOrganisations
85
		= new HashMap< Long, HashSet< String > >();
86
87
	ContactsCache()
88
	{
89
		// init id lookups
90
//		_contactsByName = new HashMap< String, Long >();
91
//		_contactsByOrg = new HashMap< String, Long >();
92
//		_contactsByNumber = new HashMap< String, Long >();
93
//		_contactsByEmail = new HashMap< String, Long >();
94
95
		// init associated data cache
96
//		_contactNumbers = new HashMap< Long, HashSet< String > >();
97
//		_contactEmails = new HashMap< Long, HashSet< String > >();
98
//		_contactAddresses = new HashMap< Long, HashSet< String > >();
99
//		_contactOrganisations = new HashMap< Long, HashSet< String > >();
100
	}
40 by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works
101
102
	public static CacheIdentifier createIdentifier(
103
		Importer.ContactData contact )
104
	{
105
		if( contact.hasName() ) {
106
			String name = normaliseName( contact.getName() );
107
			if( name != null )
108
				return new CacheIdentifier(
109
					CacheIdentifier.Type.NAME, name );
110
		}
111
112
		if( contact.hasPrimaryOrganisation() ) {
113
			String organisation = normaliseOrganisation(
114
				contact.getPrimaryOrganisation() );
115
			if( organisation != null )
116
				return new CacheIdentifier(
117
					CacheIdentifier.Type.ORGANISATION, organisation );
118
		}
119
120
		if( contact.hasPrimaryNumber() ) {
121
			String number = normalisePhoneNumber( contact.getPrimaryNumber() );
122
			if( number != null )
123
			return new CacheIdentifier(
124
				CacheIdentifier.Type.PRIMARY_NUMBER, number );
125
		}
126
127
		if( contact.hasPrimaryEmail() ) {
128
			String email = normaliseEmailAddress( contact.getPrimaryEmail() );
129
			if( email != null )
130
			return new CacheIdentifier(
131
				CacheIdentifier.Type.PRIMARY_EMAIL, email );
132
		}
133
134
		return null;
135
	}
136
137
	public boolean canLookup( CacheIdentifier identifier )
138
	{
139
		return lookup( identifier ) != null;
140
	}
141
142
	public Long lookup( CacheIdentifier identifier )
143
	{
144
		switch( identifier.getType() )
145
		{
146
		case NAME:
147
			return _contactsByName.get( identifier.getDetail() );
148
		case ORGANISATION:
149
			return _contactsByOrg.get( identifier.getDetail() );
150
		case PRIMARY_NUMBER:
151
			return _contactsByNumber.get( identifier.getDetail() );
152
		case PRIMARY_EMAIL:
153
			return _contactsByEmail.get( identifier.getDetail() );
154
		}
155
		return null;
156
	}
157
158
	public Long removeLookup( CacheIdentifier identifier )
159
	{
160
		switch( identifier.getType() )
161
		{
162
		case NAME:
163
			return _contactsByName.remove( identifier.getDetail() );
164
		case ORGANISATION:
165
			return _contactsByOrg.remove( identifier.getDetail() );
166
		case PRIMARY_NUMBER:
167
			return _contactsByNumber.remove( identifier.getDetail() );
168
		case PRIMARY_EMAIL:
169
			return _contactsByEmail.remove( identifier.getDetail() );
170
		}
171
		return null;
172
	}
173
174
	public void addLookup( CacheIdentifier identifier, Long id )
175
	{
176
		switch( identifier.getType() )
177
		{
178
		case NAME:
179
			_contactsByName.put( identifier.getDetail(), id );
180
			break;
181
		case ORGANISATION:
182
			_contactsByOrg.put( identifier.getDetail(), id );
183
			break;
184
		case PRIMARY_NUMBER:
185
			_contactsByNumber.put( identifier.getDetail(), id );
186
			break;
187
		case PRIMARY_EMAIL:
188
			_contactsByEmail.put( identifier.getDetail(), id );
189
			break;
190
		}
191
	}
192
193
	public void removeAssociatedData( Long id )
194
	{
195
		_contactNumbers.remove( id );
196
		_contactEmails.remove( id );
197
		_contactAddresses.remove( id );
198
		_contactOrganisations.remove( id );
199
	}
200
201
	public boolean hasAssociatedNumber( Long id, String number )
202
	{
203
		number = normalisePhoneNumber( number );
204
		if( number == null ) return false;
205
206
		HashSet< String > set = _contactNumbers.get( id );
207
		return set != null && set.contains( number );
208
	}
209
210
	public void addAssociatedNumber( Long id, String number )
211
	{
212
		number = normalisePhoneNumber( number );
213
		if( number == null ) return;
214
215
		HashSet< String > set = _contactNumbers.get( id );
216
		if( set == null ) {
217
			set = new HashSet< String >();
218
			_contactNumbers.put( id, set );
219
		}
220
		set.add( normalisePhoneNumber( number ) );
221
	}
222
223
	public boolean hasAssociatedEmail( Long id, String email )
224
	{
225
		email = normaliseEmailAddress( email );
226
		if( email == null ) return false;
227
228
		HashSet< String > set = _contactEmails.get( id );
229
		return set != null && set.contains( normaliseEmailAddress( email ) );
230
	}
231
232
	public void addAssociatedEmail( Long id, String email )
233
	{
234
		email = normaliseEmailAddress( email );
235
		if( email == null ) return;
236
237
		HashSet< String > set = _contactEmails.get( id );
238
		if( set == null ) {
239
			set = new HashSet< String >();
240
			_contactEmails.put( id, set );
241
		}
242
		set.add( normaliseEmailAddress( email ) );
243
	}
244
245
	public boolean hasAssociatedAddress( Long id, String address )
246
	{
247
		address = normaliseAddress( address );
248
		if( address == null ) return false;
249
250
		HashSet< String > set = _contactAddresses.get( id );
251
		return set != null && set.contains( normaliseAddress( address ) );
252
	}
253
254
	public void addAssociatedAddress( Long id, String address )
255
	{
256
		address = normaliseAddress( address );
257
		if( address == null ) return;
258
259
		HashSet< String > set = _contactAddresses.get( id );
260
		if( set == null ) {
261
			set = new HashSet< String >();
262
			_contactAddresses.put( id, set );
263
		}
264
		set.add( normaliseAddress( address ) );
265
	}
266
267
	public boolean hasAssociatedOrganisation( Long id, String organisation )
268
	{
269
		organisation = normaliseOrganisation( organisation );
270
		if( organisation == null ) return false;
271
272
		HashSet< String > set = _contactOrganisations.get( id );
273
		return set != null && set.contains(
274
			normaliseOrganisation( organisation ) );
275
	}
276
277
	public void addAssociatedOrganisation( Long id, String organisation )
278
	{
279
		organisation = normaliseOrganisation( organisation );
280
		if( organisation == null ) return;
281
282
		HashSet< String > set = _contactOrganisations.get( id );
283
		if( set == null ) {
284
			set = new HashSet< String >();
285
			_contactOrganisations.put( id, set );
286
		}
287
		set.add( normaliseOrganisation( organisation ) );
39 by edam
- pulled contacts cache out in to seperate class
288
	}
289
53 by edam
abstracted the android contacts API in to an interface, ready to be switched to
290
	static public String normaliseName( String name )
40 by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works
291
	{
292
		if( name == null ) return null;
293
		name = name.trim();
294
		return name.length() > 0? name : null;
295
	}
296
53 by edam
abstracted the android contacts API in to an interface, ready to be switched to
297
	static public String normalisePhoneNumber( String number )
40 by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works
298
	{
299
		if( number == null ) return null;
300
		number = number.trim().replaceAll( "[-\\(\\) ]", "" );
301
		return number.length() > 0? number : null;
302
	}
303
53 by edam
abstracted the android contacts API in to an interface, ready to be switched to
304
	static public String normaliseEmailAddress( String email )
40 by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works
305
	{
306
		if( email == null ) return null;
307
		email = email.trim().toLowerCase();
308
		return email.length() > 0? email : null;
309
	}
310
53 by edam
abstracted the android contacts API in to an interface, ready to be switched to
311
	static public String normaliseOrganisation( String organisation )
40 by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works
312
	{
313
		if( organisation == null ) return null;
314
		organisation = organisation.trim();
315
		return organisation.length() > 0? organisation : null;
316
	}
317
53 by edam
abstracted the android contacts API in to an interface, ready to be switched to
318
	static public String normaliseAddress( String address )
40 by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works
319
	{
320
		if( address == null ) return null;
321
		address = address.trim();
322
		return address.length() > 0? address : null;
39 by edam
- pulled contacts cache out in to seperate class
323
	}
324
}