diff --git a/src/main/java/core/basesyntax/FruitShop.java b/src/main/java/core/basesyntax/FruitShop.java new file mode 100644 index 0000000000..8289f50cfe --- /dev/null +++ b/src/main/java/core/basesyntax/FruitShop.java @@ -0,0 +1,54 @@ +package core.basesyntax; + +import core.basesyntax.handlers.BalanceOperationHandler; +import core.basesyntax.handlers.PurchaseOperationHandler; +import core.basesyntax.handlers.ReturnOperationHandler; +import core.basesyntax.handlers.SupplyOperationHandler; +import core.basesyntax.model.FruitTransaction; +import core.basesyntax.services.DataProcessorService; +import core.basesyntax.services.FileReaderService; +import core.basesyntax.services.FileWriterService; +import core.basesyntax.services.OperationProcessor; +import core.basesyntax.services.ReportCreatorService; +import core.basesyntax.services.impl.DataProcessorServiceImpl; +import core.basesyntax.services.impl.FileReaderServiceImpl; +import core.basesyntax.services.impl.FileWriterServiceImpl; +import core.basesyntax.services.impl.OperationProcessorImpl; +import core.basesyntax.services.impl.ReportCreatorServiceImpl; +import core.basesyntax.strategy.OperationHandler; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Feel free to remove this class and create your own. + */ +public class FruitShop { + public static final String INPUT_FILE_PATH = "src/main/java/resources/input.csv"; + public static final String OUTPUT_FILE_PATH = "src/main/java/resources/output.csv"; + + public static void main(String[] args) { + FileReaderService fileReaderService = new FileReaderServiceImpl(); + List lines = fileReaderService.readFromFile(INPUT_FILE_PATH); + DataProcessorService dataProcessorService = new DataProcessorServiceImpl(); + + Map operationMap = new HashMap<>(); + operationMap.put(FruitTransaction.Operation.BALANCE, new BalanceOperationHandler()); + operationMap.put(FruitTransaction.Operation.SUPPLY, new SupplyOperationHandler()); + operationMap.put(FruitTransaction.Operation.PURCHASE, new PurchaseOperationHandler()); + operationMap.put(FruitTransaction.Operation.RETURN, new ReturnOperationHandler()); + + OperationProcessor operationService = new OperationProcessorImpl(operationMap); + List fruitTransactionList + = dataProcessorService.processInputData(lines); + operationService.manageTransactions(fruitTransactionList); + + ReportCreatorService reportCreatorService = new ReportCreatorServiceImpl(); + String report = reportCreatorService.createReport(); + + FileWriterService fileWriterService = new FileWriterServiceImpl(); + fileWriterService.writeToFile(OUTPUT_FILE_PATH, report); + } + // HINT: In the `public static void main(String[] args)` it is better to create instances of your classes, + // and call their methods, but do not write any business logic in the `main` method! +} diff --git a/src/main/java/core/basesyntax/HelloWorld.java b/src/main/java/core/basesyntax/HelloWorld.java deleted file mode 100644 index 05f94be41b..0000000000 --- a/src/main/java/core/basesyntax/HelloWorld.java +++ /dev/null @@ -1,9 +0,0 @@ -package core.basesyntax; - -/** - * Feel free to remove this class and create your own. - */ -public class HelloWorld { - // HINT: In the `public static void main(String[] args)` it is better to create instances of your classes, - // and call their methods, but do not write any business logic in the `main` method! -} diff --git a/src/main/java/core/basesyntax/db/Storage.java b/src/main/java/core/basesyntax/db/Storage.java new file mode 100644 index 0000000000..cc38189c14 --- /dev/null +++ b/src/main/java/core/basesyntax/db/Storage.java @@ -0,0 +1,8 @@ +package core.basesyntax.db; + +import java.util.HashMap; +import java.util.Map; + +public class Storage { + public static final Map STORAGE = new HashMap<>(); +} diff --git a/src/main/java/core/basesyntax/exception/InvalidDataException.java b/src/main/java/core/basesyntax/exception/InvalidDataException.java new file mode 100644 index 0000000000..8a27074dd1 --- /dev/null +++ b/src/main/java/core/basesyntax/exception/InvalidDataException.java @@ -0,0 +1,7 @@ +package core.basesyntax.exception; + +public class InvalidDataException extends RuntimeException { + public InvalidDataException(String message) { + super(message); + } +} diff --git a/src/main/java/core/basesyntax/handlers/BalanceOperationHandler.java b/src/main/java/core/basesyntax/handlers/BalanceOperationHandler.java new file mode 100644 index 0000000000..852ea36be2 --- /dev/null +++ b/src/main/java/core/basesyntax/handlers/BalanceOperationHandler.java @@ -0,0 +1,12 @@ +package core.basesyntax.handlers; + +import core.basesyntax.db.Storage; +import core.basesyntax.model.FruitTransaction; +import core.basesyntax.strategy.OperationHandler; + +public class BalanceOperationHandler implements OperationHandler { + @Override + public void calculateOperation(FruitTransaction transaction) { + Storage.STORAGE.put(transaction.getFruit(), transaction.getQuantity()); + } +} diff --git a/src/main/java/core/basesyntax/handlers/PurchaseOperationHandler.java b/src/main/java/core/basesyntax/handlers/PurchaseOperationHandler.java new file mode 100644 index 0000000000..7effaec9ae --- /dev/null +++ b/src/main/java/core/basesyntax/handlers/PurchaseOperationHandler.java @@ -0,0 +1,18 @@ +package core.basesyntax.handlers; + +import core.basesyntax.db.Storage; +import core.basesyntax.model.FruitTransaction; +import core.basesyntax.strategy.OperationHandler; + +public class PurchaseOperationHandler implements OperationHandler { + @Override + public void calculateOperation(FruitTransaction transaction) { + int currentAmount = Storage.STORAGE.get(transaction.getFruit()); + int quantity = transaction.getQuantity(); + int purchaseResult = currentAmount - quantity; + if (purchaseResult < 0) { + throw new RuntimeException("Not enough fruits in storage"); + } + Storage.STORAGE.put(transaction.getFruit(), purchaseResult); + } +} diff --git a/src/main/java/core/basesyntax/handlers/ReturnOperationHandler.java b/src/main/java/core/basesyntax/handlers/ReturnOperationHandler.java new file mode 100644 index 0000000000..15f188ea5c --- /dev/null +++ b/src/main/java/core/basesyntax/handlers/ReturnOperationHandler.java @@ -0,0 +1,15 @@ +package core.basesyntax.handlers; + +import core.basesyntax.db.Storage; +import core.basesyntax.model.FruitTransaction; +import core.basesyntax.strategy.OperationHandler; + +public class ReturnOperationHandler implements OperationHandler { + @Override + public void calculateOperation(FruitTransaction transaction) { + int currentAmount = Storage.STORAGE.get(transaction.getFruit()); + int quantity = transaction.getQuantity(); + int returnResult = currentAmount + quantity; + Storage.STORAGE.put(transaction.getFruit(), returnResult); + } +} diff --git a/src/main/java/core/basesyntax/handlers/SupplyOperationHandler.java b/src/main/java/core/basesyntax/handlers/SupplyOperationHandler.java new file mode 100644 index 0000000000..b973ecf2c4 --- /dev/null +++ b/src/main/java/core/basesyntax/handlers/SupplyOperationHandler.java @@ -0,0 +1,15 @@ +package core.basesyntax.handlers; + +import core.basesyntax.db.Storage; +import core.basesyntax.model.FruitTransaction; +import core.basesyntax.strategy.OperationHandler; + +public class SupplyOperationHandler implements OperationHandler { + @Override + public void calculateOperation(FruitTransaction transaction) { + int currentAmount = Storage.STORAGE.get(transaction.getFruit()); + int quantity = transaction.getQuantity(); + int supplyResult = currentAmount + quantity; + Storage.STORAGE.put(transaction.getFruit(), supplyResult); + } +} diff --git a/src/main/java/core/basesyntax/model/FruitTransaction.java b/src/main/java/core/basesyntax/model/FruitTransaction.java new file mode 100644 index 0000000000..ba19b84854 --- /dev/null +++ b/src/main/java/core/basesyntax/model/FruitTransaction.java @@ -0,0 +1,63 @@ +package core.basesyntax.model; + +import java.util.Arrays; + +public class FruitTransaction { + private Operation operation; + private String fruit; + private int quantity; + + public FruitTransaction(Operation operation, String fruit, int quantity) { + this.operation = operation; + this.fruit = fruit; + this.quantity = 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 Operation getOperationByCode(String code) { + return Arrays.stream(Operation.values()) + .filter(o -> o.getCode().equals(code)) + .findAny() + .orElseThrow(() -> new RuntimeException("No such operation")); + } + } +} diff --git a/src/main/java/core/basesyntax/resources/input.csv b/src/main/java/core/basesyntax/resources/input.csv new file mode 100644 index 0000000000..c771f259d3 --- /dev/null +++ b/src/main/java/core/basesyntax/resources/input.csv @@ -0,0 +1,9 @@ +type,fruit,quantity +b,banana,20 +b,apple,100 +s,banana,100 +p,banana,13 +r,apple,10 +p,apple,20 +p,banana,5 +s,banana,50 \ No newline at end of file diff --git a/src/main/java/core/basesyntax/resources/output.csv b/src/main/java/core/basesyntax/resources/output.csv new file mode 100644 index 0000000000..d7ee69b6d1 --- /dev/null +++ b/src/main/java/core/basesyntax/resources/output.csv @@ -0,0 +1,3 @@ +fruit,quantity +banana,152 +apple,90 \ No newline at end of file diff --git a/src/main/java/core/basesyntax/services/DataProcessorService.java b/src/main/java/core/basesyntax/services/DataProcessorService.java new file mode 100644 index 0000000000..0870b4288c --- /dev/null +++ b/src/main/java/core/basesyntax/services/DataProcessorService.java @@ -0,0 +1,8 @@ +package core.basesyntax.services; + +import core.basesyntax.model.FruitTransaction; +import java.util.List; + +public interface DataProcessorService { + List processInputData(List dataFromFile); +} diff --git a/src/main/java/core/basesyntax/services/FileReaderService.java b/src/main/java/core/basesyntax/services/FileReaderService.java new file mode 100644 index 0000000000..f4d6d31ef6 --- /dev/null +++ b/src/main/java/core/basesyntax/services/FileReaderService.java @@ -0,0 +1,7 @@ +package core.basesyntax.services; + +import java.util.List; + +public interface FileReaderService { + List readFromFile(String filename); +} diff --git a/src/main/java/core/basesyntax/services/FileWriterService.java b/src/main/java/core/basesyntax/services/FileWriterService.java new file mode 100644 index 0000000000..8d7fa624c0 --- /dev/null +++ b/src/main/java/core/basesyntax/services/FileWriterService.java @@ -0,0 +1,5 @@ +package core.basesyntax.services; + +public interface FileWriterService { + void writeToFile(String fileName, String report); +} diff --git a/src/main/java/core/basesyntax/services/OperationProcessor.java b/src/main/java/core/basesyntax/services/OperationProcessor.java new file mode 100644 index 0000000000..36a8e78dc0 --- /dev/null +++ b/src/main/java/core/basesyntax/services/OperationProcessor.java @@ -0,0 +1,8 @@ +package core.basesyntax.services; + +import core.basesyntax.model.FruitTransaction; +import java.util.List; + +public interface OperationProcessor { + void manageTransactions(List transactions); +} diff --git a/src/main/java/core/basesyntax/services/ReportCreatorService.java b/src/main/java/core/basesyntax/services/ReportCreatorService.java new file mode 100644 index 0000000000..c608829278 --- /dev/null +++ b/src/main/java/core/basesyntax/services/ReportCreatorService.java @@ -0,0 +1,5 @@ +package core.basesyntax.services; + +public interface ReportCreatorService { + String createReport(); +} diff --git a/src/main/java/core/basesyntax/services/impl/DataProcessorServiceImpl.java b/src/main/java/core/basesyntax/services/impl/DataProcessorServiceImpl.java new file mode 100644 index 0000000000..2c89232a40 --- /dev/null +++ b/src/main/java/core/basesyntax/services/impl/DataProcessorServiceImpl.java @@ -0,0 +1,33 @@ +package core.basesyntax.services.impl; + +import core.basesyntax.exception.InvalidDataException; +import core.basesyntax.model.FruitTransaction; +import core.basesyntax.services.DataProcessorService; +import java.util.List; + +public class DataProcessorServiceImpl implements DataProcessorService { + private static final String SPLIT_DELIMITER = ","; + private static final int OPERATION_TYPE_INDEX = 0; + private static final int FRUIT_TYPE_INDEX = 1; + private static final int FRUIT_QUANTITY_INDEX = 2; + + @Override + public List processInputData(List dataFromFile) { + return dataFromFile.stream() + .map(this::getFruitTransaction) + .toList(); + } + + private FruitTransaction getFruitTransaction(String data) { + String[] processedData = data.split(SPLIT_DELIMITER); + FruitTransaction.Operation operation = FruitTransaction + .Operation.getOperationByCode(processedData[OPERATION_TYPE_INDEX]); + String fruitType = processedData[FRUIT_TYPE_INDEX]; + int fruitQuantity = Integer.parseInt(processedData[FRUIT_QUANTITY_INDEX]); + if (fruitQuantity < 0) { + throw new InvalidDataException("Invalid Quantity, fruit quantity is: " + + fruitQuantity); + } + return new FruitTransaction(operation, fruitType, fruitQuantity); + } +} diff --git a/src/main/java/core/basesyntax/services/impl/FileReaderServiceImpl.java b/src/main/java/core/basesyntax/services/impl/FileReaderServiceImpl.java new file mode 100644 index 0000000000..9cf8ec462c --- /dev/null +++ b/src/main/java/core/basesyntax/services/impl/FileReaderServiceImpl.java @@ -0,0 +1,25 @@ +package core.basesyntax.services.impl; + +import core.basesyntax.services.FileReaderService; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; + +public class FileReaderServiceImpl implements FileReaderService { + private static final int SKIP_LINE = 1; + + @Override + public List readFromFile(String filename) { + List linesFromFile = new ArrayList<>(); + Path path = Paths.get(filename); + try { + Files.lines(path).skip(SKIP_LINE).forEach(linesFromFile::add); + }catch(IOException e) { + throw new RuntimeException("Can't read data from file : " + filename); + } + return linesFromFile; + } +} diff --git a/src/main/java/core/basesyntax/services/impl/FileWriterServiceImpl.java b/src/main/java/core/basesyntax/services/impl/FileWriterServiceImpl.java new file mode 100644 index 0000000000..dedeeb3b39 --- /dev/null +++ b/src/main/java/core/basesyntax/services/impl/FileWriterServiceImpl.java @@ -0,0 +1,17 @@ +package core.basesyntax.services.impl; + +import core.basesyntax.services.FileWriterService; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; + +public class FileWriterServiceImpl implements FileWriterService { + @Override + public void writeToFile(String filePath, String report) { + try { + Files.writeString(Paths.get(filePath), report); + } catch (IOException e) { + throw new RuntimeException("Can't find file by path" + filePath); + } + } +} diff --git a/src/main/java/core/basesyntax/services/impl/OperationProcessorImpl.java b/src/main/java/core/basesyntax/services/impl/OperationProcessorImpl.java new file mode 100644 index 0000000000..b27035e0ad --- /dev/null +++ b/src/main/java/core/basesyntax/services/impl/OperationProcessorImpl.java @@ -0,0 +1,21 @@ +package core.basesyntax.services.impl; + +import core.basesyntax.model.FruitTransaction; +import core.basesyntax.services.OperationProcessor; +import core.basesyntax.strategy.OperationHandler; +import java.util.List; +import java.util.Map; + +public class OperationProcessorImpl implements OperationProcessor { + private final Map processedOperations; + + public OperationProcessorImpl( + Map processedOperations) { + this.processedOperations = processedOperations; + } + + @Override + public void manageTransactions(List transactions) { + transactions.forEach(t -> processedOperations.get(t.getOperation()).calculateOperation(t)); + } +} diff --git a/src/main/java/core/basesyntax/services/impl/ReportCreatorServiceImpl.java b/src/main/java/core/basesyntax/services/impl/ReportCreatorServiceImpl.java new file mode 100644 index 0000000000..54f3a63f5d --- /dev/null +++ b/src/main/java/core/basesyntax/services/impl/ReportCreatorServiceImpl.java @@ -0,0 +1,20 @@ +package core.basesyntax.services.impl; + +import core.basesyntax.db.Storage; +import core.basesyntax.services.ReportCreatorService; + +public class ReportCreatorServiceImpl implements ReportCreatorService { + private static final String DEFAULT_MESSAGE = "fruit,quantity"; + private static final String SPLIT_DELIMITER = ","; + private final StringBuilder reportBuilder = new StringBuilder(); + + @Override + public String createReport() { + reportBuilder.append(DEFAULT_MESSAGE).append(System.lineSeparator()); + Storage.STORAGE.forEach((key, value) -> reportBuilder.append(key) + .append(SPLIT_DELIMITER) + .append(value) + .append(System.lineSeparator())); + return reportBuilder.toString(); + } +} diff --git a/src/main/java/core/basesyntax/strategy/OperationHandler.java b/src/main/java/core/basesyntax/strategy/OperationHandler.java new file mode 100644 index 0000000000..bd659dcb85 --- /dev/null +++ b/src/main/java/core/basesyntax/strategy/OperationHandler.java @@ -0,0 +1,7 @@ +package core.basesyntax.strategy; + +import core.basesyntax.model.FruitTransaction; + +public interface OperationHandler { + void calculateOperation(FruitTransaction transaction); +}