[Bedework-commit] calendarapi r308 - in trunk: calCore/resources/hbms calFacade/src/org/bedework/calfacade/exc calFacade/src/org/bedework/calfacade/svc/prefs calsvc/src/org/bedework/calsvc calsvci/src/org/bedework/calsvci

svnadmin at bedework.org svnadmin at bedework.org
Wed Jun 13 00:03:06 EDT 2007


Author: douglm
Date: 2007-06-13 00:03:01 -0400 (Wed, 13 Jun 2007)
New Revision: 308

Modified:
   trunk/calCore/resources/hbms/Preferences.hbm.xml
   trunk/calFacade/src/org/bedework/calfacade/exc/CalFacadeException.java
   trunk/calFacade/src/org/bedework/calfacade/svc/prefs/BwPreferences.java
   trunk/calsvc/src/org/bedework/calsvc/AutoScheduler.java
   trunk/calsvc/src/org/bedework/calsvc/CalSvc.java
   trunk/calsvc/src/org/bedework/calsvc/Scheduling.java
   trunk/calsvci/src/org/bedework/calsvci/SchedulingI.java
Log:
Add preferences associated with auto responding to scheduling requests.

Fix up some of the auto processing for resources.

Make a start on handling system specific properties in the CalDAV server

Modified: trunk/calCore/resources/hbms/Preferences.hbm.xml
===================================================================
--- trunk/calCore/resources/hbms/Preferences.hbm.xml	2007-06-12 03:51:39 UTC (rev 307)
+++ trunk/calCore/resources/hbms/Preferences.hbm.xml	2007-06-13 04:03:01 UTC (rev 308)
@@ -51,6 +51,7 @@
     <property name="preferredView" column="preferred_view" type="string" />
     <property name="preferredViewPeriod" column="preferred_view_period"
               type="string" />
+    <property name="pageSize" column="bw_page_size" type="integer" />
     <property name="workDays" column="workdays" type="string" />
     <property name="workdayStart" column="workday_start" type="integer" />
     <property name="workdayEnd" column="workday_end" type="integer" />
@@ -61,6 +62,18 @@
     <property name="hour24" column="bw_hour24" type="true_false"
               not-null="true" />
 
+    <property name="scheduleAutoRespond" column="bw_sched_auto_respond" type="true_false"
+              not-null="true" />
+
+    <property name="scheduleAutoCancelAction" column="scheduleAutoCancelAction"
+              type="integer" />
+
+    <property name="scheduleDoubleBook" column="bw_sched_double_book" type="true_false"
+              not-null="true" />
+
+    <property name="scheduleAutoProcessResponses" column="bw_sched_auto_process_responses"
+              type="integer" />
+
     <set name="properties" table="bw_user_properties"
          cascade="all-delete-orphan" >
       <cache usage="read-write"/>

Modified: trunk/calFacade/src/org/bedework/calfacade/exc/CalFacadeException.java
===================================================================
--- trunk/calFacade/src/org/bedework/calfacade/exc/CalFacadeException.java	2007-06-12 03:51:39 UTC (rev 307)
+++ trunk/calFacade/src/org/bedework/calfacade/exc/CalFacadeException.java	2007-06-13 04:03:01 UTC (rev 308)
@@ -230,6 +230,10 @@
   public static final String schedulingBadResponse =
       "org.bedework.error.scheduling.badresponse";
 
+  /** Invalid scheduling action. */
+  public static final String schedulingBadAction =
+      "org.bedework.error.scheduling.badaction";
+
   /** System error: Invalid freebusy granulator date limit - Must be DATETIME. */
   public static final String schedulingBadGranulatorDt =
       "org.bedework.error.scheduling.badgranulatordt";

