Memory use is more efficient
authorem.lee <em.lee@localhost>
Fri, 18 Jun 2010 10:33:30 +0000 (10:33 +0000)
committerem.lee <em.lee@localhost>
Fri, 18 Jun 2010 10:33:30 +0000 (10:33 +0000)
cdmlib-io/src/main/java/eu/etaxonomy/cdm/io/pesi/out/PesiExportState.java
cdmlib-io/src/main/java/eu/etaxonomy/cdm/io/pesi/out/PesiOccurrenceExport.java
cdmlib-io/src/main/java/eu/etaxonomy/cdm/io/pesi/out/PesiOccurrenceSourceExport.java
cdmlib-io/src/main/java/eu/etaxonomy/cdm/io/pesi/out/PesiSourceExport.java
cdmlib-io/src/main/java/eu/etaxonomy/cdm/io/pesi/out/PesiTaxonExport.java

index eb72d524ed99ace947958429b211defb0fbf311a..8ea9172ab4a652db5948d427e12d0269dc640add 100644 (file)
@@ -9,10 +9,6 @@
 */\r
 package eu.etaxonomy.cdm.io.pesi.out;\r
 \r
-import java.sql.Connection;\r
-import java.sql.PreparedStatement;\r
-import java.sql.SQLException;\r
-import java.sql.Statement;\r
 import java.util.ArrayList;\r
 import java.util.List;\r
 \r
