Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
21 changes: 21 additions & 0 deletions src/main/java/HW/models/DefaultIOOperations.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package HW.models;

import java.io.IOException;
import java.net.URL;
import java.nio.file.Path;

public class DefaultIOOperations {
public static String getPath(String path) throws IOException {
if (Path.of(path).isAbsolute()) {
return path;
}

URL resource;
if ((resource = DefaultIOOperations.class.getClassLoader().getResource(path)) != null) {
return resource.getPath();
} else if ((resource = DefaultIOOperations.class.getResource(path)) != null) {
return resource.getPath();
}
throw new IOException("Can't find file by path: " + path);
}
}
32 changes: 32 additions & 0 deletions src/main/java/HW/models/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package HW.models;

import HW.models.basket.BasketRepository;
import HW.models.basket.BasketRepositoryInMemory;
import HW.models.enums.Product;
import HW.models.parser.CommandParserTXT;
import HW.models.storage.Storage;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;

public class Main {
private static final Logger logger = Logger.getLogger(Main.class.getSimpleName());

public static void main(String[] args) {
Map<Product, Float> storageContent = new HashMap<>();
storageContent.put(Product.Bread, 100f);
storageContent.put(Product.Flour, 100f);
storageContent.put(Product.Water, 100f);
Storage storage = new Storage(storageContent);
BasketRepository basketRepository = new BasketRepositoryInMemory(storage);
String path = "commands/list1.txt";
try {
CommandParserTXT parser = new CommandParserTXT(path, basketRepository);
parser.applyAllCommands();
} catch (IOException e) {
logger.warning("Failed while executing commands from txt file: " + e.getMessage());
}
}
}
44 changes: 44 additions & 0 deletions src/main/java/HW/models/basket/Basket.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package HW.models.basket;

import HW.models.enums.Product;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class Basket {
private ConcurrentHashMap<Product, Float> products = new ConcurrentHashMap<>();

public Basket (Map<Product, Float> products) {
this.products = new ConcurrentHashMap<>();
this.products.putAll(products);
}

public Basket () {
this.products = new ConcurrentHashMap<>();
}

public synchronized void alterContent (Product product, float change) {
if (products.containsKey(product)) {
float newValue = products.get(product) + change;
if (newValue < 0) {
throw new IllegalArgumentException("Basket content can't be negative");
}
products.put(product, newValue);
} else {
products.put(product, change);
}
}

public synchronized void clearBasket () {
products.clear();
}

public Map<Product, Float> getProducts () {
return Map.copyOf(products);
}

public Basket getCopy() {
return new Basket(getProducts());
}
}
13 changes: 13 additions & 0 deletions src/main/java/HW/models/basket/BasketRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package HW.models.basket;

import HW.models.enums.Product;

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

public interface BasketRepository {
void changeBasketContent (long id, Product product, float change);
void tryOrderBasket (long id);
void removeBasket(long id);
Map<Long, Basket> getContent();
}
64 changes: 64 additions & 0 deletions src/main/java/HW/models/basket/BasketRepositoryInMemory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package HW.models.basket;

import HW.models.enums.Product;
import HW.models.storage.Storage;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;
import java.util.stream.Collectors;

public class BasketRepositoryInMemory implements BasketRepository{
private static final Logger logger = Logger.getLogger(BasketRepositoryInMemory.class.getSimpleName());
private final ConcurrentHashMap<Long, Basket> baskets = new ConcurrentHashMap<>();
private final Storage storage;

public BasketRepositoryInMemory(Storage storage) {
this.storage = storage;
}

@Override
public void changeBasketContent(long id, Product product, float change) {
synchronized (Long.valueOf(id)) {
logger.info("Basket with id " + id + " was changed: product->" + product.displayName + " change->" + change + " " + product.unitName);
if (!baskets.containsKey(id)) {
baskets.put(id, new Basket());
}
try {
baskets.get(id).alterContent(product, change);
} catch (IllegalArgumentException e) {
logger.info("Change to basket with id " + id + " wasn't made");
}
}
}

@Override
public void tryOrderBasket(long id) {
synchronized (Long.valueOf(id)) {
logger.info("Basket with id " + id + " was ordered");
try {
Map<Product, Float> basketContent = baskets.get(id).getProducts();
this.storage.takeAway(basketContent);
baskets.get(id).clearBasket();
} catch (RuntimeException e) {
logger.info("Basket with id " + id + " was ordered but failed!");
}
}
}

@Override
public void removeBasket(long id) {
synchronized (Long.valueOf(id)) {
logger.info("Basket with id " + id + " was removed");
baskets.remove(id);
}
}

@Override
public Map<Long, Basket> getContent() {
return baskets.entrySet().stream()
.map(entry -> Map.entry(entry.getKey(), entry.getValue().getCopy()))
.collect(Collectors.toMap(val -> val.getKey(), val -> val.getValue()));
}
}
62 changes: 62 additions & 0 deletions src/main/java/HW/models/parser/CommandParserTXT.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package HW.models.parser;

