Search in sources :

Example 11 with JSONElement

use of com.zimbra.common.soap.Element.JSONElement in project zm-mailbox by Zimbra.

the class JaxbToJsonTest method missingRequiredStringElem.

/**
 * Permissive handling - if required things are not present, users need to handle this
 */
@Test
public void missingRequiredStringElem() throws Exception {
    final String attr1Val = "My attribute ONE";
    StringAttrStringElem tstr = new StringAttrStringElem();
    tstr.setAttr1(attr1Val);
    // tstr.setElem1(elem1Val);
    Element jsonJaxbElem = JacksonUtil.jaxbToJSONElement(tstr);
    logDebug("JSONElement from JAXB ---> prettyPrint\n%1$s", jsonJaxbElem.prettyPrint());
    StringAttrStringElem roundtripped = JaxbUtil.elementToJaxb(jsonJaxbElem, StringAttrStringElem.class);
    Assert.assertEquals("JSONElement attr1", attr1Val, jsonJaxbElem.getAttribute("attribute-1"));
    try {
        jsonJaxbElem.getElement("element1");
    } catch (ServiceException svcE) {
        Assert.assertEquals("JSONElement exception when getting missing item:", ServiceException.INVALID_REQUEST, svcE.getCode());
    }
    Assert.assertEquals("roundtripped attr1", attr1Val, roundtripped.getAttr1());
    Assert.assertEquals("roundtripped elem1", null, roundtripped.getElem1());
}
Also used : StringAttrStringElem(com.zimbra.soap.jaxb.StringAttrStringElem) ServiceException(com.zimbra.common.service.ServiceException) 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) FilterTest(com.zimbra.soap.mail.type.FilterTest) Test(org.junit.Test)

Example 12 with JSONElement

use of com.zimbra.common.soap.Element.JSONElement in project zm-mailbox by Zimbra.

the class JaxbToJsonTest method xmlValueAnnotation.

/**
 * XmlValue should map to an attribute with name "_content"
 * At present, classes that want this feature need the annotation @JsonProperty("_content"),
 * otherwise, the name "value" is used.
 *    "chunk": [ { "disp": "disposition 1", "_content": "text 1\nIn the sun" },
 *               { "disp": "disPosition 2", "_content": "text 2" }],
 */
@Test
public void xmlValueAnnotation() throws Exception {
    String dispos1 = "disposition 1";
    String text1 = "text 1\nIn the sun";
    String dispos2 = "disPosition 2";
    String text2 = "text 2";
    // ---------------------------------  For Comparison - Element handling where the JAXB has an @XmlValue
    Element legacyElem = JSONElement.mFactory.createElement(MailConstants.DIFF_DOCUMENT_RESPONSE);
    legacyElem.addNonUniqueElement(MailConstants.E_CHUNK).addAttribute(MailConstants.A_DISP, dispos1).setText(text1);
    legacyElem.addNonUniqueElement(MailConstants.E_CHUNK).addAttribute(MailConstants.A_DISP, dispos2).setText(text2);
    logDebug("DiffDocumentResponse JSONElement ---> prettyPrint\n%1$s", legacyElem.prettyPrint());
    // --------------------------------- @XmlValue handling test - need @JsonProperty("_content") annotation
    DiffDocumentResponse ddResp = new DiffDocumentResponse();
    ddResp.addChunk(DispositionAndText.create(dispos1, text1));
    ddResp.addChunk(DispositionAndText.create(dispos2, text2));
    Element jsonJaxbElem = JacksonUtil.jaxbToJSONElement(ddResp);
    logDebug("DiffDocumentResponse JSONElement from JAXB ---> prettyPrint\n%1$s", jsonJaxbElem.prettyPrint());
    List<Element> chunks = jsonJaxbElem.listElements();
    Assert.assertEquals("Number of child elements", 2, chunks.size());
    Element chunk1 = chunks.get(0);
    Element chunk2 = chunks.get(1);
    Assert.assertEquals("1st chunk disposition", dispos1, chunk1.getAttribute(MailConstants.A_DISP));
    Assert.assertEquals("1st chunk value", text1, chunk1.getText());
    Assert.assertEquals("2nd chunk disposition", dispos2, chunk2.getAttribute(MailConstants.A_DISP));
    Assert.assertEquals("2nd chunk value", text2, chunk2.getText());
    DiffDocumentResponse roundtripped = JaxbUtil.elementToJaxb(jsonJaxbElem, DiffDocumentResponse.class);
    List<DispositionAndText> rtChunks = roundtripped.getChunks();
    Assert.assertEquals("Number of roundtripped chunks", 2, rtChunks.size());
    DispositionAndText rtChunk1 = rtChunks.get(0);
    DispositionAndText rtChunk2 = rtChunks.get(1);
    Assert.assertEquals("1st roundtripped chunk disposition", dispos1, rtChunk1.getDisposition());
    Assert.assertEquals("1st roundtripped chunk value", text1, rtChunk1.getText());
    Assert.assertEquals("2nd roundtripped chunk disposition", dispos2, rtChunk2.getDisposition());
    Assert.assertEquals("2nd roundtripped chunk value", text2, rtChunk2.getText());
}
Also used : 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) DiffDocumentResponse(com.zimbra.soap.mail.message.DiffDocumentResponse) DispositionAndText(com.zimbra.soap.mail.type.DispositionAndText) FilterTest(com.zimbra.soap.mail.type.FilterTest) Test(org.junit.Test)

