2 * Copyright (C) 2009 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
9 package eu
.etaxonomy
.cdm
.io
.pesi
.out
;
11 import java
.sql
.Connection
;
12 import java
.sql
.PreparedStatement
;
13 import java
.sql
.ResultSet
;
14 import java
.sql
.SQLException
;
15 import java
.sql
.Types
;
16 import java
.util
.ArrayList
;
17 import java
.util
.BitSet
;
18 import java
.util
.HashMap
;
19 import java
.util
.HashSet
;
20 import java
.util
.Iterator
;
21 import java
.util
.List
;
24 import java
.util
.UUID
;
25 import java
.util
.regex
.Matcher
;
26 import java
.util
.regex
.Pattern
;
28 import org
.apache
.commons
.lang
.StringUtils
;
29 import org
.apache
.log4j
.Logger
;
30 import org
.joda
.time
.DateTime
;
31 import org
.joda
.time
.format
.DateTimeFormat
;
32 import org
.joda
.time
.format
.DateTimeFormatter
;
33 import org
.springframework
.stereotype
.Component
;
34 import org
.springframework
.transaction
.TransactionStatus
;
36 import eu
.etaxonomy
.cdm
.api
.service
.TaxonServiceImpl
;
37 import eu
.etaxonomy
.cdm
.common
.CdmUtils
;
38 import eu
.etaxonomy
.cdm
.io
.berlinModel
.BerlinModelTransformer
;
39 import eu
.etaxonomy
.cdm
.io
.common
.Source
;
40 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.UndefinedTransformerMethodException
;
41 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbConstantMapper
;
42 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbExtensionMapper
;
43 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbLastActionMapper
;
44 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbObjectMapper
;
45 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbStringMapper
;
46 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.IdMapper
;
47 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.MethodMapper
;
48 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.ObjectChangeMapper
;
49 import eu
.etaxonomy
.cdm
.io
.pesi
.erms
.ErmsTransformer
;
50 import eu
.etaxonomy
.cdm
.model
.common
.Annotation
;
51 import eu
.etaxonomy
.cdm
.model
.common
.AnnotationType
;
52 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
53 import eu
.etaxonomy
.cdm
.model
.common
.Extension
;
54 import eu
.etaxonomy
.cdm
.model
.common
.ExtensionType
;
55 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableEntity
;
56 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableSource
;
57 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
58 import eu
.etaxonomy
.cdm
.model
.common
.Marker
;
59 import eu
.etaxonomy
.cdm
.model
.common
.MarkerType
;
60 import eu
.etaxonomy
.cdm
.model
.common
.RelationshipBase
;
61 import eu
.etaxonomy
.cdm
.model
.name
.NameTypeDesignation
;
62 import eu
.etaxonomy
.cdm
.model
.name
.NameTypeDesignationStatus
;
63 import eu
.etaxonomy
.cdm
.model
.name
.NomenclaturalCode
;
64 import eu
.etaxonomy
.cdm
.model
.name
.NomenclaturalStatus
;
65 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
66 import eu
.etaxonomy
.cdm
.model
.name
.TaxonName
;
67 import eu
.etaxonomy
.cdm
.model
.reference
.INomenclaturalReference
;
68 import eu
.etaxonomy
.cdm
.model
.reference
.Reference
;
69 import eu
.etaxonomy
.cdm
.model
.taxon
.Classification
;
70 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
71 import eu
.etaxonomy
.cdm
.model
.taxon
.SynonymType
;
72 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
73 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
74 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
75 import eu
.etaxonomy
.cdm
.strategy
.cache
.HTMLTagRules
;
76 import eu
.etaxonomy
.cdm
.strategy
.cache
.TagEnum
;
77 import eu
.etaxonomy
.cdm
.strategy
.cache
.name
.INonViralNameCacheStrategy
;
78 import eu
.etaxonomy
.cdm
.strategy
.cache
.name
.TaxonNameDefaultCacheStrategy
;
79 import eu
.etaxonomy
.cdm
.strategy
.cache
.name
.ZooNameNoMarkerCacheStrategy
;
82 * The export class for {@link eu.etaxonomy.cdm.model.name.TaxonNameBase TaxonNames}.<p>
83 * Inserts into DataWarehouse database table <code>Taxon</code>.
84 * It is divided into four phases:<p><ul>
85 * <li>Phase 1: Export of all {@link eu.etaxonomy.cdm.model.name.TaxonName TaxonNames} except some data exported in the following phases.
86 * <li>Phase 2: Export of additional data: ParentTaxonFk and TreeIndex.
87 * <li>Phase 3: Export of additional data: Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk.
88 * <li>Phase 4: Export of Inferred Synonyms.</ul>
94 public class PesiTaxonExport
extends PesiExportBase
{
95 private static final long serialVersionUID
= -3412722058790200078L;
96 private static final Logger logger
= Logger
.getLogger(PesiTaxonExport
.class);
98 private static final Class
<?
extends CdmBase
> standardMethodParameter
= TaxonBase
.class;
100 private static int modCount
= 1000;
101 private static final String dbTableName
= "Taxon";
102 private static final String dbTableNameSynRel
= "RelTaxon";
103 private static final String dbTableAdditionalSourceRel
= "AdditionalTaxonSource";
105 private static final String pluralString
= "Taxa";
106 private static final String parentPluralString
= "Taxa";
108 private PreparedStatement parentTaxonFk_TreeIndex_KingdomFkStmt
;
109 private PreparedStatement parentTaxonFkStmt
;
110 private PreparedStatement rankTypeExpertsUpdateStmt
;
111 private PreparedStatement rankUpdateStmt
;
112 private NomenclaturalCode nomenclaturalCode
;
113 private Integer kingdomFk
;
114 private final HashMap
<Rank
, Rank
> rank2endRankMap
= new HashMap
<>();
115 private final List
<Rank
> rankList
= new ArrayList
<>();
116 private static final UUID uuidTreeIndex
= UUID
.fromString("28f4e205-1d02-4d3a-8288-775ea8413009");
117 private AnnotationType treeIndexAnnotationType
;
118 private static ExtensionType lastActionExtensionType
;
119 private static ExtensionType lastActionDateExtensionType
;
120 private static ExtensionType expertNameExtensionType
;
121 private static ExtensionType speciesExpertNameExtensionType
;
122 private static ExtensionType cacheCitationExtensionType
;
123 public static TaxonNameDefaultCacheStrategy zooNameStrategy
= ZooNameNoMarkerCacheStrategy
.NewInstance();
124 public static TaxonNameDefaultCacheStrategy nonViralNameStrategy
= TaxonNameDefaultCacheStrategy
.NewInstance();
125 private static int currentTaxonId
;
129 * @return the treeIndexAnnotationType
131 protected AnnotationType
getTreeIndexAnnotationType() {
132 return treeIndexAnnotationType
;
136 * @param treeIndexAnnotationType the treeIndexAnnotationType to set
138 protected void setTreeIndexAnnotationType(AnnotationType treeIndexAnnotationType
) {
139 this.treeIndexAnnotationType
= treeIndexAnnotationType
;
150 public PesiTaxonExport() {
155 public Class
<?
extends CdmBase
> getStandardMethodParameter() {
156 return standardMethodParameter
;
160 protected void doInvoke(PesiExportState state
) {
162 logger
.info("*** Started Making " + pluralString
+ " ...");
164 initPreparedStatements(state
);
166 // Stores whether this invoke was successful or not.
167 boolean success
= true;
169 // PESI: Clear the database table Taxon.
172 // Get specific mappings: (CDM) Taxon -> (PESI) Taxon
173 PesiExportMapping mapping
= getMapping();
174 PesiExportMapping synonymRelMapping
= getSynRelMapping();
175 PesiExportMapping additionalSourceMapping
= getAdditionalSourceMapping(state
);
177 // Initialize the db mapper
178 mapping
.initialize(state
);
179 synonymRelMapping
.initialize(state
);
180 additionalSourceMapping
.initialize(state
);
182 // Find extensionTypes
183 lastActionExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.lastActionUuid
);
184 lastActionDateExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.lastActionDateUuid
);
185 expertNameExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.expertNameUuid
);
186 speciesExpertNameExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.speciesExpertNameUuid
);
187 cacheCitationExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.cacheCitationUuid
);
190 success
&= doPhase01(state
, mapping
, additionalSourceMapping
);
192 //"PHASE 1b: Handle names without taxa ...
193 success
&= doNames(state
, additionalSourceMapping
);
196 // 2nd Round: Add ParentTaxonFk to each taxon
197 success
&= doPhase02(state
);
199 //PHASE 3: Add Rank data, KingdomFk, TypeNameFk ...
200 success
&= doPhase03(state
);
202 // 4nd Round: Add TreeIndex to each taxon
203 success
&= doPhase04(state
);
206 //"PHASE 5: Creating Inferred Synonyms...
207 success
&= doPhase05(state
, mapping
, synonymRelMapping
);
209 logger
.info("*** Finished Making " + pluralString
+ " ..." + getSuccessString(success
));
212 state
.getResult().addError("An error occurred in PesiTaxonExport.doInvoke. Success = false");
215 } catch (Exception e
) {
217 logger
.error(e
.getMessage());
218 state
.getResult().addException(e
);
223 private void initPreparedStatements(PesiExportState state
) throws SQLException
{
224 initTreeIndexStatement(state
);
225 initRankExpertsUpdateStmt(state
);
226 initRankUpdateStatement(state
);
228 initParentFkStatement(state
);
231 // Prepare TreeIndex-And-KingdomFk-Statement
232 private void initTreeIndexStatement(PesiExportState state
) throws SQLException
{
233 Connection connection
= state
.getConfig().getDestination().getConnection();
234 String parentTaxonFk_TreeIndex_KingdomFkSql
= "UPDATE Taxon SET ParentTaxonFk = ?, TreeIndex = ? WHERE TaxonId = ?";
235 parentTaxonFk_TreeIndex_KingdomFkStmt
= connection
.prepareStatement(parentTaxonFk_TreeIndex_KingdomFkSql
);
238 // Prepare TreeIndex-And-KingdomFk-Statement
239 private void initParentFkStatement(PesiExportState state
) throws SQLException
{
240 Connection connection
= state
.getConfig().getDestination().getConnection();
241 String parentTaxonFkSql
= "UPDATE Taxon SET ParentTaxonFk = ? WHERE TaxonId = ?";
242 parentTaxonFkStmt
= connection
.prepareStatement(parentTaxonFkSql
);
245 private void initRankUpdateStatement(PesiExportState state
) throws SQLException
{
246 Connection connection
= state
.getConfig().getDestination().getConnection();
247 String rankSql
= "UPDATE Taxon SET RankFk = ?, RankCache = ?, KingdomFk = ? WHERE TaxonId = ?";
248 rankUpdateStmt
= connection
.prepareStatement(rankSql
);
251 private void initRankExpertsUpdateStmt(PesiExportState state
) throws SQLException
{
252 // String sql_old = "UPDATE Taxon SET RankFk = ?, RankCache = ?, TypeNameFk = ?, KingdomFk = ?, " +
253 // "ExpertFk = ?, SpeciesExpertFk = ? WHERE TaxonId = ?";
254 //TODO handle experts GUIDs
255 Connection connection
= state
.getConfig().getDestination().getConnection();
257 String sql
= "UPDATE Taxon SET RankFk = ?, RankCache = ?, TypeNameFk = ?, KingdomFk = ? " +
258 " WHERE TaxonId = ?";
259 rankTypeExpertsUpdateStmt
= connection
.prepareStatement(sql
);
262 private boolean doPhase01(PesiExportState state
, PesiExportMapping mapping
, PesiExportMapping additionalSourceMapping
) throws SQLException
{
265 List
<TaxonBase
> list
;
266 boolean success
= true;
267 // Get the limit for objects to save within a single transaction.
268 int limit
= state
.getConfig().getLimitSave();
271 logger
.info("PHASE 1: Export Taxa...limit is " + limit
);
273 TransactionStatus txStatus
= startTransaction(true);
274 logger
.info("Started new transaction. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
276 int partitionCount
= 0;
278 logger
.info("Taking snapshot at the beginning of phase 1 of taxonExport");
279 //ProfilerController.memorySnapshot();
280 while ((list
= getNextTaxonPartition(null, limit
, partitionCount
++, null)) != null ) {
282 logger
.debug("Fetched " + list
.size() + " " + pluralString
+ ". Exporting...");
284 for (TaxonBase
<?
> taxon
: list
) {
285 doCount(count
++, modCount
, pluralString
);
286 TaxonName taxonName
= taxon
.getName();
288 TaxonName nvn
= CdmBase
.deproxy(taxonName
);
289 // System.err.println(nvn.getTitleCache());
290 if (! nvn
.isProtectedTitleCache()){
291 nvn
.setTitleCache(null, false);
293 if (! nvn
.isProtectedNameCache()){
294 nvn
.setNameCache(null, false);
296 if (! nvn
.isProtectedFullTitleCache()){
297 nvn
.setFullTitleCache(null, false);
299 if (! nvn
.isProtectedAuthorshipCache()){
300 nvn
.setAuthorshipCache(null, false);
303 if (nvn
.getRank().equals(Rank
.KINGDOM())){
304 if(taxon
.isInstanceOf(Taxon
.class)){
305 String treeIndex
= ((Taxon
)taxon
).getTaxonNodes().iterator().next().treeIndex();
306 Integer kingdomId
= PesiTransformer
.pesiKingdomMap
.get(nvn
.getGenusOrUninomial());
307 state
.getTreeIndexKingdomMap().put(treeIndex
, kingdomId
);
309 logger
.warn("Kingdom taxon is not of class Taxon but " + taxon
.getClass().getSimpleName() + ": " + nvn
.getGenusOrUninomial());
312 }catch(NullPointerException e
){
313 logger
.error(nvn
.getTitleCache() + " has no Rank!");
314 System
.err
.println(nvn
.getTitleCache() + " has no Rank!");
317 success
&= mapping
.invoke(taxon
);
319 if (nvn
.getNomenclaturalReference() != null || StringUtils
.isNotBlank(nvn
.getNomenclaturalMicroReference() )){
320 additionalSourceMapping
.invoke(taxon
);
323 validatePhaseOne(taxon
, nvn
);
329 // Commit transaction
330 commitTransaction(txStatus
);
331 logger
.debug("Committed transaction.");
332 logger
.info("Exported " + (count
- pastCount
) + " " + pluralString
+ ". Total: " + count
);
334 /*logger.warn("Taking snapshot at the end of the loop of phase 1 of taxonExport");
335 //ProfilerController.memorySnapshot();
338 txStatus
= startTransaction(true);
339 logger
.info("Started new transaction. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
342 logger
.info("No " + pluralString
+ " left to fetch.");
344 // Commit transaction
345 commitTransaction(txStatus
);
347 logger
.debug("Committed transaction.");
348 if (logger
.isDebugEnabled()){
349 logger
.debug("Taking snapshot at the end of phase 1 of taxonExport");
350 // ProfilerController.memorySnapshot();
356 private void validatePhaseOne(TaxonBase
<?
> taxon
, TaxonName taxonName
) {
358 // Check whether some rules are violated
359 nomenclaturalCode
= taxonName
.getNameType();
360 String genusOrUninomial
= taxonName
.getGenusOrUninomial();
361 String specificEpithet
= taxonName
.getSpecificEpithet();
362 String infraSpecificEpithet
= taxonName
.getInfraSpecificEpithet();
363 String infraGenericEpithet
= taxonName
.getInfraGenericEpithet();
364 Integer rankFk
= getRankFk(taxonName
, nomenclaturalCode
);
366 if (rankFk
== null) {
367 logger
.error("Rank was not determined: " + taxon
.getUuid() + " (" + taxon
.getTitleCache() + ")");
370 // Check whether infraGenericEpithet is set correctly
371 // 1. Childs of an accepted taxon of rank subgenus that are accepted taxa of rank species have to have an infraGenericEpithet
372 // 2. Grandchilds of an accepted taxon of rank subgenus that are accepted taxa of rank subspecies have to have an infraGenericEpithet
374 int ancestorLevel
= 0;
375 if (taxonName
.getRank().equals(Rank
.SUBSPECIES())) {
376 // The accepted taxon two rank levels above should be of rank subgenus
379 if (taxonName
.getRank().equals(Rank
.SPECIES())) {
380 // The accepted taxon one rank level above should be of rank subgenus
383 if (ancestorLevel
> 0) {
384 if (validateAncestorOfSpecificRank(taxon
, ancestorLevel
, Rank
.SUBGENUS())) {
385 // The child (species or subspecies) of this parent (subgenus) has to have an infraGenericEpithet
386 if (infraGenericEpithet
== null) {
387 logger
.warn("InfraGenericEpithet for (sub)species of infrageneric taxon does not exist even though it should (also valid for Botanical Names?) for: " + taxon
.getUuid() + " (" + taxon
.getTitleCache() + ")");
388 // maybe the taxon could be named here
393 if (infraGenericEpithet
== null && rankFk
.intValue() == 190) {
394 logger
.warn("InfraGenericEpithet was not determined although it should exist for rank 190: " + taxon
.getUuid() + " (" + taxon
.getTitleCache() + ")");
396 if (specificEpithet
!= null && rankFk
.intValue() < 216) {
397 logger
.warn("SpecificEpithet was determined for rank " + rankFk
+ " although it should only exist for ranks higher or equal to 220: TaxonName " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
399 if (infraSpecificEpithet
!= null && rankFk
.intValue() < 225) {
400 String message
= "InfraSpecificEpithet '" +infraSpecificEpithet
+ "' was determined for rank " + rankFk
+ " although it should only exist for ranks higher or equal to 230: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")";
401 if (StringUtils
.isNotBlank(infraSpecificEpithet
)){
402 logger
.warn(message
);
404 logger
.warn(message
);
408 if (infraSpecificEpithet
!= null && specificEpithet
== null) {
409 logger
.warn("An infraSpecificEpithet was determined, but a specificEpithet was not determined: " + taxon
.getUuid() + " (" + taxon
.getTitleCache() + ")");
411 if (genusOrUninomial
== null) {
412 logger
.warn("GenusOrUninomial was not determined: " + taxon
.getUuid() + " (" + taxon
.getTitleCache() + ")");
418 * 2nd Round: Add ParentTaxonFk to each taxon and add Biota if not exists
422 private boolean doPhase02(PesiExportState state
) {
425 boolean success
= true;
426 if (! state
.getConfig().isDoParentAndBiota()){
427 logger
.info ("Ignore PHASE 2: Make ParentFk and Biota...");
433 // Get the limit for objects to save within a single transaction.
434 int limit
= state
.getConfig().getLimitSave();
438 logger
.info("PHASE 2: Make ParentFk and Biota ... limit is " + limit
);
440 TransactionStatus txStatus
= startTransaction(true);
441 int partitionCount
= 0;
443 // ProfilerController.memorySnapshot();
444 while ((list
= getNextTaxonPartition(Taxon
.class, limit
, partitionCount
++, null)) != null ) {
446 logger
.info("Fetched " + list
.size() + " " + pluralString
+ ". Exporting...");
447 for (Taxon taxon
: list
) {
448 for (TaxonNode node
: taxon
.getTaxonNodes()){
449 doCount(count
++, modCount
, pluralString
);
450 TaxonNode parentNode
= node
.getParent();
451 if (parentNode
!= null && parentNode
.getTaxon() != null){ //new root node handling requires has root taxon with taxon == null
452 int childId
= state
.getDbId( taxon
);
453 int parentId
= state
.getDbId(parentNode
.getTaxon());
454 success
&= invokeParentTaxonFk(parentId
, childId
);
459 // Commit transaction
460 commitTransaction(txStatus
);
461 logger
.info("Exported " + (count
- pastCount
) + " " + pluralString
+ ". Total: " + count
);
464 txStatus
= startTransaction(true);
465 logger
.info("Started new transaction. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
468 logger
.info("No " + pluralString
+ " left to fetch.");
470 // Commit transaction
471 commitTransaction(txStatus
);
477 * Inserts the Biota Taxon if not yet exists.
479 * @throws SQLException
481 private void insertBiota(PesiExportState state
) {
483 ResultSet rs
= state
.getConfig().getDestination().getResultSet("SELECT * FROM Taxon WHERE GenusOrUninomial = 'Biota' ");
484 if (rs
.next() == false){
485 int biotaId
= state
.getConfig().getNameIdStart() -1 ;
486 String sqlInsertBiota
= "INSERT INTO Taxon (TaxonId, KingdomFk, RankFk, RankCache, GenusOrUninomial, WebSearchName, WebShowName, FullName, DisplayName, TaxonStatusFk, TaxonStatusCache) " +
487 " VALUES (" + biotaId
+ ", 0, 0, 'Superdomain', 'Biota', 'Biota', '<i>Biota</i>', 'Biota', '<i>Biota</i>', 1 , 'accepted')";
488 state
.getConfig().getDestination().update(sqlInsertBiota
);
491 } catch (SQLException e
) {
492 logger
.warn ("Biota could not be requested or inserted");
496 // 4th round: Add TreeIndex to each taxon
497 private boolean doPhase04(PesiExportState state
) {
498 boolean success
= true;
500 logger
.info("PHASE 4: Make TreeIndex ... ");
502 //TODO test if possible to move to phase 02
503 String sql
= " UPDATE Taxon SET ParentTaxonFk = (SELECT TaxonId FROM Taxon WHERE RankFk = 0) " +
504 " WHERE (RankFk = 10) and TaxonStatusFk = 1 ";
505 state
.getConfig().getDestination().update(sql
);
507 state
.getConfig().getDestination().update("EXEC dbo.recalculateallstoredpaths");
514 // // 2nd Round: Add ParentTaxonFk, TreeIndex to each Taxon
515 // private boolean doPhase02_OLD(PesiExportState state) {
516 // boolean success = true;
517 // boolean includeUnpublished = false;
518 // if (! state.getConfig().isDoTreeIndex()){
519 // logger.info ("Ignore PHASE 2: ParentTaxonFk and TreeIndex");
523 // List<Classification> classificationList = null;
524 // logger.info("PHASE 2: Add ParenTaxonFk and TreeIndex...");
526 // // Specify starting ranks for tree traversing
527 // rankList.add(Rank.KINGDOM());
528 // rankList.add(Rank.GENUS());
530 // // Specify where to stop traversing (value) when starting at a specific Rank (key)
531 // rank2endRankMap.put(Rank.GENUS(), null); // Since NULL does not match an existing Rank, traverse all the way down to the leaves
532 // rank2endRankMap.put(Rank.KINGDOM(), Rank.GENUS()); // excludes rank genus
534 // StringBuffer treeIndex = new StringBuffer();
536 // // Retrieve list of classifications
537 // TransactionStatus txStatus = startTransaction(true);
538 // logger.info("Started transaction for parentFk and treeIndex. Fetching all classifications...");
539 // classificationList = getClassificationService().listClassifications(null, 0, null, null);
540 // commitTransaction(txStatus);
541 // logger.debug("Committed transaction.");
543 // logger.info("Fetched " + classificationList.size() + " classification(s).");
545 // setTreeIndexAnnotationType(getAnnotationType(uuidTreeIndex, "TreeIndex", "TreeIndex", "TI"));
546 // List<TaxonNode> rankSpecificRootNodes;
547 // for (Classification classification : classificationList) {
548 // for (Rank rank : rankList) {
550 // txStatus = startTransaction(true);
551 // logger.info("Started transaction to fetch all rootNodes specific to Rank " + rank.getLabel() + " ...");
553 // rankSpecificRootNodes = getClassificationService().listRankSpecificRootNodes(classification,
554 // null, rank, includeUnpublished, null, null, null);
555 // logger.info("Fetched " + rankSpecificRootNodes.size() + " RootNodes for Rank " + rank.getLabel());
557 // commitTransaction(txStatus);
558 // logger.debug("Committed transaction.");
560 // for (TaxonNode rootNode : rankSpecificRootNodes) {
561 // txStatus = startTransaction(false);
562 // Rank endRank = rank2endRankMap.get(rank);
563 // if (endRank != null) {
564 // logger.debug("Started transaction to traverse childNodes of rootNode (" + rootNode.getUuid() + ") till Rank " + endRank.getLabel() + " ...");
566 // logger.debug("Started transaction to traverse childNodes of rootNode (" + rootNode.getUuid() + ") till leaves are reached ...");
569 // TaxonNode newNode = getTaxonNodeService().load(rootNode.getUuid());
571 // if (isPesiTaxon(newNode.getTaxon())){
572 // TaxonNode parentNode = newNode.getParent();
573 // if (rank.equals(Rank.KINGDOM())) {
574 // treeIndex = new StringBuffer();
575 // treeIndex.append("#");
577 // // Get treeIndex from parentNode
578 // if (parentNode != null) {
579 // boolean annotationFound = false;
580 // Set<Annotation> annotations = parentNode.getAnnotations();
581 // for (Annotation annotation : annotations) {
582 // AnnotationType annotationType = annotation.getAnnotationType();
583 // if (annotationType != null && annotationType.equals(getTreeIndexAnnotationType())) {
584 // treeIndex = new StringBuffer(CdmUtils.Nz(annotation.getText()));
585 // annotationFound = true;
586 // // logger.error("treeIndex: " + treeIndex);
590 // if (!annotationFound) {
591 // // This should not happen because it means that the treeIndex was not set correctly as an annotation to parentNode
592 // logger.error("TreeIndex could not be read from annotation of TaxonNode: " + parentNode.getUuid() + ", Taxon: " + parentNode.getTaxon().getUuid());
593 // treeIndex = new StringBuffer();
594 // treeIndex.append("#");
597 // // TreeIndex could not be determined, but it's unclear how to proceed to generate a correct treeIndex if the parentNode is NULL
598 // logger.error("ParentNode for RootNode is NULL. TreeIndex could not be determined: " + newNode.getUuid());
599 // treeIndex = new StringBuffer(); // This just prevents growing of the treeIndex in a wrong manner
600 // treeIndex.append("#");
603 // nomenclaturalCode = newNode.getTaxon().getName().getNameType();
604 // kingdomFk = PesiTransformer.nomenclaturalCode2Kingdom(nomenclaturalCode);
605 // traverseTree(newNode, parentNode, treeIndex, endRank, state);
608 // logger.debug("Taxon is not a PESI taxon: " + newNode.getTaxon().getUuid());
614 // commitTransaction(txStatus);
615 // logger.debug("Committed transaction.");
616 // } catch (Exception e) {
617 // logger.error(e.getMessage());
618 // e.printStackTrace();
622 // rankSpecificRootNodes = null;
627 // logger.warn("Taking snapshot at the end of phase 2 of taxonExport");
628 // //ProfilerController.memorySnapshot();
632 //PHASE 3: Add Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk...
633 private boolean doPhase03(PesiExportState state
) {
636 boolean success
= true;
637 if (! state
.getConfig().isDoTreeIndex()){
638 logger
.info ("Ignore PHASE 3: Add Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk...");
641 // Get the limit for objects to save within a single transaction.
642 int limit
= state
.getConfig().getLimitSave();
644 List
<TaxonBase
> list
;
645 logger
.info("PHASE 3: Add Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk...");
646 // Be sure to add rank information, KingdomFk, TypeNameFk, expertFk and speciesExpertFk to every taxonName
649 TransactionStatus txStatus
= startTransaction(true);
650 logger
.info("Started new transaction for rank, kingdom, typeName, expertFk and speciesExpertFK. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
651 int partitionCount
= 0;
652 while ((list
= getNextTaxonPartition(TaxonBase
.class, limit
, partitionCount
++, null)) != null) {
654 logger
.debug("Fetched " + list
.size() + " " + pluralString
+ ". Exporting...");
655 for (TaxonBase
<?
> taxon
: list
) {
656 TaxonName taxonName
= CdmBase
.deproxy(taxon
.getName());
657 // Determine expertFk
658 // Integer expertFk = makeExpertFk(state, taxonName);
660 // // Determine speciesExpertFk
661 // Integer speciesExpertFk = makeSpeciesExpertFk(state, taxonName);
663 doCount(count
++, modCount
, pluralString
);
664 Integer typeNameFk
= getTypeNameFk(taxonName
, state
);
665 Integer kingdomFk
= findKingdomIdFromTreeIndex(taxon
, state
);
666 // PesiTransformer.nomenClaturalCode2Kingdom(nomenclaturalCode);
668 //TODO why are expertFks needed? (Andreas M.)
669 // if (expertFk != null || speciesExpertFk != null) {
670 invokeRankDataAndTypeNameFkAndKingdomFk(taxonName
, nomenclaturalCode
, state
.getDbId(taxon
),
671 typeNameFk
, kingdomFk
, state
);
675 // Commit transaction
676 commitTransaction(txStatus
);
677 logger
.debug("Committed transaction.");
678 logger
.info("Exported " + (count
- pastCount
) + " " + pluralString
+ ". Total: " + count
);
682 txStatus
= startTransaction(true);
683 logger
.info("Started new transaction for rank, kingdom, typeName, expertFk and speciesExpertFK. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
685 logger
.info("No " + pluralString
+ " left to fetch.");
687 // Commit transaction
688 commitTransaction(txStatus
);
690 logger
.debug("Committed transaction.");
691 logger
.debug("Try to take snapshot at the end of phase 3 of taxonExport, number of partitions: " + partitionCount
);
692 //ProfilerController.memorySnapshot();
696 private Integer
findKingdomIdFromTreeIndex(TaxonBase
<?
> taxonBase
,PesiExportState state
) {
698 if (taxonBase
instanceof Synonym
){
699 taxon
= ((Synonym
) taxonBase
).getAcceptedTaxon();
701 taxon
= (Taxon
)taxonBase
;
704 Set
<TaxonNode
> nodes
= taxon
.getTaxonNodes();
706 logger
.warn("The taxon has more then 1 taxon node: " + taxon
.getTitleCache() + ". Take arbitrary one.");
708 if (!nodes
.isEmpty()){
709 String treeIndex
= nodes
.iterator().next().treeIndex();
711 Pattern pattern
= Pattern
.compile("#t[0-9]+#([0-9]+#){3}");
712 Matcher matcher
= pattern
.matcher(treeIndex
);
713 Integer kingdomID
= null;
715 String treeIndexKingdom
= matcher
.group(0);
716 kingdomID
= state
.getTreeIndexKingdomMap().get(treeIndexKingdom
);
718 pattern
= Pattern
.compile("#t[0-9]+#([0-9]+#){2}");
719 matcher
= pattern
.matcher(treeIndex
);
721 String treeIndexKingdom
= matcher
.group(0);
722 kingdomID
= state
.getTreeIndexKingdomMap().get(treeIndexKingdom
);
725 if(kingdomID
== null){
726 logger
.warn("Kingdom could not be defined for treeindex " + treeIndex
);
730 logger
.warn("The taxon has no nodes: " + taxon
.getTitleCache() + ". The kingdom is taken from the nomenclatural code: " + PesiTransformer
.nomenclaturalCode2Kingdom(nomenclaturalCode
));
731 return PesiTransformer
.nomenclaturalCode2Kingdom(nomenclaturalCode
);
734 logger
.warn("Taxon is synonym with no accepted taxon attached: " + taxonBase
.getTitleCache() + ". The kingdom is taken from the nomenclatural code: " + PesiTransformer
.nomenclaturalCode2Kingdom(nomenclaturalCode
) );
735 return PesiTransformer
.nomenclaturalCode2Kingdom(nomenclaturalCode
);
739 // "PHASE 5: Creating Inferred Synonyms..."
740 private boolean doPhase05(PesiExportState state
, PesiExportMapping mapping
, PesiExportMapping synRelMapping
) {
743 boolean success
= true;
744 // Get the limit for objects to save within a single transaction.
745 if (! state
.getConfig().isDoInferredSynonyms()){
746 logger
.info ("Ignore PHASE 5: Creating Inferred Synonyms...");
750 int limit
= state
.getConfig().getLimitSave();
751 // Create inferred synonyms for accepted taxa
752 logger
.info("PHASE 5: Creating Inferred Synonyms...");
754 // Determine the count of elements in data warehouse database table Taxon
755 currentTaxonId
= determineTaxonCount(state
);
760 int pageSize
= limit
/10;
762 String inferredSynonymPluralString
= "Inferred Synonyms";
765 TransactionStatus txStatus
= startTransaction(true);
766 logger
.info("Started new transaction. Fetching some " + parentPluralString
+ " first (max: " + limit
+ ") ...");
767 List
<TaxonBase
> taxonList
= null;
769 while ((taxonList
= getTaxonService().listTaxaByName(Taxon
.class, "*", "*", "*", "*", "*", Rank
.SPECIES(), pageSize
, pageNumber
)).size() > 0) {
771 Map
<Integer
, TaxonName
> inferredSynonymsDataToBeSaved
= new HashMap
<>();
773 logger
.info("Fetched " + taxonList
.size() + " " + parentPluralString
+ ". Exporting...");
774 inferredSynonymsDataToBeSaved
.putAll(createInferredSynonymsForTaxonList(state
, mapping
,
775 synRelMapping
, taxonList
));
777 doCount(count
+= taxonList
.size(), modCount
, inferredSynonymPluralString
);
778 // Commit transaction
779 commitTransaction(txStatus
);
780 logger
.debug("Committed transaction.");
781 logger
.info("Exported " + (taxonList
.size()) + " " + inferredSynonymPluralString
+ ". Total: " + count
);
784 // Save Rank Data and KingdomFk for inferred synonyms
785 for (Integer taxonFk
: inferredSynonymsDataToBeSaved
.keySet()) {
786 invokeRankDataAndKingdomFk(inferredSynonymsDataToBeSaved
.get(taxonFk
), nomenclaturalCode
, taxonFk
, kingdomFk
, state
);
790 txStatus
= startTransaction(true);
791 logger
.info("Started new transaction. Fetching some " + parentPluralString
+ " first (max: " + limit
+ ") ...");
793 // Increment pageNumber
797 while ((taxonList
= getTaxonService().listTaxaByName(Taxon
.class, "*", "*", "*", "*", "*", Rank
.SUBSPECIES(), pageSize
, pageNumber
)).size() > 0) {
798 Map
<Integer
, TaxonName
> inferredSynonymsDataToBeSaved
= new HashMap
<>();
800 logger
.info("Fetched " + taxonList
.size() + " " + parentPluralString
+ ". Exporting...");
801 inferredSynonymsDataToBeSaved
.putAll(createInferredSynonymsForTaxonList(state
, mapping
,
802 synRelMapping
, taxonList
));
804 doCount(count
+= taxonList
.size(), modCount
, inferredSynonymPluralString
);
805 // Commit transaction
806 commitTransaction(txStatus
);
807 logger
.debug("Committed transaction.");
808 logger
.info("Exported " + taxonList
.size()+ " " + inferredSynonymPluralString
+ ". Total: " + count
);
811 // Save Rank Data and KingdomFk for inferred synonyms
812 for (Integer taxonFk
: inferredSynonymsDataToBeSaved
.keySet()) {
813 invokeRankDataAndKingdomFk(inferredSynonymsDataToBeSaved
.get(taxonFk
), nomenclaturalCode
, taxonFk
, kingdomFk
, state
);
817 txStatus
= startTransaction(true);
818 logger
.info("Started new transaction. Fetching some " + parentPluralString
+ " first (max: " + limit
+ ") ...");
820 // Increment pageNumber
822 inferredSynonymsDataToBeSaved
= null;
824 if (taxonList
.size() == 0) {
825 logger
.info("No " + parentPluralString
+ " left to fetch.");
829 // logger.warn("Taking snapshot at the end of phase 5 of taxonExport");
830 // ProfilerController.memorySnapshot();
832 // Commit transaction
833 commitTransaction(txStatus
);
835 logger
.debug("Taking snapshot at the end of phase 5 after gc() of taxonExport");
836 //ProfilerController.memorySnapshot();
837 logger
.debug("Committed transaction.");
844 * @param synRelMapping
845 * @param currentTaxonId
847 * @param inferredSynonymsDataToBeSaved
850 private Map
<Integer
, TaxonName
> createInferredSynonymsForTaxonList(PesiExportState state
,
851 PesiExportMapping mapping
, PesiExportMapping synRelMapping
, List
<TaxonBase
> taxonList
) {
854 Classification classification
= null;
855 List
<Synonym
> inferredSynonyms
= null;
856 boolean localSuccess
= true;
858 Map
<Integer
, TaxonName
> inferredSynonymsDataToBeSaved
= new HashMap
<>();
860 for (TaxonBase
<?
> taxonBase
: taxonList
) {
862 if (taxonBase
.isInstanceOf(Taxon
.class)) { // this should always be the case since we should have fetched accepted taxon only, but you never know...
863 acceptedTaxon
= CdmBase
.deproxy(taxonBase
, Taxon
.class);
864 TaxonName taxonName
= acceptedTaxon
.getName();
866 if (taxonName
.isZoological()) {
867 nomenclaturalCode
= taxonName
.getNameType();
868 kingdomFk
= PesiTransformer
.nomenclaturalCode2Kingdom(nomenclaturalCode
);
870 Set
<TaxonNode
> taxonNodes
= acceptedTaxon
.getTaxonNodes();
871 TaxonNode singleNode
= null;
873 if (taxonNodes
.size() > 0) {
874 // Determine the classification of the current TaxonNode
876 singleNode
= taxonNodes
.iterator().next();
877 if (singleNode
!= null) {
878 classification
= singleNode
.getClassification();
880 logger
.error("A TaxonNode belonging to this accepted Taxon is NULL: " + acceptedTaxon
.getUuid() + " (" + acceptedTaxon
.getTitleCache() +")");
883 // Classification could not be determined directly from this TaxonNode
884 // The stored classification from another TaxonNode is used. It's a simple, but not a failsafe fallback solution.
885 if (taxonNodes
.size() == 0) {
886 //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");
890 if (classification
!= null) {
892 TaxonName name
= acceptedTaxon
.getName();
893 //if (name.isSpecies() || name.isInfraSpecific()){
894 inferredSynonyms
= getTaxonService().createAllInferredSynonyms(acceptedTaxon
, classification
, true);
896 // inferredSynonyms = getTaxonService().createInferredSynonyms(classification, acceptedTaxon, SynonymType.INFERRED_GENUS_OF());
897 if (inferredSynonyms
!= null) {
898 for (Synonym synonym
: inferredSynonyms
) {
899 // TaxonName synonymName = synonym.getName();
900 MarkerType markerType
=getUuidMarkerType(PesiTransformer
.uuidMarkerGuidIsMissing
, state
);
901 synonym
.addMarker(Marker
.NewInstance(markerType
, true));
902 // Both Synonym and its TaxonName have no valid Id yet
903 synonym
.setId(currentTaxonId
++);
906 localSuccess
&= mapping
.invoke(synonym
);
907 //get SynonymRelationship and export
908 if (synonym
.getAcceptedTaxon() == null ){
909 IdentifiableSource source
= synonym
.getSources().iterator().next();
910 if (source
.getIdNamespace().contains("Potential combination")){
911 acceptedTaxon
.addSynonym(synonym
, SynonymType
.POTENTIAL_COMBINATION_OF());
912 logger
.error(synonym
.getTitleCache() + " is not attached to " + acceptedTaxon
.getTitleCache() + " type is set to potential combination");
913 } else if (source
.getIdNamespace().contains("Inferred Genus")){
914 acceptedTaxon
.addSynonym(synonym
, SynonymType
.INFERRED_GENUS_OF());
915 logger
.error(synonym
.getTitleCache() + " is not attached to " + acceptedTaxon
.getTitleCache() + " type is set to inferred genus");
916 } else if (source
.getIdNamespace().contains("Inferred Epithet")){
917 acceptedTaxon
.addSynonym(synonym
, SynonymType
.INFERRED_EPITHET_OF());
918 logger
.error(synonym
.getTitleCache() + " is not attached to " + acceptedTaxon
.getTitleCache() + " type is set to inferred epithet");
920 acceptedTaxon
.addSynonym(synonym
, SynonymType
.INFERRED_SYNONYM_OF());
921 logger
.error(synonym
.getTitleCache() + " is not attached to " + acceptedTaxon
.getTitleCache() + " type is set to inferred synonym");
924 localSuccess
&= synRelMapping
.invoke(synonym
);
926 logger
.error("Synonym relationship export failed " + synonym
.getTitleCache() + " accepted taxon: " + acceptedTaxon
.getUuid() + " (" + acceptedTaxon
.getTitleCache()+")");
929 localSuccess
&= synRelMapping
.invoke(synonym
);
931 logger
.error("Synonym relationship export failed " + synonym
.getTitleCache() + " accepted taxon: " + acceptedTaxon
.getUuid() + " (" + acceptedTaxon
.getTitleCache()+")");
933 logger
.info("Synonym relationship successfully exported: " + synonym
.getTitleCache() + " " +acceptedTaxon
.getUuid() + " (" + acceptedTaxon
.getTitleCache()+")");
937 inferredSynonymsDataToBeSaved
.put(synonym
.getId(), synonym
.getName());
941 logger
.error(e
.getMessage());
945 logger
.error("Classification is NULL. Inferred Synonyms could not be created for this Taxon: " + acceptedTaxon
.getUuid() + " (" + acceptedTaxon
.getTitleCache() + ")");
948 // logger.error("TaxonName is not a ZoologicalName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
951 logger
.error("This TaxonBase is not a Taxon even though it should be: " + taxonBase
.getUuid() + " (" + taxonBase
.getTitleCache() + ")");
954 return inferredSynonymsDataToBeSaved
;
959 * Handles names that do not appear in taxa
963 private boolean doNames(PesiExportState state
, PesiExportMapping additionalSourceMapping
) throws SQLException
{
965 boolean success
= true;
966 if (! state
.getConfig().isDoPureNames()){
967 logger
.info ("Ignore PHASE 1b: PureNames");
972 PesiExportMapping mapping
= getPureNameMapping(state
);
973 mapping
.initialize(state
);
976 List
<TaxonName
> list
;
978 // Get the limit for objects to save within a single transaction.
979 int limit
= state
.getConfig().getLimitSave();
981 logger
.info("PHASE 1b: Export Pure Names ...");
983 TransactionStatus txStatus
= startTransaction(true);
984 logger
.info("Started new transaction for Pure Names. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
986 int partitionCount
= 0;
987 while ((list
= getNextPureNamePartition(null, limit
, partitionCount
++)) != null ) {
989 logger
.info("Fetched " + list
.size() + " names without taxa. Exporting...");
990 for (TaxonName taxonName
: list
) {
991 doCount(count
++, modCount
, pluralString
);
992 success
&= mapping
.invoke(taxonName
);
994 if (taxonName
.getNomenclaturalReference() != null || StringUtils
.isNotBlank(taxonName
.getNomenclaturalMicroReference() )){
995 additionalSourceMapping
.invoke(taxonName
);
999 // Commit transaction
1000 commitTransaction(txStatus
);
1001 logger
.debug("Committed transaction.");
1002 logger
.info("Exported " + (count
- pastCount
) + " " + pluralString
+ ". Total: " + count
);
1005 // Start transaction
1006 txStatus
= startTransaction(true);
1007 logger
.info("Started new transaction for PureNames. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
1009 logger
.info("No " + pluralString
+ " left to fetch.");
1011 // Commit transaction
1012 commitTransaction(txStatus
);
1013 logger
.debug("Committed transaction.");
1014 } catch (Exception e
) {
1015 logger
.error("Error occurred in pure name export");
1016 e
.printStackTrace();
1023 * Determines the current number of entries in the DataWarehouse database table <code>Taxon</code>.
1024 * @param state The {@link PesiExportState PesiExportState}.
1025 * @return The count.
1027 private Integer
determineTaxonCount(PesiExportState state
) {
1028 Integer result
= null;
1029 PesiExportConfigurator pesiConfig
= state
.getConfig();
1032 Source destination
= pesiConfig
.getDestination();
1033 sql
= "SELECT max(taxonId) FROM Taxon";
1034 destination
.setQuery(sql
);
1035 ResultSet resultSet
= destination
.getResultSet();
1038 result
= resultSet
.getInt(1);
1039 } catch (SQLException e
) {
1040 logger
.error("TaxonCount could not be determined: " + e
.getMessage());
1041 e
.printStackTrace();
1048 * Checks whether a parent at specific level has a specific Rank.
1049 * @param taxonName A {@link TaxonNameBase TaxonName}.
1050 * @param level The ancestor level.
1051 * @param ancestorRank The ancestor rank.
1052 * @return Whether a parent at a specific level has a specific Rank.
1054 private boolean validateAncestorOfSpecificRank(TaxonBase
<?
> taxonBase
, int level
, Rank ancestorRank
) {
1055 boolean result
= false;
1056 TaxonNode parentNode
= null;
1057 if (taxonBase
.isInstanceOf(Taxon
.class)){
1058 Taxon taxon
= CdmBase
.deproxy(taxonBase
, Taxon
.class);
1059 // Get ancestor Taxon via TaxonNode
1060 Set
<TaxonNode
> taxonNodes
= taxon
.getTaxonNodes();
1061 if (taxonNodes
.size() == 1) {
1062 TaxonNode taxonNode
= taxonNodes
.iterator().next();
1063 if (taxonNode
!= null) {
1064 for (int i
= 0; i
< level
; i
++) {
1065 if (taxonNode
!= null) {
1066 taxonNode
= taxonNode
.getParent();
1069 parentNode
= taxonNode
;
1071 } else if (taxonNodes
.size() > 1) {
1072 logger
.error("This taxon has " + taxonNodes
.size() + " taxonNodes: " + taxon
.getUuid() + " (" + taxon
.getTitleCache() + ")");
1076 if (parentNode
!= null) {
1077 TaxonNode node
= CdmBase
.deproxy(parentNode
, TaxonNode
.class);
1078 Taxon parentTaxon
= node
.getTaxon();
1079 if (parentTaxon
!= null) {
1080 TaxonName parentTaxonName
= parentTaxon
.getName();
1081 if (parentTaxonName
!= null && parentTaxonName
.getRank().equals(ancestorRank
)) {
1084 } else if (parentNode
.treeIndex().matches("#t\\d+#\\d+#")) {
1085 //do nothing (is root node)
1087 logger
.error("This TaxonNode has no Taxon: " + node
.getUuid());
1094 * Returns the AnnotationType for a given UUID.
1095 * @param uuid The Annotation UUID.
1096 * @param label The Annotation label.
1097 * @param text The Annotation text.
1098 * @param labelAbbrev The Annotation label abbreviation.
1099 * @return The AnnotationType.
1101 protected AnnotationType
getAnnotationType(UUID uuid
, String label
, String text
, String labelAbbrev
){
1102 AnnotationType annotationType
= (AnnotationType
)getTermService().find(uuid
);
1103 if (annotationType
== null) {
1104 annotationType
= AnnotationType
.NewInstance(label
, text
, labelAbbrev
);
1105 annotationType
.setUuid(uuid
);
1106 // annotationType.setVocabulary(AnnotationType.EDITORIAL().getVocabulary());
1107 getTermService().save(annotationType
);
1109 return annotationType
;
1113 * Traverses the classification recursively and stores determined values for every Taxon.
1114 * @param childNode The {@link TaxonNode TaxonNode} to process.
1115 * @param parentNode The parent {@link TaxonNode TaxonNode} of the childNode.
1116 * @param treeIndex The TreeIndex at the current level.
1117 * @param fetchLevel Rank to stop fetching at.
1118 * @param state The {@link PesiExportState PesiExportState}.
1120 private void traverseTree(TaxonNode childNode
, TaxonNode parentNode
, StringBuffer treeIndex
, Rank fetchLevel
, PesiExportState state
) {
1121 // Traverse all branches from this childNode until specified fetchLevel is reached.
1122 StringBuffer localTreeIndex
= new StringBuffer(treeIndex
);
1123 Taxon childTaxon
= childNode
.getTaxon();
1124 if (childTaxon
!= null) {
1125 if (isPesiTaxon(childTaxon
)){
1126 Integer taxonId
= state
.getDbId(childTaxon
);
1127 TaxonName childName
= childTaxon
.getName();
1128 if (taxonId
!= null) {
1129 Rank childRank
= childName
.getRank();
1130 if (childRank
!= null) {
1131 if (! childRank
.equals(fetchLevel
)) {
1133 localTreeIndex
.append(taxonId
+ "#");
1135 saveData(childNode
, parentNode
, localTreeIndex
, state
, taxonId
);
1137 // Store treeIndex as annotation for further use
1138 Annotation annotation
= Annotation
.NewInstance(localTreeIndex
.toString(), getTreeIndexAnnotationType(), Language
.DEFAULT());
1139 childNode
.addAnnotation(annotation
);
1141 for (TaxonNode newNode
: childNode
.getChildNodes()) {
1142 if (newNode
.getTaxon() != null && isPesiTaxon(newNode
.getTaxon())){
1143 traverseTree(newNode
, childNode
, localTreeIndex
, fetchLevel
, state
);
1148 // logger.debug("Target Rank " + fetchLevel.getLabel() + " reached");
1152 logger
.error("Rank is NULL. FetchLevel can not be checked: " + childName
.getUuid() + " (" + childName
.getTitleCache() + ")");
1155 logger
.error("Taxon can not be found in state: " + childTaxon
.getUuid() + " (" + childTaxon
.getTitleCache() + ")");
1158 if (logger
.isDebugEnabled()){
1159 logger
.debug("Taxon is not a PESI taxon: " + childTaxon
.getUuid());
1163 logger
.error("Taxon is NULL for TaxonNode: " + childNode
.getUuid());
1168 * Stores values in database for every recursive round.
1169 * @param childNode The {@link TaxonNode TaxonNode} to process.
1170 * @param parentNode The parent {@link TaxonNode TaxonNode} of the childNode.
1171 * @param treeIndex The TreeIndex at the current level.
1172 * @param state The {@link PesiExportState PesiExportState}.
1173 * @param currentTaxonFk The TaxonFk to store the values for.
1175 private void saveData(TaxonNode childNode
, TaxonNode parentNode
, StringBuffer treeIndex
, PesiExportState state
, Integer currentTaxonFk
) {
1176 // We are differentiating kingdoms by the nomenclatural code for now.
1177 // This needs to be handled in a better way as soon as we know how to differentiate between more kingdoms.
1178 Taxon childTaxon
= childNode
.getTaxon();
1179 if (isPesiTaxon(childTaxon
)) {
1180 TaxonBase
<?
> parentTaxon
= null;
1181 if (parentNode
!= null) {
1182 parentTaxon
= parentNode
.getTaxon();
1185 invokeParentTaxonFkAndTreeIndex(state
.getDbId(parentTaxon
), currentTaxonFk
, treeIndex
);
1190 * Inserts values into the Taxon database table.
1192 * @param taxonName The {@link TaxonNameBase TaxonName}.
1193 * @param state The {@link PesiExportState PesiExportState}.
1194 * @param stmt The prepared statement.
1195 * @return Whether save was successful or not.
1197 protected boolean invokeParentTaxonFkAndTreeIndex(Integer parentTaxonFk
, Integer currentTaxonFk
, StringBuffer treeIndex
) {
1199 if (parentTaxonFk
!= null) {
1200 parentTaxonFk_TreeIndex_KingdomFkStmt
.setInt(1, parentTaxonFk
);
1202 parentTaxonFk_TreeIndex_KingdomFkStmt
.setObject(1, null);
1205 if (treeIndex
!= null) {
1206 parentTaxonFk_TreeIndex_KingdomFkStmt
.setString(2, treeIndex
.toString());
1208 parentTaxonFk_TreeIndex_KingdomFkStmt
.setObject(2, null);
1211 if (currentTaxonFk
!= null) {
1212 parentTaxonFk_TreeIndex_KingdomFkStmt
.setInt(3, currentTaxonFk
);
1214 parentTaxonFk_TreeIndex_KingdomFkStmt
.setObject(3, null);
1217 parentTaxonFk_TreeIndex_KingdomFkStmt
.executeUpdate();
1219 } catch (SQLException e
) {
1220 logger
.error("ParentTaxonFk (" + (parentTaxonFk
==null?
"-":parentTaxonFk
) + ") and TreeIndex could not be inserted into database for taxon "+ (currentTaxonFk
== null?
"-" :currentTaxonFk
) + ": " + e
.getMessage());
1221 e
.printStackTrace();
1226 protected boolean invokeParentTaxonFk(Integer parentId
, Integer childId
) {
1228 parentTaxonFkStmt
.setInt(1, parentId
);
1229 parentTaxonFkStmt
.setInt(2, childId
);
1230 parentTaxonFkStmt
.executeUpdate();
1232 } catch (SQLException e
) {
1233 logger
.warn("ParentTaxonFk (" + (parentId
==null?
"-":parentId
) + ") could not be inserted into database "
1234 + "for taxon "+ (childId
== null?
"-" :childId
) + ": " + e
.getMessage());
1235 e
.printStackTrace();
1242 * Inserts Rank data and KingdomFk into the Taxon database table.
1243 * @param taxonName The {@link TaxonNameBase TaxonName}.
1244 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
1245 * @param taxonFk The TaxonFk to store the values for.
1247 * @param kindomFk The KingdomFk.
1248 * @return Whether save was successful or not.
1250 private boolean invokeRankDataAndKingdomFk(TaxonName taxonName
, NomenclaturalCode nomenclaturalCode
, Integer taxonFk
, Integer kingdomFk
, PesiExportState state
) {
1252 Integer rankFk
= getRankFk(taxonName
, nomenclaturalCode
);
1253 if (rankFk
!= null) {
1254 rankUpdateStmt
.setInt(1, rankFk
);
1256 rankUpdateStmt
.setObject(1, null);
1259 String rankCache
= getRankCache(taxonName
, nomenclaturalCode
, state
);
1260 if (rankCache
!= null) {
1261 rankUpdateStmt
.setString(2, rankCache
);
1263 rankUpdateStmt
.setObject(2, null);
1266 if (kingdomFk
!= null) {
1268 rankUpdateStmt
.setInt(3, kingdomFk
);
1270 rankUpdateStmt
.setObject(3, null);
1273 if (taxonFk
!= null) {
1274 rankUpdateStmt
.setInt(4, taxonFk
);
1276 rankUpdateStmt
.setObject(4, null);
1279 rankUpdateStmt
.executeUpdate();
1281 } catch (SQLException e
) {
1282 logger
.error("Data (RankFk, RankCache, KingdomFk) could not be inserted into database: " + e
.getMessage());
1283 e
.printStackTrace();
1289 * Inserts Rank data, TypeNameFk, KingdomFk, expertFk and speciesExpertFk into the Taxon database table.
1290 * @param taxonName The {@link TaxonNameBase TaxonName}.
1291 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
1292 * @param taxonFk The TaxonFk to store the values for.
1293 * @param typeNameFk The TypeNameFk.
1295 * @param kindomFk The KingdomFk.
1296 * @param expertFk The ExpertFk.
1297 * @param speciesExpertFk The SpeciesExpertFk.
1298 * @return Whether save was successful or not.
1300 private boolean invokeRankDataAndTypeNameFkAndKingdomFk(TaxonName taxonName
, NomenclaturalCode nomenclaturalCode
,
1301 Integer taxonFk
, Integer typeNameFk
, Integer kingdomFk
, PesiExportState state
) {
1304 Integer rankFk
= getRankFk(taxonName
, nomenclaturalCode
);
1305 if (rankFk
!= null) {
1306 rankTypeExpertsUpdateStmt
.setInt(index
++, rankFk
);
1308 rankTypeExpertsUpdateStmt
.setObject(index
++, null);
1311 String rankCache
= getRankCache(taxonName
, nomenclaturalCode
, state
);
1312 if (rankCache
!= null) {
1313 rankTypeExpertsUpdateStmt
.setString(index
++, rankCache
);
1315 rankTypeExpertsUpdateStmt
.setObject(index
++, null);
1318 if (typeNameFk
!= null) {
1319 rankTypeExpertsUpdateStmt
.setInt(index
++, typeNameFk
);
1321 rankTypeExpertsUpdateStmt
.setObject(index
++, null);
1324 if (kingdomFk
!= null) {
1325 rankTypeExpertsUpdateStmt
.setInt(index
++, kingdomFk
);
1327 rankTypeExpertsUpdateStmt
.setObject(index
++, null);
1330 // if (expertFk != null) {
1331 // rankTypeExpertsUpdateStmt.setInt(5, expertFk);
1333 // rankTypeExpertsUpdateStmt.setObject(5, null);
1336 // //TODO handle experts GUIDS
1337 // if (speciesExpertFk != null) {
1338 // rankTypeExpertsUpdateStmt.setInt(6, speciesExpertFk);
1340 // rankTypeExpertsUpdateStmt.setObject(6, null);
1343 if (taxonFk
!= null) {
1344 rankTypeExpertsUpdateStmt
.setInt(index
++, taxonFk
);
1346 rankTypeExpertsUpdateStmt
.setObject(index
++, null);
1349 rankTypeExpertsUpdateStmt
.executeUpdate();
1351 } catch (SQLException e
) {
1352 logger
.error("Data could not be inserted into database: " + e
.getMessage() + "; rankFk = " + rankFk
+ "; kingdomFk = " + kingdomFk
);
1353 e
.printStackTrace();
1355 } catch (Exception e
) {
1356 logger
.error("Some exception occurred: " + e
.getMessage() + "; rankFk = " + rankFk
+ "; kingdomFk = " + kingdomFk
);
1357 e
.printStackTrace();
1363 * Deletes all entries of database tables related to <code>Taxon</code>.
1364 * @param state The {@link PesiExportState PesiExportState}.
1365 * @return Whether the delete operation was successful or not.
1367 protected boolean doDelete(PesiExportState state
) {
1368 PesiExportConfigurator pesiConfig
= state
.getConfig();
1371 Source destination
= pesiConfig
.getDestination();
1374 sql
= "DELETE FROM " + dbTableName
;
1375 destination
.setQuery(sql
);
1376 destination
.update(sql
);
1381 * Creates the kingdom fk.
1385 @SuppressWarnings("unused") //used by mapper
1386 private static Integer
getKingdomFk(TaxonName taxonName
){
1387 return PesiTransformer
.nomenclaturalCode2Kingdom(taxonName
.getNameType());
1391 * Creates the parent fk.
1395 @SuppressWarnings("unused") //used by mapper
1396 private static Integer
getParentTaxonFk(TaxonBase
<?
> taxonBase
, PesiExportState state
){
1397 if (taxonBase
.isInstanceOf(Taxon
.class)){
1398 Taxon taxon
= CdmBase
.deproxy(taxonBase
, Taxon
.class);
1399 if (! isMisappliedName(taxon
)){
1400 Set
<TaxonNode
> nodes
= taxon
.getTaxonNodes();
1401 if (nodes
.size() == 0){
1402 if (taxon
.getName().getRank().isLower(Rank
.KINGDOM())){
1403 logger
.warn("Accepted taxon has no parent. " + taxon
.getTitleCache() + ", " + taxon
.getUuid());
1405 }else if (nodes
.size() > 1){
1406 logger
.warn("Taxon has more than 1 node attached. This is not supported by PESI export." + taxon
.getTitleCache() + ", " + taxon
.getUuid());
1408 Taxon parent
=nodes
.iterator().next().getParent().getTaxon();
1409 return state
.getDbId(parent
);
1417 * Returns the rankFk for the taxon name based on the names nomenclatural code.
1418 * You may not use this method for kingdoms other then Animalia, Plantae and Bacteria.
1422 @SuppressWarnings("unused") //used by mapper
1423 private static Integer
getRankFk(TaxonName taxonName
) {
1424 return getRankFk(taxonName
, taxonName
.getNameType());
1429 * Returns the <code>RankFk</code> attribute.
1430 * @param taxonName The {@link TaxonNameBase TaxonName}.
1431 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
1432 * @return The <code>RankFk</code> attribute.
1435 private static Integer
getRankFk(TaxonName taxonName
, NomenclaturalCode nomenclaturalCode
) {
1436 Integer result
= null;
1438 if (nomenclaturalCode
!= null) {
1439 if (taxonName
!= null) {
1440 if (taxonName
.getRank() == null) {
1441 logger
.warn("Rank is null: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1443 result
= PesiTransformer
.rank2RankId(taxonName
.getRank(), PesiTransformer
.nomenclaturalCode2Kingdom(nomenclaturalCode
));
1445 if (result
== null) {
1446 logger
.warn("Rank could not be determined for PESI-Kingdom-Id " + PesiTransformer
.nomenclaturalCode2Kingdom(nomenclaturalCode
) + " and TaxonName " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1450 } catch (Exception e
) {
1451 e
.printStackTrace();
1457 * Returns the rank cache for the taxon name based on the names nomenclatural code.
1458 * You may not use this method for kingdoms other then Animalia, Plantae and Bacteria.
1462 @SuppressWarnings("unused") //used by mapper
1463 private static String
getRankCache(TaxonName taxonName
, PesiExportState state
) {
1464 return getRankCache(taxonName
, taxonName
.getNameType(), state
);
1468 * Returns the <code>RankCache</code> attribute.
1469 * @param taxonName The {@link TaxonNameBase TaxonName}.
1470 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
1472 * @return The <code>RankCache</code> attribute.
1475 private static String
getRankCache(TaxonName taxonName
, NomenclaturalCode nomenclaturalCode
, PesiExportState state
) {
1476 if (nomenclaturalCode
!= null) {
1477 return state
.getTransformer().getCacheByRankAndKingdom(taxonName
.getRank(), PesiTransformer
.nomenclaturalCode2Kingdom(nomenclaturalCode
));
1479 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 TaxonName 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.
1507 protected static String
getAuthorString(TaxonBase
<?
> taxon
) {
1509 String result
= null;
1510 boolean isNonViralName
= false;
1511 String authorshipCache
= null;
1512 TaxonName taxonName
= taxon
.getName();
1513 if (taxonName
!= null && taxonName
.isNonViral()){
1514 authorshipCache
= taxonName
.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();
1556 * Returns the <code>DisplayName</code> attribute.
1557 * @param taxonName The {@link TaxonNameBase TaxonName}.
1558 * @return The <code>DisplayName</code> attribute.
1562 private static String
getDisplayName(TaxonName taxonName
) {
1564 if (taxonName
== null) {
1567 TaxonName nvn
= CdmBase
.deproxy(taxonName
);
1568 INonViralNameCacheStrategy cacheStrategy
= getCacheStrategy(taxonName
);
1569 HTMLTagRules tagRules
= new HTMLTagRules().
1570 addRule(TagEnum
.name
, "i").
1571 addRule(TagEnum
.nomStatus
, "@status@");
1573 String result
= cacheStrategy
.getFullTitleCache(nvn
, tagRules
);
1574 cacheStrategy
= null;
1575 return result
.replaceAll(",?\\<@status@\\>.*\\</@status@\\>", "");
1579 @SuppressWarnings("unused")
1580 private static String
getGUID(TaxonName taxonName
) {
1581 UUID uuid
= taxonName
.getUuid();
1582 String result
= "NameUUID:" + uuid
.toString();
1588 * Returns the <code>WebShowName</code> attribute for a taxon.
1589 * @param taxonName The {@link TaxonNameBase TaxonName}.
1590 * @return The <code>WebShowName</code> attribute.
1593 @SuppressWarnings("unused")
1594 private static String
getWebShowName(TaxonBase
<?
> taxon
) {
1595 TaxonName taxonName
= taxon
.getName();
1596 String result
= getWebShowName(taxonName
);
1597 if (isMisappliedName(taxon
)){
1598 result
= result
+ " " + getAuthorString(taxon
);
1604 * Returns the <code>WebShowName</code> attribute.
1605 * @param taxonName The {@link TaxonNameBase TaxonName}.
1606 * @return The <code>WebShowName</code> attribute.
1609 private static String
getWebShowName(TaxonName taxonName
) {
1611 if (taxonName
== null) {
1614 INonViralNameCacheStrategy cacheStrategy
= getCacheStrategy(taxonName
);
1616 HTMLTagRules tagRules
= new HTMLTagRules().addRule(TagEnum
.name
, "i");
1617 String result
= cacheStrategy
.getTitleCache(taxonName
, tagRules
);
1624 * Returns the <code>WebSearchName</code> attribute.
1625 * @param taxonName The {@link NonViralName NonViralName}.
1626 * @return The <code>WebSearchName</code> attribute.
1629 @SuppressWarnings("unused")
1630 private static String
getWebSearchName(TaxonName taxonName
) {
1632 TaxonNameDefaultCacheStrategy strategy
= getCacheStrategy(taxonName
);
1633 String result
= strategy
.getNameCache(taxonName
);
1639 * Returns the <code>FullName</code> attribute.
1640 * @param taxonName The {@link NonViralName NonViralName}.
1641 * @return The <code>FullName</code> attribute.
1644 @SuppressWarnings("unused")
1645 private static String
getFullName(TaxonName taxonName
) {
1647 String result
= getCacheStrategy(taxonName
).getTitleCache(taxonName
);
1648 Iterator
<Taxon
> taxa
= taxonName
.getTaxa().iterator();
1649 if (taxonName
.getTaxa().size() >0){
1650 if (taxonName
.getTaxa().size() == 1){
1651 Taxon taxon
= taxa
.next();
1652 if (isMisappliedName(taxon
)){
1653 result
= result
+ " " + getAuthorString(taxon
);
1662 * Returns the SourceNameCache for the AdditionalSource table
1666 @SuppressWarnings("unused")
1667 private static String
getSourceNameCache(TaxonName taxonName
) {
1668 if (taxonName
!= null){
1669 Reference nomRef
= taxonName
.getNomenclaturalReference();
1670 if (nomRef
!= null){
1671 //#5388 is definetely not the correct ticket number
1672 logger
.warn("Semantics of getAbbrevTitleCache has changed. Please check if output is still correct. See #5388");
1673 return nomRef
.getAbbrevTitleCache();
1682 * Returns the <code>FullName</code> attribute.
1683 * @param taxon The {@link TaxonBase taxon}.
1684 * @return The <code>FullName</code> attribute.
1687 /*@SuppressWarnings("unused")
1688 private static String getFullName(TaxonBase taxon) {
1690 TaxonNameBase name = taxon.getName();
1691 String result = getFullName(name);
1692 if (isMisappliedName(taxon)){
1693 result = result + " " + getAuthorString(taxon);
1701 * Returns the nomenclatural reference which is the reference
1702 * including the detail (microreference).
1703 * @param taxonName The {@link TaxonNameBase TaxonName}.
1704 * @return The <code>AuthorString</code> attribute.
1707 @SuppressWarnings("unused")
1708 private static String
getNomRefString(TaxonName taxonName
) {
1709 INomenclaturalReference ref
= taxonName
.getNomenclaturalReference();
1713 if (! ref
.isProtectedAbbrevTitleCache()){
1714 ref
.setAbbrevTitleCache(null, false); //to remove a false cache
1716 return ref
.getNomenclaturalCitation(taxonName
.getNomenclaturalMicroReference());
1721 * Returns the <code>NameStatusFk</code> attribute.
1722 * @param taxonName The {@link TaxonNameBase TaxonName}.
1723 * @return The <code>NameStatusFk</code> attribute.
1726 @SuppressWarnings("unused")
1727 private static Integer
getNameStatusFk(TaxonName taxonName
) {
1728 Integer result
= null;
1730 NomenclaturalStatus state
= getNameStatus(taxonName
);
1731 if (state
!= null) {
1732 result
= PesiTransformer
.nomStatus2nomStatusFk(state
.getType());
1738 * Returns the <code>NameStatusCache</code> attribute.
1739 * @param taxonName The {@link TaxonNameBase TaxonName}.
1740 * @return The <code>NameStatusCache</code> attribute.
1741 * @throws UndefinedTransformerMethodException
1744 @SuppressWarnings("unused")
1745 private static String
getNameStatusCache(TaxonName taxonName
, PesiExportState state
) throws UndefinedTransformerMethodException
{
1746 String result
= null;
1747 NomenclaturalStatus status
= getNameStatus(taxonName
);
1748 if (status
!= null) {
1749 result
= state
.getTransformer().getCacheByNomStatus(status
.getType());
1755 private static NomenclaturalStatus
getNameStatus(TaxonName taxonName
) {
1757 if (taxonName
!= null) {
1758 Set
<NomenclaturalStatus
> states
= taxonName
.getStatus();
1759 if (states
.size() == 1) {
1760 NomenclaturalStatus status
= states
.iterator().next();
1762 } else if (states
.size() > 1) {
1763 logger
.error("This TaxonName has more than one Nomenclatural Status: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1766 } catch (Exception e
) {
1767 e
.printStackTrace();
1772 * Returns the <code>TaxonStatusFk</code> attribute.
1773 * @param taxonName The {@link TaxonNameBase TaxonName}.
1774 * @param state The {@link PesiExportState PesiExportState}.
1775 * @return The <code>TaxonStatusFk</code> attribute.
1778 private static Integer
getTaxonStatusFk(TaxonBase
<?
> taxon
, PesiExportState state
) {
1779 Integer result
= null;
1782 if (isMisappliedName(taxon
)) {
1783 Synonym synonym
= Synonym
.NewInstance(null, null);
1785 // This works as long as only the instance is important to differentiate between TaxonStatus.
1786 result
= PesiTransformer
.taxonBase2statusFk(synonym
); // Auct References are treated as Synonyms in Datawarehouse now.
1788 result
= PesiTransformer
.taxonBase2statusFk(taxon
);
1790 } catch (Exception e
) {
1791 e
.printStackTrace();
1797 * Returns the <code>TaxonStatusCache</code> attribute.
1798 * @param taxonName The {@link TaxonNameBase TaxonName}.
1799 * @param state The {@link PesiExportState PesiExportState}.
1800 * @return The <code>TaxonStatusCache</code> attribute.
1801 * @throws UndefinedTransformerMethodException
1804 @SuppressWarnings("unused")
1805 private static String
getTaxonStatusCache(TaxonBase
<?
> taxon
, PesiExportState state
) throws UndefinedTransformerMethodException
{
1806 return state
.getTransformer().getTaxonStatusCacheByKey(getTaxonStatusFk(taxon
, state
));
1810 * Returns the <code>TypeNameFk</code> attribute.
1811 * @param taxonName The {@link TaxonNameBase TaxonName}.
1812 * @param state The {@link PesiExportState PesiExportState}.
1813 * @return The <code>TypeNameFk</code> attribute.
1816 private static Integer
getTypeNameFk(TaxonName taxonName
, PesiExportState state
) {
1817 Integer result
= null;
1818 if (taxonName
!= null) {
1819 Set
<NameTypeDesignation
> nameTypeDesignations
= taxonName
.getNameTypeDesignations();
1820 if (nameTypeDesignations
.size() == 1) {
1821 NameTypeDesignation nameTypeDesignation
= nameTypeDesignations
.iterator().next();
1822 if (nameTypeDesignation
!= null) {
1823 TaxonName typeName
= nameTypeDesignation
.getTypeName();
1824 if (typeName
!= null) {
1825 result
= state
.getDbId(typeName
);
1828 } else if (nameTypeDesignations
.size() > 1) {
1829 logger
.warn("This TaxonName has " + nameTypeDesignations
.size() + " NameTypeDesignations: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1836 * Returns the <code>TypeFullnameCache</code> attribute.
1837 * @param taxonName The {@link TaxonNameBase TaxonName}.
1838 * @return The <code>TypeFullnameCache</code> attribute.
1841 @SuppressWarnings("unused")
1842 private static String
getTypeFullnameCache(TaxonName taxonName
) {
1843 String result
= null;
1846 if (taxonName
!= null) {
1847 Set
<NameTypeDesignation
> nameTypeDesignations
= taxonName
.getNameTypeDesignations();
1848 if (nameTypeDesignations
.size() == 1) {
1849 NameTypeDesignation nameTypeDesignation
= nameTypeDesignations
.iterator().next();
1850 if (nameTypeDesignation
!= null) {
1851 TaxonName typeName
= nameTypeDesignation
.getTypeName();
1852 if (typeName
!= null) {
1853 result
= typeName
.getTitleCache();
1856 } else if (nameTypeDesignations
.size() > 1) {
1857 logger
.warn("This TaxonName has " + nameTypeDesignations
.size() + " NameTypeDesignations: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1860 } catch (Exception e
) {
1861 e
.printStackTrace();
1868 * Returns the <code>QualityStatusFk</code> attribute.
1869 * @param taxonName The {@link TaxonNameBase TaxonName}.
1870 * @return The <code>QualityStatusFk</code> attribute.
1873 private static Integer
getQualityStatusFk(TaxonName taxonName
) {
1874 BitSet sources
= getSources(taxonName
);
1875 return PesiTransformer
.getQualityStatusKeyBySource(sources
, taxonName
);
1880 * Returns the <code>QualityStatusCache</code> attribute.
1881 * @param taxonName The {@link TaxonNameBase TaxonName}.
1882 * @return The <code>QualityStatusCache</code> attribute.
1883 * @throws UndefinedTransformerMethodException
1886 @SuppressWarnings("unused")
1887 private static String
getQualityStatusCache(TaxonName taxonName
, PesiExportState state
) throws UndefinedTransformerMethodException
{
1888 return state
.getTransformer().getQualityStatusCacheByKey(getQualityStatusFk(taxonName
));
1893 * Returns the <code>TypeDesignationStatusFk</code> attribute.
1894 * @param taxonName The {@link TaxonNameBase TaxonName}.
1895 * @return The <code>TypeDesignationStatusFk</code> attribute.
1898 @SuppressWarnings("unused")
1899 private static Integer
getTypeDesignationStatusFk(TaxonName taxonName
) {
1900 Integer result
= null;
1903 if (taxonName
!= null) {
1904 Set
<NameTypeDesignation
> typeDesignations
= taxonName
.getNameTypeDesignations();
1905 if (typeDesignations
.size() == 1) {
1906 Object obj
= typeDesignations
.iterator().next().getTypeStatus();
1907 NameTypeDesignationStatus designationStatus
= CdmBase
.deproxy(obj
, NameTypeDesignationStatus
.class);
1908 result
= PesiTransformer
.nameTypeDesignationStatus2TypeDesignationStatusId(designationStatus
);
1909 } else if (typeDesignations
.size() > 1) {
1910 logger
.error("Found a TaxonName with more than one NameTypeDesignation: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1914 } catch (Exception e
) {
1915 e
.printStackTrace();
1921 * Returns the <code>TypeDesignationStatusCache</code> attribute.
1922 * @param taxonName The {@link TaxonNameBase TaxonName}.
1923 * @return The <code>TypeDesignationStatusCache</code> attribute.
1926 @SuppressWarnings("unused")
1927 private static String
getTypeDesignationStatusCache(TaxonName taxonName
) {
1928 String result
= null;
1931 if (taxonName
!= null) {
1932 Set
<NameTypeDesignation
> typeDesignations
= taxonName
.getNameTypeDesignations();
1933 if (typeDesignations
.size() == 1) {
1934 Object obj
= typeDesignations
.iterator().next().getTypeStatus();
1935 NameTypeDesignationStatus designationStatus
= CdmBase
.deproxy(obj
, NameTypeDesignationStatus
.class);
1936 result
= PesiTransformer
.nameTypeDesignationStatus2TypeDesignationStatusCache(designationStatus
);
1937 } else if (typeDesignations
.size() > 1) {
1938 logger
.error("Found a TaxonName with more than one NameTypeDesignation: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1942 } catch (Exception e
) {
1943 e
.printStackTrace();
1949 * Returns the <code>FossilStatusFk</code> attribute.
1950 * @param taxonName The {@link TaxonNameBase TaxonName}.
1951 * @return The <code>FossilStatusFk</code> attribute.
1954 @SuppressWarnings("unused")
1955 private static Integer
getFossilStatusFk(IdentifiableEntity
<?
> identEntity
, PesiExportState state
) {
1956 Integer result
= null;
1958 Set
<String
> fossilStatuus
= identEntity
.getExtensions(ErmsTransformer
.uuidExtFossilStatus
);
1959 if (fossilStatuus
.size() == 0){
1961 }else if (fossilStatuus
.size() > 1){
1962 logger
.warn("More than 1 fossil status given for " + identEntity
.getTitleCache() + " " + identEntity
.getUuid());
1964 String fossilStatus
= fossilStatuus
.iterator().next();
1966 int statusFk
= state
.getTransformer().fossilStatusCache2FossilStatusFk(fossilStatus
);
1971 * Returns the <code>FossilStatusCache</code> attribute.
1972 * @param taxonName The {@link TaxonNameBase TaxonName}.
1973 * @return The <code>FossilStatusCache</code> attribute.
1976 @SuppressWarnings("unused")
1977 private static String
getFossilStatusCache(IdentifiableEntity
<?
> identEntity
, PesiExportState state
) {
1978 String result
= null;
1979 Set
<String
> fossilStatuus
= identEntity
.getExtensions(ErmsTransformer
.uuidExtFossilStatus
);
1980 if (fossilStatuus
.size() == 0){
1983 for (String strFossilStatus
: fossilStatuus
){
1984 result
= CdmUtils
.concat(";", result
, strFossilStatus
);
1990 * Returns the <code>IdInSource</code> attribute.
1991 * @param taxonName The {@link TaxonNameBase TaxonName}.
1992 * @return The <code>IdInSource</code> attribute.
1995 @SuppressWarnings("unused")
1996 private static String
getIdInSource(IdentifiableEntity taxonName
) {
1997 String result
= null;
2000 Set
<IdentifiableSource
> sources
= getPesiSources(taxonName
);
2001 if (sources
.size() > 1){
2002 logger
.warn("There is > 1 Pesi source. This is not yet handled.");
2004 if (sources
.size() == 0){
2005 logger
.warn("There is no Pesi source!" +taxonName
.getUuid() + " (" + taxonName
.getTitleCache() +")");
2007 for (IdentifiableSource source
: sources
) {
2008 Reference ref
= source
.getCitation();
2009 UUID refUuid
= ref
.getUuid();
2010 String idInSource
= source
.getIdInSource();
2011 if (refUuid
.equals(BerlinModelTransformer
.uuidSourceRefEuroMed
)){
2012 result
= idInSource
!= null ?
("NameId: " + source
.getIdInSource()) : null;
2013 }else if (refUuid
.equals(PesiTransformer
.uuidSourceRefFaunaEuropaea
)){
2014 result
= idInSource
!= null ?
("TAX_ID: " + source
.getIdInSource()) : null;
2015 }else if (refUuid
.equals(PesiTransformer
.uuidSourceRefErms
)){
2016 result
= idInSource
!= null ?
("tu_id: " + source
.getIdInSource()) : null;
2017 }else if (refUuid
.equals(PesiTransformer
.uuidSourceRefIndexFungorum
)){ //Index Fungorum
2018 result
= idInSource
!= null ?
("if_id: " + source
.getIdInSource()) : null;
2020 if (logger
.isDebugEnabled()){logger
.debug("Not a PESI source");};
2023 String sourceIdNameSpace
= source
.getIdNamespace();
2024 if (sourceIdNameSpace
!= null) {
2025 if (sourceIdNameSpace
.equals(PesiTransformer
.STR_NAMESPACE_NOMINAL_TAXON
)) {
2026 result
= idInSource
!= null ?
("Nominal Taxon from TAX_ID: " + source
.getIdInSource()):null;
2027 } else if (sourceIdNameSpace
.equals(TaxonServiceImpl
.INFERRED_EPITHET_NAMESPACE
)) {
2028 result
= idInSource
!= null ?
("Inferred epithet from TAX_ID: " + source
.getIdInSource()) : null;
2029 } else if (sourceIdNameSpace
.equals(TaxonServiceImpl
.INFERRED_GENUS_NAMESPACE
)) {
2030 result
= idInSource
!= null ?
("Inferred genus from TAX_ID: " + source
.getIdInSource()):null;
2031 } else if (sourceIdNameSpace
.equals(TaxonServiceImpl
.POTENTIAL_COMBINATION_NAMESPACE
)) {
2032 result
= idInSource
!= null ?
("Potential combination from TAX_ID: " + source
.getIdInSource()):null;
2035 if (result
== null) {
2036 logger
.warn("IdInSource is NULL for this taxonName: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() +", sourceIdNameSpace: " + source
.getIdNamespace()+")");
2039 } catch (Exception e
) {
2040 e
.printStackTrace();
2041 logger
.error("An error occurs while creating idInSource..." + taxonName
.getUuid() + " (" + taxonName
.getTitleCache()+ e
.getMessage());
2044 if (result
== null) {
2045 logger
.warn("IdInSource is NULL for this taxonName: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() +")");
2051 * Returns the idInSource for a given TaxonName only.
2052 * @param taxonName The {@link TaxonNameBase TaxonName}.
2053 * @return The idInSource.
2055 private static String
getIdInSourceOnly(IdentifiableEntity identEntity
) {
2056 String result
= null;
2058 // Get the sources first
2059 Set
<IdentifiableSource
> sources
= getPesiSources(identEntity
);
2061 // Determine the idInSource
2062 if (sources
.size() == 1) {
2063 IdentifiableSource source
= sources
.iterator().next();
2064 if (source
!= null) {
2065 result
= source
.getIdInSource();
2067 } else if (sources
.size() > 1) {
2070 for (IdentifiableSource source
: sources
) {
2071 result
+= source
.getIdInSource();
2072 if (count
< sources
.size()) {
2084 * Returns the Sources for a given TaxonName only.
2085 * @param taxonName The {@link TaxonNameBase TaxonName}.
2086 * @return The Sources.
2088 private static Set
<IdentifiableSource
> getPesiSources(IdentifiableEntity identEntity
) {
2089 Set
<IdentifiableSource
> sources
= new java
.util
.HashSet
<IdentifiableSource
>();
2092 if (identEntity
.isInstanceOf(TaxonName
.class)){
2093 // Sources from TaxonName
2094 TaxonName taxonName
= CdmBase
.deproxy(identEntity
, TaxonName
.class);
2095 Set
<IdentifiableSource
> testSources
= identEntity
.getSources();
2096 sources
= filterPesiSources(identEntity
.getSources());
2098 if (sources
.size() == 0 && testSources
.size()>0){
2099 IdentifiableSource source
= testSources
.iterator().next();
2100 logger
.warn("There are sources, but they are no pesi sources!!!" + source
.getIdInSource() + " - " + source
.getIdNamespace() + " - " + source
.getCitation().getTitleCache());
2102 if (sources
.size() > 1) {
2103 logger
.warn("This TaxonName has more than one Source: " + identEntity
.getUuid() + " (" + identEntity
.getTitleCache() + ")");
2106 // name has no PESI source, take sources from TaxonBase
2107 if (sources
== null || sources
.isEmpty()) {
2108 Set
<TaxonBase
> taxa
= taxonName
.getTaxonBases();
2109 for (TaxonBase taxonBase
: taxa
){
2110 sources
.addAll(filterPesiSources(taxonBase
.getSources()));
2115 }else if (identEntity
.isInstanceOf(TaxonBase
.class)){
2116 sources
= filterPesiSources(identEntity
.getSources());
2119 /*TODO: deleted only for testing the inferred synonyms
2120 if (sources == null || sources.isEmpty()) {
2121 logger.warn("This TaxonName has no PESI Sources: " + identEntity.getUuid() + " (" + identEntity.getTitleCache() +")");
2122 }else if (sources.size() > 1){
2123 logger.warn("This Taxon(Name) has more than 1 PESI source: " + identEntity.getUuid() + " (" + identEntity.getTitleCache() +")");
2129 // return all sources with a PESI reference
2130 private static Set
<IdentifiableSource
> filterPesiSources(Set
<?
extends IdentifiableSource
> sources
) {
2131 Set
<IdentifiableSource
> result
= new HashSet
<IdentifiableSource
>();
2132 for (IdentifiableSource source
: sources
){
2133 Reference ref
= source
.getCitation();
2134 UUID refUuid
= ref
.getUuid();
2135 if (refUuid
.equals(BerlinModelTransformer
.uuidSourceRefEuroMed
) ||
2136 refUuid
.equals(PesiTransformer
.uuidSourceRefFaunaEuropaea
)||
2137 refUuid
.equals(PesiTransformer
.uuidSourceRefErms
)||
2138 refUuid
.equals(PesiTransformer
.uuidSourceRefIndexFungorum
) ||
2139 refUuid
.equals(PesiTransformer
.uuidSourceRefAuct
)){
2147 * Returns the <code>GUID</code> attribute.
2148 * @param taxonName The {@link TaxonNameBase TaxonName}.
2149 * @return The <code>GUID</code> attribute.
2152 private static String
getGUID(TaxonBase
<?
> taxon
) {
2153 if (taxon
.getLsid() != null ){
2154 return taxon
.getLsid().getLsid();
2155 }else if (taxon
.hasMarker(PesiTransformer
.uuidMarkerGuidIsMissing
, true)){
2158 return taxon
.getUuid().toString();
2164 * Returns the <code>DerivedFromGuid</code> attribute.
2165 * @param taxonName The {@link TaxonNameBase TaxonName}.
2166 * @return The <code>DerivedFromGuid</code> attribute.
2169 @SuppressWarnings("unused")
2170 private static String
getDerivedFromGuid(TaxonBase
<?
> taxon
) {
2171 String result
= null;
2173 // The same as GUID for now
2174 result
= getGUID(taxon
);
2175 } catch (Exception e
) {
2176 e
.printStackTrace();
2182 * Returns the <code>CacheCitation</code> attribute.
2183 * @param taxonName The {@link TaxonNameBase TaxonName}.
2184 * @return The CacheCitation.
2187 @SuppressWarnings("unused")
2188 private static String
getCacheCitation(TaxonBase taxon
) {
2189 // !!! See also doPhaseUpdates
2191 TaxonName taxonName
= taxon
.getName();
2193 //TODO implement anew for taxa
2195 BitSet sources
= getSources(taxonName
);
2196 if (sources
.isEmpty()) {
2197 // logger.error("OriginalDB is NULL for this TaxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
2198 } else if (sources
.get(PesiTransformer
.SOURCE_ERMS
)) {
2199 // 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...
2200 // So the following code is some kind of harmless assumption.
2201 Set
<Extension
> extensions
= taxonName
.getExtensions();
2202 for (Extension extension
: extensions
) {
2203 if (extension
.getType().equals(cacheCitationExtensionType
)) {
2204 result
= extension
.getValue();
2208 String expertName
= getExpertName(taxon
);
2209 String webShowName
= getWebShowName(taxonName
);
2212 String idInSource
= getIdInSourceOnly(taxonName
);
2214 // build the cacheCitation
2215 if (expertName
!= null) {
2216 result
+= expertName
+ ". ";
2218 if (logger
.isDebugEnabled()){logger
.debug("ExpertName could not be determined for this TaxonName: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");}
2220 if (webShowName
!= null) {
2221 result
+= webShowName
+ ". ";
2223 logger
.warn("WebShowName could not be determined for this TaxonName: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
2226 if (getOriginalDB(taxonName
).equals("FaEu")) {
2227 result
+= "Accessed through: Fauna Europaea at http://faunaeur.org/full_results.php?id=";
2228 } else if (getOriginalDB(taxonName
).equals("EM")) {
2229 result
+= "Accessed through: Euro+Med PlantBase at http://ww2.bgbm.org/euroPlusMed/PTaxonDetail.asp?UUID=";
2232 if (idInSource
!= null) {
2233 result
+= idInSource
;
2235 logger
.warn("IdInSource could not be determined for this TaxonName: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
2238 } catch (Exception e
) {
2239 e
.printStackTrace();
2242 if (StringUtils
.isBlank(result
)) {
2250 * Returns the <code>OriginalDB</code> attribute.
2251 * @param taxonName The {@link TaxonNameBase TaxonName}.
2252 * @return The <code>OriginalDB</code> attribute.
2255 private static String
getOriginalDB(IdentifiableEntity identEntity
) {
2256 // Sources from TaxonName
2257 BitSet sources
= getSources(identEntity
);
2258 return PesiTransformer
.getOriginalDbBySources(sources
);
2262 * Returns the <code>LastAction</code> attribute.
2263 * @param taxonName The {@link TaxonNameBase TaxonName}.
2264 * @return The <code>LastAction</code> attribute.
2267 @SuppressWarnings("unused")
2268 private static String
getLastAction(IdentifiableEntity
<?
> identEntity
) {
2269 String result
= null;
2271 Set
<Extension
> extensions
= identEntity
.getExtensions();
2272 for (Extension extension
: extensions
) {
2273 if (extension
.getType().equals(lastActionExtensionType
)) {
2274 result
= extension
.getValue();
2277 } catch (Exception e
) {
2278 e
.printStackTrace();
2284 * Returns the <code>LastActionDate</code> attribute.
2285 * @param taxonName The {@link TaxonNameBase TaxonName}.
2286 * @return The <code>LastActionDate</code> attribute.
2289 @SuppressWarnings({ "unused" })
2290 private static DateTime
getLastActionDate(IdentifiableEntity identEntity
) {
2291 DateTime result
= null;
2293 Set
<Extension
> extensions
= identEntity
.getExtensions();
2294 for (Extension extension
: extensions
) {
2295 if (extension
.getType().equals(lastActionDateExtensionType
)) {
2296 String dateTime
= extension
.getValue();
2297 if (dateTime
!= null) {
2298 DateTimeFormatter formatter
= DateTimeFormat
.forPattern("yyyy-MM-dd HH:mm:ss.S");
2299 result
= formatter
.parseDateTime(dateTime
);
2303 } catch (Exception e
) {
2304 e
.printStackTrace();
2310 * Returns the <code>ExpertName</code> attribute.
2311 * @param taxonName The {@link TaxonNameBase TaxonName}.
2312 * @return The <code>ExpertName</code> attribute.
2315 @SuppressWarnings("unused")
2316 private static String
getExpertName(TaxonBase
<?
> taxonName
) {
2317 String result
= null;
2319 Set
<Extension
> extensions
= taxonName
.getExtensions();
2320 for (Extension extension
: extensions
) {
2321 if (extension
.getType().equals(expertNameExtensionType
)) {
2322 result
= extension
.getValue();
2325 } catch (Exception e
) {
2326 e
.printStackTrace();
2332 * Returns the <code>ExpertFk</code> attribute.
2333 * @param taxonName The {@link TaxonNameBase TaxonName}.
2334 * @param state The {@link PesiExportState PesiExportState}.
2335 * @return The <code>ExpertFk</code> attribute.
2338 private static Integer
getExpertFk(Reference reference
, PesiExportState state
) {
2339 Integer result
= state
.getDbId(reference
);
2344 * Returns the <code>SpeciesExpertName</code> attribute.
2345 * @param taxonName The {@link TaxonNameBase TaxonName}.
2346 * @return The <code>SpeciesExpertName</code> attribute.
2349 @SuppressWarnings("unused")
2350 private static String
getSpeciesExpertName(TaxonBase
<?
> taxonName
) {
2351 String result
= null;
2353 Set
<Extension
> extensions
= taxonName
.getExtensions();
2354 for (Extension extension
: extensions
) {
2355 if (extension
.getType().equals(speciesExpertNameExtensionType
)) {
2356 result
= extension
.getValue();
2359 } catch (Exception e
) {
2360 e
.printStackTrace();
2366 * Returns the <code>SpeciesExpertFk</code> attribute.
2367 * @param reference The {@link Reference Reference}.
2368 * @param state The {@link PesiExportState PesiExportState}.
2369 * @return The <code>SpeciesExpertFk</code> attribute.
2372 private static Integer
getSpeciesExpertFk(Reference reference
, PesiExportState state
) {
2373 Integer result
= state
.getDbId(reference
);
2379 * Returns the source (E+M, Fauna Europaea, Index Fungorum, ERMS) of a given
2380 * Identifiable Entity as a BitSet
2381 * @param identEntity
2384 private static BitSet
getSources(IdentifiableEntity
<?
> identEntity
){
2385 BitSet bitSet
= new BitSet();
2386 Set
<IdentifiableSource
> sources
= getPesiSources(identEntity
);
2387 for (IdentifiableSource source
: sources
) {
2388 Reference ref
= source
.getCitation();
2389 UUID refUuid
= ref
.getUuid();
2390 if (refUuid
.equals(BerlinModelTransformer
.uuidSourceRefEuroMed
)){
2391 bitSet
.set(PesiTransformer
.SOURCE_EM
);
2392 }else if (refUuid
.equals(PesiTransformer
.uuidSourceRefFaunaEuropaea
)){
2393 bitSet
.set(PesiTransformer
.SOURCE_FE
);
2394 }else if (refUuid
.equals(PesiTransformer
.uuidSourceRefErms
)){
2395 bitSet
.set(PesiTransformer
.SOURCE_ERMS
);
2396 }else if (refUuid
.equals(PesiTransformer
.uuidSourceRefIndexFungorum
)){
2397 bitSet
.set(PesiTransformer
.SOURCE_IF
);
2399 if (logger
.isDebugEnabled()){logger
.debug("Not a PESI source");};
2406 protected static TaxonNameDefaultCacheStrategy
getCacheStrategy(TaxonName taxonName
) {
2407 taxonName
= CdmBase
.deproxy(taxonName
);
2408 TaxonNameDefaultCacheStrategy cacheStrategy
;
2409 if (taxonName
.isZoological()){
2410 cacheStrategy
= zooNameStrategy
;
2411 }else if (taxonName
.isBotanical()) {
2412 cacheStrategy
= nonViralNameStrategy
;
2413 }else if (taxonName
.isNonViral()) {
2414 cacheStrategy
= nonViralNameStrategy
;
2415 }else if (taxonName
.isBacterial()) {
2416 cacheStrategy
= nonViralNameStrategy
;
2418 logger
.error("Unhandled taxon name type. Can't define strategy class");
2419 cacheStrategy
= nonViralNameStrategy
;
2421 return cacheStrategy
;
2425 * Returns the <code>RelTaxonQualifierFk</code> attribute.
2426 * @param relationship The {@link RelationshipBase Relationship}.
2427 * @return The <code>RelTaxonQualifierFk</code> attribute.
2430 @SuppressWarnings("unused")
2431 private static Integer
getRelTaxonQualifierFk(RelationshipBase
<?
, ?
, ?
> relationship
) {
2432 return PesiTransformer
.taxonRelation2RelTaxonQualifierFk(relationship
);
2435 * Returns the <code>Notes</code> attribute.
2436 * @param relationship The {@link RelationshipBase Relationship}.
2437 * @return The <code>Notes</code> attribute.
2440 @SuppressWarnings("unused")
2441 private static String
getNotes(RelationshipBase
<?
, ?
, ?
> relationship
) {
2448 * Returns the CDM to PESI specific export mappings.
2449 * @return The {@link PesiExportMapping PesiExportMapping}.
2451 private PesiExportMapping
getMapping() {
2452 PesiExportMapping mapping
= new PesiExportMapping(dbTableName
);
2454 mapping
.addMapper(IdMapper
.NewInstance("TaxonId"));
2455 mapping
.addMapper(DbObjectMapper
.NewInstance("sec", "sourceFk")); //OLD:mapping.addMapper(MethodMapper.NewInstance("SourceFK", this.getClass(), "getSourceFk", standardMethodParameter, PesiExportState.class));
2456 mapping
.addMapper(MethodMapper
.NewInstance("TaxonStatusFk", this.getClass(), "getTaxonStatusFk", standardMethodParameter
, PesiExportState
.class));
2457 mapping
.addMapper(MethodMapper
.NewInstance("TaxonStatusCache", this.getClass(), "getTaxonStatusCache", standardMethodParameter
, PesiExportState
.class));
2459 mapping
.addMapper(MethodMapper
.NewInstance("GUID", this));
2461 mapping
.addMapper(MethodMapper
.NewInstance("DerivedFromGuid", this));
2462 mapping
.addMapper(MethodMapper
.NewInstance("CacheCitation", this));
2463 mapping
.addMapper(MethodMapper
.NewInstance("AuthorString", this)); //For Taxon because Misallied Names are handled differently
2464 mapping
.addMapper(MethodMapper
.NewInstance("WebShowName", this));
2467 mapping
.addMapper(MethodMapper
.NewInstance("DisplayName", this));
2469 // FossilStatus (Fk, Cache)
2470 mapping
.addMapper(MethodMapper
.NewInstance("FossilStatusCache", this, IdentifiableEntity
.class, PesiExportState
.class));
2471 mapping
.addMapper(MethodMapper
.NewInstance("FossilStatusFk", this, IdentifiableEntity
.class, PesiExportState
.class)); // PesiTransformer.FossilStatusCache2FossilStatusFk?
2473 //handled by name mapping
2474 mapping
.addMapper(DbLastActionMapper
.NewInstance("LastActionDate", false));
2475 mapping
.addMapper(DbLastActionMapper
.NewInstance("LastAction", true));
2478 ExtensionType extensionTypeSpeciesExpertName
= (ExtensionType
)getTermService().find(PesiTransformer
.speciesExpertNameUuid
);
2479 mapping
.addMapper(DbExtensionMapper
.NewInstance(extensionTypeSpeciesExpertName
, "SpeciesExpertName"));
2480 ExtensionType extensionTypeExpertName
= (ExtensionType
)getTermService().find(PesiTransformer
.expertNameUuid
);
2481 mapping
.addMapper(DbExtensionMapper
.NewInstance(extensionTypeExpertName
, "ExpertName"));
2483 // mapping.addMapper(MethodMapper.NewInstance("ParentTaxonFk", this, TaxonBase.class, PesiExportState.class)); //by AM, doesn't work, FK exception
2484 mapping
.addMapper(ObjectChangeMapper
.NewInstance(TaxonBase
.class, TaxonName
.class, "Name"));
2486 addNameMappers(mapping
);
2492 * Returns the CDM to PESI specific export mappings.
2494 * @return The {@link PesiExportMapping PesiExportMapping}.
2495 * @throws UndefinedTransformerMethodException
2497 private PesiExportMapping
getPureNameMapping(PesiExportState state
) throws UndefinedTransformerMethodException
{
2498 PesiExportMapping mapping
= new PesiExportMapping(dbTableName
);
2500 mapping
.addMapper(IdMapper
.NewInstance("TaxonId"));
2502 // mapping.addMapper(MethodMapper.NewInstance("TaxonStatusFk", this.getClass(), "getTaxonStatusFk", standardMethodParameter, PesiExportState.class));
2504 mapping
.addMapper(MethodMapper
.NewInstance("KingdomFk", this, TaxonName
.class));
2505 mapping
.addMapper(MethodMapper
.NewInstance("RankFk", this, TaxonName
.class));
2506 mapping
.addMapper(MethodMapper
.NewInstance("RankCache", this, TaxonName
.class, PesiExportState
.class));
2507 mapping
.addMapper(DbConstantMapper
.NewInstance("TaxonStatusFk", Types
.INTEGER
, PesiTransformer
.T_STATUS_UNACCEPTED
));
2508 mapping
.addMapper(DbConstantMapper
.NewInstance("TaxonStatusCache", Types
.VARCHAR
, state
.getTransformer().getTaxonStatusCacheByKey( PesiTransformer
.T_STATUS_UNACCEPTED
)));
2509 mapping
.addMapper(DbStringMapper
.NewInstance("AuthorshipCache", "AuthorString").setBlankToNull(true));
2510 mapping
.addMapper(MethodMapper
.NewInstance("WebShowName", this, TaxonName
.class));
2511 mapping
.addMapper(MethodMapper
.NewInstance("GUID", this, TaxonName
.class));
2514 mapping
.addMapper(MethodMapper
.NewInstance("DisplayName", this, TaxonName
.class));
2516 mapping
.addMapper(DbLastActionMapper
.NewInstance("LastActionDate", false));
2517 mapping
.addMapper(DbLastActionMapper
.NewInstance("LastAction", true));
2519 addNameMappers(mapping
);
2520 //TODO add author mapper, TypeNameFk
2526 private void addNameMappers(PesiExportMapping mapping
) {
2527 mapping
.addMapper(DbStringMapper
.NewInstance("GenusOrUninomial", "GenusOrUninomial"));
2528 mapping
.addMapper(DbStringMapper
.NewInstance("InfraGenericEpithet", "InfraGenericEpithet"));
2529 mapping
.addMapper(DbStringMapper
.NewInstance("SpecificEpithet", "SpecificEpithet"));
2530 mapping
.addMapper(DbStringMapper
.NewInstance("InfraSpecificEpithet", "InfraSpecificEpithet"));
2532 // mapping.addMapper(DbStringMapper.NewInstance("NameCache", "WebSearchName")); //does not work as we need other cache strategy
2533 mapping
.addMapper(MethodMapper
.NewInstance("WebSearchName", this, TaxonName
.class));
2535 // mapping.addMapper(DbStringMapper.NewInstance("TitleCache", "FullName")); //does not work as we need other cache strategy
2536 mapping
.addMapper(MethodMapper
.NewInstance("FullName", this, TaxonName
.class));
2539 mapping
.addMapper(MethodMapper
.NewInstance("NomRefString", this, TaxonName
.class));
2541 mapping
.addMapper(MethodMapper
.NewInstance("NameStatusFk", this, TaxonName
.class));
2542 mapping
.addMapper(MethodMapper
.NewInstance("NameStatusCache", this, TaxonName
.class, PesiExportState
.class));
2543 mapping
.addMapper(MethodMapper
.NewInstance("TypeFullnameCache", this, TaxonName
.class));
2547 mapping
.addMapper(MethodMapper
.NewInstance("QualityStatusFk", this, TaxonName
.class));
2548 mapping
.addMapper(MethodMapper
.NewInstance("QualityStatusCache", this, TaxonName
.class, PesiExportState
.class));
2550 mapping
.addMapper(MethodMapper
.NewInstance("IdInSource", this, IdentifiableEntity
.class));
2551 mapping
.addMapper(MethodMapper
.NewInstance("OriginalDB", this, IdentifiableEntity
.class) );
2553 //mapping.addMapper(ExpertsAndLastActionMapper.NewInstance());
2558 * Returns the <code>TaxonFk1</code> attribute. It corresponds to a CDM <code>TaxonRelationship</code>.
2559 * @param relationship The {@link RelationshipBase Relationship}.
2560 * @param state The {@link PesiExportState PesiExportState}.
2561 * @return The <code>TaxonFk1</code> attribute.
2564 @SuppressWarnings("unused")
2565 private static Integer
getSynonym(Synonym synonym
, PesiExportState state
) {
2566 return state
.getDbId(synonym
);
2569 @SuppressWarnings("unused")
2570 private static String
getSynonymTypeCache(Synonym synonym
, PesiExportState state
) {
2571 String result
= null;
2572 NomenclaturalCode code
= null;
2573 code
= CdmBase
.deproxy(synonym
, Synonym
.class).getAcceptedTaxon().getName().getNameType();
2576 result
= state
.getConfig().getTransformer().getCacheBySynonymType(synonym
, code
);
2578 logger
.error("NomenclaturalCode is NULL while creating the following synonym: " + synonym
.getUuid());
2583 private PesiExportMapping
getSynRelMapping() {
2584 PesiExportMapping mapping
= new PesiExportMapping(dbTableNameSynRel
);
2585 logger
.warn("SynRelMapping currently not implemented. Needs to be checked");
2587 mapping
.addMapper(MethodMapper
.NewInstance("TaxonFk1", this.getClass(), "getSynonym", Synonym
.class, PesiExportState
.class));
2588 mapping
.addMapper(DbObjectMapper
.NewInstance("acceptedTaxon", "TaxonFk2"));
2589 mapping
.addMapper(DbObjectMapper
.NewInstance("type", "RelTaxonQualifierFk"));
2590 mapping
.addMapper(MethodMapper
.NewInstance("RelQualifierCache", this.getClass(), "getSynonymTypeCache", Synonym
.class, PesiExportState
.class));
2592 // mapping.addMapper(MethodMapper.NewInstance("Notes", this, RelationshipBase.class));
2597 private PesiExportMapping
getAdditionalSourceMapping(PesiExportState state
) {
2598 PesiExportMapping mapping
= new PesiExportMapping(dbTableAdditionalSourceRel
);
2600 mapping
.addMapper(IdMapper
.NewInstance("TaxonFk"));
2601 mapping
.addMapper(ObjectChangeMapper
.NewInstance(TaxonBase
.class, TaxonName
.class, "Name"));
2603 mapping
.addMapper(DbObjectMapper
.NewInstance("NomenclaturalReference", "SourceFk"));
2604 // mapping.addMapper(DbObjectMapper.NewInstance("NomenclaturalReference", "SourceNameCache", IS_CACHE));
2605 mapping
.addMapper(MethodMapper
.NewInstance("SourceNameCache", this, TaxonName
.class));
2607 //we have only nomenclatural references here
2608 mapping
.addMapper(DbConstantMapper
.NewInstance("SourceUseFk", Types
.INTEGER
, PesiTransformer
.NOMENCLATURAL_REFERENCE
));
2609 mapping
.addMapper(DbConstantMapper
.NewInstance("SourceUseCache", Types
.VARCHAR
, state
.getTransformer().getSourceUseCacheByKey( PesiTransformer
.NOMENCLATURAL_REFERENCE
)));
2611 mapping
.addMapper(DbStringMapper
.NewInstance("NomenclaturalMicroReference", "SourceDetail"));
2618 protected boolean doCheck(PesiExportState state
) {
2623 protected boolean isIgnore(PesiExportState state
) {
2624 return ! state
.getConfig().isDoTaxa();