Modified: trunk/calFacade/src/org/bedework/calfacade/svc/prefs/BwPreferences.java
===================================================================
--- trunk/calFacade/src/org/bedework/calfacade/svc/prefs/BwPreferences.java	2007-06-12 03:51:39 UTC (rev 307)
+++ trunk/calFacade/src/org/bedework/calfacade/svc/prefs/BwPreferences.java	2007-06-13 04:03:01 UTC (rev 308)
@@ -40,7 +40,7 @@
 
 /** Account preferences for Bedework. These affect the user view of calendars.
  *
- *   @author Mike Douglass douglm at rpi.edu
+ *  @author Mike Douglass douglm at rpi.edu
  *  @version 1.0
  */
 public class BwPreferences extends BwOwnedDbentity {
@@ -116,6 +116,32 @@
 
   private boolean hour24;
 
+  private boolean scheduleAutoRespond;
+
+  /** Do not auto process cancels */
+  public static int scheduleAutoCancelNoAction = 0;
+
+  /** Set status to cancelled */
+  public static int scheduleAutoCancelSetStatus = 1;
+
+  /** Delete the event */
+  public static int scheduleAutoCancelDelete = 2;
+
+  private int scheduleAutoCancelAction;
+
+  private boolean scheduleDoubleBook;
+
+  /** Do not auto process responses */
+  public static int scheduleAutoProcessResponsesNoAction = 0;
+
+  /** Only auto process accept responses */
+  public static int scheduleAutoProcessResponsesAccepts = 1;
+
+  /** Auto process all responses */
+  public static int scheduleAutoProcessResponsesAll = 2;
+
+  private int scheduleAutoProcessResponses;
+
   private Collection<BwProperty> properties;
 
   /** Constructor
@@ -348,6 +374,62 @@
   /**
    * @param val
    */
+  public void setScheduleAutoRespond(boolean val) {
+    scheduleAutoRespond = val;
+  }
+
+  /**
+   * @return bool
+   */
+  public boolean getScheduleAutoRespond() {
+    return scheduleAutoRespond;
+  }
+
+  /**
+   * @param val
+   */
+  public void setScheduleAutoCancelAction(int val) {
+    scheduleAutoCancelAction = val;
+  }
+
+  /**
+   * @return int
+   */
+  public int getScheduleAutoCancelAction() {
+    return scheduleAutoCancelAction;
+  }
+
+  /**
+   * @param val
+   */
+  public void setScheduleDoubleBook(boolean val) {
+    scheduleDoubleBook = val;
+  }
+
+  /**
+   * @return bool
+   */
+  public boolean getScheduleDoubleBook() {
+    return scheduleDoubleBook;
+  }
+
+  /**
+   * @param val
+   */
+  public void setScheduleAutoProcessResponses(int val) {
+    scheduleAutoProcessResponses = val;
+  }
+
+  /**
+   * @return int
+   */
+  public int getScheduleAutoProcessResponses() {
+    return scheduleAutoProcessResponses;
+  }
+
+  /**
+   * @param val
+   */
   public void setProperties(Collection<BwProperty> val) {
     properties = val;
   }
@@ -359,6 +441,78 @@
     return properties;
   }
 
+  /**
+   * @return int
+   */
+  public int getNumProperties() {
+    Collection c = getProperties();
+    if (c == null) {
+      return 0;
+    }
+
+    return c.size();
+  }
+
+  /**
+   * @param val
+   */
+  public void addAttendee(BwProperty val) {
+    Collection<BwProperty> c = getProperties();
+    if (c == null) {
+      c = new TreeSet<BwProperty>();
+      setProperties(c);
+    }
+
+    if (!c.contains(val)) {
+      c.add(val);
+    }
+  }
+
+  /**
+   * @param val
+   * @return boolean
+   */
+  public boolean removeProperty(BwProperty val) {
+    Collection c = getProperties();
+    if (c == null) {
+      return false;
+    }
+
+    return c.remove(val);
+  }
+
+  /**
+   * @return BwProperty
+   */
+  public Collection<BwProperty> copyProperties() {
+    if (getNumProperties() == 0) {
+      return null;
+    }
+    TreeSet<BwProperty> ts = new TreeSet<BwProperty>();
+
+    for (BwProperty p: getProperties()) {
+      ts.add(p);
+    }
+
+    return ts;
+  }
+
+  /**
+   * @return BwProperty
+   */
+  public Collection<BwProperty> cloneProperties() {
+    if (getNumProperties() == 0) {
+      return null;
+    }
+    TreeSet<BwProperty> ts = new TreeSet<BwProperty>();
+
+    for (BwProperty p: getProperties()) {
+      ts.add((BwProperty)p.clone());
+    }
+
+    return ts;
+  }
+
   /* ====================================================================
    *                   Convenience methods
    * ==================================================================== */

Modified: trunk/calsvc/src/org/bedework/calsvc/AutoScheduler.java
===================================================================
--- trunk/calsvc/src/org/bedework/calsvc/AutoScheduler.java	2007-06-12 03:51:39 UTC (rev 307)
+++ trunk/calsvc/src/org/bedework/calsvc/AutoScheduler.java	2007-06-13 04:03:01 UTC (rev 308)
@@ -25,22 +25,30 @@
 */
 package org.bedework.calsvc;
 
