use of com.zimbra.common.calendar.ParsedDuration in project zm-mailbox by Zimbra.
the class Invite method decodeMetadata.
/**
* This API is public for RedoLogging to call into it -- you probably don't want to call it from
* anywhere else!
*
* @param mailboxId
* @param meta
* @param calItem
* @param accountTZ
* @return
* @throws ServiceException
*/
public static Invite decodeMetadata(int mailboxId, Metadata meta, CalendarItem calItem, ICalTimeZone accountTZ) throws ServiceException {
byte btype = (byte) meta.getLong(FN_ITEMTYPE, -1);
MailItem.Type type = btype >= 0 ? MailItem.Type.of(btype) : MailItem.Type.APPOINTMENT;
String uid = meta.get(FN_UID, null);
int mailItemId = (int) meta.getLong(FN_INVMSGID);
int componentNum = (int) meta.getLong(FN_COMPNUM);
String classProp = meta.get(FN_CLASS, IcalXmlStrMap.CLASS_PUBLIC);
boolean classPropSetByMe = meta.getBool(FN_CLASS_SETBYME, false);
String status = meta.get(FN_STATUS, IcalXmlStrMap.STATUS_CONFIRMED);
String freebusy = meta.get(FN_APPT_FREEBUSY, null);
String transp = meta.get(FN_TRANSP, IcalXmlStrMap.TRANSP_OPAQUE);
boolean sentByMe = meta.getBool(FN_SENTBYME);
String fragment = meta.get(FN_FRAGMENT, "");
// default to false for backward compat
boolean descInMeta = meta.getBool(FN_DESC_IN_META, false);
String desc = descInMeta ? meta.get(FN_DESC, null) : null;
String descHtml = descInMeta ? meta.get(FN_DESC_HTML, null) : null;
long completed = meta.getLong(FN_COMPLETED, 0);
ParsedDateTime dtStart = null;
ParsedDateTime dtEnd = null;
ParsedDuration duration = null;
RecurId recurrenceId = null;
TimeZoneMap tzMap = Util.decodeFromMetadata(meta.getMap(FN_TZMAP), accountTZ);
Metadata metaRecur = meta.getMap(FN_RECURRENCE, true);
Recurrence.IRecurrence recurrence = null;
if (metaRecur != null) {
recurrence = Recurrence.decodeMetadata(metaRecur, tzMap);
}
String methodStr = meta.get(FN_METHOD, ICalTok.PUBLISH.toString());
if (ICalTok.CANCEL.toString().equals(methodStr))
status = IcalXmlStrMap.STATUS_CANCELLED;
int flags = (int) meta.getLong(FN_APPT_FLAGS, 0);
try {
// DtStart
dtStart = ParsedDateTime.parse(meta.get(FN_START, null), tzMap);
// DtEnd
dtEnd = ParsedDateTime.parse(meta.get(FN_END, null), tzMap);
if ((flags & APPT_FLAG_ALLDAY) != 0) {
// Fixup historic data with incorrect all-day start/end format.
if (dtStart != null)
dtStart.forceDateOnly();
if (dtEnd != null)
dtEnd.forceDateOnly();
}
// Duration
duration = ParsedDuration.parse(meta.get(FN_DURATION, null));
if (meta.containsKey(FN_RECUR_ID)) {
Metadata rdata = meta.getMap(FN_RECUR_ID);
recurrenceId = RecurId.decodeMetadata(rdata, tzMap);
}
} catch (ParseException e) {
throw ServiceException.FAILURE(String.format("Error parsing metadata for invite %s-%s in calItem %s", mailItemId, componentNum, (calItem != null) ? Integer.toString(calItem.getId()) : "(null)"), e);
}
String name = meta.get(FN_NAME, "");
String loc = meta.get(FN_LOCATION, null);
// For existing invites with no partstat, default to ACCEPTED status.
String partStat = meta.get(FN_PARTSTAT, IcalXmlStrMap.PARTSTAT_ACCEPTED);
// For existing invites with no RSVP, default to true.
boolean rsvp = meta.getBool(FN_RSVP, true);
long dtstamp = meta.getLong(FN_DTSTAMP, 0);
long lastModified = meta.getLong(FN_LAST_MODIFIED, 0);
int seqno = (int) meta.getLong(FN_SEQ_NO, 0);
int lastFullSeqno = (int) meta.getLong(FN_LAST_FULL_SEQ_NO, seqno);
ZOrganizer org = null;
try {
Metadata metaOrg = meta.getMap(FN_ORGANIZER, true);
org = metaOrg != null ? new ZOrganizer(metaOrg) : null;
} catch (ServiceException e) {
sLog.warn("Problem decoding organizer for calItem %s invite %s-%s", (calItem != null) ? Integer.toString(calItem.getId()) : "(null)", mailItemId, componentNum);
}
long numAts = meta.getLong(FN_NUM_ATTENDEES, 0);
ArrayList<ZAttendee> attendees = new ArrayList<ZAttendee>((int) numAts);
for (int i = 0; i < numAts; i++) {
try {
Metadata metaAttendee = meta.getMap(FN_ATTENDEE + i, true);
if (metaAttendee != null)
attendees.add(new ZAttendee(metaAttendee));
} catch (ServiceException e) {
ZimbraLog.calendar.warn("Problem decoding attendee %s for calendar item %s invite %s-%s", i, (calItem != null) ? Integer.toString(calItem.getId()) : "(null)", mailItemId, componentNum);
}
}
boolean isOrganizer = false;
if (meta.containsKey(FN_IS_ORGANIZER)) {
isOrganizer = meta.getBool(FN_IS_ORGANIZER);
} else {
// backward compat for invites created before FN_IS_ORGANIZER was introduced
if (org != null) {
String orgAddr = org.getAddress();
Account account = MailboxManager.getInstance().getMailboxById(mailboxId).getAccount();
AccountAddressMatcher acctMatcher = new AccountAddressMatcher(account);
isOrganizer = acctMatcher.matches(orgAddr);
} else {
// If there are other attendees, it's an Outlook POP/IMAP bug. If not,
// it's a properly formatted single-user event. See isOrganizer()
// method for more info.
isOrganizer = numAts < 1;
}
}
String priority = meta.get(FN_PRIORITY, null);
String pctComplete = meta.get(FN_PCT_COMPLETE, null);
List<String> comments = null;
int numComm = (int) meta.getLong(FN_NUM_COMMENTS, 0);
if (numComm > 0) {
comments = new ArrayList<String>(numComm);
for (int i = 0; i < numComm; i++) {
String comm = meta.get(FN_COMMENT + i, null);
if (comm != null)
comments.add(comm);
}
}
List<String> contacts = null;
int numContacts = (int) meta.getLong(FN_NUM_CONTACTS, 0);
if (numContacts > 0) {
contacts = new ArrayList<String>(numContacts);
for (int i = 0; i < numContacts; i++) {
String contact = meta.get(FN_CONTACT + i, null);
if (contact != null)
contacts.add(contact);
}
}
List<String> categories = null;
int numCat = (int) meta.getLong(FN_NUM_CATEGORIES, 0);
if (numCat > 0) {
categories = new ArrayList<String>(numCat);
for (int i = 0; i < numCat; i++) {
String cat = meta.get(FN_CATEGORY + i, null);
if (cat != null)
categories.add(cat);
}
}
Geo geo = null;
Metadata metaGeo = meta.getMap(FN_GEO, true);
if (metaGeo != null)
geo = Util.decodeGeoFromMetadata(metaGeo);
String url = meta.get(FN_URL, null);
Invite invite = new Invite(type, methodStr, tzMap, calItem, uid, status, priority, pctComplete, completed, freebusy, transp, classProp, dtStart, dtEnd, duration, recurrence, isOrganizer, org, attendees, name, loc, flags, partStat, rsvp, recurrenceId, dtstamp, lastModified, seqno, lastFullSeqno, mailboxId, mailItemId, componentNum, sentByMe, desc, descHtml, fragment, comments, categories, contacts, geo, url);
// a little hacky, but necessary
invite.mDescInMeta = descInMeta;
invite.setClassPropSetByMe(classPropSetByMe);
long numAlarms = meta.getLong(FN_NUM_ALARMS, 0);
for (int i = 0; i < numAlarms; i++) {
try {
Metadata metaAlarm = meta.getMap(FN_ALARM + i, true);
if (metaAlarm != null) {
Alarm alarm = Alarm.decodeMetadata(metaAlarm);
if (alarm != null)
invite.addAlarm(alarm);
}
} catch (ServiceException e) {
ZimbraLog.calendar.warn("Problem decoding alarm %s for calendar item %s invite %s-%s", i, (calItem != null) ? Integer.toString(calItem.getId()) : "(null)", mailItemId, componentNum, e);
}
}
List<ZProperty> xprops = Util.decodeXPropsFromMetadata(meta);
if (xprops != null) {
for (ZProperty xprop : xprops) {
boolean isHtmlDesc = false;
if (ICalTok.X_ALT_DESC.equals(xprop.getToken())) {
// Backward compat. We used to save X-ALT-DESC property as an x-prop. Now we use it
// for HTML description, when FMTTYPE=text/html.
ZParameter fmttype = xprop.getParameter(ICalTok.FMTTYPE);
if (fmttype != null && MimeConstants.CT_TEXT_HTML.equalsIgnoreCase(fmttype.getValue())) {
isHtmlDesc = true;
invite.mDescHtml = xprop.getValue();
}
}
if (!isHtmlDesc)
invite.addXProp(xprop);
}
}
invite.setDontIndexMimeMessage(meta.getBool(FN_DONT_INDEX_MM, false));
boolean localOnly = meta.getBool(FN_LOCAL_ONLY, false);
invite.setLocalOnly(localOnly);
invite.sanitize(false);
return invite;
}
use of com.zimbra.common.calendar.ParsedDuration in project zm-mailbox by Zimbra.
the class InviteChanges method diffInvites.
private void diffInvites(Invite inv1, Invite inv2) {
// Subject
if (!StringUtil.equal(inv1.getName(), inv2.getName()))
mChanges |= SUBJECT;
// LOCATION
if (!StringUtil.equal(inv1.getLocation(), inv2.getLocation()))
mChanges |= LOCATION;
// DTSTART
boolean dtStartChanged;
ParsedDateTime dtStart1 = inv1.getStartTime();
ParsedDateTime dtStart2 = inv2.getStartTime();
if (dtStart1 == null || dtStart2 == null)
dtStartChanged = dtStart1 != dtStart2;
else
dtStartChanged = !StringUtil.equal(dtStart1.getDateTimePartString(false), dtStart2.getDateTimePartString(false));
if (dtStartChanged) {
mChanges |= TIME;
} else {
// DTEND
boolean dtEndChanged;
ParsedDateTime dtEnd1 = inv1.getEndTime();
ParsedDateTime dtEnd2 = inv2.getEndTime();
if (dtEnd1 == null || dtEnd2 == null)
dtEndChanged = dtEnd1 != dtEnd2;
else
dtEndChanged = !StringUtil.equal(dtEnd1.getDateTimePartString(false), dtEnd2.getDateTimePartString(false));
if (dtEndChanged) {
mChanges |= TIME;
} else {
boolean durationChanged;
ParsedDuration dur1 = inv1.getDuration();
ParsedDuration dur2 = inv2.getDuration();
if (dur1 == null || dur2 == null)
durationChanged = dur1 != dur2;
else
durationChanged = !dur1.equals(dur2);
if (durationChanged)
mChanges |= TIME;
}
}
// Recurrence
boolean recurChanged;
IRecurrence recur1 = inv1.getRecurrence();
IRecurrence recur2 = inv2.getRecurrence();
if (recur1 == null || recur2 == null) {
recurChanged = recur1 != recur2;
} else {
recurChanged = !Recurrence.sameSeriesRules(recur1, recur2);
}
if (recurChanged)
mChanges |= RECURRENCE;
}
use of com.zimbra.common.calendar.ParsedDuration in project zm-mailbox by Zimbra.
the class Period method parse.
public static Period parse(String value, ICalTimeZone tz, TimeZoneMap tzmap) throws ServiceException, ParseException {
String[] parsed = value.split("\\/", 2);
if (parsed.length != 2 || parsed[0].length() == 0 || parsed[1].length() == 1)
throw ServiceException.INVALID_REQUEST("Invalid PERIOD value \"" + value + "\"", null);
ParsedDateTime startTime;
startTime = ParsedDateTime.parse(parsed[0], tzmap, tz, tzmap.getLocalTimeZone());
char ch = parsed[1].charAt(0);
if (ch == 'P' || ch == '+' || ch == '-') {
ParsedDuration duration = ParsedDuration.parse(parsed[1]);
return new Period(startTime, duration);
} else {
ParsedDateTime endTime = ParsedDateTime.parse(parsed[1], tzmap, tz, tzmap.getLocalTimeZone());
return new Period(startTime, endTime);
}
}
Aggregations