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.eflora.centralAfrica.ferns;
|
11
|
|
12
|
import java.sql.ResultSet;
|
13
|
import java.sql.SQLException;
|
14
|
import java.util.Arrays;
|
15
|
import java.util.HashMap;
|
16
|
import java.util.HashSet;
|
17
|
import java.util.List;
|
18
|
import java.util.Map;
|
19
|
import java.util.Set;
|
20
|
import java.util.UUID;
|
21
|
|
22
|
import org.apache.commons.lang.StringUtils;
|
23
|
import org.apache.log4j.Logger;
|
24
|
import org.springframework.stereotype.Component;
|
25
|
|
26
|
import eu.etaxonomy.cdm.api.service.IClassificationService;
|
27
|
import eu.etaxonomy.cdm.common.CdmUtils;
|
28
|
import eu.etaxonomy.cdm.io.common.IOValidator;
|
29
|
import eu.etaxonomy.cdm.io.common.mapping.DbImportMapping;
|
30
|
import eu.etaxonomy.cdm.io.common.mapping.DbImportMethodMapper;
|
31
|
import eu.etaxonomy.cdm.io.common.mapping.DbImportTaxIncludedInMapper;
|
32
|
import eu.etaxonomy.cdm.io.common.mapping.IMappingImport;
|
33
|
import eu.etaxonomy.cdm.io.common.mapping.UndefinedTransformerMethodException;
|
34
|
import eu.etaxonomy.cdm.io.eflora.centralAfrica.ferns.validation.CentralAfricaFernsTaxonImportValidator;
|
35
|
import eu.etaxonomy.cdm.model.agent.INomenclaturalAuthor;
|
36
|
import eu.etaxonomy.cdm.model.common.CdmBase;
|
37
|
import eu.etaxonomy.cdm.model.common.Language;
|
38
|
import eu.etaxonomy.cdm.model.description.CommonTaxonName;
|
39
|
import eu.etaxonomy.cdm.model.description.Distribution;
|
40
|
import eu.etaxonomy.cdm.model.description.Feature;
|
41
|
import eu.etaxonomy.cdm.model.description.PresenceTerm;
|
42
|
import eu.etaxonomy.cdm.model.description.TaxonDescription;
|
43
|
import eu.etaxonomy.cdm.model.description.TextData;
|
44
|
import eu.etaxonomy.cdm.model.location.NamedArea;
|
45
|
import eu.etaxonomy.cdm.model.location.NamedAreaLevel;
|
46
|
import eu.etaxonomy.cdm.model.location.NamedAreaType;
|
47
|
import eu.etaxonomy.cdm.model.location.TdwgArea;
|
48
|
import eu.etaxonomy.cdm.model.location.WaterbodyOrCountry;
|
49
|
import eu.etaxonomy.cdm.model.name.BotanicalName;
|
50
|
import eu.etaxonomy.cdm.model.name.NonViralName;
|
51
|
import eu.etaxonomy.cdm.model.name.Rank;
|
52
|
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
|
53
|
import eu.etaxonomy.cdm.model.reference.Reference;
|
54
|
import eu.etaxonomy.cdm.model.taxon.Classification;
|
55
|
import eu.etaxonomy.cdm.model.taxon.Synonym;
|
56
|
import eu.etaxonomy.cdm.model.taxon.SynonymRelationship;
|
57
|
import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType;
|
58
|
import eu.etaxonomy.cdm.model.taxon.Taxon;
|
59
|
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
|
60
|
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
|
61
|
|
62
|
|
63
|
/**
|
64
|
* @author a.mueller
|
65
|
*/
|
66
|
|
67
|
@Component
|
68
|
public class CentralAfricaFernsTaxonRelationImport extends CentralAfricaFernsImportBase<TaxonBase> implements IMappingImport<TaxonBase, CentralAfricaFernsImportState>{
|
69
|
private static final Logger logger = Logger.getLogger(CentralAfricaFernsTaxonRelationImport.class);
|
70
|
|
71
|
private DbImportMapping mapping;
|
72
|
|
73
|
|
74
|
private static final String pluralString = "taxon relations";
|
75
|
private static final String dbTableName = "[African pteridophytes]";
|
76
|
private static final Class cdmTargetClass = TaxonBase.class;
|
77
|
|
78
|
private Map<String, UUID> nameCacheTaxonMap = new HashMap<String, UUID>();
|
79
|
private Map<String, UUID> titleCacheTaxonMap = new HashMap<String, UUID>();
|
80
|
|
81
|
private CentralAfricaFernsImportState state;
|
82
|
|
83
|
|
84
|
public CentralAfricaFernsTaxonRelationImport(){
|
85
|
super(pluralString, dbTableName, cdmTargetClass);
|
86
|
}
|
87
|
|
88
|
|
89
|
|
90
|
/* (non-Javadoc)
|
91
|
* @see eu.etaxonomy.cdm.io.erms.ErmsImportBase#getIdQuery()
|
92
|
*/
|
93
|
@Override
|
94
|
protected String getIdQuery() {
|
95
|
String strQuery = " SELECT [Taxon number] FROM " + dbTableName;;
|
96
|
return strQuery;
|
97
|
}
|
98
|
|
99
|
|
100
|
/* (non-Javadoc)
|
101
|
* @see eu.etaxonomy.cdm.io.eflora.centralAfrica.ferns.CentralAfricaFernsImportBase#getMapping()
|
102
|
*/
|
103
|
@Override
|
104
|
protected DbImportMapping getMapping() {
|
105
|
if (mapping == null){
|
106
|
mapping = new DbImportMapping();
|
107
|
|
108
|
mapping.addMapper(DbImportMethodMapper.NewInstance(this, "createObject", ResultSet.class, CentralAfricaFernsImportState.class));
|
109
|
mapping.addMapper(DbImportMethodMapper.NewInstance(this, "mapCommonName", ResultSet.class, CentralAfricaFernsImportState.class));
|
110
|
mapping.addMapper(DbImportMethodMapper.NewInstance(this, "mapDistribution", ResultSet.class, CentralAfricaFernsImportState.class ));
|
111
|
mapping.addMapper(DbImportMethodMapper.NewInstance(this, "mapEcology", ResultSet.class, CentralAfricaFernsImportState.class));
|
112
|
|
113
|
}
|
114
|
return mapping;
|
115
|
}
|
116
|
|
117
|
/* (non-Javadoc)
|
118
|
* @see eu.etaxonomy.cdm.io.eflora.centralAfrica.ferns.CentralAfricaFernsImportBase#getRecordQuery(eu.etaxonomy.cdm.io.eflora.centralAfrica.ferns.CentralAfricaFernsImportConfigurator)
|
119
|
*/
|
120
|
@Override
|
121
|
protected String getRecordQuery(CentralAfricaFernsImportConfigurator config) {
|
122
|
String strSelect = " SELECT * ";
|
123
|
String strFrom = " FROM [African pteridophytes] as ap";
|
124
|
String strWhere = " WHERE ( ap.[taxon number] IN (" + ID_LIST_TOKEN + ") )";
|
125
|
String strOrderBy = " ORDER BY [Taxon number]";
|
126
|
String strRecordQuery = strSelect + strFrom + strWhere + strOrderBy ;
|
127
|
return strRecordQuery;
|
128
|
}
|
129
|
|
130
|
|
131
|
/* (non-Javadoc)
|
132
|
* @see eu.etaxonomy.cdm.io.eflora.centralAfrica.ferns.CentralAfricaFernsImportBase#doInvoke(eu.etaxonomy.cdm.io.eflora.centralAfrica.ferns.CentralAfricaFernsImportState)
|
133
|
*/
|
134
|
@Override
|
135
|
protected void doInvoke(CentralAfricaFernsImportState state) {
|
136
|
this.state = state;
|
137
|
fillTaxonMap();
|
138
|
super.doInvoke(state);
|
139
|
return;
|
140
|
}
|
141
|
|
142
|
|
143
|
/**
|
144
|
* Fills the nameCache and the titleCache maps. The maps are used to find existing taxa
|
145
|
* by titleCache or nameCache matching.
|
146
|
* Matching may be implemented more sophisticated in future versions.
|
147
|
*/
|
148
|
private void fillTaxonMap() {
|
149
|
List<String> propPath = Arrays.asList(new String []{"name"});
|
150
|
|
151
|
List<Taxon> taxonList = (List)getTaxonService().list(Taxon.class, null, null, null, propPath );
|
152
|
for (Taxon taxon : taxonList){
|
153
|
NonViralName nvn = CdmBase.deproxy(taxon.getName(), NonViralName.class);
|
154
|
UUID uuid = taxon.getUuid();
|
155
|
String nameCache = nvn.getNameCache();
|
156
|
String titleCache = nvn.getTitleCache();
|
157
|
nameCacheTaxonMap.put(nameCache, uuid);
|
158
|
titleCacheTaxonMap.put(titleCache, uuid);
|
159
|
}
|
160
|
}
|
161
|
|
162
|
/* (non-Javadoc)
|
163
|
* @see eu.etaxonomy.cdm.io.common.IPartitionedIO#getRelatedObjectsForPartition(java.sql.ResultSet)
|
164
|
*/
|
165
|
public Map<Object, Map<String, ? extends CdmBase>> getRelatedObjectsForPartition(ResultSet rs) {
|
166
|
String nameSpace;
|
167
|
Class cdmClass;
|
168
|
Set<String> idSet;
|
169
|
Map<Object, Map<String, ? extends CdmBase>> result = new HashMap<Object, Map<String, ? extends CdmBase>>();
|
170
|
|
171
|
try{
|
172
|
Set<String> taxonIdSet = new HashSet<String>();
|
173
|
// Set<String> referenceIdSet = new HashSet<String>();
|
174
|
while (rs.next()){
|
175
|
handleForeignKey(rs, taxonIdSet, "Current");
|
176
|
handleForeignKey(rs, taxonIdSet, "Taxon number");
|
177
|
// handleForeignKey(rs, referenceIdSet, "PTRefFk");
|
178
|
}
|
179
|
|
180
|
//taxon map
|
181
|
nameSpace = TAXON_NAMESPACE;
|
182
|
cdmClass = TaxonBase.class;
|
183
|
Map<String, TaxonBase> taxonMap = (Map<String, TaxonBase>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, taxonIdSet, nameSpace);
|
184
|
result.put(nameSpace, taxonMap);
|
185
|
|
186
|
|
187
|
//reference map
|
188
|
this.sourceReference = getFernsSourceReference(state);
|
189
|
// nameSpace = "Reference";
|
190
|
// cdmClass = Reference.class;
|
191
|
// Map<String, Person> referenceMap = (Map<String, Person>)getCommonService().getSourcedObjectsByIdInSource(Person.class, teamIdSet, nameSpace);
|
192
|
// result.put(Reference.class, referenceMap);
|
193
|
|
194
|
} catch (SQLException e) {
|
195
|
throw new RuntimeException(e);
|
196
|
}
|
197
|
return result;
|
198
|
}
|
199
|
|
200
|
|
201
|
/* (non-Javadoc)
|
202
|
* @see eu.etaxonomy.cdm.io.common.mapping.IMappingImport#createObject(java.sql.ResultSet, eu.etaxonomy.cdm.io.common.ImportStateBase)
|
203
|
*/
|
204
|
@Override
|
205
|
public TaxonBase createObject(ResultSet rs, CentralAfricaFernsImportState state) throws SQLException {
|
206
|
TaxonBase result = null;
|
207
|
try {
|
208
|
String status = rs.getString("Current/Synonym");
|
209
|
String taxonNumber = rs.getString("Taxon number");
|
210
|
state.setTaxonNumber(taxonNumber);
|
211
|
if ("s".equalsIgnoreCase(status)){
|
212
|
//synonym
|
213
|
result = handleSynonym(rs, state);
|
214
|
}else{
|
215
|
//accepted Taxon
|
216
|
result = handleTaxon(rs, state);
|
217
|
}
|
218
|
|
219
|
return result;
|
220
|
} catch (Exception e) {
|
221
|
e.printStackTrace();
|
222
|
return result;
|
223
|
}
|
224
|
|
225
|
}
|
226
|
|
227
|
|
228
|
/**
|
229
|
* Class to store all epithets of the database record. Maybe extended with business logic.
|
230
|
*/
|
231
|
private class Epithets{
|
232
|
private String orderName;
|
233
|
private String subOrderName;
|
234
|
private String familyName;
|
235
|
private String subFamilyName;
|
236
|
private String tribusName;
|
237
|
private String subTribusName;
|
238
|
private String sectionName;
|
239
|
private String subsectionName;
|
240
|
private String genusName;
|
241
|
private String subGenusName;
|
242
|
private String seriesName;
|
243
|
private String specificEpithet;
|
244
|
private String subspeciesName;
|
245
|
private String varietyName;
|
246
|
private String subVariety;
|
247
|
private String formaName;
|
248
|
private String subFormaName;
|
249
|
}
|
250
|
|
251
|
|
252
|
/**
|
253
|
* Handles records with status synonym. A synonym relationship to the accepted taxon
|
254
|
* is created.
|
255
|
* @param rs
|
256
|
* @param state
|
257
|
* @return
|
258
|
* @throws SQLException
|
259
|
*/
|
260
|
private Synonym handleSynonym(ResultSet rs, CentralAfricaFernsImportState state) throws SQLException {
|
261
|
String accTaxonId = rs.getString("Current");
|
262
|
String nomRemarksString = rs.getString("Current/Synonym");
|
263
|
|
264
|
String synonymId = state.getTaxonNumber();
|
265
|
Synonym synonym = (Synonym)state.getRelatedObject(TAXON_NAMESPACE, synonymId);
|
266
|
if (synonym == null){
|
267
|
logger.warn ("Synonym ("+synonymId+")not found.");
|
268
|
return null;
|
269
|
}
|
270
|
TaxonBase taxonBase = CdmBase.deproxy(state.getRelatedObject(TAXON_NAMESPACE, accTaxonId), TaxonBase.class);
|
271
|
|
272
|
if (taxonBase != null){
|
273
|
if (taxonBase.isInstanceOf(Taxon.class)){
|
274
|
Taxon taxon = CdmBase.deproxy(taxonBase, Taxon.class);
|
275
|
SynonymRelationship rel = taxon.addSynonym(synonym, SynonymRelationshipType.SYNONYM_OF());
|
276
|
if ("p.p.".equalsIgnoreCase(nomRemarksString)){
|
277
|
rel.setProParte(true);
|
278
|
}
|
279
|
}else{
|
280
|
logger.warn("Accepted taxon (" + accTaxonId + ") for synonym (" + synonymId +") is not of type 'Current'");
|
281
|
}
|
282
|
}else{
|
283
|
logger.warn("Taxon (" + accTaxonId + ") not found for synonym (" + synonymId +")");
|
284
|
}
|
285
|
|
286
|
return synonym;
|
287
|
}
|
288
|
|
289
|
|
290
|
/**
|
291
|
* Handles all records with status 'current'. Creates parent-child relationships to the
|
292
|
* higher taxa. Uses a complex algorithm to reuse existing higher taxa.
|
293
|
* @param rs
|
294
|
* @param state
|
295
|
* @return
|
296
|
* @throws SQLException
|
297
|
*/
|
298
|
private Taxon handleTaxon(ResultSet rs, CentralAfricaFernsImportState state) throws SQLException {
|
299
|
String taxonNumber = rs.getString("Taxon number");
|
300
|
Taxon child = (Taxon)state.getRelatedObject(TAXON_NAMESPACE, taxonNumber);
|
301
|
if (child == null){
|
302
|
logger.warn("Taxon does not exist: " + taxonNumber);
|
303
|
return null;
|
304
|
}
|
305
|
Epithets epithets = new Epithets();
|
306
|
epithets.orderName = rs.getString("Order name");
|
307
|
epithets.subOrderName = rs.getString("Suborder name");
|
308
|
epithets.familyName = rs.getString("Family name");
|
309
|
epithets.subFamilyName = rs.getString("Subfamily name");
|
310
|
epithets.tribusName = rs.getString("Tribus name");
|
311
|
epithets.subTribusName = rs.getString("Subtribus name");
|
312
|
epithets.sectionName = rs.getString("Section name");
|
313
|
epithets.subsectionName = rs.getString("Subsection name");
|
314
|
epithets.genusName = rs.getString("Genus name");
|
315
|
epithets.subGenusName = rs.getString("Subgenus name");
|
316
|
epithets.seriesName = rs.getString("Series name");
|
317
|
epithets.specificEpithet = rs.getString("Specific epihet");
|
318
|
epithets.subspeciesName = rs.getString("Subspecies name");
|
319
|
epithets.varietyName = rs.getString("Variety name");
|
320
|
epithets.subVariety = rs.getString("Subvariery");
|
321
|
epithets.formaName = rs.getString("Forma name");
|
322
|
epithets.subFormaName = rs.getString("Subforma");
|
323
|
|
324
|
makeNextHigherTaxon(state, rs, child, epithets);
|
325
|
return child;
|
326
|
}
|
327
|
|
328
|
|
329
|
/**
|
330
|
* Adds recursively this taxon to the next higher taxon. If the taxon exists already
|
331
|
* the relationship is not added again.<BR>
|
332
|
* If the author is missing in the old taxon but not in the new taxon the
|
333
|
* old taxon will get the new taxons author.(NOT VALID ANY MORE)<BR>
|
334
|
* If authors differ a new taxon is created.<BR>
|
335
|
* If a higher taxon exists the method is called recursively on this taxon.
|
336
|
* @throws SQLException
|
337
|
*/
|
338
|
private void makeNextHigherTaxon(CentralAfricaFernsImportState state, ResultSet rs, Taxon child, Epithets epithets) throws SQLException {
|
339
|
|
340
|
Taxon constructedHigherTaxon = constructNextHigherTaxon(state, rs, child, epithets);
|
341
|
Reference<?> citation = null;
|
342
|
String microcitation = null;
|
343
|
|
344
|
if (constructedHigherTaxon != null){
|
345
|
handleHigherTaxonMustExist(state, rs, child, epithets, constructedHigherTaxon, citation, microcitation);
|
346
|
}else{
|
347
|
//add taxon to tree if not yet added
|
348
|
if (child.getTaxonNodes().size() == 0){
|
349
|
makeTaxonomicallyIncluded(state, null, child, null, citation, microcitation);
|
350
|
}
|
351
|
}
|
352
|
}
|
353
|
|
354
|
|
355
|
|
356
|
/**
|
357
|
* Handles the case when the database record has data for a taxon of a higher rank
|
358
|
* than the <code>child</code> taxon's rank.
|
359
|
* @param state
|
360
|
* @param rs
|
361
|
* @param child
|
362
|
* @param epithets
|
363
|
* @param higherTaxon
|
364
|
* @param citation
|
365
|
* @param microcitation
|
366
|
* @throws SQLException
|
367
|
*/
|
368
|
private void handleHigherTaxonMustExist(CentralAfricaFernsImportState state, ResultSet rs, Taxon child, Epithets epithets, Taxon constructedHigherTaxon, Reference<?> citation, String microCitation) throws SQLException {
|
369
|
Taxon parentTaxon = getParent(child);
|
370
|
if (parentTaxon == null){
|
371
|
//if no parent taxon exists
|
372
|
Taxon existingTaxon = findExistingNonParentTaxon(state, constructedHigherTaxon);
|
373
|
if (existingTaxon != null){
|
374
|
//a taxon with same title cache or same name cache exists
|
375
|
parentTaxon = mergeExistingAndConstructedTaxon(state, existingTaxon, constructedHigherTaxon);
|
376
|
}else{
|
377
|
parentTaxon = constructedHigherTaxon;
|
378
|
}
|
379
|
makeTaxonomicallyIncluded(state, null, child, parentTaxon, citation, microCitation);
|
380
|
}else{
|
381
|
//parent taxon exists
|
382
|
if (namesMatch(parentTaxon, constructedHigherTaxon)){
|
383
|
//parents match
|
384
|
//TODO what if the higher taxonomy does not match
|
385
|
parentTaxon = mergeExistingAndConstructedTaxon(state, parentTaxon, constructedHigherTaxon);
|
386
|
}else if (compareRanks(parentTaxon, constructedHigherTaxon) != 0){
|
387
|
//ranks unequal
|
388
|
parentTaxon = handleUnequalRanks(parentTaxon, constructedHigherTaxon);
|
389
|
}else if (! nameCachesMatch(parentTaxon, constructedHigherTaxon)){
|
390
|
//nameCache not equal
|
391
|
parentTaxon = handleUnequalNameCaches(parentTaxon, constructedHigherTaxon);
|
392
|
}else if (! authorsMatch(parentTaxon, constructedHigherTaxon)){
|
393
|
//nameCache not equal
|
394
|
parentTaxon = handleUnequalAuthors(parentTaxon, constructedHigherTaxon);
|
395
|
}
|
396
|
}
|
397
|
//save the parent taxon, if it is new
|
398
|
if (parentTaxon == constructedHigherTaxon){
|
399
|
saveConstructedTaxon(state, constructedHigherTaxon);
|
400
|
}
|
401
|
makeNextHigherTaxon(state, rs, parentTaxon, epithets);
|
402
|
}
|
403
|
|
404
|
|
405
|
/**
|
406
|
* Merges author information of the constructed taxon into the existing taxon.
|
407
|
* Returns the existing taxon.
|
408
|
* @param state
|
409
|
* @param parentTaxon
|
410
|
* @param constructedHigherTaxon
|
411
|
*/
|
412
|
private Taxon mergeExistingAndConstructedTaxon(CentralAfricaFernsImportState state, Taxon existingTaxon, Taxon constructedTaxon) {
|
413
|
NonViralName constructedName = CdmBase.deproxy(constructedTaxon.getName(), NonViralName.class);
|
414
|
NonViralName existingName = CdmBase.deproxy(existingTaxon.getName(), NonViralName.class);
|
415
|
if (constructedName.hasAuthors()){
|
416
|
if (! existingName.hasAuthors()){
|
417
|
logger.warn(state.getTaxonNumber() + " - Constrcucted name ("+constructedName.getTitleCache()+") has authors but existing name ("+existingName.getTitleCache()+") has no authors");
|
418
|
}else if (! authorsMatch(constructedName, existingName)){
|
419
|
logger.warn(state.getTaxonNumber() + " - Constrcucted name ("+constructedName.getTitleCache()+") and existing name ("+existingName.getTitleCache()+") have different authors");
|
420
|
}else {
|
421
|
//authors match and are not null
|
422
|
}
|
423
|
}
|
424
|
// more?
|
425
|
return existingTaxon;
|
426
|
}
|
427
|
|
428
|
|
429
|
/**
|
430
|
* Strategy for the decision if an existing parent or a constructed higher taxon should
|
431
|
* be taken as parent in case that the authors of the name differ somehow.
|
432
|
* Current strategy: use existing parent if constructed higher taxon has no authors
|
433
|
* at all. Use constructed taxon otherwise.
|
434
|
* @param existingParentTaxon
|
435
|
* @param constructedHigherTaxon
|
436
|
* @return
|
437
|
*/
|
438
|
private Taxon handleUnequalAuthors(Taxon existingParentTaxon, Taxon constructedHigherTaxon) {
|
439
|
Taxon result;
|
440
|
BotanicalName existingName = CdmBase.deproxy(existingParentTaxon.getName(), BotanicalName.class);
|
441
|
BotanicalName constructedName = (BotanicalName)constructedHigherTaxon.getName();
|
442
|
//current strategy: if constructedName has no authors (and parentName has
|
443
|
if (! constructedName.hasAuthors()){
|
444
|
result = existingParentTaxon;
|
445
|
}else if (! existingName.hasAuthors()){
|
446
|
result = constructedHigherTaxon;
|
447
|
}else{
|
448
|
result = constructedHigherTaxon;
|
449
|
}
|
450
|
return result;
|
451
|
}
|
452
|
|
453
|
/**
|
454
|
* Strategy for the decision if an existing parent or a constructed higher taxon
|
455
|
* should be taken as parent in case that the name caches differ somehow.
|
456
|
* Current strategy: Not implemented. Always use constructed higher taxon.
|
457
|
* @param existingParentTaxon
|
458
|
* @param constructedHigherTaxon
|
459
|
* @return
|
460
|
*/
|
461
|
private Taxon handleUnequalNameCaches(Taxon parentTaxon, Taxon constructedHigherTaxon) {
|
462
|
BotanicalName parentName = CdmBase.deproxy(parentTaxon.getName(), BotanicalName.class);
|
463
|
BotanicalName constructedName = (BotanicalName)constructedHigherTaxon.getName();
|
464
|
logger.warn("handleUnequalNameCaches not yet implemented");
|
465
|
return constructedHigherTaxon;
|
466
|
}
|
467
|
|
468
|
|
469
|
/**
|
470
|
* Handles the case that the existing parent taxon and the constructed parent taxon
|
471
|
* have a diffent rank. Returns the constructedHigherTaxon if no common grand parent exists.
|
472
|
* @param parentTaxon
|
473
|
* @param constructedHigherTaxon
|
474
|
* @return
|
475
|
*/
|
476
|
private Taxon handleUnequalRanks(Taxon parentTaxon, Taxon constructedHigherTaxon) {
|
477
|
BotanicalName parentName = CdmBase.deproxy(parentTaxon.getName(), BotanicalName.class);
|
478
|
BotanicalName constructedName = (BotanicalName)constructedHigherTaxon.getName();
|
479
|
int compare = compareRanks(parentName, constructedName);
|
480
|
Taxon lowerTaxon = parentTaxon;
|
481
|
Taxon grandParentTaxon = constructedHigherTaxon;
|
482
|
if (compare < 0){
|
483
|
lowerTaxon = constructedHigherTaxon;
|
484
|
grandParentTaxon = parentTaxon;
|
485
|
}
|
486
|
Taxon commonGrandParent = checkIsGrandParent(lowerTaxon, grandParentTaxon);
|
487
|
if (commonGrandParent != null){
|
488
|
if (lowerTaxon == constructedHigherTaxon){
|
489
|
//TODO merge
|
490
|
logger.warn("Merge in between taxon not yet implemented");
|
491
|
}
|
492
|
}else{
|
493
|
return constructedHigherTaxon;
|
494
|
}
|
495
|
return lowerTaxon;
|
496
|
}
|
497
|
|
498
|
/**
|
499
|
* Tries to find a taxon which matches the constructed taxon but is not a parent
|
500
|
* taxon of the constructed taxon's child (condition will not be checked).
|
501
|
* Returns null if no such taxon exists.
|
502
|
* @param constructedHigherTaxon
|
503
|
* @param state
|
504
|
* @return
|
505
|
*/
|
506
|
private Taxon findExistingNonParentTaxon(CentralAfricaFernsImportState state, Taxon constructedHigherTaxon) {
|
507
|
BotanicalName constructedName = CdmBase.deproxy(constructedHigherTaxon.getName(), BotanicalName.class);
|
508
|
String titleCache = constructedName.getTitleCache();
|
509
|
String nameCache = constructedName.getNameCache();
|
510
|
UUID existingUuid = titleCacheTaxonMap.get(titleCache);
|
511
|
if (existingUuid == null){
|
512
|
existingUuid = nameCacheTaxonMap.get(nameCache);
|
513
|
}
|
514
|
Taxon relatedTaxon = null;
|
515
|
if (existingUuid != null){
|
516
|
relatedTaxon = state.getRelatedObject(HIGHER_TAXON_NAMESPACE, nameCache, Taxon.class);
|
517
|
if (relatedTaxon == null){
|
518
|
//TODO find for partition
|
519
|
relatedTaxon = (Taxon)getTaxonService().find(existingUuid);
|
520
|
if (relatedTaxon == null){
|
521
|
logger.info(state.getTaxonNumber() + " - Could not find existing name ("+nameCache+") in related objects map");
|
522
|
}else{
|
523
|
state.addRelatedObject(HIGHER_TAXON_NAMESPACE, nameCache, relatedTaxon);
|
524
|
}
|
525
|
}
|
526
|
}
|
527
|
return relatedTaxon;
|
528
|
}
|
529
|
|
530
|
/**
|
531
|
* Checks if a taxon is a grand parent of another taxon
|
532
|
* @param lowerTaxon
|
533
|
* @param higherTaxon
|
534
|
* @return
|
535
|
*/
|
536
|
private Taxon checkIsGrandParent(Taxon childTaxon, Taxon grandParentTaxon) {
|
537
|
BotanicalName lowerName = CdmBase.deproxy(childTaxon.getName(), BotanicalName.class);
|
538
|
BotanicalName higherName = CdmBase.deproxy(grandParentTaxon.getName(), BotanicalName.class);
|
539
|
|
540
|
//TODO was wenn lowerTaxon constructed ist
|
541
|
logger.warn("checkIsGrandParent not yet fully implemented");
|
542
|
Taxon nextParent = getParent(childTaxon);
|
543
|
if (namesMatch(nextParent, grandParentTaxon)){
|
544
|
//TODO which one to return? Merging ?
|
545
|
logger.warn("checkIsGrandParent(matching) not yet fully implemented");
|
546
|
return grandParentTaxon;
|
547
|
}else{
|
548
|
if (compareRanks(lowerName, higherName) >= 0){
|
549
|
return null;
|
550
|
}else{
|
551
|
return checkIsGrandParent(childTaxon, grandParentTaxon);
|
552
|
}
|
553
|
}
|
554
|
}
|
555
|
|
556
|
|
557
|
/**
|
558
|
* Checks if the name caches match.
|
559
|
* @param name1
|
560
|
* @param name2
|
561
|
* @return
|
562
|
*/
|
563
|
private boolean nameCachesMatch(BotanicalName name1, BotanicalName name2) {
|
564
|
return CdmUtils.nullSafeEqual(name1.getNameCache(), name2.getNameCache());
|
565
|
}
|
566
|
|
567
|
/**
|
568
|
* Checks if the name caches of the related names match.
|
569
|
*@param taxon1
|
570
|
* @param taxon2
|
571
|
* @return
|
572
|
*/
|
573
|
private boolean nameCachesMatch(Taxon taxon1, Taxon taxon2) {
|
574
|
BotanicalName name1 = CdmBase.deproxy(taxon1.getName(), BotanicalName.class);
|
575
|
BotanicalName name2 = CdmBase.deproxy(taxon2.getName(), BotanicalName.class);
|
576
|
return nameCachesMatch(name1, name2);
|
577
|
}
|
578
|
|
579
|
|
580
|
/**
|
581
|
* Checks if all authors match
|
582
|
* @param name1
|
583
|
* @param name2
|
584
|
* @return
|
585
|
*/
|
586
|
private boolean authorsMatch(NonViralName<?> name1, NonViralName<?> name2) {
|
587
|
String combinationAuthor1 = name1.computeCombinationAuthorNomenclaturalTitle();
|
588
|
String combinationAuthor2 = name2.computeCombinationAuthorNomenclaturalTitle();
|
589
|
String basionymAuthor1 = name1.computeBasionymAuthorNomenclaturalTitle();
|
590
|
String basionymAuthor2 = name2.computeBasionymAuthorNomenclaturalTitle();
|
591
|
String exCombinationAuthor1 = name1.computeExCombinationAuthorNomenclaturalTitle();
|
592
|
String exCombinationAuthor2 = name2.computeExCombinationAuthorNomenclaturalTitle();
|
593
|
String exBasionymAuthor1 = name1.computeExBasionymAuthorNomenclaturalTitle();
|
594
|
String exBasionymAuthor2 = name2.computeExBasionymAuthorNomenclaturalTitle();
|
595
|
boolean result =
|
596
|
CdmUtils.nullSafeEqual(combinationAuthor1, combinationAuthor2) &&
|
597
|
CdmUtils.nullSafeEqual(basionymAuthor1, basionymAuthor2) &&
|
598
|
CdmUtils.nullSafeEqual(exCombinationAuthor1, exCombinationAuthor2) &&
|
599
|
CdmUtils.nullSafeEqual(exBasionymAuthor1, exBasionymAuthor2);
|
600
|
return result;
|
601
|
}
|
602
|
|
603
|
/**
|
604
|
* Checks if all authors of the related names match.
|
605
|
* @param taxon1
|
606
|
* @param taxon2
|
607
|
* @return
|
608
|
*/
|
609
|
private boolean authorsMatch(Taxon taxon1, Taxon taxon2) {
|
610
|
BotanicalName name1 = CdmBase.deproxy(taxon1.getName(), BotanicalName.class);
|
611
|
BotanicalName name2 = CdmBase.deproxy(taxon2.getName(), BotanicalName.class);
|
612
|
return authorsMatch(name1, name2);
|
613
|
}
|
614
|
|
615
|
/**
|
616
|
* Compares ranks of 2 names.
|
617
|
* @param parentName
|
618
|
* @param constructedName
|
619
|
* @return
|
620
|
*/
|
621
|
private int compareRanks(BotanicalName name1, BotanicalName name2) {
|
622
|
return name1.getRank().compareTo(name2.getRank());
|
623
|
}
|
624
|
|
625
|
/**
|
626
|
* Compares the ranks of the according names.
|
627
|
* @param taxon1
|
628
|
* @param taxon2
|
629
|
* @return
|
630
|
*/
|
631
|
private int compareRanks(Taxon taxon1, Taxon taxon2) {
|
632
|
BotanicalName name1 = CdmBase.deproxy(taxon1.getName(), BotanicalName.class);
|
633
|
BotanicalName name2 = CdmBase.deproxy(taxon2.getName(), BotanicalName.class);
|
634
|
return compareRanks(name1, name2);
|
635
|
}
|
636
|
|
637
|
|
638
|
|
639
|
/**
|
640
|
* Checks if 2 names match.
|
641
|
* Current strategy: true, if ranks are equal, nameCaches match and authors match
|
642
|
* @param name1
|
643
|
* @param name2
|
644
|
* @return
|
645
|
*/
|
646
|
private boolean namesMatch(BotanicalName name1, BotanicalName name2) {
|
647
|
return compareRanks(name1, name2)==0 && nameCachesMatch(name1, name2) && authorsMatch(name1, name2);
|
648
|
}
|
649
|
|
650
|
/**
|
651
|
* Checks if the according names match.
|
652
|
* @see #namesMatch(BotanicalName, BotanicalName)
|
653
|
* @param taxon1
|
654
|
* @param taxon2
|
655
|
* @return
|
656
|
*/
|
657
|
private boolean namesMatch(Taxon taxon1, Taxon taxon2) {
|
658
|
BotanicalName name1 = CdmBase.deproxy(taxon1.getName(), BotanicalName.class);
|
659
|
BotanicalName name2 = CdmBase.deproxy(taxon2.getName(), BotanicalName.class);
|
660
|
return namesMatch(name1, name2);
|
661
|
}
|
662
|
|
663
|
|
664
|
/**
|
665
|
* Returns the only parent of the taxon. If not parent exists <code>null</code> is
|
666
|
* returned.
|
667
|
* TODO move to taxon class (with classification)
|
668
|
* @param child
|
669
|
* @return
|
670
|
* @throws IllegalStateException if taxon belongs to multiple states
|
671
|
*/
|
672
|
private Taxon getParent(Taxon child) {
|
673
|
int countNodes = child.getTaxonNodes().size();
|
674
|
if (countNodes < 1){
|
675
|
return null;
|
676
|
}else if (countNodes > 1){
|
677
|
throw new IllegalStateException("Multiple nodes exist for child taxon. This is an invalid state for this import.");
|
678
|
}else{
|
679
|
TaxonNode childNode = child.getTaxonNodes().iterator().next();
|
680
|
TaxonNode parentNode = childNode.getParent();
|
681
|
if (parentNode != null){
|
682
|
return parentNode.getTaxon();
|
683
|
}else{
|
684
|
return null;
|
685
|
}
|
686
|
}
|
687
|
}
|
688
|
|
689
|
|
690
|
/**
|
691
|
* Persists and saves the newly created taxon to the CDM store and to the look-up
|
692
|
* maps.
|
693
|
* @param state
|
694
|
* @param constructedHigherTaxon
|
695
|
* @return
|
696
|
*/
|
697
|
private Taxon saveConstructedTaxon(CentralAfricaFernsImportState state, Taxon constructedHigherTaxon) {
|
698
|
BotanicalName constructedName = CdmBase.deproxy(constructedHigherTaxon.getName(), BotanicalName.class);
|
699
|
String nameCache = constructedName.getNameCache();
|
700
|
String titleCache = constructedName.getTitleCache();
|
701
|
nameCacheTaxonMap.put(nameCache, constructedHigherTaxon.getUuid());
|
702
|
titleCacheTaxonMap.put(titleCache, constructedHigherTaxon.getUuid());
|
703
|
state.addRelatedObject(HIGHER_TAXON_NAMESPACE, nameCache, constructedHigherTaxon);
|
704
|
|
705
|
//persist
|
706
|
// Reference citation = state.getConfig().getSourceReference(); //throws nonUniqueObject exception
|
707
|
Reference citation = null;
|
708
|
String id = state.getTaxonNumber() + "-" + constructedName.getRank().getTitleCache();
|
709
|
addOriginalSource(constructedName, id, NAME_NAMESPACE, citation);
|
710
|
addOriginalSource(constructedHigherTaxon, id, TAXON_NAMESPACE, citation);
|
711
|
getTaxonService().save(constructedHigherTaxon);
|
712
|
|
713
|
return constructedHigherTaxon;
|
714
|
}
|
715
|
|
716
|
|
717
|
//TODO use Mapper
|
718
|
/**
|
719
|
* Adds the parent child relationship. Creates and saves the classification if needed.
|
720
|
* Adds parent and child to the classification.
|
721
|
* @param state
|
722
|
* @param treeRefFk
|
723
|
* @param child
|
724
|
* @param parent
|
725
|
* @param citation
|
726
|
* @param microCitation
|
727
|
* @return
|
728
|
*/
|
729
|
private boolean makeTaxonomicallyIncluded(CentralAfricaFernsImportState state, Integer treeRefFk, Taxon child, Taxon parent, Reference citation, String microCitation){
|
730
|
String treeKey;
|
731
|
UUID treeUuid;
|
732
|
if (treeRefFk == null){
|
733
|
treeKey = "1"; // there is only one tree and it gets the map key '1'
|
734
|
treeUuid = state.getConfig().getClassificationUuid();
|
735
|
}else{
|
736
|
treeKey =String.valueOf(treeRefFk);
|
737
|
treeUuid = state.getTreeUuidByTreeKey(treeKey);
|
738
|
}
|
739
|
Classification tree = (Classification)state.getRelatedObject(DbImportTaxIncludedInMapper.TAXONOMIC_TREE_NAMESPACE, treeKey);
|
740
|
if (tree == null){
|
741
|
IClassificationService service = state.getCurrentIO().getClassificationService();
|
742
|
tree = service.find(treeUuid);
|
743
|
if (tree == null){
|
744
|
String treeName = state.getConfig().getClassificationName();
|
745
|
tree = Classification.NewInstance(treeName);
|
746
|
tree.setUuid(treeUuid);
|
747
|
//FIXME tree reference
|
748
|
tree.setReference(citation);
|
749
|
service.save(tree);
|
750
|
}
|
751
|
state.addRelatedObject(DbImportTaxIncludedInMapper.TAXONOMIC_TREE_NAMESPACE, treeKey, tree);
|
752
|
}
|
753
|
|
754
|
TaxonNode childNode;
|
755
|
if (parent != null){
|
756
|
childNode = tree.addParentChild(parent, child, citation, microCitation);
|
757
|
}else{
|
758
|
childNode = tree.addChildTaxon(child, citation, microCitation, null);
|
759
|
}
|
760
|
return (childNode != null);
|
761
|
}
|
762
|
|
763
|
|
764
|
/**
|
765
|
* Reasons if a higher taxon should exist. If it should exist it returns it as a new taxon.
|
766
|
* Returns null otherwise.
|
767
|
* @return
|
768
|
* @throws SQLException
|
769
|
*/
|
770
|
private Taxon constructNextHigherTaxon(CentralAfricaFernsImportState state, ResultSet rs, Taxon childTaxon, Epithets epithets) throws SQLException {
|
771
|
|
772
|
Taxon result = null;
|
773
|
BotanicalName childName = CdmBase.deproxy(childTaxon.getName(), BotanicalName.class);
|
774
|
Rank childRank = childName.getRank();
|
775
|
BotanicalName higherName;
|
776
|
higherName = handleInfraSpecific(childRank, epithets);
|
777
|
if (higherName.getRank() == null){
|
778
|
handleSpecies(childRank, higherName, epithets);
|
779
|
}
|
780
|
if (higherName.getRank() == null){
|
781
|
handleInfraGeneric(childRank, higherName, epithets);
|
782
|
}
|
783
|
if (higherName.getRank() == null){
|
784
|
handleUninomial(childRank, higherName, epithets);
|
785
|
}
|
786
|
|
787
|
if (higherName.getRank() != null){
|
788
|
result = Taxon.NewInstance(higherName, childTaxon.getSec());
|
789
|
//TODO correct??
|
790
|
setAuthor(higherName, rs, state.getTaxonNumber(), true);
|
791
|
// UUID uuid = higherName.getUuid();
|
792
|
// String name = higherName.getNameCache();
|
793
|
// taxonMap.put(name, uuid);
|
794
|
// state.addRelatedObject(HIGHER_TAXON_NAMESPACE, higherName.getNameCache(), result);
|
795
|
}
|
796
|
return result;
|
797
|
}
|
798
|
|
799
|
private BotanicalName handleInfraSpecific(Rank lowerTaxonRank, Epithets epithets) {
|
800
|
|
801
|
BotanicalName taxonName = BotanicalName.NewInstance(null);
|
802
|
Rank newRank = null;
|
803
|
|
804
|
if (StringUtils.isNotBlank(epithets.subFormaName) && lowerTaxonRank.isLower(Rank.SUBFORM())){
|
805
|
taxonName.setInfraSpecificEpithet(epithets.subFormaName);
|
806
|
newRank = Rank.SUBFORM();
|
807
|
}else if (StringUtils.isNotBlank(epithets.formaName) && lowerTaxonRank.isLower(Rank.FORM())){
|
808
|
taxonName.setInfraSpecificEpithet(epithets.formaName);
|
809
|
newRank = Rank.FORM();
|
810
|
}else if (StringUtils.isNotBlank(epithets.subVariety) && lowerTaxonRank.isLower(Rank.SUBVARIETY())){
|
811
|
taxonName.setInfraSpecificEpithet(epithets.subVariety);
|
812
|
newRank = Rank.SUBVARIETY();
|
813
|
}else if (StringUtils.isNotBlank(epithets.varietyName) && lowerTaxonRank.isLower(Rank.VARIETY())){
|
814
|
taxonName.setInfraSpecificEpithet(epithets.varietyName);
|
815
|
newRank = Rank.VARIETY();
|
816
|
}else if (StringUtils.isNotBlank(epithets.subspeciesName) && lowerTaxonRank.isLower(Rank.SUBSPECIES())){
|
817
|
taxonName.setInfraSpecificEpithet(epithets.subspeciesName);
|
818
|
newRank = Rank.SUBSPECIES();
|
819
|
}
|
820
|
|
821
|
if (newRank != null){
|
822
|
taxonName.setSpecificEpithet(epithets.specificEpithet);
|
823
|
taxonName.setGenusOrUninomial(epithets.genusName);
|
824
|
taxonName.setRank(newRank);
|
825
|
}
|
826
|
|
827
|
return taxonName;
|
828
|
}
|
829
|
|
830
|
private BotanicalName handleSpecies(Rank lowerTaxonRank, BotanicalName taxonName, Epithets epithets) {
|
831
|
Rank newRank = null;
|
832
|
|
833
|
if (StringUtils.isNotBlank(epithets.specificEpithet) && lowerTaxonRank.isLower(Rank.SPECIES())){
|
834
|
taxonName.setSpecificEpithet(epithets.specificEpithet);
|
835
|
newRank = Rank.SPECIES();
|
836
|
}
|
837
|
if (newRank != null){
|
838
|
taxonName.setGenusOrUninomial(epithets.genusName);
|
839
|
taxonName.setRank(newRank);
|
840
|
}
|
841
|
return taxonName;
|
842
|
}
|
843
|
|
844
|
private BotanicalName handleInfraGeneric(Rank lowerTaxonRank, BotanicalName taxonName, Epithets epithets) {
|
845
|
Rank newRank = null;
|
846
|
|
847
|
if (StringUtils.isNotBlank(epithets.seriesName) && lowerTaxonRank.isLower(Rank.SERIES())){
|
848
|
taxonName.setInfraGenericEpithet(epithets.seriesName);
|
849
|
newRank = Rank.SERIES();
|
850
|
}else if (StringUtils.isNotBlank(epithets.subsectionName) && lowerTaxonRank.isLower(Rank.SUBSECTION_BOTANY())){
|
851
|
taxonName.setInfraGenericEpithet(epithets.subsectionName);
|
852
|
newRank = Rank.SUBSECTION_BOTANY();
|
853
|
}else if (StringUtils.isNotBlank(epithets.sectionName) && lowerTaxonRank.isLower(Rank.SECTION_BOTANY())){
|
854
|
taxonName.setInfraGenericEpithet(epithets.sectionName);
|
855
|
newRank = Rank.SECTION_BOTANY();
|
856
|
}else if (StringUtils.isNotBlank(epithets.subGenusName) && lowerTaxonRank.isLower(Rank.SUBGENUS())){
|
857
|
taxonName.setInfraGenericEpithet(epithets.subGenusName);
|
858
|
newRank = Rank.SUBGENUS();
|
859
|
}
|
860
|
if (newRank != null){
|
861
|
taxonName.setGenusOrUninomial(epithets.genusName);
|
862
|
taxonName.setRank(newRank);
|
863
|
}
|
864
|
return taxonName;
|
865
|
}
|
866
|
|
867
|
|
868
|
|
869
|
private BotanicalName handleUninomial(Rank lowerTaxonRank, BotanicalName taxonName, Epithets epithets) {
|
870
|
|
871
|
Rank newRank = null;
|
872
|
if (StringUtils.isNotBlank(epithets.genusName) && lowerTaxonRank.isLower(Rank.GENUS())){
|
873
|
taxonName.setGenusOrUninomial(epithets.genusName);
|
874
|
newRank = Rank.GENUS();
|
875
|
}else if (StringUtils.isNotBlank(epithets.subTribusName) && lowerTaxonRank.isLower(Rank.SUBTRIBE())){
|
876
|
taxonName.setGenusOrUninomial(epithets.subTribusName);
|
877
|
newRank = Rank.SUBTRIBE();
|
878
|
}else if (StringUtils.isNotBlank(epithets.tribusName) && lowerTaxonRank.isLower(Rank.TRIBE())){
|
879
|
taxonName.setGenusOrUninomial(epithets.tribusName);
|
880
|
newRank = Rank.TRIBE();
|
881
|
}else if (StringUtils.isNotBlank(epithets.subFamilyName) && lowerTaxonRank.isLower(Rank.SUBFAMILY())){
|
882
|
taxonName.setGenusOrUninomial(epithets.subFamilyName);
|
883
|
newRank = Rank.SUBFAMILY();
|
884
|
}else if (StringUtils.isNotBlank(epithets.familyName) && lowerTaxonRank.isLower(Rank.FAMILY())){
|
885
|
taxonName.setGenusOrUninomial(epithets.familyName);
|
886
|
newRank = Rank.FAMILY();
|
887
|
}else if (StringUtils.isNotBlank(epithets.subOrderName) && lowerTaxonRank.isLower(Rank.SUBORDER())){
|
888
|
taxonName.setGenusOrUninomial(epithets.subOrderName);
|
889
|
newRank = Rank.SUBORDER();
|
890
|
}else if (StringUtils.isNotBlank(epithets.orderName) && lowerTaxonRank.isLower(Rank.ORDER())){
|
891
|
taxonName.setGenusOrUninomial(epithets.orderName);
|
892
|
newRank = Rank.ORDER();
|
893
|
}
|
894
|
taxonName.setRank(newRank);
|
895
|
return taxonName;
|
896
|
}
|
897
|
|
898
|
|
899
|
/**
|
900
|
* for internal use only, used by MethodMapper
|
901
|
*/
|
902
|
private TaxonBase mapCommonName(ResultSet rs, CentralAfricaFernsImportState state) throws SQLException{
|
903
|
String taxonNumber = state.getTaxonNumber();
|
904
|
String commonNames = rs.getString("Common names");
|
905
|
TaxonBase<?> taxonBase = state.getRelatedObject(state.CURRENT_OBJECT_NAMESPACE, state.CURRENT_OBJECT_ID, TaxonBase.class);
|
906
|
if (StringUtils.isNotBlank(commonNames)){
|
907
|
Taxon taxon = getAcceptedTaxon(taxonBase);
|
908
|
if ( taxon != null ){
|
909
|
TaxonDescription description = getTaxonDescription(taxon, false, true);
|
910
|
String[] split = commonNames.split(",");
|
911
|
for (String commonNameString: split){
|
912
|
CommonTaxonName commonName = CommonTaxonName.NewInstance(commonNameString.trim(), Language.ENGLISH());
|
913
|
description.addElement(commonName);
|
914
|
}
|
915
|
}else{
|
916
|
logger.warn(taxonNumber + " - Accepted taxon for synonym can't be defined for common name. Synonym " + taxonBase.getName().getTitleCache());
|
917
|
}
|
918
|
}
|
919
|
return taxonBase;
|
920
|
}
|
921
|
|
922
|
|
923
|
/**
|
924
|
* for internal use only, used by MethodMapper
|
925
|
*/
|
926
|
private TaxonBase mapDistribution(ResultSet rs, CentralAfricaFernsImportState state) throws SQLException{
|
927
|
try {
|
928
|
String taxonNumber = state.getTaxonNumber();
|
929
|
// logger.info(taxonNumber);
|
930
|
TaxonBase<?> taxonBase = state.getRelatedObject(state.CURRENT_OBJECT_NAMESPACE, state.CURRENT_OBJECT_ID, TaxonBase.class);
|
931
|
String countriesString = rs.getString("Distribution - Country");
|
932
|
String province = rs.getString("Distribution - Province");
|
933
|
String distributionDetailed = rs.getString("Distribution - detailed");
|
934
|
if (taxonBase != null){
|
935
|
TaxonNameBase nameUsedInSource = taxonBase.getName();
|
936
|
Taxon taxon = getAcceptedTaxon(taxonBase);
|
937
|
if (taxon != null){
|
938
|
|
939
|
if (StringUtils.isNotBlank(countriesString) ){
|
940
|
makeCountries(state, taxonNumber, taxon, nameUsedInSource, countriesString, province, distributionDetailed);
|
941
|
}
|
942
|
makeProvince(taxon, province);
|
943
|
makeDistributionDetailed(taxon, distributionDetailed);
|
944
|
}else{
|
945
|
logger.warn(taxonNumber + " - Accepted taxon for synonym can't be defined for distribution. Synonym " + taxonBase.getName().getTitleCache());
|
946
|
}
|
947
|
}else{
|
948
|
logger.warn(" - " + taxonNumber + ": TaxonBase was null");
|
949
|
}
|
950
|
return taxonBase;
|
951
|
} catch (Exception e) {
|
952
|
e.printStackTrace();
|
953
|
return null;
|
954
|
}
|
955
|
}
|
956
|
|
957
|
|
958
|
/**
|
959
|
* for internal use only, used by MethodMapper
|
960
|
* @param commonNames
|
961
|
*/
|
962
|
private TaxonBase mapEcology(ResultSet rs, CentralAfricaFernsImportState state) throws SQLException{
|
963
|
String taxonNumber = state.getTaxonNumber();
|
964
|
String ecologyString = rs.getString("Ecology");
|
965
|
TaxonBase<?> taxonBase = state.getRelatedObject(state.CURRENT_OBJECT_NAMESPACE, state.CURRENT_OBJECT_ID, TaxonBase.class);
|
966
|
if (StringUtils.isNotBlank(ecologyString)){
|
967
|
Taxon taxon = getAcceptedTaxon(taxonBase);
|
968
|
|
969
|
if (taxon != null){
|
970
|
TaxonDescription description = getTaxonDescription(taxon, false, true);
|
971
|
TextData ecology = TextData.NewInstance(Feature.ECOLOGY());
|
972
|
ecology.putText(Language.ENGLISH(), ecologyString.trim());
|
973
|
description.addElement(ecology);
|
974
|
}else{
|
975
|
logger.warn(taxonNumber + " - Accepted taxon for synonym can't be defined for ecology. Synonym " + taxonBase.getName().getTitleCache());
|
976
|
}
|
977
|
}
|
978
|
return taxonBase;
|
979
|
}
|
980
|
|
981
|
|
982
|
|
983
|
|
984
|
private void makeDistributionDetailed(Taxon taxon, String distributionDetailed) {
|
985
|
if (StringUtils.isNotBlank(distributionDetailed)){
|
986
|
TaxonDescription description = getTaxonDescription(taxon, false, true);
|
987
|
TextData distribution = TextData.NewInstance(Feature.DISTRIBUTION());
|
988
|
description.addElement(distribution);
|
989
|
distribution.putText(Language.ENGLISH(), distributionDetailed);
|
990
|
}
|
991
|
}
|
992
|
|
993
|
|
994
|
private void makeProvince(Taxon taxon, String province) {
|
995
|
if (StringUtils.isNotBlank(province)){
|
996
|
TaxonDescription description = getTaxonDescription(taxon, false, true);
|
997
|
TextData distribution = TextData.NewInstance(Feature.DISTRIBUTION());
|
998
|
description.addElement(distribution);
|
999
|
distribution.putText(Language.ENGLISH(), province);
|
1000
|
}
|
1001
|
}
|
1002
|
|
1003
|
|
1004
|
/**
|
1005
|
* @param state
|
1006
|
* @param taxonNumber
|
1007
|
* @param taxonBase
|
1008
|
* @param countriesString
|
1009
|
*/
|
1010
|
private void makeCountries(CentralAfricaFernsImportState state, String taxonNumber, Taxon taxon, TaxonNameBase nameUsedInSource, String countriesString, String province, String distributionDetailed) {
|
1011
|
countriesString = countriesString.replaceAll("\\*", "");
|
1012
|
countriesString = countriesString.replace(" ", " ");
|
1013
|
countriesString = countriesString.replace(", endemic", " - endemic");
|
1014
|
countriesString = countriesString.replace("(endemic)", " - endemic");
|
1015
|
countriesString = countriesString.replace("(introduced)", " - introduced");
|
1016
|
countriesString = countriesString.replace("(naturalised)", " - naturalised");
|
1017
|
countriesString = countriesString.replace("Madagascar-", "Madagascar -");
|
1018
|
countriesString = countriesString.replace("Mah?", "Mahe");
|
1019
|
|
1020
|
String[] split = countriesString.split("[,;]");
|
1021
|
String remainingString = null;
|
1022
|
for (String countryString : split){
|
1023
|
countryString = CdmUtils.concat(", ", remainingString , countryString);
|
1024
|
if (countryString.matches(".*\\(.*") && ! countryString.matches(".*\\).*")){
|
1025
|
remainingString = countryString;
|
1026
|
continue;
|
1027
|
}
|
1028
|
remainingString = null;
|
1029
|
try {
|
1030
|
makeSingleCountry(state, taxonNumber, taxon, nameUsedInSource, countryString.trim());
|
1031
|
} catch (UndefinedTransformerMethodException e) {
|
1032
|
e.printStackTrace();
|
1033
|
}
|
1034
|
}
|
1035
|
}
|
1036
|
|
1037
|
|
1038
|
private void makeSingleCountry(CentralAfricaFernsImportState state, String taxonNumber, Taxon taxon, TaxonNameBase nameUsedInSource, String country) throws UndefinedTransformerMethodException {
|
1039
|
boolean areaDoubtful = false;
|
1040
|
Distribution distribution = Distribution.NewInstance(null, PresenceTerm.PRESENT());
|
1041
|
Reference sourceReference = this.sourceReference;
|
1042
|
distribution.addSource(taxonNumber, "Distribution_Country", sourceReference, null, nameUsedInSource, null);
|
1043
|
NamedArea area = null;
|
1044
|
//empty
|
1045
|
if (StringUtils.isBlank(country)){
|
1046
|
return;
|
1047
|
}
|
1048
|
country = country.trim();
|
1049
|
//doubtful
|
1050
|
if (country.startsWith("?")){
|
1051
|
areaDoubtful = true;
|
1052
|
country = country.substring(1).trim();
|
1053
|
}
|
1054
|
//status
|
1055
|
country = makeCountryStatus(state, country, distribution);
|
1056
|
|
1057
|
//brackets
|
1058
|
country = makeCountryBrackets(state, taxonNumber, taxon, nameUsedInSource, country);
|
1059
|
String countryWithoutIslands = null;
|
1060
|
String countryWithoutDot = null;
|
1061
|
if (country.endsWith(" Isl.") || country.endsWith(" isl.") ){
|
1062
|
countryWithoutIslands = country.substring(0, country.length()-5);
|
1063
|
}
|
1064
|
if (country.endsWith(".")){
|
1065
|
countryWithoutDot = country.substring(0, country.length()-1);
|
1066
|
}
|
1067
|
if (country.endsWith("*")){
|
1068
|
country = country.substring(0, country.length()-1);
|
1069
|
}
|
1070
|
if (country.endsWith("Islands")){
|
1071
|
country = country.replace("Islands", "Is.");
|
1072
|
}
|
1073
|
|
1074
|
|
1075
|
//areas
|
1076
|
if (TdwgArea.isTdwgAreaLabel(country)){
|
1077
|
//tdwg
|
1078
|
area = TdwgArea.getAreaByTdwgLabel(country);
|
1079
|
}else if (TdwgArea.isTdwgAreaLabel(countryWithoutIslands)){
|
1080
|
//tdwg
|
1081
|
area = TdwgArea.getAreaByTdwgLabel(countryWithoutIslands);
|
1082
|
}else if (TdwgArea.isTdwgAreaLabel(countryWithoutDot)){
|
1083
|
//tdwg
|
1084
|
area = TdwgArea.getAreaByTdwgLabel(countryWithoutDot);
|
1085
|
}else if ( (area = state.getTransformer().getNamedAreaByKey(country)) != null) {
|
1086
|
//area already set
|
1087
|
}else if (WaterbodyOrCountry.isWaterbodyOrCountryLabel(country)){
|
1088
|
//iso
|
1089
|
area = WaterbodyOrCountry.getWaterbodyOrCountryByLabel(country);
|
1090
|
}else{
|
1091
|
//others
|
1092
|
NamedAreaLevel level = null;
|
1093
|
NamedAreaType areaType = null;
|
1094
|
|
1095
|
UUID uuid = state.getTransformer().getNamedAreaUuid(country);
|
1096
|
if (uuid == null){
|
1097
|
logger.error(taxonNumber + " - Unknown country: " + country);
|
1098
|
}
|
1099
|
area = getNamedArea(state, uuid, country, country, country, areaType, level);
|
1100
|
}
|
1101
|
|
1102
|
distribution.setArea(area);
|
1103
|
if (areaDoubtful == true){
|
1104
|
if (distribution.getStatus().equals(PresenceTerm.PRESENT())){
|
1105
|
distribution.setStatus(PresenceTerm.PRESENT_DOUBTFULLY());
|
1106
|
}
|
1107
|
}
|
1108
|
TaxonDescription description = getTaxonDescription(taxon, false, true);
|
1109
|
description.addElement(distribution);
|
1110
|
}
|
1111
|
|
1112
|
|
1113
|
|
1114
|
/**
|
1115
|
* @param state
|
1116
|
* @return
|
1117
|
*/
|
1118
|
Reference sourceReference = null;
|
1119
|
private Reference getFernsSourceReference(CentralAfricaFernsImportState state) {
|
1120
|
// if (sourceReference == null || true){
|
1121
|
Reference tmpReference = state.getConfig().getSourceReference();
|
1122
|
sourceReference = getReferenceService().find(tmpReference.getUuid());
|
1123
|
// }
|
1124
|
return sourceReference;
|
1125
|
}
|
1126
|
|
1127
|
|
1128
|
private String makeCountryBrackets(CentralAfricaFernsImportState state, String taxonNumber, Taxon taxon, TaxonNameBase nameUsedInSource, String country) {
|
1129
|
String[] split = (country + " ").split("\\(.*\\)");
|
1130
|
if (split.length == 2){
|
1131
|
String bracket = country.substring(split[0].length()+1, country.indexOf(")"));
|
1132
|
country = split[0].trim();
|
1133
|
makeCountries(state, taxonNumber, taxon, nameUsedInSource, bracket, null, null);
|
1134
|
}else if (split.length ==1){
|
1135
|
//do nothing
|
1136
|
}else{
|
1137
|
logger.warn("Illegal length");
|
1138
|
}
|
1139
|
return country;
|
1140
|
}
|
1141
|
|
1142
|
private String makeCountryStatus(CentralAfricaFernsImportState state, String country, Distribution distribution) throws UndefinedTransformerMethodException {
|
1143
|
PresenceTerm status = null;
|
1144
|
String[] split = country.split(" - ");
|
1145
|
|
1146
|
if (split.length == 2){
|
1147
|
country = split[0].trim();
|
1148
|
String statusString = split[1];
|
1149
|
statusString = statusString.replace(".", "");
|
1150
|
status = state.getTransformer().getPresenceTermByKey(statusString);
|
1151
|
if (status == null){
|
1152
|
logger.warn("No status found: "+ statusString);
|
1153
|
}
|
1154
|
// UUID uuid = null;
|
1155
|
// status = getPresenceTerm(state, uuid, statusString, statusString, null);
|
1156
|
}else if (split.length == 1){
|
1157
|
//nothing to do
|
1158
|
}else{
|
1159
|
logger.warn("Invalid length: " + split.length);
|
1160
|
}
|
1161
|
if (status != null){
|
1162
|
distribution.setStatus(status);
|
1163
|
}
|
1164
|
return country;
|
1165
|
}
|
1166
|
|
1167
|
|
1168
|
|
1169
|
|
1170
|
/* (non-Javadoc)
|
1171
|
* @see eu.etaxonomy.cdm.io.common.CdmIoBase#doCheck(eu.etaxonomy.cdm.io.common.IoStateBase)
|
1172
|
*/
|
1173
|
@Override
|
1174
|
protected boolean doCheck(CentralAfricaFernsImportState state){
|
1175
|
IOValidator<CentralAfricaFernsImportState> validator = new CentralAfricaFernsTaxonImportValidator();
|
1176
|
return validator.validate(state);
|
1177
|
}
|
1178
|
|
1179
|
/* (non-Javadoc)
|
1180
|
* @see eu.etaxonomy.cdm.io.common.CdmIoBase#isIgnore(eu.etaxonomy.cdm.io.common.IoStateBase)
|
1181
|
*/
|
1182
|
@Override
|
1183
|
protected boolean isIgnore(CentralAfricaFernsImportState state){
|
1184
|
return ! state.getConfig().isDoRelTaxa();
|
1185
|
}
|
1186
|
|
1187
|
|
1188
|
|
1189
|
//************************ OLD **********************************************************
|
1190
|
|
1191
|
/**
|
1192
|
* Adds the higherTaxon authors to the existingHigherTaxon authors if the higherTaxon has authors and
|
1193
|
* the existingHigherTaxon has no authors.
|
1194
|
* Returns false if both taxa have authors and the authors differ from each other.
|
1195
|
* @param higherTaxon
|
1196
|
* @param existingHigherTaxon
|
1197
|
*/
|
1198
|
private boolean mergeAuthors_old(Taxon higherTaxon, Taxon existingHigherTaxon) {
|
1199
|
NonViralName existingName = CdmBase.deproxy(higherTaxon.getName(), NonViralName.class);
|
1200
|
NonViralName newName = CdmBase.deproxy(existingHigherTaxon.getName(), NonViralName.class);
|
1201
|
if (existingName == newName){
|
1202
|
return true;
|
1203
|
}
|
1204
|
if (! newName.hasAuthors()){
|
1205
|
return true;
|
1206
|
}
|
1207
|
if (! existingName.hasAuthors()){
|
1208
|
existingName.setCombinationAuthorTeam(newName.getCombinationAuthorTeam());
|
1209
|
existingName.setExCombinationAuthorTeam(newName.getExCombinationAuthorTeam());
|
1210
|
existingName.setBasionymAuthorTeam(newName.getBasionymAuthorTeam());
|
1211
|
existingName.setExBasionymAuthorTeam(newName.getExBasionymAuthorTeam());
|
1212
|
return true;
|
1213
|
}
|
1214
|
boolean authorsAreSame = true;
|
1215
|
authorsAreSame &= getNomTitleNz(existingName.getCombinationAuthorTeam()).equals(getNomTitleNz(newName.getCombinationAuthorTeam()));
|
1216
|
authorsAreSame &= getNomTitleNz(existingName.getExCombinationAuthorTeam()).equals(getNomTitleNz(newName.getExCombinationAuthorTeam()));
|
1217
|
authorsAreSame &= getNomTitleNz(existingName.getBasionymAuthorTeam()).equals(getNomTitleNz(newName.getBasionymAuthorTeam()));
|
1218
|
authorsAreSame &= getNomTitleNz(existingName.getExBasionymAuthorTeam()).equals(getNomTitleNz(newName.getExBasionymAuthorTeam()));
|
1219
|
return authorsAreSame;
|
1220
|
|
1221
|
|
1222
|
}
|
1223
|
|
1224
|
/**
|
1225
|
* Returns the nomenclatural title of the author. Returns empty string if author is <code>null</code> or
|
1226
|
* titleCache is <code>null</code>.
|
1227
|
* @param author
|
1228
|
* @return
|
1229
|
*/
|
1230
|
private String getNomTitleNz(INomenclaturalAuthor author) {
|
1231
|
if (author != null){
|
1232
|
return CdmUtils.Nz(author.getNomenclaturalTitle());
|
1233
|
}else{
|
1234
|
return "";
|
1235
|
}
|
1236
|
}
|
1237
|
|
1238
|
private Taxon getExistingHigherTaxon_old(Taxon child, Taxon higherTaxon) {
|
1239
|
int countNodes = child.getTaxonNodes().size();
|
1240
|
if (countNodes < 1){
|
1241
|
return null;
|
1242
|
}else if (countNodes > 1){
|
1243
|
throw new IllegalStateException("Multiple nodes exist for child taxon. This is an invalid state.");
|
1244
|
}else{
|
1245
|
TaxonNode childNode = child.getTaxonNodes().iterator().next();
|
1246
|
TaxonNode parentNode = childNode.getParent();
|
1247
|
if (parentNode != null){
|
1248
|
String existingParentTitle = parentNode.getTaxon().getName().getTitleCache();
|
1249
|
String newParentTitle = higherTaxon.getName().getTitleCache();
|
1250
|
if (existingParentTitle.equals(newParentTitle)){
|
1251
|
return parentNode.getTaxon();
|
1252
|
}
|
1253
|
}
|
1254
|
return null;
|
1255
|
}
|
1256
|
}
|
1257
|
|
1258
|
|
1259
|
|
1260
|
/**
|
1261
|
* Tests if this the child taxon already is a child of the higher taxon.
|
1262
|
* @param child
|
1263
|
* @param higherTaxon
|
1264
|
* @return
|
1265
|
*/
|
1266
|
private boolean includedRelationshipExists_Old(Taxon child, Taxon higherTaxon) {
|
1267
|
int countNodes = higherTaxon.getTaxonNodes().size();
|
1268
|
if (countNodes < 1){
|
1269
|
return false;
|
1270
|
}else if (countNodes > 1){
|
1271
|
throw new IllegalStateException("Multiple nodes exist for higher taxon. This is an invalid state.");
|
1272
|
}else{
|
1273
|
TaxonNode higherNode = higherTaxon.getTaxonNodes().iterator().next();
|
1274
|
return childExists_old(child, higherNode);
|
1275
|
}
|
1276
|
}
|
1277
|
|
1278
|
|
1279
|
|
1280
|
private boolean childExists_old(Taxon child, TaxonNode higherNode) {
|
1281
|
for (TaxonNode childNode : higherNode.getChildNodes()){
|
1282
|
String existingChildTitle = childNode.getTaxon().getName().getTitleCache();
|
1283
|
String newChildTitle = child.getName().getTitleCache();
|
1284
|
if (existingChildTitle.equals(newChildTitle)){
|
1285
|
return true;
|
1286
|
}
|
1287
|
}
|
1288
|
return false;
|
1289
|
}
|
1290
|
|
1291
|
|
1292
|
}
|