From b498220d9fbf99d9669df5d69e5126e5ab53f6fe Mon Sep 17 00:00:00 2001 From: Clayton Wilson Date: Sat, 3 Oct 2020 01:34:26 -0400 Subject: [PATCH 01/21] Fixed search results not being cleared after new search --- .../src/main/java/com/example/listify/SearchResults.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Listify/app/src/main/java/com/example/listify/SearchResults.java b/Listify/app/src/main/java/com/example/listify/SearchResults.java index e87fd48..eafb400 100644 --- a/Listify/app/src/main/java/com/example/listify/SearchResults.java +++ b/Listify/app/src/main/java/com/example/listify/SearchResults.java @@ -1,4 +1,5 @@ package com.example.listify; +import android.content.Intent; import android.os.Bundle; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; @@ -77,7 +78,9 @@ public class SearchResults extends AppCompatActivity implements SortDialogFragme listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { - Toast.makeText(SearchResults.this, resultsProductListSorted.get(position).getItemName(), Toast.LENGTH_SHORT).show(); +// Toast.makeText(SearchResults.this, resultsProductListSorted.get(position).getItemName(), Toast.LENGTH_SHORT).show(); + Intent itemDetails = new Intent(SearchResults.this, ItemDetails.class); + startActivity(itemDetails); } }); @@ -129,6 +132,9 @@ public class SearchResults extends AppCompatActivity implements SortDialogFragme // TODO: Create a new Product Object for each result // TODO: Add each result to productList + // Clear the old search results + resultsProductList = new ArrayList<>(); + // Hardcode some search results... for (int i = 0; i < 2; i++) { Product a = new Product("Bottled Water", "0000", "Walmart", "0001", "0123456780", "Bro, it's water...", "Grocery", 13.37, "9/24/2020", "1", "http://3.bp.blogspot.com/-MfroPPQVDKo/UyhUZWqGvkI/AAAAAAAAB-I/DGk622onsvc/s1600/lettuce-b-kool-cat-meme.jpg"); From 69572b3a1fbf2e6905e5dacbd1255d63b276a431 Mon Sep 17 00:00:00 2001 From: NMerz Date: Sat, 3 Oct 2020 11:22:35 -0400 Subject: [PATCH 02/21] Generify endpoint groups as IntelliJ Modules This allows them to be built sperately decreasing JAR size and also creates a better structure for generic service functions and business logic. --- Lambdas/Lists/Item/src/ItemAdder.java | 27 +++++++++++++++++ Lambdas/Lists/Item/src/ItemGET.java | 11 +++++++ Lambdas/Lists/Item/src/ItemGetter.java | 9 ++++++ Lambdas/Lists/Item/src/ItemPOST.java | 11 +++++++ .../main/java => List/src}/ListAdder.java | 7 +++-- Lambdas/Lists/List/src/ListPOST.java | 11 +++++++ Lambdas/Lists/src/main/java/BasicHandler.java | 29 +++++++++++++++++++ Lambdas/Lists/src/main/java/CallHandler.java | 6 ++++ Lambdas/Lists/src/main/java/DBConnector.java | 4 +-- Lambdas/Lists/src/main/java/InputUtils.java | 4 +++ Lambdas/Lists/src/main/java/ListPOST.java | 28 ------------------ Listify/.idea/misc.xml | 2 +- 12 files changed, 115 insertions(+), 34 deletions(-) create mode 100644 Lambdas/Lists/Item/src/ItemAdder.java create mode 100644 Lambdas/Lists/Item/src/ItemGET.java create mode 100644 Lambdas/Lists/Item/src/ItemGetter.java create mode 100644 Lambdas/Lists/Item/src/ItemPOST.java rename Lambdas/Lists/{src/main/java => List/src}/ListAdder.java (75%) create mode 100644 Lambdas/Lists/List/src/ListPOST.java create mode 100644 Lambdas/Lists/src/main/java/BasicHandler.java create mode 100644 Lambdas/Lists/src/main/java/CallHandler.java delete mode 100644 Lambdas/Lists/src/main/java/ListPOST.java diff --git a/Lambdas/Lists/Item/src/ItemAdder.java b/Lambdas/Lists/Item/src/ItemAdder.java new file mode 100644 index 0000000..bea8cfa --- /dev/null +++ b/Lambdas/Lists/Item/src/ItemAdder.java @@ -0,0 +1,27 @@ +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.Map; + +public class ItemAdder implements CallHandler { + + private DBConnector connector; + private String cognitoID; + + private final String LIST_CREATE = "INSERT INTO Items (Name) VALUES (?)"; + + public ItemAdder(DBConnector connector, String cognitoID) { + this.connector = connector; + this.cognitoID = cognitoID; + } + + public String conductAction(Map bodyMap, String queryString) throws SQLException { + Connection connection = connector.getConnection(); + PreparedStatement statement = connection.prepareStatement(LIST_CREATE); + statement.setString(1, bodyMap.get("name").toString());//Needs safe checking + System.out.println(statement); + statement.executeUpdate(); + connection.commit(); + return null; + } +} diff --git a/Lambdas/Lists/Item/src/ItemGET.java b/Lambdas/Lists/Item/src/ItemGET.java new file mode 100644 index 0000000..3794b51 --- /dev/null +++ b/Lambdas/Lists/Item/src/ItemGET.java @@ -0,0 +1,11 @@ +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + +import java.util.Map; + +public class ItemGET implements RequestHandler, String> { + + public String handleRequest(Map inputMap, Context unfilled) { + return BasicHandler.handleRequest(inputMap, unfilled, ItemGetter.class); + } +} diff --git a/Lambdas/Lists/Item/src/ItemGetter.java b/Lambdas/Lists/Item/src/ItemGetter.java new file mode 100644 index 0000000..57a350c --- /dev/null +++ b/Lambdas/Lists/Item/src/ItemGetter.java @@ -0,0 +1,9 @@ +import java.sql.SQLException; +import java.util.Map; + +public class ItemGetter implements CallHandler{ + @Override + public String conductAction(Map bodyMap, String cognitoID) throws SQLException { + return null; + } +} diff --git a/Lambdas/Lists/Item/src/ItemPOST.java b/Lambdas/Lists/Item/src/ItemPOST.java new file mode 100644 index 0000000..f2279c4 --- /dev/null +++ b/Lambdas/Lists/Item/src/ItemPOST.java @@ -0,0 +1,11 @@ +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + +import java.util.Map; + +public class ItemPOST implements RequestHandler, String>{ + + public String handleRequest(Map inputMap, Context unfilled) { + return BasicHandler.handleRequest(inputMap, unfilled, ItemAdder.class); + } +} diff --git a/Lambdas/Lists/src/main/java/ListAdder.java b/Lambdas/Lists/List/src/ListAdder.java similarity index 75% rename from Lambdas/Lists/src/main/java/ListAdder.java rename to Lambdas/Lists/List/src/ListAdder.java index e1598b7..d7f4982 100644 --- a/Lambdas/Lists/src/main/java/ListAdder.java +++ b/Lambdas/Lists/List/src/ListAdder.java @@ -3,19 +3,19 @@ import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.Map; -public class ListAdder { +public class ListAdder implements CallHandler { private DBConnector connector; private String cognitoID; private final String LIST_CREATE = "INSERT INTO Lists (Name, Owner) VALUES (?, ?)"; - ListAdder(DBConnector connector, String cognitoID) { + public ListAdder(DBConnector connector, String cognitoID) { this.connector = connector; this.cognitoID = cognitoID; } - public void add(Map bodyMap) throws SQLException { + public String conductAction(Map bodyMap, String queryString) throws SQLException { Connection connection = connector.getConnection(); PreparedStatement statement = connection.prepareStatement(LIST_CREATE); statement.setString(1, bodyMap.get("name").toString());//Needs safe checking @@ -23,5 +23,6 @@ public class ListAdder { System.out.println(statement); statement.executeUpdate(); connection.commit(); + return null; } } diff --git a/Lambdas/Lists/List/src/ListPOST.java b/Lambdas/Lists/List/src/ListPOST.java new file mode 100644 index 0000000..13c2785 --- /dev/null +++ b/Lambdas/Lists/List/src/ListPOST.java @@ -0,0 +1,11 @@ +import java.util.Map; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + +public class ListPOST implements RequestHandler, String>{ + + public String handleRequest(Map inputMap, Context unfilled) { + return BasicHandler.handleRequest(inputMap, unfilled, ListAdder.class); + } +} diff --git a/Lambdas/Lists/src/main/java/BasicHandler.java b/Lambdas/Lists/src/main/java/BasicHandler.java new file mode 100644 index 0000000..8b642eb --- /dev/null +++ b/Lambdas/Lists/src/main/java/BasicHandler.java @@ -0,0 +1,29 @@ +import com.amazonaws.services.lambda.runtime.Context; + +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.sql.SQLException; +import java.util.Map; + +public class BasicHandler { + public static String handleRequest(Map inputMap, Context unfilled, Class toCall) { + String cognitoID = InputUtils.getCognitoIDFromBody(inputMap); + try { + DBConnector connector = new DBConnector(); + try { + Constructor constructor = toCall.getConstructor(DBConnector.class, String.class); + CallHandler callHandler = constructor.newInstance(connector, cognitoID); + callHandler.conductAction(InputUtils.getBody(inputMap), ""); + } catch (SQLException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) { + e.printStackTrace(); + } finally { + connector.close(); + } + } catch (IOException |SQLException|ClassNotFoundException e) { + e.printStackTrace(); + throw new RuntimeException(e.getMessage()); + } + return null; + } +} diff --git a/Lambdas/Lists/src/main/java/CallHandler.java b/Lambdas/Lists/src/main/java/CallHandler.java new file mode 100644 index 0000000..ac5aa2a --- /dev/null +++ b/Lambdas/Lists/src/main/java/CallHandler.java @@ -0,0 +1,6 @@ +import java.sql.SQLException; +import java.util.Map; + +public interface CallHandler { + String conductAction(Map bodyMap, String cognitoID) throws SQLException; +} diff --git a/Lambdas/Lists/src/main/java/DBConnector.java b/Lambdas/Lists/src/main/java/DBConnector.java index 074f4de..798cfc3 100644 --- a/Lambdas/Lists/src/main/java/DBConnector.java +++ b/Lambdas/Lists/src/main/java/DBConnector.java @@ -12,11 +12,11 @@ public class DBConnector { Connection connection; - DBConnector() throws IOException, SQLException, ClassNotFoundException { + public DBConnector() throws IOException, SQLException, ClassNotFoundException { this(loadProperties("dbProperties.json")); } - DBConnector(Properties dbProperties) throws SQLException, ClassNotFoundException { + public DBConnector(Properties dbProperties) throws SQLException, ClassNotFoundException { Class.forName("org.mariadb.jdbc.Driver"); System.out.println(dbProperties); System.out.println(DBConnector.buildURL(dbProperties)); diff --git a/Lambdas/Lists/src/main/java/InputUtils.java b/Lambdas/Lists/src/main/java/InputUtils.java index 46a0694..b10781d 100644 --- a/Lambdas/Lists/src/main/java/InputUtils.java +++ b/Lambdas/Lists/src/main/java/InputUtils.java @@ -19,6 +19,10 @@ public class InputUtils { return getMap(inputMap, "body"); } + public static String getQueryString(Map inputMap) { + return (String) (getMap(inputMap, "params").get("querystring")); + } + public static Map getMap(Map parentMap, String childKey) { if ((parentMap.get(childKey) != null) && (parentMap.get(childKey) instanceof Map)) { return ((Map) parentMap.get(childKey)); diff --git a/Lambdas/Lists/src/main/java/ListPOST.java b/Lambdas/Lists/src/main/java/ListPOST.java deleted file mode 100644 index c2fc63c..0000000 --- a/Lambdas/Lists/src/main/java/ListPOST.java +++ /dev/null @@ -1,28 +0,0 @@ -import java.io.IOException; -import java.sql.SQLException; -import java.util.Map; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; - -public class ListPOST implements RequestHandler, String>{ - - - public String handleRequest(Map inputMap, Context unfilled) { - String cognitoID = InputUtils.getCognitoIDFromBody(inputMap); - try { - DBConnector connector = new DBConnector(); - try { - new ListAdder(connector, cognitoID).add(InputUtils.getBody(inputMap)); - } catch (SQLException e) { - e.printStackTrace(); - } finally { - connector.close(); - } - } catch (IOException|SQLException|ClassNotFoundException e) { - e.printStackTrace(); - throw new RuntimeException(e.getMessage()); - } - return null; - } -} diff --git a/Listify/.idea/misc.xml b/Listify/.idea/misc.xml index d5d35ec..fdae1d0 100644 --- a/Listify/.idea/misc.xml +++ b/Listify/.idea/misc.xml @@ -1,6 +1,6 @@ - + From b951983112f502d1a80c0d8b9f20be3edd8bf629 Mon Sep 17 00:00:00 2001 From: Clayton Wilson Date: Sat, 3 Oct 2020 16:52:11 -0400 Subject: [PATCH 03/21] Fix for long titles on search results --- .../example/listify/adapter/SearchResultsListAdapter.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Listify/app/src/main/java/com/example/listify/adapter/SearchResultsListAdapter.java b/Listify/app/src/main/java/com/example/listify/adapter/SearchResultsListAdapter.java index 61f9473..cc4306c 100644 --- a/Listify/app/src/main/java/com/example/listify/adapter/SearchResultsListAdapter.java +++ b/Listify/app/src/main/java/com/example/listify/adapter/SearchResultsListAdapter.java @@ -57,7 +57,11 @@ public class SearchResultsListAdapter extends BaseAdapter { Product product = productList.get(position); // TODO: If image url is broken, display @drawable/ic_baseline_broken_image_600.xml Glide.with(activity).load(product.getImageUrl()).into(productImage); - itemName.setText(product.getItemName()); + if (product.getItemName().length() >= 35) { + itemName.setText(product.getItemName().substring(0, 35) + "..."); + } else { + itemName.setText(product.getItemName()); + } price.setText(String.format("$%.2f", product.getPrice())); itemStore.setText(product.getChainName()); From f107ab023d12cf425ff8d8793587f7e486f193d2 Mon Sep 17 00:00:00 2001 From: NMerz Date: Sat, 3 Oct 2020 17:37:46 -0400 Subject: [PATCH 04/21] GET strcuture Build out infrastructure for get requests (along with the first couple). This includes changing the request engine from Volley to OKHTTP due to issues get Volley's callbacks to call back. --- Lambdas/Lists/Item/src/Item.java | 52 ++++++++++ Lambdas/Lists/Item/src/ItemAdder.java | 25 +++-- Lambdas/Lists/Item/src/ItemGET.java | 4 +- Lambdas/Lists/Item/src/ItemGetter.java | 31 +++++- Lambdas/Lists/Item/src/ItemPOST.java | 4 +- Lambdas/Lists/List/src/ItemEntry.java | 16 ++++ Lambdas/Lists/List/src/List.java | 18 ++++ Lambdas/Lists/List/src/ListAdder.java | 8 +- Lambdas/Lists/List/src/ListGET.java | 12 +++ Lambdas/Lists/List/src/ListGetter.java | 39 ++++++++ Lambdas/Lists/List/src/ListPOST.java | 4 +- Lambdas/Lists/pom.xml | 10 ++ Lambdas/Lists/src/main/java/BasicHandler.java | 6 +- Lambdas/Lists/src/main/java/CallHandler.java | 3 +- Lambdas/Lists/src/main/java/InputUtils.java | 22 ++++- Listify/.idea/misc.xml | 2 +- Listify/app/build.gradle | 1 + .../main/java/com/example/listify/Item.java | 44 +++++++++ .../com/example/listify/MainActivity.java | 14 ++- .../java/com/example/listify/Requestor.java | 96 +++++++++++++------ .../example/listify/SynchronousReceiver.java | 39 ++++++++ 21 files changed, 398 insertions(+), 52 deletions(-) create mode 100644 Lambdas/Lists/Item/src/Item.java create mode 100644 Lambdas/Lists/List/src/ItemEntry.java create mode 100644 Lambdas/Lists/List/src/List.java create mode 100644 Lambdas/Lists/List/src/ListGET.java create mode 100644 Lambdas/Lists/List/src/ListGetter.java create mode 100644 Listify/app/src/main/java/com/example/listify/Item.java create mode 100644 Listify/app/src/main/java/com/example/listify/SynchronousReceiver.java diff --git a/Lambdas/Lists/Item/src/Item.java b/Lambdas/Lists/Item/src/Item.java new file mode 100644 index 0000000..53ef341 --- /dev/null +++ b/Lambdas/Lists/Item/src/Item.java @@ -0,0 +1,52 @@ +import java.math.BigDecimal; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.time.LocalDateTime; + +public class Item { + Integer productID; + Integer chainID; + String upc; + String description; + BigDecimal price; + String imageURL; + String department; + LocalDateTime retrievedDate; + Integer fetchCounts; + + Item(ResultSet itemRow) throws SQLException { + this.productID = itemRow.getInt(1); + System.out.println(this.productID); + this.chainID = itemRow.getInt(2); + System.out.println(this.chainID); + this.upc = itemRow.getString(3); + System.out.println(this.upc); + this.description = itemRow.getString(4); + System.out.println(this.description); + this.price = itemRow.getBigDecimal(5); + System.out.println(this.price); + this.imageURL = itemRow.getString(6); + System.out.println(imageURL); + this.department = itemRow.getString(7); + System.out.println(department); + this.retrievedDate = itemRow.getObject(8, LocalDateTime.class); + System.out.println(retrievedDate); + this.fetchCounts = itemRow.getInt(9); + System.out.println(fetchCounts); + } + + @Override + public String toString() { + return "Item{" + + "productID=" + productID + + ", chainID=" + chainID + + ", upc='" + upc + '\'' + + ", description='" + description + '\'' + + ", price=" + price + + ", imageURL='" + imageURL + '\'' + + ", department='" + department + '\'' + + ", retrievedDate=" + retrievedDate + + ", fetchCounts=" + fetchCounts + + '}'; + } +} diff --git a/Lambdas/Lists/Item/src/ItemAdder.java b/Lambdas/Lists/Item/src/ItemAdder.java index bea8cfa..c698a04 100644 --- a/Lambdas/Lists/Item/src/ItemAdder.java +++ b/Lambdas/Lists/Item/src/ItemAdder.java @@ -1,6 +1,9 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; +import java.time.Instant; +import java.time.ZoneOffset; +import java.util.HashMap; import java.util.Map; public class ItemAdder implements CallHandler { @@ -8,20 +11,28 @@ public class ItemAdder implements CallHandler { private DBConnector connector; private String cognitoID; - private final String LIST_CREATE = "INSERT INTO Items (Name) VALUES (?)"; + private final String ITEM_TO_LIST = "INSERT INTO ListProduct (productID, listID, quantity, addedDate, purchased) VALUES (?, ?, ?, ?, ?)"; public ItemAdder(DBConnector connector, String cognitoID) { this.connector = connector; this.cognitoID = cognitoID; } - public String conductAction(Map bodyMap, String queryString) throws SQLException { + public Object conductAction(Map bodyMap, HashMap queryString, String cognitoID) throws SQLException { Connection connection = connector.getConnection(); - PreparedStatement statement = connection.prepareStatement(LIST_CREATE); - statement.setString(1, bodyMap.get("name").toString());//Needs safe checking - System.out.println(statement); - statement.executeUpdate(); - connection.commit(); + try { + PreparedStatement statement = connection.prepareStatement(ITEM_TO_LIST); + statement.setInt(1, (Integer) bodyMap.get("itemID")); + statement.setInt(2, (Integer) bodyMap.get("listID")); + statement.setInt(3, (Integer) bodyMap.get("quantity")); + statement.setObject(4, Instant.now().atZone(ZoneOffset.UTC).toLocalDateTime()); + statement.setBoolean(5, (Boolean) bodyMap.get("purchased")); + System.out.println(statement); + statement.executeUpdate(); + connection.commit(); + } finally { + connection.close(); + } return null; } } diff --git a/Lambdas/Lists/Item/src/ItemGET.java b/Lambdas/Lists/Item/src/ItemGET.java index 3794b51..71c0804 100644 --- a/Lambdas/Lists/Item/src/ItemGET.java +++ b/Lambdas/Lists/Item/src/ItemGET.java @@ -3,9 +3,9 @@ import com.amazonaws.services.lambda.runtime.RequestHandler; import java.util.Map; -public class ItemGET implements RequestHandler, String> { +public class ItemGET implements RequestHandler, Object> { - public String handleRequest(Map inputMap, Context unfilled) { + public Object handleRequest(Map inputMap, Context unfilled) { return BasicHandler.handleRequest(inputMap, unfilled, ItemGetter.class); } } diff --git a/Lambdas/Lists/Item/src/ItemGetter.java b/Lambdas/Lists/Item/src/ItemGetter.java index 57a350c..2414e3a 100644 --- a/Lambdas/Lists/Item/src/ItemGetter.java +++ b/Lambdas/Lists/Item/src/ItemGetter.java @@ -1,9 +1,36 @@ +import com.google.gson.Gson; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; import java.sql.SQLException; +import java.util.HashMap; import java.util.Map; public class ItemGetter implements CallHandler{ + private final DBConnector connector; + + private final String GET_ITEM = "SELECT * FROM Product WHERE productID = ?;"; + + public ItemGetter(DBConnector connector, String cognitoID) { + this.connector = connector; + } + @Override - public String conductAction(Map bodyMap, String cognitoID) throws SQLException { - return null; + public Object conductAction(Map bodyMap, HashMap queryMap, String cognitoID) throws SQLException { + Connection connection = connector.getConnection(); + try { + PreparedStatement statement = connection.prepareStatement(GET_ITEM); + statement.setInt(1, Integer.parseInt(queryMap.get("id"))); + System.out.println(statement); + ResultSet queryResults = statement.executeQuery(); + queryResults.first(); + System.out.println(queryResults); + Item retrievedItem = new Item(queryResults); + System.out.println(retrievedItem); + return retrievedItem; + } finally { + connection.close(); + } } } diff --git a/Lambdas/Lists/Item/src/ItemPOST.java b/Lambdas/Lists/Item/src/ItemPOST.java index f2279c4..51d107f 100644 --- a/Lambdas/Lists/Item/src/ItemPOST.java +++ b/Lambdas/Lists/Item/src/ItemPOST.java @@ -3,9 +3,9 @@ import com.amazonaws.services.lambda.runtime.RequestHandler; import java.util.Map; -public class ItemPOST implements RequestHandler, String>{ +public class ItemPOST implements RequestHandler, Object> { - public String handleRequest(Map inputMap, Context unfilled) { + public Object handleRequest(Map inputMap, Context unfilled) { return BasicHandler.handleRequest(inputMap, unfilled, ItemAdder.class); } } diff --git a/Lambdas/Lists/List/src/ItemEntry.java b/Lambdas/Lists/List/src/ItemEntry.java new file mode 100644 index 0000000..b05ddc7 --- /dev/null +++ b/Lambdas/Lists/List/src/ItemEntry.java @@ -0,0 +1,16 @@ +import java.sql.ResultSet; +import java.sql.SQLException; +import java.time.LocalDateTime; + +public class ItemEntry { + Integer productID; + Integer quantity; + LocalDateTime addedDate; + Boolean purchased; + public ItemEntry(ResultSet listRow) throws SQLException { + productID = listRow.getInt(1); + quantity = listRow.getInt(2); + addedDate = listRow.getObject(3, LocalDateTime.class); + purchased = listRow.getBoolean(4); + } +} diff --git a/Lambdas/Lists/List/src/List.java b/Lambdas/Lists/List/src/List.java new file mode 100644 index 0000000..c2ac9c6 --- /dev/null +++ b/Lambdas/Lists/List/src/List.java @@ -0,0 +1,18 @@ +import java.sql.ResultSet; +import java.sql.SQLException; +import java.time.LocalDateTime; + +public class List { + Integer itemID; + String name; + String owner; + LocalDateTime lastUpdated; + + public List(ResultSet listRow) throws SQLException { + itemID = listRow.getInt(1); + name = listRow.getString(2); + owner = listRow.getString(3); + lastUpdated = listRow.getObject(8, LocalDateTime.class); + } + +} diff --git a/Lambdas/Lists/List/src/ListAdder.java b/Lambdas/Lists/List/src/ListAdder.java index d7f4982..eb56e36 100644 --- a/Lambdas/Lists/List/src/ListAdder.java +++ b/Lambdas/Lists/List/src/ListAdder.java @@ -1,6 +1,9 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; +import java.time.Instant; +import java.time.ZoneOffset; +import java.util.HashMap; import java.util.Map; public class ListAdder implements CallHandler { @@ -8,18 +11,19 @@ public class ListAdder implements CallHandler { private DBConnector connector; private String cognitoID; - private final String LIST_CREATE = "INSERT INTO Lists (Name, Owner) VALUES (?, ?)"; + private final String LIST_CREATE = "INSERT INTO List (name, owner, lastUpdated) VALUES (?, ?, ?)"; public ListAdder(DBConnector connector, String cognitoID) { this.connector = connector; this.cognitoID = cognitoID; } - public String conductAction(Map bodyMap, String queryString) throws SQLException { + public Object conductAction(Map bodyMap, HashMap queryString, String cognitoID) throws SQLException { Connection connection = connector.getConnection(); PreparedStatement statement = connection.prepareStatement(LIST_CREATE); statement.setString(1, bodyMap.get("name").toString());//Needs safe checking statement.setString(2, cognitoID); + statement.setObject(3, Instant.now().atZone(ZoneOffset.UTC).toLocalDateTime()); System.out.println(statement); statement.executeUpdate(); connection.commit(); diff --git a/Lambdas/Lists/List/src/ListGET.java b/Lambdas/Lists/List/src/ListGET.java new file mode 100644 index 0000000..12a0889 --- /dev/null +++ b/Lambdas/Lists/List/src/ListGET.java @@ -0,0 +1,12 @@ +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + +import java.util.Map; + +public class ListGET implements RequestHandler, Object> { + + public Object handleRequest(Map inputMap, Context unfilled) { + return BasicHandler.handleRequest(inputMap, unfilled, ListGetter.class); + } + +} \ No newline at end of file diff --git a/Lambdas/Lists/List/src/ListGetter.java b/Lambdas/Lists/List/src/ListGetter.java new file mode 100644 index 0000000..9e8596a --- /dev/null +++ b/Lambdas/Lists/List/src/ListGetter.java @@ -0,0 +1,39 @@ +import com.google.gson.Gson; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; + +public class ListGetter implements CallHandler{ + private final DBConnector connector; + private final String cognitoID; + + private final String GET_LIST = "SELECT * FROM List WHERE listID = ?;"; + + public ListGetter(DBConnector connector, String cognitoID) { + this.connector = connector; + this.cognitoID = cognitoID; + } + + @Override + public Object conductAction(Map bodyMap, HashMap queryMap, String cognitoID) throws SQLException { + Connection connection = connector.getConnection(); + try { + PreparedStatement statement = connection.prepareStatement(GET_LIST); + statement.setInt(1, Integer.parseInt(queryMap.get("id"))); + System.out.println(statement); + ResultSet queryResults = statement.executeQuery(); + queryResults.first(); + System.out.println(queryResults); + String returnValue; + List retrievedItem = new List(queryResults); + System.out.println(retrievedItem); + return retrievedItem; + } finally { + connection.close(); + } + } +} diff --git a/Lambdas/Lists/List/src/ListPOST.java b/Lambdas/Lists/List/src/ListPOST.java index 13c2785..4d47863 100644 --- a/Lambdas/Lists/List/src/ListPOST.java +++ b/Lambdas/Lists/List/src/ListPOST.java @@ -3,9 +3,9 @@ import java.util.Map; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; -public class ListPOST implements RequestHandler, String>{ +public class ListPOST implements RequestHandler, Object>{ - public String handleRequest(Map inputMap, Context unfilled) { + public Object handleRequest(Map inputMap, Context unfilled) { return BasicHandler.handleRequest(inputMap, unfilled, ListAdder.class); } } diff --git a/Lambdas/Lists/pom.xml b/Lambdas/Lists/pom.xml index 8d77579..1984615 100644 --- a/Lambdas/Lists/pom.xml +++ b/Lambdas/Lists/pom.xml @@ -39,6 +39,16 @@ mariadb-java-client 2.7.0 + + org.apache.httpcomponents + httpclient + 4.5 + + + com.google.code.gson + gson + 2.8.6 + 1.11 diff --git a/Lambdas/Lists/src/main/java/BasicHandler.java b/Lambdas/Lists/src/main/java/BasicHandler.java index 8b642eb..2a7ec6e 100644 --- a/Lambdas/Lists/src/main/java/BasicHandler.java +++ b/Lambdas/Lists/src/main/java/BasicHandler.java @@ -4,17 +4,19 @@ import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.sql.SQLException; +import java.util.HashMap; import java.util.Map; public class BasicHandler { - public static String handleRequest(Map inputMap, Context unfilled, Class toCall) { + public static Object handleRequest(Map inputMap, Context unfilled, Class toCall) { String cognitoID = InputUtils.getCognitoIDFromBody(inputMap); + HashMap queryMap = InputUtils.getQueryParams(inputMap); try { DBConnector connector = new DBConnector(); try { Constructor constructor = toCall.getConstructor(DBConnector.class, String.class); CallHandler callHandler = constructor.newInstance(connector, cognitoID); - callHandler.conductAction(InputUtils.getBody(inputMap), ""); + return callHandler.conductAction(InputUtils.getBody(inputMap), queryMap, cognitoID); } catch (SQLException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } finally { diff --git a/Lambdas/Lists/src/main/java/CallHandler.java b/Lambdas/Lists/src/main/java/CallHandler.java index ac5aa2a..a637412 100644 --- a/Lambdas/Lists/src/main/java/CallHandler.java +++ b/Lambdas/Lists/src/main/java/CallHandler.java @@ -1,6 +1,7 @@ import java.sql.SQLException; +import java.util.HashMap; import java.util.Map; public interface CallHandler { - String conductAction(Map bodyMap, String cognitoID) throws SQLException; + Object conductAction(Map bodyMap, HashMap queryString, String cognitoID) throws SQLException; } diff --git a/Lambdas/Lists/src/main/java/InputUtils.java b/Lambdas/Lists/src/main/java/InputUtils.java index b10781d..2a4e8bc 100644 --- a/Lambdas/Lists/src/main/java/InputUtils.java +++ b/Lambdas/Lists/src/main/java/InputUtils.java @@ -1,3 +1,9 @@ +import org.apache.http.NameValuePair; +import org.apache.http.client.utils.URLEncodedUtils; + +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.List; import java.util.Map; public class InputUtils { @@ -19,10 +25,24 @@ public class InputUtils { return getMap(inputMap, "body"); } - public static String getQueryString(Map inputMap) { + private static String getQueryString(Map inputMap) { return (String) (getMap(inputMap, "params").get("querystring")); } + public static HashMap getQueryParams(Map inputMap) { + return (HashMap) (getMap(inputMap, "params").get("querystring")); + +// String queryString = getQueryString(inputMap); +// List queryparams = URLEncodedUtils.parse(queryString, StandardCharsets.UTF_8); +// HashMap mappedParams = new HashMap<>(); +// for (NameValuePair param : queryparams) { +// mappedParams.put(param.getName(), param.getValue()); +// } +// return mappedParams; + } + + + public static Map getMap(Map parentMap, String childKey) { if ((parentMap.get(childKey) != null) && (parentMap.get(childKey) instanceof Map)) { return ((Map) parentMap.get(childKey)); diff --git a/Listify/.idea/misc.xml b/Listify/.idea/misc.xml index fdae1d0..d5d35ec 100644 --- a/Listify/.idea/misc.xml +++ b/Listify/.idea/misc.xml @@ -1,6 +1,6 @@ - + diff --git a/Listify/app/build.gradle b/Listify/app/build.gradle index 099077a..0ad5dc3 100644 --- a/Listify/app/build.gradle +++ b/Listify/app/build.gradle @@ -50,5 +50,6 @@ dependencies { implementation 'org.json:json:20200518' implementation 'com.github.bumptech.glide:glide:4.11.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0' + implementation 'com.squareup.okhttp3:okhttp:4.8.1' } \ No newline at end of file diff --git a/Listify/app/src/main/java/com/example/listify/Item.java b/Listify/app/src/main/java/com/example/listify/Item.java new file mode 100644 index 0000000..f66f8ec --- /dev/null +++ b/Listify/app/src/main/java/com/example/listify/Item.java @@ -0,0 +1,44 @@ +package com.example.listify; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +public class Item { + Integer productID; + Integer chainID; + String upc; + String description; + BigDecimal price; + String imageURL; + String department; + LocalDateTime retrievedDate; + Integer fetchCounts; + + public Item(Integer productID, Integer chainID, String upc, String description, BigDecimal price, + String imageURL, String department, LocalDateTime retrievedDate, Integer fetchCounts) { + this.productID = productID; + this.chainID = chainID; + this.upc = upc; + this.description = description; + this.price = price; + this.imageURL = imageURL; + this.department = department; + this.retrievedDate = retrievedDate; + this.fetchCounts = fetchCounts; + } + + @Override + public String toString() { + return "Item{" + + "productID=" + productID + + ", chainID=" + chainID + + ", upc='" + upc + '\'' + + ", description='" + description + '\'' + + ", price=" + price + + ", imageURL='" + imageURL + '\'' + + ", department='" + department + '\'' + + ", retrievedDate=" + retrievedDate + + ", fetchCounts=" + fetchCounts + + '}'; + } +} diff --git a/Listify/app/src/main/java/com/example/listify/MainActivity.java b/Listify/app/src/main/java/com/example/listify/MainActivity.java index 8260ed5..59c63d4 100644 --- a/Listify/app/src/main/java/com/example/listify/MainActivity.java +++ b/Listify/app/src/main/java/com/example/listify/MainActivity.java @@ -25,6 +25,8 @@ public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + + //------------------------------Auth Testing---------------------------------------------// AuthManager authManager = new AuthManager(); @@ -46,6 +48,7 @@ public class MainActivity extends AppCompatActivity { //------------------------------------------------------------------------------------------// + //----------------------------------API Testing---------------------------------------------// Properties configs = new Properties(); try { @@ -54,7 +57,7 @@ public class MainActivity extends AppCompatActivity { e.printStackTrace(); } - Requestor requestor = new Requestor(this, authManager,configs.getProperty("apiKey")); + Requestor requestor = new Requestor(authManager,configs.getProperty("apiKey")); List testList = new List("IAmATestList"); try { requestor.postObject(testList); @@ -62,6 +65,15 @@ public class MainActivity extends AppCompatActivity { e.printStackTrace(); } + SynchronousReceiver receiver = new SynchronousReceiver(); + requestor.getObject("1", Item.class, receiver, receiver); + try { + System.out.println(receiver.await()); + } catch (IOException receiverError) { + receiverError.printStackTrace(); + } + + //------------------------------------------------------------------------------------------// diff --git a/Listify/app/src/main/java/com/example/listify/Requestor.java b/Listify/app/src/main/java/com/example/listify/Requestor.java index 0c7b48d..3032c0d 100644 --- a/Listify/app/src/main/java/com/example/listify/Requestor.java +++ b/Listify/app/src/main/java/com/example/listify/Requestor.java @@ -1,66 +1,104 @@ package com.example.listify; -import android.content.Context; -import com.android.volley.RequestQueue; -import com.android.volley.Response; -import com.android.volley.toolbox.JsonObjectRequest; -import com.android.volley.toolbox.Volley; +import android.util.Log; import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; +import okhttp3.*; +import org.jetbrains.annotations.NotNull; import org.json.JSONException; -import org.json.JSONObject; -import java.util.HashMap; -import java.util.Map; +import java.io.IOException; public class Requestor { private final String DEV_BASEURL = "https://datoh7woc9.execute-api.us-east-2.amazonaws.com/Development"; AuthManager authManager; - RequestQueue queue; String apiKey; + OkHttpClient client; - Requestor(Context context, AuthManager authManager, String apiKey) { - queue = Volley.newRequestQueue(context); + Requestor(AuthManager authManager, String apiKey) { this.authManager = authManager; this.apiKey = apiKey; + client = new OkHttpClient(); } public void getObject(String id, Class classType, Receiver receiver) { - String getURL = DEV_BASEURL + "/" + classType.getSimpleName() + "?id=" + id; + getObject(id, classType, receiver, null); } - public void postObject(Object toPost, Response.ErrorListener failureHandler) throws JSONException { - String postURL = DEV_BASEURL + "/" + toPost.getClass().getSimpleName(); - queue.add(buildRequest(postURL, toPost, null, failureHandler)); + public void getObject(String id, Class classType, Receiver successHandler, RequestErrorHandler failureHandler) { + String getURL = DEV_BASEURL + "/" + classType.getSimpleName() + "?id=" + id; + Request postRequest = buildBaseRequest(getURL, "GET", null); + launchCall(postRequest, successHandler, classType, failureHandler); } public void postObject(Object toPost) throws JSONException { postObject(toPost, null); } - private JsonObjectRequest buildRequest(String url, Object toJSONify, Response.Listener successHandler, Response.ErrorListener failureHandler) throws JSONException { - return buildRequest(url, new JSONObject(new Gson().toJson(toJSONify)), successHandler, failureHandler); + public void postObject(Object toPost, RequestErrorHandler failureHandler) throws JSONException { + String postURL = DEV_BASEURL + "/" + toPost.getClass().getSimpleName(); + Request postRequest = buildBaseRequest(postURL, "POST", new Gson().toJson(toPost)); + launchCall(postRequest, null, null, failureHandler); } - private JsonObjectRequest buildRequest(String url, JSONObject jsonBody, Response.Listener successHandler, Response.ErrorListener failureHandler) { - return new JsonObjectRequest(url, jsonBody, successHandler, failureHandler) { + + private void launchCall(Request toLaunch, Receiver receiver, Class classType, RequestErrorHandler failureHandler) { + client.newCall(toLaunch).enqueue(new Callback() { @Override - public Map getHeaders() { - HashMap headers = new HashMap<>(); - System.out.println(authManager.getUserToken()); - headers.put("Authorization", authManager.getUserToken()); - headers.put("Content-Type", "application/json"); - headers.put("X-API-Key", apiKey); - return headers; + public void onResponse(@NotNull Call call, @NotNull okhttp3.Response response) throws IOException { + String responseString = response.body().string(); + if (receiver != null) { + if (classType == null) { + Log.e("Requestor Contract Error", "classType while receiver populated"); + } + try { + receiver.acceptDelivery(new Gson().fromJson(responseString, classType)); + } catch (JsonSyntaxException e) { + System.out.println(e); + Log.e("API response was not proper JSON", responseString); + throw new JsonSyntaxException(e); + } + } + Log.d("API Response", responseString); } - }; + @Override + public void onFailure(@NotNull Call call, IOException e) { + if (failureHandler != null) { + failureHandler.acceptError(e); + } else { + Log.e("Network Error", e.getLocalizedMessage()); + } + } + }); } - public class Receiver { - public void acceptDelivery(T delivered) { + public static final MediaType JSON + = MediaType.parse("application/json; charset=utf-8"); + private Request buildBaseRequest(String url, String method, String bodyJSON) { + Request.Builder requestBase = addAuthHeaders(new Request.Builder().url(url)); + if (method == "GET") { + requestBase.get(); + } else { + requestBase.method(method, RequestBody.create(bodyJSON, JSON)); } + return requestBase.build(); + } + + private Request.Builder addAuthHeaders(Request.Builder toAuthorize) { + toAuthorize.addHeader("Authorization", authManager.getUserToken()); + toAuthorize.addHeader("X-API-Key", apiKey); + return toAuthorize; + } + + public interface Receiver { + void acceptDelivery(T delivered); + } + + public interface RequestErrorHandler { + void acceptError(IOException error); } } diff --git a/Listify/app/src/main/java/com/example/listify/SynchronousReceiver.java b/Listify/app/src/main/java/com/example/listify/SynchronousReceiver.java new file mode 100644 index 0000000..7272a3e --- /dev/null +++ b/Listify/app/src/main/java/com/example/listify/SynchronousReceiver.java @@ -0,0 +1,39 @@ +package com.example.listify; + +import java.io.IOException; + +public class SynchronousReceiver implements Requestor.Receiver, Requestor.RequestErrorHandler { + private volatile boolean waiting; + private volatile IOException error; + private T toReturn; + + public SynchronousReceiver() { + waiting = true; + error = null; + } + + public T await() throws IOException { + while (waiting) { + Thread.yield(); + } + waiting = true; + if (error != null) { + IOException toThrow = error; + error = null; + throw toThrow; + } + return toReturn; + } + + @Override + public void acceptDelivery(Object delivered) { + toReturn = (T) delivered; + waiting = false; + } + + @Override + public void acceptError(IOException error) { + waiting = false; + this.error = error + } +} From 790d935e40911670d6dda93cd4d17bd179b99175 Mon Sep 17 00:00:00 2001 From: Clayton Wilson Date: Sat, 3 Oct 2020 17:48:28 -0400 Subject: [PATCH 05/21] Layout for item details page --- Listify/app/src/main/AndroidManifest.xml | 27 +++--- .../java/com/example/listify/ItemDetails.java | 83 +++++++++++++++++++ .../com/example/listify/SearchResults.java | 19 ++++- .../com/example/listify/model/Product.java | 4 +- .../main/res/drawable/ic_baseline_add_28.xml | 5 ++ .../main/res/layout/activity_item_details.xml | 70 ++++++++++++++++ .../main/res/layout/content_item_details.xml | 80 ++++++++++++++++++ Listify/app/src/main/res/values/colors.xml | 1 + Listify/app/src/main/res/values/dimens.xml | 5 ++ Listify/app/src/main/res/values/strings.xml | 1 + 10 files changed, 280 insertions(+), 15 deletions(-) create mode 100644 Listify/app/src/main/java/com/example/listify/ItemDetails.java create mode 100644 Listify/app/src/main/res/drawable/ic_baseline_add_28.xml create mode 100644 Listify/app/src/main/res/layout/activity_item_details.xml create mode 100644 Listify/app/src/main/res/layout/content_item_details.xml diff --git a/Listify/app/src/main/AndroidManifest.xml b/Listify/app/src/main/AndroidManifest.xml index d6e08aa..170664e 100644 --- a/Listify/app/src/main/AndroidManifest.xml +++ b/Listify/app/src/main/AndroidManifest.xml @@ -1,7 +1,8 @@ - + + - + - + + + + android:theme="@style/AppTheme.NoActionBar"> + - - - - - - + + + + + \ No newline at end of file diff --git a/Listify/app/src/main/java/com/example/listify/ItemDetails.java b/Listify/app/src/main/java/com/example/listify/ItemDetails.java new file mode 100644 index 0000000..8b70f19 --- /dev/null +++ b/Listify/app/src/main/java/com/example/listify/ItemDetails.java @@ -0,0 +1,83 @@ +package com.example.listify; + +import android.os.Bundle; +import com.bumptech.glide.Glide; +import com.example.listify.model.Product; +import com.google.android.material.floatingactionbutton.FloatingActionButton; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; +import android.view.View; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.TextView; + +public class ItemDetails extends AppCompatActivity { + private Product curProduct; + private FloatingActionButton fab1; + private FloatingActionButton fab2; + private TextView tvItemName; + private TextView tvStoreName; + private ImageView itemImage; + private TextView tvItemDesc; + private ImageButton backToSearchbutton; + + private boolean isFABOpen = false; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_item_details); + Toolbar toolbar = findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + + curProduct = (Product) getIntent().getSerializableExtra("SelectedProduct"); + + FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); + fab1 = (FloatingActionButton) findViewById(R.id.fab1); + fab2 = (FloatingActionButton) findViewById(R.id.fab2); + fab.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (!isFABOpen) { + showFABMenu(); + } else { + closeFABMenu(); + } + } + }); + + tvItemName = (TextView) findViewById(R.id.item_name); + tvItemName.setText(curProduct.getItemName()); + + itemImage = (ImageView) findViewById(R.id.item_image); + Glide.with(this).load(curProduct.getImageUrl()).into(itemImage); + + tvStoreName = (TextView) findViewById(R.id.store_name); + tvStoreName.setText(curProduct.getChainName()); + + tvItemDesc = (TextView) findViewById(R.id.item_desc); + tvItemDesc.setText(curProduct.getDescription()); + + backToSearchbutton = (ImageButton) findViewById(R.id.back_to_search_results_button); + backToSearchbutton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + } + + private void showFABMenu(){ + isFABOpen=true; + fab1.animate().translationY(-getResources().getDimension(R.dimen.standard_55)); + fab2.animate().translationY(-getResources().getDimension(R.dimen.standard_105)); + } + + private void closeFABMenu(){ + isFABOpen=false; + fab1.animate().translationY(0); + fab2.animate().translationY(0); + } + + +} \ No newline at end of file diff --git a/Listify/app/src/main/java/com/example/listify/SearchResults.java b/Listify/app/src/main/java/com/example/listify/SearchResults.java index eafb400..74c80ed 100644 --- a/Listify/app/src/main/java/com/example/listify/SearchResults.java +++ b/Listify/app/src/main/java/com/example/listify/SearchResults.java @@ -79,8 +79,11 @@ public class SearchResults extends AppCompatActivity implements SortDialogFragme @Override public void onItemClick(AdapterView parent, View view, int position, long id) { // Toast.makeText(SearchResults.this, resultsProductListSorted.get(position).getItemName(), Toast.LENGTH_SHORT).show(); - Intent itemDetails = new Intent(SearchResults.this, ItemDetails.class); - startActivity(itemDetails); + Intent itemDetailsPage = new Intent(SearchResults.this, ItemDetails.class); + + // Send the selected product + itemDetailsPage.putExtra("SelectedProduct", resultsProductListSorted.get(position)); + startActivity(itemDetailsPage); } }); @@ -142,13 +145,23 @@ public class SearchResults extends AppCompatActivity implements SortDialogFragme Product c = new Product("Lettuce", "0002", "Walmart", "0001", "0123456782", "Burger King foot lettuce", "Grocery", 0.60, "9/24/2020", "1", "https://www.cattitudedaily.com/wp-content/uploads/2019/12/white-cat-meme-feature.jpg"); Product d = new Product("Video Game", "0003", "Walmart", "0001", "0123456783", "Fun Vidya Gaemz", "Electronics", 60.00, "9/24/2020", "1", "https://i1.wp.com/bestlifeonline.com/wp-content/uploads/2018/06/cat-meme-67.jpg?resize=1024%2C1024&ssl=1"); Product e = new Product("Mountain Dew", "0004", "Walmart", "0001", "0123456784", "Gamer fuel", "Grocery", 5.87, "9/24/2020", "1", "https://memeguy.com/photos/images/gaming-cat-7680.png"); - Product f = new Product("Tire", "0005", "Walmart", "0001", "0123456785", "30 inch rims", "Automotive", 146.97, "9/24/2020", "1", "http://cdn.sheknows.com/articles/2013/05/pet5.jpg"); + Product f = new Product("Tire", "0005", "Kroger", "0002", "0123456785", "30 inch rims", "Automotive", 146.97, "9/24/2020", "1", "http://cdn.sheknows.com/articles/2013/05/pet5.jpg"); + Product g = new Product("This is a test for a product that has a very long title to see if the text overflows", "0006", "Target", "0003", "0123456786", "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Elit ut aliquam purus sit amet luctus venenatis. Tellus orci ac auctor augue mauris augue neque gravida. Habitant morbi tristique senectus et netus. Dignissim diam quis enim lobortis. Suspendisse sed nisi lacus sed viverra tellus in. Viverra adipiscing at in tellus integer feugiat scelerisque. Volutpat consequat mauris nunc congue nisi vitae suscipit tellus. Habitant morbi tristique senectus et netus et malesuada. Quis enim lobortis scelerisque fermentum dui faucibus in ornare quam. Mattis pellentesque id nibh tortor id aliquet. Volutpat blandit aliquam etiam erat. Vestibulum lorem sed risus ultricies tristique nulla aliquet.\n" + + "\n" + + "Placerat orci nulla pellentesque dignissim. Quisque non tellus orci ac. Mattis enim ut tellus elementum sagittis vitae et. Interdum velit euismod in pellentesque massa placerat duis ultricies. Id nibh tortor id aliquet lectus. Massa placerat duis ultricies lacus sed. Convallis convallis tellus id interdum velit laoreet id donec. Amet luctus venenatis lectus magna fringilla urna porttitor rhoncus. Sodales ut eu sem integer vitae justo. Viverra ipsum nunc aliquet bibendum enim facilisis.\n" + + "\n" + + "Eget felis eget nunc lobortis mattis aliquam faucibus purus. Odio morbi quis commodo odio aenean sed adipiscing. Hac habitasse platea dictumst quisque sagittis purus sit. Nam libero justo laoreet sit. Et malesuada fames ac turpis egestas. Erat nam at lectus urna duis convallis convallis. Morbi tincidunt ornare massa eget egestas purus viverra accumsan in. Ut venenatis tellus in metus vulputate eu scelerisque felis imperdiet. At auctor urna nunc id cursus. Sed elementum tempus egestas sed. Lorem dolor sed viverra ipsum nunc aliquet bibendum. Orci eu lobortis elementum nibh tellus molestie. Porttitor leo a diam sollicitudin tempor. Adipiscing bibendum est ultricies integer quis auctor elit sed. Arcu cursus euismod quis viverra nibh. A diam sollicitudin tempor id eu nisl.\n" + + "\n" + + "Sapien eget mi proin sed libero enim sed faucibus turpis. Pharetra massa massa ultricies mi quis hendrerit dolor magna. Integer enim neque volutpat ac tincidunt vitae semper. Euismod lacinia at quis risus sed vulputate. Ut venenatis tellus in metus vulputate eu scelerisque. Etiam erat velit scelerisque in dictum non consectetur. Viverra nam libero justo laoreet sit amet cursus sit. Arcu non sodales neque sodales. Vivamus arcu felis bibendum ut tristique et egestas quis. Sed adipiscing diam donec adipiscing tristique risus. Sollicitudin tempor id eu nisl nunc mi ipsum faucibus vitae. Velit ut tortor pretium viverra suspendisse potenti nullam ac tortor. Non nisi est sit amet facilisis magna etiam. Tortor at risus viverra adipiscing. Donec ultrices tincidunt arcu non sodales neque sodales. Eget egestas purus viverra accumsan. Enim lobortis scelerisque fermentum dui faucibus in ornare. Porttitor massa id neque aliquam. Ut consequat semper viverra nam. Orci ac auctor augue mauris augue neque gravida.\n" + + "\n" + + "Lacus sed viverra tellus in hac habitasse platea dictumst. Nec ullamcorper sit amet risus nullam eget felis eget nunc. Semper feugiat nibh sed pulvinar. Consequat nisl vel pretium lectus quam id leo in. Volutpat maecenas volutpat blandit aliquam etiam erat velit scelerisque. Faucibus a pellentesque sit amet porttitor eget. Sed viverra tellus in hac habitasse platea dictumst vestibulum. Placerat vestibulum lectus mauris ultrices eros in cursus turpis. Sed tempus urna et pharetra pharetra massa massa ultricies mi. Ornare arcu odio ut sem. Ornare arcu dui vivamus arcu felis bibendum ut. Feugiat pretium nibh ipsum consequat. Consectetur adipiscing elit ut aliquam purus sit amet luctus venenatis. Felis eget velit aliquet sagittis id consectetur purus ut.", "Automotive", 45.22, "9/24/2020", "1", "http://cdn.sheknows.com/articles/2013/05/pet5.jpg"); resultsProductList.add(a); resultsProductList.add(b); resultsProductList.add(c); resultsProductList.add(d); resultsProductList.add(e); resultsProductList.add(f); + resultsProductList.add(g); } // Create a list of all stores in the results so the user can filter by store name diff --git a/Listify/app/src/main/java/com/example/listify/model/Product.java b/Listify/app/src/main/java/com/example/listify/model/Product.java index db52386..654ac6b 100644 --- a/Listify/app/src/main/java/com/example/listify/model/Product.java +++ b/Listify/app/src/main/java/com/example/listify/model/Product.java @@ -1,6 +1,8 @@ package com.example.listify.model; -public class Product { +import java.io.Serializable; + +public class Product implements Serializable { private String itemName; private String itemId; private String chainName; diff --git a/Listify/app/src/main/res/drawable/ic_baseline_add_28.xml b/Listify/app/src/main/res/drawable/ic_baseline_add_28.xml new file mode 100644 index 0000000..28957a3 --- /dev/null +++ b/Listify/app/src/main/res/drawable/ic_baseline_add_28.xml @@ -0,0 +1,5 @@ + + + diff --git a/Listify/app/src/main/res/layout/activity_item_details.xml b/Listify/app/src/main/res/layout/activity_item_details.xml new file mode 100644 index 0000000..feace5e --- /dev/null +++ b/Listify/app/src/main/res/layout/activity_item_details.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Listify/app/src/main/res/layout/content_item_details.xml b/Listify/app/src/main/res/layout/content_item_details.xml new file mode 100644 index 0000000..35c243a --- /dev/null +++ b/Listify/app/src/main/res/layout/content_item_details.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Listify/app/src/main/res/values/colors.xml b/Listify/app/src/main/res/values/colors.xml index c6d89eb..a9055a6 100644 --- a/Listify/app/src/main/res/values/colors.xml +++ b/Listify/app/src/main/res/values/colors.xml @@ -10,4 +10,5 @@ #ffffff #ebeef0 #1c9ef4 + #e6e6e6 \ No newline at end of file diff --git a/Listify/app/src/main/res/values/dimens.xml b/Listify/app/src/main/res/values/dimens.xml index 4ab4520..2a14b50 100644 --- a/Listify/app/src/main/res/values/dimens.xml +++ b/Listify/app/src/main/res/values/dimens.xml @@ -5,4 +5,9 @@ 8dp 176dp 16dp + 20dp + + 55dp + 105dp + 155dp \ No newline at end of file diff --git a/Listify/app/src/main/res/values/strings.xml b/Listify/app/src/main/res/values/strings.xml index 6299f7d..8869c5d 100644 --- a/Listify/app/src/main/res/values/strings.xml +++ b/Listify/app/src/main/res/values/strings.xml @@ -29,4 +29,5 @@ Search Button SearchResults Store selection + ItemDetails \ No newline at end of file From 1f361cf401a2e5c58c82d13b1a92f3d8eb2bcd73 Mon Sep 17 00:00:00 2001 From: NMerz Date: Sat, 3 Oct 2020 18:35:27 -0400 Subject: [PATCH 06/21] Finish V1 of List and Item Lambdas List and Item Lambdas and client calls should be roughly finished (pending full testing once databse config is done). --- Lambdas/Lists/Item/src/Item.java | 72 +++++++++++++++++++ Lambdas/Lists/Item/src/ItemDELETE.java | 11 +++ Lambdas/Lists/Item/src/ItemDeleter.java | 33 +++++++++ Lambdas/Lists/List/src/ItemEntry.java | 32 +++++++++ Lambdas/Lists/List/src/List.java | 44 +++++++++++- Lambdas/Lists/List/src/ListGetter.java | 39 +++++++--- .../java/com/example/listify/Requestor.java | 6 ++ .../example/listify/SynchronousReceiver.java | 2 +- 8 files changed, 227 insertions(+), 12 deletions(-) create mode 100644 Lambdas/Lists/Item/src/ItemDELETE.java create mode 100644 Lambdas/Lists/Item/src/ItemDeleter.java diff --git a/Lambdas/Lists/Item/src/Item.java b/Lambdas/Lists/Item/src/Item.java index 53ef341..dcdbdd6 100644 --- a/Lambdas/Lists/Item/src/Item.java +++ b/Lambdas/Lists/Item/src/Item.java @@ -49,4 +49,76 @@ public class Item { ", fetchCounts=" + fetchCounts + '}'; } + + public Integer getProductID() { + return productID; + } + + public void setProductID(Integer productID) { + this.productID = productID; + } + + public Integer getChainID() { + return chainID; + } + + public void setChainID(Integer chainID) { + this.chainID = chainID; + } + + public String getUpc() { + return upc; + } + + public void setUpc(String upc) { + this.upc = upc; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public BigDecimal getPrice() { + return price; + } + + public void setPrice(BigDecimal price) { + this.price = price; + } + + public String getImageURL() { + return imageURL; + } + + public void setImageURL(String imageURL) { + this.imageURL = imageURL; + } + + public String getDepartment() { + return department; + } + + public void setDepartment(String department) { + this.department = department; + } + + public LocalDateTime getRetrievedDate() { + return retrievedDate; + } + + public void setRetrievedDate(LocalDateTime retrievedDate) { + this.retrievedDate = retrievedDate; + } + + public Integer getFetchCounts() { + return fetchCounts; + } + + public void setFetchCounts(Integer fetchCounts) { + this.fetchCounts = fetchCounts; + } } diff --git a/Lambdas/Lists/Item/src/ItemDELETE.java b/Lambdas/Lists/Item/src/ItemDELETE.java new file mode 100644 index 0000000..7d0f1ee --- /dev/null +++ b/Lambdas/Lists/Item/src/ItemDELETE.java @@ -0,0 +1,11 @@ +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + +import java.util.Map; + +public class ItemDELETE implements RequestHandler, Object> { + + public Object handleRequest(Map inputMap, Context unfilled) { + return BasicHandler.handleRequest(inputMap, unfilled, ItemGetter.class); + } +} \ No newline at end of file diff --git a/Lambdas/Lists/Item/src/ItemDeleter.java b/Lambdas/Lists/Item/src/ItemDeleter.java new file mode 100644 index 0000000..ad03a91 --- /dev/null +++ b/Lambdas/Lists/Item/src/ItemDeleter.java @@ -0,0 +1,33 @@ +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; + +public class ItemDeleter implements CallHandler { + + private DBConnector connector; + private String cognitoID; + + private final String REMOVE_FROM_LIST = "DELETE FROM ListProduct WHERE (ProductID = ? AND ListID = ?);"; + + public ItemDeleter(DBConnector connector, String cognitoID) { + this.connector = connector; + this.cognitoID = cognitoID; + } + + public Object conductAction(Map bodyMap, HashMap queryString, String cognitoID) throws SQLException { + Connection connection = connector.getConnection(); + try { + PreparedStatement statement = connection.prepareStatement(REMOVE_FROM_LIST); + statement.setInt(1, (Integer) bodyMap.get("ProductID")); + statement.setInt(2, (Integer) bodyMap.get("ListID")); + System.out.println(statement); + statement.executeUpdate(); + connection.commit(); + } finally { + connection.close(); + } + return null; + } +} diff --git a/Lambdas/Lists/List/src/ItemEntry.java b/Lambdas/Lists/List/src/ItemEntry.java index b05ddc7..513d4ae 100644 --- a/Lambdas/Lists/List/src/ItemEntry.java +++ b/Lambdas/Lists/List/src/ItemEntry.java @@ -13,4 +13,36 @@ public class ItemEntry { addedDate = listRow.getObject(3, LocalDateTime.class); purchased = listRow.getBoolean(4); } + + public Integer getProductID() { + return productID; + } + + public void setProductID(Integer productID) { + this.productID = productID; + } + + public Integer getQuantity() { + return quantity; + } + + public void setQuantity(Integer quantity) { + this.quantity = quantity; + } + + public LocalDateTime getAddedDate() { + return addedDate; + } + + public void setAddedDate(LocalDateTime addedDate) { + this.addedDate = addedDate; + } + + public Boolean getPurchased() { + return purchased; + } + + public void setPurchased(Boolean purchased) { + this.purchased = purchased; + } } diff --git a/Lambdas/Lists/List/src/List.java b/Lambdas/Lists/List/src/List.java index c2ac9c6..5f9c4f5 100644 --- a/Lambdas/Lists/List/src/List.java +++ b/Lambdas/Lists/List/src/List.java @@ -1,18 +1,60 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.time.LocalDateTime; +import java.util.ArrayList; public class List { Integer itemID; String name; String owner; LocalDateTime lastUpdated; + ArrayList entries; public List(ResultSet listRow) throws SQLException { itemID = listRow.getInt(1); name = listRow.getString(2); owner = listRow.getString(3); - lastUpdated = listRow.getObject(8, LocalDateTime.class); + lastUpdated = listRow.getObject(4, LocalDateTime.class); + entries = new ArrayList<>(); } + public void addItemEntry(ItemEntry entry) { + entries.add(entry); + } + + public ItemEntry[] getEntries() { + return entries.toArray(new ItemEntry[entries.size()]); + } + + public Integer getItemID() { + return itemID; + } + + public void setItemID(Integer itemID) { + this.itemID = itemID; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getOwner() { + return owner; + } + + public void setOwner(String owner) { + this.owner = owner; + } + + public LocalDateTime getLastUpdated() { + return lastUpdated; + } + + public void setLastUpdated(LocalDateTime lastUpdated) { + this.lastUpdated = lastUpdated; + } } diff --git a/Lambdas/Lists/List/src/ListGetter.java b/Lambdas/Lists/List/src/ListGetter.java index 9e8596a..3e4ff1e 100644 --- a/Lambdas/Lists/List/src/ListGetter.java +++ b/Lambdas/Lists/List/src/ListGetter.java @@ -4,6 +4,7 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.ArrayList; import java.util.HashMap; import java.util.Map; @@ -12,6 +13,8 @@ public class ListGetter implements CallHandler{ private final String cognitoID; private final String GET_LIST = "SELECT * FROM List WHERE listID = ?;"; + private final String GET_LISTS = "SELECT listID FROM List WHERE owner = ?;"; + private final String GET_ENTRIES = "SELECT * FROM ListProduct WHERE listID = ?;"; public ListGetter(DBConnector connector, String cognitoID) { this.connector = connector; @@ -21,17 +24,33 @@ public class ListGetter implements CallHandler{ @Override public Object conductAction(Map bodyMap, HashMap queryMap, String cognitoID) throws SQLException { Connection connection = connector.getConnection(); + Integer id = Integer.parseInt(queryMap.get("id")); try { - PreparedStatement statement = connection.prepareStatement(GET_LIST); - statement.setInt(1, Integer.parseInt(queryMap.get("id"))); - System.out.println(statement); - ResultSet queryResults = statement.executeQuery(); - queryResults.first(); - System.out.println(queryResults); - String returnValue; - List retrievedItem = new List(queryResults); - System.out.println(retrievedItem); - return retrievedItem; + if (id == -1) { + PreparedStatement getLists = connection.prepareStatement(GET_LISTS); + getLists.setString(1, cognitoID); + ResultSet getListsResults = getLists.executeQuery(); + ArrayList listIds = new ArrayList<>(); + while (getListsResults.next()) { + listIds.add(getListsResults.getInt(1)); + } + return listIds; + } + PreparedStatement getList = connection.prepareStatement(GET_LIST); + getList.setInt(1, id); + System.out.println(getList); + ResultSet getListResults = getList.executeQuery(); + getListResults.first(); + System.out.println(getListResults); + List retrievedList = new List(getListResults); + System.out.println(retrievedList); + PreparedStatement getListEntries = connection.prepareStatement(GET_ENTRIES); + getListEntries.setInt(1, id); + ResultSet getEntryResults = getListEntries.executeQuery(); + while (getEntryResults.next()) { + retrievedList.addItemEntry(new ItemEntry(getEntryResults)); + } + return retrievedList; } finally { connection.close(); } diff --git a/Listify/app/src/main/java/com/example/listify/Requestor.java b/Listify/app/src/main/java/com/example/listify/Requestor.java index 3032c0d..2134ac8 100644 --- a/Listify/app/src/main/java/com/example/listify/Requestor.java +++ b/Listify/app/src/main/java/com/example/listify/Requestor.java @@ -28,6 +28,12 @@ public class Requestor { getObject(id, classType, receiver, null); } + public void getListOfIds(Class ofType, Receiver successHandler, RequestErrorHandler failureHandler) { + String getURL = DEV_BASEURL + "/" + ofType.getSimpleName() + "?list=-1"; + Request postRequest = buildBaseRequest(getURL, "GET", null); + launchCall(postRequest, successHandler, Integer[].class, failureHandler); + } + public void getObject(String id, Class classType, Receiver successHandler, RequestErrorHandler failureHandler) { String getURL = DEV_BASEURL + "/" + classType.getSimpleName() + "?id=" + id; Request postRequest = buildBaseRequest(getURL, "GET", null); diff --git a/Listify/app/src/main/java/com/example/listify/SynchronousReceiver.java b/Listify/app/src/main/java/com/example/listify/SynchronousReceiver.java index 7272a3e..74ca055 100644 --- a/Listify/app/src/main/java/com/example/listify/SynchronousReceiver.java +++ b/Listify/app/src/main/java/com/example/listify/SynchronousReceiver.java @@ -34,6 +34,6 @@ public class SynchronousReceiver implements Requestor.Receiver, Requestor. @Override public void acceptError(IOException error) { waiting = false; - this.error = error + this.error = error; } } From b269bc6e78e44ced61dfeed9255d846c95d134aa Mon Sep 17 00:00:00 2001 From: Clayton Wilson Date: Sat, 3 Oct 2020 21:50:21 -0400 Subject: [PATCH 07/21] Item details layout --- .../java/com/example/listify/ItemDetails.java | 35 +++++++--- .../main/res/drawable/ic_baseline_add_28.xml | 2 +- .../res/drawable/ic_baseline_create_28.xml | 5 ++ .../res/drawable/ic_baseline_post_add_28.xml | 9 +++ .../main/res/layout/activity_item_details.xml | 68 +++++++++++++------ .../main/res/layout/content_item_details.xml | 67 +++++++++--------- Listify/app/src/main/res/values/strings.xml | 7 ++ 7 files changed, 128 insertions(+), 65 deletions(-) create mode 100644 Listify/app/src/main/res/drawable/ic_baseline_create_28.xml create mode 100644 Listify/app/src/main/res/drawable/ic_baseline_post_add_28.xml diff --git a/Listify/app/src/main/java/com/example/listify/ItemDetails.java b/Listify/app/src/main/java/com/example/listify/ItemDetails.java index 8b70f19..8da738f 100644 --- a/Listify/app/src/main/java/com/example/listify/ItemDetails.java +++ b/Listify/app/src/main/java/com/example/listify/ItemDetails.java @@ -9,15 +9,19 @@ import androidx.appcompat.widget.Toolbar; import android.view.View; import android.widget.ImageButton; import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.TextView; public class ItemDetails extends AppCompatActivity { private Product curProduct; - private FloatingActionButton fab1; - private FloatingActionButton fab2; + private LinearLayout lin1; + private LinearLayout lin2; + private TextView tvCreateNew; + private TextView tvAddItem; private TextView tvItemName; private TextView tvStoreName; private ImageView itemImage; + private TextView tvItemPrice; private TextView tvItemDesc; private ImageButton backToSearchbutton; @@ -33,8 +37,10 @@ public class ItemDetails extends AppCompatActivity { curProduct = (Product) getIntent().getSerializableExtra("SelectedProduct"); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); - fab1 = (FloatingActionButton) findViewById(R.id.fab1); - fab2 = (FloatingActionButton) findViewById(R.id.fab2); +// fab1 = (FloatingActionButton) findViewById(R.id.fab1); +// fab2 = (FloatingActionButton) findViewById(R.id.fab2); + lin1 = (LinearLayout) findViewById(R.id.lin1); + lin2 = (LinearLayout) findViewById(R.id.lin2); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { @@ -55,9 +61,18 @@ public class ItemDetails extends AppCompatActivity { tvStoreName = (TextView) findViewById(R.id.store_name); tvStoreName.setText(curProduct.getChainName()); + tvItemPrice = (TextView) findViewById(R.id.item_price); + tvItemPrice.setText(String.format("$%.2f", curProduct.getPrice())); + tvItemDesc = (TextView) findViewById(R.id.item_desc); tvItemDesc.setText(curProduct.getDescription()); + tvCreateNew = (TextView) findViewById(R.id.create_new_list); + tvCreateNew.setVisibility(View.INVISIBLE); + + tvAddItem = (TextView) findViewById(R.id.add_item_to_list); + tvAddItem.setVisibility(View.INVISIBLE); + backToSearchbutton = (ImageButton) findViewById(R.id.back_to_search_results_button); backToSearchbutton.setOnClickListener(new View.OnClickListener() { @Override @@ -69,14 +84,18 @@ public class ItemDetails extends AppCompatActivity { private void showFABMenu(){ isFABOpen=true; - fab1.animate().translationY(-getResources().getDimension(R.dimen.standard_55)); - fab2.animate().translationY(-getResources().getDimension(R.dimen.standard_105)); + lin1.animate().translationY(-getResources().getDimension(R.dimen.standard_55)); + lin2.animate().translationY(-getResources().getDimension(R.dimen.standard_105)); + tvAddItem.setVisibility(View.VISIBLE); + tvCreateNew.setVisibility(View.VISIBLE); } private void closeFABMenu(){ isFABOpen=false; - fab1.animate().translationY(0); - fab2.animate().translationY(0); + lin1.animate().translationY(0); + lin2.animate().translationY(0); + tvAddItem.setVisibility(View.INVISIBLE); + tvCreateNew.setVisibility(View.INVISIBLE); } diff --git a/Listify/app/src/main/res/drawable/ic_baseline_add_28.xml b/Listify/app/src/main/res/drawable/ic_baseline_add_28.xml index 28957a3..f320e60 100644 --- a/Listify/app/src/main/res/drawable/ic_baseline_add_28.xml +++ b/Listify/app/src/main/res/drawable/ic_baseline_add_28.xml @@ -1,4 +1,4 @@ - diff --git a/Listify/app/src/main/res/drawable/ic_baseline_create_28.xml b/Listify/app/src/main/res/drawable/ic_baseline_create_28.xml new file mode 100644 index 0000000..3740c94 --- /dev/null +++ b/Listify/app/src/main/res/drawable/ic_baseline_create_28.xml @@ -0,0 +1,5 @@ + + + diff --git a/Listify/app/src/main/res/drawable/ic_baseline_post_add_28.xml b/Listify/app/src/main/res/drawable/ic_baseline_post_add_28.xml new file mode 100644 index 0000000..4b9cc60 --- /dev/null +++ b/Listify/app/src/main/res/drawable/ic_baseline_post_add_28.xml @@ -0,0 +1,9 @@ + + + + + + + diff --git a/Listify/app/src/main/res/layout/activity_item_details.xml b/Listify/app/src/main/res/layout/activity_item_details.xml index feace5e..6ad4ac1 100644 --- a/Listify/app/src/main/res/layout/activity_item_details.xml +++ b/Listify/app/src/main/res/layout/activity_item_details.xml @@ -34,21 +34,56 @@ - + android:layout_marginBottom="22dp"> - + + + + + + android:layout_marginBottom="22dp"> + + + + + + + + - - - - - - - - - \ No newline at end of file diff --git a/Listify/app/src/main/res/layout/content_item_details.xml b/Listify/app/src/main/res/layout/content_item_details.xml index 35c243a..0e98ba7 100644 --- a/Listify/app/src/main/res/layout/content_item_details.xml +++ b/Listify/app/src/main/res/layout/content_item_details.xml @@ -13,28 +13,24 @@ android:layout_marginStart="50dp" android:layout_marginTop="16dp" android:layout_marginEnd="50dp" - android:text="Product Name" + android:text="@string/default_product_name" android:textSize="16sp" android:textStyle="bold" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> - - - - - - - - - - - - - - - + + app:layout_constraintTop_toTopOf="parent" + android:contentDescription="@string/product_image_description" /> + + - - \ No newline at end of file diff --git a/Listify/app/src/main/res/values/strings.xml b/Listify/app/src/main/res/values/strings.xml index 8869c5d..2de5c80 100644 --- a/Listify/app/src/main/res/values/strings.xml +++ b/Listify/app/src/main/res/values/strings.xml @@ -30,4 +30,11 @@ SearchResults Store selection ItemDetails + Add to list + Create new list + Product Name + Store + $00.00 + Description + Product Image \ No newline at end of file From 81b4673766c1fea78523cde26bf61140dd04289c Mon Sep 17 00:00:00 2001 From: NMerz Date: Sat, 3 Oct 2020 23:00:19 -0400 Subject: [PATCH 08/21] Lamdba Integration Test Lamdbas with full pipeline of client through database --- Lambdas/Lists/List/src/ItemEntry.java | 4 +- Lambdas/Lists/List/src/List.java | 26 ++-- Lambdas/Lists/List/src/ListAdder.java | 13 +- Lambdas/Lists/List/src/ListGetter.java | 12 +- .../src/ListEntryAdder.java} | 6 +- .../src/ListEntryDELETE.java} | 4 +- .../src/ListEntryDeleter.java} | 4 +- .../src/ListEntryPOST.java} | 4 +- Lambdas/Lists/src/main/java/BasicHandler.java | 2 +- .../java/com/example/listify/AuthManager.java | 7 ++ .../main/java/com/example/listify/Item.java | 44 ------- .../main/java/com/example/listify/List.java | 8 -- .../com/example/listify/MainActivity.java | 101 +++++++++------ .../java/com/example/listify/Requestor.java | 17 ++- .../java/com/example/listify/data/Item.java | 116 ++++++++++++++++++ .../java/com/example/listify/data/List.java | 70 +++++++++++ .../com/example/listify/data/ListEntry.java | 70 +++++++++++ Tooling/EndpointSetup.sh | 2 +- 18 files changed, 386 insertions(+), 124 deletions(-) rename Lambdas/Lists/{Item/src/ItemAdder.java => ListEntry/src/ListEntryAdder.java} (87%) rename Lambdas/Lists/{Item/src/ItemDELETE.java => ListEntry/src/ListEntryDELETE.java} (57%) rename Lambdas/Lists/{Item/src/ItemDeleter.java => ListEntry/src/ListEntryDeleter.java} (89%) rename Lambdas/Lists/{Item/src/ItemPOST.java => ListEntry/src/ListEntryPOST.java} (57%) delete mode 100644 Listify/app/src/main/java/com/example/listify/Item.java delete mode 100644 Listify/app/src/main/java/com/example/listify/List.java create mode 100644 Listify/app/src/main/java/com/example/listify/data/Item.java create mode 100644 Listify/app/src/main/java/com/example/listify/data/List.java create mode 100644 Listify/app/src/main/java/com/example/listify/data/ListEntry.java diff --git a/Lambdas/Lists/List/src/ItemEntry.java b/Lambdas/Lists/List/src/ItemEntry.java index 513d4ae..f03e910 100644 --- a/Lambdas/Lists/List/src/ItemEntry.java +++ b/Lambdas/Lists/List/src/ItemEntry.java @@ -3,11 +3,13 @@ import java.sql.SQLException; import java.time.LocalDateTime; public class ItemEntry { + Integer listID; Integer productID; Integer quantity; LocalDateTime addedDate; Boolean purchased; - public ItemEntry(ResultSet listRow) throws SQLException { + public ItemEntry(Integer listID, ResultSet listRow) throws SQLException { + this.listID = listID; productID = listRow.getInt(1); quantity = listRow.getInt(2); addedDate = listRow.getObject(3, LocalDateTime.class); diff --git a/Lambdas/Lists/List/src/List.java b/Lambdas/Lists/List/src/List.java index 5f9c4f5..1216c26 100644 --- a/Lambdas/Lists/List/src/List.java +++ b/Lambdas/Lists/List/src/List.java @@ -1,5 +1,6 @@ import java.sql.ResultSet; import java.sql.SQLException; +import java.time.Instant; import java.time.LocalDateTime; import java.util.ArrayList; @@ -7,14 +8,14 @@ public class List { Integer itemID; String name; String owner; - LocalDateTime lastUpdated; + long lastUpdated; ArrayList entries; public List(ResultSet listRow) throws SQLException { - itemID = listRow.getInt(1); - name = listRow.getString(2); - owner = listRow.getString(3); - lastUpdated = listRow.getObject(4, LocalDateTime.class); + itemID = listRow.getInt("listID"); + name = listRow.getString("name"); + owner = listRow.getString("owner"); + lastUpdated = listRow.getTimestamp("lastUpdated").toInstant().toEpochMilli(); entries = new ArrayList<>(); } @@ -22,6 +23,17 @@ public class List { entries.add(entry); } + @Override + public String toString() { + return "List{" + + "itemID=" + itemID + + ", name='" + name + '\'' + + ", owner='" + owner + '\'' + + ", lastUpdated=" + lastUpdated + + ", entries=" + entries + + '}'; + } + public ItemEntry[] getEntries() { return entries.toArray(new ItemEntry[entries.size()]); } @@ -50,11 +62,11 @@ public class List { this.owner = owner; } - public LocalDateTime getLastUpdated() { + public long getLastUpdated() { return lastUpdated; } - public void setLastUpdated(LocalDateTime lastUpdated) { + public void setLastUpdated(long lastUpdated) { this.lastUpdated = lastUpdated; } } diff --git a/Lambdas/Lists/List/src/ListAdder.java b/Lambdas/Lists/List/src/ListAdder.java index eb56e36..011cbc9 100644 --- a/Lambdas/Lists/List/src/ListAdder.java +++ b/Lambdas/Lists/List/src/ListAdder.java @@ -1,6 +1,4 @@ -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.SQLException; +import java.sql.*; import java.time.Instant; import java.time.ZoneOffset; import java.util.HashMap; @@ -20,13 +18,16 @@ public class ListAdder implements CallHandler { public Object conductAction(Map bodyMap, HashMap queryString, String cognitoID) throws SQLException { Connection connection = connector.getConnection(); - PreparedStatement statement = connection.prepareStatement(LIST_CREATE); + PreparedStatement statement = connection.prepareStatement(LIST_CREATE, Statement.RETURN_GENERATED_KEYS); statement.setString(1, bodyMap.get("name").toString());//Needs safe checking statement.setString(2, cognitoID); - statement.setObject(3, Instant.now().atZone(ZoneOffset.UTC).toLocalDateTime()); + statement.setTimestamp(3, Timestamp.from(Instant.now())); System.out.println(statement); statement.executeUpdate(); + ResultSet newIDRS = statement.getGeneratedKeys(); + newIDRS.first(); + Integer newID = newIDRS.getInt(1); connection.commit(); - return null; + return newID; } } diff --git a/Lambdas/Lists/List/src/ListGetter.java b/Lambdas/Lists/List/src/ListGetter.java index 3e4ff1e..e34366c 100644 --- a/Lambdas/Lists/List/src/ListGetter.java +++ b/Lambdas/Lists/List/src/ListGetter.java @@ -23,13 +23,14 @@ public class ListGetter implements CallHandler{ @Override public Object conductAction(Map bodyMap, HashMap queryMap, String cognitoID) throws SQLException { - Connection connection = connector.getConnection(); - Integer id = Integer.parseInt(queryMap.get("id")); - try { + try (Connection connection = connector.getConnection()) { + Integer id = Integer.parseInt(queryMap.get("id")); if (id == -1) { PreparedStatement getLists = connection.prepareStatement(GET_LISTS); getLists.setString(1, cognitoID); + System.out.println(getLists); ResultSet getListsResults = getLists.executeQuery(); + System.out.println(getListsResults); ArrayList listIds = new ArrayList<>(); while (getListsResults.next()) { listIds.add(getListsResults.getInt(1)); @@ -48,11 +49,10 @@ public class ListGetter implements CallHandler{ getListEntries.setInt(1, id); ResultSet getEntryResults = getListEntries.executeQuery(); while (getEntryResults.next()) { - retrievedList.addItemEntry(new ItemEntry(getEntryResults)); + retrievedList.addItemEntry(new ItemEntry(id, getEntryResults)); } + System.out.println(retrievedList); return retrievedList; - } finally { - connection.close(); } } } diff --git a/Lambdas/Lists/Item/src/ItemAdder.java b/Lambdas/Lists/ListEntry/src/ListEntryAdder.java similarity index 87% rename from Lambdas/Lists/Item/src/ItemAdder.java rename to Lambdas/Lists/ListEntry/src/ListEntryAdder.java index c698a04..2145cd5 100644 --- a/Lambdas/Lists/Item/src/ItemAdder.java +++ b/Lambdas/Lists/ListEntry/src/ListEntryAdder.java @@ -6,14 +6,14 @@ import java.time.ZoneOffset; import java.util.HashMap; import java.util.Map; -public class ItemAdder implements CallHandler { +public class ListEntryAdder implements CallHandler { private DBConnector connector; private String cognitoID; private final String ITEM_TO_LIST = "INSERT INTO ListProduct (productID, listID, quantity, addedDate, purchased) VALUES (?, ?, ?, ?, ?)"; - public ItemAdder(DBConnector connector, String cognitoID) { + public ListEntryAdder(DBConnector connector, String cognitoID) { this.connector = connector; this.cognitoID = cognitoID; } @@ -22,7 +22,7 @@ public class ItemAdder implements CallHandler { Connection connection = connector.getConnection(); try { PreparedStatement statement = connection.prepareStatement(ITEM_TO_LIST); - statement.setInt(1, (Integer) bodyMap.get("itemID")); + statement.setInt(1, (Integer) bodyMap.get("productID")); statement.setInt(2, (Integer) bodyMap.get("listID")); statement.setInt(3, (Integer) bodyMap.get("quantity")); statement.setObject(4, Instant.now().atZone(ZoneOffset.UTC).toLocalDateTime()); diff --git a/Lambdas/Lists/Item/src/ItemDELETE.java b/Lambdas/Lists/ListEntry/src/ListEntryDELETE.java similarity index 57% rename from Lambdas/Lists/Item/src/ItemDELETE.java rename to Lambdas/Lists/ListEntry/src/ListEntryDELETE.java index 7d0f1ee..ad3045d 100644 --- a/Lambdas/Lists/Item/src/ItemDELETE.java +++ b/Lambdas/Lists/ListEntry/src/ListEntryDELETE.java @@ -3,9 +3,9 @@ import com.amazonaws.services.lambda.runtime.RequestHandler; import java.util.Map; -public class ItemDELETE implements RequestHandler, Object> { +public class ListEntryDELETE implements RequestHandler, Object> { public Object handleRequest(Map inputMap, Context unfilled) { - return BasicHandler.handleRequest(inputMap, unfilled, ItemGetter.class); + return BasicHandler.handleRequest(inputMap, unfilled, ListEntryDeleter.class); } } \ No newline at end of file diff --git a/Lambdas/Lists/Item/src/ItemDeleter.java b/Lambdas/Lists/ListEntry/src/ListEntryDeleter.java similarity index 89% rename from Lambdas/Lists/Item/src/ItemDeleter.java rename to Lambdas/Lists/ListEntry/src/ListEntryDeleter.java index ad03a91..af074cd 100644 --- a/Lambdas/Lists/Item/src/ItemDeleter.java +++ b/Lambdas/Lists/ListEntry/src/ListEntryDeleter.java @@ -4,14 +4,14 @@ import java.sql.SQLException; import java.util.HashMap; import java.util.Map; -public class ItemDeleter implements CallHandler { +public class ListEntryDeleter implements CallHandler { private DBConnector connector; private String cognitoID; private final String REMOVE_FROM_LIST = "DELETE FROM ListProduct WHERE (ProductID = ? AND ListID = ?);"; - public ItemDeleter(DBConnector connector, String cognitoID) { + public ListEntryDeleter(DBConnector connector, String cognitoID) { this.connector = connector; this.cognitoID = cognitoID; } diff --git a/Lambdas/Lists/Item/src/ItemPOST.java b/Lambdas/Lists/ListEntry/src/ListEntryPOST.java similarity index 57% rename from Lambdas/Lists/Item/src/ItemPOST.java rename to Lambdas/Lists/ListEntry/src/ListEntryPOST.java index 51d107f..828c43c 100644 --- a/Lambdas/Lists/Item/src/ItemPOST.java +++ b/Lambdas/Lists/ListEntry/src/ListEntryPOST.java @@ -3,9 +3,9 @@ import com.amazonaws.services.lambda.runtime.RequestHandler; import java.util.Map; -public class ItemPOST implements RequestHandler, Object> { +public class ListEntryPOST implements RequestHandler, Object> { public Object handleRequest(Map inputMap, Context unfilled) { - return BasicHandler.handleRequest(inputMap, unfilled, ItemAdder.class); + return BasicHandler.handleRequest(inputMap, unfilled, ListEntryAdder.class); } } diff --git a/Lambdas/Lists/src/main/java/BasicHandler.java b/Lambdas/Lists/src/main/java/BasicHandler.java index 2a7ec6e..8c3e1d3 100644 --- a/Lambdas/Lists/src/main/java/BasicHandler.java +++ b/Lambdas/Lists/src/main/java/BasicHandler.java @@ -24,7 +24,7 @@ public class BasicHandler { } } catch (IOException |SQLException|ClassNotFoundException e) { e.printStackTrace(); - throw new RuntimeException(e.getMessage()); + throw new RuntimeException(e.getLocalizedMessage()); } return null; } diff --git a/Listify/app/src/main/java/com/example/listify/AuthManager.java b/Listify/app/src/main/java/com/example/listify/AuthManager.java index 4e67ed3..030fb88 100644 --- a/Listify/app/src/main/java/com/example/listify/AuthManager.java +++ b/Listify/app/src/main/java/com/example/listify/AuthManager.java @@ -44,6 +44,13 @@ public class AuthManager { } public String getUserToken() { + if (authSession == null) { + try { + fetchAuthSession(); + } catch (AuthException e) { + e.printStackTrace(); + } + } return authSession.getUserPoolTokens().getValue().getIdToken(); } diff --git a/Listify/app/src/main/java/com/example/listify/Item.java b/Listify/app/src/main/java/com/example/listify/Item.java deleted file mode 100644 index f66f8ec..0000000 --- a/Listify/app/src/main/java/com/example/listify/Item.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.example.listify; - -import java.math.BigDecimal; -import java.time.LocalDateTime; - -public class Item { - Integer productID; - Integer chainID; - String upc; - String description; - BigDecimal price; - String imageURL; - String department; - LocalDateTime retrievedDate; - Integer fetchCounts; - - public Item(Integer productID, Integer chainID, String upc, String description, BigDecimal price, - String imageURL, String department, LocalDateTime retrievedDate, Integer fetchCounts) { - this.productID = productID; - this.chainID = chainID; - this.upc = upc; - this.description = description; - this.price = price; - this.imageURL = imageURL; - this.department = department; - this.retrievedDate = retrievedDate; - this.fetchCounts = fetchCounts; - } - - @Override - public String toString() { - return "Item{" + - "productID=" + productID + - ", chainID=" + chainID + - ", upc='" + upc + '\'' + - ", description='" + description + '\'' + - ", price=" + price + - ", imageURL='" + imageURL + '\'' + - ", department='" + department + '\'' + - ", retrievedDate=" + retrievedDate + - ", fetchCounts=" + fetchCounts + - '}'; - } -} diff --git a/Listify/app/src/main/java/com/example/listify/List.java b/Listify/app/src/main/java/com/example/listify/List.java deleted file mode 100644 index 3a828b1..0000000 --- a/Listify/app/src/main/java/com/example/listify/List.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.example.listify; - -public class List { - String name; - List(String name) { - this.name = name; - } -} diff --git a/Listify/app/src/main/java/com/example/listify/MainActivity.java b/Listify/app/src/main/java/com/example/listify/MainActivity.java index 59c63d4..99ff02d 100644 --- a/Listify/app/src/main/java/com/example/listify/MainActivity.java +++ b/Listify/app/src/main/java/com/example/listify/MainActivity.java @@ -13,11 +13,18 @@ import androidx.navigation.Navigation; import androidx.navigation.ui.AppBarConfiguration; import androidx.navigation.ui.NavigationUI; import com.amplifyframework.auth.AuthException; +import com.example.listify.data.Item; +import com.example.listify.data.ListEntry; +import com.example.listify.data.List; import com.google.android.material.navigation.NavigationView; import org.json.JSONException; import java.io.IOException; +import java.time.Instant; +import java.time.ZoneOffset; +import java.util.Arrays; import java.util.Properties; +import java.util.Random; public class MainActivity extends AppCompatActivity { private AppBarConfiguration mAppBarConfiguration; @@ -29,51 +36,73 @@ public class MainActivity extends AppCompatActivity { //------------------------------Auth Testing---------------------------------------------// - AuthManager authManager = new AuthManager(); - try { - authManager.signIn("merzn@purdue.edu", "Password123"); - Log.i("Authentication", authManager.getAuthSession().toString()); - Log.i("Token", authManager.getAuthSession().getUserPoolTokens().getValue().getIdToken()); - } catch (AuthException e) { - Log.i("Authentication", "Login failed. User probably needs to register. Exact error: " + e.getMessage()); + boolean testAuth = false; + + if (testAuth) { + + AuthManager authManager = new AuthManager(); try { - authManager.startSignUp("merzn@purdue.edu", "Password123"); - authManager.confirmSignUp("######"); - } catch (AuthException signUpError) { - Log.e("Authentication", "SignUp error: " + signUpError.getMessage()); + authManager.signIn("merzn@purdue.edu", "Password123"); + Log.i("Authentication", authManager.getAuthSession().toString()); + Log.i("Token", authManager.getAuthSession().getUserPoolTokens().getValue().getIdToken()); + } catch (AuthException e) { + Log.i("Authentication", "Login failed. User probably needs to register. Exact error: " + e.getMessage()); + try { + authManager.startSignUp("merzn@purdue.edu", "Password123"); + authManager.confirmSignUp("######"); + } catch (AuthException signUpError) { + Log.e("Authentication", "SignUp error: " + signUpError.getMessage()); + } } } - //------------------------------------------------------------------------------------------// - + boolean testAPI = true; //----------------------------------API Testing---------------------------------------------// - Properties configs = new Properties(); - try { - configs = AuthManager.loadProperties(this, "android.resource://" + getPackageName() + "/raw/auths.json"); - } catch (IOException|JSONException e) { - e.printStackTrace(); + if (testAPI) { + AuthManager authManager = new AuthManager(); + try { + authManager.signIn("merzn@purdue.edu", "Password123"); + } catch (AuthException e) { + e.printStackTrace(); + } + Properties configs = new Properties(); + try { + configs = AuthManager.loadProperties(this, "android.resource://" + getPackageName() + "/raw/auths.json"); + } catch (IOException | JSONException e) { + e.printStackTrace(); + } + + Requestor requestor = new Requestor(authManager, configs.getProperty("apiKey")); + //The name is the only part of this that is used, the rest is generated by the Lambda. + List testList = new List(-1, "New List", "user filled by lambda", Instant.now().toEpochMilli()); + //Everything except addedDate is used for ItemEntry + ListEntry entry = new ListEntry(1, 1, new Random().nextInt(), Instant.now().atZone(ZoneOffset.UTC).toLocalDateTime(),false); + SynchronousReceiver idReceiver = new SynchronousReceiver<>(); + try { + requestor.postObject(testList, idReceiver, idReceiver); + System.out.println(idReceiver.await()); + requestor.postObject(entry); + } catch (JSONException | IOException e) { + e.printStackTrace(); + } + + SynchronousReceiver itemReceiver = new SynchronousReceiver<>(); + requestor.getObject("1", Item.class, itemReceiver, itemReceiver); + SynchronousReceiver listReceiver = new SynchronousReceiver<>(); + requestor.getObject("39", List.class, listReceiver, listReceiver); + SynchronousReceiver listIdsReceiver = new SynchronousReceiver<>(); + requestor.getListOfIds(List.class, listIdsReceiver, listIdsReceiver); + try { + System.out.println(itemReceiver.await()); + System.out.println(listReceiver.await()); + System.out.println(Arrays.toString(listIdsReceiver.await())); + } catch (IOException receiverError) { + receiverError.printStackTrace(); + } } - - Requestor requestor = new Requestor(authManager,configs.getProperty("apiKey")); - List testList = new List("IAmATestList"); - try { - requestor.postObject(testList); - } catch (JSONException e) { - e.printStackTrace(); - } - - SynchronousReceiver receiver = new SynchronousReceiver(); - requestor.getObject("1", Item.class, receiver, receiver); - try { - System.out.println(receiver.await()); - } catch (IOException receiverError) { - receiverError.printStackTrace(); - } - - //------------------------------------------------------------------------------------------// diff --git a/Listify/app/src/main/java/com/example/listify/Requestor.java b/Listify/app/src/main/java/com/example/listify/Requestor.java index 2134ac8..5f34f98 100644 --- a/Listify/app/src/main/java/com/example/listify/Requestor.java +++ b/Listify/app/src/main/java/com/example/listify/Requestor.java @@ -29,7 +29,7 @@ public class Requestor { } public void getListOfIds(Class ofType, Receiver successHandler, RequestErrorHandler failureHandler) { - String getURL = DEV_BASEURL + "/" + ofType.getSimpleName() + "?list=-1"; + String getURL = DEV_BASEURL + "/" + ofType.getSimpleName() + "?id=-1"; Request postRequest = buildBaseRequest(getURL, "GET", null); launchCall(postRequest, successHandler, Integer[].class, failureHandler); } @@ -41,15 +41,22 @@ public class Requestor { } public void postObject(Object toPost) throws JSONException { - postObject(toPost, null); + postObject(toPost, (RequestErrorHandler) null); } public void postObject(Object toPost, RequestErrorHandler failureHandler) throws JSONException { - String postURL = DEV_BASEURL + "/" + toPost.getClass().getSimpleName(); - Request postRequest = buildBaseRequest(postURL, "POST", new Gson().toJson(toPost)); - launchCall(postRequest, null, null, failureHandler); + postObject(toPost, null, failureHandler); } + public void postObject(Object toPost, Receiver idReceiver) throws JSONException { + postObject(toPost, idReceiver, null); + } + + public void postObject(Object toPost, Receiver idReceiver, RequestErrorHandler failureHandler) throws JSONException { + String postURL = DEV_BASEURL + "/" + toPost.getClass().getSimpleName(); + Request postRequest = buildBaseRequest(postURL, "POST", new Gson().toJson(toPost)); + launchCall(postRequest, idReceiver, Integer.class, failureHandler); + } private void launchCall(Request toLaunch, Receiver receiver, Class classType, RequestErrorHandler failureHandler) { client.newCall(toLaunch).enqueue(new Callback() { diff --git a/Listify/app/src/main/java/com/example/listify/data/Item.java b/Listify/app/src/main/java/com/example/listify/data/Item.java new file mode 100644 index 0000000..07662b5 --- /dev/null +++ b/Listify/app/src/main/java/com/example/listify/data/Item.java @@ -0,0 +1,116 @@ +package com.example.listify.data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +public class Item { + Integer productID; + Integer chainID; + String upc; + String description; + BigDecimal price; + String imageURL; + String department; + LocalDateTime retrievedDate; + Integer fetchCounts; + + public Item(Integer productID, Integer chainID, String upc, String description, BigDecimal price, + String imageURL, String department, LocalDateTime retrievedDate, Integer fetchCounts) { + this.productID = productID; + this.chainID = chainID; + this.upc = upc; + this.description = description; + this.price = price; + this.imageURL = imageURL; + this.department = department; + this.retrievedDate = retrievedDate; + this.fetchCounts = fetchCounts; + } + + @Override + public String toString() { + return "Item{" + + "productID=" + productID + + ", chainID=" + chainID + + ", upc='" + upc + '\'' + + ", description='" + description + '\'' + + ", price=" + price + + ", imageURL='" + imageURL + '\'' + + ", department='" + department + '\'' + + ", retrievedDate=" + (retrievedDate == null ? null : retrievedDate) + + ", fetchCounts=" + fetchCounts + + '}'; + } + + public Integer getProductID() { + return productID; + } + + public void setProductID(Integer productID) { + this.productID = productID; + } + + public Integer getChainID() { + return chainID; + } + + public void setChainID(Integer chainID) { + this.chainID = chainID; + } + + public String getUpc() { + return upc; + } + + public void setUpc(String upc) { + this.upc = upc; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public BigDecimal getPrice() { + return price; + } + + public void setPrice(BigDecimal price) { + this.price = price; + } + + public String getImageURL() { + return imageURL; + } + + public void setImageURL(String imageURL) { + this.imageURL = imageURL; + } + + public String getDepartment() { + return department; + } + + public void setDepartment(String department) { + this.department = department; + } + + public LocalDateTime getRetrievedDate() { + return retrievedDate; + } + + public void setRetrievedDate(LocalDateTime retrievedDate) { + this.retrievedDate = retrievedDate; + } + + public Integer getFetchCounts() { + return fetchCounts; + } + + public void setFetchCounts(Integer fetchCounts) { + this.fetchCounts = fetchCounts; + } +} diff --git a/Listify/app/src/main/java/com/example/listify/data/List.java b/Listify/app/src/main/java/com/example/listify/data/List.java new file mode 100644 index 0000000..23d77ea --- /dev/null +++ b/Listify/app/src/main/java/com/example/listify/data/List.java @@ -0,0 +1,70 @@ +package com.example.listify.data; + +import java.util.Arrays; + +public class List { + Integer itemID; + String name; + String owner; + long lastUpdated; + final ListEntry[] entries; + + public List(Integer itemID, String name, String owner, long lastUpdated, ListEntry[] entries) { + this.itemID = itemID; + this.name = name; + this.owner = owner; + this.lastUpdated = lastUpdated; + this.entries = entries; + } + + public List(Integer itemID, String name, String owner, long lastUpdated) { + this(itemID, name, owner, lastUpdated, null); + } + + @Override + public String toString() { + return "List{" + + "itemID=" + itemID + + ", name='" + name + '\'' + + ", owner='" + owner + '\'' + + ", lastUpdated=" + lastUpdated + + ", entries=" + Arrays.toString(entries) + + '}'; + } + + public Integer getItemID() { + return itemID; + } + + public void setItemID(Integer itemID) { + this.itemID = itemID; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getOwner() { + return owner; + } + + public void setOwner(String owner) { + this.owner = owner; + } + + public long getLastUpdated() { + return lastUpdated; + } + + public void setLastUpdated(long lastUpdated) { + this.lastUpdated = lastUpdated; + } + + public ListEntry[] getEntries() { + return entries; + } +} diff --git a/Listify/app/src/main/java/com/example/listify/data/ListEntry.java b/Listify/app/src/main/java/com/example/listify/data/ListEntry.java new file mode 100644 index 0000000..404f649 --- /dev/null +++ b/Listify/app/src/main/java/com/example/listify/data/ListEntry.java @@ -0,0 +1,70 @@ +package com.example.listify.data; + +import java.time.LocalDateTime; + +public class ListEntry { + Integer listID; + Integer productID; + Integer quantity; + LocalDateTime addedDate; + Boolean purchased; + + public ListEntry(Integer listID, Integer productID, Integer quantity, LocalDateTime addedDate, Boolean purchased) { + this.listID = listID; + this.productID = productID; + this.quantity = quantity; + this.addedDate = addedDate; + this.purchased = purchased; + } + + @Override + public String toString() { + return "ListEntry{" + + "listID=" + listID + + ", productID=" + productID + + ", quantity=" + quantity + + ", addedDate=" + addedDate + + ", purchased=" + purchased + + '}'; + } + + public Integer getListID() { + return listID; + } + + public void setListID(Integer listID) { + this.listID = listID; + } + + public Integer getProductID() { + return productID; + } + + public void setProductID(Integer productID) { + this.productID = productID; + } + + public Integer getQuantity() { + return quantity; + } + + public void setQuantity(Integer quantity) { + this.quantity = quantity; + } + + public LocalDateTime getAddedDate() { + return addedDate; + } + + public void setAddedDate(LocalDateTime addedDate) { + this.addedDate = addedDate; + } + + public Boolean getPurchased() { + return purchased; + } + + public void setPurchased(Boolean purchased) { + this.purchased = purchased; + } +} diff --git a/Tooling/EndpointSetup.sh b/Tooling/EndpointSetup.sh index 9b8940d..7d72d34 100644 --- a/Tooling/EndpointSetup.sh +++ b/Tooling/EndpointSetup.sh @@ -11,7 +11,7 @@ REL_SCRIPT_DIR=$(dirname "${BASH_SOURCE[0]}") source ${REL_SCRIPT_DIR}/VarSetup.sh -RAWLAMBDA=$(aws lambda create-function --function-name ${functionName}${method} --zip-file fileb://${jarPath} --runtime ${LANGUAGE} --role ${LAMBDAROLE} --handler ${functionName}${method} 2>${DEBUGFILE}) +RAWLAMBDA=$(aws lambda create-function --function-name ${functionName}${method} --zip-file fileb://${jarPath} --runtime ${LANGUAGE} --role ${LAMBDAROLE} --handler ${functionName}${method} --memory-size 512 2>${DEBUGFILE}) if [[ $? -ne 0 ]]; then From 4636a1b419bdf2b699b8ba25f961ba59ff839e21 Mon Sep 17 00:00:00 2001 From: Adam Ding Date: Sun, 4 Oct 2020 15:45:21 -0400 Subject: [PATCH 09/21] Added get function to get Krogger Auth token --- .../APIs/src/main/java/KroggerAPICaller.java | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 Lambdas/APIs/src/main/java/KroggerAPICaller.java diff --git a/Lambdas/APIs/src/main/java/KroggerAPICaller.java b/Lambdas/APIs/src/main/java/KroggerAPICaller.java new file mode 100644 index 0000000..a8d46b1 --- /dev/null +++ b/Lambdas/APIs/src/main/java/KroggerAPICaller.java @@ -0,0 +1,84 @@ +import netscape.javascript.JSObject; + +import java.io.*; +import java.net.ProtocolException; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.HashMap; + +public class KroggerAPITester { + + final static String client_id = "listify-f6e083b133a87ab8a98b2ec4f580dedb9125180887245441161"; + final static String client_secret = "hM88WJ3cJGou5jX1vNRZBqKKVmmcMMktTcTbvkRD"; + final static String redirect_uri = "https://example.com/callback"; //subject to change as needed + final static String scope = "product.compact"; + + final static String authString = "listify-f6e083b133a87ab8a98b2ec4f580dedb9125180887245441161:hM88WJ3cJGou5jX1vNRZBqKKVmmcMMktTcTbvkRD"; + + public static void main(String[] args) { + String s = getKroggerAuthKey(); + System.out.println(s); + getProduct(s); + } + + public static String getKroggerAuthKey() { + String token = "not found"; + try { + StringBuilder sb = new StringBuilder("https://api.kroger.com/v1/connect/oauth2/token"); + String urlParameters = "grant_type=client_credentials&scope=product.compact"; + byte[] postData = urlParameters.getBytes( StandardCharsets.UTF_8 ); + int postDataLength = postData.length; + URL url = new URL(sb.toString()); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setDoOutput(true); + connection.setRequestMethod("POST"); + connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); + connection.setRequestProperty("Authorization", "Basic " + Base64.getEncoder().encodeToString(authString.getBytes())); + connection.setRequestProperty("charset", "UTF-8"); + connection.setRequestProperty("Content-Length", Integer.toString( postDataLength )); + try( DataOutputStream wr = new DataOutputStream( connection.getOutputStream())) { //write body into POST request + wr.write( postData ); + } + + int responseStatus = connection.getResponseCode(); + if(responseStatus == 200) { + System.out.println("Success"); + try(BufferedReader br = new BufferedReader( + new InputStreamReader(connection.getInputStream(), "utf-8"))) { + StringBuilder response = new StringBuilder(); + String responseLine; + while ((responseLine = br.readLine()) != null) { + response.append(responseLine.trim()); + } + + String jsonString = response.toString(); + jsonString = jsonString.substring(1, jsonString.length() - 1); + HashMap map = new HashMap<>(); + String[] responses = jsonString.split(","); + for(int i = 0; i < responses.length; i++) { + String[] keyValue = responses[i].split(":"); + map.put(keyValue[0], keyValue[1]); + } + + if(map.containsKey("\"access_token\"")) { + token = map.get("\"access_token\""); + token = token.substring(1, token.length() - 1); //removes quotes at start and end + } + + } + } else { + System.out.println(responseStatus); + } + connection.disconnect(); + System.out.println(responseStatus); + + } catch (IOException e) { + e.printStackTrace(); + } + return token; + } + +} From cfa558bb34553838ab27f3ca07efcd8ea3b719aa Mon Sep 17 00:00:00 2001 From: Adam Ding Date: Sun, 4 Oct 2020 15:48:22 -0400 Subject: [PATCH 10/21] Removed main method out of file --- Lambdas/APIs/src/main/java/KroggerAPICaller.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Lambdas/APIs/src/main/java/KroggerAPICaller.java b/Lambdas/APIs/src/main/java/KroggerAPICaller.java index a8d46b1..9b0b22d 100644 --- a/Lambdas/APIs/src/main/java/KroggerAPICaller.java +++ b/Lambdas/APIs/src/main/java/KroggerAPICaller.java @@ -15,14 +15,8 @@ public class KroggerAPITester { final static String client_secret = "hM88WJ3cJGou5jX1vNRZBqKKVmmcMMktTcTbvkRD"; final static String redirect_uri = "https://example.com/callback"; //subject to change as needed final static String scope = "product.compact"; - final static String authString = "listify-f6e083b133a87ab8a98b2ec4f580dedb9125180887245441161:hM88WJ3cJGou5jX1vNRZBqKKVmmcMMktTcTbvkRD"; - - public static void main(String[] args) { - String s = getKroggerAuthKey(); - System.out.println(s); - getProduct(s); - } + public static String getKroggerAuthKey() { String token = "not found"; From fe846fb81f8f2ba875180bb08d35c5a60b229e0f Mon Sep 17 00:00:00 2001 From: NMerz Date: Mon, 5 Oct 2020 12:29:28 -0400 Subject: [PATCH 11/21] Delete Lambda prototype Prototype the User DELETE lambda. Amplify does not include this functionality, so putting it in a Lambda with the fine-grained API. This currently does not invalidate outstanding tokens nor does it clean up the database. @claytonwwilson You will want to add the clean up code instead of the deleted stuff in UserDeleter --- .../User/resources/cognitoProperties.json | 3 + Lambdas/Lists/User/src/UserDELETE.java | 11 ++++ Lambdas/Lists/User/src/UserDeleter.java | 59 ++++++++++++++++++ Lambdas/Lists/pom.xml | 42 ++++++++++++- Lambdas/Lists/target/Lists-1.0-SNAPSHOT.jar | Bin 0 -> 6620 bytes .../target/maven-archiver/pom.properties | 5 ++ .../compile/default-compile/inputFiles.lst | 4 ++ .../java/com/example/listify/AuthManager.java | 10 +++ .../com/example/listify/MainActivity.java | 7 ++- .../java/com/example/listify/Requestor.java | 22 +++++-- .../java/com/example/listify/data/User.java | 4 ++ 11 files changed, 158 insertions(+), 9 deletions(-) create mode 100644 Lambdas/Lists/User/resources/cognitoProperties.json create mode 100644 Lambdas/Lists/User/src/UserDELETE.java create mode 100644 Lambdas/Lists/User/src/UserDeleter.java create mode 100644 Lambdas/Lists/target/Lists-1.0-SNAPSHOT.jar create mode 100644 Lambdas/Lists/target/maven-archiver/pom.properties create mode 100644 Lambdas/Lists/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst create mode 100644 Listify/app/src/main/java/com/example/listify/data/User.java diff --git a/Lambdas/Lists/User/resources/cognitoProperties.json b/Lambdas/Lists/User/resources/cognitoProperties.json new file mode 100644 index 0000000..a01aefd --- /dev/null +++ b/Lambdas/Lists/User/resources/cognitoProperties.json @@ -0,0 +1,3 @@ +{ + "userPoolId": "us-east-2_MFgSVKQMd", +} \ No newline at end of file diff --git a/Lambdas/Lists/User/src/UserDELETE.java b/Lambdas/Lists/User/src/UserDELETE.java new file mode 100644 index 0000000..b1a7076 --- /dev/null +++ b/Lambdas/Lists/User/src/UserDELETE.java @@ -0,0 +1,11 @@ +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + +import java.util.Map; + +public class UserDELETE implements RequestHandler, Object> { + + public Object handleRequest(Map inputMap, Context unfilled) { + return BasicHandler.handleRequest(inputMap, unfilled, UserDeleter.class); + } +} \ No newline at end of file diff --git a/Lambdas/Lists/User/src/UserDeleter.java b/Lambdas/Lists/User/src/UserDeleter.java new file mode 100644 index 0000000..bd04d9b --- /dev/null +++ b/Lambdas/Lists/User/src/UserDeleter.java @@ -0,0 +1,59 @@ +import com.amazonaws.services.cognitoidp.AWSCognitoIdentityProvider; +import com.amazonaws.services.cognitoidp.AWSCognitoIdentityProviderClientBuilder; +import com.amazonaws.services.cognitoidp.model.AdminDeleteUserRequest; +import com.amazonaws.services.cognitoidp.model.AdminUserGlobalSignOutRequest; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +public class UserDeleter implements CallHandler { + + private DBConnector connector; + private String cognitoID; + + //private final String REMOVE_FROM_LIST = "DELETE FROM ListProduct WHERE (ProductID = ? AND ListID = ?);"; + + public UserDeleter(DBConnector connector, String cognitoID) { + this.connector = connector; + this.cognitoID = cognitoID; + } + + public Object conductAction(Map bodyMap, HashMap queryString, String cognitoID) throws SQLException { + AWSCognitoIdentityProvider awsCognitoIdentityProvider = AWSCognitoIdentityProviderClientBuilder.defaultClient(); + Properties cognitoProperties; + try { + cognitoProperties = DBConnector.loadProperties("cognitoProperties.json"); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + String userPoolId = cognitoProperties.get("userPoolId").toString(); + System.out.println(userPoolId); + AdminDeleteUserRequest adminDeleteUserRequest = new AdminDeleteUserRequest().withUserPoolId(userPoolId); + adminDeleteUserRequest.setUsername(cognitoID); + System.out.println(adminDeleteUserRequest); + awsCognitoIdentityProvider.adminDeleteUser(adminDeleteUserRequest); + AdminUserGlobalSignOutRequest adminUserGlobalSignOutRequest = new AdminUserGlobalSignOutRequest().withUserPoolId(userPoolId); + adminUserGlobalSignOutRequest.setUsername(cognitoID); + System.out.println(adminUserGlobalSignOutRequest); + awsCognitoIdentityProvider.adminUserGlobalSignOut(adminUserGlobalSignOutRequest); + + return null; + + // Connection connection = connector.getConnection(); +// try { +// PreparedStatement statement = connection.prepareStatement(REMOVE_FROM_LIST); +// statement.setInt(1, (Integer) bodyMap.get("ProductID")); +// statement.setInt(2, (Integer) bodyMap.get("ListID")); +// System.out.println(statement); +// statement.executeUpdate(); +// connection.commit(); +// } finally { +// connection.close(); +// } +// return null; + } +} diff --git a/Lambdas/Lists/pom.xml b/Lambdas/Lists/pom.xml index 1984615..9fb5565 100644 --- a/Lambdas/Lists/pom.xml +++ b/Lambdas/Lists/pom.xml @@ -42,13 +42,53 @@ org.apache.httpcomponents httpclient - 4.5 + 4.5.12 com.google.code.gson gson 2.8.6 + + com.amazonaws + aws-java-sdk-cognitoidentity + 1.11.875 + + + com.amazonaws + aws-java-sdk-cognitoidp + 1.11.875 + + + software.amazon.ion + ion-java + 1.5.1 + + + joda-time + joda-time + 2.10.6 + + + commons-logging + commons-logging + 1.2 + + + com.fasterxml.jackson.dataformat + jackson-dataformat-cbor + 2.11.3 + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + 2.8.5 + + + com.fasterxml.jackson.core + jackson-databind + 2.11.3 + 1.11 diff --git a/Lambdas/Lists/target/Lists-1.0-SNAPSHOT.jar b/Lambdas/Lists/target/Lists-1.0-SNAPSHOT.jar new file mode 100644 index 0000000000000000000000000000000000000000..a611fefc3c3059bbfccca1c0031a71d3b0e7443a GIT binary patch literal 6620 zcma)A2Rxhaw@>XYBB))pN9;|N*g|b;773-qie0sesy&KYwfAU^+SS&cwaeeAhEi%Y zwo+XEExot>-Fu(pect4g^F5!F^FGh_oad_p!^R;3{1`|*W!*nM{526?+_jVq6d>xi zR0MSXG9v&uU6`G&>k`;s{2Xv`fqypBQn;nAqO5Pgucfl9H8`LNgYb`%!XP~F28V0) z1Sdp3F1zz-yzAwIL7)Wqp9+kgQ1iZF^J&VA(xZgw>3d}HRDv0ZK}jNdRQ{9$db{B0 z{lUFx-=<6r5tPQ8nzn#8pmSuEv4;2vUJjMtN~?LRIp8v~XuHZv7I{(y`il2uBO2;aq2VcX z8kPHAiJ2UV93pOZW6GBP`vR*1n3wx+XPQ$|X_&vmn$5RFP*_b0E)~gApEqg`&)Rl3 zZ`?gPdCmFyN+WE9BpR2HO#^1)^%Qbo1XMJlk&EYoage za%X)#K>T5hz5hn$?(JMCh48S|J1&#Kav9NKHcKvtVb-z&?Q7~AKy_0xr#3JKm$cM&>hR`K&?H%cG!^^vFyB zt5QdNa8c|7@WDcU$U@sR`kBU3+5q_7e>{udOp%Nh=i|F9n4l}+M9)i(lvK%PrJb!+ zyO508i?Ol8@&Zjf3qp+E+fw@v=<#v4v3sK(c0eKmGKGH0olVWgAH{}WKyY_wZJEk3 zDt!D&UGT}~^{%653fgv5a9<{PHBULA^qrB@#rM0?ZJov*$WNswo&_(|l*{|t=#Eu9 z(s*aLe2RfY*DbOXoXhJsbxF#R?$4cQ=0~siR|d27=F1B+a*d}5>(nrY<@hGs&v?!} zB|u1QOi%~kR|>8zvlo(fi%n8w8#R>{9$mQ|cNNsaVZ@;>p0LVa)QA$(drvqPuCeG_ zlnQSsWrf!kDya-Rmx(`Hb;A$S#Swcq7(kk=SYB*Z*3To0G{aq)7jG3FGLJKPHv6{r zRlb=P&(>qVjj?&R7k6(TZW5*PD;$U!VVsI{+u3q!>n%zto1azlZ53#(G-qCW?GpAx zDrD?ArDIY{t%6mY_vQ=v?d4T;z~L%gFWA8@U8-ZrL#=FoPQ*>$_1ONV<~Zkl(4q?< z(kElhH^hjWj*2dhoms(GElIAGCrkd$Y0};VHhycke%q#~C8q$95tLw*#5DkVXGaK1 z6rd6)cynbqX*9S;=LADzGqjdH5+GmKbc}6!ph|Kc`Br8W!%A|>pSNro@5oXnVT?bH z#t)tODiSju$nyqRJ+Y?4>O-G@TLFjuYW|4>!{O@3MX=DKUqXOTA~drnx7UGAB0j!8 zP5k+P9$dTytTT2;kI&xrzrJcf_&r)+hMr9mYd2U>ZJeup65;WQCYq=|m)b(RZnaE< zNd!q9Ov`rbdUROP;`EcptbMC)8VoUNRQXxJV$*BaEr1E)1aD8ZTKB;b)wd$nJ_kv{ zfF4q?h_8qRJ`Nhh{mdsKuVqv|g`_V9uSSP)8mLBWO+P;-umujuC`&C#eilh1ao5Aw zJc(&jJMczWVBfOQc1_>a&g*1v@^*0hko^k(VYi@Es*XZhubo5Xs9#dR)H(hoeNk2^ z>iU!oSh?Z>00m?K0L2A;DM1xooSkjq9xm>G^4Ck_Z^o3y;4>y1j!=bbPW+Y1QCC51 z{K&$t$~-P{J}hYEJVze@Tb<(;2iLsuX4}mBt&_ILlRgAkZTD+=AYl5jiA1cAEAJLswf7;%UgPMx0`u{JD;S%J#3o`YcH4eB zhJyTys{k*P_mZ5%Eg#pLOkAun_ygNOrj#5Xorf<%2^uFoNYG&|D&oZX0;TMK0@BQi#+5-Wk_C@h zm_kJk3BV_&;kf2meg;$}Bo2fxB^b%eyW>Hz37zy~tQtJ5p#f_qQX)4zOt>Moj@N-!bgNc2R>#xF9D z=veI2IIS#Qe-~?Iq=Noq%>%AJzV1k&$ql}1d2gp`NT|wfnn4hy#o>@x?#I<1a~$j+ zSI4F-k2EDlO1+bX2vN9Z90%PiA|<+$F-XfuyRrV#km~>{^flEv8kbYg?|N@Y8wLlB zFh$Cy=r{)vWhmDC&pEj zHpiZxm4%Gi!&!sBw4XY|hlRJGkD`aByUCez3!Wm~`0MQ(k=N;B>lg*=xF_Q=q0yY% zPeO}rWgp&Um*rgY%}l6f&XSdeT^m!;>?Zcn?S}cJiF0J>kzVI7Ezm3WVC6wm(Qf(} zc5{fre6+fe3^nhna}cfXqF&w_)Nzk8iN}OTOKhivHrQr%$Y6<)ZMY@gwQY?$?ClD$ zkkBv6WxH>HGLI|bfw{F2-Cf-epmKZ=M9%KdwgmTw)@aWkX?A};YL5|+>U)mxk8#22 zC$_f?8i-YsKX>+8TT`l&FLY0c3=%D)f2ENr?mfPP&*m~x z9bdfmq_o>1b+0aMT?3~)J6g*1gM<;dnEAOSQEVdVLTpQUy zyfi>$O?`W4vW}9ywcm8Fnz&X~oeOSmcY}CvC7uP%4~4p=(xuPHc@nm-h*gc) z_Hv6I8+l9!Z@eWxN+43+Sl+5J(;0~5P2zD-0;7~fdQ7GaKpeKS0T%4&-c-Ky&$HA$ z_GhWPDZC$dp4_u*N^he8n5cpR61PR{5DZGGp;2?b0hH5EjVD0*#|3mGCaFZ8g0==| zY9)n%rEh7W19kZ<7TKDd+@;Puh>kC$=CDAjyn*A|`)F%+ib8kC8d7696=IS{MM+;` zATun+^+=QEnbJ<1hv}uDeJvO@@`aa!$Iv+H?0k3zT_Gd-s*6^wR|o!@-wA8o_53-d?YOPWw7s+jIIZO? z_{j%WWQM7_TFqy$5{`1&y!}un@Nk$ZCe=&qOEnqkbj+k=s2Fv>pNtnZdt5yn9}RCU zth3866d>~xo>BL!4NJ|p2sYLs_jp8r+>B0kpzB5+{6HbSnFR|VmHyY{hpAre8k7% zUY+DvA|nUO-Z)!a7!`apiMl5cGH`(XTR z*`AI-H2w1L*MX;uZ^UE`;@@cD?jC9K z5tBp_*);ZHq&jGb7JEhbxVfy-&?!L`dpY>!SOy3#p*g$T@Y{Ef^xl&6liU%Svu@1d7Bp<(x_5$Z-mA91Ugn-hHZ)k)lTPxqKKGi>o-WuV40y zeePS&YAuT8wg*WPgf1{$dxIKxlGc*@j5<+mPUdQZQ!q*}-}CDbaf;dkA^OG?WlF!# zIXQn-^PUf%#M~g#LsX01Yu>AbbcpUp;_Q>6pXAed% zntvWmeMqKi@STSguc;f&h#$y&Fh#4zyyD5eA)BOMIQB`j?+!A?t8D)9L7o=A7r9bx zF~+YY;}I{?J=Cde)ooKw9Y;vef8Y(RIISq2MnImu0c7hNS=ix{0e1$H`^;nIX4uZn z3~7=U_+4J*S#Qw?AArlNadP!AtgKEm$-W%U>acqtv8xkv2~`ERWUXNBqYqiw-N+Bk zj&gnRL>^1?>CyJ-g2d_6WdWP!nFYn5-X?O*myL;m`$ns@TkE{j%6G~kYnDS*O2Fbn zil_;L%$m-wA;)Wber0p5xw>}q1fQVyTyCq@^WJG08RUO_q0gsJ%06dgu1sWP)f zdWJ7v`OY@vF=bCbst8w(DLJTye5qz-p@o27B4FC;Pkr*ea+@1og}(xte%2>$FhFf& zVQ6`yYy{^ye0k1+%d8C&LMx0da*oDK>XIl|oj6ZA_E&7J*NgffTNr5vnG?EdY|0`D zLAtb2V_|PH#?7qH2c?QvCW=$qD7_L@tg~IJNB#8}@6fUywu@%U@jVkv0YAXvL14nE zSNwA~DW{$VADDaXDZba7rD8_oS+`onCo}Nd(6W&~IeiIy%^KhNF=ro~WsnEb_4TJ2(|)@@Ti1OVtBbH6av8BCX z7+ZxropKqXKn;5Pt7>?~5HK+9%quyfin2kIPJFe(I<$gxJc5zs2B*4yx?L}!Y|+ej z`94NcSv|E!k+qVlxM?h(?n{!ZNFx^GC|n43vO;m$d0GczaMOtXrgA|tber+K$$BFVN%yB40$H)bNPcY<9Q zLQ48>!J$=Co2T4@{>L<++B(M0n4C(xzBuz287DNCO!-5H@ZDIuJ9WX3#aI4p8nww#$P<*BwO9mh852=xaR^6s{`uwOhw$<`g4sVB@0&tW2HbjTiuv#zutw zh{8%`ncRo+D!D9jRe++0xu``Q0g`E5xqFC4Lil}Xj)Yk?WLKCq`Eclcz*{^%3%Ph3 z=^bd28soQ9tmAJMgwFm@c+HYcR!yTy&LHpTS+VIriRPQLW?FZ%$y{ik! z9g?udry900UOk$nL2F^4zH4_lM2UO(WjTRzRb2C20-3{G=g&a|?4K0La!GocBRyl6 z4I7P;b!wXf3}c8dv*3846FFYLAslg$g=ZJnkK+u&M#tU7)z;m^!4}1T59Q*_K3Gi_ zA_xpZXBFpU6_&7Zcv-u83hv;jn!$-*u2j(|Ew#`iP7}}1!M5DAs--YmCl?Q#J*)c` zQ~AXkF15leBmVwEyFjr1a*+E=V|#UlP;b9CO8o^T8Fu$eh8-uD%pz?c-16sU@?b9oNhyAMxMt%|YKPni~+RN7YA1&-xW13%$ z@4CBqx~e1o7ZBsWgESpb9;kny1OU~GoMwU-TM4lMfWQlVj_v<~y1F3weUMH=DY`Bh zg20}IU2fpl>G&c?Fh$ub&5S2i$z!+fd%pOb9vtJui8$F45obYYQ90(B`YL3e_nb;D zWU0Fx8q#h=7-(W_p9V>i5DeqmW%73v_h^sGwhnPPK$I2S8Lx^N4`58z{jOMtd4*yd z9Dn+zTf57P~;$wvSloC%Y5_IyZoiEV%YWWWEELXMei=^ z{;Dda*t)LPt8zYC)yC7btmW7%QiDz}>OfDQESPf$x1_gI&UUVqfM<`1-!dwHhPTSh>6ht;L+2MMU3*fIEPkVHBq7C({;O^!pyWaj(4U8JevybG<@V+#3g3+ zYZH5WrTnOR{U`dJZ{|W1Sz52)e)wd$YV<)2(WmKfQouYHZF$XNYu0VXPS179mge;v z>7$V0H~YP$>R~zTS5_EUgN`R9_bc4=8JW*^k6zg3Vzi&$5MVe8oNqHG=(V!qFmx6!F%>1!3dz!=JK6ZJQ?7_uEo2r_L zyv4!qvSx}mu;;CA_5@jxp9A?XgxxDxVC;X_rY{1%7(l?L!jJnud-M|ad#(D1@sCju z%y}{Y1N%w2{@KItH03|we|UI%G5=46`DgU+B%Moi5bkdTo}b~rYq>As%p|{Sz<?j0Q|z|m+)W7@duOsIe>ukb3DqQlK(fa{`&*}!K{~H zkzc`=Jp1oXelYE&6Z?O6@;C4P?dtc;`?s@#;Qar~)n7b(nV#Qoz)O!?RKKL>?|=Ab da6dd=Zbuy$?uBXy0FYd~_^<(hbm|}9{tKEJ2^IhV literal 0 HcmV?d00001 diff --git a/Lambdas/Lists/target/maven-archiver/pom.properties b/Lambdas/Lists/target/maven-archiver/pom.properties new file mode 100644 index 0000000..68bd418 --- /dev/null +++ b/Lambdas/Lists/target/maven-archiver/pom.properties @@ -0,0 +1,5 @@ +#Generated by Maven +#Mon Oct 05 10:19:24 EDT 2020 +groupId=groupId +artifactId=Lists +version=1.0-SNAPSHOT diff --git a/Lambdas/Lists/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/Lambdas/Lists/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst new file mode 100644 index 0000000..db1626f --- /dev/null +++ b/Lambdas/Lists/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst @@ -0,0 +1,4 @@ +/Users/MNM/Documents/GitHub/Listify/Lambdas/Lists/src/main/java/CallHandler.java +/Users/MNM/Documents/GitHub/Listify/Lambdas/Lists/src/main/java/DBConnector.java +/Users/MNM/Documents/GitHub/Listify/Lambdas/Lists/src/main/java/BasicHandler.java +/Users/MNM/Documents/GitHub/Listify/Lambdas/Lists/src/main/java/InputUtils.java diff --git a/Listify/app/src/main/java/com/example/listify/AuthManager.java b/Listify/app/src/main/java/com/example/listify/AuthManager.java index 030fb88..6f87694 100644 --- a/Listify/app/src/main/java/com/example/listify/AuthManager.java +++ b/Listify/app/src/main/java/com/example/listify/AuthManager.java @@ -8,6 +8,7 @@ import com.amplifyframework.auth.options.AuthSignUpOptions; import com.amplifyframework.auth.result.AuthSignInResult; import com.amplifyframework.auth.result.AuthSignUpResult; import com.amplifyframework.core.Amplify; +import com.example.listify.data.User; import org.json.JSONException; import org.json.JSONObject; @@ -85,6 +86,10 @@ public class AuthManager { waiting = false; } + public void signOutSuccess() { + waiting = false; + } + public void startSignUp(String email, String password) throws AuthException { this.email = email; this.password = password; @@ -124,6 +129,11 @@ public class AuthManager { throwIfAuthError(); } + public void deleteUser(Requestor requestor) { + requestor.deleteObject("N/A", User.class); + Amplify.Auth.signOut(this::signOutSuccess, error -> setAuthError(error)); + } + public static Properties loadProperties(Context context, String path) throws IOException, JSONException { diff --git a/Listify/app/src/main/java/com/example/listify/MainActivity.java b/Listify/app/src/main/java/com/example/listify/MainActivity.java index 0e8061b..0e84fdb 100644 --- a/Listify/app/src/main/java/com/example/listify/MainActivity.java +++ b/Listify/app/src/main/java/com/example/listify/MainActivity.java @@ -14,8 +14,8 @@ import androidx.navigation.ui.AppBarConfiguration; import androidx.navigation.ui.NavigationUI; import com.amplifyframework.auth.AuthException; import com.example.listify.data.Item; -import com.example.listify.data.ListEntry; import com.example.listify.data.List; +import com.example.listify.data.ListEntry; import com.google.android.material.navigation.NavigationView; import org.json.JSONException; @@ -60,7 +60,7 @@ public class MainActivity extends AppCompatActivity { //------------------------------------------------------------------------------------------// - boolean testAPI = false; + boolean testAPI = true; //----------------------------------API Testing---------------------------------------------// if (testAPI) { @@ -78,6 +78,9 @@ public class MainActivity extends AppCompatActivity { } Requestor requestor = new Requestor(authManager, configs.getProperty("apiKey")); + + authManager.deleteUser(requestor); + //The name is the only part of this that is used, the rest is generated by the Lambda. List testList = new List(-1, "New List", "user filled by lambda", Instant.now().toEpochMilli()); //Everything except addedDate is used for ItemEntry diff --git a/Listify/app/src/main/java/com/example/listify/Requestor.java b/Listify/app/src/main/java/com/example/listify/Requestor.java index 5f34f98..4d0c6d1 100644 --- a/Listify/app/src/main/java/com/example/listify/Requestor.java +++ b/Listify/app/src/main/java/com/example/listify/Requestor.java @@ -24,20 +24,30 @@ public class Requestor { client = new OkHttpClient(); } - public void getObject(String id, Class classType, Receiver receiver) { - getObject(id, classType, receiver, null); - } - public void getListOfIds(Class ofType, Receiver successHandler, RequestErrorHandler failureHandler) { String getURL = DEV_BASEURL + "/" + ofType.getSimpleName() + "?id=-1"; Request postRequest = buildBaseRequest(getURL, "GET", null); launchCall(postRequest, successHandler, Integer[].class, failureHandler); } + public void getObject(String id, Class classType, Receiver receiver) { + getObject(id, classType, receiver, null); + } + public void getObject(String id, Class classType, Receiver successHandler, RequestErrorHandler failureHandler) { String getURL = DEV_BASEURL + "/" + classType.getSimpleName() + "?id=" + id; - Request postRequest = buildBaseRequest(getURL, "GET", null); - launchCall(postRequest, successHandler, classType, failureHandler); + Request getRequest = buildBaseRequest(getURL, "GET", null); + launchCall(getRequest, successHandler, classType, failureHandler); + } + + public void deleteObject(String id, Class classType) { + deleteObject(id, classType, null); + } + + public void deleteObject(String id, Class classType, RequestErrorHandler failureHandler) { + String deleteURL = DEV_BASEURL + "/" + classType.getSimpleName() + "?id=" + id; + Request deleteRequest = buildBaseRequest(deleteURL, "DELETE", "{}"); + launchCall(deleteRequest, null, classType, failureHandler); } public void postObject(Object toPost) throws JSONException { diff --git a/Listify/app/src/main/java/com/example/listify/data/User.java b/Listify/app/src/main/java/com/example/listify/data/User.java new file mode 100644 index 0000000..65ba3e6 --- /dev/null +++ b/Listify/app/src/main/java/com/example/listify/data/User.java @@ -0,0 +1,4 @@ +package com.example.listify.data; + +public class User { +} From 5fe666fbbb0b597cf14f953d98d20aa2ba7028d4 Mon Sep 17 00:00:00 2001 From: Clayton Wilson Date: Mon, 5 Oct 2020 21:24:50 -0400 Subject: [PATCH 12/21] Add-to-list dialog and functionality on item details page --- .../java/com/example/listify/ItemDetails.java | 59 +++++++-- .../listify/ListPickerDialogFragment.java | 121 ++++++++++++++++++ .../adapter/DisplayShoppingListsAdapter.java | 55 ++++++++ .../example/listify/model/ShoppingList.java | 74 +++++++++++ .../main/res/layout/activity_item_details.xml | 4 +- .../main/res/layout/dialog_add_to_list.xml | 41 ++++++ .../layout/display_shopping_lists_item.xml | 20 +++ 7 files changed, 361 insertions(+), 13 deletions(-) create mode 100644 Listify/app/src/main/java/com/example/listify/ListPickerDialogFragment.java create mode 100644 Listify/app/src/main/java/com/example/listify/adapter/DisplayShoppingListsAdapter.java create mode 100644 Listify/app/src/main/java/com/example/listify/model/ShoppingList.java create mode 100644 Listify/app/src/main/res/layout/dialog_add_to_list.xml create mode 100644 Listify/app/src/main/res/layout/display_shopping_lists_item.xml diff --git a/Listify/app/src/main/java/com/example/listify/ItemDetails.java b/Listify/app/src/main/java/com/example/listify/ItemDetails.java index 8da738f..2417b93 100644 --- a/Listify/app/src/main/java/com/example/listify/ItemDetails.java +++ b/Listify/app/src/main/java/com/example/listify/ItemDetails.java @@ -1,8 +1,12 @@ package com.example.listify; import android.os.Bundle; + +import com.amazonaws.services.cognitoidentityprovider.model.TooManyFailedAttemptsException; import com.bumptech.glide.Glide; +import com.example.listify.adapter.DisplayShoppingListsAdapter; import com.example.listify.model.Product; +import com.example.listify.model.ShoppingList; import com.google.android.material.floatingactionbutton.FloatingActionButton; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; @@ -11,11 +15,14 @@ import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; +import android.widget.Toast; -public class ItemDetails extends AppCompatActivity { +import java.util.ArrayList; + +public class ItemDetails extends AppCompatActivity implements ListPickerDialogFragment.OnListPickListener { private Product curProduct; - private LinearLayout lin1; - private LinearLayout lin2; + private LinearLayout linAddItem; + private LinearLayout linCreateList; private TextView tvCreateNew; private TextView tvAddItem; private TextView tvItemName; @@ -25,6 +32,8 @@ public class ItemDetails extends AppCompatActivity { private TextView tvItemDesc; private ImageButton backToSearchbutton; + ArrayList shoppingLists = new ArrayList<>(); + private boolean isFABOpen = false; @Override @@ -34,13 +43,13 @@ public class ItemDetails extends AppCompatActivity { Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); + // Load Product object from search results activity curProduct = (Product) getIntent().getSerializableExtra("SelectedProduct"); + // Set up floating action buttons FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); -// fab1 = (FloatingActionButton) findViewById(R.id.fab1); -// fab2 = (FloatingActionButton) findViewById(R.id.fab2); - lin1 = (LinearLayout) findViewById(R.id.lin1); - lin2 = (LinearLayout) findViewById(R.id.lin2); + linAddItem = (LinearLayout) findViewById(R.id.lin_add_item); + linCreateList = (LinearLayout) findViewById(R.id.lin_create_list); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { @@ -52,6 +61,30 @@ public class ItemDetails extends AppCompatActivity { } }); + linAddItem.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + closeFABMenu(); + + // Hardcode shopping lists to demonstrate displaying lists + for (int i = 0; i < 10; i++) { + shoppingLists.add(new ShoppingList(Integer.toString(i))); + } + + ListPickerDialogFragment listPickerDialog = new ListPickerDialogFragment(shoppingLists); + listPickerDialog.show(getSupportFragmentManager(), "User Lists"); + } + }); + + linCreateList.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Toast.makeText(ItemDetails.this, "create", Toast.LENGTH_SHORT).show(); + closeFABMenu(); + } + }); + + // Set data tvItemName = (TextView) findViewById(R.id.item_name); tvItemName.setText(curProduct.getItemName()); @@ -84,19 +117,23 @@ public class ItemDetails extends AppCompatActivity { private void showFABMenu(){ isFABOpen=true; - lin1.animate().translationY(-getResources().getDimension(R.dimen.standard_55)); - lin2.animate().translationY(-getResources().getDimension(R.dimen.standard_105)); + linAddItem.animate().translationY(-getResources().getDimension(R.dimen.standard_55)); + linCreateList.animate().translationY(-getResources().getDimension(R.dimen.standard_105)); tvAddItem.setVisibility(View.VISIBLE); tvCreateNew.setVisibility(View.VISIBLE); } private void closeFABMenu(){ isFABOpen=false; - lin1.animate().translationY(0); - lin2.animate().translationY(0); + linAddItem.animate().translationY(0); + linCreateList.animate().translationY(0); tvAddItem.setVisibility(View.INVISIBLE); tvCreateNew.setVisibility(View.INVISIBLE); } + @Override + public void sendListSelection(int selectedListIndex, int quantity) { + Toast.makeText(this, String.format("%d of Item added to %s", quantity, shoppingLists.get(selectedListIndex).getName()), Toast.LENGTH_SHORT).show(); + } } \ No newline at end of file diff --git a/Listify/app/src/main/java/com/example/listify/ListPickerDialogFragment.java b/Listify/app/src/main/java/com/example/listify/ListPickerDialogFragment.java new file mode 100644 index 0000000..b9f7310 --- /dev/null +++ b/Listify/app/src/main/java/com/example/listify/ListPickerDialogFragment.java @@ -0,0 +1,121 @@ +package com.example.listify; +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.graphics.Color; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.AdapterView; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ListView; +import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; +import androidx.fragment.app.DialogFragment; +import com.example.listify.adapter.DisplayShoppingListsAdapter; +import com.example.listify.model.ShoppingList; +import java.util.ArrayList; + + +public class ListPickerDialogFragment extends DialogFragment { + + public interface OnListPickListener { + void sendListSelection(int selectedListIndex, int quantity); + } + + public OnListPickListener onListPickListener; + + ListView userListsView; + DisplayShoppingListsAdapter displayShoppingListsAdapter; + Button btnMinus; + Button btnPlus; + EditText etQuantity; + private ArrayList userLists; + private int selectedListIndex; + + public ListPickerDialogFragment(ArrayList userLists) { + this.userLists = userLists; + } + + + @Override + public Dialog onCreateDialog(final Bundle savedInstanceState) { + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + // Get the layout inflater + LayoutInflater inflater = requireActivity().getLayoutInflater(); + + // Inflate and set the layout for the dialog + // Pass null as the parent view because its going in the dialog layout + View root = inflater.inflate(R.layout.dialog_add_to_list, null); + builder.setView(root) + // Add action buttons + .setPositiveButton("OK", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + onListPickListener.sendListSelection(selectedListIndex, Integer.parseInt(etQuantity.getText().toString())); + } + }) + .setNegativeButton("cancel", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + ListPickerDialogFragment.this.getDialog().cancel(); + } + }); + + // Display user's shopping lists + userListsView = (ListView) root.findViewById(R.id.user_lists); + displayShoppingListsAdapter = new DisplayShoppingListsAdapter(getActivity(), userLists); + userListsView.setAdapter(displayShoppingListsAdapter); + + userListsView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + for (int i = 0; i < parent.getChildCount(); i++) { + parent.getChildAt(i).setBackgroundColor(Color.TRANSPARENT); + } + + view.setBackgroundColor(Color.GREEN); + selectedListIndex = position; + } + }); + + // Set up quantity selection + etQuantity = (EditText) root.findViewById(R.id.et_quantity); + + btnMinus = (Button) root.findViewById(R.id.btn_minus); + btnMinus.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + int curQauntity = Integer.parseInt(etQuantity.getText().toString()); + if (curQauntity > 0) { + curQauntity--; + etQuantity.setText(String.format("%d", curQauntity)); + } + } + }); + + btnPlus = (Button) root.findViewById(R.id.btn_plus); + btnPlus.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + int curQauntity = Integer.parseInt(etQuantity.getText().toString()); + curQauntity++; + etQuantity.setText(String.format("%d", curQauntity)); + } + }); + + return builder.create(); + } + + // Required to extend DialogFragment + @Override + public void onAttach(@NonNull Context context) { + super.onAttach(context); + try { + onListPickListener = (OnListPickListener) getActivity(); + } catch (ClassCastException e) { + Log.e("ListPickerDialogFragment", "onAttach: ClassCastException: " + e.getMessage()); + } + } +} diff --git a/Listify/app/src/main/java/com/example/listify/adapter/DisplayShoppingListsAdapter.java b/Listify/app/src/main/java/com/example/listify/adapter/DisplayShoppingListsAdapter.java new file mode 100644 index 0000000..056fec5 --- /dev/null +++ b/Listify/app/src/main/java/com/example/listify/adapter/DisplayShoppingListsAdapter.java @@ -0,0 +1,55 @@ +package com.example.listify.adapter; + +import android.app.Activity; +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.TextView; +import com.example.listify.R; +import com.example.listify.model.ShoppingList; +import java.util.ArrayList; + +public class DisplayShoppingListsAdapter extends BaseAdapter { + private Activity activity; + private ArrayList lists; + private LayoutInflater inflater; + + public DisplayShoppingListsAdapter(Activity activity, ArrayList lists){ + this.activity = activity; + this.lists = lists; + } + + @Override + public int getCount() { + return lists.size(); + } + + @Override + public Object getItem(int position) { + return lists.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + if (inflater == null) { + inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + } + if (convertView == null) { + convertView = inflater.inflate(R.layout.display_shopping_lists_item, null); + } + + ShoppingList curList = lists.get(position); + + TextView tvListName = (TextView) convertView.findViewById(R.id.shopping_list_name); + tvListName.setText(curList.getName()); + + return convertView; + } +} \ No newline at end of file diff --git a/Listify/app/src/main/java/com/example/listify/model/ShoppingList.java b/Listify/app/src/main/java/com/example/listify/model/ShoppingList.java new file mode 100644 index 0000000..0775c30 --- /dev/null +++ b/Listify/app/src/main/java/com/example/listify/model/ShoppingList.java @@ -0,0 +1,74 @@ +package com.example.listify.model; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.ArrayList; +import java.util.Collection; + +public class ShoppingList extends ArrayList { + private ArrayList list; + private String name; + + public ShoppingList(String name) { + list = new ArrayList(); + this.name = name; + } + + public Product get(int position) { + return this.list.get(position); + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public int size() { + return list.size(); + } + + @Override + public boolean isEmpty() { + return list.isEmpty(); + } + + @Override + public boolean contains(@Nullable Object o) { + return list.contains(o); + } + + @Override + public int indexOf(@Nullable Object o) { + return list.indexOf(o); + } + + @Override + public boolean add(Product product) { + return list.add(product); + } + + @Override + public Product remove(int index) { + return list.remove(index); + } + + @Override + public void clear() { + list.clear(); + } + + @Override + public boolean remove(@Nullable Object o) { + return list.remove(o); + } + + @Override + public boolean addAll(@NonNull Collection c) { + return list.addAll(c); + } +} \ No newline at end of file diff --git a/Listify/app/src/main/res/layout/activity_item_details.xml b/Listify/app/src/main/res/layout/activity_item_details.xml index 6ad4ac1..49f9f75 100644 --- a/Listify/app/src/main/res/layout/activity_item_details.xml +++ b/Listify/app/src/main/res/layout/activity_item_details.xml @@ -37,7 +37,7 @@ @@ -61,7 +61,7 @@ diff --git a/Listify/app/src/main/res/layout/dialog_add_to_list.xml b/Listify/app/src/main/res/layout/dialog_add_to_list.xml new file mode 100644 index 0000000..8c93694 --- /dev/null +++ b/Listify/app/src/main/res/layout/dialog_add_to_list.xml @@ -0,0 +1,41 @@ + + + + + + +