bzr branch
http://bzr.ed.am/android/import-contacts
6
by edam
- added GPL header comments to all files |
1 |
/* |
2 |
* Importer.java |
|
3 |
* |
|
95
by Tim Marston
added suopport for birthdays |
4 |
* Copyright (C) 2009 to 2013 Tim Marston <tim@ed.am> |
6
by edam
- added GPL header comments to all files |
5 |
* |
6 |
* This file is part of the Import Contacts program (hereafter referred |
|
93
by Tim Marston
minor style tweaks |
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 |
6
by edam
- added GPL header comments to all files |
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; |
1
by edam
Initial import |
25 |
|
46
by edam
- properly handle multiple TYPE= params in one entry in a v3.0 vCard |
26 |
import java.util.Arrays; |
1
by edam
Initial import |
27 |
import java.util.HashMap; |
46
by edam
- properly handle multiple TYPE= params in one entry in a v3.0 vCard |
28 |
import java.util.HashSet; |
1
by edam
Initial import |
29 |
import java.util.Iterator; |
61
by edam
made contacts backend throw exceptions when it can't create contacts on the device; specified Locale in lower/upper case conversions; stripped old Contacts types from Importer (and replaced with our own types, which are now converted in the backend; switched using Integer() constructors to Integer.valueOf(); rewrote the main importer routine a bit |
30 |
import java.util.Locale; |
1
by edam
Initial import |
31 |
import java.util.Set; |
32 |
import java.util.regex.Matcher; |
|
33 |
import java.util.regex.Pattern; |
|
34 |
||
61
by edam
made contacts backend throw exceptions when it can't create contacts on the device; specified Locale in lower/upper case conversions; stripped old Contacts types from Importer (and replaced with our own types, which are now converted in the backend; switched using Integer() constructors to Integer.valueOf(); rewrote the main importer routine a bit |
35 |
import am.ed.importcontacts.Backend.ContactCreationException; |
1
by edam
Initial import |
36 |
import android.content.SharedPreferences; |
37 |
import android.os.Message; |
|
38 |
||
39 |
public class Importer extends Thread |
|
40 |
{ |
|
3
by edam
- added "all done" message |
41 |
public final static int ACTION_ABORT = 1; |
42 |
public final static int ACTION_ALLDONE = 2; |
|
1
by edam
Initial import |
43 |
|
44 |
public final static int RESPONSE_NEGATIVE = 0; |
|
45 |
public final static int RESPONSE_POSITIVE = 1; |
|
46 |
||
47 |
public final static int RESPONSEEXTRA_NONE = 0; |
|
48 |
public final static int RESPONSEEXTRA_ALWAYS = 1; |
|
49 |
||
50 |
private Doit _doit; |
|
51 |
private int _response; |
|
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
52 |
private int _response_extra; |
53 |
private int _merge_setting; |
|
54 |
private int _last_merge_decision; |
|
1
by edam
Initial import |
55 |
private boolean _abort = false; |
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
56 |
private boolean _is_finished = false; |
41
by edam
- updated TODO |
57 |
private ContactsCache _contacts_cache = null; |
53
by edam
abstracted the android contacts API in to an interface, ready to be switched to |
58 |
private Backend _backend = null; |
1
by edam
Initial import |
59 |
|
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
60 |
/** |
61 |
* Data about a contact |
|
62 |
*/ |
|
1
by edam
Initial import |
63 |
public class ContactData |
64 |
{ |
|
61
by edam
made contacts backend throw exceptions when it can't create contacts on the device; specified Locale in lower/upper case conversions; stripped old Contacts types from Importer (and replaced with our own types, which are now converted in the backend; switched using Integer() constructors to Integer.valueOf(); rewrote the main importer routine a bit |
65 |
public final static int TYPE_HOME = 0; |
66 |
public final static int TYPE_WORK = 1; |
|
67 |
public final static int TYPE_MOBILE = 2; // only used with phones |
|
68 |
public final static int TYPE_FAX_HOME = 3; // only used with phones |
|
69 |
public final static int TYPE_FAX_WORK = 4; // only used with phones |
|
70 |
public final static int TYPE_PAGER = 5; // only used with phones |
|
71 |
||
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
72 |
class TypeDetail |
73 |
{ |
|
74 |
protected int _type; |
|
75 |
||
76 |
public TypeDetail( int type ) |
|
77 |
{ |
|
78 |
_type = type; |
|
79 |
} |
|
80 |
||
81 |
public int getType() |
|
82 |
{ |
|
83 |
return _type; |
|
84 |
} |
|
85 |
} |
|
86 |
||
87 |
class PreferredDetail extends TypeDetail |
|
88 |
{ |
|
89 |
protected boolean _is_preferred; |
|
90 |
||
91 |
public PreferredDetail( int type, boolean is_preferred ) |
|
92 |
{ |
|
93 |
super( type ); |
|
94 |
_is_preferred = is_preferred; |
|
95 |
} |
|
96 |
||
97 |
public boolean isPreferred() |
|
98 |
{ |
|
99 |
return _is_preferred; |
|
100 |
} |
|
101 |
} |
|
102 |
||
103 |
class ExtraDetail extends PreferredDetail |
|
104 |
{ |
|
105 |
protected String _extra; |
|
106 |
||
107 |
public ExtraDetail( int type, boolean is_preferred, String extra ) |
|
108 |
{ |
|
109 |
super( type, is_preferred ); |
|
110 |
||
111 |
if( extra != null ) extra = extra.trim(); |
|
112 |
_extra = extra; |
|
113 |
} |
|
114 |
||
115 |
public String getExtra() |
|
116 |
{ |
|
117 |
return _extra; |
|
118 |
} |
|
119 |
||
120 |
public void setExtra( String extra ) |
|
121 |
{ |
|
122 |
if( extra != null ) extra = extra.trim(); |
|
123 |
_extra = extra; |
|
124 |
} |
|
125 |
} |
|
126 |
||
43
by edam
- refactored some code to do with how contacts are imported |
127 |
@SuppressWarnings("serial") |
128 |
protected class ContactNotIdentifiableException extends Exception |
|
129 |
{ |
|
130 |
} |
|
131 |
||
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
132 |
protected String _name = null; |
133 |
protected String _primary_organisation = null; |
|
46
by edam
- properly handle multiple TYPE= params in one entry in a v3.0 vCard |
134 |
protected boolean _primary_organisation_is_preferred; |
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
135 |
protected String _primary_number = null; |
46
by edam
- properly handle multiple TYPE= params in one entry in a v3.0 vCard |
136 |
protected int _primary_number_type; |
137 |
protected boolean _primary_number_is_preferred; |
|
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
138 |
protected String _primary_email = null; |
46
by edam
- properly handle multiple TYPE= params in one entry in a v3.0 vCard |
139 |
protected boolean _primary_email_is_preferred; |
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
140 |
protected HashMap< String, ExtraDetail > _organisations = null; |
141 |
protected HashMap< String, PreferredDetail > _numbers = null; |
|
142 |
protected HashMap< String, PreferredDetail > _emails = null; |
|
143 |
protected HashMap< String, TypeDetail > _addresses = null; |
|
65
by edam
added support for notes; rewrote backends so that all normalising of data is now done within the contacts cache; made the vCard unescape routine slightly more acceptant of non-standard escaped characters |
144 |
protected HashSet< String > _notes = null; |
95
by Tim Marston
added suopport for birthdays |
145 |
protected String _birthday = null; |
1
by edam
Initial import |
146 |
|
43
by edam
- refactored some code to do with how contacts are imported |
147 |
private ContactsCache.CacheIdentifier _cache_identifier = null; |
148 |
||
1
by edam
Initial import |
149 |
protected void setName( String name ) |
150 |
{ |
|
151 |
_name = name; |
|
152 |
} |
|
153 |
||
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
154 |
public boolean hasName() |
155 |
{ |
|
156 |
return _name != null; |
|
157 |
} |
|
158 |
||
1
by edam
Initial import |
159 |
public String getName() |
160 |
{ |
|
161 |
return _name; |
|
162 |
} |
|
163 |
||
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
164 |
protected void addOrganisation( String organisation, String title, |
165 |
boolean is_preferred ) |
|
166 |
{ |
|
167 |
organisation = organisation.trim(); |
|
168 |
if( organisation.length() <= 0 ) |
|
169 |
{ |
|
170 |
// TODO: warn that an imported organisation is being ignored |
|
171 |
return; |
|
172 |
} |
|
173 |
||
174 |
if( title != null ) { |
|
175 |
title = title.trim(); |
|
176 |
if( title.length() <= 0 ) title = null; |
|
177 |
} |
|
178 |
||
179 |
// add the organisation, as non-preferred (we prefer only one |
|
180 |
// organisation in finalise() after they're all imported) |
|
181 |
if( _organisations == null ) |
|
182 |
_organisations = new HashMap< String, ExtraDetail >(); |
|
183 |
if( !_organisations.containsKey( organisation ) ) |
|
184 |
_organisations.put( organisation, |
|
185 |
new ExtraDetail( 0, false, title ) ); |
|
186 |
||
187 |
// if this is the first organisation added, or it's a preferred |
|
46
by edam
- properly handle multiple TYPE= params in one entry in a v3.0 vCard |
188 |
// organisation and the current primary organisation isn't, then |
93
by Tim Marston
minor style tweaks |
189 |
// record this as the primary organisation |
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
190 |
if( _primary_organisation == null || |
191 |
( is_preferred && !_primary_organisation_is_preferred ) ) |
|
192 |
{ |
|
193 |
_primary_organisation = organisation; |
|
194 |
_primary_organisation_is_preferred = is_preferred; |
|
195 |
} |
|
196 |
} |
|
197 |
||
198 |
public boolean hasOrganisations() |
|
199 |
{ |
|
200 |
return _organisations != null && _organisations.size() > 0; |
|
201 |
} |
|
202 |
||
203 |
public HashMap< String, ExtraDetail > getOrganisations() |
|
204 |
{ |
|
205 |
return _organisations; |
|
206 |
} |
|
207 |
||
208 |
public boolean hasPrimaryOrganisation() |
|
209 |
{ |
|
210 |
return _primary_organisation != null; |
|
211 |
} |
|
212 |
||
213 |
public String getPrimaryOrganisation() |
|
214 |
{ |
|
215 |
return _primary_organisation; |
|
216 |
} |
|
217 |
||
218 |
protected void addNumber( String number, int type, |
|
219 |
boolean is_preferred ) |
|
220 |
{ |
|
221 |
number = sanitisePhoneNumber( number ); |
|
222 |
if( number == null ) |
|
223 |
{ |
|
224 |
// TODO: warn that an imported phone number is being ignored |
|
225 |
return; |
|
226 |
} |
|
227 |
||
228 |
// add the number, as non-preferred (we prefer only one number |
|
229 |
// in finalise() after they're all imported) |
|
230 |
if( _numbers == null ) |
|
231 |
_numbers = new HashMap< String, PreferredDetail >(); |
|
232 |
if( !_numbers.containsKey( number ) ) |
|
233 |
_numbers.put( number, |
|
234 |
new PreferredDetail( type, false ) ); |
|
235 |
||
46
by edam
- properly handle multiple TYPE= params in one entry in a v3.0 vCard |
236 |
final Set< Integer > non_voice_types = new HashSet< Integer >( |
61
by edam
made contacts backend throw exceptions when it can't create contacts on the device; specified Locale in lower/upper case conversions; stripped old Contacts types from Importer (and replaced with our own types, which are now converted in the backend; switched using Integer() constructors to Integer.valueOf(); rewrote the main importer routine a bit |
237 |
Arrays.asList( TYPE_FAX_HOME, TYPE_FAX_WORK, TYPE_PAGER ) ); |
46
by edam
- properly handle multiple TYPE= params in one entry in a v3.0 vCard |
238 |
|
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
239 |
// if this is the first number added, or it's a preferred number |
46
by edam
- properly handle multiple TYPE= params in one entry in a v3.0 vCard |
240 |
// and the current primary number isn't, or this number is on equal |
241 |
// standing with the primary number in terms of preference and it is |
|
242 |
// a voice number and the primary number isn't, then record this as |
|
93
by Tim Marston
minor style tweaks |
243 |
// the primary number |
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
244 |
if( _primary_number == null || |
46
by edam
- properly handle multiple TYPE= params in one entry in a v3.0 vCard |
245 |
( is_preferred && !_primary_number_is_preferred ) || |
246 |
( is_preferred == _primary_number_is_preferred && |
|
247 |
!non_voice_types.contains( type ) && |
|
248 |
non_voice_types.contains( _primary_number_type ) ) ) |
|
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
249 |
{ |
250 |
_primary_number = number; |
|
46
by edam
- properly handle multiple TYPE= params in one entry in a v3.0 vCard |
251 |
_primary_number_type = type; |
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
252 |
_primary_number_is_preferred = is_preferred; |
253 |
} |
|
254 |
} |
|
255 |
||
256 |
public boolean hasNumbers() |
|
257 |
{ |
|
258 |
return _numbers != null && _numbers.size() > 0; |
|
259 |
} |
|
260 |
||
261 |
public HashMap< String, PreferredDetail > getNumbers() |
|
262 |
{ |
|
263 |
return _numbers; |
|
264 |
} |
|
265 |
||
266 |
public boolean hasPrimaryNumber() |
|
267 |
{ |
|
268 |
return _primary_number != null; |
|
269 |
} |
|
270 |
||
271 |
public String getPrimaryNumber() |
|
272 |
{ |
|
273 |
return _primary_number; |
|
274 |
} |
|
275 |
||
276 |
protected void addEmail( String email, int type, boolean is_preferred ) |
|
277 |
{ |
|
278 |
||
279 |
email = sanitisesEmailAddress( email ); |
|
280 |
if( email == null ) |
|
281 |
{ |
|
57
by edam
cleanup; fixed some typos; updated TODO |
282 |
// TODO: warn that an imported email address is being ignored |
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
283 |
return; |
284 |
} |
|
285 |
||
286 |
// add the email, as non-preferred (we prefer only one email in |
|
287 |
// finalise() after they're all imported) |
|
288 |
if( _emails == null ) |
|
289 |
_emails = new HashMap< String, PreferredDetail >(); |
|
1
by edam
Initial import |
290 |
if( !_emails.containsKey( email ) ) |
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
291 |
_emails.put( email, new PreferredDetail( type, false ) ); |
292 |
||
46
by edam
- properly handle multiple TYPE= params in one entry in a v3.0 vCard |
293 |
// if this is the first email added, or it's a preferred email and |
294 |
// the current primary organisation isn't, then record this as the |
|
93
by Tim Marston
minor style tweaks |
295 |
// primary email |
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
296 |
if( _primary_email == null || |
297 |
( is_preferred && !_primary_email_is_preferred ) ) |
|
298 |
{ |
|
299 |
_primary_email = email; |
|
300 |
_primary_email_is_preferred = is_preferred; |
|
301 |
} |
|
302 |
} |
|
303 |
||
304 |
public boolean hasEmails() |
|
305 |
{ |
|
306 |
return _emails != null && _emails.size() > 0; |
|
307 |
} |
|
308 |
||
309 |
public HashMap< String, PreferredDetail > getEmails() |
|
310 |
{ |
|
311 |
return _emails; |
|
312 |
} |
|
313 |
||
314 |
public boolean hasPrimaryEmail() |
|
315 |
{ |
|
316 |
return _primary_email != null; |
|
317 |
} |
|
318 |
||
319 |
public String getPrimaryEmail() |
|
320 |
{ |
|
321 |
return _primary_email; |
|
1
by edam
Initial import |
322 |
} |
37
by edam
- updated TODO and NEWS |
323 |
|
324 |
protected void addAddress( String address, int type ) |
|
325 |
{ |
|
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
326 |
address = address.trim(); |
327 |
if( address.length() <= 0 ) |
|
328 |
{ |
|
329 |
// TODO: warn that an imported address is being ignored |
|
330 |
return; |
|
331 |
} |
|
332 |
||
37
by edam
- updated TODO and NEWS |
333 |
if( _addresses == null ) _addresses = |
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
334 |
new HashMap< String, TypeDetail >(); |
37
by edam
- updated TODO and NEWS |
335 |
if( !_addresses.containsKey( address ) ) |
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
336 |
_addresses.put( address, new TypeDetail( type ) ); |
337 |
} |
|
338 |
||
339 |
public boolean hasAddresses() |
|
340 |
{ |
|
341 |
return _addresses != null && _addresses.size() > 0; |
|
342 |
} |
|
343 |
||
344 |
public HashMap< String, TypeDetail > getAddresses() |
|
345 |
{ |
|
346 |
return _addresses; |
|
347 |
} |
|
348 |
||
65
by edam
added support for notes; rewrote backends so that all normalising of data is now done within the contacts cache; made the vCard unescape routine slightly more acceptant of non-standard escaped characters |
349 |
protected void addNote( String note ) |
350 |
{ |
|
351 |
if( _notes == null ) _notes = new HashSet< String >(); |
|
352 |
if( !_notes.contains( note ) ) |
|
353 |
_notes.add( note ); |
|
354 |
} |
|
355 |
||
356 |
public boolean hasNotes() |
|
357 |
{ |
|
358 |
return _notes != null && _notes.size() > 0; |
|
359 |
} |
|
360 |
||
361 |
public HashSet< String > getNotes() |
|
362 |
{ |
|
363 |
return _notes; |
|
364 |
} |
|
365 |
||
95
by Tim Marston
added suopport for birthdays |
366 |
public void setBirthday( String birthday ) |
367 |
{ |
|
368 |
_birthday = birthday; |
|
369 |
} |
|
370 |
||
371 |
public boolean hasBirthday() |
|
372 |
{ |
|
373 |
return _birthday != null; |
|
374 |
} |
|
375 |
||
376 |
public String getBirthday() |
|
377 |
{ |
|
378 |
return _birthday; |
|
379 |
} |
|
380 |
||
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
381 |
protected void finalise() |
43
by edam
- refactored some code to do with how contacts are imported |
382 |
throws ContactNotIdentifiableException |
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
383 |
{ |
93
by Tim Marston
minor style tweaks |
384 |
// Ensure that if there is a primary number, it is preferred so |
385 |
// that there is always one preferred number. Android will assign |
|
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
386 |
// preference to one anyway so we might as well decide one sensibly. |
387 |
if( _primary_number != null ) { |
|
388 |
PreferredDetail data = _numbers.get( _primary_number ); |
|
389 |
_numbers.put( _primary_number, |
|
390 |
new PreferredDetail( data.getType(), true ) ); |
|
391 |
} |
|
392 |
||
393 |
// do the same for the primary email |
|
394 |
if( _primary_email != null ) { |
|
395 |
PreferredDetail data = _emails.get( _primary_email ); |
|
396 |
_emails.put( _primary_email, |
|
397 |
new PreferredDetail( data.getType(), true ) ); |
|
398 |
} |
|
399 |
||
400 |
// do the same for the primary organisation |
|
401 |
if( _primary_organisation != null ) { |
|
402 |
ExtraDetail data = _organisations.get( _primary_organisation ); |
|
403 |
_organisations.put( _primary_organisation, |
|
404 |
new ExtraDetail( 0, true, data.getExtra() ) ); |
|
405 |
} |
|
43
by edam
- refactored some code to do with how contacts are imported |
406 |
|
407 |
// create a cache identifier from this contact data, which can be |
|
408 |
// used to look-up an existing contact |
|
65
by edam
added support for notes; rewrote backends so that all normalising of data is now done within the contacts cache; made the vCard unescape routine slightly more acceptant of non-standard escaped characters |
409 |
_cache_identifier = ContactsCache.CacheIdentifier.factory( this ); |
43
by edam
- refactored some code to do with how contacts are imported |
410 |
if( _cache_identifier == null ) |
411 |
throw new ContactNotIdentifiableException(); |
|
412 |
} |
|
413 |
||
414 |
public ContactsCache.CacheIdentifier getCacheIdentifier() |
|
415 |
{ |
|
416 |
return _cache_identifier; |
|
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
417 |
} |
418 |
||
419 |
private String sanitisePhoneNumber( String number ) |
|
420 |
{ |
|
421 |
number = number.trim(); |
|
422 |
Pattern p = Pattern.compile( "^[-\\(\\) \\+0-9#*]+" ); |
|
423 |
Matcher m = p.matcher( number ); |
|
424 |
if( m.lookingAt() ) return m.group( 0 ); |
|
425 |
return null; |
|
426 |
} |
|
427 |
||
428 |
private String sanitisesEmailAddress( String email ) |
|
429 |
{ |
|
430 |
email = email.trim(); |
|
431 |
Pattern p = Pattern.compile( |
|
432 |
"^[^ @]+@[a-zA-Z]([-a-zA-Z0-9]*[a-zA-z0-9])?(\\.[a-zA-Z]([-a-zA-Z0-9]*[a-zA-z0-9])?)+$" ); |
|
433 |
Matcher m = p.matcher( email ); |
|
434 |
if( m.matches() ) { |
|
435 |
String[] bits = email.split( "@" ); |
|
61
by edam
made contacts backend throw exceptions when it can't create contacts on the device; specified Locale in lower/upper case conversions; stripped old Contacts types from Importer (and replaced with our own types, which are now converted in the backend; switched using Integer() constructors to Integer.valueOf(); rewrote the main importer routine a bit |
436 |
return bits[ 0 ] + "@" + bits[ 1 ].toLowerCase( Locale.US ); |
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
437 |
} |
438 |
return null; |
|
37
by edam
- updated TODO and NEWS |
439 |
} |
1
by edam
Initial import |
440 |
} |
441 |
||
14
by edam
- got rid of the pretend ImportContacts activity alltogether (and made the Intro activity the startup one) |
442 |
@SuppressWarnings("serial") |
1
by edam
Initial import |
443 |
protected class AbortImportException extends Exception { }; |
444 |
||
445 |
public Importer( Doit doit ) |
|
446 |
{ |
|
447 |
_doit = doit; |
|
448 |
||
449 |
SharedPreferences prefs = getSharedPreferences(); |
|
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
450 |
_merge_setting = prefs.getInt( "merge_setting", Doit.ACTION_PROMPT ); |
1
by edam
Initial import |
451 |
} |
452 |
||
453 |
@Override |
|
454 |
public void run() |
|
455 |
{ |
|
456 |
try |
|
457 |
{ |
|
39
by edam
- pulled contacts cache out in to seperate class |
458 |
// update UI |
459 |
setProgressMessage( R.string.doit_caching ); |
|
460 |
||
57
by edam
cleanup; fixed some typos; updated TODO |
461 |
// create the appropriate backend |
62
by edam
added preliminary (buggy) ContactsContract backend |
462 |
if( Integer.parseInt( android.os.Build.VERSION.SDK ) >= 5 ) |
463 |
_backend = new ContactsContractBackend( _doit ); |
|
464 |
else |
|
53
by edam
abstracted the android contacts API in to an interface, ready to be switched to |
465 |
_backend = new ContactsBackend( _doit ); |
466 |
||
467 |
// create a cache of existing contacts and populate it |
|
41
by edam
- updated TODO |
468 |
_contacts_cache = new ContactsCache(); |
53
by edam
abstracted the android contacts API in to an interface, ready to be switched to |
469 |
_backend.populateCache( _contacts_cache ); |
1
by edam
Initial import |
470 |
|
471 |
// do the import |
|
472 |
onImport(); |
|
473 |
||
474 |
// done! |
|
3
by edam
- added "all done" message |
475 |
finish( ACTION_ALLDONE ); |
1
by edam
Initial import |
476 |
} |
477 |
catch( AbortImportException e ) |
|
478 |
{} |
|
3
by edam
- added "all done" message |
479 |
|
480 |
// flag as finished to prevent interrupts |
|
481 |
setIsFinished(); |
|
482 |
} |
|
483 |
||
484 |
synchronized private void setIsFinished() |
|
485 |
{ |
|
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
486 |
_is_finished = true; |
1
by edam
Initial import |
487 |
} |
488 |
||
489 |
protected void onImport() throws AbortImportException |
|
490 |
{ |
|
491 |
} |
|
492 |
||
493 |
public void wake() |
|
494 |
{ |
|
495 |
wake( 0, RESPONSEEXTRA_NONE ); |
|
496 |
} |
|
497 |
||
498 |
public void wake( int response ) |
|
499 |
{ |
|
500 |
wake( response, RESPONSEEXTRA_NONE ); |
|
501 |
} |
|
502 |
||
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
503 |
synchronized public void wake( int response, int response_extra ) |
1
by edam
Initial import |
504 |
{ |
505 |
_response = response; |
|
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
506 |
_response_extra = response_extra; |
1
by edam
Initial import |
507 |
notify(); |
508 |
} |
|
509 |
||
3
by edam
- added "all done" message |
510 |
synchronized public boolean setAbort() |
1
by edam
Initial import |
511 |
{ |
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
512 |
if( !_is_finished && !_abort ) { |
3
by edam
- added "all done" message |
513 |
_abort = true; |
514 |
notify(); |
|
515 |
return true; |
|
516 |
} |
|
517 |
return false; |
|
1
by edam
Initial import |
518 |
} |
519 |
||
520 |
protected SharedPreferences getSharedPreferences() |
|
521 |
{ |
|
522 |
return _doit.getSharedPreferences(); |
|
523 |
} |
|
524 |
||
525 |
protected void showError( int res ) throws AbortImportException |
|
526 |
{ |
|
527 |
showError( _doit.getText( res ).toString() ); |
|
528 |
} |
|
529 |
||
530 |
synchronized protected void showError( String message ) |
|
531 |
throws AbortImportException |
|
532 |
{ |
|
533 |
checkAbort(); |
|
534 |
_doit._handler.sendMessage( Message.obtain( |
|
36
by edam
- formatting: removed some double-indents on overrunning lines |
535 |
_doit._handler, Doit.MESSAGE_ERROR, message ) ); |
1
by edam
Initial import |
536 |
try { |
537 |
wait(); |
|
538 |
} |
|
539 |
catch( InterruptedException e ) { } |
|
14
by edam
- got rid of the pretend ImportContacts activity alltogether (and made the Intro activity the startup one) |
540 |
|
3
by edam
- added "all done" message |
541 |
// no need to check if an abortion happened during the wait, we are |
542 |
// about to finish anyway! |
|
543 |
finish( ACTION_ABORT ); |
|
1
by edam
Initial import |
544 |
} |
545 |
||
546 |
protected void showFatalError( int res ) throws AbortImportException |
|
547 |
{ |
|
548 |
showFatalError( _doit.getText( res ).toString() ); |
|
549 |
} |
|
550 |
||
551 |
synchronized protected void showFatalError( String message ) |
|
552 |
throws AbortImportException |
|
553 |
{ |
|
554 |
checkAbort(); |
|
555 |
_doit._handler.sendMessage( Message.obtain( |
|
36
by edam
- formatting: removed some double-indents on overrunning lines |
556 |
_doit._handler, Doit.MESSAGE_ERROR, message ) ); |
1
by edam
Initial import |
557 |
try { |
558 |
wait(); |
|
559 |
} |
|
560 |
catch( InterruptedException e ) { } |
|
14
by edam
- got rid of the pretend ImportContacts activity alltogether (and made the Intro activity the startup one) |
561 |
|
3
by edam
- added "all done" message |
562 |
// no need to check if an abortion happened during the wait, we are |
563 |
// about to finish anyway! |
|
564 |
finish( ACTION_ABORT ); |
|
1
by edam
Initial import |
565 |
} |
566 |
||
567 |
protected boolean showContinue( int res ) throws AbortImportException |
|
568 |
{ |
|
569 |
return showContinue( _doit.getText( res ).toString() ); |
|
570 |
} |
|
571 |
||
572 |
synchronized protected boolean showContinue( String message ) |
|
573 |
throws AbortImportException |
|
574 |
{ |
|
575 |
checkAbort(); |
|
576 |
_doit._handler.sendMessage( Message.obtain( |
|
36
by edam
- formatting: removed some double-indents on overrunning lines |
577 |
_doit._handler, Doit.MESSAGE_CONTINUEORABORT, message ) ); |
1
by edam
Initial import |
578 |
try { |
579 |
wait(); |
|
580 |
} |
|
581 |
catch( InterruptedException e ) { } |
|
3
by edam
- added "all done" message |
582 |
|
583 |
// check if an abortion happened during the wait |
|
584 |
checkAbort(); |
|
585 |
||
1
by edam
Initial import |
586 |
return _response == RESPONSE_POSITIVE; |
587 |
} |
|
588 |
||
589 |
protected void setProgressMessage( int res ) throws AbortImportException |
|
590 |
{ |
|
591 |
checkAbort(); |
|
592 |
_doit._handler.sendMessage( Message.obtain( _doit._handler, |
|
36
by edam
- formatting: removed some double-indents on overrunning lines |
593 |
Doit.MESSAGE_SETPROGRESSMESSAGE, getText( res ) ) ); |
1
by edam
Initial import |
594 |
} |
595 |
||
41
by edam
- updated TODO |
596 |
protected void setProgressMax( int max_progress ) |
1
by edam
Initial import |
597 |
throws AbortImportException |
598 |
{ |
|
599 |
checkAbort(); |
|
600 |
_doit._handler.sendMessage( Message.obtain( |
|
36
by edam
- formatting: removed some double-indents on overrunning lines |
601 |
_doit._handler, Doit.MESSAGE_SETMAXPROGRESS, |
61
by edam
made contacts backend throw exceptions when it can't create contacts on the device; specified Locale in lower/upper case conversions; stripped old Contacts types from Importer (and replaced with our own types, which are now converted in the backend; switched using Integer() constructors to Integer.valueOf(); rewrote the main importer routine a bit |
602 |
Integer.valueOf( max_progress ) ) ); |
1
by edam
Initial import |
603 |
} |
604 |
||
41
by edam
- updated TODO |
605 |
protected void setTmpProgress( int tmp_progress ) |
606 |
throws AbortImportException |
|
1
by edam
Initial import |
607 |
{ |
608 |
checkAbort(); |
|
609 |
_doit._handler.sendMessage( Message.obtain( |
|
36
by edam
- formatting: removed some double-indents on overrunning lines |
610 |
_doit._handler, Doit.MESSAGE_SETTMPPROGRESS, |
61
by edam
made contacts backend throw exceptions when it can't create contacts on the device; specified Locale in lower/upper case conversions; stripped old Contacts types from Importer (and replaced with our own types, which are now converted in the backend; switched using Integer() constructors to Integer.valueOf(); rewrote the main importer routine a bit |
611 |
Integer.valueOf( tmp_progress ) ) ); |
1
by edam
Initial import |
612 |
} |
613 |
||
614 |
protected void setProgress( int progress ) throws AbortImportException |
|
615 |
{ |
|
616 |
checkAbort(); |
|
617 |
_doit._handler.sendMessage( Message.obtain( |
|
36
by edam
- formatting: removed some double-indents on overrunning lines |
618 |
_doit._handler, Doit.MESSAGE_SETPROGRESS, |
61
by edam
made contacts backend throw exceptions when it can't create contacts on the device; specified Locale in lower/upper case conversions; stripped old Contacts types from Importer (and replaced with our own types, which are now converted in the backend; switched using Integer() constructors to Integer.valueOf(); rewrote the main importer routine a bit |
619 |
Integer.valueOf( progress ) ) ); |
1
by edam
Initial import |
620 |
} |
621 |
||
3
by edam
- added "all done" message |
622 |
protected void finish( int action ) throws AbortImportException |
1
by edam
Initial import |
623 |
{ |
3
by edam
- added "all done" message |
624 |
// update UI to reflect action |
625 |
int message; |
|
626 |
switch( action ) |
|
627 |
{ |
|
14
by edam
- got rid of the pretend ImportContacts activity alltogether (and made the Intro activity the startup one) |
628 |
case ACTION_ALLDONE: message = Doit.MESSAGE_ALLDONE; break; |
3
by edam
- added "all done" message |
629 |
default: // fall through |
14
by edam
- got rid of the pretend ImportContacts activity alltogether (and made the Intro activity the startup one) |
630 |
case ACTION_ABORT: message = Doit.MESSAGE_ABORT; break; |
3
by edam
- added "all done" message |
631 |
} |
632 |
_doit._handler.sendEmptyMessage( message ); |
|
1
by edam
Initial import |
633 |
|
3
by edam
- added "all done" message |
634 |
// stop |
635 |
throw new AbortImportException(); |
|
1
by edam
Initial import |
636 |
} |
637 |
||
638 |
protected CharSequence getText( int res ) |
|
639 |
{ |
|
640 |
return _doit.getText( res ); |
|
641 |
} |
|
642 |
||
61
by edam
made contacts backend throw exceptions when it can't create contacts on the device; specified Locale in lower/upper case conversions; stripped old Contacts types from Importer (and replaced with our own types, which are now converted in the backend; switched using Integer() constructors to Integer.valueOf(); rewrote the main importer routine a bit |
643 |
/** |
644 |
* Should we skip a contact, given whether it exists or not and the current |
|
645 |
* merge setting? This routine handles throwing up a prompt, if required. |
|
93
by Tim Marston
minor style tweaks |
646 |
* |
61
by edam
made contacts backend throw exceptions when it can't create contacts on the device; specified Locale in lower/upper case conversions; stripped old Contacts types from Importer (and replaced with our own types, which are now converted in the backend; switched using Integer() constructors to Integer.valueOf(); rewrote the main importer routine a bit |
647 |
* @param contact_detail the display name of the contact |
648 |
* @param exists true if this contact matches one in the cache |
|
649 |
* @param merge_setting the merge setting to use |
|
650 |
* @return true if the contact should be skipped outright |
|
651 |
* @throws AbortImportException |
|
652 |
*/ |
|
653 |
synchronized private boolean shouldWeSkipContact( String contact_detail, |
|
654 |
boolean exists, int merge_setting ) throws AbortImportException |
|
1
by edam
Initial import |
655 |
{ |
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
656 |
_last_merge_decision = merge_setting; |
657 |
||
1
by edam
Initial import |
658 |
// handle special cases |
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
659 |
switch( merge_setting ) |
1
by edam
Initial import |
660 |
{ |
9
by edam
- added scroll view to all layouts |
661 |
case Doit.ACTION_KEEP: |
61
by edam
made contacts backend throw exceptions when it can't create contacts on the device; specified Locale in lower/upper case conversions; stripped old Contacts types from Importer (and replaced with our own types, which are now converted in the backend; switched using Integer() constructors to Integer.valueOf(); rewrote the main importer routine a bit |
662 |
// if we are skipping on a duplicate, check for one |
663 |
return exists; |
|
1
by edam
Initial import |
664 |
|
9
by edam
- added scroll view to all layouts |
665 |
case Doit.ACTION_PROMPT: |
61
by edam
made contacts backend throw exceptions when it can't create contacts on the device; specified Locale in lower/upper case conversions; stripped old Contacts types from Importer (and replaced with our own types, which are now converted in the backend; switched using Integer() constructors to Integer.valueOf(); rewrote the main importer routine a bit |
666 |
// if we are prompting on duplicate, then we can say that we won't |
667 |
// skip if there isn't one |
|
668 |
if( !exists ) return false; |
|
1
by edam
Initial import |
669 |
|
61
by edam
made contacts backend throw exceptions when it can't create contacts on the device; specified Locale in lower/upper case conversions; stripped old Contacts types from Importer (and replaced with our own types, which are now converted in the backend; switched using Integer() constructors to Integer.valueOf(); rewrote the main importer routine a bit |
670 |
// ok, duplicate exists, so do prompt |
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
671 |
_doit._handler.sendMessage( Message.obtain( _doit._handler, |
61
by edam
made contacts backend throw exceptions when it can't create contacts on the device; specified Locale in lower/upper case conversions; stripped old Contacts types from Importer (and replaced with our own types, which are now converted in the backend; switched using Integer() constructors to Integer.valueOf(); rewrote the main importer routine a bit |
672 |
Doit.MESSAGE_MERGEPROMPT, contact_detail ) ); |
1
by edam
Initial import |
673 |
try { |
674 |
wait(); |
|
675 |
} |
|
676 |
catch( InterruptedException e ) { } |
|
677 |
||
3
by edam
- added "all done" message |
678 |
// check if an abortion happened during the wait |
679 |
checkAbort(); |
|
680 |
||
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
681 |
// if "always" was selected, make choice permanent |
682 |
if( _response_extra == RESPONSEEXTRA_ALWAYS ) |
|
683 |
_merge_setting = _response; |
|
1
by edam
Initial import |
684 |
|
36
by edam
- formatting: removed some double-indents on overrunning lines |
685 |
// recurse, with our new merge setting |
61
by edam
made contacts backend throw exceptions when it can't create contacts on the device; specified Locale in lower/upper case conversions; stripped old Contacts types from Importer (and replaced with our own types, which are now converted in the backend; switched using Integer() constructors to Integer.valueOf(); rewrote the main importer routine a bit |
686 |
return shouldWeSkipContact( contact_detail, exists, _response ); |
1
by edam
Initial import |
687 |
} |
688 |
||
61
by edam
made contacts backend throw exceptions when it can't create contacts on the device; specified Locale in lower/upper case conversions; stripped old Contacts types from Importer (and replaced with our own types, which are now converted in the backend; switched using Integer() constructors to Integer.valueOf(); rewrote the main importer routine a bit |
689 |
// for all other cases (either overwriting or merging) we don't skip |
690 |
return false; |
|
1
by edam
Initial import |
691 |
} |
692 |
||
693 |
protected void skipContact() throws AbortImportException |
|
694 |
{ |
|
695 |
checkAbort(); |
|
61
by edam
made contacts backend throw exceptions when it can't create contacts on the device; specified Locale in lower/upper case conversions; stripped old Contacts types from Importer (and replaced with our own types, which are now converted in the backend; switched using Integer() constructors to Integer.valueOf(); rewrote the main importer routine a bit |
696 |
|
697 |
// show that we're skipping a new contact |
|
3
by edam
- added "all done" message |
698 |
_doit._handler.sendEmptyMessage( Doit.MESSAGE_CONTACTSKIPPED ); |
1
by edam
Initial import |
699 |
} |
700 |
||
701 |
protected void importContact( ContactData contact ) |
|
702 |
throws AbortImportException |
|
703 |
{ |
|
704 |
checkAbort(); |
|
705 |
||
93
by Tim Marston
minor style tweaks |
706 |
// It is expected that we use contact.getCacheIdentifier() here. The |
43
by edam
- refactored some code to do with how contacts are imported |
707 |
// contact we are passed should have been successfully finalise()d, |
708 |
// which includes generating a valid cache identifier. |
|
709 |
ContactsCache.CacheIdentifier cache_identifier = |
|
710 |
contact.getCacheIdentifier(); |
|
711 |
||
3
by edam
- added "all done" message |
712 |
// if( !showContinue( "====[ IMPORTING ]====\n: " + contact._name ) ) |
713 |
// finish( ACTION_ABORT ); |
|
1
by edam
Initial import |
714 |
|
43
by edam
- refactored some code to do with how contacts are imported |
715 |
// attempt to lookup the id of an existing contact in the cache with |
716 |
// this contact data's cache identifier |
|
717 |
Long id = (Long)_contacts_cache.lookup( cache_identifier ); |
|
1
by edam
Initial import |
718 |
|
61
by edam
made contacts backend throw exceptions when it can't create contacts on the device; specified Locale in lower/upper case conversions; stripped old Contacts types from Importer (and replaced with our own types, which are now converted in the backend; switched using Integer() constructors to Integer.valueOf(); rewrote the main importer routine a bit |
719 |
// check to see if this contact should be skipped |
720 |
if( shouldWeSkipContact( cache_identifier.getDetail(), id != null, |
|
721 |
_merge_setting ) ) |
|
722 |
{ |
|
723 |
// show that we're skipping a contact |
|
724 |
_doit._handler.sendEmptyMessage( Doit.MESSAGE_CONTACTSKIPPED ); |
|
725 |
return; |
|
726 |
} |
|
727 |
||
728 |
// if a contact exists, and we're overwriting, destroy the existing |
|
729 |
// contact before importing |
|
730 |
boolean contact_deleted = false; |
|
731 |
if( id != null && _last_merge_decision == Doit.ACTION_OVERWRITE ) |
|
732 |
{ |
|
733 |
contact_deleted = true; |
|
734 |
||
735 |
// remove from device |
|
736 |
_backend.deleteContact( id ); |
|
737 |
||
738 |
// update cache |
|
739 |
_contacts_cache.removeLookup( cache_identifier ); |
|
740 |
_contacts_cache.removeAssociatedData( id ); |
|
741 |
||
742 |
// show that we're overwriting a contact |
|
743 |
_doit._handler.sendEmptyMessage( Doit.MESSAGE_CONTACTOVERWRITTEN ); |
|
744 |
||
745 |
// discard the contact id |
|
746 |
id = null; |
|
747 |
} |
|
748 |
||
749 |
try { |
|
750 |
// if we don't have a contact id yet (or we did, but we destroyed it |
|
751 |
// when we deleted the contact), we'll have to create a new contact |
|
752 |
if( id == null ) |
|
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
753 |
{ |
61
by edam
made contacts backend throw exceptions when it can't create contacts on the device; specified Locale in lower/upper case conversions; stripped old Contacts types from Importer (and replaced with our own types, which are now converted in the backend; switched using Integer() constructors to Integer.valueOf(); rewrote the main importer routine a bit |
754 |
// create a new contact |
755 |
id = _backend.addContact( contact._name ); |
|
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
756 |
|
757 |
// update cache |
|
61
by edam
made contacts backend throw exceptions when it can't create contacts on the device; specified Locale in lower/upper case conversions; stripped old Contacts types from Importer (and replaced with our own types, which are now converted in the backend; switched using Integer() constructors to Integer.valueOf(); rewrote the main importer routine a bit |
758 |
_contacts_cache.addLookup( cache_identifier, id ); |
759 |
||
760 |
// if we haven't already shown that we're overwriting a contact, |
|
761 |
// show that we're creating a new contact |
|
762 |
if( !contact_deleted ) |
|
763 |
_doit._handler.sendEmptyMessage( |
|
764 |
Doit.MESSAGE_CONTACTCREATED ); |
|
1
by edam
Initial import |
765 |
} |
61
by edam
made contacts backend throw exceptions when it can't create contacts on the device; specified Locale in lower/upper case conversions; stripped old Contacts types from Importer (and replaced with our own types, which are now converted in the backend; switched using Integer() constructors to Integer.valueOf(); rewrote the main importer routine a bit |
766 |
else |
767 |
// show that we're merging with an existing contact |
|
768 |
_doit._handler.sendEmptyMessage( Doit.MESSAGE_CONTACTMERGED ); |
|
769 |
||
770 |
// import contact parts |
|
771 |
if( contact.hasNumbers() ) |
|
772 |
importContactPhones( id, contact.getNumbers() ); |
|
773 |
if( contact.hasEmails() ) |
|
774 |
importContactEmails( id, contact.getEmails() ); |
|
775 |
if( contact.hasAddresses() ) |
|
776 |
importContactAddresses( id, contact.getAddresses() ); |
|
777 |
if( contact.hasOrganisations() ) |
|
778 |
importContactOrganisations( id, contact.getOrganisations() ); |
|
65
by edam
added support for notes; rewrote backends so that all normalising of data is now done within the contacts cache; made the vCard unescape routine slightly more acceptant of non-standard escaped characters |
779 |
if( contact.hasNotes() ) |
780 |
importContactNotes( id, contact.getNotes() ); |
|
95
by Tim Marston
added suopport for birthdays |
781 |
if( contact.hasBirthday() ) |
782 |
importContactBirthday( id, contact.getBirthday() ); |
|
1
by edam
Initial import |
783 |
} |
61
by edam
made contacts backend throw exceptions when it can't create contacts on the device; specified Locale in lower/upper case conversions; stripped old Contacts types from Importer (and replaced with our own types, which are now converted in the backend; switched using Integer() constructors to Integer.valueOf(); rewrote the main importer routine a bit |
784 |
catch( Backend.ContactCreationException e ) |
1
by edam
Initial import |
785 |
{ |
61
by edam
made contacts backend throw exceptions when it can't create contacts on the device; specified Locale in lower/upper case conversions; stripped old Contacts types from Importer (and replaced with our own types, which are now converted in the backend; switched using Integer() constructors to Integer.valueOf(); rewrote the main importer routine a bit |
786 |
showError( R.string.error_unabletoaddcontact ); |
1
by edam
Initial import |
787 |
} |
788 |
} |
|
789 |
||
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
790 |
private void importContactPhones( Long id, |
61
by edam
made contacts backend throw exceptions when it can't create contacts on the device; specified Locale in lower/upper case conversions; stripped old Contacts types from Importer (and replaced with our own types, which are now converted in the backend; switched using Integer() constructors to Integer.valueOf(); rewrote the main importer routine a bit |
791 |
HashMap< String, ContactData.PreferredDetail > datas ) |
792 |
throws ContactCreationException |
|
1
by edam
Initial import |
793 |
{ |
7
by edam
- 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!?) |
794 |
// add phone numbers |
53
by edam
abstracted the android contacts API in to an interface, ready to be switched to |
795 |
Set< String > datas_keys = datas.keySet(); |
41
by edam
- updated TODO |
796 |
Iterator< String > i = datas_keys.iterator(); |
1
by edam
Initial import |
797 |
while( i.hasNext() ) { |
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
798 |
String number = i.next(); |
799 |
ContactData.PreferredDetail data = datas.get( number ); |
|
1
by edam
Initial import |
800 |
|
93
by Tim Marston
minor style tweaks |
801 |
// We don't want to add this number if it's crap, or it already |
802 |
// exists (which would cause a duplicate to be created). We don't |
|
803 |
// take in to account the type when checking for duplicates. This |
|
804 |
// is intentional: types aren't really very reliable. We assume |
|
805 |
// that if the number exists at all, it doesn't need importing. |
|
806 |
// Because of this, we also can't update the cache (which we don't |
|
807 |
// need to anyway, so it's not a problem). |
|
41
by edam
- updated TODO |
808 |
if( _contacts_cache.hasAssociatedNumber( id, number ) ) |
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
809 |
continue; |
1
by edam
Initial import |
810 |
|
811 |
// add phone number |
|
53
by edam
abstracted the android contacts API in to an interface, ready to be switched to |
812 |
_backend.addContactPhone( id, number, data ); |
37
by edam
- updated TODO and NEWS |
813 |
|
814 |
// and add this address to the cache to prevent a addition of |
|
815 |
// duplicate date from another file |
|
41
by edam
- updated TODO |
816 |
_contacts_cache.addAssociatedNumber( id, number ); |
7
by edam
- 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!?) |
817 |
} |
1
by edam
Initial import |
818 |
} |
819 |
||
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
820 |
private void importContactEmails( Long id, |
61
by edam
made contacts backend throw exceptions when it can't create contacts on the device; specified Locale in lower/upper case conversions; stripped old Contacts types from Importer (and replaced with our own types, which are now converted in the backend; switched using Integer() constructors to Integer.valueOf(); rewrote the main importer routine a bit |
821 |
HashMap< String, ContactData.PreferredDetail > datas ) |
822 |
throws ContactCreationException |
|
1
by edam
Initial import |
823 |
{ |
7
by edam
- 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!?) |
824 |
// add email addresses |
53
by edam
abstracted the android contacts API in to an interface, ready to be switched to |
825 |
Set< String > datas_keys = datas.keySet(); |
41
by edam
- updated TODO |
826 |
Iterator< String > i = datas_keys.iterator(); |
1
by edam
Initial import |
827 |
while( i.hasNext() ) { |
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
828 |
String email = i.next(); |
829 |
ContactData.PreferredDetail data = datas.get( email ); |
|
1
by edam
Initial import |
830 |
|
37
by edam
- updated TODO and NEWS |
831 |
// we don't want to add this email address if it exists already or |
93
by Tim Marston
minor style tweaks |
832 |
// we would introduce duplicates |
41
by edam
- updated TODO |
833 |
if( _contacts_cache.hasAssociatedEmail( id, email ) ) |
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
834 |
continue; |
1
by edam
Initial import |
835 |
|
836 |
// add phone number |
|
53
by edam
abstracted the android contacts API in to an interface, ready to be switched to |
837 |
_backend.addContactEmail( id, email, data ); |
37
by edam
- updated TODO and NEWS |
838 |
|
839 |
// and add this address to the cache to prevent a addition of |
|
840 |
// duplicate date from another file |
|
41
by edam
- updated TODO |
841 |
_contacts_cache.addAssociatedEmail( id, email ); |
1
by edam
Initial import |
842 |
} |
37
by edam
- updated TODO and NEWS |
843 |
} |
844 |
||
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
845 |
private void importContactAddresses( Long id, |
846 |
HashMap< String, ContactData.TypeDetail > datas ) |
|
61
by edam
made contacts backend throw exceptions when it can't create contacts on the device; specified Locale in lower/upper case conversions; stripped old Contacts types from Importer (and replaced with our own types, which are now converted in the backend; switched using Integer() constructors to Integer.valueOf(); rewrote the main importer routine a bit |
847 |
throws ContactCreationException |
37
by edam
- updated TODO and NEWS |
848 |
{ |
849 |
// add addresses |
|
41
by edam
- updated TODO |
850 |
Set< String > datas_keys = datas.keySet(); |
851 |
Iterator< String > i = datas_keys.iterator(); |
|
7
by edam
- 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!?) |
852 |
while( i.hasNext() ) { |
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
853 |
String address = i.next(); |
854 |
ContactData.TypeDetail data = datas.get( address ); |
|
37
by edam
- updated TODO and NEWS |
855 |
|
856 |
// we don't want to add this address if it exists already or we |
|
857 |
// would introduce duplicates |
|
41
by edam
- updated TODO |
858 |
if( _contacts_cache.hasAssociatedAddress( id, address ) ) |
37
by edam
- updated TODO and NEWS |
859 |
continue; |
860 |
||
861 |
// add postal address |
|
53
by edam
abstracted the android contacts API in to an interface, ready to be switched to |
862 |
_backend.addContactAddresses( id, address, data ); |
37
by edam
- updated TODO and NEWS |
863 |
|
864 |
// and add this address to the cache to prevent a addition of |
|
865 |
// duplicate date from another file |
|
41
by edam
- updated TODO |
866 |
_contacts_cache.addAssociatedAddress( id, address ); |
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
867 |
} |
868 |
} |
|
869 |
||
870 |
private void importContactOrganisations( Long id, |
|
871 |
HashMap< String, ContactData.ExtraDetail > datas ) |
|
61
by edam
made contacts backend throw exceptions when it can't create contacts on the device; specified Locale in lower/upper case conversions; stripped old Contacts types from Importer (and replaced with our own types, which are now converted in the backend; switched using Integer() constructors to Integer.valueOf(); rewrote the main importer routine a bit |
872 |
throws ContactCreationException |
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
873 |
{ |
874 |
// add addresses |
|
41
by edam
- updated TODO |
875 |
Set< String > datas_keys = datas.keySet(); |
876 |
Iterator< String > i = datas_keys.iterator(); |
|
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
877 |
while( i.hasNext() ) { |
878 |
String organisation = i.next(); |
|
879 |
ContactData.ExtraDetail data = datas.get( organisation ); |
|
880 |
||
881 |
// we don't want to add this address if it exists already or we |
|
882 |
// would introduce duplicates |
|
41
by edam
- updated TODO |
883 |
if( _contacts_cache.hasAssociatedOrganisation( id, organisation ) ) |
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
884 |
continue; |
885 |
||
886 |
// add organisation address |
|
53
by edam
abstracted the android contacts API in to an interface, ready to be switched to |
887 |
_backend.addContactOrganisation( id, organisation, data ); |
40
by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works |
888 |
|
889 |
// and add this address to the cache to prevent a addition of |
|
890 |
// duplicate date from another file |
|
41
by edam
- updated TODO |
891 |
_contacts_cache.addAssociatedOrganisation( id, organisation ); |
7
by edam
- 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!?) |
892 |
} |
1
by edam
Initial import |
893 |
} |
894 |
||
95
by Tim Marston
added suopport for birthdays |
895 |
private void importContactNotes( Long id, HashSet< String > datas ) |
65
by edam
added support for notes; rewrote backends so that all normalising of data is now done within the contacts cache; made the vCard unescape routine slightly more acceptant of non-standard escaped characters |
896 |
throws ContactCreationException |
897 |
{ |
|
898 |
// add notes |
|
899 |
Iterator< String > i = datas.iterator(); |
|
900 |
while( i.hasNext() ) { |
|
901 |
String note = i.next(); |
|
902 |
||
903 |
// we don't want to add this note if it exists already or we would |
|
904 |
// introduce duplicates |
|
905 |
if( _contacts_cache.hasAssociatedNote( id, note ) ) |
|
906 |
continue; |
|
907 |
||
908 |
// add note |
|
909 |
_backend.addContactNote( id, note ); |
|
910 |
||
911 |
// and add this note to the cache to prevent a addition of duplicate |
|
912 |
// date from another file |
|
913 |
_contacts_cache.addAssociatedNote( id, note ); |
|
914 |
} |
|
95
by Tim Marston
added suopport for birthdays |
915 |
} |
916 |
||
917 |
private void importContactBirthday( Long id, String birthday ) |
|
918 |
throws ContactCreationException |
|
919 |
{ |
|
920 |
// we don't want to import this birthday if it already exists |
|
921 |
if( _contacts_cache.hasAssociatedBirthday( id, birthday ) ) |
|
922 |
return; |
|
923 |
||
924 |
// add birthday |
|
925 |
_backend.addContactBirthday( id, birthday ); |
|
926 |
||
927 |
// and update the cache |
|
928 |
_contacts_cache.addAssociatedBirthday( id, birthday ); |
|
65
by edam
added support for notes; rewrote backends so that all normalising of data is now done within the contacts cache; made the vCard unescape routine slightly more acceptant of non-standard escaped characters |
929 |
} |
930 |
||
3
by edam
- added "all done" message |
931 |
synchronized protected void checkAbort() throws AbortImportException |
1
by edam
Initial import |
932 |
{ |
933 |
if( _abort ) { |
|
934 |
// stop |
|
935 |
throw new AbortImportException(); |
|
936 |
} |
|
937 |
} |
|
938 |
} |