Project

General

Profile

Download (22.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.pesi.erms;
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.Map;
17
import java.util.Set;
18
import java.util.UUID;
19

    
20
import org.apache.commons.lang3.StringUtils;
21
import org.apache.log4j.Logger;
22
import org.springframework.stereotype.Component;
23

    
24
import eu.etaxonomy.cdm.common.CdmUtils;
25
import eu.etaxonomy.cdm.io.common.DbImportStateBase;
26
import eu.etaxonomy.cdm.io.common.IOValidator;
27
import eu.etaxonomy.cdm.io.common.mapping.DbIgnoreMapper;
28
import eu.etaxonomy.cdm.io.common.mapping.DbImportAnnotationMapper;
29
import eu.etaxonomy.cdm.io.common.mapping.DbImportExtensionMapper;
30
import eu.etaxonomy.cdm.io.common.mapping.DbImportLsidMapper;
31
import eu.etaxonomy.cdm.io.common.mapping.DbImportMapping;
32
import eu.etaxonomy.cdm.io.common.mapping.DbImportMarkerMapper;
33
import eu.etaxonomy.cdm.io.common.mapping.DbImportMethodMapper;
34
import eu.etaxonomy.cdm.io.common.mapping.DbImportObjectCreationMapper;
35
import eu.etaxonomy.cdm.io.common.mapping.DbImportStringMapper;
36
import eu.etaxonomy.cdm.io.common.mapping.DbNotYetImplementedMapper;
37
import eu.etaxonomy.cdm.io.common.mapping.IMappingImport;
38
import eu.etaxonomy.cdm.io.common.mapping.UndefinedTransformerMethodException;
39
import eu.etaxonomy.cdm.io.common.mapping.out.DbLastActionMapper;
40
import eu.etaxonomy.cdm.io.pesi.erms.validation.ErmsTaxonImportValidator;
41
import eu.etaxonomy.cdm.io.pesi.out.PesiTaxonExport;
42
import eu.etaxonomy.cdm.io.pesi.out.PesiTransformer;
43
import eu.etaxonomy.cdm.model.common.AnnotationType;
44
import eu.etaxonomy.cdm.model.common.CdmBase;
45
import eu.etaxonomy.cdm.model.common.ExtensionType;
46
import eu.etaxonomy.cdm.model.common.Language;
47
import eu.etaxonomy.cdm.model.common.MarkerType;
48
import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
49
import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
50
import eu.etaxonomy.cdm.model.name.Rank;
51
import eu.etaxonomy.cdm.model.name.TaxonName;
52
import eu.etaxonomy.cdm.model.name.TaxonNameFactory;
53
import eu.etaxonomy.cdm.model.reference.Reference;
54
import eu.etaxonomy.cdm.model.taxon.Synonym;
55
import eu.etaxonomy.cdm.model.taxon.Taxon;
56
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
57
import eu.etaxonomy.cdm.strategy.cache.name.TaxonNameDefaultCacheStrategy;
58

    
59
/**
60
 * @author a.mueller
61
 * @since 20.02.2010
62
 */
63
@Component
64
public class ErmsTaxonImport
65
        extends ErmsImportBase<TaxonBase<?>>
66
        implements IMappingImport<TaxonBase<?>, ErmsImportState>{
67

    
68
    private static final long serialVersionUID = -7111568277264140051L;
69
    private static final Logger logger = Logger.getLogger(ErmsTaxonImport.class);
70

    
71
	private DbImportMapping<ErmsImportState, ErmsImportConfigurator> mapping;
72

    
73
	private static final String pluralString = "taxa";
74
	private static final String dbTableName = "tu";
75
	private static final Class<?> cdmTargetClass = TaxonBase.class;
76

    
77
	public ErmsTaxonImport(){
78
		super(pluralString, dbTableName, cdmTargetClass);
79
	}
80

    
81
	@Override
82
	protected String getIdQuery() {
83
		String strQuery = " SELECT id FROM tu " ;  //WHERE id NOT IN (147415) for now we exclude Monera as it has no children and is unclear what classification it has. In ERMS it is alternative accepted name (in https://en.wikipedia.org/wiki/Monera it might be a super taxon to bacteria).
84
		return strQuery;
85
	}
86

    
87
	@Override
88
    protected DbImportMapping<ErmsImportState, ErmsImportConfigurator> getMapping() {
89
		if (mapping == null){
90
			mapping = new DbImportMapping<>();
91

    
92
			mapping.addMapper(DbImportObjectCreationMapper.NewInstance(this, "id", TAXON_NAMESPACE)); //id + tu_status
93
			mapping.addMapper(DbImportLsidMapper.NewInstance("GUID", "lsid"));
94

    
95
			UUID tsnUuid = ErmsTransformer.uuidExtTsn;
96
			ExtensionType tsnExtType = getExtensionType(tsnUuid, "TSN", "TSN", "TSN");
97
			mapping.addMapper(DbImportExtensionMapper.NewInstance("tsn", tsnExtType));
98
//			mapping.addMapper(DbImportStringMapper.NewInstance("tu_name", "(NonViralName)name.nameCache"));
99

    
100
			ExtensionType displayNameExtType = getExtensionType(ErmsTransformer.uuidExtDisplayName, "display name", "display name", "display name");
101
			mapping.addMapper(DbImportExtensionMapper.NewInstance("tu_displayname", displayNameExtType));
102
            //Ignore fuzzyName
103
            //  ExtensionType fuzzyNameExtType = getExtensionType(ErmsTransformer.uuidExtFuzzyName, "fuzzy name", "fuzzy name", "fuzzy name");
104
            //  mapping.addMapper(DbImportExtensionMapper.NewInstance("tu_fuzzyname", fuzzyNameExtType));
105
			mapping.addMapper(DbImportStringMapper.NewInstance("tu_authority", "name.authorshipCache"));
106

    
107
			ExtensionType fossilStatusExtType = getExtensionType(ErmsTransformer.uuidExtFossilStatus, "fossil status", "fossil status", "fos. stat.");
108
			mapping.addMapper(DbImportExtensionMapper.NewInstance("fossil_name", fossilStatusExtType));
109

    
110
			ExtensionType unacceptExtType = getExtensionType(ErmsTransformer.uuidExtUnacceptReason, "unaccept reason", "unaccept reason", "reason");
111
			mapping.addMapper(DbImportExtensionMapper.NewInstance("tu_unacceptreason", unacceptExtType));
112

    
113
			ExtensionType qualityStatusExtType = getExtensionType(ErmsTransformer.uuidExtQualityStatus, "quality status", "quality status", "quality status");
114
			mapping.addMapper(DbImportExtensionMapper.NewInstance("qualitystatus_name", qualityStatusExtType)); //checked by Tax Editor ERMS1.1, Added by db management team (2x), checked by Tax Editor
115

    
116
			ExtensionType cacheCitationExtType = getExtensionType(PesiTransformer.uuidExtCacheCitation, "cache_citation", "quality status", "cache_citation");
117
            mapping.addMapper(DbImportExtensionMapper.NewInstance("cache_citation", cacheCitationExtType));
118

    
119
            //flags
120
			mapping.addMapper(DbImportMarkerMapper.NewInstance("tu_marine", ErmsTransformer.uuidMarkerMarine, "marine", "marine", "marine", null));
121
			mapping.addMapper(DbImportMarkerMapper.NewInstance("tu_brackish", ErmsTransformer.uuidMarkerBrackish, "brackish", "brackish", "brackish", null));
122
			mapping.addMapper(DbImportMarkerMapper.NewInstance("tu_fresh", ErmsTransformer.uuidMarkerFreshwater, "freshwater", "fresh", "fresh", null));
123
			mapping.addMapper(DbImportMarkerMapper.NewInstance("tu_terrestrial", ErmsTransformer.uuidMarkerTerrestrial, "terrestrial", "terrestrial", "terrestrial", null));
124

    
125
			//last action, species expert
126
			ExtensionType speciesExpertNameExtType = getExtensionType(PesiTransformer.uuidExtSpeciesExpertName, "species expert name", "species expert name", "species expert name");
127
            mapping.addMapper(DbImportExtensionMapper.NewInstance("ExpertName", speciesExpertNameExtType)); //according to sql script ExpertName maps to SpeciesExpertName in ERMS
128
            AnnotationType lastActionDateType = getAnnotationType(DbLastActionMapper.uuidAnnotationTypeLastActionDate, "Last action date", "Last action date", null);
129
			mapping.addMapper(DbImportAnnotationMapper.NewInstance("lastActionDate", lastActionDateType));
130
            AnnotationType lastActionType = getAnnotationType(DbLastActionMapper.uuidAnnotationTypeLastAction, "Last action", "Last action", null);
131
            MarkerType hasNoLastActionMarkerType = getMarkerType(DbLastActionMapper.uuidMarkerTypeHasNoLastAction, "has no last action", "No last action information available", "no last action");
132
            mapping.addMapper(DbImportAnnotationMapper.NewInstance("lastAction", lastActionType, hasNoLastActionMarkerType));
133

    
134
            //titleCache compare
135
            mapping.addMapper(DbImportMethodMapper.NewDefaultInstance(this, "testTitleCache", ErmsImportState.class));
136

    
137
			//not yet implemented
138
			mapping.addMapper(DbNotYetImplementedMapper.NewInstance("tu_sp", "included in rank/object creation"));
139

    
140
			//ignore
141
			mapping.addMapper(DbIgnoreMapper.NewInstance("tu_fossil", "tu_fossil implemented as foreign key"));
142

    
143
		}
144
		return mapping;
145
	}
146

    
147
	@Override
148
	protected String getRecordQuery(ErmsImportConfigurator config) {
149
		String strSelect = " SELECT tu.*, parent1.tu_name AS parent1name, parent2.tu_name AS parent2name, parent3.tu_name AS parent3name, parent4.tu_name AS parent4name, " +
150
		            " parent1.tu_rank AS parent1rank, parent2.tu_rank AS parent2rank, parent3.tu_rank AS parent3rank, " +
151
		            " status.status_id as status_id, status.status_name, fossil.fossil_name, qualitystatus.qualitystatus_name," +
152
		            " s.sessiondate lastActionDate, a.action_name lastAction, s.ExpertName ";
153
		String strFrom = " FROM tu  LEFT OUTER JOIN  tu AS parent1 ON parent1.id = tu.tu_parent " +
154
				" LEFT OUTER JOIN   tu AS parent2  ON parent2.id = parent1.tu_parent " +
155
				" LEFT OUTER JOIN tu AS parent3 ON parent2.tu_parent = parent3.id " +
156
				" LEFT OUTER JOIN tu AS parent4 ON parent3.tu_parent = parent4.id " +
157
                " LEFT OUTER JOIN status ON tu.tu_status = status.status_id " +
158
				" LEFT OUTER JOIN fossil ON tu.tu_fossil = fossil.fossil_id " +
159
				" LEFT OUTER JOIN qualitystatus ON tu.tu_qualitystatus = qualitystatus.id " +
160
				" LEFT OUTER JOIN tu_sessions ts ON ts.tu_id = tu.id " +
161
                " LEFT OUTER JOIN [sessions] s ON s.id = ts.session_id " +
162
                " LEFT OUTER JOIN actions a ON a.id = ts.action_id ";
163
		String strWhere = " WHERE ( tu.id IN (" + ID_LIST_TOKEN + ") )";
164
		String strOrderBy = " ORDER BY tu.id, s.sessiondate DESC, a.id DESC ";
165
		String strRecordQuery = strSelect + strFrom + strWhere + strOrderBy;
166
		return strRecordQuery;
167
	}
168

    
169
	@Override
170
	protected void doInvoke(ErmsImportState state) {
171
		state.setAcceptedTaxaKeys(getAcceptedTaxaKeys(state));
172

    
173
		//first path
174
		super.doInvoke(state);
175
		return;
176
	}
177

    
178
	Integer lastTaxonId = null;
179
    @Override
180
    protected boolean ignoreRecord(ResultSet rs) throws SQLException {
181
        Integer id = rs.getInt("id");
182
        boolean result = id.equals(lastTaxonId);
183
        lastTaxonId = id;
184
        return result;
185
    }
186

    
187
	private Set<Integer> getAcceptedTaxaKeys(ErmsImportState state) {
188
		Set<Integer> result = new HashSet<>();
189
		String idCol = " id ";
190
		String tuFk = "tu_id";
191
		String vernacularsTable = "vernaculars";
192
		String distributionTable = "dr";
193
		String notesTable = "notes";
194
		String sql =
195
		        "          SELECT id FROM tu WHERE tu_acctaxon is NULL" //id of taxa not having accepted taxon
196
		        + " UNION  SELECT DISTINCT tu_acctaxon FROM tu "  //fk to accepted taxon (either the accepted taxon or the taxon itself, if accepted)
197
		        + " UNION  SELECT syn.id FROM tu syn INNER JOIN tu acc ON syn.tu_acctaxon = acc.id WHERE syn.id = acc.tu_parent AND acc.id <> syn.id "  //see also ErmsTaxonRelationImport.isAccepted, there are some autonyms being the accepted taxon of there own parents
198
                + " UNION  SELECT DISTINCT %s FROM %s " //vernaculars
199
		        + " UNION  SELECT DISTINCT %s FROM %s "  //distributions
200
		        + " UNION  SELECT DISTINCT %s FROM %s ";  //notes
201
		sql = String.format(sql,
202
		        tuFk, vernacularsTable,
203
				tuFk, distributionTable,
204
				tuFk, notesTable);
205
		ResultSet rs = state.getConfig().getSource().getResultSet(sql);
206
		try {
207
			while (rs.next()){
208
				Integer id;
209
				id = rs.getInt(idCol.trim());
210
				result.add(id);
211
			}
212
			return result;
213
		} catch (SQLException e) {
214
			e.printStackTrace();
215
			throw new RuntimeException(e);
216
		}
217
	}
218

    
219
	@Override
220
	public Map<Object, Map<String, ? extends CdmBase>> getRelatedObjectsForPartition(ResultSet rs, ErmsImportState state) {
221
		//currently no referencing objects needed
222
	    Map<Object, Map<String, ? extends CdmBase>> result = new HashMap<>();
223
		return result;
224
	}
225

    
226
	@Override
227
	public TaxonBase<?> createObject(ResultSet rs, ErmsImportState state) throws SQLException {
228
		int statusId = rs.getInt("status_id");
229
//		Object accTaxonId = rs.getObject("tu_acctaxon");
230
		Integer meId = rs.getInt("id");
231

    
232
        TaxonName taxonName = getTaxonName(rs, state);
233
		fillTaxonName(taxonName, rs, state, meId);
234

    
235
		//add original source for taxon name (taxon original source is added in mapper)
236
		Reference citation = state.getTransactionalSourceReference();
237
		addOriginalSource(rs, taxonName, "id", NAME_NAMESPACE, citation);
238

    
239
		TaxonBase<?> result;
240
		//handle accepted<-> synonym, we create more accepted taxa as we need them within the tree or to attache factual data
241
		if (state.getAcceptedTaxaKeys().contains(meId)){
242
			Taxon taxon = Taxon.NewInstance(taxonName, citation);
243
			if (statusId != 1){
244
				logger.info("Taxon created as taxon but has status <> 1 ("+statusId+"): " + meId);
245
				handleNotAcceptedTaxon(taxon, statusId, state, rs);
246
			}
247
			result = taxon;
248
		}else{
249
			result = Synonym.NewInstance(taxonName, citation);
250
		}
251

    
252
		handleNameStatus(result.getName(), rs, state);
253
		return result;
254
	}
255

    
256
    private void handleNameStatus(TaxonName name, ResultSet rs, ErmsImportState state) throws SQLException {
257
        NomenclaturalStatusType nomStatus = null;
258
        int tuStatus = rs.getInt("tu_status");
259
        //the order is bottom up from SQL script as there values are overriden from top to bottom
260
        if (tuStatus == 8){
261
            //species inquirenda
262
            nomStatus = getNomenclaturalStatusType(state, ErmsTransformer.uuidNomStatusSpeciesInquirenda, "species inquirenda", "species inquirenda", null, Language.LATIN(), null);
263
        }else if (tuStatus == 7){
264
            //temporary name
265
            nomStatus = getNomenclaturalStatusType(state, PesiTransformer.uuidNomStatusTemporaryName, "temporary name", "temporary name", null, Language.ENGLISH(), null);
266
        }else if (tuStatus == 6){
267
            //nomen dubium
268
            nomStatus = NomenclaturalStatusType.DOUBTFUL();
269
        }else if (tuStatus == 5){
270
            //"alternate representation"
271
            nomStatus = getNomenclaturalStatusType(state, ErmsTransformer.uuidNomStatusAlternateRepresentation, "alternate representation", "alternate representation", null, Language.ENGLISH(), null);
272
        }else if (tuStatus == 3){
273
            //nomen nudum
274
            nomStatus = NomenclaturalStatusType.NUDUM();
275
        }
276
        if (nomStatus == null){
277
            //IN SQL Script it is set first by unacceptreason and then overriden if above tu_status exists
278
            String unacceptReason = rs.getString("tu_unacceptreason");
279
            try {
280
                nomStatus = state.getTransformer().getNomenclaturalStatusByKey(unacceptReason);
281
            } catch (UndefinedTransformerMethodException e) {logger.warn("Unhandled method");
282
            }
283
        }
284
        if (nomStatus != null){
285
            name.addStatus(nomStatus, null, null);
286
        }
287
    }
288

    
289
    private TaxonName fillTaxonName(TaxonName taxonName, ResultSet rs, ErmsImportState state, Integer meId) throws SQLException {
290
        String tuName = rs.getString("tu_name");
291
		String displayName = rs.getString("tu_displayname");
292

    
293
		String parent1Name = rs.getString("parent1name");
294
		Integer parent1Rank = rs.getInt("parent1rank");
295

    
296
		String parent2Name = rs.getString("parent2name");
297
		Integer parent2Rank = rs.getInt("parent2rank");
298

    
299
		String parent3Name = rs.getString("parent3name");
300
		Integer parent3Rank = rs.getInt("parent3rank");
301

    
302
	    String parent4Name = rs.getString("parent4name");
303

    
304
		//set epithets
305
		if (taxonName.isGenus() || taxonName.isSupraGeneric()){
306
			taxonName.setGenusOrUninomial(tuName);
307
		}else if (taxonName.isInfraGeneric()){
308
			taxonName.setInfraGenericEpithet(tuName);
309
			taxonName.setGenusOrUninomial(parent1Name);
310
		}else if (taxonName.isSpecies()){
311
			taxonName.setSpecificEpithet(tuName);
312
			getGenusAndInfraGenus(parent1Name, parent2Name, parent1Rank, taxonName);
313
		}else if (taxonName.isInfraSpecific()){
314
			if (parent1Rank < 220){
315
				handleException(parent1Rank, taxonName, displayName, meId);
316
			}
317
			taxonName.setInfraSpecificEpithet(tuName);
318
			if (parent1Rank > 220){  //parent is still infraspecific
319
			    taxonName.setSpecificEpithet(parent2Name);
320
			    getGenusAndInfraGenus(parent3Name, parent4Name, parent3Rank, taxonName);
321
			}else{
322
			    //default
323
			    taxonName.setSpecificEpithet(parent1Name);
324
			    getGenusAndInfraGenus(parent2Name, parent3Name, parent2Rank, taxonName);
325
			}
326
		}else if (taxonName.getRank()== null){
327
			if ("Biota".equalsIgnoreCase(tuName)){
328
				Rank rank = Rank.DOMAIN();  //should be Superdomain
329
				taxonName.setRank(rank);
330
				taxonName.setGenusOrUninomial(tuName);
331
			}else{
332
				String warning = "TaxonName has no rank. Use namecache.";
333
				logger.warn(warning);
334
				taxonName.setNameCache(tuName);
335
			}
336
		}
337

    
338
		//e.g. Leucon [Platyhelminthes] ornatus
339
		if (containsBrackets(displayName)){
340
			taxonName.setNameCache(displayName);
341
			logger.warn("Set name cache: " +  displayName + "; id =" + meId);
342
		}
343
        if (!taxonName.getNameCache().equals(displayName)){
344
            int pos = CdmUtils.diffIndex(taxonName.getNameCache(), displayName);
345
            logger.warn("Computed name cache differs at "+pos+".\n Computed   : " + taxonName.getNameCache()+"\n DisplayName: " +displayName);
346
            taxonName.setNameCache(displayName, true);
347
        }
348
		taxonName.getTitleCache();
349
        return taxonName;
350
    }
351

    
352
    @SuppressWarnings("unused")  //used by MethodMapper
353
    private static TaxonBase<?> testTitleCache(ResultSet rs, ErmsImportState state) throws SQLException{
354
        TaxonBase<?> taxon = (TaxonBase<?>)state.getRelatedObject(DbImportStateBase.CURRENT_OBJECT_NAMESPACE, DbImportStateBase.CURRENT_OBJECT_ID);
355
        TaxonName taxonName = taxon.getName();
356
         String displayName = rs.getString("tu_displayname");
357
         displayName = displayName == null ? null : displayName.trim();
358
         String titleCache = taxonName.resetTitleCache(); //calling titleCache should always be kept to have a computed titleCache in the CDM DB.
359
         String expectedTitleCache = getExpectedTitleCache(rs);
360
         //TODO check titleCache, but beware of autonyms
361
         if (!titleCache.equals(expectedTitleCache)){
362
             int pos = CdmUtils.diffIndex(titleCache, expectedTitleCache);
363
             logger.warn("Computed title cache differs at "+pos+".\n Computed             : " + titleCache + "\n DisplayName+Authority: " + expectedTitleCache);
364
             taxonName.setNameCache(displayName, true);
365
         }
366
         return taxon;
367
     }
368

    
369
     //see also PesiErmsValidation.srcFullName()
370
     private static String getExpectedTitleCache(ResultSet srcRs) throws SQLException {
371
        String result;
372
        String epi = srcRs.getString("tu_name");
373
        epi = " a" + epi;
374
        String display = srcRs.getString("tu_displayname");
375
        String sp = srcRs.getString("tu_sp");
376
        if (display.indexOf(epi) != display.lastIndexOf(epi) && !sp.startsWith("#2#")){ //homonym, animal
377
            result = srcRs.getString("tu_displayname").replaceFirst(epi+" ", CdmUtils.concat(" ", " "+epi, srcRs.getString("tu_authority")))+" ";
378
        }else{
379
            result = CdmUtils.concat(" ", srcRs.getString("tu_displayname"), srcRs.getString("tu_authority"));
380
        }
381
        return result;
382
    }
383

    
384
	private void handleNotAcceptedTaxon(Taxon taxon, int statusId, ErmsImportState state, ResultSet rs) throws SQLException {
385
		ExtensionType notAccExtensionType = getExtensionType(state, ErmsTransformer.uuidErmsTaxonStatus, "ERMS taxon status", "ERMS taxon status", "status", null);
386
		String statusName = rs.getString("status_name");
387

    
388
		if (statusId > 1){
389
			taxon.addExtension(statusName, notAccExtensionType);
390
		}
391
	}
392

    
393
	private void handleException(Integer parent1Rank, TaxonName taxonName, String displayName, Integer meId) {
394
		logger.warn("Parent of infra specific taxon is higher than species. Used nameCache: " + displayName +  "; id=" + meId) ;
395
		taxonName.setNameCache(displayName);
396
	}
397

    
398
	private boolean containsBrackets(String displayName) {
399
		int index = displayName.indexOf("[");
400
		return (index > -1);
401
	}
402

    
403
	private void getGenusAndInfraGenus(String parentName, String grandParentName, Integer parent1Rank, TaxonName taxonName) {
404
		if (parent1Rank <220 && parent1Rank > 180){
405
			//parent is infrageneric
406
			taxonName.setInfraGenericEpithet(parentName);
407
			taxonName.setGenusOrUninomial(grandParentName);
408
		}else{
409
			taxonName.setGenusOrUninomial(parentName);
410
		}
411
	}
412

    
413
	/**
414
	 * Returns an empty Taxon Name instance according to the given rank and kingdom.
415
	 */
416
	private TaxonName getTaxonName(ResultSet rs, ErmsImportState state) throws SQLException {
417
	    TaxonName result;
418
		int kingdomId = parseKingdomId(rs);
419
		Integer intRank = rs.getInt("tu_rank");
420

    
421
		NomenclaturalCode nc = ErmsTransformer.kingdomId2NomCode(kingdomId);
422
		Rank rank = null;
423
		rank = state.getRank(intRank, kingdomId);
424

    
425
		if (rank == null){
426
			logger.warn("Rank is null. KingdomId: " + kingdomId + ", rankId: " +  intRank);
427
		}
428
		if (nc != null){
429
			result = nc.getNewTaxonNameInstance(rank);
430
		}else{
431
			result = TaxonNameFactory.NewNonViralInstance(rank);
432
		}
433
		//cache strategy
434
		if (result.isZoological()){
435
		    TaxonNameDefaultCacheStrategy cacheStrategy = PesiTaxonExport.zooNameStrategy;
436
			result.setCacheStrategy(cacheStrategy);
437
		}
438

    
439
		return result;
440
	}
441

    
442
	/**
443
	 * Returns the kingdom id by extracting it from the second character in the <code>tu_sp</code>
444
	 * attribute. If the attribute can not be parsed to a valid id <code>null</code>
445
	 * is returned. If the attribute is <code>null</code> the id of the record is returned.
446
	 * @param rs
447
	 * @return
448
	 * @throws SQLException
449
	 */
450
	private int parseKingdomId(ResultSet rs) throws SQLException {
451
		String treeString = rs.getString("tu_sp");
452
		if (treeString != null){
453
		    if (StringUtils.isNotBlank(treeString) && treeString.length() > 1){
454
				String strKingdom = treeString.substring(1,2);
455

    
456
				if (! treeString.substring(0, 1).equals("#") && ! treeString.substring(2, 3).equals("#") ){
457
					String message = "Tree string " + treeString + " has no recognized format";
458
                    logger.warn(message);
459
                    throw new RuntimeException(message);
460
				}else{
461
					try {
462
						return Integer.valueOf(strKingdom);
463
					} catch (NumberFormatException e) {
464
					    String message = "Kingdom string " + strKingdom + "could not be recognized as a valid number";
465
						logger.warn(message);
466
						throw new RuntimeException(message);
467
					}
468
				}
469
			}else{
470
                String message = "Tree string for kingdom recognition is to short: " + treeString;
471
                logger.warn(message);
472
                throw new RuntimeException(message);
473
			}
474
		}else{
475
			int tu_id = rs.getInt("id");
476
			return tu_id;
477
		}
478
	}
479

    
480
	@Override
481
	protected boolean doCheck(ErmsImportState state){
482
		IOValidator<ErmsImportState> validator = new ErmsTaxonImportValidator();
483
		return validator.validate(state);
484
	}
485

    
486
	@Override
487
    protected boolean isIgnore(ErmsImportState state){
488
		return ! state.getConfig().isDoTaxa();
489
	}
490
}
(13-13/17)