commit 67426b792b4a488ac82ded0e5c4f398559cfd813
Author: Andreas Müller <a.mueller@bgbm.org>
Date:   Tue Oct 8 23:28:27 2019 +0200

    ref #2717 adapt PesiExport to EuroMed requirements and adapt PesiExportActivatorEM

diff --git a/cdm-pesi/src/main/java/eu/etaxonomy/cdm/app/pesi/PesiDestinations.java b/cdm-pesi/src/main/java/eu/etaxonomy/cdm/app/pesi/PesiDestinations.java
index 6c8d7657..c5107fb3 100644
--- a/cdm-pesi/src/main/java/eu/etaxonomy/cdm/app/pesi/PesiDestinations.java
+++ b/cdm-pesi/src/main/java/eu/etaxonomy/cdm/app/pesi/PesiDestinations.java
@@ -23,19 +23,19 @@ public class PesiDestinations {
 
 	public static Source pesi_test_local_CDM_EM2PESI(){
 		String dbms = Source.SQL_SERVER_2008;
-		String strServer = "localhost";
+		String strServer = "pesiimport3";
 		String strDB = "CDM_EM2PESI";
 		int port = 1433;
-		String userName =  "pesiexport";// "pesiexport3";
+		String userName =  "pesi2019";// "pesiexport3";
 		return makeSource(dbms, strServer, strDB, port, userName, null);
 	}
 
-	public static Source pesi_test_local_CDM_EM2PESI_tmp(){
+	public static Source pesi_test_local_CDM_EM2PESI_2(){
 		String dbms = Source.SQL_SERVER_2008;
-		String strServer = "localhost";
-		String strDB = "CDMTMP_EM2PESI";
+		String strServer = "pesiimport3";
+		String strDB = "CDM_EM2PESI_2";
 		int port = 1433;
-		String userName = "pesiexport";
+		String userName = "pesi2019";
 		return makeSource(dbms, strServer, strDB, port, userName, null);
 	}
 
diff --git a/cdm-pesi/src/main/java/eu/etaxonomy/cdm/app/pesi/PesiExportActivatorEM.java b/cdm-pesi/src/main/java/eu/etaxonomy/cdm/app/pesi/PesiExportActivatorEM.java
index d9ed4ee2..50e3dff0 100644
--- a/cdm-pesi/src/main/java/eu/etaxonomy/cdm/app/pesi/PesiExportActivatorEM.java
+++ b/cdm-pesi/src/main/java/eu/etaxonomy/cdm/app/pesi/PesiExportActivatorEM.java
@@ -19,7 +19,6 @@ import eu.etaxonomy.cdm.io.common.IExportConfigurator.DO_REFERENCES;
 import eu.etaxonomy.cdm.io.common.Source;
 import eu.etaxonomy.cdm.io.pesi.out.PesiExportConfigurator;
 import eu.etaxonomy.cdm.io.pesi.out.PesiTransformer;
-import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
 
 /**
  * @author a.mueller
@@ -30,73 +29,54 @@ public class PesiExportActivatorEM {
 	@SuppressWarnings("unused")
 	private static final Logger logger = Logger.getLogger(PesiExportActivatorEM.class);
 
-	static final ICdmDataSource cdmSource = CdmDestinations.test_cdm_pesi_euroMed();
+//	static final ICdmDataSource cdmSource = CdmDestinations.test_cdm_pesi_euroMed();
+	static final ICdmDataSource cdmSource = CdmDestinations.cdm_test_local_mysql_euromed();
 
 	//database validation status (create, update, validate ...)
 	static final Source pesiDestination = PesiDestinations.pesi_test_local_CDM_EM2PESI();
-//	static final Source pesiDestination = PesiDestinations.pesi_test_local_CDM_FE2PESI();
-//	static final Source pesiDestination = PesiDestinations.pesi_test_local_CDM_ERMS2PESI();
-
-	//Taxon names can't be mapped to their CDM ids as PESI Taxon table mainly holds taxa and there IDs. We ad nameIdStart to the TaxonName id to get a unique id
-	static final int nameIdStart = 10000000;
-	static final IdType idType = IdType.CDM_ID_WITH_EXCEPTIONS;
-
-	static final int partitionSize = 1000;
-
-	//check - export
-	static final CHECK check = CHECK.EXPORT_WITHOUT_CHECK;
-
-	//NomenclaturalCode
-	static final NomenclaturalCode nomenclaturalCode  = NomenclaturalCode.ICNAFP;
-
-	static final boolean deleteAll = true;
-
+//	static final Source pesiDestination = PesiDestinations.pesi_test_local_CDM_EM2PESI_2();
 
 // ****************** ALL *****************************************
 
-	//references
-	static final DO_REFERENCES doReferences =  DO_REFERENCES.ALL;
+	boolean deleteAll = false;
+	DO_REFERENCES doReferences =  DO_REFERENCES.NONE;
+	boolean doTaxa = true;
+	boolean doTaxaPhase1 = true;   //better do not use, Phase1 is needed in Phase3
+	boolean doPureNames = true;
+	boolean doTreeIndex = true;
+	boolean doParentAndBiota = true;
+	boolean doInferredSynonyms = false;   //no inferred synonyms in E+M
+	boolean doRelTaxa = true;
+	boolean doAdditionalTaxonSource = true;
+    boolean doDescriptions = true;
+	boolean doEcologyAndLink = true;
 
-	//taxa
-	static final boolean doTaxa = true;
-	static final boolean doPureNames = true;
-	static final boolean doTreeIndex = true;
-	static final boolean doParentAndBiota = true;
-	static final boolean doRank = true;
-	static final boolean doInferredSynonyms = false;   //no inferred synonyms in E+M
-	static final boolean doRelTaxa = true;
-	static final boolean doDescriptions = true;
+// ************************ NONE **************************************** //
 
-	static final boolean doNotes = true;
-	static final boolean doNoteSources = true;
-	static final boolean doAdditionalTaxonSource = true;
-	static final boolean doOccurrence = true;
-	static final boolean doOccurrenceSource = true;
-	static final boolean doImage = true;
+//    boolean deleteAll = false;
+//    DO_REFERENCES doReferences =  DO_REFERENCES.NONE;
+//    boolean doTaxa = false;
+//    boolean doPureNames = false;
+//    boolean doTreeIndex = false;
+//    boolean doParentAndBiota = false;
+//    boolean doInferredSynonyms = false;   //no inferred synonyms in E+M
+//    boolean doRelTaxa = false;
+//    boolean doAdditionalTaxonSource = false;
+//    boolean doDescriptions = false;
+//    boolean doEcologyAndLink = false;
 
 
-// ************************ NONE **************************************** //
+    //check - export
+    static final CHECK check = CHECK.EXPORT_WITHOUT_CHECK;
 
-//	//references
-//	static final DO_REFERENCES doReferences =  DO_REFERENCES.NONE;
-//
-//	//taxa
-//	static final boolean doTaxa = false;
-//	static final boolean doPureNames = false;
-//	static final boolean doRelTaxa = false;
-//	static final boolean doNotes = false;
-//	static final boolean doNoteSources = false;
-//	static final boolean doAdditionalTaxonSource = false;
-//	static final boolean doOccurrence = false;
-//	static final boolean doOccurrenceSource = false;
-//	static final boolean doImage = false;
-//	static final boolean doTreeIndex = false;
-//	static final boolean doRank = true;
-//	static final boolean doInferredSynonyms = true;
+    //Taxon names can't be mapped to their CDM ids as PESI Taxon table mainly holds taxa and there IDs. We ad nameIdStart to the TaxonName id to get a unique id
+    static final int nameIdStart = 10000000;
+    static final IdType idType = IdType.CDM_ID_WITH_EXCEPTIONS;
 
+    static final int partitionSize = 1000;
 
 	public boolean 	doExport(ICdmDataSource source){
-		System.out.println("Start export to PESI ("+ pesiDestination.getDatabase() + ") ...");
+	    System.out.println("Start export from " + source.getDatabase() + " to PESI ("+ pesiDestination.getDatabase() + ") ...");
 
 		//make PESI Source
 		Source destination = pesiDestination;
@@ -106,17 +86,15 @@ public class PesiExportActivatorEM {
 
 		config.setDoTaxa(doTaxa);
 		config.setDoPureNames(doPureNames);
+		config.setDoTaxaPhase1(doTaxaPhase1);
 		config.setDoRelTaxa(doRelTaxa);
-		config.setDoOccurrence(doOccurrence);
 		config.setDoReferences(doReferences);
-		config.setDoImages(doImage);
-		config.setDoNotes(doNotes);
-		config.setDoNoteSources(doNoteSources);
-		config.setDoOccurrenceSource(doOccurrenceSource);
 		config.setDoTreeIndex(doTreeIndex);
-		config.setDoTreeIndex(doParentAndBiota);
+		config.setDoParentAndBiota(doParentAndBiota);
 		config.setDoInferredSynonyms(doInferredSynonyms);
 		config.setDoDescription(doDescriptions);
+		config.setDoAdditionalTaxonSource(doAdditionalTaxonSource);
+		config.setDoEcologyAndLink(doEcologyAndLink);
 
 		config.setCheck(check);
 		config.setLimitSave(partitionSize);
diff --git a/cdm-pesi/src/main/java/eu/etaxonomy/cdm/io/pesi/out/PesiExportBase.java b/cdm-pesi/src/main/java/eu/etaxonomy/cdm/io/pesi/out/PesiExportBase.java
index 2890a050..f191eb2a 100644
--- a/cdm-pesi/src/main/java/eu/etaxonomy/cdm/io/pesi/out/PesiExportBase.java
+++ b/cdm-pesi/src/main/java/eu/etaxonomy/cdm/io/pesi/out/PesiExportBase.java
@@ -643,7 +643,7 @@ public abstract class PesiExportBase
     }
 
     // return all sources with a PESI reference
-    private static Set<IdentifiableSource> filterPesiSources(Set<? extends IdentifiableSource> sources) {
+    protected static Set<IdentifiableSource> filterPesiSources(Set<? extends IdentifiableSource> sources) {
         Set<IdentifiableSource> result = new HashSet<>();
         for (IdentifiableSource source : sources){
             Reference ref = source.getCitation();
diff --git a/cdm-pesi/src/main/java/eu/etaxonomy/cdm/io/pesi/out/PesiExportConfigurator.java b/cdm-pesi/src/main/java/eu/etaxonomy/cdm/io/pesi/out/PesiExportConfigurator.java
index 992b3a33..b0f239b4 100644
--- a/cdm-pesi/src/main/java/eu/etaxonomy/cdm/io/pesi/out/PesiExportConfigurator.java
+++ b/cdm-pesi/src/main/java/eu/etaxonomy/cdm/io/pesi/out/PesiExportConfigurator.java
@@ -45,6 +45,7 @@ public class PesiExportConfigurator
 	private boolean doParentAndBiota = true;
 	private boolean doInferredSynonyms = true;
 	private boolean doPureNames = true;
+	private boolean doTaxaPhase1 = true;
 	private boolean doDescription = true;
 	private boolean doEcologyAndLink = true;
 
@@ -197,7 +198,14 @@ public class PesiExportConfigurator
 		this.doPureNames = doPureNames;
 	}
 
-	public boolean isDoDescription() {
+	public boolean isDoTaxaPhase1() {
+        return doTaxaPhase1;
+    }
+    public void setDoTaxaPhase1(boolean doTaxaPhase1) {
+        this.doTaxaPhase1 = doTaxaPhase1;
+    }
+
+    public boolean isDoDescription() {
 		return doDescription;
 	}
 	public void setDoDescription(boolean doDescription) {
diff --git a/cdm-pesi/src/main/java/eu/etaxonomy/cdm/io/pesi/out/PesiSourceExport.java b/cdm-pesi/src/main/java/eu/etaxonomy/cdm/io/pesi/out/PesiSourceExport.java
index cfd0e6ed..132ad197 100644
--- a/cdm-pesi/src/main/java/eu/etaxonomy/cdm/io/pesi/out/PesiSourceExport.java
+++ b/cdm-pesi/src/main/java/eu/etaxonomy/cdm/io/pesi/out/PesiSourceExport.java
@@ -11,7 +11,6 @@ package eu.etaxonomy.cdm.io.pesi.out;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.EnumSet;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
@@ -35,7 +34,6 @@ import eu.etaxonomy.cdm.model.common.Extension;
 import eu.etaxonomy.cdm.model.common.ExtensionType;
 import eu.etaxonomy.cdm.model.common.IdentifiableSource;
 import eu.etaxonomy.cdm.model.reference.Reference;
-import eu.etaxonomy.cdm.model.reference.ReferenceType;
 
 /**
  * The export class for {@link eu.etaxonomy.cdm.model.reference.Reference References}.<p>
@@ -299,24 +297,24 @@ public class PesiSourceExport extends PesiExportBase {
 		String result = null;
 
 		try {
-		if (reference != null) {
-			Set<IdentifiableSource> sourceAll = reference.getSources();
-			Set<IdentifiableSource> sourceCandidates = filterOriginalPesiDbSources(sourceAll);
-
-			if (sourceCandidates.size() == 1) {
-				result = sourceCandidates.iterator().next().getIdInSource();
-			} else if (sourceCandidates.size() > 1) {
-				logger.warn("Reference for RefIdInSource has multiple IdentifiableSources which are candidates for a PESI originalDbSource. RefIdInSource can't be determined correctly and will be left out: " + reference.getUuid() + " (" + reference.getTitleCache() + ")");
-				int count = 1;
-//				for (IdentifiableSource source : sources) {
-//					result += source.getIdInSource();
-//					if (count < sources.size()) {
-//						result += "; ";
-//					}
-//					count++;
-//				}
-			}
-		}
+    		if (reference != null) {
+    			Set<IdentifiableSource> sourceAll = reference.getSources();
+    			Set<IdentifiableSource> sourceCandidates = filterPesiSources(sourceAll);
+
+    			if (sourceCandidates.size() == 1) {
+    				result = sourceCandidates.iterator().next().getIdInSource();
+    			} else if (sourceCandidates.size() > 1) {
+    				logger.warn("Reference for RefIdInSource has multiple IdentifiableSources which are candidates for a PESI originalDbSource. RefIdInSource can't be determined correctly and will be left out: " + reference.getUuid() + " (" + reference.getTitleCache() + ")");
+    				int count = 1;
+    //				for (IdentifiableSource source : sources) {
+    //					result += source.getIdInSource();
+    //					if (count < sources.size()) {
+    //						result += "; ";
+    //					}
+    //					count++;
+    //				}
+    			}
+    		}
 		} catch (Exception e) {
 			e.printStackTrace();
 		}
@@ -324,21 +322,21 @@ public class PesiSourceExport extends PesiExportBase {
 		return result;
 	}
 
-	private static Set<IdentifiableSource> filterOriginalPesiDbSources(
-			Set<IdentifiableSource> sourceAll) {
-		Set<IdentifiableSource> sourceCandidates = new HashSet<>();
-		for (IdentifiableSource source : sourceAll){
-			if (isOriginalPesiDbSource(source)){
-				sourceCandidates.add(source);
-			}
-		}
-		return sourceCandidates;
-	}
-
-	private static boolean isOriginalPesiDbSource(IdentifiableSource source) {
-		return (source.getCitation() != null) &&
-				source.getCitation().getType().equals(ReferenceType.Database);
-	}
+//	private static Set<IdentifiableSource> filterOriginalPesiDbSources(
+//			Set<IdentifiableSource> sourceAll) {
+//		Set<IdentifiableSource> sourceCandidates = new HashSet<>();
+//		for (IdentifiableSource source : sourceAll){
+//			if (isOriginalPesiDbSource(source)){
+//				sourceCandidates.add(source);
+//			}
+//		}
+//		return sourceCandidates;
+//	}
+//
+//	private static boolean isOriginalPesiDbSource(IdentifiableSource source) {
+//		return (source.getCitation() != null) &&
+//				source.getCitation().getType().equals(ReferenceType.Database);
+//	}
 
 	/**
 	 * Returns the <code>OriginalDB</code> attribute.
diff --git a/cdm-pesi/src/main/java/eu/etaxonomy/cdm/io/pesi/out/PesiTaxonExport.java b/cdm-pesi/src/main/java/eu/etaxonomy/cdm/io/pesi/out/PesiTaxonExport.java
index 387782cc..7bfba815 100644
--- a/cdm-pesi/src/main/java/eu/etaxonomy/cdm/io/pesi/out/PesiTaxonExport.java
+++ b/cdm-pesi/src/main/java/eu/etaxonomy/cdm/io/pesi/out/PesiTaxonExport.java
@@ -34,7 +34,6 @@ import org.springframework.transaction.TransactionStatus;
 
 import eu.etaxonomy.cdm.api.service.TaxonServiceImpl;
 import eu.etaxonomy.cdm.common.CdmUtils;
-import eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer;
 import eu.etaxonomy.cdm.io.common.Source;
 import eu.etaxonomy.cdm.io.common.mapping.UndefinedTransformerMethodException;
 import eu.etaxonomy.cdm.io.common.mapping.out.DbConstantMapper;
@@ -104,30 +103,24 @@ public class PesiTaxonExport extends PesiExportBase {
 
 	private static final String pluralString = "Taxa";
 	private static final String parentPluralString = "Taxa";
+	private static final String pluralStringNames = "Names";
 
 	private PreparedStatement parentTaxonFk_TreeIndex_KingdomFkStmt;
 	private PreparedStatement parentTaxonFkStmt;
 	private PreparedStatement rankTypeExpertsUpdateStmt;
 	private PreparedStatement rankUpdateStmt;
 	private Integer kingdomFk;
-	private AnnotationType treeIndexAnnotationType;
+
 	private static ExtensionType lastActionExtensionType;
 	private static ExtensionType lastActionDateExtensionType;
 	private static ExtensionType expertNameExtensionType;
 	private static ExtensionType speciesExpertNameExtensionType;
 	private static ExtensionType cacheCitationExtensionType;
+
 	public static TaxonNameDefaultCacheStrategy zooNameStrategy = ZooNameNoMarkerCacheStrategy.NewInstance();
 	public static TaxonNameDefaultCacheStrategy nonViralNameStrategy = TaxonNameDefaultCacheStrategy.NewInstance();
 	private static int currentTaxonId;
 
-	protected AnnotationType getTreeIndexAnnotationType() {
-		return treeIndexAnnotationType;
-	}
-
-	protected void setTreeIndexAnnotationType(AnnotationType treeIndexAnnotationType) {
-		this.treeIndexAnnotationType = treeIndexAnnotationType;
-	}
-
 	enum NamePosition {
 		beginning,
 		end,
@@ -247,7 +240,10 @@ public class PesiTaxonExport extends PesiExportBase {
 	}
 
 	private boolean doPhase01(PesiExportState state, PesiExportMapping mapping, PesiExportMapping additionalSourceMapping){
-		int count = 0;
+		if (!state.getConfig().isDoTaxaPhase1()){
+		    return true;
+		}
+	    int count = 0;
 		int pastCount = 0;
 		boolean success = true;
 		// Get the limit for objects to save within a single transaction.
@@ -294,6 +290,10 @@ public class PesiTaxonExport extends PesiExportBase {
     				    }else{
     				        logger.warn("Kingdom taxon is not of class Taxon but " + taxon.getClass().getSimpleName() + ": " + nvn.getGenusOrUninomial());
     				    }
+    				}else if (taxon.getUuid().equals(PesiTransformer.uuidTaxonValuelessEuroMed)){
+    				    String treeIndex = ((Taxon)taxon).getTaxonNodes().iterator().next().treeIndex();
+                        Integer kingdomId = PesiTransformer.pesiKingdomMap.get("Plantae");
+                        state.getTreeIndexKingdomMap().put(treeIndex, kingdomId);
     				}
 				}catch(NullPointerException e){
 				    logger.error(nvn.getTitleCache() + " has no Rank!");
@@ -425,7 +425,7 @@ public class PesiTaxonExport extends PesiExportBase {
 				for (TaxonNode node : taxon.getTaxonNodes()){
 					doCount(count++, modCount, pluralString);
 					TaxonNode parentNode = node.getParent();
-					if (parentNode != null && parentNode.getTaxon() != null){  //new root node handling requires has root taxon with taxon == null
+					if (parentNode != null && isPesiTaxon(parentNode.getTaxon())){//exclude root taxa and unpublished parents (relevant for "Valueless" parent for E+M Rubus taxa). Usually a parent should not be unpublished
 						int childId = state.getDbId( taxon);
 						int parentId = state.getDbId(parentNode.getTaxon());
 						success &= invokeParentTaxonFk(parentId, childId);
@@ -555,7 +555,7 @@ public class PesiTaxonExport extends PesiExportBase {
         return success;
     }
 
-    private static Integer findKingdomIdFromTreeIndex(TaxonBase<?> taxonBase,PesiExportState state) {
+    private static Integer findKingdomIdFromTreeIndex(TaxonBase<?> taxonBase, PesiExportState state) {
         Taxon taxon;
         if (taxonBase instanceof Synonym){
             taxon = ((Synonym) taxonBase).getAcceptedTaxon();
@@ -584,7 +584,8 @@ public class PesiTaxonExport extends PesiExportBase {
                 if(matcher.find()) {
                     String treeIndexKingdom = matcher.group(0);
                     kingdomID = state.getTreeIndexKingdomMap().get(treeIndexKingdom);
-                }else{
+                }
+                if (kingdomID == null){
                     pattern = Pattern.compile("#t[0-9]+#([0-9]+#){2}");
                     matcher = pattern.matcher(treeIndex);
                     if(matcher.find()) {
@@ -901,7 +902,7 @@ public class PesiTaxonExport extends PesiExportBase {
 			List<TaxonName> list;
 			while ((list = getNextPureNamePartition(null, limit, partitionCount++)) != null   ) {
 
-				logger.info("Fetched " + list.size() + " names without taxa. Exporting...");
+				logger.debug("Fetched " + list.size() + pluralStringNames + " without taxa. Exporting...");
 				for (TaxonName taxonName : list) {
 					doCount(count++, modCount, pluralString);
 					success &= mapping.invoke(taxonName);
@@ -914,14 +915,14 @@ public class PesiTaxonExport extends PesiExportBase {
 				// Commit transaction
 				commitTransaction(txStatus);
 				logger.debug("Committed transaction.");
-				logger.info("Exported " + (count - pastCount) + " " + pluralString + ". Total: " + count);
+				logger.info("Exported " + (count - pastCount) + " " + pluralStringNames + ". Total: " + count + ". Partition: " + partitionCount);
 				pastCount = count;
 
 				// Start transaction
 				txStatus = startTransaction(true);
-				logger.info("Started new transaction for PureNames. Fetching some " + pluralString + " (max: " + limit + ") ...");
+				logger.debug("Started new transaction for PureNames. Fetching some " + pluralString + " (max: " + limit + ") ...");
 			}
-			logger.info("No " + pluralString + " left to fetch.");
+			logger.debug("No " + pluralString + " left to fetch.");
 
 			// Commit transaction
 			commitTransaction(txStatus);
@@ -1172,16 +1173,18 @@ public class PesiTaxonExport extends PesiExportBase {
 	 * @return Whether the delete operation was successful or not.
 	 */
 	protected boolean doDelete(PesiExportState state) {
-		PesiExportConfigurator pesiConfig = state.getConfig();
-
-		String sql;
-		Source destination =  pesiConfig.getDestination();
+	    if (!state.getConfig().isDoTaxaPhase1()){
+	        return true;
+	    }
+		Source destination =  state.getConfig().getDestination();
 
-		// Clear Taxon
-		sql = "DELETE FROM " + dbTableName;
-		destination.update(sql);
+		String[] tables = new String[]{"AdditionalTaxonSource","CommonNameSource","CommonName",
+		        "Image","NoteSource","Note","OccurrenceSource","Occurrence","RelTaxon","Taxon"};
 
-		//TODO due to foreign keys we should also delete all tables linking to Taxon table
+		for(String table : tables){
+		    String sql = "DELETE FROM " + table;
+		    destination.update(sql);
+		}
 
 		return true;
 	}
@@ -1217,21 +1220,18 @@ public class PesiTaxonExport extends PesiExportBase {
 		return result;
 	}
 
-	private static String getRankCache(TaxonName taxonName, PesiExportState state) {
+	@SuppressWarnings("unused")
+    private static String getRankCache(TaxonName taxonName, PesiExportState state) {
 	    List<TaxonNode> nodes = getTaxonNodes(taxonName);
-        Integer kingdomId = findKingdomIdFromTreeIndex(nodes.iterator().next().getTaxon(), state);
+	    Integer kingdomId;
+	    if (nodes == null||nodes.isEmpty()){
+	        kingdomId = getKingdomFk(taxonName);
+	    }else{
+	        kingdomId = findKingdomIdFromTreeIndex(nodes.iterator().next().getTaxon(), state);
+	    }
         return getRankCache(taxonName, kingdomId, state);
 	}
 
-
-	/**
-	 * Returns the <code>RankCache</code> attribute.
-	 * @param taxonName The {@link TaxonNameBase TaxonName}.
-	 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
-	 * @param state
-	 * @return The <code>RankCache</code> attribute.
-	 * @see MethodMapper
-	 */
 	private static String getRankCache(TaxonName taxonName, Integer kingdomFk, PesiExportState state) {
 	    if (Rank.DOMAIN().equals(taxonName.getRank())){
             return state.getTransformer().getCacheByRankAndKingdom(Rank.DOMAIN(), null);
@@ -1255,7 +1255,7 @@ public class PesiTaxonExport extends PesiExportBase {
             }else{
                 taxon = CdmBase.deproxy(tb, Synonym.class).getAcceptedTaxon();
             }
-            if (taxon != null){
+            if (isPesiTaxon(taxon)){
                 for (TaxonNode node : taxon.getTaxonNodes()){
                     result.add(node);
                 }
@@ -1264,6 +1264,34 @@ public class PesiTaxonExport extends PesiExportBase {
         return result;
     }
 
+//    @SuppressWarnings("unused")  //used by pure name mapper and by getRankFk
+    private static Integer getKingdomFk(TaxonName taxonName){
+        EnumSet<PesiSource> origin = getSources(taxonName);
+        if (origin.size() == 1 && origin.contains(PesiSource.EM)){
+            //maybe simply replace by
+            //return PesiTransformer.KINGDOM_PLANTAE;
+            return PesiTransformer.nomenclaturalCode2Kingdom(taxonName.getNameType());
+        }else{
+            logger.warn("getKingdomFk not yet implemented for non-EuroMed pure names");
+            return null;
+        }
+    }
+
+    /**
+     * Returns the rankFk for the taxon name based on the names nomenclatural code.
+     * You may not use this method for kingdoms other then Animalia, Plantae and Bacteria.
+     */
+    @SuppressWarnings("unused")  //used by pure name mapper
+    private static Integer getRankFk(TaxonName taxonName) {
+        EnumSet<PesiSource> origin = getSources(taxonName);
+        if (origin.size() == 1 && origin.contains(PesiSource.EM)){
+            return getRankFk(taxonName, getKingdomFk(taxonName));
+        }else{
+            logger.warn("getRankFk not yet implemented for non-EuroMed pure names");
+            return null;
+        }
+    }
+
     /**
 	 * Returns the <code>DisplayName</code> attribute.
 	 * @param taxon The {@link TaxonBase Taxon}.
@@ -1470,8 +1498,7 @@ public class PesiTaxonExport extends PesiExportBase {
 	/**
 	 * Returns the nomenclatural reference which is the reference
 	 * including the detail (microreference).
-	 * @param taxonName The {@link TaxonNameBase TaxonName}.
-	 * @return The <code>AuthorString</code> attribute.
+	 * @param taxonName The {@link TaxonName taxon name}.
 	 * @see MethodMapper
 	 */
 	@SuppressWarnings("unused")
@@ -1690,22 +1717,21 @@ public class PesiTaxonExport extends PesiExportBase {
 	 * @return The <code>TypeDesignationStatusFk</code> attribute.
 	 * @see MethodMapper
 	 */
-	@SuppressWarnings("unused")
+	//TODO seems not to be used
 	private static Integer getTypeDesignationStatusFk(TaxonName taxonName) {
 		Integer result = null;
 
 		try {
-		if (taxonName != null) {
-			Set<NameTypeDesignation> typeDesignations = taxonName.getNameTypeDesignations();
-			if (typeDesignations.size() == 1) {
-				Object obj = typeDesignations.iterator().next().getTypeStatus();
-				NameTypeDesignationStatus designationStatus = CdmBase.deproxy(obj, NameTypeDesignationStatus.class);
-				result = PesiTransformer.nameTypeDesignationStatus2TypeDesignationStatusId(designationStatus);
-			} else if (typeDesignations.size() > 1) {
-				logger.error("Found a TaxonName with more than one NameTypeDesignation: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
-			}
-		}
-
+    		if (taxonName != null) {
+    			Set<NameTypeDesignation> typeDesignations = taxonName.getNameTypeDesignations();
+    			if (typeDesignations.size() == 1) {
+    				Object obj = typeDesignations.iterator().next().getTypeStatus();
+    				NameTypeDesignationStatus designationStatus = CdmBase.deproxy(obj, NameTypeDesignationStatus.class);
+    				result = PesiTransformer.nameTypeDesignationStatus2TypeDesignationStatusId(designationStatus);
+    			} else if (typeDesignations.size() > 1) {
+    				logger.error("Found a TaxonName with more than one NameTypeDesignation: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
+    			}
+    		}
 		} catch (Exception e) {
 			e.printStackTrace();
 		}
@@ -1718,22 +1744,21 @@ public class PesiTaxonExport extends PesiExportBase {
 	 * @return The <code>TypeDesignationStatusCache</code> attribute.
 	 * @see MethodMapper
 	 */
-	@SuppressWarnings("unused")
+	//TODO seems not to be used
 	private static String getTypeDesignationStatusCache(TaxonName taxonName) {
 		String result = null;
 
 		try {
-		if (taxonName != null) {
-			Set<NameTypeDesignation> typeDesignations = taxonName.getNameTypeDesignations();
-			if (typeDesignations.size() == 1) {
-				Object obj = typeDesignations.iterator().next().getTypeStatus();
-				NameTypeDesignationStatus designationStatus = CdmBase.deproxy(obj, NameTypeDesignationStatus.class);
-				result = PesiTransformer.nameTypeDesignationStatus2TypeDesignationStatusCache(designationStatus);
-			} else if (typeDesignations.size() > 1) {
-				logger.error("Found a TaxonName with more than one NameTypeDesignation: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
-			}
-		}
-
+    		if (taxonName != null) {
+    			Set<NameTypeDesignation> typeDesignations = taxonName.getNameTypeDesignations();
+    			if (typeDesignations.size() == 1) {
+    				Object obj = typeDesignations.iterator().next().getTypeStatus();
+    				NameTypeDesignationStatus designationStatus = CdmBase.deproxy(obj, NameTypeDesignationStatus.class);
+    				result = PesiTransformer.nameTypeDesignationStatus2TypeDesignationStatusCache(designationStatus);
+    			} else if (typeDesignations.size() > 1) {
+    				logger.error("Found a TaxonName with more than one NameTypeDesignation: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
+    			}
+    		}
 		} catch (Exception e) {
 			e.printStackTrace();
 		}
@@ -1803,7 +1828,7 @@ public class PesiTaxonExport extends PesiExportBase {
 				Reference ref = source.getCitation();
 				UUID refUuid = ref.getUuid();
 				String idInSource = source.getIdInSource();
-				if (refUuid.equals(BerlinModelTransformer.uuidSourceRefEuroMed)){
+				if (refUuid.equals(PesiTransformer.uuidSourceRefEuroMed)){
 					result = idInSource != null ? ("NameId: " + source.getIdInSource()) : null;
 				}else if (refUuid.equals(PesiTransformer.uuidSourceRefFaunaEuropaea)){
 					result = idInSource != null ? ("TAX_ID: " + source.getIdInSource()) : null;
@@ -1993,16 +2018,16 @@ public class PesiTaxonExport extends PesiExportBase {
 	 * @return The <code>LastAction</code> attribute.
 	 * @see MethodMapper
 	 */
-	@SuppressWarnings("unused")
+	//TODO still in use?
 	private static String getLastAction(IdentifiableEntity<?> identEntity) {
 		String result = null;
 		try {
-		Set<Extension> extensions = identEntity.getExtensions();
-		for (Extension extension : extensions) {
-			if (extension.getType().equals(lastActionExtensionType)) {
-				result = extension.getValue();
-			}
-		}
+    		Set<Extension> extensions = identEntity.getExtensions();
+    		for (Extension extension : extensions) {
+    			if (extension.getType().equals(lastActionExtensionType)) {
+    				result = extension.getValue();
+    			}
+    		}
 		} catch (Exception e) {
 			e.printStackTrace();
 		}
@@ -2015,7 +2040,7 @@ public class PesiTaxonExport extends PesiExportBase {
 	 * @return The <code>LastActionDate</code> attribute.
 	 * @see MethodMapper
 	 */
-	@SuppressWarnings({ "unused" })
+	//TODO still in use?
 	private static DateTime getLastActionDate(IdentifiableEntity<?> identEntity) {
 		DateTime result = null;
 		try {
@@ -2041,16 +2066,18 @@ public class PesiTaxonExport extends PesiExportBase {
 	 * @return The <code>ExpertName</code> attribute.
 	 * @see MethodMapper
 	 */
-	@SuppressWarnings("unused")
+	@SuppressWarnings("unused")  //for some reason it is also called by getCacheCitation
 	private static String getExpertName(TaxonBase<?> taxonName) {
-		String result = null;
+	    String result = null;
 		try {
-		Set<Extension> extensions = taxonName.getExtensions();
-		for (Extension extension : extensions) {
-			if (extension.getType().equals(expertNameExtensionType)) {
-				result = extension.getValue();
-			}
-		}
+    		if(expertNameExtensionType!=null){  //some databases do not have this extension type
+    		    Set<Extension> extensions = taxonName.getExtensions();
+    		    for (Extension extension : extensions) {
+    		        if (extension.getType().equals(expertNameExtensionType)) {
+    		            result = extension.getValue();
+    		        }
+    		    }
+    		}
 		} catch (Exception e) {
 			e.printStackTrace();
 		}
@@ -2075,16 +2102,16 @@ public class PesiTaxonExport extends PesiExportBase {
 	 * @return The <code>SpeciesExpertName</code> attribute.
 	 * @see MethodMapper
 	 */
-	@SuppressWarnings("unused")
+	//TODO still in use?
 	private static String getSpeciesExpertName(TaxonBase<?> taxonName) {
 		String result = null;
 		try {
-		Set<Extension> extensions = taxonName.getExtensions();
-		for (Extension extension : extensions) {
-			if (extension.getType().equals(speciesExpertNameExtensionType)) {
-				result = extension.getValue();
-			}
-		}
+    		Set<Extension> extensions = taxonName.getExtensions();
+    		for (Extension extension : extensions) {
+    			if (extension.getType().equals(speciesExpertNameExtensionType)) {
+    				result = extension.getValue();
+    			}
+    		}
 		} catch (Exception e) {
 			e.printStackTrace();
 		}
@@ -2132,7 +2159,7 @@ public class PesiTaxonExport extends PesiExportBase {
 		return PesiTransformer.taxonRelation2RelTaxonQualifierFk(relationship);
 	}
 
-    @SuppressWarnings("unused")
+    //TODO still in use?
     private static String getSynonymTypeCache(Synonym synonym, PesiExportState state) {
         String result = null;
         NomenclaturalCode code = null;
@@ -2208,8 +2235,8 @@ public class PesiTaxonExport extends PesiExportBase {
 		mapping.addMapper(MethodMapper.NewInstance("KingdomFk", this, TaxonName.class));
 		mapping.addMapper(MethodMapper.NewInstance("RankFk", this, TaxonName.class));
 		mapping.addMapper(MethodMapper.NewInstance("RankCache", this, TaxonName.class, PesiExportState.class));
-		mapping.addMapper(DbConstantMapper.NewInstance("TaxonStatusFk", Types.INTEGER , PesiTransformer.T_STATUS_UNACCEPTED));
-		mapping.addMapper(DbConstantMapper.NewInstance("TaxonStatusCache", Types.VARCHAR , state.getTransformer().getTaxonStatusCacheByKey( PesiTransformer.T_STATUS_UNACCEPTED)));
+		mapping.addMapper(DbConstantMapper.NewInstance("TaxonStatusFk", Types.INTEGER, PesiTransformer.T_STATUS_UNACCEPTED));
+		mapping.addMapper(DbConstantMapper.NewInstance("TaxonStatusCache", Types.VARCHAR, state.getTransformer().getTaxonStatusCacheByKey( PesiTransformer.T_STATUS_UNACCEPTED)));
 		mapping.addMapper(DbStringMapper.NewInstance("AuthorshipCache", "AuthorString").setBlankToNull(true));
 		mapping.addMapper(MethodMapper.NewInstance("WebShowName", this, TaxonName.class));
 		mapping.addMapper(MethodMapper.NewInstance("GUID", this, TaxonName.class));
diff --git a/cdm-pesi/src/main/java/eu/etaxonomy/cdm/io/pesi/out/PesiTransformer.java b/cdm-pesi/src/main/java/eu/etaxonomy/cdm/io/pesi/out/PesiTransformer.java
index e05b83b6..1c907ef4 100644
--- a/cdm-pesi/src/main/java/eu/etaxonomy/cdm/io/pesi/out/PesiTransformer.java
+++ b/cdm-pesi/src/main/java/eu/etaxonomy/cdm/io/pesi/out/PesiTransformer.java
@@ -74,6 +74,8 @@ public final class PesiTransformer extends ExportTransformerBase{
 	public static final UUID uuidSourceRefIndexFungorum = UUID.fromString("8de25d27-7d40-47f4-af3b-59d64935a843");
 	public static final UUID uuidSourceRefAuct = UUID.fromString("5f79f96c-c100-4cd8-b78e-2b2dacf09a23");
 
+    public static final UUID uuidTaxonValuelessEuroMed = UUID.fromString("f0a9322b-a57e-447b-9a75-a909f2f2a994");
+
 	public static final String SOURCE_STR_EM = "E+M";
 	public static final String SOURCE_STR_FE = "FaEu";
 	public static final String SOURCE_STR_IF = "IF";
