/android/import-contacts

To get this branch, use:
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( "@" );
111 by Tim Marston
removed some unused code, fixed locale warnings and made showContinueOrAbort()
436
				return bits[ 0 ] + "@" +
437
					bits[ 1 ].toLowerCase( Locale.ENGLISH );
40 by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works
438
			}
439
			return null;
37 by edam
- updated TODO and NEWS
440
		}
1 by edam
Initial import
441
	}
442
14 by edam
- got rid of the pretend ImportContacts activity alltogether (and made the Intro activity the startup one)
443
	@SuppressWarnings("serial")
1 by edam
Initial import
444
	protected class AbortImportException extends Exception { };
445
446
	public Importer( Doit doit )
447
	{
448
		_doit = doit;
449
450
		SharedPreferences prefs = getSharedPreferences();
40 by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works
451
		_merge_setting = prefs.getInt( "merge_setting", Doit.ACTION_PROMPT );
1 by edam
Initial import
452
	}
453
454
	@Override
455
	public void run()
456
	{
457
		try
458
		{
39 by edam
- pulled contacts cache out in to seperate class
459
			// update UI
460
			setProgressMessage( R.string.doit_caching );
461
57 by edam
cleanup; fixed some typos; updated TODO
462
			// create the appropriate backend
62 by edam
added preliminary (buggy) ContactsContract backend
463
			if( Integer.parseInt( android.os.Build.VERSION.SDK ) >= 5 )
464
				_backend = new ContactsContractBackend( _doit );
465
			else
53 by edam
abstracted the android contacts API in to an interface, ready to be switched to
466
				_backend = new ContactsBackend( _doit );
467
468
			// create a cache of existing contacts and populate it
41 by edam
- updated TODO
469
			_contacts_cache = new ContactsCache();
53 by edam
abstracted the android contacts API in to an interface, ready to be switched to
470
			_backend.populateCache( _contacts_cache );
1 by edam
Initial import
471
472
			// do the import
473
			onImport();
474
475
			// done!
3 by edam
- added "all done" message
476
			finish( ACTION_ALLDONE );
1 by edam
Initial import
477
		}
478
		catch( AbortImportException e )
479
		{}
3 by edam
- added "all done" message
480
481
		// flag as finished to prevent interrupts
482
		setIsFinished();
483
	}
484
485
	synchronized private void setIsFinished()
486
	{
40 by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works
487
		_is_finished = true;
1 by edam
Initial import
488
	}
489
490
	protected void onImport() throws AbortImportException
491
	{
492
	}
493
494
	public void wake()
495
	{
496
		wake( 0, RESPONSEEXTRA_NONE );
497
	}
498
499
	public void wake( int response )
500
	{
501
		wake( response, RESPONSEEXTRA_NONE );
502
	}
503
40 by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works
504
	synchronized public void wake( int response, int response_extra )
1 by edam
Initial import
505
	{
506
		_response = response;
40 by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works
507
		_response_extra = response_extra;
1 by edam
Initial import
508
		notify();
509
	}
510
3 by edam
- added "all done" message
511
	synchronized public boolean setAbort()
1 by edam
Initial import
512
	{
40 by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works
513
		if( !_is_finished && !_abort ) {
3 by edam
- added "all done" message
514
			_abort = true;
515
			notify();
516
			return true;
517
		}
518
		return false;
1 by edam
Initial import
519
	}
520
521
	protected SharedPreferences getSharedPreferences()
522
	{
523
		return _doit.getSharedPreferences();
524
	}
525
526
	protected void showError( int res ) throws AbortImportException
527
	{
528
		showError( _doit.getText( res ).toString() );
529
	}
530
531
	synchronized protected void showError( String message )
532
			throws AbortImportException
533
	{
534
		checkAbort();
535
		_doit._handler.sendMessage( Message.obtain(
36 by edam
- formatting: removed some double-indents on overrunning lines
536
			_doit._handler, Doit.MESSAGE_ERROR, message ) );
1 by edam
Initial import
537
		try {
538
			wait();
539
		}
540
		catch( InterruptedException e ) { }
14 by edam
- got rid of the pretend ImportContacts activity alltogether (and made the Intro activity the startup one)
541
3 by edam
- added "all done" message
542
		// no need to check if an abortion happened during the wait, we are
543
		// about to finish anyway!
544
		finish( ACTION_ABORT );
1 by edam
Initial import
545
	}
