Refactor apiv11 result unwrap to utility class

This commit is contained in:
Greg Schueler 2014-11-10 11:15:23 -08:00
parent 8cc48ecd89
commit bceb1ec4c6
3 changed files with 85 additions and 49 deletions

View file

@ -1587,26 +1587,19 @@ public class RundeckClient implements Serializable {
.param(new ExecutionQueryParameters(query))
.param("max", max)
.param("offset", offset),
patchApiV11Response(
APIV11Helper.unwrapIfNeeded(
new PagedResultParser<RundeckExecution>(
new ListParser<RundeckExecution>(new ExecutionParser(), "execution"),
new ListParser<RundeckExecution>(
new ExecutionParser(),
"execution"
),
rootXpath() + "/executions"
)
),
rootXpath() + "/executions"
)
);
}
/**
* Fix potential buggy response from Rundeck, where &lt;result&gt; wrapper exists
* even if it should not.
* @param parser
* @return
*/
private XmlNodeParser<PagedResults<RundeckExecution>> patchApiV11Response
(final PagedResultParser<RundeckExecution> parser) {
return new PagedResultParser_BugPatchV11<RundeckExecution>(parser);
}
/**
* Get a single execution, identified by the given ID
*

View file

@ -0,0 +1,78 @@
package org.rundeck.api.parser;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Node;
/**
* Utility to handle API v11 responses with &lt;result&gt; wrapper element.
*
* @author Greg Schueler <greg@simplifyops.com>
* @since 2014-11-10
*/
public class APIV11Helper {
/**
* Detect and remove extra &lt;result&gt; wrapper around xml response.
* @param parser
* @param xpath
* @param <T>
* @return
*/
public static <T> XmlNodeParser<T> unwrapIfNeeded(
final XmlNodeParser<T> parser,
final String xpath
) {
return new NodeParser_unwrap<T>(parser, xpath);
}
static class NodeParser_unwrap<T> implements XmlNodeParser<T> {
XmlNodeParser<T> parser;
String xpath;
public NodeParser_unwrap(final XmlNodeParser<T> parser, final String xpath) {
this.parser = parser;
this.xpath = xpath;
}
@Override public T parseXmlNode(final Node node) {
Node sourceNode = unwrapResultElement(node, xpath);
return parser.parseXmlNode(sourceNode);
}
}
/**
* Test the node for matching the xpath string, if it doesnt match, attempt to prefix it with
* "result" and match that. If that matches, return the first child of the 'result' element.
*
* @param node
* @param xpath
*
* @return
*/
public static Node unwrapResultElement(final Node node, final String xpath) {
Node sourceNode = node;
final Node tested = sourceNode.selectSingleNode(xpath);
if (null == tested && !xpath.startsWith("result")) {
//prepend /result
if (null != sourceNode.selectSingleNode("result" + xpath)) {
Node resultNode = sourceNode.selectSingleNode("result");
if (resultNode instanceof Element) {
Element result = (Element) resultNode;
if (result.elements().size() == 1) {
Node node1 = (Node) result.elements().get(0);
if (node1 instanceof Element) {
sourceNode = node1;
sourceNode.getParent().remove(sourceNode);
DocumentHelper.createDocument((Element) sourceNode);
}
}
}
}
}
return sourceNode;
}
}

View file

@ -1,35 +0,0 @@
package org.rundeck.api.parser;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Node;
import org.rundeck.api.util.PagedResults;
/**
* WRaps a {@link PagedResultParser} to detect whether the result XML incorrectly is wrapped with a
* &lt;result&gt; element.
*
* @author Greg Schueler <greg@simplifyops.com>
* @since 2014-11-07
*/
public class PagedResultParser_BugPatchV11<T> implements XmlNodeParser<PagedResults<T>> {
PagedResultParser<T> parser;
public PagedResultParser_BugPatchV11(final PagedResultParser<T> parser) {
this.parser = parser;
}
@Override public PagedResults<T> parseXmlNode(final Node node) {
Node sourceNode = node;
final Node tested = sourceNode.selectSingleNode(parser.getXpath());
if (null == tested && !parser.getXpath().startsWith("result")) {
//prepend /result
if (null != sourceNode.selectSingleNode("result" + parser.getXpath())) {
sourceNode = sourceNode.selectSingleNode("result" + parser.getXpath());
sourceNode.getParent().remove(sourceNode);
DocumentHelper.createDocument((Element) sourceNode);
}
}
return parser.parseXmlNode(sourceNode);
}
}