Project

General

Profile

Download (33.3 KB) Statistics
| Branch: | Revision:
1
/**
2
 * Copyright (C) 2007 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

    
10
package eu.etaxonomy.cdm.io.redlist.gefaesspflanzen;
11

    
12
import java.sql.ResultSet;
13
import java.sql.SQLException;
14
import java.util.HashMap;
15
import java.util.HashSet;
16
import java.util.Map;
17
import java.util.Set;
18
import java.util.regex.Matcher;
19
import java.util.regex.Pattern;
20

    
21
import org.apache.log4j.Logger;
22
import org.springframework.stereotype.Component;
23

    
24
import eu.etaxonomy.cdm.common.CdmUtils;
25
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
26
import eu.etaxonomy.cdm.io.common.DbImportBase;
27
import eu.etaxonomy.cdm.io.common.IPartitionedIO;
28
import eu.etaxonomy.cdm.io.common.ImportHelper;
29
import eu.etaxonomy.cdm.io.common.ResultSetPartitioner;
30
import eu.etaxonomy.cdm.io.common.mapping.UndefinedTransformerMethodException;
31
import eu.etaxonomy.cdm.model.agent.AgentBase;
32
import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
33
import eu.etaxonomy.cdm.model.common.AnnotatableEntity;
34
import eu.etaxonomy.cdm.model.common.Annotation;
35
import eu.etaxonomy.cdm.model.common.AnnotationType;
36
import eu.etaxonomy.cdm.model.common.CdmBase;
37
import eu.etaxonomy.cdm.model.common.Language;
38
import eu.etaxonomy.cdm.model.common.OrderedTermVocabulary;
39
import eu.etaxonomy.cdm.model.description.CommonTaxonName;
40
import eu.etaxonomy.cdm.model.description.TaxonDescription;
41
import eu.etaxonomy.cdm.model.name.BotanicalName;
42
import eu.etaxonomy.cdm.model.name.CultivarPlantName;
43
import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
44
import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
45
import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
46
import eu.etaxonomy.cdm.model.name.NonViralName;
47
import eu.etaxonomy.cdm.model.name.Rank;
48
import eu.etaxonomy.cdm.model.name.RankClass;
49
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
50
import eu.etaxonomy.cdm.model.taxon.Synonym;
51
import eu.etaxonomy.cdm.model.taxon.Taxon;
52
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
53
import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
54
import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
55
import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImpl;
56

    
57
/**
58
 *
59
 * @author pplitzner
60
 * @date Mar 1, 2016
61
 *
62
 */