546
111 by Tim Marston
removed some unused code, fixed locale warnings and made showContinueOrAbort()
547
	protected void showContinueOrAbort( int res ) throws AbortImportException
548
	{
549
		showContinueOrAbort( _doit.getText( res ).toString() );
550
	}
551
552
	synchronized protected void showContinueOrAbort( String message )
1 by edam
Initial import
553
			throws AbortImportException
554
	{
555
		checkAbort();
556
		_doit._handler.sendMessage( Message.obtain(
36 by edam
- formatting: removed some double-indents on overrunning lines
557
			_doit._handler, Doit.MESSAGE_CONTINUEORABORT, message ) );
1 by edam
Initial import
558
		try {
559
			wait();
560
		}
561
		catch( InterruptedException e ) { }
3 by edam
- added "all done" message
562
111 by Tim Marston
removed some unused code, fixed locale warnings and made showContinueOrAbort()
563
		// if we're aborting, there's no need to check if an abortion happened
564
		// during the wait
565
		if( _response == RESPONSE_NEGATIVE )
566
			finish( ACTION_ABORT );
567
		else
568
			checkAbort();
1 by edam
Initial import
569
	}
570
571
	protected void setProgressMessage( int res ) throws AbortImportException
572
	{
573
		checkAbort();
574
		_doit._handler.sendMessage( Message.obtain( _doit._handler,
36 by edam
- formatting: removed some double-indents on overrunning lines
575
			Doit.MESSAGE_SETPROGRESSMESSAGE, getText( res ) ) );
1 by edam
Initial import
576
	}
577
41 by edam
- updated TODO
578
	protected void setProgressMax( int max_progress )
1 by edam
Initial import
579
			throws AbortImportException
580
	{
581
		checkAbort();
582
		_doit._handler.sendMessage( Message.obtain(
36 by edam
- formatting: removed some double-indents on overrunning lines
583
			_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
584
			Integer.valueOf( max_progress ) ) );
1 by edam
Initial import
585
	}
586
41 by edam
- updated TODO
587
	protected void setTmpProgress( int tmp_progress )
588
		throws AbortImportException
1 by edam
Initial import
589
	{
590
		checkAbort();
591
		_doit._handler.sendMessage( Message.obtain(
36 by edam
- formatting: removed some double-indents on overrunning lines
592
			_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
593
			Integer.valueOf( tmp_progress ) ) );
1 by edam
Initial import
594
	}
595
596
	protected void setProgress( int progress ) throws AbortImportException
597
	{
598
		checkAbort();
599
		_doit._handler.sendMessage( Message.obtain(
36 by edam
- formatting: removed some double-indents on overrunning lines
600
			_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
601
			Integer.valueOf( progress ) ) );
1 by edam
Initial import
602
	}
603
3 by edam
- added "all done" message
604
	protected void finish( int action ) throws AbortImportException
1 by edam
Initial import
605
	{
3 by edam
- added "all done" message
606
		// update UI to reflect action
607
		int message;
608
		switch( action )
609
		{
14 by edam
- got rid of the pretend ImportContacts activity alltogether (and made the Intro activity the startup one)
610
		case ACTION_ALLDONE:	message = Doit.MESSAGE_ALLDONE; break;
3 by edam
- added "all done" message
611
		default:	// fall through
14 by edam
- got rid of the pretend ImportContacts activity alltogether (and made the Intro activity the startup one)
612
		case ACTION_ABORT:		message = Doit.MESSAGE_ABORT; break;
3 by edam
- added "all done" message
613
		}
614
		_doit._handler.sendEmptyMessage( message );
1 by edam
Initial import
615
3 by edam
- added "all done" message
616
		// stop
617
		throw new AbortImportException();
1 by edam
Initial import
618
	}
619
620
	protected CharSequence getText( int res )
621
	{
622
		return _doit.getText( res );
623
	}
624
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
625
	/**
626
	 * Should we skip a contact, given whether it exists or not and the current
627
	 * merge setting?  This routine handles throwing up a prompt, if required.
93 by Tim Marston
minor style tweaks
628
	 *
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
629
	 * @param contact_detail the display name of the contact
630
	 * @param exists true if this contact matches one in the cache
631
	 * @param merge_setting the merge setting to use
632
	 * @return true if the contact should be skipped outright
633
	 * @throws AbortImportException
634
	 */
