PQT_Gestionnaire_vent_stock/Workspace/server/src/main/java/com/pqt/server/module/stock/FileStockDao.java

174 lines
6.4 KiB
Java

package com.pqt.server.module.stock;
import com.pqt.core.entities.product.Product;
import com.pqt.server.tools.entities.SaleContent;
import com.pqt.server.tools.io.ISerialFileManager;
import com.pqt.server.tools.io.SimpleSerialFileManagerFactory;
import java.lang.IllegalStateException;
import java.util.*;
/**
* Implémentation de l'interface {@link IStockDao} utilisant un fichier de sauvegarde pour assurer la persistance des
* données liées aux produits vendus.
* <p/>
* Les données sont écrites et lues dans le fichier grâce au méchanisme de sérialisation/désérialisation. Elles ne sont
* pas faites pour être lisibles directement par un humain.
*
* @author Guillaume "Cess" Prost
*/
public class FileStockDao implements IStockDao {
private static final String STOCK_FILE_NAME = "stock.pqt";
private ISerialFileManager<Product> fileManager;
private long nextProductId;
private Random random;
private Map<Long, Product> products;
FileStockDao() {
random = new Random();
fileManager = SimpleSerialFileManagerFactory.getFileManager(Product.class, STOCK_FILE_NAME);
loadFromFile();
generateNextProductId();
}
private void generateNextProductId() {
Long newId;
do{
newId = random.nextLong();
}while (products.containsKey(newId));
nextProductId = newId;
}
/**
* @see com.pqt.server.module.stock.IStockDao#getProductList()
*/
public List<Product> getProductList() {
return copyOfProductList();
}
private List<Product> copyOfProductList() {
List<Product> copy = new ArrayList<>();
products.values().forEach(p->copy.add(new Product(p)));
return copy;
}
/**
* @see com.pqt.server.module.stock.IStockDao#getProduct(long)
*/
public Product getProduct(long id) {
return products.get(id);
}
/**
* @see com.pqt.server.module.stock.IStockDao#addProduct(com.pqt.core.entities.product.Product)
*/
public long addProduct(Product product) {
product.setId(nextProductId);
this.products.put(nextProductId, product);
long reply = nextProductId;
generateNextProductId();
saveToFile();
return reply;
}
/**
* @see com.pqt.server.module.stock.IStockDao#removeProduct(long)
*/
public void removeProduct(long id) {
Product product = getProduct(id);
if(product!=null){
this.products.remove(product.getId());
saveToFile();
}
}
/**
* @see com.pqt.server.module.stock.IStockDao#modifyProduct(long, com.pqt.core.entities.product.Product)
*/
public void modifyProduct(long id, Product product) {
if(this.products.containsKey(id)){
product.setId(id);
this.products.put(id, product);
saveToFile();
}
}
@Override
public void applySale(SaleContent saleContent) throws IllegalArgumentException {
if(saleContent==null)
return;
try {
for(Product product : saleContent.getProductList()){
applyRecursiveStockRemoval(product, saleContent.getProductAmount(product));
applySoldCounterIncrease(product, saleContent.getProductAmount(product));
}
saveToFile();
}catch (IllegalStateException e){
loadFromFile();
throw new IllegalArgumentException(e);
}
}
/**
* Cette méthode augmente le compteur de vente pour un produit donné dans la BDD.
*
* @param product données à utiliser pour déterminer le produit correspondant dans la BDD dont les données doivent
* être manipulées.
* @param amount montant à ajouter
* @throws IllegalStateException exception levée si le produit donné ne peut pas être trouvé dans la base de donnée.
*/
private void applySoldCounterIncrease(Product product, Integer amount) throws IllegalStateException{
Product correspondingProduct = getProduct(product.getId());
if(correspondingProduct!=null){
correspondingProduct.setAmountSold(correspondingProduct.getAmountSold() + amount);
}else{
StringBuilder sb = new StringBuilder("StockService>StockDao : Un produit vendu ne correspond pas à un produit connu : ");
sb.append(product.getId()).append(" - ").append(product.getName()).append("(").append(product.getCategory()).append(")");
throw new IllegalStateException(sb.toString());
}
}
/**
* Cette méthode retire à un produit donné de la BDD le montant spécifié (diminue la valeur de
* {@link Product#amountRemaining}), puis effectue récursivement la même opération pour tous les composants de ce
* produit.
*
* @param product données à utiliser pour déterminer le produit correspondant dans la BDD dont les données doivent
* être manipulées.
* @param amount montant à déduire
* @throws IllegalStateException exception levée si le produit donné ne peut pas être trouvé dans la base de donnée.
*/
private void applyRecursiveStockRemoval(Product product, int amount) throws IllegalStateException {
Product correspondingProduct = getProduct(product.getId());
if(correspondingProduct!=null) {
correspondingProduct.setAmountRemaining(correspondingProduct.getAmountRemaining() - amount);
correspondingProduct.getComponents().forEach(component -> applyRecursiveStockRemoval(component, amount));
}else{
StringBuilder sb = new StringBuilder("StockService>StockDao : Un produit vendu ne correspond pas à un produit connu : ");
sb.append(product.getId()).append(" - ").append(product.getName()).append("(").append(product.getCategory()).append(")");
throw new IllegalStateException(sb.toString());
}
}
/**
* Cette méthode charge les données relatives aux produits depuis le fichier de sauvegarde. Si ce fichier n'existe
* pas, il est créé et la liste des produits est vidée.
*/
private void loadFromFile() {
Map<Long, Product> loadedData = new HashMap<>();
fileManager.loadListFromFile().forEach(product -> loadedData.put(product.getId(), product));
products = new HashMap<>(loadedData);
}
/**
* Cette méthode écrit les données relatives aux produits dans le fichier de sauvegarde, écrasant le contenu
* précédent.
*/
private void saveToFile() {
fileManager.saveListToFile(new ArrayList<>(products.values()));
}
}