2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
9 package eu
.etaxonomy
.cdm
.io
.redlist
.gefaesspflanzen
;
11 import java
.sql
.ResultSet
;
12 import java
.sql
.SQLException
;
13 import java
.util
.Arrays
;
14 import java
.util
.HashMap
;
15 import java
.util
.HashSet
;
17 import java
.util
.Map
.Entry
;
19 import java
.util
.UUID
;
21 import org
.apache
.logging
.log4j
.LogManager
;
22 import org
.apache
.logging
.log4j
.Logger
;
23 import org
.springframework
.stereotype
.Component
;
25 import eu
.etaxonomy
.cdm
.common
.CdmUtils
;
26 import eu
.etaxonomy
.cdm
.hibernate
.HibernateProxyHelper
;
27 import eu
.etaxonomy
.cdm
.io
.common
.DbImportBase
;
28 import eu
.etaxonomy
.cdm
.io
.common
.IPartitionedIO
;
29 import eu
.etaxonomy
.cdm
.io
.common
.ResultSetPartitioner
;
30 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
31 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
32 import eu
.etaxonomy
.cdm
.model
.common
.VerbatimTimePeriod
;
33 import eu
.etaxonomy
.cdm
.model
.reference
.Reference
;
34 import eu
.etaxonomy
.cdm
.model
.reference
.ReferenceFactory
;
35 import eu
.etaxonomy
.cdm
.model
.taxon
.Classification
;
36 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
37 import eu
.etaxonomy
.cdm
.model
.taxon
.SynonymType
;
38 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
39 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
40 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationshipType
;
47 @SuppressWarnings("serial")
48 public class RedListGefaesspflanzenImportClassification
extends DbImportBase
<RedListGefaesspflanzenImportState
, RedListGefaesspflanzenImportConfigurator
> {
50 private static final Logger logger
= LogManager
.getLogger();
52 private static final String tableName
= "Rote Liste Gefäßpflanzen";
54 private static final String pluralString
= "classifications";
56 public RedListGefaesspflanzenImportClassification() {
57 super(tableName
, pluralString
);
61 protected String
getIdQuery(RedListGefaesspflanzenImportState state
) {
62 return "SELECT SEQNUM "
63 + "FROM V_TAXATLAS_D20_EXPORT t "
68 protected String
getRecordQuery(RedListGefaesspflanzenImportConfigurator config
) {
69 String result
= "select distinct e.*, f.FAMILIE "
70 + "from V_TAXATLAS_D20_EXPORT e, GATTUNG_FAMILIE f "
71 + "where e.EPI1 = f.GATTUNG and e.SEQNUM IN (@IDSET)";
72 result
= result
.replace("@IDSET", IPartitionedIO
.ID_LIST_TOKEN
);
77 protected void doInvoke(RedListGefaesspflanzenImportState state
) {
78 Classification gesamtListe
= makeClassification("Gesamtliste", state
.getConfig().getClassificationUuid(), "Gesamtliste", null, RedListUtil
.gesamtListeReferenceUuid
, state
);
79 Classification checkliste
= makeClassification("Checkliste", RedListUtil
.checkListClassificationUuid
, "Checkliste", null, RedListUtil
.checkListReferenceUuid
, state
);
80 makeClassification("Ehrendorfer", RedListUtil
.uuidClassificationE
, "Ehrendorfer", null, RedListUtil
.uuidClassificationReferenceE
, state
);
81 makeClassification("Wisskirchen (Standardliste)", RedListUtil
.uuidClassificationW
, "Wisskirchen (Standardliste)", 1998, RedListUtil
.uuidClassificationReferenceW
, state
);
82 makeClassification("Korneck (Rote Liste)", RedListUtil
.uuidClassificationK
, "Korneck (Rote Liste)", 1996, RedListUtil
.uuidClassificationReferenceK
, state
);
83 makeClassification("Atlas (Westdeutschland)", RedListUtil
.uuidClassificationAW
, "Atlas (Westdeutschland)", 1988, RedListUtil
.uuidClassificationReferenceAW
, state
);
84 makeClassification("Atlas (Ostdeutschland)", RedListUtil
.uuidClassificationAO
, "Atlas (Ostdeutschland)", 1996, RedListUtil
.uuidClassificationReferenceAO
, state
);
85 makeClassification("Rothmaler", RedListUtil
.uuidClassificationR
, "Rothmaler", 2011, RedListUtil
.uuidClassificationReferenceR
, state
);
86 makeClassification("Oberdorfer", RedListUtil
.uuidClassificationO
, "Oberdorfer", 2001, RedListUtil
.uuidClassificationReferenceO
, state
);
87 makeClassification("Schmeil-Fitschen", RedListUtil
.uuidClassificationS
, "Schmeil-Fitschen", 2011, RedListUtil
.uuidClassificationReferenceS
, state
);
88 importFamilies(gesamtListe
, checkliste
, state
);
89 super.doInvoke(state
);
92 private void importFamilies(Classification gesamtListe
, Classification checkliste
, RedListGefaesspflanzenImportState state
) {
93 for(UUID uuid
:state
.getFamilyMap().values()){
94 Taxon family
= HibernateProxyHelper
.deproxy(getTaxonService().load(uuid
, true, Arrays
.asList(new String
[]{"*"})), Taxon
.class);
96 gesamtListe
.addParentChild(null, family
, null, null);
97 checkliste
.addParentChild(null, family
, null, null);
98 family
.setSec(gesamtListe
.getReference());
99 family
.setTitleCache(null);
101 getClassificationService().saveOrUpdate(gesamtListe
);
102 getClassificationService().saveOrUpdate(checkliste
);
107 public boolean doPartition(ResultSetPartitioner partitioner
, RedListGefaesspflanzenImportState state
) {
108 ResultSet rs
= partitioner
.getResultSet();
109 Classification gesamtListeClassification
= getClassificationService().load(state
.getConfig().getClassificationUuid());
110 Classification checklistClassification
= getClassificationService().load(RedListUtil
.checkListClassificationUuid
);
111 Classification classificationE
= getClassificationService().load(RedListUtil
.uuidClassificationE
);
112 Classification classificationW
= getClassificationService().load(RedListUtil
.uuidClassificationW
);
113 Classification classificationK
= getClassificationService().load(RedListUtil
.uuidClassificationK
);
114 Classification classificationAW
= getClassificationService().load(RedListUtil
.uuidClassificationAW
);
115 Classification classificationAO
= getClassificationService().load(RedListUtil
.uuidClassificationAO
);
116 Classification classificationR
= getClassificationService().load(RedListUtil
.uuidClassificationR
);
117 Classification classificationO
= getClassificationService().load(RedListUtil
.uuidClassificationO
);
118 Classification classificationS
= getClassificationService().load(RedListUtil
.uuidClassificationS
);
121 makeSingleTaxonNode(state
, rs
, gesamtListeClassification
, checklistClassification
,
122 classificationE
, classificationW
, classificationK
, classificationAW
123 , classificationAO
, classificationR
, classificationO
, classificationS
);
126 } catch (SQLException e
) {
130 logger
.info("Update classification (1000 nodes)");
131 getClassificationService().saveOrUpdate(gesamtListeClassification
);
132 getClassificationService().saveOrUpdate(checklistClassification
);
133 getClassificationService().saveOrUpdate(classificationE
);
134 getClassificationService().saveOrUpdate(classificationW
);
135 getClassificationService().saveOrUpdate(classificationK
);
136 getClassificationService().saveOrUpdate(classificationAW
);
137 getClassificationService().saveOrUpdate(classificationAO
);
138 getClassificationService().saveOrUpdate(classificationR
);
139 getClassificationService().saveOrUpdate(classificationO
);
140 getClassificationService().saveOrUpdate(classificationS
);
144 private void makeSingleTaxonNode(RedListGefaesspflanzenImportState state
, ResultSet rs
,
145 Classification gesamtListeClassification
, Classification checklistClassification
,
146 Classification classificationE
, Classification classificationW
, Classification classificationK
,
147 Classification classificationAW
, Classification classificationAO
, Classification classificationR
,
148 Classification classificationO
, Classification classificationS
)
149 throws SQLException
{
150 long id
= rs
.getLong(RedListUtil
.NAMNR
);
151 String parentId
= String
.valueOf(rs
.getLong(RedListUtil
.LOWER
));
152 String gueltString
= rs
.getString(RedListUtil
.GUELT
);
153 String taxZusatzString
= rs
.getString(RedListUtil
.TAX_ZUSATZ
);
154 String familieString
= rs
.getString(RedListUtil
.FAMILIE
);
155 String clTaxonString
= rs
.getString(RedListUtil
.CL_TAXON
);
157 String relationE
= rs
.getString(RedListUtil
.E
);
158 String relationW
= rs
.getString(RedListUtil
.W
);
159 String relationK
= rs
.getString(RedListUtil
.K
);
160 String relationAW
= rs
.getString(RedListUtil
.AW
);
161 String relationAO
= rs
.getString(RedListUtil
.AO
);
162 String relationR
= rs
.getString(RedListUtil
.R
);
163 String relationO
= rs
.getString(RedListUtil
.O
);
164 String relationS
= rs
.getString(RedListUtil
.S
);
167 TaxonBase
<?
> taxonBase
= state
.getRelatedObject(RedListUtil
.TAXON_GESAMTLISTE_NAMESPACE
, String
.valueOf(id
), TaxonBase
.class);
168 taxonBase
.setSec(gesamtListeClassification
.getReference());
169 Taxon parent
= state
.getRelatedObject(RedListUtil
.TAXON_GESAMTLISTE_NAMESPACE
, parentId
, Taxon
.class);
170 if(parent
!=null && !parent
.isInstanceOf(Taxon
.class)){
171 RedListUtil
.logMessage(id
, parent
+" is no taxon but is a parent of "+taxonBase
+" (Gesamtliste)", logger
);
173 //add to family if no parent found
175 if(!taxonBase
.isInstanceOf(Taxon
.class)){
176 RedListUtil
.logMessage(id
, taxonBase
+" has no parent but is not a taxon.", logger
);
179 Taxon family
= (Taxon
) state
.getRelatedObject(RedListUtil
.FAMILY_NAMESPACE_GESAMTLISTE
, familieString
);
180 gesamtListeClassification
.addParentChild(family
, HibernateProxyHelper
.deproxy(taxonBase
, Taxon
.class), null, null);
181 //Buttler/Checklist taxon
182 if(CdmUtils
.isNotBlank(clTaxonString
) && clTaxonString
.equals(RedListUtil
.CL_TAXON_B
)){
183 checklistClassification
.addParentChild(family
, HibernateProxyHelper
.deproxy(taxonBase
, Taxon
.class), null, null);
184 taxonBase
.setSec(checklistClassification
.getReference());
186 if(family
.getTaxonNodes().isEmpty()){
187 gesamtListeClassification
.addChildTaxon(family
, null, null);
188 //do not add empty families to checklist classification
189 if(!getClassificationService().listChildNodesOfTaxon(family
.getUuid(), RedListUtil
.checkListClassificationUuid
,
190 true, null, null, null).isEmpty()){
191 checklistClassification
.addChildTaxon(family
, null, null);
196 //add to higher taxon
198 createParentChildNodes(gesamtListeClassification
, id
, gueltString
, taxZusatzString
, taxonBase
, parent
);
199 //Buttler/Checklist taxon
200 if(CdmUtils
.isNotBlank(clTaxonString
) && clTaxonString
.equals(RedListUtil
.CL_TAXON_B
)){
201 if(!checklistClassification
.isTaxonInTree(parent
)){
202 RedListUtil
.logInfoMessage(id
, parent
+" is parent taxon but is not in checklist. Skipping child "+taxonBase
, logger
);
205 if(taxonBase
.isInstanceOf(Taxon
.class)){
206 createParentChildNodes(checklistClassification
, id
, gueltString
, taxZusatzString
, taxonBase
, parent
);
208 else if(taxonBase
.isInstanceOf(Synonym
.class)){
209 //if it is a synonym it is already added to the accepted taxon
210 //so we just change the sec reference
211 taxonBase
.setSec(checklistClassification
.getReference());
212 taxonBase
.setTitleCache(null);
218 taxonBase
.setTitleCache(null, false);//refresh title cache
220 //add taxa for concept relationships to E, W, K, AW, AO, R, O, S
221 addTaxonToClassification(classificationE
, RedListUtil
.CLASSIFICATION_NAMESPACE_E
, relationE
, taxonBase
, id
, state
);
222 addTaxonToClassification(classificationW
, RedListUtil
.CLASSIFICATION_NAMESPACE_W
, relationW
, taxonBase
, id
, state
);
223 addTaxonToClassification(classificationK
, RedListUtil
.CLASSIFICATION_NAMESPACE_K
, relationK
, taxonBase
, id
, state
);
224 addTaxonToClassification(classificationAW
, RedListUtil
.CLASSIFICATION_NAMESPACE_AW
, relationAW
, taxonBase
, id
, state
);
225 addTaxonToClassification(classificationAO
, RedListUtil
.CLASSIFICATION_NAMESPACE_AO
, relationAO
, taxonBase
, id
, state
);
226 addTaxonToClassification(classificationR
, RedListUtil
.CLASSIFICATION_NAMESPACE_R
, relationR
, taxonBase
, id
, state
);
227 addTaxonToClassification(classificationO
, RedListUtil
.CLASSIFICATION_NAMESPACE_O
, relationO
, taxonBase
, id
, state
);
228 addTaxonToClassification(classificationS
, RedListUtil
.CLASSIFICATION_NAMESPACE_S
, relationS
, taxonBase
, id
, state
);
231 private void addTaxonToClassification(Classification classification
, String classificationNamespace
, String relationString
, final TaxonBase
<?
> gesamtListeTaxon
, long id
, RedListGefaesspflanzenImportState state
){
232 Taxon taxon
= HibernateProxyHelper
.deproxy(state
.getRelatedObject(classificationNamespace
, String
.valueOf(id
), TaxonBase
.class), Taxon
.class);
233 //add concept relation to gesamtliste/checkliste
234 if(taxon
!=null && isNotBlank(relationString
) && !relationString
.equals(".")){
235 //if the related concept in gesamtliste/checkliste is a synonym then we
236 //create a relation to the accepted taxon
237 Taxon acceptedGesamtListeTaxon
= getAcceptedTaxon(gesamtListeTaxon
);
238 String relationSubstring
= relationString
.substring(relationString
.length()-1, relationString
.length());
239 TaxonRelationshipType taxonRelationshipTypeByKey
= new RedListGefaesspflanzenTransformer().getTaxonRelationshipTypeByKey(relationSubstring
);
240 if(taxonRelationshipTypeByKey
==null){
241 RedListUtil
.logMessage(id
, "Could not interpret relationship "+relationString
+" for taxon "+gesamtListeTaxon
.generateTitle(), logger
);
243 //there is no type "included in" so we have to reverse the direction
244 if(relationSubstring
.equals("<")){
245 if(acceptedGesamtListeTaxon
!=null){
246 acceptedGesamtListeTaxon
.addTaxonRelation(taxon
, taxonRelationshipTypeByKey
, null, null);
250 if(acceptedGesamtListeTaxon
!=null){
251 taxon
.addTaxonRelation(acceptedGesamtListeTaxon
, taxonRelationshipTypeByKey
, null, null);
255 taxon
.setSec(classification
.getReference());
256 classification
.addChildTaxon(taxon
, null, null);
257 taxon
.setTitleCache(null);//Reset title cache to see sec ref in title
261 private void createParentChildNodes(Classification classification
, long id
, String gueltString
,
262 String taxZusatzString
, TaxonBase
<?
> taxonBase
, Taxon parent
) {
264 RedListUtil
.logMessage(id
, "child taxon/synonym of "+parent
+" is null. ("+classification
.generateTitle()+")" , logger
);
268 if(taxonBase
.isInstanceOf(Taxon
.class)){
270 String appendedPhrase
= taxonBase
.getAppendedPhrase();
271 if(appendedPhrase
!=null && appendedPhrase
.equals(RedListUtil
.AUCT
)){
273 RedListUtil
.logMessage(id
, "parent taxon of misapplied name "+taxonBase
+" is null. ("+classification
.getTitleCache()+")" , logger
);
276 parent
.addMisappliedName((Taxon
) taxonBase
, null, null);
277 //return because misapplied names do not have sec references
281 classification
.addParentChild(parent
, (Taxon
)taxonBase
, null, null);
284 if(isNotBlank(taxZusatzString
)){
285 if(taxZusatzString
.trim().equals("p. p.")){
286 RedListUtil
.logMessage(id
, "pro parte for accepted taxon "+taxonBase
, logger
);
291 else if(taxonBase
.isInstanceOf(Synonym
.class)){
293 RedListUtil
.logMessage(id
, "parent taxon of synonym "+taxonBase
+" is null. ("+classification
.getTitleCache()+")" , logger
);
297 if(gueltString
.equals(RedListUtil
.GUELT_BASIONYM
)){
298 parent
.addHomotypicSynonym((Synonym
) taxonBase
);
299 parent
.getName().addBasionym(taxonBase
.getName());
303 Synonym synonym
= (Synonym
) taxonBase
;
304 parent
.addSynonym(synonym
, SynonymType
.HETEROTYPIC_SYNONYM_OF
);
307 if(isNotBlank(taxZusatzString
)){
308 if(taxZusatzString
.trim().equals("p. p.")){
309 logger
.warn(id
+ ": p. p. not implemented anymore");
311 else if(taxZusatzString
.trim().equals("s. l. p. p.")){
312 logger
.warn(id
+ ": p. p. not implemented anymore");
313 taxonBase
.setAppendedPhrase("s. l.");
315 else if(taxZusatzString
.trim().equals("s. str. p. p.")){
316 logger
.warn(id
+ ": p. p. not implemented anymore");
317 taxonBase
.setAppendedPhrase("s. str.");
319 else if(taxZusatzString
.trim().equals("s. l.")
320 || taxZusatzString
.trim().equals("s. str.")){
321 taxonBase
.setAppendedPhrase(taxZusatzString
);
324 RedListUtil
.logMessage(id
, "unknown value "+taxZusatzString
+" for column "+RedListUtil
.TAX_ZUSATZ
, logger
);
330 taxonBase
.setSec(classification
.getReference());
334 public Map
<Object
, Map
<String
, ?
extends CdmBase
>> getRelatedObjectsForPartition(ResultSet rs
,
335 RedListGefaesspflanzenImportState state
) {
336 Map
<Object
, Map
<String
, ?
extends CdmBase
>> result
= new HashMap
<>();
338 Set
<String
> idSet
= new HashSet
<>();
341 idSet
.add(String
.valueOf(rs
.getLong(RedListUtil
.NAMNR
)));
342 idSet
.add(String
.valueOf(rs
.getLong(RedListUtil
.LOWER
)));
344 } catch (SQLException e
) {
347 //add taxa and their parent taxa
348 result
.put(RedListUtil
.TAXON_GESAMTLISTE_NAMESPACE
, getCommonService().getSourcedObjectsByIdInSourceC(TaxonBase
.class, idSet
, RedListUtil
.TAXON_GESAMTLISTE_NAMESPACE
));
349 result
.put(RedListUtil
.CLASSIFICATION_NAMESPACE_E
, getCommonService().getSourcedObjectsByIdInSourceC(TaxonBase
.class, idSet
, RedListUtil
.CLASSIFICATION_NAMESPACE_E
));
350 result
.put(RedListUtil
.CLASSIFICATION_NAMESPACE_W
, getCommonService().getSourcedObjectsByIdInSourceC(TaxonBase
.class, idSet
, RedListUtil
.CLASSIFICATION_NAMESPACE_W
));
351 result
.put(RedListUtil
.CLASSIFICATION_NAMESPACE_K
, getCommonService().getSourcedObjectsByIdInSourceC(TaxonBase
.class, idSet
, RedListUtil
.CLASSIFICATION_NAMESPACE_K
));
352 result
.put(RedListUtil
.CLASSIFICATION_NAMESPACE_AW
, getCommonService().getSourcedObjectsByIdInSourceC(TaxonBase
.class, idSet
, RedListUtil
.CLASSIFICATION_NAMESPACE_AW
));
353 result
.put(RedListUtil
.CLASSIFICATION_NAMESPACE_AO
, getCommonService().getSourcedObjectsByIdInSourceC(TaxonBase
.class, idSet
, RedListUtil
.CLASSIFICATION_NAMESPACE_AO
));
354 result
.put(RedListUtil
.CLASSIFICATION_NAMESPACE_R
, getCommonService().getSourcedObjectsByIdInSourceC(TaxonBase
.class, idSet
, RedListUtil
.CLASSIFICATION_NAMESPACE_R
));
355 result
.put(RedListUtil
.CLASSIFICATION_NAMESPACE_O
, getCommonService().getSourcedObjectsByIdInSourceC(TaxonBase
.class, idSet
, RedListUtil
.CLASSIFICATION_NAMESPACE_O
));
356 result
.put(RedListUtil
.CLASSIFICATION_NAMESPACE_S
, getCommonService().getSourcedObjectsByIdInSourceC(TaxonBase
.class, idSet
, RedListUtil
.CLASSIFICATION_NAMESPACE_S
));
360 Map
<String
, Taxon
> familyMapGL
= new HashMap
<String
, Taxon
>();
361 for (Entry
<String
, UUID
> entry
: state
.getFamilyMap().entrySet()) {
362 familyMapGL
.put(entry
.getKey(), HibernateProxyHelper
.deproxy(getTaxonService().load(entry
.getValue()), Taxon
.class));
364 result
.put(RedListUtil
.FAMILY_NAMESPACE_GESAMTLISTE
, familyMapGL
);
368 private Classification
makeClassification(String classificationName
, UUID classificationUuid
, String referenceName
, Integer yearPublished
, UUID referenceUuid
, RedListGefaesspflanzenImportState state
) {
369 Classification classification
= Classification
.NewInstance(classificationName
, Language
.DEFAULT());
370 classification
.setUuid(classificationUuid
);
371 Reference reference
= ReferenceFactory
.newGeneric();
372 reference
.setTitle(referenceName
);
373 reference
.setUuid(referenceUuid
);
374 classification
.setReference(reference
);
375 if(yearPublished
!=null){
376 reference
.setDatePublished(VerbatimTimePeriod
.NewVerbatimInstance(yearPublished
));
378 return getClassificationService().save(classification
);
382 protected boolean doCheck(RedListGefaesspflanzenImportState state
) {
387 protected boolean isIgnore(RedListGefaesspflanzenImportState state
) {