Search in sources :

Example 11 with ParsedDuration

use of com.zimbra.common.calendar.ParsedDuration in project zm-mailbox by Zimbra.

the class ExpandRecur method parseRecur.

protected static ParsedRecurrence parseRecur(Element request, TimeZoneMap tzmap) throws ServiceException {
    CalendarUtils.parseTimeZones(request, tzmap);
    IRecurrence recurrence = null;
    List<IException> exceptions = new ArrayList<IException>();
    for (Iterator<Element> compIter = request.elementIterator(); compIter.hasNext(); ) {
        Element elem = compIter.next();
        String elemName = elem.getName();
        boolean isCancel = false;
        if (MailConstants.E_CAL_CANCEL.equals(elemName)) {
            isCancel = true;
        } else if (!MailConstants.E_INVITE_COMPONENT.equals(elemName) && !MailConstants.E_CAL_EXCEPT.equals(elemName)) {
            continue;
        }
        RecurId recurId = null;
        Element recurIdElem = elem.getOptionalElement(MailConstants.E_CAL_EXCEPTION_ID);
        if (recurIdElem != null)
            recurId = CalendarUtils.parseRecurId(recurIdElem, tzmap);
        if (!isCancel) {
            ParsedDateTime dtStart = null;
            Element dtStartElem = elem.getElement(MailConstants.E_CAL_START_TIME);
            dtStart = CalendarUtils.parseDateTime(dtStartElem, tzmap);
            ParsedDateTime dtEnd = null;
            Element dtEndElem = elem.getOptionalElement(MailConstants.E_CAL_END_TIME);
            if (dtEndElem != null)
                dtEnd = CalendarUtils.parseDateTime(dtEndElem, tzmap);
            ParsedDuration dur = null;
            Element durElem = elem.getOptionalElement(MailConstants.E_CAL_DURATION);
            if (durElem != null)
                dur = ParsedDuration.parse(durElem);
            if (dtEnd == null && dur == null)
                throw ServiceException.INVALID_REQUEST("Must specify either " + MailConstants.E_CAL_END_TIME + " or " + MailConstants.E_CAL_DURATION + " in " + elemName, null);
            Element recurElem = elem.getOptionalElement(MailConstants.E_CAL_RECUR);
            if (recurElem != null) {
                // series with a rule
                recurrence = CalendarUtils.parseRecur(recurElem, tzmap, dtStart, dtEnd, dur, recurId);
            } else {
                // modified instance, or it has no rule and no recurrence-id
                if (dur == null && dtStart != null && dtEnd != null)
                    dur = dtEnd.difference(dtStart);
                if (recurId == null)
                    recurId = new RecurId(dtStart, RecurId.RANGE_NONE);
                exceptions.add(new ExceptionRule(recurId, dtStart, dur, null));
            }
        } else if (recurId != null) {
            // canceled instance
            exceptions.add(new CancellationRule(recurId));
        }
    }
    ParsedRecurrence parsed = new ParsedRecurrence();
    if (recurrence instanceof RecurrenceRule) {
        RecurrenceRule rrule = (RecurrenceRule) recurrence;
        for (IException exception : exceptions) {
            rrule.addException(exception);
        }
        parsed.rrule = rrule;
    } else {
        parsed.exceptions = exceptions;
    }
    return parsed;
}
Also used : RecurrenceRule(com.zimbra.cs.mailbox.calendar.Recurrence.RecurrenceRule) ParsedDuration(com.zimbra.common.calendar.ParsedDuration) CancellationRule(com.zimbra.cs.mailbox.calendar.Recurrence.CancellationRule) Element(com.zimbra.common.soap.Element) ArrayList(java.util.ArrayList) RecurId(com.zimbra.cs.mailbox.calendar.RecurId) ExceptionRule(com.zimbra.cs.mailbox.calendar.Recurrence.ExceptionRule) IRecurrence(com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence) IException(com.zimbra.cs.mailbox.calendar.Recurrence.IException) ParsedDateTime(com.zimbra.common.calendar.ParsedDateTime)

Example 12 with ParsedDuration

use of com.zimbra.common.calendar.ParsedDuration in project zm-mailbox by Zimbra.

the class WorkingHours method getRecurrenceForDay.

private static IRecurrence getRecurrenceForDay(int dayOfWeek, StartSpec startSpec, TimeRange timeRange, ICalTimeZone tz, TimeZoneMap tzmap) throws ServiceException {
    // DTSTART
    String dateStr = startSpec.getDateString(dayOfWeek);
    String dtStartStr;
    if (tz.sameAsUTC())
        dtStartStr = String.format("%sT%02d%02d00Z", dateStr, timeRange.start.hour, timeRange.start.minute);
    else
        dtStartStr = String.format("TZID=\"%s\":%sT%02d%02d00", tz.getID(), dateStr, timeRange.start.hour, timeRange.start.minute);
    ParsedDateTime dtStart;
    try {
        dtStart = ParsedDateTime.parse(dtStartStr, tzmap);
    } catch (ParseException e) {
        throw ServiceException.INVALID_REQUEST("Bad date/time value \"" + dtStartStr + "\"", e);
    }
    // DURATION
    ParsedDuration dur = timeRange.getDuration();
    // RRULE
    String dayName = DayOfWeekName.lookup(dayOfWeek);
    String ruleStr = String.format("FREQ=WEEKLY;INTERVAL=1;BYDAY=%s", dayName);
    return new Recurrence.SimpleRepeatingRule(dtStart, dur, new ZRecur(ruleStr, tzmap), null);
}
Also used : ZRecur(com.zimbra.cs.mailbox.calendar.ZRecur) ParsedDuration(com.zimbra.common.calendar.ParsedDuration) ParsedDateTime(com.zimbra.common.calendar.ParsedDateTime) ParseException(java.text.ParseException)

Example 13 with ParsedDuration

use of com.zimbra.common.calendar.ParsedDuration in project zm-mailbox by Zimbra.

the class GetCalendarItemSummaries method encodeCalendarItemInstances.

/**
     * Encodes a calendar item
     *
     * @param parent
     * @param elementName
     *         name of element to add (MailConstants .E_APPOINTMENT or MailConstants.E_TASK)
     * @param rangeStart
     *         start period to expand instances (or -1 for no start time constraint)
     * @param rangeEnd
     *         end period to expand instances (or -1 for no end time constraint)
     * @param newFormat
     *         temporary HACK - true: SearchRequest, false: GetAppointmentSummaries
     * @return
     */
static EncodeCalendarItemResult encodeCalendarItemInstances(ZimbraSoapContext lc, OperationContext octxt, CalendarItem calItem, Account acct, long rangeStart, long rangeEnd, boolean newFormat) throws ServiceException {
    EncodeCalendarItemResult toRet = new EncodeCalendarItemResult();
    ItemIdFormatter ifmt = new ItemIdFormatter(lc);
    Account authAccount = getAuthenticatedAccount(lc);
    boolean hidePrivate = !calItem.allowPrivateAccess(authAccount, lc.isUsingAdminPrivileges());
    try {
        boolean expandRanges;
        if (calItem instanceof Task) {
            expandRanges = true;
            if (rangeStart == -1 && rangeEnd == -1) {
                rangeStart = Long.MIN_VALUE;
                rangeEnd = Long.MAX_VALUE;
            }
        } else {
            expandRanges = (rangeStart != -1 && rangeEnd != -1 && rangeStart < rangeEnd);
        }
        boolean isAppointment = calItem instanceof Appointment;
        // Use the marshalling code in calendar summary cache for uniform output, when we can.
        if (isAppointment && expandRanges) {
            CalendarItemData calItemData = CalSummaryCache.reloadCalendarItemOverRange(calItem, rangeStart, rangeEnd);
            if (calItemData != null) {
                int numInstances = calItemData.getNumInstances();
                if (numInstances > 0) {
                    Element calItemElem = CacheToXML.encodeCalendarItemData(lc, ifmt, calItemData, !hidePrivate, !newFormat);
                    toRet.element = calItemElem;
                    toRet.numInstancesExpanded = numInstances;
                }
            }
            return toRet;
        }
        // But there are other cases (e.g. tasks, no time range) that require the legacy code below.
        // don't initialize until we find at least one valid instance
        Element calItemElem = null;
        Invite defaultInvite = calItem.getDefaultInviteOrNull();
        if (defaultInvite == null) {
            mLog.info("Could not load defaultinfo for calendar item with id=" + calItem.getId() + " SKIPPING");
            return toRet;
        }
        ParsedDuration defDuration = defaultInvite.getEffectiveDuration();
        // events and 1 second for non all-day.  (bug 28615)
        if (defDuration == null && !defaultInvite.isTodo()) {
            if (defaultInvite.isAllDayEvent()) {
                defDuration = ParsedDuration.ONE_DAY;
            } else {
                defDuration = ParsedDuration.ONE_SECOND;
            }
        }
        long defDurationMsecs = 0;
        if (defaultInvite.getStartTime() != null && defDuration != null) {
            ParsedDateTime s = defaultInvite.getStartTime();
            long et = s.add(defDuration).getUtcTime();
            defDurationMsecs = et - s.getUtcTime();
        }
        String defaultFba = null;
        if (calItem instanceof Appointment) {
            defaultFba = ((Appointment) calItem).getEffectiveFreeBusyActual(defaultInvite, null);
        }
        String defaultPtSt = calItem.getEffectivePartStat(defaultInvite, null);
        AlarmData alarmData = calItem.getAlarmData();
        // add all the instances:
        int numInRange = 0;
        if (expandRanges) {
            Collection<CalendarItem.Instance> instances = calItem.expandInstances(rangeStart, rangeEnd, true);
            long alarmTime = 0;
            long alarmInst = 0;
            if (alarmData != null) {
                alarmTime = alarmData.getNextAt();
                alarmInst = alarmData.getNextInstanceStart();
            }
            for (CalendarItem.Instance inst : instances) {
                try {
                    InviteInfo invId = inst.getInviteInfo();
                    Invite inv = calItem.getInvite(invId.getMsgId(), invId.getComponentId());
                    boolean showAll = !hidePrivate || inv.isPublic();
                    // figure out which fields are different from the default and put their data here...
                    ParsedDuration invDuration = inv.getEffectiveDuration();
                    long instStart = inst.getStart();
                    // For an instance whose alarm time is within the time range, we must
                    // include it even if its start time is after the range.
                    long startOrAlarm = instStart == alarmInst ? alarmTime : instStart;
                    // events and 1 second for non all-day.  (bug 28615)
                    if (invDuration == null) {
                        if (inv.isAllDayEvent())
                            invDuration = ParsedDuration.ONE_DAY;
                        else
                            invDuration = ParsedDuration.ONE_SECOND;
                    }
                    if (!inst.hasStart() || (startOrAlarm < rangeEnd && invDuration.addToTime(instStart) > rangeStart)) {
                        numInRange++;
                    } else {
                        continue;
                    }
                    if (calItemElem == null) {
                        calItemElem = lc.createElement(isAppointment ? MailConstants.E_APPOINTMENT : MailConstants.E_TASK);
                        if (showAll) {
                            // flags and tags
                            ToXML.recordItemTags(calItemElem, calItem, octxt);
                        }
                        // Organizer
                        if (inv.hasOrganizer()) {
                            ZOrganizer org = inv.getOrganizer();
                            org.toXml(calItemElem);
                        }
                        calItemElem.addAttribute("x_uid", calItem.getUid());
                        calItemElem.addAttribute(MailConstants.A_UID, calItem.getUid());
                    }
                    Element instElt = calItemElem.addElement(MailConstants.E_INSTANCE);
                    if (showAll) {
                        if (isAppointment && inv.isEvent()) {
                            String instFba = ((Appointment) calItem).getEffectiveFreeBusyActual(inv, inst);
                            if (instFba != null && (!instFba.equals(defaultFba) || inst.isException()))
                                instElt.addAttribute(MailConstants.A_APPT_FREEBUSY_ACTUAL, instFba);
                        }
                        String instPtSt = calItem.getEffectivePartStat(inv, inst);
                        if (!defaultPtSt.equals(instPtSt) || inst.isException())
                            instElt.addAttribute(MailConstants.A_CAL_PARTSTAT, instPtSt);
                    }
                    if (inst.hasStart()) {
                        instElt.addAttribute(MailConstants.A_CAL_START_TIME, instStart);
                        if (inv.isAllDayEvent())
                            instElt.addAttribute(MailConstants.A_CAL_TZ_OFFSET, inst.getStartTzOffset());
                    }
                    if (inst.isException() && inv.hasRecurId()) {
                        RecurId rid = inv.getRecurId();
                        instElt.addAttribute(MailConstants.A_CAL_RECURRENCE_ID_Z, rid.getDtZ());
                    } else {
                        instElt.addAttribute(MailConstants.A_CAL_RECURRENCE_ID_Z, inst.getRecurIdZ());
                    }
                    if (inst.isException()) {
                        instElt.addAttribute(MailConstants.A_CAL_IS_EXCEPTION, true);
                        instElt.addAttribute(MailConstants.A_CAL_INV_ID, ifmt.formatItemId(calItem, inst.getMailItemId()));
                        instElt.addAttribute(MailConstants.A_CAL_COMPONENT_NUM, inst.getComponentNum());
                        if (showAll) {
                            // fragment has already been sanitized...
                            String frag = inv.getFragment();
                            if (frag != null && !frag.equals(""))
                                instElt.addAttribute(MailConstants.E_FRAG, frag, Element.Disposition.CONTENT);
                            if (inv.getPriority() != null)
                                instElt.addAttribute(MailConstants.A_CAL_PRIORITY, inv.getPriority());
                            if (inv.isEvent()) {
                                if (inv.getFreeBusy() != null)
                                    instElt.addAttribute(MailConstants.A_APPT_FREEBUSY, inv.getFreeBusy());
                                if (inv.getTransparency() != null)
                                    instElt.addAttribute(MailConstants.A_APPT_TRANSPARENCY, inv.getTransparency());
                            }
                            if (inv.isTodo()) {
                                if (inv.getPercentComplete() != null)
                                    instElt.addAttribute(MailConstants.A_TASK_PERCENT_COMPLETE, inv.getPercentComplete());
                            }
                            if (inv.getName() != null)
                                instElt.addAttribute(MailConstants.A_NAME, inv.getName());
                            if (inv.getLocation() != null)
                                instElt.addAttribute(MailConstants.A_CAL_LOCATION, inv.getLocation());
                            List<String> categories = inv.getCategories();
                            if (categories != null) {
                                for (String cat : categories) {
                                    instElt.addElement(MailConstants.E_CAL_CATEGORY).setText(cat);
                                }
                            }
                            Geo geo = inv.getGeo();
                            if (geo != null)
                                geo.toXml(instElt);
                            if (inv.hasOtherAttendees())
                                instElt.addAttribute(MailConstants.A_CAL_OTHER_ATTENDEES, true);
                            if (inv.hasAlarm())
                                instElt.addAttribute(MailConstants.A_CAL_ALARM, true);
                        }
                        instElt.addAttribute(MailConstants.A_CAL_ISORG, inv.isOrganizer());
                        if (inv.isTodo()) {
                            if (inst.hasEnd()) {
                                instElt.addAttribute(MailConstants.A_TASK_DUE_DATE, inst.getEnd());
                                if (inv.isAllDayEvent())
                                    instElt.addAttribute(MailConstants.A_CAL_TZ_OFFSET_DUE, inst.getEndTzOffset());
                            }
                        } else {
                            if (inst.hasStart() && inst.hasEnd()) {
                                instElt.addAttribute(newFormat ? MailConstants.A_CAL_NEW_DURATION : MailConstants.A_CAL_DURATION, inst.getEnd() - inst.getStart());
                            }
                        }
                        if (inv.getStatus() != null)
                            instElt.addAttribute(MailConstants.A_CAL_STATUS, inv.getStatus());
                        if (inv.getClassProp() != null)
                            instElt.addAttribute(MailConstants.A_CAL_CLASS, inv.getClassProp());
                        if (inv.isAllDayEvent())
                            instElt.addAttribute(MailConstants.A_CAL_ALLDAY, true);
                        if (inv.isDraft())
                            instElt.addAttribute(MailConstants.A_CAL_DRAFT, true);
                        if (inv.isNeverSent())
                            instElt.addAttribute(MailConstants.A_CAL_NEVER_SENT, true);
                        if (inv.isRecurrence())
                            instElt.addAttribute(MailConstants.A_CAL_RECUR, true);
                    } else {
                        if (inv.isTodo()) {
                            if (inst.hasEnd()) {
                                instElt.addAttribute(MailConstants.A_TASK_DUE_DATE, inst.getEnd());
                                if (inv.isAllDayEvent())
                                    instElt.addAttribute(MailConstants.A_CAL_TZ_OFFSET_DUE, inst.getEndTzOffset());
                            }
                        } else {
                            // the default duration due to daylight savings time transitions.
                            if (inst.hasStart() && inst.hasEnd() && defDurationMsecs != inst.getEnd() - inst.getStart()) {
                                instElt.addAttribute(newFormat ? MailConstants.A_CAL_NEW_DURATION : MailConstants.A_CAL_DURATION, inst.getEnd() - inst.getStart());
                            }
                        }
                    }
                } catch (MailServiceException.NoSuchItemException e) {
                    mLog.info("Error could not get instance " + inst.getMailItemId() + "-" + inst.getComponentNum() + " for appt " + calItem.getId(), e);
                }
            }
        // iterate all the instances
        }
        if (!expandRanges || numInRange > 0) {
            // if we found any calItems at all, we have to encode the "Default" data here
            boolean showAll = !hidePrivate || defaultInvite.isPublic();
            if (calItemElem == null) {
                calItemElem = lc.createElement(isAppointment ? MailConstants.E_APPOINTMENT : MailConstants.E_TASK);
                calItemElem.addAttribute("x_uid", calItem.getUid());
                calItemElem.addAttribute(MailConstants.A_UID, calItem.getUid());
                if (showAll) {
                    // flags and tags
                    ToXML.recordItemTags(calItemElem, calItem, octxt);
                }
                // Organizer
                if (defaultInvite.hasOrganizer()) {
                    ZOrganizer org = defaultInvite.getOrganizer();
                    org.toXml(calItemElem);
                }
            }
            if (showAll) {
                if (alarmData != null)
                    ToXML.encodeAlarmData(calItemElem, calItem, alarmData);
                String defaultPriority = defaultInvite.getPriority();
                if (defaultPriority != null)
                    calItemElem.addAttribute(MailConstants.A_CAL_PRIORITY, defaultPriority);
                calItemElem.addAttribute(MailConstants.A_CAL_PARTSTAT, defaultPtSt);
                if (defaultInvite.isEvent()) {
                    calItemElem.addAttribute(MailConstants.A_APPT_FREEBUSY, defaultInvite.getFreeBusy());
                    calItemElem.addAttribute(MailConstants.A_APPT_FREEBUSY_ACTUAL, defaultFba);
                    calItemElem.addAttribute(MailConstants.A_APPT_TRANSPARENCY, defaultInvite.getTransparency());
                }
                if (defaultInvite.isTodo()) {
                    String pctComplete = defaultInvite.getPercentComplete();
                    if (pctComplete != null)
                        calItemElem.addAttribute(MailConstants.A_TASK_PERCENT_COMPLETE, pctComplete);
                }
                calItemElem.addAttribute(MailConstants.A_NAME, defaultInvite.getName());
                calItemElem.addAttribute(MailConstants.A_CAL_LOCATION, defaultInvite.getLocation());
                List<String> categories = defaultInvite.getCategories();
                if (categories != null) {
                    for (String cat : categories) {
                        calItemElem.addElement(MailConstants.E_CAL_CATEGORY).setText(cat);
                    }
                }
                Geo geo = defaultInvite.getGeo();
                if (geo != null)
                    geo.toXml(calItemElem);
                // fragment has already been sanitized...
                String fragment = defaultInvite.getFragment();
                if (!fragment.equals(""))
                    calItemElem.addAttribute(MailConstants.E_FRAG, fragment, Element.Disposition.CONTENT);
                if (defaultInvite.hasOtherAttendees()) {
                    calItemElem.addAttribute(MailConstants.A_CAL_OTHER_ATTENDEES, defaultInvite.hasOtherAttendees());
                }
                if (defaultInvite.hasAlarm()) {
                    calItemElem.addAttribute(MailConstants.A_CAL_ALARM, defaultInvite.hasAlarm());
                }
            }
            calItemElem.addAttribute(MailConstants.A_CAL_ISORG, defaultInvite.isOrganizer());
            calItemElem.addAttribute(MailConstants.A_ID, ifmt.formatItemId(calItem));
            calItemElem.addAttribute(MailConstants.A_CAL_INV_ID, ifmt.formatItemId(calItem, defaultInvite.getMailItemId()));
            calItemElem.addAttribute(MailConstants.A_CAL_COMPONENT_NUM, defaultInvite.getComponentNum());
            calItemElem.addAttribute(MailConstants.A_FOLDER, ifmt.formatItemId(new ItemId(calItem.getMailbox().getAccountId(), calItem.getFolderId())));
            calItemElem.addAttribute(MailConstants.A_CAL_STATUS, defaultInvite.getStatus());
            calItemElem.addAttribute(MailConstants.A_CAL_CLASS, defaultInvite.getClassProp());
            if (!defaultInvite.isTodo())
                calItemElem.addAttribute(newFormat ? MailConstants.A_CAL_NEW_DURATION : MailConstants.A_CAL_DURATION, defDurationMsecs);
            if (defaultInvite.isAllDayEvent())
                calItemElem.addAttribute(MailConstants.A_CAL_ALLDAY, defaultInvite.isAllDayEvent());
            if (defaultInvite.isDraft())
                calItemElem.addAttribute(MailConstants.A_CAL_DRAFT, defaultInvite.isDraft());
            if (defaultInvite.isNeverSent())
                calItemElem.addAttribute(MailConstants.A_CAL_NEVER_SENT, defaultInvite.isNeverSent());
            if (defaultInvite.isRecurrence())
                calItemElem.addAttribute(MailConstants.A_CAL_RECUR, defaultInvite.isRecurrence());
            if (calItem.hasExceptions()) {
                calItemElem.addAttribute(MailConstants.A_CAL_HAS_EXCEPTIONS, true);
            }
            toRet.element = calItemElem;
        }
        toRet.numInstancesExpanded = numInRange;
    } catch (MailServiceException.NoSuchItemException e) {
        mLog.info("Error could not get default invite for calendar item: " + calItem.getId(), e);
    } catch (RuntimeException e) {
        mLog.info("Caught Exception " + e + " while getting summary info for calendar item: " + calItem.getId(), e);
    }
    return toRet;
}
Also used : Appointment(com.zimbra.cs.mailbox.Appointment) Account(com.zimbra.cs.account.Account) InviteInfo(com.zimbra.cs.mailbox.calendar.InviteInfo) Task(com.zimbra.cs.mailbox.Task) ItemIdFormatter(com.zimbra.cs.service.util.ItemIdFormatter) ParsedDuration(com.zimbra.common.calendar.ParsedDuration) Element(com.zimbra.common.soap.Element) RecurId(com.zimbra.cs.mailbox.calendar.RecurId) ItemId(com.zimbra.cs.service.util.ItemId) CalendarItem(com.zimbra.cs.mailbox.CalendarItem) CalendarItemData(com.zimbra.cs.mailbox.calendar.cache.CalendarItemData) ParsedDateTime(com.zimbra.common.calendar.ParsedDateTime) MailServiceException(com.zimbra.cs.mailbox.MailServiceException) ZOrganizer(com.zimbra.cs.mailbox.calendar.ZOrganizer) Geo(com.zimbra.common.calendar.Geo) Invite(com.zimbra.cs.mailbox.calendar.Invite) AlarmData(com.zimbra.cs.mailbox.CalendarItem.AlarmData)

