Search in sources :

Example 1 with IRecurrence

use of com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence in project zm-mailbox by Zimbra.

the class CalendarItem method updateLocalExceptionsWhichMatchSeriesReply.

/**
     * Exceptions can be created which aren't communicated to ATTENDEEs, either because the ORGANIZER wants to
     * have local changes like a different alarm time or because a response is received which only affects one
     * instance of a series.
     * Caller is responsible for ensuring changed MetaData is written through to SQL sending notification of change.
     */
private void updateLocalExceptionsWhichMatchSeriesReply(Invite reply) throws ServiceException {
    if ((reply == null) || reply.getRecurId() != null) {
        // Only interested in series replies
        return;
    }
    IRecurrence replyRecurrence = reply.getRecurrence();
    if (replyRecurrence == null) {
        sLog.debug("Giving up on trying to match series reply to local exceptions - no recurrence in reply");
        return;
    }
    for (int i = 0; i < numInvites(); i++) {
        Invite cur = getInvite(i);
        if (!cur.classPropSetByMe() || (cur.getRecurId() == null)) {
            continue;
        }
        ParsedDateTime recurIdDT = cur.getRecurId().getDt();
        ParsedDateTime startDT = cur.getStartTime();
        // If the start time has moved then the series response can't be applicable.
        if ((recurIdDT == null) || (startDT == null) || !recurIdDT.sameTime(startDT)) {
            continue;
        }
        long utcTime = recurIdDT.getUtcTime();
        // Find instances within 2 seconds either side of start - assuming it will be a direct hit if found
        List<Instance> instances = Recurrence.expandInstances(replyRecurrence, getId(), utcTime - 2000L, utcTime + 2000L);
        if (instances == null || (instances.size() != 1)) {
            continue;
        }
        cur.updateMatchingAttendeesFromReply(reply);
    }
}
Also used : IRecurrence(com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence) ParsedDateTime(com.zimbra.common.calendar.ParsedDateTime) Invite(com.zimbra.cs.mailbox.calendar.Invite)

Example 2 with IRecurrence

use of com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence in project zm-mailbox by Zimbra.

the class Invite method getReferencedTZIDs.

public Set<String> getReferencedTZIDs() {
    Set<String> tzids = new HashSet<String>();
    // DTSTART
    if (mStart != null && mStart.hasTime()) {
        ICalTimeZone tz = mStart.getTimeZone();
        if (tz != null)
            tzids.add(tz.getID());
    }
    // DTEND/DUE
    if (mEnd != null && mEnd.hasTime()) {
        ICalTimeZone tz = mEnd.getTimeZone();
        if (tz != null)
            tzids.add(tz.getID());
    }
    // RECURRENCE-ID
    if (mRecurrenceId != null) {
        ParsedDateTime dt = mRecurrenceId.getDt();
        if (dt.hasTime()) {
            ICalTimeZone tz = dt.getTimeZone();
            if (tz != null)
                tzids.add(tz.getID());
        }
    }
    // RDATE/EXDATE
    IRecurrence recur = getRecurrence();
    if (recur != null)
        tzids.addAll(Recurrence.getReferencedTZIDs(recur));
    return tzids;
}
Also used : IRecurrence(com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence) ParsedDateTime(com.zimbra.common.calendar.ParsedDateTime) ICalTimeZone(com.zimbra.common.calendar.ICalTimeZone) HashSet(java.util.HashSet)

Example 3 with IRecurrence

use of com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence in project zm-mailbox by Zimbra.

the class Invite method newToVComponent.

