Project

General

Profile

Download (27.8 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.common.mapping.UndefinedTransformerMethodException;
33
import eu.etaxonomy.cdm.io.globis.validation.GlobisSpecTaxaImportValidator;
34
import eu.etaxonomy.cdm.model.common.CdmBase;
35
import eu.etaxonomy.cdm.model.common.ExtensionType;
36
import eu.etaxonomy.cdm.model.common.IdentifiableSource;
37
import eu.etaxonomy.cdm.model.common.Marker;
38
import eu.etaxonomy.cdm.model.common.MarkerType;
39
import eu.etaxonomy.cdm.model.description.Feature;
40
import eu.etaxonomy.cdm.model.location.NamedArea;
41
import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
42
import eu.etaxonomy.cdm.model.name.Rank;
43
import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;
44
import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignationStatus;
45
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
46
import eu.etaxonomy.cdm.model.name.ZoologicalName;
47
import eu.etaxonomy.cdm.model.occurrence.Collection;
48
import eu.etaxonomy.cdm.model.occurrence.DerivationEvent;
49
import eu.etaxonomy.cdm.model.occurrence.FieldObservation;
50
import eu.etaxonomy.cdm.model.occurrence.Specimen;
51
import eu.etaxonomy.cdm.model.reference.Reference;
52
import eu.etaxonomy.cdm.model.taxon.Synonym;
53
import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType;
54
import eu.etaxonomy.cdm.model.taxon.Taxon;
55
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
56
import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
57

    
58

    
59
/**
60
 * @author a.mueller
61
 * @created 20.02.2010
62
 * @version 1.0
63
 */
64
@Component
65
public class GlobisSpecTaxImport  extends GlobisImportBase<Reference> implements IMappingImport<Reference, GlobisImportState>{
66
	private static final Logger logger = Logger.getLogger(GlobisSpecTaxImport.class);
67
	
68
	private int modCount = 10000;
69
	private static final String pluralString = "taxa";
70
	private static final String dbTableName = "specTax";
71
	private static final Class cdmTargetClass = Reference.class;
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
        		//ignore: CountryDummy, currentSpecies, DepositoryDisplay, DepositoryDummy, ReferenceDisplay, SpecDescriptionImageFile, all *Valid*
141
        		
142
				try {
143
					
144
					//source ref
145
					Reference<?> sourceRef = state.getTransactionalSourceReference();
146
				
147
					Taxon acceptedTaxon =  taxonMap.get(String.valueOf(acceptedTaxonId));
148
					TaxonBase<?> thisTaxon = null;
149
					
150
					ZoologicalName name = null;
151
					if (isBlank(specSystaxRank) ){
152
						name = makeName(state, rs, specTaxId);
153
					}else if (specSystaxRank.equals("synonym")){
154
						Synonym synonym = getSynonym(state, rs, specTaxId);
155
						if (acceptedTaxon == null){
156
							if (acceptedTaxonId == null){
157
								logger.warn("Synonym has no accepted taxon defined. SpecTaxId: "+ specTaxId);
158
							}else{
159
								logger.warn("Accepted taxon (" + acceptedTaxonId + ") not found for synonym "+ specTaxId);
160
							}
161
						}else{
162
							acceptedTaxon.addSynonym(synonym, SynonymRelationshipType.SYNONYM_OF());
163
							thisTaxon = synonym;
164
						}
165
					}else if (specSystaxRank.equals("species")){
166
						validateAcceptedTaxon(acceptedTaxon, rs, specTaxId, acceptedTaxonId);
167
						thisTaxon = acceptedTaxon;
168
					}else{
169
						logger.warn(String.format("Unhandled specSystaxRank %s in specTaxId %d", specSystaxRank, specTaxId));
170
						name = makeName(state, rs, specTaxId);
171
					}
172
					
173
					if (thisTaxon != null){
174
						name = CdmBase.deproxy(thisTaxon.getName(), ZoologicalName.class);
175
					}else{
176
						if (name == null){
177
							name = makeName(state, rs, specTaxId);
178
						}
179
						thisTaxon = Taxon.NewInstance(name, sourceRef);
180
						objectsToSave.add(thisTaxon);
181
					}
182
					
183
					handleNomRef(state, referenceMap, rs, name);
184
				
185
					handleTypeInformation(state,rs, name, specTaxId);
186
				
187
				
188
//						this.doIdCreatedUpdatedNotes(state, ref, rs, refId, REFERENCE_NAMESPACE);
189
				
190
					if (acceptedTaxon != null){
191
						objectsToSave.add(acceptedTaxon); 
192
					}
193
					
194
					//makeMarker1(state, rs, name);   //ignore!
195
					
196
					makeNotAvailable(state, rs, name);
197
					
198
					//SpecCitedTypeLocality
199
					String citedTypeLocality = rs.getString("SpecCitedTypeLocality");
200
					if (isNotBlank(citedTypeLocality)){
201
//						ExtensionType exTypeCitedTypeLoc = getExtensionType(state, uuidCitedTypeLocality, "Type locality as cited in original description", "Type locality as cited in original description", null, ExtensionType.DOI().getVocabulary());
202
//						name.addExtension(citedTypeLocality, exTypeCitedTypeLoc);
203
						addNameDescription(state, name, uuidCitedTypeLocality, citedTypeLocality, "Type locality as cited in original description");
204
					}
205

    
206
					//SpecCitedTypeMaterial
207
					String citedTypeMaterial = rs.getString("SpecCitedTypeMaterial");
208
					if (isNotBlank(citedTypeMaterial)){
209
						ExtensionType exTypeCitedTypeLoc = getExtensionType(state, uuidCitedTypeMaterial, "Type material as cited in original description", "Type material as cited in original description", null, ExtensionType.DOI().getVocabulary());
210
						name.addExtension(citedTypeLocality, exTypeCitedTypeLoc);
211
					}
212

    
213
					name.addSource(String.valueOf(specTaxId), SPEC_TAX_NAMESPACE, state.getTransactionalSourceReference(), null);
214
					
215
					namesToSave.add(name);
216
					
217

    
218
				} catch (Exception e) {
219
					logger.warn("Exception in specTax: SpecTaxId " + specTaxId + ". " + e.getMessage());
220
					e.printStackTrace();
221
				} 
222
                
223
            }
224
           
225
			logger.warn(pluralString + " to save: " + objectsToSave.size());
226
			getTaxonService().save(objectsToSave);	
227
			getNameService().save(namesToSave);
228
			
229
			return success;
230
		} catch (Exception e) {
231
			logger.error("Exception: " +  e);
232
			return false;
233
		}
