#5448 Import HYB 'nf'
[cdmlib-apps.git] / app-import / src / main / java / eu / etaxonomy / cdm / io / redlist / gefaesspflanzen / RedListGefaesspflanzenImportNames.java
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.Annotation;
34 import eu.etaxonomy.cdm.model.common.AnnotationType;
35 import eu.etaxonomy.cdm.model.common.CdmBase;
36 import eu.etaxonomy.cdm.model.common.Language;
37 import eu.etaxonomy.cdm.model.common.OrderedTermVocabulary;
38 import eu.etaxonomy.cdm.model.description.CommonTaxonName;
39 import eu.etaxonomy.cdm.model.description.TaxonDescription;
40 import eu.etaxonomy.cdm.model.name.BotanicalName;
41 import eu.etaxonomy.cdm.model.name.CultivarPlantName;
42 import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
43 import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
44 import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
45 import eu.etaxonomy.cdm.model.name.NonViralName;
46 import eu.etaxonomy.cdm.model.name.Rank;
47 import eu.etaxonomy.cdm.model.name.RankClass;
48 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
49 import eu.etaxonomy.cdm.model.taxon.Synonym;
50 import eu.etaxonomy.cdm.model.taxon.Taxon;
51 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
52 import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
53 import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
54 import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImpl;
55
56 /**
57 *
58 * @author pplitzner
59 * @date Mar 1, 2016
60 *
61 */
62
63 @Component
64 @SuppressWarnings("serial")
65 public class RedListGefaesspflanzenImportNames extends DbImportBase<RedListGefaesspflanzenImportState, RedListGefaesspflanzenImportConfigurator> {
66
67 private static final Logger logger = Logger.getLogger(RedListGefaesspflanzenImportNames.class);
68
69 private static final String tableName = "Rote Liste Gefäßpflanzen";
70
71 private static final String pluralString = "names";
72
73 private static final boolean STRICT_TITLE_CHECK = false;
74
75 public RedListGefaesspflanzenImportNames() {
76 super(tableName, pluralString);
77 }
78
79 @Override
80 protected String getIdQuery(RedListGefaesspflanzenImportState state) {
81 return "SELECT NAMNR "
82 + "FROM V_TAXATLAS_D20_EXPORT t "
83 + " ORDER BY NAMNR";
84 }
85
86 @Override
87 protected String getRecordQuery(RedListGefaesspflanzenImportConfigurator config) {
88 String result = " SELECT * "
89 + " FROM V_TAXATLAS_D20_EXPORT t "
90 + " WHERE t.NAMNR IN (@IDSET)";
91 result = result.replace("@IDSET", IPartitionedIO.ID_LIST_TOKEN);
92 return result;
93 }
94
95 @Override
96 protected void doInvoke(RedListGefaesspflanzenImportState state) {
97 super.doInvoke(state);
98 }
99
100
101 @Override
102 public boolean doPartition(ResultSetPartitioner partitioner, RedListGefaesspflanzenImportState state) {
103 ResultSet rs = partitioner.getResultSet();
104 Set<TaxonNameBase> namesToSave = new HashSet<TaxonNameBase>();
105 Set<TaxonBase> taxaToSave = new HashSet<TaxonBase>();
106 try {
107 while (rs.next()){
108 makeSingleNameAndTaxon(state, rs, namesToSave, taxaToSave);
109
110 }
111 } catch (SQLException e) {
112 e.printStackTrace();
113 }
114
115 getNameService().saveOrUpdate(namesToSave);
116 getTaxonService().saveOrUpdate(taxaToSave);
117 return true;
118 }
119
120 private void makeSingleNameAndTaxon(RedListGefaesspflanzenImportState state, ResultSet rs, Set<TaxonNameBase> namesToSave, Set<TaxonBase> taxaToSave)
121 throws SQLException {
122 long id = rs.getLong(RedListUtil.NAMNR);
123 String clTaxonString = rs.getString(RedListUtil.CL_TAXON);
124 String relationE = rs.getString(RedListUtil.E);
125 String relationW = rs.getString(RedListUtil.W);
126 String relationK = rs.getString(RedListUtil.K);
127 String relationAW = rs.getString(RedListUtil.AW);
128 String relationAO = rs.getString(RedListUtil.AO);
129 String relationR = rs.getString(RedListUtil.R);
130 String relationO = rs.getString(RedListUtil.O);
131 String relationS = rs.getString(RedListUtil.S);
132
133 //---NAME---
134 NonViralName<?> name = importName(state, rs, namesToSave);
135
136
137 //--- AUTHORS ---
138 importAuthors(state, rs, name);
139
140 //---TAXON---
141 TaxonBase<?> taxonBase = importTaxon(rs, name, state);
142 if(taxonBase==null){
143 RedListUtil.logMessage(id, "Taxon for name "+name+" could not be created.", logger);
144 return;
145 }
146
147 //---CONCEPT RELATIONSHIPS---
148 //E, W, K, AW, AO, R, O, S
149 cloneTaxon(taxonBase, relationE, RedListUtil.CLASSIFICATION_NAMESPACE_E, taxaToSave, id, state);
150 cloneTaxon(taxonBase, relationW, RedListUtil.CLASSIFICATION_NAMESPACE_W, taxaToSave, id, state);
151 cloneTaxon(taxonBase, relationK, RedListUtil.CLASSIFICATION_NAMESPACE_K, taxaToSave, id, state);
152 cloneTaxon(taxonBase, relationAW, RedListUtil.CLASSIFICATION_NAMESPACE_AW, taxaToSave, id, state);
153 cloneTaxon(taxonBase, relationAO, RedListUtil.CLASSIFICATION_NAMESPACE_AO, taxaToSave, id, state);
154 cloneTaxon(taxonBase, relationR, RedListUtil.CLASSIFICATION_NAMESPACE_R, taxaToSave, id, state);
155 cloneTaxon(taxonBase, relationO, RedListUtil.CLASSIFICATION_NAMESPACE_O, taxaToSave, id, state);
156 cloneTaxon(taxonBase, relationS, RedListUtil.CLASSIFICATION_NAMESPACE_S, taxaToSave, id, state);
157 //checklist
158 TaxonBase<?> checklistTaxon = null;
159 if(CdmUtils.isNotBlank(clTaxonString) && !clTaxonString.trim().equals("-")){
160 checklistTaxon = (TaxonBase<?>) taxonBase.clone();
161 if(checklistTaxon.isInstanceOf(Taxon.class)){
162 TaxonRelationship relation = HibernateProxyHelper.deproxy(checklistTaxon, Taxon.class).addTaxonRelation(HibernateProxyHelper.deproxy(taxonBase, Taxon.class), TaxonRelationshipType.CONGRUENT_TO(), null, null);
163 relation.setDoubtful(true);
164 }
165
166 ImportHelper.setOriginalSource(checklistTaxon, state.getTransactionalSourceReference(), id, RedListUtil.TAXON_CHECKLISTE_NAMESPACE);
167 taxaToSave.add(checklistTaxon);
168 }
169
170 //NOTE: the source has to be added after cloning or otherwise the clone would also get the source
171 ImportHelper.setOriginalSource(taxonBase, state.getTransactionalSourceReference(), id, RedListUtil.TAXON_GESAMTLISTE_NAMESPACE);
172 taxaToSave.add(taxonBase);
173 }
174
175 private void cloneTaxon(final TaxonBase<?> gesamtListeTaxon, String relationString, String sourceNameSpace, Set<TaxonBase> taxaToSave, long id, RedListGefaesspflanzenImportState state){
176 if(CdmUtils.isNotBlank(relationString) && !relationString.equals(".")){
177 Taxon clonedTaxon = null;
178
179 if(gesamtListeTaxon.isInstanceOf(Taxon.class)){
180 clonedTaxon = HibernateProxyHelper.deproxy(gesamtListeTaxon.clone(), Taxon.class);
181 }
182 else if(gesamtListeTaxon.isInstanceOf(Synonym.class)){
183 clonedTaxon = Taxon.NewInstance(gesamtListeTaxon.getName(), gesamtListeTaxon.getSec());
184 }
185 else{
186 RedListUtil.logMessage(id, "Taxon base "+gesamtListeTaxon+" is neither taxon nor synonym! Taxon could not be cloned", logger);
187 return;
188 }
189 ImportHelper.setOriginalSource(clonedTaxon, state.getTransactionalSourceReference(), id, sourceNameSpace);
190 taxaToSave.add(clonedTaxon);
191 }
192 }
193
194 private TaxonBase<?> importTaxon(ResultSet rs, NonViralName<?> name, RedListGefaesspflanzenImportState state) throws SQLException {
195
196 long id = rs.getLong(RedListUtil.NAMNR);
197 String taxNameString = rs.getString(RedListUtil.TAXNAME);
198 String gueltString = rs.getString(RedListUtil.GUELT);
199 String trivialString = rs.getString(RedListUtil.TRIVIAL);
200 String authorBasiString = rs.getString(RedListUtil.AUTOR_BASI);
201 String hybString = rs.getString(RedListUtil.HYB);
202 String florString = rs.getString(RedListUtil.FLOR);
203 String atlasIdxString = rs.getString(RedListUtil.ATLAS_IDX);
204 String kartString = rs.getString(RedListUtil.KART);
205 String rl2015String = rs.getString(RedListUtil.RL2015);
206 String ehrdString = rs.getString(RedListUtil.EHRD);
207 String wisskString = rs.getString(RedListUtil.WISSK);
208
209 TaxonBase<?> taxonBase = null;
210 if(authorBasiString.trim().contains(RedListUtil.AUCT)){
211 taxonBase = Taxon.NewInstance(name, null);
212 taxonBase.setAppendedPhrase(RedListUtil.AUCT);
213 }
214 else if(gueltString.equals(RedListUtil.GUELT_ACCEPTED_TAXON)){
215 taxonBase = Taxon.NewInstance(name, null);
216 }
217 else if(gueltString.equals(RedListUtil.GUELT_SYNONYM) || gueltString.equals(RedListUtil.GUELT_BASIONYM)){
218 taxonBase = Synonym.NewInstance(name, null);
219 }
220 else{
221 return null;
222 }
223
224 //common name
225 if(taxonBase.isInstanceOf(Taxon.class) && trivialString!=null){
226 Taxon taxon = HibernateProxyHelper.deproxy(taxonBase, Taxon.class);
227 TaxonDescription description = TaxonDescription.NewInstance(taxon);
228 description.addElement(CommonTaxonName.NewInstance(trivialString, Language.GERMAN()));
229 }
230
231 //add annotations
232 addAnnotation(RedListUtil.FLOR+": "+florString, taxonBase);
233 addAnnotation(RedListUtil.ATLAS_IDX+": "+atlasIdxString, taxonBase);
234 addAnnotation(RedListUtil.KART+": "+kartString, taxonBase);
235 addAnnotation(RedListUtil.RL2015+": "+rl2015String, taxonBase);
236 addAnnotation(RedListUtil.EHRD+": "+ehrdString, taxonBase);
237 addAnnotation(RedListUtil.WISSK+": "+wisskString, taxonBase);
238
239 //check taxon name consistency
240 checkTaxonConsistency(id, taxNameString, hybString, taxonBase, state);
241 return taxonBase;
242 }
243
244 private void addAnnotation(String string, TaxonBase<?> taxonBase) {
245 if(CdmUtils.isNotBlank(string)){
246 taxonBase.addAnnotation(Annotation.NewInstance(string, AnnotationType.TECHNICAL(), Language.GERMAN()));
247 }
248 }
249
250 private void importAuthors(RedListGefaesspflanzenImportState state, ResultSet rs, NonViralName<?> name) throws SQLException {
251
252 long id = rs.getLong(RedListUtil.NAMNR);
253 String nomZusatzString = rs.getString(RedListUtil.NOM_ZUSATZ);
254 String taxZusatzString = rs.getString(RedListUtil.TAX_ZUSATZ);
255 String zusatzString = rs.getString(RedListUtil.ZUSATZ);
256 String authorKombString = rs.getString(RedListUtil.AUTOR_KOMB);
257 String authorBasiString = rs.getString(RedListUtil.AUTOR_BASI);
258 String hybString = rs.getString(RedListUtil.HYB);
259
260 //combination author
261 if(authorKombString.contains(RedListUtil.EX)){
262 //TODO: what happens with multiple ex authors??
263 String[] kombSplit = authorKombString.split(RedListUtil.EX);
264 if(kombSplit.length!=2){
265 RedListUtil.logMessage(id, "Multiple ex combination authors found", logger);
266 }
267 for (int i = 0; i < kombSplit.length; i++) {
268 if(i==0){
269 //first author is ex author
270 TeamOrPersonBase<?> authorKomb = (TeamOrPersonBase<?>) state.getRelatedObject(RedListUtil.AUTHOR_NAMESPACE, kombSplit[i]);
271 name.setExCombinationAuthorship(authorKomb);
272 }
273 else{
274 TeamOrPersonBase<?> authorKomb = (TeamOrPersonBase<?>) state.getRelatedObject(RedListUtil.AUTHOR_NAMESPACE, kombSplit[i]);
275 name.setCombinationAuthorship(authorKomb);
276 }
277 }
278 }
279 else if(authorKombString.trim().contains(RedListUtil.AUCT)){
280 RedListUtil.logMessage(id, "AUCT information in "+RedListUtil.AUTOR_KOMB+" column", logger);
281 }
282 else if(CdmUtils.isNotBlank(authorKombString)){
283 TeamOrPersonBase<?> authorKomb = (TeamOrPersonBase<?>) state.getRelatedObject(RedListUtil.AUTHOR_NAMESPACE, authorKombString);
284 name.setCombinationAuthorship(authorKomb);
285 }
286 //basionym author
287 if(authorBasiString.contains(RedListUtil.EX)){
288 String[] basiSplit = authorBasiString.split(RedListUtil.EX);
289 for (int i = 0; i < basiSplit.length; i++) {
290 if(basiSplit.length!=2){
291 RedListUtil.logMessage(id, "Multiple ex basionymn authors found", logger);
292 }
293 if(i==0){
294 TeamOrPersonBase<?> authorBasi= (TeamOrPersonBase<?>) state.getRelatedObject(RedListUtil.AUTHOR_NAMESPACE, basiSplit[i]);
295 if(CdmUtils.isBlank(authorKombString)){
296 name.setExCombinationAuthorship(authorBasi);
297 }
298 else{
299 name.setExBasionymAuthorship(authorBasi);
300 }
301 }
302 else{
303 TeamOrPersonBase<?> authorBasi= (TeamOrPersonBase<?>) state.getRelatedObject(RedListUtil.AUTHOR_NAMESPACE, basiSplit[i]);
304 if(CdmUtils.isBlank(authorKombString)){
305 name.setCombinationAuthorship(authorBasi);
306 }
307 else{
308 name.setBasionymAuthorship(authorBasi);
309 }
310 }
311 }
312 }
313 else if(CdmUtils.isNotBlank(authorBasiString)){
314 //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
315 TeamOrPersonBase<?> authorBasi= (TeamOrPersonBase<?>) state.getRelatedObject(RedListUtil.AUTHOR_NAMESPACE, authorBasiString);
316 if(CdmUtils.isBlank(authorKombString)){
317 name.setCombinationAuthorship(authorBasi);
318 }
319 else{
320 name.setBasionymAuthorship(authorBasi);
321 }
322 }
323
324 //check authorship consistency
325 String authorString = rs.getString(RedListUtil.AUTOR);
326 checkNameConsistency(id, nomZusatzString, taxZusatzString, zusatzString, authorString, hybString, name);
327 }
328
329 private NonViralName<?> importName(RedListGefaesspflanzenImportState state, ResultSet rs, Set<TaxonNameBase> namesToSave) throws SQLException {
330
331 long id = rs.getLong(RedListUtil.NAMNR);
332 String taxNameString = rs.getString(RedListUtil.TAXNAME);
333 String rangString = rs.getString(RedListUtil.RANG);
334 String ep1String = rs.getString(RedListUtil.EPI1);
335 String ep2String = rs.getString(RedListUtil.EPI2);
336 String ep3String = rs.getString(RedListUtil.EPI3);
337 String nomZusatzString = rs.getString(RedListUtil.NOM_ZUSATZ);
338 String hybString = rs.getString(RedListUtil.HYB);
339 String formelString = rs.getString(RedListUtil.FORMEL);
340
341 if(CdmUtils.isBlank(taxNameString) && CdmUtils.isBlank(ep1String)){
342 RedListUtil.logMessage(id, "No name found!", logger);
343 }
344
345 NonViralName<?> name = null;
346 Rank rank = makeRank(id, state, rangString, ep3String!=null);
347 //cultivar
348 if(rank!= null && rank.equals(Rank.CULTIVAR())){
349 CultivarPlantName cultivar = CultivarPlantName.NewInstance(rank);
350 cultivar.setGenusOrUninomial(ep1String);
351 cultivar.setSpecificEpithet(ep2String);
352 cultivar.setCultivarName(ep3String);
353 name = cultivar;
354 }
355 //botanical names
356 else{
357 name = BotanicalName.NewInstance(rank);
358
359 //ep1 should always be present
360 if(CdmUtils.isBlank(ep1String)){
361 RedListUtil.logMessage(id, RedListUtil.EPI1+" is empty!", logger);
362 }
363 name.setGenusOrUninomial(ep1String);
364 if(CdmUtils.isNotBlank(ep2String)){
365 if(rank!=null && rank.isInfraGenericButNotSpeciesGroup()){
366 name.setInfraGenericEpithet(ep2String);
367 }
368 else{
369 name.setSpecificEpithet(ep2String);
370 }
371 }
372 if(CdmUtils.isNotBlank(ep3String)){
373 name.setInfraSpecificEpithet(ep3String);
374 }
375
376
377 //nomenclatural status
378 if(CdmUtils.isNotBlank(nomZusatzString)){
379 NomenclaturalStatusType statusType = makeNomenclaturalStatus(id, state, nomZusatzString);
380 if(statusType!=null){
381 NomenclaturalStatus status = NomenclaturalStatus.NewInstance(statusType);
382 //special case for invalid names where the DB entry contains
383 //additional information in brackets e.g. "nom. inval. (sine basion.)"
384 if(statusType.equals(NomenclaturalStatusType.INVALID())){
385 Pattern pattern = Pattern.compile("\\((.*?)\\)");
386 Matcher matcher = pattern.matcher(nomZusatzString);
387 if (matcher.find()){
388 status.setRuleConsidered(matcher.group(1));
389 }
390 }
391 name.addStatus(status);
392 }
393 }
394 //hybrid
395 if(CdmUtils.isNotBlank(hybString)){
396 //save hybrid formula
397 if(CdmUtils.isNotBlank(formelString)){
398 Annotation annotation = Annotation.NewDefaultLanguageInstance(formelString);
399 annotation.setAnnotationType(AnnotationType.TECHNICAL());
400 name.addAnnotation(annotation);
401 }
402 //more than two hybrids not yet handled by name parser
403 //TODO: use parser when implemented to fully support hybrids
404 if(taxNameString.split(RedListUtil.HYB_SIGN).length>2){
405 name = BotanicalName.NewInstance(rank);
406 name.setTitleCache(taxNameString, true);
407 }
408 else if(hybString.equals(RedListUtil.HYB_X)){
409 name.setBinomHybrid(true);
410 }
411 else if(hybString.equals(RedListUtil.HYB_G)){
412 name.setMonomHybrid(true);
413 }
414 else if(hybString.equals(RedListUtil.HYB_XF) || hybString.equals(RedListUtil.HYB_NF) ){
415 name.setHybridFormula(true);
416 if(ep1String.contains(RedListUtil.HYB_SIGN)){
417 RedListUtil.logMessage(id, "EPI1 has hybrid signs but with flag: "+RedListUtil.HYB_XF, logger);
418 }
419 else if(ep2String.contains(RedListUtil.HYB_SIGN)){
420 String[] split = ep2String.split(RedListUtil.HYB_SIGN);
421 String hybridFormula1 = ep1String+" "+split[0].trim();
422 String hybridFormula2 = ep1String+" "+split[1].trim();
423 //check if the specific epithets are from the same genus or not like e.g. EPI2 = pratensis × Lolium multiflorum
424 String[] secondHybrid = split[1].trim().split(" ");
425 if(secondHybrid.length>1 && secondHybrid[0].matches("[A-Z].*")){
426 hybridFormula2 = split[1];
427 }
428 if(CdmUtils.isNotBlank(ep3String)){
429 hybridFormula1 += " "+ep3String;
430 hybridFormula2 += " "+ep3String;
431 }
432 String fullFormula = hybridFormula1+" "+RedListUtil.HYB_SIGN+" "+hybridFormula2;
433 name = NonViralNameParserImpl.NewInstance().parseFullName(fullFormula, NomenclaturalCode.ICNAFP, rank);
434 }
435 else if(ep3String.contains(RedListUtil.HYB_SIGN)){
436 String[] split = ep3String.split(RedListUtil.HYB_SIGN);
437 String hybridFormula1 = ep1String+" "+ep2String+" "+split[0];
438 String hybridFormula2 = ep1String+" "+ep2String+" "+split[1];
439 String fullFormula = hybridFormula1+" "+RedListUtil.HYB_SIGN+" "+hybridFormula2;
440 name = NonViralNameParserImpl.NewInstance().parseFullName(fullFormula, NomenclaturalCode.ICNAFP, rank);
441 }
442 }
443 else if(hybString.equals(RedListUtil.HYB_N)){
444 name = NonViralNameParserImpl.NewInstance().parseFullName(taxNameString, NomenclaturalCode.ICNAFP, rank);
445 }
446 else if(hybString.equals(RedListUtil.HYB_GF)){
447 if(ep1String.contains(RedListUtil.HYB_SIGN)){
448 name = NonViralNameParserImpl.NewInstance().parseFullName(ep1String, NomenclaturalCode.ICNAFP, rank);
449 }
450 else{
451 RedListUtil.logMessage(id, "HYB is "+hybString+" but "+RedListUtil.HYB+" does not contain "+RedListUtil.HYB_SIGN, logger);
452 }
453 }
454 else if(hybString.equals(RedListUtil.HYB_XS)){
455 //nothing to do
456 }
457 else{
458 logger.error("HYB value "+hybString+" not yet handled");
459 }
460 }
461 }
462 //add source
463 ImportHelper.setOriginalSource(name, state.getTransactionalSourceReference(), id, RedListUtil.NAME_NAMESPACE);
464
465 namesToSave.add(name);
466 return name;
467 }
468
469 private void checkNameConsistency(long id, String nomZusatzString, String taxZusatzString,
470 String zusatzString, String authorString, String hybString, NonViralName<?> name) {
471 String authorshipCache = name.getAuthorshipCache();
472 //FIXME: remove split length check when name parser can parse multiple hybrid parents
473 if(hybString.equals(RedListUtil.HYB_XF) && name.getTitleCache().split(RedListUtil.HYB_SIGN).length==2){
474 if(name.getHybridChildRelations().isEmpty()){
475 RedListUtil.logMessage(id, "Hybrid formula but no hybrid child relations: "+name.getTitleCache(), logger);
476 return;
477 }
478 return;
479 }
480
481 if(CdmUtils.isNotBlank(zusatzString)){
482 authorString = authorString.replace(", "+zusatzString, "");
483 }
484 if(CdmUtils.isNotBlank(nomZusatzString)){
485 authorString = authorString.replace(", "+nomZusatzString, "");
486 }
487 if(CdmUtils.isNotBlank(taxZusatzString)){
488 authorString = authorString.replace(", "+taxZusatzString, "");
489 }
490 if(authorString.equals(RedListUtil.AUCT)){
491 authorString = "";
492 }
493 if(STRICT_TITLE_CHECK){
494 if(!authorString.equals(authorshipCache)){
495 RedListUtil.logMessage(id, "Authorship inconsistent! name.authorhshipCache <-> Column "+RedListUtil.AUTOR+": "+authorshipCache+" <-> "+authorString, logger);
496 }
497 }
498 else{
499 if(CdmUtils.isNotBlank(authorString) && !authorString.startsWith(authorshipCache)){
500 RedListUtil.logMessage(id, "Authorship inconsistent! name.authorhshipCache <-> Column "+RedListUtil.AUTOR+": "+authorshipCache+" <-> "+authorString, logger);
501 }
502 }
503 }
504
505 private void checkTaxonConsistency(long id, String taxNameString, String hybString, TaxonBase<?> taxonBase, RedListGefaesspflanzenImportState state) {
506 String nameCache = HibernateProxyHelper.deproxy(taxonBase.getName(), NonViralName.class).getNameCache().trim();
507 taxNameString = taxNameString.trim();
508 taxNameString = taxNameString.replaceAll(" +", " ");
509
510 if(taxNameString.endsWith("agg.")){
511 taxNameString = taxNameString.replace("agg.", "aggr.");
512 }
513
514 if(hybString.equals(RedListUtil.HYB_X) || hybString.equals(RedListUtil.HYB_N)){
515 taxNameString = taxNameString.replace(" "+RedListUtil.HYB_SIGN+" ", " "+RedListUtil.HYB_SIGN);//hybrid sign has no space after it in titleCache for binomial hybrids
516 taxNameString = taxNameString.replace(" x ", " "+RedListUtil.HYB_SIGN);//in some cases a standard 'x' is used
517 }
518 else if(hybString.equals(RedListUtil.HYB_G)){
519 taxNameString = taxNameString.replace("X ", RedListUtil.HYB_SIGN);
520 }
521 else if(hybString.equals(RedListUtil.HYB_GF)){
522 taxNameString = taxNameString.replace(" "+RedListUtil.HYB_SIGN, " x");
523 }
524
525 if(taxNameString.endsWith("- Gruppe")){
526 taxNameString = taxNameString.replaceAll("- Gruppe", "species group");
527 }
528 if(taxNameString.endsWith("- group")){
529 taxNameString = taxNameString.replaceAll("- group", "species group");
530 }
531
532 taxNameString = taxNameString.replace("[ranglos]", "[unranked]");
533 if(taxonBase.getName().getRank()!=null){
534 if(taxonBase.getName().getRank().equals(Rank.PROLES())){
535 taxNameString = taxNameString.replace("proles", "prol.");
536 }
537 else if(taxonBase.getName().getRank().equals(state.getRank(RedListUtil.uuidRankCollectionSpecies))){
538 taxNameString = taxNameString.replace("\"Sammelart\"", "\"Coll. Species\"");
539 }
540 }
541 if(STRICT_TITLE_CHECK){
542 if(!taxNameString.trim().equals(nameCache)){
543 RedListUtil.logMessage(id, "Taxon name inconsistent! taxon.nameCache <-> Column "+RedListUtil.TAXNAME+": "+nameCache+" <-> "+taxNameString, logger);
544 }
545 }
546 else{
547 if(!taxNameString.startsWith(nameCache)){
548 RedListUtil.logMessage(id, "Taxon name inconsistent! taxon.nameCache <-> Column "+RedListUtil.TAXNAME+": "+nameCache+" <-> "+taxNameString, logger);
549 }
550 }
551 }
552
553 private Rank makeRank(long id, RedListGefaesspflanzenImportState state, String rankStr, boolean hasSpecificEpithet) {
554 Rank rank = null;
555 try {
556 if(rankStr.equals("ORA")){
557 //special handling for ORA because of two possibilities
558 if(hasSpecificEpithet){
559 return Rank.UNRANKED_INFRASPECIFIC();
560 }
561 else{
562 return Rank.UNRANKED_INFRAGENERIC();
563 }
564 }
565 else if(rankStr.equals("SAM")){
566 return getRank(state, RedListUtil.uuidRankCollectionSpecies, "Collective Species", "Collective Species", "\"Coll. Species\"", (OrderedTermVocabulary<Rank>) Rank.GENUS().getVocabulary(), null, RankClass.SpeciesGroup);
567 }
568 else{
569 rank = state.getTransformer().getRankByKey(rankStr);
570 }
571 } catch (UndefinedTransformerMethodException e) {
572 e.printStackTrace();
573 }
574 if(rank==null){
575 RedListUtil.logMessage(id, rankStr+" could not be associated to a known rank.", logger);
576 }
577 return rank;
578 }
579
580 private NomenclaturalStatusType makeNomenclaturalStatus(long id, RedListGefaesspflanzenImportState state, String nomZusatzString) {
581 NomenclaturalStatusType status = null;
582 try {
583 status = state.getTransformer().getNomenclaturalStatusByKey(nomZusatzString);
584 } catch (UndefinedTransformerMethodException e) {
585 e.printStackTrace();
586 }
587 if(status==null){
588 RedListUtil.logMessage(id, nomZusatzString+" could not be associated to a known nomenclatural status.", logger);
589 }
590 return status;
591 }
592
593
594
595 @Override
596 public Map<Object, Map<String, ? extends CdmBase>> getRelatedObjectsForPartition(ResultSet rs,
597 RedListGefaesspflanzenImportState state) {
598 Map<Object, Map<String, ? extends CdmBase>> result = new HashMap<>();
599 Map<String, AgentBase<?>> authorMap = new HashMap<String, AgentBase<?>>();
600
601 try {
602 while (rs.next()){
603 String authorKombString = rs.getString(RedListUtil.AUTOR_KOMB);
604
605 if(authorKombString.contains(RedListUtil.EX)){
606 String[] kombSplit = authorKombString.split(RedListUtil.EX);
607 for (int i = 0; i < kombSplit.length; i++) {
608 if(!authorMap.containsKey(kombSplit[i])){
609 authorMap.put(kombSplit[i], getAgentService().load(state.getAuthorMap().get(kombSplit[i])));
610 }
611 }
612 }
613 else if(CdmUtils.isNotBlank(authorKombString) && !authorMap.containsKey(authorKombString)){
614 authorMap.put(authorKombString, getAgentService().load(state.getAuthorMap().get(authorKombString)));
615 }
616
617 String authorBasiString = rs.getString(RedListUtil.AUTOR_BASI);
618 //basionym author
619 if(authorBasiString.contains(RedListUtil.EX)){
620 String[] basiSplit = authorBasiString.split(RedListUtil.EX);
621 for (int i = 0; i < basiSplit.length; i++) {
622 if(!authorMap.containsKey(basiSplit[i])){
623 authorMap.put(basiSplit[i], getAgentService().load(state.getAuthorMap().get(basiSplit[i])));
624 }
625 }
626 }
627 else if(CdmUtils.isNotBlank(authorBasiString) && !authorMap.containsKey(authorBasiString)){
628 authorMap.put(authorBasiString, getAgentService().load(state.getAuthorMap().get(authorBasiString)));
629 }
630 }
631 } catch (SQLException e) {
632 e.printStackTrace();
633 }
634 result.put(RedListUtil.AUTHOR_NAMESPACE, authorMap);
635
636 return result;
637 }
638
639 @Override
640 protected boolean doCheck(RedListGefaesspflanzenImportState state) {
641 return false;
642 }
643
644 @Override
645 protected boolean isIgnore(RedListGefaesspflanzenImportState state) {
646 return false;
647 }
648
649 }