Search in sources :

Example 1 with JaxbInfo

use of com.zimbra.soap.util.JaxbInfo in project zm-mailbox by Zimbra.

the class XmlElementDescription method createForElement.

private static XmlElementDescription createForElement(DescriptionNode parent, JaxbElementInfo nodeInfo) {
    XmlElementDescription desc = new XmlElementDescription(!nodeInfo.isMultiElement(), false, false);
    desc.parent = parent;
    desc.minOccurs = nodeInfo.isRequired() ? 1 : 0;
    desc.targetNamespace = nodeInfo.getNamespace();
    desc.name = nodeInfo.getName();
    desc.jaxbClass = nodeInfo.getAtomClass();
    desc.elementText = "";
    desc.fieldName = nodeInfo.getFieldName();
    processTypeInfo(desc, nodeInfo.getAtomClass());
    desc.isInnerRecursionElement = isInnerRecursion(parent, desc.typeName);
    if (!desc.isInnerRecursionElement) {
        JaxbInfo jaxbInfo = getJaxbInfoForClass(nodeInfo.getAtomClass());
        if (jaxbInfo != null) {
            addXmlInfo(desc, jaxbInfo);
        }
    }
    return desc;
}
Also used : JaxbInfo(com.zimbra.soap.util.JaxbInfo)

Example 2 with JaxbInfo

use of com.zimbra.soap.util.JaxbInfo in project zm-mailbox by Zimbra.

the class JaxbToElementTest method jaxbMessageHitInfoElementNameOrder.

@Test
public void jaxbMessageHitInfoElementNameOrder() throws Exception {
    JaxbInfo jaxbInfo = JaxbInfo.getFromCache(MessageHitInfo.class);
    List<List<org.dom4j.QName>> expectedOrder = Lists.newArrayList();
    expectedOrder.add(Lists.newArrayList(new org.dom4j.QName("meta", MailConstants.NAMESPACE)));
    expectedOrder.add(Lists.newArrayList(new org.dom4j.QName("fr", MailConstants.NAMESPACE)));
    expectedOrder.add(Lists.newArrayList(new org.dom4j.QName("e", MailConstants.NAMESPACE)));
    expectedOrder.add(Lists.newArrayList(new org.dom4j.QName("su", MailConstants.NAMESPACE)));
    expectedOrder.add(Lists.newArrayList(new org.dom4j.QName("mid", MailConstants.NAMESPACE)));
    expectedOrder.add(Lists.newArrayList(new org.dom4j.QName("irt", MailConstants.NAMESPACE)));
    expectedOrder.add(Lists.newArrayList(new org.dom4j.QName("inv", MailConstants.NAMESPACE)));
    expectedOrder.add(Lists.newArrayList(new org.dom4j.QName("header", MailConstants.NAMESPACE)));
    List<org.dom4j.QName> sameOrder = Lists.newArrayList();
    sameOrder.add(new org.dom4j.QName("mp", MailConstants.NAMESPACE));
    sameOrder.add(new org.dom4j.QName("shr", MailConstants.NAMESPACE));
    sameOrder.add(new org.dom4j.QName("dlSubs", MailConstants.NAMESPACE));
    expectedOrder.add(sameOrder);
    expectedOrder.add(Lists.newArrayList(new org.dom4j.QName("hp", MailConstants.NAMESPACE)));
    List<List<org.dom4j.QName>> nameOrder = jaxbInfo.getElementNameOrder();
    Assert.assertTrue(String.format("Number of entries in order expected=%d actual=%d", expectedOrder.size(), nameOrder.size()), expectedOrder.size() == nameOrder.size());
    for (int ndx = 0; ndx < nameOrder.size(); ndx++) {
        List<QName> expected = expectedOrder.get(ndx);
        List<QName> actual = nameOrder.get(ndx);
        Assert.assertTrue(String.format("Number of entries at pos %d expected=%d actual=%d", ndx, expected.size(), actual.size()), expected.size() == actual.size());
        for (int cnt = 0; cnt < actual.size(); cnt++) {
            QName qExpected = expected.get(cnt);
            QName qActual = actual.get(cnt);
            Assert.assertEquals(String.format("Element name at pos %d/%d", ndx, cnt), qExpected.getName(), qActual.getName());
            Assert.assertEquals(String.format("Element namespaceURI at pos %d/%d", ndx, cnt), qExpected.getNamespaceURI(), qActual.getNamespaceURI());
        }
    }
}
Also used : QName(org.dom4j.QName) List(java.util.List) QName(org.dom4j.QName) JaxbInfo(com.zimbra.soap.util.JaxbInfo) Test(org.junit.Test)

