diff --git a/src/main/java/millions/App.java b/src/main/java/millions/App.java
index 9b459b9..cb1b7d2 100644
--- a/src/main/java/millions/App.java
+++ b/src/main/java/millions/App.java
@@ -1,18 +1,22 @@
package millions;
import java.math.BigDecimal;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.stage.Stage;
import millions.controller.GameController;
+import millions.controller.fileIO.CSV.CSVStockFileWriter;
import millions.controller.fileIO.InvalidFormatException;
import millions.view.GameView;
import millions.view.StartView;
/** Main JavaFX application entry point for the Millions stock trading game. */
public class App extends Application {
-
+ private static final Logger logger = Logger.getLogger(App.class.getName());
@Override
public void start(Stage stage) {
GameController controller = new GameController();
@@ -36,15 +40,16 @@ public void start(Stage stage) {
Scene gameScene = new Scene(gameView, 1920, 1080);
stage.setScene(gameScene);
} catch (InvalidFormatException e) {
+ logger.log(Level.WARNING, "InvalidFormatException: " + e.getMessage());
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setTitle("Error");
alert.setHeaderText("Error with selected file");
- alert.setContentText("Please control the format of the selected file");
+ alert.setContentText(e.getMessage() + "\nPlease control the format of the selected file");
alert.showAndWait();
} catch (RuntimeException ex) {
- System.err.println(ex);
+ logger.log(Level.SEVERE, ex.getMessage());
System.exit(0);
}
});
diff --git a/src/main/java/millions/controller/fileIO/CSV/CSVFileHandler.java b/src/main/java/millions/controller/fileIO/CSV/CSVFileHandler.java
index 5a7d9b8..bcd783d 100644
--- a/src/main/java/millions/controller/fileIO/CSV/CSVFileHandler.java
+++ b/src/main/java/millions/controller/fileIO/CSV/CSVFileHandler.java
@@ -7,6 +7,9 @@
import java.nio.file.Path;
import java.util.List;
+/**
+ *
Bundles StockFileReader and CSVStockFileParser together to reduce boilerplate code when reading stocks from a csv file
+ */
public class CSVFileHandler {
StockFileReader reader;
CSVStockFileParser parser;
@@ -16,6 +19,12 @@ public CSVFileHandler() {
this.parser = new CSVStockFileParser();
}
+ /**
+ * Reads and parses stocks from a csv file
+ * @param filePath Path to stock file
+ * @return list of stock object created from parsed file
+ * @throws InvalidFormatException Throws an InvalidFormatException received from parser
+ */
public List getStocksFromFile(Path filePath) {
try {
StockFileReader reader = new StockFileReader();
diff --git a/src/main/java/millions/controller/fileIO/CSV/CSVStockFileParser.java b/src/main/java/millions/controller/fileIO/CSV/CSVStockFileParser.java
index 2eab5ab..9208bbc 100644
--- a/src/main/java/millions/controller/fileIO/CSV/CSVStockFileParser.java
+++ b/src/main/java/millions/controller/fileIO/CSV/CSVStockFileParser.java
@@ -12,13 +12,31 @@ public class CSVStockFileParser {
public CSVStockFileParser() {}
- // returns true if all entries have exactly 3 data points
+ /**
+ * Verifies the amount of data fields present in supplied CSV file.
+ *
+ * @param lines Lines from csv file
+ * @return Boolean: True if file satisfies expected format (3 fields)
+ */
public boolean verifyCSV(List lines) {
return lines.stream()
.filter(l -> !(l.startsWith("#") || l.isBlank()))
.noneMatch(l -> l.split(",").length != 3);
}
+ /**
+ * Parses the supplied lines if they satisfy the correct format expectations
+ *
+ * @param lines lines to be parsed.
+ * Each line must contain three data fields: String,String,BigDecimal
+ * (Fields cannot be blank)
+ * blank lines or lines beginning with '#' are ignored
+ *
+ * @return List of stock objects created from the supplied lines
+ * @throws InvalidFormatException If one or more lines contain too many or too few data fields
+ * @throws InvalidFormatException If the BigDecimal field on one or more lines are not compatible
+ * @throws InvalidFormatException Upon recieving an IllegalArgumentException (Either Symbol or Company name is blank)
+ */
public List parse(List lines) {
List stocks = new ArrayList<>();
if (verifyCSV(lines)) {
@@ -26,14 +44,20 @@ public List parse(List lines) {
.filter(l -> !((l.startsWith("#") || l.isBlank())))
.forEach(
l -> {
- String[] split = l.split(",");
- String symbol = split[0];
- String company = split[1];
- BigDecimal price = new BigDecimal(split[2]);
- stocks.add(new Stock(symbol, company, price));
+ try {
+ String[] split = l.split(",");
+ String symbol = split[0];
+ String company = split[1];
+ BigDecimal price = new BigDecimal(split[2]);
+ stocks.add(new Stock(symbol, company, price));
+ } catch (NumberFormatException e) {
+ throw new InvalidFormatException("Error with number conversion on line: " + l + "\n" + "Last field must be a number");
+ } catch (IllegalArgumentException e) {
+ throw new InvalidFormatException("Illegal argument on line: " + l + "\n" + e.getMessage());
+ }
});
} else {
- throw new InvalidFormatException("Incorrect format for CSV File");
+ throw new InvalidFormatException("Incorrect format for CSV File: incorrect amount of data fields detected on one or more lines");
}
return stocks;
}
diff --git a/src/main/java/millions/controller/fileIO/CSV/CSVStockFileWriter.java b/src/main/java/millions/controller/fileIO/CSV/CSVStockFileWriter.java
index 0233a7c..fdce35d 100644
--- a/src/main/java/millions/controller/fileIO/CSV/CSVStockFileWriter.java
+++ b/src/main/java/millions/controller/fileIO/CSV/CSVStockFileWriter.java
@@ -1,27 +1,30 @@
package millions.controller.fileIO.CSV;
-import millions.controller.fileIO.StockFileWriter;
-import millions.model.Stock;
-
-import java.io.BufferedWriter;
import java.io.*;
+import java.io.BufferedWriter;
import java.nio.file.Path;
import java.util.List;
+import java.util.logging.Logger;
+
+import millions.controller.fileIO.StockFileWriter;
+import millions.model.Stock;
-//TODO: Validation of data before writing
/**
- * Writes stock data to a CSV file.
+ * Implements StockFileWriter.
+ * Converts a list of stock objects into a writeable string with a CSV format.
+ *
*/
public class CSVStockFileWriter implements StockFileWriter {
- private final List stocks;
+ private static final Logger logger = Logger.getLogger(CSVStockFileWriter.class.getName());
private String finalString;
- public CSVStockFileWriter(List stocks) {
- this.stocks = stocks;
- }
+ public CSVStockFileWriter() {}
+ /**
+ * Formats given string to CSV format to prepare for writing to file
+ */
@Override
- public void formatString() {
+ public String formatString(List stocks) {
StringBuilder builder = new StringBuilder();
stocks.forEach(stock -> {
builder.append(stock.getSymbol());
@@ -31,16 +34,22 @@ public void formatString() {
builder.append(stock.getSalesPrice().toString());
builder.append("\n");
});
- this.finalString = builder.toString();
+ return builder.toString();
}
+ /**
+ * Writes the saved string to a file
+ * @param stocks List of stock objects to write
+ * @param path Path to desired file
+ * @return Boolean for success
+ */
@Override
- public boolean write(Path path){
+ public boolean write(List stocks, Path path){
try (FileWriter fw = new FileWriter(path.toString()); BufferedWriter writer = new BufferedWriter(fw);) {
- this.formatString();
+ this.formatString(stocks);
writer.write(finalString);
} catch (IOException e) {
- e.printStackTrace();
+ logger.severe(e.getMessage());
}
return false;
}
diff --git a/src/main/java/millions/controller/fileIO/InvalidFormatException.java b/src/main/java/millions/controller/fileIO/InvalidFormatException.java
index 6883256..a1e2136 100644
--- a/src/main/java/millions/controller/fileIO/InvalidFormatException.java
+++ b/src/main/java/millions/controller/fileIO/InvalidFormatException.java
@@ -1,5 +1,8 @@
package millions.controller.fileIO;
+/**
+ * Exception to be thrown when verifying the format of files
+ */
public class InvalidFormatException extends RuntimeException {
public InvalidFormatException(String message) {
super(message);
diff --git a/src/main/java/millions/controller/fileIO/StockFileReader.java b/src/main/java/millions/controller/fileIO/StockFileReader.java
index 33956b1..f873896 100644
--- a/src/main/java/millions/controller/fileIO/StockFileReader.java
+++ b/src/main/java/millions/controller/fileIO/StockFileReader.java
@@ -17,6 +17,11 @@ public class StockFileReader {
public StockFileReader() {}
+ /**
+ * Reads the file found at the specified path
+ * @param path Path to the desired file
+ * @return List of each line in the file as a string
+ */
public List readFile(Path path) {
File file = new File(path.toString());
List lines = new ArrayList<>();
diff --git a/src/main/java/millions/controller/fileIO/StockFileWriter.java b/src/main/java/millions/controller/fileIO/StockFileWriter.java
index cfd1baf..a85f363 100644
--- a/src/main/java/millions/controller/fileIO/StockFileWriter.java
+++ b/src/main/java/millions/controller/fileIO/StockFileWriter.java
@@ -1,11 +1,14 @@
package millions.controller.fileIO;
+import millions.model.Stock;
+
import java.nio.file.Path;
+import java.util.List;
/**
* Interface for writing stock data to a file.
*/
public interface StockFileWriter {
- public void formatString();
- public boolean write(Path path);
+ String formatString(List stocks);
+ boolean write(List stocks, Path path);
}
diff --git a/src/test/java/millions/CSVStockFileParserTest.java b/src/test/java/millions/CSVStockFileParserTest.java
index df753aa..8266d35 100644
--- a/src/test/java/millions/CSVStockFileParserTest.java
+++ b/src/test/java/millions/CSVStockFileParserTest.java
@@ -1,33 +1,75 @@
package millions;
import millions.controller.fileIO.CSV.CSVStockFileParser;
+import millions.controller.fileIO.InvalidFormatException;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
public class CSVStockFileParserTest {
static String exampleString;
+ final CSVStockFileParser parser = new CSVStockFileParser();
@BeforeAll
- public static void setUpTestFile() throws Exception {
+ public static void setUpTestString() {
exampleString = "# Top 500 US Stocks by Market Cap\n";
exampleString += "# Ticker,Name,Price\n";
exampleString += "\n";
exampleString += "NVDA,Nvidia,191.27\n";
exampleString += "AAPL,Apple Inc.,276.43\n";
exampleString += "MSFT,Microsoft,404.68\n";
+
}
@Test
public void parseStockFileTest(){
List testList = List.of(exampleString.split("\n"));
-
- CSVStockFileParser parser = new CSVStockFileParser();
assertEquals(3, parser.parse(testList).size());
}
+
+ @Test
+ public void InvalidFormatExceptionTest() {
+ exampleString += "Line with incorrect amount of data";
+ List testList = List.of(exampleString.split("\n"));
+ Exception e = assertThrows(InvalidFormatException.class, () -> {parser.parse(testList);});
+ String expectedMessage = "Incorrect format for CSV File: incorrect amount of data fields detected on one or more lines";
+ assertEquals(expectedMessage, e.getMessage());
+ }
+
+ @Test
+ public void NumberConversionExceptionTest() {
+ exampleString += "Company, Company Inc., NotANumber";
+ List testList = List.of(exampleString.split("\n"));
+ Exception e = assertThrows(InvalidFormatException.class, () -> {parser.parse(testList);});
+ String expectedMessage = "Error with number conversion on line: Company, Company Inc., NotANumber\n" +
+ "Last field must be a number";
+ assertEquals(expectedMessage, e.getMessage());
+ }
+
+ @Test
+ public void EmptySymbolFieldExceptionTest() {
+ exampleString += ",test,1";
+ List testList = List.of(exampleString.split("\n"));
+ Exception e = assertThrows(InvalidFormatException.class, () -> {parser.parse(testList);});
+ String expectedMessage = "Illegal argument on line: ,test,1\n" +
+ "Symbol cannot be null or blank";
+ assertEquals(expectedMessage, e.getMessage());
+ }
+ @Test
+ public void EmptyCompanyNameFieldExceptionTest() {
+ exampleString += "test,,1";
+ List testList = List.of(exampleString.split("\n"));
+ Exception e = assertThrows(InvalidFormatException.class, () -> {parser.parse(testList);});
+ String expectedMessage = "Illegal argument on line: test,,1\n" +
+ "Company cannot be null or blank";
+ assertEquals(expectedMessage, e.getMessage());
+ }
}
diff --git a/src/test/java/millions/CSVStockFileWriterTest.java b/src/test/java/millions/CSVStockFileWriterTest.java
deleted file mode 100644
index c6fe15a..0000000
--- a/src/test/java/millions/CSVStockFileWriterTest.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package millions;
-
-import millions.controller.fileIO.CSV.CSVStockFileWriter;
-import millions.controller.fileIO.StockFileReader;
-import millions.model.Stock;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.io.TempDir;
-
-import java.math.BigDecimal;
-import java.nio.file.Path;
-import java.util.List;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-public class CSVStockFileWriterTest {
- @TempDir
- static Path tempDir;
-
- List stocks;
-
- @BeforeEach
- void setup() {
- Stock s1 = new Stock("PEAR", "Pear Inc.", BigDecimal.valueOf(300));
- Stock s2 = new Stock("DOGL", "DOOGLE Inc.", BigDecimal.valueOf(200.00));
- Stock s3 = new Stock("MSFT", "EpsteinSoft Inc.", BigDecimal.valueOf(0.02));
-
- this.stocks = List.of(s1, s2, s3);
- }
-
- @Test
- public void testWrite() {
- for(Stock stock : this.stocks) {
- System.out.println(stock.toString());
- }
- CSVStockFileWriter csvStockFileWriter = new CSVStockFileWriter(stocks);
- csvStockFileWriter.write(tempDir.resolve("stocks.csv"));
-
- StockFileReader stockFileReader = new StockFileReader();
- assertEquals(3, stockFileReader.readFile(tempDir.resolve("stocks.csv")).size());
- }
-}