Ignore:
Timestamp:
2010-02-15T20:39:37+01:00 (14 years ago)
Author:
jttt
Message:

Fix #4528 Search for colon-containing keys broken

Location:
trunk/src/org/openstreetmap/josm/actions/search
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/actions/search/PushbackTokenizer.java

    r2973 r2993  
    1111
    1212public class PushbackTokenizer {
     13
     14    public class Range {
     15        private final long start;
     16        private final long end;
     17
     18        public Range(long start, long end) {
     19            this.start = start;
     20            this.end = end;
     21        }
     22
     23        public long getStart() {
     24            return start;
     25        }
     26
     27        public long getEnd() {
     28            return end;
     29        }
     30    }
     31
    1332    private final Reader search;
    1433
     
    1635    private String currentText;
    1736    private long currentNumber;
     37    private long currentRange;
    1838    private int c;
    1939
     
    2747        RIGHT_PARENT(marktr("<right parent>")), COLON(marktr("<colon>")), EQUALS(marktr("<equals>")),
    2848        KEY(marktr("<key>")), QUESTION_MARK(marktr("<question mark>")), NUMBER(marktr("<number>")),
    29         EOF(marktr("<end-of-file>"));
     49        RANGE(marktr("range")), EOF(marktr("<end-of-file>"));
    3050
    3151        private Token(String name) {
     
    128148            if (Character.isDigit(c)) {
    129149                currentNumber = getNumber();
    130                 return Token.NUMBER;
     150                if (c == '-') {
     151                    getChar();
     152                    currentRange = getNumber();
     153                    return Token.RANGE;
     154                } else
     155                    return Token.NUMBER;
     156
    131157            }
    132158
     
    153179    }
    154180
    155     public String readText() {
     181    public String readTextOrNumber() {
    156182        Token nextTok = nextToken();
    157183        if (nextTok == Token.KEY)
    158184            return currentText;
     185        if (nextTok == Token.NUMBER)
     186            return String.valueOf(currentNumber);
    159187        currentToken = nextTok;
    160188        return null;
    161     }
    162 
    163     public String readText(String errorMessage) throws ParseError {
    164         String text = readText();
    165         if (text == null)
    166             throw new ParseError(errorMessage);
    167         else
    168             return text;
    169189    }
    170190
     
    176196    }
    177197
     198    public long getReadNumber() {
     199        return currentNumber;
     200    }
     201
     202    public Range readRange() throws ParseError {
     203        Token token = nextToken();
     204        if (token == Token.NUMBER)
     205            return new Range(currentNumber, currentNumber);
     206        else if (token == Token.RANGE)
     207            return new Range(currentNumber, currentRange);
     208        else
     209            throw new ParseError(Token.NUMBER, token);
     210    }
     211
    178212    public String getText() {
    179213        return currentText;
  • trunk/src/org/openstreetmap/josm/actions/search/SearchCompiler.java

    r2973 r2993  
    1212
    1313import org.openstreetmap.josm.Main;
     14import org.openstreetmap.josm.actions.search.PushbackTokenizer.Range;
    1415import org.openstreetmap.josm.actions.search.PushbackTokenizer.Token;
    1516import org.openstreetmap.josm.data.osm.Node;
     
    254255            this.key = key;
    255256            this.value = value == null?"":value;
    256             if ("".equals(value) && "*".equals(key)) {
     257            if ("".equals(this.value) && "*".equals(key)) {
    257258                mode = Mode.NONE;
    258             } else if ("".equals(value)) {
     259            } else if ("".equals(this.value)) {
    259260                if (regexp) {
    260261                    mode = Mode.MISSING_KEY_REGEXP;
     
    262263                    mode = Mode.MISSING_KEY;
    263264                }
    264             } else if ("*".equals(key) && "*".equals(value)) {
     265            } else if ("*".equals(key) && "*".equals(this.value)) {
    265266                mode = Mode.ANY;
    266267            } else if ("*".equals(key)) {
     
    270271                    mode = Mode.ANY_KEY;
    271272                }
    272             } else if ("*".equals(value)) {
     273            } else if ("*".equals(this.value)) {
    273274                if (regexp) {
    274275                    mode = Mode.ANY_VALUE_REGEXP;
     
    289290                keyPattern = null;
    290291            }
    291             if (regexp && value.length() > 0 && !value.equals("*")) {
     292            if (regexp && this.value.length() > 0 && !this.value.equals("*")) {
    292293                try {
    293                     valuePattern = Pattern.compile(value);
     294                    valuePattern = Pattern.compile(this.value);
    294295                } catch (PatternSyntaxException e) {
    295296                    throw new ParseError(tr("Pattern Syntax Error: Pattern {0} in {1} is illegal!", e.getPattern(), value));
     
    471472    }
    472473
    473     private static class NodeCount extends Match {
    474         private int count;
    475         public NodeCount(int count) {this.count = count;}
    476         @Override public boolean match(OsmPrimitive osm) {
    477             return osm instanceof Way && ((Way) osm).getNodesCount() == count;
    478         }
    479         @Override public String toString() {return "nodes="+count;}
    480     }
    481 
    482474    private static class NodeCountRange extends Match {
    483475        private int minCount;
     
    500492    }
    501493
    502     private static class TagCount extends Match {
    503         private int count;
    504         public TagCount(int count) {this.count = count;}
    505         @Override public boolean match(OsmPrimitive osm) {
    506             int size = osm.getKeys().size();
    507             return size == count;
    508         }
    509         @Override public String toString() {return "tags="+count;}
    510     }
    511 
    512494    private static class TagCountRange extends Match {
    513495        private int minCount;
     
    609591        public ParseError(String msg) {
    610592            super(msg);
     593        }
     594        public ParseError(Token expected, Token found) {
     595            this(tr("Unexpected token. Expected {0}, found {1}", expected, found));
    611596        }
    612597    }
     
    656641            Match expression = parseExpression();
    657642            if (!tokenizer.readIfEqual(Token.RIGHT_PARENT))
    658                 throw new ParseError(tr("Unexpected token. Expected {0}, found {1}", Token.RIGHT_PARENT, tokenizer.nextToken()));
     643                throw new ParseError(Token.RIGHT_PARENT, tokenizer.nextToken());
    659644            return expression;
    660645        } else if (tokenizer.readIfEqual(Token.NOT))
     
    663648            String key = tokenizer.getText();
    664649            if (tokenizer.readIfEqual(Token.EQUALS))
    665                 return new ExactKeyValue(regexSearch, key, tokenizer.readText());
    666             else if (tokenizer.readIfEqual(Token.COLON))
     650                return new ExactKeyValue(regexSearch, key, tokenizer.readTextOrNumber());
     651            else if (tokenizer.readIfEqual(Token.COLON)) {
    667652                if ("id".equals(key))
    668653                    return new Id(tokenizer.readNumber(tr("Primitive id expected")));
     654                else if ("tags".equals(key)) {
     655                    Range range = tokenizer.readRange();
     656                    return new TagCountRange((int)range.getStart(), (int)range.getEnd());
     657                } else if ("nodes".equals("nodes")) {
     658                    Range range = tokenizer.readRange();
     659                    return new NodeCountRange((int)range.getStart(), (int)range.getEnd());
     660                } else if ("changeset".equals(key))
     661                    return new ChangesetId(tokenizer.readNumber(tr("Changeset id expected")));
     662                else if ("version".equals(key))
     663                    return new Version(tokenizer.readNumber(tr("Version expected")));
    669664                else
    670                     return parseKV(key, tokenizer.readText());
    671             else if (tokenizer.readIfEqual(Token.QUESTION_MARK))
     665                    return parseKV(key, tokenizer.readTextOrNumber());
     666            } else if (tokenizer.readIfEqual(Token.QUESTION_MARK))
    672667                return new BooleanMatch(key, false);
    673668            else if ("modified".equals(key))
     
    705700        else if (key.equals("user"))
    706701            return new UserMatch(value);
    707         else if (key.equals("tags")) {
    708             try {
    709                 String[] range = value.split("-");
    710                 if (range.length == 1)
    711                     return new TagCount(Integer.parseInt(value));
    712                 else if (range.length == 2)
    713                     return new TagCountRange(Integer.parseInt(range[0]), Integer.parseInt(range[1]));
    714                 else
    715                     throw new ParseError(tr("Wrong number of parameters for tags operator."));
    716             } catch (NumberFormatException e) {
    717                 throw new ParseError(tr("Incorrect value of tags operator: {0}. Tags operator expects number of tags or range, for example tags:1 or tags:2-5", value));
    718             }
    719         } else if (key.equals("nodes")) {
    720             try {
    721                 String[] range = value.split("-");
    722                 if (range.length == 1)
    723                     return new NodeCount(Integer.parseInt(value));
    724                 else if (range.length == 2)
    725                     return new NodeCountRange(Integer.parseInt(range[0]), Integer.parseInt(range[1]));
    726                 else
    727                     throw new ParseError(tr("Wrong number of parameters for nodes operator."));
    728             } catch (NumberFormatException e) {
    729                 throw new ParseError(tr("Incorrect value of nodes operator: {0}. Nodes operator expects number of nodes or range, for example nodes:10-20", value));
    730             }
    731 
    732         } else if (key.equals("changeset")) {
    733             try {
    734                 return new ChangesetId(Integer.parseInt(value));
    735             } catch (NumberFormatException x) {
    736                 throw new ParseError(tr("Incorrect value of changeset operator: {0}. Number is expected.", value));
    737             }
    738 
    739         }   else if (key.equals("version")) {
    740             try {
    741                 return new Version(Long.parseLong(value));
    742             } catch (NumberFormatException x) {
    743                 throw new ParseError(tr("Incorrect value of version operator: {0}. Number is expected.", value));
    744             }
    745         }
    746702        else
    747703            return new KeyValue(key, value, regexSearch, caseSensitive);
Note: See TracChangeset for help on using the changeset viewer.