-// $Id$\r
-/**\r
-* Copyright (C) 2009 EDIT\r
-* European Distributed Institute of Taxonomy \r
-* http://www.e-taxonomy.eu\r
-* \r
-* The contents of this file are subject to the Mozilla Public License Version 1.1\r
-* See LICENSE.TXT at the top of this package for the full license terms.\r
-*/\r
-package eu.etaxonomy.cdm.io.pesi.out;\r
-\r
-import java.sql.Connection;\r
-import java.sql.PreparedStatement;\r
-import java.sql.ResultSet;\r
-import java.sql.SQLException;\r
-import java.sql.Types;\r
-import java.util.ArrayList;\r
-import java.util.BitSet;\r
-import java.util.HashMap;\r
-import java.util.HashSet;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import java.util.Set;\r
-import java.util.UUID;\r
-\r
-import org.apache.commons.lang.StringUtils;\r
-import org.apache.log4j.Logger;\r
-import org.joda.time.DateTime;\r
-import org.joda.time.format.DateTimeFormat;\r
-import org.joda.time.format.DateTimeFormatter;\r
-import org.springframework.stereotype.Component;\r
-import org.springframework.transaction.TransactionStatus;\r
-\r
-import eu.etaxonomy.cdm.api.service.TaxonServiceImpl;\r
-import eu.etaxonomy.cdm.common.CdmUtils;\r
-import eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer;\r
-import eu.etaxonomy.cdm.io.common.Source;\r
-import eu.etaxonomy.cdm.io.common.mapping.UndefinedTransformerMethodException;\r
-import eu.etaxonomy.cdm.io.common.mapping.out.DbConstantMapper;\r
-import eu.etaxonomy.cdm.io.common.mapping.out.DbExtensionMapper;\r
-import eu.etaxonomy.cdm.io.common.mapping.out.DbLastActionMapper;\r
-import eu.etaxonomy.cdm.io.common.mapping.out.DbObjectMapper;\r
-import eu.etaxonomy.cdm.io.common.mapping.out.DbStringMapper;\r
-import eu.etaxonomy.cdm.io.common.mapping.out.IdMapper;\r
-import eu.etaxonomy.cdm.io.common.mapping.out.MethodMapper;\r
-import eu.etaxonomy.cdm.io.common.mapping.out.ObjectChangeMapper;\r
-import eu.etaxonomy.cdm.io.pesi.erms.ErmsTransformer;\r
-import eu.etaxonomy.cdm.model.common.Annotation;\r
-import eu.etaxonomy.cdm.model.common.AnnotationType;\r
-import eu.etaxonomy.cdm.model.common.CdmBase;\r
-import eu.etaxonomy.cdm.model.common.Extension;\r
-import eu.etaxonomy.cdm.model.common.ExtensionType;\r
-import eu.etaxonomy.cdm.model.common.IdentifiableEntity;\r
-import eu.etaxonomy.cdm.model.common.IdentifiableSource;\r
-import eu.etaxonomy.cdm.model.common.Language;\r
-import eu.etaxonomy.cdm.model.common.Marker;\r
-import eu.etaxonomy.cdm.model.common.MarkerType;\r
-import eu.etaxonomy.cdm.model.common.RelationshipBase;\r
-import eu.etaxonomy.cdm.model.name.BacterialName;\r
-import eu.etaxonomy.cdm.model.name.BotanicalName;\r
-import eu.etaxonomy.cdm.model.name.HybridRelationship;\r
-import eu.etaxonomy.cdm.model.name.NameRelationship;\r
-import eu.etaxonomy.cdm.model.name.NameTypeDesignation;\r
-import eu.etaxonomy.cdm.model.name.NameTypeDesignationStatus;\r
-import eu.etaxonomy.cdm.model.name.NomenclaturalCode;\r
-import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;\r
-import eu.etaxonomy.cdm.model.name.NonViralName;\r
-import eu.etaxonomy.cdm.model.name.Rank;\r
-import eu.etaxonomy.cdm.model.name.TaxonNameBase;\r
-import eu.etaxonomy.cdm.model.name.ZoologicalName;\r
-import eu.etaxonomy.cdm.model.reference.INomenclaturalReference;\r
-import eu.etaxonomy.cdm.model.reference.Reference;\r
-import eu.etaxonomy.cdm.model.taxon.Classification;\r
-import eu.etaxonomy.cdm.model.taxon.Synonym;\r
-import eu.etaxonomy.cdm.model.taxon.SynonymRelationship;\r
-import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType;\r
-import eu.etaxonomy.cdm.model.taxon.Taxon;\r
-import eu.etaxonomy.cdm.model.taxon.TaxonBase;\r
-import eu.etaxonomy.cdm.model.taxon.TaxonNode;\r
-import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;\r
-import eu.etaxonomy.cdm.profiler.ProfilerController;\r
-import eu.etaxonomy.cdm.strategy.cache.HTMLTagRules;\r
-import eu.etaxonomy.cdm.strategy.cache.TagEnum;\r
-import eu.etaxonomy.cdm.strategy.cache.name.BacterialNameDefaultCacheStrategy;\r
-import eu.etaxonomy.cdm.strategy.cache.name.BotanicNameDefaultCacheStrategy;\r
-import eu.etaxonomy.cdm.strategy.cache.name.INonViralNameCacheStrategy;\r
-import eu.etaxonomy.cdm.strategy.cache.name.NonViralNameDefaultCacheStrategy;\r
-import eu.etaxonomy.cdm.strategy.cache.name.ZooNameNoMarkerCacheStrategy;\r
-\r
-/**\r
- * The export class for {@link eu.etaxonomy.cdm.model.name.TaxonNameBase TaxonNames}.<p>\r
- * Inserts into DataWarehouse database table <code>Taxon</code>.\r
- * It is divided into four phases:<p><ul>\r
- * <li>Phase 1: Export of all {@link eu.etaxonomy.cdm.model.name.TaxonNameBase TaxonNames} except some data exported in the following phases.\r
- * <li>Phase 2: Export of additional data: ParenTaxonFk and TreeIndex.\r
- * <li>Phase 3: Export of additional data: Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk.\r
- * <li>Phase 4: Export of Inferred Synonyms.</ul>\r
- * @author e.-m.lee\r
- * @date 23.02.2010\r
- *\r
- */\r
-@Component\r
-public class PesiTaxonExport extends PesiExportBase {\r
- private static final Logger logger = Logger.getLogger(PesiTaxonExport.class);\r
- private static final Class<? extends CdmBase> standardMethodParameter = TaxonBase.class;\r
-\r
- private static int modCount = 1000;\r
- private static final String dbTableName = "Taxon";\r
- private static final String dbTableNameSynRel = "RelTaxon";\r
- private static final String dbTableAdditionalSourceRel = "AdditionalTaxonSource";\r
- private static final String pluralString = "Taxa";\r
- private static final String parentPluralString = "Taxa";\r
- private PreparedStatement parentTaxonFk_TreeIndex_KingdomFkStmt;\r
- private PreparedStatement parentTaxonFkStmt;\r
- private PreparedStatement rankTypeExpertsUpdateStmt;\r
- private PreparedStatement rankUpdateStmt;\r
- private NomenclaturalCode nomenclaturalCode;\r
- private Integer kingdomFk;\r
- private HashMap<Rank, Rank> rank2endRankMap = new HashMap<Rank, Rank>();\r
- private List<Rank> rankList = new ArrayList<Rank>();\r
- private static final UUID uuidTreeIndex = UUID.fromString("28f4e205-1d02-4d3a-8288-775ea8413009");\r
- private AnnotationType treeIndexAnnotationType;\r
- private static ExtensionType lastActionExtensionType;\r
- private static ExtensionType lastActionDateExtensionType;\r
- private static ExtensionType expertNameExtensionType;\r
- private static ExtensionType speciesExpertNameExtensionType;\r
- private static ExtensionType cacheCitationExtensionType;\r
- public static NonViralNameDefaultCacheStrategy<?> zooNameStrategy = ZooNameNoMarkerCacheStrategy.NewInstance();\r
- public static NonViralNameDefaultCacheStrategy<?> botanicalNameStrategy = BotanicNameDefaultCacheStrategy.NewInstance();\r
- public static NonViralNameDefaultCacheStrategy<?> nonViralNameStrategy = NonViralNameDefaultCacheStrategy.NewInstance();\r
- public static NonViralNameDefaultCacheStrategy<?> bacterialNameStrategy = BacterialNameDefaultCacheStrategy.NewInstance();\r
- private static int currentTaxonId;\r
- \r
- \r
- /**\r
- * @return the treeIndexAnnotationType\r
- */\r
- protected AnnotationType getTreeIndexAnnotationType() {\r
- return treeIndexAnnotationType;\r
- }\r
-\r
- /**\r
- * @param treeIndexAnnotationType the treeIndexAnnotationType to set\r
- */\r
- protected void setTreeIndexAnnotationType(AnnotationType treeIndexAnnotationType) {\r
- this.treeIndexAnnotationType = treeIndexAnnotationType;\r
- }\r
-\r
- enum NamePosition {\r
- beginning,\r
- end,\r
- between,\r
- alone,\r
- nowhere\r
- }\r
-\r
- public PesiTaxonExport() {\r
- super();\r
- }\r
-\r
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.io.common.DbExportBase#getStandardMethodParameter()\r
- */\r
- @Override\r
- public Class<? extends CdmBase> getStandardMethodParameter() {\r
- return standardMethodParameter;\r
- }\r
-\r
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doCheck(eu.etaxonomy.cdm.io.common.IoStateBase)\r
- */\r
- @Override\r
- protected boolean doCheck(PesiExportState state) {\r
- boolean result = true;\r
- return result;\r
- }\r
- \r
- \r
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doInvoke(eu.etaxonomy.cdm.io.common.IoStateBase)\r
- */\r
- @Override\r
- protected void doInvoke(PesiExportState state) {\r
- try {\r
- logger.info("*** Started Making " + pluralString + " ...");\r
-\r
- initPreparedStatements(state);\r
- \r
- // Stores whether this invoke was successful or not.\r
- boolean success = true;\r
- \r
- // PESI: Clear the database table Taxon.\r
-// doDelete(state);\r
- \r
- // Get specific mappings: (CDM) Taxon -> (PESI) Taxon\r
- PesiExportMapping mapping = getMapping();\r
- PesiExportMapping synonymRelMapping = getSynRelMapping();\r
- PesiExportMapping additionalSourceMapping = getAdditionalSourceMapping(state); \r
- \r
- // Initialize the db mapper\r
- mapping.initialize(state);\r
- synonymRelMapping.initialize(state);\r
- additionalSourceMapping.initialize(state);\r
- \r
- // Find extensionTypes\r
- lastActionExtensionType = (ExtensionType)getTermService().find(PesiTransformer.lastActionUuid);\r
- lastActionDateExtensionType = (ExtensionType)getTermService().find(PesiTransformer.lastActionDateUuid);\r
- expertNameExtensionType = (ExtensionType)getTermService().find(PesiTransformer.expertNameUuid);\r
- speciesExpertNameExtensionType = (ExtensionType)getTermService().find(PesiTransformer.speciesExpertNameUuid);\r
- cacheCitationExtensionType = (ExtensionType)getTermService().find(PesiTransformer.cacheCitationUuid);\r
- \r
- //Export Taxa..\r
- success &= doPhase01(state, mapping, additionalSourceMapping);\r
-\r
- //"PHASE 1b: Handle names without taxa ...\r
- success &= doNames(state, additionalSourceMapping);\r
-\r
- \r
- // 2nd Round: Add ParentTaxonFk to each taxon\r
- success &= doPhase02(state);\r
- \r
- //PHASE 3: Add Rank data, KingdomFk, TypeNameFk ...\r
- success &= doPhase03(state);\r
- \r
- // 4nd Round: Add TreeIndex to each taxon\r
- success &= doPhase04(state);\r
- \r
- \r
- //"PHASE 4: Creating Inferred Synonyms...\r
- success &= doPhase05(state, mapping, synonymRelMapping);\r
- \r
- logger.info("*** Finished Making " + pluralString + " ..." + getSuccessString(success));\r
-\r
- if (!success){\r
- state.setUnsuccessfull();\r
- }\r
- return;\r
- } catch (Exception e) {\r
- e.printStackTrace();\r
- logger.error(e.getMessage());\r
- state.setUnsuccessfull();\r
- }\r
- }\r
-\r
- \r
- private void initPreparedStatements(PesiExportState state) throws SQLException {\r
- initTreeIndexStatement(state);\r
- initRankExpertsUpdateStmt(state);\r
- initRankUpdateStatement(state);\r
- \r
- initParentFkStatement(state);\r
- }\r
-\r
- // Prepare TreeIndex-And-KingdomFk-Statement\r
- private void initTreeIndexStatement(PesiExportState state) throws SQLException {\r
- Connection connection = state.getConfig().getDestination().getConnection();\r
- String parentTaxonFk_TreeIndex_KingdomFkSql = "UPDATE Taxon SET ParentTaxonFk = ?, TreeIndex = ? WHERE TaxonId = ?"; \r
- parentTaxonFk_TreeIndex_KingdomFkStmt = connection.prepareStatement(parentTaxonFk_TreeIndex_KingdomFkSql);\r
- }\r
-\r
- // Prepare TreeIndex-And-KingdomFk-Statement\r
- private void initParentFkStatement(PesiExportState state) throws SQLException {\r
- Connection connection = state.getConfig().getDestination().getConnection();\r
- String parentTaxonFkSql = "UPDATE Taxon SET ParentTaxonFk = ? WHERE TaxonId = ?"; \r
- parentTaxonFkStmt = connection.prepareStatement(parentTaxonFkSql);\r
- }\r
- \r
- private void initRankUpdateStatement(PesiExportState state) throws SQLException {\r
- Connection connection = state.getConfig().getDestination().getConnection();\r
- String rankSql = "UPDATE Taxon SET RankFk = ?, RankCache = ?, KingdomFk = ? WHERE TaxonId = ?";\r
- rankUpdateStmt = connection.prepareStatement(rankSql);\r
- }\r
-\r
- private void initRankExpertsUpdateStmt(PesiExportState state) throws SQLException {\r
-// String sql_old = "UPDATE Taxon SET RankFk = ?, RankCache = ?, TypeNameFk = ?, KingdomFk = ?, " +\r
-// "ExpertFk = ?, SpeciesExpertFk = ? WHERE TaxonId = ?";\r
- //TODO handle experts GUIDs\r
- Connection connection = state.getConfig().getDestination().getConnection();\r
- \r
- String sql = "UPDATE Taxon SET RankFk = ?, RankCache = ?, TypeNameFk = ?, KingdomFk = ? " +\r
- " WHERE TaxonId = ?";\r
- rankTypeExpertsUpdateStmt = connection.prepareStatement(sql);\r
- }\r
-\r
- private boolean doPhase01(PesiExportState state, PesiExportMapping mapping, PesiExportMapping additionalSourceMapping) throws SQLException {\r
- int count = 0;\r
- int pastCount = 0;\r
- List<TaxonBase> list;\r
- boolean success = true;\r
- // Get the limit for objects to save within a single transaction.\r
- int limit = state.getConfig().getLimitSave();\r
-\r
- \r
- logger.info("PHASE 1: Export Taxa...limit is " + limit);\r
- // Start transaction\r
- TransactionStatus txStatus = startTransaction(true);\r
- logger.info("Started new transaction. Fetching some " + pluralString + " (max: " + limit + ") ...");\r
- \r
- \r
- \r
- int partitionCount = 0;\r
-\r
- logger.info("Taking snapshot at the beginning of phase 1 of taxonExport");\r
- ProfilerController.memorySnapshot();\r
- while ((list = getNextTaxonPartition(null, limit, partitionCount++, null)) != null ) {\r
- \r
- logger.debug("Fetched " + list.size() + " " + pluralString + ". Exporting...");\r
- for (TaxonBase<?> taxon : list) {\r
- doCount(count++, modCount, pluralString);\r
- TaxonNameBase<?,?> taxonName = taxon.getName();\r
- NonViralName<?> nvn = CdmBase.deproxy(taxonName, NonViralName.class);\r
- \r
- if (! nvn.isProtectedTitleCache()){\r
- nvn.setTitleCache(null, false); \r
- }\r
- if (! nvn.isProtectedNameCache()){\r
- nvn.setNameCache(null, false); \r
- }\r
- if (! nvn.isProtectedFullTitleCache()){\r
- nvn.setFullTitleCache(null, false); \r
- }\r
- if (! nvn.isProtectedAuthorshipCache()){\r
- nvn.setAuthorshipCache(null, false); \r
- }\r
- \r
- //core mapping\r
- success &= mapping.invoke(taxon);\r
- //additional source\r
- if (nvn.getNomenclaturalReference() != null || StringUtils.isNotBlank(nvn.getNomenclaturalMicroReference() )){\r
- additionalSourceMapping.invoke(taxon);\r
- }\r
- \r
- validatePhaseOne(taxon, nvn);\r
- taxon = null;\r
- nvn = null;\r
- taxonName = null;\r
-\r
- \r
- \r
- }\r
- \r
-\r
- // Commit transaction\r
- commitTransaction(txStatus);\r
- logger.debug("Committed transaction.");\r
- logger.info("Exported " + (count - pastCount) + " " + pluralString + ". Total: " + count);\r
- pastCount = count;\r
- /*logger.warn("Taking snapshot at the end of the loop of phase 1 of taxonExport");\r
- ProfilerController.memorySnapshot();\r
- */\r
- // Start transaction\r
- txStatus = startTransaction(true);\r
- logger.info("Started new transaction. Fetching some " + pluralString + " (max: " + limit + ") ...");\r
- \r
- }\r
- if (list == null ) {\r
- logger.info("No " + pluralString + " left to fetch.");\r
- }\r
- \r
- \r
- \r
- // Commit transaction\r
- commitTransaction(txStatus);\r
- txStatus = null;\r
- logger.debug("Committed transaction.");\r
- list = null;\r
- if (logger.isDebugEnabled()){\r
- logger.debug("Taking snapshot at the end of phase 1 of taxonExport");\r
- ProfilerController.memorySnapshot();\r
- }\r
- return success;\r
- }\r
-\r
-\r
- private void validatePhaseOne(TaxonBase<?> taxon, NonViralName taxonName) {\r
- // Check whether some rules are violated\r
- nomenclaturalCode = taxonName.getNomenclaturalCode();\r
- String genusOrUninomial = taxonName.getGenusOrUninomial();\r
- String specificEpithet = taxonName.getSpecificEpithet();\r
- String infraSpecificEpithet = taxonName.getInfraSpecificEpithet();\r
- String infraGenericEpithet = taxonName.getInfraGenericEpithet();\r
- Integer rank = getRankFk(taxonName, nomenclaturalCode);\r
- \r
- if (rank == null) {\r
- logger.error("Rank was not determined: " + taxon.getUuid() + " (" + taxon.getTitleCache() + ")");\r
- } else {\r
- \r
- // Check whether infraGenericEpithet is set correctly\r
- // 1. Childs of an accepted taxon of rank subgenus that are accepted taxa of rank species have to have an infraGenericEpithet\r
- // 2. Grandchilds of an accepted taxon of rank subgenus that are accepted taxa of rank subspecies have to have an infraGenericEpithet\r
- \r
- int ancestorLevel = 0;\r
- if (taxonName.getRank().equals(Rank.SUBSPECIES())) {\r
- // The accepted taxon two rank levels above should be of rank subgenus\r
- ancestorLevel = 2;\r
- }\r
- if (taxonName.getRank().equals(Rank.SPECIES())) {\r
- // The accepted taxon one rank level above should be of rank subgenus\r
- ancestorLevel = 1;\r
- }\r
- if (ancestorLevel > 0) {\r
- if (validateAncestorOfSpecificRank(taxon, ancestorLevel, Rank.SUBGENUS())) {\r
- // The child (species or subspecies) of this parent (subgenus) has to have an infraGenericEpithet\r
- if (infraGenericEpithet == null) {\r
- logger.warn("InfraGenericEpithet for (sub)species of infrageneric taxon does not exist even though it should (also valid for Botanical Names?) for: " + taxon.getUuid() + " (" + taxon.getTitleCache() + ")");\r
- // maybe the taxon could be named here\r
- }\r
- }\r
- }\r
- \r
- if (infraGenericEpithet == null && rank.intValue() == 190) {\r
- logger.warn("InfraGenericEpithet was not determined although it should exist for rank 190: " + taxon.getUuid() + " (" + taxon.getTitleCache() + ")");\r
- }\r
- if (specificEpithet != null && rank.intValue() < 216) {\r
- 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() + ")");\r
- }\r
- if (infraSpecificEpithet != null && rank.intValue() < 225) {\r
- 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() + ")"; \r
- if (StringUtils.isNotBlank(infraSpecificEpithet)){\r
- logger.warn(message);\r
- }else{\r
- logger.warn(message);\r
- }\r
- }\r
- }\r
- if (infraSpecificEpithet != null && specificEpithet == null) {\r
- logger.warn("An infraSpecificEpithet was determined, but a specificEpithet was not determined: " + taxon.getUuid() + " (" + taxon.getTitleCache() + ")");\r
- }\r
- if (genusOrUninomial == null) {\r
- logger.warn("GenusOrUninomial was not determined: " + taxon.getUuid() + " (" + taxon.getTitleCache() + ")");\r
- }\r
- }\r
-\r
- \r
- \r
- /**\r
- * 2nd Round: Add ParentTaxonFk to each taxon and add Biota if not exists\r
- * @param state\r
- * @return\r
- */\r
- private boolean doPhase02(PesiExportState state) {\r
- int count = 0;\r
- int pastCount = 0;\r
- boolean success = true;\r
- if (! state.getConfig().isDoParentAndBiota()){\r
- logger.info ("Ignore PHASE 2: Make ParentFk and Biota...");\r
- return success;\r
- }\r
- \r
- List<Taxon> list;\r
- \r
- // Get the limit for objects to save within a single transaction.\r
- int limit = state.getConfig().getLimitSave();\r
- \r
- insertBiota(state);\r
- \r
- logger.info("PHASE 2: Make ParentFk and Biota ... limit is " + limit);\r
- // Start transaction\r
- TransactionStatus txStatus = startTransaction(true);\r
- int partitionCount = 0;\r
-\r
-// ProfilerController.memorySnapshot();\r
- while ((list = getNextTaxonPartition(Taxon.class, limit, partitionCount++, null)) != null ) {\r
- \r
- logger.info("Fetched " + list.size() + " " + pluralString + ". Exporting...");\r
- for (Taxon taxon : list) {\r
- for (TaxonNode node : taxon.getTaxonNodes()){\r
- doCount(count++, modCount, pluralString);\r
- TaxonNode parentNode = node.getParent();\r
- if (parentNode != null && parentNode.getTaxon() != null){ //new root node handling requires has root taxon with taxon == null\r
- int childId = state.getDbId( taxon); \r
- int parentId = state.getDbId(parentNode.getTaxon());\r
- success &= invokeParentTaxonFk(parentId, childId);\r
- }\r
- }\r
- \r
- }\r
- \r
- // Commit transaction\r
- commitTransaction(txStatus);\r
- logger.info("Exported " + (count - pastCount) + " " + pluralString + ". Total: " + count);\r
- pastCount = count;\r
- // Start transaction\r
- txStatus = startTransaction(true);\r
- logger.info("Started new transaction. Fetching some " + pluralString + " (max: " + limit + ") ...");\r
- \r
- }\r
- if (list == null ) {\r
- logger.info("No " + pluralString + " left to fetch.");\r
- }\r
- \r
- // Commit transaction\r
- commitTransaction(txStatus);\r
- \r
- return success;\r
- \r
- }\r
-\r
- /**\r
- * Inserts the Biota Taxon if not yet exists.\r
- * @param state\r
- * @throws SQLException\r
- */\r
- private void insertBiota(PesiExportState state) {\r
- try {\r
- ResultSet rs = state.getConfig().getDestination().getResultSet("SELECT * FROM Taxon WHERE GenusOrUninomial = 'Biota' ");\r
- if (rs.next() == false){\r
- int biotaId = state.getConfig().getNameIdStart() -1 ;\r
- String sqlInsertBiota = "INSERT INTO Taxon (TaxonId, KingdomFk, RankFk, RankCache, GenusOrUninomial, WebSearchName, WebShowName, FullName, DisplayName, TaxonStatusFk, TaxonStatusCache) " +\r
- " VALUES (" + biotaId + ", 0, 0, 'Superdomain', 'Biota', 'Biota', '<i>Biota</i>', 'Biota', '<i>Biota</i>', 1 , 'accepted')";\r
- state.getConfig().getDestination().update(sqlInsertBiota);\r
- }\r
- } catch (SQLException e) {\r
- logger.warn ("Biota could not be requested or inserted");\r
- }\r
- }\r
- \r
- // 4th round: Add TreeIndex to each taxon\r
- private boolean doPhase04(PesiExportState state) {\r
- boolean success = true;\r
- \r
- logger.info("PHASE 4: Make TreeIndex ... ");\r
- \r
- //TODO test if possible to move to phase 02 \r
- String sql = " UPDATE Taxon SET ParentTaxonFk = (Select TaxonId from Taxon where RankFk = 0) " +\r
- " WHERE (RankFk = 10) and TaxonStatusFk = 1 ";\r
- state.getConfig().getDestination().update(sql);\r
- \r
- state.getConfig().getDestination().update("EXEC dbo.recalculateallstoredpaths");\r
- \r
- return success;\r
- \r
- }\r
- \r
- \r
- // 2nd Round: Add ParentTaxonFk, TreeIndex to each Taxon\r
- private boolean doPhase02_OLD(PesiExportState state) {\r
- boolean success = true;\r
- if (! state.getConfig().isDoTreeIndex()){\r
- logger.info ("Ignore PHASE 2: ParentTaxonFk and TreeIndex");\r
- return success;\r
- }\r
- \r
- List<Classification> classificationList = null;\r
- logger.info("PHASE 2: Add ParenTaxonFk and TreeIndex...");\r
- \r
- // Specify starting ranks for tree traversing\r
- rankList.add(Rank.KINGDOM());\r
- rankList.add(Rank.GENUS());\r
-\r
- // Specify where to stop traversing (value) when starting at a specific Rank (key)\r
- rank2endRankMap.put(Rank.GENUS(), null); // Since NULL does not match an existing Rank, traverse all the way down to the leaves\r
- rank2endRankMap.put(Rank.KINGDOM(), Rank.GENUS()); // excludes rank genus\r
- \r
- StringBuffer treeIndex = new StringBuffer();\r
- \r
- // Retrieve list of classifications\r
- TransactionStatus txStatus = startTransaction(true);\r
- logger.info("Started transaction for parentFk and treeIndex. Fetching all classifications...");\r
- classificationList = getClassificationService().listClassifications(null, 0, null, null);\r
- commitTransaction(txStatus);\r
- logger.debug("Committed transaction.");\r
-\r
- logger.info("Fetched " + classificationList.size() + " classification(s).");\r
-\r
- setTreeIndexAnnotationType(getAnnotationType(uuidTreeIndex, "TreeIndex", "TreeIndex", "TI"));\r
- List<TaxonNode> rankSpecificRootNodes;\r
- for (Classification classification : classificationList) {\r
- for (Rank rank : rankList) {\r
- \r
- txStatus = startTransaction(true);\r
- logger.info("Started transaction to fetch all rootNodes specific to Rank " + rank.getLabel() + " ...");\r
-\r
- rankSpecificRootNodes = getClassificationService().loadRankSpecificRootNodes(classification, rank, null, null, null);\r
- logger.info("Fetched " + rankSpecificRootNodes.size() + " RootNodes for Rank " + rank.getLabel());\r
-\r
- commitTransaction(txStatus);\r
- logger.debug("Committed transaction.");\r
-\r
- for (TaxonNode rootNode : rankSpecificRootNodes) {\r
- txStatus = startTransaction(false);\r
- Rank endRank = rank2endRankMap.get(rank);\r
- if (endRank != null) {\r
- logger.debug("Started transaction to traverse childNodes of rootNode (" + rootNode.getUuid() + ") till Rank " + endRank.getLabel() + " ...");\r
- } else {\r
- logger.debug("Started transaction to traverse childNodes of rootNode (" + rootNode.getUuid() + ") till leaves are reached ...");\r
- }\r
-\r
- TaxonNode newNode = getTaxonNodeService().load(rootNode.getUuid());\r
-\r
- if (isPesiTaxon(newNode.getTaxon())){\r
- TaxonNode parentNode = newNode.getParent();\r
- if (rank.equals(Rank.KINGDOM())) {\r
- treeIndex = new StringBuffer();\r
- treeIndex.append("#");\r
- } else {\r
- // Get treeIndex from parentNode\r
- if (parentNode != null) {\r
- boolean annotationFound = false;\r
- Set<Annotation> annotations = parentNode.getAnnotations();\r
- for (Annotation annotation : annotations) {\r
- AnnotationType annotationType = annotation.getAnnotationType();\r
- if (annotationType != null && annotationType.equals(getTreeIndexAnnotationType())) {\r
- treeIndex = new StringBuffer(CdmUtils.Nz(annotation.getText()));\r
- annotationFound = true;\r
- // logger.error("treeIndex: " + treeIndex);\r
- break;\r
- }\r
- }\r
- if (!annotationFound) {\r
- // This should not happen because it means that the treeIndex was not set correctly as an annotation to parentNode\r
- logger.error("TreeIndex could not be read from annotation of TaxonNode: " + parentNode.getUuid() + ", Taxon: " + parentNode.getTaxon().getUuid());\r
- treeIndex = new StringBuffer();\r
- treeIndex.append("#");\r
- }\r
- } else {\r
- // TreeIndex could not be determined, but it's unclear how to proceed to generate a correct treeIndex if the parentNode is NULL\r
- logger.error("ParentNode for RootNode is NULL. TreeIndex could not be determined: " + newNode.getUuid());\r
- treeIndex = new StringBuffer(); // This just prevents growing of the treeIndex in a wrong manner\r
- treeIndex.append("#");\r
- }\r
- }\r
- nomenclaturalCode = newNode.getTaxon().getName().getNomenclaturalCode();\r
- kingdomFk = PesiTransformer.nomenClaturalCode2Kingdom(nomenclaturalCode);\r
- traverseTree(newNode, parentNode, treeIndex, endRank, state);\r
- parentNode =null;\r
- }else{\r
- logger.debug("Taxon is not a PESI taxon: " + newNode.getTaxon().getUuid());\r
- }\r
- \r
- newNode = null;\r
- \r
- try {\r
- commitTransaction(txStatus);\r
- logger.debug("Committed transaction.");\r
- } catch (Exception e) {\r
- logger.error(e.getMessage());\r
- e.printStackTrace();\r
- }\r
-\r
- }\r
- rankSpecificRootNodes = null;\r
- }\r
- \r
- }\r
- \r
- logger.warn("Taking snapshot at the end of phase 2 of taxonExport");\r
- ProfilerController.memorySnapshot();\r
- return success;\r
- } \r
-\r
- //PHASE 3: Add Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk...\r
- private boolean doPhase03(PesiExportState state) {\r
- int count = 0;\r
- int pastCount = 0;\r
- boolean success = true;\r
- if (! state.getConfig().isDoTreeIndex()){\r
- logger.info ("Ignore PHASE 3: Add Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk...");\r
- return success;\r
- }\r
- // Get the limit for objects to save within a single transaction.\r
- int limit = state.getConfig().getLimitSave();\r
-\r
- List<TaxonBase> list;\r
- logger.info("PHASE 3: Add Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk...");\r
- // Be sure to add rank information, KingdomFk, TypeNameFk, expertFk and speciesExpertFk to every taxonName\r
- \r
- // Start transaction\r
- TransactionStatus txStatus = startTransaction(true);\r
- logger.info("Started new transaction for rank, kingdom, typeName, expertFk and speciesExpertFK. Fetching some " + pluralString + " (max: " + limit + ") ...");\r
- int partitionCount = 0;\r
- while ((list = getNextTaxonPartition(TaxonBase.class, limit, partitionCount++, null)) != null) {\r
-\r
- logger.debug("Fetched " + list.size() + " " + pluralString + ". Exporting...");\r
- for (TaxonBase<?> taxon : list) {\r
- TaxonNameBase<?,?> taxonName = taxon.getName();\r
- // Determine expertFk\r
-// Integer expertFk = makeExpertFk(state, taxonName);\r
-//\r
-// // Determine speciesExpertFk\r
-// Integer speciesExpertFk = makeSpeciesExpertFk(state, taxonName);\r
-\r
- doCount(count++, modCount, pluralString);\r
- Integer typeNameFk = getTypeNameFk(taxonName, state);\r
- kingdomFk = PesiTransformer.nomenClaturalCode2Kingdom(nomenclaturalCode);\r
- \r
- //TODO why are expertFks needed? (Andreas M.)\r
-// if (expertFk != null || speciesExpertFk != null) {\r
- invokeRankDataAndTypeNameFkAndKingdomFk(taxonName, nomenclaturalCode, state.getDbId(taxon), \r
- typeNameFk, kingdomFk, state);\r
-// }\r
- \r
- taxon = null;\r
- taxonName = null;\r
- }\r
-\r
- // Commit transaction\r
- commitTransaction(txStatus);\r
- logger.debug("Committed transaction.");\r
- logger.info("Exported " + (count - pastCount) + " " + pluralString + ". Total: " + count);\r
- pastCount = count;\r
-\r
- // Start transaction\r
- txStatus = startTransaction(true);\r
- logger.info("Started new transaction for rank, kingdom, typeName, expertFk and speciesExpertFK. Fetching some " + pluralString + " (max: " + limit + ") ...");\r
- }\r
- if (list == null) {\r
- logger.info("No " + pluralString + " left to fetch.");\r
- }\r
- \r
- list = null;\r
- \r
- // Commit transaction\r
- commitTransaction(txStatus);\r
- \r
- logger.debug("Committed transaction.");\r
- logger.debug("Try to take snapshot at the end of phase 3 of taxonExport, number of partitions: " + partitionCount);\r
- ProfilerController.memorySnapshot();\r
- return success;\r
- }\r
- \r
- // "PHASE 5: Creating Inferred Synonyms..."\r
- private boolean doPhase05(PesiExportState state, PesiExportMapping mapping, PesiExportMapping synRelMapping) throws SQLException {\r
- int count;\r
- int pastCount;\r
- boolean success = true;\r
- // Get the limit for objects to save within a single transaction.\r
- if (! state.getConfig().isDoInferredSynonyms()){\r
- logger.info ("Ignore PHASE 5: Creating Inferred Synonyms...");\r
- return success;\r
- }\r
- \r
- int limit = state.getConfig().getLimitSave();\r
- // Create inferred synonyms for accepted taxa\r
- logger.info("PHASE 4: Creating Inferred Synonyms...");\r
-\r
- // Determine the count of elements in datawarehouse database table Taxon\r
- currentTaxonId = determineTaxonCount(state);\r
- currentTaxonId++;\r
-\r
- count = 0;\r
- pastCount = 0;\r
- int pageSize = limit;\r
- int pageNumber = 1;\r
- String inferredSynonymPluralString = "Inferred Synonyms";\r
- \r
- // Start transaction\r
- TransactionStatus txStatus = startTransaction(true);\r
- logger.info("Started new transaction. Fetching some " + parentPluralString + " first (max: " + limit + ") ...");\r
- List<TaxonBase> taxonList = null;\r
- \r
- \r
- \r
- while ((taxonList = getTaxonService().listTaxaByName(Taxon.class, "*", "*", "*", "*", Rank.SPECIES(), pageSize, pageNumber)).size() > 0) {\r
- HashMap<Integer, TaxonNameBase<?,?>> inferredSynonymsDataToBeSaved = new HashMap<Integer, TaxonNameBase<?,?>>();\r
-\r
- logger.info("Fetched " + taxonList.size() + " " + parentPluralString + ". Exporting...");\r
- inferredSynonymsDataToBeSaved.putAll(createInferredSynonymsForTaxonList(state, mapping,\r
- synRelMapping, taxonList));\r
- \r
- doCount(count += taxonList.size(), modCount, inferredSynonymPluralString);\r
- // Commit transaction\r
- commitTransaction(txStatus);\r
- logger.debug("Committed transaction.");\r
- logger.info("Exported " + (taxonList.size()) + " " + inferredSynonymPluralString + ". Total: " + count);\r
- //pastCount = count;\r
- \r
- // Save Rank Data and KingdomFk for inferred synonyms\r
- for (Integer taxonFk : inferredSynonymsDataToBeSaved.keySet()) {\r
- invokeRankDataAndKingdomFk(inferredSynonymsDataToBeSaved.get(taxonFk), nomenclaturalCode, taxonFk, kingdomFk, state);\r
- }\r
-\r
- // Start transaction\r
- txStatus = startTransaction(true);\r
- logger.info("Started new transaction. Fetching some " + parentPluralString + " first (max: " + limit + ") ...");\r
- \r
- // Increment pageNumber\r
- pageNumber++;\r
- }\r
- taxonList = null;\r
- while ((taxonList = getTaxonService().listTaxaByName(Taxon.class, "*", "*", "*", "*", Rank.SUBSPECIES(), pageSize, pageNumber)).size() > 0) {\r
- HashMap<Integer, TaxonNameBase<?,?>> inferredSynonymsDataToBeSaved = new HashMap<Integer, TaxonNameBase<?,?>>();\r
-\r
- logger.info("Fetched " + taxonList.size() + " " + parentPluralString + ". Exporting...");\r
- inferredSynonymsDataToBeSaved.putAll(createInferredSynonymsForTaxonList(state, mapping,\r
- synRelMapping, taxonList));\r
- ;\r
- doCount(count += taxonList.size(), modCount, inferredSynonymPluralString);\r
- // Commit transaction\r
- commitTransaction(txStatus);\r
- logger.debug("Committed transaction.");\r
- logger.info("Exported " + taxonList.size()+ " " + inferredSynonymPluralString + ". Total: " + count);\r
- //pastCount = count;\r
- \r
- // Save Rank Data and KingdomFk for inferred synonyms\r
- for (Integer taxonFk : inferredSynonymsDataToBeSaved.keySet()) {\r
- invokeRankDataAndKingdomFk(inferredSynonymsDataToBeSaved.get(taxonFk), nomenclaturalCode, taxonFk, kingdomFk, state);\r
- }\r
-\r
- // Start transaction\r
- txStatus = startTransaction(true);\r
- logger.info("Started new transaction. Fetching some " + parentPluralString + " first (max: " + limit + ") ...");\r
- \r
- // Increment pageNumber\r
- pageNumber++;\r
- }\r
- if (taxonList.size() == 0) {\r
- logger.info("No " + parentPluralString + " left to fetch.");\r
- }\r
- \r
- taxonList = null;\r
-// logger.warn("Taking snapshot at the end of phase 4 of taxonExport");\r
-// ProfilerController.memorySnapshot();\r
- \r
- // Commit transaction\r
- commitTransaction(txStatus);\r
- System.gc();\r
- logger.debug("Taking snapshot at the end of phase 4 after gc() of taxonExport");\r
- ProfilerController.memorySnapshot();\r
- logger.debug("Committed transaction.");\r
- return success;\r
- }\r
-\r
- /**\r
- * @param state\r
- * @param mapping\r
- * @param synRelMapping\r
- * @param currentTaxonId\r
- * @param taxonList\r
- * @param inferredSynonymsDataToBeSaved\r
- * @return\r
- */\r
- private HashMap<Integer, TaxonNameBase<?, ?>> createInferredSynonymsForTaxonList(PesiExportState state,\r
- PesiExportMapping mapping, PesiExportMapping synRelMapping, List<TaxonBase> taxonList) {\r
- \r
- Taxon acceptedTaxon;\r
- Classification classification = null;\r
- List<Synonym> inferredSynonyms = null;\r
- boolean localSuccess = true;\r
- \r
- HashMap<Integer, TaxonNameBase<?,?>> inferredSynonymsDataToBeSaved = new HashMap<Integer, TaxonNameBase<?,?>>();\r
- \r
- for (TaxonBase<?> taxonBase : taxonList) {\r
- \r
- if (taxonBase.isInstanceOf(Taxon.class)) { // this should always be the case since we should have fetched accepted taxon only, but you never know...\r
- acceptedTaxon = CdmBase.deproxy(taxonBase, Taxon.class);\r
- TaxonNameBase<?,?> taxonName = acceptedTaxon.getName();\r
- \r
- if (taxonName.isInstanceOf(ZoologicalName.class)) {\r
- nomenclaturalCode = taxonName.getNomenclaturalCode();\r
- kingdomFk = PesiTransformer.nomenClaturalCode2Kingdom(nomenclaturalCode);\r
-\r
- Set<TaxonNode> taxonNodes = acceptedTaxon.getTaxonNodes();\r
- TaxonNode singleNode = null;\r
- \r
- if (taxonNodes.size() > 0) {\r
- // Determine the classification of the current TaxonNode\r
- \r
- singleNode = taxonNodes.iterator().next();\r
- if (singleNode != null) {\r
- classification = singleNode.getClassification();\r
- } else {\r
- logger.error("A TaxonNode belonging to this accepted Taxon is NULL: " + acceptedTaxon.getUuid() + " (" + acceptedTaxon.getTitleCache() +")");\r
- }\r
- } else {\r
- // Classification could not be determined directly from this TaxonNode\r
- // The stored classification from another TaxonNode is used. It's a simple, but not a failsafe fallback solution.\r
- if (taxonNodes.size() == 0) {\r
- //logger.error("Classification could not be determined directly from this Taxon: " + acceptedTaxon.getUuid() + " is misapplication? "+acceptedTaxon.isMisapplication()+ "). The classification of the last taxon is used");\r
- \r
- }\r
- }\r
- \r
- if (classification != null) {\r
- try{\r
- TaxonNameBase name = acceptedTaxon.getName();\r
- //if (name.isSpecies() || name.isInfraSpecific()){\r
- inferredSynonyms = getTaxonService().createAllInferredSynonyms(acceptedTaxon, classification, true);\r
- //}\r
-// inferredSynonyms = getTaxonService().createInferredSynonyms(classification, acceptedTaxon, SynonymRelationshipType.INFERRED_GENUS_OF());\r
- if (inferredSynonyms != null) {\r
- for (Synonym synonym : inferredSynonyms) {\r
-// TaxonNameBase<?,?> synonymName = synonym.getName();\r
- MarkerType markerType =getUuidMarkerType(PesiTransformer.uuidMarkerGuidIsMissing, state);\r
- synonym.addMarker(Marker.NewInstance(markerType, true));\r
- // Both Synonym and its TaxonName have no valid Id yet\r
- synonym.setId(currentTaxonId++);\r
- \r
- \r
- localSuccess &= mapping.invoke(synonym);\r
- //get SynonymRelationship and export\r
- if (synonym.getSynonymRelations().isEmpty() ){\r
- SynonymRelationship synRel; \r
- IdentifiableSource source = synonym.getSources().iterator().next();\r
- if (source.getIdNamespace().contains("Potential combination")){\r
- synRel = acceptedTaxon.addSynonym(synonym, SynonymRelationshipType.POTENTIAL_COMBINATION_OF());\r
- logger.error(synonym.getTitleCache() + " has no synonym relationship to " + acceptedTaxon.getTitleCache() + " type is set to potential combination");\r
- } else if (source.getIdNamespace().contains("Inferred Genus")){\r
- synRel = acceptedTaxon.addSynonym(synonym, SynonymRelationshipType.INFERRED_GENUS_OF());\r
- logger.error(synonym.getTitleCache() + " has no synonym relationship to " + acceptedTaxon.getTitleCache() + " type is set to inferred genus");\r
- } else if (source.getIdNamespace().contains("Inferred Epithet")){\r
- synRel = acceptedTaxon.addSynonym(synonym, SynonymRelationshipType.INFERRED_EPITHET_OF());\r
- logger.error(synonym.getTitleCache() + " has no synonym relationship to " + acceptedTaxon.getTitleCache() + " type is set to inferred epithet");\r
- } else{\r
- synRel = acceptedTaxon.addSynonym(synonym, SynonymRelationshipType.INFERRED_SYNONYM_OF());\r
- logger.error(synonym.getTitleCache() + " has no synonym relationship to " + acceptedTaxon.getTitleCache() + " type is set to inferred synonym");\r
- }\r
- \r
- localSuccess &= synRelMapping.invoke(synRel);\r
- if (!localSuccess) {\r
- logger.error("Synonym relationship export failed " + synonym.getTitleCache() + " accepted taxon: " + acceptedTaxon.getUuid() + " (" + acceptedTaxon.getTitleCache()+")");\r
- }\r
- synRel = null;\r
- } else {\r
- for (SynonymRelationship synRel: synonym.getSynonymRelations()){\r
- localSuccess &= synRelMapping.invoke(synRel);\r
- if (!localSuccess) {\r
- logger.error("Synonym relationship export failed " + synonym.getTitleCache() + " accepted taxon: " + acceptedTaxon.getUuid() + " (" + acceptedTaxon.getTitleCache()+")");\r
- } else {\r
- logger.info("Synonym relationship successfully exported: " + synonym.getTitleCache() + " " +acceptedTaxon.getUuid() + " (" + acceptedTaxon.getTitleCache()+")");\r
- }\r
- synRel = null;\r
- }\r
- }\r
- \r
- inferredSynonymsDataToBeSaved.put(synonym.getId(), synonym.getName());\r
- }\r
- }\r
- }catch(Exception e){\r
- logger.error(e.getMessage());\r
- e.printStackTrace();\r
- }\r
- } else {\r
- logger.error("Classification is NULL. Inferred Synonyms could not be created for this Taxon: " + acceptedTaxon.getUuid() + " (" + acceptedTaxon.getTitleCache() + ")");\r
- }\r
- } else {\r
-// logger.error("TaxonName is not a ZoologicalName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");\r
- }\r
- } else {\r
- logger.error("This TaxonBase is not a Taxon even though it should be: " + taxonBase.getUuid() + " (" + taxonBase.getTitleCache() + ")");\r
- }\r
- }\r
- taxonList = null;\r
- return inferredSynonymsDataToBeSaved;\r
- }\r
- \r
-\r
- /**\r
- * Handles names that do not appear in taxa\r
- * @param state\r
- * @param mapping\r
- * @return\r
- */\r
- private boolean doNames(PesiExportState state, PesiExportMapping additionalSourceMapping) throws SQLException {\r
- \r
- boolean success = true;\r
- if (! state.getConfig().isDoPureNames()){\r
- logger.info ("Ignore PHASE 1b: PureNames");\r
- return success;\r
- }\r
- \r
- try {\r
- PesiExportMapping mapping = getPureNameMapping(state);\r
- mapping.initialize(state);\r
- int count = 0;\r
- int pastCount = 0;\r
- List<NonViralName<?>> list;\r
- success = true;\r
- // Get the limit for objects to save within a single transaction.\r
- int limit = state.getConfig().getLimitSave();\r
-\r
- \r
- logger.info("PHASE 1b: Export Pure Names ...");\r
- // Start transaction\r
- TransactionStatus txStatus = startTransaction(true);\r
- logger.info("Started new transaction for Pure Names. Fetching some " + pluralString + " (max: " + limit + ") ...");\r
- \r
- int partitionCount = 0;\r
- while ((list = getNextPureNamePartition(null, limit, partitionCount++)) != null ) {\r
-\r
- logger.info("Fetched " + list.size() + " names without taxa. Exporting...");\r
- for (TaxonNameBase<?,?> taxonName : list) {\r
- doCount(count++, modCount, pluralString);\r
- success &= mapping.invoke(taxonName);\r
- //additional source\r
- if (taxonName.getNomenclaturalReference() != null || StringUtils.isNotBlank(taxonName.getNomenclaturalMicroReference() )){\r
- additionalSourceMapping.invoke(taxonName);\r
- }\r
- }\r
-\r
- // Commit transaction\r
- commitTransaction(txStatus);\r
- logger.debug("Committed transaction.");\r
- logger.info("Exported " + (count - pastCount) + " " + pluralString + ". Total: " + count);\r
- pastCount = count;\r
-\r
- // Start transaction\r
- txStatus = startTransaction(true);\r
- logger.info("Started new transaction for PureNames. Fetching some " + pluralString + " (max: " + limit + ") ...");\r
- }\r
- if (list == null) {\r
- logger.info("No " + pluralString + " left to fetch.");\r
- }\r
- // Commit transaction\r
- commitTransaction(txStatus);\r
- logger.debug("Committed transaction.");\r
- } catch (Exception e) {\r
- logger.error("Error occurred in pure name export");\r
- e.printStackTrace();\r
- success = false;\r
- }\r
- return success;\r
- }\r
-\r
- /**\r
- * Determines the current number of entries in the DataWarehouse database table <code>Taxon</code>.\r
- * @param state The {@link PesiExportState PesiExportState}.\r
- * @return The count.\r
- */\r
- private Integer determineTaxonCount(PesiExportState state) {\r
- Integer result = null;\r
- PesiExportConfigurator pesiConfig = (PesiExportConfigurator) state.getConfig();\r
- \r
- String sql;\r
- Source destination = pesiConfig.getDestination();\r
- sql = "SELECT max(taxonId) FROM Taxon";\r
- destination.setQuery(sql);\r
- ResultSet resultSet = destination.getResultSet();\r
- try {\r
- resultSet.next();\r
- result = resultSet.getInt(1);\r
- } catch (SQLException e) {\r
- logger.error("TaxonCount could not be determined: " + e.getMessage());\r
- e.printStackTrace();\r
- }\r
- return result;\r
- }\r
- \r
- /**\r
- * Checks whether a parent at specific level has a specific Rank.\r
- * @param taxonName A {@link TaxonNameBase TaxonName}.\r
- * @param level The ancestor level.\r
- * @param ancestorRank The ancestor rank.\r
- * @return Whether a parent at a specific level has a specific Rank.\r
- */\r
- private boolean validateAncestorOfSpecificRank(TaxonBase<?> taxonBase, int level, Rank ancestorRank) {\r
- boolean result = false;\r
- TaxonNode parentNode = null;\r
- if (taxonBase.isInstanceOf(Taxon.class)){\r
- Taxon taxon = CdmBase.deproxy(taxonBase, Taxon.class);\r
- // Get ancestor Taxon via TaxonNode\r
- Set<TaxonNode> taxonNodes = taxon.getTaxonNodes();\r
- if (taxonNodes.size() == 1) {\r
- TaxonNode taxonNode = taxonNodes.iterator().next();\r
- if (taxonNode != null) {\r
- for (int i = 0; i < level; i++) {\r
- if (taxonNode != null) {\r
- taxonNode = taxonNode.getParent();\r
- }\r
- }\r
- parentNode = taxonNode;\r
- }\r
- } else if (taxonNodes.size() > 1) {\r
- logger.error("This taxon has " + taxonNodes.size() + " taxonNodes: " + taxon.getUuid() + " (" + taxon.getTitleCache() + ")");\r
- }\r
- }\r
- //compare\r
- if (parentNode != null) {\r
- TaxonNode node = CdmBase.deproxy(parentNode, TaxonNode.class);\r
- Taxon parentTaxon = node.getTaxon();\r
- if (parentTaxon != null) {\r
- TaxonNameBase<?,?> parentTaxonName = parentTaxon.getName();\r
- if (parentTaxonName != null && parentTaxonName.getRank().equals(ancestorRank)) {\r
- result = true;\r
- }\r
- } else if (parentNode.treeIndex().matches("#t\\d+#\\d+#")) {\r
- //do nothing (is root node)\r
- } else {\r
- logger.error("This TaxonNode has no Taxon: " + node.getUuid());\r
- }\r
- }\r
- return result;\r
- }\r
-\r
- /**\r
- * Returns the AnnotationType for a given UUID.\r
- * @param uuid The Annotation UUID.\r
- * @param label The Annotation label.\r
- * @param text The Annotation text.\r
- * @param labelAbbrev The Annotation label abbreviation.\r
- * @return The AnnotationType.\r
- */\r
- protected AnnotationType getAnnotationType(UUID uuid, String label, String text, String labelAbbrev){\r
- AnnotationType annotationType = (AnnotationType)getTermService().find(uuid);\r
- if (annotationType == null) {\r
- annotationType = AnnotationType.NewInstance(label, text, labelAbbrev);\r
- annotationType.setUuid(uuid);\r
-// annotationType.setVocabulary(AnnotationType.EDITORIAL().getVocabulary());\r
- getTermService().save(annotationType);\r
- }\r
- return annotationType;\r
- }\r
-\r
- /**\r
- * Traverses the classification recursively and stores determined values for every Taxon.\r
- * @param childNode The {@link TaxonNode TaxonNode} to process.\r
- * @param parentNode The parent {@link TaxonNode TaxonNode} of the childNode.\r
- * @param treeIndex The TreeIndex at the current level.\r
- * @param fetchLevel Rank to stop fetching at.\r
- * @param state The {@link PesiExportState PesiExportState}.\r
- */\r
- private void traverseTree(TaxonNode childNode, TaxonNode parentNode, StringBuffer treeIndex, Rank fetchLevel, PesiExportState state) {\r
- // Traverse all branches from this childNode until specified fetchLevel is reached.\r
- StringBuffer localTreeIndex = new StringBuffer(treeIndex);\r
- Taxon childTaxon = childNode.getTaxon();\r
- if (childTaxon != null) {\r
- if (isPesiTaxon(childTaxon)){\r
- Integer taxonId = state.getDbId(childTaxon);\r
- TaxonNameBase<?,?> childName = childTaxon.getName();\r
- if (taxonId != null) {\r
- Rank childRank = childName.getRank();\r
- if (childRank != null) {\r
- if (! childRank.equals(fetchLevel)) {\r
- \r
- localTreeIndex.append(taxonId + "#");\r
- \r
- saveData(childNode, parentNode, localTreeIndex, state, taxonId);\r
- \r
- // Store treeIndex as annotation for further use\r
- Annotation annotation = Annotation.NewInstance(localTreeIndex.toString(), getTreeIndexAnnotationType(), Language.DEFAULT());\r
- childNode.addAnnotation(annotation);\r
- \r
- for (TaxonNode newNode : childNode.getChildNodes()) {\r
- if (newNode.getTaxon() != null && isPesiTaxon(newNode.getTaxon())){\r
- traverseTree(newNode, childNode, localTreeIndex, fetchLevel, state);\r
- }\r
- }\r
- \r
- } else {\r
- // logger.debug("Target Rank " + fetchLevel.getLabel() + " reached");\r
- return;\r
- }\r
- } else {\r
- logger.error("Rank is NULL. FetchLevel can not be checked: " + childName.getUuid() + " (" + childName.getTitleCache() + ")");\r
- }\r
- } else {\r
- logger.error("Taxon can not be found in state: " + childTaxon.getUuid() + " (" + childTaxon.getTitleCache() + ")");\r
- }\r
- }else{\r
- if (logger.isDebugEnabled()){ \r
- logger.debug("Taxon is not a PESI taxon: " + childTaxon.getUuid());\r
- }\r
- }\r
-\r
- } else {\r
- logger.error("Taxon is NULL for TaxonNode: " + childNode.getUuid());\r
- }\r
- }\r
-\r
- /**\r
- * Stores values in database for every recursive round.\r
- * @param childNode The {@link TaxonNode TaxonNode} to process.\r
- * @param parentNode The parent {@link TaxonNode TaxonNode} of the childNode.\r
- * @param treeIndex The TreeIndex at the current level.\r
- * @param state The {@link PesiExportState PesiExportState}.\r
- * @param currentTaxonFk The TaxonFk to store the values for.\r
- */\r
- private void saveData(TaxonNode childNode, TaxonNode parentNode, StringBuffer treeIndex, PesiExportState state, Integer currentTaxonFk) {\r
- // We are differentiating kingdoms by the nomenclatural code for now.\r
- // This needs to be handled in a better way as soon as we know how to differentiate between more kingdoms.\r
- Taxon childTaxon = childNode.getTaxon();\r
- if (isPesiTaxon(childTaxon)) {\r
- TaxonBase<?> parentTaxon = null;\r
- if (parentNode != null) {\r
- parentTaxon = parentNode.getTaxon();\r
- \r
- }\r
-\r
- invokeParentTaxonFkAndTreeIndex(state.getDbId(parentTaxon), currentTaxonFk, treeIndex);\r
- }\r
- \r
- }\r
-\r
- /**\r
- * Inserts values into the Taxon database table.\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @param state The {@link PesiExportState PesiExportState}.\r
- * @param stmt The prepared statement.\r
- * @return Whether save was successful or not.\r
- */\r
- protected boolean invokeParentTaxonFkAndTreeIndex(Integer parentTaxonFk, Integer currentTaxonFk, StringBuffer treeIndex) {\r
- try {\r
- if (parentTaxonFk != null) {\r
- parentTaxonFk_TreeIndex_KingdomFkStmt.setInt(1, parentTaxonFk);\r
- } else {\r
- parentTaxonFk_TreeIndex_KingdomFkStmt.setObject(1, null);\r
- }\r
-\r
- if (treeIndex != null) {\r
- parentTaxonFk_TreeIndex_KingdomFkStmt.setString(2, treeIndex.toString());\r
- } else {\r
- parentTaxonFk_TreeIndex_KingdomFkStmt.setObject(2, null);\r
- }\r
-\r
- if (currentTaxonFk != null) {\r
- parentTaxonFk_TreeIndex_KingdomFkStmt.setInt(3, currentTaxonFk);\r
- } else {\r
- parentTaxonFk_TreeIndex_KingdomFkStmt.setObject(3, null);\r
- }\r
- \r
- parentTaxonFk_TreeIndex_KingdomFkStmt.executeUpdate();\r
- return true;\r
- } catch (SQLException e) {\r
- logger.error("ParentTaxonFk (" + parentTaxonFk ==null? "-":parentTaxonFk + ") and TreeIndex could not be inserted into database for taxon "+ (currentTaxonFk == null? "-" :currentTaxonFk) + ": " + e.getMessage());\r
- e.printStackTrace();\r
- return false;\r
- }\r
- }\r
- \r
- protected boolean invokeParentTaxonFk(Integer parentId, Integer childId) {\r
- try {\r
- parentTaxonFkStmt.setInt(1, parentId);\r
- parentTaxonFkStmt.setInt(2, childId);\r
- parentTaxonFkStmt.executeUpdate();\r
- return true;\r
- } catch (SQLException e) {\r
- logger.warn("ParentTaxonFk (" + parentId ==null? "-":parentId + ") could not be inserted into database for taxon "+ (childId == null? "-" :childId) + ": " + e.getMessage());\r
- e.printStackTrace();\r
- return false;\r
- }\r
- }\r
-\r
-\r
- /**\r
- * Inserts Rank data and KingdomFk into the Taxon database table.\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.\r
- * @param taxonFk The TaxonFk to store the values for.\r
- * @param state \r
- * @param kindomFk The KingdomFk.\r
- * @return Whether save was successful or not.\r
- */\r
- private boolean invokeRankDataAndKingdomFk(TaxonNameBase<?,?> taxonName, NomenclaturalCode nomenclaturalCode, Integer taxonFk, Integer kingdomFk, PesiExportState state) {\r
- try {\r
- Integer rankFk = getRankFk(taxonName, nomenclaturalCode);\r
- if (rankFk != null) {\r
- rankUpdateStmt.setInt(1, rankFk);\r
- } else {\r
- rankUpdateStmt.setObject(1, null);\r
- }\r
- \r
- String rankCache = getRankCache(taxonName, nomenclaturalCode, state);\r
- if (rankCache != null) {\r
- rankUpdateStmt.setString(2, rankCache);\r
- } else {\r
- rankUpdateStmt.setObject(2, null);\r
- }\r
- \r
- if (kingdomFk != null) {\r
- rankUpdateStmt.setInt(3, kingdomFk);\r
- } else {\r
- rankUpdateStmt.setObject(3, null);\r
- }\r
- \r
- if (taxonFk != null) {\r
- rankUpdateStmt.setInt(4, taxonFk);\r
- } else {\r
- rankUpdateStmt.setObject(4, null);\r
- }\r
- \r
- rankUpdateStmt.executeUpdate();\r
- return true;\r
- } catch (SQLException e) {\r
- logger.error("Data (RankFk, RankCache, KingdomFk) could not be inserted into database: " + e.getMessage());\r
- e.printStackTrace();\r
- return false;\r
- }\r
- }\r
-\r
- /**\r
- * Inserts Rank data, TypeNameFk, KingdomFk, expertFk and speciesExpertFk into the Taxon database table.\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.\r
- * @param taxonFk The TaxonFk to store the values for.\r
- * @param typeNameFk The TypeNameFk.\r
- * @param state \r
- * @param kindomFk The KingdomFk.\r
- * @param expertFk The ExpertFk.\r
- * @param speciesExpertFk The SpeciesExpertFk.\r
- * @return Whether save was successful or not.\r
- */\r
- private boolean invokeRankDataAndTypeNameFkAndKingdomFk(TaxonNameBase<?,?> taxonName, NomenclaturalCode nomenclaturalCode, \r
- Integer taxonFk, Integer typeNameFk, Integer kingdomFkk, PesiExportState state) {\r
- try {\r
- int index = 1;\r
- Integer rankFk = getRankFk(taxonName, nomenclaturalCode);\r
- if (rankFk != null) {\r
- rankTypeExpertsUpdateStmt.setInt(index++, rankFk);\r
- } else {\r
- rankTypeExpertsUpdateStmt.setObject(index++, null);\r
- }\r
- \r
- String rankCache = getRankCache(taxonName, nomenclaturalCode, state);\r
- if (rankCache != null) {\r
- rankTypeExpertsUpdateStmt.setString(index++, rankCache);\r
- } else {\r
- rankTypeExpertsUpdateStmt.setObject(index++, null);\r
- }\r
- \r
- if (typeNameFk != null) {\r
- rankTypeExpertsUpdateStmt.setInt(index++, typeNameFk);\r
- } else {\r
- rankTypeExpertsUpdateStmt.setObject(index++, null);\r
- }\r
- \r
- if (kingdomFk != null) {\r
- rankTypeExpertsUpdateStmt.setInt(index++, kingdomFk);\r
- } else {\r
- rankTypeExpertsUpdateStmt.setObject(index++, null);\r
- }\r
- \r
-// if (expertFk != null) {\r
-// rankTypeExpertsUpdateStmt.setInt(5, expertFk);\r
-// } else {\r
-// rankTypeExpertsUpdateStmt.setObject(5, null);\r
-// }\r
-//\r
-// //TODO handle experts GUIDS\r
-// if (speciesExpertFk != null) {\r
-// rankTypeExpertsUpdateStmt.setInt(6, speciesExpertFk);\r
-// } else {\r
-// rankTypeExpertsUpdateStmt.setObject(6, null);\r
-// }\r
-// \r
- if (taxonFk != null) {\r
- rankTypeExpertsUpdateStmt.setInt(index++, taxonFk);\r
- } else {\r
- rankTypeExpertsUpdateStmt.setObject(index++, null);\r
- }\r
-\r
- rankTypeExpertsUpdateStmt.executeUpdate();\r
- return true;\r
- } catch (SQLException e) {\r
- logger.error("Data could not be inserted into database: " + e.getMessage());\r
- e.printStackTrace();\r
- return false;\r
- } catch (Exception e) {\r
- logger.error("Some exception occurred: " + e.getMessage());\r
- e.printStackTrace();\r
- return false;\r
- }\r
- }\r
-\r
- /**\r
- * Deletes all entries of database tables related to <code>Taxon</code>.\r
- * @param state The {@link PesiExportState PesiExportState}.\r
- * @return Whether the delete operation was successful or not.\r
- */\r
- protected boolean doDelete(PesiExportState state) {\r
- PesiExportConfigurator pesiConfig = (PesiExportConfigurator) state.getConfig();\r
- \r
- String sql;\r
- Source destination = pesiConfig.getDestination();\r
-\r
- // Clear Taxon\r
- sql = "DELETE FROM " + dbTableName;\r
- destination.setQuery(sql);\r
- destination.update(sql);\r
- return true;\r
- }\r
-\r
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.io.common.CdmIoBase#isIgnore(eu.etaxonomy.cdm.io.common.IoStateBase)\r
- */\r
- @Override\r
- protected boolean isIgnore(PesiExportState state) {\r
- return ! state.getConfig().isDoTaxa();\r
- }\r
-\r
- \r
- /**\r
- * Creates the kingdom fk.\r
- * @param taxonName\r
- * @return\r
- */\r
- @SuppressWarnings("unused") //used by mapper\r
- private static Integer getKingdomFk(TaxonNameBase taxonName){\r
- return PesiTransformer.nomenClaturalCode2Kingdom(taxonName.getNomenclaturalCode());\r
- }\r
- \r
- /**\r
- * Creates the parent fk.\r
- * @param taxonName\r
- * @return\r
- */\r
- @SuppressWarnings("unused") //used by mapper\r
- private static Integer getParentTaxonFk(TaxonBase<?> taxonBase, PesiExportState state){\r
- if (taxonBase.isInstanceOf(Taxon.class)){\r
- Taxon taxon = CdmBase.deproxy(taxonBase, Taxon.class);\r
- if (! isMisappliedName(taxon)){\r
- Set<TaxonNode> nodes = taxon.getTaxonNodes();\r
- if (nodes.size() == 0){\r
- if (taxon.getName().getRank().isLower(Rank.KINGDOM())){\r
- logger.warn("Accepted taxon has no parent. " + taxon.getTitleCache() + ", " + taxon.getUuid());\r
- }\r
- }else if (nodes.size() > 1){\r
- logger.warn("Taxon has more than 1 node attached. This is not supported by PESI export." + taxon.getTitleCache() + ", " + taxon.getUuid());\r
- }else{\r
- Taxon parent =nodes.iterator().next().getParent().getTaxon();\r
- return state.getDbId(parent);\r
- }\r
- }\r
- }\r
- return null;\r
- }\r
-\r
- /**\r
- * Returns the rankFk for the taxon name based on the names nomenclatural code.\r
- * You may not use this method for kingdoms other then Animalia, Plantae and Bacteria.\r
- * @param taxonName\r
- * @return\r
- */\r
- @SuppressWarnings("unused") //used by mapper\r
- private static Integer getRankFk(TaxonNameBase<?,?> taxonName) {\r
- return getRankFk(taxonName, taxonName.getNomenclaturalCode());\r
- }\r
- \r
- \r
- /**\r
- * Returns the <code>RankFk</code> attribute.\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.\r
- * @return The <code>RankFk</code> attribute.\r
- * @see MethodMapper\r
- */\r
- private static Integer getRankFk(TaxonNameBase<?,?> taxonName, NomenclaturalCode nomenclaturalCode) {\r
- Integer result = null;\r
- try {\r
- if (nomenclaturalCode != null) {\r
- if (taxonName != null) {\r
- if (taxonName.getRank() == null) {\r
- logger.warn("Rank is null: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");\r
- } else {\r
- result = PesiTransformer.rank2RankId(taxonName.getRank(), PesiTransformer.nomenClaturalCode2Kingdom(nomenclaturalCode));\r
- }\r
- if (result == null) {\r
- logger.warn("Rank could not be determined for PESI-Kingdom-Id " + PesiTransformer.nomenClaturalCode2Kingdom(nomenclaturalCode) + " and TaxonName " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");\r
- }\r
- }\r
- }\r
- } catch (Exception e) {\r
- e.printStackTrace();\r
- }\r
- return result;\r
- }\r
-\r
- /**\r
- * Returns the rank cache for the taxon name based on the names nomenclatural code.\r
- * You may not use this method for kingdoms other then Animalia, Plantae and Bacteria.\r
- * @param taxonName\r
- * @return\r
- */\r
- @SuppressWarnings("unused") //used by mapper\r
- private static String getRankCache(TaxonNameBase<?,?> taxonName, PesiExportState state) {\r
- return getRankCache(taxonName, taxonName.getNomenclaturalCode(), state);\r
- }\r
-\r
- \r
- /**\r
- * Returns the <code>RankCache</code> attribute.\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.\r
- * @param state \r
- * @return The <code>RankCache</code> attribute.\r
- * @see MethodMapper\r
- */\r
- private static String getRankCache(TaxonNameBase<?,?> taxonName, NomenclaturalCode nomenclaturalCode, PesiExportState state) {\r
- if (nomenclaturalCode != null) {\r
- return state.getTransformer().getCacheByRankAndKingdom(taxonName.getRank(), PesiTransformer.nomenClaturalCode2Kingdom(nomenclaturalCode));\r
- }else{\r
- logger.warn("No nomenclatural code defined for name " + taxonName.getUuid());\r
- return null;\r
- }\r
- \r
- }\r
-\r
- \r
- /**\r
- * Returns the <code>DisplayName</code> attribute.\r
- * @param taxon The {@link TaxonBase Taxon}.\r
- * @return The <code>DisplayName</code> attribute.\r
- * @see MethodMapper\r
- */\r
- @SuppressWarnings("unused") //used by Mapper\r
- private static String getDisplayName(TaxonBase<?> taxon) {\r
- TaxonNameBase<?,?> taxonName = taxon.getName();\r
- String result = getDisplayName(taxonName);\r
- if (isMisappliedName(taxon)){\r
- result = result + " " + getAuthorString(taxon);\r
- }\r
- return result;\r
- }\r
- \r
- /**\r
- * Returns the <code>AuthorString</code> attribute.\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @return The <code>AuthorString</code> attribute.\r
- * @see MethodMapper\r
- */\r
- @SuppressWarnings("unused") //used by mapper\r
- protected static String getAuthorString(TaxonBase<?> taxon) {\r
- try {\r
- String result = null;\r
- boolean isNonViralName = false;\r
- String authorshipCache = null;\r
- TaxonNameBase<?,?> taxonName = taxon.getName();\r
- if (taxonName != null && taxonName.isInstanceOf(NonViralName.class)){\r
- authorshipCache = CdmBase.deproxy(taxonName, NonViralName.class).getAuthorshipCache();\r
- isNonViralName = true;\r
- }\r
- result = authorshipCache;\r
- \r
- // For a misapplied names there are special rules\r
- if (isMisappliedName(taxon)){\r
- if (taxon.getSec() != null){\r
- String secTitle = taxon.getSec().getTitleCache();\r
- if (! secTitle.startsWith("auct")){\r
- secTitle = "sensu " + secTitle;\r
- }else if (secTitle.equals("auct")){ //may be removed once the title cache is generated correctly for references with title auct. #\r
- secTitle = "auct.";\r
- }\r
- return secTitle;\r
- }else if (StringUtils.isBlank(authorshipCache)) {\r
- // Set authorshipCache to "auct."\r
- result = PesiTransformer.AUCT_STRING;\r
- }else{\r
- result = PesiTransformer.AUCT_STRING;\r
-// result = authorshipCache;\r
- }\r
- }\r
- \r
- if (taxonName == null){\r
- logger.warn("TaxonName does not exist for taxon: " + taxon.getUuid() + " (" + taxon.getTitleCache() + ")");\r
- }else if (! isNonViralName){\r
- logger.warn("TaxonName is not of instance NonViralName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");\r
- }\r
- \r
- if (StringUtils.isBlank(result)) {\r
- return null;\r
- } else {\r
- return result;\r
- }\r
- } catch (Exception e) {\r
- e.printStackTrace();\r
- return null;\r
- }\r
- \r
- }\r
- \r
- \r
- /**\r
- * Returns the <code>DisplayName</code> attribute.\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @return The <code>DisplayName</code> attribute.\r
- * @see MethodMapper\r
- */\r
- @SuppressWarnings("unused") //used by Mapper\r
- private static String getDisplayName(TaxonNameBase<?,?> taxonName) {\r
- // TODO: extension?\r
- if (taxonName == null) {\r
- return null;\r
- }else{\r
- INonViralNameCacheStrategy<NonViralName<?>> cacheStrategy = getCacheStrategy(taxonName);\r
- HTMLTagRules tagRules = new HTMLTagRules().\r
- addRule(TagEnum.name, "i").\r
- addRule(TagEnum.nomStatus, "@status@");\r
- \r
- NonViralName<?> nvn = CdmBase.deproxy(taxonName, NonViralName.class);\r
- String result = cacheStrategy.getFullTitleCache(nvn, tagRules);\r
- cacheStrategy = null;\r
- nvn = null;\r
- return result.replaceAll(",?\\<@status@\\>.*\\</@status@\\>", "");\r
- }\r
- }\r
- \r
-\r
- /**\r
- * Returns the <code>WebShowName</code> attribute for a taxon.\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @return The <code>WebShowName</code> attribute.\r
- * @see MethodMapper\r
- */\r
- @SuppressWarnings("unused")\r
- private static String getWebShowName(TaxonBase<?> taxon) {\r
- TaxonNameBase<?,?> taxonName = taxon.getName();\r
- String result = getWebShowName(taxonName);\r
- if (isMisappliedName(taxon)){\r
- result = result + " " + getAuthorString(taxon);\r
- }\r
- return result;\r
- }\r
- \r
- /**\r
- * Returns the <code>WebShowName</code> attribute.\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @return The <code>WebShowName</code> attribute.\r
- * @see MethodMapper\r
- */\r
- private static String getWebShowName(TaxonNameBase<?,?> taxonName) {\r
- //TODO extensions?\r
- if (taxonName == null) {\r
- return null;\r
- }else{\r
- INonViralNameCacheStrategy<NonViralName<?>> cacheStrategy = getCacheStrategy(taxonName);\r
- \r
- HTMLTagRules tagRules = new HTMLTagRules().addRule(TagEnum.name, "i");\r
- NonViralName<?> nvn = CdmBase.deproxy(taxonName, NonViralName.class);\r
- String result = cacheStrategy.getTitleCache(nvn, tagRules);\r
- cacheStrategy = null;\r
- nvn = null;\r
- return result;\r
- }\r
- }\r
-\r
- \r
- /**\r
- * Returns the <code>WebSearchName</code> attribute.\r
- * @param taxonName The {@link NonViralName NonViralName}.\r
- * @return The <code>WebSearchName</code> attribute.\r
- * @see MethodMapper\r
- */\r
- @SuppressWarnings("unused")\r
- private static String getWebSearchName(TaxonNameBase<?,?> taxonName) {\r
- //TODO extensions?\r
- NonViralName<?> nvn = CdmBase.deproxy(taxonName, NonViralName.class);\r
- NonViralNameDefaultCacheStrategy<NonViralName<?>> strategy = getCacheStrategy(nvn);\r
- String result = strategy.getNameCache(nvn);\r
- strategy = null;\r
- nvn = null;\r
- return result;\r
- }\r
-\r
-\r
- /**\r
- * Returns the <code>FullName</code> attribute.\r
- * @param taxonName The {@link NonViralName NonViralName}.\r
- * @return The <code>FullName</code> attribute.\r
- * @see MethodMapper\r
- */\r
- @SuppressWarnings("unused")\r
- private static String getFullName(TaxonNameBase taxonName) {\r
- //TODO extensions?\r
- NonViralName<?> nvn = CdmBase.deproxy(taxonName, NonViralName.class);\r
- String result = getCacheStrategy(nvn).getTitleCache(nvn);\r
- Iterator<TaxonBase> taxa = taxonName.getTaxa().iterator();\r
- if (taxonName.getTaxa().size() >0){\r
- if (taxonName.getTaxa().size() == 1){\r
- TaxonBase taxon = taxa.next();\r
- if (isMisappliedName(taxon)){\r
- result = result + " " + getAuthorString(taxon);\r
- }\r
- taxon = null;\r
- }\r
- }\r
- taxa = null;\r
- nvn = null;\r
- return result;\r
- }\r
- \r
- /**\r
- * Returns the <code>FullName</code> attribute.\r
- * @param taxon The {@link TaxonBase taxon}.\r
- * @return The <code>FullName</code> attribute.\r
- * @see MethodMapper\r
- */\r
- /*@SuppressWarnings("unused")\r
- private static String getFullName(TaxonBase taxon) {\r
- //TODO extensions?\r
- TaxonNameBase name = taxon.getName();\r
- String result = getFullName(name);\r
- if (isMisappliedName(taxon)){\r
- result = result + " " + getAuthorString(taxon);\r
- }\r
- \r
- return result;\r
- }\r
-*/\r
- \r
- /**\r
- * Returns the nomenclatural reference which is the reference\r
- * including the detail (microreference).\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @return The <code>AuthorString</code> attribute.\r
- * @see MethodMapper\r
- */\r
- @SuppressWarnings("unused")\r
- private static String getNomRefString(TaxonNameBase<?,?> taxonName) {\r
- INomenclaturalReference ref = taxonName.getNomenclaturalReference();\r
- return ref == null ? null : ref.getNomenclaturalCitation(taxonName.getNomenclaturalMicroReference());\r
- }\r
- \r
-\r
- /**\r
- * Returns the <code>NameStatusFk</code> attribute.\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @return The <code>NameStatusFk</code> attribute.\r
- * @see MethodMapper\r
- */\r
- @SuppressWarnings("unused")\r
- private static Integer getNameStatusFk(TaxonNameBase<?,?> taxonName) {\r
- Integer result = null;\r
-\r
- NomenclaturalStatus state = getNameStatus(taxonName);\r
- if (state != null) {\r
- result = PesiTransformer.nomStatus2nomStatusFk(state.getType());\r
- }\r
- return result;\r
- }\r
- \r
- /**\r
- * Returns the <code>NameStatusCache</code> attribute.\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @return The <code>NameStatusCache</code> attribute.\r
- * @throws UndefinedTransformerMethodException \r
- * @see MethodMapper\r
- */\r
- @SuppressWarnings("unused")\r
- private static String getNameStatusCache(TaxonNameBase taxonName, PesiExportState state) throws UndefinedTransformerMethodException {\r
- String result = null;\r
- NomenclaturalStatus status = getNameStatus(taxonName);\r
- if (status != null) {\r
- result = state.getTransformer().getCacheByNomStatus(status.getType());\r
- }\r
- return result;\r
- }\r
- \r
- \r
- private static NomenclaturalStatus getNameStatus(TaxonNameBase<?,?> taxonName) {\r
- try {\r
- if (taxonName != null && (taxonName.isInstanceOf(NonViralName.class))) {\r
- NonViralName<?> nonViralName = CdmBase.deproxy(taxonName, NonViralName.class);\r
- Set<NomenclaturalStatus> states = nonViralName.getStatus();\r
- if (states.size() == 1) {\r
- NomenclaturalStatus status = states.iterator().next();\r
- return status;\r
- } else if (states.size() > 1) {\r
- logger.error("This TaxonName has more than one Nomenclatural Status: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");\r
- }\r
- }\r
- \r
- } catch (Exception e) {\r
- e.printStackTrace();\r
- }\r
- return null;\r
- }\r
- /**\r
- * Returns the <code>TaxonStatusFk</code> attribute.\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @param state The {@link PesiExportState PesiExportState}.\r
- * @return The <code>TaxonStatusFk</code> attribute.\r
- * @see MethodMapper\r
- */\r
- private static Integer getTaxonStatusFk(TaxonBase<?> taxon, PesiExportState state) {\r
- Integer result = null;\r
- \r
- try {\r
- if (isMisappliedName(taxon)) {\r
- Synonym synonym = Synonym.NewInstance(null, null);\r
- \r
- // This works as long as only the instance is important to differentiate between TaxonStatus.\r
- result = PesiTransformer.taxonBase2statusFk(synonym); // Auct References are treated as Synonyms in Datawarehouse now.\r
- } else {\r
- result = PesiTransformer.taxonBase2statusFk(taxon);\r
- }\r
- \r
- } catch (Exception e) {\r
- e.printStackTrace();\r
- }\r
- return result;\r
- }\r
- \r
- /**\r
- * Returns the <code>TaxonStatusCache</code> attribute.\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @param state The {@link PesiExportState PesiExportState}.\r
- * @return The <code>TaxonStatusCache</code> attribute.\r
- * @throws UndefinedTransformerMethodException \r
- * @see MethodMapper\r
- */\r
- @SuppressWarnings("unused")\r
- private static String getTaxonStatusCache(TaxonBase<?> taxon, PesiExportState state) throws UndefinedTransformerMethodException {\r
- return state.getTransformer().getTaxonStatusCacheByKey(getTaxonStatusFk(taxon, state));\r
- }\r
- \r
- /**\r
- * Returns the <code>TypeNameFk</code> attribute.\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @param state The {@link PesiExportState PesiExportState}.\r
- * @return The <code>TypeNameFk</code> attribute.\r
- * @see MethodMapper\r
- */\r
- private static Integer getTypeNameFk(TaxonNameBase<?,?> taxonNameBase, PesiExportState state) {\r
- Integer result = null;\r
- if (taxonNameBase != null) {\r
- Set<NameTypeDesignation> nameTypeDesignations = taxonNameBase.getNameTypeDesignations();\r
- if (nameTypeDesignations.size() == 1) {\r
- NameTypeDesignation nameTypeDesignation = nameTypeDesignations.iterator().next();\r
- if (nameTypeDesignation != null) {\r
- TaxonNameBase<?,?> typeName = nameTypeDesignation.getTypeName();\r
- if (typeName != null) {\r
- result = state.getDbId(typeName);\r
- }\r
- }\r
- } else if (nameTypeDesignations.size() > 1) {\r
- logger.warn("This TaxonName has " + nameTypeDesignations.size() + " NameTypeDesignations: " + taxonNameBase.getUuid() + " (" + taxonNameBase.getTitleCache() + ")");\r
- }\r
- }\r
- return result;\r
- }\r
- \r
- /**\r
- * Returns the <code>TypeFullnameCache</code> attribute.\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @return The <code>TypeFullnameCache</code> attribute.\r
- * @see MethodMapper\r
- */\r
- @SuppressWarnings("unused")\r
- private static String getTypeFullnameCache(TaxonNameBase<?,?> taxonName) {\r
- String result = null;\r
- \r
- try {\r
- if (taxonName != null) {\r
- Set<NameTypeDesignation> nameTypeDesignations = taxonName.getNameTypeDesignations();\r
- if (nameTypeDesignations.size() == 1) {\r
- NameTypeDesignation nameTypeDesignation = nameTypeDesignations.iterator().next();\r
- if (nameTypeDesignation != null) {\r
- TaxonNameBase<?,?> typeName = nameTypeDesignation.getTypeName();\r
- if (typeName != null) {\r
- result = typeName.getTitleCache();\r
- }\r
- }\r
- } else if (nameTypeDesignations.size() > 1) {\r
- logger.warn("This TaxonName has " + nameTypeDesignations.size() + " NameTypeDesignations: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");\r
- }\r
- }\r
- \r
- } catch (Exception e) {\r
- e.printStackTrace();\r
- }\r
- return result;\r
- }\r
-\r
- \r
- /**\r
- * Returns the <code>QualityStatusFk</code> attribute.\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @return The <code>QualityStatusFk</code> attribute.\r
- * @see MethodMapper\r
- */\r
- private static Integer getQualityStatusFk(TaxonNameBase taxonName) {\r
- BitSet sources = getSources(taxonName);\r
- return PesiTransformer.getQualityStatusKeyBySource(sources, taxonName);\r
- }\r
-\r
- \r
- /**\r
- * Returns the <code>QualityStatusCache</code> attribute.\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @return The <code>QualityStatusCache</code> attribute.\r
- * @throws UndefinedTransformerMethodException \r
- * @see MethodMapper\r
- */\r
- @SuppressWarnings("unused")\r
- private static String getQualityStatusCache(TaxonNameBase taxonName, PesiExportState state) throws UndefinedTransformerMethodException {\r
- return state.getTransformer().getQualityStatusCacheByKey(getQualityStatusFk(taxonName));\r
- }\r
-\r
- \r
- /**\r
- * Returns the <code>TypeDesignationStatusFk</code> attribute.\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @return The <code>TypeDesignationStatusFk</code> attribute.\r
- * @see MethodMapper\r
- */\r
- @SuppressWarnings("unused")\r
- private static Integer getTypeDesignationStatusFk(TaxonNameBase<?,?> taxonName) {\r
- Integer result = null;\r
- \r
- try {\r
- if (taxonName != null) {\r
- Set<NameTypeDesignation> typeDesignations = taxonName.getNameTypeDesignations();\r
- if (typeDesignations.size() == 1) {\r
- Object obj = typeDesignations.iterator().next().getTypeStatus();\r
- NameTypeDesignationStatus designationStatus = CdmBase.deproxy(obj, NameTypeDesignationStatus.class);\r
- result = PesiTransformer.nameTypeDesignationStatus2TypeDesignationStatusId(designationStatus);\r
- } else if (typeDesignations.size() > 1) {\r
- logger.error("Found a TaxonName with more than one NameTypeDesignation: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");\r
- }\r
- }\r
- \r
- } catch (Exception e) {\r
- e.printStackTrace();\r
- }\r
- return result;\r
- }\r
-\r
- /**\r
- * Returns the <code>TypeDesignationStatusCache</code> attribute.\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @return The <code>TypeDesignationStatusCache</code> attribute.\r
- * @see MethodMapper\r
- */\r
- @SuppressWarnings("unused")\r
- private static String getTypeDesignationStatusCache(TaxonNameBase<?,?> taxonName) {\r
- String result = null;\r
- \r
- try {\r
- if (taxonName != null) {\r
- Set<NameTypeDesignation> typeDesignations = taxonName.getNameTypeDesignations();\r
- if (typeDesignations.size() == 1) {\r
- Object obj = typeDesignations.iterator().next().getTypeStatus();\r
- NameTypeDesignationStatus designationStatus = CdmBase.deproxy(obj, NameTypeDesignationStatus.class);\r
- result = PesiTransformer.nameTypeDesignationStatus2TypeDesignationStatusCache(designationStatus);\r
- } else if (typeDesignations.size() > 1) {\r
- logger.error("Found a TaxonName with more than one NameTypeDesignation: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");\r
- }\r
- }\r
- \r
- } catch (Exception e) {\r
- e.printStackTrace();\r
- }\r
- return result;\r
- }\r
- \r
- /**\r
- * Returns the <code>FossilStatusFk</code> attribute.\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @return The <code>FossilStatusFk</code> attribute.\r
- * @see MethodMapper\r
- */\r
- @SuppressWarnings("unused")\r
- private static Integer getFossilStatusFk(IdentifiableEntity<?> identEntity, PesiExportState state) {\r
- Integer result = null;\r
- \r
- Set<String> fossilStatuus = identEntity.getExtensions(ErmsTransformer.uuidFossilStatus);\r
- if (fossilStatuus.size() == 0){\r
- return null;\r
- }else if (fossilStatuus.size() > 1){\r
- logger.warn("More than 1 fossil status given for " + identEntity.getTitleCache() + " " + identEntity.getUuid());\r
- }\r
- String fossilStatus = fossilStatuus.iterator().next();\r
- \r
- int statusFk = state.getTransformer().FossilStatusCache2FossilStatusFk(fossilStatus);\r
- return statusFk;\r
- }\r
- \r
- /**\r
- * Returns the <code>FossilStatusCache</code> attribute.\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @return The <code>FossilStatusCache</code> attribute.\r
- * @see MethodMapper\r
- */\r
- @SuppressWarnings("unused")\r
- private static String getFossilStatusCache(IdentifiableEntity<?> identEntity, PesiExportState state) {\r
- String result = null;\r
- Set<String> fossilStatuus = identEntity.getExtensions(ErmsTransformer.uuidFossilStatus);\r
- if (fossilStatuus.size() == 0){\r
- return null;\r
- }\r
- for (String strFossilStatus : fossilStatuus){\r
- result = CdmUtils.concat(";", result, strFossilStatus);\r
- }\r
- return result;\r
- }\r
- \r
- /**\r
- * Returns the <code>IdInSource</code> attribute.\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @return The <code>IdInSource</code> attribute.\r
- * @see MethodMapper\r
- */\r
- @SuppressWarnings("unused")\r
- private static String getIdInSource(IdentifiableEntity taxonName) {\r
- String result = null;\r
- \r
- try {\r
- Set<IdentifiableSource> sources = getPesiSources(taxonName);\r
- if (sources.size() > 1){\r
- logger.warn("There is > 1 Pesi source. This is not yet handled.");\r
- }\r
- if (sources.size() == 0){\r
- logger.warn("There is no Pesi source!" +taxonName.getUuid() + " (" + taxonName.getTitleCache() +")");\r
- }\r
- for (IdentifiableSource source : sources) {\r
- Reference<?> ref = source.getCitation();\r
- UUID refUuid = ref.getUuid();\r
- String idInSource = source.getIdInSource();\r
- if (refUuid.equals(BerlinModelTransformer.uuidSourceRefEuroMed)){\r
- result = idInSource != null ? ("NameId: " + source.getIdInSource()) : null;\r
- }else if (refUuid.equals(PesiTransformer.uuidSourceRefFaunaEuropaea)){\r
- result = idInSource != null ? ("TAX_ID: " + source.getIdInSource()) : null;\r
- }else if (refUuid.equals(PesiTransformer.uuidSourceRefErms)){\r
- result = idInSource != null ? ("tu_id: " + source.getIdInSource()) : null;\r
- }else if (refUuid.equals(PesiTransformer.uuidSourceRefIndexFungorum)){ //Index Fungorum\r
- result = idInSource != null ? ("if_id: " + source.getIdInSource()) : null;\r
- }else{\r
- if (logger.isDebugEnabled()){logger.debug("Not a PESI source");};\r
- }\r
- \r
- String sourceIdNameSpace = source.getIdNamespace();\r
- if (sourceIdNameSpace != null) {\r
- if (sourceIdNameSpace.equals(PesiTransformer.STR_NAMESPACE_NOMINAL_TAXON)) {\r
- result = idInSource != null ? ("Nominal Taxon from TAX_ID: " + source.getIdInSource()):null;\r
- } else if (sourceIdNameSpace.equals(TaxonServiceImpl.INFERRED_EPITHET_NAMESPACE)) {\r
- result = idInSource != null ? ("Inferred epithet from TAX_ID: " + source.getIdInSource()) : null;\r
- } else if (sourceIdNameSpace.equals(TaxonServiceImpl.INFERRED_GENUS_NAMESPACE)) {\r
- result = idInSource != null ? ("Inferred genus from TAX_ID: " + source.getIdInSource()):null;\r
- } else if (sourceIdNameSpace.equals(TaxonServiceImpl.POTENTIAL_COMBINATION_NAMESPACE)) {\r
- result = idInSource != null ? ("Potential combination from TAX_ID: " + source.getIdInSource()):null;\r
- } \r
- }\r
- if (result == null) {\r
- logger.warn("IdInSource is NULL for this taxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() +", sourceIdNameSpace: " + source.getIdNamespace()+")");\r
- }\r
- }\r
- } catch (Exception e) {\r
- e.printStackTrace();\r
- logger.error("An error occurs while creating idInSource..." + taxonName.getUuid() + " (" + taxonName.getTitleCache()+ e.getMessage());\r
- }\r
-\r
- if (result == null) {\r
- logger.warn("IdInSource is NULL for this taxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() +")");\r
- }\r
- return result;\r
- }\r
- \r
- /**\r
- * Returns the idInSource for a given TaxonName only.\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @return The idInSource.\r
- */\r
- private static String getIdInSourceOnly(IdentifiableEntity identEntity) {\r
- String result = null;\r
- \r
- // Get the sources first\r
- Set<IdentifiableSource> sources = getPesiSources(identEntity);\r
-\r
- // Determine the idInSource\r
- if (sources.size() == 1) {\r
- IdentifiableSource source = sources.iterator().next();\r
- if (source != null) {\r
- result = source.getIdInSource();\r
- }\r
- } else if (sources.size() > 1) {\r
- int count = 1;\r
- result = "";\r
- for (IdentifiableSource source : sources) {\r
- result += source.getIdInSource();\r
- if (count < sources.size()) {\r
- result += "; ";\r
- }\r
- count++;\r
- }\r
-\r
- }\r
- \r
- return result;\r
- }\r
- \r
- /**\r
- * Returns the Sources for a given TaxonName only.\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @return The Sources.\r
- */\r
- private static Set<IdentifiableSource> getPesiSources(IdentifiableEntity identEntity) {\r
- Set<IdentifiableSource> sources = new java.util.HashSet<IdentifiableSource>();\r
-\r
- //Taxon Names\r
- if (identEntity.isInstanceOf(TaxonNameBase.class)){\r
- // Sources from TaxonName\r
- TaxonNameBase taxonName = CdmBase.deproxy(identEntity, TaxonNameBase.class);\r
- Set<IdentifiableSource> testSources = identEntity.getSources();\r
- sources = filterPesiSources(identEntity.getSources());\r
- \r
- if (sources.size() == 0 && testSources.size()>0){\r
- IdentifiableSource source = testSources.iterator().next();\r
- logger.warn("There are sources, but they are no pesi sources!!!" + source.getIdInSource() + " - " + source.getIdNamespace() + " - " + source.getCitation().getTitleCache());\r
- }\r
- if (sources.size() > 1) {\r
- logger.warn("This TaxonName has more than one Source: " + identEntity.getUuid() + " (" + identEntity.getTitleCache() + ")");\r
- }\r
- \r
- // name has no PESI source, take sources from TaxonBase\r
- if (sources == null || sources.isEmpty()) {\r
- Set<TaxonBase> taxa = taxonName.getTaxonBases();\r
- for (TaxonBase taxonBase: taxa){\r
- sources.addAll(filterPesiSources(taxonBase.getSources()));\r
- }\r
- }\r
-\r
- //for TaxonBases\r
- }else if (identEntity.isInstanceOf(TaxonBase.class)){\r
- sources = filterPesiSources(identEntity.getSources()); \r
- }\r
-\r
- /*TODO: deleted only for testing the inferred synonyms \r
- if (sources == null || sources.isEmpty()) {\r
- logger.warn("This TaxonName has no PESI Sources: " + identEntity.getUuid() + " (" + identEntity.getTitleCache() +")");\r
- }else if (sources.size() > 1){\r
- logger.warn("This Taxon(Name) has more than 1 PESI source: " + identEntity.getUuid() + " (" + identEntity.getTitleCache() +")");\r
- }\r
- */\r
- return sources;\r
- }\r
- \r
- // return all sources with a PESI reference \r
- private static Set<IdentifiableSource> filterPesiSources(Set<? extends IdentifiableSource> sources) {\r
- Set<IdentifiableSource> result = new HashSet<IdentifiableSource>();\r
- for (IdentifiableSource source : sources){\r
- Reference ref = source.getCitation();\r
- UUID refUuid = ref.getUuid();\r
- if (refUuid.equals(BerlinModelTransformer.uuidSourceRefEuroMed) || \r
- refUuid.equals(PesiTransformer.uuidSourceRefFaunaEuropaea)||\r
- refUuid.equals(PesiTransformer.uuidSourceRefErms)||\r
- refUuid.equals(PesiTransformer.uuidSourceRefIndexFungorum) ||\r
- refUuid.equals(PesiTransformer.uuidSourceRefAuct)){\r
- result.add(source);\r
- }\r
- }\r
- return result;\r
- }\r
-\r
- /**\r
- * Returns the <code>GUID</code> attribute.\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @return The <code>GUID</code> attribute.\r
- * @see MethodMapper\r
- */\r
- private static String getGUID(TaxonBase<?> taxon) {\r
- if (taxon.getLsid() != null ){\r
- return taxon.getLsid().getLsid();\r
- }else if (taxon.hasMarker(PesiTransformer.uuidMarkerGuidIsMissing, true)){\r
- return null;\r
- }else{\r
- return taxon.getUuid().toString();\r
- }\r
- }\r
- \r
- \r
- \r
- \r
- /**\r
- * Returns the <code>DerivedFromGuid</code> attribute.\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @return The <code>DerivedFromGuid</code> attribute.\r
- * @see MethodMapper\r
- */\r
- @SuppressWarnings("unused")\r
- private static String getDerivedFromGuid(TaxonBase<?> taxon) {\r
- String result = null;\r
- try {\r
- // The same as GUID for now\r
- result = getGUID(taxon);\r
- } catch (Exception e) {\r
- e.printStackTrace();\r
- }\r
- return result;\r
- }\r
- \r
- /**\r
- * Returns the <code>CacheCitation</code> attribute.\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @return The CacheCitation.\r
- * @see MethodMapper\r
- */\r
- @SuppressWarnings("unused")\r
- private static String getCacheCitation(TaxonBase taxon) {\r
- // !!! See also doPhaseUpdates\r
- \r
- TaxonNameBase<?,?> taxonName = taxon.getName();\r
- String result = "";\r
- //TODO implement anew for taxa\r
- try {\r
- BitSet sources = getSources(taxonName);\r
- if (sources.isEmpty()) {\r
-// logger.error("OriginalDB is NULL for this TaxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");\r
- } else if (sources.get(PesiTransformer.SOURCE_ERMS)) {\r
- // 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...\r
- // So the following code is some kind of harmless assumption.\r
- Set<Extension> extensions = taxonName.getExtensions();\r
- for (Extension extension : extensions) {\r
- if (extension.getType().equals(cacheCitationExtensionType)) {\r
- result = extension.getValue();\r
- }\r
- }\r
- } else {\r
- String expertName = getExpertName(taxon);\r
- String webShowName = getWebShowName(taxonName);\r
- \r
- // idInSource only\r
- String idInSource = getIdInSourceOnly(taxonName);\r
- \r
- // build the cacheCitation\r
- if (expertName != null) {\r
- result += expertName + ". ";\r
- } else {\r
- if (logger.isDebugEnabled()){logger.debug("ExpertName could not be determined for this TaxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");}\r
- }\r
- if (webShowName != null) {\r
- result += webShowName + ". ";\r
- } else {\r
- logger.warn("WebShowName could not be determined for this TaxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");\r
- }\r
- \r
- if (getOriginalDB(taxonName).equals("FaEu")) {\r
- result += "Accessed through: Fauna Europaea at http://faunaeur.org/full_results.php?id=";\r
- } else if (getOriginalDB(taxonName).equals("EM")) {\r
- result += "Accessed through: Euro+Med PlantBase at http://ww2.bgbm.org/euroPlusMed/PTaxonDetail.asp?UUID=";\r
- }\r
- \r
- if (idInSource != null) {\r
- result += idInSource;\r
- } else {\r
- logger.warn("IdInSource could not be determined for this TaxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");\r
- }\r
- }\r
- } catch (Exception e) {\r
- e.printStackTrace();\r
- }\r
- \r
- if (StringUtils.isBlank(result)) {\r
- return null;\r
- } else {\r
- return result;\r
- }\r
- }\r
- \r
- /**\r
- * Returns the <code>OriginalDB</code> attribute.\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @return The <code>OriginalDB</code> attribute.\r
- * @see MethodMapper\r
- */\r
- private static String getOriginalDB(IdentifiableEntity identEntity) {\r
- // Sources from TaxonName\r
- BitSet sources = getSources(identEntity);\r
- return PesiTransformer.getOriginalDbBySources(sources);\r
- }\r
- \r
- /**\r
- * Returns the <code>LastAction</code> attribute.\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @return The <code>LastAction</code> attribute.\r
- * @see MethodMapper\r
- */\r
- @SuppressWarnings("unused")\r
- private static String getLastAction(IdentifiableEntity<?> identEntity) {\r
- String result = null;\r
- try {\r
- Set<Extension> extensions = identEntity.getExtensions();\r
- for (Extension extension : extensions) {\r
- if (extension.getType().equals(lastActionExtensionType)) {\r
- result = extension.getValue();\r
- }\r
- }\r
- } catch (Exception e) {\r
- e.printStackTrace();\r
- }\r
- return result;\r
- }\r
- \r
- /**\r
- * Returns the <code>LastActionDate</code> attribute.\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @return The <code>LastActionDate</code> attribute.\r
- * @see MethodMapper\r
- */\r
- @SuppressWarnings({ "unused" })\r
- private static DateTime getLastActionDate(IdentifiableEntity identEntity) {\r
- DateTime result = null;\r
- try {\r
- Set<Extension> extensions = identEntity.getExtensions();\r
- for (Extension extension : extensions) {\r
- if (extension.getType().equals(lastActionDateExtensionType)) {\r
- String dateTime = extension.getValue();\r
- if (dateTime != null) {\r
- DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss.S");\r
- result = formatter.parseDateTime(dateTime);\r
- }\r
- }\r
- }\r
- } catch (Exception e) {\r
- e.printStackTrace();\r
- }\r
- return result;\r
- }\r
- \r
- /**\r
- * Returns the <code>ExpertName</code> attribute.\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @return The <code>ExpertName</code> attribute.\r
- * @see MethodMapper\r
- */\r
- @SuppressWarnings("unused")\r
- private static String getExpertName(TaxonBase<?> taxonName) {\r
- String result = null;\r
- try {\r
- Set<Extension> extensions = taxonName.getExtensions();\r
- for (Extension extension : extensions) {\r
- if (extension.getType().equals(expertNameExtensionType)) {\r
- result = extension.getValue();\r
- }\r
- }\r
- } catch (Exception e) {\r
- e.printStackTrace();\r
- }\r
- return result;\r
- }\r
- \r
- /**\r
- * Returns the <code>ExpertFk</code> attribute.\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @param state The {@link PesiExportState PesiExportState}.\r
- * @return The <code>ExpertFk</code> attribute.\r
- * @see MethodMapper\r
- */\r
- private static Integer getExpertFk(Reference<?> reference, PesiExportState state) {\r
- Integer result = state.getDbId(reference);\r
- return result;\r
- }\r
- \r
- /**\r
- * Returns the <code>SpeciesExpertName</code> attribute.\r
- * @param taxonName The {@link TaxonNameBase TaxonName}.\r
- * @return The <code>SpeciesExpertName</code> attribute.\r
- * @see MethodMapper\r
- */\r
- @SuppressWarnings("unused")\r
- private static String getSpeciesExpertName(TaxonBase<?> taxonName) {\r
- String result = null;\r
- try {\r
- Set<Extension> extensions = taxonName.getExtensions();\r
- for (Extension extension : extensions) {\r
- if (extension.getType().equals(speciesExpertNameExtensionType)) {\r
- result = extension.getValue();\r
- }\r
- }\r
- } catch (Exception e) {\r
- e.printStackTrace();\r
- }\r
- return result;\r
- }\r
- \r
- /**\r
- * Returns the <code>SpeciesExpertFk</code> attribute.\r
- * @param reference The {@link Reference Reference}.\r
- * @param state The {@link PesiExportState PesiExportState}.\r
- * @return The <code>SpeciesExpertFk</code> attribute.\r
- * @see MethodMapper\r
- */\r
- private static Integer getSpeciesExpertFk(Reference<?> reference, PesiExportState state) {\r
- Integer result = state.getDbId(reference);\r
- return result;\r
- }\r
- \r
- \r
- /**\r
- * Returns the source (E+M, Fauna Europaea, Index Fungorum, ERMS) of a given\r
- * Identifiable Entity as a BitSet\r
- * @param identEntity\r
- * @return\r
- */\r
- private static BitSet getSources(IdentifiableEntity<?> identEntity){\r
- BitSet bitSet = new BitSet();\r
- Set<IdentifiableSource> sources = getPesiSources(identEntity);\r
- for (IdentifiableSource source : sources) {\r
- Reference<?> ref = source.getCitation();\r
- UUID refUuid = ref.getUuid();\r
- if (refUuid.equals(BerlinModelTransformer.uuidSourceRefEuroMed)){\r
- bitSet.set(PesiTransformer.SOURCE_EM);\r
- }else if (refUuid.equals(PesiTransformer.uuidSourceRefFaunaEuropaea)){\r
- bitSet.set(PesiTransformer.SOURCE_FE);\r
- }else if (refUuid.equals(PesiTransformer.uuidSourceRefErms)){\r
- bitSet.set(PesiTransformer.SOURCE_ERMS);\r
- }else if (refUuid.equals(PesiTransformer.uuidSourceRefIndexFungorum)){\r
- bitSet.set(PesiTransformer.SOURCE_IF);\r
- }else{\r
- if (logger.isDebugEnabled()){logger.debug("Not a PESI source");};\r
- }\r
- }\r
- return bitSet;\r
- \r
- }\r
- \r
- protected static NonViralNameDefaultCacheStrategy getCacheStrategy(TaxonNameBase<?, ?> taxonName) {\r
- taxonName = CdmBase.deproxy(taxonName, TaxonNameBase.class);\r
- NonViralNameDefaultCacheStrategy<?> cacheStrategy;\r
- if (taxonName.isInstanceOf(ZoologicalName.class)){\r
- cacheStrategy = zooNameStrategy;\r
- }else if (taxonName.isInstanceOf(BotanicalName.class)) {\r
- cacheStrategy = botanicalNameStrategy;\r
- }else if (taxonName.getClass().equals(NonViralName.class)) {\r
- cacheStrategy = nonViralNameStrategy;\r
- }else if (taxonName.getClass().equals(BacterialName.class)) {\r
- cacheStrategy = bacterialNameStrategy;\r
- }else{\r
- logger.error("Unhandled taxon name type. Can't define strategy class");\r
- cacheStrategy = botanicalNameStrategy;\r
- }\r
- return cacheStrategy;\r
- }\r
- \r
- /**\r
- * Returns the <code>TaxonFk1</code> attribute. It corresponds to a CDM <code>TaxonRelationship</code>.\r
- * @param relationship The {@link RelationshipBase Relationship}.\r
- * @param state The {@link PesiExportState PesiExportState}.\r
- * @return The <code>TaxonFk1</code> attribute.\r
- * @see MethodMapper\r
- */\r
- private static Integer getTaxonFk1(RelationshipBase<?, ?, ?> relationship, PesiExportState state) {\r
- \r
- return getObjectFk(relationship, state, true);\r
- }\r
- \r
- /**\r
- * Returns the <code>TaxonFk2</code> attribute. It corresponds to a CDM <code>SynonymRelationship</code>.\r
- * @param relationship The {@link RelationshipBase Relationship}.\r
- * @param state The {@link PesiExportState PesiExportState}.\r
- * @return The <code>TaxonFk2</code> attribute.\r
- * @see MethodMapper\r
- */\r
- private static Integer getTaxonFk2(RelationshipBase<?, ?, ?> relationship, PesiExportState state) {\r
- return getObjectFk(relationship, state, false);\r
- }\r
- \r
- /**\r
- * Returns the database key of an object in the given relationship.\r
- * @param relationship {@link RelationshipBase RelationshipBase}.\r
- * @param state {@link PesiExportState PesiExportState}.\r
- * @param isFrom A boolean value indicating whether the database key of the parent or child in this relationship is searched. <code>true</code> means the child is searched. <code>false</code> means the parent is searched.\r
- * @return The database key of an object in the given relationship.\r
- */\r
- private static Integer getObjectFk(RelationshipBase<?, ?, ?> relationship, PesiExportState state, boolean isFrom) {\r
- TaxonBase<?> taxonBase = null;\r
- if (relationship.isInstanceOf(TaxonRelationship.class)) {\r
- TaxonRelationship tr = (TaxonRelationship)relationship;\r
- taxonBase = (isFrom) ? tr.getFromTaxon(): tr.getToTaxon();\r
- } else if (relationship.isInstanceOf(SynonymRelationship.class)) {\r
- SynonymRelationship sr = (SynonymRelationship)relationship;\r
- taxonBase = (isFrom) ? sr.getSynonym() : sr.getAcceptedTaxon();\r
- } else if (relationship.isInstanceOf(NameRelationship.class) || relationship.isInstanceOf(HybridRelationship.class)) {\r
- if (isFrom){\r
- return state.getDbId(state.getCurrentFromObject());\r
- }else{\r
- return state.getDbId(state.getCurrentToObject());\r
- }\r
- }\r
- if (taxonBase != null) {\r
- if (! isPesiTaxon(taxonBase)){\r
- logger.warn("Related taxonBase is not a PESI taxon. Taxon: " + taxonBase.getId() + "/" + taxonBase.getUuid() + "; TaxonRel: " + relationship.getId() + "(" + relationship.getType().getTitleCache() + ")");\r
- return null;\r
- }else{\r
- return state.getDbId(taxonBase); \r
- }\r
- \r
- }\r
- logger.warn("No taxon found in state for relationship: " + relationship.toString());\r
- return null;\r
- }\r
- \r
- /**\r
- * Returns the <code>RelQualifierCache</code> attribute.\r
- * @param relationship The {@link RelationshipBase Relationship}.\r
- * @return The <code>RelQualifierCache</code> attribute.\r
- * @see MethodMapper\r
- */\r
- @SuppressWarnings("unused")\r
- private static String getRelQualifierCache(RelationshipBase<?, ?, ?> relationship, PesiExportState state) {\r
- String result = null;\r
- NomenclaturalCode code = null;\r
- if (relationship.isInstanceOf(TaxonRelationship.class)){\r
- code = CdmBase.deproxy(relationship, TaxonRelationship.class).getToTaxon().getName().getNomenclaturalCode();\r
- }else if (relationship.isInstanceOf(SynonymRelationship.class)){\r
- code = CdmBase.deproxy(relationship, SynonymRelationship.class).getAcceptedTaxon().getName().getNomenclaturalCode();\r
- }else if (relationship.isInstanceOf(NameRelationship.class)){\r
- code = CdmBase.deproxy(relationship, NameRelationship.class).getFromName().getNomenclaturalCode();\r
- }else if (relationship.isInstanceOf(HybridRelationship.class)){\r
- code = CdmBase.deproxy(relationship, HybridRelationship.class).getParentName().getNomenclaturalCode();\r
- }\r
- if (code != null) {\r
- result = state.getConfig().getTransformer().getCacheByRelationshipType(relationship, code);\r
- } else {\r
- logger.error("NomenclaturalCode is NULL while creating the following relationship: " + relationship.getUuid());\r
- }\r
- return result;\r
- }\r
- \r
- /**\r
- * Returns the <code>RelTaxonQualifierFk</code> attribute.\r
- * @param relationship The {@link RelationshipBase Relationship}.\r
- * @return The <code>RelTaxonQualifierFk</code> attribute.\r
- * @see MethodMapper\r
- */\r
- @SuppressWarnings("unused")\r
- private static Integer getRelTaxonQualifierFk(RelationshipBase<?, ?, ?> relationship) {\r
- return PesiTransformer.taxonRelation2RelTaxonQualifierFk(relationship);\r
- }\r
- /**\r
- * Returns the <code>Notes</code> attribute.\r
- * @param relationship The {@link RelationshipBase Relationship}.\r
- * @return The <code>Notes</code> attribute.\r
- * @see MethodMapper\r
- */\r
- @SuppressWarnings("unused")\r
- private static String getNotes(RelationshipBase<?, ?, ?> relationship) {\r
- // TODO\r
- return null;\r
- }\r
-\r
- \r
- /**\r
- * Returns the CDM to PESI specific export mappings.\r
- * @return The {@link PesiExportMapping PesiExportMapping}.\r
- */\r
- private PesiExportMapping getMapping() {\r
- PesiExportMapping mapping = new PesiExportMapping(dbTableName);\r
- \r
- //mapping.addMapper(IdMapper.NewInstance("TaxonId"));\r
- mapping.addMapper(DbObjectMapper.NewInstance("sec", "sourceFk")); //OLD:mapping.addMapper(MethodMapper.NewInstance("SourceFK", this.getClass(), "getSourceFk", standardMethodParameter, PesiExportState.class));\r
- mapping.addMapper(MethodMapper.NewInstance("TaxonStatusFk", this.getClass(), "getTaxonStatusFk", standardMethodParameter, PesiExportState.class));\r
- mapping.addMapper(MethodMapper.NewInstance("TaxonStatusCache", this.getClass(), "getTaxonStatusCache", standardMethodParameter, PesiExportState.class));\r
- \r
- mapping.addMapper(MethodMapper.NewInstance("GUID", this));\r
- \r
- mapping.addMapper(MethodMapper.NewInstance("DerivedFromGuid", this));\r
- mapping.addMapper(MethodMapper.NewInstance("CacheCitation", this));\r
- mapping.addMapper(MethodMapper.NewInstance("AuthorString", this)); //For Taxon because Misallied Names are handled differently\r
- mapping.addMapper(MethodMapper.NewInstance("WebShowName", this));\r
- \r
- // DisplayName\r
- mapping.addMapper(MethodMapper.NewInstance("DisplayName", this));\r
-\r
- // FossilStatus (Fk, Cache)\r
- mapping.addMapper(MethodMapper.NewInstance("FossilStatusCache", this, IdentifiableEntity.class, PesiExportState.class));\r
- mapping.addMapper(MethodMapper.NewInstance("FossilStatusFk", this, IdentifiableEntity.class, PesiExportState.class)); // PesiTransformer.FossilStatusCache2FossilStatusFk?\r
- \r
- //handled by name mapping\r
- mapping.addMapper(DbLastActionMapper.NewInstance("LastActionDate", false));\r
- mapping.addMapper(DbLastActionMapper.NewInstance("LastAction", true));\r
- \r
- //experts\r
- ExtensionType extensionTypeSpeciesExpertName = (ExtensionType)getTermService().find(PesiTransformer.speciesExpertNameUuid);\r
- mapping.addMapper(DbExtensionMapper.NewInstance(extensionTypeSpeciesExpertName, "SpeciesExpertName"));\r
- ExtensionType extensionTypeExpertName = (ExtensionType)getTermService().find(PesiTransformer.expertNameUuid);\r
- mapping.addMapper(DbExtensionMapper.NewInstance(extensionTypeExpertName, "ExpertName"));\r
- \r
-// mapping.addMapper(MethodMapper.NewInstance("ParentTaxonFk", this, TaxonBase.class, PesiExportState.class)); //by AM, doesn't work, FK exception\r
- mapping.addMapper(ObjectChangeMapper.NewInstance(TaxonBase.class, TaxonNameBase.class, "Name"));\r
- \r
- addNameMappers(mapping);\r
-\r
- return mapping;\r
- }\r
- \r
- /**\r
- * Returns the CDM to PESI specific export mappings.\r
- * @param state \r
- * @return The {@link PesiExportMapping PesiExportMapping}.\r
- * @throws UndefinedTransformerMethodException \r
- */\r
- private PesiExportMapping getPureNameMapping(PesiExportState state) throws UndefinedTransformerMethodException {\r
- PesiExportMapping mapping = new PesiExportMapping(dbTableName);\r
- \r
- mapping.addMapper(IdMapper.NewInstance("TaxonId"));\r
-\r
- // mapping.addMapper(MethodMapper.NewInstance("TaxonStatusFk", this.getClass(), "getTaxonStatusFk", standardMethodParameter, PesiExportState.class));\r
-\r
- mapping.addMapper(MethodMapper.NewInstance("KingdomFk", this, TaxonNameBase.class));\r
- mapping.addMapper(MethodMapper.NewInstance("RankFk", this, TaxonNameBase.class));\r
- mapping.addMapper(MethodMapper.NewInstance("RankCache", this, TaxonNameBase.class, PesiExportState.class));\r
- mapping.addMapper(DbConstantMapper.NewInstance("TaxonStatusFk", Types.INTEGER , PesiTransformer.T_STATUS_UNACCEPTED));\r
- mapping.addMapper(DbConstantMapper.NewInstance("TaxonStatusCache", Types.VARCHAR , state.getTransformer().getTaxonStatusCacheByKey( PesiTransformer.T_STATUS_UNACCEPTED)));\r
- mapping.addMapper(DbStringMapper.NewInstance("AuthorshipCache", "AuthorString").setBlankToNull(true)); \r
- mapping.addMapper(MethodMapper.NewInstance("WebShowName", this, TaxonNameBase.class));\r
- \r
- // DisplayName\r
- mapping.addMapper(MethodMapper.NewInstance("DisplayName", this, TaxonNameBase.class));\r
- \r
- mapping.addMapper(DbLastActionMapper.NewInstance("LastActionDate", false));\r
- mapping.addMapper(DbLastActionMapper.NewInstance("LastAction", true));\r
- \r
- addNameMappers(mapping);\r
- //TODO add author mapper, TypeNameFk\r
-\r
- return mapping;\r
- }\r
-\r
- private void addNameMappers(PesiExportMapping mapping) {\r
- mapping.addMapper(DbStringMapper.NewInstance("GenusOrUninomial", "GenusOrUninomial"));\r
- mapping.addMapper(DbStringMapper.NewInstance("InfraGenericEpithet", "InfraGenericEpithet"));\r
- mapping.addMapper(DbStringMapper.NewInstance("SpecificEpithet", "SpecificEpithet"));\r
- mapping.addMapper(DbStringMapper.NewInstance("InfraSpecificEpithet", "InfraSpecificEpithet"));\r
- \r
-// mapping.addMapper(DbStringMapper.NewInstance("NameCache", "WebSearchName")); //does not work as we need other cache strategy\r
- mapping.addMapper(MethodMapper.NewInstance("WebSearchName", this, TaxonNameBase.class));\r
- \r
-// mapping.addMapper(DbStringMapper.NewInstance("TitleCache", "FullName")); //does not work as we need other cache strategy\r
- mapping.addMapper(MethodMapper.NewInstance("FullName", this, TaxonNameBase.class));\r
- \r
- \r
- mapping.addMapper(MethodMapper.NewInstance("NomRefString", this, TaxonNameBase.class));\r
- \r
- mapping.addMapper(MethodMapper.NewInstance("NameStatusFk", this, TaxonNameBase.class));\r
- mapping.addMapper(MethodMapper.NewInstance("NameStatusCache", this, TaxonNameBase.class, PesiExportState.class));\r
- mapping.addMapper(MethodMapper.NewInstance("TypeFullnameCache", this, TaxonNameBase.class));\r
- //TODO TypeNameFk\r
- \r
- //quality status\r
- mapping.addMapper(MethodMapper.NewInstance("QualityStatusFk", this, TaxonNameBase.class));\r
- mapping.addMapper(MethodMapper.NewInstance("QualityStatusCache", this, TaxonNameBase.class, PesiExportState.class));\r
- \r
- mapping.addMapper(MethodMapper.NewInstance("IdInSource", this, IdentifiableEntity.class));\r
- mapping.addMapper(MethodMapper.NewInstance("OriginalDB", this, IdentifiableEntity.class) );\r
-\r
- //mapping.addMapper(ExpertsAndLastActionMapper.NewInstance());\r
-\r
- }\r
- \r
- private PesiExportMapping getSynRelMapping() {\r
- PesiExportMapping mapping = new PesiExportMapping(dbTableNameSynRel);\r
- \r
- mapping.addMapper(MethodMapper.NewInstance("TaxonFk1", this.getClass(), "getTaxonFk1", RelationshipBase.class, PesiExportState.class));\r
- mapping.addMapper(MethodMapper.NewInstance("TaxonFk2", this.getClass(), "getTaxonFk2", RelationshipBase.class, PesiExportState.class));\r
- mapping.addMapper(MethodMapper.NewInstance("RelTaxonQualifierFk", this, RelationshipBase.class));\r
- mapping.addMapper(MethodMapper.NewInstance("RelQualifierCache", this, RelationshipBase.class, PesiExportState.class));\r
- mapping.addMapper(MethodMapper.NewInstance("Notes", this, RelationshipBase.class));\r
-\r
- return mapping;\r
- }\r
-\r
- private PesiExportMapping getAdditionalSourceMapping(PesiExportState state) throws UndefinedTransformerMethodException{\r
- PesiExportMapping mapping = new PesiExportMapping(dbTableAdditionalSourceRel);\r
- \r
- mapping.addMapper(IdMapper.NewInstance("TaxonFk"));\r
- mapping.addMapper(ObjectChangeMapper.NewInstance(TaxonBase.class, TaxonNameBase.class, "Name"));\r
- \r
- mapping.addMapper(DbObjectMapper.NewInstance("NomenclaturalReference", "SourceFk"));\r
- mapping.addMapper(DbObjectMapper.NewInstance("NomenclaturalReference", "SourceNameCache", IS_CACHE));\r
-\r
- //we have only nomenclatural references here\r
- mapping.addMapper(DbConstantMapper.NewInstance("SourceUseFk", Types.INTEGER , PesiTransformer.NOMENCLATURAL_REFERENCE));\r
- mapping.addMapper(DbConstantMapper.NewInstance("SourceUseCache", Types.VARCHAR, state.getTransformer().getSourceUseCacheByKey( PesiTransformer.NOMENCLATURAL_REFERENCE)));\r
- \r
- mapping.addMapper(DbStringMapper.NewInstance("NomenclaturalMicroReference", "SourceDetail"));\r
- \r
- return mapping;\r
- }\r
-\r
-}\r
+/**
+* Copyright (C) 2009 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.cdm.io.pesi.out;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.TransactionStatus;
+
+import eu.etaxonomy.cdm.api.service.TaxonServiceImpl;
+import eu.etaxonomy.cdm.common.CdmUtils;
+import eu.etaxonomy.cdm.io.common.Source;
+import eu.etaxonomy.cdm.io.common.mapping.UndefinedTransformerMethodException;
+import eu.etaxonomy.cdm.io.common.mapping.out.DbConstantMapper;
+import eu.etaxonomy.cdm.io.common.mapping.out.DbLastActionMapper;
+import eu.etaxonomy.cdm.io.common.mapping.out.DbObjectMapper;
+import eu.etaxonomy.cdm.io.common.mapping.out.DbStringMapper;
+import eu.etaxonomy.cdm.io.common.mapping.out.IdMapper;
+import eu.etaxonomy.cdm.io.common.mapping.out.MethodMapper;
+import eu.etaxonomy.cdm.io.common.mapping.out.ObjectChangeMapper;
+import eu.etaxonomy.cdm.io.pesi.erms.ErmsTransformer;
+import eu.etaxonomy.cdm.model.common.AnnotationType;
+import eu.etaxonomy.cdm.model.common.CdmBase;
+import eu.etaxonomy.cdm.model.common.Extension;
+import eu.etaxonomy.cdm.model.common.ExtensionType;
+import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
+import eu.etaxonomy.cdm.model.common.IdentifiableSource;
+import eu.etaxonomy.cdm.model.common.Marker;
+import eu.etaxonomy.cdm.model.common.MarkerType;
+import eu.etaxonomy.cdm.model.common.RelationshipBase;
+import eu.etaxonomy.cdm.model.name.NameTypeDesignation;
+import eu.etaxonomy.cdm.model.name.NameTypeDesignationStatus;
+import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
+import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
+import eu.etaxonomy.cdm.model.name.Rank;
+import eu.etaxonomy.cdm.model.name.TaxonName;
+import eu.etaxonomy.cdm.model.reference.INomenclaturalReference;
+import eu.etaxonomy.cdm.model.reference.Reference;
+import eu.etaxonomy.cdm.model.taxon.Classification;
+import eu.etaxonomy.cdm.model.taxon.Synonym;
+import eu.etaxonomy.cdm.model.taxon.SynonymType;
+import eu.etaxonomy.cdm.model.taxon.Taxon;
+import eu.etaxonomy.cdm.model.taxon.TaxonBase;
+import eu.etaxonomy.cdm.model.taxon.TaxonNode;
+import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
+import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
+import eu.etaxonomy.cdm.strategy.cache.HTMLTagRules;
+import eu.etaxonomy.cdm.strategy.cache.TagEnum;
+import eu.etaxonomy.cdm.strategy.cache.name.INonViralNameCacheStrategy;
+import eu.etaxonomy.cdm.strategy.cache.name.TaxonNameDefaultCacheStrategy;
+import eu.etaxonomy.cdm.strategy.cache.name.ZooNameNoMarkerCacheStrategy;
+
+/**
+ * The export class for {@link eu.etaxonomy.cdm.model.name.TaxonNameBase TaxonNames}.<p>
+ * Inserts into DataWarehouse database table <code>Taxon</code>.
+ * It is divided into four phases:<p><ul>
+ * <li>Phase 1: Export of all {@link eu.etaxonomy.cdm.model.name.TaxonName TaxonNames} except some data exported in the following phases.
+ * <li>Phase 2: Export of additional data: ParentTaxonFk and TreeIndex.
+ * <li>Phase 3: Export of additional data: Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk.
+ * <li>Phase 4: Export of Inferred Synonyms.</ul>
+ *
+ * @author e.-m.lee
+ * @since 23.02.2010
+ */
+@Component
+public class PesiTaxonExport extends PesiExportBase {
+
+ private static final long serialVersionUID = -3412722058790200078L;
+ private static final Logger logger = Logger.getLogger(PesiTaxonExport.class);
+
+ private static final Class<? extends CdmBase> standardMethodParameter = TaxonBase.class;
+
+ private static int modCount = 1000;
+ private static final String dbTableName = "Taxon";
+ private static final String dbTableNameSynRel = "RelTaxon";
+ private static final String dbTableAdditionalSourceRel = "AdditionalTaxonSource";
+
+ private static final String pluralString = "Taxa";
+ private static final String parentPluralString = "Taxa";
+ private static final String pluralStringNames = "Names";
+
+// private PreparedStatement parentTaxonFk_TreeIndex_KingdomFkStmts;
+ private PreparedStatement parentTaxonFkStmt;
+ private PreparedStatement rankTypeExpertsUpdateStmt;
+ private PreparedStatement rankUpdateStmt;
+ private Integer kingdomFk;
+
+ private static ExtensionType lastActionExtensionType;
+ private static ExtensionType lastActionDateExtensionType;
+ private static ExtensionType expertNameExtensionType;
+ private static ExtensionType speciesExpertNameExtensionType;
+ private static ExtensionType cacheCitationExtensionType;
+
+ public static TaxonNameDefaultCacheStrategy zooNameStrategy = ZooNameNoMarkerCacheStrategy.NewInstance();
+ public static TaxonNameDefaultCacheStrategy nonViralNameStrategy = TaxonNameDefaultCacheStrategy.NewInstance();
+ private static int currentTaxonId;
+
+ enum NamePosition {
+ beginning,
+ end,
+ between,
+ alone,
+ nowhere
+ }
+
+ public PesiTaxonExport() {
+ super();
+ }
+
+ @Override
+ public Class<? extends CdmBase> getStandardMethodParameter() {
+ return standardMethodParameter;
+ }
+
+ @Override
+ protected void doInvoke(PesiExportState state) {
+ try {
+ logger.info("*** Started Making " + pluralString + " ...");
+
+ initPreparedStatements(state);
+
+ // Stores whether this invoke was successful or not.
+ boolean success = true;
+
+ // PESI: Clear the database table Taxon.
+ doDelete(state);
+
+ // Get specific mappings: (CDM) Taxon -> (PESI) Taxon
+ PesiExportMapping mapping = getMapping();
+ PesiExportMapping synonymRelMapping = getSynRelMapping();
+ PesiExportMapping additionalSourceMapping = getAdditionalSourceMapping(state);
+
+ // Initialize the db mapper
+ mapping.initialize(state);
+ synonymRelMapping.initialize(state);
+ additionalSourceMapping.initialize(state);
+
+ // Find extensionTypes
+ lastActionExtensionType = (ExtensionType)getTermService().find(PesiTransformer.uuidExtLastAction);
+ lastActionDateExtensionType = (ExtensionType)getTermService().find(PesiTransformer.uuidExtLastActionDate);
+ expertNameExtensionType = (ExtensionType)getTermService().find(PesiTransformer.uuidExtExpertName);
+ speciesExpertNameExtensionType = (ExtensionType)getTermService().find(PesiTransformer.uuidExtSpeciesExpertName);
+ cacheCitationExtensionType = (ExtensionType)getTermService().find(PesiTransformer.uuidExtCacheCitation);
+
+ //Export Taxa..
+ success &= doPhase01(state, mapping, additionalSourceMapping);
+
+ //"PHASE 1b: Handle names without taxa ...
+ success &= doPhase01b_Names(state, additionalSourceMapping);
+
+ // 2nd Round: Add ParentTaxonFk to each taxon
+ success &= doPhase02(state);
+
+ //PHASE 3: Add Rank data, KingdomFk, TypeNameFk ...
+ success &= doPhase03(state);
+
+ // 4nd Round: Add TreeIndex to each taxon
+ success &= doPhase04(state);
+
+ //"PHASE 5: Creating Inferred Synonyms...
+ success &= doPhase05(state, mapping, synonymRelMapping);
+
+ logger.info("*** Finished Making " + pluralString + " ..." + getSuccessString(success));
+
+ if (!success){
+ state.getResult().addError("An error occurred in PesiTaxonExport.doInvoke. Success = false");
+ }
+ return;
+ } catch (Exception e) {
+ e.printStackTrace();
+ logger.error(e.getMessage());
+ state.getResult().addException(e);
+ }
+ }
+
+
+ private void initPreparedStatements(PesiExportState state) throws SQLException {
+// initTreeIndexStatement(state);
+ initRankExpertsUpdateStmt(state);
+ initRankUpdateStatement(state);
+
+ initParentFkStatement(state);
+ }
+
+// // Prepare TreeIndex-And-KingdomFk-Statement
+// private void initTreeIndexStatement(PesiExportState state) throws SQLException {
+// Connection connection = state.getConfig().getDestination().getConnection();
+// String parentTaxonFk_TreeIndex_KingdomFkSql = "UPDATE Taxon SET ParentTaxonFk = ?, TreeIndex = ? WHERE TaxonId = ?";
+// parentTaxonFk_TreeIndex_KingdomFkStmt = connection.prepareStatement(parentTaxonFk_TreeIndex_KingdomFkSql);
+// }
+
+ // Prepare TreeIndex-And-KingdomFk-Statement
+ private void initParentFkStatement(PesiExportState state) throws SQLException {
+ Connection connection = state.getConfig().getDestination().getConnection();
+ String parentTaxonFkSql = "UPDATE Taxon SET ParentTaxonFk = ? WHERE TaxonId = ?";
+ parentTaxonFkStmt = connection.prepareStatement(parentTaxonFkSql);
+ }
+
+ private void initRankUpdateStatement(PesiExportState state) throws SQLException {
+ Connection connection = state.getConfig().getDestination().getConnection();
+ String rankSql = "UPDATE Taxon SET RankFk = ?, RankCache = ?, KingdomFk = ? WHERE TaxonId = ?";
+ rankUpdateStmt = connection.prepareStatement(rankSql);
+ }
+
+ private void initRankExpertsUpdateStmt(PesiExportState state) throws SQLException {
+// String sql_old = "UPDATE Taxon SET RankFk = ?, RankCache = ?, TypeNameFk = ?, KingdomFk = ?, " +
+// "ExpertFk = ?, SpeciesExpertFk = ? WHERE TaxonId = ?";
+ //TODO handle experts GUIDs
+ Connection connection = state.getConfig().getDestination().getConnection();
+
+ String sql = "UPDATE Taxon SET RankFk = ?, RankCache = ?, TypeNameFk = ?, KingdomFk = ? " +
+ " WHERE TaxonId = ?";
+ rankTypeExpertsUpdateStmt = connection.prepareStatement(sql);
+ }
+
+ private boolean doPhase01(PesiExportState state, PesiExportMapping mapping, PesiExportMapping additionalSourceMapping){
+
+ int count = 0;
+ int pastCount = 0;
+ boolean success = true;
+ // Get the limit for objects to save within a single transaction.
+ int limit = state.getConfig().getLimitSave();
+
+ logger.info("PHASE 1: Export Taxa...limit is " + limit);
+ // Start transaction
+ TransactionStatus txStatus = startTransaction(true);
+ if (logger.isDebugEnabled()) {
+ logger.info("Started new transaction. Fetching some " + pluralString + " (max: " + limit + ") ...");
+ logger.info("Taking snapshot at the beginning of phase 1 of taxonExport");
+ //ProfilerController.memorySnapshot();
+ }
+
+ int partitionCount = 0;
+ List<TaxonBase<?>> list;
+ while ((list = getNextTaxonPartition(null, limit, partitionCount++, null)) != null ) {
+
+ logger.debug("Fetched " + list.size() + " " + pluralString + ". Exporting...");
+
+ for (TaxonBase<?> taxon : list) {
+ doCount(count++, modCount, pluralString);
+ TaxonName taxonName = taxon.getName();
+
+ TaxonName nvn = CdmBase.deproxy(taxonName);
+ if (! nvn.isProtectedTitleCache()){
+ nvn.setTitleCache(null, false);
+ }
+ if (! nvn.isProtectedNameCache()){
+ nvn.setNameCache(null, false);
+ }
+ if (! nvn.isProtectedFullTitleCache()){
+ nvn.setFullTitleCache(null, false);
+ }
+ if (! nvn.isProtectedAuthorshipCache()){
+ nvn.setAuthorshipCache(null, false);
+ }
+ try{
+ if (nvn.getRank().equals(Rank.KINGDOM())){
+ if(taxon.isInstanceOf(Taxon.class)){
+ String treeIndex = ((Taxon)taxon).getTaxonNodes().iterator().next().treeIndex();
+ Integer kingdomId = PesiTransformer.pesiKingdomId(nvn.getGenusOrUninomial());
+ state.getTreeIndexKingdomMap().put(treeIndex, kingdomId);
+ }else{
+ logger.warn("Kingdom taxon is not of class Taxon but " + taxon.getClass().getSimpleName() + ": " + nvn.getGenusOrUninomial());
+ }
+ }
+ }catch(NullPointerException e){
+ logger.error(nvn.getTitleCache() + " has no Rank!");
+ System.err.println(nvn.getTitleCache() + " has no Rank!");
+ }
+ //core mapping
+ success &= mapping.invoke(taxon);
+ //additional source
+ if (nvn.getNomenclaturalReference() != null || StringUtils.isNotBlank(nvn.getNomenclaturalMicroReference() )){
+ additionalSourceMapping.invoke(taxon);
+ }
+
+ //TODO switch on again, leads to some warnings in ERMS for taxa of not correctly handled kingdoms
+ validatePhaseOne(taxon, nvn);
+ }
+
+ // Commit transaction
+ commitTransaction(txStatus);
+ logger.info("Exported " + (count - pastCount) + " " + pluralString + ". Total: " + count + " (Phase 01)");
+ pastCount = count;
+
+ // Start new transaction
+ txStatus = startTransaction(true);
+ if (logger.isDebugEnabled()) {
+ logger.info("Started new transaction. Fetching some " + pluralString + " (max: " + limit + ") ...");
+ }
+
+ }
+ logger.debug("No " + pluralString + " left to fetch.");
+
+ // Commit transaction
+ commitTransaction(txStatus);
+ txStatus = null;
+
+ return success;
+ }
+
+ private void validatePhaseOne(TaxonBase<?> taxon, TaxonName taxonName) {
+
+ // Check whether some rules are violated
+ String genusOrUninomial = taxonName.getGenusOrUninomial();
+ String specificEpithet = taxonName.getSpecificEpithet();
+ String infraSpecificEpithet = taxonName.getInfraSpecificEpithet();
+ String infraGenericEpithet = taxonName.getInfraGenericEpithet();
+ Rank rank = taxonName.getRank();
+
+ //as kingdomFk can not be defined in Phase 01 the below code was switched to use the CDM rank.
+ //This may be changed if we move validation to Phase03 or later
+// Integer rankFk = getRankFk(taxonName, taxonName.getNameType());
+// if (rankFk == null) {
+// logger.error("Rank was not determined: " + taxon.getUuid() + " (" + taxon.getTitleCache() + ")");
+// } else {
+
+ // Check whether infraGenericEpithet is set correctly
+ // 1. Childs of an accepted taxon of rank subgenus that are accepted taxa of rank species have to have an infraGenericEpithet
+ // 2. Grandchilds of an accepted taxon of rank subgenus that are accepted taxa of rank subspecies have to have an infraGenericEpithet
+
+ int ancestorLevel = 0;
+ if (rank == null){
+ logger.warn("PhaseOne validation: Taxon name has no rank: " + taxonName.getTitleCache());
+ }else if (rank.equals(Rank.SUBSPECIES())) {
+ // The accepted taxon two rank levels above should be of rank subgenus
+ ancestorLevel = 2;
+ }else if (rank.equals(Rank.SPECIES())) {
+ // The accepted taxon one rank level above should be of rank subgenus
+ ancestorLevel = 1;
+ }
+ if (ancestorLevel > 0) {
+ if (validateAncestorOfSpecificRank(taxon, ancestorLevel, Rank.SUBGENUS())) {
+ // The child (species or subspecies) of this parent (subgenus) has to have an infraGenericEpithet
+ if (infraGenericEpithet == null) {
+ logger.warn("InfraGenericEpithet for (sub)species of infrageneric taxon does not exist even though it should (also valid for Botanical Names?) for: " + taxon.getUuid() + " (" + taxon.getTitleCache() + ")");
+ // maybe the taxon could be named here
+ }
+ }
+ }
+
+ if (rank != null){
+ if (infraGenericEpithet == null && rank.isInfraGenericButNotSpeciesGroup()) {
+ logger.warn("InfraGenericEpithet was not determined although it should exist for infra generic names: " + taxon.getUuid() + " (" + taxon.getTitleCache() + ")");
+ }
+ if (specificEpithet != null && (rank.isInfraGenericButNotSpeciesGroup()||rank.isGenus()||rank.isSupraGeneric())) {
+ logger.warn("SpecificEpithet was determined for rank " + rank.getTitleCache() + " although it should only exist for species aggregates, species or infraspecific taxa: TaxonName " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
+ }
+ if (infraSpecificEpithet != null && !rank.isInfraSpecific()) {
+ String message = "InfraSpecificEpithet '" +infraSpecificEpithet + "' was determined for rank " + rank.getTitleCache() + " although it should only exist for rank species and higher: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")";
+ if (StringUtils.isNotBlank(infraSpecificEpithet)){
+ logger.warn(message);
+ }else{
+ logger.warn(message);
+ }
+ }
+ }
+// }
+ if (infraSpecificEpithet != null && specificEpithet == null) {
+ logger.warn("An infraSpecificEpithet was determined, but a specificEpithet was not determined: " + taxon.getUuid() + " (" + taxon.getTitleCache() + ")");
+ }
+ if (genusOrUninomial == null) {
+ logger.warn("GenusOrUninomial was not determined: " + taxon.getUuid() + " (" + taxon.getTitleCache() + ")");
+ }
+ }
+
+ /**
+ * 2nd Round: Add ParentTaxonFk to each taxon and add Biota if not exists
+ */
+ private boolean doPhase02(PesiExportState state) {
+ int count = 0;
+ int pastCount = 0;
+ boolean success = true;
+ if (! state.getConfig().isDoParentAndBiota()){
+ logger.info ("Ignore PHASE 2: Make ParentFk and Biota...");
+ return success;
+ }
+
+ // Get the limit for objects to save within a single transaction.
+ int limit = state.getConfig().getLimitSave();
+
+ insertBiota(state);
+
+ logger.info("PHASE 2: Make ParentFk and Biota ... limit is " + limit);
+ // Start transaction
+ TransactionStatus txStatus = startTransaction(true);
+ int partitionCount = 0;
+
+// ProfilerController.memorySnapshot();
+ List<Taxon> list;
+ while ((list = getNextTaxonPartition(Taxon.class, limit, partitionCount++, null)) != null ) {
+
+ if(logger.isDebugEnabled()) {
+ logger.info("Fetched " + list.size() + " " + pluralString + ". Exporting...");
+ }
+ for (Taxon taxon : list) {
+ for (TaxonNode node : taxon.getTaxonNodes()){
+ doCount(count++, modCount, pluralString);
+ TaxonNode parentNode = node.getParent();
+ if (parentNode != null && isPesiTaxon(parentNode.getTaxon())){ //exclude root taxa and unpublished parents (relevant for "Valueless" parent for E+M Rubus taxa). Usually a parent should not be unpublished
+ int childId = state.getDbId( taxon);
+ int parentId = state.getDbId(parentNode.getTaxon());
+ success &= invokeParentTaxonFk(parentId, childId);
+ }
+ }
+ }
+
+ // Commit transaction
+ commitTransaction(txStatus);
+ logger.info("Exported " + (count - pastCount) + " " + pluralString + ". Total: " + count + " (Phase 2)");
+ pastCount = count;
+ // Start transaction
+ txStatus = startTransaction(true);
+ if (logger.isDebugEnabled()){
+ logger.info("Started new transaction. Fetching some " + pluralString + " (max: " + limit + ") ...");
+ }
+ }
+ logger.debug("No " + pluralString + " left to fetch.");
+
+ // Commit transaction
+ commitTransaction(txStatus);
+
+ return success;
+ }
+
+ /**
+ * Inserts the Biota Taxon if not yet exists.
+ */
+ private void insertBiota(PesiExportState state) {
+ try {
+ ResultSet rs = state.getConfig().getDestination().getResultSet("SELECT * FROM Taxon WHERE GenusOrUninomial = 'Biota' ");
+ if (rs.next() == false){
+ int biotaId = state.getConfig().getNameIdStart() -1 ;
+ String sqlInsertBiota = "INSERT INTO Taxon (TaxonId, KingdomFk, RankFk, RankCache, GenusOrUninomial, WebSearchName, WebShowName, FullName, DisplayName, TaxonStatusFk, TaxonStatusCache) " +
+ " VALUES (" + biotaId + ", 0, 0, 'Superdomain', 'Biota', 'Biota', '<i>Biota</i>', 'Biota', '<i>Biota</i>', 1 , 'accepted')";
+ state.getConfig().getDestination().update(sqlInsertBiota);
+ }
+ rs = null;
+ } catch (SQLException e) {
+ logger.warn ("Biota could not be requested or inserted");
+ }
+ }
+
+ //PHASE 3: Add Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk...
+ private boolean doPhase03(PesiExportState state) {
+ int count = 0;
+ int pastCount = 0;
+ boolean success = true;
+ if (! state.getConfig().isDoTreeIndex()){
+ logger.info ("Ignore PHASE 3: Add Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk...");
+ return success;
+ }
+
+ addValuelessTaxonToKingdomMap(state);
+
+ // Get the limit for objects to save within a single transaction.
+ int limit = state.getConfig().getLimitSave();
+
+ logger.info("PHASE 3: Add Rank data, KingdomFk, TypeNameFk, expertFk and speciesExpertFk...");
+ // Be sure to add rank information, KingdomFk, TypeNameFk, expertFk and speciesExpertFk to every taxonName
+
+ // Start transaction
+ TransactionStatus txStatus = startTransaction(true);
+ if (logger.isDebugEnabled()) {
+ logger.info("Started new transaction for rank, kingdom, typeName, expertFk and speciesExpertFK. Fetching some " + pluralString + " (max: " + limit + ") ...");
+ }
+ int partitionCount = 0;
+ @SuppressWarnings("rawtypes")
+ List<TaxonBase> list;
+ while ((list = getNextTaxonPartition(TaxonBase.class, limit, partitionCount++, null)) != null) {
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Fetched " + list.size() + " " + pluralString + ". Exporting...");
+ }
+ for (TaxonBase<?> taxon : list) {
+ TaxonName taxonName = CdmBase.deproxy(taxon.getName());
+ // Determine expertFk
+// Integer expertFk = makeExpertFk(state, taxonName);
+//
+// // Determine speciesExpertFk
+// Integer speciesExpertFk = makeSpeciesExpertFk(state, taxonName);
+
+ doCount(count++, modCount, pluralString);
+ Integer typeNameFk = getTypeNameFk(taxonName, state);
+ Integer kingdomFk = findKingdomIdFromTreeIndex(taxon, state);
+ Integer rankFk = getRankFk(taxonName, kingdomFk);
+
+ invokeRankDataAndTypeNameFkAndKingdomFk(taxonName, state.getDbId(taxon),
+ typeNameFk, kingdomFk, rankFk, state);
+ }
+
+ // Commit transaction
+ commitTransaction(txStatus);
+ if (logger.isDebugEnabled()){logger.debug("Committed transaction.");}
+ logger.info("Exported " + (count - pastCount) + " " + pluralString + ". Total: " + count + " (Phase 3)");
+ pastCount = count;
+
+ // Start transaction
+ txStatus = startTransaction(true);
+ if (logger.isDebugEnabled()) {
+ logger.info("Started new transaction for rank, kingdom, typeName, expertFk and speciesExpertFK. Fetching some " + pluralString + " (max: " + limit + ") ...");
+ }
+ }
+ logger.debug("No " + pluralString + " left to fetch.");
+
+ // Commit transaction
+ commitTransaction(txStatus);
+
+ if (logger.isDebugEnabled()){
+ logger.debug("Committed transaction.");
+ logger.debug("Try to take snapshot at the end of phase 3 of taxonExport, number of partitions: " + partitionCount);
+ //ProfilerController.memorySnapshot();
+ }
+ return success;
+ }
+
+ private void addValuelessTaxonToKingdomMap(PesiExportState state) {
+ TransactionStatus txStatus = startTransaction();
+ Taxon valuelessTaxon = (Taxon)getTaxonService().find(PesiTransformer.uuidTaxonValuelessEuroMed);
+ if (valuelessTaxon != null){
+ String treeIndex = valuelessTaxon.getTaxonNodes().iterator().next().treeIndex();
+ Integer kingdomId = PesiTransformer.pesiKingdomId("Plantae");
+ state.getTreeIndexKingdomMap().put(treeIndex, kingdomId);
+ }
+ commitTransaction(txStatus);
+ }
+
+ // 4th round: Add TreeIndex to each taxon
+ private boolean doPhase04(PesiExportState state) {
+ boolean success = true;
+
+ logger.info("PHASE 4: Make TreeIndex ... ");
+
+ //TODO test if possible to move to phase 02
+ String sql = " UPDATE Taxon SET ParentTaxonFk = (SELECT TaxonId FROM Taxon WHERE RankFk = 0) " +
+ " WHERE (RankFk = 10) and TaxonStatusFk = 1 ";
+ state.getConfig().getDestination().update(sql);
+
+ state.getConfig().getDestination().update("EXEC dbo.recalculateallstoredpaths");
+
+ logger.info("PHASE 4: Make TreeIndex DONE");
+
+ return success;
+ }
+
+ private static Integer findKingdomIdFromTreeIndex(TaxonBase<?> taxonBase, PesiExportState state) {
+ Taxon taxon;
+ if (taxonBase instanceof Synonym){
+ taxon = ((Synonym) taxonBase).getAcceptedTaxon();
+ }else{
+ taxon = checkPseudoOrRelatedTaxon((Taxon)taxonBase);
+ }
+ if (taxon == null){
+ NomenclaturalCode nomenclaturalCode = taxonBase.getName().getNameType();
+ logger.warn("Taxon is synonym with no accepted taxon attached: " + taxonBase.getTitleCache() + ". The kingdom is taken from the nomenclatural code: " + PesiTransformer.nomenclaturalCode2Kingdom(nomenclaturalCode) );
+ return PesiTransformer.nomenclaturalCode2Kingdom(nomenclaturalCode);
+ } else{
+ Set<TaxonNode> nodes = taxon.getTaxonNodes();
+ if (nodes.isEmpty()){
+ NomenclaturalCode nomenclaturalCode = taxon.getName().getNameType();
+ logger.warn("The taxon has no nodes: " + taxon.getTitleCache() + ". The kingdom is taken from the nomenclatural code: " + PesiTransformer.nomenclaturalCode2Kingdom(nomenclaturalCode));
+ return PesiTransformer.nomenclaturalCode2Kingdom(nomenclaturalCode);
+ } else {
+ if (nodes.size()>1){
+ logger.warn("The taxon has more then 1 taxon node: " + taxon.getTitleCache() + ". Take arbitrary one.");
+ }
+ String treeIndex = nodes.iterator().next().treeIndex();
+
+ Pattern pattern = Pattern.compile("#t[0-9]+#([0-9]+#){3}");
+ Matcher matcher = pattern.matcher(treeIndex);
+ Integer kingdomID = null;
+ if(matcher.find()) {
+ String treeIndexKingdom = matcher.group(0);
+ kingdomID = state.getTreeIndexKingdomMap().get(treeIndexKingdom);
+ }
+ if (kingdomID == null){
+ pattern = Pattern.compile("#t[0-9]+#([0-9]+#){2}");
+ matcher = pattern.matcher(treeIndex);
+ if(matcher.find()) {
+ String treeIndexKingdom = matcher.group(0);
+ Map<String, Integer> map = state.getTreeIndexKingdomMap();
+ kingdomID = map.get(treeIndexKingdom);
+ }
+ }
+ if(Rank.DOMAIN().equals(taxon.getName().getRank())){
+ return 0;
+ }
+ if(kingdomID == null){
+ logger.warn("Kingdom could not be defined for treeindex " + treeIndex);
+ }
+ return kingdomID;
+ }
+ }
+ }
+
+ private static Taxon checkPseudoOrRelatedTaxon(Taxon taxon) {
+ if (!taxon.getTaxonNodes().isEmpty()){
+ return taxon;
+ }else if(hasPseudoTaxonRelationship(taxon)){
+ return acceptedPseudoTaxon(taxon);
+ }else if(isMisappliedNameOrProParteSynonym(taxon)){
+ return acceptedTaxonConcept(taxon);
+ }else{
+ return taxon;
+ }
+ }
+
+ private static Taxon acceptedPseudoTaxon(Taxon taxon) {
+ for (TaxonRelationship rel : taxon.getRelationsFromThisTaxon()){
+ if (TaxonRelationshipType.pseudoTaxonUuids().contains(rel.getType().getUuid())){
+ return rel.getToTaxon();
+ }
+ }
+ return taxon;
+ }
+
+ private static Taxon acceptedTaxonConcept(Taxon taxon) {
+ for (TaxonRelationship rel : taxon.getRelationsFromThisTaxon()){
+ if (TaxonRelationshipType.misappliedNameUuids().contains(rel.getType().getUuid())||
+ TaxonRelationshipType.proParteOrPartialSynonymUuids().contains(rel.getType().getUuid())){
+ return rel.getToTaxon();
+ }
+ }
+ return taxon;
+ }
+
+ private static boolean hasPseudoTaxonRelationship(Taxon taxon) {
+ for (TaxonRelationship rel : taxon.getRelationsFromThisTaxon()){
+ if (TaxonRelationshipType.pseudoTaxonUuids().contains(rel.getType().getUuid())){
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static boolean isMisappliedNameOrProParteSynonym(Taxon taxon) {
+ for (TaxonRelationship rel : taxon.getRelationsFromThisTaxon()){
+ if (TaxonRelationshipType.misappliedNameUuids().contains(rel.getType().getUuid())||
+ TaxonRelationshipType.proParteOrPartialSynonymUuids().contains(rel.getType().getUuid())){
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // "PHASE 5: Creating Inferred Synonyms..."
+ private boolean doPhase05(PesiExportState state, PesiExportMapping mapping, PesiExportMapping synRelMapping) {
+ int count;
+ int pastCount;
+ boolean success = true;
+ // Get the limit for objects to save within a single transaction.
+ if (! state.getConfig().isDoInferredSynonyms()){
+ logger.info ("Ignore PHASE 5: Creating Inferred Synonyms...");
+ return success;
+ }
+
+ int limit = state.getConfig().getLimitSave();
+ // Create inferred synonyms for accepted taxa
+ logger.info("PHASE 5: Creating Inferred Synonyms...");
+
+ // Determine the count of elements in data warehouse database table Taxon
+ currentTaxonId = determineTaxonCount(state);
+ currentTaxonId++;
+
+ count = 0;
+ pastCount = 0;
+ int pageSize = limit/10;
+ int pageNumber = 1;
+ String inferredSynonymPluralString = "Inferred Synonyms";
+
+ // Start transaction
+ TransactionStatus txStatus = startTransaction(true);
+ if (logger.isDebugEnabled()) {
+ logger.info("Started new transaction. Fetching some " + parentPluralString + " first (max: " + limit + ") ...");
+ }
+
+ List<TaxonBase> taxonList = null;
+ while ((taxonList = getTaxonService().listTaxaByName(Taxon.class, "*", "*", "*", "*", "*", Rank.SPECIES(), pageSize, pageNumber, null)).size() > 0) {
+
+ Map<Integer, TaxonName> inferredSynonymsDataToBeSaved = new HashMap<>();
+
+ if (logger.isDebugEnabled()) {
+ logger.info("Fetched " + taxonList.size() + " " + parentPluralString + ". Exporting...");
+ }
+ inferredSynonymsDataToBeSaved.putAll(createInferredSynonymsForTaxonList(state, mapping,
+ synRelMapping, taxonList));
+
+ doCount(count += taxonList.size(), modCount, inferredSynonymPluralString);
+ // Commit transaction
+ commitTransaction(txStatus);
+ if (logger.isDebugEnabled()){logger.debug("Committed transaction.");}
+ logger.info("Exported " + (taxonList.size()) + " " + inferredSynonymPluralString + ". Total: " + count);
+ //pastCount = count;
+
+ // Save Rank Data and KingdomFk for inferred synonyms
+ for (Integer taxonFk : inferredSynonymsDataToBeSaved.keySet()) {
+ TaxonName taxonName = inferredSynonymsDataToBeSaved.get(taxonFk);
+ invokeRankDataAndKingdomFk(inferredSynonymsDataToBeSaved.get(taxonFk), taxonFk, kingdomFk, state);
+ }
+
+ // Start transaction
+ txStatus = startTransaction(true);
+ if (logger.isDebugEnabled()) {
+ logger.info("Started new transaction. Fetching some " + parentPluralString + " first (max: " + limit + ") ...");
+ }
+
+ // Increment pageNumber
+ pageNumber++;
+ }
+ taxonList = null;
+ while ((taxonList = getTaxonService().listTaxaByName(Taxon.class, "*", "*", "*", "*", "*", Rank.SUBSPECIES(), pageSize, pageNumber, null)).size() > 0) {
+ Map<Integer, TaxonName> inferredSynonymsDataToBeSaved = new HashMap<>();
+
+ logger.info("Fetched " + taxonList.size() + " " + parentPluralString + ". Exporting...");
+ inferredSynonymsDataToBeSaved.putAll(createInferredSynonymsForTaxonList(state, mapping,
+ synRelMapping, taxonList));
+
+ doCount(count += taxonList.size(), modCount, inferredSynonymPluralString);
+ // Commit transaction
+ commitTransaction(txStatus);
+ logger.debug("Committed transaction.");
+ logger.info("Exported " + taxonList.size()+ " " + inferredSynonymPluralString + ". Total: " + count);
+ //pastCount = count;
+
+ // Save Rank Data and KingdomFk for inferred synonyms
+ for (Integer taxonFk : inferredSynonymsDataToBeSaved.keySet()) {
+ TaxonName taxonName = inferredSynonymsDataToBeSaved.get(taxonFk);
+ invokeRankDataAndKingdomFk(taxonName, taxonFk, kingdomFk, state);
+ }
+
+ // Start transaction
+ txStatus = startTransaction(true);
+ logger.info("Started new transaction. Fetching some " + parentPluralString + " first (max: " + limit + ") ...");
+
+ // Increment pageNumber
+ pageNumber++;
+ inferredSynonymsDataToBeSaved = null;
+ }
+ if (taxonList.size() == 0) {
+ logger.info("No " + parentPluralString + " left to fetch.");
+ }
+
+ taxonList = null;
+// logger.warn("Taking snapshot at the end of phase 5 of taxonExport");
+// ProfilerController.memorySnapshot();
+
+ // Commit transaction
+ commitTransaction(txStatus);
+ System.gc();
+ logger.debug("Taking snapshot at the end of phase 5 after gc() of taxonExport");
+ //ProfilerController.memorySnapshot();
+ logger.debug("Committed transaction.");
+ return success;
+ }
+
+ private Map<Integer, TaxonName> createInferredSynonymsForTaxonList(PesiExportState state,
+ PesiExportMapping mapping, PesiExportMapping synRelMapping, List<TaxonBase> taxonList) {
+
+ Taxon acceptedTaxon;
+ Classification classification = null;
+ List<Synonym> inferredSynonyms = null;
+ boolean localSuccess = true;
+
+ Map<Integer, TaxonName> inferredSynonymsDataToBeSaved = new HashMap<>();
+
+ for (TaxonBase<?> taxonBase : taxonList) {
+
+ if (taxonBase.isInstanceOf(Taxon.class)) { // this should always be the case since we should have fetched accepted taxon only, but you never know...
+ acceptedTaxon = CdmBase.deproxy(taxonBase, Taxon.class);
+ TaxonName taxonName = acceptedTaxon.getName();
+
+ if (taxonName.isZoological()) {
+ kingdomFk = findKingdomIdFromTreeIndex(taxonBase, state);
+
+ Set<TaxonNode> taxonNodes = acceptedTaxon.getTaxonNodes();
+ TaxonNode singleNode = null;
+
+ if (taxonNodes.size() > 0) {
+ // Determine the classification of the current TaxonNode
+
+ singleNode = taxonNodes.iterator().next();
+ if (singleNode != null) {
+ classification = singleNode.getClassification();
+ } else {
+ logger.error("A TaxonNode belonging to this accepted Taxon is NULL: " + acceptedTaxon.getUuid() + " (" + acceptedTaxon.getTitleCache() +")");
+ }
+ } else {
+ // Classification could not be determined directly from this TaxonNode
+ // The stored classification from another TaxonNode is used. It's a simple, but not a failsafe fallback solution.
+ if (taxonNodes.size() == 0) {
+ //logger.error("Classification could not be determined directly from this Taxon: " + acceptedTaxon.getUuid() + " is misapplication? "+acceptedTaxon.isMisapplication()+ "). The classification of the last taxon is used");
+ }
+ }
+
+ if (classification != null) {
+ try{
+ TaxonName name = acceptedTaxon.getName();
+ //if (name.isSpecies() || name.isInfraSpecific()){
+ inferredSynonyms = getTaxonService().createAllInferredSynonyms(acceptedTaxon, classification, true);
+ //}
+// inferredSynonyms = getTaxonService().createInferredSynonyms(classification, acceptedTaxon, SynonymType.INFERRED_GENUS_OF());
+ if (inferredSynonyms != null) {
+ for (Synonym synonym : inferredSynonyms) {
+// TaxonName synonymName = synonym.getName();
+ MarkerType markerType =getUuidMarkerType(PesiTransformer.uuidMarkerGuidIsMissing, state);
+ synonym.addMarker(Marker.NewInstance(markerType, true));
+ // Both Synonym and its TaxonName have no valid Id yet
+ synonym.setId(currentTaxonId++);
+
+
+ localSuccess &= mapping.invoke(synonym);
+ //get SynonymRelationship and export
+ if (synonym.getAcceptedTaxon() == null ){
+ IdentifiableSource source = synonym.getSources().iterator().next();
+ if (source.getIdNamespace().contains("Potential combination")){
+ acceptedTaxon.addSynonym(synonym, SynonymType.POTENTIAL_COMBINATION_OF());
+ logger.error(synonym.getTitleCache() + " is not attached to " + acceptedTaxon.getTitleCache() + " type is set to potential combination");
+ } else if (source.getIdNamespace().contains("Inferred Genus")){
+ acceptedTaxon.addSynonym(synonym, SynonymType.INFERRED_GENUS_OF());
+ logger.error(synonym.getTitleCache() + " is not attached to " + acceptedTaxon.getTitleCache() + " type is set to inferred genus");
+ } else if (source.getIdNamespace().contains("Inferred Epithet")){
+ acceptedTaxon.addSynonym(synonym, SynonymType.INFERRED_EPITHET_OF());
+ logger.error(synonym.getTitleCache() + " is not attached to " + acceptedTaxon.getTitleCache() + " type is set to inferred epithet");
+ } else{
+ acceptedTaxon.addSynonym(synonym, SynonymType.INFERRED_SYNONYM_OF());
+ logger.error(synonym.getTitleCache() + " is not attached to " + acceptedTaxon.getTitleCache() + " type is set to inferred synonym");
+ }
+
+ localSuccess &= synRelMapping.invoke(synonym);
+ if (!localSuccess) {
+ logger.error("Synonym relationship export failed " + synonym.getTitleCache() + " accepted taxon: " + acceptedTaxon.getUuid() + " (" + acceptedTaxon.getTitleCache()+")");
+ }
+ } else {
+ localSuccess &= synRelMapping.invoke(synonym);
+ if (!localSuccess) {
+ logger.error("Synonym relationship export failed " + synonym.getTitleCache() + " accepted taxon: " + acceptedTaxon.getUuid() + " (" + acceptedTaxon.getTitleCache()+")");
+ } else {
+ logger.info("Synonym relationship successfully exported: " + synonym.getTitleCache() + " " +acceptedTaxon.getUuid() + " (" + acceptedTaxon.getTitleCache()+")");
+ }
+ }
+
+ inferredSynonymsDataToBeSaved.put(synonym.getId(), synonym.getName());
+ }
+ }
+ }catch(Exception e){
+ logger.error(e.getMessage());
+ e.printStackTrace();
+ }
+ } else {
+ logger.error("Classification is NULL. Inferred Synonyms could not be created for this Taxon: " + acceptedTaxon.getUuid() + " (" + acceptedTaxon.getTitleCache() + ")");
+ }
+ } else {
+// logger.error("TaxonName is not a ZoologicalName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
+ }
+ } else {
+ logger.error("This TaxonBase is not a Taxon even though it should be: " + taxonBase.getUuid() + " (" + taxonBase.getTitleCache() + ")");
+ }
+ }
+ return inferredSynonymsDataToBeSaved;
+ }
+
+ /**
+ * Handles names that do not appear in taxa.
+ */
+ private boolean doPhase01b_Names(PesiExportState state, PesiExportMapping additionalSourceMapping) {
+
+ boolean success = true;
+ if (! state.getConfig().isDoPureNames()){
+ logger.info ("Ignore PHASE 1b: PureNames");
+ return success;
+ }
+
+ try {
+ PesiExportMapping mapping = getPureNameMapping(state);
+ mapping.initialize(state);
+ int count = 0;
+ int pastCount = 0;
+ success = true;
+ // Get the limit for objects to save within a single transaction.
+ int limit = state.getConfig().getLimitSave();
+
+ logger.info("PHASE 1b: Export Pure Names ...");
+ // Start transaction
+ TransactionStatus txStatus = startTransaction(true);
+ logger.info("Started new transaction for Pure Names. Fetching some " + pluralString + " (max: " + limit + ") ...");
+
+ int partitionCount = 0;
+ List<TaxonName> list;
+ while ((list = getNextPureNamePartition(null, limit, partitionCount++)) != null ) {
+
+ logger.debug("Fetched " + list.size() + pluralStringNames + " without taxa. Exporting...");
+ for (TaxonName taxonName : list) {
+ doCount(count++, modCount, pluralString);
+ success &= mapping.invoke(taxonName);
+ //additional source
+ if (taxonName.getNomenclaturalReference() != null || StringUtils.isNotBlank(taxonName.getNomenclaturalMicroReference() )){
+ additionalSourceMapping.invoke(taxonName);
+ }
+ }
+
+ // Commit transaction
+ commitTransaction(txStatus);
+ logger.debug("Committed transaction.");
+ logger.info("Exported " + (count - pastCount) + " " + pluralStringNames + ". Total: " + count + ". Partition: " + partitionCount);
+ pastCount = count;
+
+ // Start transaction
+ txStatus = startTransaction(true);
+ logger.debug("Started new transaction for PureNames. Fetching some " + pluralString + " (max: " + limit + ") ...");
+ }
+ logger.debug("No " + pluralString + " left to fetch.");
+
+ // Commit transaction
+ commitTransaction(txStatus);
+ logger.debug("Committed transaction.");
+ } catch (Exception e) {
+ logger.error("Error occurred in pure name export");
+ e.printStackTrace();
+ success = false;
+ }
+ return success;
+ }
+
+ /**
+ * Determines the current number of entries in the DataWarehouse database table <code>Taxon</code>.
+ * @param state The {@link PesiExportState PesiExportState}.
+ * @return The count.
+ */
+ private Integer determineTaxonCount(PesiExportState state) {
+ Integer result = null;
+ PesiExportConfigurator pesiConfig = state.getConfig();
+
+ String sql;
+ Source destination = pesiConfig.getDestination();
+ sql = "SELECT max(taxonId) FROM Taxon";
+ destination.setQuery(sql);
+ ResultSet resultSet = destination.getResultSet();
+ try {
+ resultSet.next();
+ result = resultSet.getInt(1);
+ } catch (SQLException e) {
+ logger.error("TaxonCount could not be determined: " + e.getMessage());
+ e.printStackTrace();
+ }
+ resultSet = null;
+ return result;
+ }
+
+ /**
+ * Checks whether a parent at specific level has a specific Rank.
+ * @param taxonName A {@link TaxonNameBase TaxonName}.
+ * @param level The ancestor level.
+ * @param ancestorRank The ancestor rank.
+ * @return Whether a parent at a specific level has a specific Rank.
+ */
+ private boolean validateAncestorOfSpecificRank(TaxonBase<?> taxonBase, int level, Rank ancestorRank) {
+ boolean result = false;
+ TaxonNode parentNode = null;
+ if (taxonBase.isInstanceOf(Taxon.class)){
+ Taxon taxon = CdmBase.deproxy(taxonBase, Taxon.class);
+ // Get ancestor Taxon via TaxonNode
+ Set<TaxonNode> taxonNodes = taxon.getTaxonNodes();
+ if (taxonNodes.size() == 1) {
+ TaxonNode taxonNode = taxonNodes.iterator().next();
+ if (taxonNode != null) {
+ for (int i = 0; i < level; i++) {
+ if (taxonNode != null) {
+ taxonNode = taxonNode.getParent();
+ }
+ }
+ parentNode = taxonNode;
+ }
+ } else if (taxonNodes.size() > 1) {
+ logger.error("This taxon has " + taxonNodes.size() + " taxonNodes: " + taxon.getUuid() + " (" + taxon.getTitleCache() + ")");
+ }
+ }
+ //compare
+ if (parentNode != null) {
+ TaxonNode node = CdmBase.deproxy(parentNode, TaxonNode.class);
+ Taxon parentTaxon = node.getTaxon();
+ if (parentTaxon != null) {
+ TaxonName parentTaxonName = parentTaxon.getName();
+ if (parentTaxonName != null && parentTaxonName.getRank().equals(ancestorRank)) {
+ result = true;
+ }
+ } else if (parentNode.treeIndex().matches("#t\\d+#\\d+#")) {
+ //do nothing (is root node)
+ } else {
+ logger.error("This TaxonNode has no Taxon: " + node.getUuid());
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Returns the AnnotationType for a given UUID.
+ * @param uuid The Annotation UUID.
+ * @param label The Annotation label.
+ * @param text The Annotation text.
+ * @param labelAbbrev The Annotation label abbreviation.
+ * @return The AnnotationType.
+ */
+ protected AnnotationType getAnnotationType(UUID uuid, String label, String text, String labelAbbrev){
+ AnnotationType annotationType = (AnnotationType)getTermService().find(uuid);
+ if (annotationType == null) {
+ annotationType = AnnotationType.NewInstance(label, text, labelAbbrev);
+ annotationType.setUuid(uuid);
+// annotationType.setVocabulary(AnnotationType.EDITORIAL().getVocabulary());
+ getTermService().save(annotationType);
+ }
+ return annotationType;
+ }
+
+ private boolean invokeParentTaxonFk(Integer parentId, Integer childId) {
+ try {
+ parentTaxonFkStmt.setInt(1, parentId);
+ parentTaxonFkStmt.setInt(2, childId);
+ parentTaxonFkStmt.executeUpdate();
+ return true;
+ } catch (SQLException e) {
+ logger.warn("ParentTaxonFk (" + (parentId ==null? "-":parentId) + ") could not be inserted into database "
+ + "for taxon "+ (childId == null? "-" :childId) + ": " + e.getMessage());
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+
+ /**
+ * Inserts Rank data and KingdomFk into the Taxon database table.
+ * @param taxonName The {@link TaxonNameBase TaxonName}.
+ * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
+ * @param taxonFk The TaxonFk to store the values for.
+ * @param state
+ * @param kindomFk The KingdomFk.
+ * @return Whether save was successful or not.
+ */
+ private boolean invokeRankDataAndKingdomFk(TaxonName taxonName,
+ Integer taxonFk, Integer kingdomFk, PesiExportState state) {
+
+ try {
+ Integer rankFk = getRankFk(taxonName, kingdomFk);
+ if (rankFk != null) {
+ rankUpdateStmt.setInt(1, rankFk);
+ } else {
+ rankUpdateStmt.setObject(1, null);
+ }
+
+ String rankCache = getRankCache(taxonName, kingdomFk, state);
+ if (rankCache != null) {
+ rankUpdateStmt.setString(2, rankCache);
+ } else {
+ rankUpdateStmt.setObject(2, null);
+ }
+
+ if (kingdomFk != null) {
+
+ rankUpdateStmt.setInt(3, kingdomFk);
+ } else {
+ rankUpdateStmt.setObject(3, null);
+ }
+
+ if (taxonFk != null) {
+ rankUpdateStmt.setInt(4, taxonFk);
+ } else {
+ rankUpdateStmt.setObject(4, null);
+ }
+
+ rankUpdateStmt.executeUpdate();
+ return true;
+ } catch (SQLException e) {
+ logger.error("Data (RankFk, RankCache, KingdomFk) could not be inserted into database: " + e.getMessage());
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+ /**
+ * Inserts Rank data, TypeNameFk, KingdomFk, expertFk and speciesExpertFk into the Taxon database table.
+ * @param taxonName The {@link TaxonNameBase TaxonName}.
+ * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
+ * @param taxonFk The TaxonFk to store the values for.
+ * @param typeNameFk The TypeNameFk.
+ * @param rankFk
+ * @param state
+ * @param kindomFk The KingdomFk.
+ * @param expertFk The ExpertFk.
+ * @param speciesExpertFk The SpeciesExpertFk.
+ * @return Whether save was successful or not.
+ */
+ private boolean invokeRankDataAndTypeNameFkAndKingdomFk(TaxonName taxonName,
+ Integer taxonFk, Integer typeNameFk, Integer kingdomFk, Integer rankFk, PesiExportState state) {
+
+ try {
+ int index = 1;
+ if (rankFk != null) {
+ rankTypeExpertsUpdateStmt.setInt(index++, rankFk);
+ } else {
+ rankTypeExpertsUpdateStmt.setObject(index++, null);
+ }
+
+ String rankCache = getRankCache(taxonName, kingdomFk, state);
+ if (rankCache != null) {
+ rankTypeExpertsUpdateStmt.setString(index++, rankCache);
+ } else {
+ rankTypeExpertsUpdateStmt.setObject(index++, null);
+ }
+
+ if (typeNameFk != null) {
+ rankTypeExpertsUpdateStmt.setInt(index++, typeNameFk);
+ } else {
+ rankTypeExpertsUpdateStmt.setObject(index++, null);
+ }
+
+ if (kingdomFk != null) {
+ rankTypeExpertsUpdateStmt.setInt(index++, kingdomFk);
+ } else {
+ rankTypeExpertsUpdateStmt.setObject(index++, null);
+ }
+
+// if (expertFk != null) {
+// rankTypeExpertsUpdateStmt.setInt(5, expertFk);
+// } else {
+// rankTypeExpertsUpdateStmt.setObject(5, null);
+// }
+//
+// //TODO handle experts GUIDS
+// if (speciesExpertFk != null) {
+// rankTypeExpertsUpdateStmt.setInt(6, speciesExpertFk);
+// } else {
+// rankTypeExpertsUpdateStmt.setObject(6, null);
+// }
+//
+ if (taxonFk != null) {
+ rankTypeExpertsUpdateStmt.setInt(index++, taxonFk);
+ } else {
+ rankTypeExpertsUpdateStmt.setObject(index++, null);
+ }
+
+ rankTypeExpertsUpdateStmt.executeUpdate();
+ return true;
+ } catch (SQLException e) {
+ String name = taxonName == null? null:taxonName.getTitleCache();
+ logger.error("Data could not be inserted into database: " + e.getMessage() + "; rankFk = " + rankFk + "; kingdomFk = " + kingdomFk + "; taxonFk = "+ taxonFk + "; typeNameFk = " + typeNameFk + "; name = " + name);
+ e.printStackTrace();
+ return false;
+ } catch (Exception e) {
+ String name = taxonName == null? null:taxonName.getTitleCache();
+ logger.error("Some exception occurred: " + e.getMessage() + "; rankFk = " + rankFk + "; kingdomFk = " + kingdomFk + "; taxonFk = "+ taxonFk + "; typeNameFk = " + typeNameFk + "; name = " + name);
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+ /**
+ * Deletes all entries of database tables related to <code>Taxon</code>.
+ * @param state The {@link PesiExportState PesiExportState}.
+ * @return Whether the delete operation was successful or not.
+ */
+ protected boolean doDelete(PesiExportState state) {
+
+ Source destination = state.getConfig().getDestination();
+
+ String[] tables = new String[]{"AdditionalTaxonSource","CommonNameSource","CommonName",
+ "Image","NoteSource","Note","OccurrenceSource","Occurrence","RelTaxon","Taxon"};
+
+ for(String table : tables){
+ String sql = "DELETE FROM " + table;
+ destination.update(sql);
+ }
+
+ return true;
+ }
+
+ private static Integer getRankFk(TaxonName taxonName, NomenclaturalCode nomenclaturalCode) {
+ Integer kingdomId = PesiTransformer.nomenclaturalCode2Kingdom(nomenclaturalCode);
+ return getRankFk(taxonName, kingdomId);
+ }
+
+ /**
+ * Returns the <code>RankFk</code> attribute.
+ * @param taxonName The {@link TaxonNameBase TaxonName}.
+ * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
+ * @return The <code>RankFk</code> attribute.
+ * @see MethodMapper
+ */
+ private static Integer getRankFk(TaxonName taxonName, Integer kingdomId) {
+ Integer result = null;
+ try {
+ if (taxonName != null) {
+ if (taxonName.getRank() == null) {
+ logger.warn("Rank is null: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
+ } else {
+ result = PesiTransformer.rank2RankId(taxonName.getRank(), kingdomId);
+ }
+ if (result == null) {
+ logger.warn("Rank could not be determined for PESI-Kingdom-Id " + kingdomId + " and TaxonName " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return result;
+ }
+
+ @SuppressWarnings("unused") //used by mapper
+ private static String getRankCache(TaxonName taxonName, PesiExportState state) {
+ List<TaxonNode> nodes = getTaxonNodes(taxonName);
+ Integer kingdomId;
+ if (nodes == null||nodes.isEmpty()){
+ kingdomId = getKingdomFk(taxonName);
+ }else{
+ //should not happen, method exists only pure names
+ kingdomId = findKingdomIdFromTreeIndex(nodes.iterator().next().getTaxon(), state);
+ }
+ return getRankCache(taxonName, kingdomId, state);
+ }
+
+ private static String getRankCache(TaxonName taxonName, Integer kingdomFk, PesiExportState state) {
+ if (Rank.DOMAIN().equals(taxonName.getRank())){
+ return state.getTransformer().getCacheByRankAndKingdom(Rank.DOMAIN(), null);
+ }else if (kingdomFk != null) {
+ return state.getTransformer().getCacheByRankAndKingdom(taxonName.getRank(), kingdomFk);
+ }else if (taxonName.getNameType() != null){
+ return state.getTransformer().getCacheByRankAndKingdom(taxonName.getRank(), PesiTransformer.nomenclaturalCode2Kingdom(taxonName.getNameType()));
+ }else{
+ logger.warn("No kingdom ID could be defined for name " + taxonName.getUuid());
+ return null;
+ }
+ }
+
+ private static List<TaxonNode> getTaxonNodes(TaxonName taxonName) {
+ List<TaxonNode> result = new ArrayList<>();
+ for (TaxonBase<?> tb:taxonName.getTaxonBases()){
+ Taxon taxon;
+ //TODO handle ERMS taxon relationships
+ if (tb.isInstanceOf(Taxon.class)){
+ taxon = CdmBase.deproxy(tb, Taxon.class);
+ }else{
+ taxon = CdmBase.deproxy(tb, Synonym.class).getAcceptedTaxon();
+ }
+ if (isPesiTaxon(taxon)){
+ for (TaxonNode node : taxon.getTaxonNodes()){
+ result.add(node);
+ }
+ }
+ }
+ return result;
+ }
+
+// @SuppressWarnings("unused") //used by pure name mapper and by getRankFk
+ private static Integer getKingdomFk(TaxonName taxonName){
+ EnumSet<PesiSource> origin = getSources(taxonName);
+ if (origin.size() == 1 && origin.contains(PesiSource.EM)){
+ //maybe simply replace by
+ //return PesiTransformer.KINGDOM_PLANTAE;
+ return PesiTransformer.nomenclaturalCode2Kingdom(taxonName.getNameType());
+ }else{
+ logger.warn("getKingdomFk not yet implemented for non-EuroMed pure names");
+ return null;
+ }
+ }
+
+ /**
+ * Returns the rankFk for the taxon name based on the names nomenclatural code.
+ * You may not use this method for kingdoms other then Animalia, Plantae and Bacteria.
+ */
+ @SuppressWarnings("unused") //used by pure name mapper
+ private static Integer getRankFk(TaxonName taxonName) {
+ EnumSet<PesiSource> origin = getSources(taxonName);
+ if (origin.size() == 1 && origin.contains(PesiSource.EM)){
+ return getRankFk(taxonName, getKingdomFk(taxonName));
+ }else{
+ logger.warn("getRankFk not yet implemented for non-EuroMed pure names");
+ return null;
+ }
+ }
+
+ /**
+ * Returns the <code>AuthorString</code> attribute.
+ * @param taxonName The {@link TaxonNameBase TaxonName}.
+ * @return The <code>AuthorString</code> attribute.
+ * @see MethodMapper
+ */
+ //used by mapper
+ protected static String getAuthorString(TaxonBase<?> taxon) {
+ try {
+ // For misapplied names there are special rules
+ if (isMisappliedName(taxon)){
+ return getMisappliedNameAuthorship(taxon);
+ }else{
+ boolean isNonViralName = false;
+ String authorshipCache = null;
+ TaxonName taxonName = taxon.getName();
+ if (taxonName != null && taxonName.isNonViral()){
+ authorshipCache = taxonName.getAuthorshipCache();
+ isNonViralName = true;
+ }
+ String result = authorshipCache;
+
+ if (taxonName == null){
+ logger.warn("TaxonName does not exist for taxon: " + taxon.getUuid() + " (" + taxon.getTitleCache() + ")");
+ }else if (! isNonViralName){
+ logger.warn("TaxonName is not of instance NonViralName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
+ }
+
+ if (StringUtils.isBlank(result)) {
+ return null;
+ } else {
+ return result;
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ private static String getMisappliedNameAuthorship(TaxonBase<?> taxon){
+ String result;
+ String relAppendedPhrase = taxon.getAppendedPhrase();
+ Reference sec = taxon.getSec();
+ String secTitle = sec != null ? sec.getTitleCache(): null;
+ if(relAppendedPhrase == null && sec == null) {
+ result = "auct.";
+ }else if (relAppendedPhrase != null && sec == null){
+ result = relAppendedPhrase;
+ }else if (relAppendedPhrase == null && sec != null){
+ result = "sensu " + secTitle;
+ }else{ //append!=null && sec!=null
+ result = relAppendedPhrase + " " + secTitle;
+ }
+ String authorship = taxon.getName().getAuthorshipCache();
+ if (isNotBlank(authorship)){
+ result += ", non " + authorship;
+ }
+ return result;
+ }
+
+ /**
+ * Returns the <code>DisplayName</code> attribute.
+ * @param taxon The {@link TaxonBase Taxon}.
+ * @return The <code>DisplayName</code> attribute.
+ * @see MethodMapper
+ */
+ //used by Mapper
+ private static String getDisplayName(TaxonBase<?> taxon) {
+ boolean isMisapplied = isMisappliedName(taxon);
+ TaxonName taxonName = taxon.getName();
+ String result = getDisplayName(taxonName, isMisapplied);
+ if (isMisapplied){
+ result = result + " " + getMisappliedNameAuthorship(taxon);
+ }
+ return result;
+ }
+
+ /**
+ * Returns the <code>DisplayName</code> attribute.
+ * @param taxonName The {@link TaxonNameBase TaxonName}.
+ * @return The <code>DisplayName</code> attribute.
+ * @see MethodMapper
+ */
+ @SuppressWarnings("unused") //used by Mapper
+ private static String getDisplayName(TaxonName taxonName) {
+ return getDisplayName(taxonName, false);
+ }
+
+ private static String getDisplayName(TaxonName taxonName, boolean useNameCache) {
+ if (taxonName == null) {
+ return null;
+ }else{
+ taxonName = CdmBase.deproxy(taxonName);
+ INonViralNameCacheStrategy cacheStrategy = getCacheStrategy(taxonName);
+ HTMLTagRules tagRules = new HTMLTagRules().
+ addRule(TagEnum.name, "i").
+ addRule(TagEnum.nomStatus, "@status@");
+
+ String result;
+ if (useNameCache){
+ result = cacheStrategy.getNameCache(taxonName, tagRules);
+ }else{
+ EnumSet<PesiSource> sources = getSources(taxonName);
+ if (sources.contains(PesiSource.ERMS)){
+ result = cacheStrategy.getTitleCache(taxonName, tagRules); //according to SQL script (also in ERMS sources are not abbreviated)
+ }else if (sources.contains(PesiSource.FE) || sources.contains(PesiSource.IF)){
+ //TODO define for FE + IF and for multiple sources
+ result = cacheStrategy.getFullTitleCache(taxonName, tagRules);
+ }else if (sources.contains(PesiSource.EM)){
+ result = cacheStrategy.getFullTitleCache(taxonName, tagRules);
+ }else{
+ logger.warn("Source not yet handled");
+ result = cacheStrategy.getTitleCache(taxonName, tagRules);
+ }
+ result = replaceTagForInfraSpecificMarkerForProtectedTitleCache(taxonName, result);
+ result = result.replaceAll("(, ?)?\\<@status@\\>.*\\</@status@\\>", "").trim();
+ }
+ return result;
+ }
+ }
+
+ /**
+ * Returns the <code>WebShowName</code> attribute for a taxon.
+ * See {@link #getWebShowName(TaxonName)} for further explanations.
+ * @param taxon The {@link TaxonBase taxon}.
+ * @return The <code>WebShowName</code> attribute.
+ * @see #getWebShowName(TaxonName)
+ * @see #getDisplayName(TaxonBase)
+ * @see #getFullName(TaxonBase)
+ * @see MethodMapper
+ */
+ @SuppressWarnings("unused")
+ private static String getWebShowName(TaxonBase<?> taxon) {
+ if (isMisappliedName(taxon)){
+ //for misapplications the webshowname is the same as the displayname as they do not show the nom.ref. in displayname
+ return getDisplayName(taxon);
+ }else{
+ TaxonName taxonName = taxon.getName();
+ return getWebShowName(taxonName);
+ }
+ }
+
+ /**
+ * Returns the <code>WebShowName</code> attribute for a name. The
+ * <code>WebShowName</code> is like fullName but with
+ * tagged (<i>) name part. It is also similar to
+ * <code>DisplayName</code> but for titleCache not fullTitleCache.
+ * For misapplications it slightly differs (see {@link #getWebShowName(TaxonBase)} )
+ *
+ * @param taxonName The {@link TaxonNameBase TaxonName}.
+ * @return The <code>WebShowName</code> attribute.
+ * @see #getDisplayName(TaxonName)
+ * @see #getFullName(TaxonName)
+ * @see #getWebShowName(TaxonBase)
+ * @see MethodMapper
+ */
+ private static String getWebShowName(TaxonName taxonName) {
+ if (taxonName == null) {
+ return null;
+ }else{
+ taxonName = CdmBase.deproxy(taxonName);
+ INonViralNameCacheStrategy cacheStrategy = getCacheStrategy(taxonName);
+
+ HTMLTagRules tagRules = new HTMLTagRules().addRule(TagEnum.name, "i");
+ String result = cacheStrategy.getTitleCache(taxonName, tagRules);
+ result = replaceTagForInfraSpecificMarkerForProtectedTitleCache(taxonName, result);
+ return result;
+ }
+ }
+
+ private static String replaceTagForInfraSpecificMarkerForProtectedTitleCache(TaxonName taxonName, String result) {
+ if (taxonName.isProtectedTitleCache()||taxonName.isProtectedNameCache()){
+ if (!taxonName.isAutonym()){
+ result = result
+ .replace(" subsp. ", "</i> subsp. <i>")
+ .replace(" var. ", "</i> var. <i>")
+ .replace(" subvar. ", "</i> subvar. <i>")
+ .replace(" f. ", "</i> f. <i>")
+ .replace(" subf. ", "</i> subf. <i>") //does this exist?
+ ;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Returns the <code>WebSearchName</code> attribute.
+ * @param taxonName The {@link NonViralName NonViralName}.
+ * @return The <code>WebSearchName</code> attribute.
+ * @see MethodMapper
+ */
+ @SuppressWarnings("unused")
+ private static String getWebSearchName(TaxonName taxonName) {
+ //TODO extensions?
+ TaxonNameDefaultCacheStrategy strategy = getCacheStrategy(taxonName);
+ String result = strategy.getNameCache(taxonName);
+ return result;
+ }
+
+ @SuppressWarnings("unused") //used by mapper
+ private static String getFullName(TaxonBase<?> taxon) {
+ if (isMisappliedName(taxon)){
+ String result = getCacheStrategy(taxon.getName()).getNameCache(taxon.getName());
+ result = result + " " + getMisappliedNameAuthorship(taxon);
+ return result;
+ }else{
+ return getFullName(taxon.getName());
+ }
+ }
+
+ /**
+ * Returns the <code>FullName</code> attribute.
+ * @param taxonName The {@link NonViralName NonViralName}.
+ * @return The <code>FullName</code> attribute.
+ * @see MethodMapper
+ */
+ //used by mapper
+ private static String getFullName(TaxonName taxonName) {
+ //TODO extensions?
+ String result = getCacheStrategy(taxonName).getTitleCache(taxonName);
+ //misapplied names are now handled differently in getFullName(TaxonBase)
+// Iterator<Taxon> taxa = taxonName.getTaxa().iterator();
+// if (taxonName.getTaxa().size() >0){
+// if (taxonName.getTaxa().size() == 1){
+// Taxon taxon = taxa.next();
+// if (isMisappliedName(taxon)){
+// result = result + " " + getAuthorString(taxon);
+// }
+// }
+// }
+ return result;
+ }
+
+ @SuppressWarnings("unused")
+ private static String getGUID(TaxonName taxonName) {
+ UUID uuid = taxonName.getUuid();
+ String result = "NameUUID:" + uuid.toString();
+ return result;
+ }
+
+ static boolean isFirstAbbrevTitle = true;
+ /**
+ * Returns the SourceNameCache for the AdditionalSource table
+ */
+ @SuppressWarnings("unused")
+ private static String getSourceNameCache(TaxonName taxonName) {
+ if (taxonName != null){
+ Reference nomRef = taxonName.getNomenclaturalReference();
+ if (nomRef != null ){
+ if (isFirstAbbrevTitle){
+ //#5388 is definetely not the correct ticket number
+ logger.warn("Semantics of getAbbrevTitleCache has changed. Please check if output is still correct. See #5388");
+ isFirstAbbrevTitle = false;
+ }
+ return nomRef.getAbbrevTitleCache();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the nomenclatural reference which is the reference
+ * including the detail (microreference).
+ * @param taxonName The {@link TaxonName taxon name}.
+ * @see MethodMapper
+ */
+ @SuppressWarnings("unused")
+ private static String getNomRefString(TaxonName taxonName) {
+ INomenclaturalReference ref = taxonName.getNomenclaturalReference();
+ if (ref == null){
+ return null;
+ }
+ String result = null;
+ EnumSet<PesiSource> sources = getSources(taxonName);
+ if(sources.contains(PesiSource.EM)){
+ if (! ref.isProtectedAbbrevTitleCache()){
+ ref.setAbbrevTitleCache(null, false); //to remove a false cache
+ }
+ result = ref.getNomenclaturalCitation(taxonName.getNomenclaturalMicroReference());
+ }else if(sources.contains(PesiSource.FE)||sources.contains(PesiSource.IF) ){
+ //TODO still need to check if correct for FE + IF
+ if (! ref.isProtectedAbbrevTitleCache()){
+ ref.setAbbrevTitleCache(null, false); //to remove a false cache
+ }
+ result = ref.getNomenclaturalCitation(taxonName.getNomenclaturalMicroReference());
+ return result; // according to SQL script
+ }else if(sources.contains(PesiSource.ERMS)) {
+ //result = null; //according to SQL script
+ }else{
+ logger.warn("Source not yet supported");
+ }
+ return result;
+ }
+
+ /**
+ * Returns the <code>NameStatusFk</code> attribute.
+ * @param taxonName The {@link TaxonNameBase TaxonName}.
+ * @return The <code>NameStatusFk</code> attribute.
+ * @see MethodMapper
+ */
+ @SuppressWarnings("unused")
+ private static Integer getNameStatusFk(TaxonName taxonName) {
+ Integer result = null;
+
+ NomenclaturalStatus status = getNameStatus(taxonName);
+ if (status != null) {
+ result = PesiTransformer.nomStatus2nomStatusFk(status.getType());
+ }
+ return result;
+ }
+
+ /**
+ * Returns the <code>NameStatusCache</code> attribute.
+ * @param taxonName The {@link TaxonNameBase TaxonName}.
+ * @return The <code>NameStatusCache</code> attribute.
+ * @throws UndefinedTransformerMethodException
+ * @see MethodMapper
+ */
+ @SuppressWarnings("unused")
+ private static String getNameStatusCache(TaxonName taxonName, PesiExportState state) throws UndefinedTransformerMethodException {
+ String result = null;
+ NomenclaturalStatus status = getNameStatus(taxonName);
+ if (status != null) {
+ result = state.getTransformer().getCacheByNomStatus(status.getType());
+ }
+ return result;
+ }
+
+ private static NomenclaturalStatus getNameStatus(TaxonName taxonName) {
+ try {
+ if (taxonName != null) {
+ Set<NomenclaturalStatus> states = taxonName.getStatus();
+ if (states.size() >= 1) {
+ if (states.size() > 1) {
+ String statusStr = null;
+ for (NomenclaturalStatus status: states){
+ statusStr = CdmUtils.concat(",", statusStr, status.getType()== null? null:status.getType().getTitleCache());
+ }
+ //a known case is ad43508a-8a10-480a-8519-2a76de2c0a0f (Labiatae Juss.) from E+M
+ logger.warn("This TaxonName has more than one nomenclatural status. This may happen in very rare cases but is not handled by the PESI data warehouse. Taxon name: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")Status:" + statusStr);
+ }
+ NomenclaturalStatus status = states.iterator().next();
+ return status;
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * Returns the <code>TaxonStatusFk</code> attribute.
+ * @param taxonName The {@link TaxonNameBase TaxonName}.
+ * @param state The {@link PesiExportState PesiExportState}.
+ * @return The <code>TaxonStatusFk</code> attribute.
+ * @see MethodMapper
+ */
+ private static Integer getTaxonStatusFk(TaxonBase<?> taxon, PesiExportState state) {
+ try {
+ return PesiTransformer.taxonBase2statusFk(taxon);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ /**
+ * Returns the <code>TaxonStatusCache</code> attribute.
+ * @param taxonName The {@link TaxonNameBase TaxonName}.
+ * @param state The {@link PesiExportState PesiExportState}.
+ * @return The <code>TaxonStatusCache</code> attribute.
+ * @throws UndefinedTransformerMethodException
+ * @see MethodMapper
+ */
+ @SuppressWarnings("unused")
+ private static String getTaxonStatusCache(TaxonBase<?> taxon, PesiExportState state) throws UndefinedTransformerMethodException {
+ return state.getTransformer().getTaxonStatusCacheByKey(getTaxonStatusFk(taxon, state));
+ }
+
+ /**
+ * Returns the <code>TaxonFk1</code> attribute. It corresponds to a CDM <code>TaxonRelationship</code>.
+ * @param relationship The {@link RelationshipBase Relationship}.
+ * @param state The {@link PesiExportState PesiExportState}.
+ * @return The <code>TaxonFk1</code> attribute.
+ * @see MethodMapper
+ */
+ @SuppressWarnings("unused")
+ private static Integer getSynonym(Synonym synonym, PesiExportState state) {
+ return state.getDbId(synonym);
+ }
+
+ /**
+ * Returns the <code>TypeNameFk</code> attribute.
+ * @param taxonName The {@link TaxonNameBase TaxonName}.
+ * @param state The {@link PesiExportState PesiExportState}.
+ * @return The <code>TypeNameFk</code> attribute.
+ * @see MethodMapper
+ */
+ private static Integer getTypeNameFk(TaxonName taxonName, PesiExportState state) {
+ Integer result = null;
+ if (taxonName != null) {
+ Set<NameTypeDesignation> nameTypeDesignations = taxonName.getNameTypeDesignations();
+ if (nameTypeDesignations.size() == 1) {
+ NameTypeDesignation nameTypeDesignation = nameTypeDesignations.iterator().next();
+ if (nameTypeDesignation != null) {
+ TaxonName typeName = nameTypeDesignation.getTypeName();
+ if (typeName != null) {
+ if (typeName.getTaxonBases().isEmpty()){
+ logger.warn("Type name does not belong to a taxon and therefore is not expected to be a European taxon. Type name not added. Type name: " + typeName.getTitleCache() + ", typified name: " + taxonName.getTitleCache());
+ }else{
+ result = state.getDbId(typeName);
+ }
+ }
+ }
+ } else if (nameTypeDesignations.size() > 1) {
+ logger.warn("This TaxonName has " + nameTypeDesignations.size() + " NameTypeDesignations: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Returns the <code>TypeFullnameCache</code> attribute.
+ * @param taxonName The {@link TaxonNameBase TaxonName}.
+ * @return The <code>TypeFullnameCache</code> attribute.
+ * @see MethodMapper
+ */
+ @SuppressWarnings("unused")
+ private static String getTypeFullnameCache(TaxonName taxonName) {
+ String result = null;
+
+ try {
+ if (taxonName != null) {
+ Set<NameTypeDesignation> nameTypeDesignations = taxonName.getNameTypeDesignations();
+ if (nameTypeDesignations.size() == 1) {
+ NameTypeDesignation nameTypeDesignation = nameTypeDesignations.iterator().next();
+ if (nameTypeDesignation != null) {
+ TaxonName typeName = nameTypeDesignation.getTypeName();
+ if (typeName != null) {
+ result = typeName.getTitleCache();
+ }
+ }
+ } else if (nameTypeDesignations.size() > 1) {
+ logger.warn("This TaxonName has " + nameTypeDesignations.size() + " NameTypeDesignations: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return result;
+ }
+
+
+ /**
+ * Returns the <code>QualityStatusFk</code> attribute.
+ * @param taxonName The {@link TaxonNameBase TaxonName}.
+ * @return The <code>QualityStatusFk</code> attribute.
+ * @see MethodMapper
+ */
+ private static Integer getQualityStatusFk(TaxonName taxonName) {
+ EnumSet<PesiSource> sources = getSources(taxonName);
+ return PesiTransformer.getQualityStatusKeyBySource(sources, taxonName);
+ }
+
+ /**
+ * Returns the <code>QualityStatusCache</code> attribute.
+ * @param taxonName The {@link TaxonNameBase TaxonName}.
+ * @return The <code>QualityStatusCache</code> attribute.
+ * @throws UndefinedTransformerMethodException
+ * @see MethodMapper
+ */
+ @SuppressWarnings("unused")
+ private static String getQualityStatusCache(TaxonName taxonName, PesiExportState state) throws UndefinedTransformerMethodException {
+ return state.getTransformer().getQualityStatusCacheByKey(getQualityStatusFk(taxonName));
+ }
+
+
+ /**
+ * Returns the <code>TypeDesignationStatusFk</code> attribute.
+ * @param taxonName The {@link TaxonNameBase TaxonName}.
+ * @return The <code>TypeDesignationStatusFk</code> attribute.
+ * @see MethodMapper
+ */
+ //TODO seems not to be used
+ private static Integer getTypeDesignationStatusFk(TaxonName taxonName) {
+ Integer result = null;
+
+ try {
+ if (taxonName != null) {
+ Set<NameTypeDesignation> typeDesignations = taxonName.getNameTypeDesignations();
+ if (typeDesignations.size() == 1) {
+ Object obj = typeDesignations.iterator().next().getTypeStatus();
+ NameTypeDesignationStatus designationStatus = CdmBase.deproxy(obj, NameTypeDesignationStatus.class);
+ result = PesiTransformer.nameTypeDesignationStatus2TypeDesignationStatusId(designationStatus);
+ } else if (typeDesignations.size() > 1) {
+ logger.error("Found a TaxonName with more than one NameTypeDesignation: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return result;
+ }
+
+ /**
+ * Returns the <code>TypeDesignationStatusCache</code> attribute.
+ * @param taxonName The {@link TaxonNameBase TaxonName}.
+ * @return The <code>TypeDesignationStatusCache</code> attribute.
+ * @see MethodMapper
+ */
+ //TODO seems not to be used
+ private static String getTypeDesignationStatusCache(TaxonName taxonName) {
+ String result = null;
+
+ try {
+ if (taxonName != null) {
+ Set<NameTypeDesignation> typeDesignations = taxonName.getNameTypeDesignations();
+ if (typeDesignations.size() == 1) {
+ Object obj = typeDesignations.iterator().next().getTypeStatus();
+ NameTypeDesignationStatus designationStatus = CdmBase.deproxy(obj, NameTypeDesignationStatus.class);
+ result = PesiTransformer.nameTypeDesignationStatus2TypeDesignationStatusCache(designationStatus);
+ } else if (typeDesignations.size() > 1) {
+ logger.error("Found a TaxonName with more than one NameTypeDesignation: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return result;
+ }
+
+ /**
+ * Returns the <code>FossilStatusFk</code> attribute.
+ * @param taxonName The {@link TaxonNameBase TaxonName}.
+ * @return The <code>FossilStatusFk</code> attribute.
+ * @see MethodMapper
+ */
+ @SuppressWarnings("unused")
+ private static Integer getFossilStatusFk(IdentifiableEntity<?> identEntity, PesiExportState state) {
+ Integer result = null;
+
+ Set<String> fossilStatuus = identEntity.getExtensions(ErmsTransformer.uuidExtFossilStatus);
+ if (fossilStatuus.size() == 0){
+ return null;
+ }else if (fossilStatuus.size() > 1){
+ logger.warn("More than 1 fossil status given for " + identEntity.getTitleCache() + " " + identEntity.getUuid());
+ }
+ String fossilStatus = fossilStatuus.iterator().next();
+
+ int statusFk = state.getTransformer().fossilStatusCache2FossilStatusFk(fossilStatus);
+ return statusFk;
+ }
+
+ /**
+ * Returns the <code>FossilStatusCache</code> attribute.
+ * @param taxonName The {@link TaxonNameBase TaxonName}.
+ * @return The <code>FossilStatusCache</code> attribute.
+ * @see MethodMapper
+ */
+ @SuppressWarnings("unused")
+ private static String getFossilStatusCache(IdentifiableEntity<?> identEntity, PesiExportState state) {
+ String result = null;
+ Set<String> fossilStatuus = identEntity.getExtensions(ErmsTransformer.uuidExtFossilStatus);
+ if (fossilStatuus.size() == 0){
+ return null;
+ }
+ for (String strFossilStatus : fossilStatuus){
+ result = CdmUtils.concat(";", result, strFossilStatus);
+ }
+ return result;
+ }
+
+ /**
+ * Returns the <code>IdInSource</code> attribute.
+ * @param taxonName The {@link TaxonNameBase TaxonName}.
+ * @return The <code>IdInSource</code> attribute.
+ * @see MethodMapper
+ */
+ @SuppressWarnings("unused")
+ private static String getIdInSource(IdentifiableEntity<?> taxonName) {
+ String result = null;
+
+ try {
+ Set<IdentifiableSource> sources = getPesiSources(taxonName);
+ if (sources.size() > 1){
+ logger.warn("There is > 1 Pesi source. This is not yet handled.");
+ }
+ if (sources.size() == 0){
+ logger.warn("There is no Pesi source!" +taxonName.getUuid() + " (" + taxonName.getTitleCache() +")");
+ }
+ for (IdentifiableSource source : sources) {
+ Reference ref = source.getCitation();
+ UUID refUuid = ref.getUuid();
+ String idInSource = source.getIdInSource();
+ if (refUuid.equals(PesiTransformer.uuidSourceRefEuroMed)){
+ result = idInSource != null ? ("NameId: " + source.getIdInSource()) : null;
+ }else if (refUuid.equals(PesiTransformer.uuidSourceRefFaunaEuropaea)){
+ result = idInSource != null ? ("TAX_ID: " + source.getIdInSource()) : null;
+ }else if (refUuid.equals(PesiTransformer.uuidSourceRefErms)){
+ result = idInSource != null ? ("tu_id: " + source.getIdInSource()) : null;
+ }else if (refUuid.equals(PesiTransformer.uuidSourceRefIndexFungorum)){ //Index Fungorum
+ result = idInSource != null ? ("if_id: " + source.getIdInSource()) : null;
+ }else{
+ if (logger.isDebugEnabled()){logger.debug("Not a PESI source");}
+ }
+
+ String sourceIdNameSpace = source.getIdNamespace();
+ if (sourceIdNameSpace != null) {
+ if (sourceIdNameSpace.equals(PesiTransformer.STR_NAMESPACE_NOMINAL_TAXON)) {
+ result = idInSource != null ? ("Nominal Taxon from TAX_ID: " + source.getIdInSource()):null;
+ } else if (sourceIdNameSpace.equals(TaxonServiceImpl.INFERRED_EPITHET_NAMESPACE)) {
+ result = idInSource != null ? ("Inferred epithet from TAX_ID: " + source.getIdInSource()) : null;
+ } else if (sourceIdNameSpace.equals(TaxonServiceImpl.INFERRED_GENUS_NAMESPACE)) {
+ result = idInSource != null ? ("Inferred genus from TAX_ID: " + source.getIdInSource()):null;
+ } else if (sourceIdNameSpace.equals(TaxonServiceImpl.POTENTIAL_COMBINATION_NAMESPACE)) {
+ result = idInSource != null ? ("Potential combination from TAX_ID: " + source.getIdInSource()):null;
+ }
+ }
+ if (result == null) {
+ logger.warn("IdInSource is NULL for this taxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() +", sourceIdNameSpace: " + source.getIdNamespace()+")");
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ logger.error("An error occurs while creating idInSource..." + taxonName.getUuid() + " (" + taxonName.getTitleCache()+ e.getMessage());
+ }
+
+ if (result == null) {
+ logger.warn("IdInSource is NULL for this taxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() +")");
+ }
+ return result;
+ }
+
+ /**
+ * Returns the idInSource for a given TaxonName only.
+ * @param taxonName The {@link TaxonNameBase TaxonName}.
+ * @return The idInSource.
+ */
+ private static String getIdInSourceOnly(IdentifiableEntity<?> identEntity) {
+ String result = null;
+
+ // Get the sources first
+ Set<IdentifiableSource> sources = getPesiSources(identEntity);
+
+ // Determine the idInSource
+ if (sources.size() == 1) {
+ IdentifiableSource source = sources.iterator().next();
+ if (source != null) {
+ result = source.getIdInSource();
+ }
+ } else if (sources.size() > 1) {
+ int count = 1;
+ result = "";
+ for (IdentifiableSource source : sources) {
+ result += source.getIdInSource();
+ if (count < sources.size()) {
+ result += "; ";
+ }
+ count++;
+ }
+
+ }
+
+ return result;
+ }
+
+ /**
+ * Returns the <code>GUID</code> attribute.
+ * @param taxonName The {@link TaxonNameBase TaxonName}.
+ * @return The <code>GUID</code> attribute.
+ * @see MethodMapper
+ */
+ private static String getGUID(TaxonBase<?> taxon) {
+ if (taxon.getLsid() != null ){
+ return taxon.getLsid().getLsid();
+ }else if (taxon.hasMarker(PesiTransformer.uuidMarkerGuidIsMissing, true)){
+ return null;
+ }else{
+ return taxon.getUuid().toString();
+ }
+ }
+
+ /**
+ * Returns the <code>DerivedFromGuid</code> attribute.
+ * @param taxonName The {@link TaxonNameBase TaxonName}.
+ * @return The <code>DerivedFromGuid</code> attribute.
+ * @see MethodMapper
+ */
+ @SuppressWarnings("unused")
+ private static String getDerivedFromGuid(TaxonBase<?> taxon) {
+ String result = null;
+ try {
+ // The same as GUID for now
+ result = getGUID(taxon);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return result;
+ }
+
+ /**
+ * Returns the <code>CacheCitation</code> attribute.
+ * @param taxonName The {@link TaxonNameBase TaxonName}.
+ * @return The CacheCitation.
+ * @see MethodMapper
+ */
+ @SuppressWarnings("unused")
+ private static String getCacheCitation(TaxonBase<?> taxon) {
+ // !!! See also doPhaseUpdates
+
+ TaxonName taxonName = taxon.getName();
+ String result = "";
+ //TODO implement anew for taxa
+ try {
+ EnumSet<PesiSource> sources = getSources(taxon);
+ //TODO what if 2 sources? In PESI 2014 they were pipe separated
+ //TODO why does ERMS use accessed through eu-nomen, while E+M uses accessed through E+M
+ if (sources.isEmpty()) {
+// logger.error("OriginalDB is NULL for this TaxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
+ } else if (sources.contains(PesiSource.ERMS)) {
+ //TODO check if correct, compare with PESI 2014
+ Set<Extension> extensions = taxon.getExtensions();
+ for (Extension extension : extensions) {
+ if (extension.getType().equals(cacheCitationExtensionType)) {
+ result = extension.getValue();
+ }
+ }
+ } else if (sources.contains(PesiSource.EM)) {
+ //TODO
+ boolean isMisapplied = isMisappliedName(taxon);
+ boolean isProParteSyn = isProParteOrPartialSynonym(taxon);
+ Reference sec = null;
+ if(!isMisapplied && !isProParteSyn){
+ sec = taxon.getSec();
+ }else if (isMisapplied){
+ sec = getAcceptedTaxonForMisappliedName(taxon).getSec();
+ }else if (isProParteSyn){
+ sec = getAcceptedTaxonForProParteSynonym(taxon).getSec();
+ }
+ if (sec == null){
+ logger.warn("Sec could not be defined for taxon " + taxon.getTitleCache()+ "; " + taxon.getUuid());
+ }
+ String author = sec == null? "" : sec.getTitleCache();
+ String webShowName = isMisapplied? getDisplayName(taxon):getWebShowName(taxonName); //for misapplied we need also the sensu and non author part, for ordinary names name + author is enough
+ String accessed = ". Accessed through: Euro+Med PlantBase at https://www.europlusmed.org/cdm_dataportal/taxon/";
+ result = CdmUtils.removeTrailingDot(author)
+ + ". " + CdmUtils.removeTrailingDot(webShowName)
+ + accessed + taxon.getUuid();
+ } else {
+ //TODO check for IF + FE
+
+ String expertName = getExpertName(taxon);
+ String webShowName = getWebShowName(taxonName);
+
+ // idInSource only
+ String idInSource = getIdInSourceOnly(taxonName);
+
+ // build the cacheCitation
+ if (expertName != null) {
+ result += expertName + ". ";
+ } else {
+ if (logger.isDebugEnabled()){logger.debug("ExpertName could not be determined for this TaxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");}
+ }
+ if (webShowName != null) {
+ result += webShowName + ". ";
+ } else {
+ logger.warn("WebShowName could not be determined for this TaxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
+ }
+
+ if (getOriginalDB(taxonName).equals("FaEu")) {
+ result += "Accessed through: Fauna Europaea at http://faunaeur.org/full_results.php?id=";
+ } else if (getOriginalDB(taxonName).equals("EM")) {
+ result += "Accessed through: Euro+Med PlantBase at http://ww2.bgbm.org/euroPlusMed/PTaxonDetail.asp?UUID=";
+ }
+
+ if (idInSource != null) {
+ result += idInSource;
+ } else {
+ logger.warn("IdInSource could not be determined for this TaxonName: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ if (StringUtils.isBlank(result)) {
+ return null;
+ } else {
+ return result;
+ }
+ }
+
+ /**
+ * Returns the <code>OriginalDB</code> attribute.
+ * @param identifiableEntity
+ * @return The <code>OriginalDB</code> attribute.
+ * @see MethodMapper
+ */
+// @SuppressWarnings("unused")
+ private static String getOriginalDB(IdentifiableEntity<?> identifiableEntity) {
+ EnumSet<PesiSource> sources = getSources(identifiableEntity);
+ return PesiTransformer.getOriginalDbBySources(sources);
+ }
+
+ /**
+ * Returns the <code>ExpertName</code> attribute.
+ * @param taxonName The {@link TaxonNameBase TaxonName}.
+ * @return The <code>ExpertName</code> attribute.
+ * @see MethodMapper
+ */
+ @SuppressWarnings("unused") //for some reason it is also called by getCacheCitation
+ private static String getExpertName(TaxonBase<?> taxon) {
+ try {
+ String result = null;
+ if(expertNameExtensionType!=null){ //some databases do not have this extension type
+ Set<Extension> extensions = taxon.getExtensions();
+ for (Extension extension : extensions) {
+ if (extension.getType().equals(expertNameExtensionType)) {
+ result = extension.getValue();
+ }
+ }
+ }
+ if (getPesiSources(taxon).contains(PesiSource.EM)){
+ return taxon.getSec().getTitleCache();
+ }
+ return null;
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ //TODO change to ExpertGUID
+ private static Integer getExpertFk(Reference reference, PesiExportState state) {
+ Integer result = state.getDbId(reference);
+ return result;
+ }
+
+ /**
+ * Returns the <code>SpeciesExpertName</code> attribute.
+ * @param taxonName The {@link TaxonNameBase TaxonName}.
+ * @return The <code>SpeciesExpertName</code> attribute.
+ * @see MethodMapper
+ */
+ @SuppressWarnings("unused")
+ private static String getSpeciesExpertName(TaxonBase<?> taxon) {
+ try {
+ Set<Extension> extensions = taxon.getExtensions();
+ if(speciesExpertNameExtensionType != null){ //some databases do not have this extension type
+ for (Extension extension : extensions) {
+ if (extension.getType().equals(speciesExpertNameExtensionType)) {
+ return extension.getValue();
+ }
+ }
+ }
+ if (getPesiSources(taxon).contains(PesiSource.EM)){
+ return taxon.getSec().getTitleCache();
+ }
+ return null;
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ /**
+ * Returns the <code>SpeciesExpertFk</code> attribute.
+ * @param reference The {@link Reference Reference}.
+ * @param state The {@link PesiExportState PesiExportState}.
+ * @return The <code>SpeciesExpertFk</code> attribute.
+ * @see MethodMapper
+ */
+ //TODO should be changed to SpeciesExpertGUID
+ private static Integer getSpeciesExpertFk(Reference reference, PesiExportState state) {
+ Integer result = state.getDbId(reference);
+ return result;
+ }
+
+ protected static TaxonNameDefaultCacheStrategy getCacheStrategy(TaxonName taxonName) {
+ taxonName = CdmBase.deproxy(taxonName);
+ TaxonNameDefaultCacheStrategy cacheStrategy;
+ if (taxonName.isZoological()){
+ cacheStrategy = zooNameStrategy;
+ }else if (taxonName.isBotanical()) {
+ cacheStrategy = nonViralNameStrategy;
+ }else if (taxonName.isNonViral()) {
+ cacheStrategy = nonViralNameStrategy;
+ }else if (taxonName.isBacterial()) {
+ cacheStrategy = nonViralNameStrategy;
+ }else{
+ logger.error("Unhandled taxon name type. Can't define strategy class");
+ cacheStrategy = nonViralNameStrategy;
+ }
+ return cacheStrategy;
+ }
+
+ /**
+ * Returns the <code>RelTaxonQualifierFk</code> attribute.
+ * @param relationship The {@link RelationshipBase Relationship}.
+ * @return The <code>RelTaxonQualifierFk</code> attribute.
+ * @see MethodMapper
+ */
+ @SuppressWarnings("unused")
+ private static Integer getRelTaxonQualifierFk(RelationshipBase<?, ?, ?> relationship) {
+ return PesiTransformer.taxonRelation2RelTaxonQualifierFk(relationship);
+ }
+
+ //TODO still in use?
+ private static String getSynonymTypeCache(Synonym synonym, PesiExportState state) {
+ String result = null;
+ NomenclaturalCode code = null;
+ code = CdmBase.deproxy(synonym, Synonym.class).getAcceptedTaxon().getName().getNameType();
+
+ if (code != null) {
+ result = state.getConfig().getTransformer().getCacheBySynonymType(synonym, code);
+ } else {
+ logger.error("NomenclaturalCode is NULL while creating the following synonym: " + synonym.getUuid());
+ }
+ return result;
+ }
+
+// ********************************** MAPPINGS ********************************/
+
+ /**
+ * Returns the CDM to PESI specific export mappings.
+ * @return The {@link PesiExportMapping PesiExportMapping}.
+ */
+ private PesiExportMapping getMapping() {
+ PesiExportMapping mapping = new PesiExportMapping(dbTableName);
+
+ mapping.addMapper(IdMapper.NewInstance("TaxonId"));
+ mapping.addMapper(DbObjectMapper.NewInstance("sec", "sourceFk")); //OLD:mapping.addMapper(MethodMapper.NewInstance("SourceFK", this.getClass(), "getSourceFk", standardMethodParameter, PesiExportState.class));
+ mapping.addMapper(MethodMapper.NewInstance("TaxonStatusFk", this.getClass(), "getTaxonStatusFk", standardMethodParameter, PesiExportState.class));
+ mapping.addMapper(MethodMapper.NewInstance("TaxonStatusCache", this.getClass(), "getTaxonStatusCache", standardMethodParameter, PesiExportState.class));
+
+ mapping.addMapper(MethodMapper.NewInstance("GUID", this));
+
+ mapping.addMapper(MethodMapper.NewInstance("DerivedFromGuid", this));
+ mapping.addMapper(MethodMapper.NewInstance("CacheCitation", this));
+ mapping.addMapper(MethodMapper.NewInstance("AuthorString", this)); //For Taxon because misapplied names are handled differently
+ mapping.addMapper(MethodMapper.NewInstance("FullName", this)); //For Taxon because misapplied names are handled differently
+ mapping.addMapper(MethodMapper.NewInstance("WebShowName", this));
+
+ // DisplayName
+ mapping.addMapper(MethodMapper.NewInstance("DisplayName", this));
+
+ // FossilStatus (Fk, Cache)
+ mapping.addMapper(MethodMapper.NewInstance("FossilStatusCache", this, IdentifiableEntity.class, PesiExportState.class));
+ mapping.addMapper(MethodMapper.NewInstance("FossilStatusFk", this, IdentifiableEntity.class, PesiExportState.class)); // PesiTransformer.FossilStatusCache2FossilStatusFk?
+
+ //handled by name mapping
+ mapping.addMapper(DbLastActionMapper.NewInstance("LastActionDate", false));
+ mapping.addMapper(DbLastActionMapper.NewInstance("LastAction", true));
+
+ //experts
+// mapping.addMapper(DbExtensionMapper.NewInstance(extensionTypeSpeciesExpertName, "SpeciesExpertName"));
+ mapping.addMapper(MethodMapper.NewInstance("SpeciesExpertName", this, TaxonBase.class));
+// ExtensionType extensionTypeExpertName = (ExtensionType)getTermService().find(PesiTransformer.uuidExtExpertName);
+// mapping.addMapper(DbExtensionMapper.NewInstance(extensionTypeExpertName, "ExpertName"));
+ mapping.addMapper(MethodMapper.NewInstance("ExpertName", this, TaxonBase.class));
+
+ //ParentTaxonFk handled in Phase02 now
+ mapping.addMapper(ObjectChangeMapper.NewInstance(TaxonBase.class, TaxonName.class, "Name"));
+
+ addNameMappers(mapping);
+
+ return mapping;
+ }
+
+ /**
+ * Returns the CDM to PESI specific export mappings.
+ * @param state
+ * @return The {@link PesiExportMapping PesiExportMapping}.
+ * @throws UndefinedTransformerMethodException
+ */
+ private PesiExportMapping getPureNameMapping(PesiExportState state) throws UndefinedTransformerMethodException {
+ PesiExportMapping mapping = new PesiExportMapping(dbTableName);
+
+ mapping.addMapper(IdMapper.NewInstance("TaxonId"));
+
+ mapping.addMapper(MethodMapper.NewInstance("KingdomFk", this, TaxonName.class));
+ mapping.addMapper(MethodMapper.NewInstance("RankFk", this, TaxonName.class));
+ mapping.addMapper(MethodMapper.NewInstance("RankCache", this, TaxonName.class, PesiExportState.class));
+ mapping.addMapper(DbConstantMapper.NewInstance("TaxonStatusFk", Types.INTEGER, PesiTransformer.T_STATUS_UNACCEPTED));
+ mapping.addMapper(DbConstantMapper.NewInstance("TaxonStatusCache", Types.VARCHAR, state.getTransformer().getTaxonStatusCacheByKey( PesiTransformer.T_STATUS_UNACCEPTED)));
+ mapping.addMapper(DbStringMapper.NewInstance("AuthorshipCache", "AuthorString").setBlankToNull(true));
+ mapping.addMapper(MethodMapper.NewInstance("FullName", this, TaxonName.class));
+ mapping.addMapper(MethodMapper.NewInstance("WebShowName", this, TaxonName.class));
+ mapping.addMapper(MethodMapper.NewInstance("GUID", this, TaxonName.class));
+
+ // DisplayName
+ mapping.addMapper(MethodMapper.NewInstance("DisplayName", this, TaxonName.class));
+
+ mapping.addMapper(DbLastActionMapper.NewInstance("LastActionDate", false));
+ mapping.addMapper(DbLastActionMapper.NewInstance("LastAction", true));
+
+ addNameMappers(mapping);
+ return mapping;
+ }
+
+ private void addNameMappers(PesiExportMapping mapping) {
+
+ //epithets
+ mapping.addMapper(DbStringMapper.NewInstance("GenusOrUninomial", "GenusOrUninomial"));
+ mapping.addMapper(DbStringMapper.NewInstance("InfraGenericEpithet", "InfraGenericEpithet"));
+ mapping.addMapper(DbStringMapper.NewInstance("SpecificEpithet", "SpecificEpithet"));
+ mapping.addMapper(DbStringMapper.NewInstance("InfraSpecificEpithet", "InfraSpecificEpithet"));
+
+ //full name
+// mapping.addMapper(DbStringMapper.NewInstance("NameCache", "WebSearchName")); //does not work as we need other cache strategy
+ mapping.addMapper(MethodMapper.NewInstance("WebSearchName", this, TaxonName.class));
+
+ //nom ref
+ mapping.addMapper(MethodMapper.NewInstance("NomRefString", this, TaxonName.class));
+
+ //status
+ mapping.addMapper(MethodMapper.NewInstance("NameStatusFk", this, TaxonName.class));
+ mapping.addMapper(MethodMapper.NewInstance("NameStatusCache", this, TaxonName.class, PesiExportState.class));
+ mapping.addMapper(MethodMapper.NewInstance("QualityStatusFk", this, TaxonName.class));
+ mapping.addMapper(MethodMapper.NewInstance("QualityStatusCache", this, TaxonName.class, PesiExportState.class));
+
+ //types
+ mapping.addMapper(MethodMapper.NewInstance("TypeFullnameCache", this, TaxonName.class));
+ //TypeNameFk handled in Phase3
+
+ //supplemental
+ mapping.addMapper(MethodMapper.NewInstance("IdInSource", this, IdentifiableEntity.class));
+ mapping.addMapper(MethodMapper.NewInstance("OriginalDB", this, IdentifiableEntity.class) );
+
+ //mapping.addMapper(ExpertsAndLastActionMapper.NewInstance());
+
+ }
+
+ private PesiExportMapping getSynRelMapping() {
+ PesiExportMapping mapping = new PesiExportMapping(dbTableNameSynRel);
+ logger.warn("SynRelMapping currently not implemented. Needs to be checked");
+
+ mapping.addMapper(MethodMapper.NewInstance("TaxonFk1", this.getClass(), "getSynonym", Synonym.class, PesiExportState.class));
+ mapping.addMapper(DbObjectMapper.NewInstance("acceptedTaxon", "TaxonFk2"));
+ mapping.addMapper(DbObjectMapper.NewInstance("type", "RelTaxonQualifierFk"));
+ mapping.addMapper(MethodMapper.NewInstance("RelQualifierCache", this.getClass(), "getSynonymTypeCache", Synonym.class, PesiExportState.class));
+ // TODO
+// mapping.addMapper(MethodMapper.NewInstance("Notes", this, RelationshipBase.class));
+
+ return mapping;
+ }
+
+ private PesiExportMapping getAdditionalSourceMapping(PesiExportState state) {
+ PesiExportMapping mapping = new PesiExportMapping(dbTableAdditionalSourceRel);
+
+ mapping.addMapper(IdMapper.NewInstance("TaxonFk"));
+ mapping.addMapper(ObjectChangeMapper.NewInstance(TaxonBase.class, TaxonName.class, "Name"));
+
+ mapping.addMapper(DbObjectMapper.NewInstance("NomenclaturalReference", "SourceFk"));
+// mapping.addMapper(DbObjectMapper.NewInstance("NomenclaturalReference", "SourceNameCache", IS_CACHE));
+ mapping.addMapper(MethodMapper.NewInstance("SourceNameCache", this, TaxonName.class));
+
+ //we have only nomenclatural references here
+ mapping.addMapper(DbConstantMapper.NewInstance("SourceUseFk", Types.INTEGER , PesiTransformer.NOMENCLATURAL_REFERENCE));
+ mapping.addMapper(DbConstantMapper.NewInstance("SourceUseCache", Types.VARCHAR, state.getTransformer().getSourceUseCacheByKey( PesiTransformer.NOMENCLATURAL_REFERENCE)));
+
+ mapping.addMapper(DbStringMapper.NewInstance("NomenclaturalMicroReference", "SourceDetail"));
+
+ return mapping;
+ }
+
+
+ @Override
+ protected boolean doCheck(PesiExportState state) {
+ return true;
+ }
+
+ @Override
+ protected boolean isIgnore(PesiExportState state) {
+ return ! state.getConfig().isDoTaxa();
+ }
+}