From 1d25b5a92e92c5bfd41d81941a78952deca388bc Mon Sep 17 00:00:00 2001
From: akwizgran <akwizgran@users.sourceforge.net>
Date: Tue, 13 Sep 2011 14:04:23 +0100
Subject: [PATCH] Use null instead of MessageId.NONE and AuthorId.NONE, as for
 other optional fields.

---
 api/net/sf/briar/api/protocol/AuthorId.java   |  3 ---
 api/net/sf/briar/api/protocol/MessageId.java  |  4 ---
 components/net/sf/briar/db/Database.java      |  3 ++-
 .../sf/briar/db/DatabaseComponentImpl.java    |  2 +-
 components/net/sf/briar/db/JdbcDatabase.java  | 11 +++++---
 .../sf/briar/protocol/MessageEncoderImpl.java |  5 ++--
 .../net/sf/briar/protocol/MessageReader.java  | 26 ++++++++++++-------
 test/net/sf/briar/FileReadWriteTest.java      |  8 +++---
 .../briar/db/DatabaseComponentImplTest.java   |  3 +--
 .../sf/briar/db/DatabaseComponentTest.java    | 12 ++++-----
 test/net/sf/briar/db/H2DatabaseTest.java      | 16 ++++++------
 .../briar/protocol/ProtocolReadWriteTest.java |  3 +--
 .../briar/protocol/writers/ConstantsTest.java |  2 +-
 13 files changed, 51 insertions(+), 47 deletions(-)

