cleanup
[cdmlib.git] / cdmlib-io / src / main / java / eu / etaxonomy / cdm / io / cdmLight / CdmLightClassificationExport.java
index f1dcc4ec4f660c79af247200bb656cd5665c3922..2f19184b9024b03b450a73f7d2fb501ca2c07dd0 100755 (executable)
@@ -13,6 +13,7 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
@@ -24,13 +25,19 @@ import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
-import eu.etaxonomy.cdm.api.service.dto.CondensedDistribution;
+import eu.etaxonomy.cdm.api.service.geo.IDistributionService;
+import eu.etaxonomy.cdm.api.service.name.TypeDesignationSetComparator;
+import eu.etaxonomy.cdm.api.service.name.TypeDesignationSetContainer;
 import eu.etaxonomy.cdm.api.service.name.TypeDesignationSetFormatter;
-import eu.etaxonomy.cdm.api.service.name.TypeDesignationSetManager;
 import eu.etaxonomy.cdm.common.CdmUtils;
 import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
-import eu.etaxonomy.cdm.ext.geo.IEditGeoService;
+import eu.etaxonomy.cdm.compare.name.TypeComparator;
+import eu.etaxonomy.cdm.compare.taxon.HomotypicGroupTaxonComparator;
 import eu.etaxonomy.cdm.filter.TaxonNodeFilter;
+import eu.etaxonomy.cdm.format.description.CategoricalDataFormatter;
+import eu.etaxonomy.cdm.format.description.QuantitativeDataFormatter;
+import eu.etaxonomy.cdm.format.description.distribution.CondensedDistribution;
+import eu.etaxonomy.cdm.format.reference.OriginalSourceFormatter;
 import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
 import eu.etaxonomy.cdm.io.common.CdmExportBase;
 import eu.etaxonomy.cdm.io.common.ExportResult.ExportResultState;
@@ -51,6 +58,7 @@ import eu.etaxonomy.cdm.model.common.IdentifiableSource;
 import eu.etaxonomy.cdm.model.common.Identifier;
 import eu.etaxonomy.cdm.model.common.Language;
 import eu.etaxonomy.cdm.model.common.LanguageString;
+import eu.etaxonomy.cdm.model.description.CategoricalData;
 import eu.etaxonomy.cdm.model.description.CommonTaxonName;
 import eu.etaxonomy.cdm.model.description.DescriptionBase;
 import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
@@ -58,6 +66,7 @@ import eu.etaxonomy.cdm.model.description.DescriptionElementSource;
 import eu.etaxonomy.cdm.model.description.Distribution;
 import eu.etaxonomy.cdm.model.description.Feature;
 import eu.etaxonomy.cdm.model.description.IndividualsAssociation;
+import eu.etaxonomy.cdm.model.description.QuantitativeData;
 import eu.etaxonomy.cdm.model.description.TaxonDescription;
 import eu.etaxonomy.cdm.model.description.TaxonInteraction;
 import eu.etaxonomy.cdm.model.description.TaxonNameDescription;
@@ -68,22 +77,22 @@ import eu.etaxonomy.cdm.model.media.Media;
 import eu.etaxonomy.cdm.model.media.MediaRepresentation;
 import eu.etaxonomy.cdm.model.media.MediaRepresentationPart;
 import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
-import eu.etaxonomy.cdm.model.name.HomotypicalGroupNameComparator;
 import eu.etaxonomy.cdm.model.name.NameRelationship;
 import eu.etaxonomy.cdm.model.name.NameRelationshipType;
 import eu.etaxonomy.cdm.model.name.NameTypeDesignation;
+import eu.etaxonomy.cdm.model.name.NomenclaturalSource;
 import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
 import eu.etaxonomy.cdm.model.name.Rank;
 import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;
 import eu.etaxonomy.cdm.model.name.TaxonName;
 import eu.etaxonomy.cdm.model.name.TextualTypeDesignation;
-import eu.etaxonomy.cdm.model.name.TypeComparator;
 import eu.etaxonomy.cdm.model.name.TypeDesignationBase;
 import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
 import eu.etaxonomy.cdm.model.occurrence.FieldUnit;
 import eu.etaxonomy.cdm.model.occurrence.GatheringEvent;
 import eu.etaxonomy.cdm.model.occurrence.MediaSpecimen;
 import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
+import eu.etaxonomy.cdm.model.reference.NamedSource;
 import eu.etaxonomy.cdm.model.reference.OriginalSourceType;
 import eu.etaxonomy.cdm.model.reference.Reference;
 import eu.etaxonomy.cdm.model.reference.ReferenceType;
@@ -93,15 +102,18 @@ import eu.etaxonomy.cdm.model.taxon.Taxon;
 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
 import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
-import eu.etaxonomy.cdm.model.term.DefinedTerm;
+import eu.etaxonomy.cdm.model.term.IdentifierType;
+import eu.etaxonomy.cdm.model.term.TermTree;
 import eu.etaxonomy.cdm.persistence.dto.TaxonNodeDto;
 import eu.etaxonomy.cdm.persistence.dto.TaxonNodeDtoByRankAndNameComparator;
+import eu.etaxonomy.cdm.strategy.cache.HTMLTagRules;
 import eu.etaxonomy.cdm.strategy.cache.TagEnum;
 import eu.etaxonomy.cdm.strategy.cache.TaggedText;
-import eu.etaxonomy.cdm.strategy.cache.reference.DefaultReferenceCacheStrategy;
 import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
 
 /**
+ * The export exporting a classification or a taxonomic subtree into CDM light.
+ *
  * @author k.luther
  * @since 15.03.2017
  */
@@ -110,18 +122,11 @@ public class CdmLightClassificationExport
         extends CdmExportBase<CdmLightExportConfigurator, CdmLightExportState, IExportTransformer, File>{
 
     private static final long serialVersionUID = 2518643632756927053L;
-    private static final String STD_TEAM_CONCATINATION = ", ";
-    private static final String FINAL_TEAM_CONCATINATION = " & ";
-
-    private static final String IPNI_NAME_IDENTIFIER = "Ipni Name Identifier";
-    private static final String TROPICOS_NAME_IDENTIFIER = "Tropicos Name Identifier";
-    private static final String WFO_NAME_IDENTIFIER = "WFO Name Identifier";
 
     @Autowired
-    IEditGeoService geoService;
+    private IDistributionService distributionService;
 
     public CdmLightClassificationExport() {
-        super();
         this.ioName = this.getClass().getSimpleName();
     }
 
@@ -157,11 +162,11 @@ public class CdmLightClassificationExport
                 handleTaxonNode(state, node);
                 node = partitioner.next();
             }
-            // hole den rootKnoten und von dort aus die Helper Objekte
-            // erzeugen...
+            // get rootNode and create helperObjects
             if (state.getRootId() != null) {
                 List<TaxonNodeDto> childrenOfRoot = state.getNodeChildrenMap().get(state.getRootId());
-                Comparator<TaxonNodeDto> comp = state.getConfig().getComparator();
+
+                Comparator<TaxonNodeDto> comp = state.getConfig().getTaxonNodeComparator();
                 if (comp == null) {
                     comp = new TaxonNodeDtoByRankAndNameComparator();
                 }
@@ -196,10 +201,6 @@ public class CdmLightClassificationExport
 
     private void setOrderIndex(CdmLightExportState state, OrderHelper order) {
 
-        // String sortIndex = StringUtils.isBlank(sort_index)?
-        // String.valueOf(order.getOrderIndex()): sort_index+ "_"
-        // +String.valueOf(order.getOrderIndex());
-
         if (order.getTaxonUuid() != null
                 && state.getProcessor().hasRecord(CdmLightExportTable.TAXON, order.getTaxonUuid().toString())) {
             String[] csvLine = state.getProcessor().getRecord(CdmLightExportTable.TAXON,
@@ -222,7 +223,7 @@ public class CdmLightClassificationExport
         if (children == null) {
             return null;
         }
-        Comparator<TaxonNodeDto> comp = state.getConfig().getComparator();
+        Comparator<TaxonNodeDto> comp = state.getConfig().getTaxonNodeComparator();
         if (comp == null) {
             comp = new TaxonNodeDtoByRankAndNameComparator();
         }
@@ -261,8 +262,8 @@ public class CdmLightClassificationExport
                        }
                     }
                     state.getNodeChildrenMap().put(root.getUuid(), childNodes);
-                    // add root to node map
 
+                    // add root to node map
                 }
                 TaxonNodeDto rootDto = new TaxonNodeDto(root);
                 UUID parentUuid = root.getParent() != null ? root.getParent().getUuid()
@@ -274,14 +275,12 @@ public class CdmLightClassificationExport
                     List<TaxonNodeDto> rootList = new ArrayList<>();
                     rootList.add(rootDto);
                     state.getNodeChildrenMap().put(parentUuid, rootList);
-
                 }
                 if (root.hasTaxon()) {
                     handleTaxon(state, root);
-
                 }
             } catch (Exception e) {
-                state.getResult().addException(e, "An unexpected error occurred when handling classification "
+                state.getResult().addException(e, "An unexpected error occurred when handling taxonNode "
                         + taxonNode.getUuid() + ": " + e.getMessage() + e.getStackTrace());
             }
         }
