From 8df7f1d90df398b98059bac51a94d9ed6bdd562d Mon Sep 17 00:00:00 2001
From: srosse <none@none>
Date: Mon, 16 Oct 2017 11:38:37 +0200
Subject: [PATCH] OO-3070: add a utility method to convert a list of string in
 a CSV like string (patch S. Clemenz)

---
 .../java/org/olat/core/util/StringHelper.java | 84 +++++++------------
 .../statistic/export/LogLineConverter.java    |  4 +-
 .../org/olat/core/util/StringHelperTest.java  | 24 ++++++
 3 files changed, 56 insertions(+), 56 deletions(-)

diff --git a/src/main/java/org/olat/core/util/StringHelper.java b/src/main/java/org/olat/core/util/StringHelper.java
index 7be94fd659c..2cc3cedf322 100644
--- a/src/main/java/org/olat/core/util/StringHelper.java
+++ b/src/main/java/org/olat/core/util/StringHelper.java
@@ -35,6 +35,7 @@ import java.text.DecimalFormat;
 import java.text.DecimalFormatSymbols;
 import java.text.NumberFormat;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
@@ -42,7 +43,6 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
-import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -542,67 +542,44 @@ public class StringHelper {
 	}
 	
 	/**
-	 * set of strings to one string comma separated.<br>
+	 * Collection of strings to one string comma separated. This method doesn't do any escaping
+	 * and will never do escaping to be backwards compatible.<br>
 	 * e.g. ["a","b","c","s"] -> "a,b,c,s" 
 	 * @param selection
 	 * @return
 	 */
-	public static String formatAsCSVString(Set<String> entries) {
-		boolean isFirst = true;
-		String csvStr = null;
-		for (Iterator<String> iter = entries.iterator(); iter.hasNext();) {
-			String group = iter.next();
-			if (isFirst) {
-				csvStr = group;
-				isFirst = false;
-			} else {
-				csvStr += ", " + group;
+	public static String formatAsCSVString(Collection<String> entries) {
+		StringBuilder csv = new StringBuilder(256);
+		for (String group:entries) {
+			if (csv.length() > 0) {
+				csv.append(",");
 			}
+			csv.append(group);
 		}
-		return csvStr;
+		return csv.toString();
 	}
 	
 	/**
-	 * list of strings to one string comma separated.<br>
-	 * e.g. ["a","b","c","s"] -> "a,b,c,s" 
+	 * Collection of strings to one string comma separated. The method escaped
+	 * " and ,<br>
+	 * e.g. ["a","b,1","c","s"] -> "a,"b,1",c,s" 
 	 * @param selection
 	 * @return
 	 */
-	public static String formatAsCSVString(List<String> entries) {
-		boolean isFirst = true;
-		String csvStr = null;
-		for (Iterator<String> iter = entries.iterator(); iter.hasNext();) {
-			String group = iter.next();
-			if (isFirst) {
-				csvStr = group;
-				isFirst = false;
-			} else {
-				csvStr += ", " + group;
+	public static String formatAsEscapedCSVString(Collection<String> entries) {
+		StringBuilder csv = new StringBuilder(256);
+		for (String entry:entries) {
+			entry = entry.replace("\"", "\"\"");
+			if (entry.contains(",")) {
+				entry = "\"" + entry + "\"";  
 			}
+			
+			if (csv.length() > 0) {
+				csv.append(",");
+			}
+			csv.append(entry);
 		}
-		return csvStr;
-	}
-	
-	/**
-	 * list of strings to one string comma separated.<br>
-	 * e.g. ["z","a","b","c","s","a"] -> "a, b, c, s, z"
-	 * No duplicates, alphabetically sorted
-	 * @param selection
-	 * @return
-	 */
-	public static String formatAsSortUniqCSVString(List<String> s) {
-		
-		Map <String,String>u = new HashMap<String,String>();
-		for (Iterator <String> si = s.iterator(); si.hasNext();) {
-			u.put(si.next().trim(), null);
-		}
-		
-		List <String>rv = new ArrayList<String>();
-		rv.addAll(u.keySet());
-		rv.remove("");
-		Collections.sort(rv);
-		
-		return formatAsCSVString (rv);
+		return csv.toString();
 	}
 	
 	/**
@@ -612,18 +589,17 @@ public class StringHelper {
 	 * @param selection
 	 * @return
 	 */
-	public static String formatAsSortUniqCSVString(Set<String> s) {
-		
-		Map <String,String>u = new HashMap<String,String>();
-		for (Iterator <String> si = s.iterator(); si.hasNext();) {
+	public static String formatAsSortUniqCSVString(Collection<String> s) {
+		Map<String,String> u = new HashMap<>();
+		for (Iterator<String> si = s.iterator(); si.hasNext();) {
 			u.put(si.next().trim(), null);
 		}
 		
-		List <String>rv = new ArrayList<String>();
+		List <String>rv = new ArrayList<>(u.size());
 		rv.addAll(u.keySet());
 		rv.remove("");
 		Collections.sort(rv);
 		
-		return formatAsCSVString (rv);
+		return formatAsCSVString(rv);
 	}
 }
\ No newline at end of file
diff --git a/src/main/java/org/olat/course/statistic/export/LogLineConverter.java b/src/main/java/org/olat/course/statistic/export/LogLineConverter.java
index 9a5ca06e7d6..bba51ebe260 100644
--- a/src/main/java/org/olat/course/statistic/export/LogLineConverter.java
+++ b/src/main/java/org/olat/course/statistic/export/LogLineConverter.java
@@ -125,7 +125,7 @@ public class LogLineConverter {
 			PropertyDescriptor pd = it.next();
 			propertyNames.add(pd.getName());
 		}
-		return StringHelper.formatAsCSVString(propertyNames);
+		return StringHelper.formatAsEscapedCSVString(propertyNames);
 	}
 
 	/**
@@ -160,7 +160,7 @@ public class LogLineConverter {
 			loggingObjectList.add(strValue);
 		}
 		
-		return StringHelper.formatAsCSVString(loggingObjectList);
+		return StringHelper.formatAsEscapedCSVString(loggingObjectList);
 	}
 	
 	/**
diff --git a/src/test/java/org/olat/core/util/StringHelperTest.java b/src/test/java/org/olat/core/util/StringHelperTest.java
index f554c6b3cab..5f71eddda96 100644
--- a/src/test/java/org/olat/core/util/StringHelperTest.java
+++ b/src/test/java/org/olat/core/util/StringHelperTest.java
@@ -22,6 +22,9 @@ package org.olat.core.util;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -176,4 +179,25 @@ public class StringHelperTest {
 		Assert.assertTrue(StringHelper.isHtml("<ul><li>Hello<li>world</ul>"));
 		Assert.assertTrue(StringHelper.isHtml("Hello<br>world"));
 	}
+	
+	
+	@Test
+	public void formatAsCSVString() {
+		List<String> entries = new ArrayList<>();
+		entries.add("Hell\"o\"");
+		entries.add("Test,dru,");
+		entries.add("Final");
+		String csv = StringHelper.formatAsCSVString(entries);
+		Assert.assertEquals("Hell\"o\",Test,dru,,Final", csv);
+	}
+	
+	@Test
+	public void formatAsEscapedCSVString() {
+		List<String> entries = new ArrayList<>();
+		entries.add("Hell\"o\"");
+		entries.add("Test,dru,");
+		entries.add("Final");
+		String csv = StringHelper.formatAsEscapedCSVString(entries);
+		Assert.assertEquals("Hell\"\"o\"\",\"Test,dru,\",Final", csv);
+	}
 }
-- 
GitLab