IMI-Application/src/main/java/de/vanitasvitae/imi/codes/persistence/FileRepository.java

156 lines
5.4 KiB
Java

package de.vanitasvitae.imi.codes.persistence;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import de.vanitasvitae.imi.codes.input.InvalidOptionException;
import de.vanitasvitae.imi.codes.types.StudyNumber;
/**
* Repository, that stores generated sample codes per study to files on disk.
* The repository stores the next sample code which would be generated for any {@link StudyNumber} {@code stn} to
* the directory {@code <base>/stn}.
* If no sample number record has been found for a {@link StudyNumber}, 0 is returned.
*
* Additionally, the repository is initialized with some hard-coded values for studies "AAA" and "BBB".
* If the user tries to generate codes for those studies, the generated codes start at the hard coded values instead
* of 0.
*/
public class FileRepository implements Repository {
private final File base;
private final HashMap<StudyNumber, Integer> hardCoded = new HashMap<>();
/**
* Create a new file-based repository which stores files in the given directory {@code base}.
*
* @param base base directory.
*/
public FileRepository(File base) {
this.base = base;
// Populate the repository with some hard coded values
try {
hardCoded.put(new StudyNumber("AAA"), 35);
hardCoded.put(new StudyNumber("BBB"), 42);
} catch (InvalidOptionException e) {
// It should never happen here, that the hard coded study numbers are invalid.
throw new AssertionError(e);
}
}
/**
* Return the base directory of the repository.
* @return base directory
*/
public File getBaseDirectory() {
return base;
}
// Returns a hard coded value, or 0 if absent.
private int getHardCodedOrZero(StudyNumber studyNumber) {
Integer i = hardCoded.get(studyNumber);
return (i != null ? i : 0);
}
/**
* Return the sample number of the next code which will be generated for the given {@link StudyNumber}.
*
* @param study code for the study
* @return sample number
*/
@Override
public int getNextSampleCode(StudyNumber study) {
File studyNumberFile = new File(base, study.toString());
int next;
// Check, if we have hard-coded values available
if (!studyNumberFile.exists()) {
next = getHardCodedOrZero(study);
} // Otherwise read from file
else {
next = readInt(studyNumberFile);
}
return next;
}
/**
* Write the next sample code number, which should be generated to file.
* The next sample code number should be the last generated sample code number + 1.
*
* @param study study number
* @param nextSampleCode next sample code to be generated.
*
* @throws IOException in case the file cannot be written
*/
@Override
public void setNextSampleCode(StudyNumber study, int nextSampleCode) throws IOException {
writeInt(new File(base, study.toString()), nextSampleCode);
}
/**
* Reads an integer from the first line inside a file. If the file does not exist or is not readable, 0 is returned.
*
* @param file file to read from
* @return integer or 0
*/
private int readInt(File file) {
try(BufferedReader in = new BufferedReader(new FileReader(file))) {
return Integer.parseInt(in.readLine());
} catch (FileNotFoundException e) {
System.out.println("File " + file.getAbsolutePath() + " does not exist.");
return 0;
} catch (IOException e) {
e.printStackTrace();
return 0;
}
}
/**
* Write an integer to a destination file.
* This method throws an {@link IOException} in case the parent directories or the file
* cannot be created or written to.
*
* @param file destination
* @param integer integer to be written
*/
private void writeInt(File file, int integer) throws IOException {
// Check if destination is directory, which would be illegal
if (file.isDirectory()) {
throw new IOException("Provided output directory points to a directory, which is not allowed.");
}
// Make sure, the parent folder exists
File parent = file.getParentFile();
if (!parent.exists() && !parent.mkdirs()) {
throw new IOException("Cannot create parent directory " + parent.getAbsolutePath());
}
// Check if destination file exists and if not, try to create it
if (!file.exists()) {
try {
if (!file.createNewFile()) {
throw new IOException("Output file " +file.getAbsolutePath() + " cannot be created.");
}
} catch (IOException e) {
throw new IOException("Output file " + file.getAbsolutePath() + " cannot be created." , e);
}
}
try(Writer wr = new FileWriter(file)) {
wr.write(Integer.toString(integer));
} catch (FileNotFoundException e) {
// Must not happen
throw new AssertionError(e);
} catch (IOException e) {
throw new IOException("Cannot write to output file " + file.getAbsolutePath(), e);
}
}
}