ref #10206 add publish flag to CdmLight and ColDP export in cdmlib
[cdmlib.git] / cdmlib-io / src / main / java / eu / etaxonomy / cdm / io / cdmLight / CdmLightClassificationExport.java
index 7fb2d2fe637b486b13ae26160934defaaea8a581..551b1410ce11dba609ea41484bc1a8877ff729c2 100755 (executable)
@@ -10,6 +10,7 @@ package eu.etaxonomy.cdm.io.cdmLight;
 
 import java.io.File;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
@@ -25,15 +26,18 @@ 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.compare.name.TypeComparator;
 import eu.etaxonomy.cdm.compare.taxon.HomotypicGroupTaxonComparator;
-import eu.etaxonomy.cdm.ext.geo.IEditGeoService;
 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;
@@ -55,6 +59,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;
@@ -62,6 +67,8 @@ 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.PresenceAbsenceTerm;
+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;
@@ -97,7 +104,9 @@ 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.dao.term.ITermTreeDao;
 import eu.etaxonomy.cdm.persistence.dto.TaxonNodeDto;
 import eu.etaxonomy.cdm.persistence.dto.TaxonNodeDtoByRankAndNameComparator;
 import eu.etaxonomy.cdm.strategy.cache.HTMLTagRules;
@@ -106,6 +115,8 @@ import eu.etaxonomy.cdm.strategy.cache.TaggedText;
 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
  */
@@ -115,15 +126,13 @@ public class CdmLightClassificationExport
 
     private static final long serialVersionUID = 2518643632756927053L;
 
-    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
+    private IDistributionService distributionService;
 
     @Autowired
-    IEditGeoService geoService;
+    private ITermTreeDao termTreeDao;
 
     public CdmLightClassificationExport() {
-        super();
         this.ioName = this.getClass().getSimpleName();
     }
 
@@ -163,7 +172,7 @@ public class CdmLightClassificationExport
             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();
                 }
@@ -220,7 +229,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();
         }
@@ -254,14 +263,13 @@ public class CdmLightClassificationExport
                 if (root.hasChildNodes()) {
                     childNodes = new ArrayList<>();
                     for (TaxonNode child : root.getChildNodes()) {
-                       if (child != null) {
-                               childNodes.add(new TaxonNodeDto(child));
-                       }
+                        if (child != null) {
+                            childNodes.add(new TaxonNodeDto(child));
+                        }
                     }
                     state.getNodeChildrenMap().put(root.getUuid(), childNodes);
 
                     // add root to node map
-
                 }
                 TaxonNodeDto rootDto = new TaxonNodeDto(root);
                 UUID parentUuid = root.getParent() != null ? root.getParent().getUuid()