635
	synchronized private boolean shouldWeSkipContact( String contact_detail,
636
		boolean exists, int merge_setting ) throws AbortImportException
1 by edam
Initial import
637
	{
40 by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works
638
		_last_merge_decision = merge_setting;
639
1 by edam
Initial import
640
		// handle special cases
40 by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works
641
		switch( merge_setting )
1 by edam
Initial import
642
		{
9 by edam
- added scroll view to all layouts
643
		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
644
			// if we are skipping on a duplicate, check for one
645
			return exists;
1 by edam
Initial import
646
9 by edam
- added scroll view to all layouts
647
		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
648
			// if we are prompting on duplicate, then we can say that we won't
649
			// skip if there isn't one
650
			if( !exists ) return false;
1 by edam
Initial import
651
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
652
			// ok, duplicate exists, so do prompt
40 by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works
653
			_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
654
				Doit.MESSAGE_MERGEPROMPT, contact_detail ) );
1 by edam
Initial import
655
			try {
656
				wait();
657
			}
658
			catch( InterruptedException e ) { }
659
3 by edam
- added "all done" message
660
			// check if an abortion happened during the wait
661
			checkAbort();
662
40 by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works
663
			// if "always" was selected, make choice permanent
664
			if( _response_extra == RESPONSEEXTRA_ALWAYS )
665
				_merge_setting = _response;
1 by edam
Initial import
666
36 by edam
- formatting: removed some double-indents on overrunning lines
667
			// 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
668
			return shouldWeSkipContact( contact_detail, exists, _response );
1 by edam
Initial import
669
		}
670
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
671
		// for all other cases (either overwriting or merging) we don't skip
672
		return false;
1 by edam
Initial import
673
	}
674
675
	protected void skipContact() throws AbortImportException
676
	{
677
		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
678
679
		// show that we're skipping a new contact
3 by edam
- added "all done" message
680
		_doit._handler.sendEmptyMessage( Doit.MESSAGE_CONTACTSKIPPED );
1 by edam
Initial import
681
	}
682
683
	protected void importContact( ContactData contact )
684
			throws AbortImportException
685
	{
686
		checkAbort();
687
93 by Tim Marston
minor style tweaks
688
		// It is expected that we use contact.getCacheIdentifier() here.  The
43 by edam
- refactored some code to do with how contacts are imported
689
		// contact we are passed should have been successfully finalise()d,
690
		// which includes generating a valid cache identifier.
691
		ContactsCache.CacheIdentifier cache_identifier =
692
			contact.getCacheIdentifier();
693
3 by edam
- added "all done" message
694
//		if( !showContinue( "====[ IMPORTING ]====\n: " + contact._name ) )
695
//			finish( ACTION_ABORT );
1 by edam
Initial import
696
43 by edam
- refactored some code to do with how contacts are imported
697
		// attempt to lookup the id of an existing contact in the cache with
698
		// this contact data's cache identifier
699
		Long id = (Long)_contacts_cache.lookup( cache_identifier );
1 by edam
Initial import
700
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
701
		// check to see if this contact should be skipped
702
		if( shouldWeSkipContact( cache_identifier.getDetail(), id != null,
703
			_merge_setting ) )
704
		{
705
			// show that we're skipping a contact
706
			_doit._handler.sendEmptyMessage( Doit.MESSAGE_CONTACTSKIPPED );
707
			return;
708
		}
709
710
		// if a contact exists, and we're overwriting, destroy the existing
711
		// contact before importing
712
		boolean contact_deleted = false;
713
		if( id != null && _last_merge_decision == Doit.ACTION_OVERWRITE )
714
		{
715
			contact_deleted = true;
716
717
			// remove from device
718
			_backend.deleteContact( id );
719
720
			// update cache
721
			_contacts_cache.removeLookup( cache_identifier );
722
			_contacts_cache.removeAssociatedData( id );
723
724
			// show that we're overwriting a contact
725
			_doit._handler.sendEmptyMessage( Doit.MESSAGE_CONTACTOVERWRITTEN );
726
727
			// discard the contact id
728
			id = null;
729
		}
730
731
		try {
732
			// if we don't have a contact id yet (or we did, but we destroyed it
733
			// when we deleted the contact), we'll have to create a new contact
734
			if( id == null )
40 by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works
735
			{
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
736
				// create a new contact
737
				id = _backend.addContact( contact._name );
40 by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works
738
739
				// 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
740
				_contacts_cache.addLookup( cache_identifier, id );
741
742
				// if we haven't already shown that we're overwriting a contact,
743
				// show that we're creating a new contact
744
				if( !contact_deleted )
745
					_doit._handler.sendEmptyMessage(
746
						Doit.MESSAGE_CONTACTCREATED );
1 by edam
Initial import
747
			}
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
748
			else
749
				// show that we're merging with an existing contact
750
				_doit._handler.sendEmptyMessage( Doit.MESSAGE_CONTACTMERGED );
751
752
			// import contact parts
753
			if( contact.hasNumbers() )
754
				importContactPhones( id, contact.getNumbers() );
755
			if( contact.hasEmails() )
756
				importContactEmails( id, contact.getEmails() );
757
			if( contact.hasAddresses() )
758
				importContactAddresses( id, contact.getAddresses() );
759
			if( contact.hasOrganisations() )
760
				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
761
			if( contact.hasNotes() )
762
				importContactNotes( id, contact.getNotes() );
95 by Tim Marston
added suopport for birthdays
763
			if( contact.hasBirthday() )
764
				importContactBirthday( id, contact.getBirthday() );
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
		catch( Backend.ContactCreationException e )
1 by edam
Initial import
767
		{
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
768
			showError( R.string.error_unabletoaddcontact );
1 by edam
Initial import
769
		}
770
	}
771
40 by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works
772
	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
773
		HashMap< String, ContactData.PreferredDetail > datas )
774
		throws ContactCreationException
1 by edam
Initial import
775
	{
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!?)
776
		// add phone numbers
53 by edam
abstracted the android contacts API in to an interface, ready to be switched to
777
		Set< String > datas_keys = datas.keySet();
41 by edam
- updated TODO
778
		Iterator< String > i = datas_keys.iterator();
1 by edam
Initial import
779
		while( i.hasNext() ) {
40 by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works
780
			String number = i.next();
781
			ContactData.PreferredDetail data = datas.get( number );
1 by edam
Initial import
782
93 by Tim Marston
minor style tweaks
783
			// We don't want to add this number if it's crap, or it already
784
			// exists (which would cause a duplicate to be created).  We don't
785
			// take in to account the type when checking for duplicates.  This
786
			// is intentional: types aren't really very reliable.  We assume
787
			// that if the number exists at all, it doesn't need importing.
788
			// Because of this, we also can't update the cache (which we don't
789
			// need to anyway, so it's not a problem).
41 by edam
- updated TODO
790
			if( _contacts_cache.hasAssociatedNumber( id, number ) )
40 by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works
791
				continue;
1 by edam
Initial import
792
793
			// add phone number
53 by edam
abstracted the android contacts API in to an interface, ready to be switched to
794
			_backend.addContactPhone( id, number, data );
37 by edam
- updated TODO and NEWS
795
796
			// and add this address to the cache to prevent a addition of
797
			// duplicate date from another file
41 by edam
- updated TODO
798
			_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!?)
799
		}
1 by edam
Initial import
800
	}
801
40 by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works
802
	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
803
		HashMap< String, ContactData.PreferredDetail > datas )
804
		throws ContactCreationException
1 by edam
Initial import
805
	{
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!?)
806
		// add email addresses
53 by edam
abstracted the android contacts API in to an interface, ready to be switched to
807
		Set< String > datas_keys = datas.keySet();
41 by edam
- updated TODO
808
		Iterator< String > i = datas_keys.iterator();
