From dcf0789fa500862e6f588c3ffa46ad588b359616 Mon Sep 17 00:00:00 2001 From: Angela Huang Date: Mon, 17 Jul 2023 21:08:53 -0700 Subject: [PATCH 1/3] added followers --- .../server/controller/InboxController.java | 64 +++++++++++++++++-- .../moth/server/db/FollowersRepository.java | 5 ++ 2 files changed, 63 insertions(+), 6 deletions(-) diff --git a/server/src/main/java/edu/sjsu/moth/server/controller/InboxController.java b/server/src/main/java/edu/sjsu/moth/server/controller/InboxController.java index 7382b73d..1544b89a 100644 --- a/server/src/main/java/edu/sjsu/moth/server/controller/InboxController.java +++ b/server/src/main/java/edu/sjsu/moth/server/controller/InboxController.java @@ -1,14 +1,20 @@ package edu.sjsu.moth.server.controller; +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.JsonNode; +import edu.sjsu.moth.server.db.Followers; import edu.sjsu.moth.server.db.FollowersRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import reactor.core.publisher.Mono; - -import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static org.springframework.beans.support.PagedListHolder.DEFAULT_PAGE_SIZE; + @RestController public class InboxController { @Autowired @@ -34,10 +40,11 @@ public Mono followerHandler(String id, JsonNode inboxNode, String reques String follower = inboxNode.get("actor").asText(); if (requestType.equals("Follow")) { // find id, grab arraylist, append - return followersRepository.findItemById(id).flatMap(followedUser -> { - followedUser.getFollowers().add(follower); - return followersRepository.save(followedUser).thenReturn("done"); - }); + return followersRepository.findItemById(id).switchIfEmpty(Mono.just(new Followers(id, new ArrayList<>()))) + .flatMap(followedUser -> { + followedUser.getFollowers().add(follower); + return followersRepository.save(followedUser).thenReturn("done"); + }); } if (requestType.equals("Undo")) { // find id, grab arraylist, remove @@ -48,4 +55,49 @@ public Mono followerHandler(String id, JsonNode inboxNode, String reques } return Mono.empty(); } + + @GetMapping("/users/{id}/followers") + public Mono usersFollowers(@PathVariable String id, @RequestParam(required = false) Integer page, @RequestParam(required = false) Integer limit) { + var context = getContext(); + var items = followersRepository.findItemById(id).map(Followers::getFollowers); + String returnID = MothController.BASE_URL + "/users/" + id + "/followers"; + int pageSize = limit != null ? limit : DEFAULT_PAGE_SIZE; + if(page == null) { + String first = returnID + "?page=1"; + return items.map(v -> new Response1(context, returnID, "OrderedCollection", v.size(), first)); + } else { // page number is given + return items.map(v -> { + if(page*pageSize >= v.size()) { // no next page + return new Response2(context, returnID, "OrderedCollectionPage", v.size(), returnID, paginateFollowers(v, page, pageSize)); + } else { + String next = returnID + "?page=" + (page+1); + return new Response3(context, returnID, "OrderedCollectionPage", v.size(), next, returnID, paginateFollowers(v, page, pageSize)); + } + }); + } + } + + public List paginateFollowers(ArrayList followers, int pageNo, int pageSize) { + int startIndex = (pageNo - 1) * pageSize; + int endIndex = Math.min(startIndex + pageSize, followers.size()); + if (startIndex >= followers.size()) { + return Collections.emptyList(); + } + endIndex = Math.min(endIndex, followers.size()); + return followers.subList(startIndex, endIndex); + } + + public record Response1(String context, String id, String type, int totalItems, String first) {} + + // if a page number is given + public record Response2(String context, String id, String type, int totalItems, String partOf, List orderedItems) {} + + // if there is a next follower page + public record Response3(String context, String id, String type, int totalItems, String next, String partOf, List orderedItems) {} + + @JsonProperty("@context") + public String getContext() { + return "https://www.w3.org/ns/activitystreams"; + } + } diff --git a/server/src/main/java/edu/sjsu/moth/server/db/FollowersRepository.java b/server/src/main/java/edu/sjsu/moth/server/db/FollowersRepository.java index 066f8083..8b153539 100644 --- a/server/src/main/java/edu/sjsu/moth/server/db/FollowersRepository.java +++ b/server/src/main/java/edu/sjsu/moth/server/db/FollowersRepository.java @@ -1,11 +1,16 @@ package edu.sjsu.moth.server.db; +import org.springframework.data.domain.Pageable; import org.springframework.data.mongodb.repository.Query; import org.springframework.data.mongodb.repository.ReactiveMongoRepository; +import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; public interface FollowersRepository extends ReactiveMongoRepository{ @Query("{id:'?0'}") Mono findItemById(String id); + @Query("{id:'?0'}") + Flux findItemByIdAndPage(String id, Pageable pageable); + } From 14196690e27d9c37c17bb5f028e2c4380ca1ebeb Mon Sep 17 00:00:00 2001 From: Angela Huang Date: Wed, 19 Jul 2023 11:47:01 -0700 Subject: [PATCH 2/3] added followers, fixed mentioned issues --- .../server/controller/InboxController.java | 51 ++++++++++--------- .../moth/server/db/FollowersRepository.java | 3 -- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/server/src/main/java/edu/sjsu/moth/server/controller/InboxController.java b/server/src/main/java/edu/sjsu/moth/server/controller/InboxController.java index 1544b89a..49a591e2 100644 --- a/server/src/main/java/edu/sjsu/moth/server/controller/InboxController.java +++ b/server/src/main/java/edu/sjsu/moth/server/controller/InboxController.java @@ -1,7 +1,10 @@ package edu.sjsu.moth.server.controller; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.databind.JsonNode; +import edu.sjsu.moth.server.db.AccountRepository; import edu.sjsu.moth.server.db.Followers; import edu.sjsu.moth.server.db.FollowersRepository; import org.springframework.beans.factory.annotation.Autowired; @@ -20,6 +23,7 @@ public class InboxController { @Autowired FollowersRepository followersRepository; + //required to map payload from JSON to a Java Object for data access ObjectMapper mappedLoad; @@ -40,11 +44,10 @@ public Mono followerHandler(String id, JsonNode inboxNode, String reques String follower = inboxNode.get("actor").asText(); if (requestType.equals("Follow")) { // find id, grab arraylist, append - return followersRepository.findItemById(id).switchIfEmpty(Mono.just(new Followers(id, new ArrayList<>()))) - .flatMap(followedUser -> { - followedUser.getFollowers().add(follower); - return followersRepository.save(followedUser).thenReturn("done"); - }); + return followersRepository.findItemById(id).flatMap(followedUser -> { + followedUser.getFollowers().add(follower); + return followersRepository.save(followedUser).thenReturn("done"); + }); } if (requestType.equals("Undo")) { // find id, grab arraylist, remove @@ -57,47 +60,49 @@ public Mono followerHandler(String id, JsonNode inboxNode, String reques } @GetMapping("/users/{id}/followers") - public Mono usersFollowers(@PathVariable String id, @RequestParam(required = false) Integer page, @RequestParam(required = false) Integer limit) { - var context = getContext(); + public Mono usersFollowers(@PathVariable String id, @RequestParam(required = false) Integer page, @RequestParam(required = false) Integer limit) { var items = followersRepository.findItemById(id).map(Followers::getFollowers); String returnID = MothController.BASE_URL + "/users/" + id + "/followers"; int pageSize = limit != null ? limit : DEFAULT_PAGE_SIZE; if(page == null) { String first = returnID + "?page=1"; - return items.map(v -> new Response1(context, returnID, "OrderedCollection", v.size(), first)); + return items.map(v -> new UsersFollowersResponse(returnID, "OrderedCollection", v.size(), first, null, null, null)); } else { // page number is given + int pageNum = page < 1 ? 1 : page; return items.map(v -> { - if(page*pageSize >= v.size()) { // no next page - return new Response2(context, returnID, "OrderedCollectionPage", v.size(), returnID, paginateFollowers(v, page, pageSize)); + String newReturnID = limit != null ? returnID + "?page=" + page + "&limit=" + limit : returnID + "?page=" + page; + if(pageNum*pageSize >= v.size()) { // no next page + return new UsersFollowersResponse(newReturnID, "OrderedCollectionPage", v.size(), null, null, returnID, paginateFollowers(v, pageNum, pageSize)); } else { - String next = returnID + "?page=" + (page+1); - return new Response3(context, returnID, "OrderedCollectionPage", v.size(), next, returnID, paginateFollowers(v, page, pageSize)); + String next = returnID + "?page=" + (pageNum+1); + if(limit != null) { + next += "&limit=" + limit; + } + return new UsersFollowersResponse(newReturnID, "OrderedCollectionPage", v.size(), null, next, returnID, paginateFollowers(v, pageNum, pageSize)); } }); } } + public List paginateFollowers(ArrayList followers, int pageNo, int pageSize) { int startIndex = (pageNo - 1) * pageSize; int endIndex = Math.min(startIndex + pageSize, followers.size()); if (startIndex >= followers.size()) { return Collections.emptyList(); } - endIndex = Math.min(endIndex, followers.size()); return followers.subList(startIndex, endIndex); } - public record Response1(String context, String id, String type, int totalItems, String first) {} - - // if a page number is given - public record Response2(String context, String id, String type, int totalItems, String partOf, List orderedItems) {} - // if there is a next follower page - public record Response3(String context, String id, String type, int totalItems, String next, String partOf, List orderedItems) {} - - @JsonProperty("@context") - public String getContext() { - return "https://www.w3.org/ns/activitystreams"; + @JsonPropertyOrder({"@context", "id", "type", "totalItems", "first", "next", "partOf", "orderedItems"}) + public record UsersFollowersResponse(String id, String type, int totalItems, @JsonInclude(JsonInclude.Include.NON_NULL) String first, @JsonInclude(JsonInclude.Include.NON_NULL) String next, @JsonInclude(JsonInclude.Include.NON_NULL) String partOf, @JsonInclude(JsonInclude.Include.NON_NULL) List orderedItems) { + @JsonProperty("@context") + public String getContext() { + return "https://www.w3.org/ns/activitystreams"; + } } + + } diff --git a/server/src/main/java/edu/sjsu/moth/server/db/FollowersRepository.java b/server/src/main/java/edu/sjsu/moth/server/db/FollowersRepository.java index 8b153539..04c164f9 100644 --- a/server/src/main/java/edu/sjsu/moth/server/db/FollowersRepository.java +++ b/server/src/main/java/edu/sjsu/moth/server/db/FollowersRepository.java @@ -10,7 +10,4 @@ public interface FollowersRepository extends ReactiveMongoRepository findItemById(String id); - @Query("{id:'?0'}") - Flux findItemByIdAndPage(String id, Pageable pageable); - } From 7cedace578b723d4007180e32927a43facfb8ab3 Mon Sep 17 00:00:00 2001 From: Angela Huang Date: Wed, 19 Jul 2023 12:11:02 -0700 Subject: [PATCH 3/3] fixed more issues --- .../edu/sjsu/moth/server/controller/InboxController.java | 5 ++--- .../java/edu/sjsu/moth/server/db/FollowersRepository.java | 2 -- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/server/src/main/java/edu/sjsu/moth/server/controller/InboxController.java b/server/src/main/java/edu/sjsu/moth/server/controller/InboxController.java index 49a591e2..720eccf5 100644 --- a/server/src/main/java/edu/sjsu/moth/server/controller/InboxController.java +++ b/server/src/main/java/edu/sjsu/moth/server/controller/InboxController.java @@ -4,7 +4,6 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.databind.JsonNode; -import edu.sjsu.moth.server.db.AccountRepository; import edu.sjsu.moth.server.db.Followers; import edu.sjsu.moth.server.db.FollowersRepository; import org.springframework.beans.factory.annotation.Autowired; @@ -94,9 +93,9 @@ public List paginateFollowers(ArrayList followers, int pageNo, i return followers.subList(startIndex, endIndex); } - // if there is a next follower page + @JsonInclude(JsonInclude.Include.NON_NULL) @JsonPropertyOrder({"@context", "id", "type", "totalItems", "first", "next", "partOf", "orderedItems"}) - public record UsersFollowersResponse(String id, String type, int totalItems, @JsonInclude(JsonInclude.Include.NON_NULL) String first, @JsonInclude(JsonInclude.Include.NON_NULL) String next, @JsonInclude(JsonInclude.Include.NON_NULL) String partOf, @JsonInclude(JsonInclude.Include.NON_NULL) List orderedItems) { + public record UsersFollowersResponse(String id, String type, int totalItems, String first, String next, String partOf, List orderedItems) { @JsonProperty("@context") public String getContext() { return "https://www.w3.org/ns/activitystreams"; diff --git a/server/src/main/java/edu/sjsu/moth/server/db/FollowersRepository.java b/server/src/main/java/edu/sjsu/moth/server/db/FollowersRepository.java index 04c164f9..066f8083 100644 --- a/server/src/main/java/edu/sjsu/moth/server/db/FollowersRepository.java +++ b/server/src/main/java/edu/sjsu/moth/server/db/FollowersRepository.java @@ -1,9 +1,7 @@ package edu.sjsu.moth.server.db; -import org.springframework.data.domain.Pageable; import org.springframework.data.mongodb.repository.Query; import org.springframework.data.mongodb.repository.ReactiveMongoRepository; -import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; public interface FollowersRepository extends ReactiveMongoRepository{