@@ -273,11 +281,9 @@ 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 taxonNode "
@@ -302,39 +308,47 @@ public class CdmLightClassificationExport
                 Taxon taxon = CdmBase.deproxy(taxonNode.getTaxon());
 
                 try {
+                    //accepted name
                     TaxonName name = taxon.getName();
                     handleName(state, name, taxon, true);
-                    HomotypicalGroup homotypicGroup = taxon.getHomotypicGroup();
-                    int index = 0;
-                    int homotypicGroupIndex = 0;
-                    handleHomotypicalGroup(state, homotypicGroup, taxon, homotypicGroupIndex);
-                    homotypicGroupIndex++;
-                    for (Synonym syn : taxon.getSynonymsInGroup(homotypicGroup)) {
-                        handleSynonym(state, syn, index);
-                        index++;
-                    }
-                    List<HomotypicalGroup> heterotypicHomotypicGroups = taxon.getHeterotypicSynonymyGroups();
-                    for (HomotypicalGroup group: heterotypicHomotypicGroups){
-                        handleHomotypicalGroup(state, group, taxon, homotypicGroupIndex);
-                        for (Synonym syn : taxon.getSynonymsInGroup(group)) {
+
+                    if (state.getConfig().isDoSynonyms()) {
+
+                        //homotypic group / synonyms
+                        HomotypicalGroup homotypicGroup = taxon.getHomotypicGroup();
+                        int index = 0;
+                        int homotypicGroupIndex = 0;
+                        handleHomotypicalGroup(state, homotypicGroup, taxon, homotypicGroupIndex);
+                        homotypicGroupIndex++;
+                        for (Synonym syn : taxon.getSynonymsInGroup(homotypicGroup)) {
                             handleSynonym(state, syn, index);
                             index++;
                         }
-                        homotypicGroupIndex++;
-                    }
-
-                    index = 0;
-                    for (Taxon tax : taxon.getAllProParteSynonyms()) {
-                        handleProPartePartialMisapplied(state, tax, taxon, true, false, index);
-                        index++;
-                    }
+                        List<HomotypicalGroup> heterotypicHomotypicGroups = taxon.getHeterotypicSynonymyGroups();
+                        for (HomotypicalGroup group: heterotypicHomotypicGroups){
+                            handleHomotypicalGroup(state, group, taxon, homotypicGroupIndex);
+                            for (Synonym syn : taxon.getSynonymsInGroup(group)) {
+                                handleSynonym(state, syn, index);
+                                index++;
+                            }
+                            homotypicGroupIndex++;
+                        }
 
+                        //pro parte synonyms
+                        index = 0;
+                        for (Taxon tax : taxon.getAllProParteSynonyms()) {
+                            handleProPartePartialMisapplied(state, tax, taxon, true, false, index);
+                            index++;
+                        }
 
-                    for (Taxon tax : taxon.getAllMisappliedNames()) {
-                        handleProPartePartialMisapplied(state, tax, taxon, false, true, 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()];
 
@@ -342,6 +356,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) {
@@ -357,14 +373,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,11 +414,18 @@ 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,
@@ -388,9 +433,6 @@ public class CdmLightClassificationExport
                     state.getResult().setState(ExportResultState.INCOMPLETE_WITH_ERROR);
                 }
             }
-
-            taxonNode.removeNullValueFromChildren();
-
         } catch (Exception e) {
             state.getResult().addException(e, "An unexpected error occurred when handling the taxon node of "
                     + cdmBaseStr(taxonNode.getTaxon()) + ", titleCache:"+ taxonNode.getTaxon().getTitleCache()+": " + e.getMessage());
@@ -398,6 +440,9 @@ public class CdmLightClassificationExport
     }
 
     private void handleDescriptions(CdmLightExportState state, CdmBase cdmBase) {
+        if (!state.getConfig().isDoFactualData()) {
+            return;
+        }
         String titleCache = null;
         try {
 
@@ -413,20 +458,22 @@ public class CdmLightClassificationExport
                 List<DescriptionElementBase> usageFacts = new ArrayList<>();
                 for (TaxonDescription description : descriptions) {
                     if (description.getElements() != null) {
-                        for (DescriptionElementBase element : description.getElements()) {
-                            element = CdmBase.deproxy(element);
-                            handleAnnotations(element);
-                            if (element.getFeature().equals(Feature.COMMON_NAME())) {
-                                commonNameFacts.add(element);
-                            } else if (element.getFeature().equals(Feature.DISTRIBUTION())) {
-                                distributionFacts.add(element);
-                            } else if (element instanceof IndividualsAssociation
-                                    || isSpecimenFeature(element.getFeature())) {
-                                specimenFacts.add(element);
-                            } else if (element.getFeature().isSupportsTaxonInteraction()) {
-                                taxonInteractionsFacts.add(element);
-                            } else {
-                                simpleFacts.add(element);
+                        if (description.isPublish() || state.getConfig().isIncludeUnpublishedFacts()){
+                            for (DescriptionElementBase element : description.getElements()) {
+                                element = CdmBase.deproxy(element);
+                                handleAnnotations(element);
+                                if (element.getFeature().equals(Feature.COMMON_NAME())) {
+                                    commonNameFacts.add(element);
+                                } else if (element.getFeature().equals(Feature.DISTRIBUTION())) {
+                                    distributionFacts.add(element);
+                                } else if (element instanceof IndividualsAssociation
+                                        || isSpecimenFeature(element.getFeature())) {
+                                    specimenFacts.add(element);
+                                } else if (element.getFeature().isSupportsTaxonInteraction()) {
+                                    taxonInteractionsFacts.add(element);
+                                } else {
+                                    simpleFacts.add(element);
+                                }
                             }
                         }
                     }
@@ -646,6 +693,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 "
@@ -775,13 +849,11 @@ 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,
@@ -816,31 +888,46 @@ public class CdmLightClassificationExport
                         + cdmBaseStr(element) + ": " + e.getMessage());
             }
         }
-         if(state.getConfig().isCreateCondensedDistributionString()){
-             List<Language> langs = new ArrayList<>();
-             langs.add(Language.ENGLISH());
-
-             CondensedDistribution conDis = geoService.getCondensedDistribution(
-                     //TODO add CondensedDistributionConfiguration to export configuration
-                     distributions, true, null, state.getConfig().getCondensedDistributionConfiguration(), langs);
-             CdmLightExportTable tableCondensed =
-                     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);
-             csvLine[tableCondensed.getIndex(CdmLightExportTable.FACT_TEXT)] =
-                     conDis.toString();
-             csvLine[tableCondensed.getIndex(CdmLightExportTable.LANGUAGE)] =Language.ENGLISH().toString();
-
-             csvLine[tableCondensed.getIndex(CdmLightExportTable.FACT_CATEGORY)] =
-                     "CondensedDistribution";
-
-             state.getProcessor().put(tableCondensed, taxon, csvLine);
-         }
+        if(state.getConfig().isCreateCondensedDistributionString()){
+            List<Language> langs = new ArrayList<>();
+            langs.add(Language.ENGLISH());
+            TermTree<NamedArea> areaTree = null; //TODO
+            TermTree<PresenceAbsenceTerm> statusTree = getPersistentStatusTree(state.getConfig());
+
+            CondensedDistribution conDis = distributionService.getCondensedDistribution(
+                    //TODO add CondensedDistributionConfiguration to export configuration
+                    distributions, areaTree, statusTree, true, null,
+                    state.getConfig().getCondensedDistributionConfiguration(), langs);
+            CdmLightExportTable tableCondensed =
+                    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);
+            csvLine[tableCondensed.getIndex(CdmLightExportTable.FACT_TEXT)] =
+                    conDis.toString();
+            csvLine[tableCondensed.getIndex(CdmLightExportTable.LANGUAGE)] =Language.ENGLISH().toString();
+
+            csvLine[tableCondensed.getIndex(CdmLightExportTable.FACT_CATEGORY)] =
+                    "CondensedDistribution";
+
+            state.getProcessor().put(tableCondensed, taxon, csvLine);
+        }
+    }
+
+    private TermTree<PresenceAbsenceTerm> getPersistentStatusTree(CdmLightExportConfigurator config) {
+        UUID statusTreeUuid = config.getStatusTree();
+        if (statusTreeUuid == null) {
+            return null;
+        }
+        //TODO property path
+        String[] propertyPath = new String[] {};
+        @SuppressWarnings("unchecked")
+        TermTree<PresenceAbsenceTerm> statusTree = termTreeDao.load(statusTreeUuid, Arrays.asList(propertyPath));
+        return statusTree;
     }
 
     private void handleCommonNameFacts(CdmLightExportState state, Taxon taxon,
@@ -1120,7 +1207,7 @@ public class CdmLightClassificationExport
             NomenclaturalSource nomenclaturalSource = name.getNomenclaturalSource();
             if (nomenclaturalSource != null &&nomenclaturalSource.getNameUsedInSource() != null){
                 handleName(state, nomenclaturalSource.getNameUsedInSource(), null);
-                csvLine[table.getIndex(CdmLightExportTable.NAME_USED_IN_SOURCE)] = getId(state, nomenclaturalSource.getNameUsedInSource());
+                csvLine[table.getIndex(CdmLightExportTable.NAME_USED_IN_SOURCE_FK)] = getId(state, nomenclaturalSource.getNameUsedInSource());
             }
 
             if (nomRef != null) {
@@ -1131,7 +1218,7 @@ public class CdmLightClassificationExport
                 csvLine[table.getIndex(CdmLightExportTable.PUBLICATION_TYPE)] = nomRef.getType().name();
                 if (nomRef.getVolume() != null) {
                     csvLine[table.getIndex(CdmLightExportTable.VOLUME_ISSUE)] = nomRef.getVolume();
-                    csvLine[table.getIndex(CdmLightExportTable.COLLATION)] = createCollatation(name);
+                    csvLine[table.getIndex(CdmLightExportTable.COLLATION)] = createCollation(name);
                 }
                 if (nomRef.getDatePublished() != null) {
                     csvLine[table.getIndex(CdmLightExportTable.DATE_PUBLISHED)] = nomRef.getTimePeriodPublishedString();
@@ -1153,7 +1240,7 @@ public class CdmLightClassificationExport
                     }
                     if (nomRef.getVolume() == null && inReference.getVolume() != null) {
                         csvLine[table.getIndex(CdmLightExportTable.VOLUME_ISSUE)] = inReference.getVolume();
-                        csvLine[table.getIndex(CdmLightExportTable.COLLATION)] = createCollatation(name);
+                        csvLine[table.getIndex(CdmLightExportTable.COLLATION)] = createCollation(name);
                     }
                     if (inReference.getInReference() != null) {
                         inReference = inReference.getInReference();
@@ -1257,10 +1344,9 @@ public class CdmLightClassificationExport
                     specimenTypeDesignations.add(HibernateProxyHelper.deproxy(typeDesignation, NameTypeDesignation.class));
                 }
             }
-            TypeDesignationSetManager manager = new TypeDesignationSetManager(specimenTypeDesignations, name);
+            TypeDesignationSetContainer manager = new TypeDesignationSetContainer(specimenTypeDesignations, name, TypeDesignationSetComparator.ORDER_BY.TYPE_STATUS);
             HTMLTagRules rules = new HTMLTagRules();
             rules.addRule(TagEnum.name, "i");
-            String test = manager.print(false, false, false, rules);;
             csvLine[table.getIndex(CdmLightExportTable.TYPE_SPECIMEN)] = manager.print(false, false, false, rules);
 
             StringBuilder stringbuilder = new StringBuilder();
@@ -1317,13 +1403,12 @@ public class CdmLightClassificationExport
                     synonymsInGroup = acceptedTaxon.getSynonymsInGroup(group, comparator);
                 }
 
