Implement HTML table renderer and export
This commit is contained in:
parent
dd1336beb5
commit
fa95d578f5
4 changed files with 149 additions and 25 deletions
47
src/main/java/de/vanitasvitae/imi/codes/CodeGenerator.java
Normal file
47
src/main/java/de/vanitasvitae/imi/codes/CodeGenerator.java
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
package de.vanitasvitae.imi.codes;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import de.vanitasvitae.imi.codes.input.InvalidOptionException;
|
||||||
|
import de.vanitasvitae.imi.codes.persistence.FileRepository;
|
||||||
|
import de.vanitasvitae.imi.codes.types.SampleTubeCode;
|
||||||
|
import de.vanitasvitae.imi.codes.types.SampleType;
|
||||||
|
import de.vanitasvitae.imi.codes.types.StudyNumber;
|
||||||
|
|
||||||
|
public class CodeGenerator {
|
||||||
|
|
||||||
|
private final FileRepository repository = new FileRepository(new File(".imicodes"));
|
||||||
|
|
||||||
|
public CodeGenerator() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SampleTubeCode> generateCodes(StudyNumber studyNumber, SampleType sampleType, int numberOfCodes)
|
||||||
|
throws InvalidOptionException, IOException {
|
||||||
|
List<SampleTubeCode> codes = new ArrayList<>();
|
||||||
|
|
||||||
|
// Read the next sample code from file
|
||||||
|
int nextSampleCode = repository.nextSampleCode(studyNumber);
|
||||||
|
|
||||||
|
int nextTotal = nextSampleCode + numberOfCodes;
|
||||||
|
// Check, if we'd have an overflow of sample numbers
|
||||||
|
// We check like this to prevent integer overflows
|
||||||
|
if (nextSampleCode > 9999 || numberOfCodes > 9999 || nextTotal - 1 > 9999) {
|
||||||
|
throw new InvalidOptionException("Study " + studyNumber + "would have too many sample tubes" +
|
||||||
|
" (" + (nextTotal - 1) + "). Aborting.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write back the number of the next sample number that should be generated next time
|
||||||
|
repository.writeNextSampleCode(studyNumber, nextSampleCode + numberOfCodes);
|
||||||
|
|
||||||
|
// Generate codes
|
||||||
|
for (int i = 0; i < numberOfCodes; i++) {
|
||||||
|
codes.add(new SampleTubeCode(studyNumber, sampleType, nextSampleCode + i));
|
||||||
|
}
|
||||||
|
|
||||||
|
return codes;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
package de.vanitasvitae.imi.codes;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import de.vanitasvitae.imi.codes.types.SampleTubeCode;
|
||||||
|
|
||||||
|
public class HtmlTableStringBuilder {
|
||||||
|
|
||||||
|
private StringBuilder html;
|
||||||
|
|
||||||
|
public HtmlTableStringBuilder(String title, List<SampleTubeCode> codes) {
|
||||||
|
html = new StringBuilder("<!DOCTYPE html>\n")
|
||||||
|
.append("<html>\n")
|
||||||
|
.append("<head>\n")
|
||||||
|
.append("<style>\n")
|
||||||
|
.append("table, th, td {\n")
|
||||||
|
.append(" border: 1px solid black;\n")
|
||||||
|
.append("}\n")
|
||||||
|
.append("</style>\n")
|
||||||
|
.append("</head>")
|
||||||
|
.append("<body>")
|
||||||
|
.append("\n");
|
||||||
|
|
||||||
|
// Add title
|
||||||
|
html.append("<h2>").append(title).append("</h2>\n");
|
||||||
|
|
||||||
|
// Open table
|
||||||
|
html.append("<table>\n")
|
||||||
|
.append("<tr>\n")
|
||||||
|
.append("<th>Code</th>\n")
|
||||||
|
.append("</tr>\n");
|
||||||
|
|
||||||
|
// Append table entries
|
||||||
|
for (SampleTubeCode c : codes) {
|
||||||
|
html.append("<tr>\n")
|
||||||
|
.append("<td>").append(c.toString()).append("</td>\n")
|
||||||
|
.append("</tr>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close table
|
||||||
|
html.append("</table>\n");
|
||||||
|
|
||||||
|
// Close body and html
|
||||||
|
html.append("</body>\n");
|
||||||
|
html.append("</html>");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return html.toString();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,12 +1,14 @@
|
||||||
package de.vanitasvitae.imi.codes;
|
package de.vanitasvitae.imi.codes;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import de.vanitasvitae.imi.codes.input.Arguments;
|
import de.vanitasvitae.imi.codes.input.Arguments;
|
||||||
import de.vanitasvitae.imi.codes.input.InputValidator;
|
import de.vanitasvitae.imi.codes.input.InputValidator;
|
||||||
import de.vanitasvitae.imi.codes.input.InvalidOptionException;
|
import de.vanitasvitae.imi.codes.input.InvalidOptionException;
|
||||||
import de.vanitasvitae.imi.codes.persistence.FileRepository;
|
|
||||||
import de.vanitasvitae.imi.codes.types.SampleTubeCode;
|
import de.vanitasvitae.imi.codes.types.SampleTubeCode;
|
||||||
import de.vanitasvitae.imi.codes.types.SampleType;
|
import de.vanitasvitae.imi.codes.types.SampleType;
|
||||||
import de.vanitasvitae.imi.codes.types.StudyNumber;
|
import de.vanitasvitae.imi.codes.types.StudyNumber;
|
||||||
|
@ -19,10 +21,17 @@ import org.apache.commons.cli.ParseException;
|
||||||
|
|
||||||
public class Main {
|
public class Main {
|
||||||
|
|
||||||
private static final String NAME_JAR = "imicodes";
|
private static final String NAME_JAR = "java -jar imicodes.jar";
|
||||||
private static final String HELP_HEADER = "Generate ID codes for sample tubes.";
|
private static final String HELP_HEADER = "Generate ID codes for sample tubes.";
|
||||||
private static final String HELP_FOOTER = "\nAuthor: Paul Schaub <paul.schaub@wwu.de>";
|
private static final String HELP_FOOTER = "\nAuthor: Paul Schaub <paul.schaub@wwu.de>";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entry point to the program.
|
||||||
|
* Any provided arguments are parsed and the behaviour of the program is modified respectively.
|
||||||
|
* A list of available options can be displayed using "-h".
|
||||||
|
*
|
||||||
|
* @param args arguments
|
||||||
|
*/
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
Options options = Arguments.getCommandLineOptions();
|
Options options = Arguments.getCommandLineOptions();
|
||||||
CommandLineParser parser = new DefaultParser();
|
CommandLineParser parser = new DefaultParser();
|
||||||
|
@ -42,18 +51,24 @@ public class Main {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse arguments
|
|
||||||
StudyNumber studyNumber;
|
StudyNumber studyNumber;
|
||||||
SampleType sampleType;
|
SampleType sampleType;
|
||||||
int numberOfCodes;
|
int numberOfCodes;
|
||||||
File outputPath;
|
File outputPath;
|
||||||
boolean externalBrowser;
|
boolean externalBrowser;
|
||||||
|
|
||||||
|
// Parse arguments
|
||||||
try {
|
try {
|
||||||
studyNumber = InputValidator.validateStudyNumber(arguments.getOptionValue(Arguments.STUDY_NUMBER));
|
studyNumber = InputValidator.validateStudyNumber(arguments.getOptionValue(Arguments.STUDY_NUMBER));
|
||||||
sampleType = InputValidator.validateSampleType(arguments.getOptionValue(Arguments.SAMPLE_TYPE));
|
sampleType = InputValidator.validateSampleType(arguments.getOptionValue(Arguments.SAMPLE_TYPE));
|
||||||
numberOfCodes = InputValidator.validateNumberOfCodes(arguments.getOptionValue(Arguments.NUMBER_CODES));
|
numberOfCodes = InputValidator.validateNumberOfCodes(arguments.getOptionValue(Arguments.NUMBER_CODES));
|
||||||
|
|
||||||
|
if (arguments.hasOption(Arguments.OUTPUT_DESTINATION)) {
|
||||||
outputPath = InputValidator.validateOutputPath(arguments.getOptionValue(Arguments.OUTPUT_DESTINATION));
|
outputPath = InputValidator.validateOutputPath(arguments.getOptionValue(Arguments.OUTPUT_DESTINATION));
|
||||||
|
} else {
|
||||||
|
outputPath = InputValidator.validateOutputPath("./out.html");
|
||||||
|
}
|
||||||
|
|
||||||
externalBrowser = arguments.hasOption(Arguments.EXTERNAL_BROWSER);
|
externalBrowser = arguments.hasOption(Arguments.EXTERNAL_BROWSER);
|
||||||
} catch (InvalidOptionException e) {
|
} catch (InvalidOptionException e) {
|
||||||
// Something is wrong with the users input, so exit.
|
// Something is wrong with the users input, so exit.
|
||||||
|
@ -61,32 +76,28 @@ public class Main {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileRepository repository = new FileRepository(new File(".imicodes"));
|
CodeGenerator generator = new CodeGenerator();
|
||||||
|
|
||||||
// Read the next sample code from file
|
List<SampleTubeCode> codes;
|
||||||
int nextSampleCode = repository.nextSampleCode(studyNumber);
|
|
||||||
|
|
||||||
int nextTotal = nextSampleCode + numberOfCodes;
|
|
||||||
// Check, if we'd have an overflow of sample numbers
|
|
||||||
// We check like this to prevent integer overflows
|
|
||||||
if (nextSampleCode > 9999 || numberOfCodes > 9999 || nextTotal - 1 > 9999) {
|
|
||||||
System.out.println("Study " + studyNumber + "would have too many sample tubes" +
|
|
||||||
" (" + (nextTotal - 1) + "). Aborting.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write back the number of the next sample number that should be generated next time
|
|
||||||
try {
|
try {
|
||||||
repository.writeNextSampleCode(studyNumber, nextSampleCode + numberOfCodes);
|
codes = generator.generateCodes(studyNumber, sampleType, numberOfCodes);
|
||||||
|
} catch (InvalidOptionException e) {
|
||||||
|
System.out.println(e.getMessage());
|
||||||
|
return;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Now we are finished with dangerous IO...
|
|
||||||
|
|
||||||
// Generate codes
|
String html = new HtmlTableStringBuilder("IMI Sample Tube Code Generator", codes).toString();
|
||||||
for (int i = 0; i < numberOfCodes; i++) {
|
writeHtml(html, outputPath);
|
||||||
System.out.println(new SampleTubeCode(studyNumber, sampleType, nextSampleCode + i));
|
}
|
||||||
|
|
||||||
|
private static void writeHtml(String html, File destination) {
|
||||||
|
try(Writer writer = new FileWriter(destination)) {
|
||||||
|
writer.write(html);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package de.vanitasvitae.imi.codes.input;
|
package de.vanitasvitae.imi.codes.input;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import de.vanitasvitae.imi.codes.types.SampleType;
|
import de.vanitasvitae.imi.codes.types.SampleType;
|
||||||
import de.vanitasvitae.imi.codes.types.StudyNumber;
|
import de.vanitasvitae.imi.codes.types.StudyNumber;
|
||||||
|
@ -70,7 +71,20 @@ public class InputValidator {
|
||||||
* destination is not writable.
|
* destination is not writable.
|
||||||
*/
|
*/
|
||||||
public static File validateOutputPath(String path) throws InvalidOptionException {
|
public static File validateOutputPath(String path) throws InvalidOptionException {
|
||||||
// TODO
|
File file = new File(path);
|
||||||
return null;
|
File parent = file.getParentFile();
|
||||||
|
if (!parent.exists() || parent.isFile()) {
|
||||||
|
throw new InvalidOptionException("Invalid directory " + parent.getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!file.exists()) {
|
||||||
|
try {
|
||||||
|
file.createNewFile();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new InvalidOptionException("Cannot write file " + file.getAbsolutePath(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue