Project

General

Profile

Download (15.5 KB) Statistics
| Branch: | Revision:
1
/**
2
* Copyright (C) 2016 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
package eu.etaxonomy.cdm.io.lichenes;
10

    
11
import java.util.Arrays;
12
import java.util.List;
13
import java.util.Map;
14
import java.util.Set;
15
import java.util.UUID;
16

    
17
import org.apache.log4j.Logger;
18
import org.springframework.stereotype.Component;
19

    
20
import eu.etaxonomy.cdm.common.CdmUtils;
21
import eu.etaxonomy.cdm.io.mexico.SimpleExcelTaxonImport;
22
import eu.etaxonomy.cdm.io.mexico.SimpleExcelTaxonImportState;
23
import eu.etaxonomy.cdm.model.common.Annotation;
24
import eu.etaxonomy.cdm.model.common.AnnotationType;
25
import eu.etaxonomy.cdm.model.common.IdentifiableSource;
26
import eu.etaxonomy.cdm.model.common.Language;
27
import eu.etaxonomy.cdm.model.name.INonViralName;
28
import eu.etaxonomy.cdm.model.name.NameRelationshipType;
29
import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
30
import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
31
import eu.etaxonomy.cdm.model.name.Rank;
32
import eu.etaxonomy.cdm.model.name.TaxonName;
33
import eu.etaxonomy.cdm.model.reference.Reference;
34
import eu.etaxonomy.cdm.model.taxon.Classification;
35
import eu.etaxonomy.cdm.model.taxon.Synonym;
36
import eu.etaxonomy.cdm.model.taxon.SynonymType;
37
import eu.etaxonomy.cdm.model.taxon.Taxon;
38
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
39
import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
40
import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImpl;
41

    
42
/**
43
 * Lichenes genera taxon import.
44
 *
45
 * @author a.mueller
46
 * @since 10.03.2020
47
 */