-                synonymsInGroup.stream().forEach(synonym -> typifiedNames.add(HibernateProxyHelper.deproxy(synonym.getName(), TaxonName.class)));
+                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);
@@ -1337,9 +1422,6 @@ public class CdmLightClassificationExport
         }
     }
 
-    /**
-     * @param specimenType
-     */
     private void handleSpecimenType_(CdmLightExportState state, SpecimenTypeDesignation specimenType) {
         if (specimenType.getTypeSpecimen() != null){
             DerivedUnit specimen =  specimenType.getTypeSpecimen();
@@ -1465,14 +1547,8 @@ public class CdmLightClassificationExport
             csvLine[table.getIndex(CdmLightExportTable.TYPIFIED_NAME_FK)] = getId(state, name);
         }
         state.getProcessor().put(table, specimenType, csvLine);
-
-
-
-
-
     }
 
-
     private String createNameWithItalics(List<TaggedText> taggedName) {
 
         String fullTitleWithHtml = "";
@@ -1500,11 +1576,11 @@ public class CdmLightClassificationExport
             if (!state.getNameStore().containsKey(name2.getId())) {
                 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();
@@ -1512,18 +1588,15 @@ 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, null);
             }
-
-
         }
     }
 
-    private String createCollatation(TaxonName name) {
+    private String createCollation(TaxonName name) {
         String collation = "";
         if (name.getNomenclaturalReference() != null) {
             Reference ref = name.getNomenclaturalReference();
@@ -1561,9 +1634,9 @@ public class CdmLightClassificationExport
                     List<Identifier> identifiers = name.getIdentifiers();
 
                     //first check which kind of identifiers are available and then sort and create table entries
-                    Map<DefinedTerm, Set<Identifier>> identifierTypes = new HashMap<>();
+                    Map<IdentifierType, Set<Identifier>> identifierTypes = new HashMap<>();
                     for (Identifier identifier: identifiers){
-                        DefinedTerm type = identifier.getType();
+                        IdentifierType type = identifier.getType();
                         if (identifierTypes.containsKey(type)){
                             identifierTypes.get(type).add(identifier);
                         }else{
@@ -1573,7 +1646,7 @@ public class CdmLightClassificationExport
                         }
                     }
 
-                    for (DefinedTerm type:identifierTypes.keySet()){
+                    for (IdentifierType type:identifierTypes.keySet()){
                         Set<Identifier> identifiersByType = identifierTypes.get(type);
                         csvLine = new String[table.getSize()];
                         csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, name);
@@ -1897,13 +1970,8 @@ public class CdmLightClassificationExport
                 Set<NameRelationship> related = name.getNameRelations();
                 List<NameRelationship> relatedList = new ArrayList<>(related);
 
-                Collections.sort(relatedList, new Comparator<NameRelationship>() {
-                    @Override
-                    public int compare(NameRelationship nr1, NameRelationship nr2) {
-                        return nr1.getType().compareTo(nr2.getType());
-                    }
-
-                });
+                Collections.sort(relatedList, (nr1, nr2)-> {
+                        return nr1.getType().compareTo(nr2.getType());});
 
                 List<NameRelationship> nonNames = new ArrayList<>();
                 List<NameRelationship> otherRelationships = new ArrayList<>();
@@ -1915,12 +1983,29 @@ public class CdmLightClassificationExport
                         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.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);
+//                               }
+                         }
+                    }
                 }
 
                 String nonRelNames = "";
@@ -1934,22 +2019,25 @@ public class CdmLightClassificationExport
                     TaxonName relatedName = null;
                     if (relName.getFromName().equals(name)){
                         relatedName = relName.getToName();
-                        nonRelNames += label + relatedName.getTitleCache() + " ";
+                        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() + " ";
 //                    }
-
-
                 }
-                relNames.trim();
+                nonRelNames.trim();
                 if (nonNames.size() > 0){
                     nonRelNames = StringUtils.strip(nonRelNames, null);
                     nonRelNames += "] ";
                 }
 
+                //other relationships
                 if (otherRelationships.size() > 0){
                     relNames += " [";
                 }
@@ -1965,11 +2053,15 @@ public class CdmLightClassificationExport
                             relNames += label + relatedName.getTitleCache();
                         }
                     }
-//                    else {
-//                        label = rel.getType().getInverseLabel() + " ";
-//                        relatedName = rel.getFromName();
-//                    }
-
+                    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){
@@ -1977,6 +2069,7 @@ public class CdmLightClassificationExport
                     relNames += "] ";
                 }
 
+
                 String synonymSign = "";
                 if (index > 0){
                     if (name.isInvalid()){
@@ -2041,7 +2134,12 @@ public class CdmLightClassificationExport
                         }else{
                             doubtful = "";
                         }
-                        if (tb instanceof Synonym){
+                        if (tb instanceof Synonym ){
+                            Synonym syn = CdmBase.deproxy(tb, Synonym.class);
+                            Taxon acc = syn.getAcceptedTaxon();
+                            if (acc == null || !acc.equals(acceptedTaxon)) {
+                                continue;
+                            }
                             if (StringUtils.isNotBlank(sec)){
                                 sec = " syn. sec. " + sec + " ";
                             }else {
@@ -2051,13 +2149,13 @@ public class CdmLightClassificationExport
                             break;
                         }else{
                             sec = "";
-                            if (!(((Taxon)tb).isProparteSynonym() || ((Taxon)tb).isMisapplication())){
+                            Taxon taxon = CdmBase.deproxy(tb, Taxon.class);
+                            if (!(taxon.isProparteSynonym() || taxon.isMisapplication())){
                                 isAccepted = true;
                                 break;
                             }else {
                                 synonymSign = "\u003D ";
                             }
-
                         }
                     }
                     if (!isAccepted){
@@ -2095,15 +2193,15 @@ 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 = "";
             //The typeDesignationManager does not handle the textual typeDesignations
             for (TypeDesignationBase<?> typeDes: designationList) {
-               if (typeDes instanceof TextualTypeDesignation) {
-                       typeTextDesignations = typeTextDesignations + ((TextualTypeDesignation)typeDes).getText(Language.getDefaultLanguage());
-                       String typeDesStateRefs = "";
+                if (typeDes instanceof TextualTypeDesignation) {
+                    typeTextDesignations = typeTextDesignations + ((TextualTypeDesignation)typeDes).getText(Language.getDefaultLanguage());
+                    String typeDesStateRefs = "";
                     if (typeDes.getDesignationSource() != null ){
                         typeDesStateRefs = "[";
                         NamedSource source = typeDes.getDesignationSource();
@@ -2122,26 +2220,26 @@ public class CdmLightClassificationExport
                         typeDesStateRefs += "]";
                     }
 
-                       typeTextDesignations =  typeTextDesignations + 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);
-                   }
-               }
+                }else if (typeDes instanceof SpecimenTypeDesignation){
+                    DerivedUnit specimen =  ((SpecimenTypeDesignation)typeDes).getTypeSpecimen();
+                    if(specimen != null && !state.getSpecimenStore().contains( specimen.getUuid())){
+                        handleSpecimen(state, specimen);
+                    }
+                }
             }
             if (typeTextDesignations.equals("; ")) {
-               typeTextDesignations = "";
+                typeTextDesignations = "";
             }
             if (StringUtils.isNotBlank(typeTextDesignations)) {
-               typeTextDesignations = typeTextDesignations.substring(0, typeTextDesignations.length()-2);
+                typeTextDesignations = typeTextDesignations.substring(0, typeTextDesignations.length()-2);
             }
             String specimenTypeString = !list.isEmpty()? createTypeDesignationString(list, true, typifiedNames.get(0).isSpecies() || typifiedNames.get(0).isInfraSpecific()):"";
 
             if (StringUtils.isNotBlank(specimenTypeString)) {
                 if (!specimenTypeString.endsWith(".")) {
-                       specimenTypeString = specimenTypeString + ".";
+                    specimenTypeString = specimenTypeString + ".";
                 }
                 csvLine[table.getIndex(CdmLightExportTable.TYPE_STRING)] = specimenTypeString;
 
@@ -2150,7 +2248,7 @@ public class CdmLightClassificationExport
             }
             if (StringUtils.isNotBlank(typeTextDesignations)) {
                 if (!typeTextDesignations.endsWith(".")) {
-                       typeTextDesignations = typeTextDesignations + ".";
+                    typeTextDesignations = typeTextDesignations + ".";
                 }
                 csvLine[table.getIndex(CdmLightExportTable.TYPE_CACHE)] = typeTextDesignations;
 
@@ -2441,7 +2539,6 @@ public class CdmLightClassificationExport
              * Diego, El Amatal, 14.4.1993, González 159” [Auch ohne Punkt] ->
              * FieldUnit TitleCache HerbariumAbbrev = “B” [wie gehabt]
              * HerbariumCode
-             *
              */
 
             csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_ID)] = specimenId;
@@ -2482,10 +2579,12 @@ public class CdmLightClassificationExport
                     Iterator<MediaRepresentation> it = mediaSpecimen.getMediaSpecimen().getRepresentations().iterator();
                     String mediaUris = extractMediaUris(it);
                     csvLine[table.getIndex(CdmLightExportTable.MEDIA_SPECIMEN_URL)] = mediaUris;
-
                 }
 
-                if (derivedUnit.getDerivedFrom() != null) {
+                if (derivedUnit.getDerivedFrom() == null) {
+                    state.getResult().addWarning("The specimen with uuid " + specimen.getUuid()
+                        + " does not have a field unit.");
+                } else {
                     for (SpecimenOrObservationBase<?> original : derivedUnit.getDerivedFrom().getOriginals()) {
                         // TODO: What to do if there are more then one
                         // FieldUnit??
@@ -2539,9 +2638,6 @@ public class CdmLightClassificationExport
                             }
                         }
                     }
-                } else {
-                    state.getResult().addWarning("The specimen with uuid " + specimen.getUuid()
-                            + " is not an DerivedUnit.");
                 }
             }
 
@@ -2652,5 +2748,4 @@ public class CdmLightClassificationExport
     protected boolean isIgnore(CdmLightExportState state) {
         return false;
     }
-
-}
+}
\ No newline at end of file