/* (c) 2017 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.legendgraphic;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import javax.xml.namespace.QName;
import org.geoserver.catalog.Catalog;
import org.geoserver.data.test.MockData;
import org.geoserver.data.test.SystemTestData;
import org.geoserver.ows.util.KvpUtils;
import org.geoserver.wms.GetLegendGraphicRequest;
import org.geoserver.wms.GetLegendGraphicRequest.LegendRequest;
import org.geoserver.wms.WMSTestSupport;
import org.geoserver.wms.wms_1_1_1.GetMapIntegrationTest;
import org.geotools.styling.FeatureTypeStyle;
import org.geotools.styling.Rule;
import org.geotools.styling.Style;
import org.geotools.styling.visitor.DuplicatingStyleVisitor;
import org.junit.Before;
import org.junit.Test;
public class FeatureCountLegendGraphicTest extends WMSTestSupport {
private static final QName SF_STATES = new QName(MockData.SF_URI, "states", MockData.SF_PREFIX);
private BufferedImageLegendGraphicBuilder legendProducer;
private List<Rule[]> ruleSets = new ArrayList<>();
private GetLegendGraphicRequest lastRequest;
@Override
protected void onSetUp(SystemTestData testData) throws Exception {
super.onSetUp(testData);
Catalog catalog = getCatalog();
testData.addStyle("Population", "Population.sld", GetMapIntegrationTest.class, catalog);
testData.addVectorLayer(SF_STATES, Collections.EMPTY_MAP, "states.properties",
GetMapIntegrationTest.class, catalog);
}
@Before
public void setupLegendProducer() throws Exception {
this.ruleSets.clear();
this.legendProducer = new BufferedImageLegendGraphicBuilder() {
public String getContentType() {
return "image/png";
}
@Override
protected Rule[] updateRuleTitles(FeatureCountProcessor processor, LegendRequest legend,
Rule[] applicableRules) {
Rule[] updatedRules = super.updateRuleTitles(processor, legend, applicableRules);
FeatureCountLegendGraphicTest.this.ruleSets.add(updatedRules);
return updatedRules;
}
};
}
@Test
public void testBasicPolygonsNoCount() throws Exception {
runGetLegendGraphics("wms?service=WMS&version=1.1.1&request=GetLegendGraphic" + "&layer="
+ getLayerId(MockData.BASIC_POLYGONS) + "&format=image/png");
assertEquals(0, ruleSets.size());
}
@Test
public void testBasicPolygonsNoLabels() throws Exception {
runGetLegendGraphics("wms?service=WMS&version=1.1.1&request=GetLegendGraphic" + "&layer="
+ getLayerId(MockData.BASIC_POLYGONS) + "&style="
+ "&format=image/png&SRS=EPSG%3A4326&WIDTH=256&HEIGHT=256&BBOX=30,0,40,10"
+ "&legend_options=" + GetLegendGraphicRequest.COUNT_MATCHED_KEY
+ ":true;forceLabels:off");
assertEquals(0, ruleSets.size());
}
@Test
public void testBasicPolygonsNoFeatures() throws Exception {
runGetLegendGraphics("wms?service=WMS&version=1.1.1&request=GetLegendGraphic" + "&layer="
+ getLayerId(MockData.BASIC_POLYGONS) + "&style="
+ "&format=image/png&SRS=EPSG%3A4326&WIDTH=256&HEIGHT=256&BBOX=30,0,40,10"
+ "&legend_options=" + GetLegendGraphicRequest.COUNT_MATCHED_KEY + ":true");
assertEquals(1, ruleSets.size());
Rule[] rules = ruleSets.get(0);
assertEquals(1, rules.length);
assertLabel("(0)", rules[0]);
}
@Test
public void testBasicPolygonsTwoFeatures() throws Exception {
runGetLegendGraphics("wms?service=WMS&version=1.1.1&request=GetLegendGraphic" + "&layer="
+ getLayerId(MockData.BASIC_POLYGONS) + "&style="
+ "&format=image/png&SRS=EPSG%3A4326&WIDTH=256&HEIGHT=256&BBOX=-2.4,1.4,0.4,4.2"
+ "&legend_options=" + GetLegendGraphicRequest.COUNT_MATCHED_KEY + ":true");
assertEquals(1, ruleSets.size());
Rule[] rules = ruleSets.get(0);
assertEquals(1, rules.length);
assertLabel("(2)", rules[0]);
}
@Test
public void testBasicPolygonsTwoFeaturesWms13() throws Exception {
runGetLegendGraphics("wms?service=WMS&version=1.3.0&request=GetLegendGraphic" + "&layer="
+ getLayerId(MockData.BASIC_POLYGONS) + "&style="
+ "&format=image/png&CRS=EPSG%3A4326&WIDTH=256&HEIGHT=256&BBOX=1.4,-2.4,4.2,0.4"
+ "&legend_options=" + GetLegendGraphicRequest.COUNT_MATCHED_KEY + ":true");
assertEquals(1, ruleSets.size());
Rule[] rules = ruleSets.get(0);
assertEquals(1, rules.length);
assertLabel("(2)", rules[0]);
}
@Test
public void testBasicPolygonsAllFeatures() throws Exception {
runGetLegendGraphics(
"wms?service=WMS&version=1.1.1&request=GetLegendGraphic&format=image/png"
+ "&layer=" + getLayerId(MockData.BASIC_POLYGONS) + "&style="
+ "&SRS=EPSG%3A4326&WIDTH=256&HEIGHT=256&BBOX=-180,-90,180,90"
+ "&legend_options=" + GetLegendGraphicRequest.COUNT_MATCHED_KEY + ":true");
assertEquals(1, ruleSets.size());
Rule[] rules = ruleSets.get(0);
assertEquals(1, rules.length);
assertLabel("(3)", rules[0]);
}
@Test
public void testStatesFull() throws Exception {
runGetLegendGraphics(
"wms?service=WMS&version=1.1.1&request=GetLegendGraphic&format=image/png"
+ "&layer=" + getLayerId(SF_STATES)
+ "&style=Population&width=550&height=250&srs=EPSG:4326" //
+ "&bbox=" + "-130,24,-66,50" + "&legend_options="
+ GetLegendGraphicRequest.COUNT_MATCHED_KEY + ":true");
assertEquals(1, ruleSets.size());
Rule[] rules = ruleSets.get(0);
logLabels(rules);
assertEquals(4, rules.length);
assertLabel("2M - 4M (10)", rules[0]);
assertLabel("< 2M (16)", rules[1]);
assertLabel("> 4M (23)", rules[2]);
// this is the rule for outline and text symbolizer, Alaska and Hawaii are not in the
// map but Washington DC is and it's not a state (50 - 2 + 1)
assertLabel("(49)", rules[3]);
}
@Test
public void testStatesCqlFilter() throws Exception {
runGetLegendGraphics(
"wms?service=WMS&version=1.1.1&request=GetLegendGraphic&format=image/png"
+ "&layer=" + getLayerId(SF_STATES)
+ "&style=Population&width=550&height=250&srs=EPSG:4326" //
+ "&bbox=" + "-130,24,-66,50" + "&legend_options="
+ GetLegendGraphicRequest.COUNT_MATCHED_KEY + ":true"
+ "&CQL_FILTER=PERSONS < 2000000");
assertEquals(1, ruleSets.size());
Rule[] rules = ruleSets.get(0);
logLabels(rules);
assertEquals(4, rules.length);
assertLabel("2M - 4M (0)", rules[0]);
assertLabel("< 2M (16)", rules[1]);
assertLabel("> 4M (0)", rules[2]);
assertLabel("(16)", rules[3]);
}
@Test
public void testStatesMatchFirst() throws Exception {
String requestURL = "wms?service=WMS&version=1.1.1&request=GetLegendGraphic&format=image/png"
+ "&layer=" + getLayerId(SF_STATES)
+ "&style=Population&width=550&height=250&srs=EPSG:4326" //
+ "&bbox=" + "-130,24,-66,50" //
+ "&legend_options=" + GetLegendGraphicRequest.COUNT_MATCHED_KEY + ":true"
+ "&CQL_FILTER=PERSONS < 2000000";
Map rawKvp = (Map) caseInsensitiveKvp(KvpUtils.parseQueryString(requestURL));
Map kvp = parseKvp(rawKvp);
GetLegendGraphicKvpReader reader = new GetLegendGraphicKvpReader(getWMS());
GetLegendGraphicRequest request = reader.read(reader.createRequest(), kvp, rawKvp);
// switch the FTS to match first, the last rule should never be hit
final LegendRequest legend = request.getLegends().get(0);
final Style style = legend.getStyle();
DuplicatingStyleVisitor matchFirstCloner = new DuplicatingStyleVisitor() {
public void visit(FeatureTypeStyle fts) {
super.visit(fts);
FeatureTypeStyle copy = (FeatureTypeStyle) pages.peek();
copy.getOptions().put(FeatureTypeStyle.KEY_EVALUATION_MODE,
FeatureTypeStyle.VALUE_EVALUATION_MODE_FIRST);
};
};
style.accept(matchFirstCloner);
legend.setStyle((Style) matchFirstCloner.getCopy());
// run
legendProducer.buildLegendGraphic(request);
this.lastRequest = request;
assertEquals(1, ruleSets.size());
Rule[] rules = ruleSets.get(0);
logLabels(rules);
assertEquals(4, rules.length);
assertLabel("2M - 4M (0)", rules[0]);
assertLabel("< 2M (16)", rules[1]);
assertLabel("> 4M (0)", rules[2]);
assertLabel("(0)", rules[3]);
}
@Test
public void testCountOnGroup() throws Exception {
String url = "wms?service=WMS&version=1.1.1&request=GetLegendGraphic&format=image/png"
+ "&layer=nature&width=100&height=100"
+ "&srs=epsg:4326&bbox=-0.002,-0.003,0.005,0.002" + "&legend_options="
+ GetLegendGraphicRequest.COUNT_MATCHED_KEY + ":true";
runGetLegendGraphics(url);
for (Rule[] rules : ruleSets) {
logLabels(rules);
}
// two layers, one rule each
assertEquals(2, ruleSets.size());
assertEquals(1, ruleSets.get(0).length);
assertEquals(1, ruleSets.get(1).length);
// boring case, the title is just title
assertLabel("title (1)", ruleSets.get(0)[0]);
assertLabel("title (1)", ruleSets.get(1)[0]);
}
private void logLabels(Rule[] rules) {
LOGGER.log(Level.INFO, lastRequest.toString());
for (Rule rule : rules) {
LOGGER.log(Level.INFO, LegendUtils.getRuleLabel(rule, lastRequest));
}
}
private void assertLabel(String expected, Rule rule) {
String actual = LegendUtils.getRuleLabel(rule, lastRequest);
assertThat(actual, equalTo(expected));
}
private GetLegendGraphicRequest runGetLegendGraphics(String requestURL) throws Exception {
Map rawKvp = (Map) caseInsensitiveKvp(KvpUtils.parseQueryString(requestURL));
Map kvp = parseKvp(rawKvp);
GetLegendGraphicKvpReader reader = new GetLegendGraphicKvpReader(getWMS());
GetLegendGraphicRequest request = reader.read(reader.createRequest(), kvp, rawKvp);
legendProducer.buildLegendGraphic(request);
this.lastRequest = request;
return request;
}
}