use of org.bedework.calfacade.util.Granulator.EventPeriod in project bw-calendar-engine by Bedework.
the class CalintfImpl method getFreeBusy.
/* ====================================================================
* Free busy
* ==================================================================== */
@Override
public BwEvent getFreeBusy(final Collection<BwCalendar> cals, final BwPrincipal who, final BwDateTime start, final BwDateTime end, final boolean returnAll, final boolean ignoreTransparency) throws CalFacadeException {
if (who.getKind() != WhoDefs.whoTypeUser) {
throw new CalFacadeException("Unsupported: non user principal for free-busy");
}
final Collection<CoreEventInfo> events = getFreeBusyEntities(cals, start, end, ignoreTransparency);
final BwEvent fb = new BwEventObj();
fb.setEntityType(IcalDefs.entityTypeFreeAndBusy);
fb.setOwnerHref(who.getPrincipalRef());
fb.setDtstart(start);
fb.setDtend(end);
try {
final TreeSet<EventPeriod> eventPeriods = new TreeSet<>();
for (final CoreEventInfo ei : events) {
final BwEvent ev = ei.getEvent();
// Ignore if times were specified and this event is outside the times
final BwDateTime estart = ev.getDtstart();
final BwDateTime eend = ev.getDtend();
/* Don't report out of the requested period */
final String dstart;
final String dend;
if (estart.before(start)) {
dstart = start.getDtval();
} else {
dstart = estart.getDtval();
}
if (eend.after(end)) {
dend = end.getDtval();
} else {
dend = eend.getDtval();
}
final DateTime psdt = new DateTime(dstart);
final DateTime pedt = new DateTime(dend);
psdt.setUtc(true);
pedt.setUtc(true);
int type = BwFreeBusyComponent.typeBusy;
if (BwEvent.statusTentative.equals(ev.getStatus())) {
type = BwFreeBusyComponent.typeBusyTentative;
}
eventPeriods.add(new EventPeriod(psdt, pedt, type));
}
/* iterate through the sorted periods combining them where they are
adjacent or overlap */
Period p = null;
/* For the moment just build a single BwFreeBusyComponent
*/
BwFreeBusyComponent fbc = null;
int lastType = 0;
for (final EventPeriod ep : eventPeriods) {
if (debug) {
debug(ep.toString());
}
if (p == null) {
p = new Period(ep.getStart(), ep.getEnd());
lastType = ep.getType();
} else if ((lastType != ep.getType()) || ep.getStart().after(p.getEnd())) {
// Non adjacent periods
if (fbc == null) {
fbc = new BwFreeBusyComponent();
fbc.setType(lastType);
fb.addFreeBusyPeriod(fbc);
}
fbc.addPeriod(p.getStart(), p.getEnd());
if (lastType != ep.getType()) {
fbc = null;
}
p = new Period(ep.getStart(), ep.getEnd());
lastType = ep.getType();
} else if (ep.getEnd().after(p.getEnd())) {
// Extend the current period
p = new Period(p.getStart(), ep.getEnd());
}
// else it falls within the existing period
}
if (p != null) {
if ((fbc == null) || (lastType != fbc.getType())) {
fbc = new BwFreeBusyComponent();
fbc.setType(lastType);
fb.addFreeBusyPeriod(fbc);
}
fbc.addPeriod(p.getStart(), p.getEnd());
}
} catch (final Throwable t) {
if (debug) {
error(t);
}
throw new CalFacadeException(t);
}
return fb;
}
use of org.bedework.calfacade.util.Granulator.EventPeriod in project bw-calendar-engine by Bedework.
the class FreeAndBusyHandler method aggregateFreeBusy.
/* (non-Javadoc)
* @see org.bedework.calsvci.SchedulingI#aggregateFreeBusy(org.bedework.calfacade.ScheduleResult, org.bedework.calfacade.BwDateTime, org.bedework.calfacade.BwDateTime, org.bedework.calfacade.BwDuration)
*/
@Override
public FbResponses aggregateFreeBusy(final ScheduleResult sr, final BwDateTime start, final BwDateTime end, final BwDuration granularity) throws CalFacadeException {
FbResponses resps = new FbResponses();
if (start.getDateType() || end.getDateType()) {
throw new CalFacadeException(CalFacadeException.schedulingBadGranulatorDt);
}
resps.setResponses(new ArrayList<FbGranulatedResponse>());
/* Combine the responses into one big collection */
FbGranulatedResponse allResponses = new FbGranulatedResponse();
allResponses.setStart(start);
allResponses.setEnd(end);
resps.setAggregatedResponse(allResponses);
for (ScheduleRecipientResult srr : sr.recipientResults.values()) {
FbGranulatedResponse fb = new FbGranulatedResponse();
resps.getResponses().add(fb);
fb.setRespCode(srr.getStatus());
fb.setNoResponse(srr.freeBusy == null);
fb.setRecipient(srr.recipient);
if (!fb.okResponse()) {
continue;
}
if (srr.freeBusy.getNumAttendees() == 1) {
fb.setAttendee(srr.freeBusy.getAttendees().iterator().next());
}
granulateFreeBusy(fb, srr.freeBusy, start, end, granularity);
if (fb.getStart() == null) {
continue;
}
boolean first = false;
if (allResponses.eps.isEmpty()) {
first = true;
}
// Merge resp into allResponses - they should have the same start/end
Iterator<EventPeriod> allIt = allResponses.eps.iterator();
for (EventPeriod respEp : fb.eps) {
EventPeriod allEp;
if (first) {
// Just set the event period from this first response.
allResponses.eps.add(respEp);
allEp = respEp;
continue;
}
// Merge this response period into the corresponding aggregated response
allEp = allIt.next();
// Validity check
if (!allEp.getStart().equals(respEp.getStart()) || !allEp.getEnd().equals(respEp.getEnd())) {
throw new CalFacadeException(CalFacadeException.schedulingBadResponse);
}
if ((respEp.getType() == BwFreeBusyComponent.typeBusy) || (respEp.getType() == BwFreeBusyComponent.typeBusyUnavailable)) {
allEp.setNumBusy(allEp.getNumBusy() + 1);
} else if (respEp.getType() == BwFreeBusyComponent.typeBusyTentative) {
allEp.setNumTentative(allEp.getNumTentative() + 1);
}
allEp.setType(typeTable[allEp.getType()][respEp.getType()]);
}
}
return resps;
}
use of org.bedework.calfacade.util.Granulator.EventPeriod 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);
}
}
Aggregations