#5448 Import non-CDM ranks
[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 epi1String = rs.getString(RedListUtil.EPI1);
199 String gueltString = rs.getString(RedListUtil.GUELT);
200 String trivialString = rs.getString(RedListUtil.TRIVIAL);
201 String authorBasiString = rs.getString(RedListUtil.AUTOR_BASI);
202 String hybString = rs.getString(RedListUtil.HYB);
203 String florString = rs.getString(RedListUtil.FLOR);
204 String atlasIdxString = rs.getString(RedListUtil.ATLAS_IDX);
205 String kartString = rs.getString(RedListUtil.KART);
206 String rl2015String = rs.getString(RedListUtil.RL2015);
207 String ehrdString = rs.getString(RedListUtil.EHRD);
208 String wisskString = rs.getString(RedListUtil.WISSK);
209
210 TaxonBase<?> taxonBase = null;
211 if(authorBasiString.trim().contains(RedListUtil.AUCT)){
212 taxonBase = Taxon.NewInstance(name, null);
213 taxonBase.setAppendedPhrase(RedListUtil.AUCT);
214 }
215 else if(gueltString.equals(RedListUtil.GUELT_ACCEPTED_TAXON)){
216 taxonBase = Taxon.NewInstance(name, null);
217 }
218 else if(gueltString.equals(RedListUtil.GUELT_SYNONYM) || gueltString.equals(RedListUtil.GUELT_BASIONYM)){
219 taxonBase = Synonym.NewInstance(name, null);
220 }
221 else{
222 return null;
223 }
224
225 //common name
226 if(taxonBase.isInstanceOf(Taxon.class) && trivialString!=null){
227 Taxon taxon = HibernateProxyHelper.deproxy(taxonBase, Taxon.class);
228 TaxonDescription description = TaxonDescription.NewInstance(taxon);
229 description.addElement(CommonTaxonName.NewInstance(trivialString, Language.GERMAN()));
230 }
231
232 //add annotations
233 addAnnotation(RedListUtil.FLOR+": "+florString, taxonBase);
234 addAnnotation(RedListUtil.ATLAS_IDX+": "+atlasIdxString, taxonBase);
235 addAnnotation(RedListUtil.KART+": "+kartString, taxonBase);
236 addAnnotation(RedListUtil.RL2015+": "+rl2015String, taxonBase);
237 addAnnotation(RedListUtil.EHRD+": "+ehrdString, taxonBase);
238 addAnnotation(RedListUtil.WISSK+": "+wisskString, taxonBase);
239
240 //check taxon name consistency
241 checkTaxonConsistency(id, taxNameString, hybString, epi1String, taxonBase, state);
242 return taxonBase;
243 }
244
245 private void addAnnotation(String string, TaxonBase<?> taxonBase) {
246 if(CdmUtils.isNotBlank(string)){
247 taxonBase.addAnnotation(Annotation.NewInstance(string, AnnotationType.TECHNICAL(), Language.GERMAN()));
248 }
249 }
250
251 private void importAuthors(RedListGefaesspflanzenImportState state, ResultSet rs, NonViralName<?> name) throws SQLException {
252
253 long id = rs.getLong(RedListUtil.NAMNR);
254 String nomZusatzString = rs.getString(RedListUtil.NOM_ZUSATZ);
255 String taxZusatzString = rs.getString(RedListUtil.TAX_ZUSATZ);
256 String zusatzString = rs.getString(RedListUtil.ZUSATZ);
257 String authorKombString = rs.getString(RedListUtil.AUTOR_KOMB);
258 String authorBasiString = rs.getString(RedListUtil.AUTOR_BASI);
259 String hybString = rs.getString(RedListUtil.HYB);
260
261 //combination author
262 if(authorKombString.contains(RedListUtil.EX)){
263 //TODO: what happens with multiple ex authors??
264 String[] kombSplit = authorKombString.split(RedListUtil.EX);
265 if(kombSplit.length!=2){
266 RedListUtil.logMessage(id, "Multiple ex combination authors found", logger);
267 }
268 for (int i = 0; i < kombSplit.length; i++) {
269 if(i==0){
270 //first author is ex author
271 TeamOrPersonBase<?> authorKomb = (TeamOrPersonBase<?>) state.getRelatedObject(RedListUtil.AUTHOR_NAMESPACE, kombSplit[i]);
272 name.setExCombinationAuthorship(authorKomb);
273 }
274 else{
275 TeamOrPersonBase<?> authorKomb = (TeamOrPersonBase<?>) state.getRelatedObject(RedListUtil.AUTHOR_NAMESPACE, kombSplit[i]);
276 name.setCombinationAuthorship(authorKomb);
277 }
278 }
279 }
280 else if(authorKombString.trim().contains(RedListUtil.AUCT)){
281 RedListUtil.logMessage(id, "AUCT information in "+RedListUtil.AUTOR_KOMB+" column", logger);
282 }
283 else if(CdmUtils.isNotBlank(authorKombString)){
284 TeamOrPersonBase<?> authorKomb = (TeamOrPersonBase<?>) state.getRelatedObject(RedListUtil.AUTHOR_NAMESPACE, authorKombString);
285 name.setCombinationAuthorship(authorKomb);
286 }
287 //basionym author
288 if(authorBasiString.contains(RedListUtil.EX)){
289 String[] basiSplit = authorBasiString.split(RedListUtil.EX);
290 for (int i = 0; i < basiSplit.length; i++) {
291 if(basiSplit.length!=2){
292 RedListUtil.logMessage(id, "Multiple ex basionymn authors found", logger);
293 }
294 if(i==0){
295 TeamOrPersonBase<?> authorBasi= (TeamOrPersonBase<?>) state.getRelatedObject(RedListUtil.AUTHOR_NAMESPACE, basiSplit[i]);
296 if(CdmUtils.isBlank(authorKombString)){
297 name.setExCombinationAuthorship(authorBasi);
298 }
299 else{
300 name.setExBasionymAuthorship(authorBasi);
301 }
302 }
303 else{
304 TeamOrPersonBase<?> authorBasi= (TeamOrPersonBase<?>) state.getRelatedObject(RedListUtil.AUTHOR_NAMESPACE, basiSplit[i]);
305 if(CdmUtils.isBlank(authorKombString)){
306 name.setCombinationAuthorship(authorBasi);
307 }
308 else{
309 name.setBasionymAuthorship(authorBasi);
310 }
311 }
312 }
313 }
314 else if(CdmUtils.isNotBlank(authorBasiString)){
315 //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
316 TeamOrPersonBase<?> authorBasi= (TeamOrPersonBase<?>) state.getRelatedObject(RedListUtil.AUTHOR_NAMESPACE, authorBasiString);
317 if(CdmUtils.isBlank(authorKombString)){
318 name.setCombinationAuthorship(authorBasi);
319 }
320 else{
321 name.setBasionymAuthorship(authorBasi);
322 }
323 }
324
325 //check authorship consistency
326 String authorString = rs.getString(RedListUtil.AUTOR);
327 checkNameConsistency(id, nomZusatzString, taxZusatzString, zusatzString, authorString, hybString, name);
328 }
329
330 private NonViralName<?> importName(RedListGefaesspflanzenImportState state, ResultSet rs, Set<TaxonNameBase> namesToSave) throws SQLException {
331
332 long id = rs.getLong(RedListUtil.NAMNR);
333 String taxNameString = rs.getString(RedListUtil.TAXNAME);
334 String rangString = rs.getString(RedListUtil.RANG);
335 String ep1String = rs.getString(RedListUtil.EPI1);
336 String ep2String = rs.getString(RedListUtil.EPI2);
337 String ep3String = rs.getString(RedListUtil.EPI3);
338 String nomZusatzString = rs.getString(RedListUtil.NOM_ZUSATZ);
339 String hybString = rs.getString(RedListUtil.HYB);
340 String formelString = rs.getString(RedListUtil.FORMEL);
341
342 if(CdmUtils.isBlank(taxNameString) && CdmUtils.isBlank(ep1String)){
343 RedListUtil.logMessage(id, "No name found!", logger);
344 }
345
346 NonViralName<?> name = null;
347 Rank rank = makeRank(id, state, rangString, ep3String!=null);
348 //cultivar
349 if(rank!= null && rank.equals(Rank.CULTIVAR())){
350 CultivarPlantName cultivar = CultivarPlantName.NewInstance(rank);
351 cultivar.setGenusOrUninomial(ep1String);
352 cultivar.setSpecificEpithet(ep2String);
353 cultivar.setCultivarName(ep3String);
354 name = cultivar;
355 }
356 //botanical names
357 else{
358 name = BotanicalName.NewInstance(rank);
359
360 //ep1 should always be present
361 if(CdmUtils.isBlank(ep1String)){
362 RedListUtil.logMessage(id, RedListUtil.EPI1+" is empty!", logger);
363 }
364 name.setGenusOrUninomial(ep1String);
365 if(CdmUtils.isNotBlank(ep2String)){
366 if(rank!=null && rank.isInfraGenericButNotSpeciesGroup()){
367 name.setInfraGenericEpithet(ep2String);
368 }
369 else{
370 name.setSpecificEpithet(ep2String);
371 }
372 }
373 if(CdmUtils.isNotBlank(ep3String)){
374 name.setInfraSpecificEpithet(ep3String);
375 }
376
377
378 //nomenclatural status
379 if(CdmUtils.isNotBlank(nomZusatzString)){
380 NomenclaturalStatusType statusType = makeNomenclaturalStatus(id, state, nomZusatzString);
381 if(statusType!=null){
382 NomenclaturalStatus status = NomenclaturalStatus.NewInstance(statusType);
383 //special case for invalid names where the DB entry contains
384 //additional information in brackets e.g. "nom. inval. (sine basion.)"
385 if(statusType.equals(NomenclaturalStatusType.INVALID())){
386 Pattern pattern = Pattern.compile("\\((.*?)\\)");
387 Matcher matcher = pattern.matcher(nomZusatzString);
388 if (matcher.find()){
389 status.setRuleConsidered(matcher.group(1));
390 }
391 }
392 name.addStatus(status);
393 }
394 }
395 //hybrid
396 if(CdmUtils.isNotBlank(hybString)){
397 //save hybrid formula
398 if(CdmUtils.isNotBlank(formelString)){
399 Annotation annotation = Annotation.NewDefaultLanguageInstance(formelString);
400 annotation.setAnnotationType(AnnotationType.TECHNICAL());
401 name.addAnnotation(annotation);
402 }
403 //more than two hybrids not yet handled by name parser
404 //TODO: use parser when implemented to fully support hybrids
405 if(taxNameString.split(RedListUtil.HYB_SIGN).length>2){
406 name = BotanicalName.NewInstance(rank);
407 name.setTitleCache(taxNameString, true);
408 }
409 else if(hybString.equals(RedListUtil.HYB_X)){
410 name.setBinomHybrid(true);
411 }
412 else if(hybString.equals(RedListUtil.HYB_G)){
413 name.setMonomHybrid(true);
414 }
415 else if(hybString.equals(RedListUtil.HYB_XF)){
416 name.setHybridFormula(true);
417 if(ep1String.contains(RedListUtil.HYB_SIGN)){
418 RedListUtil.logMessage(id, "EPI1 has hybrid signs but with flag: "+RedListUtil.HYB_XF, logger);
419 }
420 else if(ep2String.contains(RedListUtil.HYB_SIGN)){
421 String[] split = ep2String.split(RedListUtil.HYB_SIGN);
422 String hybridFormula1 = ep1String+" "+split[0].trim();
423 String hybridFormula2 = ep1String+" "+split[1].trim();
424 //check if the genus is mentioned in EP2 or not
425 String[] secondHybrid = split[1].trim().split(" ");
426 //check if the genus is abbreviated like e.g. Centaurea jacea × C. decipiens
427 if(secondHybrid.length>1 && secondHybrid[0].matches("[A-Z]\\.")){
428 hybridFormula2 = ep1String+" "+split[1].trim().substring(2);
429 }
430 else if(secondHybrid.length>1 && secondHybrid[0].matches("[A-Z].*")){
431 hybridFormula2 = split[1];
432 }
433 if(CdmUtils.isNotBlank(ep3String)){
434 hybridFormula1 += " "+ep3String;
435 hybridFormula2 += " "+ep3String;
436 }
437 String fullFormula = hybridFormula1+" "+RedListUtil.HYB_SIGN+" "+hybridFormula2;
438 name = NonViralNameParserImpl.NewInstance().parseFullName(fullFormula, NomenclaturalCode.ICNAFP, rank);
439 }
440 else if(ep3String.contains(RedListUtil.HYB_SIGN)){
441 String[] split = ep3String.split(RedListUtil.HYB_SIGN);
442 String hybridFormula1 = ep1String+" "+ep2String+" "+split[0];
443 String hybridFormula2 = ep1String+" "+ep2String+" "+split[1];
444 //check if the genus is mentioned in EP3 or not
445 String[] secondHybrid = split[1].trim().split(" ");
446 //check if the genus is abbreviated like e.g. Centaurea jacea jacea × C. jacea subsp. decipiens
447 if(secondHybrid.length>1 && secondHybrid[0].matches("[A-Z]\\.")){
448 hybridFormula2 = ep1String+" "+split[1].trim().substring(2);
449 }
450 else if(secondHybrid.length>1 && secondHybrid[0].matches("[A-Z].*")){
451 hybridFormula2 = split[1];
452 }
453 String fullFormula = hybridFormula1+" "+RedListUtil.HYB_SIGN+" "+hybridFormula2;
454 name = NonViralNameParserImpl.NewInstance().parseFullName(fullFormula, NomenclaturalCode.ICNAFP, rank);
455 }
456 }
457 else if(hybString.equals(RedListUtil.HYB_N)){
458 name = NonViralNameParserImpl.NewInstance().parseFullName(taxNameString, NomenclaturalCode.ICNAFP, rank);
459 }
460 else if(hybString.equals(RedListUtil.HYB_GF)){
461 if(ep1String.contains(RedListUtil.HYB_SIGN)){
462 name = NonViralNameParserImpl.NewInstance().parseFullName(ep1String, NomenclaturalCode.ICNAFP, rank);
463 }
464 else{
465 RedListUtil.logMessage(id, "HYB is "+hybString+" but "+RedListUtil.HYB+" does not contain "+RedListUtil.HYB_SIGN, logger);
466 }
467 }
468 else if(hybString.equals(RedListUtil.HYB_XS)){
469 //nothing to do
470 }
471 else{
472 logger.error("HYB value "+hybString+" not yet handled");
473 }
474 }
475 }
476 //add source
477 ImportHelper.setOriginalSource(name, state.getTransactionalSourceReference(), id, RedListUtil.NAME_NAMESPACE);
478
479 namesToSave.add(name);
480 return name;
481 }
482
483 private void checkNameConsistency(long id, String nomZusatzString, String taxZusatzString,
484 String zusatzString, String authorString, String hybString, NonViralName<?> name) {
485 String authorshipCache = name.getAuthorshipCache();
486 //FIXME: remove split length check when name parser can parse multiple hybrid parents
487 if(hybString.equals(RedListUtil.HYB_XF) && name.getTitleCache().split(RedListUtil.HYB_SIGN).length==2){
488 if(name.getHybridChildRelations().isEmpty()){
489 RedListUtil.logMessage(id, "Hybrid formula but no hybrid child relations: "+name.getTitleCache(), logger);
490 return;
491 }
492 return;
493 }
494
495 if(CdmUtils.isNotBlank(zusatzString)){
496 authorString = authorString.replace(", "+zusatzString, "");
497 }
498 if(CdmUtils.isNotBlank(nomZusatzString)){
499 authorString = authorString.replace(", "+nomZusatzString, "");
500 }
501 if(CdmUtils.isNotBlank(taxZusatzString)){
502 authorString = authorString.replace(", "+taxZusatzString, "");
503 }
504 if(authorString.equals(RedListUtil.AUCT)){
505 authorString = "";
506 }
507 if(STRICT_TITLE_CHECK){
508 if(!authorString.equals(authorshipCache)){
509 RedListUtil.logMessage(id, "Authorship inconsistent! name.authorhshipCache <-> Column "+RedListUtil.AUTOR+": "+authorshipCache+" <-> "+authorString, logger);
510 }
511 }
512 else{
513 if(CdmUtils.isNotBlank(authorString) && !authorString.startsWith(authorshipCache)){
514 RedListUtil.logMessage(id, "Authorship inconsistent! name.authorhshipCache <-> Column "+RedListUtil.AUTOR+": "+authorshipCache+" <-> "+authorString, logger);
515 }
516 }
517 }
518
519 private void checkTaxonConsistency(long id, String taxNameString, String hybString, String epi1String, TaxonBase<?> taxonBase, RedListGefaesspflanzenImportState state) {
520 if(taxNameString.split(RedListUtil.HYB_SIGN).length>2){
521 RedListUtil.logMessage(id, "multiple hybrid signs. No name check for "+taxNameString, logger);
522 return;
523 }
524
525 String nameCache = HibernateProxyHelper.deproxy(taxonBase.getName(), NonViralName.class).getNameCache().trim();
526 taxNameString = taxNameString.trim();
527 taxNameString = taxNameString.replaceAll(" +", " ");
528
529 if(taxNameString.endsWith("agg.")){
530 taxNameString = taxNameString.replace("agg.", "aggr.");
531 }
532
533 if(hybString.equals(RedListUtil.HYB_X) || hybString.equals(RedListUtil.HYB_N)){
534 taxNameString = taxNameString.replace(" "+RedListUtil.HYB_SIGN+" ", " "+RedListUtil.HYB_SIGN);//hybrid sign has no space after it in titleCache for binomial hybrids
535 taxNameString = taxNameString.replace(" x ", " "+RedListUtil.HYB_SIGN);//in some cases a standard 'x' is used
536 }
537 else if(hybString.equals(RedListUtil.HYB_G)){
538 taxNameString = taxNameString.replace("X ", RedListUtil.HYB_SIGN);
539 }
540 else if(hybString.equals(RedListUtil.HYB_GF)){
541 taxNameString = taxNameString.replace(" "+RedListUtil.HYB_SIGN, " x");
542 }
543 else if(hybString.equals(RedListUtil.HYB_XF)){
544 nameCache = taxonBase.getName().getTitleCache();
545 if(nameCache.contains("sec")){
546 nameCache = nameCache.substring(0, nameCache.indexOf("sec"));
547 }
548 if(taxNameString.matches((".*[A-Z]\\..*"))){
549 taxNameString = taxNameString.replaceAll("[A-Z]\\.", epi1String);
550 }
551 if(taxNameString.matches((".*"+RedListUtil.HYB_SIGN+"\\s[a-z].*"))){
552 taxNameString = taxNameString.replaceAll(RedListUtil.HYB_SIGN+" ", RedListUtil.HYB_SIGN+" "+epi1String+" ");
553 }
554 }
555
556 if(taxNameString.endsWith("- Gruppe")){
557 taxNameString = taxNameString.replaceAll("- Gruppe", "species group");
558 }
559 if(taxNameString.endsWith("- group")){
560 taxNameString = taxNameString.replaceAll("- group", "species group");
561 }
562
563 taxNameString = taxNameString.replace("[ranglos]", "[unranked]");
564 if(taxonBase.getName().getRank()!=null){
565 if(taxonBase.getName().getRank().equals(Rank.PROLES())){
566 taxNameString = taxNameString.replace("proles", "prol.");
567 }
568 else if(taxonBase.getName().getRank().equals(state.getRank(RedListUtil.uuidRankCollectionSpecies))){
569 taxNameString = taxNameString.replace("\"Sammelart\"", "\"Coll. Species\"");
570 }
571 }
572 if(STRICT_TITLE_CHECK){
573 if(!taxNameString.trim().equals(nameCache)){
574 RedListUtil.logMessage(id, "Taxon name inconsistent! taxon.nameCache <-> Column "+RedListUtil.TAXNAME+": "+nameCache+" <-> "+taxNameString, logger);
575 }
576 }
577 else{
578 if(!taxNameString.startsWith(nameCache)){
579 RedListUtil.logMessage(id, "Taxon name inconsistent! taxon.nameCache <-> Column "+RedListUtil.TAXNAME+": "+nameCache+" <-> "+taxNameString, logger);
580 }
581 }
582 }
583
584 private Rank makeRank(long id, RedListGefaesspflanzenImportState state, String rankStr, boolean hasSpecificEpithet) {
585 Rank rank = null;
586 try {
587 if(rankStr.equals("ORA")){
588 //special handling for ORA because of two possibilities
589 if(hasSpecificEpithet){
590 return Rank.UNRANKED_INFRASPECIFIC();
591 }
592 else{
593 return Rank.UNRANKED_INFRAGENERIC();
594 }
595 }
596 else if(rankStr.equals("SAM")){
597 return getRank(state, RedListUtil.uuidRankCollectionSpecies, "Collective Species", "Collective Species", "\"Coll. Species\"", (OrderedTermVocabulary<Rank>) Rank.GENUS().getVocabulary(), null, RankClass.SpeciesGroup);
598 }
599 else if(rankStr.equals("SPR")){
600 return getRank(state, RedListUtil.uuidRankSubproles, "Subproles", "Subproles", "subproles", (OrderedTermVocabulary<Rank>) Rank.GENUS().getVocabulary(), null, RankClass.Infraspecific);
601 }
602 else if(rankStr.equals("MOD")){
603 return getRank(state, RedListUtil.uuidRankModification, "Modification", "Modification", "modificatio", (OrderedTermVocabulary<Rank>) Rank.GENUS().getVocabulary(), null, RankClass.Infraspecific);
604 }
605 else if(rankStr.equals("LUS")){
606 return getRank(state, RedListUtil.uuidRankLusus, "Lusus", "Lusus", "lusus", (OrderedTermVocabulary<Rank>) Rank.GENUS().getVocabulary(), null, RankClass.Infraspecific);
607 }
608 else{
609 rank = state.getTransformer().getRankByKey(rankStr);
610 }
611 } catch (UndefinedTransformerMethodException e) {
612 e.printStackTrace();
613 }
614 if(rank==null){
615 RedListUtil.logMessage(id, rankStr+" could not be associated to a known rank.", logger);
616 }
617 return rank;
618 }
619
620 private NomenclaturalStatusType makeNomenclaturalStatus(long id, RedListGefaesspflanzenImportState state, String nomZusatzString) {
621 NomenclaturalStatusType status = null;
622 try {
623 status = state.getTransformer().getNomenclaturalStatusByKey(nomZusatzString);
624 } catch (UndefinedTransformerMethodException e) {
625 e.printStackTrace();
626 }
627 if(status==null){
628 RedListUtil.logMessage(id, nomZusatzString+" could not be associated to a known nomenclatural status.", logger);
629 }
630 return status;
631 }
632
633
634
635 @Override
636 public Map<Object, Map<String, ? extends CdmBase>> getRelatedObjectsForPartition(ResultSet rs,
637 RedListGefaesspflanzenImportState state) {
638 Map<Object, Map<String, ? extends CdmBase>> result = new HashMap<>();
639 Map<String, AgentBase<?>> authorMap = new HashMap<String, AgentBase<?>>();
640
641 try {
642 while (rs.next()){
643 String authorKombString = rs.getString(RedListUtil.AUTOR_KOMB);
644
645 if(authorKombString.contains(RedListUtil.EX)){
646 String[] kombSplit = authorKombString.split(RedListUtil.EX);
647 for (int i = 0; i < kombSplit.length; i++) {
648 if(!authorMap.containsKey(kombSplit[i])){
649 authorMap.put(kombSplit[i], getAgentService().load(state.getAuthorMap().get(kombSplit[i])));
650 }
651 }
652 }
653 else if(CdmUtils.isNotBlank(authorKombString) && !authorMap.containsKey(authorKombString)){
654 authorMap.put(authorKombString, getAgentService().load(state.getAuthorMap().get(authorKombString)));
655 }
656
657 String authorBasiString = rs.getString(RedListUtil.AUTOR_BASI);
658 //basionym author
659 if(authorBasiString.contains(RedListUtil.EX)){
660 String[] basiSplit = authorBasiString.split(RedListUtil.EX);
661 for (int i = 0; i < basiSplit.length; i++) {
662 if(!authorMap.containsKey(basiSplit[i])){
663 authorMap.put(basiSplit[i], getAgentService().load(state.getAuthorMap().get(basiSplit[i])));
664 }
665 }
666 }
667 else if(CdmUtils.isNotBlank(authorBasiString) && !authorMap.containsKey(authorBasiString)){
668 authorMap.put(authorBasiString, getAgentService().load(state.getAuthorMap().get(authorBasiString)));
669 }
670 }
671 } catch (SQLException e) {
672 e.printStackTrace();
673 }
674 result.put(RedListUtil.AUTHOR_NAMESPACE, authorMap);
675
676 return result;
677 }
678
679 @Override
680 protected boolean doCheck(RedListGefaesspflanzenImportState state) {
681 return false;
682 }
683
684 @Override
685 protected boolean isIgnore(RedListGefaesspflanzenImportState state) {
686 return false;
687 }
688
689 }