use of org.bedework.calfacade.BwEvent in project bw-calendar-engine by Bedework.
the class CoreEvents method updateRecurrences.
/* XXX This is a bit brute force but it will do for the moment. We have to
* turn a set of rules into a set of changes. If we'd preserved the rules
* prior to this I guess we could figure out the differences without querying
* the db.
*
* For the moment create a whole set of instances and then query the db to see if
* they match.
*/
@SuppressWarnings("unchecked")
private void updateRecurrences(final EventInfo ei, final UpdateEventResult uc, final Collection<BwEventProxy> overrides, final boolean shared) throws CalFacadeException {
final BwEvent val = ei.getEvent();
final ChangeTable changes = val.getChangeset(currentPrincipal());
if (!changes.isEmpty()) {
if (!changes.recurrenceChanged()) {
return;
}
if (!changes.recurrenceRulesChanged()) {
// We can handle exdate and rdate changes.
ChangeTableEntry ent = changes.getEntry(PropertyInfoIndex.EXDATE);
if (ent.getAddedValues() != null) {
// exdates added - remove the instances.
removeInstances(val, uc, overrides, ent.getAddedValues(), shared);
}
if (ent.getRemovedValues() != null) {
// exdates removed - add the instances.
addInstances(val, uc, overrides, ent.getRemovedValues(), shared);
}
ent = changes.getEntry(PropertyInfoIndex.RDATE);
if (ent.getAddedValues() != null) {
// rdates added - add the instances.
addInstances(val, uc, overrides, ent.getAddedValues(), shared);
}
if (ent.getRemovedValues() != null) {
// rdates removed - remove the instances.
removeInstances(val, uc, overrides, ent.getRemovedValues(), shared);
}
return;
}
}
final Map<String, BwRecurrenceInstance> updated = new HashMap<>();
/* Get all the times for this event. - this could be a problem. Need to
limit the number. Should we do this in chunks, stepping through the
whole period?
*/
final RecurPeriods rp = RecurUtil.getPeriods(val, getAuthprops().getMaxYears(), getAuthprops().getMaxInstances());
if (rp.instances.isEmpty()) {
// No instances for an alleged recurring event.
// XXX Mark the master as non-recurring to stop it disappearing
val.setRecurring(false);
// throwException(CalFacadeException.noRecurrenceInstances);
}
final String stzid = val.getDtstart().getTzid();
/* try {
val.setLatestDate(Timezones.getUtc(rp.rangeEnd.toString(), stzid));
} catch (Throwable t) {
throwException(new CalFacadeException(t));
} */
int maxInstances = getAuthprops().getMaxInstances();
final boolean dateOnly = val.getDtstart().getDateType();
for (final Period p : rp.instances) {
String dtval = p.getStart().toString();
if (dateOnly) {
dtval = dtval.substring(0, 8);
}
final BwDateTime rstart = BwDateTime.makeBwDateTime(dateOnly, dtval, stzid);
dtval = p.getEnd().toString();
if (dateOnly) {
dtval = dtval.substring(0, 8);
}
final BwDateTime rend = BwDateTime.makeBwDateTime(dateOnly, dtval, stzid);
final BwRecurrenceInstance ri = new BwRecurrenceInstance();
ri.setDtstart(rstart);
ri.setDtend(rend);
ri.setRecurrenceId(ri.getDtstart().getDate());
ri.setMaster(val);
updated.put(ri.getRecurrenceId(), ri);
maxInstances--;
if (maxInstances == 0) {
// That's all you're getting from me
break;
}
}
final List<BwRecurrenceInstance> current = dao.getInstances(val);
for (final BwRecurrenceInstance ri : current) {
final BwRecurrenceInstance updri = updated.get(ri.getRecurrenceId());
if (updri == null) {
// Not in the new instance set - delete from db
ei.removeOverride(ri.getRecurrenceId());
dao.delete(ri);
uc.addDeleted(ri);
notifyInstanceChange(SysEvent.SysCode.ENTITY_DELETED, val, shared, ri.getRecurrenceId());
continue;
}
/* Found instance with same recurrence id. Is the start and end the same
*/
if (!ri.getDtstart().equals(updri.getDtstart()) || !ri.getDtend().equals(updri.getDtend())) {
ri.setDtstart(updri.getDtstart());
ri.setDtend(updri.getDtend());
dao.update(ri);
uc.addUpdated(ri);
notifyInstanceChange(SysEvent.SysCode.ENTITY_UPDATED, val, shared, ri.getRecurrenceId());
}
// Remove the entry - we've processed it.
updated.remove(ri.getRecurrenceId());
}
for (final BwRecurrenceInstance ri : updated.values()) {
dao.save(ri);
uc.addAdded(ri);
notifyInstanceChange(SysEvent.SysCode.ENTITY_ADDED, val, shared, ri.getRecurrenceId());
}
}
use of org.bedework.calfacade.BwEvent in project bw-calendar-engine by Bedework.
the class CoreEvents method deleteEvent.
@Override
public DelEventResult deleteEvent(final EventInfo ei, final boolean scheduling, final boolean reallyDelete) throws CalFacadeException {
final DelEventResult der = new DelEventResult(false, 0);
BwEvent ev = ei.getEvent();
final boolean isMaster = ev.testRecurring() && (ev.getRecurrenceId() == null);
final boolean isInstance = (ev.getRecurrenceId() != null) && (ev instanceof BwEventProxy);
if (!isInstance && ev.unsaved()) {
final CoreEventInfo cei = getEvent(ev.getColPath(), ev.getName(), RecurringRetrievalMode.overrides);
if (cei == null) {
return der;
}
ev = cei.getEvent();
}
final long startTime = System.currentTimeMillis();
final int desiredAccess;
final boolean shared;
try {
final BwCalendar col = getEntityCollection(ev.getColPath(), privAny, scheduling, false);
shared = col.getPublick() || col.getShared();
if (!scheduling) {
desiredAccess = privUnbind;
} else {
/* Delete message while tidying up in/outbox.
* Set desiredAccess to something that works.
* */
final CalendarWrapper cw = (CalendarWrapper) col;
desiredAccess = cw.getLastDesiredAccess();
}
ac.checkAccess(ev, desiredAccess, false);
} catch (final CalFacadeException cfe) {
dao.rollback();
throw cfe;
}
if (!reallyDelete && ev.getTombstoned()) {
// no-op - just pretend
der.eventDeleted = true;
return der;
}
if (isMaster) {
// Master event - delete all instances and overrides.
deleteInstances(ev, shared);
notifyDelete(reallyDelete, ev, shared);
if (reallyDelete) {
dao.delete(ev);
} else {
tombstoneEvent(ev);
}
der.eventDeleted = true;
stat(StatsEvent.deleteTime, startTime);
unindexEntity(ei);
return der;
}
if (isInstance) {
/* Deleting a single instance. Delete any overrides, delete the instance
* and add an exdate to the master.
*/
final BwEventProxy proxy = (BwEventProxy) ev;
final BwEventAnnotation ann = proxy.getRef();
BwEvent master = ann.getMaster();
if (master.unsaved()) {
final CoreEventInfo cei = getEvent(master.getColPath(), master.getName(), RecurringRetrievalMode.overrides);
if (cei == null) {
return der;
}
master = cei.getEvent();
}
/* Fetch the instance so we can delete it */
final BwRecurrenceInstance inst = dao.getInstance(master, ev.getRecurrenceId());
if (inst == null) {
stat(StatsEvent.deleteTime, startTime);
return der;
}
notifyDelete(true, ev, shared);
dao.delete(inst);
if (!ann.unsaved()) {
// der.alarmsDeleted = deleteAlarms(ann);
ann.getAttendees().clear();
dao.delete(ann);
}
final BwDateTime instDate = inst.getDtstart();
if (!master.getRdates().remove(instDate)) {
// Wasn't an rdate event
master.addExdate(instDate);
}
master.updateLastmod();
dao.update(master);
der.eventDeleted = true;
stat(StatsEvent.deleteTime, startTime);
indexEntity(ei.getRetrievedEvent());
return der;
}
// Single non recurring event.
BwEvent deletee = ev;
if (ev instanceof BwEventProxy) {
// Deleting an annotation
deletee = ((BwEventProxy) ev).getRef();
}
// I think we need something like this -- fixReferringAnnotations(deletee);
// XXX This could be wrong.
/* If this is a proxy we should only delete alarmas attached to the
* proxy - any attached to the underlying event should be left alone.
*/
// der.alarmsDeleted = deleteAlarms(deletee);
// sess.delete(sess.merge(deletee));
notifyDelete(reallyDelete, ev, shared);
if (reallyDelete) {
clearCollection(ev.getAttendees());
dao.delete(deletee);
} else {
tombstoneEvent(deletee);
}
der.eventDeleted = true;
stat(StatsEvent.deleteTime, startTime);
unindexEntity(ei);
return der;
}
use of org.bedework.calfacade.BwEvent in project bw-calendar-engine by Bedework.
the class CoreEvents method getSynchEvents.
@Override
public Set<CoreEventInfo> getSynchEvents(final String path, final String token) throws CalFacadeException {
if (path == null) {
dao.rollback();
throw new CalFacadeBadRequest("Missing path");
}
final String fpath = fixPath(path);
final BwCalendar col = getCollection(fpath);
ac.checkAccess(col, privAny, false);
@SuppressWarnings("unchecked") final List<BwEvent> evs = dao.getSynchEventObjects(fpath, token);
if (debug) {
trace(" ----------- number evs = " + evs.size());
}
final Set<CoreEventInfo> res = new TreeSet<>();
for (final BwEvent ev : evs) {
final CurrentAccess ca = new CurrentAccess(true);
res.add(new CoreEventInfo(ev, ca));
}
return res;
}
use of org.bedework.calfacade.BwEvent in project bw-calendar-engine by Bedework.
the class CoreEvents method getEvent.
@Override
public Collection<CoreEventInfo> getEvent(final String colPath, final String uid) throws CalFacadeException {
final TreeSet<CoreEventInfo> ts = new TreeSet<>();
final int desiredAccess = privRead;
/*
if (colPath != null) {
BwCalendar cal = getEntityCollection(colPath, privRead, scheduling, false);
desiredAccess = ((CalendarWrapper)cal).getLastDesiredAccess();
}
*/
/* This works as follows:
*
* First try to retrieve the master event from the events table.
*
* If not there try the annotations table. If it's there, it's a reference
* to an event owned by somebody else. Otherwise we drew a blank.
*
* If no recurrence id was specified process any recurrence information for
* each event retrieved and return.
*
* Note that the event we retrieved might be a reference to a recurring
* instance. In that case it will inherit the recurrence id. We should check
* for this case and assume we were being asked for that event.
*
* If a recurrence id was specified then, for each master event retrieved,
* we need to retrieve the instance and build a proxy using any appropriate
* overrides.
*/
// First look in the events table for the master(s).
Collection evs = dao.eventQuery(BwEventObj.class, colPath, uid, null, null, // overrides
null, // recurRetrieval);
null);
if (Util.isEmpty(evs)) {
/* Look for an annotation to that event by the current user.
*/
evs = dao.eventQuery(BwEventAnnotation.class, colPath, uid, /*null*/
null, null, // overrides
false, // recurRetrieval);
null);
}
if (Util.isEmpty(evs)) {
return ts;
}
final Collection<CoreEventInfo> ceis = postGetEvents(evs, desiredAccess, returnResultAlways, null);
if (ceis.isEmpty()) {
return ceis;
}
/* If the recurrence id is null, do recurrences for each retrieved event,
* otherwise just retrieve the instance.
*/
final EventsQueryResult eqr = new EventsQueryResult();
eqr.flt = new Filters(cb, null);
eqr.addColPath(colPath);
for (final CoreEventInfo cei : ceis) {
final BwEvent master = cei.getEvent();
if (master.getEntityType() == IcalDefs.entityTypeVavailability) {
for (final String auid : master.getAvailableUids()) {
final Collection<CoreEventInfo> aceis = getEvent(colPath, auid);
if (aceis.size() != 1) {
throwException(CalFacadeException.badResponse);
}
cei.addContainedItem(aceis.iterator().next());
}
ts.add(cei);
} else if (!master.testRecurring()) {
ts.add(cei);
} else {
doRecurrence(cei, null);
ts.add(cei);
}
}
return ts;
}
use of org.bedework.calfacade.BwEvent in project bw-calendar-engine by Bedework.
the class CoreEvents method getEvents.
@Override
public Collection<CoreEventInfo> getEvents(final Collection<BwCalendar> calendars, final FilterBase filter, final BwDateTime startDate, final BwDateTime endDate, final List<BwIcalPropertyInfoEntry> retrieveList, final DeletedState delState, RecurringRetrievalMode recurRetrieval, final boolean freeBusy) throws CalFacadeException {
/* Ensure dates are limited explicitly or implicitly */
recurRetrieval = defaultRecurringRetrieval(recurRetrieval, startDate, endDate);
if (debug) {
trace("getEvents for start=" + startDate + " end=" + endDate);
}
FilterBase fltr = filter;
if (!Util.isEmpty(calendars)) {
FilterBase colfltr = null;
for (final BwCalendar c : calendars) {
colfltr = FilterBase.addOrChild(colfltr, new BwCollectionFilter(null, c));
}
fltr = FilterBase.addAndChild(fltr, colfltr);
}
int desiredAccess = privRead;
if (freeBusy) {
// DORECUR - freebusy events must have enough info for expansion
desiredAccess = privReadFreeBusy;
}
final List<PropertyInfoIndex> properties = new ArrayList<>(2);
properties.add(PropertyInfoIndex.DTSTART);
properties.add(PropertyInfoIndex.UTC);
final List<SortTerm> sort = new ArrayList<>(1);
sort.add(new SortTerm(properties, true));
String start = null;
String end = null;
if (startDate != null) {
start = startDate.getDate();
}
if (endDate != null) {
end = endDate.getDate();
}
final SearchResult sr = // query
getIndexer(null).search(// query
null, false, fltr, sort, // defaultFilterContext
null, start, end, -1, delState, recurRetrieval);
final List<SearchResultEntry> sres = sr.getIndexer().getSearchResult(sr, 0, -1, desiredAccess);
final TreeSet<CoreEventInfo> ceis = new TreeSet<>();
for (final SearchResultEntry sre : sres) {
final Object o = sre.getEntity();
if (!(o instanceof EventInfo)) {
continue;
}
final EventInfo ei = (EventInfo) o;
final BwEvent ev = ei.getEvent();
restoreCategories(ev);
final CoreEventInfo cei = postGetEvent(ev, null, ei.getCurrentAccess());
if (cei == null) {
continue;
}
ceis.add(cei);
}
return buildVavail(ceis);
}
Aggregations