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);
}
}
Aggregations