@@ -289,7 +288,7 @@ public class CdmLightClassificationExport
 
     private void handleTaxon(CdmLightExportState state, TaxonNode taxonNode) {
         try {
-            // Taxon taxon = taxonNode.getTaxon();
+
             if (taxonNode == null) {
                 state.getResult().addError("The taxonNode was null.", "handleTaxon");
                 state.getResult().setState(ExportResultState.INCOMPLETE_WITH_ERROR);
@@ -300,15 +299,18 @@ public class CdmLightClassificationExport
                         "handleTaxon");
                 state.getResult().setState(ExportResultState.INCOMPLETE_WITH_ERROR);
             } else {
-                Taxon taxon = HibernateProxyHelper.deproxy(taxonNode.getTaxon(), Taxon.class);
+                Taxon taxon = CdmBase.deproxy(taxonNode.getTaxon());
 
                 try {
+                    //accepted name
                     TaxonName name = taxon.getName();
-                    handleName(state, name, true);
+                    handleName(state, name, taxon, true);
+
+                    //homotypic group / synonyms
                     HomotypicalGroup homotypicGroup = taxon.getHomotypicGroup();
                     int index = 0;
                     int homotypicGroupIndex = 0;
-                    handleHomotypicalGroup(state, homotypicGroup, homotypicGroupIndex);
+                    handleHomotypicalGroup(state, homotypicGroup, taxon, homotypicGroupIndex);
                     homotypicGroupIndex++;
                     for (Synonym syn : taxon.getSynonymsInGroup(homotypicGroup)) {
                         handleSynonym(state, syn, index);
@@ -316,7 +318,7 @@ public class CdmLightClassificationExport
                     }
                     List<HomotypicalGroup> heterotypicHomotypicGroups = taxon.getHeterotypicSynonymyGroups();
                     for (HomotypicalGroup group: heterotypicHomotypicGroups){
-                        handleHomotypicalGroup(state, group, homotypicGroupIndex);
+                        handleHomotypicalGroup(state, group, taxon, homotypicGroupIndex);
                         for (Synonym syn : taxon.getSynonymsInGroup(group)) {
                             handleSynonym(state, syn, index);
                             index++;
@@ -324,18 +326,20 @@ public class CdmLightClassificationExport
                         homotypicGroupIndex++;
                     }
 
+                    //pro parte synonyms
                     index = 0;
                     for (Taxon tax : taxon.getAllProParteSynonyms()) {
                         handleProPartePartialMisapplied(state, tax, taxon, true, false, index);
                         index++;
                     }
 
-
+                    //misapplications
                     for (Taxon tax : taxon.getAllMisappliedNames()) {
                         handleProPartePartialMisapplied(state, tax, taxon, false, true, index);
                         index++;
                     }
 
+                    //taxon table
                     CdmLightExportTable table = CdmLightExportTable.TAXON;
                     String[] csvLine = new String[table.getSize()];
 
@@ -343,6 +347,8 @@ public class CdmLightClassificationExport
                     csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, name);
                     Taxon parent = (taxonNode.getParent() == null) ? null : taxonNode.getParent().getTaxon();
                     csvLine[table.getIndex(CdmLightExportTable.PARENT_FK)] = getId(state, parent);
+
+                    //secundum reference
                     csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE_FK)] = getId(state, taxon.getSec());
                     if (taxon.getSec() != null && taxon.getSec().getDatePublished() != null
                             && taxon.getSec().getDatePublished().getFreeText() != null) {
@@ -358,13 +364,36 @@ public class CdmLightClassificationExport
                             handleReference(state, taxon.getSec());
                         }
                     }
+                    //secundum subname
+                    TaxonName subName = taxon.getSecSource() == null? null : taxon.getSecSource().getNameUsedInSource();
+                    if (subName != null) {
+                        csvLine[table.getIndex(CdmLightExportTable.SEC_SUBNAME_FK)] = getId(state, subName);
+                        if (!state.getNameStore().containsKey((subName.getId()))) {
+                            handleName(state, subName, null);
+                        }
+                        csvLine[table.getIndex(CdmLightExportTable.SEC_SUBNAME)] = subName.getNameCache();
+                        csvLine[table.getIndex(CdmLightExportTable.SEC_SUBNAME_AUTHORS)] = subName.getAuthorshipCache();
+                    }
+
+                    csvLine[table.getIndex(CdmLightExportTable.APPENDED_PHRASE)] = taxon.getAppendedPhrase();
                     csvLine[table.getIndex(CdmLightExportTable.CLASSIFICATION_ID)] = getId(state,
                             taxonNode.getClassification());
                     csvLine[table.getIndex(CdmLightExportTable.CLASSIFICATION_TITLE)] = taxonNode.getClassification()
                             .getTitleCache();
-
                     csvLine[table.getIndex(CdmLightExportTable.PUBLISHED)] = taxon.isPublish() ? "1" : "0";
+
+                    //taxon node
+                    csvLine[table.getIndex(CdmLightExportTable.INCLUDED)] = taxonNode.getStatus() == null  ? "1" : "0";
+                    csvLine[table.getIndex(CdmLightExportTable.DOUBTFUL)] = taxonNode.isDoubtful() ? "1" : "0";
+                    csvLine[table.getIndex(CdmLightExportTable.UNPLACED)] = taxonNode.isUnplaced() ? "1" : "0";
                     csvLine[table.getIndex(CdmLightExportTable.EXCLUDED)] = taxonNode.isExcluded() ? "1" : "0";
+                    csvLine[table.getIndex(CdmLightExportTable.EXCLUDED_EXACT)] = taxonNode.isExcludedExact() ? "1" : "0";
+                    csvLine[table.getIndex(CdmLightExportTable.EXCLUDED_GEO)] = taxonNode.isGeographicallyExcluded() ? "1" : "0";
+                    csvLine[table.getIndex(CdmLightExportTable.EXCLUDED_TAX)] = taxonNode.isTaxonomicallyExcluded() ? "1" : "0";
+                    csvLine[table.getIndex(CdmLightExportTable.EXCLUDED_NOM)] = taxonNode.isNomenclaturallyExcluded() ? "1" : "0";
+                    csvLine[table.getIndex(CdmLightExportTable.UNCERTAIN_APPLICATION)] = taxonNode.isUncertainApplication() ? "1" : "0";
+                    csvLine[table.getIndex(CdmLightExportTable.UNRESOLVED)] = taxonNode.isUnresolved() ? "1" : "0";
+                    csvLine[table.getIndex(CdmLightExportTable.PLACEMENT_STATUS)] = taxonNode.getStatus() == null ? null : taxonNode.getStatus().getLabel();
                     Map<Language, LanguageString> notesMap = taxonNode.getStatusNote();
                     String statusNotes = "";
                     if (!notesMap.isEmpty() && notesMap.size() == 1) {
@@ -376,33 +405,41 @@ public class CdmLightClassificationExport
                             statusNotes = notesMap.values().iterator().next().getText();
                         }
                     }
-                    csvLine[table.getIndex(CdmLightExportTable.STATUS_NOTES)] = statusNotes;
+                    csvLine[table.getIndex(CdmLightExportTable.PLACEMENT_NOTES)] = statusNotes;
 
-                    csvLine[table.getIndex(CdmLightExportTable.UNPLACED)] = taxonNode.isUnplaced() ? "1" : "0";
-                    csvLine[table.getIndex(CdmLightExportTable.DOUBTFUL)] = taxonNode.isDoubtful() ? "1" : "0";
+                    if (taxonNode.getSource() != null) {
+                        csvLine[table.getIndex(CdmLightExportTable.PLACEMENT_REF_FK)] = getId(state, taxonNode.getSource().getCitation());
+                        String sourceStr = OriginalSourceFormatter.INSTANCE.format(taxonNode.getSource());
+                        csvLine[table.getIndex(CdmLightExportTable.PLACEMENT_REFERENCE)] = sourceStr;
+                    }
+
+                    //process taxon line
                     state.getProcessor().put(table, taxon, csvLine);
+
+                    //descriptions
                     handleDescriptions(state, taxon);
                 } catch (Exception e) {
                     state.getResult().addException(e,
-                            "An unexpected problem occurred when trying to export taxon with id " + taxon.getId());
+                            "An unexpected problem occurred when trying to export taxon with id " + taxon.getId() + " " + taxon.getTitleCache());
                     state.getResult().setState(ExportResultState.INCOMPLETE_WITH_ERROR);
                 }
             }
-
-            taxonNode.removeNullValueFromChildren();
-            // for (TaxonNode child: taxonNode.getChildNodes()){
-            // handleTaxon(state, child);
-            // }
         } catch (Exception e) {
             state.getResult().addException(e, "An unexpected error occurred when handling the taxon node of "
-                    + cdmBaseStr(taxonNode.getTaxon()) + ": " + e.getMessage());
+                    + cdmBaseStr(taxonNode.getTaxon()) + ", titleCache:"+ taxonNode.getTaxon().getTitleCache()+": " + e.getMessage());
         }
     }
 
     private void handleDescriptions(CdmLightExportState state, CdmBase cdmBase) {
+        if (!state.getConfig().isDoFactualData()) {
+            return;
+        }
+        String titleCache = null;
         try {
+
             if (cdmBase instanceof Taxon) {
                 Taxon taxon = HibernateProxyHelper.deproxy(cdmBase, Taxon.class);
+                titleCache = taxon.getTitleCache();
                 Set<TaxonDescription> descriptions = taxon.getDescriptions();
                 List<DescriptionElementBase> simpleFacts = new ArrayList<>();
                 List<DescriptionElementBase> specimenFacts = new ArrayList<>();
@@ -447,6 +484,7 @@ public class CdmLightClassificationExport
                 }
             } else if (cdmBase instanceof TaxonName) {
                 TaxonName name = CdmBase.deproxy(cdmBase, TaxonName.class);
+                titleCache = name.getTitleCache();
                 Set<TaxonNameDescription> descriptions = name.getDescriptions();
                 List<DescriptionElementBase> simpleFacts = new ArrayList<>();
                 for (TaxonNameDescription description : descriptions) {
@@ -461,8 +499,8 @@ public class CdmLightClassificationExport
                 }
             }
         } catch (Exception e) {
-            state.getResult().addException(e, "An unexpected error occurred when handling description of"
-                    + cdmBaseStr(cdmBase) + ": " + e.getMessage());
+            state.getResult().addException(e, "An unexpected error occurred when handling description of "
+                    + cdmBaseStr(cdmBase) + (titleCache != null? (" " +titleCache) : "")+": " + e.getMessage());
         }
     }
 