public ZComponent newToVComponent(boolean useOutlookCompatAllDayEvents, boolean includePrivateData, boolean includeAttaches) throws ServiceException {
    boolean isRequestPublishCancel = ICalTok.REQUEST.equals(mMethod) || ICalTok.PUBLISH.equals(mMethod) || ICalTok.CANCEL.equals(mMethod);
    ICalTok compTok;
    if (type == MailItem.Type.TASK) {
        compTok = ICalTok.VTODO;
        useOutlookCompatAllDayEvents = false;
    } else {
        compTok = ICalTok.VEVENT;
    }
    ZComponent component = new ZComponent(compTok);
    component.addProperty(new ZProperty(ICalTok.UID, getUid()));
    IRecurrence recur = getRecurrence();
    if (recur != null) {
        for (Iterator iter = recur.addRulesIterator(); iter != null && iter.hasNext(); ) {
            IRecurrence cur = (IRecurrence) iter.next();
            switch(cur.getType()) {
                case Recurrence.TYPE_SINGLE_DATES:
                    if (DebugConfig.enableRdate) {
                        Recurrence.SingleDates sd = (Recurrence.SingleDates) cur;
                        RdateExdate rdate = sd.getRdateExdate();
                        rdate.addAsSeparateProperties(component);
                    }
                    break;
                case Recurrence.TYPE_REPEATING:
                    Recurrence.SimpleRepeatingRule srr = (Recurrence.SimpleRepeatingRule) cur;
                    component.addProperty(new ZProperty(ICalTok.RRULE, srr.getRule().toString()));
                    break;
            }
        }
        for (Iterator iter = recur.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();
                    exdate.addAsSeparateProperties(component);
                    break;
                case Recurrence.TYPE_REPEATING:
                    Recurrence.SimpleRepeatingRule srr = (Recurrence.SimpleRepeatingRule) cur;
                    component.addProperty(new ZProperty(ICalTok.EXRULE, srr.getRule().toString()));
                    break;
            }
        }
    }
    if (includePrivateData || isPublic()) {
        // SUMMARY (aka Name or Subject)
        String name = getName();
        if (name != null && name.length() > 0)
            component.addProperty(new ZProperty(ICalTok.SUMMARY, name));
        // DESCRIPTION and X-ALT-DESC;FMTTYPE=text/html
        String desc = getDescription();
        if (desc != null) {
            // Remove Outlook-style *~*~*~ header block.  Remove separator plus two newlines.
            int delim = desc.indexOf(HEADER_SEPARATOR);
            if (delim >= 0) {
                desc = desc.substring(delim + HEADER_SEPARATOR.length());
                desc = desc.replaceFirst("^\\r?\\n\\r?\\n", "");
            }
            if (desc.length() > 0)
                component.addProperty(new ZProperty(ICalTok.DESCRIPTION, desc));
        }
        String descHtml = getDescriptionHtml();
        if (descHtml != null && descHtml.length() > 0) {
            ZProperty altDesc = new ZProperty(ICalTok.X_ALT_DESC, descHtml);
            altDesc.addParameter(new ZParameter(ICalTok.FMTTYPE, MimeConstants.CT_TEXT_HTML));
            component.addProperty(altDesc);
        }
        // COMMENT
        List<String> comments = getComments();
        if (comments != null && !comments.isEmpty()) {
            for (String comment : comments) {
                component.addProperty(new ZProperty(ICalTok.COMMENT, comment));
            }
        }
        // LOCATION
        String location = getLocation();
        if (location != null && location.length() > 0)
            component.addProperty(new ZProperty(ICalTok.LOCATION, location.toString()));
        // ATTENDEES
        for (ZAttendee at : getAttendees()) {
            component.addProperty(at.toProperty());
        }
        // PRIORITY
        if (mPriority != null)
            component.addProperty(new ZProperty(ICalTok.PRIORITY, mPriority));
        // PERCENT-COMPLETE
        if (isTodo() && mPercentComplete != null)
            component.addProperty(new ZProperty(ICalTok.PERCENT_COMPLETE, mPercentComplete));
        // COMPLETED
        if (isTodo() && mCompleted != 0) {
            ParsedDateTime completed = ParsedDateTime.fromUTCTime(mCompleted);
            component.addProperty(completed.toProperty(ICalTok.COMPLETED, false));
        }
        // CATEGORIES
        List<String> categories = getCategories();
        if (categories != null && !categories.isEmpty()) {
            ZProperty catsProp = new ZProperty(ICalTok.CATEGORIES);
            catsProp.setValueList(categories);
            component.addProperty(catsProp);
        }
        // CONTACT
        List<String> contacts = getContacts();
        if (contacts != null && !contacts.isEmpty()) {
            for (String contact : contacts) {
                component.addProperty(new ZProperty(ICalTok.CONTACT, contact));
            }
        }
        // GEO
        if (mGeo != null)
            component.addProperty(mGeo.toZProperty());
        // VALARMs
        for (Alarm alarm : mAlarms) {
            ZComponent alarmComp = alarm.toZComponent();
            component.addComponent(alarmComp);
        }
        // x-prop
        for (ZProperty xprop : mXProps) {
            component.addProperty(xprop);
        }
        // ORGANIZER
        if (hasOrganizer()) {
            ZOrganizer organizer = getOrganizer();
            ZProperty orgProp = organizer.toProperty();
            component.addProperty(orgProp);
            // Hack for Outlook 2007 (bug 25777)
            if (organizer.hasSentBy() && !ICalTok.REPLY.equals(mMethod) && !ICalTok.COUNTER.equals(mMethod)) {
                String sentByParam = orgProp.paramVal(ICalTok.SENT_BY, null);
                if (sentByParam != null) {
                    ZProperty xMsOlkSender = new ZProperty("X-MS-OLK-SENDER");
                    xMsOlkSender.setValue(sentByParam);
                    component.addProperty(xMsOlkSender);
                }
            }
        }
    }
    // DTSTART
    ParsedDateTime dtstart = getStartTime();
    if (dtstart != null)
        component.addProperty(dtstart.toProperty(ICalTok.DTSTART, useOutlookCompatAllDayEvents));
    // DTEND or DUE
    ParsedDateTime dtend = getEndTime();
    if (dtend != null) {
        ICalTok prop = ICalTok.DTEND;
        if (isTodo())
            prop = ICalTok.DUE;
        component.addProperty(dtend.toProperty(prop, useOutlookCompatAllDayEvents));
    }
    // DURATION
    ParsedDuration dur = getDuration();
    if (dur != null)
        component.addProperty(new ZProperty(ICalTok.DURATION, dur.toString()));
    // STATUS
    String status = getStatus();
    String statusIcal = IcalXmlStrMap.sStatusMap.toIcal(status);
    if (IcalXmlStrMap.STATUS_ZCO_WAITING.equals(status) || IcalXmlStrMap.STATUS_ZCO_DEFERRED.equals(status)) {
        ZParameter param = new ZParameter(ICalTok.X_ZIMBRA_STATUS, statusIcal);
        ZProperty prop = new ZProperty(ICalTok.STATUS, ICalTok.IN_PROCESS.toString());
        prop.addParameter(param);
        component.addProperty(prop);
    } else {
        component.addProperty(new ZProperty(ICalTok.STATUS, statusIcal));
    }
    // CLASS
    component.addProperty(new ZProperty(ICalTok.CLASS, IcalXmlStrMap.sClassMap.toIcal(getClassProp())));
    if (isEvent()) {
        // allDay
        if (isAllDayEvent())
            component.addProperty(new ZProperty(ICalTok.X_MICROSOFT_CDO_ALLDAYEVENT, true));
        // Microsoft Outlook compatibility for free-busy status
        if (isRequestPublishCancel) {
            String outlookFreeBusy = IcalXmlStrMap.sOutlookFreeBusyMap.toIcal(getFreeBusy());
            component.addProperty(new ZProperty(ICalTok.X_MICROSOFT_CDO_INTENDEDSTATUS, outlookFreeBusy));
        }
        // TRANSPARENCY
        component.addProperty(new ZProperty(ICalTok.TRANSP, IcalXmlStrMap.sTranspMap.toIcal(getTransparency())));
    }
    // RECURRENCE-ID
    RecurId recurId = getRecurId();
    if (recurId != null)
        component.addProperty(recurId.toProperty(useOutlookCompatAllDayEvents));
    // LAST-MODIFIED
    long lastModified = getLastModified();
    if (lastModified != 0) {
        ParsedDateTime dtLastModified = ParsedDateTime.fromUTCTime(lastModified);
        component.addProperty(dtLastModified.toProperty(ICalTok.LAST_MODIFIED, false));
    }
    // DTSTAMP
    ParsedDateTime dtStamp = ParsedDateTime.fromUTCTime(getDTStamp());
    component.addProperty(dtStamp.toProperty(ICalTok.DTSTAMP, false));
    // SEQUENCE
    component.addProperty(new ZProperty(ICalTok.SEQUENCE, getSeqNo()));
    // URL
    String url = getUrl();
    if (url != null && url.length() > 0)
        component.addProperty(new ZProperty(ICalTok.URL, url));
    if (isLocalOnly())
        component.addProperty(new ZProperty(ICalTok.X_ZIMBRA_LOCAL_ONLY, true));
    if (includeAttaches) {
        addInlineATTACHes(component);
    }
    return component;
}
Also used : IRecurrence(com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence) ParsedDuration(com.zimbra.common.calendar.ParsedDuration) ZParameter(com.zimbra.common.calendar.ZCalendar.ZParameter) ICalTok(com.zimbra.common.calendar.ZCalendar.ICalTok) ZComponent(com.zimbra.common.calendar.ZCalendar.ZComponent) IRecurrence(com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence) ZProperty(com.zimbra.common.calendar.ZCalendar.ZProperty) Iterator(java.util.Iterator) ParsedDateTime(com.zimbra.common.calendar.ParsedDateTime)

