Project

General

Profile

Download (16.4 KB) Statistics
| Branch: | Revision:
1
// $Id$
2
/**
3
* Copyright (C) 2017 EDIT
4
* European Distributed Institute of Taxonomy
5
* http://www.e-taxonomy.eu
6
*
7
* The contents of this file are subject to the Mozilla Public License Version 1.1
8
* See LICENSE.TXT at the top of this package for the full license terms.
9
*/
10
package eu.etaxonomy.cdm.io.bogota;
11

    
12
import java.util.Map;
13
import java.util.UUID;
14

    
15
import org.apache.log4j.Logger;
16
import org.springframework.stereotype.Component;
17
import org.springframework.transaction.TransactionStatus;
18

    
19
import eu.etaxonomy.cdm.common.CdmUtils;
20
import eu.etaxonomy.cdm.io.common.utils.ImportDeduplicationHelper;
21
import eu.etaxonomy.cdm.io.mexico.SimpleExcelTaxonImport;
22
import eu.etaxonomy.cdm.io.mexico.SimpleExcelTaxonImportState;
23
import eu.etaxonomy.cdm.model.common.IdentifiableSource;
24
import eu.etaxonomy.cdm.model.common.Language;
25
import eu.etaxonomy.cdm.model.name.IBotanicalName;
26
import eu.etaxonomy.cdm.model.name.Rank;
27
import eu.etaxonomy.cdm.model.name.TaxonNameFactory;
28
import eu.etaxonomy.cdm.model.reference.Reference;
29
import eu.etaxonomy.cdm.model.taxon.Classification;
30
import eu.etaxonomy.cdm.model.taxon.ITaxonTreeNode;
31
import eu.etaxonomy.cdm.model.taxon.Synonym;
32
import eu.etaxonomy.cdm.model.taxon.SynonymType;
33
import eu.etaxonomy.cdm.model.taxon.Taxon;
34
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
35
import eu.etaxonomy.cdm.strategy.homotypicgroup.BasionymRelationCreator;
36
import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImpl;
37

    
38
/**
39
 * @author a.mueller
40
 * @since 21.04.2017
41
 *
42
 */