@@ -506,11 +544,16 @@ public class CdmLightClassificationExport
 
     private void handleSimpleFacts(CdmLightExportState state, CdmBase cdmBase,
             List<DescriptionElementBase> simpleFacts) {
+        String titleCache = null;
         try {
             CdmLightExportTable table;
             if (cdmBase instanceof TaxonName) {
+                titleCache = ((TaxonName)cdmBase).getTitleCache();
                 table = CdmLightExportTable.NAME_FACT;
             } else {
+                if (cdmBase instanceof Taxon){
+                    titleCache = ((Taxon)cdmBase).getTitleCache();
+                }
                 table = CdmLightExportTable.SIMPLE_FACT;
             }
             CdmLightExportTable tableMedia = CdmLightExportTable.MEDIA;
@@ -523,14 +566,19 @@ public class CdmLightClassificationExport
             }
         } catch (Exception e) {
             state.getResult().addException(e, "An unexpected error occurred when handling simple facts for "
-                    + cdmBaseStr(cdmBase) + ": " + e.getMessage());
+                    + cdmBaseStr(cdmBase) + (titleCache != null? (" " +titleCache) : "")+ ": " + e.getMessage());
         }
     }
 
     private void handleTaxonInteractionsFacts(CdmLightExportState state, CdmBase cdmBase,
             List<DescriptionElementBase> taxonInteractionsFacts) {
         CdmLightExportTable table = CdmLightExportTable.TAXON_INTERACTION_FACT;
+        String titleCache = null;
+        if (cdmBase instanceof TaxonBase){
+            titleCache = ((TaxonBase)cdmBase).getTitleCache();
+        }
         for (DescriptionElementBase element : taxonInteractionsFacts) {
+
             try {
 
                 String[] csvLine = new String[table.getSize()];
@@ -546,7 +594,7 @@ public class CdmLightClassificationExport
 
             } catch (Exception e) {
                 state.getResult().addException(e, "An unexpected error occurred when handling taxon interaction"
-                        + cdmBaseStr(element) + ": " + e.getMessage());
+                        + cdmBaseStr(element) + (titleCache != null? (" " +titleCache) : "")+ ": " + e.getMessage());
             }
         }
     }
@@ -601,11 +649,7 @@ public class CdmLightClassificationExport
                 csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
                 if (cdmBase instanceof Taxon) {
                     csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, cdmBase);
-                    // csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] =
-                    // "";
                 } else if (cdmBase instanceof TaxonName) {
-                    // csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] =
-                    // "";
                     csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, cdmBase);
                 }
                 csvLine[table.getIndex(CdmLightExportTable.FACT_CATEGORY)] = textData.getFeature().getLabel();
@@ -622,8 +666,6 @@ public class CdmLightClassificationExport
                 }
                 csvLine[table.getIndex(CdmLightExportTable.MEDIA_URI)] = mediaUris;
                 if (textData.getFeature().equals(Feature.CITATION())) {
-                    // csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] =
-                    // getId(state, cdmBase);
                     state.getProcessor().put(table, textData, csvLine);
                 } else if (!textData.getMultilanguageText().isEmpty()) {
                     for (Language language : textData.getMultilanguageText().keySet()) {
@@ -640,6 +682,33 @@ public class CdmLightClassificationExport
                 } else {
                     state.getProcessor().put(table, textData, csvLine);
                 }
+            }else if (element instanceof CategoricalData) {
+               //use formater
+               CategoricalData categoricalData = (CategoricalData)element;
+               String cache = CategoricalDataFormatter.NewInstance(null).format(categoricalData);
+               csvLine = new String[table.getSize()];
+                csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
+                if (cdmBase instanceof Taxon) {
+                    csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, cdmBase);
+                } else if (cdmBase instanceof TaxonName) {
+                    csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, cdmBase);
+                }
+                csvLine[table.getIndex(CdmLightExportTable.FACT_TEXT)] = cache;
+                csvLine[table.getIndex(CdmLightExportTable.FACT_CATEGORY)] = categoricalData.getFeature().getLabel();
+                state.getProcessor().put(table, categoricalData, csvLine);
+            }else if (element instanceof QuantitativeData) {
+               QuantitativeData quantitativeData = (QuantitativeData) element;
+               String cache = QuantitativeDataFormatter.NewInstance(null).format(quantitativeData);
+               csvLine = new String[table.getSize()];
+                csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
+                if (cdmBase instanceof Taxon) {
+                    csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, cdmBase);
+                } else if (cdmBase instanceof TaxonName) {
+                    csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, cdmBase);
+                }
+                csvLine[table.getIndex(CdmLightExportTable.FACT_TEXT)] = cache;
+                csvLine[table.getIndex(CdmLightExportTable.FACT_CATEGORY)] = quantitativeData.getFeature().getLabel();
+                state.getProcessor().put(table, quantitativeData, csvLine);
             }
         } catch (Exception e) {
             state.getResult().addException(e, "An unexpected error occurred when handling single simple fact "
@@ -745,7 +814,7 @@ public class CdmLightClassificationExport
 
             for (DescriptionElementSource source : sources) {
                 if (!(source.getType().equals(OriginalSourceType.Import)
-                        && state.getConfig().isFilterImportSources())) {
+                        && state.getConfig().isExcludeImportSources())) {
                     String[] csvLine = new String[table.getSize()];
                     Reference ref = source.getCitation();
                     if ((ref == null) && (source.getNameUsedInSource() == null)) {
@@ -769,17 +838,16 @@ public class CdmLightClassificationExport
                     }
                     state.getProcessor().put(table, source, csvLine);
                 }
-
             }
         } catch (Exception e) {
             state.getResult().addException(e, "An unexpected error occurred when handling single source "
                     + cdmBaseStr(element) + ": " + e.getMessage());
         }
-
     }
 
     private void handleDistributionFacts(CdmLightExportState state, Taxon taxon,
             List<DescriptionElementBase> distributionFacts) {
+
         CdmLightExportTable table = CdmLightExportTable.GEOGRAPHIC_AREA_FACT;
         Set<Distribution> distributions = new HashSet<>();
         for (DescriptionElementBase element : distributionFacts) {
@@ -810,23 +878,31 @@ public class CdmLightClassificationExport
             }
         }
          if(state.getConfig().isCreateCondensedDistributionString()){
-             List<Language> langs = new ArrayList<Language>();
+             List<Language> langs = new ArrayList<>();
              langs.add(Language.ENGLISH());
+             TermTree<NamedArea> areaTree = null; //TODO
 
-             CondensedDistribution conDis =
-             geoService.getCondensedDistribution(distributions, true,
-             null,null,state.getConfig().getCondensedDistributionRecipe(), langs
-             );
+             CondensedDistribution conDis = distributionService.getCondensedDistribution(
+                     //TODO add CondensedDistributionConfiguration to export configuration
+                     distributions, areaTree, true, null, state.getConfig().getCondensedDistributionConfiguration(), langs);
              CdmLightExportTable tableCondensed =
-             CdmLightExportTable.CONDENSED_DISTRIBUTION_FACT;
-             String[] csvLine = new String[table.getSize()];
+                     CdmLightExportTable.SIMPLE_FACT;
+             String[] csvLine = new String[tableCondensed.getSize()];
+             //the computed fact has no uuid, TODO: remember the uuid for later reference assignment
+             UUID randomUuid = UUID.randomUUID();
+             csvLine[tableCondensed.getIndex(CdmLightExportTable.FACT_ID)] =
+                     randomUuid.toString();
              csvLine[tableCondensed.getIndex(CdmLightExportTable.TAXON_FK)] =
-             getId(state, taxon);
+                     getId(state, taxon);
              csvLine[tableCondensed.getIndex(CdmLightExportTable.FACT_TEXT)] =
-             conDis.toString();
+                     conDis.toString();
+             csvLine[tableCondensed.getIndex(CdmLightExportTable.LANGUAGE)] =Language.ENGLISH().toString();
+
+             csvLine[tableCondensed.getIndex(CdmLightExportTable.FACT_CATEGORY)] =
+                     "CondensedDistribution";
+
              state.getProcessor().put(tableCondensed, taxon, csvLine);
          }
-
     }
 
     private void handleCommonNameFacts(CdmLightExportState state, Taxon taxon,
@@ -851,23 +927,29 @@ public class CdmLightClassificationExport
                         csvLine[table.getIndex(CdmLightExportTable.AREA_LABEL)] = commonName.getArea().getLabel();
                     }
                     state.getProcessor().put(table, commonName, csvLine);
+                } else if (element instanceof TextData){
+                    String[] csvLine = new String[table.getSize()];
+                    TextData commonName = (TextData) element;
+                    csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
+                    handleSource(state, element, table);
+                    csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, taxon);
+                    if (commonName.getMultilanguageText() != null) {
+                        csvLine[table.getIndex(CdmLightExportTable.FACT_TEXT)] = createMultilanguageString(commonName.getMultilanguageText());
+                    }
+                    state.getProcessor().put(table, commonName, csvLine);
                 } else {
                     state.getResult()
-                            .addError("The distribution description for the taxon " + taxon.getUuid()
-                                    + " is not of type distribution. Could not be exported. UUID of the description element: "
+                            .addError("The common name description for the taxon " + taxon.getUuid()
+                                    + " is not of type common name. Could not be exported. UUID of the description element: "
                                     + element.getUuid());
                 }
             } catch (Exception e) {
                 state.getResult().addException(e, "An unexpected error occurred when handling single common name "
-                        + cdmBaseStr(element) + ": " + e.getMessage());
+                        + cdmBaseStr(element) + " - "+taxon.getTitleCache()+ ": " + e.getMessage());
             }
         }
     }
 
-    /**
-     * @param sec
-     * @return
-     */
     private String getTitleCache(IIdentifiableEntity identEntity) {
         if (identEntity == null) {
             return "";
@@ -890,7 +972,7 @@ public class CdmLightClassificationExport
                 return;
             }
             TaxonName name = synonym.getName();
-            handleName(state, name);
+            handleName(state, name, synonym.getAcceptedTaxon());
 
             CdmLightExportTable table = CdmLightExportTable.SYNONYM;
             String[] csvLine = new String[table.getSize()];
@@ -901,6 +983,7 @@ public class CdmLightClassificationExport
             if (synonym.getSec() != null && !state.getReferenceStore().contains(synonym.getSec().getUuid())) {
                 handleReference(state, synonym.getSec());
             }
+            csvLine[table.getIndex(CdmLightExportTable.APPENDED_PHRASE)] = synonym.getAppendedPhrase();
             csvLine[table.getIndex(CdmLightExportTable.SYN_SEC_REFERENCE_FK)] = getId(state, synonym.getSec());
             csvLine[table.getIndex(CdmLightExportTable.SYN_SEC_REFERENCE)] = getTitleCache(synonym.getSec());
             csvLine[table.getIndex(CdmLightExportTable.PUBLISHED)] = synonym.isPublish() ? "1" : "0";
@@ -916,11 +999,8 @@ public class CdmLightClassificationExport
     }
 
     /**
-     * Handles Misapplied names (including pro parte and partial as well as pro
+     * Handles misapplied names (including pro parte and partial as well as pro
      * parte and partial synonyms
-     *
-     * @param state
-     * @param rel
      */
     private void handleProPartePartialMisapplied(CdmLightExportState state, Taxon taxon, Taxon accepted, boolean isProParte, boolean isMisapplied, int index) {
         try {
@@ -929,7 +1009,7 @@ public class CdmLightClassificationExport
                 return;
             }
             TaxonName name = ppSyonym.getName();
-            handleName(state, name);
+            handleName(state, name, accepted);
 
             CdmLightExportTable table = CdmLightExportTable.SYNONYM;
             String[] csvLine = new String[table.getSize()];
@@ -939,6 +1019,10 @@ public class CdmLightClassificationExport
             csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, name);
 
             Reference secRef = ppSyonym.getSec();