Example 13 with JSONElement

use of com.zimbra.common.soap.Element.JSONElement in project zm-mailbox by Zimbra.

the class JaxbToJsonTest method zimbraKeyValuePairsAnnotation.

/**
 * Check that JSON can be deserialised into a JAXB object when some of the JSON represents Zimbra KeyValuePairs
 * (i.e. An "_attrs" array).
 * In this case, the target objects for each keyvalue pair use the defaults of "a" for the element name and
 * "n" for the attribute name in the XML form.
 * Desired XML :<br />
 * &lt;key-value-pairs-tester xmlns="urn:zimbraTest">
 *   &lt;a n="key1">value1&lt;/a>
 *   &lt;a n="key2">value2-a&lt;/a>
 *   &lt;a n="key2">value2-b&lt;/a>
 * &lt;/key-value-pairs-tester>
 *<br />
 * Desired JSON :<br />
 * {
 *   "_attrs": {
 *     "key1": "value1",
 *     "key2": [
 *       "value2-a",
 *       "value2-b"]
 *   },
 *   "_jsns": "urn:zimbraTest"
 * }
 */
@Test
public void zimbraKeyValuePairsAnnotation() throws Exception {
    Element jsonElem = JSONElement.mFactory.createElement(QName.get("key-value-pairs", "urn:zimbraTest"));
    jsonElem.addKeyValuePair("key1", "value1");
    jsonElem.addKeyValuePair("key2", "value2-a");
    jsonElem.addKeyValuePair("key2", "value2-b");
    List<KeyValuePair> attrs = Lists.newArrayList();
    attrs.add(new KeyValuePair("key1", "value1"));
    attrs.add(new KeyValuePair("key2", "value2-a"));
    attrs.add(new KeyValuePair("key2", "value2-b"));
    KeyValuePairsTester jaxb = new KeyValuePairsTester(attrs);
    logDebug("XMLElement (from JAXB) ---> prettyPrint\n%1$s", JaxbUtil.jaxbToElement(jaxb, Element.XMLElement.mFactory, true, false).prettyPrint());
    Element jsonJaxbElem = JacksonUtil.jaxbToJSONElement(jaxb);
    logDebug("JSONElement (for comparison) ---> prettyPrint\n%1$s", jsonElem.prettyPrint());
    logDebug("JSONElement from JAXB ---> prettyPrint\n%1$s", jsonJaxbElem.prettyPrint());
    KeyValuePairsTester roundtripped = JaxbUtil.elementToJaxb(jsonJaxbElem, KeyValuePairsTester.class);
    List<Element.KeyValuePair> elemKVPs = jsonJaxbElem.listKeyValuePairs();
    Assert.assertEquals("elemKVP num", 3, elemKVPs.size());
    Assert.assertEquals("prettyPrint", jsonElem.prettyPrint(), jsonJaxbElem.prettyPrint());
    List<KeyValuePair> kvps = roundtripped.getAttrList();
    Assert.assertEquals("roundtripped kvps num", 3, kvps.size());
}
Also used : KeyValuePair(com.zimbra.soap.type.KeyValuePair) 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) WrappedKeyValuePairsTester(com.zimbra.soap.jaxb.WrappedKeyValuePairsTester) KeyValuePairsTester(com.zimbra.soap.jaxb.KeyValuePairsTester) OddKeyValuePairsTester(com.zimbra.soap.jaxb.OddKeyValuePairsTester) FilterTest(com.zimbra.soap.mail.type.FilterTest) Test(org.junit.Test)