Example 14 with ParsedDuration

use of com.zimbra.common.calendar.ParsedDuration in project zm-mailbox by Zimbra.

the class CalendarUtils method parseInviteElementCommon.

/**
     * UID, DTSTAMP, and SEQUENCE **MUST** be set by caller
     *
     * @param account
     *            user receiving invite
     * @param element
     *            invite XML element
     * @param newInv
     *            Invite we are currently building up
     * @param oldTzMap
     *            time zone map from A DIFFERENT invite; if this method is
     *            called during modify operation, this map contains time zones
     *            before the modification; null if called during create
     *            operation
     * @return
     * @throws ServiceException
     */
private static void parseInviteElementCommon(Account account, MailItem.Type type, Element element, Invite newInv, boolean recurrenceIdAllowed, boolean recurAllowed) throws ServiceException {
    //zdsync
    String invId = element.getAttribute(MailConstants.A_ID, null);
    Element compElem = element.getOptionalElement(MailConstants.E_INVITE_COMPONENT);
    if (compElem != null) {
        element = compElem;
    }
    //zdsync
    String dts = element.getAttribute(MailConstants.A_CAL_DATETIME, null);
    TimeZoneMap tzMap = newInv.getTimeZoneMap();
    parseTimeZones(element.getParent(), tzMap);
    newInv.setItemType(type);
    // UID
    String uid = element.getAttribute(MailConstants.A_UID, null);
    if (uid != null && uid.length() > 0)
        newInv.setUid(uid);
    // RECURRENCE-ID
    if (recurrenceIdAllowed) {
        Element e = element.getOptionalElement(MailConstants.E_CAL_EXCEPTION_ID);
        if (e != null) {
            ParsedDateTime dt = parseDateTime(e, tzMap);
            RecurId recurId = new RecurId(dt, RecurId.RANGE_NONE);
            newInv.setRecurId(recurId);
        }
    } else {
        if (element.getOptionalElement(MailConstants.E_CAL_EXCEPTION_ID) != null) {
            throw ServiceException.INVALID_REQUEST("May not specify an <exceptId> in this request", null);
        }
    }
    String name = element.getAttribute(MailConstants.A_NAME, "");
    String location = element.getAttribute(MailConstants.A_CAL_LOCATION, "");
    // CATEGORIES
    for (Iterator<Element> catIter = element.elementIterator(MailConstants.E_CAL_CATEGORY); catIter.hasNext(); ) {
        String cat = catIter.next().getText();
        newInv.addCategory(cat);
    }
    // COMMENTs
    for (Iterator<Element> cmtIter = element.elementIterator(MailConstants.E_CAL_COMMENT); cmtIter.hasNext(); ) {
        String cmt = cmtIter.next().getText();
        newInv.addComment(cmt);
    }
    // CONTACTs
    for (Iterator<Element> cnIter = element.elementIterator(MailConstants.E_CAL_CONTACT); cnIter.hasNext(); ) {
        String contact = cnIter.next().getTextTrim();
        newInv.addContact(contact);
    }
    // GEO
    Element geoElem = element.getOptionalElement(MailConstants.E_CAL_GEO);
    if (geoElem != null) {
        Geo geo = Geo.parse(geoElem);
        newInv.setGeo(geo);
    }
    // URL
    String url = element.getAttribute(MailConstants.A_CAL_URL, null);
    newInv.setUrl(url);
    // SEQUENCE
    int seq = (int) element.getAttributeLong(MailConstants.A_CAL_SEQUENCE, 0);
    newInv.setSeqNo(seq);
    // SUMMARY (aka Name or Subject)
    newInv.setName(name);
    // DESCRIPTION
    Element descElem = element.getOptionalElement(MailConstants.E_CAL_DESCRIPTION);
    String desc = descElem != null ? descElem.getText() : null;
    Element descHtmlElem = element.getOptionalElement(MailConstants.E_CAL_DESC_HTML);
    String descHtml = descHtmlElem != null ? descHtmlElem.getText() : null;
    newInv.setDescription(desc, descHtml);
    boolean allDay = element.getAttributeBool(MailConstants.A_CAL_ALLDAY, false);
    newInv.setIsAllDayEvent(allDay);
    // DTSTART
    Element startElem;
    if (newInv.isTodo())
        startElem = element.getOptionalElement(MailConstants.E_CAL_START_TIME);
    else
        startElem = element.getElement(MailConstants.E_CAL_START_TIME);
    if (startElem != null) {
        ParsedDateTime dt = parseDtElement(startElem, tzMap, newInv);
        // fixup for bug 30121
        if (allDay && dt.hasTime()) {
            // If this is supposed to be an all-day event but DTSTART has time part, clear the time part.
            dt.setHasTime(false);
        } else if (!allDay && !dt.hasTime()) {
            // If the event isn't marked as all-day but DTSTART is date-only, the client simply forgot
            // to mark it all-day.  Do all-day implicitly.
            allDay = true;
            newInv.setIsAllDayEvent(allDay);
        }
        newInv.setDtStart(dt);
    }
    // DTEND (for VEVENT) or DUE (for VTODO)
    Element endElem = element.getOptionalElement(MailConstants.E_CAL_END_TIME);
    if (endElem != null) {
        ParsedDateTime dt = parseDtElement(endElem, tzMap, newInv);
        // fixup for bug 30121
        if (allDay && dt.hasTime()) {
            // If this is supposed to be an all-day event but DTEND has time part, clear the time part.
            dt.setHasTime(false);
        } else if (!allDay && !dt.hasTime()) {
            // If the event isn't marked as all-day but DTEND is date-only, the client simply forgot
            // to mark it all-day.  Do all-day implicitly.
            allDay = true;
            newInv.setIsAllDayEvent(allDay);
        }
        if (allDay && !newInv.isTodo()) {
            // HACK ALERT: okay, campers, here's the deal.
            // By definition, our end dates are EXCLUSIVE: DTEND is not
            // included.. eg a meeting 7-8pm actually stops at 7:59
            //
            // This makes sense for normal appointments, but apparently
            // this rule is confusing to people when making
            // all-day-events
            //
            // For all-day-events, people want to say that a 1-day-long
            // appointment starts on 11/1 and ends on 11/1, for example
            // this is inconsistent (and incompatible with RFC2445) but
            // it is what people want. Sooo, we to a bit of a hacky
            // translation when sending/receiving all-day-events.
            //
            dt = dt.add(ParsedDuration.ONE_DAY);
        }
        newInv.setDtEnd(dt);
    } else {
        // DURATION
        Element d = element.getOptionalElement(MailConstants.E_CAL_DURATION);
        if (d != null) {
            ParsedDuration pd = ParsedDuration.parse(d);
            newInv.setDuration(pd);
        }
    }
    // LOCATION
    newInv.setLocation(location);
    // STATUS
    String status = element.getAttribute(MailConstants.A_CAL_STATUS, newInv.isEvent() ? IcalXmlStrMap.STATUS_CONFIRMED : IcalXmlStrMap.STATUS_NEEDS_ACTION);
    validateAttr(IcalXmlStrMap.sStatusMap, MailConstants.A_CAL_STATUS, status);
    newInv.setStatus(status);
    // CLASS
    String classProp = element.getAttribute(MailConstants.A_CAL_CLASS, IcalXmlStrMap.CLASS_PUBLIC);
    validateAttr(IcalXmlStrMap.sClassMap, MailConstants.A_CAL_CLASS, classProp);
    newInv.setClassProp(classProp);
    // PRIORITY
    String priority = element.getAttribute(MailConstants.A_CAL_PRIORITY, null);
    newInv.setPriority(priority);
    if (newInv.isEvent()) {
        // FreeBusy
        String fb = element.getAttribute(MailConstants.A_APPT_FREEBUSY, null);
        if (fb != null) {
            newInv.setFreeBusy(fb);
            // Intended F/B takes precedence over TRANSP.
            if (IcalXmlStrMap.FBTYPE_FREE.equals(fb))
                newInv.setTransparency(IcalXmlStrMap.TRANSP_TRANSPARENT);
            else
                newInv.setTransparency(IcalXmlStrMap.TRANSP_OPAQUE);
        } else {
            // TRANSP is examined only when intended F/B is not supplied.
            String transp = element.getAttribute(MailConstants.A_APPT_TRANSPARENCY, IcalXmlStrMap.TRANSP_OPAQUE);
            validateAttr(IcalXmlStrMap.sTranspMap, MailConstants.A_APPT_TRANSPARENCY, transp);
            newInv.setTransparency(transp);
            // If opaque, don't set intended f/b because there are multiple possibilities.
            if (newInv.isTransparent())
                newInv.setFreeBusy(IcalXmlStrMap.FBTYPE_FREE);
        }
    }
    if (newInv.isTodo()) {
        // PERCENT-COMPLETE
        String pctComplete = element.getAttribute(MailConstants.A_TASK_PERCENT_COMPLETE, null);
        newInv.setPercentComplete(pctComplete);
        // COMPLETED
        String completed = element.getAttribute(MailConstants.A_TASK_COMPLETED, null);
        if (completed != null) {
            try {
                ParsedDateTime c = ParsedDateTime.parseUtcOnly(completed);
                newInv.setCompleted(c.getUtcTime());
            } catch (ParseException e) {
                throw ServiceException.INVALID_REQUEST("Invalid COMPLETED value: " + completed, e);
            }
        } else if (status.equals(IcalXmlStrMap.STATUS_COMPLETED)) {
            newInv.setCompleted(System.currentTimeMillis());
        } else {
            newInv.setCompleted(0);
        }
    }
    // ATTENDEEs
    boolean hasAttendees = false;
    for (Iterator<Element> iter = element.elementIterator(MailConstants.E_CAL_ATTENDEE); iter.hasNext(); ) {
        ZAttendee at = ZAttendee.parse(iter.next());
        newInv.addAttendee(at);
        hasAttendees = true;
    }
    if (hasAttendees && newInv.getMethod().equals(ICalTok.PUBLISH.toString())) {
        newInv.setMethod(ICalTok.REQUEST.toString());
    }
    // ORGANIZER
    Element orgElt = element.getOptionalElement(MailConstants.E_CAL_ORGANIZER);
    if (orgElt != null) {
        ZOrganizer org = ZOrganizer.parse(orgElt);
        newInv.setOrganizer(org);
    }
    // Once we have organizer and attendee information, we can tell if this account is the
    // organizer in this invite or not.
    newInv.setIsOrganizer(account);
    if (!newInv.isCancel()) {
        // draft flag
        // True means invite has changes that haven't been sent to attendees.
        boolean draft = element.getAttributeBool(MailConstants.A_CAL_DRAFT, false);
        newInv.setDraft(draft);
        // neverSent flag
        // True means attendees have never been notified for this invite.
        boolean neverSent = element.getAttributeBool(MailConstants.A_CAL_NEVER_SENT, false);
        newInv.setNeverSent(neverSent);
    }
    // RECUR
    Element recur = element.getOptionalElement(MailConstants.A_CAL_RECUR);
    if (recur != null) {
        if (!recurAllowed) {
            throw ServiceException.INVALID_REQUEST("No <recur> allowed in an exception", null);
        }
        // Ensure DTSTART is set if doing recurrence.
        ParsedDateTime st = newInv.getStartTime();
        if (st == null) {
            ParsedDateTime et = newInv.getEndTime();
            if (et != null) {
                if (et.hasTime())
                    st = et.add(ParsedDuration.NEGATIVE_ONE_SECOND);
                else
                    st = et.add(ParsedDuration.NEGATIVE_ONE_DAY);
                newInv.setDtStart(st);
            } else {
                // Both DTSTART and DTEND are unspecified.  Recurrence makes no sense!
                throw ServiceException.INVALID_REQUEST("recurrence used without DTSTART", null);
            }
        }
        Recurrence.IRecurrence recurrence = parseRecur(recur, tzMap, newInv.getStartTime(), newInv.getEndTime(), newInv.getDuration(), newInv.getRecurId());
        newInv.setRecurrence(recurrence);
    }
    // VALARMs
    Iterator<Element> alarmsIter = element.elementIterator(MailConstants.E_CAL_ALARM);
    while (alarmsIter.hasNext()) {
        Alarm alarm = Alarm.parse(alarmsIter.next());
        if (alarm != null)
            newInv.addAlarm(alarm);
    }
    List<ZProperty> xprops = parseXProps(element);
    for (ZProperty prop : xprops) newInv.addXProp(prop);
    newInv.validateDuration();
    //zdsync: must set this only after recur is processed
    if (invId != null) {
        try {
            int invIdInt = Integer.parseInt(invId);
            newInv.setInviteId(invIdInt);
        } catch (NumberFormatException e) {
        // ignore if invId is not a number, e.g. refers to a remote account
        }
    }
    if (dts != null) {
        newInv.setDtStamp(Long.parseLong(dts));
    }
    Element fragment = element.getOptionalElement(MailConstants.E_FRAG);
    if (fragment != null) {
        newInv.setFragment(fragment.getText());
    }
}
Also used : IRecurrence(com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence) Recurrence(com.zimbra.cs.mailbox.calendar.Recurrence) ParsedDuration(com.zimbra.common.calendar.ParsedDuration) IRecurrence(com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence) Element(com.zimbra.common.soap.Element) ZOrganizer(com.zimbra.cs.mailbox.calendar.ZOrganizer) RecurId(com.zimbra.cs.mailbox.calendar.RecurId) Geo(com.zimbra.common.calendar.Geo) ZAttendee(com.zimbra.cs.mailbox.calendar.ZAttendee) Alarm(com.zimbra.cs.mailbox.calendar.Alarm) TimeZoneMap(com.zimbra.common.calendar.TimeZoneMap) ZProperty(com.zimbra.common.calendar.ZCalendar.ZProperty) ParsedDateTime(com.zimbra.common.calendar.ParsedDateTime) ParseException(java.text.ParseException)

