diff --git a/pom.xml b/pom.xml index e4fd4ef..2739c40 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.example Widerhall - 0.0.5 + 0.0.6 diff --git a/src/main/java/de/srsoftware/widerhall/data/ListMember.java b/src/main/java/de/srsoftware/widerhall/data/ListMember.java index b0206fa..864d063 100644 --- a/src/main/java/de/srsoftware/widerhall/data/ListMember.java +++ b/src/main/java/de/srsoftware/widerhall/data/ListMember.java @@ -12,18 +12,30 @@ import java.util.*; import static de.srsoftware.widerhall.Constants.*; +/** + * @author Stephan Richter + * This class embodies the ListMembers table + */ public class ListMember { - private static final Logger LOG = LoggerFactory.getLogger(ListMember.class); public static final String TABLE_NAME = "ListMembers"; public static final int STATE_OWNER = 1; public static final int STATE_SUBSCRIBER = 2; public static final int STATE_AWAITING_CONFIRMATION = 4; + private static final Logger LOG = LoggerFactory.getLogger(ListMember.class); private static final String LIST_EMAIL = "list_email"; private static final String USER_EMAIL = "user_email"; private static final String STATE = "state"; + private final String listEmail,token,userEmail; private final int state; + /** + * create a new list member object + * @param listEmail + * @param userEmail + * @param state + * @param token + */ public ListMember(String listEmail, String userEmail, int state, String token){ this.listEmail = listEmail; this.userEmail = userEmail; @@ -31,10 +43,21 @@ public class ListMember { this.token = token; } + /** + * tries to confirm the token: + * This method loads the list member, that is assigned with the token. + * If no db entry is found for the token, null is returned. + * If an entry is found, the respective User object is loaded. + * If no User object is assigned, null is returned. + * If a matching User object is present, the member's state is altered from AWAITING_CONFIRMATION to SUBSCRIBER and the token is dropped. + * @param token + * @return + * @throws SQLException + */ public static User confirm(String token) throws SQLException { var rs = Database.open().select(TABLE_NAME).where(TOKEN,token).compile().exec(); if (rs.next()){ - var lm = new ListMember(rs.getString(LIST_EMAIL),rs.getString(USER_EMAIL),rs.getInt(STATE),rs.getString(TOKEN)); + var lm = ListMember.from(rs); rs.close(); User user = User.loadAll(List.of(lm.userEmail)).stream().findAny().orElse(null); if (user != null){ @@ -54,6 +77,15 @@ public class ListMember { } + /** + * Create a new list member entry in the database. + * If the member has the state AWAITING_CONFIRMATION, a token is assigned with the member, too. + * @param list + * @param user + * @param state + * @return + * @throws SQLException + */ public static ListMember create(MailingList list, User user, int state) throws SQLException { String token = null; if ((state & STATE_AWAITING_CONFIRMATION) > 0){ @@ -62,6 +94,10 @@ public class ListMember { return new ListMember(list.email(),user.email(),state,token).save(); } + /** + * create the table for ListMember objects + * @throws SQLException + */ public static void createTable() throws SQLException { var sql = new StringBuilder() .append("CREATE TABLE ").append(TABLE_NAME) @@ -74,11 +110,35 @@ public class ListMember { Database.open().query(sql).compile().run(); } + /** + * create a new ListMember object from a ResultSet + * @param rs + * @return + * @throws SQLException + */ + public static ListMember from(ResultSet rs) throws SQLException { + return new ListMember( + rs.getString(LIST_EMAIL), + rs.getString(USER_EMAIL), + rs.getInt(STATE), + rs.getString(TOKEN)); + } + + /** + * test, if the current object has a given state + * @param testState + * @return + */ public boolean hasState(int testState) { return (state & testState) > 0; } + /** + * return a set of list emails of MailingLists owned by the given user + * @param user + * @return + */ public static Set listsOwnedBy(User user) { var list = new HashSet(); try { @@ -92,6 +152,13 @@ public class ListMember { return list; } + /** + * load the list member specified by a MailingList and as User object + * @param list + * @param user + * @return + * @throws SQLException + */ public static ListMember load(MailingList list,User user) throws SQLException { var rs = Database .open() @@ -101,19 +168,21 @@ public class ListMember { .compile() .exec(); try { - if (rs.next()) { - return new ListMember(rs.getString(LIST_EMAIL), - rs.getString(USER_EMAIL), - rs.getInt(STATE), - rs.getString(TOKEN)); - } + if (rs.next()) return ListMember.from(rs); } finally { rs.close(); } return null; } + /** + * return a map of User → State for a given MailingList + * @param listEmail + * @return + * @throws SQLException + */ public static Map of(String listEmail) throws SQLException { + // Step 1: create mal USER_EMAIL → STATE for MailingList var rs = Database.open() .select(TABLE_NAME) .where(LIST_EMAIL,listEmail) @@ -121,6 +190,8 @@ public class ListMember { .exec(); var temp = new HashMap(); while (rs.next()) temp.put(rs.getString(USER_EMAIL),rs.getInt(STATE)); + rs.close(); + // Step 2: map user emails to users var result = new HashMap(); User.loadAll(temp.keySet()) .stream() @@ -128,6 +199,27 @@ public class ListMember { return result; } + /** + * Save the current ListMember object to the database + * @return + * @throws SQLException + */ + private ListMember save() throws SQLException { + var req = Database.open() + .insertInto(TABLE_NAME) + .set(LIST_EMAIL,listEmail) + .set(USER_EMAIL,userEmail) + .set(STATE,state); + if (token != null) req.set(TOKEN,token); + req.compile().run(); + return this; + } + + /** + * convert state flag to readable text + * @param state + * @return + */ public static String stateText(int state) { var words = new ArrayList(); if ((state & STATE_OWNER) > 0) words.add("owner"); @@ -136,20 +228,20 @@ public class ListMember { return String.join(", ",words); } - private ListMember save() throws SQLException { - var vals = new HashMap(); - vals.put(LIST_EMAIL,listEmail); - vals.put(USER_EMAIL,userEmail); - vals.put(STATE,state); - if (token != null) vals.put(TOKEN,token); - Database.open().insertInto(TABLE_NAME).values(vals).compile().run(); - return this; - } - + /** + * get the token of the current list member + * @return + */ public String token() { return token; } + /** + * unsubscribe a list member + * @param list + * @param user + * @throws SQLException + */ public static void unsubscribe(MailingList list, User user) throws SQLException { var db = Database.open(); var rs = db.select(TABLE_NAME) @@ -158,21 +250,9 @@ public class ListMember { .compile() .exec(); while (rs.next()){ - int state = Util.unset(rs.getInt(STATE),STATE_SUBSCRIBER,STATE_AWAITING_CONFIRMATION); - if (state < 1) { // drop entry - db.deleteFrom(TABLE_NAME) - .where(LIST_EMAIL,list.email()) - .where(USER_EMAIL,user.email()) - .compile() - .run(); - } else { // update entry: whitdraw subscription - db.update(TABLE_NAME) - .set(STATE,state) - .where(LIST_EMAIL,list.email()) - .where(USER_EMAIL,user.email()) - .compile() - .run(); - } + int state = Util.unset(rs.getInt(STATE),STATE_SUBSCRIBER,STATE_AWAITING_CONFIRMATION); // drop subscription and awaiting flags + var req = state < 1 ? db.deleteFrom(TABLE_NAME) : db.update(TABLE_NAME).set(STATE,state).set(TOKEN,null); + req.where(LIST_EMAIL,list.email()).where(USER_EMAIL,user.email()).compile().run(); } } }