com.github.dreamhead.moco.matcher.XmlRequestMatcher Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of moco-core Show documentation
Show all versions of moco-core Show documentation
Moco is an easy setup stub framework, mainly focusing on testing and integration.
package com.github.dreamhead.moco.matcher;
import com.github.dreamhead.moco.MocoConfig;
import com.github.dreamhead.moco.MocoException;
import com.github.dreamhead.moco.Request;
import com.github.dreamhead.moco.RequestMatcher;
import com.github.dreamhead.moco.extractor.ContentRequestExtractor;
import com.github.dreamhead.moco.extractor.XmlExtractorHelper;
import com.github.dreamhead.moco.resource.Resource;
import com.google.common.base.Optional;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.InputStream;
import static com.google.common.base.Optional.absent;
import static com.google.common.base.Optional.of;
import static com.google.common.base.Strings.isNullOrEmpty;
public class XmlRequestMatcher extends AbstractRequestMatcher {
private final XmlExtractorHelper helper = new XmlExtractorHelper();
private final ContentRequestExtractor extractor;
private final Resource resource;
public XmlRequestMatcher(final Resource resource) {
this.extractor = new ContentRequestExtractor();
this.resource = resource;
}
@Override
public boolean match(final Request request) {
try {
Optional requestDocument = extractDocument(request, extractor);
return requestDocument.isPresent() && tryToMatch(request, requestDocument.get());
} catch (SAXException e) {
return false;
}
}
private boolean tryToMatch(final Request request, final Document document) throws SAXException {
Document resourceDocument = getResourceDocument(request, this.resource);
return document.isEqualNode(resourceDocument);
}
@Override
@SuppressWarnings("unchecked")
public RequestMatcher doApply(final MocoConfig config) {
if (config.isFor(resource.id())) {
return new XmlRequestMatcher(resource.apply(config));
}
return this;
}
private Document getResourceDocument(final Request request, final Resource resource) throws SAXException {
InputStream stream = resource.readFor(of(request)).toInputStream();
return extractDocument(new InputSource(stream));
}
private Optional extractDocument(final Request request, final ContentRequestExtractor extractor) throws SAXException {
Optional inputSourceOptional = helper.extractAsInputSource(request, extractor);
if (!inputSourceOptional.isPresent()) {
return absent();
}
return of(extractDocument(inputSourceOptional.get()));
}
private void trimChild(final Node node, final Node child) {
if (child instanceof Text) {
if (isNullOrEmpty(child.getNodeValue().trim())) {
node.removeChild(child);
}
return;
}
if (child instanceof Element) {
trimNode(child);
}
}
// Whitespace will be kept by DOM parser.
private void trimNode(final Node node) {
NodeList children = node.getChildNodes();
for (int i = children.getLength() - 1; i >= 0; i--) {
trimChild(node, children.item(i));
}
}
private DocumentBuilder documentBuilder() {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
dbf.setCoalescing(true);
dbf.setIgnoringElementContentWhitespace(true);
dbf.setIgnoringComments(true);
try {
return dbf.newDocumentBuilder();
} catch (ParserConfigurationException e) {
throw new MocoException(e);
}
}
private Document extractDocument(final InputSource inputSource) throws SAXException {
try {
DocumentBuilder builder = documentBuilder();
Document document = builder.parse(inputSource);
document.normalizeDocument();
trimNode(document);
return document;
} catch (IOException e) {
throw new MocoException(e);
}
}
}