Example 14 with JSONElement

use of com.zimbra.common.soap.Element.JSONElement in project zm-mailbox by Zimbra.

the class JaxbToJsonTest method kvpForGetDLRespWithOwner.

/**
 * Ensuring that JAXB can handle having an owner in a list that is not an empty array when there are no owners
 */
@Test
public void kvpForGetDLRespWithOwner() throws Exception {
    Element jsonElem = JSONElement.mFactory.createElement(QName.get(AccountConstants.E_GET_DISTRIBUTION_LIST_RESPONSE, AccountConstants.NAMESPACE_STR));
    populateGetDlResp(jsonElem);
    Element xmlElem = XMLElement.mFactory.createElement(QName.get(AccountConstants.E_GET_DISTRIBUTION_LIST_RESPONSE, AccountConstants.NAMESPACE_STR));
    populateGetDlResp(xmlElem);
    logDebug("XmlElement (for comparison) ---> prettyPrint\n%1$s", xmlElem.prettyPrint());
    logDebug("JSONElement (for comparison) ---> prettyPrint\n%1$s", jsonElem.prettyPrint());
    List<KeyValuePair> attrs = Lists.newArrayList();
    attrs.add(new KeyValuePair("mail", "fun@example.test"));
    attrs.add(new KeyValuePair("zimbraMailStatus", "enabled"));
    DistributionListInfo dl = new DistributionListInfo("myId", "my name", null, attrs);
    dl.setDynamic(true);
    DistributionListGranteeInfo grantee = new DistributionListGranteeInfo(GranteeType.usr, "ownerId", "ownerName");
    dl.addOwner(grantee);
    GetDistributionListResponse jaxb = new GetDistributionListResponse(dl);
    Element xmlJaxbElem = JaxbUtil.jaxbToElement(jaxb, XMLElement.mFactory);
    Element jsonJaxbElem = JacksonUtil.jaxbToJSONElement(jaxb);
    GetDistributionListResponse roundtripped = JaxbUtil.elementToJaxb(jsonJaxbElem, GetDistributionListResponse.class);
    GetDistributionListResponse roundtrippedX = JaxbUtil.elementToJaxb(xmlJaxbElem, GetDistributionListResponse.class);
    logDebug("JSONElement from JAXB ---> prettyPrint\n%1$s", jsonJaxbElem.prettyPrint());
    logDebug("XMLElement from JAXB ---> prettyPrint\n%1$s", xmlJaxbElem.prettyPrint());
    List<? extends KeyValuePair> kvps = roundtripped.getDl().getAttrList();
    Assert.assertEquals("roundtripped kvps num", 2, kvps.size());
    Assert.assertEquals("roundtripped owner num", 1, roundtripped.getDl().getOwners().size());
    Assert.assertEquals("roundtrippedX owner num", 1, roundtrippedX.getDl().getOwners().size());
}
Also used : GetDistributionListResponse(com.zimbra.soap.account.message.GetDistributionListResponse) DistributionListInfo(com.zimbra.soap.account.type.DistributionListInfo) KeyValuePair(com.zimbra.soap.type.KeyValuePair) DistributionListGranteeInfo(com.zimbra.soap.account.type.DistributionListGranteeInfo) 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) FilterTest(com.zimbra.soap.mail.type.FilterTest) Test(org.junit.Test)

Example 15 with JSONElement

use of com.zimbra.common.soap.Element.JSONElement in project zm-mailbox by Zimbra.

the class JaxbUtil method fixupStructureForJaxb.

