/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2017, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotools.mbstyle.transform; import org.geotools.TestData; import org.geotools.data.property.PropertyDataStore; import org.geotools.data.simple.SimpleFeatureIterator; import org.geotools.data.store.ContentFeatureSource; import org.geotools.factory.CommonFactoryFinder; import org.geotools.mbstyle.*; import org.geotools.mbstyle.layer.*; import org.geotools.mbstyle.parse.MBObjectParser; import org.geotools.styling.*; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.ParseException; import org.junit.Before; import org.junit.Test; import org.opengis.feature.simple.SimpleFeature; import org.opengis.filter.FilterFactory2; import org.opengis.filter.expression.Expression; import org.opengis.style.GraphicalSymbol; import java.awt.*; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import static org.junit.Assert.*; /** * Test parsing and transforming a Mapbox fill layer from json. */ public class StyleTransformTest { static FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(); Map<String, JSONObject> testLayersById = new HashMap<>(); @Before public void setUp() throws IOException, ParseException { JSONObject jsonObject = MapboxTestUtils.parseTestStyle("functionParseTest.json"); JSONArray layers = (JSONArray) jsonObject.get("layers"); for (Object o : layers) { JSONObject layer = (JSONObject) o; testLayersById.put((String) layer.get("id"), layer); } } /** * Test parsing a Mapbox fill layer */ @Test public void testFill() throws IOException, ParseException { JSONObject jsonObject = parseTestStyle("fillStyleTest.json"); // Parse to MBStyle MBStyle mbStyle = new MBStyle(jsonObject); List<MBLayer> layers = mbStyle.layers("geoserver-states"); assertEquals(1, layers.size()); // Find the MBFillLayer and assert it contains the correct FeatureTypeStyle. assertTrue(layers.get(0) instanceof FillMBLayer); FillMBLayer mbFill = (FillMBLayer) layers.get(0); List<FeatureTypeStyle >fts = mbFill.transform(mbStyle); PolygonSymbolizer psym = SLD.polySymbolizer(fts.get(0)); Expression expr = psym.getFill().getColor(); assertNotNull("fillColor set", expr); assertEquals( Color.decode("#FF595E"), expr.evaluate(null,Color.class) ); assertEquals(Double.valueOf(.84), psym.getFill().getOpacity().evaluate(null, Double.class)); Expression colorStroke = psym.getStroke().getColor(); assertNotNull("stroke color set", colorStroke); assertEquals(Color.decode("#1982C4"), colorStroke.evaluate(null, Color.class)); assertNotNull("displacement not null", psym.getDisplacement()); assertNotNull("displacementX not null", psym.getDisplacement().getDisplacementX()); assertNotNull("displacementY not null", psym.getDisplacement().getDisplacementY()); assertEquals(Integer.valueOf(20), psym.getDisplacement().getDisplacementX().evaluate(null, Integer.class)); assertEquals(Integer.valueOf(20), psym.getDisplacement().getDisplacementY().evaluate(null, Integer.class)); } /** * Test parsing and generating a MapBox fill extrusion */ //@Test public void testFillExtrusion() throws IOException, ParseException { JSONObject jsonObject = parseTestStyle("fillExtrusionTest.json"); // Parse to MBStyle MBStyle mbStyle = new MBStyle(jsonObject); List<MBLayer> layers = mbStyle.layers("composite"); assertEquals(2, layers.size()); // Find the MBFillLayer and assert it contains the correct FeatureTypeStyle. assertTrue(layers.get(1) instanceof FillExtrusionMBLayer); FillExtrusionMBLayer mbFill = (FillExtrusionMBLayer) layers.get(1); List<FeatureTypeStyle> fts = mbFill.transform(mbStyle); PolygonSymbolizer psym = SLD.polySymbolizer(fts.get(0)); Expression expr = psym.getFill().getColor(); assertNotNull("fillColor set", expr); assertEquals( Color.decode("#FF595E"), expr.evaluate(null,Color.class) ); assertEquals(Double.valueOf(.91), psym.getFill().getOpacity().evaluate(null, Double.class)); assertNotNull("displacement not null", psym.getDisplacement()); assertNotNull("displacementX not null", psym.getDisplacement().getDisplacementX()); assertNotNull("displacementY not null", psym.getDisplacement().getDisplacementY()); assertEquals(Integer.valueOf(0), psym.getDisplacement().getDisplacementX().evaluate(null, Integer.class)); assertEquals(Integer.valueOf(30), psym.getDisplacement().getDisplacementY().evaluate(null, Integer.class)); } /** * Test parsing a Mapbox fill layer using a sprite fill-pattern */ @Test public void testFillSprite() throws IOException, ParseException { JSONObject jsonObject = parseTestStyle("fillStyleSpriteTest.json"); // Parse to MBStyle MBStyle mbStyle = new MBStyle(jsonObject); List<MBLayer> layers = mbStyle.layers("geoserver-states"); assertEquals(1, layers.size()); // Find the MBFillLayer and assert it contains the correct FeatureTypeStyle. assertTrue(layers.get(0) instanceof FillMBLayer); FillMBLayer mbFill = (FillMBLayer) layers.get(0); List<FeatureTypeStyle> fts = mbFill.transform(mbStyle); PolygonSymbolizer psym = SLD.polySymbolizer(fts.get(0)); Graphic g = psym.getFill().getGraphicFill(); assertNotNull(g); assertNotNull(g.graphicalSymbols()); assertEquals(1, g.graphicalSymbols().size()); } /** * Test parsing a Mapbox raster layer */ @Test public void testRaster() throws IOException, ParseException { JSONObject jsonObject = parseTestStyle("rasterStyleTest.json"); // Find the MBFillLayer and assert it contains the correct FeatureTypeStyle. MBStyle mbStyle = new MBStyle(jsonObject); List<MBLayer> layers = mbStyle.layers("geoserver-raster"); assertEquals(1, layers.size()); assertTrue(layers.get(0) instanceof RasterMBLayer); RasterMBLayer mbFill = (RasterMBLayer) layers.get(0); List<FeatureTypeStyle> fts = mbFill.transform(mbStyle); assertEquals(1, fts.get(0).rules().size()); Rule r = fts.get(0).rules().get(0); assertEquals(1, r.symbolizers().size()); Symbolizer symbolizer = r.symbolizers().get(0); assertTrue(symbolizer instanceof RasterSymbolizer); RasterSymbolizer rsym = (RasterSymbolizer) symbolizer; assertEquals(Double.valueOf(.59), rsym.getOpacity().evaluate(null, Double.class)); } /** * Test parsing a Mapbox line layer */ @Test public void testLine() throws IOException, ParseException { JSONObject jsonObject = parseTestStyle("lineStyleTest.json"); // Find the LineMBLayer and assert it contains the correct FeatureTypeStyle. MBStyle mbStyle = new MBStyle(jsonObject); List<MBLayer> layers = mbStyle.layers("test-source"); assertEquals(1, layers.size()); assertTrue(layers.get(0) instanceof LineMBLayer); LineMBLayer mbLine = (LineMBLayer) layers.get(0); List<FeatureTypeStyle> fts = mbLine.transform(mbStyle); assertEquals(1, fts.get(0).rules().size()); Rule r = fts.get(0).rules().get(0); assertEquals(1, r.symbolizers().size()); Symbolizer symbolizer = r.symbolizers().get(0); assertTrue(symbolizer instanceof LineSymbolizer); LineSymbolizer lsym = (LineSymbolizer) symbolizer; assertEquals(new Color(0, 153, 255), lsym.getStroke().getColor().evaluate(null, Color.class)); assertEquals("square", lsym.getStroke().getLineCap().evaluate(null, String.class)); assertEquals("round", lsym.getStroke().getLineJoin().evaluate(null, String.class)); assertEquals(.5d, lsym.getStroke().getOpacity().evaluate(null, Double.class), .0001); assertEquals(Integer.valueOf(10), lsym.getStroke().getWidth().evaluate(null, Integer.class)); assertEquals(Integer.valueOf(4), lsym.getPerpendicularOffset().evaluate(null, Integer.class)); List<Integer> expectedDashes = Arrays.asList(50, 50); assertEquals(expectedDashes.size(), lsym.getStroke().dashArray().size()); for (int i = 0; i < expectedDashes.size(); i++) { Integer n = (Integer) lsym.getStroke().dashArray().get(i).evaluate(null, Integer.class); assertEquals(expectedDashes.get(i), n); } } @Test public void testLineDefaults() throws IOException, ParseException { JSONObject jsonObject = parseTestStyle("lineStyleTestEmpty.json"); // Find the LineMBLayer and assert it contains the correct FeatureTypeStyle. MBStyle mbStyle = new MBStyle(jsonObject); List<MBLayer> layers = mbStyle.layers("test-source"); assertEquals(1, layers.size()); assertTrue(layers.get(0) instanceof LineMBLayer); LineMBLayer mbLine = (LineMBLayer) layers.get(0); List<FeatureTypeStyle> fts = mbLine.transform(mbStyle); assertEquals(1, fts.get(0).rules().size()); Rule r = fts.get(0).rules().get(0); assertEquals(1, r.symbolizers().size()); Symbolizer symbolizer = r.symbolizers().get(0); assertTrue(symbolizer instanceof LineSymbolizer); LineSymbolizer lsym = (LineSymbolizer) symbolizer; assertEquals(Color.BLACK, lsym.getStroke().getColor().evaluate(null, Color.class)); assertEquals("butt", lsym.getStroke().getLineCap().evaluate(null, String.class)); assertEquals("mitre", lsym.getStroke().getLineJoin().evaluate(null, String.class)); assertEquals(Integer.valueOf(1), lsym.getStroke().getOpacity().evaluate(null, Integer.class)); assertEquals(Integer.valueOf(1), lsym.getStroke().getWidth().evaluate(null, Integer.class)); assertEquals(Integer.valueOf(0), lsym.getPerpendicularOffset().evaluate(null, Integer.class)); assertTrue(lsym.getStroke().dashArray() == null); } @Test public void testCircle() throws IOException, ParseException { JSONObject jsonObject = parseTestStyle("circleStyleTest.json"); // Find the CircleMBLayer and assert it contains the correct FeatureTypeStyle. MBStyle mbStyle = new MBStyle(jsonObject); List<MBLayer> layers = mbStyle.layers("test-source"); assertEquals(1, layers.size()); assertTrue(layers.get(0) instanceof CircleMBLayer); CircleMBLayer mbCircle = (CircleMBLayer) layers.get(0); List<FeatureTypeStyle> fts = mbCircle.transform(mbStyle); assertEquals(1, fts.get(0).rules().size()); Rule r = fts.get(0).rules().get(0); assertEquals(1, r.symbolizers().size()); Symbolizer symbolizer = r.symbolizers().get(0); assertTrue(symbolizer instanceof PointSymbolizer); PointSymbolizer psym = (PointSymbolizer) symbolizer; assertTrue(psym.getGraphic() != null); assertEquals(Integer.valueOf(30), psym.getGraphic().getSize().evaluate(null, Integer.class)); assertNotNull(psym.getGraphic().getDisplacement()); assertEquals(Integer.valueOf(10), psym.getGraphic().getDisplacement().getDisplacementX().evaluate(null, Integer.class)); assertEquals(Integer.valueOf(10),psym.getGraphic().getDisplacement().getDisplacementY().evaluate(null, Integer.class)); assertEquals(1, psym.getGraphic().graphicalSymbols().size()); GraphicalSymbol gs = psym.getGraphic().graphicalSymbols().get(0); assertTrue(gs instanceof Mark); Mark m = (Mark) gs; assertNotNull(m.getFill()); assertEquals(Color.RED, m.getFill().getColor().evaluate(null, Color.class)); assertEquals(Double.valueOf(.5), m.getFill().getOpacity().evaluate(null, Double.class), .0001); assertNotNull(m.getStroke()); assertEquals(Color.GREEN, m.getStroke().getColor().evaluate(null, Color.class)); assertEquals(Integer.valueOf(2), m.getStroke().getWidth().evaluate(null, Integer.class)); assertEquals(Double.valueOf(.75), m.getStroke().getOpacity().evaluate(null, Double.class), .0001); } @Test public void testCircleDefaults() throws IOException, ParseException { JSONObject jsonObject = parseTestStyle("circleStyleTestDefaults.json"); // Find the CircleMBLayer and assert it contains the correct FeatureTypeStyle. MBStyle mbStyle = new MBStyle(jsonObject); List<MBLayer> layers = mbStyle.layers("test-source"); assertEquals(1, layers.size()); assertTrue(layers.get(0) instanceof CircleMBLayer); CircleMBLayer mbCircle = (CircleMBLayer) layers.get(0); List<FeatureTypeStyle> fts = mbCircle.transform(mbStyle); assertEquals(1, fts.get(0).rules().size()); Rule r = fts.get(0).rules().get(0); assertEquals(1, r.symbolizers().size()); Symbolizer symbolizer = r.symbolizers().get(0); assertTrue(symbolizer instanceof PointSymbolizer); PointSymbolizer psym = (PointSymbolizer) symbolizer; assertTrue(psym.getGraphic() != null); assertEquals(Integer.valueOf(10), psym.getGraphic().getSize().evaluate(null, Integer.class)); if (psym.getGraphic().getDisplacement() != null) { assertEquals(Integer.valueOf(0), psym.getGraphic().getDisplacement().getDisplacementX() .evaluate(null, Integer.class)); assertEquals(Integer.valueOf(0), psym.getGraphic().getDisplacement().getDisplacementY() .evaluate(null, Integer.class)); } assertEquals(1, psym.getGraphic().graphicalSymbols().size()); GraphicalSymbol gs = psym.getGraphic().graphicalSymbols().get(0); assertTrue(gs instanceof Mark); Mark m = (Mark) gs; assertNotNull(m.getFill()); assertEquals(Color.BLACK, m.getFill().getColor().evaluate(null, Color.class)); assertEquals(Integer.valueOf(1), m.getFill().getOpacity().evaluate(null, Integer.class)); assertNotNull(m.getStroke()); assertEquals(Color.BLACK, m.getStroke().getColor().evaluate(null, Color.class)); assertEquals(Integer.valueOf(0), m.getStroke().getWidth().evaluate(null, Integer.class)); assertEquals(Integer.valueOf(1), m.getStroke().getOpacity().evaluate(null, Integer.class)); } @Test public void testBackgroundColor() throws IOException, ParseException { JSONObject jsonObject = parseTestStyle("backgroundColorStyleTest.json"); // Find the CircleMBLayer and assert it contains the correct FeatureTypeStyle. MBStyle mbStyle = new MBStyle(jsonObject); List<MBLayer> layers = mbStyle.layers("test-source"); assertEquals(1, layers.size()); assertTrue(layers.get(0) instanceof BackgroundMBLayer); List<FeatureTypeStyle> fts = layers.get(0).transform(mbStyle); assertEquals(1, fts.get(0).rules().size()); Rule r = fts.get(0).rules().get(0); assertEquals(1, r.symbolizers().size()); Symbolizer symbolizer = r.symbolizers().get(0); assertTrue(symbolizer instanceof PolygonSymbolizer); PolygonSymbolizer psym = (PolygonSymbolizer) symbolizer; assertEquals(Color.GREEN, psym.getFill().getColor().evaluate(null, Color.class)); assertEquals(Double.valueOf(.45), psym.getFill().getOpacity().evaluate(null, Double.class), .0001); assertNull(psym.getStroke()); } @Test public void testBackgroundDefaults() throws IOException, ParseException { JSONObject jsonObject = parseTestStyle("backgroundStyleTestDefault.json"); // Find the CircleMBLayer and assert it contains the correct FeatureTypeStyle. MBStyle mbStyle = new MBStyle(jsonObject); List<MBLayer> layers = mbStyle.layers("test-source"); assertEquals(1, layers.size()); assertTrue(layers.get(0) instanceof BackgroundMBLayer); List<FeatureTypeStyle> fts = layers.get(0).transform(mbStyle); assertEquals(1, fts.get(0).rules().size()); Rule r = fts.get(0).rules().get(0); assertEquals(1, r.symbolizers().size()); Symbolizer symbolizer = r.symbolizers().get(0); assertTrue(symbolizer instanceof PolygonSymbolizer); PolygonSymbolizer psym = (PolygonSymbolizer) symbolizer; assertEquals(Color.BLACK, psym.getFill().getColor().evaluate(null, Color.class)); assertEquals(Integer.valueOf(1), psym.getFill().getOpacity().evaluate(null, Integer.class)); assertNull(psym.getStroke()); } @Test public void testBackgroundPattern() throws IOException, ParseException { JSONObject jsonObject = parseTestStyle("backgroundImgStyleTest.json"); MBStyle mbStyle = new MBStyle(jsonObject); List<MBLayer> layers = mbStyle.layers("test-source"); assertEquals(1, layers.size()); assertTrue(layers.get(0) instanceof BackgroundMBLayer); List<FeatureTypeStyle> fts = layers.get(0).transform(mbStyle); assertEquals(1, fts.get(0).rules().size()); Rule r = fts.get(0).rules().get(0); assertEquals(1, r.symbolizers().size()); Symbolizer symbolizer = r.symbolizers().get(0); assertTrue(symbolizer instanceof PolygonSymbolizer); PolygonSymbolizer psym = (PolygonSymbolizer) symbolizer; assertEquals(Color.GREEN, psym.getFill().getColor().evaluate(null, Color.class)); assertEquals(1, psym.getFill().getGraphicFill().graphicalSymbols().size()); assertEquals(Double.valueOf(0.75), psym.getFill().getOpacity().evaluate(null, Double.class)); assertNull(psym.getStroke()); } @Test public void testSymbolFont() throws IOException, ParseException { JSONObject jsonObject = parseTestStyle("symbolTextTest.json"); MBStyle mbStyle = new MBStyle(jsonObject); List<MBLayer> layers = mbStyle.layers("test-source"); assertEquals(1, layers.size()); assertTrue(layers.get(0) instanceof SymbolMBLayer); List<FeatureTypeStyle> fts = layers.get(0).transform(mbStyle); assertEquals(1, fts.get(0).rules().size()); Rule r = fts.get(0).rules().get(0); assertEquals(1, r.symbolizers().size()); Symbolizer symbolizer = r.symbolizers().get(0); assertTrue(symbolizer instanceof TextSymbolizer); TextSymbolizer tsym = (TextSymbolizer) symbolizer; assertEquals(1, tsym.fonts().size()); assertEquals(2, tsym.fonts().get(0).getFamily().size()); assertEquals("Some Test Font", tsym.fonts().get(0).getFamily().get(0).toString()); assertEquals("Other Test Font", tsym.fonts().get(0).getFamily().get(1).toString()); } /** * * Read a test Mapbox Style file (json) and parse it into a {@link JSONObject}. */ private JSONObject parseTestStyle(String filename) throws IOException, ParseException { return MapboxTestUtils.parseTestStyle(filename); } @Test public void testMapboxTokenValues() throws Exception { File property = new File(TestData.getResource(this, "testpoints.properties").toURI()); PropertyDataStore ds = new PropertyDataStore(property.getParentFile()); ContentFeatureSource pointFS = ds.getFeatureSource("testpoints"); MBStyleTransformer transformer =new MBStyleTransformer(new MBObjectParser(SymbolMBLayer.class)); Expression e = transformer.cqlExpressionFromTokens("Replace text here: \"{text}\""); Map<String, String> m = new HashMap<>(); SimpleFeatureIterator sfi = pointFS.getFeatures().features(); while (sfi.hasNext()) { SimpleFeature sf = sfi.next(); String s = e.evaluate(sf, String.class); } } }