Example 15 with ParsedDuration

use of com.zimbra.common.calendar.ParsedDuration in project zm-mailbox by Zimbra.

the class CalendarUtils method parseRecur.

static Recurrence.IRecurrence parseRecur(Element recurElt, TimeZoneMap invTzMap, ParsedDateTime dtStart, ParsedDateTime dtEnd, ParsedDuration dur, RecurId recurId) throws ServiceException {
    if (dur == null && dtStart != null && dtEnd != null)
        dur = dtEnd.difference(dtStart);
    ArrayList<IRecurrence> addRules = new ArrayList<IRecurrence>();
    ArrayList<IRecurrence> subRules = new ArrayList<IRecurrence>();
    for (Iterator iter = recurElt.elementIterator(); iter.hasNext(); ) {
        Element e = (Element) iter.next();
        boolean exclude = false;
        if (e.getName().equals(MailConstants.E_CAL_EXCLUDE)) {
            exclude = true;
        } else {
            if (!e.getName().equals(MailConstants.E_CAL_ADD)) {
                continue;
            }
        }
        for (Iterator intIter = e.elementIterator(); intIter.hasNext(); ) {
            Element intElt = (Element) intIter.next();
            if (intElt.getName().equals(MailConstants.E_CAL_DATES)) {
                // handle RDATE or EXDATE
                String tzid = intElt.getAttribute(MailConstants.A_CAL_TIMEZONE, null);
                ICalTimeZone tz = tzid != null ? invTzMap.lookupAndAdd(tzid) : null;
                RdateExdate rexdate = new RdateExdate(exclude ? ICalTok.EXDATE : ICalTok.RDATE, tz);
                ICalTok valueType = null;
                for (Iterator<Element> dtvalIter = intElt.elementIterator(MailConstants.E_CAL_DATE_VAL); dtvalIter.hasNext(); ) {
                    ICalTok dtvalValueType = null;
                    Element dtvalElem = dtvalIter.next();
                    Element dtvalStartElem = dtvalElem.getElement(MailConstants.E_CAL_START_TIME);
                    String dtvalStartDateStr = dtvalStartElem.getAttribute(MailConstants.A_CAL_DATETIME);
                    ParsedDateTime dtvalStart = parseDateTime(dtvalElem.getName(), dtvalStartDateStr, tzid, invTzMap);
                    Element dtvalEndElem = dtvalElem.getOptionalElement(MailConstants.E_CAL_END_TIME);
                    Element dtvalDurElem = dtvalElem.getOptionalElement(MailConstants.E_CAL_DURATION);
                    if (dtvalEndElem == null && dtvalDurElem == null) {
                        if (dtvalStart.hasTime())
                            dtvalValueType = ICalTok.DATE_TIME;
                        else
                            dtvalValueType = ICalTok.DATE;
                        rexdate.addValue(dtvalStart);
                    } else {
                        dtvalValueType = ICalTok.PERIOD;
                        if (dtvalEndElem != null) {
                            String dtvalEndDateStr = dtvalEndElem.getAttribute(MailConstants.A_CAL_DATETIME);
                            ParsedDateTime dtvalEnd = parseDateTime(dtvalElem.getName(), dtvalEndDateStr, tzid, invTzMap);
                            Period p = new Period(dtvalStart, dtvalEnd);
                            rexdate.addValue(p);
                        } else {
                            ParsedDuration d = ParsedDuration.parse(dtvalDurElem);
                            Period p = new Period(dtvalStart, d);
                            rexdate.addValue(p);
                        }
                    }
                    if (valueType == null) {
                        valueType = dtvalValueType;
                        rexdate.setValueType(valueType);
                    } else if (valueType != dtvalValueType)
                        throw ServiceException.INVALID_REQUEST("Cannot mix different value types in a single <" + intElt.getName() + "> element", null);
                }
                Recurrence.SingleDates sd = new Recurrence.SingleDates(rexdate, dur);
                if (exclude)
                    subRules.add(sd);
                else
                    addRules.add(sd);
            } else if (intElt.getName().equals(MailConstants.E_CAL_RULE)) {
                // handle RRULE or EXRULE
                // Turn XML into iCal RECUR string, which will then be
                // parsed by ical4j Recur object.
                StringBuilder recurBuf = new StringBuilder(100);
                String freq = IcalXmlStrMap.sFreqMap.toIcal(intElt.getAttribute(MailConstants.A_CAL_RULE_FREQ));
                recurBuf.append("FREQ=").append(freq);
                for (Iterator ruleIter = intElt.elementIterator(); ruleIter.hasNext(); ) {
                    Element ruleElt = (Element) ruleIter.next();
                    String ruleEltName = ruleElt.getName();
                    if (ruleEltName.equals(MailConstants.E_CAL_RULE_UNTIL)) {
                        recurBuf.append(";UNTIL=");
                        String d = ruleElt.getAttribute(MailConstants.A_CAL_DATETIME);
                        recurBuf.append(d);
                        // (RFC2445 Section 4.3.10 Recurrence Rule)
                        if (d.indexOf("T") >= 0)
                            if (d.indexOf("Z") < 0)
                                recurBuf.append('Z');
                    } else if (ruleEltName.equals(MailConstants.E_CAL_RULE_COUNT)) {
                        int num = (int) ruleElt.getAttributeLong(MailConstants.A_CAL_RULE_COUNT_NUM, -1);
                        if (num > 0) {
                            recurBuf.append(";COUNT=").append(num);
                        } else {
                            throw ServiceException.INVALID_REQUEST("Expected positive num attribute in <recur> <rule> <count>", null);
                        }
                    } else if (ruleEltName.equals(MailConstants.E_CAL_RULE_INTERVAL)) {
                        String ival = ruleElt.getAttribute(MailConstants.A_CAL_RULE_INTERVAL_IVAL);
                        recurBuf.append(";INTERVAL=").append(ival);
                    } else if (ruleEltName.equals(MailConstants.E_CAL_RULE_BYSECOND)) {
                        String list = ruleElt.getAttribute(MailConstants.A_CAL_RULE_BYSECOND_SECLIST);
                        recurBuf.append(";BYSECOND=").append(list);
                    } else if (ruleEltName.equals(MailConstants.E_CAL_RULE_BYMINUTE)) {
                        String list = ruleElt.getAttribute(MailConstants.A_CAL_RULE_BYMINUTE_MINLIST);
                        recurBuf.append(";BYMINUTE=").append(list);
                    } else if (ruleEltName.equals(MailConstants.E_CAL_RULE_BYHOUR)) {
                        String list = ruleElt.getAttribute(MailConstants.A_CAL_RULE_BYHOUR_HRLIST);
                        recurBuf.append(";BYHOUR=").append(list);
                    } else if (ruleEltName.equals(MailConstants.E_CAL_RULE_BYDAY)) {
                        recurBuf.append(";BYDAY=");
                        int pos = 0;
                        for (Iterator bydayIter = ruleElt.elementIterator(MailConstants.E_CAL_RULE_BYDAY_WKDAY); bydayIter.hasNext(); pos++) {
                            Element wkdayElt = (Element) bydayIter.next();
                            if (pos > 0)
                                recurBuf.append(",");
                            String ordwk = wkdayElt.getAttribute(MailConstants.A_CAL_RULE_BYDAY_WKDAY_ORDWK, null);
                            if (ordwk != null)
                                recurBuf.append(ordwk);
                            String day = wkdayElt.getAttribute(MailConstants.A_CAL_RULE_DAY);
                            if (day == null || day.length() == 0)
                                throw ServiceException.INVALID_REQUEST("Missing " + MailConstants.A_CAL_RULE_DAY + " in <" + ruleEltName + ">", null);
                            recurBuf.append(day);
                        }
                    } else if (ruleEltName.equals(MailConstants.E_CAL_RULE_BYMONTHDAY)) {
                        String list = ruleElt.getAttribute(MailConstants.A_CAL_RULE_BYMONTHDAY_MODAYLIST);
                        recurBuf.append(";BYMONTHDAY=").append(list);
                    } else if (ruleEltName.equals(MailConstants.E_CAL_RULE_BYYEARDAY)) {
                        String list = ruleElt.getAttribute(MailConstants.A_CAL_RULE_BYYEARDAY_YRDAYLIST);
                        recurBuf.append(";BYYEARDAY=").append(list);
                    } else if (ruleEltName.equals(MailConstants.E_CAL_RULE_BYWEEKNO)) {
                        String list = ruleElt.getAttribute(MailConstants.A_CAL_RULE_BYWEEKNO_WKLIST);
                        recurBuf.append(";BYWEEKNO=").append(list);
                    } else if (ruleEltName.equals(MailConstants.E_CAL_RULE_BYMONTH)) {
                        String list = ruleElt.getAttribute(MailConstants.A_CAL_RULE_BYMONTH_MOLIST);
                        recurBuf.append(";BYMONTH=").append(list);
                    } else if (ruleEltName.equals(MailConstants.E_CAL_RULE_BYSETPOS)) {
                        String list = ruleElt.getAttribute(MailConstants.A_CAL_RULE_BYSETPOS_POSLIST);
                        recurBuf.append(";BYSETPOS=").append(list);
                    } else if (ruleEltName.equals(MailConstants.E_CAL_RULE_WKST)) {
                        String day = ruleElt.getAttribute(MailConstants.A_CAL_RULE_DAY);
                        recurBuf.append(";WKST=").append(day);
                    } else if (ruleEltName.equals(MailConstants.E_CAL_RULE_XNAME)) {
                        String name = ruleElt.getAttribute(MailConstants.A_CAL_RULE_XNAME_NAME, null);
                        if (name != null) {
                            String value = ruleElt.getAttribute(MailConstants.A_CAL_RULE_XNAME_VALUE, "");
                            // TODO: Escape/unescape value according to
                            // "text" rule.
                            recurBuf.append(";").append(name).append("=").append(value);
                        }
                    }
                }
                try {
                    ZRecur recur = new ZRecur(recurBuf.toString(), invTzMap);
                    if (exclude) {
                        subRules.add(new Recurrence.SimpleRepeatingRule(dtStart, dur, recur, null));
                    } else {
                        addRules.add(new Recurrence.SimpleRepeatingRule(dtStart, dur, recur, null));
                    }
                } catch (ServiceException ex) {
                    throw ServiceException.INVALID_REQUEST("Exception parsing <recur> <rule>", ex);
                }
            } else {
                throw ServiceException.INVALID_REQUEST("Expected <date> or <rule> inside of " + e.getName() + ", got " + intElt.getName(), null);
            }
        }
    // iterate inside <add> or <exclude>
    }
    if (recurId != null) {
        return new Recurrence.ExceptionRule(recurId, dtStart, dur, null, addRules, subRules);
    } else {
        return new Recurrence.RecurrenceRule(dtStart, dur, null, addRules, subRules);
    }
}
Also used : IRecurrence(com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence) Recurrence(com.zimbra.cs.mailbox.calendar.Recurrence) RdateExdate(com.zimbra.cs.mailbox.calendar.RdateExdate) ParsedDuration(com.zimbra.common.calendar.ParsedDuration) Element(com.zimbra.common.soap.Element) ArrayList(java.util.ArrayList) Period(com.zimbra.cs.mailbox.calendar.Period) ICalTok(com.zimbra.common.calendar.ZCalendar.ICalTok) IRecurrence(com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence) ZRecur(com.zimbra.cs.mailbox.calendar.ZRecur) ServiceException(com.zimbra.common.service.ServiceException) Iterator(java.util.Iterator) ParsedDateTime(com.zimbra.common.calendar.ParsedDateTime) ICalTimeZone(com.zimbra.common.calendar.ICalTimeZone)

