Search in sources :

Example 1 with Instance

use of com.zimbra.cs.mailbox.CalendarItem.Instance in project zm-mailbox by Zimbra.

the class Recurrence method main.

public static void main(String[] args) throws Exception {
    ICalTimeZone pacific = new ICalTimeZone("America/Los_Angeles", -28800000, "16010101T020000", "FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=11;BYDAY=1SU", "PST", -25200000, "16010101T020000", "FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=3;BYDAY=2SU", "PDT");
    TimeZoneMap tzmap = new TimeZoneMap(pacific);
    String str = "TZID=\"" + pacific.getID() + "\":20090105T120000";
    ParsedDateTime dtStart = ParsedDateTime.parse(str, tzmap);
    ParsedDuration duration = ParsedDuration.parse("PT1H");
    List<IRecurrence> addRules = new ArrayList<IRecurrence>();
    List<IRecurrence> subRules = new ArrayList<IRecurrence>();
    // weekly from 2009/01/05, for 52 weeks
    ZRecur rule = new ZRecur("FREQ=WEEKLY;INTERVAL=1", tzmap);
    addRules.add(new SimpleRepeatingRule(dtStart, duration, rule, null));
    // add a couple of RDATES: 2009/01/06, 2009/01/07
    RdateExdate rdate = new RdateExdate(ICalTok.RDATE, pacific);
    str = "TZID=\"" + pacific.getID() + "\":20090106T120000";
    ParsedDateTime rd1 = ParsedDateTime.parse(str, tzmap);
    rdate.addValue(rd1);
    str = "TZID=\"" + pacific.getID() + "\":20090107T120000";
    ParsedDateTime rd2 = ParsedDateTime.parse(str, tzmap);
    rdate.addValue(rd2);
    addRules.add(new SingleDates(rdate, duration));
    // modify instance on 2009/02/16 to start at 1pm instead of noon, for 2 hours
    str = "TZID=\"" + pacific.getID() + "\":20090216T120000";
    ParsedDateTime ridDtModify1 = ParsedDateTime.parse(str, tzmap);
    RecurId ridModify1 = new RecurId(ridDtModify1, RecurId.RANGE_NONE);
    str = "TZID=\"" + pacific.getID() + "\":20090216T130000";
    ParsedDateTime dtStartModify1 = ParsedDateTime.parse(str, tzmap);
    ParsedDuration durModify1 = ParsedDuration.parse("PT2H");
    ExceptionRule modify1 = new ExceptionRule(ridModify1, dtStartModify1, durModify1, null);
    // cancel instance on 2009/01/19
    str = "TZID=\"" + pacific.getID() + "\":20090119T120000";
    ParsedDateTime dtCancel1 = ParsedDateTime.parse(str, tzmap);
    RecurId ridCancel1 = new RecurId(dtCancel1, RecurId.RANGE_NONE);
    CancellationRule cancel1 = new CancellationRule(ridCancel1);
    // EXDATE on 2009/02/09
    RdateExdate exdate = new RdateExdate(ICalTok.EXDATE, pacific);
    str = "TZID=\"" + pacific.getID() + "\":20090209T120000";
    ParsedDateTime ex1 = ParsedDateTime.parse(str, tzmap);
    exdate.addValue(ex1);
    SingleDates exdateRule = new SingleDates(exdate, duration);
    subRules.add(exdateRule);
    RecurrenceRule recurrence = new RecurrenceRule(dtStart, duration, null, addRules, subRules);
    recurrence.addException(modify1);
    recurrence.addException(cancel1);
    // Get all instances between 2009/01/01 and 2010/01/01.
    Calendar startCal = new GregorianCalendar(pacific);
    startCal.clear();
    startCal.set(2009, Calendar.JANUARY, 1, 0, 0, 0);
    Calendar endCal = (Calendar) startCal.clone();
    endCal.add(Calendar.YEAR, 1);
    // List<Instance> instances = recurrence.expandInstances(-1, startCal.getTimeInMillis(), endCal.getTimeInMillis());
    List<Instance> instances = recurrence.expandInstances(-1, startCal.getTimeInMillis(), Long.MAX_VALUE);
    for (Instance inst : instances) {
        System.out.println(inst);
    }
    System.out.println("Got " + instances.size() + " instances");
}
Also used : ParsedDuration(com.zimbra.common.calendar.ParsedDuration) Instance(com.zimbra.cs.mailbox.CalendarItem.Instance) Calendar(java.util.Calendar) GregorianCalendar(java.util.GregorianCalendar) ArrayList(java.util.ArrayList) GregorianCalendar(java.util.GregorianCalendar) TimeZoneMap(com.zimbra.common.calendar.TimeZoneMap) ParsedDateTime(com.zimbra.common.calendar.ParsedDateTime) ICalTimeZone(com.zimbra.common.calendar.ICalTimeZone)

