Search in sources :

Example 21 with BwEventAnnotation

use of org.bedework.calfacade.BwEventAnnotation in project bw-calendar-engine by Bedework.

the class CoreEvents method updateEvent.

@Override
public UpdateEventResult updateEvent(final EventInfo ei) throws CalFacadeException {
    final BwEvent val = ei.getEvent();
    final Collection<BwEventProxy> overrides = ei.getOverrideProxies();
    final Collection<BwEventProxy> deletedOverrides = ei.getDeletedOverrideProxies(cb.getPrincipalInfo().getPrincipal().getPrincipalRef());
    final UpdateEventResult ue = new UpdateEventResult();
    if (!ac.checkAccess(val, privWrite, true).getAccessAllowed()) {
        // XXX Is this correct?
        try {
            ac.checkAccess(val, privWriteContent, false);
        } catch (final CalFacadeException cfe) {
            throwException(cfe);
        }
    }
    BwEventProxy proxy = null;
    if (val instanceof BwEventProxy) {
        proxy = (BwEventProxy) val;
    }
    final BwCalendar col = getCollection(val.getColPath());
    final boolean shared = col.getPublick() || col.getShared();
    if ((proxy != null) && (proxy.getRef().getOverride())) {
        final BwEventAnnotation ann = proxy.getRef();
        final BwEvent mstr = ann.getMaster();
        if (!proxy.getUid().equals(mstr.getUid())) {
            throwException("org.bedework.cannot.overrideuid");
        }
        if (!proxy.getName().equals(mstr.getName())) {
            throwException("org.bedework.cannot.overridename");
        }
    } else {
        /* The guid must not exist in the same calendar. We assign a guid if
       * one wasn't assigned already. However, the event may have come with a guid
       * (caldav, import, etc) so we need to check here.
       *
       * It also ensures our guid allocation is working OK
       */
        final CollectionInfo collInf = col.getCollectionInfo();
        if (collInf.uniqueKey) {
            String name = calendarGuidExists(val, false, false);
            if (name == null) {
                name = calendarGuidExists(val, true, false);
            }
            if (name != null) {
                throwException(CalFacadeException.duplicateGuid, name);
            }
        }
        /* Similarly for event names which must be unique within a collection
       */
        if (calendarNameExists(val, false, false) || calendarNameExists(val, true, false)) {
            throwException(new CalFacadeDupNameException(val.getName()));
        }
    }
    if (!(val instanceof BwEventProxy)) {
        dao.update(val);
        final Collection<BwDbentity<?>> deleted = val.getDeletedEntities();
        if (deleted != null) {
            for (final BwDbentity ent : deleted) {
                dao.delete(ent);
            }
            deleted.clear();
        }
        if (val.testRecurring()) {
            if (!Util.isEmpty(overrides)) {
                for (final BwEventProxy pxy : overrides) {
                    final BwEventAnnotation ann = pxy.getRef();
                    boolean updated = false;
                    if ((ann.getRecurring() != null) && ann.getRecurring()) {
                        // be safe
                        ann.setRecurring(false);
                        updated = true;
                    }
                    if (ann.getTombstoned() == null) {
                        // be safe
                        ann.setTombstoned(false);
                        updated = true;
                    }
                    if (ann.unsaved()) {
                        dao.save(ann);
                    } else if (updated) {
                        updateProxy(new BwEventProxy(ann));
                    }
                }
            }
            updateRecurrences(ei, ue, overrides, shared);
        }
        if (!val.testRecurring() || (Util.isEmpty(overrides) && Util.isEmpty(deletedOverrides))) {
            notify(SysEvent.SysCode.ENTITY_UPDATED, val, shared);
            indexEntity(ei);
            return ue;
        }
        if (!Util.isEmpty(overrides)) {
            updateOverrides: for (final BwEventProxy pxy : overrides) {
                final BwEventAnnotation ann = pxy.getRef();
                if (ue.deleted != null) {
                    for (final BwRecurrenceInstance ri : ue.deleted) {
                        if (ri.getRecurrenceId().equals(ann.getRecurrenceId())) {
                            continue updateOverrides;
                        }
                    }
                }
                if (ue.added != null) {
                    for (final BwRecurrenceInstance ri : ue.added) {
                        if (ri.getRecurrenceId().equals(ann.getRecurrenceId())) {
                            continue updateOverrides;
                        }
                    }
                }
                // be safe
                ann.setRecurring(false);
                if (ann.getTombstoned() == null) {
                    // be safe
                    ann.setTombstoned(false);
                }
                if (!ann.unsaved()) {
                    updateProxy(new BwEventProxy(ann));
                } else {
                    dao.save(ann);
                    /* See if there is an instance for this override
             */
                    BwRecurrenceInstance ri = dao.getInstance(val, ann.getRecurrenceId());
                    if (ri == null) {
                        final BwDateTime rid = BwDateTime.fromUTC(ann.getRecurrenceId().length() == 8, ann.getRecurrenceId());
                        final Dur dur = new Dur(val.getDuration());
                        final BwDateTime end = rid.addDur(dur);
                        ri = new BwRecurrenceInstance();
                        ri.setDtstart(rid);
                        ri.setDtend(end);
                        ri.setRecurrenceId(rid.getDate());
                        ri.setMaster(val);
                        ri.setOverride(ann);
                        dao.save(ri);
                    } else {
                        ri.setOverride(ann);
                        dao.update(ri);
                    }
                }
                notifyInstanceChange(SysEvent.SysCode.ENTITY_UPDATED, val, shared, ann.getRecurrenceId());
            }
        }
        if (!Util.isEmpty(deletedOverrides)) {
            final Collection<String> rids = new ArrayList<>();
            for (final BwEventProxy pxy : deletedOverrides) {
                rids.add(pxy.getRecurrenceId());
            }
            removeInstances(val, rids, ue, deletedOverrides, shared);
        }
    } else {
        if (proxy.getChangeFlag()) {
            updateProxy(proxy);
        }
    }
    notify(SysEvent.SysCode.ENTITY_UPDATED, val, shared);
    if (proxy != null) {
        if (ei.getRetrievedEvent() == null) {
            warn("No retrieved event for indexer");
        } else {
            final EventInfo rei = ei.getRetrievedEvent();
            rei.addOverride(ei);
            indexEntity(rei);
        }
    } else {
        indexEntity(ei);
    }
    return ue;
}
Also used : Dur(net.fortuna.ical4j.model.Dur) BwDateTime(org.bedework.calfacade.BwDateTime) CoreEventInfo(org.bedework.calcorei.CoreEventInfo) EventInfo(org.bedework.calfacade.svc.EventInfo) CollectionInfo(org.bedework.calfacade.BwCalendar.CollectionInfo) ArrayList(java.util.ArrayList) 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) CalFacadeDupNameException(org.bedework.calfacade.exc.CalFacadeDupNameException) BwEventAnnotation(org.bedework.calfacade.BwEventAnnotation) BwDbentity(org.bedework.calfacade.base.BwDbentity)

