use of org.bedework.calfacade.BwDateTime in project bw-calendar-engine by Bedework.
the class EventPeriods method addPeriod.
/**
* @param pstart
* @param pend
* @param type
* @throws CalFacadeException
*/
public void addPeriod(final BwDateTime pstart, final BwDateTime pend, final int type) throws CalFacadeException {
// Ignore if times were specified and this period is outside the times
/* Don't report out of the requested period */
String dstart;
String dend;
if ((pstart.after(end)) || (pend.before(start))) {
// XXX Should get here - but apparently we do.
return;
}
if (pstart.before(start)) {
dstart = start.getDate();
} else {
dstart = pstart.getDate();
}
if (pend.after(end)) {
dend = end.getDate();
} else {
dend = pend.getDate();
}
try {
DateTime psdt = new DateTime(dstart);
DateTime pedt = new DateTime(dend);
psdt.setUtc(true);
pedt.setUtc(true);
add(new EventPeriod(psdt, pedt, type));
} catch (Throwable t) {
throw new CalFacadeException(t);
}
}
use of org.bedework.calfacade.BwDateTime in project bw-calendar-engine by Bedework.
the class SchedulingBase method copyEventInfo.
/**
* Same as copyEventInfo(EventInfo, BwPrincipal) except it only copies
* significant changes.
*
* @param ei
* @param significantChangesOnly
* @param owner
* @return a copy of the event.
* @throws CalFacadeException
*/
protected EventInfo copyEventInfo(final EventInfo ei, final boolean significantChangesOnly, final BwPrincipal owner) throws CalFacadeException {
BwEvent ev = ei.getEvent();
BwEvent newEv = copyEvent(ev, null, owner);
StringBuilder changeInfo = new StringBuilder();
changeInfo.append(ev.getDtstamp());
final boolean cancel = ev.getScheduleMethod() == ScheduleMethods.methodTypeCancel;
final boolean adding = ei.getUpdResult().adding;
final boolean reply = ev.getScheduleMethod() == ScheduleMethods.methodTypeReply;
if (cancel) {
changeInfo.append(";CANCEL");
} else if (adding) {
changeInfo.append(";CREATE");
} else if (reply) {
changeInfo.append(";REPLY");
} else {
changeInfo.append(";UPDATE");
}
if (adding || cancel) {
changeInfo.append(";MASTER");
} else {
addChangeInfo(ei, changeInfo, "MASTER");
}
if (!ev.getRecurring()) {
setChangeInfo(newEv, changeInfo);
return new EventInfo(newEv);
}
if (cancel) {
/* Collect any attendees in overrides not in the copied master */
Set<EventInfo> overrides = ei.getOverrides();
if (overrides != null) {
for (EventInfo oei : overrides) {
for (BwAttendee ovatt : oei.getEvent().getAttendees()) {
if (newEv.findAttendee(ovatt.getAttendeeUri()) == null) {
newEv.addAttendee((BwAttendee) ovatt.clone());
}
}
}
}
setChangeInfo(newEv, changeInfo);
return new EventInfo(newEv);
}
boolean fromOrganizer = ev.getOrganizerSchedulingObject();
boolean attendeeInMaster = false;
String uri = getSvc().getDirectories().principalToCaladdr(owner);
if (fromOrganizer) {
attendeeInMaster = ev.findAttendee(uri) != null;
}
/* Save the status - we may change to master-suppressed */
String masterStatus = newEv.getStatus();
/* We may suppress the master event if there is no significant change and
* we only want significant changes or if the attendee is not an attendee
* of the master event.
*/
boolean masterSuppressed = false;
boolean significant = ei.getChangeset(getPrincipalHref()).getSignificantChange();
if (fromOrganizer && !attendeeInMaster) {
masterSuppressed = true;
}
List<String> deletedRecurids = null;
if (masterSuppressed) {
// Attendee will appear in overrides. Remove rules and r/exdates
if (!Util.isEmpty(ei.getUpdResult().deletedInstances)) {
deletedRecurids = new ArrayList<>();
for (BwRecurrenceInstance ri : ei.getUpdResult().deletedInstances) {
deletedRecurids.add(ri.getRecurrenceId());
}
}
if (newEv.getRrules() != null) {
newEv.getRrules().clear();
}
if (newEv.getRdates() != null) {
newEv.getRdates().clear();
}
if (newEv.getExrules() != null) {
newEv.getExrules().clear();
}
if (newEv.getExdates() != null) {
newEv.getExdates().clear();
}
newEv.setSuppressed(true);
}
Set<EventInfo> overrides = ei.getOverrides();
Set<EventInfo> newovs = new TreeSet<>();
if (overrides != null) {
for (EventInfo oei : overrides) {
BwEvent oev = oei.getEvent();
boolean attendeeInOverride = oev.findAttendee(uri) != null;
if (!masterSuppressed && attendeeInMaster && attendeeInOverride) {
if (significantChangesOnly) {
significant = oei.getChangeset(getPrincipalHref()).getSignificantChange();
if (!oei.getNewEvent() && !significant) {
continue;
}
}
}
if (fromOrganizer) {
if (!masterSuppressed && attendeeInMaster) {
/* If the attendee is not in this override, add an exdate to the master
*/
if (!attendeeInOverride) {
String rid = oev.getRecurrenceId();
BwDateTime bwrdt = BwDateTime.fromUTC(rid.length() == 8, rid);
newEv.addExdate(bwrdt);
continue;
}
} else if (attendeeInOverride) {
/* Add this override as an rdate */
String rid = oev.getRecurrenceId();
BwDateTime bwrdt = BwDateTime.fromUTC(rid.length() == 8, rid);
newEv.addRdate(bwrdt);
if ((deletedRecurids != null) && deletedRecurids.contains(oev.getRecurrenceId())) {
oev.setStatus(BwEvent.statusCancelled);
} else if ((oev.getStatus() != null) && oev.getStatus().equals(BwEvent.statusMasterSuppressed)) {
// Not overridden - set to saved master value
oev.setStatus(masterStatus);
}
oev.setSequence(ev.getSequence());
} else {
continue;
}
}
if (adding || cancel) {
changeInfo.append(";RID=");
changeInfo.append(oev.getRecurrenceId());
} else {
addChangeInfo(ei, changeInfo, oev.getRecurrenceId());
}
newovs.add(new EventInfo(copyEvent(oev, newEv, owner)));
}
}
setChangeInfo(newEv, changeInfo);
return new EventInfo(newEv, newovs);
}
use of org.bedework.calfacade.BwDateTime in project bw-calendar-engine by Bedework.
the class FreeAndBusyHandler method granulateFreeBusy.
/* ====================================================================
* Private methods
* ==================================================================== */
/*
private void addFbcal(Collection<BwCalendar> cals,
BwCalendar cal) throws CalFacadeException {
if (cal.getCalType() == BwCalendar.calTypeCollection) {
// Leaf
cals.add(cal);
return;
}
Collection<BwCalendar> chs = getSvc().getCalendarsHandler().getChildren(cal);
for (BwCalendar ch: chs) {
addFbcal(cals, ch);
}
}
*/
private void granulateFreeBusy(final FbGranulatedResponse fbresp, final BwEvent fb, final BwDateTime start, final BwDateTime end, final BwDuration granularity) throws CalFacadeException {
DateTime startDt;
DateTime endDt;
try {
startDt = new DateTime(start.getDate());
endDt = new DateTime(end.getDate());
} catch (ParseException pe) {
throw new CalFacadeException(pe);
}
if (fb.getDtstart().after(start)) {
// XXX Should warn - or fill in with tentative?
// warn("Response start after requested start");
}
if (fb.getDtend().before(end)) {
// XXX Should warn - or fill in with tentative?
// warn("Response end before requested end");
}
fbresp.setStart(start);
fbresp.setEnd(end);
Collection<EventPeriod> periods = new ArrayList<EventPeriod>();
if (fb.getFreeBusyPeriods() != null) {
for (BwFreeBusyComponent fbcomp : fb.getFreeBusyPeriods()) {
for (Period p : fbcomp.getPeriods()) {
DateTime pstart = p.getStart();
DateTime pend = p.getEnd();
if (!pend.isUtc()) {
pend.setUtc(true);
}
/* Adjust for servers sending times outside requested range */
if (pend.after(endDt)) {
pend = endDt;
}
if (pstart.before(startDt)) {
pstart = startDt;
}
if (!pend.after(pstart)) {
continue;
}
periods.add(new EventPeriod(pstart, pend, fbcomp.getType()));
}
}
}
GetPeriodsPars gpp = new GetPeriodsPars();
gpp.periods = periods;
gpp.startDt = start;
gpp.dur = granularity;
BwDateTime bwend = end;
Collection<EventPeriod> respeps = new ArrayList<EventPeriod>();
fbresp.eps = respeps;
// XXX do this better
int limit = 10000;
/* endDt is null first time through, then represents end of last
* segment.
*/
while ((gpp.endDt == null) || (gpp.endDt.before(bwend))) {
// }
if (limit < 0) {
throw new CalFacadeException("org.bedework.svci.limit.exceeded");
}
limit--;
Collection<?> periodEvents = Granulator.getPeriodsEvents(gpp);
/* Some events fall in the period. Add an entry.
* We eliminated cancelled events earler. Now we should set the
* free/busy type based on the events status.
*/
DateTime psdt;
DateTime pedt;
try {
psdt = new DateTime(gpp.startDt.getDtval());
pedt = new DateTime(gpp.endDt.getDtval());
} catch (ParseException pe) {
throw new CalFacadeException(pe);
}
psdt.setUtc(true);
pedt.setUtc(true);
EventPeriod ep = new EventPeriod(psdt, pedt, 0);
setFreeBusyType(ep, periodEvents);
respeps.add(ep);
}
}
use of org.bedework.calfacade.BwDateTime 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.calfacade.BwDateTime in project bw-calendar-engine by Bedework.
the class InRequest method findOverride.
private EventInfo findOverride(final EventInfo ei, final String recurrenceId) throws CalFacadeException {
final EventInfo ovei = ei.findOverride(recurrenceId);
if (ovei.getEvent().unsaved()) {
// New override - set start/end based on duration
BwDateTime start = BwDateTime.fromUTC(recurrenceId.length() == 8, recurrenceId, ei.getEvent().getDtstart().getTzid());
BwDateTime end = start.addDur(new Dur(ei.getEvent().getDuration()));
ovei.getEvent().setDtstart(start);
ovei.getEvent().setDtend(end);
}
return ovei;
}
Aggregations