Project

General

Profile

Download (24.5 KB) Statistics
| Branch: | Revision:
1
/**
2
* Copyright (C) 2007 EDIT
3
* European Distributed Institute of Taxonomy 
4
* http://www.e-taxonomy.eu
5
* 
6
* The contents of this file are subject to the Mozilla Public License Version 1.1
7
* See LICENSE.TXT at the top of this package for the full license terms.
8
*/
9

    
10
package eu.etaxonomy.cdm.io.globis;
11

    
12
import java.sql.ResultSet;
13
import java.sql.SQLException;
14
import java.util.HashMap;
15
import java.util.HashSet;
16
import java.util.List;
17
import java.util.Map;
18
import java.util.Set;
19
import java.util.UUID;
20
import java.util.regex.Matcher;
21
import java.util.regex.Pattern;
22

    
23
import org.apache.log4j.Logger;
24
import org.springframework.stereotype.Component;
25

    
26
import eu.etaxonomy.cdm.api.facade.DerivedUnitFacade;
27
import eu.etaxonomy.cdm.api.facade.DerivedUnitFacade.DerivedUnitType;
28
import eu.etaxonomy.cdm.common.CdmUtils;
29
import eu.etaxonomy.cdm.io.common.IOValidator;
30
import eu.etaxonomy.cdm.io.common.ResultSetPartitioner;
31
import eu.etaxonomy.cdm.io.common.mapping.IMappingImport;
32
import eu.etaxonomy.cdm.io.globis.validation.GlobisSpecTaxaImportValidator;
33
import eu.etaxonomy.cdm.model.common.CdmBase;
34
import eu.etaxonomy.cdm.model.common.ExtensionType;
35
import eu.etaxonomy.cdm.model.common.IdentifiableSource;
36
import eu.etaxonomy.cdm.model.common.Marker;
37
import eu.etaxonomy.cdm.model.common.MarkerType;
38
import eu.etaxonomy.cdm.model.location.WaterbodyOrCountry;
39
import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
40
import eu.etaxonomy.cdm.model.name.Rank;
41
import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;
42
import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignationStatus;
43
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
44
import eu.etaxonomy.cdm.model.name.ZoologicalName;
45
import eu.etaxonomy.cdm.model.occurrence.Collection;
46
import eu.etaxonomy.cdm.model.occurrence.DerivationEvent;
47
import eu.etaxonomy.cdm.model.occurrence.FieldObservation;
48
import eu.etaxonomy.cdm.model.occurrence.Specimen;
49
import eu.etaxonomy.cdm.model.reference.Reference;
50
import eu.etaxonomy.cdm.model.taxon.Synonym;
51
import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType;
52
import eu.etaxonomy.cdm.model.taxon.Taxon;
53
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
54
import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
55

    
56

    
57
/**
58
 * @author a.mueller
59
 * @created 20.02.2010
60
 * @version 1.0
61
 */