Example 2 with Instance

use of com.zimbra.cs.mailbox.CalendarItem.Instance in project zm-mailbox by Zimbra.

the class ExpandRecur method handle.

@Override
public Element handle(Element request, Map<String, Object> context) throws ServiceException {
    ZimbraSoapContext zsc = getZimbraSoapContext(context);
    Account authAcct = getAuthenticatedAccount(zsc);
    long rangeStart = request.getAttributeLong(MailConstants.A_CAL_START_TIME);
    long rangeEnd = request.getAttributeLong(MailConstants.A_CAL_END_TIME);
    long days = (rangeEnd - rangeStart) / Constants.MILLIS_PER_DAY;
    long maxDays = LC.calendar_freebusy_max_days.longValueWithinRange(0, 36600);
    if (days > maxDays)
        throw ServiceException.INVALID_REQUEST("Requested range is too large (Maximum " + maxDays + " days)", null);
    TimeZoneMap tzmap = new TimeZoneMap(Util.getAccountTimeZone(authAcct));
    ParsedRecurrence parsed = parseRecur(request, tzmap);
    List<Instance> instances = getInstances(parsed, rangeStart, rangeEnd);
    Element response = getResponseElement(zsc);
    if (instances != null) {
        for (Instance inst : instances) {
            addInstance(response, inst);
        }
    }
    return response;
}
Also used : Account(com.zimbra.cs.account.Account) Instance(com.zimbra.cs.mailbox.CalendarItem.Instance) ZimbraSoapContext(com.zimbra.soap.ZimbraSoapContext) Element(com.zimbra.common.soap.Element) TimeZoneMap(com.zimbra.common.calendar.TimeZoneMap)

Example 3 with Instance

use of com.zimbra.cs.mailbox.CalendarItem.Instance in project zm-mailbox by Zimbra.

the class ArchiveFormatter method saveItem.

