diff --git a/src/main/java/de/rwu/easydrop/Main.java b/src/main/java/de/rwu/easydrop/Main.java index c8f4f1e..db1fedb 100644 --- a/src/main/java/de/rwu/easydrop/Main.java +++ b/src/main/java/de/rwu/easydrop/Main.java @@ -1,23 +1,8 @@ package de.rwu.easydrop; -import java.util.List; - import javax.naming.ConfigurationException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.sqlite.SQLiteDataSource; - -import de.rwu.easydrop.api.client.DataSourceFactory; import de.rwu.easydrop.core.Core; -import de.rwu.easydrop.data.connector.AbstractProductPersistence; -import de.rwu.easydrop.data.connector.SQLiteConnector; -import de.rwu.easydrop.model.ProductCatalogue; -import de.rwu.easydrop.service.retriever.CatalogueRetriever; -import de.rwu.easydrop.service.retriever.ProductRetriever; -import de.rwu.easydrop.service.writer.CatalogueWriter; -import de.rwu.easydrop.util.Config; -import de.rwu.easydrop.util.ProductsConfig; /** * Kickoff point for the service. @@ -25,11 +10,6 @@ import de.rwu.easydrop.util.ProductsConfig; * @since 0.1.0 */ public final class Main { - /** - * Logger for main process. - */ - private static final Logger LOGGER = LoggerFactory.getLogger(Main.class); - /** * Prevents unwanted instantiation. */ @@ -43,19 +23,6 @@ public final class Main { * @param args */ public static void main(final String[] args) throws ConfigurationException { - Config config = Config.getInstance(); - ProductsConfig pConfig = ProductsConfig.getInstance(); - DataSourceFactory dataSourceFactory = new DataSourceFactory(config); - ProductRetriever retriever = new ProductRetriever(dataSourceFactory); - CatalogueRetriever catRetriever = new CatalogueRetriever(pConfig, retriever); - AbstractProductPersistence db = new SQLiteConnector(new SQLiteDataSource()); - CatalogueWriter catWriter = new CatalogueWriter(db); - - catRetriever.loadCatalogues(); - List pCats = catRetriever.getProductCatalogues(); - catWriter.writeCatalogues(pCats); - - Core core = new Core(); - core.runCore(pCats); + Core.run(); } } diff --git a/src/main/java/de/rwu/easydrop/api/client/AmazonProductDataSource.java b/src/main/java/de/rwu/easydrop/api/client/AmazonProductDataSource.java index 404398c..06c806e 100644 --- a/src/main/java/de/rwu/easydrop/api/client/AmazonProductDataSource.java +++ b/src/main/java/de/rwu/easydrop/api/client/AmazonProductDataSource.java @@ -9,6 +9,7 @@ import com.jayway.jsonpath.ReadContext; import de.rwu.easydrop.api.dto.ProductDTO; import de.rwu.easydrop.model.Webshop; +import de.rwu.easydrop.util.Timestamp; /** * Interface to an Amazon data source. @@ -61,6 +62,7 @@ public final class AmazonProductDataSource extends AbstractDataSource { product.setDeliveryPrice( ctx.read(root + "shippingOptions[0].shippingCost.value.amount", double.class)); product.setMerchant(ctx.read(root + "merchant.name", String.class)); + product.setLastUpdate(Timestamp.now()); } catch (PathNotFoundException e) { // Pass, allow incomplete ProductDTO to pass for later validation } diff --git a/src/main/java/de/rwu/easydrop/api/client/DataSourceFactory.java b/src/main/java/de/rwu/easydrop/api/client/DataSourceFactory.java index 490466c..ba79ab5 100644 --- a/src/main/java/de/rwu/easydrop/api/client/DataSourceFactory.java +++ b/src/main/java/de/rwu/easydrop/api/client/DataSourceFactory.java @@ -2,8 +2,6 @@ package de.rwu.easydrop.api.client; import javax.naming.ConfigurationException; -import de.rwu.easydrop.data.connector.AbstractProductPersistence; -import de.rwu.easydrop.exception.PersistenceException; import de.rwu.easydrop.util.Config; /** @@ -17,17 +15,6 @@ public class DataSourceFactory { * The data source config. */ private Config config; - /** - * Persistence interface. - */ - private AbstractProductPersistence persistence = null; - - /** - * @param newPersistence the persistence to set - */ - public void setPersistence(final AbstractProductPersistence newPersistence) { - this.persistence = newPersistence; - } /** * @param newConfig the config to set @@ -65,17 +52,4 @@ public class DataSourceFactory { String apiKey = config.getProperty("EBAY_API_KEY"); return new EbayItemDataSource(apiUrl, apiKey); } - - /** - * Creates a persistence data source. - * - * @return ProductPersistenceInterface - */ - public AbstractProductPersistence createProductPersistenceDataSource() { - if (persistence == null) { - throw new PersistenceException("Persistence is not set"); - } - - return persistence; - } } diff --git a/src/main/java/de/rwu/easydrop/api/client/EbayItemDataSource.java b/src/main/java/de/rwu/easydrop/api/client/EbayItemDataSource.java index 5e62394..0b1ed40 100644 --- a/src/main/java/de/rwu/easydrop/api/client/EbayItemDataSource.java +++ b/src/main/java/de/rwu/easydrop/api/client/EbayItemDataSource.java @@ -9,6 +9,7 @@ import com.jayway.jsonpath.ReadContext; import de.rwu.easydrop.api.dto.ProductDTO; import de.rwu.easydrop.model.Webshop; +import de.rwu.easydrop.util.Timestamp; /** * Interface to an eBay data source. @@ -70,6 +71,7 @@ public final class EbayItemDataSource extends AbstractDataSource { product.setDeliveryPrice( ctx.read(root + "shippingOptions[0].shippingCost.value", double.class)); product.setMerchant(ctx.read(root + "seller.username", String.class)); + product.setLastUpdate(Timestamp.now()); } catch (PathNotFoundException e) { // Pass, allow incomplete ProductDTO to pass for later validation } diff --git a/src/main/java/de/rwu/easydrop/api/dto/OfferDTO.java b/src/main/java/de/rwu/easydrop/api/dto/OfferDTO.java index c2d680f..8ffd6a8 100644 --- a/src/main/java/de/rwu/easydrop/api/dto/OfferDTO.java +++ b/src/main/java/de/rwu/easydrop/api/dto/OfferDTO.java @@ -1,52 +1,31 @@ package de.rwu.easydrop.api.dto; import lombok.Data; -import de.rwu.easydrop.model.Product; -import java.util.Date; /* - * Offer data transfer object + * Offer data transfer object. + * + * @since 0.3.0 */ @Data public class OfferDTO { /** - * Platform internal offer identifier. + * ID of the offer, built from identifiers of the source platforms. */ private String offerId; /** * The product that our software buys. */ - private Product sourceProduct; + private ProductDTO sourceProduct; /** * The product that our software sells. */ - private Product saleProduct; + private ProductDTO targetProduct; /** - * Date of the creation of the offer - * NOTE: Use Timestamp? - * https://docs.oracle.com/javase/8/docs/api/java/sql/Timestamp.html + * Date of last update of the offer. */ - private Date creationDate; - - /** - * Date of last update of the offer on the destination website (API). - */ - private Date upDate; - - /** - * Date of last check if offer is still valid. - */ - private Date checkDate; - - /** - * Creates OfferDTO instance. - * - * @param newOfferId Internal Offer identifier - */ - public OfferDTO(final String newOfferId) { - this.offerId = newOfferId; - } + private String lastUpdate; } diff --git a/src/main/java/de/rwu/easydrop/api/dto/ProductDTO.java b/src/main/java/de/rwu/easydrop/api/dto/ProductDTO.java index 7d7ea70..00956b1 100644 --- a/src/main/java/de/rwu/easydrop/api/dto/ProductDTO.java +++ b/src/main/java/de/rwu/easydrop/api/dto/ProductDTO.java @@ -40,6 +40,11 @@ public class ProductDTO { */ private boolean available; + /** + * Last update from API. + */ + private String lastUpdate; + /** * Creates ProductDTO instance. * diff --git a/src/main/java/de/rwu/easydrop/core/Core.java b/src/main/java/de/rwu/easydrop/core/Core.java index ce7e63b..3403b00 100644 --- a/src/main/java/de/rwu/easydrop/core/Core.java +++ b/src/main/java/de/rwu/easydrop/core/Core.java @@ -4,42 +4,74 @@ import java.util.List; import javax.naming.ConfigurationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sqlite.SQLiteDataSource; + +import de.rwu.easydrop.api.client.DataSourceFactory; +import de.rwu.easydrop.data.connector.OfferPersistenceInterface; +import de.rwu.easydrop.data.connector.ProductPersistenceInterface; +import de.rwu.easydrop.data.connector.SQLiteConnector; import de.rwu.easydrop.model.Offer; import de.rwu.easydrop.model.ProductCatalogue; +import de.rwu.easydrop.service.processing.OfferIdentifier; +import de.rwu.easydrop.service.processing.OfferProvisioner; +import de.rwu.easydrop.service.retriever.CatalogueRetriever; +import de.rwu.easydrop.service.retriever.ProductRetriever; +import de.rwu.easydrop.service.writer.CatalogueWriter; +import de.rwu.easydrop.util.Config; +import de.rwu.easydrop.util.ProductsConfig; /** * The application core. * * @since 0.3.0 */ -public class Core { +public final class Core { /** - * Offer identifier. + * Logging instance. */ - private OfferIdentifier ident; - /** - * Offer provisioner. - */ - private OfferProvisioner provis; + private static final Logger LOGGER = LoggerFactory.getLogger(Core.class); /** - * Constructor. - * - * @throws ConfigurationException + * Hidden Constructor. */ - public Core() throws ConfigurationException { - this.ident = new OfferIdentifier(); - this.provis = new OfferProvisioner(); - + private Core() { + // Hidden constructor } /** * Runs the core. * - * @param pCats + * @throws ConfigurationException */ - public void runCore(final List pCats) { + public static void run() throws ConfigurationException { + LOGGER.info("Loading config..."); + Config config = Config.getInstance(); + ProductsConfig pConfig = ProductsConfig.getInstance(); + + LOGGER.info("Preparing..."); + DataSourceFactory dataSourceFactory = new DataSourceFactory(config); + ProductPersistenceInterface pdb = new SQLiteConnector(new SQLiteDataSource()); + OfferPersistenceInterface odb = new SQLiteConnector(new SQLiteDataSource()); + ProductRetriever retriever = new ProductRetriever(dataSourceFactory, pdb); + CatalogueRetriever catRetriever = new CatalogueRetriever(pConfig, retriever); + CatalogueWriter catWriter = new CatalogueWriter(pdb); + + LOGGER.info("Loading catalogues"); + catRetriever.loadCatalogues(); + List pCats = catRetriever.getProductCatalogues(); + catWriter.writeCatalogues(pCats); + + LOGGER.info("Creating offers"); + OfferIdentifier ident = new OfferIdentifier(); List identifiedOffers = ident.runIdentifier(pCats); + OfferProvisioner provis = new OfferProvisioner(odb); provis.runProvisioner(identifiedOffers); + + // LOGGER.info("Creating transactions"); + // TODO: Transactions + + LOGGER.info("Done!"); } } diff --git a/src/main/java/de/rwu/easydrop/core/OfferIdentifier.java b/src/main/java/de/rwu/easydrop/core/OfferIdentifier.java deleted file mode 100644 index 99d4b23..0000000 --- a/src/main/java/de/rwu/easydrop/core/OfferIdentifier.java +++ /dev/null @@ -1,83 +0,0 @@ -package de.rwu.easydrop.core; - -import javax.naming.ConfigurationException; -import java.util.List; -import java.util.ArrayList; -import java.util.Date; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import de.rwu.easydrop.model.Offer; -import de.rwu.easydrop.model.ProductCatalogue; -import de.rwu.easydrop.model.ProductPair; -import de.rwu.easydrop.service.retriever.OfferRetriever; -import de.rwu.easydrop.service.processing.OrderManager; -import de.rwu.easydrop.exception.InvalidCatalogueException; - -public class OfferIdentifier { - /** - * Logger for main process. - */ - private static final Logger LOGGER = LoggerFactory.getLogger(OfferIdentifier.class); - /** - * OfferRetriever gets the offer from persistence. - */ - private OfferRetriever offerRetriever; - - /** - * OfferIdentifier identifies offers that are - * feasible to place on a target platform based on - * their margin. - * - * @throws ConfigurationException - */ - public OfferIdentifier() throws ConfigurationException { - this.offerRetriever = new OfferRetriever(); - } - - /** - * runIdentifier calls the price function that decides - * if it is feasible to dropship products and if so, - * at which margin. - * - * @param pCats - * @return newOffers - */ - public List runIdentifier(final List pCats) { - List identifiedOffers = new ArrayList<>(); - for (ProductCatalogue pCat : pCats) { - try { - // Call price finder for all catalogue - ProductPair pair = OrderManager.getHighestMarginProducts(pCat); - Offer possibleOffer = new Offer(); - possibleOffer.setCheckDate(new Date()); - possibleOffer.setSourceProduct(pair.getProduct1()); - possibleOffer.setSaleProduct(pair.getProduct2()); - identifiedOffers.add(possibleOffer); - LOGGER.info( - "Identified offer " - + - pair.getProduct1().getProductId() - + - " -> " - + - pair.getProduct2().getProductId()); - // Following fields will be set if offer confirmed - // creationDate, offerId - // Following fields will be set if offer needs update - // upDate - } catch (InvalidCatalogueException e) { - // if no margin, getHighestMarginProducts will throw - System.out.print("product has no margin"); - } - } - List newOffers = new ArrayList<>(); - for (Offer identifiedOffer : identifiedOffers) { - boolean isNew = true; - if (isNew) { - newOffers.add(identifiedOffer); - } - } - return newOffers; - } -} diff --git a/src/main/java/de/rwu/easydrop/core/OfferReviewer.java b/src/main/java/de/rwu/easydrop/core/OfferReviewer.java deleted file mode 100644 index e394093..0000000 --- a/src/main/java/de/rwu/easydrop/core/OfferReviewer.java +++ /dev/null @@ -1,81 +0,0 @@ -package de.rwu.easydrop.core; - -import de.rwu.easydrop.model.Offer; -import de.rwu.easydrop.model.Product; - -import java.util.List; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.Date; - -public class OfferReviewer { - - /** - * Check all Offers and compare them with the API. - * @return list of all items that need to be changed - */ - public List checkOffer(/*OfferReader/retriever for database? */) { - - Connection connection = null; - Statement statement = null; - ResultSet resultSet = null; - List changedOffers = new ArrayList<>(); - - try { - // Establish the database connection - connection = DriverManager.getConnection("jdbc:sqlite:persistence.db"); - - // Create a SQL statement - statement = connection.createStatement(); - - // Execute the query to retrieve the entries - String query = "SELECT sourceProduct, saleProduct, creationDate, upDate, " - + "checkDate, offerId FROM table"; - resultSet = statement.executeQuery(query); - - // Process the retrieved entries - while (resultSet.next()) { - Product sourceProduct = (Product) resultSet.getObject("sourceProduct"); - Product saleProduct = (Product) resultSet.getObject("saleProduct"); - java.sql.Date creationDate = resultSet.getDate("creationDate"); - Date updateDate = resultSet.getDate("upDate"); - Date checkDate = resultSet.getDate("checkDate"); - String offerId = resultSet.getString("offerId"); - - // Call the API to get the current price - double apiPrice = getPriceFromAPI(sourceProduct); - - // Compare the prices - if (saleProduct.getCurrentPrice() != apiPrice) { - // Price has changed, create a Product object and add it to the changedProducts list - Offer offer = new Offer(); - changedOffers.add(offer); - } - } - } catch (SQLException e) { - e.printStackTrace(); - } finally { - try { - if (resultSet != null) { - resultSet.close(); - } - if (statement != null) { - statement.close(); - } - if (connection != null) { - connection.close(); - } - } catch (SQLException e) { - e.printStackTrace(); - } - } - return new ArrayList(); - } - - - -} diff --git a/src/main/java/de/rwu/easydrop/core/OfferUpdater.java b/src/main/java/de/rwu/easydrop/core/OfferUpdater.java deleted file mode 100644 index 27d08a9..0000000 --- a/src/main/java/de/rwu/easydrop/core/OfferUpdater.java +++ /dev/null @@ -1,110 +0,0 @@ -package de.rwu.easydrop.core; - -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.util.List; -import de.rwu.easydrop.model.Offer; -import de.rwu.easydrop.model.Product; - - -public class OfferUpdater { - - /** - * a. - */ - public OfferUpdater() { - - OfferReviewer offerReviewer = new OfferReviewer(); - List changedOffers = offerReviewer.checkOffer(); - } - - /** - * A. - * @param offersToUpdate - */ - public void runUpdater(final List offersToUpdate) { - Connection connection = null; - PreparedStatement deleteStatement = null; - PreparedStatement insertStatement = null; - - try { - // Establish the database connection - connection = DriverManager.getConnection("jdbc:sqlite:persistence.db"); - - // Disable auto-commit to perform a transaction - connection.setAutoCommit(false); - - // Prepare the DELETE statement to remove the existing entries - String deleteQuery = "DELETE FROM your_table WHERE product_id = ?"; - deleteStatement = connection.prepareStatement(deleteQuery); - - // Prepare the INSERT statement to add the new entries - String insertQuery = "INSERT INTO your_table (product_id, product_name, price)" - + "VALUES (?, ?, ?)"; - insertStatement = connection.prepareStatement(insertQuery); - - // Retrieve the existing entries from the database - List existingProducts = retrieveExistingProducts(connection); - - // Delete the existing entries that are not present in the changedProducts list - for (Product existingProduct : existingProducts) { - if (!changedOffers.(existingProduct)) { - deleteStatement.setString(1, existingProduct.getProductId()); - deleteStatement.executeUpdate(); - } - } - - // Insert the new entries or update the existing entries - for (Product changedOffers : offersToUpdate) { - if (existingProducts.contains(changedOffers)) { - // Update the existing entry with the new data - // You need to modify the update query and statement based on your requirements - // Here's an example of updating the price of an existing entry - String updateQuery = "UPDATE table SET currentPrice = ? WHERE offerId = ?"; - PreparedStatement updateStatement = connection.prepareStatement(updateQuery); - updateStatement.setDouble(1, changedOffers.getCurrentPrice()); - updateStatement.setString(2, changedOffers.getProductId()); - updateStatement.executeUpdate(); - updateStatement.close(); - } else { - // Insert the new entry - insertStatement.setString(1, changedOffers.getProductId()); - insertStatement.setString(2, changedOffers.getMerchant()); - insertStatement.setDouble(3, changedOffers.getCurrentPrice()); - insertStatement.executeUpdate(); - } - } - - // Commit the transaction - connection.commit(); - } catch (SQLException e) { - // Rollback the transaction in case of an exception - if (connection != null) { - try { - connection.rollback(); - } catch (SQLException rollbackException) { - rollbackException.printStackTrace(); - } - } - e.printStackTrace(); - } finally { - // Close the resources (deleteStatement, insertStatement, connection) in a finally block - try { - if (deleteStatement != null) { - deleteStatement.close(); - } - if (insertStatement != null) { - insertStatement.close(); - } - if (connection != null) { - connection.close(); - } - } catch (SQLException e) { - e.printStackTrace(); - } - } -} -} - diff --git a/src/main/java/de/rwu/easydrop/data/connector/AbstractProductPersistence.java b/src/main/java/de/rwu/easydrop/data/connector/AbstractProductPersistence.java deleted file mode 100644 index 6a302dc..0000000 --- a/src/main/java/de/rwu/easydrop/data/connector/AbstractProductPersistence.java +++ /dev/null @@ -1,34 +0,0 @@ -package de.rwu.easydrop.data.connector; - -import de.rwu.easydrop.api.client.AbstractDataSource; -import de.rwu.easydrop.api.dto.ProductDTO; - -/** - * Allows connecting to a persistent product data store. - * - * @since 0.2.0 - */ -public abstract class AbstractProductPersistence extends AbstractDataSource { - /** - * Data origin. - */ - public static final String DATA_ORIGIN = "Persistence"; - - /** - * Writes a ProductDTO to persistence. - * - * @param dto - */ - public abstract void saveProduct(ProductDTO dto); - - /** - * Gets a ProductDTO from persistence. - */ - @Override - public abstract ProductDTO getProductDTOById(String productId); - - /** - * Deletes all data from persistence. - */ - public abstract void clearData(); -} diff --git a/src/main/java/de/rwu/easydrop/data/connector/AbstractOfferPersistence.java b/src/main/java/de/rwu/easydrop/data/connector/OfferPersistenceInterface.java similarity index 64% rename from src/main/java/de/rwu/easydrop/data/connector/AbstractOfferPersistence.java rename to src/main/java/de/rwu/easydrop/data/connector/OfferPersistenceInterface.java index 5f4bbeb..5d2284b 100644 --- a/src/main/java/de/rwu/easydrop/data/connector/AbstractOfferPersistence.java +++ b/src/main/java/de/rwu/easydrop/data/connector/OfferPersistenceInterface.java @@ -2,13 +2,13 @@ package de.rwu.easydrop.data.connector; import de.rwu.easydrop.api.dto.OfferDTO; -public abstract class AbstractOfferPersistence { +public interface OfferPersistenceInterface { /** * Writes a ProductDTO to persistence. * * @param dto */ - public abstract void saveOffer(OfferDTO dto); + void writeOffer(OfferDTO dto); /** * Gets a OfferDTO from persistence. @@ -16,10 +16,10 @@ public abstract class AbstractOfferPersistence { * @param offerId * @return Offer data transfer object */ - public abstract OfferDTO getOfferDTOById(String offerId); + OfferDTO getOfferDTOById(String offerId); /** * Deletes all data from persistence. */ - public abstract void clearData(); + void clearData(); } diff --git a/src/main/java/de/rwu/easydrop/data/connector/ProductPersistenceInterface.java b/src/main/java/de/rwu/easydrop/data/connector/ProductPersistenceInterface.java new file mode 100644 index 0000000..b5a1c1a --- /dev/null +++ b/src/main/java/de/rwu/easydrop/data/connector/ProductPersistenceInterface.java @@ -0,0 +1,30 @@ +package de.rwu.easydrop.data.connector; + +import de.rwu.easydrop.api.dto.ProductDTO; + +/** + * Allows connecting to a persistent product data store. + * + * @since 0.2.0 + */ +public interface ProductPersistenceInterface { + /** + * Writes a ProductDTO to persistence. + * + * @param dto + */ + void writeProduct(ProductDTO dto); + + /** + * Gets a ProductDTO from persistence. + * + * @param productId Product identifier + * @return Product data transfer object + */ + ProductDTO getProductDTOById(String productId); + + /** + * Deletes all data from persistence. + */ + void clearData(); +} diff --git a/src/main/java/de/rwu/easydrop/data/connector/SQLiteConnector.java b/src/main/java/de/rwu/easydrop/data/connector/SQLiteConnector.java index 43bb4fe..ba43d53 100644 --- a/src/main/java/de/rwu/easydrop/data/connector/SQLiteConnector.java +++ b/src/main/java/de/rwu/easydrop/data/connector/SQLiteConnector.java @@ -1,6 +1,5 @@ package de.rwu.easydrop.data.connector; -import java.net.URL; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -9,6 +8,7 @@ import java.sql.Statement; import org.sqlite.SQLiteDataSource; +import de.rwu.easydrop.api.dto.OfferDTO; import de.rwu.easydrop.api.dto.ProductDTO; import de.rwu.easydrop.exception.PersistenceException; import de.rwu.easydrop.model.Webshop; @@ -18,7 +18,8 @@ import de.rwu.easydrop.model.Webshop; * * @since 0.2.0 */ -public final class SQLiteConnector extends AbstractProductPersistence { +public final class SQLiteConnector implements + ProductPersistenceInterface, OfferPersistenceInterface { /** * SQLite Database. */ @@ -53,8 +54,8 @@ public final class SQLiteConnector extends AbstractProductPersistence { Connection connection = db.getConnection(); // Execute SQL statements to create tables - Statement statement = connection.createStatement(); - statement.execute( + Statement createProducts = connection.createStatement(); + createProducts.execute( "CREATE TABLE IF NOT EXISTS products (" + "dataOrigin TEXT, " + "productId TEXT, " @@ -62,12 +63,29 @@ public final class SQLiteConnector extends AbstractProductPersistence { + "merchant TEXT, " + "deliveryPrice REAL, " + "available INT, " - + "lastupdate TEXT, " + + "lastUpdate TEXT, " + "UNIQUE(productId, dataOrigin) ON CONFLICT REPLACE" + ")"); - // Close the statement and connection - statement.close(); + // Close the statement + createProducts.close(); + + Statement createOffers = connection.createStatement(); + createOffers.execute( + "CREATE TABLE IF NOT EXISTS offers (" + + "offerId TEXT, " + + "sourceWebshop TEXT, " + + "sourceId TEXT," + + "sourcePrice REAL, " + + "targetWebshop TEXT, " + + "targetId TEXT, " + + "targetPrice REAL, " + + "lastUpdate TEXT, " + + "UNIQUE(offerId) ON CONFLICT REPLACE" + + ")"); + createOffers.close(); + + // Close the connection connection.close(); } catch (SQLException e) { throw new PersistenceException("Something went wrong while initializing SQLite DB", e); @@ -79,12 +97,12 @@ public final class SQLiteConnector extends AbstractProductPersistence { * * @param dto */ - public void saveProduct(final ProductDTO dto) { + public void writeProduct(final ProductDTO dto) { String query = "INSERT INTO products (" + "dataOrigin, productId, currentPrice, merchant, " - + "deliveryPrice, available, lastupdate" + + "deliveryPrice, available, lastUpdate" + ") VALUES (" - + "?, ?, ?, ?, ?, ?, datetime('now', 'localtime')" + + "?, ?, ?, ?, ?, ?, ?" + ")"; try (Connection connection = db.getConnection(); @@ -97,6 +115,7 @@ public final class SQLiteConnector extends AbstractProductPersistence { statement.setString(++index, dto.getMerchant()); statement.setDouble(++index, dto.getDeliveryPrice()); statement.setBoolean(++index, dto.isAvailable()); + statement.setString(++index, dto.getLastUpdate()); statement.executeUpdate(); } catch (SQLException e) { @@ -138,7 +157,7 @@ public final class SQLiteConnector extends AbstractProductPersistence { public void clearData() { try (Connection connection = db.getConnection(); Statement statement = connection.createStatement()) { - String query = "DELETE FROM products"; + String query = "DELETE FROM products; DELETE FROM offers;"; statement.executeUpdate(query); } catch (SQLException e) { throw new PersistenceException("Something went wrong while clearing the database", e); @@ -146,26 +165,68 @@ public final class SQLiteConnector extends AbstractProductPersistence { } @Override - protected Webshop getDataOrigin() { - throw new UnsupportedOperationException( - this.getClass().getName() + " doesn't support getDataOrigin"); + public void writeOffer(final OfferDTO dto) { + String query = "INSERT INTO offers (" + + "offerId, " + + "sourceWebshop, sourceId, sourcePrice, " + + "targetWebshop, targetId, targetPrice, " + + "lastUpdate" + + ") VALUES (" + + "?, ?, ?, ?, ?, ?, ?, ?" + + ")"; + + try (Connection connection = db.getConnection(); + PreparedStatement statement = connection.prepareStatement(query)) { + int index = 0; + ProductDTO sourceProduct = dto.getSourceProduct(); + ProductDTO targetProduct = dto.getTargetProduct(); + + statement.setString(++index, dto.getOfferId()); + statement.setString(++index, sourceProduct.getProductId()); + statement.setString(++index, sourceProduct.getDataOrigin().toString()); + statement.setDouble(++index, sourceProduct.getCurrentPrice()); + statement.setString(++index, targetProduct.getProductId()); + statement.setString(++index, targetProduct.getDataOrigin().toString()); + statement.setDouble(++index, targetProduct.getCurrentPrice()); + statement.setString(++index, dto.getLastUpdate()); + + statement.executeUpdate(); + } catch (SQLException e) { + throw new PersistenceException("Something went wrong while saving to SQLite", e); + } } @Override - protected String getApiKey() { - throw new UnsupportedOperationException( - this.getClass().getName() + " doesn't support getApiKey"); - } + public OfferDTO getOfferDTOById(final String offerId) { + String query = "SELECT * FROM offers WHERE offerId = ?"; + OfferDTO dto = null; - @Override - protected ProductDTO buildProductDTO(final ProductDTO product, final String json) { - throw new UnsupportedOperationException( - this.getClass().getName() + " doesn't support buildProductDTO"); - } + try (Connection connection = db.getConnection(); + PreparedStatement statement = connection.prepareStatement(query)) { - @Override - protected URL createApiUrl(final String productIdentifier) { - throw new UnsupportedOperationException( - this.getClass().getName() + " doesn't support createApiUrl"); + statement.setString(1, offerId); + + try (ResultSet resultSet = statement.executeQuery()) { + if (resultSet.next()) { + dto = new OfferDTO(); + ProductDTO srcProduct = new ProductDTO( + resultSet.getString("sourceId"), + Webshop.fromString(resultSet.getString("sourceWebshop"))); + srcProduct.setCurrentPrice(resultSet.getDouble("sourcePrice")); + ProductDTO targetProduct = new ProductDTO( + resultSet.getString("targetId"), + Webshop.fromString(resultSet.getString("targetWebshop"))); + srcProduct.setCurrentPrice(resultSet.getDouble("targetPrice")); + dto.setOfferId(resultSet.getString("offerId")); + dto.setSourceProduct(srcProduct); + dto.setTargetProduct(targetProduct); + dto.setLastUpdate(resultSet.getString("lastUpdate")); + } + } + } catch (SQLException e) { + throw new PersistenceException("Something went wrong while reading from SQLite", e); + } + + return dto; } } diff --git a/src/main/java/de/rwu/easydrop/exception/InvalidOfferException.java b/src/main/java/de/rwu/easydrop/exception/InvalidOfferException.java new file mode 100644 index 0000000..f4d2c0b --- /dev/null +++ b/src/main/java/de/rwu/easydrop/exception/InvalidOfferException.java @@ -0,0 +1,22 @@ +package de.rwu.easydrop.exception; + +public class InvalidOfferException extends RuntimeException { + /** + * Throws an exception that signifies the data of an Offer are invalid. + * + * @param message + */ + public InvalidOfferException(final String message) { + super(message); + } + + /** + * Throws an exception that signifies the data of an Offer are invalid. + * + * @param message + * @param cause + */ + public InvalidOfferException(final String message, final Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/de/rwu/easydrop/model/Offer.java b/src/main/java/de/rwu/easydrop/model/Offer.java index 8fae3b7..b2e3577 100644 --- a/src/main/java/de/rwu/easydrop/model/Offer.java +++ b/src/main/java/de/rwu/easydrop/model/Offer.java @@ -1,8 +1,5 @@ package de.rwu.easydrop.model; -import java.util.Date; - - import lombok.Data; /** @@ -10,9 +7,13 @@ import lombok.Data; * * @since 0.3.0 */ - @Data public class Offer { + /** + * ID of the offer, built from identifiers of the source platforms. + */ + private String offerId; + /** * The product that our software buys. */ @@ -21,27 +22,10 @@ public class Offer { /** * The product that our software sells. */ - private Product saleProduct; + private Product targetProduct; /** - * Date of the creation of the offer. - * NOTE: Use Timestamp? https://docs.oracle.com/javase/8/docs/api/java/sql/Timestamp.html + * Date of last update of the offer. */ - private Date creationDate; - - /** - * Date of last update of the offer on the destination website (API). - */ - private Date upDate; - - /** - * Date of last check if offer is still valid. - */ - private Date checkDate; - - /** - * ID of the offer. - */ - private String offerId; - + private String lastUpdate; } diff --git a/src/main/java/de/rwu/easydrop/model/Product.java b/src/main/java/de/rwu/easydrop/model/Product.java index 7e84311..dd412dd 100644 --- a/src/main/java/de/rwu/easydrop/model/Product.java +++ b/src/main/java/de/rwu/easydrop/model/Product.java @@ -40,6 +40,11 @@ public class Product { */ private boolean available; + /** + * Last update from API. + */ + private String lastUpdate; + @Override public final String toString() { return "Product: [" diff --git a/src/main/java/de/rwu/easydrop/model/ProductCatalogue.java b/src/main/java/de/rwu/easydrop/model/ProductCatalogue.java index 97f31dc..2e91d1c 100644 --- a/src/main/java/de/rwu/easydrop/model/ProductCatalogue.java +++ b/src/main/java/de/rwu/easydrop/model/ProductCatalogue.java @@ -68,7 +68,7 @@ public class ProductCatalogue { @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("Product Catalogue: ").append(productName).append("\n"); + sb.append("Catalogue Name: ").append(productName).append("\n"); sb.append("Description: ").append(description).append("\n"); sb.append("Products:\n"); for (Product product : products) { diff --git a/src/main/java/de/rwu/easydrop/service/mapping/OfferMapper.java b/src/main/java/de/rwu/easydrop/service/mapping/OfferMapper.java index a83a148..aa98afe 100644 --- a/src/main/java/de/rwu/easydrop/service/mapping/OfferMapper.java +++ b/src/main/java/de/rwu/easydrop/service/mapping/OfferMapper.java @@ -1,7 +1,6 @@ package de.rwu.easydrop.service.mapping; import de.rwu.easydrop.api.dto.OfferDTO; - import de.rwu.easydrop.model.Offer; /** @@ -31,6 +30,10 @@ public final class OfferMapper { */ public static Offer mapOfferFromDTO(final OfferDTO dto) { Offer offer = new Offer(); + offer.setOfferId(dto.getOfferId()); + offer.setSourceProduct(ProductMapper.mapProductFromDTO(dto.getSourceProduct())); + offer.setTargetProduct(ProductMapper.mapProductFromDTO(dto.getTargetProduct())); + offer.setLastUpdate(dto.getLastUpdate()); return offer; } @@ -42,7 +45,11 @@ public final class OfferMapper { * @return OfferDTO */ public static OfferDTO mapOfferToDTO(final Offer offer) { - OfferDTO dto = new OfferDTO(offer.getOfferId()); + OfferDTO dto = new OfferDTO(); + dto.setOfferId(offer.getOfferId()); + dto.setSourceProduct(ProductMapper.mapProductToDTO(offer.getSourceProduct())); + dto.setTargetProduct(ProductMapper.mapProductToDTO(offer.getTargetProduct())); + dto.setLastUpdate(offer.getLastUpdate()); return dto; } diff --git a/src/main/java/de/rwu/easydrop/service/mapping/ProductMapper.java b/src/main/java/de/rwu/easydrop/service/mapping/ProductMapper.java index 123080a..6ada1b4 100644 --- a/src/main/java/de/rwu/easydrop/service/mapping/ProductMapper.java +++ b/src/main/java/de/rwu/easydrop/service/mapping/ProductMapper.java @@ -39,6 +39,7 @@ public final class ProductMapper { product.setDeliveryPrice(dto.getDeliveryPrice()); product.setMerchant(dto.getMerchant()); product.setProductId(dto.getProductId()); + product.setLastUpdate(dto.getLastUpdate()); return product; } @@ -56,6 +57,7 @@ public final class ProductMapper { dto.setCurrentPrice(product.getCurrentPrice()); dto.setDeliveryPrice(product.getDeliveryPrice()); dto.setMerchant(product.getMerchant()); + dto.setLastUpdate(product.getLastUpdate()); return dto; } diff --git a/src/main/java/de/rwu/easydrop/service/processing/OrderManager.java b/src/main/java/de/rwu/easydrop/service/processing/OfferIdentifier.java similarity index 64% rename from src/main/java/de/rwu/easydrop/service/processing/OrderManager.java rename to src/main/java/de/rwu/easydrop/service/processing/OfferIdentifier.java index d841505..629d594 100644 --- a/src/main/java/de/rwu/easydrop/service/processing/OrderManager.java +++ b/src/main/java/de/rwu/easydrop/service/processing/OfferIdentifier.java @@ -1,56 +1,56 @@ package de.rwu.easydrop.service.processing; +import java.util.ArrayList; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import de.rwu.easydrop.exception.InvalidCatalogueException; +import de.rwu.easydrop.exception.InvalidOfferException; +import de.rwu.easydrop.model.Offer; import de.rwu.easydrop.model.Product; import de.rwu.easydrop.model.ProductCatalogue; import de.rwu.easydrop.model.ProductPair; import de.rwu.easydrop.util.FormattingUtil; +import de.rwu.easydrop.util.Timestamp; -/** - * Creates dropshipping orders based on price margin. - * - * @since 0.3.0 - */ -public final class OrderManager { - +public class OfferIdentifier { /** - * Temporary logging instance. + * Logging instance. */ - private static final Logger LOGGER = LoggerFactory.getLogger(OrderManager.class); + private static final Logger LOGGER = LoggerFactory.getLogger(OfferIdentifier.class); /** - * Private constructor to prevent unwanted instantiation. + * runIdentifier calls the price function that decides + * if it is feasible to dropship products. * - * @throws UnsupportedOperationException always + * @param pCats Product catalogues + * @return Identified offers */ - private OrderManager() throws UnsupportedOperationException { - throw new UnsupportedOperationException("This is a stateless class, don't instantiate it."); - } - - /** - * Creates orders for products with sufficient margin. - * - * @param pCats Product Catalogues - */ - public static void createOrders(final List pCats) { + public List runIdentifier(final List pCats) { + List identifiedOffers = new ArrayList<>(); for (ProductCatalogue pCat : pCats) { - ProductPair pair = getHighestMarginProducts(pCat); - // #12: Create actual orders/transactions, remove logger + // Call price finder for all catalogue + ProductPair pair = getHighestMarginProducts(pCat); + Offer possibleOffer = new Offer(); + possibleOffer.setLastUpdate(Timestamp.now()); + possibleOffer.setSourceProduct(pair.getProduct1()); + possibleOffer.setTargetProduct(pair.getProduct2()); + identifiedOffers.add(possibleOffer); + double margin = pair.getProduct2().getCurrentPrice() - pair.getProduct1().getCurrentPrice(); String marginFormatted = FormattingUtil.formatEuro(margin); - LOGGER.info("{}: Margin {} ({} to {})", + LOGGER.info("\n Identified Offer: {} ({} to {}) with margin {} ", pCat.getProductName(), - marginFormatted, pair.getProduct1().getDataOrigin(), - pair.getProduct2().getDataOrigin()); + pair.getProduct2().getDataOrigin(), + marginFormatted); } + + return identifiedOffers; } /** @@ -79,7 +79,7 @@ public final class OrderManager { } if (cheapestProduct.getCurrentPrice() == mostExpensiveProduct.getCurrentPrice()) { - throw new InvalidCatalogueException("Price margin is zero!"); + throw new InvalidOfferException("Price margin is zero!"); } return new ProductPair(cheapestProduct, mostExpensiveProduct); diff --git a/src/main/java/de/rwu/easydrop/core/OfferProvisioner.java b/src/main/java/de/rwu/easydrop/service/processing/OfferProvisioner.java similarity index 57% rename from src/main/java/de/rwu/easydrop/core/OfferProvisioner.java rename to src/main/java/de/rwu/easydrop/service/processing/OfferProvisioner.java index 0f318bd..d6801c7 100644 --- a/src/main/java/de/rwu/easydrop/core/OfferProvisioner.java +++ b/src/main/java/de/rwu/easydrop/service/processing/OfferProvisioner.java @@ -1,15 +1,16 @@ -package de.rwu.easydrop.core; +package de.rwu.easydrop.service.processing; import java.util.List; import de.rwu.easydrop.api.client.AmazonSeller; import de.rwu.easydrop.api.client.EbaySeller; -import de.rwu.easydrop.exception.DataWriterException; +import de.rwu.easydrop.data.connector.OfferPersistenceInterface; import de.rwu.easydrop.model.Offer; import de.rwu.easydrop.model.Webshop; import de.rwu.easydrop.service.mapping.ProductMapper; import de.rwu.easydrop.service.writer.OfferWriter; import de.rwu.easydrop.util.Config; +import de.rwu.easydrop.util.FormattingUtil; public class OfferProvisioner { /** @@ -31,11 +32,11 @@ public class OfferProvisioner { private EbaySeller ebaySeller; private void toSeller(final Offer offer) throws IllegalArgumentException { - if (offer.getSaleProduct().getDataOrigin() == Webshop.eBay) { - this.ebaySeller.sellProduct(ProductMapper.mapProductToDTO(offer.getSaleProduct())); + if (offer.getTargetProduct().getDataOrigin() == Webshop.eBay) { + this.ebaySeller.sellProduct(ProductMapper.mapProductToDTO(offer.getTargetProduct())); - } else if (offer.getSaleProduct().getDataOrigin().equals(Webshop.Amazon)) { - this.amazonSeller.sellProduct(ProductMapper.mapProductToDTO(offer.getSaleProduct())); + } else if (offer.getTargetProduct().getDataOrigin().equals(Webshop.Amazon)) { + this.amazonSeller.sellProduct(ProductMapper.mapProductToDTO(offer.getTargetProduct())); } else { throw new IllegalArgumentException("Unsupported target plattform"); } @@ -44,10 +45,11 @@ public class OfferProvisioner { /** * Is the class for placing orders on a target platform. + * + * @param db Persistence Interface */ - public OfferProvisioner(/* OfferWriter for database? */) { - - this.offerWriter = new OfferWriter(); + public OfferProvisioner(final OfferPersistenceInterface db) { + this.offerWriter = new OfferWriter(db); this.config = Config.getInstance(); this.amazonSeller = new AmazonSeller( config.getProperty("AMAZON_API_URL"), @@ -63,27 +65,17 @@ public class OfferProvisioner { * @param offersToProvision */ public final void runProvisioner(final List offersToProvision) { - for (Offer newOffer : offersToProvision) { + String newOfferId = FormattingUtil.removeSpaces( + newOffer.getSourceProduct().getDataOrigin().toString() + + newOffer.getTargetProduct().getDataOrigin().toString() + + "_" + + newOffer.getSourceProduct().getProductId() + + newOffer.getTargetProduct().getProductId()); - try { - this.toSeller(newOffer); - // if successfully transmitted - // add to persistence - // "duplicate" the product with dataOrigin new platform and merchant = "me" - try { - offerWriter.writeOfferToPersistence(newOffer); - } catch (Exception e) { - System.out.println("Could not write to persistence"); - } - } catch (IllegalArgumentException e) { - System.out.println( - "Offer could not be placed, " - + newOffer.getSaleProduct().getDataOrigin() - + " is not supported"); - } catch (DataWriterException e) { - System.out.println("could not transmit offer"); - } + this.toSeller(newOffer); + newOffer.setOfferId(newOfferId); + offerWriter.writeOfferToPersistence(newOffer); } } } diff --git a/src/main/java/de/rwu/easydrop/service/retriever/CatalogueRetriever.java b/src/main/java/de/rwu/easydrop/service/retriever/CatalogueRetriever.java index c299412..9af6436 100644 --- a/src/main/java/de/rwu/easydrop/service/retriever/CatalogueRetriever.java +++ b/src/main/java/de/rwu/easydrop/service/retriever/CatalogueRetriever.java @@ -5,6 +5,9 @@ import java.util.List; import javax.naming.ConfigurationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import de.rwu.easydrop.model.Product; import de.rwu.easydrop.model.ProductCatalogue; import de.rwu.easydrop.util.ProductsConfig; @@ -17,6 +20,11 @@ import lombok.Data; */ @Data public class CatalogueRetriever { + /** + * Logging instance. + */ + private static final Logger LOGGER = LoggerFactory.getLogger(CatalogueRetriever.class); + /** * User-configured products. */ @@ -56,15 +64,14 @@ public class CatalogueRetriever { pCat.getProductName(), pCat.getDescription()); for (Product product : pCat.getProducts()) { - Product newProduct = new Product(); - - newProduct = productRetriever.getProductFromWebshop(product.getDataOrigin(), + Product newProduct = productRetriever.getProductFromWebshop(product.getDataOrigin(), product.getProductId()); newProductCatalogue.addProduct(newProduct); } productCatalogues.add(newProductCatalogue); + LOGGER.info("\nLoaded Catalogue: \n" + newProductCatalogue.toString()); } } } diff --git a/src/main/java/de/rwu/easydrop/service/retriever/OfferRetriever.java b/src/main/java/de/rwu/easydrop/service/retriever/OfferRetriever.java index 5488b29..4cef58d 100644 --- a/src/main/java/de/rwu/easydrop/service/retriever/OfferRetriever.java +++ b/src/main/java/de/rwu/easydrop/service/retriever/OfferRetriever.java @@ -1,5 +1,40 @@ package de.rwu.easydrop.service.retriever; -public class OfferRetriever { +import de.rwu.easydrop.api.dto.OfferDTO; +import de.rwu.easydrop.data.connector.OfferPersistenceInterface; +import de.rwu.easydrop.model.Offer; +import de.rwu.easydrop.service.mapping.OfferMapper; +/** + * Retrieves offer information from different sources. + * + * @since 0.3.0 + */ +public class OfferRetriever { + /** + * Persistence interface. + */ + private OfferPersistenceInterface persistence; + + /** + * Creates an Offer Retriever. + * + * @param db Persistence Interface + */ + public OfferRetriever(final OfferPersistenceInterface db) { + this.persistence = db; + } + + /** + * Retrieves an offer from persistence. + * + * @param offerId + * @return Offer from persistence + */ + public Offer getOfferFromPersistence(final String offerId) { + OfferPersistenceInterface src = persistence; + + OfferDTO dto = src.getOfferDTOById(offerId); + return OfferMapper.mapOfferFromDTO(dto); + } } diff --git a/src/main/java/de/rwu/easydrop/service/retriever/ProductRetriever.java b/src/main/java/de/rwu/easydrop/service/retriever/ProductRetriever.java index ddbe4b1..cd5cb30 100644 --- a/src/main/java/de/rwu/easydrop/service/retriever/ProductRetriever.java +++ b/src/main/java/de/rwu/easydrop/service/retriever/ProductRetriever.java @@ -4,7 +4,7 @@ import de.rwu.easydrop.api.client.AmazonProductDataSource; import de.rwu.easydrop.api.client.DataSourceFactory; import de.rwu.easydrop.api.client.EbayItemDataSource; import de.rwu.easydrop.api.dto.ProductDTO; -import de.rwu.easydrop.data.connector.AbstractProductPersistence; +import de.rwu.easydrop.data.connector.ProductPersistenceInterface; import de.rwu.easydrop.model.Product; import de.rwu.easydrop.model.Webshop; import de.rwu.easydrop.service.mapping.ProductMapper; @@ -20,19 +20,20 @@ public class ProductRetriever { * Data source factory. */ private DataSourceFactory dataSourceFactory; - /** - * @param newDataSourceFactory the WebshopFactory to set + * Persistence interface. */ - public void setWebshopFactory(final DataSourceFactory newDataSourceFactory) { - this.dataSourceFactory = newDataSourceFactory; - } + private ProductPersistenceInterface persistence; /** * @param newDataSourceFactory + * @param newPersistence */ - public ProductRetriever(final DataSourceFactory newDataSourceFactory) { - this.setWebshopFactory(newDataSourceFactory); + public ProductRetriever( + final DataSourceFactory newDataSourceFactory, + final ProductPersistenceInterface newPersistence) { + this.dataSourceFactory = newDataSourceFactory; + this.persistence = newPersistence; } /** @@ -74,9 +75,7 @@ public class ProductRetriever { * @return Product from persistence */ public Product getProductFromPersistence(final String productId) { - AbstractProductPersistence src = dataSourceFactory.createProductPersistenceDataSource(); - - ProductDTO dto = src.getProductDTOById(productId); + ProductDTO dto = persistence.getProductDTOById(productId); Product product = ProductMapper.mapProductFromDTO(dto); ProductValidator.validate(product); diff --git a/src/main/java/de/rwu/easydrop/service/validation/OfferValidator.java b/src/main/java/de/rwu/easydrop/service/validation/OfferValidator.java index c3f2257..82fbd89 100644 --- a/src/main/java/de/rwu/easydrop/service/validation/OfferValidator.java +++ b/src/main/java/de/rwu/easydrop/service/validation/OfferValidator.java @@ -1,5 +1,6 @@ package de.rwu.easydrop.service.validation; +import de.rwu.easydrop.exception.InvalidOfferException; import de.rwu.easydrop.model.Offer; /** @@ -8,7 +9,7 @@ import de.rwu.easydrop.model.Offer; * @since 0.2.0 */ public final class OfferValidator { - /** + /** * Private constructor to prevent unwanted instantiation. * * @throws UnsupportedOperationException always @@ -16,13 +17,19 @@ public final class OfferValidator { private OfferValidator() throws UnsupportedOperationException { throw new UnsupportedOperationException("This is a validator class, don't instantiate it."); } - /** + + /** * Makes sure an Offer does not contain invalid information. * * @param offer the Offer */ - public static void validate(final Offer offer) { } + public static void validate(final Offer offer) { + try { + if (offer.getOfferId().equals("")) { + throw new InvalidOfferException("Offer ID cannot be empty"); + } + } catch (NullPointerException e) { + throw new InvalidOfferException("Required information is missing in the offer", e); + } + } } - - - diff --git a/src/main/java/de/rwu/easydrop/service/writer/CatalogueWriter.java b/src/main/java/de/rwu/easydrop/service/writer/CatalogueWriter.java index a1cf486..c243f60 100644 --- a/src/main/java/de/rwu/easydrop/service/writer/CatalogueWriter.java +++ b/src/main/java/de/rwu/easydrop/service/writer/CatalogueWriter.java @@ -3,7 +3,7 @@ package de.rwu.easydrop.service.writer; import java.util.List; import de.rwu.easydrop.api.dto.ProductDTO; -import de.rwu.easydrop.data.connector.AbstractProductPersistence; +import de.rwu.easydrop.data.connector.ProductPersistenceInterface; import de.rwu.easydrop.model.Product; import de.rwu.easydrop.model.ProductCatalogue; import de.rwu.easydrop.service.mapping.ProductMapper; @@ -18,14 +18,14 @@ public final class CatalogueWriter { /** * Holds a persistence reference. */ - private AbstractProductPersistence persistence; + private ProductPersistenceInterface persistence; /** * Creates new instance. * * @param newPersistence */ - public CatalogueWriter(final AbstractProductPersistence newPersistence) { + public CatalogueWriter(final ProductPersistenceInterface newPersistence) { persistence = newPersistence; } @@ -40,7 +40,7 @@ public final class CatalogueWriter { ProductValidator.validate(product); ProductDTO dto = ProductMapper.mapProductToDTO(product); - persistence.saveProduct(dto); + persistence.writeProduct(dto); } } } diff --git a/src/main/java/de/rwu/easydrop/service/writer/OfferWriter.java b/src/main/java/de/rwu/easydrop/service/writer/OfferWriter.java index 6ba6a4c..ba43912 100644 --- a/src/main/java/de/rwu/easydrop/service/writer/OfferWriter.java +++ b/src/main/java/de/rwu/easydrop/service/writer/OfferWriter.java @@ -1,21 +1,20 @@ package de.rwu.easydrop.service.writer; import de.rwu.easydrop.api.dto.OfferDTO; -import de.rwu.easydrop.data.connector.AbstractOfferPersistence; +import de.rwu.easydrop.data.connector.OfferPersistenceInterface; import de.rwu.easydrop.model.Offer; import de.rwu.easydrop.service.mapping.OfferMapper; -import de.rwu.easydrop.service.validation.OfferValidator; public class OfferWriter { /** * Persistence. */ - private AbstractOfferPersistence persistence; + private OfferPersistenceInterface persistence; /** * @param newPersistence the persistence to set */ - public void setPersistence(final AbstractOfferPersistence newPersistence) { + public OfferWriter(final OfferPersistenceInterface newPersistence) { this.persistence = newPersistence; } @@ -25,9 +24,8 @@ public class OfferWriter { * @param offer */ public void writeOfferToPersistence(final Offer offer) { - OfferValidator.validate(offer); OfferDTO dto = OfferMapper.mapOfferToDTO(offer); - persistence.saveOffer(dto); + persistence.writeOffer(dto); } } diff --git a/src/main/java/de/rwu/easydrop/service/writer/ProductWriter.java b/src/main/java/de/rwu/easydrop/service/writer/ProductWriter.java index d1be850..79d8114 100644 --- a/src/main/java/de/rwu/easydrop/service/writer/ProductWriter.java +++ b/src/main/java/de/rwu/easydrop/service/writer/ProductWriter.java @@ -1,7 +1,7 @@ package de.rwu.easydrop.service.writer; import de.rwu.easydrop.api.dto.ProductDTO; -import de.rwu.easydrop.data.connector.AbstractProductPersistence; +import de.rwu.easydrop.data.connector.ProductPersistenceInterface; import de.rwu.easydrop.model.Product; import de.rwu.easydrop.service.mapping.ProductMapper; import de.rwu.easydrop.service.validation.ProductValidator; @@ -15,12 +15,12 @@ public class ProductWriter { /** * Persistence. */ - private AbstractProductPersistence persistence; + private ProductPersistenceInterface persistence; /** * @param newPersistence the persistence to set */ - public void setPersistence(final AbstractProductPersistence newPersistence) { + public ProductWriter(final ProductPersistenceInterface newPersistence) { this.persistence = newPersistence; } @@ -33,6 +33,6 @@ public class ProductWriter { ProductValidator.validate(product); ProductDTO dto = ProductMapper.mapProductToDTO(product); - persistence.saveProduct(dto); + persistence.writeProduct(dto); } } diff --git a/src/main/java/de/rwu/easydrop/util/FormattingUtil.java b/src/main/java/de/rwu/easydrop/util/FormattingUtil.java index e8ea662..544e729 100644 --- a/src/main/java/de/rwu/easydrop/util/FormattingUtil.java +++ b/src/main/java/de/rwu/easydrop/util/FormattingUtil.java @@ -37,4 +37,14 @@ public final class FormattingUtil { public static String urlEncode(final String str) { return str.replace(" ", "+"); } + + /** + * Removes spaces from target string. + * + * @param str String + * @return Space-less string + */ + public static String removeSpaces(final String str) { + return str.replace(" ", ""); + } } diff --git a/src/main/java/de/rwu/easydrop/util/Timestamp.java b/src/main/java/de/rwu/easydrop/util/Timestamp.java new file mode 100644 index 0000000..a087982 --- /dev/null +++ b/src/main/java/de/rwu/easydrop/util/Timestamp.java @@ -0,0 +1,29 @@ +package de.rwu.easydrop.util; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +/** + * Serves as a timestamp source. + * + * @since 0.3.0 + */ +public abstract class Timestamp { + /** + * Hidden constructor. + */ + private Timestamp() { + // Don't instantiate me! + } + + /** + * Returns a formatted time string. + * + * @return String such as "2023-01-01 00:00:00" + */ + public static String now() { + LocalDateTime now = LocalDateTime.now(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + return now.format(formatter); + } +}