package fi.utu.ville.exercises.helpers;
import java.util.Collections;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactoryConfigurationError;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Component;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Layout;
import com.vaadin.ui.VerticalLayout;
import fi.utu.ville.exercises.model.Editor;
import fi.utu.ville.exercises.model.EditorHelper;
import fi.utu.ville.exercises.model.ExecutionSettings;
import fi.utu.ville.exercises.model.ExecutionState;
import fi.utu.ville.exercises.model.ExecutionStateChangeListener;
import fi.utu.ville.exercises.model.Executor;
import fi.utu.ville.exercises.model.ExerciseData;
import fi.utu.ville.exercises.model.ExerciseException;
import fi.utu.ville.exercises.model.ExerciseException.ErrorType;
import fi.utu.ville.exercises.model.ExerciseTypeDescriptor;
import fi.utu.ville.exercises.model.PersistenceHandler;
import fi.utu.ville.exercises.model.StatisticalSubmissionInfo;
import fi.utu.ville.exercises.model.StatisticsInfoColumn;
import fi.utu.ville.exercises.model.SubmissionInfo;
import fi.utu.ville.exercises.model.SubmissionListener;
import fi.utu.ville.exercises.model.SubmissionStatisticsGiver;
import fi.utu.ville.exercises.model.SubmissionType;
import fi.utu.ville.exercises.model.SubmissionVisualizer;
import fi.utu.ville.exercises.model.VilleContent;
import fi.utu.ville.exercises.model.VilleUI;
import fi.utu.ville.standardutils.Localizer;
import fi.utu.ville.standardutils.StandardUIConstants;
import fi.utu.ville.standardutils.StandardUIFactory;
import fi.utu.ville.standardutils.TempFilesManager;
import fi.utu.ville.standardutils.XMLHelper;
/**
* A collection of classes that can be used to give implementations that inform the user that certain aspect of the exercise-type system is not really
* implemented for certain exercise-type. These classes should of course only be used temporarily.
*
* @author Riku Haavisto
*
*/
public final class ExerTypeVoidImplCollection {
private ExerTypeVoidImplCollection() {
// this class is just to collect some empty-implementations together
}
/**
* An abstract class that can be extended to get a very simple {@link ExerciseTypeDescriptor}-implementor returning more or less void-values for everything
* else than {@link Executor}. <b>Only usable for starting a new exercise-type-development by first developing the {@link Executor} with some fixed test
* data-set.</b>
*
* @author Riku Haavisto
*
*/
public static abstract class NoDataExerciseDescriptor implements
ExerciseTypeDescriptor<VoidExerciseData, VoidSubmissionData> {
/**
*
*/
private static final long serialVersionUID = 6388065029097594861L;
@Override
public PersistenceHandler<VoidExerciseData, VoidSubmissionData> newExerciseXML() {
return VoidExerciseXMLHandler.INSTANCE;
}
@Override
public Editor<VoidExerciseData> newExerciseEditor() {
return new VoidExerciseEditor();
}
@Override
public Class<VoidExerciseData> getTypeDataClass() {
return VoidExerciseData.class;
}
@Override
public Class<VoidSubmissionData> getSubDataClass() {
return VoidSubmissionData.class;
}
@Override
public SubmissionStatisticsGiver<VoidExerciseData, VoidSubmissionData> newStatisticsGiver() {
return new VoidSubmissionDataStatsGiver<VoidExerciseData, VoidSubmissionData>();
}
@Override
public SubmissionVisualizer<VoidExerciseData, VoidSubmissionData> newSubmissionVisualizer(String assignmentName,Localizer localizer) {
return new VoidSubmissionVisualizer<VoidExerciseData, VoidSubmissionData>();
}
@Override
public String getTypeDescription(Localizer localizer) {
return "Void-description";
}
}
/**
* An abstract class that can be extended to get a very simple {@link Executor}-implementor that does not care about {@link ExerciseData}-object it
* receives. <b>Only usable for starting a new exercise-type-development by first developing the {@link Executor} with some fixed test data-set.</b>
*
* @author Riku Haavisto
*
*/
public abstract static class RealSimpleExerciseExecutor extends
VerticalLayout implements
Executor<VoidExerciseData, VoidSubmissionData> {
/**
*
*/
private static final long serialVersionUID = 1683026008965901979L;
private final ExerciseExecutionHelper<VoidSubmissionData> execHelper =
new ExerciseExecutionHelper<VoidSubmissionData>();
private Localizer localizer;
/**
* @return current {@link Localizer}
*/
protected Localizer getLocalizer() {
return localizer;
}
/**
* Creates the layout for the class extending {@link RealSimpleExerciseExecutor}. The layout should be added to implementor itself as it extends
* {@link VerticalLayout}.
*/
protected abstract void doLayout();
/**
* @return the correctness of the current state of the {@link Executor} as double in range 0.0 - 1.0
*/
protected abstract double getCorrectness();
@Override
public void initialize(Localizer localizer,
VoidExerciseData exerciseData, VoidSubmissionData oldSubm,
TempFilesManager materials, ExecutionSettings execSettings)
throws ExerciseException {
this.localizer = localizer;
doLayout();
}
@Override
public Component getView() {
return this;
}
@Override
public void askSubmit(SubmissionType askedSubmType) {
execHelper.informOnlySubmit(getCorrectness(), null, askedSubmType,
null);
}
@Override
public void registerSubmitListener(
SubmissionListener<VoidSubmissionData> submitListener) {
execHelper.registerSubmitListener(submitListener);
}
@Override
public void shutdown() {
// nothing to do
}
@Override
public void askReset() {
// nothing to do
}
@Override
public void registerExecutionStateChangeListener(
ExecutionStateChangeListener execStateListener) {
execHelper
.registerExerciseExecutionStateListener(execStateListener);
}
@Override
public ExecutionState getCurrentExecutionState() {
return execHelper.getState();
}
}
/**
* An {@link Editor}-implementor that only has a button for saving an empty-xml-file. Only usable in conjunction with {@link NoDataExerciseDescriptor}. The
* stub-ViLLE requires some file to be saved before the {@link Executor} of an exercise-type can be loaded; the empty file returned by this class can act as
* such if the {@link Executor} does not yet use any real {@link ExerciseData}-object.
*
* @author Riku Haavisto
*/
public static final class VoidExerciseEditor extends VilleContent
implements Editor<VoidExerciseData> {
public VoidExerciseEditor() {
super(null);
}
/**
*
*/
private static final long serialVersionUID = 3825284271956719565L;
private EditorHelper<VoidExerciseData> genExerInfoEditor;
@Override
public void doLayout() {
Button saveButton = new Button("save");
saveButton.addClickListener(new ClickListener() {
/**
*
*/
private static final long serialVersionUID = 7007598145996138576L;
@Override
public void buttonClick(ClickEvent event) {
genExerInfoEditor
.informSaveListeners(VoidExerciseData.INSTANCE);
}
});
this.addComponent(saveButton);
}
@Override
public VilleContent getView() {
return this;
}
@Override
public void initialize(VilleUI villeUI, Localizer localizer,
VoidExerciseData oldData,
EditorHelper<VoidExerciseData> genExerInfoEditor)
throws ExerciseException {
this.genExerInfoEditor = genExerInfoEditor;
doLayout();
}
@Override
public boolean isOkToExit() {
return true;
}
@Override
public String getViewName() {
return "testeditor";
}
}
/**
* Empty implementation for the {@link ExerciseData} interface.
*
* @author Riku Haavisto
*
*/
public static final class VoidExerciseData implements ExerciseData {
/**
*
*/
private static final long serialVersionUID = 5033069436051595412L;
public static final VoidExerciseData INSTANCE = new VoidExerciseData();
private VoidExerciseData() {
}
}
/**
* Empty implementation for the {@link PersistenceHandler}. Creates empty XML-files and returns {@link VoidExerciseData #INSTANCE} or
* {@link VoidSubmissionData} from its load-methods regardless of the file really used.
*
* @author Riku Haavisto
*
*/
public static final class VoidExerciseXMLHandler implements
PersistenceHandler<VoidExerciseData, VoidSubmissionData> {
/**
*
*/
private static final long serialVersionUID = 5033069436051595412L;
public static final VoidExerciseXMLHandler INSTANCE = new VoidExerciseXMLHandler();
private VoidExerciseXMLHandler() {
}
@Override
public byte[] saveExerData(VoidExerciseData etd,
TempFilesManager tempFiles, ByRefSaver matSaver)
throws ExerciseException {
try {
return XMLHelper.xmlToBytes(XMLHelper.createEmptyDocument());
} catch (TransformerConfigurationException e) {
throw new ExerciseException(ErrorType.EXER_WRITE_ERROR, "", e);
} catch (TransformerException e) {
throw new ExerciseException(ErrorType.EXER_WRITE_ERROR, "", e);
} catch (TransformerFactoryConfigurationError e) {
throw new ExerciseException(ErrorType.EXER_WRITE_ERROR, "", e);
} catch (ParserConfigurationException e) {
throw new ExerciseException(ErrorType.EXER_WRITE_ERROR, "", e);
}
}
@Override
public VoidExerciseData loadExerData(byte[] inStream,
TempFilesManager tempFiles, ByRefLoader matLoader)
throws ExerciseException {
return VoidExerciseData.INSTANCE;
}
@Override
public byte[] saveSubmission(VoidSubmissionData subm,
TempFilesManager tempManager) throws ExerciseException {
try {
return XMLHelper.xmlToBytes(XMLHelper.createEmptyDocument());
} catch (TransformerConfigurationException e) {
throw new ExerciseException(ErrorType.EXER_WRITE_ERROR, "", e);
} catch (TransformerException e) {
throw new ExerciseException(ErrorType.EXER_WRITE_ERROR, "", e);
} catch (TransformerFactoryConfigurationError e) {
throw new ExerciseException(ErrorType.EXER_WRITE_ERROR, "", e);
} catch (ParserConfigurationException e) {
throw new ExerciseException(ErrorType.EXER_WRITE_ERROR, "", e);
}
}
@Override
public VoidSubmissionData loadSubmission(byte[] inStream,
boolean forStatGiver, TempFilesManager tempManager)
throws ExerciseException {
return VoidSubmissionData.INSTANCE;
}
}
/**
* Empty implementation for the {@link SubmissionInfo} interface.
*
* @author Riku Haavisto
*
*/
public static final class VoidSubmissionData implements SubmissionInfo {
/**
*
*/
private static final long serialVersionUID = 5033069436051595412L;
public static final VoidSubmissionData INSTANCE = new VoidSubmissionData();
private VoidSubmissionData() {
}
}
/**
* <p>
* Empty implementation for the {@link SubmissionStatisticsGiver} that can be used with any implementor of the {@link SubmissionInfo}-interface.
* </p>
* <p>
* Only displays a localized message stating that "Submission statistics viewer is not implemented for the exercise type".
* </p>
* <p>
* In principle {@link SubmissionStatisticsGiver} can be implemented later than the rest of an exercise-type if the {@link SubmissionInfo} for that
* exercise-type is well thought out (so that it contains enough data of done submissions).
* </p>
*
* @author Riku Haavisto
*
* @param <S>
* implementor of the {@link SubmissionInfo}-interface.
*/
public static final class VoidSubmissionDataStatsGiver<E extends ExerciseData, S extends SubmissionInfo>
implements SubmissionStatisticsGiver<E, S> {
/**
*
*/
private static final long serialVersionUID = 2796141876732642688L;
private Localizer localizer;
@Override
public void initialize(E exercise,
List<StatisticalSubmissionInfo<S>> dataObjects,
Localizer localizer, TempFilesManager tempFiles) {
this.localizer = localizer;
// Void method
}
@Override
public Layout getView() {
HorizontalLayout info = StandardUIFactory
.getInformationPanel(localizer
.getUIText(StandardUIConstants.TYPE_SUBMISSION_STATISTICS_GIVER_NOT_IMPL));
Layout res = new VerticalLayout();
res.addComponent(info);
return res;
}
@Override
public List<StatisticsInfoColumn<?>> getAsTabularData() {
return Collections.emptyList();
}
}
/**
* <p>
* Empty implementation for the {@link SubmissionVisualizer} that can be used with any implementor of the {@link SubmissionInfo}-interface.
* </p>
* <p>
* Only displays a localized message stating that "Submission viewer / export is not implemented for the exercise type".
* </p>
* <p>
* In principle {@link SubmissionVisualizer} can be implemented later than the rest of an exercise-type if the {@link SubmissionInfo} for that exercise-type
* is well thought out (so that it contains enough data of done submissions).
* </p>
*
* @author Riku Haavisto
*
* @param <S>
* implementor of the {@link SubmissionInfo}-interface.
*/
public static final class VoidSubmissionVisualizer<E extends ExerciseData, S extends SubmissionInfo>
implements SubmissionVisualizer<E, S> {
/**
*
*/
private static final long serialVersionUID = -7703972393720883138L;
private Localizer localizer;
@Override
public Layout getView() {
HorizontalLayout info = StandardUIFactory
.getInformationPanel(localizer
.getUIText(StandardUIConstants.TYPE_SUBMISSION_VIEWER_NOT_IMPLEMENTED));
Layout res = new VerticalLayout();
res.addComponent(info);
return res;
}
@Override
public String exportSubmissionDataAsText() {
return localizer
.getUIText(StandardUIConstants.TYPE_SUBMISSION_EXPORT_NOT_IMPLEMENTED);
}
@Override
public void initialize(E exercise, S dataObject, Localizer localizer,
TempFilesManager tempManager) {
this.localizer = localizer;
}
}
}