63

    
64
@Component
65
@SuppressWarnings("serial")
66
public class RedListGefaesspflanzenImportNames extends DbImportBase<RedListGefaesspflanzenImportState, RedListGefaesspflanzenImportConfigurator> {
67

    
68
    private static final Logger logger = Logger.getLogger(RedListGefaesspflanzenImportNames.class);
69

    
70
    private static final String tableName = "Rote Liste Gefäßpflanzen";
71

    
72
    private static final String pluralString = "names";
73

    
74
    private static final boolean STRICT_TITLE_CHECK = false;
75

    
76
    public RedListGefaesspflanzenImportNames() {
77
        super(tableName, pluralString);
78
    }
79

    
80
    @Override
81
    protected String getIdQuery(RedListGefaesspflanzenImportState state) {
82
        return "SELECT SEQNUM "
83
                + "FROM V_TAXATLAS_D20_EXPORT t "
84
                + " ORDER BY SEQNUM";
85
    }
86

    
87
    @Override
88
    protected String getRecordQuery(RedListGefaesspflanzenImportConfigurator config) {
89
        String result = " SELECT * "
90
                + " FROM V_TAXATLAS_D20_EXPORT t "
91
                + " WHERE t.SEQNUM IN (@IDSET)";
92
        result = result.replace("@IDSET", IPartitionedIO.ID_LIST_TOKEN);
93
        return result;
94
    }
95

    
96
    @Override
97
    protected void doInvoke(RedListGefaesspflanzenImportState state) {
98
        super.doInvoke(state);
99
    }
100

    
101

    
102
    @Override
103
    public boolean doPartition(ResultSetPartitioner partitioner, RedListGefaesspflanzenImportState state) {
104
        ResultSet rs = partitioner.getResultSet();
105
        Set<TaxonNameBase> namesToSave = new HashSet<TaxonNameBase>();
106
        Set<TaxonBase> taxaToSave = new HashSet<TaxonBase>();
107
        try {
108
            while (rs.next()){
109
                makeSingleNameAndTaxon(state, rs, namesToSave, taxaToSave);
110

    
111
            }
112
        } catch (SQLException e) {
113
            e.printStackTrace();
114
        }
115

    
116
        getNameService().saveOrUpdate(namesToSave);
117
        getTaxonService().saveOrUpdate(taxaToSave);
118
        return true;
119
    }
120

    
121
    private void makeSingleNameAndTaxon(RedListGefaesspflanzenImportState state, ResultSet rs, Set<TaxonNameBase> namesToSave, Set<TaxonBase> taxaToSave)
122
            throws SQLException {
123
        long id = rs.getLong(RedListUtil.NAMNR);
124
        String clTaxonString = rs.getString(RedListUtil.CL_TAXON);
125
        String relationE = rs.getString(RedListUtil.E);
126
        String relationW = rs.getString(RedListUtil.W);
127
        String relationK = rs.getString(RedListUtil.K);
128
        String relationAW = rs.getString(RedListUtil.AW);
129
        String relationAO = rs.getString(RedListUtil.AO);
130
        String relationR = rs.getString(RedListUtil.R);
131
        String relationO = rs.getString(RedListUtil.O);
132
        String relationS = rs.getString(RedListUtil.S);
133

    
134
        //---NAME---
135
        NonViralName<?> name = importName(state, rs, namesToSave);
136

    
137

    
138
        //--- AUTHORS ---
139
        importAuthors(state, rs, name);
140

    
141
        //---TAXON---
142
        TaxonBase<?> taxonBase = importTaxon(rs, name, state);
143
        if(taxonBase==null){
144
            RedListUtil.logMessage(id, "Taxon for name "+name+" could not be created.", logger);
145
            return;
146
        }
147

    
148
        //---CONCEPT RELATIONSHIPS---
149
        //E, W, K, AW, AO, R, O, S
150
        cloneTaxon(taxonBase, relationE, RedListUtil.CLASSIFICATION_NAMESPACE_E, taxaToSave, id, state);
151
        cloneTaxon(taxonBase, relationW, RedListUtil.CLASSIFICATION_NAMESPACE_W, taxaToSave, id, state);
152
        cloneTaxon(taxonBase, relationK, RedListUtil.CLASSIFICATION_NAMESPACE_K, taxaToSave, id, state);
153
        cloneTaxon(taxonBase, relationAW, RedListUtil.CLASSIFICATION_NAMESPACE_AW, taxaToSave, id, state);
154
        cloneTaxon(taxonBase, relationAO, RedListUtil.CLASSIFICATION_NAMESPACE_AO, taxaToSave, id, state);
155
        cloneTaxon(taxonBase, relationR, RedListUtil.CLASSIFICATION_NAMESPACE_R, taxaToSave, id, state);
156
        cloneTaxon(taxonBase, relationO, RedListUtil.CLASSIFICATION_NAMESPACE_O, taxaToSave, id, state);
157
        cloneTaxon(taxonBase, relationS, RedListUtil.CLASSIFICATION_NAMESPACE_S, taxaToSave, id, state);
158
        //checklist
159
        TaxonBase<?> checklistTaxon = null;
160
        if(CdmUtils.isNotBlank(clTaxonString) && !clTaxonString.trim().equals("-")){
161
            checklistTaxon = (TaxonBase<?>) taxonBase.clone();
162
            if(checklistTaxon.isInstanceOf(Taxon.class)){
163
                TaxonRelationship relation = HibernateProxyHelper.deproxy(checklistTaxon, Taxon.class).addTaxonRelation(HibernateProxyHelper.deproxy(taxonBase, Taxon.class), TaxonRelationshipType.CONGRUENT_TO(), null, null);
164
                relation.setDoubtful(true);
165
            }
166

    
167
            ImportHelper.setOriginalSource(checklistTaxon, state.getTransactionalSourceReference(), id, RedListUtil.TAXON_CHECKLISTE_NAMESPACE);
168
            taxaToSave.add(checklistTaxon);
169
        }
170

    
171
        //NOTE: the source has to be added after cloning or otherwise the clone would also get the source
172
        ImportHelper.setOriginalSource(taxonBase, state.getTransactionalSourceReference(), id, RedListUtil.TAXON_GESAMTLISTE_NAMESPACE);
173
        taxaToSave.add(taxonBase);
174
    }
175

    
176
    private void cloneTaxon(final TaxonBase<?> gesamtListeTaxon, String relationString, String sourceNameSpace, Set<TaxonBase> taxaToSave, long id, RedListGefaesspflanzenImportState state){
177
        if(CdmUtils.isNotBlank(relationString) && !relationString.equals(".")){
178
            Taxon clonedTaxon = null;
179

    
180
            if(gesamtListeTaxon.isInstanceOf(Taxon.class)){
181
                clonedTaxon = HibernateProxyHelper.deproxy(gesamtListeTaxon.clone(), Taxon.class);
182
            }
183
            else if(gesamtListeTaxon.isInstanceOf(Synonym.class)){
184
                clonedTaxon = Taxon.NewInstance(gesamtListeTaxon.getName(), gesamtListeTaxon.getSec());
185
            }
186
            else{
187
                RedListUtil.logMessage(id, "Taxon base "+gesamtListeTaxon+" is neither taxon nor synonym! Taxon could not be cloned", logger);
188
                return;
189
            }
190
            ImportHelper.setOriginalSource(clonedTaxon, state.getTransactionalSourceReference(), id, sourceNameSpace);
191
            taxaToSave.add(clonedTaxon);
192
        }
193
    }
194

    
195
    private TaxonBase<?> importTaxon(ResultSet rs, NonViralName<?> name, RedListGefaesspflanzenImportState state) throws SQLException {
196

    
197
        long id = rs.getLong(RedListUtil.NAMNR);
198
        String taxNameString = rs.getString(RedListUtil.TAXNAME);
199
        String epi1String = rs.getString(RedListUtil.EPI1);
200
        String epi2String = rs.getString(RedListUtil.EPI2);
201
        String epi3String = rs.getString(RedListUtil.EPI3);
202
        String gueltString = rs.getString(RedListUtil.GUELT);
203
        String trivialString = rs.getString(RedListUtil.TRIVIAL);
204
        String authorBasiString = rs.getString(RedListUtil.AUTOR_BASI);
205
        String hybString = rs.getString(RedListUtil.HYB);
206
        String florString = rs.getString(RedListUtil.FLOR);
207
        String atlasIdxString = rs.getString(RedListUtil.ATLAS_IDX);
208
        String kartString = rs.getString(RedListUtil.KART);
209
        String rl2015String = rs.getString(RedListUtil.RL2015);
210
        String ehrdString = rs.getString(RedListUtil.EHRD);
211
        String wisskString = rs.getString(RedListUtil.WISSK);
212

    
213
        TaxonBase<?> taxonBase = null;
214
        if(authorBasiString.trim().contains(RedListUtil.AUCT)){
215
            taxonBase = Taxon.NewInstance(name, null);
216
            taxonBase.setAppendedPhrase(RedListUtil.AUCT);
217
        }
218
        else if(gueltString.equals(RedListUtil.GUELT_ACCEPTED_TAXON)){
219
            taxonBase = Taxon.NewInstance(name, null);
220
        }
221
        else if(gueltString.equals(RedListUtil.GUELT_SYNONYM) || gueltString.equals(RedListUtil.GUELT_BASIONYM)){
222
            taxonBase = Synonym.NewInstance(name, null);
223
        }
224
        else{
225
            return null;
226
        }
227

    
228
        //common name
229
        if(taxonBase.isInstanceOf(Taxon.class) && trivialString!=null){
230
            Taxon taxon = HibernateProxyHelper.deproxy(taxonBase, Taxon.class);
231
            TaxonDescription description = TaxonDescription.NewInstance(taxon);
232
            description.addElement(CommonTaxonName.NewInstance(trivialString, Language.GERMAN()));
233
        }
234

    
235
        //add annotations
236
        addAnnotation(RedListUtil.FLOR+": "+florString, taxonBase);
237
        addAnnotation(RedListUtil.ATLAS_IDX+": "+atlasIdxString, taxonBase);
238
        addAnnotation(RedListUtil.KART+": "+kartString, taxonBase);
239
        addAnnotation(RedListUtil.RL2015+": "+rl2015String, taxonBase);
240
        addAnnotation(RedListUtil.EHRD+": "+ehrdString, taxonBase);
241
        addAnnotation(RedListUtil.WISSK+": "+wisskString, taxonBase);
242

    
243
        //check taxon name consistency
244
        checkTaxonConsistency(id, taxNameString, hybString, epi1String, epi2String, epi3String, taxonBase, state);
245
        return taxonBase;
246
    }
247

    
248
    private void addAnnotation(String string, AnnotatableEntity entity) {
249
        if(CdmUtils.isNotBlank(string)){
250
            entity.addAnnotation(Annotation.NewInstance(string, AnnotationType.TECHNICAL(), Language.GERMAN()));
251
        }
252
    }
253

    
254
    private void importAuthors(RedListGefaesspflanzenImportState state, ResultSet rs, NonViralName<?> name) throws SQLException {
255

    
256
        long id = rs.getLong(RedListUtil.NAMNR);
257
        String nomZusatzString = rs.getString(RedListUtil.NOM_ZUSATZ);
258
        String taxZusatzString = rs.getString(RedListUtil.TAX_ZUSATZ);
259
        String zusatzString = rs.getString(RedListUtil.ZUSATZ);
260
        String authorKombString = rs.getString(RedListUtil.AUTOR_KOMB);
261
        String authorBasiString = rs.getString(RedListUtil.AUTOR_BASI);
262
        String hybString = rs.getString(RedListUtil.HYB);
263

    
264
        //combination author
265
        if(authorKombString.contains(RedListUtil.EX)){
266
            //TODO: what happens with multiple ex authors??
267
            String[] kombSplit = authorKombString.split(RedListUtil.EX);
268
            if(kombSplit.length!=2){
269
                RedListUtil.logMessage(id, "Multiple ex combination authors found", logger);
270
            }
271
            for (int i = 0; i < kombSplit.length; i++) {
272
                if(i==0){
273
                    //first author is ex author
274
                    TeamOrPersonBase<?> authorKomb = (TeamOrPersonBase<?>) state.getRelatedObject(RedListUtil.AUTHOR_NAMESPACE, kombSplit[i]);
275
                    name.setExCombinationAuthorship(authorKomb);
276
                }
277
                else{
278
                    TeamOrPersonBase<?> authorKomb = (TeamOrPersonBase<?>) state.getRelatedObject(RedListUtil.AUTHOR_NAMESPACE, kombSplit[i]);
279
                    name.setCombinationAuthorship(authorKomb);
280
                }
281
            }
282
        }
283
        else if(authorKombString.trim().contains(RedListUtil.AUCT)){
284
            RedListUtil.logMessage(id, "AUCT information in "+RedListUtil.AUTOR_KOMB+" column", logger);
285
        }
286
        else if(CdmUtils.isNotBlank(authorKombString)){
287
            TeamOrPersonBase<?> authorKomb = (TeamOrPersonBase<?>) state.getRelatedObject(RedListUtil.AUTHOR_NAMESPACE, authorKombString);
288
            name.setCombinationAuthorship(authorKomb);
289
        }
290
        //basionym author
291
        if(authorBasiString.contains(RedListUtil.EX)){
292
            String[] basiSplit = authorBasiString.split(RedListUtil.EX);
293
            for (int i = 0; i < basiSplit.length; i++) {
294
                if(basiSplit.length!=2){
295
                    RedListUtil.logMessage(id, "Multiple ex basionymn authors found", logger);
296
                }
297
                if(i==0){
298
                    TeamOrPersonBase<?> authorBasi= (TeamOrPersonBase<?>) state.getRelatedObject(RedListUtil.AUTHOR_NAMESPACE, basiSplit[i]);
299
                    if(CdmUtils.isBlank(authorKombString)){
300
                        name.setExCombinationAuthorship(authorBasi);
301
                    }
302
                    else{
303
                        name.setExBasionymAuthorship(authorBasi);
304
                    }
305
                }
306
                else{
307
                    TeamOrPersonBase<?> authorBasi= (TeamOrPersonBase<?>) state.getRelatedObject(RedListUtil.AUTHOR_NAMESPACE, basiSplit[i]);
308
                    if(CdmUtils.isBlank(authorKombString)){
309
                        name.setCombinationAuthorship(authorBasi);
310
                    }
311
                    else{
312
                        name.setBasionymAuthorship(authorBasi);
313
                    }
314
                }
315
            }
316
        }
317
        else if(CdmUtils.isNotBlank(authorBasiString)){
318
            //this seems to be a convention in the source database: When there is only a single author then only the "AUTOR_BASI" column is used
319
            TeamOrPersonBase<?> authorBasi= (TeamOrPersonBase<?>) state.getRelatedObject(RedListUtil.AUTHOR_NAMESPACE, authorBasiString);
320
            if(CdmUtils.isBlank(authorKombString)){
321
                name.setCombinationAuthorship(authorBasi);
322
            }
323
            else{
324
                name.setBasionymAuthorship(authorBasi);
325
            }
326
        }
327

    
328
        //check authorship consistency
329
        String authorString = rs.getString(RedListUtil.AUTOR);
330
        checkNameConsistency(id, nomZusatzString, taxZusatzString, zusatzString, authorString, hybString, name);
331
    }
332

    
333
    private NonViralName<?> importName(RedListGefaesspflanzenImportState state, ResultSet rs, Set<TaxonNameBase> namesToSave) throws SQLException {
334

    
335
        long id = rs.getLong(RedListUtil.NAMNR);
336
        String taxNameString = rs.getString(RedListUtil.TAXNAME);
337
        String rangString = rs.getString(RedListUtil.RANG);
338
        String ep1String = rs.getString(RedListUtil.EPI1);
339
        String ep2String = rs.getString(RedListUtil.EPI2);
340
        String ep3String = rs.getString(RedListUtil.EPI3);
341
        String nomZusatzString = rs.getString(RedListUtil.NOM_ZUSATZ);
342
        String hybString = rs.getString(RedListUtil.HYB);
343
        String formelString = rs.getString(RedListUtil.FORMEL);
344

    
345
        if(CdmUtils.isBlank(taxNameString) && CdmUtils.isBlank(ep1String)){
346
            RedListUtil.logMessage(id, "No name found!", logger);
347
        }
348

    
349
        NonViralName<?> name = null;
350
        Rank rank = makeRank(id, state, rangString, CdmUtils.isNotBlank(ep3String));
351
        //cultivar
352
        if(rank!= null && rank.equals(Rank.CULTIVAR())){
353
            CultivarPlantName cultivar = CultivarPlantName.NewInstance(rank);
354
            cultivar.setGenusOrUninomial(ep1String);
355
            cultivar.setSpecificEpithet(ep2String);
356
            cultivar.setCultivarName(ep3String);
357
            name = cultivar;
358
        }
359
        //botanical names
360
        else{
361
            name = BotanicalName.NewInstance(rank);
362

    
363
            //ep1 should always be present
364
            if(CdmUtils.isBlank(ep1String)){
365
                RedListUtil.logMessage(id, RedListUtil.EPI1+" is empty!", logger);
366
            }
367
            name.setGenusOrUninomial(ep1String);
368
            if(CdmUtils.isNotBlank(ep2String)){
369
                if(rank!=null && rank.isInfraGenericButNotSpeciesGroup()){
370
                    name.setInfraGenericEpithet(ep2String);
371
                }
372
                else{
373
                    name.setSpecificEpithet(ep2String);
374
                }
375
            }
376
            if(CdmUtils.isNotBlank(ep3String)){
377
                name.setInfraSpecificEpithet(ep3String);
378
            }
379

    
380

    
381
            //nomenclatural status
382
            if(CdmUtils.isNotBlank(nomZusatzString)){
383
                NomenclaturalStatusType statusType = makeNomenclaturalStatus(id, state, nomZusatzString);
384
                if(statusType!=null){
385
                    NomenclaturalStatus status = NomenclaturalStatus.NewInstance(statusType);
386
                    //special case for invalid names where the DB entry contains
387
                    //additional information in brackets e.g. "nom. inval. (sine basion.)"
388
                    if(statusType.equals(NomenclaturalStatusType.INVALID()) || statusType.equals(NomenclaturalStatusType.REJECTED()) ){
389
                        Pattern pattern = Pattern.compile("\\((.*?)\\)");
390
                        Matcher matcher = pattern.matcher(nomZusatzString);
391
                        if (matcher.find()){
392
                            status.setRuleConsidered(matcher.group(1));
393
                        }
394
                    }
395
                    name.addStatus(status);
396
                }
397
            }
398
            //hybrid
399
            if(CdmUtils.isNotBlank(hybString)){
400
                //more than two hybrids not yet handled by name parser
401
                //TODO: use parser when implemented to fully support hybrids
402
                if(taxNameString.split(RedListUtil.HYB_SIGN).length>2){
403
                    name = BotanicalName.NewInstance(rank);
404
                    name.setTitleCache(taxNameString, true);
405
                }
406
                else if(hybString.equals(RedListUtil.HYB_X)){
407
                    name.setBinomHybrid(true);
408
                }
409
                else if(hybString.equals(RedListUtil.HYB_G)){
410
                    name.setMonomHybrid(true);
411
                }
412
                else if(hybString.equals(RedListUtil.HYB_XF) || hybString.equals(RedListUtil.HYB_XU)){
413
                    name.setHybridFormula(true);
414
                    String fullFormula = buildHybridFormula(ep1String, ep2String, ep3String, rank);
415
                    name = NonViralNameParserImpl.NewInstance().parseFullName(fullFormula, NomenclaturalCode.ICNAFP, rank);
416
                }
417
                else if(hybString.equals(RedListUtil.HYB_N)){
418
                    name = NonViralNameParserImpl.NewInstance().parseFullName(taxNameString, NomenclaturalCode.ICNAFP, rank);
419
                }
420
                else if(hybString.equals(RedListUtil.HYB_GF)){
421
                    if(ep1String.contains(RedListUtil.HYB_SIGN)){
422
                        name = NonViralNameParserImpl.NewInstance().parseFullName(ep1String, NomenclaturalCode.ICNAFP, rank);
423
                    }
424
                    else{
425
                        RedListUtil.logMessage(id, "HYB is "+hybString+" but "+RedListUtil.HYB+" does not contain "+RedListUtil.HYB_SIGN, logger);
426
                    }
427
                }
428
                else if(hybString.equals(RedListUtil.HYB_XS)){
429
                    //nothing to do
430
                }
431
                else{
432
                    logger.error("HYB value "+hybString+" not yet handled");
433
                }
434
                //save hybrid formula
435
                if(CdmUtils.isNotBlank(formelString)){
436
                    Annotation annotation = Annotation.NewDefaultLanguageInstance(formelString);
437
                    annotation.setAnnotationType(AnnotationType.TECHNICAL());
438
                    name.addAnnotation(annotation);
439
                }
440
            }
441
        }
442

    
443
        //add source
444
        ImportHelper.setOriginalSource(name, state.getTransactionalSourceReference(), id, RedListUtil.NAME_NAMESPACE);
445

    
446
        namesToSave.add(name);
447
        return name;
448
    }
449

    
450
    private String buildHybridFormula(String ep1String, String ep2String, String ep3String, Rank rank) {
451
        String fullFormula = null;
452
        if(ep1String.contains(RedListUtil.HYB_SIGN)){
453
            fullFormula = ep1String;
454
        }
455
        else if(ep2String.contains(RedListUtil.HYB_SIGN)){
456
            String[] split = ep2String.split(RedListUtil.HYB_SIGN);
457
            String hybridFormula1 = ep1String+" "+split[0].trim();
458
            String hybridFormula2 = ep1String+" "+split[1].trim();
459
            //check if the genus is mentioned in EP2 or not
460
            String[] secondHybrid = split[1].trim().split(" ");
461
            //check if the genus is abbreviated like e.g. Centaurea jacea × C. decipiens
462
            if(secondHybrid.length>1 && secondHybrid[0].matches("[A-Z]\\.")){
463
                hybridFormula2 = ep1String+" "+split[1].trim().substring(3);
464
            }
465
            else if(secondHybrid.length>1 && secondHybrid[0].matches("[A-Z].*")){
466
                hybridFormula2 = split[1].trim();
467
            }
468
            if(CdmUtils.isNotBlank(ep3String)){
469
                hybridFormula1 += " "+rank.getAbbreviation()+" "+ep3String;
470
                hybridFormula2 += " "+rank.getAbbreviation()+" "+ep3String;
471
            }
472
            fullFormula = hybridFormula1+" "+RedListUtil.HYB_SIGN+" "+hybridFormula2;
473
        }
474
        else if(ep3String.contains(RedListUtil.HYB_SIGN)){
475
            String[] split = ep3String.split(RedListUtil.HYB_SIGN);
476
            String hybridFormula1 = ep1String+" "+ep2String+" "+rank.getAbbreviation()+" "+split[0].trim();
477
            String hybridFormula2 = ep1String+" "+ep2String+" "+rank.getAbbreviation()+" "+split[1].trim();
478
            //check if the genus is mentioned in EP3 or not
479
            String[] secondHybrid = split[1].trim().split(" ");
480
            //check if the genus is abbreviated like e.g. Centaurea jacea jacea × C. jacea subsp. decipiens
481
            if(secondHybrid.length>1 && secondHybrid[0].matches("[A-Z]\\.")){
482
                hybridFormula2 = ep1String+" "+split[1].trim().substring(3);
483
            }
484
            else if(secondHybrid.length>1 && secondHybrid[0].matches("[A-Z].*")){
485
                hybridFormula2 = split[1].trim();
486
            }
487
            fullFormula = hybridFormula1+" "+RedListUtil.HYB_SIGN+" "+hybridFormula2;
488
        }
489
        return fullFormula;
490
    }
491

    
492
    private void checkNameConsistency(long id, String nomZusatzString, String taxZusatzString,
493
            String zusatzString, String authorString, String hybString, NonViralName<?> name) {
494
        String authorshipCache = name.getAuthorshipCache();
495
        //FIXME: remove split length check when name parser can parse multiple hybrid parents
496
        if(hybString.equals(RedListUtil.HYB_XF) && name.getTitleCache().split(RedListUtil.HYB_SIGN).length==2){
497
            if(name.getHybridChildRelations().isEmpty()){
498
                RedListUtil.logMessage(id, "Hybrid formula but no hybrid child relations: "+name.getTitleCache(), logger);
499
                return;
500
            }
501
            return;
502
        }
503

    
504
        if(CdmUtils.isNotBlank(zusatzString)){
505
            authorString = authorString.replace(", "+zusatzString, "");
506
        }
507
        if(CdmUtils.isNotBlank(nomZusatzString)){
508
            authorString = authorString.replace(", "+nomZusatzString, "");
509
        }
510
        if(CdmUtils.isNotBlank(taxZusatzString)){
511
            authorString = authorString.replace(", "+taxZusatzString, "");
512
        }
513
        if(authorString.equals(RedListUtil.AUCT)){
514
            authorString = "";
515
        }
516
        if(STRICT_TITLE_CHECK){
517
            if(!authorString.equals(authorshipCache)){
518
                RedListUtil.logMessage(id, "Authorship inconsistent! name.authorhshipCache <-> Column "+RedListUtil.AUTOR+": "+authorshipCache+" <-> "+authorString, logger);
519
            }
520
        }
521
        else{
522
            if(CdmUtils.isNotBlank(authorString) && !authorString.startsWith(authorshipCache)){
523
                RedListUtil.logMessage(id, "Authorship inconsistent! name.authorhshipCache <-> Column "+RedListUtil.AUTOR+": "+authorshipCache+" <-> "+authorString, logger);
524
            }
525
        }
526
    }
527

    
528
    private void checkTaxonConsistency(long id, String taxNameString, String hybString, String epi1String, String epi2String, String epi3String, TaxonBase<?> taxonBase, RedListGefaesspflanzenImportState state) {
529
        if(taxNameString.split(RedListUtil.HYB_SIGN).length>2){
530
            RedListUtil.logInfoMessage(id, "multiple hybrid signs. No name check for "+taxNameString, logger);
531
            return;
532
        }
533

    
534
        String nameCache = HibernateProxyHelper.deproxy(taxonBase.getName(), NonViralName.class).getNameCache().trim();
535
        taxNameString = taxNameString.trim();
536
        taxNameString = taxNameString.replaceAll(" +", " ");
537

    
538

    
539
        if(hybString.equals(RedListUtil.HYB_X) || hybString.equals(RedListUtil.HYB_N)){
540
            taxNameString = taxNameString.replace(" "+RedListUtil.HYB_SIGN+" ", " "+RedListUtil.HYB_SIGN);//hybrid sign has no space after it in titleCache for binomial hybrids
541
            taxNameString = taxNameString.replace(" x ", " "+RedListUtil.HYB_SIGN);//in some cases a standard 'x' is used
542
        }
543
        else if(hybString.equals(RedListUtil.HYB_G)){
544
            taxNameString = taxNameString.replace("X ", RedListUtil.HYB_SIGN);
545
        }
546
        else if(hybString.equals(RedListUtil.HYB_GF)){
547
            taxNameString = taxNameString.replace(" "+RedListUtil.HYB_SIGN+" ", " "+RedListUtil.HYB_SIGN);
548
        }
549
        else if(hybString.equals(RedListUtil.HYB_XF)){
550
            nameCache = taxonBase.getName().getTitleCache();
551
            if(nameCache.contains("sec")){
552
                nameCache = nameCache.substring(0, nameCache.indexOf("sec"));
553
            }
554
            if(!STRICT_TITLE_CHECK){
555
                taxNameString = buildHybridFormula(epi1String, epi2String, epi3String, taxonBase.getName().getRank());
556
            }
557
            if(taxNameString.split(RedListUtil.HYB_SIGN).length==1){
558
                taxNameString = taxNameString.replace(RedListUtil.HYB_SIGN+" ", RedListUtil.HYB_SIGN);
559
            }
560
        }
561

    
562
        if(taxNameString.endsWith("- Gruppe")){
563
            taxNameString = taxNameString.replaceAll("- Gruppe", "species group");
564
        }
565
        if(taxNameString.endsWith("- group")){
566
            taxNameString = taxNameString.replaceAll("- group", "species group");
567
        }
568

    
569
        taxNameString = taxNameString.replace("agg.", "aggr.");
570
        taxNameString = taxNameString.replace("[ranglos]", "[unranked]");
571

    
572
        if(taxonBase.getName().getRank()!=null){
573
            if(taxonBase.getName().getRank().equals(Rank.PROLES())){
574
                taxNameString = taxNameString.replace("proles", "prol.");
575
            }
576
            else if(taxonBase.getName().getRank().equals(state.getRank(RedListUtil.uuidRankCollectionSpecies))){
577
                taxNameString = taxNameString.replace("\"Sammelart\"", "\"Coll. Species\"");
578
            }
579
        }
580
        if(STRICT_TITLE_CHECK){
581
            if(!taxNameString.trim().equals(nameCache)){
582
                RedListUtil.logMessage(id, "Taxon name inconsistent! taxon.nameCache <-> Column "+RedListUtil.TAXNAME+": "+nameCache+" <-> "+taxNameString, logger);
583
            }
584
        }
585
        else{
586
            if(!taxNameString.startsWith(nameCache)){
587
                RedListUtil.logMessage(id, "Taxon name inconsistent! taxon.nameCache <-> Column "+RedListUtil.TAXNAME+": "+nameCache+" <-> "+taxNameString, logger);
588
            }
589
        }
590
    }
591

    
592
    private Rank makeRank(long id, RedListGefaesspflanzenImportState state, String rankStr, boolean hasSpecificEpithet) {
593
        Rank rank = null;
594
        try {
595
            if(rankStr.equals("ORA")){
596
                //special handling for ORA because of two possibilities
597
                if(hasSpecificEpithet){
598
                    return Rank.UNRANKED_INFRASPECIFIC();
599
                }
600
                else{
601
                    return Rank.UNRANKED_INFRAGENERIC();
602
                }
603
            }
604
            else if(rankStr.equals("SAM")){
605
                return getRank(state, RedListUtil.uuidRankCollectionSpecies, "Collective Species", "Collective Species", "\"Coll. Species\"", (OrderedTermVocabulary<Rank>) Rank.GENUS().getVocabulary(), null, RankClass.SpeciesGroup);
606
            }
607
            else if(rankStr.equals("SPR")){
608
                return getRank(state, RedListUtil.uuidRankSubproles, "Subproles", "Subproles", "subproles", (OrderedTermVocabulary<Rank>) Rank.GENUS().getVocabulary(), null, RankClass.Infraspecific);
609
            }
610
            else if(rankStr.equals("MOD")){
611
                return getRank(state, RedListUtil.uuidRankModification, "Modification", "Modification", "modificatio", (OrderedTermVocabulary<Rank>) Rank.GENUS().getVocabulary(), null, RankClass.Infraspecific);
612
            }
613
            else if(rankStr.equals("LUS")){
614
                return getRank(state, RedListUtil.uuidRankLusus, "Lusus", "Lusus", "lusus", (OrderedTermVocabulary<Rank>) Rank.GENUS().getVocabulary(), null, RankClass.Infraspecific);
615
            }
616
            else if(rankStr.equals("SPI")){
617
                return getRank(state, RedListUtil.uuidRankSubspeciesPrincipes, "Subspecies principes", "Subspecies principes", "subsp. princ.", (OrderedTermVocabulary<Rank>) Rank.GENUS().getVocabulary(), null, RankClass.Infraspecific);
618
            }
619
            else if(rankStr.equals("KMB")){
620
                return getRank(state, RedListUtil.uuidRankCombination, "Combination", "Combination", "", (OrderedTermVocabulary<Rank>) Rank.GENUS().getVocabulary(), null, RankClass.Infraspecific);
621
            }
622
            else{
623
                rank = state.getTransformer().getRankByKey(rankStr);
624
            }
625
        } catch (UndefinedTransformerMethodException e) {
626
            e.printStackTrace();
627
        }
628
        if(rank==null){
629
            RedListUtil.logMessage(id, rankStr+" could not be associated to a known rank.", logger);
630
        }
631
        return rank;
632
    }
633

    
634
    private NomenclaturalStatusType makeNomenclaturalStatus(long id, RedListGefaesspflanzenImportState state, String nomZusatzString) {
635
        NomenclaturalStatusType status = null;
636
        try {
637
            status = state.getTransformer().getNomenclaturalStatusByKey(nomZusatzString);
638
        } catch (UndefinedTransformerMethodException e) {
639
            e.printStackTrace();
640
        }
641
        if(status==null){
642
            RedListUtil.logMessage(id, nomZusatzString+" could not be associated to a known nomenclatural status.", logger);
643
        }
644
        return status;
645
    }
646

    
647

    
648

    
649
    @Override
650
    public Map<Object, Map<String, ? extends CdmBase>> getRelatedObjectsForPartition(ResultSet rs,
651
            RedListGefaesspflanzenImportState state) {
652
        Map<Object, Map<String, ? extends CdmBase>> result = new HashMap<>();
653
        Map<String, AgentBase<?>> authorMap = new HashMap<String, AgentBase<?>>();
654

    
655
        try {
656
            while (rs.next()){
657
                String authorKombString = rs.getString(RedListUtil.AUTOR_KOMB);
658

    
659
                if(authorKombString.contains(RedListUtil.EX)){
660
                    String[] kombSplit = authorKombString.split(RedListUtil.EX);
661
                    for (int i = 0; i < kombSplit.length; i++) {
662
                        if(!authorMap.containsKey(kombSplit[i])){
663
                            authorMap.put(kombSplit[i], getAgentService().load(state.getAuthorMap().get(kombSplit[i])));
664
                        }
665
                    }
666
                }
667
                else if(CdmUtils.isNotBlank(authorKombString) && !authorMap.containsKey(authorKombString)){
668
                    authorMap.put(authorKombString, getAgentService().load(state.getAuthorMap().get(authorKombString)));
669
                }
670

    
671
                String authorBasiString = rs.getString(RedListUtil.AUTOR_BASI);
672
                //basionym author
673
                if(authorBasiString.contains(RedListUtil.EX)){
674
                    String[] basiSplit = authorBasiString.split(RedListUtil.EX);
675
                    for (int i = 0; i < basiSplit.length; i++) {
676
                        if(!authorMap.containsKey(basiSplit[i])){
677
                            authorMap.put(basiSplit[i], getAgentService().load(state.getAuthorMap().get(basiSplit[i])));
678
                        }
679
                    }
680
                }
681
                else if(CdmUtils.isNotBlank(authorBasiString) && !authorMap.containsKey(authorBasiString)){
682
                    authorMap.put(authorBasiString, getAgentService().load(state.getAuthorMap().get(authorBasiString)));
683
                }
684
            }
685
        } catch (SQLException e) {
686
            e.printStackTrace();
687
        }
688
        result.put(RedListUtil.AUTHOR_NAMESPACE, authorMap);
689

    
690
        return result;
691
    }
692

    
693
    @Override
694
    protected boolean doCheck(RedListGefaesspflanzenImportState state) {
695
        return false;
696
    }
697

    
698
    @Override
699
    protected boolean isIgnore(RedListGefaesspflanzenImportState state) {
700
        return false;
701
    }
702

    
703
}
(5-5/8)