Search in sources :

Example 46 with BwEvent

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());
    }
}
Also used : BwDateTime(org.bedework.calfacade.BwDateTime) HashMap(java.util.HashMap) Period(net.fortuna.ical4j.model.Period) BwEvent(org.bedework.calfacade.BwEvent) BwRecurrenceInstance(org.bedework.calfacade.BwRecurrenceInstance) ChangeTable(org.bedework.calfacade.util.ChangeTable) ChangeTableEntry(org.bedework.calfacade.util.ChangeTableEntry) RecurPeriods(org.bedework.icalendar.RecurUtil.RecurPeriods)

Example 47 with BwEvent

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;
}
Also used : BwDateTime(org.bedework.calfacade.BwDateTime) CoreEventInfo(org.bedework.calcorei.CoreEventInfo) BwEvent(org.bedework.calfacade.BwEvent) BwCalendar(org.bedework.calfacade.BwCalendar) BwEventProxy(org.bedework.calfacade.BwEventProxy) CalFacadeException(org.bedework.calfacade.exc.CalFacadeException) BwRecurrenceInstance(org.bedework.calfacade.BwRecurrenceInstance) BwEventAnnotation(org.bedework.calfacade.BwEventAnnotation) CalendarWrapper(org.bedework.calfacade.wrappers.CalendarWrapper)

Example 48 with BwEvent

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;
}
Also used : CalFacadeBadRequest(org.bedework.calfacade.exc.CalFacadeBadRequest) CoreEventInfo(org.bedework.calcorei.CoreEventInfo) TreeSet(java.util.TreeSet) BwEvent(org.bedework.calfacade.BwEvent) CurrentAccess(org.bedework.access.Acl.CurrentAccess) BwCalendar(org.bedework.calfacade.BwCalendar)

Example 49 with BwEvent

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;
}
Also used : BwEventAnnotation(org.bedework.calfacade.BwEventAnnotation) CoreEventInfo(org.bedework.calcorei.CoreEventInfo) TreeSet(java.util.TreeSet) Collection(java.util.Collection) EventsQueryResult(org.bedework.calcore.hibernate.EventQueryBuilder.EventsQueryResult) BwEvent(org.bedework.calfacade.BwEvent)

Example 50 with BwEvent

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);
}
Also used : SortTerm(org.bedework.calfacade.filter.SortTerm) CoreEventInfo(org.bedework.calcorei.CoreEventInfo) EventInfo(org.bedework.calfacade.svc.EventInfo) CoreEventInfo(org.bedework.calcorei.CoreEventInfo) ArrayList(java.util.ArrayList) SearchResult(org.bedework.calfacade.indexing.SearchResult) BwEvent(org.bedework.calfacade.BwEvent) BwCalendar(org.bedework.calfacade.BwCalendar) BwCollectionFilter(org.bedework.calfacade.filter.BwCollectionFilter) PropertyInfoIndex(org.bedework.util.calendar.PropertyIndex.PropertyInfoIndex) TreeSet(java.util.TreeSet) FilterBase(org.bedework.caldav.util.filter.FilterBase) SearchResultEntry(org.bedework.calfacade.indexing.SearchResultEntry)

Aggregations

BwEvent (org.bedework.calfacade.BwEvent)160 EventInfo (org.bedework.calfacade.svc.EventInfo)80 CalFacadeException (org.bedework.calfacade.exc.CalFacadeException)55 BwEventProxy (org.bedework.calfacade.BwEventProxy)33 ChangeTableEntry (org.bedework.calfacade.util.ChangeTableEntry)26 BwAttendee (org.bedework.calfacade.BwAttendee)25 BwDateTime (org.bedework.calfacade.BwDateTime)25 BwString (org.bedework.calfacade.BwString)24 UpdateResult (org.bedework.caldav.server.sysinterface.SysIntf.UpdateResult)23 BwEventAnnotation (org.bedework.calfacade.BwEventAnnotation)23 CoreEventInfo (org.bedework.calcorei.CoreEventInfo)21 BwCalendar (org.bedework.calfacade.BwCalendar)21 WebdavException (org.bedework.webdav.servlet.shared.WebdavException)20 BwXproperty (org.bedework.calfacade.BwXproperty)16 TreeSet (java.util.TreeSet)15 BwEventObj (org.bedework.calfacade.BwEventObj)13 ArrayList (java.util.ArrayList)12 Period (net.fortuna.ical4j.model.Period)12 BwCategory (org.bedework.calfacade.BwCategory)10 BwContact (org.bedework.calfacade.BwContact)10