From febc8763871ba4cf8af6363a83d28e94cba63da1 Mon Sep 17 00:00:00 2001
From: uhensler <urs.hensler@frentix.com>
Date: Wed, 20 Jun 2018 12:21:46 +0200
Subject: [PATCH] OO-3303: Sort evaluation form list by name, shuffle anonymous

---
 .../MultipleChoiceLegendTextHandler.java      |  2 +-
 .../SingleChoiceLegendTextHandler.java        |  2 +-
 .../handler/TextInputLegendTextHandler.java   |  2 +-
 .../forms/ui/EvaluationFormExcelExport.java   |  1 +
 .../ui/EvaluationFormReportsController.java   |  4 +
 ...luationFormSessionSelectionController.java | 30 +++++--
 .../ui/NameShuffleAnonymousComparator.java    | 74 ++++++++++++++++++
 .../olat/modules/forms/ui/ReportHelper.java   | 29 +++++++
 .../forms/ui/SessionSelectionDataSource.java  | 78 -------------------
 .../forms/ui/SessionSelectionModel.java       | 60 +++++++-------
 .../modules/forms/ui/SessionSelectionRow.java |  8 +-
 .../forms/ui/_i18n/LocalStrings_de.properties |  3 +-
 .../forms/ui/_i18n/LocalStrings_en.properties |  1 -
 .../MultipleChoiceLegendTextDataSource.java   |  9 ++-
 .../SingleChoiceLegendTextDataSource.java     |  6 +-
 .../model/TextInputLegendTextDataSource.java  |  7 +-
 16 files changed, 192 insertions(+), 124 deletions(-)
 create mode 100644 src/main/java/org/olat/modules/forms/ui/NameShuffleAnonymousComparator.java
 delete mode 100644 src/main/java/org/olat/modules/forms/ui/SessionSelectionDataSource.java

