/* (c) 2014 Open Source Geospatial Foundation - all rights reserved * Copyright (C) 2007-2008-2009 GeoSolutions S.A.S. * http://www.geo-solutions.it * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.sldservice.utils.classifier; import java.io.IOException; import java.util.Iterator; import java.util.TreeSet; import org.geoserver.sldservice.rest.resource.ClassifierResource; import org.geotools.data.DataUtilities; import org.geotools.data.memory.MemoryDataStore; import org.geotools.data.simple.SimpleFeatureCollection; import org.geotools.data.simple.SimpleFeatureSource; import org.geotools.factory.CommonFactoryFinder; import org.geotools.factory.GeoTools; import org.geotools.factory.Hints; import org.geotools.feature.simple.SimpleFeatureBuilder; import org.geotools.filter.function.FilterFunction_parseDouble; import org.geotools.styling.PolygonSymbolizer; import org.geotools.styling.Rule; import org.mockito.Mockito; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.filter.FilterFactory2; import org.restlet.resource.Representation; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.GeometryFactory; public class ClassifierTestSupport extends SLDServiceBaseTest { private static final int DEFAULT_INTERVALS = 2; protected SimpleFeatureCollection pointCollection, lineCollection; FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(GeoTools.getDefaultHints()); protected SimpleFeatureType dataType; protected SimpleFeature[] testFeatures; ClassifierResource resource; private static final String sldPrefix = "<StyledLayerDescriptor><NamedLayer><Name>feature</Name><UserStyle><FeatureTypeStyle>"; private static final String sldPostfix = "</FeatureTypeStyle></UserStyle></NamedLayer></StyledLayerDescriptor>"; @Override public void setUp() throws Exception { super.setUp(); resource = new ClassifierResource(context, request, response, catalog); dataType = DataUtilities.createType("classification.test1", "id:0,name:string,foo:int,bar:double,geom:Point,group:String"); int iVal[] = new int[] { 4, 90, 20, 43, 29, 61, 8, 12 }; double dVal[] = new double[] { 2.5, 80.433, 24.5, 9.75, 18, 53, 43.2, 16 }; String[] names = new String[] {"foo", "bar", "bar", "foo", "foobar", "bar", "foo", "foo"}; testFeatures = new SimpleFeature[iVal.length]; GeometryFactory fac = new GeometryFactory(); for (int i = 0; i < iVal.length; i++) { testFeatures[i] = SimpleFeatureBuilder.build(dataType, new Object[] { new Integer(i + 1), names[i], new Integer(iVal[i]), new Double(dVal[i]), fac.createPoint(new Coordinate(iVal[i], iVal[i])), "Group" + (i % 4) }, "classification.t" + (i + 1)); } MemoryDataStore store = new MemoryDataStore(); store.createSchema(dataType); store.addFeatures(testFeatures); SimpleFeatureSource featureSource = store.getFeatureSource("test1"); pointCollection = featureSource.getFeatures(); double[] jenks71 = { 50.12, 83.9, 76.43, 71.61, 79.66, 84.84, 87.87, 92.45, 119.9, 155.3, 131.5, 111.8, 96.78, 86.75, 62.41, 96.37, 75.51, 77.29, 85.41, 116.4, 58.5, 75.29, 66.32, 62.65, 80.45, 72.76, 63.67, 60.27, 68.45, 100.1, 55.3, 54.07, 57.49, 73.52, 68.25, 64.28, 50.64, 52.47, 68.19, 57.4, 39.72, 60.66, 57.59, 38.22, 57.22, 67.04, 47.29, 71.05, 50.53, 34.63, 59.65, 62.06, 52.89, 56.35, 57.26, 53.77, 59.89, 55.44, 45.4, 52.21, 49.38, 51.15, 54.27, 54.32, 41.2, 34.58, 50.11, 52.05, 33.82, 39.88, 36.24, 41.02, 46.13, 51.15, 32.28, 33.26, 31.78, 31.28, 50.52, 47.21, 32.69, 38.3, 33.83, 40.3, 40.62, 32.14, 31.66, 26.09, 39.84, 24.83, 28.2, 31.19, 37.57, 27.16, 23.42, 18.57, 30.97, 17.82, 15.57, 15.93, 28.71, 32.22 }; SimpleFeature[] features = new SimpleFeature[jenks71.length]; SimpleFeatureType jenksType = DataUtilities.createType("jenks71", "id:0,jenks71:double,geom:LineString"); for(int i=0;i<jenks71.length;i++) { features[i] = SimpleFeatureBuilder.build(jenksType, new Object[] { new Integer(i + 1), new Double(jenks71[i]), fac.createLineString(new Coordinate[]{new Coordinate(jenks71[i], jenks71[i]), new Coordinate(jenks71[i]-1.0, jenks71[i]+1.0)})},"jenks"+i); } MemoryDataStore jenks = new MemoryDataStore(); jenks.createSchema(jenksType); jenks.addFeatures(features); lineCollection = jenks.getFeatureSource("jenks71").getFeatures(); Mockito.doReturn(featureSource).when(resourcePool) .getFeatureSource(Mockito.eq(testFeatureTypeInfo), Mockito.any(Hints.class)); } public void testClassifyForFeatureDefault() throws IOException { attributes.put("layer", FEATURETYPE_LAYER); attributes.put("attribute", "foo"); initRequestUrl(request, "xml"); resource.handleGet(); assertNotNull(responseEntity); assertTrue(responseEntity instanceof Representation); Representation representation = (Representation)responseEntity; String resultXml = representation.getText().replace("\r", "").replace("\n", ""); Rule[] rules = checkRules(resultXml.replace("<Rules>", sldPrefix).replace("</Rules>", sldPostfix), DEFAULT_INTERVALS); checkRule(rules[0], "#680000", org.opengis.filter.And.class); checkRule(rules[1], "#B20000", org.opengis.filter.And.class); } public void testClassifyOpenRange() throws IOException { attributes.put("layer", FEATURETYPE_LAYER); attributes.put("attribute", "id"); attributes.put("intervals", 3); attributes.put("open", true); initRequestUrl(request, "xml"); resource.handleGet(); assertNotNull(responseEntity); assertTrue(responseEntity instanceof Representation); Representation representation = (Representation)responseEntity; String resultXml = representation.getText().replace("\r", "").replace("\n", ""); Rule[] rules = checkRules(resultXml.replace("<Rules>", sldPrefix).replace("</Rules>", sldPostfix), 3); checkRule(rules[0], "#550000", org.opengis.filter.PropertyIsLessThanOrEqualTo.class); checkRule(rules[1], "#8C0000", org.opengis.filter.And.class); checkRule(rules[2], "#C30000", org.opengis.filter.PropertyIsGreaterThan.class); } public void testQuantile() throws IOException { attributes.put("layer", FEATURETYPE_LAYER); attributes.put("attribute", "foo"); attributes.put("intervals", 3); attributes.put("open", true); attributes.put("method", "quantile"); initRequestUrl(request, "xml"); resource.handleGet(); assertNotNull(responseEntity); assertTrue(responseEntity instanceof Representation); Representation representation = (Representation)responseEntity; String resultXml = representation.getText().replace("\r", "").replace("\n", ""); Rule[] rules = checkRules(resultXml.replace("<Rules>", sldPrefix).replace("</Rules>", sldPostfix), 3); assertTrue(rules[0].getTitle().contains("20.0")); assertTrue(rules[1].getTitle().contains("20.0")); assertTrue(rules[1].getTitle().contains("61.0")); assertTrue(rules[2].getTitle().contains("61.0")); } public void testJenks() throws IOException { attributes.put("layer", FEATURETYPE_LAYER); attributes.put("attribute", "foo"); attributes.put("intervals", 3); attributes.put("open", true); attributes.put("method", "jenks"); initRequestUrl(request, "xml"); resource.handleGet(); assertNotNull(responseEntity); assertTrue(responseEntity instanceof Representation); Representation representation = (Representation)responseEntity; String resultXml = representation.getText().replace("\r", "").replace("\n", ""); Rule[] rules = checkRules(resultXml.replace("<Rules>", sldPrefix).replace("</Rules>", sldPostfix), 3); assertTrue(rules[0].getTitle().contains("12.0")); assertTrue(rules[1].getTitle().contains("12.0")); assertTrue(rules[1].getTitle().contains("29.0")); assertTrue(rules[2].getTitle().contains("29.0")); } public void testEqualInterval() throws IOException { attributes.put("layer", FEATURETYPE_LAYER); attributes.put("attribute", "foo"); attributes.put("intervals", 3); attributes.put("open", true); attributes.put("method", "equalInterval"); initRequestUrl(request, "xml"); resource.handleGet(); assertNotNull(responseEntity); assertTrue(responseEntity instanceof Representation); Representation representation = (Representation)responseEntity; String resultXml = representation.getText().replace("\r", "").replace("\n", ""); Rule[] rules = checkRules(resultXml.replace("<Rules>", sldPrefix).replace("</Rules>", sldPostfix), 3); assertTrue(rules[0].getTitle().contains("32.6")); assertTrue(rules[1].getTitle().contains("32.6")); assertTrue(rules[1].getTitle().contains("61.3")); assertTrue(rules[2].getTitle().contains("61.3")); } public void testUnique() throws IOException { attributes.put("layer", FEATURETYPE_LAYER); attributes.put("attribute", "name"); attributes.put("intervals", 3); attributes.put("method", "uniqueInterval"); initRequestUrl(request, "xml"); resource.handleGet(); assertNotNull(responseEntity); assertTrue(responseEntity instanceof Representation); Representation representation = (Representation)responseEntity; String resultXml = representation.getText().replace("\r", "").replace("\n", ""); Rule[] rules = checkRules(resultXml.replace("<Rules>", sldPrefix).replace("</Rules>", sldPostfix), 3); checkRule(rules[0], "#550000", org.opengis.filter.PropertyIsEqualTo.class); checkRule(rules[1], "#8C0000", org.opengis.filter.PropertyIsEqualTo.class); checkRule(rules[2], "#C30000", org.opengis.filter.PropertyIsEqualTo.class); TreeSet<String> orderedRules = new TreeSet<String>(); orderedRules.add(rules[0].getTitle()); orderedRules.add(rules[1].getTitle()); orderedRules.add(rules[2].getTitle()); Iterator iter = orderedRules.iterator(); assertEquals("bar", iter.next()); assertEquals("foo", iter.next()); assertEquals("foobar", iter.next()); } public void testBlueRamp() throws IOException { attributes.put("layer", FEATURETYPE_LAYER); attributes.put("attribute", "name"); attributes.put("intervals", 3); attributes.put("method", "uniqueInterval"); attributes.put("ramp", "blue"); initRequestUrl(request, "xml"); resource.handleGet(); assertNotNull(responseEntity); assertTrue(responseEntity instanceof Representation); Representation representation = (Representation)responseEntity; String resultXml = representation.getText().replace("\r", "").replace("\n", ""); Rule[] rules = checkRules(resultXml.replace("<Rules>", sldPrefix).replace("</Rules>", sldPostfix), 3); checkRule(rules[0], "#000055", org.opengis.filter.PropertyIsEqualTo.class); checkRule(rules[1], "#00008C", org.opengis.filter.PropertyIsEqualTo.class); checkRule(rules[2], "#0000C3", org.opengis.filter.PropertyIsEqualTo.class); } public void testReverse() throws IOException { attributes.put("layer", FEATURETYPE_LAYER); attributes.put("attribute", "name"); attributes.put("intervals", 3); attributes.put("method", "uniqueInterval"); attributes.put("ramp", "blue"); attributes.put("reverse", true); initRequestUrl(request, "xml"); resource.handleGet(); assertNotNull(responseEntity); assertTrue(responseEntity instanceof Representation); Representation representation = (Representation)responseEntity; String resultXml = representation.getText().replace("\r", "").replace("\n", ""); Rule[] rules = checkRules(resultXml.replace("<Rules>", sldPrefix).replace("</Rules>", sldPostfix), 3); checkRule(rules[0], "#0000C3", org.opengis.filter.PropertyIsEqualTo.class); checkRule(rules[1], "#00008C", org.opengis.filter.PropertyIsEqualTo.class); checkRule(rules[2], "#000055", org.opengis.filter.PropertyIsEqualTo.class); } public void testNormalize() throws IOException { attributes.put("layer", FEATURETYPE_LAYER); attributes.put("attribute", "id"); attributes.put("intervals", 3); attributes.put("open", true); attributes.put("normalize", true); initRequestUrl(request, "xml"); resource.handleGet(); assertNotNull(responseEntity); assertTrue(responseEntity instanceof Representation); Representation representation = (Representation)responseEntity; String resultXml = representation.getText().replace("\r", "").replace("\n", ""); Rule[] rules = checkRules(resultXml.replace("<Rules>", sldPrefix).replace("</Rules>", sldPostfix), 3); checkRule(rules[0], "#550000", org.opengis.filter.PropertyIsLessThanOrEqualTo.class); org.opengis.filter.PropertyIsLessThanOrEqualTo filter = (org.opengis.filter.PropertyIsLessThanOrEqualTo) rules[0].getFilter(); assertTrue(filter.getExpression1() instanceof FilterFunction_parseDouble); } public void testCustomRamp() throws IOException { attributes.put("layer", FEATURETYPE_LAYER); attributes.put("attribute", "name"); attributes.put("intervals", 3); attributes.put("method", "uniqueInterval"); attributes.put("ramp", "custom"); attributes.put("startColor", "0xFF0000"); attributes.put("endColor", "0x0000FF"); initRequestUrl(request, "xml"); resource.handleGet(); assertNotNull(responseEntity); assertTrue(responseEntity instanceof Representation); Representation representation = (Representation)responseEntity; String resultXml = representation.getText().replace("\r", "").replace("\n", ""); Rule[] rules = checkRules(resultXml.replace("<Rules>", sldPrefix).replace("</Rules>", sldPostfix), 3); checkRule(rules[0], "#FF0000", org.opengis.filter.PropertyIsEqualTo.class); checkRule(rules[1], "#AA0055", org.opengis.filter.PropertyIsEqualTo.class); checkRule(rules[2], "#5500AA", org.opengis.filter.PropertyIsEqualTo.class); } private void checkRule(Rule rule, String color, Class<?> filterType) { assertNotNull(rule.getFilter()); assertTrue(filterType.isAssignableFrom(rule.getFilter().getClass())); assertNotNull(rule.getSymbolizers()); assertEquals(1, rule.getSymbolizers().length); assertTrue(rule.getSymbolizers()[0] instanceof PolygonSymbolizer); PolygonSymbolizer symbolizer = (PolygonSymbolizer) rule.getSymbolizers()[0]; assertNotNull(symbolizer.getFill()); assertEquals(color, symbolizer.getFill().getColor().toString()); } public void testClassifyForCoverageIsEmpty() throws IOException { attributes.put("layer", COVERAGE_LAYER); initRequestUrl(request, "xml"); resource.handleGet(); assertNotNull(responseEntity); assertTrue(responseEntity instanceof Representation); Representation representation = (Representation)responseEntity; String resultXml = representation.getText().replace("\r", "").replace("\n", ""); assertEquals("<list/>", resultXml); } private Rule[] checkRules(String resultXml, int classes) { Rule[] rules = checkSLD(resultXml); assertEquals(classes, rules.length); return rules; } @Override protected String getServiceUrl() { return "classify"; } }