+
+            if (secRef != null && !state.getReferenceStore().contains(secRef.getUuid())) {
+                handleReference(state, secRef);
+            }
             csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE_FK)] = getId(state, secRef);
             csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE)] = getTitleCache(secRef);
             Set<TaxonRelationship> rels = accepted.getTaxonRelations(ppSyonym);
@@ -962,6 +1046,9 @@ public class CdmLightClassificationExport
             }
             if (rel != null){
                 Reference synSecRef = rel.getCitation();
+                if (synSecRef != null && !state.getReferenceStore().contains(synSecRef.getUuid())) {
+                    handleReference(state, synSecRef);
+                }
                 csvLine[table.getIndex(CdmLightExportTable.SYN_SEC_REFERENCE_FK)] = getId(state, synSecRef);
                 csvLine[table.getIndex(CdmLightExportTable.SYN_SEC_REFERENCE)] = getTitleCache(synSecRef);
                 isProParte = rel.getType().isProParte();
@@ -986,11 +1073,11 @@ public class CdmLightClassificationExport
 
     }
 
-    private void handleName(CdmLightExportState state, TaxonName name){
-        handleName(state, name, false);
+    private void handleName(CdmLightExportState state, TaxonName name, Taxon acceptedTaxon){
+        handleName(state, name, acceptedTaxon, false);
     }
 
-    private void handleName(CdmLightExportState state, TaxonName name, boolean acceptedName) {
+    private void handleName(CdmLightExportState state, TaxonName name, Taxon acceptedTaxon, boolean acceptedName) {
         if (name == null || state.getNameStore().containsKey(name.getId())) {
             return;
         }
@@ -1041,6 +1128,8 @@ public class CdmLightClassificationExport
                 csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_WITH_REF)] = name.getFullTitleCache();
             } else {
                 List<TaggedText> taggedFullTitleCache = name.getTaggedFullTitle();
+                List<TaggedText> taggedName = name.getTaggedName();
+
                 String fullTitleWithHtml = createNameWithItalics(taggedFullTitleCache);
                 // TODO: adapt the tropicos titlecache creation
                 csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_WITH_REF)] = fullTitleWithHtml.trim();
@@ -1053,6 +1142,9 @@ public class CdmLightClassificationExport
             csvLine[table.getIndex(CdmLightExportTable.SPECIFIC_EPITHET)] = name.getSpecificEpithet();
 
             csvLine[table.getIndex(CdmLightExportTable.INFRASPECIFIC_EPITHET)] = name.getInfraSpecificEpithet();
+
+            csvLine[table.getIndex(CdmLightExportTable.APPENDED_PHRASE)] = name.getAppendedPhrase();
+
             csvLine[table.getIndex(CdmLightExportTable.BAS_AUTHORTEAM_FK)] = getId(state, name.getBasionymAuthorship());
             if (name.getBasionymAuthorship() != null) {
                 if (state.getAuthorFromStore(name.getBasionymAuthorship().getId()) == null) {
@@ -1087,6 +1179,12 @@ public class CdmLightClassificationExport
 
             Reference nomRef = name.getNomenclaturalReference();
 
+            NomenclaturalSource nomenclaturalSource = name.getNomenclaturalSource();
+            if (nomenclaturalSource != null &&nomenclaturalSource.getNameUsedInSource() != null){
+                handleName(state, nomenclaturalSource.getNameUsedInSource(), null);
+                csvLine[table.getIndex(CdmLightExportTable.NAME_USED_IN_SOURCE_FK)] = getId(state, nomenclaturalSource.getNameUsedInSource());
+            }
+
             if (nomRef != null) {
                 if (!state.getReferenceStore().contains(nomRef.getUuid())) {
                     handleReference(state, nomRef);
@@ -1140,7 +1238,7 @@ public class CdmLightClassificationExport
                     if (author != null
                             && (nomRef.isOfType(ReferenceType.BookSection) || nomRef.isOfType(ReferenceType.Section))) {
                         csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_AUTHOR)] = author.isProtectedTitleCache()
-                                ? author.getTitleCache() : CdmUtils.Nz(author.getNomenclaturalTitle());
+                                ? author.getTitleCache() : CdmUtils.Nz(author.getNomenclaturalTitleCache());
                         csvLine[table.getIndex(CdmLightExportTable.FULL_REF_AUTHOR)] = CdmUtils
                                 .Nz(author.getTitleCache());
                     } else {
@@ -1164,7 +1262,7 @@ public class CdmLightClassificationExport
                     TeamOrPersonBase<?> author = nomRef.getAuthorship();
                     if (author != null) {
                         csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_AUTHOR)] = author.isProtectedTitleCache()
-                                ? author.getTitleCache() : CdmUtils.Nz(author.getNomenclaturalTitle());
+                                ? author.getTitleCache() : CdmUtils.Nz(author.getNomenclaturalTitleCache());
                         csvLine[table.getIndex(CdmLightExportTable.FULL_REF_AUTHOR)] = CdmUtils
                                 .Nz(author.getTitleCache());
                     } else {
@@ -1198,7 +1296,7 @@ public class CdmLightClassificationExport
                         if (sources != null && !sources.isEmpty()){
                             IdentifiableSource source = sources.iterator().next();
                             if (name.getNomenclaturalReference() != null){
-                                isProtologue = source.getCitation().getUuid().equals(name.getNomenclaturalReference().getUuid());
+                                isProtologue = source.getCitation() != null? source.getCitation().getUuid().equals(name.getNomenclaturalReference().getUuid()): false;
                             }
                         }
                         if (isProtologue){
@@ -1212,19 +1310,19 @@ public class CdmLightClassificationExport
                         textualTypeDesignations.add((TextualTypeDesignation) typeDesignation);
                     }
                 } else if (typeDesignation.isInstanceOf(SpecimenTypeDesignation.class)) {
+                    SpecimenTypeDesignation specimenType = HibernateProxyHelper.deproxy(typeDesignation, SpecimenTypeDesignation.class);
+                    specimenTypeDesignations.add(specimenType);
+                    handleSpecimenType(state, specimenType);
 
-                    specimenTypeDesignations.add(HibernateProxyHelper.deproxy(typeDesignation, SpecimenTypeDesignation.class));
 
                 }else if (typeDesignation instanceof NameTypeDesignation){
                     specimenTypeDesignations.add(HibernateProxyHelper.deproxy(typeDesignation, NameTypeDesignation.class));
                 }
             }
-            TypeDesignationSetManager manager = new TypeDesignationSetManager(specimenTypeDesignations, name);
-
-//            String typeDesignationString = createTypeDesignationString(manager.toTaggedText(false, true, true), false, name.isSpecies() || name.isInfraSpecific());
-//            String test = manager.print(false, false, false);
-
-            csvLine[table.getIndex(CdmLightExportTable.TYPE_SPECIMEN)] = manager.print(false, false, false);
+            TypeDesignationSetContainer manager = new TypeDesignationSetContainer(specimenTypeDesignations, name, TypeDesignationSetComparator.ORDER_BY.TYPE_STATUS);
+            HTMLTagRules rules = new HTMLTagRules();
+            rules.addRule(TagEnum.name, "i");
+            csvLine[table.getIndex(CdmLightExportTable.TYPE_SPECIMEN)] = manager.print(false, false, false, rules);
 
             StringBuilder stringbuilder = new StringBuilder();
             int i = 1;
@@ -1235,8 +1333,7 @@ public class CdmLightClassificationExport
                     int index = 1;
                     for (IdentifiableSource source: typeDesignation.getSources()){
                         if (source.getCitation() != null){
-                            DefaultReferenceCacheStrategy cacheStrategy = ((DefaultReferenceCacheStrategy)source.getCitation().getCacheStrategy());
-                            stringbuilder.append(cacheStrategy.getCitation(source.getCitation(), source.getCitationMicroReference()));
+                            stringbuilder.append(OriginalSourceFormatter.INSTANCE.format(source));
                         }
                         if (index < typeDesignation.getSources().size()) {
                             stringbuilder.append( ", ");
@@ -1269,17 +1366,25 @@ public class CdmLightClassificationExport
 
             HomotypicalGroup group = HibernateProxyHelper.deproxy(name.getHomotypicalGroup(), HomotypicalGroup.class);
 
-//            if (!state.containsHomotypicalGroupFromStore(group.getUuid())) {
-//                if (acceptedName){
-//                    handleHomotypicalGroup(state, HibernateProxyHelper.deproxy(group, HomotypicalGroup.class));
-//                }else{
-//                    handleHomotypicalGroup(state, HibernateProxyHelper.deproxy(group, HomotypicalGroup.class));
-//                }
-//            }
             csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_FK)] = getId(state, group);
             List<TaxonName> typifiedNames = new ArrayList<>();