48
@Component
49
public class LichenesGeneraTaxonImport<CONFIG extends LichenesGeneraImportConfigurator>
50
            extends SimpleExcelTaxonImport<CONFIG>{
51

    
52
	private static final long serialVersionUID = -2448091105224956821L;
53
	private static final Logger logger = Logger.getLogger(LichenesGeneraTaxonImport.class);
54

    
55
	private static final String INCERTAE_SEDIS = "Incertae sedis";
56

    
57
	private static UUID rootUuid = UUID.fromString("61187f71-96d1-419d-958b-25ab4c01a93c");
58

    
59
    private  static List<String> expectedKeys= Arrays.asList(new String[]{
60
            "SORT","GENUS_X","PHYLUM","SUBPHYLUM","CLASS","SUBCLASS","ORDER","SUBORDER","FAMILY",
61
            "FAM_SYNONYMS","SUBFAMILY","GENUS","SYNONYMS","SPECIES","REFERENCES","MOLECULAR","NOTES"
62
    });
63

    
64
    private Reference sourceReference;
65
    private Reference secReference;
66

    
67
    private NonViralNameParserImpl parser = NonViralNameParserImpl.NewInstance();
68

    
69
//    @Override
70
//    protected String getWorksheetName(CONFIG config) {
71
//        return "valid taxa names";
72
//    }
73

    
74
    @Override
75
    protected void firstPass(SimpleExcelTaxonImportState<CONFIG> state) {
76

    
77
        String line = getLine(state, 100);
78
        Map<String, String> record = state.getOriginalRecord();
79

    
80
        Set<String> keys = record.keySet();
81
        for (String key: keys) {
82
            if (! expectedKeys.contains(key)){
83
                logger.warn(line + "Unexpected Key: " + key);
84
            }
85
        }
86

    
87
        makeTaxon(state, line, record);
88

    
89
//        state.putTaxon(noStr, taxon);
90
    }
91

    
92
    private Taxon makeTaxon(SimpleExcelTaxonImportState<CONFIG> state, String line, Map<String, String> record) {
93

    
94
        TaxonNode parentNode = getParentNode(record, state, line);
95
        if (parentNode == null){
96
            logger.warn(line + "Parent not created");
97
        }
98

    
99
        Reference sec = getSecReference(state);
100
        String genusStr = getValue(record, "GENUS");
101
        String[] split = parseNomStatus(genusStr);
102
        genusStr = split[0];
103
        TaxonName genusName = (TaxonName)parser.parseFullName(genusStr, state.getConfig().getNomenclaturalCode(), Rank.GENUS());
104
        checkParsed(TaxonName.castAndDeproxy(genusName), genusStr, line);
105
        makeStatusAndHomonym(state, genusName, split);
106
        replaceNameAuthorsAndReferences(state, genusName);
107
        Taxon genusTaxon = Taxon.NewInstance(genusName, sec);
108
        genusName.addSource(makeOriginalSource(state));
109
        genusTaxon.addSource(makeOriginalSource(state));
110

    
111
        makeSynonyms(state, line, record, genusTaxon, "SYNONYMS");
112

    
113
        //TODO reference  => for now we don't use it
114

    
115
        makeNotes(genusTaxon, record, line);
116
        TaxonNode genusNode = parentNode.addChildTaxon(genusTaxon, null, null);
117
        getTaxonNodeService().saveOrUpdate(genusNode);
118

    
119
        return genusTaxon;
120
    }
121

    
122
    private void makeStatusAndHomonym(SimpleExcelTaxonImportState<CONFIG> state, TaxonName name, String[] split) {
123
		if (isNotBlank(split[1])) {
124
			try {
125
				NomenclaturalStatusType statusType = NomenclaturalStatusType.getNomenclaturalStatusTypeByAbbreviation(split[1], name);
126
				name.addStatus(statusType, null, null);
127
			} catch (UnknownCdmTypeException e) {
128
				e.printStackTrace();
129
			}
130
		}
131
		if (isNotBlank(split[2])) {
132
			TaxonName earlierName = (TaxonName)parser.parseFullName(split[2], NomenclaturalCode.ICNAFP, Rank.GENUS());
133
			replaceNameAuthorsAndReferences(state, earlierName);
134
			name.addRelationshipToName(earlierName, NameRelationshipType.LATER_HOMONYM());
135
			name.addSource(makeOriginalSource(state));
136
			getNameService().saveOrUpdate(earlierName);
137
		}
138
	}
139

    
140
	private String[] parseNomStatus(String nameStr) {
141
		String[] result = new String[3];
142
		if (nameStr.endsWith(", non Tayloriella Kylin (Rhodophyta)")) {
143
			result[2] = "Tayloriella Kylin";
144
			nameStr = nameStr.replace(", non Tayloriella Kylin (Rhodophyta)".trim(), "");
145
		}
146
		if (nameStr.endsWith("[nom. illeg.]")) {
147
			result[1] = "nom. illeg.";
148
			result[0] = nameStr.replace("[nom. illeg.]".trim(), "");
149
		}else if (nameStr.endsWith("[nom. inval.]")) {
150
			result[1] = "nom. inval.";
151
			result[0] = nameStr.replace("[nom. inval.]".trim(), "");
152
		}else if (nameStr.endsWith("[nom. cons. prop.]")) {
153
			result[1] = "nom. cons. prop.";
154
			result[0] = nameStr.replace("[nom. cons. prop.]".trim(), "");
155
		}else{
156
			result[0] = nameStr;
157
		}
158
		return result;
159
	}
160

    
161
	private void makeNotes(Taxon genusTaxon, Map<String, String> record, String line) {
162
    	String notesStr = getValue(record, "NOTES");
163
    	if (isNotBlank(notesStr)) {
164
    		if (notesStr.startsWith("Notes.")) {
165
    			notesStr = notesStr.substring(6).trim();
166
    		}
167
    		//TODO or handle as fact of type "Notes"
168
    		genusTaxon.addAnnotation(Annotation.NewInstance(notesStr, AnnotationType.EDITORIAL(), Language.ENGLISH()));
169
    	}
170
 	}
171

    
172
	private void checkParsed(TaxonName name, String nameStr, String line) {
173
		if (name.isProtectedTitleCache() || name.isProtectedFullTitleCache() || name.isProtectedNameCache()) {
174
			logger.warn(line + "Name could not be parsed: " + nameStr);
175
		}
176
	}
177

    
178
	private void makeSynonyms(SimpleExcelTaxonImportState<CONFIG> state,
179
    		String line, Map<String, String> record, Taxon accepted, String fieldName) {
180

    
181
    	String synonymsStr = getValue(record, fieldName);
182
    	if (isBlank(synonymsStr)) {
183
    		return;
184
    	}else if (!synonymsStr.matches("\\(syn\\.:.*\\)")) {
185
    		logger.warn(line + "Synonyms has unexpected format. No synonyms imported: " + synonymsStr);
186
    		return;
187
    	}else{
188
    		String synonymsStr2 = synonymsStr.substring(7).trim();
189
    		synonymsStr2 = synonymsStr2.substring(0, synonymsStr2.length()-1);
190
    		String[] splits = synonymsStr2.split(";");
191
    		for (String singleSynonymStr: splits) {
192
    			String[] split2 = parseNomStatus(singleSynonymStr);
193
    	        singleSynonymStr = split2[0];
194

    
195
    			TaxonName synonymName = (TaxonName)parser.parseFullName(singleSynonymStr, state.getConfig().getNomenclaturalCode(), null);
196
    			checkParsed(TaxonName.castAndDeproxy(synonymName), singleSynonymStr, line);
197
    			makeStatusAndHomonym(state, synonymName, split2);
198
    			replaceNameAuthorsAndReferences(state, synonymName);
199
    	        synonymName.addSource(makeOriginalSource(state));
200
    	        Synonym synonym = Synonym.NewInstance(synonymName, accepted.getSec());
201
    	        accepted.addSynonym(synonym, SynonymType.SYNONYM_OF());
202
    			synonymName.addSource(makeOriginalSource(state));
203
    			synonym.addSource(makeOriginalSource(state));
204
    		}
205
    	}
206
	}
207

    
208
	private String lastPhylum = "";
209
	private String lastSubphylum = "";
210
	private String lastClassname = "";
211
	private String lastSubclass = "";
212
	private String lastOrder = "";
213
	private String lastSubOrder = "";
214
	private String lastFamily = "";
215
	private String lastSubFamily = "";
216

    
217
	private Taxon taxonPhylum = null;
218
	private Taxon taxonSubphylum = null;
219
	private Taxon taxonClass = null;
220
	private Taxon taxonSubclass = null;
221
	private Taxon taxonOrder = null;
222
	private Taxon taxonSubOrder = null;
223
	private Taxon taxonFamily = null;
224
	private Taxon taxonSubFamily = null;
225

    
226
	private TaxonNode getParentNode(Map<String, String> record, SimpleExcelTaxonImportState<CONFIG> state, String line) {
227

    
228
	    Taxon higherTaxon = null;
229
		Classification classification = getClassification(state).getClassification();
230

    
231
		String phylum =  Nz(getValue(record, "PHYLUM"));
232
		String subphylum = Nz(getValue(record, "SUBPHYLUM"));
233
		String classname = Nz(getValue(record, "CLASS"));
234
		String subclass = Nz(getValue(record, "SUBCLASS"));
235
		String order = Nz(getValue(record, "ORDER"));
236
		String suborder = Nz(getValue(record, "SUBORDER"));
237
		String family = Nz(getValue(record, "FAMILY"));
238
		String subfamily = Nz(getValue(record, "SUBFAMILY"));
239

    
240
		if (isNewTaxon(subfamily, lastSubFamily)){
241
			if (isNewTaxon(family, lastFamily)){
242
				if (isNewTaxon(suborder, lastSubOrder)){
243
					if (isNewTaxon(order, lastOrder)){
244
						if (isNewTaxon(subclass, lastSubclass)){
245
							if (isNewTaxon(classname, lastClassname)){
246
								if (isNewTaxon(subphylum, lastSubphylum)){
247
									if (isNewTaxon(phylum, lastPhylum)){
248
										//new phylum
249
										taxonPhylum = makeHigherTaxon(state, phylum, Rank.PHYLUM());
250
										lastPhylum = phylum;
251
										logger.info("Import phylum " +  phylum);
252
										getTaxonService().saveOrUpdate(taxonPhylum);
253
									}
254
									higherTaxon = taxonPhylum;
255
									//new subphylum
256
									taxonSubphylum = makeHigherTaxon(state, subphylum, Rank.SUBPHYLUM());
257
									if (taxonSubphylum != null){  //no null expected
258
										classification.addParentChild(higherTaxon,taxonSubphylum, null, null);
259
									}
260
									higherTaxon = isIncertisSedis(subphylum) ? higherTaxon : taxonSubphylum;
261
									lastSubphylum = subphylum;
262
								}else{
263
									higherTaxon = taxonSubphylum;
264
								}
265
								//new class
266
								taxonClass = makeHigherTaxon(state, classname, Rank.CLASS());
267
								if (taxonClass != null){
268
									classification.addParentChild(higherTaxon, taxonClass, null, null);
269
								}
270
								higherTaxon = isIncertisSedis(classname) ? higherTaxon : taxonClass;
271
								lastClassname = classname;
272
							}else{
273
								higherTaxon = taxonClass;
274
							}
275
							//new subclass
276
							taxonSubclass = makeHigherTaxon(state, subclass, Rank.SUBCLASS());
277
							if (taxonSubclass != null){
278
								classification.addParentChild(higherTaxon, taxonSubclass,null, null);
279
							}
280
							higherTaxon = isIncertisSedis(subclass) ? higherTaxon : taxonSubclass;
281
							lastSubclass = subclass;
282
						}else{
283
							higherTaxon = taxonSubclass;
284
						}
285
						//new order
286
						taxonOrder = makeHigherTaxon(state, order, Rank.ORDER());
287
						if (taxonOrder != null){
288
							classification.addParentChild(higherTaxon, taxonOrder, null, null);
289
						}
290
						higherTaxon = isIncertisSedis(order) ? higherTaxon : taxonOrder;
291
						lastOrder = order;
292
					}else{
293
						higherTaxon = taxonOrder;
294
					}
295
					//new suborder
296
					taxonSubOrder = makeHigherTaxon(state, suborder, Rank.SUBORDER());
297
					if (taxonSubOrder != null){
298
						classification.addParentChild(higherTaxon, taxonSubOrder, null, null);
299
					}
300
					higherTaxon = isIncertisSedis(suborder) ? higherTaxon : taxonSubOrder;
301
					lastSubOrder = suborder;
302
				}else{
303
					higherTaxon = taxonSubOrder;
304
				}
305
				taxonFamily = makeHigherTaxon(state, family, Rank.FAMILY());
306
				if (taxonFamily != null){
307
					classification.addParentChild(higherTaxon, taxonFamily, null, null);
308
					makeSynonyms(state, line, record, taxonFamily, "FAM_SYNONYMS");
309
				}
310
				higherTaxon = isIncertisSedis(family) ? higherTaxon : taxonFamily;
311
				lastFamily = family;
312
				getTaxonService().saveOrUpdate(higherTaxon);
313
			}else{
314
				higherTaxon = taxonFamily;
315
			}
316
			taxonSubFamily = makeHigherTaxon(state, subfamily, Rank.SUBFAMILY());
317
			if (taxonSubFamily != null){
318
				classification.addParentChild(higherTaxon, taxonSubFamily, null, null);
319
			}
320
			higherTaxon = isIncertisSedis(subfamily) ? higherTaxon : taxonSubFamily;
321
			lastSubFamily = subfamily;
322
		}else {
323
			higherTaxon = taxonSubFamily;
324
		}
325

    
326
		getTaxonService().saveOrUpdate(higherTaxon);
327

    
328
		return higherTaxon.getTaxonNode(classification);
329
	}
330

    
331
	private String Nz(String value) {
332
		return CdmUtils.Nz(value);
333
	}
334

    
335
	private boolean isIncertisSedis(String uninomial) {
336
		return isBlank(uninomial) || uninomial.equalsIgnoreCase(INCERTAE_SEDIS);
337
	}
338

    
339
	private boolean isNewTaxon(String uninomial, String lastUninomial) {
340
		boolean result = isBlank(uninomial) || !uninomial.equalsIgnoreCase(lastUninomial);
341
//		result |= !uninomial.equalsIgnoreCase(lastUninomial);
342
		result |= lastUninomial.equalsIgnoreCase(INCERTAE_SEDIS);
343
		return result;
344
	}
345

    
346
	private Taxon makeHigherTaxon(SimpleExcelTaxonImportState<CONFIG> state, String nameStr, Rank rank) {
347
		if (isBlank(nameStr) || nameStr.equalsIgnoreCase(INCERTAE_SEDIS)){
348
			return null;
349
		}
350
		//name
351
		INonViralName name = parser.parseFullName(nameStr, NomenclaturalCode.Fungi, rank);
352
		replaceNameAuthorsAndReferences(state, name);
353
		//taxon
354
		Reference secRef = getSecReference(state);
355
		Taxon taxon = Taxon.NewInstance(name, secRef);
356
        name.addSource(makeOriginalSource(state));
357
        taxon.addSource(makeOriginalSource(state));
358
		return taxon;
359
	}
360

    
361
    private TaxonNode rootNode;
362

    
363
    private TaxonNode getClassification(SimpleExcelTaxonImportState<CONFIG> state) {
364
        if (rootNode == null){
365
            Reference sec = getSecReference(state);
366
            String classificationName = state.getConfig().getClassificationName();
367
            Language language = Language.DEFAULT();
368
            Classification classification = Classification.NewInstance(classificationName, sec, language);
369
            classification.setUuid(state.getConfig().getClassificationUuid());
370
            classification.getRootNode().setUuid(rootUuid);
371
            getClassificationService().save(classification);
372

    
373
            rootNode = classification.getRootNode();
374
        }
375
        return rootNode;
376
    }
377

    
378
    private Reference getSecReference(SimpleExcelTaxonImportState<CONFIG> state) {
379
        if (this.secReference == null){
380
            this.secReference = getPersistentReference(state.getConfig().getSecReference());
381
        }
382
        return this.secReference;
383
    }
384

    
385
    protected Reference getSourceCitation(SimpleExcelTaxonImportState<CONFIG> state) {
386
        if (this.sourceReference == null){
387
            this.sourceReference = getPersistentReference(state.getConfig().getSourceReference());
388
        }
389
        return this.sourceReference;
390
    }
391

    
392
    private Reference getPersistentReference(Reference reference) {
393
        Reference result = getReferenceService().find(reference.getUuid());
394
        if (result == null){
395
            result = reference;
396
        }
397
        return result;
398
    }
399

    
400
    private void replaceNameAuthorsAndReferences(SimpleExcelTaxonImportState<CONFIG> state, INonViralName name) {
401
        state.getDeduplicationHelper().replaceAuthorNamesAndNomRef(name);
402
    }
403

    
404
    @Override
405
    protected IdentifiableSource makeOriginalSource(SimpleExcelTaxonImportState<CONFIG> state) {
406
    	String noStr = getValue(state.getOriginalRecord(), "SORT");
407
        return IdentifiableSource.NewDataImportInstance(noStr, "SORT", state.getConfig().getSourceReference());
408
    }
409
}
(2-2/2)