diff --git a/src/org/openstreetmap/josm/actions/search/PushbackTokenizer.java b/src/org/openstreetmap/josm/actions/search/PushbackTokenizer.java
index aedd0fd..9063a32 100644
a
|
b
|
public class PushbackTokenizer {
|
39 | 39 | private Long currentNumber; |
40 | 40 | private Long currentRange; |
41 | 41 | private int c; |
| 42 | private boolean isRange; |
42 | 43 | |
43 | 44 | public PushbackTokenizer(Reader search) { |
44 | 45 | this.search = search; |
… |
… |
public class PushbackTokenizer {
|
156 | 157 | return Token.OR; |
157 | 158 | if ("and".equalsIgnoreCase(currentText)) |
158 | 159 | return nextToken(); |
| 160 | // try parsing number |
159 | 161 | try { |
160 | 162 | currentNumber = Long.parseLong(currentText); |
161 | 163 | } catch (NumberFormatException e) { |
162 | 164 | currentNumber = null; |
163 | 165 | } |
| 166 | // if text contains "-", try parsing a range |
164 | 167 | int pos = currentText.indexOf('-', 1); |
165 | | if (pos > 0) { |
| 168 | isRange = pos > 0; |
| 169 | if (isRange) { |
166 | 170 | try { |
167 | 171 | currentNumber = Long.parseLong(currentText.substring(0, pos)); |
168 | | currentRange = Long.parseLong(currentText.substring(pos + 1)); |
169 | 172 | } catch (NumberFormatException e) { |
170 | 173 | currentNumber = null; |
| 174 | } |
| 175 | try { |
| 176 | currentRange = Long.parseLong(currentText.substring(pos + 1)); |
| 177 | } catch (NumberFormatException e) { |
| 178 | currentRange = null; |
| 179 | } |
| 180 | } else { |
171 | 181 | currentRange = null; |
172 | 182 | } |
173 | | } |
174 | 183 | return Token.KEY; |
175 | 184 | } |
176 | 185 | } |
… |
… |
public class PushbackTokenizer {
|
203 | 212 | } |
204 | 213 | |
205 | 214 | public Range readRange(String errorMessage) throws ParseError { |
206 | | if ((nextToken() == Token.KEY) && (currentNumber != null)) { |
207 | | if (currentRange == null) |
| 215 | if (nextToken() != Token.KEY || (currentNumber == null && currentRange == null)) { |
| 216 | throw new ParseError(errorMessage); |
| 217 | } else if (!isRange && currentNumber != null) { |
| 218 | if (currentNumber >= 0) { |
208 | 219 | return new Range(currentNumber, currentNumber); |
209 | | else |
210 | | return new Range(currentNumber, currentRange); |
211 | | } else |
| 220 | } else { |
| 221 | return new Range(0, Math.abs(currentNumber)); |
| 222 | } |
| 223 | } else if (isRange && currentRange == null) { |
| 224 | return new Range(currentNumber, Integer.MAX_VALUE); |
| 225 | } else if (currentNumber != null && currentRange != null) { |
| 226 | return new Range(currentNumber, currentRange); |
| 227 | } else { |
212 | 228 | throw new ParseError(errorMessage); |
| 229 | } |
213 | 230 | } |
214 | 231 | |
215 | 232 | public String getText() { |
diff --git a/src/org/openstreetmap/josm/actions/search/SearchAction.java b/src/org/openstreetmap/josm/actions/search/SearchAction.java
index 4d7938f..2257951 100644
a
|
b
|
public class SearchAction extends JosmAction implements ParameterizedAction {
|
194 | 194 | + "<li>"+tr("<b>id:</b>... - object with given ID (0 for new objects)")+"</li>" |
195 | 195 | + "<li>"+tr("<b>version:</b>... - object with given version (0 objects without an assigned version)")+"</li>" |
196 | 196 | + "<li>"+tr("<b>changeset:</b>... - object with given changeset id (0 objects without assigned changeset)")+"</li>" |
197 | | + "<li>"+tr("<b>nodes:</b>... - object with given number of nodes (nodes:count or nodes:min-max)")+"</li>" |
198 | | + "<li>"+tr("<b>tags:</b>... - object with given number of tags (tags:count or tags:min-max)")+"</li>" |
| 197 | + "<li>"+tr("<b>nodes:</b>... - object with given number of nodes (nodes:count, nodes:min-max, nodes:min- or nodes:-max)")+"</li>" |
| 198 | + "<li>"+tr("<b>tags:</b>... - object with given number of tags (nodes:count, nodes:min-max, nodes:min- or nodes:-max)")+"</li>" |
199 | 199 | + "<li>"+tr("<b>role:</b>... - object with given role in a relation")+"</li>" |
200 | 200 | + "<li>"+tr("<b>timestamp:</b>... - objects with this timestamp (<b>2009-11-12T14:51:09Z</b>, <b>2009-11-12</b> or <b>T14:51</b> ...)")+"</li>" |
201 | | + "<li>"+tr("<b>areasize:</b>... - closed ways with area between MIN and MAX m\u00b2. (areasize:MIN-MAX or areasize:MAX)")+"</li>" |
| 201 | + "<li>"+tr("<b>areasize:</b>... - closed ways with given area in m\u00b2 (areasize:min-max or areasize:max)")+"</li>" |
202 | 202 | + "<li>"+tr("<b>modified</b> - all changed objects")+"</li>" |
203 | 203 | + "<li>"+tr("<b>selected</b> - all selected objects")+"</li>" |
204 | 204 | + "<li>"+tr("<b>incomplete</b> - all incomplete objects")+"</li>" |
diff --git a/src/org/openstreetmap/josm/actions/search/SearchCompiler.java b/src/org/openstreetmap/josm/actions/search/SearchCompiler.java
index 8300913..b34d0c1 100644
a
|
b
|
public class SearchCompiler {
|
508 | 508 | } |
509 | 509 | } |
510 | 510 | |
511 | | private static class NodeCountRange extends Match { |
| 511 | private abstract static class CountRange extends Match { |
| 512 | |
512 | 513 | private int minCount; |
513 | 514 | private int maxCount; |
514 | | public NodeCountRange(int minCount, int maxCount) { |
515 | | if(maxCount < minCount) { |
516 | | this.minCount = maxCount; |
517 | | this.maxCount = minCount; |
| 515 | |
| 516 | public CountRange(int minCount, int maxCount) { |
| 517 | this.minCount = Math.min(minCount, maxCount); |
| 518 | this.maxCount = Math.max(minCount, maxCount); |
| 519 | } |
| 520 | |
| 521 | protected abstract Integer getCount(OsmPrimitive osm); |
| 522 | |
| 523 | protected abstract String getCountString(); |
| 524 | |
| 525 | @Override |
| 526 | public boolean match(OsmPrimitive osm) { |
| 527 | Integer count = getCount(osm); |
| 528 | if (count == null) { |
| 529 | return false; |
518 | 530 | } else { |
519 | | this.minCount = minCount; |
520 | | this.maxCount = maxCount; |
| 531 | return (count >= minCount) && (count <= maxCount); |
521 | 532 | } |
522 | 533 | } |
523 | | @Override public boolean match(OsmPrimitive osm) { |
524 | | if(!(osm instanceof Way)) return false; |
525 | | int size = ((Way)osm).getNodesCount(); |
526 | | return (size >= minCount) && (size <= maxCount); |
| 534 | |
| 535 | @Override |
| 536 | public String toString() { |
| 537 | return getCountString() + "=" + minCount + "-" + maxCount; |
527 | 538 | } |
528 | | @Override public String toString() {return "nodes="+minCount+"-"+maxCount;} |
529 | 539 | } |
530 | 540 | |
531 | | private static class TagCountRange extends Match { |
532 | | private int minCount; |
533 | | private int maxCount; |
534 | | public TagCountRange(int minCount, int maxCount) { |
535 | | if(maxCount < minCount) { |
536 | | this.minCount = maxCount; |
537 | | this.maxCount = minCount; |
| 541 | |
| 542 | |
| 543 | private static class NodeCountRange extends CountRange { |
| 544 | |
| 545 | public NodeCountRange(int minCount, int maxCount) { |
| 546 | super(minCount, maxCount); |
| 547 | } |
| 548 | |
| 549 | @Override |
| 550 | protected Integer getCount(OsmPrimitive osm) { |
| 551 | if (!(osm instanceof Way)) { |
| 552 | return null; |
538 | 553 | } else { |
539 | | this.minCount = minCount; |
540 | | this.maxCount = maxCount; |
| 554 | return ((Way) osm).getNodesCount(); |
541 | 555 | } |
542 | 556 | } |
543 | | @Override public boolean match(OsmPrimitive osm) { |
544 | | int size = osm.getKeys().size(); |
545 | | return (size >= minCount) && (size <= maxCount); |
| 557 | |
| 558 | @Override |
| 559 | protected String getCountString() { |
| 560 | return "nodes"; |
| 561 | } |
| 562 | } |
| 563 | |
| 564 | private static class TagCountRange extends CountRange { |
| 565 | |
| 566 | public TagCountRange(int minCount, int maxCount) { |
| 567 | super(minCount, maxCount); |
| 568 | } |
| 569 | |
| 570 | @Override |
| 571 | protected Integer getCount(OsmPrimitive osm) { |
| 572 | return osm.getKeys().size(); |
| 573 | } |
| 574 | |
| 575 | @Override |
| 576 | protected String getCountString() { |
| 577 | return "tags"; |
546 | 578 | } |
547 | | @Override public String toString() {return "tags="+minCount+"-"+maxCount;} |
548 | 579 | } |
549 | 580 | |
550 | 581 | private static class Modified extends Match { |
… |
… |
public class SearchCompiler {
|
636 | 667 | * |
637 | 668 | * @author Ole Jørgen Brønner |
638 | 669 | */ |
639 | | private static class Area extends Match { |
640 | | private int min, max; |
641 | | |
642 | | public Area(int min, int max) { |
643 | | this.min = min; |
644 | | this.max = max; |
645 | | if (min == max) { |
646 | | this.min = 0; |
| 670 | private static class Area extends CountRange { |
| 671 | |
| 672 | public Area(int minCount, int maxCount) { |
| 673 | super(minCount, maxCount); |
| 674 | } |
| 675 | |
| 676 | @Override |
| 677 | protected Integer getCount(OsmPrimitive osm) { |
| 678 | if (!(osm instanceof Way && ((Way) osm).isClosed())) { |
| 679 | return null; |
647 | 680 | } |
| 681 | Way way = (Way) osm; |
| 682 | return (int) Geometry.closedWayArea(way); |
648 | 683 | } |
649 | 684 | |
650 | 685 | @Override |
651 | | public boolean match(OsmPrimitive osm) { |
652 | | if(!(osm instanceof Way && ((Way) osm).isClosed())) |
653 | | return false; |
654 | | Way way = (Way)osm; |
655 | | double area = Geometry.closedWayArea(way); |
656 | | return (min <= area && area <= max); |
| 686 | protected String getCountString() { |
| 687 | return "area"; |
657 | 688 | } |
658 | 689 | } |
659 | 690 | |