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").trim();
|
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.trim();
|
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
|
}
|