use of org.bedework.calfacade.BwFreeBusyComponent in project bw-calendar-engine by Bedework.
the class FreeAndBusyHandler method getFreeBusy.
/* (non-Javadoc)
* @see org.bedework.calsvci.SchedulingI#getFreeBusy(java.util.Collection, org.bedework.calfacade.BwPrincipal, org.bedework.calfacade.BwDateTime, org.bedework.calfacade.BwDateTime, org.bedework.calfacade.BwOrganizer, java.lang.String)
*/
@Override
public BwEvent getFreeBusy(final Collection<BwCalendar> fbset, final BwPrincipal who, final BwDateTime start, final BwDateTime end, final BwOrganizer org, final String uid, final String exceptUid) throws CalFacadeException {
CalendarsI colHandler = getSvc().getCalendarsHandler();
Collection<BwCalendar> cals = null;
if (fbset != null) {
/* Don't check - we do so at the fetch of events
getCal().checkAccess(cal, PrivilegeDefs.privReadFreeBusy, false);
*/
cals = addToFreeBusySet(cals, fbset);
} else if (getPrincipal().equals(who)) {
cals = getFreebusySet();
} else {
/* CalDAV uses Inbox to determine scheduling acccess */
try {
getSpecialCalendar(who, BwCalendar.calTypeInbox, true, PrivilegeDefs.privReadFreeBusy);
} catch (CalFacadeAccessException cae) {
getSpecialCalendar(who, BwCalendar.calTypeInbox, true, PrivilegeDefs.privScheduleFreeBusy);
}
cals = addToFreeBusySet(cals, colHandler.getChildren(colHandler.getHome(who, true)));
}
if (cals == null) {
throw new CalFacadeAccessException();
}
BwEvent fb = new BwEventObj();
fb.setEntityType(IcalDefs.entityTypeFreeAndBusy);
fb.setOwnerHref(who.getPrincipalRef());
fb.setDtstart(start);
fb.setDtend(end);
fb.setEndType(StartEndComponent.endTypeDate);
if (uid == null) {
assignGuid(fb);
} else {
fb.setUid(uid);
}
fb.setDtstamps(getCurrentTimestamp());
String uri = getSvc().getDirectories().principalToCaladdr(who);
BwAttendee att = new BwAttendee();
att.setAttendeeUri(uri);
fb.addAttendee(att);
fb.setOrganizer((BwOrganizer) org.clone());
Collection<EventInfo> events = new TreeSet<EventInfo>();
/* Only events and freebusy for freebusy reports. */
FilterBase filter = new OrFilter();
try {
filter.addChild(EntityTypeFilter.makeEntityTypeFilter(null, "event", false));
filter.addChild(EntityTypeFilter.makeEntityTypeFilter(null, "freeAndBusy", false));
} catch (Throwable t) {
throw new CalFacadeException(t);
}
String userHref = who.getPrincipalRef();
for (BwCalendar c : cals) {
if (!c.getAffectsFreeBusy()) {
continue;
}
// XXX If it's an external subscription we probably just get free busy and
// merge it in.
RecurringRetrievalMode rrm = new RecurringRetrievalMode(Rmode.expanded, start, end);
Collection<BwCalendar> cs = new ArrayList<BwCalendar>();
cs.add(c);
Collection<EventInfo> evs = getEvents(cs, filter, start, end, // retrieveList
null, rrm, true);
// Filter out transparent events
for (EventInfo ei : evs) {
BwEvent ev = ei.getEvent();
if ((exceptUid != null) && exceptUid.equals(ev.getUid())) {
continue;
}
if (!c.getIgnoreTransparency() && IcalDefs.transparencyTransparent.equals(ev.getPeruserTransparency(userHref))) {
// Ignore this one.
continue;
}
if (BwEvent.statusCancelled.equals(ev.getStatus())) {
// Ignore this one.
continue;
}
if (ev.getAttendeeSchedulingObject()) {
att = ev.findAttendee(uri);
if (att != null) {
int pstat = IcalDefs.checkPartstat(att.getPartstat());
if (pstat == IcalDefs.partstatDeclined) {
continue;
}
if (pstat == IcalDefs.partstatNeedsAction) {
continue;
}
}
}
events.add(ei);
}
}
try {
EventPeriods eventPeriods = new EventPeriods(start, end);
for (EventInfo ei : events) {
BwEvent ev = ei.getEvent();
int type;
if (ev.getEntityType() == IcalDefs.entityTypeEvent) {
if (BwEvent.statusCancelled.equals(ev.getStatus())) {
// Ignore this one.
continue;
}
type = BwFreeBusyComponent.typeBusy;
if (ev.getAttendeeSchedulingObject()) {
att = ev.findAttendee(uri);
if (att != null) {
if (IcalDefs.checkPartstat(att.getPartstat()) == IcalDefs.partstatTentative) {
type = BwFreeBusyComponent.typeBusyTentative;
}
}
}
if (BwEvent.statusTentative.equals(ev.getStatus())) {
type = BwFreeBusyComponent.typeBusyTentative;
} else if (BwEvent.statusUnavailable.equals(ev.getStatus())) {
type = BwFreeBusyComponent.typeBusyUnavailable;
}
eventPeriods.addPeriod(ev.getDtstart(), ev.getDtend(), type);
} else if (ev.getEntityType() == IcalDefs.entityTypeFreeAndBusy) {
Collection<BwFreeBusyComponent> fbcs = ev.getFreeBusyPeriods();
for (BwFreeBusyComponent fbc : fbcs) {
type = fbc.getType();
for (Period p : fbc.getPeriods()) {
eventPeriods.addPeriod(p.getStart(), p.getEnd(), type);
}
}
}
}
/* iterate through the sorted periods combining them where they are
adjacent or overlap */
BwFreeBusyComponent fbc = eventPeriods.makeFreeBusyComponent(BwFreeBusyComponent.typeBusy);
if (fbc != null) {
fb.addFreeBusyPeriod(fbc);
}
fbc = eventPeriods.makeFreeBusyComponent(BwFreeBusyComponent.typeBusyUnavailable);
if (fbc != null) {
fb.addFreeBusyPeriod(fbc);
}
fbc = eventPeriods.makeFreeBusyComponent(BwFreeBusyComponent.typeBusyTentative);
if (fbc != null) {
fb.addFreeBusyPeriod(fbc);
}
} catch (Throwable t) {
if (debug) {
error(t);
}
throw new CalFacadeException(t);
}
return fb;
}
use of org.bedework.calfacade.BwFreeBusyComponent in project bw-calendar-engine by Bedework.
the class CalintfImpl method getFreeBusy.
/* ====================================================================
* Free busy
* ==================================================================== */
@Override
public BwEvent getFreeBusy(final Collection<BwCalendar> cals, final BwPrincipal who, final BwDateTime start, final BwDateTime end, final boolean returnAll, final boolean ignoreTransparency) throws CalFacadeException {
if (who.getKind() != WhoDefs.whoTypeUser) {
throw new CalFacadeException("Unsupported: non user principal for free-busy");
}
final Collection<CoreEventInfo> events = getFreeBusyEntities(cals, start, end, ignoreTransparency);
final BwEvent fb = new BwEventObj();
fb.setEntityType(IcalDefs.entityTypeFreeAndBusy);
fb.setOwnerHref(who.getPrincipalRef());
fb.setDtstart(start);
fb.setDtend(end);
try {
final TreeSet<EventPeriod> eventPeriods = new TreeSet<>();
for (final CoreEventInfo ei : events) {
final BwEvent ev = ei.getEvent();
// Ignore if times were specified and this event is outside the times
final BwDateTime estart = ev.getDtstart();
final BwDateTime eend = ev.getDtend();
/* Don't report out of the requested period */
final String dstart;
final String dend;
if (estart.before(start)) {
dstart = start.getDtval();
} else {
dstart = estart.getDtval();
}
if (eend.after(end)) {
dend = end.getDtval();
} else {
dend = eend.getDtval();
}
final DateTime psdt = new DateTime(dstart);
final DateTime pedt = new DateTime(dend);
psdt.setUtc(true);
pedt.setUtc(true);
int type = BwFreeBusyComponent.typeBusy;
if (BwEvent.statusTentative.equals(ev.getStatus())) {
type = BwFreeBusyComponent.typeBusyTentative;
}
eventPeriods.add(new EventPeriod(psdt, pedt, type));
}
/* iterate through the sorted periods combining them where they are
adjacent or overlap */
Period p = null;
/* For the moment just build a single BwFreeBusyComponent
*/
BwFreeBusyComponent fbc = null;
int lastType = 0;
for (final EventPeriod ep : eventPeriods) {
if (debug) {
debug(ep.toString());
}
if (p == null) {
p = new Period(ep.getStart(), ep.getEnd());
lastType = ep.getType();
} else if ((lastType != ep.getType()) || ep.getStart().after(p.getEnd())) {
// Non adjacent periods
if (fbc == null) {
fbc = new BwFreeBusyComponent();
fbc.setType(lastType);
fb.addFreeBusyPeriod(fbc);
}
fbc.addPeriod(p.getStart(), p.getEnd());
if (lastType != ep.getType()) {
fbc = null;
}
p = new Period(ep.getStart(), ep.getEnd());
lastType = ep.getType();
} else if (ep.getEnd().after(p.getEnd())) {
// Extend the current period
p = new Period(p.getStart(), ep.getEnd());
}
// else it falls within the existing period
}
if (p != null) {
if ((fbc == null) || (lastType != fbc.getType())) {
fbc = new BwFreeBusyComponent();
fbc.setType(lastType);
fb.addFreeBusyPeriod(fbc);
}
fbc.addPeriod(p.getStart(), p.getEnd());
}
} catch (final Throwable t) {
if (debug) {
error(t);
}
throw new CalFacadeException(t);
}
return fb;
}
use of org.bedework.calfacade.BwFreeBusyComponent in project bw-calendar-engine by Bedework.
the class BwEventUtil method toEvent.
/**
* We are going to try to construct a BwEvent object from a VEvent. This
* may represent a new event or an update to a pre-existing event. In any
* case, the VEvent probably has insufficient information to completely
* reconstitute the event object so we'll get the uid first and retrieve
* the event if it exists.
*
* <p>To put it another way we're doing a diff then update.
*
* <p>If it doesn't exist, we'll first fill in the appropriate fields,
* (non-public, creator, created etc) then for both cases update the
* remaining fields from the VEvent.
*
* <p>Recurring events present some challenges. If there is no recurrence
* id the vevent represents the master entity which defines the recurrence
* rules. If a recurrence id is present then the vevent represents a
* recurrence instance override and we should not attempt to retrieve the
* actual object but the referenced instance.
*
* <p>Also, note that we sorted the components first so we get the master
* before any instances.
*
* <p>If DTSTART, RRULE, EXRULE have changed (also RDATE, EXDATE?) then any
* existing overrides are unusable. We should delete all overrides and replace
* with new ones.
*
* <p>For an update we have to keep track of which fields were present in
* the vevent and set all absent fields to null in the BwEvent.
*
* @param cb IcalCallback object
* @param cal Needed so we can retrieve the event.
* @param ical Icalendar we are converting. We check its events for
* overrides.
* @param val VEvent object
* @param diff True if we should assume we are updating existing events.
* @param mergeAttendees True if we should only update our own attendee.
* @return EventInfo object representing new entry or updated entry
* @throws CalFacadeException
*/
public static EventInfo toEvent(final IcalCallback cb, final BwCalendar cal, final Icalendar ical, final Component val, final boolean diff, final boolean mergeAttendees) throws CalFacadeException {
if (val == null) {
return null;
}
String currentPrincipal = null;
final BwPrincipal principal = cb.getPrincipal();
if (principal != null) {
currentPrincipal = principal.getPrincipalRef();
}
final boolean debug = getLog().isDebugEnabled();
@SuppressWarnings("unchecked") final Holder<Boolean> hasXparams = new Holder<Boolean>(Boolean.FALSE);
final int methodType = ical.getMethodType();
String attUri = null;
if (mergeAttendees) {
// We'll need this later.
attUri = cb.getCaladdr(cb.getPrincipal().getPrincipalRef());
}
final String colPath;
if (cal == null) {
colPath = null;
} else {
colPath = cal.getPath();
}
try {
final PropertyList pl = val.getProperties();
boolean vpoll = false;
if (pl == null) {
// Empty component
return null;
}
final int entityType;
if (val instanceof VEvent) {
entityType = IcalDefs.entityTypeEvent;
} else if (val instanceof VToDo) {
entityType = IcalDefs.entityTypeTodo;
} else if (val instanceof VJournal) {
entityType = IcalDefs.entityTypeJournal;
} else if (val instanceof VFreeBusy) {
entityType = IcalDefs.entityTypeFreeAndBusy;
} else if (val instanceof VAvailability) {
entityType = IcalDefs.entityTypeVavailability;
} else if (val instanceof Available) {
entityType = IcalDefs.entityTypeAvailable;
} else if (val instanceof VPoll) {
entityType = IcalDefs.entityTypeVpoll;
vpoll = true;
} else {
throw new CalFacadeException("org.bedework.invalid.component.type", val.getName());
}
Property prop;
// Get the guid from the component
String guid = null;
prop = pl.getProperty(Property.UID);
if (prop != null) {
testXparams(prop, hasXparams);
guid = prop.getValue();
}
if (guid == null) {
/* XXX A guid is required - but are there devices out there without a
* guid - and if so how do we handle it?
*/
throw new CalFacadeException(CalFacadeException.noGuid);
}
/* See if we have a recurrence id */
BwDateTime ridObj = null;
String rid = null;
prop = pl.getProperty(Property.RECURRENCE_ID);
if (prop != null) {
testXparams(prop, hasXparams);
ridObj = BwDateTime.makeBwDateTime((DateProperty) prop);
if (ridObj.getRange() != null) {
/* XXX What do I do with it? */
warn("TRANS-TO_EVENT: Got a recurrence id range");
}
rid = ridObj.getDate();
}
EventInfo masterEI = null;
EventInfo evinfo = null;
BwEvent ev = null;
/* If we have a recurrence id see if we already have the master (we should
* get a master + all its overrides).
*
* If so find the override and use the annnotation or if no override,
* make one.
*
* If no override retrieve the event, add it to our table and then locate the
* annotation.
*
* If there is no annotation, create one.
*
* It's possible we have been sent 'detached' instances of a recurring
* event. This may happen if we are invited to one or more instances of a
* meeting. In this case we try to retrieve the master and if it doesn't
* exist we manufacture one. We consider such an instance an update to
* that instance only and leave the others alone.
*/
/* We need this in a couple of places */
final DtStart dtStart = (DtStart) pl.getProperty(Property.DTSTART);
/* If this is a recurrence instance see if we can find the master
*/
if (rid != null) {
// See if we have a new master event. If so create a proxy to this event.
masterEI = findMaster(guid, ical.getComponents());
if (masterEI != null) {
evinfo = masterEI.findOverride(rid);
}
}
if (diff && (evinfo == null) && (cal != null) && (cal.getCalType() != BwCalendar.calTypeInbox) && (cal.getCalType() != BwCalendar.calTypePendingInbox) && (cal.getCalType() != BwCalendar.calTypeOutbox)) {
if (debug) {
debugMsg("TRANS-TO_EVENT: try to fetch event with guid=" + guid);
}
final Collection<EventInfo> eis = cb.getEvent(colPath, guid);
if (Util.isEmpty(eis)) {
// do nothing
} else if (eis.size() > 1) {
// DORECUR - wrong again
throw new CalFacadeException("More than one event returned for guid.");
} else {
evinfo = eis.iterator().next();
}
if (debug) {
if (evinfo != null) {
debugMsg("TRANS-TO_EVENT: fetched event with guid");
} else {
debugMsg("TRANS-TO_EVENT: did not find event with guid");
}
}
if (evinfo != null) {
if (rid != null) {
// We just retrieved it's master
masterEI = evinfo;
masterEI.setInstanceOnly(true);
evinfo = masterEI.findOverride(rid);
ical.addComponent(masterEI);
} else if (methodType == ScheduleMethods.methodTypeCancel) {
// This should never have an rid for cancel of entire event.
evinfo.setInstanceOnly(evinfo.getEvent().getSuppressed());
} else {
// Presumably sent an update for the entire event. No longer suppressed master
evinfo.getEvent().setSuppressed(false);
}
} else if (rid != null) {
/* Manufacture a master for the instance */
masterEI = makeNewEvent(cb, entityType, guid, colPath);
final BwEvent e = masterEI.getEvent();
// XXX This seems bogus
final DtStart mdtStart;
final String bogusDate = "19980118";
final String bogusTime = "T230000";
final Parameter par = dtStart.getParameter("VALUE");
final boolean isDateType = (par != null) && (par.equals(Value.DATE));
if (isDateType) {
mdtStart = new DtStart(new Date(bogusDate));
} else if (dtStart.isUtc()) {
mdtStart = new DtStart(bogusDate + bogusTime + "Z");
} else if (dtStart.getTimeZone() == null) {
mdtStart = new DtStart(bogusDate + bogusTime);
} else {
mdtStart = new DtStart(bogusDate + bogusTime + "Z", dtStart.getTimeZone());
}
setDates(cb.getPrincipal().getPrincipalRef(), masterEI, mdtStart, null, null);
e.setRecurring(true);
// e.addRdate(ridObj);
e.setSuppressed(true);
ical.addComponent(masterEI);
evinfo = masterEI.findOverride(rid);
masterEI.setInstanceOnly(rid != null);
}
}
if (evinfo == null) {
evinfo = makeNewEvent(cb, entityType, guid, colPath);
} else if (evinfo.getEvent().getEntityType() != entityType) {
throw new CalFacadeException("org.bedework.mismatched.entity.type", val.toString());
}
final ChangeTable chg = evinfo.getChangeset(cb.getPrincipal().getPrincipalRef());
if (rid != null) {
final String evrid = evinfo.getEvent().getRecurrenceId();
if ((evrid == null) || (!evrid.equals(rid))) {
warn("Mismatched rid ev=" + evrid + " expected " + rid);
// XXX spurious???
chg.changed(PropertyInfoIndex.RECURRENCE_ID, evrid, rid);
}
if (masterEI.getEvent().getSuppressed()) {
masterEI.getEvent().addRdate(ridObj);
}
}
ev = evinfo.getEvent();
ev.setScheduleMethod(methodType);
DtEnd dtEnd = null;
if (entityType == IcalDefs.entityTypeTodo) {
final Due due = (Due) pl.getProperty(Property.DUE);
if (due != null) {
dtEnd = new DtEnd(due.getParameters(), due.getValue());
}
} else {
dtEnd = (DtEnd) pl.getProperty(Property.DTEND);
}
final Duration duration = (Duration) pl.getProperty(Property.DURATION);
setDates(cb.getPrincipal().getPrincipalRef(), evinfo, dtStart, dtEnd, duration);
for (final Object aPl : pl) {
prop = (Property) aPl;
testXparams(prop, hasXparams);
// debugMsg("ical prop " + prop.getClass().getName());
String pval = prop.getValue();
if ((pval != null) && (pval.length() == 0)) {
pval = null;
}
final PropertyInfoIndex pi;
if (prop instanceof XProperty) {
pi = PropertyInfoIndex.XPROP;
} else {
pi = PropertyInfoIndex.fromName(prop.getName());
}
if (pi == null) {
debugMsg("Unknown property with name " + prop.getName() + " class " + prop.getClass() + " and value " + pval);
continue;
}
chg.present(pi);
switch(pi) {
case ACCEPT_RESPONSE:
/* ------------------- Accept Response -------------------- */
String sval = ((AcceptResponse) prop).getValue();
if (chg.changed(pi, ev.getPollAcceptResponse(), sval)) {
ev.setPollAcceptResponse(sval);
}
break;
case ATTACH:
/* ------------------- Attachment -------------------- */
chg.addValue(pi, getAttachment((Attach) prop));
break;
case ATTENDEE:
if (methodType == ScheduleMethods.methodTypePublish) {
if (cb.getStrictness() == IcalCallback.conformanceStrict) {
throw new CalFacadeException(CalFacadeException.attendeesInPublish);
}
if (cb.getStrictness() == IcalCallback.conformanceWarn) {
// warn("Had attendees for PUBLISH");
}
}
Attendee attPr = (Attendee) prop;
if (evinfo.getNewEvent() || !mergeAttendees) {
chg.addValue(pi, getAttendee(cb, attPr));
} else {
final String pUri = cb.getCaladdr(attPr.getValue());
if (pUri.equals(attUri)) {
/* Only update for our own attendee
* We're doing a PUT and this must be the attendee updating their
* partstat. We don't allow them to change other attendees
* whatever the PUT content says.
*/
chg.addValue(pi, getAttendee(cb, attPr));
} else {
// Use the value we currently have
boolean found = false;
for (final BwAttendee att : ev.getAttendees()) {
if (pUri.equals(att.getAttendeeUri())) {
chg.addValue(pi, att.clone());
found = true;
break;
}
}
if (!found) {
// An added attendee
final BwAttendee att = getAttendee(cb, attPr);
att.setPartstat(IcalDefs.partstatValNeedsAction);
chg.addValue(pi, att);
}
}
}
break;
case BUSYTYPE:
int ibt = BwEvent.fromBusyTypeString(pval);
if (chg.changed(pi, ev.getBusyType(), ibt)) {
ev.setBusyType(ibt);
}
break;
case CATEGORIES:
/* ------------------- Categories -------------------- */
Categories cats = (Categories) prop;
TextList cl = cats.getCategories();
String lang = getLang(cats);
if (cl != null) {
/* Got some categories */
Iterator cit = cl.iterator();
while (cit.hasNext()) {
String wd = (String) cit.next();
if (wd == null) {
continue;
}
BwString key = new BwString(lang, wd);
BwCategory cat = cb.findCategory(key);
if (cat == null) {
cat = BwCategory.makeCategory();
cat.setWord(key);
cb.addCategory(cat);
}
chg.addValue(pi, cat);
}
}
break;
case CLASS:
if (chg.changed(pi, ev.getClassification(), pval)) {
ev.setClassification(pval);
}
break;
case COMMENT:
/* ------------------- Comment -------------------- */
chg.addValue(pi, new BwString(null, pval));
break;
case COMPLETED:
if (chg.changed(pi, ev.getCompleted(), pval)) {
ev.setCompleted(pval);
}
break;
case CONTACT:
/* ------------------- Contact -------------------- */
String altrep = getAltRepPar(prop);
lang = getLang(prop);
String uid = getUidPar(prop);
BwString nm = new BwString(lang, pval);
BwContact contact = null;
if (uid != null) {
contact = cb.getContact(uid);
}
if (contact == null) {
contact = cb.findContact(nm);
}
if (contact == null) {
contact = BwContact.makeContact();
contact.setCn(nm);
contact.setLink(altrep);
cb.addContact(contact);
} else {
contact.setCn(nm);
contact.setLink(altrep);
}
chg.addValue(pi, contact);
break;
case CREATED:
if (chg.changed(pi, ev.getCreated(), pval)) {
ev.setCreated(pval);
}
break;
case DESCRIPTION:
if (chg.changed(pi, ev.getDescription(), pval)) {
ev.setDescription(pval);
}
break;
case DTEND:
break;
case DTSTAMP:
/* ------------------- DtStamp -------------------- */
ev.setDtstamp(pval);
break;
case DTSTART:
break;
case DURATION:
break;
case EXDATE:
/* ------------------- ExDate -------------------- */
chg.addValues(pi, makeDateTimes((DateListProperty) prop));
break;
case EXRULE:
/* ------------------- ExRule -------------------- */
chg.addValue(pi, pval);
break;
case FREEBUSY:
/* ------------------- freebusy -------------------- */
FreeBusy fbusy = (FreeBusy) prop;
PeriodList perpl = fbusy.getPeriods();
Parameter par = getParameter(fbusy, "FBTYPE");
int fbtype;
if (par == null) {
fbtype = BwFreeBusyComponent.typeBusy;
} else if (par.equals(FbType.BUSY)) {
fbtype = BwFreeBusyComponent.typeBusy;
} else if (par.equals(FbType.BUSY_TENTATIVE)) {
fbtype = BwFreeBusyComponent.typeBusyTentative;
} else if (par.equals(FbType.BUSY_UNAVAILABLE)) {
fbtype = BwFreeBusyComponent.typeBusyUnavailable;
} else if (par.equals(FbType.FREE)) {
fbtype = BwFreeBusyComponent.typeFree;
} else {
if (debug) {
debugMsg("Unsupported parameter " + par.getName());
}
throw new IcalMalformedException("parameter " + par.getName());
}
BwFreeBusyComponent fbc = new BwFreeBusyComponent();
fbc.setType(fbtype);
Iterator perit = perpl.iterator();
while (perit.hasNext()) {
Period per = (Period) perit.next();
fbc.addPeriod(per);
}
ev.addFreeBusyPeriod(fbc);
break;
case GEO:
/* ------------------- Geo -------------------- */
Geo g = (Geo) prop;
BwGeo geo = new BwGeo(g.getLatitude(), g.getLongitude());
if (chg.changed(pi, ev.getGeo(), geo)) {
ev.setGeo(geo);
}
break;
case LAST_MODIFIED:
if (chg.changed(pi, ev.getLastmod(), pval)) {
ev.setLastmod(pval);
}
break;
case LOCATION:
/* ------------------- Location -------------------- */
BwLocation loc = null;
// String uid = getUidPar(prop);
/* At the moment Mozilla lightning is broken and this leads to all
* sorts of problems.
if (uid != null) {
loc = cb.getLocation(uid);
}
*/
lang = getLang(prop);
BwString addr = null;
if (pval != null) {
if (loc == null) {
addr = new BwString(lang, pval);
loc = cb.findLocation(addr);
}
if (loc == null) {
loc = BwLocation.makeLocation();
loc.setAddress(addr);
cb.addLocation(loc);
}
}
BwLocation evloc = ev.getLocation();
if (chg.changed(pi, evloc, loc)) {
// CHGTBL - this only shows that it's a different location object
ev.setLocation(loc);
} else if ((loc != null) && (evloc != null)) {
// See if the value is changed
String evval = evloc.getAddress().getValue();
String inval = loc.getAddress().getValue();
if (!evval.equals(inval)) {
chg.changed(pi, evval, inval);
evloc.getAddress().setValue(inval);
}
}
break;
case ORGANIZER:
/* ------------------- Organizer -------------------- */
final BwOrganizer org = getOrganizer(cb, (Organizer) prop);
final BwOrganizer evorg = ev.getOrganizer();
final BwOrganizer evorgCopy;
if (evorg == null) {
evorgCopy = null;
} else {
evorgCopy = (BwOrganizer) evorg.clone();
}
if (chg.changed(pi, evorgCopy, org)) {
if (evorg == null) {
ev.setOrganizer(org);
} else {
evorg.update(org);
}
}
break;
case PERCENT_COMPLETE:
/* ------------------- PercentComplete -------------------- */
Integer ival = ((PercentComplete) prop).getPercentage();
if (chg.changed(pi, ev.getPercentComplete(), ival)) {
ev.setPercentComplete(ival);
}
break;
case POLL_MODE:
/* ------------------- Poll mode -------------------- */
sval = ((PollMode) prop).getValue();
if (chg.changed(pi, ev.getPollMode(), sval)) {
ev.setPollMode(sval);
}
break;
case POLL_PROPERTIES:
/* ------------------- Poll properties ---------------- */
sval = ((PollProperties) prop).getValue();
if (chg.changed(pi, ev.getPollProperties(), sval)) {
ev.setPollProperties(sval);
}
break;
case POLL_WINNER:
/* ------------------- Poll winner -------------------- */
ival = ((PollWinner) prop).getPollwinner();
if (chg.changed(pi, ev.getPollWinner(), ival)) {
ev.setPollWinner(ival);
}
break;
case PRIORITY:
/* ------------------- Priority -------------------- */
ival = ((Priority) prop).getLevel();
if (chg.changed(pi, ev.getPriority(), ival)) {
ev.setPriority(ival);
}
break;
case RDATE:
/* ------------------- RDate -------------------- */
chg.addValues(pi, makeDateTimes((DateListProperty) prop));
break;
case RECURRENCE_ID:
break;
case RELATED_TO:
/* ------------------- RelatedTo -------------------- */
final RelatedTo irelto = (RelatedTo) prop;
final BwRelatedTo relto = new BwRelatedTo();
final String parval = IcalUtil.getParameterVal(irelto, "RELTYPE");
if (parval != null) {
relto.setRelType(parval);
}
relto.setValue(irelto.getValue());
if (chg.changed(pi, ev.getRelatedTo(), relto)) {
ev.setRelatedTo(relto);
}
break;
case REQUEST_STATUS:
/* ------------------- RequestStatus -------------------- */
final BwRequestStatus rs = BwRequestStatus.fromRequestStatus((RequestStatus) prop);
chg.addValue(pi, rs);
break;
case RESOURCES:
/* ------------------- Resources -------------------- */
final TextList rl = ((Resources) prop).getResources();
if (rl != null) {
/* Got some resources */
lang = getLang(prop);
Iterator rit = rl.iterator();
while (rit.hasNext()) {
BwString rsrc = new BwString(lang, (String) rit.next());
chg.addValue(pi, rsrc);
}
}
break;
case RRULE:
/* ------------------- RRule -------------------- */
chg.addValue(pi, pval);
break;
case SEQUENCE:
/* ------------------- Sequence -------------------- */
int seq = ((Sequence) prop).getSequenceNo();
if (seq != ev.getSequence()) {
chg.changed(pi, ev.getSequence(), seq);
ev.setSequence(seq);
}
break;
case STATUS:
if (chg.changed(pi, ev.getStatus(), pval)) {
ev.setStatus(pval);
}
break;
case SUMMARY:
if (chg.changed(pi, ev.getSummary(), pval)) {
ev.setSummary(pval);
}
break;
case TRANSP:
if (chg.changed(pi, ev.getPeruserTransparency(cb.getPrincipal().getPrincipalRef()), pval)) {
BwXproperty pu = ev.setPeruserTransparency(cb.getPrincipal().getPrincipalRef(), pval);
if (pu != null) {
chg.addValue(PropertyInfoIndex.XPROP, pu);
}
}
break;
case UID:
break;
case URL:
if (chg.changed(pi, ev.getLink(), pval)) {
ev.setLink(pval);
}
break;
case XPROP:
/* ------------------------- x-property --------------------------- */
final String name = prop.getName();
if (name.equalsIgnoreCase(BwXproperty.bedeworkCost)) {
if (chg.changed(PropertyInfoIndex.COST, ev.getCost(), pval)) {
ev.setCost(pval);
}
break;
}
if (name.equalsIgnoreCase(BwXproperty.xBedeworkCategories)) {
if (checkCategory(cb, chg, ev, null, pval)) {
break;
}
}
if (name.equalsIgnoreCase(BwXproperty.xBedeworkLocation)) {
if (checkLocation(cb, chg, ev, prop)) {
break;
}
}
if (name.equalsIgnoreCase(BwXproperty.xBedeworkContact)) {
if (checkContact(cb, chg, ev, null, pval)) {
break;
}
}
/* See if this is an x-category that can be
converted to a real category
*/
final XProperty xp = (XProperty) prop;
chg.addValue(PropertyInfoIndex.XPROP, new BwXproperty(name, xp.getParameters().toString(), pval));
break;
default:
if (debug) {
debugMsg("Unsupported property with index " + pi + "; class " + prop.getClass() + " and value " + pval);
}
}
}
if (val instanceof VAvailability) {
processAvailable(cb, cal, ical, (VAvailability) val, evinfo);
} else if (!(val instanceof Available)) {
VAlarmUtil.processComponentAlarms(cb, val, ev, currentPrincipal, chg);
if (val instanceof VPoll) {
processVvoters((VPoll) val, evinfo, cb, chg, mergeAttendees);
processCandidates((VPoll) val, evinfo, chg);
}
}
/* Fix up timestamps. */
if (ev.getCreated() == null) {
if (ev.getLastmod() != null) {
ev.setCreated(ev.getLastmod());
chg.changed(PropertyInfoIndex.CREATED, null, ev.getCreated());
} else {
ev.updateDtstamp();
chg.changed(PropertyInfoIndex.CREATED, null, ev.getCreated());
chg.changed(PropertyInfoIndex.LAST_MODIFIED, null, ev.getLastmod());
}
}
if (ev.getLastmod() == null) {
// created cannot be null now
ev.setLastmod(ev.getCreated());
chg.changed(PropertyInfoIndex.LAST_MODIFIED, null, ev.getLastmod());
}
processTimezones(ev, ical, chg);
/* Remove any recipients and originator
*/
if (ev.getRecipients() != null) {
ev.getRecipients().clear();
}
ev.setOriginator(null);
if (hasXparams.value) {
/* Save a text copy of the entire event as an x-property */
Component valCopy = val.copy();
/* Remove potentially large values */
prop = valCopy.getProperty(Property.DESCRIPTION);
if (prop != null) {
prop.setValue(null);
}
prop = valCopy.getProperty(Property.ATTACH);
// Don't store the entire attachment - we just need the parameters.
if (prop != null) {
Value v = (Value) prop.getParameter(Parameter.VALUE);
if (v != null) {
prop.setValue(String.valueOf(prop.getValue().hashCode()));
}
}
chg.addValue(PropertyInfoIndex.XPROP, new BwXproperty(BwXproperty.bedeworkIcal, null, valCopy.toString()));
}
chg.processChanges(ev, true);
ev.setRecurring(new Boolean(ev.isRecurringEntity()));
if (debug) {
debugMsg(chg.toString());
debugMsg(ev.toString());
}
if (masterEI != null) {
// Just return null as this event is on its override list
return null;
}
return evinfo;
} catch (CalFacadeException cfe) {
if (debug) {
cfe.printStackTrace();
}
throw cfe;
} catch (Throwable t) {
if (debug) {
t.printStackTrace();
}
throw new CalFacadeException(t);
}
}
use of org.bedework.calfacade.BwFreeBusyComponent in project bw-calendar-engine by Bedework.
the class VFreeUtil method toVFreeBusy.
/**
* Make a VFreeBusy object from a BwFreeBusy.
*/
/**
* @param val
* @return VFreeBusy
* @throws CalFacadeException
*/
public static VFreeBusy toVFreeBusy(final BwEvent val) throws CalFacadeException {
try {
VFreeBusy vfb = new VFreeBusy(IcalUtil.makeDateTime(val.getDtstart()), IcalUtil.makeDateTime(val.getDtend()));
PropertyList pl = vfb.getProperties();
Property prop;
/* ------------------- Attendees -------------------- */
if (val.getNumAttendees() > 0) {
for (BwAttendee att : val.getAttendees()) {
pl.add(setAttendee(att));
}
}
if (val.getNumComments() > 0) {
for (BwString str : val.getComments()) {
// LANG
pl.add(new Comment(str.getValue()));
}
}
if (val.getDtstamp() != null) {
DtStamp dts = (DtStamp) pl.getProperty(Property.DTSTAMP);
if (dts == null) {
prop = new DtStamp(new DateTime(val.getDtstamp()));
// if (pars.includeDateTimeProperty) {
// prop.getParameters().add(Value.DATE_TIME);
// }
pl.add(prop);
} else {
dts.setDateTime(new DateTime(val.getDtstamp()));
}
}
/* ------------------- freebusy -------------------- */
Collection<BwFreeBusyComponent> times = val.getFreeBusyPeriods();
if (times != null) {
for (BwFreeBusyComponent fbc : times) {
FreeBusy fb = new FreeBusy();
int type = fbc.getType();
if (type == BwFreeBusyComponent.typeBusy) {
addParameter(fb, FbType.BUSY);
} else if (type == BwFreeBusyComponent.typeFree) {
addParameter(fb, FbType.FREE);
} else if (type == BwFreeBusyComponent.typeBusyUnavailable) {
addParameter(fb, FbType.BUSY_UNAVAILABLE);
} else if (type == BwFreeBusyComponent.typeBusyTentative) {
addParameter(fb, FbType.BUSY_TENTATIVE);
} else {
throw new CalFacadeException("Bad free-busy type " + type);
}
PeriodList pdl = fb.getPeriods();
for (Period p : fbc.getPeriods()) {
// XXX inverse.ca plugin cannot handle durations.
Period np = new Period(p.getStart(), p.getEnd());
pdl.add(np);
}
pl.add(fb);
}
}
/* ------------------- Organizer -------------------- */
BwOrganizer org = val.getOrganizer();
if (org != null) {
pl.add(setOrganizer(org));
}
if (val.getUid() != null) {
pl.add(new Uid(val.getUid()));
}
return vfb;
} catch (CalFacadeException cfe) {
throw cfe;
} catch (Throwable t) {
throw new CalFacadeException(t);
}
}
use of org.bedework.calfacade.BwFreeBusyComponent in project bw-calendar-engine by Bedework.
the class FreeAndBusyHandler method granulateFreeBusy.
/* ====================================================================
* Private methods
* ==================================================================== */
/*
private void addFbcal(Collection<BwCalendar> cals,
BwCalendar cal) throws CalFacadeException {
if (cal.getCalType() == BwCalendar.calTypeCollection) {
// Leaf
cals.add(cal);
return;
}
Collection<BwCalendar> chs = getSvc().getCalendarsHandler().getChildren(cal);
for (BwCalendar ch: chs) {
addFbcal(cals, ch);
}
}
*/
private void granulateFreeBusy(final FbGranulatedResponse fbresp, final BwEvent fb, final BwDateTime start, final BwDateTime end, final BwDuration granularity) throws CalFacadeException {
DateTime startDt;
DateTime endDt;
try {
startDt = new DateTime(start.getDate());
endDt = new DateTime(end.getDate());
} catch (ParseException pe) {
throw new CalFacadeException(pe);
}
if (fb.getDtstart().after(start)) {
// XXX Should warn - or fill in with tentative?
// warn("Response start after requested start");
}
if (fb.getDtend().before(end)) {
// XXX Should warn - or fill in with tentative?
// warn("Response end before requested end");
}
fbresp.setStart(start);
fbresp.setEnd(end);
Collection<EventPeriod> periods = new ArrayList<EventPeriod>();
if (fb.getFreeBusyPeriods() != null) {
for (BwFreeBusyComponent fbcomp : fb.getFreeBusyPeriods()) {
for (Period p : fbcomp.getPeriods()) {
DateTime pstart = p.getStart();
DateTime pend = p.getEnd();
if (!pend.isUtc()) {
pend.setUtc(true);
}
/* Adjust for servers sending times outside requested range */
if (pend.after(endDt)) {
pend = endDt;
}
if (pstart.before(startDt)) {
pstart = startDt;
}
if (!pend.after(pstart)) {
continue;
}
periods.add(new EventPeriod(pstart, pend, fbcomp.getType()));
}
}
}
GetPeriodsPars gpp = new GetPeriodsPars();
gpp.periods = periods;
gpp.startDt = start;
gpp.dur = granularity;
BwDateTime bwend = end;
Collection<EventPeriod> respeps = new ArrayList<EventPeriod>();
fbresp.eps = respeps;
// XXX do this better
int limit = 10000;
/* endDt is null first time through, then represents end of last
* segment.
*/
while ((gpp.endDt == null) || (gpp.endDt.before(bwend))) {
// }
if (limit < 0) {
throw new CalFacadeException("org.bedework.svci.limit.exceeded");
}
limit--;
Collection<?> periodEvents = Granulator.getPeriodsEvents(gpp);
/* Some events fall in the period. Add an entry.
* We eliminated cancelled events earler. Now we should set the
* free/busy type based on the events status.
*/
DateTime psdt;
DateTime pedt;
try {
psdt = new DateTime(gpp.startDt.getDtval());
pedt = new DateTime(gpp.endDt.getDtval());
} catch (ParseException pe) {
throw new CalFacadeException(pe);
}
psdt.setUtc(true);
pedt.setUtc(true);
EventPeriod ep = new EventPeriod(psdt, pedt, 0);
setFreeBusyType(ep, periodEvents);
respeps.add(ep);
}
}
Aggregations