234
	}
235

    
236

    
237
	private void makeNotAvailable(GlobisImportState state, ResultSet rs, ZoologicalName name) throws SQLException {
238
		String notAvailableStr = rs.getString("SpecNotAvailable");
239
		try {
240
			if (isNotBlank(notAvailableStr)){
241
				if (notAvailableStr.contains("not available") ){ 
242
					UUID uuidNotAvailableMarkerType = state.getTransformer().getMarkerTypeUuid("not available");
243
					
244
					MarkerType markerType = getMarkerType(state, uuidNotAvailableMarkerType, "not available", "not available", null);
245
					name.addMarker(Marker.NewInstance(markerType, true));
246
				}
247
			}
248
		} catch (UndefinedTransformerMethodException e) {
249
			e.printStackTrace();
250
		}
251
		//Not available reason
252
		//TODO make it a vocabulary
253
		String notAvailableReason = rs.getString("SpecNotAvailableReason");
254
		if (isNotBlank(notAvailableReason)){
255
			UUID uuidNotAvailableReason;
256
			try {
257
				uuidNotAvailableReason = state.getTransformer().getExtensionTypeUuid("not available reason");
258
				ExtensionType notAvailableReasonExtType = getExtensionType(state, uuidNotAvailableReason, "Not available reason", "Not available reason", null, null);
259
				name.addExtension(notAvailableReason, notAvailableReasonExtType);
260
			} catch (UndefinedTransformerMethodException e) {
261
				e.printStackTrace();
262
			} 
263
		}
264
		
265
	}
