Project

General

Profile

Download (16.3 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.mexico.SimpleExcelTaxonImport;
21
import eu.etaxonomy.cdm.io.mexico.SimpleExcelTaxonImportState;
22
import eu.etaxonomy.cdm.model.common.IdentifiableSource;
23
import eu.etaxonomy.cdm.model.common.Language;
24
import eu.etaxonomy.cdm.model.name.IBotanicalName;
25
import eu.etaxonomy.cdm.model.name.Rank;
26
import eu.etaxonomy.cdm.model.name.TaxonNameFactory;
27
import eu.etaxonomy.cdm.model.reference.Reference;
28
import eu.etaxonomy.cdm.model.taxon.Classification;
29
import eu.etaxonomy.cdm.model.taxon.ITaxonTreeNode;
30
import eu.etaxonomy.cdm.model.taxon.Synonym;
31
import eu.etaxonomy.cdm.model.taxon.SynonymType;
32
import eu.etaxonomy.cdm.model.taxon.Taxon;
33
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
34
import eu.etaxonomy.cdm.strategy.homotypicgroup.BasionymRelationCreator;
35
import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImpl;
36

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

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

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

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

    
59
    private String lastGenus;
60
    private NonViralNameParserImpl parser = NonViralNameParserImpl.NewInstance();
61
    private BasionymRelationCreator basionymCreator = new BasionymRelationCreator();
62

    
63

    
64
    @Override
65
    protected String getWorksheetName(CONFIG config) {
66
        return "Resultados Busqueda Avanzada";
67
    }
68

    
69
    private boolean isFirst = true;
70
    private TransactionStatus tx = null;
71

    
72
    @Override
73
    protected void firstPass(SimpleExcelTaxonImportState<CONFIG> state) {
74
        if (isFirst){
75
            tx = this.startTransaction();
76
            isFirst = false;
77
        }
78

    
79
        String line = state.getCurrentLine() + ": ";
80
        Map<String, String> record = state.getOriginalRecord();
81

    
82
        String noStr = getValue(record, ID_COL);
83

    
84
        //species
85
        TaxonNode taxonNode = makeTaxon(state, line, record, noStr);
86

    
87
        if (taxonNode != null){
88
            //synonyms
89
            makeSynonyms(state, record, line, taxonNode.getTaxon(), noStr);
90

    
91
            //infraspecific
92
            makeInfraSpecific(state, record, line, taxonNode, noStr);
93
        }else{
94
            logger.warn(line + "No taxon node given");
95
        }
96
    }
97

    
98

    
99
    @Override
100
    protected void secondPass(SimpleExcelTaxonImportState<CONFIG> state) {
101
        if (tx != null){
102
            this.commitTransaction(tx);
103
            tx = null;
104
        }
105
    }
106

    
107
    /**
108
     * @param state
109
     * @param record
110
     * @param line
111
     * @param taxon
112
     */
113
    private void makeSynonyms(SimpleExcelTaxonImportState<CONFIG> state, Map<String, String> record, String line,
114
            Taxon taxon, String noStr) {
115

    
116
        String synonymsStr = getValue(record, SINONIMOS);
117
        if (synonymsStr != null){
118
            String[] splits = synonymsStr.split(",");
119
            for(String split : splits){
120
                split = split.trim();
121
                boolean isMisapplied = split.contains("auct.") || split.contains(" sensu ");
122
                if (split.endsWith(" None")){
123
                    split = split.replace(" None", "").trim();
124
                }
125
                if (isMisapplied){
126
                    handleSingleMisapplied(state, split, line, taxon, noStr);
127
                }else{
128
                    handleSingleSynonym(state, split, line, taxon, noStr);
129
                }
130
            }
131
        }
132
        basionymCreator.invoke(taxon);
133
    }
134

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

    
167
        }else{
168
            nameStr = nameStr.replace(auctStr, "").trim();
169
        }
170
        IBotanicalName name = (IBotanicalName)parser.parseFullName(nameStr, state.getConfig().getNomenclaturalCode(), rank);
171
        name.addImportSource(noStr, getNamespace(state.getConfig()), getSourceCitation(state), null);
172
        name = state.getDeduplicationHelper().getExistingName(state, name);
173
        if (name.isProtectedTitleCache()){
174
            logger.warn(line + "Misapplied name could not be parsed: " + nameStr);
175
        }
176
        state.getDeduplicationHelper().replaceAuthorNamesAndNomRef(state, name);
177

    
178
        Taxon misApp = Taxon.NewInstance(name, null);
