use of com.zimbra.cs.mailbox.CalendarItem.Instance in project zm-mailbox by Zimbra.
the class CheckRecurConflicts method getConflicts.
private static UserConflicts getConflicts(FreeBusy fb, List<Instance> instances) throws ServiceException {
UserConflicts conflicts = new UserConflicts(fb.getName());
Iterator<Interval> ivalIter = fb.iterator();
Iterator<Instance> instIter = instances.iterator();
Interval ival = ivalIter.hasNext() ? ivalIter.next() : null;
Instance inst = instIter.hasNext() ? instIter.next() : null;
// f/b status of the previous overlap between instance and interval, if previous and current overlaps
// are with the same instance
String prevStatus = null;
while (ival != null && inst != null) {
String status = ival.getStatus();
if (IcalXmlStrMap.FBTYPE_FREE.equals(status)) {
ival = ivalIter.hasNext() ? ivalIter.next() : null;
continue;
}
if (!inst.hasStart() || !inst.hasEnd()) {
inst = instIter.hasNext() ? instIter.next() : null;
prevStatus = null;
continue;
}
long instStart = inst.getStart();
long instEnd = inst.getEnd();
long ivalStart = ival.getStart();
long ivalEnd = ival.getEnd();
// If instance is before interval, go to next instance.
if (instEnd <= ivalStart) {
inst = instIter.hasNext() ? instIter.next() : null;
prevStatus = null;
continue;
}
// If interval is before instance, go to next interval.
if (ivalEnd <= instStart) {
ival = ivalIter.hasNext() ? ivalIter.next() : null;
prevStatus = null;
continue;
}
// We have an overlap!
if (prevStatus != null)
status = FreeBusy.chooseBusier(status, prevStatus);
conflicts.put(inst, status);
prevStatus = status;
// Advance to the next interval or instance.
if (ivalEnd < instEnd) {
// Go to the next interval if its end time is earlier than the instance end time, because
// the next interval may still overlap the same instance.
ival = ivalIter.hasNext() ? ivalIter.next() : null;
} else {
// instEnd >= ivalEnd
// If instance end time is at or earlier than interval end time, go to the next
// instance. Clear prevStatus because we're changing instance.
inst = instIter.hasNext() ? instIter.next() : null;
prevStatus = null;
}
}
return conflicts;
}
use of com.zimbra.cs.mailbox.CalendarItem.Instance in project zm-mailbox by Zimbra.
the class CompleteTaskInstance method handle.
@Override
public Element handle(Element request, Map<String, Object> context) throws ServiceException {
ZimbraSoapContext zsc = getZimbraSoapContext(context);
Mailbox mbox = getRequestedMailbox(zsc);
OperationContext octxt = getOperationContext(zsc, context);
ItemId iid = new ItemId(request.getAttribute(MailConstants.A_ID), zsc);
Element exceptElem = request.getElement(MailConstants.E_CAL_EXCEPTION_ID);
mbox.lock.lock();
try {
CalendarItem calItem = mbox.getCalendarItemById(octxt, iid.getId());
if (calItem == null) {
throw MailServiceException.NO_SUCH_CALITEM(iid.toString(), "Could not find calendar item");
}
if (!(calItem instanceof Task)) {
throw MailServiceException.NO_SUCH_CALITEM(iid.toString(), "Calendar item is not a task");
}
Invite inv = calItem.getDefaultInviteOrNull();
if (inv == null) {
throw MailServiceException.NO_SUCH_CALITEM(iid.toString(), "No default invite found");
}
if (!inv.isRecurrence()) {
throw ServiceException.INVALID_REQUEST("Task is not a recurring task", null);
}
ParsedDateTime recurStart = inv.getStartTime();
if (recurStart == null) {
throw ServiceException.INVALID_REQUEST("Recurring task is missing start time", null);
}
// the instance being marked complete
TimeZoneMap tzmap = inv.getTimeZoneMap();
Element tzElem = request.getOptionalElement(MailConstants.E_CAL_TZ);
ICalTimeZone tz = null;
if (tzElem != null) {
tz = CalendarUtils.parseTzElement(tzElem);
tzmap.add(tz);
}
ParsedDateTime exceptDt = CalendarUtils.parseDateTime(exceptElem, tzmap);
if (exceptDt.getUtcTime() != recurStart.getUtcTime()) {
throw MailServiceException.INVITE_OUT_OF_DATE(iid.toString());
}
// Create a new single-instance task for completed date.
Invite completed = createCompletedInstanceInvite(inv, exceptDt);
mbox.addInvite(octxt, completed, calItem.getFolderId());
// Update recurrence's start date to the next instance start date.
long oldStart = recurStart.getUtcTime();
long newStart = -1;
Collection<Instance> instances = calItem.expandInstances(oldStart, Long.MAX_VALUE, false);
for (Instance inst : instances) {
if (inst.getStart() > oldStart) {
newStart = inst.getStart();
break;
}
}
if (newStart != -1) {
// Update DTSTART to newStart.
ParsedDateTime newStartDt = ParsedDateTime.fromUTCTime(newStart);
newStartDt.toTimeZone(inv.getStartTime().getTimeZone());
newStartDt.setHasTime(recurStart.hasTime());
// Update DUE.
ParsedDuration dur = inv.getEffectiveDuration();
if (dur != null) {
ParsedDateTime due = newStartDt.add(dur);
inv.setDtEnd(due);
}
inv.setDtStart(newStartDt);
inv.setSeqNo(inv.getSeqNo() + 1);
inv.setDtStamp(System.currentTimeMillis());
mbox.addInvite(octxt, inv, calItem.getFolderId());
} else {
// No more instance left. Delete the recurring task.
mbox.delete(octxt, calItem.getId(), calItem.getType());
}
} finally {
mbox.lock.release();
}
// response
Element response = getResponseElement(zsc);
return response;
}
use of com.zimbra.cs.mailbox.CalendarItem.Instance in project zm-mailbox by Zimbra.
the class XmlFormatter method formatCallback.
@Override
public void formatCallback(UserServletContext context) throws ServiceException, IOException {
Element elt = getFactory().createElement("items");
ItemIdFormatter ifmt = new ItemIdFormatter(context.getAuthAccount(), context.targetMailbox, false);
Iterator<? extends MailItem> iterator = null;
try {
long start = context.getStartTime();
long end = context.getEndTime();
boolean hasTimeRange = start != TIME_UNSPECIFIED && end != TIME_UNSPECIFIED;
iterator = getMailItems(context, start, end, Integer.MAX_VALUE);
// this is lame
while (iterator.hasNext()) {
MailItem item = iterator.next();
if (item instanceof CalendarItem && hasTimeRange) {
// Skip appointments that have no instance in the time range.
CalendarItem calItem = (CalendarItem) item;
Collection<Instance> instances = calItem.expandInstances(start, end, false);
if (instances.isEmpty())
continue;
}
ToXML.encodeItem(elt, ifmt, context.opContext, item, ToXML.NOTIFY_FIELDS);
}
context.resp.getOutputStream().write(elt.toUTF8());
} finally {
if (iterator instanceof QueryResultIterator)
((QueryResultIterator) iterator).finished();
}
}
use of com.zimbra.cs.mailbox.CalendarItem.Instance in project zm-mailbox by Zimbra.
the class Invite method getExdates.
public List<Instance> getExdates() {
List<Instance> exdates = Lists.newArrayList();
IRecurrence recurrence = getRecurrence();
if (recurrence == null) {
return exdates;
}
for (Iterator<?> iter = recurrence.subRulesIterator(); iter != null && iter.hasNext(); ) {
IRecurrence cur = (IRecurrence) iter.next();
switch(cur.getType()) {
case Recurrence.TYPE_SINGLE_DATES:
Recurrence.SingleDates sd = (Recurrence.SingleDates) cur;
RdateExdate exdate = sd.getRdateExdate();
if (exdate.isEXDATE()) {
exdates.addAll(sd.expandInstances(getMailItemId()));
} else {
ZimbraLog.calendar.debug("RDATE '%s' ignored", exdate);
}
break;
case Recurrence.TYPE_REPEATING:
// See http://tools.ietf.org/html/rfc5545 A.3. Deprecated Features
// 1. The "EXRULE" property can no longer be specified in a component.
ZimbraLog.calendar.debug("EXRULE ignored - no longer supported in rfc5545");
break;
}
}
return exdates;
}
use of com.zimbra.cs.mailbox.CalendarItem.Instance in project zm-mailbox by Zimbra.
the class OrganizerInviteChanges method getExdatesOnlyInFirst.
public List<Instance> getExdatesOnlyInFirst(List<Instance> first, List<Instance> second) {
List<Instance> newList = Lists.newArrayList(first);
Iterator<Instance> iter = newList.iterator();
while (iter.hasNext()) {
Instance curr = iter.next();
for (Instance fromSecond : second) {
if (fromSecond.sameTime(curr)) {
iter.remove();
break;
}
}
}
return newList;
}
Aggregations