Search in sources :

Example 1 with InstanceDataInfo

use of com.zimbra.soap.mail.type.InstanceDataInfo in project zm-mailbox by Zimbra.

the class TestJaxb method testAcceptSeriesDeclineInstance.

/**
     * Bug 94018.  Accepting series, then declining single instance leads to inconsistent display of attendee
     * status for organizer copy for the declined instance.
     * Test steps:
     * 1.  Invite 2 users to a daily meeting.
     * 2.  User 1 replies, accepting the daily meeting.
     * 3.  User 1 replies again, declining one of the instances in the daily meeting.
     * 4.  User 2 replies tentatively accepting the daily meeting.
     *
     * At the end of this, check that an exception has been created.  Check that that exception registers
     * the decline from user 1 AND the tentative acceptance from user2 that arrived later.
     */
@Test
public void testAcceptSeriesDeclineInstance() throws Exception {
    TestUtil.createAccount(ORGANIZER);
    TestUtil.createAccount(ATTENDEE1);
    TestUtil.createAccount(ATTENDEE2);
    String subject = NAME_PREFIX + " Daily";
    ZMailbox organizerBox = TestUtil.getZMailbox(ORGANIZER);
    ZMailbox attendeeBox = TestUtil.getZMailbox(ATTENDEE1);
    ZMailbox attendee2Box = TestUtil.getZMailbox(ATTENDEE2);
    String organizerEmail = organizerBox.getName();
    // Create and send the daily meeting
    InviteComponent inviteComp = new InviteComponent();
    inviteComp.addAttendee(CalendarAttendee.createForAddressDisplaynameRolePartstatRsvp(attendeeBox.getName(), getCN(attendeeBox), "REQ", "NE", true));
    inviteComp.addAttendee(CalendarAttendee.createForAddressDisplaynameRolePartstatRsvp(attendee2Box.getName(), getCN(attendee2Box), "REQ", "NE", true));
    inviteComp.setStatus("CONF");
    inviteComp.setFreeBusy("B");
    inviteComp.setCalClass("PUB");
    inviteComp.setTransparency("O");
    inviteComp.setIsDraft(false);
    inviteComp.setIsAllDay(false);
    inviteComp.setDtStart(DtTimeInfo.createForDatetimeAndZone("20161008T130000", "Europe/London"));
    inviteComp.setDtEnd(DtTimeInfo.createForDatetimeAndZone("20161008T140000", "Europe/London"));
    inviteComp.setName(subject);
    inviteComp.setLocation("room 101");
    inviteComp.setOrganizer(CalOrganizer.createForAddress(organizerEmail));
    inviteComp.setRecurrence(RecurrenceInfo.create(AddRecurrenceInfo.create(SimpleRepeatingRule.createFromFrequencyAndInterval("DAI", IntervalRule.create(1)))));
    InvitationInfo invite = new InvitationInfo();
    invite.setInviteComponent(inviteComp);
    EmailAddrInfo attendeeAddr = EmailAddrInfo.createForAddressPersonalAndAddressType(attendeeBox.getName(), getCN(attendeeBox), "t");
    EmailAddrInfo attendeeAddr2 = EmailAddrInfo.createForAddressPersonalAndAddressType(attendee2Box.getName(), getCN(attendee2Box), "t");
    MimePartInfo mimePart = MimePartInfo.createForContentType("multipart/alternative");
    mimePart.addMimePart(MimePartInfo.createForContentTypeAndContent("text/plain", "invite body"));
    mimePart.addMimePart(MimePartInfo.createForContentTypeAndContent("text/html", "<html><body><p><b>invite</b> body</p></body></html>"));
    Msg msg = new Msg();
    msg.setFolderId("10");
    msg.setInvite(invite);
    msg.addEmailAddress(attendeeAddr);
    msg.addEmailAddress(attendeeAddr2);
    msg.setSubject(subject);
    msg.setMimePart(mimePart);
    CreateAppointmentRequest createSeriesRequest = CreateAppointmentRequest.create(msg);
    CreateAppointmentResponse caResp = organizerBox.invokeJaxb(createSeriesRequest);
    Assert.assertNotNull("JAXB CreateAppointmentResponse object", caResp);
    Assert.assertNotNull("JAXB CreateAppointmentResponse calItemId", caResp.getCalItemId());
    Assert.assertNotNull("JAXB CreateAppointmentResponse invId", caResp.getCalInvId());
    Assert.assertNotNull("JAXB CreateAppointmentResponse modified sequence ms", caResp.getModifiedSequence());
    Assert.assertNotNull("JAXB CreateAppointmentResponse rev", caResp.getRevision());
    ZMessage seriesInviteMsg = TestUtil.waitForMessage(attendeeBox, subject);
    Assert.assertNotNull("ZMessage for series invite", seriesInviteMsg);
    ZInvite seriesInvite = seriesInviteMsg.getInvite();
    Assert.assertNotNull("ZInvite for series invite", seriesInvite);
    // User 1 accepts the daily meeting
    ZMessage seriesAcceptMsg = sendInviteReplyToSeries(attendeeBox, organizerBox, seriesInviteMsg.getId(), subject, "ACCEPT");
    Assert.assertNotNull("ZMessage for series accept", seriesAcceptMsg);
    // User 1 declines one instance of the daily meeting
    SendInviteReplyRequest sirReq = new SendInviteReplyRequest(seriesInviteMsg.getId(), 0, /* componentNum */
    "DECLINE");
    sirReq.setIdentityId(attendeeBox.getAccountInfo(false).getId());
    sirReq.setExceptionId(DtTimeInfo.createForDatetimeAndZone("20161011T130000", "Europe/London"));
    sirReq.setUpdateOrganizer(true);
    attendeeAddr.setAddressType("f");
    mimePart = MimePartInfo.createForContentType("multipart/alternative");
    mimePart.addMimePart(MimePartInfo.createForContentTypeAndContent("text/plain", "I won't attend on Tuesday, October 11, 2016."));
    mimePart.addMimePart(MimePartInfo.createForContentTypeAndContent("text/html", "<html><body><p><b>I won't attend  on Tuesday, October 11, 2016</b></p></body></html>"));
    msg = new Msg();
    msg.setReplyType("r");
    msg.setIdentityId(attendeeBox.getAccountInfo(false).getId());
    EmailAddrInfo orgAddr = EmailAddrInfo.createForAddressPersonalAndAddressType(organizerBox.getName(), organizerBox.getName(), "t");
    msg.addEmailAddress(orgAddr);
    msg.addEmailAddress(attendeeAddr);
    String declineSubject = "Decline: " + subject;
    msg.setSubject(declineSubject);
    msg.setMimePart(mimePart);
    sirReq.setMsg(msg);
    SendInviteReplyResponse sirResp = attendeeBox.invokeJaxb(sirReq);
    Assert.assertNotNull("JAXB SendInviteReplyResponse object", sirResp);
    ZMessage instanceDeclineMsg = TestUtil.waitForMessage(organizerBox, String.format("subject:\"%s\"", declineSubject));
    Assert.assertNotNull("ZMessage for series accept", instanceDeclineMsg);
    seriesInviteMsg = TestUtil.waitForMessage(attendee2Box, subject);
    Assert.assertNotNull("ZMessage for series invite", seriesInviteMsg);
    seriesInvite = seriesInviteMsg.getInvite();
    Assert.assertNotNull("ZInvite for series invite", seriesInvite);
    // User 2 tentatively accepts the daily meeting
    ZMessage seriesTentativeMsg = sendInviteReplyToSeries(attendee2Box, organizerBox, seriesInviteMsg.getId(), subject, "TENTATIVE");
    Assert.assertNotNull("ZMessage for series tentative", seriesTentativeMsg);
    // Search for the organizer's calendar entry
    SearchRequest sReq = new SearchRequest();
    sReq.setSearchTypes(ZSearchParams.TYPE_APPOINTMENT);
    sReq.setCalItemExpandStart(ymdStringToDate("2016-10-09"));
    sReq.setCalItemExpandEnd(ymdStringToDate("2016-10-14"));
    sReq.setQuery((String.format("in:Calendar and subject:%s", subject)));
    SearchResponse sResp = organizerBox.invokeJaxb(sReq);
    List<SearchHit> hits = sResp.getSearchHits();
    Assert.assertNotNull("Organizer calendar Search hits at end", hits);
    Assert.assertEquals("Num Organizer calendar hits at end", 1, hits.size());
    SearchHit orgCalHit = hits.get(0);
    Assert.assertTrue(orgCalHit instanceof AppointmentHitInfo);
    AppointmentHitInfo orgApptHit = (AppointmentHitInfo) orgCalHit;
    String seriesInviteId = orgApptHit.getInvId();
    Assert.assertNotNull("Organizer Calendar at end - series invite id", seriesInviteId);
    List<InstanceDataInfo> instances = orgApptHit.getInstances();
    Assert.assertNotNull("Organizer Calendar at end - instances in expansion", instances);
    Assert.assertEquals("Organizer Calendar at end - number of instances in expansion", 5, instances.size());
    // The third entry in the list should be for the exception
    String exceptionInviteId = instances.get(2).getInvId();
    Assert.assertNotNull("Organizer Calendar at end - exception invite id", exceptionInviteId);
    String exceptionRidZ = instances.get(2).getRecurIdZ();
    Assert.assertNotNull("Organizer Calendar at end - exception invite RecurIdZ", exceptionRidZ);
    // Do a GetMsg for the exception in the Organizer's calendar
    MsgSpec gmeMsgSpec = new MsgSpec(exceptionInviteId);
    gmeMsgSpec.setRecurIdZ(exceptionRidZ);
    GetMsgRequest gmeReq = new GetMsgRequest(gmeMsgSpec);
    GetMsgResponse gmeResp = organizerBox.invokeJaxb(gmeReq);
    List<InviteComponentWithGroupInfo> eInviteComps = gmeResp.getMsg().getInvite().getInviteComponents();
    Assert.assertEquals("Organizer Calendar at end - number of components in exception", 1, eInviteComps.size());
    List<CalendarAttendeeWithGroupInfo> eAttendees = eInviteComps.get(0).getAttendees();
    Assert.assertEquals("Organizer Calendar at end - number of attendees in exception", 2, eAttendees.size());
    for (CalendarAttendeeWithGroupInfo eAttendee : eAttendees) {
        String addr = eAttendee.getAddress();
        String ptst = eAttendee.getPartStat();
        if (addr.equals(attendeeBox.getName())) {
            Assert.assertEquals("exception attendee1 partstat", "DE", ptst);
        } else if (addr.equals(attendee2Box.getName())) {
            Assert.assertEquals("exception attendee2 partstat", "TE", ptst);
        } else {
            Assert.fail(String.format("Unexpected attendee in exception [%s]", addr));
        }
    }
    // Do a GetMsg for the series in the Organizer's calendar
    MsgSpec gmsMsgSpec = new MsgSpec(seriesInviteId);
    GetMsgRequest gmsReq = new GetMsgRequest(gmsMsgSpec);
    GetMsgResponse gmsResp = organizerBox.invokeJaxb(gmsReq);
    List<InviteComponentWithGroupInfo> sInviteComps = gmsResp.getMsg().getInvite().getInviteComponents();
    Assert.assertEquals("Organizer Calendar at end - number of components in series", 1, sInviteComps.size());
    List<CalendarAttendeeWithGroupInfo> sAttendees = sInviteComps.get(0).getAttendees();
    Assert.assertEquals("Organizer Calendar at end - number of attendees in exception", 2, sAttendees.size());
    for (CalendarAttendeeWithGroupInfo sAttendee : sAttendees) {
        String addr = sAttendee.getAddress();
        String ptst = sAttendee.getPartStat();
        if (addr.equals(attendeeBox.getName())) {
            Assert.assertEquals("exception attendee1 partstat", "AC", ptst);
        } else if (addr.equals(attendee2Box.getName())) {
            Assert.assertEquals("exception attendee2 partstat", "TE", ptst);
        } else {
            Assert.fail(String.format("Unexpected attendee in exception [%s]", addr));
        }
    }
}
Also used : ZMessage(com.zimbra.client.ZMessage) SearchRequest(com.zimbra.soap.mail.message.SearchRequest) CreateAppointmentRequest(com.zimbra.soap.mail.message.CreateAppointmentRequest) ZInvite(com.zimbra.client.ZInvite) SearchHit(com.zimbra.soap.type.SearchHit) InvitationInfo(com.zimbra.soap.mail.type.InvitationInfo) CreateAppointmentResponse(com.zimbra.soap.mail.message.CreateAppointmentResponse) SendInviteReplyRequest(com.zimbra.soap.mail.message.SendInviteReplyRequest) CalendarAttendeeWithGroupInfo(com.zimbra.soap.mail.type.CalendarAttendeeWithGroupInfo) ZMailbox(com.zimbra.client.ZMailbox) EmailAddrInfo(com.zimbra.soap.mail.type.EmailAddrInfo) GetMsgResponse(com.zimbra.soap.mail.message.GetMsgResponse) MimePartInfo(com.zimbra.soap.mail.type.MimePartInfo) InstanceDataInfo(com.zimbra.soap.mail.type.InstanceDataInfo) InviteComponentWithGroupInfo(com.zimbra.soap.mail.type.InviteComponentWithGroupInfo) Msg(com.zimbra.soap.mail.type.Msg) SendInviteReplyResponse(com.zimbra.soap.mail.message.SendInviteReplyResponse) GetMsgRequest(com.zimbra.soap.mail.message.GetMsgRequest) MsgSpec(com.zimbra.soap.mail.type.MsgSpec) AppointmentHitInfo(com.zimbra.soap.mail.type.AppointmentHitInfo) InviteComponent(com.zimbra.soap.mail.type.InviteComponent) SearchResponse(com.zimbra.soap.mail.message.SearchResponse) Test(org.junit.Test)

Example 2 with InstanceDataInfo

use of com.zimbra.soap.mail.type.InstanceDataInfo in project zm-mailbox by Zimbra.

the class JaxbToJsonTest method bug61264AttributeDispositionCONTENThandling.

/**
 * the element referenced MailConstants.E_FRAG is treated in XML as an element with content but no attributes.
 * However in JSON, it is just treated like an ordinary attribute.
 * So, in JSON we DO want:
 *    "fr": "Here is some wonderful text and some more",
 * We do NOT want it to be treated as if it was an element which would look like:
 *    "fr": [{
 *           "_content": "Here is some wonderful text and some more"
 *         }],
 */
@Test
public void bug61264AttributeDispositionCONTENThandling() throws Exception {
    StringBuilder sb;
    final String uid = "uidString";
    final String frag = "Fragment text";
    final String name = "name Attribute";
    // From stacktrace of where the SOAP response gets assembled:
    // at com.zimbra.common.soap.Element.output(Element.java:432)
    // at com.zimbra.soap.SoapServlet.sendResponse(SoapServlet.java:349)
    // at com.zimbra.soap.SoapServlet.doWork(SoapServlet.java:307)
    // at com.zimbra.soap.SoapServlet.doPost(SoapServlet.java:206)
    // Bug 61264 is about issues with code that used JAXB which replaced code in GetCalendarItemSummaries
    // which started with an element created using:
    // calItemElem = lc.createElement(isAppointment ? MailConstants.E_APPOINTMENT : MailConstants.E_TASK);
    // At present, that code has been reverted to be element based.
    // For comparison purposes, create an JSONElement tree and a XMLElement tree
    Element jsoncalItemElem = JSONElement.mFactory.createElement(MailConstants.E_APPOINTMENT);
    jsoncalItemElem.addAttribute(MailConstants.A_UID, uid);
    jsoncalItemElem.addAttribute("x_uid", uid);
    Element instElt = jsoncalItemElem.addNonUniqueElement(MailConstants.E_INSTANCE);
    instElt.addAttribute(MailConstants.E_FRAG, frag, Element.Disposition.CONTENT);
    instElt.addAttribute(MailConstants.A_CAL_IS_EXCEPTION, true);
    instElt.addAttribute(MailConstants.A_NAME, name);
    Element xmlcalItemElem = XMLElement.mFactory.createElement(MailConstants.E_APPOINTMENT);
    xmlcalItemElem.addAttribute(MailConstants.A_UID, uid);
    xmlcalItemElem.addAttribute("x_uid", uid);
    Element xmlinstElt = xmlcalItemElem.addNonUniqueElement(MailConstants.E_INSTANCE);
    xmlinstElt.addAttribute(MailConstants.E_FRAG, frag, Element.Disposition.CONTENT);
    xmlinstElt.addAttribute(MailConstants.A_CAL_IS_EXCEPTION, true);
    xmlinstElt.addAttribute(MailConstants.A_NAME, name);
    CalendaringDataInterface calData = null;
    calData = new AppointmentData(uid, uid);
    InstanceDataInfo instance = new InstanceDataInfo();
    calData.addCalendaringInstance(instance);
    instance.setIsException(true);
    instance.setName(name);
    instance.setFragment(frag);
    Element jsonJaxbElem = JaxbUtil.jaxbToNamedElement(MailConstants.E_APPOINTMENT, MailConstants.NAMESPACE_STR, calData, JSONElement.mFactory);
    Element xmlJaxbElem = JaxbUtil.jaxbToNamedElement(MailConstants.E_APPOINTMENT, MailConstants.NAMESPACE_STR, calData, XMLElement.mFactory);
    // As AppointmentData doesn't have an XmlRootElement, this gives a poor choice for the root name.
    // Element jacksonJaxbElem = JacksonUtil.jaxbToJSONElement(calData);
    // This is probably a closer analog to JSONElement.mFactory.createElement(MailConstants.E_APPOINTMENT);
    // Element jacksonJaxbElem = JacksonUtil.jaxbToJSONElement(calData, new QName("appt", null));
    Element jacksonJaxbElem = JacksonUtil.jaxbToJSONElement(calData, new QName(MailConstants.E_APPOINTMENT, MailConstants.NAMESPACE));
    Element parent4legacyJson = JSONElement.mFactory.createElement(new QName("legacy-json", MailConstants.NAMESPACE));
    Element parent4jackson = JSONElement.mFactory.createElement(new QName("jacksonjson", MailConstants.NAMESPACE));
    parent4legacyJson.addNonUniqueElement(jsoncalItemElem);
    parent4jackson.addNonUniqueElement(jacksonJaxbElem);
    sb = new StringBuilder();
    xmlcalItemElem.output(sb);
    logDebug("bug61264 - XML from XMLElement\n%1$s", sb.toString());
    sb = new StringBuilder();
    xmlJaxbElem.output(sb);
    logDebug("bug61264 - XML from JAXB\n%1$s", sb.toString());
    // something that is appendable for Element.out(Appendable) to play with
    sb = new StringBuilder();
    jsoncalItemElem.output(sb);
    String jsonFromElement = sb.toString();
    logDebug("bug61264 - JSON from JSONElement\n%1$s", jsonFromElement);
    sb = new StringBuilder();
    jsonJaxbElem.output(sb);
    logDebug("bug61264 - JSON from JAXB\n%1$s", sb.toString());
    sb = new StringBuilder();
    jacksonJaxbElem.output(sb);
    logDebug("bug61264 - JSON from JAXB using Jackson\n%1$s", sb.toString());
    sb = new StringBuilder();
    parent4legacyJson.output(sb);
    logDebug("bug61264 - JSON from JAXB child using Jackson\n%1$s", sb.toString());
    sb = new StringBuilder();
    parent4jackson.output(sb);
    logDebug("bug61264 - JSON from JSONElement child\n%1$s", sb.toString());
    Assert.assertEquals("UID", uid, jacksonJaxbElem.getAttribute(MailConstants.A_UID));
    Assert.assertEquals("x_uid", uid, jacksonJaxbElem.getAttribute("x_uid"));
    Element instE = jacksonJaxbElem.getElement(MailConstants.E_INSTANCE);
    Assert.assertNotNull("instance elem", instE);
    Assert.assertEquals("fragment", frag, instE.getAttribute(MailConstants.E_FRAG));
    Assert.assertTrue("is exception", instE.getAttributeBool(MailConstants.A_CAL_IS_EXCEPTION));
    Assert.assertEquals("name", name, instE.getAttribute(MailConstants.A_NAME));
}
Also used : QName(org.dom4j.QName) XmlAnyElement(javax.xml.bind.annotation.XmlAnyElement) Element(com.zimbra.common.soap.Element) XMLElement(com.zimbra.common.soap.Element.XMLElement) JSONElement(com.zimbra.common.soap.Element.JSONElement) XmlElement(javax.xml.bind.annotation.XmlElement) CalendaringDataInterface(com.zimbra.soap.mail.type.CalendaringDataInterface) AppointmentData(com.zimbra.soap.mail.type.AppointmentData) InstanceDataInfo(com.zimbra.soap.mail.type.InstanceDataInfo) FilterTest(com.zimbra.soap.mail.type.FilterTest) Test(org.junit.Test)