private ArchiveOutputStream saveItem(UserServletContext context, MailItem mi, Map<Integer, String> fldrs, Map<Integer, Integer> cnts, boolean version, ArchiveOutputStream aos, CharsetEncoder charsetEncoder, Set<String> names) throws ServiceException {
    String ext = null, name = null;
    String extra = null;
    Integer fid = mi.getFolderId();
    String fldr;
    InputStream is = null;
    String metaParam = context.params.get(UserServlet.QP_META);
    boolean meta = metaParam == null ? getDefaultMeta() : !metaParam.equals("0");
    if (!version && mi.isTagged(Flag.FlagInfo.VERSIONED)) {
        for (MailItem rev : context.targetMailbox.getAllRevisions(context.opContext, mi.getId(), mi.getType())) {
            if (mi.getVersion() != rev.getVersion())
                aos = saveItem(context, rev, fldrs, cnts, true, aos, charsetEncoder, names);
        }
    }
    switch(mi.getType()) {
        case APPOINTMENT:
            Appointment appt = (Appointment) mi;
            if (!appt.isPublic() && !appt.allowPrivateAccess(context.getAuthAccount(), context.isUsingAdminPrivileges())) {
                return aos;
            }
            if (meta) {
                name = appt.getSubject();
                ext = "appt";
            } else {
                ext = "ics";
            }
            break;
        case CHAT:
            ext = "chat";
            break;
        case CONTACT:
            Contact ct = (Contact) mi;
            name = ct.getFileAsString();
            if (!meta) {
                ext = "vcf";
            }
            break;
        case FLAG:
            return aos;
        case FOLDER:
        case MOUNTPOINT:
        case SEARCHFOLDER:
            if (mi.getId() == Mailbox.ID_FOLDER_ROOT) {
                name = "ROOT";
            } else if (mi.getId() == Mailbox.ID_FOLDER_USER_ROOT) {
                name = "USER_ROOT";
            } else {
                name = mi.getName();
            }
            break;
        case MESSAGE:
            Message msg = (Message) mi;
            if (msg.hasCalendarItemInfos()) {
                Set<ItemId> calItems = Sets.newHashSet();
                for (Iterator<CalendarItemInfo> it = msg.getCalendarItemInfoIterator(); it.hasNext(); ) {
                    ItemId iid = it.next().getCalendarItemId();
                    if (iid != null) {
                        calItems.add(iid);
                    }
                }
                for (ItemId i : calItems) {
                    if (extra == null) {
                        extra = "calendar=" + i.toString();
                    } else {
                        extra += ',' + i.toString();
                    }
                }
            }
            ext = "eml";
            break;
        case NOTE:
            ext = "note";
            break;
        case TASK:
            Task task = (Task) mi;
            if (!task.isPublic() && !task.allowPrivateAccess(context.getAuthAccount(), context.isUsingAdminPrivileges())) {
                return aos;
            }
            ext = "task";
            break;
        case VIRTUAL_CONVERSATION:
            return aos;
        case WIKI:
            ext = "wiki";
            break;
    }
    fldr = fldrs.get(fid);
    if (fldr == null) {
        Folder f = mi.getMailbox().getFolderById(context.opContext, fid);
        cnts.put(fid, 1);
        fldr = f.getPath();
        if (fldr.startsWith("/")) {
            fldr = fldr.substring(1);
        }
        fldr = sanitize(fldr, charsetEncoder);
        fldr = ILLEGAL_FOLDER_CHARS.matcher(fldr).replaceAll("_");
        fldrs.put(fid, fldr);
    } else if (!(mi instanceof Folder)) {
        final int BATCH = 500;
        int cnt = cnts.get(fid) + 1;
        cnts.put(fid, cnt);
        cnt /= BATCH;
        if (cnt > 0) {
            fldr = fldr + '!' + cnt;
        }
    }
    int targetBaseLength = 0;
    if (context.noHierarchy()) {
        // Parent hierarchy is not needed, so construct the folder names without parent hierarchy.
        // e.g> represent "inbox/subfolder/target" as "target".
        String targetPath = null;
        if (context.itemPath.endsWith("/")) {
            // inbox/subfolder/target/
            targetPath = context.itemPath.substring(0, context.itemPath.lastIndexOf("/"));
        } else {
            // inbox/subfolder/target
            targetPath = context.itemPath;
        }
        // "inbox/subfolder".length()
        targetBaseLength = targetPath.lastIndexOf('/');
        if (targetBaseLength >= fldr.length()) {
            // fldr is "inbox/subfolder"
            fldr = "";
        } else if (targetBaseLength > 0) {
            // fldr is "inbox/subfolder/target"
            fldr = fldr.substring(targetBaseLength + 1);
        }
    }
    try {
        ArchiveOutputEntry aoe;
        byte[] data = null;
        String path = mi instanceof Contact ? getEntryName(mi, fldr, name, ext, charsetEncoder, names) : getEntryName(mi, fldr, name, ext, charsetEncoder, !(mi instanceof Document));
        long miSize = mi.getSize();
        if (miSize == 0 && mi.getDigest() != null) {
            ZimbraLog.misc.debug("blob db size 0 for item %d", mi.getId());
            return aos;
        }
        try {
            is = mi.getContentStream();
        } catch (Exception e) {
            ZimbraLog.misc.error("missing blob for item %d: expected %d", mi.getId(), miSize);
            return aos;
        }
        if (aos == null) {
            aos = getOutputStream(context, charsetEncoder.charset().name());
        }
        if ((mi instanceof CalendarItem) && (context.getStartTime() != TIME_UNSPECIFIED || context.getEndTime() != TIME_UNSPECIFIED)) {
            Collection<Instance> instances = ((CalendarItem) mi).expandInstances(context.getStartTime(), context.getEndTime(), false);
            if (instances.isEmpty()) {
                return aos;
            }
        }
        aoe = aos.newOutputEntry(path + ".meta", mi.getType().toString(), mi.getType().toByte(), mi.getDate());
        if (mi instanceof Message && (mi.getFlagBitmask() & Flag.ID_UNREAD) != 0) {
            aoe.setUnread();
        }
        if (meta) {
            ItemData itemData = new ItemData(mi, extra);
            if (context.noHierarchy()) {
                // itemData.path is of the form /Inbox/subfolder/target and after this step it becomes /target.
                if (targetBaseLength > 0 && ((targetBaseLength + 1) < itemData.path.length())) {
                    itemData.path = itemData.path.substring(targetBaseLength + 1);
                }
            }
            byte[] metaData = itemData.encode();
            aoe.setSize(metaData.length);
            aos.putNextEntry(aoe);
            aos.write(metaData);
            aos.closeEntry();
        } else if (mi instanceof CalendarItem) {
            Browser browser = HttpUtil.guessBrowser(context.req);
            List<CalendarItem> calItems = new ArrayList<CalendarItem>();
            boolean needAppleICalHacks = Browser.APPLE_ICAL.equals(browser);
            boolean useOutlookCompatMode = Browser.IE.equals(browser);
            OperationContext octxt = new OperationContext(context.getAuthAccount(), context.isUsingAdminPrivileges());
            StringWriter writer = new StringWriter();
            calItems.add((CalendarItem) mi);
            context.targetMailbox.writeICalendarForCalendarItems(writer, octxt, calItems, useOutlookCompatMode, true, needAppleICalHacks, true);
            data = writer.toString().getBytes(charsetEncoder.charset());
        } else if (mi instanceof Contact) {
            VCard vcf = VCard.formatContact((Contact) mi);
            data = vcf.getFormatted().getBytes(charsetEncoder.charset());
        } else if (mi instanceof Message) {
            if (context.hasPart()) {
                MimeMessage mm = ((Message) mi).getMimeMessage();
                Set<String> attachmentNames = new HashSet<String>();
                for (String part : context.getPart().split(",")) {
                    BufferStream bs;
                    MimePart mp = Mime.getMimePart(mm, part);
                    long sz;
                    if (mp == null) {
                        throw MailServiceException.NO_SUCH_PART(part);
                    }
                    name = Mime.getFilename(mp);
                    if (!Normalizer.isNormalized(name, Normalizer.Form.NFC)) {
                        name = Normalizer.normalize(name, Normalizer.Form.NFC);
                    }
                    ext = null;
                    sz = mp.getSize();
                    if (sz == -1) {
                        sz = miSize;
                    }
                    if (name == null) {
                        name = "attachment";
                    } else {
                        int dot = name.lastIndexOf('.');
                        if (dot != -1 && dot < name.length() - 1) {
                            ext = name.substring(dot + 1);
                            name = name.substring(0, dot);
                        }
                    }
                    bs = new BufferStream(sz, 1024 * 1024);
                    InputStream stream = mp.getInputStream();
                    try {
                        bs.readFrom(stream);
                    } finally {
                        // close the stream, it could be an instance of PipedInputStream.
                        ByteUtil.closeStream(stream);
                    }
                    aoe = aos.newOutputEntry(getEntryName(mi, "", name, ext, charsetEncoder, attachmentNames), mi.getType().toString(), mi.getType().toByte(), mi.getDate());
                    sz = bs.getSize();
                    aoe.setSize(sz);
                    aos.putNextEntry(aoe);
                    bs.copyTo(aos.getOutputStream());
                    bs.close();
                    aos.closeEntry();
                }
                return aos;
            }
        }
        aoe = aos.newOutputEntry(path, mi.getType().toString(), mi.getType().toByte(), mi.getDate());
        if (data != null) {
            aoe.setSize(data.length);
            aos.putNextEntry(aoe);
            aos.write(data);
            aos.closeEntry();
        } else if (is != null) {
            if (context.shouldReturnBody()) {
                byte[] buf = new byte[aos.getRecordSize() * 20];
                int in;
                long remain = miSize;
                aoe.setSize(miSize);
                aos.putNextEntry(aoe);
                while (remain > 0 && (in = is.read(buf)) >= 0) {
                    aos.write(buf, 0, remain < in ? (int) remain : in);
                    remain -= in;
                }
                if (remain != 0) {
                    ZimbraLog.misc.error("mismatched blob size for item %d: expected %d", mi.getId(), miSize);
                    if (remain > 0) {
                        Arrays.fill(buf, (byte) ' ');
                        while (remain > 0) {
                            aos.write(buf, 0, remain < buf.length ? (int) remain : buf.length);
                            remain -= buf.length;
                        }
                    }
                    aos.closeEntry();
                    aoe = aos.newOutputEntry(path + ".err", mi.getType().toString(), mi.getType().toByte(), mi.getDate());
                    aoe.setSize(0);
                    aos.putNextEntry(aoe);
                }
            } else {
                // Read headers into memory to compute size
                byte[] headerData = HeadersOnlyInputStream.getHeaders(is);
                aoe.setSize(headerData.length);
                aos.putNextEntry(aoe);
                aos.write(headerData);
            }
            aos.closeEntry();
        }
    } catch (Exception e) {
        throw ServiceException.FAILURE("archive error", e);
    } finally {
        ByteUtil.closeStream(is);
    }
    return aos;
}
Also used : Appointment(com.zimbra.cs.mailbox.Appointment) Task(com.zimbra.cs.mailbox.Task) EnumSet(java.util.EnumSet) Set(java.util.Set) HashSet(java.util.HashSet) MimeMessage(javax.mail.internet.MimeMessage) ParsedMessage(com.zimbra.cs.mime.ParsedMessage) Message(com.zimbra.cs.mailbox.Message) Instance(com.zimbra.cs.mailbox.CalendarItem.Instance) SearchFolder(com.zimbra.cs.mailbox.SearchFolder) Folder(com.zimbra.cs.mailbox.Folder) Document(com.zimbra.cs.mailbox.Document) ItemId(com.zimbra.cs.service.util.ItemId) CalendarItemInfo(com.zimbra.cs.mailbox.Message.CalendarItemInfo) CalendarItem(com.zimbra.cs.mailbox.CalendarItem) StringWriter(java.io.StringWriter) MimeMessage(javax.mail.internet.MimeMessage) ArrayList(java.util.ArrayList) List(java.util.List) LinkedList(java.util.LinkedList) OperationContext(com.zimbra.cs.mailbox.OperationContext) InputStream(java.io.InputStream) Mountpoint(com.zimbra.cs.mailbox.Mountpoint) NoSuchItemException(com.zimbra.cs.mailbox.MailServiceException.NoSuchItemException) ExportPeriodNotSpecifiedException(com.zimbra.cs.mailbox.MailServiceException.ExportPeriodNotSpecifiedException) ServiceException(com.zimbra.common.service.ServiceException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) MailServiceException(com.zimbra.cs.mailbox.MailServiceException) ExportPeriodTooLongException(com.zimbra.cs.mailbox.MailServiceException.ExportPeriodTooLongException) UserServletException(com.zimbra.cs.service.UserServletException) ParsedContact(com.zimbra.cs.mime.ParsedContact) Contact(com.zimbra.cs.mailbox.Contact) BufferStream(com.zimbra.common.util.BufferStream) MailItem(com.zimbra.cs.mailbox.MailItem) MimePart(javax.mail.internet.MimePart) SetCalendarItemData(com.zimbra.cs.mailbox.Mailbox.SetCalendarItemData) ItemData(com.zimbra.cs.service.util.ItemData) Browser(com.zimbra.common.util.HttpUtil.Browser)

