3 * Copyright (C) 2009 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
10 package eu
.etaxonomy
.cdm
.io
.pesi
.out
;
12 import java
.sql
.Connection
;
13 import java
.sql
.PreparedStatement
;
14 import java
.sql
.ResultSet
;
15 import java
.sql
.SQLException
;
16 import java
.util
.ArrayList
;
17 import java
.util
.HashMap
;
18 import java
.util
.List
;
20 import java
.util
.UUID
;
22 import org
.apache
.commons
.lang
.StringUtils
;
23 import org
.apache
.log4j
.Logger
;
24 import org
.joda
.time
.DateTime
;
25 import org
.joda
.time
.format
.DateTimeFormat
;
26 import org
.joda
.time
.format
.DateTimeFormatter
;
27 import org
.springframework
.stereotype
.Component
;
28 import org
.springframework
.transaction
.TransactionStatus
;
30 import eu
.etaxonomy
.cdm
.common
.CdmUtils
;
31 import eu
.etaxonomy
.cdm
.io
.common
.Source
;
32 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbExtensionMapper
;
33 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbObjectMapper
;
34 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.IdMapper
;
35 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.MethodMapper
;
36 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.ObjectChangeMapper
;
37 import eu
.etaxonomy
.cdm
.io
.pesi
.erms
.ErmsTransformer
;
38 import eu
.etaxonomy
.cdm
.model
.common
.Annotation
;
39 import eu
.etaxonomy
.cdm
.model
.common
.AnnotationType
;
40 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
41 import eu
.etaxonomy
.cdm
.model
.common
.Extension
;
42 import eu
.etaxonomy
.cdm
.model
.common
.ExtensionType
;
43 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableSource
;
44 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
45 import eu
.etaxonomy
.cdm
.model
.name
.NameTypeDesignation
;
46 import eu
.etaxonomy
.cdm
.model
.name
.NameTypeDesignationStatus
;
47 import eu
.etaxonomy
.cdm
.model
.name
.NomenclaturalCode
;
48 import eu
.etaxonomy
.cdm
.model
.name
.NomenclaturalStatus
;
49 import eu
.etaxonomy
.cdm
.model
.name
.NomenclaturalStatusType
;
50 import eu
.etaxonomy
.cdm
.model
.name
.NonViralName
;
51 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
52 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameBase
;
53 import eu
.etaxonomy
.cdm
.model
.name
.ZoologicalName
;
54 import eu
.etaxonomy
.cdm
.model
.reference
.Reference
;
55 import eu
.etaxonomy
.cdm
.model
.taxon
.Classification
;
56 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
57 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
58 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
59 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
60 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationship
;
61 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationshipType
;
62 import eu
.etaxonomy
.cdm
.persistence
.query
.MatchMode
;
63 import eu
.etaxonomy
.cdm
.strategy
.cache
.TaggedText
;
66 * The export class for {@link eu.etaxonomy.cdm.model.name.TaxonNameBase TaxonNames}.<p>
67 * Inserts into DataWarehouse database table <code>Taxon</code>.
68 * It is divided into four phases:<p><ul>
69 * <li>Phase 1: Export of all {@link eu.etaxonomy.cdm.model.name.TaxonNameBase TaxonNames} except some data exported in the following phases.
70 * <li>Phase 2: Export of additional data: ParenTaxonFk and TreeIndex.
71 * <li>Phase 3: Export of additional data: Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk.
72 * <li>Phase 4: Export of Inferred Synonyms.</ul>
78 public class PesiTaxonExport
extends PesiExportBase
{
79 private static final Logger logger
= Logger
.getLogger(PesiTaxonExport
.class);
80 private static final Class
<?
extends CdmBase
> standardMethodParameter
= TaxonBase
.class;
82 private static int modCount
= 1000;
83 private static final String dbTableName
= "Taxon";
84 private static final String pluralString
= "Taxa";
85 private static final String parentPluralString
= "Taxa";
86 private PreparedStatement parentTaxonFk_TreeIndex_KingdomFkStmt
;
87 private PreparedStatement rankTypeExpertsUpdateStmt
;
88 private PreparedStatement rankUpdateStmt
;
89 private NomenclaturalCode nomenclaturalCode
;
90 private Integer kingdomFk
;
91 private HashMap
<Rank
, Rank
> rankMap
= new HashMap
<Rank
, Rank
>();
92 private List
<Rank
> rankList
= new ArrayList
<Rank
>();
93 private static final UUID uuidTreeIndex
= UUID
.fromString("28f4e205-1d02-4d3a-8288-775ea8413009");
94 private AnnotationType treeIndexAnnotationType
;
95 private static ExtensionType lastActionExtensionType
;
96 private static ExtensionType lastActionDateExtensionType
;
97 private static ExtensionType expertNameExtensionType
;
98 private static ExtensionType speciesExpertNameExtensionType
;
99 private static ExtensionType cacheCitationExtensionType
;
100 private static ExtensionType expertUserIdExtensionType
;
101 private static ExtensionType speciesExpertUserIdExtensionType
;
104 * @return the treeIndexAnnotationType
106 protected AnnotationType
getTreeIndexAnnotationType() {
107 return treeIndexAnnotationType
;
111 * @param treeIndexAnnotationType the treeIndexAnnotationType to set
113 protected void setTreeIndexAnnotationType(AnnotationType treeIndexAnnotationType
) {
114 this.treeIndexAnnotationType
= treeIndexAnnotationType
;
125 public PesiTaxonExport() {
130 * @see eu.etaxonomy.cdm.io.common.DbExportBase#getStandardMethodParameter()
133 public Class
<?
extends CdmBase
> getStandardMethodParameter() {
134 return standardMethodParameter
;
138 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doCheck(eu.etaxonomy.cdm.io.common.IoStateBase)
141 protected boolean doCheck(PesiExportState state
) {
142 boolean result
= true;
148 * Returns the CDM to PESI specific export mappings.
149 * @return The {@link PesiExportMapping PesiExportMapping}.
151 private PesiExportMapping
getMapping() {
152 PesiExportMapping mapping
= new PesiExportMapping(dbTableName
);
153 ExtensionType extensionType
= null;
155 mapping
.addMapper(IdMapper
.NewInstance("TaxonId"));
156 mapping
.addMapper(DbObjectMapper
.NewInstance("sec", "sourceFk")); //OLD:mapping.addMapper(MethodMapper.NewInstance("SourceFK", this.getClass(), "getSourceFk", standardMethodParameter, PesiExportState.class));
157 mapping
.addMapper(MethodMapper
.NewInstance("TaxonStatusFk", this.getClass(), "getTaxonStatusFk", standardMethodParameter
, PesiExportState
.class));
158 mapping
.addMapper(MethodMapper
.NewInstance("TaxonStatusCache", this.getClass(), "getTaxonStatusCache", standardMethodParameter
, PesiExportState
.class));
159 // QualityStatus (Fk, Cache)
160 extensionType
= (ExtensionType
)getTermService().find(ErmsTransformer
.uuidQualityStatus
);
161 if (extensionType
!= null) {
162 mapping
.addMapper(DbExtensionMapper
.NewInstance(extensionType
, "QualityStatusCache"));
164 mapping
.addMapper(MethodMapper
.NewInstance("QualityStatusCache", this));
166 mapping
.addMapper(MethodMapper
.NewInstance("QualityStatusFk", this)); // PesiTransformer.QualityStatusCache2QualityStatusFk?
168 mapping
.addMapper(MethodMapper
.NewInstance("GUID", this));
169 //TODO implement again
170 // mapping.addMapper(MethodMapper.NewInstance("IdInSource", this));
172 mapping
.addMapper(MethodMapper
.NewInstance("DerivedFromGuid", this));
173 mapping
.addMapper(MethodMapper
.NewInstance("CacheCitation", this));
174 mapping
.addMapper(MethodMapper
.NewInstance("OriginalDB", this));
175 mapping
.addMapper(MethodMapper
.NewInstance("LastAction", this));
176 mapping
.addMapper(MethodMapper
.NewInstance("LastActionDate", this));
177 mapping
.addMapper(MethodMapper
.NewInstance("ExpertName", this));
178 mapping
.addMapper(MethodMapper
.NewInstance("SpeciesExpertName", this));
180 mapping
.addMapper(MethodMapper
.NewInstance("AuthorString", this)); //For Taxon because Misallied Names are handled differently
183 mapping
.addMapper(ObjectChangeMapper
.NewInstance(TaxonBase
.class, TaxonNameBase
.class, "Name"));
184 mapping
.addMapper(MethodMapper
.NewInstance("GenusOrUninomial", this, TaxonNameBase
.class ));
185 mapping
.addMapper(MethodMapper
.NewInstance("InfraGenericEpithet", this, TaxonNameBase
.class));
186 mapping
.addMapper(MethodMapper
.NewInstance("SpecificEpithet", this, TaxonNameBase
.class));
187 mapping
.addMapper(MethodMapper
.NewInstance("InfraSpecificEpithet", this, TaxonNameBase
.class));
188 mapping
.addMapper(MethodMapper
.NewInstance("WebSearchName", this, TaxonNameBase
.class));
189 mapping
.addMapper(MethodMapper
.NewInstance("WebShowName", this, TaxonNameBase
.class));
190 mapping
.addMapper(MethodMapper
.NewInstance("FullName", this, TaxonNameBase
.class));
191 mapping
.addMapper(MethodMapper
.NewInstance("NomRefString", this, TaxonNameBase
.class));
194 extensionType
= (ExtensionType
)getTermService().find(ErmsTransformer
.uuidDisplayName
);
195 if (extensionType
!= null) {
196 mapping
.addMapper(DbExtensionMapper
.NewInstance(extensionType
, "DisplayName"));
198 mapping
.addMapper(MethodMapper
.NewInstance("DisplayName", this, TaxonNameBase
.class));
201 mapping
.addMapper(MethodMapper
.NewInstance("NameStatusFk", this, TaxonNameBase
.class));
202 mapping
.addMapper(MethodMapper
.NewInstance("NameStatusCache", this, TaxonNameBase
.class));
203 mapping
.addMapper(MethodMapper
.NewInstance("TypeFullnameCache", this, TaxonNameBase
.class));
206 mapping
.addMapper(MethodMapper
.NewInstance("TypeDesignationStatusFk", this, TaxonNameBase
.class));
207 mapping
.addMapper(MethodMapper
.NewInstance("TypeDesignationStatusCache", this, TaxonNameBase
.class));
209 // FossilStatus (Fk, Cache)
210 extensionType
= (ExtensionType
)getTermService().find(ErmsTransformer
.uuidFossilStatus
);
211 if (extensionType
!= null) {
212 mapping
.addMapper(DbExtensionMapper
.NewInstance(extensionType
, "FossilStatusCache"));
214 mapping
.addMapper(MethodMapper
.NewInstance("FossilStatusCache", this, TaxonNameBase
.class));
216 mapping
.addMapper(MethodMapper
.NewInstance("FossilStatusFk", this, TaxonNameBase
.class)); // PesiTransformer.FossilStatusCache2FossilStatusFk?
222 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doInvoke(eu.etaxonomy.cdm.io.common.IoStateBase)
225 protected void doInvoke(PesiExportState state
) {
227 logger
.info("*** Started Making " + pluralString
+ " ...");
229 initPreparedStatements(state
);
231 // Stores whether this invoke was successful or not.
232 boolean success
= true;
234 // PESI: Clear the database table Taxon.
237 // Get specific mappings: (CDM) Taxon -> (PESI) Taxon
238 PesiExportMapping mapping
= getMapping();
240 // Initialize the db mapper
241 mapping
.initialize(state
);
243 // Find extensionTypes
244 lastActionExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.lastActionUuid
);
245 lastActionDateExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.lastActionDateUuid
);
246 expertNameExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.expertNameUuid
);
247 speciesExpertNameExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.speciesExpertNameUuid
);
248 cacheCitationExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.cacheCitationUuid
);
249 expertUserIdExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.expertUserIdUuid
);
250 speciesExpertUserIdExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.speciesExpertUserIdUuid
);
253 success
&= doPhaseOne(state
, mapping
);
255 // 2nd Round: Add ParentTaxonFk, TreeIndex to each Taxon
256 success
&= doPhaseTwo(state
);
258 //PHASE 3: Add Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk...
259 success
&= doPhaseThree(state
);
261 //"PHASE 4: Creating Inferred Synonyms...
262 success
&= doPhaseFour(state
, mapping
);
264 logger
.info("*** Finished Making " + pluralString
+ " ..." + getSuccessString(success
));
267 state
.setUnsuccessfull();
270 } catch (SQLException e
) {
272 logger
.error(e
.getMessage());
273 state
.setUnsuccessfull();
278 private void initPreparedStatements(PesiExportState state
) throws SQLException
{
279 initTreeIndexStatement(state
);
280 initRankExpertsUpdateStmt(state
);
281 initRankUpdateStatement(state
);
284 // Prepare TreeIndex-And-KingdomFk-Statement
285 private void initTreeIndexStatement(PesiExportState state
) throws SQLException
{
286 Connection connection
= state
.getConfig().getDestination().getConnection();
287 String parentTaxonFk_TreeIndex_KingdomFkSql
= "UPDATE Taxon SET ParentTaxonFk = ?, TreeIndex = ? WHERE TaxonId = ?";
288 parentTaxonFk_TreeIndex_KingdomFkStmt
= connection
.prepareStatement(parentTaxonFk_TreeIndex_KingdomFkSql
);
291 private void initRankUpdateStatement(PesiExportState state
) throws SQLException
{
292 Connection connection
= state
.getConfig().getDestination().getConnection();
293 String rankSql
= "UPDATE Taxon SET RankFk = ?, RankCache = ?, KingdomFk = ? WHERE TaxonId = ?";
294 rankUpdateStmt
= connection
.prepareStatement(rankSql
);
297 private void initRankExpertsUpdateStmt(PesiExportState state
) throws SQLException
{
298 // String sql_old = "UPDATE Taxon SET RankFk = ?, RankCache = ?, TypeNameFk = ?, KingdomFk = ?, " +
299 // "ExpertFk = ?, SpeciesExpertFk = ? WHERE TaxonId = ?";
300 //TODO handle experts GUIDs
301 Connection connection
= state
.getConfig().getDestination().getConnection();
303 String sql
= "UPDATE Taxon SET RankFk = ?, RankCache = ?, TypeNameFk = ?, KingdomFk = ? " +
304 " WHERE TaxonId = ?";
305 rankTypeExpertsUpdateStmt
= connection
.prepareStatement(sql
);
308 private boolean doPhaseOne(PesiExportState state
, PesiExportMapping mapping
) throws SQLException
{
311 List
<TaxonBase
> list
;
312 boolean success
= true;
313 // Get the limit for objects to save within a single transaction.
314 int limit
= state
.getConfig().getLimitSave();
317 logger
.info("PHASE 1: Export Taxa...");
319 TransactionStatus txStatus
= startTransaction(true);
320 logger
.info("Started new transaction. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
321 while ((list
= getTaxonService().list(null, limit
, count
, null, null)).size() > 0) {
323 logger
.info("Fetched " + list
.size() + " " + pluralString
+ ". Exporting...");
324 for (TaxonBase
<?
> taxon
: list
) {
325 doCount(count
++, modCount
, pluralString
);
326 success
&= mapping
.invoke(taxon
);
328 TaxonNameBase
<?
,?
> taxonName
= taxon
.getName();
330 // Check whether some rules are violated
331 nomenclaturalCode
= PesiTransformer
.getNomenclaturalCode(taxonName
);
332 String genusOrUninomial
= getGenusOrUninomial(taxonName
);
333 String specificEpithet
= getSpecificEpithet(taxonName
);
334 String infraSpecificEpithet
= getInfraSpecificEpithet(taxonName
);
335 String infraGenericEpithet
= getInfraGenericEpithet(taxonName
);
336 Integer rank
= getRankFk(taxonName
, nomenclaturalCode
);
339 logger
.error("Rank was not determined: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
342 // Check whether infraGenericEpithet is set correctly
343 // 1. Childs of an accepted taxon of rank subgenus that are accepted taxa of rank species have to have an infraGenericEpithet
344 // 2. Grandchilds of an accepted taxon of rank subgenus that are accepted taxa of rank subspecies have to have an infraGenericEpithet
346 int ancestorLevel
= 0;
347 if (taxonName
.getRank().equals(Rank
.SUBSPECIES())) {
348 // The accepted taxon two rank levels above should be of rank subgenus
351 if (taxonName
.getRank().equals(Rank
.SPECIES())) {
352 // The accepted taxon one rank level above should be of rank subgenus
355 if (ancestorLevel
> 0) {
356 if (ancestorOfSpecificRank(taxon
, ancestorLevel
, Rank
.SUBGENUS())) {
357 // The child (species or subspecies) of this parent (subgenus) has to have an infraGenericEpithet
358 if (infraGenericEpithet
== null) {
359 logger
.warn("InfraGenericEpithet does not exist even though it should for: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
360 // maybe the taxon could be named here
365 if (infraGenericEpithet
== null && rank
.intValue() == 190) {
366 logger
.warn("InfraGenericEpithet was not determined although it should exist for rank 190: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
368 if (specificEpithet
!= null && rank
.intValue() < 220) {
369 logger
.warn("SpecificEpithet was determined for rank " + rank
+ " although it should only exist for ranks higher or equal to 220: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
371 if (infraSpecificEpithet
!= null && rank
.intValue() < 230) {
372 String message
= "InfraSpecificEpithet '" +infraSpecificEpithet
+ "' was determined for rank " + rank
+ " although it should only exist for ranks higher or equal to 230: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")";
373 if (StringUtils
.isNotBlank(infraSpecificEpithet
)){
374 logger
.warn(message
);
376 logger
.warn(message
);
380 if (infraSpecificEpithet
!= null && specificEpithet
== null) {
381 logger
.error("An infraSpecificEpithet was determined, but a specificEpithet was not determined: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
383 if (genusOrUninomial
== null) {
384 logger
.error("GenusOrUninomial was not determined: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
389 // Commit transaction
390 commitTransaction(txStatus
);
391 logger
.debug("Committed transaction.");
392 logger
.info("Exported " + (count
- pastCount
) + " " + pluralString
+ ". Total: " + count
);
396 txStatus
= startTransaction(true);
397 logger
.info("Started new transaction. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
399 if (list
.size() == 0) {
400 logger
.info("No " + pluralString
+ " left to fetch.");
402 // Commit transaction
403 commitTransaction(txStatus
);
404 logger
.debug("Committed transaction.");
408 // 2nd Round: Add ParentTaxonFk, TreeIndex to each Taxon
409 private boolean doPhaseTwo(PesiExportState state
) {
410 boolean success
= true;
411 List
<Classification
> classificationList
= null;
412 logger
.info("PHASE 2: Add ParenTaxonFk and TreeIndex...");
414 // Specify starting ranks for tree traversing
415 rankList
.add(Rank
.KINGDOM());
416 rankList
.add(Rank
.GENUS());
418 // Specify where to stop traversing (value) when starting at a specific Rank (key)
419 rankMap
.put(Rank
.GENUS(), null); // Since NULL does not match an existing Rank, traverse all the way down to the leaves
420 rankMap
.put(Rank
.KINGDOM(), Rank
.GENUS()); // excludes rank genus
422 StringBuffer treeIndex
= new StringBuffer();
424 // Retrieve list of classifications
425 TransactionStatus txStatus
= startTransaction(true);
426 logger
.info("Started transaction. Fetching all classifications...");
427 classificationList
= getClassificationService().listClassifications(null, 0, null, null);
428 commitTransaction(txStatus
);
429 logger
.debug("Committed transaction.");
431 logger
.info("Fetched " + classificationList
.size() + " classification(s).");
433 setTreeIndexAnnotationType(getAnnotationType(uuidTreeIndex
, "TreeIndex", "", "TI"));
435 for (Classification classification
: classificationList
) {
436 for (Rank rank
: rankList
) {
438 txStatus
= startTransaction(true);
439 logger
.info("Started transaction to fetch all rootNodes specific to Rank " + rank
.getLabel() + " ...");
441 List
<TaxonNode
> rankSpecificRootNodes
= getClassificationService().loadRankSpecificRootNodes(classification
, rank
, null);
442 logger
.info("Fetched " + rankSpecificRootNodes
.size() + " RootNodes for Rank " + rank
.getLabel());
444 commitTransaction(txStatus
);
445 logger
.debug("Committed transaction.");
447 for (TaxonNode rootNode
: rankSpecificRootNodes
) {
448 txStatus
= startTransaction(false);
449 Rank endRank
= rankMap
.get(rank
);
450 if (endRank
!= null) {
451 logger
.debug("Started transaction to traverse childNodes of rootNode (" + rootNode
.getUuid() + ") till Rank " + endRank
.getLabel() + " ...");
453 logger
.debug("Started transaction to traverse childNodes of rootNode (" + rootNode
.getUuid() + ") till leaves are reached ...");
456 TaxonNode newNode
= getTaxonNodeService().load(rootNode
.getUuid());
458 TaxonNode parentNode
= newNode
.getParent();
459 if (rank
.equals(Rank
.KINGDOM())) {
460 treeIndex
= new StringBuffer();
461 treeIndex
.append("#");
463 // Get treeIndex from parentNode
464 if (parentNode
!= null) {
465 boolean annotationFound
= false;
466 Set
<Annotation
> annotations
= parentNode
.getAnnotations();
467 for (Annotation annotation
: annotations
) {
468 AnnotationType annotationType
= annotation
.getAnnotationType();
469 if (annotationType
!= null && annotationType
.equals(getTreeIndexAnnotationType())) {
470 treeIndex
= new StringBuffer(CdmUtils
.Nz(annotation
.getText()));
471 annotationFound
= true;
472 // logger.error("treeIndex: " + treeIndex);
476 if (!annotationFound
) {
477 // This should not happen because it means that the treeIndex was not set correctly as an annotation to parentNode
478 logger
.error("TreeIndex could not be read from annotation of this TaxonNode: " + parentNode
.getUuid());
479 treeIndex
= new StringBuffer();
480 treeIndex
.append("#");
483 // TreeIndex could not be determined, but it's unclear how to proceed to generate a correct treeIndex if the parentNode is NULL
484 logger
.error("ParentNode for RootNode is NULL. TreeIndex could not be determined: " + newNode
.getUuid());
485 treeIndex
= new StringBuffer(); // This just prevents growing of the treeIndex in a wrong manner
486 treeIndex
.append("#");
490 nomenclaturalCode
= PesiTransformer
.getNomenclaturalCode(newNode
.getTaxon().getName());
491 kingdomFk
= PesiTransformer
.nomenClaturalCode2Kingdom(nomenclaturalCode
);
492 traverseTree(newNode
, parentNode
, treeIndex
, rankMap
.get(rank
), state
);
494 commitTransaction(txStatus
);
495 logger
.debug("Committed transaction.");
503 //PHASE 3: Add Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk...
504 private boolean doPhaseThree(PesiExportState state
) {
507 boolean success
= true;
508 // Get the limit for objects to save within a single transaction.
509 int limit
= state
.getConfig().getLimitSave();
511 List
<TaxonNameBase
> list
;
512 logger
.info("PHASE 3: Add Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk...");
513 // Be sure to add rank information, KingdomFk, TypeNameFk, expertFk and speciesExpertFk to every taxonName
516 TransactionStatus txStatus
= startTransaction(true);
517 logger
.info("Started new transaction. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
518 while ((list
= getNameService().list(null, limit
, count
, null, null)).size() > 0) {
520 logger
.info("Fetched " + list
.size() + " " + pluralString
+ ". Exporting...");
521 for (TaxonNameBase
<?
,?
> taxonName
: list
) {
523 // Determine expertFk
524 Integer expertFk
= makeExpertFk(state
, taxonName
);
526 // Determine speciesExpertFk
527 Integer speciesExpertFk
= makeSpeciesExpertFk(state
, taxonName
);
529 doCount(count
++, modCount
, pluralString
);
530 Integer typeNameFk
= getTypeNameFk(taxonName
, state
);
532 //TODO why are expertFks needed? (Andreas M.)
533 // if (expertFk != null || speciesExpertFk != null) {
534 invokeRankDataAndTypeNameFkAndKingdomFk(taxonName
, nomenclaturalCode
, state
.getDbId(taxonName
),
535 typeNameFk
, kingdomFk
, expertFk
, speciesExpertFk
);
539 // Commit transaction
540 commitTransaction(txStatus
);
541 logger
.debug("Committed transaction.");
542 logger
.info("Exported " + (count
- pastCount
) + " " + pluralString
+ ". Total: " + count
);
546 txStatus
= startTransaction(true);
547 logger
.info("Started new transaction. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
549 if (list
.size() == 0) {
550 logger
.info("No " + pluralString
+ " left to fetch.");
552 // Commit transaction
553 commitTransaction(txStatus
);
554 logger
.debug("Committed transaction.");
558 private Integer
makeSpeciesExpertFk(PesiExportState state
, TaxonNameBase
<?
, ?
> taxonName
) {
559 List
<Reference
> referenceList
;
560 Integer speciesExpertFk
= null;
561 String speciesExpertUserId
= getSpeciesExpertUserId(taxonName
);
562 if (speciesExpertUserId
!= null) {
564 // The speciesExpertUserId was stored in the field 'title' of the corresponding Reference during FaEu import
565 referenceList
= getReferenceService().listByReferenceTitle(null, speciesExpertUserId
, MatchMode
.EXACT
, null, null, null, null, null);
566 if (referenceList
.size() == 1) {
567 speciesExpertFk
= getSpeciesExpertFk(referenceList
.iterator().next(), state
);
568 } else if (referenceList
.size() > 1) {
569 logger
.error("Found more than one match using listByTitle() searching for a Reference with this speciesExpertUserId as title: " + speciesExpertUserId
);
570 } else if (referenceList
.size() == 0) {
571 logger
.error("Found no match using listByReferenceTitle() searching for a Reference with this speciesExpertUserId as title: " + speciesExpertUserId
);
574 logger
.debug("SpeciesExpertName is NULL for this TaxonName: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
576 return speciesExpertFk
;
579 private Integer
makeExpertFk(PesiExportState state
,
580 TaxonNameBase
<?
, ?
> taxonName
) {
581 List
<Reference
> referenceList
;
582 Integer expertFk
= null;
583 String expertUserId
= getExpertUserId(taxonName
);
584 if (expertUserId
!= null) {
586 // The expertUserId was stored in the field 'title' of the corresponding Reference during FaEu import
587 referenceList
= getReferenceService().listByReferenceTitle(null, expertUserId
, MatchMode
.EXACT
, null, null, null, null, null);
588 if (referenceList
.size() == 1) {
589 expertFk
= getExpertFk(referenceList
.iterator().next(), state
);
590 } else if (referenceList
.size() > 1) {
591 logger
.error("Found more than one match using listByReferenceTitle() searching for a Reference with this expertUserId as title: " + expertUserId
);
592 } else if (referenceList
.size() == 0) {
593 logger
.error("Found no match using listByReferenceTitle() searching for a Reference with this expertUserId as title: " + expertUserId
);
596 logger
.debug("ExpertName is NULL for this TaxonName: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
601 private boolean doPhaseFour(PesiExportState state
, PesiExportMapping mapping
) throws SQLException
{
604 boolean success
= true;
605 // Get the limit for objects to save within a single transaction.
606 int limit
= state
.getConfig().getLimitSave();
608 // Create inferred synonyms for accepted taxa
609 logger
.info("PHASE 4: Creating Inferred Synonyms...");
611 // Determine the count of elements in datawarehouse database table Taxon
612 Integer currentTaxonId
= determineTaxonCount(state
);
617 int pageSize
= limit
;
619 String inferredSynonymPluralString
= "Inferred Synonyms";
622 Classification classification
= null;
623 Taxon acceptedTaxon
= null;
624 TransactionStatus txStatus
= startTransaction(true);
625 logger
.info("Started new transaction. Fetching some " + parentPluralString
+ " first (max: " + limit
+ ") ...");
626 List
<TaxonBase
> taxonList
= null;
627 List
<Synonym
> inferredSynonyms
= null;
628 while ((taxonList
= getTaxonService().listTaxaByName(Taxon
.class, "*", "*", "*", "*", null, pageSize
, pageNumber
)).size() > 0) {
629 HashMap
<Integer
, TaxonNameBase
<?
,?
>> inferredSynonymsDataToBeSaved
= new HashMap
<Integer
, TaxonNameBase
<?
,?
>>();
631 logger
.info("Fetched " + taxonList
.size() + " " + parentPluralString
+ ". Exporting...");
632 for (TaxonBase
<?
> taxonBase
: taxonList
) {
634 if (taxonBase
.isInstanceOf(Taxon
.class)) { // this should always be the case since we should have fetched accepted taxon only, but you never know...
635 acceptedTaxon
= CdmBase
.deproxy(taxonBase
, Taxon
.class);
636 TaxonNameBase
<?
,?
> taxonName
= acceptedTaxon
.getName();
638 if (taxonName
.isInstanceOf(ZoologicalName
.class)) {
639 nomenclaturalCode
= PesiTransformer
.getNomenclaturalCode(taxonName
);
640 kingdomFk
= PesiTransformer
.nomenClaturalCode2Kingdom(nomenclaturalCode
);
642 Set
<TaxonNode
> taxonNodes
= acceptedTaxon
.getTaxonNodes();
643 TaxonNode singleNode
= null;
644 if (taxonNodes
.size() > 0) {
645 // Determine the classification of the current TaxonNode
646 singleNode
= taxonNodes
.iterator().next();
647 if (singleNode
!= null) {
648 classification
= singleNode
.getClassification();
650 logger
.error("A TaxonNode belonging to this accepted Taxon is NULL: " + acceptedTaxon
.getUuid() + " (" + acceptedTaxon
.getTitleCache() +")");
653 // Classification could not be determined directly from this TaxonNode
654 // The stored classification from another TaxonNode is used. It's a simple, but not a failsafe fallback solution.
655 if (classification
== null) {
656 logger
.error("Classification could not be determined directly from this TaxonNode: " + singleNode
.getUuid() + "). " +
657 "This classification stored from another TaxonNode is used: " + classification
.getTitleCache());
661 if (classification
!= null) {
662 inferredSynonyms
= getTaxonService().createAllInferredSynonyms(classification
, acceptedTaxon
);
664 // inferredSynonyms = getTaxonService().createInferredSynonyms(classification, acceptedTaxon, SynonymRelationshipType.INFERRED_GENUS_OF());
665 if (inferredSynonyms
!= null) {
666 for (Synonym synonym
: inferredSynonyms
) {
667 TaxonNameBase
<?
,?
> synonymName
= synonym
.getName();
668 if (synonymName
!= null) {
670 // Both Synonym and its TaxonName have no valid Id yet
671 synonym
.setId(currentTaxonId
++);
672 synonymName
.setId(currentTaxonId
++);
674 doCount(count
++, modCount
, inferredSynonymPluralString
);
675 success
&= mapping
.invoke(synonymName
);
677 // Add Rank Data and KingdomFk to hashmap for later saving
678 inferredSynonymsDataToBeSaved
.put(synonymName
.getId(), synonymName
);
680 logger
.error("TaxonName of this Synonym is NULL: " + synonym
.getUuid() + " (" + synonym
.getTitleCache() + ")");
685 logger
.error("Classification is NULL. Inferred Synonyms could not be created for this Taxon: " + acceptedTaxon
.getUuid() + " (" + acceptedTaxon
.getTitleCache() + ")");
688 // logger.error("TaxonName is not a ZoologicalName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
691 logger
.error("This TaxonBase is not a Taxon even though it should be: " + taxonBase
.getUuid() + " (" + taxonBase
.getTitleCache() + ")");
695 // Commit transaction
696 commitTransaction(txStatus
);
697 logger
.debug("Committed transaction.");
698 logger
.info("Exported " + (count
- pastCount
) + " " + inferredSynonymPluralString
+ ". Total: " + count
);
701 // Save Rank Data and KingdomFk for inferred synonyms
702 for (Integer taxonFk
: inferredSynonymsDataToBeSaved
.keySet()) {
703 invokeRankDataAndKingdomFk(inferredSynonymsDataToBeSaved
.get(taxonFk
), nomenclaturalCode
, taxonFk
, kingdomFk
);
707 txStatus
= startTransaction(true);
708 logger
.info("Started new transaction. Fetching some " + parentPluralString
+ " first (max: " + limit
+ ") ...");
710 // Increment pageNumber
713 if (taxonList
.size() == 0) {
714 logger
.info("No " + parentPluralString
+ " left to fetch.");
716 // Commit transaction
717 commitTransaction(txStatus
);
718 logger
.debug("Committed transaction.");
723 * Determines the current number of entries in the DataWarehouse database table <code>Taxon</code>.
724 * @param state The {@link PesiExportState PesiExportState}.
727 private Integer
determineTaxonCount(PesiExportState state
) {
728 Integer result
= null;
729 PesiExportConfigurator pesiConfig
= (PesiExportConfigurator
) state
.getConfig();
732 Source destination
= pesiConfig
.getDestination();
733 sql
= "SELECT COUNT(*) FROM Taxon";
734 destination
.setQuery(sql
);
735 ResultSet resultSet
= destination
.getResultSet();
738 result
= resultSet
.getInt(1);
739 } catch (SQLException e
) {
740 logger
.error("TaxonCount could not be determined: " + e
.getMessage());
747 * Returns the userId of the expert associated with the given TaxonName.
748 * @param taxonName A {@link TaxonNameBase TaxonName}.
749 * @return The userId.
751 private String
getExpertUserId(TaxonNameBase
<?
,?
> taxonName
) {
752 String result
= null;
754 Set
<Extension
> extensions
= taxonName
.getExtensions();
755 for (Extension extension
: extensions
) {
756 if (extension
.getType().equals(expertUserIdExtensionType
)) {
757 result
= extension
.getValue();
760 } catch (Exception e
) {
767 * Returns the userId of the speciesExpert associated with the given TaxonName.
768 * @param taxonName A {@link TaxonNameBase TaxonName}.
769 * @return The userId.
771 private String
getSpeciesExpertUserId(TaxonNameBase
<?
,?
> taxonName
) {
772 String result
= null;
774 Set
<Extension
> extensions
= taxonName
.getExtensions();
775 for (Extension extension
: extensions
) {
776 if (extension
.getType().equals(speciesExpertUserIdExtensionType
)) {
777 result
= extension
.getValue();
780 } catch (Exception e
) {
787 * Checks whether a parent at specific level has a specific Rank.
788 * @param taxonName A {@link TaxonNameBase TaxonName}.
789 * @param level The ancestor level.
790 * @param ancestorRank The ancestor rank.
791 * @return Whether a parent at a specific level has a specific Rank.
793 private boolean ancestorOfSpecificRank(TaxonBase
<?
> taxonBase
, int level
, Rank ancestorRank
) {
794 boolean result
= false;
795 TaxonNode parentNode
= null;
796 if (taxonBase
.isInstanceOf(Taxon
.class)){
797 Taxon taxon
= CdmBase
.deproxy(taxonBase
, Taxon
.class);
798 // Get ancestor Taxon via TaxonNode
799 Set
<TaxonNode
> taxonNodes
= taxon
.getTaxonNodes();
800 if (taxonNodes
.size() == 1) {
801 TaxonNode taxonNode
= taxonNodes
.iterator().next();
802 if (taxonNode
!= null) {
803 for (int i
= 0; i
< level
; i
++) {
804 if (taxonNode
!= null) {
805 taxonNode
= taxonNode
.getParent();
808 parentNode
= taxonNode
;
810 } else if (taxonNodes
.size() > 1) {
811 logger
.error("This taxon has " + taxonNodes
.size() + " taxonNodes: " + taxon
.getUuid() + " (" + taxon
.getTitleCache() + ")");
815 if (parentNode
!= null) {
816 TaxonNode node
= CdmBase
.deproxy(parentNode
, TaxonNode
.class);
817 Taxon parentTaxon
= node
.getTaxon();
818 if (parentTaxon
!= null) {
819 TaxonNameBase
<?
,?
> parentTaxonName
= parentTaxon
.getName();
820 if (parentTaxonName
!= null && parentTaxonName
.getRank().equals(ancestorRank
)) {
824 logger
.error("This TaxonNode has no Taxon: " + node
.getUuid());
831 * Returns the AnnotationType for a given UUID.
832 * @param uuid The Annotation UUID.
833 * @param label The Annotation label.
834 * @param text The Annotation text.
835 * @param labelAbbrev The Annotation label abbreviation.
836 * @return The AnnotationType.
838 protected AnnotationType
getAnnotationType(UUID uuid
, String label
, String text
, String labelAbbrev
){
839 AnnotationType annotationType
= (AnnotationType
)getTermService().find(uuid
);
840 if (annotationType
== null) {
841 annotationType
= AnnotationType
.NewInstance(label
, text
, labelAbbrev
);
842 annotationType
.setUuid(uuid
);
843 // annotationType.setVocabulary(AnnotationType.EDITORIAL().getVocabulary());
844 getTermService().save(annotationType
);
846 return annotationType
;
850 * Traverses the classification recursively and stores determined values for every Taxon.
851 * @param childNode The {@link TaxonNode TaxonNode} to process.
852 * @param parentNode The parent {@link TaxonNode TaxonNode} of the childNode.
853 * @param treeIndex The TreeIndex at the current level.
854 * @param fetchLevel Rank to stop fetching at.
855 * @param state The {@link PesiExportState PesiExportState}.
857 private void traverseTree(TaxonNode childNode
, TaxonNode parentNode
, StringBuffer treeIndex
, Rank fetchLevel
, PesiExportState state
) {
858 // Traverse all branches from this childNode until specified fetchLevel is reached.
859 StringBuffer localTreeIndex
= new StringBuffer(treeIndex
);
860 if (childNode
.getTaxon() != null) {
861 TaxonNameBase
<?
,?
> taxonName
= childNode
.getTaxon().getName();
862 Integer taxonNameId
= state
.getDbId(taxonName
);
863 if (taxonNameId
!= null) {
864 Rank childTaxonNameRank
= taxonName
.getRank();
865 if (childTaxonNameRank
!= null) {
866 if (! childTaxonNameRank
.equals(fetchLevel
)) {
868 localTreeIndex
.append(taxonNameId
);
869 localTreeIndex
.append("#");
871 saveData(childNode
, parentNode
, localTreeIndex
, state
, taxonNameId
);
873 // Store treeIndex as annotation for further use
874 Annotation annotation
= Annotation
.NewInstance(localTreeIndex
.toString(), getTreeIndexAnnotationType(), Language
.DEFAULT());
875 childNode
.addAnnotation(annotation
);
877 for (TaxonNode newNode
: childNode
.getChildNodes()) {
878 traverseTree(newNode
, childNode
, localTreeIndex
, fetchLevel
, state
);
882 // logger.error("Target Rank " + fetchLevel.getLabel() + " reached");
886 logger
.error("Rank is NULL. FetchLevel can not be checked: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
889 logger
.error("TaxonName can not be found in State: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
893 logger
.error("Taxon is NULL for TaxonNode: " + childNode
.getUuid());
898 * Stores values in database for every recursive round.
899 * @param childNode The {@link TaxonNode TaxonNode} to process.
900 * @param parentNode The parent {@link TaxonNode TaxonNode} of the childNode.
901 * @param treeIndex The TreeIndex at the current level.
902 * @param state The {@link PesiExportState PesiExportState}.
903 * @param currentTaxonFk The TaxonFk to store the values for.
905 private void saveData(TaxonNode childNode
, TaxonNode parentNode
, StringBuffer treeIndex
, PesiExportState state
, Integer currentTaxonFk
) {
906 // We are differentiating kingdoms by the nomenclatural code for now.
907 // This needs to be handled in a better way as soon as we know how to differentiate between more kingdoms.
908 Taxon childNodeTaxon
= childNode
.getTaxon();
909 TaxonNameBase
<?
,?
> childNodeTaxonName
= childNode
.getTaxon().getName();
910 if (childNodeTaxon
!= null && childNodeTaxonName
!= null) {
911 TaxonNameBase
<?
,?
> parentNodeTaxonName
= null;
912 if (parentNode
!= null) {
913 Taxon parentNodeTaxon
= parentNode
.getTaxon();
914 if (parentNodeTaxon
!= null) {
915 parentNodeTaxonName
= parentNodeTaxon
.getName();
919 invokeParentTaxonFkAndTreeIndex(
920 state
.getDbId(parentNodeTaxonName
),
928 * Inserts values into the Taxon database table.
929 * @param taxonName The {@link TaxonNameBase TaxonName}.
930 * @param state The {@link PesiExportState PesiExportState}.
931 * @param stmt The prepared statement.
932 * @return Whether save was successful or not.
934 protected boolean invokeParentTaxonFkAndTreeIndex(Integer parentTaxonFk
, Integer currentTaxonFk
, StringBuffer treeIndex
) {
936 if (parentTaxonFk
!= null) {
937 parentTaxonFk_TreeIndex_KingdomFkStmt
.setInt(1, parentTaxonFk
);
939 parentTaxonFk_TreeIndex_KingdomFkStmt
.setObject(1, null);
942 if (treeIndex
!= null) {
943 parentTaxonFk_TreeIndex_KingdomFkStmt
.setString(2, treeIndex
.toString());
945 parentTaxonFk_TreeIndex_KingdomFkStmt
.setObject(2, null);
948 if (currentTaxonFk
!= null) {
949 parentTaxonFk_TreeIndex_KingdomFkStmt
.setInt(3, currentTaxonFk
);
951 parentTaxonFk_TreeIndex_KingdomFkStmt
.setObject(3, null);
954 parentTaxonFk_TreeIndex_KingdomFkStmt
.executeUpdate();
956 } catch (SQLException e
) {
957 logger
.error("ParentTaxonFk and TreeIndex could not be inserted into database: " + e
.getMessage());
964 * Inserts Rank data and KingdomFk into the Taxon database table.
965 * @param taxonName The {@link TaxonNameBase TaxonName}.
966 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
967 * @param taxonFk The TaxonFk to store the values for.
968 * @param kindomFk The KingdomFk.
969 * @return Whether save was successful or not.
971 private boolean invokeRankDataAndKingdomFk(TaxonNameBase
<?
,?
> taxonName
, NomenclaturalCode nomenclaturalCode
,
972 Integer taxonFk
, Integer kingdomFk
) {
974 Integer rankFk
= getRankFk(taxonName
, nomenclaturalCode
);
975 if (rankFk
!= null) {
976 rankUpdateStmt
.setInt(1, rankFk
);
978 rankUpdateStmt
.setObject(1, null);
981 String rankCache
= getRankCache(taxonName
, nomenclaturalCode
);
982 if (rankCache
!= null) {
983 rankUpdateStmt
.setString(2, rankCache
);
985 rankUpdateStmt
.setObject(2, null);
988 if (kingdomFk
!= null) {
989 rankUpdateStmt
.setInt(3, kingdomFk
);
991 rankUpdateStmt
.setObject(3, null);
994 if (taxonFk
!= null) {
995 rankUpdateStmt
.setInt(4, taxonFk
);
997 rankUpdateStmt
.setObject(4, null);
1000 rankUpdateStmt
.executeUpdate();
1002 } catch (SQLException e
) {
1003 logger
.error("Data (RankFk, RankCache, KingdomFk) could not be inserted into database: " + e
.getMessage());
1004 e
.printStackTrace();
1010 * Inserts Rank data, TypeNameFk, KingdomFk, expertFk and speciesExpertFk into the Taxon database table.
1011 * @param taxonName The {@link TaxonNameBase TaxonName}.
1012 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
1013 * @param taxonFk The TaxonFk to store the values for.
1014 * @param typeNameFk The TypeNameFk.
1015 * @param kindomFk The KingdomFk.
1016 * @param expertFk The ExpertFk.
1017 * @param speciesExpertFk The SpeciesExpertFk.
1018 * @return Whether save was successful or not.
1020 private boolean invokeRankDataAndTypeNameFkAndKingdomFk(TaxonNameBase
<?
,?
> taxonName
, NomenclaturalCode nomenclaturalCode
,
1021 Integer taxonFk
, Integer typeNameFk
, Integer kingdomFk
,
1022 Integer expertFk
, Integer speciesExpertFk
) {
1024 Integer rankFk
= getRankFk(taxonName
, nomenclaturalCode
);
1025 if (rankFk
!= null) {
1026 rankTypeExpertsUpdateStmt
.setInt(1, rankFk
);
1028 rankTypeExpertsUpdateStmt
.setObject(1, null);
1031 String rankCache
= getRankCache(taxonName
, nomenclaturalCode
);
1032 if (rankCache
!= null) {
1033 rankTypeExpertsUpdateStmt
.setString(2, rankCache
);
1035 rankTypeExpertsUpdateStmt
.setObject(2, null);
1038 if (typeNameFk
!= null) {
1039 rankTypeExpertsUpdateStmt
.setInt(3, typeNameFk
);
1041 rankTypeExpertsUpdateStmt
.setObject(3, null);
1044 if (kingdomFk
!= null) {
1045 rankTypeExpertsUpdateStmt
.setInt(4, kingdomFk
);
1047 rankTypeExpertsUpdateStmt
.setObject(4, null);
1050 if (expertFk
!= null) {
1051 rankTypeExpertsUpdateStmt
.setInt(5, expertFk
);
1053 rankTypeExpertsUpdateStmt
.setObject(5, null);
1056 //TODO handle experts GUIDS
1057 // if (speciesExpertFk != null) {
1058 // rankTypeExpertsUpdateStmt.setInt(6, speciesExpertFk);
1060 // rankTypeExpertsUpdateStmt.setObject(6, null);
1063 // if (taxonFk != null) {
1064 // rankTypeExpertsUpdateStmt.setInt(7, taxonFk);
1066 // rankTypeExpertsUpdateStmt.setObject(7, null);
1069 rankTypeExpertsUpdateStmt
.executeUpdate();
1071 } catch (SQLException e
) {
1072 logger
.error("Data could not be inserted into database: " + e
.getMessage());
1073 e
.printStackTrace();
1079 * Deletes all entries of database tables related to <code>Taxon</code>.
1080 * @param state The {@link PesiExportState PesiExportState}.
1081 * @return Whether the delete operation was successful or not.
1083 protected boolean doDelete(PesiExportState state
) {
1084 PesiExportConfigurator pesiConfig
= (PesiExportConfigurator
) state
.getConfig();
1087 Source destination
= pesiConfig
.getDestination();
1090 sql
= "DELETE FROM " + dbTableName
;
1091 destination
.setQuery(sql
);
1092 destination
.update(sql
);
1097 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#isIgnore(eu.etaxonomy.cdm.io.common.IoStateBase)
1100 protected boolean isIgnore(PesiExportState state
) {
1101 return ! state
.getConfig().isDoTaxa();
1105 * Returns the <code>RankFk</code> attribute.
1106 * @param taxonName The {@link TaxonNameBase TaxonName}.
1107 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
1108 * @return The <code>RankFk</code> attribute.
1111 private static Integer
getRankFk(TaxonNameBase
<?
,?
> taxonName
, NomenclaturalCode nomenclaturalCode
) {
1112 Integer result
= null;
1114 if (nomenclaturalCode
!= null) {
1115 if (taxonName
!= null) {
1116 if (taxonName
.getRank() == null) {
1117 logger
.warn("Rank is null: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1119 result
= PesiTransformer
.rank2RankId(taxonName
.getRank(), PesiTransformer
.nomenClaturalCode2Kingdom(nomenclaturalCode
));
1121 if (result
== null) {
1122 logger
.warn("Rank could not be determined for PESI-Kingdom-Id " + PesiTransformer
.nomenClaturalCode2Kingdom(nomenclaturalCode
) + " and TaxonName " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1126 } catch (Exception e
) {
1127 e
.printStackTrace();
1133 * Returns the <code>RankCache</code> attribute.
1134 * @param taxonName The {@link TaxonNameBase TaxonName}.
1135 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
1136 * @return The <code>RankCache</code> attribute.
1139 private static String
getRankCache(TaxonNameBase
<?
,?
> taxonName
, NomenclaturalCode nomenclaturalCode
) {
1140 String result
= null;
1142 if (nomenclaturalCode
!= null) {
1143 result
= PesiTransformer
.rank2RankCache(taxonName
.getRank(), PesiTransformer
.nomenClaturalCode2Kingdom(nomenclaturalCode
));
1145 } catch (Exception e
) {
1146 e
.printStackTrace();
1152 * Returns the <code>GenusOrUninomial</code> attribute.
1153 * @param taxonName The {@link TaxonNameBase TaxonName}.
1154 * @return The <code>GenusOrUninomial</code> attribute.
1157 private static String
getGenusOrUninomial(TaxonNameBase
<?
,?
> taxonName
) {
1158 String result
= null;
1160 if (taxonName
!= null && (taxonName
.isInstanceOf(NonViralName
.class))) {
1161 NonViralName
<?
> nonViralName
= CdmBase
.deproxy(taxonName
, NonViralName
.class);
1162 result
= nonViralName
.getGenusOrUninomial();
1164 } catch (Exception e
) {
1165 e
.printStackTrace();
1171 * Returns the <code>InfraGenericEpithet</code> attribute.
1172 * @param taxonName The {@link TaxonNameBase TaxonName}.
1173 * @return The <code>InfraGenericEpithet</code> attribute.
1176 private static String
getInfraGenericEpithet(TaxonNameBase
<?
,?
> taxonName
) {
1177 String result
= null;
1179 if (taxonName
!= null && (taxonName
.isInstanceOf(NonViralName
.class))) {
1180 NonViralName
<?
> nonViralName
= CdmBase
.deproxy(taxonName
, NonViralName
.class);
1181 result
= nonViralName
.getInfraGenericEpithet();
1183 } catch (Exception e
) {
1184 e
.printStackTrace();
1190 * Returns the <code>SpecificEpithet</code> attribute.
1191 * @param taxonName The {@link TaxonNameBase TaxonName}.
1192 * @return The <code>SpecificEpithet</code> attribute.
1195 private static String
getSpecificEpithet(TaxonNameBase
<?
,?
> taxonName
) {
1196 String result
= null;
1198 if (taxonName
!= null && (taxonName
.isInstanceOf(NonViralName
.class))) {
1199 NonViralName
<?
> nonViralName
= CdmBase
.deproxy(taxonName
, NonViralName
.class);
1200 result
= nonViralName
.getSpecificEpithet();
1202 } catch (Exception e
) {
1203 e
.printStackTrace();
1209 * Returns the <code>InfraSpecificEpithet</code> attribute.
1210 * @param taxonName The {@link TaxonNameBase TaxonName}.
1211 * @return The <code>InfraSpecificEpithet</code> attribute.
1214 private static String
getInfraSpecificEpithet(TaxonNameBase
<?
,?
> taxonName
) {
1215 String result
= null;
1217 if (taxonName
!= null && (taxonName
.isInstanceOf(NonViralName
.class))) {
1218 NonViralName
<?
> nonViralName
= CdmBase
.deproxy(taxonName
, NonViralName
.class);
1219 result
= nonViralName
.getInfraSpecificEpithet();
1221 } catch (Exception e
) {
1222 e
.printStackTrace();
1228 * Returns the <code>WebSearchName</code> attribute.
1229 * @param taxonName The {@link TaxonNameBase TaxonName}.
1230 * @return The <code>WebSearchName</code> attribute.
1233 @SuppressWarnings("unused")
1234 private static String
getWebSearchName(TaxonNameBase
<?
,?
> taxonName
) {
1235 String result
= null;
1237 if (taxonName
!= null && (taxonName
.isInstanceOf(NonViralName
.class))) {
1238 NonViralName
<?
> nonViralName
= CdmBase
.deproxy(taxonName
, NonViralName
.class);
1239 result
= nonViralName
.getNameCache();
1241 } catch (Exception e
) {
1242 e
.printStackTrace();
1248 * Returns the <code>WebShowName</code> attribute.
1249 * @param taxonName The {@link TaxonNameBase TaxonName}.
1250 * @return The <code>WebShowName</code> attribute.
1253 private static String
getWebShowName(TaxonNameBase
<?
,?
> taxonName
) {
1257 List
<TaggedText
> taggedName
= taxonName
.getTaggedName();
1258 boolean openTag
= false;
1259 boolean start
= true;
1260 for (TaggedText taggedText
: taggedName
) {
1261 if (taggedText
.isName() || taggedText
.isHybridSign() ) {
1274 result
+= taggedText
.getText();
1275 } else if (taggedText
.isSeparator()) {
1278 logger
.warn("Semantics of separator outside name not yet defined: "+ taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1280 result
+= taggedText
.getText();
1281 } else if (taggedText
.isRank()) {
1283 String rankAbbrev
= taggedText
.getText();
1285 if (StringUtils
.isBlank(rankAbbrev
)) {
1286 logger
.error("Rank abbreviation is an empty string: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1294 result
+=rankAbbrev
;
1296 } else if (taggedText
.isAuthors()) {
1304 result
+= taggedText
.getText();
1305 } else if (taggedText
.isYear()) {
1312 result
+= taggedText
.getText();
1313 } else if (taggedText
.isReference()) {
1320 result
+= taggedText
.getText();
1322 if (taggedText
.getText() == null) {
1323 logger
.warn("TaggedName for " + taggedText
.getType() +" is NULL for this TaxonName: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() +")");
1325 logger
.error("TaggedText typ is unknown. Tag type: " + taggedText
.getType() + ", TaxonName: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1332 } catch (Exception e
) {
1333 e
.printStackTrace();
1340 * Returns the <code>AuthorString</code> attribute.
1341 * @param taxonName The {@link TaxonNameBase TaxonName}.
1342 * @return The <code>AuthorString</code> attribute.
1345 @SuppressWarnings("unused")
1346 private static String
getAuthorString(TaxonBase
<?
> taxon
) {
1347 String result
= null;
1349 boolean isNonViralName
= false;
1350 String authorshipCache
= null;
1351 TaxonNameBase
<?
,?
> taxonName
= taxon
.getName();
1352 if (taxonName
!= null && taxonName
.isInstanceOf(NonViralName
.class)){
1353 authorshipCache
= CdmBase
.deproxy(taxonName
, NonViralName
.class).getAuthorshipCache();
1354 isNonViralName
= true;
1356 // For a misapplied name without an authorshipCache the authorString should be set to "auct."
1357 if (isMisappliedName(taxon
) && authorshipCache
== null) {
1358 // Set authorshipCache to "auct."
1359 result
= PesiTransformer
.auctString
;
1361 result
= authorshipCache
;
1363 if (taxonName
== null){
1364 logger
.warn("TaxonName does not exist for taxon: " + taxon
.getUuid() + " (" + taxon
.getTitleCache() + ")");
1365 }else if (! isNonViralName
){
1366 logger
.warn("TaxonName is not of instance NonViralName: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1369 } catch (Exception e
) {
1370 e
.printStackTrace();
1373 if (StringUtils
.isBlank(result
)) {
1382 * Checks whether a given TaxonName is a misapplied name.
1383 * @param taxonName The {@link TaxonNameBase TaxonName}.
1384 * @return Whether the given TaxonName is a misapplied name or not.
1386 private static boolean isMisappliedName(TaxonNameBase taxonName
) {
1387 boolean result
= false;
1388 Set
<Taxon
> taxa
= taxonName
.getTaxa();
1389 if (taxa
.size() == 1){
1390 return isMisappliedName(taxa
.iterator().next());
1391 }else if (taxa
.size() > 1){
1392 logger
.warn("TaxonNameBase has " + taxa
.size() + " taxa attached. Can't define if it is a misapplied name.");
1401 * Checks whether a given Taxon is a misapplied name.
1402 * @param taxonName The {@link TaxonNameBase TaxonName}.
1403 * @return Whether the given TaxonName is a misapplied name or not.
1405 private static boolean isMisappliedName(TaxonBase
<?
> taxon
) {
1406 boolean result
= false;
1408 if (! taxon
.isInstanceOf(Taxon
.class)){
1411 Set
<TaxonRelationship
> taxonRelations
= CdmBase
.deproxy(taxon
, Taxon
.class).getRelationsFromThisTaxon();
1412 for (TaxonRelationship taxonRelationship
: taxonRelations
) {
1413 TaxonRelationshipType taxonRelationshipType
= taxonRelationship
.getType();
1414 if (taxonRelationshipType
.equals(TaxonRelationshipType
.MISAPPLIED_NAME_FOR())) {
1422 * Returns the <code>FullName</code> attribute.
1423 * @param taxonName The {@link TaxonNameBase TaxonName}.
1424 * @return The <code>FullName</code> attribute.
1427 @SuppressWarnings("unused")
1428 private static String
getFullName(TaxonNameBase
<?
,?
> taxonName
) {
1429 if (taxonName
!= null) {
1430 return taxonName
.getTitleCache();
1437 * Returns the <code>NomRefString</code> attribute.
1438 * @param taxonName The {@link TaxonNameBase TaxonName}.
1439 * @return The <code>NomRefString</code> attribute.
1442 @SuppressWarnings("unused")
1443 private static String
getNomRefString(TaxonNameBase
<?
,?
> taxonName
) {
1444 String result
= null;
1446 if (taxonName
!= null) {
1448 result
= taxonName
.getNomenclaturalMicroReference();
1449 } catch (Exception e
) {
1450 logger
.error("While getting NomRefString");
1451 e
.printStackTrace();
1454 } catch (Exception e
) {
1455 e
.printStackTrace();
1461 * Returns the <code>DisplayName</code> attribute.
1462 * @param taxonName The {@link TaxonNameBase TaxonName}.
1463 * @return The <code>DisplayName</code> attribute.
1466 @SuppressWarnings("unused")
1467 private static String
getDisplayName(TaxonNameBase
<?
,?
> taxonName
) {
1469 if (taxonName
!= null) {
1470 return taxonName
.getFullTitleCache();
1477 * Returns the <code>NameStatusFk</code> attribute.
1478 * @param taxonName The {@link TaxonNameBase TaxonName}.
1479 * @return The <code>NameStatusFk</code> attribute.
1482 @SuppressWarnings("unused")
1483 private static Integer
getNameStatusFk(TaxonNameBase
<?
,?
> taxonName
) {
1484 Integer result
= null;
1487 if (taxonName
!= null && (taxonName
.isInstanceOf(NonViralName
.class))) {
1488 NonViralName
<?
> nonViralName
= CdmBase
.deproxy(taxonName
, NonViralName
.class);
1489 Set
<NomenclaturalStatus
> states
= nonViralName
.getStatus();
1490 if (states
.size() == 1) {
1491 NomenclaturalStatus state
= states
.iterator().next();
1492 NomenclaturalStatusType statusType
= null;
1493 if (state
!= null) {
1494 statusType
= state
.getType();
1496 if (statusType
!= null) {
1497 result
= PesiTransformer
.nomStatus2nomStatusFk(statusType
);
1499 } else if (states
.size() > 1) {
1500 logger
.error("This TaxonName has more than one Nomenclatural Status: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1504 } catch (Exception e
) {
1505 e
.printStackTrace();
1511 * Returns the <code>NameStatusCache</code> attribute.
1512 * @param taxonName The {@link TaxonNameBase TaxonName}.
1513 * @return The <code>NameStatusCache</code> attribute.
1516 @SuppressWarnings("unused")
1517 private static String
getNameStatusCache(TaxonNameBase
<?
,?
> taxonName
) {
1518 String result
= null;
1521 if (taxonName
!= null && (taxonName
.isInstanceOf(NonViralName
.class))) {
1522 NonViralName
<?
> nonViralName
= CdmBase
.deproxy(taxonName
, NonViralName
.class);
1523 Set
<NomenclaturalStatus
> states
= nonViralName
.getStatus();
1524 if (states
.size() == 1) {
1525 NomenclaturalStatus state
= states
.iterator().next();
1526 if (state
!= null) {
1527 result
= PesiTransformer
.nomStatus2NomStatusCache(state
.getType());
1529 } else if (states
.size() > 1) {
1530 logger
.error("This TaxonName has more than one Nomenclatural Status: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1534 } catch (Exception e
) {
1535 e
.printStackTrace();
1541 * Returns the <code>TaxonStatusFk</code> attribute.
1542 * @param taxonName The {@link TaxonNameBase TaxonName}.
1543 * @param state The {@link PesiExportState PesiExportState}.
1544 * @return The <code>TaxonStatusFk</code> attribute.
1547 @SuppressWarnings("unused")
1548 private static Integer
getTaxonStatusFk(TaxonBase
<?
> taxon
, PesiExportState state
) {
1549 Integer result
= null;
1552 if (isMisappliedName(taxon
)) {
1553 Synonym synonym
= Synonym
.NewInstance(null, null);
1555 // This works as long as only the instance is important to differentiate between TaxonStatus.
1556 result
= PesiTransformer
.taxonBase2statusFk(synonym
); // Auct References are treated as Synonyms in Datawarehouse now.
1558 result
= PesiTransformer
.taxonBase2statusFk(taxon
);
1561 } catch (Exception e
) {
1562 e
.printStackTrace();
1568 * Returns the <code>TaxonStatusCache</code> attribute.
1569 * @param taxonName The {@link TaxonNameBase TaxonName}.
1570 * @param state The {@link PesiExportState PesiExportState}.
1571 * @return The <code>TaxonStatusCache</code> attribute.
1574 @SuppressWarnings("unused")
1575 private static String
getTaxonStatusCache(TaxonBase
<?
> taxon
, PesiExportState state
) {
1576 String result
= null;
1579 if (isMisappliedName(taxon
)) {
1580 Synonym synonym
= Synonym
.NewInstance(null, null);
1582 // This works as long as only the instance is important to differentiate between TaxonStatus.
1583 result
= PesiTransformer
.taxonBase2statusCache(synonym
); // Auct References are treated as Synonyms in Datawarehouse now.
1585 result
= PesiTransformer
.taxonBase2statusCache(taxon
);
1588 } catch (Exception e
) {
1589 e
.printStackTrace();
1595 * Returns the <code>TypeNameFk</code> attribute.
1596 * @param taxonName The {@link TaxonNameBase TaxonName}.
1597 * @param state The {@link PesiExportState PesiExportState}.
1598 * @return The <code>TypeNameFk</code> attribute.
1601 private static Integer
getTypeNameFk(TaxonNameBase
<?
,?
> taxonNameBase
, PesiExportState state
) {
1602 Integer result
= null;
1603 if (taxonNameBase
!= null) {
1604 Set
<NameTypeDesignation
> nameTypeDesignations
= taxonNameBase
.getNameTypeDesignations();
1605 if (nameTypeDesignations
.size() == 1) {
1606 NameTypeDesignation nameTypeDesignation
= nameTypeDesignations
.iterator().next();
1607 if (nameTypeDesignation
!= null) {
1608 TaxonNameBase
<?
,?
> typeName
= nameTypeDesignation
.getTypeName();
1609 if (typeName
!= null) {
1610 result
= state
.getDbId(typeName
);
1613 } else if (nameTypeDesignations
.size() > 1) {
1614 logger
.warn("This TaxonName has " + nameTypeDesignations
.size() + " NameTypeDesignations: " + taxonNameBase
.getUuid() + " (" + taxonNameBase
.getTitleCache() + ")");
1621 * Returns the <code>TypeFullnameCache</code> attribute.
1622 * @param taxonName The {@link TaxonNameBase TaxonName}.
1623 * @return The <code>TypeFullnameCache</code> attribute.
1626 @SuppressWarnings("unused")
1627 private static String
getTypeFullnameCache(TaxonNameBase
<?
,?
> taxonName
) {
1628 String result
= null;
1631 if (taxonName
!= null) {
1632 Set
<NameTypeDesignation
> nameTypeDesignations
= taxonName
.getNameTypeDesignations();
1633 if (nameTypeDesignations
.size() == 1) {
1634 NameTypeDesignation nameTypeDesignation
= nameTypeDesignations
.iterator().next();
1635 if (nameTypeDesignation
!= null) {
1636 TaxonNameBase
<?
,?
> typeName
= nameTypeDesignation
.getTypeName();
1637 if (typeName
!= null) {
1638 result
= typeName
.getTitleCache();
1641 } else if (nameTypeDesignations
.size() > 1) {
1642 logger
.warn("This TaxonName has " + nameTypeDesignations
.size() + " NameTypeDesignations: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1646 } catch (Exception e
) {
1647 e
.printStackTrace();
1653 * Returns the <code>QualityStatusFk</code> attribute.
1654 * @param taxonName The {@link TaxonNameBase TaxonName}.
1655 * @return The <code>QualityStatusFk</code> attribute.
1658 @SuppressWarnings("unused")
1659 private static Integer
getQualityStatusFk(TaxonBase
<?
> taxonName
) {
1660 // TODO: Not represented in CDM right now. Depends on import.
1661 Integer result
= null;
1666 * Returns the <code>QualityStatusCache</code> attribute.
1667 * @param taxonName The {@link TaxonNameBase TaxonName}.
1668 * @return The <code>QualityStatusCache</code> attribute.
1671 @SuppressWarnings("unused")
1672 private static String
getQualityStatusCache(TaxonBase
<?
> taxonName
) {
1673 // TODO: Not represented in CDM right now. Depends on import.
1674 String result
= null;
1679 * Returns the <code>TypeDesignationStatusFk</code> attribute.
1680 * @param taxonName The {@link TaxonNameBase TaxonName}.
1681 * @return The <code>TypeDesignationStatusFk</code> attribute.
1684 @SuppressWarnings("unused")
1685 private static Integer
getTypeDesignationStatusFk(TaxonNameBase
<?
,?
> taxonName
) {
1686 Integer result
= null;
1689 if (taxonName
!= null) {
1690 Set
<NameTypeDesignation
> typeDesignations
= taxonName
.getNameTypeDesignations();
1691 if (typeDesignations
.size() == 1) {
1692 Object obj
= typeDesignations
.iterator().next().getTypeStatus();
1693 NameTypeDesignationStatus designationStatus
= CdmBase
.deproxy(obj
, NameTypeDesignationStatus
.class);
1694 result
= PesiTransformer
.nameTypeDesignationStatus2TypeDesignationStatusId(designationStatus
);
1695 } else if (typeDesignations
.size() > 1) {
1696 logger
.error("Found a TaxonName with more than one NameTypeDesignation: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1700 } catch (Exception e
) {
1701 e
.printStackTrace();
1707 * Returns the <code>TypeDesignationStatusCache</code> attribute.
1708 * @param taxonName The {@link TaxonNameBase TaxonName}.
1709 * @return The <code>TypeDesignationStatusCache</code> attribute.
1712 @SuppressWarnings("unused")
1713 private static String
getTypeDesignationStatusCache(TaxonNameBase
<?
,?
> taxonName
) {
1714 String result
= null;
1717 if (taxonName
!= null) {
1718 Set
<NameTypeDesignation
> typeDesignations
= taxonName
.getNameTypeDesignations();
1719 if (typeDesignations
.size() == 1) {
1720 Object obj
= typeDesignations
.iterator().next().getTypeStatus();
1721 NameTypeDesignationStatus designationStatus
= CdmBase
.deproxy(obj
, NameTypeDesignationStatus
.class);
1722 result
= PesiTransformer
.nameTypeDesignationStatus2TypeDesignationStatusCache(designationStatus
);
1723 } else if (typeDesignations
.size() > 1) {
1724 logger
.error("Found a TaxonName with more than one NameTypeDesignation: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1728 } catch (Exception e
) {
1729 e
.printStackTrace();
1735 * Returns the <code>FossilStatusFk</code> attribute.
1736 * @param taxonName The {@link TaxonNameBase TaxonName}.
1737 * @return The <code>FossilStatusFk</code> attribute.
1740 @SuppressWarnings("unused")
1741 private static Integer
getFossilStatusFk(TaxonNameBase
<?
,?
> taxonNameBase
) {
1742 Integer result
= null;
1744 // if (taxonBase.isInstanceOf(Taxon.class)) {
1745 // taxon = CdmBase.deproxy(taxonBase, Taxon.class);
1746 // Set<TaxonDescription> specimenDescription = taxon.;
1747 // result = PesiTransformer.fossil2FossilStatusId(fossil);
1753 * Returns the <code>FossilStatusCache</code> attribute.
1754 * @param taxonName The {@link TaxonNameBase TaxonName}.
1755 * @return The <code>FossilStatusCache</code> attribute.
1758 @SuppressWarnings("unused")
1759 private static String
getFossilStatusCache(TaxonNameBase
<?
,?
> taxonName
) {
1761 String result
= null;
1766 // * Returns the <code>IdInSource</code> attribute.
1767 // * @param taxonName The {@link TaxonNameBase TaxonName}.
1768 // * @return The <code>IdInSource</code> attribute.
1769 // * @see MethodMapper
1771 // @SuppressWarnings("unused")
1772 // private static String getIdInSource(TaxonNameBase<?,?> taxonName) {
1773 // String result = null;
1776 // Set<IdentifiableSource> sources = getSources(taxonName);
1777 // for (IdentifiableSource source : sources) {
1778 // result = "TAX_ID: " + source.getIdInSource();
1779 // String sourceIdNameSpace = source.getIdNamespace();
1780 // if (sourceIdNameSpace != null) {
1781 // if (sourceIdNameSpace.equals("originalGenusId")) {
1782 // result = "Nominal Taxon from TAX_ID: " + source.getIdInSource();
1783 // } else if (sourceIdNameSpace.equals("InferredEpithetOf")) {
1784 // result = "Inferred epithet from TAX_ID: " + source.getIdInSource();
1785 // } else if (sourceIdNameSpace.equals("InferredGenusOf")) {
1786 // result = "Inferred genus from TAX_ID: " + source.getIdInSource();
1787 // } else if (sourceIdNameSpace.equals("PotentialCombinationOf")) {
1788 // result = "Potential combination from TAX_ID: " + source.getIdInSource();
1790 // result = "TAX_ID: " + source.getIdInSource();
1794 // } catch (Exception e) {
1795 // e.printStackTrace();
1798 // if (result == null) {
1799 // logger.error("IdInSource is NULL for this taxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() +")");
1805 // * Returns the idInSource for a given TaxonName only.
1806 // * @param taxonName The {@link TaxonNameBase TaxonName}.
1807 // * @return The idInSource.
1809 // private static String getIdInSourceOnly(TaxonBase<?> taxonName) {
1810 // String result = null;
1812 // // Get the sources first
1813 // Set<IdentifiableSource> sources = getSources(taxonName);
1815 // // Determine the idInSource
1816 // if (sources.size() == 1) {
1817 // IdentifiableSource source = sources.iterator().next();
1818 // if (source != null) {
1819 // result = source.getIdInSource();
1821 // } else if (sources.size() > 1) {
1824 // for (IdentifiableSource source : sources) {
1825 // result += source.getIdInSource();
1826 // if (count < sources.size()) {
1838 // * Returns the Sources for a given TaxonName only.
1839 // * @param taxonName The {@link TaxonNameBase TaxonName}.
1840 // * @return The Sources.
1842 // private static Set<IdentifiableSource> getSources(TaxonBase<?> taxon) {
1843 // Set<IdentifiableSource> sources = null;
1845 // // Sources from TaxonName
1846 // Set<IdentifiableSource> nameSources = taxon.getSources();
1847 // sources = nameSources;
1848 // if (nameSources.size() > 1) {
1849 // logger.warn("This TaxonName has more than one Source: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
1852 // // Sources from TaxonBase
1853 // if (sources == null || sources.isEmpty()) {
1854 // Set<Taxon> taxa = taxonName.getTaxa();
1855 // Set<Synonym> synonyms = taxonName.getSynonyms();
1856 // if (taxa.size() == 1) {
1857 // Taxon taxon = taxa.iterator().next();
1859 // if (taxon != null) {
1860 // sources = taxon.getSources();
1862 // } else if (taxa.size() > 1) {
1863 // logger.warn("This TaxonName has " + taxa.size() + " Taxa: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() +")");
1865 // if (synonyms.size() == 1) {
1866 // Synonym synonym = synonyms.iterator().next();
1868 // if (synonym != null) {
1869 // sources = synonym.getSources();
1871 // } else if (synonyms.size() > 1) {
1872 // logger.warn("This TaxonName has " + synonyms.size() + " Synonyms: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() +")");
1876 // if (sources == null || sources.isEmpty()) {
1877 // logger.error("This TaxonName has no Sources: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() +")");
1883 * Returns the <code>GUID</code> attribute.
1884 * @param taxonName The {@link TaxonNameBase TaxonName}.
1885 * @return The <code>GUID</code> attribute.
1888 private static String
getGUID(TaxonBase
<?
> taxon
) {
1889 if (taxon
.getLsid() != null ){
1890 return taxon
.getLsid().getLsid();
1892 return taxon
.getUuid().toString();
1897 * Returns the <code>DerivedFromGuid</code> attribute.
1898 * @param taxonName The {@link TaxonNameBase TaxonName}.
1899 * @return The <code>DerivedFromGuid</code> attribute.
1902 @SuppressWarnings("unused")
1903 private static String
getDerivedFromGuid(TaxonBase
<?
> taxon
) {
1904 String result
= null;
1906 // The same as GUID for now
1907 result
= getGUID(taxon
);
1908 } catch (Exception e
) {
1909 e
.printStackTrace();
1915 * Returns the <code>CacheCitation</code> attribute.
1916 * @param taxonName The {@link TaxonNameBase TaxonName}.
1917 * @return The CacheCitation.
1920 @SuppressWarnings("unused")
1921 private static String
getCacheCitation(TaxonBase
<?
> taxon
) {
1923 //TODO implement anew for taxa
1925 // String originalDb = getOriginalDB(taxon);
1926 // if (originalDb == null) {
1927 //// logger.error("OriginalDB is NULL for this TaxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
1928 // } else if (originalDb.equals("ERMS")) {
1929 // // TODO: 19.08.2010: An import of CacheCitation does not exist in the ERMS import yet or it will be imported in a different way...
1930 // // So the following code is some kind of harmless assumption.
1931 // Set<Extension> extensions = taxon.getExtensions();
1932 // for (Extension extension : extensions) {
1933 // if (extension.getType().equals(cacheCitationExtensionType)) {
1934 // result = extension.getValue();
1938 // String expertName = getExpertName(taxon);
1939 // String webShowName = getWebShowName(taxon);
1941 // // idInSource only
1942 // String idInSource = getIdInSourceOnly(taxo);
1944 // // build the cacheCitation
1945 // if (expertName != null) {
1946 // result += expertName + ". ";
1948 // // logger.error("ExpertName could not be determined for this TaxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
1950 // if (webShowName != null) {
1951 // result += webShowName + ". ";
1953 // // logger.error("WebShowName could not be determined for this TaxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
1956 // if (getOriginalDB(taxonName).equals("FaEu")) {
1957 // result += "Accessed through: Fauna Europaea at http://faunaeur.org/full_results.php?id=";
1958 // } else if (getOriginalDB(taxonName).equals("EM")) {
1959 // result += "Accessed through: Euro+Med PlantBase at http://ww2.bgbm.org/euroPlusMed/PTaxonDetail.asp?UUID=";
1962 // if (idInSource != null) {
1963 // result += idInSource;
1965 // // logger.error("IdInSource could not be determined for this TaxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
1968 // } catch (Exception e) {
1969 // e.printStackTrace();
1972 // if ("".equals(result)) {
1981 * Returns the <code>OriginalDB</code> attribute.
1982 * @param taxonName The {@link TaxonNameBase TaxonName}.
1983 * @return The <code>OriginalDB</code> attribute.
1986 private static String
getOriginalDB(TaxonBase
<?
> taxonBase
) {
1990 // Sources from TaxonName
1991 // Set<IdentifiableSource> sources = taxonName.getSources();
1992 Set
<IdentifiableSource
> sources
= taxonBase
.getSources();
1994 // IdentifiableEntity<?> taxonBase = null;
1995 // if (sources != null && sources.isEmpty()) {
1996 // // Sources from Taxa or Synonyms
1997 // Set<Taxon> taxa = taxonName.getTaxa();
1998 // if (taxa.size() == 1) {
1999 // taxonBase = taxa.iterator().next();
2000 // sources = taxonBase.getSources();
2001 // } else if (taxa.size() > 1) {
2002 // logger.warn("This TaxonName has " + taxa.size() + " Taxa: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() +")");
2004 // Set<Synonym> synonyms = taxonName.getSynonyms();
2005 // if (synonyms.size() == 1) {
2006 // taxonBase = synonyms.iterator().next();
2007 // sources = taxonBase.getSources();
2008 // } else if (synonyms.size() > 1) {
2009 // logger.warn("This TaxonName has " + synonyms.size() + " Synonyms: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() +")");
2013 if (sources
!= null && ! sources
.isEmpty()) {
2014 if (sources
.size() == 1) {
2015 IdentifiableSource source
= sources
.iterator().next();
2016 if (source
!= null) {
2017 Reference
<?
> citation
= source
.getCitation();
2018 if (citation
!= null) {
2019 result
= PesiTransformer
.databaseString2Abbreviation(citation
.getTitleCache());
2022 } else if (sources
.size() > 1) {
2024 for (IdentifiableSource source
: sources
) {
2025 Reference
<?
> citation
= source
.getCitation();
2026 if (citation
!= null) {
2030 result
+= PesiTransformer
.databaseString2Abbreviation(citation
.getTitleCache());
2039 } catch (Exception e
) {
2040 e
.printStackTrace();
2042 if ("".equals(result
)) {
2050 * Returns the <code>LastAction</code> attribute.
2051 * @param taxonName The {@link TaxonNameBase TaxonName}.
2052 * @return The <code>LastAction</code> attribute.
2055 @SuppressWarnings("unused")
2056 private static String
getLastAction(TaxonBase
<?
> taxon
) {
2057 String result
= null;
2059 Set
<Extension
> extensions
= taxon
.getExtensions();
2060 for (Extension extension
: extensions
) {
2061 if (extension
.getType().equals(lastActionExtensionType
)) {
2062 result
= extension
.getValue();
2065 } catch (Exception e
) {
2066 e
.printStackTrace();
2072 * Returns the <code>LastActionDate</code> attribute.
2073 * @param taxonName The {@link TaxonNameBase TaxonName}.
2074 * @return The <code>LastActionDate</code> attribute.
2077 @SuppressWarnings({ "unused" })
2078 private static DateTime
getLastActionDate(TaxonBase
<?
> taxon
) {
2079 DateTime result
= null;
2081 Set
<Extension
> extensions
= taxon
.getExtensions();
2082 for (Extension extension
: extensions
) {
2083 if (extension
.getType().equals(lastActionDateExtensionType
)) {
2084 String dateTime
= extension
.getValue();
2085 if (dateTime
!= null) {
2086 DateTimeFormatter formatter
= DateTimeFormat
.forPattern("yyyy-MM-dd HH:mm:ss.S");
2087 result
= formatter
.parseDateTime(dateTime
);
2091 } catch (Exception e
) {
2092 e
.printStackTrace();
2098 * Returns the <code>ExpertName</code> attribute.
2099 * @param taxonName The {@link TaxonNameBase TaxonName}.
2100 * @return The <code>ExpertName</code> attribute.
2103 @SuppressWarnings("unused")
2104 private static String
getExpertName(TaxonBase
<?
> taxonName
) {
2105 String result
= null;
2107 Set
<Extension
> extensions
= taxonName
.getExtensions();
2108 for (Extension extension
: extensions
) {
2109 if (extension
.getType().equals(expertNameExtensionType
)) {
2110 result
= extension
.getValue();
2113 } catch (Exception e
) {
2114 e
.printStackTrace();
2120 * Returns the <code>ExpertFk</code> attribute.
2121 * @param taxonName The {@link TaxonNameBase TaxonName}.
2122 * @param state The {@link PesiExportState PesiExportState}.
2123 * @return The <code>ExpertFk</code> attribute.
2126 private static Integer
getExpertFk(Reference
<?
> reference
, PesiExportState state
) {
2127 Integer result
= state
.getDbId(reference
);
2132 * Returns the <code>SpeciesExpertName</code> attribute.
2133 * @param taxonName The {@link TaxonNameBase TaxonName}.
2134 * @return The <code>SpeciesExpertName</code> attribute.
2137 @SuppressWarnings("unused")
2138 private static String
getSpeciesExpertName(TaxonBase
<?
> taxonName
) {
2139 String result
= null;
2141 Set
<Extension
> extensions
= taxonName
.getExtensions();
2142 for (Extension extension
: extensions
) {
2143 if (extension
.getType().equals(speciesExpertNameExtensionType
)) {
2144 result
= extension
.getValue();
2147 } catch (Exception e
) {
2148 e
.printStackTrace();
2154 * Returns the <code>SpeciesExpertFk</code> attribute.
2155 * @param reference The {@link Reference Reference}.
2156 * @param state The {@link PesiExportState PesiExportState}.
2157 * @return The <code>SpeciesExpertFk</code> attribute.
2160 private static Integer
getSpeciesExpertFk(Reference
<?
> reference
, PesiExportState state
) {
2161 Integer result
= state
.getDbId(reference
);
2166 // * Returns the <code>SourceFk</code> attribute.
2167 // * @param taxonName The {@link TaxonNameBase TaxonName}.
2168 // * @param state The {@link PesiExportState PesiExportState}.
2169 // * @return The <code>SourceFk</code> attribute.
2171 // @SuppressWarnings("unused")
2172 // private static Integer getSourceFk(TaxonNameBase<?,?> taxonName, PesiExportState state) {
2173 // Integer result = null;
2176 // TaxonBase<?> taxonBase = getSourceTaxonBase(taxonName);
2178 // if (taxonBase != null) {
2179 // result = state.getDbId(taxonBase.getSec());
2181 // } catch (Exception e) {
2182 // e.printStackTrace();
2189 // * Determines the TaxonBase of a TaxonName.
2190 // * @param taxonName The {@link TaxonNameBase TaxonName}.
2191 // * @return The TaxonBase.
2193 // private static TaxonBase<?> getSourceTaxonBase(TaxonNameBase<?,?> taxonName) {
2194 // TaxonBase<?> taxonBase = null;
2195 // Set<Taxon> taxa = taxonName.getTaxa();
2196 // if (taxa.size() == 1) {
2197 // taxonBase =taxa.iterator().next();
2198 // } else if (taxa.size() > 1) {
2199 // logger.warn("This TaxonName has " + taxa.size() + " Taxa: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
2202 // Set<Synonym> synonyms = taxonName.getSynonyms();
2203 // if (synonyms.size() == 1) {
2204 // taxonBase = synonyms.iterator().next();
2205 // } else if (synonyms.size() > 1) {
2206 // logger.warn("This TaxonName has " + synonyms.size() + " Synonyms: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
2208 // return taxonBase;