Example 3 with InstanceDataInfo

use of com.zimbra.soap.mail.type.InstanceDataInfo in project zm-mailbox by Zimbra.

the class TestJaxb method acceptAndTentativeSeriesDeclineInstanceAcceptInstance.

/**
 * Bug 94018.  Accepting series, then declining single instance leads to inconsistent display of attendee
 * status for organizer copy for the declined instance.
 *
 * Pseudo exceptions should be created for each reply to an individual instance of the series.
 *
 * At the end of this, check that exceptions have been created.  Check that the exceptions register
 * the correct statuses for the users.
 */
@Test
public void acceptAndTentativeSeriesDeclineInstanceAcceptInstance() throws Exception {
    TestUtil.createAccount(ORGANIZER);
    TestUtil.createAccount(ATTENDEE1);
    TestUtil.createAccount(ATTENDEE2);
    String subject = NAME_PREFIX + " every 2 days";
    ZMailbox organizerZMbox = TestUtil.getZMailbox(ORGANIZER);
    ZMailbox attendee1ZMbox = TestUtil.getZMailbox(ATTENDEE1);
    ZMailbox attendee2ZMbox = TestUtil.getZMailbox(ATTENDEE2);
    String londonTZ = "Europe/London";
    int year = Calendar.getInstance().get(Calendar.YEAR) + 1;
    // Create and send meeting that occurs every 2 days
    InviteComponent inviteComp = createInviteComponentSkeleton(subject, "room 101", organizerZMbox, attendee1ZMbox, attendee2ZMbox);
    GregorianCalendar start = startTime(londonTZ, year, 1, /* February */
    2, /* day */
    14, /* hour */
    0);
    GregorianCalendar end = plus(start, Calendar.MINUTE, 30);
    setStartAndEnd(inviteComp, londonTZ, start, end);
    inviteComp.setRecurrence(recurrence("DAI", 2, /* every 2 days */
    String.format("%d0529", year)));
    sendMeetingRequest(organizerZMbox, createMsgForAppointmentRequest(subject, inviteComp, attendee1ZMbox, attendee2ZMbox));
    // attendee 1 wait for original invite
    ZMessage seriesMsg = waitForInvite(attendee1ZMbox, subject);
    // attendee 1 accepts the original invite to the whole series
    sendInviteReplyAndWaitForIt(attendee1ZMbox, organizerZMbox, seriesMsg.getId(), subject, "ACCEPT", null);
    // attendee 1 declines one instance of the daily meeting - 2 + 4 --> 6th Feb
    GregorianCalendar exceptionTime = plus(start, Calendar.DAY_OF_MONTH, 4);
    sendInviteReplyAndWaitForIt(attendee1ZMbox, organizerZMbox, seriesMsg.getId(), subject, "DECLINE", DtTimeInfo.createForDatetimeAndZone(dateTime(exceptionTime), londonTZ));
    // attendee 2 wait for original invite
    seriesMsg = waitForInvite(attendee2ZMbox, subject);
    // attendee 2 tentatively accepts the original invite to the whole series
    sendInviteReplyAndWaitForIt(attendee2ZMbox, organizerZMbox, seriesMsg.getId(), subject, "TENTATIVE", null);
    // attendee 2 declines one instance of the daily meeting 2 + 8 --> 10th Feb
    GregorianCalendar exceptionTime2 = plus(start, Calendar.DAY_OF_MONTH, 8);
    sendInviteReplyAndWaitForIt(attendee2ZMbox, organizerZMbox, seriesMsg.getId(), subject + " " + ATTENDEE2, "DECLINE", DtTimeInfo.createForDatetimeAndZone(dateTime(exceptionTime2), londonTZ));
    // Search for a range of instances of the organizer's calendar entry
    SearchRequest sReq = new SearchRequest();
    sReq.setSearchTypes(ZSearchParams.TYPE_APPOINTMENT);
    /* 2nd Feb + 1 --> 3rd, 2nd Feb + 13 --> 15th.  So should match instances on:
         *     4th, 6th, 8th, 10th, 12th, 14th. */
    List<AppointmentHitInfo> apptHits = findMatchingExpandedAppointments(organizerZMbox, plus(start, Calendar.DAY_OF_MONTH, 1).getTime(), plus(start, Calendar.DAY_OF_MONTH, 13).getTime(), String.format("in:Calendar and subject:%s", subject), 1);
    AppointmentHitInfo orgApptHit = apptHits.get(0);
    Assert.assertNotNull("Organizer Calendar at end - series invite id", orgApptHit.getInvId());
    List<InstanceDataInfo> instances = orgApptHit.getInstances();
    Assert.assertNotNull("Organizer Calendar at end - instances in expansion", instances);
    Assert.assertEquals("Organizer Calendar at end - number of instances in expansion", 6, instances.size());
    // The 2nd entry in the list should be for an exception
    Map<ZMailbox, String> partstatMap = new HashMap<>(2);
    partstatMap.put(attendee1ZMbox, ZAppointmentHit.PSTATUS_DECLINED);
    /* for this instance */
    partstatMap.put(attendee2ZMbox, ZAppointmentHit.PSTATUS_TENTATIVE);
    /* for the series */
    validateException(organizerZMbox, instances.get(1), partstatMap, exceptionTime);
    // The 4th entry in the list should also be for an exception
    partstatMap.put(attendee1ZMbox, ZAppointmentHit.PSTATUS_ACCEPT);
    /* for the series */
    partstatMap.put(attendee2ZMbox, ZAppointmentHit.PSTATUS_DECLINED);
    /* for the instance */
    validateException(organizerZMbox, instances.get(3), partstatMap, exceptionTime2);
    // Do a GetMsg for the series in the Organizer's calendar
    MsgSpec gmsMsgSpec = new MsgSpec(orgApptHit.getInvId());
    GetMsgRequest gmsReq = new GetMsgRequest(gmsMsgSpec);
    GetMsgResponse gmsResp = organizerZMbox.invokeJaxb(gmsReq);
    List<InviteComponentWithGroupInfo> sInviteComps = gmsResp.getMsg().getInvite().getInviteComponents();
    Assert.assertEquals("number of components in series", 1, sInviteComps.size());
    List<CalendarAttendeeWithGroupInfo> sAttendees = sInviteComps.get(0).getAttendees();
    Assert.assertEquals("number of attendees in exception", 2, sAttendees.size());
    for (CalendarAttendeeWithGroupInfo sAttendee : sAttendees) {
        String addr = sAttendee.getAddress();
        String ptst = sAttendee.getPartStat();
        if (addr.equals(attendee1ZMbox.getName())) {
            Assert.assertEquals("exception attendee1 partstat", ZAppointmentHit.PSTATUS_ACCEPT, ptst);
        } else if (addr.equals(attendee2ZMbox.getName())) {
            Assert.assertEquals("exception attendee2 partstat", ZAppointmentHit.PSTATUS_TENTATIVE, ptst);
        } else {
            Assert.fail(String.format("Unexpected attendee in exception [%s]", addr));
        }
    }
}
Also used : ZMessage(com.zimbra.client.ZMessage) SearchRequest(com.zimbra.soap.mail.message.SearchRequest) HashMap(java.util.HashMap) GetMsgRequest(com.zimbra.soap.mail.message.GetMsgRequest) GregorianCalendar(java.util.GregorianCalendar) MsgSpec(com.zimbra.soap.mail.type.MsgSpec) AppointmentHitInfo(com.zimbra.soap.mail.type.AppointmentHitInfo) InviteComponent(com.zimbra.soap.mail.type.InviteComponent) CalendarAttendeeWithGroupInfo(com.zimbra.soap.mail.type.CalendarAttendeeWithGroupInfo) ZMailbox(com.zimbra.client.ZMailbox) GetMsgResponse(com.zimbra.soap.mail.message.GetMsgResponse) InstanceDataInfo(com.zimbra.soap.mail.type.InstanceDataInfo) InviteComponentWithGroupInfo(com.zimbra.soap.mail.type.InviteComponentWithGroupInfo) Test(org.junit.Test)

