3 * Copyright (C) 2009 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
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.
10 package eu
.etaxonomy
.cdm
.io
.pesi
.out
;
12 import java
.sql
.Connection
;
13 import java
.sql
.PreparedStatement
;
14 import java
.sql
.ResultSet
;
15 import java
.sql
.SQLException
;
16 import java
.sql
.Types
;
17 import java
.util
.ArrayList
;
18 import java
.util
.BitSet
;
19 import java
.util
.HashMap
;
20 import java
.util
.HashSet
;
21 import java
.util
.Iterator
;
22 import java
.util
.List
;
24 import java
.util
.UUID
;
26 import org
.apache
.commons
.lang
.StringUtils
;
27 import org
.apache
.log4j
.Logger
;
28 import org
.joda
.time
.DateTime
;
29 import org
.joda
.time
.format
.DateTimeFormat
;
30 import org
.joda
.time
.format
.DateTimeFormatter
;
31 import org
.springframework
.stereotype
.Component
;
32 import org
.springframework
.transaction
.TransactionStatus
;
34 import eu
.etaxonomy
.cdm
.api
.service
.TaxonServiceImpl
;
35 import eu
.etaxonomy
.cdm
.common
.CdmUtils
;
36 import eu
.etaxonomy
.cdm
.io
.common
.Source
;
37 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.UndefinedTransformerMethodException
;
38 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbConstantMapper
;
39 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbExtensionMapper
;
40 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbLastActionMapper
;
41 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbObjectMapper
;
42 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbStringMapper
;
43 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.IdMapper
;
44 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.MethodMapper
;
45 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.ObjectChangeMapper
;
46 import eu
.etaxonomy
.cdm
.io
.pesi
.erms
.ErmsTransformer
;
47 import eu
.etaxonomy
.cdm
.model
.common
.Annotation
;
48 import eu
.etaxonomy
.cdm
.model
.common
.AnnotationType
;
49 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
50 import eu
.etaxonomy
.cdm
.model
.common
.Extension
;
51 import eu
.etaxonomy
.cdm
.model
.common
.ExtensionType
;
52 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableEntity
;
53 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableSource
;
54 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
55 import eu
.etaxonomy
.cdm
.model
.common
.Marker
;
56 import eu
.etaxonomy
.cdm
.model
.common
.MarkerType
;
57 import eu
.etaxonomy
.cdm
.model
.common
.RelationshipBase
;
58 import eu
.etaxonomy
.cdm
.model
.name
.BacterialName
;
59 import eu
.etaxonomy
.cdm
.model
.name
.BotanicalName
;
60 import eu
.etaxonomy
.cdm
.model
.name
.HybridRelationship
;
61 import eu
.etaxonomy
.cdm
.model
.name
.NameRelationship
;
62 import eu
.etaxonomy
.cdm
.model
.name
.NameTypeDesignation
;
63 import eu
.etaxonomy
.cdm
.model
.name
.NameTypeDesignationStatus
;
64 import eu
.etaxonomy
.cdm
.model
.name
.NomenclaturalCode
;
65 import eu
.etaxonomy
.cdm
.model
.name
.NomenclaturalStatus
;
66 import eu
.etaxonomy
.cdm
.model
.name
.NonViralName
;
67 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
68 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameBase
;
69 import eu
.etaxonomy
.cdm
.model
.name
.ZoologicalName
;
70 import eu
.etaxonomy
.cdm
.model
.reference
.INomenclaturalReference
;
71 import eu
.etaxonomy
.cdm
.model
.reference
.Reference
;
72 import eu
.etaxonomy
.cdm
.model
.taxon
.Classification
;
73 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
74 import eu
.etaxonomy
.cdm
.model
.taxon
.SynonymRelationship
;
75 import eu
.etaxonomy
.cdm
.model
.taxon
.SynonymRelationshipType
;
76 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
77 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
78 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
79 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationship
;
80 import eu
.etaxonomy
.cdm
.profiler
.ProfilerController
;
81 import eu
.etaxonomy
.cdm
.strategy
.cache
.HTMLTagRules
;
82 import eu
.etaxonomy
.cdm
.strategy
.cache
.TagEnum
;
83 import eu
.etaxonomy
.cdm
.strategy
.cache
.name
.BacterialNameDefaultCacheStrategy
;
84 import eu
.etaxonomy
.cdm
.strategy
.cache
.name
.BotanicNameDefaultCacheStrategy
;
85 import eu
.etaxonomy
.cdm
.strategy
.cache
.name
.INonViralNameCacheStrategy
;
86 import eu
.etaxonomy
.cdm
.strategy
.cache
.name
.NonViralNameDefaultCacheStrategy
;
87 import eu
.etaxonomy
.cdm
.strategy
.cache
.name
.ZooNameNoMarkerCacheStrategy
;
90 * The export class for {@link eu.etaxonomy.cdm.model.name.TaxonNameBase TaxonNames}.<p>
91 * Inserts into DataWarehouse database table <code>Taxon</code>.
92 * It is divided into four phases:<p><ul>
93 * <li>Phase 1: Export of all {@link eu.etaxonomy.cdm.model.name.TaxonNameBase TaxonNames} except some data exported in the following phases.
94 * <li>Phase 2: Export of additional data: ParenTaxonFk and TreeIndex.
95 * <li>Phase 3: Export of additional data: Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk.
96 * <li>Phase 4: Export of Inferred Synonyms.</ul>
102 public class PesiTaxonExport
extends PesiExportBase
{
103 private static final Logger logger
= Logger
.getLogger(PesiTaxonExport
.class);
104 private static final Class
<?
extends CdmBase
> standardMethodParameter
= TaxonBase
.class;
106 private static int modCount
= 1000;
107 private static final String dbTableName
= "Taxon";
108 private static final String dbTableNameSynRel
= "RelTaxon";
109 private static final String dbTableAdditionalSourceRel
= "AdditionalTaxonSource";
110 private static final String pluralString
= "Taxa";
111 private static final String parentPluralString
= "Taxa";
112 private PreparedStatement parentTaxonFk_TreeIndex_KingdomFkStmt
;
113 private PreparedStatement parentTaxonFkStmt
;
114 private PreparedStatement rankTypeExpertsUpdateStmt
;
115 private PreparedStatement rankUpdateStmt
;
116 private NomenclaturalCode nomenclaturalCode
;
117 private Integer kingdomFk
;
118 private HashMap
<Rank
, Rank
> rank2endRankMap
= new HashMap
<Rank
, Rank
>();
119 private List
<Rank
> rankList
= new ArrayList
<Rank
>();
120 private static final UUID uuidTreeIndex
= UUID
.fromString("28f4e205-1d02-4d3a-8288-775ea8413009");
121 private AnnotationType treeIndexAnnotationType
;
122 private static ExtensionType lastActionExtensionType
;
123 private static ExtensionType lastActionDateExtensionType
;
124 private static ExtensionType expertNameExtensionType
;
125 private static ExtensionType speciesExpertNameExtensionType
;
126 private static ExtensionType cacheCitationExtensionType
;
127 public static NonViralNameDefaultCacheStrategy
<?
> zooNameStrategy
= ZooNameNoMarkerCacheStrategy
.NewInstance();
128 public static NonViralNameDefaultCacheStrategy
<?
> botanicalNameStrategy
= BotanicNameDefaultCacheStrategy
.NewInstance();
129 public static NonViralNameDefaultCacheStrategy
<?
> nonViralNameStrategy
= NonViralNameDefaultCacheStrategy
.NewInstance();
130 public static NonViralNameDefaultCacheStrategy
<?
> bacterialNameStrategy
= BacterialNameDefaultCacheStrategy
.NewInstance();
131 private static int currentTaxonId
;
135 * @return the treeIndexAnnotationType
137 protected AnnotationType
getTreeIndexAnnotationType() {
138 return treeIndexAnnotationType
;
142 * @param treeIndexAnnotationType the treeIndexAnnotationType to set
144 protected void setTreeIndexAnnotationType(AnnotationType treeIndexAnnotationType
) {
145 this.treeIndexAnnotationType
= treeIndexAnnotationType
;
156 public PesiTaxonExport() {
161 * @see eu.etaxonomy.cdm.io.common.DbExportBase#getStandardMethodParameter()
164 public Class
<?
extends CdmBase
> getStandardMethodParameter() {
165 return standardMethodParameter
;
169 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doCheck(eu.etaxonomy.cdm.io.common.IoStateBase)
172 protected boolean doCheck(PesiExportState state
) {
173 boolean result
= true;
179 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doInvoke(eu.etaxonomy.cdm.io.common.IoStateBase)
182 protected void doInvoke(PesiExportState state
) {
184 logger
.info("*** Started Making " + pluralString
+ " ...");
186 initPreparedStatements(state
);
188 // Stores whether this invoke was successful or not.
189 boolean success
= true;
191 // PESI: Clear the database table Taxon.
194 // Get specific mappings: (CDM) Taxon -> (PESI) Taxon
195 PesiExportMapping mapping
= getMapping();
196 PesiExportMapping synonymRelMapping
= getSynRelMapping();
197 PesiExportMapping additionalSourceMapping
= getAdditionalSourceMapping(state
);
199 // Initialize the db mapper
200 mapping
.initialize(state
);
201 synonymRelMapping
.initialize(state
);
202 additionalSourceMapping
.initialize(state
);
204 // Find extensionTypes
205 lastActionExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.lastActionUuid
);
206 lastActionDateExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.lastActionDateUuid
);
207 expertNameExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.expertNameUuid
);
208 speciesExpertNameExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.speciesExpertNameUuid
);
209 cacheCitationExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.cacheCitationUuid
);
212 success
&= doPhase01(state
, mapping
, additionalSourceMapping
);
214 //"PHASE 1b: Handle names without taxa ...
215 success
&= doNames(state
, additionalSourceMapping
);
218 // 2nd Round: Add ParentTaxonFk to each taxon
219 success
&= doPhase02(state
);
221 //PHASE 3: Add Rank data, KingdomFk, TypeNameFk ...
222 success
&= doPhase03(state
);
224 // 4nd Round: Add TreeIndex to each taxon
225 success
&= doPhase04(state
);
228 //"PHASE 4: Creating Inferred Synonyms...
229 success
&= doPhase05(state
, mapping
, synonymRelMapping
);
231 logger
.info("*** Finished Making " + pluralString
+ " ..." + getSuccessString(success
));
234 state
.setUnsuccessfull();
237 } catch (Exception e
) {
239 logger
.error(e
.getMessage());
240 state
.setUnsuccessfull();
245 private void initPreparedStatements(PesiExportState state
) throws SQLException
{
246 initTreeIndexStatement(state
);
247 initRankExpertsUpdateStmt(state
);
248 initRankUpdateStatement(state
);
250 initParentFkStatement(state
);
253 // Prepare TreeIndex-And-KingdomFk-Statement
254 private void initTreeIndexStatement(PesiExportState state
) throws SQLException
{
255 Connection connection
= state
.getConfig().getDestination().getConnection();
256 String parentTaxonFk_TreeIndex_KingdomFkSql
= "UPDATE Taxon SET ParentTaxonFk = ?, TreeIndex = ? WHERE TaxonId = ?";
257 parentTaxonFk_TreeIndex_KingdomFkStmt
= connection
.prepareStatement(parentTaxonFk_TreeIndex_KingdomFkSql
);
260 // Prepare TreeIndex-And-KingdomFk-Statement
261 private void initParentFkStatement(PesiExportState state
) throws SQLException
{
262 Connection connection
= state
.getConfig().getDestination().getConnection();
263 String parentTaxonFkSql
= "UPDATE Taxon SET ParentTaxonFk = ? WHERE TaxonId = ?";
264 parentTaxonFkStmt
= connection
.prepareStatement(parentTaxonFkSql
);
267 private void initRankUpdateStatement(PesiExportState state
) throws SQLException
{
268 Connection connection
= state
.getConfig().getDestination().getConnection();
269 String rankSql
= "UPDATE Taxon SET RankFk = ?, RankCache = ?, KingdomFk = ? WHERE TaxonId = ?";
270 rankUpdateStmt
= connection
.prepareStatement(rankSql
);
273 private void initRankExpertsUpdateStmt(PesiExportState state
) throws SQLException
{
274 // String sql_old = "UPDATE Taxon SET RankFk = ?, RankCache = ?, TypeNameFk = ?, KingdomFk = ?, " +
275 // "ExpertFk = ?, SpeciesExpertFk = ? WHERE TaxonId = ?";
276 //TODO handle experts GUIDs
277 Connection connection
= state
.getConfig().getDestination().getConnection();
279 String sql
= "UPDATE Taxon SET RankFk = ?, RankCache = ?, TypeNameFk = ?, KingdomFk = ? " +
280 " WHERE TaxonId = ?";
281 rankTypeExpertsUpdateStmt
= connection
.prepareStatement(sql
);
284 private boolean doPhase01(PesiExportState state
, PesiExportMapping mapping
, PesiExportMapping additionalSourceMapping
) throws SQLException
{
287 List
<TaxonBase
> list
;
288 boolean success
= true;
289 // Get the limit for objects to save within a single transaction.
290 int limit
= state
.getConfig().getLimitSave();
293 logger
.info("PHASE 1: Export Taxa...limit is " + limit
);
295 TransactionStatus txStatus
= startTransaction(true);
296 logger
.info("Started new transaction. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
300 int partitionCount
= 0;
302 logger
.info("Taking snapshot at the beginning of phase 1 of taxonExport");
303 ProfilerController
.memorySnapshot();
304 while ((list
= getNextTaxonPartition(null, limit
, partitionCount
++, null)) != null ) {
306 logger
.debug("Fetched " + list
.size() + " " + pluralString
+ ". Exporting...");
307 for (TaxonBase
<?
> taxon
: list
) {
308 doCount(count
++, modCount
, pluralString
);
309 TaxonNameBase
<?
,?
> taxonName
= taxon
.getName();
310 NonViralName
<?
> nvn
= CdmBase
.deproxy(taxonName
, NonViralName
.class);
312 if (! nvn
.isProtectedTitleCache()){
313 nvn
.setTitleCache(null, false);
315 if (! nvn
.isProtectedNameCache()){
316 nvn
.setNameCache(null, false);
318 if (! nvn
.isProtectedFullTitleCache()){
319 nvn
.setFullTitleCache(null, false);
321 if (! nvn
.isProtectedAuthorshipCache()){
322 nvn
.setAuthorshipCache(null, false);
326 success
&= mapping
.invoke(taxon
);
328 if (nvn
.getNomenclaturalReference() != null || StringUtils
.isNotBlank(nvn
.getNomenclaturalMicroReference() )){
329 additionalSourceMapping
.invoke(taxon
);
332 validatePhaseOne(taxon
, nvn
);
342 // Commit transaction
343 commitTransaction(txStatus
);
344 logger
.debug("Committed transaction.");
345 logger
.info("Exported " + (count
- pastCount
) + " " + pluralString
+ ". Total: " + count
);
347 /*logger.warn("Taking snapshot at the end of the loop of phase 1 of taxonExport");
348 ProfilerController.memorySnapshot();
351 txStatus
= startTransaction(true);
352 logger
.info("Started new transaction. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
356 logger
.info("No " + pluralString
+ " left to fetch.");
361 // Commit transaction
362 commitTransaction(txStatus
);
364 logger
.debug("Committed transaction.");
366 if (logger
.isDebugEnabled()){
367 logger
.debug("Taking snapshot at the end of phase 1 of taxonExport");
368 ProfilerController
.memorySnapshot();
374 private void validatePhaseOne(TaxonBase
<?
> taxon
, NonViralName taxonName
) {
375 // Check whether some rules are violated
376 nomenclaturalCode
= taxonName
.getNomenclaturalCode();
377 String genusOrUninomial
= taxonName
.getGenusOrUninomial();
378 String specificEpithet
= taxonName
.getSpecificEpithet();
379 String infraSpecificEpithet
= taxonName
.getInfraSpecificEpithet();
380 String infraGenericEpithet
= taxonName
.getInfraGenericEpithet();
381 Integer rank
= getRankFk(taxonName
, nomenclaturalCode
);
384 logger
.error("Rank was not determined: " + taxon
.getUuid() + " (" + taxon
.getTitleCache() + ")");
387 // Check whether infraGenericEpithet is set correctly
388 // 1. Childs of an accepted taxon of rank subgenus that are accepted taxa of rank species have to have an infraGenericEpithet
389 // 2. Grandchilds of an accepted taxon of rank subgenus that are accepted taxa of rank subspecies have to have an infraGenericEpithet
391 int ancestorLevel
= 0;
392 if (taxonName
.getRank().equals(Rank
.SUBSPECIES())) {
393 // The accepted taxon two rank levels above should be of rank subgenus
396 if (taxonName
.getRank().equals(Rank
.SPECIES())) {
397 // The accepted taxon one rank level above should be of rank subgenus
400 if (ancestorLevel
> 0) {
401 if (validateAncestorOfSpecificRank(taxon
, ancestorLevel
, Rank
.SUBGENUS())) {
402 // The child (species or subspecies) of this parent (subgenus) has to have an infraGenericEpithet
403 if (infraGenericEpithet
== null) {
404 logger
.warn("InfraGenericEpithet does not exist even though it should for: " + taxon
.getUuid() + " (" + taxon
.getTitleCache() + ")");
405 // maybe the taxon could be named here
410 if (infraGenericEpithet
== null && rank
.intValue() == 190) {
411 logger
.warn("InfraGenericEpithet was not determined although it should exist for rank 190: " + taxon
.getUuid() + " (" + taxon
.getTitleCache() + ")");
413 if (specificEpithet
!= null && rank
.intValue() < 216) {
414 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() + ")");
416 if (infraSpecificEpithet
!= null && rank
.intValue() < 225) {
417 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() + ")";
418 if (StringUtils
.isNotBlank(infraSpecificEpithet
)){
419 logger
.warn(message
);
421 logger
.warn(message
);
425 if (infraSpecificEpithet
!= null && specificEpithet
== null) {
426 logger
.warn("An infraSpecificEpithet was determined, but a specificEpithet was not determined: " + taxon
.getUuid() + " (" + taxon
.getTitleCache() + ")");
428 if (genusOrUninomial
== null) {
429 logger
.warn("GenusOrUninomial was not determined: " + taxon
.getUuid() + " (" + taxon
.getTitleCache() + ")");
436 * 2nd Round: Add ParentTaxonFk to each taxon and add Biota if not exists
440 private boolean doPhase02(PesiExportState state
) {
443 boolean success
= true;
444 if (! state
.getConfig().isDoParentAndBiota()){
445 logger
.info ("Ignore PHASE 2: Make ParentFk and Biota...");
451 // Get the limit for objects to save within a single transaction.
452 int limit
= state
.getConfig().getLimitSave();
456 logger
.info("PHASE 2: Make ParentFk and Biota ... limit is " + limit
);
458 TransactionStatus txStatus
= startTransaction(true);
459 int partitionCount
= 0;
461 // ProfilerController.memorySnapshot();
462 while ((list
= getNextTaxonPartition(Taxon
.class, limit
, partitionCount
++, null)) != null ) {
464 logger
.info("Fetched " + list
.size() + " " + pluralString
+ ". Exporting...");
465 for (Taxon taxon
: list
) {
466 for (TaxonNode node
: taxon
.getTaxonNodes()){
467 doCount(count
++, modCount
, pluralString
);
468 TaxonNode parentNode
= node
.getParent();
469 if (parentNode
!= null){
470 int childId
= state
.getDbId( taxon
);
471 int parentId
= state
.getDbId(parentNode
.getTaxon());
472 success
&= invokeParentTaxonFk(parentId
, childId
);
478 // Commit transaction
479 commitTransaction(txStatus
);
480 logger
.info("Exported " + (count
- pastCount
) + " " + pluralString
+ ". Total: " + count
);
483 txStatus
= startTransaction(true);
484 logger
.info("Started new transaction. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
488 logger
.info("No " + pluralString
+ " left to fetch.");
491 // Commit transaction
492 commitTransaction(txStatus
);
499 * Inserts the Biota Taxon if not yet exists.
501 * @throws SQLException
503 private void insertBiota(PesiExportState state
) {
505 ResultSet rs
= state
.getConfig().getDestination().getResultSet("SELECT * FROM Taxon WHERE GenusOrUninomial = 'Biota' ");
506 if (rs
.next() == false){
507 int biotaId
= state
.getConfig().getNameIdStart() -1 ;
508 String sqlInsertBiota
= "INSERT INTO Taxon (TaxonId, KingdomFk, RankFk, RankCache, GenusOrUninomial, WebSearchName, WebShowName, FullName, DisplayName, TaxonStatusFk, TaxonStatusCache) " +
509 " VALUES (" + biotaId
+ ", 0, 0, 'Superdomain', 'Biota', 'Biota', '<i>Biota</i>', 'Biota', '<i>Biota</i>', 1 , 'accepted')";
510 state
.getConfig().getDestination().update(sqlInsertBiota
);
512 } catch (SQLException e
) {
513 logger
.warn ("Biota could not be requested or inserted");
517 // 4th round: Add TreeIndex to each taxon
518 private boolean doPhase04(PesiExportState state
) {
519 boolean success
= true;
521 logger
.info("PHASE 4: Make TreeIndex ... ");
523 //TODO test if possible to move to phase 02
524 String sql
= " UPDATE Taxon SET ParentTaxonFk = (Select TaxonId from Taxon where RankFk = 0) " +
525 " WHERE (RankFk = 10) and TaxonStatusFk = 1 ";
526 state
.getConfig().getDestination().update(sql
);
528 state
.getConfig().getDestination().update("EXEC dbo.recalculateallstoredpaths");
535 // 2nd Round: Add ParentTaxonFk, TreeIndex to each Taxon
536 private boolean doPhase02_OLD(PesiExportState state
) {
537 boolean success
= true;
538 if (! state
.getConfig().isDoTreeIndex()){
539 logger
.info ("Ignore PHASE 2: ParentTaxonFk and TreeIndex");
543 List
<Classification
> classificationList
= null;
544 logger
.info("PHASE 2: Add ParenTaxonFk and TreeIndex...");
546 // Specify starting ranks for tree traversing
547 rankList
.add(Rank
.KINGDOM());
548 rankList
.add(Rank
.GENUS());
550 // Specify where to stop traversing (value) when starting at a specific Rank (key)
551 rank2endRankMap
.put(Rank
.GENUS(), null); // Since NULL does not match an existing Rank, traverse all the way down to the leaves
552 rank2endRankMap
.put(Rank
.KINGDOM(), Rank
.GENUS()); // excludes rank genus
554 StringBuffer treeIndex
= new StringBuffer();
556 // Retrieve list of classifications
557 TransactionStatus txStatus
= startTransaction(true);
558 logger
.info("Started transaction for parentFk and treeIndex. Fetching all classifications...");
559 classificationList
= getClassificationService().listClassifications(null, 0, null, null);
560 commitTransaction(txStatus
);
561 logger
.debug("Committed transaction.");
563 logger
.info("Fetched " + classificationList
.size() + " classification(s).");
565 setTreeIndexAnnotationType(getAnnotationType(uuidTreeIndex
, "TreeIndex", "TreeIndex", "TI"));
566 List
<TaxonNode
> rankSpecificRootNodes
;
567 for (Classification classification
: classificationList
) {
568 for (Rank rank
: rankList
) {
570 txStatus
= startTransaction(true);
571 logger
.info("Started transaction to fetch all rootNodes specific to Rank " + rank
.getLabel() + " ...");
573 rankSpecificRootNodes
= getClassificationService().loadRankSpecificRootNodes(classification
, rank
, null, null, null);
574 logger
.info("Fetched " + rankSpecificRootNodes
.size() + " RootNodes for Rank " + rank
.getLabel());
576 commitTransaction(txStatus
);
577 logger
.debug("Committed transaction.");
579 for (TaxonNode rootNode
: rankSpecificRootNodes
) {
580 txStatus
= startTransaction(false);
581 Rank endRank
= rank2endRankMap
.get(rank
);
582 if (endRank
!= null) {
583 logger
.debug("Started transaction to traverse childNodes of rootNode (" + rootNode
.getUuid() + ") till Rank " + endRank
.getLabel() + " ...");
585 logger
.debug("Started transaction to traverse childNodes of rootNode (" + rootNode
.getUuid() + ") till leaves are reached ...");
588 TaxonNode newNode
= getTaxonNodeService().load(rootNode
.getUuid());
590 if (isPesiTaxon(newNode
.getTaxon())){
591 TaxonNode parentNode
= newNode
.getParent();
592 if (rank
.equals(Rank
.KINGDOM())) {
593 treeIndex
= new StringBuffer();
594 treeIndex
.append("#");
596 // Get treeIndex from parentNode
597 if (parentNode
!= null) {
598 boolean annotationFound
= false;
599 Set
<Annotation
> annotations
= parentNode
.getAnnotations();
600 for (Annotation annotation
: annotations
) {
601 AnnotationType annotationType
= annotation
.getAnnotationType();
602 if (annotationType
!= null && annotationType
.equals(getTreeIndexAnnotationType())) {
603 treeIndex
= new StringBuffer(CdmUtils
.Nz(annotation
.getText()));
604 annotationFound
= true;
605 // logger.error("treeIndex: " + treeIndex);
609 if (!annotationFound
) {
610 // This should not happen because it means that the treeIndex was not set correctly as an annotation to parentNode
611 logger
.error("TreeIndex could not be read from annotation of TaxonNode: " + parentNode
.getUuid() + ", Taxon: " + parentNode
.getTaxon().getUuid());
612 treeIndex
= new StringBuffer();
613 treeIndex
.append("#");
616 // TreeIndex could not be determined, but it's unclear how to proceed to generate a correct treeIndex if the parentNode is NULL
617 logger
.error("ParentNode for RootNode is NULL. TreeIndex could not be determined: " + newNode
.getUuid());
618 treeIndex
= new StringBuffer(); // This just prevents growing of the treeIndex in a wrong manner
619 treeIndex
.append("#");
622 nomenclaturalCode
= newNode
.getTaxon().getName().getNomenclaturalCode();
623 kingdomFk
= PesiTransformer
.nomenClaturalCode2Kingdom(nomenclaturalCode
);
624 traverseTree(newNode
, parentNode
, treeIndex
, endRank
, state
);
627 logger
.debug("Taxon is not a PESI taxon: " + newNode
.getTaxon().getUuid());
633 commitTransaction(txStatus
);
634 logger
.debug("Committed transaction.");
635 } catch (Exception e
) {
636 logger
.error(e
.getMessage());
641 rankSpecificRootNodes
= null;
646 logger
.warn("Taking snapshot at the end of phase 2 of taxonExport");
647 ProfilerController
.memorySnapshot();
651 //PHASE 3: Add Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk...
652 private boolean doPhase03(PesiExportState state
) {
655 boolean success
= true;
656 if (! state
.getConfig().isDoTreeIndex()){
657 logger
.info ("Ignore PHASE 3: Add Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk...");
660 // Get the limit for objects to save within a single transaction.
661 int limit
= state
.getConfig().getLimitSave();
663 List
<TaxonBase
> list
;
664 logger
.info("PHASE 3: Add Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk...");
665 // Be sure to add rank information, KingdomFk, TypeNameFk, expertFk and speciesExpertFk to every taxonName
668 TransactionStatus txStatus
= startTransaction(true);
669 logger
.info("Started new transaction for rank, kingdom, typeName, expertFk and speciesExpertFK. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
670 int partitionCount
= 0;
671 while ((list
= getNextTaxonPartition(TaxonBase
.class, limit
, partitionCount
++, null)) != null) {
673 logger
.debug("Fetched " + list
.size() + " " + pluralString
+ ". Exporting...");
674 for (TaxonBase
<?
> taxon
: list
) {
675 TaxonNameBase
<?
,?
> taxonName
= taxon
.getName();
676 // Determine expertFk
677 // Integer expertFk = makeExpertFk(state, taxonName);
679 // // Determine speciesExpertFk
680 // Integer speciesExpertFk = makeSpeciesExpertFk(state, taxonName);
682 doCount(count
++, modCount
, pluralString
);
683 Integer typeNameFk
= getTypeNameFk(taxonName
, state
);
684 kingdomFk
= PesiTransformer
.nomenClaturalCode2Kingdom(nomenclaturalCode
);
686 //TODO why are expertFks needed? (Andreas M.)
687 // if (expertFk != null || speciesExpertFk != null) {
688 invokeRankDataAndTypeNameFkAndKingdomFk(taxonName
, nomenclaturalCode
, state
.getDbId(taxon
),
689 typeNameFk
, kingdomFk
, state
);
696 // Commit transaction
697 commitTransaction(txStatus
);
698 logger
.debug("Committed transaction.");
699 logger
.info("Exported " + (count
- pastCount
) + " " + pluralString
+ ". Total: " + count
);
703 txStatus
= startTransaction(true);
704 logger
.info("Started new transaction for rank, kingdom, typeName, expertFk and speciesExpertFK. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
707 logger
.info("No " + pluralString
+ " left to fetch.");
712 // Commit transaction
713 commitTransaction(txStatus
);
715 logger
.debug("Committed transaction.");
716 logger
.debug("Try to take snapshot at the end of phase 3 of taxonExport, number of partitions: " + partitionCount
);
717 ProfilerController
.memorySnapshot();
721 // "PHASE 5: Creating Inferred Synonyms..."
722 private boolean doPhase05(PesiExportState state
, PesiExportMapping mapping
, PesiExportMapping synRelMapping
) throws SQLException
{
725 boolean success
= true;
726 // Get the limit for objects to save within a single transaction.
727 if (! state
.getConfig().isDoInferredSynonyms()){
728 logger
.info ("Ignore PHASE 5: Creating Inferred Synonyms...");
732 int limit
= state
.getConfig().getLimitSave();
733 // Create inferred synonyms for accepted taxa
734 logger
.info("PHASE 4: Creating Inferred Synonyms...");
736 // Determine the count of elements in datawarehouse database table Taxon
737 currentTaxonId
= determineTaxonCount(state
);
742 int pageSize
= limit
;
744 String inferredSynonymPluralString
= "Inferred Synonyms";
747 TransactionStatus txStatus
= startTransaction(true);
748 logger
.info("Started new transaction. Fetching some " + parentPluralString
+ " first (max: " + limit
+ ") ...");
749 List
<TaxonBase
> taxonList
= null;
753 while ((taxonList
= getTaxonService().listTaxaByName(Taxon
.class, "*", "*", "*", "*", Rank
.SPECIES(), pageSize
, pageNumber
)).size() > 0) {
754 HashMap
<Integer
, TaxonNameBase
<?
,?
>> inferredSynonymsDataToBeSaved
= new HashMap
<Integer
, TaxonNameBase
<?
,?
>>();
756 logger
.info("Fetched " + taxonList
.size() + " " + parentPluralString
+ ". Exporting...");
757 inferredSynonymsDataToBeSaved
.putAll(createInferredSynonymsForTaxonList(state
, mapping
,
758 synRelMapping
, taxonList
));
760 doCount(count
+= taxonList
.size(), modCount
, inferredSynonymPluralString
);
761 // Commit transaction
762 commitTransaction(txStatus
);
763 logger
.debug("Committed transaction.");
764 logger
.info("Exported " + (taxonList
.size()) + " " + inferredSynonymPluralString
+ ". Total: " + count
);
767 // Save Rank Data and KingdomFk for inferred synonyms
768 for (Integer taxonFk
: inferredSynonymsDataToBeSaved
.keySet()) {
769 invokeRankDataAndKingdomFk(inferredSynonymsDataToBeSaved
.get(taxonFk
), nomenclaturalCode
, taxonFk
, kingdomFk
, state
);
773 txStatus
= startTransaction(true);
774 logger
.info("Started new transaction. Fetching some " + parentPluralString
+ " first (max: " + limit
+ ") ...");
776 // Increment pageNumber
780 while ((taxonList
= getTaxonService().listTaxaByName(Taxon
.class, "*", "*", "*", "*", Rank
.SUBSPECIES(), pageSize
, pageNumber
)).size() > 0) {
781 HashMap
<Integer
, TaxonNameBase
<?
,?
>> inferredSynonymsDataToBeSaved
= new HashMap
<Integer
, TaxonNameBase
<?
,?
>>();
783 logger
.info("Fetched " + taxonList
.size() + " " + parentPluralString
+ ". Exporting...");
784 inferredSynonymsDataToBeSaved
.putAll(createInferredSynonymsForTaxonList(state
, mapping
,
785 synRelMapping
, taxonList
));
787 doCount(count
+= taxonList
.size(), modCount
, inferredSynonymPluralString
);
788 // Commit transaction
789 commitTransaction(txStatus
);
790 logger
.debug("Committed transaction.");
791 logger
.info("Exported " + taxonList
.size()+ " " + inferredSynonymPluralString
+ ". Total: " + count
);
794 // Save Rank Data and KingdomFk for inferred synonyms
795 for (Integer taxonFk
: inferredSynonymsDataToBeSaved
.keySet()) {
796 invokeRankDataAndKingdomFk(inferredSynonymsDataToBeSaved
.get(taxonFk
), nomenclaturalCode
, taxonFk
, kingdomFk
, state
);
800 txStatus
= startTransaction(true);
801 logger
.info("Started new transaction. Fetching some " + parentPluralString
+ " first (max: " + limit
+ ") ...");
803 // Increment pageNumber
806 if (taxonList
.size() == 0) {
807 logger
.info("No " + parentPluralString
+ " left to fetch.");
811 // logger.warn("Taking snapshot at the end of phase 4 of taxonExport");
812 // ProfilerController.memorySnapshot();
814 // Commit transaction
815 commitTransaction(txStatus
);
817 logger
.debug("Taking snapshot at the end of phase 4 after gc() of taxonExport");
818 ProfilerController
.memorySnapshot();
819 logger
.debug("Committed transaction.");
826 * @param synRelMapping
827 * @param currentTaxonId
829 * @param inferredSynonymsDataToBeSaved
832 private HashMap
<Integer
, TaxonNameBase
<?
, ?
>> createInferredSynonymsForTaxonList(PesiExportState state
,
833 PesiExportMapping mapping
, PesiExportMapping synRelMapping
, List
<TaxonBase
> taxonList
) {
836 Classification classification
= null;
837 List
<Synonym
> inferredSynonyms
= null;
838 boolean localSuccess
= true;
840 HashMap
<Integer
, TaxonNameBase
<?
,?
>> inferredSynonymsDataToBeSaved
= new HashMap
<Integer
, TaxonNameBase
<?
,?
>>();
842 for (TaxonBase
<?
> taxonBase
: taxonList
) {
844 if (taxonBase
.isInstanceOf(Taxon
.class)) { // this should always be the case since we should have fetched accepted taxon only, but you never know...
845 acceptedTaxon
= CdmBase
.deproxy(taxonBase
, Taxon
.class);
846 TaxonNameBase
<?
,?
> taxonName
= acceptedTaxon
.getName();
848 if (taxonName
.isInstanceOf(ZoologicalName
.class)) {
849 nomenclaturalCode
= taxonName
.getNomenclaturalCode();
850 kingdomFk
= PesiTransformer
.nomenClaturalCode2Kingdom(nomenclaturalCode
);
852 Set
<TaxonNode
> taxonNodes
= acceptedTaxon
.getTaxonNodes();
853 TaxonNode singleNode
= null;
855 if (taxonNodes
.size() > 0) {
856 // Determine the classification of the current TaxonNode
858 singleNode
= taxonNodes
.iterator().next();
859 if (singleNode
!= null) {
860 classification
= singleNode
.getClassification();
862 logger
.error("A TaxonNode belonging to this accepted Taxon is NULL: " + acceptedTaxon
.getUuid() + " (" + acceptedTaxon
.getTitleCache() +")");
865 // Classification could not be determined directly from this TaxonNode
866 // The stored classification from another TaxonNode is used. It's a simple, but not a failsafe fallback solution.
867 if (taxonNodes
.size() == 0) {
868 logger
.error("Classification could not be determined directly from this Taxon: " + acceptedTaxon
.getUuid() + " is misapplication? "+acceptedTaxon
.isMisapplication()+ "). The classification of the last taxon is used");
873 if (classification
!= null) {
875 TaxonNameBase name
= acceptedTaxon
.getName();
876 //if (name.isSpecies() || name.isInfraSpecific()){
877 inferredSynonyms
= getTaxonService().createAllInferredSynonyms(acceptedTaxon
, classification
, true);
879 // inferredSynonyms = getTaxonService().createInferredSynonyms(classification, acceptedTaxon, SynonymRelationshipType.INFERRED_GENUS_OF());
880 if (inferredSynonyms
!= null) {
881 for (Synonym synonym
: inferredSynonyms
) {
882 // TaxonNameBase<?,?> synonymName = synonym.getName();
883 MarkerType markerType
=getUuidMarkerType(PesiTransformer
.uuidMarkerGuidIsMissing
, state
);
884 synonym
.addMarker(Marker
.NewInstance(markerType
, true));
885 // Both Synonym and its TaxonName have no valid Id yet
886 synonym
.setId(currentTaxonId
++);
889 localSuccess
&= mapping
.invoke(synonym
);
890 //get SynonymRelationship and export
891 if (synonym
.getSynonymRelations().isEmpty() ){
892 SynonymRelationship synRel
;
893 IdentifiableSource source
= synonym
.getSources().iterator().next();
894 if (source
.getIdNamespace().contains("Potential combination")){
895 synRel
= acceptedTaxon
.addSynonym(synonym
, SynonymRelationshipType
.POTENTIAL_COMBINATION_OF());
896 logger
.error(synonym
.getTitleCache() + " has no synonym relationship to " + acceptedTaxon
.getTitleCache() + " type is set to potential combination");
897 } else if (source
.getIdNamespace().contains("Inferred Genus")){
898 synRel
= acceptedTaxon
.addSynonym(synonym
, SynonymRelationshipType
.INFERRED_GENUS_OF());
899 logger
.error(synonym
.getTitleCache() + " has no synonym relationship to " + acceptedTaxon
.getTitleCache() + " type is set to inferred genus");
900 } else if (source
.getIdNamespace().contains("Inferred Epithet")){
901 synRel
= acceptedTaxon
.addSynonym(synonym
, SynonymRelationshipType
.INFERRED_EPITHET_OF());
902 logger
.error(synonym
.getTitleCache() + " has no synonym relationship to " + acceptedTaxon
.getTitleCache() + " type is set to inferred epithet");
904 synRel
= acceptedTaxon
.addSynonym(synonym
, SynonymRelationshipType
.INFERRED_SYNONYM_OF());
905 logger
.error(synonym
.getTitleCache() + " has no synonym relationship to " + acceptedTaxon
.getTitleCache() + " type is set to inferred synonym");
908 localSuccess
&= synRelMapping
.invoke(synRel
);
910 logger
.error("Synonym relationship export failed " + synonym
.getTitleCache() + " accepted taxon: " + acceptedTaxon
.getUuid() + " (" + acceptedTaxon
.getTitleCache()+")");
914 for (SynonymRelationship synRel
: synonym
.getSynonymRelations()){
915 localSuccess
&= synRelMapping
.invoke(synRel
);
917 logger
.error("Synonym relationship export failed " + synonym
.getTitleCache() + " accepted taxon: " + acceptedTaxon
.getUuid() + " (" + acceptedTaxon
.getTitleCache()+")");
919 logger
.info("Synonym relationship successfully exported: " + synonym
.getTitleCache() + " " +acceptedTaxon
.getUuid() + " (" + acceptedTaxon
.getTitleCache()+")");
925 inferredSynonymsDataToBeSaved
.put(synonym
.getId(), synonym
.getName());
929 logger
.error(e
.getMessage());
933 logger
.error("Classification is NULL. Inferred Synonyms could not be created for this Taxon: " + acceptedTaxon
.getUuid() + " (" + acceptedTaxon
.getTitleCache() + ")");
936 // logger.error("TaxonName is not a ZoologicalName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
939 logger
.error("This TaxonBase is not a Taxon even though it should be: " + taxonBase
.getUuid() + " (" + taxonBase
.getTitleCache() + ")");
942 return inferredSynonymsDataToBeSaved
;
947 * Handles names that do not appear in taxa
952 private boolean doNames(PesiExportState state
, PesiExportMapping additionalSourceMapping
) throws SQLException
{
954 boolean success
= true;
955 if (! state
.getConfig().isDoPureNames()){
956 logger
.info ("Ignore PHASE 1b: PureNames");
961 PesiExportMapping mapping
= getPureNameMapping(state
);
962 mapping
.initialize(state
);
965 List
<NonViralName
<?
>> list
;
967 // Get the limit for objects to save within a single transaction.
968 int limit
= state
.getConfig().getLimitSave();
971 logger
.info("PHASE 1b: Export Pure Names ...");
973 TransactionStatus txStatus
= startTransaction(true);
974 logger
.info("Started new transaction for Pure Names. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
976 int partitionCount
= 0;
977 while ((list
= getNextPureNamePartition(null, limit
, partitionCount
++)) != null ) {
979 logger
.info("Fetched " + list
.size() + " names without taxa. Exporting...");
980 for (TaxonNameBase
<?
,?
> taxonName
: list
) {
981 doCount(count
++, modCount
, pluralString
);
982 success
&= mapping
.invoke(taxonName
);
984 if (taxonName
.getNomenclaturalReference() != null || StringUtils
.isNotBlank(taxonName
.getNomenclaturalMicroReference() )){
985 additionalSourceMapping
.invoke(taxonName
);
989 // Commit transaction
990 commitTransaction(txStatus
);
991 logger
.debug("Committed transaction.");
992 logger
.info("Exported " + (count
- pastCount
) + " " + pluralString
+ ". Total: " + count
);
996 txStatus
= startTransaction(true);
997 logger
.info("Started new transaction for PureNames. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
1000 logger
.info("No " + pluralString
+ " left to fetch.");
1002 // Commit transaction
1003 commitTransaction(txStatus
);
1004 logger
.debug("Committed transaction.");
1005 } catch (Exception e
) {
1006 logger
.error("Error occurred in pure name export");
1007 e
.printStackTrace();
1014 * Determines the current number of entries in the DataWarehouse database table <code>Taxon</code>.
1015 * @param state The {@link PesiExportState PesiExportState}.
1016 * @return The count.
1018 private Integer
determineTaxonCount(PesiExportState state
) {
1019 Integer result
= null;
1020 PesiExportConfigurator pesiConfig
= (PesiExportConfigurator
) state
.getConfig();
1023 Source destination
= pesiConfig
.getDestination();
1024 sql
= "SELECT max(taxonId) FROM Taxon";
1025 destination
.setQuery(sql
);
1026 ResultSet resultSet
= destination
.getResultSet();
1029 result
= resultSet
.getInt(1);
1030 } catch (SQLException e
) {
1031 logger
.error("TaxonCount could not be determined: " + e
.getMessage());
1032 e
.printStackTrace();
1038 * Checks whether a parent at specific level has a specific Rank.
1039 * @param taxonName A {@link TaxonNameBase TaxonName}.
1040 * @param level The ancestor level.
1041 * @param ancestorRank The ancestor rank.
1042 * @return Whether a parent at a specific level has a specific Rank.
1044 private boolean validateAncestorOfSpecificRank(TaxonBase
<?
> taxonBase
, int level
, Rank ancestorRank
) {
1045 boolean result
= false;
1046 TaxonNode parentNode
= null;
1047 if (taxonBase
.isInstanceOf(Taxon
.class)){
1048 Taxon taxon
= CdmBase
.deproxy(taxonBase
, Taxon
.class);
1049 // Get ancestor Taxon via TaxonNode
1050 Set
<TaxonNode
> taxonNodes
= taxon
.getTaxonNodes();
1051 if (taxonNodes
.size() == 1) {
1052 TaxonNode taxonNode
= taxonNodes
.iterator().next();
1053 if (taxonNode
!= null) {
1054 for (int i
= 0; i
< level
; i
++) {
1055 if (taxonNode
!= null) {
1056 taxonNode
= taxonNode
.getParent();
1059 parentNode
= taxonNode
;
1061 } else if (taxonNodes
.size() > 1) {
1062 logger
.error("This taxon has " + taxonNodes
.size() + " taxonNodes: " + taxon
.getUuid() + " (" + taxon
.getTitleCache() + ")");
1066 if (parentNode
!= null) {
1067 TaxonNode node
= CdmBase
.deproxy(parentNode
, TaxonNode
.class);
1068 Taxon parentTaxon
= node
.getTaxon();
1069 if (parentTaxon
!= null) {
1070 TaxonNameBase
<?
,?
> parentTaxonName
= parentTaxon
.getName();
1071 if (parentTaxonName
!= null && parentTaxonName
.getRank().equals(ancestorRank
)) {
1075 logger
.error("This TaxonNode has no Taxon: " + node
.getUuid());
1082 * Returns the AnnotationType for a given UUID.
1083 * @param uuid The Annotation UUID.
1084 * @param label The Annotation label.
1085 * @param text The Annotation text.
1086 * @param labelAbbrev The Annotation label abbreviation.
1087 * @return The AnnotationType.
1089 protected AnnotationType
getAnnotationType(UUID uuid
, String label
, String text
, String labelAbbrev
){
1090 AnnotationType annotationType
= (AnnotationType
)getTermService().find(uuid
);
1091 if (annotationType
== null) {
1092 annotationType
= AnnotationType
.NewInstance(label
, text
, labelAbbrev
);
1093 annotationType
.setUuid(uuid
);
1094 // annotationType.setVocabulary(AnnotationType.EDITORIAL().getVocabulary());
1095 getTermService().save(annotationType
);
1097 return annotationType
;
1101 * Traverses the classification recursively and stores determined values for every Taxon.
1102 * @param childNode The {@link TaxonNode TaxonNode} to process.
1103 * @param parentNode The parent {@link TaxonNode TaxonNode} of the childNode.
1104 * @param treeIndex The TreeIndex at the current level.
1105 * @param fetchLevel Rank to stop fetching at.
1106 * @param state The {@link PesiExportState PesiExportState}.
1108 private void traverseTree(TaxonNode childNode
, TaxonNode parentNode
, StringBuffer treeIndex
, Rank fetchLevel
, PesiExportState state
) {
1109 // Traverse all branches from this childNode until specified fetchLevel is reached.
1110 StringBuffer localTreeIndex
= new StringBuffer(treeIndex
);
1111 Taxon childTaxon
= childNode
.getTaxon();
1112 if (childTaxon
!= null) {
1113 if (isPesiTaxon(childTaxon
)){
1114 Integer taxonId
= state
.getDbId(childTaxon
);
1115 TaxonNameBase
<?
,?
> childName
= childTaxon
.getName();
1116 if (taxonId
!= null) {
1117 Rank childRank
= childName
.getRank();
1118 if (childRank
!= null) {
1119 if (! childRank
.equals(fetchLevel
)) {
1121 localTreeIndex
.append(taxonId
+ "#");
1123 saveData(childNode
, parentNode
, localTreeIndex
, state
, taxonId
);
1125 // Store treeIndex as annotation for further use
1126 Annotation annotation
= Annotation
.NewInstance(localTreeIndex
.toString(), getTreeIndexAnnotationType(), Language
.DEFAULT());
1127 childNode
.addAnnotation(annotation
);
1129 for (TaxonNode newNode
: childNode
.getChildNodes()) {
1130 if (newNode
.getTaxon() != null && isPesiTaxon(newNode
.getTaxon())){
1131 traverseTree(newNode
, childNode
, localTreeIndex
, fetchLevel
, state
);
1136 // logger.debug("Target Rank " + fetchLevel.getLabel() + " reached");
1140 logger
.error("Rank is NULL. FetchLevel can not be checked: " + childName
.getUuid() + " (" + childName
.getTitleCache() + ")");
1143 logger
.error("Taxon can not be found in state: " + childTaxon
.getUuid() + " (" + childTaxon
.getTitleCache() + ")");
1146 if (logger
.isDebugEnabled()){
1147 logger
.debug("Taxon is not a PESI taxon: " + childTaxon
.getUuid());
1152 logger
.error("Taxon is NULL for TaxonNode: " + childNode
.getUuid());
1157 * Stores values in database for every recursive round.
1158 * @param childNode The {@link TaxonNode TaxonNode} to process.
1159 * @param parentNode The parent {@link TaxonNode TaxonNode} of the childNode.
1160 * @param treeIndex The TreeIndex at the current level.
1161 * @param state The {@link PesiExportState PesiExportState}.
1162 * @param currentTaxonFk The TaxonFk to store the values for.
1164 private void saveData(TaxonNode childNode
, TaxonNode parentNode
, StringBuffer treeIndex
, PesiExportState state
, Integer currentTaxonFk
) {
1165 // We are differentiating kingdoms by the nomenclatural code for now.
1166 // This needs to be handled in a better way as soon as we know how to differentiate between more kingdoms.
1167 Taxon childTaxon
= childNode
.getTaxon();
1168 if (isPesiTaxon(childTaxon
)) {
1169 TaxonBase
<?
> parentTaxon
= null;
1170 if (parentNode
!= null) {
1171 parentTaxon
= parentNode
.getTaxon();
1175 invokeParentTaxonFkAndTreeIndex(state
.getDbId(parentTaxon
), currentTaxonFk
, treeIndex
);
1181 * Inserts values into the Taxon database table.
1182 * @param taxonName The {@link TaxonNameBase TaxonName}.
1183 * @param state The {@link PesiExportState PesiExportState}.
1184 * @param stmt The prepared statement.
1185 * @return Whether save was successful or not.
1187 protected boolean invokeParentTaxonFkAndTreeIndex(Integer parentTaxonFk
, Integer currentTaxonFk
, StringBuffer treeIndex
) {
1189 if (parentTaxonFk
!= null) {
1190 parentTaxonFk_TreeIndex_KingdomFkStmt
.setInt(1, parentTaxonFk
);
1192 parentTaxonFk_TreeIndex_KingdomFkStmt
.setObject(1, null);
1195 if (treeIndex
!= null) {
1196 parentTaxonFk_TreeIndex_KingdomFkStmt
.setString(2, treeIndex
.toString());
1198 parentTaxonFk_TreeIndex_KingdomFkStmt
.setObject(2, null);
1201 if (currentTaxonFk
!= null) {
1202 parentTaxonFk_TreeIndex_KingdomFkStmt
.setInt(3, currentTaxonFk
);
1204 parentTaxonFk_TreeIndex_KingdomFkStmt
.setObject(3, null);
1207 parentTaxonFk_TreeIndex_KingdomFkStmt
.executeUpdate();
1209 } catch (SQLException e
) {
1210 logger
.error("ParentTaxonFk (" + parentTaxonFk
==null?
"-":parentTaxonFk
+ ") and TreeIndex could not be inserted into database for taxon "+ (currentTaxonFk
== null?
"-" :currentTaxonFk
) + ": " + e
.getMessage());
1211 e
.printStackTrace();
1216 protected boolean invokeParentTaxonFk(Integer parentId
, Integer childId
) {
1218 parentTaxonFkStmt
.setInt(1, parentId
);
1219 parentTaxonFkStmt
.setInt(2, childId
);
1220 parentTaxonFkStmt
.executeUpdate();
1222 } catch (SQLException e
) {
1223 logger
.warn("ParentTaxonFk (" + parentId
==null?
"-":parentId
+ ") could not be inserted into database for taxon "+ (childId
== null?
"-" :childId
) + ": " + e
.getMessage());
1224 e
.printStackTrace();
1231 * Inserts Rank data and KingdomFk into the Taxon database table.
1232 * @param taxonName The {@link TaxonNameBase TaxonName}.
1233 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
1234 * @param taxonFk The TaxonFk to store the values for.
1236 * @param kindomFk The KingdomFk.
1237 * @return Whether save was successful or not.
1239 private boolean invokeRankDataAndKingdomFk(TaxonNameBase
<?
,?
> taxonName
, NomenclaturalCode nomenclaturalCode
, Integer taxonFk
, Integer kingdomFk
, PesiExportState state
) {
1241 Integer rankFk
= getRankFk(taxonName
, nomenclaturalCode
);
1242 if (rankFk
!= null) {
1243 rankUpdateStmt
.setInt(1, rankFk
);
1245 rankUpdateStmt
.setObject(1, null);
1248 String rankCache
= getRankCache(taxonName
, nomenclaturalCode
, state
);
1249 if (rankCache
!= null) {
1250 rankUpdateStmt
.setString(2, rankCache
);
1252 rankUpdateStmt
.setObject(2, null);
1255 if (kingdomFk
!= null) {
1256 rankUpdateStmt
.setInt(3, kingdomFk
);
1258 rankUpdateStmt
.setObject(3, null);
1261 if (taxonFk
!= null) {
1262 rankUpdateStmt
.setInt(4, taxonFk
);
1264 rankUpdateStmt
.setObject(4, null);
1267 rankUpdateStmt
.executeUpdate();
1269 } catch (SQLException e
) {
1270 logger
.error("Data (RankFk, RankCache, KingdomFk) could not be inserted into database: " + e
.getMessage());
1271 e
.printStackTrace();
1277 * Inserts Rank data, TypeNameFk, KingdomFk, expertFk and speciesExpertFk into the Taxon database table.
1278 * @param taxonName The {@link TaxonNameBase TaxonName}.
1279 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
1280 * @param taxonFk The TaxonFk to store the values for.
1281 * @param typeNameFk The TypeNameFk.
1283 * @param kindomFk The KingdomFk.
1284 * @param expertFk The ExpertFk.
1285 * @param speciesExpertFk The SpeciesExpertFk.
1286 * @return Whether save was successful or not.
1288 private boolean invokeRankDataAndTypeNameFkAndKingdomFk(TaxonNameBase
<?
,?
> taxonName
, NomenclaturalCode nomenclaturalCode
,
1289 Integer taxonFk
, Integer typeNameFk
, Integer kingdomFkk
, PesiExportState state
) {
1292 Integer rankFk
= getRankFk(taxonName
, nomenclaturalCode
);
1293 if (rankFk
!= null) {
1294 rankTypeExpertsUpdateStmt
.setInt(index
++, rankFk
);
1296 rankTypeExpertsUpdateStmt
.setObject(index
++, null);
1299 String rankCache
= getRankCache(taxonName
, nomenclaturalCode
, state
);
1300 if (rankCache
!= null) {
1301 rankTypeExpertsUpdateStmt
.setString(index
++, rankCache
);
1303 rankTypeExpertsUpdateStmt
.setObject(index
++, null);
1306 if (typeNameFk
!= null) {
1307 rankTypeExpertsUpdateStmt
.setInt(index
++, typeNameFk
);
1309 rankTypeExpertsUpdateStmt
.setObject(index
++, null);
1312 if (kingdomFk
!= null) {
1313 rankTypeExpertsUpdateStmt
.setInt(index
++, kingdomFk
);
1315 rankTypeExpertsUpdateStmt
.setObject(index
++, null);
1318 // if (expertFk != null) {
1319 // rankTypeExpertsUpdateStmt.setInt(5, expertFk);
1321 // rankTypeExpertsUpdateStmt.setObject(5, null);
1324 // //TODO handle experts GUIDS
1325 // if (speciesExpertFk != null) {
1326 // rankTypeExpertsUpdateStmt.setInt(6, speciesExpertFk);
1328 // rankTypeExpertsUpdateStmt.setObject(6, null);
1331 if (taxonFk
!= null) {
1332 rankTypeExpertsUpdateStmt
.setInt(index
++, taxonFk
);
1334 rankTypeExpertsUpdateStmt
.setObject(index
++, null);
1337 rankTypeExpertsUpdateStmt
.executeUpdate();
1339 } catch (SQLException e
) {
1340 logger
.error("Data could not be inserted into database: " + e
.getMessage());
1341 e
.printStackTrace();
1343 } catch (Exception e
) {
1344 logger
.error("Some exception occurred: " + e
.getMessage());
1345 e
.printStackTrace();
1351 * Deletes all entries of database tables related to <code>Taxon</code>.
1352 * @param state The {@link PesiExportState PesiExportState}.
1353 * @return Whether the delete operation was successful or not.
1355 protected boolean doDelete(PesiExportState state
) {
1356 PesiExportConfigurator pesiConfig
= (PesiExportConfigurator
) state
.getConfig();
1359 Source destination
= pesiConfig
.getDestination();
1362 sql
= "DELETE FROM " + dbTableName
;
1363 destination
.setQuery(sql
);
1364 destination
.update(sql
);
1369 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#isIgnore(eu.etaxonomy.cdm.io.common.IoStateBase)
1372 protected boolean isIgnore(PesiExportState state
) {
1373 return ! state
.getConfig().isDoTaxa();
1378 * Creates the kingdom fk.
1382 @SuppressWarnings("unused") //used by mapper
1383 private static Integer
getKingdomFk(TaxonNameBase taxonName
){
1384 return PesiTransformer
.nomenClaturalCode2Kingdom(taxonName
.getNomenclaturalCode());
1388 * Creates the parent fk.
1392 @SuppressWarnings("unused") //used by mapper
1393 private static Integer
getParentTaxonFk(TaxonBase
<?
> taxonBase
, PesiExportState state
){
1394 if (taxonBase
.isInstanceOf(Taxon
.class)){
1395 Taxon taxon
= CdmBase
.deproxy(taxonBase
, Taxon
.class);
1396 if (! isMisappliedName(taxon
)){
1397 Set
<TaxonNode
> nodes
= taxon
.getTaxonNodes();
1398 if (nodes
.size() == 0){
1399 if (taxon
.getName().getRank().isLower(Rank
.KINGDOM())){
1400 logger
.warn("Accepted taxon has no parent. " + taxon
.getTitleCache() + ", " + taxon
.getUuid());
1402 }else if (nodes
.size() > 1){
1403 logger
.warn("Taxon has more than 1 node attached. This is not supported by PESI export." + taxon
.getTitleCache() + ", " + taxon
.getUuid());
1405 Taxon parent
=nodes
.iterator().next().getParent().getTaxon();
1406 return state
.getDbId(parent
);
1414 * Returns the rankFk for the taxon name based on the names nomenclatural code.
1415 * You may not use this method for kingdoms other then Animalia, Plantae and Bacteria.
1419 @SuppressWarnings("unused") //used by mapper
1420 private static Integer
getRankFk(TaxonNameBase
<?
,?
> taxonName
) {
1421 return getRankFk(taxonName
, taxonName
.getNomenclaturalCode());
1426 * Returns the <code>RankFk</code> attribute.
1427 * @param taxonName The {@link TaxonNameBase TaxonName}.
1428 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
1429 * @return The <code>RankFk</code> attribute.
1432 private static Integer
getRankFk(TaxonNameBase
<?
,?
> taxonName
, NomenclaturalCode nomenclaturalCode
) {
1433 Integer result
= null;
1435 if (nomenclaturalCode
!= null) {
1436 if (taxonName
!= null) {
1437 if (taxonName
.getRank() == null) {
1438 logger
.warn("Rank is null: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1440 result
= PesiTransformer
.rank2RankId(taxonName
.getRank(), PesiTransformer
.nomenClaturalCode2Kingdom(nomenclaturalCode
));
1442 if (result
== null) {
1443 logger
.warn("Rank could not be determined for PESI-Kingdom-Id " + PesiTransformer
.nomenClaturalCode2Kingdom(nomenclaturalCode
) + " and TaxonName " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1447 } catch (Exception e
) {
1448 e
.printStackTrace();
1454 * Returns the rank cache for the taxon name based on the names nomenclatural code.
1455 * You may not use this method for kingdoms other then Animalia, Plantae and Bacteria.
1459 @SuppressWarnings("unused") //used by mapper
1460 private static String
getRankCache(TaxonNameBase
<?
,?
> taxonName
, PesiExportState state
) {
1461 return getRankCache(taxonName
, taxonName
.getNomenclaturalCode(), state
);
1466 * Returns the <code>RankCache</code> attribute.
1467 * @param taxonName The {@link TaxonNameBase TaxonName}.
1468 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
1470 * @return The <code>RankCache</code> attribute.
1473 private static String
getRankCache(TaxonNameBase
<?
,?
> taxonName
, NomenclaturalCode nomenclaturalCode
, PesiExportState state
) {
1474 if (nomenclaturalCode
!= null) {
1475 return state
.getTransformer().getCacheByRankAndKingdom(taxonName
.getRank(), PesiTransformer
.nomenClaturalCode2Kingdom(nomenclaturalCode
));
1477 logger
.warn("No nomenclatural code defined for name " + taxonName
.getUuid());
1485 * Returns the <code>DisplayName</code> attribute.
1486 * @param taxon The {@link TaxonBase Taxon}.
1487 * @return The <code>DisplayName</code> attribute.
1490 @SuppressWarnings("unused") //used by Mapper
1491 private static String
getDisplayName(TaxonBase
<?
> taxon
) {
1492 TaxonNameBase
<?
,?
> taxonName
= taxon
.getName();
1493 String result
= getDisplayName(taxonName
);
1494 if (isMisappliedName(taxon
)){
1495 result
= result
+ " " + getAuthorString(taxon
);
1501 * Returns the <code>AuthorString</code> attribute.
1502 * @param taxonName The {@link TaxonNameBase TaxonName}.
1503 * @return The <code>AuthorString</code> attribute.
1506 @SuppressWarnings("unused") //used by mapper
1507 protected static String
getAuthorString(TaxonBase
<?
> taxon
) {
1509 String result
= null;
1510 boolean isNonViralName
= false;
1511 String authorshipCache
= null;
1512 TaxonNameBase
<?
,?
> taxonName
= taxon
.getName();
1513 if (taxonName
!= null && taxonName
.isInstanceOf(NonViralName
.class)){
1514 authorshipCache
= CdmBase
.deproxy(taxonName
, NonViralName
.class).getAuthorshipCache();
1515 isNonViralName
= true;
1517 result
= authorshipCache
;
1519 // For a misapplied names there are special rules
1520 if (isMisappliedName(taxon
)){
1521 if (taxon
.getSec() != null){
1522 String secTitle
= taxon
.getSec().getTitleCache();
1523 if (! secTitle
.startsWith("auct")){
1524 secTitle
= "sensu " + secTitle
;
1525 }else if (secTitle
.equals("auct")){ //may be removed once the title cache is generated correctly for references with title auct. #
1529 }else if (StringUtils
.isBlank(authorshipCache
)) {
1530 // Set authorshipCache to "auct."
1531 result
= PesiTransformer
.AUCT_STRING
;
1533 result
= PesiTransformer
.AUCT_STRING
;
1534 // result = authorshipCache;
1538 if (taxonName
== null){
1539 logger
.warn("TaxonName does not exist for taxon: " + taxon
.getUuid() + " (" + taxon
.getTitleCache() + ")");
1540 }else if (! isNonViralName
){
1541 logger
.warn("TaxonName is not of instance NonViralName: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1544 if (StringUtils
.isBlank(result
)) {
1549 } catch (Exception e
) {
1550 e
.printStackTrace();
1558 * Returns the <code>DisplayName</code> attribute.
1559 * @param taxonName The {@link TaxonNameBase TaxonName}.
1560 * @return The <code>DisplayName</code> attribute.
1563 @SuppressWarnings("unused") //used by Mapper
1564 private static String
getDisplayName(TaxonNameBase
<?
,?
> taxonName
) {
1566 if (taxonName
== null) {
1569 INonViralNameCacheStrategy
<NonViralName
<?
>> cacheStrategy
= getCacheStrategy(taxonName
);
1570 HTMLTagRules tagRules
= new HTMLTagRules().
1571 addRule(TagEnum
.name
, "i").
1572 addRule(TagEnum
.nomStatus
, "@status@");
1574 NonViralName
<?
> nvn
= CdmBase
.deproxy(taxonName
, NonViralName
.class);
1575 String result
= cacheStrategy
.getFullTitleCache(nvn
, tagRules
);
1576 cacheStrategy
= null;
1578 return result
.replaceAll(",?\\<@status@\\>.*\\</@status@\\>", "");
1584 * Returns the <code>WebShowName</code> attribute for a taxon.
1585 * @param taxonName The {@link TaxonNameBase TaxonName}.
1586 * @return The <code>WebShowName</code> attribute.
1589 @SuppressWarnings("unused")
1590 private static String
getWebShowName(TaxonBase
<?
> taxon
) {
1591 TaxonNameBase
<?
,?
> taxonName
= taxon
.getName();
1592 String result
= getWebShowName(taxonName
);
1593 if (isMisappliedName(taxon
)){
1594 result
= result
+ " " + getAuthorString(taxon
);
1600 * Returns the <code>WebShowName</code> attribute.
1601 * @param taxonName The {@link TaxonNameBase TaxonName}.
1602 * @return The <code>WebShowName</code> attribute.
1605 private static String
getWebShowName(TaxonNameBase
<?
,?
> taxonName
) {
1607 if (taxonName
== null) {
1610 INonViralNameCacheStrategy
<NonViralName
<?
>> cacheStrategy
= getCacheStrategy(taxonName
);
1612 HTMLTagRules tagRules
= new HTMLTagRules().addRule(TagEnum
.name
, "i");
1613 NonViralName
<?
> nvn
= CdmBase
.deproxy(taxonName
, NonViralName
.class);
1614 String result
= cacheStrategy
.getTitleCache(nvn
, tagRules
);
1615 cacheStrategy
= null;
1623 * Returns the <code>WebSearchName</code> attribute.
1624 * @param taxonName The {@link NonViralName NonViralName}.
1625 * @return The <code>WebSearchName</code> attribute.
1628 @SuppressWarnings("unused")
1629 private static String
getWebSearchName(TaxonNameBase
<?
,?
> taxonName
) {
1631 NonViralName
<?
> nvn
= CdmBase
.deproxy(taxonName
, NonViralName
.class);
1632 NonViralNameDefaultCacheStrategy
<NonViralName
<?
>> strategy
= getCacheStrategy(nvn
);
1633 String result
= strategy
.getNameCache(nvn
);
1641 * Returns the <code>FullName</code> attribute.
1642 * @param taxonName The {@link NonViralName NonViralName}.
1643 * @return The <code>FullName</code> attribute.
1646 @SuppressWarnings("unused")
1647 private static String
getFullName(TaxonNameBase taxonName
) {
1649 NonViralName
<?
> nvn
= CdmBase
.deproxy(taxonName
, NonViralName
.class);
1650 String result
= getCacheStrategy(nvn
).getTitleCache(nvn
);
1651 Iterator
<TaxonBase
> taxa
= taxonName
.getTaxa().iterator();
1652 if (taxonName
.getTaxa().size() >0){
1653 if (taxonName
.getTaxa().size() == 1){
1654 TaxonBase taxon
= taxa
.next();
1655 if (isMisappliedName(taxon
)){
1656 result
= result
+ " " + getAuthorString(taxon
);
1667 * Returns the <code>FullName</code> attribute.
1668 * @param taxon The {@link TaxonBase taxon}.
1669 * @return The <code>FullName</code> attribute.
1672 /*@SuppressWarnings("unused")
1673 private static String getFullName(TaxonBase taxon) {
1675 TaxonNameBase name = taxon.getName();
1676 String result = getFullName(name);
1677 if (isMisappliedName(taxon)){
1678 result = result + " " + getAuthorString(taxon);
1686 * Returns the nomenclatural reference which is the reference
1687 * including the detail (microreference).
1688 * @param taxonName The {@link TaxonNameBase TaxonName}.
1689 * @return The <code>AuthorString</code> attribute.
1692 @SuppressWarnings("unused")
1693 private static String
getNomRefString(TaxonNameBase
<?
,?
> taxonName
) {
1694 INomenclaturalReference ref
= taxonName
.getNomenclaturalReference();
1695 return ref
== null ?
null : ref
.getNomenclaturalCitation(taxonName
.getNomenclaturalMicroReference());
1700 * Returns the <code>NameStatusFk</code> attribute.
1701 * @param taxonName The {@link TaxonNameBase TaxonName}.
1702 * @return The <code>NameStatusFk</code> attribute.
1705 @SuppressWarnings("unused")
1706 private static Integer
getNameStatusFk(TaxonNameBase
<?
,?
> taxonName
) {
1707 Integer result
= null;
1709 NomenclaturalStatus state
= getNameStatus(taxonName
);
1710 if (state
!= null) {
1711 result
= PesiTransformer
.nomStatus2nomStatusFk(state
.getType());
1717 * Returns the <code>NameStatusCache</code> attribute.
1718 * @param taxonName The {@link TaxonNameBase TaxonName}.
1719 * @return The <code>NameStatusCache</code> attribute.
1720 * @throws UndefinedTransformerMethodException
1723 @SuppressWarnings("unused")
1724 private static String
getNameStatusCache(TaxonNameBase taxonName
, PesiExportState state
) throws UndefinedTransformerMethodException
{
1725 String result
= null;
1726 NomenclaturalStatus status
= getNameStatus(taxonName
);
1727 if (status
!= null) {
1728 result
= state
.getTransformer().getCacheByNomStatus(status
.getType());
1734 private static NomenclaturalStatus
getNameStatus(TaxonNameBase
<?
,?
> taxonName
) {
1736 if (taxonName
!= null && (taxonName
.isInstanceOf(NonViralName
.class))) {
1737 NonViralName
<?
> nonViralName
= CdmBase
.deproxy(taxonName
, NonViralName
.class);
1738 Set
<NomenclaturalStatus
> states
= nonViralName
.getStatus();
1739 if (states
.size() == 1) {
1740 NomenclaturalStatus status
= states
.iterator().next();
1742 } else if (states
.size() > 1) {
1743 logger
.error("This TaxonName has more than one Nomenclatural Status: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1747 } catch (Exception e
) {
1748 e
.printStackTrace();
1753 * Returns the <code>TaxonStatusFk</code> attribute.
1754 * @param taxonName The {@link TaxonNameBase TaxonName}.
1755 * @param state The {@link PesiExportState PesiExportState}.
1756 * @return The <code>TaxonStatusFk</code> attribute.
1759 private static Integer
getTaxonStatusFk(TaxonBase
<?
> taxon
, PesiExportState state
) {
1760 Integer result
= null;
1763 if (isMisappliedName(taxon
)) {
1764 Synonym synonym
= Synonym
.NewInstance(null, null);
1766 // This works as long as only the instance is important to differentiate between TaxonStatus.
1767 result
= PesiTransformer
.taxonBase2statusFk(synonym
); // Auct References are treated as Synonyms in Datawarehouse now.
1769 result
= PesiTransformer
.taxonBase2statusFk(taxon
);
1772 } catch (Exception e
) {
1773 e
.printStackTrace();
1779 * Returns the <code>TaxonStatusCache</code> attribute.
1780 * @param taxonName The {@link TaxonNameBase TaxonName}.
1781 * @param state The {@link PesiExportState PesiExportState}.
1782 * @return The <code>TaxonStatusCache</code> attribute.
1783 * @throws UndefinedTransformerMethodException
1786 @SuppressWarnings("unused")
1787 private static String
getTaxonStatusCache(TaxonBase
<?
> taxon
, PesiExportState state
) throws UndefinedTransformerMethodException
{
1788 return state
.getTransformer().getTaxonStatusCacheByKey(getTaxonStatusFk(taxon
, state
));
1792 * Returns the <code>TypeNameFk</code> attribute.
1793 * @param taxonName The {@link TaxonNameBase TaxonName}.
1794 * @param state The {@link PesiExportState PesiExportState}.
1795 * @return The <code>TypeNameFk</code> attribute.
1798 private static Integer
getTypeNameFk(TaxonNameBase
<?
,?
> taxonNameBase
, PesiExportState state
) {
1799 Integer result
= null;
1800 if (taxonNameBase
!= null) {
1801 Set
<NameTypeDesignation
> nameTypeDesignations
= taxonNameBase
.getNameTypeDesignations();
1802 if (nameTypeDesignations
.size() == 1) {
1803 NameTypeDesignation nameTypeDesignation
= nameTypeDesignations
.iterator().next();
1804 if (nameTypeDesignation
!= null) {
1805 TaxonNameBase
<?
,?
> typeName
= nameTypeDesignation
.getTypeName();
1806 if (typeName
!= null) {
1807 result
= state
.getDbId(typeName
);
1810 } else if (nameTypeDesignations
.size() > 1) {
1811 logger
.warn("This TaxonName has " + nameTypeDesignations
.size() + " NameTypeDesignations: " + taxonNameBase
.getUuid() + " (" + taxonNameBase
.getTitleCache() + ")");
1818 * Returns the <code>TypeFullnameCache</code> attribute.
1819 * @param taxonName The {@link TaxonNameBase TaxonName}.
1820 * @return The <code>TypeFullnameCache</code> attribute.
1823 @SuppressWarnings("unused")
1824 private static String
getTypeFullnameCache(TaxonNameBase
<?
,?
> taxonName
) {
1825 String result
= null;
1828 if (taxonName
!= null) {
1829 Set
<NameTypeDesignation
> nameTypeDesignations
= taxonName
.getNameTypeDesignations();
1830 if (nameTypeDesignations
.size() == 1) {
1831 NameTypeDesignation nameTypeDesignation
= nameTypeDesignations
.iterator().next();
1832 if (nameTypeDesignation
!= null) {
1833 TaxonNameBase
<?
,?
> typeName
= nameTypeDesignation
.getTypeName();
1834 if (typeName
!= null) {
1835 result
= typeName
.getTitleCache();
1838 } else if (nameTypeDesignations
.size() > 1) {
1839 logger
.warn("This TaxonName has " + nameTypeDesignations
.size() + " NameTypeDesignations: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1843 } catch (Exception e
) {
1844 e
.printStackTrace();
1851 * Returns the <code>QualityStatusFk</code> attribute.
1852 * @param taxonName The {@link TaxonNameBase TaxonName}.
1853 * @return The <code>QualityStatusFk</code> attribute.
1856 private static Integer
getQualityStatusFk(TaxonNameBase taxonName
) {
1857 BitSet sources
= getSources(taxonName
);
1858 return PesiTransformer
.getQualityStatusKeyBySource(sources
, taxonName
);
1863 * Returns the <code>QualityStatusCache</code> attribute.
1864 * @param taxonName The {@link TaxonNameBase TaxonName}.
1865 * @return The <code>QualityStatusCache</code> attribute.
1866 * @throws UndefinedTransformerMethodException
1869 @SuppressWarnings("unused")
1870 private static String
getQualityStatusCache(TaxonNameBase taxonName
, PesiExportState state
) throws UndefinedTransformerMethodException
{
1871 return state
.getTransformer().getQualityStatusCacheByKey(getQualityStatusFk(taxonName
));
1876 * Returns the <code>TypeDesignationStatusFk</code> attribute.
1877 * @param taxonName The {@link TaxonNameBase TaxonName}.
1878 * @return The <code>TypeDesignationStatusFk</code> attribute.
1881 @SuppressWarnings("unused")
1882 private static Integer
getTypeDesignationStatusFk(TaxonNameBase
<?
,?
> taxonName
) {
1883 Integer result
= null;
1886 if (taxonName
!= null) {
1887 Set
<NameTypeDesignation
> typeDesignations
= taxonName
.getNameTypeDesignations();
1888 if (typeDesignations
.size() == 1) {
1889 Object obj
= typeDesignations
.iterator().next().getTypeStatus();
1890 NameTypeDesignationStatus designationStatus
= CdmBase
.deproxy(obj
, NameTypeDesignationStatus
.class);
1891 result
= PesiTransformer
.nameTypeDesignationStatus2TypeDesignationStatusId(designationStatus
);
1892 } else if (typeDesignations
.size() > 1) {
1893 logger
.error("Found a TaxonName with more than one NameTypeDesignation: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1897 } catch (Exception e
) {
1898 e
.printStackTrace();
1904 * Returns the <code>TypeDesignationStatusCache</code> attribute.
1905 * @param taxonName The {@link TaxonNameBase TaxonName}.
1906 * @return The <code>TypeDesignationStatusCache</code> attribute.
1909 @SuppressWarnings("unused")
1910 private static String
getTypeDesignationStatusCache(TaxonNameBase
<?
,?
> taxonName
) {
1911 String result
= null;
1914 if (taxonName
!= null) {
1915 Set
<NameTypeDesignation
> typeDesignations
= taxonName
.getNameTypeDesignations();
1916 if (typeDesignations
.size() == 1) {
1917 Object obj
= typeDesignations
.iterator().next().getTypeStatus();
1918 NameTypeDesignationStatus designationStatus
= CdmBase
.deproxy(obj
, NameTypeDesignationStatus
.class);
1919 result
= PesiTransformer
.nameTypeDesignationStatus2TypeDesignationStatusCache(designationStatus
);
1920 } else if (typeDesignations
.size() > 1) {
1921 logger
.error("Found a TaxonName with more than one NameTypeDesignation: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1925 } catch (Exception e
) {
1926 e
.printStackTrace();
1932 * Returns the <code>FossilStatusFk</code> attribute.
1933 * @param taxonName The {@link TaxonNameBase TaxonName}.
1934 * @return The <code>FossilStatusFk</code> attribute.
1937 @SuppressWarnings("unused")
1938 private static Integer
getFossilStatusFk(IdentifiableEntity
<?
> identEntity
, PesiExportState state
) {
1939 Integer result
= null;
1941 Set
<String
> fossilStatuus
= identEntity
.getExtensions(ErmsTransformer
.uuidFossilStatus
);
1942 if (fossilStatuus
.size() == 0){
1944 }else if (fossilStatuus
.size() > 1){
1945 logger
.warn("More than 1 fossil status given for " + identEntity
.getTitleCache() + " " + identEntity
.getUuid());
1947 String fossilStatus
= fossilStatuus
.iterator().next();
1949 int statusFk
= state
.getTransformer().FossilStatusCache2FossilStatusFk(fossilStatus
);
1954 * Returns the <code>FossilStatusCache</code> attribute.
1955 * @param taxonName The {@link TaxonNameBase TaxonName}.
1956 * @return The <code>FossilStatusCache</code> attribute.
1959 @SuppressWarnings("unused")
1960 private static String
getFossilStatusCache(IdentifiableEntity
<?
> identEntity
, PesiExportState state
) {
1961 String result
= null;
1962 Set
<String
> fossilStatuus
= identEntity
.getExtensions(ErmsTransformer
.uuidFossilStatus
);
1963 if (fossilStatuus
.size() == 0){
1966 for (String strFossilStatus
: fossilStatuus
){
1967 result
= CdmUtils
.concat(";", result
, strFossilStatus
);
1973 * Returns the <code>IdInSource</code> attribute.
1974 * @param taxonName The {@link TaxonNameBase TaxonName}.
1975 * @return The <code>IdInSource</code> attribute.
1978 @SuppressWarnings("unused")
1979 private static String
getIdInSource(IdentifiableEntity taxonName
) {
1980 String result
= null;
1983 Set
<IdentifiableSource
> sources
= getPesiSources(taxonName
);
1984 if (sources
.size() > 1){
1985 logger
.warn("There is > 1 Pesi source. This is not yet handled.");
1987 if (sources
.size() == 0){
1988 logger
.warn("There is no Pesi source!" +taxonName
.getUuid() + " (" + taxonName
.getTitleCache() +")");
1990 for (IdentifiableSource source
: sources
) {
1991 Reference
<?
> ref
= source
.getCitation();
1992 UUID refUuid
= ref
.getUuid();
1993 String idInSource
= source
.getIdInSource();
1994 if (refUuid
.equals(PesiTransformer
.uuidSourceRefEuroMed
)){
1995 result
= idInSource
!= null ?
("NameId: " + source
.getIdInSource()) : null;
1996 }else if (refUuid
.equals(PesiTransformer
.uuidSourceRefFaunaEuropaea
)){
1997 result
= idInSource
!= null ?
("TAX_ID: " + source
.getIdInSource()) : null;
1998 }else if (refUuid
.equals(PesiTransformer
.uuidSourceRefErms
)){
1999 result
= idInSource
!= null ?
("tu_id: " + source
.getIdInSource()) : null;
2000 }else if (refUuid
.equals(PesiTransformer
.uuidSourceRefIndexFungorum
)){ //Index Fungorum
2001 result
= idInSource
!= null ?
("if_id: " + source
.getIdInSource()) : null;
2003 if (logger
.isDebugEnabled()){logger
.debug("Not a PESI source");};
2006 String sourceIdNameSpace
= source
.getIdNamespace();
2007 if (sourceIdNameSpace
!= null) {
2008 if (sourceIdNameSpace
.equals(PesiTransformer
.STR_NAMESPACE_NOMINAL_TAXON
)) {
2009 result
= idInSource
!= null ?
("Nominal Taxon from TAX_ID: " + source
.getIdInSource()):null;
2010 } else if (sourceIdNameSpace
.equals(TaxonServiceImpl
.INFERRED_EPITHET_NAMESPACE
)) {
2011 result
= idInSource
!= null ?
("Inferred epithet from TAX_ID: " + source
.getIdInSource()) : null;
2012 } else if (sourceIdNameSpace
.equals(TaxonServiceImpl
.INFERRED_GENUS_NAMESPACE
)) {
2013 result
= idInSource
!= null ?
("Inferred genus from TAX_ID: " + source
.getIdInSource()):null;
2014 } else if (sourceIdNameSpace
.equals(TaxonServiceImpl
.POTENTIAL_COMBINATION_NAMESPACE
)) {
2015 result
= idInSource
!= null ?
("Potential combination from TAX_ID: " + source
.getIdInSource()):null;
2018 if (result
== null) {
2019 logger
.warn("IdInSource is NULL for this taxonName: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() +", sourceIdNameSpace: " + source
.getIdNamespace()+")");
2022 } catch (Exception e
) {
2023 e
.printStackTrace();
2024 logger
.error("An error occurs while creating idInSource..." + taxonName
.getUuid() + " (" + taxonName
.getTitleCache()+ e
.getMessage());
2027 if (result
== null) {
2028 logger
.warn("IdInSource is NULL for this taxonName: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() +")");
2034 * Returns the idInSource for a given TaxonName only.
2035 * @param taxonName The {@link TaxonNameBase TaxonName}.
2036 * @return The idInSource.
2038 private static String
getIdInSourceOnly(IdentifiableEntity identEntity
) {
2039 String result
= null;
2041 // Get the sources first
2042 Set
<IdentifiableSource
> sources
= getPesiSources(identEntity
);
2044 // Determine the idInSource
2045 if (sources
.size() == 1) {
2046 IdentifiableSource source
= sources
.iterator().next();
2047 if (source
!= null) {
2048 result
= source
.getIdInSource();
2050 } else if (sources
.size() > 1) {
2053 for (IdentifiableSource source
: sources
) {
2054 result
+= source
.getIdInSource();
2055 if (count
< sources
.size()) {
2067 * Returns the Sources for a given TaxonName only.
2068 * @param taxonName The {@link TaxonNameBase TaxonName}.
2069 * @return The Sources.
2071 private static Set
<IdentifiableSource
> getPesiSources(IdentifiableEntity identEntity
) {
2072 Set
<IdentifiableSource
> sources
= new java
.util
.HashSet
<IdentifiableSource
>();
2075 if (identEntity
.isInstanceOf(TaxonNameBase
.class)){
2076 // Sources from TaxonName
2077 TaxonNameBase taxonName
= CdmBase
.deproxy(identEntity
, TaxonNameBase
.class);
2078 Set
<IdentifiableSource
> testSources
= identEntity
.getSources();
2079 sources
= filterPesiSources(identEntity
.getSources());
2081 if (sources
.size() == 0 && testSources
.size()>0){
2082 IdentifiableSource source
= testSources
.iterator().next();
2083 logger
.warn("There are sources, but they are no pesi sources!!!" + source
.getIdInSource() + " - " + source
.getIdNamespace() + " - "+source
.getCitation().generateTitle());
2085 if (sources
.size() > 1) {
2086 logger
.warn("This TaxonName has more than one Source: " + identEntity
.getUuid() + " (" + identEntity
.getTitleCache() + ")");
2089 // name has no PESI source, take sources from TaxonBase
2090 if (sources
== null || sources
.isEmpty()) {
2091 Set
<TaxonBase
> taxa
= taxonName
.getTaxonBases();
2092 for (TaxonBase taxonBase
: taxa
){
2093 sources
.addAll(filterPesiSources(taxonBase
.getSources()));
2098 }else if (identEntity
.isInstanceOf(TaxonBase
.class)){
2099 sources
= filterPesiSources(identEntity
.getSources());
2102 /*TODO: deleted only for testing the inferred synonyms
2103 if (sources == null || sources.isEmpty()) {
2104 logger.warn("This TaxonName has no PESI Sources: " + identEntity.getUuid() + " (" + identEntity.getTitleCache() +")");
2105 }else if (sources.size() > 1){
2106 logger.warn("This Taxon(Name) has more than 1 PESI source: " + identEntity.getUuid() + " (" + identEntity.getTitleCache() +")");
2112 // return all sources with a PESI reference
2113 private static Set
<IdentifiableSource
> filterPesiSources(Set
<?
extends IdentifiableSource
> sources
) {
2114 Set
<IdentifiableSource
> result
= new HashSet
<IdentifiableSource
>();
2115 for (IdentifiableSource source
: sources
){
2116 Reference ref
= source
.getCitation();
2117 UUID refUuid
= ref
.getUuid();
2118 if (refUuid
.equals(PesiTransformer
.uuidSourceRefEuroMed
) ||
2119 refUuid
.equals(PesiTransformer
.uuidSourceRefFaunaEuropaea
)||
2120 refUuid
.equals(PesiTransformer
.uuidSourceRefErms
)||
2121 refUuid
.equals(PesiTransformer
.uuidSourceRefIndexFungorum
) ||
2122 refUuid
.equals(PesiTransformer
.uuidSourceRefAuct
)){
2130 * Returns the <code>GUID</code> attribute.
2131 * @param taxonName The {@link TaxonNameBase TaxonName}.
2132 * @return The <code>GUID</code> attribute.
2135 private static String
getGUID(TaxonBase
<?
> taxon
) {
2136 if (taxon
.getLsid() != null ){
2137 return taxon
.getLsid().getLsid();
2138 }else if (taxon
.hasMarker(PesiTransformer
.uuidMarkerGuidIsMissing
, true)){
2141 return taxon
.getUuid().toString();
2149 * Returns the <code>DerivedFromGuid</code> attribute.
2150 * @param taxonName The {@link TaxonNameBase TaxonName}.
2151 * @return The <code>DerivedFromGuid</code> attribute.
2154 @SuppressWarnings("unused")
2155 private static String
getDerivedFromGuid(TaxonBase
<?
> taxon
) {
2156 String result
= null;
2158 // The same as GUID for now
2159 result
= getGUID(taxon
);
2160 } catch (Exception e
) {
2161 e
.printStackTrace();
2167 * Returns the <code>CacheCitation</code> attribute.
2168 * @param taxonName The {@link TaxonNameBase TaxonName}.
2169 * @return The CacheCitation.
2172 @SuppressWarnings("unused")
2173 private static String
getCacheCitation(TaxonBase taxon
) {
2174 // !!! See also doPhaseUpdates
2176 TaxonNameBase
<?
,?
> taxonName
= taxon
.getName();
2178 //TODO implement anew for taxa
2180 BitSet sources
= getSources(taxonName
);
2181 if (sources
.isEmpty()) {
2182 // logger.error("OriginalDB is NULL for this TaxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
2183 } else if (sources
.get(PesiTransformer
.SOURCE_ERMS
)) {
2184 // 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...
2185 // So the following code is some kind of harmless assumption.
2186 Set
<Extension
> extensions
= taxonName
.getExtensions();
2187 for (Extension extension
: extensions
) {
2188 if (extension
.getType().equals(cacheCitationExtensionType
)) {
2189 result
= extension
.getValue();
2193 String expertName
= getExpertName(taxon
);
2194 String webShowName
= getWebShowName(taxonName
);
2197 String idInSource
= getIdInSourceOnly(taxonName
);
2199 // build the cacheCitation
2200 if (expertName
!= null) {
2201 result
+= expertName
+ ". ";
2203 if (logger
.isDebugEnabled()){logger
.debug("ExpertName could not be determined for this TaxonName: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");}
2205 if (webShowName
!= null) {
2206 result
+= webShowName
+ ". ";
2208 logger
.warn("WebShowName could not be determined for this TaxonName: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
2211 if (getOriginalDB(taxonName
).equals("FaEu")) {
2212 result
+= "Accessed through: Fauna Europaea at http://faunaeur.org/full_results.php?id=";
2213 } else if (getOriginalDB(taxonName
).equals("EM")) {
2214 result
+= "Accessed through: Euro+Med PlantBase at http://ww2.bgbm.org/euroPlusMed/PTaxonDetail.asp?UUID=";
2217 if (idInSource
!= null) {
2218 result
+= idInSource
;
2220 logger
.warn("IdInSource could not be determined for this TaxonName: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
2223 } catch (Exception e
) {
2224 e
.printStackTrace();
2227 if (StringUtils
.isBlank(result
)) {
2235 * Returns the <code>OriginalDB</code> attribute.
2236 * @param taxonName The {@link TaxonNameBase TaxonName}.
2237 * @return The <code>OriginalDB</code> attribute.
2240 private static String
getOriginalDB(IdentifiableEntity identEntity
) {
2241 // Sources from TaxonName
2242 BitSet sources
= getSources(identEntity
);
2243 return PesiTransformer
.getOriginalDbBySources(sources
);
2247 * Returns the <code>LastAction</code> attribute.
2248 * @param taxonName The {@link TaxonNameBase TaxonName}.
2249 * @return The <code>LastAction</code> attribute.
2252 @SuppressWarnings("unused")
2253 private static String
getLastAction(IdentifiableEntity
<?
> identEntity
) {
2254 String result
= null;
2256 Set
<Extension
> extensions
= identEntity
.getExtensions();
2257 for (Extension extension
: extensions
) {
2258 if (extension
.getType().equals(lastActionExtensionType
)) {
2259 result
= extension
.getValue();
2262 } catch (Exception e
) {
2263 e
.printStackTrace();
2269 * Returns the <code>LastActionDate</code> attribute.
2270 * @param taxonName The {@link TaxonNameBase TaxonName}.
2271 * @return The <code>LastActionDate</code> attribute.
2274 @SuppressWarnings({ "unused" })
2275 private static DateTime
getLastActionDate(IdentifiableEntity identEntity
) {
2276 DateTime result
= null;
2278 Set
<Extension
> extensions
= identEntity
.getExtensions();
2279 for (Extension extension
: extensions
) {
2280 if (extension
.getType().equals(lastActionDateExtensionType
)) {
2281 String dateTime
= extension
.getValue();
2282 if (dateTime
!= null) {
2283 DateTimeFormatter formatter
= DateTimeFormat
.forPattern("yyyy-MM-dd HH:mm:ss.S");
2284 result
= formatter
.parseDateTime(dateTime
);
2288 } catch (Exception e
) {
2289 e
.printStackTrace();
2295 * Returns the <code>ExpertName</code> attribute.
2296 * @param taxonName The {@link TaxonNameBase TaxonName}.
2297 * @return The <code>ExpertName</code> attribute.
2300 @SuppressWarnings("unused")
2301 private static String
getExpertName(TaxonBase
<?
> taxonName
) {
2302 String result
= null;
2304 Set
<Extension
> extensions
= taxonName
.getExtensions();
2305 for (Extension extension
: extensions
) {
2306 if (extension
.getType().equals(expertNameExtensionType
)) {
2307 result
= extension
.getValue();
2310 } catch (Exception e
) {
2311 e
.printStackTrace();
2317 * Returns the <code>ExpertFk</code> attribute.
2318 * @param taxonName The {@link TaxonNameBase TaxonName}.
2319 * @param state The {@link PesiExportState PesiExportState}.
2320 * @return The <code>ExpertFk</code> attribute.
2323 private static Integer
getExpertFk(Reference
<?
> reference
, PesiExportState state
) {
2324 Integer result
= state
.getDbId(reference
);
2329 * Returns the <code>SpeciesExpertName</code> attribute.
2330 * @param taxonName The {@link TaxonNameBase TaxonName}.
2331 * @return The <code>SpeciesExpertName</code> attribute.
2334 @SuppressWarnings("unused")
2335 private static String
getSpeciesExpertName(TaxonBase
<?
> taxonName
) {
2336 String result
= null;
2338 Set
<Extension
> extensions
= taxonName
.getExtensions();
2339 for (Extension extension
: extensions
) {
2340 if (extension
.getType().equals(speciesExpertNameExtensionType
)) {
2341 result
= extension
.getValue();
2344 } catch (Exception e
) {
2345 e
.printStackTrace();
2351 * Returns the <code>SpeciesExpertFk</code> attribute.
2352 * @param reference The {@link Reference Reference}.
2353 * @param state The {@link PesiExportState PesiExportState}.
2354 * @return The <code>SpeciesExpertFk</code> attribute.
2357 private static Integer
getSpeciesExpertFk(Reference
<?
> reference
, PesiExportState state
) {
2358 Integer result
= state
.getDbId(reference
);
2364 * Returns the source (E+M, Fauna Europaea, Index Fungorum, ERMS) of a given
2365 * Identifiable Entity as a BitSet
2366 * @param identEntity
2369 private static BitSet
getSources(IdentifiableEntity
<?
> identEntity
){
2370 BitSet bitSet
= new BitSet();
2371 Set
<IdentifiableSource
> sources
= getPesiSources(identEntity
);
2372 for (IdentifiableSource source
: sources
) {
2373 Reference
<?
> ref
= source
.getCitation();
2374 UUID refUuid
= ref
.getUuid();
2375 if (refUuid
.equals(PesiTransformer
.uuidSourceRefEuroMed
)){
2376 bitSet
.set(PesiTransformer
.SOURCE_EM
);
2377 }else if (refUuid
.equals(PesiTransformer
.uuidSourceRefFaunaEuropaea
)){
2378 bitSet
.set(PesiTransformer
.SOURCE_FE
);
2379 }else if (refUuid
.equals(PesiTransformer
.uuidSourceRefErms
)){
2380 bitSet
.set(PesiTransformer
.SOURCE_ERMS
);
2381 }else if (refUuid
.equals(PesiTransformer
.uuidSourceRefIndexFungorum
)){
2382 bitSet
.set(PesiTransformer
.SOURCE_IF
);
2384 if (logger
.isDebugEnabled()){logger
.debug("Not a PESI source");};
2391 protected static NonViralNameDefaultCacheStrategy
getCacheStrategy(TaxonNameBase
<?
, ?
> taxonName
) {
2392 taxonName
= CdmBase
.deproxy(taxonName
, TaxonNameBase
.class);
2393 NonViralNameDefaultCacheStrategy
<?
> cacheStrategy
;
2394 if (taxonName
.isInstanceOf(ZoologicalName
.class)){
2395 cacheStrategy
= zooNameStrategy
;
2396 }else if (taxonName
.isInstanceOf(BotanicalName
.class)) {
2397 cacheStrategy
= botanicalNameStrategy
;
2398 }else if (taxonName
.getClass().equals(NonViralName
.class)) {
2399 cacheStrategy
= nonViralNameStrategy
;
2400 }else if (taxonName
.getClass().equals(BacterialName
.class)) {
2401 cacheStrategy
= bacterialNameStrategy
;
2403 logger
.error("Unhandled taxon name type. Can't define strategy class");
2404 cacheStrategy
= botanicalNameStrategy
;
2406 return cacheStrategy
;
2410 * Returns the <code>TaxonFk1</code> attribute. It corresponds to a CDM <code>TaxonRelationship</code>.
2411 * @param relationship The {@link RelationshipBase Relationship}.
2412 * @param state The {@link PesiExportState PesiExportState}.
2413 * @return The <code>TaxonFk1</code> attribute.
2416 private static Integer
getTaxonFk1(RelationshipBase
<?
, ?
, ?
> relationship
, PesiExportState state
) {
2418 return getObjectFk(relationship
, state
, true);
2422 * Returns the <code>TaxonFk2</code> attribute. It corresponds to a CDM <code>SynonymRelationship</code>.
2423 * @param relationship The {@link RelationshipBase Relationship}.
2424 * @param state The {@link PesiExportState PesiExportState}.
2425 * @return The <code>TaxonFk2</code> attribute.
2428 private static Integer
getTaxonFk2(RelationshipBase
<?
, ?
, ?
> relationship
, PesiExportState state
) {
2429 return getObjectFk(relationship
, state
, false);
2433 * Returns the database key of an object in the given relationship.
2434 * @param relationship {@link RelationshipBase RelationshipBase}.
2435 * @param state {@link PesiExportState PesiExportState}.
2436 * @param isFrom A boolean value indicating whether the database key of the parent or child in this relationship is searched. <code>true</code> means the child is searched. <code>false</code> means the parent is searched.
2437 * @return The database key of an object in the given relationship.
2439 private static Integer
getObjectFk(RelationshipBase
<?
, ?
, ?
> relationship
, PesiExportState state
, boolean isFrom
) {
2440 TaxonBase
<?
> taxonBase
= null;
2441 if (relationship
.isInstanceOf(TaxonRelationship
.class)) {
2442 TaxonRelationship tr
= (TaxonRelationship
)relationship
;
2443 taxonBase
= (isFrom
) ? tr
.getFromTaxon(): tr
.getToTaxon();
2444 } else if (relationship
.isInstanceOf(SynonymRelationship
.class)) {
2445 SynonymRelationship sr
= (SynonymRelationship
)relationship
;
2446 taxonBase
= (isFrom
) ? sr
.getSynonym() : sr
.getAcceptedTaxon();
2447 } else if (relationship
.isInstanceOf(NameRelationship
.class) || relationship
.isInstanceOf(HybridRelationship
.class)) {
2449 return state
.getDbId(state
.getCurrentFromObject());
2451 return state
.getDbId(state
.getCurrentToObject());
2454 if (taxonBase
!= null) {
2455 if (! isPesiTaxon(taxonBase
)){
2456 logger
.warn("Related taxonBase is not a PESI taxon. Taxon: " + taxonBase
.getId() + "/" + taxonBase
.getUuid() + "; TaxonRel: " + relationship
.getId() + "(" + relationship
.getType().getTitleCache() + ")");
2459 return state
.getDbId(taxonBase
);
2463 logger
.warn("No taxon found in state for relationship: " + relationship
.toString());
2468 * Returns the <code>RelQualifierCache</code> attribute.
2469 * @param relationship The {@link RelationshipBase Relationship}.
2470 * @return The <code>RelQualifierCache</code> attribute.
2473 @SuppressWarnings("unused")
2474 private static String
getRelQualifierCache(RelationshipBase
<?
, ?
, ?
> relationship
, PesiExportState state
) {
2475 String result
= null;
2476 NomenclaturalCode code
= null;
2477 if (relationship
.isInstanceOf(TaxonRelationship
.class)){
2478 code
= CdmBase
.deproxy(relationship
, TaxonRelationship
.class).getToTaxon().getName().getNomenclaturalCode();
2479 }else if (relationship
.isInstanceOf(SynonymRelationship
.class)){
2480 code
= CdmBase
.deproxy(relationship
, SynonymRelationship
.class).getAcceptedTaxon().getName().getNomenclaturalCode();
2481 }else if (relationship
.isInstanceOf(NameRelationship
.class)){
2482 code
= CdmBase
.deproxy(relationship
, NameRelationship
.class).getFromName().getNomenclaturalCode();
2483 }else if (relationship
.isInstanceOf(HybridRelationship
.class)){
2484 code
= CdmBase
.deproxy(relationship
, HybridRelationship
.class).getParentName().getNomenclaturalCode();
2487 result
= state
.getConfig().getTransformer().getCacheByRelationshipType(relationship
, code
);
2489 logger
.error("NomenclaturalCode is NULL while creating the following relationship: " + relationship
.getUuid());
2495 * Returns the <code>RelTaxonQualifierFk</code> attribute.
2496 * @param relationship The {@link RelationshipBase Relationship}.
2497 * @return The <code>RelTaxonQualifierFk</code> attribute.
2500 @SuppressWarnings("unused")
2501 private static Integer
getRelTaxonQualifierFk(RelationshipBase
<?
, ?
, ?
> relationship
) {
2502 return PesiTransformer
.taxonRelation2RelTaxonQualifierFk(relationship
);
2505 * Returns the <code>Notes</code> attribute.
2506 * @param relationship The {@link RelationshipBase Relationship}.
2507 * @return The <code>Notes</code> attribute.
2510 @SuppressWarnings("unused")
2511 private static String
getNotes(RelationshipBase
<?
, ?
, ?
> relationship
) {
2518 * Returns the CDM to PESI specific export mappings.
2519 * @return The {@link PesiExportMapping PesiExportMapping}.
2521 private PesiExportMapping
getMapping() {
2522 PesiExportMapping mapping
= new PesiExportMapping(dbTableName
);
2524 mapping
.addMapper(IdMapper
.NewInstance("TaxonId"));
2525 mapping
.addMapper(DbObjectMapper
.NewInstance("sec", "sourceFk")); //OLD:mapping.addMapper(MethodMapper.NewInstance("SourceFK", this.getClass(), "getSourceFk", standardMethodParameter, PesiExportState.class));
2526 mapping
.addMapper(MethodMapper
.NewInstance("TaxonStatusFk", this.getClass(), "getTaxonStatusFk", standardMethodParameter
, PesiExportState
.class));
2527 mapping
.addMapper(MethodMapper
.NewInstance("TaxonStatusCache", this.getClass(), "getTaxonStatusCache", standardMethodParameter
, PesiExportState
.class));
2529 mapping
.addMapper(MethodMapper
.NewInstance("GUID", this));
2531 mapping
.addMapper(MethodMapper
.NewInstance("DerivedFromGuid", this));
2532 mapping
.addMapper(MethodMapper
.NewInstance("CacheCitation", this));
2533 mapping
.addMapper(MethodMapper
.NewInstance("AuthorString", this)); //For Taxon because Misallied Names are handled differently
2534 mapping
.addMapper(MethodMapper
.NewInstance("WebShowName", this));
2537 mapping
.addMapper(MethodMapper
.NewInstance("DisplayName", this));
2539 // FossilStatus (Fk, Cache)
2540 mapping
.addMapper(MethodMapper
.NewInstance("FossilStatusCache", this, IdentifiableEntity
.class, PesiExportState
.class));
2541 mapping
.addMapper(MethodMapper
.NewInstance("FossilStatusFk", this, IdentifiableEntity
.class, PesiExportState
.class)); // PesiTransformer.FossilStatusCache2FossilStatusFk?
2543 //handled by name mapping
2544 mapping
.addMapper(DbLastActionMapper
.NewInstance("LastActionDate", false));
2545 mapping
.addMapper(DbLastActionMapper
.NewInstance("LastAction", true));
2548 ExtensionType extensionTypeSpeciesExpertName
= (ExtensionType
)getTermService().find(PesiTransformer
.speciesExpertNameUuid
);
2549 mapping
.addMapper(DbExtensionMapper
.NewInstance(extensionTypeSpeciesExpertName
, "SpeciesExpertName"));
2550 ExtensionType extensionTypeExpertName
= (ExtensionType
)getTermService().find(PesiTransformer
.expertNameUuid
);
2551 mapping
.addMapper(DbExtensionMapper
.NewInstance(extensionTypeExpertName
, "ExpertName"));
2553 // mapping.addMapper(MethodMapper.NewInstance("ParentTaxonFk", this, TaxonBase.class, PesiExportState.class)); //by AM, doesn't work, FK exception
2554 mapping
.addMapper(ObjectChangeMapper
.NewInstance(TaxonBase
.class, TaxonNameBase
.class, "Name"));
2556 addNameMappers(mapping
);
2562 * Returns the CDM to PESI specific export mappings.
2564 * @return The {@link PesiExportMapping PesiExportMapping}.
2565 * @throws UndefinedTransformerMethodException
2567 private PesiExportMapping
getPureNameMapping(PesiExportState state
) throws UndefinedTransformerMethodException
{
2568 PesiExportMapping mapping
= new PesiExportMapping(dbTableName
);
2570 mapping
.addMapper(IdMapper
.NewInstance("TaxonId"));
2572 // mapping.addMapper(MethodMapper.NewInstance("TaxonStatusFk", this.getClass(), "getTaxonStatusFk", standardMethodParameter, PesiExportState.class));
2574 mapping
.addMapper(MethodMapper
.NewInstance("KingdomFk", this, TaxonNameBase
.class));
2575 mapping
.addMapper(MethodMapper
.NewInstance("RankFk", this, TaxonNameBase
.class));
2576 mapping
.addMapper(MethodMapper
.NewInstance("RankCache", this, TaxonNameBase
.class, PesiExportState
.class));
2577 mapping
.addMapper(DbConstantMapper
.NewInstance("TaxonStatusFk", Types
.INTEGER
, PesiTransformer
.T_STATUS_UNACCEPTED
));
2578 mapping
.addMapper(DbConstantMapper
.NewInstance("TaxonStatusCache", Types
.VARCHAR
, state
.getTransformer().getTaxonStatusCacheByKey( PesiTransformer
.T_STATUS_UNACCEPTED
)));
2579 mapping
.addMapper(DbStringMapper
.NewInstance("AuthorshipCache", "AuthorString").setBlankToNull(true));
2580 mapping
.addMapper(MethodMapper
.NewInstance("WebShowName", this, TaxonNameBase
.class));
2583 mapping
.addMapper(MethodMapper
.NewInstance("DisplayName", this, TaxonNameBase
.class));
2585 mapping
.addMapper(DbLastActionMapper
.NewInstance("LastActionDate", false));
2586 mapping
.addMapper(DbLastActionMapper
.NewInstance("LastAction", true));
2588 addNameMappers(mapping
);
2589 //TODO add author mapper, TypeNameFk
2594 private void addNameMappers(PesiExportMapping mapping
) {
2595 mapping
.addMapper(DbStringMapper
.NewInstance("GenusOrUninomial", "GenusOrUninomial"));
2596 mapping
.addMapper(DbStringMapper
.NewInstance("InfraGenericEpithet", "InfraGenericEpithet"));
2597 mapping
.addMapper(DbStringMapper
.NewInstance("SpecificEpithet", "SpecificEpithet"));
2598 mapping
.addMapper(DbStringMapper
.NewInstance("InfraSpecificEpithet", "InfraSpecificEpithet"));
2600 // mapping.addMapper(DbStringMapper.NewInstance("NameCache", "WebSearchName")); //does not work as we need other cache strategy
2601 mapping
.addMapper(MethodMapper
.NewInstance("WebSearchName", this, TaxonNameBase
.class));
2603 // mapping.addMapper(DbStringMapper.NewInstance("TitleCache", "FullName")); //does not work as we need other cache strategy
2604 mapping
.addMapper(MethodMapper
.NewInstance("FullName", this, TaxonNameBase
.class));
2607 mapping
.addMapper(MethodMapper
.NewInstance("NomRefString", this, TaxonNameBase
.class));
2609 mapping
.addMapper(MethodMapper
.NewInstance("NameStatusFk", this, TaxonNameBase
.class));
2610 mapping
.addMapper(MethodMapper
.NewInstance("NameStatusCache", this, TaxonNameBase
.class, PesiExportState
.class));
2611 mapping
.addMapper(MethodMapper
.NewInstance("TypeFullnameCache", this, TaxonNameBase
.class));
2615 mapping
.addMapper(MethodMapper
.NewInstance("QualityStatusFk", this, TaxonNameBase
.class));
2616 mapping
.addMapper(MethodMapper
.NewInstance("QualityStatusCache", this, TaxonNameBase
.class, PesiExportState
.class));
2618 mapping
.addMapper(MethodMapper
.NewInstance("IdInSource", this, IdentifiableEntity
.class));
2619 mapping
.addMapper(MethodMapper
.NewInstance("OriginalDB", this, IdentifiableEntity
.class) );
2621 //mapping.addMapper(ExpertsAndLastActionMapper.NewInstance());
2625 private PesiExportMapping
getSynRelMapping() {
2626 PesiExportMapping mapping
= new PesiExportMapping(dbTableNameSynRel
);
2628 mapping
.addMapper(MethodMapper
.NewInstance("TaxonFk1", this.getClass(), "getTaxonFk1", RelationshipBase
.class, PesiExportState
.class));
2629 mapping
.addMapper(MethodMapper
.NewInstance("TaxonFk2", this.getClass(), "getTaxonFk2", RelationshipBase
.class, PesiExportState
.class));
2630 mapping
.addMapper(MethodMapper
.NewInstance("RelTaxonQualifierFk", this, RelationshipBase
.class));
2631 mapping
.addMapper(MethodMapper
.NewInstance("RelQualifierCache", this, RelationshipBase
.class, PesiExportState
.class));
2632 mapping
.addMapper(MethodMapper
.NewInstance("Notes", this, RelationshipBase
.class));
2637 private PesiExportMapping
getAdditionalSourceMapping(PesiExportState state
) throws UndefinedTransformerMethodException
{
2638 PesiExportMapping mapping
= new PesiExportMapping(dbTableAdditionalSourceRel
);
2640 mapping
.addMapper(IdMapper
.NewInstance("TaxonFk"));
2641 mapping
.addMapper(ObjectChangeMapper
.NewInstance(TaxonBase
.class, TaxonNameBase
.class, "Name"));
2643 mapping
.addMapper(DbObjectMapper
.NewInstance("NomenclaturalReference", "SourceFk"));
2644 mapping
.addMapper(DbObjectMapper
.NewInstance("NomenclaturalReference", "SourceNameCache", IS_CACHE
));
2646 //we have only nomenclatural references here
2647 mapping
.addMapper(DbConstantMapper
.NewInstance("SourceUseFk", Types
.INTEGER
, PesiTransformer
.NOMENCLATURAL_REFERENCE
));
2648 mapping
.addMapper(DbConstantMapper
.NewInstance("SourceUseCache", Types
.VARCHAR
, state
.getTransformer().getSourceUseCacheByKey( PesiTransformer
.NOMENCLATURAL_REFERENCE
)));
2650 mapping
.addMapper(DbStringMapper
.NewInstance("NomenclaturalMicroReference", "SourceDetail"));