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