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
.Iterator
;
20 import java
.util
.List
;
23 import java
.util
.UUID
;
24 import java
.util
.regex
.Matcher
;
25 import java
.util
.regex
.Pattern
;
27 import org
.apache
.commons
.lang
.StringUtils
;
28 import org
.apache
.log4j
.Logger
;
29 import org
.joda
.time
.DateTime
;
30 import org
.joda
.time
.format
.DateTimeFormat
;
31 import org
.joda
.time
.format
.DateTimeFormatter
;
32 import org
.springframework
.stereotype
.Component
;
33 import org
.springframework
.transaction
.TransactionStatus
;
35 import eu
.etaxonomy
.cdm
.api
.service
.TaxonServiceImpl
;
36 import eu
.etaxonomy
.cdm
.common
.CdmUtils
;
37 import eu
.etaxonomy
.cdm
.io
.berlinModel
.BerlinModelTransformer
;
38 import eu
.etaxonomy
.cdm
.io
.common
.Source
;
39 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.UndefinedTransformerMethodException
;
40 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbConstantMapper
;
41 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbExtensionMapper
;
42 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbLastActionMapper
;
43 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbObjectMapper
;
44 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbStringMapper
;
45 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.IdMapper
;
46 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.MethodMapper
;
47 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.ObjectChangeMapper
;
48 import eu
.etaxonomy
.cdm
.io
.pesi
.erms
.ErmsTransformer
;
49 import eu
.etaxonomy
.cdm
.model
.common
.Annotation
;
50 import eu
.etaxonomy
.cdm
.model
.common
.AnnotationType
;
51 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
52 import eu
.etaxonomy
.cdm
.model
.common
.Extension
;
53 import eu
.etaxonomy
.cdm
.model
.common
.ExtensionType
;
54 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableEntity
;
55 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableSource
;
56 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
57 import eu
.etaxonomy
.cdm
.model
.common
.Marker
;
58 import eu
.etaxonomy
.cdm
.model
.common
.MarkerType
;
59 import eu
.etaxonomy
.cdm
.model
.common
.RelationshipBase
;
60 import eu
.etaxonomy
.cdm
.model
.name
.NameTypeDesignation
;
61 import eu
.etaxonomy
.cdm
.model
.name
.NameTypeDesignationStatus
;
62 import eu
.etaxonomy
.cdm
.model
.name
.NomenclaturalCode
;
63 import eu
.etaxonomy
.cdm
.model
.name
.NomenclaturalStatus
;
64 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
65 import eu
.etaxonomy
.cdm
.model
.name
.TaxonName
;
66 import eu
.etaxonomy
.cdm
.model
.reference
.INomenclaturalReference
;
67 import eu
.etaxonomy
.cdm
.model
.reference
.Reference
;
68 import eu
.etaxonomy
.cdm
.model
.taxon
.Classification
;
69 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
70 import eu
.etaxonomy
.cdm
.model
.taxon
.SynonymType
;
71 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
72 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
73 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
74 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationship
;
75 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationshipType
;
76 import eu
.etaxonomy
.cdm
.strategy
.cache
.HTMLTagRules
;
77 import eu
.etaxonomy
.cdm
.strategy
.cache
.TagEnum
;
78 import eu
.etaxonomy
.cdm
.strategy
.cache
.name
.INonViralNameCacheStrategy
;
79 import eu
.etaxonomy
.cdm
.strategy
.cache
.name
.TaxonNameDefaultCacheStrategy
;
80 import eu
.etaxonomy
.cdm
.strategy
.cache
.name
.ZooNameNoMarkerCacheStrategy
;
83 * The export class for {@link eu.etaxonomy.cdm.model.name.TaxonNameBase TaxonNames}.<p>
84 * Inserts into DataWarehouse database table <code>Taxon</code>.
85 * It is divided into four phases:<p><ul>
86 * <li>Phase 1: Export of all {@link eu.etaxonomy.cdm.model.name.TaxonName TaxonNames} except some data exported in the following phases.
87 * <li>Phase 2: Export of additional data: ParentTaxonFk and TreeIndex.
88 * <li>Phase 3: Export of additional data: Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk.
89 * <li>Phase 4: Export of Inferred Synonyms.</ul>
95 public class PesiTaxonExport
extends PesiExportBase
{
97 private static final long serialVersionUID
= -3412722058790200078L;
98 private static final Logger logger
= Logger
.getLogger(PesiTaxonExport
.class);
100 private static final Class
<?
extends CdmBase
> standardMethodParameter
= TaxonBase
.class;
102 private static int modCount
= 1000;
103 private static final String dbTableName
= "Taxon";
104 private static final String dbTableNameSynRel
= "RelTaxon";
105 private static final String dbTableAdditionalSourceRel
= "AdditionalTaxonSource";
107 private static final String pluralString
= "Taxa";
108 private static final String parentPluralString
= "Taxa";
110 private PreparedStatement parentTaxonFk_TreeIndex_KingdomFkStmt
;
111 private PreparedStatement parentTaxonFkStmt
;
112 private PreparedStatement rankTypeExpertsUpdateStmt
;
113 private PreparedStatement rankUpdateStmt
;
114 private Integer kingdomFk
;
115 private AnnotationType treeIndexAnnotationType
;
116 private static ExtensionType lastActionExtensionType
;
117 private static ExtensionType lastActionDateExtensionType
;
118 private static ExtensionType expertNameExtensionType
;
119 private static ExtensionType speciesExpertNameExtensionType
;
120 private static ExtensionType cacheCitationExtensionType
;
121 public static TaxonNameDefaultCacheStrategy zooNameStrategy
= ZooNameNoMarkerCacheStrategy
.NewInstance();
122 public static TaxonNameDefaultCacheStrategy nonViralNameStrategy
= TaxonNameDefaultCacheStrategy
.NewInstance();
123 private static int currentTaxonId
;
125 protected AnnotationType
getTreeIndexAnnotationType() {
126 return treeIndexAnnotationType
;
129 protected void setTreeIndexAnnotationType(AnnotationType treeIndexAnnotationType
) {
130 this.treeIndexAnnotationType
= treeIndexAnnotationType
;
141 public PesiTaxonExport() {
146 public Class
<?
extends CdmBase
> getStandardMethodParameter() {
147 return standardMethodParameter
;
151 protected void doInvoke(PesiExportState state
) {
153 logger
.info("*** Started Making " + pluralString
+ " ...");
155 initPreparedStatements(state
);
157 // Stores whether this invoke was successful or not.
158 boolean success
= true;
160 // PESI: Clear the database table Taxon.
163 // Get specific mappings: (CDM) Taxon -> (PESI) Taxon
164 PesiExportMapping mapping
= getMapping();
165 PesiExportMapping synonymRelMapping
= getSynRelMapping();
166 PesiExportMapping additionalSourceMapping
= getAdditionalSourceMapping(state
);
168 // Initialize the db mapper
169 mapping
.initialize(state
);
170 synonymRelMapping
.initialize(state
);
171 additionalSourceMapping
.initialize(state
);
173 // Find extensionTypes
174 lastActionExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.uuidExtLastAction
);
175 lastActionDateExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.uuidExtLastActionDate
);
176 expertNameExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.uuidExtExpertName
);
177 speciesExpertNameExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.uuidExtSpeciesExpertName
);
178 cacheCitationExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.uuidExtCacheCitation
);
181 success
&= doPhase01(state
, mapping
, additionalSourceMapping
);
183 //"PHASE 1b: Handle names without taxa ...
184 success
&= doNames(state
, additionalSourceMapping
);
186 // 2nd Round: Add ParentTaxonFk to each taxon
187 success
&= doPhase02(state
);
189 //PHASE 3: Add Rank data, KingdomFk, TypeNameFk ...
190 success
&= doPhase03(state
);
192 // 4nd Round: Add TreeIndex to each taxon
193 success
&= doPhase04(state
);
195 //"PHASE 5: Creating Inferred Synonyms...
196 success
&= doPhase05(state
, mapping
, synonymRelMapping
);
198 logger
.info("*** Finished Making " + pluralString
+ " ..." + getSuccessString(success
));
201 state
.getResult().addError("An error occurred in PesiTaxonExport.doInvoke. Success = false");
204 } catch (Exception e
) {
206 logger
.error(e
.getMessage());
207 state
.getResult().addException(e
);
212 private void initPreparedStatements(PesiExportState state
) throws SQLException
{
213 initTreeIndexStatement(state
);
214 initRankExpertsUpdateStmt(state
);
215 initRankUpdateStatement(state
);
217 initParentFkStatement(state
);
220 // Prepare TreeIndex-And-KingdomFk-Statement
221 private void initTreeIndexStatement(PesiExportState state
) throws SQLException
{
222 Connection connection
= state
.getConfig().getDestination().getConnection();
223 String parentTaxonFk_TreeIndex_KingdomFkSql
= "UPDATE Taxon SET ParentTaxonFk = ?, TreeIndex = ? WHERE TaxonId = ?";
224 parentTaxonFk_TreeIndex_KingdomFkStmt
= connection
.prepareStatement(parentTaxonFk_TreeIndex_KingdomFkSql
);
227 // Prepare TreeIndex-And-KingdomFk-Statement
228 private void initParentFkStatement(PesiExportState state
) throws SQLException
{
229 Connection connection
= state
.getConfig().getDestination().getConnection();
230 String parentTaxonFkSql
= "UPDATE Taxon SET ParentTaxonFk = ? WHERE TaxonId = ?";
231 parentTaxonFkStmt
= connection
.prepareStatement(parentTaxonFkSql
);
234 private void initRankUpdateStatement(PesiExportState state
) throws SQLException
{
235 Connection connection
= state
.getConfig().getDestination().getConnection();
236 String rankSql
= "UPDATE Taxon SET RankFk = ?, RankCache = ?, KingdomFk = ? WHERE TaxonId = ?";
237 rankUpdateStmt
= connection
.prepareStatement(rankSql
);
240 private void initRankExpertsUpdateStmt(PesiExportState state
) throws SQLException
{
241 // String sql_old = "UPDATE Taxon SET RankFk = ?, RankCache = ?, TypeNameFk = ?, KingdomFk = ?, " +
242 // "ExpertFk = ?, SpeciesExpertFk = ? WHERE TaxonId = ?";
243 //TODO handle experts GUIDs
244 Connection connection
= state
.getConfig().getDestination().getConnection();
246 String sql
= "UPDATE Taxon SET RankFk = ?, RankCache = ?, TypeNameFk = ?, KingdomFk = ? " +
247 " WHERE TaxonId = ?";
248 rankTypeExpertsUpdateStmt
= connection
.prepareStatement(sql
);
251 private boolean doPhase01(PesiExportState state
, PesiExportMapping mapping
, PesiExportMapping additionalSourceMapping
){
254 List
<TaxonBase
> list
;
255 boolean success
= true;
256 // Get the limit for objects to save within a single transaction.
257 int limit
= state
.getConfig().getLimitSave();
259 logger
.info("PHASE 1: Export Taxa...limit is " + limit
);
261 TransactionStatus txStatus
= startTransaction(true);
262 if (logger
.isDebugEnabled()) {
263 logger
.info("Started new transaction. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
264 logger
.info("Taking snapshot at the beginning of phase 1 of taxonExport");
265 //ProfilerController.memorySnapshot();
268 int partitionCount
= 0;
269 while ((list
= getNextTaxonPartition(null, limit
, partitionCount
++, null)) != null ) {
271 logger
.debug("Fetched " + list
.size() + " " + pluralString
+ ". Exporting...");
273 for (TaxonBase
<?
> taxon
: list
) {
274 doCount(count
++, modCount
, pluralString
);
275 TaxonName taxonName
= taxon
.getName();
277 TaxonName nvn
= CdmBase
.deproxy(taxonName
);
278 // System.err.println(nvn.getTitleCache());
279 if (! nvn
.isProtectedTitleCache()){
280 nvn
.setTitleCache(null, false);
282 if (! nvn
.isProtectedNameCache()){
283 nvn
.setNameCache(null, false);
285 if (! nvn
.isProtectedFullTitleCache()){
286 nvn
.setFullTitleCache(null, false);
288 if (! nvn
.isProtectedAuthorshipCache()){
289 nvn
.setAuthorshipCache(null, false);
292 if (nvn
.getRank().equals(Rank
.KINGDOM())){
293 if(taxon
.isInstanceOf(Taxon
.class)){
294 String treeIndex
= ((Taxon
)taxon
).getTaxonNodes().iterator().next().treeIndex();
295 Integer kingdomId
= PesiTransformer
.pesiKingdomMap
.get(nvn
.getGenusOrUninomial());
296 state
.getTreeIndexKingdomMap().put(treeIndex
, kingdomId
);
298 logger
.warn("Kingdom taxon is not of class Taxon but " + taxon
.getClass().getSimpleName() + ": " + nvn
.getGenusOrUninomial());
301 }catch(NullPointerException e
){
302 logger
.error(nvn
.getTitleCache() + " has no Rank!");
303 System
.err
.println(nvn
.getTitleCache() + " has no Rank!");
306 success
&= mapping
.invoke(taxon
);
308 if (nvn
.getNomenclaturalReference() != null || StringUtils
.isNotBlank(nvn
.getNomenclaturalMicroReference() )){
309 additionalSourceMapping
.invoke(taxon
);
312 //TODO switch on again, leads to some warnings in ERMS for taxa of not correctly handled kingdoms
313 // validatePhaseOne(taxon, nvn);
316 // Commit transaction
317 commitTransaction(txStatus
);
318 logger
.debug("Committed transaction.");
319 logger
.info("Exported " + (count
- pastCount
) + " " + pluralString
+ ". Total: " + count
+ " (Phase 01)");
321 /*logger.warn("Taking snapshot at the end of the loop of phase 1 of taxonExport");
322 //ProfilerController.memorySnapshot();
325 txStatus
= startTransaction(true);
326 if (logger
.isDebugEnabled()) {
327 logger
.info("Started new transaction. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
331 logger
.info("No " + pluralString
+ " left to fetch.");
333 // Commit transaction
334 commitTransaction(txStatus
);
336 logger
.debug("Committed transaction.");
337 if (logger
.isDebugEnabled()){
338 logger
.debug("Taking snapshot at the end of phase 1 of taxonExport");
339 // ProfilerController.memorySnapshot();
345 private void validatePhaseOne(TaxonBase
<?
> taxon
, TaxonName taxonName
) {
347 // Check whether some rules are violated
348 NomenclaturalCode nomenclaturalCode
= taxonName
.getNameType();
349 String genusOrUninomial
= taxonName
.getGenusOrUninomial();
350 String specificEpithet
= taxonName
.getSpecificEpithet();
351 String infraSpecificEpithet
= taxonName
.getInfraSpecificEpithet();
352 String infraGenericEpithet
= taxonName
.getInfraGenericEpithet();
353 Integer rankFk
= getRankFk(taxonName
, nomenclaturalCode
);
355 if (rankFk
== null) {
356 logger
.error("Rank was not determined: " + taxon
.getUuid() + " (" + taxon
.getTitleCache() + ")");
359 // Check whether infraGenericEpithet is set correctly
360 // 1. Childs of an accepted taxon of rank subgenus that are accepted taxa of rank species have to have an infraGenericEpithet
361 // 2. Grandchilds of an accepted taxon of rank subgenus that are accepted taxa of rank subspecies have to have an infraGenericEpithet
363 int ancestorLevel
= 0;
364 if (taxonName
.getRank().equals(Rank
.SUBSPECIES())) {
365 // The accepted taxon two rank levels above should be of rank subgenus
368 if (taxonName
.getRank().equals(Rank
.SPECIES())) {
369 // The accepted taxon one rank level above should be of rank subgenus
372 if (ancestorLevel
> 0) {
373 if (validateAncestorOfSpecificRank(taxon
, ancestorLevel
, Rank
.SUBGENUS())) {
374 // The child (species or subspecies) of this parent (subgenus) has to have an infraGenericEpithet
375 if (infraGenericEpithet
== null) {
376 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() + ")");
377 // maybe the taxon could be named here
382 if (infraGenericEpithet
== null && rankFk
.intValue() == 190) {
383 logger
.warn("InfraGenericEpithet was not determined although it should exist for rank 190: " + taxon
.getUuid() + " (" + taxon
.getTitleCache() + ")");
385 if (specificEpithet
!= null && rankFk
.intValue() < 216) {
386 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() + ")");
388 if (infraSpecificEpithet
!= null && rankFk
.intValue() < 225) {
389 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() + ")";
390 if (StringUtils
.isNotBlank(infraSpecificEpithet
)){
391 logger
.warn(message
);
393 logger
.warn(message
);
397 if (infraSpecificEpithet
!= null && specificEpithet
== null) {
398 logger
.warn("An infraSpecificEpithet was determined, but a specificEpithet was not determined: " + taxon
.getUuid() + " (" + taxon
.getTitleCache() + ")");
400 if (genusOrUninomial
== null) {
401 logger
.warn("GenusOrUninomial was not determined: " + taxon
.getUuid() + " (" + taxon
.getTitleCache() + ")");
406 * 2nd Round: Add ParentTaxonFk to each taxon and add Biota if not exists
410 private boolean doPhase02(PesiExportState state
) {
413 boolean success
= true;
414 if (! state
.getConfig().isDoParentAndBiota()){
415 logger
.info ("Ignore PHASE 2: Make ParentFk and Biota...");
421 // Get the limit for objects to save within a single transaction.
422 int limit
= state
.getConfig().getLimitSave();
426 logger
.info("PHASE 2: Make ParentFk and Biota ... limit is " + limit
);
428 TransactionStatus txStatus
= startTransaction(true);
429 int partitionCount
= 0;
431 // ProfilerController.memorySnapshot();
432 while ((list
= getNextTaxonPartition(Taxon
.class, limit
, partitionCount
++, null)) != null ) {
434 if(logger
.isDebugEnabled()) {
435 logger
.info("Fetched " + list
.size() + " " + pluralString
+ ". Exporting...");
437 for (Taxon taxon
: list
) {
438 for (TaxonNode node
: taxon
.getTaxonNodes()){
439 doCount(count
++, modCount
, pluralString
);
440 TaxonNode parentNode
= node
.getParent();
441 if (parentNode
!= null && parentNode
.getTaxon() != null){ //new root node handling requires has root taxon with taxon == null
442 int childId
= state
.getDbId( taxon
);
443 int parentId
= state
.getDbId(parentNode
.getTaxon());
444 success
&= invokeParentTaxonFk(parentId
, childId
);
449 // Commit transaction
450 commitTransaction(txStatus
);
451 logger
.info("Exported " + (count
- pastCount
) + " " + pluralString
+ ". Total: " + count
+ " (Phase 2)");
454 txStatus
= startTransaction(true);
455 if (logger
.isDebugEnabled()){
456 logger
.info("Started new transaction. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
459 logger
.info("No " + pluralString
+ " left to fetch.");
461 // Commit transaction
462 commitTransaction(txStatus
);
468 * Inserts the Biota Taxon if not yet exists.
470 * @throws SQLException
472 private void insertBiota(PesiExportState state
) {
474 ResultSet rs
= state
.getConfig().getDestination().getResultSet("SELECT * FROM Taxon WHERE GenusOrUninomial = 'Biota' ");
475 if (rs
.next() == false){
476 int biotaId
= state
.getConfig().getNameIdStart() -1 ;
477 String sqlInsertBiota
= "INSERT INTO Taxon (TaxonId, KingdomFk, RankFk, RankCache, GenusOrUninomial, WebSearchName, WebShowName, FullName, DisplayName, TaxonStatusFk, TaxonStatusCache) " +
478 " VALUES (" + biotaId
+ ", 0, 0, 'Superdomain', 'Biota', 'Biota', '<i>Biota</i>', 'Biota', '<i>Biota</i>', 1 , 'accepted')";
479 state
.getConfig().getDestination().update(sqlInsertBiota
);
482 } catch (SQLException e
) {
483 logger
.warn ("Biota could not be requested or inserted");
487 // 4th round: Add TreeIndex to each taxon
488 private boolean doPhase04(PesiExportState state
) {
489 boolean success
= true;
491 logger
.info("PHASE 4: Make TreeIndex ... ");
493 //TODO test if possible to move to phase 02
494 String sql
= " UPDATE Taxon SET ParentTaxonFk = (SELECT TaxonId FROM Taxon WHERE RankFk = 0) " +
495 " WHERE (RankFk = 10) and TaxonStatusFk = 1 ";
496 state
.getConfig().getDestination().update(sql
);
498 state
.getConfig().getDestination().update("EXEC dbo.recalculateallstoredpaths");
500 logger
.info("PHASE 4: Make TreeIndex DONE");
507 // // 2nd Round: Add ParentTaxonFk, TreeIndex to each Taxon
508 // private boolean doPhase02_OLD(PesiExportState state) {
509 // boolean success = true;
510 // boolean includeUnpublished = false;
511 // if (! state.getConfig().isDoTreeIndex()){
512 // logger.info ("Ignore PHASE 2: ParentTaxonFk and TreeIndex");
516 // List<Classification> classificationList = null;
517 // logger.info("PHASE 2: Add ParenTaxonFk and TreeIndex...");
519 // // Specify starting ranks for tree traversing
520 // rankList.add(Rank.KINGDOM());
521 // rankList.add(Rank.GENUS());
523 // // Specify where to stop traversing (value) when starting at a specific Rank (key)
524 // rank2endRankMap.put(Rank.GENUS(), null); // Since NULL does not match an existing Rank, traverse all the way down to the leaves
525 // rank2endRankMap.put(Rank.KINGDOM(), Rank.GENUS()); // excludes rank genus
527 // StringBuffer treeIndex = new StringBuffer();
529 // // Retrieve list of classifications
530 // TransactionStatus txStatus = startTransaction(true);
531 // logger.info("Started transaction for parentFk and treeIndex. Fetching all classifications...");
532 // classificationList = getClassificationService().listClassifications(null, 0, null, null);
533 // commitTransaction(txStatus);
534 // logger.debug("Committed transaction.");
536 // logger.info("Fetched " + classificationList.size() + " classification(s).");
538 // setTreeIndexAnnotationType(getAnnotationType(uuidTreeIndex, "TreeIndex", "TreeIndex", "TI"));
539 // List<TaxonNode> rankSpecificRootNodes;
540 // for (Classification classification : classificationList) {
541 // for (Rank rank : rankList) {
543 // txStatus = startTransaction(true);
544 // logger.info("Started transaction to fetch all rootNodes specific to Rank " + rank.getLabel() + " ...");
546 // rankSpecificRootNodes = getClassificationService().listRankSpecificRootNodes(classification,
547 // null, rank, includeUnpublished, null, null, null);
548 // logger.info("Fetched " + rankSpecificRootNodes.size() + " RootNodes for Rank " + rank.getLabel());
550 // commitTransaction(txStatus);
551 // logger.debug("Committed transaction.");
553 // for (TaxonNode rootNode : rankSpecificRootNodes) {
554 // txStatus = startTransaction(false);
555 // Rank endRank = rank2endRankMap.get(rank);
556 // if (endRank != null) {
557 // logger.debug("Started transaction to traverse childNodes of rootNode (" + rootNode.getUuid() + ") till Rank " + endRank.getLabel() + " ...");
559 // logger.debug("Started transaction to traverse childNodes of rootNode (" + rootNode.getUuid() + ") till leaves are reached ...");
562 // TaxonNode newNode = getTaxonNodeService().load(rootNode.getUuid());
564 // if (isPesiTaxon(newNode.getTaxon())){
565 // TaxonNode parentNode = newNode.getParent();
566 // if (rank.equals(Rank.KINGDOM())) {
567 // treeIndex = new StringBuffer();
568 // treeIndex.append("#");
570 // // Get treeIndex from parentNode
571 // if (parentNode != null) {
572 // boolean annotationFound = false;
573 // Set<Annotation> annotations = parentNode.getAnnotations();
574 // for (Annotation annotation : annotations) {
575 // AnnotationType annotationType = annotation.getAnnotationType();
576 // if (annotationType != null && annotationType.equals(getTreeIndexAnnotationType())) {
577 // treeIndex = new StringBuffer(CdmUtils.Nz(annotation.getText()));
578 // annotationFound = true;
579 // // logger.error("treeIndex: " + treeIndex);
583 // if (!annotationFound) {
584 // // This should not happen because it means that the treeIndex was not set correctly as an annotation to parentNode
585 // logger.error("TreeIndex could not be read from annotation of TaxonNode: " + parentNode.getUuid() + ", Taxon: " + parentNode.getTaxon().getUuid());
586 // treeIndex = new StringBuffer();
587 // treeIndex.append("#");
590 // // TreeIndex could not be determined, but it's unclear how to proceed to generate a correct treeIndex if the parentNode is NULL
591 // logger.error("ParentNode for RootNode is NULL. TreeIndex could not be determined: " + newNode.getUuid());
592 // treeIndex = new StringBuffer(); // This just prevents growing of the treeIndex in a wrong manner
593 // treeIndex.append("#");
596 // nomenclaturalCode = newNode.getTaxon().getName().getNameType();
597 // kingdomFk = PesiTransformer.nomenclaturalCode2Kingdom(nomenclaturalCode);
598 // traverseTree(newNode, parentNode, treeIndex, endRank, state);
601 // logger.debug("Taxon is not a PESI taxon: " + newNode.getTaxon().getUuid());
607 // commitTransaction(txStatus);
608 // logger.debug("Committed transaction.");
609 // } catch (Exception e) {
610 // logger.error(e.getMessage());
611 // e.printStackTrace();
615 // rankSpecificRootNodes = null;
620 // logger.warn("Taking snapshot at the end of phase 2 of taxonExport");
621 // //ProfilerController.memorySnapshot();
625 //PHASE 3: Add Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk...
626 private boolean doPhase03(PesiExportState state
) {
629 boolean success
= true;
630 if (! state
.getConfig().isDoTreeIndex()){
631 logger
.info ("Ignore PHASE 3: Add Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk...");
634 // Get the limit for objects to save within a single transaction.
635 int limit
= state
.getConfig().getLimitSave();
637 List
<TaxonBase
> list
;
638 logger
.info("PHASE 3: Add Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk...");
639 // Be sure to add rank information, KingdomFk, TypeNameFk, expertFk and speciesExpertFk to every taxonName
642 TransactionStatus txStatus
= startTransaction(true);
643 if (logger
.isDebugEnabled()) {
644 logger
.info("Started new transaction for rank, kingdom, typeName, expertFk and speciesExpertFK. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
646 int partitionCount
= 0;
647 while ((list
= getNextTaxonPartition(TaxonBase
.class, limit
, partitionCount
++, null)) != null) {
649 if (logger
.isDebugEnabled()) {
650 logger
.debug("Fetched " + list
.size() + " " + pluralString
+ ". Exporting...");
652 for (TaxonBase
<?
> taxon
: list
) {
653 TaxonName taxonName
= CdmBase
.deproxy(taxon
.getName());
654 // Determine expertFk
655 // Integer expertFk = makeExpertFk(state, taxonName);
657 // // Determine speciesExpertFk
658 // Integer speciesExpertFk = makeSpeciesExpertFk(state, taxonName);
660 doCount(count
++, modCount
, pluralString
);
661 Integer typeNameFk
= getTypeNameFk(taxonName
, state
);
662 Integer kingdomFk
= findKingdomIdFromTreeIndex(taxon
, state
);
663 // PesiTransformer.nomenClaturalCode2Kingdom(nomenclaturalCode);
665 //TODO why are expertFks needed? (Andreas M.)
666 // if (expertFk != null || speciesExpertFk != null) {
667 NomenclaturalCode nomCode
= taxonName
.getNameType();
668 //is there a reason why we do pass nomCode separately? Before nomCode was class variable, but not clear why and when it was set
669 invokeRankDataAndTypeNameFkAndKingdomFk(taxonName
, nomCode
, state
.getDbId(taxon
),
670 typeNameFk
, kingdomFk
, state
);
674 // Commit transaction
675 commitTransaction(txStatus
);
676 if (logger
.isDebugEnabled()){logger
.debug("Committed transaction.");}
677 logger
.info("Exported " + (count
- pastCount
) + " " + pluralString
+ ". Total: " + count
+ " (Phase 3)");
681 txStatus
= startTransaction(true);
682 if (logger
.isDebugEnabled()) {
683 logger
.info("Started new transaction for rank, kingdom, typeName, expertFk and speciesExpertFK. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
686 logger
.info("No " + pluralString
+ " left to fetch.");
688 // Commit transaction
689 commitTransaction(txStatus
);
691 if (logger
.isDebugEnabled()){
692 logger
.debug("Committed transaction.");
693 logger
.debug("Try to take snapshot at the end of phase 3 of taxonExport, number of partitions: " + partitionCount
);
694 //ProfilerController.memorySnapshot();
699 private static Integer
findKingdomIdFromTreeIndex(TaxonBase
<?
> taxonBase
,PesiExportState state
) {
701 if (taxonBase
instanceof Synonym
){
702 taxon
= ((Synonym
) taxonBase
).getAcceptedTaxon();
704 taxon
= checkPseudoOrRelatedTaxon((Taxon
)taxonBase
);
707 Set
<TaxonNode
> nodes
= taxon
.getTaxonNodes();
709 logger
.warn("The taxon has more then 1 taxon node: " + taxon
.getTitleCache() + ". Take arbitrary one.");
711 if (!nodes
.isEmpty()){
712 String treeIndex
= nodes
.iterator().next().treeIndex();
714 Pattern pattern
= Pattern
.compile("#t[0-9]+#([0-9]+#){3}");
715 Matcher matcher
= pattern
.matcher(treeIndex
);
716 Integer kingdomID
= null;
718 String treeIndexKingdom
= matcher
.group(0);
719 kingdomID
= state
.getTreeIndexKingdomMap().get(treeIndexKingdom
);
721 pattern
= Pattern
.compile("#t[0-9]+#([0-9]+#){2}");
722 matcher
= pattern
.matcher(treeIndex
);
724 String treeIndexKingdom
= matcher
.group(0);
725 kingdomID
= state
.getTreeIndexKingdomMap().get(treeIndexKingdom
);
728 if(Rank
.DOMAIN().equals(taxon
.getName().getRank())){
731 if(kingdomID
== null){
732 logger
.warn("Kingdom could not be defined for treeindex " + treeIndex
);
736 NomenclaturalCode nomenclaturalCode
= taxon
.getName().getNameType();
737 logger
.warn("The taxon has no nodes: " + taxon
.getTitleCache() + ". The kingdom is taken from the nomenclatural code: " + PesiTransformer
.nomenclaturalCode2Kingdom(nomenclaturalCode
));
738 return PesiTransformer
.nomenclaturalCode2Kingdom(nomenclaturalCode
);
741 NomenclaturalCode nomenclaturalCode
= taxonBase
.getName().getNameType();
742 logger
.warn("Taxon is synonym with no accepted taxon attached: " + taxonBase
.getTitleCache() + ". The kingdom is taken from the nomenclatural code: " + PesiTransformer
.nomenclaturalCode2Kingdom(nomenclaturalCode
) );
743 return PesiTransformer
.nomenclaturalCode2Kingdom(nomenclaturalCode
);
747 private static Taxon
checkPseudoOrRelatedTaxon(Taxon taxon
) {
748 if (!taxon
.getTaxonNodes().isEmpty()){
750 }else if(hasPseudoTaxonRelationship(taxon
)){
751 return acceptedPseudoTaxon(taxon
);
752 }else if(isMisappliedNameOrProParteSynonym(taxon
)){
753 return acceptedTaxonConcept(taxon
);
759 private static Taxon
acceptedPseudoTaxon(Taxon taxon
) {
760 for (TaxonRelationship rel
: taxon
.getRelationsFromThisTaxon()){
761 if (TaxonRelationshipType
.pseudoTaxonUuids().contains(rel
.getType().getUuid())){
762 return rel
.getToTaxon();
768 private static Taxon
acceptedTaxonConcept(Taxon taxon
) {
769 for (TaxonRelationship rel
: taxon
.getRelationsFromThisTaxon()){
770 if (TaxonRelationshipType
.misappliedNameUuids().contains(rel
.getType().getUuid())||
771 TaxonRelationshipType
.proParteOrPartialSynonymUuids().contains(rel
.getType().getUuid())){
772 return rel
.getToTaxon();
778 private static boolean hasPseudoTaxonRelationship(Taxon taxon
) {
779 for (TaxonRelationship rel
: taxon
.getRelationsFromThisTaxon()){
780 if (TaxonRelationshipType
.pseudoTaxonUuids().contains(rel
.getType().getUuid())){
787 private static boolean isMisappliedNameOrProParteSynonym(Taxon taxon
) {
788 for (TaxonRelationship rel
: taxon
.getRelationsFromThisTaxon()){
789 if (TaxonRelationshipType
.misappliedNameUuids().contains(rel
.getType().getUuid())||
790 TaxonRelationshipType
.proParteOrPartialSynonymUuids().contains(rel
.getType().getUuid())){
797 // "PHASE 5: Creating Inferred Synonyms..."
798 private boolean doPhase05(PesiExportState state
, PesiExportMapping mapping
, PesiExportMapping synRelMapping
) {
801 boolean success
= true;
802 // Get the limit for objects to save within a single transaction.
803 if (! state
.getConfig().isDoInferredSynonyms()){
804 logger
.info ("Ignore PHASE 5: Creating Inferred Synonyms...");
808 int limit
= state
.getConfig().getLimitSave();
809 // Create inferred synonyms for accepted taxa
810 logger
.info("PHASE 5: Creating Inferred Synonyms...");
812 // Determine the count of elements in data warehouse database table Taxon
813 currentTaxonId
= determineTaxonCount(state
);
818 int pageSize
= limit
/10;
820 String inferredSynonymPluralString
= "Inferred Synonyms";
823 TransactionStatus txStatus
= startTransaction(true);
824 if (logger
.isDebugEnabled()) {
825 logger
.info("Started new transaction. Fetching some " + parentPluralString
+ " first (max: " + limit
+ ") ...");
827 List
<TaxonBase
> taxonList
= null;
829 while ((taxonList
= getTaxonService().listTaxaByName(Taxon
.class, "*", "*", "*", "*", "*", Rank
.SPECIES(), pageSize
, pageNumber
)).size() > 0) {
831 Map
<Integer
, TaxonName
> inferredSynonymsDataToBeSaved
= new HashMap
<>();
833 if (logger
.isDebugEnabled()) {
834 logger
.info("Fetched " + taxonList
.size() + " " + parentPluralString
+ ". Exporting...");
836 inferredSynonymsDataToBeSaved
.putAll(createInferredSynonymsForTaxonList(state
, mapping
,
837 synRelMapping
, taxonList
));
839 doCount(count
+= taxonList
.size(), modCount
, inferredSynonymPluralString
);
840 // Commit transaction
841 commitTransaction(txStatus
);
842 if (logger
.isDebugEnabled()){logger
.debug("Committed transaction.");}
843 logger
.info("Exported " + (taxonList
.size()) + " " + inferredSynonymPluralString
+ ". Total: " + count
);
846 // Save Rank Data and KingdomFk for inferred synonyms
847 for (Integer taxonFk
: inferredSynonymsDataToBeSaved
.keySet()) {
848 TaxonName taxonName
= inferredSynonymsDataToBeSaved
.get(taxonFk
);
849 NomenclaturalCode nomCode
= taxonName
.getNameType(); //nomCode was class variable before, not sure if this was important
850 invokeRankDataAndKingdomFk(inferredSynonymsDataToBeSaved
.get(taxonFk
), nomCode
, taxonFk
, kingdomFk
, state
);
854 txStatus
= startTransaction(true);
855 if (logger
.isDebugEnabled()) {
856 logger
.info("Started new transaction. Fetching some " + parentPluralString
+ " first (max: " + limit
+ ") ...");
859 // Increment pageNumber
863 while ((taxonList
= getTaxonService().listTaxaByName(Taxon
.class, "*", "*", "*", "*", "*", Rank
.SUBSPECIES(), pageSize
, pageNumber
)).size() > 0) {
864 Map
<Integer
, TaxonName
> inferredSynonymsDataToBeSaved
= new HashMap
<>();
866 logger
.info("Fetched " + taxonList
.size() + " " + parentPluralString
+ ". Exporting...");
867 inferredSynonymsDataToBeSaved
.putAll(createInferredSynonymsForTaxonList(state
, mapping
,
868 synRelMapping
, taxonList
));
870 doCount(count
+= taxonList
.size(), modCount
, inferredSynonymPluralString
);
871 // Commit transaction
872 commitTransaction(txStatus
);
873 logger
.debug("Committed transaction.");
874 logger
.info("Exported " + taxonList
.size()+ " " + inferredSynonymPluralString
+ ". Total: " + count
);
877 // Save Rank Data and KingdomFk for inferred synonyms
878 for (Integer taxonFk
: inferredSynonymsDataToBeSaved
.keySet()) {
879 TaxonName taxonName
= inferredSynonymsDataToBeSaved
.get(taxonFk
);
880 NomenclaturalCode nomCode
= taxonName
.getNameType(); //nomCode was class variable before, not sure if this was important
881 invokeRankDataAndKingdomFk(inferredSynonymsDataToBeSaved
.get(taxonFk
), nomCode
, taxonFk
, kingdomFk
, state
);
885 txStatus
= startTransaction(true);
886 logger
.info("Started new transaction. Fetching some " + parentPluralString
+ " first (max: " + limit
+ ") ...");
888 // Increment pageNumber
890 inferredSynonymsDataToBeSaved
= null;
892 if (taxonList
.size() == 0) {
893 logger
.info("No " + parentPluralString
+ " left to fetch.");
897 // logger.warn("Taking snapshot at the end of phase 5 of taxonExport");
898 // ProfilerController.memorySnapshot();
900 // Commit transaction
901 commitTransaction(txStatus
);
903 logger
.debug("Taking snapshot at the end of phase 5 after gc() of taxonExport");
904 //ProfilerController.memorySnapshot();
905 logger
.debug("Committed transaction.");
912 * @param synRelMapping
913 * @param currentTaxonId
915 * @param inferredSynonymsDataToBeSaved
918 private Map
<Integer
, TaxonName
> createInferredSynonymsForTaxonList(PesiExportState state
,
919 PesiExportMapping mapping
, PesiExportMapping synRelMapping
, List
<TaxonBase
> taxonList
) {
922 Classification classification
= null;
923 List
<Synonym
> inferredSynonyms
= null;
924 boolean localSuccess
= true;
926 Map
<Integer
, TaxonName
> inferredSynonymsDataToBeSaved
= new HashMap
<>();
928 for (TaxonBase
<?
> taxonBase
: taxonList
) {
930 if (taxonBase
.isInstanceOf(Taxon
.class)) { // this should always be the case since we should have fetched accepted taxon only, but you never know...
931 acceptedTaxon
= CdmBase
.deproxy(taxonBase
, Taxon
.class);
932 TaxonName taxonName
= acceptedTaxon
.getName();
934 if (taxonName
.isZoological()) {
935 kingdomFk
= findKingdomIdFromTreeIndex(taxonBase
, state
);
937 Set
<TaxonNode
> taxonNodes
= acceptedTaxon
.getTaxonNodes();
938 TaxonNode singleNode
= null;
940 if (taxonNodes
.size() > 0) {
941 // Determine the classification of the current TaxonNode
943 singleNode
= taxonNodes
.iterator().next();
944 if (singleNode
!= null) {
945 classification
= singleNode
.getClassification();
947 logger
.error("A TaxonNode belonging to this accepted Taxon is NULL: " + acceptedTaxon
.getUuid() + " (" + acceptedTaxon
.getTitleCache() +")");
950 // Classification could not be determined directly from this TaxonNode
951 // The stored classification from another TaxonNode is used. It's a simple, but not a failsafe fallback solution.
952 if (taxonNodes
.size() == 0) {
953 //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");
957 if (classification
!= null) {
959 TaxonName name
= acceptedTaxon
.getName();
960 //if (name.isSpecies() || name.isInfraSpecific()){
961 inferredSynonyms
= getTaxonService().createAllInferredSynonyms(acceptedTaxon
, classification
, true);
963 // inferredSynonyms = getTaxonService().createInferredSynonyms(classification, acceptedTaxon, SynonymType.INFERRED_GENUS_OF());
964 if (inferredSynonyms
!= null) {
965 for (Synonym synonym
: inferredSynonyms
) {
966 // TaxonName synonymName = synonym.getName();
967 MarkerType markerType
=getUuidMarkerType(PesiTransformer
.uuidMarkerGuidIsMissing
, state
);
968 synonym
.addMarker(Marker
.NewInstance(markerType
, true));
969 // Both Synonym and its TaxonName have no valid Id yet
970 synonym
.setId(currentTaxonId
++);
973 localSuccess
&= mapping
.invoke(synonym
);
974 //get SynonymRelationship and export
975 if (synonym
.getAcceptedTaxon() == null ){
976 IdentifiableSource source
= synonym
.getSources().iterator().next();
977 if (source
.getIdNamespace().contains("Potential combination")){
978 acceptedTaxon
.addSynonym(synonym
, SynonymType
.POTENTIAL_COMBINATION_OF());
979 logger
.error(synonym
.getTitleCache() + " is not attached to " + acceptedTaxon
.getTitleCache() + " type is set to potential combination");
980 } else if (source
.getIdNamespace().contains("Inferred Genus")){
981 acceptedTaxon
.addSynonym(synonym
, SynonymType
.INFERRED_GENUS_OF());
982 logger
.error(synonym
.getTitleCache() + " is not attached to " + acceptedTaxon
.getTitleCache() + " type is set to inferred genus");
983 } else if (source
.getIdNamespace().contains("Inferred Epithet")){
984 acceptedTaxon
.addSynonym(synonym
, SynonymType
.INFERRED_EPITHET_OF());
985 logger
.error(synonym
.getTitleCache() + " is not attached to " + acceptedTaxon
.getTitleCache() + " type is set to inferred epithet");
987 acceptedTaxon
.addSynonym(synonym
, SynonymType
.INFERRED_SYNONYM_OF());
988 logger
.error(synonym
.getTitleCache() + " is not attached to " + acceptedTaxon
.getTitleCache() + " type is set to inferred synonym");
991 localSuccess
&= synRelMapping
.invoke(synonym
);
993 logger
.error("Synonym relationship export failed " + synonym
.getTitleCache() + " accepted taxon: " + acceptedTaxon
.getUuid() + " (" + acceptedTaxon
.getTitleCache()+")");
996 localSuccess
&= synRelMapping
.invoke(synonym
);
998 logger
.error("Synonym relationship export failed " + synonym
.getTitleCache() + " accepted taxon: " + acceptedTaxon
.getUuid() + " (" + acceptedTaxon
.getTitleCache()+")");
1000 logger
.info("Synonym relationship successfully exported: " + synonym
.getTitleCache() + " " +acceptedTaxon
.getUuid() + " (" + acceptedTaxon
.getTitleCache()+")");
1004 inferredSynonymsDataToBeSaved
.put(synonym
.getId(), synonym
.getName());
1007 }catch(Exception e
){
1008 logger
.error(e
.getMessage());
1009 e
.printStackTrace();
1012 logger
.error("Classification is NULL. Inferred Synonyms could not be created for this Taxon: " + acceptedTaxon
.getUuid() + " (" + acceptedTaxon
.getTitleCache() + ")");
1015 // logger.error("TaxonName is not a ZoologicalName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
1018 logger
.error("This TaxonBase is not a Taxon even though it should be: " + taxonBase
.getUuid() + " (" + taxonBase
.getTitleCache() + ")");
1021 return inferredSynonymsDataToBeSaved
;
1026 * Handles names that do not appear in taxa
1030 private boolean doNames(PesiExportState state
, PesiExportMapping additionalSourceMapping
) throws SQLException
{
1032 boolean success
= true;
1033 if (! state
.getConfig().isDoPureNames()){
1034 logger
.info ("Ignore PHASE 1b: PureNames");
1039 PesiExportMapping mapping
= getPureNameMapping(state
);
1040 mapping
.initialize(state
);
1043 List
<TaxonName
> list
;
1045 // Get the limit for objects to save within a single transaction.
1046 int limit
= state
.getConfig().getLimitSave();
1048 logger
.info("PHASE 1b: Export Pure Names ...");
1049 // Start transaction
1050 TransactionStatus txStatus
= startTransaction(true);
1051 logger
.info("Started new transaction for Pure Names. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
1053 int partitionCount
= 0;
1054 while ((list
= getNextPureNamePartition(null, limit
, partitionCount
++)) != null ) {
1056 logger
.info("Fetched " + list
.size() + " names without taxa. Exporting...");
1057 for (TaxonName taxonName
: list
) {
1058 doCount(count
++, modCount
, pluralString
);
1059 success
&= mapping
.invoke(taxonName
);
1061 if (taxonName
.getNomenclaturalReference() != null || StringUtils
.isNotBlank(taxonName
.getNomenclaturalMicroReference() )){
1062 additionalSourceMapping
.invoke(taxonName
);
1066 // Commit transaction
1067 commitTransaction(txStatus
);
1068 logger
.debug("Committed transaction.");
1069 logger
.info("Exported " + (count
- pastCount
) + " " + pluralString
+ ". Total: " + count
);
1072 // Start transaction
1073 txStatus
= startTransaction(true);
1074 logger
.info("Started new transaction for PureNames. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
1076 logger
.info("No " + pluralString
+ " left to fetch.");
1078 // Commit transaction
1079 commitTransaction(txStatus
);
1080 logger
.debug("Committed transaction.");
1081 } catch (Exception e
) {
1082 logger
.error("Error occurred in pure name export");
1083 e
.printStackTrace();
1090 * Determines the current number of entries in the DataWarehouse database table <code>Taxon</code>.
1091 * @param state The {@link PesiExportState PesiExportState}.
1092 * @return The count.
1094 private Integer
determineTaxonCount(PesiExportState state
) {
1095 Integer result
= null;
1096 PesiExportConfigurator pesiConfig
= state
.getConfig();
1099 Source destination
= pesiConfig
.getDestination();
1100 sql
= "SELECT max(taxonId) FROM Taxon";
1101 destination
.setQuery(sql
);
1102 ResultSet resultSet
= destination
.getResultSet();
1105 result
= resultSet
.getInt(1);
1106 } catch (SQLException e
) {
1107 logger
.error("TaxonCount could not be determined: " + e
.getMessage());
1108 e
.printStackTrace();
1115 * Checks whether a parent at specific level has a specific Rank.
1116 * @param taxonName A {@link TaxonNameBase TaxonName}.
1117 * @param level The ancestor level.
1118 * @param ancestorRank The ancestor rank.
1119 * @return Whether a parent at a specific level has a specific Rank.
1121 private boolean validateAncestorOfSpecificRank(TaxonBase
<?
> taxonBase
, int level
, Rank ancestorRank
) {
1122 boolean result
= false;
1123 TaxonNode parentNode
= null;
1124 if (taxonBase
.isInstanceOf(Taxon
.class)){
1125 Taxon taxon
= CdmBase
.deproxy(taxonBase
, Taxon
.class);
1126 // Get ancestor Taxon via TaxonNode
1127 Set
<TaxonNode
> taxonNodes
= taxon
.getTaxonNodes();
1128 if (taxonNodes
.size() == 1) {
1129 TaxonNode taxonNode
= taxonNodes
.iterator().next();
1130 if (taxonNode
!= null) {
1131 for (int i
= 0; i
< level
; i
++) {
1132 if (taxonNode
!= null) {
1133 taxonNode
= taxonNode
.getParent();
1136 parentNode
= taxonNode
;
1138 } else if (taxonNodes
.size() > 1) {
1139 logger
.error("This taxon has " + taxonNodes
.size() + " taxonNodes: " + taxon
.getUuid() + " (" + taxon
.getTitleCache() + ")");
1143 if (parentNode
!= null) {
1144 TaxonNode node
= CdmBase
.deproxy(parentNode
, TaxonNode
.class);
1145 Taxon parentTaxon
= node
.getTaxon();
1146 if (parentTaxon
!= null) {
1147 TaxonName parentTaxonName
= parentTaxon
.getName();
1148 if (parentTaxonName
!= null && parentTaxonName
.getRank().equals(ancestorRank
)) {
1151 } else if (parentNode
.treeIndex().matches("#t\\d+#\\d+#")) {
1152 //do nothing (is root node)
1154 logger
.error("This TaxonNode has no Taxon: " + node
.getUuid());
1161 * Returns the AnnotationType for a given UUID.
1162 * @param uuid The Annotation UUID.
1163 * @param label The Annotation label.
1164 * @param text The Annotation text.
1165 * @param labelAbbrev The Annotation label abbreviation.
1166 * @return The AnnotationType.
1168 protected AnnotationType
getAnnotationType(UUID uuid
, String label
, String text
, String labelAbbrev
){
1169 AnnotationType annotationType
= (AnnotationType
)getTermService().find(uuid
);
1170 if (annotationType
== null) {
1171 annotationType
= AnnotationType
.NewInstance(label
, text
, labelAbbrev
);
1172 annotationType
.setUuid(uuid
);
1173 // annotationType.setVocabulary(AnnotationType.EDITORIAL().getVocabulary());
1174 getTermService().save(annotationType
);
1176 return annotationType
;
1180 * Traverses the classification recursively and stores determined values for every Taxon.
1181 * @param childNode The {@link TaxonNode TaxonNode} to process.
1182 * @param parentNode The parent {@link TaxonNode TaxonNode} of the childNode.
1183 * @param treeIndex The TreeIndex at the current level.
1184 * @param fetchLevel Rank to stop fetching at.
1185 * @param state The {@link PesiExportState PesiExportState}.
1187 private void traverseTree(TaxonNode childNode
, TaxonNode parentNode
, StringBuffer treeIndex
, Rank fetchLevel
, PesiExportState state
) {
1188 // Traverse all branches from this childNode until specified fetchLevel is reached.
1189 StringBuffer localTreeIndex
= new StringBuffer(treeIndex
);
1190 Taxon childTaxon
= childNode
.getTaxon();
1191 if (childTaxon
!= null) {
1192 if (isPesiTaxon(childTaxon
)){
1193 Integer taxonId
= state
.getDbId(childTaxon
);
1194 TaxonName childName
= childTaxon
.getName();
1195 if (taxonId
!= null) {
1196 Rank childRank
= childName
.getRank();
1197 if (childRank
!= null) {
1198 if (! childRank
.equals(fetchLevel
)) {
1200 localTreeIndex
.append(taxonId
+ "#");
1202 saveData(childNode
, parentNode
, localTreeIndex
, state
, taxonId
);
1204 // Store treeIndex as annotation for further use
1205 Annotation annotation
= Annotation
.NewInstance(localTreeIndex
.toString(), getTreeIndexAnnotationType(), Language
.DEFAULT());
1206 childNode
.addAnnotation(annotation
);
1208 for (TaxonNode newNode
: childNode
.getChildNodes()) {
1209 if (newNode
.getTaxon() != null && isPesiTaxon(newNode
.getTaxon())){
1210 traverseTree(newNode
, childNode
, localTreeIndex
, fetchLevel
, state
);
1215 // logger.debug("Target Rank " + fetchLevel.getLabel() + " reached");
1219 logger
.error("Rank is NULL. FetchLevel can not be checked: " + childName
.getUuid() + " (" + childName
.getTitleCache() + ")");
1222 logger
.error("Taxon can not be found in state: " + childTaxon
.getUuid() + " (" + childTaxon
.getTitleCache() + ")");
1225 if (logger
.isDebugEnabled()){
1226 logger
.debug("Taxon is not a PESI taxon: " + childTaxon
.getUuid());
1230 logger
.error("Taxon is NULL for TaxonNode: " + childNode
.getUuid());
1235 * Stores values in database for every recursive round.
1236 * @param childNode The {@link TaxonNode TaxonNode} to process.
1237 * @param parentNode The parent {@link TaxonNode TaxonNode} of the childNode.
1238 * @param treeIndex The TreeIndex at the current level.
1239 * @param state The {@link PesiExportState PesiExportState}.
1240 * @param currentTaxonFk The TaxonFk to store the values for.
1242 private void saveData(TaxonNode childNode
, TaxonNode parentNode
, StringBuffer treeIndex
, PesiExportState state
, Integer currentTaxonFk
) {
1243 // We are differentiating kingdoms by the nomenclatural code for now.
1244 // This needs to be handled in a better way as soon as we know how to differentiate between more kingdoms.
1245 Taxon childTaxon
= childNode
.getTaxon();
1246 if (isPesiTaxon(childTaxon
)) {
1247 TaxonBase
<?
> parentTaxon
= null;
1248 if (parentNode
!= null) {
1249 parentTaxon
= parentNode
.getTaxon();
1252 invokeParentTaxonFkAndTreeIndex(state
.getDbId(parentTaxon
), currentTaxonFk
, treeIndex
);
1257 * Inserts values into the Taxon database table.
1259 * @param taxonName The {@link TaxonNameBase TaxonName}.
1260 * @param state The {@link PesiExportState PesiExportState}.
1261 * @param stmt The prepared statement.
1262 * @return Whether save was successful or not.
1264 protected boolean invokeParentTaxonFkAndTreeIndex(Integer parentTaxonFk
, Integer currentTaxonFk
, StringBuffer treeIndex
) {
1266 if (parentTaxonFk
!= null) {
1267 parentTaxonFk_TreeIndex_KingdomFkStmt
.setInt(1, parentTaxonFk
);
1269 parentTaxonFk_TreeIndex_KingdomFkStmt
.setObject(1, null);
1272 if (treeIndex
!= null) {
1273 parentTaxonFk_TreeIndex_KingdomFkStmt
.setString(2, treeIndex
.toString());
1275 parentTaxonFk_TreeIndex_KingdomFkStmt
.setObject(2, null);
1278 if (currentTaxonFk
!= null) {
1279 parentTaxonFk_TreeIndex_KingdomFkStmt
.setInt(3, currentTaxonFk
);
1281 parentTaxonFk_TreeIndex_KingdomFkStmt
.setObject(3, null);
1284 parentTaxonFk_TreeIndex_KingdomFkStmt
.executeUpdate();
1286 } catch (SQLException e
) {
1287 logger
.error("ParentTaxonFk (" + (parentTaxonFk
==null?
"-":parentTaxonFk
) + ") and TreeIndex could not be inserted into database for taxon "+ (currentTaxonFk
== null?
"-" :currentTaxonFk
) + ": " + e
.getMessage());
1288 e
.printStackTrace();
1293 protected boolean invokeParentTaxonFk(Integer parentId
, Integer childId
) {
1295 parentTaxonFkStmt
.setInt(1, parentId
);
1296 parentTaxonFkStmt
.setInt(2, childId
);
1297 parentTaxonFkStmt
.executeUpdate();
1299 } catch (SQLException e
) {
1300 logger
.warn("ParentTaxonFk (" + (parentId
==null?
"-":parentId
) + ") could not be inserted into database "
1301 + "for taxon "+ (childId
== null?
"-" :childId
) + ": " + e
.getMessage());
1302 e
.printStackTrace();
1309 * Inserts Rank data and KingdomFk into the Taxon database table.
1310 * @param taxonName The {@link TaxonNameBase TaxonName}.
1311 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
1312 * @param taxonFk The TaxonFk to store the values for.
1314 * @param kindomFk The KingdomFk.
1315 * @return Whether save was successful or not.
1317 private boolean invokeRankDataAndKingdomFk(TaxonName taxonName
, NomenclaturalCode nomenclaturalCode
, Integer taxonFk
, Integer kingdomFk
, PesiExportState state
) {
1319 Integer rankFk
= getRankFk(taxonName
, nomenclaturalCode
);
1320 if (rankFk
!= null) {
1321 rankUpdateStmt
.setInt(1, rankFk
);
1323 rankUpdateStmt
.setObject(1, null);
1326 String rankCache
= getRankCache(taxonName
, nomenclaturalCode
, state
);
1327 if (rankCache
!= null) {
1328 rankUpdateStmt
.setString(2, rankCache
);
1330 rankUpdateStmt
.setObject(2, null);
1333 if (kingdomFk
!= null) {
1335 rankUpdateStmt
.setInt(3, kingdomFk
);
1337 rankUpdateStmt
.setObject(3, null);
1340 if (taxonFk
!= null) {
1341 rankUpdateStmt
.setInt(4, taxonFk
);
1343 rankUpdateStmt
.setObject(4, null);
1346 rankUpdateStmt
.executeUpdate();
1348 } catch (SQLException e
) {
1349 logger
.error("Data (RankFk, RankCache, KingdomFk) could not be inserted into database: " + e
.getMessage());
1350 e
.printStackTrace();
1356 * Inserts Rank data, TypeNameFk, KingdomFk, expertFk and speciesExpertFk into the Taxon database table.
1357 * @param taxonName The {@link TaxonNameBase TaxonName}.
1358 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
1359 * @param taxonFk The TaxonFk to store the values for.
1360 * @param typeNameFk The TypeNameFk.
1362 * @param kindomFk The KingdomFk.
1363 * @param expertFk The ExpertFk.
1364 * @param speciesExpertFk The SpeciesExpertFk.
1365 * @return Whether save was successful or not.
1367 private boolean invokeRankDataAndTypeNameFkAndKingdomFk(TaxonName taxonName
, NomenclaturalCode nomenclaturalCode
,
1368 Integer taxonFk
, Integer typeNameFk
, Integer kingdomFk
, PesiExportState state
) {
1370 Integer rankFk
= null;
1373 rankFk
= getRankFk(taxonName
, nomenclaturalCode
);
1374 if (rankFk
!= null) {
1375 rankTypeExpertsUpdateStmt
.setInt(index
++, rankFk
);
1377 rankTypeExpertsUpdateStmt
.setObject(index
++, null);
1380 String rankCache
= getRankCache(taxonName
, nomenclaturalCode
, state
);
1381 if (rankCache
!= null) {
1382 rankTypeExpertsUpdateStmt
.setString(index
++, rankCache
);
1384 rankTypeExpertsUpdateStmt
.setObject(index
++, null);
1387 if (typeNameFk
!= null) {
1388 rankTypeExpertsUpdateStmt
.setInt(index
++, typeNameFk
);
1390 rankTypeExpertsUpdateStmt
.setObject(index
++, null);
1393 if (kingdomFk
!= null) {
1394 rankTypeExpertsUpdateStmt
.setInt(index
++, kingdomFk
);
1396 rankTypeExpertsUpdateStmt
.setObject(index
++, null);
1399 // if (expertFk != null) {
1400 // rankTypeExpertsUpdateStmt.setInt(5, expertFk);
1402 // rankTypeExpertsUpdateStmt.setObject(5, null);
1405 // //TODO handle experts GUIDS
1406 // if (speciesExpertFk != null) {
1407 // rankTypeExpertsUpdateStmt.setInt(6, speciesExpertFk);
1409 // rankTypeExpertsUpdateStmt.setObject(6, null);
1412 if (taxonFk
!= null) {
1413 rankTypeExpertsUpdateStmt
.setInt(index
++, taxonFk
);
1415 rankTypeExpertsUpdateStmt
.setObject(index
++, null);
1418 rankTypeExpertsUpdateStmt
.executeUpdate();
1420 } catch (SQLException e
) {
1421 logger
.error("Data could not be inserted into database: " + e
.getMessage() + "; rankFk = " + rankFk
+ "; kingdomFk = " + kingdomFk
);
1422 e
.printStackTrace();
1424 } catch (Exception e
) {
1425 logger
.error("Some exception occurred: " + e
.getMessage() + "; rankFk = " + rankFk
+ "; kingdomFk = " + kingdomFk
);
1426 e
.printStackTrace();
1432 * Deletes all entries of database tables related to <code>Taxon</code>.
1433 * @param state The {@link PesiExportState PesiExportState}.
1434 * @return Whether the delete operation was successful or not.
1436 protected boolean doDelete(PesiExportState state
) {
1437 PesiExportConfigurator pesiConfig
= state
.getConfig();
1440 Source destination
= pesiConfig
.getDestination();
1443 sql
= "DELETE FROM " + dbTableName
;
1444 destination
.update(sql
);
1449 * Creates the kingdom fk.
1453 @SuppressWarnings("unused") //used by mapper
1454 private static Integer
getKingdomFk(TaxonName taxonName
){
1455 return PesiTransformer
.nomenclaturalCode2Kingdom(taxonName
.getNameType());
1459 * Creates the parent fk.
1463 @SuppressWarnings("unused") //used by mapper
1464 private static Integer
getParentTaxonFk(TaxonBase
<?
> taxonBase
, PesiExportState state
){
1465 if (taxonBase
.isInstanceOf(Taxon
.class)){
1466 Taxon taxon
= CdmBase
.deproxy(taxonBase
, Taxon
.class);
1467 if (! isMisappliedName(taxon
)){
1468 Set
<TaxonNode
> nodes
= taxon
.getTaxonNodes();
1469 if (nodes
.size() == 0){
1470 if (taxon
.getName().getRank().isLower(Rank
.KINGDOM())){
1471 logger
.warn("Accepted taxon has no parent. " + taxon
.getTitleCache() + ", " + taxon
.getUuid());
1473 }else if (nodes
.size() > 1){
1474 logger
.warn("Taxon has more than 1 node attached. This is not supported by PESI export." + taxon
.getTitleCache() + ", " + taxon
.getUuid());
1476 Taxon parent
=nodes
.iterator().next().getParent().getTaxon();
1477 return state
.getDbId(parent
);
1485 * Returns the rankFk for the taxon name based on the names nomenclatural code.
1486 * You may not use this method for kingdoms other then Animalia, Plantae and Bacteria.
1490 @SuppressWarnings("unused") //used by mapper
1491 private static Integer
getRankFk(TaxonName taxonName
) {
1492 return getRankFk(taxonName
, taxonName
.getNameType());
1497 * Returns the <code>RankFk</code> attribute.
1498 * @param taxonName The {@link TaxonNameBase TaxonName}.
1499 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
1500 * @return The <code>RankFk</code> attribute.
1503 private static Integer
getRankFk(TaxonName taxonName
, NomenclaturalCode nomenclaturalCode
) {
1504 Integer result
= null;
1506 if (nomenclaturalCode
!= null) {
1507 if (taxonName
!= null) {
1508 if (taxonName
.getRank() == null) {
1509 logger
.warn("Rank is null: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1511 result
= PesiTransformer
.rank2RankId(taxonName
.getRank(), PesiTransformer
.nomenclaturalCode2Kingdom(nomenclaturalCode
));
1513 if (result
== null) {
1514 logger
.warn("Rank could not be determined for PESI-Kingdom-Id " + PesiTransformer
.nomenclaturalCode2Kingdom(nomenclaturalCode
) + " and TaxonName " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1518 } catch (Exception e
) {
1519 e
.printStackTrace();
1525 * Returns the rank cache for the taxon name based on the names nomenclatural code.
1526 * You may not use this method for kingdoms other then Animalia, Plantae and Bacteria.
1528 @SuppressWarnings("unused") //used by mapper
1529 private static String
getRankCache(TaxonName taxonName
, PesiExportState state
) {
1530 return getRankCache(taxonName
, taxonName
.getNameType(), state
);
1534 * Returns the <code>RankCache</code> attribute.
1535 * @param taxonName The {@link TaxonNameBase TaxonName}.
1536 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
1538 * @return The <code>RankCache</code> attribute.
1541 private static String
getRankCache(TaxonName taxonName
, NomenclaturalCode nomenclaturalCode
, PesiExportState state
) {
1542 List
<TaxonNode
> nodes
= getTaxonNodes(taxonName
);
1543 if (Rank
.DOMAIN().equals(taxonName
.getRank())){
1544 return state
.getTransformer().getCacheByRankAndKingdom(Rank
.DOMAIN(), null);
1545 }else if (!nodes
.isEmpty()) {
1546 return state
.getTransformer().getCacheByRankAndKingdom(taxonName
.getRank(), findKingdomIdFromTreeIndex(nodes
.iterator().next().getTaxon(), state
)); //PesiTransformer.nomenclaturalCode2Kingdom(nomenclaturalCode));
1547 }else if (nomenclaturalCode
!= null){
1548 return state
.getTransformer().getCacheByRankAndKingdom(taxonName
.getRank(), PesiTransformer
.nomenclaturalCode2Kingdom(nomenclaturalCode
));
1550 logger
.warn("No nomenclatural code defined for name " + taxonName
.getUuid());
1559 private static List
<TaxonNode
> getTaxonNodes(TaxonName taxonName
) {
1560 List
<TaxonNode
> result
= new ArrayList
<>();
1561 for (TaxonBase
<?
> tb
:taxonName
.getTaxonBases()){
1563 //TODO handle ERMS taxon relationships
1564 if (tb
.isInstanceOf(Taxon
.class)){
1565 taxon
= CdmBase
.deproxy(tb
, Taxon
.class);
1567 taxon
= CdmBase
.deproxy(tb
, Synonym
.class).getAcceptedTaxon();
1570 for (TaxonNode node
: taxon
.getTaxonNodes()){
1579 * Returns the <code>DisplayName</code> attribute.
1580 * @param taxon The {@link TaxonBase Taxon}.
1581 * @return The <code>DisplayName</code> attribute.
1584 @SuppressWarnings("unused") //used by Mapper
1585 private static String
getDisplayName(TaxonBase
<?
> taxon
) {
1586 TaxonName taxonName
= taxon
.getName();
1587 String result
= getDisplayName(taxonName
);
1588 if (isMisappliedName(taxon
)){
1589 result
= result
+ " " + getAuthorString(taxon
);
1595 * Returns the <code>AuthorString</code> attribute.
1596 * @param taxonName The {@link TaxonNameBase TaxonName}.
1597 * @return The <code>AuthorString</code> attribute.
1601 protected static String
getAuthorString(TaxonBase
<?
> taxon
) {
1603 String result
= null;
1604 boolean isNonViralName
= false;
1605 String authorshipCache
= null;
1606 TaxonName taxonName
= taxon
.getName();
1607 if (taxonName
!= null && taxonName
.isNonViral()){
1608 authorshipCache
= taxonName
.getAuthorshipCache();
1609 isNonViralName
= true;
1611 result
= authorshipCache
;
1613 // For a misapplied names there are special rules
1614 if (isMisappliedName(taxon
)){
1615 if (taxon
.getSec() != null){
1616 String secTitle
= taxon
.getSec().getTitleCache();
1617 if (! secTitle
.startsWith("auct")){
1618 secTitle
= "sensu " + secTitle
;
1619 }else if (secTitle
.equals("auct")){ //may be removed once the title cache is generated correctly for references with title auct. #
1623 }else if (StringUtils
.isBlank(authorshipCache
)) {
1624 // Set authorshipCache to "auct."
1625 result
= PesiTransformer
.AUCT_STRING
;
1627 result
= PesiTransformer
.AUCT_STRING
;
1628 // result = authorshipCache;
1632 if (taxonName
== null){
1633 logger
.warn("TaxonName does not exist for taxon: " + taxon
.getUuid() + " (" + taxon
.getTitleCache() + ")");
1634 }else if (! isNonViralName
){
1635 logger
.warn("TaxonName is not of instance NonViralName: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1638 if (StringUtils
.isBlank(result
)) {
1643 } catch (Exception e
) {
1644 e
.printStackTrace();
1650 * Returns the <code>DisplayName</code> attribute.
1651 * @param taxonName The {@link TaxonNameBase TaxonName}.
1652 * @return The <code>DisplayName</code> attribute.
1656 private static String
getDisplayName(TaxonName taxonName
) {
1658 if (taxonName
== null) {
1661 taxonName
= CdmBase
.deproxy(taxonName
);
1662 INonViralNameCacheStrategy cacheStrategy
= getCacheStrategy(taxonName
);
1663 HTMLTagRules tagRules
= new HTMLTagRules().
1664 addRule(TagEnum
.name
, "i").
1665 addRule(TagEnum
.nomStatus
, "@status@");
1668 if (getSources(taxonName
).get(PesiTransformer
.SOURCE_ERMS
)){
1669 result
= cacheStrategy
.getTitleCache(taxonName
, tagRules
); //according to SQL script (also in ERMS sources are not abbreviated)
1670 }else if (getSources(taxonName
).get(PesiTransformer
.SOURCE_EM
)){
1671 result
= cacheStrategy
.getFullTitleCache(taxonName
, tagRules
);
1673 //TODO define for FE + IF and for multiple sources
1674 result
= cacheStrategy
.getFullTitleCache(taxonName
, tagRules
);
1676 return result
.replaceAll(",?\\<@status@\\>.*\\</@status@\\>", "");
1680 @SuppressWarnings("unused")
1681 private static String
getGUID(TaxonName taxonName
) {
1682 UUID uuid
= taxonName
.getUuid();
1683 String result
= "NameUUID:" + uuid
.toString();
1689 * Returns the <code>WebShowName</code> attribute for a taxon.
1690 * @param taxonName The {@link TaxonNameBase TaxonName}.
1691 * @return The <code>WebShowName</code> attribute.
1694 @SuppressWarnings("unused")
1695 private static String
getWebShowName(TaxonBase
<?
> taxon
) {
1696 TaxonName taxonName
= taxon
.getName();
1697 String result
= getWebShowName(taxonName
);
1698 if (isMisappliedName(taxon
)){
1699 result
= result
+ " " + getAuthorString(taxon
);
1705 * Returns the <code>WebShowName</code> attribute.
1706 * @param taxonName The {@link TaxonNameBase TaxonName}.
1707 * @return The <code>WebShowName</code> attribute.
1710 private static String
getWebShowName(TaxonName taxonName
) {
1712 if (taxonName
== null) {
1715 INonViralNameCacheStrategy cacheStrategy
= getCacheStrategy(taxonName
);
1717 HTMLTagRules tagRules
= new HTMLTagRules().addRule(TagEnum
.name
, "i");
1718 String result
= cacheStrategy
.getTitleCache(taxonName
, tagRules
);
1725 * Returns the <code>WebSearchName</code> attribute.
1726 * @param taxonName The {@link NonViralName NonViralName}.
1727 * @return The <code>WebSearchName</code> attribute.
1730 @SuppressWarnings("unused")
1731 private static String
getWebSearchName(TaxonName taxonName
) {
1733 TaxonNameDefaultCacheStrategy strategy
= getCacheStrategy(taxonName
);
1734 String result
= strategy
.getNameCache(taxonName
);
1740 * Returns the <code>FullName</code> attribute.
1741 * @param taxonName The {@link NonViralName NonViralName}.
1742 * @return The <code>FullName</code> attribute.
1745 @SuppressWarnings("unused")
1746 private static String
getFullName(TaxonName taxonName
) {
1748 String result
= getCacheStrategy(taxonName
).getTitleCache(taxonName
);
1749 Iterator
<Taxon
> taxa
= taxonName
.getTaxa().iterator();
1750 if (taxonName
.getTaxa().size() >0){
1751 if (taxonName
.getTaxa().size() == 1){
1752 Taxon taxon
= taxa
.next();
1753 if (isMisappliedName(taxon
)){
1754 result
= result
+ " " + getAuthorString(taxon
);
1763 * Returns the SourceNameCache for the AdditionalSource table
1767 static boolean isFirstAbbrevTitle
= true;
1768 @SuppressWarnings("unused")
1769 private static String
getSourceNameCache(TaxonName taxonName
) {
1770 if (taxonName
!= null){
1771 Reference nomRef
= taxonName
.getNomenclaturalReference();
1772 if (nomRef
!= null ){
1773 if (isFirstAbbrevTitle
){
1774 //#5388 is definetely not the correct ticket number
1775 logger
.warn("Semantics of getAbbrevTitleCache has changed. Please check if output is still correct. See #5388");
1776 isFirstAbbrevTitle
= false;
1778 return nomRef
.getAbbrevTitleCache();
1787 * Returns the <code>FullName</code> attribute.
1788 * @param taxon The {@link TaxonBase taxon}.
1789 * @return The <code>FullName</code> attribute.
1792 /*@SuppressWarnings("unused")
1793 private static String getFullName(TaxonBase taxon) {
1795 TaxonNameBase name = taxon.getName();
1796 String result = getFullName(name);
1797 if (isMisappliedName(taxon)){
1798 result = result + " " + getAuthorString(taxon);
1806 * Returns the nomenclatural reference which is the reference
1807 * including the detail (microreference).
1808 * @param taxonName The {@link TaxonNameBase TaxonName}.
1809 * @return The <code>AuthorString</code> attribute.
1812 @SuppressWarnings("unused")
1813 private static String
getNomRefString(TaxonName taxonName
) {
1814 INomenclaturalReference ref
= taxonName
.getNomenclaturalReference();
1818 String result
= null;
1819 BitSet sources
= getSources(taxonName
);
1820 int len
= sources
.length();
1821 if(sources
.get(PesiTransformer
.SOURCE_EM
)){
1822 if (! ref
.isProtectedAbbrevTitleCache()){
1823 ref
.setAbbrevTitleCache(null, false); //to remove a false cache
1825 result
= ref
.getNomenclaturalCitation(taxonName
.getNomenclaturalMicroReference());
1826 }else if(sources
.get(PesiTransformer
.SOURCE_FE
)||sources
.get(PesiTransformer
.SOURCE_IF
) ){
1827 //TODO still need to check if correct for FE + IF
1828 if (! ref
.isProtectedAbbrevTitleCache()){
1829 ref
.setAbbrevTitleCache(null, false); //to remove a false cache
1831 result
= ref
.getNomenclaturalCitation(taxonName
.getNomenclaturalMicroReference());
1832 return result
; // according to SQL script
1833 }else if(sources
.get(PesiTransformer
.SOURCE_ERMS
)) {
1834 //result = null; //according to SQL script
1836 logger
.warn("Source not yet supported");
1843 * Returns the <code>NameStatusFk</code> attribute.
1844 * @param taxonName The {@link TaxonNameBase TaxonName}.
1845 * @return The <code>NameStatusFk</code> attribute.
1848 @SuppressWarnings("unused")
1849 private static Integer
getNameStatusFk(TaxonName taxonName
) {
1850 Integer result
= null;
1852 NomenclaturalStatus status
= getNameStatus(taxonName
);
1853 if (status
!= null) {
1854 result
= PesiTransformer
.nomStatus2nomStatusFk(status
.getType());
1860 * Returns the <code>NameStatusCache</code> attribute.
1861 * @param taxonName The {@link TaxonNameBase TaxonName}.
1862 * @return The <code>NameStatusCache</code> attribute.
1863 * @throws UndefinedTransformerMethodException
1866 @SuppressWarnings("unused")
1867 private static String
getNameStatusCache(TaxonName taxonName
, PesiExportState state
) throws UndefinedTransformerMethodException
{
1868 String result
= null;
1869 NomenclaturalStatus status
= getNameStatus(taxonName
);
1870 if (status
!= null) {
1871 result
= state
.getTransformer().getCacheByNomStatus(status
.getType());
1877 private static NomenclaturalStatus
getNameStatus(TaxonName taxonName
) {
1879 if (taxonName
!= null) {
1880 Set
<NomenclaturalStatus
> states
= taxonName
.getStatus();
1881 if (states
.size() == 1) {
1882 NomenclaturalStatus status
= states
.iterator().next();
1884 } else if (states
.size() > 1) {
1885 logger
.error("This TaxonName has more than one Nomenclatural Status: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1888 } catch (Exception e
) {
1889 e
.printStackTrace();
1894 * Returns the <code>TaxonStatusFk</code> attribute.
1895 * @param taxonName The {@link TaxonNameBase TaxonName}.
1896 * @param state The {@link PesiExportState PesiExportState}.
1897 * @return The <code>TaxonStatusFk</code> attribute.
1900 private static Integer
getTaxonStatusFk(TaxonBase
<?
> taxon
, PesiExportState state
) {
1901 Integer result
= null;
1904 if (isMisappliedName(taxon
)) {
1905 Synonym synonym
= Synonym
.NewInstance(null, null);
1907 // This works as long as only the instance is important to differentiate between TaxonStatus.
1908 result
= PesiTransformer
.taxonBase2statusFk(synonym
); // Auct References are treated as Synonyms in Datawarehouse now.
1910 result
= PesiTransformer
.taxonBase2statusFk(taxon
);
1912 } catch (Exception e
) {
1913 e
.printStackTrace();
1919 * Returns the <code>TaxonStatusCache</code> attribute.
1920 * @param taxonName The {@link TaxonNameBase TaxonName}.
1921 * @param state The {@link PesiExportState PesiExportState}.
1922 * @return The <code>TaxonStatusCache</code> attribute.
1923 * @throws UndefinedTransformerMethodException
1926 @SuppressWarnings("unused")
1927 private static String
getTaxonStatusCache(TaxonBase
<?
> taxon
, PesiExportState state
) throws UndefinedTransformerMethodException
{
1928 return state
.getTransformer().getTaxonStatusCacheByKey(getTaxonStatusFk(taxon
, state
));
1932 * Returns the <code>TypeNameFk</code> attribute.
1933 * @param taxonName The {@link TaxonNameBase TaxonName}.
1934 * @param state The {@link PesiExportState PesiExportState}.
1935 * @return The <code>TypeNameFk</code> attribute.
1938 private static Integer
getTypeNameFk(TaxonName taxonName
, PesiExportState state
) {
1939 Integer result
= null;
1940 if (taxonName
!= null) {
1941 Set
<NameTypeDesignation
> nameTypeDesignations
= taxonName
.getNameTypeDesignations();
1942 if (nameTypeDesignations
.size() == 1) {
1943 NameTypeDesignation nameTypeDesignation
= nameTypeDesignations
.iterator().next();
1944 if (nameTypeDesignation
!= null) {
1945 TaxonName typeName
= nameTypeDesignation
.getTypeName();
1946 if (typeName
!= null) {
1947 result
= state
.getDbId(typeName
);
1950 } else if (nameTypeDesignations
.size() > 1) {
1951 logger
.warn("This TaxonName has " + nameTypeDesignations
.size() + " NameTypeDesignations: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1958 * Returns the <code>TypeFullnameCache</code> attribute.
1959 * @param taxonName The {@link TaxonNameBase TaxonName}.
1960 * @return The <code>TypeFullnameCache</code> attribute.
1963 @SuppressWarnings("unused")
1964 private static String
getTypeFullnameCache(TaxonName taxonName
) {
1965 String result
= null;
1968 if (taxonName
!= null) {
1969 Set
<NameTypeDesignation
> nameTypeDesignations
= taxonName
.getNameTypeDesignations();
1970 if (nameTypeDesignations
.size() == 1) {
1971 NameTypeDesignation nameTypeDesignation
= nameTypeDesignations
.iterator().next();
1972 if (nameTypeDesignation
!= null) {
1973 TaxonName typeName
= nameTypeDesignation
.getTypeName();
1974 if (typeName
!= null) {
1975 result
= typeName
.getTitleCache();
1978 } else if (nameTypeDesignations
.size() > 1) {
1979 logger
.warn("This TaxonName has " + nameTypeDesignations
.size() + " NameTypeDesignations: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1982 } catch (Exception e
) {
1983 e
.printStackTrace();
1990 * Returns the <code>QualityStatusFk</code> attribute.
1991 * @param taxonName The {@link TaxonNameBase TaxonName}.
1992 * @return The <code>QualityStatusFk</code> attribute.
1995 private static Integer
getQualityStatusFk(TaxonName taxonName
) {
1996 BitSet sources
= getSources(taxonName
);
1997 return PesiTransformer
.getQualityStatusKeyBySource(sources
, taxonName
);
2002 * Returns the <code>QualityStatusCache</code> attribute.
2003 * @param taxonName The {@link TaxonNameBase TaxonName}.
2004 * @return The <code>QualityStatusCache</code> attribute.
2005 * @throws UndefinedTransformerMethodException
2008 @SuppressWarnings("unused")
2009 private static String
getQualityStatusCache(TaxonName taxonName
, PesiExportState state
) throws UndefinedTransformerMethodException
{
2010 return state
.getTransformer().getQualityStatusCacheByKey(getQualityStatusFk(taxonName
));
2015 * Returns the <code>TypeDesignationStatusFk</code> attribute.
2016 * @param taxonName The {@link TaxonNameBase TaxonName}.
2017 * @return The <code>TypeDesignationStatusFk</code> attribute.
2020 @SuppressWarnings("unused")
2021 private static Integer
getTypeDesignationStatusFk(TaxonName taxonName
) {
2022 Integer result
= null;
2025 if (taxonName
!= null) {
2026 Set
<NameTypeDesignation
> typeDesignations
= taxonName
.getNameTypeDesignations();
2027 if (typeDesignations
.size() == 1) {
2028 Object obj
= typeDesignations
.iterator().next().getTypeStatus();
2029 NameTypeDesignationStatus designationStatus
= CdmBase
.deproxy(obj
, NameTypeDesignationStatus
.class);
2030 result
= PesiTransformer
.nameTypeDesignationStatus2TypeDesignationStatusId(designationStatus
);
2031 } else if (typeDesignations
.size() > 1) {
2032 logger
.error("Found a TaxonName with more than one NameTypeDesignation: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
2036 } catch (Exception e
) {
2037 e
.printStackTrace();
2043 * Returns the <code>TypeDesignationStatusCache</code> attribute.
2044 * @param taxonName The {@link TaxonNameBase TaxonName}.
2045 * @return The <code>TypeDesignationStatusCache</code> attribute.
2048 @SuppressWarnings("unused")
2049 private static String
getTypeDesignationStatusCache(TaxonName taxonName
) {
2050 String result
= null;
2053 if (taxonName
!= null) {
2054 Set
<NameTypeDesignation
> typeDesignations
= taxonName
.getNameTypeDesignations();
2055 if (typeDesignations
.size() == 1) {
2056 Object obj
= typeDesignations
.iterator().next().getTypeStatus();
2057 NameTypeDesignationStatus designationStatus
= CdmBase
.deproxy(obj
, NameTypeDesignationStatus
.class);
2058 result
= PesiTransformer
.nameTypeDesignationStatus2TypeDesignationStatusCache(designationStatus
);
2059 } else if (typeDesignations
.size() > 1) {
2060 logger
.error("Found a TaxonName with more than one NameTypeDesignation: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
2064 } catch (Exception e
) {
2065 e
.printStackTrace();
2071 * Returns the <code>FossilStatusFk</code> attribute.
2072 * @param taxonName The {@link TaxonNameBase TaxonName}.
2073 * @return The <code>FossilStatusFk</code> attribute.
2076 @SuppressWarnings("unused")
2077 private static Integer
getFossilStatusFk(IdentifiableEntity
<?
> identEntity
, PesiExportState state
) {
2078 Integer result
= null;
2080 Set
<String
> fossilStatuus
= identEntity
.getExtensions(ErmsTransformer
.uuidExtFossilStatus
);
2081 if (fossilStatuus
.size() == 0){
2083 }else if (fossilStatuus
.size() > 1){
2084 logger
.warn("More than 1 fossil status given for " + identEntity
.getTitleCache() + " " + identEntity
.getUuid());
2086 String fossilStatus
= fossilStatuus
.iterator().next();
2088 int statusFk
= state
.getTransformer().fossilStatusCache2FossilStatusFk(fossilStatus
);
2093 * Returns the <code>FossilStatusCache</code> attribute.
2094 * @param taxonName The {@link TaxonNameBase TaxonName}.
2095 * @return The <code>FossilStatusCache</code> attribute.
2098 @SuppressWarnings("unused")
2099 private static String
getFossilStatusCache(IdentifiableEntity
<?
> identEntity
, PesiExportState state
) {
2100 String result
= null;
2101 Set
<String
> fossilStatuus
= identEntity
.getExtensions(ErmsTransformer
.uuidExtFossilStatus
);
2102 if (fossilStatuus
.size() == 0){
2105 for (String strFossilStatus
: fossilStatuus
){
2106 result
= CdmUtils
.concat(";", result
, strFossilStatus
);
2112 * Returns the <code>IdInSource</code> attribute.
2113 * @param taxonName The {@link TaxonNameBase TaxonName}.
2114 * @return The <code>IdInSource</code> attribute.
2117 @SuppressWarnings("unused")
2118 private static String
getIdInSource(IdentifiableEntity taxonName
) {
2119 String result
= null;
2122 Set
<IdentifiableSource
> sources
= getPesiSources(taxonName
);
2123 if (sources
.size() > 1){
2124 logger
.warn("There is > 1 Pesi source. This is not yet handled.");
2126 if (sources
.size() == 0){
2127 logger
.warn("There is no Pesi source!" +taxonName
.getUuid() + " (" + taxonName
.getTitleCache() +")");
2129 for (IdentifiableSource source
: sources
) {
2130 Reference ref
= source
.getCitation();
2131 UUID refUuid
= ref
.getUuid();
2132 String idInSource
= source
.getIdInSource();
2133 if (refUuid
.equals(BerlinModelTransformer
.uuidSourceRefEuroMed
)){
2134 result
= idInSource
!= null ?
("NameId: " + source
.getIdInSource()) : null;
2135 }else if (refUuid
.equals(PesiTransformer
.uuidSourceRefFaunaEuropaea
)){
2136 result
= idInSource
!= null ?
("TAX_ID: " + source
.getIdInSource()) : null;
2137 }else if (refUuid
.equals(PesiTransformer
.uuidSourceRefErms
)){
2138 result
= idInSource
!= null ?
("tu_id: " + source
.getIdInSource()) : null;
2139 }else if (refUuid
.equals(PesiTransformer
.uuidSourceRefIndexFungorum
)){ //Index Fungorum
2140 result
= idInSource
!= null ?
("if_id: " + source
.getIdInSource()) : null;
2142 if (logger
.isDebugEnabled()){logger
.debug("Not a PESI source");};
2145 String sourceIdNameSpace
= source
.getIdNamespace();
2146 if (sourceIdNameSpace
!= null) {
2147 if (sourceIdNameSpace
.equals(PesiTransformer
.STR_NAMESPACE_NOMINAL_TAXON
)) {
2148 result
= idInSource
!= null ?
("Nominal Taxon from TAX_ID: " + source
.getIdInSource()):null;
2149 } else if (sourceIdNameSpace
.equals(TaxonServiceImpl
.INFERRED_EPITHET_NAMESPACE
)) {
2150 result
= idInSource
!= null ?
("Inferred epithet from TAX_ID: " + source
.getIdInSource()) : null;
2151 } else if (sourceIdNameSpace
.equals(TaxonServiceImpl
.INFERRED_GENUS_NAMESPACE
)) {
2152 result
= idInSource
!= null ?
("Inferred genus from TAX_ID: " + source
.getIdInSource()):null;
2153 } else if (sourceIdNameSpace
.equals(TaxonServiceImpl
.POTENTIAL_COMBINATION_NAMESPACE
)) {
2154 result
= idInSource
!= null ?
("Potential combination from TAX_ID: " + source
.getIdInSource()):null;
2157 if (result
== null) {
2158 logger
.warn("IdInSource is NULL for this taxonName: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() +", sourceIdNameSpace: " + source
.getIdNamespace()+")");
2161 } catch (Exception e
) {
2162 e
.printStackTrace();
2163 logger
.error("An error occurs while creating idInSource..." + taxonName
.getUuid() + " (" + taxonName
.getTitleCache()+ e
.getMessage());
2166 if (result
== null) {
2167 logger
.warn("IdInSource is NULL for this taxonName: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() +")");
2173 * Returns the idInSource for a given TaxonName only.
2174 * @param taxonName The {@link TaxonNameBase TaxonName}.
2175 * @return The idInSource.
2177 private static String
getIdInSourceOnly(IdentifiableEntity identEntity
) {
2178 String result
= null;
2180 // Get the sources first
2181 Set
<IdentifiableSource
> sources
= getPesiSources(identEntity
);
2183 // Determine the idInSource
2184 if (sources
.size() == 1) {
2185 IdentifiableSource source
= sources
.iterator().next();
2186 if (source
!= null) {
2187 result
= source
.getIdInSource();
2189 } else if (sources
.size() > 1) {
2192 for (IdentifiableSource source
: sources
) {
2193 result
+= source
.getIdInSource();
2194 if (count
< sources
.size()) {
2206 * Returns the <code>GUID</code> attribute.
2207 * @param taxonName The {@link TaxonNameBase TaxonName}.
2208 * @return The <code>GUID</code> attribute.
2211 private static String
getGUID(TaxonBase
<?
> taxon
) {
2212 if (taxon
.getLsid() != null ){
2213 return taxon
.getLsid().getLsid();
2214 }else if (taxon
.hasMarker(PesiTransformer
.uuidMarkerGuidIsMissing
, true)){
2217 return taxon
.getUuid().toString();
2222 * Returns the <code>DerivedFromGuid</code> attribute.
2223 * @param taxonName The {@link TaxonNameBase TaxonName}.
2224 * @return The <code>DerivedFromGuid</code> attribute.
2227 @SuppressWarnings("unused")
2228 private static String
getDerivedFromGuid(TaxonBase
<?
> taxon
) {
2229 String result
= null;
2231 // The same as GUID for now
2232 result
= getGUID(taxon
);
2233 } catch (Exception e
) {
2234 e
.printStackTrace();
2240 * Returns the <code>CacheCitation</code> attribute.
2241 * @param taxonName The {@link TaxonNameBase TaxonName}.
2242 * @return The CacheCitation.
2245 @SuppressWarnings("unused")
2246 private static String
getCacheCitation(TaxonBase
<?
> taxon
) {
2247 // !!! See also doPhaseUpdates
2249 TaxonName taxonName
= taxon
.getName();
2251 //TODO implement anew for taxa
2253 BitSet sources
= getSources(taxon
);
2254 if (sources
.isEmpty()) {
2255 // logger.error("OriginalDB is NULL for this TaxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
2256 } else if (sources
.get(PesiTransformer
.SOURCE_ERMS
)) {
2257 Set
<Extension
> extensions
= taxon
.getExtensions();
2258 for (Extension extension
: extensions
) {
2259 if (extension
.getType().equals(cacheCitationExtensionType
)) {
2260 result
= extension
.getValue();
2264 String expertName
= getExpertName(taxon
);
2265 String webShowName
= getWebShowName(taxonName
);
2268 String idInSource
= getIdInSourceOnly(taxonName
);
2270 // build the cacheCitation
2271 if (expertName
!= null) {
2272 result
+= expertName
+ ". ";
2274 if (logger
.isDebugEnabled()){logger
.debug("ExpertName could not be determined for this TaxonName: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");}
2276 if (webShowName
!= null) {
2277 result
+= webShowName
+ ". ";
2279 logger
.warn("WebShowName could not be determined for this TaxonName: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
2282 if (getOriginalDB(taxonName
).equals("FaEu")) {
2283 result
+= "Accessed through: Fauna Europaea at http://faunaeur.org/full_results.php?id=";
2284 } else if (getOriginalDB(taxonName
).equals("EM")) {
2285 result
+= "Accessed through: Euro+Med PlantBase at http://ww2.bgbm.org/euroPlusMed/PTaxonDetail.asp?UUID=";
2288 if (idInSource
!= null) {
2289 result
+= idInSource
;
2291 logger
.warn("IdInSource could not be determined for this TaxonName: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
2294 } catch (Exception e
) {
2295 e
.printStackTrace();
2298 if (StringUtils
.isBlank(result
)) {
2306 * Returns the <code>OriginalDB</code> attribute.
2307 * @param identifiableEntity
2308 * @return The <code>OriginalDB</code> attribute.
2311 @SuppressWarnings("unused")
2312 private static String
getOriginalDB(IdentifiableEntity identifiableEntity
) {
2313 BitSet sources
= getSources(identifiableEntity
);
2314 return PesiTransformer
.getOriginalDbBySources(sources
);
2318 * Returns the <code>LastAction</code> attribute.
2319 * @param taxonName The {@link TaxonNameBase TaxonName}.
2320 * @return The <code>LastAction</code> attribute.
2323 @SuppressWarnings("unused")
2324 private static String
getLastAction(IdentifiableEntity
<?
> identEntity
) {
2325 String result
= null;
2327 Set
<Extension
> extensions
= identEntity
.getExtensions();
2328 for (Extension extension
: extensions
) {
2329 if (extension
.getType().equals(lastActionExtensionType
)) {
2330 result
= extension
.getValue();
2333 } catch (Exception e
) {
2334 e
.printStackTrace();
2340 * Returns the <code>LastActionDate</code> attribute.
2341 * @param taxonName The {@link TaxonNameBase TaxonName}.
2342 * @return The <code>LastActionDate</code> attribute.
2345 @SuppressWarnings({ "unused" })
2346 private static DateTime
getLastActionDate(IdentifiableEntity identEntity
) {
2347 DateTime result
= null;
2349 Set
<Extension
> extensions
= identEntity
.getExtensions();
2350 for (Extension extension
: extensions
) {
2351 if (extension
.getType().equals(lastActionDateExtensionType
)) {
2352 String dateTime
= extension
.getValue();
2353 if (dateTime
!= null) {
2354 DateTimeFormatter formatter
= DateTimeFormat
.forPattern("yyyy-MM-dd HH:mm:ss.S");
2355 result
= formatter
.parseDateTime(dateTime
);
2359 } catch (Exception e
) {
2360 e
.printStackTrace();
2366 * Returns the <code>ExpertName</code> attribute.
2367 * @param taxonName The {@link TaxonNameBase TaxonName}.
2368 * @return The <code>ExpertName</code> attribute.
2371 @SuppressWarnings("unused")
2372 private static String
getExpertName(TaxonBase
<?
> taxonName
) {
2373 String result
= null;
2375 Set
<Extension
> extensions
= taxonName
.getExtensions();
2376 for (Extension extension
: extensions
) {
2377 if (extension
.getType().equals(expertNameExtensionType
)) {
2378 result
= extension
.getValue();
2381 } catch (Exception e
) {
2382 e
.printStackTrace();
2388 * Returns the <code>ExpertFk</code> attribute.
2389 * @param taxonName The {@link TaxonNameBase TaxonName}.
2390 * @param state The {@link PesiExportState PesiExportState}.
2391 * @return The <code>ExpertFk</code> attribute.
2394 private static Integer
getExpertFk(Reference reference
, PesiExportState state
) {
2395 Integer result
= state
.getDbId(reference
);
2400 * Returns the <code>SpeciesExpertName</code> attribute.
2401 * @param taxonName The {@link TaxonNameBase TaxonName}.
2402 * @return The <code>SpeciesExpertName</code> attribute.
2405 @SuppressWarnings("unused")
2406 private static String
getSpeciesExpertName(TaxonBase
<?
> taxonName
) {
2407 String result
= null;
2409 Set
<Extension
> extensions
= taxonName
.getExtensions();
2410 for (Extension extension
: extensions
) {
2411 if (extension
.getType().equals(speciesExpertNameExtensionType
)) {
2412 result
= extension
.getValue();
2415 } catch (Exception e
) {
2416 e
.printStackTrace();
2422 * Returns the <code>SpeciesExpertFk</code> attribute.
2423 * @param reference The {@link Reference Reference}.
2424 * @param state The {@link PesiExportState PesiExportState}.
2425 * @return The <code>SpeciesExpertFk</code> attribute.
2428 private static Integer
getSpeciesExpertFk(Reference reference
, PesiExportState state
) {
2429 Integer result
= state
.getDbId(reference
);
2433 protected static TaxonNameDefaultCacheStrategy
getCacheStrategy(TaxonName taxonName
) {
2434 taxonName
= CdmBase
.deproxy(taxonName
);
2435 TaxonNameDefaultCacheStrategy cacheStrategy
;
2436 if (taxonName
.isZoological()){
2437 cacheStrategy
= zooNameStrategy
;
2438 }else if (taxonName
.isBotanical()) {
2439 cacheStrategy
= nonViralNameStrategy
;
2440 }else if (taxonName
.isNonViral()) {
2441 cacheStrategy
= nonViralNameStrategy
;
2442 }else if (taxonName
.isBacterial()) {
2443 cacheStrategy
= nonViralNameStrategy
;
2445 logger
.error("Unhandled taxon name type. Can't define strategy class");
2446 cacheStrategy
= nonViralNameStrategy
;
2448 return cacheStrategy
;
2452 * Returns the <code>RelTaxonQualifierFk</code> attribute.
2453 * @param relationship The {@link RelationshipBase Relationship}.
2454 * @return The <code>RelTaxonQualifierFk</code> attribute.
2457 @SuppressWarnings("unused")
2458 private static Integer
getRelTaxonQualifierFk(RelationshipBase
<?
, ?
, ?
> relationship
) {
2459 return PesiTransformer
.taxonRelation2RelTaxonQualifierFk(relationship
);
2461 @SuppressWarnings("unused")
2462 private static String
getSynonymTypeCache(Synonym synonym
, PesiExportState state
) {
2463 String result
= null;
2464 NomenclaturalCode code
= null;
2465 code
= CdmBase
.deproxy(synonym
, Synonym
.class).getAcceptedTaxon().getName().getNameType();
2468 result
= state
.getConfig().getTransformer().getCacheBySynonymType(synonym
, code
);
2470 logger
.error("NomenclaturalCode is NULL while creating the following synonym: " + synonym
.getUuid());
2477 * Returns the CDM to PESI specific export mappings.
2478 * @return The {@link PesiExportMapping PesiExportMapping}.
2480 private PesiExportMapping
getMapping() {
2481 PesiExportMapping mapping
= new PesiExportMapping(dbTableName
);
2483 mapping
.addMapper(IdMapper
.NewInstance("TaxonId"));
2484 mapping
.addMapper(DbObjectMapper
.NewInstance("sec", "sourceFk")); //OLD:mapping.addMapper(MethodMapper.NewInstance("SourceFK", this.getClass(), "getSourceFk", standardMethodParameter, PesiExportState.class));
2485 mapping
.addMapper(MethodMapper
.NewInstance("TaxonStatusFk", this.getClass(), "getTaxonStatusFk", standardMethodParameter
, PesiExportState
.class));
2486 mapping
.addMapper(MethodMapper
.NewInstance("TaxonStatusCache", this.getClass(), "getTaxonStatusCache", standardMethodParameter
, PesiExportState
.class));
2488 mapping
.addMapper(MethodMapper
.NewInstance("GUID", this));
2490 mapping
.addMapper(MethodMapper
.NewInstance("DerivedFromGuid", this));
2491 mapping
.addMapper(MethodMapper
.NewInstance("CacheCitation", this));
2492 mapping
.addMapper(MethodMapper
.NewInstance("AuthorString", this)); //For Taxon because Misapllied Names are handled differently
2493 mapping
.addMapper(MethodMapper
.NewInstance("WebShowName", this));
2496 mapping
.addMapper(MethodMapper
.NewInstance("DisplayName", this));
2498 // FossilStatus (Fk, Cache)
2499 mapping
.addMapper(MethodMapper
.NewInstance("FossilStatusCache", this, IdentifiableEntity
.class, PesiExportState
.class));
2500 mapping
.addMapper(MethodMapper
.NewInstance("FossilStatusFk", this, IdentifiableEntity
.class, PesiExportState
.class)); // PesiTransformer.FossilStatusCache2FossilStatusFk?
2502 //handled by name mapping
2503 mapping
.addMapper(DbLastActionMapper
.NewInstance("LastActionDate", false));
2504 mapping
.addMapper(DbLastActionMapper
.NewInstance("LastAction", true));
2507 ExtensionType extensionTypeSpeciesExpertName
= (ExtensionType
)getTermService().find(PesiTransformer
.uuidExtSpeciesExpertName
);
2508 mapping
.addMapper(DbExtensionMapper
.NewInstance(extensionTypeSpeciesExpertName
, "SpeciesExpertName"));
2510 ExtensionType extensionTypeExpertName
= (ExtensionType
)getTermService().find(PesiTransformer
.uuidExtExpertName
);
2511 mapping
.addMapper(DbExtensionMapper
.NewInstance(extensionTypeExpertName
, "ExpertName"));
2513 // mapping.addMapper(MethodMapper.NewInstance("ParentTaxonFk", this, TaxonBase.class, PesiExportState.class)); //by AM, doesn't work, FK exception
2514 mapping
.addMapper(ObjectChangeMapper
.NewInstance(TaxonBase
.class, TaxonName
.class, "Name"));
2516 addNameMappers(mapping
);
2522 * Returns the CDM to PESI specific export mappings.
2524 * @return The {@link PesiExportMapping PesiExportMapping}.
2525 * @throws UndefinedTransformerMethodException
2527 private PesiExportMapping
getPureNameMapping(PesiExportState state
) throws UndefinedTransformerMethodException
{
2528 PesiExportMapping mapping
= new PesiExportMapping(dbTableName
);
2530 mapping
.addMapper(IdMapper
.NewInstance("TaxonId"));
2532 // mapping.addMapper(MethodMapper.NewInstance("TaxonStatusFk", this.getClass(), "getTaxonStatusFk", standardMethodParameter, PesiExportState.class));
2534 mapping
.addMapper(MethodMapper
.NewInstance("KingdomFk", this, TaxonName
.class));
2535 mapping
.addMapper(MethodMapper
.NewInstance("RankFk", this, TaxonName
.class));
2536 mapping
.addMapper(MethodMapper
.NewInstance("RankCache", this, TaxonName
.class, PesiExportState
.class));
2537 mapping
.addMapper(DbConstantMapper
.NewInstance("TaxonStatusFk", Types
.INTEGER
, PesiTransformer
.T_STATUS_UNACCEPTED
));
2538 mapping
.addMapper(DbConstantMapper
.NewInstance("TaxonStatusCache", Types
.VARCHAR
, state
.getTransformer().getTaxonStatusCacheByKey( PesiTransformer
.T_STATUS_UNACCEPTED
)));
2539 mapping
.addMapper(DbStringMapper
.NewInstance("AuthorshipCache", "AuthorString").setBlankToNull(true));
2540 mapping
.addMapper(MethodMapper
.NewInstance("WebShowName", this, TaxonName
.class));
2541 mapping
.addMapper(MethodMapper
.NewInstance("GUID", this, TaxonName
.class));
2544 mapping
.addMapper(MethodMapper
.NewInstance("DisplayName", this, TaxonName
.class));
2546 mapping
.addMapper(DbLastActionMapper
.NewInstance("LastActionDate", false));
2547 mapping
.addMapper(DbLastActionMapper
.NewInstance("LastAction", true));
2549 addNameMappers(mapping
);
2550 //TODO add author mapper, TypeNameFk
2556 private void addNameMappers(PesiExportMapping mapping
) {
2557 mapping
.addMapper(DbStringMapper
.NewInstance("GenusOrUninomial", "GenusOrUninomial"));
2558 mapping
.addMapper(DbStringMapper
.NewInstance("InfraGenericEpithet", "InfraGenericEpithet"));
2559 mapping
.addMapper(DbStringMapper
.NewInstance("SpecificEpithet", "SpecificEpithet"));
2560 mapping
.addMapper(DbStringMapper
.NewInstance("InfraSpecificEpithet", "InfraSpecificEpithet"));
2562 // mapping.addMapper(DbStringMapper.NewInstance("NameCache", "WebSearchName")); //does not work as we need other cache strategy
2563 mapping
.addMapper(MethodMapper
.NewInstance("WebSearchName", this, TaxonName
.class));
2565 // mapping.addMapper(DbStringMapper.NewInstance("TitleCache", "FullName")); //does not work as we need other cache strategy
2566 mapping
.addMapper(MethodMapper
.NewInstance("FullName", this, TaxonName
.class));
2569 mapping
.addMapper(MethodMapper
.NewInstance("NomRefString", this, TaxonName
.class));
2571 mapping
.addMapper(MethodMapper
.NewInstance("NameStatusFk", this, TaxonName
.class));
2572 mapping
.addMapper(MethodMapper
.NewInstance("NameStatusCache", this, TaxonName
.class, PesiExportState
.class));
2573 mapping
.addMapper(MethodMapper
.NewInstance("TypeFullnameCache", this, TaxonName
.class));
2577 mapping
.addMapper(MethodMapper
.NewInstance("QualityStatusFk", this, TaxonName
.class));
2578 mapping
.addMapper(MethodMapper
.NewInstance("QualityStatusCache", this, TaxonName
.class, PesiExportState
.class));
2580 mapping
.addMapper(MethodMapper
.NewInstance("IdInSource", this, IdentifiableEntity
.class));
2581 mapping
.addMapper(MethodMapper
.NewInstance("OriginalDB", this, IdentifiableEntity
.class) );
2583 //mapping.addMapper(ExpertsAndLastActionMapper.NewInstance());
2588 * Returns the <code>TaxonFk1</code> attribute. It corresponds to a CDM <code>TaxonRelationship</code>.
2589 * @param relationship The {@link RelationshipBase Relationship}.
2590 * @param state The {@link PesiExportState PesiExportState}.
2591 * @return The <code>TaxonFk1</code> attribute.
2594 @SuppressWarnings("unused")
2595 private static Integer
getSynonym(Synonym synonym
, PesiExportState state
) {
2596 return state
.getDbId(synonym
);
2600 private PesiExportMapping
getSynRelMapping() {
2601 PesiExportMapping mapping
= new PesiExportMapping(dbTableNameSynRel
);
2602 logger
.warn("SynRelMapping currently not implemented. Needs to be checked");
2604 mapping
.addMapper(MethodMapper
.NewInstance("TaxonFk1", this.getClass(), "getSynonym", Synonym
.class, PesiExportState
.class));
2605 mapping
.addMapper(DbObjectMapper
.NewInstance("acceptedTaxon", "TaxonFk2"));
2606 mapping
.addMapper(DbObjectMapper
.NewInstance("type", "RelTaxonQualifierFk"));
2607 mapping
.addMapper(MethodMapper
.NewInstance("RelQualifierCache", this.getClass(), "getSynonymTypeCache", Synonym
.class, PesiExportState
.class));
2609 // mapping.addMapper(MethodMapper.NewInstance("Notes", this, RelationshipBase.class));
2614 private PesiExportMapping
getAdditionalSourceMapping(PesiExportState state
) {
2615 PesiExportMapping mapping
= new PesiExportMapping(dbTableAdditionalSourceRel
);
2617 mapping
.addMapper(IdMapper
.NewInstance("TaxonFk"));
2618 mapping
.addMapper(ObjectChangeMapper
.NewInstance(TaxonBase
.class, TaxonName
.class, "Name"));
2620 mapping
.addMapper(DbObjectMapper
.NewInstance("NomenclaturalReference", "SourceFk"));
2621 // mapping.addMapper(DbObjectMapper.NewInstance("NomenclaturalReference", "SourceNameCache", IS_CACHE));
2622 mapping
.addMapper(MethodMapper
.NewInstance("SourceNameCache", this, TaxonName
.class));
2624 //we have only nomenclatural references here
2625 mapping
.addMapper(DbConstantMapper
.NewInstance("SourceUseFk", Types
.INTEGER
, PesiTransformer
.NOMENCLATURAL_REFERENCE
));
2626 mapping
.addMapper(DbConstantMapper
.NewInstance("SourceUseCache", Types
.VARCHAR
, state
.getTransformer().getSourceUseCacheByKey( PesiTransformer
.NOMENCLATURAL_REFERENCE
)));
2628 mapping
.addMapper(DbStringMapper
.NewInstance("NomenclaturalMicroReference", "SourceDetail"));
2635 protected boolean doCheck(PesiExportState state
) {
2640 protected boolean isIgnore(PesiExportState state
) {
2641 return ! state
.getConfig().isDoTaxa();