266

    
267

    
268

    
269

    
270
	
271
	/**
272
	 * This method is not used anymore as according to Alexander Marker1 should be ignored.
273
	 * @param state
274
	 * @param rs
275
	 * @param name
276
	 * @throws SQLException
277
	 */
278
	private void makeMarker1(GlobisImportState state, ResultSet rs, ZoologicalName name) throws SQLException {
279
		String marker1Str = rs.getString("Marker1");
280
		try {
281
			if (isNotBlank(marker1Str)){
282
				marker1Str = marker1Str.trim();
283
				if (marker1Str.contains("checked") || marker1Str.contains("berpr") ){ //überprüft
284
					UUID uuidCheckedMarkerType;
285
						uuidCheckedMarkerType = state.getTransformer().getMarkerTypeUuid("checked");
286
					
287
					MarkerType markerType = getMarkerType(state, uuidCheckedMarkerType, "checked", "checked", null);
288
					name.addMarker(Marker.NewInstance(markerType, true));
289
				}
290
				if (marker1Str.contains("old record") || marker1Str.contains("alte Angabe") ){
291
					UUID uuidOldRecordMarkerType = state.getTransformer().getMarkerTypeUuid("old record");
292
					MarkerType markerType = getMarkerType(state, uuidOldRecordMarkerType, "checked", "checked", null);
293
					name.addMarker(Marker.NewInstance(markerType, true));
294
				}
295
			}
296
		} catch (UndefinedTransformerMethodException e) {
297
			e.printStackTrace();
298
		}
299
		
300
	}
301

    
302

    
303
	private void addNameDescription(GlobisImportState state, ZoologicalName name, UUID featureUuid,
304
			String citedTypeLocality, String featureLabel) {
305
		Feature feature = getFeature(state, featureUuid,featureLabel,featureLabel, null, null);
306
		getTaxonNameDescription(name, false, true);
307
		
308
	}
309

    
310

    
311
	private Pattern patternAll = Pattern.compile("(.+,\\s.+)(\\(.+\\))");
312
	
313

    
314
	private void handleTypeInformation(GlobisImportState state, ResultSet rs, ZoologicalName name, Integer specTaxId) throws SQLException {
315
		if (! hasTypeInformation(rs)){
316
			return;
317
		}
318
		
319
		FieldObservation fieldObservation = makeTypeFieldObservation(state, rs);
320
		
321
		//typeDepository
322
		String specTypeDepositoriesStr = rs.getString("SpecTypeDepository");
323
		String[] specTypeDepositories; 
324
		if (isNotBlank(specTypeDepositoriesStr) ){
325
			specTypeDepositories = specTypeDepositoriesStr.trim().split(";");
326
		}else{
327
			specTypeDepositories = new String[0];
328
		}
329
		
330
		//TODO several issues
331
		if (specTypeDepositories.length == 0){
332
			Specimen specimen = makeSingleTypeSpecimen(fieldObservation);
333
			makeTypeDesignation(name, rs, specimen, specTaxId);
334
			makeTypeIdInSource(state, specimen, "null", specTaxId);
335
		}
336
		for (String specTypeDepositoryStr : specTypeDepositories){
337
			specTypeDepositoryStr = specTypeDepositoryStr.trim();
338
			
339
			//Specimen
340
			Specimen specimen = makeSingleTypeSpecimen(fieldObservation);
341

    
342
			if (specTypeDepositoryStr.equals("??")){
343
				//unknown
344
				specimen.setTitleCache("??", true);
345
				makeTypeIdInSource(state, specimen, "??", specTaxId);
346
				
347
			}else{
348
				specTypeDepositoryStr = makeAdditionalSpecimenInformation(
349
						specTypeDepositoryStr, specimen, specTaxId);
350
				
351
				Collection collection = makeCollection(state, specTypeDepositoryStr, specimen, specTaxId);
352
				String collectionCode = collection.getCode();
353
				if (isBlank(collectionCode)){
354
					collectionCode = collection.getName();
355
				}
356
				if (isBlank(collectionCode)){
357
					logger.warn("Collection has empty representation: " + specTypeDepositoryStr + ", specTaxId" +  specTaxId);
358
				}
359
				makeTypeIdInSource(state, specimen, collectionCode , specTaxId);	
360
			}
361
			
362
			//type Designation
363
			makeTypeDesignation(name, rs, specimen, specTaxId);
364
		}
365

    
366
		
367
	}
