use of com.zimbra.common.soap.Element in project zm-mailbox by Zimbra.
the class JaxbUtil method addChildElementFromJaxb.
public static Element addChildElementFromJaxb(Element parent, String name, String namespace, Object o) {
Element.ElementFactory factory;
if (parent instanceof XMLElement) {
factory = XMLElement.mFactory;
} else {
factory = JSONElement.mFactory;
}
Element child = null;
try {
child = jaxbToNamedElement(name, namespace, o, factory);
} catch (ServiceException e) {
ZimbraLog.misc.info("JAXB Problem making " + name + " element", e);
}
parent.addElement(child);
return child;
}
use of com.zimbra.common.soap.Element 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.common.soap.Element in project zm-mailbox by Zimbra.
the class OctopusJaxbTest method checkDeviceStatusResponse.
/**
* Validating that method used to create response in CheckDeviceStatus
* should work.
* @throws Exception
*/
@Test
public void checkDeviceStatusResponse() throws Exception {
IdStatus idStatus = IdStatus.fromIdAndStatus("idString", "statusString");
CheckDeviceStatusResponse resp = new CheckDeviceStatusResponse(idStatus);
Element response = JaxbUtil.jaxbToElement(resp, XMLElement.mFactory);
Assert.assertNotNull("response object", response);
resp = JaxbUtil.elementToJaxb(response);
Assert.assertEquals("round tripped id", "idString", resp.getDevice().getId());
Assert.assertEquals("round tripped status", "statusString", resp.getDevice().getStatus());
}
use of com.zimbra.common.soap.Element in project zm-mailbox by Zimbra.
the class OctopusJaxbTest method activityInfoForGetActivityStreamXml.
@Test
public void activityInfoForGetActivityStreamXml() throws Exception {
Map<String, String> args = Maps.newHashMap();
args.put("key1", "value1");
args.put("key2", "value2");
ActivityInfo ai = toActivityInfo("account", "op", 333L, "123-123-123:22", 44, "itemName", args);
Element notify = XMLElement.create(SoapProtocol.Soap12, "pink");
Element activityElem = JaxbUtil.addChildElementFromJaxb(notify, MailConstants.E_A, MailConstants.NAMESPACE_STR, ai);
ai = JaxbUtil.elementToJaxb(activityElem, ActivityInfo.class);
checkActivityInfo(ai, "XML round tripped ");
}
use of com.zimbra.common.soap.Element in project zm-mailbox by Zimbra.
the class ZimbraSoapUtils method invokeJaxb.
@SuppressWarnings("unchecked")
public static <T> T invokeJaxb(SoapHttpTransport transport, Object jaxbObject) throws ServiceException {
Element req = JaxbUtil.jaxbToElement(jaxbObject);
Element res = invoke(transport, req);
return (T) JaxbUtil.elementToJaxb(res);
}
Aggregations