diff --git a/src/androidTest/java/im/conversations/android/xmpp/TransformationTest.java b/src/androidTest/java/im/conversations/android/xmpp/TransformationTest.java index 76ff19b16..32a7c1671 100644 --- a/src/androidTest/java/im/conversations/android/xmpp/TransformationTest.java +++ b/src/androidTest/java/im/conversations/android/xmpp/TransformationTest.java @@ -4,6 +4,7 @@ import android.content.Context; import androidx.room.Room; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.common.collect.Iterables; import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.IDs; import im.conversations.android.database.ConversationsDatabase; @@ -16,6 +17,7 @@ import im.conversations.android.xmpp.model.reactions.Reactions; import im.conversations.android.xmpp.model.stanza.Message; import java.time.Instant; import java.util.concurrent.ExecutionException; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -26,13 +28,15 @@ public class TransformationTest { private static final Jid ACCOUNT = Jid.of("user@example.com"); private static final Jid REMOTE = Jid.of("juliet@example.com"); + private static final String GREETING = "Hi Juliet. How are you?"; + + private ConversationsDatabase database; private Transformer transformer; @Before public void setupTransformer() throws ExecutionException, InterruptedException { Context context = ApplicationProvider.getApplicationContext(); - final var database = - Room.inMemoryDatabaseBuilder(context, ConversationsDatabase.class).build(); + this.database = Room.inMemoryDatabaseBuilder(context, ConversationsDatabase.class).build(); final var account = new AccountEntity(); account.address = ACCOUNT; account.enabled = true; @@ -60,8 +64,17 @@ public class TransformationTest { originalMessage.setTo(REMOTE); originalMessage.setFrom(ACCOUNT.withResource("junit")); final var body = originalMessage.addExtension(new Body()); - body.setContent("Hi Juliet. How are you?"); + body.setContent(GREETING); this.transformer.transform( Transformation.of(originalMessage, Instant.now(), REMOTE, "stanza-a", null)); + + final var messages = database.messageDao().getMessages(1L); + Assert.assertEquals(1, messages.size()); + final var message = Iterables.getOnlyElement(messages); + final var onlyContent = Iterables.getOnlyElement(message.contents); + Assert.assertEquals(GREETING, onlyContent.body); + final var onlyReaction = Iterables.getOnlyElement(message.reactions); + Assert.assertEquals("Y", onlyReaction.reaction); + Assert.assertEquals(REMOTE, onlyReaction.reactionBy); } } diff --git a/src/main/java/im/conversations/android/database/dao/MessageDao.java b/src/main/java/im/conversations/android/database/dao/MessageDao.java index 8020f03fd..a769c043a 100644 --- a/src/main/java/im/conversations/android/database/dao/MessageDao.java +++ b/src/main/java/im/conversations/android/database/dao/MessageDao.java @@ -5,6 +5,7 @@ import androidx.room.Dao; import androidx.room.Insert; import androidx.room.Query; import androidx.room.Transaction; +import androidx.room.Update; import com.google.common.base.Preconditions; import com.google.common.collect.Collections2; import com.google.common.collect.Lists; @@ -19,6 +20,7 @@ import im.conversations.android.database.model.ChatIdentifier; import im.conversations.android.database.model.MessageContent; import im.conversations.android.database.model.MessageIdentifier; import im.conversations.android.database.model.MessageState; +import im.conversations.android.database.model.MessageWithContentReactions; import im.conversations.android.database.model.Modification; import im.conversations.android.transformer.Transformation; import im.conversations.android.xmpp.model.reactions.Reactions; @@ -80,9 +82,23 @@ public abstract class MessageDao { "Found stub for stanzaId '{}' and messageId '{}'", transformation.stanzaId, transformation.messageId); - // TODO create version - // TODO fill up information - return messageIdentifier; + final long messageVersionId = + insert( + MessageVersionEntity.of( + messageIdentifier.id, + Modification.ORIGINAl, + transformation)); + final MessageEntity updatedEntity = + MessageEntity.of(chatIdentifier.id, transformation); + updatedEntity.id = messageIdentifier.id; + updatedEntity.latestVersion = messageVersionId; + update(updatedEntity); + return new MessageIdentifier( + updatedEntity.id, + transformation.stanzaId, + transformation.messageId, + transformation.fromBare(), + messageVersionId); } else { throw new IllegalStateException( String.format( @@ -201,6 +217,9 @@ public abstract class MessageDao { @Insert protected abstract long insert(MessageEntity messageEntity); + @Update + protected abstract void update(final MessageEntity messageEntity); + @Insert protected abstract long insert(MessageVersionEntity messageVersionEntity); @@ -293,4 +312,13 @@ public abstract class MessageDao { reactions.getReactions(), r -> MessageReactionEntity.of(messageIdentifier.id, r, transformation))); } + + @Transaction + @Query( + "SELECT message.id as" + + " id,sentAt,outgoing,toBare,toResource,fromBare,fromResource,modification,latestVersion" + + " as version FROM message JOIN message_version ON" + + " message.latestVersion=message_version.id WHERE message.chatId=:chatId AND" + + " latestVersion IS NOT NULL ORDER BY message.receivedAt") + public abstract List getMessages(long chatId); } diff --git a/src/main/java/im/conversations/android/database/model/MessageReaction.java b/src/main/java/im/conversations/android/database/model/MessageReaction.java new file mode 100644 index 000000000..c7b677831 --- /dev/null +++ b/src/main/java/im/conversations/android/database/model/MessageReaction.java @@ -0,0 +1,20 @@ +package im.conversations.android.database.model; + +import eu.siacs.conversations.xmpp.Jid; + +public class MessageReaction { + + public final Jid reactionBy; + public final String reactionByResource; + public final String occupantId; + + public final String reaction; + + public MessageReaction( + Jid reactionBy, String reactionByResource, String occupantId, String reaction) { + this.reactionBy = reactionBy; + this.reactionByResource = reactionByResource; + this.occupantId = occupantId; + this.reaction = reaction; + } +} diff --git a/src/main/java/im/conversations/android/database/model/MessageWithContentReactions.java b/src/main/java/im/conversations/android/database/model/MessageWithContentReactions.java new file mode 100644 index 000000000..8ac2f832e --- /dev/null +++ b/src/main/java/im/conversations/android/database/model/MessageWithContentReactions.java @@ -0,0 +1,37 @@ +package im.conversations.android.database.model; + +import androidx.room.Relation; +import eu.siacs.conversations.xmpp.Jid; +import im.conversations.android.database.entity.MessageContentEntity; +import im.conversations.android.database.entity.MessageReactionEntity; +import java.time.Instant; +import java.util.List; + +public class MessageWithContentReactions { + + public long id; + + public Instant sentAt; + + public boolean outgoing; + + public Jid toBare; + public String toResource; + public Jid fromBare; + public String fromResource; + + public Modification modification; + public long version; + + @Relation( + entity = MessageContentEntity.class, + parentColumn = "version", + entityColumn = "messageVersionId") + public List contents; + + @Relation( + entity = MessageReactionEntity.class, + parentColumn = "id", + entityColumn = "messageEntityId") + public List reactions; +}