Example 22 with BwEventAnnotation

use of org.bedework.calfacade.BwEventAnnotation in project bw-calendar-engine by Bedework.

the class CoreEvents method addEvent.

@Override
public UpdateEventResult addEvent(final EventInfo ei, final boolean scheduling, final boolean rollbackOnError) throws CalFacadeException {
    final BwEvent val = ei.getEvent();
    final Collection<BwEventProxy> overrides = ei.getOverrideProxies();
    final long startTime = System.currentTimeMillis();
    RecuridTable recurids = null;
    final UpdateEventResult uer = new UpdateEventResult();
    uer.addedUpdated = true;
    final BwCalendar cal = getEntityCollection(val.getColPath(), privBind, scheduling, false);
    /* Indicate if we want sharing notifications of changes */
    final boolean shared = cal.getPublick() || cal.getShared();
    final CollectionInfo collInf = cal.getCollectionInfo();
    if (!Util.isEmpty(overrides)) {
        if (!val.testRecurring()) {
            throwException(CalFacadeException.overridesForNonRecurring);
        }
        recurids = new RecuridTable(overrides);
    }
    if (val.getUid() == null) {
        throwException(CalFacadeException.noEventGuid);
    }
    if (val.getName() == null) {
        throwException(CalFacadeException.noEventName);
    }
    /* The guid must not exist in the same calendar. We assign a guid if
     * one wasn't assigned already. However, the event may have come with a guid
     * (caldav, import, etc) so we need to check here.
     *
     * It also ensures our guid allocation is working OK
     */
    if (collInf.uniqueKey) {
        String name = calendarGuidExists(val, false, true);
        if (name == null) {
            name = calendarGuidExists(val, true, true);
        }
        if (name != null) {
            throwException(CalFacadeException.duplicateGuid, name);
        }
    }
    /* Similarly for event names which must be unique within a collection.
     * Note that a duplicate name is essentially overwriting an event with a
     * new uid - also disallowed.
     */
    if ((val.getEntityType() != IcalDefs.entityTypeAvailable) && (calendarNameExists(val, false, true) || calendarNameExists(val, true, true))) {
        throwException(CalFacadeException.duplicateName, val.getName());
    }
    setupDependentEntities(val);
    /* Remove any tombstoned event in the collection with same uid */
    deleteTombstoned(val.getColPath(), val.getUid());
    /* If it's a recurring event see what we can do to optimize searching
     * and retrieval
     */
    if ((val instanceof BwEventAnnotation) || !val.getRecurring()) {
        dao.save(val);
        if (!getForRestore()) {
            notify(SysEvent.SysCode.ENTITY_ADDED, val, shared);
        }
        stat(StatsEvent.createTime, startTime);
        indexEntity(ei);
        return uer;
    }
    /* 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.
        if (rollbackOnError) {
            throwException(CalFacadeException.noRecurrenceInstances, val.getUid());
        }
        uer.addedUpdated = false;
        uer.errorCode = CalFacadeException.noRecurrenceInstances;
        stat(StatsEvent.createTime, startTime);
        indexEntity(ei);
        return uer;
    }
    /* We can save the master at this point */
    dao.save(val);
    final String stzid = val.getDtstart().getTzid();
    final TimeZone stz = null;
    /*    try {
      if (stzid != null) {
        stz = Timezones.getTz(stzid);
      }
      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();
    /* There appears to be a bug in ical4j in which the first instance gets
     * duplicated. Rather than change that code and run the risk of breaking
     * all recurrences I'll just look for that duplicate.
     */
    String firstRecurrenceId = null;
    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);
        final DateTime edt = p.getEnd();
        if (!dateOnly && (stz != null)) {
            edt.setTimeZone(stz);
        }
        dtval = edt.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);
        if (firstRecurrenceId == null) {
            firstRecurrenceId = ri.getRecurrenceId();
        } else if (firstRecurrenceId.equals(ri.getRecurrenceId())) {
            // Skip it
            if (debug) {
                debugMsg("Skipping duplicate recurid " + firstRecurrenceId);
            }
            continue;
        }
        if (recurids != null) {
            /* See if we have a recurrence */
            final String rid = ri.getRecurrenceId();
            final BwEventProxy ov = recurids.get(rid);
            if (ov != null) {
                if (debug) {
                    debugMsg("Add override with recurid " + rid);
                }
                setupDependentEntities(ov);
                addOverride(ov, ri);
                recurids.remove(rid);
            }
        }
        dao.save(ri);
        maxInstances--;
        if (maxInstances == 0) {
            // That's all you're getting from me
            break;
        }
    }
    if ((recurids != null) && (recurids.size() != 0)) {
        /* We removed all the valid overrides - we are left with those
       * with recurrence ids that don't match.
       */
        if (rollbackOnError) {
            throwException(CalFacadeException.invalidOverride);
        }
        uer.failedOverrides = recurids.values();
    }
    if (!getForRestore()) {
        notify(SysEvent.SysCode.ENTITY_ADDED, val, shared);
    }
    indexEntity(ei);
    stat(StatsEvent.createTime, startTime);
    return uer;
}
Also used : BwDateTime(org.bedework.calfacade.BwDateTime) CollectionInfo(org.bedework.calfacade.BwCalendar.CollectionInfo) Period(net.fortuna.ical4j.model.Period) BwEvent(org.bedework.calfacade.BwEvent) BwCalendar(org.bedework.calfacade.BwCalendar) BwEventProxy(org.bedework.calfacade.BwEventProxy) DateTime(net.fortuna.ical4j.model.DateTime) BwDateTime(org.bedework.calfacade.BwDateTime) BwRecurrenceInstance(org.bedework.calfacade.BwRecurrenceInstance) TimeZone(net.fortuna.ical4j.model.TimeZone) BwEventAnnotation(org.bedework.calfacade.BwEventAnnotation) RecurPeriods(org.bedework.icalendar.RecurUtil.RecurPeriods)

