Skip to content
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

add solution #1242

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
56 changes: 54 additions & 2 deletions src/main/java/core/basesyntax/HelloWorld.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,61 @@
package core.basesyntax;

import core.basesyntax.dao.FruitRepository;
import core.basesyntax.dao.impl.FruitRepositoryImpl;
import core.basesyntax.model.FruitTransaction;
import core.basesyntax.model.enums.Operation;
import core.basesyntax.service.DataConverter;
import core.basesyntax.service.FileService;
import core.basesyntax.service.ReportGenerator;
import core.basesyntax.service.ShopService;
import core.basesyntax.service.handler.OperationHandler;
import core.basesyntax.service.handler.OperationStrategy;
import core.basesyntax.service.handler.impl.BalanceOperationHandler;
import core.basesyntax.service.handler.impl.OperationStrategyImpl;
import core.basesyntax.service.handler.impl.PurchaseOperationHandler;
import core.basesyntax.service.handler.impl.ReturnOperationHandler;
import core.basesyntax.service.handler.impl.SupplyOperationHandler;
import core.basesyntax.service.impl.DataConverterImpl;
import core.basesyntax.service.impl.FileServiceImpl;
import core.basesyntax.service.impl.ReportGeneratorImpl;
import core.basesyntax.service.impl.ShopServiceImpl;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* 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!
public static void main(String[] arg) {
// 1. Read the data from the input CSV file
FileService fileService = new FileServiceImpl();
List<String> inputReport = fileService.read("transactions.csv");

// 2. Convert the incoming data into FruitTransactions list
DataConverter dataConverter = new DataConverterImpl();

// 3. Create and feel the map with all OperationHandler implementations
FruitRepository repository = new FruitRepositoryImpl();
Map<Operation, OperationHandler> operationHandlers = new HashMap<>();
operationHandlers.put(Operation.BALANCE, new BalanceOperationHandler(repository));
operationHandlers.put(Operation.PURCHASE, new PurchaseOperationHandler(repository));
operationHandlers.put(Operation.RETURN, new ReturnOperationHandler(repository));
operationHandlers.put(Operation.SUPPLY, new SupplyOperationHandler(repository));
OperationStrategy operationStrategy = new OperationStrategyImpl(operationHandlers);

// 4. Process the incoming transactions with applicable OperationHandler implementations

List<FruitTransaction> transactions = dataConverter
.convertStringsDataToFruitTransactions(inputReport);
ShopService shopService = new ShopServiceImpl(operationStrategy);
shopService.process(transactions);

// 5.Generate report based on the current Storage state
ReportGenerator reportGenerator = new ReportGeneratorImpl(repository);
String resultingReport = reportGenerator.generateReport();

// 6. Write the received report into the destination file
fileService.write("report.csv", resultingReport);
}
}
13 changes: 13 additions & 0 deletions src/main/java/core/basesyntax/dao/FruitRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package core.basesyntax.dao;

import java.util.Map;

public interface FruitRepository {
void add(String fruit, int quantity);

void remove(String fruit, int quantity);

boolean hasFruit(String fruit);

Map<String, Integer> getAll();
}
35 changes: 35 additions & 0 deletions src/main/java/core/basesyntax/dao/impl/FruitRepositoryImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package core.basesyntax.dao.impl;

import core.basesyntax.dao.FruitRepository;
import core.basesyntax.db.Database;
import java.util.Map;

public class FruitRepositoryImpl implements FruitRepository {
private final Map<String, Integer> db = Database.getStorage();

@Override
public void add(String fruit, int quantity) {
Integer newQuantity = db.containsKey(fruit)
? db.get(fruit) + quantity
: quantity;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

map has native merge method to handle cases when key exists and doesn't exist

db.put(fruit, newQuantity);
}

@Override
public void remove(String fruit, int quantity) {
if (db.get(fruit) - quantity < 0) {
throw new RuntimeException("Not enough " + fruit + " in storage to remove");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's create a custom exception for such cases

}
db.put(fruit, db.get(fruit) - quantity);
}

@Override
public boolean hasFruit(String fruit) {
return db.containsKey(fruit);
}

@Override
public Map<String, Integer> getAll() {
return Map.copyOf(db);
}
}
16 changes: 16 additions & 0 deletions src/main/java/core/basesyntax/db/Database.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package core.basesyntax.db;

import java.util.HashMap;
import java.util.Map;

public class Database {
private static final Map<String, Integer> storage;

static {
storage = new HashMap<>();
}

public static Map<String, Integer> getStorage() {
return storage;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
private static final Map<String, Integer> storage;
static {
storage = new HashMap<>();
}
public static Map<String, Integer> getStorage() {
return storage;
}
public static final Map<String, Integer> storage = new HashMap<>();

}
39 changes: 39 additions & 0 deletions src/main/java/core/basesyntax/model/FruitTransaction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package core.basesyntax.model;

import core.basesyntax.model.enums.Operation;

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 String getFruit() {
return fruit;
}

public int getQuantity() {
return quantity;
}

public void setOperation(Operation operation) {
this.operation = operation;
}

public void setFruit(String fruit) {
this.fruit = fruit;
}

public void setQuantity(int quantity) {
this.quantity = quantity;
}
}
27 changes: 27 additions & 0 deletions src/main/java/core/basesyntax/model/enums/Operation.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package core.basesyntax.model.enums;