@@ -29,250 +25,45 @@ import eu.etaxonomy.cdm.model.common.CdmBase;
  */\r
 public class PesiExportState extends DbExportStateBase<PesiExportConfigurator>{\r
        private static final Logger logger = Logger.getLogger(PesiExportState.class);\r
-       private static List<Integer> processedTaxonNameList = new ArrayList<Integer>();\r
        private static List<Integer> processedSourceList = new ArrayList<Integer>();\r
-       private List<Integer> treeIndexList = new ArrayList<Integer>();\r
-       private static final String state_db_table = "tmp_state";\r
-       private static final String processed_taxonname_db_table = "tmp_processed_taxonname";\r
-       private static final String processed_source_db_table = "tmp_processed_source";\r
-       private static final String processed_treeindex_and_kingdomfk_db_table = "tmp_processed_treeindex_kingdomfk";\r
-       private Connection connection;\r
-       private PreparedStatement select_KingdomId_TreeIndex_NomenclaturalCode_Stmt;\r
-       private PreparedStatement insert_KingdomId_TreeIndex_NomenclaturalCode_Stmt;\r
-       private PreparedStatement insert_state_Stmt;\r
-       private PreparedStatement select_state_Stmt;\r
-       \r
+\r
        /**\r
         * @param config\r
         */\r
        public PesiExportState(PesiExportConfigurator config) {\r
                super(config);\r
-               \r
-               try {\r
-                       connection = getConfig().getDestination().getConnection();\r
-\r
-                       // Retrieve treeIndex, kingdomId and nomenclaturalCode from database\r
-//                     String sql = "SELECT kingdom_id, tree_index, nomenclatural_code FROM " + processed_treeindex_and_kingdomfk_db_table + " WHERE tree_index like ?";\r
-//                     select_KingdomId_TreeIndex_NomenclaturalCode_Stmt = connection.prepareStatement(sql);\r
-                       \r
-                       // Add TreeIndex, KingdomFk and nomenclaturalCode to database\r
-//                     sql = "INSERT INTO " + processed_treeindex_and_kingdomfk_db_table + " VALUES (?, ?, ?)";\r
-//                     insert_KingdomId_TreeIndex_NomenclaturalCode_Stmt = connection.prepareStatement(sql);\r
-                       \r
-                       // Add cdmId/pesiId pair to database \r
-                       String sql = "INSERT INTO " + state_db_table + " VALUES ( ?, ?)";\r
-                       insert_state_Stmt = connection.prepareStatement(sql);\r
-                       \r
-                       sql = "SELECT pesi_id FROM " + state_db_table + " WHERE cdm_id = ?";\r
-                       select_state_Stmt = connection.prepareStatement(sql);\r
-\r
-               } catch (SQLException e) {\r
-                       // TODO Auto-generated catch block\r
-                       e.printStackTrace();\r
-               }\r
-\r
-               createStateTables();\r
        }\r
        \r
-       /**\r
-        * Create the database table that hosts state information.\r
-        */\r
-       public boolean createStateTables() {\r
-               \r
-               String query;\r
-        Statement stmt;\r
-        \r
-        if (deleteStateTables()) {\r
-/*             try {\r
-                       query="CREATE TABLE " + state_db_table + " (cdm_id varchar(100), pesi_id int)";\r
-                       stmt = connection.createStatement();\r
-                       stmt.executeUpdate(query);\r
-               } catch (Exception e) {\r
-                       logger.error("Couldn't create database table for state information.");\r
-                   e.printStackTrace();\r
-                   throw new RuntimeException("Couldn't create database table for state information.");\r
-               }\r
-       \r
-               try {\r
-                       query="CREATE TABLE " + processed_taxonname_db_table + " (cdm_id varchar(100))";\r
-                       stmt = connection.createStatement();\r
-                       stmt.executeUpdate(query);\r
-                       stmt.close();\r
-               } catch (Exception e) {\r
-                       logger.error("Couldn't create database table for processed taxonnames.");\r
-                   e.printStackTrace();\r
-                   throw new RuntimeException("Couldn't create database table for processed taxonnames.");\r
-               }\r
-       \r
-               try {\r
-                       query="CREATE TABLE " + processed_source_db_table + " (cdm_id int)";\r
-                       stmt = connection.createStatement();\r
-                       stmt.executeUpdate(query);\r
-                       stmt.close();\r
-               } catch (Exception e) {\r
-                       logger.error("Couldn't create database table for processed sources.");\r
-                   e.printStackTrace();\r
-                   throw new RuntimeException("Couldn't create database table for processed sources.");\r
-               }\r
-\r
-               try {\r
-                query="CREATE TABLE " + processed_treeindex_and_kingdomfk_db_table + " (kingdom_id int, tree_index varchar(200), nomenclatural_code varchar(100))";\r
-                stmt = connection.createStatement();\r
-                stmt.executeUpdate(query);\r
-                stmt.close();\r
-               } catch (Exception e) {\r
-                       logger.error("Couldn't create database table for processed treeindex and kingdomfk.");\r
-                   e.printStackTrace();\r
-                   throw new RuntimeException("Couldn't create database table for processed treeindex and kingdomfk.");\r
-               }*/\r
-        }\r
-\r
-        return true;\r
-       }\r
-\r
-       /**\r
-        * Deletes existing state tables.\r
-        */\r
-       public boolean deleteStateTables() {\r
-               boolean result = true;\r
-               \r
-               String query;\r
-        Statement stmt;\r
-        \r
-/*        try {\r
-                query="DROP TABLE " + state_db_table;\r
-                stmt = connection.createStatement();\r
-                stmt.executeUpdate(query);\r
-                stmt.close();\r
-        } catch (Exception e) {\r
-               logger.error("Couldn't drop database table for state information.");\r
-//            result = false;\r
-        }\r
-\r
-        try {\r
-                query="DROP TABLE " + processed_taxonname_db_table;\r
-                stmt = connection.createStatement();\r
-                stmt.executeUpdate(query);\r
-                stmt.close();\r
-        } catch (Exception e) {\r
-               logger.error("Couldn't drop database table for processed taxonnames.");\r
-//            result = false;\r
-        }\r
 \r
-        try {\r
-                query="DROP TABLE " + processed_source_db_table;\r
-                stmt = connection.createStatement();\r
-                stmt.executeUpdate(query);\r
-                stmt.close();\r
-        } catch (Exception e) {\r
-               logger.error("Couldn't drop database table for processed sources.");\r
-//            result = false;\r
-        }\r
-\r
-        try {\r
-            query="DROP TABLE " + processed_treeindex_and_kingdomfk_db_table;\r
-            stmt = connection.createStatement();\r
-            stmt.executeUpdate(query);\r
-            stmt.close();\r
-    } catch (Exception e) {\r
-       logger.error("Couldn't drop database table for treeindex and kingdomfk.");\r
-//        result = false;\r
-    }*/\r
-\r
-        return result;\r
-       }\r
-       \r
        /**\r
-        * Put datawarehouse database identifier into table for state information.\r
+        * Stores the Datawarehouse.id to a specific CDM object originally.\r
+        * Does nothing now since we do not want to store Cdm.id/Datawarehouse.id pairs. This saves precious memory.\r
         * @param cdmBase\r
         * @param dbId\r
         */\r
        @Override\r
        public void putDbId(CdmBase cdmBase, int dbId) {\r
-//             try {\r
-//                     insert_state_Stmt.setInt(1, cdmBase.getId());\r
-//                     insert_state_Stmt.setInt(2, dbId);\r
-//                     insert_state_Stmt.executeUpdate();\r
-//             } catch (SQLException e) {\r
-//                     logger.error("Could not store state information into database: " + e.getMessage());\r
-//                     e.printStackTrace();\r
-//             }\r
+               // Do nothing\r
        }\r
 \r
        /**\r
-        * Get datawarehouse database identifier from table for state information.\r
+        * Gets the Datawarehouse.id to a specific CDM object originally.\r
+        * Here it just returns the CDM object's id.\r
         * @param cdmBase\r
         * @return\r
         */\r
        @Override\r
        public Integer getDbId(CdmBase cdmBase) {\r
-               return cdmBase.getId();\r
-               \r
-//             ResultSet resultSet = null;\r
-//             try {\r
-//                     select_state_Stmt.setInt(1, cdmBase.getId());\r
-//                     resultSet = select_state_Stmt.executeQuery();\r
-//             } catch (SQLException e) {\r
-//                     logger.error("Could not determine datawarehouse database identifier: " + e.getMessage());\r
-//                     e.printStackTrace();\r
-//             }\r
-//\r
-//             Integer pesiDbKey = 0;\r
-//             try {\r
-//                     if (resultSet != null) {\r
-//                             while (resultSet.next()) {\r
-//                                     pesiDbKey = resultSet.getInt("pesi_id");\r
-//                             }\r
-//                     }\r
-//             } catch (SQLException e) {\r
-//                     logger.error("Could not determine pesiId for cdmId.");\r
-//                     throw new RuntimeException("Could not determine pesiId for cdmId.");\r
-//             }\r
-//             if (pesiDbKey == 0) {\r
-//                     logger.warn("A datawarehouse database identifier could not be determined for this cdmBase entity: " + cdmBase.getId());\r
-//                     pesiDbKey = null;\r
-//             }\r
-//             return pesiDbKey;\r
+               // We use the Cdm.id for Datawarehouse.id\r
+               if (cdmBase == null) {\r
+                       return null;\r
+               } else {\r
+                       return cdmBase.getId();\r
+               }\r
        }\r
        \r
-\r
-//     @Override\r
-//     public Integer getDbId(CdmBase cdmBase) {\r
-//             if (cdmBase != null) {\r
-//                     IdType type = getConfig().getIdType();\r
-//                     if (type == IdType.CDM_ID) {\r
-//                             return cdmBase.getId();\r
-//                     } else {\r
-//                             return dbIdMap.get(cdmBase.getUuid());\r
-//                     }\r
-//             } else {\r
-//                     logger.warn("CdmBase was (null). No entries in dbIdMap available");\r
-//                     return null;\r
-//             }\r
-//     }\r
-\r
-       /**\r
-        * Removes a {@link CdmBase CdmBase} entry from this state's {@link java.util.Map Map}.\r
-        * @param cdmBase The {@link CdmBase CdmBase} to be deleted.\r
-        * @return Whether deletion was successful or not.\r
-        */\r
-//     public boolean removeDbId(CdmBase cdmBase) {\r
-//             if (cdmBase != null) {\r
-//                     IdType type = getConfig().getIdType();\r
-//                     if (type != IdType.CDM_ID) {\r
-//                             dbIdMap.remove(cdmBase.getUuid());\r
-//                             return true;\r
-//                     } else {\r
-//                             return false;\r
-//                     }\r
-//             } else {\r
-//                     logger.warn("CdmBase was (null). No entries in dbIdMap available");\r
-//                     return false;\r
-//             }\r
-//     }\r
-\r
        /**\r
-        * Returns whether the given object was processed before or not.\r
+        * Returns whether the given Source object was processed before or not.\r
         * @param\r
         * @return\r
         */\r
index 8f63d99318828ff6022be1d719dbf5e1a8932a71..e98f93d26fbb31cfc758763cc06cbb78d9127528 100644 (file)
@@ -169,10 +169,10 @@ public class PesiOccurrenceExport extends PesiExportBase {
 \r
                                // Start transaction\r
                                txStatus = startTransaction(true);\r
-                               logger.error("Started new transaction. Fetching some " + pluralString + " first (max: " + limit + ") ...");\r
+                               logger.error("Started new transaction. Fetching some " + parentPluralString + " first (max: " + limit + ") ...");\r
                        }\r
                        if (list.size() == 0) {\r
-                               logger.error("No " + pluralString + " left to fetch.");\r
+                               logger.error("No " + parentPluralString + " left to fetch.");\r
                        }\r
                        // Commit transaction\r
                        commitTransaction(txStatus);\r
@@ -411,10 +411,16 @@ public class PesiOccurrenceExport extends PesiExportBase {
         * @see MethodMapper\r
         */\r
        private static Integer getSourceFk(AnnotatableEntity entity, PesiExportState state) {\r
-               Integer result = null;          \r
-               if (state != null && entity != null && entity.isInstanceOf(ReferenceBase.class)) {\r
-                       ReferenceBase reference = CdmBase.deproxy(entity, ReferenceBase.class);\r
-                       result = state.getDbId(reference);\r
+               Integer result = null;\r
+               if (state != null && entity != null && entity.isInstanceOf(Distribution.class)) {\r
+                       Distribution distribution = CdmBase.deproxy(entity, Distribution.class);\r
+                       Set<DescriptionElementSource> sources = distribution.getSources();\r
+                       if (sources.size() == 1) {\r
+                               DescriptionElementSource source = sources.iterator().next();\r
+                               result = state.getDbId(source.getCitation());\r
+                       } else if (sources.size() > 1) {\r
+                               logger.warn("Found Distribution with " + sources.size() + " sources.");\r
+                       }\r
                }\r
                return result;\r
        }\r
@@ -427,9 +433,19 @@ public class PesiOccurrenceExport extends PesiExportBase {
         */\r
        private static String getSourceCache(AnnotatableEntity entity) {\r
                String result = null;\r
-               if (entity != null && entity.isInstanceOf(ReferenceBase.class)) {\r
-                       ReferenceBase reference = CdmBase.deproxy(entity, ReferenceBase.class);\r
-                       result = reference.getTitle();\r
+               ReferenceBase reference;\r
+               if (entity != null && entity.isInstanceOf(Distribution.class)) {\r
+                       Distribution distribution = CdmBase.deproxy(entity, Distribution.class);\r
+                       Set<DescriptionElementSource> sources = distribution.getSources();\r
+                       if (sources.size() == 1) {\r
+                               DescriptionElementSource source = sources.iterator().next();\r
+                               reference = source.getCitation();\r
+                               if (reference != null) {\r
+                                       result = reference.getTitle();\r
+                               }\r
+                       } else if (sources.size() > 1) {\r
+                               logger.warn("Found Distribution with " + sources.size() + " sources.");\r
+                       }\r
                }\r
                return result;\r
        }\r
index 1a276c95dd4eb490531a6f2fe34d2d6f08752e0a..76c8938d9d0fafbb52c39ecd1fc1757846e38ed9 100644 (file)
@@ -182,9 +182,6 @@ public class PesiOccurrenceSourceExport extends PesiExportBase {
        \r
                        logger.error("*** Finished Making " + pluralString + " ..." + getSuccessString(success));\r
                        \r
-                       // Delete database table helper\r
-                       state.deleteStateTables();\r
-                       \r
                        return success;\r
                } catch (SQLException e) {\r
                        e.printStackTrace();\r
index 2426bbbb9cb9f0f6a577ec3cb8a53331d35e8594..4bfc119260f029b62bb66ffd62e1e689b8d26a8f 100644 (file)
@@ -82,9 +82,6 @@ public class PesiSourceExport extends PesiExportBase {
                        // PESI: Clear the database table Source.\r
                        doDelete(state);\r
 \r
-                       // Create the database table that hosts state information\r
-                       state.createStateTables();\r
-\r
                        // CDM: Get the number of all available references.\r
 //                     int maxCount = getReferenceService().count(null);\r
 //                     logger.error("Total amount of " + maxCount + " " + pluralString + " will be exported.");\r
index 7b928fd45cd53405819607448718a9abbad55885..c71ff155ee44ae22dfb92583ad3b1376692cc749 100644 (file)
@@ -13,8 +13,10 @@ import java.sql.Connection;
 import java.sql.PreparedStatement;\r
 import java.sql.SQLException;\r
 import java.util.ArrayList;\r
+import java.util.HashMap;\r
 import java.util.List;\r
 import java.util.Set;\r
+import java.util.UUID;\r
 import java.util.regex.Matcher;\r
 import java.util.regex.Pattern;\r
 \r
@@ -26,9 +28,12 @@ import org.springframework.transaction.TransactionStatus;
 import eu.etaxonomy.cdm.io.berlinModel.out.mapper.IdMapper;\r
 import eu.etaxonomy.cdm.io.berlinModel.out.mapper.MethodMapper;\r
 import eu.etaxonomy.cdm.io.common.Source;\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.IdentifiableEntity;\r
 import eu.etaxonomy.cdm.model.common.IdentifiableSource;\r
+import eu.etaxonomy.cdm.model.common.Language;\r
 import eu.etaxonomy.cdm.model.common.VersionableEntity;\r
 import eu.etaxonomy.cdm.model.name.NameTypeDesignation;\r
 import eu.etaxonomy.cdm.model.name.NameTypeDesignationStatus;\r
@@ -62,6 +67,10 @@ public class PesiTaxonExport extends PesiExportBase {
        private static final String pluralString = "Taxa";\r
        private PreparedStatement parentTaxonFk_TreeIndex_KingdomFkStmt;\r
        private PreparedStatement synonymsStmt;\r
+       private NomenclaturalCode nomenclaturalCode;\r
+       private Integer kingdomFk;\r
+       private HashMap<Rank, Rank> rankMap = new HashMap<Rank, Rank>();\r
+       private List<Rank> rankList = new ArrayList<Rank>();\r
        \r
        enum NamePosition {\r
                beginning,\r
@@ -154,7 +163,6 @@ public class PesiTaxonExport extends PesiExportBase {
        /* (non-Javadoc)\r
         * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doInvoke(eu.etaxonomy.cdm.io.common.IoStateBase)\r
         */\r
-       @SuppressWarnings("deprecation")\r
        @Override\r
        protected boolean doInvoke(PesiExportState state) {\r
                try {\r
@@ -168,7 +176,7 @@ public class PesiTaxonExport extends PesiExportBase {
 \r
                        String synonymsSql = "UPDATE Taxon SET ParentTaxonFk = ?, KingdomFk = ?, RankFk = ?, RankCache = ? WHERE TaxonId = ?"; \r
                        synonymsStmt = con.prepareStatement(synonymsSql);\r
-\r
+                       \r
                        // Get the limit for objects to save within a single transaction.\r
                        int limit = state.getConfig().getLimitSave();\r
 \r
@@ -194,7 +202,7 @@ public class PesiTaxonExport extends PesiExportBase {
                        List<TaxonNameBase> list = null;\r
 \r
                        // 1st Round: Make Taxa\r
-/*                     logger.error("PHASE 1...");\r
+                       logger.error("PHASE 1...");\r
                        // Start transaction\r
                        txStatus = startTransaction(true);\r
                        logger.error("Started new transaction. Fetching some " + pluralString + " (max: " + limit + ") ...");\r
@@ -206,31 +214,32 @@ public class PesiTaxonExport extends PesiExportBase {
                                        success &= mapping.invoke(taxonName);\r
                                        \r
                                        // Check whether some rules are violated\r
-//                                             if (rank == null) {\r
-//                                                     logger.error("Rank was not determined: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");\r
-//                                             } else {\r
-//                                                     if (infraSpecificEpithet == null && rank.intValue() == 190) {\r
-//                                                             logger.error("InfraSpecificEpithet was not determined although it should exist for rank 190: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");\r
-//                                                     }\r
-//                                                     if (specificEpithet != null && rank.intValue() < 220) {\r
-//                                                             logger.error("SpecificEpithet was determined for rank " + rank + " although it should only exist for ranks higher or equal to 220: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");\r
-//                                                     }\r
-//                                                     if (infraSpecificEpithet != null && rank.intValue() < 230) {\r
-//                                                             logger.error("InfraSpecificEpithet was determined for rank " + rank + " although it should only exist for ranks higher or equal to 230: "  + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");\r
-//                                                     }\r
-//                                             }\r
-//                                             if (infraSpecificEpithet != null && specificEpithet == null) {\r
-//                                                     logger.error("An infraSpecificEpithet was determined, but a specificEpithet was not determined: "  + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");\r
-//                                             }\r
-//                                             if (genusOrUninomial == null) {\r
-//                                                     logger.error("GenusOrUninomial was not determined: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");\r
-//                                             }\r
-//                                             \r
-//                                             rank = null;\r
-//                                             infraSpecificEpithet = null;\r
-//                                             genusOrUninomial = null;\r
-//                                             specificEpithet = null;\r
-\r
+                                       nomenclaturalCode = taxonName.getNomenclaturalCode();\r
+                                       String genusOrUninomial = getGenusOrUninomial(taxonName);\r
+                                       String specificEpithet = getSpecificEpithet(taxonName);\r
+                                       String infraSpecificEpithet = getInfraSpecificEpithet(taxonName);\r
+                                       Integer rank = getRankFk(taxonName, nomenclaturalCode);\r
+                                       \r
+                                       if (rank == null) {\r
+                                               logger.error("Rank was not determined: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");\r
+                                       } else {\r
+                                               if (infraSpecificEpithet == null && rank.intValue() == 190) {\r
+                                                       logger.error("InfraSpecificEpithet was not determined although it should exist for rank 190: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");\r
+                                               }\r
+                                               if (specificEpithet != null && rank.intValue() < 220) {\r
+                                                       logger.error("SpecificEpithet was determined for rank " + rank + " although it should only exist for ranks higher or equal to 220: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");\r
+                                               }\r
+                                               if (infraSpecificEpithet != null && rank.intValue() < 230) {\r
+                                                       logger.error("InfraSpecificEpithet was determined for rank " + rank + " although it should only exist for ranks higher or equal to 230: "  + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");\r
+                                               }\r
+                                       }\r
+                                       if (infraSpecificEpithet != null && specificEpithet == null) {\r
+                                               logger.error("An infraSpecificEpithet was determined, but a specificEpithet was not determined: "  + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");\r
+                                       }\r
+                                       if (genusOrUninomial == null) {\r
+                                               logger.error("GenusOrUninomial was not determined: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");\r
+                                       }\r
+                                       \r
                                }\r
 \r
                                // Commit transaction\r
@@ -248,53 +257,104 @@ public class PesiTaxonExport extends PesiExportBase {
                        }\r
                        // Commit transaction\r
                        commitTransaction(txStatus);\r
-                       logger.error("Committed transaction.");*/\r
+                       logger.error("Committed transaction.");\r
 \r
                        count = 0;\r
                        pastCount = 0;\r
                        List<TaxonomicTree> taxonomicTreeList = null;\r
-                       // 2nd Round: Add ParentTaxonFk to each Taxon\r
+                       // 2nd Round: Add ParentTaxonFk, TreeIndex, Rank and KingdomFk to each Taxon\r
                        logger.error("PHASE 2...");\r
-                       // Start transaction\r
-                       txStatus = startTransaction(true);\r
-                       logger.error("Started new transaction. Fetching some " + pluralString + " (max: " + limit + ") ...");\r
-                       Integer taxonomicTreeLimit = 1;\r
-                       Integer taxonomicTreeStart = 0;\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
+                       rankMap.put(Rank.GENUS(), null); // Since NULL does not match an existing Rank, traverse all the way down to the leafs\r
+                       rankMap.put(Rank.KINGDOM(), Rank.GENUS()); // excludes rank genus\r
+                       \r
                        StringBuffer treeIndex = new StringBuffer();\r
-                       while ((taxonomicTreeList = getTaxonTreeService().listTaxonomicTrees(taxonomicTreeLimit, taxonomicTreeStart, null, null)).size() > 0) {\r
-                               logger.error("Fetched " + taxonomicTreeList.size() + " Taxonomic Tree.");\r
+                       \r
+                       // Retrieve list of Taxonomic Trees\r
+                       txStatus = startTransaction(true);\r
+                       logger.error("Started transaction. Fetching all Taxonomic Trees...");\r
+                       taxonomicTreeList = getTaxonTreeService().listTaxonomicTrees(null, 0, null, null);\r
+                       commitTransaction(txStatus);\r
+                       logger.error("Committed transaction.");\r
+\r
+                       logger.error("Fetched " + taxonomicTreeList.size() + " Taxonomic Tree.");\r
 \r
-                               for (TaxonomicTree taxonomicTree : taxonomicTreeList) {\r
-                                       logger.error("Number of Root Nodes for this Taxonomic Tree: " + taxonomicTree.getRootNodes().size());\r
+                       for (TaxonomicTree taxonomicTree : taxonomicTreeList) {\r
+                               for (Rank rank : rankList) {\r
                                        \r
-                                       for (TaxonNode rootNode : taxonomicTree.getRootNodes()) {\r
-                                               logger.error("Number of Child Nodes for this Root Node: " + rootNode.getChildNodes().size() + ". Traversing branches...");\r
+                                       txStatus = startTransaction(true);\r
+                                       logger.error("Started transaction for Tree Pass starting from Rank " + rank.getLabel() + " ...");\r
+                                       \r
+                                       logger.error("Fetching RootNodes for Rank " + rank.getLabel());\r
+                                       List<TaxonNode> rankSpecificRootNodes = getTaxonTreeService().loadRankSpecificRootNodes(taxonomicTree, rank, null);\r
+                                       logger.error("Fetched " + rankSpecificRootNodes.size() + " RootNodes for Rank " + rank.getLabel());\r
+\r
+                                       commitTransaction(txStatus);\r
+                                       logger.error("Committed transaction.");\r
+\r
+                                       int elementCount = 0;\r
+                                       int halfCount = rankSpecificRootNodes.size() / 2;\r
+\r
+                                       logger.error("Working through nodes...");\r
+                                       for (TaxonNode rootNode : rankSpecificRootNodes) {\r
+                                               txStatus = startTransaction(false);\r
+                                               \r
+                                               rootNode = getTaxonNodeService().load(rootNode.getUuid());\r
                                                \r
-                                               for (TaxonNode rootChild : rootNode.getChildNodes()) {\r
-                                                       // Traverse all branches from this rootChild\r
+//                                             logger.error("Traversing childNodes of Node " + rootNode.getUuid());\r
+\r
+                                               TaxonNode parentNode = rootNode.getParent();\r
+                                               if (rank.equals(Rank.KINGDOM())) {\r
+                                                       treeIndex = new StringBuffer();\r
                                                        treeIndex.append("#");\r
-                                                       traverseTree(rootChild, rootNode, treeIndex, rootChild.getTaxon().getName().getRank(), state);\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(AnnotationType.TREEINDEX())) {\r
+                                                                               // It is assumed that there is only one annotation using AnnotationType TREEINDEX. If there are more only the first is noticed.\r
+                                                                               treeIndex = new StringBuffer(annotation.getText());\r
+                                                                               annotationFound = true;\r
+                                                                               logger.error("treeIndex: " + treeIndex);\r
+                                                                               break;\r
+                                                                       }\r
+                                                               }\r
+                                                               if (!annotationFound) {\r
+                                                                       // This should not happen usually since 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 this TaxonNode: " + parentNode.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: " + rootNode.getUuid());\r
+                                                               treeIndex = new StringBuffer(); // This just prevents growing of the treeIndex in a wrong manner\r
+                                                               treeIndex.append("#");\r
+                                                       }\r
                                                }\r
-                                       }\r
-                               }\r
+                                               \r
+                                               nomenclaturalCode = rootNode.getTaxon().getName().getNomenclaturalCode();\r
+                                               kingdomFk = PesiTransformer.nomenClaturalCode2Kingdom(nomenclaturalCode);\r
+                                               traverseTree(rootNode, parentNode, treeIndex, rankMap.get(rank), state);\r
+                                               \r
+                                               commitTransaction(txStatus);\r
 \r
-                               // Commit transaction\r
-                               commitTransaction(txStatus);\r
-                               logger.error("Committed transaction.");\r
+                                               elementCount++;\r
+                                               if (elementCount == halfCount) {\r
+                                                       logger.error("50% of " + rank.getLabel() + " RootNodes processed...");\r
+                                               }\r
+                                       }\r
 \r
-                               // Start transaction\r
-                               txStatus = startTransaction(true);\r
-                               logger.error("Started new transaction. Fetching some " + pluralString + " (max: " + limit + ") ...");\r
-                               \r
-                               // Pick next Taxonomic Tree\r
-                               taxonomicTreeStart++;\r
-                       }\r
-                       if (taxonomicTreeList.size() == 0) {\r
-                               logger.error("No " + pluralString + " left to fetch.");\r
+                               }\r
                        }\r
-                       // Commit transaction\r
-                       commitTransaction(txStatus);\r
-                       logger.error("Committed transaction.");\r
 \r
                        logger.error("*** Finished Making " + pluralString + " ..." + getSuccessString(success));\r
 \r
@@ -307,23 +367,58 @@ public class PesiTaxonExport extends PesiExportBase {
        }\r
 \r
        /**\r
-        * Traverse the TaxonTree and store determined values for every Taxon.\r
-        * @param rootChild\r
+        * Traverse the TaxonTree recursively and store determined values for every Taxon.\r
+        * @param childNode\r
+        * @param parentNode\r
+        * @param treeIndex\r
+        * @param fetchLevel\r
+        * @param state\r
         */\r
-       private void traverseTree(TaxonNode childNode, TaxonNode parentNode, StringBuffer treeIndex, Rank kingdomRank, PesiExportState state) {\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
                if (childNode.getTaxon() != null) {\r
-                       if (state.getDbId(childNode.getTaxon().getName()) != null) {\r
-                               treeIndex.append(state.getDbId(childNode.getTaxon().getName()));\r
-                               treeIndex.append("#");\r
+                       TaxonNameBase taxonName = childNode.getTaxon().getName();\r
+                       Integer taxonNameId = state.getDbId(taxonName);\r
+                       if (taxonNameId != null) {\r
+                               Rank childTaxonNameRank = taxonName.getRank();\r
+                               if (childTaxonNameRank != null) {\r
+                                       if (! childTaxonNameRank.equals(fetchLevel)) {\r
 \r
-                               saveData(childNode, parentNode, treeIndex, state, state.getDbId(childNode.getTaxon().getName()));\r
+                                               treeIndex.append(taxonNameId);\r
+                                               treeIndex.append("#");\r
 \r
-                               for (TaxonNode newNode : childNode.getChildNodes()) {\r
-                                       traverseTree(newNode, childNode, treeIndex, kingdomRank, state);\r
+                                               saveData(childNode, parentNode, treeIndex, state, taxonNameId);\r
+                                               \r
+                                               // Store treeIndex as annotation for further use\r
+                                               Set<Annotation> annotations = childNode.getAnnotations();\r
+                                               boolean found = false;\r
+                                               for (Annotation annotation : annotations) {\r
+                                                       AnnotationType annotationType = annotation.getAnnotationType();\r
+                                                       if (annotationType != null && annotationType.equals(AnnotationType.TREEINDEX())) {\r
+                                                               annotation.setText(treeIndex.toString());\r
+                                                               found = true;\r
+                                                               break;\r
+                                                       }\r
+                                               }\r
+                                               if (!found) {\r
+                                                       childNode.addAnnotation(Annotation.NewInstance(treeIndex.toString(), AnnotationType.TREEINDEX(), Language.DEFAULT()));\r
+                                               }\r
+\r
+                                               for (TaxonNode newNode : childNode.getChildNodes()) {\r
+                                                       traverseTree(newNode, childNode, treeIndex, fetchLevel, state);\r
+                                               }\r
+                                               \r
+                                       } else {\r
+//                                             logger.error("Target Rank " + fetchLevel.getLabel() + " reached");\r
+                                               return;\r
+                                       }\r
+                               } else {\r
+                                       logger.error("Rank is NULL. FetchLevel can not be checked: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");\r
                                }\r
                        } else {\r
-                               logger.error("TaxonName can not be found in State: " + childNode.getTaxon().getName().getUuid() + " (" + childNode.getTaxon().getName().getTitleCache());\r
+                               logger.error("TaxonName can not be found in State: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");\r
                        }\r
+\r
                } else {\r
                        logger.error("Taxon is NULL for TaxonNode: " + childNode.getUuid());\r
                }\r
@@ -340,25 +435,35 @@ public class PesiTaxonExport extends PesiExportBase {
        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
-               if (childNode.getTaxon() != null && childNode.getTaxon().getName() != null) {\r
-                       if (parentNode.getTaxon() != null && parentNode.getTaxon().getName() != null) {\r
-                                       invokeParentTaxonFkAndTreeIndexAndKindomFk(childNode.getTaxon().getName(), \r
-                                                       childNode.getTaxon().getName().getNomenclaturalCode(), \r
-                                                       PesiTransformer.nomenClaturalCode2Kingdom(childNode.getTaxon().getName().getNomenclaturalCode()), \r
-                                                       state.getDbId(parentNode.getTaxon().getName()), \r
-                                                       currentTaxonFk, \r
-                                                       treeIndex);\r
+               Taxon childNodeTaxon = childNode.getTaxon();\r
+               TaxonNameBase childNodeTaxonName = childNode.getTaxon().getName();\r
+               if (childNodeTaxon != null && childNodeTaxonName != null) {\r
+                       TaxonNameBase parentNodeTaxonName = null;\r
+                       if (parentNode != null) {\r
+                               Taxon parentNodeTaxon = parentNode.getTaxon();\r
+                               if (parentNodeTaxon != null) {\r
+                                       parentNodeTaxonName  = parentNodeTaxon.getName();\r
+                               }\r
                        }\r
+\r
+                       invokeParentTaxonFkAndTreeIndexAndKingdomFk(childNodeTaxonName, \r
+                                       nomenclaturalCode, \r
+                                       kingdomFk, \r
+                                       state.getDbId(parentNodeTaxonName), \r
+                                       currentTaxonFk, \r
+                                       treeIndex);\r
                }\r
                \r
+               // TODO: Move to RelTaxon export\r
                // Synonyms of the current Taxon: Don't store treeIndex for Synonyms\r
-               for (Synonym synonym : childNode.getTaxon().getSynonyms()) {\r
-                       invokeSynonyms(synonym.getName(), \r
-                                       childNode.getTaxon().getName().getNomenclaturalCode(), \r
-                                       PesiTransformer.nomenClaturalCode2Kingdom(childNode.getTaxon().getName().getNomenclaturalCode()), \r
-                                       currentTaxonFk, \r
-                                       state.getDbId(synonym.getName()));\r
-               }\r
+//             for (Synonym synonym : childNodeTaxon.getSynonyms()) {\r
+//                     TaxonNameBase synonymTaxonName = synonym.getName();\r
+//                     invokeSynonyms(synonymTaxonName, \r
+//                                     nomenclaturalCode, \r
+//                                     kingdomFk, \r
+//                                     currentTaxonFk, \r
+//                                     state.getDbId(synonymTaxonName));\r
+//             }\r
        }\r
 \r
        /**\r
@@ -394,9 +499,13 @@ public class PesiTaxonExport extends PesiExportBase {
         * @param stmt\r
         * @return\r
         */\r
-       protected boolean invokeParentTaxonFkAndTreeIndexAndKindomFk(TaxonNameBase taxonName, NomenclaturalCode nomenclaturalCode, Integer kingdomFk, Integer parentTaxonFk, Integer currentTaxonFk, StringBuffer treeIndex) {\r
+       protected boolean invokeParentTaxonFkAndTreeIndexAndKingdomFk(TaxonNameBase taxonName, NomenclaturalCode nomenclaturalCode, Integer kingdomFk, Integer parentTaxonFk, Integer currentTaxonFk, StringBuffer treeIndex) {\r
                try {\r
-                       parentTaxonFk_TreeIndex_KingdomFkStmt.setInt(1, parentTaxonFk);\r
+                       if (parentTaxonFk != null) {\r
+                               parentTaxonFk_TreeIndex_KingdomFkStmt.setInt(1, parentTaxonFk);\r
+                       } else {\r
+                               parentTaxonFk_TreeIndex_KingdomFkStmt.setObject(1, parentTaxonFk);\r
+                       }\r
                        parentTaxonFk_TreeIndex_KingdomFkStmt.setString(2, treeIndex.toString());\r
                        parentTaxonFk_TreeIndex_KingdomFkStmt.setInt(3, kingdomFk);\r
                        parentTaxonFk_TreeIndex_KingdomFkStmt.setInt(4, getRankFk(taxonName, nomenclaturalCode));\r
@@ -406,7 +515,13 @@ public class PesiTaxonExport extends PesiExportBase {
                        return true;\r
                } catch (SQLException e) {\r
                        logger.error("SQLException during treeIndex invoke for taxonName - " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + "): " + e.getMessage());\r
-                       e.printStackTrace();\r
+                       logger.error("parentTaxonFk: " + parentTaxonFk);\r
+                       logger.error("treeIndex: " + treeIndex);\r
+                       logger.error("kingdomFk: " + kingdomFk);\r
+                       logger.error("rankFk: " + getRankFk(taxonName, nomenclaturalCode));\r
+                       logger.error("rankCache: " + getRankCache(taxonName, nomenclaturalCode));\r
+                       logger.error("taxonFk: " + currentTaxonFk);\r
+//                     e.printStackTrace();\r
                        return false;\r
                }\r
        }\r