368

    
369

    
370
	private void makeTypeIdInSource(GlobisImportState state, Specimen specimen, String collectionCode, Integer specTaxId) {
371
		String namespace = TYPE_NAMESPACE;
372
		String id = getTypeId(specTaxId, collectionCode);
373
		IdentifiableSource source = IdentifiableSource.NewInstance(id, namespace, state.getTransactionalSourceReference(), null);
374
		specimen.addSource(source);
375
	}
376

    
377

    
378

    
379

    
380
	public static String getTypeId(Integer specTaxId, String collectionCode) {
381
		String result = String.valueOf(specTaxId) + "@" + collectionCode;
382
		return result;
383
	}
384

    
385

    
386

    
387

    
388
	private boolean hasTypeInformation(ResultSet rs) throws SQLException {
389
		String specTypeDepositoriesStr = rs.getString("SpecTypeDepository");
390
		String countryString = rs.getString("SpecTypeCountry");
391
		String specType = rs.getString("SpecType");
392
		boolean result = false;
393
		result |= isNotBlank(specTypeDepositoriesStr) || isNotBlank(countryString)
394
			|| isNotBlank(specType);
395
		return result;
396
	}
397

    
398

    
399

    
400
	/**
401
	 * @param state 
402
	 * @param specTypeDepositoryStr
403
	 * @param specimen
404
	 * @param specTaxId 
405
	 */