Example 4 with IRecurrence

use of com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence in project zm-mailbox by Zimbra.

the class Invite method createFromCalendar.

private static void createFromCalendar(List<Invite> toAdd, Account account, String fragment, String method, TimeZoneMap tzmap, Iterator<ZComponent> compIter, boolean sentByMe, Mailbox mbx, int mailItemId, boolean continueOnError, InviteVisitor visitor) throws ServiceException {
    int compNum = 0;
    while (compIter.hasNext()) {
        ZComponent comp = compIter.next();
        Invite newInv = null;
        try {
            MailItem.Type type;
            ICalTok compTypeTok = comp.getTok();
            if (compTypeTok == null)
                continue;
            if (ICalTok.VTODO.equals(compTypeTok)) {
                type = MailItem.Type.TASK;
            } else {
                type = MailItem.Type.APPOINTMENT;
            }
            switch(compTypeTok) {
                case VEVENT:
                case VTODO:
                    boolean isEvent = ICalTok.VEVENT.equals(compTypeTok);
                    boolean isTodo = ICalTok.VTODO.equals(compTypeTok);
                    try {
                        newInv = new Invite(type, method, tzmap, false);
                        // set to true later if X-ZIMBRA-LOCAL-ONLY is present
                        newInv.setLocalOnly(false);
                        if (toAdd != null)
                            toAdd.add(newInv);
                        List<Object> addRecurs = new ArrayList<Object>();
                        List<Object> subRecurs = new ArrayList<Object>();
                        newInv.setComponentNum(compNum);
                        if (mbx != null)
                            newInv.setMailboxId(mbx.getId());
                        newInv.setMailItemId(mailItemId);
                        newInv.setSentByMe(sentByMe);
                        compNum++;
                        List<ZComponent> subcomponents = Lists.newArrayList(comp.getComponentIterator());
                        for (ZComponent subcomp : subcomponents) {
                            ICalTok subCompTypeTok = subcomp.getTok();
                            switch(subCompTypeTok) {
                                case VALARM:
                                    Alarm alarm = Alarm.parse(subcomp);
                                    if (alarm != null)
                                        newInv.addAlarm(alarm);
                                    break;
                                default:
                            }
                        }
                        boolean isTodoCompleted = false;
                        boolean sawIntendedFreeBusy = false;
                        List<ZProperty> properties = Lists.newArrayList(comp.getPropertyIterator());
                        for (ZProperty prop : properties) {
                            String propVal = prop.getValue();
                            ICalTok propToken = prop.getToken();
                            if (propToken == null) {
                                // parse errors later, so ignore them.
                                if (propVal == null || propVal.length() < 1)
                                    continue;
                                String name = prop.getName();
                                if (name.startsWith("X-") || name.startsWith("x-"))
                                    newInv.addXProp(prop);
                            } else if (propToken.equals(ICalTok.CATEGORIES)) {
                                List<String> categories = prop.getValueList();
                                if (categories != null && !categories.isEmpty()) {
                                    for (String cat : categories) {
                                        newInv.addCategory(cat);
                                    }
                                }
                            } else {
                                // parse errors later, so ignore them.
                                if (propVal == null || propVal.length() < 1)
                                    continue;
                                switch(propToken) {
                                    case ORGANIZER:
                                        newInv.setOrganizer(new ZOrganizer(prop));
                                        break;
                                    case ATTENDEE:
                                        newInv.addAttendee(new ZAttendee(prop));
                                        break;
                                    case DTSTAMP:
                                        ParsedDateTime dtstamp = ParsedDateTime.parse(prop, tzmap);
                                        newInv.setDtStamp(dtstamp.getUtcTime());
                                        break;
                                    case LAST_MODIFIED:
                                        ParsedDateTime lastModified = ParsedDateTime.parse(prop, tzmap);
                                        newInv.setLastModified(lastModified.getUtcTime());
                                        break;
                                    case RECURRENCE_ID:
                                        ParsedDateTime rid = ParsedDateTime.parse(prop, tzmap);
                                        if (DebugConfig.enableThisAndFuture) {
                                            newInv.setRecurId(new RecurId(rid, prop.paramVal(ICalTok.RANGE, null)));
                                        } else {
                                            newInv.setRecurId(new RecurId(rid, RecurId.RANGE_NONE));
                                        }
                                        break;
                                    case SEQUENCE:
                                        newInv.setSeqNo(prop.getIntValue());
                                        break;
                                    case DTSTART:
                                        ParsedDateTime dtstart = ParsedDateTime.parse(prop, tzmap);
                                        newInv.setDtStart(dtstart);
                                        if (!dtstart.hasTime())
                                            newInv.setIsAllDayEvent(true);
                                        break;
                                    case DTEND:
                                        if (isEvent) {
                                            ParsedDateTime dtend = ParsedDateTime.parse(prop, tzmap);
                                            newInv.setDtEnd(dtend);
                                            if (!dtend.hasTime())
                                                newInv.setIsAllDayEvent(true);
                                        }
                                        break;
                                    case DUE:
                                        if (isTodo) {
                                            ParsedDateTime due = ParsedDateTime.parse(prop, tzmap);
                                            // DUE is for VTODO what DTEND is for VEVENT.
                                            newInv.setDtEnd(due);
                                            if (!due.hasTime())
                                                newInv.setIsAllDayEvent(true);
                                        }
                                        break;
                                    case DURATION:
                                        ParsedDuration dur = ParsedDuration.parse(propVal);
                                        newInv.setDuration(dur);
                                        break;
                                    case LOCATION:
                                        newInv.setLocation(propVal);
                                        break;
                                    case SUMMARY:
                                        String summary = propVal;
                                        if (summary != null) {
                                            // Make sure SUMMARY is a single line.
                                            summary = summary.replaceAll("[\\\r\\\n]+", " ");
                                        }
                                        prop.setValue(summary);
                                        newInv.setName(summary);
                                        break;
                                    case DESCRIPTION:
                                        newInv.setDescription(propVal, newInv.mDescHtml);
                                        newInv.setFragment(Fragment.getFragment(propVal, true));
                                        break;
                                    case X_ALT_DESC:
                                        ZParameter fmttype = prop.getParameter(ICalTok.FMTTYPE);
                                        if (fmttype != null && MimeConstants.CT_TEXT_HTML.equalsIgnoreCase(fmttype.getValue())) {
                                            String html = propVal;
                                            newInv.setDescription(newInv.mDescription, html);
                                        } else {
                                            // Unknown format.  Just add as an x-prop.
                                            newInv.addXProp(prop);
                                        }
                                        break;
                                    case COMMENT:
                                        newInv.addComment(propVal);
                                        break;
                                    case UID:
                                        newInv.setUid(propVal);
                                        break;
                                    case RRULE:
                                        ZRecur recur = new ZRecur(propVal, tzmap);
                                        addRecurs.add(recur);
                                        newInv.setIsRecurrence(true);
                                        break;
                                    case RDATE:
                                        if (DebugConfig.enableRdate) {
                                            RdateExdate rdate = RdateExdate.parse(prop, tzmap);
                                            addRecurs.add(rdate);
                                            newInv.setIsRecurrence(true);
                                        }
                                        break;
                                    case EXRULE:
                                        ZRecur exrecur = new ZRecur(propVal, tzmap);
                                        subRecurs.add(exrecur);
                                        newInv.setIsRecurrence(true);
                                        break;
                                    case EXDATE:
                                        RdateExdate exdate = RdateExdate.parse(prop, tzmap);
                                        subRecurs.add(exdate);
                                        newInv.setIsRecurrence(true);
                                        break;
                                    case STATUS:
                                        String status = IcalXmlStrMap.sStatusMap.toXml(propVal);
                                        if (status != null) {
                                            if (IcalXmlStrMap.STATUS_IN_PROCESS.equals(status)) {
                                                String zstatus = prop.getParameterVal(ICalTok.X_ZIMBRA_STATUS, null);
                                                if (ICalTok.X_ZIMBRA_STATUS_WAITING.toString().equals(zstatus) || ICalTok.X_ZIMBRA_STATUS_DEFERRED.toString().equals(zstatus)) {
                                                    newInv.setStatus(IcalXmlStrMap.sStatusMap.toXml(zstatus));
                                                } else {
                                                    newInv.setStatus(status);
                                                }
                                            } else {
                                                newInv.setStatus(status);
                                                if (isTodo && IcalXmlStrMap.STATUS_COMPLETED.equals(status))
                                                    isTodoCompleted = true;
                                            }
                                        }
                                        break;
                                    case TRANSP:
                                        // TRANSP is examined only when intended F/B is not supplied.
                                        if (isEvent && !sawIntendedFreeBusy) {
                                            String transp = IcalXmlStrMap.sTranspMap.toXml(propVal);
                                            if (transp != null) {
                                                newInv.setTransparency(transp);
                                                // If opaque, don't set intended f/b because there are multiple possibilities.
                                                if (newInv.isTransparent())
                                                    newInv.setFreeBusy(IcalXmlStrMap.FBTYPE_FREE);
                                            }
                                        }
                                        break;
                                    case CLASS:
                                        String classProp = IcalXmlStrMap.sClassMap.toXml(propVal);
                                        if (classProp != null)
                                            newInv.setClassProp(classProp);
                                        break;
                                    case X_MICROSOFT_CDO_ALLDAYEVENT:
                                        if (isEvent) {
                                            if (prop.getBoolValue())
                                                newInv.setIsAllDayEvent(true);
                                        }
                                        break;
                                    case X_MICROSOFT_CDO_INTENDEDSTATUS:
                                        sawIntendedFreeBusy = true;
                                        if (isEvent) {
                                            String fb = IcalXmlStrMap.sOutlookFreeBusyMap.toXml(propVal);
                                            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);
                                            }
                                        }
                                        break;
                                    case PRIORITY:
                                        String prio = propVal;
                                        if (prio != null)
                                            newInv.setPriority(prio);
                                        break;
                                    case PERCENT_COMPLETE:
                                        if (isTodo) {
                                            String pctComplete = propVal;
                                            if (pctComplete != null) {
                                                newInv.setPercentComplete(pctComplete);
                                                if (prop.getIntValue() == 100)
                                                    isTodoCompleted = true;
                                            }
                                        }
                                        break;
                                    case COMPLETED:
                                        if (isTodo) {
                                            ParsedDateTime completed = ParsedDateTime.parseUtcOnly(propVal);
                                            newInv.setCompleted(completed.getUtcTime());
                                            isTodoCompleted = true;
                                        }
                                        break;
                                    case CONTACT:
                                        newInv.addContact(propVal);
                                        break;
                                    case GEO:
                                        Geo geo = Geo.parse(prop);
                                        newInv.setGeo(geo);
                                        break;
                                    case URL:
                                        newInv.setUrl(propVal);
                                        break;
                                    case X_ZIMBRA_LOCAL_ONLY:
                                        if (prop.getBoolValue())
                                            newInv.setLocalOnly(true);
                                        break;
                                    case X_ZIMBRA_DISCARD_EXCEPTIONS:
                                        newInv.addXProp(prop);
                                        break;
                                    case X_ZIMBRA_CHANGES:
                                        newInv.addXProp(prop);
                                        break;
                                    case ATTACH:
                                        Attach attach = Attach.parse(prop);
                                        if (attach.getBinaryB64Data() != null) {
                                            newInv.addIcalendarAttach(attach);
                                        }
                                        break;
                                }
                            }
                        }
                        if (isTodoCompleted) {
                            // set the status to Completed.
                            newInv.setStatus(IcalXmlStrMap.STATUS_COMPLETED);
                            // set percent-complete to 100
                            newInv.setPercentComplete(Integer.toString(100));
                            if (// set COMPLETED property to now if not already set.
                            newInv.getCompleted() == 0)
                                newInv.setCompleted(System.currentTimeMillis());
                        }
                        newInv.setIsOrganizer(account);
                        newInv.validateDuration();
                        ParsedDuration duration = newInv.getDuration();
                        boolean durationCalculated = false;
                        if (duration == null) {
                            ParsedDateTime end = newInv.getEndTime();
                            if (end != null && newInv.getStartTime() != null) {
                                duration = end.difference(newInv.getStartTime());
                                durationCalculated = true;
                            }
                        }
                        if (!addRecurs.isEmpty() || !subRecurs.isEmpty()) {
                            // We have a recurrence.  Make sure DTSTART is not null.
                            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);
                                }
                            }
                            if (durationCalculated && newInv.getItemType() == MailItem.Type.TASK) {
                                if (newInv.getStartTime() != null && !newInv.getStartTime().hasTime()) {
                                    duration = ParsedDuration.ONE_DAY;
                                } else {
                                    duration = ParsedDuration.ONE_SECOND;
                                }
                            }
                        }
                        InviteInfo inviteInfo = new InviteInfo(newInv);
                        List<IRecurrence> addRules = new ArrayList<IRecurrence>();
                        if (addRecurs.size() > 0) {
                            for (Iterator<Object> iter = addRecurs.iterator(); iter.hasNext(); ) {
                                Object next = iter.next();
                                if (next instanceof ZRecur) {
                                    ZRecur cur = (ZRecur) next;
                                    addRules.add(new Recurrence.SimpleRepeatingRule(newInv.getStartTime(), duration, cur, inviteInfo));
                                } else if (next instanceof RdateExdate) {
                                    RdateExdate rdate = (RdateExdate) next;
                                    addRules.add(new Recurrence.SingleDates(rdate, duration, inviteInfo));
                                }
                            }
                        }
                        List<IRecurrence> subRules = new ArrayList<IRecurrence>();
                        if (subRecurs.size() > 0) {
                            for (Iterator<Object> iter = subRecurs.iterator(); iter.hasNext(); ) {
                                Object next = iter.next();
                                if (next instanceof ZRecur) {
                                    ZRecur cur = (ZRecur) iter.next();
                                    subRules.add(new Recurrence.SimpleRepeatingRule(newInv.getStartTime(), duration, cur, inviteInfo));
                                } else if (next instanceof RdateExdate) {
                                    RdateExdate exdate = (RdateExdate) next;
                                    subRules.add(new Recurrence.SingleDates(exdate, duration, inviteInfo));
                                }
                            }
                        }
                        if (newInv.hasRecurId()) {
                            if (addRules.size() > 0) {
                                newInv.setRecurrence(new Recurrence.ExceptionRule(newInv.getRecurId(), newInv.getStartTime(), duration, new InviteInfo(newInv), addRules, subRules));
                            }
                        } else {
                            if (addRules.size() > 0) {
                                // since exclusions can't affect DtStart, just ignore them if there are no add rules
                                newInv.setRecurrence(new Recurrence.RecurrenceRule(newInv.getStartTime(), duration, new InviteInfo(newInv), addRules, subRules));
                            }
                        }
                        String location = newInv.getLocation();
                        if (location == null)
                            newInv.setLocation("");
                        // Process callback.
                        if (visitor != null)
                            visitor.visit(newInv);
                    } catch (ParseException e) {
                        throw ServiceException.PARSE_ERROR("Unable to parse iCalendar data: " + e.getMessage(), e);
                    }
                    break;
            }
        } catch (ServiceException e) {
            if (!continueOnError)
                throw e;
            if (newInv != null)
                logIcsParseImportError(newInv, e);
            else
                ZimbraLog.calendar.warn("Skipping error during ics parse/import", e);
        } catch (RuntimeException e) {
            if (!continueOnError)
                throw e;
            if (newInv != null)
                logIcsParseImportError(newInv, e);
            else
                ZimbraLog.calendar.warn("Skipping error during ics parse/import", e);
        }
    }
}
Also used : IRecurrence(com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence) ParsedDuration(com.zimbra.common.calendar.ParsedDuration) ArrayList(java.util.ArrayList) ICalTok(com.zimbra.common.calendar.ZCalendar.ICalTok) ZComponent(com.zimbra.common.calendar.ZCalendar.ZComponent) IRecurrence(com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence) List(java.util.List) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) ParsedDateTime(com.zimbra.common.calendar.ParsedDateTime) Attach(com.zimbra.common.calendar.Attach) ZParameter(com.zimbra.common.calendar.ZCalendar.ZParameter) Geo(com.zimbra.common.calendar.Geo) MailItem(com.zimbra.cs.mailbox.MailItem) ServiceException(com.zimbra.common.service.ServiceException) ZProperty(com.zimbra.common.calendar.ZCalendar.ZProperty) ParseException(java.text.ParseException)