diff --git a/src/main/java/org/olat/modules/forms/handler/MultipleChoiceLegendTextHandler.java b/src/main/java/org/olat/modules/forms/handler/MultipleChoiceLegendTextHandler.java
index d3b24014a46..3e5f55b0701 100644
--- a/src/main/java/org/olat/modules/forms/handler/MultipleChoiceLegendTextHandler.java
+++ b/src/main/java/org/olat/modules/forms/handler/MultipleChoiceLegendTextHandler.java
@@ -51,7 +51,7 @@ public class MultipleChoiceLegendTextHandler implements EvaluationFormReportHand
 			List<? extends EvaluationFormSessionRef> sessions, ReportHelper reportHelper) {
 		if (element instanceof MultipleChoice) {
 			MultipleChoice multipleChoice = (MultipleChoice) element;
-			LegendTextDataSource dataSource = new MultipleChoiceLegendTextDataSource(multipleChoice, sessions);
+			LegendTextDataSource dataSource = new MultipleChoiceLegendTextDataSource(multipleChoice, sessions, reportHelper);
 			Controller ctrl = new LegendTextController(ureq, windowControl, dataSource, reportHelper);
 			return ctrl.getInitialComponent();
 		}
diff --git a/src/main/java/org/olat/modules/forms/handler/SingleChoiceLegendTextHandler.java b/src/main/java/org/olat/modules/forms/handler/SingleChoiceLegendTextHandler.java
index e6350414118..04e1e273379 100644
--- a/src/main/java/org/olat/modules/forms/handler/SingleChoiceLegendTextHandler.java
+++ b/src/main/java/org/olat/modules/forms/handler/SingleChoiceLegendTextHandler.java
@@ -51,7 +51,7 @@ public class SingleChoiceLegendTextHandler implements EvaluationFormReportHandle
 			List<? extends EvaluationFormSessionRef> sessions, ReportHelper reportHelper) {
 		if (element instanceof SingleChoice) {
 			SingleChoice singleChoice = (SingleChoice) element;
-			LegendTextDataSource dataSource = new SingleChoiceLegendTextDataSource(singleChoice, sessions);
+			LegendTextDataSource dataSource = new SingleChoiceLegendTextDataSource(singleChoice, sessions, reportHelper);
 			Controller ctrl = new LegendTextController(ureq, windowControl, dataSource, reportHelper);
 			return ctrl.getInitialComponent();
 		}
diff --git a/src/main/java/org/olat/modules/forms/handler/TextInputLegendTextHandler.java b/src/main/java/org/olat/modules/forms/handler/TextInputLegendTextHandler.java
index ec440f1f22a..ef547fee7a5 100644
--- a/src/main/java/org/olat/modules/forms/handler/TextInputLegendTextHandler.java
+++ b/src/main/java/org/olat/modules/forms/handler/TextInputLegendTextHandler.java
@@ -51,7 +51,7 @@ public class TextInputLegendTextHandler implements EvaluationFormReportHandler {
 			List<? extends EvaluationFormSessionRef> sessions, ReportHelper reportHelper) {
 		if (element instanceof TextInput) {
 			TextInput textInput = (TextInput) element;
-			LegendTextDataSource dataSource = new TextInputLegendTextDataSource(textInput.getId(), sessions);
+			LegendTextDataSource dataSource = new TextInputLegendTextDataSource(textInput.getId(), sessions, reportHelper);
 			Controller ctrl = new LegendTextController(ureq, windowControl, dataSource, reportHelper);
 			return ctrl.getInitialComponent();
 		}
diff --git a/src/main/java/org/olat/modules/forms/ui/EvaluationFormExcelExport.java b/src/main/java/org/olat/modules/forms/ui/EvaluationFormExcelExport.java
index a119e8976a1..fd20c8fbdfc 100644
--- a/src/main/java/org/olat/modules/forms/ui/EvaluationFormExcelExport.java
+++ b/src/main/java/org/olat/modules/forms/ui/EvaluationFormExcelExport.java
@@ -102,6 +102,7 @@ public class EvaluationFormExcelExport {
 	public OpenXMLWorkbookResource createMediaResource() {
 		// refresh to avoid lazy instantiation exception
 		sessions = evaluationFormManager.loadSessionsByKey(sessions, 0, -1);
+		sessions.sort(reportHelper.getComparator());
 		return new OpenXMLWorkbookResource(fileName) {
 			@Override
 			protected void generate(OutputStream out) {
diff --git a/src/main/java/org/olat/modules/forms/ui/EvaluationFormReportsController.java b/src/main/java/org/olat/modules/forms/ui/EvaluationFormReportsController.java
index e7fd826c55e..8b674d5dbe9 100644
--- a/src/main/java/org/olat/modules/forms/ui/EvaluationFormReportsController.java
+++ b/src/main/java/org/olat/modules/forms/ui/EvaluationFormReportsController.java
@@ -19,6 +19,7 @@
  */
 package org.olat.modules.forms.ui;
 
+import java.util.Comparator;
 import java.util.List;
 
 import org.olat.core.gui.UserRequest;
@@ -61,9 +62,12 @@ public class EvaluationFormReportsController extends BasicController {
 		this.form = form;
 		this.sessions = sessions;
 		
+		Comparator<EvaluationFormSession> comparator = new NameShuffleAnonymousComparator();
+		sessions.sort(comparator);
 		LegendNameGenerator legendNameGenerator = new SessionInformationLegendNameGenerator(sessions);
 		this.reportHelper = ReportHelper.builder(getLocale())
 				.withLegendNameGenrator(legendNameGenerator)
+				.withSessionComparator(comparator)
 				.withColors()
 				.build();
 
diff --git a/src/main/java/org/olat/modules/forms/ui/EvaluationFormSessionSelectionController.java b/src/main/java/org/olat/modules/forms/ui/EvaluationFormSessionSelectionController.java
index d1dc891aeb2..e767af0bccc 100644
--- a/src/main/java/org/olat/modules/forms/ui/EvaluationFormSessionSelectionController.java
+++ b/src/main/java/org/olat/modules/forms/ui/EvaluationFormSessionSelectionController.java
@@ -19,6 +19,7 @@
  */
 package org.olat.modules.forms.ui;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
@@ -38,7 +39,6 @@ import org.olat.core.gui.control.Controller;
 import org.olat.core.gui.control.WindowControl;
 import org.olat.modules.forms.EvaluationFormManager;
 import org.olat.modules.forms.EvaluationFormSession;
-import org.olat.modules.forms.EvaluationFormSessionRef;
 import org.olat.modules.forms.model.jpa.EvaluationFormResponses;
 import org.olat.modules.forms.model.xml.Form;
 import org.olat.modules.forms.model.xml.SessionInformations.InformationType;
@@ -61,17 +61,17 @@ public class EvaluationFormSessionSelectionController extends FormBasicControlle
 	private FlexiTableElement tableEl;
 
 	private final Form form;
-	private final List<? extends EvaluationFormSessionRef> sessionRefs;
+	private final List<EvaluationFormSession> sessions;
 	private final ReportHelper reportHelper;
 	
 	@Autowired
 	private EvaluationFormManager evaluationFormManager;
 	
 	public EvaluationFormSessionSelectionController(UserRequest ureq, WindowControl wControl, Form form,
-			List<? extends EvaluationFormSessionRef> sessionRefs, ReportHelper reportHelper) {
+			List<EvaluationFormSession> sessions, ReportHelper reportHelper) {
 		super(ureq, wControl, LAYOUT_BAREBONE);
 		this.form = form;
-		this.sessionRefs = sessionRefs;
+		this.sessions = sessions;
 		this.reportHelper = reportHelper;
 		initForm(ureq);
 	}
@@ -86,7 +86,7 @@ public class EvaluationFormSessionSelectionController extends FormBasicControlle
 		FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel();
 		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("report.session.quickview",
 				"<i class='o_icon o_icon_quickview'> </i>", CMD_QUICKVIEW));
-		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(SessionSelectionCols.submissionDate));
+		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(SessionSelectionCols.participant));
 		
 		if (SessionInformationsUIFactory.hasInformationType(form, InformationType.USER_FIRSTNAME)) {
 			DefaultFlexiColumnModel columnModel = new DefaultFlexiColumnModel(SessionSelectionCols.firstname);
@@ -122,9 +122,25 @@ public class EvaluationFormSessionSelectionController extends FormBasicControlle
 			columnsModel.addFlexiColumnModel(columnModel);
 		}
 		
-		SessionSelectionDataSource dataSource = new SessionSelectionDataSource(sessionRefs);
-		dataModel = new SessionSelectionModel(dataSource, columnsModel, reportHelper);
+		dataModel = new SessionSelectionModel(columnsModel);
 		tableEl = uifactory.addTableElement(getWindowControl(), "sessions", dataModel, 25, true, getTranslator(), formLayout);
+		loadModel();
+	}
+
+	private void loadModel() {
+		List<SessionSelectionRow> rows = new ArrayList<>();
+		int count = 1;
+		sessions.sort(reportHelper.getComparator());
+		for (EvaluationFormSession session: sessions) {
+			String participant = new StringBuilder()
+					.append(translate("report.session.participant"))
+					.append(" ")
+					.append(count++)
+					.toString();
+			SessionSelectionRow row = new SessionSelectionRow(participant , session);
+			rows.add(row);
+		}
+		dataModel.setObjects(rows);
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/modules/forms/ui/NameShuffleAnonymousComparator.java b/src/main/java/org/olat/modules/forms/ui/NameShuffleAnonymousComparator.java
new file mode 100644
index 00000000000..8eeb18aab9c
--- /dev/null
+++ b/src/main/java/org/olat/modules/forms/ui/NameShuffleAnonymousComparator.java
@@ -0,0 +1,74 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.modules.forms.ui;
+
+import java.util.Comparator;
+
+import org.olat.core.util.Encoder;
+import org.olat.core.util.StringHelper;
+import org.olat.modules.forms.EvaluationFormSession;
+
+/**
+ * 
+ * Initial date: 20.06.2018<br>
+ * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
+ *
+ */
+public class NameShuffleAnonymousComparator implements Comparator<EvaluationFormSession> {
+	
+	@Override
+	public int compare(EvaluationFormSession session1, EvaluationFormSession session2) {
+		if(session1 == null || session2 == null) {
+			return compareNullsLast(session1, session2);
+		}
+		
+		String lastName1 = StringHelper.containsNonWhitespace(session1.getLastname())? session1.getLastname(): null;
+		String lastName2 = StringHelper.containsNonWhitespace(session2.getLastname())? session2.getLastname(): null;
+		String firstName1 = StringHelper.containsNonWhitespace(session1.getFirstname())? session1.getFirstname(): null;
+		String firstName2 = StringHelper.containsNonWhitespace(session2.getFirstname())? session2.getFirstname(): null;
+		String keyHash1 = Encoder.md5hash(String.valueOf(session1.getKey()));
+		String keyHash2 = Encoder.md5hash(String.valueOf(session2.getKey()));
+
+		int c = 0;
+		if(lastName1 == null || lastName2 == null) {
+			c = compareNullsLast(lastName1, lastName2);
+		} else {
+			c = lastName1.compareTo(lastName2);
+		}
+		if(c == 0) {
+			if(firstName1 == null || firstName2 == null) {
+				c = compareNullsLast(firstName1, firstName2);
+			} else {
+				c = firstName1.compareTo(firstName2);
+			}
+		}
+		if(c == 0) {
+			c = keyHash1.compareTo(keyHash2);
+		}
+
+		return c;
+	}
+	
+	private final int compareNullsLast(final Object a, final Object b) {
+		boolean ba = (a == null);
+		boolean bb = (b == null);
+		return bb? (ba? 0: -1):(ba? 1: 0);
+	}
+}
diff --git a/src/main/java/org/olat/modules/forms/ui/ReportHelper.java b/src/main/java/org/olat/modules/forms/ui/ReportHelper.java
index 9934f13e1f7..56706cacfbd 100644
--- a/src/main/java/org/olat/modules/forms/ui/ReportHelper.java
+++ b/src/main/java/org/olat/modules/forms/ui/ReportHelper.java
@@ -19,6 +19,7 @@
  */
 package org.olat.modules.forms.ui;
 
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
@@ -47,6 +48,7 @@ public class ReportHelper {
 	private final Legend anonymousLegend;
 	private final ColorGenerator colorGenerator;
 	private final LegendNameGenerator legendNameGenerator;
+	private final Comparator<EvaluationFormSession> comparator;
 	
 	private final Map<EvaluationFormSession, Legend> sessionKeyToData = new HashMap<>();
 	private final Map<EvaluationFormParticipation, Legend> participationToLegend = new HashMap<>();
@@ -83,8 +85,17 @@ public class ReportHelper {
 		} else {
 			this.legendNameGenerator = new NullNameGenerator();
 		}
+		if (builder.comparator != null) {
+			this.comparator = builder.comparator;
+		} else {
+			this.comparator = new KeyComparator();
+		}
 	}
 	
+	public Comparator<EvaluationFormSession> getComparator() {
+		return comparator;
+	}
+
 	Legend getLegend(EvaluationFormSession session) {
 		Legend legend = sessionKeyToData.get(session);
 		if (legend == null && session.getParticipation() != null) {
@@ -142,6 +153,7 @@ public class ReportHelper {
 		private String anonymousColor = null;
 		private boolean hasColors = false;
 		private LegendNameGenerator legendNameGenerator;
+		private Comparator<EvaluationFormSession> comparator;
 		
 		Builder(Locale locale) {
 			this.locale = locale;
@@ -166,6 +178,11 @@ public class ReportHelper {
 			this.legendNameGenerator = legendNameGenerator;
 			return this;
 		}
+
+		public Builder withSessionComparator(Comparator<EvaluationFormSession> comparator) {
+			this.comparator = comparator;
+			return this;
+		}
 		
 		public ReportHelper build() {
 			return new ReportHelper(this);
@@ -195,6 +212,7 @@ public class ReportHelper {
 		boolean isAnonymous() {
 			return anonymous;
 		}
+
 	}
 	
 	private final static class NullNameGenerator implements LegendNameGenerator {
@@ -205,5 +223,16 @@ public class ReportHelper {
 		}
 
 	}
+	
+	private final static class KeyComparator implements Comparator<EvaluationFormSession> {
+
+		@Override
+		public int compare(EvaluationFormSession o1, EvaluationFormSession o2) {
+			long key1 = o1 != null? o1.getKey(): -1;
+			long key2 = o2 != null? o2.getKey(): -1;
+			return Long.compare(key1, key2);
+		}
+
+	}
 
 }
diff --git a/src/main/java/org/olat/modules/forms/ui/SessionSelectionDataSource.java b/src/main/java/org/olat/modules/forms/ui/SessionSelectionDataSource.java
deleted file mode 100644
index 353af834c45..00000000000
--- a/src/main/java/org/olat/modules/forms/ui/SessionSelectionDataSource.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/**
- * <a href="http://www.openolat.org">
- * OpenOLAT - Online Learning and Training</a><br>
- * <p>
- * Licensed under the Apache License, Version 2.0 (the "License"); <br>
- * you may not use this file except in compliance with the License.<br>
- * You may obtain a copy of the License at the
- * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
- * <p>
- * Unless required by applicable law or agreed to in writing,<br>
- * software distributed under the License is distributed on an "AS IS" BASIS, <br>
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
- * See the License for the specific language governing permissions and <br>
- * limitations under the License.
- * <p>
- * Initial code contributed and copyrighted by<br>
- * frentix GmbH, http://www.frentix.com
- * <p>
- */
-package org.olat.modules.forms.ui;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import org.olat.core.CoreSpringFactory;
-import org.olat.core.commons.persistence.DefaultResultInfos;
-import org.olat.core.commons.persistence.ResultInfos;
-import org.olat.core.commons.persistence.SortKey;
-import org.olat.core.gui.components.form.flexible.elements.FlexiTableFilter;
-import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataSourceDelegate;
-import org.olat.modules.forms.EvaluationFormManager;
-import org.olat.modules.forms.EvaluationFormSession;
-import org.olat.modules.forms.EvaluationFormSessionRef;
-import org.springframework.beans.factory.annotation.Autowired;
-
-/**
- * 
- * Initial date: 25.05.2018<br>
- * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
- *
- */
-public class SessionSelectionDataSource implements FlexiTableDataSourceDelegate<SessionSelectionRow> {
-	
-	private final List<? extends EvaluationFormSessionRef> sessionRefs;
-	
-	@Autowired
-	private EvaluationFormManager evaluationFormManager;
-	
-	public SessionSelectionDataSource(List<? extends EvaluationFormSessionRef> sessionRefs) {
-		this.sessionRefs = sessionRefs;
-		CoreSpringFactory.autowireObject(this);
-	}
-
-	@Override
-	public int getRowCount() {
-		return sessionRefs.size();
-	}
-
-	@Override
-	public List<SessionSelectionRow> reload(List<SessionSelectionRow> rows) {
-		return Collections.emptyList();
-	}
-
-	@Override
-	public ResultInfos<SessionSelectionRow> getRows(String query, List<FlexiTableFilter> filters,
-			List<String> condQueries, int firstResult, int maxResults, SortKey... orderBy) {
-		
-		List<EvaluationFormSession> sessions = evaluationFormManager.loadSessionsByKey(sessionRefs, firstResult, maxResults, orderBy);
-		List<SessionSelectionRow> rows = new ArrayList<>();
-		for (EvaluationFormSession session: sessions) {
-			rows.add(new SessionSelectionRow(session));
-		}
-
-		return new DefaultResultInfos<>(firstResult + rows.size(), -1, rows);
-	}
-
-}
diff --git a/src/main/java/org/olat/modules/forms/ui/SessionSelectionModel.java b/src/main/java/org/olat/modules/forms/ui/SessionSelectionModel.java
index a2d41f6dd56..c93b6db883c 100644
--- a/src/main/java/org/olat/modules/forms/ui/SessionSelectionModel.java
+++ b/src/main/java/org/olat/modules/forms/ui/SessionSelectionModel.java
@@ -19,11 +19,14 @@
  */
 package org.olat.modules.forms.ui;
 
-import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiTableDataSourceModel;
+import java.util.List;
+
+import org.olat.core.commons.persistence.SortKey;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiTableDataModel;
 import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiSortableColumnDef;
 import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel;
-import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataSourceDelegate;
-import org.olat.core.util.StringHelper;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.SortableFlexiTableDataModel;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.SortableFlexiTableModelDelegate;
 
 /**
  * 
@@ -31,46 +34,47 @@ import org.olat.core.util.StringHelper;
  * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
  *
  */
-public class SessionSelectionModel extends DefaultFlexiTableDataSourceModel<SessionSelectionRow> {
-	
-	private final ReportHelper reportHelper;
+public class SessionSelectionModel extends DefaultFlexiTableDataModel<SessionSelectionRow>
+		implements SortableFlexiTableDataModel<SessionSelectionRow> {
 	
-	public SessionSelectionModel(FlexiTableDataSourceDelegate<SessionSelectionRow> dataSource,
-			FlexiTableColumnModel columnsModel, ReportHelper reportHelper) {
-		super(dataSource, columnsModel);
-		this.reportHelper = reportHelper;
+	public SessionSelectionModel(FlexiTableColumnModel columnsModel) {
+		super(columnsModel);
+	}
+
+	@Override
+	public void sort(SortKey sortKey) {
+		List<SessionSelectionRow> rows = new SortableFlexiTableModelDelegate<>(sortKey, this, null).sort();
+		super.setObjects(rows);
 	}
 
 	@Override
 	public Object getValueAt(int row, int col) {
 		SessionSelectionRow sessionSelectionRow = getObject(row);
+		return getValueAt(sessionSelectionRow, col);
+	}
+
+	@Override
+	public Object getValueAt(SessionSelectionRow row, int col) {
 		switch(SessionSelectionCols.values()[col]) {
-			case submissionDate: return sessionSelectionRow.getSession().getSubmissionDate();
-			case firstname: return sessionSelectionRow.getSession().getFirstname();
-			case lastname: {
-				boolean hasFirstname = StringHelper.containsNonWhitespace(sessionSelectionRow.getSession().getFirstname());
-				String lastname = sessionSelectionRow.getSession().getLastname();
-				boolean hasLastname = StringHelper.containsNonWhitespace(lastname);
-				return hasFirstname || hasLastname
-						? lastname
-						: reportHelper.getLegend(sessionSelectionRow.getSession()).getName();
-			}
-			case email: return sessionSelectionRow.getSession().getEmail();
-			case age: return sessionSelectionRow.getSession().getAge();
-			case gender: return sessionSelectionRow.getSession().getGender();
-			case orgUnit: return sessionSelectionRow.getSession().getOrgUnit();
-			case studySubject: return sessionSelectionRow.getSession().getStudySubject();
+			case participant: return row.getParticipant();
+			case firstname: return row.getSession().getFirstname();
+			case lastname: return row.getSession().getLastname();
+			case email: return row.getSession().getEmail();
+			case age: return row.getSession().getAge();
+			case gender: return row.getSession().getGender();
+			case orgUnit: return row.getSession().getOrgUnit();
+			case studySubject: return row.getSession().getStudySubject();
 			default: return null;
 		}	
 	}
 
 	@Override
-	public DefaultFlexiTableDataSourceModel<SessionSelectionRow> createCopyWithEmptyList() {
-		return new SessionSelectionModel(getSourceDelegate(),  getTableColumnModel(), reportHelper);
+	public DefaultFlexiTableDataModel<SessionSelectionRow> createCopyWithEmptyList() {
+		return new SessionSelectionModel(getTableColumnModel());
 	}
 	
 	public enum SessionSelectionCols implements FlexiSortableColumnDef {
-		submissionDate("report.session.submission.date"),
+		participant("report.session.participant"),
 		firstname("report.session.dummy"),
 		lastname("report.session.dummy"),
 		email("report.session.dummy"),
diff --git a/src/main/java/org/olat/modules/forms/ui/SessionSelectionRow.java b/src/main/java/org/olat/modules/forms/ui/SessionSelectionRow.java
index 2fc225405f7..427cdbb25fc 100644
--- a/src/main/java/org/olat/modules/forms/ui/SessionSelectionRow.java
+++ b/src/main/java/org/olat/modules/forms/ui/SessionSelectionRow.java
@@ -29,10 +29,12 @@ import org.olat.modules.forms.EvaluationFormSession;
  */
 class SessionSelectionRow {
 	
+	private final String participant;
 	private final EvaluationFormSession session;
 
-	protected SessionSelectionRow(EvaluationFormSession session) {
+	protected SessionSelectionRow(String participant, EvaluationFormSession session) {
 		super();
+		this.participant = participant;
 		this.session = session;
 	}
 
@@ -40,4 +42,8 @@ class SessionSelectionRow {
 		return session;
 	}
 
+	public String getParticipant() {
+		return participant;
+	}
+
 }
diff --git a/src/main/java/org/olat/modules/forms/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/forms/ui/_i18n/LocalStrings_de.properties
index 6177e4f4ef5..2345b4f4c9a 100644
--- a/src/main/java/org/olat/modules/forms/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/modules/forms/ui/_i18n/LocalStrings_de.properties
@@ -79,8 +79,7 @@ report.print.title.session=$\:reports.session.selection
 report.print.title.tables=$\:reports.table.report
 report.session.dummy=
 report.session.quickview=<i class\='o_icon o_icon_quickview'> </i>
-report.session.participant=Teilnehmer/in
-report.session.submission.date=Abgabedatum
+report.session.participant=Teilnehmer
 reports.diagram.report=Diagramme
 reports.session.forms=Frageb\u00f6gen
 reports.session.selection=Einzelne Frageb\u00f6gen
diff --git a/src/main/java/org/olat/modules/forms/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/forms/ui/_i18n/LocalStrings_en.properties
index 39ec32d9bca..c9e64e2467e 100644
--- a/src/main/java/org/olat/modules/forms/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/modules/forms/ui/_i18n/LocalStrings_en.properties
@@ -84,7 +84,6 @@ report.print.title.tables=$\:reports.table.report
 report.session.dummy=
 report.session.quickview=<i class\='o_icon o_icon_quickview'> </i>
 report.session.participant=Participant
-report.session.submission.date=Submission date
 reports.diagram.report=Diagrams
 report.session.quickview=<i class\='o_icon o_icon_quickview'> </i>
 reports.session.forms=Questionnaires
diff --git a/src/main/java/org/olat/modules/forms/ui/model/MultipleChoiceLegendTextDataSource.java b/src/main/java/org/olat/modules/forms/ui/model/MultipleChoiceLegendTextDataSource.java
index a679713525d..4fb61998c5b 100644
--- a/src/main/java/org/olat/modules/forms/ui/model/MultipleChoiceLegendTextDataSource.java
+++ b/src/main/java/org/olat/modules/forms/ui/model/MultipleChoiceLegendTextDataSource.java
@@ -31,6 +31,7 @@ import org.olat.modules.forms.EvaluationFormSessionRef;
 import org.olat.modules.forms.manager.EvaluationFormReportDAO;
 import org.olat.modules.forms.model.xml.Choice;
 import org.olat.modules.forms.model.xml.MultipleChoice;
+import org.olat.modules.forms.ui.ReportHelper;
 
 /**
  * 
@@ -42,14 +43,16 @@ public class MultipleChoiceLegendTextDataSource implements LegendTextDataSource
 
 	private final MultipleChoice multipleChoice;
 	private final List<? extends EvaluationFormSessionRef> sessions;
+	private final ReportHelper reportHelper;
 	
 	private EvaluationFormReportDAO reportDAO;
 	
 	public MultipleChoiceLegendTextDataSource(MultipleChoice multipleChoice,
-			List<? extends EvaluationFormSessionRef> sessions) {
+			List<? extends EvaluationFormSessionRef> sessions, ReportHelper reportHelper) {
 		super();
 		this.multipleChoice = multipleChoice;
 		this.sessions = sessions;
+		this.reportHelper = reportHelper;
 		this.reportDAO = CoreSpringFactory.getImpl(EvaluationFormReportDAO.class);
 	}
 
@@ -60,7 +63,9 @@ public class MultipleChoiceLegendTextDataSource implements LegendTextDataSource
 		Map<EvaluationFormSession, List<EvaluationFormResponse>> sessionToResponse = responses.stream()
 				.collect(Collectors.groupingBy(EvaluationFormResponse::getSession));
 		
-		for (EvaluationFormSession session: sessionToResponse.keySet()) {
+		List<EvaluationFormSession> sessions = new ArrayList<>(sessionToResponse.keySet());
+		sessions.sort(reportHelper.getComparator());
+		for (EvaluationFormSession session: sessions) {
 			List<EvaluationFormResponse> sessionResponses = sessionToResponse.get(session);
 			String text = concatResponses(sessionResponses);
 			if (text != null) {
diff --git a/src/main/java/org/olat/modules/forms/ui/model/SingleChoiceLegendTextDataSource.java b/src/main/java/org/olat/modules/forms/ui/model/SingleChoiceLegendTextDataSource.java
index 4350b3df235..c38580fb3ad 100644
--- a/src/main/java/org/olat/modules/forms/ui/model/SingleChoiceLegendTextDataSource.java
+++ b/src/main/java/org/olat/modules/forms/ui/model/SingleChoiceLegendTextDataSource.java
@@ -28,6 +28,7 @@ import org.olat.modules.forms.EvaluationFormSessionRef;
 import org.olat.modules.forms.manager.EvaluationFormReportDAO;
 import org.olat.modules.forms.model.xml.Choice;
 import org.olat.modules.forms.model.xml.SingleChoice;
+import org.olat.modules.forms.ui.ReportHelper;
 
 /**
  * 
@@ -39,14 +40,16 @@ public class SingleChoiceLegendTextDataSource implements LegendTextDataSource {
 
 	private final SingleChoice singleChoice;
 	private final List<? extends EvaluationFormSessionRef> sessions;
+	private final ReportHelper reportHelper;
 	
 	private EvaluationFormReportDAO reportDAO;
 	
 	public SingleChoiceLegendTextDataSource(SingleChoice singleChoice,
-			List<? extends EvaluationFormSessionRef> sessions) {
+			List<? extends EvaluationFormSessionRef> sessions, ReportHelper reportHelper) {
 		super();
 		this.singleChoice = singleChoice;
 		this.sessions = sessions;
+		this.reportHelper = reportHelper;
 		this.reportDAO = CoreSpringFactory.getImpl(EvaluationFormReportDAO.class);
 	}
 
@@ -54,6 +57,7 @@ public class SingleChoiceLegendTextDataSource implements LegendTextDataSource {
 	public List<SessionText> getResponses() {
 		List<SessionText> sessionTexts = new ArrayList<>();
 		List<EvaluationFormResponse> responses = reportDAO.getResponses(singleChoice.getId(), sessions);
+		responses.sort((r1, r2) -> reportHelper.getComparator().compare(r1.getSession(), r2.getSession()));
 		
 		for (EvaluationFormResponse response : responses) {
 			String text = getText(response);
diff --git a/src/main/java/org/olat/modules/forms/ui/model/TextInputLegendTextDataSource.java b/src/main/java/org/olat/modules/forms/ui/model/TextInputLegendTextDataSource.java
index a758745c932..354001cc26c 100644
--- a/src/main/java/org/olat/modules/forms/ui/model/TextInputLegendTextDataSource.java
+++ b/src/main/java/org/olat/modules/forms/ui/model/TextInputLegendTextDataSource.java
@@ -26,6 +26,7 @@ import org.olat.core.CoreSpringFactory;
 import org.olat.modules.forms.EvaluationFormResponse;
 import org.olat.modules.forms.EvaluationFormSessionRef;
 import org.olat.modules.forms.manager.EvaluationFormReportDAO;
+import org.olat.modules.forms.ui.ReportHelper;
 
 /**
  * 
@@ -37,13 +38,16 @@ public class TextInputLegendTextDataSource implements LegendTextDataSource {
 
 	private final String responseIdentifier;
 	private final List<? extends EvaluationFormSessionRef> sessions;
+	private final ReportHelper reportHelper;
 	
 	private EvaluationFormReportDAO reportDAO;
 	
-	public TextInputLegendTextDataSource(String responseIdentifier, List<? extends EvaluationFormSessionRef> sessions) {
+	public TextInputLegendTextDataSource(String responseIdentifier, List<? extends EvaluationFormSessionRef> sessions,
+			ReportHelper reportHelper) {
 		super();
 		this.responseIdentifier = responseIdentifier;
 		this.sessions = sessions;
+		this.reportHelper = reportHelper;
 		this.reportDAO = CoreSpringFactory.getImpl(EvaluationFormReportDAO.class);
 	}
 
@@ -51,6 +55,7 @@ public class TextInputLegendTextDataSource implements LegendTextDataSource {
 	public List<SessionText> getResponses() {
 		List<SessionText> sessionTexts = new ArrayList<>();
 		List<EvaluationFormResponse> responses = reportDAO.getResponses(responseIdentifier, sessions);
+		responses.sort((r1, r2) -> reportHelper.getComparator().compare(r1.getSession(), r2.getSession()));
 		for (EvaluationFormResponse response : responses) {
 			SessionText sessionText = new SessionText(response.getSession(), response.getStringuifiedResponse());
 			sessionTexts.add(sessionText);
-- 
GitLab