You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by rc...@apache.org on 2020/10/26 02:55:05 UTC

[james-project] 02/11: JAMES-3430 Split PropertyBuilder in two

This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 123103b5c5bf81ca18d01f151cb35922d669b789
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Tue Oct 20 16:04:58 2020 +0700

    JAMES-3430 Split PropertyBuilder in two
    
        Stop building several time property builder
        Stop mixing read & writes on Property Builder
        Stop passing mutable data around
    
    This can be achieved by introducing a new, immutable Properties relying
    on PropertyBuilder to be built.
---
 .../mailbox/backup/MailboxMessageFixture.java      |   6 +-
 .../cassandra/mail/CassandraMessageDAO.java        |  10 +-
 .../cassandra/mail/MessageRepresentation.java      |  14 +-
 .../cassandra/mail/CassandraMessageDAOTest.java    |   6 +-
 ...asticSearchListeningMessageSearchIndexTest.java |   2 +-
 .../json/MessageToElasticSearchJsonTest.java       |  26 +--
 .../model/openjpa/AbstractJPAMailboxMessage.java   |  24 ++-
 .../james/mailbox/jpa/mail/MessageUtilsTest.java   |   2 +-
 .../mailbox/maildir/mail/model/MaildirMessage.java |  12 +-
 .../spamassassin/SpamAssassinListenerTest.java     |   2 +-
 .../james/mailbox/store/LazyMimeDescriptor.java    |  11 +-
 .../apache/james/mailbox/store/MessageFactory.java |   2 +-
 .../store/mail/model/DelegatingMailboxMessage.java |   3 +-
 .../james/mailbox/store/mail/model/Message.java    |   5 +-
 .../impl/{PropertyBuilder.java => Properties.java} | 230 ++-------------------
 .../store/mail/model/impl/PropertyBuilder.java     | 182 +---------------
 .../mail/model/impl/SimpleMailboxMessage.java      |  32 +--
 .../store/mail/model/impl/SimpleMessage.java       |  15 +-
 .../apache/james/mailbox/store/MessageBuilder.java |   2 +-
 .../mailbox/store/MessageIdManagerTestSystem.java  |   2 +-
 .../StoreMailboxMessageResultIteratorTest.java     |   2 +-
 .../store/mail/model/ListMessageAssertTest.java    |   4 +-
 .../model/ListMessagePropertiesAssertTest.java     |   2 +-
 .../store/mail/model/MailboxMessageAssertTest.java |  12 +-
 .../store/mail/model/MessageIdMapperTest.java      |   2 +-
 .../store/mail/model/MessageMapperTest.java        |  15 +-
 .../mailbox/store/mail/model/MessageMoveTest.java  |   2 +-
 .../model/MessageWithAttachmentMapperTest.java     |   4 +-
 .../store/mail/model/MetadataMapAssertTest.java    |   2 +-
 .../mail/model/impl/SimpleMailboxMessageTest.java  |  24 +--
 .../mail/utils/ApplicableFlagCalculatorTest.java   |   2 +-
 .../ListeningMessageSearchIndexContract.java       |   2 +-
 .../james/webadmin/routes/MailboxesRoutesTest.java |   4 +-
 .../webadmin/routes/UserMailboxesRoutesTest.java   |   2 +-
 34 files changed, 156 insertions(+), 511 deletions(-)