import HW.models.DefaultIOOperations;
import HW.models.basket.BasketRepository;
import HW.models.enums.Product;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.logging.Logger;

public class CommandParserTXT {
private static final Logger logger = Logger.getLogger(CommandParserTXT.class.getSimpleName());
private final String sourcePath;
private final BasketRepository basketRepository;
private final BufferedReader reader;

public CommandParserTXT(String sourcePath, BasketRepository basketRepository) throws IOException {
this.basketRepository = basketRepository;
if (!sourcePath.contains(".txt")) {
throw new IllegalArgumentException("File for CommandParserTXT has to be of type txt");
}
this.sourcePath = sourcePath;
this.reader = new BufferedReader(new FileReader(DefaultIOOperations.getPath(this.sourcePath)));
}

public boolean applyNextCommand () throws IOException {
String newLine = reader.readLine();
if (newLine == null) {
return false;
}
applyCommand(newLine);
return true;
}

public void applyAllCommands () throws IOException {
reader.lines().forEachOrdered(this::applyCommand);
reader.close();
}

private void applyCommand (String command) {
String[] parts = command.split(" ");
if (parts[0].equalsIgnoreCase("get")) {
try {
long id = Long.parseLong(parts[1]);
Product product = Product.valueOf(parts[2]);
float change = Float.parseFloat(parts[3]);
basketRepository.changeBasketContent(id, product, change);
} catch (IllegalArgumentException e) {
logger.info("Unknown product: " + parts[2]);
}
} else if (parts[0].equalsIgnoreCase("order")) {
long id = Long.parseLong(parts[1]);
basketRepository.tryOrderBasket(id);
} else if (parts[0].equalsIgnoreCase("remove")) {
long id = Long.parseLong(parts[1]);
basketRepository.removeBasket(id);
} else {
logger.info("Unknown command: " + parts[0]);
}
}
}
42 changes: 42 additions & 0 deletions src/main/java/HW/models/storage/Storage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package HW.models.storage;

import HW.models.basket.Basket;
import HW.models.enums.Product;

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

public class Storage{
private Map<Product, Float> content;

public Storage() {
this.content = new HashMap<Product, Float>();
}

public Storage(Map<Product, Float> content) {
this.content = content;
}

public synchronized void takeAway(Map<Product, Float> basketContent)
throws UnavailablePurchaseException {
for (Product product : basketContent.keySet()) {
if (this.content.containsKey(product)) {
if (this.content.get(product) < basketContent.get(product)) {
throw new UnavailablePurchaseException("Shortage of product!",
product + " не в наличии или его недостаточно для осуществления заказа");
}
} else {
throw new UnavailablePurchaseException("Unavailable product!",
product + " не хранится на складе");
}
}

for (Product product : basketContent.keySet()) {
this.content.put(product, this.content.get(product) - basketContent.get(product));
}
}

public synchronized Map<Product, Float> getContent() {
return Map.copyOf(content);
}
}
10 changes: 10 additions & 0 deletions src/main/java/HW/models/storage/UnavailablePurchaseException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package HW.models.storage;

public class UnavailablePurchaseException extends RuntimeException{
public final String reasonDescription;

public UnavailablePurchaseException(String message, String reasonDescription) {
super(message);
this.reasonDescription = reasonDescription;
}
}
16 changes: 16 additions & 0 deletions src/main/resources/commands/list1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
get 1 Water 10
get 1 Bread 20
get 2 Flour 5
get 3 Water 7
order 1
get 2 Bread 1000
remove 2
get 2 Flour 3
order 2
order 3
get 1 Water 5
order 1
get 4 Flour 1
remove 4
get 2 Bread 2
order 2
6 changes: 6 additions & 0 deletions src/main/resources/commands/testIllegal.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
get 1 Water 8
get 1 Bread 5
order 1
get 2 Flour 4
order 2
order 3
15 changes: 15 additions & 0 deletions src/main/resources/commands/testOverall.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
get 1 Water 2
get 1 Bread 8
get 2 Water 4
order 2
order 1
get 3 Bread 4
order 3
remove 3
get 2 Water 7
get 2 Bread 9
remove 2
get 2 Water 0.5
get 2 Bread 2
order 2
get 5 Bread 2
Loading