Example 23 with BwEventAnnotation

use of org.bedework.calfacade.BwEventAnnotation in project bw-calendar-engine by Bedework.

the class CoreEvents method addInstances.

/* Add instances identified by the Collection of recurrence ids
   */
private void addInstances(final BwEvent master, final UpdateEventResult uc, final Collection<BwEventProxy> overrides, final Collection rids, final boolean shared) throws CalFacadeException {
    final Dur dur = new Dur(master.getDuration());
    for (final Object rid : rids) {
        final BwDateTime start = (BwDateTime) rid;
        final BwDateTime end = start.addDur(dur);
        final BwRecurrenceInstance ri = new BwRecurrenceInstance();
        ri.setDtstart(start);
        ri.setDtend(end);
        ri.setRecurrenceId(start.getDate());
        ri.setMaster(master);
        if (!Util.isEmpty(overrides)) {
            for (final BwEventProxy pxy : overrides) {
                final BwEventAnnotation ann = pxy.getRef();
                if (!ann.getRecurrenceId().equals(ri.getRecurrenceId())) {
                    continue;
                }
                // be safe
                ann.setRecurring(false);
                if (ann.getTombstoned() == null) {
                    // be safe
                    ann.setTombstoned(false);
                }
                if (!ann.unsaved()) {
                    updateProxy(new BwEventProxy(ann));
                } else {
                    dao.save(ann);
                }
                ri.setOverride(ann);
                break;
            }
        }
        dao.save(ri);
        notifyInstanceChange(SysEvent.SysCode.ENTITY_ADDED, master, shared, start.getDate());
        uc.addAdded(ri);
    }
}
Also used : Dur(net.fortuna.ical4j.model.Dur) BwRecurrenceInstance(org.bedework.calfacade.BwRecurrenceInstance) BwDateTime(org.bedework.calfacade.BwDateTime) BwEventAnnotation(org.bedework.calfacade.BwEventAnnotation) BwEventProxy(org.bedework.calfacade.BwEventProxy)

Example 24 with BwEventAnnotation

use of org.bedework.calfacade.BwEventAnnotation in project bw-calendar-engine by Bedework.

the class CoreEvents method fixReferringAnnotations.

private void fixReferringAnnotations(final BwEvent val) throws CalFacadeException {
    for (final BwEventAnnotation ev : dao.getAnnotations(val, false)) {
        /* The recursive call is intended to allow annotations to annotatiuons.
       * Unfortunately this in't going to work as the reference in the
       * annotation class is always to the master event. We need an extra column
       * which allows chaining to an annotation
       */
        // XXX fix this fixReferringAnnotations(ev);
        // Force a fetch of the attendees - we need to look at them later
        ev.getAttendees();
        // if (ev.getAttendees() != null) {
        // ev.getAttendees().clear();
        // }
        dao.delete(ev);
    }
}
Also used : BwEventAnnotation(org.bedework.calfacade.BwEventAnnotation)

Example 25 with BwEventAnnotation

use of org.bedework.calfacade.BwEventAnnotation in project bw-calendar-engine by Bedework.

the class EventRule method end.

@Override
public void end(final String ns, final String name) throws Exception {
    if (!(top() instanceof EventInfo)) {
        warn("Top is not an event");
        warn(top().toString());
        return;
    }
    if (globals.entityError) {
        warn("Not restoring event because of previous error");
        warn(top().toString());
        return;
    }
    EventInfo ei = (EventInfo) top();
    BwEvent entity = ei.getEvent();
    if (entity instanceof BwEventProxy) {
        entity = ((BwEventProxy) entity).getRef();
    }
    boolean override = (entity instanceof BwEventAnnotation) && (((BwEventAnnotation) entity).getOverride());
    boolean alias = (entity instanceof BwEventAnnotation) && !override;
    globals.counts[globals.events]++;
    if ((globals.counts[globals.events] % 100) == 0) {
        info("Restore event # " + globals.counts[globals.events]);
    }
    if (!override) {
        fixSharableEntity(entity, "Event");
    }
    if ((entity.getEntityType() == IcalDefs.entityTypeTodo) && entity.getNoStart() && (entity.getEndType() == StartEndComponent.endTypeNone)) {
        /* The end date should be sometime in the distant future. If it isn't make
       * it so.
       * A bug was creating essentially one day events.
       */
        Date sdt = BwDateTimeUtil.getDate(entity.getDtstart());
        Date edt = BwDateTimeUtil.getDate(entity.getDtend());
        // about 9 years of millis
        long years9 = 52L * 7L * 24L * 60L * 60L * 1000L * 9L;
        if ((edt.getTime() - sdt.getTime()) < years9) {
            // about 10 years
            Dur years10 = new Dur(520);
            net.fortuna.ical4j.model.Date newDt = new net.fortuna.ical4j.model.Date(sdt.getTime());
            DtEnd dtEnd = new DtEnd(new net.fortuna.ical4j.model.Date(years10.getTime(newDt)));
            entity.setDtend(BwDateTime.makeBwDateTime(dtEnd));
            warn("Fixed task uid=" + entity.getUid());
        }
    }
    // Out here for debugging
    BwEvent target = null;
    BwEvent master = null;
    try {
        if (override) {
            pop();
            if (!(top() instanceof EventInfo)) {
                warn("Not restoring event because of previous error");
                warn(top().toString());
                return;
            }
            if (debug) {
                trace("Add override to event ");
            }
            EventInfo masterei = (EventInfo) top();
            masterei.addOverride(ei);
            return;
        }
        if (alias) {
            BwEventAnnotation ann = (BwEventAnnotation) entity;
            /* It's an alias, save an entry in the alias table then remove the dummy target.
         * We'll update them all at the end
         */
            // XXX Never did get on table globals.aliasTbl.put(ann);
            target = ann.getTarget();
            BwPrincipal annOwner = globals.getPrincipal(ann.getOwnerHref());
            BwEvent ntarget = globals.rintf.getEvent(annOwner, target.getColPath(), target.getRecurrenceId(), target.getUid());
            if (ntarget == null) {
                error("Unknown target " + target);
            }
            ann.setTarget(ntarget);
            master = ann.getMaster();
            if (master.equals(target)) {
                ann.setMaster(ntarget);
            } else {
                BwEvent nmaster = globals.rintf.getEvent(annOwner, master.getColPath(), master.getRecurrenceId(), master.getUid());
                if (nmaster == null) {
                    error("Unknown master " + master);
                }
                ann.setMaster(nmaster);
            }
        }
        boolean ok = true;
        if ((entity.getUid() == null) || (entity.getUid().length() == 0)) {
            error("Unable to save event " + entity + ". Has no guid.");
            ok = false;
        }
        if (entity.getColPath() == null) {
            error("Unable to save event " + entity + ". Has no calendar.");
            ok = false;
        }
        BwEvent ev = ei.getEvent();
        if (ok && (globals.rintf != null) && globals.onlyUsersMap.check(ev)) {
            globals.currentUser = globals.getPrincipal(ev.getOwnerHref());
            globals.rintf.restoreEvent(ei);
        }
    } catch (CalFacadeException cfe) {
        if (cfe.getMessage().equals(CalFacadeException.noRecurrenceInstances)) {
            error("Event has no recurrence instances - not restored." + entity.getUid() + "\n" + atLine());
        } else {
            error("Unable to save event " + entity.getUid() + "\n" + atLine());
            cfe.printStackTrace();
        }
    } catch (Throwable t) {
        error("Unable to save event " + entity.getUid() + "\n" + atLine());
        t.printStackTrace();
    }
    pop();
}
Also used : Dur(net.fortuna.ical4j.model.Dur) EventInfo(org.bedework.calfacade.svc.EventInfo) BwEvent(org.bedework.calfacade.BwEvent) BwEventProxy(org.bedework.calfacade.BwEventProxy) Date(java.util.Date) CalFacadeException(org.bedework.calfacade.exc.CalFacadeException) BwPrincipal(org.bedework.calfacade.BwPrincipal) BwEventAnnotation(org.bedework.calfacade.BwEventAnnotation) DtEnd(net.fortuna.ical4j.model.property.DtEnd)

