Make TextRenderer and HTMLRenderer thread-safe (or so I think ...)
This commit is contained in:
parent
8774324b65
commit
cf96949f8e
5 changed files with 292 additions and 294 deletions
|
@ -9,6 +9,8 @@ import java.nio.file.Path;
|
|||
import java.nio.file.StandardOpenOption;
|
||||
|
||||
public class HTMLFileRenderer implements Renderer<Path> {
|
||||
@NonNull
|
||||
private static final HTMLRenderer HTML_RENDERER = HTMLRenderer.newInstance();
|
||||
@Setter
|
||||
private Path targetFile;
|
||||
|
||||
|
@ -35,7 +37,7 @@ public class HTMLFileRenderer implements Renderer<Path> {
|
|||
if (!this.isTargetFileDefinedAndWritable()) {
|
||||
throw new IllegalArgumentException("Cannot write to target file. See previous log messages for details.");
|
||||
}
|
||||
final String html = HTMLRenderer.newInstance().render(labyrinth);
|
||||
final String html = HTML_RENDERER.render(labyrinth);
|
||||
try {
|
||||
Files.writeString(this.targetFile, html, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE);
|
||||
} catch (IOException e) {
|
||||
|
|
|
@ -3,6 +3,7 @@ package ch.fritteli.labyrinth;
|
|||
import io.vavr.collection.HashSet;
|
||||
import io.vavr.collection.Set;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
public class HTMLRenderer implements Renderer<String> {
|
||||
private static final String PREAMBLE = "<!DOCTYPE html><html lang=\"en\">" +
|
||||
|
@ -33,11 +34,6 @@ public class HTMLRenderer implements Renderer<String> {
|
|||
"<body>" +
|
||||
"<input type=\"checkbox\" onclick=\"toggleSolution()\">show solution</input>";
|
||||
private static final String POSTAMBLE = "</body></html>";
|
||||
private Labyrinth labyrinth;
|
||||
private int width;
|
||||
private int height;
|
||||
// row counter
|
||||
private int y = 0;
|
||||
|
||||
private HTMLRenderer() {
|
||||
}
|
||||
|
@ -49,29 +45,32 @@ public class HTMLRenderer implements Renderer<String> {
|
|||
|
||||
@NonNull
|
||||
public String render(@NonNull final Labyrinth labyrinth) {
|
||||
this.labyrinth = labyrinth;
|
||||
this.width = labyrinth.getWidth();
|
||||
this.height = labyrinth.getHeight();
|
||||
if (this.width == 0 || this.height == 0) {
|
||||
if (labyrinth.getWidth() == 0 || labyrinth.getHeight() == 0) {
|
||||
return PREAMBLE + POSTAMBLE;
|
||||
}
|
||||
final Generator generator = new Generator(labyrinth);
|
||||
final StringBuilder sb = new StringBuilder(PREAMBLE);
|
||||
sb.append("<table>");
|
||||
while (this.hasNext()) {
|
||||
sb.append(this.next());
|
||||
while (generator.hasNext()) {
|
||||
sb.append(generator.next());
|
||||
}
|
||||
sb.append("</table>");
|
||||
sb.append(POSTAMBLE);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
private static class Generator {
|
||||
private final Labyrinth labyrinth;
|
||||
private int y = 0;
|
||||
|
||||
private boolean hasNext() {
|
||||
return this.y < this.height;
|
||||
return this.y < this.labyrinth.getHeight();
|
||||
}
|
||||
|
||||
private String next() {
|
||||
StringBuilder sb = new StringBuilder("<tr>");
|
||||
for (int x = 0; x < this.width; x++) {
|
||||
for (int x = 0; x < this.labyrinth.getWidth(); x++) {
|
||||
final Tile currentTile = this.labyrinth.getTileAt(x, this.y);
|
||||
sb.append("<td class=\"");
|
||||
sb.append(this.getClasses(currentTile).mkString(" "));
|
||||
|
@ -102,3 +101,4 @@ public class HTMLRenderer implements Renderer<String> {
|
|||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ public class Main {
|
|||
final Labyrinth labyrinth = new Labyrinth(width, height);
|
||||
final TextRenderer textRenderer = TextRenderer.newInstance();
|
||||
System.out.println(textRenderer.render(labyrinth));
|
||||
System.out.println(textRenderer.setRenderingSolution(true).render(labyrinth));
|
||||
System.out.println(textRenderer.setRenderSolution(true).render(labyrinth));
|
||||
final HTMLRenderer htmlRenderer = HTMLRenderer.newInstance();
|
||||
System.out.println(htmlRenderer.render(labyrinth));
|
||||
System.out.println(HTMLFileRenderer.newInstance().render(labyrinth));
|
||||
|
|
|
@ -4,20 +4,12 @@ import lombok.AccessLevel;
|
|||
import lombok.AllArgsConstructor;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.experimental.FieldDefaults;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class TextRenderer implements Renderer<String> {
|
||||
private Labyrinth labyrinth;
|
||||
private int width;
|
||||
private int height;
|
||||
private boolean renderSolution;
|
||||
// column counter
|
||||
private int x;
|
||||
// row counter
|
||||
private int y;
|
||||
// line counter (top-, center- or bottom line of a row)
|
||||
private int line;
|
||||
|
||||
private TextRenderer() {
|
||||
this.renderSolution = false;
|
||||
|
@ -29,31 +21,35 @@ public class TextRenderer implements Renderer<String> {
|
|||
}
|
||||
|
||||
@NonNull
|
||||
public TextRenderer setRenderingSolution(final boolean renderSolution) {
|
||||
public TextRenderer setRenderSolution(final boolean renderSolution) {
|
||||
this.renderSolution = renderSolution;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String render(@NonNull final Labyrinth labyrinth) {
|
||||
this.labyrinth = labyrinth;
|
||||
this.width = labyrinth.getWidth();
|
||||
this.height = labyrinth.getHeight();
|
||||
if (this.width == 0 || this.height == 0) {
|
||||
if (labyrinth.getWidth() == 0 || labyrinth.getHeight() == 0) {
|
||||
return "";
|
||||
}
|
||||
this.x = 0;
|
||||
this.y = 0;
|
||||
this.line = 0;
|
||||
final Generator generator = new Generator(labyrinth, this.renderSolution);
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
while (this.hasNext()) {
|
||||
sb.append(this.next());
|
||||
while (generator.hasNext()) {
|
||||
sb.append(generator.next());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
static class Generator {
|
||||
@NonNull
|
||||
private final Labyrinth labyrinth;
|
||||
private final boolean renderSolution;
|
||||
private int x = 0;
|
||||
private int y = 0;
|
||||
private int line = 0;
|
||||
|
||||
private boolean hasNext() {
|
||||
return this.y < this.height;
|
||||
return this.y < this.labyrinth.getHeight();
|
||||
}
|
||||
|
||||
private String next() {
|
||||
|
@ -82,13 +78,13 @@ public class TextRenderer implements Renderer<String> {
|
|||
private void prepareNextStep() {
|
||||
// do some magic ...
|
||||
this.x++;
|
||||
if (this.x == this.width) {
|
||||
if (this.x == this.labyrinth.getWidth()) {
|
||||
// Reached the end of the row?
|
||||
// On to the next line then!
|
||||
this.x = 0;
|
||||
this.line++;
|
||||
}
|
||||
if (this.line == 2 && this.y < this.height - 1) {
|
||||
if (this.line == 2 && this.y < this.labyrinth.getHeight() - 1) {
|
||||
// Finished rendering the center line, and more rows available?
|
||||
// On to the next row then!
|
||||
this.line = 0;
|
||||
|
@ -103,7 +99,7 @@ public class TextRenderer implements Renderer<String> {
|
|||
}
|
||||
|
||||
private Tile getTileOrNull(final int x, final int y) {
|
||||
if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
|
||||
if (x < 0 || y < 0 || x >= this.labyrinth.getWidth() || y >= this.labyrinth.getHeight()) {
|
||||
return null;
|
||||
}
|
||||
return this.labyrinth.getTileAt(x, y);
|
||||
|
@ -137,7 +133,7 @@ public class TextRenderer implements Renderer<String> {
|
|||
}
|
||||
}
|
||||
result = charDef1.toString() + charDef2;
|
||||
if (this.x == this.width - 1) {
|
||||
if (this.x == this.labyrinth.getWidth() - 1) {
|
||||
result += charDef3 + "\n";
|
||||
}
|
||||
return result;
|
||||
|
@ -156,7 +152,7 @@ public class TextRenderer implements Renderer<String> {
|
|||
|
||||
result = charDef1 + (currentTile.isSolution() && this.renderSolution ? "x" : " ");
|
||||
|
||||
if (this.x == this.width - 1) {
|
||||
if (this.x == this.labyrinth.getWidth() - 1) {
|
||||
result += charDef2 + "\n";
|
||||
}
|
||||
|
||||
|
@ -186,7 +182,7 @@ public class TextRenderer implements Renderer<String> {
|
|||
|
||||
result = charDef1.toString() + charDef2;
|
||||
|
||||
if (this.x == this.width - 1) {
|
||||
if (this.x == this.labyrinth.getWidth() - 1) {
|
||||
result += charDef3;
|
||||
}
|
||||
return result;
|
||||
|
@ -255,7 +251,6 @@ public class TextRenderer implements Renderer<String> {
|
|||
return this;
|
||||
}
|
||||
|
||||
|
||||
CharDefinition horizontal() {
|
||||
return this.left().right();
|
||||
}
|
||||
|
@ -325,3 +320,4 @@ public class TextRenderer implements Renderer<String> {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package ch.fritteli.labyrinth;
|
||||
|
||||
import ch.fritteli.labyrinth.TextRenderer.CharDefinition;
|
||||
import ch.fritteli.labyrinth.TextRenderer.Generator.CharDefinition;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
|
Loading…
Reference in a new issue