Merge branch 'dev' into 'main'
Release 1.0.0 See merge request team1/sandbox2!12
This commit is contained in:
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -4,5 +4,6 @@
|
|||||||
"connectionId": "LocalSonarQube",
|
"connectionId": "LocalSonarQube",
|
||||||
"projectKey": "EasyDrop"
|
"projectKey": "EasyDrop"
|
||||||
},
|
},
|
||||||
"java.debug.settings.onBuildFailureProceed": true
|
"java.debug.settings.onBuildFailureProceed": true,
|
||||||
|
"java.checkstyle.configuration": "${workspaceFolder}\\config\\custom-checkstyle.xml"
|
||||||
}
|
}
|
||||||
|
|||||||
12
CHANGELOG.md
12
CHANGELOG.md
@@ -1,14 +1,18 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## 0.3.0-SNAPSHOT
|
## 1.0.0
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added script for local UML generation (#56)
|
- Script for local UML generation (#56)
|
||||||
|
- Transaction fulfillment API classes (#71)
|
||||||
|
- Offer handling classes (#12, #64, #70)
|
||||||
|
- Transaction handling classes (#75)
|
||||||
|
- Dockerfile and `docker-compose.yml` (#73)
|
||||||
|
|
||||||
### Removed
|
### Changed
|
||||||
|
|
||||||
- Document stage from CI run (#56)
|
- Webshops are now handled via enum instead of being hard-coded
|
||||||
|
|
||||||
## 0.2.0
|
## 0.2.0
|
||||||
|
|
||||||
|
|||||||
28
Dockerfile
Normal file
28
Dockerfile
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# Use the official maven/Java 17 image to create a build artifact.
|
||||||
|
# https://hub.docker.com/_/maven
|
||||||
|
FROM maven:3.9.1-eclipse-temurin-17 AS build
|
||||||
|
|
||||||
|
# Set the working directory in the image to /app
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy the pom.xml file into the current directory (/app) in the image
|
||||||
|
COPY pom.xml .
|
||||||
|
|
||||||
|
# Download all required dependencies into one layer
|
||||||
|
RUN mvn -B dependency:go-offline
|
||||||
|
|
||||||
|
# Copy the rest of the application source code
|
||||||
|
COPY src /app/src
|
||||||
|
|
||||||
|
# Build the application
|
||||||
|
RUN mvn -B package -DskipTests
|
||||||
|
|
||||||
|
# Use OpenJDK 17 for the runtime stage of the Dockerfile
|
||||||
|
FROM openjdk:17-jdk-slim
|
||||||
|
|
||||||
|
# Copy the jar file from the build stage
|
||||||
|
COPY --from=build /app/target/easydrop-1.0.0.jar /easydrop.jar
|
||||||
|
|
||||||
|
# Execute the application when the docker container starts.
|
||||||
|
ENTRYPOINT ["java", "-jar", "/easydrop.jar"]
|
||||||
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 76 KiB |
31
README.md
31
README.md
@@ -1,6 +1,6 @@
|
|||||||
# EasyDrop
|
# EasyDrop
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||
[](https://sonar.fbe-adswen.rwu.de/dashboard?id=de.rwu%3Aeasydrop)
|
[](https://sonar.fbe-adswen.rwu.de/dashboard?id=de.rwu%3Aeasydrop)
|
||||||

|

|
||||||
@@ -13,30 +13,33 @@ Get rich quick™ with fully automated dropshipping!
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Installation ⚙
|
## Installation/Usage ⚙
|
||||||
|
|
||||||
As the application is still in development, development software will be required along its regular execution environment.
|
- Install Docker + Compose
|
||||||
|
- Clone this repository
|
||||||
- JDK 17
|
|
||||||
- Maven
|
|
||||||
- _[More/context](https://gitlab.fbe-adswen.rwu.de/team1/sandbox2/-/wikis/Projektdokumentation/Development#software)_
|
|
||||||
|
|
||||||
## Usage 🛠
|
|
||||||
|
|
||||||
Set up the required configuration files, use the corresponding demo files for orientation.
|
Set up the required configuration files, use the corresponding demo files for orientation.
|
||||||
|
|
||||||
- `config/config.properties` for API authorization
|
- `config/config.properties` for API authorization
|
||||||
- `products-config.json` to define product catalogues to use for dropshipping
|
- `products-config.json` to define product catalogues to use for dropshipping
|
||||||
|
|
||||||
Run the following command to execute the program:
|
Create the container
|
||||||
|
|
||||||
```sh
|
```bash
|
||||||
mvn compile exec:java -Dexec.mainClass="de.rwu.easydrop.Main"
|
docker-compose build
|
||||||
```
|
```
|
||||||
|
|
||||||
## Roadmap 🏁
|
Then run it!
|
||||||
|
|
||||||
_Future ideas!_
|
```bash
|
||||||
|
docker-compose up
|
||||||
|
```
|
||||||
|
|
||||||
|
To run it on a fixed schedule, install a cron job, e.g.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
*/30 * * * * cd /home/user/easydrop && docker-compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
## Contributing 👷♂️👷♀️
|
## Contributing 👷♂️👷♀️
|
||||||
|
|
||||||
|
|||||||
23
Script/Bump_Version.sh
Normal file
23
Script/Bump_Version.sh
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Checking if correct number of arguments are provided
|
||||||
|
if [ "$#" -ne 2 ]; then
|
||||||
|
echo "Required CLI args missing: [old_version, new_version]"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Assigning command line arguments to variables
|
||||||
|
old_version="$1"
|
||||||
|
new_version="$2"
|
||||||
|
|
||||||
|
old_version_alt=${old_version//-/–}
|
||||||
|
new_version_alt=${new_version//-/–}
|
||||||
|
|
||||||
|
# Replacing old_version with new_version in README.md
|
||||||
|
sed -i "s/version-$old_version_alt-orange/version-$new_version_alt-orange/g" README.md
|
||||||
|
sed -i "s/<version>$old_version/<version>$new_version/g" pom.xml
|
||||||
|
sed -i "s/easydrop-$old_version.jar/easydrop-$new_version.jar/g" Dockerfile
|
||||||
|
sed -i "s/image: easydrop:$old_version/image: easydrop:$new_version/g" docker-compose.yml
|
||||||
|
|
||||||
|
echo "Version number updated successfully"
|
||||||
|
|
||||||
@@ -2,6 +2,5 @@ mvn clean verify sonar:sonar -Pcoverage \
|
|||||||
-Dsonar.projectKey=EasyDrop \
|
-Dsonar.projectKey=EasyDrop \
|
||||||
-Dsonar.projectName='EasyDrop' \
|
-Dsonar.projectName='EasyDrop' \
|
||||||
-Dsonar.host.url=http://localhost:9000 \
|
-Dsonar.host.url=http://localhost:9000 \
|
||||||
-Dsonar.token=sqp_82d35689c620c15fd1064549375e17a2a5b0b931
|
-Dsonar.token=sqp_82d35689c620c15fd1064549375e17a2a5b0b931 \
|
||||||
|
&& start http://localhost:9000/dashboard?id=EasyDrop
|
||||||
start http://localhost:9000/dashboard?id=EasyDrop
|
|
||||||
@@ -44,6 +44,11 @@ https://www.oracle.com/java/technologies/javase/codeconventions-contents.html
|
|||||||
|
|
||||||
<property name="fileExtensions" value="java, properties, xml" />
|
<property name="fileExtensions" value="java, properties, xml" />
|
||||||
|
|
||||||
|
<module name="SuppressionFilter">
|
||||||
|
<property name="file" value="config/suppressions.xml" />
|
||||||
|
<property name="optional" value="false" />
|
||||||
|
</module>
|
||||||
|
|
||||||
<!-- Excludes all 'module-info.java' files -->
|
<!-- Excludes all 'module-info.java' files -->
|
||||||
<!-- See https://checkstyle.org/config_filefilters.html -->
|
<!-- See https://checkstyle.org/config_filefilters.html -->
|
||||||
<module name="BeforeExecutionExclusionFileFilter">
|
<module name="BeforeExecutionExclusionFileFilter">
|
||||||
|
|||||||
@@ -3,3 +3,4 @@ AMAZON_API_URL=
|
|||||||
AMAZON_API_KEY=
|
AMAZON_API_KEY=
|
||||||
EBAY_API_URL=
|
EBAY_API_URL=
|
||||||
EBAY_API_KEY=
|
EBAY_API_KEY=
|
||||||
|
WEBSHOPS=amazon,ebay
|
||||||
@@ -5,10 +5,34 @@
|
|||||||
"description": "Very epic GPU",
|
"description": "Very epic GPU",
|
||||||
"identifiers": [
|
"identifiers": [
|
||||||
{
|
{
|
||||||
"Amazon": "B096Y2TYKV"
|
"AMAZON": "B096Y2TYKV"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"eBay": "Gigabyte GeForce RTX 3060"
|
"EBAY": "Gigabyte GeForce RTX 3060"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Gigabyte Radeon RX 6700 XT",
|
||||||
|
"description": "Another one",
|
||||||
|
"identifiers": [
|
||||||
|
{
|
||||||
|
"AMAZON": "B08Y758F6C"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"EBAY": "Gigabyte Radeon RX 6700 XT"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "NVIDIA GeForce RTX 4060 Ti",
|
||||||
|
"description": "Premium!",
|
||||||
|
"identifiers": [
|
||||||
|
{
|
||||||
|
"AMAZON": "B0C4F9HCF6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"EBAY": "NVIDIA GeForce RTX 4060 Ti"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
6
config/suppressions.xml
Normal file
6
config/suppressions.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<!DOCTYPE suppressions PUBLIC "-//Checkstyle//DTD SuppressionFilter Configuration 1.2//EN" "https://checkstyle.org/dtds/suppressions_1_2.dtd">
|
||||||
|
|
||||||
|
<suppressions>
|
||||||
|
<suppress checks=".*" files=".*[\\/]src[\\/](test)[\\/]" />
|
||||||
|
</suppressions>
|
||||||
12
docker-compose.yml
Normal file
12
docker-compose.yml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
version: "3.8"
|
||||||
|
|
||||||
|
services:
|
||||||
|
easydrop:
|
||||||
|
container_name: easydrop
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
image: easydrop:1.0.0
|
||||||
|
volumes:
|
||||||
|
- ./config:/config
|
||||||
|
- ./persistence.db:/persistence.db
|
||||||
23
pom.xml
23
pom.xml
@@ -5,7 +5,7 @@
|
|||||||
<groupId>de.rwu</groupId>
|
<groupId>de.rwu</groupId>
|
||||||
<artifactId>easydrop</artifactId>
|
<artifactId>easydrop</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<version>0.3.0-SNAPSHOT</version>
|
<version>1.0.0</version>
|
||||||
<name>EasyDrop</name>
|
<name>EasyDrop</name>
|
||||||
<url>http://maven.apache.org</url>
|
<url>http://maven.apache.org</url>
|
||||||
|
|
||||||
@@ -86,6 +86,27 @@
|
|||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
<version>3.2.4</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>shade</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<transformers>
|
||||||
|
<transformer
|
||||||
|
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||||
|
<mainClass>de.rwu.easydrop.Main</mainClass>
|
||||||
|
</transformer>
|
||||||
|
</transformers>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||||
|
|||||||
@@ -1,22 +1,8 @@
|
|||||||
package de.rwu.easydrop;
|
package de.rwu.easydrop;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.naming.ConfigurationException;
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import de.rwu.easydrop.core.Core;
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.sqlite.SQLiteDataSource;
|
|
||||||
|
|
||||||
import de.rwu.easydrop.api.client.DataSourceFactory;
|
|
||||||
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.
|
* Kickoff point for the service.
|
||||||
@@ -24,11 +10,6 @@ import de.rwu.easydrop.util.ProductsConfig;
|
|||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
public final class Main {
|
public final class Main {
|
||||||
/**
|
|
||||||
* Logger for main process.
|
|
||||||
*/
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(Main.class);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prevents unwanted instantiation.
|
* Prevents unwanted instantiation.
|
||||||
*/
|
*/
|
||||||
@@ -42,21 +23,6 @@ public final class Main {
|
|||||||
* @param args
|
* @param args
|
||||||
*/
|
*/
|
||||||
public static void main(final String[] args) throws ConfigurationException {
|
public static void main(final String[] args) throws ConfigurationException {
|
||||||
Config config = Config.getInstance();
|
Core.run();
|
||||||
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);
|
|
||||||
|
|
||||||
for (ProductCatalogue pCat : pCats) {
|
|
||||||
String pCatStr = pCat.toString();
|
|
||||||
LOGGER.info(pCatStr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import java.net.URL;
|
|||||||
|
|
||||||
import de.rwu.easydrop.api.dto.ProductDTO;
|
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||||
import de.rwu.easydrop.exception.DataSourceException;
|
import de.rwu.easydrop.exception.DataSourceException;
|
||||||
|
import de.rwu.easydrop.model.Webshop;
|
||||||
import de.rwu.easydrop.util.FormattingUtil;
|
import de.rwu.easydrop.util.FormattingUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -23,7 +24,7 @@ public abstract class AbstractDataSource implements DataSource {
|
|||||||
*
|
*
|
||||||
* @return Data source name
|
* @return Data source name
|
||||||
*/
|
*/
|
||||||
protected abstract String getDataOrigin();
|
protected abstract Webshop getDataOrigin();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the data source's API key.
|
* Returns the data source's API key.
|
||||||
@@ -42,13 +43,13 @@ public abstract class AbstractDataSource implements DataSource {
|
|||||||
protected abstract ProductDTO buildProductDTO(ProductDTO product, String json);
|
protected abstract ProductDTO buildProductDTO(ProductDTO product, String json);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overridable standard implementation.
|
* Pulls product data from a remote data source.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ProductDTO getProductDTOById(final String productIdentifier)
|
public ProductDTO getProductDTOById(final String productIdentifier)
|
||||||
throws IllegalArgumentException {
|
throws IllegalArgumentException {
|
||||||
StringBuilder response = new StringBuilder();
|
StringBuilder response = new StringBuilder();
|
||||||
String dataOrigin = getDataOrigin();
|
Webshop dataOrigin = getDataOrigin();
|
||||||
String apiKey = getApiKey();
|
String apiKey = getApiKey();
|
||||||
ProductDTO product = new ProductDTO(productIdentifier, dataOrigin);
|
ProductDTO product = new ProductDTO(productIdentifier, dataOrigin);
|
||||||
|
|
||||||
@@ -78,7 +79,13 @@ public abstract class AbstractDataSource implements DataSource {
|
|||||||
}
|
}
|
||||||
reader.close();
|
reader.close();
|
||||||
|
|
||||||
buildProductDTO(product, response.toString());
|
String data;
|
||||||
|
if (response.toString().isEmpty()) {
|
||||||
|
data = "{}";
|
||||||
|
} else {
|
||||||
|
data = response.toString();
|
||||||
|
}
|
||||||
|
buildProductDTO(product, data);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new DataSourceException(
|
throw new DataSourceException(
|
||||||
"Couldn't fulfill "
|
"Couldn't fulfill "
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
package de.rwu.easydrop.api.client;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||||
|
import de.rwu.easydrop.exception.DataWriterException;
|
||||||
|
import de.rwu.easydrop.model.Webshop;
|
||||||
|
import de.rwu.easydrop.util.FormattingUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes data to a remote API.
|
||||||
|
*
|
||||||
|
* @since 0.3.0
|
||||||
|
*/
|
||||||
|
public abstract class AbstractDataWriter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the data source's API key.
|
||||||
|
*
|
||||||
|
* @return Data source API key
|
||||||
|
*/
|
||||||
|
protected abstract String getApiKey();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the target API's name.
|
||||||
|
*
|
||||||
|
* @return Data target API name
|
||||||
|
*/
|
||||||
|
protected abstract Webshop getDataTarget();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an URL object to connect to the API with.
|
||||||
|
*
|
||||||
|
* @param productIdentifier Product identifier
|
||||||
|
* @return URL object
|
||||||
|
* @throws MalformedURLException
|
||||||
|
*/
|
||||||
|
protected abstract URL createApiUrl(String productIdentifier) throws MalformedURLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a put request to the API.
|
||||||
|
*
|
||||||
|
* @param dto Product data transfer object
|
||||||
|
* @param apiType API Type, like Purchase or Sales
|
||||||
|
*/
|
||||||
|
protected void sendPutRequest(final ProductDTO dto, final String apiType) {
|
||||||
|
String apiKey = getApiKey();
|
||||||
|
Webshop dataTarget = getDataTarget();
|
||||||
|
|
||||||
|
if (!dataTarget.equals(dto.getDataOrigin())) {
|
||||||
|
throw new DataWriterException(
|
||||||
|
"Product data source and target " + apiType + " API are incompatible.");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
String urlReadyIdentifier = FormattingUtil.urlEncode(dto.getProductId());
|
||||||
|
URL apiUrl = createApiUrl(urlReadyIdentifier);
|
||||||
|
|
||||||
|
HttpURLConnection connection = (HttpURLConnection) apiUrl.openConnection();
|
||||||
|
connection.setRequestMethod("PUT");
|
||||||
|
connection.setRequestProperty("Credential", apiKey);
|
||||||
|
|
||||||
|
int responseCode = connection.getResponseCode();
|
||||||
|
if (responseCode != HttpURLConnection.HTTP_OK) {
|
||||||
|
throw new DataWriterException(
|
||||||
|
dataTarget
|
||||||
|
+ " "
|
||||||
|
+ apiType
|
||||||
|
+ " API responded with error code "
|
||||||
|
+ responseCode);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new DataWriterException(
|
||||||
|
"Couldn't fulfill "
|
||||||
|
+ dataTarget
|
||||||
|
+ " API request");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package de.rwu.easydrop.api.client;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract construct to provide access to a purchase API.
|
||||||
|
*
|
||||||
|
* @since 0.3.0
|
||||||
|
*/
|
||||||
|
public abstract class AbstractPurchaser extends AbstractDataWriter {
|
||||||
|
/**
|
||||||
|
* Sends a buy request to the Amazon API.
|
||||||
|
*
|
||||||
|
* @param dto
|
||||||
|
*/
|
||||||
|
public void purchaseProduct(final ProductDTO dto) {
|
||||||
|
sendPutRequest(dto, "Purchase");
|
||||||
|
}
|
||||||
|
}
|
||||||
19
src/main/java/de/rwu/easydrop/api/client/AbstractSeller.java
Normal file
19
src/main/java/de/rwu/easydrop/api/client/AbstractSeller.java
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package de.rwu.easydrop.api.client;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract construct to provide access to a sales API.
|
||||||
|
*
|
||||||
|
* @since 0.3.0
|
||||||
|
*/
|
||||||
|
public abstract class AbstractSeller extends AbstractDataWriter {
|
||||||
|
/**
|
||||||
|
* Sends a sell request to the Amazon API.
|
||||||
|
*
|
||||||
|
* @param dto
|
||||||
|
*/
|
||||||
|
public void sellProduct(final ProductDTO dto) {
|
||||||
|
sendPutRequest(dto, "Sales");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,6 +8,8 @@ import com.jayway.jsonpath.PathNotFoundException;
|
|||||||
import com.jayway.jsonpath.ReadContext;
|
import com.jayway.jsonpath.ReadContext;
|
||||||
|
|
||||||
import de.rwu.easydrop.api.dto.ProductDTO;
|
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.
|
* Interface to an Amazon data source.
|
||||||
@@ -18,7 +20,7 @@ public final class AmazonProductDataSource extends AbstractDataSource {
|
|||||||
/**
|
/**
|
||||||
* Name of this data source.
|
* Name of this data source.
|
||||||
*/
|
*/
|
||||||
private static final String DATA_ORIGIN = "Amazon";
|
private static final Webshop DATA_ORIGIN = Webshop.AMAZON;
|
||||||
/**
|
/**
|
||||||
* Base URL to the Amazon data source.
|
* Base URL to the Amazon data source.
|
||||||
*/
|
*/
|
||||||
@@ -60,6 +62,7 @@ public final class AmazonProductDataSource extends AbstractDataSource {
|
|||||||
product.setDeliveryPrice(
|
product.setDeliveryPrice(
|
||||||
ctx.read(root + "shippingOptions[0].shippingCost.value.amount", double.class));
|
ctx.read(root + "shippingOptions[0].shippingCost.value.amount", double.class));
|
||||||
product.setMerchant(ctx.read(root + "merchant.name", String.class));
|
product.setMerchant(ctx.read(root + "merchant.name", String.class));
|
||||||
|
product.setLastUpdate(Timestamp.now());
|
||||||
} catch (PathNotFoundException e) {
|
} catch (PathNotFoundException e) {
|
||||||
// Pass, allow incomplete ProductDTO to pass for later validation
|
// Pass, allow incomplete ProductDTO to pass for later validation
|
||||||
}
|
}
|
||||||
@@ -82,7 +85,7 @@ public final class AmazonProductDataSource extends AbstractDataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getDataOrigin() {
|
protected Webshop getDataOrigin() {
|
||||||
return DATA_ORIGIN;
|
return DATA_ORIGIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
package de.rwu.easydrop.api.client;
|
||||||
|
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.model.Webshop;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a buy request to the Amazon API.
|
||||||
|
*
|
||||||
|
* @since 0.3.0
|
||||||
|
*/
|
||||||
|
public final class AmazonPurchaser extends AbstractPurchaser {
|
||||||
|
/**
|
||||||
|
* Name of this data source.
|
||||||
|
*/
|
||||||
|
private static final Webshop DATA_TARGET = Webshop.AMAZON;
|
||||||
|
/**
|
||||||
|
* Base URL to the Amazon Purchase API.
|
||||||
|
*/
|
||||||
|
private String baseUrl;
|
||||||
|
/**
|
||||||
|
* Access credential.
|
||||||
|
*/
|
||||||
|
private String apiKey;
|
||||||
|
/**
|
||||||
|
* Product region parameter required for data writes.
|
||||||
|
*/
|
||||||
|
private static final String PRODUCT_REGION = "DE";
|
||||||
|
/**
|
||||||
|
* Locale parameter required for data writes.
|
||||||
|
*/
|
||||||
|
private static final String LOCALE = "de_DE";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up instance with Base URL and API Key.
|
||||||
|
*
|
||||||
|
* @param newBaseUrl
|
||||||
|
* @param newApiKey
|
||||||
|
*/
|
||||||
|
public AmazonPurchaser(final String newBaseUrl, final String newApiKey) {
|
||||||
|
this.baseUrl = newBaseUrl;
|
||||||
|
this.apiKey = newApiKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param productId ASIN
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected URL createApiUrl(final String productId) throws MalformedURLException {
|
||||||
|
return new URL(baseUrl
|
||||||
|
+ "/products/2020-08-26/products/"
|
||||||
|
+ productId
|
||||||
|
+ "/buy?productRegion="
|
||||||
|
+ PRODUCT_REGION
|
||||||
|
+ "&locale="
|
||||||
|
+ LOCALE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getApiKey() {
|
||||||
|
return this.apiKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Webshop getDataTarget() {
|
||||||
|
return DATA_TARGET;
|
||||||
|
}
|
||||||
|
}
|
||||||
69
src/main/java/de/rwu/easydrop/api/client/AmazonSeller.java
Normal file
69
src/main/java/de/rwu/easydrop/api/client/AmazonSeller.java
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
package de.rwu.easydrop.api.client;
|
||||||
|
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.model.Webshop;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a sell request to the Amazon API.
|
||||||
|
*
|
||||||
|
* @since 0.3.0
|
||||||
|
*/
|
||||||
|
public final class AmazonSeller extends AbstractSeller {
|
||||||
|
/**
|
||||||
|
* Name of this data source.
|
||||||
|
*/
|
||||||
|
private static final Webshop DATA_TARGET = Webshop.AMAZON;
|
||||||
|
/**
|
||||||
|
* Base URL to the Amazon Purchase API.
|
||||||
|
*/
|
||||||
|
private String baseUrl;
|
||||||
|
/**
|
||||||
|
* Access credential.
|
||||||
|
*/
|
||||||
|
private String apiKey;
|
||||||
|
/**
|
||||||
|
* Product region parameter required for data writes.
|
||||||
|
*/
|
||||||
|
private static final String PRODUCT_REGION = "DE";
|
||||||
|
/**
|
||||||
|
* Locale parameter required for data writes.
|
||||||
|
*/
|
||||||
|
private static final String LOCALE = "de_DE";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up instance with Base URL and API Key.
|
||||||
|
*
|
||||||
|
* @param newBaseUrl
|
||||||
|
* @param newApiKey
|
||||||
|
*/
|
||||||
|
public AmazonSeller(final String newBaseUrl, final String newApiKey) {
|
||||||
|
this.baseUrl = newBaseUrl;
|
||||||
|
this.apiKey = newApiKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param productId ASIN
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected URL createApiUrl(final String productId) throws MalformedURLException {
|
||||||
|
return new URL(baseUrl
|
||||||
|
+ "/products/2020-08-26/products/"
|
||||||
|
+ productId
|
||||||
|
+ "/sell?productRegion="
|
||||||
|
+ PRODUCT_REGION
|
||||||
|
+ "&locale="
|
||||||
|
+ LOCALE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getApiKey() {
|
||||||
|
return apiKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Webshop getDataTarget() {
|
||||||
|
return DATA_TARGET;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,8 +2,6 @@ package de.rwu.easydrop.api.client;
|
|||||||
|
|
||||||
import javax.naming.ConfigurationException;
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
import de.rwu.easydrop.data.connector.AbstractProductPersistence;
|
|
||||||
import de.rwu.easydrop.exception.PersistenceException;
|
|
||||||
import de.rwu.easydrop.util.Config;
|
import de.rwu.easydrop.util.Config;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -17,17 +15,6 @@ public class DataSourceFactory {
|
|||||||
* The data source config.
|
* The data source config.
|
||||||
*/
|
*/
|
||||||
private Config 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
|
* @param newConfig the config to set
|
||||||
@@ -65,17 +52,4 @@ public class DataSourceFactory {
|
|||||||
String apiKey = config.getProperty("EBAY_API_KEY");
|
String apiKey = config.getProperty("EBAY_API_KEY");
|
||||||
return new EbayItemDataSource(apiUrl, apiKey);
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import com.jayway.jsonpath.PathNotFoundException;
|
|||||||
import com.jayway.jsonpath.ReadContext;
|
import com.jayway.jsonpath.ReadContext;
|
||||||
|
|
||||||
import de.rwu.easydrop.api.dto.ProductDTO;
|
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.
|
* Interface to an eBay data source.
|
||||||
@@ -18,7 +20,7 @@ public final class EbayItemDataSource extends AbstractDataSource {
|
|||||||
/**
|
/**
|
||||||
* Name of this data source.
|
* Name of this data source.
|
||||||
*/
|
*/
|
||||||
private static final String DATA_ORIGIN = "eBay";
|
private static final Webshop DATA_ORIGIN = Webshop.EBAY;
|
||||||
/**
|
/**
|
||||||
* Base URL to the eBay data source.
|
* Base URL to the eBay data source.
|
||||||
*/
|
*/
|
||||||
@@ -69,6 +71,7 @@ public final class EbayItemDataSource extends AbstractDataSource {
|
|||||||
product.setDeliveryPrice(
|
product.setDeliveryPrice(
|
||||||
ctx.read(root + "shippingOptions[0].shippingCost.value", double.class));
|
ctx.read(root + "shippingOptions[0].shippingCost.value", double.class));
|
||||||
product.setMerchant(ctx.read(root + "seller.username", String.class));
|
product.setMerchant(ctx.read(root + "seller.username", String.class));
|
||||||
|
product.setLastUpdate(Timestamp.now());
|
||||||
} catch (PathNotFoundException e) {
|
} catch (PathNotFoundException e) {
|
||||||
// Pass, allow incomplete ProductDTO to pass for later validation
|
// Pass, allow incomplete ProductDTO to pass for later validation
|
||||||
}
|
}
|
||||||
@@ -77,7 +80,7 @@ public final class EbayItemDataSource extends AbstractDataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getDataOrigin() {
|
protected Webshop getDataOrigin() {
|
||||||
return DATA_ORIGIN;
|
return DATA_ORIGIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
54
src/main/java/de/rwu/easydrop/api/client/EbayPurchaser.java
Normal file
54
src/main/java/de/rwu/easydrop/api/client/EbayPurchaser.java
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
package de.rwu.easydrop.api.client;
|
||||||
|
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.model.Webshop;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a buy request to the eBay API.
|
||||||
|
*
|
||||||
|
* @since 0.3.0
|
||||||
|
*/
|
||||||
|
public final class EbayPurchaser extends AbstractPurchaser {
|
||||||
|
/**
|
||||||
|
* Name of this data source.
|
||||||
|
*/
|
||||||
|
private static final Webshop DATA_TARGET = Webshop.EBAY;
|
||||||
|
/**
|
||||||
|
* Base URL to the eBay Purchase API.
|
||||||
|
*/
|
||||||
|
private String baseUrl;
|
||||||
|
/**
|
||||||
|
* Access credential.
|
||||||
|
*/
|
||||||
|
private String apiKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up instance with Base URL and API Key.
|
||||||
|
*
|
||||||
|
* @param newBaseUrl
|
||||||
|
* @param newApiKey
|
||||||
|
*/
|
||||||
|
public EbayPurchaser(final String newBaseUrl, final String newApiKey) {
|
||||||
|
this.baseUrl = newBaseUrl;
|
||||||
|
this.apiKey = newApiKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected URL createApiUrl(final String searchQuery) throws MalformedURLException {
|
||||||
|
return new URL(baseUrl
|
||||||
|
+ "/buy/"
|
||||||
|
+ searchQuery);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getApiKey() {
|
||||||
|
return apiKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Webshop getDataTarget() {
|
||||||
|
return DATA_TARGET;
|
||||||
|
}
|
||||||
|
}
|
||||||
54
src/main/java/de/rwu/easydrop/api/client/EbaySeller.java
Normal file
54
src/main/java/de/rwu/easydrop/api/client/EbaySeller.java
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
package de.rwu.easydrop.api.client;
|
||||||
|
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.model.Webshop;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a sell request to the eBay API.
|
||||||
|
*
|
||||||
|
* @since 0.3.0
|
||||||
|
*/
|
||||||
|
public final class EbaySeller extends AbstractSeller {
|
||||||
|
/**
|
||||||
|
* Name of this data source.
|
||||||
|
*/
|
||||||
|
private static final Webshop DATA_TARGET = Webshop.EBAY;
|
||||||
|
/**
|
||||||
|
* Base URL to the eBay Purchase API.
|
||||||
|
*/
|
||||||
|
private String baseUrl;
|
||||||
|
/**
|
||||||
|
* Access credential.
|
||||||
|
*/
|
||||||
|
private String apiKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up instance with Base URL and API Key.
|
||||||
|
*
|
||||||
|
* @param newBaseUrl
|
||||||
|
* @param newApiKey
|
||||||
|
*/
|
||||||
|
public EbaySeller(final String newBaseUrl, final String newApiKey) {
|
||||||
|
this.baseUrl = newBaseUrl;
|
||||||
|
this.apiKey = newApiKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected URL createApiUrl(final String searchQuery) throws MalformedURLException {
|
||||||
|
return new URL(baseUrl
|
||||||
|
+ "/sell/"
|
||||||
|
+ searchQuery);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getApiKey() {
|
||||||
|
return this.apiKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Webshop getDataTarget() {
|
||||||
|
return DATA_TARGET;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package de.rwu.easydrop.api.client;
|
||||||
|
|
||||||
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.util.Config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory for Buyer API accessors.
|
||||||
|
*
|
||||||
|
* @since 0.3.0
|
||||||
|
*/
|
||||||
|
public class PurchaserFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The data source config.
|
||||||
|
*/
|
||||||
|
private Config config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param newConfig the config to set
|
||||||
|
*/
|
||||||
|
public void setConfig(final Config newConfig) throws ConfigurationException {
|
||||||
|
this.config = newConfig;
|
||||||
|
this.config.loadConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param newConfig
|
||||||
|
*/
|
||||||
|
public PurchaserFactory(final Config newConfig) throws ConfigurationException {
|
||||||
|
this.setConfig(newConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an Amazon purchaser.
|
||||||
|
*
|
||||||
|
* @return AmazonPurchaser
|
||||||
|
*/
|
||||||
|
public AmazonPurchaser createAmazonPurchaser() {
|
||||||
|
String apiUrl = config.getProperty("AMAZON_API_URL");
|
||||||
|
String apiKey = config.getProperty("AMAZON_API_KEY");
|
||||||
|
return new AmazonPurchaser(apiUrl, apiKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an eBay purchaser.
|
||||||
|
*
|
||||||
|
* @return EbayPurchaser
|
||||||
|
*/
|
||||||
|
public EbayPurchaser createEbayPurchaser() {
|
||||||
|
String apiUrl = config.getProperty("EBAY_API_URL");
|
||||||
|
String apiKey = config.getProperty("EBAY_API_KEY");
|
||||||
|
return new EbayPurchaser(apiUrl, apiKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
55
src/main/java/de/rwu/easydrop/api/client/SellerFactory.java
Normal file
55
src/main/java/de/rwu/easydrop/api/client/SellerFactory.java
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
package de.rwu.easydrop.api.client;
|
||||||
|
|
||||||
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.util.Config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory for Sales API accessors.
|
||||||
|
*
|
||||||
|
* @since 0.3.0
|
||||||
|
*/
|
||||||
|
public class SellerFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The data source config.
|
||||||
|
*/
|
||||||
|
private Config config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param newConfig the config to set
|
||||||
|
*/
|
||||||
|
public void setConfig(final Config newConfig) throws ConfigurationException {
|
||||||
|
this.config = newConfig;
|
||||||
|
this.config.loadConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param newConfig
|
||||||
|
*/
|
||||||
|
public SellerFactory(final Config newConfig) throws ConfigurationException {
|
||||||
|
this.setConfig(newConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an Amazon Seller.
|
||||||
|
*
|
||||||
|
* @return AmazonSeller
|
||||||
|
*/
|
||||||
|
public AmazonSeller createAmazonSeller() {
|
||||||
|
String apiUrl = config.getProperty("AMAZON_API_URL");
|
||||||
|
String apiKey = config.getProperty("AMAZON_API_KEY");
|
||||||
|
return new AmazonSeller(apiUrl, apiKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an eBay Seller.
|
||||||
|
*
|
||||||
|
* @return EbaySeller
|
||||||
|
*/
|
||||||
|
public EbaySeller createEbaySeller() {
|
||||||
|
String apiUrl = config.getProperty("EBAY_API_URL");
|
||||||
|
String apiKey = config.getProperty("EBAY_API_KEY");
|
||||||
|
return new EbaySeller(apiUrl, apiKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
33
src/main/java/de/rwu/easydrop/api/dto/OfferDTO.java
Normal file
33
src/main/java/de/rwu/easydrop/api/dto/OfferDTO.java
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package de.rwu.easydrop.api.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Offer data transfer object.
|
||||||
|
*
|
||||||
|
* @since 0.3.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class OfferDTO {
|
||||||
|
/**
|
||||||
|
* ID of the offer, built from identifiers of the source platforms.
|
||||||
|
*/
|
||||||
|
private String offerId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The product that our software buys.
|
||||||
|
*/
|
||||||
|
private ProductDTO sourceProduct;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The product that our software sells.
|
||||||
|
*/
|
||||||
|
private ProductDTO targetProduct;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Date of last update of the offer.
|
||||||
|
*/
|
||||||
|
private String lastUpdate;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package de.rwu.easydrop.api.dto;
|
package de.rwu.easydrop.api.dto;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.model.Webshop;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -10,9 +11,9 @@ import lombok.Data;
|
|||||||
@Data
|
@Data
|
||||||
public class ProductDTO {
|
public class ProductDTO {
|
||||||
/**
|
/**
|
||||||
* Data source platform, like "Amazon".
|
* Data source platform, like Amazon.
|
||||||
*/
|
*/
|
||||||
private String dataOrigin;
|
private Webshop dataOrigin;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Platform internal product identifier.
|
* Platform internal product identifier.
|
||||||
@@ -39,13 +40,18 @@ public class ProductDTO {
|
|||||||
*/
|
*/
|
||||||
private boolean available;
|
private boolean available;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Last update from API.
|
||||||
|
*/
|
||||||
|
private String lastUpdate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates ProductDTO instance.
|
* Creates ProductDTO instance.
|
||||||
*
|
*
|
||||||
* @param newProductId Internal Product indetifier
|
* @param newProductId Internal Product indetifier
|
||||||
* @param newDataOrigin Data Origin
|
* @param newDataOrigin Data Origin
|
||||||
*/
|
*/
|
||||||
public ProductDTO(final String newProductId, final String newDataOrigin) {
|
public ProductDTO(final String newProductId, final Webshop newDataOrigin) {
|
||||||
this.productId = newProductId;
|
this.productId = newProductId;
|
||||||
this.dataOrigin = newDataOrigin;
|
this.dataOrigin = newDataOrigin;
|
||||||
}
|
}
|
||||||
|
|||||||
28
src/main/java/de/rwu/easydrop/api/dto/TransactionDTO.java
Normal file
28
src/main/java/de/rwu/easydrop/api/dto/TransactionDTO.java
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package de.rwu.easydrop.api.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction data transfer object.
|
||||||
|
*
|
||||||
|
* @since 0.3.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class TransactionDTO {
|
||||||
|
/**
|
||||||
|
* Offer ID.
|
||||||
|
*/
|
||||||
|
private String offerId;
|
||||||
|
/**
|
||||||
|
* Sales volume.
|
||||||
|
*/
|
||||||
|
private double volume;
|
||||||
|
/**
|
||||||
|
* Earnings (volume - cost).
|
||||||
|
*/
|
||||||
|
private double earnings;
|
||||||
|
/**
|
||||||
|
* Transaction timestamp.
|
||||||
|
*/
|
||||||
|
private String transactionTime;
|
||||||
|
}
|
||||||
92
src/main/java/de/rwu/easydrop/core/Core.java
Normal file
92
src/main/java/de/rwu/easydrop/core/Core.java
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
package de.rwu.easydrop.core;
|
||||||
|
|
||||||
|
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.api.client.PurchaserFactory;
|
||||||
|
import de.rwu.easydrop.api.client.SellerFactory;
|
||||||
|
import de.rwu.easydrop.api.dto.OfferDTO;
|
||||||
|
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.data.connector.TransactionPersistenceInterface;
|
||||||
|
import de.rwu.easydrop.model.Offer;
|
||||||
|
import de.rwu.easydrop.model.ProductCatalogue;
|
||||||
|
import de.rwu.easydrop.service.mapping.OfferMapper;
|
||||||
|
import de.rwu.easydrop.service.processing.OfferIdentifier;
|
||||||
|
import de.rwu.easydrop.service.processing.OfferProvisioner;
|
||||||
|
import de.rwu.easydrop.service.processing.TransactionHandler;
|
||||||
|
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 final class Core {
|
||||||
|
/**
|
||||||
|
* Logging instance.
|
||||||
|
*/
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(Core.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hidden Constructor.
|
||||||
|
*/
|
||||||
|
private Core() {
|
||||||
|
// Hidden constructor
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the core.
|
||||||
|
*
|
||||||
|
* @throws ConfigurationException
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
SellerFactory sellerFactory = new SellerFactory(config);
|
||||||
|
PurchaserFactory purchaserFactory = new PurchaserFactory(config);
|
||||||
|
|
||||||
|
ProductPersistenceInterface productDB = new SQLiteConnector(new SQLiteDataSource());
|
||||||
|
OfferPersistenceInterface offerDB = new SQLiteConnector(new SQLiteDataSource());
|
||||||
|
TransactionPersistenceInterface txDB = new SQLiteConnector(new SQLiteDataSource());
|
||||||
|
|
||||||
|
ProductRetriever retriever = new ProductRetriever(dataSourceFactory, productDB);
|
||||||
|
CatalogueRetriever catRetriever = new CatalogueRetriever(pConfig, retriever);
|
||||||
|
CatalogueWriter catWriter = new CatalogueWriter(productDB);
|
||||||
|
|
||||||
|
LOGGER.info("Loading catalogues");
|
||||||
|
catRetriever.loadCatalogues();
|
||||||
|
List<ProductCatalogue> pCats = catRetriever.getProductCatalogues();
|
||||||
|
catWriter.writeCatalogues(pCats);
|
||||||
|
|
||||||
|
LOGGER.info("Creating offers");
|
||||||
|
OfferIdentifier ident = new OfferIdentifier();
|
||||||
|
OfferProvisioner provis = new OfferProvisioner(offerDB, sellerFactory, purchaserFactory);
|
||||||
|
List<Offer> identifiedOffers = ident.runIdentifier(pCats);
|
||||||
|
provis.runProvisioner(identifiedOffers);
|
||||||
|
|
||||||
|
LOGGER.info("Creating transactions");
|
||||||
|
TransactionHandler txHandler = new TransactionHandler(txDB);
|
||||||
|
for (OfferDTO o : offerDB.getOffers()) {
|
||||||
|
txHandler.turnOfferToTransaction(OfferMapper.mapOfferFromDTO(o));
|
||||||
|
}
|
||||||
|
|
||||||
|
txDB.outputTransactionsToLog();
|
||||||
|
txDB.outputSummaryToLog();
|
||||||
|
}
|
||||||
|
}
|
||||||
6
src/main/java/de/rwu/easydrop/core/package-info.java
Normal file
6
src/main/java/de/rwu/easydrop/core/package-info.java
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
/**
|
||||||
|
* EasyDrop's core.
|
||||||
|
*
|
||||||
|
* @since 0.3.0
|
||||||
|
*/
|
||||||
|
package de.rwu.easydrop.core;
|
||||||
@@ -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();
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package de.rwu.easydrop.data.connector;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.api.dto.OfferDTO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface to offer persistence.
|
||||||
|
*
|
||||||
|
* @since 0.3.0
|
||||||
|
*/
|
||||||
|
public interface OfferPersistenceInterface {
|
||||||
|
/**
|
||||||
|
* Writes a ProductDTO to persistence.
|
||||||
|
*
|
||||||
|
* @param dto
|
||||||
|
*/
|
||||||
|
void writeOffer(OfferDTO dto);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a OfferDTO from persistence.
|
||||||
|
*
|
||||||
|
* @param offerId
|
||||||
|
* @return Offer data transfer object
|
||||||
|
*/
|
||||||
|
OfferDTO getOfferDTOById(String offerId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all offerDTOs from persistence.
|
||||||
|
*
|
||||||
|
* @return offerDTOs
|
||||||
|
*/
|
||||||
|
List<OfferDTO> getOffers();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes all offer data from persistence.
|
||||||
|
*/
|
||||||
|
void clearOfferData();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes an offer from persistence.
|
||||||
|
*
|
||||||
|
* @param offerId
|
||||||
|
*/
|
||||||
|
void deleteOfferById(String offerId);
|
||||||
|
}
|
||||||
@@ -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 product data from persistence.
|
||||||
|
*/
|
||||||
|
void clearProductData();
|
||||||
|
}
|
||||||
@@ -1,27 +1,41 @@
|
|||||||
package de.rwu.easydrop.data.connector;
|
package de.rwu.easydrop.data.connector;
|
||||||
|
|
||||||
import java.net.URL;
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.Statement;
|
import java.sql.Statement;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.sqlite.SQLiteDataSource;
|
import org.sqlite.SQLiteDataSource;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.api.dto.OfferDTO;
|
||||||
import de.rwu.easydrop.api.dto.ProductDTO;
|
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||||
|
import de.rwu.easydrop.api.dto.TransactionDTO;
|
||||||
import de.rwu.easydrop.exception.PersistenceException;
|
import de.rwu.easydrop.exception.PersistenceException;
|
||||||
|
import de.rwu.easydrop.model.Webshop;
|
||||||
|
import de.rwu.easydrop.util.FormattingUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows connecting to a SQLite Database.
|
* Allows connecting to a SQLite Database.
|
||||||
*
|
*
|
||||||
* @since 0.2.0
|
* @since 0.2.0
|
||||||
*/
|
*/
|
||||||
public final class SQLiteConnector extends AbstractProductPersistence {
|
public final class SQLiteConnector implements
|
||||||
|
ProductPersistenceInterface, OfferPersistenceInterface,
|
||||||
|
TransactionPersistenceInterface {
|
||||||
/**
|
/**
|
||||||
* Data origin.
|
* Base for calculating percentages.
|
||||||
*/
|
*/
|
||||||
private static final String DATA_ORIGIN = "SQLite";
|
private static final int PERCENT = 100;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logging instance.
|
||||||
|
*/
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(SQLiteConnector.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SQLite Database.
|
* SQLite Database.
|
||||||
@@ -39,6 +53,15 @@ public final class SQLiteConnector extends AbstractProductPersistence {
|
|||||||
* Path to SQLite db file.
|
* Path to SQLite db file.
|
||||||
*/
|
*/
|
||||||
private static final String PERSISTENCE_PATH = "jdbc:sqlite:persistence.db";
|
private static final String PERSISTENCE_PATH = "jdbc:sqlite:persistence.db";
|
||||||
|
/**
|
||||||
|
* Name of 'lastUpdate' column.
|
||||||
|
*/
|
||||||
|
private static final String LAST_UPDATE_COL_NAME = "lastUpdate";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of 'offerId' column.
|
||||||
|
*/
|
||||||
|
private static final String OFFERID_COL_NAME = "offerId";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates instance.
|
* Creates instance.
|
||||||
@@ -57,8 +80,8 @@ public final class SQLiteConnector extends AbstractProductPersistence {
|
|||||||
Connection connection = db.getConnection();
|
Connection connection = db.getConnection();
|
||||||
|
|
||||||
// Execute SQL statements to create tables
|
// Execute SQL statements to create tables
|
||||||
Statement statement = connection.createStatement();
|
Statement createProducts = connection.createStatement();
|
||||||
statement.execute(
|
createProducts.execute(
|
||||||
"CREATE TABLE IF NOT EXISTS products ("
|
"CREATE TABLE IF NOT EXISTS products ("
|
||||||
+ "dataOrigin TEXT, "
|
+ "dataOrigin TEXT, "
|
||||||
+ "productId TEXT, "
|
+ "productId TEXT, "
|
||||||
@@ -66,12 +89,39 @@ public final class SQLiteConnector extends AbstractProductPersistence {
|
|||||||
+ "merchant TEXT, "
|
+ "merchant TEXT, "
|
||||||
+ "deliveryPrice REAL, "
|
+ "deliveryPrice REAL, "
|
||||||
+ "available INT, "
|
+ "available INT, "
|
||||||
+ "lastupdate TEXT, "
|
+ "lastUpdate TEXT, "
|
||||||
+ "UNIQUE(productId, dataOrigin) ON CONFLICT REPLACE"
|
+ "UNIQUE(productId, dataOrigin) ON CONFLICT REPLACE"
|
||||||
+ ")");
|
+ ")");
|
||||||
|
|
||||||
// Close the statement and connection
|
// Close the statement
|
||||||
statement.close();
|
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();
|
||||||
|
|
||||||
|
Statement createTransactions = connection.createStatement();
|
||||||
|
createTransactions.execute(
|
||||||
|
"CREATE TABLE IF NOT EXISTS transactions ("
|
||||||
|
+ "offerId TEXT, "
|
||||||
|
+ "earnings REAL, "
|
||||||
|
+ "volume REAL, "
|
||||||
|
+ "transactionTime TEXT"
|
||||||
|
+ ")");
|
||||||
|
createTransactions.close();
|
||||||
|
|
||||||
|
// Close the connection
|
||||||
connection.close();
|
connection.close();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new PersistenceException("Something went wrong while initializing SQLite DB", e);
|
throw new PersistenceException("Something went wrong while initializing SQLite DB", e);
|
||||||
@@ -83,53 +133,64 @@ public final class SQLiteConnector extends AbstractProductPersistence {
|
|||||||
*
|
*
|
||||||
* @param dto
|
* @param dto
|
||||||
*/
|
*/
|
||||||
public void saveProduct(final ProductDTO dto) {
|
public void writeProduct(final ProductDTO dto) {
|
||||||
String query = "INSERT INTO products ("
|
String query = "INSERT INTO products ("
|
||||||
+ "dataOrigin, productId, currentPrice, merchant, "
|
+ "dataOrigin, productId, currentPrice, merchant, "
|
||||||
+ "deliveryPrice, available, lastupdate"
|
+ "deliveryPrice, available, lastUpdate"
|
||||||
+ ") VALUES ( "
|
+ ") VALUES ( "
|
||||||
+ "?, ?, ?, ?, ?, ?, datetime('now', 'localtime')"
|
+ "?, ?, ?, ?, ?, ?, ?"
|
||||||
+ ")";
|
+ ")";
|
||||||
|
|
||||||
try (Connection connection = db.getConnection();
|
try (Connection connection = db.getConnection();
|
||||||
PreparedStatement statement = connection.prepareStatement(query)) {
|
PreparedStatement statement = connection.prepareStatement(query)) {
|
||||||
int index = 0;
|
int index = 0;
|
||||||
|
|
||||||
statement.setString(++index, dto.getDataOrigin());
|
statement.setString(++index, dto.getDataOrigin().toString());
|
||||||
statement.setString(++index, dto.getProductId());
|
statement.setString(++index, dto.getProductId());
|
||||||
statement.setDouble(++index, dto.getCurrentPrice());
|
statement.setDouble(++index, dto.getCurrentPrice());
|
||||||
statement.setString(++index, dto.getMerchant());
|
statement.setString(++index, dto.getMerchant());
|
||||||
statement.setDouble(++index, dto.getDeliveryPrice());
|
statement.setDouble(++index, dto.getDeliveryPrice());
|
||||||
statement.setBoolean(++index, dto.isAvailable());
|
statement.setBoolean(++index, dto.isAvailable());
|
||||||
|
statement.setString(++index, dto.getLastUpdate());
|
||||||
|
|
||||||
statement.executeUpdate();
|
statement.executeUpdate();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new PersistenceException("Something went wrong while saving to SQLite", e);
|
throw new PersistenceException(
|
||||||
|
"Something went wrong while saving product to SQLite", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
|
* Gets a ProductDTO by identifier.
|
||||||
|
*
|
||||||
|
* @param productId
|
||||||
|
* @return DTO
|
||||||
|
*/
|
||||||
public ProductDTO getProductDTOById(final String productId) {
|
public ProductDTO getProductDTOById(final String productId) {
|
||||||
String query = "SELECT * FROM products WHERE productId = ?";
|
String query = "SELECT * FROM products WHERE productId = ?";
|
||||||
ProductDTO dto = null;
|
ProductDTO dto = null;
|
||||||
|
|
||||||
try (Connection connection = db.getConnection();
|
try {
|
||||||
PreparedStatement statement = connection.prepareStatement(query)) {
|
Connection connection = db.getConnection();
|
||||||
|
PreparedStatement statement = connection.prepareStatement(query);
|
||||||
|
|
||||||
statement.setString(1, productId);
|
statement.setString(1, productId);
|
||||||
|
|
||||||
try (ResultSet resultSet = statement.executeQuery()) {
|
try (ResultSet resultSet = statement.executeQuery()) {
|
||||||
if (resultSet.next()) {
|
if (resultSet.next()) {
|
||||||
dto = new ProductDTO(resultSet.getString("productId"),
|
Webshop newShop = Webshop.fromString(resultSet.getString("dataOrigin"));
|
||||||
resultSet.getString("dataOrigin"));
|
|
||||||
|
dto = new ProductDTO(resultSet.getString("productId"), newShop);
|
||||||
dto.setCurrentPrice(resultSet.getDouble("currentPrice"));
|
dto.setCurrentPrice(resultSet.getDouble("currentPrice"));
|
||||||
dto.setMerchant(resultSet.getString("merchant"));
|
dto.setMerchant(resultSet.getString("merchant"));
|
||||||
dto.setDeliveryPrice(resultSet.getDouble("deliveryPrice"));
|
dto.setDeliveryPrice(resultSet.getDouble("deliveryPrice"));
|
||||||
dto.setAvailable(resultSet.getBoolean("available"));
|
dto.setAvailable(resultSet.getBoolean("available"));
|
||||||
|
dto.setLastUpdate(resultSet.getString(LAST_UPDATE_COL_NAME));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new PersistenceException("Something went wrong while reading from SQLite", e);
|
throw new PersistenceException(
|
||||||
|
"Something went wrong while reading product from SQLite");
|
||||||
}
|
}
|
||||||
|
|
||||||
return dto;
|
return dto;
|
||||||
@@ -137,11 +198,201 @@ public final class SQLiteConnector extends AbstractProductPersistence {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes all data from persistence.
|
* Deletes all data from persistence.
|
||||||
|
*
|
||||||
|
* @throws SQLException
|
||||||
*/
|
*/
|
||||||
public void clearData() {
|
public void clearData() {
|
||||||
|
clearProductData();
|
||||||
|
clearOfferData();
|
||||||
|
clearTXData();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes an offer to persistence.
|
||||||
|
*
|
||||||
|
* @param dto OfferDTO
|
||||||
|
*/
|
||||||
|
public void writeOffer(final OfferDTO dto) {
|
||||||
|
String query = "INSERT INTO offers ("
|
||||||
|
+ "offerId, "
|
||||||
|
+ "sourceWebshop, sourceId, sourcePrice, "
|
||||||
|
+ "targetWebshop, targetId, targetPrice, "
|
||||||
|
+ LAST_UPDATE_COL_NAME
|
||||||
|
+ ") 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.getDataOrigin().toString());
|
||||||
|
statement.setString(++index, sourceProduct.getProductId());
|
||||||
|
statement.setDouble(++index, sourceProduct.getCurrentPrice());
|
||||||
|
statement.setString(++index, targetProduct.getDataOrigin().toString());
|
||||||
|
statement.setString(++index, targetProduct.getProductId());
|
||||||
|
statement.setDouble(++index, targetProduct.getCurrentPrice());
|
||||||
|
statement.setString(++index, dto.getLastUpdate());
|
||||||
|
|
||||||
|
statement.executeUpdate();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new PersistenceException(
|
||||||
|
"Something went wrong while saving offer to SQLite", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an OfferDTO by identifier.
|
||||||
|
*
|
||||||
|
* @param offerId
|
||||||
|
* @return OfferDTO
|
||||||
|
*/
|
||||||
|
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 = getProductDTOById(resultSet.getString("sourceId"));
|
||||||
|
ProductDTO targetProduct = getProductDTOById(resultSet.getString("targetId"));
|
||||||
|
dto.setOfferId(resultSet.getString(OFFERID_COL_NAME));
|
||||||
|
dto.setSourceProduct(srcProduct);
|
||||||
|
dto.setTargetProduct(targetProduct);
|
||||||
|
dto.setLastUpdate(resultSet.getString(LAST_UPDATE_COL_NAME));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new PersistenceException(
|
||||||
|
"Something went wrong while reading offer from SQLite", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeTX(final TransactionDTO dto) {
|
||||||
|
String query = "INSERT INTO transactions ("
|
||||||
|
+ "offerId, volume, earnings, transactionTime"
|
||||||
|
+ ") VALUES ("
|
||||||
|
+ "?, ?, ?, ?"
|
||||||
|
+ ")";
|
||||||
|
|
||||||
|
try (Connection connection = db.getConnection();
|
||||||
|
PreparedStatement statement = connection.prepareStatement(query)) {
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
statement.setString(++index, dto.getOfferId());
|
||||||
|
statement.setDouble(++index, dto.getVolume());
|
||||||
|
statement.setDouble(++index, dto.getEarnings());
|
||||||
|
statement.setString(++index, dto.getTransactionTime());
|
||||||
|
|
||||||
|
statement.executeUpdate();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new PersistenceException(
|
||||||
|
"Something went wrong while saving transaction to SQLite", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void outputTransactionsToLog() {
|
||||||
|
String query = "SELECT * FROM transactions t "
|
||||||
|
+ "LEFT JOIN offers o ON t.offerId = o.offerId "
|
||||||
|
+ "ORDER BY transactionTime ASC";
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
int index = 0;
|
||||||
|
sb.append("Transaction History:");
|
||||||
|
|
||||||
|
try (Connection connection = db.getConnection();
|
||||||
|
PreparedStatement statement = connection.prepareStatement(query)) {
|
||||||
|
|
||||||
|
try (ResultSet resultSet = statement.executeQuery()) {
|
||||||
|
while (resultSet.next()) {
|
||||||
|
sb.append("\n");
|
||||||
|
sb.append(String.format("%3d", ++index));
|
||||||
|
sb.append(String.format(" - %s - ", resultSet.getString("transactionTime")));
|
||||||
|
sb.append(String.format("+%s (%s) - ",
|
||||||
|
FormattingUtil.formatEuro(resultSet.getDouble("earnings")),
|
||||||
|
FormattingUtil.formatEuro(resultSet.getDouble("volume"))));
|
||||||
|
sb.append(String.format("[%s to %s] %s",
|
||||||
|
resultSet.getString("sourceWebshop"),
|
||||||
|
resultSet.getString("targetWebshop"),
|
||||||
|
resultSet.getString(OFFERID_COL_NAME)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new PersistenceException(
|
||||||
|
"Something went wrong while reading transaction from SQLite", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
String logString = sb.toString();
|
||||||
|
LOGGER.info(logString);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void outputSummaryToLog() {
|
||||||
|
String query = "SELECT SUM(earnings) AS earnings, SUM(volume) AS volume FROM transactions;";
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("Summary:\n");
|
||||||
|
|
||||||
|
try (Connection connection = db.getConnection();
|
||||||
|
PreparedStatement statement = connection.prepareStatement(query)) {
|
||||||
|
|
||||||
|
try (ResultSet resultSet = statement.executeQuery()) {
|
||||||
|
if (resultSet.next()) {
|
||||||
|
double earnings = resultSet.getDouble("earnings");
|
||||||
|
double volume = resultSet.getDouble("volume");
|
||||||
|
String avgMargin = String.valueOf(
|
||||||
|
Math.round(earnings / volume * PERCENT)) + "%";
|
||||||
|
|
||||||
|
String earningsFormatted = FormattingUtil.formatEuro(earnings);
|
||||||
|
String volumeFormatted = FormattingUtil.formatEuro(volume);
|
||||||
|
|
||||||
|
sb.append(String.format("Total earnings: %s, ", earningsFormatted));
|
||||||
|
sb.append(String.format("total volume: %s ", volumeFormatted));
|
||||||
|
sb.append(String.format("(average margin %s)", avgMargin));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new PersistenceException(
|
||||||
|
"Something went wrong while reading transaction summary from SQLite", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
String logString = sb.toString();
|
||||||
|
LOGGER.info(logString);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearTXData() {
|
||||||
|
runDeletionQuery("DELETE FROM transactions;");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearOfferData() {
|
||||||
|
runDeletionQuery("DELETE FROM offers;");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearProductData() {
|
||||||
|
runDeletionQuery("DELETE FROM products;");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flushes all data using the specified query.
|
||||||
|
*
|
||||||
|
* @param query
|
||||||
|
*/
|
||||||
|
private void runDeletionQuery(final String query) {
|
||||||
try (Connection connection = db.getConnection();
|
try (Connection connection = db.getConnection();
|
||||||
Statement statement = connection.createStatement()) {
|
Statement statement = connection.createStatement()) {
|
||||||
String query = "DELETE FROM products";
|
|
||||||
statement.executeUpdate(query);
|
statement.executeUpdate(query);
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new PersistenceException("Something went wrong while clearing the database", e);
|
throw new PersistenceException("Something went wrong while clearing the database", e);
|
||||||
@@ -149,25 +400,46 @@ public final class SQLiteConnector extends AbstractProductPersistence {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getDataOrigin() {
|
public void deleteOfferById(final String offerId) {
|
||||||
return DATA_ORIGIN;
|
String query = "DELETE FROM offers WHERE offerID = ?;";
|
||||||
|
|
||||||
|
try (Connection connection = db.getConnection();
|
||||||
|
PreparedStatement statement = connection.prepareStatement(query)) {
|
||||||
|
statement.setString(1, offerId);
|
||||||
|
|
||||||
|
statement.executeUpdate();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new PersistenceException(
|
||||||
|
"Something went wrong while deleting offer from SQLite", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getApiKey() {
|
public List<OfferDTO> getOffers() {
|
||||||
throw new UnsupportedOperationException(
|
List<OfferDTO> list = new ArrayList<>();
|
||||||
this.getClass().getName() + " doesn't support getApiKey");
|
String query = "SELECT * FROM offers";
|
||||||
|
|
||||||
|
try (Connection connection = db.getConnection();
|
||||||
|
PreparedStatement statement = connection.prepareStatement(query)) {
|
||||||
|
|
||||||
|
try (ResultSet resultSet = statement.executeQuery()) {
|
||||||
|
while (resultSet.next()) {
|
||||||
|
OfferDTO dto = new OfferDTO();
|
||||||
|
ProductDTO srcProduct = getProductDTOById(resultSet.getString("sourceId"));
|
||||||
|
ProductDTO targetProduct = getProductDTOById(resultSet.getString("targetId"));
|
||||||
|
dto.setOfferId(resultSet.getString(OFFERID_COL_NAME));
|
||||||
|
dto.setSourceProduct(srcProduct);
|
||||||
|
dto.setTargetProduct(targetProduct);
|
||||||
|
dto.setLastUpdate(resultSet.getString(LAST_UPDATE_COL_NAME));
|
||||||
|
|
||||||
|
list.add(dto);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new PersistenceException(
|
||||||
|
"Something went wrong while reading offers from SQLite", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
return list;
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package de.rwu.easydrop.data.connector;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.api.dto.TransactionDTO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Persistence interface for transactions.
|
||||||
|
*
|
||||||
|
* @since 0.3.0
|
||||||
|
*/
|
||||||
|
public interface TransactionPersistenceInterface {
|
||||||
|
/**
|
||||||
|
* Writes a ProductDTO to persistence.
|
||||||
|
*
|
||||||
|
* @param dto
|
||||||
|
*/
|
||||||
|
void writeTX(TransactionDTO dto);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes transactions to log.
|
||||||
|
*/
|
||||||
|
void outputTransactionsToLog();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes transaction summary (total volume and earnings) to log.
|
||||||
|
*/
|
||||||
|
void outputSummaryToLog();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes all transaction data from persistence.
|
||||||
|
*/
|
||||||
|
void clearTXData();
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package de.rwu.easydrop.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception that signifies a communication problem with a writer API.
|
||||||
|
*
|
||||||
|
* @since 0.3.0
|
||||||
|
*/
|
||||||
|
public class DataWriterException extends RuntimeException {
|
||||||
|
/**
|
||||||
|
* Throws an exception that signifies the data of a Product are invalid.
|
||||||
|
*
|
||||||
|
* @param message
|
||||||
|
*/
|
||||||
|
public DataWriterException(final String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throws an exception that signifies the data of a Product are invalid.
|
||||||
|
*
|
||||||
|
* @param message
|
||||||
|
* @param cause
|
||||||
|
*/
|
||||||
|
public DataWriterException(final String message, final Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package de.rwu.easydrop.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception that signifies the data of a Product are invalid.
|
||||||
|
*
|
||||||
|
* @since 0.3.0
|
||||||
|
*/
|
||||||
|
public class InvalidCatalogueException extends RuntimeException {
|
||||||
|
/**
|
||||||
|
* Throws an exception that signifies the data of a Product are invalid.
|
||||||
|
*
|
||||||
|
* @param message
|
||||||
|
*/
|
||||||
|
public InvalidCatalogueException(final String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throws an exception that signifies the data of a Product are invalid.
|
||||||
|
*
|
||||||
|
* @param message
|
||||||
|
* @param cause
|
||||||
|
*/
|
||||||
|
public InvalidCatalogueException(final String message, final Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package de.rwu.easydrop.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception that signifies the data of an Offer are invalid.
|
||||||
|
*
|
||||||
|
* @since 0.3.0
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package de.rwu.easydrop.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception that signifies the data of a Transaction are invalid.
|
||||||
|
*
|
||||||
|
* @since 0.3.0
|
||||||
|
*/
|
||||||
|
public class InvalidTransactionException extends RuntimeException {
|
||||||
|
/**
|
||||||
|
* Throws an exception that signifies the data of an Offer are invalid.
|
||||||
|
*
|
||||||
|
* @param message
|
||||||
|
*/
|
||||||
|
public InvalidTransactionException(final String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throws an exception that signifies the data of an Offer are invalid.
|
||||||
|
*
|
||||||
|
* @param message
|
||||||
|
* @param cause
|
||||||
|
*/
|
||||||
|
public InvalidTransactionException(final String message, final Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
}
|
||||||
31
src/main/java/de/rwu/easydrop/model/Offer.java
Normal file
31
src/main/java/de/rwu/easydrop/model/Offer.java
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package de.rwu.easydrop.model;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An Offer.
|
||||||
|
*
|
||||||
|
* @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.
|
||||||
|
*/
|
||||||
|
private Product sourceProduct;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The product that our software sells.
|
||||||
|
*/
|
||||||
|
private Product targetProduct;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Date of last update of the offer.
|
||||||
|
*/
|
||||||
|
private String lastUpdate;
|
||||||
|
}
|
||||||
@@ -13,7 +13,7 @@ public class Product {
|
|||||||
/**
|
/**
|
||||||
* Data source platform, like "Amazon".
|
* Data source platform, like "Amazon".
|
||||||
*/
|
*/
|
||||||
private String dataOrigin;
|
private Webshop dataOrigin;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Platform internal product identifier.
|
* Platform internal product identifier.
|
||||||
@@ -40,6 +40,11 @@ public class Product {
|
|||||||
*/
|
*/
|
||||||
private boolean available;
|
private boolean available;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Last update from API.
|
||||||
|
*/
|
||||||
|
private String lastUpdate;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final String toString() {
|
public final String toString() {
|
||||||
return "Product: ["
|
return "Product: ["
|
||||||
|
|||||||
@@ -68,11 +68,11 @@ public class ProductCatalogue {
|
|||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append("Product Catalogue: ").append(productName).append("\n");
|
sb.append(String.format("Catalogue Name: %s%n", productName));
|
||||||
sb.append("Description: ").append(description).append("\n");
|
sb.append(String.format("Description: %s%n", description));
|
||||||
sb.append("Products:\n");
|
sb.append("Products:\n");
|
||||||
for (Product product : products) {
|
for (Product product : products) {
|
||||||
sb.append(product.toString()).append("\n");
|
sb.append(String.format("%s%n", product.toString()));
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|||||||
31
src/main/java/de/rwu/easydrop/model/ProductPair.java
Normal file
31
src/main/java/de/rwu/easydrop/model/ProductPair.java
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package de.rwu.easydrop.model;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Associates two related Products to one another.
|
||||||
|
*
|
||||||
|
* @since 0.3.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ProductPair {
|
||||||
|
/**
|
||||||
|
* The first product.
|
||||||
|
*/
|
||||||
|
private final Product product1;
|
||||||
|
/**
|
||||||
|
* The second product.
|
||||||
|
*/
|
||||||
|
private final Product product2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a Product Pair.
|
||||||
|
*
|
||||||
|
* @param a First product
|
||||||
|
* @param b Second product
|
||||||
|
*/
|
||||||
|
public ProductPair(final Product a, final Product b) {
|
||||||
|
this.product1 = a;
|
||||||
|
this.product2 = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
30
src/main/java/de/rwu/easydrop/model/Transaction.java
Normal file
30
src/main/java/de/rwu/easydrop/model/Transaction.java
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
package de.rwu.easydrop.model;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A transaction.
|
||||||
|
*
|
||||||
|
* @since 0.3.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class Transaction {
|
||||||
|
/**
|
||||||
|
* Offer ID.
|
||||||
|
*
|
||||||
|
* @see Offer
|
||||||
|
*/
|
||||||
|
private String offerId;
|
||||||
|
/**
|
||||||
|
* Sales volume.
|
||||||
|
*/
|
||||||
|
private double volume;
|
||||||
|
/**
|
||||||
|
* Earnings (volume - cost).
|
||||||
|
*/
|
||||||
|
private double earnings;
|
||||||
|
/**
|
||||||
|
* Transaction timestamp.
|
||||||
|
*/
|
||||||
|
private String transactionTime;
|
||||||
|
}
|
||||||
31
src/main/java/de/rwu/easydrop/model/Webshop.java
Normal file
31
src/main/java/de/rwu/easydrop/model/Webshop.java
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package de.rwu.easydrop.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constants for data source/destination platforms.
|
||||||
|
*/
|
||||||
|
public enum Webshop {
|
||||||
|
/**
|
||||||
|
* Amazon Product API.
|
||||||
|
*/
|
||||||
|
AMAZON,
|
||||||
|
/**
|
||||||
|
* eBay Item API.
|
||||||
|
*/
|
||||||
|
EBAY;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to derive a webshop value from a string.
|
||||||
|
*
|
||||||
|
* @param str String
|
||||||
|
* @return webshop
|
||||||
|
* @throws IllegalArgumentException
|
||||||
|
*/
|
||||||
|
public static Webshop fromString(final String str) {
|
||||||
|
for (Webshop shop : Webshop.values()) {
|
||||||
|
if (shop.toString().equalsIgnoreCase(str)) {
|
||||||
|
return shop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException(String.format("No webshop called %s found", str));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package de.rwu.easydrop.service.mapping;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.api.dto.OfferDTO;
|
||||||
|
import de.rwu.easydrop.model.Offer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps between Offer, OfferDTO and OfferDTO.
|
||||||
|
*
|
||||||
|
* @since 0.2.0
|
||||||
|
*
|
||||||
|
* @see Offer
|
||||||
|
* @see OfferDTO
|
||||||
|
*/
|
||||||
|
public final class OfferMapper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private constructor to prevent unwanted instantiation.
|
||||||
|
*
|
||||||
|
* @throws UnsupportedOperationException always
|
||||||
|
*/
|
||||||
|
private OfferMapper() throws UnsupportedOperationException {
|
||||||
|
throw new UnsupportedOperationException("This is a mapping class, don't instantiate it.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a Offer object from a corresponding DTO.
|
||||||
|
*
|
||||||
|
* @param dto Offer Data Transfer Object
|
||||||
|
* @return Offer
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an OfferDTO object from a corresponding offer.
|
||||||
|
*
|
||||||
|
* @param offer
|
||||||
|
* @return OfferDTO
|
||||||
|
*/
|
||||||
|
public static OfferDTO mapOfferToDTO(final Offer offer) {
|
||||||
|
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.setDeliveryPrice(dto.getDeliveryPrice());
|
||||||
product.setMerchant(dto.getMerchant());
|
product.setMerchant(dto.getMerchant());
|
||||||
product.setProductId(dto.getProductId());
|
product.setProductId(dto.getProductId());
|
||||||
|
product.setLastUpdate(dto.getLastUpdate());
|
||||||
|
|
||||||
return product;
|
return product;
|
||||||
}
|
}
|
||||||
@@ -56,6 +57,7 @@ public final class ProductMapper {
|
|||||||
dto.setCurrentPrice(product.getCurrentPrice());
|
dto.setCurrentPrice(product.getCurrentPrice());
|
||||||
dto.setDeliveryPrice(product.getDeliveryPrice());
|
dto.setDeliveryPrice(product.getDeliveryPrice());
|
||||||
dto.setMerchant(product.getMerchant());
|
dto.setMerchant(product.getMerchant());
|
||||||
|
dto.setLastUpdate(product.getLastUpdate());
|
||||||
|
|
||||||
return dto;
|
return dto;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package de.rwu.easydrop.service.mapping;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.api.dto.TransactionDTO;
|
||||||
|
import de.rwu.easydrop.model.Transaction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps transaction DTOs and objects.
|
||||||
|
*
|
||||||
|
* @since 0.3.0
|
||||||
|
*/
|
||||||
|
public final class TransactionMapper {
|
||||||
|
/**
|
||||||
|
* Private constructor to prevent unwanted instantiation.
|
||||||
|
*
|
||||||
|
* @throws UnsupportedOperationException always
|
||||||
|
*/
|
||||||
|
private TransactionMapper() throws UnsupportedOperationException {
|
||||||
|
throw new UnsupportedOperationException("This is a mapping class, don't instantiate it.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a Transaction object from a corresponding DTO.
|
||||||
|
*
|
||||||
|
* @param dto Transaction Data Transfer Object
|
||||||
|
* @return Product
|
||||||
|
*/
|
||||||
|
public static Transaction mapTXFromDTO(final TransactionDTO dto) {
|
||||||
|
Transaction tx = new Transaction();
|
||||||
|
|
||||||
|
tx.setOfferId(dto.getOfferId());
|
||||||
|
tx.setVolume(dto.getVolume());
|
||||||
|
tx.setEarnings(dto.getEarnings());
|
||||||
|
tx.setTransactionTime(dto.getTransactionTime());
|
||||||
|
|
||||||
|
return tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a ProductDTO object from a corresponding Product.
|
||||||
|
*
|
||||||
|
* @param tx Transaction
|
||||||
|
* @return TransactionDTO
|
||||||
|
*/
|
||||||
|
public static TransactionDTO mapTXToDTO(final Transaction tx) {
|
||||||
|
TransactionDTO dto = new TransactionDTO();
|
||||||
|
|
||||||
|
dto.setOfferId(tx.getOfferId());
|
||||||
|
dto.setVolume(tx.getVolume());
|
||||||
|
dto.setEarnings(tx.getEarnings());
|
||||||
|
dto.setTransactionTime(tx.getTransactionTime());
|
||||||
|
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
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;
|
||||||
|
|
||||||
|
public class OfferIdentifier {
|
||||||
|
/**
|
||||||
|
* Logging instance.
|
||||||
|
*/
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(OfferIdentifier.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* runIdentifier calls the price function that decides
|
||||||
|
* if it is feasible to dropship products.
|
||||||
|
*
|
||||||
|
* @param pCats Product catalogues
|
||||||
|
* @return Identified offers
|
||||||
|
*/
|
||||||
|
public List<Offer> runIdentifier(final List<ProductCatalogue> pCats) {
|
||||||
|
List<Offer> identifiedOffers = new ArrayList<>();
|
||||||
|
for (ProductCatalogue pCat : pCats) {
|
||||||
|
|
||||||
|
// Call price finder for all catalogue
|
||||||
|
try {
|
||||||
|
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("\n Identified Offer: {} ({} to {}) with margin {} ",
|
||||||
|
pCat.getProductName(),
|
||||||
|
pair.getProduct1().getDataOrigin(),
|
||||||
|
pair.getProduct2().getDataOrigin(),
|
||||||
|
marginFormatted);
|
||||||
|
} catch (InvalidOfferException e) {
|
||||||
|
// Don't include offer if deemed invalid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return identifiedOffers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the cheapest and most expensive product of a catalogue to guarantee
|
||||||
|
* the biggest margin as a pair.
|
||||||
|
*
|
||||||
|
* @param pCat Product Catalogue
|
||||||
|
* @return Cheapest Product, Most Expensive Product as a Product Pair
|
||||||
|
*/
|
||||||
|
public static ProductPair getHighestMarginProducts(final ProductCatalogue pCat) {
|
||||||
|
if (pCat.getProducts().size() < 2) {
|
||||||
|
throw new InvalidCatalogueException("Product Catalogue holds less than 2 products!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize indexes
|
||||||
|
Product cheapestProduct = pCat.getProducts().get(0);
|
||||||
|
Product mostExpensiveProduct = pCat.getProducts().get(0);
|
||||||
|
|
||||||
|
for (Product product : pCat.getProducts()) {
|
||||||
|
if (product.getCurrentPrice() < cheapestProduct.getCurrentPrice()) {
|
||||||
|
cheapestProduct = product;
|
||||||
|
}
|
||||||
|
if (product.getCurrentPrice() > mostExpensiveProduct.getCurrentPrice()) {
|
||||||
|
mostExpensiveProduct = product;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cheapestProduct.getCurrentPrice() == mostExpensiveProduct.getCurrentPrice()) {
|
||||||
|
throw new InvalidOfferException("Price margin is zero!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ProductPair(cheapestProduct, mostExpensiveProduct);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
package de.rwu.easydrop.service.processing;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.api.client.AmazonPurchaser;
|
||||||
|
import de.rwu.easydrop.api.client.AmazonSeller;
|
||||||
|
import de.rwu.easydrop.api.client.EbayPurchaser;
|
||||||
|
import de.rwu.easydrop.api.client.EbaySeller;
|
||||||
|
import de.rwu.easydrop.api.client.PurchaserFactory;
|
||||||
|
import de.rwu.easydrop.api.client.SellerFactory;
|
||||||
|
import de.rwu.easydrop.data.connector.OfferPersistenceInterface;
|
||||||
|
import de.rwu.easydrop.model.Offer;
|
||||||
|
import de.rwu.easydrop.service.mapping.ProductMapper;
|
||||||
|
import de.rwu.easydrop.service.writer.OfferWriter;
|
||||||
|
import de.rwu.easydrop.util.FormattingUtil;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Offer provisioner.
|
||||||
|
*
|
||||||
|
* @since 0.3.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class OfferProvisioner {
|
||||||
|
/**
|
||||||
|
* Writes offers into persistence.
|
||||||
|
*/
|
||||||
|
private OfferWriter offerWriter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the API for selling products on Amazon.
|
||||||
|
*/
|
||||||
|
private AmazonSeller amazonSeller;
|
||||||
|
/**
|
||||||
|
* Is the API for selling products on Ebay.
|
||||||
|
*/
|
||||||
|
private EbaySeller ebaySeller;
|
||||||
|
/**
|
||||||
|
* Is the API for buying products on Amazon.
|
||||||
|
*/
|
||||||
|
private AmazonPurchaser amazonPurchaser;
|
||||||
|
/**
|
||||||
|
* Is the API for buying products on Ebay.
|
||||||
|
*/
|
||||||
|
private EbayPurchaser ebayPurchaser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Puts up the sell order.
|
||||||
|
*
|
||||||
|
* @param offer
|
||||||
|
*/
|
||||||
|
private void toSeller(final Offer offer) throws IllegalArgumentException {
|
||||||
|
switch (offer.getTargetProduct().getDataOrigin()) {
|
||||||
|
case EBAY -> this.ebaySeller.sellProduct(
|
||||||
|
ProductMapper.mapProductToDTO(offer.getTargetProduct()));
|
||||||
|
case AMAZON -> this.amazonSeller.sellProduct(
|
||||||
|
ProductMapper.mapProductToDTO(offer.getTargetProduct()));
|
||||||
|
default -> throw new IllegalArgumentException("Unsupported source plattform");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Puts up the buy order.
|
||||||
|
*
|
||||||
|
* @param offer
|
||||||
|
*/
|
||||||
|
private void toBuyer(final Offer offer) throws IllegalArgumentException {
|
||||||
|
switch (offer.getSourceProduct().getDataOrigin()) {
|
||||||
|
case EBAY -> ebayPurchaser.purchaseProduct(
|
||||||
|
ProductMapper.mapProductToDTO(offer.getSourceProduct()));
|
||||||
|
case AMAZON -> amazonPurchaser.purchaseProduct(
|
||||||
|
ProductMapper.mapProductToDTO(offer.getSourceProduct()));
|
||||||
|
default -> throw new IllegalArgumentException("Unsupported target plattform");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the class for placing orders on a target platform.
|
||||||
|
*
|
||||||
|
* @param db Persistence Interface
|
||||||
|
* @param newSellerFactory Seller Factory
|
||||||
|
* @param newPurchaserFactory Purchaser Factory
|
||||||
|
*/
|
||||||
|
public OfferProvisioner(
|
||||||
|
final OfferPersistenceInterface db,
|
||||||
|
final SellerFactory newSellerFactory,
|
||||||
|
final PurchaserFactory newPurchaserFactory) {
|
||||||
|
this.offerWriter = new OfferWriter(db);
|
||||||
|
this.ebaySeller = newSellerFactory.createEbaySeller();
|
||||||
|
this.amazonSeller = newSellerFactory.createAmazonSeller();
|
||||||
|
this.ebayPurchaser = newPurchaserFactory.createEbayPurchaser();
|
||||||
|
this.amazonPurchaser = newPurchaserFactory.createAmazonPurchaser();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method for placing orders on a target platform.
|
||||||
|
*
|
||||||
|
* @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());
|
||||||
|
|
||||||
|
this.toSeller(newOffer);
|
||||||
|
this.toBuyer(newOffer);
|
||||||
|
newOffer.setOfferId(newOfferId);
|
||||||
|
offerWriter.writeOfferToPersistence(newOffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package de.rwu.easydrop.service.processing;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Processes dropshipping orders.
|
|
||||||
*
|
|
||||||
* TODO implement
|
|
||||||
*/
|
|
||||||
public class OrderManager {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package de.rwu.easydrop.service.processing;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.api.dto.TransactionDTO;
|
||||||
|
import de.rwu.easydrop.data.connector.TransactionPersistenceInterface;
|
||||||
|
import de.rwu.easydrop.model.Offer;
|
||||||
|
import de.rwu.easydrop.model.Transaction;
|
||||||
|
import de.rwu.easydrop.service.mapping.TransactionMapper;
|
||||||
|
import de.rwu.easydrop.util.Timestamp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles transactions.
|
||||||
|
*
|
||||||
|
* @since 0.3.0
|
||||||
|
*/
|
||||||
|
public class TransactionHandler {
|
||||||
|
/**
|
||||||
|
* Transaction persistence.
|
||||||
|
*/
|
||||||
|
private TransactionPersistenceInterface txPersistence;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new transaction handler.
|
||||||
|
*
|
||||||
|
* @param txdb transaction persistence
|
||||||
|
*/
|
||||||
|
public TransactionHandler(final TransactionPersistenceInterface txdb) {
|
||||||
|
this.txPersistence = txdb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates transaction from offer.
|
||||||
|
*
|
||||||
|
* @param offer Offer
|
||||||
|
*/
|
||||||
|
public void turnOfferToTransaction(final Offer offer) {
|
||||||
|
Transaction tx = new Transaction();
|
||||||
|
tx.setOfferId(offer.getOfferId());
|
||||||
|
tx.setVolume(offer.getTargetProduct().getCurrentPrice());
|
||||||
|
tx.setEarnings(offer.getTargetProduct().getCurrentPrice()
|
||||||
|
- offer.getSourceProduct().getCurrentPrice());
|
||||||
|
tx.setTransactionTime(Timestamp.now());
|
||||||
|
|
||||||
|
// Write transaction to persistence
|
||||||
|
TransactionDTO txDTO = TransactionMapper.mapTXToDTO(tx);
|
||||||
|
txPersistence.writeTX(txDTO);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,9 @@ import java.util.List;
|
|||||||
|
|
||||||
import javax.naming.ConfigurationException;
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
import de.rwu.easydrop.exception.InvalidProductException;
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import de.rwu.easydrop.model.Product;
|
import de.rwu.easydrop.model.Product;
|
||||||
import de.rwu.easydrop.model.ProductCatalogue;
|
import de.rwu.easydrop.model.ProductCatalogue;
|
||||||
import de.rwu.easydrop.util.ProductsConfig;
|
import de.rwu.easydrop.util.ProductsConfig;
|
||||||
@@ -18,6 +20,11 @@ import lombok.Data;
|
|||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class CatalogueRetriever {
|
public class CatalogueRetriever {
|
||||||
|
/**
|
||||||
|
* Logging instance.
|
||||||
|
*/
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(CatalogueRetriever.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User-configured products.
|
* User-configured products.
|
||||||
*/
|
*/
|
||||||
@@ -57,22 +64,16 @@ public class CatalogueRetriever {
|
|||||||
pCat.getProductName(), pCat.getDescription());
|
pCat.getProductName(), pCat.getDescription());
|
||||||
|
|
||||||
for (Product product : pCat.getProducts()) {
|
for (Product product : pCat.getProducts()) {
|
||||||
Product newProduct = new Product();
|
Product newProduct = productRetriever.getProductFromWebshop(product.getDataOrigin(),
|
||||||
newProduct.setDataOrigin(product.getDataOrigin());
|
product.getProductId());
|
||||||
newProduct.setProductId(product.getProductId());
|
|
||||||
|
|
||||||
if (newProduct.getDataOrigin().equals("Amazon")) {
|
|
||||||
newProduct = productRetriever.getProductFromAmazon(product.getProductId());
|
|
||||||
} else if (newProduct.getDataOrigin().equals("eBay")) {
|
|
||||||
newProduct = productRetriever.getProductFromEbay(product.getProductId());
|
|
||||||
} else {
|
|
||||||
throw new InvalidProductException("Product data origin is invalid");
|
|
||||||
}
|
|
||||||
|
|
||||||
newProductCatalogue.addProduct(newProduct);
|
newProductCatalogue.addProduct(newProduct);
|
||||||
}
|
}
|
||||||
|
|
||||||
productCatalogues.add(newProductCatalogue);
|
productCatalogues.add(newProductCatalogue);
|
||||||
|
String catString = String.format(
|
||||||
|
"%nLoaded Catalogue: %n%s", newProductCatalogue.toString());
|
||||||
|
LOGGER.info(catString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package de.rwu.easydrop.service.retriever;
|
||||||
|
|
||||||
|
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,8 +4,9 @@ import de.rwu.easydrop.api.client.AmazonProductDataSource;
|
|||||||
import de.rwu.easydrop.api.client.DataSourceFactory;
|
import de.rwu.easydrop.api.client.DataSourceFactory;
|
||||||
import de.rwu.easydrop.api.client.EbayItemDataSource;
|
import de.rwu.easydrop.api.client.EbayItemDataSource;
|
||||||
import de.rwu.easydrop.api.dto.ProductDTO;
|
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.Product;
|
||||||
|
import de.rwu.easydrop.model.Webshop;
|
||||||
import de.rwu.easydrop.service.mapping.ProductMapper;
|
import de.rwu.easydrop.service.mapping.ProductMapper;
|
||||||
import de.rwu.easydrop.service.validation.ProductValidator;
|
import de.rwu.easydrop.service.validation.ProductValidator;
|
||||||
|
|
||||||
@@ -19,19 +20,20 @@ public class ProductRetriever {
|
|||||||
* Data source factory.
|
* Data source factory.
|
||||||
*/
|
*/
|
||||||
private DataSourceFactory dataSourceFactory;
|
private DataSourceFactory dataSourceFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param newDataSourceFactory the dataSourceFactory to set
|
* Persistence interface.
|
||||||
*/
|
*/
|
||||||
public void setDataSourceFactory(final DataSourceFactory newDataSourceFactory) {
|
private ProductPersistenceInterface persistence;
|
||||||
this.dataSourceFactory = newDataSourceFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param newDataSourceFactory
|
* @param newDataSourceFactory
|
||||||
|
* @param newPersistence
|
||||||
*/
|
*/
|
||||||
public ProductRetriever(final DataSourceFactory newDataSourceFactory) {
|
public ProductRetriever(
|
||||||
this.setDataSourceFactory(newDataSourceFactory);
|
final DataSourceFactory newDataSourceFactory,
|
||||||
|
final ProductPersistenceInterface newPersistence) {
|
||||||
|
this.dataSourceFactory = newDataSourceFactory;
|
||||||
|
this.persistence = newPersistence;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -73,12 +75,27 @@ public class ProductRetriever {
|
|||||||
* @return Product from persistence
|
* @return Product from persistence
|
||||||
*/
|
*/
|
||||||
public Product getProductFromPersistence(final String productId) {
|
public Product getProductFromPersistence(final String productId) {
|
||||||
AbstractProductPersistence src = dataSourceFactory.createProductPersistenceDataSource();
|
ProductDTO dto = persistence.getProductDTOById(productId);
|
||||||
|
|
||||||
ProductDTO dto = src.getProductDTOById(productId);
|
|
||||||
Product product = ProductMapper.mapProductFromDTO(dto);
|
Product product = ProductMapper.mapProductFromDTO(dto);
|
||||||
ProductValidator.validate(product);
|
ProductValidator.validate(product);
|
||||||
|
|
||||||
return product;
|
return product;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a product from an API by name of the API so that high-level
|
||||||
|
* components do not need to be extended
|
||||||
|
* with exact function call names if we extend the list of webshops.
|
||||||
|
*
|
||||||
|
* @param shop Data source name, e.g. Amazon
|
||||||
|
* @param productIdentifier Product name, translated to the correct product ID
|
||||||
|
* for the data source
|
||||||
|
* @return Product from that data source or null if data source not available
|
||||||
|
*/
|
||||||
|
public Product getProductFromWebshop(final Webshop shop, final String productIdentifier) {
|
||||||
|
return switch (shop) {
|
||||||
|
case AMAZON -> getProductFromAmazon(productIdentifier);
|
||||||
|
case EBAY -> getProductFromEbay(productIdentifier);
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package de.rwu.easydrop.service.validation;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.exception.InvalidOfferException;
|
||||||
|
import de.rwu.easydrop.model.Offer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Confirms validity of Offer data.
|
||||||
|
*
|
||||||
|
* @since 0.2.0
|
||||||
|
*/
|
||||||
|
public final class OfferValidator {
|
||||||
|
/**
|
||||||
|
* Private constructor to prevent unwanted instantiation.
|
||||||
|
*
|
||||||
|
* @throws UnsupportedOperationException always
|
||||||
|
*/
|
||||||
|
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) {
|
||||||
|
try {
|
||||||
|
if (offer.getOfferId().equals("")) {
|
||||||
|
throw new InvalidOfferException("Offer ID cannot be empty");
|
||||||
|
}
|
||||||
|
if (offer.getLastUpdate().equals("")) {
|
||||||
|
throw new InvalidOfferException("LastUpdate cannot be empty");
|
||||||
|
}
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
throw new InvalidOfferException("Required information is missing in the offer", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,5 @@
|
|||||||
package de.rwu.easydrop.service.validation;
|
package de.rwu.easydrop.service.validation;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import de.rwu.easydrop.exception.InvalidProductException;
|
import de.rwu.easydrop.exception.InvalidProductException;
|
||||||
import de.rwu.easydrop.model.Product;
|
import de.rwu.easydrop.model.Product;
|
||||||
|
|
||||||
@@ -31,26 +28,8 @@ public final class ProductValidator {
|
|||||||
if (product.getCurrentPrice() == 0.00) {
|
if (product.getCurrentPrice() == 0.00) {
|
||||||
throw new InvalidProductException("Current price cannot be 0.00");
|
throw new InvalidProductException("Current price cannot be 0.00");
|
||||||
}
|
}
|
||||||
if (!isInValidDataOrigins(product.getDataOrigin())) {
|
|
||||||
throw new InvalidProductException("Unknown data source");
|
|
||||||
}
|
|
||||||
if (product.getProductId().equals("")) {
|
if (product.getProductId().equals("")) {
|
||||||
throw new InvalidProductException("Product ID cannot be empty");
|
throw new InvalidProductException("Product ID cannot be empty");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether a dataOrigin is within the set of valid ones.
|
|
||||||
*
|
|
||||||
* @param dataOrigin like "Amazon"
|
|
||||||
* @return true if valid
|
|
||||||
*/
|
|
||||||
public static boolean isInValidDataOrigins(final String dataOrigin) {
|
|
||||||
Set<String> validOrigins = new HashSet<>();
|
|
||||||
|
|
||||||
validOrigins.add("Amazon");
|
|
||||||
validOrigins.add("eBay");
|
|
||||||
|
|
||||||
return validOrigins.contains(dataOrigin);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package de.rwu.easydrop.service.validation;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.exception.InvalidTransactionException;
|
||||||
|
import de.rwu.easydrop.model.Transaction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates transactions.
|
||||||
|
*
|
||||||
|
* @since 0.3.0
|
||||||
|
*/
|
||||||
|
public final class TransactionValidator {
|
||||||
|
/**
|
||||||
|
* Private constructor to prevent unwanted instantiation.
|
||||||
|
*
|
||||||
|
* @throws UnsupportedOperationException always
|
||||||
|
*/
|
||||||
|
private TransactionValidator() throws UnsupportedOperationException {
|
||||||
|
throw new UnsupportedOperationException("This is a validator class, don't instantiate it.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes sure a transaction does not contain invalid information.
|
||||||
|
*
|
||||||
|
* @param tx the Transaction
|
||||||
|
*/
|
||||||
|
public static void validate(final Transaction tx) {
|
||||||
|
try {
|
||||||
|
if (tx.getOfferId().equals("")) {
|
||||||
|
throw new InvalidTransactionException("Offer ID cannot be empty");
|
||||||
|
}
|
||||||
|
if (tx.getEarnings() == 0) {
|
||||||
|
throw new InvalidTransactionException("Earnings can't be zero");
|
||||||
|
}
|
||||||
|
if (tx.getVolume() == 0) {
|
||||||
|
throw new InvalidTransactionException("Volume can't be zero");
|
||||||
|
}
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
throw new InvalidTransactionException(
|
||||||
|
"Required information is missing in the transaction", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ package de.rwu.easydrop.service.writer;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import de.rwu.easydrop.api.dto.ProductDTO;
|
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.Product;
|
||||||
import de.rwu.easydrop.model.ProductCatalogue;
|
import de.rwu.easydrop.model.ProductCatalogue;
|
||||||
import de.rwu.easydrop.service.mapping.ProductMapper;
|
import de.rwu.easydrop.service.mapping.ProductMapper;
|
||||||
@@ -18,14 +18,14 @@ public final class CatalogueWriter {
|
|||||||
/**
|
/**
|
||||||
* Holds a persistence reference.
|
* Holds a persistence reference.
|
||||||
*/
|
*/
|
||||||
private AbstractProductPersistence persistence;
|
private ProductPersistenceInterface persistence;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new instance.
|
* Creates new instance.
|
||||||
*
|
*
|
||||||
* @param newPersistence
|
* @param newPersistence
|
||||||
*/
|
*/
|
||||||
public CatalogueWriter(final AbstractProductPersistence newPersistence) {
|
public CatalogueWriter(final ProductPersistenceInterface newPersistence) {
|
||||||
persistence = newPersistence;
|
persistence = newPersistence;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ public final class CatalogueWriter {
|
|||||||
ProductValidator.validate(product);
|
ProductValidator.validate(product);
|
||||||
ProductDTO dto = ProductMapper.mapProductToDTO(product);
|
ProductDTO dto = ProductMapper.mapProductToDTO(product);
|
||||||
|
|
||||||
persistence.saveProduct(dto);
|
persistence.writeProduct(dto);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package de.rwu.easydrop.service.writer;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
public class OfferWriter {
|
||||||
|
/**
|
||||||
|
* Persistence.
|
||||||
|
*/
|
||||||
|
private OfferPersistenceInterface persistence;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param newPersistence the persistence to set
|
||||||
|
*/
|
||||||
|
public OfferWriter(final OfferPersistenceInterface newPersistence) {
|
||||||
|
this.persistence = newPersistence;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates and saves product to persistence.
|
||||||
|
*
|
||||||
|
* @param offer
|
||||||
|
*/
|
||||||
|
public void writeOfferToPersistence(final Offer offer) {
|
||||||
|
OfferDTO dto = OfferMapper.mapOfferToDTO(offer);
|
||||||
|
|
||||||
|
persistence.writeOffer(dto);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package de.rwu.easydrop.service.writer;
|
package de.rwu.easydrop.service.writer;
|
||||||
|
|
||||||
import de.rwu.easydrop.api.dto.ProductDTO;
|
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.Product;
|
||||||
import de.rwu.easydrop.service.mapping.ProductMapper;
|
import de.rwu.easydrop.service.mapping.ProductMapper;
|
||||||
import de.rwu.easydrop.service.validation.ProductValidator;
|
import de.rwu.easydrop.service.validation.ProductValidator;
|
||||||
@@ -15,12 +15,12 @@ public class ProductWriter {
|
|||||||
/**
|
/**
|
||||||
* Persistence.
|
* Persistence.
|
||||||
*/
|
*/
|
||||||
private AbstractProductPersistence persistence;
|
private ProductPersistenceInterface persistence;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param newPersistence the persistence to set
|
* @param newPersistence the persistence to set
|
||||||
*/
|
*/
|
||||||
public void setPersistence(final AbstractProductPersistence newPersistence) {
|
public ProductWriter(final ProductPersistenceInterface newPersistence) {
|
||||||
this.persistence = newPersistence;
|
this.persistence = newPersistence;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,6 +33,6 @@ public class ProductWriter {
|
|||||||
ProductValidator.validate(product);
|
ProductValidator.validate(product);
|
||||||
ProductDTO dto = ProductMapper.mapProductToDTO(product);
|
ProductDTO dto = ProductMapper.mapProductToDTO(product);
|
||||||
|
|
||||||
persistence.saveProduct(dto);
|
persistence.writeProduct(dto);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package de.rwu.easydrop.service.writer;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.api.dto.TransactionDTO;
|
||||||
|
import de.rwu.easydrop.data.connector.TransactionPersistenceInterface;
|
||||||
|
import de.rwu.easydrop.model.Transaction;
|
||||||
|
import de.rwu.easydrop.service.mapping.TransactionMapper;
|
||||||
|
import de.rwu.easydrop.service.validation.TransactionValidator;
|
||||||
|
|
||||||
|
public class TransactionWriter {
|
||||||
|
/**
|
||||||
|
* Persistence.
|
||||||
|
*/
|
||||||
|
private TransactionPersistenceInterface persistence;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param newPersistence the persistence to set
|
||||||
|
*/
|
||||||
|
public TransactionWriter(final TransactionPersistenceInterface newPersistence) {
|
||||||
|
this.persistence = newPersistence;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates and saves a transaction to persistence.
|
||||||
|
*
|
||||||
|
* @param tx Transaction
|
||||||
|
*/
|
||||||
|
public void writeTXToPersistence(final Transaction tx) {
|
||||||
|
TransactionDTO dto = TransactionMapper.mapTXToDTO(tx);
|
||||||
|
TransactionValidator.validate(tx);
|
||||||
|
|
||||||
|
persistence.writeTX(dto);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,7 +25,7 @@ public final class FormattingUtil {
|
|||||||
* @return formatted price
|
* @return formatted price
|
||||||
*/
|
*/
|
||||||
public static String formatEuro(final double amount) {
|
public static String formatEuro(final double amount) {
|
||||||
return String.format(Locale.GERMAN, "%,.2f", amount) + " €";
|
return String.format(Locale.GERMAN, "%,.2f", amount) + " Euro";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,4 +37,14 @@ public final class FormattingUtil {
|
|||||||
public static String urlEncode(final String str) {
|
public static String urlEncode(final String str) {
|
||||||
return str.replace(" ", "+");
|
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(" ", "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import com.jayway.jsonpath.JsonPathException;
|
|||||||
|
|
||||||
import de.rwu.easydrop.model.Product;
|
import de.rwu.easydrop.model.Product;
|
||||||
import de.rwu.easydrop.model.ProductCatalogue;
|
import de.rwu.easydrop.model.ProductCatalogue;
|
||||||
|
import de.rwu.easydrop.model.Webshop;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the user-specified catalogue of products.
|
* Reads the user-specified catalogue of products.
|
||||||
@@ -122,8 +123,8 @@ public final class ProductsConfig {
|
|||||||
ArrayList<HashMap<String, Object>> identifiers = JsonPath.read(jsonIdentifiers, "$");
|
ArrayList<HashMap<String, Object>> identifiers = JsonPath.read(jsonIdentifiers, "$");
|
||||||
|
|
||||||
for (HashMap<String, Object> product : identifiers) {
|
for (HashMap<String, Object> product : identifiers) {
|
||||||
String dataOrigin = product.keySet().iterator().next();
|
Webshop dataOrigin = Webshop.fromString(product.keySet().iterator().next());
|
||||||
String identifier = product.get(dataOrigin).toString();
|
String identifier = product.get(dataOrigin.toString()).toString();
|
||||||
|
|
||||||
Product newProduct = new Product();
|
Product newProduct = new Product();
|
||||||
newProduct.setDataOrigin(dataOrigin);
|
newProduct.setDataOrigin(dataOrigin);
|
||||||
|
|||||||
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 final 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
package de.rwu.easydrop.api.client;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
import static org.mockito.Mockito.doCallRealMethod;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||||
|
import de.rwu.easydrop.exception.DataWriterException;
|
||||||
|
import de.rwu.easydrop.model.Webshop;
|
||||||
|
|
||||||
|
class AbstractDataWriterTest {
|
||||||
|
private static String demoProductId = "whateverId";
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private HttpURLConnection mockConnection;
|
||||||
|
@Mock
|
||||||
|
private URL mockUrl;
|
||||||
|
|
||||||
|
private AbstractDataWriter writer;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() throws Exception {
|
||||||
|
MockitoAnnotations.openMocks(this);
|
||||||
|
writer = new AbstractDataWriter() {
|
||||||
|
@Override
|
||||||
|
protected String getApiKey() {
|
||||||
|
return "testApiKey";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Webshop getDataTarget() {
|
||||||
|
return Webshop.AMAZON;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected URL createApiUrl(String productIdentifier) throws MalformedURLException {
|
||||||
|
return mockUrl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void sendPutRequest_badResponseCode_throwsException() throws IOException {
|
||||||
|
// Set up DTO
|
||||||
|
ProductDTO dto = new ProductDTO(demoProductId, Webshop.AMAZON);
|
||||||
|
|
||||||
|
// Set up Mocks
|
||||||
|
AbstractDataWriter mockWriter = mock(AbstractDataWriter.class);
|
||||||
|
doCallRealMethod().when(mockWriter).sendPutRequest(any(), anyString());
|
||||||
|
when(mockUrl.openConnection()).thenReturn(mockConnection);
|
||||||
|
when(mockConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_BAD_REQUEST);
|
||||||
|
|
||||||
|
DataWriterException e = assertThrows(DataWriterException.class, () -> {
|
||||||
|
writer.sendPutRequest(dto, "Sales");
|
||||||
|
});
|
||||||
|
|
||||||
|
assertEquals("AMAZON Sales API responded with error code 400", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void sendPutRequest_ioException_throwsException() throws IOException {
|
||||||
|
// Set up DTO
|
||||||
|
ProductDTO dto = new ProductDTO(demoProductId, Webshop.AMAZON);
|
||||||
|
|
||||||
|
// Set up Mocks
|
||||||
|
AbstractDataWriter mockWriter = mock(AbstractDataWriter.class);
|
||||||
|
doCallRealMethod().when(mockWriter).sendPutRequest(any(), anyString());
|
||||||
|
when(mockUrl.openConnection()).thenThrow(new IOException());
|
||||||
|
|
||||||
|
DataWriterException e = assertThrows(DataWriterException.class, () -> {
|
||||||
|
writer.sendPutRequest(dto, "testApiType");
|
||||||
|
});
|
||||||
|
|
||||||
|
assertEquals("Couldn't fulfill AMAZON API request", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void sendPutRequest_successfulRequest() throws IOException {
|
||||||
|
// Set up DTO
|
||||||
|
ProductDTO dto = new ProductDTO(demoProductId, Webshop.AMAZON);
|
||||||
|
|
||||||
|
// Set up Mocks
|
||||||
|
AbstractDataWriter mockWriter = mock(AbstractDataWriter.class);
|
||||||
|
URL mockURL = mock(URL.class);
|
||||||
|
when(mockWriter.createApiUrl(demoProductId)).thenReturn(mockURL);
|
||||||
|
doCallRealMethod().when(mockWriter).sendPutRequest(any(), anyString());
|
||||||
|
HttpURLConnection mockConnection = mock(HttpURLConnection.class);
|
||||||
|
when(mockURL.openConnection()).thenReturn(mockConnection);
|
||||||
|
when(mockConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_OK);
|
||||||
|
when(mockWriter.getDataTarget()).thenReturn(Webshop.AMAZON);
|
||||||
|
|
||||||
|
assertDoesNotThrow(() -> {
|
||||||
|
mockWriter.sendPutRequest(dto, "Purchase");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void sendPutRequest_wrongDataTarget() {
|
||||||
|
ProductDTO dto = new ProductDTO(demoProductId, Webshop.EBAY);
|
||||||
|
|
||||||
|
DataWriterException e = assertThrows(DataWriterException.class, () -> {
|
||||||
|
writer.sendPutRequest(dto, demoProductId);
|
||||||
|
});
|
||||||
|
|
||||||
|
assertEquals("Product data source and target whateverId API are incompatible.", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package de.rwu.easydrop.api.client;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.Mockito.doCallRealMethod;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||||
|
import de.rwu.easydrop.model.Webshop;
|
||||||
|
|
||||||
|
class AbstractPurchaserTest {
|
||||||
|
private AbstractPurchaser mockPurchaser = mock(AbstractPurchaser.class);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void purchaseProduct_CorrectApiTypeInException() throws IOException {
|
||||||
|
// Set up DTO
|
||||||
|
ProductDTO dto = new ProductDTO("12345", Webshop.AMAZON);
|
||||||
|
|
||||||
|
// Set up mocks
|
||||||
|
URL mockURL = mock(URL.class);
|
||||||
|
when(mockPurchaser.createApiUrl("12345")).thenReturn(mockURL);
|
||||||
|
doCallRealMethod().when(mockPurchaser).purchaseProduct(any());
|
||||||
|
HttpURLConnection mockConnection = mock(HttpURLConnection.class);
|
||||||
|
when(mockURL.openConnection()).thenReturn(mockConnection);
|
||||||
|
when(mockConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_OK);
|
||||||
|
when(mockPurchaser.getDataTarget()).thenReturn(Webshop.AMAZON);
|
||||||
|
|
||||||
|
assertDoesNotThrow(() -> {
|
||||||
|
mockPurchaser.purchaseProduct(dto);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package de.rwu.easydrop.api.client;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.Mockito.doCallRealMethod;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||||
|
import de.rwu.easydrop.model.Webshop;
|
||||||
|
|
||||||
|
class AbstractSellerTest {
|
||||||
|
private AbstractSeller mockSeller = mock(AbstractSeller.class);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void purchaseProduct_CorrectApiTypeInException() throws IOException {
|
||||||
|
// Set up DTO
|
||||||
|
ProductDTO dto = new ProductDTO("12345", Webshop.AMAZON);
|
||||||
|
|
||||||
|
// Set up mocks
|
||||||
|
URL mockURL = mock(URL.class);
|
||||||
|
when(mockSeller.createApiUrl("12345")).thenReturn(mockURL);
|
||||||
|
doCallRealMethod().when(mockSeller).sellProduct(any());
|
||||||
|
HttpURLConnection mockConnection = mock(HttpURLConnection.class);
|
||||||
|
when(mockURL.openConnection()).thenReturn(mockConnection);
|
||||||
|
when(mockConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_OK);
|
||||||
|
when(mockSeller.getDataTarget()).thenReturn(Webshop.AMAZON);
|
||||||
|
|
||||||
|
assertDoesNotThrow(() -> {
|
||||||
|
mockSeller.sellProduct(dto);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,6 +21,7 @@ import org.mockito.MockitoAnnotations;
|
|||||||
|
|
||||||
import de.rwu.easydrop.api.dto.ProductDTO;
|
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||||
import de.rwu.easydrop.exception.DataSourceException;
|
import de.rwu.easydrop.exception.DataSourceException;
|
||||||
|
import de.rwu.easydrop.model.Webshop;
|
||||||
|
|
||||||
class AmazonProductDataSourceTest {
|
class AmazonProductDataSourceTest {
|
||||||
|
|
||||||
@@ -28,7 +29,7 @@ class AmazonProductDataSourceTest {
|
|||||||
|
|
||||||
private static String demoApiKey = "my-api-key";
|
private static String demoApiKey = "my-api-key";
|
||||||
private static String demoApiUrl = "https://www.example.com/api";
|
private static String demoApiUrl = "https://www.example.com/api";
|
||||||
private static String demoDataOrigin = "Amazon";
|
private static Webshop demoDataOrigin = Webshop.AMAZON;
|
||||||
private static String demoProductId = "whateverId";
|
private static String demoProductId = "whateverId";
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
@@ -138,7 +139,7 @@ class AmazonProductDataSourceTest {
|
|||||||
|
|
||||||
// Verify the product DTO properties
|
// Verify the product DTO properties
|
||||||
assertEquals(demoProductId, result.getProductId());
|
assertEquals(demoProductId, result.getProductId());
|
||||||
assertEquals("Amazon", result.getDataOrigin());
|
assertEquals(Webshop.AMAZON, result.getDataOrigin());
|
||||||
assertEquals(true, result.isAvailable());
|
assertEquals(true, result.isAvailable());
|
||||||
assertEquals(10.0, result.getCurrentPrice());
|
assertEquals(10.0, result.getCurrentPrice());
|
||||||
assertEquals(2.5, result.getDeliveryPrice());
|
assertEquals(2.5, result.getDeliveryPrice());
|
||||||
@@ -149,33 +150,60 @@ class AmazonProductDataSourceTest {
|
|||||||
void testGetProductDTOById_failedRequest() throws IOException {
|
void testGetProductDTOById_failedRequest() throws IOException {
|
||||||
// Set up the test environment
|
// Set up the test environment
|
||||||
|
|
||||||
AmazonProductDataSource dataSource = mock(AmazonProductDataSource.class);
|
AmazonProductDataSource DataSource = mock(AmazonProductDataSource.class);
|
||||||
URL mockURL = mock(URL.class);
|
URL mockURL = mock(URL.class);
|
||||||
when(dataSource.getDataOrigin()).thenReturn(demoDataOrigin);
|
when(DataSource.getDataOrigin()).thenReturn(demoDataOrigin);
|
||||||
when(dataSource.createApiUrl(demoProductId)).thenReturn(mockURL);
|
when(DataSource.createApiUrl(demoProductId)).thenReturn(mockURL);
|
||||||
when(dataSource.getProductDTOById(demoProductId)).thenCallRealMethod();
|
when(DataSource.getProductDTOById(demoProductId)).thenCallRealMethod();
|
||||||
HttpURLConnection mockConnection = mock(HttpURLConnection.class);
|
HttpURLConnection mockConnection = mock(HttpURLConnection.class);
|
||||||
when(mockURL.openConnection()).thenReturn(mockConnection);
|
when(mockURL.openConnection()).thenReturn(mockConnection);
|
||||||
when(mockConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_NOT_FOUND);
|
when(mockConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_NOT_FOUND);
|
||||||
|
|
||||||
// Invoke the method and verify the exception
|
// Invoke the method and verify the exception
|
||||||
DataSourceException exception = assertThrows(DataSourceException.class, () -> {
|
DataSourceException exception = assertThrows(DataSourceException.class, () -> {
|
||||||
dataSource.getProductDTOById(demoProductId);
|
DataSource.getProductDTOById(demoProductId);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Verify the exception message
|
// Verify the exception message
|
||||||
assertEquals("Nothing found: Amazon API responded with error code 404", exception.getMessage());
|
assertEquals("Nothing found: AMAZON API responded with error code 404", exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetProductDTOById_emptyResponse() throws IOException {
|
||||||
|
// Set up the test environment
|
||||||
|
String mockResponse = "";
|
||||||
|
|
||||||
|
AmazonProductDataSource dataSource = mock(AmazonProductDataSource.class);
|
||||||
|
URL mockURL = mock(URL.class);
|
||||||
|
when(dataSource.createApiUrl(demoProductId)).thenReturn(mockURL);
|
||||||
|
when(dataSource.buildProductDTO(any(), anyString())).thenCallRealMethod();
|
||||||
|
HttpURLConnection mockConnection = mock(HttpURLConnection.class);
|
||||||
|
when(mockURL.openConnection()).thenReturn(mockConnection);
|
||||||
|
when(mockConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_OK);
|
||||||
|
when(mockConnection.getInputStream()).thenReturn(new ByteArrayInputStream(mockResponse.getBytes()));
|
||||||
|
when(dataSource.getProductDTOById(demoProductId)).thenCallRealMethod();
|
||||||
|
|
||||||
|
// Invoke the method
|
||||||
|
ProductDTO result = dataSource.getProductDTOById(demoProductId);
|
||||||
|
|
||||||
|
// Verify the product DTO properties
|
||||||
|
assertEquals(demoProductId, result.getProductId());
|
||||||
|
assertEquals(Webshop.AMAZON, result.getDataOrigin());
|
||||||
|
assertEquals(false, result.isAvailable());
|
||||||
|
assertEquals(0.0, result.getCurrentPrice());
|
||||||
|
assertEquals(0.0, result.getDeliveryPrice());
|
||||||
|
assertEquals(null, result.getMerchant());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testGetProductDTOById_ioException() throws IOException {
|
void testGetProductDTOById_ioException() throws IOException {
|
||||||
// Set up the test environment
|
// Set up the test environment
|
||||||
AmazonProductDataSource dataSource = mock(AmazonProductDataSource.class);
|
AmazonProductDataSource DataSource = mock(AmazonProductDataSource.class);
|
||||||
URL mockURL = mock(URL.class);
|
URL mockURL = mock(URL.class);
|
||||||
when(dataSource.getDataOrigin()).thenReturn(demoDataOrigin);
|
when(DataSource.getDataOrigin()).thenReturn(demoDataOrigin);
|
||||||
when(dataSource.createApiUrl(demoProductId)).thenReturn(mockURL);
|
when(DataSource.createApiUrl(demoProductId)).thenReturn(mockURL);
|
||||||
when(dataSource.getProductDTOById(demoProductId)).thenCallRealMethod();
|
when(DataSource.getProductDTOById(demoProductId)).thenCallRealMethod();
|
||||||
when(dataSource.buildProductDTO(any(), anyString())).thenCallRealMethod();
|
when(DataSource.buildProductDTO(any(), anyString())).thenCallRealMethod();
|
||||||
HttpURLConnection mockConnection = mock(HttpURLConnection.class);
|
HttpURLConnection mockConnection = mock(HttpURLConnection.class);
|
||||||
when(mockURL.openConnection()).thenReturn(mockConnection);
|
when(mockURL.openConnection()).thenReturn(mockConnection);
|
||||||
when(mockConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_OK);
|
when(mockConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_OK);
|
||||||
@@ -183,16 +211,16 @@ class AmazonProductDataSourceTest {
|
|||||||
|
|
||||||
// Invoke the method and verify the exception
|
// Invoke the method and verify the exception
|
||||||
DataSourceException exception = assertThrows(DataSourceException.class, () -> {
|
DataSourceException exception = assertThrows(DataSourceException.class, () -> {
|
||||||
dataSource.getProductDTOById(demoProductId);
|
DataSource.getProductDTOById(demoProductId);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Verify the exception message
|
// Verify the exception message
|
||||||
assertEquals("Couldn't fulfill Amazon API request", exception.getMessage());
|
assertEquals("Couldn't fulfill AMAZON API request", exception.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void getDataOrigin_ReturnsExpectedDataOrigin() {
|
void getDataOrigin_ReturnsExpectedDataOrigin() {
|
||||||
String dataOrigin = demoDataSource.getDataOrigin();
|
Webshop dataOrigin = demoDataSource.getDataOrigin();
|
||||||
assertEquals(demoDataOrigin, dataOrigin);
|
assertEquals(demoDataOrigin, dataOrigin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
package de.rwu.easydrop.api.client;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.model.Webshop;
|
||||||
|
|
||||||
|
class AmazonPurchaserTest {
|
||||||
|
private AmazonPurchaser demoPurchaser;
|
||||||
|
|
||||||
|
private static String demoApiKey = "my-api-key";
|
||||||
|
private static String demoApiUrl = "https://www.example.com/api";
|
||||||
|
private static Webshop demoDataTarget = Webshop.AMAZON;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setup() {
|
||||||
|
demoPurchaser = new AmazonPurchaser(
|
||||||
|
demoApiUrl,
|
||||||
|
demoApiKey);
|
||||||
|
MockitoAnnotations.openMocks(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testConstructor() {
|
||||||
|
// Assert
|
||||||
|
try {
|
||||||
|
Field baseUrlField = AmazonPurchaser.class.getDeclaredField("baseUrl");
|
||||||
|
baseUrlField.setAccessible(true);
|
||||||
|
Assertions.assertEquals(demoApiUrl, baseUrlField.get(demoPurchaser));
|
||||||
|
|
||||||
|
Field apiKeyField = AmazonPurchaser.class.getDeclaredField("apiKey");
|
||||||
|
apiKeyField.setAccessible(true);
|
||||||
|
Assertions.assertEquals(demoApiKey, apiKeyField.get(demoPurchaser));
|
||||||
|
} catch (NoSuchFieldException e) {
|
||||||
|
Assertions.fail();
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
Assertions.fail();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCreateApiUrl() throws MalformedURLException {
|
||||||
|
// Test case 1
|
||||||
|
String productId1 = "12345";
|
||||||
|
URL expectedUrl1 = new URL(
|
||||||
|
"https://www.example.com/api/products/2020-08-26/products/"
|
||||||
|
+ productId1
|
||||||
|
+ "/buy?productRegion=DE&locale=de_DE");
|
||||||
|
URL createdUrl1 = demoPurchaser.createApiUrl(productId1);
|
||||||
|
Assertions.assertEquals(expectedUrl1, createdUrl1);
|
||||||
|
|
||||||
|
// Test case 2
|
||||||
|
String productId2 = "67890";
|
||||||
|
URL expectedUrl2 = new URL(
|
||||||
|
"https://www.example.com/api/products/2020-08-26/"
|
||||||
|
+ "products/"
|
||||||
|
+ productId2
|
||||||
|
+ "/buy?productRegion=DE&locale=de_DE");
|
||||||
|
URL createdUrl2 = demoPurchaser.createApiUrl(productId2);
|
||||||
|
Assertions.assertEquals(expectedUrl2, createdUrl2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getDataTarget_ReturnsExpectedDataOrigin() {
|
||||||
|
Webshop dataTarget = demoPurchaser.getDataTarget();
|
||||||
|
assertEquals(demoDataTarget, dataTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getApiKey_ReturnsExpectedApiKey() {
|
||||||
|
String apiKey = demoPurchaser.getApiKey();
|
||||||
|
assertEquals(demoApiKey, apiKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
package de.rwu.easydrop.api.client;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.model.Webshop;
|
||||||
|
|
||||||
|
class AmazonSellerTest {
|
||||||
|
private AmazonSeller demoSeller;
|
||||||
|
|
||||||
|
private static String demoApiKey = "my-api-key";
|
||||||
|
private static String demoApiUrl = "https://www.example.com/api";
|
||||||
|
private static Webshop demoDataTarget = Webshop.AMAZON;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setup() {
|
||||||
|
demoSeller = new AmazonSeller(
|
||||||
|
demoApiUrl,
|
||||||
|
demoApiKey);
|
||||||
|
MockitoAnnotations.openMocks(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testConstructor() {
|
||||||
|
// Assert
|
||||||
|
try {
|
||||||
|
Field baseUrlField = AmazonSeller.class.getDeclaredField("baseUrl");
|
||||||
|
baseUrlField.setAccessible(true);
|
||||||
|
Assertions.assertEquals(demoApiUrl, baseUrlField.get(demoSeller));
|
||||||
|
|
||||||
|
Field apiKeyField = AmazonSeller.class.getDeclaredField("apiKey");
|
||||||
|
apiKeyField.setAccessible(true);
|
||||||
|
Assertions.assertEquals(demoApiKey, apiKeyField.get(demoSeller));
|
||||||
|
} catch (NoSuchFieldException e) {
|
||||||
|
Assertions.fail();
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
Assertions.fail();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCreateApiUrl() throws MalformedURLException {
|
||||||
|
// Test case 1
|
||||||
|
String productId1 = "12345";
|
||||||
|
URL expectedUrl1 = new URL(
|
||||||
|
"https://www.example.com/api/products/2020-08-26/products/"
|
||||||
|
+ productId1
|
||||||
|
+ "/sell?productRegion=DE&locale=de_DE");
|
||||||
|
URL createdUrl1 = demoSeller.createApiUrl(productId1);
|
||||||
|
Assertions.assertEquals(expectedUrl1, createdUrl1);
|
||||||
|
|
||||||
|
// Test case 2
|
||||||
|
String productId2 = "67890";
|
||||||
|
URL expectedUrl2 = new URL(
|
||||||
|
"https://www.example.com/api/products/2020-08-26/"
|
||||||
|
+ "products/"
|
||||||
|
+ productId2
|
||||||
|
+ "/sell?productRegion=DE&locale=de_DE");
|
||||||
|
URL createdUrl2 = demoSeller.createApiUrl(productId2);
|
||||||
|
Assertions.assertEquals(expectedUrl2, createdUrl2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getDataTarget_ReturnsExpectedDataOrigin() {
|
||||||
|
Webshop dataTarget = demoSeller.getDataTarget();
|
||||||
|
assertEquals(demoDataTarget, dataTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getApiKey_ReturnsExpectedApiKey() {
|
||||||
|
String apiKey = demoSeller.getApiKey();
|
||||||
|
assertEquals(demoApiKey, apiKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
package de.rwu.easydrop.api.client;
|
package de.rwu.easydrop.api.client;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import javax.naming.ConfigurationException;
|
import javax.naming.ConfigurationException;
|
||||||
@@ -11,17 +9,14 @@ import org.junit.jupiter.api.BeforeEach;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
import org.sqlite.SQLiteDataSource;
|
|
||||||
|
|
||||||
import de.rwu.easydrop.data.connector.SQLiteConnector;
|
|
||||||
import de.rwu.easydrop.exception.PersistenceException;
|
|
||||||
import de.rwu.easydrop.util.Config;
|
import de.rwu.easydrop.util.Config;
|
||||||
|
|
||||||
class DataSourceFactoryTest {
|
class DataSourceFactoryTest {
|
||||||
@Mock
|
@Mock
|
||||||
private Config config;
|
private Config config;
|
||||||
|
|
||||||
private DataSourceFactory dataSourceFactory;
|
private DataSourceFactory DataSourceFactory;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setUp() throws ConfigurationException {
|
void setUp() throws ConfigurationException {
|
||||||
@@ -30,40 +25,24 @@ class DataSourceFactoryTest {
|
|||||||
when(config.getProperty("AMAZON_API_KEY")).thenReturn("amazon-api-key");
|
when(config.getProperty("AMAZON_API_KEY")).thenReturn("amazon-api-key");
|
||||||
when(config.getProperty("EBAY_API_URL")).thenReturn("https://api.ebay.com");
|
when(config.getProperty("EBAY_API_URL")).thenReturn("https://api.ebay.com");
|
||||||
when(config.getProperty("EBAY_API_KEY")).thenReturn("ebay-api-key");
|
when(config.getProperty("EBAY_API_KEY")).thenReturn("ebay-api-key");
|
||||||
dataSourceFactory = new DataSourceFactory(config);
|
DataSourceFactory = new DataSourceFactory(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void createAmazonProductDataSource_ReturnsAmazonProductDataSource() {
|
void createAmazonProductDataSource_ReturnsAmazonProductDataSource() {
|
||||||
// Act
|
// Act
|
||||||
AmazonProductDataSource dataSource = dataSourceFactory.createAmazonProductDataSource();
|
AmazonProductDataSource DataSource = DataSourceFactory.createAmazonProductDataSource();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assertEquals("amazon-api-key", dataSource.getApiKey());
|
assertEquals("amazon-api-key", DataSource.getApiKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void createEbayItemDataSource_ReturnsEbayItemDataSource() {
|
void createEbayItemDataSource_ReturnsEbayItemDataSource() {
|
||||||
// Act
|
// Act
|
||||||
EbayItemDataSource dataSource = dataSourceFactory.createEbayItemDataSource();
|
EbayItemDataSource DataSource = DataSourceFactory.createEbayItemDataSource();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assertEquals("ebay-api-key", dataSource.getApiKey());
|
assertEquals("ebay-api-key", DataSource.getApiKey());
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void createProductPersistenceDataSource_NullPersistence() {
|
|
||||||
PersistenceException exception = assertThrows(PersistenceException.class, () -> {
|
|
||||||
dataSourceFactory.createProductPersistenceDataSource();
|
|
||||||
});
|
|
||||||
|
|
||||||
assertEquals("Persistence is not set", exception.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void createProductPersistenceDataSource_WorkingPersistence() {
|
|
||||||
dataSourceFactory.setPersistence(new SQLiteConnector(new SQLiteDataSource()));
|
|
||||||
|
|
||||||
assertDoesNotThrow(() -> dataSourceFactory.createProductPersistenceDataSource());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,13 +19,14 @@ import org.mockito.MockitoAnnotations;
|
|||||||
|
|
||||||
import de.rwu.easydrop.api.dto.ProductDTO;
|
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||||
import de.rwu.easydrop.exception.DataSourceException;
|
import de.rwu.easydrop.exception.DataSourceException;
|
||||||
|
import de.rwu.easydrop.model.Webshop;
|
||||||
|
|
||||||
class EbayItemDataSourceTest {
|
class EbayItemDataSourceTest {
|
||||||
private EbayItemDataSource demoDataSource;
|
private EbayItemDataSource demoDataSource;
|
||||||
|
|
||||||
private static String demoApiKey = "my-api-key";
|
private static String demoApiKey = "my-api-key";
|
||||||
private static String demoApiUrl = "https://www.example.com/api";
|
private static String demoApiUrl = "https://www.example.com/api";
|
||||||
private static String demoDataOrigin = "eBay";
|
private static Webshop demoDataOrigin = Webshop.EBAY;
|
||||||
private static String demoQuery = "iPhone";
|
private static String demoQuery = "iPhone";
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
@@ -82,7 +83,7 @@ class EbayItemDataSourceTest {
|
|||||||
|
|
||||||
ProductDTO result = demoDataSource.buildProductDTO(product, json);
|
ProductDTO result = demoDataSource.buildProductDTO(product, json);
|
||||||
|
|
||||||
assertEquals("eBay", result.getDataOrigin());
|
assertEquals(Webshop.EBAY, result.getDataOrigin());
|
||||||
assertEquals(false, result.isAvailable()); // Default value for boolean
|
assertEquals(false, result.isAvailable()); // Default value for boolean
|
||||||
assertEquals(0.0, result.getCurrentPrice()); // Default value for double
|
assertEquals(0.0, result.getCurrentPrice()); // Default value for double
|
||||||
assertEquals(0.0, result.getDeliveryPrice()); // Default value for double
|
assertEquals(0.0, result.getDeliveryPrice()); // Default value for double
|
||||||
@@ -91,7 +92,7 @@ class EbayItemDataSourceTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void getDataOrigin_ReturnsExpectedDataOrigin() {
|
void getDataOrigin_ReturnsExpectedDataOrigin() {
|
||||||
String dataOrigin = demoDataSource.getDataOrigin();
|
Webshop dataOrigin = demoDataSource.getDataOrigin();
|
||||||
assertEquals(demoDataOrigin, dataOrigin);
|
assertEquals(demoDataOrigin, dataOrigin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,21 +106,21 @@ class EbayItemDataSourceTest {
|
|||||||
void testGetProductDTOById_failedRequest() throws IOException {
|
void testGetProductDTOById_failedRequest() throws IOException {
|
||||||
// Set up the test environment
|
// Set up the test environment
|
||||||
|
|
||||||
EbayItemDataSource dataSource = mock(EbayItemDataSource.class);
|
EbayItemDataSource DataSource = mock(EbayItemDataSource.class);
|
||||||
URL mockURL = mock(URL.class);
|
URL mockURL = mock(URL.class);
|
||||||
when(dataSource.getDataOrigin()).thenReturn(demoDataOrigin);
|
when(DataSource.getDataOrigin()).thenReturn(demoDataOrigin);
|
||||||
when(dataSource.createApiUrl(demoQuery)).thenReturn(mockURL);
|
when(DataSource.createApiUrl(demoQuery)).thenReturn(mockURL);
|
||||||
when(dataSource.getProductDTOById(demoQuery)).thenCallRealMethod();
|
when(DataSource.getProductDTOById(demoQuery)).thenCallRealMethod();
|
||||||
HttpURLConnection mockConnection = mock(HttpURLConnection.class);
|
HttpURLConnection mockConnection = mock(HttpURLConnection.class);
|
||||||
when(mockURL.openConnection()).thenReturn(mockConnection);
|
when(mockURL.openConnection()).thenReturn(mockConnection);
|
||||||
when(mockConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_NOT_FOUND);
|
when(mockConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_NOT_FOUND);
|
||||||
|
|
||||||
// Invoke the method and verify the exception
|
// Invoke the method and verify the exception
|
||||||
DataSourceException exception = assertThrows(DataSourceException.class, () -> {
|
DataSourceException exception = assertThrows(DataSourceException.class, () -> {
|
||||||
dataSource.getProductDTOById(demoQuery);
|
DataSource.getProductDTOById(demoQuery);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Verify the exception message
|
// Verify the exception message
|
||||||
assertEquals("Nothing found: eBay API responded with error code 404", exception.getMessage());
|
assertEquals("Nothing found: EBAY API responded with error code 404", exception.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
package de.rwu.easydrop.api.client;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.model.Webshop;
|
||||||
|
|
||||||
|
class EbayPurchaserTest {
|
||||||
|
private EbayPurchaser demoPurchaser;
|
||||||
|
|
||||||
|
private static String demoApiKey = "my-api-key";
|
||||||
|
private static String demoApiUrl = "https://www.example.com/api";
|
||||||
|
private static Webshop demoDataTarget = Webshop.EBAY;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setup() {
|
||||||
|
demoPurchaser = new EbayPurchaser(
|
||||||
|
demoApiUrl,
|
||||||
|
demoApiKey);
|
||||||
|
MockitoAnnotations.openMocks(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testConstructor() {
|
||||||
|
// Assert
|
||||||
|
try {
|
||||||
|
Field baseUrlField = EbayPurchaser.class.getDeclaredField("baseUrl");
|
||||||
|
baseUrlField.setAccessible(true);
|
||||||
|
Assertions.assertEquals(demoApiUrl, baseUrlField.get(demoPurchaser));
|
||||||
|
|
||||||
|
Field apiKeyField = EbayPurchaser.class.getDeclaredField("apiKey");
|
||||||
|
apiKeyField.setAccessible(true);
|
||||||
|
Assertions.assertEquals(demoApiKey, apiKeyField.get(demoPurchaser));
|
||||||
|
} catch (NoSuchFieldException e) {
|
||||||
|
Assertions.fail();
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
Assertions.fail();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCreateApiUrl() throws MalformedURLException {
|
||||||
|
// Test case 1
|
||||||
|
String productId1 = "12345";
|
||||||
|
URL expectedUrl1 = new URL(
|
||||||
|
"https://www.example.com/api/buy/"
|
||||||
|
+ productId1);
|
||||||
|
URL createdUrl1 = demoPurchaser.createApiUrl(productId1);
|
||||||
|
Assertions.assertEquals(expectedUrl1, createdUrl1);
|
||||||
|
|
||||||
|
// Test case 2
|
||||||
|
String productId2 = "67890";
|
||||||
|
URL expectedUrl2 = new URL(
|
||||||
|
"https://www.example.com/api/buy/"
|
||||||
|
+ productId2);
|
||||||
|
URL createdUrl2 = demoPurchaser.createApiUrl(productId2);
|
||||||
|
Assertions.assertEquals(expectedUrl2, createdUrl2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getDataTarget_ReturnsExpectedDataOrigin() {
|
||||||
|
Webshop dataTarget = demoPurchaser.getDataTarget();
|
||||||
|
assertEquals(demoDataTarget, dataTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getApiKey_ReturnsExpectedApiKey() {
|
||||||
|
String apiKey = demoPurchaser.getApiKey();
|
||||||
|
assertEquals(demoApiKey, apiKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
79
src/test/java/de/rwu/easydrop/api/client/EbaySellerTest.java
Normal file
79
src/test/java/de/rwu/easydrop/api/client/EbaySellerTest.java
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
package de.rwu.easydrop.api.client;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.model.Webshop;
|
||||||
|
|
||||||
|
class EbaySellerTest {
|
||||||
|
private EbaySeller demoSeller;
|
||||||
|
|
||||||
|
private static String demoApiKey = "my-api-key";
|
||||||
|
private static String demoApiUrl = "https://www.example.com/api";
|
||||||
|
private static Webshop demoDataTarget = Webshop.EBAY;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setup() {
|
||||||
|
demoSeller = new EbaySeller(
|
||||||
|
demoApiUrl,
|
||||||
|
demoApiKey);
|
||||||
|
MockitoAnnotations.openMocks(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testConstructor() {
|
||||||
|
// Assert
|
||||||
|
try {
|
||||||
|
Field baseUrlField = EbaySeller.class.getDeclaredField("baseUrl");
|
||||||
|
baseUrlField.setAccessible(true);
|
||||||
|
Assertions.assertEquals(demoApiUrl, baseUrlField.get(demoSeller));
|
||||||
|
|
||||||
|
Field apiKeyField = EbaySeller.class.getDeclaredField("apiKey");
|
||||||
|
apiKeyField.setAccessible(true);
|
||||||
|
Assertions.assertEquals(demoApiKey, apiKeyField.get(demoSeller));
|
||||||
|
} catch (NoSuchFieldException e) {
|
||||||
|
Assertions.fail();
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
Assertions.fail();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCreateApiUrl() throws MalformedURLException {
|
||||||
|
// Test case 1
|
||||||
|
String productId1 = "12345";
|
||||||
|
URL expectedUrl1 = new URL(
|
||||||
|
"https://www.example.com/api/sell/"
|
||||||
|
+ productId1);
|
||||||
|
URL createdUrl1 = demoSeller.createApiUrl(productId1);
|
||||||
|
Assertions.assertEquals(expectedUrl1, createdUrl1);
|
||||||
|
|
||||||
|
// Test case 2
|
||||||
|
String productId2 = "67890";
|
||||||
|
URL expectedUrl2 = new URL(
|
||||||
|
"https://www.example.com/api/sell/"
|
||||||
|
+ productId2);
|
||||||
|
URL createdUrl2 = demoSeller.createApiUrl(productId2);
|
||||||
|
Assertions.assertEquals(expectedUrl2, createdUrl2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getDataTarget_ReturnsExpectedDataOrigin() {
|
||||||
|
Webshop dataTarget = demoSeller.getDataTarget();
|
||||||
|
assertEquals(demoDataTarget, dataTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getApiKey_ReturnsExpectedApiKey() {
|
||||||
|
String apiKey = demoSeller.getApiKey();
|
||||||
|
assertEquals(demoApiKey, apiKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package de.rwu.easydrop.api.client;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.util.Config;
|
||||||
|
|
||||||
|
class PurchaserFactoryTest {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private Config mockConfig;
|
||||||
|
|
||||||
|
private PurchaserFactory purchaserFactory;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() throws ConfigurationException {
|
||||||
|
MockitoAnnotations.openMocks(this);
|
||||||
|
purchaserFactory = new PurchaserFactory(mockConfig);
|
||||||
|
purchaserFactory.setConfig(mockConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void createAmazonPurchaser_ValidConfig_ReturnsAmazonPurchaser() {
|
||||||
|
// Arrange
|
||||||
|
String amazonApiUrl = "amazon_api_url";
|
||||||
|
String amazonApiKey = "amazon_api_key";
|
||||||
|
|
||||||
|
when(mockConfig.getProperty("AMAZON_API_URL")).thenReturn(amazonApiUrl);
|
||||||
|
when(mockConfig.getProperty("AMAZON_API_KEY")).thenReturn(amazonApiKey);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
AmazonPurchaser amazonPurchaser = purchaserFactory.createAmazonPurchaser();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertNotNull(amazonPurchaser);
|
||||||
|
assertEquals(amazonApiKey, amazonPurchaser.getApiKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void createEbayPurchaser_ValidConfig_ReturnsEbayPurchaser() {
|
||||||
|
// Arrange
|
||||||
|
String ebayApiUrl = "ebay_api_url";
|
||||||
|
String ebayApiKey = "ebay_api_key";
|
||||||
|
|
||||||
|
when(mockConfig.getProperty("EBAY_API_URL")).thenReturn(ebayApiUrl);
|
||||||
|
when(mockConfig.getProperty("EBAY_API_KEY")).thenReturn(ebayApiKey);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
EbayPurchaser ebayPurchaser = purchaserFactory.createEbayPurchaser();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertNotNull(ebayPurchaser);
|
||||||
|
assertEquals(ebayApiKey, ebayPurchaser.getApiKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package de.rwu.easydrop.api.client;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.util.Config;
|
||||||
|
|
||||||
|
class SellerFactoryTest {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private Config mockConfig;
|
||||||
|
|
||||||
|
private SellerFactory sellerFactory;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() throws ConfigurationException {
|
||||||
|
MockitoAnnotations.openMocks(this);
|
||||||
|
sellerFactory = new SellerFactory(mockConfig);
|
||||||
|
sellerFactory.setConfig(mockConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void createAmazonSeller_ValidConfig_ReturnsAmazonSeller() {
|
||||||
|
// Arrange
|
||||||
|
String amazonApiUrl = "amazon_api_url";
|
||||||
|
String amazonApiKey = "amazon_api_key";
|
||||||
|
|
||||||
|
when(mockConfig.getProperty("AMAZON_API_URL")).thenReturn(amazonApiUrl);
|
||||||
|
when(mockConfig.getProperty("AMAZON_API_KEY")).thenReturn(amazonApiKey);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
AmazonSeller amazonSeller = sellerFactory.createAmazonSeller();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertNotNull(amazonSeller);
|
||||||
|
assertEquals(amazonApiKey, amazonSeller.getApiKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void createEbaySeller_ValidConfig_ReturnsEbaySeller() {
|
||||||
|
// Arrange
|
||||||
|
String ebayApiUrl = "ebay_api_url";
|
||||||
|
String ebayApiKey = "ebay_api_key";
|
||||||
|
|
||||||
|
when(mockConfig.getProperty("EBAY_API_URL")).thenReturn(ebayApiUrl);
|
||||||
|
when(mockConfig.getProperty("EBAY_API_KEY")).thenReturn(ebayApiKey);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
EbaySeller ebaySeller = sellerFactory.createEbaySeller();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertNotNull(ebaySeller);
|
||||||
|
assertEquals(ebayApiKey, ebaySeller.getApiKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,13 +6,15 @@ import static org.junit.jupiter.api.Assertions.assertNull;
|
|||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.model.Webshop;
|
||||||
|
|
||||||
class ProductDTOTest {
|
class ProductDTOTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void constructor_SetsProductIdAndDataOrigin() {
|
void constructor_SetsProductIdAndDataOrigin() {
|
||||||
// Arrange
|
// Arrange
|
||||||
String productId = "12345";
|
String productId = "12345";
|
||||||
String dataOrigin = "Amazon";
|
Webshop dataOrigin = Webshop.AMAZON;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
ProductDTO productDTO = new ProductDTO(productId, dataOrigin);
|
ProductDTO productDTO = new ProductDTO(productId, dataOrigin);
|
||||||
@@ -25,19 +27,19 @@ class ProductDTOTest {
|
|||||||
@Test
|
@Test
|
||||||
void gettersAndSetters_WorkAsExpected() {
|
void gettersAndSetters_WorkAsExpected() {
|
||||||
// Arrange
|
// Arrange
|
||||||
ProductDTO productDTO = new ProductDTO("12345", "Amazon");
|
ProductDTO productDTO = new ProductDTO("12345", Webshop.AMAZON);
|
||||||
|
|
||||||
// Act and Assert
|
// Act and Assert
|
||||||
assertEquals("12345", productDTO.getProductId());
|
assertEquals("12345", productDTO.getProductId());
|
||||||
assertEquals("Amazon", productDTO.getDataOrigin());
|
assertEquals(Webshop.AMAZON, productDTO.getDataOrigin());
|
||||||
|
|
||||||
// Modify fields
|
// Modify fields
|
||||||
productDTO.setProductId("54321");
|
productDTO.setProductId("54321");
|
||||||
productDTO.setDataOrigin("eBay");
|
productDTO.setDataOrigin(Webshop.EBAY);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assertEquals("54321", productDTO.getProductId());
|
assertEquals("54321", productDTO.getProductId());
|
||||||
assertEquals("eBay", productDTO.getDataOrigin());
|
assertEquals(Webshop.EBAY, productDTO.getDataOrigin());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -8,45 +8,51 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
|||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import static org.junit.jupiter.api.Assertions.fail;
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
import static org.mockito.Mockito.doThrow;
|
import static org.mockito.Mockito.doThrow;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.TestInstance;
|
|
||||||
import org.junit.jupiter.api.TestInstance.Lifecycle;
|
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
import org.sqlite.SQLiteDataSource;
|
import org.sqlite.SQLiteDataSource;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.api.dto.OfferDTO;
|
||||||
import de.rwu.easydrop.api.dto.ProductDTO;
|
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||||
|
import de.rwu.easydrop.api.dto.TransactionDTO;
|
||||||
import de.rwu.easydrop.exception.PersistenceException;
|
import de.rwu.easydrop.exception.PersistenceException;
|
||||||
|
import de.rwu.easydrop.model.Webshop;
|
||||||
|
|
||||||
@TestInstance(Lifecycle.PER_CLASS)
|
|
||||||
class SQLiteConnectorTest {
|
class SQLiteConnectorTest {
|
||||||
private static final String TEST_PRODUCT_ID = "12345";
|
private static final String TEST_PRODUCT_ID = "12345";
|
||||||
private SQLiteConnector sqliteConnector;
|
private SQLiteConnector sqliteConnector = new SQLiteConnector(new SQLiteDataSource());
|
||||||
|
@Mock
|
||||||
|
private Connection connection;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private PreparedStatement statement;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private ResultSet resultSet;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private SQLiteDataSource mockDataSource;
|
private SQLiteDataSource mockDataSource;
|
||||||
|
|
||||||
@BeforeAll
|
|
||||||
public void setup() {
|
|
||||||
sqliteConnector = new SQLiteConnector(new SQLiteDataSource());
|
|
||||||
}
|
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void clearDatabase() {
|
public void prepare() {
|
||||||
MockitoAnnotations.openMocks(this);
|
MockitoAnnotations.openMocks(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void saveProduct_ValidProduct_SuccessfullySaved() {
|
void writeProduct_ValidProduct_SuccessfullySaved() {
|
||||||
// Arrange
|
// Arrange
|
||||||
sqliteConnector.clearData();
|
sqliteConnector.clearData();
|
||||||
ProductDTO ProductDTO = new ProductDTO(TEST_PRODUCT_ID, "Amazon");
|
ProductDTO ProductDTO = new ProductDTO(TEST_PRODUCT_ID, Webshop.AMAZON);
|
||||||
ProductDTO.setDataOrigin("Amazon");
|
ProductDTO.setDataOrigin(Webshop.AMAZON);
|
||||||
ProductDTO.setProductId(TEST_PRODUCT_ID);
|
ProductDTO.setProductId(TEST_PRODUCT_ID);
|
||||||
ProductDTO.setCurrentPrice(9.99);
|
ProductDTO.setCurrentPrice(9.99);
|
||||||
ProductDTO.setMerchant("Sample Merchant");
|
ProductDTO.setMerchant("Sample Merchant");
|
||||||
@@ -54,12 +60,12 @@ class SQLiteConnectorTest {
|
|||||||
ProductDTO.setAvailable(true);
|
ProductDTO.setAvailable(true);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
assertDoesNotThrow(() -> sqliteConnector.saveProduct(ProductDTO));
|
assertDoesNotThrow(() -> sqliteConnector.writeProduct(ProductDTO));
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
ProductDTO savedProductDTO = sqliteConnector.getProductDTOById(TEST_PRODUCT_ID);
|
ProductDTO savedProductDTO = sqliteConnector.getProductDTOById(TEST_PRODUCT_ID);
|
||||||
assertNotNull(savedProductDTO);
|
assertNotNull(savedProductDTO);
|
||||||
assertEquals("Amazon", savedProductDTO.getDataOrigin());
|
assertEquals(Webshop.AMAZON, savedProductDTO.getDataOrigin());
|
||||||
assertEquals(TEST_PRODUCT_ID, savedProductDTO.getProductId());
|
assertEquals(TEST_PRODUCT_ID, savedProductDTO.getProductId());
|
||||||
assertEquals(9.99, savedProductDTO.getCurrentPrice());
|
assertEquals(9.99, savedProductDTO.getCurrentPrice());
|
||||||
assertEquals("Sample Merchant", savedProductDTO.getMerchant());
|
assertEquals("Sample Merchant", savedProductDTO.getMerchant());
|
||||||
@@ -78,7 +84,7 @@ class SQLiteConnectorTest {
|
|||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assertNotNull(ProductDTO);
|
assertNotNull(ProductDTO);
|
||||||
assertEquals("Amazon", ProductDTO.getDataOrigin());
|
assertEquals(Webshop.AMAZON, ProductDTO.getDataOrigin());
|
||||||
assertEquals(TEST_PRODUCT_ID, ProductDTO.getProductId());
|
assertEquals(TEST_PRODUCT_ID, ProductDTO.getProductId());
|
||||||
assertEquals(9.99, ProductDTO.getCurrentPrice());
|
assertEquals(9.99, ProductDTO.getCurrentPrice());
|
||||||
assertEquals("Sample Merchant", ProductDTO.getMerchant());
|
assertEquals("Sample Merchant", ProductDTO.getMerchant());
|
||||||
@@ -111,14 +117,14 @@ class SQLiteConnectorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void saveProduct_ThrowsPersistenceException_OnSQLException() throws SQLException {
|
void writeProduct_ThrowsPersistenceException_OnSQLException() throws SQLException {
|
||||||
// Arrange
|
// Arrange
|
||||||
ProductDTO ProductDTO = new ProductDTO(TEST_PRODUCT_ID, "Amazon");
|
ProductDTO ProductDTO = new ProductDTO(TEST_PRODUCT_ID, Webshop.AMAZON);
|
||||||
sqliteConnector.setDb(mockDataSource);
|
sqliteConnector.setDb(mockDataSource);
|
||||||
doThrow(SQLException.class).when(mockDataSource).getConnection();
|
doThrow(SQLException.class).when(mockDataSource).getConnection();
|
||||||
|
|
||||||
// Act and Assert
|
// Act and Assert
|
||||||
assertThrows(PersistenceException.class, () -> sqliteConnector.saveProduct(ProductDTO));
|
assertThrows(PersistenceException.class, () -> sqliteConnector.writeProduct(ProductDTO));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -143,53 +149,179 @@ class SQLiteConnectorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void insertSampleProduct() {
|
private void insertSampleProduct() {
|
||||||
ProductDTO ProductDTO = new ProductDTO(TEST_PRODUCT_ID, "Amazon");
|
ProductDTO productDTO = new ProductDTO(TEST_PRODUCT_ID, Webshop.AMAZON);
|
||||||
ProductDTO.setCurrentPrice(9.99);
|
productDTO.setCurrentPrice(9.99);
|
||||||
ProductDTO.setMerchant("Sample Merchant");
|
productDTO.setMerchant("Sample Merchant");
|
||||||
ProductDTO.setDeliveryPrice(2.50);
|
productDTO.setDeliveryPrice(2.50);
|
||||||
ProductDTO.setAvailable(true);
|
productDTO.setAvailable(true);
|
||||||
sqliteConnector.saveProduct(ProductDTO);
|
sqliteConnector.writeProduct(productDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void insertSampleOffer() {
|
||||||
|
ProductDTO p1 = new ProductDTO("p1", Webshop.AMAZON);
|
||||||
|
p1.setCurrentPrice(123f);
|
||||||
|
|
||||||
|
ProductDTO p2 = new ProductDTO("p2", Webshop.EBAY);
|
||||||
|
p2.setCurrentPrice(234f);
|
||||||
|
|
||||||
|
OfferDTO dto = new OfferDTO();
|
||||||
|
dto.setOfferId("123");
|
||||||
|
dto.setLastUpdate("2020-01-01 00:00:00");
|
||||||
|
dto.setSourceProduct(p1);
|
||||||
|
dto.setTargetProduct(p2);
|
||||||
|
sqliteConnector.writeOffer(dto);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void insertSampleTransaction() {
|
||||||
|
TransactionDTO dto = new TransactionDTO();
|
||||||
|
dto.setOfferId("123");
|
||||||
|
dto.setEarnings(12f);
|
||||||
|
dto.setVolume(123f);
|
||||||
|
dto.setTransactionTime("2020-01-01 00:00:00");
|
||||||
|
sqliteConnector.writeTX(dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void getDataOrigin_ReturnsCorrectDataOrigin() {
|
void outputTransactionsToLog_NothingThrown() {
|
||||||
|
insertSampleTransaction();
|
||||||
|
|
||||||
|
assertDoesNotThrow(() -> {
|
||||||
|
sqliteConnector.outputTransactionsToLog();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void outputSummaryToLog_NothingThrown() {
|
||||||
|
insertSampleTransaction();
|
||||||
|
|
||||||
|
assertDoesNotThrow(() -> {
|
||||||
|
sqliteConnector.outputSummaryToLog();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void outputTransactionsToLog_ThrowsPersistenceException_OnSQLException() throws SQLException {
|
||||||
// Arrange
|
// Arrange
|
||||||
SQLiteConnector connector = new SQLiteConnector(new SQLiteDataSource());
|
sqliteConnector.setDb(mockDataSource);
|
||||||
|
doThrow(SQLException.class).when(mockDataSource).getConnection();
|
||||||
|
|
||||||
|
// Act and Assert
|
||||||
|
PersistenceException e = assertThrows(PersistenceException.class,
|
||||||
|
() -> sqliteConnector.outputTransactionsToLog());
|
||||||
|
assertEquals("Something went wrong while reading transaction from SQLite", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void outputSummaryToLog_ThrowsPersistenceException_OnSQLException() throws SQLException {
|
||||||
|
// Arrange
|
||||||
|
sqliteConnector.setDb(mockDataSource);
|
||||||
|
doThrow(SQLException.class).when(mockDataSource).getConnection();
|
||||||
|
|
||||||
|
// Act and Assert
|
||||||
|
PersistenceException e = assertThrows(PersistenceException.class,
|
||||||
|
() -> sqliteConnector.outputSummaryToLog());
|
||||||
|
assertEquals("Something went wrong while reading transaction summary from SQLite", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void deleteOfferById_SuccessfulDelete() {
|
||||||
|
// Arrange
|
||||||
|
sqliteConnector.clearData();
|
||||||
|
insertSampleOffer();
|
||||||
|
|
||||||
|
// Make sure it's there
|
||||||
|
assertEquals(1, sqliteConnector.getOffers().size());
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
String dataOrigin = connector.getDataOrigin();
|
sqliteConnector.deleteOfferById("123");
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assertEquals("SQLite", dataOrigin);
|
assertEquals(0, sqliteConnector.getOffers().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void getApiKey_UnsupportedOperationExceptionThrown() {
|
void deleteOfferById_ThrowsPersistenceException_OnSQLException() throws SQLException {
|
||||||
// Arrange
|
sqliteConnector.setDb(mockDataSource);
|
||||||
SQLiteConnector connector = new SQLiteConnector(new SQLiteDataSource());
|
doThrow(SQLException.class).when(mockDataSource).getConnection();
|
||||||
|
|
||||||
// Act and Assert
|
// Act and Assert
|
||||||
assertThrows(UnsupportedOperationException.class, connector::getApiKey);
|
PersistenceException e = assertThrows(PersistenceException.class,
|
||||||
|
() -> sqliteConnector.deleteOfferById("123"));
|
||||||
|
assertEquals("Something went wrong while deleting offer from SQLite", e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void buildProductDTO_UnsupportedOperationExceptionThrown() {
|
void getOffers_ReturnsCorrectValues() {
|
||||||
// Arrange
|
sqliteConnector.clearData();
|
||||||
SQLiteConnector connector = new SQLiteConnector(new SQLiteDataSource());
|
assertEquals(0, sqliteConnector.getOffers().size());
|
||||||
ProductDTO product = new ProductDTO("ASIN123", "Amazon");
|
|
||||||
String json = "{\"productId\":\"ASIN123\",\"dataOrigin\":\"Amazon\"}";
|
|
||||||
|
|
||||||
// Act and Assert
|
insertSampleOffer();
|
||||||
assertThrows(UnsupportedOperationException.class, () -> connector.buildProductDTO(product, json));
|
|
||||||
|
assertEquals(1, sqliteConnector.getOffers().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void createApiUrl_UnsupportedOperationExceptionThrown() {
|
void getOffers_ThrowsPersistenceException_OnSQLException() throws SQLException {
|
||||||
// Arrange
|
sqliteConnector.setDb(mockDataSource);
|
||||||
SQLiteConnector connector = new SQLiteConnector(new SQLiteDataSource());
|
doThrow(SQLException.class).when(mockDataSource).getConnection();
|
||||||
String productIdentifier = "ASIN123";
|
|
||||||
|
|
||||||
// Act and Assert
|
// Act and Assert
|
||||||
assertThrows(UnsupportedOperationException.class, () -> connector.createApiUrl(productIdentifier));
|
PersistenceException e = assertThrows(PersistenceException.class,
|
||||||
|
() -> sqliteConnector.getOffers());
|
||||||
|
assertEquals("Something went wrong while reading offers from SQLite", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeOffer_ValidDTO_DataSavedToDatabase() throws SQLException {
|
||||||
|
// Arrange
|
||||||
|
OfferDTO offerDTO = new OfferDTO();
|
||||||
|
offerDTO.setOfferId("123");
|
||||||
|
offerDTO.setSourceProduct(new ProductDTO(TEST_PRODUCT_ID, Webshop.AMAZON));
|
||||||
|
offerDTO.setTargetProduct(new ProductDTO(TEST_PRODUCT_ID, Webshop.AMAZON));
|
||||||
|
|
||||||
|
String expectedQuery = "INSERT INTO offers (offerId, sourceWebshop, sourceId, sourcePrice, " +
|
||||||
|
"targetWebshop, targetId, targetPrice, lastupdate) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
|
||||||
|
|
||||||
|
when(connection.prepareStatement(expectedQuery)).thenReturn(statement);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
assertDoesNotThrow(() -> sqliteConnector.writeOffer(offerDTO));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeTX_NothingThrown() {
|
||||||
|
TransactionDTO dto = new TransactionDTO();
|
||||||
|
|
||||||
|
assertDoesNotThrow(() -> {
|
||||||
|
sqliteConnector.writeTX(dto);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeTX_ThrowsPersistenceException_OnSQLException() throws SQLException {
|
||||||
|
// Arrange
|
||||||
|
sqliteConnector.setDb(mockDataSource);
|
||||||
|
doThrow(SQLException.class).when(mockDataSource).getConnection();
|
||||||
|
TransactionDTO dto = new TransactionDTO();
|
||||||
|
|
||||||
|
// Act and Assert
|
||||||
|
PersistenceException e = assertThrows(PersistenceException.class,
|
||||||
|
() -> sqliteConnector.writeTX(dto));
|
||||||
|
assertEquals("Something went wrong while saving transaction to SQLite", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getOfferDTOById_OfferExists_ReturnsProductDTO() {
|
||||||
|
// Arrange
|
||||||
|
sqliteConnector.clearData();
|
||||||
|
insertSampleOffer();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
OfferDTO offerDTO = sqliteConnector.getOfferDTOById("123");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertNotNull(offerDTO);
|
||||||
|
assertEquals("123", offerDTO.getOfferId());
|
||||||
|
assertEquals("2020-01-01 00:00:00", offerDTO.getLastUpdate());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package de.rwu.easydrop.exception;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class DataWriterExceptionTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void constructor_WithMessage_SetsMessage() {
|
||||||
|
// Arrange
|
||||||
|
String message = "Data source error";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
DataWriterException exception = new DataWriterException(message);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertEquals(message, exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void constructor_WithMessageAndCause_SetsMessageAndCause() {
|
||||||
|
// Arrange
|
||||||
|
String message = "Data source error";
|
||||||
|
Throwable cause = new IllegalArgumentException("Invalid argument");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
DataWriterException exception = new DataWriterException(message, cause);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertEquals(message, exception.getMessage());
|
||||||
|
assertEquals(cause, exception.getCause());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void constructor_WithNullMessage_SetsNullMessage() {
|
||||||
|
// Act
|
||||||
|
DataWriterException exception = new DataWriterException(null);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertEquals(null, exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void constructor_WithNullCause_SetsNullCause() {
|
||||||
|
// Act
|
||||||
|
DataWriterException exception = new DataWriterException("Data source error", null);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertEquals(null, exception.getCause());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void throw_DataWriterException() {
|
||||||
|
// Act and Assert
|
||||||
|
assertThrows(DataWriterException.class, () -> {
|
||||||
|
throw new DataWriterException("Data source error");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package de.rwu.easydrop.exception;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class InvalidCatalogueExceptionTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testConstructorWithMessage_ExceptionWithMessageCreated() {
|
||||||
|
// Arrange
|
||||||
|
String message = "Invalid catalogue";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
InvalidCatalogueException exception = new InvalidCatalogueException(message);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assertions.assertEquals(message, exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testConstructorWithMessageAndCause_ExceptionWithMessageAndCauseCreated() {
|
||||||
|
// Arrange
|
||||||
|
String message = "Invalid catalogue";
|
||||||
|
Throwable cause = new RuntimeException("Cause exception");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
InvalidCatalogueException exception = new InvalidCatalogueException(message, cause);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assertions.assertEquals(message, exception.getMessage());
|
||||||
|
Assertions.assertEquals(cause, exception.getCause());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package de.rwu.easydrop.exception;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class InvalidOfferExceptionTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void constructor_WithMessage_SetsMessage() {
|
||||||
|
// Arrange
|
||||||
|
String message = "Invalid Offer data";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
InvalidOfferException exception = new InvalidOfferException(message);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertEquals(message, exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void constructor_WithMessageAndCause_SetsMessageAndCause() {
|
||||||
|
// Arrange
|
||||||
|
String message = "Invalid Offer data";
|
||||||
|
Throwable cause = new IllegalArgumentException("Invalid argument");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
InvalidOfferException exception = new InvalidOfferException(message, cause);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertEquals(message, exception.getMessage());
|
||||||
|
assertEquals(cause, exception.getCause());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void constructor_WithNullMessage_SetsNullMessage() {
|
||||||
|
// Act
|
||||||
|
InvalidOfferException exception = new InvalidOfferException(null);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertEquals(null, exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void constructor_WithNullCause_SetsNullCause() {
|
||||||
|
// Act
|
||||||
|
InvalidOfferException exception = new InvalidOfferException("Invalid Offer data", null);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertEquals(null, exception.getCause());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void throw_InvalidOfferException() {
|
||||||
|
// Act and Assert
|
||||||
|
assertThrows(InvalidOfferException.class, () -> {
|
||||||
|
throw new InvalidOfferException("Invalid Offer data");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package de.rwu.easydrop.exception;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class InvalidTransactionExceptionTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void constructor_WithMessage_SetsMessage() {
|
||||||
|
// Arrange
|
||||||
|
String message = "Invalid Transaction data";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
InvalidTransactionException exception = new InvalidTransactionException(message);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertEquals(message, exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void constructor_WithMessageAndCause_SetsMessageAndCause() {
|
||||||
|
// Arrange
|
||||||
|
String message = "Invalid Transaction data";
|
||||||
|
Throwable cause = new IllegalArgumentException("Invalid argument");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
InvalidTransactionException exception = new InvalidTransactionException(message, cause);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertEquals(message, exception.getMessage());
|
||||||
|
assertEquals(cause, exception.getCause());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void constructor_WithNullMessage_SetsNullMessage() {
|
||||||
|
// Act
|
||||||
|
InvalidTransactionException exception = new InvalidTransactionException(null);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertEquals(null, exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void constructor_WithNullCause_SetsNullCause() {
|
||||||
|
// Act
|
||||||
|
InvalidTransactionException exception = new InvalidTransactionException("Invalid Transaction data", null);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertEquals(null, exception.getCause());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void throw_InvalidTransactionException() {
|
||||||
|
// Act and Assert
|
||||||
|
assertThrows(InvalidTransactionException.class, () -> {
|
||||||
|
throw new InvalidTransactionException("Invalid Transaction data");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
package de.rwu.easydrop.model;
|
package de.rwu.easydrop.model;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
@@ -19,7 +21,7 @@ class ProductCatalogueTest {
|
|||||||
Product product = new Product();
|
Product product = new Product();
|
||||||
product.setProductId("12345");
|
product.setProductId("12345");
|
||||||
product.setMerchant("AmazonSeller");
|
product.setMerchant("AmazonSeller");
|
||||||
product.setDataOrigin("Amazon");
|
product.setDataOrigin(Webshop.AMAZON);
|
||||||
productCatalogue.addProduct(product);
|
productCatalogue.addProduct(product);
|
||||||
|
|
||||||
List<Product> products = productCatalogue.getProducts();
|
List<Product> products = productCatalogue.getProducts();
|
||||||
@@ -32,13 +34,13 @@ class ProductCatalogueTest {
|
|||||||
Product product1 = new Product();
|
Product product1 = new Product();
|
||||||
product1.setProductId("12345");
|
product1.setProductId("12345");
|
||||||
product1.setMerchant("AmazonSeller");
|
product1.setMerchant("AmazonSeller");
|
||||||
product1.setDataOrigin("Amazon");
|
product1.setDataOrigin(Webshop.AMAZON);
|
||||||
productCatalogue.addProduct(product1);
|
productCatalogue.addProduct(product1);
|
||||||
|
|
||||||
Product product2 = new Product();
|
Product product2 = new Product();
|
||||||
product2.setProductId("54321");
|
product2.setProductId("54321");
|
||||||
product2.setMerchant("eBaySeller");
|
product2.setMerchant("eBaySeller");
|
||||||
product2.setDataOrigin("eBay");
|
product2.setDataOrigin(Webshop.EBAY);
|
||||||
productCatalogue.addProduct(product2);
|
productCatalogue.addProduct(product2);
|
||||||
|
|
||||||
productCatalogue.removeProduct(product1);
|
productCatalogue.removeProduct(product1);
|
||||||
@@ -53,13 +55,13 @@ class ProductCatalogueTest {
|
|||||||
Product product1 = new Product();
|
Product product1 = new Product();
|
||||||
product1.setProductId("12345");
|
product1.setProductId("12345");
|
||||||
product1.setMerchant("AmazonSeller");
|
product1.setMerchant("AmazonSeller");
|
||||||
product1.setDataOrigin("Amazon");
|
product1.setDataOrigin(Webshop.AMAZON);
|
||||||
productCatalogue.addProduct(product1);
|
productCatalogue.addProduct(product1);
|
||||||
|
|
||||||
Product product2 = new Product();
|
Product product2 = new Product();
|
||||||
product2.setProductId("54321");
|
product2.setProductId("54321");
|
||||||
product2.setMerchant("eBay");
|
product2.setMerchant("ebayMerchant");
|
||||||
product2.setDataOrigin("eBay");
|
product2.setDataOrigin(Webshop.EBAY);
|
||||||
productCatalogue.addProduct(product2);
|
productCatalogue.addProduct(product2);
|
||||||
|
|
||||||
productCatalogue.clearProducts();
|
productCatalogue.clearProducts();
|
||||||
@@ -73,20 +75,23 @@ class ProductCatalogueTest {
|
|||||||
Product product1 = new Product();
|
Product product1 = new Product();
|
||||||
product1.setProductId("12345");
|
product1.setProductId("12345");
|
||||||
product1.setMerchant("AmazonSeller");
|
product1.setMerchant("AmazonSeller");
|
||||||
product1.setDataOrigin("Amazon");
|
product1.setDataOrigin(Webshop.AMAZON);
|
||||||
productCatalogue.addProduct(product1);
|
productCatalogue.addProduct(product1);
|
||||||
|
|
||||||
Product product2 = new Product();
|
Product product2 = new Product();
|
||||||
product2.setProductId("54321");
|
product2.setProductId("54321");
|
||||||
product2.setMerchant("eBaySeller");
|
product2.setMerchant("eBaySeller");
|
||||||
product2.setDataOrigin("eBay");
|
product2.setDataOrigin(Webshop.EBAY);
|
||||||
productCatalogue.addProduct(product2);
|
productCatalogue.addProduct(product2);
|
||||||
|
|
||||||
String expectedString = "Product Catalogue: GPU\n" +
|
StringBuilder sb = new StringBuilder();
|
||||||
"Description: Graphics Processing Units\n" +
|
sb.append(String.format("Catalogue Name: %s%n", "GPU"));
|
||||||
"Products:\n" +
|
sb.append(String.format("Description: %s%n", "Graphics Processing Units"));
|
||||||
"Product: [12345 from AmazonSeller (Amazon) at 0,00 € (available: no)]\n" +
|
sb.append("Products:\n");
|
||||||
"Product: [54321 from eBaySeller (eBay) at 0,00 € (available: no)]\n";
|
sb.append(String.format("%s%n", product1.toString()));
|
||||||
|
sb.append(String.format("%s%n", product2.toString()));
|
||||||
|
|
||||||
|
String expectedString = sb.toString();
|
||||||
|
|
||||||
Assertions.assertEquals(expectedString, productCatalogue.toString());
|
Assertions.assertEquals(expectedString, productCatalogue.toString());
|
||||||
}
|
}
|
||||||
|
|||||||
25
src/test/java/de/rwu/easydrop/model/ProductPairTest.java
Normal file
25
src/test/java/de/rwu/easydrop/model/ProductPairTest.java
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package de.rwu.easydrop.model;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class ProductPairTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void constructor_TwoProducts_ProductsInitializedCorrectly() {
|
||||||
|
// Arrange
|
||||||
|
Product product1 = new Product();
|
||||||
|
product1.setProductId("123");
|
||||||
|
|
||||||
|
Product product2 = new Product();
|
||||||
|
product2.setProductId("234");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
ProductPair pair = new ProductPair(product1, product2);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertSame(product1, pair.getProduct1());
|
||||||
|
assertSame(product2, pair.getProduct2());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,13 +10,13 @@ class ProductTest {
|
|||||||
@Test
|
@Test
|
||||||
void testToString1() {
|
void testToString1() {
|
||||||
Product product1 = new Product();
|
Product product1 = new Product();
|
||||||
product1.setDataOrigin("Amazon");
|
product1.setDataOrigin(Webshop.AMAZON);
|
||||||
product1.setProductId("12345");
|
product1.setProductId("12345");
|
||||||
product1.setMerchant("Merchant A");
|
product1.setMerchant("Merchant A");
|
||||||
product1.setCurrentPrice(19.99);
|
product1.setCurrentPrice(19.99);
|
||||||
product1.setAvailable(true);
|
product1.setAvailable(true);
|
||||||
|
|
||||||
String expectedString1 = "Product: [12345 from Merchant A (Amazon) at 19,99 € (available: yes)]";
|
String expectedString1 = "Product: [12345 from Merchant A (AMAZON) at 19,99 Euro (available: yes)]";
|
||||||
String result1 = product1.toString();
|
String result1 = product1.toString();
|
||||||
|
|
||||||
assertEquals(expectedString1, result1);
|
assertEquals(expectedString1, result1);
|
||||||
@@ -25,13 +25,13 @@ class ProductTest {
|
|||||||
@Test
|
@Test
|
||||||
void testToString2() {
|
void testToString2() {
|
||||||
Product product2 = new Product();
|
Product product2 = new Product();
|
||||||
product2.setDataOrigin("eBay");
|
product2.setDataOrigin(Webshop.EBAY);
|
||||||
product2.setProductId("67890");
|
product2.setProductId("67890");
|
||||||
product2.setMerchant("Merchant B");
|
product2.setMerchant("Merchant B");
|
||||||
product2.setCurrentPrice(9.99);
|
product2.setCurrentPrice(9.99);
|
||||||
product2.setAvailable(false);
|
product2.setAvailable(false);
|
||||||
|
|
||||||
String expectedString2 = "Product: [67890 from Merchant B (eBay) at 9,99 € (available: no)]";
|
String expectedString2 = "Product: [67890 from Merchant B (EBAY) at 9,99 Euro (available: no)]";
|
||||||
String result2 = product2.toString();
|
String result2 = product2.toString();
|
||||||
|
|
||||||
assertEquals(expectedString2, result2);
|
assertEquals(expectedString2, result2);
|
||||||
@@ -41,7 +41,7 @@ class ProductTest {
|
|||||||
void gettersAndSetters_WorkAsExpected() {
|
void gettersAndSetters_WorkAsExpected() {
|
||||||
// Arrange
|
// Arrange
|
||||||
Product product = new Product();
|
Product product = new Product();
|
||||||
product.setDataOrigin("Amazon");
|
product.setDataOrigin(Webshop.AMAZON);
|
||||||
product.setProductId("12345");
|
product.setProductId("12345");
|
||||||
product.setCurrentPrice(9.99);
|
product.setCurrentPrice(9.99);
|
||||||
product.setMerchant("Example Merchant");
|
product.setMerchant("Example Merchant");
|
||||||
@@ -49,7 +49,7 @@ class ProductTest {
|
|||||||
product.setAvailable(true);
|
product.setAvailable(true);
|
||||||
|
|
||||||
// Act and Assert
|
// Act and Assert
|
||||||
assertEquals("Amazon", product.getDataOrigin());
|
assertEquals(Webshop.AMAZON, product.getDataOrigin());
|
||||||
assertEquals("12345", product.getProductId());
|
assertEquals("12345", product.getProductId());
|
||||||
assertEquals(9.99, product.getCurrentPrice());
|
assertEquals(9.99, product.getCurrentPrice());
|
||||||
assertEquals("Example Merchant", product.getMerchant());
|
assertEquals("Example Merchant", product.getMerchant());
|
||||||
@@ -57,7 +57,7 @@ class ProductTest {
|
|||||||
assertTrue(product.isAvailable());
|
assertTrue(product.isAvailable());
|
||||||
|
|
||||||
// Modify fields
|
// Modify fields
|
||||||
product.setDataOrigin("eBay");
|
product.setDataOrigin(Webshop.EBAY);
|
||||||
product.setProductId("54321");
|
product.setProductId("54321");
|
||||||
product.setCurrentPrice(19.99);
|
product.setCurrentPrice(19.99);
|
||||||
product.setMerchant("New Merchant");
|
product.setMerchant("New Merchant");
|
||||||
@@ -65,7 +65,7 @@ class ProductTest {
|
|||||||
product.setAvailable(false);
|
product.setAvailable(false);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assertEquals("eBay", product.getDataOrigin());
|
assertEquals(Webshop.EBAY, product.getDataOrigin());
|
||||||
assertEquals("54321", product.getProductId());
|
assertEquals("54321", product.getProductId());
|
||||||
assertEquals(19.99, product.getCurrentPrice());
|
assertEquals(19.99, product.getCurrentPrice());
|
||||||
assertEquals("New Merchant", product.getMerchant());
|
assertEquals("New Merchant", product.getMerchant());
|
||||||
|
|||||||
23
src/test/java/de/rwu/easydrop/model/WebshopTest.java
Normal file
23
src/test/java/de/rwu/easydrop/model/WebshopTest.java
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package de.rwu.easydrop.model;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class WebshopTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testFromString_returnsIntendedConstant() {
|
||||||
|
Webshop testShop = Webshop.fromString("Amazon");
|
||||||
|
|
||||||
|
assertEquals(Webshop.AMAZON, testShop);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testFromString_invalidShop() {
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> {
|
||||||
|
Webshop.fromString("thisdoesnotexist");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package de.rwu.easydrop.service.mapping;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.api.dto.OfferDTO;
|
||||||
|
import de.rwu.easydrop.model.Offer;
|
||||||
|
import de.rwu.easydrop.model.Product;
|
||||||
|
import de.rwu.easydrop.model.Webshop;
|
||||||
|
|
||||||
|
class OfferMapperTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testConstructorIsPrivate()
|
||||||
|
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
|
||||||
|
// Check for private constructor
|
||||||
|
Constructor<OfferMapper> constructor = OfferMapper.class.getDeclaredConstructor();
|
||||||
|
assertTrue(Modifier.isPrivate(constructor.getModifiers()));
|
||||||
|
|
||||||
|
// Make sure exception is thrown when instantiating
|
||||||
|
constructor.setAccessible(true);
|
||||||
|
assertThrows(InvocationTargetException.class, () -> {
|
||||||
|
constructor.newInstance();
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void mapOfferToDTO() {
|
||||||
|
// Arrange
|
||||||
|
Product product = new Product();
|
||||||
|
product.setProductId("12345");
|
||||||
|
product.setDataOrigin(Webshop.AMAZON);
|
||||||
|
product.setAvailable(true);
|
||||||
|
product.setCurrentPrice(9.99);
|
||||||
|
product.setDeliveryPrice(2.50);
|
||||||
|
product.setMerchant("Seller1");
|
||||||
|
|
||||||
|
Offer offer = new Offer();
|
||||||
|
offer.setOfferId("68735");
|
||||||
|
offer.setLastUpdate("2020-07-07");
|
||||||
|
offer.setSourceProduct(product);
|
||||||
|
offer.setTargetProduct(product);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
OfferDTO dto = OfferMapper.mapOfferToDTO(offer);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertEquals("68735", dto.getOfferId());
|
||||||
|
assertEquals("2020-07-07", dto.getLastUpdate());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@ import org.junit.jupiter.api.Test;
|
|||||||
import de.rwu.easydrop.api.dto.ProductDTO;
|
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||||
|
|
||||||
import de.rwu.easydrop.model.Product;
|
import de.rwu.easydrop.model.Product;
|
||||||
|
import de.rwu.easydrop.model.Webshop;
|
||||||
|
|
||||||
class ProductMapperTest {
|
class ProductMapperTest {
|
||||||
@Test
|
@Test
|
||||||
@@ -47,7 +48,7 @@ class ProductMapperTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ProductDTO createProductDTO() {
|
private ProductDTO createProductDTO() {
|
||||||
ProductDTO dto = new ProductDTO("12345", "Amazon");
|
ProductDTO dto = new ProductDTO("12345", Webshop.AMAZON);
|
||||||
dto.setAvailable(true);
|
dto.setAvailable(true);
|
||||||
dto.setCurrentPrice(9.99);
|
dto.setCurrentPrice(9.99);
|
||||||
dto.setDeliveryPrice(2.50);
|
dto.setDeliveryPrice(2.50);
|
||||||
@@ -60,7 +61,7 @@ class ProductMapperTest {
|
|||||||
// Arrange
|
// Arrange
|
||||||
Product product = new Product();
|
Product product = new Product();
|
||||||
product.setProductId("12345");
|
product.setProductId("12345");
|
||||||
product.setDataOrigin("Amazon");
|
product.setDataOrigin(Webshop.AMAZON);
|
||||||
product.setAvailable(true);
|
product.setAvailable(true);
|
||||||
product.setCurrentPrice(9.99);
|
product.setCurrentPrice(9.99);
|
||||||
product.setDeliveryPrice(2.50);
|
product.setDeliveryPrice(2.50);
|
||||||
@@ -71,7 +72,7 @@ class ProductMapperTest {
|
|||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assertEquals("12345", dto.getProductId());
|
assertEquals("12345", dto.getProductId());
|
||||||
assertEquals("Amazon", dto.getDataOrigin());
|
assertEquals(Webshop.AMAZON, dto.getDataOrigin());
|
||||||
assertTrue(dto.isAvailable());
|
assertTrue(dto.isAvailable());
|
||||||
assertEquals(9.99, dto.getCurrentPrice());
|
assertEquals(9.99, dto.getCurrentPrice());
|
||||||
assertEquals(2.50, dto.getDeliveryPrice());
|
assertEquals(2.50, dto.getDeliveryPrice());
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package de.rwu.easydrop.service.mapping;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.api.dto.TransactionDTO;
|
||||||
|
import de.rwu.easydrop.model.Transaction;
|
||||||
|
|
||||||
|
class TransactionMapperTest {
|
||||||
|
@Test
|
||||||
|
void testConstructorIsPrivate()
|
||||||
|
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
|
||||||
|
// Check for private constructor
|
||||||
|
Constructor<TransactionMapper> constructor = TransactionMapper.class.getDeclaredConstructor();
|
||||||
|
assertTrue(Modifier.isPrivate(constructor.getModifiers()));
|
||||||
|
|
||||||
|
// Make sure exception is thrown when instantiating
|
||||||
|
constructor.setAccessible(true);
|
||||||
|
assertThrows(InvocationTargetException.class, () -> {
|
||||||
|
constructor.newInstance();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void mapTXFromDTO_WithValidTransactionDTO_ReturnsTransaction() {
|
||||||
|
// Arrange
|
||||||
|
TransactionDTO transactionDTO = new TransactionDTO();
|
||||||
|
transactionDTO.setOfferId("123");
|
||||||
|
transactionDTO.setVolume(10.0);
|
||||||
|
transactionDTO.setEarnings(5.0);
|
||||||
|
transactionDTO.setTransactionTime("2023-06-25 03:26:59");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
Transaction transaction = TransactionMapper.mapTXFromDTO(transactionDTO);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertNotNull(transaction);
|
||||||
|
assertEquals(transactionDTO.getOfferId(), transaction.getOfferId());
|
||||||
|
assertEquals(transactionDTO.getVolume(), transaction.getVolume());
|
||||||
|
assertEquals(transactionDTO.getEarnings(), transaction.getEarnings());
|
||||||
|
assertEquals(transactionDTO.getTransactionTime(), transaction.getTransactionTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void mapTXToDTO_WithValidTransaction_ReturnsTransactionDTO() {
|
||||||
|
// Arrange
|
||||||
|
Transaction transaction = new Transaction();
|
||||||
|
transaction.setOfferId("123");
|
||||||
|
transaction.setVolume(10.0);
|
||||||
|
transaction.setEarnings(5.0);
|
||||||
|
transaction.setTransactionTime("2023-06-25 03:26:59");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
TransactionDTO transactionDTO = TransactionMapper.mapTXToDTO(transaction);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertNotNull(transactionDTO);
|
||||||
|
assertEquals(transaction.getOfferId(), transactionDTO.getOfferId());
|
||||||
|
assertEquals(transaction.getVolume(), transactionDTO.getVolume());
|
||||||
|
assertEquals(transaction.getEarnings(), transactionDTO.getEarnings());
|
||||||
|
assertEquals(transaction.getTransactionTime(), transactionDTO.getTransactionTime());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,176 @@
|
|||||||
|
package de.rwu.easydrop.service.processing;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
class OfferIdentifierTest {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private ProductCatalogue mockProductCatalogue;
|
||||||
|
|
||||||
|
private OfferIdentifier offerIdentifier;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
MockitoAnnotations.openMocks(this);
|
||||||
|
|
||||||
|
offerIdentifier = new OfferIdentifier();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void runIdentifier_WithValidProductCatalogues_IdentifiesOffers() {
|
||||||
|
// Arrange
|
||||||
|
List<ProductCatalogue> productCatalogues = new ArrayList<>();
|
||||||
|
ProductCatalogue productCatalogue1 = new ProductCatalogue("Catalogue1", "desc");
|
||||||
|
ProductCatalogue productCatalogue2 = new ProductCatalogue("Catalogue2", "desc");
|
||||||
|
|
||||||
|
Product product1 = new Product();
|
||||||
|
product1.setCurrentPrice(100.0);
|
||||||
|
Product product2 = new Product();
|
||||||
|
product2.setCurrentPrice(200.0);
|
||||||
|
Product product3 = new Product();
|
||||||
|
product3.setCurrentPrice(300.0);
|
||||||
|
Product product4 = new Product();
|
||||||
|
product4.setCurrentPrice(400.0);
|
||||||
|
|
||||||
|
productCatalogue1.addProduct(product1);
|
||||||
|
productCatalogue1.addProduct(product2);
|
||||||
|
productCatalogue2.addProduct(product3);
|
||||||
|
productCatalogue2.addProduct(product4);
|
||||||
|
|
||||||
|
productCatalogues.add(productCatalogue1);
|
||||||
|
productCatalogues.add(productCatalogue2);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
List<Offer> identifiedOffers = offerIdentifier.runIdentifier(productCatalogues);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertEquals(2, identifiedOffers.size());
|
||||||
|
assertNotNull(identifiedOffers.get(0).getSourceProduct());
|
||||||
|
assertNotNull(identifiedOffers.get(0).getTargetProduct());
|
||||||
|
assertNotNull(identifiedOffers.get(1).getSourceProduct());
|
||||||
|
assertNotNull(identifiedOffers.get(1).getTargetProduct());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void runIdentifier_WithOneGoodOneBadCatalogue_BadOneIsntIncluded() {
|
||||||
|
// Arrange
|
||||||
|
List<ProductCatalogue> productCatalogues = new ArrayList<>();
|
||||||
|
ProductCatalogue productCatalogue1 = new ProductCatalogue("Catalogue1", "desc");
|
||||||
|
ProductCatalogue productCatalogue2 = new ProductCatalogue("Catalogue2", "desc");
|
||||||
|
|
||||||
|
Product product1 = new Product();
|
||||||
|
product1.setCurrentPrice(100.0);
|
||||||
|
Product product2 = new Product();
|
||||||
|
product2.setCurrentPrice(200.0);
|
||||||
|
Product product3 = new Product();
|
||||||
|
product3.setCurrentPrice(300.0);
|
||||||
|
Product product4 = new Product();
|
||||||
|
product4.setCurrentPrice(300.0);
|
||||||
|
|
||||||
|
productCatalogue1.addProduct(product1);
|
||||||
|
productCatalogue1.addProduct(product2);
|
||||||
|
productCatalogue2.addProduct(product3);
|
||||||
|
productCatalogue2.addProduct(product4);
|
||||||
|
|
||||||
|
productCatalogues.add(productCatalogue1);
|
||||||
|
productCatalogues.add(productCatalogue2);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
List<Offer> identifiedOffers = offerIdentifier.runIdentifier(productCatalogues);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertEquals(1, identifiedOffers.size()); // Only 1 passed
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getHighestMarginProducts_WithValidProductCatalogue_ReturnsProductPair() {
|
||||||
|
// Arrange
|
||||||
|
ProductCatalogue productCatalogue = new ProductCatalogue("TestCatalogue", "desc");
|
||||||
|
Product product1 = new Product();
|
||||||
|
product1.setCurrentPrice(100.0);
|
||||||
|
Product product2 = new Product();
|
||||||
|
product2.setCurrentPrice(200.0);
|
||||||
|
productCatalogue.addProduct(product1);
|
||||||
|
productCatalogue.addProduct(product2);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
ProductPair productPair = OfferIdentifier.getHighestMarginProducts(productCatalogue);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertNotNull(productPair);
|
||||||
|
assertNotNull(productPair.getProduct1());
|
||||||
|
assertNotNull(productPair.getProduct2());
|
||||||
|
assertNotEquals(productPair.getProduct1(), productPair.getProduct2());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getHighestMarginProducts_SecondProductCheaper() {
|
||||||
|
// Arrange
|
||||||
|
ProductCatalogue productCatalogue = new ProductCatalogue("TestCatalogue", "desc");
|
||||||
|
Product product1 = new Product();
|
||||||
|
product1.setCurrentPrice(200.0);
|
||||||
|
Product product2 = new Product();
|
||||||
|
product2.setCurrentPrice(100.0);
|
||||||
|
productCatalogue.addProduct(product1);
|
||||||
|
productCatalogue.addProduct(product2);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
ProductPair productPair = OfferIdentifier.getHighestMarginProducts(productCatalogue);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertNotNull(productPair);
|
||||||
|
assertNotNull(productPair.getProduct1());
|
||||||
|
assertNotNull(productPair.getProduct2());
|
||||||
|
assertNotEquals(productPair.getProduct1(), productPair.getProduct2());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getHighestMarginProducts_WithCatalogueSizeLessThan2_ThrowsInvalidCatalogueException() {
|
||||||
|
// Arrange
|
||||||
|
ProductCatalogue productCatalogue = new ProductCatalogue("SmallCatalogue", "desc");
|
||||||
|
|
||||||
|
// Act and Assert
|
||||||
|
assertThrows(InvalidCatalogueException.class, () -> {
|
||||||
|
OfferIdentifier.getHighestMarginProducts(productCatalogue);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getHighestMarginProducts_WithZeroPriceMargin_ThrowsInvalidOfferException() {
|
||||||
|
// Arrange
|
||||||
|
ProductCatalogue productCatalogue = new ProductCatalogue("name", "desc");
|
||||||
|
Product product1 = new Product();
|
||||||
|
product1.setCurrentPrice(200.0);
|
||||||
|
|
||||||
|
Product product2 = new Product();
|
||||||
|
product2.setCurrentPrice(200.0);
|
||||||
|
|
||||||
|
productCatalogue.getProducts().add(product1);
|
||||||
|
productCatalogue.getProducts().add(product2);
|
||||||
|
|
||||||
|
// Act and Assert
|
||||||
|
InvalidOfferException e = assertThrows(InvalidOfferException.class, () -> {
|
||||||
|
OfferIdentifier.getHighestMarginProducts(productCatalogue);
|
||||||
|
});
|
||||||
|
|
||||||
|
assertEquals("Price margin is zero!", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
package de.rwu.easydrop.service.processing;
|
||||||
|
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.api.client.AmazonPurchaser;
|
||||||
|
import de.rwu.easydrop.api.client.AmazonSeller;
|
||||||
|
import de.rwu.easydrop.api.client.EbayPurchaser;
|
||||||
|
import de.rwu.easydrop.api.client.EbaySeller;
|
||||||
|
import de.rwu.easydrop.api.client.PurchaserFactory;
|
||||||
|
import de.rwu.easydrop.api.client.SellerFactory;
|
||||||
|
import de.rwu.easydrop.data.connector.OfferPersistenceInterface;
|
||||||
|
import de.rwu.easydrop.model.Offer;
|
||||||
|
import de.rwu.easydrop.model.Product;
|
||||||
|
import de.rwu.easydrop.model.Webshop;
|
||||||
|
import de.rwu.easydrop.service.writer.OfferWriter;
|
||||||
|
|
||||||
|
class OfferProvisionerTest {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private OfferPersistenceInterface mockPersistence;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private SellerFactory mockSellerFactory;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private PurchaserFactory mockPurchaserFactory;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private OfferWriter mockOfferWriter;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private AmazonSeller mockAmazonSeller;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private EbaySeller mockEbaySeller;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private AmazonPurchaser mockAmazonPurchaser;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private EbayPurchaser mockEbayPurchaser;
|
||||||
|
|
||||||
|
private OfferProvisioner offerProvisioner;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
MockitoAnnotations.openMocks(this);
|
||||||
|
|
||||||
|
when(mockSellerFactory.createAmazonSeller()).thenReturn(mockAmazonSeller);
|
||||||
|
when(mockSellerFactory.createEbaySeller()).thenReturn(mockEbaySeller);
|
||||||
|
when(mockPurchaserFactory.createAmazonPurchaser()).thenReturn(mockAmazonPurchaser);
|
||||||
|
when(mockPurchaserFactory.createEbayPurchaser()).thenReturn(mockEbayPurchaser);
|
||||||
|
|
||||||
|
offerProvisioner = new OfferProvisioner(mockPersistence, mockSellerFactory, mockPurchaserFactory);
|
||||||
|
offerProvisioner.setOfferWriter(mockOfferWriter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void runProvisioner_WithValidOffers_PlacesOrders() {
|
||||||
|
// Arrange
|
||||||
|
List<Offer> offers = new ArrayList<>();
|
||||||
|
Offer offer1 = createOffer(Webshop.AMAZON, "ASIN123", Webshop.EBAY, "12345");
|
||||||
|
Offer offer2 = createOffer(Webshop.EBAY, "54321", Webshop.AMAZON, "ASIN456");
|
||||||
|
offers.add(offer1);
|
||||||
|
offers.add(offer2);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
offerProvisioner.runProvisioner(offers);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
verify(mockAmazonSeller, times(1)).sellProduct(any());
|
||||||
|
verify(mockEbaySeller, times(1)).sellProduct(any());
|
||||||
|
verify(mockAmazonPurchaser, times(1)).purchaseProduct(any());
|
||||||
|
verify(mockEbayPurchaser, times(1)).purchaseProduct(any());
|
||||||
|
verify(mockOfferWriter, times(2)).writeOfferToPersistence(any());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Offer createOffer(Webshop sourceWebshop, String sourceProductId, Webshop targetWebshop,
|
||||||
|
String targetProductId) {
|
||||||
|
Product sourceProduct = new Product();
|
||||||
|
sourceProduct.setDataOrigin(sourceWebshop);
|
||||||
|
sourceProduct.setProductId(sourceProductId);
|
||||||
|
|
||||||
|
Product targetProduct = new Product();
|
||||||
|
targetProduct.setDataOrigin(targetWebshop);
|
||||||
|
targetProduct.setProductId(targetProductId);
|
||||||
|
|
||||||
|
Offer offer = new Offer();
|
||||||
|
offer.setSourceProduct(sourceProduct);
|
||||||
|
offer.setTargetProduct(targetProduct);
|
||||||
|
|
||||||
|
return offer;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package de.rwu.easydrop.service.processing;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.api.dto.TransactionDTO;
|
||||||
|
import de.rwu.easydrop.data.connector.TransactionPersistenceInterface;
|
||||||
|
import de.rwu.easydrop.model.Offer;
|
||||||
|
import de.rwu.easydrop.model.Product;
|
||||||
|
import de.rwu.easydrop.model.Transaction;
|
||||||
|
import de.rwu.easydrop.service.mapping.TransactionMapper;
|
||||||
|
|
||||||
|
class TransactionHandlerTest {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private TransactionPersistenceInterface mockPersistence;
|
||||||
|
|
||||||
|
public TransactionHandlerTest() {
|
||||||
|
MockitoAnnotations.openMocks(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void turnOfferToTransaction_ValidOffer_TransactionCreatedAndWrittenToPersistence() {
|
||||||
|
// Arrange
|
||||||
|
Offer offer = new Offer();
|
||||||
|
Product product = new Product();
|
||||||
|
offer.setSourceProduct(product);
|
||||||
|
offer.setTargetProduct(product);
|
||||||
|
|
||||||
|
TransactionHandler handler = new TransactionHandler(mockPersistence);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
handler.turnOfferToTransaction(offer);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
ArgumentCaptor<TransactionDTO> transactionDtoCaptor = ArgumentCaptor.forClass(TransactionDTO.class);
|
||||||
|
verify(mockPersistence, times(1)).writeTX(transactionDtoCaptor.capture());
|
||||||
|
|
||||||
|
TransactionDTO capturedTransactionDto = transactionDtoCaptor.getValue();
|
||||||
|
Transaction capturedTransaction = TransactionMapper.mapTXFromDTO(capturedTransactionDto);
|
||||||
|
|
||||||
|
assertEquals(offer.getOfferId(), capturedTransaction.getOfferId());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
package de.rwu.easydrop.service.retriever;
|
package de.rwu.easydrop.service.retriever;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
@@ -14,9 +13,9 @@ import javax.naming.ConfigurationException;
|
|||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import de.rwu.easydrop.exception.InvalidProductException;
|
|
||||||
import de.rwu.easydrop.model.Product;
|
import de.rwu.easydrop.model.Product;
|
||||||
import de.rwu.easydrop.model.ProductCatalogue;
|
import de.rwu.easydrop.model.ProductCatalogue;
|
||||||
|
import de.rwu.easydrop.model.Webshop;
|
||||||
import de.rwu.easydrop.util.ProductsConfig;
|
import de.rwu.easydrop.util.ProductsConfig;
|
||||||
|
|
||||||
class CatalogueRetrieverTest {
|
class CatalogueRetrieverTest {
|
||||||
@@ -39,20 +38,20 @@ class CatalogueRetrieverTest {
|
|||||||
// Create a sample product catalogue with two products
|
// Create a sample product catalogue with two products
|
||||||
ProductCatalogue productCatalogue = new ProductCatalogue("Catalogue 1", "Sample catalogue");
|
ProductCatalogue productCatalogue = new ProductCatalogue("Catalogue 1", "Sample catalogue");
|
||||||
Product product1 = new Product();
|
Product product1 = new Product();
|
||||||
product1.setDataOrigin("Amazon");
|
product1.setDataOrigin(Webshop.AMAZON);
|
||||||
product1.setProductId("ASIN1");
|
product1.setProductId("ASIN1");
|
||||||
productCatalogue.addProduct(product1);
|
productCatalogue.addProduct(product1);
|
||||||
|
|
||||||
Product product2 = new Product();
|
Product product2 = new Product();
|
||||||
product2.setDataOrigin("eBay");
|
product2.setDataOrigin(Webshop.EBAY);
|
||||||
product2.setProductId("ProductID2");
|
product2.setProductId("ProductID2");
|
||||||
productCatalogue.addProduct(product2);
|
productCatalogue.addProduct(product2);
|
||||||
productCatalogues.add(productCatalogue);
|
productCatalogues.add(productCatalogue);
|
||||||
|
|
||||||
// Mock the methods
|
// Mock the methods
|
||||||
when(productsConfig.getProductCatalogues()).thenReturn(productCatalogues);
|
when(productsConfig.getProductCatalogues()).thenReturn(productCatalogues);
|
||||||
when(productRetriever.getProductFromAmazon("ASIN1")).thenReturn(product1);
|
when(productRetriever.getProductFromWebshop(Webshop.AMAZON, "ASIN1")).thenReturn(product1);
|
||||||
when(productRetriever.getProductFromEbay("ProductID2")).thenReturn(product2);
|
when(productRetriever.getProductFromWebshop(Webshop.EBAY, "ProductID2")).thenReturn(product2);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
catalogueRetriever.loadCatalogues();
|
catalogueRetriever.loadCatalogues();
|
||||||
@@ -71,33 +70,7 @@ class CatalogueRetrieverTest {
|
|||||||
|
|
||||||
// Verify the method invocations
|
// Verify the method invocations
|
||||||
verify(productsConfig).loadConfig();
|
verify(productsConfig).loadConfig();
|
||||||
verify(productRetriever).getProductFromAmazon("ASIN1");
|
verify(productRetriever).getProductFromWebshop(Webshop.AMAZON, "ASIN1");
|
||||||
verify(productRetriever).getProductFromEbay("ProductID2");
|
verify(productRetriever).getProductFromWebshop(Webshop.EBAY, "ProductID2");
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void loadCatalogues_ValidConfig_CataloguesLoaded_InvalidProduct() throws ConfigurationException {
|
|
||||||
// Arrange
|
|
||||||
List<ProductCatalogue> productCatalogues = new ArrayList<>();
|
|
||||||
|
|
||||||
// Create a sample product catalogue
|
|
||||||
ProductCatalogue productCatalogue = new ProductCatalogue("Catalogue 1", "Sample catalogue");
|
|
||||||
|
|
||||||
Product product = new Product();
|
|
||||||
product.setDataOrigin("");
|
|
||||||
product.setProductId("ProductID1");
|
|
||||||
productCatalogue.addProduct(product);
|
|
||||||
productCatalogues.add(productCatalogue);
|
|
||||||
|
|
||||||
// Mock the methods
|
|
||||||
when(productsConfig.getProductCatalogues()).thenReturn(productCatalogues);
|
|
||||||
when(productRetriever.getProductFromAmazon("ProductID1")).thenReturn(product);
|
|
||||||
|
|
||||||
// Act and Assert
|
|
||||||
InvalidProductException exception = assertThrows(InvalidProductException.class, () -> {
|
|
||||||
catalogueRetriever.loadCatalogues();
|
|
||||||
});
|
|
||||||
|
|
||||||
assertEquals("Product data origin is invalid", exception.getMessage());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
package de.rwu.easydrop.service.retriever;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
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.OfferDTO;
|
||||||
|
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||||
|
import de.rwu.easydrop.data.connector.OfferPersistenceInterface;
|
||||||
|
import de.rwu.easydrop.model.Offer;
|
||||||
|
import de.rwu.easydrop.util.Config;
|
||||||
|
|
||||||
|
|
||||||
|
class OfferRetrieverTest {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private Config config;
|
||||||
|
@Mock
|
||||||
|
private DataSourceFactory dataSourceFactory;
|
||||||
|
@Mock
|
||||||
|
private AmazonProductDataSource amazonDataSource;
|
||||||
|
@Mock
|
||||||
|
private EbayItemDataSource ebayDataSource;
|
||||||
|
@Mock
|
||||||
|
private OfferDTO offerDTO;
|
||||||
|
@Mock
|
||||||
|
private Offer offer;
|
||||||
|
@Mock
|
||||||
|
private OfferPersistenceInterface persistence;
|
||||||
|
|
||||||
|
private OfferRetriever offerRetriever;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() throws ConfigurationException {
|
||||||
|
MockitoAnnotations.openMocks(this);
|
||||||
|
when(config.getProperty("AMAZON_API_URL")).thenReturn("https://api.amazon.com");
|
||||||
|
when(config.getProperty("AMAZON_API_KEY")).thenReturn("amazon-api-key");
|
||||||
|
dataSourceFactory.setConfig(config);
|
||||||
|
offerRetriever = new OfferRetriever(persistence);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getOfferFromPersistence(){
|
||||||
|
|
||||||
|
//Mock ProductDTO object to return from the offerDTO mock
|
||||||
|
ProductDTO productDTO = mock(ProductDTO.class);
|
||||||
|
when(productDTO.isAvailable()).thenReturn(true);
|
||||||
|
|
||||||
|
//Arrange
|
||||||
|
String offerId = "187";
|
||||||
|
String lastUpdate = "2023-01-01";
|
||||||
|
when(persistence.getOfferDTOById(offerId)).thenReturn(offerDTO);
|
||||||
|
when(offerDTO.getOfferId()).thenReturn(offerId);
|
||||||
|
when(offerDTO.getLastUpdate()).thenReturn(lastUpdate);
|
||||||
|
when(offerDTO.getSourceProduct()).thenReturn(productDTO);
|
||||||
|
when(offerDTO.getTargetProduct()).thenReturn(productDTO);
|
||||||
|
|
||||||
|
//Act
|
||||||
|
Offer result = offerRetriever.getOfferFromPersistence(offerId);
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
assertEquals(offerId, result.getOfferId());
|
||||||
|
assertEquals(lastUpdate, result.getLastUpdate());
|
||||||
|
|
||||||
|
//Verify
|
||||||
|
verify(persistence, times(1)).getOfferDTOById(offerId);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,6 +2,8 @@ package de.rwu.easydrop.service.retriever;
|
|||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
@@ -17,8 +19,9 @@ import de.rwu.easydrop.api.client.AmazonProductDataSource;
|
|||||||
import de.rwu.easydrop.api.client.DataSourceFactory;
|
import de.rwu.easydrop.api.client.DataSourceFactory;
|
||||||
import de.rwu.easydrop.api.client.EbayItemDataSource;
|
import de.rwu.easydrop.api.client.EbayItemDataSource;
|
||||||
import de.rwu.easydrop.api.dto.ProductDTO;
|
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.Product;
|
||||||
|
import de.rwu.easydrop.model.Webshop;
|
||||||
import de.rwu.easydrop.util.Config;
|
import de.rwu.easydrop.util.Config;
|
||||||
|
|
||||||
class ProductRetrieverTest {
|
class ProductRetrieverTest {
|
||||||
@@ -35,7 +38,7 @@ class ProductRetrieverTest {
|
|||||||
@Mock
|
@Mock
|
||||||
private Product product;
|
private Product product;
|
||||||
@Mock
|
@Mock
|
||||||
private AbstractProductPersistence persistence;
|
private ProductPersistenceInterface persistence;
|
||||||
|
|
||||||
private ProductRetriever productRetriever;
|
private ProductRetriever productRetriever;
|
||||||
|
|
||||||
@@ -45,7 +48,7 @@ class ProductRetrieverTest {
|
|||||||
when(config.getProperty("AMAZON_API_URL")).thenReturn("https://api.amazon.com");
|
when(config.getProperty("AMAZON_API_URL")).thenReturn("https://api.amazon.com");
|
||||||
when(config.getProperty("AMAZON_API_KEY")).thenReturn("amazon-api-key");
|
when(config.getProperty("AMAZON_API_KEY")).thenReturn("amazon-api-key");
|
||||||
dataSourceFactory.setConfig(config);
|
dataSourceFactory.setConfig(config);
|
||||||
productRetriever = new ProductRetriever(dataSourceFactory);
|
productRetriever = new ProductRetriever(dataSourceFactory, persistence);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -56,7 +59,7 @@ class ProductRetrieverTest {
|
|||||||
when(amazonDataSource.getProductDTOById(asin)).thenReturn(productDTO);
|
when(amazonDataSource.getProductDTOById(asin)).thenReturn(productDTO);
|
||||||
when(productDTO.getProductId()).thenReturn(asin);
|
when(productDTO.getProductId()).thenReturn(asin);
|
||||||
when(productDTO.getCurrentPrice()).thenReturn(9.99);
|
when(productDTO.getCurrentPrice()).thenReturn(9.99);
|
||||||
when(productDTO.getDataOrigin()).thenReturn("Amazon");
|
when(productDTO.getDataOrigin()).thenReturn(Webshop.AMAZON);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
Product result = productRetriever.getProductFromAmazon(asin);
|
Product result = productRetriever.getProductFromAmazon(asin);
|
||||||
@@ -76,7 +79,7 @@ class ProductRetrieverTest {
|
|||||||
when(ebayDataSource.getProductDTOById(productQuery)).thenReturn(productDTO);
|
when(ebayDataSource.getProductDTOById(productQuery)).thenReturn(productDTO);
|
||||||
when(productDTO.getProductId()).thenReturn(productQuery);
|
when(productDTO.getProductId()).thenReturn(productQuery);
|
||||||
when(productDTO.getCurrentPrice()).thenReturn(9.99);
|
when(productDTO.getCurrentPrice()).thenReturn(9.99);
|
||||||
when(productDTO.getDataOrigin()).thenReturn("eBay");
|
when(productDTO.getDataOrigin()).thenReturn(Webshop.EBAY);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
Product result = productRetriever.getProductFromEbay(productQuery);
|
Product result = productRetriever.getProductFromEbay(productQuery);
|
||||||
@@ -92,11 +95,10 @@ class ProductRetrieverTest {
|
|||||||
void getProductFromPersistence_ValidProductId_ReturnsProduct() {
|
void getProductFromPersistence_ValidProductId_ReturnsProduct() {
|
||||||
// Arrange
|
// Arrange
|
||||||
String productId = "123";
|
String productId = "123";
|
||||||
when(dataSourceFactory.createProductPersistenceDataSource()).thenReturn(persistence);
|
|
||||||
when(persistence.getProductDTOById(productId)).thenReturn(productDTO);
|
when(persistence.getProductDTOById(productId)).thenReturn(productDTO);
|
||||||
when(productDTO.getProductId()).thenReturn(productId);
|
when(productDTO.getProductId()).thenReturn(productId);
|
||||||
when(productDTO.getCurrentPrice()).thenReturn(9.99);
|
when(productDTO.getCurrentPrice()).thenReturn(9.99);
|
||||||
when(productDTO.getDataOrigin()).thenReturn("Amazon");
|
when(productDTO.getDataOrigin()).thenReturn(Webshop.AMAZON);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
Product result = productRetriever.getProductFromPersistence(productId);
|
Product result = productRetriever.getProductFromPersistence(productId);
|
||||||
@@ -108,4 +110,49 @@ class ProductRetrieverTest {
|
|||||||
// Verify the interactions
|
// Verify the interactions
|
||||||
verify(persistence, times(1)).getProductDTOById(productId);
|
verify(persistence, times(1)).getProductDTOById(productId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getProductFromWebshop_ValidAmazonWebshop_ReturnsProduct() {
|
||||||
|
// Arrange
|
||||||
|
String productIdentifier = "ASIN1";
|
||||||
|
ProductDTO dto = new ProductDTO(productIdentifier, Webshop.AMAZON);
|
||||||
|
dto.setCurrentPrice(1.23);
|
||||||
|
AmazonProductDataSource dataSource = mock(AmazonProductDataSource.class);
|
||||||
|
Product expectedProduct = new Product();
|
||||||
|
expectedProduct.setProductId(productIdentifier);
|
||||||
|
expectedProduct.setDataOrigin(Webshop.AMAZON);
|
||||||
|
expectedProduct.setCurrentPrice(1.23);
|
||||||
|
when(dataSource.getProductDTOById(productIdentifier)).thenReturn(dto);
|
||||||
|
when(dataSourceFactory.createAmazonProductDataSource()).thenReturn(dataSource);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
Product actualProduct = productRetriever.getProductFromWebshop(Webshop.AMAZON, productIdentifier);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertEquals(expectedProduct, actualProduct);
|
||||||
|
verify(dataSourceFactory).createAmazonProductDataSource();
|
||||||
|
verify(dataSource).getProductDTOById(productIdentifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getProductFromWebshop_ValidEbayWebshop_ReturnsProduct() {
|
||||||
|
// Arrange
|
||||||
|
String productIdentifier = "ASIN1";
|
||||||
|
ProductDTO dto = new ProductDTO(productIdentifier, Webshop.EBAY);
|
||||||
|
dto.setCurrentPrice(1.23);
|
||||||
|
Product expectedProduct = new Product();
|
||||||
|
expectedProduct.setProductId(productIdentifier);
|
||||||
|
expectedProduct.setDataOrigin(Webshop.EBAY);
|
||||||
|
expectedProduct.setCurrentPrice(1.23);
|
||||||
|
when(ebayDataSource.getProductDTOById(productIdentifier)).thenReturn(dto);
|
||||||
|
when(dataSourceFactory.createEbayItemDataSource()).thenReturn(ebayDataSource);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
Product actualProduct = productRetriever.getProductFromWebshop(Webshop.EBAY, productIdentifier);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertEquals(expectedProduct, actualProduct);
|
||||||
|
verify(dataSourceFactory).createEbayItemDataSource();
|
||||||
|
verify(ebayDataSource).getProductDTOById(productIdentifier);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
package de.rwu.easydrop.service.validation;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
|
||||||
|
import de.rwu.easydrop.exception.InvalidOfferException;
|
||||||
|
import de.rwu.easydrop.model.Offer;
|
||||||
|
|
||||||
|
class OfferValidatorTest {
|
||||||
|
@Test
|
||||||
|
void testConstructorIsPrivate()
|
||||||
|
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
|
||||||
|
// Check for private constructor
|
||||||
|
Constructor<OfferValidator> constructor = OfferValidator.class.getDeclaredConstructor();
|
||||||
|
assertTrue(Modifier.isPrivate(constructor.getModifiers()));
|
||||||
|
|
||||||
|
// Make sure exception is thrown when instantiating
|
||||||
|
constructor.setAccessible(true);
|
||||||
|
assertThrows(InvocationTargetException.class, () -> {
|
||||||
|
constructor.newInstance();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void validate_Offer_ValidProduct_NoExceptionThrown() {
|
||||||
|
// Arrange
|
||||||
|
Offer offer = new Offer();
|
||||||
|
offer.setOfferId("3672");
|
||||||
|
offer.setLastUpdate("2021-02-03");
|
||||||
|
|
||||||
|
// Act and Assert
|
||||||
|
assertDoesNotThrow(() -> OfferValidator.validate(offer));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void validate_Offer_NullPointer() {
|
||||||
|
// Arrange
|
||||||
|
Offer offer = new Offer();
|
||||||
|
|
||||||
|
InvalidOfferException e = assertThrows(InvalidOfferException.class, () -> {
|
||||||
|
OfferValidator.validate(offer);
|
||||||
|
});
|
||||||
|
|
||||||
|
assertEquals("Required information is missing in the offer", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("invalidOfferProvider")
|
||||||
|
void validate_InvalidOffer_ThrowsInvalidOfferException(Offer offer) {
|
||||||
|
// Act and Assert
|
||||||
|
assertThrows(InvalidOfferException.class, () -> OfferValidator.validate(offer));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static Stream<Offer> invalidOfferProvider() {
|
||||||
|
return Stream.of(
|
||||||
|
createOfferWithEmptylastUpdate(),
|
||||||
|
createOfferWithEmptyId());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Offer createOfferWithEmptylastUpdate() {
|
||||||
|
Offer offer = new Offer();
|
||||||
|
offer.setOfferId("3729798");
|
||||||
|
offer.setLastUpdate("");
|
||||||
|
return offer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Offer createOfferWithEmptyId() {
|
||||||
|
Offer offer = new Offer();
|
||||||
|
offer.setOfferId("");
|
||||||
|
offer.setLastUpdate("8798476");
|
||||||
|
return offer;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
package de.rwu.easydrop.service.validation;
|
package de.rwu.easydrop.service.validation;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
@@ -16,6 +15,7 @@ import org.junit.jupiter.params.provider.MethodSource;
|
|||||||
|
|
||||||
import de.rwu.easydrop.exception.InvalidProductException;
|
import de.rwu.easydrop.exception.InvalidProductException;
|
||||||
import de.rwu.easydrop.model.Product;
|
import de.rwu.easydrop.model.Product;
|
||||||
|
import de.rwu.easydrop.model.Webshop;
|
||||||
|
|
||||||
class ProductValidatorTest {
|
class ProductValidatorTest {
|
||||||
|
|
||||||
@@ -38,37 +38,13 @@ class ProductValidatorTest {
|
|||||||
// Arrange
|
// Arrange
|
||||||
Product product = new Product();
|
Product product = new Product();
|
||||||
product.setCurrentPrice(9.99);
|
product.setCurrentPrice(9.99);
|
||||||
product.setDataOrigin("Amazon");
|
product.setDataOrigin(Webshop.AMAZON);
|
||||||
product.setProductId("12345");
|
product.setProductId("12345");
|
||||||
|
|
||||||
// Act and Assert
|
// Act and Assert
|
||||||
assertDoesNotThrow(() -> ProductValidator.validate(product));
|
assertDoesNotThrow(() -> ProductValidator.validate(product));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
void isInValidDataOrigins_ValidDataOrigin_ReturnsTrue() {
|
|
||||||
// Arrange
|
|
||||||
String dataOrigin = "Amazon";
|
|
||||||
|
|
||||||
// Act
|
|
||||||
boolean result = ProductValidator.isInValidDataOrigins(dataOrigin);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
assertTrue(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void isInValidDataOrigins_InvalidDataOrigin_ReturnsFalse() {
|
|
||||||
// Arrange
|
|
||||||
String dataOrigin = "UnknownOrigin";
|
|
||||||
|
|
||||||
// Act
|
|
||||||
boolean result = ProductValidator.isInValidDataOrigins(dataOrigin);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
assertFalse(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("invalidProductProvider")
|
@MethodSource("invalidProductProvider")
|
||||||
void validate_InvalidProduct_ThrowsInvalidProductException(Product product) {
|
void validate_InvalidProduct_ThrowsInvalidProductException(Product product) {
|
||||||
@@ -79,22 +55,13 @@ class ProductValidatorTest {
|
|||||||
static Stream<Product> invalidProductProvider() {
|
static Stream<Product> invalidProductProvider() {
|
||||||
return Stream.of(
|
return Stream.of(
|
||||||
createProductWithZeroPrice(),
|
createProductWithZeroPrice(),
|
||||||
createProductWithUnknownDataOrigin(),
|
|
||||||
createProductWithEmptyProductId());
|
createProductWithEmptyProductId());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Product createProductWithZeroPrice() {
|
private static Product createProductWithZeroPrice() {
|
||||||
Product product = new Product();
|
Product product = new Product();
|
||||||
product.setCurrentPrice(0.00);
|
product.setCurrentPrice(0.00);
|
||||||
product.setDataOrigin("Amazon");
|
product.setDataOrigin(Webshop.AMAZON);
|
||||||
product.setProductId("12345");
|
|
||||||
return product;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Product createProductWithUnknownDataOrigin() {
|
|
||||||
Product product = new Product();
|
|
||||||
product.setCurrentPrice(9.99);
|
|
||||||
product.setDataOrigin("UnknownOrigin");
|
|
||||||
product.setProductId("12345");
|
product.setProductId("12345");
|
||||||
return product;
|
return product;
|
||||||
}
|
}
|
||||||
@@ -102,7 +69,7 @@ class ProductValidatorTest {
|
|||||||
private static Product createProductWithEmptyProductId() {
|
private static Product createProductWithEmptyProductId() {
|
||||||
Product product = new Product();
|
Product product = new Product();
|
||||||
product.setCurrentPrice(9.99);
|
product.setCurrentPrice(9.99);
|
||||||
product.setDataOrigin("Amazon");
|
product.setDataOrigin(Webshop.AMAZON);
|
||||||
product.setProductId("");
|
product.setProductId("");
|
||||||
return product;
|
return product;
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user