All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.james.jmap.model.Message Maven / Gradle / Ivy

/****************************************************************
 * Licensed to the Apache Software Foundation (ASF) under one   *
 * or more contributor license agreements.  See the NOTICE file *
 * distributed with this work for additional information        *
 * regarding copyright ownership.  The ASF licenses this file   *
 * to you under the Apache License, Version 2.0 (the            *
 * "License"); you may not use this file except in compliance   *
 * with the License.  You may obtain a copy of the License at   *
 *                                                              *
 *   http://www.apache.org/licenses/LICENSE-2.0                 *
 *                                                              *
 * Unless required by applicable law or agreed to in writing,   *
 * software distributed under the License is distributed on an  *
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
 * KIND, either express or implied.  See the License for the    *
 * specific language governing permissions and limitations      *
 * under the License.                                           *
 ****************************************************************/

package org.apache.james.jmap.model;

import java.time.ZonedDateTime;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Predicate;

import org.apache.james.jmap.methods.GetMessagesMethod;
import org.apache.james.jmap.methods.JmapResponseWriterImpl;
import org.apache.james.mailbox.model.MailboxId;
import org.apache.james.mailbox.model.MessageId;

import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;

@JsonDeserialize(builder = Message.Builder.class)
@JsonFilter(JmapResponseWriterImpl.PROPERTIES_FILTER)
public class Message {

    public static Builder builder() {
        return new Builder();
    }

    @JsonPOJOBuilder(withPrefix = "")
    public static class Builder {
        private MessageId id;
        private BlobId blobId;
        private String threadId;
        private ImmutableList mailboxIds;
        private String inReplyToMessageId;
        private boolean isUnread;
        private boolean isFlagged;
        private boolean isAnswered;
        private boolean isDraft;
        private ImmutableMap headers;
        private Emailer from;
        private final ImmutableList.Builder to;
        private final ImmutableList.Builder cc;
        private final ImmutableList.Builder bcc;
        private final ImmutableList.Builder replyTo;
        private String subject;
        private ZonedDateTime date;
        private Long size;
        private String preview;
        private Optional textBody = Optional.empty();
        private Optional htmlBody = Optional.empty();
        private final ImmutableList.Builder attachments;
        private final ImmutableMap.Builder attachedMessages;

        private Builder() {
            to = ImmutableList.builder();
            cc = ImmutableList.builder();
            bcc = ImmutableList.builder();
            replyTo = ImmutableList.builder();
            attachments = ImmutableList.builder();
            attachedMessages = ImmutableMap.builder();
        }

        public Builder id(MessageId id) {
            this.id = id;
            return this;
        }

        public Builder blobId(BlobId blobId) {
            this.blobId = blobId;
            return this;
        }

        public Builder threadId(String threadId) {
            this.threadId = threadId;
            return this;
        }

        @JsonIgnore
        public Builder mailboxId(MailboxId mailboxId) {
            return this.fluentMailboxIds(mailboxId);
        }

        @JsonIgnore
        public Builder fluentMailboxIds(MailboxId... mailboxIds) {
            return this.mailboxIds(Arrays.asList((mailboxIds)));
        }

        public Builder mailboxIds(Collection mailboxIds) {
            this.mailboxIds = ImmutableList.copyOf(mailboxIds);
            return this;
        }

        public Builder inReplyToMessageId(String inReplyToMessageId) {
            this.inReplyToMessageId = inReplyToMessageId;
            return this;
        }

        public Builder isUnread(boolean isUnread) {
            this.isUnread = isUnread;
            return this;
        }

        public Builder isFlagged(boolean isFlagged) {
            this.isFlagged = isFlagged;
            return this;
        }

        public Builder isAnswered(boolean isAnswered) {
            this.isAnswered = isAnswered;
            return this;
        }

        public Builder isDraft(boolean isDraft) {
            this.isDraft = isDraft;
            return this;
        }

        public Builder headers(ImmutableMap headers) {
            this.headers = headers;
            return this;
        }

        public Builder from(Emailer from) {
            this.from = from;
            return this;
        }

        public Builder to(List to) {
            this.to.addAll(to);
            return this;
        }

        public Builder cc(List cc) {
            this.cc.addAll(cc);
            return this;
        }

        public Builder bcc(List bcc) {
            this.bcc.addAll(bcc);
            return this;
        }

        public Builder replyTo(List replyTo) {
            this.replyTo.addAll(replyTo);
            return this;
        }

        public Builder subject(String subject) {
            this.subject = subject;
            return this;
        }

        public Builder date(ZonedDateTime date) {
            this.date = date;
            return this;
        }

        public Builder size(long size) {
            this.size = size;
            return this;
        }

        public Builder preview(String preview) {
            this.preview = preview;
            return this;
        }

        public Builder textBody(Optional textBody) {
            this.textBody = textBody;
            return this;
        }

        public Builder htmlBody(Optional htmlBody) {
            this.htmlBody = htmlBody;
            return this;
        }

        public Builder attachments(List attachments) {
            this.attachments.addAll(attachments);
            return this;
        }

        public Builder attachedMessages(Map attachedMessages) {
            this.attachedMessages.putAll(attachedMessages);
            return this;
        }

