(no commit message)
[cdmlib.git] / cdmlib-io / src / main / java / eu / etaxonomy / cdm / io / faunaEuropaea / FaunaEuropaeaTaxonNameImport.java
index 2baac9fe46dbeb5de466f7460a3e7f6796b6af3d..1355d67867f0258c7cbf87e0afc6ebe3ac326a22 100644 (file)
@@ -11,7 +11,6 @@ package eu.etaxonomy.cdm.io.faunaEuropaea;
 \r
 import static eu.etaxonomy.cdm.io.faunaEuropaea.FaunaEuropaeaTransformer.A_AUCT;\r
 import static eu.etaxonomy.cdm.io.faunaEuropaea.FaunaEuropaeaTransformer.P_PARENTHESIS;\r
-import static eu.etaxonomy.cdm.io.faunaEuropaea.FaunaEuropaeaTransformer.Q_NO_RESTRICTION;\r
 import static eu.etaxonomy.cdm.io.faunaEuropaea.FaunaEuropaeaTransformer.R_GENUS;\r
 import static eu.etaxonomy.cdm.io.faunaEuropaea.FaunaEuropaeaTransformer.R_SPECIES;\r
 import static eu.etaxonomy.cdm.io.faunaEuropaea.FaunaEuropaeaTransformer.R_SUBGENUS;\r
@@ -21,8 +20,10 @@ import static eu.etaxonomy.cdm.io.faunaEuropaea.FaunaEuropaeaTransformer.T_STATU
 \r
 import java.sql.ResultSet;\r
 import java.sql.SQLException;\r
+import java.util.ArrayList;\r
 import java.util.Collection;\r
 import java.util.HashMap;\r
+import java.util.HashSet;\r
 import java.util.List;\r
 import java.util.Map;\r
 import java.util.Set;\r
@@ -32,7 +33,6 @@ import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;\r
 import org.springframework.transaction.TransactionStatus;\r
 \r
-import eu.etaxonomy.cdm.api.service.IService;\r
 import eu.etaxonomy.cdm.common.CdmUtils;\r
 import eu.etaxonomy.cdm.io.common.ICdmIO;\r
 import eu.etaxonomy.cdm.io.common.ImportHelper;\r
@@ -40,14 +40,12 @@ import eu.etaxonomy.cdm.io.common.MapWrapper;
 import eu.etaxonomy.cdm.io.common.Source;\r
 import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;\r
 import eu.etaxonomy.cdm.model.common.CdmBase;\r