Example 4 with InstanceDataInfo

use of com.zimbra.soap.mail.type.InstanceDataInfo in project zm-mailbox by Zimbra.

the class JaxbToJsonTest method bug61264_AttributeDispositionCONTENThandling.

/**
     * the element referenced MailConstants.E_FRAG is treated in XML as an element with content but no attributes.
     * However in JSON, it is just treated like an ordinary attribute.
     * So, in JSON we DO want:
     *    "fr": "Here is some wonderful text and some more",
     * We do NOT want it to be treated as if it was an element which would look like:
     *    "fr": [{
     *           "_content": "Here is some wonderful text and some more"
     *         }],
     */
@Test
public void bug61264_AttributeDispositionCONTENThandling() throws Exception {
    StringBuilder sb;
    final String uid = "uidString";
    final String frag = "Fragment text";
    final String name = "name Attribute";
    // From stacktrace of where the SOAP response gets assembled:
    //     at com.zimbra.common.soap.Element.output(Element.java:432)
    //     at com.zimbra.soap.SoapServlet.sendResponse(SoapServlet.java:349)
    //     at com.zimbra.soap.SoapServlet.doWork(SoapServlet.java:307)
    //     at com.zimbra.soap.SoapServlet.doPost(SoapServlet.java:206)
    // Bug 61264 is about issues with code that used JAXB which replaced code in GetCalendarItemSummaries
    // which started with an element created using:
    //     calItemElem = lc.createElement(isAppointment ? MailConstants.E_APPOINTMENT : MailConstants.E_TASK);
    // At present, that code has been reverted to be element based.
    // For comparison purposes, create an JSONElement tree and a XMLElement tree
    Element jsoncalItemElem = JSONElement.mFactory.createElement(MailConstants.E_APPOINTMENT);
    jsoncalItemElem.addAttribute(MailConstants.A_UID, uid);
    jsoncalItemElem.addAttribute("x_uid", uid);
    Element instElt = jsoncalItemElem.addElement(MailConstants.E_INSTANCE);
    instElt.addAttribute(MailConstants.E_FRAG, frag, Element.Disposition.CONTENT);
    instElt.addAttribute(MailConstants.A_CAL_IS_EXCEPTION, true);
    instElt.addAttribute(MailConstants.A_NAME, name);
    Element xmlcalItemElem = XMLElement.mFactory.createElement(MailConstants.E_APPOINTMENT);
    xmlcalItemElem.addAttribute(MailConstants.A_UID, uid);
    xmlcalItemElem.addAttribute("x_uid", uid);
    Element xmlinstElt = xmlcalItemElem.addElement(MailConstants.E_INSTANCE);
    xmlinstElt.addAttribute(MailConstants.E_FRAG, frag, Element.Disposition.CONTENT);
    xmlinstElt.addAttribute(MailConstants.A_CAL_IS_EXCEPTION, true);
    xmlinstElt.addAttribute(MailConstants.A_NAME, name);
    CalendaringDataInterface calData = null;
    calData = new AppointmentData(uid, uid);
    InstanceDataInfo instance = new InstanceDataInfo();
    calData.addCalendaringInstance(instance);
    instance.setIsException(true);
    instance.setName(name);
    instance.setFragment(frag);
    Element jsonJaxbElem = JaxbUtil.jaxbToNamedElement(MailConstants.E_APPOINTMENT, MailConstants.NAMESPACE_STR, calData, JSONElement.mFactory);
    Element xmlJaxbElem = JaxbUtil.jaxbToNamedElement(MailConstants.E_APPOINTMENT, MailConstants.NAMESPACE_STR, calData, XMLElement.mFactory);
    // As AppointmentData doesn't have an XmlRootElement, this gives a poor choice for the root name.
    //     Element jacksonJaxbElem = JacksonUtil.jaxbToJSONElement(calData);
    // This is probably a closer analog to JSONElement.mFactory.createElement(MailConstants.E_APPOINTMENT);
    //     Element jacksonJaxbElem = JacksonUtil.jaxbToJSONElement(calData, new QName("appt", null));
    Element jacksonJaxbElem = JacksonUtil.jaxbToJSONElement(calData, new QName(MailConstants.E_APPOINTMENT, MailConstants.NAMESPACE));
    Element parent4legacyJson = JSONElement.mFactory.createElement(new QName("legacy-json", MailConstants.NAMESPACE));
    Element parent4jackson = JSONElement.mFactory.createElement(new QName("jacksonjson", MailConstants.NAMESPACE));
    parent4legacyJson.addElement(jsoncalItemElem);
    parent4jackson.addElement(jacksonJaxbElem);
    sb = new StringBuilder();
    xmlcalItemElem.output(sb);
    logDebug("bug61264 - XML from XMLElement\n%1$s", sb.toString());
    sb = new StringBuilder();
    xmlJaxbElem.output(sb);
    logDebug("bug61264 - XML from JAXB\n%1$s", sb.toString());
    // something that is appendable for Element.out(Appendable) to play with
    sb = new StringBuilder();
    jsoncalItemElem.output(sb);
    String jsonFromElement = sb.toString();
    logDebug("bug61264 - JSON from JSONElement\n%1$s", jsonFromElement);
    sb = new StringBuilder();
    jsonJaxbElem.output(sb);
    logDebug("bug61264 - JSON from JAXB\n%1$s", sb.toString());
    sb = new StringBuilder();
    jacksonJaxbElem.output(sb);
    logDebug("bug61264 - JSON from JAXB using Jackson\n%1$s", sb.toString());
    sb = new StringBuilder();
    parent4legacyJson.output(sb);
    logDebug("bug61264 - JSON from JAXB child using Jackson\n%1$s", sb.toString());
    sb = new StringBuilder();
    parent4jackson.output(sb);
    logDebug("bug61264 - JSON from JSONElement child\n%1$s", sb.toString());
    Assert.assertEquals("UID", uid, jacksonJaxbElem.getAttribute(MailConstants.A_UID));
    Assert.assertEquals("x_uid", uid, jacksonJaxbElem.getAttribute("x_uid"));
    Element instE = jacksonJaxbElem.getElement(MailConstants.E_INSTANCE);
    Assert.assertNotNull("instance elem", instE);
    Assert.assertEquals("fragment", frag, instE.getAttribute(MailConstants.E_FRAG));
    Assert.assertTrue("is exception", instE.getAttributeBool(MailConstants.A_CAL_IS_EXCEPTION));
    Assert.assertEquals("name", name, instE.getAttribute(MailConstants.A_NAME));
}
Also used : QName(org.dom4j.QName) XmlAnyElement(javax.xml.bind.annotation.XmlAnyElement) Element(com.zimbra.common.soap.Element) XMLElement(com.zimbra.common.soap.Element.XMLElement) JSONElement(com.zimbra.common.soap.Element.JSONElement) XmlElement(javax.xml.bind.annotation.XmlElement) CalendaringDataInterface(com.zimbra.soap.mail.type.CalendaringDataInterface) AppointmentData(com.zimbra.soap.mail.type.AppointmentData) InstanceDataInfo(com.zimbra.soap.mail.type.InstanceDataInfo) FilterTest(com.zimbra.soap.mail.type.FilterTest) Test(org.junit.Test)

