-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
implemented fruit shop program logic using solid principles #1292
base: master
Are you sure you want to change the base?
Changes from 14 commits
9c9e0b4
dac23fa
10ebf10
e830cb2
a12a686
032eb85
49e39f5
ee9f43e
142296e
71a9138
c19eee1
b0dd1dd
06aa862
b977aa7
dfec118
31644a0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package core.basesyntax; | ||
|
||
import db.Storage; | ||
import java.io.FileNotFoundException; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import model.FruitTransaction; | ||
import service.DataConverter; | ||
import service.FileReader; | ||
import service.ReportGenerator; | ||
import service.ShopService; | ||
import service.impl.DataConverterImpl; | ||
import service.impl.FileReaderImpl; | ||
import service.impl.FileWriterImpl; | ||
import service.impl.OperationStrategyImpl; | ||
import service.impl.ReportGeneratorImpl; | ||
import service.impl.ShopServiceImpl; | ||
import service.operation.BalanceOperation; | ||
import service.operation.OperationHandler; | ||
import service.operation.PurchaseOperation; | ||
import service.operation.ReturnOperation; | ||
import service.operation.SupplyOperation; | ||
import strategy.OperationStrategy; | ||
|
||
public class Main { | ||
private static final String REPORT_TO_READ_FILE = "src/main/resources/reportToRead.csv"; | ||
private static final String FINAL_REPORT_FILE = "src/main/resources/finalReport.csv"; | ||
|
||
public static void main(String[] args) throws FileNotFoundException { | ||
FileReader fileReader = new FileReaderImpl(); | ||
List<String> inputReport = fileReader.read(REPORT_TO_READ_FILE); | ||
|
||
DataConverter dataConverter = new DataConverterImpl(); | ||
|
||
Map<FruitTransaction.Operation, OperationHandler> operationHandlers = new HashMap<>(); | ||
operationHandlers.put(FruitTransaction.Operation.BALANCE, new BalanceOperation()); | ||
operationHandlers.put(FruitTransaction.Operation.PURCHASE, new PurchaseOperation()); | ||
operationHandlers.put(FruitTransaction.Operation.RETURN, new ReturnOperation()); | ||
operationHandlers.put(FruitTransaction.Operation.SUPPLY, new SupplyOperation()); | ||
OperationStrategy operationStrategy = new OperationStrategyImpl(operationHandlers); | ||
|
||
List<FruitTransaction> transactions = dataConverter.convertToTransaction(inputReport); | ||
ShopService shopService = new ShopServiceImpl(operationStrategy); | ||
shopService.process(transactions); | ||
|
||
Storage storage = new Storage(); | ||
ReportGenerator reportGenerator = new ReportGeneratorImpl(storage); | ||
String resultingReport = reportGenerator.getReport(); | ||
|
||
FileWriterImpl fileWriter = new FileWriterImpl(); | ||
fileWriter.write(FINAL_REPORT_FILE, resultingReport); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package db; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
public class Storage { | ||
private static final Map<String, Integer> fruits = new HashMap<>(); | ||
|
||
public static void add(String fruit, Integer amount) { | ||
fruits.put(fruit, fruits.getOrDefault(fruit, 0) + amount); | ||
} | ||
|
||
public static void remove(String fruit, Integer amount) { | ||
if (!fruits.containsKey(fruit) || fruits.get(fruit) < amount) { | ||
throw new IllegalArgumentException("Not enough " + fruit + " in storage."); | ||
} | ||
fruits.put(fruit, fruits.get(fruit) - amount); | ||
} | ||
|
||
public static int getAmount(String fruit) { | ||
return fruits.getOrDefault(fruit, 0); | ||
} | ||
|
||
public Map<String, Integer> getAllFruits() { | ||
return new HashMap<>(fruits); | ||
Comment on lines
+24
to
+25
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Returning a new There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fix comment |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package model; | ||
|
||
public class FruitTransaction { | ||
private Operation operation; | ||
private String fruit; | ||
private int quantity; | ||
|
||
public Operation getOperation() { | ||
return operation; | ||
} | ||
|
||
public void setOperation(Operation operation) { | ||
this.operation = operation; | ||
} | ||
|
||
public String getFruit() { | ||
return fruit; | ||
} | ||
|
||
public void setFruit(String fruit) { | ||
this.fruit = fruit; | ||
} | ||
|
||
public int getQuantity() { | ||
return quantity; | ||
} | ||
|
||
public void setQuantity(int quantity) { | ||
this.quantity = quantity; | ||
} | ||
|
||
public enum Operation { | ||
BALANCE("b"), | ||
SUPPLY("s"), | ||
PURCHASE("p"), | ||
RETURN("r"); | ||
|
||
private String code; | ||
|
||
Operation(String code) { | ||
this.code = code; | ||
} | ||
|
||
public String getCode() { | ||
return code; | ||
} | ||
|
||
public static FruitTransaction.Operation getOperationFromCode(String code) { | ||
for (FruitTransaction.Operation operation : FruitTransaction.Operation.values()) { | ||
if (operation.getCode().equals(code)) { | ||
return operation; | ||
} | ||
} | ||
throw new IllegalArgumentException("Unknown operation: " + code); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package service; | ||
|
||
import java.util.List; | ||
import model.FruitTransaction; | ||
|
||
public interface DataConverter { | ||
List<FruitTransaction> convertToTransaction(List<String> reportLines); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package service; | ||
|
||
import java.io.FileNotFoundException; | ||
import java.util.List; | ||
|
||
public interface FileReader { | ||
List<String> read(String fileName) throws FileNotFoundException; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package service; | ||
|
||
public interface ReportGenerator { | ||
String getReport(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package service; | ||
|
||
import java.util.List; | ||
import model.FruitTransaction; | ||
|
||
public interface ShopService { | ||
void process(List<FruitTransaction> fruitTransactionList); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package service.impl; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import model.FruitTransaction; | ||
import service.DataConverter; | ||
|
||
public class DataConverterImpl implements DataConverter { | ||
private static final String COMMA_SEPARATOR = ","; | ||
|
||
@Override | ||
public List<FruitTransaction> convertToTransaction(List<String> report) { | ||
List<FruitTransaction> fruitTransactionList = new ArrayList<>(); | ||
for (int i = 1; i < report.size(); i++) { | ||
FruitTransaction fruitTransaction = getFromCsvRow(report.get(i)); | ||
fruitTransactionList.add(fruitTransaction); | ||
} | ||
return fruitTransactionList; | ||
} | ||
|
||
private FruitTransaction getFromCsvRow(String row) { | ||
String[] fields = row.split(COMMA_SEPARATOR); | ||
FruitTransaction fruitTransaction = new FruitTransaction(); | ||
fruitTransaction.setOperation(FruitTransaction.Operation.getOperationFromCode(fields[0])); | ||
kriznychenko marked this conversation as resolved.
Show resolved
Hide resolved
|
||
fruitTransaction.setFruit(fields[1]); | ||
fruitTransaction.setQuantity(Integer.parseInt(fields[2])); | ||
kriznychenko marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Parsing |
||
return fruitTransaction; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,27 @@ | ||||||||
package service.impl; | ||||||||
|
||||||||
import java.io.File; | ||||||||
import java.io.IOException; | ||||||||
import java.nio.file.Files; | ||||||||
import java.util.List; | ||||||||
import service.FileReader; | ||||||||
|
||||||||
public class FileReaderImpl implements FileReader { | ||||||||
|
||||||||
public FileReaderImpl() { | ||||||||
|
||||||||
} | ||||||||
Comment on lines
+11
to
+13
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fix comment |
||||||||
|
||||||||
@Override | ||||||||
public List<String> read(String fileName) { | ||||||||
File file = new File(fileName); | ||||||||
if (!file.exists()) { | ||||||||
throw new IllegalArgumentException("File not found: " + fileName); | ||||||||
} | ||||||||
try { | ||||||||
return Files.readAllLines(file.toPath()); | ||||||||
} catch (IOException e) { | ||||||||
throw new RuntimeException("Error reading file: " + fileName, e); | ||||||||
} | ||||||||
} | ||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package service.impl; | ||
|
||
import java.io.FileWriter; | ||
import java.io.IOException; | ||
|
||
public class FileWriterImpl { | ||
public void write(String filePath, String content) { | ||
try (FileWriter fileWriter = new FileWriter(filePath)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. check if FileWriter implements AutoCloseable |
||
fileWriter.write(content); | ||
} catch (IOException e) { | ||
throw new RuntimeException("Error writing to file: " + filePath, e); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package service.impl; | ||
|
||
import java.util.Map; | ||
import model.FruitTransaction; | ||
import service.operation.OperationHandler; | ||
import strategy.OperationStrategy; | ||
|
||
public class OperationStrategyImpl implements OperationStrategy { | ||
private Map<FruitTransaction.Operation, OperationHandler> operationHandlerMap; | ||
|
||
public OperationStrategyImpl(Map<FruitTransaction.Operation, | ||
OperationHandler> operationHandlerMap) { | ||
this.operationHandlerMap = operationHandlerMap; | ||
} | ||
|
||
@Override | ||
public OperationHandler get(FruitTransaction.Operation operationType) { | ||
return operationHandlerMap.get(operationType); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package service.impl; | ||
|
||
import db.Storage; | ||
import java.util.Map; | ||
import service.ReportGenerator; | ||
|
||
public class ReportGeneratorImpl implements ReportGenerator { | ||
private static final String HEADER = "fruit,amount"; | ||
private static final String COMMA_DELIMITER = ","; | ||
private static final String NEW_LINE = System.lineSeparator(); | ||
kriznychenko marked this conversation as resolved.
Show resolved
Hide resolved
|
||
private final Storage storage; | ||
|
||
public ReportGeneratorImpl(Storage storage) { | ||
this.storage = storage; | ||
} | ||
|
||
@Override | ||
public String getReport() { | ||
StringBuilder report = new StringBuilder(); | ||
Map<String, Integer> fruits = storage.getAllFruits(); | ||
kriznychenko marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
report.append(HEADER).append(NEW_LINE); | ||
for (Map.Entry<String, Integer> entry : fruits.entrySet()) { | ||
report.append(entry.getKey()) | ||
.append(COMMA_DELIMITER) | ||
.append(entry.getValue()) | ||
.append(NEW_LINE); | ||
} | ||
|
||
return report.toString(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package service.impl; | ||
|
||
import java.util.List; | ||
import model.FruitTransaction; | ||
import service.ShopService; | ||
import service.operation.OperationHandler; | ||
import strategy.OperationStrategy; | ||
|
||
public class ShopServiceImpl implements ShopService { | ||
private final OperationStrategy operationStrategy; | ||
|
||
public ShopServiceImpl(OperationStrategy operationStrategy) { | ||
this.operationStrategy = operationStrategy; | ||
} | ||
|
||
@Override | ||
public void process(List<FruitTransaction> fruitTransactionList) { | ||
for (FruitTransaction transaction : fruitTransactionList) { | ||
OperationHandler handler = operationStrategy.get(transaction.getOperation()); | ||
handler.performOperation(transaction); | ||
Comment on lines
+19
to
+20
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package service.operation; | ||
|
||
import db.Storage; | ||
import model.FruitTransaction; | ||
|
||
public class BalanceOperation implements OperationHandler { | ||
@Override | ||
public void performOperation(FruitTransaction fruitTransaction) { | ||
Storage.add(fruitTransaction.getFruit(), fruitTransaction.getQuantity()); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package service.operation; | ||
|
||
import model.FruitTransaction; | ||
|
||
public interface OperationHandler { | ||
void performOperation(FruitTransaction fruitTransaction); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package service.operation; | ||
|
||
import db.Storage; | ||
import model.FruitTransaction; | ||
|
||
public class PurchaseOperation implements OperationHandler { | ||
@Override | ||
public void performOperation(FruitTransaction fruitTransaction) { | ||
Storage.remove(fruitTransaction.getFruit(), fruitTransaction.getQuantity()); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package service.operation; | ||
|
||
import db.Storage; | ||
import model.FruitTransaction; | ||
|
||
public class ReturnOperation implements OperationHandler { | ||
@Override | ||
public void performOperation(FruitTransaction fruitTransaction) { | ||
Storage.add(fruitTransaction.getFruit(), fruitTransaction.getQuantity()); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package service.operation; | ||
|
||
import db.Storage; | ||
import model.FruitTransaction; | ||
|
||
public class SupplyOperation implements OperationHandler { | ||
@Override | ||
public void performOperation(FruitTransaction fruitTransaction) { | ||
Storage.add(fruitTransaction.getFruit(), fruitTransaction.getQuantity()); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package strategy; | ||
|
||
import model.FruitTransaction; | ||
import service.operation.OperationHandler; | ||
|
||
public interface OperationStrategy { | ||
OperationHandler get(FruitTransaction.Operation operationType); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Direct instantiation of
Storage
might expose its internal state. Consider using a method to access its data to maintain encapsulation.