diff --git a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MailboxMessageFixture.java b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MailboxMessageFixture.java
index 50f8a76..e85e0cc 100644
--- a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MailboxMessageFixture.java
+++ b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MailboxMessageFixture.java
@@ -130,7 +130,7 @@ public interface MailboxMessageFixture {
         .internalDate(new Date(DATE_1.toEpochSecond()))
         .bodyStartOctet(0)
         .flags(flags1)
-        .propertyBuilder(new PropertyBuilder())
+        .properties(new PropertyBuilder())
         .mailboxId(MAILBOX_ID_1)
         .build();
 
@@ -142,7 +142,7 @@ public interface MailboxMessageFixture {
         .internalDate(new Date(DATE_1.toEpochSecond()))
         .bodyStartOctet(0)
         .flags(flags1)
-        .propertyBuilder(new PropertyBuilder())
+        .properties(new PropertyBuilder())
         .mailboxId(MAILBOX_ID_11)
         .build();
 
@@ -154,7 +154,7 @@ public interface MailboxMessageFixture {
         .internalDate(new Date(DATE_2.toEpochSecond()))
         .bodyStartOctet(0)
         .flags(new Flags())
-        .propertyBuilder(new PropertyBuilder())
+        .properties(new PropertyBuilder())
         .mailboxId(MAILBOX_ID_1)
         .build();
 }
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAO.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAO.java
index a321551..632af57 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAO.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAO.java
@@ -192,7 +192,9 @@ public class CassandraMessageDAO {
     }
 
     private List<UDTValue> buildPropertiesUdt(MailboxMessage message) {
-        return message.getProperties().stream()
+        return message.getProperties()
+            .toProperties()
+            .stream()
             .map(property -> typesProvider.getDefinedUserType(PROPERTIES)
                 .newValue()
                 .setString(Properties.NAMESPACE, property.getNamespace())
@@ -236,19 +238,19 @@ public class CassandraMessageDAO {
                 row.getLong(FULL_CONTENT_OCTETS),
                 row.getInt(BODY_START_OCTET),
                 new SharedByteArrayInputStream(content),
-                getPropertyBuilder(row),
+                getProperties(row),
                 getAttachments(row).collect(Guavate.toImmutableList()),
                 headerId,
                 bodyId));
     }
 
-    private PropertyBuilder getPropertyBuilder(Row row) {
+    private org.apache.james.mailbox.store.mail.model.impl.Properties getProperties(Row row) {
         PropertyBuilder property = new PropertyBuilder(
             row.getList(PROPERTIES, UDTValue.class).stream()
                 .map(this::toProperty)
                 .collect(Collectors.toList()));
         property.setTextualLineCount(row.getLong(TEXTUAL_LINE_COUNT));
-        return property;
+        return property.build();
     }
 
     private Property toProperty(UDTValue udtValue) {
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MessageRepresentation.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MessageRepresentation.java
index 7ac496b..19fd945 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MessageRepresentation.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MessageRepresentation.java
@@ -28,7 +28,7 @@ import org.apache.james.blob.api.BlobId;
 import org.apache.james.mailbox.model.ComposedMessageIdWithMetaData;
 import org.apache.james.mailbox.model.MessageAttachmentMetadata;
 import org.apache.james.mailbox.model.MessageId;
-import org.apache.james.mailbox.store.mail.model.impl.PropertyBuilder;
+import org.apache.james.mailbox.store.mail.model.impl.Properties;
 import org.apache.james.mailbox.store.mail.model.impl.SimpleMailboxMessage;
 
 public class MessageRepresentation {
@@ -37,19 +37,19 @@ public class MessageRepresentation {
     private final Long size;
     private final Integer bodySize;
     private final SharedByteArrayInputStream content;
-    private final PropertyBuilder propertyBuilder;
+    private final Properties properties;
     private final List<MessageAttachmentRepresentation> attachments;
     private final BlobId headerId;
     private final BlobId bodyId;
 
     public MessageRepresentation(MessageId messageId, Date internalDate, Long size, Integer bodySize, SharedByteArrayInputStream content,
-                                 PropertyBuilder propertyBuilder, List<MessageAttachmentRepresentation> attachments, BlobId headerId, BlobId bodyId) {
+                                 Properties properties, List<MessageAttachmentRepresentation> attachments, BlobId headerId, BlobId bodyId) {
         this.messageId = messageId;
         this.internalDate = internalDate;
         this.size = size;
         this.bodySize = bodySize;
         this.content = content;
-        this.propertyBuilder = propertyBuilder;
+        this.properties = properties;
         this.attachments = attachments;
         this.headerId = headerId;
         this.bodyId = bodyId;
@@ -66,7 +66,7 @@ public class MessageRepresentation {
             .size(size)
             .content(content)
             .flags(metadata.getFlags())
-            .propertyBuilder(propertyBuilder)
+            .properties(properties)
             .addAttachments(attachments)
             .build();
     }
@@ -79,8 +79,8 @@ public class MessageRepresentation {
         return content;
     }
 
-    public PropertyBuilder getPropertyBuilder() {
-        return propertyBuilder;
+    public Properties getProperties() {
+        return properties;
     }
 
     public List<MessageAttachmentRepresentation> getAttachments() {
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAOTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAOTest.java
index b255ac7..bb52781 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAOTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAOTest.java
@@ -112,7 +112,7 @@ class CassandraMessageDAOTest {
         MessageRepresentation attachmentRepresentation =
             toMessage(testee.retrieveMessage(messageIdWithMetadata, MessageMapper.FetchType.Metadata));
 
-        assertThat(attachmentRepresentation.getPropertyBuilder().getTextualLineCount())
+        assertThat(attachmentRepresentation.getProperties().getTextualLineCount())
             .isEqualTo(0L);
     }
 
@@ -128,7 +128,7 @@ class CassandraMessageDAOTest {
         MessageRepresentation attachmentRepresentation =
             toMessage(testee.retrieveMessage(messageIdWithMetadata, MessageMapper.FetchType.Metadata));
 
-        assertThat(attachmentRepresentation.getPropertyBuilder().getTextualLineCount()).isEqualTo(textualLineCount);
+        assertThat(attachmentRepresentation.getProperties().getTextualLineCount()).isEqualTo(textualLineCount);
     }
 
     @Test
@@ -183,7 +183,7 @@ class CassandraMessageDAOTest {
             .size(content.length())
             .content(new SharedByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8)))
             .flags(new Flags())
-            .propertyBuilder(propertyBuilder)
+            .properties(propertyBuilder.build())
             .addAttachments(attachments)
             .build();
     }
diff --git a/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndexTest.java b/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndexTest.java
index 3275897..1dc6d7e 100644
--- a/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndexTest.java
+++ b/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndexTest.java
@@ -109,7 +109,7 @@ class ElasticSearchListeningMessageSearchIndexTest {
         .internalDate(new Date(1433628000000L))
         .size(SIZE)
         .content(new SharedByteArrayInputStream("message".getBytes(StandardCharsets.UTF_8)))
-        .propertyBuilder(new PropertyBuilder())
+        .properties(new PropertyBuilder())
         .modseq(MOD_SEQ);
 
     static final SimpleMailboxMessage MESSAGE_1 = MESSAGE_BUILDER.messageId(MESSAGE_ID_1)
diff --git a/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/json/MessageToElasticSearchJsonTest.java b/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/json/MessageToElasticSearchJsonTest.java
index 7c7f5ba..93ec1ad 100644
--- a/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/json/MessageToElasticSearchJsonTest.java
+++ b/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/json/MessageToElasticSearchJsonTest.java
@@ -100,7 +100,7 @@ class MessageToElasticSearchJsonTest {
                 BODY_START_OCTET,
                 ClassLoaderUtils.getSystemResourceAsSharedStream("eml/spamMail.eml"),
                 new Flags(),
-                propertyBuilder,
+                propertyBuilder.build(),
                 MAILBOX_ID);
         spamMail.setUid(UID);
         spamMail.setModSeq(MOD_SEQ);
@@ -120,7 +120,7 @@ class MessageToElasticSearchJsonTest {
                 BODY_START_OCTET,
                 ClassLoaderUtils.getSystemResourceAsSharedStream("eml/invalidCharset.eml"),
                 new Flags(),
-                propertyBuilder,
+                propertyBuilder.build(),
                 MAILBOX_ID);
         spamMail.setUid(UID);
         spamMail.setModSeq(MOD_SEQ);
@@ -142,7 +142,7 @@ class MessageToElasticSearchJsonTest {
                 BODY_START_OCTET,
                 ClassLoaderUtils.getSystemResourceAsSharedStream("eml/htmlMail.eml"),
                 new FlagsBuilder().add(Flags.Flag.DELETED, Flags.Flag.SEEN).add("social", "pocket-money").build(),
-                propertyBuilder,
+                propertyBuilder.build(),
                 MAILBOX_ID);
         htmlMail.setModSeq(MOD_SEQ);
         htmlMail.setUid(UID);
@@ -162,7 +162,7 @@ class MessageToElasticSearchJsonTest {
                 BODY_START_OCTET,
                 ClassLoaderUtils.getSystemResourceAsSharedStream("eml/pgpSignedMail.eml"),
                 new FlagsBuilder().add(Flags.Flag.DELETED, Flags.Flag.SEEN).add("debian", "security").build(),
-                propertyBuilder,
+                propertyBuilder.build(),
                 MAILBOX_ID);
         pgpSignedMail.setModSeq(MOD_SEQ);
         pgpSignedMail.setUid(UID);
@@ -182,7 +182,7 @@ class MessageToElasticSearchJsonTest {
                 BODY_START_OCTET,
                 ClassLoaderUtils.getSystemResourceAsSharedStream("eml/mail.eml"),
                 new FlagsBuilder().add(Flags.Flag.DELETED, Flags.Flag.SEEN).add("debian", "security").build(),
-                propertyBuilder,
+                propertyBuilder.build(),
                 MAILBOX_ID);
         mail.setModSeq(MOD_SEQ);
         mail.setUid(UID);
@@ -203,7 +203,7 @@ class MessageToElasticSearchJsonTest {
                 BODY_START_OCTET,
                 ClassLoaderUtils.getSystemResourceAsSharedStream("eml/recursiveMail.eml"),
                 new FlagsBuilder().add(Flags.Flag.DELETED, Flags.Flag.SEEN).add("debian", "security").build(),
-                propertyBuilder,
+                propertyBuilder.build(),
                 MAILBOX_ID);
         recursiveMail.setModSeq(MOD_SEQ);
         recursiveMail.setUid(UID);
@@ -223,7 +223,7 @@ class MessageToElasticSearchJsonTest {
                 BODY_START_OCTET,
                 ClassLoaderUtils.getSystemResourceAsSharedStream("eml/recursiveMail.eml"),
                 new FlagsBuilder().add(Flags.Flag.DELETED, Flags.Flag.SEEN).add("debian", "security").build(),
-                propertyBuilder,
+                propertyBuilder.build(),
                 MAILBOX_ID);
         mailWithNoInternalDate.setModSeq(MOD_SEQ);
         mailWithNoInternalDate.setUid(UID);
@@ -242,7 +242,7 @@ class MessageToElasticSearchJsonTest {
                 BODY_START_OCTET,
                 ClassLoaderUtils.getSystemResourceAsSharedStream("eml/recursiveMail.eml"),
                 new FlagsBuilder().add(Flags.Flag.DELETED, Flags.Flag.SEEN).add("debian", "security").build(),
-                propertyBuilder,
+                propertyBuilder.build(),
                 MAILBOX_ID);
         mailWithNoInternalDate.setModSeq(MOD_SEQ);
         mailWithNoInternalDate.setUid(UID);
@@ -270,7 +270,7 @@ class MessageToElasticSearchJsonTest {
                 BODY_START_OCTET,
                 ClassLoaderUtils.getSystemResourceAsSharedStream("eml/recursiveMail.eml"),
                 new FlagsBuilder().add(Flags.Flag.DELETED, Flags.Flag.SEEN).add("debian", "security").build(),
-                propertyBuilder,
+                propertyBuilder.build(),
                 MAILBOX_ID);
         mailWithNoInternalDate.setModSeq(MOD_SEQ);
         mailWithNoInternalDate.setUid(UID);
@@ -299,7 +299,7 @@ class MessageToElasticSearchJsonTest {
             BODY_START_OCTET,
             ClassLoaderUtils.getSystemResourceAsSharedStream("eml/recursiveMail.eml"),
             new FlagsBuilder().add(Flags.Flag.DELETED, Flags.Flag.SEEN).add("debian", "security").build(),
-            propertyBuilder,
+            propertyBuilder.build(),
             null);
         mailWithNoMailboxId.setModSeq(MOD_SEQ);
         mailWithNoMailboxId.setUid(UID);
@@ -351,7 +351,7 @@ class MessageToElasticSearchJsonTest {
             BODY_START_OCTET,
             ClassLoaderUtils.getSystemResourceAsSharedStream("eml/nonTextual.eml"),
             new Flags(),
-            propertyBuilder,
+            propertyBuilder.build(),
             MAILBOX_ID);
         spamMail.setUid(UID);
         spamMail.setModSeq(MOD_SEQ);
@@ -371,7 +371,7 @@ class MessageToElasticSearchJsonTest {
             BODY_START_OCTET,
             ClassLoaderUtils.getSystemResourceAsSharedStream("eml/emailWithNonIndexableAttachment.eml"),
             new FlagsBuilder().add(Flags.Flag.DELETED, Flags.Flag.SEEN).add("debian", "security").build(),
-            propertyBuilder,
+            propertyBuilder.build(),
             MAILBOX_ID);
         message.setModSeq(MOD_SEQ);
         message.setUid(UID);
@@ -399,7 +399,7 @@ class MessageToElasticSearchJsonTest {
             BODY_START_OCTET,
             ClassLoaderUtils.getSystemResourceAsSharedStream("eml/emailWithNonIndexableAttachment.eml"),
             new FlagsBuilder().add(Flags.Flag.DELETED, Flags.Flag.SEEN).add("debian", "security").build(),
-            propertyBuilder,
+            propertyBuilder.build(),
             MAILBOX_ID);
         message.setModSeq(MOD_SEQ);
         message.setUid(UID);
diff --git a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/AbstractJPAMailboxMessage.java b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/AbstractJPAMailboxMessage.java
index 480989a..7f62ce3 100644
--- a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/AbstractJPAMailboxMessage.java
+++ b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/AbstractJPAMailboxMessage.java
@@ -61,6 +61,7 @@ import org.apache.james.mailbox.store.mail.model.FlagsFactory;
 import org.apache.james.mailbox.store.mail.model.MailboxMessage;
 import org.apache.james.mailbox.store.mail.model.Property;
 import org.apache.james.mailbox.store.mail.model.impl.MessageParser;
+import org.apache.james.mailbox.store.mail.model.impl.Properties;
 import org.apache.james.mailbox.store.mail.model.impl.PropertyBuilder;
 import org.apache.openjpa.persistence.jdbc.ElementJoinColumn;
 import org.apache.openjpa.persistence.jdbc.ElementJoinColumns;
@@ -254,13 +255,14 @@ public abstract class AbstractJPAMailboxMessage implements MailboxMessage {
         setFlags(flags);
         this.contentOctets = contentOctets;
         this.bodyStartOctet = bodyStartOctet;
-        this.textualLineCount = propertyBuilder.getTextualLineCount();
-        this.mediaType = propertyBuilder.getMediaType();
-        this.subType = propertyBuilder.getSubType();
-        final List<Property> properties = propertyBuilder.toProperties();
-        this.properties = new ArrayList<>(properties.size());
+        Properties properties = propertyBuilder.build();
+        this.textualLineCount = properties.getTextualLineCount();
+        this.mediaType = properties.getMediaType();
+        this.subType = properties.getSubType();
+        final List<Property> propertiesAsList = properties.toProperties();
+        this.properties = new ArrayList<>(propertiesAsList.size());
         int order = 0;
-        for (Property property : properties) {
+        for (Property property : propertiesAsList) {
             this.properties.add(new JPAProperty(property, order++));
         }
 
@@ -296,11 +298,10 @@ public abstract class AbstractJPAMailboxMessage implements MailboxMessage {
         this.bodyStartOctet = (int) (original.getFullContentOctets() - original.getBodyOctets());
         this.internalDate = original.getInternalDate();
 
-        PropertyBuilder pBuilder = new PropertyBuilder(original.getProperties());
         this.textualLineCount = original.getTextualLineCount();
         this.mediaType = original.getMediaType();
         this.subType = original.getSubType();
-        final List<Property> properties = pBuilder.toProperties();
+        final List<Property> properties = original.getProperties().toProperties();
         this.properties = new ArrayList<>(properties.size());
         int order = 0;
         for (Property property : properties) {
@@ -360,10 +361,11 @@ public abstract class AbstractJPAMailboxMessage implements MailboxMessage {
      * @return unmodifiable list of meta-data, not null
      */
     @Override
-    public List<Property> getProperties() {
-        return properties.stream()
+    public Properties getProperties() {
+        return new PropertyBuilder(properties.stream()
             .map(JPAProperty::toProperty)
-            .collect(Guavate.toImmutableList());
+            .collect(Guavate.toImmutableList()))
+            .build();
     }
 
     @Override
diff --git a/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/mail/MessageUtilsTest.java b/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/mail/MessageUtilsTest.java
index c58c204..afb4acc 100644
--- a/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/mail/MessageUtilsTest.java
+++ b/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/mail/MessageUtilsTest.java
@@ -63,7 +63,7 @@ class MessageUtilsTest {
         MockitoAnnotations.initMocks(this);
         messageUtils = new MessageUtils(uidProvider, modSeqProvider);
         message = new SimpleMailboxMessage(MESSAGE_ID, new Date(), CONTENT.length(), BODY_START,
-            new SharedByteArrayInputStream(CONTENT.getBytes()), new Flags(), new PropertyBuilder(), mailbox.getMailboxId());
+            new SharedByteArrayInputStream(CONTENT.getBytes()), new Flags(), new PropertyBuilder().build(), mailbox.getMailboxId());
     }
     
     @Test
diff --git a/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/model/MaildirMessage.java b/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/model/MaildirMessage.java
index 3861dd9..af337cb 100644
--- a/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/model/MaildirMessage.java
+++ b/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/model/MaildirMessage.java
@@ -37,8 +37,8 @@ import org.apache.james.mailbox.model.MessageId;
 import org.apache.james.mailbox.model.ParsedAttachment;
 import org.apache.james.mailbox.store.mail.model.DefaultMessageId;
 import org.apache.james.mailbox.store.mail.model.Message;
-import org.apache.james.mailbox.store.mail.model.Property;
 import org.apache.james.mailbox.store.mail.model.impl.MessageParser;
+import org.apache.james.mailbox.store.mail.model.impl.Properties;
 import org.apache.james.mailbox.store.mail.model.impl.PropertyBuilder;
 import org.apache.james.mailbox.store.streaming.CountingInputStream;
 import org.apache.james.mime4j.MimeException;
@@ -185,13 +185,13 @@ public class MaildirMessage implements Message {
     @Override
     public String getMediaType() {
         parseMessage();
-        return propertyBuilder.getMediaType();
+        return propertyBuilder.build().getMediaType();
     }
 
     @Override
     public String getSubType() {
         parseMessage();
-        return propertyBuilder.getSubType();
+        return propertyBuilder.build().getSubType();
     }
 
     @Override
@@ -221,13 +221,13 @@ public class MaildirMessage implements Message {
     @Override
     public Long getTextualLineCount() {
         parseMessage();
-        return propertyBuilder.getTextualLineCount();
+        return propertyBuilder.build().getTextualLineCount();
     }
 
     @Override
-    public List<Property> getProperties() {
+    public Properties getProperties() {
         parseMessage();
-        return propertyBuilder.toProperties();
+        return propertyBuilder.build();
     }
 
     @Override
diff --git a/mailbox/plugin/spamassassin/src/test/java/org/apache/james/mailbox/spamassassin/SpamAssassinListenerTest.java b/mailbox/plugin/spamassassin/src/test/java/org/apache/james/mailbox/spamassassin/SpamAssassinListenerTest.java
index e159800..c24ee8e 100644
--- a/mailbox/plugin/spamassassin/src/test/java/org/apache/james/mailbox/spamassassin/SpamAssassinListenerTest.java
+++ b/mailbox/plugin/spamassassin/src/test/java/org/apache/james/mailbox/spamassassin/SpamAssassinListenerTest.java
@@ -271,7 +271,7 @@ class SpamAssassinListenerTest {
         int bodyStartOctet = 25;
         byte[] content = "Subject: test\r\n\r\nBody\r\n".getBytes(StandardCharsets.UTF_8);
         SimpleMailboxMessage message = new SimpleMailboxMessage(MESSAGE_ID, new Date(),
-            size, bodyStartOctet, new SharedByteArrayInputStream(content), new Flags(), new PropertyBuilder(),
+            size, bodyStartOctet, new SharedByteArrayInputStream(content), new Flags(), new PropertyBuilder().build(),
             mailbox.getMailboxId());
         MessageMetaData messageMetaData = mapperFactory.createMessageMapper(null).add(mailbox, message);
         message.setUid(messageMetaData.getUid());
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/LazyMimeDescriptor.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/LazyMimeDescriptor.java
index e1d4ae2..20ad442 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/LazyMimeDescriptor.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/LazyMimeDescriptor.java
@@ -32,6 +32,7 @@ import org.apache.james.mailbox.model.Header;
 import org.apache.james.mailbox.model.MessageResult;
 import org.apache.james.mailbox.model.MimeDescriptor;
 import org.apache.james.mailbox.store.mail.model.Message;
+import org.apache.james.mailbox.store.mail.model.impl.Properties;
 import org.apache.james.mailbox.store.mail.model.impl.PropertyBuilder;
 
 /**
@@ -42,7 +43,7 @@ public class LazyMimeDescriptor implements MimeDescriptor {
 
     private final Message message;
     private final MessageResult result;
-    private PropertyBuilder pbuilder;
+    private Properties properties;
     
     public LazyMimeDescriptor(MessageResult result, Message message) {
         this.message = message;
@@ -151,11 +152,11 @@ public class LazyMimeDescriptor implements MimeDescriptor {
      * 
      * @return pbuilder
      */
-    private PropertyBuilder getPropertyBuilder() {
-        if (pbuilder == null) {
-            pbuilder = new PropertyBuilder(message.getProperties());
+    private Properties getPropertyBuilder() {
+        if (properties == null) {
+            properties = message.getProperties();
         }
-        return pbuilder;
+        return properties;
     }
     
 }
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/MessageFactory.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/MessageFactory.java
index 4a4a4f2..2a3006f 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/MessageFactory.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/MessageFactory.java
@@ -43,7 +43,7 @@ public interface MessageFactory<T extends MailboxMessage> {
         public SimpleMailboxMessage createMessage(MessageId messageId, Mailbox mailbox, Date internalDate, int size,
                                             int bodyStartOctet, SharedInputStream content, Flags flags,
                                             PropertyBuilder propertyBuilder, List<MessageAttachmentMetadata> attachments) {
-            return new SimpleMailboxMessage(messageId, internalDate, size, bodyStartOctet, content, flags, propertyBuilder,
+            return new SimpleMailboxMessage(messageId, internalDate, size, bodyStartOctet, content, flags, propertyBuilder.build(),
                 mailbox.getMailboxId(), attachments);
         }
     }
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/DelegatingMailboxMessage.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/DelegatingMailboxMessage.java
index cdd3ff2..6b5c5f9 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/DelegatingMailboxMessage.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/DelegatingMailboxMessage.java
@@ -27,6 +27,7 @@ import javax.mail.Flags;
 
 import org.apache.james.mailbox.model.MessageAttachmentMetadata;
 import org.apache.james.mailbox.model.MessageId;
+import org.apache.james.mailbox.store.mail.model.impl.Properties;
 
 public abstract class DelegatingMailboxMessage implements MailboxMessage {
 
@@ -77,7 +78,7 @@ public abstract class DelegatingMailboxMessage implements MailboxMessage {
     }
 
     @Override
-    public List<Property> getProperties() {
+    public Properties getProperties() {
         return message.getProperties();
     }
 
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/Message.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/Message.java
index 9cacbfc..fef05fb 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/Message.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/Message.java
@@ -25,6 +25,7 @@ import java.util.List;
 
 import org.apache.james.mailbox.model.MessageAttachmentMetadata;
 import org.apache.james.mailbox.model.MessageId;
+import org.apache.james.mailbox.store.mail.model.impl.Properties;
 
 public interface Message {
 
@@ -96,11 +97,11 @@ public interface Message {
     /**
      * Gets a read-only list of meta-data properties.
      * For properties with multiple values, this list will contain
-     * several enteries with the same namespace and local name.
+     * several entries with the same namespace and local name.
      *
      * @return unmodifiable list of meta-data, not null
      */
-    List<Property> getProperties();
+    Properties getProperties();
     
     /**
      * Return the list of attachments
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/PropertyBuilder.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/Properties.java
similarity index 57%
copy from mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/PropertyBuilder.java
copy to mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/Properties.java
index 1f53595..b8900a4 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/PropertyBuilder.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/Properties.java
@@ -42,7 +42,6 @@ import static org.apache.james.mailbox.store.mail.model.StandardNames.MIME_SUB_T
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Locale;
 import java.util.Map;
 import java.util.SortedMap;
 import java.util.TreeMap;
@@ -50,27 +49,16 @@ import java.util.TreeMap;
 import org.apache.james.mailbox.store.mail.model.Property;
 
 import com.github.steveash.guavate.Guavate;
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableList;
 
-/**
- * Builds properties
- */
-public class PropertyBuilder {
-    private static final int INITIAL_CAPACITY = 32;
-
+public class Properties {
     private Long textualLineCount;
-    private final List<Property> properties;
+    private final ImmutableList<Property> properties;
 
-    public PropertyBuilder(List<Property> props) {
-        textualLineCount = null;
-        properties = new ArrayList<>(props.size());
-        for (Property property:props) {
-            properties.add(new Property(property));
-        }
-    }
-    
-    public PropertyBuilder() {
-        textualLineCount = null;
-        properties = new ArrayList<>(INITIAL_CAPACITY);
+    public Properties(List<Property> props, Long textualLineCount) {
+        this.textualLineCount = textualLineCount;
+        this.properties = ImmutableList.copyOf(props);
     }
 
     /**
@@ -81,15 +69,6 @@ public class PropertyBuilder {
     public Long getTextualLineCount() {
         return textualLineCount;
     }
-
-    /**
-     * Aets the number of CRLF in a textual document.
-     * @param textualLineCount count when document is textual,
-     * null otherwise
-     */
-    public void setTextualLineCount(Long textualLineCount) {
-        this.textualLineCount = textualLineCount;
-    }
     
     /**
      * Gets the first value with the given name.
@@ -99,7 +78,7 @@ public class PropertyBuilder {
      * @return value, 
      * or null when no property has the given name and namespace
      */
-    public String getFirstValue(String namespace, String localName) {
+    private String getFirstValue(String namespace, String localName) {
         return properties.stream()
             .filter(property -> property.isNamed(namespace, localName))
             .findFirst()
@@ -113,48 +92,20 @@ public class PropertyBuilder {
      * @param localName not null
      * @return not null
      */
-    public List<String> getValues(String namespace, String localName) {
+    private List<String> getValues(String namespace, String localName) {
         return properties.stream()
             .filter(property -> property.isNamed(namespace, localName))
             .map(Property::getValue)
             .collect(Guavate.toImmutableList());
     }
-    
-    /**
-     * Sets a property allowing only a single value.
-     * @param namespace not null
-     * @param localName not null
-     * @param value null to remove property
-     */
-    public void setProperty(String namespace, String localName, String value) {
-        properties.removeIf(property -> property.isNamed(namespace, localName));
-        
-        if (value != null) {
-            properties.add(new Property(namespace, localName, value));
-        }
-    }
-    
-    /**
-     * Sets a multiple valued property.
-     * @param namespace not null
-     * @param localName not null
-     * @param values null to remove property
-     */
-    public void setProperty(String namespace, String localName, List<String> values) {
-        properties.removeIf(property -> property.isNamed(namespace, localName));
-        if (values != null) {
-            for (String value:values) {
-                properties.add(new Property(namespace, localName, value));
-            }
-        }
-    }
+
     
     /**
      * Maps properties in the given namespace.
      * @param namespace not null
      * @return values indexed by local name
      */
-    public SortedMap<String,String> getProperties(String namespace) {
+    private SortedMap<String,String> getProperties(String namespace) {
         final SortedMap<String, String> parameters = new TreeMap<>();
         for (Property property : properties) {
             if (property.isInSpace(namespace)) {
@@ -165,20 +116,6 @@ public class PropertyBuilder {
     }
     
     /**
-     * Sets properties in the given namespace from the map.
-     * Existing properties in the namespace will be removed.
-     * All local names will be converted to lower case.
-     * @param namespace not null
-     * @param valuesByLocalName not null
-     */
-    public void setProperties(String namespace, Map<String,String> valuesByLocalName) {
-        properties.removeIf(property -> property.isInSpace(namespace));
-        for (Map.Entry<String, String> valueByLocalName:valuesByLocalName.entrySet()) {
-            properties.add(new Property(namespace, valueByLocalName.getKey().toLowerCase(Locale.US), valueByLocalName.getValue()));
-        }
-    }
-    
-    /**
      * Gets the top level MIME content media type.
      * 
      * @return top level MIME content media type, or null if default
@@ -186,16 +123,6 @@ public class PropertyBuilder {
     public String getMediaType() {
         return getFirstValue(MIME_MIME_TYPE_SPACE, MIME_MEDIA_TYPE_NAME);
     }
-    
-    /**
-     * Sets the top level MIME content media type.
-     * 
-     * @param value top level MIME content media type, 
-     * or null to remove
-     */
-    public void setMediaType(String value) {
-        setProperty(MIME_MIME_TYPE_SPACE, MIME_MEDIA_TYPE_NAME, value);
-    }
 
     /**
      * Gets the MIME content subtype.
@@ -205,16 +132,7 @@ public class PropertyBuilder {
     public String getSubType() {
         return getFirstValue(MIME_MIME_TYPE_SPACE, MIME_SUB_TYPE_NAME);
     }
-    
-    /**
-     * Sets the MIME content subtype.
-     * 
-     * @param value the MIME content subtype, 
-     * or null to remove
-     */
-    public void setSubType(String value) {
-        setProperty(MIME_MIME_TYPE_SPACE, MIME_SUB_TYPE_NAME, value);
-    }
+
     
     /**
      * Gets the MIME Content-ID.
@@ -226,16 +144,6 @@ public class PropertyBuilder {
     }
     
     /**
-     * Sets MIME Content-ID.
-     * 
-     * @param value the MIME content subtype, 
-     * or null to remove
-     */
-    public void setContentID(String value) {
-        setProperty(MIME_CONTENT_ID_SPACE, MIME_CONTENT_ID_NAME, value);
-    }
-    
-    /**
      * Gets the MIME Content-Description.
      * 
      * @return the MIME Content-Description, 
@@ -246,16 +154,6 @@ public class PropertyBuilder {
     }
     
     /**
-     * Sets MIME Content-Description.
-     * 
-     * @param value the MIME Content-Description
-     * or null to remove
-     */
-    public void setContentDescription(String value) {
-        setProperty(MIME_CONTENT_DESCRIPTION_SPACE, MIME_CONTENT_DESCRIPTION_NAME, value);
-    }
-    
-    /**
      * Gets the MIME Content-Transfer-Encoding.
      * 
      * @return the MIME Content-Transfer-Encoding, 
@@ -264,16 +162,7 @@ public class PropertyBuilder {
     public String getContentTransferEncoding() {
         return getFirstValue(MIME_CONTENT_TRANSFER_ENCODING_SPACE, MIME_CONTENT_TRANSFER_ENCODING_NAME);
     }
-    
-    /**
-     * Sets MIME Content-Transfer-Encoding.
-     * 
-     * @param value the MIME Content-Transfer-Encoding
-     * or null to remove
-     */
-    public void setContentTransferEncoding(String value) {
-        setProperty(MIME_CONTENT_TRANSFER_ENCODING_SPACE, MIME_CONTENT_TRANSFER_ENCODING_NAME, value);
-    }
+
     
     /**
      * Gets the RFC2557 Content-Location.
@@ -286,26 +175,6 @@ public class PropertyBuilder {
     }
     
     /**
-     * Sets RFC2557 Content-Location.
-     * 
-     * @param value the RFC2557 Content-Location
-     * or null to remove
-     */
-    public void setContentLocation(String value) {
-        setProperty(MIME_CONTENT_LOCATION_SPACE, MIME_CONTENT_LOCATION_NAME, value);
-    }
-    
-    /**
-     * Sets RFC2183 Content-Disposition disposition-type.
-     * 
-     * @param value the RFC2183 Content-Disposition
-     * or null to remove
-     */
-    public void setContentDispositionType(String value) {
-        setProperty(MIME_CONTENT_DISPOSITION_SPACE, MIME_CONTENT_DISPOSITION_TYPE_NAME, value);
-    }
-    
-    /**
      * Gets the RFC2183 Content-Disposition disposition-type.
      * 
      * @return the RFC2183 Content-Disposition, 
@@ -324,15 +193,6 @@ public class PropertyBuilder {
     }
     
     /**
-     * Sets Content-Disposition parameters.
-     * Parameter names will be normalised to lower case.
-     * @param valuesByParameterName values indexed by parameter name
-     */
-    public void setContentDispositionParameters(Map<String,String> valuesByParameterName) {
-        setProperties(MIME_CONTENT_DISPOSITION_PARAMETER_SPACE, valuesByParameterName);
-    }
-    
-    /**
      * Gets RFC2045 Content-Type parameters.
      * @return parameter values indexed by lower case local names 
      */
@@ -341,15 +201,6 @@ public class PropertyBuilder {
     }
     
     /**
-     * Sets Content-Type parameters.
-     * Parameter names will be normalised to lower case.
-     * @param valuesByParameterName values indexed by parameter name
-     */
-    public void setContentTypeParameters(Map<String,String> valuesByParameterName) {
-        setProperties(MIME_CONTENT_TYPE_PARAMETER_SPACE, valuesByParameterName);
-    }
-    
-    /**
      * Gets the RFC1864 Content-MD5.
      * 
      * @return the RFC1864 Content-MD5, 
@@ -360,16 +211,6 @@ public class PropertyBuilder {
     }
     
     /**
-     * Sets RFC1864 Content-MD5.
-     * 
-     * @param value the RFC1864 Content-MD5
-     * or null to remove
-     */
-    public void setContentMD5(String value) {
-        setProperty(MIME_CONTENT_MD5_SPACE, MIME_CONTENT_MD5_NAME, value);
-    }
-    
-    /**
      * Gets the RFC2045 Content-Type "charset" parameter.
      * 
      * @return the RFC2045 Content-Type "charset" parameter, 
@@ -378,16 +219,7 @@ public class PropertyBuilder {
     public String getCharset() {
         return getFirstValue(MIME_CONTENT_TYPE_PARAMETER_SPACE, MIME_CONTENT_TYPE_PARAMETER_CHARSET_NAME);
     }
-    
-    /**
-     * Sets RFC2045 Content-Type "charset" parameter.
-     * 
-     * @param value the RFC2045 Content-Type "charset" parameter
-     * or null to remove
-     */
-    public void setCharset(String value) {
-        setProperty(MIME_CONTENT_TYPE_PARAMETER_SPACE, MIME_CONTENT_TYPE_PARAMETER_CHARSET_NAME, value);
-    }
+
     
     /**
      * Gets the RFC2045 Content-Type "boundary" parameter.
@@ -400,16 +232,6 @@ public class PropertyBuilder {
     }
     
     /**
-     * Sets RFC2045 Content-Type "boundary" parameter.
-     * 
-     * @param value the RFC2045 Content-Type "boundary" parameter
-     * or null to remove
-     */
-    public void setBoundary(String value) {
-        setProperty(MIME_CONTENT_TYPE_PARAMETER_SPACE, MIME_CONTENT_TYPE_PARAMETER_BOUNDARY_NAME, value);
-    }
-    
-    /**
      * Gets the RFC1766 Content-Language.
      * 
      * @return list of parsed langauge tags from the RFC1766 Content-Language, 
@@ -418,21 +240,7 @@ public class PropertyBuilder {
     public List<String> getContentLanguage() {
         return getValues(MIME_CONTENT_LANGUAGE_SPACE, MIME_CONTENT_LANGUAGE_NAME);
     }
-    
-    /**
-     * Sets RFC1766 Content-Language.
-     * 
-     * @param values list of parsed language tags from the RFC1766 Content-Language, 
-     * possibly empty
-     */
-    public void setContentLanguage(List<String> values) {
-        setProperty(MIME_CONTENT_LANGUAGE_SPACE, MIME_CONTENT_LANGUAGE_NAME, values);
-    }
-    
-    /**
-     * Builds a list of properties.
-     * @return not null
-     */
+
     public List<Property> toProperties() {
         return new ArrayList<>(properties);
     }
@@ -445,9 +253,9 @@ public class PropertyBuilder {
      * of this object.
      */
     public String toString() {
-        return "PropertyBuilder ( "
-        + " textualLineCount = " + this.textualLineCount
-        + " properties = " + this.properties
-        + " )";
+        return MoreObjects.toStringHelper(this)
+            .add("textualLineCount", textualLineCount)
+            .add("properties", properties)
+            .toString();
     }
 }
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/PropertyBuilder.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/PropertyBuilder.java
index 1f53595..0abf1ee 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/PropertyBuilder.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/PropertyBuilder.java
@@ -44,13 +44,9 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
-import java.util.SortedMap;
-import java.util.TreeMap;
 
 import org.apache.james.mailbox.store.mail.model.Property;
 
-import com.github.steveash.guavate.Guavate;
-
 /**
  * Builds properties
  */
@@ -90,35 +86,7 @@ public class PropertyBuilder {
     public void setTextualLineCount(Long textualLineCount) {
         this.textualLineCount = textualLineCount;
     }
-    
-    /**
-     * Gets the first value with the given name.
-     * Used to retrieve values with a single value.
-     * @param namespace not null
-     * @param localName not null
-     * @return value, 
-     * or null when no property has the given name and namespace
-     */
-    public String getFirstValue(String namespace, String localName) {
-        return properties.stream()
-            .filter(property -> property.isNamed(namespace, localName))
-            .findFirst()
-            .map(Property::getValue)
-            .orElse(null);
-    }
-    
-    /**
-     * Lists all values for a property.
-     * @param namespace not null
-     * @param localName not null
-     * @return not null
-     */
-    public List<String> getValues(String namespace, String localName) {
-        return properties.stream()
-            .filter(property -> property.isNamed(namespace, localName))
-            .map(Property::getValue)
-            .collect(Guavate.toImmutableList());
-    }
+
     
     /**
      * Sets a property allowing only a single value.
@@ -126,7 +94,7 @@ public class PropertyBuilder {
      * @param localName not null
      * @param value null to remove property
      */
-    public void setProperty(String namespace, String localName, String value) {
+    private void setProperty(String namespace, String localName, String value) {
         properties.removeIf(property -> property.isNamed(namespace, localName));
         
         if (value != null) {
@@ -140,7 +108,7 @@ public class PropertyBuilder {
      * @param localName not null
      * @param values null to remove property
      */
-    public void setProperty(String namespace, String localName, List<String> values) {
+    private void setProperty(String namespace, String localName, List<String> values) {
         properties.removeIf(property -> property.isNamed(namespace, localName));
         if (values != null) {
             for (String value:values) {
@@ -150,28 +118,13 @@ public class PropertyBuilder {
     }
     
     /**
-     * Maps properties in the given namespace.
-     * @param namespace not null
-     * @return values indexed by local name
-     */
-    public SortedMap<String,String> getProperties(String namespace) {
-        final SortedMap<String, String> parameters = new TreeMap<>();
-        for (Property property : properties) {
-            if (property.isInSpace(namespace)) {
-                parameters.put(property.getLocalName(), property.getValue());
-            }
-        }
-        return parameters;
-    }
-    
-    /**
      * Sets properties in the given namespace from the map.
      * Existing properties in the namespace will be removed.
      * All local names will be converted to lower case.
      * @param namespace not null
      * @param valuesByLocalName not null
      */
-    public void setProperties(String namespace, Map<String,String> valuesByLocalName) {
+    private void setProperties(String namespace, Map<String,String> valuesByLocalName) {
         properties.removeIf(property -> property.isInSpace(namespace));
         for (Map.Entry<String, String> valueByLocalName:valuesByLocalName.entrySet()) {
             properties.add(new Property(namespace, valueByLocalName.getKey().toLowerCase(Locale.US), valueByLocalName.getValue()));
@@ -179,15 +132,6 @@ public class PropertyBuilder {
     }
     
     /**
-     * Gets the top level MIME content media type.
-     * 
-     * @return top level MIME content media type, or null if default
-     */
-    public String getMediaType() {
-        return getFirstValue(MIME_MIME_TYPE_SPACE, MIME_MEDIA_TYPE_NAME);
-    }
-    
-    /**
      * Sets the top level MIME content media type.
      * 
      * @param value top level MIME content media type, 
@@ -196,15 +140,6 @@ public class PropertyBuilder {
     public void setMediaType(String value) {
         setProperty(MIME_MIME_TYPE_SPACE, MIME_MEDIA_TYPE_NAME, value);
     }
-
-    /**
-     * Gets the MIME content subtype.
-     * 
-     * @return the MIME content subtype, or null if default
-     */
-    public String getSubType() {
-        return getFirstValue(MIME_MIME_TYPE_SPACE, MIME_SUB_TYPE_NAME);
-    }
     
     /**
      * Sets the MIME content subtype.
@@ -217,15 +152,6 @@ public class PropertyBuilder {
     }
     
     /**
-     * Gets the MIME Content-ID.
-     * 
-     * @return the MIME content subtype, or null if default
-     */
-    public String getContentID() {
-        return getFirstValue(MIME_CONTENT_ID_SPACE, MIME_CONTENT_ID_NAME);
-    }
-    
-    /**
      * Sets MIME Content-ID.
      * 
      * @param value the MIME content subtype, 
@@ -236,16 +162,6 @@ public class PropertyBuilder {
     }
     
     /**
-     * Gets the MIME Content-Description.
-     * 
-     * @return the MIME Content-Description, 
-     * or null if this meta data is not present
-     */
-    public String getContentDescription() {
-        return getFirstValue(MIME_CONTENT_DESCRIPTION_SPACE, MIME_CONTENT_DESCRIPTION_NAME);
-    }
-    
-    /**
      * Sets MIME Content-Description.
      * 
      * @param value the MIME Content-Description
@@ -256,16 +172,6 @@ public class PropertyBuilder {
     }
     
     /**
-     * Gets the MIME Content-Transfer-Encoding.
-     * 
-     * @return the MIME Content-Transfer-Encoding, 
-     * or null if this meta data is not present
-     */
-    public String getContentTransferEncoding() {
-        return getFirstValue(MIME_CONTENT_TRANSFER_ENCODING_SPACE, MIME_CONTENT_TRANSFER_ENCODING_NAME);
-    }
-    
-    /**
      * Sets MIME Content-Transfer-Encoding.
      * 
      * @param value the MIME Content-Transfer-Encoding
@@ -276,16 +182,6 @@ public class PropertyBuilder {
     }
     
     /**
-     * Gets the RFC2557 Content-Location.
-     * 
-     * @return the RFC2557 Content-Location, 
-     * or null if this meta data is not present
-     */
-    public String getContentLocation() {
-        return getFirstValue(MIME_CONTENT_LOCATION_SPACE, MIME_CONTENT_LOCATION_NAME);
-    }
-    
-    /**
      * Sets RFC2557 Content-Location.
      * 
      * @param value the RFC2557 Content-Location
@@ -306,24 +202,6 @@ public class PropertyBuilder {
     }
     
     /**
-     * Gets the RFC2183 Content-Disposition disposition-type.
-     * 
-     * @return the RFC2183 Content-Disposition, 
-     * or null if this meta data is not present
-     */
-    public String getContentDispositionType() {
-        return getFirstValue(MIME_CONTENT_DISPOSITION_SPACE, MIME_CONTENT_DISPOSITION_TYPE_NAME);
-    }
-    
-    /**
-     * Gets RFC2183 Content-Disposition parameters.
-     * @return parameter values indexed by lower case local names 
-     */
-    public Map<String,String> getContentDispositionParameters() {
-        return getProperties(MIME_CONTENT_DISPOSITION_PARAMETER_SPACE);
-    }
-    
-    /**
      * Sets Content-Disposition parameters.
      * Parameter names will be normalised to lower case.
      * @param valuesByParameterName values indexed by parameter name
@@ -333,14 +211,6 @@ public class PropertyBuilder {
     }
     
     /**
-     * Gets RFC2045 Content-Type parameters.
-     * @return parameter values indexed by lower case local names 
-     */
-    public Map<String,String> getContentTypeParameters() {
-        return getProperties(MIME_CONTENT_TYPE_PARAMETER_SPACE);
-    }
-    
-    /**
      * Sets Content-Type parameters.
      * Parameter names will be normalised to lower case.
      * @param valuesByParameterName values indexed by parameter name
@@ -350,16 +220,6 @@ public class PropertyBuilder {
     }
     
     /**
-     * Gets the RFC1864 Content-MD5.
-     * 
-     * @return the RFC1864 Content-MD5, 
-     * or null if this meta data is not present
-     */
-    public String getContentMD5() {
-        return getFirstValue(MIME_CONTENT_MD5_SPACE, MIME_CONTENT_MD5_NAME);
-    }
-    
-    /**
      * Sets RFC1864 Content-MD5.
      * 
      * @param value the RFC1864 Content-MD5
@@ -370,16 +230,6 @@ public class PropertyBuilder {
     }
     
     /**
-     * Gets the RFC2045 Content-Type "charset" parameter.
-     * 
-     * @return the RFC2045 Content-Type "charset" parameter, 
-     * or null if this meta data is not present
-     */
-    public String getCharset() {
-        return getFirstValue(MIME_CONTENT_TYPE_PARAMETER_SPACE, MIME_CONTENT_TYPE_PARAMETER_CHARSET_NAME);
-    }
-    
-    /**
      * Sets RFC2045 Content-Type "charset" parameter.
      * 
      * @param value the RFC2045 Content-Type "charset" parameter
@@ -390,16 +240,6 @@ public class PropertyBuilder {
     }
     
     /**
-     * Gets the RFC2045 Content-Type "boundary" parameter.
-     * 
-     * @return the RFC2045 Content-Type "boundary" parameter, 
-     * or null if this meta data is not present
-     */
-    public String getBoundary() {
-        return getFirstValue(MIME_CONTENT_TYPE_PARAMETER_SPACE, MIME_CONTENT_TYPE_PARAMETER_BOUNDARY_NAME);
-    }
-    
-    /**
      * Sets RFC2045 Content-Type "boundary" parameter.
      * 
      * @param value the RFC2045 Content-Type "boundary" parameter
@@ -410,16 +250,6 @@ public class PropertyBuilder {
     }
     
     /**
-     * Gets the RFC1766 Content-Language.
-     * 
-     * @return list of parsed langauge tags from the RFC1766 Content-Language, 
-     * possibly empty
-     */
-    public List<String> getContentLanguage() {
-        return getValues(MIME_CONTENT_LANGUAGE_SPACE, MIME_CONTENT_LANGUAGE_NAME);
-    }
-    
-    /**
      * Sets RFC1766 Content-Language.
      * 
      * @param values list of parsed language tags from the RFC1766 Content-Language, 
@@ -437,6 +267,10 @@ public class PropertyBuilder {
         return new ArrayList<>(properties);
     }
 
+    public Properties build() {
+        return new Properties(properties, textualLineCount);
+    }
+
     /**
      * Constructs a <code>String</code> with all attributes
      * in name = value format.
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMailboxMessage.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMailboxMessage.java
index 32be330..acbe59f 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMailboxMessage.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMailboxMessage.java
@@ -60,7 +60,7 @@ public class SimpleMailboxMessage extends DelegatingMailboxMessage {
         private Integer bodyStartOctet;
         private SharedInputStream content;
         private Flags flags;
-        private PropertyBuilder propertyBuilder;
+        private Properties properties;
         private MailboxId mailboxId;
         private Optional<MessageUid> uid = Optional.empty();
         private Optional<ModSeq> modseq = Optional.empty();
@@ -108,8 +108,13 @@ public class SimpleMailboxMessage extends DelegatingMailboxMessage {
             return this;
         }
 
-        public Builder propertyBuilder(PropertyBuilder propertyBuilder) {
-            this.propertyBuilder = propertyBuilder;
+        public Builder properties(PropertyBuilder propertyBuilder) {
+            this.properties = propertyBuilder.build();
+            return this;
+        }
+
+        public Builder properties(Properties properties) {
+            this.properties = properties;
             return this;
         }
 
@@ -130,12 +135,12 @@ public class SimpleMailboxMessage extends DelegatingMailboxMessage {
             Preconditions.checkNotNull(bodyStartOctet, "bodyStartOctet is required");
             Preconditions.checkNotNull(content, "content is required");
             Preconditions.checkNotNull(flags, "flags is required");
-            Preconditions.checkNotNull(propertyBuilder, "propertyBuilder is required");
+            Preconditions.checkNotNull(properties, "properties is required");
             Preconditions.checkNotNull(mailboxId, "mailboxId is required");
 
             ImmutableList<MessageAttachmentMetadata> attachments = this.attachments.build();
             SimpleMailboxMessage simpleMailboxMessage = new SimpleMailboxMessage(messageId, internalDate, size,
-                bodyStartOctet, content, flags, propertyBuilder, mailboxId, attachments);
+                bodyStartOctet, content, flags, properties, mailboxId, attachments);
 
             uid.ifPresent(simpleMailboxMessage::setUid);
             modseq.ifPresent(simpleMailboxMessage::setModSeq);
@@ -154,8 +159,6 @@ public class SimpleMailboxMessage extends DelegatingMailboxMessage {
     }
 
     public static Builder fromWithoutAttachments(MailboxMessage original) throws MailboxException {
-        PropertyBuilder propertyBuilder = new PropertyBuilder(original.getProperties());
-        propertyBuilder.setTextualLineCount(original.getTextualLineCount());
         return builder()
             .bodyStartOctet(Ints.checkedCast(original.getFullContentOctets() - original.getBodyOctets()))
             .content(copyFullContent(original))
@@ -163,7 +166,7 @@ public class SimpleMailboxMessage extends DelegatingMailboxMessage {
             .internalDate(original.getInternalDate())
             .size(original.getFullContentOctets())
             .flags(original.createFlags())
-            .propertyBuilder(propertyBuilder);
+            .properties(original.getProperties());
     }
 
     public static SimpleMailboxMessage copyWithoutAttachments(MailboxId mailboxId, MailboxMessage original) throws MailboxException {
@@ -192,14 +195,13 @@ public class SimpleMailboxMessage extends DelegatingMailboxMessage {
 
     public SimpleMailboxMessage(MessageId messageId, Date internalDate, long size, int bodyStartOctet,
             SharedInputStream content, Flags flags,
-            PropertyBuilder propertyBuilder, MailboxId mailboxId, List<MessageAttachmentMetadata> attachments) {
+            Properties properties, MailboxId mailboxId, List<MessageAttachmentMetadata> attachments) {
         super(new SimpleMessage(
                 messageId,
-                content, size, internalDate, propertyBuilder.getSubType(),
-                propertyBuilder.getMediaType(),
+                content, size, internalDate,
                 bodyStartOctet,
-                propertyBuilder.getTextualLineCount(),
-                propertyBuilder.toProperties(),
+                properties.getTextualLineCount(),
+                properties,
                 attachments));
 
             setFlags(flags);
@@ -209,10 +211,10 @@ public class SimpleMailboxMessage extends DelegatingMailboxMessage {
 
     public SimpleMailboxMessage(MessageId messageId, Date internalDate, long size, int bodyStartOctet,
                                 SharedInputStream content, Flags flags,
-                                PropertyBuilder propertyBuilder, MailboxId mailboxId) {
+                                Properties properties, MailboxId mailboxId) {
         this(messageId, internalDate, size, bodyStartOctet,
                 content, flags,
-                propertyBuilder, mailboxId, ImmutableList.of());
+                properties, mailboxId, ImmutableList.of());
     }
 
     @Override
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMessage.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMessage.java
index 62a5b86..88356b0 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMessage.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMessage.java
@@ -28,25 +28,20 @@ import javax.mail.internet.SharedInputStream;
 import org.apache.james.mailbox.model.MessageAttachmentMetadata;
 import org.apache.james.mailbox.model.MessageId;
 import org.apache.james.mailbox.store.mail.model.Message;
-import org.apache.james.mailbox.store.mail.model.Property;
 
 public class SimpleMessage implements Message {
 
     private final MessageId messageId;
-    private final String subType;
-    private final String mediaType;
     private final SharedInputStream content;
     private final int bodyStartOctet;
     private final Date internalDate;
     private final long size;
     private final Long textualLineCount;
-    private final List<Property> properties;
+    private final Properties properties;
     private final List<MessageAttachmentMetadata> attachments;
 
-    public SimpleMessage(MessageId messageId, SharedInputStream content, long size, Date internalDate, String subType, String mediaType, int bodyStartOctet, Long textualLineCount, List<Property> properties, List<MessageAttachmentMetadata> attachments) {
+    public SimpleMessage(MessageId messageId, SharedInputStream content, long size, Date internalDate, int bodyStartOctet, Long textualLineCount, Properties properties, List<MessageAttachmentMetadata> attachments) {
         this.messageId = messageId;
-        this.subType = subType;
-        this.mediaType = mediaType;
         this.content = content;
         this.bodyStartOctet = bodyStartOctet;
         this.internalDate = internalDate;
@@ -73,12 +68,12 @@ public class SimpleMessage implements Message {
 
     @Override
     public String getMediaType() {
-        return mediaType;
+        return properties.getMediaType();
     }
 
     @Override
     public String getSubType() {
-        return subType;
+        return properties.getSubType();
     }
 
     @Override
@@ -116,7 +111,7 @@ public class SimpleMessage implements Message {
     }
 
     @Override
-    public List<Property> getProperties() {
+    public Properties getProperties() {
         return properties;
     }
 
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/MessageBuilder.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/MessageBuilder.java
index 9e593c5..065202f 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/MessageBuilder.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/MessageBuilder.java
@@ -81,7 +81,7 @@ public class MessageBuilder {
     public MailboxMessage build(MessageId messageId) throws Exception {
         byte[] headerContent = getHeaderContent();
         SimpleMailboxMessage mailboxMessage = new SimpleMailboxMessage(messageId, internalDate, size, headerContent.length,
-            new SharedByteArrayInputStream(Bytes.concat(headerContent, body)), flags, new PropertyBuilder(), mailboxId, NO_ATTACHMENTS);
+            new SharedByteArrayInputStream(Bytes.concat(headerContent, body)), flags, new PropertyBuilder().build(), mailboxId, NO_ATTACHMENTS);
         mailboxMessage.setUid(uid);
         return mailboxMessage;
     }
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/MessageIdManagerTestSystem.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/MessageIdManagerTestSystem.java
index 24ccc3c..7728ed3 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/MessageIdManagerTestSystem.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/MessageIdManagerTestSystem.java
@@ -114,7 +114,7 @@ public class MessageIdManagerTestSystem {
 
     private static MailboxMessage createMessage(MailboxId mailboxId, Flags flags, MessageId messageId, MessageUid uid) {
         MailboxMessage mailboxMessage = new SimpleMailboxMessage(messageId, new Date(), MESSAGE_CONTENT.length, 1256,
-            new SharedByteArrayInputStream(MESSAGE_CONTENT), flags, new PropertyBuilder(), mailboxId);
+            new SharedByteArrayInputStream(MESSAGE_CONTENT), flags, new PropertyBuilder().build(), mailboxId);
         mailboxMessage.setModSeq(MOD_SEQ);
         mailboxMessage.setUid(uid);
         return mailboxMessage;
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreMailboxMessageResultIteratorTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreMailboxMessageResultIteratorTest.java
index c20c807..d608338 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreMailboxMessageResultIteratorTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreMailboxMessageResultIteratorTest.java
@@ -98,7 +98,7 @@ class StoreMailboxMessageResultIteratorTest {
 
         private SimpleMailboxMessage createMessage(MessageUid uid) {
             SimpleMailboxMessage message = new SimpleMailboxMessage(new DefaultMessageId(), null, 0, 0, new SharedByteArrayInputStream(
-                    "".getBytes()), new Flags(), new PropertyBuilder(), TestId.of(1L));
+                    "".getBytes()), new Flags(), new PropertyBuilder().build(), TestId.of(1L));
             message.setUid(uid);
             return message;
         }
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/ListMessageAssertTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/ListMessageAssertTest.java
index 99318de..6d369bc 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/ListMessageAssertTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/ListMessageAssertTest.java
@@ -90,7 +90,7 @@ class ListMessageAssertTest {
     private MailboxMessage createMailboxMessage(MailboxId mailboxId, MessageId messageId, MessageUid uid, Date internalDate,
                                                 String content, int bodyStart, PropertyBuilder propertyBuilder) {
         SimpleMailboxMessage simpleMailboxMessage = new SimpleMailboxMessage(messageId, internalDate, content.length(),
-            bodyStart, new SharedByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8)), new Flags(), propertyBuilder, mailboxId);
+            bodyStart, new SharedByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8)), new Flags(), propertyBuilder.build(), mailboxId);
 
         simpleMailboxMessage.setUid(uid);
         simpleMailboxMessage.setModSeq(ModSeq.first());
@@ -103,7 +103,7 @@ class ListMessageAssertTest {
 
     private MailboxMessage createMessage(Mailbox mailbox, MessageId messageId, String content, int bodyStart, PropertyBuilder propertyBuilder) {
         SimpleMailboxMessage simpleMailboxMessage = new SimpleMailboxMessage(messageId, INTERNAL_DATE, content.length(),
-            bodyStart, new SharedByteArrayInputStream(content.getBytes()), new Flags(), propertyBuilder, mailbox.getMailboxId());
+            bodyStart, new SharedByteArrayInputStream(content.getBytes()), new Flags(), propertyBuilder.build(), mailbox.getMailboxId());
 
         simpleMailboxMessage.setUid(MESSAGE_UID);
         return simpleMailboxMessage;
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/ListMessagePropertiesAssertTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/ListMessagePropertiesAssertTest.java
index beef849..249283d 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/ListMessagePropertiesAssertTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/ListMessagePropertiesAssertTest.java
@@ -31,7 +31,7 @@ import com.google.common.collect.ImmutableList;
 
 class ListMessagePropertiesAssertTest {
     static final String OTHER_VALUE = "US-ASCII";
-    static final String OTHER_LOCAL_NAME = StandardNames.MIME_CONTENT_TYPE_PARAMETER_CHARSET_NAME;
+    static final String OTHER_LOCAL_NAME = StandardNames.MIME_CONTENT_MD5_NAME;
     static final String OTHER_NAMESPACE = StandardNames.MIME_CONTENT_TYPE_PARAMETER_SPACE;
     static final String VALUE = "7bit";
     static final String LOCAL_NAME = StandardNames.MIME_CONTENT_TRANSFER_ENCODING_NAME;
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MailboxMessageAssertTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MailboxMessageAssertTest.java
index 703eae0..02b0c8b 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MailboxMessageAssertTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MailboxMessageAssertTest.java
@@ -48,11 +48,11 @@ class MailboxMessageAssertTest {
         Date date = new Date();
 
         SimpleMailboxMessage message1 = new SimpleMailboxMessage(MESSAGE_ID, date, headerString.length() + bodyString.length(),
-            headerString.length(), new SharedByteArrayInputStream((headerString + bodyString).getBytes()), new Flags(), new PropertyBuilder(), MAILBOX_ID);
+            headerString.length(), new SharedByteArrayInputStream((headerString + bodyString).getBytes()), new Flags(), new PropertyBuilder().build(), MAILBOX_ID);
         message1.setUid(UID);
 
         SimpleMailboxMessage message2 = new SimpleMailboxMessage(MESSAGE_ID, date, headerString.length() + bodyString.length(),
-            headerString.length(), new SharedByteArrayInputStream((headerString + bodyString).getBytes()), new Flags(), new PropertyBuilder(), MAILBOX_ID);
+            headerString.length(), new SharedByteArrayInputStream((headerString + bodyString).getBytes()), new Flags(), new PropertyBuilder().build(), MAILBOX_ID);
         message2.setUid(UID);
 
         MessageAssert.assertThat(message1).isEqualTo(message2, MessageMapper.FetchType.Full);
@@ -65,12 +65,12 @@ class MailboxMessageAssertTest {
         Date date = new Date();
 
         SimpleMailboxMessage message1 = new SimpleMailboxMessage(MESSAGE_ID, date, headerString.length() + bodyString.length(),
-            headerString.length(), new SharedByteArrayInputStream((headerString + bodyString).getBytes()), new Flags(), new PropertyBuilder(), MAILBOX_ID);
+            headerString.length(), new SharedByteArrayInputStream((headerString + bodyString).getBytes()), new Flags(), new PropertyBuilder().build(), MAILBOX_ID);
         message1.setUid(UID);
 
         bodyString = "work\n.\n";
         SimpleMailboxMessage message2 = new SimpleMailboxMessage(MESSAGE_ID, date, headerString.length() + bodyString.length(),
-            headerString.length(), new SharedByteArrayInputStream((headerString + bodyString).getBytes()), new Flags(), new PropertyBuilder(), MAILBOX_ID);
+            headerString.length(), new SharedByteArrayInputStream((headerString + bodyString).getBytes()), new Flags(), new PropertyBuilder().build(), MAILBOX_ID);
         message2.setUid(UID);
 
         MessageAssert.assertThat(message1).isEqualTo(message2, MessageMapper.FetchType.Headers);
@@ -83,12 +83,12 @@ class MailboxMessageAssertTest {
         Date date = new Date();
 
         SimpleMailboxMessage message1 = new SimpleMailboxMessage(MESSAGE_ID, date, headerString.length() + bodyString.length(),
-            headerString.length(), new SharedByteArrayInputStream((headerString + bodyString).getBytes()), new Flags(), new PropertyBuilder(), MAILBOX_ID);
+            headerString.length(), new SharedByteArrayInputStream((headerString + bodyString).getBytes()), new Flags(), new PropertyBuilder().build(), MAILBOX_ID);
         message1.setUid(UID);
 
         bodyString = "work\n.\n";
         SimpleMailboxMessage message2 = new SimpleMailboxMessage(MESSAGE_ID, date, headerString.length() + bodyString.length(),
-            headerString.length(), new SharedByteArrayInputStream((headerString + bodyString).getBytes()), new Flags(), new PropertyBuilder(), MAILBOX_ID);
+            headerString.length(), new SharedByteArrayInputStream((headerString + bodyString).getBytes()), new Flags(), new PropertyBuilder().build(), MAILBOX_ID);
         message2.setUid(UID);
 
         assertThatThrownBy(() -> MessageAssert.assertThat(message1).isEqualTo(message2, MessageMapper.FetchType.Body))
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageIdMapperTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageIdMapperTest.java
index 3abb0c9..6f97388 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageIdMapperTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageIdMapperTest.java
@@ -992,7 +992,7 @@ public abstract class MessageIdMapperTest {
                 bodyStart, 
                 new SharedByteArrayInputStream(content.getBytes()), 
                 new Flags(), 
-                propertyBuilder, 
+                propertyBuilder.build(),
                 mailbox.getMailboxId());
     }
 }
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java
index 9907c5e..0a59a33 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java
@@ -800,27 +800,26 @@ public abstract class MessageMapperTest {
         propBuilder.setMediaType("text");
         propBuilder.setSubType("html");
         propBuilder.setTextualLineCount(2L);
-        propBuilder.setProperty(StandardNames.NAMESPACE_RFC_2045, StandardNames.MIME_CONTENT_TRANSFER_ENCODING_NAME, "7bit");
-        propBuilder.setProperty(StandardNames.MIME_CONTENT_TYPE_PARAMETER_SPACE, StandardNames.MIME_CONTENT_TYPE_PARAMETER_CHARSET_NAME, "US-ASCII");
+        propBuilder.setContentTransferEncoding("7bit");
+        propBuilder.setCharset("US-ASCII");
 
         MailboxMessage messageWithProperties = createMessage(benwaWorkMailbox, mapperProvider.generateMessageId(), "Subject: messagePropertiesShouldBeStored \n\nBody\n.\n", BODY_START, propBuilder);
         MessageMetaData messageMetaData = messageMapper.add(benwaInboxMailbox, messageWithProperties);
         MailboxMessage message = messageMapper.findInMailbox(benwaInboxMailbox, MessageRange.one(messageMetaData.getUid()), FetchType.Body, 1).next();
 
-        assertProperties(message.getProperties()).containsOnly(propBuilder.toProperties());
+        assertProperties(message.getProperties().toProperties()).containsOnly(propBuilder.toProperties());
     }
     
     @Test
     void messagePropertiesShouldBeStoredWhenDuplicateEntries() throws Exception {
         PropertyBuilder propBuilder = new PropertyBuilder();
-        propBuilder.setProperty(StandardNames.MIME_CONTENT_LANGUAGE_SPACE, StandardNames.MIME_CONTENT_LANGUAGE_NAME, "us");
-        propBuilder.setProperty(StandardNames.MIME_CONTENT_LANGUAGE_SPACE, StandardNames.MIME_CONTENT_LANGUAGE_NAME, "fr");
+        propBuilder.setContentLanguage(ImmutableList.of("us", "fr"));
 
         MailboxMessage messageWithProperties = createMessage(benwaWorkMailbox, mapperProvider.generateMessageId(), "Subject: messagePropertiesShouldBeStoredWhenDuplicateEntries \n\nBody\n.\n", BODY_START, propBuilder);
         MessageMetaData messageMetaData = messageMapper.add(benwaInboxMailbox, messageWithProperties);
         MailboxMessage message = messageMapper.findInMailbox(benwaInboxMailbox, MessageRange.one(messageMetaData.getUid()), FetchType.Body, 1).next();
 
-        assertProperties(message.getProperties()).containsOnly(propBuilder.toProperties());
+        assertProperties(message.getProperties().toProperties()).containsOnly(propBuilder.toProperties());
     }
 
     @Test
@@ -828,7 +827,7 @@ public abstract class MessageMapperTest {
         MailboxMessage messageWithProperties = createMessage(benwaWorkMailbox, mapperProvider.generateMessageId(), "Subject: messagePropertiesShouldBeStoredWhenNoProperty \n\nBody\n.\n", BODY_START, new PropertyBuilder());
         MessageMetaData messageMetaData = messageMapper.add(benwaInboxMailbox, messageWithProperties);
         MailboxMessage message = messageMapper.findInMailbox(benwaInboxMailbox, MessageRange.one(messageMetaData.getUid()), FetchType.Body, 1).next();
-        assertThat(message.getProperties()).isEmpty();
+        assertThat(message.getProperties().toProperties()).isEmpty();
     }
 
     @Test
@@ -1251,6 +1250,6 @@ public abstract class MessageMapperTest {
     }
     
     private MailboxMessage createMessage(Mailbox mailbox, MessageId messageId, String content, int bodyStart, PropertyBuilder propertyBuilder) {
-        return new SimpleMailboxMessage(messageId, new Date(), content.length(), bodyStart, new SharedByteArrayInputStream(content.getBytes()), new Flags(), propertyBuilder, mailbox.getMailboxId());
+        return new SimpleMailboxMessage(messageId, new Date(), content.length(), bodyStart, new SharedByteArrayInputStream(content.getBytes()), new Flags(), propertyBuilder.build(), mailbox.getMailboxId());
     }
 }
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMoveTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMoveTest.java
index a9b2182..d0260f5 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMoveTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMoveTest.java
@@ -143,6 +143,6 @@ public abstract class MessageMoveTest {
     }
     
     private MailboxMessage createMessage(Mailbox mailbox, MessageId messageId, String content, int bodyStart, PropertyBuilder propertyBuilder) {
-        return new SimpleMailboxMessage(messageId, new Date(), content.length(), bodyStart, new SharedByteArrayInputStream(content.getBytes()), new Flags(), propertyBuilder, mailbox.getMailboxId());
+        return new SimpleMailboxMessage(messageId, new Date(), content.length(), bodyStart, new SharedByteArrayInputStream(content.getBytes()), new Flags(), propertyBuilder.build(), mailbox.getMailboxId());
     }
 }
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageWithAttachmentMapperTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageWithAttachmentMapperTest.java
index 0c241b6..a08cb2b 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageWithAttachmentMapperTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageWithAttachmentMapperTest.java
@@ -193,10 +193,10 @@ public abstract class MessageWithAttachmentMapperTest {
     }
 
     private SimpleMailboxMessage createMessage(Mailbox mailbox, MessageId messageId, String content, int bodyStart, PropertyBuilder propertyBuilder, List<MessageAttachmentMetadata> attachments) {
-        return new SimpleMailboxMessage(messageId, new Date(), content.length(), bodyStart, new SharedByteArrayInputStream(content.getBytes()), new Flags(), propertyBuilder, mailbox.getMailboxId(), attachments);
+        return new SimpleMailboxMessage(messageId, new Date(), content.length(), bodyStart, new SharedByteArrayInputStream(content.getBytes()), new Flags(), propertyBuilder.build(), mailbox.getMailboxId(), attachments);
     }
 
     private SimpleMailboxMessage createMessage(Mailbox mailbox, MessageId messageId, String content, int bodyStart, PropertyBuilder propertyBuilder) {
-        return new SimpleMailboxMessage(messageId, new Date(), content.length(), bodyStart, new SharedByteArrayInputStream(content.getBytes()), new Flags(), propertyBuilder, mailbox.getMailboxId());
+        return new SimpleMailboxMessage(messageId, new Date(), content.length(), bodyStart, new SharedByteArrayInputStream(content.getBytes()), new Flags(), propertyBuilder.build(), mailbox.getMailboxId());
     }
 }
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MetadataMapAssertTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MetadataMapAssertTest.java
index af057a0..be33351 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MetadataMapAssertTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MetadataMapAssertTest.java
@@ -53,7 +53,7 @@ class MetadataMapAssertTest {
     @BeforeEach
     void setUp() {
         message1 = new SimpleMailboxMessage(MESSAGE_ID, DATE, HEADER_STRING.length() + BODY_STRING.length(),
-            HEADER_STRING.length(), new SharedByteArrayInputStream((HEADER_STRING + BODY_STRING).getBytes()), new Flags(), new PropertyBuilder(), MAILBOX_ID);
+            HEADER_STRING.length(), new SharedByteArrayInputStream((HEADER_STRING + BODY_STRING).getBytes()), new Flags(), new PropertyBuilder().build(), MAILBOX_ID);
         message1.setUid(UID);
         message1.setModSeq(MODSEQ);
     }
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMailboxMessageTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMailboxMessageTest.java
index 3b7a0d1..c3ed460 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMailboxMessageTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMailboxMessageTest.java
@@ -114,7 +114,7 @@ class SimpleMailboxMessageTest {
             BODY_START_OCTET,
             CONTENT_STREAM,
             new Flags(),
-            propertyBuilder,
+            propertyBuilder.build(),
             TEST_ID);
 
         SimpleMailboxMessage copy = SimpleMailboxMessage.copy(TestId.of(1337), original);
@@ -135,7 +135,7 @@ class SimpleMailboxMessageTest {
         return new SimpleMailboxMessage(new DefaultMessageId(), Calendar.getInstance().getTime(),
             content.length(), BODY_START_OCTET, new SharedByteArrayInputStream(
                     content.getBytes(MESSAGE_CHARSET)), new Flags(),
-            new PropertyBuilder(), TEST_ID);
+            new PropertyBuilder().build(), TEST_ID);
     }
 
     @Test
@@ -163,7 +163,7 @@ class SimpleMailboxMessageTest {
             .size(SIZE)
             .content(CONTENT_STREAM)
             .flags(new Flags())
-            .propertyBuilder(new PropertyBuilder())
+            .properties(new PropertyBuilder())
             .build();
     }
 
@@ -195,7 +195,7 @@ class SimpleMailboxMessageTest {
             .size(SIZE)
             .content(CONTENT_STREAM)
             .flags(flags)
-            .propertyBuilder(propertyBuilder)
+            .properties(propertyBuilder)
             .addAttachments(ImmutableList.of(messageAttachment))
             .build();
         String messageContent = IOUtils.toString(message.getFullContent(), StandardCharsets.UTF_8);
@@ -208,7 +208,7 @@ class SimpleMailboxMessageTest {
             soft.assertThat(message.getFullContentOctets()).isEqualTo(SIZE);
             soft.assertThat(messageContent).isEqualTo(MESSAGE_CONTENT);
             soft.assertThat(message.createFlags()).isEqualTo(flags);
-            soft.assertThat(message.getProperties()).isEqualTo(propertyBuilder.toProperties());
+            soft.assertThat(message.getProperties().toProperties()).isEqualTo(propertyBuilder.toProperties());
             soft.assertThat(message.getUid()).isEqualTo(uid);
             soft.assertThat(message.getModSeq()).isEqualTo(modseq);
             soft.assertThat(message.getAttachments()).containsOnly(messageAttachment);
@@ -225,7 +225,7 @@ class SimpleMailboxMessageTest {
                 .size(SIZE)
                 .content(CONTENT_STREAM)
                 .flags(new Flags())
-                .propertyBuilder(new PropertyBuilder())
+                .properties(new PropertyBuilder())
                 .build())
             .isInstanceOf(NullPointerException.class);
     }
@@ -240,7 +240,7 @@ class SimpleMailboxMessageTest {
                 .size(SIZE)
                 .content(CONTENT_STREAM)
                 .flags(new Flags())
-                .propertyBuilder(new PropertyBuilder())
+                .properties(new PropertyBuilder())
                 .build())
             .isInstanceOf(NullPointerException.class);
     }
@@ -254,7 +254,7 @@ class SimpleMailboxMessageTest {
                 .size(SIZE)
                 .content(CONTENT_STREAM)
                 .flags(new Flags())
-                .propertyBuilder(new PropertyBuilder())
+                .properties(new PropertyBuilder())
                 .build())
             .isInstanceOf(NullPointerException.class);
     }
@@ -269,7 +269,7 @@ class SimpleMailboxMessageTest {
                 .size(SIZE)
                 .content(CONTENT_STREAM)
                 .flags(new Flags())
-                .propertyBuilder(new PropertyBuilder())
+                .properties(new PropertyBuilder())
                 .build())
             .isInstanceOf(NullPointerException.class);
     }
@@ -284,7 +284,7 @@ class SimpleMailboxMessageTest {
                 .bodyStartOctet(BODY_START_OCTET)
                 .content(CONTENT_STREAM)
                 .flags(new Flags())
-                .propertyBuilder(new PropertyBuilder())
+                .properties(new PropertyBuilder())
                 .build())
             .isInstanceOf(NullPointerException.class);
     }
@@ -299,7 +299,7 @@ class SimpleMailboxMessageTest {
                 .bodyStartOctet(BODY_START_OCTET)
                 .size(SIZE)
                 .flags(new Flags())
-                .propertyBuilder(new PropertyBuilder())
+                .properties(new PropertyBuilder())
                 .build())
             .isInstanceOf(NullPointerException.class);
     }
@@ -314,7 +314,7 @@ class SimpleMailboxMessageTest {
                 .bodyStartOctet(BODY_START_OCTET)
                 .size(SIZE)
                 .content(CONTENT_STREAM)
-                .propertyBuilder(new PropertyBuilder())
+                .properties(new PropertyBuilder())
                 .build())
             .isInstanceOf(NullPointerException.class);
     }
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/utils/ApplicableFlagCalculatorTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/utils/ApplicableFlagCalculatorTest.java
index db11e31..1632ce3 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/utils/ApplicableFlagCalculatorTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/utils/ApplicableFlagCalculatorTest.java
@@ -105,7 +105,7 @@ class ApplicableFlagCalculatorTest {
         int bodyStart = 10;
 
         return new SimpleMailboxMessage(new DefaultMessageId(), new Date(), content.length(), bodyStart,
-            new SharedByteArrayInputStream(content.getBytes()), messageFlags, new PropertyBuilder(), TestId.of(1));
+            new SharedByteArrayInputStream(content.getBytes()), messageFlags, new PropertyBuilder().build(), TestId.of(1));
     }
 
     private Flags getDefaultApplicableFlag() {
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/search/ListeningMessageSearchIndexContract.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/search/ListeningMessageSearchIndexContract.java
index f9ab723..184dfcc 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/search/ListeningMessageSearchIndexContract.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/search/ListeningMessageSearchIndexContract.java
@@ -52,7 +52,7 @@ public interface ListeningMessageSearchIndexContract {
         .internalDate(new Date(1433628000000L))
         .size(SIZE)
         .content(new SharedByteArrayInputStream("message".getBytes(StandardCharsets.UTF_8)))
-        .propertyBuilder(new PropertyBuilder())
+        .properties(new PropertyBuilder())
         .modseq(MOD_SEQ);
     
     ListeningMessageSearchIndex testee();
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MailboxesRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MailboxesRoutesTest.java
index b64e4ab..1bbbbdf 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MailboxesRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MailboxesRoutesTest.java
@@ -519,7 +519,7 @@ class MailboxesRoutesTest {
                     .internalDate(new Date(ZonedDateTime.parse("2018-02-15T15:54:02Z").toEpochSecond()))
                     .bodyStartOctet(0)
                     .flags(new Flags("myFlags"))
-                    .propertyBuilder(new PropertyBuilder())
+                    .properties(new PropertyBuilder())
                     .mailboxId(mailboxId)
                     .build();
 
@@ -938,7 +938,7 @@ class MailboxesRoutesTest {
                     .internalDate(new Date(ZonedDateTime.parse("2018-02-15T15:54:02Z").toEpochSecond()))
                     .bodyStartOctet(0)
                     .flags(new Flags("myFlags"))
-                    .propertyBuilder(new PropertyBuilder())
+                    .properties(new PropertyBuilder())
                     .mailboxId(mailboxId)
                     .build();
 
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java
index d96f4d8..fbd28e9 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java
@@ -1529,7 +1529,7 @@ class UserMailboxesRoutesTest {
                     .internalDate(new Date(ZonedDateTime.parse("2018-02-15T15:54:02Z").toEpochSecond()))
                     .bodyStartOctet(0)
                     .flags(new Flags("myFlags"))
-                    .propertyBuilder(new PropertyBuilder())
+                    .properties(new PropertyBuilder())
                     .mailboxId(mailboxId)
                     .build();
 


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org