From 421fceb364bffba60523abdc954b81d2d75dbeef Mon Sep 17 00:00:00 2001 From: NMerz Date: Sat, 14 Nov 2020 15:55:29 -0500 Subject: [PATCH 1/5] Store uiPosition This will later be changeable and can then be used to sort lists received by the UI controller --- Lambdas/Lists/List/src/List.java | 14 +++++++++++- Lambdas/Lists/List/src/ListAdder.java | 16 +++++++++++--- Lambdas/Lists/List/src/ListGetter.java | 6 +++-- .../java/com/example/listify/ItemDetails.java | 22 +++++-------------- .../com/example/listify/MainActivity.java | 2 +- .../java/com/example/listify/data/List.java | 17 +++++++++++--- .../example/listify/ui/home/HomeFragment.java | 2 +- 7 files changed, 51 insertions(+), 28 deletions(-) diff --git a/Lambdas/Lists/List/src/List.java b/Lambdas/Lists/List/src/List.java index 02d9723..eeef2e4 100644 --- a/Lambdas/Lists/List/src/List.java +++ b/Lambdas/Lists/List/src/List.java @@ -9,14 +9,16 @@ public class List { long lastUpdated; ArrayList entries; boolean shared; + Integer uiPosition; - public List(ResultSet listRow, boolean shared) throws SQLException { + public List(ResultSet listRow, boolean shared, Integer uiPosition) throws SQLException { itemID = listRow.getInt("listID"); name = listRow.getString("name"); owner = listRow.getString("owner"); lastUpdated = listRow.getTimestamp("lastUpdated").toInstant().toEpochMilli(); entries = new ArrayList<>(); this.shared = shared; + this.uiPosition = uiPosition; } public void addItemEntry(ItemEntry entry) { @@ -31,6 +33,8 @@ public class List { ", owner='" + owner + '\'' + ", lastUpdated=" + lastUpdated + ", entries=" + entries + + ", shared=" + shared + + ", uiPosition=" + uiPosition + '}'; } @@ -77,4 +81,12 @@ public class List { public void setShared(boolean shared) { this.shared = shared; } + + public Integer getUiPosition() { + return uiPosition; + } + + public void setUiPosition(Integer uiPosition) { + this.uiPosition = uiPosition; + } } diff --git a/Lambdas/Lists/List/src/ListAdder.java b/Lambdas/Lists/List/src/ListAdder.java index b94af67..18a7d7e 100644 --- a/Lambdas/Lists/List/src/ListAdder.java +++ b/Lambdas/Lists/List/src/ListAdder.java @@ -9,7 +9,8 @@ public class ListAdder implements CallHandler { private String cognitoID; private final String LIST_CREATE = "INSERT INTO List (name, owner, lastUpdated) VALUES (?, ?, ?);"; - private final String LIST_ACCESS_GRANT = "INSERT INTO ListSharee(listID, userID, permissionLevel) VALUES(?, ?, ?);"; + private final String LIST_ACCESS_GRANT = "INSERT INTO ListSharee(listID, userID, permissionLevel, uiPosition) VALUES(?, ?, ?, ?);"; + private final String UI_POSITION_CHECK = "SELECT Max(uiPosition) as maxUIPosition FROM ListSharee WHERE userID = ?;"; public ListAdder(Connection connection, String cognitoID) { this.connection = connection; @@ -17,9 +18,17 @@ public class ListAdder implements CallHandler { } public Object conductAction(Map bodyMap, HashMap queryString, String cognitoID) throws SQLException { - PreparedStatement statement = connection.prepareStatement(LIST_CREATE, Statement.RETURN_GENERATED_KEYS); - String listName = bodyMap.get("name").toString();//Needs safe checking + + PreparedStatement uiPositionCheck = connection.prepareStatement(UI_POSITION_CHECK); + uiPositionCheck.setString(1, cognitoID); + ResultSet uiPositionCheckRS = uiPositionCheck.executeQuery(); + int nextPosition = 1; + if (uiPositionCheckRS.next()) { + nextPosition = uiPositionCheckRS.getInt("maxUIPosition") + 1; + } + + PreparedStatement statement = connection.prepareStatement(LIST_CREATE, Statement.RETURN_GENERATED_KEYS); statement.setString(1, listName); statement.setString(2, cognitoID); statement.setTimestamp(3, Timestamp.from(Instant.now())); @@ -32,6 +41,7 @@ public class ListAdder implements CallHandler { accessGrant.setInt(1, newID); accessGrant.setString(2, cognitoID); accessGrant.setInt(3, ListPermissions.getAll()); + accessGrant.setInt(4, nextPosition); System.out.println(accessGrant); accessGrant.executeUpdate(); connection.commit(); diff --git a/Lambdas/Lists/List/src/ListGetter.java b/Lambdas/Lists/List/src/ListGetter.java index de3fe5f..5886d35 100644 --- a/Lambdas/Lists/List/src/ListGetter.java +++ b/Lambdas/Lists/List/src/ListGetter.java @@ -12,7 +12,7 @@ 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 ListSharee WHERE userID = ?;"; + private final String GET_LISTS = "SELECT listID FROM ListSharee WHERE userID = ? ORDER BY uiPosition;"; private final String SHARE_CHECK = "SELECT * FROM ListSharee WHERE listID = ?;"; private final String GET_ENTRIES = "SELECT * FROM ListProduct WHERE listID = ?;"; @@ -42,12 +42,14 @@ public class ListGetter implements CallHandler{ ResultSet accessResults = checkAccess.executeQuery(); int sharees = 0; boolean verifiedAccess = false; + int uiPosition = 1; while ((sharees < 2 && accessResults.next()) || !verifiedAccess) { if (accessResults.getString("userID").equals(cognitoID)) { verifiedAccess = true; if (!ListPermissions.hasPermission(accessResults.getInt("permissionLevel"), "Read")) { throw new AccessControlException("User " + cognitoID + " does not have permission to read list " + id); } + uiPosition = accessResults.getInt("uiPosition"); } sharees++; } @@ -61,7 +63,7 @@ public class ListGetter implements CallHandler{ ResultSet getListResults = getList.executeQuery(); getListResults.first(); System.out.println(getListResults); - List retrievedList = new List(getListResults, shared); + List retrievedList = new List(getListResults, shared, uiPosition); System.out.println(retrievedList); PreparedStatement getListEntries = connection.prepareStatement(GET_ENTRIES); getListEntries.setInt(1, id); 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 46dd926..6ef7e05 100644 --- a/Listify/app/src/main/java/com/example/listify/ItemDetails.java +++ b/Listify/app/src/main/java/com/example/listify/ItemDetails.java @@ -1,27 +1,15 @@ package com.example.listify; -import android.app.Dialog; -import android.graphics.Color; -import android.graphics.drawable.ColorDrawable; import android.os.Bundle; - -import com.amplifyframework.auth.AuthException; +import android.view.View; +import android.widget.*; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; import com.bumptech.glide.Glide; import com.example.listify.data.List; import com.example.listify.data.ListEntry; 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.view.Window; -import android.view.WindowManager; -import android.widget.ImageButton; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; -import android.widget.Toast; - import org.json.JSONException; import java.io.IOException; @@ -239,7 +227,7 @@ public class ItemDetails extends AppCompatActivity implements ListPickerDialogFr Requestor requestor = new Requestor(am, configs.getProperty("apiKey")); SynchronousReceiver idReceiver = new SynchronousReceiver<>(); - com.example.listify.data.List newList = new List(-1, name, "user filled by lambda", Instant.now().toEpochMilli()); + com.example.listify.data.List newList = new List(-1, name, "user filled by lambda", Instant.now().toEpochMilli(), -1); Thread t = new Thread(new Runnable() { @Override 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 ec0c89b..55b3da0 100644 --- a/Listify/app/src/main/java/com/example/listify/MainActivity.java +++ b/Listify/app/src/main/java/com/example/listify/MainActivity.java @@ -205,7 +205,7 @@ public class MainActivity extends AppCompatActivity implements CreateListDialogF Requestor requestor = new Requestor(am, configs.getProperty("apiKey")); SynchronousReceiver idReceiver = new SynchronousReceiver<>(); - List newList = new List(-1, name, "user filled by lambda", Instant.now().toEpochMilli()); + List newList = new List(-1, name, "user filled by lambda", Instant.now().toEpochMilli(), -1); try { requestor.postObject(newList, idReceiver, idReceiver); 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 index e04211f..580eef6 100644 --- a/Listify/app/src/main/java/com/example/listify/data/List.java +++ b/Listify/app/src/main/java/com/example/listify/data/List.java @@ -9,18 +9,20 @@ public class List { long lastUpdated; final ListEntry[] entries; boolean shared; + Integer uiPosition; - public List(Integer itemID, String name, String owner, long lastUpdated, ListEntry[] entries, boolean shared) { + public List(Integer itemID, String name, String owner, long lastUpdated, ListEntry[] entries, boolean shared, Integer uiPosition) { this.itemID = itemID; this.name = name; this.owner = owner; this.lastUpdated = lastUpdated; this.entries = entries; this.shared = false; + this.uiPosition = uiPosition; } - public List(Integer itemID, String name, String owner, long lastUpdated) { - this(itemID, name, owner, lastUpdated, null, false); + public List(Integer itemID, String name, String owner, long lastUpdated, Integer uiPosition) { + this(itemID, name, owner, lastUpdated, null, false, uiPosition); } @Override @@ -32,6 +34,7 @@ public class List { ", lastUpdated=" + lastUpdated + ", entries=" + Arrays.toString(entries) + ", shared=" + shared + + ", uiPosition=" + uiPosition + '}'; } @@ -78,4 +81,12 @@ public class List { public void setShared(boolean shared) { this.shared = shared; } + + public Integer getUiPosition() { + return uiPosition; + } + + public void setUiPosition(Integer uiPosition) { + this.uiPosition = uiPosition; + } } diff --git a/Listify/app/src/main/java/com/example/listify/ui/home/HomeFragment.java b/Listify/app/src/main/java/com/example/listify/ui/home/HomeFragment.java index bd44ea3..77b7739 100644 --- a/Listify/app/src/main/java/com/example/listify/ui/home/HomeFragment.java +++ b/Listify/app/src/main/java/com/example/listify/ui/home/HomeFragment.java @@ -88,7 +88,7 @@ public class HomeFragment extends Fragment implements CreateListDialogFragment.O Requestor requestor = new Requestor(am, configs.getProperty("apiKey")); SynchronousReceiver idReceiver = new SynchronousReceiver<>(); - List newList = new List(-1, name, "user filled by lambda", Instant.now().toEpochMilli()); + List newList = new List(-1, name, "user filled by lambda", Instant.now().toEpochMilli() , -1); try { requestor.postObject(newList, idReceiver, idReceiver); From 35f709fcd949ff887e00f618b2ed9c00b47485ff Mon Sep 17 00:00:00 2001 From: NMerz Date: Sat, 14 Nov 2020 16:21:18 -0500 Subject: [PATCH 2/5] Add list position changing Lambdas Initial shot at repositioning Lambdas. --- .../src/ListRepositionActor.java | 60 +++++++++++++++++++ .../ListReposition/src/ListRepositionPUT.java | 11 ++++ Lambdas/Lists/ListShare/src/ListSharer.java | 14 ++++- .../example/listify/data/ListReposition.java | 35 +++++++++++ 4 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 Lambdas/Lists/ListReposition/src/ListRepositionActor.java create mode 100644 Lambdas/Lists/ListReposition/src/ListRepositionPUT.java create mode 100644 Listify/app/src/main/java/com/example/listify/data/ListReposition.java diff --git a/Lambdas/Lists/ListReposition/src/ListRepositionActor.java b/Lambdas/Lists/ListReposition/src/ListRepositionActor.java new file mode 100644 index 0000000..180e9a0 --- /dev/null +++ b/Lambdas/Lists/ListReposition/src/ListRepositionActor.java @@ -0,0 +1,60 @@ +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 ListRepositionActor implements CallHandler { + + private Connection connection; + private String cognitoID; + + public ListRepositionActor(Connection connection, String cognitoID) { + this.connection = connection; + this.cognitoID = cognitoID; + } + + final private String GET_PRIOR_POSITON = "SELECT uiPosition FROM ListSharee WHERE userID = ? AND listID = ?;"; + final private String SET_NEW_POSITON = "UPDATE ListSharee SET uiPosition = ? WHERE userID = ? AND listID = ?;"; + final private String DECREMENT_HIGHER_POSITIONS = "UPDATE ListSharee SET uiPosition = uiPosition - 1 WHERE uiPosition > ? AND userID = ?;"; + final private String INCREMENT_GEQ_POSITIONS = "UPDATE ListSharee SET uiPosition = uiPosition + 1 WHERE uiPosition >= ? AND userID = ?;"; + + + public Object conductAction(Map bodyMap, HashMap queryString, String cognitoID) throws SQLException { + Integer listID = (Integer) bodyMap.get("listID"); + Integer newPosition = (Integer) bodyMap.get("newPosition"); + + PreparedStatement getPriorPosition = connection.prepareStatement(GET_PRIOR_POSITON); + getPriorPosition.setString(1, cognitoID); + getPriorPosition.setInt(2, listID); + ResultSet priorPositionRS = getPriorPosition.executeQuery(); + if (!priorPositionRS.next()) { + throw new IllegalArgumentException("Bad listID for user"); + } + Integer priorPosition = priorPositionRS.getInt("uiPosition"); + + PreparedStatement fillPriorPosition = connection.prepareStatement(DECREMENT_HIGHER_POSITIONS); + fillPriorPosition.setInt(1, priorPosition); + fillPriorPosition.setString(2, cognitoID); + System.out.println(fillPriorPosition); + fillPriorPosition.executeUpdate(); + + PreparedStatement openNewPosition = connection.prepareStatement(INCREMENT_GEQ_POSITIONS); + openNewPosition.setInt(1, priorPosition); + openNewPosition.setString(2, cognitoID); + System.out.println(openNewPosition); + openNewPosition.executeUpdate(); + + PreparedStatement setNewPosition = connection.prepareStatement(SET_NEW_POSITON); + setNewPosition.setInt(1, newPosition); + setNewPosition.setString(2, cognitoID); + setNewPosition.setInt(3, listID); + System.out.println(setNewPosition); + setNewPosition.executeUpdate(); + + connection.commit(); + return null; + } + +} \ No newline at end of file diff --git a/Lambdas/Lists/ListReposition/src/ListRepositionPUT.java b/Lambdas/Lists/ListReposition/src/ListRepositionPUT.java new file mode 100644 index 0000000..20fc102 --- /dev/null +++ b/Lambdas/Lists/ListReposition/src/ListRepositionPUT.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 ListRepositionPUT implements RequestHandler, Object> { + + public Object handleRequest(Map inputMap, Context unfilled) { + return BasicHandler.handleRequest(inputMap, unfilled, ListRepositionActor.class); + } +} diff --git a/Lambdas/Lists/ListShare/src/ListSharer.java b/Lambdas/Lists/ListShare/src/ListSharer.java index 2d55631..2beef67 100644 --- a/Lambdas/Lists/ListShare/src/ListSharer.java +++ b/Lambdas/Lists/ListShare/src/ListSharer.java @@ -22,7 +22,8 @@ public class ListSharer implements CallHandler { } final private String CHECK_ACCESS = "SELECT * from ListSharee WHERE listID = ? AND userID = ?;"; - final private String SHARE_LIST = "INSERT INTO ListSharee(listID, userID, permissionLevel) VALUES(?, ?, ?) ON DUPLICATE KEY UPDATE permissionLevel = ?;"; + final private String SHARE_LIST = "INSERT INTO ListSharee(listID, userID, permissionLevel, ) VALUES(?, ?, ?, ?) ON DUPLICATE KEY UPDATE permissionLevel = ?;"; + private final String UI_POSITION_CHECK = "SELECT Max(uiPosition) as maxUIPosition FROM ListSharee WHERE userID = ?;"; public Object conductAction(Map bodyMap, HashMap queryString, String cognitoID) throws SQLException { PreparedStatement checkAccess = connection.prepareStatement(CHECK_ACCESS); @@ -62,12 +63,21 @@ public class ListSharer implements CallHandler { // throw new InputMismatchException("The specified user already has access"); // } + PreparedStatement uiPositionCheck = connection.prepareStatement(UI_POSITION_CHECK); + uiPositionCheck.setString(1, shareWithSub); + ResultSet uiPositionCheckRS = uiPositionCheck.executeQuery(); + int nextPosition = 1; + if (uiPositionCheckRS.next()) { + nextPosition = uiPositionCheckRS.getInt("maxUIPosition") + 1; + } + PreparedStatement shareList = connection.prepareStatement(SHARE_LIST); shareList.setInt(1, listID); shareList.setString(2, shareWithSub); Integer permissionLevel = Integer.parseInt(bodyMap.get("permissionLevel").toString()); shareList.setInt(3, permissionLevel); - shareList.setInt(4, permissionLevel); + shareList.setInt(4, nextPosition); + shareList.setInt(5, permissionLevel); shareList.executeUpdate(); connection.commit(); return null; diff --git a/Listify/app/src/main/java/com/example/listify/data/ListReposition.java b/Listify/app/src/main/java/com/example/listify/data/ListReposition.java new file mode 100644 index 0000000..6d3e5ef --- /dev/null +++ b/Listify/app/src/main/java/com/example/listify/data/ListReposition.java @@ -0,0 +1,35 @@ +package com.example.listify.data; + +public class ListReposition { + Integer listID; + Integer newPosition; + + public ListReposition(Integer listID, Integer newPosition) { + this.listID = listID; + this.newPosition = newPosition; + } + + @Override + public String toString() { + return "ListReposition{" + + "listID=" + listID + + ", newPosition=" + newPosition + + '}'; + } + + public Integer getListID() { + return listID; + } + + public void setListID(Integer listID) { + this.listID = listID; + } + + public Integer getNewPosition() { + return newPosition; + } + + public void setNewPosition(Integer newPosition) { + this.newPosition = newPosition; + } +} From 1fe04e038b79e25e84467e079ffe964710a6e165 Mon Sep 17 00:00:00 2001 From: NMerz Date: Sun, 15 Nov 2020 12:28:18 -0500 Subject: [PATCH 3/5] Refine repositioning logic --- .../src/ListRepositionActor.java | 28 +++++++++++++------ Lambdas/Lists/ListShare/src/ListSharer.java | 2 ++ .../com/example/listify/MainActivity.java | 2 ++ 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/Lambdas/Lists/ListReposition/src/ListRepositionActor.java b/Lambdas/Lists/ListReposition/src/ListRepositionActor.java index 180e9a0..a1d7517 100644 --- a/Lambdas/Lists/ListReposition/src/ListRepositionActor.java +++ b/Lambdas/Lists/ListReposition/src/ListRepositionActor.java @@ -15,8 +15,8 @@ public class ListRepositionActor implements CallHandler { this.cognitoID = cognitoID; } - final private String GET_PRIOR_POSITON = "SELECT uiPosition FROM ListSharee WHERE userID = ? AND listID = ?;"; - final private String SET_NEW_POSITON = "UPDATE ListSharee SET uiPosition = ? WHERE userID = ? AND listID = ?;"; + final private String GET_PRIOR_POSITION = "SELECT uiPosition FROM ListSharee WHERE userID = ? AND listID = ?;"; + final private String SET_NEW_POSITION = "UPDATE ListSharee SET uiPosition = ? WHERE userID = ? AND listID = ?;"; final private String DECREMENT_HIGHER_POSITIONS = "UPDATE ListSharee SET uiPosition = uiPosition - 1 WHERE uiPosition > ? AND userID = ?;"; final private String INCREMENT_GEQ_POSITIONS = "UPDATE ListSharee SET uiPosition = uiPosition + 1 WHERE uiPosition >= ? AND userID = ?;"; @@ -25,7 +25,7 @@ public class ListRepositionActor implements CallHandler { Integer listID = (Integer) bodyMap.get("listID"); Integer newPosition = (Integer) bodyMap.get("newPosition"); - PreparedStatement getPriorPosition = connection.prepareStatement(GET_PRIOR_POSITON); + PreparedStatement getPriorPosition = connection.prepareStatement(GET_PRIOR_POSITION); getPriorPosition.setString(1, cognitoID); getPriorPosition.setInt(2, listID); ResultSet priorPositionRS = getPriorPosition.executeQuery(); @@ -34,19 +34,29 @@ public class ListRepositionActor implements CallHandler { } Integer priorPosition = priorPositionRS.getInt("uiPosition"); + PreparedStatement openNewPosition = connection.prepareStatement(INCREMENT_GEQ_POSITIONS); + + if (newPosition.equals(priorPosition)) { + return null; + } + if (newPosition < priorPosition) { + openNewPosition.setInt(1, newPosition); + } else { + openNewPosition.setInt(1, newPosition + 1); + } + openNewPosition.setString(2, cognitoID); + System.out.println(openNewPosition); + openNewPosition.executeUpdate(); + PreparedStatement fillPriorPosition = connection.prepareStatement(DECREMENT_HIGHER_POSITIONS); fillPriorPosition.setInt(1, priorPosition); fillPriorPosition.setString(2, cognitoID); System.out.println(fillPriorPosition); fillPriorPosition.executeUpdate(); - PreparedStatement openNewPosition = connection.prepareStatement(INCREMENT_GEQ_POSITIONS); - openNewPosition.setInt(1, priorPosition); - openNewPosition.setString(2, cognitoID); - System.out.println(openNewPosition); - openNewPosition.executeUpdate(); - PreparedStatement setNewPosition = connection.prepareStatement(SET_NEW_POSITON); + + PreparedStatement setNewPosition = connection.prepareStatement(SET_NEW_POSITION); setNewPosition.setInt(1, newPosition); setNewPosition.setString(2, cognitoID); setNewPosition.setInt(3, listID); diff --git a/Lambdas/Lists/ListShare/src/ListSharer.java b/Lambdas/Lists/ListShare/src/ListSharer.java index c8b67cd..a80d0d8 100644 --- a/Lambdas/Lists/ListShare/src/ListSharer.java +++ b/Lambdas/Lists/ListShare/src/ListSharer.java @@ -65,6 +65,7 @@ public class ListSharer implements CallHandler { PreparedStatement uiPositionCheck = connection.prepareStatement(UI_POSITION_CHECK); uiPositionCheck.setString(1, shareWithSub); + System.out.println(uiPositionCheck); ResultSet uiPositionCheckRS = uiPositionCheck.executeQuery(); int nextPosition = 1; if (uiPositionCheckRS.next()) { @@ -78,6 +79,7 @@ public class ListSharer implements CallHandler { shareList.setInt(3, permissionLevel); shareList.setInt(4, nextPosition); shareList.setInt(5, permissionLevel); + System.out.println(shareList); shareList.executeUpdate(); connection.commit(); return null; 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 55b3da0..b4864c8 100644 --- a/Listify/app/src/main/java/com/example/listify/MainActivity.java +++ b/Listify/app/src/main/java/com/example/listify/MainActivity.java @@ -17,6 +17,7 @@ import androidx.navigation.ui.AppBarConfiguration; import androidx.navigation.ui.NavigationUI; import com.amplifyframework.auth.AuthException; import com.example.listify.data.List; +import com.example.listify.data.ListReposition; import com.example.listify.data.SearchHistory; import com.example.listify.ui.LoginPage; import com.google.android.material.navigation.NavigationView; @@ -108,6 +109,7 @@ public class MainActivity extends AppCompatActivity implements CreateListDialogF requestor.getObject("N/A", SearchHistory.class, historyReceiver, historyReceiver); try { System.out.println(historyReceiver.await()); + requestor.putObject(new ListReposition(291, 1)); } catch (Exception e) { e.printStackTrace(); } From 5f14d2462523d2dd5ed9f23190e9070cff3b8e1e Mon Sep 17 00:00:00 2001 From: Aaron Sun Date: Sun, 15 Nov 2020 12:04:04 -0800 Subject: [PATCH 4/5] Wrote the Lambdas API for getting and deleting list sharees -- testing still needed --- Lambdas/Lists/List/src/List.java | 16 ++--- Lambdas/Lists/ListShare/src/ListShare.java | 37 +++++++++++ .../Lists/ListShare/src/ListShareDELETE.java | 12 ++++ .../Lists/ListShare/src/ListShareDeleter.java | 65 +++++++++++++++++++ Lambdas/Lists/ListShare/src/ListShareGET.java | 11 ++++ .../Lists/ListShare/src/ListShareGetter.java | 40 ++++++++++++ .../java/com/example/listify/data/List.java | 8 +-- .../com/example/listify/data/ListShare.java | 12 ++++ 8 files changed, 189 insertions(+), 12 deletions(-) create mode 100644 Lambdas/Lists/ListShare/src/ListShare.java create mode 100644 Lambdas/Lists/ListShare/src/ListShareDELETE.java create mode 100644 Lambdas/Lists/ListShare/src/ListShareDeleter.java create mode 100644 Lambdas/Lists/ListShare/src/ListShareGET.java create mode 100644 Lambdas/Lists/ListShare/src/ListShareGetter.java diff --git a/Lambdas/Lists/List/src/List.java b/Lambdas/Lists/List/src/List.java index 02d9723..83b8274 100644 --- a/Lambdas/Lists/List/src/List.java +++ b/Lambdas/Lists/List/src/List.java @@ -19,10 +19,6 @@ public class List { this.shared = shared; } - public void addItemEntry(ItemEntry entry) { - entries.add(entry); - } - @Override public String toString() { return "List{" + @@ -34,10 +30,6 @@ public class List { '}'; } - public ItemEntry[] getEntries() { - return entries.toArray(new ItemEntry[entries.size()]); - } - public Integer getItemID() { return itemID; } @@ -77,4 +69,12 @@ public class List { public void setShared(boolean shared) { this.shared = shared; } + + public ItemEntry[] getEntries() { + return entries.toArray(new ItemEntry[entries.size()]); + } + + public void addItemEntry(ItemEntry entry) { + entries.add(entry); + } } diff --git a/Lambdas/Lists/ListShare/src/ListShare.java b/Lambdas/Lists/ListShare/src/ListShare.java new file mode 100644 index 0000000..151d842 --- /dev/null +++ b/Lambdas/Lists/ListShare/src/ListShare.java @@ -0,0 +1,37 @@ +package com.example.listify.data; + +public class ListShare { + Integer listID; + String shareWithEmail; + ArrayList other; + + public ListShare(ResultSet listRow) throws SQLException { + this.listID = listRow.getInt("listID"); + this.shareWithEmail = listRow.getString("userID"); + other = new ArrayList<>(); + } + + public Integer getListID() { + return listID; + } + + public void setListID(Integer listID) { + this.listID = listID; + } + + public String getShareWithEmail() { + return shareWithEmail; + } + + public void setShareWithEmail(String shareWithEmail) { + this.shareWithEmail = shareWithEmail; + } + + public ListShare[] getEntries() { + return other.toArray(new ListShare[other.size()]); + } + + public void addtoList(ListShare entry) { + other.add(entry); + } +} diff --git a/Lambdas/Lists/ListShare/src/ListShareDELETE.java b/Lambdas/Lists/ListShare/src/ListShareDELETE.java new file mode 100644 index 0000000..784a725 --- /dev/null +++ b/Lambdas/Lists/ListShare/src/ListShareDELETE.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 ListShareDELETE implements RequestHandler, Object> { + + public Object handleRequest(Map inputMap, Context unfilled) { + return BasicHandler.handleRequest(inputMap, unfilled, ListShareDeleter.class); + } + +} diff --git a/Lambdas/Lists/ListShare/src/ListShareDeleter.java b/Lambdas/Lists/ListShare/src/ListShareDeleter.java new file mode 100644 index 0000000..7ec0076 --- /dev/null +++ b/Lambdas/Lists/ListShare/src/ListShareDeleter.java @@ -0,0 +1,65 @@ +import java.security.AccessControlException; +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 ListShareDeleter implements CallHandler { + private final Connection connection; + private final String cognitoID; + + private final String GET_LIST_ACCESS = "SELECT * FROM List WHERE (owner = ? AND listID = ?);"; + private final String REMOVE_SHAREE = "DELETE FROM ListSharee WHERE listID = ? AND user = ?;"; + + public ListShareDeleter(Connection connection, String cognitoID) { + this.connection = connection; + this.cognitoID = cognitoID; + } + + @Override + public Object conductAction(Map bodyMap, HashMap queryMap, String cognitoID) throws SQLException { + Integer listID = Integer.parseInt(queryMap.get("id")); + + InvokeRequest invokeRequest = new InvokeRequest(); + invokeRequest.setFunctionName("UserGET"); + invokeRequest.setPayload("{" + + " \"body\": {" + + " \"emailToCheck\": \"" + bodyMap.get("shareWithEmail").toString() + "\"" + + " }," + + " \"params\": {" + + " \"querystring\": {" + + " }" + + " }," + + " \"context\": {" + + " \"sub\": \"not used\"" + + " }" + + "}"); + InvokeResult invokeResult = AWSLambdaClientBuilder.defaultClient().invoke(invokeRequest); + + String shareeID = new String(invokeResult.getPayload().array()).replace("\"", ""); + + //Ensure that the user who is unsharing a list is the owner of that list + PreparedStatement accessCheck = connection.prepareStatement(GET_LIST_ACCESS); + accessCheck.setString(1, cognitoID); + accessCheck.setInt(2, listID); + + ResultSet userLists = accessCheck.executeQuery(); + + //User does not own the list; unshare attempt fails + if (!userLists.next()) { + throw new AccessControlException("User does not have access to list"); + } + + //Unshare the list with the specified sharee + PreparedStatement unshareList = connection.prepareStatement(REMOVE_SHAREE); + unshareList.setInt(1, listID); + unshareList.setInt(2, shareeID); + + cleanAccess.executeUpdate(); + connection.commit(); + + return null; + } +} diff --git a/Lambdas/Lists/ListShare/src/ListShareGET.java b/Lambdas/Lists/ListShare/src/ListShareGET.java new file mode 100644 index 0000000..d59ffcf --- /dev/null +++ b/Lambdas/Lists/ListShare/src/ListShareGET.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 ListShareGET implements RequestHandler, Object> { + + public Object handleRequest(Map inputMap, Context unfilled) { + return BasicHandler.handleRequest(inputMap, unfilled, ListShareGetter.class); + } +} diff --git a/Lambdas/Lists/ListShare/src/ListShareGetter.java b/Lambdas/Lists/ListShare/src/ListShareGetter.java new file mode 100644 index 0000000..009f0d6 --- /dev/null +++ b/Lambdas/Lists/ListShare/src/ListShareGetter.java @@ -0,0 +1,40 @@ +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; + +public class ListShareGetter implements CallHandler{ + private final Connection connection; + private final String cognitoID; + + private final String GET_LISTS = "SELECT * FROM ListSharee WHERE listID = ?;"; + + public ListShareGetter(Connection connection, String cognitoID) { + this.connection = connection; + this.cognitoID = cognitoID; + } + + @Override + public Object conductAction(Map bodyMap, HashMap queryMap, String cognitoID) throws SQLException { + Integer listID = Integer.parseInt(queryMap.get("id")); + + PreparedStatement getList = connection.prepareStatement(GET_LIST); + getList.setInt(1, listID); + + ResultSet getListResults = getList.executeQuery(); + getListResults.first(); + + //ListShare object to hold the data values of the first row retrived + ListShare first = new ListShare(getListResults); + + //Insert the ListShare objects to hold the data of the remaining rows into first's ListShare list + while (getListResults.next()) { + first.addtoList(new ListShare(getListResults)); + } + + return first; + } +} 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 index e04211f..6a3fab0 100644 --- a/Listify/app/src/main/java/com/example/listify/data/List.java +++ b/Listify/app/src/main/java/com/example/listify/data/List.java @@ -67,10 +67,6 @@ public class List { this.lastUpdated = lastUpdated; } - public ListEntry[] getEntries() { - return entries; - } - public boolean isShared() { return shared; } @@ -78,4 +74,8 @@ public class List { public void setShared(boolean shared) { this.shared = shared; } + + public ListEntry[] getEntries() { + return entries; + } } diff --git a/Listify/app/src/main/java/com/example/listify/data/ListShare.java b/Listify/app/src/main/java/com/example/listify/data/ListShare.java index 406f286..df984ee 100644 --- a/Listify/app/src/main/java/com/example/listify/data/ListShare.java +++ b/Listify/app/src/main/java/com/example/listify/data/ListShare.java @@ -3,10 +3,18 @@ package com.example.listify.data; public class ListShare { Integer listID; String shareWithEmail; + final ListShare[] other; + + public ListShare(Integer listID, String shareWithEmail, ListShare[] other) { + this.listID = listID; + this.shareWithEmail = shareWithEmail; + this.other = other; + } public ListShare(Integer listID, String shareWithEmail) { this.listID = listID; this.shareWithEmail = shareWithEmail; + this.other = null; } public Integer getListID() { @@ -24,4 +32,8 @@ public class ListShare { public void setShareWithEmail(String shareWithEmail) { this.shareWithEmail = shareWithEmail; } + + public ListShare[] getEntries() { + return other; + } } From 519feec6f47b0872c4939faa6de1ec5b715e1f34 Mon Sep 17 00:00:00 2001 From: Aaron Sun Date: Sun, 15 Nov 2020 17:22:30 -0800 Subject: [PATCH 5/5] Viewing sharees v1 --- .../java/com/example/listify/ListPage.java | 4 +- .../java/com/example/listify/ListSharees.java | 102 ++++++++++++++ .../adapter/ShareeSwipeableAdapter.java | 128 ++++++++++++++++++ .../res/layout/activity_listofsharees.xml | 22 +++ ...ry.xml => shopping_list_product_entry.xml} | 0 5 files changed, 254 insertions(+), 2 deletions(-) create mode 100644 Listify/app/src/main/java/com/example/listify/ListSharees.java create mode 100644 Listify/app/src/main/java/com/example/listify/adapter/ShareeSwipeableAdapter.java create mode 100644 Listify/app/src/main/res/layout/activity_listofsharees.xml rename Listify/app/src/main/res/layout/{activity_listproductentry.xml => shopping_list_product_entry.xml} (100%) diff --git a/Listify/app/src/main/java/com/example/listify/ListPage.java b/Listify/app/src/main/java/com/example/listify/ListPage.java index 49cddfa..1828e89 100644 --- a/Listify/app/src/main/java/com/example/listify/ListPage.java +++ b/Listify/app/src/main/java/com/example/listify/ListPage.java @@ -249,7 +249,7 @@ public class ListPage extends AppCompatActivity implements Requestor.Receiver { MyAdapter (Context c, ArrayList names, ArrayList stores, ArrayList prices, ArrayList quantity, ArrayList images) { - super(c, R.layout.activity_listproductentry, R.id.productView, names); + super(c, R.layout.shopping_list_product_entry, R.id.productView, names); context = c; pNames = names; pStores = stores; @@ -262,7 +262,7 @@ public class ListPage extends AppCompatActivity implements Requestor.Receiver { @Override public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { LayoutInflater layoutInflater = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); - View listproduct = layoutInflater.inflate(R.layout.activity_listproductentry, parent,false); + View listproduct = layoutInflater.inflate(R.layout.shopping_list_product_entry, parent,false); decrQuan = (Button) listproduct.findViewById(R.id.buttonDecr); incrQuan = (Button) listproduct.findViewById(R.id.buttonIncr); diff --git a/Listify/app/src/main/java/com/example/listify/ListSharees.java b/Listify/app/src/main/java/com/example/listify/ListSharees.java new file mode 100644 index 0000000..c7527a8 --- /dev/null +++ b/Listify/app/src/main/java/com/example/listify/ListSharees.java @@ -0,0 +1,102 @@ +package com.example.listify; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.ProgressBar; +import android.widget.TextView; + +import com.bumptech.glide.Glide; +import com.example.listify.adapter.ShareeSwipeableAdapter; +import com.example.listify.adapter.ShoppingListsSwipeableAdapter; +import com.example.listify.data.Chain; +import com.example.listify.data.Item; +import com.example.listify.data.List; +import com.example.listify.data.ListEntry; +import com.example.listify.data.ListShare; + +import org.json.JSONException; + +import java.io.IOException; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; + +import static com.example.listify.MainActivity.am; + +public class ListSharees extends AppCompatActivity implements Requestor.Receiver { + ShareeSwipeableAdapter myAdapter; + Requestor requestor; + ProgressBar loadingListItems; + + + DecimalFormat df = new DecimalFormat("0.00"); + + // TODO: Display a message if their list is empty + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_listofsharees); + + final int listID = (int) getIntent().getSerializableExtra("listID"); + + Properties configs = new Properties(); + try { + configs = AuthManager.loadProperties(this, "android.resource://" + getPackageName() + "/raw/auths.json"); + } catch (IOException | JSONException e) { + e.printStackTrace(); + } + requestor = new Requestor(am, configs.getProperty("apiKey")); + requestor.getObject(Integer.toString(listID), ListShare.class, this); + + loadingListItems = findViewById(R.id.progress_loading_list_items); + loadingListItems.setVisibility(View.VISIBLE); + } + + @Override + public void acceptDelivery(Object delivered) { + ListShare sharee = (ListShare) delivered; + + if(sharee != null) { + SynchronousReceiver listShareReceiver = new SynchronousReceiver<>(); + requestor.getObject(Integer.toString(sharee.getListID()), ListShare.class, listShareReceiver, listShareReceiver); + + ArrayList resultList = new ArrayList<>(); + ListShare result; + + try { + result = listShareReceiver.await(); + } + catch (Exception e) { + e.printStackTrace(); + result = null; + } + + if(result != null) { + resultList.add(result); + + for(ListShare r : result.getEntries()) { + resultList.add(r); + } + + myAdapter = new ShareeSwipeableAdapter(this, resultList); + } + } + } +} diff --git a/Listify/app/src/main/java/com/example/listify/adapter/ShareeSwipeableAdapter.java b/Listify/app/src/main/java/com/example/listify/adapter/ShareeSwipeableAdapter.java new file mode 100644 index 0000000..ac8ee0e --- /dev/null +++ b/Listify/app/src/main/java/com/example/listify/adapter/ShareeSwipeableAdapter.java @@ -0,0 +1,128 @@ +package com.example.listify.adapter; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; + +import com.chauthai.swipereveallayout.SwipeRevealLayout; +import com.chauthai.swipereveallayout.ViewBinderHelper; +import com.example.listify.AuthManager; +import com.example.listify.ListPage; +import com.example.listify.R; +import com.example.listify.Requestor; +import com.example.listify.data.List; +import com.example.listify.data.ListShare; + +import org.json.JSONException; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Properties; + +import static com.example.listify.MainActivity.am; + +public class ShareeSwipeableAdapter extends BaseAdapter { + private Activity activity; + private ArrayList sharees; + private LayoutInflater inflater; + private final ViewBinderHelper binderHelper; + + public ShareeSwipeableAdapter(Activity activity, ArrayList sharees){ + binderHelper = new ViewBinderHelper(); + this.activity = activity; + this.sharees = sharees; + } + + @Override + public int getCount() { + return sharees.size(); + } + + @Override + public Object getItem(int position) { + return sharees.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + ViewHolder holder; + + Properties configs = new Properties(); + try { + configs = AuthManager.loadProperties(activity, "android.resource://" + activity.getPackageName() + "/raw/auths.json"); + } catch (IOException | JSONException e) { + e.printStackTrace(); + } + Requestor requestor = new Requestor(am, configs.getProperty("apiKey")); + + if (inflater == null) { + inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + } + if (convertView == null) { + convertView = inflater.inflate(R.layout.shopping_lists_swipeable_name_item, null); + + holder = new ViewHolder(); + holder.swipeLayout = (SwipeRevealLayout)convertView.findViewById(R.id.swipe_layout); + holder.frontView = convertView.findViewById(R.id.front_layout); + holder.deleteList = convertView.findViewById(R.id.delete_list); + holder.shareList = convertView.findViewById(R.id.share_list); + holder.textView = (TextView) convertView.findViewById(R.id.shopping_list_name); + + convertView.setTag(holder); + } else { + holder = (ViewHolder) convertView.getTag(); + } + + final ListShare currSharee = sharees.get(position); + + // Bind the view to the unique list ID + binderHelper.bind(holder.swipeLayout, currSharee.getShareWithEmail()); + + holder.textView.setText(currSharee.getShareWithEmail()); + + holder.deleteList.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + + } + }); + + holder.shareList.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + + } + }); + + holder.frontView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + + } + }); + + return convertView; + } + + private class ViewHolder { + SwipeRevealLayout swipeLayout; + View frontView; + View deleteList; + View shareList; + TextView textView; + } +} diff --git a/Listify/app/src/main/res/layout/activity_listofsharees.xml b/Listify/app/src/main/res/layout/activity_listofsharees.xml new file mode 100644 index 0000000..58747d3 --- /dev/null +++ b/Listify/app/src/main/res/layout/activity_listofsharees.xml @@ -0,0 +1,22 @@ + + + + + + + \ No newline at end of file diff --git a/Listify/app/src/main/res/layout/activity_listproductentry.xml b/Listify/app/src/main/res/layout/shopping_list_product_entry.xml similarity index 100% rename from Listify/app/src/main/res/layout/activity_listproductentry.xml rename to Listify/app/src/main/res/layout/shopping_list_product_entry.xml