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
.util
.ArrayList
;
17 import java
.util
.HashMap
;
18 import java
.util
.List
;
20 import java
.util
.UUID
;
22 import org
.apache
.commons
.lang
.StringUtils
;
23 import org
.apache
.log4j
.Logger
;
24 import org
.joda
.time
.DateTime
;
25 import org
.joda
.time
.format
.DateTimeFormat
;
26 import org
.joda
.time
.format
.DateTimeFormatter
;
27 import org
.springframework
.stereotype
.Component
;
28 import org
.springframework
.transaction
.TransactionStatus
;
30 import eu
.etaxonomy
.cdm
.common
.CdmUtils
;
31 import eu
.etaxonomy
.cdm
.io
.common
.Source
;
32 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbExtensionMapper
;
33 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbObjectMapper
;
34 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbStringMapper
;
35 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.IdMapper
;
36 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.MethodMapper
;
37 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.ObjectChangeMapper
;
38 import eu
.etaxonomy
.cdm
.io
.pesi
.erms
.ErmsTransformer
;
39 import eu
.etaxonomy
.cdm
.model
.common
.Annotation
;
40 import eu
.etaxonomy
.cdm
.model
.common
.AnnotationType
;
41 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
42 import eu
.etaxonomy
.cdm
.model
.common
.Extension
;
43 import eu
.etaxonomy
.cdm
.model
.common
.ExtensionType
;
44 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableEntity
;
45 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableSource
;
46 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
47 import eu
.etaxonomy
.cdm
.model
.name
.BotanicalName
;
48 import eu
.etaxonomy
.cdm
.model
.name
.NameTypeDesignation
;
49 import eu
.etaxonomy
.cdm
.model
.name
.NameTypeDesignationStatus
;
50 import eu
.etaxonomy
.cdm
.model
.name
.NomenclaturalCode
;
51 import eu
.etaxonomy
.cdm
.model
.name
.NomenclaturalStatus
;
52 import eu
.etaxonomy
.cdm
.model
.name
.NonViralName
;
53 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
54 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameBase
;
55 import eu
.etaxonomy
.cdm
.model
.name
.ZoologicalName
;
56 import eu
.etaxonomy
.cdm
.model
.reference
.Reference
;
57 import eu
.etaxonomy
.cdm
.model
.taxon
.Classification
;
58 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
59 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
60 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
61 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
62 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationship
;
63 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationshipType
;
64 import eu
.etaxonomy
.cdm
.persistence
.query
.MatchMode
;
65 import eu
.etaxonomy
.cdm
.strategy
.cache
.HTMLTagRules
;
66 import eu
.etaxonomy
.cdm
.strategy
.cache
.TagEnum
;
67 import eu
.etaxonomy
.cdm
.strategy
.cache
.TaggedText
;
68 import eu
.etaxonomy
.cdm
.strategy
.cache
.name
.BotanicNameDefaultCacheStrategy
;
69 import eu
.etaxonomy
.cdm
.strategy
.cache
.name
.INonViralNameCacheStrategy
;
70 import eu
.etaxonomy
.cdm
.strategy
.cache
.name
.NonViralNameDefaultCacheStrategy
;
71 import eu
.etaxonomy
.cdm
.strategy
.cache
.name
.ZooNameDefaultCacheStrategy
;
72 import eu
.etaxonomy
.cdm
.strategy
.cache
.name
.ZooNameNoMarkerCacheStrategy
;
75 * The export class for {@link eu.etaxonomy.cdm.model.name.TaxonNameBase TaxonNames}.<p>
76 * Inserts into DataWarehouse database table <code>Taxon</code>.
77 * It is divided into four phases:<p><ul>
78 * <li>Phase 1: Export of all {@link eu.etaxonomy.cdm.model.name.TaxonNameBase TaxonNames} except some data exported in the following phases.
79 * <li>Phase 2: Export of additional data: ParenTaxonFk and TreeIndex.
80 * <li>Phase 3: Export of additional data: Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk.
81 * <li>Phase 4: Export of Inferred Synonyms.</ul>
87 public class PesiTaxonExport
extends PesiExportBase
{
88 private static final Logger logger
= Logger
.getLogger(PesiTaxonExport
.class);
89 private static final Class
<?
extends CdmBase
> standardMethodParameter
= TaxonBase
.class;
91 private static int modCount
= 1000;
92 private static final String dbTableName
= "Taxon";
93 private static final String pluralString
= "Taxa";
94 private static final String parentPluralString
= "Taxa";
95 private PreparedStatement parentTaxonFk_TreeIndex_KingdomFkStmt
;
96 private PreparedStatement rankTypeExpertsUpdateStmt
;
97 private PreparedStatement rankUpdateStmt
;
98 private NomenclaturalCode nomenclaturalCode
;
99 private Integer kingdomFk
;
100 private HashMap
<Rank
, Rank
> rank2endRankMap
= new HashMap
<Rank
, Rank
>();
101 private List
<Rank
> rankList
= new ArrayList
<Rank
>();
102 private static final UUID uuidTreeIndex
= UUID
.fromString("28f4e205-1d02-4d3a-8288-775ea8413009");
103 private AnnotationType treeIndexAnnotationType
;
104 private static ExtensionType lastActionExtensionType
;
105 private static ExtensionType lastActionDateExtensionType
;
106 private static ExtensionType expertNameExtensionType
;
107 private static ExtensionType speciesExpertNameExtensionType
;
108 private static ExtensionType cacheCitationExtensionType
;
109 private static ExtensionType expertUserIdExtensionType
;
110 private static ExtensionType speciesExpertUserIdExtensionType
;
111 private static NonViralNameDefaultCacheStrategy zooNameStrategy
= ZooNameNoMarkerCacheStrategy
.NewInstance();
112 private static NonViralNameDefaultCacheStrategy botanicalNameStrategy
= BotanicNameDefaultCacheStrategy
.NewInstance();
116 * @return the treeIndexAnnotationType
118 protected AnnotationType
getTreeIndexAnnotationType() {
119 return treeIndexAnnotationType
;
123 * @param treeIndexAnnotationType the treeIndexAnnotationType to set
125 protected void setTreeIndexAnnotationType(AnnotationType treeIndexAnnotationType
) {
126 this.treeIndexAnnotationType
= treeIndexAnnotationType
;
137 public PesiTaxonExport() {
142 * @see eu.etaxonomy.cdm.io.common.DbExportBase#getStandardMethodParameter()
145 public Class
<?
extends CdmBase
> getStandardMethodParameter() {
146 return standardMethodParameter
;
150 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doCheck(eu.etaxonomy.cdm.io.common.IoStateBase)
153 protected boolean doCheck(PesiExportState state
) {
154 boolean result
= true;
160 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doInvoke(eu.etaxonomy.cdm.io.common.IoStateBase)
163 protected void doInvoke(PesiExportState state
) {
165 logger
.info("*** Started Making " + pluralString
+ " ...");
167 initPreparedStatements(state
);
169 // Stores whether this invoke was successful or not.
170 boolean success
= true;
172 // PESI: Clear the database table Taxon.
175 // Get specific mappings: (CDM) Taxon -> (PESI) Taxon
176 PesiExportMapping mapping
= getMapping();
178 // Initialize the db mapper
179 mapping
.initialize(state
);
181 // Find extensionTypes
182 lastActionExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.lastActionUuid
);
183 lastActionDateExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.lastActionDateUuid
);
184 expertNameExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.expertNameUuid
);
185 speciesExpertNameExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.speciesExpertNameUuid
);
186 cacheCitationExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.cacheCitationUuid
);
187 expertUserIdExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.expertUserIdUuid
);
188 speciesExpertUserIdExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.speciesExpertUserIdUuid
);
193 success
&= doPhase01(state
, mapping
);
195 //"PHASE 1b: Handle names without taxa ...
196 success
&= doNames(state
);
199 // 2nd Round: Add ParentTaxonFk, TreeIndex to each Taxon
200 success
&= doPhase02(state
);
202 //PHASE 3: Add Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk...
203 success
&= doPhase03(state
);
205 //"PHASE 4: Creating Inferred Synonyms...
206 success
&= doPhase04(state
, mapping
);
209 logger
.info("*** Finished Making " + pluralString
+ " ..." + getSuccessString(success
));
212 state
.setUnsuccessfull();
215 } catch (SQLException e
) {
217 logger
.error(e
.getMessage());
218 state
.setUnsuccessfull();
223 private void initPreparedStatements(PesiExportState state
) throws SQLException
{
224 initTreeIndexStatement(state
);
225 initRankExpertsUpdateStmt(state
);
226 initRankUpdateStatement(state
);
229 // Prepare TreeIndex-And-KingdomFk-Statement
230 private void initTreeIndexStatement(PesiExportState state
) throws SQLException
{
231 Connection connection
= state
.getConfig().getDestination().getConnection();
232 String parentTaxonFk_TreeIndex_KingdomFkSql
= "UPDATE Taxon SET ParentTaxonFk = ?, TreeIndex = ? WHERE TaxonId = ?";
233 parentTaxonFk_TreeIndex_KingdomFkStmt
= connection
.prepareStatement(parentTaxonFk_TreeIndex_KingdomFkSql
);
236 private void initRankUpdateStatement(PesiExportState state
) throws SQLException
{
237 Connection connection
= state
.getConfig().getDestination().getConnection();
238 String rankSql
= "UPDATE Taxon SET RankFk = ?, RankCache = ?, KingdomFk = ? WHERE TaxonId = ?";
239 rankUpdateStmt
= connection
.prepareStatement(rankSql
);
242 private void initRankExpertsUpdateStmt(PesiExportState state
) throws SQLException
{
243 // String sql_old = "UPDATE Taxon SET RankFk = ?, RankCache = ?, TypeNameFk = ?, KingdomFk = ?, " +
244 // "ExpertFk = ?, SpeciesExpertFk = ? WHERE TaxonId = ?";
245 //TODO handle experts GUIDs
246 Connection connection
= state
.getConfig().getDestination().getConnection();
248 String sql
= "UPDATE Taxon SET RankFk = ?, RankCache = ?, TypeNameFk = ?, KingdomFk = ? " +
249 " WHERE TaxonId = ?";
250 rankTypeExpertsUpdateStmt
= connection
.prepareStatement(sql
);
253 private boolean doPhase01(PesiExportState state
, PesiExportMapping mapping
) throws SQLException
{
256 List
<TaxonBase
> list
;
257 boolean success
= true;
258 // Get the limit for objects to save within a single transaction.
259 int limit
= state
.getConfig().getLimitSave();
262 logger
.info("PHASE 1: Export Taxa...");
264 TransactionStatus txStatus
= startTransaction(true);
265 logger
.info("Started new transaction. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
268 int partitionCount
= 0;
269 while ((list
= getNextTaxonPartition(null, limit
, partitionCount
++, null)).size() > 0 ) {
271 logger
.info("Fetched " + list
.size() + " " + pluralString
+ ". Exporting...");
272 for (TaxonBase
<?
> taxon
: list
) {
273 doCount(count
++, modCount
, pluralString
);
274 TaxonNameBase
<?
,?
> taxonName
= taxon
.getName();
275 NonViralName
<?
> nvn
= CdmBase
.deproxy(taxonName
, NonViralName
.class);
277 if (! nvn
.isProtectedTitleCache()){
278 nvn
.setTitleCache(null, false);
280 if (! nvn
.isProtectedNameCache()){
281 nvn
.setNameCache(null, false);
283 if (! nvn
.isProtectedFullTitleCache()){
284 nvn
.setFullTitleCache(null, false);
286 if (! nvn
.isProtectedAuthorshipCache()){
287 nvn
.setAuthorshipCache(null, false);
290 success
&= mapping
.invoke(taxon
);
292 validatePhaseOne(taxon
, nvn
);
296 // Commit transaction
297 commitTransaction(txStatus
);
298 logger
.debug("Committed transaction.");
299 logger
.info("Exported " + (count
- pastCount
) + " " + pluralString
+ ". Total: " + count
);
303 txStatus
= startTransaction(true);
304 logger
.info("Started new transaction. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
306 if (list
.size() == 0) {
307 logger
.info("No " + pluralString
+ " left to fetch.");
309 // Commit transaction
310 commitTransaction(txStatus
);
311 logger
.debug("Committed transaction.");
316 private void validatePhaseOne(TaxonBase
<?
> taxon
, NonViralName taxonName
) {
317 // Check whether some rules are violated
318 nomenclaturalCode
= taxonName
.getNomenclaturalCode();
319 String genusOrUninomial
= taxonName
.getGenusOrUninomial();
320 String specificEpithet
= taxonName
.getSpecificEpithet();
321 String infraSpecificEpithet
= taxonName
.getInfraSpecificEpithet();
322 String infraGenericEpithet
= taxonName
.getInfraGenericEpithet();
323 Integer rank
= getRankFk(taxonName
, nomenclaturalCode
);
326 logger
.error("Rank was not determined: " + taxon
.getUuid() + " (" + taxon
.getTitleCache() + ")");
329 // Check whether infraGenericEpithet is set correctly
330 // 1. Childs of an accepted taxon of rank subgenus that are accepted taxa of rank species have to have an infraGenericEpithet
331 // 2. Grandchilds of an accepted taxon of rank subgenus that are accepted taxa of rank subspecies have to have an infraGenericEpithet
333 int ancestorLevel
= 0;
334 if (taxonName
.getRank().equals(Rank
.SUBSPECIES())) {
335 // The accepted taxon two rank levels above should be of rank subgenus
338 if (taxonName
.getRank().equals(Rank
.SPECIES())) {
339 // The accepted taxon one rank level above should be of rank subgenus
342 if (ancestorLevel
> 0) {
343 if (ancestorOfSpecificRank(taxon
, ancestorLevel
, Rank
.SUBGENUS())) {
344 // The child (species or subspecies) of this parent (subgenus) has to have an infraGenericEpithet
345 if (infraGenericEpithet
== null) {
346 logger
.warn("InfraGenericEpithet does not exist even though it should for: " + taxon
.getUuid() + " (" + taxon
.getTitleCache() + ")");
347 // maybe the taxon could be named here
352 if (infraGenericEpithet
== null && rank
.intValue() == 190) {
353 logger
.warn("InfraGenericEpithet was not determined although it should exist for rank 190: " + taxon
.getUuid() + " (" + taxon
.getTitleCache() + ")");
355 if (specificEpithet
!= null && rank
.intValue() < 216) {
356 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() + ")");
358 if (infraSpecificEpithet
!= null && rank
.intValue() < 225) {
359 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() + ")";
360 if (StringUtils
.isNotBlank(infraSpecificEpithet
)){
361 logger
.warn(message
);
363 logger
.warn(message
);
367 if (infraSpecificEpithet
!= null && specificEpithet
== null) {
368 logger
.warn("An infraSpecificEpithet was determined, but a specificEpithet was not determined: " + taxon
.getUuid() + " (" + taxon
.getTitleCache() + ")");
370 if (genusOrUninomial
== null) {
371 logger
.warn("GenusOrUninomial was not determined: " + taxon
.getUuid() + " (" + taxon
.getTitleCache() + ")");
375 // 2nd Round: Add ParentTaxonFk, TreeIndex to each Taxon
376 private boolean doPhase02(PesiExportState state
) {
377 boolean success
= true;
378 if (! state
.getConfig().isDoTreeIndex()){
379 logger
.info ("Ignore PHASE 2: ParentTaxonFk and TreeIndex");
383 List
<Classification
> classificationList
= null;
384 logger
.info("PHASE 2: Add ParenTaxonFk and TreeIndex...");
386 // Specify starting ranks for tree traversing
387 rankList
.add(Rank
.KINGDOM());
388 rankList
.add(Rank
.GENUS());
390 // Specify where to stop traversing (value) when starting at a specific Rank (key)
391 rank2endRankMap
.put(Rank
.GENUS(), null); // Since NULL does not match an existing Rank, traverse all the way down to the leaves
392 rank2endRankMap
.put(Rank
.KINGDOM(), Rank
.GENUS()); // excludes rank genus
394 StringBuffer treeIndex
= new StringBuffer();
396 // Retrieve list of classifications
397 TransactionStatus txStatus
= startTransaction(true);
398 logger
.info("Started transaction. Fetching all classifications...");
399 classificationList
= getClassificationService().listClassifications(null, 0, null, null);
400 commitTransaction(txStatus
);
401 logger
.debug("Committed transaction.");
403 logger
.info("Fetched " + classificationList
.size() + " classification(s).");
405 setTreeIndexAnnotationType(getAnnotationType(uuidTreeIndex
, "TreeIndex", "", "TI"));
407 for (Classification classification
: classificationList
) {
408 for (Rank rank
: rankList
) {
410 txStatus
= startTransaction(true);
411 logger
.info("Started transaction to fetch all rootNodes specific to Rank " + rank
.getLabel() + " ...");
413 List
<TaxonNode
> rankSpecificRootNodes
= getClassificationService().loadRankSpecificRootNodes(classification
, rank
, null);
414 logger
.info("Fetched " + rankSpecificRootNodes
.size() + " RootNodes for Rank " + rank
.getLabel());
416 commitTransaction(txStatus
);
417 logger
.debug("Committed transaction.");
419 for (TaxonNode rootNode
: rankSpecificRootNodes
) {
420 txStatus
= startTransaction(false);
421 Rank endRank
= rank2endRankMap
.get(rank
);
422 if (endRank
!= null) {
423 logger
.debug("Started transaction to traverse childNodes of rootNode (" + rootNode
.getUuid() + ") till Rank " + endRank
.getLabel() + " ...");
425 logger
.debug("Started transaction to traverse childNodes of rootNode (" + rootNode
.getUuid() + ") till leaves are reached ...");
428 TaxonNode newNode
= getTaxonNodeService().load(rootNode
.getUuid());
430 if (isPesiTaxon(newNode
.getTaxon())){
431 TaxonNode parentNode
= newNode
.getParent();
432 if (rank
.equals(Rank
.KINGDOM())) {
433 treeIndex
= new StringBuffer();
434 treeIndex
.append("#");
436 // Get treeIndex from parentNode
437 if (parentNode
!= null) {
438 boolean annotationFound
= false;
439 Set
<Annotation
> annotations
= parentNode
.getAnnotations();
440 for (Annotation annotation
: annotations
) {
441 AnnotationType annotationType
= annotation
.getAnnotationType();
442 if (annotationType
!= null && annotationType
.equals(getTreeIndexAnnotationType())) {
443 treeIndex
= new StringBuffer(CdmUtils
.Nz(annotation
.getText()));
444 annotationFound
= true;
445 // logger.error("treeIndex: " + treeIndex);
449 if (!annotationFound
) {
450 // This should not happen because it means that the treeIndex was not set correctly as an annotation to parentNode
451 logger
.error("TreeIndex could not be read from annotation of TaxonNode: " + parentNode
.getUuid() + ", Taxon: " + parentNode
.getTaxon().getUuid());
452 treeIndex
= new StringBuffer();
453 treeIndex
.append("#");
456 // TreeIndex could not be determined, but it's unclear how to proceed to generate a correct treeIndex if the parentNode is NULL
457 logger
.error("ParentNode for RootNode is NULL. TreeIndex could not be determined: " + newNode
.getUuid());
458 treeIndex
= new StringBuffer(); // This just prevents growing of the treeIndex in a wrong manner
459 treeIndex
.append("#");
462 nomenclaturalCode
= newNode
.getTaxon().getName().getNomenclaturalCode();
463 kingdomFk
= PesiTransformer
.nomenClaturalCode2Kingdom(nomenclaturalCode
);
464 traverseTree(newNode
, parentNode
, treeIndex
, endRank
, state
);
466 logger
.debug("Taxon is not a PESI taxon: " + newNode
.getTaxon().getUuid());
471 commitTransaction(txStatus
);
472 logger
.debug("Committed transaction.");
480 //PHASE 3: Add Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk...
481 private boolean doPhase03(PesiExportState state
) {
484 boolean success
= true;
485 if (! state
.getConfig().isDoTreeIndex()){
486 logger
.info ("Ignore PHASE 3: Add Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk...");
489 // Get the limit for objects to save within a single transaction.
490 int limit
= state
.getConfig().getLimitSave();
492 List
<TaxonBase
> list
;
493 logger
.info("PHASE 3: Add Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk...");
494 // Be sure to add rank information, KingdomFk, TypeNameFk, expertFk and speciesExpertFk to every taxonName
497 TransactionStatus txStatus
= startTransaction(true);
498 logger
.info("Started new transaction. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
499 int partitionCount
= 0;
500 while ((list
= getNextTaxonPartition(TaxonBase
.class, limit
, partitionCount
++, null)).size() > 0) {
502 logger
.info("Fetched " + list
.size() + " " + pluralString
+ ". Exporting...");
503 for (TaxonBase
<?
> taxon
: list
) {
504 TaxonNameBase
<?
,?
> taxonName
= taxon
.getName();
505 // Determine expertFk
506 Integer expertFk
= makeExpertFk(state
, taxonName
);
508 // Determine speciesExpertFk
509 Integer speciesExpertFk
= makeSpeciesExpertFk(state
, taxonName
);
511 doCount(count
++, modCount
, pluralString
);
512 Integer typeNameFk
= getTypeNameFk(taxonName
, state
);
514 //TODO why are expertFks needed? (Andreas M.)
515 // if (expertFk != null || speciesExpertFk != null) {
516 invokeRankDataAndTypeNameFkAndKingdomFk(taxonName
, nomenclaturalCode
, state
.getDbId(taxon
),
517 typeNameFk
, kingdomFk
, expertFk
, speciesExpertFk
);
521 // Commit transaction
522 commitTransaction(txStatus
);
523 logger
.debug("Committed transaction.");
524 logger
.info("Exported " + (count
- pastCount
) + " " + pluralString
+ ". Total: " + count
);
528 txStatus
= startTransaction(true);
529 logger
.info("Started new transaction. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
531 if (list
.size() == 0) {
532 logger
.info("No " + pluralString
+ " left to fetch.");
534 // Commit transaction
535 commitTransaction(txStatus
);
536 logger
.debug("Committed transaction.");
540 private Integer
makeSpeciesExpertFk(PesiExportState state
, TaxonNameBase
<?
, ?
> taxonName
) {
541 List
<Reference
> referenceList
;
542 Integer speciesExpertFk
= null;
543 String speciesExpertUserId
= getSpeciesExpertUserId(taxonName
);
544 if (speciesExpertUserId
!= null) {
546 // The speciesExpertUserId was stored in the field 'title' of the corresponding Reference during FaEu import
547 referenceList
= getReferenceService().listByReferenceTitle(null, speciesExpertUserId
, MatchMode
.EXACT
, null, null, null, null, null);
548 if (referenceList
.size() == 1) {
549 speciesExpertFk
= getSpeciesExpertFk(referenceList
.iterator().next(), state
);
550 } else if (referenceList
.size() > 1) {
551 logger
.error("Found more than one match using listByTitle() searching for a Reference with this speciesExpertUserId as title: " + speciesExpertUserId
);
552 } else if (referenceList
.size() == 0) {
553 logger
.error("Found no match using listByReferenceTitle() searching for a Reference with this speciesExpertUserId as title: " + speciesExpertUserId
);
556 logger
.debug("SpeciesExpertName is NULL for this TaxonName: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
558 return speciesExpertFk
;
561 private Integer
makeExpertFk(PesiExportState state
,
562 TaxonNameBase
<?
, ?
> taxonName
) {
563 List
<Reference
> referenceList
;
564 Integer expertFk
= null;
565 String expertUserId
= getExpertUserId(taxonName
);
566 if (expertUserId
!= null) {
568 // The expertUserId was stored in the field 'title' of the corresponding Reference during FaEu import
569 referenceList
= getReferenceService().listByReferenceTitle(null, expertUserId
, MatchMode
.EXACT
, null, null, null, null, null);
570 if (referenceList
.size() == 1) {
571 expertFk
= getExpertFk(referenceList
.iterator().next(), state
);
572 } else if (referenceList
.size() > 1) {
573 logger
.error("Found more than one match using listByReferenceTitle() searching for a Reference with this expertUserId as title: " + expertUserId
);
574 } else if (referenceList
.size() == 0) {
575 logger
.error("Found no match using listByReferenceTitle() searching for a Reference with this expertUserId as title: " + expertUserId
);
578 logger
.debug("ExpertName is NULL for this TaxonName: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
583 // "PHASE 4: Creating Inferred Synonyms..."
584 private boolean doPhase04(PesiExportState state
, PesiExportMapping mapping
) throws SQLException
{
587 boolean success
= true;
588 // Get the limit for objects to save within a single transaction.
589 if (! state
.getConfig().isDoTreeIndex()){
590 logger
.info ("Ignore PHASE 4: Creating Inferred Synonyms...");
594 int limit
= state
.getConfig().getLimitSave();
595 // Create inferred synonyms for accepted taxa
596 logger
.info("PHASE 4: Creating Inferred Synonyms...");
598 // Determine the count of elements in datawarehouse database table Taxon
599 Integer currentTaxonId
= determineTaxonCount(state
);
604 int pageSize
= limit
;
606 String inferredSynonymPluralString
= "Inferred Synonyms";
609 Classification classification
= null;
610 Taxon acceptedTaxon
= null;
611 TransactionStatus txStatus
= startTransaction(true);
612 logger
.info("Started new transaction. Fetching some " + parentPluralString
+ " first (max: " + limit
+ ") ...");
613 List
<TaxonBase
> taxonList
= null;
614 List
<Synonym
> inferredSynonyms
= null;
615 while ((taxonList
= getTaxonService().listTaxaByName(Taxon
.class, "*", "*", "*", "*", null, pageSize
, pageNumber
)).size() > 0) {
616 HashMap
<Integer
, TaxonNameBase
<?
,?
>> inferredSynonymsDataToBeSaved
= new HashMap
<Integer
, TaxonNameBase
<?
,?
>>();
618 logger
.info("Fetched " + taxonList
.size() + " " + parentPluralString
+ ". Exporting...");
619 for (TaxonBase
<?
> taxonBase
: taxonList
) {
621 if (taxonBase
.isInstanceOf(Taxon
.class)) { // this should always be the case since we should have fetched accepted taxon only, but you never know...
622 acceptedTaxon
= CdmBase
.deproxy(taxonBase
, Taxon
.class);
623 TaxonNameBase
<?
,?
> taxonName
= acceptedTaxon
.getName();
625 if (taxonName
.isInstanceOf(ZoologicalName
.class)) {
626 nomenclaturalCode
= taxonName
.getNomenclaturalCode();
627 kingdomFk
= PesiTransformer
.nomenClaturalCode2Kingdom(nomenclaturalCode
);
629 Set
<TaxonNode
> taxonNodes
= acceptedTaxon
.getTaxonNodes();
630 TaxonNode singleNode
= null;
631 if (taxonNodes
.size() > 0) {
632 // Determine the classification of the current TaxonNode
633 singleNode
= taxonNodes
.iterator().next();
634 if (singleNode
!= null) {
635 classification
= singleNode
.getClassification();
637 logger
.error("A TaxonNode belonging to this accepted Taxon is NULL: " + acceptedTaxon
.getUuid() + " (" + acceptedTaxon
.getTitleCache() +")");
640 // Classification could not be determined directly from this TaxonNode
641 // The stored classification from another TaxonNode is used. It's a simple, but not a failsafe fallback solution.
642 if (classification
== null) {
643 logger
.error("Classification could not be determined directly from this TaxonNode: " + singleNode
.getUuid() + "). " +
644 "This classification stored from another TaxonNode is used: " + classification
.getTitleCache());
648 if (classification
!= null) {
649 inferredSynonyms
= getTaxonService().createAllInferredSynonyms(acceptedTaxon
, classification
);
651 // inferredSynonyms = getTaxonService().createInferredSynonyms(classification, acceptedTaxon, SynonymRelationshipType.INFERRED_GENUS_OF());
652 if (inferredSynonyms
!= null) {
653 for (Synonym synonym
: inferredSynonyms
) {
654 // TaxonNameBase<?,?> synonymName = synonym.getName();
656 // Both Synonym and its TaxonName have no valid Id yet
657 synonym
.setId(currentTaxonId
++);
659 doCount(count
++, modCount
, inferredSynonymPluralString
);
660 success
&= mapping
.invoke(synonym
);
662 // Add Rank Data and KingdomFk to hashmap for later saving
663 inferredSynonymsDataToBeSaved
.put(synonym
.getId(), synonym
.getName());
667 logger
.error("Classification is NULL. Inferred Synonyms could not be created for this Taxon: " + acceptedTaxon
.getUuid() + " (" + acceptedTaxon
.getTitleCache() + ")");
670 // logger.error("TaxonName is not a ZoologicalName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
673 logger
.error("This TaxonBase is not a Taxon even though it should be: " + taxonBase
.getUuid() + " (" + taxonBase
.getTitleCache() + ")");
677 // Commit transaction
678 commitTransaction(txStatus
);
679 logger
.debug("Committed transaction.");
680 logger
.info("Exported " + (count
- pastCount
) + " " + inferredSynonymPluralString
+ ". Total: " + count
);
683 // Save Rank Data and KingdomFk for inferred synonyms
684 for (Integer taxonFk
: inferredSynonymsDataToBeSaved
.keySet()) {
685 invokeRankDataAndKingdomFk(inferredSynonymsDataToBeSaved
.get(taxonFk
), nomenclaturalCode
, taxonFk
, kingdomFk
);
689 txStatus
= startTransaction(true);
690 logger
.info("Started new transaction. Fetching some " + parentPluralString
+ " first (max: " + limit
+ ") ...");
692 // Increment pageNumber
695 if (taxonList
.size() == 0) {
696 logger
.info("No " + parentPluralString
+ " left to fetch.");
698 // Commit transaction
699 commitTransaction(txStatus
);
700 logger
.debug("Committed transaction.");
706 * Handles names that do not appear in taxa
711 private boolean doNames(PesiExportState state
) throws SQLException
{
713 boolean success
= true;
714 if (! state
.getConfig().isDoPureNames()){
715 logger
.info ("Ignore PHASE 1b: PureNames");
720 PesiExportMapping mapping
= getNameMapping();
721 mapping
.initialize(state
);
724 List
<NonViralName
<?
>> list
;
726 // Get the limit for objects to save within a single transaction.
727 int limit
= state
.getConfig().getLimitSave();
730 logger
.info("PHASE 5: Export Pure Names ...");
732 TransactionStatus txStatus
= startTransaction(true);
733 logger
.info("Started new transaction. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
736 int partitionCount
= 0;
737 while ((list
= getNextPureNamePartition(null, limit
, partitionCount
++)) != null ) {
739 logger
.info("Fetched " + list
.size() + " names without taxa. Exporting...");
740 for (NonViralName
<?
> taxonName
: list
) {
741 doCount(count
++, modCount
, pluralString
);
742 success
&= mapping
.invoke(taxonName
);
745 // Commit transaction
746 commitTransaction(txStatus
);
747 logger
.debug("Committed transaction.");
748 logger
.info("Exported " + (count
- pastCount
) + " " + pluralString
+ ". Total: " + count
);
752 txStatus
= startTransaction(true);
753 logger
.info("Started new transaction. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
756 logger
.info("No " + pluralString
+ " left to fetch.");
758 // Commit transaction
759 commitTransaction(txStatus
);
760 logger
.debug("Committed transaction.");
761 } catch (Exception e
) {
762 logger
.error("Error occurred in pure name export");
770 * Determines the current number of entries in the DataWarehouse database table <code>Taxon</code>.
771 * @param state The {@link PesiExportState PesiExportState}.
774 private Integer
determineTaxonCount(PesiExportState state
) {
775 Integer result
= null;
776 PesiExportConfigurator pesiConfig
= (PesiExportConfigurator
) state
.getConfig();
779 Source destination
= pesiConfig
.getDestination();
780 sql
= "SELECT max(taxonId) FROM Taxon";
781 destination
.setQuery(sql
);
782 ResultSet resultSet
= destination
.getResultSet();
785 result
= resultSet
.getInt(1);
786 } catch (SQLException e
) {
787 logger
.error("TaxonCount could not be determined: " + e
.getMessage());
794 * Returns the userId of the expert associated with the given TaxonName.
795 * @param taxonName A {@link TaxonNameBase TaxonName}.
796 * @return The userId.
798 private String
getExpertUserId(TaxonNameBase
<?
,?
> taxonName
) {
799 String result
= null;
801 Set
<Extension
> extensions
= taxonName
.getExtensions();
802 for (Extension extension
: extensions
) {
803 if (extension
.getType().equals(expertUserIdExtensionType
)) {
804 result
= extension
.getValue();
807 } catch (Exception e
) {
814 * Returns the userId of the speciesExpert associated with the given TaxonName.
815 * @param taxonName A {@link TaxonNameBase TaxonName}.
816 * @return The userId.
818 private String
getSpeciesExpertUserId(TaxonNameBase
<?
,?
> taxonName
) {
819 String result
= null;
821 Set
<Extension
> extensions
= taxonName
.getExtensions();
822 for (Extension extension
: extensions
) {
823 if (extension
.getType().equals(speciesExpertUserIdExtensionType
)) {
824 result
= extension
.getValue();
827 } catch (Exception e
) {
834 * Checks whether a parent at specific level has a specific Rank.
835 * @param taxonName A {@link TaxonNameBase TaxonName}.
836 * @param level The ancestor level.
837 * @param ancestorRank The ancestor rank.
838 * @return Whether a parent at a specific level has a specific Rank.
840 private boolean ancestorOfSpecificRank(TaxonBase
<?
> taxonBase
, int level
, Rank ancestorRank
) {
841 boolean result
= false;
842 TaxonNode parentNode
= null;
843 if (taxonBase
.isInstanceOf(Taxon
.class)){
844 Taxon taxon
= CdmBase
.deproxy(taxonBase
, Taxon
.class);
845 // Get ancestor Taxon via TaxonNode
846 Set
<TaxonNode
> taxonNodes
= taxon
.getTaxonNodes();
847 if (taxonNodes
.size() == 1) {
848 TaxonNode taxonNode
= taxonNodes
.iterator().next();
849 if (taxonNode
!= null) {
850 for (int i
= 0; i
< level
; i
++) {
851 if (taxonNode
!= null) {
852 taxonNode
= taxonNode
.getParent();
855 parentNode
= taxonNode
;
857 } else if (taxonNodes
.size() > 1) {
858 logger
.error("This taxon has " + taxonNodes
.size() + " taxonNodes: " + taxon
.getUuid() + " (" + taxon
.getTitleCache() + ")");
862 if (parentNode
!= null) {
863 TaxonNode node
= CdmBase
.deproxy(parentNode
, TaxonNode
.class);
864 Taxon parentTaxon
= node
.getTaxon();
865 if (parentTaxon
!= null) {
866 TaxonNameBase
<?
,?
> parentTaxonName
= parentTaxon
.getName();
867 if (parentTaxonName
!= null && parentTaxonName
.getRank().equals(ancestorRank
)) {
871 logger
.error("This TaxonNode has no Taxon: " + node
.getUuid());
878 * Returns the AnnotationType for a given UUID.
879 * @param uuid The Annotation UUID.
880 * @param label The Annotation label.
881 * @param text The Annotation text.
882 * @param labelAbbrev The Annotation label abbreviation.
883 * @return The AnnotationType.
885 protected AnnotationType
getAnnotationType(UUID uuid
, String label
, String text
, String labelAbbrev
){
886 AnnotationType annotationType
= (AnnotationType
)getTermService().find(uuid
);
887 if (annotationType
== null) {
888 annotationType
= AnnotationType
.NewInstance(label
, text
, labelAbbrev
);
889 annotationType
.setUuid(uuid
);
890 // annotationType.setVocabulary(AnnotationType.EDITORIAL().getVocabulary());
891 getTermService().save(annotationType
);
893 return annotationType
;
897 * Traverses the classification recursively and stores determined values for every Taxon.
898 * @param childNode The {@link TaxonNode TaxonNode} to process.
899 * @param parentNode The parent {@link TaxonNode TaxonNode} of the childNode.
900 * @param treeIndex The TreeIndex at the current level.
901 * @param fetchLevel Rank to stop fetching at.
902 * @param state The {@link PesiExportState PesiExportState}.
904 private void traverseTree(TaxonNode childNode
, TaxonNode parentNode
, StringBuffer treeIndex
, Rank fetchLevel
, PesiExportState state
) {
905 // Traverse all branches from this childNode until specified fetchLevel is reached.
906 StringBuffer localTreeIndex
= new StringBuffer(treeIndex
);
907 Taxon childTaxon
= childNode
.getTaxon();
908 if (childTaxon
!= null) {
909 if (isPesiTaxon(childTaxon
)){
910 Integer taxonId
= state
.getDbId(childTaxon
);
911 TaxonNameBase
<?
,?
> childName
= childTaxon
.getName();
912 if (taxonId
!= null) {
913 Rank childRank
= childName
.getRank();
914 if (childRank
!= null) {
915 if (! childRank
.equals(fetchLevel
)) {
917 localTreeIndex
.append(taxonId
+ "#");
919 saveData(childNode
, parentNode
, localTreeIndex
, state
, taxonId
);
921 // Store treeIndex as annotation for further use
922 Annotation annotation
= Annotation
.NewInstance(localTreeIndex
.toString(), getTreeIndexAnnotationType(), Language
.DEFAULT());
923 childNode
.addAnnotation(annotation
);
925 for (TaxonNode newNode
: childNode
.getChildNodes()) {
926 if (newNode
.getTaxon() != null && isPesiTaxon(newNode
.getTaxon())){
927 traverseTree(newNode
, childNode
, localTreeIndex
, fetchLevel
, state
);
932 // logger.debug("Target Rank " + fetchLevel.getLabel() + " reached");
936 logger
.error("Rank is NULL. FetchLevel can not be checked: " + childName
.getUuid() + " (" + childName
.getTitleCache() + ")");
939 logger
.error("Taxon can not be found in state: " + childTaxon
.getUuid() + " (" + childTaxon
.getTitleCache() + ")");
942 if (logger
.isDebugEnabled()){
943 logger
.debug("Taxon is not a PESI taxon: " + childTaxon
.getUuid());
948 logger
.error("Taxon is NULL for TaxonNode: " + childNode
.getUuid());
953 * Stores values in database for every recursive round.
954 * @param childNode The {@link TaxonNode TaxonNode} to process.
955 * @param parentNode The parent {@link TaxonNode TaxonNode} of the childNode.
956 * @param treeIndex The TreeIndex at the current level.
957 * @param state The {@link PesiExportState PesiExportState}.
958 * @param currentTaxonFk The TaxonFk to store the values for.
960 private void saveData(TaxonNode childNode
, TaxonNode parentNode
, StringBuffer treeIndex
, PesiExportState state
, Integer currentTaxonFk
) {
961 // We are differentiating kingdoms by the nomenclatural code for now.
962 // This needs to be handled in a better way as soon as we know how to differentiate between more kingdoms.
963 Taxon childTaxon
= childNode
.getTaxon();
964 if (isPesiTaxon(childTaxon
)) {
965 TaxonBase
<?
> parentTaxon
= null;
966 if (parentNode
!= null) {
967 parentTaxon
= parentNode
.getTaxon();
971 invokeParentTaxonFkAndTreeIndex(state
.getDbId(parentTaxon
), currentTaxonFk
, treeIndex
);
977 * Inserts values into the Taxon database table.
978 * @param taxonName The {@link TaxonNameBase TaxonName}.
979 * @param state The {@link PesiExportState PesiExportState}.
980 * @param stmt The prepared statement.
981 * @return Whether save was successful or not.
983 protected boolean invokeParentTaxonFkAndTreeIndex(Integer parentTaxonFk
, Integer currentTaxonFk
, StringBuffer treeIndex
) {
985 if (parentTaxonFk
!= null) {
986 parentTaxonFk_TreeIndex_KingdomFkStmt
.setInt(1, parentTaxonFk
);
988 parentTaxonFk_TreeIndex_KingdomFkStmt
.setObject(1, null);
991 if (treeIndex
!= null) {
992 parentTaxonFk_TreeIndex_KingdomFkStmt
.setString(2, treeIndex
.toString());
994 parentTaxonFk_TreeIndex_KingdomFkStmt
.setObject(2, null);
997 if (currentTaxonFk
!= null) {
998 parentTaxonFk_TreeIndex_KingdomFkStmt
.setInt(3, currentTaxonFk
);
1000 parentTaxonFk_TreeIndex_KingdomFkStmt
.setObject(3, null);
1003 parentTaxonFk_TreeIndex_KingdomFkStmt
.executeUpdate();
1005 } catch (SQLException e
) {
1006 logger
.error("ParentTaxonFk (" + parentTaxonFk
==null?
"-":parentTaxonFk
+ ") and TreeIndex could not be inserted into database for taxon "+ (currentTaxonFk
== null?
"-" :currentTaxonFk
) + ": " + e
.getMessage());
1007 e
.printStackTrace();
1013 * Inserts Rank data and KingdomFk into the Taxon database table.
1014 * @param taxonName The {@link TaxonNameBase TaxonName}.
1015 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
1016 * @param taxonFk The TaxonFk to store the values for.
1017 * @param kindomFk The KingdomFk.
1018 * @return Whether save was successful or not.
1020 private boolean invokeRankDataAndKingdomFk(TaxonNameBase
<?
,?
> taxonName
, NomenclaturalCode nomenclaturalCode
, Integer taxonFk
, Integer kingdomFk
) {
1022 Integer rankFk
= getRankFk(taxonName
, nomenclaturalCode
);
1023 if (rankFk
!= null) {
1024 rankUpdateStmt
.setInt(1, rankFk
);
1026 rankUpdateStmt
.setObject(1, null);
1029 String rankCache
= getRankCache(taxonName
, nomenclaturalCode
);
1030 if (rankCache
!= null) {
1031 rankUpdateStmt
.setString(2, rankCache
);
1033 rankUpdateStmt
.setObject(2, null);
1036 if (kingdomFk
!= null) {
1037 rankUpdateStmt
.setInt(3, kingdomFk
);
1039 rankUpdateStmt
.setObject(3, null);
1042 if (taxonFk
!= null) {
1043 rankUpdateStmt
.setInt(4, taxonFk
);
1045 rankUpdateStmt
.setObject(4, null);
1048 rankUpdateStmt
.executeUpdate();
1050 } catch (SQLException e
) {
1051 logger
.error("Data (RankFk, RankCache, KingdomFk) could not be inserted into database: " + e
.getMessage());
1052 e
.printStackTrace();
1058 * Inserts Rank data, TypeNameFk, KingdomFk, expertFk and speciesExpertFk into the Taxon database table.
1059 * @param taxonName The {@link TaxonNameBase TaxonName}.
1060 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
1061 * @param taxonFk The TaxonFk to store the values for.
1062 * @param typeNameFk The TypeNameFk.
1063 * @param kindomFk The KingdomFk.
1064 * @param expertFk The ExpertFk.
1065 * @param speciesExpertFk The SpeciesExpertFk.
1066 * @return Whether save was successful or not.
1068 private boolean invokeRankDataAndTypeNameFkAndKingdomFk(TaxonNameBase
<?
,?
> taxonName
, NomenclaturalCode nomenclaturalCode
,
1069 Integer taxonFk
, Integer typeNameFk
, Integer kingdomFk
,
1070 Integer expertFk
, Integer speciesExpertFk
) {
1073 Integer rankFk
= getRankFk(taxonName
, nomenclaturalCode
);
1074 if (rankFk
!= null) {
1075 rankTypeExpertsUpdateStmt
.setInt(index
++, rankFk
);
1077 rankTypeExpertsUpdateStmt
.setObject(index
++, null);
1080 String rankCache
= getRankCache(taxonName
, nomenclaturalCode
);
1081 if (rankCache
!= null) {
1082 rankTypeExpertsUpdateStmt
.setString(index
++, rankCache
);
1084 rankTypeExpertsUpdateStmt
.setObject(index
++, null);
1087 if (typeNameFk
!= null) {
1088 rankTypeExpertsUpdateStmt
.setInt(index
++, typeNameFk
);
1090 rankTypeExpertsUpdateStmt
.setObject(index
++, null);
1093 if (kingdomFk
!= null) {
1094 rankTypeExpertsUpdateStmt
.setInt(index
++, kingdomFk
);
1096 rankTypeExpertsUpdateStmt
.setObject(index
++, null);
1099 // if (expertFk != null) {
1100 // rankTypeExpertsUpdateStmt.setInt(5, expertFk);
1102 // rankTypeExpertsUpdateStmt.setObject(5, null);
1105 // //TODO handle experts GUIDS
1106 // if (speciesExpertFk != null) {
1107 // rankTypeExpertsUpdateStmt.setInt(6, speciesExpertFk);
1109 // rankTypeExpertsUpdateStmt.setObject(6, null);
1112 if (taxonFk
!= null) {
1113 rankTypeExpertsUpdateStmt
.setInt(index
++, taxonFk
);
1115 rankTypeExpertsUpdateStmt
.setObject(index
++, null);
1118 rankTypeExpertsUpdateStmt
.executeUpdate();
1120 } catch (SQLException e
) {
1121 logger
.error("Data could not be inserted into database: " + e
.getMessage());
1122 e
.printStackTrace();
1128 * Deletes all entries of database tables related to <code>Taxon</code>.
1129 * @param state The {@link PesiExportState PesiExportState}.
1130 * @return Whether the delete operation was successful or not.
1132 protected boolean doDelete(PesiExportState state
) {
1133 PesiExportConfigurator pesiConfig
= (PesiExportConfigurator
) state
.getConfig();
1136 Source destination
= pesiConfig
.getDestination();
1139 sql
= "DELETE FROM " + dbTableName
;
1140 destination
.setQuery(sql
);
1141 destination
.update(sql
);
1146 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#isIgnore(eu.etaxonomy.cdm.io.common.IoStateBase)
1149 protected boolean isIgnore(PesiExportState state
) {
1150 return ! state
.getConfig().isDoTaxa();
1154 * Returns the <code>RankFk</code> attribute.
1155 * @param taxonName The {@link TaxonNameBase TaxonName}.
1156 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
1157 * @return The <code>RankFk</code> attribute.
1160 private static Integer
getRankFk(TaxonNameBase
<?
,?
> taxonName
, NomenclaturalCode nomenclaturalCode
) {
1161 Integer result
= null;
1163 if (nomenclaturalCode
!= null) {
1164 if (taxonName
!= null) {
1165 if (taxonName
.getRank() == null) {
1166 logger
.warn("Rank is null: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1168 result
= PesiTransformer
.rank2RankId(taxonName
.getRank(), PesiTransformer
.nomenClaturalCode2Kingdom(nomenclaturalCode
));
1170 if (result
== null) {
1171 logger
.warn("Rank could not be determined for PESI-Kingdom-Id " + PesiTransformer
.nomenClaturalCode2Kingdom(nomenclaturalCode
) + " and TaxonName " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1175 } catch (Exception e
) {
1176 e
.printStackTrace();
1182 * Returns the <code>RankCache</code> attribute.
1183 * @param taxonName The {@link TaxonNameBase TaxonName}.
1184 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
1185 * @return The <code>RankCache</code> attribute.
1188 private static String
getRankCache(TaxonNameBase
<?
,?
> taxonName
, NomenclaturalCode nomenclaturalCode
) {
1189 String result
= null;
1191 if (nomenclaturalCode
!= null) {
1192 result
= PesiTransformer
.rank2RankCache(taxonName
.getRank(), PesiTransformer
.nomenClaturalCode2Kingdom(nomenclaturalCode
));
1194 } catch (Exception e
) {
1195 e
.printStackTrace();
1202 * Returns the <code>WebShowName</code> attribute.
1203 * @param taxonName The {@link TaxonNameBase TaxonName}.
1204 * @return The <code>WebShowName</code> attribute.
1207 @SuppressWarnings("unused")
1208 private static String
getWebShowName(TaxonNameBase
<?
,?
> taxonName
) {
1210 if (taxonName
== null) {
1213 INonViralNameCacheStrategy cacheStrategy
= getCacheStrategy(taxonName
);
1215 HTMLTagRules tagRules
= new HTMLTagRules().addRule(TagEnum
.name
, "i");
1216 NonViralName
<?
> nvn
= CdmBase
.deproxy(taxonName
, NonViralName
.class);
1217 return cacheStrategy
.getTitleCache(nvn
, tagRules
);
1222 * Returns the <code>WebSearchName</code> attribute.
1223 * @param taxonName The {@link NonViralName NonViralName}.
1224 * @return The <code>WebSearchName</code> attribute.
1227 @SuppressWarnings("unused")
1228 private static String
getWebSearchName(TaxonNameBase taxonName
) {
1230 NonViralName
<?
> nvn
= CdmBase
.deproxy(taxonName
, NonViralName
.class);
1231 NonViralNameDefaultCacheStrategy strategy
= getCacheStrategy(nvn
);
1232 String result
= strategy
.getNameCache(nvn
);
1238 * Returns the <code>FullName</code> attribute.
1239 * @param taxonName The {@link NonViralName NonViralName}.
1240 * @return The <code>FullName</code> attribute.
1243 @SuppressWarnings("unused")
1244 private static String
getFullName(TaxonNameBase taxonName
) {
1246 NonViralName
<?
> nvn
= CdmBase
.deproxy(taxonName
, NonViralName
.class);
1247 String result
= getCacheStrategy(nvn
).getTitleCache(nvn
);
1253 * Returns the <code>AuthorString</code> attribute.
1254 * @param taxonName The {@link TaxonNameBase TaxonName}.
1255 * @return The <code>AuthorString</code> attribute.
1258 @SuppressWarnings("unused")
1259 private static String
getAuthorString(TaxonBase
<?
> taxon
) {
1260 String result
= null;
1262 boolean isNonViralName
= false;
1263 String authorshipCache
= null;
1264 TaxonNameBase
<?
,?
> taxonName
= taxon
.getName();
1265 if (taxonName
!= null && taxonName
.isInstanceOf(NonViralName
.class)){
1266 authorshipCache
= CdmBase
.deproxy(taxonName
, NonViralName
.class).getAuthorshipCache();
1267 isNonViralName
= true;
1269 // For a misapplied name without an authorshipCache the authorString should be set to "auct."
1270 if (isMisappliedName(taxon
) && authorshipCache
== null) {
1271 // Set authorshipCache to "auct."
1272 result
= PesiTransformer
.auctString
;
1274 result
= authorshipCache
;
1276 if (taxonName
== null){
1277 logger
.warn("TaxonName does not exist for taxon: " + taxon
.getUuid() + " (" + taxon
.getTitleCache() + ")");
1278 }else if (! isNonViralName
){
1279 logger
.warn("TaxonName is not of instance NonViralName: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1282 } catch (Exception e
) {
1283 e
.printStackTrace();
1286 if (StringUtils
.isBlank(result
)) {
1295 * Checks whether a given TaxonName is a misapplied name.
1296 * @param taxonName The {@link TaxonNameBase TaxonName}.
1297 * @return Whether the given TaxonName is a misapplied name or not.
1299 private static boolean isMisappliedName(TaxonNameBase taxonName
) {
1300 boolean result
= false;
1301 Set
<Taxon
> taxa
= taxonName
.getTaxa();
1302 if (taxa
.size() == 1){
1303 return isMisappliedName(taxa
.iterator().next());
1304 }else if (taxa
.size() > 1){
1305 logger
.warn("TaxonNameBase has " + taxa
.size() + " taxa attached. Can't define if it is a misapplied name.");
1314 * Checks whether a given Taxon is a misapplied name.
1315 * @param taxonName The {@link TaxonNameBase TaxonName}.
1316 * @return Whether the given TaxonName is a misapplied name or not.
1318 private static boolean isMisappliedName(TaxonBase
<?
> taxon
) {
1319 boolean result
= false;
1321 if (! taxon
.isInstanceOf(Taxon
.class)){
1324 Set
<TaxonRelationship
> taxonRelations
= CdmBase
.deproxy(taxon
, Taxon
.class).getRelationsFromThisTaxon();
1325 for (TaxonRelationship taxonRelationship
: taxonRelations
) {
1326 TaxonRelationshipType taxonRelationshipType
= taxonRelationship
.getType();
1327 if (taxonRelationshipType
.equals(TaxonRelationshipType
.MISAPPLIED_NAME_FOR())) {
1336 * Returns the <code>DisplayName</code> attribute.
1337 * @param taxonName The {@link TaxonNameBase TaxonName}.
1338 * @return The <code>DisplayName</code> attribute.
1341 @SuppressWarnings("unused")
1342 private static String
getDisplayName(TaxonNameBase
<?
,?
> taxonName
) {
1344 if (taxonName
== null) {
1348 INonViralNameCacheStrategy cacheStrategy
= getCacheStrategy(taxonName
);
1350 HTMLTagRules tagRules
= new HTMLTagRules().addRule(TagEnum
.name
, "i");
1351 NonViralName
<?
> nvn
= CdmBase
.deproxy(taxonName
, NonViralName
.class);
1352 return cacheStrategy
.getFullTitleCache(nvn
, tagRules
);
1358 * Returns the <code>NameStatusFk</code> attribute.
1359 * @param taxonName The {@link TaxonNameBase TaxonName}.
1360 * @return The <code>NameStatusFk</code> attribute.
1363 @SuppressWarnings("unused")
1364 private static Integer
getNameStatusFk(TaxonNameBase
<?
,?
> taxonName
) {
1365 Integer result
= null;
1367 NomenclaturalStatus state
= getNameStatus(taxonName
);
1368 if (state
!= null) {
1369 result
= PesiTransformer
.nomStatus2nomStatusFk(state
.getType());
1375 * Returns the <code>NameStatusCache</code> attribute.
1376 * @param taxonName The {@link TaxonNameBase TaxonName}.
1377 * @return The <code>NameStatusCache</code> attribute.
1380 @SuppressWarnings("unused")
1381 private static String
getNameStatusCache(TaxonNameBase
<?
,?
> taxonName
) {
1382 String result
= null;
1383 NomenclaturalStatus state
= getNameStatus(taxonName
);
1384 if (state
!= null) {
1385 result
= PesiTransformer
.nomStatus2NomStatusCache(state
.getType());
1391 private static NomenclaturalStatus
getNameStatus(TaxonNameBase
<?
,?
> taxonName
) {
1394 if (taxonName
!= null && (taxonName
.isInstanceOf(NonViralName
.class))) {
1395 NonViralName
<?
> nonViralName
= CdmBase
.deproxy(taxonName
, NonViralName
.class);
1396 Set
<NomenclaturalStatus
> states
= nonViralName
.getStatus();
1397 if (states
.size() == 1) {
1398 NomenclaturalStatus state
= states
.iterator().next();
1400 } else if (states
.size() > 1) {
1401 logger
.error("This TaxonName has more than one Nomenclatural Status: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1405 } catch (Exception e
) {
1406 e
.printStackTrace();
1411 * Returns the <code>TaxonStatusFk</code> attribute.
1412 * @param taxonName The {@link TaxonNameBase TaxonName}.
1413 * @param state The {@link PesiExportState PesiExportState}.
1414 * @return The <code>TaxonStatusFk</code> attribute.
1417 @SuppressWarnings("unused")
1418 private static Integer
getTaxonStatusFk(TaxonBase
<?
> taxon
, PesiExportState state
) {
1419 Integer result
= null;
1422 if (isMisappliedName(taxon
)) {
1423 Synonym synonym
= Synonym
.NewInstance(null, null);
1425 // This works as long as only the instance is important to differentiate between TaxonStatus.
1426 result
= PesiTransformer
.taxonBase2statusFk(synonym
); // Auct References are treated as Synonyms in Datawarehouse now.
1428 result
= PesiTransformer
.taxonBase2statusFk(taxon
);
1431 } catch (Exception e
) {
1432 e
.printStackTrace();
1438 * Returns the <code>TaxonStatusCache</code> attribute.
1439 * @param taxonName The {@link TaxonNameBase TaxonName}.
1440 * @param state The {@link PesiExportState PesiExportState}.
1441 * @return The <code>TaxonStatusCache</code> attribute.
1444 @SuppressWarnings("unused")
1445 private static String
getTaxonStatusCache(TaxonBase
<?
> taxon
, PesiExportState state
) {
1446 String result
= null;
1449 if (isMisappliedName(taxon
)) {
1450 Synonym synonym
= Synonym
.NewInstance(null, null);
1452 // This works as long as only the instance is important to differentiate between TaxonStatus.
1453 result
= PesiTransformer
.taxonBase2statusCache(synonym
); // Auct References are treated as Synonyms in Datawarehouse now.
1455 result
= PesiTransformer
.taxonBase2statusCache(taxon
);
1458 } catch (Exception e
) {
1459 e
.printStackTrace();
1465 * Returns the <code>TypeNameFk</code> attribute.
1466 * @param taxonName The {@link TaxonNameBase TaxonName}.
1467 * @param state The {@link PesiExportState PesiExportState}.
1468 * @return The <code>TypeNameFk</code> attribute.
1471 private static Integer
getTypeNameFk(TaxonNameBase
<?
,?
> taxonNameBase
, PesiExportState state
) {
1472 Integer result
= null;
1473 if (taxonNameBase
!= null) {
1474 Set
<NameTypeDesignation
> nameTypeDesignations
= taxonNameBase
.getNameTypeDesignations();
1475 if (nameTypeDesignations
.size() == 1) {
1476 NameTypeDesignation nameTypeDesignation
= nameTypeDesignations
.iterator().next();
1477 if (nameTypeDesignation
!= null) {
1478 TaxonNameBase
<?
,?
> typeName
= nameTypeDesignation
.getTypeName();
1479 if (typeName
!= null) {
1480 result
= state
.getDbId(typeName
);
1483 } else if (nameTypeDesignations
.size() > 1) {
1484 logger
.warn("This TaxonName has " + nameTypeDesignations
.size() + " NameTypeDesignations: " + taxonNameBase
.getUuid() + " (" + taxonNameBase
.getTitleCache() + ")");
1491 * Returns the <code>TypeFullnameCache</code> attribute.
1492 * @param taxonName The {@link TaxonNameBase TaxonName}.
1493 * @return The <code>TypeFullnameCache</code> attribute.
1496 @SuppressWarnings("unused")
1497 private static String
getTypeFullnameCache(TaxonNameBase
<?
,?
> taxonName
) {
1498 String result
= null;
1501 if (taxonName
!= null) {
1502 Set
<NameTypeDesignation
> nameTypeDesignations
= taxonName
.getNameTypeDesignations();
1503 if (nameTypeDesignations
.size() == 1) {
1504 NameTypeDesignation nameTypeDesignation
= nameTypeDesignations
.iterator().next();
1505 if (nameTypeDesignation
!= null) {
1506 TaxonNameBase
<?
,?
> typeName
= nameTypeDesignation
.getTypeName();
1507 if (typeName
!= null) {
1508 result
= typeName
.getTitleCache();
1511 } else if (nameTypeDesignations
.size() > 1) {
1512 logger
.warn("This TaxonName has " + nameTypeDesignations
.size() + " NameTypeDesignations: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1516 } catch (Exception e
) {
1517 e
.printStackTrace();
1523 * Returns the <code>QualityStatusFk</code> attribute.
1524 * @param taxonName The {@link TaxonNameBase TaxonName}.
1525 * @return The <code>QualityStatusFk</code> attribute.
1528 @SuppressWarnings("unused")
1529 private static Integer
getQualityStatusFk(TaxonBase
<?
> taxonName
) {
1530 // TODO: Not represented in CDM right now. Depends on import.
1531 Integer result
= null;
1536 * Returns the <code>QualityStatusCache</code> attribute.
1537 * @param taxonName The {@link TaxonNameBase TaxonName}.
1538 * @return The <code>QualityStatusCache</code> attribute.
1541 @SuppressWarnings("unused")
1542 private static String
getQualityStatusCache(TaxonBase
<?
> taxonName
) {
1543 // TODO: Not represented in CDM right now. Depends on import.
1544 String result
= null;
1549 * Returns the <code>TypeDesignationStatusFk</code> attribute.
1550 * @param taxonName The {@link TaxonNameBase TaxonName}.
1551 * @return The <code>TypeDesignationStatusFk</code> attribute.
1554 @SuppressWarnings("unused")
1555 private static Integer
getTypeDesignationStatusFk(TaxonNameBase
<?
,?
> taxonName
) {
1556 Integer result
= null;
1559 if (taxonName
!= null) {
1560 Set
<NameTypeDesignation
> typeDesignations
= taxonName
.getNameTypeDesignations();
1561 if (typeDesignations
.size() == 1) {
1562 Object obj
= typeDesignations
.iterator().next().getTypeStatus();
1563 NameTypeDesignationStatus designationStatus
= CdmBase
.deproxy(obj
, NameTypeDesignationStatus
.class);
1564 result
= PesiTransformer
.nameTypeDesignationStatus2TypeDesignationStatusId(designationStatus
);
1565 } else if (typeDesignations
.size() > 1) {
1566 logger
.error("Found a TaxonName with more than one NameTypeDesignation: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1570 } catch (Exception e
) {
1571 e
.printStackTrace();
1577 * Returns the <code>TypeDesignationStatusCache</code> attribute.
1578 * @param taxonName The {@link TaxonNameBase TaxonName}.
1579 * @return The <code>TypeDesignationStatusCache</code> attribute.
1582 @SuppressWarnings("unused")
1583 private static String
getTypeDesignationStatusCache(TaxonNameBase
<?
,?
> taxonName
) {
1584 String result
= null;
1587 if (taxonName
!= null) {
1588 Set
<NameTypeDesignation
> typeDesignations
= taxonName
.getNameTypeDesignations();
1589 if (typeDesignations
.size() == 1) {
1590 Object obj
= typeDesignations
.iterator().next().getTypeStatus();
1591 NameTypeDesignationStatus designationStatus
= CdmBase
.deproxy(obj
, NameTypeDesignationStatus
.class);
1592 result
= PesiTransformer
.nameTypeDesignationStatus2TypeDesignationStatusCache(designationStatus
);
1593 } else if (typeDesignations
.size() > 1) {
1594 logger
.error("Found a TaxonName with more than one NameTypeDesignation: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1598 } catch (Exception e
) {
1599 e
.printStackTrace();
1605 * Returns the <code>FossilStatusFk</code> attribute.
1606 * @param taxonName The {@link TaxonNameBase TaxonName}.
1607 * @return The <code>FossilStatusFk</code> attribute.
1610 @SuppressWarnings("unused")
1611 private static Integer
getFossilStatusFk(TaxonNameBase
<?
,?
> taxonNameBase
) {
1612 Integer result
= null;
1614 // if (taxonBase.isInstanceOf(Taxon.class)) {
1615 // taxon = CdmBase.deproxy(taxonBase, Taxon.class);
1616 // Set<TaxonDescription> specimenDescription = taxon.;
1617 // result = PesiTransformer.fossil2FossilStatusId(fossil);
1623 * Returns the <code>FossilStatusCache</code> attribute.
1624 * @param taxonName The {@link TaxonNameBase TaxonName}.
1625 * @return The <code>FossilStatusCache</code> attribute.
1628 @SuppressWarnings("unused")
1629 private static String
getFossilStatusCache(TaxonNameBase
<?
,?
> taxonName
) {
1631 String result
= null;
1636 * Returns the <code>IdInSource</code> attribute.
1637 * @param taxonName The {@link TaxonNameBase TaxonName}.
1638 * @return The <code>IdInSource</code> attribute.
1641 @SuppressWarnings("unused")
1642 private static String
getIdInSource(IdentifiableEntity taxonName
) {
1643 String result
= null;
1646 Set
<IdentifiableSource
> sources
= getSources(taxonName
);
1647 for (IdentifiableSource source
: sources
) {
1648 result
= "TAX_ID: " + source
.getIdInSource();
1649 String sourceIdNameSpace
= source
.getIdNamespace();
1650 if (sourceIdNameSpace
!= null) {
1651 if (sourceIdNameSpace
.equals("originalGenusId")) {
1652 result
= "Nominal Taxon from TAX_ID: " + source
.getIdInSource();
1653 } else if (sourceIdNameSpace
.equals("InferredEpithetOf")) {
1654 result
= "Inferred epithet from TAX_ID: " + source
.getIdInSource();
1655 } else if (sourceIdNameSpace
.equals("InferredGenusOf")) {
1656 result
= "Inferred genus from TAX_ID: " + source
.getIdInSource();
1657 } else if (sourceIdNameSpace
.equals("PotentialCombinationOf")) {
1658 result
= "Potential combination from TAX_ID: " + source
.getIdInSource();
1660 result
= "TAX_ID: " + source
.getIdInSource();
1664 } catch (Exception e
) {
1665 e
.printStackTrace();
1668 if (result
== null) {
1669 logger
.warn("IdInSource is NULL for this taxonName: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() +")");
1675 * Returns the idInSource for a given TaxonName only.
1676 * @param taxonName The {@link TaxonNameBase TaxonName}.
1677 * @return The idInSource.
1679 private static String
getIdInSourceOnly(IdentifiableEntity identEntity
) {
1680 String result
= null;
1682 // Get the sources first
1683 Set
<IdentifiableSource
> sources
= getSources(identEntity
);
1685 // Determine the idInSource
1686 if (sources
.size() == 1) {
1687 IdentifiableSource source
= sources
.iterator().next();
1688 if (source
!= null) {
1689 result
= source
.getIdInSource();
1691 } else if (sources
.size() > 1) {
1694 for (IdentifiableSource source
: sources
) {
1695 result
+= source
.getIdInSource();
1696 if (count
< sources
.size()) {
1708 * Returns the Sources for a given TaxonName only.
1709 * @param taxonName The {@link TaxonNameBase TaxonName}.
1710 * @return The Sources.
1712 private static Set
<IdentifiableSource
> getSources(IdentifiableEntity identEntity
) {
1713 Set
<IdentifiableSource
> sources
= null;
1716 if (identEntity
.isInstanceOf(TaxonNameBase
.class)){
1717 // Sources from TaxonName
1718 TaxonNameBase taxonName
= CdmBase
.deproxy(identEntity
, TaxonNameBase
.class);
1719 Set
<IdentifiableSource
> nameSources
= identEntity
.getSources();
1720 sources
= nameSources
;
1721 if (nameSources
.size() > 1) {
1722 logger
.warn("This TaxonName has more than one Source: " + identEntity
.getUuid() + " (" + identEntity
.getTitleCache() + ")");
1725 // Sources from TaxonBase
1726 if (sources
== null || sources
.isEmpty()) {
1727 Set
<Taxon
> taxa
= taxonName
.getTaxa();
1728 Set
<Synonym
> synonyms
= taxonName
.getSynonyms();
1729 if (taxa
.size() == 1) {
1730 Taxon taxon
= taxa
.iterator().next();
1732 if (taxon
!= null) {
1733 sources
= taxon
.getSources();
1735 } else if (taxa
.size() > 1) {
1736 logger
.warn("This TaxonName has " + taxa
.size() + " Taxa: " + identEntity
.getUuid() + " (" + identEntity
.getTitleCache() +")");
1738 if (synonyms
.size() == 1) {
1739 Synonym synonym
= synonyms
.iterator().next();
1741 if (synonym
!= null) {
1742 sources
= synonym
.getSources();
1744 } else if (synonyms
.size() > 1) {
1745 logger
.warn("This TaxonName has " + synonyms
.size() + " Synonyms: " + identEntity
.getUuid() + " (" + identEntity
.getTitleCache() +")");
1750 }else if (identEntity
.isInstanceOf(TaxonBase
.class)){
1751 sources
= identEntity
.getSources();
1755 if (sources
== null || sources
.isEmpty()) {
1756 logger
.warn("This TaxonName has no Sources: " + identEntity
.getUuid() + " (" + identEntity
.getTitleCache() +")");
1762 * Returns the <code>GUID</code> attribute.
1763 * @param taxonName The {@link TaxonNameBase TaxonName}.
1764 * @return The <code>GUID</code> attribute.
1767 private static String
getGUID(TaxonBase
<?
> taxon
) {
1768 if (taxon
.getLsid() != null ){
1769 return taxon
.getLsid().getLsid();
1771 return taxon
.getUuid().toString();
1776 * Returns the <code>DerivedFromGuid</code> attribute.
1777 * @param taxonName The {@link TaxonNameBase TaxonName}.
1778 * @return The <code>DerivedFromGuid</code> attribute.
1781 @SuppressWarnings("unused")
1782 private static String
getDerivedFromGuid(TaxonBase
<?
> taxon
) {
1783 String result
= null;
1785 // The same as GUID for now
1786 result
= getGUID(taxon
);
1787 } catch (Exception e
) {
1788 e
.printStackTrace();
1794 * Returns the <code>CacheCitation</code> attribute.
1795 * @param taxonName The {@link TaxonNameBase TaxonName}.
1796 * @return The CacheCitation.
1799 @SuppressWarnings("unused")
1800 private static String
getCacheCitation(TaxonBase
<?
> taxon
) {
1802 //TODO implement anew for taxa
1804 // String originalDb = getOriginalDB(taxon);
1805 // if (originalDb == null) {
1806 //// logger.error("OriginalDB is NULL for this TaxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
1807 // } else if (originalDb.equals("ERMS")) {
1808 // // 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...
1809 // // So the following code is some kind of harmless assumption.
1810 // Set<Extension> extensions = taxon.getExtensions();
1811 // for (Extension extension : extensions) {
1812 // if (extension.getType().equals(cacheCitationExtensionType)) {
1813 // result = extension.getValue();
1817 // String expertName = getExpertName(taxon);
1818 // String webShowName = getWebShowName(taxon);
1820 // // idInSource only
1821 // String idInSource = getIdInSourceOnly(taxo);
1823 // // build the cacheCitation
1824 // if (expertName != null) {
1825 // result += expertName + ". ";
1827 // // logger.error("ExpertName could not be determined for this TaxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
1829 // if (webShowName != null) {
1830 // result += webShowName + ". ";
1832 // // logger.error("WebShowName could not be determined for this TaxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
1835 // if (getOriginalDB(taxonName).equals("FaEu")) {
1836 // result += "Accessed through: Fauna Europaea at http://faunaeur.org/full_results.php?id=";
1837 // } else if (getOriginalDB(taxonName).equals("EM")) {
1838 // result += "Accessed through: Euro+Med PlantBase at http://ww2.bgbm.org/euroPlusMed/PTaxonDetail.asp?UUID=";
1841 // if (idInSource != null) {
1842 // result += idInSource;
1844 // // logger.error("IdInSource could not be determined for this TaxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
1847 // } catch (Exception e) {
1848 // e.printStackTrace();
1851 // if ("".equals(result)) {
1860 * Returns the <code>OriginalDB</code> attribute.
1861 * @param taxonName The {@link TaxonNameBase TaxonName}.
1862 * @return The <code>OriginalDB</code> attribute.
1865 private static String
getOriginalDB(IdentifiableEntity identEntity
) {
1869 // Sources from TaxonName
1870 // Set<IdentifiableSource> sources = taxonName.getSources();
1871 Set
<IdentifiableSource
> sources
= identEntity
.getSources();
1873 // IdentifiableEntity<?> taxonBase = null;
1874 // if (sources != null && sources.isEmpty()) {
1875 // // Sources from Taxa or Synonyms
1876 // Set<Taxon> taxa = taxonName.getTaxa();
1877 // if (taxa.size() == 1) {
1878 // taxonBase = taxa.iterator().next();
1879 // sources = taxonBase.getSources();
1880 // } else if (taxa.size() > 1) {
1881 // logger.warn("This TaxonName has " + taxa.size() + " Taxa: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() +")");
1883 // Set<Synonym> synonyms = taxonName.getSynonyms();
1884 // if (synonyms.size() == 1) {
1885 // taxonBase = synonyms.iterator().next();
1886 // sources = taxonBase.getSources();
1887 // } else if (synonyms.size() > 1) {
1888 // logger.warn("This TaxonName has " + synonyms.size() + " Synonyms: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() +")");
1892 if (sources
!= null && ! sources
.isEmpty()) {
1893 if (sources
.size() == 1) {
1894 IdentifiableSource source
= sources
.iterator().next();
1895 if (source
!= null) {
1896 Reference
<?
> citation
= source
.getCitation();
1897 if (citation
!= null) {
1898 result
= PesiTransformer
.databaseString2Abbreviation(citation
.getTitleCache());
1901 } else if (sources
.size() > 1) {
1903 for (IdentifiableSource source
: sources
) {
1904 Reference
<?
> citation
= source
.getCitation();
1905 if (citation
!= null) {
1909 result
+= PesiTransformer
.databaseString2Abbreviation(citation
.getTitleCache());
1918 } catch (Exception e
) {
1919 e
.printStackTrace();
1921 if ("".equals(result
)) {
1929 * Returns the <code>LastAction</code> attribute.
1930 * @param taxonName The {@link TaxonNameBase TaxonName}.
1931 * @return The <code>LastAction</code> attribute.
1934 @SuppressWarnings("unused")
1935 private static String
getLastAction(IdentifiableEntity
<?
> identEntity
) {
1936 String result
= null;
1938 Set
<Extension
> extensions
= identEntity
.getExtensions();
1939 for (Extension extension
: extensions
) {
1940 if (extension
.getType().equals(lastActionExtensionType
)) {
1941 result
= extension
.getValue();
1944 } catch (Exception e
) {
1945 e
.printStackTrace();
1951 * Returns the <code>LastActionDate</code> attribute.
1952 * @param taxonName The {@link TaxonNameBase TaxonName}.
1953 * @return The <code>LastActionDate</code> attribute.
1956 @SuppressWarnings({ "unused" })
1957 private static DateTime
getLastActionDate(IdentifiableEntity identEntity
) {
1958 DateTime result
= null;
1960 Set
<Extension
> extensions
= identEntity
.getExtensions();
1961 for (Extension extension
: extensions
) {
1962 if (extension
.getType().equals(lastActionDateExtensionType
)) {
1963 String dateTime
= extension
.getValue();
1964 if (dateTime
!= null) {
1965 DateTimeFormatter formatter
= DateTimeFormat
.forPattern("yyyy-MM-dd HH:mm:ss.S");
1966 result
= formatter
.parseDateTime(dateTime
);
1970 } catch (Exception e
) {
1971 e
.printStackTrace();
1977 * Returns the <code>ExpertName</code> attribute.
1978 * @param taxonName The {@link TaxonNameBase TaxonName}.
1979 * @return The <code>ExpertName</code> attribute.
1982 @SuppressWarnings("unused")
1983 private static String
getExpertName(TaxonBase
<?
> taxonName
) {
1984 String result
= null;
1986 Set
<Extension
> extensions
= taxonName
.getExtensions();
1987 for (Extension extension
: extensions
) {
1988 if (extension
.getType().equals(expertNameExtensionType
)) {
1989 result
= extension
.getValue();
1992 } catch (Exception e
) {
1993 e
.printStackTrace();
1999 * Returns the <code>ExpertFk</code> attribute.
2000 * @param taxonName The {@link TaxonNameBase TaxonName}.
2001 * @param state The {@link PesiExportState PesiExportState}.
2002 * @return The <code>ExpertFk</code> attribute.
2005 private static Integer
getExpertFk(Reference
<?
> reference
, PesiExportState state
) {
2006 Integer result
= state
.getDbId(reference
);
2011 * Returns the <code>SpeciesExpertName</code> attribute.
2012 * @param taxonName The {@link TaxonNameBase TaxonName}.
2013 * @return The <code>SpeciesExpertName</code> attribute.
2016 @SuppressWarnings("unused")
2017 private static String
getSpeciesExpertName(TaxonBase
<?
> taxonName
) {
2018 String result
= null;
2020 Set
<Extension
> extensions
= taxonName
.getExtensions();
2021 for (Extension extension
: extensions
) {
2022 if (extension
.getType().equals(speciesExpertNameExtensionType
)) {
2023 result
= extension
.getValue();
2026 } catch (Exception e
) {
2027 e
.printStackTrace();
2033 * Returns the <code>SpeciesExpertFk</code> attribute.
2034 * @param reference The {@link Reference Reference}.
2035 * @param state The {@link PesiExportState PesiExportState}.
2036 * @return The <code>SpeciesExpertFk</code> attribute.
2039 private static Integer
getSpeciesExpertFk(Reference
<?
> reference
, PesiExportState state
) {
2040 Integer result
= state
.getDbId(reference
);
2045 private static NonViralNameDefaultCacheStrategy
getCacheStrategy(TaxonNameBase
<?
, ?
> taxonName
) {
2046 NonViralNameDefaultCacheStrategy cacheStrategy
;
2047 if (taxonName
.isInstanceOf(ZoologicalName
.class)){
2048 cacheStrategy
= zooNameStrategy
;
2049 }else if (taxonName
.isInstanceOf(BotanicalName
.class)) {
2050 cacheStrategy
= botanicalNameStrategy
;
2052 logger
.error("Unhandled taxon name type. Can't define strategy class");
2053 cacheStrategy
= botanicalNameStrategy
;
2055 return cacheStrategy
;
2059 // * Returns the <code>SourceFk</code> attribute.
2060 // * @param taxonName The {@link TaxonNameBase TaxonName}.
2061 // * @param state The {@link PesiExportState PesiExportState}.
2062 // * @return The <code>SourceFk</code> attribute.
2064 // @SuppressWarnings("unused")
2065 // private static Integer getSourceFk(TaxonNameBase<?,?> taxonName, PesiExportState state) {
2066 // Integer result = null;
2069 // TaxonBase<?> taxonBase = getSourceTaxonBase(taxonName);
2071 // if (taxonBase != null) {
2072 // result = state.getDbId(taxonBase.getSec());
2074 // } catch (Exception e) {
2075 // e.printStackTrace();
2082 // * Determines the TaxonBase of a TaxonName.
2083 // * @param taxonName The {@link TaxonNameBase TaxonName}.
2084 // * @return The TaxonBase.
2086 // private static TaxonBase<?> getSourceTaxonBase(TaxonNameBase<?,?> taxonName) {
2087 // TaxonBase<?> taxonBase = null;
2088 // Set<Taxon> taxa = taxonName.getTaxa();
2089 // if (taxa.size() == 1) {
2090 // taxonBase =taxa.iterator().next();
2091 // } else if (taxa.size() > 1) {
2092 // logger.warn("This TaxonName has " + taxa.size() + " Taxa: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
2095 // Set<Synonym> synonyms = taxonName.getSynonyms();
2096 // if (synonyms.size() == 1) {
2097 // taxonBase = synonyms.iterator().next();
2098 // } else if (synonyms.size() > 1) {
2099 // logger.warn("This TaxonName has " + synonyms.size() + " Synonyms: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
2101 // return taxonBase;
2105 * Returns the CDM to PESI specific export mappings.
2106 * @return The {@link PesiExportMapping PesiExportMapping}.
2108 private PesiExportMapping
getMapping() {
2109 PesiExportMapping mapping
= new PesiExportMapping(dbTableName
);
2110 ExtensionType extensionType
= null;
2112 mapping
.addMapper(IdMapper
.NewInstance("TaxonId"));
2113 mapping
.addMapper(DbObjectMapper
.NewInstance("sec", "sourceFk")); //OLD:mapping.addMapper(MethodMapper.NewInstance("SourceFK", this.getClass(), "getSourceFk", standardMethodParameter, PesiExportState.class));
2114 mapping
.addMapper(MethodMapper
.NewInstance("TaxonStatusFk", this.getClass(), "getTaxonStatusFk", standardMethodParameter
, PesiExportState
.class));
2115 mapping
.addMapper(MethodMapper
.NewInstance("TaxonStatusCache", this.getClass(), "getTaxonStatusCache", standardMethodParameter
, PesiExportState
.class));
2116 // QualityStatus (Fk, Cache)
2117 extensionType
= (ExtensionType
)getTermService().find(ErmsTransformer
.uuidQualityStatus
);
2118 if (extensionType
!= null) {
2119 mapping
.addMapper(DbExtensionMapper
.NewInstance(extensionType
, "QualityStatusCache"));
2121 mapping
.addMapper(MethodMapper
.NewInstance("QualityStatusCache", this));
2123 mapping
.addMapper(MethodMapper
.NewInstance("QualityStatusFk", this)); // PesiTransformer.QualityStatusCache2QualityStatusFk?
2125 mapping
.addMapper(MethodMapper
.NewInstance("GUID", this));
2126 //TODO implement again
2127 mapping
.addMapper(MethodMapper
.NewInstance("IdInSource", this, IdentifiableEntity
.class));
2129 mapping
.addMapper(MethodMapper
.NewInstance("DerivedFromGuid", this));
2130 mapping
.addMapper(MethodMapper
.NewInstance("CacheCitation", this));
2131 mapping
.addMapper(MethodMapper
.NewInstance("OriginalDB", this.getClass(), "getOriginalDB", IdentifiableEntity
.class) );
2133 mapping
.addMapper(MethodMapper
.NewInstance("LastAction", this.getClass(), "getLastAction", IdentifiableEntity
.class));
2134 mapping
.addMapper(MethodMapper
.NewInstance("LastActionDate", this.getClass(), "getLastActionDate", IdentifiableEntity
.class));
2135 mapping
.addMapper(MethodMapper
.NewInstance("ExpertName", this));
2136 mapping
.addMapper(MethodMapper
.NewInstance("SpeciesExpertName", this));
2138 mapping
.addMapper(MethodMapper
.NewInstance("AuthorString", this)); //For Taxon because Misallied Names are handled differently
2141 mapping
.addMapper(ObjectChangeMapper
.NewInstance(TaxonBase
.class, TaxonNameBase
.class, "Name"));
2143 addNameMappers(mapping
);
2149 * Returns the CDM to PESI specific export mappings.
2150 * @return The {@link PesiExportMapping PesiExportMapping}.
2152 private PesiExportMapping
getNameMapping() {
2153 PesiExportMapping mapping
= new PesiExportMapping(dbTableName
);
2155 mapping
.addMapper(IdMapper
.NewInstance("TaxonId"));
2157 // mapping.addMapper(MethodMapper.NewInstance("TaxonStatusFk", this.getClass(), "getTaxonStatusFk", standardMethodParameter, PesiExportState.class));
2159 mapping
.addMapper(MethodMapper
.NewInstance("LastAction", this.getClass(), "getLastAction", IdentifiableEntity
.class));
2160 mapping
.addMapper(MethodMapper
.NewInstance("LastActionDate", this.getClass(), "getLastAction", IdentifiableEntity
.class));
2161 mapping
.addMapper(MethodMapper
.NewInstance("OriginalDB", this.getClass(), "getOriginalDB", IdentifiableEntity
.class) );
2164 mapping
.addMapper(MethodMapper
.NewInstance("IdInSource", this));
2166 addNameMappers(mapping
);
2168 //TODO add author mapper, taxonStatusFk, TaxonStatusCache, TypeNameFk
2170 // immer 2 für E+M ? mapping.addMapper(MethodMapper.NewInstance("QualityStatusFk", this)); // PesiTransformer.QualityStatusCache2QualityStatusFk?
2171 // mapping.addMapper(MethodMapper.NewInstance("TaxonStatusCache", this.getClass(), "getTaxonStatusCache", standardMethodParameter, PesiExportState.class));
2176 private void addNameMappers(PesiExportMapping mapping
) {
2177 ExtensionType extensionType
;
2178 mapping
.addMapper(DbStringMapper
.NewInstance("GenusOrUninomial", "GenusOrUninomial"));
2179 mapping
.addMapper(DbStringMapper
.NewInstance("InfraGenericEpithet", "InfraGenericEpithet"));
2180 mapping
.addMapper(DbStringMapper
.NewInstance("SpecificEpithet", "SpecificEpithet"));
2181 mapping
.addMapper(DbStringMapper
.NewInstance("InfraSpecificEpithet", "InfraSpecificEpithet"));
2183 // mapping.addMapper(DbStringMapper.NewInstance("NameCache", "WebSearchName"));
2184 mapping
.addMapper(MethodMapper
.NewInstance("WebSearchName", this, TaxonNameBase
.class));
2186 // mapping.addMapper(DbStringMapper.NewInstance("TitleCache", "FullName"));
2187 mapping
.addMapper(MethodMapper
.NewInstance("FullName", this, TaxonNameBase
.class));
2190 //TODO FIXME incorrect mapping -> should be ref + microref but is only microref
2191 mapping
.addMapper(DbStringMapper
.NewInstance("NomenclaturalMicroReference", "NomRefString"));
2192 mapping
.addMapper(MethodMapper
.NewInstance("WebShowName", this, TaxonNameBase
.class));
2195 extensionType
= (ExtensionType
)getTermService().find(ErmsTransformer
.uuidDisplayName
);
2196 if (extensionType
!= null) {
2197 mapping
.addMapper(DbExtensionMapper
.NewInstance(extensionType
, "DisplayName"));
2199 mapping
.addMapper(MethodMapper
.NewInstance("DisplayName", this, TaxonNameBase
.class));
2202 mapping
.addMapper(MethodMapper
.NewInstance("NameStatusFk", this, TaxonNameBase
.class));
2203 mapping
.addMapper(MethodMapper
.NewInstance("NameStatusCache", this, TaxonNameBase
.class));
2204 mapping
.addMapper(MethodMapper
.NewInstance("TypeFullnameCache", this, TaxonNameBase
.class));
2207 // FossilStatus (Fk, Cache)
2208 extensionType
= (ExtensionType
)getTermService().find(ErmsTransformer
.uuidFossilStatus
);
2209 if (extensionType
!= null) {
2210 mapping
.addMapper(DbExtensionMapper
.NewInstance(extensionType
, "FossilStatusCache"));
2212 mapping
.addMapper(MethodMapper
.NewInstance("FossilStatusCache", this, TaxonNameBase
.class));
2214 mapping
.addMapper(MethodMapper
.NewInstance("FossilStatusFk", this, TaxonNameBase
.class)); // PesiTransformer.FossilStatusCache2FossilStatusFk?