Formatting outbound messages
Any given notification needs to be converted into one or more forms for sending on to the recipient. Notifications are XML messages with an outer <notification> element. This element has a child element which identifies the type of message. It may be a sharing invitation or notification of a resource change. This type element is exposed as a DAV property on the notification resource so that we can select the notifications of interest. To format these notifications we are going to use FreeMarker which uses templates which are filled in with properties we will supply as a table.
Below is an example of a notification.
<?xml version="1.0" encoding="UTF-8" ?> <CSS:notification xmlns:C="urn:ietf:params:xml:ns:caldav" xmlns:BSS="http://bedework.org/ns/" xmlns:BW="http://bedeworkcalserver.org/ns/" xmlns:CSS="http://calendarserver.org/ns/" xmlns:DAV="DAV:"> <CSS:dtstamp> </CSS:dtstamp> <BSS:eventregRegistered> <CSS:uid>0c4aa4c2-b10d-41ec-ae0e-4e544460111c</CSS:uid> <DAV:href>/ucaldav/public/cals/MainCal/CAL-2c9378d1-502dc79a-0150-2dc91578-00000001.ics</DAV:href> <DAV:principal-URL> <DAV:href>/ucaldav/principals/user/douglm</DAV:href> </DAV:principal-URL> <BSS:comment> </BSS:comment> <BSS:eventregNumTicketsRequested>1</BSS:eventregNumTicketsRequested> <BSS:eventregNumTickets>1</BSS:eventregNumTickets> </BSS:eventregRegistered> </CSS:notification>
We need to select an appropriate template. FreeMarker has the concept of an abstract path which it will use to select the actual template based on locale (and other characteristics). We will use configuration and mappings to create the abstract path from the following elements:
- Base path: provided in the configuration for the engine - all templates are under this path
- Outbound type: "email", "sms" etc.
- Notification type: e.g. AS/invite-notification (see note below)
The resulting path is then searched by FreeMarker for templates (files ending with "ftl").
Notification type: these path elements are derived from the namespace and name of the element which defines the type of the notification. The element in its full form would look something like "http://calendarserver.org/ns/:invite-notification". Clearly the namespace is not suitable in its raw form for use as a path element. We could encode it so that it becomes a valid path element. Instead we will map them in much the same way as XML namespace declarations do, that is we will use a "standard" abbreviation - standard for bedework that is. The xml util class NsContext provides the mappings. Note that we cannot easily change those mappings as this will invalidate the paths (though we could rename the directory to match). This should not be an issue as the abbreviations have no meaning outside the context in which they are used. From time to time we may need to add mappings as new notification namespaces are defined. If a new notification type is defined we only need to add a corresponding template.
Note: We may want to add further elements to the path. At the moment it's not clear what the content type is - if we want to generate html and text we need 2 templates and we need to choose between them.
Namespace abbreviations
As explained above these turn up as path elements for selecting the template and the also tun up as prefixes to the names of elements in the templates.
They are as follows:
"D", "DAV"
"AS", AppleServerTags.appleCaldavNamespace
"BW", BedeworkServerTags.bedeworkSystemNamespace
"BWC", BedeworkServerTags.bedeworkCaldavNamespace
"BWCD", BedeworkServerTags.bedeworkCarddavNamespace
"C", CaldavTags.caldavNamespace
"CD", CarddavTags.namespace="IS", IscheduleTags.namespace
"X", XcalTags.namespace
"df", "urn:ietf:params:xml:ns:pidf-diff"
"xml", XMLConstants.XML_NS_URI
"xmlns", XMLConstants.XMLNS_ATTRIBUTE_NS_URI
Notification preprocessing
The notification engine will extract a number of values and make them more easily available for the template.The template values appear as namespaced properties:
- ASnotification - the outermost element
- BWnotifyValues - a table of values added to the data
- event - the event as an iCal4j component
- dtstart - the start date
- dtend - the end date
- summary - event summary
<#setting date_format="iso"> <#setting time_format="iso m"> <#setting datetime_format="iso m"> <#assign msg = ASnotification.BWeventregRegistered> <#assign nvs = BWnotifyValues> <#assign event = nvs.event> <#assign ticketsRequested = msg.BWeventregNumTicketsRequested?number> <#assign ticketsAssigned = msg.BWeventregNumTickets?number> <#assign eventUID = event.uid> <#if ticketsAssigned != 0> Your registration for this event has been confirmed. <#else> You have been placed on the waitlist for this event. If a space becomes available, you will be notified via email. </#if> EVENT DETAILS <#--Start: ${nvs.dtstart?date}--> Title: ${nvs.summary} Event URL: https://mysite.edu/cal/event/eventView.do?href=${msg.Dhref} <#if ticketsRequested > 1> You requested ${msg.BWeventregNumTicketsRequested} tickets <#else> You requested ${msg.BWeventregNumTicketsRequested} ticket </#if> <#if ticketsAssigned > 1> and have been assigned ${msg.BWeventregNumTickets} tickets <#else> and have been assigned ${msg.BWeventregNumTickets} ticket </#if>
Bedework Enterprise Calendar Server, version 3.10