diff --git a/api/net/sf/briar/api/protocol/AuthorId.java b/api/net/sf/briar/api/protocol/AuthorId.java
index c34d32c054..b5136c222f 100644
--- a/api/net/sf/briar/api/protocol/AuthorId.java
+++ b/api/net/sf/briar/api/protocol/AuthorId.java
@@ -8,9 +8,6 @@ import net.sf.briar.api.serial.Writer;
 /** Type-safe wrapper for a byte array that uniquely identifies an author. */
 public class AuthorId extends UniqueId {
 
-	/** Used to indicate that a message is anonymous. */
-	public static final AuthorId NONE = new AuthorId(new byte[UniqueId.LENGTH]);
-
 	public AuthorId(byte[] id) {
 		super(id);
 	}
diff --git a/api/net/sf/briar/api/protocol/MessageId.java b/api/net/sf/briar/api/protocol/MessageId.java
index e70a44f762..e559be69de 100644
--- a/api/net/sf/briar/api/protocol/MessageId.java
+++ b/api/net/sf/briar/api/protocol/MessageId.java
@@ -8,10 +8,6 @@ import net.sf.briar.api.serial.Writer;
 /** Type-safe wrapper for a byte array that uniquely identifies a message. */
 public class MessageId extends UniqueId {
 
-	/** Used to indicate that the first message in a thread has no parent. */
-	public static final MessageId NONE =
-		new MessageId(new byte[UniqueId.LENGTH]);
-
 	public MessageId(byte[] id) {
 		super(id);
 	}
diff --git a/components/net/sf/briar/db/Database.java b/components/net/sf/briar/db/Database.java
index c2f186e717..0bf6e058b0 100644
--- a/components/net/sf/briar/db/Database.java
+++ b/components/net/sf/briar/db/Database.java
@@ -241,7 +241,8 @@ interface Database<T> {
 	Collection<MessageId> getOldMessages(T txn, int size) throws DbException;
 
 	/**
-	 * Returns the parent of the given message.
+	 * Returns the parent of the given message, or null if the message has
+	 * no parent.
 	 * <p>
 	 * Locking: messages read.
 	 */
diff --git a/components/net/sf/briar/db/DatabaseComponentImpl.java b/components/net/sf/briar/db/DatabaseComponentImpl.java
index c7c10d577f..677864257c 100644
--- a/components/net/sf/briar/db/DatabaseComponentImpl.java
+++ b/components/net/sf/briar/db/DatabaseComponentImpl.java
@@ -213,7 +213,7 @@ DatabaseCleaner.Callback {
 		boolean changed = true;
 		while(changed) {
 			MessageId parent = db.getParent(txn, m);
-			if(parent.equals(MessageId.NONE)) break;
+			if(parent == null) break;
 			if(!db.containsMessage(txn, parent)) break;
 			if(!db.getGroup(txn, m).equals(db.getGroup(txn, parent))) break;
 			Integer parentSendability = db.getSendability(txn, parent);
diff --git a/components/net/sf/briar/db/JdbcDatabase.java b/components/net/sf/briar/db/JdbcDatabase.java
index c242372f6e..d4891e7e70 100644
--- a/components/net/sf/briar/db/JdbcDatabase.java
+++ b/components/net/sf/briar/db/JdbcDatabase.java
@@ -8,6 +8,7 @@ import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
+import java.sql.Types;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -51,9 +52,9 @@ abstract class JdbcDatabase implements Database<Connection> {
 	private static final String CREATE_MESSAGES =
 		"CREATE TABLE messages"
 		+ " (messageId HASH NOT NULL,"
-		+ " parentId HASH NOT NULL,"
+		+ " parentId HASH,"
 		+ " groupId HASH NOT NULL,"
-		+ " authorId HASH NOT NULL,"
+		+ " authorId HASH,"
 		+ " timestamp BIGINT NOT NULL,"
 		+ " size INT NOT NULL,"
 		+ " raw BLOB NOT NULL,"
@@ -536,9 +537,11 @@ abstract class JdbcDatabase implements Database<Connection> {
 				+ " VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
 			ps = txn.prepareStatement(sql);
 			ps.setBytes(1, m.getId().getBytes());
-			ps.setBytes(2, m.getParent().getBytes());
+			if(m.getParent() == null) ps.setNull(2, Types.BINARY);
+			else ps.setBytes(2, m.getParent().getBytes());
 			ps.setBytes(3, m.getGroup().getBytes());
-			ps.setBytes(4, m.getAuthor().getBytes());
+			if(m.getAuthor() == null) ps.setNull(4, Types.BINARY);
+			else ps.setBytes(4, m.getAuthor().getBytes());
 			ps.setLong(5, m.getTimestamp());
 			ps.setInt(6, m.getSize());
 			byte[] raw = m.getBytes();
diff --git a/components/net/sf/briar/protocol/MessageEncoderImpl.java b/components/net/sf/briar/protocol/MessageEncoderImpl.java
index af8f7b902b..0a5b92a0a7 100644
--- a/components/net/sf/briar/protocol/MessageEncoderImpl.java
+++ b/components/net/sf/briar/protocol/MessageEncoderImpl.java
@@ -66,7 +66,8 @@ class MessageEncoderImpl implements MessageEncoder {
 		Writer w = writerFactory.createWriter(out);
 		// Write the message
 		w.writeUserDefinedTag(Types.MESSAGE);
-		parent.writeTo(w);
+		if(parent == null) w.writeNull();
+		else parent.writeTo(w);
 		group.writeTo(w);
 		if(author == null) w.writeNull();
 		else author.writeTo(w);
@@ -99,7 +100,7 @@ class MessageEncoderImpl implements MessageEncoder {
 		messageDigest.reset();
 		messageDigest.update(raw);
 		MessageId id = new MessageId(messageDigest.digest());
-		AuthorId authorId = author == null ? AuthorId.NONE : author.getId();
+		AuthorId authorId = author == null ? null : author.getId();
 		return new MessageImpl(id, parent, group.getId(), authorId, timestamp,
 				raw);
 	}
diff --git a/components/net/sf/briar/protocol/MessageReader.java b/components/net/sf/briar/protocol/MessageReader.java
index 669fa38051..688056e019 100644
--- a/components/net/sf/briar/protocol/MessageReader.java
+++ b/components/net/sf/briar/protocol/MessageReader.java
@@ -48,20 +48,28 @@ class MessageReader implements ObjectReader<Message> {
 		r.addConsumer(counting);
 		// Read the initial tag
 		r.readUserDefinedId(Types.MESSAGE);
-		// Read the parent's message ID
-		r.addObjectReader(Types.MESSAGE_ID, messageIdReader);
-		MessageId parent = r.readUserDefined(Types.MESSAGE_ID, MessageId.class);
-		r.removeObjectReader(Types.MESSAGE_ID);
+		// Read the parent's message ID, if there is one
+		MessageId parent = null;
+		if(r.hasNull()) {
+			r.readNull();
+		} else {
+			r.addObjectReader(Types.MESSAGE_ID, messageIdReader);
+			parent = r.readUserDefined(Types.MESSAGE_ID, MessageId.class);
+			r.removeObjectReader(Types.MESSAGE_ID);
+		}
 		// Read the group
 		r.addObjectReader(Types.GROUP, groupReader);
 		Group group = r.readUserDefined(Types.GROUP, Group.class);
 		r.removeObjectReader(Types.GROUP);
 		// Read the author, if there is one
-		r.addObjectReader(Types.AUTHOR, authorReader);
 		Author author = null;
-		if(r.hasNull()) r.readNull();
-		else author = r.readUserDefined(Types.AUTHOR, Author.class);
-		r.removeObjectReader(Types.AUTHOR);
+		if(r.hasNull()) {
+			r.readNull();
+		} else {
+			r.addObjectReader(Types.AUTHOR, authorReader);
+			author = r.readUserDefined(Types.AUTHOR, Author.class);
+			r.removeObjectReader(Types.AUTHOR);
+		}
 		// Read the timestamp
 		long timestamp = r.readInt64();
 		if(timestamp < 0L) throw new FormatException();
@@ -109,7 +117,7 @@ class MessageReader implements ObjectReader<Message> {
 		messageDigest.reset();
 		messageDigest.update(raw);
 		MessageId id = new MessageId(messageDigest.digest());
-		AuthorId authorId = author == null ? AuthorId.NONE : author.getId();
+		AuthorId authorId = author == null ? null : author.getId();
 		return new MessageImpl(id, parent, group.getId(), authorId, timestamp,
 				raw);
 	}
diff --git a/test/net/sf/briar/FileReadWriteTest.java b/test/net/sf/briar/FileReadWriteTest.java
index de0dfd619b..c50f1d4535 100644
--- a/test/net/sf/briar/FileReadWriteTest.java
+++ b/test/net/sf/briar/FileReadWriteTest.java
@@ -109,13 +109,13 @@ public class FileReadWriteTest extends TestCase {
 				authorKeyPair.getPublic().getEncoded());
 		// Create two messages to each group: one anonymous, one pseudonymous
 		MessageEncoder messageEncoder = i.getInstance(MessageEncoder.class);
-		message = messageEncoder.encodeMessage(MessageId.NONE, group,
+		message = messageEncoder.encodeMessage(null, group,
 				messageBody.getBytes("UTF-8"));
-		message1 = messageEncoder.encodeMessage(MessageId.NONE, group1,
+		message1 = messageEncoder.encodeMessage(null, group1,
 				groupKeyPair.getPrivate(), messageBody.getBytes("UTF-8"));
-		message2 = messageEncoder.encodeMessage(MessageId.NONE, group, author,
+		message2 = messageEncoder.encodeMessage(null, group, author,
 				authorKeyPair.getPrivate(), messageBody.getBytes("UTF-8"));
-		message3 = messageEncoder.encodeMessage(MessageId.NONE, group1,
+		message3 = messageEncoder.encodeMessage(null, group1,
 				groupKeyPair.getPrivate(), author, authorKeyPair.getPrivate(),
 				messageBody.getBytes("UTF-8"));
 		transports = Collections.singletonMap("foo",
diff --git a/test/net/sf/briar/db/DatabaseComponentImplTest.java b/test/net/sf/briar/db/DatabaseComponentImplTest.java
index 98e39c1bc6..8e114c46f3 100644
--- a/test/net/sf/briar/db/DatabaseComponentImplTest.java
+++ b/test/net/sf/briar/db/DatabaseComponentImplTest.java
@@ -6,7 +6,6 @@ import static net.sf.briar.api.db.DatabaseComponent.MIN_FREE_SPACE;
 import java.util.Collections;
 
 import net.sf.briar.api.db.DbException;
-import net.sf.briar.api.protocol.MessageId;
 import net.sf.briar.db.DatabaseCleaner.Callback;
 
 import org.jmock.Expectations;
@@ -109,7 +108,7 @@ public abstract class DatabaseComponentImplTest extends DatabaseComponentTest {
 			oneOf(database).getSendability(txn, messageId);
 			will(returnValue(1));
 			oneOf(database).getParent(txn, messageId);
-			will(returnValue(MessageId.NONE));
+			will(returnValue(null));
 			oneOf(database).removeMessage(txn, messageId);
 			oneOf(database).commitTransaction(txn);
 			oneOf(database).getFreeSpace();
diff --git a/test/net/sf/briar/db/DatabaseComponentTest.java b/test/net/sf/briar/db/DatabaseComponentTest.java
index 04297083df..0fb571e168 100644
--- a/test/net/sf/briar/db/DatabaseComponentTest.java
+++ b/test/net/sf/briar/db/DatabaseComponentTest.java
@@ -68,8 +68,8 @@ public abstract class DatabaseComponentTest extends TestCase {
 		timestamp = System.currentTimeMillis();
 		size = 1234;
 		raw = new byte[size];
-		message = new TestMessage(messageId, MessageId.NONE, groupId, authorId,
-				timestamp, raw);
+		message =
+			new TestMessage(messageId, null, groupId, authorId, timestamp, raw);
 		group = new TestGroup(groupId, "The really exciting group", null);
 		transports = Collections.singletonMap("foo",
 				Collections.singletonMap("bar", "baz"));
@@ -198,7 +198,7 @@ public abstract class DatabaseComponentTest extends TestCase {
 			oneOf(database).setSendability(txn, messageId, 1);
 			// Backward inclusion stops when the message has no parent
 			oneOf(database).getParent(txn, messageId);
-			will(returnValue(MessageId.NONE));
+			will(returnValue(null));
 			oneOf(database).commitTransaction(txn);
 		}});
 		DatabaseComponent db = createDatabaseComponent(database, cleaner);
@@ -349,7 +349,7 @@ public abstract class DatabaseComponentTest extends TestCase {
 			will(returnValue(0));
 			oneOf(database).setSendability(txn, parentId, 1);
 			oneOf(database).getParent(txn, parentId);
-			will(returnValue(MessageId.NONE));
+			will(returnValue(null));
 			oneOf(database).commitTransaction(txn);
 		}});
 		DatabaseComponent db = createDatabaseComponent(database, cleaner);
@@ -462,7 +462,7 @@ public abstract class DatabaseComponentTest extends TestCase {
 			oneOf(database).setSendability(txn, messageId, 3);
 			// The sendability of the message's ancestors should be updated
 			oneOf(database).getParent(txn, messageId);
-			will(returnValue(MessageId.NONE));
+			will(returnValue(null));
 			oneOf(database).commitTransaction(txn);
 		}});
 		DatabaseComponent db = createDatabaseComponent(database, cleaner);
@@ -988,7 +988,7 @@ public abstract class DatabaseComponentTest extends TestCase {
 			will(returnValue(1));
 			oneOf(database).setSendability(txn, messageId, 2);
 			oneOf(database).getParent(txn, messageId);
-			will(returnValue(MessageId.NONE));
+			will(returnValue(null));
 			// The batch needs to be acknowledged
 			oneOf(batch).getId();
 			will(returnValue(batchId));
diff --git a/test/net/sf/briar/db/H2DatabaseTest.java b/test/net/sf/briar/db/H2DatabaseTest.java
index ba5ecd7f3b..0698f8e137 100644
--- a/test/net/sf/briar/db/H2DatabaseTest.java
+++ b/test/net/sf/briar/db/H2DatabaseTest.java
@@ -84,8 +84,8 @@ public class H2DatabaseTest extends TestCase {
 		size = 1234;
 		raw = new byte[size];
 		random.nextBytes(raw);
-		message = new TestMessage(messageId, MessageId.NONE, groupId, authorId,
-				timestamp, raw);
+		message =
+			new TestMessage(messageId, null, groupId, authorId, timestamp, raw);
 		group = groupFactory.createGroup(groupId, "Group name", null);
 		transports = Collections.singletonMap("foo",
 				Collections.singletonMap("bar", "baz"));
@@ -675,8 +675,8 @@ public class H2DatabaseTest extends TestCase {
 	public void testGetMessagesByAuthor() throws DbException {
 		AuthorId authorId1 = new AuthorId(TestUtils.getRandomId());
 		MessageId messageId1 = new MessageId(TestUtils.getRandomId());
-		Message message1 = new TestMessage(messageId1, MessageId.NONE, groupId,
-				authorId1, timestamp, raw);
+		Message message1 = new TestMessage(messageId1, null, groupId, authorId1,
+				timestamp, raw);
 		Database<Connection> db = open(false);
 		Connection txn = db.startTransaction();
 
@@ -744,8 +744,8 @@ public class H2DatabaseTest extends TestCase {
 	@Test
 	public void testGetOldMessages() throws DbException {
 		MessageId messageId1 = new MessageId(TestUtils.getRandomId());
-		Message message1 = new TestMessage(messageId1, MessageId.NONE, groupId,
-				authorId, timestamp + 1000, raw);
+		Message message1 = new TestMessage(messageId1, null, groupId, authorId,
+				timestamp + 1000, raw);
 		Database<Connection> db = open(false);
 		Connection txn = db.startTransaction();
 
@@ -775,8 +775,8 @@ public class H2DatabaseTest extends TestCase {
 	public void testGetFreeSpace() throws Exception {
 		byte[] largeBody = new byte[ONE_MEGABYTE];
 		for(int i = 0; i < largeBody.length; i++) largeBody[i] = (byte) i;
-		Message message1 = new TestMessage(messageId, MessageId.NONE, groupId,
-				authorId, timestamp, largeBody);
+		Message message1 = new TestMessage(messageId, null, groupId, authorId,
+				timestamp, largeBody);
 		Database<Connection> db = open(false);
 
 		// Sanity check: there should be enough space on disk for this test
diff --git a/test/net/sf/briar/protocol/ProtocolReadWriteTest.java b/test/net/sf/briar/protocol/ProtocolReadWriteTest.java
index 393a86816f..ad5a7981c0 100644
--- a/test/net/sf/briar/protocol/ProtocolReadWriteTest.java
+++ b/test/net/sf/briar/protocol/ProtocolReadWriteTest.java
@@ -15,7 +15,6 @@ import net.sf.briar.api.protocol.Group;
 import net.sf.briar.api.protocol.GroupFactory;
 import net.sf.briar.api.protocol.Message;
 import net.sf.briar.api.protocol.MessageEncoder;
-import net.sf.briar.api.protocol.MessageId;
 import net.sf.briar.api.protocol.Offer;
 import net.sf.briar.api.protocol.ProtocolReader;
 import net.sf.briar.api.protocol.ProtocolReaderFactory;
@@ -61,7 +60,7 @@ public class ProtocolReadWriteTest extends TestCase {
 		GroupFactory groupFactory = i.getInstance(GroupFactory.class);
 		group = groupFactory.createGroup("Unrestricted group", null);
 		MessageEncoder messageEncoder = i.getInstance(MessageEncoder.class);
-		message = messageEncoder.encodeMessage(MessageId.NONE, group,
+		message = messageEncoder.encodeMessage(null, group,
 				messageBody.getBytes("UTF-8"));
 		bitSet = new BitSet();
 		bitSet.set(3);
diff --git a/test/net/sf/briar/protocol/writers/ConstantsTest.java b/test/net/sf/briar/protocol/writers/ConstantsTest.java
index 45b08284dd..6d37814337 100644
--- a/test/net/sf/briar/protocol/writers/ConstantsTest.java
+++ b/test/net/sf/briar/protocol/writers/ConstantsTest.java
@@ -87,7 +87,7 @@ public class ConstantsTest extends TestCase {
 		PrivateKey groupPrivate = crypto.generateKeyPair().getPrivate();
 		PrivateKey authorPrivate = crypto.generateKeyPair().getPrivate();
 		byte[] body = new byte[Message.MAX_BODY_LENGTH];
-		Message message = messageEncoder.encodeMessage(MessageId.NONE, group,
+		Message message = messageEncoder.encodeMessage(null, group,
 				groupPrivate, author, authorPrivate, body);
 		// Add the message to a batch
 		ByteArrayOutputStream out = new ByteArrayOutputStream(
-- 
GitLab