001    // License: GPL. For details, see LICENSE file.
002    package org.openstreetmap.josm.gui.widgets;
003    
004    import static org.openstreetmap.josm.tools.I18n.tr;
005    
006    import java.util.ArrayList;
007    import java.util.List;
008    import java.util.StringTokenizer;
009    
010    import javax.swing.JTextField;
011    import javax.swing.text.JTextComponent;
012    
013    import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
014    import org.openstreetmap.josm.data.osm.PrimitiveId;
015    import org.openstreetmap.josm.data.osm.SimplePrimitiveId;
016    
017    /**
018     * @author Matthias Julius
019     */
020    public class OsmIdTextField extends JTextField {
021    
022        private OsmIdValidator validator;
023    
024        public OsmIdTextField() {
025            validator = OsmIdValidator.decorate(this);
026        }
027    
028        public void setType(OsmPrimitiveType type) {
029            validator.type = type;
030        }
031    
032        /**
033         * Get entered ID list - supports "1,2,3" "1 2   ,3" or even "1 2 3 v2 6 v8"
034         * @return list of id's
035         */
036        public List<PrimitiveId> getIds() {
037            return validator.ids;
038        }
039    
040        public boolean readOsmIds() {
041            return validator.readOsmIds();
042        }
043    
044        public void performValidation() {
045            validator.validate();
046        }
047    
048        public void clearTextIfInvalid() {
049            if (!validator.isValid()) 
050                setText("");
051            validator.validate();
052        }
053    
054        /**
055         * Validator for a changeset ID entered in a {@link JTextComponent}.
056         *
057         */
058        static private class OsmIdValidator extends AbstractTextComponentValidator {
059    
060            static public OsmIdValidator decorate(JTextComponent tc) {
061                return new OsmIdValidator(tc);
062            }
063    
064            private List<PrimitiveId> ids = new ArrayList<PrimitiveId>();
065            private OsmPrimitiveType type;
066    
067            public OsmIdValidator(JTextComponent tc) {
068                super(tc, false);
069            }
070    
071            @Override
072            public boolean isValid() {
073                return readOsmIds();
074            }
075    
076            @Override
077            public void validate() {
078                if (!isValid()) {
079                    feedbackInvalid(tr("The current value is not a valid OSM ID. Please enter an integer value > 0"));
080                } else {
081                    feedbackValid(tr("Please enter an integer value > 0"));
082                }
083            }
084    
085            public boolean readOsmIds() {
086                String value = getComponent().getText();
087                char c;
088                if (value == null || value.trim().length() == 0) {
089                    return false;
090                }
091                ids.clear();
092                StringTokenizer st = new StringTokenizer(value, ",.+/ \t\n");
093                String s;
094                while (st.hasMoreTokens()) {
095                    s = st.nextToken();
096                    // convert tokens to int skipping v-words (version v2 etc)
097                    c = s.charAt(0);
098                    if (c == 'v') {
099                        continue;
100                    } else {
101                        try {
102                            ids.add(SimplePrimitiveId.fromString(s));
103                        } catch (IllegalArgumentException ex) {
104                            try {
105                                long id = Long.parseLong(s);
106                                if (id <= 0) {
107                                    return false;
108                                } else if (type == OsmPrimitiveType.NODE) {
109                                    ids.add(new SimplePrimitiveId(id, OsmPrimitiveType.NODE));
110                                } else if (type == OsmPrimitiveType.WAY) {
111                                    ids.add(new SimplePrimitiveId(id, OsmPrimitiveType.WAY));
112                                } else if (type == OsmPrimitiveType.RELATION) {
113                                    ids.add(new SimplePrimitiveId(id, OsmPrimitiveType.RELATION));
114                                } else {
115                                    return false;
116                                }
117                            } catch (IllegalArgumentException ex2) {
118                                return false;
119                            }
120                        }
121                    }
122                }
123                return true;
124            }
125        }
126    }