Example 5 with IRecurrence

use of com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence in project zm-mailbox by Zimbra.

the class FriendlyCalendaringDescription method getRecur.

public static ZRecur getRecur(Invite invite) {
    ZRecur zr = null;
    Recurrence.IRecurrence r = invite.getRecurrence();
    if (r != null) {
        //which is a container of everything.
        assert r.getType() == Recurrence.TYPE_RECURRENCE;
        Recurrence.RecurrenceRule masterRule = (Recurrence.RecurrenceRule) r;
        for (Iterator<IRecurrence> iter = masterRule.addRulesIterator(); iter != null && iter.hasNext(); ) {
            r = iter.next();
            switch(r.getType()) {
                case Recurrence.TYPE_SINGLE_DATES:
                    //We don't support single instance.
                    assert false;
                    break;
                case Recurrence.TYPE_REPEATING:
                    Recurrence.SimpleRepeatingRule srr = (Recurrence.SimpleRepeatingRule) r;
                    zr = srr.getRule();
                    break;
                default:
                    //can't be anything else
                    assert false;
                    break;
            }
            //we don't support more than one RRULE/RDATE
            assert !iter.hasNext();
            break;
        }
        assert zr != null;
    }
    return zr;
}
Also used : IRecurrence(com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence) IRecurrence(com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence) IRecurrence(com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence)

