diff --git a/src/main/java/org/olat/ims/qti21/model/xml/TestFeedbackBuilder.java b/src/main/java/org/olat/ims/qti21/model/xml/TestFeedbackBuilder.java index 53923f3b9d89c51f2d6872b5c9ad670d4de6485b..6d6d357f83b069e2b6cc3940c1e0bef9e95fab14 100644 --- a/src/main/java/org/olat/ims/qti21/model/xml/TestFeedbackBuilder.java +++ b/src/main/java/org/olat/ims/qti21/model/xml/TestFeedbackBuilder.java @@ -19,9 +19,18 @@ */ package org.olat.ims.qti21.model.xml; +import java.io.StringReader; import java.util.List; +import org.cyberneko.html.parsers.SAXParser; +import org.olat.core.logging.OLog; +import org.olat.core.logging.Tracing; +import org.olat.core.util.StringHelper; +import org.olat.core.util.filter.FilterFactory; import org.olat.ims.qti21.QTI21Constants; +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.helpers.DefaultHandler; import uk.ac.ed.ph.jqtiplus.node.expression.Expression; import uk.ac.ed.ph.jqtiplus.node.expression.general.BaseValue; @@ -48,6 +57,8 @@ import uk.ac.ed.ph.jqtiplus.value.SingleValue; */ public class TestFeedbackBuilder { + private static final OLog log = Tracing.createLoggerFor(TestFeedbackBuilder.class); + private final TestFeedback testFeedback; private final AssessmentTest assessmentTest; @@ -74,8 +85,7 @@ public class TestFeedbackBuilder { } public OutcomeRule getResponseRule() { - OutcomeRule feedbackRule = findFeedbackRule(testFeedback.getOutcomeValue()); - return feedbackRule; + return findFeedbackRule(testFeedback.getOutcomeValue()); } public boolean isPassedRule() { @@ -210,4 +220,51 @@ public class TestFeedbackBuilder { } return false; } + + /** + * + * @param value The content of the feedback. + * @return + */ + public static boolean isEmpty(String value) { + if(!StringHelper.containsNonWhitespace(value)) { + return true; + } + if(StringHelper.containsNonWhitespace(FilterFactory.getHtmlTagsFilter().filter(value))) { + return false; + } + + try { + SAXParser parser = new SAXParser(); + HTMLHandler contentHandler = new HTMLHandler(); + parser.setContentHandler(contentHandler); + parser.parse(new InputSource(new StringReader(value))); + return !contentHandler.hasRelevantTags(); + } catch (Exception e) { + log.error("", e); + } + return true; + } + + private static class HTMLHandler extends DefaultHandler { + + private int count = 0; + + public boolean hasRelevantTags() { + return count > 0; + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) { + String elem = localName.toLowerCase(); + if("img".equals(elem)) { + count++; + } else if("span".equals(elem) ) { + String cssClass = attributes.getValue("class"); + if(cssClass != null && cssClass.contains("olatFlashMovieViewer")) { + count++; + } + } + } + } } diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/FeedbacksEditorController.java b/src/main/java/org/olat/ims/qti21/ui/editor/FeedbacksEditorController.java index dc15839d99cb918d8c058d684de02f47f419133a..3ec419a9340dbf098b3e60e08c71f2730b2c0802 100644 --- a/src/main/java/org/olat/ims/qti21/ui/editor/FeedbacksEditorController.java +++ b/src/main/java/org/olat/ims/qti21/ui/editor/FeedbacksEditorController.java @@ -43,8 +43,6 @@ import org.olat.core.gui.components.link.Link; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.core.util.CodeHelper; -import org.olat.core.util.StringHelper; -import org.olat.core.util.filter.FilterFactory; import org.olat.core.util.vfs.VFSContainer; import org.olat.ims.qti21.model.xml.AssessmentItemBuilder; import org.olat.ims.qti21.model.xml.ModalFeedbackBuilder; @@ -52,6 +50,7 @@ import org.olat.ims.qti21.model.xml.ModalFeedbackBuilder.ModalFeedbackType; import org.olat.ims.qti21.model.xml.ModalFeedbackCondition; import org.olat.ims.qti21.model.xml.ResponseIdentifierForFeedback; import org.olat.ims.qti21.model.xml.ResponseIdentifierForFeedback.Answer; +import org.olat.ims.qti21.model.xml.TestFeedbackBuilder; import org.olat.ims.qti21.ui.ResourcesMapper; import org.olat.ims.qti21.ui.components.FlowFormItem; import org.olat.ims.qti21.ui.editor.events.AssessmentItemEvent; @@ -287,13 +286,13 @@ public class FeedbacksEditorController extends FormBasicController implements Sy @Override protected boolean validateFormLogic(UserRequest ureq) { - boolean allOk = true; + boolean allOk = super.validateFormLogic(ureq); for(RuledFeedbackForm additionalForm:additionalForms) { allOk &= additionalForm.validateFormLogic(); } - return allOk & super.validateFormLogic(ureq); + return allOk; } @Override @@ -353,8 +352,7 @@ public class FeedbacksEditorController extends FormBasicController implements Sy } public boolean isEmpty() { - String val = textEl.getValue(); - return !StringHelper.containsNonWhitespace(FilterFactory.getHtmlTagsFilter().filter(val)); + return TestFeedbackBuilder.isEmpty(textEl.getValue()); } public boolean isVisible() { @@ -368,7 +366,7 @@ public class FeedbacksEditorController extends FormBasicController implements Sy public void commit() { String title = titleEl.getValue(); String text = textEl.getRawValue(); - if(StringHelper.containsNonWhitespace(FilterFactory.getHtmlTagsFilter().filter(text))) { + if(!TestFeedbackBuilder.isEmpty(text) ) { feedbackBuilder = itemBuilder.getFeedbackBuilder(feedbackType); if(feedbackBuilder == null) { feedbackBuilder = itemBuilder.createFeedbackBuilder(feedbackType); @@ -496,7 +494,7 @@ public class FeedbacksEditorController extends FormBasicController implements Sy feedbackConditions.add(condition.commit()); } - if(StringHelper.containsNonWhitespace(FilterFactory.getHtmlTagsFilter().filter(text)) && feedbackConditions.size() > 0) { + if(!TestFeedbackBuilder.isEmpty(text) && !feedbackConditions.isEmpty()) { if(feedbackBuilder == null) { feedbackBuilder = itemBuilder.createFeedbackBuilder(feedbackType); } @@ -735,13 +733,11 @@ public class FeedbacksEditorController extends FormBasicController implements Sy textValueEl.setVisible(!responseVar); dropDownValueEl.setVisible(responseVar); - String[] answerKeys = new String[] {}; - String[] answerValues = new String[] {}; if(itemBuilder instanceof ResponseIdentifierForFeedback) { ResponseIdentifierForFeedback responseFeedback = (ResponseIdentifierForFeedback)itemBuilder; List<Answer> answers = responseFeedback.getAnswers(); - answerKeys = new String[answers.size()]; - answerValues = new String[answers.size()]; + String[] answerKeys = new String[answers.size()]; + String[] answerValues = new String[answers.size()]; for(int i=0; i<answers.size(); i++) { Answer answer = answers.get(i);