Project

General

Profile

Download (15.5 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.HashMap;
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.Language;
24
import eu.etaxonomy.cdm.model.name.BotanicalName;
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
 * @date 21.04.2017
40
 *
41
 */
42
@Component
43
public class BogotaChecklistTaxonImport<CONFIG extends BogotaChecklistImportConfigurator>
44
        extends SimpleExcelTaxonImport<CONFIG> {
45

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

    
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

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

    
57
    @SuppressWarnings("unchecked")
58
    private ImportDeduplicationHelper<SimpleExcelTaxonImportState<?>> deduplicationHelper = (ImportDeduplicationHelper<SimpleExcelTaxonImportState<?>>)ImportDeduplicationHelper.NewStandaloneInstance();
59

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

    
64

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

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

    
73
    /**
74
     * {@inheritDoc}
75
     */
76
    @Override
77
    protected void firstPass(SimpleExcelTaxonImportState<CONFIG> state) {
78
        if (isFirst){
79
            tx = this.startTransaction();
80
            isFirst = false;
81
        }
82

    
83
        String line = state.getCurrentLine() + ": ";
84
        HashMap<String, String> record = state.getOriginalRecord();
85

    
86
        String noStr = getValue(record, "#");
87

    
88
        //species
89
        TaxonNode taxonNode = makeTaxon(state, line, record, noStr);
90
        if (taxonNode != null){
91
            //synonyms
92
            makeSynonyms(state, record, line, taxonNode.getTaxon(), noStr);
93

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

    
101

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

    
110
    /**
111
     * @param state
112
     * @param record
113
     * @param line
114
     * @param taxon
115
     */
116
    private void makeSynonyms(SimpleExcelTaxonImportState<CONFIG> state, HashMap<String, String> record, String line,
117
            Taxon taxon, String noStr) {
118

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

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

    
170
        }else{
171
            nameStr = nameStr.replace(auctStr, "").trim();
172
        }
173
        BotanicalName name = (BotanicalName)parser.parseFullName(nameStr, state.getConfig().getNomenclaturalCode(), rank);
174
        if (name.isProtectedTitleCache()){
175
            logger.warn(line + "Misapplied name could not be parsed: " + nameStr);
176
        }
177
        deduplicationHelper.replaceAuthorNamesAndNomRef(state, name);
178

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

    
188

    
189
    /**
190
     * @param state
191
     * @param record
192
     * @param line
193
     * @param taxon
194
     * @param noStr
195
     */
196
    private void handleSingleSynonym(SimpleExcelTaxonImportState<CONFIG> state, String nameStr,
197
            String line, Taxon taxon, String noStr) {
198
        Rank rank = Rank.SPECIES();
199
        BotanicalName name = (BotanicalName)parser.parseFullName(nameStr, state.getConfig().getNomenclaturalCode(), rank);
200
        if (name.isProtectedTitleCache()){
201
            logger.warn(line + "Synonym could not be parsed: " + nameStr);
202
        }
203
        deduplicationHelper.replaceAuthorNamesAndNomRef(state, name);
204

    
205
        Synonym synonym = Synonym.NewInstance(name, getSecReference(state));
206
        synonym.addImportSource(noStr, getWorksheetName(), getSourceCitation(state), null);
207
        name.addImportSource(noStr, getWorksheetName(), getSourceCitation(state), null);
208
        taxon.addSynonym(synonym, SynonymType.SYNONYM_OF());
209
    }
210

    
211

    
212
    /**
213
     * @param state
214
     * @param line
215
     * @param record
216
     * @param taxon
217
     * @param noStr
218
     */
219
    private void makeInfraSpecific(SimpleExcelTaxonImportState<CONFIG> state, HashMap<String, String> record, String line,
220
            TaxonNode speciesNode, String noStr) {
221
        String subSpeciesStr = getValue(record, "Taxones infraespecíficos");
222
        if (subSpeciesStr != null){
223
            String[] splits = subSpeciesStr.split(",");
224
            for(String split : splits){
225
                if (split.endsWith(" None")){
226
                    split = split.replace(" None", "").trim();
227
                }
228
                Rank rank = Rank.SUBSPECIES();
229
                BotanicalName name = (BotanicalName)parser.parseFullName(split.trim(), state.getConfig().getNomenclaturalCode(), rank);
230
                if (name.isProtectedTitleCache()){
231
                    logger.warn(line + "Infraspecific taxon could not be parsed: " + split.trim());
232
                }
233
                deduplicationHelper.replaceAuthorNamesAndNomRef(state, name);
234

    
235
                Taxon subSpecies = Taxon.NewInstance(name, getSecReference(state));
236
                subSpecies.addImportSource(noStr, getWorksheetName(), getSourceCitation(state), null);
237
                name.addImportSource(noStr, getWorksheetName(), getSourceCitation(state), null);
238
                TaxonNode subSpeciesNode = speciesNode.addChildTaxon(subSpecies, getSecReference(state), null);
239
                getTaxonNodeService().save(subSpeciesNode);
240
            }
241
        }
242
    }
243

    
244
    /**
245
     * @param state
246
     * @param line
247
     * @param record
248
     * @param noStr
249
     * @return
250
     */
251
    private TaxonNode makeTaxon(SimpleExcelTaxonImportState<CONFIG> state, String line, HashMap<String, String> record,
252
            String noStr) {
253

    
254
        TaxonNode familyTaxon = getFamilyTaxon(record, state);
255
        if (familyTaxon == null){
256
            logger.warn(line + "Family not created: " + record.get(FAMILIA));
257
        }
258

    
259
        String genusStr = getValue(record, GENUS);
260
        String nameStr = getValue(record, NAME);
261
        String speciesAuthorStr = getValue(record, AUTHOR);
262

    
263
        nameStr = CdmUtils.concat(" ", nameStr, speciesAuthorStr);
264
        Rank rank = Rank.SPECIES();
265
        BotanicalName name = (BotanicalName)parser.parseFullName(nameStr, state.getConfig().getNomenclaturalCode(), rank);
266
        if (name.isProtectedTitleCache()){
267
            logger.warn(line + "Name could not be parsed: " + nameStr);
268
        }
269
        deduplicationHelper.replaceAuthorNamesAndNomRef(state, name);
270

    
271
        Taxon taxon = Taxon.NewInstance(name, getSecReference(state));
272
        taxon.addImportSource(noStr, getWorksheetName(), getSourceCitation(state), null);
273
        name.addImportSource(noStr, getWorksheetName(), getSourceCitation(state), null);
274

    
275
        String parentStr = genusStr;
276
        boolean genusAsBefore = genusStr.equals(lastGenus);
277
        TaxonNode parent = getParent(state, parentStr);
278
        TaxonNode newNode;
279
        if (parent != null){
280
            if (genusAsBefore ){
281
                //everything as expected
282
                newNode = parent.addChildTaxon(taxon, getSecReference(state), null);
283
                getTaxonNodeService().save(newNode);
284
            }else{
285
                logger.warn(line + "Unexpected non-missing parent");
286
                newNode = null;
287
            }
288
        }else{
289
            if (genusAsBefore){
290
                logger.warn(line + "Unexpected missing genus parent");
291
                newNode = null;
292
            }else{
293
                parent = makeGenusNode(state, record, genusStr);
294
                newNode = parent.addChildTaxon(taxon, getSecReference(state), null);
295
                getTaxonNodeService().save(newNode);
296
            }
297
        }
298

    
299
        this.lastGenus = genusStr;
300
        return newNode;
301
    }
302

    
303
    /**
304
     * @param record
305
     * @param state
306
     * @return
307
     */
308
    private TaxonNode getFamilyTaxon(HashMap<String, String> record, SimpleExcelTaxonImportState<CONFIG> state) {
309
        String familyStr = getValue(record, FAMILIA);
310
        if (familyStr == null){
311
            return null;
312
        }
313
        familyStr = familyStr.trim();
314

    
315
        Taxon family = state.getHigherTaxon(familyStr);
316
        TaxonNode familyNode;
317
        if (family != null){
318
            familyNode = family.getTaxonNodes().iterator().next();
319
        }else{
320
            BotanicalName name = makeFamilyName(state, familyStr);
321
            Reference sec = getSecReference(state);
322
            family = Taxon.NewInstance(name, sec);
323

    
324
            ITaxonTreeNode classificationNode = getClassification(state);
325
            familyNode = classificationNode.addChildTaxon(family, sec, null);
326
            state.putHigherTaxon(familyStr, family);
327
            getTaxonNodeService().save(familyNode);
328
        }
329

    
330
        return familyNode;
331
    }
332

    
333

    
334
    private TaxonNode rootNode;
335
    private TaxonNode getClassification(SimpleExcelTaxonImportState<CONFIG> state) {
336
        if (rootNode == null){
337
            Reference sec = getSecReference(state);
338
            String classificationName = state.getConfig().getClassificationName();
339
            Language language = Language.DEFAULT();
340
            Classification classification = Classification.NewInstance(classificationName, sec, language);
341
            classification.setUuid(state.getConfig().getClassificationUuid());
342
            classification.getRootNode().setUuid(rootUuid);
343

    
344
            BotanicalName plantaeName = TaxonNameFactory.NewBotanicalInstance(Rank.KINGDOM());
345
            plantaeName.setGenusOrUninomial("Plantae");
346
            Taxon plantae = Taxon.NewInstance(plantaeName, sec);
347
            TaxonNode plantaeNode = classification.addChildTaxon(plantae, null, null);
348
            plantaeNode.setUuid(plantaeUuid);
349
            getClassificationService().save(classification);
350

    
351
            rootNode = plantaeNode;
352
        }
353
        return rootNode;
354
    }
355

    
356

    
357
    protected BotanicalName makeFamilyName(SimpleExcelTaxonImportState<CONFIG> state, String famStr) {
358
        BotanicalName name = TaxonNameFactory.NewBotanicalInstance(Rank.FAMILY());
359
        famStr = decapitalize(famStr);
360
        name.setGenusOrUninomial(famStr);
361
        name.addSource(makeOriginalSource(state));
362
        return name;
363
    }
364

    
365
    /**
366
     * @param famStr
367
     * @return
368
     */
369
    private String decapitalize(String famStr) {
370
        String result = famStr.substring(0,1) + famStr.substring(1).toLowerCase();
371
        return result;
372
    }
373

    
374

    
375
    protected Reference getSecReference(SimpleExcelTaxonImportState<CONFIG> state) {
376
        return state.getConfig().getSecReference();
377
    }
378

    
379
    /**
380
     * @param state
381
     * @return
382
     */
383
    protected Reference getSourceCitation(SimpleExcelTaxonImportState<CONFIG> state) {
384
        return state.getConfig().getSourceReference();
385
    }
386

    
387
    /**
388
     * @param state
389
     * @param parentStr
390
     * @return
391
     */
392
    private TaxonNode getParent(SimpleExcelTaxonImportState<CONFIG> state, String parentStr) {
393
        Taxon taxon = state.getHigherTaxon(parentStr);
394

    
395
        return taxon == null ? null : taxon.getTaxonNodes().iterator().next();
396
    }
397

    
398
    /**
399
     * @param state
400
     * @param record
401
     * @param genusStr
402
     * @return
403
     */
404
    private TaxonNode makeGenusNode(SimpleExcelTaxonImportState<CONFIG> state,
405
            HashMap<String, String> record, String genusStr) {
406
        BotanicalName name = TaxonNameFactory.NewBotanicalInstance(Rank.GENUS());
407
        name.setGenusOrUninomial(genusStr);
408
        Taxon genus = Taxon.NewInstance(name, getSecReference(state));
409
        TaxonNode family = getFamilyTaxon(record, state);
410
        TaxonNode genusNode = family.addChildTaxon(genus, getSecReference(state), null);
411
        state.putHigherTaxon(genusStr, genus);
412
        genus.addSource(makeOriginalSource(state));
413
        getTaxonNodeService().save(genusNode);
414
        return genusNode;
415
    }
416

    
417
}
(2-2/2)