Search in sources :

Example 46 with ParsedDateTime

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

the class CalendarItem method expandInstances.

/**
     * Expand all the instances for the time period from start to end
     *
     * @param start
     * @param end
     * @param includeAlarmOnlyInstances
     * @return list of Instances for the specified time period
     */
public Collection<Instance> expandInstances(long start, long end, boolean includeAlarmOnlyInstances) throws ServiceException {
    long endAdjusted = end;
    long alarmInstStart = 0;
    if (includeAlarmOnlyInstances) {
        // range.
        if (mAlarmData != null) {
            alarmInstStart = mAlarmData.getNextInstanceStart();
            long nextAlarm = mAlarmData.getNextAtBase();
            if (nextAlarm >= start && nextAlarm < end) {
                if (alarmInstStart >= end)
                    endAdjusted = alarmInstStart + 1;
            }
        }
    }
    List<Instance> instances = new ArrayList<Instance>();
    if (mRecurrence != null) {
        long startTime = System.currentTimeMillis();
        instances = Recurrence.expandInstances(mRecurrence, getId(), start, endAdjusted);
        if (ZimbraLog.calendar.isDebugEnabled()) {
            long elapsed = System.currentTimeMillis() - startTime;
            ZimbraLog.calendar.debug("RECURRENCE EXPANSION for appt/task %s: start=%s, end=%s; took %sms.  %s instances", getId(), start, end, elapsed, instances.size());
        }
    } else {
        // organizer.
        if (mInvites != null) {
            for (Invite inv : mInvites) {
                if (// Skip canceled instances.
                inv.isCancel())
                    continue;
                ParsedDateTime dtStart = inv.getStartTime();
                long invStart = dtStart != null ? dtStart.getUtcTime() : 0;
                ParsedDateTime dtEnd = inv.getEffectiveEndTime();
                long invEnd = dtEnd != null ? dtEnd.getUtcTime() : 0;
                if ((invStart < endAdjusted && invEnd > start) || (dtStart == null)) {
                    Instance inst = new Instance(getId(), new InviteInfo(inv), dtStart != null, dtEnd != null, invStart, invEnd, inv.isAllDayEvent(), dtStart != null ? dtStart.getOffset() : 0, dtEnd != null ? dtEnd.getOffset() : 0, inv.hasRecurId(), false);
                    instances.add(inst);
                }
            }
        }
    }
    // Remove instances that aren't in the actual range.
    for (Iterator<Instance> iter = instances.iterator(); iter.hasNext(); ) {
        Instance inst = iter.next();
        if (inst.hasStart() && inst.hasEnd()) {
            long instStart = inst.getStart();
            long instEnd = inst.getEnd();
            // or instance starts after range end. (i.e. instance does not overlap range)
            if (instStart != alarmInstStart && (instEnd <= start || instStart >= end))
                iter.remove();
        }
    }
    return instances;
}
Also used : InviteInfo(com.zimbra.cs.mailbox.calendar.InviteInfo) ArrayList(java.util.ArrayList) ParsedDateTime(com.zimbra.common.calendar.ParsedDateTime) Invite(com.zimbra.cs.mailbox.calendar.Invite)

Example 47 with ParsedDateTime

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

the class CalendarItem method updateRecurrence.

