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;
}
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());
}
}
}
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);
}
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>
* <xml-elem-json-attr>XML elem but JSON attribute</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>
* <a n="anID">val</a><a n="anID2">val2</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);
}
}
}
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());
}
}
}
Aggregations