/* (c) 2014 - 2015 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.wfs.response;
import static org.junit.Assert.*;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import net.opengis.wfs.FeatureCollectionType;
import net.opengis.wfs.GetFeatureType;
import net.opengis.wfs.WfsFactory;
import org.geoserver.config.impl.GeoServerImpl;
import org.geoserver.platform.Operation;
import org.geoserver.platform.Service;
import org.geotools.data.DataStore;
import org.geotools.data.property.PropertyDataStore;
import org.geotools.feature.FeatureCollection;
import org.geotools.util.Version;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
import org.opengis.filter.Filter;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
public class Ogr2OgrFormatTest {
DataStore dataStore;
Ogr2OgrOutputFormat ogr;
Operation op;
FeatureCollectionType fct;
GetFeatureType gft;
@Before
public void setUp() throws Exception {
// check if we can run the tests
Assume.assumeTrue(Ogr2OgrTestUtil.isOgrAvailable());
// the data source we'll use for the tests
dataStore = new PropertyDataStore(new File("./src/test/java/org/geoserver/wfs/response"));
// the output format (and let's add a few output formats to play with
ogr = new Ogr2OgrOutputFormat(new GeoServerImpl(), new OGRWrapperFactory());
ogr.addFormat(new OgrFormat("KML", "OGR-KML", ".kml", true, "application/vnd.google-earth.kml"));
ogr.addFormat(new OgrFormat("KML", "OGR-KML-ZIP", ".kml", false, "application/vnd.google-earth.kml"));
ogr.addFormat(new OgrFormat("CSV", "OGR-CSV", ".csv", true, "text/csv"));
ogr.addFormat(new OgrFormat("SHP", "OGR-SHP", ".shp", false, null));
ogr.addFormat(new OgrFormat("MapInfo File", "OGR-MIF", ".mif", false, null, "-dsco", "FORMAT=MIF"));
ogr.setExecutable(Ogr2OgrTestUtil.getOgr2Ogr());
ogr.setEnvironment(Collections.singletonMap("GDAL_DATA", Ogr2OgrTestUtil.getGdalData()));
// the EMF objects used to talk with the output format
gft = WfsFactory.eINSTANCE.createGetFeatureType();
fct = WfsFactory.eINSTANCE.createFeatureCollectionType();
op = new Operation("GetFeature", new Service("WFS", null, new Version("1.0.0"),
Arrays.asList("GetFeature")), null, new Object[] { gft });
}
@Test
public void testCanHandle() {
gft.setOutputFormat("OGR-KML");
assertTrue(ogr.canHandle(op));
gft.setOutputFormat("OGR-CSV");
assertTrue(ogr.canHandle(op));
gft.setOutputFormat("RANDOM_FORMAT");
assertTrue(ogr.canHandle(op));
}
@Test
public void testContentTypeZip() {
gft.setOutputFormat("OGR-SHP");
assertEquals("application/zip", ogr.getMimeType(null, op));
}
@Test
public void testContentTypeKml() {
gft.setOutputFormat("OGR-KML");
assertEquals("application/vnd.google-earth.kml", ogr.getMimeType(null, op));
}
@Test
public void testSimpleKML() throws Exception {
// prepare input
FeatureCollection fc = dataStore.getFeatureSource("Buildings").getFeatures();
fct.getFeature().add(fc);
// write out
ByteArrayOutputStream bos = new ByteArrayOutputStream();
gft.setOutputFormat("OGR-KML");
ogr.write(fct, bos, op);
// parse the kml to check it's really xml...
Document dom = dom(new ByteArrayInputStream(bos.toByteArray()));
// print(dom);
// some very light assumptions on the contents, since we
// cannot control how ogr encodes the kml... let's just assess
// it's kml with the proper number of features
assertEquals("kml", dom.getDocumentElement().getTagName());
assertEquals(2, dom.getElementsByTagName("Placemark").getLength());
}
@Test
public void testZippedKML() throws Exception {
// prepare input
FeatureCollection fc = dataStore.getFeatureSource("Buildings").getFeatures();
fct.getFeature().add(fc);
// write out
ByteArrayOutputStream bos = new ByteArrayOutputStream();
gft.setOutputFormat("OGR-KML-ZIP");
ogr.write(fct, bos, op);
// unzip the result
ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(bos.toByteArray()));
Document dom = null;
ZipEntry entry = zis.getNextEntry();
assertEquals("Buildings.kml", entry.getName());
dom = dom(zis);
// some very light assumptions on the contents, since we
// cannot control how ogr encodes the kml... let's just assess
// it's kml with the proper number of features
assertEquals("kml", dom.getDocumentElement().getTagName());
assertEquals(2, dom.getElementsByTagName("Placemark").getLength());
}
@Test
public void testEmptyKML() throws Exception {
// prepare input
FeatureCollection fc = dataStore.getFeatureSource("Buildings").getFeatures(Filter.EXCLUDE);
fct.getFeature().add(fc);
// write out
ByteArrayOutputStream bos = new ByteArrayOutputStream();
gft.setOutputFormat("OGR-KML");
ogr.write(fct, bos, op);
// parse the kml to check it's really xml...
Document dom = dom(new ByteArrayInputStream(bos.toByteArray()));
// print(dom);
// some very light assumptions on the contents, since we
// cannot control how ogr encodes the kml... let's just assess
// it's kml with the proper number of features
assertEquals("kml", dom.getDocumentElement().getTagName());
assertEquals(0, dom.getElementsByTagName("Placemark").getLength());
}
@Test
public void testSimpleCSV() throws Exception {
// prepare input
FeatureCollection fc = dataStore.getFeatureSource("Buildings").getFeatures();
fct.getFeature().add(fc);
// write out
ByteArrayOutputStream bos = new ByteArrayOutputStream();
gft.setOutputFormat("OGR-CSV");
ogr.write(fct, bos, op);
// read back
String csv = read(new ByteArrayInputStream(bos.toByteArray()));
// couple simple checks
String[] lines = csv.split("\n");
// headers and the two lines
assertEquals(3, lines.length);
assertTrue(csv.contains("123 Main Street"));
}
@Test
public void testSimpleMIF() throws Exception {
// prepare input
FeatureCollection fc = dataStore.getFeatureSource("Buildings").getFeatures();
fct.getFeature().add(fc);
// write out
ByteArrayOutputStream bos = new ByteArrayOutputStream();
gft.setOutputFormat("OGR-MIF");
ogr.write(fct, bos, op);
// read back
ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(bos.toByteArray()));
// we should get two files at least, a .mif and a .mid
Set<String> fileNames = new HashSet<String>();
ZipEntry entry = null;
while((entry = zis.getNextEntry()) != null) {
fileNames.add(entry.getName());
}
assertTrue(fileNames.contains("Buildings.mif"));
assertTrue(fileNames.contains("Buildings.mid"));
}
@Test
public void testGeometrylessCSV() throws Exception {
// prepare input
FeatureCollection fc = dataStore.getFeatureSource("Geometryless").getFeatures();
fct.getFeature().add(fc);
// write out
ByteArrayOutputStream bos = new ByteArrayOutputStream();
gft.setOutputFormat("OGR-CSV");
ogr.write(fct, bos, op);
// read back
String csv = read(new ByteArrayInputStream(bos.toByteArray()));
// couple simple checks
String[] lines = csv.split("\n");
// headers and the feature lines
assertEquals(4, lines.length);
// let's see if one of the expected lines is there
assertTrue(csv.contains("Alessia"));
}
@Test
public void testAllTypesKML() throws Exception {
// prepare input
FeatureCollection fc = dataStore.getFeatureSource("AllTypes").getFeatures();
fct.getFeature().add(fc);
// write out
ByteArrayOutputStream bos = new ByteArrayOutputStream();
gft.setOutputFormat("OGR-KML");
ogr.write(fct, bos, op);
// read back
Document dom = dom(new ByteArrayInputStream(bos.toByteArray()));
// print(dom);
// some very light assumptions on the contents, since we
// cannot control how ogr encodes the kml... let's just assess
// it's kml with the proper number of features
assertEquals("kml", dom.getDocumentElement().getTagName());
assertEquals(6, dom.getElementsByTagName("Placemark").getLength());
}
/**
* Utility method to print out a dom.
*/
protected void print(Document dom) throws Exception {
TransformerFactory txFactory = TransformerFactory.newInstance();
try {
txFactory.setAttribute("{http://xml.apache.org/xalan}indent-number", new Integer(2));
} catch (Exception e) {
// some
}
Transformer tx = txFactory.newTransformer();
tx.setOutputProperty(OutputKeys.METHOD, "xml");
tx.setOutputProperty(OutputKeys.INDENT, "yes");
tx.transform(new DOMSource(dom), new StreamResult(new OutputStreamWriter(System.out,
"utf-8")));
}
protected String read(InputStream is) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line = null;
StringBuilder sb = new StringBuilder();
while((line = br.readLine()) != null) {
sb.append(line);
sb.append("\n");
}
return sb.toString();
}
/**
* Parses a stream into a dom.
*
* @param input
* @param skipDTD
* If true, will skip loading and validating against the
* associated DTD
*/
protected Document dom(InputStream input) throws ParserConfigurationException, SAXException,
IOException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
factory.setValidating(false);
DocumentBuilder builder = factory.newDocumentBuilder();
return builder.parse(input);
}
}