Aggregations

InstanceDataInfo (com.zimbra.soap.mail.type.InstanceDataInfo)4 Test (org.junit.Test)4 ZMailbox (com.zimbra.client.ZMailbox)2 ZMessage (com.zimbra.client.ZMessage)2 Element (com.zimbra.common.soap.Element)2 JSONElement (com.zimbra.common.soap.Element.JSONElement)2 XMLElement (com.zimbra.common.soap.Element.XMLElement)2 GetMsgRequest (com.zimbra.soap.mail.message.GetMsgRequest)2 GetMsgResponse (com.zimbra.soap.mail.message.GetMsgResponse)2 SearchRequest (com.zimbra.soap.mail.message.SearchRequest)2 AppointmentData (com.zimbra.soap.mail.type.AppointmentData)2 AppointmentHitInfo (com.zimbra.soap.mail.type.AppointmentHitInfo)2 CalendarAttendeeWithGroupInfo (com.zimbra.soap.mail.type.CalendarAttendeeWithGroupInfo)2 CalendaringDataInterface (com.zimbra.soap.mail.type.CalendaringDataInterface)2 FilterTest (com.zimbra.soap.mail.type.FilterTest)2 InviteComponent (com.zimbra.soap.mail.type.InviteComponent)2 InviteComponentWithGroupInfo (com.zimbra.soap.mail.type.InviteComponentWithGroupInfo)2 MsgSpec (com.zimbra.soap.mail.type.MsgSpec)2 XmlAnyElement (javax.xml.bind.annotation.XmlAnyElement)2 XmlElement (javax.xml.bind.annotation.XmlElement)2