/**
 * Manipulates a structure under {@link elem} which obeys Zimbra's SOAP XML structure rules to comply with more
 * stringent JAXB rules.
 * <ol>
 * <li>Zimbra allows attributes to be specified as elements.
 * <p>One scenario where this happens - {@link XMLElement}'s {@code getAttribute(String key, String defaultValue)}
 * will look for an attribute with "key" as the name.
 * If it fails to find that, it looks for an element with "key" as the name and returns the elements text.</p></li>
 * <li>Zimbra allows elements to be specified as attributes.
 * <p>One scenario where this happens.
 * <pre>
 *      elem.addAttribute("xml-elem-json-attr", "XML elem but JSON attribute", Element.Disposition.CONTENT);
 * </pre>
 * Will be serialized to this JSON (i.e. treated as an attribute in JSON) :
 * <pre>
 *       "xml-elem-json-attr": "XML elem but JSON attribute"
 * </pre>
 * or to this XML (i.e. treated as an element in XML) :
 * <pre>
 *       &lt;xml-elem-json-attr>XML elem but JSON attribute&lt;/xml-elem-json-attr>
 * </pre>
 * In JAXB, we typically use {@link XmlElement} for the associated field.  Round tripping from XML will result in
 * an element but round tripping from JSON will result in an attribute.
 * <li>Zimbra uses key/value pairs which serialize to JSON as:
 * <pre>
 *     "_attrs":{"anID":"val","anID2":"val2"}
 * </pre>
 * If this is read into a JSONElement structure and written out as XML, you get:
 * <pre>
 *     &lt;a n="anID">val&lt;/a>&lt;a n="anID2">val2&lt;/a>
 * </pre>
 * The element name "a" and the attribute name "n" are defaults - the actual expected values can be different - so
 * we query the JAXB classes to see what they should be.
 * </ol>
 * @param klass is the JAXB class for {@code elem} which must be under the "com.zimbra" package hierarchy.
 */