Example 3 with JaxbInfo

use of com.zimbra.soap.util.JaxbInfo in project zm-mailbox by Zimbra.

the class JaxbToElementTest method jaxbInfoWrapperHandling.

@Test
public void jaxbInfoWrapperHandling() throws Exception {
    JaxbInfo jaxbInfo = JaxbInfo.getFromCache(WaitSetRequest.class);
    Class<?> klass;
    klass = jaxbInfo.getClassForWrappedElement("notWrapperName", "nonexistent");
    if (klass != null) {
        Assert.fail("Class " + klass.getName() + " should be null for non-existent wrapper/wrapped");
    }
    klass = jaxbInfo.getClassForWrappedElement(MailConstants.E_WAITSET_ADD, /* add */
    "nonexistent");
    if (klass != null) {
        Assert.fail("Class " + klass.getName() + " should be null for existing wrapper/non-existent wrapped");
    }
    klass = jaxbInfo.getClassForWrappedElement(MailConstants.E_WAITSET_ADD, /* add */
    MailConstants.E_A);
    Assert.assertNotNull("Class should NOT be null for existing wrapper/non-existent wrapped", klass);
    Assert.assertEquals("WaitSetAddSpec class", WaitSetAddSpec.class, klass);
}
Also used : JaxbInfo(com.zimbra.soap.util.JaxbInfo) Test(org.junit.Test)

Example 4 with JaxbInfo

use of com.zimbra.soap.util.JaxbInfo 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)

Example 5 with JaxbInfo

use of com.zimbra.soap.util.JaxbInfo in project zm-mailbox by Zimbra.

the class JaxbToElementTest method jaxbElementNameOrderXmlElementWrapperTest.

@Test
public void jaxbElementNameOrderXmlElementWrapperTest() throws Exception {
    JaxbInfo jaxbInfo = JaxbInfo.getFromCache(GetWhiteBlackListResponse.class);
    List<List<org.dom4j.QName>> expectedOrder = Lists.newArrayList();
    expectedOrder.add(Lists.newArrayList(new org.dom4j.QName(AccountConstants.E_WHITE_LIST, AccountConstants.NAMESPACE)));
    expectedOrder.add(Lists.newArrayList(new org.dom4j.QName(AccountConstants.E_BLACK_LIST, AccountConstants.NAMESPACE)));
    List<List<org.dom4j.QName>> nameOrder = jaxbInfo.getElementNameOrder();
    Assert.assertTrue(String.format("Number of entries in order expected=%d actual=%d", expectedOrder.size(), nameOrder.size()), expectedOrder.size() == nameOrder.size());
    for (int ndx = 0; ndx < nameOrder.size(); ndx++) {
        List<QName> expected = expectedOrder.get(ndx);
        List<QName> actual = nameOrder.get(ndx);
        Assert.assertTrue(String.format("Number of entries at pos %d expected=%d actual=%d", ndx, expected.size(), actual.size()), expected.size() == actual.size());
        for (int cnt = 0; cnt < actual.size(); cnt++) {
            QName qExpected = expected.get(cnt);
            QName qActual = actual.get(cnt);
            Assert.assertEquals(String.format("Element name at pos %d/%d", ndx, cnt), qExpected.getName(), qActual.getName());
            Assert.assertEquals(String.format("Element namespaceURI at pos %d/%d", ndx, cnt), qExpected.getNamespaceURI(), qActual.getNamespaceURI());
        }
    }
}
Also used : QName(org.dom4j.QName) List(java.util.List) JaxbInfo(com.zimbra.soap.util.JaxbInfo) Test(org.junit.Test)

Aggregations

JaxbInfo (com.zimbra.soap.util.JaxbInfo)8 Test (org.junit.Test)4 List (java.util.List)3 Element (com.zimbra.common.soap.Element)2 QName (org.dom4j.QName)2 ServiceException (com.zimbra.common.service.ServiceException)1 JSONElement (com.zimbra.common.soap.Element.JSONElement)1 XMLElement (com.zimbra.common.soap.Element.XMLElement)1 MessagePartHit (com.zimbra.cs.index.MessagePartHit)1 Message (com.zimbra.cs.mailbox.Message)1 JaxbElementInfo (com.zimbra.soap.util.JaxbElementInfo)1 JaxbNodeInfo (com.zimbra.soap.util.JaxbNodeInfo)1 JAXBElement (javax.xml.bind.JAXBElement)1 Attr (org.w3c.dom.Attr)1 NamedNodeMap (org.w3c.dom.NamedNodeMap)1 Node (org.w3c.dom.Node)1 NodeList (org.w3c.dom.NodeList)1