406
	protected Collection makeCollection(GlobisImportState state, String specTypeDepositoryStr, Specimen specimen, Integer specTaxId) {
407
		
408
		//Collection
409
		specTypeDepositoryStr = specTypeDepositoryStr.replace("Washington, D.C.", "Washington@ D.C.");
410
		
411
		Collection collection;
412
		if (specTypeDepositoryStr.equals("BMNH, London and/or MNHN, Paris")){
413
			collection = state.getRelatedObject(COLLECTION_NAMESPACE, specTypeDepositoryStr, Collection.class);
414
			if (collection == null){
415
				collection = Collection.NewInstance();
416
				collection.setName(specTypeDepositoryStr);
417
				collection.setTownOrLocation("London or Paris");
418
				state.addRelatedObject(COLLECTION_NAMESPACE, collection.getName(), collection);
419
			}
420
			specimen.setCollection(collection);
421
		}else if (specTypeDepositoryStr.equals("coll. L. V. Kaabak, A .V. Sotshivko & V. V. Titov, Moscow")){
422
			String colName = "coll. L. V. Kaabak, A .V. Sotshivko & V. V. Titov";
423
			collection = state.getRelatedObject(COLLECTION_NAMESPACE, colName, Collection.class);
424
			if (collection == null){
425
				collection = Collection.NewInstance();
426
				collection.setName(colName);
427
				collection.setTownOrLocation("Moscow");
428
				state.addRelatedObject(COLLECTION_NAMESPACE, collection.getName(), collection);
429
			}
430
			specimen.setCollection(collection);
431
		}else if (specTypeDepositoryStr.matches("coll. R. E. Parrott?, Port Hope, Ontario")){
432
			String colName = "coll. R. E. Parrott";
433
			collection = state.getRelatedObject(COLLECTION_NAMESPACE, colName, Collection.class);
434
			if (collection == null){
435
				collection = Collection.NewInstance();
436
				collection.setName(colName);
437
				collection.setTownOrLocation("Port Hope, Ontario");
438
				state.addRelatedObject(COLLECTION_NAMESPACE, collection.getName(), collection);
439
			}
440
			specimen.setCollection(collection);
441
		}else{
442
			
443
			String[] split = specTypeDepositoryStr.split(",");
444
			if (split.length != 2){
445
				if (split.length == 1 && split[0].startsWith("coll.")){
446
					collection = state.getRelatedObject(COLLECTION_NAMESPACE, split[0], Collection.class);
447
					if (collection == null){
448
						collection = Collection.NewInstance();
449
						collection.setName(split[0]);
450
						state.addRelatedObject(COLLECTION_NAMESPACE, collection.getName(), collection);
451
					}
452
					specimen.setCollection(collection);
453
				}else{
454
					logger.warn("Split size is not 2: " + specTypeDepositoryStr + " (specTaxID:" + specTaxId + ")");
455
					collection = Collection.NewInstance();
456
					collection.setCode("??");
457
					//TODO deduplicate ??
458
				}
459
				
460
			}else{
461
				String collectionStr = split[0];
462
				String location = split[1].replace("Washington@ D.C.", "Washington, D.C.");
463
				
464
				collection = state.getRelatedObject(COLLECTION_NAMESPACE, collectionStr, Collection.class);
465
				if (collection == null){
466
					collection = Collection.NewInstance();
467
					collection.setCode(collectionStr);
468
					collection.setTownOrLocation(split[1]);
469
					state.addRelatedObject(COLLECTION_NAMESPACE, collection.getCode(), collection);
470
						
471
				}else if (! CdmUtils.nullSafeEqual(location, collection.getTownOrLocation())){
472
					String message = "Location (%s) is not equal to location (%s) of existing collection";
473
					logger.warn(String.format(message, location, collection.getTownOrLocation(), collection.getCode()));
474
				}
475
				
476
				specimen.setCollection(collection);
477
			}
478
		}
479
		return collection;
480
	}
481

    
482

    
483

    
484

    
485
	/**
486
	 * @param specTypeDepositoriesStr
487
	 * @param specTypeDepositoryStr
488
	 * @param specimen
489
	 * @param specTaxId 
490
	 * @return
491
	 */
492
	protected String makeAdditionalSpecimenInformation( String specTypeDepositoryStr, Specimen specimen, Integer specTaxId) {
493
		//doubful
494
		if (specTypeDepositoryStr.endsWith("?")){
495
			Marker.NewInstance(specimen, true, MarkerType.IS_DOUBTFUL());
496
			specTypeDepositoryStr = specTypeDepositoryStr.substring(0, specTypeDepositoryStr.length() -1).trim();
497
		}
498
		
499
		//brackets
500
		Matcher matcher = patternAll.matcher(specTypeDepositoryStr);
501
		if (matcher.find()){
502
			//has brackets
503
			String brackets = matcher.group(2);
504
			brackets = brackets.substring(1, brackets.length()-1);
505
			
506
			brackets = brackets.replace("[mm]", "\u2642\u2642");
507
			brackets = brackets.replace("[m]", "\u2642");
508
			brackets = brackets.replace("[ff]", "\u2640\u2640");
509
			brackets = brackets.replace("[f]", "\u2640");
510
			brackets = brackets.replace("[m/f]", "\u26a5");
511
			
512
			if (brackets.contains("[") || brackets.contains("]")){
513
				logger.warn ("There are still '[', ']' in the bracket part: " + brackets + "; specTaxId: " + specTaxId);
514
			}
515
			
516
			//TODO replace mm/ff by Unicode male 
517
			specimen.setTitleCache(brackets, true);
518
			specTypeDepositoryStr = matcher.group(1).trim();
519
		}
520
		return specTypeDepositoryStr;
521
	}