179
        if (auctRequired){
180
            misApp.setAppendedPhrase(auctStr);
181
        }
182
        misApp.addImportSource(noStr, getNamespace(state.getConfig()),
183
                getSourceCitation(state), null);
184
        taxon.addMisappliedName(misApp, state.getConfig().getSecReference(), null);
185
    }
186

    
187

    
188
    /**
189
     * @param col
190
     * @return
191
     */
192
    private String getNamespace(CONFIG config) {
193
        return getWorksheetName(config)+"."+ ID_COL;
194
    }
195

    
196

    
197
    /**
198
     * @param state
199
     * @param record
200
     * @param line
201
     * @param taxon
202
     * @param noStr
203
     */
204
    private void handleSingleSynonym(SimpleExcelTaxonImportState<CONFIG> state, String nameStr,
205
            String line, Taxon taxon, String noStr) {
206
        Rank rank = Rank.SPECIES();
207
        IBotanicalName name = (IBotanicalName)parser.parseFullName(nameStr, state.getConfig().getNomenclaturalCode(), rank);
208
        name.addImportSource(noStr, getNamespace(state.getConfig()), getSourceCitation(state), null);
209
        name = state.getDeduplicationHelper().getExistingName(state, name);
210
        if (name.isProtectedTitleCache()){
211
            logger.warn(line + "Synonym could not be parsed: " + nameStr);
212
        }
213
        state.getDeduplicationHelper().replaceAuthorNamesAndNomRef(state, name);
214

    
215
        Synonym synonym = Synonym.NewInstance(name, getSecReference(state));
216
        synonym.addImportSource(noStr, getNamespace(state.getConfig()), getSourceCitation(state), null);
217
        taxon.addSynonym(synonym, SynonymType.SYNONYM_OF());
218
    }
219

    
220

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

    
246
                Taxon subSpecies = Taxon.NewInstance(name, getSecReference(state));
247
                subSpecies.addImportSource(noStr, getNamespace(state.getConfig()), getSourceCitation(state), null);
248
                TaxonNode subSpeciesNode = speciesNode.addChildTaxon(subSpecies, getSecReference(state), null);
249
                getTaxonNodeService().save(subSpeciesNode);
250
            }
251
        }
252
    }
253

    
254
    /**
255
     * @param state
256
     * @param line
257
     * @param record
258
     * @param noStr
259
     * @return
260
     */
261
    private TaxonNode makeTaxon(SimpleExcelTaxonImportState<CONFIG> state, String line, Map<String, String> record,
262
            String noStr) {
263

    
264
        TaxonNode familyTaxon = getFamilyTaxon(record, state);
265
        if (familyTaxon == null){
266
            logger.warn(line + "Family not created: " + record.get(FAMILIA));
267
        }
268

    
269
        String genusStr = getValue(record, GENUS);
270
        String nameStr = getValue(record, NAME);
271
        String speciesAuthorStr = getValue(record, AUTHOR);
272

    
273
        nameStr = CdmUtils.concat(" ", nameStr, speciesAuthorStr);
274
        Rank rank = Rank.SPECIES();
275
        IBotanicalName name = (IBotanicalName)parser.parseFullName(nameStr, state.getConfig().getNomenclaturalCode(), rank);
276
        name.addImportSource(noStr, getNamespace(state.getConfig()), getSourceCitation(state), null);
277
        name = state.getDeduplicationHelper().getExistingName(state, name);
278
        if (name.isProtectedTitleCache()){
279
            logger.warn(line + "Name could not be parsed: " + nameStr);
280
        }
281
        state.getDeduplicationHelper().replaceAuthorNamesAndNomRef(state, name);
282

    
283
        Taxon taxon = Taxon.NewInstance(name, getSecReference(state));
284

    
285
        taxon.addImportSource(noStr, getNamespace(state.getConfig()), getSourceCitation(state), null);
286

    
287
        String parentStr = genusStr;
288
        boolean genusAsBefore = genusStr.equals(lastGenus);
289
        TaxonNode parent = getParent(state, parentStr);
290
        TaxonNode newNode;
291
        if (parent != null){
292
            if (genusAsBefore ){
293
                //everything as expected
294
                newNode = parent.addChildTaxon(taxon, getSecReference(state), null);
295
                getTaxonNodeService().save(newNode);
296
            }else{
297
                logger.warn(line + "Unexpected non-missing parent");
298
                newNode = null;
299
            }
300
        }else{
301
            if (genusAsBefore){
302
                logger.warn(line + "Unexpected missing genus parent");
303
                newNode = null;
304
            }else{
305
                parent = makeGenusNode(state, record, genusStr);
306
                newNode = parent.addChildTaxon(taxon, getSecReference(state), null);
307
                getTaxonNodeService().save(newNode);
308
            }
309
        }
310

    
311
        this.lastGenus = genusStr;
312
        return newNode;
313
    }
