From 31e2804b820eae7c19313c97e51c6e9859c5bb76 Mon Sep 17 00:00:00 2001
From: srosse <none@none>
Date: Thu, 29 Aug 2013 10:57:23 +0200
Subject: [PATCH] OO-691: allow essay in test with a lot of warnings and
 messages

---
 .../course/nodes/iq/IQEditController.java     | 29 +++++++++-
 .../nodes/iq/_i18n/LocalStrings_de.properties |  3 +-
 .../nodes/iq/_i18n/LocalStrings_en.properties |  1 +
 .../ims/qti/QTI12ResultDetailsController.java | 31 ++++++++++-
 .../org/olat/ims/qti/_content/qtires.html     |  3 ++
 .../ims/qti/_i18n/LocalStrings_de.properties  |  1 +
 .../ims/qti/_i18n/LocalStrings_en.properties  |  1 +
 .../olat/ims/qti/container/ItemContext.java   |  4 ++
 .../org/olat/ims/qti/container/Variables.java | 10 ++--
 .../ims/qti/editor/ChoiceItemController.java  | 16 +++---
 .../ims/qti/editor/EssayItemController.java   | 16 +++++-
 .../editor/ItemMetadataFormController.java    |  9 ++--
 .../editor/ItemNodeTabbedFormController.java  |  5 +-
 .../olat/ims/qti/editor/QTIEditHelper.java    |  4 +-
 .../qti/editor/QTIEditorMainController.java   | 54 +++++++++++++------
 .../olat/ims/qti/editor/_content/index.html   |  3 ++
 .../qti/editor/_content/tab_essayItem.html    |  5 ++
 .../editor/_i18n/LocalStrings_de.properties   |  3 ++
 .../editor/_i18n/LocalStrings_en.properties   |  3 ++
 .../editor/beecom/objects/ChoiceQuestion.java |  2 +-
 .../editor/beecom/objects/EssayQuestion.java  | 21 +++++++-
 .../beecom/objects/OutcomesProcessing.java    |  5 +-
 .../qti/editor/tree/QTIEditorTreeModel.java   |  4 +-
 23 files changed, 187 insertions(+), 46 deletions(-)

diff --git a/src/main/java/org/olat/course/nodes/iq/IQEditController.java b/src/main/java/org/olat/course/nodes/iq/IQEditController.java
index 19342beb76a..1f588601b1b 100644
--- a/src/main/java/org/olat/course/nodes/iq/IQEditController.java
+++ b/src/main/java/org/olat/course/nodes/iq/IQEditController.java
@@ -81,6 +81,11 @@ import org.olat.course.tree.CourseInternalLinkTreeModel;
 import org.olat.fileresource.FileResourceManager;
 import org.olat.ims.qti.QTIResult;
 import org.olat.ims.qti.QTIResultManager;
+import org.olat.ims.qti.editor.QTIEditorPackage;
+import org.olat.ims.qti.editor.QTIEditorPackageImpl;
+import org.olat.ims.qti.editor.beecom.objects.Assessment;
+import org.olat.ims.qti.editor.beecom.objects.Item;
+import org.olat.ims.qti.editor.beecom.objects.Section;
 import org.olat.ims.qti.fileresource.SurveyFileResource;
 import org.olat.ims.qti.fileresource.TestFileResource;
 import org.olat.ims.qti.process.AssessmentInstance;
@@ -566,6 +571,7 @@ public class IQEditController extends ActivateableTabbableDefaultController impl
 	/**
 	 * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, org.olat.core.gui.control.Controller, org.olat.core.gui.control.Event)
 	 */
