156 lines
5.4 KiB
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);
|
|
}
|
|
}
|
|
}
|