Changeset 4546 in josm for trunk/src/org/openstreetmap


Ignore:
Timestamp:
2011-10-29T09:01:30+02:00 (12 years ago)
Author:
jttt
Message:

Extend name templates with context switch - possibility to use tags of referenced primitive when constructing primitive name

Location:
trunk/src/org/openstreetmap/josm
Files:
1 added
4 edited

Legend:

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

    r4377 r4546  
    6969        protected boolean existsMatch(Collection<? extends OsmPrimitive> primitives) {
    7070            for (OsmPrimitive p : primitives) {
    71                 if (match(p)) {
     71                if (match(p))
    7272                    return true;
    73                 }
    7473            }
    7574            return false;
     
    8180        protected boolean forallMatch(Collection<? extends OsmPrimitive> primitives) {
    8281            for (OsmPrimitive p : primitives) {
    83                 if (!match(p)) {
     82                if (!match(p))
    8483                    return false;
    85                 }
    8684            }
    8785            return true;
     
    110108        }
    111109        @Override public String toString() {return "!"+match;}
     110        public Match getMatch() {
     111            return match;
     112        }
    112113    }
    113114
     
    130131    }
    131132
    132     private static 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;
    135136        public And(Match lhs, Match rhs) {this.lhs = lhs; this.rhs = rhs;}
    136137        @Override public boolean match(OsmPrimitive osm) {
     
    138139        }
    139140        @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;
    145152        public Or(Match lhs, Match rhs) {this.lhs = lhs; this.rhs = rhs;}
    146153        @Override public boolean match(OsmPrimitive osm) {
     
    148155        }
    149156        @Override public String toString() {return lhs+" || "+rhs;}
     157        public Match getLhs() {
     158            return lhs;
     159        }
     160        public Match getRhs() {
     161            return rhs;
     162        }
    150163    }
    151164
     
    552565        public boolean match(OsmPrimitive osm) {
    553566            Integer count = getCount(osm);
    554             if (count == null) {
     567            if (count == null)
    555568                return false;
    556             } else {
     569            else
    557570                return (count >= minCount) && (count <= maxCount);
    558             }
    559571        }
    560572
     
    575587        @Override
    576588        protected Integer getCount(OsmPrimitive osm) {
    577             if (!(osm instanceof Way)) {
     589            if (!(osm instanceof Way))
    578590                return null;
    579             } else {
     591            else
    580592                return ((Way) osm).getNodesCount();
    581             }
    582593        }
    583594
     
    649660    }
    650661
    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        }
    654673        @Override public boolean match(OsmPrimitive osm) {
    655674            boolean isParent = false;
    656 
    657             // "parent" (null) should mean the same as "parent()"
    658             // (Always). I.e. match everything
    659             if (child == null) {
    660                 child = new Always();
    661             }
    662675
    663676            if (osm instanceof Way) {
     
    673686        }
    674687        @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 {
    678694        private final Match parent;
    679695
     
    696712        }
    697713        @Override public String toString() {return "child(" + parent + ")";}
    698     }
    699    
     714
     715        public Match getParent() {
     716            return parent;
     717        }
     718    }
     719
    700720    /**
    701721     * Matches on the area of a closed way.
    702      * 
     722     *
    703723     * @author Ole Jørgen Brønner
    704724     */
     
    711731        @Override
    712732        protected Integer getCount(OsmPrimitive osm) {
    713             if (!(osm instanceof Way && ((Way) osm).isClosed())) {
     733            if (!(osm instanceof Way && ((Way) osm).isClosed()))
    714734                return null;
    715             }
    716735            Way way = (Way) osm;
    717736            return (int) Geometry.closedWayArea(way);
     
    743762        @Override
    744763        public boolean match(OsmPrimitive osm) {
    745             if (!osm.isUsable()) {
     764            if (!osm.isUsable())
    746765                return false;
    747             } else if (osm instanceof Node) {
     766            else if (osm instanceof Node)
    748767                return bounds.contains(((Node) osm).getCoor());
    749             } else if (osm instanceof Way) {
     768            else if (osm instanceof Way) {
    750769                Collection<Node> nodes = ((Way) osm).getNodes();
    751770                return all ? forallMatch(nodes) : existsMatch(nodes);
     
    753772                Collection<OsmPrimitive> primitives = ((Relation) osm).getMemberPrimitives();
    754773                return all ? forallMatch(primitives) : existsMatch(primitives);
    755             } else {
     774            } else
    756775                return false;
    757             }
    758776        }
    759777    }
     
    799817
    800818    public static Match compile(String searchStr, boolean caseSensitive, boolean regexSearch)
    801     throws ParseError {
     819            throws ParseError {
    802820        return new SearchCompiler(caseSensitive, regexSearch,
    803821                new PushbackTokenizer(
  • trunk/src/org/openstreetmap/josm/tools/template_engine/ParseError.java

    r4282 r4546  
    2121    }
    2222
    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);
    2530        unexpectedToken = null;
    2631    }
     
    2934        return unexpectedToken;
    3035    }
     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    }
    3140}
  • trunk/src/org/openstreetmap/josm/tools/template_engine/TemplateParser.java

    r4282 r4546  
    22package org.openstreetmap.josm.tools.template_engine;
    33
     4
     5import static org.openstreetmap.josm.tools.I18n.tr;
    46
    57import java.util.ArrayList;
     
    911
    1012import org.openstreetmap.josm.actions.search.SearchCompiler;
     13import org.openstreetmap.josm.actions.search.SearchCompiler.Match;
    1114import org.openstreetmap.josm.tools.template_engine.Tokenizer.Token;
    1215import org.openstreetmap.josm.tools.template_engine.Tokenizer.TokenType;
     
    4245            if (token.getType() == TokenType.CONDITION_START) {
    4346                templateEntry = parseCondition();
     47            } else if (token.getType() == TokenType.CONTEXT_SWITCH_START) {
     48                templateEntry = parseContextSwitch();
    4449            } else if (token.getType() == TokenType.VARIABLE_START) {
    4550                templateEntry = parseVariable();
     
    6368    }
    6469
    65     private void skipWhitespace() {
     70    private void skipWhitespace() throws ParseError {
    6671        Token token = tokenizer.lookAhead();
    6772        if (token.getType() == TokenType.TEXT && token.getText().trim().isEmpty()) {
     
    7681
    7782            TemplateEntry condition;
    78             String searchExpression = tokenizer.skip('\'');
     83            Token searchExpression = tokenizer.skip('\'');
    7984            check(TokenType.APOSTROPHE);
    8085            condition = parseExpression(CONDITION_WITH_APOSTROPHES_END_TOKENS);
    8186            check(TokenType.APOSTROPHE);
    82             if (searchExpression.trim().isEmpty()) {
     87            if (searchExpression.getText().trim().isEmpty()) {
    8388                result.getEntries().add(condition);
    8489            } else {
    8590                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));
    8792                } catch (org.openstreetmap.josm.actions.search.SearchCompiler.ParseError e) {
    88                     throw new ParseError(e);
     93                    throw new ParseError(searchExpression.getPosition(), e);
    8994                }
    9095            }
     
    101106    }
    102107
     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
    103131}
  • trunk/src/org/openstreetmap/josm/tools/template_engine/Tokenizer.java

    r4282 r4546  
    4040    }
    4141
    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 }
    4343
    4444    private final List<Character> specialCharaters = Arrays.asList(new Character[] {'$', '?', '{', '}', '|', '\''});
     
    6464    }
    6565
    66     public Token nextToken() {
     66    public Token nextToken() throws ParseError {
    6767        if (currentToken != null) {
    6868            Token result = currentToken;
     
    7979            getChar();
    8080            return new Token(TokenType.VARIABLE_START, position);
    81 
    8281        case '?':
    8382            getChar();
     
    8685                return new Token(TokenType.CONDITION_START, position);
    8786            } 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);
    8995        case '}':
    9096            getChar();
     
    111117    }
    112118
    113     public Token lookAhead() {
     119    public Token lookAhead() throws ParseError {
    114120        if (currentToken == null) {
    115121            currentToken = nextToken();
     
    118124    }
    119125
    120     public String skip(char lastChar) {
     126    public Token skip(char lastChar) {
    121127        currentToken = null;
     128        int position = index;
    122129        StringBuilder result = new StringBuilder();
    123130        while (c != lastChar && c != -1) {
     
    128135            getChar();
    129136        }
    130         return result.toString();
     137        return new Token(TokenType.TEXT, position, result.toString());
    131138    }
    132139
Note: See TracChangeset for help on using the changeset viewer.