From 2f1bd4407c0c6c4d4d0ac62c2052b35ae249eec7 Mon Sep 17 00:00:00 2001 From: Marvin Scham Date: Wed, 31 May 2023 13:47:08 +0200 Subject: [PATCH] Added abstraction layer to DataSources --- .../api/client/AbstractDataSource.java | 99 +++++++++++++++++++ .../api/client/AmazonProductDataSource.java | 60 +++-------- .../rwu/easydrop/api/client/DataSource.java | 16 +-- .../de/rwu/easydrop/util/FormattingUtil.java | 10 ++ 4 files changed, 125 insertions(+), 60 deletions(-) create mode 100644 src/main/java/de/rwu/easydrop/api/client/AbstractDataSource.java diff --git a/src/main/java/de/rwu/easydrop/api/client/AbstractDataSource.java b/src/main/java/de/rwu/easydrop/api/client/AbstractDataSource.java new file mode 100644 index 0000000..9d1df1c --- /dev/null +++ b/src/main/java/de/rwu/easydrop/api/client/AbstractDataSource.java @@ -0,0 +1,99 @@ +package de.rwu.easydrop.api.client; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; + +import de.rwu.easydrop.api.dto.ProductDTO; +import de.rwu.easydrop.util.FormattingUtil; + +/** + * Helper class for shared data and functions between data sources. + * + * @since 0.2.0 + */ +public abstract class AbstractDataSource implements DataSource { + + /** + * Returns the data origin for the current source. + * + * @return Data source name + */ + protected abstract String getDataOrigin(); + + /** + * Returns the data source's API key. + * + * @return Data source API key + */ + protected abstract String getApiKey(); + + /** + * Enriches a ProductDTO with API-gathered data. + * + * @param product Unfinished ProductDTO + * @param json Product data + * @return Finished ProductDTO + */ + public abstract ProductDTO buildProductDTO(ProductDTO product, String json); + + /** + * Overridable standard implementation. + */ + @Override + public ProductDTO getProductDTOById(final String productIdentifier) + throws IllegalArgumentException { + StringBuilder response = new StringBuilder(); + String dataOrigin = getDataOrigin(); + String apiKey = getApiKey(); + ProductDTO product = new ProductDTO(productIdentifier, dataOrigin); + + try { + String urlReadyIdentifier = FormattingUtil.urlEncode(productIdentifier); + URL apiUrl = createApiUrl(urlReadyIdentifier); + + HttpURLConnection connection = (HttpURLConnection) apiUrl.openConnection(); + connection.setRequestMethod("GET"); + connection.setRequestProperty("Credential", apiKey); + + int responseCode = connection.getResponseCode(); + BufferedReader reader; + if (responseCode == HttpURLConnection.HTTP_OK) { + reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); + } else { + throw new IllegalArgumentException( + "Nothing found: " + + dataOrigin + + " API responded with error code " + + responseCode); + } + + String line; + while ((line = reader.readLine()) != null) { + response.append(line); + } + reader.close(); + + buildProductDTO(product, response.toString()); + } catch (IOException e) { + throw new IllegalArgumentException( + "Couldn't fulfill " + + dataOrigin + + " API request"); + } + + return product; + } + + /** + * 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; +} diff --git a/src/main/java/de/rwu/easydrop/api/client/AmazonProductDataSource.java b/src/main/java/de/rwu/easydrop/api/client/AmazonProductDataSource.java index d8c5d3e..5654765 100644 --- a/src/main/java/de/rwu/easydrop/api/client/AmazonProductDataSource.java +++ b/src/main/java/de/rwu/easydrop/api/client/AmazonProductDataSource.java @@ -1,9 +1,5 @@ package de.rwu.easydrop.api.client; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; @@ -18,7 +14,7 @@ import de.rwu.easydrop.api.dto.ProductDTO; * * @since 0.1.0 */ -public final class AmazonProductDataSource implements DataSource { +public final class AmazonProductDataSource extends AbstractDataSource { /** * Name of this data source. */ @@ -52,47 +48,6 @@ public final class AmazonProductDataSource implements DataSource { } @Override - public ProductDTO getProductDTOById(final String productId) throws IllegalArgumentException { - StringBuilder response = new StringBuilder(); - ProductDTO product = new ProductDTO(productId, DATA_ORIGIN); - - try { - URL apiUrl = createApiUrl(productId); - - HttpURLConnection connection = (HttpURLConnection) apiUrl.openConnection(); - connection.setRequestMethod("GET"); - connection.setRequestProperty("Credential", apiKey); - - int responseCode = connection.getResponseCode(); - BufferedReader reader; - if (responseCode == HttpURLConnection.HTTP_OK) { - reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); - } else { - throw new IllegalArgumentException( - "Nothing found: Amazon API responded with error code " + responseCode); - } - - String line; - while ((line = reader.readLine()) != null) { - response.append(line); - } - reader.close(); - - buildProductDTO(product, response.toString()); - } catch (IOException e) { - throw new IllegalArgumentException("Couldn't fulfill Amazon API request"); - } - - return product; - } - - /** - * Enriches a ProductDTO with API-gathered data. - * - * @param product Unfinished ProductDTO - * @param json Product data - * @return Finished ProductDTO - */ public ProductDTO buildProductDTO(final ProductDTO product, final String json) { String root = "$.featuredOffer."; ReadContext ctx = JsonPath.parse(json); @@ -112,6 +67,9 @@ public final class AmazonProductDataSource implements DataSource { return product; } + /** + * @param productId ASIN + */ @Override public URL createApiUrl(final String productId) throws MalformedURLException { return new URL(baseUrl @@ -122,4 +80,14 @@ public final class AmazonProductDataSource implements DataSource { + "&locale=" + LOCALE); } + + @Override + protected String getDataOrigin() { + return DATA_ORIGIN; + } + + @Override + protected String getApiKey() { + return this.apiKey; + } } diff --git a/src/main/java/de/rwu/easydrop/api/client/DataSource.java b/src/main/java/de/rwu/easydrop/api/client/DataSource.java index 7b1c4e7..bda028f 100644 --- a/src/main/java/de/rwu/easydrop/api/client/DataSource.java +++ b/src/main/java/de/rwu/easydrop/api/client/DataSource.java @@ -1,8 +1,5 @@ package de.rwu.easydrop.api.client; -import java.net.MalformedURLException; -import java.net.URL; - import de.rwu.easydrop.api.dto.ProductDTO; /** @@ -12,17 +9,8 @@ public interface DataSource { /** * Retrieves product info from the data source. * - * @param productId ASIN + * @param productIdentifier Product identifier * @return ProductDTO */ - ProductDTO getProductDTOById(String productId); - - /** - * Creates an URL object to connect to the API with. - * - * @param productId ASIN - * @return URL object - * @throws MalformedURLException - */ - URL createApiUrl(String productId) throws MalformedURLException; + ProductDTO getProductDTOById(String productIdentifier); } diff --git a/src/main/java/de/rwu/easydrop/util/FormattingUtil.java b/src/main/java/de/rwu/easydrop/util/FormattingUtil.java index 283e506..7ef0e69 100644 --- a/src/main/java/de/rwu/easydrop/util/FormattingUtil.java +++ b/src/main/java/de/rwu/easydrop/util/FormattingUtil.java @@ -27,4 +27,14 @@ public final class FormattingUtil { public static String formatEuro(final double amount) { return String.format(Locale.GERMAN, "%,.2f", amount) + " €"; } + + /** + * Makes a string URL ready. For now, only spaces are replaced. + * + * @param str + * @return URL-ready string + */ + public static String urlEncode(final String str) { + return str.replace(" ", "+"); + } }