113 lines
4.1 KiB
Java
113 lines
4.1 KiB
Java
package ch.fritteli.maze.generator.renderer.textfile;
|
|
|
|
import ch.fritteli.maze.generator.model.Maze;
|
|
import ch.fritteli.maze.generator.renderer.Renderer;
|
|
import ch.fritteli.maze.generator.renderer.text.TextRenderer;
|
|
import io.vavr.collection.List;
|
|
import io.vavr.control.Option;
|
|
import io.vavr.control.Try;
|
|
import lombok.NonNull;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.util.NoSuchElementException;
|
|
|
|
@Slf4j
|
|
public class TextFileRenderer implements Renderer<List<Path>> {
|
|
@NonNull
|
|
private static final TextRenderer TEXT_RENDERER = TextRenderer.newInstance();
|
|
@NonNull
|
|
private Option<Path> targetMazeFile;
|
|
@NonNull
|
|
private Option<Path> targetSolutionFile;
|
|
|
|
private TextFileRenderer() {
|
|
this.targetMazeFile = Try
|
|
.of(() -> Files.createTempFile("maze_", ".txt"))
|
|
.onFailure(ex -> log.error("Unable to set default target file", ex))
|
|
.toOption();
|
|
|
|
this.targetSolutionFile = this.targetMazeFile.toTry()
|
|
.map(Path::getParent)
|
|
.flatMap(parent -> this.targetMazeFile.toTry()
|
|
.map(Path::getFileName)
|
|
.map(Path::toString)
|
|
.map(a -> a.replace(".txt", "-solution.txt"))
|
|
.map(parent::resolve))
|
|
.onFailure(ex -> log.error("Unable to set default solution target file", ex))
|
|
.toOption();
|
|
}
|
|
|
|
@NonNull
|
|
public static TextFileRenderer newInstance() {
|
|
return new TextFileRenderer();
|
|
}
|
|
|
|
public boolean isTargetMazeFileDefinedAndWritable() {
|
|
return this.targetMazeFile
|
|
.map(Path::toFile)
|
|
.exists(File::canWrite);
|
|
}
|
|
|
|
public boolean isTargetSolutionFileDefinedAndWritable() {
|
|
return this.targetSolutionFile
|
|
.map(Path::toFile)
|
|
.exists(File::canWrite);
|
|
}
|
|
|
|
@NonNull
|
|
public TextFileRenderer setTargetMazeFile(@NonNull final Path targetMazeFile) {
|
|
this.targetMazeFile = Option.of(targetMazeFile);
|
|
return this;
|
|
}
|
|
|
|
@NonNull
|
|
public TextFileRenderer setTargetSolutionFile(@NonNull final Path targetSolutionFile) {
|
|
this.targetSolutionFile = Option.of(targetSolutionFile);
|
|
return this;
|
|
}
|
|
|
|
@NonNull
|
|
@Override
|
|
public List<Path> render(@NonNull final Maze maze) {
|
|
if (!this.isTargetMazeFileDefinedAndWritable()) {
|
|
try {
|
|
Files.createFile(this.targetMazeFile.get());
|
|
} catch (IOException | NoSuchElementException e) {
|
|
log.error("Cannot write to target maze file.", e);
|
|
throw new IllegalArgumentException("Cannot write to target maze file.", e);
|
|
}
|
|
}
|
|
if (!this.isTargetSolutionFileDefinedAndWritable()) {
|
|
try {
|
|
Files.createFile(this.targetSolutionFile.get());
|
|
} catch (IOException | NoSuchElementException e) {
|
|
throw new IllegalArgumentException("Cannot write to target solution file.", e);
|
|
}
|
|
}
|
|
final String text;
|
|
final String solution;
|
|
synchronized (TEXT_RENDERER) {
|
|
text = TEXT_RENDERER.setRenderSolution(false).render(maze).strip();
|
|
solution = TEXT_RENDERER.setRenderSolution(true).render(maze).strip();
|
|
}
|
|
final Path targetMazeFile = this.targetMazeFile.get();
|
|
final Path targetSolutionFile = this.targetSolutionFile.get();
|
|
try {
|
|
Files.write(targetMazeFile, text.getBytes(StandardCharsets.UTF_8));
|
|
} catch (IOException e) {
|
|
log.error("Failed writing to file " + targetMazeFile.normalize(), e);
|
|
}
|
|
try {
|
|
Files.write(targetSolutionFile, solution.getBytes(StandardCharsets.UTF_8));
|
|
} catch (IOException e) {
|
|
log.error("Failed writing to file " + targetSolutionFile.normalize());
|
|
}
|
|
return List.of(targetMazeFile, targetSolutionFile);
|
|
}
|
|
}
|