private boolean updateRecurrence(long nextAlarm) throws ServiceException {
    long startTime, endTime;
    // update our recurrence rule, start with the initial rule
    Invite firstInv = getDefaultInviteOrNull();
    if (firstInv == null) {
        return false;
    }
    IRecurrence recur = firstInv.getRecurrence();
    if (recur instanceof Recurrence.RecurrenceRule) {
        mRecurrence = (IRecurrence) recur.clone();
        // now, go through the list of invites and find all the exceptions
        for (Invite cur : mInvites) {
            if (cur != firstInv) {
                String method = cur.getMethod();
                if (cur.isCancel()) {
                    assert (cur.hasRecurId());
                    if (cur.hasRecurId()) {
                        checkExdateIsSensible(cur.getRecurId());
                        Recurrence.CancellationRule cancelRule = new Recurrence.CancellationRule(cur.getRecurId());
                        ((Recurrence.RecurrenceRule) mRecurrence).addException(cancelRule);
                    }
                } else if (method.equals(ICalTok.REQUEST.toString()) || method.equals(ICalTok.PUBLISH.toString())) {
                    assert (cur.hasRecurId());
                    if (cur.hasRecurId() && cur.getStartTime() != null) {
                        checkRecurIdIsSensible(cur.getRecurId());
                        Recurrence.ExceptionRule exceptRule = null;
                        IRecurrence curRule = cur.getRecurrence();
                        if (curRule != null && curRule instanceof Recurrence.ExceptionRule) {
                            exceptRule = (Recurrence.ExceptionRule) curRule.clone();
                        } else {
                            // create a fake ExceptionRule wrapper around the single-instance
                            exceptRule = new Recurrence.ExceptionRule(cur.getRecurId(), cur.getStartTime(), cur.getEffectiveDuration(), new InviteInfo(cur));
                        }
                        ((Recurrence.RecurrenceRule) mRecurrence).addException(exceptRule);
                    } else {
                        sLog.debug("Got second invite with no RecurID: " + cur.toString());
                    }
                }
            }
        }
        // Find the earliest DTSTART and latest DTEND.  We're just looking for the bounds, so we won't worry
        // about cancelled instances.
        ParsedDateTime earliestStart = null;
        ParsedDateTime latestEnd = null;
        for (Invite cur : mInvites) {
            if (!cur.isCancel()) {
                ParsedDateTime start = cur.getStartTime();
                if (earliestStart == null)
                    earliestStart = start;
                else if (start != null && start.compareTo(earliestStart) < 0)
                    earliestStart = start;
                ParsedDateTime end = cur.getEffectiveEndTime();
                if (latestEnd == null)
                    latestEnd = end;
                else if (end != null && end.compareTo(latestEnd) > 0)
                    latestEnd = end;
            }
        }
        // Take the later of latestEnd and recurrence's end time.
        ParsedDateTime recurEnd = mRecurrence.getEndTime();
        if (latestEnd == null)
            latestEnd = recurEnd;
        else if (recurEnd != null && recurEnd.compareTo(latestEnd) > 0)
            latestEnd = recurEnd;
        // update the start and end time in the CalendarItem table if
        // necessary
        startTime = earliestStart != null ? earliestStart.getUtcTime() : 0;
        endTime = latestEnd != null ? latestEnd.getUtcTime() : 0;
    } else {
        mRecurrence = null;
        startTime = 0;
        endTime = 0;
        for (Invite inv : mInvites) {
            if (!inv.isCancel()) {
                ParsedDateTime dtStart = inv.getStartTime();
                long st = dtStart != null ? dtStart.getUtcTime() : 0;
                if (st != 0 && (st < startTime || startTime == 0))
                    startTime = st;
                ParsedDateTime dtEnd = inv.getEffectiveEndTime();
                long et = dtEnd != null ? dtEnd.getUtcTime() : 0;
                if (et != 0 && et > endTime)
                    endTime = et;
            }
        }
    }
    // Adjust start/end times before recomputing alarm because alarm computation depends on those times.
    boolean timesChanged = false;
    if (mStartTime != startTime || mEndTime != endTime) {
        timesChanged = true;
        mStartTime = startTime;
        mEndTime = endTime;
    }
    // Recompute next alarm.  Bring appointment start time forward to the alarm time,
    // if the next alarm is before the first instance.
    recomputeNextAlarm(nextAlarm, false, false);
    if (mAlarmData != null) {
        long newNextAlarm = mAlarmData.getNextAtBase();
        if (newNextAlarm > 0 && newNextAlarm < startTime && mStartTime != startTime) {
            timesChanged = true;
            mStartTime = newNextAlarm;
        }
    }
    if (timesChanged) {
        if (ZimbraLog.calendar.isDebugEnabled()) {
            ZimbraLog.calendar.debug("Updating recurrence for %s.  nextAlarm=%d.", getMailopContext(this), nextAlarm);
        }
        DbMailItem.updateInCalendarItemTable(this);
    }
    return true;
}
Also used : RecurrenceRule(com.zimbra.cs.mailbox.calendar.Recurrence.RecurrenceRule) IRecurrence(com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence) IRecurrence(com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence) Recurrence(com.zimbra.cs.mailbox.calendar.Recurrence) InviteInfo(com.zimbra.cs.mailbox.calendar.InviteInfo) ParsedDateTime(com.zimbra.common.calendar.ParsedDateTime) Invite(com.zimbra.cs.mailbox.calendar.Invite)

Example 48 with ParsedDateTime

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

the class CalendarMailSender method createCalendarInviteDeniedMessage.

private static MimeMessage createCalendarInviteDeniedMessage(Account fromAccount, Account senderAccount, boolean onBehalfOf, boolean allowPrivateAccess, Address toAddr, Invite inv, MsgKey bodyTextKey) throws ServiceException {
    Locale locale = !onBehalfOf ? fromAccount.getLocale() : senderAccount.getLocale();
    Identity fromIdentity = getTargetedIdentity(fromAccount, inv);
    StringBuilder replyText = new StringBuilder();
    String sigText = getSignatureText(fromAccount, fromIdentity, Provisioning.A_zimbraPrefCalendarAutoDenySignatureId);
    if (sigText == null || sigText.length() < 1)
        sigText = L10nUtil.getMessage(bodyTextKey, locale);
    if (sigText != null && sigText.length() > 0)
        replyText.append(sigText).append("\r\n");
    attachInviteSummary(replyText, inv, null, locale);
    String subject = L10nUtil.getMessage(MsgKey.calendarReplySubjectDecline, locale) + ": " + inv.getName();
    String uid = inv.getUid();
    ParsedDateTime exceptDt = null;
    if (inv.hasRecurId())
        exceptDt = inv.getRecurId().getDt();
    Invite replyInv = replyToInvite(fromAccount, senderAccount, onBehalfOf, allowPrivateAccess, inv, VERB_DECLINE, subject, exceptDt);
    ZVCalendar iCal = replyInv.newToICalendar(true);
    Address fromAddr = fromIdentity.getFriendlyEmailAddress();
    Address senderAddr = null;
    if (onBehalfOf)
        senderAddr = AccountUtil.getFriendlyEmailAddress(senderAccount);
    List<Address> toAddrs = new ArrayList<Address>(1);
    toAddrs.add(toAddr);
    return createCalendarMessage(senderAccount, fromAddr, senderAddr, toAddrs, subject, replyText.toString(), null, uid, iCal);
}
Also used : Locale(java.util.Locale) ZVCalendar(com.zimbra.common.calendar.ZCalendar.ZVCalendar) Address(javax.mail.Address) InternetAddress(javax.mail.internet.InternetAddress) JavaMailInternetAddress(com.zimbra.common.mime.shim.JavaMailInternetAddress) ArrayList(java.util.ArrayList) ParsedDateTime(com.zimbra.common.calendar.ParsedDateTime) Identity(com.zimbra.cs.account.Identity)

Example 49 with ParsedDateTime

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

the class CalendarMailSender method createCancelMessage.

public static MimeMessage createCancelMessage(Account fromAccount, Account senderAccount, boolean asAdmin, boolean onBehalfOf, List<Address> toAddrs, CalendarItem calItem, Invite inv, String text, ZVCalendar iCal) throws ServiceException {
    Locale locale = !onBehalfOf ? fromAccount.getLocale() : senderAccount.getLocale();
    Invite defaultInv = calItem.getDefaultInviteOrNull();
    boolean hidePrivate = !calItem.isPublic() && !calItem.allowPrivateAccess(senderAccount, asAdmin);
    String invSubject;
    if (hidePrivate)
        invSubject = L10nUtil.getMessage(MsgKey.calendarSubjectWithheld, locale);
    else
        invSubject = inv != null ? inv.getName() : "";
    String sbj = getCancelSubject(invSubject, locale);
    StringBuilder sb = new StringBuilder(text);
    sb.append("\r\n\r\n");
    if (!inv.equals(defaultInv) && inv.getStartTime() != null && inv.getRecurId() != null) {
        sb.append(L10nUtil.getMessage(MsgKey.calendarCancelAppointmentInstanceWhich, locale));
        sb.append(" ");
        ParsedDateTime start = inv.getStartTime();
        TimeZone tz = start.getTimeZone();
        Date startDate = new Date(start.getUtcTime());
        sb.append(CalendarMailSender.formatDateTime(startDate, tz, locale));
        sb.append("\r\n\r\n");
    }
    if (!hidePrivate) {
        MimeMessage mmInv = inv.getMimeMessage();
        if (mmInv == null && defaultInv != null)
            mmInv = defaultInv.getMimeMessage();
        if (mmInv != null)
            attachInviteSummary(sb, inv, mmInv, locale);
    }
    Address from = AccountUtil.getFriendlyEmailAddress(fromAccount);
    Address sender = null;
    if (onBehalfOf)
        sender = AccountUtil.getFriendlyEmailAddress(senderAccount);
    return createCalendarMessage(senderAccount, from, sender, toAddrs, sbj, sb.toString(), null, defaultInv != null ? defaultInv.getUid() : "unknown", iCal);
}
Also used : Locale(java.util.Locale) ICalTimeZone(com.zimbra.common.calendar.ICalTimeZone) TimeZone(java.util.TimeZone) Address(javax.mail.Address) InternetAddress(javax.mail.internet.InternetAddress) JavaMailInternetAddress(com.zimbra.common.mime.shim.JavaMailInternetAddress) ZMimeMessage(com.zimbra.common.zmime.ZMimeMessage) MimeMessage(javax.mail.internet.MimeMessage) ParsedDateTime(com.zimbra.common.calendar.ParsedDateTime) Date(java.util.Date)

Example 50 with ParsedDateTime

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

the class Alarm method decodeMetadata.

/**
     * Create an Alarm from Metadata.  Return value may be null.
     * @param meta
     * @return
     * @throws ServiceException
     * @throws ParseException
     */
public static Alarm decodeMetadata(Metadata meta) throws ServiceException {
    Action action = expandAction(meta.get(FN_ACTION));
    if (!actionAllowed(action))
        return null;
    TriggerType tt = expandTriggerType(meta.get(FN_TRIGGER_TYPE));
    TriggerRelated triggerRelated = null;
    ParsedDuration triggerRelative = null;
    ParsedDateTime triggerAbsolute = null;
    if (TriggerType.ABSOLUTE.equals(tt)) {
        try {
            triggerAbsolute = ParsedDateTime.parseUtcOnly(meta.get(FN_TRIGGER_ABSOLUTE));
        } catch (ParseException e) {
            throw ServiceException.FAILURE("Error parsing metadata for alarm", e);
        }
    } else {
        triggerRelative = ParsedDuration.parse(meta.get(FN_TRIGGER_RELATIVE));
        triggerRelated = expandTriggerRelated(meta.get(FN_TRIGGER_RELATED, null));
    }
    ParsedDuration repeatDuration = null;
    int repeatCount = 0;
    String val = meta.get(FN_REPEAT_DURATION, null);
    if (val != null) {
        repeatDuration = ParsedDuration.parse(val);
        repeatCount = (int) meta.getLong(FN_REPEAT_COUNT, 0);
    }
    String description = meta.get(FN_DESCRIPTION, null);
    String summary = meta.get(FN_SUMMARY, null);
    Attach attach = null;
    Metadata metaAttach = meta.getMap(FN_ATTACH, true);
    if (metaAttach != null)
        attach = Util.decodeAttachFromMetadata(metaAttach);
    int numAts = (int) meta.getLong(FN_NUM_ATTENDEES, 0);
    List<ZAttendee> attendees = new ArrayList<ZAttendee>(numAts);
    for (int i = 0; i < numAts; i++) {
        try {
            Metadata metaAttendee = meta.getMap(FN_ATTENDEE + i, true);
            if (metaAttendee != null)
                attendees.add(new ZAttendee(metaAttendee));
        } catch (ServiceException e) {
            ZimbraLog.calendar.warn("Problem decoding attendee " + i + " in ALARM ");
        }
    }
    Alarm alarm = new Alarm(action, tt, triggerRelated, triggerRelative, triggerAbsolute, repeatDuration, repeatCount, description, summary, attach, attendees, Util.decodeXPropsFromMetadata(meta));
    return alarm;
}
Also used : ParsedDuration(com.zimbra.common.calendar.ParsedDuration) Attach(com.zimbra.common.calendar.Attach) CalendarAttach(com.zimbra.soap.mail.type.CalendarAttach) Metadata(com.zimbra.cs.mailbox.Metadata) ArrayList(java.util.ArrayList) ServiceException(com.zimbra.common.service.ServiceException) ParsedDateTime(com.zimbra.common.calendar.ParsedDateTime) ParseException(java.text.ParseException)

Aggregations

ParsedDateTime (com.zimbra.common.calendar.ParsedDateTime)66 ParsedDuration (com.zimbra.common.calendar.ParsedDuration)23 Invite (com.zimbra.cs.mailbox.calendar.Invite)20 ICalTimeZone (com.zimbra.common.calendar.ICalTimeZone)18 ParseException (java.text.ParseException)16 ArrayList (java.util.ArrayList)16 IRecurrence (com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence)15 ZProperty (com.zimbra.common.calendar.ZCalendar.ZProperty)14 Element (com.zimbra.common.soap.Element)13 RecurId (com.zimbra.cs.mailbox.calendar.RecurId)11 TimeZoneMap (com.zimbra.common.calendar.TimeZoneMap)10 Account (com.zimbra.cs.account.Account)10 ZOrganizer (com.zimbra.cs.mailbox.calendar.ZOrganizer)10 ZVCalendar (com.zimbra.common.calendar.ZCalendar.ZVCalendar)9 ICalTok (com.zimbra.common.calendar.ZCalendar.ICalTok)8 ZAttendee (com.zimbra.cs.mailbox.calendar.ZAttendee)8 ZComponent (com.zimbra.common.calendar.ZCalendar.ZComponent)7 ZParameter (com.zimbra.common.calendar.ZCalendar.ZParameter)7 ServiceException (com.zimbra.common.service.ServiceException)7 CalendarItem (com.zimbra.cs.mailbox.CalendarItem)7