+import org.bedework.calfacade.BwAttendee;
 import org.bedework.calfacade.BwCalendar;
 import org.bedework.calfacade.BwEvent;
+import org.bedework.calfacade.BwFreeBusy;
+import org.bedework.calfacade.BwFreeBusyComponent;
 import org.bedework.calfacade.RecurringRetrievalMode;
 import org.bedework.calfacade.ScheduleResult;
 import org.bedework.calfacade.RecurringRetrievalMode.Rmode;
 import org.bedework.calfacade.exc.CalFacadeException;
 import org.bedework.calfacade.svc.EventInfo;
+import org.bedework.calfacade.svc.prefs.BwPreferences;
 import org.bedework.calsvci.CalSvcFactoryDefault;
 import org.bedework.calsvci.CalSvcI;
 import org.bedework.calsvci.CalSvcIPars;
 import org.bedework.calsvci.SchedulingI;
 import org.bedework.icalendar.Icalendar;
 
+import net.fortuna.ical4j.model.Period;
+import net.fortuna.ical4j.model.parameter.PartStat;
+
 import org.apache.log4j.Logger;
 
 import java.io.Serializable;
+import java.util.Collection;
 import java.util.LinkedList;
 import java.util.Queue;
 
@@ -132,6 +140,13 @@
         return;
       }
 
+      BwPreferences prefs = svci.getUserPrefs();
+
+      boolean scheduleAutoRespond = prefs.getScheduleAutoRespond();
+      int scheduleAutoCancelAction = prefs.getScheduleAutoCancelAction();
+      boolean scheduleDoubleBook = prefs.getScheduleDoubleBook();
+      int scheduleAutoProcessResponses = prefs.getScheduleAutoProcessResponses();
+
       SchedulingI sched =  svci.getScheduler();
       ScheduleResult sr = null;
       BwEvent ev = ei.getEvent();