Aggregations

IRecurrence (com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence)13 ParsedDateTime (com.zimbra.common.calendar.ParsedDateTime)10 ParsedDuration (com.zimbra.common.calendar.ParsedDuration)7 ICalTimeZone (com.zimbra.common.calendar.ICalTimeZone)4 Invite (com.zimbra.cs.mailbox.calendar.Invite)4 ArrayList (java.util.ArrayList)4 ICalTok (com.zimbra.common.calendar.ZCalendar.ICalTok)3 ZProperty (com.zimbra.common.calendar.ZCalendar.ZProperty)3 Element (com.zimbra.common.soap.Element)3 RecurrenceRule (com.zimbra.cs.mailbox.calendar.Recurrence.RecurrenceRule)3 Iterator (java.util.Iterator)3 TimeZoneMap (com.zimbra.common.calendar.TimeZoneMap)2 ZComponent (com.zimbra.common.calendar.ZCalendar.ZComponent)2 ZParameter (com.zimbra.common.calendar.ZCalendar.ZParameter)2 ServiceException (com.zimbra.common.service.ServiceException)2 Instance (com.zimbra.cs.mailbox.CalendarItem.Instance)2 RecurId (com.zimbra.cs.mailbox.calendar.RecurId)2 Recurrence (com.zimbra.cs.mailbox.calendar.Recurrence)2 ZRecur (com.zimbra.cs.mailbox.calendar.ZRecur)2 HashSet (java.util.HashSet)2