-            typifiedNames.addAll(group.getTypifiedNames());
-            Collections.sort(typifiedNames, new HomotypicalGroupNameComparator(null, true));
+            if (acceptedTaxon != null){
+                HomotypicGroupTaxonComparator comparator = new HomotypicGroupTaxonComparator(acceptedTaxon);
+                List<Synonym> synonymsInGroup = null;
+                if (group.equals(acceptedTaxon.getHomotypicGroup())){
+                    synonymsInGroup = acceptedTaxon.getHomotypicSynonymsByHomotypicGroup(comparator);
+                    typifiedNames.add(name);
+                }else{
+                    synonymsInGroup = acceptedTaxon.getSynonymsInGroup(group, comparator);
+                }
+
+                synonymsInGroup.stream().forEach(synonym -> typifiedNames.add(HibernateProxyHelper.deproxy(synonym.getName())));
+
+            }else{
+                typifiedNames.addAll(group.getTypifiedNames());
+            }
+
+
             Integer seqNumber = typifiedNames.indexOf(name);
             csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_SEQ)] = String.valueOf(seqNumber);
             state.getProcessor().put(table, name, csvLine);
@@ -1287,12 +1392,139 @@ public class CdmLightClassificationExport
 
         } catch (Exception e) {
             state.getResult().addException(e,
-                    "An unexpected error occurred when handling synonym " + cdmBaseStr(name) + ": " + e.getMessage());
+                    "An unexpected error occurred when handling the name " + cdmBaseStr(name) + ": " + name.getTitleCache() + ": " + e.getMessage());
 
             e.printStackTrace();
         }
     }
 
+    private void handleSpecimenType_(CdmLightExportState state, SpecimenTypeDesignation specimenType) {
+        if (specimenType.getTypeSpecimen() != null){
+            DerivedUnit specimen =  specimenType.getTypeSpecimen();
+            if(specimen != null && !state.getSpecimenStore().contains( specimen.getUuid())){
+               handleSpecimen(state, specimen);
+            }
+        }
+        CdmLightExportTable table = CdmLightExportTable.TYPE_DESIGNATION;
+        String[] csvLine = new String[table.getSize()];
+        //TYPE_ID, SPECIMEN_FK, TYPE_VERBATIM_CITATION, TYPE_STATUS, TYPE_DESIGNATED_BY_STRING, TYPE_DESIGNATED_BY_REF_FK};
+        //Specimen_Fk und den Typusangaben (Art des Typus [holo, lecto, etc.], Quelle, Designation-Quelle, +
+        Set<TaxonName> typifiedNames = specimenType.getTypifiedNames();
+        for (TaxonName name: typifiedNames){
+            csvLine[table.getIndex(CdmLightExportTable.TYPE_STATUS)] = specimenType.getTypeStatus() != null? specimenType.getTypeStatus().getDescription(): "";
+            csvLine[table.getIndex(CdmLightExportTable.TYPE_ID)] = getId(state, specimenType);
+            csvLine[table.getIndex(CdmLightExportTable.TYPIFIED_NAME_FK)] = getId(state, name);
+            csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_FK)] = getId(state, specimenType.getTypeSpecimen());
+            if (specimenType.getSources() != null && !specimenType.getSources().isEmpty()){
+                String sourceString = "";
+                int index = 0;
+                for (IdentifiableSource source: specimenType.getSources()){
+                    if (source.getCitation()!= null){
+                        sourceString = sourceString.concat(source.getCitation().getCitation());
+                    }
+                    index++;
+                    if (index != specimenType.getSources().size()){
+                        sourceString.concat(", ");
+                    }
+                }
+                csvLine[table.getIndex(CdmLightExportTable.TYPE_INFORMATION_REF_STRING)] = sourceString;
+            }
+            if (specimenType.getDesignationSource() != null && specimenType.getDesignationSource().getCitation() != null && !state.getReferenceStore().contains(specimenType.getDesignationSource().getCitation().getUuid())){
+                handleReference(state, specimenType.getDesignationSource().getCitation());
+                csvLine[table.getIndex(CdmLightExportTable.TYPE_DESIGNATED_BY_REF_FK)] = specimenType.getDesignationSource() != null ? getId(state, specimenType.getDesignationSource().getCitation()): "";
+            }
+
+            state.getProcessor().put(table, specimenType, csvLine);
+        }
+    }
+
+
+    /**
+     * @param specimenType
+     */
+    private void handleSpecimenType(CdmLightExportState state, SpecimenTypeDesignation specimenType) {
+        if (specimenType.getTypeSpecimen() != null){
+            DerivedUnit specimen =  specimenType.getTypeSpecimen();
+            if(specimen != null && !state.getSpecimenStore().contains( specimen.getUuid())){
+               handleSpecimen(state, specimen);
+            }
+        }
+        CdmLightExportTable table = CdmLightExportTable.TYPE_DESIGNATION;
+        String[] csvLine = new String[table.getSize()];
+
+        csvLine[table.getIndex(CdmLightExportTable.TYPE_STATUS)] = specimenType.getTypeStatus() != null? specimenType.getTypeStatus().getDescription(): "";
+        csvLine[table.getIndex(CdmLightExportTable.TYPE_ID)] = getId(state, specimenType);
+        csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_FK)] = getId(state, specimenType.getTypeSpecimen());
+        if (specimenType.getSources() != null && !specimenType.getSources().isEmpty()){
+            String sourceString = "";
+            int index = 0;
+            List<IdentifiableSource> sources = new ArrayList<>(specimenType.getSources());
+            Comparator<IdentifiableSource> compareByYear = new Comparator<IdentifiableSource>() {
+                @Override
+                public int compare(IdentifiableSource o1, IdentifiableSource o2) {
+                    if (o1 == o2){
+                        return 0;
+                    }
+                    if (o1.getCitation() == null && o2.getCitation() != null){
+                        return -1;
+                    }
+                    if (o2.getCitation() == null && o1.getCitation() != null){
+                        return 1;
+                    }
+                    if (o1.getCitation().equals(o2.getCitation())){
+                        return 0;
+                    }
+                    if (o1.getCitation().getDatePublished() == null && o2.getCitation().getDatePublished() != null){
+                        return -1;
+                    }
+                    if (o1.getCitation().getDatePublished() != null && o2.getCitation().getDatePublished() == null){
+                        return 1;
+                    }
+                    if (o1.getCitation().getDatePublished().getYear() == null && o2.getCitation().getDatePublished().getYear() != null){
+                        return -1;
+                    }
+                    if (o1.getCitation().getDatePublished().getYear() != null && o2.getCitation().getDatePublished().getYear() == null){
+                        return 1;
+                    }
+                    return o1.getCitation().getDatePublished().getYear().compareTo(o2.getCitation().getDatePublished().getYear());
+                }
+            };
+            Collections.sort(sources, compareByYear);
+            for (IdentifiableSource source: sources){
+                if (source.getCitation()!= null){
+                    sourceString = sourceString.concat(source.getCitation().getCitation());
+                    handleReference(state, source.getCitation());
+                }
+                index++;
+                if (index <= specimenType.getSources().size()){
+                    sourceString = sourceString.concat("; ");
+                }
+            }
+
+            csvLine[table.getIndex(CdmLightExportTable.TYPE_INFORMATION_REF_STRING)] = sourceString;
+            if (sources.get(0).getCitation() != null ){
+                csvLine[table.getIndex(CdmLightExportTable.TYPE_INFORMATION_REF_FK)] = getId(state, sources.get(0).getCitation());
+            }
+        }
+        if (specimenType.getDesignationSource() != null && specimenType.getDesignationSource().getCitation() != null && !state.getReferenceStore().contains(specimenType.getDesignationSource().getCitation().getUuid())){
+            handleReference(state, specimenType.getDesignationSource().getCitation());
+            csvLine[table.getIndex(CdmLightExportTable.TYPE_DESIGNATED_BY_REF_FK)] = specimenType.getDesignationSource() != null ? getId(state, specimenType.getDesignationSource().getCitation()): "";
+        }
+
+
+        Set<TaxonName> typifiedNames = specimenType.getTypifiedNames();
+
+        if (typifiedNames.size() > 1){
+            state.getResult().addWarning("Please check the specimen type  "
+                    + cdmBaseStr(specimenType) + " there are more then one typified name.");
+        }
+        if (typifiedNames.iterator().hasNext()){
+            TaxonName name = typifiedNames.iterator().next();
+            csvLine[table.getIndex(CdmLightExportTable.TYPIFIED_NAME_FK)] = getId(state, name);
+        }
+        state.getProcessor().put(table, specimenType, csvLine);
+    }
+
     private String createNameWithItalics(List<TaggedText> taggedName) {
 
         String fullTitleWithHtml = "";
@@ -1318,13 +1550,13 @@ public class CdmLightClassificationExport
             TaxonName name2 = rel.getToName();
             name2 = HibernateProxyHelper.deproxy(name2, TaxonName.class);
             if (!state.getNameStore().containsKey(name2.getId())) {
-                handleName(state, name2);
+                handleName(state, name2, null);
             }
-
+            csvLine = new String[table.getSize()];
             csvLine[table.getIndex(CdmLightExportTable.NAME_REL_TYPE)] = type.getLabel();
             csvLine[table.getIndex(CdmLightExportTable.NAME1_FK)] = getId(state, name);
             csvLine[table.getIndex(CdmLightExportTable.NAME2_FK)] = getId(state, name2);
-            state.getProcessor().put(table, name, csvLine);
+            state.getProcessor().put(table, rel.getUuid().toString(), csvLine);
         }
 
         rels = name.getRelationsToThisName();
@@ -1332,14 +1564,11 @@ public class CdmLightClassificationExport
         csvLine = new String[table.getSize()];
 
         for (NameRelationship rel : rels) {
-            NameRelationshipType type = rel.getType();
             TaxonName name2 = rel.getFromName();
-            name2 = HibernateProxyHelper.deproxy(name2, TaxonName.class);
+            name2 = HibernateProxyHelper.deproxy(name2);
             if (!state.getNameStore().containsKey(name2.getId())) {
-                handleName(state, name2);
+                handleName(state, name2, null);
             }
-
-
         }
     }
 