@@ -143,18 +158,46 @@
       }
 
       if (method == Icalendar.methodTypeCancel) {
-        svci.deleteEvent(ev, true);
-        return;
+        if (scheduleAutoRespond &&
+            (scheduleAutoCancelAction != BwPreferences.scheduleAutoCancelNoAction)) {
+          sched.processCancel(ev, scheduleAutoCancelAction, null);
+        }
       }
 
       if (ev.getScheduleMethod() == Icalendar.methodTypeRequest) {
         if (debug) {
           trace("send response event " + ase.eventName);
         }
+
+        String partStat = PartStat.ACCEPTED.getValue();
+
+        if (!scheduleDoubleBook) {
+          // See if there are any events booked during this time.
+          BwFreeBusy fb = svci.getFreeBusy(null, null,
+                                           svci.getUser(),
+                                           ev.getDtstart(), ev.getDtend(),
+                                           null, false);
+
+          Collection<BwFreeBusyComponent> times = fb.getTimes();
+
+          if ((times != null) && !times.isEmpty()) {
+            for (BwFreeBusyComponent fbc: times) {
+              if (fbc.getType() != BwFreeBusyComponent.typeFree) {
+                Collection<Period> periods = fbc.getPeriods();
+
+                if ((periods != null) && !periods.isEmpty()) {
+                  partStat = PartStat.DECLINED.getValue();
+                  break;
+                }
+              }
+            }
+          }
+        }
+
         sr = sched.attendeeRespond(ev,
                                    null,         // delegate
                                    "REPLY",      // method
-                                   "ACCEPTED",   // partstat
+                                   partStat,
                                    // Use preferred calendar
                                    svci.getPreferredCalendar(), // evCal
                                    null,         // comment
@@ -162,7 +205,25 @@
       }
 
       if (ev.getScheduleMethod() == Icalendar.methodTypeReply) {
-        sr = sched.processResponse(ev, null);
+        /* Reply back from attendee - update our copy
+         */
+        if (scheduleAutoProcessResponses != BwPreferences.scheduleAutoProcessResponsesNoAction) {
+          boolean process = true;
+
+          if (scheduleAutoProcessResponses == BwPreferences.scheduleAutoProcessResponsesAccepts) {
+            /* Should be exactly one attendee */
+            Collection<BwAttendee> atts = ev.getAttendees();
+            if ((atts != null) && (atts.size() == 1)) {
+              BwAttendee att = atts.iterator().next();
+
+              process = att.getPartstat() == PartStat.ACCEPTED.getValue();
+            }
+          }
+
+          if (process) {
+            sr = sched.processResponse(ev, null);
+          }
+        }
       }
 
       if (debug) {

Modified: trunk/calsvc/src/org/bedework/calsvc/CalSvc.java
===================================================================
--- trunk/calsvc/src/org/bedework/calsvc/CalSvc.java	2007-06-12 03:51:39 UTC (rev 307)
+++ trunk/calsvc/src/org/bedework/calsvc/CalSvc.java	2007-06-13 04:03:01 UTC (rev 308)
@@ -132,6 +132,7 @@
 import edu.rpi.cct.uwcal.resources.Resources;
 import edu.rpi.cmt.access.Ace;
 import edu.rpi.cmt.access.AceWho;
+import edu.rpi.cmt.access.PrincipalInfo;
 import edu.rpi.cmt.access.PrivilegeDefs;
 import edu.rpi.cmt.access.Acl.CurrentAccess;
 
@@ -3054,6 +3055,12 @@
     prefs.setPreferredViewPeriod("week");
     prefs.setHour24(getSyspars().getDefaultUserHour24());
 
+    PrincipalInfo pi = getDirectories().getPrincipalInfo(user.getAccount());
+    if (pi != null) {
+      prefs.setScheduleAutoRespond(pi.whoType == Ace.whoTypeResource);
+    }
+
+    prefs.setScheduleAutoProcessResponses(BwPreferences.scheduleAutoProcessResponsesAccepts);
     dbi.updatePreferences(prefs);
   }
 

Modified: trunk/calsvc/src/org/bedework/calsvc/Scheduling.java
===================================================================
--- trunk/calsvc/src/org/bedework/calsvc/Scheduling.java	2007-06-12 03:51:39 UTC (rev 307)
+++ trunk/calsvc/src/org/bedework/calsvc/Scheduling.java	2007-06-13 04:03:01 UTC (rev 308)
@@ -45,6 +45,7 @@
 import org.bedework.calfacade.exc.CalFacadeException;
 import org.bedework.calfacade.svc.BwSubscription;
 import org.bedework.calfacade.svc.EventInfo;
+import org.bedework.calfacade.svc.prefs.BwPreferences;
 import org.bedework.calfacade.util.CalFacadeUtil;
 import org.bedework.calfacade.util.Granulator;
 import org.bedework.calfacade.util.Granulator.EventPeriod;
@@ -54,8 +55,6 @@
 import org.bedework.icalendar.IcalTranslator;
 import org.bedework.icalendar.Icalendar;
 
-import edu.rpi.cmt.access.Ace;
-import edu.rpi.cmt.access.PrincipalInfo;
 import edu.rpi.cmt.access.PrivilegeDefs;
 
 import net.fortuna.ical4j.model.Calendar;
@@ -357,13 +356,13 @@
     }
 
     /* Should be exactly one attendee */
-    Collection atts = ev.getAttendees();
+    Collection<BwAttendee> atts = ev.getAttendees();
     if ((atts == null) || (atts.size() != 1)) {
       sr.errorCode = CalFacadeException.schedulingExpectOneAttendee;
       return sr;
     }
 
-    BwAttendee att = (BwAttendee)atts.iterator().next();
+    BwAttendee att = atts.iterator().next();
     BwCalendar inbox = ev.getCalendar();
 
     if (inbox.getCalType() != BwCalendar.calTypeInbox) {
@@ -399,6 +398,7 @@
       return forwardError;
     }
                                   */
+
     /* Look for any events with the same guid and for the time being update any
      * in ordinary calendar collections. This is probably wrong.
      */
@@ -441,6 +441,67 @@
     return sr;
   }
 