522

    
523

    
524

    
525

    
526
	/**
527
	 * @param fieldObservation
528
	 * @return
529
	 */
530
	protected Specimen makeSingleTypeSpecimen(FieldObservation fieldObservation) {
531
		DerivationEvent derivEvent = DerivationEvent.NewInstance();
532
//			derivEvent.setType(DerivationEventType.ACCESSIONING());
533
		fieldObservation.addDerivationEvent(derivEvent);
534
		Specimen specimen = Specimen.NewInstance();
535
		specimen.setDerivedFrom(derivEvent);
536
		return specimen;
537
	}
538

    
539

    
540

    
541

    
542
	/**
543
	 * @param state
544
	 * @return
545
	 * @throws SQLException
546
	 */
547
	protected FieldObservation makeTypeFieldObservation(GlobisImportState state, 
548
			ResultSet rs) throws SQLException {
549
		
550
		String countryString = rs.getString("SpecTypeCountry");
551
		
552
		DerivedUnitType unitType = DerivedUnitType.Specimen;
553
		DerivedUnitFacade facade = DerivedUnitFacade.NewInstance(unitType);
554
		
555
		NamedArea typeCountry = getCountry(state, countryString);
556
		facade.setCountry(typeCountry);
557
		FieldObservation fieldObservation = facade.innerFieldObservation();
558
		return fieldObservation;
559
	}
560

    
561

    
562

    
563

    
564
	/**
565
	 * @param name
566
	 * @param rs 
567
	 * @param status
568
	 * @param specimen
569
	 * @param specTaxId 
570
	 * @throws SQLException 
571
	 */
572
	protected void makeTypeDesignation(ZoologicalName name, ResultSet rs, Specimen specimen, Integer specTaxId) throws SQLException {
573
		//type
574
		String specType = rs.getString("SpecType");
575
		SpecimenTypeDesignationStatus status = getTypeDesigType(specType, specTaxId);
576

    
577
		SpecimenTypeDesignation typeDesignation = SpecimenTypeDesignation.NewInstance();
578
		typeDesignation.setTypeStatus(status);
579
		typeDesignation.setTypeSpecimen(specimen);
580
		
581
		name.addTypeDesignation(typeDesignation, true);
582
	}
583

    
584

    
585

    
586

    
587
	private SpecimenTypeDesignationStatus getTypeDesigType(String specType, Integer specTaxId) {
588
		if (isBlank(specType) ){
589
			return null;
590
		}else if (specType.matches("Holotype(.*Holotypus)?")){
591
			return SpecimenTypeDesignationStatus.HOLOTYPE();
592
		}else if (specType.matches("Neotype")){
593
			return SpecimenTypeDesignationStatus.NEOTYPE();
594
		}else if (specType.matches("Syntype(\\(s\\))?") || specType.matches("Syntype.*Syntype\\(s\\)\\s*") ){
595
			return SpecimenTypeDesignationStatus.SYNTYPE();
596
		}else if (specType.matches("Lectotype")){
597
			return SpecimenTypeDesignationStatus.LECTOTYPE();
598
		}else{
599
			logger.warn("SpecimenTypeDesignationStatus does not match: " + specType + " in specTaxId "  + specTaxId);
600
			return null;
601
		}
602
	}
603

    
604

    
605

    
606

    
607
	/**
608
	 * @param state
609
	 * @param referenceMap
610
	 * @param rs
611
	 * @param name
612
	 * @return
613
	 * @throws SQLException
614
	 */
