3 * Copyright (C) 2009 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
10 package eu
.etaxonomy
.cdm
.io
.pesi
.out
;
12 import java
.sql
.Connection
;
13 import java
.sql
.PreparedStatement
;
14 import java
.sql
.ResultSet
;
15 import java
.sql
.SQLException
;
16 import java
.util
.ArrayList
;
17 import java
.util
.HashMap
;
18 import java
.util
.List
;
20 import java
.util
.UUID
;
22 import org
.apache
.commons
.lang
.StringUtils
;
23 import org
.apache
.log4j
.Logger
;
24 import org
.joda
.time
.DateTime
;
25 import org
.joda
.time
.format
.DateTimeFormat
;
26 import org
.joda
.time
.format
.DateTimeFormatter
;
27 import org
.springframework
.stereotype
.Component
;
28 import org
.springframework
.transaction
.TransactionStatus
;
30 import eu
.etaxonomy
.cdm
.common
.CdmUtils
;
31 import eu
.etaxonomy
.cdm
.io
.common
.Source
;
32 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbExtensionMapper
;
33 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbObjectMapper
;
34 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.DbStringMapper
;
35 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.IdMapper
;
36 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.MethodMapper
;
37 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.ObjectChangeMapper
;
38 import eu
.etaxonomy
.cdm
.io
.pesi
.erms
.ErmsTransformer
;
39 import eu
.etaxonomy
.cdm
.model
.common
.Annotation
;
40 import eu
.etaxonomy
.cdm
.model
.common
.AnnotationType
;
41 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
42 import eu
.etaxonomy
.cdm
.model
.common
.Extension
;
43 import eu
.etaxonomy
.cdm
.model
.common
.ExtensionType
;
44 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableSource
;
45 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
46 import eu
.etaxonomy
.cdm
.model
.name
.NameTypeDesignation
;
47 import eu
.etaxonomy
.cdm
.model
.name
.NameTypeDesignationStatus
;
48 import eu
.etaxonomy
.cdm
.model
.name
.NomenclaturalCode
;
49 import eu
.etaxonomy
.cdm
.model
.name
.NomenclaturalStatus
;
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(DbStringMapper
.NewInstance("GenusOrUninomial", "GenusOrUninomial"));
185 mapping
.addMapper(DbStringMapper
.NewInstance("InfraGenericEpithet", "InfraGenericEpithet"));
186 mapping
.addMapper(DbStringMapper
.NewInstance("SpecificEpithet", "SpecificEpithet"));
187 mapping
.addMapper(DbStringMapper
.NewInstance("InfraSpecificEpithet", "InfraSpecificEpithet"));
188 mapping
.addMapper(DbStringMapper
.NewInstance("NameCache", "WebSearchName"));
189 mapping
.addMapper(DbStringMapper
.NewInstance("TitleCache", "FullName"));
190 mapping
.addMapper(DbStringMapper
.NewInstance("NomenclaturalMicroReference", "NomRefString"));
191 mapping
.addMapper(MethodMapper
.NewInstance("WebShowName", 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));
205 mapping
.addMapper(MethodMapper
.NewInstance("TypeDesignationStatusFk", this, TaxonNameBase
.class));
206 mapping
.addMapper(MethodMapper
.NewInstance("TypeDesignationStatusCache", this, TaxonNameBase
.class));
208 // FossilStatus (Fk, Cache)
209 extensionType
= (ExtensionType
)getTermService().find(ErmsTransformer
.uuidFossilStatus
);
210 if (extensionType
!= null) {
211 mapping
.addMapper(DbExtensionMapper
.NewInstance(extensionType
, "FossilStatusCache"));
213 mapping
.addMapper(MethodMapper
.NewInstance("FossilStatusCache", this, TaxonNameBase
.class));
215 mapping
.addMapper(MethodMapper
.NewInstance("FossilStatusFk", this, TaxonNameBase
.class)); // PesiTransformer.FossilStatusCache2FossilStatusFk?
221 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doInvoke(eu.etaxonomy.cdm.io.common.IoStateBase)
224 protected void doInvoke(PesiExportState state
) {
226 logger
.info("*** Started Making " + pluralString
+ " ...");
228 initPreparedStatements(state
);
230 // Stores whether this invoke was successful or not.
231 boolean success
= true;
233 // PESI: Clear the database table Taxon.
236 // Get specific mappings: (CDM) Taxon -> (PESI) Taxon
237 PesiExportMapping mapping
= getMapping();
239 // Initialize the db mapper
240 mapping
.initialize(state
);
242 // Find extensionTypes
243 lastActionExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.lastActionUuid
);
244 lastActionDateExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.lastActionDateUuid
);
245 expertNameExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.expertNameUuid
);
246 speciesExpertNameExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.speciesExpertNameUuid
);
247 cacheCitationExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.cacheCitationUuid
);
248 expertUserIdExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.expertUserIdUuid
);
249 speciesExpertUserIdExtensionType
= (ExtensionType
)getTermService().find(PesiTransformer
.speciesExpertUserIdUuid
);
252 success
&= doPhase01(state
, mapping
);
254 // 2nd Round: Add ParentTaxonFk, TreeIndex to each Taxon
255 success
&= doPhase02(state
);
257 //PHASE 3: Add Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk...
258 success
&= doPhase03(state
);
260 //"PHASE 4: Creating Inferred Synonyms...
261 success
&= doPhase04(state
, mapping
);
263 logger
.info("*** Finished Making " + pluralString
+ " ..." + getSuccessString(success
));
266 state
.setUnsuccessfull();
269 } catch (SQLException e
) {
271 logger
.error(e
.getMessage());
272 state
.setUnsuccessfull();
277 private void initPreparedStatements(PesiExportState state
) throws SQLException
{
278 initTreeIndexStatement(state
);
279 initRankExpertsUpdateStmt(state
);
280 initRankUpdateStatement(state
);
283 // Prepare TreeIndex-And-KingdomFk-Statement
284 private void initTreeIndexStatement(PesiExportState state
) throws SQLException
{
285 Connection connection
= state
.getConfig().getDestination().getConnection();
286 String parentTaxonFk_TreeIndex_KingdomFkSql
= "UPDATE Taxon SET ParentTaxonFk = ?, TreeIndex = ? WHERE TaxonId = ?";
287 parentTaxonFk_TreeIndex_KingdomFkStmt
= connection
.prepareStatement(parentTaxonFk_TreeIndex_KingdomFkSql
);
290 private void initRankUpdateStatement(PesiExportState state
) throws SQLException
{
291 Connection connection
= state
.getConfig().getDestination().getConnection();
292 String rankSql
= "UPDATE Taxon SET RankFk = ?, RankCache = ?, KingdomFk = ? WHERE TaxonId = ?";
293 rankUpdateStmt
= connection
.prepareStatement(rankSql
);
296 private void initRankExpertsUpdateStmt(PesiExportState state
) throws SQLException
{
297 // String sql_old = "UPDATE Taxon SET RankFk = ?, RankCache = ?, TypeNameFk = ?, KingdomFk = ?, " +
298 // "ExpertFk = ?, SpeciesExpertFk = ? WHERE TaxonId = ?";
299 //TODO handle experts GUIDs
300 Connection connection
= state
.getConfig().getDestination().getConnection();
302 String sql
= "UPDATE Taxon SET RankFk = ?, RankCache = ?, TypeNameFk = ?, KingdomFk = ? " +
303 " WHERE TaxonId = ?";
304 rankTypeExpertsUpdateStmt
= connection
.prepareStatement(sql
);
307 private boolean doPhase01(PesiExportState state
, PesiExportMapping mapping
) throws SQLException
{
310 List
<TaxonBase
> list
;
311 boolean success
= true;
312 // Get the limit for objects to save within a single transaction.
313 int limit
= state
.getConfig().getLimitSave();
316 logger
.info("PHASE 1: Export Taxa...");
318 TransactionStatus txStatus
= startTransaction(true);
319 logger
.info("Started new transaction. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
322 int partitionCount
= 0;
323 while ((list
= getNextTaxonPartition(null, limit
, partitionCount
++)).size() > 0 ) {
325 logger
.info("Fetched " + list
.size() + " " + pluralString
+ ". Exporting...");
326 for (TaxonBase
<?
> taxon
: list
) {
327 doCount(count
++, modCount
, pluralString
);
328 success
&= mapping
.invoke(taxon
);
330 TaxonNameBase
<?
,?
> taxonName
= taxon
.getName();
332 validatePhaseOne(taxon
, taxonName
);
336 // Commit transaction
337 commitTransaction(txStatus
);
338 logger
.debug("Committed transaction.");
339 logger
.info("Exported " + (count
- pastCount
) + " " + pluralString
+ ". Total: " + count
);
343 txStatus
= startTransaction(true);
344 logger
.info("Started new transaction. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
346 if (list
.size() == 0) {
347 logger
.info("No " + pluralString
+ " left to fetch.");
349 // Commit transaction
350 commitTransaction(txStatus
);
351 logger
.debug("Committed transaction.");
356 private void validatePhaseOne(TaxonBase
<?
> taxon
, TaxonNameBase
<?
, ?
> taxonName
) {
357 // Check whether some rules are violated
358 nomenclaturalCode
= PesiTransformer
.getNomenclaturalCode(taxonName
);
359 if (! taxonName
.isInstanceOf(NonViralName
.class)){
360 logger
.warn("Viral names can't be validated");
362 NonViralName
<?
> nvn
= CdmBase
.deproxy(taxonName
, NonViralName
.class);
363 String genusOrUninomial
= nvn
.getGenusOrUninomial();
364 String specificEpithet
= nvn
.getSpecificEpithet();
365 String infraSpecificEpithet
= nvn
.getInfraSpecificEpithet();
366 String infraGenericEpithet
= nvn
.getInfraGenericEpithet();
367 Integer rank
= getRankFk(taxonName
, nomenclaturalCode
);
370 logger
.error("Rank was not determined: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
373 // Check whether infraGenericEpithet is set correctly
374 // 1. Childs of an accepted taxon of rank subgenus that are accepted taxa of rank species have to have an infraGenericEpithet
375 // 2. Grandchilds of an accepted taxon of rank subgenus that are accepted taxa of rank subspecies have to have an infraGenericEpithet
377 int ancestorLevel
= 0;
378 if (taxonName
.getRank().equals(Rank
.SUBSPECIES())) {
379 // The accepted taxon two rank levels above should be of rank subgenus
382 if (taxonName
.getRank().equals(Rank
.SPECIES())) {
383 // The accepted taxon one rank level above should be of rank subgenus
386 if (ancestorLevel
> 0) {
387 if (ancestorOfSpecificRank(taxon
, ancestorLevel
, Rank
.SUBGENUS())) {
388 // The child (species or subspecies) of this parent (subgenus) has to have an infraGenericEpithet
389 if (infraGenericEpithet
== null) {
390 logger
.warn("InfraGenericEpithet does not exist even though it should for: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
391 // maybe the taxon could be named here
396 if (infraGenericEpithet
== null && rank
.intValue() == 190) {
397 logger
.warn("InfraGenericEpithet was not determined although it should exist for rank 190: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
399 if (specificEpithet
!= null && rank
.intValue() < 216) {
400 logger
.warn("SpecificEpithet was determined for rank " + rank
+ " although it should only exist for ranks higher or equal to 220: TaxonName " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
402 if (infraSpecificEpithet
!= null && rank
.intValue() < 230) {
403 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() + ")";
404 if (StringUtils
.isNotBlank(infraSpecificEpithet
)){
405 logger
.warn(message
);
407 logger
.warn(message
);
411 if (infraSpecificEpithet
!= null && specificEpithet
== null) {
412 logger
.error("An infraSpecificEpithet was determined, but a specificEpithet was not determined: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
414 if (genusOrUninomial
== null) {
415 logger
.error("GenusOrUninomial was not determined: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
419 // 2nd Round: Add ParentTaxonFk, TreeIndex to each Taxon
420 private boolean doPhase02(PesiExportState state
) {
421 boolean success
= true;
422 List
<Classification
> classificationList
= null;
423 logger
.info("PHASE 2: Add ParenTaxonFk and TreeIndex...");
425 // Specify starting ranks for tree traversing
426 rankList
.add(Rank
.KINGDOM());
427 rankList
.add(Rank
.GENUS());
429 // Specify where to stop traversing (value) when starting at a specific Rank (key)
430 rankMap
.put(Rank
.GENUS(), null); // Since NULL does not match an existing Rank, traverse all the way down to the leaves
431 rankMap
.put(Rank
.KINGDOM(), Rank
.GENUS()); // excludes rank genus
433 StringBuffer treeIndex
= new StringBuffer();
435 // Retrieve list of classifications
436 TransactionStatus txStatus
= startTransaction(true);
437 logger
.info("Started transaction. Fetching all classifications...");
438 classificationList
= getClassificationService().listClassifications(null, 0, null, null);
439 commitTransaction(txStatus
);
440 logger
.debug("Committed transaction.");
442 logger
.info("Fetched " + classificationList
.size() + " classification(s).");
444 setTreeIndexAnnotationType(getAnnotationType(uuidTreeIndex
, "TreeIndex", "", "TI"));
446 for (Classification classification
: classificationList
) {
447 for (Rank rank
: rankList
) {
449 txStatus
= startTransaction(true);
450 logger
.info("Started transaction to fetch all rootNodes specific to Rank " + rank
.getLabel() + " ...");
452 List
<TaxonNode
> rankSpecificRootNodes
= getClassificationService().loadRankSpecificRootNodes(classification
, rank
, null);
453 logger
.info("Fetched " + rankSpecificRootNodes
.size() + " RootNodes for Rank " + rank
.getLabel());
455 commitTransaction(txStatus
);
456 logger
.debug("Committed transaction.");
458 for (TaxonNode rootNode
: rankSpecificRootNodes
) {
459 txStatus
= startTransaction(false);
460 Rank endRank
= rankMap
.get(rank
);
461 if (endRank
!= null) {
462 logger
.debug("Started transaction to traverse childNodes of rootNode (" + rootNode
.getUuid() + ") till Rank " + endRank
.getLabel() + " ...");
464 logger
.debug("Started transaction to traverse childNodes of rootNode (" + rootNode
.getUuid() + ") till leaves are reached ...");
467 TaxonNode newNode
= getTaxonNodeService().load(rootNode
.getUuid());
469 TaxonNode parentNode
= newNode
.getParent();
470 if (rank
.equals(Rank
.KINGDOM())) {
471 treeIndex
= new StringBuffer();
472 treeIndex
.append("#");
474 // Get treeIndex from parentNode
475 if (parentNode
!= null) {
476 boolean annotationFound
= false;
477 Set
<Annotation
> annotations
= parentNode
.getAnnotations();
478 for (Annotation annotation
: annotations
) {
479 AnnotationType annotationType
= annotation
.getAnnotationType();
480 if (annotationType
!= null && annotationType
.equals(getTreeIndexAnnotationType())) {
481 treeIndex
= new StringBuffer(CdmUtils
.Nz(annotation
.getText()));
482 annotationFound
= true;
483 // logger.error("treeIndex: " + treeIndex);
487 if (!annotationFound
) {
488 // This should not happen because it means that the treeIndex was not set correctly as an annotation to parentNode
489 logger
.error("TreeIndex could not be read from annotation of this TaxonNode: " + parentNode
.getUuid());
490 treeIndex
= new StringBuffer();
491 treeIndex
.append("#");
494 // TreeIndex could not be determined, but it's unclear how to proceed to generate a correct treeIndex if the parentNode is NULL
495 logger
.error("ParentNode for RootNode is NULL. TreeIndex could not be determined: " + newNode
.getUuid());
496 treeIndex
= new StringBuffer(); // This just prevents growing of the treeIndex in a wrong manner
497 treeIndex
.append("#");
501 nomenclaturalCode
= PesiTransformer
.getNomenclaturalCode(newNode
.getTaxon().getName());
502 kingdomFk
= PesiTransformer
.nomenClaturalCode2Kingdom(nomenclaturalCode
);
503 traverseTree(newNode
, parentNode
, treeIndex
, rankMap
.get(rank
), state
);
505 commitTransaction(txStatus
);
506 logger
.debug("Committed transaction.");
514 //PHASE 3: Add Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk...
515 private boolean doPhase03(PesiExportState state
) {
518 boolean success
= true;
519 // Get the limit for objects to save within a single transaction.
520 int limit
= state
.getConfig().getLimitSave();
522 List
<TaxonBase
> list
;
523 logger
.info("PHASE 3: Add Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk...");
524 // Be sure to add rank information, KingdomFk, TypeNameFk, expertFk and speciesExpertFk to every taxonName
527 TransactionStatus txStatus
= startTransaction(true);
528 logger
.info("Started new transaction. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
529 int partitionCount
= 0;
530 while ((list
= getNextTaxonPartition(null, limit
, partitionCount
++)).size() > 0) {
532 logger
.info("Fetched " + list
.size() + " " + pluralString
+ ". Exporting...");
533 for (TaxonBase
<?
> taxon
: list
) {
534 TaxonNameBase
<?
,?
> taxonName
= taxon
.getName();
535 // Determine expertFk
536 Integer expertFk
= makeExpertFk(state
, taxonName
);
538 // Determine speciesExpertFk
539 Integer speciesExpertFk
= makeSpeciesExpertFk(state
, taxonName
);
541 doCount(count
++, modCount
, pluralString
);
542 Integer typeNameFk
= getTypeNameFk(taxonName
, state
);
544 //TODO why are expertFks needed? (Andreas M.)
545 // if (expertFk != null || speciesExpertFk != null) {
546 invokeRankDataAndTypeNameFkAndKingdomFk(taxonName
, nomenclaturalCode
, state
.getDbId(taxonName
),
547 typeNameFk
, kingdomFk
, expertFk
, speciesExpertFk
);
551 // Commit transaction
552 commitTransaction(txStatus
);
553 logger
.debug("Committed transaction.");
554 logger
.info("Exported " + (count
- pastCount
) + " " + pluralString
+ ". Total: " + count
);
558 txStatus
= startTransaction(true);
559 logger
.info("Started new transaction. Fetching some " + pluralString
+ " (max: " + limit
+ ") ...");
561 if (list
.size() == 0) {
562 logger
.info("No " + pluralString
+ " left to fetch.");
564 // Commit transaction
565 commitTransaction(txStatus
);
566 logger
.debug("Committed transaction.");
570 private Integer
makeSpeciesExpertFk(PesiExportState state
, TaxonNameBase
<?
, ?
> taxonName
) {
571 List
<Reference
> referenceList
;
572 Integer speciesExpertFk
= null;
573 String speciesExpertUserId
= getSpeciesExpertUserId(taxonName
);
574 if (speciesExpertUserId
!= null) {
576 // The speciesExpertUserId was stored in the field 'title' of the corresponding Reference during FaEu import
577 referenceList
= getReferenceService().listByReferenceTitle(null, speciesExpertUserId
, MatchMode
.EXACT
, null, null, null, null, null);
578 if (referenceList
.size() == 1) {
579 speciesExpertFk
= getSpeciesExpertFk(referenceList
.iterator().next(), state
);
580 } else if (referenceList
.size() > 1) {
581 logger
.error("Found more than one match using listByTitle() searching for a Reference with this speciesExpertUserId as title: " + speciesExpertUserId
);
582 } else if (referenceList
.size() == 0) {
583 logger
.error("Found no match using listByReferenceTitle() searching for a Reference with this speciesExpertUserId as title: " + speciesExpertUserId
);
586 logger
.debug("SpeciesExpertName is NULL for this TaxonName: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
588 return speciesExpertFk
;
591 private Integer
makeExpertFk(PesiExportState state
,
592 TaxonNameBase
<?
, ?
> taxonName
) {
593 List
<Reference
> referenceList
;
594 Integer expertFk
= null;
595 String expertUserId
= getExpertUserId(taxonName
);
596 if (expertUserId
!= null) {
598 // The expertUserId was stored in the field 'title' of the corresponding Reference during FaEu import
599 referenceList
= getReferenceService().listByReferenceTitle(null, expertUserId
, MatchMode
.EXACT
, null, null, null, null, null);
600 if (referenceList
.size() == 1) {
601 expertFk
= getExpertFk(referenceList
.iterator().next(), state
);
602 } else if (referenceList
.size() > 1) {
603 logger
.error("Found more than one match using listByReferenceTitle() searching for a Reference with this expertUserId as title: " + expertUserId
);
604 } else if (referenceList
.size() == 0) {
605 logger
.error("Found no match using listByReferenceTitle() searching for a Reference with this expertUserId as title: " + expertUserId
);
608 logger
.debug("ExpertName is NULL for this TaxonName: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
613 // "PHASE 4: Creating Inferred Synonyms..."
614 private boolean doPhase04(PesiExportState state
, PesiExportMapping mapping
) throws SQLException
{
617 boolean success
= true;
618 // Get the limit for objects to save within a single transaction.
619 int limit
= state
.getConfig().getLimitSave();
621 // Create inferred synonyms for accepted taxa
622 logger
.info("PHASE 4: Creating Inferred Synonyms...");
624 // Determine the count of elements in datawarehouse database table Taxon
625 Integer currentTaxonId
= determineTaxonCount(state
);
630 int pageSize
= limit
;
632 String inferredSynonymPluralString
= "Inferred Synonyms";
635 Classification classification
= null;
636 Taxon acceptedTaxon
= null;
637 TransactionStatus txStatus
= startTransaction(true);
638 logger
.info("Started new transaction. Fetching some " + parentPluralString
+ " first (max: " + limit
+ ") ...");
639 List
<TaxonBase
> taxonList
= null;
640 List
<Synonym
> inferredSynonyms
= null;
641 while ((taxonList
= getTaxonService().listTaxaByName(Taxon
.class, "*", "*", "*", "*", null, pageSize
, pageNumber
)).size() > 0) {
642 HashMap
<Integer
, TaxonNameBase
<?
,?
>> inferredSynonymsDataToBeSaved
= new HashMap
<Integer
, TaxonNameBase
<?
,?
>>();
644 logger
.info("Fetched " + taxonList
.size() + " " + parentPluralString
+ ". Exporting...");
645 for (TaxonBase
<?
> taxonBase
: taxonList
) {
647 if (taxonBase
.isInstanceOf(Taxon
.class)) { // this should always be the case since we should have fetched accepted taxon only, but you never know...
648 acceptedTaxon
= CdmBase
.deproxy(taxonBase
, Taxon
.class);
649 TaxonNameBase
<?
,?
> taxonName
= acceptedTaxon
.getName();
651 if (taxonName
.isInstanceOf(ZoologicalName
.class)) {
652 nomenclaturalCode
= PesiTransformer
.getNomenclaturalCode(taxonName
);
653 kingdomFk
= PesiTransformer
.nomenClaturalCode2Kingdom(nomenclaturalCode
);
655 Set
<TaxonNode
> taxonNodes
= acceptedTaxon
.getTaxonNodes();
656 TaxonNode singleNode
= null;
657 if (taxonNodes
.size() > 0) {
658 // Determine the classification of the current TaxonNode
659 singleNode
= taxonNodes
.iterator().next();
660 if (singleNode
!= null) {
661 classification
= singleNode
.getClassification();
663 logger
.error("A TaxonNode belonging to this accepted Taxon is NULL: " + acceptedTaxon
.getUuid() + " (" + acceptedTaxon
.getTitleCache() +")");
666 // Classification could not be determined directly from this TaxonNode
667 // The stored classification from another TaxonNode is used. It's a simple, but not a failsafe fallback solution.
668 if (classification
== null) {
669 logger
.error("Classification could not be determined directly from this TaxonNode: " + singleNode
.getUuid() + "). " +
670 "This classification stored from another TaxonNode is used: " + classification
.getTitleCache());
674 if (classification
!= null) {
675 inferredSynonyms
= getTaxonService().createAllInferredSynonyms(classification
, acceptedTaxon
);
677 // inferredSynonyms = getTaxonService().createInferredSynonyms(classification, acceptedTaxon, SynonymRelationshipType.INFERRED_GENUS_OF());
678 if (inferredSynonyms
!= null) {
679 for (Synonym synonym
: inferredSynonyms
) {
680 TaxonNameBase
<?
,?
> synonymName
= synonym
.getName();
681 if (synonymName
!= null) {
683 // Both Synonym and its TaxonName have no valid Id yet
684 synonym
.setId(currentTaxonId
++);
685 synonymName
.setId(currentTaxonId
++);
687 doCount(count
++, modCount
, inferredSynonymPluralString
);
688 success
&= mapping
.invoke(synonymName
);
690 // Add Rank Data and KingdomFk to hashmap for later saving
691 inferredSynonymsDataToBeSaved
.put(synonymName
.getId(), synonymName
);
693 logger
.error("TaxonName of this Synonym is NULL: " + synonym
.getUuid() + " (" + synonym
.getTitleCache() + ")");
698 logger
.error("Classification is NULL. Inferred Synonyms could not be created for this Taxon: " + acceptedTaxon
.getUuid() + " (" + acceptedTaxon
.getTitleCache() + ")");
701 // logger.error("TaxonName is not a ZoologicalName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
704 logger
.error("This TaxonBase is not a Taxon even though it should be: " + taxonBase
.getUuid() + " (" + taxonBase
.getTitleCache() + ")");
708 // Commit transaction
709 commitTransaction(txStatus
);
710 logger
.debug("Committed transaction.");
711 logger
.info("Exported " + (count
- pastCount
) + " " + inferredSynonymPluralString
+ ". Total: " + count
);
714 // Save Rank Data and KingdomFk for inferred synonyms
715 for (Integer taxonFk
: inferredSynonymsDataToBeSaved
.keySet()) {
716 invokeRankDataAndKingdomFk(inferredSynonymsDataToBeSaved
.get(taxonFk
), nomenclaturalCode
, taxonFk
, kingdomFk
);
720 txStatus
= startTransaction(true);
721 logger
.info("Started new transaction. Fetching some " + parentPluralString
+ " first (max: " + limit
+ ") ...");
723 // Increment pageNumber
726 if (taxonList
.size() == 0) {
727 logger
.info("No " + parentPluralString
+ " left to fetch.");
729 // Commit transaction
730 commitTransaction(txStatus
);
731 logger
.debug("Committed transaction.");
736 * Determines the current number of entries in the DataWarehouse database table <code>Taxon</code>.
737 * @param state The {@link PesiExportState PesiExportState}.
740 private Integer
determineTaxonCount(PesiExportState state
) {
741 Integer result
= null;
742 PesiExportConfigurator pesiConfig
= (PesiExportConfigurator
) state
.getConfig();
745 Source destination
= pesiConfig
.getDestination();
746 sql
= "SELECT COUNT(*) FROM Taxon";
747 destination
.setQuery(sql
);
748 ResultSet resultSet
= destination
.getResultSet();
751 result
= resultSet
.getInt(1);
752 } catch (SQLException e
) {
753 logger
.error("TaxonCount could not be determined: " + e
.getMessage());
760 * Returns the userId of the expert associated with the given TaxonName.
761 * @param taxonName A {@link TaxonNameBase TaxonName}.
762 * @return The userId.
764 private String
getExpertUserId(TaxonNameBase
<?
,?
> taxonName
) {
765 String result
= null;
767 Set
<Extension
> extensions
= taxonName
.getExtensions();
768 for (Extension extension
: extensions
) {
769 if (extension
.getType().equals(expertUserIdExtensionType
)) {
770 result
= extension
.getValue();
773 } catch (Exception e
) {
780 * Returns the userId of the speciesExpert associated with the given TaxonName.
781 * @param taxonName A {@link TaxonNameBase TaxonName}.
782 * @return The userId.
784 private String
getSpeciesExpertUserId(TaxonNameBase
<?
,?
> taxonName
) {
785 String result
= null;
787 Set
<Extension
> extensions
= taxonName
.getExtensions();
788 for (Extension extension
: extensions
) {
789 if (extension
.getType().equals(speciesExpertUserIdExtensionType
)) {
790 result
= extension
.getValue();
793 } catch (Exception e
) {
800 * Checks whether a parent at specific level has a specific Rank.
801 * @param taxonName A {@link TaxonNameBase TaxonName}.
802 * @param level The ancestor level.
803 * @param ancestorRank The ancestor rank.
804 * @return Whether a parent at a specific level has a specific Rank.
806 private boolean ancestorOfSpecificRank(TaxonBase
<?
> taxonBase
, int level
, Rank ancestorRank
) {
807 boolean result
= false;
808 TaxonNode parentNode
= null;
809 if (taxonBase
.isInstanceOf(Taxon
.class)){
810 Taxon taxon
= CdmBase
.deproxy(taxonBase
, Taxon
.class);
811 // Get ancestor Taxon via TaxonNode
812 Set
<TaxonNode
> taxonNodes
= taxon
.getTaxonNodes();
813 if (taxonNodes
.size() == 1) {
814 TaxonNode taxonNode
= taxonNodes
.iterator().next();
815 if (taxonNode
!= null) {
816 for (int i
= 0; i
< level
; i
++) {
817 if (taxonNode
!= null) {
818 taxonNode
= taxonNode
.getParent();
821 parentNode
= taxonNode
;
823 } else if (taxonNodes
.size() > 1) {
824 logger
.error("This taxon has " + taxonNodes
.size() + " taxonNodes: " + taxon
.getUuid() + " (" + taxon
.getTitleCache() + ")");
828 if (parentNode
!= null) {
829 TaxonNode node
= CdmBase
.deproxy(parentNode
, TaxonNode
.class);
830 Taxon parentTaxon
= node
.getTaxon();
831 if (parentTaxon
!= null) {
832 TaxonNameBase
<?
,?
> parentTaxonName
= parentTaxon
.getName();
833 if (parentTaxonName
!= null && parentTaxonName
.getRank().equals(ancestorRank
)) {
837 logger
.error("This TaxonNode has no Taxon: " + node
.getUuid());
844 * Returns the AnnotationType for a given UUID.
845 * @param uuid The Annotation UUID.
846 * @param label The Annotation label.
847 * @param text The Annotation text.
848 * @param labelAbbrev The Annotation label abbreviation.
849 * @return The AnnotationType.
851 protected AnnotationType
getAnnotationType(UUID uuid
, String label
, String text
, String labelAbbrev
){
852 AnnotationType annotationType
= (AnnotationType
)getTermService().find(uuid
);
853 if (annotationType
== null) {
854 annotationType
= AnnotationType
.NewInstance(label
, text
, labelAbbrev
);
855 annotationType
.setUuid(uuid
);
856 // annotationType.setVocabulary(AnnotationType.EDITORIAL().getVocabulary());
857 getTermService().save(annotationType
);
859 return annotationType
;
863 * Traverses the classification recursively and stores determined values for every Taxon.
864 * @param childNode The {@link TaxonNode TaxonNode} to process.
865 * @param parentNode The parent {@link TaxonNode TaxonNode} of the childNode.
866 * @param treeIndex The TreeIndex at the current level.
867 * @param fetchLevel Rank to stop fetching at.
868 * @param state The {@link PesiExportState PesiExportState}.
870 private void traverseTree(TaxonNode childNode
, TaxonNode parentNode
, StringBuffer treeIndex
, Rank fetchLevel
, PesiExportState state
) {
871 // Traverse all branches from this childNode until specified fetchLevel is reached.
872 StringBuffer localTreeIndex
= new StringBuffer(treeIndex
);
873 Taxon childTaxon
= childNode
.getTaxon();
874 if (childTaxon
!= null) {
875 if (isPesiTaxon(childTaxon
)){
876 TaxonNameBase
<?
,?
> childName
= childTaxon
.getName();
877 Integer taxonId
= state
.getDbId(childName
);
878 if (taxonId
!= null) {
879 Rank childRank
= childName
.getRank();
880 if (childRank
!= null) {
881 if (! childRank
.equals(fetchLevel
)) {
883 localTreeIndex
.append(taxonId
+ "#");
885 saveData(childNode
, parentNode
, localTreeIndex
, state
, taxonId
);
887 // Store treeIndex as annotation for further use
888 Annotation annotation
= Annotation
.NewInstance(localTreeIndex
.toString(), getTreeIndexAnnotationType(), Language
.DEFAULT());
889 childNode
.addAnnotation(annotation
);
891 for (TaxonNode newNode
: childNode
.getChildNodes()) {
892 if (newNode
.getTaxon() != null && isPesiTaxon(newNode
.getTaxon())){
893 traverseTree(newNode
, childNode
, localTreeIndex
, fetchLevel
, state
);
898 // logger.error("Target Rank " + fetchLevel.getLabel() + " reached");
902 logger
.error("Rank is NULL. FetchLevel can not be checked: " + childName
.getUuid() + " (" + childName
.getTitleCache() + ")");
905 logger
.error("TaxonName can not be found in State: " + childName
.getUuid() + " (" + childName
.getTitleCache() + ")");
908 if (logger
.isDebugEnabled()){
909 logger
.debug("Taxon is not a PESI taxon: " + childTaxon
.getUuid());
914 logger
.error("Taxon is NULL for TaxonNode: " + childNode
.getUuid());
919 * Stores values in database for every recursive round.
920 * @param childNode The {@link TaxonNode TaxonNode} to process.
921 * @param parentNode The parent {@link TaxonNode TaxonNode} of the childNode.
922 * @param treeIndex The TreeIndex at the current level.
923 * @param state The {@link PesiExportState PesiExportState}.
924 * @param currentTaxonFk The TaxonFk to store the values for.
926 private void saveData(TaxonNode childNode
, TaxonNode parentNode
, StringBuffer treeIndex
, PesiExportState state
, Integer currentTaxonFk
) {
927 // We are differentiating kingdoms by the nomenclatural code for now.
928 // This needs to be handled in a better way as soon as we know how to differentiate between more kingdoms.
929 Taxon childTaxon
= childNode
.getTaxon();
930 if (isPesiTaxon(childTaxon
)) {
931 TaxonBase
<?
> parentTaxon
= null;
932 if (parentNode
!= null) {
933 parentTaxon
= parentNode
.getTaxon();
937 invokeParentTaxonFkAndTreeIndex(state
.getDbId(parentTaxon
), currentTaxonFk
, treeIndex
);
943 * Inserts values into the Taxon database table.
944 * @param taxonName The {@link TaxonNameBase TaxonName}.
945 * @param state The {@link PesiExportState PesiExportState}.
946 * @param stmt The prepared statement.
947 * @return Whether save was successful or not.
949 protected boolean invokeParentTaxonFkAndTreeIndex(Integer parentTaxonFk
, Integer currentTaxonFk
, StringBuffer treeIndex
) {
951 if (parentTaxonFk
!= null) {
952 parentTaxonFk_TreeIndex_KingdomFkStmt
.setInt(1, parentTaxonFk
);
954 parentTaxonFk_TreeIndex_KingdomFkStmt
.setObject(1, null);
957 if (treeIndex
!= null) {
958 parentTaxonFk_TreeIndex_KingdomFkStmt
.setString(2, treeIndex
.toString());
960 parentTaxonFk_TreeIndex_KingdomFkStmt
.setObject(2, null);
963 if (currentTaxonFk
!= null) {
964 parentTaxonFk_TreeIndex_KingdomFkStmt
.setInt(3, currentTaxonFk
);
966 parentTaxonFk_TreeIndex_KingdomFkStmt
.setObject(3, null);
969 parentTaxonFk_TreeIndex_KingdomFkStmt
.executeUpdate();
971 } catch (SQLException e
) {
972 logger
.error("ParentTaxonFk (" + parentTaxonFk
==null?
"-":parentTaxonFk
+ ") and TreeIndex could not be inserted into database for taxon "+ (currentTaxonFk
== null?
"-" :currentTaxonFk
) + ": " + e
.getMessage());
979 * Inserts Rank data and KingdomFk into the Taxon database table.
980 * @param taxonName The {@link TaxonNameBase TaxonName}.
981 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
982 * @param taxonFk The TaxonFk to store the values for.
983 * @param kindomFk The KingdomFk.
984 * @return Whether save was successful or not.
986 private boolean invokeRankDataAndKingdomFk(TaxonNameBase
<?
,?
> taxonName
, NomenclaturalCode nomenclaturalCode
,
987 Integer taxonFk
, Integer kingdomFk
) {
989 Integer rankFk
= getRankFk(taxonName
, nomenclaturalCode
);
990 if (rankFk
!= null) {
991 rankUpdateStmt
.setInt(1, rankFk
);
993 rankUpdateStmt
.setObject(1, null);
996 String rankCache
= getRankCache(taxonName
, nomenclaturalCode
);
997 if (rankCache
!= null) {
998 rankUpdateStmt
.setString(2, rankCache
);
1000 rankUpdateStmt
.setObject(2, null);
1003 if (kingdomFk
!= null) {
1004 rankUpdateStmt
.setInt(3, kingdomFk
);
1006 rankUpdateStmt
.setObject(3, null);
1009 if (taxonFk
!= null) {
1010 rankUpdateStmt
.setInt(4, taxonFk
);
1012 rankUpdateStmt
.setObject(4, null);
1015 rankUpdateStmt
.executeUpdate();
1017 } catch (SQLException e
) {
1018 logger
.error("Data (RankFk, RankCache, KingdomFk) could not be inserted into database: " + e
.getMessage());
1019 e
.printStackTrace();
1025 * Inserts Rank data, TypeNameFk, KingdomFk, expertFk and speciesExpertFk into the Taxon database table.
1026 * @param taxonName The {@link TaxonNameBase TaxonName}.
1027 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
1028 * @param taxonFk The TaxonFk to store the values for.
1029 * @param typeNameFk The TypeNameFk.
1030 * @param kindomFk The KingdomFk.
1031 * @param expertFk The ExpertFk.
1032 * @param speciesExpertFk The SpeciesExpertFk.
1033 * @return Whether save was successful or not.
1035 private boolean invokeRankDataAndTypeNameFkAndKingdomFk(TaxonNameBase
<?
,?
> taxonName
, NomenclaturalCode nomenclaturalCode
,
1036 Integer taxonFk
, Integer typeNameFk
, Integer kingdomFk
,
1037 Integer expertFk
, Integer speciesExpertFk
) {
1039 Integer rankFk
= getRankFk(taxonName
, nomenclaturalCode
);
1040 if (rankFk
!= null) {
1041 rankTypeExpertsUpdateStmt
.setInt(1, rankFk
);
1043 rankTypeExpertsUpdateStmt
.setObject(1, null);
1046 String rankCache
= getRankCache(taxonName
, nomenclaturalCode
);
1047 if (rankCache
!= null) {
1048 rankTypeExpertsUpdateStmt
.setString(2, rankCache
);
1050 rankTypeExpertsUpdateStmt
.setObject(2, null);
1053 if (typeNameFk
!= null) {
1054 rankTypeExpertsUpdateStmt
.setInt(3, typeNameFk
);
1056 rankTypeExpertsUpdateStmt
.setObject(3, null);
1059 if (kingdomFk
!= null) {
1060 rankTypeExpertsUpdateStmt
.setInt(4, kingdomFk
);
1062 rankTypeExpertsUpdateStmt
.setObject(4, null);
1065 if (expertFk
!= null) {
1066 rankTypeExpertsUpdateStmt
.setInt(5, expertFk
);
1068 rankTypeExpertsUpdateStmt
.setObject(5, null);
1071 //TODO handle experts GUIDS
1072 // if (speciesExpertFk != null) {
1073 // rankTypeExpertsUpdateStmt.setInt(6, speciesExpertFk);
1075 // rankTypeExpertsUpdateStmt.setObject(6, null);
1078 // if (taxonFk != null) {
1079 // rankTypeExpertsUpdateStmt.setInt(7, taxonFk);
1081 // rankTypeExpertsUpdateStmt.setObject(7, null);
1084 rankTypeExpertsUpdateStmt
.executeUpdate();
1086 } catch (SQLException e
) {
1087 logger
.error("Data could not be inserted into database: " + e
.getMessage());
1088 e
.printStackTrace();
1094 * Deletes all entries of database tables related to <code>Taxon</code>.
1095 * @param state The {@link PesiExportState PesiExportState}.
1096 * @return Whether the delete operation was successful or not.
1098 protected boolean doDelete(PesiExportState state
) {
1099 PesiExportConfigurator pesiConfig
= (PesiExportConfigurator
) state
.getConfig();
1102 Source destination
= pesiConfig
.getDestination();
1105 sql
= "DELETE FROM " + dbTableName
;
1106 destination
.setQuery(sql
);
1107 destination
.update(sql
);
1112 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#isIgnore(eu.etaxonomy.cdm.io.common.IoStateBase)
1115 protected boolean isIgnore(PesiExportState state
) {
1116 return ! state
.getConfig().isDoTaxa();
1120 * Returns the <code>RankFk</code> attribute.
1121 * @param taxonName The {@link TaxonNameBase TaxonName}.
1122 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
1123 * @return The <code>RankFk</code> attribute.
1126 private static Integer
getRankFk(TaxonNameBase
<?
,?
> taxonName
, NomenclaturalCode nomenclaturalCode
) {
1127 Integer result
= null;
1129 if (nomenclaturalCode
!= null) {
1130 if (taxonName
!= null) {
1131 if (taxonName
.getRank() == null) {
1132 logger
.warn("Rank is null: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1134 result
= PesiTransformer
.rank2RankId(taxonName
.getRank(), PesiTransformer
.nomenClaturalCode2Kingdom(nomenclaturalCode
));
1136 if (result
== null) {
1137 logger
.warn("Rank could not be determined for PESI-Kingdom-Id " + PesiTransformer
.nomenClaturalCode2Kingdom(nomenclaturalCode
) + " and TaxonName " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1141 } catch (Exception e
) {
1142 e
.printStackTrace();
1148 * Returns the <code>RankCache</code> attribute.
1149 * @param taxonName The {@link TaxonNameBase TaxonName}.
1150 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
1151 * @return The <code>RankCache</code> attribute.
1154 private static String
getRankCache(TaxonNameBase
<?
,?
> taxonName
, NomenclaturalCode nomenclaturalCode
) {
1155 String result
= null;
1157 if (nomenclaturalCode
!= null) {
1158 result
= PesiTransformer
.rank2RankCache(taxonName
.getRank(), PesiTransformer
.nomenClaturalCode2Kingdom(nomenclaturalCode
));
1160 } catch (Exception e
) {
1161 e
.printStackTrace();
1168 * Returns the <code>WebShowName</code> attribute.
1169 * @param taxonName The {@link TaxonNameBase TaxonName}.
1170 * @return The <code>WebShowName</code> attribute.
1173 private static String
getWebShowName(TaxonNameBase
<?
,?
> taxonName
) {
1177 List
<TaggedText
> taggedName
= taxonName
.getTaggedName();
1178 boolean openTag
= false;
1179 boolean start
= true;
1180 for (TaggedText taggedText
: taggedName
) {
1181 if (taggedText
.isName() || taggedText
.isHybridSign() ) {
1194 result
+= taggedText
.getText();
1195 } else if (taggedText
.isSeparator()) {
1198 logger
.warn("Semantics of separator outside name not yet defined: "+ taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1200 result
+= taggedText
.getText();
1201 } else if (taggedText
.isRank()) {
1203 String rankAbbrev
= taggedText
.getText();
1205 if (StringUtils
.isBlank(rankAbbrev
)) {
1206 logger
.error("Rank abbreviation is an empty string: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1214 result
+=rankAbbrev
;
1216 } else if (taggedText
.isAuthors()) {
1224 result
+= taggedText
.getText();
1225 } else if (taggedText
.isYear()) {
1232 result
+= taggedText
.getText();
1233 } else if (taggedText
.isReference()) {
1240 result
+= taggedText
.getText();
1242 if (taggedText
.getText() == null) {
1243 logger
.warn("TaggedName for " + taggedText
.getType() +" is NULL for this TaxonName: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() +")");
1245 logger
.error("TaggedText typ is unknown. Tag type: " + taggedText
.getType() + ", TaxonName: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1252 } catch (Exception e
) {
1253 e
.printStackTrace();
1260 * Returns the <code>AuthorString</code> attribute.
1261 * @param taxonName The {@link TaxonNameBase TaxonName}.
1262 * @return The <code>AuthorString</code> attribute.
1265 @SuppressWarnings("unused")
1266 private static String
getAuthorString(TaxonBase
<?
> taxon
) {
1267 String result
= null;
1269 boolean isNonViralName
= false;
1270 String authorshipCache
= null;
1271 TaxonNameBase
<?
,?
> taxonName
= taxon
.getName();
1272 if (taxonName
!= null && taxonName
.isInstanceOf(NonViralName
.class)){
1273 authorshipCache
= CdmBase
.deproxy(taxonName
, NonViralName
.class).getAuthorshipCache();
1274 isNonViralName
= true;
1276 // For a misapplied name without an authorshipCache the authorString should be set to "auct."
1277 if (isMisappliedName(taxon
) && authorshipCache
== null) {
1278 // Set authorshipCache to "auct."
1279 result
= PesiTransformer
.auctString
;
1281 result
= authorshipCache
;
1283 if (taxonName
== null){
1284 logger
.warn("TaxonName does not exist for taxon: " + taxon
.getUuid() + " (" + taxon
.getTitleCache() + ")");
1285 }else if (! isNonViralName
){
1286 logger
.warn("TaxonName is not of instance NonViralName: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1289 } catch (Exception e
) {
1290 e
.printStackTrace();
1293 if (StringUtils
.isBlank(result
)) {
1302 * Checks whether a given TaxonName is a misapplied name.
1303 * @param taxonName The {@link TaxonNameBase TaxonName}.
1304 * @return Whether the given TaxonName is a misapplied name or not.
1306 private static boolean isMisappliedName(TaxonNameBase taxonName
) {
1307 boolean result
= false;
1308 Set
<Taxon
> taxa
= taxonName
.getTaxa();
1309 if (taxa
.size() == 1){
1310 return isMisappliedName(taxa
.iterator().next());
1311 }else if (taxa
.size() > 1){
1312 logger
.warn("TaxonNameBase has " + taxa
.size() + " taxa attached. Can't define if it is a misapplied name.");
1321 * Checks whether a given Taxon is a misapplied name.
1322 * @param taxonName The {@link TaxonNameBase TaxonName}.
1323 * @return Whether the given TaxonName is a misapplied name or not.
1325 private static boolean isMisappliedName(TaxonBase
<?
> taxon
) {
1326 boolean result
= false;
1328 if (! taxon
.isInstanceOf(Taxon
.class)){
1331 Set
<TaxonRelationship
> taxonRelations
= CdmBase
.deproxy(taxon
, Taxon
.class).getRelationsFromThisTaxon();
1332 for (TaxonRelationship taxonRelationship
: taxonRelations
) {
1333 TaxonRelationshipType taxonRelationshipType
= taxonRelationship
.getType();
1334 if (taxonRelationshipType
.equals(TaxonRelationshipType
.MISAPPLIED_NAME_FOR())) {
1342 * Returns the <code>FullName</code> attribute.
1343 * @param taxonName The {@link TaxonNameBase TaxonName}.
1344 * @return The <code>FullName</code> attribute.
1347 @SuppressWarnings("unused")
1348 private static String
getFullName(TaxonNameBase
<?
,?
> taxonName
) {
1349 if (taxonName
!= null) {
1350 return taxonName
.getTitleCache();
1357 * Returns the <code>DisplayName</code> attribute.
1358 * @param taxonName The {@link TaxonNameBase TaxonName}.
1359 * @return The <code>DisplayName</code> attribute.
1362 @SuppressWarnings("unused")
1363 private static String
getDisplayName(TaxonNameBase
<?
,?
> taxonName
) {
1365 if (taxonName
!= null) {
1366 return taxonName
.getFullTitleCache();
1373 * Returns the <code>NameStatusFk</code> attribute.
1374 * @param taxonName The {@link TaxonNameBase TaxonName}.
1375 * @return The <code>NameStatusFk</code> attribute.
1378 @SuppressWarnings("unused")
1379 private static Integer
getNameStatusFk(TaxonNameBase
<?
,?
> taxonName
) {
1380 Integer result
= null;
1382 NomenclaturalStatus state
= getNameStatus(taxonName
);
1383 if (state
!= null) {
1384 result
= PesiTransformer
.nomStatus2nomStatusFk(state
.getType());
1390 * Returns the <code>NameStatusCache</code> attribute.
1391 * @param taxonName The {@link TaxonNameBase TaxonName}.
1392 * @return The <code>NameStatusCache</code> attribute.
1395 @SuppressWarnings("unused")
1396 private static String
getNameStatusCache(TaxonNameBase
<?
,?
> taxonName
) {
1397 String result
= null;
1398 NomenclaturalStatus state
= getNameStatus(taxonName
);
1399 if (state
!= null) {
1400 result
= PesiTransformer
.nomStatus2NomStatusCache(state
.getType());
1406 private static NomenclaturalStatus
getNameStatus(TaxonNameBase
<?
,?
> taxonName
) {
1409 if (taxonName
!= null && (taxonName
.isInstanceOf(NonViralName
.class))) {
1410 NonViralName
<?
> nonViralName
= CdmBase
.deproxy(taxonName
, NonViralName
.class);
1411 Set
<NomenclaturalStatus
> states
= nonViralName
.getStatus();
1412 if (states
.size() == 1) {
1413 NomenclaturalStatus state
= states
.iterator().next();
1415 } else if (states
.size() > 1) {
1416 logger
.error("This TaxonName has more than one Nomenclatural Status: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1420 } catch (Exception e
) {
1421 e
.printStackTrace();
1426 * Returns the <code>TaxonStatusFk</code> attribute.
1427 * @param taxonName The {@link TaxonNameBase TaxonName}.
1428 * @param state The {@link PesiExportState PesiExportState}.
1429 * @return The <code>TaxonStatusFk</code> attribute.
1432 @SuppressWarnings("unused")
1433 private static Integer
getTaxonStatusFk(TaxonBase
<?
> taxon
, PesiExportState state
) {
1434 Integer result
= null;
1437 if (isMisappliedName(taxon
)) {
1438 Synonym synonym
= Synonym
.NewInstance(null, null);
1440 // This works as long as only the instance is important to differentiate between TaxonStatus.
1441 result
= PesiTransformer
.taxonBase2statusFk(synonym
); // Auct References are treated as Synonyms in Datawarehouse now.
1443 result
= PesiTransformer
.taxonBase2statusFk(taxon
);
1446 } catch (Exception e
) {
1447 e
.printStackTrace();
1453 * Returns the <code>TaxonStatusCache</code> attribute.
1454 * @param taxonName The {@link TaxonNameBase TaxonName}.
1455 * @param state The {@link PesiExportState PesiExportState}.
1456 * @return The <code>TaxonStatusCache</code> attribute.
1459 @SuppressWarnings("unused")
1460 private static String
getTaxonStatusCache(TaxonBase
<?
> taxon
, PesiExportState state
) {
1461 String result
= null;
1464 if (isMisappliedName(taxon
)) {
1465 Synonym synonym
= Synonym
.NewInstance(null, null);
1467 // This works as long as only the instance is important to differentiate between TaxonStatus.
1468 result
= PesiTransformer
.taxonBase2statusCache(synonym
); // Auct References are treated as Synonyms in Datawarehouse now.
1470 result
= PesiTransformer
.taxonBase2statusCache(taxon
);
1473 } catch (Exception e
) {
1474 e
.printStackTrace();
1480 * Returns the <code>TypeNameFk</code> attribute.
1481 * @param taxonName The {@link TaxonNameBase TaxonName}.
1482 * @param state The {@link PesiExportState PesiExportState}.
1483 * @return The <code>TypeNameFk</code> attribute.
1486 private static Integer
getTypeNameFk(TaxonNameBase
<?
,?
> taxonNameBase
, PesiExportState state
) {
1487 Integer result
= null;
1488 if (taxonNameBase
!= null) {
1489 Set
<NameTypeDesignation
> nameTypeDesignations
= taxonNameBase
.getNameTypeDesignations();
1490 if (nameTypeDesignations
.size() == 1) {
1491 NameTypeDesignation nameTypeDesignation
= nameTypeDesignations
.iterator().next();
1492 if (nameTypeDesignation
!= null) {
1493 TaxonNameBase
<?
,?
> typeName
= nameTypeDesignation
.getTypeName();
1494 if (typeName
!= null) {
1495 result
= state
.getDbId(typeName
);
1498 } else if (nameTypeDesignations
.size() > 1) {
1499 logger
.warn("This TaxonName has " + nameTypeDesignations
.size() + " NameTypeDesignations: " + taxonNameBase
.getUuid() + " (" + taxonNameBase
.getTitleCache() + ")");
1506 * Returns the <code>TypeFullnameCache</code> attribute.
1507 * @param taxonName The {@link TaxonNameBase TaxonName}.
1508 * @return The <code>TypeFullnameCache</code> attribute.
1511 @SuppressWarnings("unused")
1512 private static String
getTypeFullnameCache(TaxonNameBase
<?
,?
> taxonName
) {
1513 String result
= null;
1516 if (taxonName
!= null) {
1517 Set
<NameTypeDesignation
> nameTypeDesignations
= taxonName
.getNameTypeDesignations();
1518 if (nameTypeDesignations
.size() == 1) {
1519 NameTypeDesignation nameTypeDesignation
= nameTypeDesignations
.iterator().next();
1520 if (nameTypeDesignation
!= null) {
1521 TaxonNameBase
<?
,?
> typeName
= nameTypeDesignation
.getTypeName();
1522 if (typeName
!= null) {
1523 result
= typeName
.getTitleCache();
1526 } else if (nameTypeDesignations
.size() > 1) {
1527 logger
.warn("This TaxonName has " + nameTypeDesignations
.size() + " NameTypeDesignations: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1531 } catch (Exception e
) {
1532 e
.printStackTrace();
1538 * Returns the <code>QualityStatusFk</code> attribute.
1539 * @param taxonName The {@link TaxonNameBase TaxonName}.
1540 * @return The <code>QualityStatusFk</code> attribute.
1543 @SuppressWarnings("unused")
1544 private static Integer
getQualityStatusFk(TaxonBase
<?
> taxonName
) {
1545 // TODO: Not represented in CDM right now. Depends on import.
1546 Integer result
= null;
1551 * Returns the <code>QualityStatusCache</code> attribute.
1552 * @param taxonName The {@link TaxonNameBase TaxonName}.
1553 * @return The <code>QualityStatusCache</code> attribute.
1556 @SuppressWarnings("unused")
1557 private static String
getQualityStatusCache(TaxonBase
<?
> taxonName
) {
1558 // TODO: Not represented in CDM right now. Depends on import.
1559 String result
= null;
1564 * Returns the <code>TypeDesignationStatusFk</code> attribute.
1565 * @param taxonName The {@link TaxonNameBase TaxonName}.
1566 * @return The <code>TypeDesignationStatusFk</code> attribute.
1569 @SuppressWarnings("unused")
1570 private static Integer
getTypeDesignationStatusFk(TaxonNameBase
<?
,?
> taxonName
) {
1571 Integer result
= null;
1574 if (taxonName
!= null) {
1575 Set
<NameTypeDesignation
> typeDesignations
= taxonName
.getNameTypeDesignations();
1576 if (typeDesignations
.size() == 1) {
1577 Object obj
= typeDesignations
.iterator().next().getTypeStatus();
1578 NameTypeDesignationStatus designationStatus
= CdmBase
.deproxy(obj
, NameTypeDesignationStatus
.class);
1579 result
= PesiTransformer
.nameTypeDesignationStatus2TypeDesignationStatusId(designationStatus
);
1580 } else if (typeDesignations
.size() > 1) {
1581 logger
.error("Found a TaxonName with more than one NameTypeDesignation: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1585 } catch (Exception e
) {
1586 e
.printStackTrace();
1592 * Returns the <code>TypeDesignationStatusCache</code> attribute.
1593 * @param taxonName The {@link TaxonNameBase TaxonName}.
1594 * @return The <code>TypeDesignationStatusCache</code> attribute.
1597 @SuppressWarnings("unused")
1598 private static String
getTypeDesignationStatusCache(TaxonNameBase
<?
,?
> taxonName
) {
1599 String result
= null;
1602 if (taxonName
!= null) {
1603 Set
<NameTypeDesignation
> typeDesignations
= taxonName
.getNameTypeDesignations();
1604 if (typeDesignations
.size() == 1) {
1605 Object obj
= typeDesignations
.iterator().next().getTypeStatus();
1606 NameTypeDesignationStatus designationStatus
= CdmBase
.deproxy(obj
, NameTypeDesignationStatus
.class);
1607 result
= PesiTransformer
.nameTypeDesignationStatus2TypeDesignationStatusCache(designationStatus
);
1608 } else if (typeDesignations
.size() > 1) {
1609 logger
.error("Found a TaxonName with more than one NameTypeDesignation: " + taxonName
.getUuid() + " (" + taxonName
.getTitleCache() + ")");
1613 } catch (Exception e
) {
1614 e
.printStackTrace();
1620 * Returns the <code>FossilStatusFk</code> attribute.
1621 * @param taxonName The {@link TaxonNameBase TaxonName}.
1622 * @return The <code>FossilStatusFk</code> attribute.
1625 @SuppressWarnings("unused")
1626 private static Integer
getFossilStatusFk(TaxonNameBase
<?
,?
> taxonNameBase
) {
1627 Integer result
= null;
1629 // if (taxonBase.isInstanceOf(Taxon.class)) {
1630 // taxon = CdmBase.deproxy(taxonBase, Taxon.class);
1631 // Set<TaxonDescription> specimenDescription = taxon.;
1632 // result = PesiTransformer.fossil2FossilStatusId(fossil);
1638 * Returns the <code>FossilStatusCache</code> attribute.
1639 * @param taxonName The {@link TaxonNameBase TaxonName}.
1640 * @return The <code>FossilStatusCache</code> attribute.
1643 @SuppressWarnings("unused")
1644 private static String
getFossilStatusCache(TaxonNameBase
<?
,?
> taxonName
) {
1646 String result
= null;
1651 // * Returns the <code>IdInSource</code> attribute.
1652 // * @param taxonName The {@link TaxonNameBase TaxonName}.
1653 // * @return The <code>IdInSource</code> attribute.
1654 // * @see MethodMapper
1656 // @SuppressWarnings("unused")
1657 // private static String getIdInSource(TaxonNameBase<?,?> taxonName) {
1658 // String result = null;
1661 // Set<IdentifiableSource> sources = getSources(taxonName);
1662 // for (IdentifiableSource source : sources) {
1663 // result = "TAX_ID: " + source.getIdInSource();
1664 // String sourceIdNameSpace = source.getIdNamespace();
1665 // if (sourceIdNameSpace != null) {
1666 // if (sourceIdNameSpace.equals("originalGenusId")) {
1667 // result = "Nominal Taxon from TAX_ID: " + source.getIdInSource();
1668 // } else if (sourceIdNameSpace.equals("InferredEpithetOf")) {
1669 // result = "Inferred epithet from TAX_ID: " + source.getIdInSource();
1670 // } else if (sourceIdNameSpace.equals("InferredGenusOf")) {
1671 // result = "Inferred genus from TAX_ID: " + source.getIdInSource();
1672 // } else if (sourceIdNameSpace.equals("PotentialCombinationOf")) {
1673 // result = "Potential combination from TAX_ID: " + source.getIdInSource();
1675 // result = "TAX_ID: " + source.getIdInSource();
1679 // } catch (Exception e) {
1680 // e.printStackTrace();
1683 // if (result == null) {
1684 // logger.error("IdInSource is NULL for this taxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() +")");
1690 // * Returns the idInSource for a given TaxonName only.
1691 // * @param taxonName The {@link TaxonNameBase TaxonName}.
1692 // * @return The idInSource.
1694 // private static String getIdInSourceOnly(TaxonBase<?> taxonName) {
1695 // String result = null;
1697 // // Get the sources first
1698 // Set<IdentifiableSource> sources = getSources(taxonName);
1700 // // Determine the idInSource
1701 // if (sources.size() == 1) {
1702 // IdentifiableSource source = sources.iterator().next();
1703 // if (source != null) {
1704 // result = source.getIdInSource();
1706 // } else if (sources.size() > 1) {
1709 // for (IdentifiableSource source : sources) {
1710 // result += source.getIdInSource();
1711 // if (count < sources.size()) {
1723 // * Returns the Sources for a given TaxonName only.
1724 // * @param taxonName The {@link TaxonNameBase TaxonName}.
1725 // * @return The Sources.
1727 // private static Set<IdentifiableSource> getSources(TaxonBase<?> taxon) {
1728 // Set<IdentifiableSource> sources = null;
1730 // // Sources from TaxonName
1731 // Set<IdentifiableSource> nameSources = taxon.getSources();
1732 // sources = nameSources;
1733 // if (nameSources.size() > 1) {
1734 // logger.warn("This TaxonName has more than one Source: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
1737 // // Sources from TaxonBase
1738 // if (sources == null || sources.isEmpty()) {
1739 // Set<Taxon> taxa = taxonName.getTaxa();
1740 // Set<Synonym> synonyms = taxonName.getSynonyms();
1741 // if (taxa.size() == 1) {
1742 // Taxon taxon = taxa.iterator().next();
1744 // if (taxon != null) {
1745 // sources = taxon.getSources();
1747 // } else if (taxa.size() > 1) {
1748 // logger.warn("This TaxonName has " + taxa.size() + " Taxa: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() +")");
1750 // if (synonyms.size() == 1) {
1751 // Synonym synonym = synonyms.iterator().next();
1753 // if (synonym != null) {
1754 // sources = synonym.getSources();
1756 // } else if (synonyms.size() > 1) {
1757 // logger.warn("This TaxonName has " + synonyms.size() + " Synonyms: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() +")");
1761 // if (sources == null || sources.isEmpty()) {
1762 // logger.error("This TaxonName has no Sources: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() +")");
1768 * Returns the <code>GUID</code> attribute.
1769 * @param taxonName The {@link TaxonNameBase TaxonName}.
1770 * @return The <code>GUID</code> attribute.
1773 private static String
getGUID(TaxonBase
<?
> taxon
) {
1774 if (taxon
.getLsid() != null ){
1775 return taxon
.getLsid().getLsid();
1777 return taxon
.getUuid().toString();
1782 * Returns the <code>DerivedFromGuid</code> attribute.
1783 * @param taxonName The {@link TaxonNameBase TaxonName}.
1784 * @return The <code>DerivedFromGuid</code> attribute.
1787 @SuppressWarnings("unused")
1788 private static String
getDerivedFromGuid(TaxonBase
<?
> taxon
) {
1789 String result
= null;
1791 // The same as GUID for now
1792 result
= getGUID(taxon
);
1793 } catch (Exception e
) {
1794 e
.printStackTrace();
1800 * Returns the <code>CacheCitation</code> attribute.
1801 * @param taxonName The {@link TaxonNameBase TaxonName}.
1802 * @return The CacheCitation.
1805 @SuppressWarnings("unused")
1806 private static String
getCacheCitation(TaxonBase
<?
> taxon
) {
1808 //TODO implement anew for taxa
1810 // String originalDb = getOriginalDB(taxon);
1811 // if (originalDb == null) {
1812 //// logger.error("OriginalDB is NULL for this TaxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
1813 // } else if (originalDb.equals("ERMS")) {
1814 // // 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...
1815 // // So the following code is some kind of harmless assumption.
1816 // Set<Extension> extensions = taxon.getExtensions();
1817 // for (Extension extension : extensions) {
1818 // if (extension.getType().equals(cacheCitationExtensionType)) {
1819 // result = extension.getValue();
1823 // String expertName = getExpertName(taxon);
1824 // String webShowName = getWebShowName(taxon);
1826 // // idInSource only
1827 // String idInSource = getIdInSourceOnly(taxo);
1829 // // build the cacheCitation
1830 // if (expertName != null) {
1831 // result += expertName + ". ";
1833 // // logger.error("ExpertName could not be determined for this TaxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
1835 // if (webShowName != null) {
1836 // result += webShowName + ". ";
1838 // // logger.error("WebShowName could not be determined for this TaxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
1841 // if (getOriginalDB(taxonName).equals("FaEu")) {
1842 // result += "Accessed through: Fauna Europaea at http://faunaeur.org/full_results.php?id=";
1843 // } else if (getOriginalDB(taxonName).equals("EM")) {
1844 // result += "Accessed through: Euro+Med PlantBase at http://ww2.bgbm.org/euroPlusMed/PTaxonDetail.asp?UUID=";
1847 // if (idInSource != null) {
1848 // result += idInSource;
1850 // // logger.error("IdInSource could not be determined for this TaxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
1853 // } catch (Exception e) {
1854 // e.printStackTrace();
1857 // if ("".equals(result)) {
1866 * Returns the <code>OriginalDB</code> attribute.
1867 * @param taxonName The {@link TaxonNameBase TaxonName}.
1868 * @return The <code>OriginalDB</code> attribute.
1871 private static String
getOriginalDB(TaxonBase
<?
> taxonBase
) {
1875 // Sources from TaxonName
1876 // Set<IdentifiableSource> sources = taxonName.getSources();
1877 Set
<IdentifiableSource
> sources
= taxonBase
.getSources();
1879 // IdentifiableEntity<?> taxonBase = null;
1880 // if (sources != null && sources.isEmpty()) {
1881 // // Sources from Taxa or Synonyms
1882 // Set<Taxon> taxa = taxonName.getTaxa();
1883 // if (taxa.size() == 1) {
1884 // taxonBase = taxa.iterator().next();
1885 // sources = taxonBase.getSources();
1886 // } else if (taxa.size() > 1) {
1887 // logger.warn("This TaxonName has " + taxa.size() + " Taxa: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() +")");
1889 // Set<Synonym> synonyms = taxonName.getSynonyms();
1890 // if (synonyms.size() == 1) {
1891 // taxonBase = synonyms.iterator().next();
1892 // sources = taxonBase.getSources();
1893 // } else if (synonyms.size() > 1) {
1894 // logger.warn("This TaxonName has " + synonyms.size() + " Synonyms: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() +")");
1898 if (sources
!= null && ! sources
.isEmpty()) {
1899 if (sources
.size() == 1) {
1900 IdentifiableSource source
= sources
.iterator().next();
1901 if (source
!= null) {
1902 Reference
<?
> citation
= source
.getCitation();
1903 if (citation
!= null) {
1904 result
= PesiTransformer
.databaseString2Abbreviation(citation
.getTitleCache());
1907 } else if (sources
.size() > 1) {
1909 for (IdentifiableSource source
: sources
) {
1910 Reference
<?
> citation
= source
.getCitation();
1911 if (citation
!= null) {
1915 result
+= PesiTransformer
.databaseString2Abbreviation(citation
.getTitleCache());
1924 } catch (Exception e
) {
1925 e
.printStackTrace();
1927 if ("".equals(result
)) {
1935 * Returns the <code>LastAction</code> attribute.
1936 * @param taxonName The {@link TaxonNameBase TaxonName}.
1937 * @return The <code>LastAction</code> attribute.
1940 @SuppressWarnings("unused")
1941 private static String
getLastAction(TaxonBase
<?
> taxon
) {
1942 String result
= null;
1944 Set
<Extension
> extensions
= taxon
.getExtensions();
1945 for (Extension extension
: extensions
) {
1946 if (extension
.getType().equals(lastActionExtensionType
)) {
1947 result
= extension
.getValue();
1950 } catch (Exception e
) {
1951 e
.printStackTrace();
1957 * Returns the <code>LastActionDate</code> attribute.
1958 * @param taxonName The {@link TaxonNameBase TaxonName}.
1959 * @return The <code>LastActionDate</code> attribute.
1962 @SuppressWarnings({ "unused" })
1963 private static DateTime
getLastActionDate(TaxonBase
<?
> taxon
) {
1964 DateTime result
= null;
1966 Set
<Extension
> extensions
= taxon
.getExtensions();
1967 for (Extension extension
: extensions
) {
1968 if (extension
.getType().equals(lastActionDateExtensionType
)) {
1969 String dateTime
= extension
.getValue();
1970 if (dateTime
!= null) {
1971 DateTimeFormatter formatter
= DateTimeFormat
.forPattern("yyyy-MM-dd HH:mm:ss.S");
1972 result
= formatter
.parseDateTime(dateTime
);
1976 } catch (Exception e
) {
1977 e
.printStackTrace();
1983 * Returns the <code>ExpertName</code> attribute.
1984 * @param taxonName The {@link TaxonNameBase TaxonName}.
1985 * @return The <code>ExpertName</code> attribute.
1988 @SuppressWarnings("unused")
1989 private static String
getExpertName(TaxonBase
<?
> taxonName
) {
1990 String result
= null;
1992 Set
<Extension
> extensions
= taxonName
.getExtensions();
1993 for (Extension extension
: extensions
) {
1994 if (extension
.getType().equals(expertNameExtensionType
)) {
1995 result
= extension
.getValue();
1998 } catch (Exception e
) {
1999 e
.printStackTrace();
2005 * Returns the <code>ExpertFk</code> attribute.
2006 * @param taxonName The {@link TaxonNameBase TaxonName}.
2007 * @param state The {@link PesiExportState PesiExportState}.
2008 * @return The <code>ExpertFk</code> attribute.
2011 private static Integer
getExpertFk(Reference
<?
> reference
, PesiExportState state
) {
2012 Integer result
= state
.getDbId(reference
);
2017 * Returns the <code>SpeciesExpertName</code> attribute.
2018 * @param taxonName The {@link TaxonNameBase TaxonName}.
2019 * @return The <code>SpeciesExpertName</code> attribute.
2022 @SuppressWarnings("unused")
2023 private static String
getSpeciesExpertName(TaxonBase
<?
> taxonName
) {
2024 String result
= null;
2026 Set
<Extension
> extensions
= taxonName
.getExtensions();
2027 for (Extension extension
: extensions
) {
2028 if (extension
.getType().equals(speciesExpertNameExtensionType
)) {
2029 result
= extension
.getValue();
2032 } catch (Exception e
) {
2033 e
.printStackTrace();
2039 * Returns the <code>SpeciesExpertFk</code> attribute.
2040 * @param reference The {@link Reference Reference}.
2041 * @param state The {@link PesiExportState PesiExportState}.
2042 * @return The <code>SpeciesExpertFk</code> attribute.
2045 private static Integer
getSpeciesExpertFk(Reference
<?
> reference
, PesiExportState state
) {
2046 Integer result
= state
.getDbId(reference
);
2051 // * Returns the <code>SourceFk</code> attribute.
2052 // * @param taxonName The {@link TaxonNameBase TaxonName}.
2053 // * @param state The {@link PesiExportState PesiExportState}.
2054 // * @return The <code>SourceFk</code> attribute.
2056 // @SuppressWarnings("unused")
2057 // private static Integer getSourceFk(TaxonNameBase<?,?> taxonName, PesiExportState state) {
2058 // Integer result = null;
2061 // TaxonBase<?> taxonBase = getSourceTaxonBase(taxonName);
2063 // if (taxonBase != null) {
2064 // result = state.getDbId(taxonBase.getSec());
2066 // } catch (Exception e) {
2067 // e.printStackTrace();
2074 // * Determines the TaxonBase of a TaxonName.
2075 // * @param taxonName The {@link TaxonNameBase TaxonName}.
2076 // * @return The TaxonBase.
2078 // private static TaxonBase<?> getSourceTaxonBase(TaxonNameBase<?,?> taxonName) {
2079 // TaxonBase<?> taxonBase = null;
2080 // Set<Taxon> taxa = taxonName.getTaxa();
2081 // if (taxa.size() == 1) {
2082 // taxonBase =taxa.iterator().next();
2083 // } else if (taxa.size() > 1) {
2084 // logger.warn("This TaxonName has " + taxa.size() + " Taxa: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
2087 // Set<Synonym> synonyms = taxonName.getSynonyms();
2088 // if (synonyms.size() == 1) {
2089 // taxonBase = synonyms.iterator().next();
2090 // } else if (synonyms.size() > 1) {
2091 // logger.warn("This TaxonName has " + synonyms.size() + " Synonyms: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
2093 // return taxonBase;