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;
}
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;
}
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);
}
}
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);
}
}
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();
}
Aggregations