Search in sources :

Example 1 with CollectionInfo

use of org.bedework.calfacade.BwCalendar.CollectionInfo 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 2 with CollectionInfo

use of org.bedework.calfacade.BwCalendar.CollectionInfo 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)

Aggregations

BwCalendar (org.bedework.calfacade.BwCalendar)2 CollectionInfo (org.bedework.calfacade.BwCalendar.CollectionInfo)2 BwDateTime (org.bedework.calfacade.BwDateTime)2 BwEvent (org.bedework.calfacade.BwEvent)2 BwEventAnnotation (org.bedework.calfacade.BwEventAnnotation)2 BwEventProxy (org.bedework.calfacade.BwEventProxy)2 BwRecurrenceInstance (org.bedework.calfacade.BwRecurrenceInstance)2 ArrayList (java.util.ArrayList)1 DateTime (net.fortuna.ical4j.model.DateTime)1 Dur (net.fortuna.ical4j.model.Dur)1 Period (net.fortuna.ical4j.model.Period)1 TimeZone (net.fortuna.ical4j.model.TimeZone)1 CoreEventInfo (org.bedework.calcorei.CoreEventInfo)1 BwDbentity (org.bedework.calfacade.base.BwDbentity)1 CalFacadeDupNameException (org.bedework.calfacade.exc.CalFacadeDupNameException)1 CalFacadeException (org.bedework.calfacade.exc.CalFacadeException)1 EventInfo (org.bedework.calfacade.svc.EventInfo)1 RecurPeriods (org.bedework.icalendar.RecurUtil.RecurPeriods)1