1
2
3
4
5
6
7
8
9
10 package eu.etaxonomy.cdm.io.pesi.out;
11
12 import java.sql.Connection;
13 import java.sql.PreparedStatement;
14 import java.sql.SQLException;
15 import java.util.ArrayList;
16 import java.util.HashMap;
17 import java.util.List;
18 import java.util.Set;
19
20 import org.apache.log4j.Logger;
21 import org.springframework.stereotype.Component;
22 import org.springframework.transaction.TransactionStatus;
23
24 import eu.etaxonomy.cdm.io.berlinModel.out.mapper.MethodMapper;
25 import eu.etaxonomy.cdm.io.common.DbExportStateBase;
26 import eu.etaxonomy.cdm.io.common.Source;
27 import eu.etaxonomy.cdm.model.common.CdmBase;
28 import eu.etaxonomy.cdm.model.common.RelationshipBase;
29 import eu.etaxonomy.cdm.model.name.NameRelationship;
30 import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
31 import eu.etaxonomy.cdm.model.name.Rank;
32 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
33 import eu.etaxonomy.cdm.model.taxon.Synonym;
34 import eu.etaxonomy.cdm.model.taxon.SynonymRelationship;
35 import eu.etaxonomy.cdm.model.taxon.Taxon;
36 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
37 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
38 import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
39 import eu.etaxonomy.cdm.model.taxon.TaxonomicTree;
40
41
42
43
44
45
46
47
48 @Component
49 @SuppressWarnings("unchecked")
50 public class PesiRelTaxonExport extends PesiExportBase {
51 private static final Logger logger = Logger.getLogger(PesiRelTaxonExport.class);
52 private static final Class<? extends CdmBase> standardMethodParameter = RelationshipBase.class;
53
54 private static int modCount = 1000;
55 private static final String dbTableName = "RelTaxon";
56 private static final String pluralString = "Relationships";
57 private static PreparedStatement synonymsStmt;
58 private HashMap<Rank, Rank> rankMap = new HashMap<Rank, Rank>();
59 private List<Rank> rankList = new ArrayList<Rank>();
60 private PesiExportMapping mapping;
61 private int count = 0;
62 private boolean success = true;
63 private static NomenclaturalCode nomenclaturalCode;
64
65 public PesiRelTaxonExport() {
66 super();
67 }
68
69
70
71
72 @Override
73 public Class<? extends CdmBase> getStandardMethodParameter() {
74 return standardMethodParameter;
75 }
76
77
78
79
80 @Override
81 protected boolean doCheck(PesiExportState state) {
82 boolean result = true;
83 return result;
84 }
85
86
87
88
89 @Override
90 protected boolean doInvoke(PesiExportState state) {
91 try {
92 logger.error("*** Started Making " + pluralString + " ...");
93
94 Connection connection = state.getConfig().getDestination().getConnection();
95 String synonymsSql = "UPDATE Taxon SET KingdomFk = ?, RankFk = ?, RankCache = ? WHERE TaxonId = ?";
96 synonymsStmt = connection.prepareStatement(synonymsSql);
97
98
99 int pageSize = 1000;
100
101
102 int limit = state.getConfig().getLimitSave();
103
104
105 boolean success = true;
106
107
108 doDelete(state);
109
110
111 mapping = getMapping();
112
113
114 mapping.initialize(state);
115
116 TransactionStatus txStatus = null;
117 List<TaxonomicTree> taxonomicTreeList = null;
118
119
120 rankList.add(Rank.KINGDOM());
121 rankList.add(Rank.GENUS());
122
123
124 rankMap.put(Rank.GENUS(), null);
125 rankMap.put(Rank.KINGDOM(), Rank.GENUS());
126
127
128 txStatus = startTransaction(true);
129 logger.error("Started transaction. Fetching all Taxonomic Trees...");
130 taxonomicTreeList = getTaxonTreeService().listTaxonomicTrees(null, 0, null, null);
131 commitTransaction(txStatus);
132 logger.error("Committed transaction.");
133
134 logger.error("Fetched " + taxonomicTreeList.size() + " Taxonomic Tree.");
135
136 for (TaxonomicTree taxonomicTree : taxonomicTreeList) {
137 for (Rank rank : rankList) {
138
139 txStatus = startTransaction(true);
140 logger.error("Started transaction to fetch all rootNodes specific to Rank " + rank.getLabel() + " ...");
141
142 List<TaxonNode> rankSpecificRootNodes = getTaxonTreeService().loadRankSpecificRootNodes(taxonomicTree, rank, null);
143 logger.error("Fetched " + rankSpecificRootNodes.size() + " RootNodes for Rank " + rank.getLabel());
144
145 commitTransaction(txStatus);
146 logger.error("Committed transaction.");
147
148 for (TaxonNode rootNode : rankSpecificRootNodes) {
149 txStatus = startTransaction(false);
150 Rank endRank = rankMap.get(rank);
151 if (endRank != null) {
152 logger.error("Started transaction to traverse childNodes of rootNode (" + rootNode.getUuid() + ") till Rank " + endRank.getLabel() + " ...");
153 } else {
154 logger.error("Started transaction to traverse childNodes of rootNode (" + rootNode.getUuid() + ") till leaves are reached ...");
155 }
156
157 TaxonNode newNode = getTaxonNodeService().load(rootNode.getUuid());
158
159 TaxonNode parentNode = newNode.getParent();
160
161 traverseTree(newNode, parentNode, rankMap.get(rank), state);
162
163 commitTransaction(txStatus);
164 logger.error("Committed transaction.");
165
166 }
167 }
168 }
169
170 logger.error("*** Finished Making " + pluralString + " ..." + getSuccessString(success));
171
172
173 return success;
174 } catch (SQLException e) {
175 e.printStackTrace();
176 logger.error(e.getMessage());
177 return false;
178 }
179 }
180
181
182
183
184
185
186
187
188
189 private void traverseTree(TaxonNode childNode, TaxonNode parentNode, Rank fetchLevel, PesiExportState state) {
190
191 if (childNode.getTaxon() != null) {
192 TaxonNameBase taxonName = childNode.getTaxon().getName();
193 if (taxonName != null) {
194 Rank childTaxonNameRank = taxonName.getRank();
195 if (childTaxonNameRank != null) {
196 if (! childTaxonNameRank.equals(fetchLevel)) {
197
198 saveData(childNode, parentNode, state);
199
200 for (TaxonNode newNode : childNode.getChildNodes()) {
201 traverseTree(newNode, childNode, fetchLevel, state);
202 }
203
204 } else {
205
206 return;
207 }
208 } else {
209 logger.error("Rank is NULL. FetchLevel can not be checked: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
210 }
211 } else {
212 logger.error("TaxonName is NULL for this node: " + childNode.getUuid());
213 }
214
215 } else {
216 logger.error("Taxon is NULL for TaxonNode: " + childNode.getUuid());
217 }
218 }
219
220
221
222
223
224
225
226
227
228 private void saveData(TaxonNode childNode, TaxonNode parentNode, PesiExportState state) {
229 Taxon childNodeTaxon = childNode.getTaxon();
230 if (childNodeTaxon != null) {
231 TaxonNameBase childNodeTaxonName = childNodeTaxon.getName();
232 nomenclaturalCode = PesiTransformer.getNomenclaturalCode(childNodeTaxonName);
233
234 if (childNodeTaxonName != null) {
235
236
237 Set<Taxon> taxa = childNodeTaxonName.getTaxa();
238 if (taxa.size() == 1) {
239 Taxon taxon = CdmBase.deproxy(taxa.iterator().next(), Taxon.class);
240 Set<TaxonRelationship> taxonRelations = taxon.getRelationsToThisTaxon();
241 for (TaxonRelationship taxonRelationship : taxonRelations) {
242 try {
243 if (neededValuesNotNull(taxonRelationship, state)) {
244 doCount(count++, modCount, pluralString);
245 success &= mapping.invoke(taxonRelationship);
246 }
247 } catch (SQLException e) {
248 logger.error("TaxonRelationship could not be created for this TaxonRelation (" + taxonRelationship.getUuid() + "): " + e.getMessage());
249 }
250 }
251 } else if (taxa.size() > 1) {
252 logger.error("TaxonRelationship could not be created. This TaxonNode has " + taxa.size() + " Taxa: " + childNodeTaxon.getUuid() + " (" + childNodeTaxon.getTitleCache() + ")");
253 }
254
255
256 Set<NameRelationship> nameRelations = childNodeTaxonName.getRelationsFromThisName();
257 for (NameRelationship nameRelation : nameRelations) {
258 try {
259 if (neededValuesNotNull(nameRelation, state)) {
260 doCount(count++, modCount, pluralString);
261 success &= mapping.invoke(nameRelation);
262 }
263 } catch (SQLException e) {
264 logger.error("NameRelationship could not be created: " + e.getMessage());
265 }
266 }
267
268 }
269
270
271 Set<Synonym> synonyms = childNodeTaxon.getSynonyms();
272 for (Synonym synonym : synonyms) {
273 TaxonNameBase synonymTaxonName = synonym.getName();
274
275
276 invokeSynonyms(state, synonymTaxonName);
277
278 Set<SynonymRelationship> synonymRelations = synonym.getSynonymRelations();
279 for (SynonymRelationship synonymRelationship : synonymRelations) {
280 try {
281 if (neededValuesNotNull(synonymRelationship, state)) {
282 doCount(count++, modCount, pluralString);
283 success &= mapping.invoke(synonymRelationship);
284
285 }
286 } catch (SQLException e) {
287 logger.error("SynonymRelationship could not be created for this SynonymRelation (" + synonymRelationship.getUuid() + "): " + e.getMessage());
288 }
289 }
290
291
292 Set<NameRelationship> nameRelations = synonymTaxonName.getRelationsFromThisName();
293 for (NameRelationship nameRelation : nameRelations) {
294 try {
295 if (neededValuesNotNull(nameRelation, state)) {
296 doCount(count++, modCount, pluralString);
297 success &= mapping.invoke(nameRelation);
298 }
299 } catch (SQLException e) {
300 logger.error("NameRelationship could not be created for this NameRelation (" + nameRelation.getUuid() + "): " + e.getMessage());
301 }
302 }
303
304 }
305
306 }
307
308 }
309
310
311
312
313
314
315 private static void invokeSynonyms(PesiExportState state, TaxonNameBase synonymTaxonName) {
316
317 Integer kingdomFk = PesiTransformer.nomenClaturalCode2Kingdom(nomenclaturalCode);
318 Integer synonymFk = state.getDbId(synonymTaxonName);
319
320 saveSynonymData(synonymTaxonName, nomenclaturalCode, kingdomFk, synonymFk);
321 }
322
323
324
325
326
327
328
329
330
331 private static boolean saveSynonymData(TaxonNameBase taxonName,
332 NomenclaturalCode nomenclaturalCode, Integer kingdomFk,
333 Integer currentSynonymFk) {
334 try {
335 if (kingdomFk != null) {
336 synonymsStmt.setInt(1, kingdomFk);
337 } else {
338 synonymsStmt.setObject(1, null);
339 }
340
341 Integer rankFk = getRankFk(taxonName, nomenclaturalCode);
342 if (rankFk != null) {
343 synonymsStmt.setInt(2, rankFk);
344 } else {
345 synonymsStmt.setObject(2, null);
346 }
347 synonymsStmt.setString(3, getRankCache(taxonName, nomenclaturalCode));
348
349 if (currentSynonymFk != null) {
350 synonymsStmt.setInt(4, currentSynonymFk);
351 } else {
352 synonymsStmt.setObject(4, null);
353 }
354 synonymsStmt.executeUpdate();
355 return true;
356 } catch (SQLException e) {
357 logger.error("SQLException during invoke for taxonName - " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + "): " + e.getMessage());
358 e.printStackTrace();
359 return false;
360 }
361 }
362
363
364
365
366
367 private boolean neededValuesNotNull(RelationshipBase<?, ?, ?> relationship, PesiExportState state) {
368 boolean result = true;
369 if (getTaxonFk1(relationship, state) == null) {
370 logger.error("TaxonFk1 is NULL, but is not allowed to be. Therefore no record was written to export database for this relationship: " + relationship.getUuid());
371 result = false;
372 }
373 if (getTaxonFk2(relationship, state) == null) {
374 logger.error("TaxonFk2 is NULL, but is not allowed to be. Therefore no record was written to export database for this relationship: " + relationship.getUuid());
375 result = false;
376 }
377 return result;
378 }
379
380
381
382
383
384
385 protected boolean doDelete(PesiExportState state) {
386 PesiExportConfigurator pesiConfig = (PesiExportConfigurator) state.getConfig();
387
388 String sql;
389 Source destination = pesiConfig.getDestination();
390
391
392 sql = "DELETE FROM " + dbTableName;
393 destination.setQuery(sql);
394 destination.update(sql);
395 return true;
396 }
397
398
399
400
401 @Override
402 protected boolean isIgnore(PesiExportState state) {
403 return ! state.getConfig().isDoRelTaxa();
404 }
405
406
407
408
409
410
411
412
413 private static Integer getTaxonFk1(RelationshipBase<?, ?, ?> relationship, PesiExportState state) {
414 return getObjectFk(relationship, state, true);
415 }
416
417
418
419
420
421
422
423
424 private static Integer getTaxonFk2(RelationshipBase<?, ?, ?> relationship, PesiExportState state) {
425 return getObjectFk(relationship, state, false);
426 }
427
428
429
430
431
432
433
434 @SuppressWarnings("unused")
435 private static Integer getRelTaxonQualifierFk(RelationshipBase<?, ?, ?> relationship) {
436 return PesiTransformer.taxonRelation2RelTaxonQualifierFk(relationship);
437 }
438
439
440
441
442
443
444
445 @SuppressWarnings("unused")
446 private static String getRelQualifierCache(RelationshipBase<?, ?, ?> relationship) {
447 String result = null;
448 if (nomenclaturalCode != null) {
449 if (nomenclaturalCode.equals(NomenclaturalCode.ICZN)) {
450 result = PesiTransformer.zoologicalTaxonRelation2RelTaxonQualifierCache(relationship);
451 } else {
452 result = PesiTransformer.taxonRelation2RelTaxonQualifierCache(relationship);
453 }
454 } else {
455 logger.error("NomenclaturalCode is NULL while creating the following relationship: " + relationship.getUuid());
456 }
457 return result;
458 }
459
460
461
462
463
464
465
466 @SuppressWarnings("unused")
467 private static String getNotes(RelationshipBase<?, ?, ?> relationship) {
468
469 return null;
470 }
471
472
473
474
475
476
477
478
479 private static Integer getObjectFk(RelationshipBase<?, ?, ?> relationship, PesiExportState state, boolean isFrom) {
480 TaxonBase<?> taxon = null;
481 if (relationship.isInstanceOf(TaxonRelationship.class)) {
482 TaxonRelationship tr = (TaxonRelationship)relationship;
483 taxon = (isFrom) ? tr.getFromTaxon(): tr.getToTaxon();
484 } else if (relationship.isInstanceOf(SynonymRelationship.class)) {
485 SynonymRelationship sr = (SynonymRelationship)relationship;
486 taxon = (isFrom) ? sr.getSynonym() : sr.getAcceptedTaxon();
487 } else if (relationship.isInstanceOf(NameRelationship.class)) {
488 NameRelationship nr = (NameRelationship)relationship;
489 TaxonNameBase taxonName = (isFrom) ? nr.getFromName() : nr.getToName();
490 return state.getDbId(taxonName);
491 }
492 if (taxon != null) {
493 return state.getDbId(taxon.getName());
494 }
495 logger.warn("No taxon found in state for relationship: " + relationship.toString());
496 return null;
497 }
498
499
500
501
502
503
504
505
506 private static Integer getRankFk(TaxonNameBase taxonName, NomenclaturalCode nomenclaturalCode) {
507 Integer result = null;
508 if (nomenclaturalCode != null) {
509 if (taxonName != null && taxonName.getRank() == null) {
510 logger.warn("Rank is null: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
511 }
512 result = PesiTransformer.rank2RankId(taxonName.getRank(), PesiTransformer.nomenClaturalCode2Kingdom(nomenclaturalCode));
513 if (result == null) {
514 logger.warn("Rank could not be determined for PESI-Kingdom-Id " + PesiTransformer.nomenClaturalCode2Kingdom(nomenclaturalCode) + " and TaxonName " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
515 }
516 }
517 return result;
518 }
519
520
521
522
523
524
525
526
527 private static String getRankCache(TaxonNameBase taxonName, NomenclaturalCode nomenclaturalCode) {
528 String result = null;
529 if (nomenclaturalCode != null) {
530 result = PesiTransformer.rank2RankCache(taxonName.getRank(), PesiTransformer.nomenClaturalCode2Kingdom(nomenclaturalCode));
531 }
532 return result;
533 }
534
535
536
537
538
539 private PesiExportMapping getMapping() {
540 PesiExportMapping mapping = new PesiExportMapping(dbTableName);
541
542 mapping.addMapper(MethodMapper.NewInstance("TaxonFk1", this.getClass(), "getTaxonFk1", standardMethodParameter, PesiExportState.class));
543 mapping.addMapper(MethodMapper.NewInstance("TaxonFk2", this.getClass(), "getTaxonFk2", standardMethodParameter, PesiExportState.class));
544 mapping.addMapper(MethodMapper.NewInstance("RelTaxonQualifierFk", this));
545 mapping.addMapper(MethodMapper.NewInstance("RelQualifierCache", this));
546 mapping.addMapper(MethodMapper.NewInstance("Notes", this));
547
548 return mapping;
549 }
550
551 }