Connected application components
This commit is contained in:
@@ -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<ProductCatalogue> pCats = catRetriever.getProductCatalogues();
|
||||
catWriter.writeCatalogues(pCats);
|
||||
|
||||
Core core = new Core();
|
||||
core.runCore(pCats);
|
||||
Core.run();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,11 @@ public class ProductDTO {
|
||||
*/
|
||||
private boolean available;
|
||||
|
||||
/**
|
||||
* Last update from API.
|
||||
*/
|
||||
private String lastUpdate;
|
||||
|
||||
/**
|
||||
* Creates ProductDTO instance.
|
||||
*
|
||||
|
||||
@@ -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<ProductCatalogue> 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<ProductCatalogue> pCats = catRetriever.getProductCatalogues();
|
||||
catWriter.writeCatalogues(pCats);
|
||||
|
||||
LOGGER.info("Creating offers");
|
||||
OfferIdentifier ident = new OfferIdentifier();
|
||||
List<Offer> identifiedOffers = ident.runIdentifier(pCats);
|
||||
OfferProvisioner provis = new OfferProvisioner(odb);
|
||||
provis.runProvisioner(identifiedOffers);
|
||||
|
||||
// LOGGER.info("Creating transactions");
|
||||
// TODO: Transactions
|
||||
|
||||
LOGGER.info("Done!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Offer> runIdentifier(final List<ProductCatalogue> pCats) {
|
||||
List<Offer> 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<Offer> newOffers = new ArrayList<>();
|
||||
for (Offer identifiedOffer : identifiedOffers) {
|
||||
boolean isNew = true;
|
||||
if (isNew) {
|
||||
newOffers.add(identifiedOffer);
|
||||
}
|
||||
}
|
||||
return newOffers;
|
||||
}
|
||||
}
|
||||
@@ -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<Offer> checkOffer(/*OfferReader/retriever for database? */) {
|
||||
|
||||
Connection connection = null;
|
||||
Statement statement = null;
|
||||
ResultSet resultSet = null;
|
||||
List<Offer> 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<Offer>();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -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<Offer> changedOffers = offerReviewer.checkOffer();
|
||||
}
|
||||
|
||||
/**
|
||||
* A.
|
||||
* @param offersToUpdate
|
||||
*/
|
||||
public void runUpdater(final List<Offer> 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<Product> 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
try (Connection connection = db.getConnection();
|
||||
PreparedStatement statement = connection.prepareStatement(query)) {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ProductDTO buildProductDTO(final ProductDTO product, final String json) {
|
||||
throw new UnsupportedOperationException(
|
||||
this.getClass().getName() + " doesn't support buildProductDTO");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected URL createApiUrl(final String productIdentifier) {
|
||||
throw new UnsupportedOperationException(
|
||||
this.getClass().getName() + " doesn't support createApiUrl");
|
||||
return dto;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,11 @@ public class Product {
|
||||
*/
|
||||
private boolean available;
|
||||
|
||||
/**
|
||||
* Last update from API.
|
||||
*/
|
||||
private String lastUpdate;
|
||||
|
||||
@Override
|
||||
public final String toString() {
|
||||
return "Product: ["
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 class OfferIdentifier {
|
||||
/**
|
||||
* Logging instance.
|
||||
*/
|
||||
public final class OrderManager {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(OfferIdentifier.class);
|
||||
|
||||
/**
|
||||
* Temporary logging instance.
|
||||
*/
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(OrderManager.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<ProductCatalogue> pCats) {
|
||||
public List<Offer> runIdentifier(final List<ProductCatalogue> pCats) {
|
||||
List<Offer> 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);
|
||||
@@ -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<Offer> 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 {
|
||||
newOffer.setOfferId(newOfferId);
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package de.rwu.easydrop.service.validation;
|
||||
|
||||
import de.rwu.easydrop.exception.InvalidOfferException;
|
||||
import de.rwu.easydrop.model.Offer;
|
||||
|
||||
/**
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(" ", "");
|
||||
}
|
||||
}
|
||||
|
||||
29
src/main/java/de/rwu/easydrop/util/Timestamp.java
Normal file
29
src/main/java/de/rwu/easydrop/util/Timestamp.java
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user