package fi.utu.ville.exercises.stub;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.io.FileUtils;
import fi.utu.ville.exercises.model.ExerciseException;
import fi.utu.ville.exercises.model.ExerciseException.ErrorType;
import fi.utu.ville.exercises.model.PersistenceHandler.ByRefLoader;
import fi.utu.ville.exercises.model.PersistenceHandler.ByRefSaver;
import fi.utu.ville.standardutils.AFFile;
import fi.utu.ville.standardutils.AbstractFile;
import fi.utu.ville.standardutils.Util;
/**
* Stub-implementation for scoped material saving and loading ( {@link ByRefSaver} and {@link ByRefLoader}).
*
*
*
* @author Riku Haavisto
*
*/
public class StubMatPersistenceHandler implements ByRefSaver, ByRefLoader {
/**
*
*/
private static final long serialVersionUID = 1432351237084696903L;
private final String matScope;
private final Set<String> regToBeSaved = new HashSet<String>();
private final boolean inSaveMode;
/**
* Constructs a new {@link StubMatPersistenceHandler} and initializes it to use certain matScope-folder.
*
* @param matScope
* path to folder to be used as material-scope
* @param inSaveMode
* whether to allow saving by reference or not
*/
StubMatPersistenceHandler(String matScope, boolean inSaveMode) {
this.matScope = matScope;
this.inSaveMode = inSaveMode;
}
@Override
public AbstractFile loadByReference(String refId) throws ExerciseException {
File afFile = new File(matScope + File.separator + refId);
if (afFile.exists()) {
return new ExistingAFFile(afFile);
} else {
throw new ExerciseException(ErrorType.OTHER,
"No persistent-material with refId= " + refId + " exists",
null);
}
}
@Override
public String saveByReference(AbstractFile toSave) throws ExerciseException {
if (!inSaveMode) {
throw new IllegalStateException("Not in save mode!");
}
// create the folder only 'lazily'
File matScopeF = new File(matScope);
if (!matScopeF.exists()) {
matScopeF.mkdir();
}
if (toSave instanceof ExistingAFFile) {
ExistingAFFile fileToSave = (ExistingAFFile) toSave;
String oldRef = fileToSave.getName();
regToBeSaved.add(oldRef);
return oldRef;
} else {
File newlyCreatedFile = Util.getNonConflictingFile(matScope,
toSave.getName());
try {
FileUtils.writeByteArrayToFile(newlyCreatedFile,
toSave.getRawData());
} catch (IOException e) {
throw new ExerciseException(ErrorType.OTHER,
"Error saving abstract-file persistently", e);
}
String newRef = newlyCreatedFile.getName();
regToBeSaved.add(newRef);
return newRef;
}
}
/**
* This method attempts to clean-up all the saved material-files that have become obsolete (were not saved when the exercise-instance was last saved).
*/
void cleanupObsoleteFiles() {
if (!inSaveMode) {
throw new IllegalStateException("Not in save mode!");
}
File matFolder = new File(matScope);
if (!matFolder.exists()) {
// nothing is really saved by given exercise-type
return;
}
for (String fname : matFolder.list()) {
if (!regToBeSaved.contains(fname)) {
File toDel = new File(matScope + File.separator + fname);
toDel.delete();
}
}
}
// this is used only as a marker class to know which files have already been
// saved to disk
private static final class ExistingAFFile extends AFFile {
/**
*
*/
private static final long serialVersionUID = 5235576214041087662L;
public ExistingAFFile(File file) {
super(file);
}
}
}