+  public ScheduleResult processCancel(BwEvent ev,
+                                     int action,
+                                     BwCalendar eventCal) throws CalFacadeException {
+    ScheduleResult sr = new ScheduleResult();
+    BwCalendar inbox = ev.getCalendar();
+
+    if ((ev == null) || (ev.getScheduleMethod() != Icalendar.methodTypeCancel)) {
+      sr.errorCode = CalFacadeException.schedulingBadMethod;
+      return sr;
+    }
+
+    if (inbox.getCalType() != BwCalendar.calTypeInbox) {
+      sr.errorCode = CalFacadeException.schedulingBadSourceCalendar;
+      return sr;
+    }
+
+    if (ev.getOriginator() == null) {
+      sr.errorCode = CalFacadeException.schedulingNoOriginator;
+      return sr;
+    }
+
+    /* Look for any events with the same guid and for the time being update any
+     * in ordinary calendar collections. This is probably wrong.
+     */
+    RecurringRetrievalMode rrm =
+      new RecurringRetrievalMode(Rmode.overrides);
+
+    Collection<EventInfo> evs = svci.getEvent(null, eventCal, ev.getUid(),
+                                              ev.getRecurrenceId(), rrm);
+
+    if (evs.size() == 0) {
+      sr.errorCode = CalFacadeException.schedulingUnknownEvent;
+
+      /* I guess we delete event from inbox */
+      svci.deleteEvent(ev, true);
+      return sr;
+    }
+
+    for (EventInfo ei: evs) {
+      BwEvent calEv = ei.getEvent();
+
+      if (!ev.equals(calEv) && // Not the inbox event
+         (calEv.getCalendar().getCalType() == BwCalendar.calTypeCollection)) {
+        if (action == BwPreferences.scheduleAutoCancelDelete) {
+          svci.deleteEvent(calEv, true);
+        } else if (action == BwPreferences.scheduleAutoCancelSetStatus) {
+          calEv.setStatus(BwEvent.statusCancelled);
+          svci.updateEvent(calEv, null, null);
+        } else {
+          sr.errorCode = CalFacadeException.schedulingBadAction;
+          return sr;
+        }
+      }
+    }
+
+    /* Now delete processed event from inbox */
+    svci.deleteEvent(ev, true);
+
+    return sr;
+  }
+
   /* (non-Javadoc)
    * @see org.bedework.calsvci.SchedulingI#scheduleResponse(org.bedework.calfacade.BwEvent)
    */
@@ -819,11 +880,6 @@
                                         null, false);
           } else if (!ui.account.equals(svci.getUser().getAccount())) {
             addToInbox(ui, event);
-            if (!ui.autoProcess && (ui.account != null) &&
-                (event.getScheduleMethod() == Icalendar.methodTypeReply)) {
-              // For the moment always handle replies automatically
-              ui.autoProcess = true;
-            }
           }
 
           ui.status = ScheduleRecipientResult.scheduleOk;
@@ -840,10 +896,9 @@
         trace("added recipient " + ui.recipient + " status = " + ui.status);
       }
 
-      if (!freeBusyRequest && ui.autoProcess) {
-        if (autoSchedule != null) {
-          autoSchedule.add(ui.account, ui.inboxEvent.getName(), null);
-        }
+      if (!freeBusyRequest && (autoSchedule != null) &&
+          (ui.inboxEvent != null)) {
+        autoSchedule.add(ui.account, ui.inboxEvent.getName(), null);
       }
     }
 
@@ -857,8 +912,6 @@
 
     /* Event we added to the inbox */
     BwEvent inboxEvent;
-
-    boolean autoProcess;
   }
 
   /* Return with deferred for external user.
@@ -886,10 +939,6 @@
       }
 
       ui.user = svci.findUser(ui.account, true);
-      PrincipalInfo pi = svci.getDirectories().getPrincipalInfo(ui.account);
-      if (pi != null) {
-        ui.autoProcess = pi.whoType == Ace.whoTypeResource;
-      }
 
       ui.inbox = svci.getSpecialCalendar(ui.user,
                                          BwCalendar.calTypeInbox,

Modified: trunk/calsvci/src/org/bedework/calsvci/SchedulingI.java
===================================================================
--- trunk/calsvci/src/org/bedework/calsvci/SchedulingI.java	2007-06-12 03:51:39 UTC (rev 307)
+++ trunk/calsvci/src/org/bedework/calsvci/SchedulingI.java	2007-06-13 04:03:01 UTC (rev 308)
@@ -91,6 +91,22 @@
   public ScheduleResult processResponse(BwEvent ev,
                                         BwCalendar eventCal) throws CalFacadeException;
 
+  /** The organizer has cancelled the meeting - or taken us (the attendee) off
+   * the list.
+   *
+   * <p>We will look for the event in the users calendar(s) and either remove it
+   * or set the status to cancelled.
+   *
+   * @param ev            BwEvent object with method=CANCEL
+   * @param action        Value from BwPreferences
+   * @param eventCal - if non-null where we have a copy of the meeting
+   * @return ScheduleResult
+   * @throws CalFacadeException
+   */
+  public ScheduleResult processCancel(BwEvent ev,
+                                      int action,
+                                      BwCalendar eventCal) throws CalFacadeException;
+
   /** Respond to a scheduling request. The event object must have the organizer
    * and a single attendee and possibly recipient set according to itip + caldav.
    *



More information about the Bedework-commit mailing list