Example 4 with Instance

use of com.zimbra.cs.mailbox.CalendarItem.Instance in project zm-mailbox by Zimbra.

the class ToXML method encodeInviteComponent.

public static Element encodeInviteComponent(Element parent, ItemIdFormatter ifmt, OperationContext octxt, CalendarItem calItem, /* may be null */
ItemId calId, /* may be null */
Invite invite, int fields, boolean neuter) throws ServiceException {
    boolean allFields = true;
    if (fields != NOTIFY_FIELDS) {
        allFields = false;
        if (!needToOutput(fields, Change.INVITE)) {
            return parent;
        }
    }
    Element e = parent.addNonUniqueElement(MailConstants.E_INVITE_COMPONENT);
    e.addAttribute(MailConstants.A_CAL_METHOD, invite.getMethod());
    e.addAttribute(MailConstants.A_CAL_COMPONENT_NUM, invite.getComponentNum());
    if (invite.hasRsvp()) {
        e.addAttribute(MailConstants.A_CAL_RSVP, invite.getRsvp());
    }
    boolean allowPrivateAccess = calItem != null ? allowPrivateAccess(octxt, calItem) : true;
    if (allFields) {
        if (invite.isPublic() || allowPrivateAccess) {
            String priority = invite.getPriority();
            if (priority != null) {
                e.addAttribute(MailConstants.A_CAL_PRIORITY, priority);
            }
            e.addAttribute(MailConstants.A_NAME, invite.getName());
            e.addAttribute(MailConstants.A_CAL_LOCATION, invite.getLocation());
            List<String> categories = invite.getCategories();
            if (categories != null) {
                for (String cat : categories) {
                    e.addNonUniqueElement(MailConstants.E_CAL_CATEGORY).setText(cat);
                }
            }
            List<String> comments = invite.getComments();
            if (comments != null) {
                for (String cmt : comments) {
                    e.addNonUniqueElement(MailConstants.E_CAL_COMMENT).setText(cmt);
                }
            }
            List<String> contacts = invite.getContacts();
            if (contacts != null) {
                for (String contact : contacts) {
                    e.addNonUniqueElement(MailConstants.E_CAL_CONTACT).setText(contact);
                }
            }
            Geo geo = invite.getGeo();
            if (geo != null) {
                geo.toXml(e);
            }
            // Percent Complete (VTODO)
            if (invite.isTodo()) {
                String pct = invite.getPercentComplete();
                if (pct != null)
                    e.addAttribute(MailConstants.A_TASK_PERCENT_COMPLETE, pct);
                long completed = invite.getCompleted();
                if (completed != 0) {
                    ParsedDateTime c = ParsedDateTime.fromUTCTime(completed);
                    e.addAttribute(MailConstants.A_TASK_COMPLETED, c.getDateTimePartString());
                }
            }
            // Attendee(s)
            List<ZAttendee> attendees = invite.getAttendees();
            for (ZAttendee at : attendees) {
                at.toXml(e);
            }
            // Alarms
            Iterator<Alarm> alarmsIter = invite.alarmsIterator();
            while (alarmsIter.hasNext()) {
                Alarm alarm = alarmsIter.next();
                alarm.toXml(e);
            }
            // x-prop
            encodeXProps(e, invite.xpropsIterator());
            // fragment
            String fragment = invite.getFragment();
            if (!Strings.isNullOrEmpty(fragment)) {
                e.addAttribute(MailConstants.E_FRAG, fragment, Element.Disposition.CONTENT);
            }
            if (!invite.hasBlobPart()) {
                e.addAttribute(MailConstants.A_CAL_NO_BLOB, true);
            }
            // Description (plain and html)
            String desc = invite.getDescription();
            if (desc != null) {
                Element descElem = e.addNonUniqueElement(MailConstants.E_CAL_DESCRIPTION);
                descElem.setText(desc);
            }
            String descHtml = invite.getDescriptionHtml();
            BrowserDefang defanger = DefangFactory.getDefanger(MimeConstants.CT_TEXT_HTML);
            if (descHtml != null) {
                try {
                    descHtml = StringUtil.stripControlCharacters(descHtml);
                    descHtml = defanger.defang(descHtml, neuter);
                    Element descHtmlElem = e.addNonUniqueElement(MailConstants.E_CAL_DESC_HTML);
                    descHtmlElem.setText(descHtml);
                } catch (IOException ex) {
                    ZimbraLog.calendar.warn("Unable to defang HTML for SetAppointmentRequest", ex);
                }
            }
            if (invite.isEvent()) {
                if (calItem != null && calItem instanceof Appointment) {
                    Instance inst = Instance.fromInvite(calItem.getId(), invite);
                    Appointment appt = (Appointment) calItem;
                    e.addAttribute(MailConstants.A_APPT_FREEBUSY_ACTUAL, appt.getEffectiveFreeBusyActual(invite, inst));
                }
                e.addAttribute(MailConstants.A_APPT_FREEBUSY, invite.getFreeBusy());
                e.addAttribute(MailConstants.A_APPT_TRANSPARENCY, invite.getTransparency());
            }
            // Organizer
            if (invite.hasOrganizer()) {
                ZOrganizer org = invite.getOrganizer();
                org.toXml(e);
            }
            e.addAttribute(MailConstants.A_CAL_URL, invite.getUrl());
        }
        if (invite.isOrganizer()) {
            e.addAttribute(MailConstants.A_CAL_ISORG, true);
        }
        boolean isRecurring = false;
        e.addAttribute("x_uid", invite.getUid());
        e.addAttribute(MailConstants.A_UID, invite.getUid());
        e.addAttribute(MailConstants.A_CAL_SEQUENCE, invite.getSeqNo());
        // zdsync
        e.addAttribute(MailConstants.A_CAL_DATETIME, invite.getDTStamp());
        String itemId = null;
        if (calId != null) {
            itemId = calId.toString(ifmt);
        } else if (calItem != null) {
            itemId = ifmt.formatItemId(calItem);
        }
        if ((itemId != null) && !("0".equals(itemId))) {
            e.addAttribute(MailConstants.A_CAL_ID, /* calItemId */
            itemId);
            if (invite.isEvent()) {
                // for backward compat
                e.addAttribute(MailConstants.A_APPT_ID_DEPRECATE_ME, /* apptId */
                itemId);
            }
            if (calItem != null) {
                ItemId ciFolderId = new ItemId(calItem.getMailbox(), calItem.getFolderId());
                e.addAttribute(MailConstants.A_CAL_ITEM_FOLDER, /* ciFolder */
                ifmt.formatItemId(ciFolderId));
            }
        }
        Recurrence.IRecurrence recur = invite.getRecurrence();
        if (recur != null) {
            isRecurring = true;
            Element recurElt = e.addNonUniqueElement(MailConstants.E_CAL_RECUR);
            recur.toXml(recurElt);
        }
        e.addAttribute(MailConstants.A_CAL_STATUS, invite.getStatus());
        e.addAttribute(MailConstants.A_CAL_CLASS, invite.getClassProp());
        boolean allDay = invite.isAllDayEvent();
        boolean isException = invite.hasRecurId();
        if (isException) {
            e.addAttribute(MailConstants.A_CAL_IS_EXCEPTION, true);
            RecurId rid = invite.getRecurId();
            e.addAttribute(MailConstants.A_CAL_RECURRENCE_ID_Z, rid.getDtZ());
            encodeRecurId(e, rid, allDay);
        }
        boolean forceUTC = DebugConfig.calendarForceUTC && !isRecurring && !isException && !allDay;
        ParsedDateTime dtStart = invite.getStartTime();
        if (dtStart != null) {
            encodeDtStart(e, dtStart, allDay, forceUTC);
        }
        ParsedDateTime dtEnd = invite.getEndTime();
        if (dtEnd != null) {
            encodeDtEnd(e, dtEnd, allDay, invite.isTodo(), forceUTC);
        }
        ParsedDuration dur = invite.getDuration();
        if (dur != null) {
            dur.toXml(e);
        }
        if (allDay) {
            e.addAttribute(MailConstants.A_CAL_ALLDAY, true);
        }
        if (invite.isDraft()) {
            e.addAttribute(MailConstants.A_CAL_DRAFT, true);
        }
        if (invite.isNeverSent()) {
            e.addAttribute(MailConstants.A_CAL_NEVER_SENT, true);
        }
    }
    return e;
}
Also used : Appointment(com.zimbra.cs.mailbox.Appointment) Recurrence(com.zimbra.cs.mailbox.calendar.Recurrence) IRecurrence(com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence) Instance(com.zimbra.cs.mailbox.CalendarItem.Instance) IRecurrence(com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence) ParsedDuration(com.zimbra.common.calendar.ParsedDuration) Element(com.zimbra.common.soap.Element) ZOrganizer(com.zimbra.cs.mailbox.calendar.ZOrganizer) BrowserDefang(com.zimbra.cs.html.BrowserDefang) RecurId(com.zimbra.cs.mailbox.calendar.RecurId) IOException(java.io.IOException) ItemId(com.zimbra.cs.service.util.ItemId) Geo(com.zimbra.common.calendar.Geo) ZAttendee(com.zimbra.cs.mailbox.calendar.ZAttendee) Alarm(com.zimbra.cs.mailbox.calendar.Alarm) ParsedDateTime(com.zimbra.common.calendar.ParsedDateTime)