1 by edam
Initial import
809
		while( i.hasNext() ) {
40 by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works
810
			String email = i.next();
811
			ContactData.PreferredDetail data = datas.get( email );
1 by edam
Initial import
812
37 by edam
- updated TODO and NEWS
813
			// we don't want to add this email address if it exists already or
93 by Tim Marston
minor style tweaks
814
			// we would introduce duplicates
41 by edam
- updated TODO
815
			if( _contacts_cache.hasAssociatedEmail( id, email ) )
40 by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works
816
				continue;
1 by edam
Initial import
817
818
			// add phone number
53 by edam
abstracted the android contacts API in to an interface, ready to be switched to
819
			_backend.addContactEmail( id, email, data );
37 by edam
- updated TODO and NEWS
820
821
			// and add this address to the cache to prevent a addition of
822
			// duplicate date from another file
41 by edam
- updated TODO
823
			_contacts_cache.addAssociatedEmail( id, email );
1 by edam
Initial import
824
		}
37 by edam
- updated TODO and NEWS
825
	}
826
40 by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works
827
	private void importContactAddresses( Long id,
828
		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
829
		throws ContactCreationException
37 by edam
- updated TODO and NEWS
830
	{
831
		// add addresses
41 by edam
- updated TODO
832
		Set< String > datas_keys = datas.keySet();
833
		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!?)
834
		while( i.hasNext() ) {
40 by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works
835
			String address = i.next();
836
			ContactData.TypeDetail data = datas.get( address );
37 by edam
- updated TODO and NEWS
837
838
			// we don't want to add this address if it exists already or we
839
			// would introduce duplicates
41 by edam
- updated TODO
840
			if( _contacts_cache.hasAssociatedAddress( id, address ) )
37 by edam
- updated TODO and NEWS
841
				continue;
842
843
			// add postal address
53 by edam
abstracted the android contacts API in to an interface, ready to be switched to
844
			_backend.addContactAddresses( id, address, data );
37 by edam
- updated TODO and NEWS
845
846
			// and add this address to the cache to prevent a addition of
847
			// duplicate date from another file
41 by edam
- updated TODO
848
			_contacts_cache.addAssociatedAddress( id, address );
40 by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works
849
		}
850
	}
851
852
	private void importContactOrganisations( Long id,
853
		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
854
		throws ContactCreationException
40 by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works
855
	{
856
		// add addresses
41 by edam
- updated TODO
857
		Set< String > datas_keys = datas.keySet();
858
		Iterator< String > i = datas_keys.iterator();
40 by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works
859
		while( i.hasNext() ) {
860
			String organisation = i.next();
861
			ContactData.ExtraDetail data = datas.get( organisation );
862
863
			// we don't want to add this address if it exists already or we
864
			// would introduce duplicates
41 by edam
- updated TODO
865
			if( _contacts_cache.hasAssociatedOrganisation( id, organisation ) )
40 by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works
866
				continue;
867
868
			// add organisation address
53 by edam
abstracted the android contacts API in to an interface, ready to be switched to
869
			_backend.addContactOrganisation( id, organisation, data );
40 by edam
- fixed logic for vcard field types (home, work, cell, etc) so it works
870
871
			// and add this address to the cache to prevent a addition of
872
			// duplicate date from another file
41 by edam
- updated TODO
873
			_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!?)
874
		}
1 by edam
Initial import
875
	}
876
95 by Tim Marston
added suopport for birthdays
877
	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
878
		throws ContactCreationException
879
	{
880
		// add notes
881
		Iterator< String > i = datas.iterator();
882
		while( i.hasNext() ) {
883
			String note = i.next();
884
885
			// we don't want to add this note if it exists already or we would
886
			// introduce duplicates
887
			if( _contacts_cache.hasAssociatedNote( id, note ) )
888
				continue;
889
890
			// add note
891
			_backend.addContactNote( id, note );
892
893
			// and add this note to the cache to prevent a addition of duplicate
894
			// date from another file
895
			_contacts_cache.addAssociatedNote( id, note );
896
		}
95 by Tim Marston
added suopport for birthdays
897
	}
898
899
	private void importContactBirthday( Long id, String birthday )
900
		throws ContactCreationException
901
	{
902
		// we don't want to import this birthday if it already exists
903
		if( _contacts_cache.hasAssociatedBirthday( id, birthday ) )
904
			return;
905
906
		// add birthday
907
		_backend.addContactBirthday( id, birthday );
908
909
		// and update the cache
910
		_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
911
	}
912
3 by edam
- added "all done" message
913
	synchronized protected void checkAbort() throws AbortImportException
1 by edam
Initial import
914
	{
915
		if( _abort ) {
916
			// stop
917
			throw new AbortImportException();
918
		}
919
	}
920
}