615
	private Reference<?> handleNomRef(GlobisImportState state, Map<String, Reference> referenceMap, ResultSet rs,
616
			ZoologicalName name) throws SQLException {
617
		//ref
618
		Integer refId = nullSafeInt(rs, "fiSpecRefID");
619
		Reference<?> nomRef = null;
620
		if (refId != null){
621
			nomRef = referenceMap.get(String.valueOf(refId));
622
			if (nomRef == null && state.getConfig().getDoReferences().equals(state.getConfig().getDoReferences().ALL)){
623
				logger.warn("Reference " + refId + " could not be found.");
624
			}else if (nomRef != null){
625
				name.setNomenclaturalReference(nomRef);
626
			}
627
		}
628
		
629
		//refDetail
630
		String refDetail = rs.getString("SpecPage");
631
		if (isNotBlank(refDetail)){
632
			name.setNomenclaturalMicroReference(refDetail);
633
		}
634
		return nomRef;
635
	}
636

    
637

    
638

    
639
	
640
	private void validateAcceptedTaxon(Taxon acceptedTaxon, ResultSet rs, Integer specTaxId, Integer acceptedTaxonId) throws SQLException {
641
		if (acceptedTaxon == null){
642
			logger.warn("Accepted taxon is null for taxon taxon to validate: ");
643
			return;
644
		}
645
		
646
		//TODO 
647
		ZoologicalName name = CdmBase.deproxy(acceptedTaxon.getName(), ZoologicalName.class);
648
		
649
		String specName = rs.getString("SpecName");
650
		if (! name.getSpecificEpithet().equals(specName)){
651
			logger.warn(String.format("Species epithet is not equal for accepted taxon: %s - %s", name.getSpecificEpithet(), specName));
652
		}
653
		//TODO
654
	}
655

    
656

    
657

    
658

    
659
	private Synonym getSynonym(GlobisImportState state, ResultSet rs, Integer specTaxId) throws SQLException {
660
		ZoologicalName name = makeName(state, rs, specTaxId);
661
				
662
		Synonym synonym = Synonym.NewInstance(name, state.getTransactionalSourceReference());
663
		
664
		return synonym;
665
	}
666

    
667

    
668

    
669

    
670
	/**
671
	 * @param state
672
	 * @param rs
673
	 * @param specTaxId 
674
	 * @return
675
	 * @throws SQLException
676
	 */
677
	protected ZoologicalName makeName(GlobisImportState state, ResultSet rs, Integer specTaxId)
678
			throws SQLException {
679
		//rank
680
		String rankStr = rs.getString("SpecRank");
681
		Rank rank = null;
682
		if (isNotBlank(rankStr)){
683
			try {
684
				rank = Rank.getRankByNameOrAbbreviation(rankStr, NomenclaturalCode.ICZN, true);
685
			} catch (UnknownCdmTypeException e) {
686
				e.printStackTrace();
687
			}
688
		}
689
		
690
		//name
691
		ZoologicalName name = ZoologicalName.NewInstance(rank);
692
		makeNamePartsAndCache(state, rs, rankStr, name);
693
		
694

    
695
//		name.setGenusOrUninomial(genusOrUninomial);
696
		String authorStr = rs.getString("SpecAuthor");
697
		String yearStr = rs.getString("SpecYear");
698
		String authorAndYearStr = CdmUtils.concat(", ", authorStr, yearStr);
699
		handleAuthorAndYear(authorAndYearStr, name, specTaxId);
700
		
701
		return name;
702
	}