Example 5 with Instance

use of com.zimbra.cs.mailbox.CalendarItem.Instance in project zm-mailbox by Zimbra.

the class CheckRecurConflicts method handle.

@Override
public Element handle(Element request, Map<String, Object> context) throws ServiceException {
    ZimbraSoapContext zsc = getZimbraSoapContext(context);
    Account authAcct = getAuthenticatedAccount(zsc);
    Element response = getResponseElement(zsc);
    long rangeStart = request.getAttributeLong(MailConstants.A_CAL_START_TIME, 0);
    if (rangeStart == 0)
        rangeStart = System.currentTimeMillis();
    long rangeEnd = request.getAttributeLong(MailConstants.A_CAL_END_TIME, 0);
    if (rangeEnd == 0)
        rangeEnd = Long.MAX_VALUE;
    boolean allInstances = request.getAttributeBool(MailConstants.A_CAL_ALL, false);
    String exApptUid = request.getAttribute(MailConstants.A_APPT_FREEBUSY_EXCLUDE_UID, null);
    // Parse and expand the recurrence.
    TimeZoneMap tzmap = new TimeZoneMap(Util.getAccountTimeZone(authAcct));
    ParsedRecurrence parsed = parseRecur(request, tzmap);
    List<Instance> instances = getInstances(parsed, rangeStart, rangeEnd);
    if (instances == null || instances.isEmpty())
        return response;
    // Find the range covered by the instances.
    long rangeStartActual = rangeEnd, rangeEndActual = rangeStart;
    for (Instance inst : instances) {
        if (inst.hasStart() && inst.hasEnd()) {
            rangeStartActual = Math.min(rangeStartActual, inst.getStart());
            rangeEndActual = Math.max(rangeEndActual, inst.getEnd());
        }
    }
    if (rangeStartActual >= rangeEndActual)
        return response;
    // Run free/busy search on the users.
    FreeBusyQuery fbQuery = new FreeBusyQuery((HttpServletRequest) context.get(SoapServlet.SERVLET_REQUEST), zsc, authAcct, rangeStartActual, rangeEndActual, exApptUid);
    for (Iterator<Element> usrIter = request.elementIterator(MailConstants.E_FREEBUSY_USER); usrIter.hasNext(); ) {
        Element usrElem = usrIter.next();
        int folderId = (int) usrElem.getAttributeLong(MailConstants.A_FOLDER, FreeBusyQuery.CALENDAR_FOLDER_ALL);
        if (folderId == Mailbox.ID_FOLDER_USER_ROOT || folderId == 0)
            folderId = FreeBusyQuery.CALENDAR_FOLDER_ALL;
        String id = usrElem.getAttribute(MailConstants.A_ID, null);
        if (id != null)
            fbQuery.addAccountId(id, folderId);
        String name = usrElem.getAttribute(MailConstants.A_NAME, null);
        if (name != null)
            fbQuery.addEmailAddress(name, folderId);
    }
    Collection<FreeBusy> fbResults = fbQuery.getResults();
    List<UserConflicts> conflicts = new ArrayList<UserConflicts>();
    for (FreeBusy fb : fbResults) {
        UserConflicts ucon = getConflicts(fb, instances);
        conflicts.add(ucon);
    }
    // Find conflicts for each instance.
    for (Instance inst : instances) {
        Element instElem = addInstance(response, inst);
        int numConflicts = 0;
        for (UserConflicts ucon : conflicts) {
            String fbStatus = ucon.get(inst);
            if (fbStatus != null) {
                ++numConflicts;
                String username = ucon.getUsername();
                Element usrElem = instElem.addElement(MailConstants.E_FREEBUSY_USER);
                usrElem.addAttribute(MailConstants.A_NAME, username);
                usrElem.addAttribute(MailConstants.A_APPT_FREEBUSY, fbStatus);
            }
        }
        if (numConflicts == 0 && !allInstances)
            instElem.detach();
    }
    return response;
}
Also used : Account(com.zimbra.cs.account.Account) FreeBusy(com.zimbra.cs.fb.FreeBusy) Instance(com.zimbra.cs.mailbox.CalendarItem.Instance) Element(com.zimbra.common.soap.Element) FreeBusyQuery(com.zimbra.cs.fb.FreeBusyQuery) ArrayList(java.util.ArrayList) ZimbraSoapContext(com.zimbra.soap.ZimbraSoapContext) TimeZoneMap(com.zimbra.common.calendar.TimeZoneMap)