62
@Component
63
public class GlobisSpecTaxImport  extends GlobisImportBase<Reference> implements IMappingImport<Reference, GlobisImportState>{
64
	private static final Logger logger = Logger.getLogger(GlobisSpecTaxImport.class);
65
	
66
	private int modCount = 10000;
67
	private static final String pluralString = "taxa";
68
	private static final String dbTableName = "specTax";
69
	private static final Class cdmTargetClass = Reference.class;
70
	public static final String SPEC_TAX_NAMESPACE = dbTableName;
71
	public static final String TYPE_NAMESPACE = dbTableName + ".SpecTypeDepository";
72
	
73
	private static UUID uuidCitedTypeLocality = UUID.fromString("ca431e0a-84ec-4828-935f-df4c8f5cf880");
74
	private static UUID uuidCitedTypeMaterial = UUID.fromString("8395021a-e596-4a55-9794-8c03aaad9e16");
75

    
76
	public GlobisSpecTaxImport(){
77
		super(pluralString, dbTableName, cdmTargetClass);
78
	}
79

    
80

    
81
	
82
	
83
	/* (non-Javadoc)
84
	 * @see eu.etaxonomy.cdm.io.globis.GlobisImportBase#getIdQuery()
85
	 */
86
	@Override
87
	protected String getIdQuery() {
88
		String strRecordQuery = 
89
			" SELECT specTaxId " + 
90
			" FROM " + dbTableName; 
91
		return strRecordQuery;	
92
	}
93

    
94

    
95

    
96

    
97
	/* (non-Javadoc)
98
	 * @see eu.etaxonomy.cdm.io.berlinModel.in.BerlinModelImportBase#getRecordQuery(eu.etaxonomy.cdm.io.berlinModel.in.BerlinModelImportConfigurator)
99
	 */
100
	@Override
101
	protected String getRecordQuery(GlobisImportConfigurator config) {
102
		String strRecordQuery = 
103
			" SELECT t.*, t.DateCreated as Created_When, t.CreatedBy as Created_Who," +
104
			"        t.ModifiedBy as Updated_who, t.DateModified as Updated_When, t.SpecRemarks as Notes " + 
105
			" FROM " + getTableName() + " t " +
106
			" WHERE ( t.specTaxId IN (" + ID_LIST_TOKEN + ") )";
107
		return strRecordQuery;
108
	}
109
	
110

    
111

    
112
	/* (non-Javadoc)
113
	 * @see eu.etaxonomy.cdm.io.globis.GlobisImportBase#doPartition(eu.etaxonomy.cdm.io.common.ResultSetPartitioner, eu.etaxonomy.cdm.io.globis.GlobisImportState)
114
	 */
115
	@Override
116
	public boolean doPartition(ResultSetPartitioner partitioner, GlobisImportState state) {
117
		boolean success = true;
118
		
119
		Set<TaxonBase> objectsToSave = new HashSet<TaxonBase>();
120
		Set<TaxonNameBase> namesToSave = new HashSet<TaxonNameBase>();
121
		
122
		Map<String, Taxon> taxonMap = (Map<String, Taxon>) partitioner.getObjectMap(TAXON_NAMESPACE);
123
		Map<String, Reference> referenceMap = (Map<String, Reference>) partitioner.getObjectMap(REFERENCE_NAMESPACE);
124
		
125
		ResultSet rs = partitioner.getResultSet();
126

    
127
		try {
128
			
129
			int i = 0;
130

    
131
			//for each reference
132
            while (rs.next()){
133
                
134
        		if ((i++ % modCount) == 0 && i!= 1 ){ logger.info(pluralString + " handled: " + (i-1));}
135
				
136
        		Integer specTaxId = rs.getInt("SpecTaxId");
137
        		Integer acceptedTaxonId = nullSafeInt(rs, "SpecCurrspecID");
138
        		String specSystaxRank = rs.getString("SpecSystaxRank");
139
        		
140
				try {
141
					
142
					//source ref
143
					Reference<?> sourceRef = state.getTransactionalSourceReference();
144
				
145
					Taxon acceptedTaxon =  taxonMap.get(String.valueOf(acceptedTaxonId));
146
					TaxonBase<?> thisTaxon = null;
147
					
148
					ZoologicalName name = null;
149
					if (isBlank(specSystaxRank) ){
150
						name = makeName(state, rs, specTaxId);
151
					}else if (specSystaxRank.equals("synonym")){
152
						Synonym synonym = getSynonym(state, rs, specTaxId);
153
						if (acceptedTaxon == null){
154
							if (acceptedTaxonId == null){
155
								logger.warn("Synonym has no accepted taxon defined. SpecTaxId: "+ specTaxId);
156
							}else{
157
								logger.warn("Accepted taxon (" + acceptedTaxonId + ") not found for synonym "+ specTaxId);
158
							}
159
						}else{
160
							acceptedTaxon.addSynonym(synonym, SynonymRelationshipType.SYNONYM_OF());
161
							thisTaxon = synonym;
162
						}
163
					}else if (specSystaxRank.equals("species")){
164
						validateAcceptedTaxon(acceptedTaxon, rs, specTaxId, acceptedTaxonId);
165
						thisTaxon = acceptedTaxon;
166
					}else{
167
						logger.warn(String.format("Unhandled specSystaxRank %s in specTaxId %d", specSystaxRank, specTaxId));
168
						name = makeName(state, rs, specTaxId);
169
					}
170
					
171
					if (thisTaxon != null){
172
						name = CdmBase.deproxy(thisTaxon.getName(), ZoologicalName.class);
173
					}else{
174
						if (name == null){
175
							name = makeName(state, rs, specTaxId);
176
						}
177
						thisTaxon = Taxon.NewInstance(name, sourceRef);
178
						objectsToSave.add(thisTaxon);
179
					}
180
					
181
					handleNomRef(state, referenceMap, rs, name);
182
				
183
					handleTypeInformation(state,rs, name, specTaxId);
184
				
185
				
186
//						this.doIdCreatedUpdatedNotes(state, ref, rs, refId, REFERENCE_NAMESPACE);
187
				
188
					if (acceptedTaxon != null){
189
						objectsToSave.add(acceptedTaxon); 
190
					}
191
					
192
					//SpecCitedTypeLocality
193
					String citedTypeLocality = rs.getString("SpecCitedTypeLocality");
194
					if (isNotBlank(citedTypeLocality)){
195
						ExtensionType exTypeCitedTypeLoc = getExtensionType(state, uuidCitedTypeLocality, "Type locality as cited in original description", "Type locality as cited in original description", null, ExtensionType.DOI().getVocabulary());
196
						name.addExtension(citedTypeLocality, exTypeCitedTypeLoc);
197
					}
198

    
199
					//SpecCitedTypeMaterial
200
					String citedTypeMaterial = rs.getString("SpecCitedTypeMaterial");
201
					if (isNotBlank(citedTypeMaterial)){
202
						ExtensionType exTypeCitedTypeLoc = getExtensionType(state, uuidCitedTypeMaterial, "Type material as cited in original description", "Type locality as cited in original description", null, ExtensionType.DOI().getVocabulary());
203
						name.addExtension(citedTypeLocality, exTypeCitedTypeLoc);
204
					}
205

    
206
					
207
					namesToSave.add(name);
208
					
209

    
210
				} catch (Exception e) {
211
					logger.warn("Exception in specTax: SpecTaxId " + specTaxId + ". " + e.getMessage());
212
					e.printStackTrace();
213
				} 
214
                
215
            }
216
           
217
			logger.warn(pluralString + " to save: " + objectsToSave.size());
218
			getTaxonService().save(objectsToSave);	
219
			getNameService().save(namesToSave);
220
			
221
			return success;
222
		} catch (Exception e) {
223
			logger.error("Exception: " +  e);
224
			return false;
225
		}
226
	}
227

    
228

    
229
	private Pattern patternAll = Pattern.compile("(.+,\\s.+)(\\(.+\\))");
230
	
231

    
232
	private void handleTypeInformation(GlobisImportState state, ResultSet rs, ZoologicalName name, Integer specTaxId) throws SQLException {
233
		if (! hasTypeInformation(rs)){
234
			return;
235
		}
236
		
237
		FieldObservation fieldObservation = makeTypeFieldObservation(state, rs);
238
		
239
		//typeDepository
240
		String specTypeDepositoriesStr = rs.getString("SpecTypeDepository");
241
		String[] specTypeDepositories; 
242
		if (isNotBlank(specTypeDepositoriesStr) ){
243
			specTypeDepositories = specTypeDepositoriesStr.trim().split(";");
244
		}else{
245
			specTypeDepositories = new String[0];
246
		}
247
		
248
		//TODO several issues
249
		if (specTypeDepositories.length == 0){
250
			Specimen specimen = makeSingleTypeSpecimen(fieldObservation);
251
			makeTypeDesignation(name, rs, specimen);
252
			makeTypeIdInSource(state, specimen, "null", specTaxId);
253
		}
254
		for (String specTypeDepositoryStr : specTypeDepositories){
255
			specTypeDepositoryStr = specTypeDepositoryStr.trim();
256
			
257
			//Specimen
258
			Specimen specimen = makeSingleTypeSpecimen(fieldObservation);
259

    
260
			if (specTypeDepositoryStr.equals("??")){
261
				//unknown
262
				specimen.setTitleCache("??", true);
263
				makeTypeIdInSource(state, specimen, "??", specTaxId);
264
				
265
			}else{
266
				specTypeDepositoryStr = makeAdditionalSpecimenInformation(
267
						specTypeDepositoryStr, specimen, specTaxId);
268
				
269
				Collection collection = makeCollection(state, specTypeDepositoryStr, specimen, specTaxId);
270
				String collectionCode = collection.getCode();
271
				if (isBlank(collectionCode)){
272
					collectionCode = collection.getName();
273
				}
274
				if (isBlank(collectionCode)){
275
					logger.warn("Collection has empty representation: " + specTypeDepositoryStr + ", specTaxId" +  specTaxId);
276
				}
277
				makeTypeIdInSource(state, specimen, collectionCode , specTaxId);	
278
			}
279
			
280
			//type Designation
281
			makeTypeDesignation(name, rs, specimen);
282
		}
283

    
284
		
285
	}
286

    
287

    
288
	private void makeTypeIdInSource(GlobisImportState state, Specimen specimen, String collectionCode, Integer specTaxId) {
289
		String namespace = TYPE_NAMESPACE;
290
		String id = getTypeId(specTaxId, collectionCode);
291
		IdentifiableSource source = IdentifiableSource.NewInstance(id, namespace, state.getTransactionalSourceReference(), null);
292
		specimen.addSource(source);
293
	}
294

    
295

    
296

    
297

    
298
	public static String getTypeId(Integer specTaxId, String collectionCode) {
299
		String result = String.valueOf(specTaxId) + "@" + collectionCode;
300
		return result;
301
	}
302

    
303

    
304

    
305

    
306
	private boolean hasTypeInformation(ResultSet rs) throws SQLException {
307
		String specTypeDepositoriesStr = rs.getString("SpecTypeDepository");
308
		String countryString = rs.getString("SpecTypeCountry");
309
		String specType = rs.getString("SpecType");
310
		boolean result = false;
311
		result |= isNotBlank(specTypeDepositoriesStr) || isNotBlank(countryString)
312
			|| isNotBlank(specType);
313
		return result;
314
	}
315

    
316

    
317

    
318
	/**
319
	 * @param state 
320
	 * @param specTypeDepositoryStr
321
	 * @param specimen
322
	 * @param specTaxId 
323
	 */
324
	protected Collection makeCollection(GlobisImportState state, String specTypeDepositoryStr, Specimen specimen, Integer specTaxId) {
325
		
326
		//Collection
327
		specTypeDepositoryStr = specTypeDepositoryStr.replace("Washington, D.C.", "Washington@ D.C.");
328
		
329
		Collection collection;
330
		if (specTypeDepositoryStr.equals("BMNH, London and/or MNHN, Paris")){
331
			collection = state.getRelatedObject(COLLECTION_NAMESPACE, specTypeDepositoryStr, Collection.class);
332
			if (collection == null){
333
				collection = Collection.NewInstance();
334
				collection.setName(specTypeDepositoryStr);
335
				collection.setTownOrLocation("London or Paris");
336
				state.addRelatedObject(COLLECTION_NAMESPACE, collection.getName(), collection);
337
			}
338
			specimen.setCollection(collection);
339
		}else if (specTypeDepositoryStr.equals("coll. L. V. Kaabak, A .V. Sotshivko & V. V. Titov, Moscow")){
340
			String colName = "coll. L. V. Kaabak, A .V. Sotshivko & V. V. Titov";
341
			collection = state.getRelatedObject(COLLECTION_NAMESPACE, colName, Collection.class);
342
			if (collection == null){
343
				collection = Collection.NewInstance();
344
				collection.setName(colName);
345
				collection.setTownOrLocation("Moscow");
346
				state.addRelatedObject(COLLECTION_NAMESPACE, collection.getName(), collection);
347
			}
348
			specimen.setCollection(collection);
349
		}else if (specTypeDepositoryStr.matches("coll. R. E. Parrott?, Port Hope, Ontario")){
350
			String colName = "coll. R. E. Parrott";
351
			collection = state.getRelatedObject(COLLECTION_NAMESPACE, colName, Collection.class);
352
			if (collection == null){
353
				collection = Collection.NewInstance();
354
				collection.setName(colName);
355
				collection.setTownOrLocation("Port Hope, Ontario");
356
				state.addRelatedObject(COLLECTION_NAMESPACE, collection.getName(), collection);
357
			}
358
			specimen.setCollection(collection);
359
		}else{
360
			
361
			String[] split = specTypeDepositoryStr.split(",");
362
			if (split.length != 2){
363
				if (split.length == 1 && split[0].startsWith("coll.")){
364
					collection = state.getRelatedObject(COLLECTION_NAMESPACE, split[0], Collection.class);
365
					if (collection == null){
366
						collection = Collection.NewInstance();
367
						collection.setName(split[0]);
368
						state.addRelatedObject(COLLECTION_NAMESPACE, collection.getName(), collection);
369
					}
370
					specimen.setCollection(collection);
371
				}else{
372
					logger.warn("Split size is not 2: " + specTypeDepositoryStr + " (specTaxID:" + specTaxId + ")");
373
					collection = Collection.NewInstance();
374
					collection.setCode("??");
375
					//TODO deduplicate ??
376
				}
377
				
378
			}else{
379
				String collectionStr = split[0];
380
				String location = split[1].replace("Washington@ D.C.", "Washington, D.C.");
381
				
382
				collection = state.getRelatedObject(COLLECTION_NAMESPACE, collectionStr, Collection.class);
383
				if (collection == null){
384
					collection = Collection.NewInstance();
385
					collection.setCode(collectionStr);
386
					collection.setTownOrLocation(split[1]);
387
					state.addRelatedObject(COLLECTION_NAMESPACE, collection.getCode(), collection);
388
						
389
				}else if (! CdmUtils.nullSafeEqual(location, collection.getTownOrLocation())){
390
					String message = "Location (%s) is not equal to location (%s) of existing collection";
391
					logger.warn(String.format(message, location, collection.getTownOrLocation(), collection.getCode()));
392
				}
393
				
394
				specimen.setCollection(collection);
395
			}
396
		}
397
		return collection;
398
	}
399

    
400

    
401

    
402

    
403
	/**
404
	 * @param specTypeDepositoriesStr
405
	 * @param specTypeDepositoryStr
406
	 * @param specimen
407
	 * @param specTaxId 
408
	 * @return
409
	 */
410
	protected String makeAdditionalSpecimenInformation( String specTypeDepositoryStr, Specimen specimen, Integer specTaxId) {
411
		//doubful
412
		if (specTypeDepositoryStr.endsWith("?")){
413
			Marker.NewInstance(specimen, true, MarkerType.IS_DOUBTFUL());
414
			specTypeDepositoryStr = specTypeDepositoryStr.substring(0, specTypeDepositoryStr.length() -1).trim();
415
		}
416
		
417
		//brackets
418
		Matcher matcher = patternAll.matcher(specTypeDepositoryStr);
419
		if (matcher.find()){
420
			//has brackets
421
			String brackets = matcher.group(2);
422
			brackets = brackets.substring(1, brackets.length()-1);
423
			
424
			brackets = brackets.replace("[mm]", "\u2642\u2642");
425
			brackets = brackets.replace("[m]", "\u2642");
426
			brackets = brackets.replace("[ff]", "\u2640\u2640");
427
			brackets = brackets.replace("[f]", "\u2640");
428
			brackets = brackets.replace("[m/f]", "\u26a5");
429
			
430
			if (brackets.contains("[") || brackets.contains("]")){
431
				logger.warn ("There are still '[', ']' in the bracket part: " + brackets + "; specTaxId: " + specTaxId);
432
			}
433
			
434
			//TODO replace mm/ff by Unicode male 
435
			specimen.setTitleCache(brackets, true);
436
			specTypeDepositoryStr = matcher.group(1).trim();
437
		}
438
		return specTypeDepositoryStr;
439
	}
440

    
441

    
442

    
443

    
444
	/**
445
	 * @param fieldObservation
446
	 * @return
447
	 */
448
	protected Specimen makeSingleTypeSpecimen(FieldObservation fieldObservation) {
449
		DerivationEvent derivEvent = DerivationEvent.NewInstance();
450
//			derivEvent.setType(DerivationEventType.ACCESSIONING());
451
		fieldObservation.addDerivationEvent(derivEvent);
452
		Specimen specimen = Specimen.NewInstance();
453
		specimen.setDerivedFrom(derivEvent);
454
		return specimen;
455
	}
456

    
457

    
458

    
459

    
460
	/**
461
	 * @param state
462
	 * @return
463
	 * @throws SQLException
464
	 */
465
	protected FieldObservation makeTypeFieldObservation(GlobisImportState state, 
466
			ResultSet rs) throws SQLException {
467
		
468
		String countryString = rs.getString("SpecTypeCountry");
469
		
470
		DerivedUnitType unitType = DerivedUnitType.Specimen;
471
		DerivedUnitFacade facade = DerivedUnitFacade.NewInstance(unitType);
472
		
473
		WaterbodyOrCountry typeCountry = getCountry(state, countryString);
474
		facade.setCountry(typeCountry);
475
		FieldObservation fieldObservation = facade.innerFieldObservation();
476
		return fieldObservation;
477
	}
478

    
479

    
480

    
481

    
482
	/**
483
	 * @param name
484
	 * @param rs 
485
	 * @param status
486
	 * @param specimen
487
	 * @throws SQLException 
488
	 */
489
	protected void makeTypeDesignation(ZoologicalName name, ResultSet rs, Specimen specimen) throws SQLException {
490
		//type
491
		String specType = rs.getString("SpecType");
492
		SpecimenTypeDesignationStatus status = getTypeDesigType(specType);
493

    
494
		SpecimenTypeDesignation typeDesignation = SpecimenTypeDesignation.NewInstance();
495
		typeDesignation.setTypeStatus(status);
496
		typeDesignation.setTypeSpecimen(specimen);
497
		
498
		name.addTypeDesignation(typeDesignation, true);
499
	}
500

    
501

    
502

    
503

    
504
	private SpecimenTypeDesignationStatus getTypeDesigType(String specType) {
505
		if (isBlank(specType) ){
506
			return null;
507
		}else if (specType.matches("Holotype(Holotypus)?")){
508
			return SpecimenTypeDesignationStatus.HOLOTYPE();
509
		}else if (specType.matches("Neotype")){
510
			return SpecimenTypeDesignationStatus.NEOTYPE();
511
		}else if (specType.matches("Syntype(\\(s\\))?") || specType.matches("Syntype.*Syntype\\(s\\)\\s*") ){
512
			return SpecimenTypeDesignationStatus.SYNTYPE();
513
		}else if (specType.matches("Lectotype")){
514
			return SpecimenTypeDesignationStatus.LECTOTYPE();
515
		}else{
516
			logger.warn("SpecimenTypeDesignationStatus does not match: " + specType);
517
			return null;
518
		}
519
	}
520

    
521

    
522

    
523

    
524
	/**
525
	 * @param state
526
	 * @param referenceMap
527
	 * @param rs
528
	 * @param name
529
	 * @return
530
	 * @throws SQLException
531
	 */
532
	private Reference<?> handleNomRef(GlobisImportState state, Map<String, Reference> referenceMap, ResultSet rs,
533
			ZoologicalName name) throws SQLException {
534
		//ref
535
		Integer refId = nullSafeInt(rs, "fiSpecRefID");
536
		Reference<?> nomRef = null;
537
		if (refId != null){
538
			nomRef = referenceMap.get(String.valueOf(refId));
539
			if (nomRef == null && state.getConfig().getDoReferences().equals(state.getConfig().getDoReferences().ALL)){
540
				logger.warn("Reference " + refId + " could not be found.");
541
			}else if (nomRef != null){
542
				name.setNomenclaturalReference(nomRef);
543
			}
544
		}
545
		
546
		//refDetail
547
		String refDetail = rs.getString("SpecPage");
548
		if (isNotBlank(refDetail)){
549
			name.setNomenclaturalMicroReference(refDetail);
550
		}
551
		return nomRef;
552
	}
553

    
554

    
555

    
556
	
557
	private void validateAcceptedTaxon(Taxon acceptedTaxon, ResultSet rs, Integer specTaxId, Integer acceptedTaxonId) throws SQLException {
558
		if (acceptedTaxon == null){
559
			logger.warn("Accepted taxon is null for taxon taxon to validate: ");
560
			return;
561
		}
562
		
563
		//TODO 
564
		ZoologicalName name = CdmBase.deproxy(acceptedTaxon.getName(), ZoologicalName.class);
565
		
566
		String specName = rs.getString("SpecName");
567
		if (! name.getSpecificEpithet().equals(specName)){
568
			logger.warn(String.format("Species epithet is not equal for accepted taxon: %s - %s", name.getSpecificEpithet(), specName));
569
		}
570
		//TODO
571
	}
572

    
573

    
574

    
575

    
576
	private Synonym getSynonym(GlobisImportState state, ResultSet rs, Integer specTaxId) throws SQLException {
577
		ZoologicalName name = makeName(state, rs, specTaxId);
578
				
579
		Synonym synonym = Synonym.NewInstance(name, state.getTransactionalSourceReference());
580
		
581
		return synonym;
582
	}
583

    
584

    
585

    
586

    
587
	/**
588
	 * @param state
589
	 * @param rs
590
	 * @param specTaxId 
591
	 * @return
592
	 * @throws SQLException
593
	 */
594
	protected ZoologicalName makeName(GlobisImportState state, ResultSet rs, Integer specTaxId)
595
			throws SQLException {
596
		//rank
597
		String rankStr = rs.getString("SpecRank");
598
		Rank rank = null;
599
		if (isNotBlank(rankStr)){
600
			try {
601
				rank = Rank.getRankByNameOrAbbreviation(rankStr, NomenclaturalCode.ICZN, true);
602
			} catch (UnknownCdmTypeException e) {
603
				e.printStackTrace();
604
			}
605
		}
606
		
607
		//name
608
		ZoologicalName name = ZoologicalName.NewInstance(rank);
609
		makeNamePartsAndCache(state, rs, rankStr, name);
610
		
611

    
612
//		name.setGenusOrUninomial(genusOrUninomial);
613
		String authorStr = rs.getString("SpecAuthor");
614
		String yearStr = rs.getString("SpecYear");
615
		String authorAndYearStr = CdmUtils.concat(", ", authorStr, yearStr);
616
		handleAuthorAndYear(authorAndYearStr, name);
617
		
618
		name.addSource(String.valueOf(specTaxId), SPEC_TAX_NAMESPACE, state.getTransactionalSourceReference(), null);
619
		return name;
620
	}
621

    
622

    
623

    
624

    
625
	private void makeNamePartsAndCache(GlobisImportState state, ResultSet rs, String rank, ZoologicalName name) throws SQLException {
626
		String citedFamily = rs.getString("SpecCitedFamily");
627
		String citedGenus = rs.getString("SpecCitedGenus");
628
		String citedSpecies = rs.getString("SpecCitedSpecies");
629
		String citedSubspecies = rs.getString("SpecCitedSubspecies");
630
		String lastEpithet = rs.getString("SpecName");
631
		
632
		
633
		String cache = CdmUtils.concat(" ", new String[]{citedFamily, citedGenus, citedSpecies, citedSubspecies, rank, lastEpithet});
634
		name.setGenusOrUninomial(citedGenus);
635
		//TODO sperate authors
636
		if (isBlank(citedSpecies)){
637
			name.setSpecificEpithet(lastEpithet);
638
		}else{
639
			name.setSpecificEpithet(citedSpecies);
640
			if (isBlank(citedSubspecies)){
641
				name.setInfraSpecificEpithet(lastEpithet);
642
			}
643
		}
644
		
645
		//TODO check if cache needs protection
646
		name.setNameCache(cache, true);
647
	}
648

    
649

    
650
	/* (non-Javadoc)
651
	 * @see eu.etaxonomy.cdm.io.berlinModel.in.IPartitionedIO#getRelatedObjectsForPartition(java.sql.ResultSet)
652
	 */
653
	public Map<Object, Map<String, ? extends CdmBase>> getRelatedObjectsForPartition(ResultSet rs) {
654
		String nameSpace;
655
		Class cdmClass;
656
		Set<String> idSet;
657
		Map<Object, Map<String, ? extends CdmBase>> result = new HashMap<Object, Map<String, ? extends CdmBase>>();
658
		try{
659
			Set<String> taxonIdSet = new HashSet<String>();
660
			Set<String> referenceIdSet = new HashSet<String>();
661
			
662
			while (rs.next()){
663
				handleForeignKey(rs, taxonIdSet, "SpecCurrspecID");
664
				handleForeignKey(rs, referenceIdSet, "fiSpecRefID");
665
			}
666
			
667
			//taxon map
668
			nameSpace = TAXON_NAMESPACE;
669
			cdmClass = Taxon.class;
670
			idSet = taxonIdSet;
671
			Map<String, Taxon> objectMap = (Map<String, Taxon>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
672
			result.put(nameSpace, objectMap);
673

    
674
			//reference map
675
			nameSpace = REFERENCE_NAMESPACE;
676
			cdmClass = Reference.class;
677
			idSet = referenceIdSet;
678
			Map<String, Reference> referenceMap = (Map<String, Reference>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
679
			result.put(nameSpace, referenceMap);
680
			
681
			//collection map
682
			nameSpace = COLLECTION_NAMESPACE;
683
			List<Collection> listCollection = getCollectionService().list(Collection.class, null, null, null, null);
684
			Map<String, Collection> collectionMap = new HashMap<String, Collection>();
685
			for (Collection collection : listCollection){
686
				collectionMap.put(collection.getCode(), collection);
687
				if (isBlank(collection.getCode())){
688
					logger.warn("Collection code is blank: " + collection);
689
				}
690
			}
691
			result.put(nameSpace, collectionMap);
692
			
693
		} catch (SQLException e) {
694
			throw new RuntimeException(e);
695
		}
696
		return result;
697
	}
698
	
699
	/* (non-Javadoc)
700
	 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doCheck(eu.etaxonomy.cdm.io.common.IImportConfigurator)
701
	 */
702
	@Override
703
	protected boolean doCheck(GlobisImportState state){
704
		IOValidator<GlobisImportState> validator = new GlobisSpecTaxaImportValidator();
705
		return validator.validate(state);
706
	}
707
	
708
	
709
	/* (non-Javadoc)
710
	 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#isIgnore(eu.etaxonomy.cdm.io.common.IImportConfigurator)
711
	 */
712
	protected boolean isIgnore(GlobisImportState state){
713
		return ! state.getConfig().isDoSpecTaxa();
714
	}
715

    
716

    
717

    
718

    
719
	@Override
720
	public Reference createObject(ResultSet rs, GlobisImportState state)
721
			throws SQLException {
722
		// not needed
723
		return null;
724
	}
725

    
726

    
727

    
728

    
729

    
730
}
(8-8/9)