43
@Component
44
public class BogotaChecklistTaxonImport<CONFIG extends BogotaChecklistImportConfigurator>
45
        extends SimpleExcelTaxonImport<CONFIG> {
46

    
47
    private static final long serialVersionUID = -884838817884874228L;
48
    private static final Logger logger = Logger.getLogger(BogotaChecklistTaxonImport.class);
49

    
50
    private static final String ID_COL = "#";
51
    private static final String AUTHOR = "Autor";
52
    private static final String NAME = "Nombre";
53
    private static final String GENUS = "Género";
54
    private static final String FAMILIA = "Familia";
55
    private static final String INFRASPECIFIC = "Taxones infraespecíficos";
56
    private static final String SINONIMOS = "Sinonimos";
57

    
58
    private static UUID rootUuid = UUID.fromString("d66eda18-4c11-4472-bfe8-f6cd5ed95c9f");
59
    private static UUID plantaeUuid = UUID.fromString("032fc183-eb4f-4f19-a290-28597a849096");
60

    
61
    @SuppressWarnings("unchecked")
62
    private ImportDeduplicationHelper<SimpleExcelTaxonImportState<?>> deduplicationHelper
63
           = (ImportDeduplicationHelper<SimpleExcelTaxonImportState<?>>)ImportDeduplicationHelper.NewStandaloneInstance();
64

    
65
    private String lastGenus;
66
    private NonViralNameParserImpl parser = NonViralNameParserImpl.NewInstance();
67
    private BasionymRelationCreator basionymCreator = new BasionymRelationCreator();
68

    
69

    
70
    @Override
71
    protected String getWorksheetName() {
72
        return "Resultados Busqueda Avanzada";
73
    }
74

    
75
    private boolean isFirst = true;
76
    private TransactionStatus tx = null;
77

    
78
    /**
79
     * {@inheritDoc}
80
     */
81
    @Override
82
    protected void firstPass(SimpleExcelTaxonImportState<CONFIG> state) {
83
        if (isFirst){
84
            tx = this.startTransaction();
85
            isFirst = false;
86
        }
87

    
88
        String line = state.getCurrentLine() + ": ";
89
        Map<String, String> record = state.getOriginalRecord();
90

    
91
        String noStr = getValue(record, ID_COL);
92

    
93
        //species
94
        TaxonNode taxonNode = makeTaxon(state, line, record, noStr);
95

    
96
        if (taxonNode != null){
97
            //synonyms
98
            makeSynonyms(state, record, line, taxonNode.getTaxon(), noStr);
99

    
100
            //infraspecific
101
            makeInfraSpecific(state, record, line, taxonNode, noStr);
102
        }else{
103
            logger.warn(line + "No taxon node given");
104
        }
105
    }
106

    
107

    
108
    @Override
109
    protected void secondPass(SimpleExcelTaxonImportState<CONFIG> state) {
110
        if (tx != null){
111
            this.commitTransaction(tx);
112
            tx = null;
113
        }
114
    }
115

    
116
    /**
117
     * @param state
118
     * @param record
119
     * @param line
120
     * @param taxon
121
     */
122
    private void makeSynonyms(SimpleExcelTaxonImportState<CONFIG> state, Map<String, String> record, String line,
123
            Taxon taxon, String noStr) {
124

    
125
        String synonymsStr = getValue(record, SINONIMOS);
126
        if (synonymsStr != null){
127
            String[] splits = synonymsStr.split(",");
128
            for(String split : splits){
129
                split = split.trim();
130
                boolean isMisapplied = split.contains("auct.") || split.contains(" sensu ");
131
                if (split.endsWith(" None")){
132
                    split = split.replace(" None", "").trim();
133
                }
134
                if (isMisapplied){
135
                    handleSingleMisapplied(state, split, line, taxon, noStr);
136
                }else{
137
                    handleSingleSynonym(state, split, line, taxon, noStr);
138
                }
139
            }
140
        }
141
        basionymCreator.invoke(taxon);
142
    }
143

    
144
    /**
145
     * @param state
146
     * @param trim
147
     * @param line
148
     * @param taxon
149
     * @param noStr
150
     */
151
    private void handleSingleMisapplied(SimpleExcelTaxonImportState<CONFIG> state, String nameStr, String line,
152
            Taxon taxon, String noStr) {
153
        Rank rank = Rank.SPECIES();
154
        String AUCT_NON = "auct. non ";
155
        String auctStr = nameStr.contains(AUCT_NON)? AUCT_NON: nameStr.endsWith("auct.")? "auct.": null;
156
        boolean auctRequired = false;
157
        if (auctStr == null){
158
            auctRequired = true;
159
            if (nameStr.endsWith("auct.colomb.")){
160
                nameStr = nameStr.replace(" auct.colomb.", "");
161
                auctStr = "auct.colomb.";
162
            }else if (nameStr.endsWith(" [auct.mult.non Sw.]")){
163
                nameStr = nameStr.replace(" [auct.mult.non Sw.]", "");
164
                auctStr = "[auct.mult.non Sw.]";
165
            }else if (nameStr.endsWith(" auct.pr.p.")){
166
                nameStr = nameStr.replace(" auct.pr.p.", "");
167
                auctStr = "auct.pr.p.";
168
            }else if (nameStr.contains(" sensu ")){
169
                logger.warn(line + "sensu not yet handled correctly:" +  nameStr);
170
                auctRequired = false;
171
            }else{
172
                auctRequired = false;
173
                logger.warn(line + "auct. not recognized: " + nameStr);
174
            }
175

    
176
        }else{
177
            nameStr = nameStr.replace(auctStr, "").trim();
178
        }
179
        IBotanicalName name = (IBotanicalName)parser.parseFullName(nameStr, state.getConfig().getNomenclaturalCode(), rank);
180
        name.addImportSource(noStr, getNamespace(), getSourceCitation(state), null);
181
        name = deduplicationHelper.getExistingName(state, name);
182
        if (name.isProtectedTitleCache()){
183
            logger.warn(line + "Misapplied name could not be parsed: " + nameStr);
184
        }
185
        deduplicationHelper.replaceAuthorNamesAndNomRef(state, name);
186

    
187
        Taxon misApp = Taxon.NewInstance(name, null);
188
        if (auctRequired){
189
            misApp.setAppendedPhrase(auctStr);
190
        }
191
        misApp.addImportSource(noStr, getNamespace(), getSourceCitation(state), null);
192
        taxon.addMisappliedName(misApp, state.getConfig().getSecReference(), null);
193
    }
194

    
195

    
196
    /**
197
     * @param col
198
     * @return
199
     */
200
    private String getNamespace() {
201
        return getWorksheetName()+"."+ ID_COL;
202
    }
203

    
204

    
205
    /**
206
     * @param state
207
     * @param record
208
     * @param line
209
     * @param taxon
210
     * @param noStr
211
     */
212
    private void handleSingleSynonym(SimpleExcelTaxonImportState<CONFIG> state, String nameStr,
213
            String line, Taxon taxon, String noStr) {
214
        Rank rank = Rank.SPECIES();
215
        IBotanicalName name = (IBotanicalName)parser.parseFullName(nameStr, state.getConfig().getNomenclaturalCode(), rank);
216
        name.addImportSource(noStr, getNamespace(), getSourceCitation(state), null);
217
        name = deduplicationHelper.getExistingName(state, name);
218
        if (name.isProtectedTitleCache()){
219
            logger.warn(line + "Synonym could not be parsed: " + nameStr);
220
        }
221
        deduplicationHelper.replaceAuthorNamesAndNomRef(state, name);
222

    
223
        Synonym synonym = Synonym.NewInstance(name, getSecReference(state));
224
        synonym.addImportSource(noStr, getNamespace(), getSourceCitation(state), null);
225
        taxon.addSynonym(synonym, SynonymType.SYNONYM_OF());
226
    }
227

    
228

    
229
    /**
230
     * @param state
231
     * @param line
232
     * @param record
233
     * @param taxon
234
     * @param noStr
235
     */
236
    private void makeInfraSpecific(SimpleExcelTaxonImportState<CONFIG> state, Map<String, String> record, String line,
237
            TaxonNode speciesNode, String noStr) {
238
        String subSpeciesStr = getValue(record, INFRASPECIFIC);
239
        if (subSpeciesStr != null){
240
            String[] splits = subSpeciesStr.split(",");
241
            for(String split : splits){
242
                if (split.endsWith(" None")){
243
                    split = split.replace(" None", "").trim();
244
                }
245
                Rank rank = Rank.SUBSPECIES();
246
                IBotanicalName name = (IBotanicalName)parser.parseFullName(split.trim(), state.getConfig().getNomenclaturalCode(), rank);
247
                name.addImportSource(noStr, getNamespace(), getSourceCitation(state), null);
248
                name = deduplicationHelper.getExistingName(state, name);
249
                if (name.isProtectedTitleCache()){
250
                    logger.warn(line + "Infraspecific taxon could not be parsed: " + split.trim());
251
                }
252
                deduplicationHelper.replaceAuthorNamesAndNomRef(state, name);
253

    
254
                Taxon subSpecies = Taxon.NewInstance(name, getSecReference(state));
255
                subSpecies.addImportSource(noStr, getNamespace(), getSourceCitation(state), null);
256
                TaxonNode subSpeciesNode = speciesNode.addChildTaxon(subSpecies, getSecReference(state), null);
257
                getTaxonNodeService().save(subSpeciesNode);
258
            }
259
        }
260
    }
261

    
262
    /**
263
     * @param state
264
     * @param line
265
     * @param record
266
     * @param noStr
267
     * @return
268
     */
269
    private TaxonNode makeTaxon(SimpleExcelTaxonImportState<CONFIG> state, String line, Map<String, String> record,
270
            String noStr) {
271

    
272
        TaxonNode familyTaxon = getFamilyTaxon(record, state);
273
        if (familyTaxon == null){
274
            logger.warn(line + "Family not created: " + record.get(FAMILIA));
275
        }
276

    
277
        String genusStr = getValue(record, GENUS);
278
        String nameStr = getValue(record, NAME);
279
        String speciesAuthorStr = getValue(record, AUTHOR);
280

    
281
        nameStr = CdmUtils.concat(" ", nameStr, speciesAuthorStr);
282
        Rank rank = Rank.SPECIES();
283
        IBotanicalName name = (IBotanicalName)parser.parseFullName(nameStr, state.getConfig().getNomenclaturalCode(), rank);
284
        name.addImportSource(noStr, getNamespace(), getSourceCitation(state), null);
285
        name = deduplicationHelper.getExistingName(state, name);
286
        if (name.isProtectedTitleCache()){
287
            logger.warn(line + "Name could not be parsed: " + nameStr);
288
        }
289
        deduplicationHelper.replaceAuthorNamesAndNomRef(state, name);
290

    
291
        Taxon taxon = Taxon.NewInstance(name, getSecReference(state));
292

    
293
        taxon.addImportSource(noStr, getNamespace(), getSourceCitation(state), null);
294

    
295
        String parentStr = genusStr;
296
        boolean genusAsBefore = genusStr.equals(lastGenus);
297
        TaxonNode parent = getParent(state, parentStr);
298
        TaxonNode newNode;
299
        if (parent != null){
300
            if (genusAsBefore ){
301
                //everything as expected
302
                newNode = parent.addChildTaxon(taxon, getSecReference(state), null);
303
                getTaxonNodeService().save(newNode);
304
            }else{
305
                logger.warn(line + "Unexpected non-missing parent");
306
                newNode = null;
307
            }
308
        }else{
309
            if (genusAsBefore){
310
                logger.warn(line + "Unexpected missing genus parent");
311
                newNode = null;
312
            }else{
313
                parent = makeGenusNode(state, record, genusStr);
314
                newNode = parent.addChildTaxon(taxon, getSecReference(state), null);
315
                getTaxonNodeService().save(newNode);
316
            }
317
        }
318

    
319
        this.lastGenus = genusStr;
320
        return newNode;
321
    }
322

    
323
    /**
324
     * @param record
325
     * @param state
326
     * @return
327
     */
328
    private TaxonNode getFamilyTaxon(Map<String, String> record, SimpleExcelTaxonImportState<CONFIG> state) {
329
        String familyStr = getValue(record, FAMILIA);
330
        if (familyStr == null){
331
            return null;
332
        }
333
        familyStr = familyStr.trim();
334

    
335
        Taxon family = state.getHigherTaxon(familyStr);
336
        TaxonNode familyNode;
337
        if (family != null){
338
            familyNode = family.getTaxonNodes().iterator().next();
339
        }else{
340
            IBotanicalName name = makeFamilyName(state, familyStr);
341
            Reference sec = getSecReference(state);
342
            family = Taxon.NewInstance(name, sec);
343

    
344
            ITaxonTreeNode classificationNode = getClassification(state);
345
            familyNode = classificationNode.addChildTaxon(family, sec, null);
346
            state.putHigherTaxon(familyStr, family);
347
            getTaxonNodeService().save(familyNode);
348
        }
349

    
350
        return familyNode;
351
    }
352

    
353

    
354
    private TaxonNode rootNode;
355
    private TaxonNode getClassification(SimpleExcelTaxonImportState<CONFIG> state) {
356
        if (rootNode == null){
357
            Reference sec = getSecReference(state);
358
            String classificationName = state.getConfig().getClassificationName();
359
            Language language = Language.DEFAULT();
360
            Classification classification = Classification.NewInstance(classificationName, sec, language);
361
            classification.setUuid(state.getConfig().getClassificationUuid());
362
            classification.getRootNode().setUuid(rootUuid);
363

    
364
            IBotanicalName plantaeName = TaxonNameFactory.NewBotanicalInstance(Rank.KINGDOM());
365
            plantaeName.setGenusOrUninomial("Plantae");
366
            Taxon plantae = Taxon.NewInstance(plantaeName, sec);
367
            TaxonNode plantaeNode = classification.addChildTaxon(plantae, null, null);
368
            plantaeNode.setUuid(plantaeUuid);
369
            getClassificationService().save(classification);
370

    
371
            rootNode = plantaeNode;
372
        }
373
        return rootNode;
374
    }
375

    
376

    
377
    protected IBotanicalName makeFamilyName(SimpleExcelTaxonImportState<CONFIG> state, String famStr) {
378
        IBotanicalName name = TaxonNameFactory.NewBotanicalInstance(Rank.FAMILY());
379
        famStr = decapitalize(famStr);
380
        name.setGenusOrUninomial(famStr);
381
        name.addSource(makeOriginalSource(state));
382
        return name;
383
    }
384

    
385
    /**
386
     * @param state
387
     * @return
388
     */
389
    @Override
390
    protected IdentifiableSource makeOriginalSource(SimpleExcelTaxonImportState<CONFIG> state) {
391
        return IdentifiableSource.NewDataImportInstance(getValue(state.getOriginalRecord(),ID_COL), getNamespace(), state.getConfig().getSourceReference());
392
    }
393

    
394
    /**
395
     * @param famStr
396
     * @return
397
     */
398
    private String decapitalize(String famStr) {
399
        String result = famStr.substring(0,1) + famStr.substring(1).toLowerCase();
400
        return result;
401
    }
402

    
403

    
404
    protected Reference getSecReference(SimpleExcelTaxonImportState<CONFIG> state) {
405
        return state.getConfig().getSecReference();
406
    }
407

    
408
    /**
409
     * @param state
410
     * @return
411
     */
412
    protected Reference getSourceCitation(SimpleExcelTaxonImportState<CONFIG> state) {
413
        return state.getConfig().getSourceReference();
414
    }
415

    
416
    /**
417
     * @param state
418
     * @param parentStr
419
     * @return
420
     */
421
    private TaxonNode getParent(SimpleExcelTaxonImportState<CONFIG> state, String parentStr) {
422
        Taxon taxon = state.getHigherTaxon(parentStr);
423

    
424
        return taxon == null ? null : taxon.getTaxonNodes().iterator().next();
425
    }
426

    
427
    /**
428
     * @param state
429
     * @param record
430
     * @param genusStr
431
     * @return
432
     */
433
    private TaxonNode makeGenusNode(SimpleExcelTaxonImportState<CONFIG> state,
434
            Map<String, String> record, String genusStr) {
435
        IBotanicalName name = TaxonNameFactory.NewBotanicalInstance(Rank.GENUS());
436
        name.setGenusOrUninomial(genusStr);
437
        Taxon genus = Taxon.NewInstance(name, getSecReference(state));
438
        TaxonNode family = getFamilyTaxon(record, state);
439
        TaxonNode genusNode = family.addChildTaxon(genus, getSecReference(state), null);
440
        state.putHigherTaxon(genusStr, genus);
441
        genus.addSource(makeOriginalSource(state));
442
        getTaxonNodeService().save(genusNode);
443
        return genusNode;
444
    }
445

    
446
}
(2-2/6)