Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,8 @@ out/
!**/src/main/**/out/
!**/src/test/**/out/

# macOS
**/.DS_Store
.DS_Store

.worktrees/
2 changes: 2 additions & 0 deletions area-rectangular-room/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ plugins {
}

dependencies {
implementation(project(':line-io'))
testImplementation(testFixtures(project(':line-io')))
testImplementation(libs.assertj.core)
testImplementation(libs.junit.jupiter)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package dev.delivercraft.rectangular;

import dev.delivercraft.io.LineReader;
import dev.delivercraft.io.LineWriter;

class AreaRectangularRoomCalculator {

private static final double CONVERSION_FACTOR = 0.092_903_04;
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package dev.delivercraft.rectangular;

import dev.delivercraft.io.InputStreamLineReader;
import dev.delivercraft.io.LineReader;
import dev.delivercraft.io.LineWriter;
import dev.delivercraft.io.OutputStreamLineWriter;

public final class Main {

void main() {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package dev.delivercraft.rectangular;

import dev.delivercraft.io.CapturingLineWriter;
import dev.delivercraft.io.LineReader;
import dev.delivercraft.io.LineWriter;
import dev.delivercraft.io.StubLineReader;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.NullAndEmptySource;

import java.util.StringJoiner;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;

Expand All @@ -16,7 +18,7 @@ class AreaRectangularRoomCalculatorTest {
void calculateArea_GivenNoInput_ShouldThrowException(String input) {
LineReader lineReader = () -> input;
AreaRectangularRoomCalculator calculator = new AreaRectangularRoomCalculator(lineReader,
new InMemoryLineWriter());
new CapturingLineWriter());

assertThatIllegalArgumentException()
.isThrownBy(calculator::calculateArea)
Expand All @@ -26,7 +28,7 @@ void calculateArea_GivenNoInput_ShouldThrowException(String input) {
@Test
void calculateArea_ShouldAskForLength() {
LineReader lineReader = () -> "123";
LineWriter lineWriter = new InMemoryLineWriter();
LineWriter lineWriter = new CapturingLineWriter();
AreaRectangularRoomCalculator calculator = new AreaRectangularRoomCalculator(lineReader, lineWriter);

calculator.calculateArea();
Expand All @@ -38,7 +40,7 @@ void calculateArea_ShouldAskForLength() {
@Test
void calculateArea_ShouldAskForWidth() {
LineReader lineReader = () -> "123";
LineWriter lineWriter = new InMemoryLineWriter();
LineWriter lineWriter = new CapturingLineWriter();
AreaRectangularRoomCalculator calculator = new AreaRectangularRoomCalculator(lineReader, lineWriter);

calculator.calculateArea();
Expand All @@ -50,7 +52,7 @@ void calculateArea_ShouldAskForWidth() {
@Test
void calculateArea_GivenLengthAndWidth_ShouldDisplayDimensions() {
LineReader lineReader = new StubLineReader("15", "20");
LineWriter lineWriter = new InMemoryLineWriter();
LineWriter lineWriter = new CapturingLineWriter();
AreaRectangularRoomCalculator calculator = new AreaRectangularRoomCalculator(lineReader, lineWriter);

calculator.calculateArea();
Expand All @@ -62,7 +64,7 @@ void calculateArea_GivenLengthAndWidth_ShouldDisplayDimensions() {
@Test
void calculateArea_GivenValidInput_ShouldDisplayTheAreaInSquareFeet() {
LineReader lineReader = new StubLineReader("15", "20");
LineWriter lineWriter = new InMemoryLineWriter();
LineWriter lineWriter = new CapturingLineWriter();
AreaRectangularRoomCalculator calculator = new AreaRectangularRoomCalculator(lineReader, lineWriter);

calculator.calculateArea();
Expand All @@ -75,7 +77,7 @@ void calculateArea_GivenValidInput_ShouldDisplayTheAreaInSquareFeet() {
@Test
void calculateArea_GivenValidInput_ShouldDisplayTheAreaInSquareMeters() {
LineReader lineReader = new StubLineReader("15", "20");
LineWriter lineWriter = new InMemoryLineWriter();
LineWriter lineWriter = new CapturingLineWriter();
AreaRectangularRoomCalculator calculator = new AreaRectangularRoomCalculator(lineReader, lineWriter);

calculator.calculateArea();
Expand All @@ -87,47 +89,11 @@ void calculateArea_GivenValidInput_ShouldDisplayTheAreaInSquareMeters() {
@Test
void calculateArea_GivenNonNumericInput_ShouldThrowException() {
LineReader lineReader = new StubLineReader("asdf");
LineWriter lineWriter = new InMemoryLineWriter();
LineWriter lineWriter = new CapturingLineWriter();
AreaRectangularRoomCalculator calculator = new AreaRectangularRoomCalculator(lineReader, lineWriter);

assertThatIllegalArgumentException()
.isThrownBy(calculator::calculateArea)
.withMessage("Please enter a numeric value! Input: asdf");
}

private static final class StubLineReader implements LineReader {

private final String[] inputs;

private int index;

private StubLineReader(String... inputs) {
this.inputs = inputs;
}

@Override
public String readLine() {
return this.inputs[this.index++];
}
}

private static final class InMemoryLineWriter implements LineWriter {

private final StringJoiner stringJoiner = new StringJoiner("");

@Override
public void write(String text) {
this.stringJoiner.add(text);
}

@Override
public void writeLine(String line) {
this.stringJoiner.add(line).add(System.lineSeparator());
}

@Override
public String toString() {
return this.stringJoiner.toString();
}
}
}
10 changes: 10 additions & 0 deletions line-io/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
plugins {
id 'dev.delivercraft.common-conventions'
id 'java-library'
id 'java-test-fixtures'
}

dependencies {
testImplementation(libs.assertj.core)
testImplementation(libs.junit.jupiter)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package dev.delivercraft.io;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UncheckedIOException;
import java.util.Objects;

/**
* Reads lines from an {@link InputStream}.
*
* <p>This implementation uses the platform default charset, returns {@code null} when the stream is exhausted, and
* wraps checked {@link IOException} failures in {@link UncheckedIOException}.
*/
public final class InputStreamLineReader implements LineReader {

private final BufferedReader bufferedReader;

/**
* Creates a line reader backed by the supplied input stream.
*
* @param inputStream the stream to read from
* @throws NullPointerException when {@code inputStream} is {@code null}
*/
public InputStreamLineReader(InputStream inputStream) {
Objects.requireNonNull(inputStream, "inputStream must not be null");
this.bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
}

/**
* Reads the next line from the stream.
*
* @return the next line without a line separator, or {@code null} when the stream is exhausted
* @throws UncheckedIOException when the underlying stream cannot be read
*/
@Override
public String readLine() {
try {
return this.bufferedReader.readLine();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}
14 changes: 14 additions & 0 deletions line-io/src/main/java/dev/delivercraft/io/LineReader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package dev.delivercraft.io;

/**
* Reads one line of text.
*/
public interface LineReader {

/**
* Reads one line of text.
*
* @return the line without a line separator, or {@code null} when no input remains
*/
String readLine();
}
21 changes: 21 additions & 0 deletions line-io/src/main/java/dev/delivercraft/io/LineWriter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package dev.delivercraft.io;

/**
* Writes text and lines of text.
*/
public interface LineWriter {

/**
* Writes text without appending a line separator.
*
* @param text the text to write
*/
void write(String text);

/**
* Writes text followed by the platform line separator.
*
* @param line the line to write
*/
void writeLine(String line);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package dev.delivercraft.io;

import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Objects;

/**
* Writes text and lines to an {@link OutputStream}.
*
* <p>This implementation writes text without validation or formatting, flushes prompt text written through
* {@link #write(String)}, and uses {@link PrintWriter#println(String)} for line output.
*/
public final class OutputStreamLineWriter implements LineWriter {

private final PrintWriter printWriter;

/**
* Creates a line writer backed by the supplied output stream.
*
* @param outputStream the stream to write to
* @throws NullPointerException when {@code outputStream} is {@code null}
*/
public OutputStreamLineWriter(OutputStream outputStream) {
Objects.requireNonNull(outputStream, "outputStream must not be null");
this.printWriter = new PrintWriter(outputStream, true);
}

/**
* Writes text without appending a line separator and flushes the underlying writer.
*
* @param text the text to write
*/
@Override
public void write(String text) {
this.printWriter.print(text);
this.printWriter.flush();
}

/**
* Writes text followed by the platform line separator.
*
* @param line the line to write
*/
@Override
public void writeLine(String line) {
this.printWriter.println(line);
}
}
Loading