use of com.zimbra.cs.util.tnef.mapi.TimeZoneDefinition in project zm-mailbox by Zimbra.
the class DefaultTnefToICalendar method convert.
/* (non-Javadoc)
* @see com.zimbra.cs.util.tnef.TnefToICalendar#convert(java.io.InputStream, net.fortuna.ical4j.data.ContentHandler)
*/
public boolean convert(MimeMessage mimeMsg, InputStream tnefInput, ContentHandler icalOutput) throws ServiceException {
boolean conversionSuccessful = false;
recurDef = null;
TNEFInputStream tnefStream = null;
SchedulingViewOfTnef schedView = null;
Integer sequenceNum = 0;
icalType = ICALENDAR_TYPE.VEVENT;
try {
tnefStream = new TNEFInputStream(tnefInput);
schedView = new SchedulingViewOfTnef(tnefStream);
String msgClass = schedView.getMessageClass();
if (msgClass == null) {
sLog.debug("Unable to determine Class of TNEF - cannot generate ICALENDER equivalent");
// throw TNEFtoIcalendarServiceException.NON_CALENDARING_CLASS(msgClass);
return false;
}
icalType = schedView.getIcalType();
method = null;
PartStat partstat = null;
boolean replyWanted = schedView.getResponseRequested();
Boolean isCounterProposal = schedView.isCounterProposal();
if (msgClass != null) {
// just in case.
if (msgClass.startsWith("IPM.Microsoft Schedule.MtgReq")) {
method = Method.REQUEST;
partstat = PartStat.NEEDS_ACTION;
} else if (msgClass.startsWith("IPM.Microsoft Schedule.MtgRespP")) {
method = Method.REPLY;
partstat = PartStat.ACCEPTED;
replyWanted = false;
} else if (msgClass.startsWith("IPM.Microsoft Schedule.MtgRespN")) {
method = Method.REPLY;
partstat = PartStat.DECLINED;
replyWanted = false;
} else if (msgClass.startsWith("IPM.Microsoft Schedule.MtgRespA")) {
if ((isCounterProposal != null) && isCounterProposal) {
method = Method.COUNTER;
} else {
method = Method.REPLY;
}
partstat = PartStat.TENTATIVE;
replyWanted = false;
} else if (msgClass.startsWith("IPM.Microsoft Schedule.MtgCncl")) {
method = Method.CANCEL;
replyWanted = false;
} else if (msgClass.startsWith("IPM.TaskRequest.Accept")) {
method = Method.REPLY;
partstat = PartStat.ACCEPTED;
replyWanted = false;
} else if (msgClass.startsWith("IPM.TaskRequest.Decline")) {
method = Method.REPLY;
partstat = PartStat.DECLINED;
replyWanted = false;
} else if (msgClass.startsWith("IPM.TaskRequest.Update")) {
method = Method.REPLY;
// May be overridden?
partstat = PartStat.IN_PROCESS;
replyWanted = false;
} else if (msgClass.startsWith("IPM.TaskRequest")) {
method = Method.REQUEST;
partstat = PartStat.NEEDS_ACTION;
replyWanted = true;
}
}
if (method == null) {
sLog.debug("Unable to map class %s to ICALENDER", msgClass);
return false;
// throw TNEFtoIcalendarServiceException.NON_CALENDARING_CLASS(msgClass);
}
if (icalType == ICALENDAR_TYPE.VTODO) {
List<?> attaches = (List<?>) schedView.getAttachments();
if (attaches == null) {
sLog.debug("Unable to map class %s to ICALENDER - no attachments", msgClass);
return false;
}
schedView = null;
for (Object obj : attaches) {
if (obj instanceof Attachment) {
Attachment currAttach = (Attachment) obj;
MAPIProps attachMPs = currAttach.getMAPIProps();
if (attachMPs != null) {
MAPIProp attachData = attachMPs.getProp(MAPIProp.PR_ATTACH_DATA_OBJ);
if (attachData != null) {
Object theVal = attachData.getValue();
if ((theVal != null) && (theVal instanceof TNEFInputStream)) {
TNEFInputStream tnefSubStream = (TNEFInputStream) theVal;
schedView = new SchedulingViewOfTnef(tnefSubStream);
break;
}
}
}
}
}
if (schedView == null) {
sLog.debug("Unable to map class %s to ICALENDER - no properties found for sub-msg", msgClass);
return false;
}
}
uid = schedView.getIcalUID();
sequenceNum = schedView.getSequenceNumber();
boolean reminderSet = schedView.getReminderSet();
String location = schedView.getLocation();
Boolean isAllDayEvent = schedView.isAllDayEvent();
Integer importance = schedView.getMapiImportance();
Clazz icalClass = schedView.getIcalClass();
Integer ownerApptId = schedView.getOwnerAppointmentId();
EnumSet<MeetingTypeFlag> meetingTypeFlags = schedView.getMeetingTypeFlags();
BusyStatus busyStatus = schedView.getBusyStatus();
BusyStatus intendedBusyStatus = schedView.getIntendedBusyStatus();
// For some ICAL properties like TRANSP and STATUS, intendedBusyStatus
// seems closer to what is intended than straight busyStatus
BusyStatus bestBusyStatus = intendedBusyStatus;
if (bestBusyStatus == null) {
bestBusyStatus = busyStatus;
}
// An algorithm is used to choose the values for these
// TimeZoneDefinitions - they don't necessarily map to single
// MAPI properties
TimeZoneDefinition startTimeTZinfo = schedView.getStartDateTimezoneInfo();
TimeZoneDefinition endTimeTZinfo = schedView.getEndDateTimezoneInfo();
TimeZoneDefinition recurrenceTZinfo = schedView.getRecurrenceTimezoneInfo();
recurDef = schedView.getRecurrenceDefinition(recurrenceTZinfo);
DateTime icalStartDate = schedView.getStartTime();
DateTime icalEndDate = schedView.getEndTime();
DateTime icalDueDate = schedView.getDueDate();
DateTime icalDateTaskCompleted = schedView.getDateTaskCompleted();
DateTime icalCreateDate = MapiPropertyId.PidTagCreationTime.getDateTimeAsUTC(schedView);
DateTime icalLastModDate = MapiPropertyId.PidTagLastModificationTime.getDateTimeAsUTC(schedView);
DateTime recurrenceIdDateTime = schedView.getRecurrenceIdTime();
DateTime attendeeCriticalChange = schedView.getAttendeeCriticalChange();
DateTime ownerCriticalChange = schedView.getOwnerCriticalChange();
int percentComplete = schedView.getPercentComplete();
TaskStatus taskStatus = schedView.getTaskStatus();
TaskMode taskMode = schedView.getTaskMode();
String mileage = schedView.getMileage();
String billingInfo = schedView.getBillingInfo();
String companies = schedView.getCompanies();
Integer actualEffort = schedView.getActualEffort();
Integer estimatedEffort = schedView.getEstimatedEffort();
List<String> categories = schedView.getCategories();
String descriptionText = null;
String summary = null;
if (mimeMsg != null) {
summary = mimeMsg.getSubject();
PlainTextFinder finder = new PlainTextFinder();
finder.accept(mimeMsg);
descriptionText = finder.getPlainText();
}
// RTF might be useful as a basis for X-ALT-DESC if we can find a reliable
// conversion to HTML
// String rtfText = schedView.getRTF();
icalOutput.startCalendar();
// Results in a 2nd PRODID in iCalendar
// IcalUtil.addProperty(icalOutput, Property.PRODID,
// "Zimbra-TNEF-iCalendar-Converter");
IcalUtil.addProperty(icalOutput, method);
if (recurDef != null) {
String MsCalScale = recurDef.xMicrosoftCalscale();
if ((MsCalScale == null) || (MsCalScale.equals(""))) {
IcalUtil.addProperty(icalOutput, CalScale.GREGORIAN);
} else {
IcalUtil.addProperty(icalOutput, "X-MICROSOFT-CALSCALE", MsCalScale);
}
} else {
IcalUtil.addProperty(icalOutput, CalScale.GREGORIAN);
}
String startTZname = null;
String endTZname = null;
String recurTZname = null;
if (startTimeTZinfo != null) {
startTZname = startTimeTZinfo.getTimezoneName();
startTimeTZinfo.addVtimezone(icalOutput);
}
if (endTimeTZinfo != null) {
endTZname = endTimeTZinfo.getTimezoneName();
if ((startTZname == null) || (!endTZname.equals(startTZname))) {
endTimeTZinfo.addVtimezone(icalOutput);
}
}
if (recurrenceTZinfo != null) {
recurTZname = recurrenceTZinfo.getTimezoneName();
boolean addName = true;
if ((startTZname != null) && (recurTZname.equals(startTZname))) {
addName = false;
}
if ((endTZname != null) && (recurTZname.equals(endTZname))) {
addName = false;
}
if (addName) {
recurrenceTZinfo.addVtimezone(icalOutput);
}
}
if (uid == null) {
sLog.debug("Unable to map class %s to ICALENDER - no suitable value found for UID", msgClass);
return false;
}
icalOutput.startComponent(icalType.toString());
IcalUtil.addProperty(icalOutput, Property.UID, uid);
if ((attendeeCriticalChange != null) && (method.equals(Method.REPLY) || method.equals(Method.COUNTER))) {
dtstamp = new DtStamp(attendeeCriticalChange);
} else if (ownerCriticalChange != null) {
dtstamp = new DtStamp(ownerCriticalChange);
} else {
DateTime stampTime = new DateTime("20000101T000000Z");
dtstamp = new DtStamp(stampTime);
}
IcalUtil.addProperty(icalOutput, dtstamp);
IcalUtil.addProperty(icalOutput, Property.CREATED, icalCreateDate, false);
IcalUtil.addProperty(icalOutput, Property.LAST_MODIFIED, icalLastModDate, false);
IcalUtil.addProperty(icalOutput, Property.SEQUENCE, sequenceNum, false);
if ((summary == null) || (summary.length() == 0)) {
// TNEF_to_iCalendar.pdf Spec requires SUMMARY for certain method types
if (this.icalType == ICALENDAR_TYPE.VTODO) {
if (method.equals(Method.REQUEST)) {
summary = new String("Task Request");
} else if (method.equals(Method.REPLY)) {
summary = new String("Task Response");
} else {
summary = new String("Task");
}
} else {
if (method.equals(Method.REPLY)) {
summary = new String("Response");
} else if (method.equals(Method.CANCEL)) {
summary = new String("Canceled");
} else if (method.equals(Method.COUNTER)) {
summary = new String("Counter Proposal");
}
}
}
IcalUtil.addProperty(icalOutput, Property.SUMMARY, summary, false);
IcalUtil.addProperty(icalOutput, Property.LOCATION, location, false);
IcalUtil.addProperty(icalOutput, Property.DESCRIPTION, descriptionText, false);
if (method.equals(Method.COUNTER)) {
IcalUtil.addPropertyFromUtcTimeAndZone(icalOutput, Property.DTSTART, schedView.getProposedStartTime(), startTimeTZinfo, isAllDayEvent);
IcalUtil.addPropertyFromUtcTimeAndZone(icalOutput, Property.DTEND, schedView.getProposedEndTime(), endTimeTZinfo, isAllDayEvent);
IcalUtil.addPropertyFromUtcTimeAndZone(icalOutput, "X-MS-OLK-ORIGINALSTART", icalStartDate, startTimeTZinfo, isAllDayEvent);
IcalUtil.addPropertyFromUtcTimeAndZone(icalOutput, "X-MS-OLK-ORIGINALEND", icalEndDate, endTimeTZinfo, isAllDayEvent);
} else {
if (this.icalType == ICALENDAR_TYPE.VTODO) {
IcalUtil.addFloatingDateProperty(icalOutput, Property.DTSTART, icalStartDate);
IcalUtil.addFloatingDateProperty(icalOutput, Property.DUE, icalDueDate);
Status icalStatus = null;
if (method.equals(Method.CANCEL)) {
icalStatus = Status.VTODO_CANCELLED;
} else if (taskStatus != null) {
if (taskStatus.equals(TaskStatus.COMPLETE)) {
icalStatus = Status.VTODO_COMPLETED;
} else if (taskStatus.equals(TaskStatus.IN_PROGRESS)) {
icalStatus = Status.VTODO_IN_PROCESS;
}
}
IcalUtil.addProperty(icalOutput, icalStatus);
if (percentComplete != 0) {
IcalUtil.addProperty(icalOutput, Property.PERCENT_COMPLETE, percentComplete, false);
}
// COMPLETED must be a UTC DATE-TIME according to rfc5545
IcalUtil.addPropertyFromUtcTimeAndZone(icalOutput, Property.COMPLETED, icalDateTaskCompleted, null, false);
} else {
IcalUtil.addPropertyFromUtcTimeAndZone(icalOutput, Property.DTSTART, icalStartDate, startTimeTZinfo, isAllDayEvent);
IcalUtil.addPropertyFromUtcTimeAndZone(icalOutput, Property.DTEND, icalEndDate, endTimeTZinfo, isAllDayEvent);
}
}
// just the original start date.
if (recurrenceIdDateTime != null) {
IcalUtil.addPropertyFromUtcTimeAndZone(icalOutput, Property.RECURRENCE_ID, recurrenceIdDateTime, startTimeTZinfo, isAllDayEvent);
} else {
// Outlook messages related to a specific instance still include info on
// the full recurrence but we don't want to include that.
addRecurrenceRelatedProps(icalOutput, recurDef, startTimeTZinfo, isAllDayEvent);
}
// VTODO REQUEST must have priority according to http://tools.ietf.org/html/rfc5546
// No harm in always setting it
Priority priority = Priority.MEDIUM;
if (importance != null) {
if (importance == 2) {
priority = Priority.HIGH;
} else if (importance == 1) {
priority = Priority.MEDIUM;
} else if (importance == 0) {
priority = Priority.LOW;
}
}
IcalUtil.addProperty(icalOutput, priority);
IcalUtil.addProperty(icalOutput, icalClass);
addStatusProperty(icalOutput, bestBusyStatus, meetingTypeFlags);
addTranspProperty(icalOutput, bestBusyStatus);
addAttendees(icalOutput, mimeMsg, partstat, replyWanted);
// Not done as Zimbra doesn't currently support "RESOURCES".
if (categories != null) {
CategoryList cl = new CategoryList();
for (String category : categories) {
cl.add(category);
}
if (cl.size() > 0) {
Categories myCategories = new Categories(cl);
IcalUtil.addProperty(icalOutput, myCategories);
}
}
if (taskStatus != null) {
if (taskStatus.equals(TaskStatus.DEFERRED) || taskStatus.equals(TaskStatus.WAITING_ON_OTHER)) {
IcalUtil.addProperty(icalOutput, "X-ZIMBRA-TASK-STATUS", taskStatus, false);
}
}
if ((taskMode != null) && (!taskMode.equals(TaskMode.TASK_REQUEST))) {
IcalUtil.addProperty(icalOutput, "X-ZIMBRA-TASK-MODE", taskMode, false);
}
IcalUtil.addProperty(icalOutput, "X-ZIMBRA-MILEAGE", mileage, false);
IcalUtil.addProperty(icalOutput, "X-ZIMBRA-BILLING-INFO", billingInfo, false);
IcalUtil.addProperty(icalOutput, "X-ZIMBRA-COMPANIES", companies, false);
IcalUtil.addProperty(icalOutput, "X-ZIMBRA-ACTUAL-WORK-MINS", actualEffort, false);
IcalUtil.addProperty(icalOutput, "X-ZIMBRA-TOTAL-WORK-MINS", estimatedEffort, false);
if (this.icalType == ICALENDAR_TYPE.VEVENT) {
IcalUtil.addProperty(icalOutput, "X-MICROSOFT-CDO-ALLDAYEVENT", isAllDayEvent ? "TRUE" : "FALSE");
IcalUtil.addProperty(icalOutput, "X-MICROSOFT-CDO-BUSYSTATUS", busyStatus, false);
if (method.equals(Method.REQUEST)) {
IcalUtil.addProperty(icalOutput, "X-MICROSOFT-CDO-INTENDEDSTATUS", intendedBusyStatus, false);
}
IcalUtil.addProperty(icalOutput, "X-MICROSOFT-CDO-OWNERAPPTID", ownerApptId, false);
IcalUtil.addProperty(icalOutput, "X-MICROSOFT-CDO-REPLYTIME", schedView.getAppointmentReplyTime(), false);
IcalUtil.addProperty(icalOutput, "X-MICROSOFT-CDO-OWNER-CRITICAL-CHANGE", ownerCriticalChange, false);
Boolean disallowCounter = schedView.isDisallowCounter();
if (disallowCounter != null) {
IcalUtil.addProperty(icalOutput, "X-MICROSOFT-CDO-DISALLOW-COUNTER", disallowCounter ? "TRUE" : "FALSE");
}
}
if (reminderSet) {
addAlarmComponent(icalOutput, schedView.getReminderDelta());
}
icalOutput.endComponent(icalType.toString());
if (recurrenceIdDateTime == null) {
// If this message primarily relates to a specific instance,
// exception information is superfluous
addExceptions(icalOutput, recurDef, recurrenceTZinfo, sequenceNum, ownerApptId, summary, location, isAllDayEvent);
}
icalOutput.endCalendar();
conversionSuccessful = true;
sLog.info("Calendaring TNEF message mapped to ICALENDAR with UID=%s", uid);
} catch (ParserException e) {
sLog.debug("Unexpected ParserException thrown", e);
} catch (URISyntaxException e) {
sLog.debug("Unexpected URISyntaxException thrown", e);
} catch (ParseException e) {
sLog.debug("Unexpected ParseException thrown", e);
} catch (MessagingException e) {
sLog.debug("Unexpected MessagingException thrown", e);
} catch (NegativeArraySizeException e) {
sLog.debug("Problem decoding TNEF for ICALENDAR", e);
} catch (IOException e) {
sLog.debug("Unexpected IOException thrown", e);
} catch (UnsupportedTnefCalendaringMsgException e) {
sLog.debug("Unable to map this message to ICALENDAR", e);
} catch (TNEFtoIcalendarServiceException e) {
sLog.debug("Problem encountered mapping this message to ICALENDAR", e);
} finally {
try {
if (tnefStream != null) {
tnefStream.close();
}
} catch (IOException ioe) {
sLog.debug("Problem encountered closing TNEF stream", ioe);
}
}
return conversionSuccessful;
}
use of com.zimbra.cs.util.tnef.mapi.TimeZoneDefinition in project zm-mailbox by Zimbra.
the class TnefTimeZone method getTimeZone.
/**
* Ref: [MS-OXOCAL] - v20100729
* Returns a time zone from the given index;
* The default TimeZone ID is "tnefTimeZone"
* @param index
* @return
* @throws IOException
*/
public static TimeZone getTimeZone(int index, boolean observeDaylightSaving, String tzId) throws IOException {
if (index < 0 || index > 59)
return null;
// UTC offset in minutes
int bias = 0;
// offset in minutes from bias during standard time.; has a value of 0 in most cases
int standardBias = 0;
// offset in minutes from bias during daylight saving time.
int daylightBias = 0;
SYSTEMTIME StandardDate = null;
SYSTEMTIME DaylightDate = null;
// 1 - January, 12 - December
int startMonth = 0;
// 0 - Sunday, 6 - Saturday
int startDayOfWeek = 0;
// day of the week within the month, 5 = last occurrence of that day
int startDay = 0;
int startHour = 0;
int endMonth = 0;
int endDayOfWeek = 0;
int endDay = 0;
int endHour = 0;
// get the UTC+12 standard offset in minutes from MS_OXOCAL_STANDARD_OFFSET table!!
int utcPlus12offset = MS_OXOCAL_STANDARD_OFFSET[index][0];
int indexToDaytimeSavingDatesTable = MS_OXOCAL_STANDARD_OFFSET[index][1];
if (utcPlus12offset > 12 * 60)
bias = (utcPlus12offset - 12 * 60) * -1;
else if (utcPlus12offset < 12 * 60)
bias = (12 * 60 - utcPlus12offset);
if (indexToDaytimeSavingDatesTable == -1 || !observeDaylightSaving) {
int utcOffsetInMilliseconds = bias * 60 * 1000;
return getNoDaylightSavingTimeZoneFromUtcOffset(utcOffsetInMilliseconds);
}
// handle the daylight saving case here...
// HACK!!
// HACK!!
// TZRule.getStandardUtcOffset() always multiply the offset by -1;
// Hence, we are multiplying by -1 in reverse order.
bias = bias * -1;
// If daylight saving time is observed, during the daylight time period,
// an additional -60 offset is added to the standard offset.
daylightBias = -60;
startMonth = MS_OXOCAL_STAN_DST_DATES[indexToDaytimeSavingDatesTable][1][0];
startDayOfWeek = MS_OXOCAL_STAN_DST_DATES[indexToDaytimeSavingDatesTable][1][1];
startDay = MS_OXOCAL_STAN_DST_DATES[indexToDaytimeSavingDatesTable][1][2];
startHour = MS_OXOCAL_STAN_DST_DATES[indexToDaytimeSavingDatesTable][1][3];
endMonth = MS_OXOCAL_STAN_DST_DATES[indexToDaytimeSavingDatesTable][0][0];
endDayOfWeek = MS_OXOCAL_STAN_DST_DATES[indexToDaytimeSavingDatesTable][0][1];
endDay = MS_OXOCAL_STAN_DST_DATES[indexToDaytimeSavingDatesTable][0][2];
endHour = MS_OXOCAL_STAN_DST_DATES[indexToDaytimeSavingDatesTable][0][3];
StandardDate = new SYSTEMTIME(endMonth, endDayOfWeek, endDay, endHour);
DaylightDate = new SYSTEMTIME(startMonth, startDayOfWeek, startDay, startHour);
if (sLog.isDebugEnabled()) {
StringBuilder debugInfo = new StringBuilder();
debugInfo.append(bias * -1 + " " + "{" + endMonth + "," + endDayOfWeek + "," + endDay + "," + endHour + "} " + "{" + startMonth + "," + startDayOfWeek + "," + startDay + "," + startHour + "}");
sLog.debug(debugInfo);
}
String timeZoneId;
if (tzId == null || tzId.length() == 0)
timeZoneId = DEFAULT_TNEF_TIMEZONE_ID;
else
timeZoneId = tzId;
TimeZoneDefinition timeZoneDefinition = new TimeZoneDefinition(timeZoneId, bias, standardBias, daylightBias, StandardDate, DaylightDate);
return timeZoneDefinition.getTimeZone();
}
use of com.zimbra.cs.util.tnef.mapi.TimeZoneDefinition in project zm-mailbox by Zimbra.
the class SchedulingViewOfTnef method getTimeZoneStructInfo.
/**
* PidLidTimeZoneStruct Specifies time zone information for a recurring meeting.
*
* @param tzName
* @return
* @throws IOException
*/
private TimeZoneDefinition getTimeZoneStructInfo(String tzName) throws IOException {
RawInputStream tzRis = MapiPropertyId.PidLidTimeZoneStruct.getRawInputStreamValue(this);
if (tzRis == null) {
return null;
}
TimeZoneDefinition tzDef = new TimeZoneDefinition(tzRis, tzName);
if (tzDef == null) {
if (sLog.isDebugEnabled()) {
sLog.debug("Failed to load TimeZoneDefinition from PidLidTimeZoneStruct and " + tzName);
}
}
return tzDef;
}
use of com.zimbra.cs.util.tnef.mapi.TimeZoneDefinition in project zm-mailbox by Zimbra.
the class SchedulingViewOfTnef method initTZinfo.
/**
* Initialise timezone related fields.
* Replies from Outlook 2007 related to a recurrence or an instance
* of a recurrence had :
* PidLidTimeZoneDescription,PidLidTimeZoneStruct,
* PidLidAppointmentTimeZoneDefinitionStartDisplay and
* PidLidAppointmentTimeZoneDefinitionEndDisplay present but NOT
* PidLidAppointmentTimeZoneDefinitionRecur
* further, the StartDisplay/EndDisplay properties were appropriate to the
* Outlook client replying and were NOT related to the originally sent ICAL.
*
* The Outlook originated TimeZone names associated with
* StartDisplay/EndDisplay/Recur props seem "nicer" than the names
* used in PidLidTimeZoneDescription - so, tend to prefer those.
*
* @throws IOException
*/
private void initTZinfo() {
if (tzinfoInitialized) {
return;
}
try {
RawInputStream tzRis;
MapiPropertyId mpi;
mpi = MapiPropertyId.PidLidAppointmentTimeZoneDefinitionStartDisplay;
tzRis = mpi.getRawInputStreamValue(this);
if (tzRis != null) {
startTimeTZinfo = new TimeZoneDefinition(mpi, tzRis);
}
mpi = MapiPropertyId.PidLidAppointmentTimeZoneDefinitionEndDisplay;
tzRis = mpi.getRawInputStreamValue(this);
if (tzRis != null) {
endTimeTZinfo = new TimeZoneDefinition(mpi, tzRis);
}
mpi = MapiPropertyId.PidLidAppointmentTimeZoneDefinitionRecur;
tzRis = mpi.getRawInputStreamValue(this);
if (tzRis != null) {
recurrenceTZinfo = new TimeZoneDefinition(mpi, tzRis);
}
String tzDesc = this.getTimeZoneDescription();
if (null != tzDesc) {
TimeZoneDefinition tzStructInfo = this.getTimeZoneStructInfo(tzDesc);
if (tzStructInfo != null) {
// We know we have a recurrence related TZ definition. Make
// sure we have the most appropriate/nice definition for that.
TZRule tzsRule = tzStructInfo.getEffectiveRule();
if (recurrenceTZinfo == null) {
if ((startTimeTZinfo != null) && (tzsRule.equivalentRule(startTimeTZinfo.getEffectiveRule()))) {
recurrenceTZinfo = startTimeTZinfo;
sLog.debug("Using %s for TZ info", "PidLidAppointmentTimeZoneDefinitionStart");
} else if ((endTimeTZinfo != null) && (tzsRule.equivalentRule(endTimeTZinfo.getEffectiveRule()))) {
recurrenceTZinfo = endTimeTZinfo;
sLog.debug("Using %s for TZ info", "PidLidAppointmentTimeZoneDefinitionEnd");
} else {
recurrenceTZinfo = tzStructInfo;
sLog.debug("Using %s for TZ info", "PidLidTimeZoneStruct");
}
} else if (!tzsRule.equivalentRule(recurrenceTZinfo.getEffectiveRule())) {
recurrenceTZinfo = tzStructInfo;
sLog.debug("Using %s for TZ info", "PidLidAppointmentTimeZoneDefinitionRecur");
}
}
}
} catch (IOException e) {
sLog.debug("Problem encountered initialising timezone information", e);
}
if (recurrenceTZinfo != null) {
// For recurrences, we want just one TZ for consistency
if (endTimeTZinfo == null) {
endTimeTZinfo = recurrenceTZinfo;
} else if (recurrenceTZinfo.getEffectiveRule().equivalentRule(endTimeTZinfo.getEffectiveRule())) {
endTimeTZinfo = recurrenceTZinfo;
} else if (startTimeTZinfo != null) {
// for cancel/request, even when related to an exception.
if (startTimeTZinfo.getEffectiveRule().equivalentRule(endTimeTZinfo.getEffectiveRule())) {
endTimeTZinfo = recurrenceTZinfo;
}
}
startTimeTZinfo = recurrenceTZinfo;
}
if (endTimeTZinfo == null) {
endTimeTZinfo = startTimeTZinfo;
} else if (startTimeTZinfo == null) {
startTimeTZinfo = endTimeTZinfo;
} else if (startTimeTZinfo.getEffectiveRule().equivalentRule(endTimeTZinfo.getEffectiveRule())) {
endTimeTZinfo = startTimeTZinfo;
}
}
Aggregations