Facades for forums. #172

This commit is contained in:
akwizgran
2015-12-17 13:37:55 +00:00
parent d0ba274111
commit 4450ab171a
25 changed files with 285 additions and 128 deletions

View File

@@ -170,7 +170,7 @@ public class BriarService extends RoboService implements EventListener {
public void eventOccurred(Event e) {
if (e instanceof MessageAddedEvent) {
MessageAddedEvent m = (MessageAddedEvent) e;
GroupId g = m.getGroup().getId();
GroupId g = m.getGroupId();
ContactId c = m.getContactId();
if (c != null) showMessageNotification(g, c);
}

View File

@@ -347,7 +347,7 @@ implements EventListener, OnClickListener, OnItemClickListener {
finishOnUiThread();
}
} else if (e instanceof MessageAddedEvent) {
GroupId g = ((MessageAddedEvent) e).getGroup().getId();
GroupId g = ((MessageAddedEvent) e).getGroupId();
if (g.equals(groupId)) {
LOG.info("Message added, reloading");
loadHeaders();

View File

@@ -20,8 +20,8 @@ import org.briarproject.api.event.EventListener;
import org.briarproject.api.event.RemoteSubscriptionsUpdatedEvent;
import org.briarproject.api.event.SubscriptionAddedEvent;
import org.briarproject.api.event.SubscriptionRemovedEvent;
import org.briarproject.api.forum.Forum;
import org.briarproject.api.forum.ForumManager;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupId;
import java.util.ArrayList;
@@ -43,7 +43,6 @@ implements EventListener, OnItemClickListener {
private AvailableForumsAdapter adapter = null;
private ListView list = null;
private ListLoadingProgressBar loading = null;
// Fields that are accessed from background threads must be volatile
@Inject private volatile ForumManager forumManager;
@@ -60,7 +59,7 @@ implements EventListener, OnItemClickListener {
list.setOnItemClickListener(this);
// Show a progress bar while the list is loading
loading = new ListLoadingProgressBar(this);
ListLoadingProgressBar loading = new ListLoadingProgressBar(this);
setContentView(loading);
}
@@ -78,12 +77,12 @@ implements EventListener, OnItemClickListener {
Collection<ForumContacts> available =
new ArrayList<ForumContacts>();
long now = System.currentTimeMillis();
for (Group g : forumManager.getAvailableGroups()) {
for (Forum f : forumManager.getAvailableForums()) {
try {
GroupId id = g.getId();
GroupId id = f.getId();
Collection<Contact> c =
forumManager.getSubscribers(id);
available.add(new ForumContacts(g, c));
available.add(new ForumContacts(f, c));
} catch (NoSuchSubscriptionException e) {
// Continue
}
@@ -142,18 +141,18 @@ implements EventListener, OnItemClickListener {
AvailableForumsItem item = adapter.getItem(position);
Collection<ContactId> visible = new ArrayList<ContactId>();
for (Contact c : item.getContacts()) visible.add(c.getId());
addSubscription(item.getGroup(), visible);
addSubscription(item.getForum(), visible);
String subscribed = getString(R.string.subscribed_toast);
Toast.makeText(this, subscribed, LENGTH_SHORT).show();
}
private void addSubscription(final Group g,
private void addSubscription(final Forum f,
final Collection<ContactId> visible) {
runOnDbThread(new Runnable() {
public void run() {
try {
forumManager.addGroup(g);
forumManager.setVisibility(g.getId(), visible);
forumManager.addForum(f);
forumManager.setVisibility(f.getId(), visible);
} catch (DbException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);

View File

@@ -41,7 +41,7 @@ class AvailableForumsAdapter extends ArrayAdapter<AvailableForumsItem> {
name.setSingleLine();
name.setEllipsize(END);
name.setPadding(pad, pad, pad, pad);
name.setText(item.getGroup().getName());
name.setText(item.getForum().getName());
layout.addView(name);
TextView status = new TextView(ctx);

View File

@@ -1,7 +1,7 @@
package org.briarproject.android.forum;
import org.briarproject.api.contact.Contact;
import org.briarproject.api.sync.Group;
import org.briarproject.api.forum.Forum;
import java.util.Collection;
@@ -13,8 +13,8 @@ class AvailableForumsItem {
this.forumContacts = forumContacts;
}
Group getGroup() {
return forumContacts.getGroup();
Forum getForum() {
return forumContacts.getForum();
}
Collection<Contact> getContacts() {

View File

@@ -9,8 +9,8 @@ class AvailableForumsItemComparator implements Comparator<AvailableForumsItem> {
public int compare(AvailableForumsItem a, AvailableForumsItem b) {
if (a == b) return 0;
String aName = a.getGroup().getName();
String bName = b.getGroup().getName();
String aName = a.getForum().getName();
String bName = b.getForum().getName();
return String.CASE_INSENSITIVE_ORDER.compare(aName, bName);
}
}

View File

@@ -17,9 +17,9 @@ import org.briarproject.R;
import org.briarproject.android.BriarActivity;
import org.briarproject.android.util.LayoutUtils;
import org.briarproject.api.db.DbException;
import org.briarproject.api.forum.Forum;
import org.briarproject.api.forum.ForumFactory;
import org.briarproject.api.forum.ForumManager;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupFactory;
import org.briarproject.util.StringUtils;
import java.util.logging.Logger;
@@ -52,7 +52,7 @@ implements OnEditorActionListener, OnClickListener {
private TextView feedback = null;
// Fields that are accessed from background threads must be volatile
@Inject private volatile GroupFactory groupFactory;
@Inject private volatile ForumFactory forumFactory;
@Inject private volatile ForumManager forumManager;
@Override
@@ -138,13 +138,13 @@ implements OnEditorActionListener, OnClickListener {
runOnDbThread(new Runnable() {
public void run() {
try {
Group g = groupFactory.createGroup(name);
Forum f = forumFactory.createForum(name);
long now = System.currentTimeMillis();
forumManager.addGroup(g);
forumManager.addForum(f);
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Storing forum took " + duration + " ms");
displayForum(g);
displayForum(f);
} catch (DbException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
@@ -154,13 +154,13 @@ implements OnEditorActionListener, OnClickListener {
});
}
private void displayForum(final Group g) {
private void displayForum(final Forum f) {
runOnUiThread(new Runnable() {
public void run() {
Intent i = new Intent(CreateForumActivity.this,
ForumActivity.class);
i.putExtra("briar.GROUP_ID", g.getId().getBytes());
i.putExtra("briar.FORUM_NAME", g.getName());
i.putExtra("briar.GROUP_ID", f.getId().getBytes());
i.putExtra("briar.FORUM_NAME", f.getName());
startActivity(i);
Toast.makeText(CreateForumActivity.this,
R.string.forum_created_toast, LENGTH_LONG).show();

View File

@@ -26,9 +26,9 @@ import org.briarproject.api.event.EventBus;
import org.briarproject.api.event.EventListener;
import org.briarproject.api.event.MessageAddedEvent;
import org.briarproject.api.event.SubscriptionRemovedEvent;
import org.briarproject.api.forum.Forum;
import org.briarproject.api.forum.ForumManager;
import org.briarproject.api.identity.Author;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.MessageHeader;
import org.briarproject.api.sync.MessageId;
@@ -74,7 +74,7 @@ OnClickListener, OnItemClickListener {
@Inject private volatile ForumManager forumManager;
@Inject private volatile EventBus eventBus;
private volatile GroupId groupId = null;
private volatile Group group = null;
private volatile Forum forum = null;
@Override
public void onCreate(Bundle state) {
@@ -152,10 +152,10 @@ OnClickListener, OnItemClickListener {
public void run() {
try {
long now = System.currentTimeMillis();
group = forumManager.getGroup(groupId);
forum = forumManager.getForum(groupId);
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Loading group " + duration + " ms");
LOG.info("Loading forum " + duration + " ms");
displayForumName();
} catch (NoSuchSubscriptionException e) {
finishOnUiThread();
@@ -170,7 +170,7 @@ OnClickListener, OnItemClickListener {
private void displayForumName() {
runOnUiThread(new Runnable() {
public void run() {
setTitle(group.getName());
setTitle(forum.getName());
}
});
}
@@ -313,7 +313,7 @@ OnClickListener, OnItemClickListener {
public void eventOccurred(Event e) {
if (e instanceof MessageAddedEvent) {
if (((MessageAddedEvent) e).getGroup().getId().equals(groupId)) {
if (((MessageAddedEvent) e).getGroupId().equals(groupId)) {
LOG.info("Message added, reloading");
loadHeaders();
}
@@ -330,13 +330,13 @@ OnClickListener, OnItemClickListener {
if (view == composeButton) {
Intent i = new Intent(this, WriteForumPostActivity.class);
i.putExtra("briar.GROUP_ID", groupId.getBytes());
i.putExtra("briar.FORUM_NAME", group.getName());
i.putExtra("briar.FORUM_NAME", forum.getName());
i.putExtra("briar.MIN_TIMESTAMP", getMinTimestampForNewMessage());
startActivity(i);
} else if (view == shareButton) {
Intent i = new Intent(this, ShareForumActivity.class);
i.putExtra("briar.GROUP_ID", groupId.getBytes());
i.putExtra("briar.FORUM_NAME", group.getName());
i.putExtra("briar.FORUM_NAME", forum.getName());
startActivity(i);
}
}
@@ -361,7 +361,7 @@ OnClickListener, OnItemClickListener {
MessageHeader item = adapter.getItem(position).getHeader();
Intent i = new Intent(this, ReadForumPostActivity.class);
i.putExtra("briar.GROUP_ID", groupId.getBytes());
i.putExtra("briar.FORUM_NAME", group.getName());
i.putExtra("briar.FORUM_NAME", forum.getName());
i.putExtra("briar.MESSAGE_ID", item.getId().getBytes());
Author author = item.getAuthor();
if (author != null) i.putExtra("briar.AUTHOR_NAME", author.getName());

View File

@@ -1,22 +1,22 @@
package org.briarproject.android.forum;
import org.briarproject.api.contact.Contact;
import org.briarproject.api.sync.Group;
import org.briarproject.api.forum.Forum;
import java.util.Collection;
class ForumContacts {
private final Group group;
private final Forum forum;
private final Collection<Contact> contacts;
ForumContacts(Group group, Collection<Contact> contacts) {
this.group = group;
ForumContacts(Forum forum, Collection<Contact> contacts) {
this.forum = forum;
this.contacts = contacts;
}
Group getGroup() {
return group;
Forum getForum() {
return forum;
}
Collection<Contact> getContacts() {

View File

@@ -32,6 +32,7 @@ import org.briarproject.api.event.MessageAddedEvent;
import org.briarproject.api.event.RemoteSubscriptionsUpdatedEvent;
import org.briarproject.api.event.SubscriptionAddedEvent;
import org.briarproject.api.event.SubscriptionRemovedEvent;
import org.briarproject.api.forum.Forum;
import org.briarproject.api.forum.ForumManager;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupId;
@@ -153,16 +154,16 @@ OnCreateContextMenuListener {
public void run() {
try {
long now = System.currentTimeMillis();
for (Group g : forumManager.getGroups()) {
for (Forum f : forumManager.getForums()) {
try {
Collection<MessageHeader> headers =
forumManager.getMessageHeaders(g.getId());
displayHeaders(g, headers);
forumManager.getMessageHeaders(f.getId());
displayHeaders(f, headers);
} catch (NoSuchSubscriptionException e) {
// Continue
}
}
int available = forumManager.getAvailableGroups().size();
int available = forumManager.getAvailableForums().size();
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Full load took " + duration + " ms");
@@ -189,11 +190,11 @@ OnCreateContextMenuListener {
});
}
private void displayHeaders(final Group g,
private void displayHeaders(final Forum f,
final Collection<MessageHeader> headers) {
runOnUiThread(new Runnable() {
public void run() {
GroupId id = g.getId();
GroupId id = f.getId();
groupIds.put(id, id);
list.setVisibility(VISIBLE);
loading.setVisibility(GONE);
@@ -201,7 +202,7 @@ OnCreateContextMenuListener {
ForumListItem item = findForum(id);
if (item != null) adapter.remove(item);
// Add a new item
adapter.add(new ForumListItem(g, headers));
adapter.add(new ForumListItem(f, headers));
adapter.sort(ForumListItemComparator.INSTANCE);
adapter.notifyDataSetChanged();
selectFirstUnread();
@@ -230,7 +231,7 @@ OnCreateContextMenuListener {
int count = adapter.getCount();
for (int i = 0; i < count; i++) {
ForumListItem item = adapter.getItem(i);
if (item.getGroup().getId().equals(g)) return item;
if (item.getForum().getId().equals(g)) return item;
}
return null; // Not found
}
@@ -255,8 +256,8 @@ OnCreateContextMenuListener {
public void eventOccurred(Event e) {
if (e instanceof MessageAddedEvent) {
Group g = ((MessageAddedEvent) e).getGroup();
if (groupIds.containsKey(g.getId())) {
GroupId g = ((MessageAddedEvent) e).getGroupId();
if (groupIds.containsKey(g)) {
LOG.info("Message added, reloading");
loadHeaders(g);
}
@@ -275,19 +276,20 @@ OnCreateContextMenuListener {
}
}
private void loadHeaders(final Group g) {
private void loadHeaders(final GroupId g) {
runOnDbThread(new Runnable() {
public void run() {
try {
long now = System.currentTimeMillis();
Forum f = forumManager.getForum(g);
Collection<MessageHeader> headers =
forumManager.getMessageHeaders(g.getId());
forumManager.getMessageHeaders(g);
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Partial load took " + duration + " ms");
displayHeaders(g, headers);
displayHeaders(f, headers);
} catch (NoSuchSubscriptionException e) {
removeForum(g.getId());
removeForum(g);
} catch (DbException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
@@ -320,7 +322,7 @@ OnCreateContextMenuListener {
public void run() {
try {
long now = System.currentTimeMillis();
int available = forumManager.getAvailableGroups().size();
int available = forumManager.getAvailableForums().size();
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Loading available took " + duration + " ms");
@@ -344,9 +346,9 @@ OnCreateContextMenuListener {
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
Intent i = new Intent(this, ForumActivity.class);
Group g = adapter.getItem(position).getGroup();
i.putExtra("briar.GROUP_ID", g.getId().getBytes());
i.putExtra("briar.FORUM_NAME", g.getName());
Forum f = adapter.getItem(position).getForum();
i.putExtra("briar.GROUP_ID", f.getId().getBytes());
i.putExtra("briar.FORUM_NAME", f.getName());
startActivity(i);
}
@@ -363,19 +365,19 @@ OnCreateContextMenuListener {
ContextMenuInfo info = menuItem.getMenuInfo();
int position = ((AdapterContextMenuInfo) info).position;
ForumListItem item = adapter.getItem(position);
removeSubscription(item.getGroup());
removeSubscription(item.getForum());
String unsubscribed = getString(R.string.unsubscribed_toast);
Toast.makeText(this, unsubscribed, LENGTH_SHORT).show();
}
return true;
}
private void removeSubscription(final Group g) {
private void removeSubscription(final Forum f) {
runOnDbThread(new Runnable() {
public void run() {
try {
long now = System.currentTimeMillis();
forumManager.removeGroup(g);
forumManager.removeForum(f);
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Removing group took " + duration + " ms");

View File

@@ -46,7 +46,7 @@ class ForumListAdapter extends ArrayAdapter<ForumListItem> {
name.setSingleLine();
name.setEllipsize(END);
name.setPadding(pad, pad, pad, pad);
String forumName = item.getGroup().getName();
String forumName = item.getForum().getName();
if (unread > 0) name.setText(forumName + " (" + unread + ")");
else name.setText(forumName);
layout.addView(name);

View File

@@ -1,19 +1,19 @@
package org.briarproject.android.forum;
import org.briarproject.api.sync.Group;
import org.briarproject.api.forum.Forum;
import org.briarproject.api.sync.MessageHeader;
import java.util.Collection;
class ForumListItem {
private final Group group;
private final Forum forum;
private final boolean empty;
private final long timestamp;
private final int unread;
ForumListItem(Group group, Collection<MessageHeader> headers) {
this.group = group;
ForumListItem(Forum forum, Collection<MessageHeader> headers) {
this.forum = forum;
empty = headers.isEmpty();
if (empty) {
timestamp = 0;
@@ -34,8 +34,8 @@ class ForumListItem {
}
}
Group getGroup() {
return group;
Forum getForum() {
return forum;
}
boolean isEmpty() {

View File

@@ -9,13 +9,13 @@ class ForumListItemComparator implements Comparator<ForumListItem> {
public int compare(ForumListItem a, ForumListItem b) {
if (a == b) return 0;
// The item with the newest message comes first
// The forum with the newest message comes first
long aTime = a.getTimestamp(), bTime = b.getTimestamp();
if (aTime > bTime) return -1;
if (aTime < bTime) return 1;
// Break ties by group name
String aName = a.getGroup().getName();
String bName = b.getGroup().getName();
// Break ties by forum name
String aName = a.getForum().getName();
String bName = b.getForum().getName();
return String.CASE_INSENSITIVE_ORDER.compare(aName, bName);
}
}

View File

@@ -28,14 +28,14 @@ import org.briarproject.api.crypto.CryptoExecutor;
import org.briarproject.api.crypto.KeyParser;
import org.briarproject.api.crypto.PrivateKey;
import org.briarproject.api.db.DbException;
import org.briarproject.api.forum.Forum;
import org.briarproject.api.forum.ForumManager;
import org.briarproject.api.forum.ForumPostFactory;
import org.briarproject.api.identity.AuthorId;
import org.briarproject.api.identity.IdentityManager;
import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.Message;
import org.briarproject.api.sync.MessageFactory;
import org.briarproject.api.sync.MessageId;
import org.briarproject.util.StringUtils;
@@ -79,11 +79,11 @@ implements OnItemSelectedListener, OnClickListener {
@Inject private volatile IdentityManager identityManager;
@Inject private volatile ForumManager forumManager;
@Inject private volatile CryptoComponent crypto;
@Inject private volatile MessageFactory messageFactory;
@Inject private volatile ForumPostFactory forumPostFactory;
private volatile MessageId parentId = null;
private volatile long minTimestamp = -1;
private volatile LocalAuthor localAuthor = null;
private volatile Group group = null;
private volatile Forum forum = null;
@Override
public void onCreate(Bundle state) {
@@ -138,7 +138,7 @@ implements OnItemSelectedListener, OnClickListener {
sendButton.setId(3);
sendButton.setBackgroundResource(0);
sendButton.setImageResource(R.drawable.social_send_now);
sendButton.setEnabled(false); // Enabled after loading the group
sendButton.setEnabled(false); // Enabled after loading the forum
sendButton.setOnClickListener(this);
RelativeLayout.LayoutParams right = CommonLayoutParams.relative();
right.addRule(ALIGN_PARENT_RIGHT);
@@ -170,7 +170,7 @@ implements OnItemSelectedListener, OnClickListener {
long now = System.currentTimeMillis();
Collection<LocalAuthor> localAuthors =
identityManager.getLocalAuthors();
group = forumManager.getGroup(groupId);
forum = forumManager.getForum(groupId);
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Load took " + duration + " ms");
@@ -204,7 +204,7 @@ implements OnItemSelectedListener, OnClickListener {
break;
}
}
setTitle(group.getName());
setTitle(forum.getName());
sendButton.setEnabled(true);
}
});
@@ -253,7 +253,7 @@ implements OnItemSelectedListener, OnClickListener {
}
public void onClick(View view) {
if (group == null) throw new IllegalStateException();
if (forum == null) throw new IllegalStateException();
String message = content.getText().toString();
if (message.equals("")) return;
createMessage(StringUtils.toUtf8(message));
@@ -270,14 +270,14 @@ implements OnItemSelectedListener, OnClickListener {
Message m;
try {
if (localAuthor == null) {
m = messageFactory.createAnonymousMessage(parentId,
group, "text/plain", timestamp, body);
m = forumPostFactory.createAnonymousPost(parentId,
forum, "text/plain", timestamp, body);
} else {
KeyParser keyParser = crypto.getSignatureKeyParser();
byte[] b = localAuthor.getPrivateKey();
PrivateKey authorKey = keyParser.parsePrivateKey(b);
m = messageFactory.createPseudonymousMessage(parentId,
group, localAuthor, authorKey, "text/plain",
m = forumPostFactory.createPseudonymousPost(parentId,
forum, localAuthor, authorKey, "text/plain",
timestamp, body);
}
} catch (GeneralSecurityException e) {

View File

@@ -1,22 +1,22 @@
package org.briarproject.api.event;
import org.briarproject.api.contact.ContactId;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupId;
/** An event that is broadcast when a message is added to the database. */
public class MessageAddedEvent extends Event {
private final Group group;
private final GroupId groupId;
private final ContactId contactId;
public MessageAddedEvent(Group group, ContactId contactId) {
this.group = group;
public MessageAddedEvent(GroupId groupId, ContactId contactId) {
this.groupId = groupId;
this.contactId = contactId;
}
/** Returns the group to which the message belongs. */
public Group getGroup() {
return group;
/** Returns the ID of the group to which the message belongs. */
public GroupId getGroupId() {
return groupId;
}
/**

View File

@@ -0,0 +1,10 @@
package org.briarproject.api.forum;
import org.briarproject.api.sync.GroupId;
public interface Forum {
GroupId getId();
String getName();
}

View File

@@ -0,0 +1,7 @@
package org.briarproject.api.forum;
public interface ForumFactory {
/** Creates a forum with the given name and a random salt. */
Forum createForum(String name);
}

View File

@@ -3,7 +3,6 @@ package org.briarproject.api.forum;
import org.briarproject.api.contact.Contact;
import org.briarproject.api.contact.ContactId;
import org.briarproject.api.db.DbException;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.Message;
import org.briarproject.api.sync.MessageHeader;
@@ -14,56 +13,54 @@ import java.util.Collection;
public interface ForumManager {
/**
* Subscribes to a group, or returns false if the user already has the
* maximum number of public subscriptions.
* Subscribes to a forum, or returns false if the user already has the
* maximum number of forum subscriptions.
*/
boolean addGroup(Group g) throws DbException;
boolean addForum(Forum f) throws DbException;
/** Stores a local message. */
void addLocalMessage(Message m) throws DbException;
/** Returns all groups to which the user could subscribe. */
Collection<Group> getAvailableGroups() throws DbException;
/** Returns all forums to which the user could subscribe. */
Collection<Forum> getAvailableForums() throws DbException;
/** Returns the group with the given ID, if the user subscribes to it. */
Group getGroup(GroupId g) throws DbException;
/** Returns the forum with the given ID, if the user subscribes to it. */
Forum getForum(GroupId g) throws DbException;
/** Returns all groups to which the user subscribes, excluding inboxes. */
Collection<Group> getGroups() throws DbException;
/** Returns all forums to which the user subscribes. */
Collection<Forum> getForums() throws DbException;
/** Returns the body of the message with the given ID. */
byte[] getMessageBody(MessageId m) throws DbException;
/** Returns the headers of all messages in the given group. */
/** Returns the headers of all messages in the given forum. */
Collection<MessageHeader> getMessageHeaders(GroupId g)
throws DbException;
/** Returns all contacts who subscribe to the given group. */
/** Returns all contacts who subscribe to the given forum. */
Collection<Contact> getSubscribers(GroupId g) throws DbException;
/** Returns the IDs of all contacts to which the given group is visible. */
/** Returns the IDs of all contacts to which the given forum is visible. */
Collection<ContactId> getVisibility(GroupId g) throws DbException;
/**
* Unsubscribes from a group. Any messages belonging to the group
* are deleted.
* Unsubscribes from a forum. Any messages belonging to the forum are
* deleted.
*/
void removeGroup(Group g) throws DbException;
void removeForum(Forum f) throws DbException;
/**
* Marks a message as read or unread.
*/
/** Marks a message as read or unread. */
void setReadFlag(MessageId m, boolean read) throws DbException;
/**
* Makes a group visible to the given set of contacts and invisible to any
* Makes a forum visible to the given set of contacts and invisible to any
* other current or future contacts.
*/
void setVisibility(GroupId g, Collection<ContactId> visible)
throws DbException;
/**
* Makes a group visible to all current and future contacts, or invisible
* Makes a forum visible to all current and future contacts, or invisible
* to future contacts.
*/
void setVisibleToAll(GroupId g, boolean all) throws DbException;

View File

@@ -0,0 +1,21 @@
package org.briarproject.api.forum;
import org.briarproject.api.crypto.PrivateKey;
import org.briarproject.api.identity.Author;
import org.briarproject.api.sync.Message;
import org.briarproject.api.sync.MessageId;
import java.io.IOException;
import java.security.GeneralSecurityException;
public interface ForumPostFactory {
Message createAnonymousPost(MessageId parent, Forum forum,
String contentType, long timestamp, byte[] body) throws IOException,
GeneralSecurityException;
Message createPseudonymousPost(MessageId parent, Forum forum,
Author author, PrivateKey privateKey, String contentType,
long timestamp, byte[] body) throws IOException,
GeneralSecurityException;
}

View File

@@ -222,8 +222,10 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
} finally {
lock.writeLock().unlock();
}
if (!duplicate && subscribed)
eventBus.broadcast(new MessageAddedEvent(m.getGroup(), null));
if (!duplicate && subscribed) {
GroupId g = m.getGroup().getId();
eventBus.broadcast(new MessageAddedEvent(g, null));
}
}
/**
@@ -1050,8 +1052,10 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
lock.writeLock().unlock();
}
if (visible) {
if (!duplicate)
eventBus.broadcast(new MessageAddedEvent(m.getGroup(), c));
if (!duplicate) {
GroupId g = m.getGroup().getId();
eventBus.broadcast(new MessageAddedEvent(g, c));
}
eventBus.broadcast(new MessageToAckEvent(c));
}
}

View File

@@ -0,0 +1,22 @@
package org.briarproject.forum;
import com.google.inject.Inject;
import org.briarproject.api.forum.Forum;
import org.briarproject.api.forum.ForumFactory;
import org.briarproject.api.sync.GroupFactory;
// Temporary facade during sync protocol refactoring
class ForumFactoryImpl implements ForumFactory {
private final GroupFactory groupFactory;
@Inject
ForumFactoryImpl(GroupFactory groupFactory) {
this.groupFactory = groupFactory;
}
public Forum createForum(String name) {
return new ForumImpl(groupFactory.createGroup(name));
}
}

View File

@@ -0,0 +1,37 @@
package org.briarproject.forum;
import org.briarproject.api.forum.Forum;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupId;
// Temporary facade during sync protocol refactoring
class ForumImpl implements Forum {
private final Group group;
ForumImpl(Group group) {
this.group = group;
}
public GroupId getId() {
return group.getId();
}
public String getName() {
return group.getName();
}
Group getGroup() {
return group;
}
@Override
public int hashCode() {
return group.hashCode();
}
@Override
public boolean equals(Object o) {
return o instanceof ForumImpl && group.equals(((ForumImpl) o).group);
}
}

View File

@@ -6,6 +6,7 @@ import org.briarproject.api.contact.Contact;
import org.briarproject.api.contact.ContactId;
import org.briarproject.api.db.DatabaseComponent;
import org.briarproject.api.db.DbException;
import org.briarproject.api.forum.Forum;
import org.briarproject.api.forum.ForumManager;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupId;
@@ -13,8 +14,12 @@ import org.briarproject.api.sync.Message;
import org.briarproject.api.sync.MessageHeader;
import org.briarproject.api.sync.MessageId;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
// Temporary facade during sync protocol refactoring
class ForumManagerImpl implements ForumManager {
private final DatabaseComponent db;
@@ -25,8 +30,8 @@ class ForumManagerImpl implements ForumManager {
}
@Override
public boolean addGroup(Group g) throws DbException {
return db.addGroup(g);
public boolean addForum(Forum f) throws DbException {
return db.addGroup(((ForumImpl) f).getGroup());
}
@Override
@@ -35,18 +40,24 @@ class ForumManagerImpl implements ForumManager {
}
@Override
public Collection<Group> getAvailableGroups() throws DbException {
return db.getAvailableGroups();
public Collection<Forum> getAvailableForums() throws DbException {
Collection<Group> groups = db.getAvailableGroups();
List<Forum> forums = new ArrayList<Forum>(groups.size());
for (Group g : groups) forums.add(new ForumImpl(g));
return Collections.unmodifiableList(forums);
}
@Override
public Group getGroup(GroupId g) throws DbException {
return db.getGroup(g);
public Forum getForum(GroupId g) throws DbException {
return new ForumImpl(db.getGroup(g));
}
@Override
public Collection<Group> getGroups() throws DbException {
return db.getGroups();
public Collection<Forum> getForums() throws DbException {
Collection<Group> groups = db.getGroups();
List<Forum> forums = new ArrayList<Forum>(groups.size());
for (Group g : groups) forums.add(new ForumImpl(g));
return Collections.unmodifiableList(forums);
}
@Override
@@ -71,8 +82,8 @@ class ForumManagerImpl implements ForumManager {
}
@Override
public void removeGroup(Group g) throws DbException {
db.removeGroup(g);
public void removeForum(Forum f) throws DbException {
db.removeGroup(((ForumImpl) f).getGroup());
}
@Override

View File

@@ -2,12 +2,16 @@ package org.briarproject.forum;
import com.google.inject.AbstractModule;
import org.briarproject.api.forum.ForumFactory;
import org.briarproject.api.forum.ForumManager;
import org.briarproject.api.forum.ForumPostFactory;
public class ForumModule extends AbstractModule {
@Override
protected void configure() {
bind(ForumFactory.class).to(ForumFactoryImpl.class);
bind(ForumManager.class).to(ForumManagerImpl.class);
bind(ForumPostFactory.class).to(ForumPostFactoryImpl.class);
}
}

View File

@@ -0,0 +1,43 @@
package org.briarproject.forum;
import com.google.inject.Inject;
import org.briarproject.api.crypto.PrivateKey;
import org.briarproject.api.forum.Forum;
import org.briarproject.api.forum.ForumPostFactory;
import org.briarproject.api.identity.Author;
import org.briarproject.api.sync.Message;
import org.briarproject.api.sync.MessageFactory;
import org.briarproject.api.sync.MessageId;
import java.io.IOException;
import java.security.GeneralSecurityException;
// Temporary facade during sync protocol refactoring
class ForumPostFactoryImpl implements ForumPostFactory {
private final MessageFactory messageFactory;
@Inject
ForumPostFactoryImpl(MessageFactory messageFactory) {
this.messageFactory = messageFactory;
}
@Override
public Message createAnonymousPost(MessageId parent, Forum forum,
String contentType, long timestamp, byte[] body)
throws IOException, GeneralSecurityException {
return messageFactory.createAnonymousMessage(parent,
((ForumImpl) forum).getGroup(), contentType, timestamp, body);
}
@Override
public Message createPseudonymousPost(MessageId parent, Forum forum,
Author author, PrivateKey privateKey, String contentType,
long timestamp, byte[] body)
throws IOException, GeneralSecurityException {
return messageFactory.createPseudonymousMessage(parent,
((ForumImpl) forum).getGroup(), author, privateKey, contentType,
timestamp, body);
}
}