use of org.bedework.calfacade.BwAttendee in project bw-calendar-engine by Bedework.
the class AttendeeSchedulingHandler method requestRefresh.
@Override
public ScheduleResult requestRefresh(final EventInfo ei, final String comment) throws CalFacadeException {
ScheduleResult sr = new ScheduleResult();
BwEvent ev = ei.getEvent();
if (ev.getScheduleMethod() != ScheduleMethods.methodTypeRequest) {
sr.errorCode = CalFacadeException.schedulingBadMethod;
return sr;
}
BwAttendee att = findUserAttendee(ev);
if (att == null) {
throw new CalFacadeException(CalFacadeException.schedulingNotAttendee);
}
BwEvent outEv = new BwEventObj();
EventInfo outEi = new EventInfo(outEv);
outEv.setScheduleMethod(ScheduleMethods.methodTypeRefresh);
outEv.addRecipient(ev.getOrganizer().getOrganizerUri());
outEv.setOriginator(att.getAttendeeUri());
outEv.updateDtstamp();
outEv.setOrganizer((BwOrganizer) ev.getOrganizer().clone());
outEv.getOrganizer().setDtstamp(outEv.getDtstamp());
outEv.addAttendee((BwAttendee) att.clone());
outEv.setUid(ev.getUid());
outEv.setRecurrenceId(ev.getRecurrenceId());
outEv.setDtstart(ev.getDtstart());
outEv.setDtend(ev.getDtend());
outEv.setDuration(ev.getDuration());
outEv.setNoStart(ev.getNoStart());
outEv.setRecurring(false);
if (comment != null) {
outEv.addComment(new BwString(null, comment));
}
sr = scheduleResponse(outEi);
outEv.setScheduleState(BwEvent.scheduleStateProcessed);
return sr;
}
use of org.bedework.calfacade.BwAttendee in project bw-calendar-engine by Bedework.
the class AttendeeSchedulingHandler method attendeeRespond.
@Override
public ScheduleResult attendeeRespond(final EventInfo ei, final int method) throws CalFacadeException {
ScheduleResult sr = new ScheduleResult();
final BwEvent ev = ei.getEvent();
check: {
/* Check that the current user is actually the only attendee of the event.
* Note we may have a suppressed master and/or multiple overrides
*/
BwAttendee att = null;
if (!ev.getSuppressed()) {
att = findUserAttendee(ev);
if (att == null) {
sr.errorCode = CalFacadeException.schedulingNotAttendee;
break check;
}
}
if (ei.getNumOverrides() > 0) {
for (final EventInfo oei : ei.getOverrides()) {
att = findUserAttendee(oei.getEvent());
if (att == null) {
sr.errorCode = CalFacadeException.schedulingNotAttendee;
break check;
}
}
}
if (ev.getOriginator() == null) {
sr.errorCode = CalFacadeException.schedulingNoOriginator;
break check;
}
// EventInfo outEi = makeReplyEventInfo(ei, getUser().getPrincipalRef());
final EventInfo outEi = copyEventInfo(ei, getPrincipal());
final BwEvent outEv = outEi.getEvent();
if (!Util.isEmpty(outEv.getRecipients())) {
outEv.getRecipients().clear();
}
if (!Util.isEmpty(outEv.getAttendees())) {
outEv.getAttendees().clear();
}
// XXX we should get a comment from non db field in event
// if (comment != null) {
// // Just add for the moment
// outEv.addComment(null, comment);
// }
outEv.addRecipient(outEv.getOrganizer().getOrganizerUri());
outEv.setOriginator(att.getAttendeeUri());
outEv.updateDtstamp();
outEv.getOrganizer().setDtstamp(outEv.getDtstamp());
String delegate = att.getDelegatedTo();
if (delegate != null) {
/* RFC 2446 4.2.5 - Delegating an event
*
* When delegating an event request to another "Calendar User", the
* "Delegator" must both update the "Organizer" with a "REPLY" and send
* a request to the "Delegate". There is currently no protocol
* limitation to delegation depth. It is possible for the original
* delegate to delegate the meeting to someone else, and so on. When a
* request is delegated from one CUA to another there are a number of
* responsibilities required of the "Delegator". The "Delegator" MUST:
*
* . Send a "REPLY" to the "Organizer" with the following updates:
* . The "Delegator's" "ATTENDEE" property "partstat" parameter set
* to "delegated" and the "delegated-to" parameter is set to the
* address of the "Delegate"
* . Add an additional "ATTENDEE" property for the "Delegate" with
* the "delegated-from" property parameter set to the "Delegator"
* . Indicate whether they want to continue to receive updates when
* the "Organizer" sends out updated versions of the event.
* Setting the "rsvp" property parameter to "TRUE" will cause the
* updates to be sent, setting it to "FALSE" causes no further
* updates to be sent. Note that in either case, if the "Delegate"
* declines the invitation the "Delegator" will be notified.
* . The "Delegator" MUST also send a copy of the original "REQUEST"
* method to the "Delegate".
*/
// outEv is the reply
outEv.setScheduleMethod(ScheduleMethods.methodTypeReply);
// Additional attendee
BwAttendee delAtt = new BwAttendee();
delAtt.setAttendeeUri(delegate);
delAtt.setDelegatedFrom(att.getAttendeeUri());
delAtt.setPartstat(IcalDefs.partstatValNeedsAction);
delAtt.setRsvp(true);
delAtt.setRole(att.getRole());
outEv.addAttendee(delAtt);
// ei is 'original "REQUEST"'. */
EventInfo delegateEi = copyEventInfo(ei, getPrincipal());
BwEvent delegateEv = delegateEi.getEvent();
delegateEv.addRecipient(delegate);
// Not in RFC
delegateEv.addAttendee((BwAttendee) delAtt.clone());
delegateEv.setScheduleMethod(ScheduleMethods.methodTypeRequest);
att.setPartstat(IcalDefs.partstatValDelegated);
att.setRsvp(false);
att.setDelegatedTo(delegate);
// XXX Not sure if this is correct
schedule(delegateEi, null, null, false);
} else if (method == ScheduleMethods.methodTypeReply) {
// Only attendee should be us
ei.setOnlyAttendee(outEi, att.getAttendeeUri());
if (ev.getEntityType() == IcalDefs.entityTypeVpoll) {
setPollResponse(outEi, ei, att.getAttendeeUri());
}
outEv.setScheduleMethod(ScheduleMethods.methodTypeReply);
} else if (method == ScheduleMethods.methodTypeCounter) {
// Only attendee should be us
ei.setOnlyAttendee(outEi, att.getAttendeeUri());
/* Not sure how much we can change - at least times of the meeting.
*/
outEv.setScheduleMethod(ScheduleMethods.methodTypeCounter);
} else {
throw new RuntimeException("Never get here");
}
outEv.addRequestStatus(new BwRequestStatus(IcalDefs.requestStatusSuccess.getCode(), IcalDefs.requestStatusSuccess.getDescription()));
sr = scheduleResponse(outEi);
outEv.setScheduleState(BwEvent.scheduleStateProcessed);
ev.getOrganizer().setScheduleStatus(IcalDefs.deliveryStatusDelivered);
}
return sr;
}
use of org.bedework.calfacade.BwAttendee in project bw-calendar-engine by Bedework.
the class InRefresh method process.
/**
* @param ei the event
* @return ScheduleResult
* @throws CalFacadeException
*/
@Override
public ProcessResult process(final EventInfo ei) throws CalFacadeException {
final SchedulingI sched = getSvc().getScheduler();
final BwEvent ev = ei.getEvent();
final ProcessResult pr = new ProcessResult();
pr.noInboxChange = true;
/* Refresh request from attendee - send our copy
*/
/* Should be exactly one attendee. */
Collection<BwAttendee> atts = ev.getAttendees();
if ((atts == null) || (atts.size() != 1)) {
return null;
}
BwAttendee att = atts.iterator().next();
/* We can only do this if there is an active copy */
EventInfo calEi = sched.getStoredMeeting(ev);
if (calEi == null) {
return null;
}
calEi.getEvent().setScheduleMethod(ScheduleMethods.methodTypeRequest);
/* Just send a copy to the attendee. */
pr.sr = sched.schedule(calEi, att.getAttendeeUri(), null, false);
if (pr.sr.errorCode == null) {
getSvc().getEventsHandler().delete(ei, false);
}
return pr;
}
use of org.bedework.calfacade.BwAttendee in project bw-calendar-engine by Bedework.
the class InRequest method initAttendeeCopy.
private boolean initAttendeeCopy(final CalSvcI svci, final String newColPath, final BwEvent ev, final String uri) throws CalFacadeException {
ev.setColPath(newColPath);
ev.setAttendeeSchedulingObject(true);
ev.setOrganizerSchedulingObject(false);
if (!(ev instanceof BwEventProxy) && ev.getSuppressed()) {
return true;
}
BwAttendee att = ev.findAttendee(uri);
if (att == null) {
// Error?
if (debug) {
trace("Schedule - no attendee with uri " + uri + " for " + svci.getPrincipal().getPrincipalRef());
}
return false;
}
// att.setScheduleStatus(IcalDefs.deliveryStatusSuccess);
if ((att.getPartstat() == null) || att.getPartstat().equals(IcalDefs.partstatValNeedsAction)) {
if (att.getPartstat() == null) {
att.setPartstat(IcalDefs.partstatValNeedsAction);
}
ev.setTransparency(IcalDefs.transparencyTransparent);
// Apple ical seems to expect an x-prop.
// ev.addXproperty(new BwXproperty(BwXproperty.appleNeedsReply,
// null, "TRUE"));
}
return true;
}
use of org.bedework.calfacade.BwAttendee in project bw-calendar-engine by Bedework.
the class InRequest method autoRespond.
/* ====================================================================
Private methods
==================================================================== */
private boolean autoRespond(final CalSvcI svci, final EventInfo ourCopy, final EventInfo inboxEi, final boolean doubleBookOk, final String uri) throws CalFacadeException {
BwEvent inboxEv = inboxEi.getEvent();
String owner = inboxEv.getOwnerHref();
if (ourCopy == null) {
// Error - deleted while we did this?
if (debug) {
trace("InSchedule - no event for auto respond for " + owner);
}
return false;
}
BwOrganizer org = new BwOrganizer();
org.setOrganizerUri(uri);
BwAttendee att = null;
BwEvent ourEvent = ourCopy.getEvent();
String now = DateTimeUtil.isoDateTimeUTC(new Date());
if (!ourEvent.getRecurring()) {
if (ourEvent.getDtend().getDate().compareTo(now) < 0) {
return false;
}
att = ourEvent.findAttendee(uri);
if (att == null) {
// Error?
if (debug) {
trace("InSchedule - no attendee on our copy for auto respond for " + owner);
}
return false;
}
if (debug) {
trace("send response event for " + owner + " " + inboxEv.getName());
}
// We're about to reply.
att.setRsvp(false);
String partStat = IcalDefs.partstatValAccepted;
ourEvent.removeXproperties(BwXproperty.appleNeedsReply);
if (!doubleBookOk) {
// See if there are any events booked during this time.
if (checkBusy(svci, ourEvent.getUid(), inboxEv.getDtstart(), inboxEv.getDtend(), org, inboxEv.getUid())) {
partStat = IcalDefs.partstatValDeclined;
} else {
ourEvent.setTransparency(IcalDefs.transparencyOpaque);
}
}
ourEvent.setScheduleMethod(ScheduleMethods.methodTypeReply);
att = (BwAttendee) att.clone();
ourEvent.removeAttendee(att);
ourEvent.addAttendee(att);
att.setPartstat(partStat);
return true;
}
// Recurring event - do the above per recurrence
AuthProperties authpars = svci.getAuthProperties();
int maxYears = authpars.getMaxYears();
int maxInstances = authpars.getMaxInstances();
Collection<Recurrence> recurrences = RecurUtil.getRecurrences(inboxEi, maxYears, maxInstances, now, null);
if (Util.isEmpty(recurrences)) {
return false;
}
if (debug) {
trace("autoRespond: " + recurrences.size() + " instances");
}
/* Assume accept and then override with declines - assuming we're in the
* master
*/
ourEvent.removeXproperties(BwXproperty.appleNeedsReply);
boolean masterSupressed = true;
if (!inboxEv.getSuppressed()) {
masterSupressed = false;
att = ourEvent.findAttendee(uri);
if (att != null) {
// It should never be null
att.setRsvp(false);
att.setPartstat(IcalDefs.partstatValAccepted);
}
ourEvent.setTransparency(IcalDefs.transparencyOpaque);
}
RecurInfo rinfo = checkBusy(svci, ourEvent.getUid(), recurrences, org, inboxEv.getUid(), doubleBookOk);
/* If we have a master then we should set its status to cover the largest
* number of overrides - if any.
*
* The easiest case is no overrides and all accepted or all declined.
*
* Otherwise we have to update or add overrides.
*/
boolean allAcceptedOrDeclined = (rinfo.availCt == 0) || (rinfo.busyCt == 0);
boolean masterAccept = rinfo.availCt >= rinfo.busyCt;
String masterPartStat;
if (masterAccept) {
masterPartStat = IcalDefs.partstatValAccepted;
} else {
masterPartStat = IcalDefs.partstatValDeclined;
}
if (!masterSupressed) {
att = ourEvent.findAttendee(uri);
if (!masterPartStat.equals(att.getPartstat())) {
att.setPartstat(masterPartStat);
}
if (masterAccept) {
ourEvent.setTransparency(IcalDefs.transparencyOpaque);
} else {
ourEvent.setTransparency(IcalDefs.transparencyTransparent);
}
}
if (allAcceptedOrDeclined) {
// Ensure any overrides have the same status
for (EventInfo oei : ourCopy.getOverrides()) {
BwEvent override = oei.getEvent();
att = override.findAttendee(uri);
att = (BwAttendee) att.clone();
// We're about to reply.
att.setRsvp(false);
override.removeAttendee(att);
override.addAttendee(att);
if (!masterPartStat.equals(att.getPartstat())) {
att.setPartstat(masterPartStat);
}
if (masterAccept) {
override.setTransparency(IcalDefs.transparencyOpaque);
} else {
override.setTransparency(IcalDefs.transparencyTransparent);
}
override.removeXproperties(BwXproperty.appleNeedsReply);
}
return true;
}
for (RecurrenceInfo ri : rinfo.ris) {
Recurrence r = ri.r;
// if (!masterSupressed && !ri.busy && (r.override == null)) {
// // fine
// continue;
// }
boolean mustOverride = masterAccept == ri.busy;
EventInfo oei = ourCopy.findOverride(r.recurrenceId, mustOverride);
if (oei == null) {
continue;
}
BwEvent override = oei.getEvent();
if (((BwEventProxy) override).getRef().unsaved()) {
override.setDtstart(r.start);
override.setDtend(r.end);
override.setDuration(BwDateTime.makeDuration(r.start, r.end).toString());
}
att = override.findAttendee(uri);
if (att == null) {
// Guess we weren't invited
continue;
}
att = (BwAttendee) att.clone();
// We're about to reply.
att.setRsvp(false);
override.removeAttendee(att);
override.addAttendee(att);
if (!ri.busy) {
att.setPartstat(IcalDefs.partstatValAccepted);
override.setTransparency(IcalDefs.transparencyOpaque);
} else {
att.setPartstat(IcalDefs.partstatValDeclined);
override.setTransparency(IcalDefs.transparencyTransparent);
}
override.removeXproperties(BwXproperty.appleNeedsReply);
}
return true;
}
Aggregations