| 1 | // License: GPL. For details, see LICENSE file.
|
|---|
| 2 | package org.openstreetmap.josm.tools.template_engine;
|
|---|
| 3 |
|
|---|
| 4 | import java.util.Arrays;
|
|---|
| 5 | import java.util.List;
|
|---|
| 6 |
|
|---|
| 7 | import org.junit.Assert;
|
|---|
| 8 | import org.junit.BeforeClass;
|
|---|
| 9 | import org.junit.Test;
|
|---|
| 10 | import org.openstreetmap.josm.JOSMFixture;
|
|---|
| 11 | import org.openstreetmap.josm.actions.search.SearchCompiler;
|
|---|
| 12 | import org.openstreetmap.josm.actions.search.SearchCompiler.Match;
|
|---|
| 13 | import org.openstreetmap.josm.data.osm.Node;
|
|---|
| 14 | import org.openstreetmap.josm.data.osm.Relation;
|
|---|
| 15 | import org.openstreetmap.josm.data.osm.RelationMember;
|
|---|
| 16 | import org.openstreetmap.josm.testutils.DatasetFactory;
|
|---|
| 17 | import org.unitils.reflectionassert.ReflectionAssert;
|
|---|
| 18 |
|
|---|
| 19 | /**
|
|---|
| 20 | * Unit tests of {@link TemplateParser} class.
|
|---|
| 21 | */
|
|---|
| 22 | public class TemplateParserTest {
|
|---|
| 23 |
|
|---|
| 24 | /**
|
|---|
| 25 | * Setup test.
|
|---|
| 26 | */
|
|---|
| 27 | @BeforeClass
|
|---|
| 28 | public static void setUp() {
|
|---|
| 29 | JOSMFixture.createUnitTestFixture().init();
|
|---|
| 30 | }
|
|---|
| 31 |
|
|---|
| 32 | /**
|
|---|
| 33 | * Test to parse an empty string.
|
|---|
| 34 | * @throws ParseError if the template cannot be parsed
|
|---|
| 35 | */
|
|---|
| 36 | @Test
|
|---|
| 37 | public void testEmpty() throws ParseError {
|
|---|
| 38 | TemplateParser parser = new TemplateParser("");
|
|---|
| 39 | ReflectionAssert.assertReflectionEquals(new StaticText(""), parser.parse());
|
|---|
| 40 | }
|
|---|
| 41 |
|
|---|
| 42 | /**
|
|---|
| 43 | * Test to parse a variable.
|
|---|
| 44 | * @throws ParseError if the template cannot be parsed
|
|---|
| 45 | */
|
|---|
| 46 | @Test
|
|---|
| 47 | public void testVariable() throws ParseError {
|
|---|
| 48 | TemplateParser parser = new TemplateParser("abc{var}\\{ef\\$\\{g");
|
|---|
| 49 | ReflectionAssert.assertReflectionEquals(CompoundTemplateEntry.fromArray(new StaticText("abc"),
|
|---|
| 50 | new Variable("var"), new StaticText("{ef${g")), parser.parse());
|
|---|
| 51 | }
|
|---|
| 52 |
|
|---|
| 53 | /**
|
|---|
| 54 | * Test to parse a condition with whitespaces.
|
|---|
| 55 | * @throws ParseError if the template cannot be parsed
|
|---|
| 56 | */
|
|---|
| 57 | @Test
|
|---|
| 58 | public void testConditionWhitespace() throws ParseError {
|
|---|
| 59 | TemplateParser parser = new TemplateParser("?{ '{name} {desc}' | '{name}' | '{desc}' }");
|
|---|
| 60 | Condition condition = new Condition();
|
|---|
| 61 | condition.getEntries().add(CompoundTemplateEntry.fromArray(new Variable("name"), new StaticText(" "), new Variable("desc")));
|
|---|
| 62 | condition.getEntries().add(new Variable("name"));
|
|---|
| 63 | condition.getEntries().add(new Variable("desc"));
|
|---|
| 64 | ReflectionAssert.assertReflectionEquals(condition, parser.parse());
|
|---|
| 65 | }
|
|---|
| 66 |
|
|---|
| 67 | /**
|
|---|
| 68 | * Test to parse a condition without whitespace.
|
|---|
| 69 | * @throws ParseError if the template cannot be parsed
|
|---|
| 70 | */
|
|---|
| 71 | @Test
|
|---|
| 72 | public void testConditionNoWhitespace() throws ParseError {
|
|---|
| 73 | TemplateParser parser = new TemplateParser("?{'{name} {desc}'|'{name}'|'{desc}'}");
|
|---|
| 74 | Condition condition = new Condition();
|
|---|
| 75 | condition.getEntries().add(CompoundTemplateEntry.fromArray(new Variable("name"), new StaticText(" "), new Variable("desc")));
|
|---|
| 76 | condition.getEntries().add(new Variable("name"));
|
|---|
| 77 | condition.getEntries().add(new Variable("desc"));
|
|---|
| 78 | ReflectionAssert.assertReflectionEquals(condition, parser.parse());
|
|---|
| 79 | }
|
|---|
| 80 |
|
|---|
| 81 | private static Match compile(String expression) throws SearchCompiler.ParseError {
|
|---|
| 82 | return SearchCompiler.compile(expression);
|
|---|
| 83 | }
|
|---|
| 84 |
|
|---|
| 85 | /**
|
|---|
| 86 | * Test to parse a search expression condition.
|
|---|
| 87 | * @throws ParseError if the template cannot be parsed
|
|---|
| 88 | * @throws SearchCompiler.ParseError if an error has been encountered while compiling
|
|---|
| 89 | */
|
|---|
| 90 | @Test
|
|---|
| 91 | public void testConditionSearchExpression() throws ParseError, SearchCompiler.ParseError {
|
|---|
| 92 | TemplateParser parser = new TemplateParser("?{ admin_level = 2 'NUTS 1' | admin_level = 4 'NUTS 2' | '{admin_level}'}");
|
|---|
| 93 | Condition condition = new Condition();
|
|---|
| 94 | condition.getEntries().add(new SearchExpressionCondition(compile("admin_level = 2"), new StaticText("NUTS 1")));
|
|---|
| 95 | condition.getEntries().add(new SearchExpressionCondition(compile("admin_level = 4"), new StaticText("NUTS 2")));
|
|---|
| 96 | condition.getEntries().add(new Variable("admin_level"));
|
|---|
| 97 | ReflectionAssert.assertReflectionEquals(condition, parser.parse());
|
|---|
| 98 | }
|
|---|
| 99 |
|
|---|
| 100 | TemplateEngineDataProvider dataProvider = new TemplateEngineDataProvider() {
|
|---|
| 101 | @Override
|
|---|
| 102 | public Object getTemplateValue(String name, boolean special) {
|
|---|
| 103 | if (special) {
|
|---|
| 104 | if ("localName".equals(name))
|
|---|
| 105 | return "localName";
|
|---|
| 106 | else
|
|---|
| 107 | return null;
|
|---|
| 108 | } else {
|
|---|
| 109 | switch (name) {
|
|---|
| 110 | case "name":
|
|---|
| 111 | return "waypointName";
|
|---|
| 112 | case "number":
|
|---|
| 113 | return 10;
|
|---|
| 114 | case "special:key":
|
|---|
| 115 | return "specialKey";
|
|---|
| 116 | default:
|
|---|
| 117 | return null;
|
|---|
| 118 | }
|
|---|
| 119 | }
|
|---|
| 120 | }
|
|---|
| 121 |
|
|---|
| 122 | @Override
|
|---|
| 123 | public boolean evaluateCondition(Match condition) {
|
|---|
| 124 | return true;
|
|---|
| 125 | }
|
|---|
| 126 |
|
|---|
| 127 | @Override
|
|---|
| 128 | public List<String> getTemplateKeys() {
|
|---|
| 129 | return Arrays.asList("name", "number");
|
|---|
| 130 | }
|
|---|
| 131 | };
|
|---|
| 132 |
|
|---|
| 133 | /**
|
|---|
| 134 | * Test to fill a template.
|
|---|
| 135 | * @throws ParseError if the template cannot be parsed
|
|---|
| 136 | */
|
|---|
| 137 | @Test
|
|---|
| 138 | public void testFilling() throws ParseError {
|
|---|
| 139 | TemplateParser parser = new TemplateParser("{name} u{unknown}u i{number}i");
|
|---|
| 140 | TemplateEntry entry = parser.parse();
|
|---|
| 141 | StringBuilder sb = new StringBuilder();
|
|---|
| 142 | entry.appendText(sb, dataProvider);
|
|---|
| 143 | Assert.assertEquals("waypointName uu i10i", sb.toString());
|
|---|
| 144 | }
|
|---|
| 145 |
|
|---|
| 146 | /**
|
|---|
| 147 | * Test to parse a search expression.
|
|---|
| 148 | * @throws ParseError if the template cannot be parsed
|
|---|
| 149 | */
|
|---|
| 150 | @Test
|
|---|
| 151 | public void testFillingSearchExpression() throws ParseError {
|
|---|
| 152 | TemplateParser parser = new TemplateParser("?{ admin_level = 2 'NUTS 1' | admin_level = 4 'NUTS 2' | '{admin_level}'}");
|
|---|
| 153 | TemplateEntry templateEntry = parser.parse();
|
|---|
| 154 |
|
|---|
| 155 | StringBuilder sb = new StringBuilder();
|
|---|
| 156 | Relation r = new Relation();
|
|---|
| 157 | r.put("admin_level", "2");
|
|---|
| 158 | templateEntry.appendText(sb, r);
|
|---|
| 159 | Assert.assertEquals("NUTS 1", sb.toString());
|
|---|
| 160 |
|
|---|
| 161 | sb.setLength(0);
|
|---|
| 162 | r.put("admin_level", "5");
|
|---|
| 163 | templateEntry.appendText(sb, r);
|
|---|
| 164 | Assert.assertEquals("5", sb.toString());
|
|---|
| 165 | }
|
|---|
| 166 |
|
|---|
| 167 | /**
|
|---|
| 168 | * Test to print all.
|
|---|
| 169 | * @throws ParseError if the template cannot be parsed
|
|---|
| 170 | */
|
|---|
| 171 | @Test
|
|---|
| 172 | public void testPrintAll() throws ParseError {
|
|---|
| 173 | TemplateParser parser = new TemplateParser("{special:everything}");
|
|---|
| 174 | TemplateEntry entry = parser.parse();
|
|---|
| 175 | StringBuilder sb = new StringBuilder();
|
|---|
| 176 | entry.appendText(sb, dataProvider);
|
|---|
| 177 | Assert.assertEquals("name=waypointName, number=10", sb.toString());
|
|---|
| 178 | Assert.assertEquals("{special:everything}", entry.toString());
|
|---|
| 179 | }
|
|---|
| 180 |
|
|---|
| 181 | /**
|
|---|
| 182 | * Test to print on several lines.
|
|---|
| 183 | * @throws ParseError if the template cannot be parsed
|
|---|
| 184 | */
|
|---|
| 185 | @Test
|
|---|
| 186 | public void testPrintMultiline() throws ParseError {
|
|---|
| 187 | TemplateParser parser = new TemplateParser("{name}\\n{number}");
|
|---|
| 188 | TemplateEntry entry = parser.parse();
|
|---|
| 189 | StringBuilder sb = new StringBuilder();
|
|---|
| 190 | entry.appendText(sb, dataProvider);
|
|---|
| 191 | Assert.assertEquals("waypointName\n10", sb.toString());
|
|---|
| 192 | }
|
|---|
| 193 |
|
|---|
| 194 | /**
|
|---|
| 195 | * Test to print special variables.
|
|---|
| 196 | * @throws ParseError if the template cannot be parsed
|
|---|
| 197 | */
|
|---|
| 198 | @Test
|
|---|
| 199 | public void testSpecialVariable() throws ParseError {
|
|---|
| 200 | TemplateParser parser = new TemplateParser("{name}u{special:localName}u{special:special:key}");
|
|---|
| 201 | TemplateEntry templateEntry = parser.parse();
|
|---|
| 202 |
|
|---|
| 203 | StringBuilder sb = new StringBuilder();
|
|---|
| 204 | templateEntry.appendText(sb, dataProvider);
|
|---|
| 205 | Assert.assertEquals("waypointNameulocalNameuspecialKey", sb.toString());
|
|---|
| 206 | }
|
|---|
| 207 |
|
|---|
| 208 | @Test
|
|---|
| 209 | public void testSearchExpression() throws Exception {
|
|---|
| 210 | compile("(parent type=type1 type=parent1) | (parent type=type2 type=parent2)");
|
|---|
| 211 | //"parent(type=type1,type=parent1) | (parent(type=type2,type=parent2)"
|
|---|
| 212 | //TODO
|
|---|
| 213 | }
|
|---|
| 214 |
|
|---|
| 215 | /**
|
|---|
| 216 | * Test to switch context.
|
|---|
| 217 | * @throws ParseError if the template cannot be parsed
|
|---|
| 218 | */
|
|---|
| 219 | @Test
|
|---|
| 220 | public void testSwitchContext() throws ParseError {
|
|---|
| 221 | TemplateParser parser = new TemplateParser("!{parent() type=parent2 '{name}'}");
|
|---|
| 222 | DatasetFactory ds = new DatasetFactory();
|
|---|
| 223 | Relation parent1 = ds.addRelation(1);
|
|---|
| 224 | parent1.put("type", "parent1");
|
|---|
| 225 | parent1.put("name", "name_parent1");
|
|---|
| 226 | Relation parent2 = ds.addRelation(2);
|
|---|
| 227 | parent2.put("type", "parent2");
|
|---|
| 228 | parent2.put("name", "name_parent2");
|
|---|
| 229 | Node child = ds.addNode(1);
|
|---|
| 230 | parent1.addMember(new RelationMember("", child));
|
|---|
| 231 | parent2.addMember(new RelationMember("", child));
|
|---|
| 232 |
|
|---|
| 233 | StringBuilder sb = new StringBuilder();
|
|---|
| 234 | TemplateEntry entry = parser.parse();
|
|---|
| 235 | entry.appendText(sb, child);
|
|---|
| 236 |
|
|---|
| 237 | Assert.assertEquals("name_parent2", sb.toString());
|
|---|
| 238 | }
|
|---|
| 239 |
|
|---|
| 240 | @Test
|
|---|
| 241 | public void testSetAnd() throws ParseError {
|
|---|
| 242 | TemplateParser parser = new TemplateParser("!{(parent(type=child) type=parent) & (parent type=child subtype=parent) '{name}'}");
|
|---|
| 243 | DatasetFactory ds = new DatasetFactory();
|
|---|
| 244 | Relation parent1 = ds.addRelation(1);
|
|---|
| 245 | parent1.put("type", "parent");
|
|---|
| 246 | parent1.put("subtype", "parent");
|
|---|
| 247 | parent1.put("name", "name_parent1");
|
|---|
| 248 | Node child = ds.addNode(1);
|
|---|
| 249 | child.put("type", "child");
|
|---|
| 250 | parent1.addMember(new RelationMember("", child));
|
|---|
| 251 |
|
|---|
| 252 | StringBuilder sb = new StringBuilder();
|
|---|
| 253 | TemplateEntry entry = parser.parse();
|
|---|
| 254 | entry.appendText(sb, child);
|
|---|
| 255 |
|
|---|
| 256 | Assert.assertEquals("name_parent1", sb.toString());
|
|---|
| 257 | }
|
|---|
| 258 |
|
|---|
| 259 | @Test
|
|---|
| 260 | public void testSetOr() throws ParseError {
|
|---|
| 261 | TemplateParser parser = new TemplateParser("!{(parent(type=type1) type=parent1) | (parent type=type2 type=parent2) '{name}'}");
|
|---|
| 262 | DatasetFactory ds = new DatasetFactory();
|
|---|
| 263 | Relation parent1 = ds.addRelation(1);
|
|---|
| 264 | parent1.put("type", "parent1");
|
|---|
| 265 | parent1.put("name", "name_parent1");
|
|---|
| 266 | Relation parent2 = ds.addRelation(2);
|
|---|
| 267 | parent2.put("type", "parent2");
|
|---|
| 268 | parent2.put("name", "name_parent2");
|
|---|
| 269 | Node child1 = ds.addNode(1);
|
|---|
| 270 | child1.put("type", "type1");
|
|---|
| 271 | parent1.addMember(new RelationMember("", child1));
|
|---|
| 272 | parent2.addMember(new RelationMember("", child1));
|
|---|
| 273 | Node child2 = ds.addNode(2);
|
|---|
| 274 | child2.put("type", "type2");
|
|---|
| 275 | parent1.addMember(new RelationMember("", child2));
|
|---|
| 276 | parent2.addMember(new RelationMember("", child2));
|
|---|
| 277 |
|
|---|
| 278 | StringBuilder sb = new StringBuilder();
|
|---|
| 279 | TemplateEntry entry = parser.parse();
|
|---|
| 280 | entry.appendText(sb, child1);
|
|---|
| 281 | entry.appendText(sb, child2);
|
|---|
| 282 |
|
|---|
| 283 | Assert.assertEquals("name_parent1name_parent2", sb.toString());
|
|---|
| 284 | }
|
|---|
| 285 |
|
|---|
| 286 | @Test
|
|---|
| 287 | public void testMultilevel() throws ParseError {
|
|---|
| 288 | TemplateParser parser = new TemplateParser(
|
|---|
| 289 | "!{(parent(parent(type=type1)) type=grandparent) | (parent type=type2 type=parent2) '{name}'}");
|
|---|
| 290 | DatasetFactory ds = new DatasetFactory();
|
|---|
| 291 | Relation parent1 = ds.addRelation(1);
|
|---|
| 292 | parent1.put("type", "parent1");
|
|---|
| 293 | parent1.put("name", "name_parent1");
|
|---|
| 294 | Relation parent2 = ds.addRelation(2);
|
|---|
| 295 | parent2.put("type", "parent2");
|
|---|
| 296 | parent2.put("name", "name_parent2");
|
|---|
| 297 | Node child1 = ds.addNode(1);
|
|---|
| 298 | child1.put("type", "type1");
|
|---|
| 299 | parent1.addMember(new RelationMember("", child1));
|
|---|
| 300 | parent2.addMember(new RelationMember("", child1));
|
|---|
| 301 | Node child2 = ds.addNode(2);
|
|---|
| 302 | child2.put("type", "type2");
|
|---|
| 303 | parent1.addMember(new RelationMember("", child2));
|
|---|
| 304 | parent2.addMember(new RelationMember("", child2));
|
|---|
| 305 | Relation grandParent = ds.addRelation(3);
|
|---|
| 306 | grandParent.put("type", "grandparent");
|
|---|
| 307 | grandParent.put("name", "grandparent_name");
|
|---|
| 308 | grandParent.addMember(new RelationMember("", parent1));
|
|---|
| 309 |
|
|---|
| 310 |
|
|---|
| 311 | StringBuilder sb = new StringBuilder();
|
|---|
| 312 | TemplateEntry entry = parser.parse();
|
|---|
| 313 | entry.appendText(sb, child1);
|
|---|
| 314 | entry.appendText(sb, child2);
|
|---|
| 315 |
|
|---|
| 316 | Assert.assertEquals("grandparent_namename_parent2", sb.toString());
|
|---|
| 317 | }
|
|---|
| 318 |
|
|---|
| 319 | @Test(expected = ParseError.class)
|
|---|
| 320 | public void testErrorsNot() throws ParseError {
|
|---|
| 321 | TemplateParser parser = new TemplateParser("!{-parent() '{name}'}");
|
|---|
| 322 | parser.parse();
|
|---|
| 323 | }
|
|---|
| 324 |
|
|---|
| 325 | @Test(expected = ParseError.class)
|
|---|
| 326 | public void testErrorOr() throws ParseError {
|
|---|
| 327 | TemplateParser parser = new TemplateParser("!{parent() | type=type1 '{name}'}");
|
|---|
| 328 | parser.parse();
|
|---|
| 329 | }
|
|---|
| 330 |
|
|---|
| 331 | @Test
|
|---|
| 332 | public void testChild() throws ParseError {
|
|---|
| 333 | TemplateParser parser = new TemplateParser("!{((child(type=type1) type=child1) | (child type=type2 type=child2)) type=child2 '{name}'}");
|
|---|
| 334 | DatasetFactory ds = new DatasetFactory();
|
|---|
| 335 | Relation parent1 = ds.addRelation(1);
|
|---|
| 336 | parent1.put("type", "type1");
|
|---|
| 337 | Relation parent2 = ds.addRelation(2);
|
|---|
| 338 | parent2.put("type", "type2");
|
|---|
| 339 | Node child1 = ds.addNode(1);
|
|---|
| 340 | child1.put("type", "child1");
|
|---|
| 341 | child1.put("name", "child1");
|
|---|
| 342 | parent1.addMember(new RelationMember("", child1));
|
|---|
| 343 | parent2.addMember(new RelationMember("", child1));
|
|---|
| 344 | Node child2 = ds.addNode(2);
|
|---|
| 345 | child2.put("type", "child2");
|
|---|
| 346 | child2.put("name", "child2");
|
|---|
| 347 | parent1.addMember(new RelationMember("", child2));
|
|---|
| 348 | parent2.addMember(new RelationMember("", child2));
|
|---|
| 349 |
|
|---|
| 350 |
|
|---|
| 351 | StringBuilder sb = new StringBuilder();
|
|---|
| 352 | TemplateEntry entry = parser.parse();
|
|---|
| 353 | entry.appendText(sb, parent2);
|
|---|
| 354 |
|
|---|
| 355 | Assert.assertEquals("child2", sb.toString());
|
|---|
| 356 | }
|
|---|
| 357 |
|
|---|
| 358 | @Test
|
|---|
| 359 | public void testToStringCanBeParsedAgain() throws Exception {
|
|---|
| 360 | final String s1 = "?{ '{name} ({desc})' | '{name} ({cmt})' | '{name}' | '{desc}' | '{cmt}' }";
|
|---|
| 361 | final String s2 = new TemplateParser(s1).parse().toString();
|
|---|
| 362 | final String s3 = new TemplateParser(s2).parse().toString();
|
|---|
| 363 | Assert.assertEquals(s1, s2);
|
|---|
| 364 | Assert.assertEquals(s2, s3);
|
|---|
| 365 | }
|
|---|
| 366 | }
|
|---|