/*
* This is part of Geomajas, a GIS framework, http://www.geomajas.org/.
*
* Copyright 2008-2015 Geosparc nv, http://www.geosparc.com/, Belgium.
*
* The program is available in open source according to the GNU Affero
* General Public License. All contributions in this program are covered
* by the Geomajas Contributors License Agreement. For full licensing
* details, see LICENSE.txt in the project root.
*/
package org.geomajas.gwt2.plugin.wfs.client.service;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.StringReader;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.io.IOUtils;
import org.apache.xerces.parsers.DOMParser;
import org.geomajas.gwt2.plugin.wfs.client.protocol.WfsGetCapabilitiesInfo;
import org.geomajas.gwt2.plugin.wfs.client.service.WfsServiceImpl.RequestBuilderFactory;
import org.geomajas.gwt2.plugin.wfs.client.service.WfsServiceImpl.UrlEncoder;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.xml.sax.InputSource;
import com.google.gwt.core.client.Callback;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.Response;
import com.google.gwt.xml.client.Document;
import com.google.gwt.xml.client.impl.XMLParserImpl;
import com.google.gwtmockito.GwtMockitoTestRunner;
@RunWith(GwtMockitoTestRunner.class)
public abstract class AbstractWfsServiceTest {
@Mock
protected RequestBuilder requestBuilder;
protected WfsServiceImpl wfsService;
protected String capabilitiesXml;
protected Document capabilitiesDoc;
@Before
public void init() throws Exception {
wfsService = new WfsServiceImpl();
wfsService.setRequestBuilderFactory(new RequestBuilderFactory() {
@Override
public RequestBuilder create(RequestBuilder.Method method, String url) {
return requestBuilder;
}
});
wfsService.setUrlEncoder(new UrlEncoder() {
@Override
public String encodeUrl(String url) {
return url;
}
});
when(XMLParserImpl.getInstance().parse(anyString())).thenAnswer(new Answer<Document>() {
@Override
public Document answer(InvocationOnMock invocation) throws Throwable {
return capabilitiesDoc;
}
});
}
protected void prepareResponse(String resource) throws Exception {
capabilitiesXml = IOUtils.toString(this.getClass().getResourceAsStream(resource), "UTF-8");
DOMParser parser = new DOMParser();
parser.parse(new InputSource(new StringReader(capabilitiesXml)));
capabilitiesDoc = w3cToGoogle(parser.getDocument());
final Response response = mock(Response.class);
when(response.getStatusCode()).thenReturn(200);
when(response.getText()).thenReturn(capabilitiesXml);
when(requestBuilder.sendRequest(anyString(), any(RequestCallback.class))).thenAnswer(new Answer<Request>() {
@Override
public Request answer(InvocationOnMock invocation) throws Throwable {
((RequestCallback) invocation.getArguments()[1]).onResponseReceived(null, response);
return null;
}
});
}
private Document w3cToGoogle(final org.w3c.dom.Document document) {
return (Document) Proxy.newProxyInstance(getClass().getClassLoader(), new Class<?>[] { Document.class },
new W3CToGoogleHandler(document));
}
/**
* Recursive proxy to expose w3c dom classes as gwt dom classes.
*
* @author Jan De Moerloose
*
*/
public class W3CToGoogleHandler implements InvocationHandler {
private Object delegate;
public W3CToGoogleHandler(Object delegate) {
this.delegate = delegate;
}
@Override
public Object invoke(Object target, Method method, Object[] args) throws Throwable {
try {
Method m = delegate.getClass().getMethod(method.getName(), method.getParameterTypes());
Object result = m.invoke(delegate, args == null ? null : new Object[] { args[0] });
// equals() should equal the other's delegate
if (m.getName().equals("equals")) {
if (Proxy.isProxyClass(args[0].getClass())) {
W3CToGoogleHandler handler = (W3CToGoogleHandler) Proxy.getInvocationHandler(args[0]);
return delegate.equals(handler.delegate);
}
}
if (result == null) {
return null;
}
// find the matching interfaces for the return type and create a new proxy for those interfaces
Class<?>[] c = getClasses(result, m.getReturnType());
if (c.length > 0) {
return Proxy.newProxyInstance(getClass().getClassLoader(), c, new W3CToGoogleHandler(result));
} else {
return result;
}
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
private Class[] getClasses(Object result, Class type) {
List<Class> matches = new ArrayList<Class>();
if (result instanceof org.w3c.dom.NamedNodeMap) {
matches.add(com.google.gwt.xml.client.NamedNodeMap.class);
}
if (result instanceof org.w3c.dom.NodeList) {
matches.add(com.google.gwt.xml.client.NodeList.class);
}
if (result instanceof org.w3c.dom.Document) {
matches.add(com.google.gwt.xml.client.Document.class);
}
if (result instanceof org.w3c.dom.Element) {
matches.add(com.google.gwt.xml.client.Element.class);
}
if (result instanceof org.w3c.dom.Node) {
matches.add(com.google.gwt.xml.client.Node.class);
}
return matches.toArray(new Class[0]);
}
}
class CapabilitiesCallback implements Callback<WfsGetCapabilitiesInfo, String> {
WfsGetCapabilitiesInfo result;
private String reason;
@Override
public void onSuccess(WfsGetCapabilitiesInfo result) {
this.result = result;
}
@Override
public void onFailure(String reason) {
this.reason = reason;
}
public WfsGetCapabilitiesInfo getResult() {
return result;
}
public String getReason() {
return reason;
}
}
}