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;
}
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;
}
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;
}
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;
}
Aggregations