public enum Operation {
BALANCE("b"),
SUPPLY("s"),
PURCHASE("p"),
RETURN("r");

private final String code;

Operation(String code) {
this.code = code;
}

public String getCode() {
return code;
}

public static Operation getByCode(String code) {
for (Operation operation : values()) {
if (operation.code.equals(code)) {
return operation;
}
}
return null;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's throw an exception instead

}
}
8 changes: 8 additions & 0 deletions src/main/java/core/basesyntax/service/DataConverter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package core.basesyntax.service;

import core.basesyntax.model.FruitTransaction;
import java.util.List;

public interface DataConverter {
List<FruitTransaction> convertStringsDataToFruitTransactions(List<String> stringsData);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's make the method name concise and clear enough

}
9 changes: 9 additions & 0 deletions src/main/java/core/basesyntax/service/FileService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package core.basesyntax.service;

import java.util.List;

public interface FileService {
List<String> read(String filePath);

void write(String filePath, String data);
}
5 changes: 5 additions & 0 deletions src/main/java/core/basesyntax/service/ReportGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package core.basesyntax.service;

public interface ReportGenerator {
String generateReport();
}
8 changes: 8 additions & 0 deletions src/main/java/core/basesyntax/service/ShopService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package core.basesyntax.service;

import core.basesyntax.model.FruitTransaction;
import java.util.List;

public interface ShopService {
void process(List<FruitTransaction> transactions);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package core.basesyntax.service.handler;

import core.basesyntax.model.FruitTransaction;

public interface OperationHandler {
void handle(FruitTransaction transaction);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package core.basesyntax.service.handler;

import core.basesyntax.model.enums.Operation;

public interface OperationStrategy {
OperationHandler getOperationHandler(Operation operation);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package core.basesyntax.service.handler.impl;

import core.basesyntax.dao.FruitRepository;
import core.basesyntax.model.FruitTransaction;
import core.basesyntax.service.handler.OperationHandler;

public class BalanceOperationHandler extends BaseOperationHandler implements OperationHandler {
private final FruitRepository fruitRepository;

public BalanceOperationHandler(FruitRepository fruitRepository) {
this.fruitRepository = fruitRepository;
}

@Override
public void handle(FruitTransaction transaction) {
checkTransaction(transaction);
fruitRepository.add(transaction.getFruit(), transaction.getQuantity());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package core.basesyntax.service.handler.impl;

import core.basesyntax.model.FruitTransaction;

public class BaseOperationHandler {
public void checkTransaction(FruitTransaction transaction) {
if (transaction.getQuantity() < 0) {
throw new RuntimeException("Quantity can't be less than 0");
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this isn't a good place for transaction validations. It's better to validate quantity before or during parsing phase

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package core.basesyntax.service.handler.impl;

import core.basesyntax.model.enums.Operation;
import core.basesyntax.service.handler.OperationHandler;
import core.basesyntax.service.handler.OperationStrategy;
import java.util.Map;

public class OperationStrategyImpl implements OperationStrategy {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove empty line

Suggested change

private final Map<Operation, OperationHandler> handlersMap;

public OperationStrategyImpl(Map<Operation, OperationHandler> handlersMap) {
this.handlersMap = handlersMap;
}

@Override
public OperationHandler getOperationHandler(Operation operation) {
return handlersMap.get(operation);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package core.basesyntax.service.handler.impl;

import core.basesyntax.dao.FruitRepository;
import core.basesyntax.model.FruitTransaction;
import core.basesyntax.service.handler.OperationHandler;

public class PurchaseOperationHandler extends BaseOperationHandler implements OperationHandler {
private final FruitRepository repository;

public PurchaseOperationHandler(FruitRepository repository) {
this.repository = repository;
}

@Override
public void handle(FruitTransaction transaction) {
checkTransaction(transaction);
if (repository.hasFruit(transaction.getFruit())) {
repository.remove(transaction.getFruit(), transaction.getQuantity());
} else {
throw new RuntimeException("Can't return fruits that are/were not in storage");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do not use the most general RuntimeException. Create your own one for such a case. Fix the same issue in all places

}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package core.basesyntax.service.handler.impl;

import core.basesyntax.dao.FruitRepository;
import core.basesyntax.model.FruitTransaction;
import core.basesyntax.service.handler.OperationHandler;

public class ReturnOperationHandler extends BaseOperationHandler implements OperationHandler {
private final FruitRepository fruitRepository;

public ReturnOperationHandler(FruitRepository fruitRepository) {
this.fruitRepository = fruitRepository;
}

@Override
public void handle(FruitTransaction transaction) {
checkTransaction(transaction);
if (fruitRepository.hasFruit(transaction.getFruit())) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the same

fruitRepository.add(transaction.getFruit(), transaction.getQuantity());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package core.basesyntax.service.handler.impl;

import core.basesyntax.dao.FruitRepository;
import core.basesyntax.model.FruitTransaction;
import core.basesyntax.service.handler.OperationHandler;

public class SupplyOperationHandler extends BaseOperationHandler implements OperationHandler {
private final FruitRepository repository;

public SupplyOperationHandler(FruitRepository repository) {
this.repository = repository;
}

@Override
public void handle(FruitTransaction transaction) {
checkTransaction(transaction);
repository.add(transaction.getFruit(), transaction.getQuantity());
}
}
Loading
Loading