@@ -1378,36 +1607,63 @@ public class CdmLightClassificationExport
                 TaxonName name = (TaxonName)cdmBase;
 
                 try{
-                    Set<String> IPNIidentifiers = name.getIdentifiers(DefinedTerm.IDENTIFIER_NAME_IPNI());
-                    Set<String> tropicosIdentifiers = name.getIdentifiers(DefinedTerm.IDENTIFIER_NAME_TROPICOS());
-                    Set<String> WFOIdentifiers = name.getIdentifiers(DefinedTerm.uuidWfoNameIdentifier);
-                    if (!IPNIidentifiers.isEmpty()) {
-                        csvLine = new String[table.getSize()];
-                        csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, name);
-                        csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = "ScientificName";
-                        csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = IPNI_NAME_IDENTIFIER;
-                        csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
-                                IPNIidentifiers);
-                        state.getProcessor().put(table, name.getUuid() + ", " + IPNI_NAME_IDENTIFIER, csvLine);
-                    }
-                    if (!tropicosIdentifiers.isEmpty()) {
-                        csvLine = new String[table.getSize()];
-                        csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, name);
-                        csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = "ScientificName";
-                        csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = name.getUuid() + ", " + IPNI_NAME_IDENTIFIER;
-                        csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
-                                tropicosIdentifiers);
-                        state.getProcessor().put(table, name.getUuid() + ", " + IPNI_NAME_IDENTIFIER, csvLine);
+                    List<Identifier> identifiers = name.getIdentifiers();
+
+                    //first check which kind of identifiers are available and then sort and create table entries
+                    Map<IdentifierType, Set<Identifier>> identifierTypes = new HashMap<>();
+                    for (Identifier identifier: identifiers){
+                        IdentifierType type = identifier.getType();
+                        if (identifierTypes.containsKey(type)){
+                            identifierTypes.get(type).add(identifier);
+                        }else{
+                            Set<Identifier> tempList = new HashSet<>();
+                            tempList.add(identifier);
+                            identifierTypes.put(type, tempList);
+                        }
                     }
-                    if (!WFOIdentifiers.isEmpty()) {
+
+                    for (IdentifierType type:identifierTypes.keySet()){
+                        Set<Identifier> identifiersByType = identifierTypes.get(type);
                         csvLine = new String[table.getSize()];
                         csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, name);
                         csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = "ScientificName";
-                        csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = WFO_NAME_IDENTIFIER;
+                        csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = type.getLabel();
                         csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
-                                WFOIdentifiers);
-                        state.getProcessor().put(table, name.getUuid() + ", " + WFO_NAME_IDENTIFIER, csvLine);
+                                identifiersByType);
+                        state.getProcessor().put(table, name.getUuid() + ", " + type.getLabel(), csvLine);
                     }
+
+
+//                    Set<String> IPNIidentifiers = name.getIdentifiers(DefinedTerm.IDENTIFIER_NAME_IPNI());
+//                    Set<String> tropicosIdentifiers = name.getIdentifiers(DefinedTerm.IDENTIFIER_NAME_TROPICOS());
+//                    Set<String> WFOIdentifiers = name.getIdentifiers(DefinedTerm.uuidWfoNameIdentifier);
+//                    if (!IPNIidentifiers.isEmpty()) {
+//                        csvLine = new String[table.getSize()];
+//                        csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, name);
+//                        csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = "ScientificName";
+//                        csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = IPNI_NAME_IDENTIFIER;
+//                        csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
+//                                IPNIidentifiers);
+//                        state.getProcessor().put(table, name.getUuid() + ", " + IPNI_NAME_IDENTIFIER, csvLine);
+//                    }
+//                    if (!tropicosIdentifiers.isEmpty()) {
+//                        csvLine = new String[table.getSize()];
+//                        csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, name);
+//                        csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = "ScientificName";
+//                        csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = TROPICOS_NAME_IDENTIFIER;
+//                        csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
+//                                tropicosIdentifiers);
+//                        state.getProcessor().put(table, name.getUuid() + ", " + IPNI_NAME_IDENTIFIER, csvLine);
+//                    }
+//                    if (!WFOIdentifiers.isEmpty()) {
+//                        csvLine = new String[table.getSize()];
+//                        csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, name);
+//                        csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = "ScientificName";
+//                        csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = WFO_NAME_IDENTIFIER;
+//                        csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
+//                                WFOIdentifiers);
+//                        state.getProcessor().put(table, name.getUuid() + ", " + WFO_NAME_IDENTIFIER, csvLine);
+//                    }
                 }catch(Exception e){
                     state.getResult().addWarning("Please check the identifiers for "
                             + cdmBaseStr(cdmBase) + " maybe there is an empty identifier");
@@ -1431,7 +1687,7 @@ public class CdmLightClassificationExport
                         tableName = "PersonOrTeam";
                     }
 
-                    for (Identifier<?> identifier: identifiers){
+                    for (Identifier identifier: identifiers){
                         if (identifier.getType() == null && identifier.getIdentifier() == null){
                             state.getResult().addWarning("Please check the identifiers for "
                                     + cdmBaseStr(cdmBase) + " there is an empty identifier");
@@ -1480,14 +1736,14 @@ public class CdmLightClassificationExport
         }
     }
 
-    private String extractIdentifier(Set<String> identifierSet) {
+    private String extractIdentifier(Set<Identifier> identifierSet) {
 
         String identifierString = "";
-        for (String identifier : identifierSet) {
+        for (Identifier identifier : identifierSet) {
             if (!StringUtils.isBlank(identifierString)) {
                 identifierString += ", ";
             }
-            identifierString += identifier;
+            identifierString += identifier.getIdentifier();
         }
         return identifierString;
     }
@@ -1546,7 +1802,7 @@ public class CdmLightClassificationExport
             String[] csvLineMember = new String[table.getSize()];
             csvLine[table.getIndex(CdmLightExportTable.AUTHOR_ID)] = getId(state, author);
             csvLine[table.getIndex(CdmLightExportTable.ABBREV_AUTHOR)] = author.isProtectedTitleCache()
-                    ? author.getTitleCache() : author.getNomenclaturalTitle();
+                    ? author.getTitleCache() : author.getNomenclaturalTitleCache();
             csvLine[table.getIndex(CdmLightExportTable.AUTHOR_TITLE)] = author.getTitleCache();
             author = HibernateProxyHelper.deproxy(author);
             if (author instanceof Person) {
@@ -1574,7 +1830,7 @@ public class CdmLightClassificationExport
                         csvLineMember = new String[table.getSize()];
                         csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_ID)] = getId(state, member);
                         csvLineMember[table.getIndex(CdmLightExportTable.ABBREV_AUTHOR)] = member
-                                .isProtectedTitleCache() ? member.getTitleCache() : member.getNomenclaturalTitle();
+                                .isProtectedTitleCache() ? member.getTitleCache() : member.getNomenclaturalTitleCache();
                         csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_TITLE)] = member.getTitleCache();
                         csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_GIVEN_NAME)] = member.getGivenName();
                         csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_FAMILY_NAME)] = member.getFamilyName();
@@ -1614,15 +1870,16 @@ public class CdmLightClassificationExport
 
                         if (nameStatus.getRuleConsidered() != null
                                 && !StringUtils.isBlank(nameStatus.getRuleConsidered())) {
-                            statusString += " " + nameStatus.getRuleConsidered();
+                            statusString += ": " + nameStatus.getRuleConsidered();
                         }
                         if (nameStatus.getCitation() != null) {
-                            statusString += " " + nameStatus.getCitation().getTitleCache();
-                        }
-                        if (nameStatus.getCitationMicroReference() != null
-                                && !StringUtils.isBlank(nameStatus.getCitationMicroReference())) {
-                            statusString += " " + nameStatus.getCitationMicroReference();
+                            String shortCitation = OriginalSourceFormatter.INSTANCE.format(nameStatus.getCitation(), null);
+                            statusString += " (" + shortCitation + ")";
                         }
+//                        if (nameStatus.getCitationMicroReference() != null
+//                                && !StringUtils.isBlank(nameStatus.getCitationMicroReference())) {
+//                            statusString += " " + nameStatus.getCitationMicroReference();
+//                        }
                     }
                     statusString += " ";
                 }
@@ -1635,16 +1892,24 @@ public class CdmLightClassificationExport
         }
     }
 
-    private void handleHomotypicalGroup(CdmLightExportState state, HomotypicalGroup group, int sortIndex) {
+    private void handleHomotypicalGroup(CdmLightExportState state, HomotypicalGroup group, Taxon acceptedTaxon, int sortIndex) {
         try {
             state.addHomotypicalGroupToStore(group);
             CdmLightExportTable table = CdmLightExportTable.HOMOTYPIC_GROUP;
             String[] csvLine = new String[table.getSize()];
             csvLine[table.getIndex(CdmLightExportTable.SORT_INDEX)] = String.valueOf(sortIndex);
             csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_ID)] = getId(state, group);
+
             List<TaxonName> typifiedNames = new ArrayList<>();
-//            typifiedNames.addAll(group.getTypifiedNames());
-            group.getTypifiedNames().stream().forEach(name -> typifiedNames.add(HibernateProxyHelper.deproxy(name, TaxonName.class)));
+            if (acceptedTaxon != null){
+                List<Synonym> synonymsInGroup = acceptedTaxon.getSynonymsInGroup(group);
+                if (group.equals(acceptedTaxon.getHomotypicGroup())){
+                    typifiedNames.add(acceptedTaxon.getName());
+                }
+                synonymsInGroup.stream().forEach(synonym -> typifiedNames.add(CdmBase.deproxy(synonym.getName())));
+            }
+
+
             TaxonName firstname = null;
             for (TaxonName name: typifiedNames){
                 Iterator<Taxon> taxa = name.getTaxa().iterator();
@@ -1657,7 +1922,7 @@ public class CdmLightClassificationExport
                 }
             }
 
-            Collections.sort(typifiedNames, new HomotypicalGroupNameComparator(firstname, true));
+//            Collections.sort(typifiedNames, new HomotypicalGroupNameComparator(firstname, true));
             String typifiedNamesString = "";
             String typifiedNamesWithSecString = "";
             String typifiedNamesWithoutAccepted = "";
@@ -1678,30 +1943,130 @@ public class CdmLightClassificationExport
                     nameString = createNameWithItalics(name.getTaggedFullTitle()) ;
                 }
 