+	@Override
 	public void event(UserRequest urequest, Controller source, Event event) {
 		if (source.equals(searchController)) {
 			if (event == ReferencableEntriesSearchController.EVENT_REPOSITORY_ENTRY_SELECTED) {
@@ -573,7 +579,8 @@ public class IQEditController extends ActivateableTabbableDefaultController impl
 				cmc.deactivate();
 				RepositoryEntry re = searchController.getSelectedEntry();
 				doIQReference(urequest, re);
-				this.updateEditController(urequest);
+				updateEditController(urequest);
+				checkEssay(re);
 			}
 		} else if (source == accessibilityCondContr) {
 			if (event == Event.CHANGED_EVENT) {
@@ -629,6 +636,26 @@ public class IQEditController extends ActivateableTabbableDefaultController impl
 		}
 	}
 	
+	private void checkEssay(RepositoryEntry re) {
+		TestFileResource fr = new TestFileResource();
+		fr.overrideResourceableId(re.getOlatResource().getResourceableId());
+		QTIEditorPackage qtiPackage = new QTIEditorPackageImpl(getIdentity(), fr, getTranslator());
+		Assessment ass = qtiPackage.getQTIDocument().getAssessment();
+
+		//Sections with their Items
+		List<Section> sections = ass.getSections();
+		for (Section section:sections) {
+			List<Item> items = section.getItems();
+			for (Item item:items) {
+				String ident = item.getIdent();
+				if(ident != null && ident.startsWith("QTIEDIT:ESSAY")) {
+					showWarning("warning.test.with.essay");
+					break;
+				}
+			}
+		}
+	}
+	
 	private void doModOnyxConfigForm(IQEditForm modConfigForm) {
 		String qtiType = null;
 		if (moduleConfiguration.get(IQEditController.CONFIG_KEY_TYPE_QTI) != null) {
diff --git a/src/main/java/org/olat/course/nodes/iq/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/nodes/iq/_i18n/LocalStrings_de.properties
index 12d4b747331..33764945283 100644
--- a/src/main/java/org/olat/course/nodes/iq/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/course/nodes/iq/_i18n/LocalStrings_de.properties
@@ -230,4 +230,5 @@ command.editRepFile = Editieren
 
 help.select.file.test=Hilfe zur Auswahl eines Tests
 help.select.file.self=Hilfe zur Auswahl eines Selbsttests
-help.select.file.surv=Hilfe zur Auswahl eines Fragebogens
\ No newline at end of file
+help.select.file.surv=Hilfe zur Auswahl eines Fragebogens
+warning.test.with.essay=$org.olat.ims.qti.editor\:warning.test.with.essay
\ No newline at end of file
diff --git a/src/main/java/org/olat/course/nodes/iq/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/nodes/iq/_i18n/LocalStrings_en.properties
index f898075a970..a7ccf50ff17 100644
--- a/src/main/java/org/olat/course/nodes/iq/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/course/nodes/iq/_i18n/LocalStrings_en.properties
@@ -196,3 +196,4 @@ showResults.detailed=Results
 showResults.title=Results
 showResults.visibility=Your results will be displayed from "{0}" until "{1}"
 start=Start
+warning.test.with.essay=$org.olat.ims.qti.editor\:warning.test.with.essay
diff --git a/src/main/java/org/olat/ims/qti/QTI12ResultDetailsController.java b/src/main/java/org/olat/ims/qti/QTI12ResultDetailsController.java
index c858187128c..5c83a3e578a 100644
--- a/src/main/java/org/olat/ims/qti/QTI12ResultDetailsController.java
+++ b/src/main/java/org/olat/ims/qti/QTI12ResultDetailsController.java
@@ -53,6 +53,12 @@ import org.olat.course.nodes.AssessableCourseNode;
 import org.olat.course.run.scoring.ScoreEvaluation;
 import org.olat.course.run.userview.UserCourseEnvironment;
 import org.olat.ims.qti.container.AssessmentContext;
+import org.olat.ims.qti.editor.QTIEditorPackage;
+import org.olat.ims.qti.editor.QTIEditorPackageImpl;
+import org.olat.ims.qti.editor.beecom.objects.Assessment;
+import org.olat.ims.qti.editor.beecom.objects.Item;
+import org.olat.ims.qti.editor.beecom.objects.Section;
+import org.olat.ims.qti.fileresource.TestFileResource;
 import org.olat.ims.qti.process.AssessmentFactory;
 import org.olat.ims.qti.process.AssessmentInstance;
 import org.olat.ims.qti.process.FilePersister;
@@ -110,14 +116,37 @@ public class QTI12ResultDetailsController extends BasicController {
 		
 		String resourcePath = courseResourceableId + File.separator + nodeIdent;
 		qtiPersister = new FilePersister(assessedIdentity, resourcePath);
-		
+
 		init(ureq);
 	}
 	
+	private boolean checkEssay() {
+		TestFileResource fr = new TestFileResource();
+		fr.overrideResourceableId(repositoryEntry.getOlatResource().getResourceableId());
+		QTIEditorPackage qtiPackage = new QTIEditorPackageImpl(getIdentity(), fr, getTranslator());
+		Assessment ass = qtiPackage.getQTIDocument().getAssessment();
+
+		//Sections with their Items
+		List<Section> sections = ass.getSections();
+		for (Section section:sections) {
+			List<Item> items = section.getItems();
+			for (Item item:items) {
+				String ident = item.getIdent();
+				if(ident != null && ident.startsWith("QTIEDIT:ESSAY")) {
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+	
 	private void init(UserRequest ureq) {
 		main = createVelocityContainer("qtires");
 		details = createVelocityContainer("qtires_details");
 		
+		boolean hasEssay = checkEssay();
+		main.contextPut("warningEssay", new Boolean(hasEssay));
+		
 		TableGuiConfiguration tableConfig = new TableGuiConfiguration();
 		tableCtr = new TableController(tableConfig, ureq, getWindowControl(), getTranslator());
 		tableCtr.addColumnDescriptor(new DefaultColumnDescriptor("column.header.date", 0, null, ureq.getLocale()));
diff --git a/src/main/java/org/olat/ims/qti/_content/qtires.html b/src/main/java/org/olat/ims/qti/_content/qtires.html
index 62644395557..91d1faed4c6 100644
--- a/src/main/java/org/olat/ims/qti/_content/qtires.html
+++ b/src/main/java/org/olat/ims/qti/_content/qtires.html
@@ -1 +1,4 @@
+#if($warningEssay)
+	<div class="b_warning">$r.translate("warning.test.with.essay")</div>
+#end
 $r.render("qtirestable")
diff --git a/src/main/java/org/olat/ims/qti/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/ims/qti/_i18n/LocalStrings_de.properties
index 3de4cc7c03d..d488fa5b925 100644
--- a/src/main/java/org/olat/ims/qti/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/ims/qti/_i18n/LocalStrings_de.properties
@@ -68,3 +68,4 @@ score.val=Erreichte Punktzahl
 sec=Sektion
 secs=Sekunden
 time=Zeit
+warning.test.with.essay=$org.olat.ims.qti.editor\:warning.test.with.essay
diff --git a/src/main/java/org/olat/ims/qti/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/ims/qti/_i18n/LocalStrings_en.properties
index c9c7993e7da..50c2678201e 100644
--- a/src/main/java/org/olat/ims/qti/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/ims/qti/_i18n/LocalStrings_en.properties
@@ -65,3 +65,4 @@ score.val=Achieved score
 sec=Section
 secs=Seconds
 time=Time
+warning.test.with.essay=$org.olat.ims.qti.editor\:warning.test.with.essay
diff --git a/src/main/java/org/olat/ims/qti/container/ItemContext.java b/src/main/java/org/olat/ims/qti/container/ItemContext.java
index d82ebcc83c8..2a72e44b262 100644
--- a/src/main/java/org/olat/ims/qti/container/ItemContext.java
+++ b/src/main/java/org/olat/ims/qti/container/ItemContext.java
@@ -409,6 +409,10 @@ public class ItemContext implements Serializable {
 	public float getScore() {
 		Variable var = getVariables().getSCOREVariable();
 		if (var == null) {
+			if(ident.startsWith("QTIEDIT:ESSAY")) {
+				return 0.0f;
+			}
+			
 			// we demand that a SCORE variable must always exist
 			throw new RuntimeException("no SCORE def for " + getIdent());
 		} else {
diff --git a/src/main/java/org/olat/ims/qti/container/Variables.java b/src/main/java/org/olat/ims/qti/container/Variables.java
index a48d53e402e..bdf0b20f35a 100644
--- a/src/main/java/org/olat/ims/qti/container/Variables.java
+++ b/src/main/java/org/olat/ims/qti/container/Variables.java
@@ -32,16 +32,18 @@ import java.util.Map;
 /**
  */
 public class Variables implements Serializable{
-	Map vars;
+
+	private static final long serialVersionUID = 4599004441875604671L;
+	private final Map<String,Variable> vars;
 	
 	public Variables() {
 		super();
-		vars = new HashMap(3);
+		vars = new HashMap<String,Variable>(3);
 	}
 
 
 	public Variable getVariable(String varName) {
-		return (Variable)vars.get(varName);
+		return vars.get(varName);
 	}
 
 	public Variable getSCOREVariable() {
@@ -60,7 +62,7 @@ public class Variables implements Serializable{
 		vars.put(var.getVarName(),var);
 	}
 	
-	
+	@Override
 	public String toString() {
 		return vars.toString()+"="+super.toString();
 	}
diff --git a/src/main/java/org/olat/ims/qti/editor/ChoiceItemController.java b/src/main/java/org/olat/ims/qti/editor/ChoiceItemController.java
index b6931087359..d0f37769d76 100644
--- a/src/main/java/org/olat/ims/qti/editor/ChoiceItemController.java
+++ b/src/main/java/org/olat/ims/qti/editor/ChoiceItemController.java
@@ -108,14 +108,14 @@ public class ChoiceItemController extends DefaultController implements Controlle
 			if (sPosid != null) posid = Integer.parseInt(sPosid);
 			if (cmd.equals("up")) {
 				if (posid > 0) {
-					List elements = item.getQuestion().getResponses();
-					Object obj = elements.remove(posid);
+					List<Response> elements = item.getQuestion().getResponses();
+					Response obj = elements.remove(posid);
 					elements.add(posid - 1, obj);
 				}
 			} else if (cmd.equals("down")) {
-				List elements = item.getQuestion().getResponses();
+				List<Response> elements = item.getQuestion().getResponses();
 				if (posid < elements.size() - 1) {
-					Object obj = elements.remove(posid);
+					Response obj = elements.remove(posid);
 					elements.add(posid + 1, obj);
 				}
 			} else if (cmd.equals("editq")) {
@@ -129,7 +129,7 @@ public class ChoiceItemController extends DefaultController implements Controlle
 
 			} else if (cmd.equals("addchoice")) {
 				ChoiceQuestion question = (ChoiceQuestion) item.getQuestion();
-				List choices = question.getResponses();
+				List<Response> choices = question.getResponses();
 				ChoiceResponse newChoice = new ChoiceResponse();
 				newChoice.getContent().add(new Mattext(trnsltr.translate("newresponsetext")));
 				newChoice.setCorrect(false);
@@ -142,7 +142,7 @@ public class ChoiceItemController extends DefaultController implements Controlle
 				getWindowControl().pushAsModalDialog( delYesNoCtrl.getInitialComponent());
 			} else if (cmd.equals("ssc")) { // submit sc
 				ChoiceQuestion question = (ChoiceQuestion) item.getQuestion();
-				List q_choices = question.getResponses();
+				List<Response> q_choices = question.getResponses();
 				String correctChoice = ureq.getParameter("correctChoice");
 				for (int i = 0; i < q_choices.size(); i++) {
 					ChoiceResponse choice = (ChoiceResponse) q_choices.get(i);
@@ -169,7 +169,7 @@ public class ChoiceItemController extends DefaultController implements Controlle
 				
 			} else if (cmd.equals("smc")) { // submit mc
 				ChoiceQuestion question = (ChoiceQuestion) item.getQuestion();
-				List choices = question.getResponses();
+				List<Response> choices = question.getResponses();
 				boolean hasZeroPointChoice = false;
 				for (int i = 0; i < choices.size(); i++) {
 					ChoiceResponse choice = (ChoiceResponse) choices.get(i);
@@ -201,7 +201,7 @@ public class ChoiceItemController extends DefaultController implements Controlle
 					// invalid input, set maxValue 0
 				}
 				ChoiceQuestion question = (ChoiceQuestion) item.getQuestion();
-				List q_choices = question.getResponses();
+				List<Response> q_choices = question.getResponses();
 				for (int i = 0; i < q_choices.size(); i++) {
 					String correctChoice = ureq.getParameter("correctChoice_q" + i);
 					ChoiceResponse choice = (ChoiceResponse) q_choices.get(i);
diff --git a/src/main/java/org/olat/ims/qti/editor/EssayItemController.java b/src/main/java/org/olat/ims/qti/editor/EssayItemController.java
index 87673329a05..a4dd74647f1 100644
--- a/src/main/java/org/olat/ims/qti/editor/EssayItemController.java
+++ b/src/main/java/org/olat/ims/qti/editor/EssayItemController.java
@@ -35,7 +35,6 @@ import org.olat.core.gui.control.Event;
 import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController;
 import org.olat.core.gui.translator.Translator;
-import org.olat.core.util.Formatter;
 import org.olat.core.util.Util;
 import org.olat.ims.qti.editor.beecom.objects.EssayQuestion;
 import org.olat.ims.qti.editor.beecom.objects.Item;
@@ -82,6 +81,8 @@ public class EssayItemController extends DefaultController implements Controller
 		main.contextPut("response", essayQuestion.getEssayResponse());
 		main.contextPut("mediaBaseURL", qtiPackage.getMediaBaseURL());
 		main.contextPut("isRestrictedEdit", restrictedEdit ? Boolean.TRUE : Boolean.FALSE);
+		main.contextPut("isSurveyMode", qtiPackage.getQTIDocument().isSurvey() ? "true" : "false");
+		
 		setInitialComponent(main);
 	}
 
@@ -115,6 +116,19 @@ public class EssayItemController extends DefaultController implements Controller
 					iRows = 5;
 					getWindowControl().setWarning(trnsltr.translate("error.rows"));
 				}
+				
+				
+				try {
+					String score = ureq.getParameter("single_score");
+					float sc = Float.parseFloat(score);
+					if(sc <= 0.0001f) {
+						getWindowControl().setWarning(trnsltr.translate("editor.info.mc.zero.points"));
+					}
+					essayQuestion.setMinValue(0.0f);
+					essayQuestion.setMaxValue(sc);
+				} catch(Exception e) {
+					getWindowControl().setWarning(trnsltr.translate("editor.info.mc.zero.points"));
+				}
 
 				if (restrictedEdit) {
 					boolean hasChange = false;
diff --git a/src/main/java/org/olat/ims/qti/editor/ItemMetadataFormController.java b/src/main/java/org/olat/ims/qti/editor/ItemMetadataFormController.java
index 6466328a32d..79a295fd84e 100644
--- a/src/main/java/org/olat/ims/qti/editor/ItemMetadataFormController.java
+++ b/src/main/java/org/olat/ims/qti/editor/ItemMetadataFormController.java
@@ -166,14 +166,17 @@ public class ItemMetadataFormController extends FormBasicController {
 	 *      org.olat.core.gui.control.Controller, org.olat.core.gui.UserRequest)
 	 */
 	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
-		this.setFormTitle("fieldset.legend.metadata");
+		setFormTitle("fieldset.legend.metadata");
 		
 		int t = item.getQuestion().getType();
+		if(!isSurvey && t == Question.TYPE_ESSAY) {
+			setFormWarning("warning.essay.test");
+		}
 		
 		if (isSurvey) {
-			this.setFormContextHelp("org.olat.ims.qti.editor", "qed-meta-surv-"+t+".html", "help.hover.qti-meta-"+t);
+			setFormContextHelp("org.olat.ims.qti.editor", "qed-meta-surv-"+t+".html", "help.hover.qti-meta-"+t);
 		} else {
-			this.setFormContextHelp("org.olat.ims.qti.editor", "qed-meta-test-"+t+".html", "help.hover.qti-meta-"+t);
+			setFormContextHelp("org.olat.ims.qti.editor", "qed-meta-test-"+t+".html", "help.hover.qti-meta-"+t);
 		}
 		
 		// Title
diff --git a/src/main/java/org/olat/ims/qti/editor/ItemNodeTabbedFormController.java b/src/main/java/org/olat/ims/qti/editor/ItemNodeTabbedFormController.java
index 92404558187..69045374942 100644
--- a/src/main/java/org/olat/ims/qti/editor/ItemNodeTabbedFormController.java
+++ b/src/main/java/org/olat/ims/qti/editor/ItemNodeTabbedFormController.java
@@ -60,7 +60,6 @@ public class ItemNodeTabbedFormController extends TabbableDefaultController {
 	 * @param wControl
 	 * @param trnsltr
 	 */
-	@SuppressWarnings("unused")
 	public ItemNodeTabbedFormController(Item item, QTIEditorPackage qtiPackage, UserRequest ureq, WindowControl wControl, Translator trnsltr,
 			boolean restrictedEdit) {
 		super(ureq, wControl);
@@ -148,8 +147,8 @@ public class ItemNodeTabbedFormController extends TabbableDefaultController {
 		}
 		if (ctrl != null) { // if item was identified
 			tabbedPane.addTab(translate("tab.question"), ctrl.getInitialComponent());			
-			this.listenTo(ctrl);
-			if (!isSurvey) {
+			listenTo(ctrl);
+			if (!isSurvey && questionType != Question.TYPE_ESSAY) {
 				tabbedPane.addTab(translate("tab.feedback"), feedbackPanel);
 			}
 			Controller itemPreviewController = new ItemPreviewController(getWindowControl(), item, qtiPackage, getTranslator());
diff --git a/src/main/java/org/olat/ims/qti/editor/QTIEditHelper.java b/src/main/java/org/olat/ims/qti/editor/QTIEditHelper.java
index 3519db6be06..9de4b52d1e2 100644
--- a/src/main/java/org/olat/ims/qti/editor/QTIEditHelper.java
+++ b/src/main/java/org/olat/ims/qti/editor/QTIEditHelper.java
@@ -460,8 +460,8 @@ public class QTIEditHelper {
 	 * @param response_labels
 	 * @return Map of choices.
 	 */
-	public static List fetchChoices(List response_labels) {
-		List choices = new ArrayList();
+	public static List<Response> fetchChoices(List response_labels) {
+		List<Response> choices = new ArrayList<Response>();
 		for (Iterator i = response_labels.iterator(); i.hasNext();) {
 			ChoiceResponse choice = new ChoiceResponse();
 			Element response_label = (Element) i.next();
diff --git a/src/main/java/org/olat/ims/qti/editor/QTIEditorMainController.java b/src/main/java/org/olat/ims/qti/editor/QTIEditorMainController.java
index afacd0e07ad..b42ce1fc9a9 100644
--- a/src/main/java/org/olat/ims/qti/editor/QTIEditorMainController.java
+++ b/src/main/java/org/olat/ims/qti/editor/QTIEditorMainController.java
@@ -25,6 +25,7 @@
 
 package org.olat.ims.qti.editor;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Date;
 import java.util.HashMap;
@@ -75,6 +76,7 @@ import org.olat.core.util.mail.ContactList;
 import org.olat.core.util.mail.ContactMessage;
 import org.olat.core.util.memento.Memento;
 import org.olat.core.util.nodes.INode;
+import org.olat.core.util.tree.TreeHelper;
 import org.olat.core.util.tree.TreeVisitor;
 import org.olat.core.util.tree.Visitor;
 import org.olat.core.util.vfs.VFSContainer;
@@ -216,7 +218,7 @@ public class QTIEditorMainController extends MainLayoutBasicController implement
 	private InsertItemTreeModel insertTreeModel;
 	private LockResult lockEntry;
 	private boolean restrictedEdit;
-	private Map history = null;
+	private Map<String, Memento> history = null;
 	private String startedWithTitle;
 	private List<ReferenceImpl> referencees;
 	private ChangeMessageForm chngMsgFrom;
@@ -274,6 +276,7 @@ public class QTIEditorMainController extends MainLayoutBasicController implement
 			}
 			//
 			init(ureq); // initialize the gui
+			updateWarning();
 		} else {
 			String fullName = userManager.getUserDisplayName(lockEntry.getOwner());
 			wControl.setWarning( getTranslator().translate("error.lock", new String[] { fullName,
@@ -326,7 +329,7 @@ public class QTIEditorMainController extends MainLayoutBasicController implement
 		} else {
 			// start with a fresh history. Editor is resumed but no changes were made
 			// so far.
-			history = new HashMap();
+			history = new HashMap<String, Memento>();
 		}
 
 		if (restrictedEdit) {
@@ -337,7 +340,7 @@ public class QTIEditorMainController extends MainLayoutBasicController implement
 
 			mainToolC.setEnabled(CMD_TOOLS_ADD_FIB, false);
 			if (!qtiPackage.getQTIDocument().isSurvey()) mainToolC.setEnabled(CMD_TOOLS_ADD_KPRIM, false);
-			if (qtiPackage.getQTIDocument().isSurvey()) mainToolC.setEnabled(CMD_TOOLS_ADD_FREETEXT, false);
+			mainToolC.setEnabled(CMD_TOOLS_ADD_FREETEXT, false);
 		}
 		mainToolC.setEnabled(CMD_TOOLS_CHANGE_DELETE, false);
 		mainToolC.setEnabled(CMD_TOOLS_CHANGE_MOVE, false);
@@ -383,6 +386,23 @@ public class QTIEditorMainController extends MainLayoutBasicController implement
 			columnLayoutCtr.hideCol2(true);
 		}
 	}
+	
+	private void updateWarning() {
+		boolean warningEssay = false;
+		if(!qtiPackage.getQTIDocument().isSurvey()) {
+			//check if the test contains some essay
+			List<TreeNode> flattedTree = new ArrayList<TreeNode>();
+			TreeHelper.makeTreeFlat(menuTreeModel.getRootNode(), flattedTree);
+			for(TreeNode node:flattedTree) {
+				Object uo = node.getUserObject();
+				if(uo instanceof String && ((String)uo).startsWith("QTIEDIT:ESSAY")) {
+					warningEssay = true;
+					break;
+				}
+			}
+		}
+		main.contextPut("warningEssay", new Boolean(warningEssay));
+	}
 
 
 	/**
@@ -454,6 +474,7 @@ public class QTIEditorMainController extends MainLayoutBasicController implement
 				parentTargetNode.insertQTIObjectAt(subject, targetPos);
 				qtiPackage.serializeQTIDocument();
 				menuTree.setDirty(true); //force rerendering for ajax mode
+				updateWarning();
 			}
 		} else if (source == copyTree) { // catch copy operations
 			cmc.deactivate();
@@ -503,6 +524,7 @@ public class QTIEditorMainController extends MainLayoutBasicController implement
 				menuTree.setSelectedNodeId(newNode.getIdent());
 				event(ureq, menuTree, new Event(MenuTree.COMMAND_TREENODE_CLICKED));
 				qtiPackage.serializeQTIDocument();
+				updateWarning();
 			}
 		} else if (source == insertTree) { // catch insert operations
 			cmc.deactivate();
@@ -512,6 +534,7 @@ public class QTIEditorMainController extends MainLayoutBasicController implement
 			TreeEvent te = (TreeEvent) event;
 			if (te.getCommand().equals(TreeEvent.COMMAND_TREENODE_CLICKED)) { // insert
 				doInsert(ureq, te.getNodeId(), insertTree.getUserObject());
+				updateWarning();
 			}
 		} else if (source == exitVC) {
 			if (event.getCommand().equals(CMD_EXIT_SAVE)) {
@@ -695,7 +718,7 @@ public class QTIEditorMainController extends MainLayoutBasicController implement
 			} else if (CMD_TOOLS_ADD_QPOOL.equals(cmd)) {
 				doSelectQItem(ureq);
 			} else if (CMD_TOOLS_EXPORT_QPOOL.equals(cmd)) {
-				doExportQItem(ureq);
+				doExportQItem();
 			} else if (cmd.startsWith(CMD_TOOLS_ADD_PREFIX)) { // add new object
 				// fetch new object
 				GenericQtiNode insertObject = null;
@@ -741,7 +764,8 @@ public class QTIEditorMainController extends MainLayoutBasicController implement
 				if(deletableMediaFiles!=null && deletableMediaFiles.size()>0) {					
 					String msg = translate("delete.item.media", deletableMediaFiles.toString());
 					deleteMediaDialog = activateYesNoDialog(ureq, null, msg, deleteMediaDialog);
-				}		
+				}
+				updateWarning();
 			}
 			// cleanup controller
 			removeAsListenerAndDispose(deleteDialog);
@@ -811,7 +835,7 @@ public class QTIEditorMainController extends MainLayoutBasicController implement
 				QTIChangeLogMessage clm = new QTIChangeLogMessage(changeLog, chngMsgFrom.hasInformLearners());
 				qtiPackage.commitChangelog(clm);
 				StringBuilder traceMsg = new StringBuilder(chngMsgFrom.hasInformLearners() ? "Visible for ALL \n" : "Visible for GROUP only \n");
-				Tracing.logAudit(traceMsg.append(changeLog).toString(), QTIEditorMainController.class);
+				logAudit(traceMsg.append(changeLog).toString(), null);
 				// save, remove locks and tmp files
 				saveAndExit(ureq);
 			}
@@ -896,6 +920,7 @@ public class QTIEditorMainController extends MainLayoutBasicController implement
 
 		event(ureq, menuTree, new Event(MenuTree.COMMAND_TREENODE_CLICKED));
 		qtiPackage.serializeQTIDocument();
+		updateWarning();
 	}
 	
 	private void doInsert(GenericQtiNode parentTargetNode, GenericQtiNode insertNode, int position) {
@@ -926,7 +951,7 @@ public class QTIEditorMainController extends MainLayoutBasicController implement
 		listenTo(cmc);
 	}
 	
-	private void doExportQItem(UserRequest ureq) {
+	private void doExportQItem() {
 		GenericQtiNode selectedNode = menuTreeModel.getQtiNode(menuTree.getSelectedNodeId());
 		if(selectedNode instanceof ItemNode) {
 			ItemNode itemNode = (ItemNode)selectedNode;
@@ -1005,8 +1030,7 @@ public class QTIEditorMainController extends MainLayoutBasicController implement
 		if (!qtiPackage.getQTIDocument().isSurvey()) tc.addLink(CMD_TOOLS_ADD_KPRIM, translate("tools.add.kprim"), CMD_TOOLS_ADD_KPRIM,
 				"o_mi_qtikprim");
 		tc.addLink(CMD_TOOLS_ADD_FIB, translate("tools.add.cloze"), CMD_TOOLS_ADD_FIB, "o_mi_qtifib");
-		if (qtiPackage.getQTIDocument().isSurvey()) tc.addLink(CMD_TOOLS_ADD_FREETEXT, translate("tools.add.freetext"),
-				CMD_TOOLS_ADD_FREETEXT, "o_mi_qtiessay");
+		tc.addLink(CMD_TOOLS_ADD_FREETEXT, translate("tools.add.freetext"), CMD_TOOLS_ADD_FREETEXT, "o_mi_qtiessay");
 		// change
 		tc.addHeader(translate("tools.change.header"));
 		// change actions
@@ -1059,8 +1083,8 @@ public class QTIEditorMainController extends MainLayoutBasicController implement
 
 		StringBuilder result = new StringBuilder();
 		result.append(translate("qti.restricted.leading"));
-		for (Iterator iter = referencees.iterator(); iter.hasNext();) {
-			ReferenceImpl element = (ReferenceImpl) iter.next();
+		for (Iterator<ReferenceImpl> iter = referencees.iterator(); iter.hasNext();) {
+			ReferenceImpl element = iter.next();
 			// FIXME:discuss:possible performance/cache problem
 			if ("CourseModule".equals(element.getSource().getResourceableTypeName())) {
 				ICourse course = CourseFactory.loadCourse(element.getSource().getResourceableId());
@@ -1154,7 +1178,7 @@ public class QTIEditorMainController extends MainLayoutBasicController implement
 							Memento respMem = null;
 							if (history.containsKey(key)) {
 								// question changed!
-								questMem = (Memento) history.get(key);
+								questMem = history.get(key);
 								hasChanges = true;
 							}
 							// if(!hasChanges){
@@ -1162,11 +1186,11 @@ public class QTIEditorMainController extends MainLayoutBasicController implement
 							// new prefix for responses
 							prefixKey += "/null/";
 							// list contains org.olat.ims.qti.editor.beecom.objects.Response
-							List responses = question != null ? question.getResponses() : null;
+							List<Response> responses = question != null ? question.getResponses() : null;
 							if (responses != null && responses.size() > 0) {
 								// check for changes in each response
-								for (Iterator iter = responses.iterator(); iter.hasNext();) {
-									Response resp = (Response) iter.next();
+								for (Iterator<Response> iter = responses.iterator(); iter.hasNext();) {
+									Response resp = iter.next();
 									if (history.containsKey(prefixKey + resp.getIdent())) {
 										// this response changed!
 										Memento tmpMem = (Memento) history.get(prefixKey + resp.getIdent());
diff --git a/src/main/java/org/olat/ims/qti/editor/_content/index.html b/src/main/java/org/olat/ims/qti/editor/_content/index.html
index 0e533d59dd6..38d3706ba70 100644
--- a/src/main/java/org/olat/ims/qti/editor/_content/index.html
+++ b/src/main/java/org/olat/ims/qti/editor/_content/index.html
@@ -1,2 +1,5 @@
 <h4>$qtititle</h4>
+#if($warningEssay)
+	<div class="b_warning">$r.translate("warning.test.with.essay")</div>
+#end
 $r.render("tabbedPane")
diff --git a/src/main/java/org/olat/ims/qti/editor/_content/tab_essayItem.html b/src/main/java/org/olat/ims/qti/editor/_content/tab_essayItem.html
index 616d4ce6301..7d78c014301 100644
--- a/src/main/java/org/olat/ims/qti/editor/_content/tab_essayItem.html
+++ b/src/main/java/org/olat/ims/qti/editor/_content/tab_essayItem.html
@@ -58,6 +58,11 @@
 		</tbody>
 		</table>
 		<br><br>
+#if($isSurveyMode.equals("false") && !$isRestrictedEdit)
+	$r.translate("score")
+	<input type="text" name="single_score" value="$question.getMaxValue()" size="4" onchange="return setFormDirty('ofo_tab_scitem')" onclick="return setFormDirty('ofo_tab_scitem')"/>
+	<br />
+#end		
 <div class="b_button_group"><input type="submit" value="$r.translateInAttribute("submit")" class="b_button" name="olat_fosm" /></div>
 </form>
 </fieldset>
diff --git a/src/main/java/org/olat/ims/qti/editor/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/ims/qti/editor/_i18n/LocalStrings_de.properties
index 3295c388fe0..6fd74557976 100644
--- a/src/main/java/org/olat/ims/qti/editor/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/ims/qti/editor/_i18n/LocalStrings_de.properties
@@ -391,3 +391,6 @@ tools.tools.preview=Vorschau
 valuation_method=Bewertungsmethode
 valuation_method_multi=Punkte pro Antwort
 valuation_method_single=Alle korrekten Antworten
+warning.essay.test=Diese Frage muss manuell bewertet werden.
+warning.test.with.essay=Dieser enth?lt ein Freitext Frage. Die Freitext Fragen m?ssen manuell bewertet werden und der End Score manuell angepasst.
+
diff --git a/src/main/java/org/olat/ims/qti/editor/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/ims/qti/editor/_i18n/LocalStrings_en.properties
index b7d10faa5a1..cf6564468fc 100644
--- a/src/main/java/org/olat/ims/qti/editor/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/ims/qti/editor/_i18n/LocalStrings_en.properties
@@ -340,3 +340,6 @@ tools.tools.preview=Preview
 valuation_method=Method of assessment
 valuation_method_multi=Score per answer
 valuation_method_single=All correct answers
+warning.essay.test=This question muss be manually corrected.
+warning.test.with.essay=This test contains question of type essay. The essay has to be corrected manually and the final score after the test does not reflect the correction of the essay type and might be adjusted manually later.
+
diff --git a/src/main/java/org/olat/ims/qti/editor/beecom/objects/ChoiceQuestion.java b/src/main/java/org/olat/ims/qti/editor/beecom/objects/ChoiceQuestion.java
index 54a36675115..13517e3f6c6 100644
--- a/src/main/java/org/olat/ims/qti/editor/beecom/objects/ChoiceQuestion.java
+++ b/src/main/java/org/olat/ims/qti/editor/beecom/objects/ChoiceQuestion.java
@@ -113,7 +113,7 @@ public class ChoiceQuestion extends Question implements QTIObject {
 			if (flow_label != null) instance.setFlowLabelClass(flow_label.attributeValue("class"));
 
 			List response_lables = response_lid.selectNodes(".//response_label");
-			List choices = QTIEditHelper.fetchChoices(response_lables);
+			List<Response> choices = QTIEditHelper.fetchChoices(response_lables);
 			instance.setResponses(choices);
 
 			Element resprocessingXML = item.element("resprocessing");
diff --git a/src/main/java/org/olat/ims/qti/editor/beecom/objects/EssayQuestion.java b/src/main/java/org/olat/ims/qti/editor/beecom/objects/EssayQuestion.java
index 3cec74c5f8f..301f71681b8 100644
--- a/src/main/java/org/olat/ims/qti/editor/beecom/objects/EssayQuestion.java
+++ b/src/main/java/org/olat/ims/qti/editor/beecom/objects/EssayQuestion.java
@@ -29,6 +29,7 @@ import java.util.Iterator;
 import java.util.List;
 
 import org.dom4j.Element;
+import org.olat.ims.qti.editor.QTIEditHelper;
 import org.olat.ims.qti.editor.beecom.parser.ParserManager;
 
 /**
@@ -72,7 +73,7 @@ public class EssayQuestion extends Question implements QTIObject {
 			instance.setQuestion(matQuestion);
 	
 		// Response
-		List responses = instance.getResponses();
+		List<Response> responses = instance.getResponses();
 		EssayResponse response = new EssayResponse();
 		Element response_str = (Element)presentationXML.selectSingleNode(".//response_str"); // export uses flow
 
@@ -116,6 +117,22 @@ public class EssayQuestion extends Question implements QTIObject {
 		response_label.addAttribute("rshuffle", "Yes"); // QTI default
 
 		// No resprocessing since only used in survey mode
+		
+		Element resprocessingXML = root.addElement("resprocessing");
+		resprocessingXML.addAttribute("scoremodel","HumanRater");
+
+		Element outcomes = resprocessingXML.addElement("outcomes");
+		Element decvar = outcomes.addElement("decvar");
+		decvar.addAttribute("varname", "SCORE");
+		decvar.addAttribute("vartype", "Decimal");
+		decvar.addAttribute("defaultval", "0");
+		decvar.addAttribute("minvalue", "" + getMinValue());
+		float maxScore = QTIEditHelper.calculateMaxScore(this);
+		maxScore = maxScore > getMaxValue() ? getMaxValue() : maxScore;
+		decvar.addAttribute("maxvalue", "" + maxScore);
+		decvar.addAttribute("cutvalue", "" + maxScore);
+		
+		Element procExtension = resprocessingXML.addElement("itemproc_extension");	
 	}
 	
 
@@ -126,7 +143,7 @@ public class EssayQuestion extends Question implements QTIObject {
 	 */
 	public EssayResponse getEssayResponse(){
 		EssayResponse response = null;
-		for (Iterator iter = getResponses().iterator(); iter.hasNext();){
+		for (Iterator<Response> iter = getResponses().iterator(); iter.hasNext();){
 			response = (EssayResponse) iter.next();
 		} 
 		return response;
diff --git a/src/main/java/org/olat/ims/qti/editor/beecom/objects/OutcomesProcessing.java b/src/main/java/org/olat/ims/qti/editor/beecom/objects/OutcomesProcessing.java
index 002be0e487e..083678a5105 100644
--- a/src/main/java/org/olat/ims/qti/editor/beecom/objects/OutcomesProcessing.java
+++ b/src/main/java/org/olat/ims/qti/editor/beecom/objects/OutcomesProcessing.java
@@ -26,6 +26,7 @@
 package org.olat.ims.qti.editor.beecom.objects;
 
 import java.util.HashMap;
+import java.util.Map;
 
 import org.dom4j.Element;
 
@@ -42,7 +43,7 @@ import org.dom4j.Element;
  */
 public class OutcomesProcessing implements QTIObject {
 
-	private HashMap outcomesProcessing = new HashMap();
+	private Map<String,String> outcomesProcessing = new HashMap<String,String>();
 	
 	// Strings used in outcomes processing
 //	public static final String DEFAULTVAL 	= "defaultval";
@@ -68,7 +69,7 @@ public class OutcomesProcessing implements QTIObject {
 		decvar.addAttribute(CUTVALUE, (String)outcomesProcessing.get(CUTVALUE));
 	}
 
-	public String getField(String key) { return (String)outcomesProcessing.get(key); }
+	public String getField(String key) { return outcomesProcessing.get(key); }
 	
 	public void setField(String key, String value) { outcomesProcessing.put(key, value); }
 
diff --git a/src/main/java/org/olat/ims/qti/editor/tree/QTIEditorTreeModel.java b/src/main/java/org/olat/ims/qti/editor/tree/QTIEditorTreeModel.java
index 61e787b7288..739ec288ef8 100644
--- a/src/main/java/org/olat/ims/qti/editor/tree/QTIEditorTreeModel.java
+++ b/src/main/java/org/olat/ims/qti/editor/tree/QTIEditorTreeModel.java
@@ -75,10 +75,10 @@ public class QTIEditorTreeModel extends GenericTreeModel {
 		GenericQtiNode rootNode = new AssessmentNode(ass, qtiPackage);
 		this.setRootNode(rootNode);
 		//Sections with their Items
-		List sections = ass.getSections();
+		List<Section> sections = ass.getSections();
 		for (int i=0; i < sections.size(); i++) {
 			//get section data
-			Section elem = (Section)sections.get(i);
+			Section elem = sections.get(i);
 			GenericQtiNode sectionNode = new SectionNode(elem, qtiPackage);
 			List<Item> items = elem.getItems();
 			for (int j=0; j < items.size(); j++) {
-- 
GitLab