private static void fixupStructureForJaxb(org.w3c.dom.Element elem, Class<?> klass) {
    if (elem == null) {
        return;
    }
    if (klass == null) {
        LOG.debug("JAXB no class associated with " + elem.getLocalName());
        return;
    }
    if (!isJaxbType(klass)) {
        return;
    }
    JaxbInfo jaxbInfo = JaxbInfo.getFromCache(klass);
    NamedNodeMap attrs = elem.getAttributes();
    int numAttrs = attrs.getLength();
    List<String> orphanAttrs = null;
    // Process each attribute
    for (int i = 0; i < numAttrs; i++) {
        Attr attr = (Attr) attrs.item(i);
        // Get attribute name and value
        String attrName = attr.getNodeName();
        if (!jaxbInfo.hasAttribute(attrName) && jaxbInfo.hasElement(attrName)) {
            if (orphanAttrs == null) {
                orphanAttrs = Lists.newArrayList();
            }
            orphanAttrs.add(attrName);
            String attrValue = attr.getNodeValue();
            elem.getNamespaceURI();
            org.w3c.dom.Element newElem = elem.getOwnerDocument().createElementNS(elem.getNamespaceURI(), attrName);
            newElem.setTextContent(attrValue);
            elem.appendChild(newElem);
        }
    }
    if (orphanAttrs != null) {
        for (String orphan : orphanAttrs) {
            attrs.removeNamedItem(orphan);
        }
    }
    NodeList list = elem.getChildNodes();
    List<org.w3c.dom.Element> orphans = null;
    for (int i = 0; i < list.getLength(); i++) {
        Node subnode = list.item(i);
        if (subnode.getNodeType() == Node.ELEMENT_NODE) {
            org.w3c.dom.Element child = (org.w3c.dom.Element) subnode;
            String childName = child.getLocalName();
            if (jaxbInfo.hasWrapperElement(childName)) {
                NodeList wrappedList = child.getChildNodes();
                for (int j = 0; j < wrappedList.getLength(); j++) {
                    Node wSubnode = wrappedList.item(j);
                    if (wSubnode.getNodeType() == Node.ELEMENT_NODE) {
                        org.w3c.dom.Element wChild = (org.w3c.dom.Element) wSubnode;
                        fixupStructureForJaxb(wChild, jaxbInfo.getClassForWrappedElement(childName, wChild.getLocalName()));
                    }
                }
            } else if (jaxbInfo.hasElement(childName)) {
                fixupStructureForJaxb(child, jaxbInfo.getClassForElement(childName));
            } else if (jaxbInfo.hasAttribute(childName)) {
                elem.setAttribute(childName, child.getTextContent());
                // Don't remove pre-existing child until later pass to avoid changing the list of child elements
                if (orphans == null) {
                    orphans = Lists.newArrayList();
                }
                orphans.add(child);
            } else if (Element.XMLElement.E_ATTRIBUTE.equals(childName)) {
                // This might be a keyvaluepair, the Element code doesn't have access to JAXB info, so defaults
                // the element name to "a" and its attribute will be "n".  If this is what has happened, replace
                // it with a corrected equivalent using the JAXB object for reference.
                JaxbInfo.KeyValuePairXmlRepresentationInfo kvpXmlRep = jaxbInfo.getKeyValuePairElementInfo();
                if (kvpXmlRep != null) {
                    elem.getNamespaceURI();
                    org.w3c.dom.Element newElem = elem.getOwnerDocument().createElementNS(elem.getNamespaceURI(), kvpXmlRep.getXmlElementName());
                    newElem.setTextContent(child.getTextContent());
                    newElem.setAttribute(kvpXmlRep.getXmlAttributeName(), child.getAttribute(Element.XMLElement.A_ATTR_NAME));
                    elem.appendChild(newElem);
                    if (orphans == null) {
                        orphans = Lists.newArrayList();
                    }
                    orphans.add(child);
                }
            } else {
                LOG.debug("JAXB class " + klass.getName() + " does NOT recognise element named:" + childName);
            }
        }
    }
    // Prune the promoted elements from the list of children
    if (orphans != null) {
        for (org.w3c.dom.Element orphan : orphans) {
            elem.removeChild(orphan);
        }
    }
}
Also used : NamedNodeMap(org.w3c.dom.NamedNodeMap) NodeList(org.w3c.dom.NodeList) Element(com.zimbra.common.soap.Element) JSONElement(com.zimbra.common.soap.Element.JSONElement) JAXBElement(javax.xml.bind.JAXBElement) XMLElement(com.zimbra.common.soap.Element.XMLElement) Node(org.w3c.dom.Node) Attr(org.w3c.dom.Attr) JaxbInfo(com.zimbra.soap.util.JaxbInfo)

Aggregations

JSONElement (com.zimbra.common.soap.Element.JSONElement)49 XMLElement (com.zimbra.common.soap.Element.XMLElement)48 Element (com.zimbra.common.soap.Element)47 XmlAnyElement (javax.xml.bind.annotation.XmlAnyElement)45 XmlElement (javax.xml.bind.annotation.XmlElement)45 Test (org.junit.Test)44 FilterTest (com.zimbra.soap.mail.type.FilterTest)43 KeyValuePair (com.zimbra.soap.type.KeyValuePair)9 StringAttribIntValue (com.zimbra.soap.jaxb.StringAttribIntValue)5 StringAttrStringElem (com.zimbra.soap.jaxb.StringAttrStringElem)3 ViewEnum (com.zimbra.soap.jaxb.ViewEnum)3 WrappedEnumElemList (com.zimbra.soap.jaxb.WrappedEnumElemList)3 FilterTests (com.zimbra.soap.mail.type.FilterTests)3 ServiceException (com.zimbra.common.service.ServiceException)2 CreateDistributionListResponse (com.zimbra.soap.account.message.CreateDistributionListResponse)2 GetDistributionListResponse (com.zimbra.soap.account.message.GetDistributionListResponse)2 DLInfo (com.zimbra.soap.account.type.DLInfo)2 DistributionListInfo (com.zimbra.soap.account.type.DistributionListInfo)2 VerifyIndexResponse (com.zimbra.soap.admin.message.VerifyIndexResponse)2 EnumAttribEnumElem (com.zimbra.soap.jaxb.EnumAttribEnumElem)2