Project

General

Profile

Download (20 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.uzbekistan;
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.io.mexico.SimpleExcelTaxonImport;
21
import eu.etaxonomy.cdm.io.mexico.SimpleExcelTaxonImportState;
22
import eu.etaxonomy.cdm.model.common.CdmBase;
23
import eu.etaxonomy.cdm.model.common.IdentifiableSource;
24
import eu.etaxonomy.cdm.model.common.Language;
25
import eu.etaxonomy.cdm.model.description.CommonTaxonName;
26
import eu.etaxonomy.cdm.model.name.INonViralName;
27
import eu.etaxonomy.cdm.model.name.NameTypeDesignationStatus;
28
import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
29
import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
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.reference.ReferenceType;
35
import eu.etaxonomy.cdm.model.taxon.Classification;
36
import eu.etaxonomy.cdm.model.taxon.Synonym;
37
import eu.etaxonomy.cdm.model.taxon.SynonymType;
38
import eu.etaxonomy.cdm.model.taxon.Taxon;
39
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
40
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
41
import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImpl;
42

    
43
/**
44
 * Uzbekistan taxon import.
45
 *
46
 * @author a.mueller
47
 * @since 05.05.2020
48
 */
49
@Component
50
public class UzbekistanTaxonImport<CONFIG extends UzbekistanTaxonImportConfigurator>
51
            extends SimpleExcelTaxonImport<CONFIG>{
52

    
53
    private static final long serialVersionUID = 7793140600785382094L;
54
    private static final Logger logger = Logger.getLogger(UzbekistanTaxonImport.class);
55

    
56
    private static final String COMMON_NAME = "common name";
57
    private static final String PARENT_TAXON_UUID = "parentTaxonUuid";
58
    private static final String ACCEPTED_TAXON_UUID = "acceptedTaxonUuid";
59
    private static final String NAME_TYPE_UUID = "nameTypeUuid";
60
    private static final String REPLACED_SYNONYM_UUID = "replacedSynonymUuid";
61
    private static final String BASIONYM_UUID = "basionymUuid";
62
    private static final String TAXON_UUID = "taxonUuid";
63
    private static final String NAME_STATUS = "nameStatus";
64
    private static final String STATUS = "status";
65
    private static final String RANK = "rank";
66
    private static final String FULL_NAME = "fullName";
67
    private static final String FULL_TITLE = "fullTitle";
68
    private static final String REFERENCE_TYPE = "referenceType";
69

    
70
	private static UUID rootUuid = UUID.fromString("3ee689d2-17c2-4f02-9905-7092a45aa1b9");
71

    
72
    private  static List<String> expectedKeys= Arrays.asList(new String[]{
73
            TAXON_UUID,FULL_TITLE,FULL_NAME,"pureName",
74
            RANK,STATUS,REFERENCE_TYPE,PARENT_TAXON_UUID,"parenTaxonName",
75
            ACCEPTED_TAXON_UUID,"acceptedTaxonName","homotypicGroupUuid",BASIONYM_UUID,
76
            REPLACED_SYNONYM_UUID,NAME_STATUS,NAME_TYPE_UUID,COMMON_NAME
77
    });
78

    
79
    private Reference sourceReference;
80
    private Reference secReference;
81

    
82
    private NonViralNameParserImpl parser = NonViralNameParserImpl.NewInstance();
83

    
84
//    @Override
85
//    protected String getWorksheetName(CONFIG config) {
86
//        return "valid taxa names";
87
//    }
88

    
89
    @Override
90
    protected void firstPass(SimpleExcelTaxonImportState<CONFIG> state) {
91

    
92
        String line = getLine(state, 50);
93
        System.out.println(line);
94
        Map<String, String> record = state.getOriginalRecord();
95

    
96
        Set<String> keys = record.keySet();
97
        for (String key: keys) {
98
            if (! expectedKeys.contains(key)){
99
                logger.warn(line + "Unexpected Key: " + key);
100
            }
101
        }
102

    
103
        makeTaxon(state, line, record);
104
    }
105

    
106
    private void makeTaxon(SimpleExcelTaxonImportState<CONFIG> state, String line, Map<String, String> record) {
107
        state.getTransactionStatus().flush();
108

    
109
        Reference sec = getSecReference(state);
110
        state.getTransactionStatus().flush();
111

    
112
        String fullTitle = getValue(record, FULL_TITLE);
113
        String fullName = getValue(record, FULL_NAME);
114
        Rank rank = makeRank(line, record);
115

    
116
        //name
117
        TaxonName taxonName = parser.parseReferencedName(fullTitle, NomenclaturalCode.ICNAFP, rank);
118

    
119
        //TODO validation, deduplication, source, ...
120

    
121
        //name status
122
        makeNameStatus(line, record, taxonName);
123

    
124
        taxonName = TaxonName.castAndDeproxy(taxonName);
125
       //TODO
126
        checkParsed(TaxonName.castAndDeproxy(taxonName), fullTitle, fullName, line);
127
        checkReference(record, line, taxonName, fullTitle);
128
        replaceNameAuthorsAndReferences(state, taxonName);
129
        taxonName.addSource(makeOriginalSource(state));
130

    
131
        //taxon
132
        TaxonBase<?> taxonBase = makeTaxonBase(state, line, record, taxonName, sec);
133
        //common name
134
        makeCommonName(line, record, taxonBase);
135

    
136
        getNameService().saveOrUpdate(taxonName);
137
        if (taxonBase != null){
138
            getTaxonService().saveOrUpdate(taxonBase);
139
        }
140
        state.getTransactionStatus().flush();
141

    
142
        return;
143
    }
144

    
145
    private void checkReference(Map<String, String> record, String line,
146
            TaxonName taxonName, String fullTitle) {
147
        String refTypeStr = getValue(record, REFERENCE_TYPE);
148
        String statusStr = getValue(record, STATUS);
149
        Reference ref = taxonName.getNomenclaturalReference();
150
        if(ref == null){
151
            if (isNotBlank(refTypeStr)){
152
                logger.warn(line + "RefType given but no nom. ref. parsed: " + fullTitle);
153
            }
154
            if(isNotBlank(statusStr)){
155
                logger.warn(line+"Taxon status exist but name has no nom. ref.: " + fullTitle);
156
            }
157
        }else{
158
            if ("A".equals(refTypeStr)){
159
                if (!ref.getType().equals(ReferenceType.Article)){
160
                    logger.warn(line+"RefType should be article but was not: " + ref.getType().getLabel() + ";" + fullTitle);
161
                }
162
            }else if ("B".equals(refTypeStr)){
163
                if (!ref.getType().equals(ReferenceType.Book)){
164
                    logger.warn(line+"RefType should be book but was not: " + ref.getType().getLabel() + ";" + fullTitle);
165
                }
166
            }else if ("BS".equals(refTypeStr)){
167
                if (!ref.getType().equals(ReferenceType.BookSection)){
168
                    logger.warn(line+"RefType should be book section but was not: " + ref.getType().getLabel() + ";" + fullTitle) ;
169
                }
170
            }else{
171
                logger.warn(line+"Name has nom. ref. but ref type could not be recognized/was empty: " + refTypeStr + ";" + fullTitle);
172
            }
173
        }
174
    }
175

    
176
    private void makeCommonName(String line,
177
            Map<String, String> record,
178
            TaxonBase<?> taxonBase) {
179
        String commonNameStr = getValue(record, COMMON_NAME);
180
        if(isBlank(commonNameStr)){
181
            return;
182
        }else if(taxonBase == null){
183
            logger.warn(line + "No taxon exists for common name: " + commonNameStr);
184
        }else if(! (taxonBase instanceof Taxon)){
185
            logger.warn(line + "Taxon is not accepted for common name: " + commonNameStr);
186
        }else{
187
            Taxon taxon = (Taxon)taxonBase;
188
            CommonTaxonName commonName = CommonTaxonName.NewInstance(commonNameStr, Language.RUSSIAN());
189
            getTaxonDescription(taxon, false, true).addElement(commonName);
190
        }
191
    }
192

    
193
    private void makeNameStatus(String line, Map<String, String> record,
194
            TaxonName taxonName) {
195
        String nameStatus = getValue(record, NAME_STATUS);
196
        NomenclaturalStatusType status;
197
        if (isBlank(nameStatus)){
198
            status = null;
199
        }else if ("nom. cons.".equals(nameStatus)){
200
            status = NomenclaturalStatusType.CONSERVED();
201
        }else if ("nom. inval.".equals(nameStatus)){
202
            status = NomenclaturalStatusType.INVALID();
203
        }else if ("nom. illeg.".equals(nameStatus)){
204
            status = NomenclaturalStatusType.ILLEGITIMATE();
205
        }else if ("nom. rej.".equals(nameStatus)){
206
            status = NomenclaturalStatusType.REJECTED();
207
        }else{
208
            logger.warn(line + "Nom. status not recognized: " + nameStatus);
209
            status = null;
210
        }
211
        if (status != null){
212
            taxonName.addStatus(NomenclaturalStatus.NewInstance(status));
213
        }
214
    }
215

    
216

    
217
    private TaxonBase<?> makeTaxonBase(SimpleExcelTaxonImportState<CONFIG> state, String line,
218
            Map<String, String> record, TaxonName taxonName, Reference sec) {
219
        TaxonBase<?> taxonBase;
220
        String statusStr = getValue(record, STATUS);
221
        String taxonUuidStr = getValue(record, TAXON_UUID);
222
        UUID taxonUuid = UUID.fromString(taxonUuidStr);
223
        if ("A".equals(statusStr)){
224
            taxonBase = Taxon.NewInstance(taxonName, sec);
225
        }else if ("S".equals(statusStr)){
226
            taxonBase = Synonym.NewInstance(taxonName, sec);
227
        }else if (statusStr == null){
228
            taxonName.setUuid(taxonUuid);
229
            return null;
230
        }else{
231
            logger.warn(line + "Status not handled: " + statusStr);
232
            return null;
233
        }
234
        taxonBase.setUuid(taxonUuid);
235
        taxonBase.addSource(makeOriginalSource(state));
236
        return taxonBase;
237
    }
238

    
239
    private Rank makeRank(String line, Map<String, String> record) {
240
        String rankStr = getValue(record, RANK);
241
        if (rankStr.equals("family")){
242
            return Rank.FAMILY();
243
        }else if(rankStr.equals("genus")){
244
            return Rank.GENUS();
245
        }else if(rankStr.equals("species")){
246
            return Rank.SPECIES();
247
        }else if(rankStr.equals("section")){
248
            return Rank.SECTION_BOTANY();
249
        }else if(rankStr.equals("subsection")){
250
            return Rank.SUBSECTION_BOTANY();
251
        }else if(rankStr.equals("series")){
252
            return Rank.SERIES();
253
        }else if(rankStr.equals("subgenus")){
254
            return Rank.SUBGENUS();
255
        }else if(rankStr.equals("subspecies")){
256
            return Rank.SUBSPECIES();
257
        }else if(rankStr.equals("variety")){
258
            return Rank.VARIETY();
259
        }else if(rankStr.equals("unranked infrageneric")){
260
            return Rank.UNRANKED_INFRAGENERIC();
261
        }else{
262
            logger.warn(line + "Unknown rank: " + rankStr);
263
        }
264
        return null;
265
    }
266

    
267
    @Override
268
    protected void secondPass(SimpleExcelTaxonImportState<CONFIG> state) {
269
        String line = state.getCurrentLine() + ": ";
270
        System.out.println(line);
271
        Map<String, String> record = state.getOriginalRecord();
272

    
273
        String statusStr = getValue(record, STATUS);
274
        String rankStr = getValue(record, RANK);
275

    
276
        UUID taxonUuid = getUuid(record, TAXON_UUID, true, line);
277
        TaxonBase<?> taxonBase = getTaxonService().find(taxonUuid);
278
        TaxonName taxonName;
279
        if (taxonBase == null){
280
            taxonName = getNameService().find(taxonUuid);
281
        }else{
282
            taxonName = taxonBase.getName();
283
        }
284

    
285
        UUID parentUuid = getUuid(record, PARENT_TAXON_UUID, false, line);
286
        if (parentUuid != null){
287
            TaxonBase<?> parentBase = getTaxonService().find(parentUuid);
288
            if(!parentBase.isInstanceOf(Taxon.class)){
289
                logger.warn(line + "Parent taxon is not accepted: " + parentUuid);
290
            }else if (taxonBase == null || (!taxonBase.isInstanceOf(Taxon.class))){
291
                logger.warn(line + "Taxon has parent uuid but has not status accepted");
292
            }else{
293
                Taxon child = CdmBase.deproxy(taxonBase, Taxon.class);
294
                Taxon parentTaxon = CdmBase.deproxy(parentBase, Taxon.class);
295
                Classification classification = getClassification(state).getClassification();
296
                TaxonNode node = classification.addParentChild(parentTaxon, child, null, null);
297
                getTaxonNodeService().saveOrUpdate(node);
298
            }
299
        }else if("A".equals(statusStr) && !"family".equals(rankStr)){
300
            logger.warn(line + "No parent given for accepted non-family taxon");
301
        }
302

    
303
        UUID acceptedUuid = getUuid(record, ACCEPTED_TAXON_UUID, false, line);
304
        if (acceptedUuid != null){
305
            TaxonBase<?> acceptedBase = getTaxonService().find(acceptedUuid);
306
            if(acceptedBase == null){
307
                logger.warn(line + "Taxon for existing uuid could not be found. This should not happen");
308
                return;
309
            }else if(!acceptedBase.isInstanceOf(Taxon.class)){
310
                logger.warn(line + "Accepted taxon is not accepted: " + acceptedUuid);
311
            }else if (taxonBase == null || (!taxonBase.isInstanceOf(Synonym.class))){
312
                logger.warn(line + "Synonym has accepted uuid but has not status accepted");
313
            }else{
314
                Synonym syn = CdmBase.deproxy(taxonBase, Synonym.class);
315
                Taxon acc = CdmBase.deproxy(acceptedBase, Taxon.class);
316
                //TODO synType
317
                acc.addSynonym(syn, SynonymType.HETEROTYPIC_SYNONYM_OF());
318
            }
319
        }else if("S".equals(statusStr)){
320
            logger.warn(line + "No accepted taxon given for synonym");
321
        }
322

    
323
        UUID basionymUuid = getUuid(record, BASIONYM_UUID, false, line);
324
        if (basionymUuid != null){
325
            TaxonBase<?> basionymTaxon = getTaxonService().find(basionymUuid);
326
            if(basionymTaxon == null){
327
                logger.warn(line + "Basionym does not exist as taxon but only as name: " + basionymUuid);
328
            }else{
329
                TaxonName basionymName = basionymTaxon.getName();
330
                taxonName.addBasionym(basionymName);
331
                taxonName.mergeHomotypicGroups(basionymName);  //just in case this is not automatically done
332
                adjustSynonymType(taxonBase, basionymTaxon, line);
333
            }
334
        }
335

    
336
        UUID replacedSynonymUuid = getUuid(record, REPLACED_SYNONYM_UUID, false, line);
337
        if (replacedSynonymUuid != null){
338
            TaxonBase<?> replacedTaxon = getTaxonService().find(replacedSynonymUuid);
339
            if(replacedTaxon == null){
340
                logger.warn(line + "Replaced synonym does not exist as taxon but only as name: " + replacedSynonymUuid);
341
            }else{
342
                TaxonName replacedName = replacedTaxon.getName();
343
                taxonName.addBasionym(replacedName);
344
                taxonName.mergeHomotypicGroups(replacedName);  //just in case this is not automatically done
345
                adjustSynonymType(taxonBase, replacedTaxon, line);
346
            }
347
        }
348

    
349
        UUID nameTypeUuid = getUuid(record, NAME_TYPE_UUID, false, line);
350
        if (nameTypeUuid != null){
351
            TaxonBase<?> typeTaxon = getTaxonService().find(nameTypeUuid);
352
            TaxonName typeName;
353
            if (typeTaxon == null){
354
                typeName = getNameService().find(nameTypeUuid);
355
            }else{
356
                typeName = typeTaxon.getName();
357
            }
358
            //TODO
359
            NameTypeDesignationStatus status = null; //NameTypeDesignationStatus.
360
            taxonName.addNameTypeDesignation(typeName, null, null, null, status, false);
361
        }
362
    }
363

    
364
    private void adjustSynonymType(TaxonBase<?> taxonBase, TaxonBase<?> homotypicTaxon, String line) {
365
        adjustSynonymTypeOrdered(taxonBase, homotypicTaxon, line);
366
        adjustSynonymTypeOrdered(homotypicTaxon, taxonBase, line);
367
    }
368

    
369
    private void adjustSynonymTypeOrdered(TaxonBase<?> firstTaxon, TaxonBase<?> secondTaxon, String line) {
370
        if (firstTaxon == null){
371
            logger.warn(line + "first taxon is null for adjust synonym type");
372
        }else if (secondTaxon == null){
373
            logger.warn(line + "second taxon is null for adjust synonym type");
374
        }else if (secondTaxon.isInstanceOf(Synonym.class)){
375
            Synonym syn = CdmBase.deproxy(secondTaxon, Synonym.class);
376
            if (firstTaxon.equals(syn.getAcceptedTaxon())){
377
                syn.setType(SynonymType.HOMOTYPIC_SYNONYM_OF());
378
            }
379
        }
380
    }
381

    
382
    protected UUID getUuid(Map<String, String> record, String columnName, boolean required, String line) {
383
        String uuidStr = getValue(record, columnName);
384
        if (isNotBlank(uuidStr)){
385
            UUID uuid;
386
            try {
387
                uuid = UUID.fromString(uuidStr);
388
                return uuid;
389
            } catch (Exception e) {
390
                logger.warn(line + "UUID could not be parsed: " + uuidStr);
391
                return null;
392
            }
393
        }else{
394
            if (required){
395
                logger.warn(line + "UUID required but does not exist");
396
            }
397
            return null;
398
        }
399
    }
400

    
401
	private void checkParsed(TaxonName name, String fullName, String nameStr, String line) {
402
		if (name.isProtectedTitleCache() || name.isProtectedFullTitleCache() || name.isProtectedNameCache()) {
403
			logger.warn(line + "Name could not be parsed: " + fullName);
404
		}
405
		if (name.getNomenclaturalReference() != null && name.getNomenclaturalReference().isProtectedTitleCache()){
406
		    logger.warn(line + "Nom ref could not be parsed: " + fullName);
407
		}
408
		if (!name.getTitleCache().equals(nameStr)){
409
            logger.warn(line + "Name part not parsed correctly: " + name.getTitleCache() + "<-> expected: " + nameStr);
410
        }
411
	}
412

    
413
    private TaxonNode rootNode;
414

    
415
    private TaxonNode getClassification(SimpleExcelTaxonImportState<CONFIG> state) {
416
        if (rootNode == null){
417
            logger.warn("Load root node");
418
            rootNode = getTaxonNodeService().find(UUID.fromString("3ee689d2-17c2-4f02-9905-7092a45aa1b9"));
419
        }
420
        if (rootNode == null){
421
            logger.warn("Create root node");
422
            Reference sec = getSecReference(state);
423
            String classificationName = state.getConfig().getClassificationName();
424
            Language language = Language.DEFAULT();
425
            Classification classification = Classification.NewInstance(classificationName, sec, language);
426
            classification.setUuid(state.getConfig().getClassificationUuid());
427
            classification.getRootNode().setUuid(rootUuid);
428
            getClassificationService().save(classification);
429

    
430
            rootNode = classification.getRootNode();
431
        }
432
        return rootNode;
433
    }
434

    
435
    private Reference getSecReference(SimpleExcelTaxonImportState<CONFIG> state) {
436
        if (this.secReference == null){
437
            logger.warn("Load sec ref");
438
            this.secReference = getPersistentReference(state.getConfig().getSecReference());
439
            if (this.secReference == null){
440
                logger.warn("Sec ref is null");
441
            }
442
        }
443
        return this.secReference;
444
    }
445

    
446
    private Reference getSourceCitation(SimpleExcelTaxonImportState<CONFIG> state) {
447
        if (this.sourceReference == null){
448
            this.sourceReference = getPersistentReference(state.getConfig().getSourceReference());
449
            this.sourceReference.setInReference(getSecReference(state));  //special for Uzbekistan
450
        }
451
        return this.sourceReference;
452
    }
453

    
454
    private Reference getPersistentReference(Reference reference) {
455
        Reference result = getReferenceService().find(reference.getUuid());
456
        logger.warn("Loaded persistent reference: "+ reference.getUuid());
457
        if (result == null){
458
            logger.warn("Persistent reference is null: " + reference.getUuid());
459
            result = reference;
460
            getReferenceService().saveOrUpdate(result);
461
        }
462
        return result;
463
    }
464

    
465
    private void replaceNameAuthorsAndReferences(SimpleExcelTaxonImportState<CONFIG> state, INonViralName name) {
466
        state.getDeduplicationHelper().replaceAuthorNamesAndNomRef(state, name);
467
    }
468

    
469

    
470
    @Override
471
    protected IdentifiableSource makeOriginalSource(SimpleExcelTaxonImportState<CONFIG> state) {
472
    	String noStr = getValue(state.getOriginalRecord(), "taxonUuid");
473
        return IdentifiableSource.NewDataImportInstance(noStr, "taxonUuid", getSourceCitation(state));
474
    }
475

    
476
}
(1-1/2)