package org.mapfish.print.parser; import com.vividsolutions.jts.util.AssertionFailedException; import org.json.JSONException; import org.json.JSONObject; import org.junit.Assert; import org.junit.Test; import org.mapfish.print.AbstractMapfishSpringTest; import org.mapfish.print.ExtraPropertyException; import org.mapfish.print.MissingPropertyException; import org.mapfish.print.attribute.LegendAttribute; import org.mapfish.print.wrapper.PObject; import org.mapfish.print.wrapper.json.PJsonArray; import org.mapfish.print.wrapper.json.PJsonObject; import java.io.IOException; import java.net.URL; import java.util.regex.Matcher; import java.util.regex.Pattern; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mapfish.print.AbstractMapfishSpringTest.parseJSONObjectFromFile; public class MapfishParserTest { private final MapfishParser mapfishJsonParser = new MapfishParser(); @Test public void testNullOptionalArray() throws Exception { OptionalArrayParam p = new OptionalArrayParam(); final PJsonObject json = AbstractMapfishSpringTest.parseJSONObjectFromString("{\"sa\":null}"); this.mapfishJsonParser.parse(true, json, p, "toIgnore"); Assert.assertNull(p.sa); } @Test public void testEnum() throws Exception { TestEnumParam p = new TestEnumParam(); final PJsonObject json = AbstractMapfishSpringTest.parseJSONObjectFromString("{\"e1\":\"VAL1\", \"e2\": [1, \"VAL2\"]}"); this.mapfishJsonParser.parse(true, json, p, "toIgnore"); Assert.assertEquals(TestEnum.DEF, p.def2); Assert.assertEquals(TestEnum.VAL1, p.e1); Assert.assertArrayEquals(new TestEnum[]{TestEnum.VAL2, TestEnum.VAL2}, p.e2); } @Test public void testChoice() throws Exception { TestChoiceClass p = new TestChoiceClass(); PJsonObject json = AbstractMapfishSpringTest.parseJSONObjectFromString("{\"choiceA\":1}"); String[] ignore = null; // done this way to remove compiler warning. this.mapfishJsonParser.parse(true, json, p, ignore); Assert.assertEquals(1, p.choiceA); Assert.assertEquals(0.0, p.choiceB, 0.0000000001); Assert.assertEquals(0, p.choiceC); p = new TestChoiceClass(); json = AbstractMapfishSpringTest.parseJSONObjectFromString("{\"choiceB\":2.0}"); this.mapfishJsonParser.parse(true, json, p); Assert.assertEquals(0, p.choiceA); Assert.assertEquals(2.0, p.choiceB, 0.0000000001); Assert.assertEquals(0, p.choiceC); p = new TestChoiceClass(); json = AbstractMapfishSpringTest.parseJSONObjectFromString("{\"choiceC\":2}"); this.mapfishJsonParser.parse(true, json, p); Assert.assertEquals(0, p.choiceA); Assert.assertEquals(0.0, p.choiceB, 0.0000000001); Assert.assertEquals(2, p.choiceC, 0.0000000001); p = new TestChoiceClass(); json = AbstractMapfishSpringTest.parseJSONObjectFromString("{\"choiceA\":3,\"choiceC\":2}"); this.mapfishJsonParser.parse(true, json, p); Assert.assertEquals(3, p.choiceA); Assert.assertEquals(0.0, p.choiceB, 0.0000000001); Assert.assertEquals(2, p.choiceC, 0.0000000001); p = new TestChoiceClass(); json = AbstractMapfishSpringTest.parseJSONObjectFromString("{\"choiceB\":3.0,\"choiceC\":2}"); this.mapfishJsonParser.parse(true, json, p); Assert.assertEquals(0, p.choiceA); Assert.assertEquals(3.0, p.choiceB, 0.0000000001); Assert.assertEquals(2, p.choiceC, 0.0000000001); } @Test(expected = AssertionFailedException.class) public void testBothOneOfChoices() throws Exception { TestChoiceClass p = new TestChoiceClass(); PJsonObject json = AbstractMapfishSpringTest.parseJSONObjectFromString("{\"choiceA\":1,\"choiceB\":2.0}"); this.mapfishJsonParser.parse(true, json, p); } @Test(expected = AssertionFailedException.class) public void testBothOneOfChoicesAndCanSatisfyOneOf() throws Exception { TestChoiceClass p = new TestChoiceClass(); PJsonObject json = AbstractMapfishSpringTest.parseJSONObjectFromString("{\"choiceA\":1,\"choiceB\":2.0,\"choiceC\":3.0}"); this.mapfishJsonParser.parse(true, json, p); } @Test(expected = AssertionFailedException.class) public void testMissingOneOfChoices() throws Exception { TestChoiceClass p = new TestChoiceClass(); PJsonObject json = AbstractMapfishSpringTest.parseJSONObjectFromString("{}"); this.mapfishJsonParser.parse(true, json, p); } @Test public void testRequireDependantNotDefined() throws Exception { TestRequireClass p = new TestRequireClass(); PJsonObject json = AbstractMapfishSpringTest.parseJSONObjectFromString("{}"); this.mapfishJsonParser.parse(true, json, p); assertNull(p.i); assertNull(p.b); assertNull(p.c); } @Test public void testRequirementSatisfied() throws Exception { TestRequireClass p = new TestRequireClass(); PJsonObject json = AbstractMapfishSpringTest.parseJSONObjectFromString("{\"i\":1, \"b\":true, \"c\":true}"); this.mapfishJsonParser.parse(true, json, p); assertEquals(1, p.i.intValue()); assertTrue(p.b); assertTrue(p.c); } @Test public void testOnlyRequirementDefinedNotDependant() throws Exception { TestRequireClass p = new TestRequireClass(); PJsonObject json = AbstractMapfishSpringTest.parseJSONObjectFromString("{\"b\":true}"); this.mapfishJsonParser.parse(true, json, p); assertNull(p.i); assertTrue(p.b); assertNull(p.c); } @Test(expected = AssertionFailedException.class) public void testMissingBothRequirements() throws Exception { TestRequireClass p = new TestRequireClass(); PJsonObject json = AbstractMapfishSpringTest.parseJSONObjectFromString("{\"i\":1}"); this.mapfishJsonParser.parse(true, json, p); } @Test(expected = AssertionFailedException.class) public void testMissingOneOfTwoRequirements() throws Exception { TestRequireClass p = new TestRequireClass(); PJsonObject json = AbstractMapfishSpringTest.parseJSONObjectFromString("{\"i\":1, \"b\":true}"); this.mapfishJsonParser.parse(true, json, p); } @Test public void testFinalPublic() throws Exception { TestFinalClass p = new TestFinalClass(); PJsonObject json = AbstractMapfishSpringTest.parseJSONObjectFromString("{}"); this.mapfishJsonParser.parse(true, json, p); assertEquals(100, p.i.intValue()); } @Test(expected = ExtraPropertyException.class) public void testFinalFieldMustNotBeInJson() throws Exception { TestFinalClass p = new TestFinalClass(); PJsonObject json = AbstractMapfishSpringTest.parseJSONObjectFromString("{\"i\":1}"); this.mapfishJsonParser.parse(true, json, p); } @Test (expected = IllegalArgumentException.class) public void testEnumIllegalVal() throws Exception { TestEnumParam p = new TestEnumParam(); final PJsonObject json = AbstractMapfishSpringTest.parseJSONObjectFromString("{\"e1\":\"foo\", \"e2\": [2, \"VAL2\"]}"); this.mapfishJsonParser.parse(true, json, p, "toIgnore"); } @Test public void testPopulateLayerParam() throws Exception { final TestParam param = new TestParam(); final PJsonObject json = parseJSONObjectFromFile(MapfishParserTest.class, "mapAttributeTest.json"); this.mapfishJsonParser.parse(true, json, param, "toIgnore"); Assert.assertEquals("string", param.s); Assert.assertEquals("newValue", param.defS); Assert.assertEquals("default2", param.defS2); Assert.assertEquals(11, param.bigI.intValue()); Assert.assertEquals(1, param.littleI); final double delta = 0.00001; Assert.assertEquals(12.0, param.bigD, delta); Assert.assertEquals(2, param.littleD, delta); Assert.assertEquals(13.0f, param.bigF, delta); Assert.assertEquals(3.0f, param.littleF, delta); Assert.assertEquals(true, param.bigB); Assert.assertEquals(true, param.littleB); Assert.assertEquals("fieldValue", param.po.getString("poField")); Assert.assertEquals("http://localhost:8080", param.url.toExternalForm()); Assert.assertEquals(3, param.pa.size()); Assert.assertEquals(1, param.pa.getInt(0)); Assert.assertEquals("hi", param.pa.getString(1)); Assert.assertEquals(3, param.pa.getJSONObject(2).getInt("faField")); Assert.assertArrayEquals(new String[]{"s1", "s2"}, param.sa); Assert.assertEquals(2, param.ba.length); Assert.assertEquals(true, param.ba[0]); Assert.assertEquals(false, param.ba[1]); Assert.assertArrayEquals(new double[]{2.1, 2.2}, param.da, delta); Assert.assertEquals(2, param.oa.length); Assert.assertEquals(true, param.oa[0].has("f")); Assert.assertEquals(true, param.oa[1].has("b")); Assert.assertEquals(true, param.calledByPostConstruct); Assert.assertEquals("embeddedValue", param.e.embeddedValue); Assert.assertEquals("def", param.e.embeddedDefault); assertTrue(param.e.calledByPostConstruct); Assert.assertEquals(2, param.ea.length); Assert.assertEquals("embeddedValue2", param.ea[0].embeddedValue); Assert.assertEquals("updateddef", param.ea[0].embeddedDefault); assertTrue(param.ea[0].calledByPostConstruct); Assert.assertEquals("embeddedValue3", param.ea[1].embeddedValue); Assert.assertEquals("def", param.ea[1].embeddedDefault); assertTrue(param.ea[1].calledByPostConstruct); } @Test public void testPopulateLayerParam_MissingParam() throws Exception { final TestParam param = new TestParam(); try { this.mapfishJsonParser.parse(true, new PJsonObject(new JSONObject(), "spec"), param); fail("Expected an exception to be raised"); } catch (MissingPropertyException e) { final Matcher missingParameterMatcher = Pattern.compile("\\*.+?").matcher(e.getMessage()); int errorCount = 0; while (missingParameterMatcher.find()) { errorCount ++; } int totalAttributes = ParserUtils.getAllAttributeNames(param.getClass()).size(); Assert.assertEquals(18 + totalAttributes, errorCount); Assert.assertEquals(18, e.getMissingProperties().size()); Assert.assertEquals(totalAttributes, e.getAttributeNames().size()); } } @Test public void testPopulateLayerParam_TooManyParams() throws Exception { final TestParam param = new TestParam(); final PJsonObject json = parseJSONObjectFromFile(MapfishParserTest.class, "mapAttributeTest.json"); json.getInternalObj().put("extraProperty", "value"); json.getInternalObj().put("extraProperty2", "value2"); try { this.mapfishJsonParser.parse(true, json, param, "toIgnore"); } catch (ExtraPropertyException e) { final Matcher missingParameterMatcher = Pattern.compile("\\*.+?").matcher(e.getMessage()); int errorCount = 0; while (missingParameterMatcher.find()) { errorCount ++; } int totalAttributes = ParserUtils.getAllAttributeNames(param.getClass()).size(); Assert.assertEquals(2 + totalAttributes, errorCount); Assert.assertEquals(2, e.getExtraProperties().size()); Assert.assertEquals(totalAttributes, e.getAttributeNames().size()); assertTrue(e.getExtraProperties().contains("extraProperty")); } } @Test(expected = ExtraPropertyException.class) public void testDoesntMap() throws Exception { String legendAtts = "{\n" + " \"extra\": \"\",\n" + " \"classes\": [{\n" + " \"name\": \"osm\",\n" + " \"icons\": [\"http://localhost:9876/e2egeoserver/wms?REQUEST=GetLegendGraphic&VERSION=1.0" + ".0&FORMAT=image/png&WIDTH=20&HEIGHT=20&LAYER=topp:states\"]\n" + " }]\n" + "}\n"; PObject requestData = new PJsonObject(new JSONObject(legendAtts), "legend"); LegendAttribute.LegendAttributeValue param = new LegendAttribute.LegendAttributeValue(); new MapfishParser().parse(true, requestData, param); } public static void populateLayerParam(PObject requestData, Object param, String... extraNamesToIgnore) throws IOException, JSONException { new MapfishParser().parse(true, requestData, param, extraNamesToIgnore); } static class TestParam { public String s; @HasDefaultValue public String defS = "default"; @HasDefaultValue public String defS2 = "default2"; public Integer bigI; public int littleI; public Double bigD; public double littleD; public Float bigF; public float littleF; public Boolean bigB; public boolean littleB; public PObject po; public URL url; public PJsonArray pa; public String[] sa; public boolean[] ba; public PJsonObject[] oa; public double[] da; public EmbeddedClass e; public EmbeddedClass[] ea; private boolean calledByPostConstruct = false; public void postConstruct() { calledByPostConstruct = true; } } static class EmbeddedClass { public String embeddedValue; @HasDefaultValue public String embeddedDefault = "def"; private boolean calledByPostConstruct = false; public void postConstruct() { calledByPostConstruct = true; } } static class OptionalArrayParam { @HasDefaultValue public String[] sa; } enum TestEnum { VAL1, VAL2, DEF } static class TestEnumParam { public TestEnum e1 = TestEnum.DEF; public TestEnum[] e2; @HasDefaultValue public TestEnum def2 = TestEnum.DEF; } static class TestChoiceClass { @OneOf("choiceGroup1") public int choiceA; @OneOf("choiceGroup1") public double choiceB; @CanSatisfyOneOf("choiceGroup1") public int choiceC; } static class TestRequireClass { @HasDefaultValue @Requires({"b", "c"}) public Integer i; @HasDefaultValue public Boolean b; @HasDefaultValue public Boolean c; } static class TestFinalClass { public final Integer i = 100; } }