314

    
315
    /**
316
     * @param record
317
     * @param state
318
     * @return
319
     */
320
    private TaxonNode getFamilyTaxon(Map<String, String> record, SimpleExcelTaxonImportState<CONFIG> state) {
321
        String familyStr = getValue(record, FAMILIA);
322
        if (familyStr == null){
323
            return null;
324
        }
325
        familyStr = familyStr.trim();
326

    
327
        Taxon family = state.getHigherTaxon(familyStr);
328
        TaxonNode familyNode;
329
        if (family != null){
330
            familyNode = family.getTaxonNodes().iterator().next();
331
        }else{
332
            IBotanicalName name = makeFamilyName(state, familyStr);
333
            Reference sec = getSecReference(state);
334
            family = Taxon.NewInstance(name, sec);
335

    
336
            ITaxonTreeNode classificationNode = getClassification(state);
337
            familyNode = classificationNode.addChildTaxon(family, sec, null);
338
            state.putHigherTaxon(familyStr, family);
339
            getTaxonNodeService().save(familyNode);
340
        }
341

    
342
        return familyNode;
343
    }
344

    
345

    
346
    private TaxonNode rootNode;
347
    private TaxonNode getClassification(SimpleExcelTaxonImportState<CONFIG> state) {
348
        if (rootNode == null){
349
            Reference sec = getSecReference(state);
350
            String classificationName = state.getConfig().getClassificationName();
351
            Language language = Language.DEFAULT();
352
            Classification classification = Classification.NewInstance(classificationName, sec, language);
353
            classification.setUuid(state.getConfig().getClassificationUuid());
354
            classification.getRootNode().setUuid(rootUuid);
355

    
356
            IBotanicalName plantaeName = TaxonNameFactory.NewBotanicalInstance(Rank.KINGDOM());
357
            plantaeName.setGenusOrUninomial("Plantae");
358
            Taxon plantae = Taxon.NewInstance(plantaeName, sec);
359
            TaxonNode plantaeNode = classification.addChildTaxon(plantae, null, null);
360
            plantaeNode.setUuid(plantaeUuid);
361
            getClassificationService().save(classification);
362

    
363
            rootNode = plantaeNode;
364
        }
365
        return rootNode;
366
    }
367

    
368

    
369
    protected IBotanicalName makeFamilyName(SimpleExcelTaxonImportState<CONFIG> state, String famStr) {
370
        IBotanicalName name = TaxonNameFactory.NewBotanicalInstance(Rank.FAMILY());
371
        famStr = decapitalize(famStr);
372
        name.setGenusOrUninomial(famStr);
373
        name.addSource(makeOriginalSource(state));
374
        return name;
375
    }
376

    
377
    /**
378
     * @param state
379
     * @return
380
     */
381
    @Override
382
    protected IdentifiableSource makeOriginalSource(SimpleExcelTaxonImportState<CONFIG> state) {
383
        return IdentifiableSource.NewDataImportInstance(getValue(state.getOriginalRecord(),ID_COL),
384
                getNamespace(state.getConfig()), state.getConfig().getSourceReference());
385
    }
386

    
387
    /**
388
     * @param famStr
389
     * @return
390
     */
391
    private String decapitalize(String famStr) {
392
        String result = famStr.substring(0,1) + famStr.substring(1).toLowerCase();
393
        return result;
394
    }
395

    
396

    
397
    protected Reference getSecReference(SimpleExcelTaxonImportState<CONFIG> state) {
398
        return state.getConfig().getSecReference();
399
    }
400

    
401
    /**
402
     * @param state
403
     * @return
404
     */
405
    protected Reference getSourceCitation(SimpleExcelTaxonImportState<CONFIG> state) {
406
        return state.getConfig().getSourceReference();
407
    }
408

    
409
    /**
410
     * @param state
411
     * @param parentStr
412
     * @return
413
     */
414
    private TaxonNode getParent(SimpleExcelTaxonImportState<CONFIG> state, String parentStr) {
415
        Taxon taxon = state.getHigherTaxon(parentStr);
416

    
417
        return taxon == null ? null : taxon.getTaxonNodes().iterator().next();
418
    }
419

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

    
439
}
(2-2/6)