use of org.bedework.calfacade.svc.EventInfo in project bw-calendar-engine by Bedework.
the class InReply method process.
@Override
public ProcessResult process(final EventInfo ei) throws CalFacadeException {
/* Process a response we as the organizer, or their proxy, received from
* an attendee
*/
final ProcessResult pr = new ProcessResult();
final SchedulingI sched = getSvc().getScheduler();
BwEvent ev = ei.getEvent();
final EventInfo colEi = sched.getStoredMeeting(ev);
/* The event should have a calendar set to the inbox it came from.
* That inbox may be owned by somebody other than the current user if a
* calendar user has delegated control of their inbox to some other user
* e.g. secretary.
*/
pr.attendeeAccepting = true;
check: {
if (colEi == null) {
// No corresponding stored meeting
break check;
}
if (ev.getOriginator() == null) {
pr.sr.errorCode = CalFacadeException.schedulingNoOriginator;
break check;
}
String attUri = null;
/* Should be exactly one attendee */
if (!ev.getSuppressed()) {
final Collection<BwAttendee> atts = ev.getAttendees();
if ((atts == null) || (atts.size() != 1)) {
pr.sr.errorCode = CalFacadeException.schedulingExpectOneAttendee;
break check;
}
final BwAttendee att = atts.iterator().next();
if (!att.getPartstat().equals(acceptPartstat)) {
pr.attendeeAccepting = false;
}
attUri = att.getAttendeeUri();
}
if (ei.getNumOverrides() > 0) {
for (final EventInfo oei : ei.getOverrides()) {
ev = oei.getEvent();
final Collection<BwAttendee> atts = ev.getAttendees();
if ((atts == null) || (atts.size() != 1)) {
pr.sr.errorCode = CalFacadeException.schedulingExpectOneAttendee;
break check;
}
final BwAttendee att = atts.iterator().next();
if (!att.getPartstat().equals(acceptPartstat)) {
pr.attendeeAccepting = false;
}
if (attUri == null) {
attUri = att.getAttendeeUri();
} else if (!attUri.equals(att.getAttendeeUri())) {
pr.sr.errorCode = CalFacadeException.schedulingExpectOneAttendee;
break check;
}
}
}
if (attUri == null) {
pr.sr.errorCode = CalFacadeException.schedulingExpectOneAttendee;
break check;
}
/*TODO If the sequence of the incoming event is lower than the sequence on the
* calendar event we ignore it.
*/
final boolean vpoll = colEi.getEvent().getEntityType() == IcalDefs.entityTypeVpoll;
if (vpoll) {
if (!updateOrganizerPollCopy(colEi, ei, attUri, pr.sr)) {
break check;
}
} else if (!updateOrganizerCopy(colEi, ei, attUri, pr.sr)) {
break check;
}
pr.removeInboxEntry = false;
}
return pr;
}
use of org.bedework.calfacade.svc.EventInfo in project bw-calendar-engine by Bedework.
the class InReply method updateOrganizerCopy.
private boolean updateOrganizerCopy(final EventInfo colEi, final EventInfo inBoxEi, final String attUri, final ScheduleResult sr) throws CalFacadeException {
final BwEvent inBoxEv = inBoxEi.getEvent();
final BwEvent calEv = colEi.getEvent();
final ChangeTable chg = calEv.getChangeset(getPrincipalHref());
/* Only set true if the inbox copy needs to stay as notification.
* Do not set true for status updates
*/
boolean changed = false;
if (debug) {
trace("Update for attendee " + attUri);
}
if (inBoxEv.getScheduleMethod() != ScheduleMethods.methodTypeReply) {
sr.errorCode = CalFacadeException.schedulingBadMethod;
return false;
}
/* If the incoming sequence is less than that in the organizers event
* then ignore the incoming reply?
*/
/* Update the participation status from the incoming attendee */
BwAttendee calAtt;
final ChangeTableEntry cte = chg.getEntry(PropertyIndex.PropertyInfoIndex.ATTENDEE);
if (!inBoxEv.getSuppressed()) {
calAtt = calEv.findAttendee(attUri);
if (calAtt == null) {
if (debug) {
trace("Not an attendee of " + calEv);
}
sr.errorCode = CalFacadeException.schedulingUnknownAttendee;
sr.extraInfo = attUri;
return false;
}
// For a recurring instance we replace or we update all recurring instances.
final boolean recurringInstance = (calEv instanceof BwEventProxy);
final BwAttendee att = inBoxEv.findAttendee(attUri);
if (calAtt.changedBy(att)) {
changed = true;
if (recurringInstance) {
calEv.removeAttendee(att);
calAtt = (BwAttendee) att.clone();
} else {
att.copyTo(calAtt);
}
cte.addChangedValue(calAtt);
}
calAtt.setScheduleStatus(getRstat(inBoxEv));
if (recurringInstance) {
calEv.addAttendee(calAtt);
}
// XXX Ensure no name change
if (calEv instanceof BwEventProxy) {
final BwEventProxy pr = (BwEventProxy) calEv;
final BwEventAnnotation ann = pr.getRef();
ann.setName(null);
}
}
/* The above changed the master - now we need to update or add any overrides
*/
if (calEv.getRecurring() && (inBoxEi.getOverrides() != null)) {
for (final EventInfo oei : inBoxEi.getOverrides()) {
final BwEvent oev = oei.getEvent();
final EventInfo cei = colEi.findOverride(oev.getRecurrenceId());
/*
if (cei == null) {
// Organizer must have deleted the override.
if (debug) {
trace("Skipping missing override " + oev.getRecurrenceId());
}
continue;
}*/
final BwEvent ocalEv = cei.getEvent();
if (((BwEventProxy) ocalEv).getRef().unsaved()) {
// New Override
try {
final String rid = oev.getRecurrenceId();
Date dt = new DateTime(rid);
if (calEv.getDtstart().getDateType()) {
// RECUR - fix all day recurrences sometime
if (rid.length() > 8) {
// Try to fix up bad all day recurrence ids. - assume a local timezone
((DateTime) dt).setTimeZone(null);
dt = new Date(dt.toString().substring(0, 8));
}
}
final DtStart st = new DtStart(dt);
final String tzid = calEv.getDtstart().getTzid();
if (tzid != null) {
final TimeZone tz = Timezones.getTz(tzid);
st.setTimeZone(tz);
}
ocalEv.setDtstart(BwDateTime.makeBwDateTime(st));
ocalEv.setDuration(calEv.getDuration());
ocalEv.setDtend(ocalEv.getDtstart().addDur(new Dur(calEv.getDuration())));
} catch (final CalFacadeException cfe) {
throw cfe;
} catch (final Throwable t) {
throw new CalFacadeException(t);
}
}
final BwAttendee ovatt = oev.findAttendee(attUri);
calAtt = ocalEv.findAttendee(attUri);
if (calAtt == null) {
// Organizer must have removed the attendee.
if (debug) {
trace("Skipping override " + attUri + " is not attending");
}
continue;
}
if (calAtt.changedBy(ovatt)) {
changed = true;
ocalEv.removeAttendee(ovatt);
calAtt = (BwAttendee) ovatt.clone();
calAtt.setScheduleStatus(getRstat(oev));
ocalEv.addAttendee(calAtt);
cte.addChangedValue(calAtt);
}
}
}
final boolean noinvites = !changed;
colEi.setReplyUpdate(true);
/* Update the organizer copy. This will broadcast the changes tp all
* attendees
*/
getSvc().getEventsHandler().update(colEi, noinvites, attUri);
return changed;
}
use of org.bedework.calfacade.svc.EventInfo in project bw-calendar-engine by Bedework.
the class ImplicitSchedulingHandler method implicitSchedule.
@Override
public void implicitSchedule(final EventInfo ei, final boolean noInvites) throws CalFacadeException {
UpdateResult uer = ei.getUpdResult();
if (debug) {
dump(uer);
}
BwEvent ev = ei.getEvent();
boolean organizerSchedulingObject = ev.getOrganizerSchedulingObject();
boolean attendeeSchedulingObject = ev.getAttendeeSchedulingObject();
if (ev.getSuppressed()) {
if (!Util.isEmpty(ei.getOverrides())) {
for (EventInfo oei : ei.getOverrides()) {
uer = oei.getUpdResult();
if (debug) {
dump(uer);
}
BwEvent oev = oei.getEvent();
if (oev.getOrganizerSchedulingObject()) {
organizerSchedulingObject = true;
}
if (oev.getAttendeeSchedulingObject()) {
attendeeSchedulingObject = true;
}
}
}
}
if (!organizerSchedulingObject && !attendeeSchedulingObject) {
// Not a scheduling event
if (debug) {
trace("No a scheduling object: just return");
}
return;
}
if (ev.getOrganizer() == null) {
throw new CalFacadeBadRequest(CalFacadeException.missingEventProperty);
}
if (ev.getOriginator() == null) {
ev.setOriginator(ev.getOrganizer().getOrganizerUri());
}
if (uer.reply) {
int meth;
if (ei.getReplyAttendeeURI() != null) {
meth = ScheduleMethods.methodTypeRefresh;
} else {
meth = ScheduleMethods.methodTypeReply;
}
ev.setScheduleMethod(meth);
uer.schedulingResult = attendeeRespond(ei, meth);
return;
}
if (uer.deleting) {
if (organizerSchedulingObject) {
// if (schedMethod == Icalendar.methodTypeCancel) {
// /* We already canceled this one */
// return;
// }
ev.setScheduleMethod(ScheduleMethods.methodTypeCancel);
} else {
// Reply from attendee setting partstat
ev.setScheduleMethod(ScheduleMethods.methodTypeReply);
}
} else {
ev.setScheduleMethod(ScheduleMethods.methodTypeRequest);
}
if (!noInvites) {
uer.schedulingResult = schedule(ei, ei.getReplyAttendeeURI(), uer.fromAttUri, false);
}
if (!uer.adding && !Util.isEmpty(uer.deletedAttendees)) {
/* Send cancel to removed attendees */
for (BwAttendee att : uer.deletedAttendees) {
if (Util.compareStrings(att.getPartstat(), IcalDefs.partstats[IcalDefs.partstatDeclined]) == 0) {
// Already declined - send nothing
continue;
}
/* Clone is adequate here. For a CANCEL we just send either the master
* or the particular instance.
*/
BwEvent cncl = (BwEvent) ev.clone();
cncl.setAttendees(null);
cncl.addAttendee((BwAttendee) att.clone());
cncl.setRecipients(null);
cncl.addRecipient(att.getAttendeeUri());
cncl.setScheduleMethod(ScheduleMethods.methodTypeCancel);
cncl.setOrganizerSchedulingObject(true);
cncl.setAttendeeSchedulingObject(false);
EventInfo cei = new EventInfo(cncl);
ScheduleResult cnclr = schedule(cei, null, null, false);
if (debug) {
trace(cnclr.toString());
}
}
}
if (ei.getInboxEventName() != null) {
// Delete the given event from the inbox.
EventsI events = getSvc().getEventsHandler();
BwCalendar inbox = getSvc().getCalendarsHandler().getSpecial(BwCalendar.calTypeInbox, true);
final EventInfo inboxei = events.get(inbox.getPath(), ei.getInboxEventName());
if (inboxei != null) {
events.delete(inboxei, false);
}
}
}
use of org.bedework.calfacade.svc.EventInfo in project bw-calendar-engine by Bedework.
the class OrganizerSchedulingHandler method declineCounter.
@Override
public ScheduleResult declineCounter(final EventInfo ei, final String comment, final BwAttendee fromAtt) throws CalFacadeException {
final EventInfo outEi = copyEventInfo(ei, getPrincipal());
final BwEvent ev = outEi.getEvent();
ev.setScheduleMethod(ScheduleMethods.methodTypeDeclineCounter);
if (comment != null) {
ev.addComment(null, comment);
}
return schedule(outEi, fromAtt.getAttendeeUri(), null, false);
}
use of org.bedework.calfacade.svc.EventInfo in project bw-calendar-engine by Bedework.
the class OutboundSchedulingHandler method addToInbox.
/**
* Add a copy of senderEi to the users inbox and add to the autoschedule queue.
* The 'sender' may be the organizer of a meeting, if it's REQUEST etc, or the
* attendee replying.
*
* @param inboxPath - eventual destination
* @param attPrincipal - attendees principal
* @param senderEi the event
* @param fromOrganizer - true if it's coming from the organizer
* @return null for ok, errorcode otherwise
* @throws CalFacadeException
*/
private String addToInbox(final String inboxPath, final BwPrincipal attPrincipal, final EventInfo senderEi, final boolean fromOrganizer) throws CalFacadeException {
final EventInfo ei = copyEventInfo(senderEi, fromOrganizer, attPrincipal);
final BwEvent ev = ei.getEvent();
if (senderEi.getReplyUpdate()) {
// Flag as a trivial update to attendee status
ev.addXproperty(new BwXproperty(BwXproperty.bedeworkSchedulingReplyUpdate, null, "true"));
}
if (!Util.isEmpty(ev.getRecipients())) {
ev.getRecipients().clear();
}
ev.addRecipient(getSvc().getDirectories().principalToCaladdr(attPrincipal));
/*
if (destAtt != null) {
String attPartStat = destAtt.getPartstat();
if ((attPartStat == null) || // default - needs-action
(!attPartStat.equalsIgnoreCase(IcalDefs.partstatValAccepted) &&
!attPartStat.equalsIgnoreCase(IcalDefs.partstatValCompleted) &&
!attPartStat.equalsIgnoreCase(IcalDefs.partstatValDelegated))) {
ev.setTransparency(IcalDefs.transparencyTransparent);
}
}*/
final String evDtstamp = ev.getDtstamp();
ev.setScheduleState(BwEvent.scheduleStateNotProcessed);
ev.setColPath(inboxPath);
if (ei.getNumContainedItems() > 0) {
for (final EventInfo cei : ei.getContainedItems()) {
cei.getEvent().setColPath(inboxPath);
}
}
/* Before we add this we should see if there is an earlier one we can
* discard. As attendees update their status we get many requests sent to
* each attendee.
*
* Also this current message may be earlier than one already in the inbox.
*
* TODO - fix recurrences
*
* We could get separate messages for the same uid but with different
* recurrence ids if we are an attendee to some instances only.
*
* In the inbox these will be separate events with the same uid -
* possibly, They probably need to be combined in the users
* calendar as a single recurring event.
*/
final int smethod = ev.getScheduleMethod();
if (Icalendar.itipRequestMethodType(smethod)) {
final Collection<EventInfo> inevs = getEventsByUid(inboxPath, ev.getUid());
for (final EventInfo inei : inevs) {
final BwEvent inev = inei.getEvent();
final int cres = evDtstamp.compareTo(inev.getDtstamp());
if (cres <= 0) {
// Discard the new one
return null;
}
/* Discard the earlier message */
/* XXX What if this message is currently being processed by the inbox
* handler process? Does it matter - will it reappear?
*
* Probably need to handle stale-state exceptions at the other end.
*/
deleteEvent(inei, true, false);
}
}
/* Add it and post to the autoscheduler */
final String ecode = addEvent(ei, "In-" + Uid.getUid() + "-" + evDtstamp, BwCalendar.calTypePendingInbox, true);
if (ecode != null) {
return ecode;
}
if (debug) {
trace("Add event with name " + ev.getName() + " and summary " + ev.getSummary() + " to " + ev.getColPath());
}
addAutoScheduleMessage(true, attPrincipal.getPrincipalRef(), ev.getName());
return null;
}
Aggregations