- Timestamp:
- 2011-10-29T09:01:30+02:00 (13 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/actions/search/SearchCompiler.java
r4377 r4546 69 69 protected boolean existsMatch(Collection<? extends OsmPrimitive> primitives) { 70 70 for (OsmPrimitive p : primitives) { 71 if (match(p)) {71 if (match(p)) 72 72 return true; 73 }74 73 } 75 74 return false; … … 81 80 protected boolean forallMatch(Collection<? extends OsmPrimitive> primitives) { 82 81 for (OsmPrimitive p : primitives) { 83 if (!match(p)) {82 if (!match(p)) 84 83 return false; 85 }86 84 } 87 85 return true; … … 110 108 } 111 109 @Override public String toString() {return "!"+match;} 110 public Match getMatch() { 111 return match; 112 } 112 113 } 113 114 … … 130 131 } 131 132 132 p rivatestatic class And extends Match {133 private Match lhs;134 private Match rhs;133 public static class And extends Match { 134 private final Match lhs; 135 private final Match rhs; 135 136 public And(Match lhs, Match rhs) {this.lhs = lhs; this.rhs = rhs;} 136 137 @Override public boolean match(OsmPrimitive osm) { … … 138 139 } 139 140 @Override public String toString() {return lhs+" && "+rhs;} 140 } 141 142 private static class Or extends Match { 143 private Match lhs; 144 private Match rhs; 141 public Match getLhs() { 142 return lhs; 143 } 144 public Match getRhs() { 145 return rhs; 146 } 147 } 148 149 public static class Or extends Match { 150 private final Match lhs; 151 private final Match rhs; 145 152 public Or(Match lhs, Match rhs) {this.lhs = lhs; this.rhs = rhs;} 146 153 @Override public boolean match(OsmPrimitive osm) { … … 148 155 } 149 156 @Override public String toString() {return lhs+" || "+rhs;} 157 public Match getLhs() { 158 return lhs; 159 } 160 public Match getRhs() { 161 return rhs; 162 } 150 163 } 151 164 … … 552 565 public boolean match(OsmPrimitive osm) { 553 566 Integer count = getCount(osm); 554 if (count == null) {567 if (count == null) 555 568 return false; 556 } else {569 else 557 570 return (count >= minCount) && (count <= maxCount); 558 }559 571 } 560 572 … … 575 587 @Override 576 588 protected Integer getCount(OsmPrimitive osm) { 577 if (!(osm instanceof Way)) {589 if (!(osm instanceof Way)) 578 590 return null; 579 } else {591 else 580 592 return ((Way) osm).getNodesCount(); 581 }582 593 } 583 594 … … 649 660 } 650 661 651 private static class Parent extends Match { 652 private Match child; 653 public Parent(Match m) { child = m; } 662 public static class Parent extends Match { 663 private final Match child; 664 public Parent(Match m) { 665 if (m == null) { 666 // "parent" (null) should mean the same as "parent()" 667 // (Always). I.e. match everything 668 child = new Always(); 669 } else { 670 child = m; 671 } 672 } 654 673 @Override public boolean match(OsmPrimitive osm) { 655 674 boolean isParent = false; 656 657 // "parent" (null) should mean the same as "parent()"658 // (Always). I.e. match everything659 if (child == null) {660 child = new Always();661 }662 675 663 676 if (osm instanceof Way) { … … 673 686 } 674 687 @Override public String toString() {return "parent(" + child + ")";} 675 } 676 677 private static class Child extends Match { 688 public Match getChild() { 689 return child; 690 } 691 } 692 693 public static class Child extends Match { 678 694 private final Match parent; 679 695 … … 696 712 } 697 713 @Override public String toString() {return "child(" + parent + ")";} 698 } 699 714 715 public Match getParent() { 716 return parent; 717 } 718 } 719 700 720 /** 701 721 * Matches on the area of a closed way. 702 * 722 * 703 723 * @author Ole Jørgen Brønner 704 724 */ … … 711 731 @Override 712 732 protected Integer getCount(OsmPrimitive osm) { 713 if (!(osm instanceof Way && ((Way) osm).isClosed())) {733 if (!(osm instanceof Way && ((Way) osm).isClosed())) 714 734 return null; 715 }716 735 Way way = (Way) osm; 717 736 return (int) Geometry.closedWayArea(way); … … 743 762 @Override 744 763 public boolean match(OsmPrimitive osm) { 745 if (!osm.isUsable()) {764 if (!osm.isUsable()) 746 765 return false; 747 } else if (osm instanceof Node) {766 else if (osm instanceof Node) 748 767 return bounds.contains(((Node) osm).getCoor()); 749 }else if (osm instanceof Way) {768 else if (osm instanceof Way) { 750 769 Collection<Node> nodes = ((Way) osm).getNodes(); 751 770 return all ? forallMatch(nodes) : existsMatch(nodes); … … 753 772 Collection<OsmPrimitive> primitives = ((Relation) osm).getMemberPrimitives(); 754 773 return all ? forallMatch(primitives) : existsMatch(primitives); 755 } else {774 } else 756 775 return false; 757 }758 776 } 759 777 } … … 799 817 800 818 public static Match compile(String searchStr, boolean caseSensitive, boolean regexSearch) 801 throws ParseError {819 throws ParseError { 802 820 return new SearchCompiler(caseSensitive, regexSearch, 803 821 new PushbackTokenizer( -
trunk/src/org/openstreetmap/josm/tools/template_engine/ParseError.java
r4282 r4546 21 21 } 22 22 23 public ParseError(org.openstreetmap.josm.actions.search.SearchCompiler.ParseError e) { 24 super(tr("Error while parsing search expression"), e); 23 public ParseError(int position, org.openstreetmap.josm.actions.search.SearchCompiler.ParseError e) { 24 super(tr("Error while parsing search expression on position {0}", position), e); 25 unexpectedToken = null; 26 } 27 28 public ParseError(String message) { 29 super(message); 25 30 unexpectedToken = null; 26 31 } … … 29 34 return unexpectedToken; 30 35 } 36 37 public static ParseError unexpectedChar(char expected, char found, int position) { 38 return new ParseError(tr("Unexpected char on {0}. Expected {1} found {2}", position, expected, found)); 39 } 31 40 } -
trunk/src/org/openstreetmap/josm/tools/template_engine/TemplateParser.java
r4282 r4546 2 2 package org.openstreetmap.josm.tools.template_engine; 3 3 4 5 import static org.openstreetmap.josm.tools.I18n.tr; 4 6 5 7 import java.util.ArrayList; … … 9 11 10 12 import org.openstreetmap.josm.actions.search.SearchCompiler; 13 import org.openstreetmap.josm.actions.search.SearchCompiler.Match; 11 14 import org.openstreetmap.josm.tools.template_engine.Tokenizer.Token; 12 15 import org.openstreetmap.josm.tools.template_engine.Tokenizer.TokenType; … … 42 45 if (token.getType() == TokenType.CONDITION_START) { 43 46 templateEntry = parseCondition(); 47 } else if (token.getType() == TokenType.CONTEXT_SWITCH_START) { 48 templateEntry = parseContextSwitch(); 44 49 } else if (token.getType() == TokenType.VARIABLE_START) { 45 50 templateEntry = parseVariable(); … … 63 68 } 64 69 65 private void skipWhitespace() {70 private void skipWhitespace() throws ParseError { 66 71 Token token = tokenizer.lookAhead(); 67 72 if (token.getType() == TokenType.TEXT && token.getText().trim().isEmpty()) { … … 76 81 77 82 TemplateEntry condition; 78 StringsearchExpression = tokenizer.skip('\'');83 Token searchExpression = tokenizer.skip('\''); 79 84 check(TokenType.APOSTROPHE); 80 85 condition = parseExpression(CONDITION_WITH_APOSTROPHES_END_TOKENS); 81 86 check(TokenType.APOSTROPHE); 82 if (searchExpression. trim().isEmpty()) {87 if (searchExpression.getText().trim().isEmpty()) { 83 88 result.getEntries().add(condition); 84 89 } else { 85 90 try { 86 result.getEntries().add(new SearchExpressionCondition(SearchCompiler.compile(searchExpression , false, false), condition));91 result.getEntries().add(new SearchExpressionCondition(SearchCompiler.compile(searchExpression.getText(), false, false), condition)); 87 92 } catch (org.openstreetmap.josm.actions.search.SearchCompiler.ParseError e) { 88 throw new ParseError( e);93 throw new ParseError(searchExpression.getPosition(), e); 89 94 } 90 95 } … … 101 106 } 102 107 108 private TemplateEntry parseContextSwitch() throws ParseError { 109 110 check(TokenType.CONTEXT_SWITCH_START); 111 Token searchExpression = tokenizer.skip('\''); 112 check(TokenType.APOSTROPHE); 113 TemplateEntry template = parseExpression(CONDITION_WITH_APOSTROPHES_END_TOKENS); 114 check(TokenType.APOSTROPHE); 115 ContextSwitchTemplate result; 116 if (searchExpression.getText().trim().isEmpty()) 117 throw new ParseError(tr("Expected search expression")); 118 else { 119 try { 120 Match match = SearchCompiler.compile(searchExpression.getText(), false, false); 121 result = new ContextSwitchTemplate(match, template, searchExpression.getPosition()); 122 } catch (org.openstreetmap.josm.actions.search.SearchCompiler.ParseError e) { 123 throw new ParseError(searchExpression.getPosition(), e); 124 } 125 } 126 skipWhitespace(); 127 check(TokenType.END); 128 return result; 129 } 130 103 131 } -
trunk/src/org/openstreetmap/josm/tools/template_engine/Tokenizer.java
r4282 r4546 40 40 } 41 41 42 public enum TokenType { CONDITION_START, VARIABLE_START, END, PIPE, APOSTROPHE, TEXT, EOF }42 public enum TokenType { CONDITION_START, VARIABLE_START, CONTEXT_SWITCH_START, END, PIPE, APOSTROPHE, TEXT, EOF } 43 43 44 44 private final List<Character> specialCharaters = Arrays.asList(new Character[] {'$', '?', '{', '}', '|', '\''}); … … 64 64 } 65 65 66 public Token nextToken() {66 public Token nextToken() throws ParseError { 67 67 if (currentToken != null) { 68 68 Token result = currentToken; … … 79 79 getChar(); 80 80 return new Token(TokenType.VARIABLE_START, position); 81 82 81 case '?': 83 82 getChar(); … … 86 85 return new Token(TokenType.CONDITION_START, position); 87 86 } else 88 throw new AssertionError(); 87 throw ParseError.unexpectedChar('{', (char)c, position); 88 case '!': 89 getChar(); 90 if (c == '{') { 91 getChar(); 92 return new Token(TokenType.CONTEXT_SWITCH_START, position); 93 } else 94 throw ParseError.unexpectedChar('{', (char)c, position); 89 95 case '}': 90 96 getChar(); … … 111 117 } 112 118 113 public Token lookAhead() {119 public Token lookAhead() throws ParseError { 114 120 if (currentToken == null) { 115 121 currentToken = nextToken(); … … 118 124 } 119 125 120 public Stringskip(char lastChar) {126 public Token skip(char lastChar) { 121 127 currentToken = null; 128 int position = index; 122 129 StringBuilder result = new StringBuilder(); 123 130 while (c != lastChar && c != -1) { … … 128 135 getChar(); 129 136 } 130 return result.toString();137 return new Token(TokenType.TEXT, position, result.toString()); 131 138 } 132 139 -
trunk/test/unit/org/openstreetmap/josm/tools/template_engine/TemplateEngineTest.java
r4431 r4546 13 13 import org.openstreetmap.josm.actions.search.SearchCompiler.Match; 14 14 import org.openstreetmap.josm.data.Preferences; 15 import org.openstreetmap.josm.data.osm.DatasetFactory; 16 import org.openstreetmap.josm.data.osm.Node; 15 17 import org.openstreetmap.josm.data.osm.Relation; 18 import org.openstreetmap.josm.data.osm.RelationMember; 16 19 import org.unitils.reflectionassert.ReflectionAssert; 17 20 … … 150 153 templateEntry.appendText(sb, dataProvider); 151 154 Assert.assertEquals("waypointNameulocalNameuspecialKey", sb.toString()); 152 153 } 154 155 } 156 157 @Test 158 public void testSearchExpression() throws Exception { 159 Match match = compile("(parent type=type1 type=parent1) | (parent type=type2 type=parent2)"); 160 //"parent(type=type1,type=parent1) | (parent(type=type2,type=parent2)" 161 //TODO 162 } 163 164 @Test 165 public void testSwitchContext() throws Exception { 166 TemplateParser parser = new TemplateParser("!{parent() type=parent2 '{name}'}"); 167 DatasetFactory ds = new DatasetFactory(); 168 Relation parent1 = ds.addRelation(1); 169 parent1.put("type", "parent1"); 170 parent1.put("name", "name_parent1"); 171 Relation parent2 = ds.addRelation(2); 172 parent2.put("type", "parent2"); 173 parent2.put("name", "name_parent2"); 174 Node child = ds.addNode(1); 175 parent1.addMember(new RelationMember("", child)); 176 parent2.addMember(new RelationMember("", child)); 177 178 StringBuilder sb = new StringBuilder(); 179 TemplateEntry entry = parser.parse(); 180 entry.appendText(sb, child); 181 182 Assert.assertEquals("name_parent2", sb.toString()); 183 } 184 185 @Test 186 public void testSetOr() throws ParseError { 187 TemplateParser parser = new TemplateParser("!{(parent(type=type1) type=parent1) | (parent type=type2 type=parent2) '{name}'}"); 188 DatasetFactory ds = new DatasetFactory(); 189 Relation parent1 = ds.addRelation(1); 190 parent1.put("type", "parent1"); 191 parent1.put("name", "name_parent1"); 192 Relation parent2 = ds.addRelation(2); 193 parent2.put("type", "parent2"); 194 parent2.put("name", "name_parent2"); 195 Node child1 = ds.addNode(1); 196 child1.put("type", "type1"); 197 parent1.addMember(new RelationMember("", child1)); 198 parent2.addMember(new RelationMember("", child1)); 199 Node child2 = ds.addNode(2); 200 child2.put("type", "type2"); 201 parent1.addMember(new RelationMember("", child2)); 202 parent2.addMember(new RelationMember("", child2)); 203 204 205 StringBuilder sb = new StringBuilder(); 206 TemplateEntry entry = parser.parse(); 207 entry.appendText(sb, child1); 208 entry.appendText(sb, child2); 209 210 Assert.assertEquals("name_parent1name_parent2", sb.toString()); 211 } 212 213 @Test 214 public void testMultilevel() throws ParseError { 215 TemplateParser parser = new TemplateParser("!{(parent(parent(type=type1)) type=grandparent) | (parent type=type2 type=parent2) '{name}'}"); 216 DatasetFactory ds = new DatasetFactory(); 217 Relation parent1 = ds.addRelation(1); 218 parent1.put("type", "parent1"); 219 parent1.put("name", "name_parent1"); 220 Relation parent2 = ds.addRelation(2); 221 parent2.put("type", "parent2"); 222 parent2.put("name", "name_parent2"); 223 Node child1 = ds.addNode(1); 224 child1.put("type", "type1"); 225 parent1.addMember(new RelationMember("", child1)); 226 parent2.addMember(new RelationMember("", child1)); 227 Node child2 = ds.addNode(2); 228 child2.put("type", "type2"); 229 parent1.addMember(new RelationMember("", child2)); 230 parent2.addMember(new RelationMember("", child2)); 231 Relation grandParent = ds.addRelation(3); 232 grandParent.put("type", "grandparent"); 233 grandParent.put("name", "grandparent_name"); 234 grandParent.addMember(new RelationMember("", parent1)); 235 236 237 StringBuilder sb = new StringBuilder(); 238 TemplateEntry entry = parser.parse(); 239 entry.appendText(sb, child1); 240 entry.appendText(sb, child2); 241 242 Assert.assertEquals("grandparent_namename_parent2", sb.toString()); 243 } 244 245 @Test(expected=ParseError.class) 246 public void testErrorsNot() throws ParseError { 247 TemplateParser parser = new TemplateParser("!{-parent() '{name}'}"); 248 parser.parse(); 249 } 250 251 @Test(expected=ParseError.class) 252 public void testErrorOr() throws ParseError { 253 TemplateParser parser = new TemplateParser("!{parent() | type=type1 '{name}'}"); 254 parser.parse(); 255 } 256 257 @Test 258 public void testChild() throws ParseError { 259 TemplateParser parser = new TemplateParser("!{((child(type=type1) type=child1) | (child type=type2 type=child2)) type=child2 '{name}'}"); 260 DatasetFactory ds = new DatasetFactory(); 261 Relation parent1 = ds.addRelation(1); 262 parent1.put("type", "type1"); 263 Relation parent2 = ds.addRelation(2); 264 parent2.put("type", "type2"); 265 Node child1 = ds.addNode(1); 266 child1.put("type", "child1"); 267 child1.put("name", "child1"); 268 parent1.addMember(new RelationMember("", child1)); 269 parent2.addMember(new RelationMember("", child1)); 270 Node child2 = ds.addNode(2); 271 child2.put("type", "child2"); 272 child2.put("name", "child2"); 273 parent1.addMember(new RelationMember("", child2)); 274 parent2.addMember(new RelationMember("", child2)); 275 276 277 StringBuilder sb = new StringBuilder(); 278 TemplateEntry entry = parser.parse(); 279 entry.appendText(sb, parent2); 280 281 Assert.assertEquals("child2", sb.toString()); 282 } 155 283 156 284 }
Note:
See TracChangeset
for help on using the changeset viewer.