-import eu.etaxonomy.cdm.model.common.OriginalSource;\r
+import eu.etaxonomy.cdm.model.common.IdentifiableSource;\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.ReferenceBase;\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.strategy.exceptions.UnknownCdmTypeException;\r
@@ -108,7 +106,9 @@ public class FaunaEuropaeaTaxonNameImport extends FaunaEuropaeaImportBase  {
                \r
                boolean success = true;\r
                if(logger.isInfoEnabled()) { logger.info("Start making taxa..."); }\r
-\r
+               \r
+               \r
+               \r
                success = processTaxa(state);\r
                \r
                logger.info("End making taxa...");\r
@@ -128,6 +128,8 @@ public class FaunaEuropaeaTaxonNameImport extends FaunaEuropaeaImportBase  {
                \r
                Map<Integer, TaxonBase<?>> taxonMap = null;\r
                Map<Integer, FaunaEuropaeaTaxon> fauEuTaxonMap = null;\r
+               /* Store for heterotypic synonyms to be save separately */\r
+               Set<Synonym> synonymSet = null;\r
 \r
                FaunaEuropaeaImportConfigurator fauEuConfig = state.getConfig();\r
                ReferenceBase<?> sourceRef = fauEuConfig.getSourceReference();\r
@@ -141,9 +143,11 @@ public class FaunaEuropaeaTaxonNameImport extends FaunaEuropaeaImportBase  {
 \r
                String selectColumns = \r
                        " SELECT Parent.TAX_NAME AS P2Name, Parent.TAX_RNK_ID AS P2RankId, " +\r
-                       " GrandParent.TAX_NAME AS GP3Name, GrandParent.TAX_RNK_ID AS GP3RankId, " +\r
-                       " GreatGrandParent.TAX_NAME AS GGP4Name, GreatGrandParent.TAX_RNK_ID AS GGP4RankId, " +\r
-                       " GreatGreatGrandParent.TAX_NAME AS GGGP5Name, OriginalGenusTaxon.TAX_NAME AS OGenusName, " +\r
+                       " GrandParent.TAX_ID AS GP3Id, GrandParent.TAX_NAME AS GP3Name, GrandParent.TAX_RNK_ID AS GP3RankId, " +\r
+                       " GreatGrandParent.TAX_ID AS GGP4Id, GreatGrandParent.TAX_NAME AS GGP4Name, GreatGrandParent.TAX_RNK_ID AS GGP4RankId, " +\r
+                       " GreatGreatGrandParent.TAX_ID AS GGGP5Id, GreatGreatGrandParent.TAX_NAME AS GGGP5Name, GreatGreatGrandParent.TAX_RNK_ID AS GGGP5RankId, " +\r
+                       " OriginalGenusTaxon.TAX_NAME AS OGenusName, " +\r
+                       " GreatGreatGreatGrandParent.TAX_ID AS GGGGP6Id, GreatGreatGreatGrandParent.TAX_NAME AS GGGGP6Name, GreatGreatGreatGrandParent.TAX_RNK_ID AS GGGGP6RankId," +\r
                        " Taxon.*, rank.*, author.* ";\r
                \r
                String fromClause = \r
@@ -152,6 +156,7 @@ public class FaunaEuropaeaTaxonNameImport extends FaunaEuropaeaImportBase  {
                        " Taxon AS GrandParent ON Parent.TAX_TAX_IDPARENT = GrandParent.TAX_ID LEFT OUTER JOIN " +\r
                        " Taxon AS GreatGrandParent ON GrandParent.TAX_TAX_IDPARENT = GreatGrandParent.TAX_ID LEFT OUTER JOIN " +\r
                        " Taxon AS GreatGreatGrandParent ON GreatGrandParent.TAX_TAX_IDPARENT = GreatGreatGrandParent.TAX_ID LEFT OUTER JOIN " +\r
+                       " Taxon AS GreatGreatGreatGrandParent ON GreatGreatGrandParent.TAX_TAX_IDPARENT = GreatGreatGreatGrandParent.TAX_ID LEFT OUTER JOIN " +\r
                        " Taxon AS OriginalGenusTaxon ON Taxon.TAX_TAX_IDGENUS = OriginalGenusTaxon.TAX_ID LEFT OUTER JOIN " +\r
                        " author ON Taxon.TAX_AUT_ID = author.aut_id LEFT OUTER JOIN " +\r
                        " rank ON Taxon.TAX_RNK_ID = rank.rnk_id ";\r
@@ -184,6 +189,7 @@ public class FaunaEuropaeaTaxonNameImport extends FaunaEuropaeaImportBase  {
                                        txStatus = startTransaction();\r
                                        taxonMap = new HashMap<Integer, TaxonBase<?>>(limit);\r
                                        fauEuTaxonMap = new HashMap<Integer, FaunaEuropaeaTaxon>(limit);\r
+                                       synonymSet = new HashSet<Synonym>();\r
                                        \r
                                        if(logger.isInfoEnabled()) {\r
                                                logger.info("i = " + i + " - Transaction started"); \r
@@ -192,9 +198,13 @@ public class FaunaEuropaeaTaxonNameImport extends FaunaEuropaeaImportBase  {
 \r
                                String localName = rs.getString("TAX_NAME");\r
                                String parentName = rs.getString("P2Name");\r
+                               int grandParentId = rs.getInt("GP3Id");\r
                                String grandParentName = rs.getString("GP3Name");\r
+                               int greatGrandParentId = rs.getInt("GGP4Id");\r
                                String greatGrandParentName = rs.getString("GGP4Name");\r
+                               int greatGreatGrandParentId = rs.getInt("GGGP5Id");\r
                                String greatGreatGrandParentName = rs.getString("GGGP5Name");\r
+                               String greatGreatGreatGrandParentName = rs.getString("GGGGP6Name");\r
                                String originalGenusName = rs.getString("OGenusName");\r
                                String autName = rs.getString("aut_name");\r
                                int taxonId = rs.getInt("TAX_ID");\r
@@ -203,10 +213,18 @@ public class FaunaEuropaeaTaxonNameImport extends FaunaEuropaeaImportBase  {
                                int parentRankId = rs.getInt("P2RankId");\r
                                int grandParentRankId = rs.getInt("GP3RankId");\r
                                int greatGrandParentRankId = rs.getInt("GGP4RankId");\r
+                               int greatGreatGrandParentRankId = rs.getInt("GGGP5RankId");\r
+                               int greatGreatGreatGrandParentRankId = rs.getInt("GGGGP6RankId");\r
                                int originalGenusId = rs.getInt("TAX_TAX_IDGENUS");\r
                                int autId = rs.getInt("TAX_AUT_ID");\r
                                int status = rs.getInt("TAX_VALID");\r
-                               int year = rs.getInt("TAX_YEAR");\r
+                               \r
+                               // Avoid publication year 0 for NULL values in database.\r
+                               Integer year = rs.getInt("TAX_YEAR");\r
+                               if (year != null && year.intValue() == 0) {\r
+                                       year = null;\r
+                               }\r
+                               \r
                                //int familyId = rs.getInt("TAX_TAX_IDFAMILY");\r
 \r
                                Rank rank = null;\r
@@ -222,17 +240,29 @@ public class FaunaEuropaeaTaxonNameImport extends FaunaEuropaeaImportBase  {
                                fauEuTaxon.setUuid(taxonBaseUuid);\r
                                fauEuTaxon.setId(taxonId);\r
                                fauEuTaxon.setRankId(rankId);\r
+                               fauEuTaxon.setLocalName(localName);\r
+                               \r
                                fauEuTaxon.setParentId(parentId);\r
                                fauEuTaxon.setParentRankId(parentRankId);\r
-                               fauEuTaxon.setGrandParentRankId(grandParentRankId);\r
-                               fauEuTaxon.setGreatGrandParentRankId(greatGrandParentRankId);\r
-                               fauEuTaxon.setOriginalGenusId(originalGenusId);\r
-                               fauEuTaxon.setYear(year);\r
-                               fauEuTaxon.setLocalName(localName);\r
                                fauEuTaxon.setParentName(parentName);\r
+                               \r
+                               fauEuTaxon.setGrandParentId(grandParentId);\r
+                               fauEuTaxon.setGrandParentRankId(grandParentRankId);\r
                                fauEuTaxon.setGrandParentName(grandParentName);\r
+                               \r
+                               fauEuTaxon.setGreatGrandParentId(greatGrandParentId);\r
+                               fauEuTaxon.setGreatGrandParentRankId(greatGrandParentRankId);\r
                                fauEuTaxon.setGreatGrandParentName(greatGrandParentName);\r
+                               \r
+                               fauEuTaxon.setGreatGreatGrandParentId(greatGreatGrandParentId);\r
+                               fauEuTaxon.setGreatGreatGrandParentRankId(greatGreatGrandParentRankId);\r
                                fauEuTaxon.setGreatGreatGrandParentName(greatGreatGrandParentName);\r
+                               \r
+                               fauEuTaxon.setGreatGreatGreatGrandParentRankId(greatGreatGreatGrandParentRankId);\r
+                               fauEuTaxon.setGreatGreatGreatGrandParentName(greatGreatGreatGrandParentName);\r
+                               \r
+                               fauEuTaxon.setOriginalGenusId(originalGenusId);\r
+                               fauEuTaxon.setYear(year);\r
                                fauEuTaxon.setOriginalGenusName(originalGenusName);\r
                                fauEuTaxon.setAuthorName(autName);\r
                                if (parenthesis == P_PARENTHESIS) {\r
@@ -263,9 +293,10 @@ public class FaunaEuropaeaTaxonNameImport extends FaunaEuropaeaImportBase  {
 \r
                                ZoologicalName zooName = ZoologicalName.NewInstance(rank);\r
                                TeamOrPersonBase<?> author = authorStore.get(autId);\r
+                               \r
                                zooName.setCombinationAuthorTeam(author);\r
                                zooName.setPublicationYear(year);\r
-\r
+                               \r
                                TaxonBase<?> taxonBase;\r
 \r
                                Synonym synonym;\r
@@ -273,6 +304,8 @@ public class FaunaEuropaeaTaxonNameImport extends FaunaEuropaeaImportBase  {
                                try {\r
                                        if ((status == T_STATUS_ACCEPTED) || (autId == A_AUCT)) { // taxon\r
                                                if (autId == A_AUCT) { // misapplied name\r
+                                                       zooName.setCombinationAuthorTeam(null);\r
+                                                       zooName.setPublicationYear(null);\r
                                                        taxon = Taxon.NewInstance(zooName, auctReference);\r
                                                        if (logger.isDebugEnabled()) {\r
                                                                logger.debug("Misapplied name created (" + taxonId + ")");\r
@@ -286,6 +319,7 @@ public class FaunaEuropaeaTaxonNameImport extends FaunaEuropaeaImportBase  {
                                                taxonBase = taxon;\r
                                        } else if ((status == T_STATUS_NOT_ACCEPTED) && (autId != A_AUCT)) { // synonym\r
                                                synonym = Synonym.NewInstance(zooName, sourceReference);\r
+                                               //logger.info("Synonym created: " + synonym.getTitleCache() + " taxonName: " + zooName.getTitleCache());\r
                                                if (logger.isDebugEnabled()) {\r
                                                        logger.debug("Synonym created (" + taxonId + ")");\r
                                                }\r
@@ -326,10 +360,13 @@ public class FaunaEuropaeaTaxonNameImport extends FaunaEuropaeaImportBase  {
 \r
                                if (((i % limit) == 0 && i != 1 ) || i == count) { \r
 \r
-                                       success = processTaxaSecondPass(state, taxonMap, fauEuTaxonMap);\r
-                                       saveTaxa(state, taxonMap);\r
+                                       success = processTaxaSecondPass(state, taxonMap, fauEuTaxonMap, synonymSet);\r
+                                       if(logger.isDebugEnabled()) { logger.debug("Saving taxa ..."); }\r
+                                       getTaxonService().save((Collection)taxonMap.values());\r
+                                       getTaxonService().save((Collection)synonymSet);\r
                                        \r
                                        taxonMap = null;\r
+                                       synonymSet = null;\r
                                        fauEuTaxonMap = null;\r
                                        commitTransaction(txStatus);\r
                                        \r
@@ -352,12 +389,11 @@ public class FaunaEuropaeaTaxonNameImport extends FaunaEuropaeaImportBase  {
         * Processes taxa from complete taxon store\r
         */\r
        private boolean processTaxaSecondPass(FaunaEuropaeaImportState state, Map<Integer, TaxonBase<?>> taxonMap,\r
-                       Map<Integer, FaunaEuropaeaTaxon> fauEuTaxonMap) {\r
+                       Map<Integer, FaunaEuropaeaTaxon> fauEuTaxonMap, Set<Synonym> synonymSet) {\r
 \r
                if(logger.isDebugEnabled()) { logger.debug("Processing taxa second pass..."); }\r
 \r
                FaunaEuropaeaImportConfigurator fauEuConfig = state.getConfig();\r
-               ReferenceBase<?> sourceRef = fauEuConfig.getSourceReference();\r
                \r
                boolean success = true;\r
 \r
@@ -368,14 +404,40 @@ public class FaunaEuropaeaTaxonNameImport extends FaunaEuropaeaImportBase  {
                        TaxonBase<?> taxonBase = taxonMap.get(id);\r
                        TaxonNameBase<?,?> taxonName = taxonBase.getName();\r
                        FaunaEuropaeaTaxon fauEuTaxon = fauEuTaxonMap.get(id);\r
+                       boolean useOriginalGenus = false;\r
+                       if (taxonBase instanceof Synonym){\r
+                               useOriginalGenus = true;\r
+                       }\r
                        \r
                        String nameString = \r
-                               buildTaxonName(fauEuTaxon, taxonBase, taxonName, false, fauEuConfig);\r
+                               buildTaxonName(fauEuTaxon, taxonBase, taxonName, useOriginalGenus, fauEuConfig);\r
+                       \r
+                       if (taxonBase instanceof Synonym){\r
+                               logger.info("Name of Synonym: " + nameString);\r
+                       }\r
                        \r
-                       if (fauEuConfig.isDoBasionyms() && fauEuTaxon.isValid() &&\r
-                                       (fauEuTaxon.getOriginalGenusId() != 0) &&\r
-                                       (fauEuTaxon.getParentId() != fauEuTaxon.getOriginalGenusId())) {\r
-                               success = createBasionym(fauEuTaxon, taxonBase, taxonName, fauEuConfig);\r
+                       if (fauEuConfig.isDoBasionyms() \r
+                                       && fauEuTaxon.getRankId() > R_SUBGENUS\r
+                                       && (fauEuTaxon.getOriginalGenusId() != 0)) {\r
+                               \r
+                               Integer originalGenusId = fauEuTaxon.getOriginalGenusId();\r
+                               Integer actualGenusId = getActualGenusId(fauEuTaxon);\r
+                               \r
+                               if (logger.isDebugEnabled()) {\r
+                                       logger.debug("actual genus id = " + actualGenusId + ", original genus id = " + originalGenusId);\r
+                               }\r
+                               \r
+                               if (actualGenusId != originalGenusId && taxonBase.isInstanceOf(Taxon.class)) {\r
+                                       success = createBasionym(fauEuTaxon, taxonBase, taxonName, fauEuConfig, synonymSet);\r
+                               } else if (fauEuTaxon.isParenthesis()) {\r
+                                       //the authorteam should be set in parenthesis because there should be a basionym, but we do not know it?\r
+                                       ZoologicalName zooName = taxonName.deproxy(taxonName, ZoologicalName.class);\r
+                                       zooName.setBasionymAuthorTeam(zooName.getCombinationAuthorTeam());\r
+                                       zooName.setCombinationAuthorTeam(null);\r
+                                       zooName.setOriginalPublicationYear(zooName.getPublicationYear());\r
+                                       zooName.setPublicationYear(null);\r
+                               }\r
+                               \r
                        }\r
                }\r
                return success; \r
@@ -383,40 +445,63 @@ public class FaunaEuropaeaTaxonNameImport extends FaunaEuropaeaImportBase  {
 \r
        \r
        private boolean createBasionym(FaunaEuropaeaTaxon fauEuTaxon, TaxonBase<?> taxonBase, \r
-                       TaxonNameBase<?,?>taxonName, FaunaEuropaeaImportConfigurator fauEuConfig) {\r
-\r
-//             if (fauEuTaxon.isParenthesis() && (fauEuTaxon.getOriginalGenusId() != 0)\r
-//             && (fauEuTaxon.getParentId() != fauEuTaxon.getOriginalGenusId())) {\r
+                       TaxonNameBase<?,?>taxonName, FaunaEuropaeaImportConfigurator fauEuConfig,\r
+                       Set<Synonym> synonymSet) {\r
 \r
                boolean success = true;\r
 \r
                try {\r
                        ZoologicalName zooName = taxonName.deproxy(taxonName, ZoologicalName.class);\r
-                       Taxon taxon = taxonBase.deproxy(taxonBase, Taxon.class);\r
                        \r
                        // create basionym\r
                        ZoologicalName basionym = ZoologicalName.NewInstance(taxonName.getRank());\r
                        basionym.setCombinationAuthorTeam(zooName.getCombinationAuthorTeam());\r
+                       \r
+                       zooName.setOriginalPublicationYear(zooName.getPublicationYear());\r
                        basionym.setPublicationYear(zooName.getPublicationYear());\r
+\r
+                       // add originalGenusId as source\r
+                       String originalGenusIdString = "" + fauEuTaxon.getId();\r
+                       IdentifiableSource basionymSource = IdentifiableSource.NewInstance(originalGenusIdString, "originalGenusId");\r
+                       basionym.addSource(basionymSource);\r
+                       \r
+                       // add original database reference\r
+                       ImportHelper.setOriginalSource(basionym, fauEuConfig.getSourceReference(), fauEuTaxon.getId(), "TaxonName");\r
+                       \r
                        zooName.addBasionym(basionym, fauEuConfig.getSourceReference(), null, null);\r
                        zooName.setBasionymAuthorTeam(zooName.getCombinationAuthorTeam());\r
+                       zooName.setCombinationAuthorTeam(null);\r
+                       zooName.setPublicationYear(null);\r
+                       zooName.setTitleCache(null); // This should (re)generate the titleCache automagically\r
                        if (logger.isDebugEnabled()) {\r
                                logger.debug("Basionym created (" + fauEuTaxon.getId() + ")");\r
                        }\r
 \r
-                       // create homotypic synonym\r
-                       Synonym homotypicSynonym = Synonym.NewInstance(basionym, fauEuConfig.getSourceReference());\r
-//                     SynonymRelationship synRel = \r
-//                     taxon.addSynonym(homotypicSynonym, SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF(), \r
-//                     sourceReference, null);\r
-//                     homotypicSynonym.addRelationship(synRel);\r
-                       taxon.addHomotypicSynonym(homotypicSynonym, fauEuConfig.getSourceReference(), null);\r
-                       if (logger.isDebugEnabled()) {\r
-                               logger.debug("Homotypic synonym created (" + fauEuTaxon.getId() + ")");\r
+                       // create synonym\r
+                       Synonym synonym = Synonym.NewInstance(basionym, fauEuConfig.getSourceReference());\r
+                       \r
+                       if (fauEuTaxon.isValid()) { // Taxon\r
+\r
+                               // homotypic synonym\r
+                               Taxon taxon = taxonBase.deproxy(taxonBase, Taxon.class);\r
+                               taxon.addHomotypicSynonym(synonym, fauEuConfig.getSourceReference(), null);\r
+                               if (logger.isDebugEnabled()) {\r
+                                       logger.debug("Homotypic synonym created (" + fauEuTaxon.getId() + ")");\r
+                               }\r
+\r
+                       } else { // Synonym\r
+                               \r
+                               // heterotypic synonym\r
+                               // synonym relationship to the accepted taxon is created later\r
+                               synonymSet.add(synonym);\r
+                               \r
+                               if (logger.isDebugEnabled()) {\r
+                                       logger.debug("Heterotypic synonym stored (" + fauEuTaxon.getId() + ")");\r
+                               }\r
                        }\r
                        \r
-                       buildTaxonName(fauEuTaxon, homotypicSynonym, basionym, true, fauEuConfig);\r
                        \r
+                       buildTaxonName(fauEuTaxon, synonym, basionym, true, fauEuConfig);\r
                } catch (Exception e) {\r
                        logger.warn("Exception occurred when creating basionym for " + fauEuTaxon.getId());\r
                        e.printStackTrace();\r
@@ -431,8 +516,8 @@ public class FaunaEuropaeaTaxonNameImport extends FaunaEuropaeaImportBase  {
        private String buildNameTitleCache(String nameString, boolean useOriginalGenus, FaunaEuropaeaTaxon fauEuTaxon) {\r
                \r
                StringBuilder titleCacheStringBuilder = new StringBuilder(nameString);\r
-               int year = fauEuTaxon.getYear();\r
-               if (year != 0) { // TODO: Ignore authors like xp, xf, etc?\r
+               Integer year = fauEuTaxon.getYear();\r
+               if (year != null) { // TODO: Ignore authors like xp, xf, etc?\r
                        titleCacheStringBuilder.append(" ");\r
                        if ((fauEuTaxon.isParenthesis() == true) && !useOriginalGenus) {\r
                                titleCacheStringBuilder.append("(");\r
@@ -473,7 +558,7 @@ public class FaunaEuropaeaTaxonNameImport extends FaunaEuropaeaImportBase  {
 \r
                StringBuilder stringBuilder = new StringBuilder();\r
                \r
-               if(useOriginalGenus == true) {\r
+               if(useOriginalGenus) {\r
                        stringBuilder.append(originalGenusName);\r
                        genusOrUninomial.delete(0, genusOrUninomial.length());\r
                        genusOrUninomial.append(originalGenusName);\r
@@ -486,15 +571,24 @@ public class FaunaEuropaeaTaxonNameImport extends FaunaEuropaeaImportBase  {
        }\r
 \r
        \r
-       private String genusSubGenusPart(StringBuilder originalGenusName, boolean useOriginalGenus,\r
+       private String genusSubGenusPart(StringBuilder originalGenusName, boolean useOriginalGenus, \r
                        StringBuilder genusOrUninomial,\r
-                       StringBuilder infraGenericEpithet) {\r
+                       StringBuilder infraGenericEpithet,\r
+                       FaunaEuropaeaTaxon fauEuTaxon) {\r
 \r
                StringBuilder stringBuilder = new StringBuilder();\r
                \r
                stringBuilder.append(genusPart(originalGenusName, useOriginalGenus, genusOrUninomial));\r
 \r
-               if (useOriginalGenus == true) {\r
+               // The infraGenericEpithet is set to empty only if the original genus should be used and\r
+               // the actualGenusId is not the originalGenusId.\r
+               // This differentiation is relevant for synonyms and for basionyms.\r
+               // InfraGenericEpithets of accepted taxa are not touched at all.\r
+               Integer originalGenusId = fauEuTaxon.getOriginalGenusId();\r
+               Integer actualGenusId = getActualGenusId(fauEuTaxon);\r
+               if (useOriginalGenus && originalGenusId != actualGenusId && \r
+                               originalGenusId.intValue() > 0 &&\r
+                               actualGenusId.intValue() > 0) {\r
                        infraGenericEpithet.delete(0, infraGenericEpithet.length());\r
                        stringBuilder.append(" ");\r
                        return stringBuilder.toString();\r
@@ -507,14 +601,30 @@ public class FaunaEuropaeaTaxonNameImport extends FaunaEuropaeaImportBase  {
                \r
                return stringBuilder.toString();\r
        }\r
+\r
+       /** Get actual genus id **/\r
+       private Integer getActualGenusId(FaunaEuropaeaTaxon fauEuTaxon) {\r
+               Integer actualGenusId = null;\r
+               HashMap<Integer, Integer> ranks = new HashMap<Integer, Integer>();\r
+               ranks.put(fauEuTaxon.getParentRankId(), fauEuTaxon.getParentId());\r
+               ranks.put(fauEuTaxon.getGrandParentRankId(), fauEuTaxon.getGrandParentId());\r
+               ranks.put(fauEuTaxon.getGreatGrandParentRankId(), fauEuTaxon.getGreatGrandParentId());\r
+               ranks.put(fauEuTaxon.getGreatGreatGrandParentRankId(), fauEuTaxon.getGreatGreatGrandParentId());\r
+               ranks.put(fauEuTaxon.getGreatGreatGreatGrandParentRankId(), fauEuTaxon.getGreatGreatGreatGrandParentId());\r
+               \r
+               actualGenusId = ranks.get(R_GENUS);\r
+\r
+               return actualGenusId;\r
+       }\r
        \r
        \r
        /** Build species and subspecies names */\r
-       private String buildLowerTaxonName(StringBuilder originalGenus, boolean useOriginalGenus,\r
+       private String buildLowerTaxonName(StringBuilder originalGenus, boolean useOriginalGenus, \r
                        StringBuilder genusOrUninomial, StringBuilder infraGenericEpithet, \r
                        StringBuilder specificEpithet, StringBuilder infraSpecificEpithet,\r
                        FaunaEuropaeaTaxon fauEuTaxon) {\r
                \r
+               // species or subspecies name\r
                String localName = fauEuTaxon.getLocalName();\r
                int taxonId = fauEuTaxon.getId();\r
                int parentId = fauEuTaxon.getParentId();\r
@@ -545,11 +655,13 @@ public class FaunaEuropaeaTaxonNameImport extends FaunaEuropaeaImportBase  {
                        if (rank == R_SPECIES) {\r
 \r
                                if(parentRankId == R_SUBGENUS) {\r
-\r
+                                       //differ between isParanthesis= true and false\r
                                        String genusSubGenusPart = genusSubGenusPart(originalGenus, useOriginalGenus, \r
                                                        genusOrUninomial.append(grandParentName), \r
-                                                       infraGenericEpithet.append(parentName));\r
-                                       nameCacheStringBuilder.append(genusSubGenusPart);\r
+                                                       infraGenericEpithet.append(parentName),\r
+                                                       fauEuTaxon);\r
+                                               nameCacheStringBuilder.append(genusSubGenusPart);\r
+                                       \r
 \r
                                } else if(parentRankId == R_GENUS) {\r
 \r
@@ -566,7 +678,8 @@ public class FaunaEuropaeaTaxonNameImport extends FaunaEuropaeaImportBase  {
 \r
                                        String genusSubGenusPart = genusSubGenusPart(originalGenus, useOriginalGenus, \r
                                                        genusOrUninomial.append(greatGrandParentName), \r
-                                                       infraGenericEpithet.append(grandParentName));\r
+                                                       infraGenericEpithet.append(grandParentName),\r
+                                                       fauEuTaxon);\r
                                        nameCacheStringBuilder.append(genusSubGenusPart);\r
 \r
                                } else if (grandParentRankId == R_GENUS) {\r
@@ -590,7 +703,8 @@ public class FaunaEuropaeaTaxonNameImport extends FaunaEuropaeaImportBase  {
                                        \r
                                        String genusSubGenusPart = genusSubGenusPart(originalGenus, useOriginalGenus, \r
                                                        genusOrUninomial.append(greatGrandParentName), \r
-                                                       infraGenericEpithet.append(grandParentName));\r
+                                                       infraGenericEpithet.append(grandParentName),\r
+                                                       fauEuTaxon);\r
                                        nameCacheStringBuilder.append(genusSubGenusPart);\r
 \r
                                } else if (grandParentRankId == R_GENUS) {\r
@@ -600,6 +714,8 @@ public class FaunaEuropaeaTaxonNameImport extends FaunaEuropaeaImportBase  {
                                        nameCacheStringBuilder.append(genusPart);\r
 \r
                                }\r
+                               nameCacheStringBuilder.append(localName);\r
+                               specificEpithet.append(localName);\r
 \r
                        } else if (rank == R_SUBSPECIES) {\r
                                \r
@@ -609,7 +725,8 @@ public class FaunaEuropaeaTaxonNameImport extends FaunaEuropaeaImportBase  {
                                        \r
                                        String genusSubGenusPart = genusSubGenusPart(originalGenus, useOriginalGenus, \r
                                                        genusOrUninomial.append(greatGreatGrandParentName), \r
-                                                       infraGenericEpithet.append(greatGrandParentName));\r
+                                                       infraGenericEpithet.append(greatGrandParentName),\r
+                                                       fauEuTaxon);\r
                                        nameCacheStringBuilder.append(genusSubGenusPart);\r
                                        \r
                                } else if (greatGrandParentRankId == R_GENUS) {\r
@@ -622,10 +739,11 @@ public class FaunaEuropaeaTaxonNameImport extends FaunaEuropaeaImportBase  {
                                nameCacheStringBuilder.append(grandParentName);\r
                                nameCacheStringBuilder.append(" ");\r
                                specificEpithet.append(grandParentName);\r
+                               nameCacheStringBuilder.append(localName);\r
+                               infraSpecificEpithet.append(localName);\r
                        }\r
                        \r
-                       nameCacheStringBuilder.append(fauEuTaxon.getLocalName());\r
-                       infraSpecificEpithet.append(fauEuTaxon.getLocalName());\r
+                       \r
                        \r
                }\r
                \r
@@ -642,56 +760,92 @@ public class FaunaEuropaeaTaxonNameImport extends FaunaEuropaeaImportBase  {
                /* Concatenated taxon name string */\r
                String completeString = "";\r
 \r
-               StringBuilder originalGenus = null;\r
-               String originalGenusString = fauEuTaxon.getOriginalGenusName();\r
+               StringBuilder originalGenus = new StringBuilder("");\r
                \r
-               if (useOriginalGenus && originalGenusString != null) {\r
-                       originalGenus = new StringBuilder(originalGenusString);\r
-               }\r
                StringBuilder genusOrUninomial = new StringBuilder();\r
                StringBuilder infraGenericEpithet = new StringBuilder(); \r
                StringBuilder specificEpithet = new StringBuilder();\r
                StringBuilder infraSpecificEpithet = new StringBuilder();\r
 \r
                localString = fauEuTaxon.getLocalName();\r
-\r
                int rank = fauEuTaxon.getRankId();\r
+               \r
+               // determine genus: this also works for cases of synonyms since the accepted taxon is its parent\r
+               String originalGenusString = null;\r
+               if (useOriginalGenus && ! "".equals(fauEuTaxon.getOriginalGenusName())) {\r
+                       originalGenusString  = fauEuTaxon.getOriginalGenusName();\r
+               } else {\r
+                       originalGenusString = determineOriginalGenus(fauEuTaxon);\r
+               }\r
+\r
+               if (originalGenusString != null) {\r
+                       originalGenus = new StringBuilder(originalGenusString);\r
+               }\r
 \r
                if(logger.isDebugEnabled()) { \r
                        logger.debug("Local taxon name (rank = " + rank + "): " + localString); \r
                }\r
 \r
                if (rank < R_SPECIES) {\r
+                       // subgenus or above\r
 \r
                        completeString = localString;\r
                        if (rank == R_SUBGENUS) {\r
+                               // subgenus part\r
                                infraGenericEpithet.append(localString);\r
+                               \r
+                               // genus part\r
+                               genusOrUninomial.append(originalGenus);\r
+                               \r
+                               completeString = originalGenus + " ("+ localString + ")";\r
                        } else {\r
+                               // genus or above\r
                                genusOrUninomial.append(localString);\r
                        }\r
                        \r
                } else {\r
+                       // species or below\r
 \r
                        taxonBase = taxonBase.deproxy(taxonBase, TaxonBase.class);\r
 \r
                        completeString = \r
-                               buildLowerTaxonName(originalGenus, useOriginalGenus,\r
+                               buildLowerTaxonName(originalGenus, useOriginalGenus, \r
                                                genusOrUninomial, infraGenericEpithet, specificEpithet, infraSpecificEpithet,\r
                                                fauEuTaxon);\r
                        \r
                        completeString = (String) CdmUtils.removeDuplicateWhitespace(completeString.trim());\r
 \r
                }\r
-               setCompleteTaxonName(completeString, useOriginalGenus,\r
+               return setCompleteTaxonName(completeString, useOriginalGenus,\r
                                genusOrUninomial.toString(), infraGenericEpithet.toString(), \r
                                specificEpithet.toString(), infraSpecificEpithet.toString(),\r
                                fauEuTaxon, taxonBase, fauEuConfig);\r
-               return completeString;\r
+                \r
        }\r
        \r
        \r
+       /**\r
+        * Determines the original genus name by searching the taxon with rank Genus.\r
+        * @param fauEuTaxon\r
+        * @return\r
+        */\r
+       private String determineOriginalGenus(FaunaEuropaeaTaxon fauEuTaxon) {\r
+               String originalGenus = null;\r
+\r
+               HashMap<Integer, String> ranks = new HashMap<Integer, String>();\r
+               ranks.put(fauEuTaxon.getParentRankId(), fauEuTaxon.getParentName());\r
+               ranks.put(fauEuTaxon.getGrandParentRankId(), fauEuTaxon.getGrandParentName());\r
+               ranks.put(fauEuTaxon.getGreatGrandParentRankId(), fauEuTaxon.getGreatGrandParentName());\r
+               ranks.put(fauEuTaxon.getGreatGreatGrandParentRankId(), fauEuTaxon.getGreatGreatGrandParentName());\r
+               ranks.put(fauEuTaxon.getGreatGreatGreatGrandParentRankId(), fauEuTaxon.getGreatGreatGreatGrandParentName());\r
+               \r
+               originalGenus = ranks.get(R_GENUS);\r
+\r
+               return originalGenus;\r
+       }\r
+\r
        /** Sets name parts and caches */\r
-       private boolean setCompleteTaxonName(String concatString, boolean useOriginalGenus,\r
+       private String setCompleteTaxonName(String concatString, boolean useOriginalGenus,\r
                        String genusOrUninomial, String infraGenericEpithet, String specificEpithet, String infraSpecificEpithet, \r
                        FaunaEuropaeaTaxon fauEuTaxon, TaxonBase<?> taxonBase, FaunaEuropaeaImportConfigurator fauEuConfig) {\r
 \r
@@ -701,56 +855,66 @@ public class FaunaEuropaeaTaxonNameImport extends FaunaEuropaeaImportBase  {
                ZoologicalName zooName = (ZoologicalName)taxonName;\r
                \r
                if (!genusOrUninomial.equals("")) {\r
-                       zooName.setGenusOrUninomial(genusOrUninomial);\r
+                       zooName.setGenusOrUninomial(emptyToNull(genusOrUninomial));\r
                        if (logger.isDebugEnabled()) { \r
                                logger.debug("genusOrUninomial: " + genusOrUninomial); \r
                        }\r
                }\r
-               if (!infraGenericEpithet.equals("")) {\r
-                       zooName.setInfraGenericEpithet(infraGenericEpithet);\r
+               \r
+               //if ((!infraGenericEpithet.equals("") && fauEuTaxon.isParenthesis()) || (!infraGenericEpithet.equals("") && fauEuTaxon.)) {\r
+               if (fauEuTaxon.getParentRankId() == R_SUBGENUS || fauEuTaxon.getRankId() == R_SUBGENUS ||\r
+                               fauEuTaxon.getGrandParentRankId() == R_SUBGENUS || fauEuTaxon.getGreatGrandParentRankId() == R_SUBGENUS) {\r
+                       zooName.setInfraGenericEpithet(emptyToNull(infraGenericEpithet));\r
                        if (logger.isDebugEnabled()) { \r
                                logger.debug("infraGenericEpithet: " + infraGenericEpithet); \r
                        }\r
                }\r
-               if (!specificEpithet.equals("")) {\r
-                       zooName.setSpecificEpithet(specificEpithet);\r
+               if ((fauEuTaxon.getRankId() == R_SPECIES || fauEuTaxon.getRankId() == R_SUBSPECIES)) {\r
+                       zooName.setSpecificEpithet(emptyToNull(specificEpithet));\r
                        if (logger.isDebugEnabled()) { \r
                                logger.debug("specificEpithet: " + specificEpithet); \r
                        }\r
                }\r
-               if (!infraSpecificEpithet.equals("")) {\r
-                       zooName.setInfraSpecificEpithet(infraSpecificEpithet);\r
+               if (fauEuTaxon.getRankId() == R_SUBSPECIES) {\r
+                       zooName.setInfraSpecificEpithet(emptyToNull(infraSpecificEpithet));\r
                        if (logger.isDebugEnabled()) { \r
                                logger.debug("infraSpecificEpithet: " + infraSpecificEpithet); \r
                        }\r
                }\r
-\r
-               zooName.setNameCache(concatString);\r
-               String titleCache = buildNameTitleCache(concatString, useOriginalGenus, fauEuTaxon);\r
-               zooName.setTitleCache(titleCache);\r
+               //TODO: use generate NameCache\r
+               //zooName.setNameCache(concatString);\r
+               String result = zooName.getNameCache();\r
+//             zooName.generateTitle();\r
+               //String titleCache = buildNameTitleCache(concatString, useOriginalGenus, fauEuTaxon);\r
+               //zooName.setTitleCache(titleCache);\r
                //titleCache = buildNameFullTitleCache(concatString, fauEuConfig);\r
-               zooName.setFullTitleCache(titleCache); // TODO: Add reference, NC status\r
+//             zooName.generateFullTitle();\r
+               //zooName.setFullTitleCache(titleCache); // TODO: Add reference, NC status\r
                \r
 //             ImportHelper.setOriginalSource(taxonName, fauEuConfig.getSourceReference(), \r
 //                             fauEuTaxon.getId(), "TaxonName");\r
-\r
-               titleCache = buildTaxonTitleCache(concatString, fauEuConfig.getSourceReference());\r
-               taxonBase.setTitleCache(titleCache);\r
-                       \r
+//             taxonBase.setSec(fauEuConfig.getSourceReference());\r
+//             taxonBase.generateTitle();\r
+               //titleCache = buildTaxonTitleCache(concatString, fauEuConfig.getSourceReference());\r
+               //taxonBase.setTitleCache(titleCache);\r
+               \r
                if (logger.isDebugEnabled()) { \r
-                       logger.debug("Name stored: " + concatString); \r
+                       logger.debug("Name stored: " + result); \r
                }\r
-               return success;\r
+               return result;\r
        }\r
 \r
-       \r
-       protected void saveTaxa(FaunaEuropaeaImportState state, Map<Integer, TaxonBase<?>> taxonMap) {\r
-\r
-               if(logger.isDebugEnabled()) { logger.debug("Saving taxa ..."); }\r
-\r
-               getTaxonService().saveTaxonAll(taxonMap.values());\r
-\r
+       /**\r
+        * Ensures that empty strings are translated to null.\r
+        * @param genusOrUninomial\r
+        * @return\r
+        */\r
+       private String emptyToNull(String text) {\r
+               if (CdmUtils.isEmpty(text)) {\r
+                       return null;\r
+               } else {\r
+                       return text;\r
+               }\r
        }\r
-       \r
 \r
 }\r