Aggregations

BwEventAnnotation (org.bedework.calfacade.BwEventAnnotation)27 BwEvent (org.bedework.calfacade.BwEvent)22 BwEventProxy (org.bedework.calfacade.BwEventProxy)19 EventInfo (org.bedework.calfacade.svc.EventInfo)15 CoreEventInfo (org.bedework.calcorei.CoreEventInfo)10 BwDateTime (org.bedework.calfacade.BwDateTime)8 CalFacadeException (org.bedework.calfacade.exc.CalFacadeException)7 BwRecurrenceInstance (org.bedework.calfacade.BwRecurrenceInstance)6 BwCalendar (org.bedework.calfacade.BwCalendar)5 Dur (net.fortuna.ical4j.model.Dur)4 ArrayList (java.util.ArrayList)3 TreeSet (java.util.TreeSet)3 DateTime (net.fortuna.ical4j.model.DateTime)3 SearchResponse (org.elasticsearch.action.search.SearchResponse)3 SearchHit (org.elasticsearch.search.SearchHit)3 Period (net.fortuna.ical4j.model.Period)2 TimeZone (net.fortuna.ical4j.model.TimeZone)2 DtStart (net.fortuna.ical4j.model.property.DtStart)2 CurrentAccess (org.bedework.access.Acl.CurrentAccess)2 HibSession (org.bedework.calcorei.HibSession)2