        public Message build() {
            Preconditions.checkState(id != null, "'id' is mandatory");
            Preconditions.checkState(blobId != null, "'blobId' is mandatory");
            Preconditions.checkState(!Strings.isNullOrEmpty(threadId), "'threadId' is mandatory");
            Preconditions.checkState(mailboxIds != null, "'mailboxIds' is mandatory");
            Preconditions.checkState(headers != null, "'headers' is mandatory");
            Preconditions.checkState(size != null, "'size' is mandatory");
            Preconditions.checkState(date != null, "'date' is mandatory");
            Preconditions.checkState(!Strings.isNullOrEmpty(preview), "'preview' is mandatory");
            ImmutableList attachments = this.attachments.build();
            ImmutableMap attachedMessages = this.attachedMessages.build();
            Preconditions.checkState(areAttachedMessagesKeysInAttachments(attachments, attachedMessages), "'attachedMessages' keys must be in 'attachements'");
            boolean hasAttachment = hasAttachment(attachments);

            return new Message(id, blobId, threadId, mailboxIds, Optional.ofNullable(inReplyToMessageId), isUnread, isFlagged, isAnswered, isDraft, hasAttachment, headers, Optional.ofNullable(from),
                    to.build(), cc.build(), bcc.build(), replyTo.build(), subject, date, size, preview, textBody, htmlBody, attachments, attachedMessages);
        }
    }

    protected static boolean areAttachedMessagesKeysInAttachments(ImmutableList attachments, ImmutableMap attachedMessages) {
        return attachedMessages.isEmpty() || attachedMessages.keySet().stream()
                .anyMatch(inAttachments(attachments));
    }

    private static Predicate inAttachments(ImmutableList attachments) {
        return (key) -> {
            return attachments.stream()
                .map(Attachment::getBlobId)
                .anyMatch(blobId -> blobId.equals(key));
        };
    }

    private static boolean hasAttachment(List attachments) {
        return attachments.stream()
                .filter(attachment -> !attachment.isInlinedWithCid())
                .findAny()
                .isPresent();
    }

    private final MessageId id;
    private final BlobId blobId;
    private final String threadId;
    private final ImmutableList mailboxIds;
    private final Optional inReplyToMessageId;
    private final boolean isUnread;
    private final boolean isFlagged;
    private final boolean isAnswered;
    private final boolean isDraft;
    private final boolean hasAttachment;
    @JsonFilter(GetMessagesMethod.HEADERS_FILTER)
    private final ImmutableMap headers;
    private final Optional from;
    private final ImmutableList to;
    private final ImmutableList cc;
    private final ImmutableList bcc;
    private final ImmutableList replyTo;
    private final String subject;
    private final ZonedDateTime date;
    private final long size;
    private final String preview;
    private final Optional textBody;
    private final Optional htmlBody;
    private final ImmutableList attachments;
    private final ImmutableMap attachedMessages;

    @VisibleForTesting Message(MessageId id, BlobId blobId, String threadId, ImmutableList mailboxIds, Optional inReplyToMessageId, boolean isUnread, boolean isFlagged, boolean isAnswered, boolean isDraft, boolean hasAttachment, ImmutableMap headers, Optional from,
            ImmutableList to, ImmutableList cc, ImmutableList bcc, ImmutableList replyTo, String subject, ZonedDateTime date, long size, String preview, Optional textBody, Optional htmlBody, ImmutableList attachments,
            ImmutableMap attachedMessages) {
        this.id = id;
        this.blobId = blobId;
        this.threadId = threadId;
        this.mailboxIds = mailboxIds;
        this.inReplyToMessageId = inReplyToMessageId;
        this.isUnread = isUnread;
        this.isFlagged = isFlagged;
        this.isAnswered = isAnswered;
        this.isDraft = isDraft;
        this.hasAttachment = hasAttachment;
        this.headers = headers;
        this.from = from;
        this.to = to;
        this.cc = cc;
        this.bcc = bcc;
        this.replyTo = replyTo;
        this.subject = subject;
        this.date = date;
        this.size = size;
        this.preview = preview;
        this.textBody = textBody;
        this.htmlBody = htmlBody;
        this.attachments = attachments;
        this.attachedMessages = attachedMessages;
    }

    public MessageId getId() {
        return id;
    }

    public BlobId getBlobId() {
        return blobId;
    }

    public String getThreadId() {
        return threadId;
    }

    public ImmutableList getMailboxIds() {
        return mailboxIds;
    }

    public Optional getInReplyToMessageId() {
        return inReplyToMessageId;
    }

    public boolean isIsUnread() {
        return isUnread;
    }

    public boolean isIsFlagged() {
        return isFlagged;
    }

    public boolean isIsAnswered() {
        return isAnswered;
    }

    public boolean isIsDraft() {
        return isDraft;
    }

    public boolean isHasAttachment() {
        return hasAttachment;
    }

    public ImmutableMap getHeaders() {
        return headers;
    }

    public Optional getFrom() {
        return from;
    }

    public ImmutableList getTo() {
        return to;
    }

    public ImmutableList getCc() {
        return cc;
    }

    public ImmutableList getBcc() {
        return bcc;
    }

    public ImmutableList getReplyTo() {
        return replyTo;
    }

    public String getSubject() {
        return subject;
    }

    public ZonedDateTime getDate() {
        return date;
    }

    public long getSize() {
        return size;
    }

    public String getPreview() {
        return preview;
    }

    public Optional getTextBody() {
        return textBody;
    }

    public Optional getHtmlBody() {
        return htmlBody;
    }

    public ImmutableList getAttachments() {
        return attachments;
    }

    public ImmutableMap getAttachedMessages() {
        return attachedMessages;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy