Search in sources :

Example 1 with Recurrence

use of org.bedework.icalendar.RecurUtil.Recurrence in project bw-calendar-engine by Bedework.

the class Events method processExpanded.

private Collection<EventInfo> processExpanded(final Collection<EventInfo> events, final RecurringRetrievalMode recurRetrieval) throws CalFacadeException {
    Collection<EventInfo> res = new ArrayList<>();
    for (EventInfo ei : events) {
        BwEvent ev = ei.getEvent();
        if (!ev.getRecurring()) {
            res.add(ei);
            continue;
        }
        CurrentAccess ca = ei.getCurrentAccess();
        Set<EventInfo> oveis = ei.getOverrides();
        if (!Util.isEmpty(oveis)) {
            for (EventInfo oei : oveis) {
                if (oei.getEvent().inDateTimeRange(recurRetrieval.start.getDate(), recurRetrieval.end.getDate())) {
                    oei.setRetrievedEvent(ei);
                    res.add(oei);
                }
            }
        }
        /* Generate non-overridden instances. */
        final Collection<Recurrence> instances = RecurUtil.getRecurrences(ei, getAuthpars().getMaxYears(), getAuthpars().getMaxInstances(), recurRetrieval.getStartDate(), recurRetrieval.getEndDate());
        if (instances == null) {
            return res;
        }
        for (final Recurrence rec : instances) {
            if (rec.override != null) {
                continue;
            }
            final BwEventAnnotation ann = new BwEventAnnotation();
            ann.setDtstart(rec.start);
            ann.setDtend(rec.end);
            ann.setRecurrenceId(rec.recurrenceId);
            ann.setOwnerHref(ev.getOwnerHref());
            // Call it an override
            ann.setOverride(true);
            ann.setTombstoned(false);
            ann.setName(ev.getName());
            ann.setUid(ev.getUid());
            ann.setTarget(ev);
            ann.setMaster(ev);
            final BwEvent proxy = new BwEventProxy(ann);
            final EventInfo oei = new EventInfo(proxy);
            oei.setCurrentAccess(ei.getCurrentAccess());
            oei.setRetrievedEvent(ei);
            res.add(oei);
        }
    }
    return res;
}
Also used : Recurrence(org.bedework.icalendar.RecurUtil.Recurrence) CoreEventInfo(org.bedework.calcorei.CoreEventInfo) EventInfo(org.bedework.calfacade.svc.EventInfo) BwEventAnnotation(org.bedework.calfacade.BwEventAnnotation) ArrayList(java.util.ArrayList) BwEvent(org.bedework.calfacade.BwEvent) CurrentAccess(org.bedework.access.Acl.CurrentAccess) BwEventProxy(org.bedework.calfacade.BwEventProxy)

Example 2 with Recurrence

use of org.bedework.icalendar.RecurUtil.Recurrence in project bw-calendar-engine by Bedework.

the class InRequest method checkBusy.

private RecurInfo checkBusy(final CalSvcI svci, final String excludeUid, final Collection<Recurrence> recurrences, final BwOrganizer org, final String uid, final boolean doubleBookOk) throws CalFacadeException {
    /* TODO
     * We should chunk up the freebusy into fewer requests over longer periods.
     * That means we have to figure out the overlaps with the returned info ourselves.
     *
     * If we don't do that we could fire off 100s of freebusy queries.
     */
    RecurInfo res = new RecurInfo();
    for (Recurrence r : recurrences) {
        boolean busy = false;
        if (!doubleBookOk) {
            // See if there are any events booked during this time.
            busy = checkBusy(svci, excludeUid, r.start, r.end, org, uid);
            if (debug) {
                trace("busy=" + busy + " for " + r.start + " to " + r.end);
            }
        }
        res.add(r, busy);
    }
    return res;
}
Also used : Recurrence(org.bedework.icalendar.RecurUtil.Recurrence)

Example 3 with Recurrence

use of org.bedework.icalendar.RecurUtil.Recurrence in project bw-calendar-engine by Bedework.

the class InRequest method updateAttendeeCopy.

/**
 * Update our (the attendees) copy of the event from the inbox copy. We
 * should have received cancellations for any instances we are no longer
 * attending. This could include extra instances (fewer exdates) for which we
 * have received no notifications.
 *
 * <p>The partstat on those instances should be currently set to NEEDS-ACTION
 * and we need to add some information to the event to allow us to highlight
 * those instances.
 *
 * <p>This may be why Apple is adding a needs reply x-prop?
 *
 * @param ourCopy
 * @param inCopy
 * @param attUri - our attendee uri
 * @return boolean true for OK
 * @throws CalFacadeException
 */
private boolean updateAttendeeCopy(final EventInfo ourCopy, final EventInfo inCopy, final String attUri) throws CalFacadeException {
    /* Update from an incoming inbox event. The incoming event may be a partial
     * recurring event, that is we may have a suppressed master and an incomplete
     * set of overrides.
     *
     * If the master is suppressed we simply update from each supplied override.
     *
     * We do not remove overrides if they are not in the incoming event. We need
     * an explicit CANCEL.
     */
    BwEvent ourEv = ourCopy.getEvent();
    BwEvent inEv = inCopy.getEvent();
    boolean ourMaster = !(ourEv instanceof BwEventProxy);
    boolean inMaster = !(inEv instanceof BwEventProxy);
    if (ourMaster != inMaster) {
        throw new CalFacadeException("Only one master event for updateAttendeeCopy");
    }
    boolean ourRecurMaster = ourMaster && ourEv.getRecurring();
    if (!inMaster || !inEv.getSuppressed()) {
        if (debug) {
            trace("Update the master event or single recurrence");
        }
        if (!updateAttendeeFields(ourCopy, inCopy, attUri)) {
            return false;
        }
    }
    if (!ourRecurMaster) {
        return true;
    }
    if (inCopy.getOverrides() != null) {
        // Go through all the overrides
        Collection<Recurrence> recurrences = null;
        for (EventInfo inOvei : inCopy.getOverrides()) {
            BwEvent inOv = inOvei.getEvent();
            String rid = inOv.getRecurrenceId();
            EventInfo ourOvei = findOverride(ourCopy, rid);
            if (ourOvei.getEvent().unsaved()) {
                if (recurrences == null) {
                    recurrences = getRecurrences(ourCopy);
                }
                Recurrence rec = null;
                for (Recurrence r : recurrences) {
                    if (rid.equals(r.recurrenceId)) {
                        rec = r;
                        break;
                    }
                }
                if (rec == null) {
                    // Not in set
                    BwDateTime bwrdt = BwDateTime.fromUTC(rid.length() == 8, rid);
                    ourEv.addRdate(bwrdt);
                }
            }
            if (!updateAttendeeCopy(ourOvei, inOvei, attUri)) {
                return false;
            }
        }
    }
    /* The incoming event may have exdates that are not in the
       attendee copy. Remove each of those and add an override cancelling
       that instance.
     */
    final Set<BwDateTime> inExdates = inCopy.getEvent().getExdates();
    if (!Util.isEmpty(inExdates)) {
        final Set<BwDateTime> ourExdates = ourCopy.getEvent().getExdates();
        for (final BwDateTime exdt : inExdates) {
            if (!Util.isEmpty(ourExdates) && ourExdates.contains(exdt)) {
                continue;
            }
            final EventInfo ourOvei = findOverride(ourCopy, exdt.getDate());
            ourOvei.getEvent().setStatus(BwEvent.statusCancelled);
        }
    }
    return true;
}
Also used : Recurrence(org.bedework.icalendar.RecurUtil.Recurrence) EventInfo(org.bedework.calfacade.svc.EventInfo) BwDateTime(org.bedework.calfacade.BwDateTime) BwEvent(org.bedework.calfacade.BwEvent) BwString(org.bedework.calfacade.BwString) BwEventProxy(org.bedework.calfacade.BwEventProxy) CalFacadeException(org.bedework.calfacade.exc.CalFacadeException)

Example 4 with Recurrence

use of org.bedework.icalendar.RecurUtil.Recurrence in project bw-calendar-engine by Bedework.

the class InRequest method autoRespond.

/* ====================================================================
                      Private methods
     ==================================================================== */
private boolean autoRespond(final CalSvcI svci, final EventInfo ourCopy, final EventInfo inboxEi, final boolean doubleBookOk, final String uri) throws CalFacadeException {
    BwEvent inboxEv = inboxEi.getEvent();
    String owner = inboxEv.getOwnerHref();
    if (ourCopy == null) {
        // Error - deleted while we did this?
        if (debug) {
            trace("InSchedule - no event for auto respond for " + owner);
        }
        return false;
    }
    BwOrganizer org = new BwOrganizer();
    org.setOrganizerUri(uri);
    BwAttendee att = null;
    BwEvent ourEvent = ourCopy.getEvent();
    String now = DateTimeUtil.isoDateTimeUTC(new Date());
    if (!ourEvent.getRecurring()) {
        if (ourEvent.getDtend().getDate().compareTo(now) < 0) {
            return false;
        }
        att = ourEvent.findAttendee(uri);
        if (att == null) {
            // Error?
            if (debug) {
                trace("InSchedule - no attendee on our copy for auto respond for " + owner);
            }
            return false;
        }
        if (debug) {
            trace("send response event for " + owner + " " + inboxEv.getName());
        }
        // We're about to reply.
        att.setRsvp(false);
        String partStat = IcalDefs.partstatValAccepted;
        ourEvent.removeXproperties(BwXproperty.appleNeedsReply);
        if (!doubleBookOk) {
            // See if there are any events booked during this time.
            if (checkBusy(svci, ourEvent.getUid(), inboxEv.getDtstart(), inboxEv.getDtend(), org, inboxEv.getUid())) {
                partStat = IcalDefs.partstatValDeclined;
            } else {
                ourEvent.setTransparency(IcalDefs.transparencyOpaque);
            }
        }
        ourEvent.setScheduleMethod(ScheduleMethods.methodTypeReply);
        att = (BwAttendee) att.clone();
        ourEvent.removeAttendee(att);
        ourEvent.addAttendee(att);
        att.setPartstat(partStat);
        return true;
    }
    // Recurring event - do the above per recurrence
    AuthProperties authpars = svci.getAuthProperties();
    int maxYears = authpars.getMaxYears();
    int maxInstances = authpars.getMaxInstances();
    Collection<Recurrence> recurrences = RecurUtil.getRecurrences(inboxEi, maxYears, maxInstances, now, null);
    if (Util.isEmpty(recurrences)) {
        return false;
    }
    if (debug) {
        trace("autoRespond: " + recurrences.size() + " instances");
    }
    /* Assume accept and then override with declines - assuming we're in the
     * master
     */
    ourEvent.removeXproperties(BwXproperty.appleNeedsReply);
    boolean masterSupressed = true;
    if (!inboxEv.getSuppressed()) {
        masterSupressed = false;
        att = ourEvent.findAttendee(uri);
        if (att != null) {
            // It should never be null
            att.setRsvp(false);
            att.setPartstat(IcalDefs.partstatValAccepted);
        }
        ourEvent.setTransparency(IcalDefs.transparencyOpaque);
    }
    RecurInfo rinfo = checkBusy(svci, ourEvent.getUid(), recurrences, org, inboxEv.getUid(), doubleBookOk);
    /* If we have a master then we should set its status to cover the largest
     * number of overrides - if any.
     *
     * The easiest case is no overrides and all accepted or all declined.
     *
     * Otherwise we have to update or add overrides.
     */
    boolean allAcceptedOrDeclined = (rinfo.availCt == 0) || (rinfo.busyCt == 0);
    boolean masterAccept = rinfo.availCt >= rinfo.busyCt;
    String masterPartStat;
    if (masterAccept) {
        masterPartStat = IcalDefs.partstatValAccepted;
    } else {
        masterPartStat = IcalDefs.partstatValDeclined;
    }
    if (!masterSupressed) {
        att = ourEvent.findAttendee(uri);
        if (!masterPartStat.equals(att.getPartstat())) {
            att.setPartstat(masterPartStat);
        }
        if (masterAccept) {
            ourEvent.setTransparency(IcalDefs.transparencyOpaque);
        } else {
            ourEvent.setTransparency(IcalDefs.transparencyTransparent);
        }
    }
    if (allAcceptedOrDeclined) {
        // Ensure any overrides have the same status
        for (EventInfo oei : ourCopy.getOverrides()) {
            BwEvent override = oei.getEvent();
            att = override.findAttendee(uri);
            att = (BwAttendee) att.clone();
            // We're about to reply.
            att.setRsvp(false);
            override.removeAttendee(att);
            override.addAttendee(att);
            if (!masterPartStat.equals(att.getPartstat())) {
                att.setPartstat(masterPartStat);
            }
            if (masterAccept) {
                override.setTransparency(IcalDefs.transparencyOpaque);
            } else {
                override.setTransparency(IcalDefs.transparencyTransparent);
            }
            override.removeXproperties(BwXproperty.appleNeedsReply);
        }
        return true;
    }
    for (RecurrenceInfo ri : rinfo.ris) {
        Recurrence r = ri.r;
        // if (!masterSupressed && !ri.busy && (r.override == null)) {
        // // fine
        // continue;
        // }
        boolean mustOverride = masterAccept == ri.busy;
        EventInfo oei = ourCopy.findOverride(r.recurrenceId, mustOverride);
        if (oei == null) {
            continue;
        }
        BwEvent override = oei.getEvent();
        if (((BwEventProxy) override).getRef().unsaved()) {
            override.setDtstart(r.start);
            override.setDtend(r.end);
            override.setDuration(BwDateTime.makeDuration(r.start, r.end).toString());
        }
        att = override.findAttendee(uri);
        if (att == null) {
            // Guess we weren't invited
            continue;
        }
        att = (BwAttendee) att.clone();
        // We're about to reply.
        att.setRsvp(false);
        override.removeAttendee(att);
        override.addAttendee(att);
        if (!ri.busy) {
            att.setPartstat(IcalDefs.partstatValAccepted);
            override.setTransparency(IcalDefs.transparencyOpaque);
        } else {
            att.setPartstat(IcalDefs.partstatValDeclined);
            override.setTransparency(IcalDefs.transparencyTransparent);
        }
        override.removeXproperties(BwXproperty.appleNeedsReply);
    }
    return true;
}
Also used : Recurrence(org.bedework.icalendar.RecurUtil.Recurrence) AuthProperties(org.bedework.calfacade.configs.AuthProperties) EventInfo(org.bedework.calfacade.svc.EventInfo) BwEvent(org.bedework.calfacade.BwEvent) BwString(org.bedework.calfacade.BwString) Date(java.util.Date) BwAttendee(org.bedework.calfacade.BwAttendee) BwOrganizer(org.bedework.calfacade.BwOrganizer)

Aggregations

Recurrence (org.bedework.icalendar.RecurUtil.Recurrence)4 BwEvent (org.bedework.calfacade.BwEvent)3 EventInfo (org.bedework.calfacade.svc.EventInfo)3 BwEventProxy (org.bedework.calfacade.BwEventProxy)2 BwString (org.bedework.calfacade.BwString)2 ArrayList (java.util.ArrayList)1 Date (java.util.Date)1 CurrentAccess (org.bedework.access.Acl.CurrentAccess)1 CoreEventInfo (org.bedework.calcorei.CoreEventInfo)1 BwAttendee (org.bedework.calfacade.BwAttendee)1 BwDateTime (org.bedework.calfacade.BwDateTime)1 BwEventAnnotation (org.bedework.calfacade.BwEventAnnotation)1 BwOrganizer (org.bedework.calfacade.BwOrganizer)1 AuthProperties (org.bedework.calfacade.configs.AuthProperties)1 CalFacadeException (org.bedework.calfacade.exc.CalFacadeException)1