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.excel.taxa;
|
11
|
|
12
|
import java.net.MalformedURLException;
|
13
|
import java.net.URI;
|
14
|
import java.net.URISyntaxException;
|
15
|
import java.util.Arrays;
|
16
|
import java.util.HashMap;
|
17
|
import java.util.HashSet;
|
18
|
import java.util.List;
|
19
|
import java.util.Map;
|
20
|
import java.util.Set;
|
21
|
import java.util.UUID;
|
22
|
|
23
|
import org.apache.commons.lang.StringUtils;
|
24
|
import org.apache.log4j.Logger;
|
25
|
import org.springframework.stereotype.Component;
|
26
|
|
27
|
import eu.etaxonomy.cdm.common.CdmUtils;
|
28
|
import eu.etaxonomy.cdm.io.excel.common.ExcelRowBase.SourceDataHolder;
|
29
|
import eu.etaxonomy.cdm.model.agent.Team;
|
30
|
import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
|
31
|
import eu.etaxonomy.cdm.model.common.CdmBase;
|
32
|
import eu.etaxonomy.cdm.model.common.DescriptionElementSource;
|
33
|
import eu.etaxonomy.cdm.model.common.Extension;
|
34
|
import eu.etaxonomy.cdm.model.common.ExtensionType;
|
35
|
import eu.etaxonomy.cdm.model.common.Language;
|
36
|
import eu.etaxonomy.cdm.model.common.TimePeriod;
|
37
|
import eu.etaxonomy.cdm.model.description.CommonTaxonName;
|
38
|
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
|
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.TaxonNameDescription;
|
44
|
import eu.etaxonomy.cdm.model.description.TextData;
|
45
|
import eu.etaxonomy.cdm.model.location.NamedArea;
|
46
|
import eu.etaxonomy.cdm.model.location.TdwgArea;
|
47
|
import eu.etaxonomy.cdm.model.media.Media;
|
48
|
import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
|
49
|
import eu.etaxonomy.cdm.model.name.NonViralName;
|
50
|
import eu.etaxonomy.cdm.model.name.Rank;
|
51
|
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
|
52
|
import eu.etaxonomy.cdm.model.reference.Reference;
|
53
|
import eu.etaxonomy.cdm.model.reference.ReferenceFactory;
|
54
|
import eu.etaxonomy.cdm.model.taxon.Classification;
|
55
|
import eu.etaxonomy.cdm.model.taxon.Synonym;
|
56
|
import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType;
|
57
|
import eu.etaxonomy.cdm.model.taxon.Taxon;
|
58
|
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
|
59
|
import eu.etaxonomy.cdm.strategy.exceptions.StringNotParsableException;
|
60
|
import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
|
61
|
import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImpl;
|
62
|
|
63
|
/**
|
64
|
* @author a.babadshanjan
|
65
|
* @created 08.01.2009
|
66
|
*/
|
67
|
|
68
|
@Component
|
69
|
public class NormalExplicitImport extends TaxonExcelImporterBase {
|
70
|
private static final Logger logger = Logger.getLogger(NormalExplicitImport.class);
|
71
|
|
72
|
public static Set<String> validMarkers = new HashSet<String>(Arrays.asList(new String[]{"", "valid", "accepted", "a", "v", "t"}));
|
73
|
public static Set<String> synonymMarkers = new HashSet<String>(Arrays.asList(new String[]{"", "invalid", "synonym", "s", "i"}));
|
74
|
public static final UUID uuidRefExtension = UUID.fromString("a46533df-7a78-448f-9b80-36d087fbdf2a");
|
75
|
|
76
|
/* (non-Javadoc)
|
77
|
* @see eu.etaxonomy.cdm.io.excel.common.ExcelTaxonOrSpecimenImportBase#analyzeSingleValue(eu.etaxonomy.cdm.io.excel.common.ExcelTaxonOrSpecimenImportBase.KeyValue, eu.etaxonomy.cdm.io.excel.common.ExcelImportState)
|
78
|
*/
|
79
|
@Override
|
80
|
protected void analyzeSingleValue(KeyValue keyValue, TaxonExcelImportState state) {
|
81
|
|
82
|
NormalExplicitRow normalExplicitRow = state.getCurrentRow();
|
83
|
String key = keyValue.key;
|
84
|
String value = keyValue.value;
|
85
|
Integer index = keyValue.index;
|
86
|
if (key.equalsIgnoreCase(ID_COLUMN)) {
|
87
|
int ivalue = floatString2IntValue(value);
|
88
|
normalExplicitRow.setId(ivalue);
|
89
|
|
90
|
} else if(key.equalsIgnoreCase(PARENT_ID_COLUMN)) {
|
91
|
int ivalue = floatString2IntValue(value);
|
92
|
normalExplicitRow.setParentId(ivalue);
|
93
|
|
94
|
} else if(key.equalsIgnoreCase(RANK_COLUMN)) {
|
95
|
normalExplicitRow.setRank(value);
|
96
|
|
97
|
} else if(key.equalsIgnoreCase(SCIENTIFIC_NAME_COLUMN)) {
|
98
|
normalExplicitRow.setScientificName(value);
|
99
|
|
100
|
} else if(key.equalsIgnoreCase(AUTHOR_COLUMN)) {
|
101
|
normalExplicitRow.setAuthor(value);
|
102
|
|
103
|
} else if(key.equalsIgnoreCase(NAME_STATUS_COLUMN)) {
|
104
|
normalExplicitRow.setNameStatus(value);
|
105
|
|
106
|
} else if(key.equalsIgnoreCase(VERNACULAR_NAME_COLUMN)) {
|
107
|
normalExplicitRow.setCommonName(value);
|
108
|
|
109
|
} else if(key.equalsIgnoreCase(LANGUAGE_COLUMN)) {
|
110
|
normalExplicitRow.setLanguage(value);
|
111
|
|
112
|
} else if(key.equalsIgnoreCase(TDWG_COLUMN)) {
|
113
|
//TODO replace still necessary?
|
114
|
value = value.replace(".0", "");
|
115
|
normalExplicitRow.putDistribution(index, value);
|
116
|
|
117
|
} else if(key.equalsIgnoreCase(PROTOLOGUE_COLUMN)) {
|
118
|
normalExplicitRow.putProtologue(index, value);
|
119
|
|
120
|
} else if(key.equalsIgnoreCase(IMAGE_COLUMN)) {
|
121
|
normalExplicitRow.putImage(index, value);
|
122
|
|
123
|
} else {
|
124
|
if (analyzeFeatures(state, keyValue)){
|
125
|
//ok
|
126
|
}else{
|
127
|
String message = "Unexpected column header " + key;
|
128
|
fireWarningEvent(message, state, 10);
|
129
|
state.setUnsuccessfull();
|
130
|
logger.error(message);
|
131
|
}
|
132
|
}
|
133
|
return;
|
134
|
}
|
135
|
|
136
|
|
137
|
/**
|
138
|
* Create base taxa and add all information attached to it's name.
|
139
|
*/
|
140
|
@Override
|
141
|
protected void firstPass(TaxonExcelImportState state) {
|
142
|
|
143
|
// if (1==1){
|
144
|
// return;
|
145
|
// }
|
146
|
// System.out.println("FP:" + state.getCurrentLine());
|
147
|
Rank rank = null;
|
148
|
NormalExplicitRow taxonDataHolder = state.getCurrentRow();
|
149
|
|
150
|
String rankStr = taxonDataHolder.getRank();
|
151
|
String taxonNameStr = taxonDataHolder.getScientificName();
|
152
|
String authorStr = taxonDataHolder.getAuthor();
|
153
|
String nameStatus = taxonDataHolder.getNameStatus();
|
154
|
Integer id = taxonDataHolder.getId();
|
155
|
UUID cdmUuid = taxonDataHolder.getCdmUuid();
|
156
|
|
157
|
TaxonBase taxonBase = null;
|
158
|
if (cdmUuid != null){
|
159
|
taxonBase = getTaxonService().find(cdmUuid);
|
160
|
}else{
|
161
|
if (CdmUtils.isNotEmpty(taxonNameStr)) {
|
162
|
|
163
|
// Rank
|
164
|
try {
|
165
|
rank = Rank.getRankByNameOrAbbreviation(rankStr);
|
166
|
} catch (UnknownCdmTypeException ex) {
|
167
|
try {
|
168
|
rank = Rank.getRankByEnglishName(rankStr, state.getConfig().getNomenclaturalCode(), false);
|
169
|
} catch (UnknownCdmTypeException e) {
|
170
|
state.setUnsuccessfull();
|
171
|
logger.error(rankStr + " is not a valid rank.");
|
172
|
}
|
173
|
}
|
174
|
|
175
|
//taxon
|
176
|
taxonBase = createTaxon(state, rank, taxonNameStr, authorStr, nameStatus);
|
177
|
}else{
|
178
|
return;
|
179
|
}
|
180
|
}
|
181
|
if (taxonBase == null){
|
182
|
String message = "Taxon could not be created. Record will not be handled";
|
183
|
fireWarningEvent(message, "Record: " + state.getCurrentLine(), 6);
|
184
|
logger.warn(message);
|
185
|
state.setUnsuccessfull();
|
186
|
return;
|
187
|
}
|
188
|
|
189
|
//protologue
|
190
|
for (String protologue : taxonDataHolder.getProtologues()){
|
191
|
TextData textData = TextData.NewInstance(Feature.PROTOLOGUE());
|
192
|
this.getNameDescription(taxonBase.getName()).addElement(textData);
|
193
|
URI uri;
|
194
|
try {
|
195
|
uri = new URI(protologue);
|
196
|
textData.addMedia(Media.NewInstance(uri, null, null, null));
|
197
|
} catch (URISyntaxException e) {
|
198
|
String warning = "URISyntaxException when trying to convert to URI: " + protologue;
|
199
|
logger.error(warning);
|
200
|
state.setUnsuccessfull();
|
201
|
}
|
202
|
}
|
203
|
|
204
|
state.putTaxon(id, taxonBase);
|
205
|
getTaxonService().save(taxonBase);
|
206
|
|
207
|
return;
|
208
|
}
|
209
|
|
210
|
|
211
|
|
212
|
/**
|
213
|
* Stores parent-child, synonym and common name relationships.
|
214
|
* Adds all taxon related descriptive information (this is not done in the first pass
|
215
|
* because the information may also be attached to a synonym).
|
216
|
*/
|
217
|
@Override
|
218
|
protected void secondPass(TaxonExcelImportState state) {
|
219
|
System.out.println(state.getCurrentLine());
|
220
|
try {
|
221
|
NormalExplicitRow taxonDataHolder = state.getCurrentRow();
|
222
|
String taxonNameStr = taxonDataHolder.getScientificName();
|
223
|
String nameStatus = taxonDataHolder.getNameStatus();
|
224
|
String commonNameStr = taxonDataHolder.getCommonName();
|
225
|
Integer parentId = taxonDataHolder.getParentId();
|
226
|
Integer childId = taxonDataHolder.getId();
|
227
|
UUID cdmUuid = taxonDataHolder.getCdmUuid();
|
228
|
Taxon acceptedTaxon;
|
229
|
TaxonNameBase nameUsedInSource;
|
230
|
|
231
|
if (cdmUuid != null){
|
232
|
TaxonBase taxonBase = getTaxonService().find(cdmUuid);
|
233
|
acceptedTaxon = getAcceptedTaxon(taxonBase);
|
234
|
nameUsedInSource = taxonBase.getName();
|
235
|
}else{
|
236
|
//TODO error handling for class cast
|
237
|
Taxon parentTaxon = CdmBase.deproxy(state.getTaxonBase(parentId), Taxon.class);
|
238
|
if (CdmUtils.isNotEmpty(taxonNameStr)) {
|
239
|
TaxonBase taxonBase = state.getTaxonBase(childId);
|
240
|
nameUsedInSource = taxonBase.getName();
|
241
|
nameStatus = CdmUtils.Nz(nameStatus).trim().toLowerCase();
|
242
|
if (validMarkers.contains(nameStatus)){
|
243
|
Taxon taxon = CdmBase.deproxy(taxonBase, Taxon.class);
|
244
|
acceptedTaxon = taxon;
|
245
|
// Add the parent relationship
|
246
|
if (state.getCurrentRow().getParentId() != 0) {
|
247
|
if (parentTaxon != null) {
|
248
|
//Taxon taxon = (Taxon)state.getTaxonBase(childId);
|
249
|
|
250
|
Reference citation = state.getConfig().getSourceReference();
|
251
|
String microCitation = null;
|
252
|
Taxon childTaxon = taxon;
|
253
|
makeParent(state, parentTaxon, childTaxon, citation, microCitation);
|
254
|
getTaxonService().saveOrUpdate(parentTaxon);
|
255
|
} else {
|
256
|
String message = "Taxonomic parent not found for " + taxonNameStr;
|
257
|
logger.warn(message);
|
258
|
fireWarningEvent(message, state, 6);
|
259
|
state.setUnsuccessfull();
|
260
|
}
|
261
|
}else{
|
262
|
//do nothing (parent == 0) no parent exists
|
263
|
}
|
264
|
}else if (synonymMarkers.contains(nameStatus)){
|
265
|
//add synonym relationship
|
266
|
acceptedTaxon = parentTaxon;
|
267
|
try {
|
268
|
Synonym synonym = CdmBase.deproxy(taxonBase,Synonym.class);
|
269
|
if (acceptedTaxon == null){
|
270
|
String message = "Accepted/valid taxon could not be found. Please check referential integrity.";
|
271
|
fireWarningEvent(message, state, 8);
|
272
|
}else{
|
273
|
acceptedTaxon.addSynonym(synonym, SynonymRelationshipType.SYNONYM_OF());
|
274
|
getTaxonService().saveOrUpdate(acceptedTaxon);
|
275
|
}
|
276
|
} catch (Exception e) {
|
277
|
String message = "Unhandled exception (%s) occurred during synonym import/update";
|
278
|
message = String.format(message, e.getMessage());
|
279
|
fireWarningEvent(message, state, 10);
|
280
|
state.setUnsuccessfull();
|
281
|
}
|
282
|
}else{
|
283
|
acceptedTaxon = null;
|
284
|
String message = "Unhandled name status (%s)";
|
285
|
message = String.format(message, nameStatus);
|
286
|
fireWarningEvent(message, state, 8);
|
287
|
}
|
288
|
}else{//taxonNameStr is empty
|
289
|
//vernacular name case
|
290
|
acceptedTaxon = parentTaxon;
|
291
|
nameUsedInSource = null;
|
292
|
}
|
293
|
}
|
294
|
|
295
|
if (acceptedTaxon == null && (CdmUtils.isNotEmpty(commonNameStr) ||taxonDataHolder.getFeatures().size() > 0 )){
|
296
|
String message = "Accepted taxon could not be found. Can't add additional data (common names, descriptive data, ...) to taxon";
|
297
|
fireWarningEvent(message, state, 6);
|
298
|
}else{
|
299
|
//common names
|
300
|
if (CdmUtils.isNotEmpty(commonNameStr)){ // add common name to taxon
|
301
|
handleCommonName(state, taxonNameStr, commonNameStr, acceptedTaxon);
|
302
|
}
|
303
|
|
304
|
|
305
|
//media
|
306
|
for (String imageUrl : taxonDataHolder.getImages()){
|
307
|
TaxonDescription td = acceptedTaxon.getImageGallery(true);
|
308
|
DescriptionElementBase mediaHolder;
|
309
|
if (td.getElements().size() != 0){
|
310
|
mediaHolder = td.getElements().iterator().next();
|
311
|
}else{
|
312
|
mediaHolder = TextData.NewInstance(Feature.IMAGE());
|
313
|
td.addElement(mediaHolder);
|
314
|
}
|
315
|
try {
|
316
|
Media media = getImageMedia(imageUrl, READ_MEDIA_DATA, false);
|
317
|
mediaHolder.addMedia(media);
|
318
|
} catch (MalformedURLException e) {
|
319
|
logger.warn("Can't add media: " + e.getMessage());
|
320
|
state.setUnsuccessfull();
|
321
|
}
|
322
|
}
|
323
|
|
324
|
//tdwg label
|
325
|
for (String tdwg : taxonDataHolder.getDistributions()){
|
326
|
TaxonDescription td = this.getTaxonDescription(acceptedTaxon, state.getConfig().getSourceReference() ,false, true);
|
327
|
NamedArea area = TdwgArea.getAreaByTdwgAbbreviation(tdwg);
|
328
|
if (area == null){
|
329
|
area = TdwgArea.getAreaByTdwgLabel(tdwg);
|
330
|
}
|
331
|
if (area != null){
|
332
|
Distribution distribution = Distribution.NewInstance(area, PresenceTerm.PRESENT());
|
333
|
td.addElement(distribution);
|
334
|
}else{
|
335
|
String message = "TDWG area could not be recognized: " + tdwg;
|
336
|
logger.warn(message);
|
337
|
state.setUnsuccessfull();
|
338
|
}
|
339
|
}
|
340
|
|
341
|
//features
|
342
|
handleFeatures(state, taxonDataHolder, acceptedTaxon, nameUsedInSource);
|
343
|
}
|
344
|
} catch (Exception e) {
|
345
|
e.printStackTrace();
|
346
|
}
|
347
|
return;
|
348
|
}
|
349
|
|
350
|
|
351
|
/**
|
352
|
* @param state
|
353
|
* @param taxonDataHolder
|
354
|
* @param acceptedTaxon
|
355
|
*/
|
356
|
private void handleFeatures(TaxonExcelImportState state, NormalExplicitRow taxonDataHolder, Taxon acceptedTaxon, TaxonNameBase nameUsedInSource) {
|
357
|
//feature
|
358
|
for (UUID featureUuid : taxonDataHolder.getFeatures()){
|
359
|
Feature feature = getFeature(state, featureUuid);
|
360
|
List<String> textList = taxonDataHolder.getFeatureTexts(featureUuid);
|
361
|
List<String> languageList = taxonDataHolder.getFeatureLanguages(featureUuid);
|
362
|
|
363
|
for (int i = 0; i < textList.size(); i++){
|
364
|
String featureText = textList.get(i);
|
365
|
String featureLanguage = languageList == null ? null :languageList.get(i);
|
366
|
Language language = getFeatureLanguage(featureLanguage, state);
|
367
|
//TODO
|
368
|
TaxonDescription td = this.getTaxonDescription(acceptedTaxon, state.getConfig().getSourceReference() ,false, true);
|
369
|
TextData textData = TextData.NewInstance(feature);
|
370
|
textData.putText(language, featureText);
|
371
|
td.addElement(textData);
|
372
|
|
373
|
SourceDataHolder sourceDataHolder = taxonDataHolder.getFeatureTextReferences(featureUuid, i);
|
374
|
List<Map<SourceType, String>> sourceList = sourceDataHolder.getSources();
|
375
|
for (Map<SourceType, String> sourceMap : sourceList){
|
376
|
|
377
|
DescriptionElementSource source = DescriptionElementSource.NewInstance();
|
378
|
//ref
|
379
|
Reference<?> ref = ReferenceFactory.newGeneric();
|
380
|
boolean refExists = false; //in case none of the ref fields exists, the ref should not be added
|
381
|
for (SourceType type : sourceMap.keySet()){
|
382
|
String value = sourceMap.get(type);
|
383
|
if (type.equals(SourceType.Author)){
|
384
|
TeamOrPersonBase author = getAuthorAccordingToConfig(value, state);
|
385
|
ref.setAuthorTeam(author);
|
386
|
}else if (type.equals(SourceType.Title)) {
|
387
|
ref.setTitle(value);
|
388
|
}else if (type.equals(SourceType.Year)) {
|
389
|
ref.setDatePublished(TimePeriod.parseString(value));
|
390
|
}else if (type.equals(SourceType.RefExtension)) {
|
391
|
ExtensionType extensionType = getExtensionType(state, uuidRefExtension, "RefExtension", "Reference Extension", "RefExt.");
|
392
|
Extension extension = Extension.NewInstance(ref, value, extensionType);
|
393
|
}
|
394
|
refExists = true;
|
395
|
}
|
396
|
if (refExists){
|
397
|
ref = getReferenceAccordingToConfig(ref, state);
|
398
|
source.setCitation(ref);
|
399
|
source.setNameUsedInSource(nameUsedInSource);
|
400
|
}
|
401
|
textData.addSource(source);
|
402
|
}
|
403
|
}
|
404
|
}
|
405
|
}
|
406
|
|
407
|
private Map<String, UUID> referenceMapping = new HashMap<String, UUID>();
|
408
|
private Map<UUID, Reference> referenceStore = new HashMap<UUID, Reference>();
|
409
|
|
410
|
private Reference getReferenceAccordingToConfig(Reference value, TaxonExcelImportState state) {
|
411
|
Reference result = null;
|
412
|
String titleCache = value.getTitleCache();
|
413
|
UUID referenceUuid = referenceMapping.get(titleCache);
|
414
|
if (referenceUuid != null){
|
415
|
result = referenceStore.get(referenceUuid);
|
416
|
}
|
417
|
if (result == null){
|
418
|
result = value;
|
419
|
referenceStore.put(result.getUuid(), result);
|
420
|
}
|
421
|
if (referenceUuid == null){
|
422
|
referenceMapping.put(titleCache, result.getUuid());
|
423
|
}
|
424
|
return result;
|
425
|
}
|
426
|
|
427
|
|
428
|
private Map<String, UUID> authorMapping = new HashMap<String, UUID>();
|
429
|
private Map<UUID, TeamOrPersonBase> authorStore = new HashMap<UUID, TeamOrPersonBase>();
|
430
|
|
431
|
private TeamOrPersonBase getAuthorAccordingToConfig(String value, TaxonExcelImportState state) {
|
432
|
TeamOrPersonBase result = null;
|
433
|
UUID authorUuid = authorMapping.get(value);
|
434
|
if (authorUuid != null){
|
435
|
result = authorStore.get(authorUuid);
|
436
|
}
|
437
|
if (result == null){
|
438
|
//TODO parsing
|
439
|
TeamOrPersonBase author = Team.NewInstance();
|
440
|
author.setTitleCache(value, true);
|
441
|
result = author;
|
442
|
authorStore.put(result.getUuid(), result);
|
443
|
}
|
444
|
if (authorUuid == null){
|
445
|
authorMapping.put(value, result.getUuid());
|
446
|
}
|
447
|
return result;
|
448
|
}
|
449
|
|
450
|
|
451
|
private Map<String, UUID> languageMapping = new HashMap<String, UUID>();
|
452
|
|
453
|
private Language getFeatureLanguage(String featureLanguage, TaxonExcelImportState state) {
|
454
|
if (StringUtils.isBlank(featureLanguage)){
|
455
|
return null;
|
456
|
}
|
457
|
UUID languageUuid = languageMapping.get(featureLanguage);
|
458
|
if (languageUuid == null){
|
459
|
Language result = getTermService().getLanguageByIso(featureLanguage);
|
460
|
languageUuid = result.getUuid();
|
461
|
languageMapping.put(featureLanguage, languageUuid);
|
462
|
}
|
463
|
Language result = getLanguage(state, languageUuid, null, null, null);
|
464
|
return result;
|
465
|
}
|
466
|
|
467
|
|
468
|
/**
|
469
|
* @param state
|
470
|
* @param taxonNameStr
|
471
|
* @param commonNameStr
|
472
|
* @param parentId
|
473
|
*/
|
474
|
private void handleCommonName(TaxonExcelImportState state,
|
475
|
String taxonNameStr, String commonNameStr, Taxon acceptedTaxon) {
|
476
|
Language language = getTermService().getLanguageByIso(state.getCurrentRow().getLanguage());
|
477
|
if (language == null && CdmUtils.isNotEmpty(state.getCurrentRow().getLanguage()) ){
|
478
|
String error ="Language is null but shouldn't";
|
479
|
logger.error(error);
|
480
|
throw new IllegalArgumentException(error);
|
481
|
}
|
482
|
CommonTaxonName commonTaxonName = CommonTaxonName.NewInstance(commonNameStr, language);
|
483
|
try {
|
484
|
TaxonDescription taxonDescription = getTaxonDescription(acceptedTaxon, false, true);
|
485
|
taxonDescription.addElement(commonTaxonName);
|
486
|
logger.info("Common name " + commonNameStr + " added to " + acceptedTaxon.getTitleCache());
|
487
|
} catch (ClassCastException ex) {
|
488
|
logger.error(taxonNameStr + " is not a taxon instance.");
|
489
|
}
|
490
|
}
|
491
|
|
492
|
|
493
|
/**
|
494
|
* @param state
|
495
|
* @param rank
|
496
|
* @param taxonNameStr
|
497
|
* @param authorStr
|
498
|
* @param nameStatus
|
499
|
* @return
|
500
|
*/
|
501
|
private TaxonBase createTaxon(TaxonExcelImportState state, Rank rank,
|
502
|
String taxonNameStr, String authorStr, String nameStatus) {
|
503
|
// Create the taxon name object depending on the setting of the nomenclatural code
|
504
|
// in the configurator (botanical code, zoological code, etc.)
|
505
|
if (StringUtils.isBlank(taxonNameStr)){
|
506
|
return null;
|
507
|
}
|
508
|
NomenclaturalCode nc = getConfigurator().getNomenclaturalCode();
|
509
|
|
510
|
TaxonBase taxonBase = null;
|
511
|
|
512
|
String titleCache = CdmUtils.concat(" ", taxonNameStr, authorStr);
|
513
|
if (! synonymMarkers.contains(nameStatus) && state.getConfig().isDoMatchTaxa()){
|
514
|
titleCache = CdmUtils.concat(" ", taxonNameStr, authorStr);
|
515
|
taxonBase = getTaxonService().findBestMatchingTaxon(titleCache);
|
516
|
}else{
|
517
|
taxonBase = getTaxonService().findBestMatchingSynonym(titleCache);
|
518
|
if (taxonBase != null){
|
519
|
logger.info("Matching taxon/synonym found for " + titleCache);
|
520
|
}
|
521
|
}
|
522
|
if (taxonBase != null){
|
523
|
logger.info("Matching taxon/synonym found for " + titleCache);
|
524
|
}else {
|
525
|
taxonBase = createTaxon(state, rank, taxonNameStr, authorStr, nameStatus, nc);
|
526
|
}
|
527
|
return taxonBase;
|
528
|
}
|
529
|
|
530
|
|
531
|
|
532
|
|
533
|
/**
|
534
|
* @param state
|
535
|
* @param rank
|
536
|
* @param taxonNameStr
|
537
|
* @param authorStr
|
538
|
* @param nameStatus
|
539
|
* @param nc
|
540
|
* @return
|
541
|
*/
|
542
|
private TaxonBase createTaxon(TaxonExcelImportState state, Rank rank, String taxonNameStr,
|
543
|
String authorStr, String nameStatus, NomenclaturalCode nc) {
|
544
|
TaxonBase taxonBase;
|
545
|
NonViralName taxonNameBase = null;
|
546
|
if (nc == NomenclaturalCode.ICVCN){
|
547
|
logger.warn("ICVCN not yet supported");
|
548
|
|
549
|
}else{
|
550
|
taxonNameBase =(NonViralName) nc.getNewTaxonNameInstance(rank);
|
551
|
//NonViralName nonViralName = (NonViralName)taxonNameBase;
|
552
|
NonViralNameParserImpl parser = NonViralNameParserImpl.NewInstance();
|
553
|
taxonNameBase = parser.parseFullName(taxonNameStr, nc, rank);
|
554
|
|
555
|
taxonNameBase.setNameCache(taxonNameStr);
|
556
|
|
557
|
// Create the author
|
558
|
if (CdmUtils.isNotEmpty(authorStr)) {
|
559
|
try {
|
560
|
parser.parseAuthors(taxonNameBase, authorStr);
|
561
|
} catch (StringNotParsableException e) {
|
562
|
taxonNameBase.setAuthorshipCache(authorStr);
|
563
|
}
|
564
|
}
|
565
|
}
|
566
|
|
567
|
//Create the taxon
|
568
|
Reference sec = state.getConfig().getSourceReference();
|
569
|
// Create the status
|
570
|
nameStatus = CdmUtils.Nz(nameStatus).trim().toLowerCase();
|
571
|
if (validMarkers.contains(nameStatus)){
|
572
|
taxonBase = Taxon.NewInstance(taxonNameBase, sec);
|
573
|
}else if (synonymMarkers.contains(nameStatus)){
|
574
|
taxonBase = Synonym.NewInstance(taxonNameBase, sec);
|
575
|
}else {
|
576
|
Taxon taxon = Taxon.NewInstance(taxonNameBase, sec);
|
577
|
taxon.setTaxonStatusUnknown(true);
|
578
|
taxonBase = taxon;
|
579
|
}
|
580
|
return taxonBase;
|
581
|
}
|
582
|
|
583
|
/**
|
584
|
* @param taxon
|
585
|
* @return
|
586
|
*/
|
587
|
//TODO implementation must be improved when matching of taxon names with existing names is implemented
|
588
|
//=> the assumption that the only description is the description added by this import
|
589
|
//is wrong then
|
590
|
private TaxonNameDescription getNameDescription(TaxonNameBase name) {
|
591
|
Set<TaxonNameDescription> descriptions = name.getDescriptions();
|
592
|
if (descriptions.size()>1){
|
593
|
throw new IllegalStateException("Implementation does not yet support names with multiple descriptions");
|
594
|
}else if (descriptions.size()==1){
|
595
|
return descriptions.iterator().next();
|
596
|
}else{
|
597
|
return TaxonNameDescription.NewInstance(name);
|
598
|
}
|
599
|
}
|
600
|
|
601
|
private void makeParent(TaxonExcelImportState state, Taxon parentTaxon, Taxon childTaxon, Reference citation, String microCitation){
|
602
|
Reference sec = state.getConfig().getSourceReference();
|
603
|
|
604
|
// Reference sec = parentTaxon.getSec();
|
605
|
Classification tree = state.getTree(sec);
|
606
|
if (tree == null){
|
607
|
tree = makeTree(state, sec);
|
608
|
}
|
609
|
if (sec.equals(childTaxon.getSec())){
|
610
|
boolean success = (null != tree.addParentChild(parentTaxon, childTaxon, citation, microCitation));
|
611
|
if (success == false){
|
612
|
state.setUnsuccessfull();
|
613
|
}
|
614
|
}else{
|
615
|
logger.warn("No relationship added for child " + childTaxon.getTitleCache());
|
616
|
}
|
617
|
return;
|
618
|
}
|
619
|
|
620
|
|
621
|
/* (non-Javadoc)
|
622
|
* @see eu.etaxonomy.cdm.io.excel.common.ExcelTaxonOrSpecimenImportBase#createDataHolderRow()
|
623
|
*/
|
624
|
@Override
|
625
|
protected NormalExplicitRow createDataHolderRow() {
|
626
|
return new NormalExplicitRow();
|
627
|
}
|
628
|
|
629
|
|
630
|
|
631
|
/* (non-Javadoc)
|
632
|
* @see eu.etaxonomy.cdm.io.common.CdmIoBase#doCheck(eu.etaxonomy.cdm.io.common.IoStateBase)
|
633
|
*/
|
634
|
@Override
|
635
|
protected boolean doCheck(TaxonExcelImportState state) {
|
636
|
logger.warn("DoCheck not yet implemented for NormalExplicitImport");
|
637
|
return true;
|
638
|
}
|
639
|
|
640
|
/* (non-Javadoc)
|
641
|
* @see eu.etaxonomy.cdm.io.common.CdmIoBase#isIgnore(eu.etaxonomy.cdm.io.common.IoStateBase)
|
642
|
*/
|
643
|
@Override
|
644
|
protected boolean isIgnore(TaxonExcelImportState state) {
|
645
|
return false;
|
646
|
}
|
647
|
|
648
|
|
649
|
|
650
|
}
|