Aggregations

ParsedDateTime (com.zimbra.common.calendar.ParsedDateTime)23 ParsedDuration (com.zimbra.common.calendar.ParsedDuration)23 IRecurrence (com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence)10 ParseException (java.text.ParseException)9 ArrayList (java.util.ArrayList)9 Element (com.zimbra.common.soap.Element)8 ZProperty (com.zimbra.common.calendar.ZCalendar.ZProperty)7 Invite (com.zimbra.cs.mailbox.calendar.Invite)6 Geo (com.zimbra.common.calendar.Geo)5 TimeZoneMap (com.zimbra.common.calendar.TimeZoneMap)5 ServiceException (com.zimbra.common.service.ServiceException)5 RecurId (com.zimbra.cs.mailbox.calendar.RecurId)5 ZAttendee (com.zimbra.cs.mailbox.calendar.ZAttendee)5 ZOrganizer (com.zimbra.cs.mailbox.calendar.ZOrganizer)5 Attach (com.zimbra.common.calendar.Attach)4 ICalTimeZone (com.zimbra.common.calendar.ICalTimeZone)4 ICalTok (com.zimbra.common.calendar.ZCalendar.ICalTok)4 ZParameter (com.zimbra.common.calendar.ZCalendar.ZParameter)4 Account (com.zimbra.cs.account.Account)3 CalendarItem (com.zimbra.cs.mailbox.CalendarItem)3