Search in sources :

Example 1 with SetCalendarItem

use of com.zimbra.cs.redolog.op.SetCalendarItem in project zm-mailbox by Zimbra.

the class Mailbox method setCalendarItem.

/**
     * @param exceptions can be NULL
     * @return calendar item ID
     */
public CalendarItem setCalendarItem(OperationContext octxt, int folderId, int flags, String[] tags, SetCalendarItemData defaultInv, SetCalendarItemData[] exceptions, List<ReplyInfo> replies, long nextAlarm) throws ServiceException {
    flags = (flags & ~Flag.FLAGS_SYSTEM);
    SetCalendarItem redoRecorder = new SetCalendarItem(getId(), attachmentsIndexingEnabled(), flags, tags);
    boolean success = false;
    try {
        beginTransaction("setCalendarItem", octxt, redoRecorder);
        Tag.NormalizedTags ntags = new Tag.NormalizedTags(this, tags);
        // Make a single list containing default and exceptions.
        int scidLen = (defaultInv != null ? 1 : 0) + (exceptions != null ? exceptions.length : 0);
        List<SetCalendarItemData> scidList = new ArrayList<SetCalendarItemData>(scidLen);
        if (defaultInv != null) {
            defaultInv.invite.setLastFullSeqNo(defaultInv.invite.getSeqNo());
            scidList.add(defaultInv);
        }
        if (exceptions != null) {
            for (SetCalendarItemData scid : exceptions) {
                scid.invite.setLastFullSeqNo(scid.invite.getSeqNo());
                scidList.add(scid);
            }
        }
        CalendarItem calItem = null;
        // old invId information.
        if (!scidList.isEmpty()) {
            calItem = getCalendarItemByUid(octxt, scidList.get(0).invite.getUid());
            for (SetCalendarItemData scid : scidList) {
                int idBeingSet = scid.invite.getMailItemId();
                if (idBeingSet <= 0) {
                    if (calItem != null) {
                        Invite currInv = calItem.getInvite(scid.invite.getRecurId());
                        if (currInv != null) {
                            scid.invite.setInviteId(currInv.getMailItemId());
                            // Carry over local-only setting.
                            boolean currLO = currInv.isLocalOnly();
                            boolean newLO = scid.invite.isLocalOnly();
                            scid.invite.setLocalOnly(currLO && newLO);
                        } else {
                            scid.invite.setInviteId(getNextItemId(Mailbox.ID_AUTO_INCREMENT));
                        }
                    } else {
                        scid.invite.setInviteId(getNextItemId(Mailbox.ID_AUTO_INCREMENT));
                    }
                }
            }
            // if new version doesn't specify it.  (bug 41002)
            if (calItem != null && calItem.getFolderId() != Mailbox.ID_FOLDER_TRASH) {
                Invite currSeries = calItem.getDefaultInviteOrNull();
                for (SetCalendarItemData scid : scidList) {
                    if (!scid.invite.hasFreeBusy()) {
                        Invite currInv = calItem.getInvite(scid.invite.getRecurId());
                        if (currInv == null) {
                            // Inherit from series as fallback.
                            currInv = currSeries;
                        }
                        if (currInv != null && currInv.hasFreeBusy()) {
                            if (scid.invite.isTransparent()) {
                                // New invite is transparent.  New intended f/b must be free.
                                scid.invite.setFreeBusy(IcalXmlStrMap.FBTYPE_FREE);
                            } else {
                                // New invite is opaque.
                                if (IcalXmlStrMap.FBTYPE_FREE.equals(currInv.getFreeBusy())) {
                                    // An opaque invite cannot have intended f/b value of free.  Make it busy.
                                    scid.invite.setFreeBusy(IcalXmlStrMap.FBTYPE_BUSY);
                                } else {
                                    // Current intended f/b has a non-free value, so keep it.  It's better
                                    // to preserve tentative or OOO value than to unconditionally change to busy.
                                    scid.invite.setFreeBusy(currInv.getFreeBusy());
                                }
                            }
                        }
                    }
                }
            }
        }
        // trace logging
        if (!scidList.isEmpty()) {
            Invite invLog = scidList.get(0).invite;
            String idStr = calItem != null ? Integer.toString(calItem.getId()) : "(new)";
            ZimbraLog.calendar.info("setCalendarItem: id=%s, folderId=%d, subject=\"%s\", UID=%s", idStr, folderId, (invLog != null && invLog.isPublic() ? invLog.getName() : "(private)"), invLog.getUid());
        }
        redoRecorder.setData(defaultInv, exceptions, replies, nextAlarm);
        AlarmData oldAlarmData = null;
        for (SetCalendarItemData scid : scidList) {
            if (scid.message == null) {
                // the MimeMessage is fake, so we don't need to index it
                scid.invite.setDontIndexMimeMessage(true);
                String desc = scid.invite.getDescription();
                if (desc != null && desc.length() > Invite.getMaxDescInMeta()) {
                    MimeMessage mm = CalendarMailSender.createCalendarMessage(scid.invite);
                    scid.message = new ParsedMessage(mm, octxt == null ? System.currentTimeMillis() : octxt.getTimestamp(), true);
                }
            }
        }
        if (scidList.size() > 0) {
            SetCalendarItemData scid = scidList.get(0);
            if (calItem == null) {
                // ONLY create an calendar item if this is a REQUEST method...otherwise don't.
                String method = scid.invite.getMethod();
                if ("REQUEST".equals(method) || "PUBLISH".equals(method)) {
                    try {
                        calItem = createCalendarItem(folderId, flags, ntags, scid.invite.getUid(), scid.message, scid.invite, null);
                    } catch (MailServiceException e) {
                        if (e.getCode() == MailServiceException.ALREADY_EXISTS) {
                            //bug 49106 - did not find the appointment above in getCalendarItemByUid(), but the mail_item exists
                            ZimbraLog.calendar.error("failed to create calendar item; already exists. cause: " + (scidList.isEmpty() ? "no items in uid list." : "uid not found in appointment: " + scidList.get(0).invite.getUid() + " or bad mail_item type"));
                        }
                        throw e;
                    }
                } else {
                    // for now, just ignore this Invitation
                    return null;
                }
            } else {
                calItem.snapshotRevision();
                // Preserve alarm time before any modification is made to the item.
                if (calItem.getAlarmData() != null) {
                    oldAlarmData = (AlarmData) calItem.getAlarmData().clone();
                }
                calItem.setTags(flags, ntags);
                calItem.processNewInvite(scid.message, scid.invite, folderId, nextAlarm, false, true);
            }
            redoRecorder.setCalendarItemAttrs(calItem.getId(), calItem.getFolderId());
        }
        if (scidList.size() > 1) {
            // remove the first one. it is already processed
            scidList.remove(0);
            // exceptions
            calItem.processNewInviteExceptions(scidList, folderId, nextAlarm, false, false);
        }
        // Recompute alarm time after processing all Invites.
        if (nextAlarm == CalendarItem.NEXT_ALARM_KEEP_CURRENT) {
            nextAlarm = oldAlarmData != null ? oldAlarmData.getNextAt() : CalendarItem.NEXT_ALARM_FROM_NOW;
        }
        calItem.updateNextAlarm(nextAlarm, oldAlarmData, false);
        // List with one or more replies means replacing existing replies.
        if (replies != null) {
            calItem.setReplies(replies);
        }
        index.add(calItem);
        success = true;
        return calItem;
    } finally {
        endTransaction(success);
    }
}
Also used : NormalizedTags(com.zimbra.cs.mailbox.Tag.NormalizedTags) ParsedMessage(com.zimbra.cs.mime.ParsedMessage) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList) RefreshMountpoint(com.zimbra.cs.redolog.op.RefreshMountpoint) TargetConstraint(com.zimbra.cs.mailbox.MailItem.TargetConstraint) CreateMountpoint(com.zimbra.cs.redolog.op.CreateMountpoint) SetCalendarItem(com.zimbra.cs.redolog.op.SetCalendarItem) MimeMessage(javax.mail.internet.MimeMessage) SetCalendarItem(com.zimbra.cs.redolog.op.SetCalendarItem) NormalizedTags(com.zimbra.cs.mailbox.Tag.NormalizedTags) AlterItemTag(com.zimbra.cs.redolog.op.AlterItemTag) CreateTag(com.zimbra.cs.redolog.op.CreateTag) DbTag(com.zimbra.cs.db.DbTag) CreateInvite(com.zimbra.cs.redolog.op.CreateInvite) Invite(com.zimbra.cs.mailbox.calendar.Invite) AlarmData(com.zimbra.cs.mailbox.CalendarItem.AlarmData)

Aggregations

DbTag (com.zimbra.cs.db.DbTag)1 AlarmData (com.zimbra.cs.mailbox.CalendarItem.AlarmData)1 TargetConstraint (com.zimbra.cs.mailbox.MailItem.TargetConstraint)1 NormalizedTags (com.zimbra.cs.mailbox.Tag.NormalizedTags)1 Invite (com.zimbra.cs.mailbox.calendar.Invite)1 ParsedMessage (com.zimbra.cs.mime.ParsedMessage)1 AlterItemTag (com.zimbra.cs.redolog.op.AlterItemTag)1 CreateInvite (com.zimbra.cs.redolog.op.CreateInvite)1 CreateMountpoint (com.zimbra.cs.redolog.op.CreateMountpoint)1 CreateTag (com.zimbra.cs.redolog.op.CreateTag)1 RefreshMountpoint (com.zimbra.cs.redolog.op.RefreshMountpoint)1 SetCalendarItem (com.zimbra.cs.redolog.op.SetCalendarItem)1 ArrayList (java.util.ArrayList)1 CopyOnWriteArrayList (java.util.concurrent.CopyOnWriteArrayList)1 MimeMessage (javax.mail.internet.MimeMessage)1