commit 0a7c1eec98593aefbaf66eebd097d659d51edb85
Author: Patrick Plitzner <p.plitzner@bgbm.org>
Date:   Mon Jun 27 12:33:50 2016 +0200

    classifications

diff --git a/cdmlib-io/src/main/java/eu/etaxonomy/cdm/io/csv/redlist/out/CsvExportBaseRedlist.java b/cdmlib-io/src/main/java/eu/etaxonomy/cdm/io/csv/redlist/out/CsvExportBaseRedlist.java
index e47c079571..9c65ab0ebe 100644
--- a/cdmlib-io/src/main/java/eu/etaxonomy/cdm/io/csv/redlist/out/CsvExportBaseRedlist.java
+++ b/cdmlib-io/src/main/java/eu/etaxonomy/cdm/io/csv/redlist/out/CsvExportBaseRedlist.java
@@ -16,7 +16,6 @@ import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
 import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -33,14 +32,11 @@ import eu.etaxonomy.cdm.common.CdmUtils;
 import eu.etaxonomy.cdm.io.common.CdmExportBase;
 import eu.etaxonomy.cdm.io.common.ICdmExport;
 import eu.etaxonomy.cdm.io.common.mapping.out.IExportTransformer;
-import eu.etaxonomy.cdm.io.csv.redlist.out.CsvTaxExportConfiguratorRedlist;
-import eu.etaxonomy.cdm.io.csv.redlist.out.CsvTaxExportStateRedlist;
 import eu.etaxonomy.cdm.model.common.CdmBase;
 import eu.etaxonomy.cdm.model.common.IOriginalSource;
 import eu.etaxonomy.cdm.model.common.ISourceable;
-import eu.etaxonomy.cdm.model.location.NamedArea;
 import eu.etaxonomy.cdm.model.location.Country;
-import eu.etaxonomy.cdm.model.taxon.Classification;
+import eu.etaxonomy.cdm.model.location.NamedArea;
 import eu.etaxonomy.cdm.model.taxon.Taxon;
 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
@@ -73,25 +69,22 @@ public abstract class CsvExportBaseRedlist extends CdmExportBase<CsvTaxExportCon
 	
 	
 	/**
-	 * Returns the list of {@link TaxonNode taxon nodes} that are part in one of the given {@link Classification classifications} 
-	 * and do have a {@link Taxon} attached (empty taxon nodes should not but do exist in CDM databases).
-	 * If <code>classificationList</code> is <code>null</code> or empty then all {@link TaxonNode taxon nodes} of all 
-	 * {@link Classification classifications} are returned.<BR>
-	 * Preliminary implementation. Better implement API method for this.
+	 * Returns all children of the given taxon node and the node itself if the node has
+	 *  a {@link Taxon} attached (empty taxon nodes should not but do exist in CDM databases).
 	 * @return
 	 */
-	protected List<TaxonNode> getAllNodes(Set<Classification> classificationList) {
+	protected Set<TaxonNode> getAllNodes(Set<TaxonNode> taxonNodes) {
 		//handle empty list as no filter defined
-		if (classificationList != null && classificationList.isEmpty()){
-			classificationList = null;
+		if (taxonNodes != null && taxonNodes.isEmpty()){
+			taxonNodes = null;
 		}
 		
 		List<TaxonNode> allNodes =  getClassificationService().getAllNodes();
-		List<TaxonNode> result = new ArrayList<TaxonNode>();
+		Set<TaxonNode> result = new HashSet<TaxonNode>();
 		for (TaxonNode node : allNodes){
 			if (node.getClassification() == null ){
 				continue;
-			}else if (classificationList != null && ! classificationList.contains(node.getClassification())){
+			}else if (taxonNodes != null && ! taxonNodes.contains(node.getClassification())){
 				continue;
 			}else{
 				Taxon taxon = CdmBase.deproxy(node.getTaxon(), Taxon.class);
diff --git a/cdmlib-io/src/main/java/eu/etaxonomy/cdm/io/csv/redlist/out/CsvTaxExportConfiguratorRedlist.java b/cdmlib-io/src/main/java/eu/etaxonomy/cdm/io/csv/redlist/out/CsvTaxExportConfiguratorRedlist.java
index a766530757..138eff6ba9 100644
--- a/cdmlib-io/src/main/java/eu/etaxonomy/cdm/io/csv/redlist/out/CsvTaxExportConfiguratorRedlist.java
+++ b/cdmlib-io/src/main/java/eu/etaxonomy/cdm/io/csv/redlist/out/CsvTaxExportConfiguratorRedlist.java
@@ -1,298 +1,298 @@
-/**
- * Copyright (C) 2007 EDIT
- * European Distributed Institute of Taxonomy 
- * http://www.e-taxonomy.eu
- * 
- * The contents of this file are subject to the Mozilla Public License Version 1.1
- * See LICENSE.TXT at the top of this package for the full license terms.
- */
-
-package eu.etaxonomy.cdm.io.csv.redlist.out;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.UUID;
-
-import org.apache.log4j.Logger;
-
-import eu.etaxonomy.cdm.database.ICdmDataSource;
-import eu.etaxonomy.cdm.io.common.XmlExportConfiguratorBase;
-import eu.etaxonomy.cdm.io.common.mapping.out.IExportTransformer;
-import eu.etaxonomy.cdm.model.description.Feature;
-import eu.etaxonomy.cdm.model.location.NamedArea;
-
-
-/**
- * @author a.oppermann
- * @created 17.10.2012
- */
-public class CsvTaxExportConfiguratorRedlist extends XmlExportConfiguratorBase<CsvTaxExportStateRedlist> {
-	@SuppressWarnings("unused")
-	private static final Logger logger = Logger.getLogger(CsvTaxExportConfiguratorRedlist.class);
-
-	private String encoding = "UTF-8";
-	private String linesTerminatedBy = "\r\n";
-	private String fieldsEnclosedBy = "\"";
-	private boolean hasHeaderLines = true;
-	private String fieldsTerminatedBy=",";
-	private boolean doTaxa = true;
-	private boolean doDistributions = false;
-	private ByteArrayOutputStream baos;
-	private boolean isUseIdWherePossible = false;
-	private boolean includeBasionymsInResourceRelations;
-	private boolean includeMisappliedNamesInResourceRelations;
-	private String defaultBibliographicCitation = null;
-	private List<UUID> featureExclusions = new ArrayList<UUID>();
-	//filter on the classifications to be exported
-	private Set<UUID> classificationUuids = new HashSet<UUID>();   
-	private boolean withHigherClassification = false;
-	private String setSeparator = ";";
-
-	private List<Feature> features;
-
-	private String classificationTitleCache;
-
-	private List<NamedArea> areas;
-
-	//TODO
-	private static IExportTransformer defaultTransformer = null;
-
-	public static CsvTaxExportConfiguratorRedlist NewInstance(ICdmDataSource source, File destinationFolder) { 
-		return new CsvTaxExportConfiguratorRedlist(source, destinationFolder);
-	}
-
-	@Override
-	@SuppressWarnings("unchecked")
-	protected void makeIoClassList() {
-		ioClassList = new Class[] {
-				CsvTaxExportRedlist.class
-		};
-	}
-
-	/**
-	 * @param url
-	 * @param destination
-	 */
-	private CsvTaxExportConfiguratorRedlist(ICdmDataSource source, File destination) {
-		super(destination, source, defaultTransformer);
-	}
-
-	/* (non-Javadoc)
-	 * @see eu.etaxonomy.cdm.io.common.ImportConfiguratorBase#getSource()
-	 */
-	@Override
-	public File getDestination() {
-		return super.getDestination();
-	}
-
-	/**
-	 * @param file
-	 */
-	@Override
-	public void setDestination(File fileName) {
-		super.setDestination(fileName);
-	}
-
-	/* (non-Javadoc)
-	 * @see eu.etaxonomy.cdm.io.common.IExportConfigurator#getDestinationNameString()
-	 */
-	@Override
-	public String getDestinationNameString() {
-		if (this.getDestination() == null) {
-			return null;
-		} else {
-			return this.getDestination().toString();
-		}
-	}
-
-	/* (non-Javadoc)
-	 * @see eu.etaxonomy.cdm.io.common.IExportConfigurator#getNewState()
-	 */
-	public CsvTaxExportStateRedlist getNewState() {
-		return new CsvTaxExportStateRedlist(this);
-	}
-
-	public boolean isDoTaxa() {
-		return doTaxa;
-	}
-
-	public void setDoTaxa(boolean doTaxa) {
-		this.doTaxa = doTaxa;
-	}
-
-
-	public boolean isDoDistributions() {
-		return doDistributions;
-	}
-
-	public void setDoDistributions(boolean doDistributions) {
-		this.doDistributions = doDistributions;
-	}
-
-	public void setFeatureExclusions(List<UUID> featureExclusions) {
-		this.featureExclusions = featureExclusions;
-	}
-
-	public List<UUID> getFeatureExclusions() {
-		return featureExclusions;
-	}
-
-	public String getEncoding() {
-		return encoding;
-	}
-
-	public void setEncoding(String encoding) {
-		this.encoding = encoding;
-	}
-
-	public String getLinesTerminatedBy() {
-		return linesTerminatedBy;
-	}
-
-	public void setLinesTerminatedBy(String linesTerminatedBy) {
-		this.linesTerminatedBy = linesTerminatedBy;
-	}
-
-	public String getFieldsEnclosedBy() {
-		return fieldsEnclosedBy;
-	}
-
-	public void setFieldsEnclosedBy(String fieldsEnclosedBy) {
-		this.fieldsEnclosedBy = fieldsEnclosedBy;
-	}
-
-	/**
-	 * Equals darwin core archive ignoreHeaderLines attribute
-	 * @return
-	 */
-	public boolean isHasHeaderLines() {
-		return hasHeaderLines;
-	}
-
-	public void setHasHeaderLines(boolean hasHeaderLines) {
-		this.hasHeaderLines = hasHeaderLines;
-	}
-
-	public boolean isIncludeBasionymsInResourceRelations() {
-		return includeBasionymsInResourceRelations;
-	}
-
-	public void setIncludeBasionymsInResourceRelations(boolean includeBasionymsInResourceRelations) {
-		this.includeBasionymsInResourceRelations = includeBasionymsInResourceRelations;
-	}
-
-	public boolean isIncludeMisappliedNamesInResourceRelations() {
-		return includeMisappliedNamesInResourceRelations;
-	}
-
-	public void setIncludeMisappliedNamesInResourceRelations(boolean includeMisappliedNamesInResourceRelations) {
-		this.includeMisappliedNamesInResourceRelations = includeMisappliedNamesInResourceRelations;
-	}
-
-	public boolean isUseIdWherePossible() {
-		return this.isUseIdWherePossible;
-	}
-
-	public void setUseIdWherePossible(boolean isUseIdWherePossible) {
-		this.isUseIdWherePossible = isUseIdWherePossible;
-	}
-
-	public void setDefaultBibliographicCitation(String defaultBibliographicCitation) {
-		this.defaultBibliographicCitation = defaultBibliographicCitation;
-	}
-
-
-	public String getDefaultBibliographicCitation() {
-		return defaultBibliographicCitation;
-	}
-
-	/**
-	 * The default value for the taxon.source column. This may be a column linking to a url that provides 
-	 * data about the given taxon. The id is replaced by a placeholder, 
-	 * e.g. http://wp6-cichorieae.e-taxonomy.eu/portal/?q=cdm_dataportal/taxon/{id}.
-	 * NOTE: This may be replaced in future versions by concrete CDM server implementations.
-	 * 
-	 * @return the taxonSourceDefault
-	 */
-
-	public boolean isWithHigherClassification() {
-		return withHigherClassification;
-	}
-
-	public void setWithHigherClassification(boolean withHigherClassification) {
-		this.withHigherClassification = withHigherClassification;
-	}
-
-	/**
-	 * @return the setSeparator
-	 */
-	public String getSetSeparator() {
-		return setSeparator;
-	}
-
-	/**
-	 * @param setSeparator the setSeparator to set
-	 */
-	public void setSetSeparator(String setSeparator) {
-		this.setSeparator = setSeparator;
-	}
-
-	public void setFieldsTerminatedBy(String fieldsTerminatedBy) {
-		this.fieldsTerminatedBy = fieldsTerminatedBy;
-	}
-
-	public String getFieldsTerminatedBy() {
-		return fieldsTerminatedBy;
-	}
-
-	public Set<UUID> getTaxonNodeUuids() {
-		return classificationUuids;
-	}
-
-	public void setTaxonNodeUuids(Set<UUID> classificationUuids) {
-		this.classificationUuids = classificationUuids;
-	}
-
-	public ByteArrayOutputStream getByteArrayOutputStream() {
-		return baos;
-	}
-
-	public void setByteArrayOutputStream(ByteArrayOutputStream baos) {
-		this.baos = baos;
-	}
-
-	public void setFeatures(List<Feature> features) {
-		this.features = features;
-		
-	}
-	
-	public List<Feature>  getFeatures() {
-		return features;
-		
-	}
-
-	public void setClassificationTitleCache(String classificationTitleCache) {
-		this.classificationTitleCache = classificationTitleCache;
-	}
-	
-	public String getClassificationTitleCache() {
-		return classificationTitleCache;
-	}
-
-	/**
-	 * @param areas
-	 */
-	public void setNamedAreas(List<NamedArea> areas) {
-		// TODO Auto-generated method stub
-		this.areas = areas;
-		
-	}
-	public List<NamedArea> getNamedAreas(){
-		return areas;
-	}
-	
+/**
+ * Copyright (C) 2007 EDIT
+ * European Distributed Institute of Taxonomy 
+ * http://www.e-taxonomy.eu
+ * 
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * See LICENSE.TXT at the top of this package for the full license terms.
+ */
+
+package eu.etaxonomy.cdm.io.csv.redlist.out;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+
+import org.apache.log4j.Logger;
+
+import eu.etaxonomy.cdm.database.ICdmDataSource;
+import eu.etaxonomy.cdm.io.common.XmlExportConfiguratorBase;
+import eu.etaxonomy.cdm.io.common.mapping.out.IExportTransformer;
+import eu.etaxonomy.cdm.model.description.Feature;
+import eu.etaxonomy.cdm.model.location.NamedArea;
+
+
+/**
+ * @author a.oppermann
+ * @created 17.10.2012
+ */
+public class CsvTaxExportConfiguratorRedlist extends XmlExportConfiguratorBase<CsvTaxExportStateRedlist> {
+	@SuppressWarnings("unused")
+	private static final Logger logger = Logger.getLogger(CsvTaxExportConfiguratorRedlist.class);
+
+	private String encoding = "UTF-8";
+	private String linesTerminatedBy = "\r\n";
+	private String fieldsEnclosedBy = "\"";
+	private boolean hasHeaderLines = true;
+	private String fieldsTerminatedBy=",";
+	private boolean doTaxa = true;
+	private boolean doDistributions = false;
+	private ByteArrayOutputStream baos;
+	private boolean isUseIdWherePossible = false;
+	private boolean includeBasionymsInResourceRelations;
+	private boolean includeMisappliedNamesInResourceRelations;
+	private String defaultBibliographicCitation = null;
+	private List<UUID> featureExclusions = new ArrayList<UUID>();
+	//filter on the classifications to be exported
+	private Set<UUID> classificationUuids = new HashSet<UUID>();   
+	private boolean withHigherClassification = false;
+	private String setSeparator = ";";
+
+	private List<Feature> features;
+
+	private String classificationTitleCache;
+
+	private List<NamedArea> areas;
+
+	//TODO
+	private static IExportTransformer defaultTransformer = null;
+
+	public static CsvTaxExportConfiguratorRedlist NewInstance(ICdmDataSource source, File destinationFolder) { 
+		return new CsvTaxExportConfiguratorRedlist(source, destinationFolder);
+	}
+
+	@Override
+	@SuppressWarnings("unchecked")
+	protected void makeIoClassList() {
+		ioClassList = new Class[] {
+				CsvTaxExportRedlist.class
+		};
+	}
+
+	/**
+	 * @param url
+	 * @param destination
+	 */
+	private CsvTaxExportConfiguratorRedlist(ICdmDataSource source, File destination) {
+		super(destination, source, defaultTransformer);
+	}
+
+	/* (non-Javadoc)
+	 * @see eu.etaxonomy.cdm.io.common.ImportConfiguratorBase#getSource()
+	 */
+	@Override
+	public File getDestination() {
+		return super.getDestination();
+	}
+
+	/**
+	 * @param file
+	 */
+	@Override
+	public void setDestination(File fileName) {
+		super.setDestination(fileName);
+	}
+
+	/* (non-Javadoc)
+	 * @see eu.etaxonomy.cdm.io.common.IExportConfigurator#getDestinationNameString()
+	 */
+	@Override
+	public String getDestinationNameString() {
+		if (this.getDestination() == null) {
+			return null;
+		} else {
+			return this.getDestination().toString();
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see eu.etaxonomy.cdm.io.common.IExportConfigurator#getNewState()
+	 */
+	public CsvTaxExportStateRedlist getNewState() {
+		return new CsvTaxExportStateRedlist(this);
+	}
+
+	public boolean isDoTaxa() {
+		return doTaxa;
+	}
+
+	public void setDoTaxa(boolean doTaxa) {
+		this.doTaxa = doTaxa;
+	}
+
+
+	public boolean isDoDistributions() {
+		return doDistributions;
+	}
+
+	public void setDoDistributions(boolean doDistributions) {
+		this.doDistributions = doDistributions;
+	}
+
+	public void setFeatureExclusions(List<UUID> featureExclusions) {
+		this.featureExclusions = featureExclusions;
+	}
+
+	public List<UUID> getFeatureExclusions() {
+		return featureExclusions;
+	}
+
+	public String getEncoding() {
+		return encoding;
+	}
+
+	public void setEncoding(String encoding) {
+		this.encoding = encoding;
+	}
+
+	public String getLinesTerminatedBy() {
+		return linesTerminatedBy;
+	}
+
+	public void setLinesTerminatedBy(String linesTerminatedBy) {
+		this.linesTerminatedBy = linesTerminatedBy;
+	}
+
+	public String getFieldsEnclosedBy() {
+		return fieldsEnclosedBy;
+	}
+
+	public void setFieldsEnclosedBy(String fieldsEnclosedBy) {
+		this.fieldsEnclosedBy = fieldsEnclosedBy;
+	}
+
+	/**
+	 * Equals darwin core archive ignoreHeaderLines attribute
+	 * @return
+	 */
+	public boolean isHasHeaderLines() {
+		return hasHeaderLines;
+	}
+
+	public void setHasHeaderLines(boolean hasHeaderLines) {
+		this.hasHeaderLines = hasHeaderLines;
+	}
+
+	public boolean isIncludeBasionymsInResourceRelations() {
+		return includeBasionymsInResourceRelations;
+	}
+
+	public void setIncludeBasionymsInResourceRelations(boolean includeBasionymsInResourceRelations) {
+		this.includeBasionymsInResourceRelations = includeBasionymsInResourceRelations;
+	}
+
+	public boolean isIncludeMisappliedNamesInResourceRelations() {
+		return includeMisappliedNamesInResourceRelations;
+	}
+
+	public void setIncludeMisappliedNamesInResourceRelations(boolean includeMisappliedNamesInResourceRelations) {
+		this.includeMisappliedNamesInResourceRelations = includeMisappliedNamesInResourceRelations;
+	}
+
+	public boolean isUseIdWherePossible() {
+		return this.isUseIdWherePossible;
+	}
+
+	public void setUseIdWherePossible(boolean isUseIdWherePossible) {
+		this.isUseIdWherePossible = isUseIdWherePossible;
+	}
+
+	public void setDefaultBibliographicCitation(String defaultBibliographicCitation) {
+		this.defaultBibliographicCitation = defaultBibliographicCitation;
+	}
+
+
+	public String getDefaultBibliographicCitation() {
+		return defaultBibliographicCitation;
+	}
+
+	/**
+	 * The default value for the taxon.source column. This may be a column linking to a url that provides 
+	 * data about the given taxon. The id is replaced by a placeholder, 
+	 * e.g. http://wp6-cichorieae.e-taxonomy.eu/portal/?q=cdm_dataportal/taxon/{id}.
+	 * NOTE: This may be replaced in future versions by concrete CDM server implementations.
+	 * 
+	 * @return the taxonSourceDefault
+	 */
+
+	public boolean isWithHigherClassification() {
+		return withHigherClassification;
+	}
+
+	public void setWithHigherClassification(boolean withHigherClassification) {
+		this.withHigherClassification = withHigherClassification;
+	}
+
+	/**
+	 * @return the setSeparator
+	 */
+	public String getSetSeparator() {
+		return setSeparator;
+	}
+
+	/**
+	 * @param setSeparator the setSeparator to set
+	 */
+	public void setSetSeparator(String setSeparator) {
+		this.setSeparator = setSeparator;
+	}
+
+	public void setFieldsTerminatedBy(String fieldsTerminatedBy) {
+		this.fieldsTerminatedBy = fieldsTerminatedBy;
+	}
+
+	public String getFieldsTerminatedBy() {
+		return fieldsTerminatedBy;
+	}
+
+	public Set<UUID> getTaxonNodeUuids() {
+		return classificationUuids;
+	}
+
+	public void setTaxonNodeUuids(Set<UUID> classificationUuids) {
+		this.classificationUuids = classificationUuids;
+	}
+
+	public ByteArrayOutputStream getByteArrayOutputStream() {
+		return baos;
+	}
+
+	public void setByteArrayOutputStream(ByteArrayOutputStream baos) {
+		this.baos = baos;
+	}
+
+	public void setFeatures(List<Feature> features) {
+		this.features = features;
+		
+	}
+	
+	public List<Feature>  getFeatures() {
+		return features;
+		
+	}
+
+	public void setClassificationTitleCache(String classificationTitleCache) {
+		this.classificationTitleCache = classificationTitleCache;
+	}
+	
+	public String getClassificationTitleCache() {
+		return classificationTitleCache;
+	}
+
+	/**
+	 * @param areas
+	 */
+	public void setNamedAreas(List<NamedArea> areas) {
+		// TODO Auto-generated method stub
+		this.areas = areas;
+		
+	}
+	public List<NamedArea> getNamedAreas(){
+		return areas;
+	}
+	
 }
\ No newline at end of file
diff --git a/cdmlib-io/src/main/java/eu/etaxonomy/cdm/io/csv/redlist/out/CsvTaxExportRedlist.java b/cdmlib-io/src/main/java/eu/etaxonomy/cdm/io/csv/redlist/out/CsvTaxExportRedlist.java
index dbb436428a..40adedebc0 100644
--- a/cdmlib-io/src/main/java/eu/etaxonomy/cdm/io/csv/redlist/out/CsvTaxExportRedlist.java
+++ b/cdmlib-io/src/main/java/eu/etaxonomy/cdm/io/csv/redlist/out/CsvTaxExportRedlist.java
@@ -1,411 +1,409 @@
-/**
-* Copyright (C) 2007 EDIT
-* European Distributed Institute of Taxonomy 
-* http://www.e-taxonomy.eu
-* 
-* The contents of this file are subject to the Mozilla Public License Version 1.1
-* See LICENSE.TXT at the top of this package for the full license terms.
-*/
-
-package eu.etaxonomy.cdm.io.csv.redlist.out;
-
-import java.io.ByteArrayOutputStream;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.UUID;
-
-import org.apache.log4j.Logger;
-import org.springframework.stereotype.Component;
-import org.springframework.transaction.TransactionStatus;
-
-import eu.etaxonomy.cdm.model.common.CdmBase;
-import eu.etaxonomy.cdm.model.common.Language;
-import eu.etaxonomy.cdm.model.common.RelationshipTermBase;
-import eu.etaxonomy.cdm.model.description.CategoricalData;
-import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
-import eu.etaxonomy.cdm.model.description.Distribution;
-import eu.etaxonomy.cdm.model.description.Feature;
-import eu.etaxonomy.cdm.model.description.State;
-import eu.etaxonomy.cdm.model.description.TaxonDescription;
-import eu.etaxonomy.cdm.model.description.TextData;
-import eu.etaxonomy.cdm.model.location.NamedArea;
-import eu.etaxonomy.cdm.model.name.NonViralName;
-import eu.etaxonomy.cdm.model.taxon.Classification;
-import eu.etaxonomy.cdm.model.taxon.Synonym;
-import eu.etaxonomy.cdm.model.taxon.SynonymRelationship;
-import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType;
-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.taxon.TaxonRelationshipType;
-
-
-/**
- * @author a.oppermann
- * @created 18.10.2012
- */
-
-@Component
-public class CsvTaxExportRedlist extends CsvExportBaseRedlist {
-	private static final Logger logger = Logger.getLogger(CsvTaxExportRedlist.class);
-
-	private static final String ROW_TYPE = "http://rs.tdwg.org/dwc/terms/Taxon";
-	private static final String fileName = "RedlistCoreTax.csv";
-
-	public CsvTaxExportRedlist() {
-		super();
-		this.ioName = this.getClass().getSimpleName();
-	}
-	
-
-	/** Retrieves data from a CDM DB and serializes them CDM to CSV.
-	 * Starts with root taxa and traverses the classification to retrieve 
-	 * children taxa, synonyms, relationships, descriptive data, red list 
-	 * status (features). 
-	 * Taxa that are not part of the classification are not found.
-	 * 
-	 * @param exImpConfig
-	 * @param dbname
-	 * @param filename
-	 */
-	@Override
-	protected void doInvoke(CsvTaxExportStateRedlist state){
-		CsvTaxExportConfiguratorRedlist config = state.getConfig();
-		TransactionStatus txStatus = startTransaction(true);
-		List<NamedArea> selectedAreas = config.getNamedAreas();
-		Set<Classification> classificationSet = assembleClassificationSet(config);
-		
-		PrintWriter writer = null;
-		ByteArrayOutputStream byteArrayOutputStream;
-		try {
-			byteArrayOutputStream = config.getByteArrayOutputStream();
-			writer = new PrintWriter(byteArrayOutputStream); 
-			//geographical Filter
-			List<TaxonNode> filteredNodes = handleGeographicalFilter(selectedAreas, classificationSet);
-			
-			//sorting List
-			Collections.sort(filteredNodes, new Comparator<TaxonNode>() {
-
-				@Override
-				public int compare(TaxonNode tn1, TaxonNode tn2) {
-					Taxon taxon1 = tn1.getTaxon();
-					Taxon taxon2 = tn2.getTaxon();
-					if(taxon1 != null && taxon2 != null){
-						return taxon1.getTitleCache().compareTo(taxon2.getTitleCache());
-					}
-					else{
-						return 0;
-					}
-				}
-			});
-			for (TaxonNode node : filteredNodes){
-				Taxon taxon = CdmBase.deproxy(node.getTaxon(), Taxon.class);
-				CsvTaxRecordRedlist record = assembleRecord(state);
-				NonViralName<?> name = CdmBase.deproxy(taxon.getName(), NonViralName.class);
-				Classification classification = node.getClassification();
-				config.setClassificationTitleCache(classification.getTitleCache());	
-				if (! this.recordExists(taxon)){
-					handleTaxonBase(record, taxon, name, taxon, classification, null, false, false, config);
-					record.write(writer);
-					this.addExistingRecord(taxon);
-				}
-				//misapplied names
-				handleMisapplication(taxon, writer, classification, record, config);
-				writer.flush();
-			}
-		} catch (ClassCastException e) {
-			e.printStackTrace();
-		}
-		finally{
-			writer.close();
-			this.clearExistingRecordIds();
-		}
-		commitTransaction(txStatus);
-		return;
-
-	}
-	
-	
-	//TODO: Exception handling
-	protected Set<Classification> assembleClassificationSet(CsvTaxExportConfiguratorRedlist config){
-		if(config != null){
-			Set<UUID> taxonNodeUuidSet = config.getTaxonNodeUuids();
-			List<Classification> classificationList = getClassificationService().find(taxonNodeUuidSet);
-			Set<Classification> classificationSet = new HashSet<Classification>();
-			classificationSet.addAll(classificationList);
-			return classificationSet;
-		}
-		return null;
-	}
-
-	//TODO: Exception handling
-	private CsvTaxRecordRedlist assembleRecord(CsvTaxExportStateRedlist state) {
-		if(state!=null){
-			CsvTaxExportConfiguratorRedlist config = state.getConfig();
-			CsvMetaDataRecordRedlist metaRecord = new CsvMetaDataRecordRedlist(true, fileName, ROW_TYPE);
-			state.addMetaRecord(metaRecord);
-			CsvTaxRecordRedlist record = new CsvTaxRecordRedlist(metaRecord, config);
-			return record;
-		}
-		return null;
-	}
-
-	/**
-	 * Takes positive List of areas and iterates over a given classification 
-	 * and their {@link Taxon} to return all {@link Taxon} with the desired 
-	 * geographical attribute.
-	 * 
-	 * <p><p>
-	 *
-	 * If selectedAreas is null all {@link TaxonNode}s of the given {@link Classification} will be returned.
-	 * 
-	 * @param selectedAreas 
-	 * @param classificationSet
-	 * @return
-	 */
-	protected List<TaxonNode> handleGeographicalFilter(List<NamedArea> selectedAreas,
-			Set<Classification> classificationSet) {
-		List<TaxonNode> filteredNodes = new ArrayList<TaxonNode>();
-		List<TaxonNode> allNodes =  getAllNodes(classificationSet);
-		//Geographical filter
-		logger.info(selectedAreas.size());
-		if(selectedAreas != null && !selectedAreas.isEmpty() && selectedAreas.size() < 16){
-//				if(selectedAreas.size() == 16){
-//					//Germany TDWG Level 3
-//					String germany="uu7b7c2db5-aa44-4302-bdec-6556fd74b0b9id";
-//					selectedAreas.add((NamedArea) getTermService().find(UUID.fromString(germany)));
-//				}
-			for (TaxonNode node : allNodes){
-				Taxon taxon = CdmBase.deproxy(node.getTaxon(), Taxon.class);
-				Set<TaxonDescription> descriptions = taxon.getDescriptions();
-				for (TaxonDescription description : descriptions){
-					for (DescriptionElementBase el : description.getElements()){
-						if (el.isInstanceOf(Distribution.class) ){
-							Distribution distribution = CdmBase.deproxy(el, Distribution.class);
-							NamedArea area = distribution.getArea();
-							for(NamedArea selectedArea:selectedAreas){
-								if(selectedArea.getUuid().equals(area.getUuid())){
-									filteredNodes.add(node);
-								}
-							}
-						}
-					}
-				}
-			}
-		}else{
-			filteredNodes = allNodes;
-		}
-		return filteredNodes;
-	}
-
-	/**
-	 * handles misapplied {@link Taxon}
-	 * @param taxon
-	 * @param writer
-	 * @param classification
-	 * @param metaRecord
-	 * @param config
-	 */
-	private void handleMisapplication(Taxon taxon, PrintWriter writer, Classification classification, CsvTaxRecordRedlist record, CsvTaxExportConfiguratorRedlist config) {
-		Set<Taxon> misappliedNames = taxon.getMisappliedNames();
-		for (Taxon misappliedName : misappliedNames ){
-//			CsvTaxRecordRedlist record = new CsvTaxRecordRedlist(metaRecord, config);
-			TaxonRelationshipType relType = TaxonRelationshipType.MISAPPLIED_NAME_FOR();
-			NonViralName<?> name = CdmBase.deproxy(misappliedName.getName(), NonViralName.class);
-		
-			if (! this.recordExists(misappliedName)){
-				handleTaxonBase(record, misappliedName, name, taxon, classification, relType, false, false, config);
-				record.write(writer);
-				this.addExistingRecord(misappliedName);
-			}
-		}	
-	}
-
-	/**
-	 * handles the information record for the actual {@link Taxon} including {@link Classification classification}, Taxon Name, Taxon ID,
-	 * Taxon Status, Synonyms, {@link Feature features} data 
-	 * @param record the concrete information record
-	 * @param taxonBase {@link Taxon}
-	 * @param name
-	 * @param acceptedTaxon
-	 * @param parent
-	 * @param basionym
-	 * @param isPartial 
-	 * @param isProParte 
-	 * @param config 
-	 * @param type
-	 */
-	private void handleTaxonBase(CsvTaxRecordRedlist record,TaxonBase<?> taxonBase,
-			NonViralName<?> name, Taxon acceptedTaxon, Classification classification, 
-			RelationshipTermBase<?> relType, boolean isProParte, boolean isPartial, 
-			CsvTaxExportConfiguratorRedlist config) {
-		
-		List<Feature> features = config.getFeatures();
-		record.setHeadLinePrinted(config.isHasHeaderLines());
-		if(features != null)record.setPrintFeatures(features);
-		config.setHasHeaderLines(false);
-
-		record.setDatasetName(classification.getTitleCache());
-		record.setScientificName(name.getTitleCache());
-		record.setScientificNameId(name.getUuid().toString());
-		handleTaxonomicStatus(record, name, relType, isProParte, isPartial);
-		//synonyms
-		handleSynonyms(record,(Taxon) taxonBase);
-		//distribution
-		handleDiscriptionData(record, (Taxon) taxonBase);
-		if(features!= null) {
-			
-			List<List<String>> featureCells = new ArrayList<List<String>>(features.size());
-			for(int i = 0; i < features.size(); i++) {
-				featureCells.add(new ArrayList<String>());
-			}
-			handleRelatedRedlistStatus(record, (Taxon)taxonBase, false, featureCells, features);
-			handleRelatedRedlistStatus(record, (Taxon)taxonBase, true, featureCells, features);
-
-		}
-		return;
-	}
-
-	private void handleTaxonomicStatus(
-			CsvTaxRecordRedlist record,
-			NonViralName<?> name, 
-			RelationshipTermBase<?> type,
-			boolean isProParte,
-			boolean isPartial) {
-		if (type == null){
-			record.setTaxonomicStatus(name.getNomenclaturalCode().acceptedTaxonStatusLabel());
-		}else{
-			String status = name.getNomenclaturalCode().synonymStatusLabel();
-			if (type.equals(SynonymRelationshipType.HETEROTYPIC_SYNONYM_OF())){
-				status = "heterotypicSynonym";
-			}else if(type.equals(SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF())){
-				status = "homotypicSynonym";
-			}else if(type.equals(TaxonRelationshipType.MISAPPLIED_NAME_FOR())){
-				status = "misapplied";
-			}
-			if (isProParte){
-				status = "proParteSynonym";
-			}else if (isPartial){
-				String message = "Partial synonym is not part of the gbif toxonomic status vocabulary";
-				logger.warn(message);
-				status = "partialSynonym";
-			}
-			
-			record.setTaxonomicStatus(status);
-		}
-	}
-
-	private void handleSynonyms(CsvTaxRecordRedlist record, Taxon taxon) {
-		
-		Set<SynonymRelationship> synRels = taxon.getSynonymRelations();
-		ArrayList<String> synonyms = new ArrayList<String>(); 
-		for (SynonymRelationship synRel :synRels ){
-			Synonym synonym = synRel.getSynonym();
-			SynonymRelationshipType type = synRel.getType();
-			if (type == null){ // should not happen
-				type = SynonymRelationshipType.SYNONYM_OF();
-			}
-			NonViralName<?> name = CdmBase.deproxy(synonym.getName(), NonViralName.class);
-			synonyms.add(name.getTitleCache());
-		}
-		record.setSynonyms(synonyms);
-	}
-
-	private void handleDiscriptionData(CsvTaxRecordRedlist record, Taxon taxon) {
-		
-		Set<TaxonDescription> descriptions = taxon.getDescriptions();
-		ArrayList<String> distributions = new ArrayList<String>();
-		for (TaxonDescription description : descriptions){
-			for (DescriptionElementBase el : description.getElements()){
-				if (el.isInstanceOf(Distribution.class) ){
-						Distribution distribution = CdmBase.deproxy(el, Distribution.class);
-						NamedArea area = distribution.getArea();
-						distributions.add(area.getTitleCache());
-				}
-
-			}
-		}
-		record.setCountryCode(distributions);
-	}
-
-	private void handleRedlistStatus(CsvTaxRecordRedlist record, Taxon taxon, List<List<String>> featureCells, List<Feature> features){
-		Set<TaxonDescription> descriptions = taxon.getDescriptions();
-
-		for (TaxonDescription description : descriptions){
-			for (DescriptionElementBase el : description.getElements()){
-				if(el.isInstanceOf(CategoricalData.class)){
-					CategoricalData categoricalData = CdmBase.deproxy(el, CategoricalData.class);
-					for(State state:categoricalData.getStatesOnly()){
-						Feature stateFeature = categoricalData.getFeature();
-						// find matching feature and put data into according cell
-						for(int i = 0; i < features.size(); i++) {
-							if(features.get(i).equals(stateFeature)){
-								List<String> cell = featureCells.get(i);
-								cell.add(state.toString());
-							}
-						}
-					}
-				}else if(el.isInstanceOf(TextData.class)){
-					TextData textData = CdmBase.deproxy(el, TextData.class);
-					Feature textFeature = textData.getFeature();
-					// find matching feature and put data into according cell
-					for(int i = 0; i < features.size(); i++) {
-						if(features.get(i).equals(textFeature)){
-							List<String> cell = featureCells.get(i);
-							String text = textData.getText(Language.GERMAN());
-							text = text.replaceAll(System.getProperty("line.separator"), "");
-							text = text.replaceAll("                            ", " ");
-							cell.add(text);
-							
-						}
-					}
-				}
-			}
-		}
-		record.setFeatures(featureCells);
-	}
-
-
-	private void handleRelatedRedlistStatus(CsvTaxRecordRedlist record, Taxon taxon, boolean relationFrom, List<List<String>> featureCells, List<Feature> features) {
-
-		if (relationFrom)handleRedlistStatus(record, taxon, featureCells, features);
-		
-		
-		Set<TaxonRelationship> taxRels;
-		if(relationFrom){
-			taxRels = taxon.getRelationsFromThisTaxon();
-		}else{
-			taxRels = taxon.getRelationsToThisTaxon();
-		}
-		for (TaxonRelationship taxRel:taxRels){
-			if(taxRel.getType().equals(TaxonRelationshipType.CONGRUENT_TO())){
-				Taxon relatedTaxon;
-				if(relationFrom){
-					relatedTaxon = taxRel.getToTaxon();
-				}else{
-					relatedTaxon = taxRel.getFromTaxon();
-				}
-				handleRedlistStatus(record, relatedTaxon, featureCells, features);
-			}
-		}
-	}
-
-	@Override
-	protected boolean doCheck(CsvTaxExportStateRedlist state) {
-		boolean result = true;
-		logger.warn("No check implemented for " + this.ioName);
-		return result;
-	}
-
-	@Override
-	protected boolean isIgnore(CsvTaxExportStateRedlist state) {
-		return ! state.getConfig().isDoTaxa();
-	}
-	
-}
+/**
+* Copyright (C) 2007 EDIT
+* European Distributed Institute of Taxonomy 
+* http://www.e-taxonomy.eu
+* 
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+
+package eu.etaxonomy.cdm.io.csv.redlist.out;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.TransactionStatus;
+
+import eu.etaxonomy.cdm.model.common.CdmBase;
+import eu.etaxonomy.cdm.model.common.Language;
+import eu.etaxonomy.cdm.model.common.RelationshipTermBase;
+import eu.etaxonomy.cdm.model.description.CategoricalData;
+import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
+import eu.etaxonomy.cdm.model.description.Distribution;
+import eu.etaxonomy.cdm.model.description.Feature;
+import eu.etaxonomy.cdm.model.description.State;
+import eu.etaxonomy.cdm.model.description.TaxonDescription;
+import eu.etaxonomy.cdm.model.description.TextData;
+import eu.etaxonomy.cdm.model.location.NamedArea;
+import eu.etaxonomy.cdm.model.name.NonViralName;
+import eu.etaxonomy.cdm.model.taxon.Classification;
+import eu.etaxonomy.cdm.model.taxon.Synonym;
+import eu.etaxonomy.cdm.model.taxon.SynonymRelationship;
+import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType;
+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.taxon.TaxonRelationshipType;
+
+
+/**
+ * @author a.oppermann
+ * @created 18.10.2012
+ */
+
+@Component
+public class CsvTaxExportRedlist extends CsvExportBaseRedlist {
+	private static final Logger logger = Logger.getLogger(CsvTaxExportRedlist.class);
+
+	private static final String ROW_TYPE = "http://rs.tdwg.org/dwc/terms/Taxon";
+	private static final String fileName = "RedlistCoreTax.csv";
+
+	public CsvTaxExportRedlist() {
+		super();
+		this.ioName = this.getClass().getSimpleName();
+	}
+	
+
+	/** Retrieves data from a CDM DB and serializes them CDM to CSV.
+	 * Starts with root taxa and traverses the classification to retrieve 
+	 * children taxa, synonyms, relationships, descriptive data, red list 
+	 * status (features). 
+	 * Taxa that are not part of the classification are not found.
+	 * 
+	 * @param exImpConfig
+	 * @param dbname
+	 * @param filename
+	 */
+	@Override
+	protected void doInvoke(CsvTaxExportStateRedlist state){
+		CsvTaxExportConfiguratorRedlist config = state.getConfig();
+		TransactionStatus txStatus = startTransaction(true);
+		List<NamedArea> selectedAreas = config.getNamedAreas();
+		Set<TaxonNode> taxonNodes = assembleTaxonNodeSet(config);
+		
+		PrintWriter writer = null;
+		ByteArrayOutputStream byteArrayOutputStream;
+		try {
+			byteArrayOutputStream = config.getByteArrayOutputStream();
+			writer = new PrintWriter(byteArrayOutputStream); 
+			//geographical Filter
+			List<TaxonNode> filteredNodes = handleGeographicalFilter(selectedAreas, taxonNodes);
+			
+			//sorting List
+			Collections.sort(filteredNodes, new Comparator<TaxonNode>() {
+
+				@Override
+				public int compare(TaxonNode tn1, TaxonNode tn2) {
+					Taxon taxon1 = tn1.getTaxon();
+					Taxon taxon2 = tn2.getTaxon();
+					if(taxon1 != null && taxon2 != null){
+						return taxon1.getTitleCache().compareTo(taxon2.getTitleCache());
+					}
+					else{
+						return 0;
+					}
+				}
+			});
+			for (TaxonNode node : filteredNodes){
+				Taxon taxon = CdmBase.deproxy(node.getTaxon(), Taxon.class);
+				CsvTaxRecordRedlist record = assembleRecord(state);
+				NonViralName<?> name = CdmBase.deproxy(taxon.getName(), NonViralName.class);
+				Classification classification = node.getClassification();
+				config.setClassificationTitleCache(classification.getTitleCache());	
+				if (! this.recordExists(taxon)){
+					handleTaxonBase(record, taxon, name, taxon, classification, null, false, false, config);
+					record.write(writer);
+					this.addExistingRecord(taxon);
+				}
+				//misapplied names
+				handleMisapplication(taxon, writer, classification, record, config);
+				writer.flush();
+			}
+		} catch (ClassCastException e) {
+			e.printStackTrace();
+		}
+		finally{
+			writer.close();
+			this.clearExistingRecordIds();
+		}
+		commitTransaction(txStatus);
+		return;
+
+	}
+	
+	
+	//TODO: Exception handling
+	protected Set<TaxonNode> assembleTaxonNodeSet(CsvTaxExportConfiguratorRedlist config){
+		Set<TaxonNode> taxonNodes = new HashSet<>();
+		if(config != null){
+			Set<UUID> taxonNodeUuidSet = config.getTaxonNodeUuids();
+			taxonNodes.addAll(getTaxonNodeService().find(taxonNodeUuidSet));
+		}
+		return taxonNodes;
+	}
+
+	//TODO: Exception handling
+	private CsvTaxRecordRedlist assembleRecord(CsvTaxExportStateRedlist state) {
+		if(state!=null){
+			CsvTaxExportConfiguratorRedlist config = state.getConfig();
+			CsvMetaDataRecordRedlist metaRecord = new CsvMetaDataRecordRedlist(true, fileName, ROW_TYPE);
+			state.addMetaRecord(metaRecord);
+			CsvTaxRecordRedlist record = new CsvTaxRecordRedlist(metaRecord, config);
+			return record;
+		}
+		return null;
+	}
+
+	/**
+	 * Takes positive List of areas and iterates over a given taxon node 
+	 * and their {@link Taxon} to return all {@link Taxon} with the desired 
+	 * geographical attribute.
+	 * 
+	 * <p><p>
+	 *
+	 * If selectedAreas is null all child {@link TaxonNode}s of the given taxon node will be returned.
+	 * 
+	 * @param selectedAreas 
+	 * @param taxonNodes
+	 * @return
+	 */
+	protected List<TaxonNode> handleGeographicalFilter(List<NamedArea> selectedAreas,
+			Set<TaxonNode> taxonNodes) {
+		List<TaxonNode> filteredNodes = new ArrayList<TaxonNode>();
+		List<TaxonNode> allNodes =  new ArrayList(getAllNodes(taxonNodes));
+		//Geographical filter
+		logger.info(selectedAreas.size());
+		if(selectedAreas != null && !selectedAreas.isEmpty() && selectedAreas.size() < 16){
+//				if(selectedAreas.size() == 16){
+//					//Germany TDWG Level 3
+//					String germany="uu7b7c2db5-aa44-4302-bdec-6556fd74b0b9id";
+//					selectedAreas.add((NamedArea) getTermService().find(UUID.fromString(germany)));
+//				}
+			for (TaxonNode node : allNodes){
+				Taxon taxon = CdmBase.deproxy(node.getTaxon(), Taxon.class);
+				Set<TaxonDescription> descriptions = taxon.getDescriptions();
+				for (TaxonDescription description : descriptions){
+					for (DescriptionElementBase el : description.getElements()){
+						if (el.isInstanceOf(Distribution.class) ){
+							Distribution distribution = CdmBase.deproxy(el, Distribution.class);
+							NamedArea area = distribution.getArea();
+							for(NamedArea selectedArea:selectedAreas){
+								if(selectedArea.getUuid().equals(area.getUuid())){
+									filteredNodes.add(node);
+								}
+							}
+						}
+					}
+				}
+			}
+		}else{
+			filteredNodes = allNodes;
+		}
+		return filteredNodes;
+	}
+
+	/**
+	 * handles misapplied {@link Taxon}
+	 * @param taxon
+	 * @param writer
+	 * @param classification
+	 * @param metaRecord
+	 * @param config
+	 */
+	private void handleMisapplication(Taxon taxon, PrintWriter writer, Classification classification, CsvTaxRecordRedlist record, CsvTaxExportConfiguratorRedlist config) {
+		Set<Taxon> misappliedNames = taxon.getMisappliedNames();
+		for (Taxon misappliedName : misappliedNames ){
+//			CsvTaxRecordRedlist record = new CsvTaxRecordRedlist(metaRecord, config);
+			TaxonRelationshipType relType = TaxonRelationshipType.MISAPPLIED_NAME_FOR();
+			NonViralName<?> name = CdmBase.deproxy(misappliedName.getName(), NonViralName.class);
+		
+			if (! this.recordExists(misappliedName)){
+				handleTaxonBase(record, misappliedName, name, taxon, classification, relType, false, false, config);
+				record.write(writer);
+				this.addExistingRecord(misappliedName);
+			}
+		}	
+	}
+
+	/**
+	 * handles the information record for the actual {@link Taxon} including {@link Classification classification}, Taxon Name, Taxon ID,
+	 * Taxon Status, Synonyms, {@link Feature features} data 
+	 * @param record the concrete information record
+	 * @param taxonBase {@link Taxon}
+	 * @param name
+	 * @param acceptedTaxon
+	 * @param parent
+	 * @param basionym
+	 * @param isPartial 
+	 * @param isProParte 
+	 * @param config 
+	 * @param type
+	 */
+	private void handleTaxonBase(CsvTaxRecordRedlist record,TaxonBase<?> taxonBase,
+			NonViralName<?> name, Taxon acceptedTaxon, Classification classification, 
+			RelationshipTermBase<?> relType, boolean isProParte, boolean isPartial, 
+			CsvTaxExportConfiguratorRedlist config) {
+		
+		List<Feature> features = config.getFeatures();
+		record.setHeadLinePrinted(config.isHasHeaderLines());
+		if(features != null)record.setPrintFeatures(features);
+		config.setHasHeaderLines(false);
+
+		record.setDatasetName(classification.getTitleCache());
+		record.setScientificName(name.getTitleCache());
+		record.setScientificNameId(name.getUuid().toString());
+		handleTaxonomicStatus(record, name, relType, isProParte, isPartial);
+		//synonyms
+		handleSynonyms(record,(Taxon) taxonBase);
+		//distribution
+		handleDiscriptionData(record, (Taxon) taxonBase);
+		if(features!= null) {
+			
+			List<List<String>> featureCells = new ArrayList<List<String>>(features.size());
+			for(int i = 0; i < features.size(); i++) {
+				featureCells.add(new ArrayList<String>());
+			}
+			handleRelatedRedlistStatus(record, (Taxon)taxonBase, false, featureCells, features);
+			handleRelatedRedlistStatus(record, (Taxon)taxonBase, true, featureCells, features);
+
+		}
+		return;
+	}
+
+	private void handleTaxonomicStatus(
+			CsvTaxRecordRedlist record,
+			NonViralName<?> name, 
+			RelationshipTermBase<?> type,
+			boolean isProParte,
+			boolean isPartial) {
+		if (type == null){
+			record.setTaxonomicStatus(name.getNomenclaturalCode().acceptedTaxonStatusLabel());
+		}else{
+			String status = name.getNomenclaturalCode().synonymStatusLabel();
+			if (type.equals(SynonymRelationshipType.HETEROTYPIC_SYNONYM_OF())){
+				status = "heterotypicSynonym";
+			}else if(type.equals(SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF())){
+				status = "homotypicSynonym";
+			}else if(type.equals(TaxonRelationshipType.MISAPPLIED_NAME_FOR())){
+				status = "misapplied";
+			}
+			if (isProParte){
+				status = "proParteSynonym";
+			}else if (isPartial){
+				String message = "Partial synonym is not part of the gbif toxonomic status vocabulary";
+				logger.warn(message);
+				status = "partialSynonym";
+			}
+			
+			record.setTaxonomicStatus(status);
+		}
+	}
+
+	private void handleSynonyms(CsvTaxRecordRedlist record, Taxon taxon) {
+		
+		Set<SynonymRelationship> synRels = taxon.getSynonymRelations();
+		ArrayList<String> synonyms = new ArrayList<String>(); 
+		for (SynonymRelationship synRel :synRels ){
+			Synonym synonym = synRel.getSynonym();
+			SynonymRelationshipType type = synRel.getType();
+			if (type == null){ // should not happen
+				type = SynonymRelationshipType.SYNONYM_OF();
+			}
+			NonViralName<?> name = CdmBase.deproxy(synonym.getName(), NonViralName.class);
+			synonyms.add(name.getTitleCache());
+		}
+		record.setSynonyms(synonyms);
+	}
+
+	private void handleDiscriptionData(CsvTaxRecordRedlist record, Taxon taxon) {
+		
+		Set<TaxonDescription> descriptions = taxon.getDescriptions();
+		ArrayList<String> distributions = new ArrayList<String>();
+		for (TaxonDescription description : descriptions){
+			for (DescriptionElementBase el : description.getElements()){
+				if (el.isInstanceOf(Distribution.class) ){
+						Distribution distribution = CdmBase.deproxy(el, Distribution.class);
+						NamedArea area = distribution.getArea();
+						distributions.add(area.getTitleCache());
+				}
+
+			}
+		}
+		record.setCountryCode(distributions);
+	}
+
+	private void handleRedlistStatus(CsvTaxRecordRedlist record, Taxon taxon, List<List<String>> featureCells, List<Feature> features){
+		Set<TaxonDescription> descriptions = taxon.getDescriptions();
+
+		for (TaxonDescription description : descriptions){
+			for (DescriptionElementBase el : description.getElements()){
+				if(el.isInstanceOf(CategoricalData.class)){
+					CategoricalData categoricalData = CdmBase.deproxy(el, CategoricalData.class);
+					for(State state:categoricalData.getStatesOnly()){
+						Feature stateFeature = categoricalData.getFeature();
+						// find matching feature and put data into according cell
+						for(int i = 0; i < features.size(); i++) {
+							if(features.get(i).equals(stateFeature)){
+								List<String> cell = featureCells.get(i);
+								cell.add(state.toString());
+							}
+						}
+					}
+				}else if(el.isInstanceOf(TextData.class)){
+					TextData textData = CdmBase.deproxy(el, TextData.class);
+					Feature textFeature = textData.getFeature();
+					// find matching feature and put data into according cell
+					for(int i = 0; i < features.size(); i++) {
+						if(features.get(i).equals(textFeature)){
+							List<String> cell = featureCells.get(i);
+							String text = textData.getText(Language.GERMAN());
+							text = text.replaceAll(System.getProperty("line.separator"), "");
+							text = text.replaceAll("                            ", " ");
+							cell.add(text);
+							
+						}
+					}
+				}
+			}
+		}
+		record.setFeatures(featureCells);
+	}
+
+
+	private void handleRelatedRedlistStatus(CsvTaxRecordRedlist record, Taxon taxon, boolean relationFrom, List<List<String>> featureCells, List<Feature> features) {
+
+		if (relationFrom)handleRedlistStatus(record, taxon, featureCells, features);
+		
+		
+		Set<TaxonRelationship> taxRels;
+		if(relationFrom){
+			taxRels = taxon.getRelationsFromThisTaxon();
+		}else{
+			taxRels = taxon.getRelationsToThisTaxon();
+		}
+		for (TaxonRelationship taxRel:taxRels){
+			if(taxRel.getType().equals(TaxonRelationshipType.CONGRUENT_TO())){
+				Taxon relatedTaxon;
+				if(relationFrom){
+					relatedTaxon = taxRel.getToTaxon();
+				}else{
+					relatedTaxon = taxRel.getFromTaxon();
+				}
+				handleRedlistStatus(record, relatedTaxon, featureCells, features);
+			}
+		}
+	}
+
+	@Override
+	protected boolean doCheck(CsvTaxExportStateRedlist state) {
+		boolean result = true;
+		logger.warn("No check implemented for " + this.ioName);
+		return result;
+	}
+
+	@Override
+	protected boolean isIgnore(CsvTaxExportStateRedlist state) {
+		return ! state.getConfig().isDoTaxa();
+	}
+	
+}
diff --git a/cdmlib-remote/src/main/java/eu/etaxonomy/cdm/remote/controller/checklist/CsvExportController.java b/cdmlib-remote/src/main/java/eu/etaxonomy/cdm/remote/controller/checklist/CsvExportController.java
index 61079870da..5ba3614b37 100644
--- a/cdmlib-remote/src/main/java/eu/etaxonomy/cdm/remote/controller/checklist/CsvExportController.java
+++ b/cdmlib-remote/src/main/java/eu/etaxonomy/cdm/remote/controller/checklist/CsvExportController.java
@@ -1,184 +1,185 @@
-/**
-* Copyright (C) 2009 EDIT
-* European Distributed Institute of Taxonomy 
-* http://www.e-taxonomy.eu
-* 
-* The contents of this file are subject to the Mozilla Public License Version 1.1
-* See LICENSE.TXT at the top of this package for the full license terms.
-*/
-package eu.etaxonomy.cdm.remote.controller.checklist;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.InputStreamReader;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-import java.util.UUID;
-
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.log4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.propertyeditors.UUIDEditor;
-import org.springframework.context.ApplicationContext;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.WebDataBinder;
-import org.springframework.web.bind.annotation.InitBinder;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
-
-import eu.etaxonomy.cdm.api.service.IService;
-import eu.etaxonomy.cdm.api.service.ITermService;
-import eu.etaxonomy.cdm.io.common.CdmApplicationAwareDefaultExport;
-import eu.etaxonomy.cdm.io.csv.redlist.out.CsvTaxExportConfiguratorRedlist;
-import eu.etaxonomy.cdm.model.description.Feature;
-import eu.etaxonomy.cdm.model.location.NamedArea;
-import eu.etaxonomy.cdm.model.taxon.Classification;
-import eu.etaxonomy.cdm.model.taxon.Taxon;
-import eu.etaxonomy.cdm.remote.controller.AbstractController;
-import eu.etaxonomy.cdm.remote.controller.ProgressMonitorController;
-import eu.etaxonomy.cdm.remote.editor.UUIDListPropertyEditor;
-import eu.etaxonomy.cdm.remote.editor.UuidList;
-
-/**
- * @author a.oppermann
- * @created 20.09.2012
- * 
- */
-@Controller
-@RequestMapping(value = { "/csv" })
-public class CsvExportController extends AbstractController{
-
-	/**
-	 * 
-	 */
-	@Autowired
-	private ApplicationContext appContext;
-	
-	@Autowired 
-	private ITermService termService;
-	
-	@Autowired
-	public ProgressMonitorController progressMonitorController;
-	
-	private static final Logger logger = Logger.getLogger(CsvExportController.class);
-	
-	/**
-	 * Helper method, which allows to convert strings directly into uuids.
-	 * 
-	 * @param binder Special DataBinder for data binding from web request parameters to JavaBean objects.
-	 */
-    @InitBinder
-    public void initBinder(WebDataBinder binder) {
-        binder.registerCustomEditor(UuidList.class, new UUIDListPropertyEditor());
-//        binder.registerCustomEditor(NamedArea.class, new NamedAreaPropertyEditor());
-        binder.registerCustomEditor(UUID.class, new UUIDEditor());
-    }
-
-    /**
-     * Fetches data from the application context and forwards the stream to the HttpServletResponse, which offers a file download.
-     *
-     * @param featureUuids List of uuids to download/select {@link Feature feature}features
-     * @param taxonNodeUuid Selected {@link Classification classification} to iterate the {@link Taxon}
-     * @param response HttpServletResponse which returns the ByteArrayOutputStream
-     */
-	@RequestMapping(value = { "exportRedlist" }, method = { RequestMethod.POST })
-	public void doExportRedlist(
-			@RequestParam(value = "features", required = false) UuidList featureUuids,
-			@RequestParam(value = "taxonNode", required = false) String taxonNodeUuid,
-            @RequestParam(value = "area", required = false) UuidList areas,
-			@RequestParam(value = "downloadTokenValueId", required = false) String downloadTokenValueId,
-			HttpServletResponse response,
-			HttpServletRequest request) {
-		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
-		CsvTaxExportConfiguratorRedlist config = setTaxExportConfigurator(taxonNodeUuid, featureUuids, areas, byteArrayOutputStream);
-		CdmApplicationAwareDefaultExport<?> defaultExport = (CdmApplicationAwareDefaultExport<?>) appContext.getBean("defaultExport");
-		logger.info("Start export...");
-		logger.info("doExportRedlist()" + requestPathAndQuery(request));
-		defaultExport.invoke(config);
-		try {
-			/*
-			 *  Fetch data from the appContext and forward stream to HttpServleResponse
-			 *  
-			 *  FIXME: Large Data could be out of memory
-			 *  
-			 *  HTPP Error Break
-			 */
-			ByteArrayInputStream bais = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());//byteArrayOutputStream.toByteArray()
-			InputStreamReader isr = new InputStreamReader(bais);
-			Cookie progressCookie = new Cookie("fileDownloadToken", downloadTokenValueId);
-			progressCookie.setPath("/");
-			progressCookie.setMaxAge(60);
-			response.addCookie(progressCookie);
-			response.setContentType("text/csv; charset=utf-8");
-			response.setHeader("Content-Disposition", "attachment; filename=\""+config.getClassificationTitleCache()+".txt\"");
-			PrintWriter printWriter = response.getWriter();
-
-			int i;
-			while((i = isr.read())!= -1){
-				printWriter.write(i);
-			}
-			byteArrayOutputStream.flush();
-			isr.close();
-			byteArrayOutputStream.close();
-			printWriter.flush();
-			printWriter.close();
-		} catch (Exception e) {
-			logger.error("error generating feed", e);
-		}
-	}
-
-	/**
-	 * Cofiguration method to set the configuration details for the defaultExport in the application context.
-	 * 
-	 * @param taxonNodeUuid pass-through the selected {@link Classification classification}
-	 * @param featureUuids pass-through the selected {@link Feature feature} of a {@link Taxon}, in order to fetch it.
-	 * @param areas 
-	 * @param byteArrayOutputStream pass-through the stream to write out the data later.
-	 * @return the CsvTaxExportConfiguratorRedlist config
-	 */
-	private CsvTaxExportConfiguratorRedlist setTaxExportConfigurator(String taxonNodeUuid, UuidList featureUuids, UuidList areas, ByteArrayOutputStream byteArrayOutputStream) {
-
-		@SuppressWarnings({ "unchecked", "rawtypes" })
-		Set<UUID> taxonNodeUuids = java.util.Collections.singleton(UUID.fromString(taxonNodeUuid)); 
-		String destination = System.getProperty("java.io.tmpdir");
-		List<Feature> features = new ArrayList<Feature>();
-		if(featureUuids != null){
-			for(UUID uuid : featureUuids) {
-				features.add((Feature) termService.find(uuid));
-			}
-		}
-		List<NamedArea> selectedAreas = new ArrayList<NamedArea>();
-		if(areas != null){
-			for(UUID area:areas){
-				logger.info(area);
-				selectedAreas.add((NamedArea)termService.find(area));
-			}
-		}
-
-		CsvTaxExportConfiguratorRedlist config = CsvTaxExportConfiguratorRedlist.NewInstance(null, new File(destination));
-		config.setHasHeaderLines(true);
-		config.setFieldsTerminatedBy("\t");
-		config.setTaxonNodeUuids(taxonNodeUuids);
-		config.setByteArrayOutputStream(byteArrayOutputStream);
-		if(features != null)config.setFeatures(features);
-        config.setNamedAreas(selectedAreas);
-		return config;
-	}
-	
-	/* (non-Javadoc)
-	 * @see eu.etaxonomy.cdm.remote.controller.AbstractController#setService(eu.etaxonomy.cdm.api.service.IService)
-	 */
-	@Override
-	public void setService(IService service) {
-		// TODO Auto-generated method stub
-		
-	}
-	
+/**
+* Copyright (C) 2009 EDIT
+* European Distributed Institute of Taxonomy 
+* http://www.e-taxonomy.eu
+* 
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.cdm.remote.controller.checklist;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.propertyeditors.UUIDEditor;
+import org.springframework.context.ApplicationContext;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.WebDataBinder;
+import org.springframework.web.bind.annotation.InitBinder;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import eu.etaxonomy.cdm.api.service.IService;
+import eu.etaxonomy.cdm.api.service.ITermService;
+import eu.etaxonomy.cdm.io.common.CdmApplicationAwareDefaultExport;
+import eu.etaxonomy.cdm.io.csv.redlist.out.CsvTaxExportConfiguratorRedlist;
+import eu.etaxonomy.cdm.model.description.Feature;
+import eu.etaxonomy.cdm.model.location.NamedArea;
+import eu.etaxonomy.cdm.model.taxon.Classification;
+import eu.etaxonomy.cdm.model.taxon.Taxon;
+import eu.etaxonomy.cdm.remote.controller.AbstractController;
+import eu.etaxonomy.cdm.remote.controller.ProgressMonitorController;
+import eu.etaxonomy.cdm.remote.editor.UUIDListPropertyEditor;
+import eu.etaxonomy.cdm.remote.editor.UuidList;
+
+/**
+ * @author a.oppermann
+ * @created 20.09.2012
+ * 
+ */
+@Controller
+@RequestMapping(value = { "/csv" })
+public class CsvExportController extends AbstractController{
+
+	/**
+	 * 
+	 */
+	@Autowired
+	private ApplicationContext appContext;
+	
+	@Autowired 
+	private ITermService termService;
+	
+	@Autowired
+	public ProgressMonitorController progressMonitorController;
+	
+	private static final Logger logger = Logger.getLogger(CsvExportController.class);
+	
+	/**
+	 * Helper method, which allows to convert strings directly into uuids.
+	 * 
+	 * @param binder Special DataBinder for data binding from web request parameters to JavaBean objects.
+	 */
+    @InitBinder
+    public void initBinder(WebDataBinder binder) {
+        binder.registerCustomEditor(UuidList.class, new UUIDListPropertyEditor());
+//        binder.registerCustomEditor(NamedArea.class, new NamedAreaPropertyEditor());
+        binder.registerCustomEditor(UUID.class, new UUIDEditor());
+    }
+
+    /**
+     * Fetches data from the application context and forwards the stream to the HttpServletResponse, which offers a file download.
+     *
+     * @param featureUuids List of uuids to download/select {@link Feature feature}features
+     * @param taxonNodeUuid Selected {@link Classification classification} to iterate the {@link Taxon}
+     * @param response HttpServletResponse which returns the ByteArrayOutputStream
+     */
+	@RequestMapping(value = { "exportRedlist" }, method = { RequestMethod.POST })
+	public void doExportRedlist(
+			@RequestParam(value = "features", required = false) UuidList featureUuids,
+			@RequestParam(value = "taxonNode", required = false) String taxonNodeUuid,
+            @RequestParam(value = "area", required = false) UuidList areas,
+			@RequestParam(value = "downloadTokenValueId", required = false) String downloadTokenValueId,
+			HttpServletResponse response,
+			HttpServletRequest request) {
+		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+		CsvTaxExportConfiguratorRedlist config = setTaxExportConfigurator(taxonNodeUuid, featureUuids, areas, byteArrayOutputStream);
+		CdmApplicationAwareDefaultExport<?> defaultExport = (CdmApplicationAwareDefaultExport<?>) appContext.getBean("defaultExport");
+		logger.info("Start export...");
+		logger.info("doExportRedlist()" + requestPathAndQuery(request));
+		defaultExport.invoke(config);
+		try {
+			/*
+			 *  Fetch data from the appContext and forward stream to HttpServleResponse
+			 *  
+			 *  FIXME: Large Data could be out of memory
+			 *  
+			 *  HTPP Error Break
+			 */
+			ByteArrayInputStream bais = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());//byteArrayOutputStream.toByteArray()
+			InputStreamReader isr = new InputStreamReader(bais);
+			Cookie progressCookie = new Cookie("fileDownloadToken", downloadTokenValueId);
+			progressCookie.setPath("/");
+			progressCookie.setMaxAge(60);
+			response.addCookie(progressCookie);
+			response.setContentType("text/csv; charset=utf-8");
+			response.setHeader("Content-Disposition", "attachment; filename=\""+config.getClassificationTitleCache()+".txt\"");
+			PrintWriter printWriter = response.getWriter();
+
+			int i;
+			while((i = isr.read())!= -1){
+				printWriter.write(i);
+			}
+			byteArrayOutputStream.flush();
+			isr.close();
+			byteArrayOutputStream.close();
+			printWriter.flush();
+			printWriter.close();
+		} catch (Exception e) {
+			logger.error("error generating feed", e);
+		}
+	}
+
+	/**
+	 * Cofiguration method to set the configuration details for the defaultExport in the application context.
+	 * 
+	 * @param taxonNodeUuid pass-through the selected {@link Classification classification}
+	 * @param featureUuids pass-through the selected {@link Feature feature} of a {@link Taxon}, in order to fetch it.
+	 * @param areas 
+	 * @param byteArrayOutputStream pass-through the stream to write out the data later.
+	 * @return the CsvTaxExportConfiguratorRedlist config
+	 */
+	private CsvTaxExportConfiguratorRedlist setTaxExportConfigurator(String taxonNodeUuid, UuidList featureUuids, UuidList areas, ByteArrayOutputStream byteArrayOutputStream) {
+
+		@SuppressWarnings({ "unchecked", "rawtypes" })
+		Set<UUID> taxonNodeUuids = Collections.singleton(UUID.fromString(taxonNodeUuid)); 
+		String destination = System.getProperty("java.io.tmpdir");
+		List<Feature> features = new ArrayList<Feature>();
+		if(featureUuids != null){
+			for(UUID uuid : featureUuids) {
+				features.add((Feature) termService.find(uuid));
+			}
+		}
+		List<NamedArea> selectedAreas = new ArrayList<NamedArea>();
+		if(areas != null){
+			for(UUID area:areas){
+				logger.info(area);
+				selectedAreas.add((NamedArea)termService.find(area));
+			}
+		}
+
+		CsvTaxExportConfiguratorRedlist config = CsvTaxExportConfiguratorRedlist.NewInstance(null, new File(destination));
+		config.setHasHeaderLines(true);
+		config.setFieldsTerminatedBy("\t");
+		config.setTaxonNodeUuids(taxonNodeUuids);
+		config.setByteArrayOutputStream(byteArrayOutputStream);
+		if(features != null)config.setFeatures(features);
+        config.setNamedAreas(selectedAreas);
+		return config;
+	}
+	
+	/* (non-Javadoc)
+	 * @see eu.etaxonomy.cdm.remote.controller.AbstractController#setService(eu.etaxonomy.cdm.api.service.IService)
+	 */
+	@Override
+	public void setService(IService service) {
+		// TODO Auto-generated method stub
+		
+	}
+	
 }
\ No newline at end of file
