Skip to content

Commit

Permalink
Feat: Updated fileconverter and fileparser.
Browse files Browse the repository at this point in the history
  • Loading branch information
tommyah committed Mar 15, 2026
1 parent d419387 commit 9a015da
Show file tree
Hide file tree
Showing 2 changed files with 178 additions and 12 deletions.
60 changes: 55 additions & 5 deletions src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/FileConverter.java
Original file line number Diff line number Diff line change
@@ -1,23 +1,73 @@
package edu.ntnu.idi.idatt2003.g40.mappe;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
* Converts stock objects to/from string format for file handling.
*
* <p style ="font-weight: bold;">Responsibilities:</p>
* <ul>
* <li>Turn a valid list of stock string elements to a
* list of {@link Stock} objects.</li>
*
* <li>Turn a list of stock objects to a
* list of string elements.</li>
* </ul>
*
* <p>Used with {@link FileParser}</p>
*
* @see FileParser
* @author tohja
* @version 1.0.0
*
* */
public class FileConverter {

public List<Stock> getStocksFromFile(FileParser fileParser) throws IOException {
List<String> strings = fileParser.readFile();
/**
* Turns a list of valid string representations
* of stock objects to a list of stock objects.
*
* @param validStocks list of string elements properly
* representing stock objects.
*
* @return {@link List<Stock>}
* */
public List<Stock> getStocksFromStrings(final List<String> validStocks) {
List<Stock> stocksFromFile = new ArrayList<>();
List<String> stockSymbols = new ArrayList<>();

strings.forEach(s -> {
validStocks.forEach(s -> {
String[] lineElements = s.split(",");
String stockSymbol = lineElements[0].trim();
String stockName = lineElements[1].trim();
BigDecimal stockPrice = new BigDecimal(lineElements[2].trim());
stocksFromFile.add(new Stock(stockSymbol, stockName, stockPrice));
// TODO: try-catch
Stock stockObject = new Stock(stockSymbol, stockName, stockPrice);
if (!stockSymbols.contains(stockSymbol)) {
stockSymbols.add(stockSymbol);
stocksFromFile.add(stockObject);
}
});
return stocksFromFile;
}

/**
* Converts a list of stocks to string representations of that stock.
*
* <p>format: SYMBOL, NAME, PRICE</p>
*
* @param stocks a list of {@link Stock} objects.
*
* @return a list of string representation of the stock objects.
* */
public List<String> stocksToStrings(final List<Stock> stocks) {
ArrayList<String> stringList = new ArrayList<>();
stocks.forEach(s ->
stringList.add(s.getSymbol().trim() + "," + s.getCompany().trim()
+ "," + s.getSalesPrice().toString())
);
return stringList;
}
}
130 changes: 123 additions & 7 deletions src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/FileParser.java
Original file line number Diff line number Diff line change
@@ -1,23 +1,74 @@
package edu.ntnu.idi.idatt2003.g40.mappe;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.List;
import java.util.function.Predicate;

/**
* Class used to parse (filter) valid stocks from a .txt file.
*
* <p style ="font-weight: bold;">Responsibilities:</p>
* <ul>
* <li>Read file and return a filtered list of string elements,
* where each element represents a valid stock line.</li>
*
* <li>Write a list of string representations of stock objects
* to file, each stock separated by a line.</li>
* </ul>
*
* <p>Used with {@link FileConverter}</p>
*
* @see FileConverter
* @author tohja
* @version 1.0.0
* */
public class FileParser {

/** The path name this parser is using.*/
private final String pathName;

/**
* Rule set for validating lines and strings.
*
* <p>Uses predicates.</p>
* */
private enum ParserRuleSet {

/**
* Rule for whether string is empty or not.
* */
NOT_EMPTY(s -> !s.trim().isEmpty()),

/**
* Rule for if string is comment or not.
* */
NOT_COMMENT(s -> !s.startsWith("#")),

/**
* Rule for if line is in valid format.
* */
VALID_FORMAT(NOT_EMPTY.rule.and(NOT_COMMENT.rule)),

/**
* Rule for if string is considered a valid company symbol.
* */
VALID_CODE(s -> s.matches("[A-Z]{4}")),

/**
* Rule for if string is a valid company name.
* */
VALID_NAME(s -> s.matches(".*")),

/**
* Rule for if string can be parsed to a {@link BigDecimal} object.
* */
CAN_PARSE_TO_BIG_DECIMAL(s -> {
try {
new BigDecimal(s);
Expand All @@ -26,25 +77,56 @@ private enum ParserRuleSet {
return false;
}
}),

/**
* Rule for if string is in a valid price format.
* */
VALID_PRICE_FORMAT(s -> s.matches("[^a-zA-Z]+")),

/**
* Rule for if string is a valid price.
* */
VALID_PRICE(VALID_PRICE_FORMAT.rule.and(CAN_PARSE_TO_BIG_DECIMAL.rule));

/**
* The constants' rules as predicates with input of type string.
* */
private final Predicate<String> rule;

ParserRuleSet(final Predicate<String> rule) {
this.rule = rule;
}
}

/**
* Constructor.
*
* @param pathName the file path name to read.
* */
public FileParser(final String pathName) {
this.pathName = pathName;
}

/**
* Reads the file and returns a list element of all valid stocks as strings.
*
* <p>Uses {@link BufferedReader} for opening a file stream. </p>
*
* @return {@link List<String>} object of all valid stock strings in file.
*
* @throws IOException if path cannot be read.
*
* @see Path
* */

public List<String> readFile() throws IOException {
try {
Path path = Paths.get(pathName);
List<String> allLines = Files.readAllLines(path);
List<String> readableLines = allLines.stream().filter(ParserRuleSet.VALID_FORMAT.rule).toList();
Path path = Paths.get(pathName);
try (BufferedReader bufferedReader = Files.newBufferedReader(path)) {

List<String> allLines = bufferedReader.readAllLines();
List<String> readableLines =
allLines.stream()
.filter(ParserRuleSet.VALID_FORMAT.rule).toList();

// Valid lines (following the correct regular expressions)
return readableLines.stream().filter(s -> {
Expand All @@ -54,9 +136,14 @@ public List<String> readFile() throws IOException {
return false;
}

boolean validCode = ParserRuleSet.VALID_CODE.rule.test(parts[0].trim());
boolean validName = ParserRuleSet.VALID_NAME.rule.test(parts[1].trim());
boolean validPrice = ParserRuleSet.VALID_PRICE.rule.test(parts[2].trim());
boolean validCode = ParserRuleSet
.VALID_CODE.rule.test(parts[0].trim());

boolean validName = ParserRuleSet
.VALID_NAME.rule.test(parts[1].trim());

boolean validPrice = ParserRuleSet
.VALID_PRICE.rule.test(parts[2].trim());

return validCode && validName && validPrice;
}).toList();
Expand All @@ -65,4 +152,33 @@ public List<String> readFile() throws IOException {
throw new IOException("File parser could not parse file!");
}
}

/**
* Writes a given lists of stocks to the file.
*
* <p>Uses {@link BufferedWriter}.</p>
*
* @param stringList list of strings representing stocks in the format
* SYMBOL, NAME, PRICE
*
* @throws IOException if writing process throws error.
* */
public void writeStocksToFile(final List<String> stringList)
throws IOException {
Path path = Paths.get(pathName);

try (BufferedWriter writer = Files.newBufferedWriter(path,
StandardOpenOption.CREATE,
StandardOpenOption.APPEND)) {

writer.newLine();

for (String line : stringList) {
writer.write(line);
writer.newLine();
}
} catch (IOException e) {
throw new IOException("Error during buffered write", e);
}
}
}

0 comments on commit 9a015da

Please sign in to comment.