Aggregations

Instance (com.zimbra.cs.mailbox.CalendarItem.Instance)15 Element (com.zimbra.common.soap.Element)7 CalendarItem (com.zimbra.cs.mailbox.CalendarItem)6 TimeZoneMap (com.zimbra.common.calendar.TimeZoneMap)5 ArrayList (java.util.ArrayList)5 ICalTimeZone (com.zimbra.common.calendar.ICalTimeZone)3 ParsedDateTime (com.zimbra.common.calendar.ParsedDateTime)3 ParsedDuration (com.zimbra.common.calendar.ParsedDuration)3 MailItem (com.zimbra.cs.mailbox.MailItem)3 OperationContext (com.zimbra.cs.mailbox.OperationContext)3 Invite (com.zimbra.cs.mailbox.calendar.Invite)3 IRecurrence (com.zimbra.cs.mailbox.calendar.Recurrence.IRecurrence)3 ItemId (com.zimbra.cs.service.util.ItemId)3 ZimbraSoapContext (com.zimbra.soap.ZimbraSoapContext)3 Browser (com.zimbra.common.util.HttpUtil.Browser)2 Account (com.zimbra.cs.account.Account)2 Interval (com.zimbra.cs.fb.FreeBusy.Interval)2 Appointment (com.zimbra.cs.mailbox.Appointment)2 Folder (com.zimbra.cs.mailbox.Folder)2 Task (com.zimbra.cs.mailbox.Task)2