-                String synonymSign = "";
-                if (index > 0){
-                    boolean isInvalid = false;
+                Set<NameRelationship> related = name.getNameRelations();
+                List<NameRelationship> relatedList = new ArrayList<>(related);
+
+                Collections.sort(relatedList, (nr1, nr2)-> {
+                        return nr1.getType().compareTo(nr2.getType());});
+
+                List<NameRelationship> nonNames = new ArrayList<>();
+                List<NameRelationship> otherRelationships = new ArrayList<>();
+
+                for (NameRelationship rel: relatedList){
+                    //no inverse relations
+                    if (rel.getFromName().equals(name)){
+                     // alle Homonyme und inverse blocking names
+                        if (rel.getType().equals(NameRelationshipType.LATER_HOMONYM())
+                                || rel.getType().equals(NameRelationshipType.TREATED_AS_LATER_HOMONYM())
+                                || (rel.getType().equals(NameRelationshipType.BLOCKING_NAME_FOR()))
+                                || (rel.getType().equals(NameRelationshipType.UNSPECIFIC_NON()))
+                                || (rel.getType().equals(NameRelationshipType.AVOIDS_HOMONYM_OF()))
+                                ){
+                            nonNames.add(rel);
+                        }else if (!rel.getType().isBasionymRelation()){
+                            otherRelationships.add(rel);
+                        }
+                    }
+                    if (state.getConfig().isShowInverseNameRelationsInHomotypicGroup()) {
+                       if (rel.getToName().equals(name)){
+                            // alle Homonyme und inverse blocking names
+//                               if (rel.getType().equals(NameRelationshipType.LATER_HOMONYM())
+//                                       || rel.getType().equals(NameRelationshipType.TREATED_AS_LATER_HOMONYM())
+//                                       || (rel.getType().equals(NameRelationshipType.BLOCKING_NAME_FOR()))
+//                                       || (rel.getType().equals(NameRelationshipType.UNSPECIFIC_NON()))
+//                                       || (rel.getType().equals(NameRelationshipType.AVOIDS_HOMONYM_OF()))
+//                                       ){
+//                                   nonNames.add(rel);
+//                               }else if (!rel.getType().isBasionymRelation()){
+                                   otherRelationships.add(rel);
+//                               }
+                           }
+                    }
+                }
 
-                    for (NomenclaturalStatus status: name.getStatus()){
-                        if (status != null && status.getType() != null && status.getType().isInvalid()){
-                            isInvalid = true;
-                            break;
+                String nonRelNames = "";
+                String relNames = "";
+
+                if (nonNames.size() > 0){
+                    nonRelNames += " [";
+                }
+                for (NameRelationship relName: nonNames){
+                    String label = "non ";
+                    TaxonName relatedName = null;
+                    if (relName.getFromName().equals(name)){
+                        relatedName = relName.getToName();
+                        if (state.getConfig().isAddHTML()){
+                               nonRelNames += label + createNameWithItalics(relatedName.getTaggedName())+ " ";
+                        }else{
+                               nonRelNames += label + relatedName.getTitleCache();
+                        }
+                    }
+//                    else{
+//                        label = relName.getType().getInverseLabel() + " ";
+//                        relatedName = relName.getFromName();
+//                        nonRelNames += label + relatedName.getTitleCache() + " ";
+//                    }
+                }
+                nonRelNames.trim();
+                if (nonNames.size() > 0){
+                    nonRelNames = StringUtils.strip(nonRelNames, null);
+                    nonRelNames += "] ";
+                }
+
+                //other relationships
+                if (otherRelationships.size() > 0){
+                    relNames += " [";
+                }
+                for (NameRelationship rel: otherRelationships){
+                    String label = "";
+                    TaxonName relatedName = null;
+                    if (rel.getFromName().equals(name)){
+                        label = rel.getType().getLabel() + " ";
+                        relatedName = rel.getToName();
+                        if (state.getConfig().isAddHTML()){
+                            relNames += label + createNameWithItalics(relatedName.getTaggedName())+ " ";
+                        }else{
+                            relNames += label + relatedName.getTitleCache();
                         }
                     }
-                    if (isInvalid){
+                    else {
+                        label = rel.getType().getInverseLabel() + " ";
+                        relatedName = rel.getFromName();
+                        if (state.getConfig().isAddHTML()){
+                            relNames += label + createNameWithItalics(relatedName.getTaggedName())+ " ";
+                        }else{
+                            relNames += label + relatedName.getTitleCache();
+                        }
+                    }
+                }
+                relNames.trim();
+                if (otherRelationships.size() > 0){
+                    relNames = StringUtils.stripEnd(relNames, null);
+                    relNames += "] ";
+                }
+
+
+                String synonymSign = "";
+                if (index > 0){
+                    if (name.isInvalid()){
                         synonymSign = "\u2212 ";
                     }else{
                         synonymSign = "\u2261 ";
                     }
+                }else{
+                    if (name.isInvalid() ){
+                        synonymSign = "\u2212 ";
+                    }else{
+                        synonymSign = "\u003D ";
+                    }
                 }
                 boolean isAccepted = false;
 
                 if (taxonBases.size() == 1){
                      taxonBase = HibernateProxyHelper.deproxy(taxonBases.iterator().next());
-                     Reference secRef = taxonBase.getSec();
-                     if (secRef != null){
-                         sec = ((DefaultReferenceCacheStrategy) secRef.getCacheStrategy())
-                             .createShortCitation(secRef, taxonBase.getSecMicroReference(), true);
+
+                     if (taxonBase.getSec() != null){
+                         sec = OriginalSourceFormatter.INSTANCE_WITH_YEAR_BRACKETS.format(taxonBase.getSecSource());
                      }
                      if (taxonBase.isDoubtful()){
                          doubtful = "?";
@@ -1709,39 +2074,48 @@ public class CdmLightClassificationExport
                          doubtful = "";
                      }
                      if (taxonBase instanceof Synonym){
-                         if (StringUtils.isNotBlank(sec)){
-                             sec = " syn. sec. " + sec;
+                         if (isNotBlank(sec)){
+                             sec = " syn. sec. " + sec + " ";
                          }else {
                              sec = "";
                          }
 
-
-                         typifiedNamesWithoutAccepted += synonymSign + doubtful + nameString ;
-                         typifiedNamesWithoutAcceptedWithSec += synonymSign + doubtful + nameString + sec ;
+                         typifiedNamesWithoutAccepted += synonymSign + doubtful + nameString + nonRelNames + relNames;
+                         typifiedNamesWithoutAcceptedWithSec += synonymSign + doubtful + nameString + sec + nonRelNames + relNames;
                      }else{
-                         sec = "";
+//                         sec = "";
                          if (!(((Taxon)taxonBase).isProparteSynonym() || ((Taxon)taxonBase).isMisapplication())){
                              isAccepted = true;
+                         }else {
+                             synonymSign = "\u003D ";
                          }
 
                      }
-
+                     if (taxonBase.getAppendedPhrase() != null){
+                         if (state.getConfig().isAddHTML()){
+                             String taxonString = createNameWithItalics(taxonBase.getTaggedTitle()) ;
+                             taxonString = taxonString.replace("sec "+sec, "");
+                             String nameCacheWithItalics = createNameWithItalics(name.getTaggedName());
+                             nameString = nameString.replace(nameCacheWithItalics, taxonString);
+                         }
+                     }
                 }else{
                     //there are names used more than once?
                     for (TaxonBase<?> tb: taxonBases){
-                        Reference secRef = tb.getSec();
-                        if (secRef != null){
-                            sec = ((DefaultReferenceCacheStrategy) secRef.getCacheStrategy())
-                                .createShortCitation(secRef, tb.getSecMicroReference(), true);
+                        if (tb.getSec() != null){
+                            sec = OriginalSourceFormatter.INSTANCE_WITH_YEAR_BRACKETS.format(tb.getSecSource());
                         }
                         if (tb.isDoubtful()){
                             doubtful = "?";
                         }else{
                             doubtful = "";
                         }
-                        if (tb instanceof Synonym){
+                        if (tb instanceof Synonym ){
+                            if (!((Synonym)tb).getAcceptedTaxon().equals(acceptedTaxon)) {
+                                continue;
+                            }
                             if (StringUtils.isNotBlank(sec)){
-                                sec = " syn. sec. " + sec;
+                                sec = " syn. sec. " + sec + " ";
                             }else {
                                 sec = "";
                             }
@@ -1752,31 +2126,24 @@ public class CdmLightClassificationExport
                             if (!(((Taxon)tb).isProparteSynonym() || ((Taxon)tb).isMisapplication())){
                                 isAccepted = true;
                                 break;
+                            }else {
+                                synonymSign = "\u003D ";
                             }
-
                         }
                     }
                     if (!isAccepted){
                         typifiedNamesWithoutAccepted += synonymSign + doubtful + nameString + "; ";
-                        typifiedNamesWithoutAcceptedWithSec += synonymSign + doubtful + nameString + sec + "; ";
+                        typifiedNamesWithoutAcceptedWithSec += synonymSign + doubtful + nameString + sec;
+                        typifiedNamesWithoutAcceptedWithSec = typifiedNamesWithoutAcceptedWithSec.trim() + "; ";
                     }
                 }
-                typifiedNamesString += synonymSign + doubtful + nameString ;
-                typifiedNamesWithSecString += synonymSign + doubtful + nameString + sec;
+                typifiedNamesString += synonymSign + doubtful + nameString + nonRelNames + relNames;
+                typifiedNamesWithSecString += synonymSign + doubtful + nameString + sec + nonRelNames + relNames;
 
 
-                if (typifiedNamesString != null) {
-                    csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_STRING)] = typifiedNamesString.trim();
-                } else {
-                    csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_STRING)] = "";
-                }
-
+                csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_STRING)] = typifiedNamesString.trim();
 
-                if (typifiedNamesWithSecString != null) {
-                    csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITH_SEC_STRING)] = typifiedNamesWithSecString.trim();
-                } else {
-                    csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITH_SEC_STRING)] = "";
-                }
+                csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITH_SEC_STRING)] = typifiedNamesWithSecString.trim();
 
                 if (typifiedNamesWithoutAccepted != null && firstname != null) {
                     csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITHOUT_ACCEPTED)] = typifiedNamesWithoutAccepted.trim();