703

    
704

    
705

    
706

    
707
	private void makeNamePartsAndCache(GlobisImportState state, ResultSet rs, String rank, ZoologicalName name) throws SQLException {
708
		String citedFamily = rs.getString("SpecCitedFamily");
709
		String citedGenus = rs.getString("SpecCitedGenus");
710
		String citedSpecies = rs.getString("SpecCitedSpecies");
711
		String citedSubspecies = rs.getString("SpecCitedSubspecies");
712
		String lastEpithet = rs.getString("SpecName");
713
		
714
		
715
		String cache = CdmUtils.concat(" ", new String[]{citedFamily, citedGenus, citedSpecies, citedSubspecies, rank, lastEpithet});
716
		name.setGenusOrUninomial(citedGenus);
717
		//TODO sperate authors
718
		if (isBlank(citedSpecies)){
719
			name.setSpecificEpithet(lastEpithet);
720
		}else{
721
			name.setSpecificEpithet(citedSpecies);
722
			if (isBlank(citedSubspecies)){
723
				name.setInfraSpecificEpithet(lastEpithet);
724
			}
725
		}
726
		
727
		//TODO check if cache needs protection
728
		name.setNameCache(cache, true);
729
	}
730

    
731

    
732
	/* (non-Javadoc)
733
	 * @see eu.etaxonomy.cdm.io.berlinModel.in.IPartitionedIO#getRelatedObjectsForPartition(java.sql.ResultSet)
734
	 */
735
	public Map<Object, Map<String, ? extends CdmBase>> getRelatedObjectsForPartition(ResultSet rs) {
736
		String nameSpace;
737
		Class cdmClass;
738
		Set<String> idSet;
739
		Map<Object, Map<String, ? extends CdmBase>> result = new HashMap<Object, Map<String, ? extends CdmBase>>();
740
		try{
741
			Set<String> taxonIdSet = new HashSet<String>();
742
			Set<String> referenceIdSet = new HashSet<String>();
743
			
744
			while (rs.next()){
745
				handleForeignKey(rs, taxonIdSet, "SpecCurrspecID");
746
				handleForeignKey(rs, referenceIdSet, "fiSpecRefID");
747
			}
748
			
749
			//taxon map
750
			nameSpace = TAXON_NAMESPACE;
751
			cdmClass = Taxon.class;
752
			idSet = taxonIdSet;
753
			Map<String, Taxon> objectMap = (Map<String, Taxon>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
754
			result.put(nameSpace, objectMap);
755

    
756
			//reference map
757
			nameSpace = REFERENCE_NAMESPACE;
758
			cdmClass = Reference.class;
759
			idSet = referenceIdSet;
760
			Map<String, Reference> referenceMap = (Map<String, Reference>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
761
			result.put(nameSpace, referenceMap);
762
			
763
			//collection map
764
			nameSpace = COLLECTION_NAMESPACE;
765
			List<Collection> listCollection = getCollectionService().list(Collection.class, null, null, null, null);
766
			Map<String, Collection> collectionMap = new HashMap<String, Collection>();
767
			for (Collection collection : listCollection){
768
				collectionMap.put(collection.getCode(), collection);
769
				if (isBlank(collection.getCode())){
770
					logger.warn("Collection code is blank: " + collection);
771
				}
772
			}
773
			result.put(nameSpace, collectionMap);
774
			
775
		} catch (SQLException e) {
776
			throw new RuntimeException(e);
777
		}
778
		return result;
779
	}
780
	
781
	/* (non-Javadoc)
782
	 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doCheck(eu.etaxonomy.cdm.io.common.IImportConfigurator)
783
	 */
784
	@Override
785
	protected boolean doCheck(GlobisImportState state){
786
		IOValidator<GlobisImportState> validator = new GlobisSpecTaxaImportValidator();
787
		return validator.validate(state);
788
	}
789
	
790
	
791
	/* (non-Javadoc)
792
	 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#isIgnore(eu.etaxonomy.cdm.io.common.IImportConfigurator)
793
	 */
794
	protected boolean isIgnore(GlobisImportState state){
795
		return ! state.getConfig().isDoSpecTaxa();
796
	}
797

    
798

    
799

    
800

    
801
	@Override
802
	public Reference<?> createObject(ResultSet rs, GlobisImportState state)
803
			throws SQLException {
804
		// not needed
805
		return null;
806
	}
807

    
808
}
(8-8/9)