6d961e049a932374344ee4dd8c954ac0cdb34e64
[cdmlib-apps.git] / cdm-pesi / src / main / java / eu / etaxonomy / cdm / io / pesi / out / PesiTaxonExport.java
1 // $Id$
2 /**
3 * Copyright (C) 2009 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
6 *
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
9 */
10 package eu.etaxonomy.cdm.io.pesi.out;
11
12 import java.sql.Connection;
13 import java.sql.PreparedStatement;
14 import java.sql.ResultSet;
15 import java.sql.SQLException;
16 import java.util.ArrayList;
17 import java.util.HashMap;
18 import java.util.List;
19 import java.util.Set;
20 import java.util.UUID;
21
22 import org.apache.commons.lang.StringUtils;
23 import org.apache.log4j.Logger;
24 import org.joda.time.DateTime;
25 import org.joda.time.format.DateTimeFormat;
26 import org.joda.time.format.DateTimeFormatter;
27 import org.springframework.stereotype.Component;
28 import org.springframework.transaction.TransactionStatus;
29
30 import eu.etaxonomy.cdm.common.CdmUtils;
31 import eu.etaxonomy.cdm.io.common.Source;
32 import eu.etaxonomy.cdm.io.common.mapping.out.DbExtensionMapper;
33 import eu.etaxonomy.cdm.io.common.mapping.out.DbObjectMapper;
34 import eu.etaxonomy.cdm.io.common.mapping.out.IdMapper;
35 import eu.etaxonomy.cdm.io.common.mapping.out.MethodMapper;
36 import eu.etaxonomy.cdm.io.common.mapping.out.ObjectChangeMapper;
37 import eu.etaxonomy.cdm.io.pesi.erms.ErmsTransformer;
38 import eu.etaxonomy.cdm.model.common.Annotation;
39 import eu.etaxonomy.cdm.model.common.AnnotationType;
40 import eu.etaxonomy.cdm.model.common.CdmBase;
41 import eu.etaxonomy.cdm.model.common.Extension;
42 import eu.etaxonomy.cdm.model.common.ExtensionType;
43 import eu.etaxonomy.cdm.model.common.IdentifiableSource;
44 import eu.etaxonomy.cdm.model.common.Language;
45 import eu.etaxonomy.cdm.model.name.NameTypeDesignation;
46 import eu.etaxonomy.cdm.model.name.NameTypeDesignationStatus;
47 import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
48 import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
49 import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
50 import eu.etaxonomy.cdm.model.name.NonViralName;
51 import eu.etaxonomy.cdm.model.name.Rank;
52 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
53 import eu.etaxonomy.cdm.model.name.ZoologicalName;
54 import eu.etaxonomy.cdm.model.reference.Reference;
55 import eu.etaxonomy.cdm.model.taxon.Classification;
56 import eu.etaxonomy.cdm.model.taxon.Synonym;
57 import eu.etaxonomy.cdm.model.taxon.Taxon;
58 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
59 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
60 import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
61 import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
62 import eu.etaxonomy.cdm.persistence.query.MatchMode;
63 import eu.etaxonomy.cdm.strategy.cache.TaggedText;
64
65 /**
66 * The export class for {@link eu.etaxonomy.cdm.model.name.TaxonNameBase TaxonNames}.<p>
67 * Inserts into DataWarehouse database table <code>Taxon</code>.
68 * It is divided into four phases:<p><ul>
69 * <li>Phase 1: Export of all {@link eu.etaxonomy.cdm.model.name.TaxonNameBase TaxonNames} except some data exported in the following phases.
70 * <li>Phase 2: Export of additional data: ParenTaxonFk and TreeIndex.
71 * <li>Phase 3: Export of additional data: Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk.
72 * <li>Phase 4: Export of Inferred Synonyms.</ul>
73 * @author e.-m.lee
74 * @date 23.02.2010
75 *
76 */
77 @Component
78 public class PesiTaxonExport extends PesiExportBase {
79 private static final Logger logger = Logger.getLogger(PesiTaxonExport.class);
80 private static final Class<? extends CdmBase> standardMethodParameter = TaxonBase.class;
81
82 private static int modCount = 1000;
83 private static final String dbTableName = "Taxon";
84 private static final String pluralString = "Taxa";
85 private static final String parentPluralString = "Taxa";
86 private PreparedStatement parentTaxonFk_TreeIndex_KingdomFkStmt;
87 private PreparedStatement rankTypeExpertsUpdateStmt;
88 private PreparedStatement rankUpdateStmt;
89 private NomenclaturalCode nomenclaturalCode;
90 private Integer kingdomFk;
91 private HashMap<Rank, Rank> rankMap = new HashMap<Rank, Rank>();
92 private List<Rank> rankList = new ArrayList<Rank>();
93 private static final UUID uuidTreeIndex = UUID.fromString("28f4e205-1d02-4d3a-8288-775ea8413009");
94 private AnnotationType treeIndexAnnotationType;
95 private static ExtensionType lastActionExtensionType;
96 private static ExtensionType lastActionDateExtensionType;
97 private static ExtensionType expertNameExtensionType;
98 private static ExtensionType speciesExpertNameExtensionType;
99 private static ExtensionType cacheCitationExtensionType;
100 private static ExtensionType expertUserIdExtensionType;
101 private static ExtensionType speciesExpertUserIdExtensionType;
102
103 /**
104 * @return the treeIndexAnnotationType
105 */
106 protected AnnotationType getTreeIndexAnnotationType() {
107 return treeIndexAnnotationType;
108 }
109
110 /**
111 * @param treeIndexAnnotationType the treeIndexAnnotationType to set
112 */
113 protected void setTreeIndexAnnotationType(AnnotationType treeIndexAnnotationType) {
114 this.treeIndexAnnotationType = treeIndexAnnotationType;
115 }
116
117 enum NamePosition {
118 beginning,
119 end,
120 between,
121 alone,
122 nowhere
123 }
124
125 public PesiTaxonExport() {
126 super();
127 }
128
129 /* (non-Javadoc)
130 * @see eu.etaxonomy.cdm.io.common.DbExportBase#getStandardMethodParameter()
131 */
132 @Override
133 public Class<? extends CdmBase> getStandardMethodParameter() {
134 return standardMethodParameter;
135 }
136
137 /* (non-Javadoc)
138 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doCheck(eu.etaxonomy.cdm.io.common.IoStateBase)
139 */
140 @Override
141 protected boolean doCheck(PesiExportState state) {
142 boolean result = true;
143 return result;
144 }
145
146
147 /**
148 * Returns the CDM to PESI specific export mappings.
149 * @return The {@link PesiExportMapping PesiExportMapping}.
150 */
151 private PesiExportMapping getMapping() {
152 PesiExportMapping mapping = new PesiExportMapping(dbTableName);
153 ExtensionType extensionType = null;
154
155 mapping.addMapper(IdMapper.NewInstance("TaxonId"));
156 mapping.addMapper(DbObjectMapper.NewInstance("sec", "sourceFk")); //OLD:mapping.addMapper(MethodMapper.NewInstance("SourceFK", this.getClass(), "getSourceFk", standardMethodParameter, PesiExportState.class));
157 mapping.addMapper(MethodMapper.NewInstance("TaxonStatusFk", this.getClass(), "getTaxonStatusFk", standardMethodParameter, PesiExportState.class));
158 mapping.addMapper(MethodMapper.NewInstance("TaxonStatusCache", this.getClass(), "getTaxonStatusCache", standardMethodParameter, PesiExportState.class));
159 // QualityStatus (Fk, Cache)
160 extensionType = (ExtensionType)getTermService().find(ErmsTransformer.uuidQualityStatus);
161 if (extensionType != null) {
162 mapping.addMapper(DbExtensionMapper.NewInstance(extensionType, "QualityStatusCache"));
163 } else {
164 mapping.addMapper(MethodMapper.NewInstance("QualityStatusCache", this));
165 }
166 mapping.addMapper(MethodMapper.NewInstance("QualityStatusFk", this)); // PesiTransformer.QualityStatusCache2QualityStatusFk?
167
168 mapping.addMapper(MethodMapper.NewInstance("GUID", this));
169 //TODO implement again
170 // mapping.addMapper(MethodMapper.NewInstance("IdInSource", this));
171
172 mapping.addMapper(MethodMapper.NewInstance("DerivedFromGuid", this));
173 mapping.addMapper(MethodMapper.NewInstance("CacheCitation", this));
174 mapping.addMapper(MethodMapper.NewInstance("OriginalDB", this));
175 mapping.addMapper(MethodMapper.NewInstance("LastAction", this));
176 mapping.addMapper(MethodMapper.NewInstance("LastActionDate", this));
177 mapping.addMapper(MethodMapper.NewInstance("ExpertName", this));
178 mapping.addMapper(MethodMapper.NewInstance("SpeciesExpertName", this));
179
180 mapping.addMapper(MethodMapper.NewInstance("AuthorString", this)); //For Taxon because Misallied Names are handled differently
181
182
183 mapping.addMapper(ObjectChangeMapper.NewInstance(TaxonBase.class, TaxonNameBase.class, "Name"));
184 mapping.addMapper(MethodMapper.NewInstance("GenusOrUninomial", this, TaxonNameBase.class ));
185 mapping.addMapper(MethodMapper.NewInstance("InfraGenericEpithet", this, TaxonNameBase.class));
186 mapping.addMapper(MethodMapper.NewInstance("SpecificEpithet", this, TaxonNameBase.class));
187 mapping.addMapper(MethodMapper.NewInstance("InfraSpecificEpithet", this, TaxonNameBase.class));
188 mapping.addMapper(MethodMapper.NewInstance("WebSearchName", this, TaxonNameBase.class));
189 mapping.addMapper(MethodMapper.NewInstance("WebShowName", this, TaxonNameBase.class));
190 mapping.addMapper(MethodMapper.NewInstance("FullName", this, TaxonNameBase.class));
191 mapping.addMapper(MethodMapper.NewInstance("NomRefString", this, TaxonNameBase.class));
192
193 // DisplayName
194 extensionType = (ExtensionType)getTermService().find(ErmsTransformer.uuidDisplayName);
195 if (extensionType != null) {
196 mapping.addMapper(DbExtensionMapper.NewInstance(extensionType, "DisplayName"));
197 } else {
198 mapping.addMapper(MethodMapper.NewInstance("DisplayName", this, TaxonNameBase.class));
199 }
200
201 mapping.addMapper(MethodMapper.NewInstance("NameStatusFk", this, TaxonNameBase.class));
202 mapping.addMapper(MethodMapper.NewInstance("NameStatusCache", this, TaxonNameBase.class));
203 mapping.addMapper(MethodMapper.NewInstance("TypeFullnameCache", this, TaxonNameBase.class));
204
205
206 mapping.addMapper(MethodMapper.NewInstance("TypeDesignationStatusFk", this, TaxonNameBase.class));
207 mapping.addMapper(MethodMapper.NewInstance("TypeDesignationStatusCache", this, TaxonNameBase.class));
208
209 // FossilStatus (Fk, Cache)
210 extensionType = (ExtensionType)getTermService().find(ErmsTransformer.uuidFossilStatus);
211 if (extensionType != null) {
212 mapping.addMapper(DbExtensionMapper.NewInstance(extensionType, "FossilStatusCache"));
213 } else {
214 mapping.addMapper(MethodMapper.NewInstance("FossilStatusCache", this, TaxonNameBase.class));
215 }
216 mapping.addMapper(MethodMapper.NewInstance("FossilStatusFk", this, TaxonNameBase.class)); // PesiTransformer.FossilStatusCache2FossilStatusFk?
217
218 return mapping;
219 }
220
221 /* (non-Javadoc)
222 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doInvoke(eu.etaxonomy.cdm.io.common.IoStateBase)
223 */
224 @Override
225 protected void doInvoke(PesiExportState state) {
226 try {
227 logger.info("*** Started Making " + pluralString + " ...");
228
229 initPreparedStatements(state);
230
231 // Stores whether this invoke was successful or not.
232 boolean success = true;
233
234 // PESI: Clear the database table Taxon.
235 doDelete(state);
236
237 // Get specific mappings: (CDM) Taxon -> (PESI) Taxon
238 PesiExportMapping mapping = getMapping();
239
240 // Initialize the db mapper
241 mapping.initialize(state);
242
243 // Find extensionTypes
244 lastActionExtensionType = (ExtensionType)getTermService().find(PesiTransformer.lastActionUuid);
245 lastActionDateExtensionType = (ExtensionType)getTermService().find(PesiTransformer.lastActionDateUuid);
246 expertNameExtensionType = (ExtensionType)getTermService().find(PesiTransformer.expertNameUuid);
247 speciesExpertNameExtensionType = (ExtensionType)getTermService().find(PesiTransformer.speciesExpertNameUuid);
248 cacheCitationExtensionType = (ExtensionType)getTermService().find(PesiTransformer.cacheCitationUuid);
249 expertUserIdExtensionType = (ExtensionType)getTermService().find(PesiTransformer.expertUserIdUuid);
250 speciesExpertUserIdExtensionType = (ExtensionType)getTermService().find(PesiTransformer.speciesExpertUserIdUuid);
251
252 //Export Taxa..
253 success &= doPhaseOne(state, mapping);
254
255 // 2nd Round: Add ParentTaxonFk, TreeIndex to each Taxon
256 success &= doPhaseTwo(state);
257
258 //PHASE 3: Add Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk...
259 success &= doPhaseThree(state);
260
261 //"PHASE 4: Creating Inferred Synonyms...
262 success &= doPhaseFour(state, mapping);
263
264 logger.info("*** Finished Making " + pluralString + " ..." + getSuccessString(success));
265
266 if (!success){
267 state.setUnsuccessfull();
268 }
269 return;
270 } catch (SQLException e) {
271 e.printStackTrace();
272 logger.error(e.getMessage());
273 state.setUnsuccessfull();
274 return;
275 }
276 }
277
278 private void initPreparedStatements(PesiExportState state) throws SQLException {
279 initTreeIndexStatement(state);
280 initRankExpertsUpdateStmt(state);
281 initRankUpdateStatement(state);
282 }
283
284 // Prepare TreeIndex-And-KingdomFk-Statement
285 private void initTreeIndexStatement(PesiExportState state) throws SQLException {
286 Connection connection = state.getConfig().getDestination().getConnection();
287 String parentTaxonFk_TreeIndex_KingdomFkSql = "UPDATE Taxon SET ParentTaxonFk = ?, TreeIndex = ? WHERE TaxonId = ?";
288 parentTaxonFk_TreeIndex_KingdomFkStmt = connection.prepareStatement(parentTaxonFk_TreeIndex_KingdomFkSql);
289 }
290
291 private void initRankUpdateStatement(PesiExportState state) throws SQLException {
292 Connection connection = state.getConfig().getDestination().getConnection();
293 String rankSql = "UPDATE Taxon SET RankFk = ?, RankCache = ?, KingdomFk = ? WHERE TaxonId = ?";
294 rankUpdateStmt = connection.prepareStatement(rankSql);
295 }
296
297 private void initRankExpertsUpdateStmt(PesiExportState state) throws SQLException {
298 // String sql_old = "UPDATE Taxon SET RankFk = ?, RankCache = ?, TypeNameFk = ?, KingdomFk = ?, " +
299 // "ExpertFk = ?, SpeciesExpertFk = ? WHERE TaxonId = ?";
300 //TODO handle experts GUIDs
301 Connection connection = state.getConfig().getDestination().getConnection();
302
303 String sql = "UPDATE Taxon SET RankFk = ?, RankCache = ?, TypeNameFk = ?, KingdomFk = ? " +
304 " WHERE TaxonId = ?";
305 rankTypeExpertsUpdateStmt = connection.prepareStatement(sql);
306 }
307
308 private boolean doPhaseOne(PesiExportState state, PesiExportMapping mapping) throws SQLException {
309 int count = 0;
310 int pastCount = 0;
311 List<TaxonBase> list;
312 boolean success = true;
313 // Get the limit for objects to save within a single transaction.
314 int limit = state.getConfig().getLimitSave();
315
316
317 logger.info("PHASE 1: Export Taxa...");
318 // Start transaction
319 TransactionStatus txStatus = startTransaction(true);
320 logger.info("Started new transaction. Fetching some " + pluralString + " (max: " + limit + ") ...");
321 while ((list = getTaxonService().list(null, limit, count, null, null)).size() > 0) {
322
323 logger.info("Fetched " + list.size() + " " + pluralString + ". Exporting...");
324 for (TaxonBase<?> taxon : list) {
325 doCount(count++, modCount, pluralString);
326 success &= mapping.invoke(taxon);
327
328 TaxonNameBase<?,?> taxonName = taxon.getName();
329
330 // Check whether some rules are violated
331 nomenclaturalCode = PesiTransformer.getNomenclaturalCode(taxonName);
332 String genusOrUninomial = getGenusOrUninomial(taxonName);
333 String specificEpithet = getSpecificEpithet(taxonName);
334 String infraSpecificEpithet = getInfraSpecificEpithet(taxonName);
335 String infraGenericEpithet = getInfraGenericEpithet(taxonName);
336 Integer rank = getRankFk(taxonName, nomenclaturalCode);
337
338 if (rank == null) {
339 logger.error("Rank was not determined: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
340 } else {
341
342 // Check whether infraGenericEpithet is set correctly
343 // 1. Childs of an accepted taxon of rank subgenus that are accepted taxa of rank species have to have an infraGenericEpithet
344 // 2. Grandchilds of an accepted taxon of rank subgenus that are accepted taxa of rank subspecies have to have an infraGenericEpithet
345
346 int ancestorLevel = 0;
347 if (taxonName.getRank().equals(Rank.SUBSPECIES())) {
348 // The accepted taxon two rank levels above should be of rank subgenus
349 ancestorLevel = 2;
350 }
351 if (taxonName.getRank().equals(Rank.SPECIES())) {
352 // The accepted taxon one rank level above should be of rank subgenus
353 ancestorLevel = 1;
354 }
355 if (ancestorLevel > 0) {
356 if (ancestorOfSpecificRank(taxon, ancestorLevel, Rank.SUBGENUS())) {
357 // The child (species or subspecies) of this parent (subgenus) has to have an infraGenericEpithet
358 if (infraGenericEpithet == null) {
359 logger.warn("InfraGenericEpithet does not exist even though it should for: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
360 // maybe the taxon could be named here
361 }
362 }
363 }
364
365 if (infraGenericEpithet == null && rank.intValue() == 190) {
366 logger.warn("InfraGenericEpithet was not determined although it should exist for rank 190: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
367 }
368 if (specificEpithet != null && rank.intValue() < 220) {
369 logger.warn("SpecificEpithet was determined for rank " + rank + " although it should only exist for ranks higher or equal to 220: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
370 }
371 if (infraSpecificEpithet != null && rank.intValue() < 230) {
372 String message = "InfraSpecificEpithet '" +infraSpecificEpithet + "' was determined for rank " + rank + " although it should only exist for ranks higher or equal to 230: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")";
373 if (StringUtils.isNotBlank(infraSpecificEpithet)){
374 logger.warn(message);
375 }else{
376 logger.warn(message);
377 }
378 }
379 }
380 if (infraSpecificEpithet != null && specificEpithet == null) {
381 logger.error("An infraSpecificEpithet was determined, but a specificEpithet was not determined: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
382 }
383 if (genusOrUninomial == null) {
384 logger.error("GenusOrUninomial was not determined: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
385 }
386
387 }
388
389 // Commit transaction
390 commitTransaction(txStatus);
391 logger.debug("Committed transaction.");
392 logger.info("Exported " + (count - pastCount) + " " + pluralString + ". Total: " + count);
393 pastCount = count;
394
395 // Start transaction
396 txStatus = startTransaction(true);
397 logger.info("Started new transaction. Fetching some " + pluralString + " (max: " + limit + ") ...");
398 }
399 if (list.size() == 0) {
400 logger.info("No " + pluralString + " left to fetch.");
401 }
402 // Commit transaction
403 commitTransaction(txStatus);
404 logger.debug("Committed transaction.");
405 return success;
406 }
407
408 // 2nd Round: Add ParentTaxonFk, TreeIndex to each Taxon
409 private boolean doPhaseTwo(PesiExportState state) {
410 boolean success = true;
411 List<Classification> classificationList = null;
412 logger.info("PHASE 2: Add ParenTaxonFk and TreeIndex...");
413
414 // Specify starting ranks for tree traversing
415 rankList.add(Rank.KINGDOM());
416 rankList.add(Rank.GENUS());
417
418 // Specify where to stop traversing (value) when starting at a specific Rank (key)
419 rankMap.put(Rank.GENUS(), null); // Since NULL does not match an existing Rank, traverse all the way down to the leaves
420 rankMap.put(Rank.KINGDOM(), Rank.GENUS()); // excludes rank genus
421
422 StringBuffer treeIndex = new StringBuffer();
423
424 // Retrieve list of classifications
425 TransactionStatus txStatus = startTransaction(true);
426 logger.info("Started transaction. Fetching all classifications...");
427 classificationList = getClassificationService().listClassifications(null, 0, null, null);
428 commitTransaction(txStatus);
429 logger.debug("Committed transaction.");
430
431 logger.info("Fetched " + classificationList.size() + " classification(s).");
432
433 setTreeIndexAnnotationType(getAnnotationType(uuidTreeIndex, "TreeIndex", "", "TI"));
434
435 for (Classification classification : classificationList) {
436 for (Rank rank : rankList) {
437
438 txStatus = startTransaction(true);
439 logger.info("Started transaction to fetch all rootNodes specific to Rank " + rank.getLabel() + " ...");
440
441 List<TaxonNode> rankSpecificRootNodes = getClassificationService().loadRankSpecificRootNodes(classification, rank, null);
442 logger.info("Fetched " + rankSpecificRootNodes.size() + " RootNodes for Rank " + rank.getLabel());
443
444 commitTransaction(txStatus);
445 logger.debug("Committed transaction.");
446
447 for (TaxonNode rootNode : rankSpecificRootNodes) {
448 txStatus = startTransaction(false);
449 Rank endRank = rankMap.get(rank);
450 if (endRank != null) {
451 logger.debug("Started transaction to traverse childNodes of rootNode (" + rootNode.getUuid() + ") till Rank " + endRank.getLabel() + " ...");
452 } else {
453 logger.debug("Started transaction to traverse childNodes of rootNode (" + rootNode.getUuid() + ") till leaves are reached ...");
454 }
455
456 TaxonNode newNode = getTaxonNodeService().load(rootNode.getUuid());
457
458 TaxonNode parentNode = newNode.getParent();
459 if (rank.equals(Rank.KINGDOM())) {
460 treeIndex = new StringBuffer();
461 treeIndex.append("#");
462 } else {
463 // Get treeIndex from parentNode
464 if (parentNode != null) {
465 boolean annotationFound = false;
466 Set<Annotation> annotations = parentNode.getAnnotations();
467 for (Annotation annotation : annotations) {
468 AnnotationType annotationType = annotation.getAnnotationType();
469 if (annotationType != null && annotationType.equals(getTreeIndexAnnotationType())) {
470 treeIndex = new StringBuffer(CdmUtils.Nz(annotation.getText()));
471 annotationFound = true;
472 // logger.error("treeIndex: " + treeIndex);
473 break;
474 }
475 }
476 if (!annotationFound) {
477 // This should not happen because it means that the treeIndex was not set correctly as an annotation to parentNode
478 logger.error("TreeIndex could not be read from annotation of this TaxonNode: " + parentNode.getUuid());
479 treeIndex = new StringBuffer();
480 treeIndex.append("#");
481 }
482 } else {
483 // TreeIndex could not be determined, but it's unclear how to proceed to generate a correct treeIndex if the parentNode is NULL
484 logger.error("ParentNode for RootNode is NULL. TreeIndex could not be determined: " + newNode.getUuid());
485 treeIndex = new StringBuffer(); // This just prevents growing of the treeIndex in a wrong manner
486 treeIndex.append("#");
487 }
488 }
489
490 nomenclaturalCode = PesiTransformer.getNomenclaturalCode(newNode.getTaxon().getName());
491 kingdomFk = PesiTransformer.nomenClaturalCode2Kingdom(nomenclaturalCode);
492 traverseTree(newNode, parentNode, treeIndex, rankMap.get(rank), state);
493
494 commitTransaction(txStatus);
495 logger.debug("Committed transaction.");
496
497 }
498 }
499 }
500 return success;
501 }
502
503 //PHASE 3: Add Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk...
504 private boolean doPhaseThree(PesiExportState state) {
505 int count = 0;
506 int pastCount = 0;
507 boolean success = true;
508 // Get the limit for objects to save within a single transaction.
509 int limit = state.getConfig().getLimitSave();
510
511 List<TaxonNameBase> list;
512 logger.info("PHASE 3: Add Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk...");
513 // Be sure to add rank information, KingdomFk, TypeNameFk, expertFk and speciesExpertFk to every taxonName
514
515 // Start transaction
516 TransactionStatus txStatus = startTransaction(true);
517 logger.info("Started new transaction. Fetching some " + pluralString + " (max: " + limit + ") ...");
518 while ((list = getNameService().list(null, limit, count, null, null)).size() > 0) {
519
520 logger.info("Fetched " + list.size() + " " + pluralString + ". Exporting...");
521 for (TaxonNameBase<?,?> taxonName : list) {
522
523 // Determine expertFk
524 Integer expertFk = makeExpertFk(state, taxonName);
525
526 // Determine speciesExpertFk
527 Integer speciesExpertFk = makeSpeciesExpertFk(state, taxonName);
528
529 doCount(count++, modCount, pluralString);
530 Integer typeNameFk = getTypeNameFk(taxonName, state);
531
532 //TODO why are expertFks needed? (Andreas M.)
533 // if (expertFk != null || speciesExpertFk != null) {
534 invokeRankDataAndTypeNameFkAndKingdomFk(taxonName, nomenclaturalCode, state.getDbId(taxonName),
535 typeNameFk, kingdomFk, expertFk, speciesExpertFk);
536 // }
537 }
538
539 // Commit transaction
540 commitTransaction(txStatus);
541 logger.debug("Committed transaction.");
542 logger.info("Exported " + (count - pastCount) + " " + pluralString + ". Total: " + count);
543 pastCount = count;
544
545 // Start transaction
546 txStatus = startTransaction(true);
547 logger.info("Started new transaction. Fetching some " + pluralString + " (max: " + limit + ") ...");
548 }
549 if (list.size() == 0) {
550 logger.info("No " + pluralString + " left to fetch.");
551 }
552 // Commit transaction
553 commitTransaction(txStatus);
554 logger.debug("Committed transaction.");
555 return success;
556 }
557
558 private Integer makeSpeciesExpertFk(PesiExportState state, TaxonNameBase<?, ?> taxonName) {
559 List<Reference> referenceList;
560 Integer speciesExpertFk = null;
561 String speciesExpertUserId = getSpeciesExpertUserId(taxonName);
562 if (speciesExpertUserId != null) {
563
564 // The speciesExpertUserId was stored in the field 'title' of the corresponding Reference during FaEu import
565 referenceList = getReferenceService().listByReferenceTitle(null, speciesExpertUserId, MatchMode.EXACT, null, null, null, null, null);
566 if (referenceList.size() == 1) {
567 speciesExpertFk = getSpeciesExpertFk(referenceList.iterator().next(), state);
568 } else if (referenceList.size() > 1) {
569 logger.error("Found more than one match using listByTitle() searching for a Reference with this speciesExpertUserId as title: " + speciesExpertUserId);
570 } else if (referenceList.size() == 0) {
571 logger.error("Found no match using listByReferenceTitle() searching for a Reference with this speciesExpertUserId as title: " + speciesExpertUserId);
572 }
573 } else {
574 logger.debug("SpeciesExpertName is NULL for this TaxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
575 }
576 return speciesExpertFk;
577 }
578
579 private Integer makeExpertFk(PesiExportState state,
580 TaxonNameBase<?, ?> taxonName) {
581 List<Reference> referenceList;
582 Integer expertFk = null;
583 String expertUserId = getExpertUserId(taxonName);
584 if (expertUserId != null) {
585
586 // The expertUserId was stored in the field 'title' of the corresponding Reference during FaEu import
587 referenceList = getReferenceService().listByReferenceTitle(null, expertUserId, MatchMode.EXACT, null, null, null, null, null);
588 if (referenceList.size() == 1) {
589 expertFk = getExpertFk(referenceList.iterator().next(), state);
590 } else if (referenceList.size() > 1) {
591 logger.error("Found more than one match using listByReferenceTitle() searching for a Reference with this expertUserId as title: " + expertUserId);
592 } else if (referenceList.size() == 0) {
593 logger.error("Found no match using listByReferenceTitle() searching for a Reference with this expertUserId as title: " + expertUserId);
594 }
595 } else {
596 logger.debug("ExpertName is NULL for this TaxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
597 }
598 return expertFk;
599 }
600
601 private boolean doPhaseFour(PesiExportState state, PesiExportMapping mapping) throws SQLException {
602 int count;
603 int pastCount;
604 boolean success = true;
605 // Get the limit for objects to save within a single transaction.
606 int limit = state.getConfig().getLimitSave();
607
608 // Create inferred synonyms for accepted taxa
609 logger.info("PHASE 4: Creating Inferred Synonyms...");
610
611 // Determine the count of elements in datawarehouse database table Taxon
612 Integer currentTaxonId = determineTaxonCount(state);
613 currentTaxonId++;
614
615 count = 0;
616 pastCount = 0;
617 int pageSize = limit;
618 int pageNumber = 1;
619 String inferredSynonymPluralString = "Inferred Synonyms";
620
621 // Start transaction
622 Classification classification = null;
623 Taxon acceptedTaxon = null;
624 TransactionStatus txStatus = startTransaction(true);
625 logger.info("Started new transaction. Fetching some " + parentPluralString + " first (max: " + limit + ") ...");
626 List<TaxonBase> taxonList = null;
627 List<Synonym> inferredSynonyms = null;
628 while ((taxonList = getTaxonService().listTaxaByName(Taxon.class, "*", "*", "*", "*", null, pageSize, pageNumber)).size() > 0) {
629 HashMap<Integer, TaxonNameBase<?,?>> inferredSynonymsDataToBeSaved = new HashMap<Integer, TaxonNameBase<?,?>>();
630
631 logger.info("Fetched " + taxonList.size() + " " + parentPluralString + ". Exporting...");
632 for (TaxonBase<?> taxonBase : taxonList) {
633
634 if (taxonBase.isInstanceOf(Taxon.class)) { // this should always be the case since we should have fetched accepted taxon only, but you never know...
635 acceptedTaxon = CdmBase.deproxy(taxonBase, Taxon.class);
636 TaxonNameBase<?,?> taxonName = acceptedTaxon.getName();
637
638 if (taxonName.isInstanceOf(ZoologicalName.class)) {
639 nomenclaturalCode = PesiTransformer.getNomenclaturalCode(taxonName);
640 kingdomFk = PesiTransformer.nomenClaturalCode2Kingdom(nomenclaturalCode);
641
642 Set<TaxonNode> taxonNodes = acceptedTaxon.getTaxonNodes();
643 TaxonNode singleNode = null;
644 if (taxonNodes.size() > 0) {
645 // Determine the classification of the current TaxonNode
646 singleNode = taxonNodes.iterator().next();
647 if (singleNode != null) {
648 classification = singleNode.getClassification();
649 } else {
650 logger.error("A TaxonNode belonging to this accepted Taxon is NULL: " + acceptedTaxon.getUuid() + " (" + acceptedTaxon.getTitleCache() +")");
651 }
652 } else {
653 // Classification could not be determined directly from this TaxonNode
654 // The stored classification from another TaxonNode is used. It's a simple, but not a failsafe fallback solution.
655 if (classification == null) {
656 logger.error("Classification could not be determined directly from this TaxonNode: " + singleNode.getUuid() + "). " +
657 "This classification stored from another TaxonNode is used: " + classification.getTitleCache());
658 }
659 }
660
661 if (classification != null) {
662 inferredSynonyms = getTaxonService().createAllInferredSynonyms(classification, acceptedTaxon);
663
664 // inferredSynonyms = getTaxonService().createInferredSynonyms(classification, acceptedTaxon, SynonymRelationshipType.INFERRED_GENUS_OF());
665 if (inferredSynonyms != null) {
666 for (Synonym synonym : inferredSynonyms) {
667 TaxonNameBase<?,?> synonymName = synonym.getName();
668 if (synonymName != null) {
669
670 // Both Synonym and its TaxonName have no valid Id yet
671 synonym.setId(currentTaxonId++);
672 synonymName.setId(currentTaxonId++);
673
674 doCount(count++, modCount, inferredSynonymPluralString);
675 success &= mapping.invoke(synonymName);
676
677 // Add Rank Data and KingdomFk to hashmap for later saving
678 inferredSynonymsDataToBeSaved.put(synonymName.getId(), synonymName);
679 } else {
680 logger.error("TaxonName of this Synonym is NULL: " + synonym.getUuid() + " (" + synonym.getTitleCache() + ")");
681 }
682 }
683 }
684 } else {
685 logger.error("Classification is NULL. Inferred Synonyms could not be created for this Taxon: " + acceptedTaxon.getUuid() + " (" + acceptedTaxon.getTitleCache() + ")");
686 }
687 } else {
688 // logger.error("TaxonName is not a ZoologicalName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
689 }
690 } else {
691 logger.error("This TaxonBase is not a Taxon even though it should be: " + taxonBase.getUuid() + " (" + taxonBase.getTitleCache() + ")");
692 }
693 }
694
695 // Commit transaction
696 commitTransaction(txStatus);
697 logger.debug("Committed transaction.");
698 logger.info("Exported " + (count - pastCount) + " " + inferredSynonymPluralString + ". Total: " + count);
699 pastCount = count;
700
701 // Save Rank Data and KingdomFk for inferred synonyms
702 for (Integer taxonFk : inferredSynonymsDataToBeSaved.keySet()) {
703 invokeRankDataAndKingdomFk(inferredSynonymsDataToBeSaved.get(taxonFk), nomenclaturalCode, taxonFk, kingdomFk);
704 }
705
706 // Start transaction
707 txStatus = startTransaction(true);
708 logger.info("Started new transaction. Fetching some " + parentPluralString + " first (max: " + limit + ") ...");
709
710 // Increment pageNumber
711 pageNumber++;
712 }
713 if (taxonList.size() == 0) {
714 logger.info("No " + parentPluralString + " left to fetch.");
715 }
716 // Commit transaction
717 commitTransaction(txStatus);
718 logger.debug("Committed transaction.");
719 return success;
720 }
721
722 /**
723 * Determines the current number of entries in the DataWarehouse database table <code>Taxon</code>.
724 * @param state The {@link PesiExportState PesiExportState}.
725 * @return The count.
726 */
727 private Integer determineTaxonCount(PesiExportState state) {
728 Integer result = null;
729 PesiExportConfigurator pesiConfig = (PesiExportConfigurator) state.getConfig();
730
731 String sql;
732 Source destination = pesiConfig.getDestination();
733 sql = "SELECT COUNT(*) FROM Taxon";
734 destination.setQuery(sql);
735 ResultSet resultSet = destination.getResultSet();
736 try {
737 resultSet.next();
738 result = resultSet.getInt(1);
739 } catch (SQLException e) {
740 logger.error("TaxonCount could not be determined: " + e.getMessage());
741 e.printStackTrace();
742 }
743 return result;
744 }
745
746 /**
747 * Returns the userId of the expert associated with the given TaxonName.
748 * @param taxonName A {@link TaxonNameBase TaxonName}.
749 * @return The userId.
750 */
751 private String getExpertUserId(TaxonNameBase<?,?> taxonName) {
752 String result = null;
753 try {
754 Set<Extension> extensions = taxonName.getExtensions();
755 for (Extension extension : extensions) {
756 if (extension.getType().equals(expertUserIdExtensionType)) {
757 result = extension.getValue();
758 }
759 }
760 } catch (Exception e) {
761 e.printStackTrace();
762 }
763 return result;
764 }
765
766 /**
767 * Returns the userId of the speciesExpert associated with the given TaxonName.
768 * @param taxonName A {@link TaxonNameBase TaxonName}.
769 * @return The userId.
770 */
771 private String getSpeciesExpertUserId(TaxonNameBase<?,?> taxonName) {
772 String result = null;
773 try {
774 Set<Extension> extensions = taxonName.getExtensions();
775 for (Extension extension : extensions) {
776 if (extension.getType().equals(speciesExpertUserIdExtensionType)) {
777 result = extension.getValue();
778 }
779 }
780 } catch (Exception e) {
781 e.printStackTrace();
782 }
783 return result;
784 }
785
786 /**
787 * Checks whether a parent at specific level has a specific Rank.
788 * @param taxonName A {@link TaxonNameBase TaxonName}.
789 * @param level The ancestor level.
790 * @param ancestorRank The ancestor rank.
791 * @return Whether a parent at a specific level has a specific Rank.
792 */
793 private boolean ancestorOfSpecificRank(TaxonBase<?> taxonBase, int level, Rank ancestorRank) {
794 boolean result = false;
795 TaxonNode parentNode = null;
796 if (taxonBase.isInstanceOf(Taxon.class)){
797 Taxon taxon = CdmBase.deproxy(taxonBase, Taxon.class);
798 // Get ancestor Taxon via TaxonNode
799 Set<TaxonNode> taxonNodes = taxon.getTaxonNodes();
800 if (taxonNodes.size() == 1) {
801 TaxonNode taxonNode = taxonNodes.iterator().next();
802 if (taxonNode != null) {
803 for (int i = 0; i < level; i++) {
804 if (taxonNode != null) {
805 taxonNode = taxonNode.getParent();
806 }
807 }
808 parentNode = taxonNode;
809 }
810 } else if (taxonNodes.size() > 1) {
811 logger.error("This taxon has " + taxonNodes.size() + " taxonNodes: " + taxon.getUuid() + " (" + taxon.getTitleCache() + ")");
812 }
813 }
814 //compare
815 if (parentNode != null) {
816 TaxonNode node = CdmBase.deproxy(parentNode, TaxonNode.class);
817 Taxon parentTaxon = node.getTaxon();
818 if (parentTaxon != null) {
819 TaxonNameBase<?,?> parentTaxonName = parentTaxon.getName();
820 if (parentTaxonName != null && parentTaxonName.getRank().equals(ancestorRank)) {
821 result = true;
822 }
823 } else {
824 logger.error("This TaxonNode has no Taxon: " + node.getUuid());
825 }
826 }
827 return result;
828 }
829
830 /**
831 * Returns the AnnotationType for a given UUID.
832 * @param uuid The Annotation UUID.
833 * @param label The Annotation label.
834 * @param text The Annotation text.
835 * @param labelAbbrev The Annotation label abbreviation.
836 * @return The AnnotationType.
837 */
838 protected AnnotationType getAnnotationType(UUID uuid, String label, String text, String labelAbbrev){
839 AnnotationType annotationType = (AnnotationType)getTermService().find(uuid);
840 if (annotationType == null) {
841 annotationType = AnnotationType.NewInstance(label, text, labelAbbrev);
842 annotationType.setUuid(uuid);
843 // annotationType.setVocabulary(AnnotationType.EDITORIAL().getVocabulary());
844 getTermService().save(annotationType);
845 }
846 return annotationType;
847 }
848
849 /**
850 * Traverses the classification recursively and stores determined values for every Taxon.
851 * @param childNode The {@link TaxonNode TaxonNode} to process.
852 * @param parentNode The parent {@link TaxonNode TaxonNode} of the childNode.
853 * @param treeIndex The TreeIndex at the current level.
854 * @param fetchLevel Rank to stop fetching at.
855 * @param state The {@link PesiExportState PesiExportState}.
856 */
857 private void traverseTree(TaxonNode childNode, TaxonNode parentNode, StringBuffer treeIndex, Rank fetchLevel, PesiExportState state) {
858 // Traverse all branches from this childNode until specified fetchLevel is reached.
859 StringBuffer localTreeIndex = new StringBuffer(treeIndex);
860 if (childNode.getTaxon() != null) {
861 TaxonNameBase<?,?> taxonName = childNode.getTaxon().getName();
862 Integer taxonNameId = state.getDbId(taxonName);
863 if (taxonNameId != null) {
864 Rank childTaxonNameRank = taxonName.getRank();
865 if (childTaxonNameRank != null) {
866 if (! childTaxonNameRank.equals(fetchLevel)) {
867
868 localTreeIndex.append(taxonNameId);
869 localTreeIndex.append("#");
870
871 saveData(childNode, parentNode, localTreeIndex, state, taxonNameId);
872
873 // Store treeIndex as annotation for further use
874 Annotation annotation = Annotation.NewInstance(localTreeIndex.toString(), getTreeIndexAnnotationType(), Language.DEFAULT());
875 childNode.addAnnotation(annotation);
876
877 for (TaxonNode newNode : childNode.getChildNodes()) {
878 traverseTree(newNode, childNode, localTreeIndex, fetchLevel, state);
879 }
880
881 } else {
882 // logger.error("Target Rank " + fetchLevel.getLabel() + " reached");
883 return;
884 }
885 } else {
886 logger.error("Rank is NULL. FetchLevel can not be checked: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
887 }
888 } else {
889 logger.error("TaxonName can not be found in State: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
890 }
891
892 } else {
893 logger.error("Taxon is NULL for TaxonNode: " + childNode.getUuid());
894 }
895 }
896
897 /**
898 * Stores values in database for every recursive round.
899 * @param childNode The {@link TaxonNode TaxonNode} to process.
900 * @param parentNode The parent {@link TaxonNode TaxonNode} of the childNode.
901 * @param treeIndex The TreeIndex at the current level.
902 * @param state The {@link PesiExportState PesiExportState}.
903 * @param currentTaxonFk The TaxonFk to store the values for.
904 */
905 private void saveData(TaxonNode childNode, TaxonNode parentNode, StringBuffer treeIndex, PesiExportState state, Integer currentTaxonFk) {
906 // We are differentiating kingdoms by the nomenclatural code for now.
907 // This needs to be handled in a better way as soon as we know how to differentiate between more kingdoms.
908 Taxon childNodeTaxon = childNode.getTaxon();
909 TaxonNameBase<?,?> childNodeTaxonName = childNode.getTaxon().getName();
910 if (childNodeTaxon != null && childNodeTaxonName != null) {
911 TaxonNameBase<?,?> parentNodeTaxonName = null;
912 if (parentNode != null) {
913 Taxon parentNodeTaxon = parentNode.getTaxon();
914 if (parentNodeTaxon != null) {
915 parentNodeTaxonName = parentNodeTaxon.getName();
916 }
917 }
918
919 invokeParentTaxonFkAndTreeIndex(
920 state.getDbId(parentNodeTaxonName),
921 currentTaxonFk,
922 treeIndex);
923 }
924
925 }
926
927 /**
928 * Inserts values into the Taxon database table.
929 * @param taxonName The {@link TaxonNameBase TaxonName}.
930 * @param state The {@link PesiExportState PesiExportState}.
931 * @param stmt The prepared statement.
932 * @return Whether save was successful or not.
933 */
934 protected boolean invokeParentTaxonFkAndTreeIndex(Integer parentTaxonFk, Integer currentTaxonFk, StringBuffer treeIndex) {
935 try {
936 if (parentTaxonFk != null) {
937 parentTaxonFk_TreeIndex_KingdomFkStmt.setInt(1, parentTaxonFk);
938 } else {
939 parentTaxonFk_TreeIndex_KingdomFkStmt.setObject(1, null);
940 }
941
942 if (treeIndex != null) {
943 parentTaxonFk_TreeIndex_KingdomFkStmt.setString(2, treeIndex.toString());
944 } else {
945 parentTaxonFk_TreeIndex_KingdomFkStmt.setObject(2, null);
946 }
947
948 if (currentTaxonFk != null) {
949 parentTaxonFk_TreeIndex_KingdomFkStmt.setInt(3, currentTaxonFk);
950 } else {
951 parentTaxonFk_TreeIndex_KingdomFkStmt.setObject(3, null);
952 }
953
954 parentTaxonFk_TreeIndex_KingdomFkStmt.executeUpdate();
955 return true;
956 } catch (SQLException e) {
957 logger.error("ParentTaxonFk and TreeIndex could not be inserted into database: " + e.getMessage());
958 e.printStackTrace();
959 return false;
960 }
961 }
962
963 /**
964 * Inserts Rank data and KingdomFk into the Taxon database table.
965 * @param taxonName The {@link TaxonNameBase TaxonName}.
966 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
967 * @param taxonFk The TaxonFk to store the values for.
968 * @param kindomFk The KingdomFk.
969 * @return Whether save was successful or not.
970 */
971 private boolean invokeRankDataAndKingdomFk(TaxonNameBase<?,?> taxonName, NomenclaturalCode nomenclaturalCode,
972 Integer taxonFk, Integer kingdomFk) {
973 try {
974 Integer rankFk = getRankFk(taxonName, nomenclaturalCode);
975 if (rankFk != null) {
976 rankUpdateStmt.setInt(1, rankFk);
977 } else {
978 rankUpdateStmt.setObject(1, null);
979 }
980
981 String rankCache = getRankCache(taxonName, nomenclaturalCode);
982 if (rankCache != null) {
983 rankUpdateStmt.setString(2, rankCache);
984 } else {
985 rankUpdateStmt.setObject(2, null);
986 }
987
988 if (kingdomFk != null) {
989 rankUpdateStmt.setInt(3, kingdomFk);
990 } else {
991 rankUpdateStmt.setObject(3, null);
992 }
993
994 if (taxonFk != null) {
995 rankUpdateStmt.setInt(4, taxonFk);
996 } else {
997 rankUpdateStmt.setObject(4, null);
998 }
999
1000 rankUpdateStmt.executeUpdate();
1001 return true;
1002 } catch (SQLException e) {
1003 logger.error("Data (RankFk, RankCache, KingdomFk) could not be inserted into database: " + e.getMessage());
1004 e.printStackTrace();
1005 return false;
1006 }
1007 }
1008
1009 /**
1010 * Inserts Rank data, TypeNameFk, KingdomFk, expertFk and speciesExpertFk into the Taxon database table.
1011 * @param taxonName The {@link TaxonNameBase TaxonName}.
1012 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
1013 * @param taxonFk The TaxonFk to store the values for.
1014 * @param typeNameFk The TypeNameFk.
1015 * @param kindomFk The KingdomFk.
1016 * @param expertFk The ExpertFk.
1017 * @param speciesExpertFk The SpeciesExpertFk.
1018 * @return Whether save was successful or not.
1019 */
1020 private boolean invokeRankDataAndTypeNameFkAndKingdomFk(TaxonNameBase<?,?> taxonName, NomenclaturalCode nomenclaturalCode,
1021 Integer taxonFk, Integer typeNameFk, Integer kingdomFk,
1022 Integer expertFk, Integer speciesExpertFk) {
1023 try {
1024 Integer rankFk = getRankFk(taxonName, nomenclaturalCode);
1025 if (rankFk != null) {
1026 rankTypeExpertsUpdateStmt.setInt(1, rankFk);
1027 } else {
1028 rankTypeExpertsUpdateStmt.setObject(1, null);
1029 }
1030
1031 String rankCache = getRankCache(taxonName, nomenclaturalCode);
1032 if (rankCache != null) {
1033 rankTypeExpertsUpdateStmt.setString(2, rankCache);
1034 } else {
1035 rankTypeExpertsUpdateStmt.setObject(2, null);
1036 }
1037
1038 if (typeNameFk != null) {
1039 rankTypeExpertsUpdateStmt.setInt(3, typeNameFk);
1040 } else {
1041 rankTypeExpertsUpdateStmt.setObject(3, null);
1042 }
1043
1044 if (kingdomFk != null) {
1045 rankTypeExpertsUpdateStmt.setInt(4, kingdomFk);
1046 } else {
1047 rankTypeExpertsUpdateStmt.setObject(4, null);
1048 }
1049
1050 if (expertFk != null) {
1051 rankTypeExpertsUpdateStmt.setInt(5, expertFk);
1052 } else {
1053 rankTypeExpertsUpdateStmt.setObject(5, null);
1054 }
1055
1056 //TODO handle experts GUIDS
1057 // if (speciesExpertFk != null) {
1058 // rankTypeExpertsUpdateStmt.setInt(6, speciesExpertFk);
1059 // } else {
1060 // rankTypeExpertsUpdateStmt.setObject(6, null);
1061 // }
1062 //
1063 // if (taxonFk != null) {
1064 // rankTypeExpertsUpdateStmt.setInt(7, taxonFk);
1065 // } else {
1066 // rankTypeExpertsUpdateStmt.setObject(7, null);
1067 // }
1068
1069 rankTypeExpertsUpdateStmt.executeUpdate();
1070 return true;
1071 } catch (SQLException e) {
1072 logger.error("Data could not be inserted into database: " + e.getMessage());
1073 e.printStackTrace();
1074 return false;
1075 }
1076 }
1077
1078 /**
1079 * Deletes all entries of database tables related to <code>Taxon</code>.
1080 * @param state The {@link PesiExportState PesiExportState}.
1081 * @return Whether the delete operation was successful or not.
1082 */
1083 protected boolean doDelete(PesiExportState state) {
1084 PesiExportConfigurator pesiConfig = (PesiExportConfigurator) state.getConfig();
1085
1086 String sql;
1087 Source destination = pesiConfig.getDestination();
1088
1089 // Clear Taxon
1090 sql = "DELETE FROM " + dbTableName;
1091 destination.setQuery(sql);
1092 destination.update(sql);
1093 return true;
1094 }
1095
1096 /* (non-Javadoc)
1097 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#isIgnore(eu.etaxonomy.cdm.io.common.IoStateBase)
1098 */
1099 @Override
1100 protected boolean isIgnore(PesiExportState state) {
1101 return ! state.getConfig().isDoTaxa();
1102 }
1103
1104 /**
1105 * Returns the <code>RankFk</code> attribute.
1106 * @param taxonName The {@link TaxonNameBase TaxonName}.
1107 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
1108 * @return The <code>RankFk</code> attribute.
1109 * @see MethodMapper
1110 */
1111 private static Integer getRankFk(TaxonNameBase<?,?> taxonName, NomenclaturalCode nomenclaturalCode) {
1112 Integer result = null;
1113 try {
1114 if (nomenclaturalCode != null) {
1115 if (taxonName != null) {
1116 if (taxonName.getRank() == null) {
1117 logger.warn("Rank is null: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
1118 } else {
1119 result = PesiTransformer.rank2RankId(taxonName.getRank(), PesiTransformer.nomenClaturalCode2Kingdom(nomenclaturalCode));
1120 }
1121 if (result == null) {
1122 logger.warn("Rank could not be determined for PESI-Kingdom-Id " + PesiTransformer.nomenClaturalCode2Kingdom(nomenclaturalCode) + " and TaxonName " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
1123 }
1124 }
1125 }
1126 } catch (Exception e) {
1127 e.printStackTrace();
1128 }
1129 return result;
1130 }
1131
1132 /**
1133 * Returns the <code>RankCache</code> attribute.
1134 * @param taxonName The {@link TaxonNameBase TaxonName}.
1135 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
1136 * @return The <code>RankCache</code> attribute.
1137 * @see MethodMapper
1138 */
1139 private static String getRankCache(TaxonNameBase<?,?> taxonName, NomenclaturalCode nomenclaturalCode) {
1140 String result = null;
1141 try {
1142 if (nomenclaturalCode != null) {
1143 result = PesiTransformer.rank2RankCache(taxonName.getRank(), PesiTransformer.nomenClaturalCode2Kingdom(nomenclaturalCode));
1144 }
1145 } catch (Exception e) {
1146 e.printStackTrace();
1147 }
1148 return result;
1149 }
1150
1151 /**
1152 * Returns the <code>GenusOrUninomial</code> attribute.
1153 * @param taxonName The {@link TaxonNameBase TaxonName}.
1154 * @return The <code>GenusOrUninomial</code> attribute.
1155 * @see MethodMapper
1156 */
1157 private static String getGenusOrUninomial(TaxonNameBase<?,?> taxonName) {
1158 String result = null;
1159 try {
1160 if (taxonName != null && (taxonName.isInstanceOf(NonViralName.class))) {
1161 NonViralName<?> nonViralName = CdmBase.deproxy(taxonName, NonViralName.class);
1162 result = nonViralName.getGenusOrUninomial();
1163 }
1164 } catch (Exception e) {
1165 e.printStackTrace();
1166 }
1167 return result;
1168 }
1169
1170 /**
1171 * Returns the <code>InfraGenericEpithet</code> attribute.
1172 * @param taxonName The {@link TaxonNameBase TaxonName}.
1173 * @return The <code>InfraGenericEpithet</code> attribute.
1174 * @see MethodMapper
1175 */
1176 private static String getInfraGenericEpithet(TaxonNameBase<?,?> taxonName) {
1177 String result = null;
1178 try {
1179 if (taxonName != null && (taxonName.isInstanceOf(NonViralName.class))) {
1180 NonViralName<?> nonViralName = CdmBase.deproxy(taxonName, NonViralName.class);
1181 result = nonViralName.getInfraGenericEpithet();
1182 }
1183 } catch (Exception e) {
1184 e.printStackTrace();
1185 }
1186 return result;
1187 }
1188
1189 /**
1190 * Returns the <code>SpecificEpithet</code> attribute.
1191 * @param taxonName The {@link TaxonNameBase TaxonName}.
1192 * @return The <code>SpecificEpithet</code> attribute.
1193 * @see MethodMapper
1194 */
1195 private static String getSpecificEpithet(TaxonNameBase<?,?> taxonName) {
1196 String result = null;
1197 try {
1198 if (taxonName != null && (taxonName.isInstanceOf(NonViralName.class))) {
1199 NonViralName<?> nonViralName = CdmBase.deproxy(taxonName, NonViralName.class);
1200 result = nonViralName.getSpecificEpithet();
1201 }
1202 } catch (Exception e) {
1203 e.printStackTrace();
1204 }
1205 return result;
1206 }
1207
1208 /**
1209 * Returns the <code>InfraSpecificEpithet</code> attribute.
1210 * @param taxonName The {@link TaxonNameBase TaxonName}.
1211 * @return The <code>InfraSpecificEpithet</code> attribute.
1212 * @see MethodMapper
1213 */
1214 private static String getInfraSpecificEpithet(TaxonNameBase<?,?> taxonName) {
1215 String result = null;
1216 try {
1217 if (taxonName != null && (taxonName.isInstanceOf(NonViralName.class))) {
1218 NonViralName<?> nonViralName = CdmBase.deproxy(taxonName, NonViralName.class);
1219 result = nonViralName.getInfraSpecificEpithet();
1220 }
1221 } catch (Exception e) {
1222 e.printStackTrace();
1223 }
1224 return result;
1225 }
1226
1227 /**
1228 * Returns the <code>WebSearchName</code> attribute.
1229 * @param taxonName The {@link TaxonNameBase TaxonName}.
1230 * @return The <code>WebSearchName</code> attribute.
1231 * @see MethodMapper
1232 */
1233 @SuppressWarnings("unused")
1234 private static String getWebSearchName(TaxonNameBase<?,?> taxonName) {
1235 String result = null;
1236 try {
1237 if (taxonName != null && (taxonName.isInstanceOf(NonViralName.class))) {
1238 NonViralName<?> nonViralName = CdmBase.deproxy(taxonName, NonViralName.class);
1239 result = nonViralName.getNameCache();
1240 }
1241 } catch (Exception e) {
1242 e.printStackTrace();
1243 }
1244 return result;
1245 }
1246
1247 /**
1248 * Returns the <code>WebShowName</code> attribute.
1249 * @param taxonName The {@link TaxonNameBase TaxonName}.
1250 * @return The <code>WebShowName</code> attribute.
1251 * @see MethodMapper
1252 */
1253 private static String getWebShowName(TaxonNameBase<?,?> taxonName) {
1254 String result = "";
1255
1256 try {
1257 List<TaggedText> taggedName = taxonName.getTaggedName();
1258 boolean openTag = false;
1259 boolean start = true;
1260 for (TaggedText taggedText : taggedName) {
1261 if (taggedText.isName() || taggedText.isHybridSign() ) {
1262 // Name
1263 if (! openTag) {
1264 if (start) {
1265 result = "<i>";
1266 start = false;
1267 } else {
1268 result += " <i>";
1269 }
1270 openTag = true;
1271 } else {
1272 result += " ";
1273 }
1274 result += taggedText.getText();
1275 } else if (taggedText.isSeparator()) {
1276 //Separator
1277 if (! openTag) {
1278 logger.warn("Semantics of separator outside name not yet defined: "+ taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
1279 }
1280 result += taggedText.getText();
1281 } else if (taggedText.isRank()) {
1282 // Rank
1283 String rankAbbrev = taggedText.getText();
1284
1285 if (StringUtils.isBlank(rankAbbrev)) {
1286 logger.error("Rank abbreviation is an empty string: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
1287 } else {
1288 if (openTag) {
1289 result += "</i> ";
1290 openTag = false;
1291 } else {
1292 result += " ";
1293 }
1294 result +=rankAbbrev;
1295 }
1296 } else if (taggedText.isAuthors()) {
1297 //Team
1298 if (openTag) {
1299 result += "</i> ";
1300 openTag = false;
1301 } else {
1302 result += " ";
1303 }
1304 result += taggedText.getText();
1305 } else if (taggedText.isYear()) {
1306 if (openTag) {
1307 result += "</i> ";
1308 openTag = false;
1309 } else {
1310 result += " ";
1311 }
1312 result += taggedText.getText();
1313 } else if (taggedText.isReference()) {
1314 if (openTag) {
1315 result += "</i> ";
1316 openTag = false;
1317 } else {
1318 result += " ";
1319 }
1320 result += taggedText.getText();
1321 } else {
1322 if (taggedText.getText() == null) {
1323 logger.warn("TaggedName for " + taggedText.getType() +" is NULL for this TaxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() +")");
1324 } else {
1325 logger.error("TaggedText typ is unknown. Tag type: " + taggedText.getType() + ", TaxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
1326 }
1327 }
1328 }
1329 if (openTag) {
1330 result += "</i>";
1331 }
1332 } catch (Exception e) {
1333 e.printStackTrace();
1334 }
1335
1336 return result;
1337 }
1338
1339 /**
1340 * Returns the <code>AuthorString</code> attribute.
1341 * @param taxonName The {@link TaxonNameBase TaxonName}.
1342 * @return The <code>AuthorString</code> attribute.
1343 * @see MethodMapper
1344 */
1345 @SuppressWarnings("unused")
1346 private static String getAuthorString(TaxonBase<?> taxon) {
1347 String result = null;
1348 try {
1349 boolean isNonViralName = false;
1350 String authorshipCache = null;
1351 TaxonNameBase<?,?> taxonName = taxon.getName();
1352 if (taxonName != null && taxonName.isInstanceOf(NonViralName.class)){
1353 authorshipCache = CdmBase.deproxy(taxonName, NonViralName.class).getAuthorshipCache();
1354 isNonViralName = true;
1355 }
1356 // For a misapplied name without an authorshipCache the authorString should be set to "auct."
1357 if (isMisappliedName(taxon) && authorshipCache == null) {
1358 // Set authorshipCache to "auct."
1359 result = PesiTransformer.auctString;
1360 }else{
1361 result = authorshipCache;
1362 }
1363 if (taxonName == null){
1364 logger.warn("TaxonName does not exist for taxon: " + taxon.getUuid() + " (" + taxon.getTitleCache() + ")");
1365 }else if (! isNonViralName){
1366 logger.warn("TaxonName is not of instance NonViralName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
1367 }
1368
1369 } catch (Exception e) {
1370 e.printStackTrace();
1371 }
1372
1373 if (StringUtils.isBlank(result)) {
1374 return null;
1375 } else {
1376 return result;
1377 }
1378 }
1379
1380
1381 /**
1382 * Checks whether a given TaxonName is a misapplied name.
1383 * @param taxonName The {@link TaxonNameBase TaxonName}.
1384 * @return Whether the given TaxonName is a misapplied name or not.
1385 */
1386 private static boolean isMisappliedName(TaxonNameBase taxonName) {
1387 boolean result = false;
1388 Set<Taxon> taxa = taxonName.getTaxa();
1389 if (taxa.size() == 1){
1390 return isMisappliedName(taxa.iterator().next());
1391 }else if (taxa.size() > 1){
1392 logger.warn("TaxonNameBase has " + taxa.size() + " taxa attached. Can't define if it is a misapplied name.");
1393 }
1394 return result;
1395 }
1396
1397
1398
1399
1400 /**
1401 * Checks whether a given Taxon is a misapplied name.
1402 * @param taxonName The {@link TaxonNameBase TaxonName}.
1403 * @return Whether the given TaxonName is a misapplied name or not.
1404 */
1405 private static boolean isMisappliedName(TaxonBase<?> taxon) {
1406 boolean result = false;
1407
1408 if (! taxon.isInstanceOf(Taxon.class)){
1409 return false;
1410 }
1411 Set<TaxonRelationship> taxonRelations = CdmBase.deproxy(taxon, Taxon.class).getRelationsFromThisTaxon();
1412 for (TaxonRelationship taxonRelationship : taxonRelations) {
1413 TaxonRelationshipType taxonRelationshipType = taxonRelationship.getType();
1414 if (taxonRelationshipType.equals(TaxonRelationshipType.MISAPPLIED_NAME_FOR())) {
1415 result = true;
1416 }
1417 }
1418 return result;
1419 }
1420
1421 /**
1422 * Returns the <code>FullName</code> attribute.
1423 * @param taxonName The {@link TaxonNameBase TaxonName}.
1424 * @return The <code>FullName</code> attribute.
1425 * @see MethodMapper
1426 */
1427 @SuppressWarnings("unused")
1428 private static String getFullName(TaxonNameBase<?,?> taxonName) {
1429 if (taxonName != null) {
1430 return taxonName.getTitleCache();
1431 } else {
1432 return null;
1433 }
1434 }
1435
1436 /**
1437 * Returns the <code>NomRefString</code> attribute.
1438 * @param taxonName The {@link TaxonNameBase TaxonName}.
1439 * @return The <code>NomRefString</code> attribute.
1440 * @see MethodMapper
1441 */
1442 @SuppressWarnings("unused")
1443 private static String getNomRefString(TaxonNameBase<?,?> taxonName) {
1444 String result = null;
1445 try {
1446 if (taxonName != null) {
1447 try {
1448 result = taxonName.getNomenclaturalMicroReference();
1449 } catch (Exception e) {
1450 logger.error("While getting NomRefString");
1451 e.printStackTrace();
1452 }
1453 }
1454 } catch (Exception e) {
1455 e.printStackTrace();
1456 }
1457 return result;
1458 }
1459
1460 /**
1461 * Returns the <code>DisplayName</code> attribute.
1462 * @param taxonName The {@link TaxonNameBase TaxonName}.
1463 * @return The <code>DisplayName</code> attribute.
1464 * @see MethodMapper
1465 */
1466 @SuppressWarnings("unused")
1467 private static String getDisplayName(TaxonNameBase<?,?> taxonName) {
1468 // TODO: extension?
1469 if (taxonName != null) {
1470 return taxonName.getFullTitleCache();
1471 } else {
1472 return null;
1473 }
1474 }
1475
1476 /**
1477 * Returns the <code>NameStatusFk</code> attribute.
1478 * @param taxonName The {@link TaxonNameBase TaxonName}.
1479 * @return The <code>NameStatusFk</code> attribute.
1480 * @see MethodMapper
1481 */
1482 @SuppressWarnings("unused")
1483 private static Integer getNameStatusFk(TaxonNameBase<?,?> taxonName) {
1484 Integer result = null;
1485
1486 try {
1487 if (taxonName != null && (taxonName.isInstanceOf(NonViralName.class))) {
1488 NonViralName<?> nonViralName = CdmBase.deproxy(taxonName, NonViralName.class);
1489 Set<NomenclaturalStatus> states = nonViralName.getStatus();
1490 if (states.size() == 1) {
1491 NomenclaturalStatus state = states.iterator().next();
1492 NomenclaturalStatusType statusType = null;
1493 if (state != null) {
1494 statusType = state.getType();
1495 }
1496 if (statusType != null) {
1497 result = PesiTransformer.nomStatus2nomStatusFk(statusType);
1498 }
1499 } else if (states.size() > 1) {
1500 logger.error("This TaxonName has more than one Nomenclatural Status: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
1501 }
1502 }
1503
1504 } catch (Exception e) {
1505 e.printStackTrace();
1506 }
1507 return result;
1508 }
1509
1510 /**
1511 * Returns the <code>NameStatusCache</code> attribute.
1512 * @param taxonName The {@link TaxonNameBase TaxonName}.
1513 * @return The <code>NameStatusCache</code> attribute.
1514 * @see MethodMapper
1515 */
1516 @SuppressWarnings("unused")
1517 private static String getNameStatusCache(TaxonNameBase<?,?> taxonName) {
1518 String result = null;
1519
1520 try {
1521 if (taxonName != null && (taxonName.isInstanceOf(NonViralName.class))) {
1522 NonViralName<?> nonViralName = CdmBase.deproxy(taxonName, NonViralName.class);
1523 Set<NomenclaturalStatus> states = nonViralName.getStatus();
1524 if (states.size() == 1) {
1525 NomenclaturalStatus state = states.iterator().next();
1526 if (state != null) {
1527 result = PesiTransformer.nomStatus2NomStatusCache(state.getType());
1528 }
1529 } else if (states.size() > 1) {
1530 logger.error("This TaxonName has more than one Nomenclatural Status: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
1531 }
1532 }
1533
1534 } catch (Exception e) {
1535 e.printStackTrace();
1536 }
1537 return result;
1538 }
1539
1540 /**
1541 * Returns the <code>TaxonStatusFk</code> attribute.
1542 * @param taxonName The {@link TaxonNameBase TaxonName}.
1543 * @param state The {@link PesiExportState PesiExportState}.
1544 * @return The <code>TaxonStatusFk</code> attribute.
1545 * @see MethodMapper
1546 */
1547 @SuppressWarnings("unused")
1548 private static Integer getTaxonStatusFk(TaxonBase<?> taxon, PesiExportState state) {
1549 Integer result = null;
1550
1551 try {
1552 if (isMisappliedName(taxon)) {
1553 Synonym synonym = Synonym.NewInstance(null, null);
1554
1555 // This works as long as only the instance is important to differentiate between TaxonStatus.
1556 result = PesiTransformer.taxonBase2statusFk(synonym); // Auct References are treated as Synonyms in Datawarehouse now.
1557 } else {
1558 result = PesiTransformer.taxonBase2statusFk(taxon);
1559 }
1560
1561 } catch (Exception e) {
1562 e.printStackTrace();
1563 }
1564 return result;
1565 }
1566
1567 /**
1568 * Returns the <code>TaxonStatusCache</code> attribute.
1569 * @param taxonName The {@link TaxonNameBase TaxonName}.
1570 * @param state The {@link PesiExportState PesiExportState}.
1571 * @return The <code>TaxonStatusCache</code> attribute.
1572 * @see MethodMapper
1573 */
1574 @SuppressWarnings("unused")
1575 private static String getTaxonStatusCache(TaxonBase<?> taxon, PesiExportState state) {
1576 String result = null;
1577
1578 try {
1579 if (isMisappliedName(taxon)) {
1580 Synonym synonym = Synonym.NewInstance(null, null);
1581
1582 // This works as long as only the instance is important to differentiate between TaxonStatus.
1583 result = PesiTransformer.taxonBase2statusCache(synonym); // Auct References are treated as Synonyms in Datawarehouse now.
1584 } else {
1585 result = PesiTransformer.taxonBase2statusCache(taxon);
1586 }
1587
1588 } catch (Exception e) {
1589 e.printStackTrace();
1590 }
1591 return result;
1592 }
1593
1594 /**
1595 * Returns the <code>TypeNameFk</code> attribute.
1596 * @param taxonName The {@link TaxonNameBase TaxonName}.
1597 * @param state The {@link PesiExportState PesiExportState}.
1598 * @return The <code>TypeNameFk</code> attribute.
1599 * @see MethodMapper
1600 */
1601 private static Integer getTypeNameFk(TaxonNameBase<?,?> taxonNameBase, PesiExportState state) {
1602 Integer result = null;
1603 if (taxonNameBase != null) {
1604 Set<NameTypeDesignation> nameTypeDesignations = taxonNameBase.getNameTypeDesignations();
1605 if (nameTypeDesignations.size() == 1) {
1606 NameTypeDesignation nameTypeDesignation = nameTypeDesignations.iterator().next();
1607 if (nameTypeDesignation != null) {
1608 TaxonNameBase<?,?> typeName = nameTypeDesignation.getTypeName();
1609 if (typeName != null) {
1610 result = state.getDbId(typeName);
1611 }
1612 }
1613 } else if (nameTypeDesignations.size() > 1) {
1614 logger.warn("This TaxonName has " + nameTypeDesignations.size() + " NameTypeDesignations: " + taxonNameBase.getUuid() + " (" + taxonNameBase.getTitleCache() + ")");
1615 }
1616 }
1617 return result;
1618 }
1619
1620 /**
1621 * Returns the <code>TypeFullnameCache</code> attribute.
1622 * @param taxonName The {@link TaxonNameBase TaxonName}.
1623 * @return The <code>TypeFullnameCache</code> attribute.
1624 * @see MethodMapper
1625 */
1626 @SuppressWarnings("unused")
1627 private static String getTypeFullnameCache(TaxonNameBase<?,?> taxonName) {
1628 String result = null;
1629
1630 try {
1631 if (taxonName != null) {
1632 Set<NameTypeDesignation> nameTypeDesignations = taxonName.getNameTypeDesignations();
1633 if (nameTypeDesignations.size() == 1) {
1634 NameTypeDesignation nameTypeDesignation = nameTypeDesignations.iterator().next();
1635 if (nameTypeDesignation != null) {
1636 TaxonNameBase<?,?> typeName = nameTypeDesignation.getTypeName();
1637 if (typeName != null) {
1638 result = typeName.getTitleCache();
1639 }
1640 }
1641 } else if (nameTypeDesignations.size() > 1) {
1642 logger.warn("This TaxonName has " + nameTypeDesignations.size() + " NameTypeDesignations: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
1643 }
1644 }
1645
1646 } catch (Exception e) {
1647 e.printStackTrace();
1648 }
1649 return result;
1650 }
1651
1652 /**
1653 * Returns the <code>QualityStatusFk</code> attribute.
1654 * @param taxonName The {@link TaxonNameBase TaxonName}.
1655 * @return The <code>QualityStatusFk</code> attribute.
1656 * @see MethodMapper
1657 */
1658 @SuppressWarnings("unused")
1659 private static Integer getQualityStatusFk(TaxonBase<?> taxonName) {
1660 // TODO: Not represented in CDM right now. Depends on import.
1661 Integer result = null;
1662 return result;
1663 }
1664
1665 /**
1666 * Returns the <code>QualityStatusCache</code> attribute.
1667 * @param taxonName The {@link TaxonNameBase TaxonName}.
1668 * @return The <code>QualityStatusCache</code> attribute.
1669 * @see MethodMapper
1670 */
1671 @SuppressWarnings("unused")
1672 private static String getQualityStatusCache(TaxonBase<?> taxonName) {
1673 // TODO: Not represented in CDM right now. Depends on import.
1674 String result = null;
1675 return result;
1676 }
1677
1678 /**
1679 * Returns the <code>TypeDesignationStatusFk</code> attribute.
1680 * @param taxonName The {@link TaxonNameBase TaxonName}.
1681 * @return The <code>TypeDesignationStatusFk</code> attribute.
1682 * @see MethodMapper
1683 */
1684 @SuppressWarnings("unused")
1685 private static Integer getTypeDesignationStatusFk(TaxonNameBase<?,?> taxonName) {
1686 Integer result = null;
1687
1688 try {
1689 if (taxonName != null) {
1690 Set<NameTypeDesignation> typeDesignations = taxonName.getNameTypeDesignations();
1691 if (typeDesignations.size() == 1) {
1692 Object obj = typeDesignations.iterator().next().getTypeStatus();
1693 NameTypeDesignationStatus designationStatus = CdmBase.deproxy(obj, NameTypeDesignationStatus.class);
1694 result = PesiTransformer.nameTypeDesignationStatus2TypeDesignationStatusId(designationStatus);
1695 } else if (typeDesignations.size() > 1) {
1696 logger.error("Found a TaxonName with more than one NameTypeDesignation: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
1697 }
1698 }
1699
1700 } catch (Exception e) {
1701 e.printStackTrace();
1702 }
1703 return result;
1704 }
1705
1706 /**
1707 * Returns the <code>TypeDesignationStatusCache</code> attribute.
1708 * @param taxonName The {@link TaxonNameBase TaxonName}.
1709 * @return The <code>TypeDesignationStatusCache</code> attribute.
1710 * @see MethodMapper
1711 */
1712 @SuppressWarnings("unused")
1713 private static String getTypeDesignationStatusCache(TaxonNameBase<?,?> taxonName) {
1714 String result = null;
1715
1716 try {
1717 if (taxonName != null) {
1718 Set<NameTypeDesignation> typeDesignations = taxonName.getNameTypeDesignations();
1719 if (typeDesignations.size() == 1) {
1720 Object obj = typeDesignations.iterator().next().getTypeStatus();
1721 NameTypeDesignationStatus designationStatus = CdmBase.deproxy(obj, NameTypeDesignationStatus.class);
1722 result = PesiTransformer.nameTypeDesignationStatus2TypeDesignationStatusCache(designationStatus);
1723 } else if (typeDesignations.size() > 1) {
1724 logger.error("Found a TaxonName with more than one NameTypeDesignation: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
1725 }
1726 }
1727
1728 } catch (Exception e) {
1729 e.printStackTrace();
1730 }
1731 return result;
1732 }
1733
1734 /**
1735 * Returns the <code>FossilStatusFk</code> attribute.
1736 * @param taxonName The {@link TaxonNameBase TaxonName}.
1737 * @return The <code>FossilStatusFk</code> attribute.
1738 * @see MethodMapper
1739 */
1740 @SuppressWarnings("unused")
1741 private static Integer getFossilStatusFk(TaxonNameBase<?,?> taxonNameBase) {
1742 Integer result = null;
1743 // Taxon taxon;
1744 // if (taxonBase.isInstanceOf(Taxon.class)) {
1745 // taxon = CdmBase.deproxy(taxonBase, Taxon.class);
1746 // Set<TaxonDescription> specimenDescription = taxon.;
1747 // result = PesiTransformer.fossil2FossilStatusId(fossil);
1748 // }
1749 return result;
1750 }
1751
1752 /**
1753 * Returns the <code>FossilStatusCache</code> attribute.
1754 * @param taxonName The {@link TaxonNameBase TaxonName}.
1755 * @return The <code>FossilStatusCache</code> attribute.
1756 * @see MethodMapper
1757 */
1758 @SuppressWarnings("unused")
1759 private static String getFossilStatusCache(TaxonNameBase<?,?> taxonName) {
1760 // TODO
1761 String result = null;
1762 return result;
1763 }
1764
1765 // /**
1766 // * Returns the <code>IdInSource</code> attribute.
1767 // * @param taxonName The {@link TaxonNameBase TaxonName}.
1768 // * @return The <code>IdInSource</code> attribute.
1769 // * @see MethodMapper
1770 // */
1771 // @SuppressWarnings("unused")
1772 // private static String getIdInSource(TaxonNameBase<?,?> taxonName) {
1773 // String result = null;
1774 //
1775 // try {
1776 // Set<IdentifiableSource> sources = getSources(taxonName);
1777 // for (IdentifiableSource source : sources) {
1778 // result = "TAX_ID: " + source.getIdInSource();
1779 // String sourceIdNameSpace = source.getIdNamespace();
1780 // if (sourceIdNameSpace != null) {
1781 // if (sourceIdNameSpace.equals("originalGenusId")) {
1782 // result = "Nominal Taxon from TAX_ID: " + source.getIdInSource();
1783 // } else if (sourceIdNameSpace.equals("InferredEpithetOf")) {
1784 // result = "Inferred epithet from TAX_ID: " + source.getIdInSource();
1785 // } else if (sourceIdNameSpace.equals("InferredGenusOf")) {
1786 // result = "Inferred genus from TAX_ID: " + source.getIdInSource();
1787 // } else if (sourceIdNameSpace.equals("PotentialCombinationOf")) {
1788 // result = "Potential combination from TAX_ID: " + source.getIdInSource();
1789 // } else {
1790 // result = "TAX_ID: " + source.getIdInSource();
1791 // }
1792 // }
1793 // }
1794 // } catch (Exception e) {
1795 // e.printStackTrace();
1796 // }
1797 //
1798 // if (result == null) {
1799 // logger.error("IdInSource is NULL for this taxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() +")");
1800 // }
1801 // return result;
1802 // }
1803
1804 // /**
1805 // * Returns the idInSource for a given TaxonName only.
1806 // * @param taxonName The {@link TaxonNameBase TaxonName}.
1807 // * @return The idInSource.
1808 // */
1809 // private static String getIdInSourceOnly(TaxonBase<?> taxonName) {
1810 // String result = null;
1811 //
1812 // // Get the sources first
1813 // Set<IdentifiableSource> sources = getSources(taxonName);
1814 //
1815 // // Determine the idInSource
1816 // if (sources.size() == 1) {
1817 // IdentifiableSource source = sources.iterator().next();
1818 // if (source != null) {
1819 // result = source.getIdInSource();
1820 // }
1821 // } else if (sources.size() > 1) {
1822 // int count = 1;
1823 // result = "";
1824 // for (IdentifiableSource source : sources) {
1825 // result += source.getIdInSource();
1826 // if (count < sources.size()) {
1827 // result += "; ";
1828 // }
1829 // count++;
1830 // }
1831 //
1832 // }
1833 //
1834 // return result;
1835 // }
1836 //
1837 // /**
1838 // * Returns the Sources for a given TaxonName only.
1839 // * @param taxonName The {@link TaxonNameBase TaxonName}.
1840 // * @return The Sources.
1841 // */
1842 // private static Set<IdentifiableSource> getSources(TaxonBase<?> taxon) {
1843 // Set<IdentifiableSource> sources = null;
1844 //
1845 // // Sources from TaxonName
1846 // Set<IdentifiableSource> nameSources = taxon.getSources();
1847 // sources = nameSources;
1848 // if (nameSources.size() > 1) {
1849 // logger.warn("This TaxonName has more than one Source: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
1850 // }
1851 //
1852 // // Sources from TaxonBase
1853 // if (sources == null || sources.isEmpty()) {
1854 // Set<Taxon> taxa = taxonName.getTaxa();
1855 // Set<Synonym> synonyms = taxonName.getSynonyms();
1856 // if (taxa.size() == 1) {
1857 // Taxon taxon = taxa.iterator().next();
1858 //
1859 // if (taxon != null) {
1860 // sources = taxon.getSources();
1861 // }
1862 // } else if (taxa.size() > 1) {
1863 // logger.warn("This TaxonName has " + taxa.size() + " Taxa: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() +")");
1864 // }
1865 // if (synonyms.size() == 1) {
1866 // Synonym synonym = synonyms.iterator().next();
1867 //
1868 // if (synonym != null) {
1869 // sources = synonym.getSources();
1870 // }
1871 // } else if (synonyms.size() > 1) {
1872 // logger.warn("This TaxonName has " + synonyms.size() + " Synonyms: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() +")");
1873 // }
1874 // }
1875 //
1876 // if (sources == null || sources.isEmpty()) {
1877 // logger.error("This TaxonName has no Sources: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() +")");
1878 // }
1879 // return sources;
1880 // }
1881
1882 /**
1883 * Returns the <code>GUID</code> attribute.
1884 * @param taxonName The {@link TaxonNameBase TaxonName}.
1885 * @return The <code>GUID</code> attribute.
1886 * @see MethodMapper
1887 */
1888 private static String getGUID(TaxonBase<?> taxon) {
1889 if (taxon.getLsid() != null ){
1890 return taxon.getLsid().getLsid();
1891 }else{
1892 return taxon.getUuid().toString();
1893 }
1894 }
1895
1896 /**
1897 * Returns the <code>DerivedFromGuid</code> attribute.
1898 * @param taxonName The {@link TaxonNameBase TaxonName}.
1899 * @return The <code>DerivedFromGuid</code> attribute.
1900 * @see MethodMapper
1901 */
1902 @SuppressWarnings("unused")
1903 private static String getDerivedFromGuid(TaxonBase<?> taxon) {
1904 String result = null;
1905 try {
1906 // The same as GUID for now
1907 result = getGUID(taxon);
1908 } catch (Exception e) {
1909 e.printStackTrace();
1910 }
1911 return result;
1912 }
1913
1914 /**
1915 * Returns the <code>CacheCitation</code> attribute.
1916 * @param taxonName The {@link TaxonNameBase TaxonName}.
1917 * @return The CacheCitation.
1918 * @see MethodMapper
1919 */
1920 @SuppressWarnings("unused")
1921 private static String getCacheCitation(TaxonBase<?> taxon) {
1922 String result = "";
1923 //TODO implement anew for taxa
1924 // try {
1925 // String originalDb = getOriginalDB(taxon);
1926 // if (originalDb == null) {
1927 //// logger.error("OriginalDB is NULL for this TaxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
1928 // } else if (originalDb.equals("ERMS")) {
1929 // // TODO: 19.08.2010: An import of CacheCitation does not exist in the ERMS import yet or it will be imported in a different way...
1930 // // So the following code is some kind of harmless assumption.
1931 // Set<Extension> extensions = taxon.getExtensions();
1932 // for (Extension extension : extensions) {
1933 // if (extension.getType().equals(cacheCitationExtensionType)) {
1934 // result = extension.getValue();
1935 // }
1936 // }
1937 // } else {
1938 // String expertName = getExpertName(taxon);
1939 // String webShowName = getWebShowName(taxon);
1940 //
1941 // // idInSource only
1942 // String idInSource = getIdInSourceOnly(taxo);
1943 //
1944 // // build the cacheCitation
1945 // if (expertName != null) {
1946 // result += expertName + ". ";
1947 // } else {
1948 // // logger.error("ExpertName could not be determined for this TaxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
1949 // }
1950 // if (webShowName != null) {
1951 // result += webShowName + ". ";
1952 // } else {
1953 // // logger.error("WebShowName could not be determined for this TaxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
1954 // }
1955 //
1956 // if (getOriginalDB(taxonName).equals("FaEu")) {
1957 // result += "Accessed through: Fauna Europaea at http://faunaeur.org/full_results.php?id=";
1958 // } else if (getOriginalDB(taxonName).equals("EM")) {
1959 // result += "Accessed through: Euro+Med PlantBase at http://ww2.bgbm.org/euroPlusMed/PTaxonDetail.asp?UUID=";
1960 // }
1961 //
1962 // if (idInSource != null) {
1963 // result += idInSource;
1964 // } else {
1965 // // logger.error("IdInSource could not be determined for this TaxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
1966 // }
1967 // }
1968 // } catch (Exception e) {
1969 // e.printStackTrace();
1970 // }
1971 //
1972 // if ("".equals(result)) {
1973 // return null;
1974 // } else {
1975 // return result;
1976 // }
1977 return result;
1978 }
1979
1980 /**
1981 * Returns the <code>OriginalDB</code> attribute.
1982 * @param taxonName The {@link TaxonNameBase TaxonName}.
1983 * @return The <code>OriginalDB</code> attribute.
1984 * @see MethodMapper
1985 */
1986 private static String getOriginalDB(TaxonBase<?> taxonBase) {
1987 String result = "";
1988 try {
1989
1990 // Sources from TaxonName
1991 // Set<IdentifiableSource> sources = taxonName.getSources();
1992 Set<IdentifiableSource> sources = taxonBase.getSources();
1993
1994 // IdentifiableEntity<?> taxonBase = null;
1995 // if (sources != null && sources.isEmpty()) {
1996 // // Sources from Taxa or Synonyms
1997 // Set<Taxon> taxa = taxonName.getTaxa();
1998 // if (taxa.size() == 1) {
1999 // taxonBase = taxa.iterator().next();
2000 // sources = taxonBase.getSources();
2001 // } else if (taxa.size() > 1) {
2002 // logger.warn("This TaxonName has " + taxa.size() + " Taxa: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() +")");
2003 // }
2004 // Set<Synonym> synonyms = taxonName.getSynonyms();
2005 // if (synonyms.size() == 1) {
2006 // taxonBase = synonyms.iterator().next();
2007 // sources = taxonBase.getSources();
2008 // } else if (synonyms.size() > 1) {
2009 // logger.warn("This TaxonName has " + synonyms.size() + " Synonyms: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() +")");
2010 // }
2011 // }
2012
2013 if (sources != null && ! sources.isEmpty()) {
2014 if (sources.size() == 1) {
2015 IdentifiableSource source = sources.iterator().next();
2016 if (source != null) {
2017 Reference<?> citation = source.getCitation();
2018 if (citation != null) {
2019 result = PesiTransformer.databaseString2Abbreviation(citation.getTitleCache());
2020 }
2021 }
2022 } else if (sources.size() > 1) {
2023 int count = 1;
2024 for (IdentifiableSource source : sources) {
2025 Reference<?> citation = source.getCitation();
2026 if (citation != null) {
2027 if (count > 1) {
2028 result += "; ";
2029 }
2030 result += PesiTransformer.databaseString2Abbreviation(citation.getTitleCache());
2031 count++;
2032 }
2033 }
2034 } else {
2035 result = null;
2036 }
2037 }
2038
2039 } catch (Exception e) {
2040 e.printStackTrace();
2041 }
2042 if ("".equals(result)) {
2043 return null;
2044 } else {
2045 return result;
2046 }
2047 }
2048
2049 /**
2050 * Returns the <code>LastAction</code> attribute.
2051 * @param taxonName The {@link TaxonNameBase TaxonName}.
2052 * @return The <code>LastAction</code> attribute.
2053 * @see MethodMapper
2054 */
2055 @SuppressWarnings("unused")
2056 private static String getLastAction(TaxonBase<?> taxon) {
2057 String result = null;
2058 try {
2059 Set<Extension> extensions = taxon.getExtensions();
2060 for (Extension extension : extensions) {
2061 if (extension.getType().equals(lastActionExtensionType)) {
2062 result = extension.getValue();
2063 }
2064 }
2065 } catch (Exception e) {
2066 e.printStackTrace();
2067 }
2068 return result;
2069 }
2070
2071 /**
2072 * Returns the <code>LastActionDate</code> attribute.
2073 * @param taxonName The {@link TaxonNameBase TaxonName}.
2074 * @return The <code>LastActionDate</code> attribute.
2075 * @see MethodMapper
2076 */
2077 @SuppressWarnings({ "unused" })
2078 private static DateTime getLastActionDate(TaxonBase<?> taxon) {
2079 DateTime result = null;
2080 try {
2081 Set<Extension> extensions = taxon.getExtensions();
2082 for (Extension extension : extensions) {
2083 if (extension.getType().equals(lastActionDateExtensionType)) {
2084 String dateTime = extension.getValue();
2085 if (dateTime != null) {
2086 DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss.S");
2087 result = formatter.parseDateTime(dateTime);
2088 }
2089 }
2090 }
2091 } catch (Exception e) {
2092 e.printStackTrace();
2093 }
2094 return result;
2095 }
2096
2097 /**
2098 * Returns the <code>ExpertName</code> attribute.
2099 * @param taxonName The {@link TaxonNameBase TaxonName}.
2100 * @return The <code>ExpertName</code> attribute.
2101 * @see MethodMapper
2102 */
2103 @SuppressWarnings("unused")
2104 private static String getExpertName(TaxonBase<?> taxonName) {
2105 String result = null;
2106 try {
2107 Set<Extension> extensions = taxonName.getExtensions();
2108 for (Extension extension : extensions) {
2109 if (extension.getType().equals(expertNameExtensionType)) {
2110 result = extension.getValue();
2111 }
2112 }
2113 } catch (Exception e) {
2114 e.printStackTrace();
2115 }
2116 return result;
2117 }
2118
2119 /**
2120 * Returns the <code>ExpertFk</code> attribute.
2121 * @param taxonName The {@link TaxonNameBase TaxonName}.
2122 * @param state The {@link PesiExportState PesiExportState}.
2123 * @return The <code>ExpertFk</code> attribute.
2124 * @see MethodMapper
2125 */
2126 private static Integer getExpertFk(Reference<?> reference, PesiExportState state) {
2127 Integer result = state.getDbId(reference);
2128 return result;
2129 }
2130
2131 /**
2132 * Returns the <code>SpeciesExpertName</code> attribute.
2133 * @param taxonName The {@link TaxonNameBase TaxonName}.
2134 * @return The <code>SpeciesExpertName</code> attribute.
2135 * @see MethodMapper
2136 */
2137 @SuppressWarnings("unused")
2138 private static String getSpeciesExpertName(TaxonBase<?> taxonName) {
2139 String result = null;
2140 try {
2141 Set<Extension> extensions = taxonName.getExtensions();
2142 for (Extension extension : extensions) {
2143 if (extension.getType().equals(speciesExpertNameExtensionType)) {
2144 result = extension.getValue();
2145 }
2146 }
2147 } catch (Exception e) {
2148 e.printStackTrace();
2149 }
2150 return result;
2151 }
2152
2153 /**
2154 * Returns the <code>SpeciesExpertFk</code> attribute.
2155 * @param reference The {@link Reference Reference}.
2156 * @param state The {@link PesiExportState PesiExportState}.
2157 * @return The <code>SpeciesExpertFk</code> attribute.
2158 * @see MethodMapper
2159 */
2160 private static Integer getSpeciesExpertFk(Reference<?> reference, PesiExportState state) {
2161 Integer result = state.getDbId(reference);
2162 return result;
2163 }
2164
2165 // /**
2166 // * Returns the <code>SourceFk</code> attribute.
2167 // * @param taxonName The {@link TaxonNameBase TaxonName}.
2168 // * @param state The {@link PesiExportState PesiExportState}.
2169 // * @return The <code>SourceFk</code> attribute.
2170 // */
2171 // @SuppressWarnings("unused")
2172 // private static Integer getSourceFk(TaxonNameBase<?,?> taxonName, PesiExportState state) {
2173 // Integer result = null;
2174 //
2175 // try {
2176 // TaxonBase<?> taxonBase = getSourceTaxonBase(taxonName);
2177 //
2178 // if (taxonBase != null) {
2179 // result = state.getDbId(taxonBase.getSec());
2180 // }
2181 // } catch (Exception e) {
2182 // e.printStackTrace();
2183 // }
2184 // return result;
2185 // }
2186
2187
2188 // /**
2189 // * Determines the TaxonBase of a TaxonName.
2190 // * @param taxonName The {@link TaxonNameBase TaxonName}.
2191 // * @return The TaxonBase.
2192 // */
2193 // private static TaxonBase<?> getSourceTaxonBase(TaxonNameBase<?,?> taxonName) {
2194 // TaxonBase<?> taxonBase = null;
2195 // Set<Taxon> taxa = taxonName.getTaxa();
2196 // if (taxa.size() == 1) {
2197 // taxonBase =taxa.iterator().next();
2198 // } else if (taxa.size() > 1) {
2199 // logger.warn("This TaxonName has " + taxa.size() + " Taxa: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
2200 // }
2201 //
2202 // Set<Synonym> synonyms = taxonName.getSynonyms();
2203 // if (synonyms.size() == 1) {
2204 // taxonBase = synonyms.iterator().next();
2205 // } else if (synonyms.size() > 1) {
2206 // logger.warn("This TaxonName has " + synonyms.size() + " Synonyms: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
2207 // }
2208 // return taxonBase;
2209 // }
2210
2211 }