@@ -1799,7 +2166,7 @@ public class CdmLightClassificationExport
 
             List<TaggedText> list = new ArrayList<>();
             if (!designationList.isEmpty()) {
-                TypeDesignationSetManager manager = new TypeDesignationSetManager(group);
+                TypeDesignationSetContainer manager = new TypeDesignationSetContainer(group);
                 list.addAll(new TypeDesignationSetFormatter(true, false, false).toTaggedText(manager));
             }
             String typeTextDesignations = "";
@@ -1807,7 +2174,32 @@ public class CdmLightClassificationExport
             for (TypeDesignationBase<?> typeDes: designationList) {
                if (typeDes instanceof TextualTypeDesignation) {
                        typeTextDesignations = typeTextDesignations + ((TextualTypeDesignation)typeDes).getText(Language.getDefaultLanguage());
-                       typeTextDesignations =  typeTextDesignations + "; ";
+                       String typeDesStateRefs = "";
+                    if (typeDes.getDesignationSource() != null ){
+                        typeDesStateRefs = "[";
+                        NamedSource source = typeDes.getDesignationSource();
+                        if (source.getCitation() != null){
+                            typeDesStateRefs += "fide " + OriginalSourceFormatter.INSTANCE.format(source.getCitation(), null);
+                        }
+                        typeDesStateRefs += "]";
+                    }else if (typeDes.getSources() != null && !typeDes.getSources().isEmpty()){
+                        typeDesStateRefs = "[";
+                        for (IdentifiableSource source: typeDes.getSources()) {
+                            if (source.getCitation() != null){
+                                typeDesStateRefs += "fide " +OriginalSourceFormatter.INSTANCE.format(source.getCitation(), null);
+                            }
+                        }
+
+                        typeDesStateRefs += "]";
+                    }
+
+                       typeTextDesignations =  typeTextDesignations + typeDesStateRefs +"; ";
+
+               }else if (typeDes instanceof SpecimenTypeDesignation){
+                   DerivedUnit specimen =  ((SpecimenTypeDesignation)typeDes).getTypeSpecimen();
+                   if(specimen != null && !state.getSpecimenStore().contains( specimen.getUuid())){
+                       handleSpecimen(state, specimen);
+                   }
                }
             }
             if (typeTextDesignations.equals("; ")) {
@@ -1818,7 +2210,6 @@ public class CdmLightClassificationExport
             }
             String specimenTypeString = !list.isEmpty()? createTypeDesignationString(list, true, typifiedNames.get(0).isSpecies() || typifiedNames.get(0).isInfraSpecific()):"";
 
-            // typeDesignations = typeDesignationString.toString();
             if (StringUtils.isNotBlank(specimenTypeString)) {
                 if (!specimenTypeString.endsWith(".")) {
                        specimenTypeString = specimenTypeString + ".";
@@ -1839,7 +2230,6 @@ public class CdmLightClassificationExport
             }
             state.getProcessor().put(table, String.valueOf(group.getId()), csvLine);
         } catch (Exception e) {
-            e.printStackTrace();
             state.getResult().addException(e, "An unexpected error occurred when handling homotypic group "
                     + cdmBaseStr(group) + ": " + e.getMessage());
         }
@@ -1849,12 +2239,21 @@ public class CdmLightClassificationExport
         StringBuffer homotypicalGroupTypeDesignationString = new StringBuffer();
 
         for (TaggedText text : list) {
-            if (text != null && text.getText() != null
-                    && (text.getText().equals("Type:") || text.getText().equals("NameType:") || (text.getType().equals(TagEnum.name) && !isHomotypicGroup))) {
+            if (text == null || text.getText() == null){
+                continue;  //just in case
+            }
+            if ((text.getText().equalsIgnoreCase("Type:")  //should not happen anymore
+                    || text.getText().equalsIgnoreCase("Nametype:")  //should not happen anymore
+                    || (text.getType().equals(TagEnum.name) && !isHomotypicGroup))) {
                 // do nothing
-            } else if (text.getType().equals(TagEnum.reference)) {
+            }else if (text.getType().equals(TagEnum.reference)) {
                 homotypicalGroupTypeDesignationString.append(text.getText());
-            } else if (text.getType().equals(TagEnum.typeDesignation) ) {
+            }else if (text.getType().equals(TagEnum.name)){
+                if (!isSpecimenTypeDesignation){
+                    homotypicalGroupTypeDesignationString
+                        .append("<i>"+text.getText()+"</i> ");
+                }
+            }else if (text.getType().equals(TagEnum.typeDesignation) ) {
                 if(isSpecimenTypeDesignation){
                     homotypicalGroupTypeDesignationString
                         .append(text.getText().replace(").", "").replace("(", "").replace(")", ""));
@@ -1877,6 +2276,7 @@ public class CdmLightClassificationExport
         typeDesignations += ".";
         typeDesignations = typeDesignations.replace("..", ".");
         typeDesignations = typeDesignations.replace(". .", ".");
+        typeDesignations = typeDesignations.replace("; \u2261", " \u2261 ");
 
         if (typeDesignations.trim().equals(".")) {
             typeDesignations = null;
@@ -2029,9 +2429,7 @@ public class CdmLightClassificationExport
             String[] csvLine = new String[table.getSize()];
             csvLine[table.getIndex(CdmLightExportTable.REFERENCE_ID)] = getId(state, reference);
             // TODO short citations correctly
-            String shortCitation = ((DefaultReferenceCacheStrategy) reference.getCacheStrategy())
-                    .createShortCitation(reference, null, true); // Should be Author(year)
-                                                     // like in Taxon.sec
+            String shortCitation = OriginalSourceFormatter.INSTANCE_WITH_YEAR_BRACKETS.format(reference, null); // Should be Author(year) like in Taxon.sec
             csvLine[table.getIndex(CdmLightExportTable.BIBLIO_SHORT_CITATION)] = shortCitation;
             // TODO get preferred title
             csvLine[table.getIndex(CdmLightExportTable.REF_TITLE)] = reference.isProtectedTitleCache()
@@ -2096,71 +2494,12 @@ public class CdmLightClassificationExport
 
         } else if (authorship instanceof Team) {
 
-            Team authorTeam = HibernateProxyHelper.deproxy(authorship, Team.class);
-            int index = 0;
-
-            for (Person teamMember : authorTeam.getTeamMembers()) {
-                index++;
-                String concat = concatString(authorTeam, authorTeam.getTeamMembers(), index);
-                fullAuthorship += concat + teamMember.getTitleCache();
-            }
-            if (StringUtils.isBlank(fullAuthorship)){
-                fullAuthorship = authorTeam.getTitleCache();
-            }
+            Team authorTeam = (Team)authorship;
+            fullAuthorship = authorTeam.cacheStrategy().getTitleCache(authorTeam);
         }
         return fullAuthorship;
     }
 
-    private static String concatString(Team team, List<Person> teamMembers, int i) {
-        String concat;
-        if (i <= 1) {
-            concat = "";
-        } else if (i < teamMembers.size() || (team.isHasMoreMembers() && i == teamMembers.size())) {
-            concat = STD_TEAM_CONCATINATION;
-        } else {
-            concat = FINAL_TEAM_CONCATINATION;
-        }
-        return concat;
-    }
-
-    /*
-     * TypeDesignation table Specimen_Fk EditName_Fk TypeVerbatimCitation
-     * TypeCategory TypeDesignatedByString TypeDesignatedByRef_Fk
-     */
-
-    // private void handleSpecimenTypeDesignations(CdmLightExportState state,
-    // TaxonName name){
-    // try {
-    // Set<SpecimenTypeDesignation> typeDesignations =
-    // name.getSpecimenTypeDesignations();
-    // CdmLightExportTable table = CdmLightExportTable.TYPE_DESIGNATION;
-    // String nameId = getId(state, name);
-    // String[] csvLine = new String[table.getSize()];
-    // for (SpecimenTypeDesignation specimenType: typeDesignations){
-    // csvLine = new String[table.getSize()];
-    // DerivedUnit specimen = specimenType.getTypeSpecimen();
-    // if (state.getSpecimenFromStore(specimen.getId()) == null){
-    // handleSpecimen(state, specimen);
-    // }
-    // csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_FK)] = getId(state,
-    // specimenType.getTypeSpecimen());
-    // csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = nameId;
-    // csvLine[table.getIndex(CdmLightExportTable.TYPE_VERBATIM_CITATION)] =
-    // specimenType.getTypeSpecimen().generateTitle();
-    // //TODO: add link to existing Vorcabulary
-    // csvLine[table.getIndex(CdmLightExportTable.TYPE_CATEGORY)] = "";
-    // csvLine[table.getIndex(CdmLightExportTable.TYPE_DESIGNATED_BY_STRING)] =
-    // specimenType.getCitation().getTitleCache();
-    // csvLine[table.getIndex(CdmLightExportTable.TYPE_DESIGNATED_BY_REF_FK)] =
-    // getId(state, specimenType.getCitation());
-    // }
-    // } catch (Exception e) {
-    // state.getResult().addException(e, "An unexpected error occurred when
-    // handling specimen type designations for " +
-    // cdmBaseStr(name) + ": " + e.getMessage());
-    // }
-    // }
-
     private void handleSpecimen(CdmLightExportState state, SpecimenOrObservationBase<?> specimen) {
         try {
             state.addSpecimenToStore(specimen);
@@ -2203,7 +2542,7 @@ public class CdmLightClassificationExport
             csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_IMAGE_URIS)] = extractMediaURIs(state,
                     specimen.getDescriptions(), Feature.IMAGE());
             if (specimen instanceof DerivedUnit) {
-                DerivedUnit derivedUnit = (DerivedUnit) specimen;
+                DerivedUnit derivedUnit = HibernateProxyHelper.deproxy(specimen, DerivedUnit.class);
                 if (derivedUnit.getCollection() != null) {
                     csvLine[table.getIndex(CdmLightExportTable.HERBARIUM_ABBREV)] = derivedUnit.getCollection()
                             .getCode();
@@ -2272,8 +2611,8 @@ public class CdmLightClassificationExport
                         }
                     }
                 } else {
-                    state.getResult().addError("The specimen with uuid " + specimen.getUuid()
-                            + " is not an DerivedUnit. Could not be exported.");
+                    state.getResult().addWarning("The specimen with uuid " + specimen.getUuid()
+                            + " is not an DerivedUnit.");
                 }
             }