/* (c) 2015 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.wms.vector;
import static org.junit.Assert.*;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.*;
import java.awt.Rectangle;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.wicket.spring.test.ApplicationContextMock;
import org.geoserver.catalog.SLDHandler;
import org.geoserver.config.GeoServerLoader;
import org.geoserver.platform.GeoServerExtensionsHelper;
import org.geoserver.wms.GetMapRequest;
import org.geoserver.wms.MapLayerInfo;
import org.geoserver.wms.WMS;
import org.geoserver.wms.WMSMapContent;
import org.geoserver.wms.WebMap;
import org.geotools.data.DataUtilities;
import org.geotools.data.memory.MemoryDataStore;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.geometry.jts.WKTReader2;
import org.geotools.map.FeatureLayer;
import org.geotools.map.Layer;
import org.geotools.referencing.CRS;
import org.geotools.styling.NamedLayer;
import org.geotools.styling.Style;
import org.geotools.styling.StyledLayerDescriptor;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.GeometryDescriptor;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import com.google.common.collect.ImmutableSet;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.io.ParseException;
public class VectorTileMapOutputFormatTest {
private static CoordinateReferenceSystem WEB_MERCATOR;
private static CoordinateReferenceSystem WGS84;
private static Style defaultPointStyle, defaultLineStyle, defaultPolygonStyle;
private WMS wmsMock;
private VectorTileMapOutputFormat outptFormat;
private VectorTileBuilder tileBuilderMock;
private FeatureLayer pointLayer, lineLayer, polygonLayer;
@BeforeClass
public static void beforeClass() throws Exception {
defaultPointStyle = parseStyle("default_point.sld");
defaultLineStyle = parseStyle("default_line.sld");
defaultPolygonStyle = parseStyle("default_polygon.sld");
// avoid lots of application context unset warnings in the console
GeoServerExtensionsHelper.init(new ApplicationContextMock());
WEB_MERCATOR = CRS.decode("EPSG:3857");
WGS84 = CRS.decode("EPSG:4326", true);
}
@Before
public void before() throws Exception {
wmsMock = mock(WMS.class);
tileBuilderMock = mock(VectorTileBuilder.class);
VectorTileBuilderFactory tileBuilderFactory = mock(VectorTileBuilderFactory.class);
when(tileBuilderFactory.getMimeType()).thenReturn("testMime");
when(tileBuilderFactory.getOutputFormats()).thenReturn(
ImmutableSet.of("testMime", "testFormat"));
when(tileBuilderFactory.newBuilder(any(Rectangle.class), any(ReferencedEnvelope.class)))
.thenReturn(tileBuilderMock);
outptFormat = new VectorTileMapOutputFormat(wmsMock, tileBuilderFactory);
MemoryDataStore ds = new MemoryDataStore();
final String pointsTypeSpec = "sp:String,ip:Integer,geom:Point:srid=4326";
final String linesTypeSpec = "sp:String,ip:Integer,geom:LineString:srid=4326";
final String polyTypeSpec = "sp:String,ip:Integer,geom:Polygon:srid=4326";
SimpleFeatureType pointType = DataUtilities.createType("points", pointsTypeSpec);
SimpleFeatureType lineType = DataUtilities.createType("lines", linesTypeSpec);
SimpleFeatureType polyType = DataUtilities.createType("polygons", polyTypeSpec);
ds.addFeature(feature(pointType, "point1", "StringProp1_1", 1000, "POINT(1 1)"));
ds.addFeature(feature(pointType, "point2", "StringProp1_2", 2000, "POINT(2 2)"));
ds.addFeature(feature(pointType, "point3", "StringProp1_3", 3000, "POINT(3 3)"));
ds.addFeature(feature(lineType, "line1", "StringProp2_1", 1000, "LINESTRING (1 1, 2 2)"));
ds.addFeature(feature(lineType, "line1", "StringProp2_2", 2000, "LINESTRING (3 3, 4 4)"));
ds.addFeature(feature(lineType, "line1", "StringProp2_3", 3000, "LINESTRING (5 5, 6 6)"));
ds.addFeature(feature(polyType, "polygon1", "StringProp3_1", 1000,
"POLYGON ((1 1, 2 2, 3 3, 4 4, 1 1))"));
ds.addFeature(feature(polyType, "polygon2", "StringProp3_2", 2000,
"POLYGON ((6 6, 7 7, 8 8, 9 9, 6 6))"));
ds.addFeature(feature(polyType, "polygon3", "StringProp3_3", 3000,
"POLYGON ((11 11, 12 12, 13 13, 14 14, 11 11))"));
pointLayer = new FeatureLayer(ds.getFeatureSource("points"), defaultPointStyle);
lineLayer = new FeatureLayer(ds.getFeatureSource("lines"), defaultLineStyle);
polygonLayer = new FeatureLayer(ds.getFeatureSource("polygons"), defaultPolygonStyle);
}
@Test
public void testSimple() throws Exception {
ReferencedEnvelope mapBounds = new ReferencedEnvelope(0, 180, -90, 90, WGS84);
Rectangle renderingArea = new Rectangle(256, 256);
WMSMapContent mapContent = createMapContent(mapBounds, renderingArea, pointLayer);
WebMap mockMap = mock(WebMap.class);
when(tileBuilderMock.build(same(mapContent))).thenReturn(mockMap);
assertSame(mockMap, outptFormat.produceMap(mapContent));
verify(tileBuilderMock, times(1)).addFeature(eq("points"), eq("point1"), eq("geom"),
any(Geometry.class), any(Map.class));
}
private WMSMapContent createMapContent(ReferencedEnvelope mapBounds, Rectangle renderingArea,
Layer... layers) throws Exception {
GetMapRequest mapRequest = createGetMapRequest(mapBounds, renderingArea);
WMSMapContent map = new WMSMapContent(mapRequest);
map.getViewport().setBounds(mapBounds);
if (layers != null) {
for (Layer l : layers) {
map.addLayer(l);
}
}
map.setMapWidth(renderingArea.width);
map.setMapHeight(renderingArea.height);
return map;
}
protected GetMapRequest createGetMapRequest(ReferencedEnvelope requestEnvelope,
Rectangle renderingArea) {
GetMapRequest request = new GetMapRequest();
request.setBaseUrl("http://localhost:8080/geoserver");
List<MapLayerInfo> layers = new ArrayList<>();
List<Style> styles = new ArrayList<>();
// for (int i = 0; i < layerNames.length; i++) {
// LayerInfo layerInfo = getCatalog().getLayerByName(layerNames[i].getLocalPart());
// try {
// styles.add(layerInfo.getDefaultStyle().getStyle());
// } catch (IOException e) {
// throw new RuntimeException(e);
// }
// layers.add(new MapLayerInfo(layerInfo));
// }
request.setLayers(layers);
request.setStyles(styles);
request.setBbox((Envelope) requestEnvelope);
request.setCrs(requestEnvelope.getCoordinateReferenceSystem());
if (requestEnvelope.getCoordinateReferenceSystem() == WGS84) {
request.setSRS("EPSG:4326");
} else if (requestEnvelope.getCoordinateReferenceSystem() == WEB_MERCATOR) {
request.setSRS("EPSG:3857");
} else {
throw new IllegalArgumentException("Please use one of the test CRS's");
}
request.setWidth(renderingArea.width);
request.setHeight(renderingArea.height);
request.setRawKvp(new HashMap<String, String>());
return request;
}
// @Test
// public void testMapBoxTileBuilder() throws Exception {
//
// Envelope mapBounds = new Envelope(-92.8, -93.2, 4.5, 4.6);
// mapBounds = JTS.transform(mapBounds,
// CRS.findMathTransform(CRS.decode("EPSG:4326"), CRS.decode("EPSG:900913"), true));
//
// WMSMapContent mapContent = createMapContent("EPSG:900913", mapBounds, POINTS, POLYGONS);
// mapContent.setMapHeight(256);
// mapContent.setMapWidth(256);
//
// MapBoxTileBuilderFactory builderFact = new MapBoxTileBuilderFactory();
//
// VectorTileMapOutputFormat outputFormat = new VectorTileMapOutputFormat(getWMS(),
// builderFact);
// outputFormat.setTransformToScreenCoordinates(true);
//
// RawMap map = (RawMap) outputFormat.produceMap(mapContent);
// ByteArrayOutputStream bos = new ByteArrayOutputStream();
// map.writeTo(bos);
// VectorTileDecoder decoder = new VectorTileDecoder();
// decoder.setAutoScale(false);
//
// FeatureIterable feats = decoder.decode(bos.toByteArray());
//
// for (Feature feat : feats) {
// System.out.println(feat.getLayerName() + ": ");
// System.out.print(feat.getAttributes());
// System.out.println(feat.getGeometry());
// }
//
// bos.close();
//
// List<Feature> featList = feats.asList();
// assertEquals(2, featList.size());
// assertEquals("Points", featList.get(0).getLayerName());
// assertTrue(featList.get(0).getGeometry() instanceof Point);
// assertEquals(new Coordinate(641, 973),
// ((Point) featList.get(0).getGeometry()).getCoordinate());
// assertEquals("Polygons", featList.get(1).getLayerName());
// assertTrue(featList.get(1).getGeometry() instanceof Polygon);
// assertEquals(new Coordinate(646, 976),
// (((Polygon) featList.get(1).getGeometry()).getCoordinates()[0]));
// }
//
// @Test
// public void testMapBoxTileBuilderOtherCrs() throws Exception {
// WMSMapContent mapContent = createMapContent("EPSG:4326", new Envelope(-92.8, -93.2, 4.5,
// 4.6), POINTS, POLYGONS);
//
// mapContent.setMapHeight(256);
// mapContent.setMapWidth(256);
//
// MapBoxTileBuilderFactory builderFact = new MapBoxTileBuilderFactory();
//
// VectorTileMapOutputFormat outputFormat = new VectorTileMapOutputFormat(getWMS(),
// builderFact);
// outputFormat.setTransformToScreenCoordinates(true);
//
// RawMap map = (RawMap) outputFormat.produceMap(mapContent);
// ByteArrayOutputStream bos = new ByteArrayOutputStream();
// map.writeTo(bos);
// VectorTileDecoder decoder = new VectorTileDecoder();
// decoder.setAutoScale(false);
//
// FeatureIterable feats = decoder.decode(bos.toByteArray());
//
// for (Feature feat : feats) {
// System.out.println(feat.getLayerName() + ": ");
// System.out.print(feat.getAttributes());
// System.out.println(feat.getGeometry());
// }
//
// bos.close();
//
// List<Feature> featList = feats.asList();
// assertEquals(2, featList.size());
// assertEquals("Points", featList.get(0).getLayerName());
// assertTrue(featList.get(0).getGeometry() instanceof Point);
// assertEquals(new Coordinate(641, 973),
// ((Point) featList.get(0).getGeometry()).getCoordinate());
// assertEquals("Polygons", featList.get(1).getLayerName());
// assertTrue(featList.get(1).getGeometry() instanceof Polygon);
// assertEquals(new Coordinate(646, 976),
// (((Polygon) featList.get(1).getGeometry()).getCoordinates()[0]));
// }
protected static SimpleFeature feature(SimpleFeatureType type, String id, Object... values)
throws ParseException {
SimpleFeatureBuilder builder = new SimpleFeatureBuilder(type);
for (int i = 0; i < values.length; i++) {
Object value = values[i];
if (type.getDescriptor(i) instanceof GeometryDescriptor) {
if (value instanceof String) {
value = new WKTReader2().read((String) value);
}
}
builder.set(i, value);
}
return builder.buildFeature(id);
}
private static Style parseStyle(String styleResource) throws IOException {
try (InputStream in = GeoServerLoader.class.getResourceAsStream(styleResource)) {
StyledLayerDescriptor sld = new SLDHandler().parse(in, null, null, null);
return ((NamedLayer) sld.getStyledLayers()[0]).getStyles()[0];
}
}
}